diff options
454 files changed, 16634 insertions, 11211 deletions
diff --git a/Documentation/networking/dccp.txt b/Documentation/networking/dccp.txt new file mode 100644 index 000000000000..c45daabd3bfe --- /dev/null +++ b/Documentation/networking/dccp.txt | |||
@@ -0,0 +1,56 @@ | |||
1 | DCCP protocol | ||
2 | ============ | ||
3 | |||
4 | Last updated: 10 November 2005 | ||
5 | |||
6 | Contents | ||
7 | ======== | ||
8 | |||
9 | - Introduction | ||
10 | - Missing features | ||
11 | - Socket options | ||
12 | - Notes | ||
13 | |||
14 | Introduction | ||
15 | ============ | ||
16 | |||
17 | Datagram Congestion Control Protocol (DCCP) is an unreliable, connection | ||
18 | based protocol designed to solve issues present in UDP and TCP particularly | ||
19 | for real time and multimedia traffic. | ||
20 | |||
21 | It has a base protocol and pluggable congestion control IDs (CCIDs). | ||
22 | |||
23 | It is at draft RFC status and the homepage for DCCP as a protocol is at: | ||
24 | http://www.icir.org/kohler/dcp/ | ||
25 | |||
26 | Missing features | ||
27 | ================ | ||
28 | |||
29 | The DCCP implementation does not currently have all the features that are in | ||
30 | the draft RFC. | ||
31 | |||
32 | In particular the following are missing: | ||
33 | - CCID2 support | ||
34 | - feature negotiation | ||
35 | |||
36 | When testing against other implementations it appears that elapsed time | ||
37 | options are not coded compliant to the specification. | ||
38 | |||
39 | Socket options | ||
40 | ============== | ||
41 | |||
42 | DCCP_SOCKOPT_PACKET_SIZE is used for CCID3 to set default packet size for | ||
43 | calculations. | ||
44 | |||
45 | DCCP_SOCKOPT_SERVICE sets the service. This is compulsory as per the | ||
46 | specification. If you don't set it you will get EPROTO. | ||
47 | |||
48 | Notes | ||
49 | ===== | ||
50 | |||
51 | SELinux does not yet have support for DCCP. You will need to turn it off or | ||
52 | else you will get EACCES. | ||
53 | |||
54 | DCCP does not travel through NAT successfully at present. This is because | ||
55 | the checksum covers the psuedo-header as per TCP and UDP. It should be | ||
56 | relatively trivial to add Linux NAT support for DCCP. | ||
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index 65895bb51414..ebc09a159f62 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt | |||
@@ -78,6 +78,11 @@ inet_peer_gc_maxtime - INTEGER | |||
78 | 78 | ||
79 | TCP variables: | 79 | TCP variables: |
80 | 80 | ||
81 | tcp_abc - INTEGER | ||
82 | Controls Appropriate Byte Count defined in RFC3465. If set to | ||
83 | 0 then does congestion avoid once per ack. 1 is conservative | ||
84 | value, and 2 is more agressive. | ||
85 | |||
81 | tcp_syn_retries - INTEGER | 86 | tcp_syn_retries - INTEGER |
82 | Number of times initial SYNs for an active TCP connection attempt | 87 | Number of times initial SYNs for an active TCP connection attempt |
83 | will be retransmitted. Should not be higher than 255. Default value | 88 | will be retransmitted. Should not be higher than 255. Default value |
diff --git a/MAINTAINERS b/MAINTAINERS index 5541f9970b87..0b03a88e88be 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -707,7 +707,7 @@ DCCP PROTOCOL | |||
707 | P: Arnaldo Carvalho de Melo | 707 | P: Arnaldo Carvalho de Melo |
708 | M: acme@mandriva.com | 708 | M: acme@mandriva.com |
709 | L: dccp@vger.kernel.org | 709 | L: dccp@vger.kernel.org |
710 | W: http://www.wlug.org.nz/DCCP | 710 | W: http://linux-net.osdl.org/index.php/DCCP |
711 | S: Maintained | 711 | S: Maintained |
712 | 712 | ||
713 | DECnet NETWORK LAYER | 713 | DECnet NETWORK LAYER |
@@ -347,7 +347,7 @@ AFLAGS_KERNEL = | |||
347 | # Needed to be compatible with the O= option | 347 | # Needed to be compatible with the O= option |
348 | LINUXINCLUDE := -Iinclude \ | 348 | LINUXINCLUDE := -Iinclude \ |
349 | $(if $(KBUILD_SRC),-Iinclude2 -I$(srctree)/include) \ | 349 | $(if $(KBUILD_SRC),-Iinclude2 -I$(srctree)/include) \ |
350 | -imacros include/linux/autoconf.h | 350 | -include include/linux/autoconf.h |
351 | 351 | ||
352 | CPPFLAGS := -D__KERNEL__ $(LINUXINCLUDE) | 352 | CPPFLAGS := -D__KERNEL__ $(LINUXINCLUDE) |
353 | 353 | ||
@@ -407,7 +407,7 @@ outputmakefile: | |||
407 | # of make so .config is not included in this case either (for *config). | 407 | # of make so .config is not included in this case either (for *config). |
408 | 408 | ||
409 | no-dot-config-targets := clean mrproper distclean \ | 409 | no-dot-config-targets := clean mrproper distclean \ |
410 | cscope TAGS tags help %docs check% | 410 | cscope TAGS tags help %docs check% kernelrelease |
411 | 411 | ||
412 | config-targets := 0 | 412 | config-targets := 0 |
413 | mixed-targets := 0 | 413 | mixed-targets := 0 |
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index ec77721507cb..3df7cbd924a1 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -239,6 +239,8 @@ source "arch/arm/plat-omap/Kconfig" | |||
239 | 239 | ||
240 | source "arch/arm/mach-omap1/Kconfig" | 240 | source "arch/arm/mach-omap1/Kconfig" |
241 | 241 | ||
242 | source "arch/arm/mach-omap2/Kconfig" | ||
243 | |||
242 | source "arch/arm/mach-s3c2410/Kconfig" | 244 | source "arch/arm/mach-s3c2410/Kconfig" |
243 | 245 | ||
244 | source "arch/arm/mach-lh7a40x/Kconfig" | 246 | source "arch/arm/mach-lh7a40x/Kconfig" |
diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 114cda7f1b73..81bd2193fe6d 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile | |||
@@ -93,6 +93,7 @@ textaddr-$(CONFIG_ARCH_FORTUNET) := 0xc0008000 | |||
93 | machine-$(CONFIG_ARCH_IXP4XX) := ixp4xx | 93 | machine-$(CONFIG_ARCH_IXP4XX) := ixp4xx |
94 | machine-$(CONFIG_ARCH_IXP2000) := ixp2000 | 94 | machine-$(CONFIG_ARCH_IXP2000) := ixp2000 |
95 | machine-$(CONFIG_ARCH_OMAP1) := omap1 | 95 | machine-$(CONFIG_ARCH_OMAP1) := omap1 |
96 | machine-$(CONFIG_ARCH_OMAP2) := omap2 | ||
96 | incdir-$(CONFIG_ARCH_OMAP) := omap | 97 | incdir-$(CONFIG_ARCH_OMAP) := omap |
97 | machine-$(CONFIG_ARCH_S3C2410) := s3c2410 | 98 | machine-$(CONFIG_ARCH_S3C2410) := s3c2410 |
98 | machine-$(CONFIG_ARCH_LH7A40X) := lh7a40x | 99 | machine-$(CONFIG_ARCH_LH7A40X) := lh7a40x |
diff --git a/arch/arm/configs/omap_h2_1610_defconfig b/arch/arm/configs/omap_h2_1610_defconfig index 4198677cd394..529f0f72e1e9 100644 --- a/arch/arm/configs/omap_h2_1610_defconfig +++ b/arch/arm/configs/omap_h2_1610_defconfig | |||
@@ -1,7 +1,7 @@ | |||
1 | # | 1 | # |
2 | # Automatically generated make config: don't edit | 2 | # Automatically generated make config: don't edit |
3 | # Linux kernel version: 2.6.13 | 3 | # Linux kernel version: 2.6.14 |
4 | # Mon Sep 5 18:07:12 2005 | 4 | # Wed Nov 9 18:53:40 2005 |
5 | # | 5 | # |
6 | CONFIG_ARM=y | 6 | CONFIG_ARM=y |
7 | CONFIG_MMU=y | 7 | CONFIG_MMU=y |
@@ -22,6 +22,7 @@ CONFIG_INIT_ENV_ARG_LIMIT=32 | |||
22 | # General setup | 22 | # General setup |
23 | # | 23 | # |
24 | CONFIG_LOCALVERSION="" | 24 | CONFIG_LOCALVERSION="" |
25 | CONFIG_LOCALVERSION_AUTO=y | ||
25 | CONFIG_SWAP=y | 26 | CONFIG_SWAP=y |
26 | CONFIG_SYSVIPC=y | 27 | CONFIG_SYSVIPC=y |
27 | # CONFIG_POSIX_MQUEUE is not set | 28 | # CONFIG_POSIX_MQUEUE is not set |
@@ -31,6 +32,7 @@ CONFIG_SYSCTL=y | |||
31 | # CONFIG_HOTPLUG is not set | 32 | # CONFIG_HOTPLUG is not set |
32 | CONFIG_KOBJECT_UEVENT=y | 33 | CONFIG_KOBJECT_UEVENT=y |
33 | # CONFIG_IKCONFIG is not set | 34 | # CONFIG_IKCONFIG is not set |
35 | CONFIG_INITRAMFS_SOURCE="" | ||
34 | # CONFIG_EMBEDDED is not set | 36 | # CONFIG_EMBEDDED is not set |
35 | CONFIG_KALLSYMS=y | 37 | CONFIG_KALLSYMS=y |
36 | # CONFIG_KALLSYMS_EXTRA_PASS is not set | 38 | # CONFIG_KALLSYMS_EXTRA_PASS is not set |
@@ -60,6 +62,23 @@ CONFIG_OBSOLETE_MODPARM=y | |||
60 | # CONFIG_KMOD is not set | 62 | # CONFIG_KMOD is not set |
61 | 63 | ||
62 | # | 64 | # |
65 | # Block layer | ||
66 | # | ||
67 | |||
68 | # | ||
69 | # IO Schedulers | ||
70 | # | ||
71 | CONFIG_IOSCHED_NOOP=y | ||
72 | CONFIG_IOSCHED_AS=y | ||
73 | CONFIG_IOSCHED_DEADLINE=y | ||
74 | CONFIG_IOSCHED_CFQ=y | ||
75 | CONFIG_DEFAULT_AS=y | ||
76 | # CONFIG_DEFAULT_DEADLINE is not set | ||
77 | # CONFIG_DEFAULT_CFQ is not set | ||
78 | # CONFIG_DEFAULT_NOOP is not set | ||
79 | CONFIG_DEFAULT_IOSCHED="anticipatory" | ||
80 | |||
81 | # | ||
63 | # System Type | 82 | # System Type |
64 | # | 83 | # |
65 | # CONFIG_ARCH_CLPS7500 is not set | 84 | # CONFIG_ARCH_CLPS7500 is not set |
@@ -81,6 +100,7 @@ CONFIG_OBSOLETE_MODPARM=y | |||
81 | # CONFIG_ARCH_LH7A40X is not set | 100 | # CONFIG_ARCH_LH7A40X is not set |
82 | CONFIG_ARCH_OMAP=y | 101 | CONFIG_ARCH_OMAP=y |
83 | # CONFIG_ARCH_VERSATILE is not set | 102 | # CONFIG_ARCH_VERSATILE is not set |
103 | # CONFIG_ARCH_REALVIEW is not set | ||
84 | # CONFIG_ARCH_IMX is not set | 104 | # CONFIG_ARCH_IMX is not set |
85 | # CONFIG_ARCH_H720X is not set | 105 | # CONFIG_ARCH_H720X is not set |
86 | # CONFIG_ARCH_AAEC2000 is not set | 106 | # CONFIG_ARCH_AAEC2000 is not set |
@@ -112,7 +132,7 @@ CONFIG_OMAP_SERIAL_WAKE=y | |||
112 | # OMAP Core Type | 132 | # OMAP Core Type |
113 | # | 133 | # |
114 | # CONFIG_ARCH_OMAP730 is not set | 134 | # CONFIG_ARCH_OMAP730 is not set |
115 | # CONFIG_ARCH_OMAP1510 is not set | 135 | # CONFIG_ARCH_OMAP15XX is not set |
116 | CONFIG_ARCH_OMAP16XX=y | 136 | CONFIG_ARCH_OMAP16XX=y |
117 | 137 | ||
118 | # | 138 | # |
@@ -177,6 +197,8 @@ CONFIG_FLATMEM_MANUAL=y | |||
177 | # CONFIG_SPARSEMEM_MANUAL is not set | 197 | # CONFIG_SPARSEMEM_MANUAL is not set |
178 | CONFIG_FLATMEM=y | 198 | CONFIG_FLATMEM=y |
179 | CONFIG_FLAT_NODE_MEM_MAP=y | 199 | CONFIG_FLAT_NODE_MEM_MAP=y |
200 | # CONFIG_SPARSEMEM_STATIC is not set | ||
201 | CONFIG_SPLIT_PTLOCK_CPUS=4096 | ||
180 | # CONFIG_LEDS is not set | 202 | # CONFIG_LEDS is not set |
181 | CONFIG_ALIGNMENT_TRAP=y | 203 | CONFIG_ALIGNMENT_TRAP=y |
182 | 204 | ||
@@ -258,14 +280,19 @@ CONFIG_IP_PNP_BOOTP=y | |||
258 | # CONFIG_INET_ESP is not set | 280 | # CONFIG_INET_ESP is not set |
259 | # CONFIG_INET_IPCOMP is not set | 281 | # CONFIG_INET_IPCOMP is not set |
260 | # CONFIG_INET_TUNNEL is not set | 282 | # CONFIG_INET_TUNNEL is not set |
261 | CONFIG_IP_TCPDIAG=y | 283 | CONFIG_INET_DIAG=y |
262 | # CONFIG_IP_TCPDIAG_IPV6 is not set | 284 | CONFIG_INET_TCP_DIAG=y |
263 | # CONFIG_TCP_CONG_ADVANCED is not set | 285 | # CONFIG_TCP_CONG_ADVANCED is not set |
264 | CONFIG_TCP_CONG_BIC=y | 286 | CONFIG_TCP_CONG_BIC=y |
265 | # CONFIG_IPV6 is not set | 287 | # CONFIG_IPV6 is not set |
266 | # CONFIG_NETFILTER is not set | 288 | # CONFIG_NETFILTER is not set |
267 | 289 | ||
268 | # | 290 | # |
291 | # DCCP Configuration (EXPERIMENTAL) | ||
292 | # | ||
293 | # CONFIG_IP_DCCP is not set | ||
294 | |||
295 | # | ||
269 | # SCTP Configuration (EXPERIMENTAL) | 296 | # SCTP Configuration (EXPERIMENTAL) |
270 | # | 297 | # |
271 | # CONFIG_IP_SCTP is not set | 298 | # CONFIG_IP_SCTP is not set |
@@ -281,6 +308,10 @@ CONFIG_TCP_CONG_BIC=y | |||
281 | # CONFIG_NET_DIVERT is not set | 308 | # CONFIG_NET_DIVERT is not set |
282 | # CONFIG_ECONET is not set | 309 | # CONFIG_ECONET is not set |
283 | # CONFIG_WAN_ROUTER is not set | 310 | # CONFIG_WAN_ROUTER is not set |
311 | |||
312 | # | ||
313 | # QoS and/or fair queueing | ||
314 | # | ||
284 | # CONFIG_NET_SCHED is not set | 315 | # CONFIG_NET_SCHED is not set |
285 | # CONFIG_NET_CLS_ROUTE is not set | 316 | # CONFIG_NET_CLS_ROUTE is not set |
286 | 317 | ||
@@ -291,6 +322,7 @@ CONFIG_TCP_CONG_BIC=y | |||
291 | # CONFIG_HAMRADIO is not set | 322 | # CONFIG_HAMRADIO is not set |
292 | # CONFIG_IRDA is not set | 323 | # CONFIG_IRDA is not set |
293 | # CONFIG_BT is not set | 324 | # CONFIG_BT is not set |
325 | # CONFIG_IEEE80211 is not set | ||
294 | 326 | ||
295 | # | 327 | # |
296 | # Device Drivers | 328 | # Device Drivers |
@@ -328,21 +360,13 @@ CONFIG_BLK_DEV_RAM=y | |||
328 | CONFIG_BLK_DEV_RAM_COUNT=16 | 360 | CONFIG_BLK_DEV_RAM_COUNT=16 |
329 | CONFIG_BLK_DEV_RAM_SIZE=8192 | 361 | CONFIG_BLK_DEV_RAM_SIZE=8192 |
330 | CONFIG_BLK_DEV_INITRD=y | 362 | CONFIG_BLK_DEV_INITRD=y |
331 | CONFIG_INITRAMFS_SOURCE="" | ||
332 | # CONFIG_CDROM_PKTCDVD is not set | 363 | # CONFIG_CDROM_PKTCDVD is not set |
333 | |||
334 | # | ||
335 | # IO Schedulers | ||
336 | # | ||
337 | CONFIG_IOSCHED_NOOP=y | ||
338 | CONFIG_IOSCHED_AS=y | ||
339 | CONFIG_IOSCHED_DEADLINE=y | ||
340 | CONFIG_IOSCHED_CFQ=y | ||
341 | CONFIG_ATA_OVER_ETH=m | 364 | CONFIG_ATA_OVER_ETH=m |
342 | 365 | ||
343 | # | 366 | # |
344 | # SCSI device support | 367 | # SCSI device support |
345 | # | 368 | # |
369 | # CONFIG_RAID_ATTRS is not set | ||
346 | CONFIG_SCSI=y | 370 | CONFIG_SCSI=y |
347 | CONFIG_SCSI_PROC_FS=y | 371 | CONFIG_SCSI_PROC_FS=y |
348 | 372 | ||
@@ -369,10 +393,12 @@ CONFIG_SCSI_PROC_FS=y | |||
369 | # CONFIG_SCSI_SPI_ATTRS is not set | 393 | # CONFIG_SCSI_SPI_ATTRS is not set |
370 | # CONFIG_SCSI_FC_ATTRS is not set | 394 | # CONFIG_SCSI_FC_ATTRS is not set |
371 | # CONFIG_SCSI_ISCSI_ATTRS is not set | 395 | # CONFIG_SCSI_ISCSI_ATTRS is not set |
396 | # CONFIG_SCSI_SAS_ATTRS is not set | ||
372 | 397 | ||
373 | # | 398 | # |
374 | # SCSI low-level drivers | 399 | # SCSI low-level drivers |
375 | # | 400 | # |
401 | # CONFIG_ISCSI_TCP is not set | ||
376 | # CONFIG_SCSI_SATA is not set | 402 | # CONFIG_SCSI_SATA is not set |
377 | # CONFIG_SCSI_DEBUG is not set | 403 | # CONFIG_SCSI_DEBUG is not set |
378 | 404 | ||
@@ -404,6 +430,11 @@ CONFIG_NETDEVICES=y | |||
404 | # CONFIG_TUN is not set | 430 | # CONFIG_TUN is not set |
405 | 431 | ||
406 | # | 432 | # |
433 | # PHY device support | ||
434 | # | ||
435 | # CONFIG_PHYLIB is not set | ||
436 | |||
437 | # | ||
407 | # Ethernet (10 or 100Mbit) | 438 | # Ethernet (10 or 100Mbit) |
408 | # | 439 | # |
409 | CONFIG_NET_ETHERNET=y | 440 | CONFIG_NET_ETHERNET=y |
@@ -439,6 +470,7 @@ CONFIG_PPP=y | |||
439 | # CONFIG_PPP_SYNC_TTY is not set | 470 | # CONFIG_PPP_SYNC_TTY is not set |
440 | # CONFIG_PPP_DEFLATE is not set | 471 | # CONFIG_PPP_DEFLATE is not set |
441 | # CONFIG_PPP_BSDCOMP is not set | 472 | # CONFIG_PPP_BSDCOMP is not set |
473 | # CONFIG_PPP_MPPE is not set | ||
442 | # CONFIG_PPPOE is not set | 474 | # CONFIG_PPPOE is not set |
443 | CONFIG_SLIP=y | 475 | CONFIG_SLIP=y |
444 | CONFIG_SLIP_COMPRESSED=y | 476 | CONFIG_SLIP_COMPRESSED=y |
@@ -541,18 +573,18 @@ CONFIG_WATCHDOG_NOWAYOUT=y | |||
541 | # | 573 | # |
542 | # TPM devices | 574 | # TPM devices |
543 | # | 575 | # |
576 | # CONFIG_TELCLOCK is not set | ||
544 | 577 | ||
545 | # | 578 | # |
546 | # I2C support | 579 | # I2C support |
547 | # | 580 | # |
548 | # CONFIG_I2C is not set | 581 | # CONFIG_I2C is not set |
549 | # CONFIG_I2C_SENSOR is not set | ||
550 | CONFIG_ISP1301_OMAP=y | ||
551 | 582 | ||
552 | # | 583 | # |
553 | # Hardware Monitoring support | 584 | # Hardware Monitoring support |
554 | # | 585 | # |
555 | CONFIG_HWMON=y | 586 | CONFIG_HWMON=y |
587 | # CONFIG_HWMON_VID is not set | ||
556 | # CONFIG_HWMON_DEBUG_CHIP is not set | 588 | # CONFIG_HWMON_DEBUG_CHIP is not set |
557 | 589 | ||
558 | # | 590 | # |
@@ -560,6 +592,10 @@ CONFIG_HWMON=y | |||
560 | # | 592 | # |
561 | 593 | ||
562 | # | 594 | # |
595 | # Multimedia Capabilities Port drivers | ||
596 | # | ||
597 | |||
598 | # | ||
563 | # Multimedia devices | 599 | # Multimedia devices |
564 | # | 600 | # |
565 | # CONFIG_VIDEO_DEV is not set | 601 | # CONFIG_VIDEO_DEV is not set |
@@ -576,7 +612,6 @@ CONFIG_FB=y | |||
576 | # CONFIG_FB_CFB_FILLRECT is not set | 612 | # CONFIG_FB_CFB_FILLRECT is not set |
577 | # CONFIG_FB_CFB_COPYAREA is not set | 613 | # CONFIG_FB_CFB_COPYAREA is not set |
578 | # CONFIG_FB_CFB_IMAGEBLIT is not set | 614 | # CONFIG_FB_CFB_IMAGEBLIT is not set |
579 | # CONFIG_FB_SOFT_CURSOR is not set | ||
580 | # CONFIG_FB_MACMODES is not set | 615 | # CONFIG_FB_MACMODES is not set |
581 | CONFIG_FB_MODE_HELPERS=y | 616 | CONFIG_FB_MODE_HELPERS=y |
582 | # CONFIG_FB_TILEBLITTING is not set | 617 | # CONFIG_FB_TILEBLITTING is not set |
@@ -589,6 +624,7 @@ CONFIG_FB_MODE_HELPERS=y | |||
589 | # CONFIG_VGA_CONSOLE is not set | 624 | # CONFIG_VGA_CONSOLE is not set |
590 | CONFIG_DUMMY_CONSOLE=y | 625 | CONFIG_DUMMY_CONSOLE=y |
591 | CONFIG_FRAMEBUFFER_CONSOLE=y | 626 | CONFIG_FRAMEBUFFER_CONSOLE=y |
627 | # CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set | ||
592 | CONFIG_FONTS=y | 628 | CONFIG_FONTS=y |
593 | CONFIG_FONT_8x8=y | 629 | CONFIG_FONT_8x8=y |
594 | CONFIG_FONT_8x16=y | 630 | CONFIG_FONT_8x16=y |
@@ -600,6 +636,7 @@ CONFIG_FONT_8x16=y | |||
600 | # CONFIG_FONT_SUN8x16 is not set | 636 | # CONFIG_FONT_SUN8x16 is not set |
601 | # CONFIG_FONT_SUN12x22 is not set | 637 | # CONFIG_FONT_SUN12x22 is not set |
602 | # CONFIG_FONT_10x18 is not set | 638 | # CONFIG_FONT_10x18 is not set |
639 | # CONFIG_FONT_RL is not set | ||
603 | 640 | ||
604 | # | 641 | # |
605 | # Logo configuration | 642 | # Logo configuration |
@@ -624,10 +661,10 @@ CONFIG_SOUND=y | |||
624 | # Open Sound System | 661 | # Open Sound System |
625 | # | 662 | # |
626 | CONFIG_SOUND_PRIME=y | 663 | CONFIG_SOUND_PRIME=y |
664 | # CONFIG_OBSOLETE_OSS_DRIVER is not set | ||
627 | # CONFIG_SOUND_MSNDCLAS is not set | 665 | # CONFIG_SOUND_MSNDCLAS is not set |
628 | # CONFIG_SOUND_MSNDPIN is not set | 666 | # CONFIG_SOUND_MSNDPIN is not set |
629 | # CONFIG_SOUND_OSS is not set | 667 | # CONFIG_SOUND_OSS is not set |
630 | # CONFIG_SOUND_AD1980 is not set | ||
631 | 668 | ||
632 | # | 669 | # |
633 | # USB support | 670 | # USB support |
@@ -637,22 +674,21 @@ CONFIG_USB_ARCH_HAS_OHCI=y | |||
637 | # CONFIG_USB is not set | 674 | # CONFIG_USB is not set |
638 | 675 | ||
639 | # | 676 | # |
677 | # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' | ||
678 | # | ||
679 | |||
680 | # | ||
640 | # USB Gadget Support | 681 | # USB Gadget Support |
641 | # | 682 | # |
642 | CONFIG_USB_GADGET=y | 683 | # CONFIG_USB_GADGET is not set |
643 | # CONFIG_USB_GADGET_DEBUG_FILES is not set | ||
644 | CONFIG_USB_GADGET_SELECTED=y | ||
645 | # CONFIG_USB_GADGET_NET2280 is not set | 684 | # CONFIG_USB_GADGET_NET2280 is not set |
646 | # CONFIG_USB_GADGET_PXA2XX is not set | 685 | # CONFIG_USB_GADGET_PXA2XX is not set |
647 | # CONFIG_USB_GADGET_GOKU is not set | 686 | # CONFIG_USB_GADGET_GOKU is not set |
648 | # CONFIG_USB_GADGET_LH7A40X is not set | 687 | # CONFIG_USB_GADGET_LH7A40X is not set |
649 | CONFIG_USB_GADGET_OMAP=y | 688 | # CONFIG_USB_GADGET_OMAP is not set |
650 | CONFIG_USB_OMAP=y | ||
651 | # CONFIG_USB_GADGET_DUMMY_HCD is not set | 689 | # CONFIG_USB_GADGET_DUMMY_HCD is not set |
652 | # CONFIG_USB_GADGET_DUALSPEED is not set | ||
653 | # CONFIG_USB_ZERO is not set | 690 | # CONFIG_USB_ZERO is not set |
654 | CONFIG_USB_ETH=y | 691 | # CONFIG_USB_ETH is not set |
655 | CONFIG_USB_ETH_RNDIS=y | ||
656 | # CONFIG_USB_GADGETFS is not set | 692 | # CONFIG_USB_GADGETFS is not set |
657 | # CONFIG_USB_FILE_STORAGE is not set | 693 | # CONFIG_USB_FILE_STORAGE is not set |
658 | # CONFIG_USB_G_SERIAL is not set | 694 | # CONFIG_USB_G_SERIAL is not set |
@@ -673,10 +709,6 @@ CONFIG_EXT2_FS=y | |||
673 | # CONFIG_REISERFS_FS is not set | 709 | # CONFIG_REISERFS_FS is not set |
674 | # CONFIG_JFS_FS is not set | 710 | # CONFIG_JFS_FS is not set |
675 | # CONFIG_FS_POSIX_ACL is not set | 711 | # CONFIG_FS_POSIX_ACL is not set |
676 | |||
677 | # | ||
678 | # XFS support | ||
679 | # | ||
680 | # CONFIG_XFS_FS is not set | 712 | # CONFIG_XFS_FS is not set |
681 | # CONFIG_MINIX_FS is not set | 713 | # CONFIG_MINIX_FS is not set |
682 | CONFIG_ROMFS_FS=y | 714 | CONFIG_ROMFS_FS=y |
@@ -685,6 +717,7 @@ CONFIG_INOTIFY=y | |||
685 | CONFIG_DNOTIFY=y | 717 | CONFIG_DNOTIFY=y |
686 | # CONFIG_AUTOFS_FS is not set | 718 | # CONFIG_AUTOFS_FS is not set |
687 | # CONFIG_AUTOFS4_FS is not set | 719 | # CONFIG_AUTOFS4_FS is not set |
720 | # CONFIG_FUSE_FS is not set | ||
688 | 721 | ||
689 | # | 722 | # |
690 | # CD-ROM/DVD Filesystems | 723 | # CD-ROM/DVD Filesystems |
@@ -706,10 +739,10 @@ CONFIG_FAT_DEFAULT_CODEPAGE=437 | |||
706 | # | 739 | # |
707 | CONFIG_PROC_FS=y | 740 | CONFIG_PROC_FS=y |
708 | CONFIG_SYSFS=y | 741 | CONFIG_SYSFS=y |
709 | # CONFIG_DEVPTS_FS_XATTR is not set | ||
710 | # CONFIG_TMPFS is not set | 742 | # CONFIG_TMPFS is not set |
711 | # CONFIG_HUGETLB_PAGE is not set | 743 | # CONFIG_HUGETLB_PAGE is not set |
712 | CONFIG_RAMFS=y | 744 | CONFIG_RAMFS=y |
745 | # CONFIG_RELAYFS_FS is not set | ||
713 | 746 | ||
714 | # | 747 | # |
715 | # Miscellaneous filesystems | 748 | # Miscellaneous filesystems |
@@ -750,6 +783,7 @@ CONFIG_RPCSEC_GSS_KRB5=y | |||
750 | # CONFIG_NCP_FS is not set | 783 | # CONFIG_NCP_FS is not set |
751 | # CONFIG_CODA_FS is not set | 784 | # CONFIG_CODA_FS is not set |
752 | # CONFIG_AFS_FS is not set | 785 | # CONFIG_AFS_FS is not set |
786 | # CONFIG_9P_FS is not set | ||
753 | 787 | ||
754 | # | 788 | # |
755 | # Partition Types | 789 | # Partition Types |
@@ -859,6 +893,7 @@ CONFIG_CRYPTO_DES=y | |||
859 | # Library routines | 893 | # Library routines |
860 | # | 894 | # |
861 | # CONFIG_CRC_CCITT is not set | 895 | # CONFIG_CRC_CCITT is not set |
896 | # CONFIG_CRC16 is not set | ||
862 | CONFIG_CRC32=y | 897 | CONFIG_CRC32=y |
863 | # CONFIG_LIBCRC32C is not set | 898 | # CONFIG_LIBCRC32C is not set |
864 | CONFIG_ZLIB_INFLATE=y | 899 | CONFIG_ZLIB_INFLATE=y |
diff --git a/arch/arm/lib/csumpartial.S b/arch/arm/lib/csumpartial.S index cb5e3708f118..fe797cf320bb 100644 --- a/arch/arm/lib/csumpartial.S +++ b/arch/arm/lib/csumpartial.S | |||
@@ -39,6 +39,7 @@ td3 .req lr | |||
39 | 39 | ||
40 | /* we must have at least one byte. */ | 40 | /* we must have at least one byte. */ |
41 | tst buf, #1 @ odd address? | 41 | tst buf, #1 @ odd address? |
42 | movne sum, sum, ror #8 | ||
42 | ldrneb td0, [buf], #1 | 43 | ldrneb td0, [buf], #1 |
43 | subne len, len, #1 | 44 | subne len, len, #1 |
44 | adcnes sum, sum, td0, put_byte_1 | 45 | adcnes sum, sum, td0, put_byte_1 |
@@ -103,6 +104,9 @@ ENTRY(csum_partial) | |||
103 | cmp len, #8 @ Ensure that we have at least | 104 | cmp len, #8 @ Ensure that we have at least |
104 | blo .less8 @ 8 bytes to copy. | 105 | blo .less8 @ 8 bytes to copy. |
105 | 106 | ||
107 | tst buf, #1 | ||
108 | movne sum, sum, ror #8 | ||
109 | |||
106 | adds sum, sum, #0 @ C = 0 | 110 | adds sum, sum, #0 @ C = 0 |
107 | tst buf, #3 @ Test destination alignment | 111 | tst buf, #3 @ Test destination alignment |
108 | blne .not_aligned @ aligh destination, return here | 112 | blne .not_aligned @ aligh destination, return here |
diff --git a/arch/arm/mach-ixp4xx/Kconfig b/arch/arm/mach-ixp4xx/Kconfig index 89762a26495c..385285851cb5 100644 --- a/arch/arm/mach-ixp4xx/Kconfig +++ b/arch/arm/mach-ixp4xx/Kconfig | |||
@@ -8,6 +8,16 @@ menu "Intel IXP4xx Implementation Options" | |||
8 | 8 | ||
9 | comment "IXP4xx Platforms" | 9 | comment "IXP4xx Platforms" |
10 | 10 | ||
11 | # This entry is placed on top because otherwise it would have | ||
12 | # been shown as a submenu. | ||
13 | config MACH_NSLU2 | ||
14 | bool | ||
15 | prompt "NSLU2" if !(MACH_IXDP465 || MACH_IXDPG425 || ARCH_IXDP425 || ARCH_ADI_COYOTE || ARCH_AVILA || ARCH_IXCDP1100 || ARCH_PRPMC1100 || MACH_GTWX5715) | ||
16 | help | ||
17 | Say 'Y' here if you want your kernel to support Linksys's | ||
18 | NSLU2 NAS device. For more information on this platform, | ||
19 | see http://www.nslu2-linux.org | ||
20 | |||
11 | config ARCH_AVILA | 21 | config ARCH_AVILA |
12 | bool "Avila" | 22 | bool "Avila" |
13 | help | 23 | help |
diff --git a/arch/arm/mach-ixp4xx/Makefile b/arch/arm/mach-ixp4xx/Makefile index ddecbda4a633..7a15629c18d0 100644 --- a/arch/arm/mach-ixp4xx/Makefile +++ b/arch/arm/mach-ixp4xx/Makefile | |||
@@ -8,4 +8,5 @@ obj-$(CONFIG_ARCH_IXDP4XX) += ixdp425-pci.o ixdp425-setup.o | |||
8 | obj-$(CONFIG_MACH_IXDPG425) += ixdpg425-pci.o coyote-setup.o | 8 | obj-$(CONFIG_MACH_IXDPG425) += ixdpg425-pci.o coyote-setup.o |
9 | obj-$(CONFIG_ARCH_ADI_COYOTE) += coyote-pci.o coyote-setup.o | 9 | obj-$(CONFIG_ARCH_ADI_COYOTE) += coyote-pci.o coyote-setup.o |
10 | obj-$(CONFIG_MACH_GTWX5715) += gtwx5715-pci.o gtwx5715-setup.o | 10 | obj-$(CONFIG_MACH_GTWX5715) += gtwx5715-pci.o gtwx5715-setup.o |
11 | obj-$(CONFIG_MACH_NSLU2) += nslu2-pci.o nslu2-setup.o nslu2-power.o | ||
11 | 12 | ||
diff --git a/arch/arm/mach-ixp4xx/nslu2-pci.c b/arch/arm/mach-ixp4xx/nslu2-pci.c new file mode 100644 index 000000000000..a575f2e0b2c8 --- /dev/null +++ b/arch/arm/mach-ixp4xx/nslu2-pci.c | |||
@@ -0,0 +1,77 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-ixp4xx/nslu2-pci.c | ||
3 | * | ||
4 | * NSLU2 board-level PCI initialization | ||
5 | * | ||
6 | * based on ixdp425-pci.c: | ||
7 | * Copyright (C) 2002 Intel Corporation. | ||
8 | * Copyright (C) 2003-2004 MontaVista Software, Inc. | ||
9 | * | ||
10 | * Maintainer: http://www.nslu2-linux.org/ | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License version 2 as | ||
14 | * published by the Free Software Foundation. | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | #include <linux/config.h> | ||
19 | #include <linux/pci.h> | ||
20 | #include <linux/init.h> | ||
21 | |||
22 | #include <asm/mach/pci.h> | ||
23 | #include <asm/mach-types.h> | ||
24 | |||
25 | void __init nslu2_pci_preinit(void) | ||
26 | { | ||
27 | set_irq_type(IRQ_NSLU2_PCI_INTA, IRQT_LOW); | ||
28 | set_irq_type(IRQ_NSLU2_PCI_INTB, IRQT_LOW); | ||
29 | set_irq_type(IRQ_NSLU2_PCI_INTC, IRQT_LOW); | ||
30 | |||
31 | gpio_line_isr_clear(NSLU2_PCI_INTA_PIN); | ||
32 | gpio_line_isr_clear(NSLU2_PCI_INTB_PIN); | ||
33 | gpio_line_isr_clear(NSLU2_PCI_INTC_PIN); | ||
34 | |||
35 | /* INTD is not configured as GPIO is used | ||
36 | * for the power input button. | ||
37 | */ | ||
38 | |||
39 | ixp4xx_pci_preinit(); | ||
40 | } | ||
41 | |||
42 | static int __init nslu2_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | ||
43 | { | ||
44 | static int pci_irq_table[NSLU2_PCI_IRQ_LINES] = { | ||
45 | IRQ_NSLU2_PCI_INTA, | ||
46 | IRQ_NSLU2_PCI_INTB, | ||
47 | IRQ_NSLU2_PCI_INTC, | ||
48 | }; | ||
49 | |||
50 | int irq = -1; | ||
51 | |||
52 | if (slot >= 1 && slot <= NSLU2_PCI_MAX_DEV && | ||
53 | pin >= 1 && pin <= NSLU2_PCI_IRQ_LINES) { | ||
54 | irq = pci_irq_table[(slot + pin - 2) % NSLU2_PCI_IRQ_LINES]; | ||
55 | } | ||
56 | |||
57 | return irq; | ||
58 | } | ||
59 | |||
60 | struct hw_pci __initdata nslu2_pci = { | ||
61 | .nr_controllers = 1, | ||
62 | .preinit = nslu2_pci_preinit, | ||
63 | .swizzle = pci_std_swizzle, | ||
64 | .setup = ixp4xx_setup, | ||
65 | .scan = ixp4xx_scan_bus, | ||
66 | .map_irq = nslu2_map_irq, | ||
67 | }; | ||
68 | |||
69 | int __init nslu2_pci_init(void) /* monkey see, monkey do */ | ||
70 | { | ||
71 | if (machine_is_nslu2()) | ||
72 | pci_common_init(&nslu2_pci); | ||
73 | |||
74 | return 0; | ||
75 | } | ||
76 | |||
77 | subsys_initcall(nslu2_pci_init); | ||
diff --git a/arch/arm/mach-ixp4xx/nslu2-power.c b/arch/arm/mach-ixp4xx/nslu2-power.c new file mode 100644 index 000000000000..18fbc8c0fb30 --- /dev/null +++ b/arch/arm/mach-ixp4xx/nslu2-power.c | |||
@@ -0,0 +1,92 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-ixp4xx/nslu2-power.c | ||
3 | * | ||
4 | * NSLU2 Power/Reset driver | ||
5 | * | ||
6 | * Copyright (C) 2005 Tower Technologies | ||
7 | * | ||
8 | * based on nslu2-io.c | ||
9 | * Copyright (C) 2004 Karen Spearel | ||
10 | * | ||
11 | * Author: Alessandro Zummo <a.zummo@towertech.it> | ||
12 | * Maintainers: http://www.nslu2-linux.org/ | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify | ||
15 | * it under the terms of the GNU General Public License version 2 as | ||
16 | * published by the Free Software Foundation. | ||
17 | * | ||
18 | */ | ||
19 | |||
20 | #include <linux/module.h> | ||
21 | #include <linux/reboot.h> | ||
22 | #include <linux/interrupt.h> | ||
23 | |||
24 | #include <asm/mach-types.h> | ||
25 | |||
26 | extern void ctrl_alt_del(void); | ||
27 | |||
28 | static irqreturn_t nslu2_power_handler(int irq, void *dev_id, struct pt_regs *regs) | ||
29 | { | ||
30 | /* Signal init to do the ctrlaltdel action, this will bypass init if | ||
31 | * it hasn't started and do a kernel_restart. | ||
32 | */ | ||
33 | ctrl_alt_del(); | ||
34 | |||
35 | return IRQ_HANDLED; | ||
36 | } | ||
37 | |||
38 | static irqreturn_t nslu2_reset_handler(int irq, void *dev_id, struct pt_regs *regs) | ||
39 | { | ||
40 | /* This is the paper-clip reset, it shuts the machine down directly. | ||
41 | */ | ||
42 | machine_power_off(); | ||
43 | |||
44 | return IRQ_HANDLED; | ||
45 | } | ||
46 | |||
47 | static int __init nslu2_power_init(void) | ||
48 | { | ||
49 | if (!(machine_is_nslu2())) | ||
50 | return 0; | ||
51 | |||
52 | *IXP4XX_GPIO_GPISR = 0x20400000; /* read the 2 irqs to clr */ | ||
53 | |||
54 | set_irq_type(NSLU2_RB_IRQ, IRQT_LOW); | ||
55 | set_irq_type(NSLU2_PB_IRQ, IRQT_HIGH); | ||
56 | |||
57 | gpio_line_isr_clear(NSLU2_RB_GPIO); | ||
58 | gpio_line_isr_clear(NSLU2_PB_GPIO); | ||
59 | |||
60 | if (request_irq(NSLU2_RB_IRQ, &nslu2_reset_handler, | ||
61 | SA_INTERRUPT, "NSLU2 reset button", NULL) < 0) { | ||
62 | |||
63 | printk(KERN_DEBUG "Reset Button IRQ %d not available\n", | ||
64 | NSLU2_RB_IRQ); | ||
65 | |||
66 | return -EIO; | ||
67 | } | ||
68 | |||
69 | if (request_irq(NSLU2_PB_IRQ, &nslu2_power_handler, | ||
70 | SA_INTERRUPT, "NSLU2 power button", NULL) < 0) { | ||
71 | |||
72 | printk(KERN_DEBUG "Power Button IRQ %d not available\n", | ||
73 | NSLU2_PB_IRQ); | ||
74 | |||
75 | return -EIO; | ||
76 | } | ||
77 | |||
78 | return 0; | ||
79 | } | ||
80 | |||
81 | static void __exit nslu2_power_exit(void) | ||
82 | { | ||
83 | free_irq(NSLU2_RB_IRQ, NULL); | ||
84 | free_irq(NSLU2_PB_IRQ, NULL); | ||
85 | } | ||
86 | |||
87 | module_init(nslu2_power_init); | ||
88 | module_exit(nslu2_power_exit); | ||
89 | |||
90 | MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); | ||
91 | MODULE_DESCRIPTION("NSLU2 Power/Reset driver"); | ||
92 | MODULE_LICENSE("GPL"); | ||
diff --git a/arch/arm/mach-ixp4xx/nslu2-setup.c b/arch/arm/mach-ixp4xx/nslu2-setup.c new file mode 100644 index 000000000000..289e94cb65c2 --- /dev/null +++ b/arch/arm/mach-ixp4xx/nslu2-setup.c | |||
@@ -0,0 +1,134 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-ixp4xx/nslu2-setup.c | ||
3 | * | ||
4 | * NSLU2 board-setup | ||
5 | * | ||
6 | * based ixdp425-setup.c: | ||
7 | * Copyright (C) 2003-2004 MontaVista Software, Inc. | ||
8 | * | ||
9 | * Author: Mark Rakes <mrakes at mac.com> | ||
10 | * Maintainers: http://www.nslu2-linux.org/ | ||
11 | * | ||
12 | * Fixed missing init_time in MACHINE_START kas11 10/22/04 | ||
13 | * Changed to conform to new style __init ixdp425 kas11 10/22/04 | ||
14 | */ | ||
15 | |||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/serial.h> | ||
18 | #include <linux/serial_8250.h> | ||
19 | |||
20 | #include <asm/mach-types.h> | ||
21 | #include <asm/mach/arch.h> | ||
22 | #include <asm/mach/flash.h> | ||
23 | |||
24 | static struct flash_platform_data nslu2_flash_data = { | ||
25 | .map_name = "cfi_probe", | ||
26 | .width = 2, | ||
27 | }; | ||
28 | |||
29 | static struct resource nslu2_flash_resource = { | ||
30 | .start = NSLU2_FLASH_BASE, | ||
31 | .end = NSLU2_FLASH_BASE + NSLU2_FLASH_SIZE, | ||
32 | .flags = IORESOURCE_MEM, | ||
33 | }; | ||
34 | |||
35 | static struct platform_device nslu2_flash = { | ||
36 | .name = "IXP4XX-Flash", | ||
37 | .id = 0, | ||
38 | .dev.platform_data = &nslu2_flash_data, | ||
39 | .num_resources = 1, | ||
40 | .resource = &nslu2_flash_resource, | ||
41 | }; | ||
42 | |||
43 | static struct ixp4xx_i2c_pins nslu2_i2c_gpio_pins = { | ||
44 | .sda_pin = NSLU2_SDA_PIN, | ||
45 | .scl_pin = NSLU2_SCL_PIN, | ||
46 | }; | ||
47 | |||
48 | static struct platform_device nslu2_i2c_controller = { | ||
49 | .name = "IXP4XX-I2C", | ||
50 | .id = 0, | ||
51 | .dev.platform_data = &nslu2_i2c_gpio_pins, | ||
52 | .num_resources = 0, | ||
53 | }; | ||
54 | |||
55 | static struct resource nslu2_uart_resources[] = { | ||
56 | { | ||
57 | .start = IXP4XX_UART1_BASE_PHYS, | ||
58 | .end = IXP4XX_UART1_BASE_PHYS + 0x0fff, | ||
59 | .flags = IORESOURCE_MEM, | ||
60 | }, | ||
61 | { | ||
62 | .start = IXP4XX_UART2_BASE_PHYS, | ||
63 | .end = IXP4XX_UART2_BASE_PHYS + 0x0fff, | ||
64 | .flags = IORESOURCE_MEM, | ||
65 | } | ||
66 | }; | ||
67 | |||
68 | static struct plat_serial8250_port nslu2_uart_data[] = { | ||
69 | { | ||
70 | .mapbase = IXP4XX_UART1_BASE_PHYS, | ||
71 | .membase = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET, | ||
72 | .irq = IRQ_IXP4XX_UART1, | ||
73 | .flags = UPF_BOOT_AUTOCONF, | ||
74 | .iotype = UPIO_MEM, | ||
75 | .regshift = 2, | ||
76 | .uartclk = IXP4XX_UART_XTAL, | ||
77 | }, | ||
78 | { | ||
79 | .mapbase = IXP4XX_UART2_BASE_PHYS, | ||
80 | .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET, | ||
81 | .irq = IRQ_IXP4XX_UART2, | ||
82 | .flags = UPF_BOOT_AUTOCONF, | ||
83 | .iotype = UPIO_MEM, | ||
84 | .regshift = 2, | ||
85 | .uartclk = IXP4XX_UART_XTAL, | ||
86 | }, | ||
87 | { } | ||
88 | }; | ||
89 | |||
90 | static struct platform_device nslu2_uart = { | ||
91 | .name = "serial8250", | ||
92 | .id = PLAT8250_DEV_PLATFORM, | ||
93 | .dev.platform_data = nslu2_uart_data, | ||
94 | .num_resources = 2, | ||
95 | .resource = nslu2_uart_resources, | ||
96 | }; | ||
97 | |||
98 | static struct platform_device *nslu2_devices[] __initdata = { | ||
99 | &nslu2_i2c_controller, | ||
100 | &nslu2_flash, | ||
101 | &nslu2_uart, | ||
102 | }; | ||
103 | |||
104 | static void nslu2_power_off(void) | ||
105 | { | ||
106 | /* This causes the box to drop the power and go dead. */ | ||
107 | |||
108 | /* enable the pwr cntl gpio */ | ||
109 | gpio_line_config(NSLU2_PO_GPIO, IXP4XX_GPIO_OUT); | ||
110 | |||
111 | /* do the deed */ | ||
112 | gpio_line_set(NSLU2_PO_GPIO, IXP4XX_GPIO_HIGH); | ||
113 | } | ||
114 | |||
115 | static void __init nslu2_init(void) | ||
116 | { | ||
117 | ixp4xx_sys_init(); | ||
118 | |||
119 | pm_power_off = nslu2_power_off; | ||
120 | |||
121 | platform_add_devices(nslu2_devices, ARRAY_SIZE(nslu2_devices)); | ||
122 | } | ||
123 | |||
124 | MACHINE_START(NSLU2, "Linksys NSLU2") | ||
125 | /* Maintainer: www.nslu2-linux.org */ | ||
126 | .phys_ram = PHYS_OFFSET, | ||
127 | .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, | ||
128 | .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xFFFC, | ||
129 | .boot_params = 0x00000100, | ||
130 | .map_io = ixp4xx_map_io, | ||
131 | .init_irq = ixp4xx_init_irq, | ||
132 | .timer = &ixp4xx_timer, | ||
133 | .init_machine = nslu2_init, | ||
134 | MACHINE_END | ||
diff --git a/arch/arm/mach-omap1/Kconfig b/arch/arm/mach-omap1/Kconfig index 27fc2e8e5fca..86a0f0d14345 100644 --- a/arch/arm/mach-omap1/Kconfig +++ b/arch/arm/mach-omap1/Kconfig | |||
@@ -6,10 +6,10 @@ config ARCH_OMAP730 | |||
6 | bool "OMAP730 Based System" | 6 | bool "OMAP730 Based System" |
7 | select ARCH_OMAP_OTG | 7 | select ARCH_OMAP_OTG |
8 | 8 | ||
9 | config ARCH_OMAP1510 | 9 | config ARCH_OMAP15XX |
10 | depends on ARCH_OMAP1 | 10 | depends on ARCH_OMAP1 |
11 | default y | 11 | default y |
12 | bool "OMAP1510 Based System" | 12 | bool "OMAP15xx Based System" |
13 | 13 | ||
14 | config ARCH_OMAP16XX | 14 | config ARCH_OMAP16XX |
15 | depends on ARCH_OMAP1 | 15 | depends on ARCH_OMAP1 |
@@ -21,7 +21,7 @@ comment "OMAP Board Type" | |||
21 | 21 | ||
22 | config MACH_OMAP_INNOVATOR | 22 | config MACH_OMAP_INNOVATOR |
23 | bool "TI Innovator" | 23 | bool "TI Innovator" |
24 | depends on ARCH_OMAP1 && (ARCH_OMAP1510 || ARCH_OMAP16XX) | 24 | depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX) |
25 | help | 25 | help |
26 | TI OMAP 1510 or 1610 Innovator board support. Say Y here if you | 26 | TI OMAP 1510 or 1610 Innovator board support. Say Y here if you |
27 | have such a board. | 27 | have such a board. |
@@ -64,20 +64,30 @@ config MACH_OMAP_PERSEUS2 | |||
64 | 64 | ||
65 | config MACH_VOICEBLUE | 65 | config MACH_VOICEBLUE |
66 | bool "Voiceblue" | 66 | bool "Voiceblue" |
67 | depends on ARCH_OMAP1 && ARCH_OMAP1510 | 67 | depends on ARCH_OMAP1 && ARCH_OMAP15XX |
68 | help | 68 | help |
69 | Support for Voiceblue GSM/VoIP gateway. Say Y here if you have | 69 | Support for Voiceblue GSM/VoIP gateway. Say Y here if you have |
70 | such a board. | 70 | such a board. |
71 | 71 | ||
72 | config MACH_NETSTAR | 72 | config MACH_NETSTAR |
73 | bool "NetStar" | 73 | bool "NetStar" |
74 | depends on ARCH_OMAP1 && ARCH_OMAP1510 | 74 | depends on ARCH_OMAP1 && ARCH_OMAP15XX |
75 | help | 75 | help |
76 | Support for NetStar PBX. Say Y here if you have such a board. | 76 | Support for NetStar PBX. Say Y here if you have such a board. |
77 | 77 | ||
78 | config MACH_OMAP_PALMTE | ||
79 | bool "Palm Tungsten E" | ||
80 | depends on ARCH_OMAP1 && ARCH_OMAP15XX | ||
81 | help | ||
82 | Support for the Palm Tungsten E PDA. Currently only the LCD panel | ||
83 | is supported. To boot the kernel, you'll need a PalmOS compatible | ||
84 | bootloader; check out http://palmtelinux.sourceforge.net for more | ||
85 | informations. | ||
86 | Say Y here if you have such a PDA, say NO otherwise. | ||
87 | |||
78 | config MACH_OMAP_GENERIC | 88 | config MACH_OMAP_GENERIC |
79 | bool "Generic OMAP board" | 89 | bool "Generic OMAP board" |
80 | depends on ARCH_OMAP1 && (ARCH_OMAP1510 || ARCH_OMAP16XX) | 90 | depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX) |
81 | help | 91 | help |
82 | Support for generic OMAP-1510, 1610 or 1710 board with | 92 | Support for generic OMAP-1510, 1610 or 1710 board with |
83 | no FPGA. Can be used as template for porting Linux to | 93 | no FPGA. Can be used as template for porting Linux to |
@@ -121,32 +131,32 @@ config OMAP_ARM_182MHZ | |||
121 | 131 | ||
122 | config OMAP_ARM_168MHZ | 132 | config OMAP_ARM_168MHZ |
123 | bool "OMAP ARM 168 MHz CPU" | 133 | bool "OMAP ARM 168 MHz CPU" |
124 | depends on ARCH_OMAP1 && (ARCH_OMAP1510 || ARCH_OMAP16XX || ARCH_OMAP730) | 134 | depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730) |
125 | help | 135 | help |
126 | Enable 168MHz clock for OMAP CPU. If unsure, say N. | 136 | Enable 168MHz clock for OMAP CPU. If unsure, say N. |
127 | 137 | ||
128 | config OMAP_ARM_150MHZ | 138 | config OMAP_ARM_150MHZ |
129 | bool "OMAP ARM 150 MHz CPU" | 139 | bool "OMAP ARM 150 MHz CPU" |
130 | depends on ARCH_OMAP1 && ARCH_OMAP1510 | 140 | depends on ARCH_OMAP1 && ARCH_OMAP15XX |
131 | help | 141 | help |
132 | Enable 150MHz clock for OMAP CPU. If unsure, say N. | 142 | Enable 150MHz clock for OMAP CPU. If unsure, say N. |
133 | 143 | ||
134 | config OMAP_ARM_120MHZ | 144 | config OMAP_ARM_120MHZ |
135 | bool "OMAP ARM 120 MHz CPU" | 145 | bool "OMAP ARM 120 MHz CPU" |
136 | depends on ARCH_OMAP1 && (ARCH_OMAP1510 || ARCH_OMAP16XX || ARCH_OMAP730) | 146 | depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730) |
137 | help | 147 | help |
138 | Enable 120MHz clock for OMAP CPU. If unsure, say N. | 148 | Enable 120MHz clock for OMAP CPU. If unsure, say N. |
139 | 149 | ||
140 | config OMAP_ARM_60MHZ | 150 | config OMAP_ARM_60MHZ |
141 | bool "OMAP ARM 60 MHz CPU" | 151 | bool "OMAP ARM 60 MHz CPU" |
142 | depends on ARCH_OMAP1 && (ARCH_OMAP1510 || ARCH_OMAP16XX || ARCH_OMAP730) | 152 | depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730) |
143 | default y | 153 | default y |
144 | help | 154 | help |
145 | Enable 60MHz clock for OMAP CPU. If unsure, say Y. | 155 | Enable 60MHz clock for OMAP CPU. If unsure, say Y. |
146 | 156 | ||
147 | config OMAP_ARM_30MHZ | 157 | config OMAP_ARM_30MHZ |
148 | bool "OMAP ARM 30 MHz CPU" | 158 | bool "OMAP ARM 30 MHz CPU" |
149 | depends on ARCH_OMAP1 && (ARCH_OMAP1510 || ARCH_OMAP16XX || ARCH_OMAP730) | 159 | depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730) |
150 | help | 160 | help |
151 | Enable 30MHz clock for OMAP CPU. If unsure, say N. | 161 | Enable 30MHz clock for OMAP CPU. If unsure, say N. |
152 | 162 | ||
diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile index 181a93deaaee..b0b00156faae 100644 --- a/arch/arm/mach-omap1/Makefile +++ b/arch/arm/mach-omap1/Makefile | |||
@@ -3,7 +3,7 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | # Common support | 5 | # Common support |
6 | obj-y := io.o id.o irq.o time.o serial.o devices.o | 6 | obj-y := io.o id.o clock.o irq.o time.o mux.o serial.o devices.o |
7 | led-y := leds.o | 7 | led-y := leds.o |
8 | 8 | ||
9 | # Specific board support | 9 | # Specific board support |
@@ -15,8 +15,9 @@ obj-$(CONFIG_MACH_OMAP_OSK) += board-osk.o | |||
15 | obj-$(CONFIG_MACH_OMAP_H3) += board-h3.o | 15 | obj-$(CONFIG_MACH_OMAP_H3) += board-h3.o |
16 | obj-$(CONFIG_MACH_VOICEBLUE) += board-voiceblue.o | 16 | obj-$(CONFIG_MACH_VOICEBLUE) += board-voiceblue.o |
17 | obj-$(CONFIG_MACH_NETSTAR) += board-netstar.o | 17 | obj-$(CONFIG_MACH_NETSTAR) += board-netstar.o |
18 | obj-$(CONFIG_MACH_OMAP_PALMTE) += board-palmte.o | ||
18 | 19 | ||
19 | ifeq ($(CONFIG_ARCH_OMAP1510),y) | 20 | ifeq ($(CONFIG_ARCH_OMAP15XX),y) |
20 | # Innovator-1510 FPGA | 21 | # Innovator-1510 FPGA |
21 | obj-$(CONFIG_MACH_OMAP_INNOVATOR) += fpga.o | 22 | obj-$(CONFIG_MACH_OMAP_INNOVATOR) += fpga.o |
22 | endif | 23 | endif |
diff --git a/arch/arm/mach-omap1/board-generic.c b/arch/arm/mach-omap1/board-generic.c index c209c7172a9a..4b292e93fbe2 100644 --- a/arch/arm/mach-omap1/board-generic.c +++ b/arch/arm/mach-omap1/board-generic.c | |||
@@ -15,7 +15,7 @@ | |||
15 | 15 | ||
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
18 | #include <linux/device.h> | 18 | #include <linux/platform_device.h> |
19 | 19 | ||
20 | #include <asm/hardware.h> | 20 | #include <asm/hardware.h> |
21 | #include <asm/mach-types.h> | 21 | #include <asm/mach-types.h> |
@@ -28,8 +28,6 @@ | |||
28 | #include <asm/arch/board.h> | 28 | #include <asm/arch/board.h> |
29 | #include <asm/arch/common.h> | 29 | #include <asm/arch/common.h> |
30 | 30 | ||
31 | static int __initdata generic_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1}; | ||
32 | |||
33 | static void __init omap_generic_init_irq(void) | 31 | static void __init omap_generic_init_irq(void) |
34 | { | 32 | { |
35 | omap_init_irq(); | 33 | omap_init_irq(); |
@@ -37,7 +35,7 @@ static void __init omap_generic_init_irq(void) | |||
37 | 35 | ||
38 | /* assume no Mini-AB port */ | 36 | /* assume no Mini-AB port */ |
39 | 37 | ||
40 | #ifdef CONFIG_ARCH_OMAP1510 | 38 | #ifdef CONFIG_ARCH_OMAP15XX |
41 | static struct omap_usb_config generic1510_usb_config __initdata = { | 39 | static struct omap_usb_config generic1510_usb_config __initdata = { |
42 | .register_host = 1, | 40 | .register_host = 1, |
43 | .register_dev = 1, | 41 | .register_dev = 1, |
@@ -76,21 +74,19 @@ static struct omap_mmc_config generic_mmc_config __initdata = { | |||
76 | 74 | ||
77 | #endif | 75 | #endif |
78 | 76 | ||
77 | static struct omap_uart_config generic_uart_config __initdata = { | ||
78 | .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)), | ||
79 | }; | ||
80 | |||
79 | static struct omap_board_config_kernel generic_config[] = { | 81 | static struct omap_board_config_kernel generic_config[] = { |
80 | { OMAP_TAG_USB, NULL }, | 82 | { OMAP_TAG_USB, NULL }, |
81 | { OMAP_TAG_MMC, &generic_mmc_config }, | 83 | { OMAP_TAG_MMC, &generic_mmc_config }, |
84 | { OMAP_TAG_UART, &generic_uart_config }, | ||
82 | }; | 85 | }; |
83 | 86 | ||
84 | static void __init omap_generic_init(void) | 87 | static void __init omap_generic_init(void) |
85 | { | 88 | { |
86 | const struct omap_uart_config *uart_conf; | 89 | #ifdef CONFIG_ARCH_OMAP15XX |
87 | |||
88 | /* | ||
89 | * Make sure the serial ports are muxed on at this point. | ||
90 | * You have to mux them off in device drivers later on | ||
91 | * if not needed. | ||
92 | */ | ||
93 | #ifdef CONFIG_ARCH_OMAP1510 | ||
94 | if (cpu_is_omap1510()) { | 90 | if (cpu_is_omap1510()) { |
95 | generic_config[0].data = &generic1510_usb_config; | 91 | generic_config[0].data = &generic1510_usb_config; |
96 | } | 92 | } |
@@ -101,20 +97,9 @@ static void __init omap_generic_init(void) | |||
101 | } | 97 | } |
102 | #endif | 98 | #endif |
103 | 99 | ||
104 | uart_conf = omap_get_config(OMAP_TAG_UART, struct omap_uart_config); | ||
105 | if (uart_conf != NULL) { | ||
106 | unsigned int enabled_ports, i; | ||
107 | |||
108 | enabled_ports = uart_conf->enabled_uarts; | ||
109 | for (i = 0; i < 3; i++) { | ||
110 | if (!(enabled_ports & (1 << i))) | ||
111 | generic_serial_ports[i] = 0; | ||
112 | } | ||
113 | } | ||
114 | |||
115 | omap_board_config = generic_config; | 100 | omap_board_config = generic_config; |
116 | omap_board_config_size = ARRAY_SIZE(generic_config); | 101 | omap_board_config_size = ARRAY_SIZE(generic_config); |
117 | omap_serial_init(generic_serial_ports); | 102 | omap_serial_init(); |
118 | } | 103 | } |
119 | 104 | ||
120 | static void __init omap_generic_map_io(void) | 105 | static void __init omap_generic_map_io(void) |
diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c index 4ee6bd8a50b8..a07e2c9307fa 100644 --- a/arch/arm/mach-omap1/board-h2.c +++ b/arch/arm/mach-omap1/board-h2.c | |||
@@ -40,8 +40,6 @@ | |||
40 | 40 | ||
41 | extern int omap_gpio_init(void); | 41 | extern int omap_gpio_init(void); |
42 | 42 | ||
43 | static int __initdata h2_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1}; | ||
44 | |||
45 | static struct mtd_partition h2_partitions[] = { | 43 | static struct mtd_partition h2_partitions[] = { |
46 | /* bootloader (U-Boot, etc) in first sector */ | 44 | /* bootloader (U-Boot, etc) in first sector */ |
47 | { | 45 | { |
@@ -160,9 +158,20 @@ static struct omap_mmc_config h2_mmc_config __initdata = { | |||
160 | }, | 158 | }, |
161 | }; | 159 | }; |
162 | 160 | ||
161 | static struct omap_uart_config h2_uart_config __initdata = { | ||
162 | .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)), | ||
163 | }; | ||
164 | |||
165 | static struct omap_lcd_config h2_lcd_config __initdata = { | ||
166 | .panel_name = "h2", | ||
167 | .ctrl_name = "internal", | ||
168 | }; | ||
169 | |||
163 | static struct omap_board_config_kernel h2_config[] = { | 170 | static struct omap_board_config_kernel h2_config[] = { |
164 | { OMAP_TAG_USB, &h2_usb_config }, | 171 | { OMAP_TAG_USB, &h2_usb_config }, |
165 | { OMAP_TAG_MMC, &h2_mmc_config }, | 172 | { OMAP_TAG_MMC, &h2_mmc_config }, |
173 | { OMAP_TAG_UART, &h2_uart_config }, | ||
174 | { OMAP_TAG_LCD, &h2_lcd_config }, | ||
166 | }; | 175 | }; |
167 | 176 | ||
168 | static void __init h2_init(void) | 177 | static void __init h2_init(void) |
@@ -180,12 +189,12 @@ static void __init h2_init(void) | |||
180 | platform_add_devices(h2_devices, ARRAY_SIZE(h2_devices)); | 189 | platform_add_devices(h2_devices, ARRAY_SIZE(h2_devices)); |
181 | omap_board_config = h2_config; | 190 | omap_board_config = h2_config; |
182 | omap_board_config_size = ARRAY_SIZE(h2_config); | 191 | omap_board_config_size = ARRAY_SIZE(h2_config); |
192 | omap_serial_init(); | ||
183 | } | 193 | } |
184 | 194 | ||
185 | static void __init h2_map_io(void) | 195 | static void __init h2_map_io(void) |
186 | { | 196 | { |
187 | omap_map_common_io(); | 197 | omap_map_common_io(); |
188 | omap_serial_init(h2_serial_ports); | ||
189 | } | 198 | } |
190 | 199 | ||
191 | MACHINE_START(OMAP_H2, "TI-H2") | 200 | MACHINE_START(OMAP_H2, "TI-H2") |
diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c index fc824361430d..668e278433c2 100644 --- a/arch/arm/mach-omap1/board-h3.c +++ b/arch/arm/mach-omap1/board-h3.c | |||
@@ -41,8 +41,6 @@ | |||
41 | 41 | ||
42 | extern int omap_gpio_init(void); | 42 | extern int omap_gpio_init(void); |
43 | 43 | ||
44 | static int __initdata h3_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1}; | ||
45 | |||
46 | static struct mtd_partition h3_partitions[] = { | 44 | static struct mtd_partition h3_partitions[] = { |
47 | /* bootloader (U-Boot, etc) in first sector */ | 45 | /* bootloader (U-Boot, etc) in first sector */ |
48 | { | 46 | { |
@@ -168,9 +166,20 @@ static struct omap_mmc_config h3_mmc_config __initdata = { | |||
168 | }, | 166 | }, |
169 | }; | 167 | }; |
170 | 168 | ||
169 | static struct omap_uart_config h3_uart_config __initdata = { | ||
170 | .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)), | ||
171 | }; | ||
172 | |||
173 | static struct omap_lcd_config h3_lcd_config __initdata = { | ||
174 | .panel_name = "h3", | ||
175 | .ctrl_name = "internal", | ||
176 | }; | ||
177 | |||
171 | static struct omap_board_config_kernel h3_config[] = { | 178 | static struct omap_board_config_kernel h3_config[] = { |
172 | { OMAP_TAG_USB, &h3_usb_config }, | 179 | { OMAP_TAG_USB, &h3_usb_config }, |
173 | { OMAP_TAG_MMC, &h3_mmc_config }, | 180 | { OMAP_TAG_MMC, &h3_mmc_config }, |
181 | { OMAP_TAG_UART, &h3_uart_config }, | ||
182 | { OMAP_TAG_LCD, &h3_lcd_config }, | ||
174 | }; | 183 | }; |
175 | 184 | ||
176 | static void __init h3_init(void) | 185 | static void __init h3_init(void) |
@@ -180,6 +189,7 @@ static void __init h3_init(void) | |||
180 | (void) platform_add_devices(devices, ARRAY_SIZE(devices)); | 189 | (void) platform_add_devices(devices, ARRAY_SIZE(devices)); |
181 | omap_board_config = h3_config; | 190 | omap_board_config = h3_config; |
182 | omap_board_config_size = ARRAY_SIZE(h3_config); | 191 | omap_board_config_size = ARRAY_SIZE(h3_config); |
192 | omap_serial_init(); | ||
183 | } | 193 | } |
184 | 194 | ||
185 | static void __init h3_init_smc91x(void) | 195 | static void __init h3_init_smc91x(void) |
@@ -201,7 +211,6 @@ void h3_init_irq(void) | |||
201 | static void __init h3_map_io(void) | 211 | static void __init h3_map_io(void) |
202 | { | 212 | { |
203 | omap_map_common_io(); | 213 | omap_map_common_io(); |
204 | omap_serial_init(h3_serial_ports); | ||
205 | } | 214 | } |
206 | 215 | ||
207 | MACHINE_START(OMAP_H3, "TI OMAP1710 H3 board") | 216 | MACHINE_START(OMAP_H3, "TI OMAP1710 H3 board") |
diff --git a/arch/arm/mach-omap1/board-innovator.c b/arch/arm/mach-omap1/board-innovator.c index a2eac853b2da..95f1ff36cdcb 100644 --- a/arch/arm/mach-omap1/board-innovator.c +++ b/arch/arm/mach-omap1/board-innovator.c | |||
@@ -36,8 +36,6 @@ | |||
36 | #include <asm/arch/usb.h> | 36 | #include <asm/arch/usb.h> |
37 | #include <asm/arch/common.h> | 37 | #include <asm/arch/common.h> |
38 | 38 | ||
39 | static int __initdata innovator_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1}; | ||
40 | |||
41 | static struct mtd_partition innovator_partitions[] = { | 39 | static struct mtd_partition innovator_partitions[] = { |
42 | /* bootloader (U-Boot, etc) in first sector */ | 40 | /* bootloader (U-Boot, etc) in first sector */ |
43 | { | 41 | { |
@@ -99,7 +97,7 @@ static struct platform_device innovator_flash_device = { | |||
99 | .resource = &innovator_flash_resource, | 97 | .resource = &innovator_flash_resource, |
100 | }; | 98 | }; |
101 | 99 | ||
102 | #ifdef CONFIG_ARCH_OMAP1510 | 100 | #ifdef CONFIG_ARCH_OMAP15XX |
103 | 101 | ||
104 | /* Only FPGA needs to be mapped here. All others are done with ioremap */ | 102 | /* Only FPGA needs to be mapped here. All others are done with ioremap */ |
105 | static struct map_desc innovator1510_io_desc[] __initdata = { | 103 | static struct map_desc innovator1510_io_desc[] __initdata = { |
@@ -136,7 +134,7 @@ static struct platform_device *innovator1510_devices[] __initdata = { | |||
136 | &innovator1510_smc91x_device, | 134 | &innovator1510_smc91x_device, |
137 | }; | 135 | }; |
138 | 136 | ||
139 | #endif /* CONFIG_ARCH_OMAP1510 */ | 137 | #endif /* CONFIG_ARCH_OMAP15XX */ |
140 | 138 | ||
141 | #ifdef CONFIG_ARCH_OMAP16XX | 139 | #ifdef CONFIG_ARCH_OMAP16XX |
142 | 140 | ||
@@ -185,7 +183,7 @@ void innovator_init_irq(void) | |||
185 | { | 183 | { |
186 | omap_init_irq(); | 184 | omap_init_irq(); |
187 | omap_gpio_init(); | 185 | omap_gpio_init(); |
188 | #ifdef CONFIG_ARCH_OMAP1510 | 186 | #ifdef CONFIG_ARCH_OMAP15XX |
189 | if (cpu_is_omap1510()) { | 187 | if (cpu_is_omap1510()) { |
190 | omap1510_fpga_init_irq(); | 188 | omap1510_fpga_init_irq(); |
191 | } | 189 | } |
@@ -193,7 +191,7 @@ void innovator_init_irq(void) | |||
193 | innovator_init_smc91x(); | 191 | innovator_init_smc91x(); |
194 | } | 192 | } |
195 | 193 | ||
196 | #ifdef CONFIG_ARCH_OMAP1510 | 194 | #ifdef CONFIG_ARCH_OMAP15XX |
197 | static struct omap_usb_config innovator1510_usb_config __initdata = { | 195 | static struct omap_usb_config innovator1510_usb_config __initdata = { |
198 | /* for bundled non-standard host and peripheral cables */ | 196 | /* for bundled non-standard host and peripheral cables */ |
199 | .hmc_mode = 4, | 197 | .hmc_mode = 4, |
@@ -205,6 +203,11 @@ static struct omap_usb_config innovator1510_usb_config __initdata = { | |||
205 | .register_dev = 1, | 203 | .register_dev = 1, |
206 | .pins[0] = 2, | 204 | .pins[0] = 2, |
207 | }; | 205 | }; |
206 | |||
207 | static struct omap_lcd_config innovator1510_lcd_config __initdata = { | ||
208 | .panel_name = "inn1510", | ||
209 | .ctrl_name = "internal", | ||
210 | }; | ||
208 | #endif | 211 | #endif |
209 | 212 | ||
210 | #ifdef CONFIG_ARCH_OMAP16XX | 213 | #ifdef CONFIG_ARCH_OMAP16XX |
@@ -222,6 +225,11 @@ static struct omap_usb_config h2_usb_config __initdata = { | |||
222 | 225 | ||
223 | .pins[1] = 3, | 226 | .pins[1] = 3, |
224 | }; | 227 | }; |
228 | |||
229 | static struct omap_lcd_config innovator1610_lcd_config __initdata = { | ||
230 | .panel_name = "inn1610", | ||
231 | .ctrl_name = "internal", | ||
232 | }; | ||
225 | #endif | 233 | #endif |
226 | 234 | ||
227 | static struct omap_mmc_config innovator_mmc_config __initdata = { | 235 | static struct omap_mmc_config innovator_mmc_config __initdata = { |
@@ -234,14 +242,20 @@ static struct omap_mmc_config innovator_mmc_config __initdata = { | |||
234 | }, | 242 | }, |
235 | }; | 243 | }; |
236 | 244 | ||
245 | static struct omap_uart_config innovator_uart_config __initdata = { | ||
246 | .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)), | ||
247 | }; | ||
248 | |||
237 | static struct omap_board_config_kernel innovator_config[] = { | 249 | static struct omap_board_config_kernel innovator_config[] = { |
238 | { OMAP_TAG_USB, NULL }, | 250 | { OMAP_TAG_USB, NULL }, |
251 | { OMAP_TAG_LCD, NULL }, | ||
239 | { OMAP_TAG_MMC, &innovator_mmc_config }, | 252 | { OMAP_TAG_MMC, &innovator_mmc_config }, |
253 | { OMAP_TAG_UART, &innovator_uart_config }, | ||
240 | }; | 254 | }; |
241 | 255 | ||
242 | static void __init innovator_init(void) | 256 | static void __init innovator_init(void) |
243 | { | 257 | { |
244 | #ifdef CONFIG_ARCH_OMAP1510 | 258 | #ifdef CONFIG_ARCH_OMAP15XX |
245 | if (cpu_is_omap1510()) { | 259 | if (cpu_is_omap1510()) { |
246 | platform_add_devices(innovator1510_devices, ARRAY_SIZE(innovator1510_devices)); | 260 | platform_add_devices(innovator1510_devices, ARRAY_SIZE(innovator1510_devices)); |
247 | } | 261 | } |
@@ -252,23 +266,28 @@ static void __init innovator_init(void) | |||
252 | } | 266 | } |
253 | #endif | 267 | #endif |
254 | 268 | ||
255 | #ifdef CONFIG_ARCH_OMAP1510 | 269 | #ifdef CONFIG_ARCH_OMAP15XX |
256 | if (cpu_is_omap1510()) | 270 | if (cpu_is_omap1510()) { |
257 | innovator_config[0].data = &innovator1510_usb_config; | 271 | innovator_config[0].data = &innovator1510_usb_config; |
272 | innovator_config[1].data = &innovator1510_lcd_config; | ||
273 | } | ||
258 | #endif | 274 | #endif |
259 | #ifdef CONFIG_ARCH_OMAP16XX | 275 | #ifdef CONFIG_ARCH_OMAP16XX |
260 | if (cpu_is_omap1610()) | 276 | if (cpu_is_omap1610()) { |
261 | innovator_config[0].data = &h2_usb_config; | 277 | innovator_config[0].data = &h2_usb_config; |
278 | innovator_config[1].data = &innovator1610_lcd_config; | ||
279 | } | ||
262 | #endif | 280 | #endif |
263 | omap_board_config = innovator_config; | 281 | omap_board_config = innovator_config; |
264 | omap_board_config_size = ARRAY_SIZE(innovator_config); | 282 | omap_board_config_size = ARRAY_SIZE(innovator_config); |
283 | omap_serial_init(); | ||
265 | } | 284 | } |
266 | 285 | ||
267 | static void __init innovator_map_io(void) | 286 | static void __init innovator_map_io(void) |
268 | { | 287 | { |
269 | omap_map_common_io(); | 288 | omap_map_common_io(); |
270 | 289 | ||
271 | #ifdef CONFIG_ARCH_OMAP1510 | 290 | #ifdef CONFIG_ARCH_OMAP15XX |
272 | if (cpu_is_omap1510()) { | 291 | if (cpu_is_omap1510()) { |
273 | iotable_init(innovator1510_io_desc, ARRAY_SIZE(innovator1510_io_desc)); | 292 | iotable_init(innovator1510_io_desc, ARRAY_SIZE(innovator1510_io_desc)); |
274 | udelay(10); /* Delay needed for FPGA */ | 293 | udelay(10); /* Delay needed for FPGA */ |
@@ -280,7 +299,6 @@ static void __init innovator_map_io(void) | |||
280 | fpga_read(OMAP1510_FPGA_BOARD_REV)); | 299 | fpga_read(OMAP1510_FPGA_BOARD_REV)); |
281 | } | 300 | } |
282 | #endif | 301 | #endif |
283 | omap_serial_init(innovator_serial_ports); | ||
284 | } | 302 | } |
285 | 303 | ||
286 | MACHINE_START(OMAP_INNOVATOR, "TI-Innovator") | 304 | MACHINE_START(OMAP_INNOVATOR, "TI-Innovator") |
diff --git a/arch/arm/mach-omap1/board-netstar.c b/arch/arm/mach-omap1/board-netstar.c index c851c2e4dfcb..0448fa7de8a4 100644 --- a/arch/arm/mach-omap1/board-netstar.c +++ b/arch/arm/mach-omap1/board-netstar.c | |||
@@ -55,6 +55,14 @@ static struct platform_device *netstar_devices[] __initdata = { | |||
55 | &netstar_smc91x_device, | 55 | &netstar_smc91x_device, |
56 | }; | 56 | }; |
57 | 57 | ||
58 | static struct omap_uart_config netstar_uart_config __initdata = { | ||
59 | .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)), | ||
60 | }; | ||
61 | |||
62 | static struct omap_board_config_kernel netstar_config[] = { | ||
63 | { OMAP_TAG_UART, &netstar_uart_config }, | ||
64 | }; | ||
65 | |||
58 | static void __init netstar_init_irq(void) | 66 | static void __init netstar_init_irq(void) |
59 | { | 67 | { |
60 | omap_init_irq(); | 68 | omap_init_irq(); |
@@ -92,14 +100,15 @@ static void __init netstar_init(void) | |||
92 | /* Switch off red LED */ | 100 | /* Switch off red LED */ |
93 | omap_writeb(0x00, OMAP_LPG1_PMR); /* Disable clock */ | 101 | omap_writeb(0x00, OMAP_LPG1_PMR); /* Disable clock */ |
94 | omap_writeb(0x80, OMAP_LPG1_LCR); | 102 | omap_writeb(0x80, OMAP_LPG1_LCR); |
95 | } | ||
96 | 103 | ||
97 | static int __initdata omap_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1}; | 104 | omap_board_config = netstar_config; |
105 | omap_board_config_size = ARRAY_SIZE(netstar_config); | ||
106 | omap_serial_init(); | ||
107 | } | ||
98 | 108 | ||
99 | static void __init netstar_map_io(void) | 109 | static void __init netstar_map_io(void) |
100 | { | 110 | { |
101 | omap_map_common_io(); | 111 | omap_map_common_io(); |
102 | omap_serial_init(omap_serial_ports); | ||
103 | } | 112 | } |
104 | 113 | ||
105 | #define MACHINE_PANICED 1 | 114 | #define MACHINE_PANICED 1 |
diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c index a88524e7c315..e990e1bc1669 100644 --- a/arch/arm/mach-omap1/board-osk.c +++ b/arch/arm/mach-omap1/board-osk.c | |||
@@ -46,8 +46,6 @@ | |||
46 | #include <asm/arch/tc.h> | 46 | #include <asm/arch/tc.h> |
47 | #include <asm/arch/common.h> | 47 | #include <asm/arch/common.h> |
48 | 48 | ||
49 | static int __initdata osk_serial_ports[OMAP_MAX_NR_PORTS] = {1, 0, 0}; | ||
50 | |||
51 | static struct mtd_partition osk_partitions[] = { | 49 | static struct mtd_partition osk_partitions[] = { |
52 | /* bootloader (U-Boot, etc) in first sector */ | 50 | /* bootloader (U-Boot, etc) in first sector */ |
53 | { | 51 | { |
@@ -155,7 +153,7 @@ static void __init osk_init_smc91x(void) | |||
155 | } | 153 | } |
156 | 154 | ||
157 | /* Check EMIFS wait states to fix errors with SMC_GET_PKT_HDR */ | 155 | /* Check EMIFS wait states to fix errors with SMC_GET_PKT_HDR */ |
158 | EMIFS_CCS(1) |= 0x2; | 156 | EMIFS_CCS(1) |= 0x3; |
159 | } | 157 | } |
160 | 158 | ||
161 | static void __init osk_init_cf(void) | 159 | static void __init osk_init_cf(void) |
@@ -193,8 +191,19 @@ static struct omap_usb_config osk_usb_config __initdata = { | |||
193 | .pins[0] = 2, | 191 | .pins[0] = 2, |
194 | }; | 192 | }; |
195 | 193 | ||
194 | static struct omap_uart_config osk_uart_config __initdata = { | ||
195 | .enabled_uarts = (1 << 0), | ||
196 | }; | ||
197 | |||
198 | static struct omap_lcd_config osk_lcd_config __initdata = { | ||
199 | .panel_name = "osk", | ||
200 | .ctrl_name = "internal", | ||
201 | }; | ||
202 | |||
196 | static struct omap_board_config_kernel osk_config[] = { | 203 | static struct omap_board_config_kernel osk_config[] = { |
197 | { OMAP_TAG_USB, &osk_usb_config }, | 204 | { OMAP_TAG_USB, &osk_usb_config }, |
205 | { OMAP_TAG_UART, &osk_uart_config }, | ||
206 | { OMAP_TAG_LCD, &osk_lcd_config }, | ||
198 | }; | 207 | }; |
199 | 208 | ||
200 | #ifdef CONFIG_OMAP_OSK_MISTRAL | 209 | #ifdef CONFIG_OMAP_OSK_MISTRAL |
@@ -254,13 +263,13 @@ static void __init osk_init(void) | |||
254 | omap_board_config_size = ARRAY_SIZE(osk_config); | 263 | omap_board_config_size = ARRAY_SIZE(osk_config); |
255 | USB_TRANSCEIVER_CTRL_REG |= (3 << 1); | 264 | USB_TRANSCEIVER_CTRL_REG |= (3 << 1); |
256 | 265 | ||
266 | omap_serial_init(); | ||
257 | osk_mistral_init(); | 267 | osk_mistral_init(); |
258 | } | 268 | } |
259 | 269 | ||
260 | static void __init osk_map_io(void) | 270 | static void __init osk_map_io(void) |
261 | { | 271 | { |
262 | omap_map_common_io(); | 272 | omap_map_common_io(); |
263 | omap_serial_init(osk_serial_ports); | ||
264 | } | 273 | } |
265 | 274 | ||
266 | MACHINE_START(OMAP_OSK, "TI-OSK") | 275 | MACHINE_START(OMAP_OSK, "TI-OSK") |
diff --git a/arch/arm/mach-omap1/board-palmte.c b/arch/arm/mach-omap1/board-palmte.c new file mode 100644 index 000000000000..540b20d78cca --- /dev/null +++ b/arch/arm/mach-omap1/board-palmte.c | |||
@@ -0,0 +1,87 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-omap1/board-palmte.c | ||
3 | * | ||
4 | * Modified from board-generic.c | ||
5 | * | ||
6 | * Support for the Palm Tungsten E PDA. | ||
7 | * | ||
8 | * Original version : Laurent Gonzalez | ||
9 | * | ||
10 | * Maintainters : http://palmtelinux.sf.net | ||
11 | * palmtelinux-developpers@lists.sf.net | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License version 2 as | ||
15 | * published by the Free Software Foundation. | ||
16 | */ | ||
17 | |||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/notifier.h> | ||
22 | |||
23 | #include <asm/hardware.h> | ||
24 | #include <asm/mach-types.h> | ||
25 | #include <asm/mach/arch.h> | ||
26 | #include <asm/mach/map.h> | ||
27 | |||
28 | #include <asm/arch/gpio.h> | ||
29 | #include <asm/arch/mux.h> | ||
30 | #include <asm/arch/usb.h> | ||
31 | #include <asm/arch/board.h> | ||
32 | #include <asm/arch/common.h> | ||
33 | #include <asm/hardware/clock.h> | ||
34 | |||
35 | static void __init omap_generic_init_irq(void) | ||
36 | { | ||
37 | omap_init_irq(); | ||
38 | } | ||
39 | |||
40 | static struct omap_usb_config palmte_usb_config __initdata = { | ||
41 | .register_dev = 1, | ||
42 | .hmc_mode = 0, | ||
43 | .pins[0] = 3, | ||
44 | }; | ||
45 | |||
46 | static struct omap_mmc_config palmte_mmc_config __initdata = { | ||
47 | .mmc [0] = { | ||
48 | .enabled = 1, | ||
49 | .wire4 = 1, | ||
50 | .wp_pin = OMAP_MPUIO(3), | ||
51 | .power_pin = -1, | ||
52 | .switch_pin = -1, | ||
53 | }, | ||
54 | }; | ||
55 | |||
56 | static struct omap_lcd_config palmte_lcd_config __initdata = { | ||
57 | .panel_name = "palmte", | ||
58 | .ctrl_name = "internal", | ||
59 | }; | ||
60 | |||
61 | static struct omap_board_config_kernel palmte_config[] = { | ||
62 | { OMAP_TAG_USB, &palmte_usb_config }, | ||
63 | { OMAP_TAG_MMC, &palmte_mmc_config }, | ||
64 | { OMAP_TAG_LCD, &palmte_lcd_config }, | ||
65 | }; | ||
66 | |||
67 | static void __init omap_generic_init(void) | ||
68 | { | ||
69 | omap_board_config = palmte_config; | ||
70 | omap_board_config_size = ARRAY_SIZE(palmte_config); | ||
71 | } | ||
72 | |||
73 | static void __init omap_generic_map_io(void) | ||
74 | { | ||
75 | omap_map_common_io(); | ||
76 | } | ||
77 | |||
78 | MACHINE_START(OMAP_PALMTE, "OMAP310 based Palm Tungsten E") | ||
79 | .phys_ram = 0x10000000, | ||
80 | .phys_io = 0xfff00000, | ||
81 | .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc, | ||
82 | .boot_params = 0x10000100, | ||
83 | .map_io = omap_generic_map_io, | ||
84 | .init_irq = omap_generic_init_irq, | ||
85 | .init_machine = omap_generic_init, | ||
86 | .timer = &omap_timer, | ||
87 | MACHINE_END | ||
diff --git a/arch/arm/mach-omap1/board-perseus2.c b/arch/arm/mach-omap1/board-perseus2.c index 354b157acb3a..bd900b7ab33c 100644 --- a/arch/arm/mach-omap1/board-perseus2.c +++ b/arch/arm/mach-omap1/board-perseus2.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <asm/arch/mux.h> | 29 | #include <asm/arch/mux.h> |
30 | #include <asm/arch/fpga.h> | 30 | #include <asm/arch/fpga.h> |
31 | #include <asm/arch/common.h> | 31 | #include <asm/arch/common.h> |
32 | #include <asm/arch/board.h> | ||
32 | 33 | ||
33 | static struct resource smc91x_resources[] = { | 34 | static struct resource smc91x_resources[] = { |
34 | [0] = { | 35 | [0] = { |
@@ -43,8 +44,6 @@ static struct resource smc91x_resources[] = { | |||
43 | }, | 44 | }, |
44 | }; | 45 | }; |
45 | 46 | ||
46 | static int __initdata p2_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 0}; | ||
47 | |||
48 | static struct mtd_partition p2_partitions[] = { | 47 | static struct mtd_partition p2_partitions[] = { |
49 | /* bootloader (U-Boot, etc) in first sector */ | 48 | /* bootloader (U-Boot, etc) in first sector */ |
50 | { | 49 | { |
@@ -111,9 +110,27 @@ static struct platform_device *devices[] __initdata = { | |||
111 | &smc91x_device, | 110 | &smc91x_device, |
112 | }; | 111 | }; |
113 | 112 | ||
113 | static struct omap_uart_config perseus2_uart_config __initdata = { | ||
114 | .enabled_uarts = ((1 << 0) | (1 << 1)), | ||
115 | }; | ||
116 | |||
117 | static struct omap_lcd_config perseus2_lcd_config __initdata = { | ||
118 | .panel_name = "p2", | ||
119 | .ctrl_name = "internal", | ||
120 | }; | ||
121 | |||
122 | static struct omap_board_config_kernel perseus2_config[] = { | ||
123 | { OMAP_TAG_UART, &perseus2_uart_config }, | ||
124 | { OMAP_TAG_LCD, &perseus2_lcd_config }, | ||
125 | }; | ||
126 | |||
114 | static void __init omap_perseus2_init(void) | 127 | static void __init omap_perseus2_init(void) |
115 | { | 128 | { |
116 | (void) platform_add_devices(devices, ARRAY_SIZE(devices)); | 129 | (void) platform_add_devices(devices, ARRAY_SIZE(devices)); |
130 | |||
131 | omap_board_config = perseus2_config; | ||
132 | omap_board_config_size = ARRAY_SIZE(perseus2_config); | ||
133 | omap_serial_init(); | ||
117 | } | 134 | } |
118 | 135 | ||
119 | static void __init perseus2_init_smc91x(void) | 136 | static void __init perseus2_init_smc91x(void) |
@@ -131,7 +148,6 @@ void omap_perseus2_init_irq(void) | |||
131 | omap_gpio_init(); | 148 | omap_gpio_init(); |
132 | perseus2_init_smc91x(); | 149 | perseus2_init_smc91x(); |
133 | } | 150 | } |
134 | |||
135 | /* Only FPGA needs to be mapped here. All others are done with ioremap */ | 151 | /* Only FPGA needs to be mapped here. All others are done with ioremap */ |
136 | static struct map_desc omap_perseus2_io_desc[] __initdata = { | 152 | static struct map_desc omap_perseus2_io_desc[] __initdata = { |
137 | { | 153 | { |
@@ -179,7 +195,6 @@ static void __init omap_perseus2_map_io(void) | |||
179 | * It is used as the Ethernet controller interrupt | 195 | * It is used as the Ethernet controller interrupt |
180 | */ | 196 | */ |
181 | omap_writel(omap_readl(OMAP730_IO_CONF_9) & 0x1FFFFFFF, OMAP730_IO_CONF_9); | 197 | omap_writel(omap_readl(OMAP730_IO_CONF_9) & 0x1FFFFFFF, OMAP730_IO_CONF_9); |
182 | omap_serial_init(p2_serial_ports); | ||
183 | } | 198 | } |
184 | 199 | ||
185 | MACHINE_START(OMAP_PERSEUS2, "OMAP730 Perseus2") | 200 | MACHINE_START(OMAP_PERSEUS2, "OMAP730 Perseus2") |
diff --git a/arch/arm/mach-omap1/board-voiceblue.c b/arch/arm/mach-omap1/board-voiceblue.c index 3f018b296861..6f9a6220e78a 100644 --- a/arch/arm/mach-omap1/board-voiceblue.c +++ b/arch/arm/mach-omap1/board-voiceblue.c | |||
@@ -150,9 +150,14 @@ static struct omap_mmc_config voiceblue_mmc_config __initdata = { | |||
150 | }, | 150 | }, |
151 | }; | 151 | }; |
152 | 152 | ||
153 | static struct omap_uart_config voiceblue_uart_config __initdata = { | ||
154 | .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)), | ||
155 | }; | ||
156 | |||
153 | static struct omap_board_config_kernel voiceblue_config[] = { | 157 | static struct omap_board_config_kernel voiceblue_config[] = { |
154 | { OMAP_TAG_USB, &voiceblue_usb_config }, | 158 | { OMAP_TAG_USB, &voiceblue_usb_config }, |
155 | { OMAP_TAG_MMC, &voiceblue_mmc_config }, | 159 | { OMAP_TAG_MMC, &voiceblue_mmc_config }, |
160 | { OMAP_TAG_UART, &voiceblue_uart_config }, | ||
156 | }; | 161 | }; |
157 | 162 | ||
158 | static void __init voiceblue_init_irq(void) | 163 | static void __init voiceblue_init_irq(void) |
@@ -191,6 +196,7 @@ static void __init voiceblue_init(void) | |||
191 | platform_add_devices(voiceblue_devices, ARRAY_SIZE(voiceblue_devices)); | 196 | platform_add_devices(voiceblue_devices, ARRAY_SIZE(voiceblue_devices)); |
192 | omap_board_config = voiceblue_config; | 197 | omap_board_config = voiceblue_config; |
193 | omap_board_config_size = ARRAY_SIZE(voiceblue_config); | 198 | omap_board_config_size = ARRAY_SIZE(voiceblue_config); |
199 | omap_serial_init(); | ||
194 | 200 | ||
195 | /* There is a good chance board is going up, so enable power LED | 201 | /* There is a good chance board is going up, so enable power LED |
196 | * (it is connected through invertor) */ | 202 | * (it is connected through invertor) */ |
@@ -198,12 +204,9 @@ static void __init voiceblue_init(void) | |||
198 | omap_writeb(0x00, OMAP_LPG1_PMR); /* Disable clock */ | 204 | omap_writeb(0x00, OMAP_LPG1_PMR); /* Disable clock */ |
199 | } | 205 | } |
200 | 206 | ||
201 | static int __initdata omap_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1}; | ||
202 | |||
203 | static void __init voiceblue_map_io(void) | 207 | static void __init voiceblue_map_io(void) |
204 | { | 208 | { |
205 | omap_map_common_io(); | 209 | omap_map_common_io(); |
206 | omap_serial_init(omap_serial_ports); | ||
207 | } | 210 | } |
208 | 211 | ||
209 | #define MACHINE_PANICED 1 | 212 | #define MACHINE_PANICED 1 |
diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c new file mode 100644 index 000000000000..4277eee44ed5 --- /dev/null +++ b/arch/arm/mach-omap1/clock.c | |||
@@ -0,0 +1,792 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-omap1/clock.c | ||
3 | * | ||
4 | * Copyright (C) 2004 - 2005 Nokia corporation | ||
5 | * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com> | ||
6 | * | ||
7 | * Modified to use omap shared clock framework by | ||
8 | * Tony Lindgren <tony@atomide.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/list.h> | ||
17 | #include <linux/errno.h> | ||
18 | #include <linux/err.h> | ||
19 | |||
20 | #include <asm/io.h> | ||
21 | #include <asm/hardware/clock.h> | ||
22 | |||
23 | #include <asm/arch/usb.h> | ||
24 | #include <asm/arch/clock.h> | ||
25 | #include <asm/arch/sram.h> | ||
26 | |||
27 | #include "clock.h" | ||
28 | |||
29 | __u32 arm_idlect1_mask; | ||
30 | |||
31 | /*------------------------------------------------------------------------- | ||
32 | * Omap1 specific clock functions | ||
33 | *-------------------------------------------------------------------------*/ | ||
34 | |||
35 | static void omap1_watchdog_recalc(struct clk * clk) | ||
36 | { | ||
37 | clk->rate = clk->parent->rate / 14; | ||
38 | } | ||
39 | |||
40 | static void omap1_uart_recalc(struct clk * clk) | ||
41 | { | ||
42 | unsigned int val = omap_readl(clk->enable_reg); | ||
43 | if (val & clk->enable_bit) | ||
44 | clk->rate = 48000000; | ||
45 | else | ||
46 | clk->rate = 12000000; | ||
47 | } | ||
48 | |||
49 | static int omap1_clk_enable_dsp_domain(struct clk *clk) | ||
50 | { | ||
51 | int retval; | ||
52 | |||
53 | retval = omap1_clk_use(&api_ck.clk); | ||
54 | if (!retval) { | ||
55 | retval = omap1_clk_enable(clk); | ||
56 | omap1_clk_unuse(&api_ck.clk); | ||
57 | } | ||
58 | |||
59 | return retval; | ||
60 | } | ||
61 | |||
62 | static void omap1_clk_disable_dsp_domain(struct clk *clk) | ||
63 | { | ||
64 | if (omap1_clk_use(&api_ck.clk) == 0) { | ||
65 | omap1_clk_disable(clk); | ||
66 | omap1_clk_unuse(&api_ck.clk); | ||
67 | } | ||
68 | } | ||
69 | |||
70 | static int omap1_clk_enable_uart_functional(struct clk *clk) | ||
71 | { | ||
72 | int ret; | ||
73 | struct uart_clk *uclk; | ||
74 | |||
75 | ret = omap1_clk_enable(clk); | ||
76 | if (ret == 0) { | ||
77 | /* Set smart idle acknowledgement mode */ | ||
78 | uclk = (struct uart_clk *)clk; | ||
79 | omap_writeb((omap_readb(uclk->sysc_addr) & ~0x10) | 8, | ||
80 | uclk->sysc_addr); | ||
81 | } | ||
82 | |||
83 | return ret; | ||
84 | } | ||
85 | |||
86 | static void omap1_clk_disable_uart_functional(struct clk *clk) | ||
87 | { | ||
88 | struct uart_clk *uclk; | ||
89 | |||
90 | /* Set force idle acknowledgement mode */ | ||
91 | uclk = (struct uart_clk *)clk; | ||
92 | omap_writeb((omap_readb(uclk->sysc_addr) & ~0x18), uclk->sysc_addr); | ||
93 | |||
94 | omap1_clk_disable(clk); | ||
95 | } | ||
96 | |||
97 | static void omap1_clk_allow_idle(struct clk *clk) | ||
98 | { | ||
99 | struct arm_idlect1_clk * iclk = (struct arm_idlect1_clk *)clk; | ||
100 | |||
101 | if (!(clk->flags & CLOCK_IDLE_CONTROL)) | ||
102 | return; | ||
103 | |||
104 | if (iclk->no_idle_count > 0 && !(--iclk->no_idle_count)) | ||
105 | arm_idlect1_mask |= 1 << iclk->idlect_shift; | ||
106 | } | ||
107 | |||
108 | static void omap1_clk_deny_idle(struct clk *clk) | ||
109 | { | ||
110 | struct arm_idlect1_clk * iclk = (struct arm_idlect1_clk *)clk; | ||
111 | |||
112 | if (!(clk->flags & CLOCK_IDLE_CONTROL)) | ||
113 | return; | ||
114 | |||
115 | if (iclk->no_idle_count++ == 0) | ||
116 | arm_idlect1_mask &= ~(1 << iclk->idlect_shift); | ||
117 | } | ||
118 | |||
119 | static __u16 verify_ckctl_value(__u16 newval) | ||
120 | { | ||
121 | /* This function checks for following limitations set | ||
122 | * by the hardware (all conditions must be true): | ||
123 | * DSPMMU_CK == DSP_CK or DSPMMU_CK == DSP_CK/2 | ||
124 | * ARM_CK >= TC_CK | ||
125 | * DSP_CK >= TC_CK | ||
126 | * DSPMMU_CK >= TC_CK | ||
127 | * | ||
128 | * In addition following rules are enforced: | ||
129 | * LCD_CK <= TC_CK | ||
130 | * ARMPER_CK <= TC_CK | ||
131 | * | ||
132 | * However, maximum frequencies are not checked for! | ||
133 | */ | ||
134 | __u8 per_exp; | ||
135 | __u8 lcd_exp; | ||
136 | __u8 arm_exp; | ||
137 | __u8 dsp_exp; | ||
138 | __u8 tc_exp; | ||
139 | __u8 dspmmu_exp; | ||
140 | |||
141 | per_exp = (newval >> CKCTL_PERDIV_OFFSET) & 3; | ||
142 | lcd_exp = (newval >> CKCTL_LCDDIV_OFFSET) & 3; | ||
143 | arm_exp = (newval >> CKCTL_ARMDIV_OFFSET) & 3; | ||
144 | dsp_exp = (newval >> CKCTL_DSPDIV_OFFSET) & 3; | ||
145 | tc_exp = (newval >> CKCTL_TCDIV_OFFSET) & 3; | ||
146 | dspmmu_exp = (newval >> CKCTL_DSPMMUDIV_OFFSET) & 3; | ||
147 | |||
148 | if (dspmmu_exp < dsp_exp) | ||
149 | dspmmu_exp = dsp_exp; | ||
150 | if (dspmmu_exp > dsp_exp+1) | ||
151 | dspmmu_exp = dsp_exp+1; | ||
152 | if (tc_exp < arm_exp) | ||
153 | tc_exp = arm_exp; | ||
154 | if (tc_exp < dspmmu_exp) | ||
155 | tc_exp = dspmmu_exp; | ||
156 | if (tc_exp > lcd_exp) | ||
157 | lcd_exp = tc_exp; | ||
158 | if (tc_exp > per_exp) | ||
159 | per_exp = tc_exp; | ||
160 | |||
161 | newval &= 0xf000; | ||
162 | newval |= per_exp << CKCTL_PERDIV_OFFSET; | ||
163 | newval |= lcd_exp << CKCTL_LCDDIV_OFFSET; | ||
164 | newval |= arm_exp << CKCTL_ARMDIV_OFFSET; | ||
165 | newval |= dsp_exp << CKCTL_DSPDIV_OFFSET; | ||
166 | newval |= tc_exp << CKCTL_TCDIV_OFFSET; | ||
167 | newval |= dspmmu_exp << CKCTL_DSPMMUDIV_OFFSET; | ||
168 | |||
169 | return newval; | ||
170 | } | ||
171 | |||
172 | static int calc_dsor_exp(struct clk *clk, unsigned long rate) | ||
173 | { | ||
174 | /* Note: If target frequency is too low, this function will return 4, | ||
175 | * which is invalid value. Caller must check for this value and act | ||
176 | * accordingly. | ||
177 | * | ||
178 | * Note: This function does not check for following limitations set | ||
179 | * by the hardware (all conditions must be true): | ||
180 | * DSPMMU_CK == DSP_CK or DSPMMU_CK == DSP_CK/2 | ||
181 | * ARM_CK >= TC_CK | ||
182 | * DSP_CK >= TC_CK | ||
183 | * DSPMMU_CK >= TC_CK | ||
184 | */ | ||
185 | unsigned long realrate; | ||
186 | struct clk * parent; | ||
187 | unsigned dsor_exp; | ||
188 | |||
189 | if (unlikely(!(clk->flags & RATE_CKCTL))) | ||
190 | return -EINVAL; | ||
191 | |||
192 | parent = clk->parent; | ||
193 | if (unlikely(parent == 0)) | ||
194 | return -EIO; | ||
195 | |||
196 | realrate = parent->rate; | ||
197 | for (dsor_exp=0; dsor_exp<4; dsor_exp++) { | ||
198 | if (realrate <= rate) | ||
199 | break; | ||
200 | |||
201 | realrate /= 2; | ||
202 | } | ||
203 | |||
204 | return dsor_exp; | ||
205 | } | ||
206 | |||
207 | static void omap1_ckctl_recalc(struct clk * clk) | ||
208 | { | ||
209 | int dsor; | ||
210 | |||
211 | /* Calculate divisor encoded as 2-bit exponent */ | ||
212 | dsor = 1 << (3 & (omap_readw(ARM_CKCTL) >> clk->rate_offset)); | ||
213 | |||
214 | if (unlikely(clk->rate == clk->parent->rate / dsor)) | ||
215 | return; /* No change, quick exit */ | ||
216 | clk->rate = clk->parent->rate / dsor; | ||
217 | |||
218 | if (unlikely(clk->flags & RATE_PROPAGATES)) | ||
219 | propagate_rate(clk); | ||
220 | } | ||
221 | |||
222 | static void omap1_ckctl_recalc_dsp_domain(struct clk * clk) | ||
223 | { | ||
224 | int dsor; | ||
225 | |||
226 | /* Calculate divisor encoded as 2-bit exponent | ||
227 | * | ||
228 | * The clock control bits are in DSP domain, | ||
229 | * so api_ck is needed for access. | ||
230 | * Note that DSP_CKCTL virt addr = phys addr, so | ||
231 | * we must use __raw_readw() instead of omap_readw(). | ||
232 | */ | ||
233 | omap1_clk_use(&api_ck.clk); | ||
234 | dsor = 1 << (3 & (__raw_readw(DSP_CKCTL) >> clk->rate_offset)); | ||
235 | omap1_clk_unuse(&api_ck.clk); | ||
236 | |||
237 | if (unlikely(clk->rate == clk->parent->rate / dsor)) | ||
238 | return; /* No change, quick exit */ | ||
239 | clk->rate = clk->parent->rate / dsor; | ||
240 | |||
241 | if (unlikely(clk->flags & RATE_PROPAGATES)) | ||
242 | propagate_rate(clk); | ||
243 | } | ||
244 | |||
245 | /* MPU virtual clock functions */ | ||
246 | static int omap1_select_table_rate(struct clk * clk, unsigned long rate) | ||
247 | { | ||
248 | /* Find the highest supported frequency <= rate and switch to it */ | ||
249 | struct mpu_rate * ptr; | ||
250 | |||
251 | if (clk != &virtual_ck_mpu) | ||
252 | return -EINVAL; | ||
253 | |||
254 | for (ptr = rate_table; ptr->rate; ptr++) { | ||
255 | if (ptr->xtal != ck_ref.rate) | ||
256 | continue; | ||
257 | |||
258 | /* DPLL1 cannot be reprogrammed without risking system crash */ | ||
259 | if (likely(ck_dpll1.rate!=0) && ptr->pll_rate != ck_dpll1.rate) | ||
260 | continue; | ||
261 | |||
262 | /* Can check only after xtal frequency check */ | ||
263 | if (ptr->rate <= rate) | ||
264 | break; | ||
265 | } | ||
266 | |||
267 | if (!ptr->rate) | ||
268 | return -EINVAL; | ||
269 | |||
270 | /* | ||
271 | * In most cases we should not need to reprogram DPLL. | ||
272 | * Reprogramming the DPLL is tricky, it must be done from SRAM. | ||
273 | */ | ||
274 | omap_sram_reprogram_clock(ptr->dpllctl_val, ptr->ckctl_val); | ||
275 | |||
276 | ck_dpll1.rate = ptr->pll_rate; | ||
277 | propagate_rate(&ck_dpll1); | ||
278 | return 0; | ||
279 | } | ||
280 | |||
281 | static int omap1_clk_set_rate_dsp_domain(struct clk *clk, unsigned long rate) | ||
282 | { | ||
283 | int ret = -EINVAL; | ||
284 | int dsor_exp; | ||
285 | __u16 regval; | ||
286 | |||
287 | if (clk->flags & RATE_CKCTL) { | ||
288 | dsor_exp = calc_dsor_exp(clk, rate); | ||
289 | if (dsor_exp > 3) | ||
290 | dsor_exp = -EINVAL; | ||
291 | if (dsor_exp < 0) | ||
292 | return dsor_exp; | ||
293 | |||
294 | regval = __raw_readw(DSP_CKCTL); | ||
295 | regval &= ~(3 << clk->rate_offset); | ||
296 | regval |= dsor_exp << clk->rate_offset; | ||
297 | __raw_writew(regval, DSP_CKCTL); | ||
298 | clk->rate = clk->parent->rate / (1 << dsor_exp); | ||
299 | ret = 0; | ||
300 | } | ||
301 | |||
302 | if (unlikely(ret == 0 && (clk->flags & RATE_PROPAGATES))) | ||
303 | propagate_rate(clk); | ||
304 | |||
305 | return ret; | ||
306 | } | ||
307 | |||
308 | static long omap1_round_to_table_rate(struct clk * clk, unsigned long rate) | ||
309 | { | ||
310 | /* Find the highest supported frequency <= rate */ | ||
311 | struct mpu_rate * ptr; | ||
312 | long highest_rate; | ||
313 | |||
314 | if (clk != &virtual_ck_mpu) | ||
315 | return -EINVAL; | ||
316 | |||
317 | highest_rate = -EINVAL; | ||
318 | |||
319 | for (ptr = rate_table; ptr->rate; ptr++) { | ||
320 | if (ptr->xtal != ck_ref.rate) | ||
321 | continue; | ||
322 | |||
323 | highest_rate = ptr->rate; | ||
324 | |||
325 | /* Can check only after xtal frequency check */ | ||
326 | if (ptr->rate <= rate) | ||
327 | break; | ||
328 | } | ||
329 | |||
330 | return highest_rate; | ||
331 | } | ||
332 | |||
333 | static unsigned calc_ext_dsor(unsigned long rate) | ||
334 | { | ||
335 | unsigned dsor; | ||
336 | |||
337 | /* MCLK and BCLK divisor selection is not linear: | ||
338 | * freq = 96MHz / dsor | ||
339 | * | ||
340 | * RATIO_SEL range: dsor <-> RATIO_SEL | ||
341 | * 0..6: (RATIO_SEL+2) <-> (dsor-2) | ||
342 | * 6..48: (8+(RATIO_SEL-6)*2) <-> ((dsor-8)/2+6) | ||
343 | * Minimum dsor is 2 and maximum is 96. Odd divisors starting from 9 | ||
344 | * can not be used. | ||
345 | */ | ||
346 | for (dsor = 2; dsor < 96; ++dsor) { | ||
347 | if ((dsor & 1) && dsor > 8) | ||
348 | continue; | ||
349 | if (rate >= 96000000 / dsor) | ||
350 | break; | ||
351 | } | ||
352 | return dsor; | ||
353 | } | ||
354 | |||
355 | /* Only needed on 1510 */ | ||
356 | static int omap1_set_uart_rate(struct clk * clk, unsigned long rate) | ||
357 | { | ||
358 | unsigned int val; | ||
359 | |||
360 | val = omap_readl(clk->enable_reg); | ||
361 | if (rate == 12000000) | ||
362 | val &= ~(1 << clk->enable_bit); | ||
363 | else if (rate == 48000000) | ||
364 | val |= (1 << clk->enable_bit); | ||
365 | else | ||
366 | return -EINVAL; | ||
367 | omap_writel(val, clk->enable_reg); | ||
368 | clk->rate = rate; | ||
369 | |||
370 | return 0; | ||
371 | } | ||
372 | |||
373 | /* External clock (MCLK & BCLK) functions */ | ||
374 | static int omap1_set_ext_clk_rate(struct clk * clk, unsigned long rate) | ||
375 | { | ||
376 | unsigned dsor; | ||
377 | __u16 ratio_bits; | ||
378 | |||
379 | dsor = calc_ext_dsor(rate); | ||
380 | clk->rate = 96000000 / dsor; | ||
381 | if (dsor > 8) | ||
382 | ratio_bits = ((dsor - 8) / 2 + 6) << 2; | ||
383 | else | ||
384 | ratio_bits = (dsor - 2) << 2; | ||
385 | |||
386 | ratio_bits |= omap_readw(clk->enable_reg) & ~0xfd; | ||
387 | omap_writew(ratio_bits, clk->enable_reg); | ||
388 | |||
389 | return 0; | ||
390 | } | ||
391 | |||
392 | static long omap1_round_ext_clk_rate(struct clk * clk, unsigned long rate) | ||
393 | { | ||
394 | return 96000000 / calc_ext_dsor(rate); | ||
395 | } | ||
396 | |||
397 | static void omap1_init_ext_clk(struct clk * clk) | ||
398 | { | ||
399 | unsigned dsor; | ||
400 | __u16 ratio_bits; | ||
401 | |||
402 | /* Determine current rate and ensure clock is based on 96MHz APLL */ | ||
403 | ratio_bits = omap_readw(clk->enable_reg) & ~1; | ||
404 | omap_writew(ratio_bits, clk->enable_reg); | ||
405 | |||
406 | ratio_bits = (ratio_bits & 0xfc) >> 2; | ||
407 | if (ratio_bits > 6) | ||
408 | dsor = (ratio_bits - 6) * 2 + 8; | ||
409 | else | ||
410 | dsor = ratio_bits + 2; | ||
411 | |||
412 | clk-> rate = 96000000 / dsor; | ||
413 | } | ||
414 | |||
415 | static int omap1_clk_use(struct clk *clk) | ||
416 | { | ||
417 | int ret = 0; | ||
418 | if (clk->usecount++ == 0) { | ||
419 | if (likely(clk->parent)) { | ||
420 | ret = omap1_clk_use(clk->parent); | ||
421 | |||
422 | if (unlikely(ret != 0)) { | ||
423 | clk->usecount--; | ||
424 | return ret; | ||
425 | } | ||
426 | |||
427 | if (clk->flags & CLOCK_NO_IDLE_PARENT) | ||
428 | if (!cpu_is_omap24xx()) | ||
429 | omap1_clk_deny_idle(clk->parent); | ||
430 | } | ||
431 | |||
432 | ret = clk->enable(clk); | ||
433 | |||
434 | if (unlikely(ret != 0) && clk->parent) { | ||
435 | omap1_clk_unuse(clk->parent); | ||
436 | clk->usecount--; | ||
437 | } | ||
438 | } | ||
439 | |||
440 | return ret; | ||
441 | } | ||
442 | |||
443 | static void omap1_clk_unuse(struct clk *clk) | ||
444 | { | ||
445 | if (clk->usecount > 0 && !(--clk->usecount)) { | ||
446 | clk->disable(clk); | ||
447 | if (likely(clk->parent)) { | ||
448 | omap1_clk_unuse(clk->parent); | ||
449 | if (clk->flags & CLOCK_NO_IDLE_PARENT) | ||
450 | if (!cpu_is_omap24xx()) | ||
451 | omap1_clk_allow_idle(clk->parent); | ||
452 | } | ||
453 | } | ||
454 | } | ||
455 | |||
456 | static int omap1_clk_enable(struct clk *clk) | ||
457 | { | ||
458 | __u16 regval16; | ||
459 | __u32 regval32; | ||
460 | |||
461 | if (clk->flags & ALWAYS_ENABLED) | ||
462 | return 0; | ||
463 | |||
464 | if (unlikely(clk->enable_reg == 0)) { | ||
465 | printk(KERN_ERR "clock.c: Enable for %s without enable code\n", | ||
466 | clk->name); | ||
467 | return 0; | ||
468 | } | ||
469 | |||
470 | if (clk->flags & ENABLE_REG_32BIT) { | ||
471 | if (clk->flags & VIRTUAL_IO_ADDRESS) { | ||
472 | regval32 = __raw_readl(clk->enable_reg); | ||
473 | regval32 |= (1 << clk->enable_bit); | ||
474 | __raw_writel(regval32, clk->enable_reg); | ||
475 | } else { | ||
476 | regval32 = omap_readl(clk->enable_reg); | ||
477 | regval32 |= (1 << clk->enable_bit); | ||
478 | omap_writel(regval32, clk->enable_reg); | ||
479 | } | ||
480 | } else { | ||
481 | if (clk->flags & VIRTUAL_IO_ADDRESS) { | ||
482 | regval16 = __raw_readw(clk->enable_reg); | ||
483 | regval16 |= (1 << clk->enable_bit); | ||
484 | __raw_writew(regval16, clk->enable_reg); | ||
485 | } else { | ||
486 | regval16 = omap_readw(clk->enable_reg); | ||
487 | regval16 |= (1 << clk->enable_bit); | ||
488 | omap_writew(regval16, clk->enable_reg); | ||
489 | } | ||
490 | } | ||
491 | |||
492 | return 0; | ||
493 | } | ||
494 | |||
495 | static void omap1_clk_disable(struct clk *clk) | ||
496 | { | ||
497 | __u16 regval16; | ||
498 | __u32 regval32; | ||
499 | |||
500 | if (clk->enable_reg == 0) | ||
501 | return; | ||
502 | |||
503 | if (clk->flags & ENABLE_REG_32BIT) { | ||
504 | if (clk->flags & VIRTUAL_IO_ADDRESS) { | ||
505 | regval32 = __raw_readl(clk->enable_reg); | ||
506 | regval32 &= ~(1 << clk->enable_bit); | ||
507 | __raw_writel(regval32, clk->enable_reg); | ||
508 | } else { | ||
509 | regval32 = omap_readl(clk->enable_reg); | ||
510 | regval32 &= ~(1 << clk->enable_bit); | ||
511 | omap_writel(regval32, clk->enable_reg); | ||
512 | } | ||
513 | } else { | ||
514 | if (clk->flags & VIRTUAL_IO_ADDRESS) { | ||
515 | regval16 = __raw_readw(clk->enable_reg); | ||
516 | regval16 &= ~(1 << clk->enable_bit); | ||
517 | __raw_writew(regval16, clk->enable_reg); | ||
518 | } else { | ||
519 | regval16 = omap_readw(clk->enable_reg); | ||
520 | regval16 &= ~(1 << clk->enable_bit); | ||
521 | omap_writew(regval16, clk->enable_reg); | ||
522 | } | ||
523 | } | ||
524 | } | ||
525 | |||
526 | static long omap1_clk_round_rate(struct clk *clk, unsigned long rate) | ||
527 | { | ||
528 | int dsor_exp; | ||
529 | |||
530 | if (clk->flags & RATE_FIXED) | ||
531 | return clk->rate; | ||
532 | |||
533 | if (clk->flags & RATE_CKCTL) { | ||
534 | dsor_exp = calc_dsor_exp(clk, rate); | ||
535 | if (dsor_exp < 0) | ||
536 | return dsor_exp; | ||
537 | if (dsor_exp > 3) | ||
538 | dsor_exp = 3; | ||
539 | return clk->parent->rate / (1 << dsor_exp); | ||
540 | } | ||
541 | |||
542 | if(clk->round_rate != 0) | ||
543 | return clk->round_rate(clk, rate); | ||
544 | |||
545 | return clk->rate; | ||
546 | } | ||
547 | |||
548 | static int omap1_clk_set_rate(struct clk *clk, unsigned long rate) | ||
549 | { | ||
550 | int ret = -EINVAL; | ||
551 | int dsor_exp; | ||
552 | __u16 regval; | ||
553 | |||
554 | if (clk->set_rate) | ||
555 | ret = clk->set_rate(clk, rate); | ||
556 | else if (clk->flags & RATE_CKCTL) { | ||
557 | dsor_exp = calc_dsor_exp(clk, rate); | ||
558 | if (dsor_exp > 3) | ||
559 | dsor_exp = -EINVAL; | ||
560 | if (dsor_exp < 0) | ||
561 | return dsor_exp; | ||
562 | |||
563 | regval = omap_readw(ARM_CKCTL); | ||
564 | regval &= ~(3 << clk->rate_offset); | ||
565 | regval |= dsor_exp << clk->rate_offset; | ||
566 | regval = verify_ckctl_value(regval); | ||
567 | omap_writew(regval, ARM_CKCTL); | ||
568 | clk->rate = clk->parent->rate / (1 << dsor_exp); | ||
569 | ret = 0; | ||
570 | } | ||
571 | |||
572 | if (unlikely(ret == 0 && (clk->flags & RATE_PROPAGATES))) | ||
573 | propagate_rate(clk); | ||
574 | |||
575 | return ret; | ||
576 | } | ||
577 | |||
578 | /*------------------------------------------------------------------------- | ||
579 | * Omap1 clock reset and init functions | ||
580 | *-------------------------------------------------------------------------*/ | ||
581 | |||
582 | #ifdef CONFIG_OMAP_RESET_CLOCKS | ||
583 | /* | ||
584 | * Resets some clocks that may be left on from bootloader, | ||
585 | * but leaves serial clocks on. See also omap_late_clk_reset(). | ||
586 | */ | ||
587 | static inline void omap1_early_clk_reset(void) | ||
588 | { | ||
589 | //omap_writel(0x3 << 29, MOD_CONF_CTRL_0); | ||
590 | } | ||
591 | |||
592 | static int __init omap1_late_clk_reset(void) | ||
593 | { | ||
594 | /* Turn off all unused clocks */ | ||
595 | struct clk *p; | ||
596 | __u32 regval32; | ||
597 | |||
598 | /* USB_REQ_EN will be disabled later if necessary (usb_dc_ck) */ | ||
599 | regval32 = omap_readw(SOFT_REQ_REG) & (1 << 4); | ||
600 | omap_writew(regval32, SOFT_REQ_REG); | ||
601 | omap_writew(0, SOFT_REQ_REG2); | ||
602 | |||
603 | list_for_each_entry(p, &clocks, node) { | ||
604 | if (p->usecount > 0 || (p->flags & ALWAYS_ENABLED) || | ||
605 | p->enable_reg == 0) | ||
606 | continue; | ||
607 | |||
608 | /* Clocks in the DSP domain need api_ck. Just assume bootloader | ||
609 | * has not enabled any DSP clocks */ | ||
610 | if ((u32)p->enable_reg == DSP_IDLECT2) { | ||
611 | printk(KERN_INFO "Skipping reset check for DSP domain " | ||
612 | "clock \"%s\"\n", p->name); | ||
613 | continue; | ||
614 | } | ||
615 | |||
616 | /* Is the clock already disabled? */ | ||
617 | if (p->flags & ENABLE_REG_32BIT) { | ||
618 | if (p->flags & VIRTUAL_IO_ADDRESS) | ||
619 | regval32 = __raw_readl(p->enable_reg); | ||
620 | else | ||
621 | regval32 = omap_readl(p->enable_reg); | ||
622 | } else { | ||
623 | if (p->flags & VIRTUAL_IO_ADDRESS) | ||
624 | regval32 = __raw_readw(p->enable_reg); | ||
625 | else | ||
626 | regval32 = omap_readw(p->enable_reg); | ||
627 | } | ||
628 | |||
629 | if ((regval32 & (1 << p->enable_bit)) == 0) | ||
630 | continue; | ||
631 | |||
632 | /* FIXME: This clock seems to be necessary but no-one | ||
633 | * has asked for its activation. */ | ||
634 | if (p == &tc2_ck // FIX: pm.c (SRAM), CCP, Camera | ||
635 | || p == &ck_dpll1out.clk // FIX: SoSSI, SSR | ||
636 | || p == &arm_gpio_ck // FIX: GPIO code for 1510 | ||
637 | ) { | ||
638 | printk(KERN_INFO "FIXME: Clock \"%s\" seems unused\n", | ||
639 | p->name); | ||
640 | continue; | ||
641 | } | ||
642 | |||
643 | printk(KERN_INFO "Disabling unused clock \"%s\"... ", p->name); | ||
644 | p->disable(p); | ||
645 | printk(" done\n"); | ||
646 | } | ||
647 | |||
648 | return 0; | ||
649 | } | ||
650 | late_initcall(omap1_late_clk_reset); | ||
651 | |||
652 | #else | ||
653 | #define omap1_early_clk_reset() {} | ||
654 | #endif | ||
655 | |||
656 | static struct clk_functions omap1_clk_functions = { | ||
657 | .clk_use = omap1_clk_use, | ||
658 | .clk_unuse = omap1_clk_unuse, | ||
659 | .clk_round_rate = omap1_clk_round_rate, | ||
660 | .clk_set_rate = omap1_clk_set_rate, | ||
661 | }; | ||
662 | |||
663 | int __init omap1_clk_init(void) | ||
664 | { | ||
665 | struct clk ** clkp; | ||
666 | const struct omap_clock_config *info; | ||
667 | int crystal_type = 0; /* Default 12 MHz */ | ||
668 | |||
669 | omap1_early_clk_reset(); | ||
670 | clk_init(&omap1_clk_functions); | ||
671 | |||
672 | /* By default all idlect1 clocks are allowed to idle */ | ||
673 | arm_idlect1_mask = ~0; | ||
674 | |||
675 | for (clkp = onchip_clks; clkp < onchip_clks+ARRAY_SIZE(onchip_clks); clkp++) { | ||
676 | if (((*clkp)->flags &CLOCK_IN_OMAP1510) && cpu_is_omap1510()) { | ||
677 | clk_register(*clkp); | ||
678 | continue; | ||
679 | } | ||
680 | |||
681 | if (((*clkp)->flags &CLOCK_IN_OMAP16XX) && cpu_is_omap16xx()) { | ||
682 | clk_register(*clkp); | ||
683 | continue; | ||
684 | } | ||
685 | |||
686 | if (((*clkp)->flags &CLOCK_IN_OMAP730) && cpu_is_omap730()) { | ||
687 | clk_register(*clkp); | ||
688 | continue; | ||
689 | } | ||
690 | } | ||
691 | |||
692 | info = omap_get_config(OMAP_TAG_CLOCK, struct omap_clock_config); | ||
693 | if (info != NULL) { | ||
694 | if (!cpu_is_omap1510()) | ||
695 | crystal_type = info->system_clock_type; | ||
696 | } | ||
697 | |||
698 | #if defined(CONFIG_ARCH_OMAP730) | ||
699 | ck_ref.rate = 13000000; | ||
700 | #elif defined(CONFIG_ARCH_OMAP16XX) | ||
701 | if (crystal_type == 2) | ||
702 | ck_ref.rate = 19200000; | ||
703 | #endif | ||
704 | |||
705 | printk("Clocks: ARM_SYSST: 0x%04x DPLL_CTL: 0x%04x ARM_CKCTL: 0x%04x\n", | ||
706 | omap_readw(ARM_SYSST), omap_readw(DPLL_CTL), | ||
707 | omap_readw(ARM_CKCTL)); | ||
708 | |||
709 | /* We want to be in syncronous scalable mode */ | ||
710 | omap_writew(0x1000, ARM_SYSST); | ||
711 | |||
712 | #ifdef CONFIG_OMAP_CLOCKS_SET_BY_BOOTLOADER | ||
713 | /* Use values set by bootloader. Determine PLL rate and recalculate | ||
714 | * dependent clocks as if kernel had changed PLL or divisors. | ||
715 | */ | ||
716 | { | ||
717 | unsigned pll_ctl_val = omap_readw(DPLL_CTL); | ||
718 | |||
719 | ck_dpll1.rate = ck_ref.rate; /* Base xtal rate */ | ||
720 | if (pll_ctl_val & 0x10) { | ||
721 | /* PLL enabled, apply multiplier and divisor */ | ||
722 | if (pll_ctl_val & 0xf80) | ||
723 | ck_dpll1.rate *= (pll_ctl_val & 0xf80) >> 7; | ||
724 | ck_dpll1.rate /= ((pll_ctl_val & 0x60) >> 5) + 1; | ||
725 | } else { | ||
726 | /* PLL disabled, apply bypass divisor */ | ||
727 | switch (pll_ctl_val & 0xc) { | ||
728 | case 0: | ||
729 | break; | ||
730 | case 0x4: | ||
731 | ck_dpll1.rate /= 2; | ||
732 | break; | ||
733 | default: | ||
734 | ck_dpll1.rate /= 4; | ||
735 | break; | ||
736 | } | ||
737 | } | ||
738 | } | ||
739 | propagate_rate(&ck_dpll1); | ||
740 | #else | ||
741 | /* Find the highest supported frequency and enable it */ | ||
742 | if (omap1_select_table_rate(&virtual_ck_mpu, ~0)) { | ||
743 | printk(KERN_ERR "System frequencies not set. Check your config.\n"); | ||
744 | /* Guess sane values (60MHz) */ | ||
745 | omap_writew(0x2290, DPLL_CTL); | ||
746 | omap_writew(0x1005, ARM_CKCTL); | ||
747 | ck_dpll1.rate = 60000000; | ||
748 | propagate_rate(&ck_dpll1); | ||
749 | } | ||
750 | #endif | ||
751 | /* Cache rates for clocks connected to ck_ref (not dpll1) */ | ||
752 | propagate_rate(&ck_ref); | ||
753 | printk(KERN_INFO "Clocking rate (xtal/DPLL1/MPU): " | ||
754 | "%ld.%01ld/%ld.%01ld/%ld.%01ld MHz\n", | ||
755 | ck_ref.rate / 1000000, (ck_ref.rate / 100000) % 10, | ||
756 | ck_dpll1.rate / 1000000, (ck_dpll1.rate / 100000) % 10, | ||
757 | arm_ck.rate / 1000000, (arm_ck.rate / 100000) % 10); | ||
758 | |||
759 | #ifdef CONFIG_MACH_OMAP_PERSEUS2 | ||
760 | /* Select slicer output as OMAP input clock */ | ||
761 | omap_writew(omap_readw(OMAP730_PCC_UPLD_CTRL) & ~0x1, OMAP730_PCC_UPLD_CTRL); | ||
762 | #endif | ||
763 | |||
764 | /* Turn off DSP and ARM_TIMXO. Make sure ARM_INTHCK is not divided */ | ||
765 | omap_writew(omap_readw(ARM_CKCTL) & 0x0fff, ARM_CKCTL); | ||
766 | |||
767 | /* Put DSP/MPUI into reset until needed */ | ||
768 | omap_writew(0, ARM_RSTCT1); | ||
769 | omap_writew(1, ARM_RSTCT2); | ||
770 | omap_writew(0x400, ARM_IDLECT1); | ||
771 | |||
772 | /* | ||
773 | * According to OMAP5910 Erratum SYS_DMA_1, bit DMACK_REQ (bit 8) | ||
774 | * of the ARM_IDLECT2 register must be set to zero. The power-on | ||
775 | * default value of this bit is one. | ||
776 | */ | ||
777 | omap_writew(0x0000, ARM_IDLECT2); /* Turn LCD clock off also */ | ||
778 | |||
779 | /* | ||
780 | * Only enable those clocks we will need, let the drivers | ||
781 | * enable other clocks as necessary | ||
782 | */ | ||
783 | clk_use(&armper_ck.clk); | ||
784 | clk_use(&armxor_ck.clk); | ||
785 | clk_use(&armtim_ck.clk); /* This should be done by timer code */ | ||
786 | |||
787 | if (cpu_is_omap1510()) | ||
788 | clk_enable(&arm_gpio_ck); | ||
789 | |||
790 | return 0; | ||
791 | } | ||
792 | |||
diff --git a/arch/arm/mach-omap1/clock.h b/arch/arm/mach-omap1/clock.h new file mode 100644 index 000000000000..f3bdfb50e01a --- /dev/null +++ b/arch/arm/mach-omap1/clock.h | |||
@@ -0,0 +1,768 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-omap1/clock.h | ||
3 | * | ||
4 | * Copyright (C) 2004 - 2005 Nokia corporation | ||
5 | * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com> | ||
6 | * Based on clocks.h by Tony Lindgren, Gordon McNutt and RidgeRun, Inc | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #ifndef __ARCH_ARM_MACH_OMAP1_CLOCK_H | ||
14 | #define __ARCH_ARM_MACH_OMAP1_CLOCK_H | ||
15 | |||
16 | static int omap1_clk_enable(struct clk * clk); | ||
17 | static void omap1_clk_disable(struct clk * clk); | ||
18 | static void omap1_ckctl_recalc(struct clk * clk); | ||
19 | static void omap1_watchdog_recalc(struct clk * clk); | ||
20 | static void omap1_ckctl_recalc_dsp_domain(struct clk * clk); | ||
21 | static int omap1_clk_enable_dsp_domain(struct clk * clk); | ||
22 | static int omap1_clk_set_rate_dsp_domain(struct clk * clk, unsigned long rate); | ||
23 | static void omap1_clk_disable_dsp_domain(struct clk * clk); | ||
24 | static int omap1_set_uart_rate(struct clk * clk, unsigned long rate); | ||
25 | static void omap1_uart_recalc(struct clk * clk); | ||
26 | static int omap1_clk_enable_uart_functional(struct clk * clk); | ||
27 | static void omap1_clk_disable_uart_functional(struct clk * clk); | ||
28 | static int omap1_set_ext_clk_rate(struct clk * clk, unsigned long rate); | ||
29 | static long omap1_round_ext_clk_rate(struct clk * clk, unsigned long rate); | ||
30 | static void omap1_init_ext_clk(struct clk * clk); | ||
31 | static int omap1_select_table_rate(struct clk * clk, unsigned long rate); | ||
32 | static long omap1_round_to_table_rate(struct clk * clk, unsigned long rate); | ||
33 | static int omap1_clk_use(struct clk *clk); | ||
34 | static void omap1_clk_unuse(struct clk *clk); | ||
35 | |||
36 | struct mpu_rate { | ||
37 | unsigned long rate; | ||
38 | unsigned long xtal; | ||
39 | unsigned long pll_rate; | ||
40 | __u16 ckctl_val; | ||
41 | __u16 dpllctl_val; | ||
42 | }; | ||
43 | |||
44 | struct uart_clk { | ||
45 | struct clk clk; | ||
46 | unsigned long sysc_addr; | ||
47 | }; | ||
48 | |||
49 | /* Provide a method for preventing idling some ARM IDLECT clocks */ | ||
50 | struct arm_idlect1_clk { | ||
51 | struct clk clk; | ||
52 | unsigned long no_idle_count; | ||
53 | __u8 idlect_shift; | ||
54 | }; | ||
55 | |||
56 | /* ARM_CKCTL bit shifts */ | ||
57 | #define CKCTL_PERDIV_OFFSET 0 | ||
58 | #define CKCTL_LCDDIV_OFFSET 2 | ||
59 | #define CKCTL_ARMDIV_OFFSET 4 | ||
60 | #define CKCTL_DSPDIV_OFFSET 6 | ||
61 | #define CKCTL_TCDIV_OFFSET 8 | ||
62 | #define CKCTL_DSPMMUDIV_OFFSET 10 | ||
63 | /*#define ARM_TIMXO 12*/ | ||
64 | #define EN_DSPCK 13 | ||
65 | /*#define ARM_INTHCK_SEL 14*/ /* Divide-by-2 for mpu inth_ck */ | ||
66 | /* DSP_CKCTL bit shifts */ | ||
67 | #define CKCTL_DSPPERDIV_OFFSET 0 | ||
68 | |||
69 | /* ARM_IDLECT2 bit shifts */ | ||
70 | #define EN_WDTCK 0 | ||
71 | #define EN_XORPCK 1 | ||
72 | #define EN_PERCK 2 | ||
73 | #define EN_LCDCK 3 | ||
74 | #define EN_LBCK 4 /* Not on 1610/1710 */ | ||
75 | /*#define EN_HSABCK 5*/ | ||
76 | #define EN_APICK 6 | ||
77 | #define EN_TIMCK 7 | ||
78 | #define DMACK_REQ 8 | ||
79 | #define EN_GPIOCK 9 /* Not on 1610/1710 */ | ||
80 | /*#define EN_LBFREECK 10*/ | ||
81 | #define EN_CKOUT_ARM 11 | ||
82 | |||
83 | /* ARM_IDLECT3 bit shifts */ | ||
84 | #define EN_OCPI_CK 0 | ||
85 | #define EN_TC1_CK 2 | ||
86 | #define EN_TC2_CK 4 | ||
87 | |||
88 | /* DSP_IDLECT2 bit shifts (0,1,2 are same as for ARM_IDLECT2) */ | ||
89 | #define EN_DSPTIMCK 5 | ||
90 | |||
91 | /* Various register defines for clock controls scattered around OMAP chip */ | ||
92 | #define USB_MCLK_EN_BIT 4 /* In ULPD_CLKC_CTRL */ | ||
93 | #define USB_HOST_HHC_UHOST_EN 9 /* In MOD_CONF_CTRL_0 */ | ||
94 | #define SWD_ULPD_PLL_CLK_REQ 1 /* In SWD_CLK_DIV_CTRL_SEL */ | ||
95 | #define COM_ULPD_PLL_CLK_REQ 1 /* In COM_CLK_DIV_CTRL_SEL */ | ||
96 | #define SWD_CLK_DIV_CTRL_SEL 0xfffe0874 | ||
97 | #define COM_CLK_DIV_CTRL_SEL 0xfffe0878 | ||
98 | #define SOFT_REQ_REG 0xfffe0834 | ||
99 | #define SOFT_REQ_REG2 0xfffe0880 | ||
100 | |||
101 | /*------------------------------------------------------------------------- | ||
102 | * Omap1 MPU rate table | ||
103 | *-------------------------------------------------------------------------*/ | ||
104 | static struct mpu_rate rate_table[] = { | ||
105 | /* MPU MHz, xtal MHz, dpll1 MHz, CKCTL, DPLL_CTL | ||
106 | * NOTE: Comment order here is different from bits in CKCTL value: | ||
107 | * armdiv, dspdiv, dspmmu, tcdiv, perdiv, lcddiv | ||
108 | */ | ||
109 | #if defined(CONFIG_OMAP_ARM_216MHZ) | ||
110 | { 216000000, 12000000, 216000000, 0x050d, 0x2910 }, /* 1/1/2/2/2/8 */ | ||
111 | #endif | ||
112 | #if defined(CONFIG_OMAP_ARM_195MHZ) | ||
113 | { 195000000, 13000000, 195000000, 0x050e, 0x2790 }, /* 1/1/2/2/4/8 */ | ||
114 | #endif | ||
115 | #if defined(CONFIG_OMAP_ARM_192MHZ) | ||
116 | { 192000000, 19200000, 192000000, 0x050f, 0x2510 }, /* 1/1/2/2/8/8 */ | ||
117 | { 192000000, 12000000, 192000000, 0x050f, 0x2810 }, /* 1/1/2/2/8/8 */ | ||
118 | { 96000000, 12000000, 192000000, 0x055f, 0x2810 }, /* 2/2/2/2/8/8 */ | ||
119 | { 48000000, 12000000, 192000000, 0x0baf, 0x2810 }, /* 4/4/4/8/8/8 */ | ||
120 | { 24000000, 12000000, 192000000, 0x0fff, 0x2810 }, /* 8/8/8/8/8/8 */ | ||
121 | #endif | ||
122 | #if defined(CONFIG_OMAP_ARM_182MHZ) | ||
123 | { 182000000, 13000000, 182000000, 0x050e, 0x2710 }, /* 1/1/2/2/4/8 */ | ||
124 | #endif | ||
125 | #if defined(CONFIG_OMAP_ARM_168MHZ) | ||
126 | { 168000000, 12000000, 168000000, 0x010f, 0x2710 }, /* 1/1/1/2/8/8 */ | ||
127 | #endif | ||
128 | #if defined(CONFIG_OMAP_ARM_150MHZ) | ||
129 | { 150000000, 12000000, 150000000, 0x010a, 0x2cb0 }, /* 1/1/1/2/4/4 */ | ||
130 | #endif | ||
131 | #if defined(CONFIG_OMAP_ARM_120MHZ) | ||
132 | { 120000000, 12000000, 120000000, 0x010a, 0x2510 }, /* 1/1/1/2/4/4 */ | ||
133 | #endif | ||
134 | #if defined(CONFIG_OMAP_ARM_96MHZ) | ||
135 | { 96000000, 12000000, 96000000, 0x0005, 0x2410 }, /* 1/1/1/1/2/2 */ | ||
136 | #endif | ||
137 | #if defined(CONFIG_OMAP_ARM_60MHZ) | ||
138 | { 60000000, 12000000, 60000000, 0x0005, 0x2290 }, /* 1/1/1/1/2/2 */ | ||
139 | #endif | ||
140 | #if defined(CONFIG_OMAP_ARM_30MHZ) | ||
141 | { 30000000, 12000000, 60000000, 0x0555, 0x2290 }, /* 2/2/2/2/2/2 */ | ||
142 | #endif | ||
143 | { 0, 0, 0, 0, 0 }, | ||
144 | }; | ||
145 | |||
146 | /*------------------------------------------------------------------------- | ||
147 | * Omap1 clocks | ||
148 | *-------------------------------------------------------------------------*/ | ||
149 | |||
150 | static struct clk ck_ref = { | ||
151 | .name = "ck_ref", | ||
152 | .rate = 12000000, | ||
153 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | ||
154 | ALWAYS_ENABLED, | ||
155 | .enable = &omap1_clk_enable, | ||
156 | .disable = &omap1_clk_disable, | ||
157 | }; | ||
158 | |||
159 | static struct clk ck_dpll1 = { | ||
160 | .name = "ck_dpll1", | ||
161 | .parent = &ck_ref, | ||
162 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | ||
163 | RATE_PROPAGATES | ALWAYS_ENABLED, | ||
164 | .enable = &omap1_clk_enable, | ||
165 | .disable = &omap1_clk_disable, | ||
166 | }; | ||
167 | |||
168 | static struct arm_idlect1_clk ck_dpll1out = { | ||
169 | .clk = { | ||
170 | .name = "ck_dpll1out", | ||
171 | .parent = &ck_dpll1, | ||
172 | .flags = CLOCK_IN_OMAP16XX | CLOCK_IDLE_CONTROL, | ||
173 | .enable_reg = (void __iomem *)ARM_IDLECT2, | ||
174 | .enable_bit = EN_CKOUT_ARM, | ||
175 | .recalc = &followparent_recalc, | ||
176 | .enable = &omap1_clk_enable, | ||
177 | .disable = &omap1_clk_disable, | ||
178 | }, | ||
179 | .idlect_shift = 12, | ||
180 | }; | ||
181 | |||
182 | static struct clk arm_ck = { | ||
183 | .name = "arm_ck", | ||
184 | .parent = &ck_dpll1, | ||
185 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | ||
186 | RATE_CKCTL | RATE_PROPAGATES | ALWAYS_ENABLED, | ||
187 | .rate_offset = CKCTL_ARMDIV_OFFSET, | ||
188 | .recalc = &omap1_ckctl_recalc, | ||
189 | .enable = &omap1_clk_enable, | ||
190 | .disable = &omap1_clk_disable, | ||
191 | }; | ||
192 | |||
193 | static struct arm_idlect1_clk armper_ck = { | ||
194 | .clk = { | ||
195 | .name = "armper_ck", | ||
196 | .parent = &ck_dpll1, | ||
197 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | ||
198 | RATE_CKCTL | CLOCK_IDLE_CONTROL, | ||
199 | .enable_reg = (void __iomem *)ARM_IDLECT2, | ||
200 | .enable_bit = EN_PERCK, | ||
201 | .rate_offset = CKCTL_PERDIV_OFFSET, | ||
202 | .recalc = &omap1_ckctl_recalc, | ||
203 | .enable = &omap1_clk_enable, | ||
204 | .disable = &omap1_clk_disable, | ||
205 | }, | ||
206 | .idlect_shift = 2, | ||
207 | }; | ||
208 | |||
209 | static struct clk arm_gpio_ck = { | ||
210 | .name = "arm_gpio_ck", | ||
211 | .parent = &ck_dpll1, | ||
212 | .flags = CLOCK_IN_OMAP1510, | ||
213 | .enable_reg = (void __iomem *)ARM_IDLECT2, | ||
214 | .enable_bit = EN_GPIOCK, | ||
215 | .recalc = &followparent_recalc, | ||
216 | .enable = &omap1_clk_enable, | ||
217 | .disable = &omap1_clk_disable, | ||
218 | }; | ||
219 | |||
220 | static struct arm_idlect1_clk armxor_ck = { | ||
221 | .clk = { | ||
222 | .name = "armxor_ck", | ||
223 | .parent = &ck_ref, | ||
224 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | ||
225 | CLOCK_IDLE_CONTROL, | ||
226 | .enable_reg = (void __iomem *)ARM_IDLECT2, | ||
227 | .enable_bit = EN_XORPCK, | ||
228 | .recalc = &followparent_recalc, | ||
229 | .enable = &omap1_clk_enable, | ||
230 | .disable = &omap1_clk_disable, | ||
231 | }, | ||
232 | .idlect_shift = 1, | ||
233 | }; | ||
234 | |||
235 | static struct arm_idlect1_clk armtim_ck = { | ||
236 | .clk = { | ||
237 | .name = "armtim_ck", | ||
238 | .parent = &ck_ref, | ||
239 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | ||
240 | CLOCK_IDLE_CONTROL, | ||
241 | .enable_reg = (void __iomem *)ARM_IDLECT2, | ||
242 | .enable_bit = EN_TIMCK, | ||
243 | .recalc = &followparent_recalc, | ||
244 | .enable = &omap1_clk_enable, | ||
245 | .disable = &omap1_clk_disable, | ||
246 | }, | ||
247 | .idlect_shift = 9, | ||
248 | }; | ||
249 | |||
250 | static struct arm_idlect1_clk armwdt_ck = { | ||
251 | .clk = { | ||
252 | .name = "armwdt_ck", | ||
253 | .parent = &ck_ref, | ||
254 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | ||
255 | CLOCK_IDLE_CONTROL, | ||
256 | .enable_reg = (void __iomem *)ARM_IDLECT2, | ||
257 | .enable_bit = EN_WDTCK, | ||
258 | .recalc = &omap1_watchdog_recalc, | ||
259 | .enable = &omap1_clk_enable, | ||
260 | .disable = &omap1_clk_disable, | ||
261 | }, | ||
262 | .idlect_shift = 0, | ||
263 | }; | ||
264 | |||
265 | static struct clk arminth_ck16xx = { | ||
266 | .name = "arminth_ck", | ||
267 | .parent = &arm_ck, | ||
268 | .flags = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED, | ||
269 | .recalc = &followparent_recalc, | ||
270 | /* Note: On 16xx the frequency can be divided by 2 by programming | ||
271 | * ARM_CKCTL:ARM_INTHCK_SEL(14) to 1 | ||
272 | * | ||
273 | * 1510 version is in TC clocks. | ||
274 | */ | ||
275 | .enable = &omap1_clk_enable, | ||
276 | .disable = &omap1_clk_disable, | ||
277 | }; | ||
278 | |||
279 | static struct clk dsp_ck = { | ||
280 | .name = "dsp_ck", | ||
281 | .parent = &ck_dpll1, | ||
282 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | ||
283 | RATE_CKCTL, | ||
284 | .enable_reg = (void __iomem *)ARM_CKCTL, | ||
285 | .enable_bit = EN_DSPCK, | ||
286 | .rate_offset = CKCTL_DSPDIV_OFFSET, | ||
287 | .recalc = &omap1_ckctl_recalc, | ||
288 | .enable = &omap1_clk_enable, | ||
289 | .disable = &omap1_clk_disable, | ||
290 | }; | ||
291 | |||
292 | static struct clk dspmmu_ck = { | ||
293 | .name = "dspmmu_ck", | ||
294 | .parent = &ck_dpll1, | ||
295 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | ||
296 | RATE_CKCTL | ALWAYS_ENABLED, | ||
297 | .rate_offset = CKCTL_DSPMMUDIV_OFFSET, | ||
298 | .recalc = &omap1_ckctl_recalc, | ||
299 | .enable = &omap1_clk_enable, | ||
300 | .disable = &omap1_clk_disable, | ||
301 | }; | ||
302 | |||
303 | static struct clk dspper_ck = { | ||
304 | .name = "dspper_ck", | ||
305 | .parent = &ck_dpll1, | ||
306 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | ||
307 | RATE_CKCTL | VIRTUAL_IO_ADDRESS, | ||
308 | .enable_reg = (void __iomem *)DSP_IDLECT2, | ||
309 | .enable_bit = EN_PERCK, | ||
310 | .rate_offset = CKCTL_PERDIV_OFFSET, | ||
311 | .recalc = &omap1_ckctl_recalc_dsp_domain, | ||
312 | .set_rate = &omap1_clk_set_rate_dsp_domain, | ||
313 | .enable = &omap1_clk_enable_dsp_domain, | ||
314 | .disable = &omap1_clk_disable_dsp_domain, | ||
315 | }; | ||
316 | |||
317 | static struct clk dspxor_ck = { | ||
318 | .name = "dspxor_ck", | ||
319 | .parent = &ck_ref, | ||
320 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | ||
321 | VIRTUAL_IO_ADDRESS, | ||
322 | .enable_reg = (void __iomem *)DSP_IDLECT2, | ||
323 | .enable_bit = EN_XORPCK, | ||
324 | .recalc = &followparent_recalc, | ||
325 | .enable = &omap1_clk_enable_dsp_domain, | ||
326 | .disable = &omap1_clk_disable_dsp_domain, | ||
327 | }; | ||
328 | |||
329 | static struct clk dsptim_ck = { | ||
330 | .name = "dsptim_ck", | ||
331 | .parent = &ck_ref, | ||
332 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | ||
333 | VIRTUAL_IO_ADDRESS, | ||
334 | .enable_reg = (void __iomem *)DSP_IDLECT2, | ||
335 | .enable_bit = EN_DSPTIMCK, | ||
336 | .recalc = &followparent_recalc, | ||
337 | .enable = &omap1_clk_enable_dsp_domain, | ||
338 | .disable = &omap1_clk_disable_dsp_domain, | ||
339 | }; | ||
340 | |||
341 | /* Tie ARM_IDLECT1:IDLIF_ARM to this logical clock structure */ | ||
342 | static struct arm_idlect1_clk tc_ck = { | ||
343 | .clk = { | ||
344 | .name = "tc_ck", | ||
345 | .parent = &ck_dpll1, | ||
346 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | ||
347 | CLOCK_IN_OMAP730 | RATE_CKCTL | | ||
348 | RATE_PROPAGATES | ALWAYS_ENABLED | | ||
349 | CLOCK_IDLE_CONTROL, | ||
350 | .rate_offset = CKCTL_TCDIV_OFFSET, | ||
351 | .recalc = &omap1_ckctl_recalc, | ||
352 | .enable = &omap1_clk_enable, | ||
353 | .disable = &omap1_clk_disable, | ||
354 | }, | ||
355 | .idlect_shift = 6, | ||
356 | }; | ||
357 | |||
358 | static struct clk arminth_ck1510 = { | ||
359 | .name = "arminth_ck", | ||
360 | .parent = &tc_ck.clk, | ||
361 | .flags = CLOCK_IN_OMAP1510 | ALWAYS_ENABLED, | ||
362 | .recalc = &followparent_recalc, | ||
363 | /* Note: On 1510 the frequency follows TC_CK | ||
364 | * | ||
365 | * 16xx version is in MPU clocks. | ||
366 | */ | ||
367 | .enable = &omap1_clk_enable, | ||
368 | .disable = &omap1_clk_disable, | ||
369 | }; | ||
370 | |||
371 | static struct clk tipb_ck = { | ||
372 | /* No-idle controlled by "tc_ck" */ | ||
373 | .name = "tibp_ck", | ||
374 | .parent = &tc_ck.clk, | ||
375 | .flags = CLOCK_IN_OMAP1510 | ALWAYS_ENABLED, | ||
376 | .recalc = &followparent_recalc, | ||
377 | .enable = &omap1_clk_enable, | ||
378 | .disable = &omap1_clk_disable, | ||
379 | }; | ||
380 | |||
381 | static struct clk l3_ocpi_ck = { | ||
382 | /* No-idle controlled by "tc_ck" */ | ||
383 | .name = "l3_ocpi_ck", | ||
384 | .parent = &tc_ck.clk, | ||
385 | .flags = CLOCK_IN_OMAP16XX, | ||
386 | .enable_reg = (void __iomem *)ARM_IDLECT3, | ||
387 | .enable_bit = EN_OCPI_CK, | ||
388 | .recalc = &followparent_recalc, | ||
389 | .enable = &omap1_clk_enable, | ||
390 | .disable = &omap1_clk_disable, | ||
391 | }; | ||
392 | |||
393 | static struct clk tc1_ck = { | ||
394 | .name = "tc1_ck", | ||
395 | .parent = &tc_ck.clk, | ||
396 | .flags = CLOCK_IN_OMAP16XX, | ||
397 | .enable_reg = (void __iomem *)ARM_IDLECT3, | ||
398 | .enable_bit = EN_TC1_CK, | ||
399 | .recalc = &followparent_recalc, | ||
400 | .enable = &omap1_clk_enable, | ||
401 | .disable = &omap1_clk_disable, | ||
402 | }; | ||
403 | |||
404 | static struct clk tc2_ck = { | ||
405 | .name = "tc2_ck", | ||
406 | .parent = &tc_ck.clk, | ||
407 | .flags = CLOCK_IN_OMAP16XX, | ||
408 | .enable_reg = (void __iomem *)ARM_IDLECT3, | ||
409 | .enable_bit = EN_TC2_CK, | ||
410 | .recalc = &followparent_recalc, | ||
411 | .enable = &omap1_clk_enable, | ||
412 | .disable = &omap1_clk_disable, | ||
413 | }; | ||
414 | |||
415 | static struct clk dma_ck = { | ||
416 | /* No-idle controlled by "tc_ck" */ | ||
417 | .name = "dma_ck", | ||
418 | .parent = &tc_ck.clk, | ||
419 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | ||
420 | ALWAYS_ENABLED, | ||
421 | .recalc = &followparent_recalc, | ||
422 | .enable = &omap1_clk_enable, | ||
423 | .disable = &omap1_clk_disable, | ||
424 | }; | ||
425 | |||
426 | static struct clk dma_lcdfree_ck = { | ||
427 | .name = "dma_lcdfree_ck", | ||
428 | .parent = &tc_ck.clk, | ||
429 | .flags = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED, | ||
430 | .recalc = &followparent_recalc, | ||
431 | .enable = &omap1_clk_enable, | ||
432 | .disable = &omap1_clk_disable, | ||
433 | }; | ||
434 | |||
435 | static struct arm_idlect1_clk api_ck = { | ||
436 | .clk = { | ||
437 | .name = "api_ck", | ||
438 | .parent = &tc_ck.clk, | ||
439 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | ||
440 | CLOCK_IDLE_CONTROL, | ||
441 | .enable_reg = (void __iomem *)ARM_IDLECT2, | ||
442 | .enable_bit = EN_APICK, | ||
443 | .recalc = &followparent_recalc, | ||
444 | .enable = &omap1_clk_enable, | ||
445 | .disable = &omap1_clk_disable, | ||
446 | }, | ||
447 | .idlect_shift = 8, | ||
448 | }; | ||
449 | |||
450 | static struct arm_idlect1_clk lb_ck = { | ||
451 | .clk = { | ||
452 | .name = "lb_ck", | ||
453 | .parent = &tc_ck.clk, | ||
454 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IDLE_CONTROL, | ||
455 | .enable_reg = (void __iomem *)ARM_IDLECT2, | ||
456 | .enable_bit = EN_LBCK, | ||
457 | .recalc = &followparent_recalc, | ||
458 | .enable = &omap1_clk_enable, | ||
459 | .disable = &omap1_clk_disable, | ||
460 | }, | ||
461 | .idlect_shift = 4, | ||
462 | }; | ||
463 | |||
464 | static struct clk rhea1_ck = { | ||
465 | .name = "rhea1_ck", | ||
466 | .parent = &tc_ck.clk, | ||
467 | .flags = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED, | ||
468 | .recalc = &followparent_recalc, | ||
469 | .enable = &omap1_clk_enable, | ||
470 | .disable = &omap1_clk_disable, | ||
471 | }; | ||
472 | |||
473 | static struct clk rhea2_ck = { | ||
474 | .name = "rhea2_ck", | ||
475 | .parent = &tc_ck.clk, | ||
476 | .flags = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED, | ||
477 | .recalc = &followparent_recalc, | ||
478 | .enable = &omap1_clk_enable, | ||
479 | .disable = &omap1_clk_disable, | ||
480 | }; | ||
481 | |||
482 | static struct clk lcd_ck_16xx = { | ||
483 | .name = "lcd_ck", | ||
484 | .parent = &ck_dpll1, | ||
485 | .flags = CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP730 | RATE_CKCTL, | ||
486 | .enable_reg = (void __iomem *)ARM_IDLECT2, | ||
487 | .enable_bit = EN_LCDCK, | ||
488 | .rate_offset = CKCTL_LCDDIV_OFFSET, | ||
489 | .recalc = &omap1_ckctl_recalc, | ||
490 | .enable = &omap1_clk_enable, | ||
491 | .disable = &omap1_clk_disable, | ||
492 | }; | ||
493 | |||
494 | static struct arm_idlect1_clk lcd_ck_1510 = { | ||
495 | .clk = { | ||
496 | .name = "lcd_ck", | ||
497 | .parent = &ck_dpll1, | ||
498 | .flags = CLOCK_IN_OMAP1510 | RATE_CKCTL | | ||
499 | CLOCK_IDLE_CONTROL, | ||
500 | .enable_reg = (void __iomem *)ARM_IDLECT2, | ||
501 | .enable_bit = EN_LCDCK, | ||
502 | .rate_offset = CKCTL_LCDDIV_OFFSET, | ||
503 | .recalc = &omap1_ckctl_recalc, | ||
504 | .enable = &omap1_clk_enable, | ||
505 | .disable = &omap1_clk_disable, | ||
506 | }, | ||
507 | .idlect_shift = 3, | ||
508 | }; | ||
509 | |||
510 | static struct clk uart1_1510 = { | ||
511 | .name = "uart1_ck", | ||
512 | /* Direct from ULPD, no real parent */ | ||
513 | .parent = &armper_ck.clk, | ||
514 | .rate = 12000000, | ||
515 | .flags = CLOCK_IN_OMAP1510 | ENABLE_REG_32BIT | | ||
516 | ALWAYS_ENABLED | CLOCK_NO_IDLE_PARENT, | ||
517 | .enable_reg = (void __iomem *)MOD_CONF_CTRL_0, | ||
518 | .enable_bit = 29, /* Chooses between 12MHz and 48MHz */ | ||
519 | .set_rate = &omap1_set_uart_rate, | ||
520 | .recalc = &omap1_uart_recalc, | ||
521 | .enable = &omap1_clk_enable, | ||
522 | .disable = &omap1_clk_disable, | ||
523 | }; | ||
524 | |||
525 | static struct uart_clk uart1_16xx = { | ||
526 | .clk = { | ||
527 | .name = "uart1_ck", | ||
528 | /* Direct from ULPD, no real parent */ | ||
529 | .parent = &armper_ck.clk, | ||
530 | .rate = 48000000, | ||
531 | .flags = CLOCK_IN_OMAP16XX | RATE_FIXED | | ||
532 | ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT, | ||
533 | .enable_reg = (void __iomem *)MOD_CONF_CTRL_0, | ||
534 | .enable_bit = 29, | ||
535 | .enable = &omap1_clk_enable_uart_functional, | ||
536 | .disable = &omap1_clk_disable_uart_functional, | ||
537 | }, | ||
538 | .sysc_addr = 0xfffb0054, | ||
539 | }; | ||
540 | |||
541 | static struct clk uart2_ck = { | ||
542 | .name = "uart2_ck", | ||
543 | /* Direct from ULPD, no real parent */ | ||
544 | .parent = &armper_ck.clk, | ||
545 | .rate = 12000000, | ||
546 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | ||
547 | ENABLE_REG_32BIT | ALWAYS_ENABLED | | ||
548 | CLOCK_NO_IDLE_PARENT, | ||
549 | .enable_reg = (void __iomem *)MOD_CONF_CTRL_0, | ||
550 | .enable_bit = 30, /* Chooses between 12MHz and 48MHz */ | ||
551 | .set_rate = &omap1_set_uart_rate, | ||
552 | .recalc = &omap1_uart_recalc, | ||
553 | .enable = &omap1_clk_enable, | ||
554 | .disable = &omap1_clk_disable, | ||
555 | }; | ||
556 | |||
557 | static struct clk uart3_1510 = { | ||
558 | .name = "uart3_ck", | ||
559 | /* Direct from ULPD, no real parent */ | ||
560 | .parent = &armper_ck.clk, | ||
561 | .rate = 12000000, | ||
562 | .flags = CLOCK_IN_OMAP1510 | ENABLE_REG_32BIT | | ||
563 | ALWAYS_ENABLED | CLOCK_NO_IDLE_PARENT, | ||
564 | .enable_reg = (void __iomem *)MOD_CONF_CTRL_0, | ||
565 | .enable_bit = 31, /* Chooses between 12MHz and 48MHz */ | ||
566 | .set_rate = &omap1_set_uart_rate, | ||
567 | .recalc = &omap1_uart_recalc, | ||
568 | .enable = &omap1_clk_enable, | ||
569 | .disable = &omap1_clk_disable, | ||
570 | }; | ||
571 | |||
572 | static struct uart_clk uart3_16xx = { | ||
573 | .clk = { | ||
574 | .name = "uart3_ck", | ||
575 | /* Direct from ULPD, no real parent */ | ||
576 | .parent = &armper_ck.clk, | ||
577 | .rate = 48000000, | ||
578 | .flags = CLOCK_IN_OMAP16XX | RATE_FIXED | | ||
579 | ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT, | ||
580 | .enable_reg = (void __iomem *)MOD_CONF_CTRL_0, | ||
581 | .enable_bit = 31, | ||
582 | .enable = &omap1_clk_enable_uart_functional, | ||
583 | .disable = &omap1_clk_disable_uart_functional, | ||
584 | }, | ||
585 | .sysc_addr = 0xfffb9854, | ||
586 | }; | ||
587 | |||
588 | static struct clk usb_clko = { /* 6 MHz output on W4_USB_CLKO */ | ||
589 | .name = "usb_clko", | ||
590 | /* Direct from ULPD, no parent */ | ||
591 | .rate = 6000000, | ||
592 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | ||
593 | RATE_FIXED | ENABLE_REG_32BIT, | ||
594 | .enable_reg = (void __iomem *)ULPD_CLOCK_CTRL, | ||
595 | .enable_bit = USB_MCLK_EN_BIT, | ||
596 | .enable = &omap1_clk_enable, | ||
597 | .disable = &omap1_clk_disable, | ||
598 | }; | ||
599 | |||
600 | static struct clk usb_hhc_ck1510 = { | ||
601 | .name = "usb_hhc_ck", | ||
602 | /* Direct from ULPD, no parent */ | ||
603 | .rate = 48000000, /* Actually 2 clocks, 12MHz and 48MHz */ | ||
604 | .flags = CLOCK_IN_OMAP1510 | | ||
605 | RATE_FIXED | ENABLE_REG_32BIT, | ||
606 | .enable_reg = (void __iomem *)MOD_CONF_CTRL_0, | ||
607 | .enable_bit = USB_HOST_HHC_UHOST_EN, | ||
608 | .enable = &omap1_clk_enable, | ||
609 | .disable = &omap1_clk_disable, | ||
610 | }; | ||
611 | |||
612 | static struct clk usb_hhc_ck16xx = { | ||
613 | .name = "usb_hhc_ck", | ||
614 | /* Direct from ULPD, no parent */ | ||
615 | .rate = 48000000, | ||
616 | /* OTG_SYSCON_2.OTG_PADEN == 0 (not 1510-compatible) */ | ||
617 | .flags = CLOCK_IN_OMAP16XX | | ||
618 | RATE_FIXED | ENABLE_REG_32BIT, | ||
619 | .enable_reg = (void __iomem *)OTG_BASE + 0x08 /* OTG_SYSCON_2 */, | ||
620 | .enable_bit = 8 /* UHOST_EN */, | ||
621 | .enable = &omap1_clk_enable, | ||
622 | .disable = &omap1_clk_disable, | ||
623 | }; | ||
624 | |||
625 | static struct clk usb_dc_ck = { | ||
626 | .name = "usb_dc_ck", | ||
627 | /* Direct from ULPD, no parent */ | ||
628 | .rate = 48000000, | ||
629 | .flags = CLOCK_IN_OMAP16XX | RATE_FIXED, | ||
630 | .enable_reg = (void __iomem *)SOFT_REQ_REG, | ||
631 | .enable_bit = 4, | ||
632 | .enable = &omap1_clk_enable, | ||
633 | .disable = &omap1_clk_disable, | ||
634 | }; | ||
635 | |||
636 | static struct clk mclk_1510 = { | ||
637 | .name = "mclk", | ||
638 | /* Direct from ULPD, no parent. May be enabled by ext hardware. */ | ||
639 | .rate = 12000000, | ||
640 | .flags = CLOCK_IN_OMAP1510 | RATE_FIXED, | ||
641 | .enable = &omap1_clk_enable, | ||
642 | .disable = &omap1_clk_disable, | ||
643 | }; | ||
644 | |||
645 | static struct clk mclk_16xx = { | ||
646 | .name = "mclk", | ||
647 | /* Direct from ULPD, no parent. May be enabled by ext hardware. */ | ||
648 | .flags = CLOCK_IN_OMAP16XX, | ||
649 | .enable_reg = (void __iomem *)COM_CLK_DIV_CTRL_SEL, | ||
650 | .enable_bit = COM_ULPD_PLL_CLK_REQ, | ||
651 | .set_rate = &omap1_set_ext_clk_rate, | ||
652 | .round_rate = &omap1_round_ext_clk_rate, | ||
653 | .init = &omap1_init_ext_clk, | ||
654 | .enable = &omap1_clk_enable, | ||
655 | .disable = &omap1_clk_disable, | ||
656 | }; | ||
657 | |||
658 | static struct clk bclk_1510 = { | ||
659 | .name = "bclk", | ||
660 | /* Direct from ULPD, no parent. May be enabled by ext hardware. */ | ||
661 | .rate = 12000000, | ||
662 | .flags = CLOCK_IN_OMAP1510 | RATE_FIXED, | ||
663 | .enable = &omap1_clk_enable, | ||
664 | .disable = &omap1_clk_disable, | ||
665 | }; | ||
666 | |||
667 | static struct clk bclk_16xx = { | ||
668 | .name = "bclk", | ||
669 | /* Direct from ULPD, no parent. May be enabled by ext hardware. */ | ||
670 | .flags = CLOCK_IN_OMAP16XX, | ||
671 | .enable_reg = (void __iomem *)SWD_CLK_DIV_CTRL_SEL, | ||
672 | .enable_bit = SWD_ULPD_PLL_CLK_REQ, | ||
673 | .set_rate = &omap1_set_ext_clk_rate, | ||
674 | .round_rate = &omap1_round_ext_clk_rate, | ||
675 | .init = &omap1_init_ext_clk, | ||
676 | .enable = &omap1_clk_enable, | ||
677 | .disable = &omap1_clk_disable, | ||
678 | }; | ||
679 | |||
680 | static struct clk mmc1_ck = { | ||
681 | .name = "mmc1_ck", | ||
682 | /* Functional clock is direct from ULPD, interface clock is ARMPER */ | ||
683 | .parent = &armper_ck.clk, | ||
684 | .rate = 48000000, | ||
685 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | ||
686 | RATE_FIXED | ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT, | ||
687 | .enable_reg = (void __iomem *)MOD_CONF_CTRL_0, | ||
688 | .enable_bit = 23, | ||
689 | .enable = &omap1_clk_enable, | ||
690 | .disable = &omap1_clk_disable, | ||
691 | }; | ||
692 | |||
693 | static struct clk mmc2_ck = { | ||
694 | .name = "mmc2_ck", | ||
695 | /* Functional clock is direct from ULPD, interface clock is ARMPER */ | ||
696 | .parent = &armper_ck.clk, | ||
697 | .rate = 48000000, | ||
698 | .flags = CLOCK_IN_OMAP16XX | | ||
699 | RATE_FIXED | ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT, | ||
700 | .enable_reg = (void __iomem *)MOD_CONF_CTRL_0, | ||
701 | .enable_bit = 20, | ||
702 | .enable = &omap1_clk_enable, | ||
703 | .disable = &omap1_clk_disable, | ||
704 | }; | ||
705 | |||
706 | static struct clk virtual_ck_mpu = { | ||
707 | .name = "mpu", | ||
708 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | ||
709 | VIRTUAL_CLOCK | ALWAYS_ENABLED, | ||
710 | .parent = &arm_ck, /* Is smarter alias for */ | ||
711 | .recalc = &followparent_recalc, | ||
712 | .set_rate = &omap1_select_table_rate, | ||
713 | .round_rate = &omap1_round_to_table_rate, | ||
714 | .enable = &omap1_clk_enable, | ||
715 | .disable = &omap1_clk_disable, | ||
716 | }; | ||
717 | |||
718 | static struct clk * onchip_clks[] = { | ||
719 | /* non-ULPD clocks */ | ||
720 | &ck_ref, | ||
721 | &ck_dpll1, | ||
722 | /* CK_GEN1 clocks */ | ||
723 | &ck_dpll1out.clk, | ||
724 | &arm_ck, | ||
725 | &armper_ck.clk, | ||
726 | &arm_gpio_ck, | ||
727 | &armxor_ck.clk, | ||
728 | &armtim_ck.clk, | ||
729 | &armwdt_ck.clk, | ||
730 | &arminth_ck1510, &arminth_ck16xx, | ||
731 | /* CK_GEN2 clocks */ | ||
732 | &dsp_ck, | ||
733 | &dspmmu_ck, | ||
734 | &dspper_ck, | ||
735 | &dspxor_ck, | ||
736 | &dsptim_ck, | ||
737 | /* CK_GEN3 clocks */ | ||
738 | &tc_ck.clk, | ||
739 | &tipb_ck, | ||
740 | &l3_ocpi_ck, | ||
741 | &tc1_ck, | ||
742 | &tc2_ck, | ||
743 | &dma_ck, | ||
744 | &dma_lcdfree_ck, | ||
745 | &api_ck.clk, | ||
746 | &lb_ck.clk, | ||
747 | &rhea1_ck, | ||
748 | &rhea2_ck, | ||
749 | &lcd_ck_16xx, | ||
750 | &lcd_ck_1510.clk, | ||
751 | /* ULPD clocks */ | ||
752 | &uart1_1510, | ||
753 | &uart1_16xx.clk, | ||
754 | &uart2_ck, | ||
755 | &uart3_1510, | ||
756 | &uart3_16xx.clk, | ||
757 | &usb_clko, | ||
758 | &usb_hhc_ck1510, &usb_hhc_ck16xx, | ||
759 | &usb_dc_ck, | ||
760 | &mclk_1510, &mclk_16xx, | ||
761 | &bclk_1510, &bclk_16xx, | ||
762 | &mmc1_ck, | ||
763 | &mmc2_ck, | ||
764 | /* Virtual clocks */ | ||
765 | &virtual_ck_mpu, | ||
766 | }; | ||
767 | |||
768 | #endif | ||
diff --git a/arch/arm/mach-omap1/devices.c b/arch/arm/mach-omap1/devices.c index 3c5d901efeaa..ecbc47514adc 100644 --- a/arch/arm/mach-omap1/devices.c +++ b/arch/arm/mach-omap1/devices.c | |||
@@ -25,56 +25,7 @@ | |||
25 | #include <asm/arch/mux.h> | 25 | #include <asm/arch/mux.h> |
26 | #include <asm/arch/gpio.h> | 26 | #include <asm/arch/gpio.h> |
27 | 27 | ||
28 | 28 | extern void omap_nop_release(struct device *dev); | |
29 | static void omap_nop_release(struct device *dev) | ||
30 | { | ||
31 | /* Nothing */ | ||
32 | } | ||
33 | |||
34 | /*-------------------------------------------------------------------------*/ | ||
35 | |||
36 | #if defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE) | ||
37 | |||
38 | #define OMAP_I2C_BASE 0xfffb3800 | ||
39 | |||
40 | static struct resource i2c_resources[] = { | ||
41 | { | ||
42 | .start = OMAP_I2C_BASE, | ||
43 | .end = OMAP_I2C_BASE + 0x3f, | ||
44 | .flags = IORESOURCE_MEM, | ||
45 | }, | ||
46 | { | ||
47 | .start = INT_I2C, | ||
48 | .flags = IORESOURCE_IRQ, | ||
49 | }, | ||
50 | }; | ||
51 | |||
52 | /* DMA not used; works around erratum writing to non-empty i2c fifo */ | ||
53 | |||
54 | static struct platform_device omap_i2c_device = { | ||
55 | .name = "i2c_omap", | ||
56 | .id = -1, | ||
57 | .dev = { | ||
58 | .release = omap_nop_release, | ||
59 | }, | ||
60 | .num_resources = ARRAY_SIZE(i2c_resources), | ||
61 | .resource = i2c_resources, | ||
62 | }; | ||
63 | |||
64 | static void omap_init_i2c(void) | ||
65 | { | ||
66 | /* FIXME define and use a boot tag, in case of boards that | ||
67 | * either don't wire up I2C, or chips that mux it differently... | ||
68 | * it can include clocking and address info, maybe more. | ||
69 | */ | ||
70 | omap_cfg_reg(I2C_SCL); | ||
71 | omap_cfg_reg(I2C_SDA); | ||
72 | |||
73 | (void) platform_device_register(&omap_i2c_device); | ||
74 | } | ||
75 | #else | ||
76 | static inline void omap_init_i2c(void) {} | ||
77 | #endif | ||
78 | 29 | ||
79 | /*-------------------------------------------------------------------------*/ | 30 | /*-------------------------------------------------------------------------*/ |
80 | 31 | ||
@@ -110,137 +61,6 @@ static inline void omap_init_irda(void) {} | |||
110 | 61 | ||
111 | /*-------------------------------------------------------------------------*/ | 62 | /*-------------------------------------------------------------------------*/ |
112 | 63 | ||
113 | #if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) | ||
114 | |||
115 | #define OMAP_MMC1_BASE 0xfffb7800 | ||
116 | #define OMAP_MMC2_BASE 0xfffb7c00 /* omap16xx only */ | ||
117 | |||
118 | static struct omap_mmc_conf mmc1_conf; | ||
119 | |||
120 | static u64 mmc1_dmamask = 0xffffffff; | ||
121 | |||
122 | static struct resource mmc1_resources[] = { | ||
123 | { | ||
124 | .start = IO_ADDRESS(OMAP_MMC1_BASE), | ||
125 | .end = IO_ADDRESS(OMAP_MMC1_BASE) + 0x7f, | ||
126 | .flags = IORESOURCE_MEM, | ||
127 | }, | ||
128 | { | ||
129 | .start = INT_MMC, | ||
130 | .flags = IORESOURCE_IRQ, | ||
131 | }, | ||
132 | }; | ||
133 | |||
134 | static struct platform_device mmc_omap_device1 = { | ||
135 | .name = "mmci-omap", | ||
136 | .id = 1, | ||
137 | .dev = { | ||
138 | .release = omap_nop_release, | ||
139 | .dma_mask = &mmc1_dmamask, | ||
140 | .platform_data = &mmc1_conf, | ||
141 | }, | ||
142 | .num_resources = ARRAY_SIZE(mmc1_resources), | ||
143 | .resource = mmc1_resources, | ||
144 | }; | ||
145 | |||
146 | #ifdef CONFIG_ARCH_OMAP16XX | ||
147 | |||
148 | static struct omap_mmc_conf mmc2_conf; | ||
149 | |||
150 | static u64 mmc2_dmamask = 0xffffffff; | ||
151 | |||
152 | static struct resource mmc2_resources[] = { | ||
153 | { | ||
154 | .start = IO_ADDRESS(OMAP_MMC2_BASE), | ||
155 | .end = IO_ADDRESS(OMAP_MMC2_BASE) + 0x7f, | ||
156 | .flags = IORESOURCE_MEM, | ||
157 | }, | ||
158 | { | ||
159 | .start = INT_1610_MMC2, | ||
160 | .flags = IORESOURCE_IRQ, | ||
161 | }, | ||
162 | }; | ||
163 | |||
164 | static struct platform_device mmc_omap_device2 = { | ||
165 | .name = "mmci-omap", | ||
166 | .id = 2, | ||
167 | .dev = { | ||
168 | .release = omap_nop_release, | ||
169 | .dma_mask = &mmc2_dmamask, | ||
170 | .platform_data = &mmc2_conf, | ||
171 | }, | ||
172 | .num_resources = ARRAY_SIZE(mmc2_resources), | ||
173 | .resource = mmc2_resources, | ||
174 | }; | ||
175 | #endif | ||
176 | |||
177 | static void __init omap_init_mmc(void) | ||
178 | { | ||
179 | const struct omap_mmc_config *mmc_conf; | ||
180 | const struct omap_mmc_conf *mmc; | ||
181 | |||
182 | /* NOTE: assumes MMC was never (wrongly) enabled */ | ||
183 | mmc_conf = omap_get_config(OMAP_TAG_MMC, struct omap_mmc_config); | ||
184 | if (!mmc_conf) | ||
185 | return; | ||
186 | |||
187 | /* block 1 is always available and has just one pinout option */ | ||
188 | mmc = &mmc_conf->mmc[0]; | ||
189 | if (mmc->enabled) { | ||
190 | omap_cfg_reg(MMC_CMD); | ||
191 | omap_cfg_reg(MMC_CLK); | ||
192 | omap_cfg_reg(MMC_DAT0); | ||
193 | if (cpu_is_omap1710()) { | ||
194 | omap_cfg_reg(M15_1710_MMC_CLKI); | ||
195 | omap_cfg_reg(P19_1710_MMC_CMDDIR); | ||
196 | omap_cfg_reg(P20_1710_MMC_DATDIR0); | ||
197 | } | ||
198 | if (mmc->wire4) { | ||
199 | omap_cfg_reg(MMC_DAT1); | ||
200 | /* NOTE: DAT2 can be on W10 (here) or M15 */ | ||
201 | if (!mmc->nomux) | ||
202 | omap_cfg_reg(MMC_DAT2); | ||
203 | omap_cfg_reg(MMC_DAT3); | ||
204 | } | ||
205 | mmc1_conf = *mmc; | ||
206 | (void) platform_device_register(&mmc_omap_device1); | ||
207 | } | ||
208 | |||
209 | #ifdef CONFIG_ARCH_OMAP16XX | ||
210 | /* block 2 is on newer chips, and has many pinout options */ | ||
211 | mmc = &mmc_conf->mmc[1]; | ||
212 | if (mmc->enabled) { | ||
213 | if (!mmc->nomux) { | ||
214 | omap_cfg_reg(Y8_1610_MMC2_CMD); | ||
215 | omap_cfg_reg(Y10_1610_MMC2_CLK); | ||
216 | omap_cfg_reg(R18_1610_MMC2_CLKIN); | ||
217 | omap_cfg_reg(W8_1610_MMC2_DAT0); | ||
218 | if (mmc->wire4) { | ||
219 | omap_cfg_reg(V8_1610_MMC2_DAT1); | ||
220 | omap_cfg_reg(W15_1610_MMC2_DAT2); | ||
221 | omap_cfg_reg(R10_1610_MMC2_DAT3); | ||
222 | } | ||
223 | |||
224 | /* These are needed for the level shifter */ | ||
225 | omap_cfg_reg(V9_1610_MMC2_CMDDIR); | ||
226 | omap_cfg_reg(V5_1610_MMC2_DATDIR0); | ||
227 | omap_cfg_reg(W19_1610_MMC2_DATDIR1); | ||
228 | } | ||
229 | |||
230 | /* Feedback clock must be set on OMAP-1710 MMC2 */ | ||
231 | if (cpu_is_omap1710()) | ||
232 | omap_writel(omap_readl(MOD_CONF_CTRL_1) | (1 << 24), | ||
233 | MOD_CONF_CTRL_1); | ||
234 | mmc2_conf = *mmc; | ||
235 | (void) platform_device_register(&mmc_omap_device2); | ||
236 | } | ||
237 | #endif | ||
238 | return; | ||
239 | } | ||
240 | #else | ||
241 | static inline void omap_init_mmc(void) {} | ||
242 | #endif | ||
243 | |||
244 | #if defined(CONFIG_OMAP_RTC) || defined(CONFIG_OMAP_RTC) | 64 | #if defined(CONFIG_OMAP_RTC) || defined(CONFIG_OMAP_RTC) |
245 | 65 | ||
246 | #define OMAP_RTC_BASE 0xfffb4800 | 66 | #define OMAP_RTC_BASE 0xfffb4800 |
@@ -279,38 +99,6 @@ static void omap_init_rtc(void) | |||
279 | static inline void omap_init_rtc(void) {} | 99 | static inline void omap_init_rtc(void) {} |
280 | #endif | 100 | #endif |
281 | 101 | ||
282 | /*-------------------------------------------------------------------------*/ | ||
283 | |||
284 | #if defined(CONFIG_OMAP16XX_WATCHDOG) || defined(CONFIG_OMAP16XX_WATCHDOG_MODULE) | ||
285 | |||
286 | #define OMAP_WDT_BASE 0xfffeb000 | ||
287 | |||
288 | static struct resource wdt_resources[] = { | ||
289 | { | ||
290 | .start = OMAP_WDT_BASE, | ||
291 | .end = OMAP_WDT_BASE + 0x4f, | ||
292 | .flags = IORESOURCE_MEM, | ||
293 | }, | ||
294 | }; | ||
295 | |||
296 | static struct platform_device omap_wdt_device = { | ||
297 | .name = "omap1610_wdt", | ||
298 | .id = -1, | ||
299 | .dev = { | ||
300 | .release = omap_nop_release, | ||
301 | }, | ||
302 | .num_resources = ARRAY_SIZE(wdt_resources), | ||
303 | .resource = wdt_resources, | ||
304 | }; | ||
305 | |||
306 | static void omap_init_wdt(void) | ||
307 | { | ||
308 | (void) platform_device_register(&omap_wdt_device); | ||
309 | } | ||
310 | #else | ||
311 | static inline void omap_init_wdt(void) {} | ||
312 | #endif | ||
313 | |||
314 | 102 | ||
315 | /*-------------------------------------------------------------------------*/ | 103 | /*-------------------------------------------------------------------------*/ |
316 | 104 | ||
@@ -334,18 +122,15 @@ static inline void omap_init_wdt(void) {} | |||
334 | * may be handled by the boot loader, and drivers should expect it will | 122 | * may be handled by the boot loader, and drivers should expect it will |
335 | * normally have been done by the time they're probed. | 123 | * normally have been done by the time they're probed. |
336 | */ | 124 | */ |
337 | static int __init omap_init_devices(void) | 125 | static int __init omap1_init_devices(void) |
338 | { | 126 | { |
339 | /* please keep these calls, and their implementations above, | 127 | /* please keep these calls, and their implementations above, |
340 | * in alphabetical order so they're easier to sort through. | 128 | * in alphabetical order so they're easier to sort through. |
341 | */ | 129 | */ |
342 | omap_init_i2c(); | ||
343 | omap_init_irda(); | 130 | omap_init_irda(); |
344 | omap_init_mmc(); | ||
345 | omap_init_rtc(); | 131 | omap_init_rtc(); |
346 | omap_init_wdt(); | ||
347 | 132 | ||
348 | return 0; | 133 | return 0; |
349 | } | 134 | } |
350 | arch_initcall(omap_init_devices); | 135 | arch_initcall(omap1_init_devices); |
351 | 136 | ||
diff --git a/arch/arm/mach-omap1/id.c b/arch/arm/mach-omap1/id.c index 986c3b7e09bb..5c637c048368 100644 --- a/arch/arm/mach-omap1/id.c +++ b/arch/arm/mach-omap1/id.c | |||
@@ -18,6 +18,13 @@ | |||
18 | 18 | ||
19 | #include <asm/io.h> | 19 | #include <asm/io.h> |
20 | 20 | ||
21 | #define OMAP_DIE_ID_0 0xfffe1800 | ||
22 | #define OMAP_DIE_ID_1 0xfffe1804 | ||
23 | #define OMAP_PRODUCTION_ID_0 0xfffe2000 | ||
24 | #define OMAP_PRODUCTION_ID_1 0xfffe2004 | ||
25 | #define OMAP32_ID_0 0xfffed400 | ||
26 | #define OMAP32_ID_1 0xfffed404 | ||
27 | |||
21 | struct omap_id { | 28 | struct omap_id { |
22 | u16 jtag_id; /* Used to determine OMAP type */ | 29 | u16 jtag_id; /* Used to determine OMAP type */ |
23 | u8 die_rev; /* Processor revision */ | 30 | u8 die_rev; /* Processor revision */ |
@@ -27,6 +34,7 @@ struct omap_id { | |||
27 | 34 | ||
28 | /* Register values to detect the OMAP version */ | 35 | /* Register values to detect the OMAP version */ |
29 | static struct omap_id omap_ids[] __initdata = { | 36 | static struct omap_id omap_ids[] __initdata = { |
37 | { .jtag_id = 0xb574, .die_rev = 0x2, .omap_id = 0x03310315, .type = 0x03100000}, | ||
30 | { .jtag_id = 0x355f, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x07300100}, | 38 | { .jtag_id = 0x355f, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x07300100}, |
31 | { .jtag_id = 0xb55f, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x07300300}, | 39 | { .jtag_id = 0xb55f, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x07300300}, |
32 | { .jtag_id = 0xb470, .die_rev = 0x0, .omap_id = 0x03310100, .type = 0x15100000}, | 40 | { .jtag_id = 0xb470, .die_rev = 0x0, .omap_id = 0x03310100, .type = 0x15100000}, |
@@ -164,6 +172,7 @@ void __init omap_check_revision(void) | |||
164 | case 0x07: | 172 | case 0x07: |
165 | system_rev |= 0x07; | 173 | system_rev |= 0x07; |
166 | break; | 174 | break; |
175 | case 0x03: | ||
167 | case 0x15: | 176 | case 0x15: |
168 | system_rev |= 0x15; | 177 | system_rev |= 0x15; |
169 | break; | 178 | break; |
diff --git a/arch/arm/mach-omap1/io.c b/arch/arm/mach-omap1/io.c index 79fb86535ebc..a7a19f75b9e1 100644 --- a/arch/arm/mach-omap1/io.c +++ b/arch/arm/mach-omap1/io.c | |||
@@ -15,9 +15,10 @@ | |||
15 | 15 | ||
16 | #include <asm/mach/map.h> | 16 | #include <asm/mach/map.h> |
17 | #include <asm/io.h> | 17 | #include <asm/io.h> |
18 | #include <asm/arch/mux.h> | ||
18 | #include <asm/arch/tc.h> | 19 | #include <asm/arch/tc.h> |
19 | 20 | ||
20 | extern int clk_init(void); | 21 | extern int omap1_clk_init(void); |
21 | extern void omap_check_revision(void); | 22 | extern void omap_check_revision(void); |
22 | extern void omap_sram_init(void); | 23 | extern void omap_sram_init(void); |
23 | 24 | ||
@@ -50,7 +51,7 @@ static struct map_desc omap730_io_desc[] __initdata = { | |||
50 | }; | 51 | }; |
51 | #endif | 52 | #endif |
52 | 53 | ||
53 | #ifdef CONFIG_ARCH_OMAP1510 | 54 | #ifdef CONFIG_ARCH_OMAP15XX |
54 | static struct map_desc omap1510_io_desc[] __initdata = { | 55 | static struct map_desc omap1510_io_desc[] __initdata = { |
55 | { | 56 | { |
56 | .virtual = OMAP1510_DSP_BASE, | 57 | .virtual = OMAP1510_DSP_BASE, |
@@ -98,7 +99,7 @@ static void __init _omap_map_io(void) | |||
98 | iotable_init(omap730_io_desc, ARRAY_SIZE(omap730_io_desc)); | 99 | iotable_init(omap730_io_desc, ARRAY_SIZE(omap730_io_desc)); |
99 | } | 100 | } |
100 | #endif | 101 | #endif |
101 | #ifdef CONFIG_ARCH_OMAP1510 | 102 | #ifdef CONFIG_ARCH_OMAP15XX |
102 | if (cpu_is_omap1510()) { | 103 | if (cpu_is_omap1510()) { |
103 | iotable_init(omap1510_io_desc, ARRAY_SIZE(omap1510_io_desc)); | 104 | iotable_init(omap1510_io_desc, ARRAY_SIZE(omap1510_io_desc)); |
104 | } | 105 | } |
@@ -119,7 +120,7 @@ static void __init _omap_map_io(void) | |||
119 | 120 | ||
120 | /* Must init clocks early to assure that timer interrupt works | 121 | /* Must init clocks early to assure that timer interrupt works |
121 | */ | 122 | */ |
122 | clk_init(); | 123 | omap1_clk_init(); |
123 | } | 124 | } |
124 | 125 | ||
125 | /* | 126 | /* |
@@ -127,7 +128,9 @@ static void __init _omap_map_io(void) | |||
127 | */ | 128 | */ |
128 | void __init omap_map_common_io(void) | 129 | void __init omap_map_common_io(void) |
129 | { | 130 | { |
130 | if (!initialized) | 131 | if (!initialized) { |
131 | _omap_map_io(); | 132 | _omap_map_io(); |
133 | omap1_mux_init(); | ||
134 | } | ||
132 | } | 135 | } |
133 | 136 | ||
diff --git a/arch/arm/mach-omap1/irq.c b/arch/arm/mach-omap1/irq.c index 192ce6055faa..ed65a7d2e941 100644 --- a/arch/arm/mach-omap1/irq.c +++ b/arch/arm/mach-omap1/irq.c | |||
@@ -47,6 +47,7 @@ | |||
47 | #include <asm/irq.h> | 47 | #include <asm/irq.h> |
48 | #include <asm/mach/irq.h> | 48 | #include <asm/mach/irq.h> |
49 | #include <asm/arch/gpio.h> | 49 | #include <asm/arch/gpio.h> |
50 | #include <asm/arch/cpu.h> | ||
50 | 51 | ||
51 | #include <asm/io.h> | 52 | #include <asm/io.h> |
52 | 53 | ||
@@ -147,11 +148,15 @@ static struct omap_irq_bank omap730_irq_banks[] = { | |||
147 | }; | 148 | }; |
148 | #endif | 149 | #endif |
149 | 150 | ||
150 | #ifdef CONFIG_ARCH_OMAP1510 | 151 | #ifdef CONFIG_ARCH_OMAP15XX |
151 | static struct omap_irq_bank omap1510_irq_banks[] = { | 152 | static struct omap_irq_bank omap1510_irq_banks[] = { |
152 | { .base_reg = OMAP_IH1_BASE, .trigger_map = 0xb3febfff }, | 153 | { .base_reg = OMAP_IH1_BASE, .trigger_map = 0xb3febfff }, |
153 | { .base_reg = OMAP_IH2_BASE, .trigger_map = 0xffbfffed }, | 154 | { .base_reg = OMAP_IH2_BASE, .trigger_map = 0xffbfffed }, |
154 | }; | 155 | }; |
156 | static struct omap_irq_bank omap310_irq_banks[] = { | ||
157 | { .base_reg = OMAP_IH1_BASE, .trigger_map = 0xb3faefc3 }, | ||
158 | { .base_reg = OMAP_IH2_BASE, .trigger_map = 0x65b3c061 }, | ||
159 | }; | ||
155 | #endif | 160 | #endif |
156 | 161 | ||
157 | #if defined(CONFIG_ARCH_OMAP16XX) | 162 | #if defined(CONFIG_ARCH_OMAP16XX) |
@@ -181,11 +186,15 @@ void __init omap_init_irq(void) | |||
181 | irq_bank_count = ARRAY_SIZE(omap730_irq_banks); | 186 | irq_bank_count = ARRAY_SIZE(omap730_irq_banks); |
182 | } | 187 | } |
183 | #endif | 188 | #endif |
184 | #ifdef CONFIG_ARCH_OMAP1510 | 189 | #ifdef CONFIG_ARCH_OMAP15XX |
185 | if (cpu_is_omap1510()) { | 190 | if (cpu_is_omap1510()) { |
186 | irq_banks = omap1510_irq_banks; | 191 | irq_banks = omap1510_irq_banks; |
187 | irq_bank_count = ARRAY_SIZE(omap1510_irq_banks); | 192 | irq_bank_count = ARRAY_SIZE(omap1510_irq_banks); |
188 | } | 193 | } |
194 | if (cpu_is_omap310()) { | ||
195 | irq_banks = omap310_irq_banks; | ||
196 | irq_bank_count = ARRAY_SIZE(omap310_irq_banks); | ||
197 | } | ||
189 | #endif | 198 | #endif |
190 | #if defined(CONFIG_ARCH_OMAP16XX) | 199 | #if defined(CONFIG_ARCH_OMAP16XX) |
191 | if (cpu_is_omap16xx()) { | 200 | if (cpu_is_omap16xx()) { |
@@ -226,9 +235,11 @@ void __init omap_init_irq(void) | |||
226 | } | 235 | } |
227 | 236 | ||
228 | /* Unmask level 2 handler */ | 237 | /* Unmask level 2 handler */ |
229 | if (cpu_is_omap730()) { | 238 | |
239 | if (cpu_is_omap730()) | ||
230 | omap_unmask_irq(INT_730_IH2_IRQ); | 240 | omap_unmask_irq(INT_730_IH2_IRQ); |
231 | } else { | 241 | else if (cpu_is_omap1510()) |
232 | omap_unmask_irq(INT_IH2_IRQ); | 242 | omap_unmask_irq(INT_1510_IH2_IRQ); |
233 | } | 243 | else if (cpu_is_omap16xx()) |
244 | omap_unmask_irq(INT_1610_IH2_IRQ); | ||
234 | } | 245 | } |
diff --git a/arch/arm/mach-omap1/leds-h2p2-debug.c b/arch/arm/mach-omap1/leds-h2p2-debug.c index 399010c14036..650650815915 100644 --- a/arch/arm/mach-omap1/leds-h2p2-debug.c +++ b/arch/arm/mach-omap1/leds-h2p2-debug.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <asm/hardware.h> | 18 | #include <asm/hardware.h> |
19 | #include <asm/leds.h> | 19 | #include <asm/leds.h> |
20 | #include <asm/system.h> | 20 | #include <asm/system.h> |
21 | #include <asm/mach-types.h> | ||
21 | 22 | ||
22 | #include <asm/arch/fpga.h> | 23 | #include <asm/arch/fpga.h> |
23 | #include <asm/arch/gpio.h> | 24 | #include <asm/arch/gpio.h> |
@@ -63,14 +64,19 @@ void h2p2_dbg_leds_event(led_event_t evt) | |||
63 | case led_stop: | 64 | case led_stop: |
64 | case led_halted: | 65 | case led_halted: |
65 | /* all leds off during suspend or shutdown */ | 66 | /* all leds off during suspend or shutdown */ |
66 | omap_set_gpio_dataout(GPIO_TIMER, 0); | 67 | |
67 | omap_set_gpio_dataout(GPIO_IDLE, 0); | 68 | if (! machine_is_omap_perseus2()) { |
69 | omap_set_gpio_dataout(GPIO_TIMER, 0); | ||
70 | omap_set_gpio_dataout(GPIO_IDLE, 0); | ||
71 | } | ||
72 | |||
68 | __raw_writew(~0, &fpga->leds); | 73 | __raw_writew(~0, &fpga->leds); |
69 | led_state &= ~LED_STATE_ENABLED; | 74 | led_state &= ~LED_STATE_ENABLED; |
70 | if (evt == led_halted) { | 75 | if (evt == led_halted) { |
71 | iounmap(fpga); | 76 | iounmap(fpga); |
72 | fpga = NULL; | 77 | fpga = NULL; |
73 | } | 78 | } |
79 | |||
74 | goto done; | 80 | goto done; |
75 | 81 | ||
76 | case led_claim: | 82 | case led_claim: |
@@ -85,18 +91,37 @@ void h2p2_dbg_leds_event(led_event_t evt) | |||
85 | #ifdef CONFIG_LEDS_TIMER | 91 | #ifdef CONFIG_LEDS_TIMER |
86 | case led_timer: | 92 | case led_timer: |
87 | led_state ^= LED_TIMER_ON; | 93 | led_state ^= LED_TIMER_ON; |
88 | omap_set_gpio_dataout(GPIO_TIMER, led_state & LED_TIMER_ON); | 94 | |
89 | goto done; | 95 | if (machine_is_omap_perseus2()) |
96 | hw_led_state ^= H2P2_DBG_FPGA_P2_LED_TIMER; | ||
97 | else { | ||
98 | omap_set_gpio_dataout(GPIO_TIMER, led_state & LED_TIMER_ON); | ||
99 | goto done; | ||
100 | } | ||
101 | |||
102 | break; | ||
90 | #endif | 103 | #endif |
91 | 104 | ||
92 | #ifdef CONFIG_LEDS_CPU | 105 | #ifdef CONFIG_LEDS_CPU |
93 | case led_idle_start: | 106 | case led_idle_start: |
94 | omap_set_gpio_dataout(GPIO_IDLE, 1); | 107 | if (machine_is_omap_perseus2()) |
95 | goto done; | 108 | hw_led_state |= H2P2_DBG_FPGA_P2_LED_IDLE; |
109 | else { | ||
110 | omap_set_gpio_dataout(GPIO_IDLE, 1); | ||
111 | goto done; | ||
112 | } | ||
113 | |||
114 | break; | ||
96 | 115 | ||
97 | case led_idle_end: | 116 | case led_idle_end: |
98 | omap_set_gpio_dataout(GPIO_IDLE, 0); | 117 | if (machine_is_omap_perseus2()) |
99 | goto done; | 118 | hw_led_state &= ~H2P2_DBG_FPGA_P2_LED_IDLE; |
119 | else { | ||
120 | omap_set_gpio_dataout(GPIO_IDLE, 0); | ||
121 | goto done; | ||
122 | } | ||
123 | |||
124 | break; | ||
100 | #endif | 125 | #endif |
101 | 126 | ||
102 | case led_green_on: | 127 | case led_green_on: |
@@ -135,7 +160,7 @@ void h2p2_dbg_leds_event(led_event_t evt) | |||
135 | /* | 160 | /* |
136 | * Actually burn the LEDs | 161 | * Actually burn the LEDs |
137 | */ | 162 | */ |
138 | if (led_state & LED_STATE_CLAIMED) | 163 | if (led_state & LED_STATE_ENABLED) |
139 | __raw_writew(~hw_led_state, &fpga->leds); | 164 | __raw_writew(~hw_led_state, &fpga->leds); |
140 | 165 | ||
141 | done: | 166 | done: |
diff --git a/arch/arm/mach-omap1/leds.c b/arch/arm/mach-omap1/leds.c index 5c6b1bb6e722..3f9dcac4fd41 100644 --- a/arch/arm/mach-omap1/leds.c +++ b/arch/arm/mach-omap1/leds.c | |||
@@ -33,7 +33,6 @@ omap_leds_init(void) | |||
33 | 33 | ||
34 | if (machine_is_omap_h2() | 34 | if (machine_is_omap_h2() |
35 | || machine_is_omap_h3() | 35 | || machine_is_omap_h3() |
36 | || machine_is_omap_perseus2() | ||
37 | #ifdef CONFIG_OMAP_OSK_MISTRAL | 36 | #ifdef CONFIG_OMAP_OSK_MISTRAL |
38 | || machine_is_omap_osk() | 37 | || machine_is_omap_osk() |
39 | #endif | 38 | #endif |
diff --git a/arch/arm/mach-omap1/mux.c b/arch/arm/mach-omap1/mux.c new file mode 100644 index 000000000000..d4b8d624e742 --- /dev/null +++ b/arch/arm/mach-omap1/mux.c | |||
@@ -0,0 +1,289 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-omap1/mux.c | ||
3 | * | ||
4 | * OMAP1 pin multiplexing configurations | ||
5 | * | ||
6 | * Copyright (C) 2003 - 2005 Nokia Corporation | ||
7 | * | ||
8 | * Written by Tony Lindgren <tony.lindgren@nokia.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
23 | * | ||
24 | */ | ||
25 | #include <linux/config.h> | ||
26 | #include <linux/module.h> | ||
27 | #include <linux/init.h> | ||
28 | #include <asm/system.h> | ||
29 | #include <asm/io.h> | ||
30 | #include <linux/spinlock.h> | ||
31 | |||
32 | #include <asm/arch/mux.h> | ||
33 | |||
34 | #ifdef CONFIG_OMAP_MUX | ||
35 | |||
36 | #ifdef CONFIG_ARCH_OMAP730 | ||
37 | struct pin_config __initdata_or_module omap730_pins[] = { | ||
38 | MUX_CFG_730("E2_730_KBR0", 12, 21, 0, 0, 20, 1, NA, 0, 0) | ||
39 | MUX_CFG_730("J7_730_KBR1", 12, 25, 0, 0, 24, 1, NA, 0, 0) | ||
40 | MUX_CFG_730("E1_730_KBR2", 12, 29, 0, 0, 28, 1, NA, 0, 0) | ||
41 | MUX_CFG_730("F3_730_KBR3", 13, 1, 0, 0, 0, 1, NA, 0, 0) | ||
42 | MUX_CFG_730("D2_730_KBR4", 13, 5, 0, 0, 4, 1, NA, 0, 0) | ||
43 | MUX_CFG_730("C2_730_KBC0", 13, 9, 0, 0, 8, 1, NA, 0, 0) | ||
44 | MUX_CFG_730("D3_730_KBC1", 13, 13, 0, 0, 12, 1, NA, 0, 0) | ||
45 | MUX_CFG_730("E4_730_KBC2", 13, 17, 0, 0, 16, 1, NA, 0, 0) | ||
46 | MUX_CFG_730("F4_730_KBC3", 13, 21, 0, 0, 20, 1, NA, 0, 0) | ||
47 | MUX_CFG_730("E3_730_KBC4", 13, 25, 0, 0, 24, 1, NA, 0, 0) | ||
48 | }; | ||
49 | #endif | ||
50 | |||
51 | #if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX) | ||
52 | struct pin_config __initdata_or_module omap1xxx_pins[] = { | ||
53 | /* | ||
54 | * description mux mode mux pull pull pull pu_pd pu dbg | ||
55 | * reg offset mode reg bit ena reg | ||
56 | */ | ||
57 | MUX_CFG("UART1_TX", 9, 21, 1, 2, 3, 0, NA, 0, 0) | ||
58 | MUX_CFG("UART1_RTS", 9, 12, 1, 2, 0, 0, NA, 0, 0) | ||
59 | |||
60 | /* UART2 (COM_UART_GATING), conflicts with USB2 */ | ||
61 | MUX_CFG("UART2_TX", C, 27, 1, 3, 3, 0, NA, 0, 0) | ||
62 | MUX_CFG("UART2_RX", C, 18, 0, 3, 1, 1, NA, 0, 0) | ||
63 | MUX_CFG("UART2_CTS", C, 21, 0, 3, 1, 1, NA, 0, 0) | ||
64 | MUX_CFG("UART2_RTS", C, 24, 1, 3, 2, 0, NA, 0, 0) | ||
65 | |||
66 | /* UART3 (GIGA_UART_GATING) */ | ||
67 | MUX_CFG("UART3_TX", 6, 0, 1, 0, 30, 0, NA, 0, 0) | ||
68 | MUX_CFG("UART3_RX", 6, 3, 0, 0, 31, 1, NA, 0, 0) | ||
69 | MUX_CFG("UART3_CTS", 5, 12, 2, 0, 24, 0, NA, 0, 0) | ||
70 | MUX_CFG("UART3_RTS", 5, 15, 2, 0, 25, 0, NA, 0, 0) | ||
71 | MUX_CFG("UART3_CLKREQ", 9, 27, 0, 2, 5, 0, NA, 0, 0) | ||
72 | MUX_CFG("UART3_BCLK", A, 0, 0, 2, 6, 0, NA, 0, 0) | ||
73 | MUX_CFG("Y15_1610_UART3_RTS", A, 0, 1, 2, 6, 0, NA, 0, 0) | ||
74 | |||
75 | /* PWT & PWL, conflicts with UART3 */ | ||
76 | MUX_CFG("PWT", 6, 0, 2, 0, 30, 0, NA, 0, 0) | ||
77 | MUX_CFG("PWL", 6, 3, 1, 0, 31, 1, NA, 0, 0) | ||
78 | |||
79 | /* USB internal master generic */ | ||
80 | MUX_CFG("R18_USB_VBUS", 7, 9, 2, 1, 11, 0, NA, 0, 1) | ||
81 | MUX_CFG("R18_1510_USB_GPIO0", 7, 9, 0, 1, 11, 1, NA, 0, 1) | ||
82 | /* works around erratum: W4_USB_PUEN and W4_USB_PUDIS are switched! */ | ||
83 | MUX_CFG("W4_USB_PUEN", D, 3, 3, 3, 5, 1, NA, 0, 1) | ||
84 | MUX_CFG("W4_USB_CLKO", D, 3, 1, 3, 5, 0, NA, 0, 1) | ||
85 | MUX_CFG("W4_USB_HIGHZ", D, 3, 4, 3, 5, 0, 3, 0, 1) | ||
86 | MUX_CFG("W4_GPIO58", D, 3, 7, 3, 5, 0, 3, 0, 1) | ||
87 | |||
88 | /* USB1 master */ | ||
89 | MUX_CFG("USB1_SUSP", 8, 27, 2, 1, 27, 0, NA, 0, 1) | ||
90 | MUX_CFG("USB1_SE0", 9, 0, 2, 1, 28, 0, NA, 0, 1) | ||
91 | MUX_CFG("W13_1610_USB1_SE0", 9, 0, 4, 1, 28, 0, NA, 0, 1) | ||
92 | MUX_CFG("USB1_TXEN", 9, 3, 2, 1, 29, 0, NA, 0, 1) | ||
93 | MUX_CFG("USB1_TXD", 9, 24, 1, 2, 4, 0, NA, 0, 1) | ||
94 | MUX_CFG("USB1_VP", A, 3, 1, 2, 7, 0, NA, 0, 1) | ||
95 | MUX_CFG("USB1_VM", A, 6, 1, 2, 8, 0, NA, 0, 1) | ||
96 | MUX_CFG("USB1_RCV", A, 9, 1, 2, 9, 0, NA, 0, 1) | ||
97 | MUX_CFG("USB1_SPEED", A, 12, 2, 2, 10, 0, NA, 0, 1) | ||
98 | MUX_CFG("R13_1610_USB1_SPEED", A, 12, 5, 2, 10, 0, NA, 0, 1) | ||
99 | MUX_CFG("R13_1710_USB1_SEO", A, 12, 5, 2, 10, 0, NA, 0, 1) | ||
100 | |||
101 | /* USB2 master */ | ||
102 | MUX_CFG("USB2_SUSP", B, 3, 1, 2, 17, 0, NA, 0, 1) | ||
103 | MUX_CFG("USB2_VP", B, 6, 1, 2, 18, 0, NA, 0, 1) | ||
104 | MUX_CFG("USB2_TXEN", B, 9, 1, 2, 19, 0, NA, 0, 1) | ||
105 | MUX_CFG("USB2_VM", C, 18, 1, 3, 0, 0, NA, 0, 1) | ||
106 | MUX_CFG("USB2_RCV", C, 21, 1, 3, 1, 0, NA, 0, 1) | ||
107 | MUX_CFG("USB2_SE0", C, 24, 2, 3, 2, 0, NA, 0, 1) | ||
108 | MUX_CFG("USB2_TXD", C, 27, 2, 3, 3, 0, NA, 0, 1) | ||
109 | |||
110 | /* OMAP-1510 GPIO */ | ||
111 | MUX_CFG("R18_1510_GPIO0", 7, 9, 0, 1, 11, 1, 0, 0, 1) | ||
112 | MUX_CFG("R19_1510_GPIO1", 7, 6, 0, 1, 10, 1, 0, 0, 1) | ||
113 | MUX_CFG("M14_1510_GPIO2", 7, 3, 0, 1, 9, 1, 0, 0, 1) | ||
114 | |||
115 | /* OMAP1610 GPIO */ | ||
116 | MUX_CFG("P18_1610_GPIO3", 7, 0, 0, 1, 8, 0, NA, 0, 1) | ||
117 | MUX_CFG("Y15_1610_GPIO17", A, 0, 7, 2, 6, 0, NA, 0, 1) | ||
118 | |||
119 | /* OMAP-1710 GPIO */ | ||
120 | MUX_CFG("R18_1710_GPIO0", 7, 9, 0, 1, 11, 1, 1, 1, 1) | ||
121 | MUX_CFG("V2_1710_GPIO10", F, 27, 1, 4, 3, 1, 4, 1, 1) | ||
122 | MUX_CFG("N21_1710_GPIO14", 6, 9, 0, 1, 1, 1, 1, 1, 1) | ||
123 | MUX_CFG("W15_1710_GPIO40", 9, 27, 7, 2, 5, 1, 2, 1, 1) | ||
124 | |||
125 | /* MPUIO */ | ||
126 | MUX_CFG("MPUIO2", 7, 18, 0, 1, 14, 1, NA, 0, 1) | ||
127 | MUX_CFG("N15_1610_MPUIO2", 7, 18, 0, 1, 14, 1, 1, 0, 1) | ||
128 | MUX_CFG("MPUIO4", 7, 15, 0, 1, 13, 1, NA, 0, 1) | ||
129 | MUX_CFG("MPUIO5", 7, 12, 0, 1, 12, 1, NA, 0, 1) | ||
130 | |||
131 | MUX_CFG("T20_1610_MPUIO5", 7, 12, 0, 1, 12, 0, 3, 0, 1) | ||
132 | MUX_CFG("W11_1610_MPUIO6", 10, 15, 2, 3, 8, 0, 3, 0, 1) | ||
133 | MUX_CFG("V10_1610_MPUIO7", A, 24, 2, 2, 14, 0, 2, 0, 1) | ||
134 | MUX_CFG("W11_1610_MPUIO9", 10, 15, 1, 3, 8, 0, 3, 0, 1) | ||
135 | MUX_CFG("V10_1610_MPUIO10", A, 24, 1, 2, 14, 0, 2, 0, 1) | ||
136 | MUX_CFG("W10_1610_MPUIO11", A, 18, 2, 2, 11, 0, 2, 0, 1) | ||
137 | MUX_CFG("E20_1610_MPUIO13", 3, 21, 1, 0, 7, 0, 0, 0, 1) | ||
138 | MUX_CFG("U20_1610_MPUIO14", 9, 6, 6, 0, 30, 0, 0, 0, 1) | ||
139 | MUX_CFG("E19_1610_MPUIO15", 3, 18, 1, 0, 6, 0, 0, 0, 1) | ||
140 | |||
141 | /* MCBSP2 */ | ||
142 | MUX_CFG("MCBSP2_CLKR", C, 6, 0, 2, 27, 1, NA, 0, 1) | ||
143 | MUX_CFG("MCBSP2_CLKX", C, 9, 0, 2, 29, 1, NA, 0, 1) | ||
144 | MUX_CFG("MCBSP2_DR", C, 0, 0, 2, 26, 1, NA, 0, 1) | ||
145 | MUX_CFG("MCBSP2_DX", C, 15, 0, 2, 31, 1, NA, 0, 1) | ||
146 | MUX_CFG("MCBSP2_FSR", C, 12, 0, 2, 30, 1, NA, 0, 1) | ||
147 | MUX_CFG("MCBSP2_FSX", C, 3, 0, 2, 27, 1, NA, 0, 1) | ||
148 | |||
149 | /* MCBSP3 NOTE: Mode must 1 for clock */ | ||
150 | MUX_CFG("MCBSP3_CLKX", 9, 3, 1, 1, 29, 0, NA, 0, 1) | ||
151 | |||
152 | /* Misc ballouts */ | ||
153 | MUX_CFG("BALLOUT_V8_ARMIO3", B, 18, 0, 2, 25, 1, NA, 0, 1) | ||
154 | MUX_CFG("N20_HDQ", 6, 18, 1, 1, 4, 0, 1, 4, 0) | ||
155 | |||
156 | /* OMAP-1610 MMC2 */ | ||
157 | MUX_CFG("W8_1610_MMC2_DAT0", B, 21, 6, 2, 23, 1, 2, 1, 1) | ||
158 | MUX_CFG("V8_1610_MMC2_DAT1", B, 27, 6, 2, 25, 1, 2, 1, 1) | ||
159 | MUX_CFG("W15_1610_MMC2_DAT2", 9, 12, 6, 2, 5, 1, 2, 1, 1) | ||
160 | MUX_CFG("R10_1610_MMC2_DAT3", B, 18, 6, 2, 22, 1, 2, 1, 1) | ||
161 | MUX_CFG("Y10_1610_MMC2_CLK", B, 3, 6, 2, 17, 0, 2, 0, 1) | ||
162 | MUX_CFG("Y8_1610_MMC2_CMD", B, 24, 6, 2, 24, 1, 2, 1, 1) | ||
163 | MUX_CFG("V9_1610_MMC2_CMDDIR", B, 12, 6, 2, 20, 0, 2, 1, 1) | ||
164 | MUX_CFG("V5_1610_MMC2_DATDIR0", B, 15, 6, 2, 21, 0, 2, 1, 1) | ||
165 | MUX_CFG("W19_1610_MMC2_DATDIR1", 8, 15, 6, 1, 23, 0, 1, 1, 1) | ||
166 | MUX_CFG("R18_1610_MMC2_CLKIN", 7, 9, 6, 1, 11, 0, 1, 11, 1) | ||
167 | |||
168 | /* OMAP-1610 External Trace Interface */ | ||
169 | MUX_CFG("M19_1610_ETM_PSTAT0", 5, 27, 1, 0, 29, 0, 0, 0, 1) | ||
170 | MUX_CFG("L15_1610_ETM_PSTAT1", 5, 24, 1, 0, 28, 0, 0, 0, 1) | ||
171 | MUX_CFG("L18_1610_ETM_PSTAT2", 5, 21, 1, 0, 27, 0, 0, 0, 1) | ||
172 | MUX_CFG("L19_1610_ETM_D0", 5, 18, 1, 0, 26, 0, 0, 0, 1) | ||
173 | MUX_CFG("J19_1610_ETM_D6", 5, 0, 1, 0, 20, 0, 0, 0, 1) | ||
174 | MUX_CFG("J18_1610_ETM_D7", 5, 27, 1, 0, 19, 0, 0, 0, 1) | ||
175 | |||
176 | /* OMAP16XX GPIO */ | ||
177 | MUX_CFG("P20_1610_GPIO4", 6, 27, 0, 1, 7, 0, 1, 1, 1) | ||
178 | MUX_CFG("V9_1610_GPIO7", B, 12, 1, 2, 20, 0, 2, 1, 1) | ||
179 | MUX_CFG("W8_1610_GPIO9", B, 21, 0, 2, 23, 0, 2, 1, 1) | ||
180 | MUX_CFG("N20_1610_GPIO11", 6, 18, 0, 1, 4, 0, 1, 1, 1) | ||
181 | MUX_CFG("N19_1610_GPIO13", 6, 12, 0, 1, 2, 0, 1, 1, 1) | ||
182 | MUX_CFG("P10_1610_GPIO22", C, 0, 7, 2, 26, 0, 2, 1, 1) | ||
183 | MUX_CFG("V5_1610_GPIO24", B, 15, 7, 2, 21, 0, 2, 1, 1) | ||
184 | MUX_CFG("AA20_1610_GPIO_41", 9, 9, 7, 1, 31, 0, 1, 1, 1) | ||
185 | MUX_CFG("W19_1610_GPIO48", 8, 15, 7, 1, 23, 1, 1, 0, 1) | ||
186 | MUX_CFG("M7_1610_GPIO62", 10, 0, 0, 4, 24, 0, 4, 0, 1) | ||
187 | MUX_CFG("V14_16XX_GPIO37", 9, 18, 7, 2, 2, 0, 2, 2, 0) | ||
188 | MUX_CFG("R9_16XX_GPIO18", C, 18, 7, 3, 0, 0, 3, 0, 0) | ||
189 | MUX_CFG("L14_16XX_GPIO49", 6, 3, 7, 0, 31, 0, 0, 31, 0) | ||
190 | |||
191 | /* OMAP-1610 uWire */ | ||
192 | MUX_CFG("V19_1610_UWIRE_SCLK", 8, 6, 0, 1, 20, 0, 1, 1, 1) | ||
193 | MUX_CFG("U18_1610_UWIRE_SDI", 8, 0, 0, 1, 18, 0, 1, 1, 1) | ||
194 | MUX_CFG("W21_1610_UWIRE_SDO", 8, 3, 0, 1, 19, 0, 1, 1, 1) | ||
195 | MUX_CFG("N14_1610_UWIRE_CS0", 8, 9, 1, 1, 21, 0, 1, 1, 1) | ||
196 | MUX_CFG("P15_1610_UWIRE_CS3", 8, 12, 1, 1, 22, 0, 1, 1, 1) | ||
197 | MUX_CFG("N15_1610_UWIRE_CS1", 7, 18, 2, 1, 14, 0, NA, 0, 1) | ||
198 | |||
199 | /* OMAP-1610 Flash */ | ||
200 | MUX_CFG("L3_1610_FLASH_CS2B_OE",10, 6, 1, NA, 0, 0, NA, 0, 1) | ||
201 | MUX_CFG("M8_1610_FLASH_CS2B_WE",10, 3, 1, NA, 0, 0, NA, 0, 1) | ||
202 | |||
203 | /* First MMC interface, same on 1510, 1610 and 1710 */ | ||
204 | MUX_CFG("MMC_CMD", A, 27, 0, 2, 15, 1, 2, 1, 1) | ||
205 | MUX_CFG("MMC_DAT1", A, 24, 0, 2, 14, 1, 2, 1, 1) | ||
206 | MUX_CFG("MMC_DAT2", A, 18, 0, 2, 12, 1, 2, 1, 1) | ||
207 | MUX_CFG("MMC_DAT0", B, 0, 0, 2, 16, 1, 2, 1, 1) | ||
208 | MUX_CFG("MMC_CLK", A, 21, 0, NA, 0, 0, NA, 0, 1) | ||
209 | MUX_CFG("MMC_DAT3", 10, 15, 0, 3, 8, 1, 3, 1, 1) | ||
210 | MUX_CFG("M15_1710_MMC_CLKI", 6, 21, 2, 0, 0, 0, NA, 0, 1) | ||
211 | MUX_CFG("P19_1710_MMC_CMDDIR", 6, 24, 6, 0, 0, 0, NA, 0, 1) | ||
212 | MUX_CFG("P20_1710_MMC_DATDIR0", 6, 27, 5, 0, 0, 0, NA, 0, 1) | ||
213 | |||
214 | /* OMAP-1610 USB0 alternate configuration */ | ||
215 | MUX_CFG("W9_USB0_TXEN", B, 9, 5, 2, 19, 0, 2, 0, 1) | ||
216 | MUX_CFG("AA9_USB0_VP", B, 6, 5, 2, 18, 0, 2, 0, 1) | ||
217 | MUX_CFG("Y5_USB0_RCV", C, 21, 5, 3, 1, 0, 1, 0, 1) | ||
218 | MUX_CFG("R9_USB0_VM", C, 18, 5, 3, 0, 0, 3, 0, 1) | ||
219 | MUX_CFG("V6_USB0_TXD", C, 27, 5, 3, 3, 0, 3, 0, 1) | ||
220 | MUX_CFG("W5_USB0_SE0", C, 24, 5, 3, 2, 0, 3, 0, 1) | ||
221 | MUX_CFG("V9_USB0_SPEED", B, 12, 5, 2, 20, 0, 2, 0, 1) | ||
222 | MUX_CFG("Y10_USB0_SUSP", B, 3, 5, 2, 17, 0, 2, 0, 1) | ||
223 | |||
224 | /* USB2 interface */ | ||
225 | MUX_CFG("W9_USB2_TXEN", B, 9, 1, NA, 0, 0, NA, 0, 1) | ||
226 | MUX_CFG("AA9_USB2_VP", B, 6, 1, NA, 0, 0, NA, 0, 1) | ||
227 | MUX_CFG("Y5_USB2_RCV", C, 21, 1, NA, 0, 0, NA, 0, 1) | ||
228 | MUX_CFG("R9_USB2_VM", C, 18, 1, NA, 0, 0, NA, 0, 1) | ||
229 | MUX_CFG("V6_USB2_TXD", C, 27, 2, NA, 0, 0, NA, 0, 1) | ||
230 | MUX_CFG("W5_USB2_SE0", C, 24, 2, NA, 0, 0, NA, 0, 1) | ||
231 | |||
232 | /* 16XX UART */ | ||
233 | MUX_CFG("R13_1610_UART1_TX", A, 12, 6, 2, 10, 0, 2, 10, 1) | ||
234 | MUX_CFG("V14_16XX_UART1_RX", 9, 18, 0, 2, 2, 0, 2, 2, 1) | ||
235 | MUX_CFG("R14_1610_UART1_CTS", 9, 15, 0, 2, 1, 0, 2, 1, 1) | ||
236 | MUX_CFG("AA15_1610_UART1_RTS", 9, 12, 1, 2, 0, 0, 2, 0, 1) | ||
237 | MUX_CFG("R9_16XX_UART2_RX", C, 18, 0, 3, 0, 0, 3, 0, 1) | ||
238 | MUX_CFG("L14_16XX_UART3_RX", 6, 3, 0, 0, 31, 0, 0, 31, 1) | ||
239 | |||
240 | /* I2C interface */ | ||
241 | MUX_CFG("I2C_SCL", 7, 24, 0, NA, 0, 0, NA, 0, 0) | ||
242 | MUX_CFG("I2C_SDA", 7, 27, 0, NA, 0, 0, NA, 0, 0) | ||
243 | |||
244 | /* Keypad */ | ||
245 | MUX_CFG("F18_1610_KBC0", 3, 15, 0, 0, 5, 1, 0, 0, 0) | ||
246 | MUX_CFG("D20_1610_KBC1", 3, 12, 0, 0, 4, 1, 0, 0, 0) | ||
247 | MUX_CFG("D19_1610_KBC2", 3, 9, 0, 0, 3, 1, 0, 0, 0) | ||
248 | MUX_CFG("E18_1610_KBC3", 3, 6, 0, 0, 2, 1, 0, 0, 0) | ||
249 | MUX_CFG("C21_1610_KBC4", 3, 3, 0, 0, 1, 1, 0, 0, 0) | ||
250 | MUX_CFG("G18_1610_KBR0", 4, 0, 0, 0, 10, 1, 0, 1, 0) | ||
251 | MUX_CFG("F19_1610_KBR1", 3, 27, 0, 0, 9, 1, 0, 1, 0) | ||
252 | MUX_CFG("H14_1610_KBR2", 3, 24, 0, 0, 8, 1, 0, 1, 0) | ||
253 | MUX_CFG("E20_1610_KBR3", 3, 21, 0, 0, 7, 1, 0, 1, 0) | ||
254 | MUX_CFG("E19_1610_KBR4", 3, 18, 0, 0, 6, 1, 0, 1, 0) | ||
255 | MUX_CFG("N19_1610_KBR5", 6, 12, 1, 1, 2, 1, 1, 1, 0) | ||
256 | |||
257 | /* Power management */ | ||
258 | MUX_CFG("T20_1610_LOW_PWR", 7, 12, 1, NA, 0, 0, NA, 0, 0) | ||
259 | |||
260 | /* MCLK Settings */ | ||
261 | MUX_CFG("V5_1710_MCLK_ON", B, 15, 0, NA, 0, 0, NA, 0, 0) | ||
262 | MUX_CFG("V5_1710_MCLK_OFF", B, 15, 6, NA, 0, 0, NA, 0, 0) | ||
263 | MUX_CFG("R10_1610_MCLK_ON", B, 18, 0, NA, 22, 0, NA, 1, 0) | ||
264 | MUX_CFG("R10_1610_MCLK_OFF", B, 18, 6, 2, 22, 1, 2, 1, 1) | ||
265 | |||
266 | /* CompactFlash controller, conflicts with MMC1 */ | ||
267 | MUX_CFG("P11_1610_CF_CD2", A, 27, 3, 2, 15, 1, 2, 1, 1) | ||
268 | MUX_CFG("R11_1610_CF_IOIS16", B, 0, 3, 2, 16, 1, 2, 1, 1) | ||
269 | MUX_CFG("V10_1610_CF_IREQ", A, 24, 3, 2, 14, 0, 2, 0, 1) | ||
270 | MUX_CFG("W10_1610_CF_RESET", A, 18, 3, 2, 12, 1, 2, 1, 1) | ||
271 | MUX_CFG("W11_1610_CF_CD1", 10, 15, 3, 3, 8, 1, 3, 1, 1) | ||
272 | }; | ||
273 | #endif /* CONFIG_ARCH_OMAP15XX || CONFIG_ARCH_OMAP16XX */ | ||
274 | |||
275 | int __init omap1_mux_init(void) | ||
276 | { | ||
277 | |||
278 | #ifdef CONFIG_ARCH_OMAP730 | ||
279 | omap_mux_register(omap730_pins, ARRAY_SIZE(omap730_pins)); | ||
280 | #endif | ||
281 | |||
282 | #if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX) | ||
283 | omap_mux_register(omap1xxx_pins, ARRAY_SIZE(omap1xxx_pins)); | ||
284 | #endif | ||
285 | |||
286 | return 0; | ||
287 | } | ||
288 | |||
289 | #endif | ||
diff --git a/arch/arm/mach-omap1/serial.c b/arch/arm/mach-omap1/serial.c index 40c4f7c40e73..6810cfb84462 100644 --- a/arch/arm/mach-omap1/serial.c +++ b/arch/arm/mach-omap1/serial.c | |||
@@ -109,9 +109,10 @@ static struct platform_device serial_device = { | |||
109 | * By default UART2 does not work on Innovator-1510 if you have | 109 | * By default UART2 does not work on Innovator-1510 if you have |
110 | * USB OHCI enabled. To use UART2, you must disable USB2 first. | 110 | * USB OHCI enabled. To use UART2, you must disable USB2 first. |
111 | */ | 111 | */ |
112 | void __init omap_serial_init(int ports[OMAP_MAX_NR_PORTS]) | 112 | void __init omap_serial_init(void) |
113 | { | 113 | { |
114 | int i; | 114 | int i; |
115 | const struct omap_uart_config *info; | ||
115 | 116 | ||
116 | if (cpu_is_omap730()) { | 117 | if (cpu_is_omap730()) { |
117 | serial_platform_data[0].regshift = 0; | 118 | serial_platform_data[0].regshift = 0; |
@@ -126,10 +127,14 @@ void __init omap_serial_init(int ports[OMAP_MAX_NR_PORTS]) | |||
126 | serial_platform_data[2].uartclk = OMAP1510_BASE_BAUD * 16; | 127 | serial_platform_data[2].uartclk = OMAP1510_BASE_BAUD * 16; |
127 | } | 128 | } |
128 | 129 | ||
130 | info = omap_get_config(OMAP_TAG_UART, struct omap_uart_config); | ||
131 | if (info == NULL) | ||
132 | return; | ||
133 | |||
129 | for (i = 0; i < OMAP_MAX_NR_PORTS; i++) { | 134 | for (i = 0; i < OMAP_MAX_NR_PORTS; i++) { |
130 | unsigned char reg; | 135 | unsigned char reg; |
131 | 136 | ||
132 | if (ports[i] == 0) { | 137 | if (!((1 << i) & info->enabled_uarts)) { |
133 | serial_platform_data[i].membase = NULL; | 138 | serial_platform_data[i].membase = NULL; |
134 | serial_platform_data[i].mapbase = 0; | 139 | serial_platform_data[i].mapbase = 0; |
135 | continue; | 140 | continue; |
diff --git a/arch/arm/mach-omap1/time.c b/arch/arm/mach-omap1/time.c index 191a9b1ee9b7..cdbf4d7620c6 100644 --- a/arch/arm/mach-omap1/time.c +++ b/arch/arm/mach-omap1/time.c | |||
@@ -226,8 +226,8 @@ unsigned long long sched_clock(void) | |||
226 | 226 | ||
227 | #ifdef CONFIG_OMAP_32K_TIMER | 227 | #ifdef CONFIG_OMAP_32K_TIMER |
228 | 228 | ||
229 | #ifdef CONFIG_ARCH_OMAP1510 | 229 | #ifdef CONFIG_ARCH_OMAP15XX |
230 | #error OMAP 32KHz timer does not currently work on 1510! | 230 | #error OMAP 32KHz timer does not currently work on 15XX! |
231 | #endif | 231 | #endif |
232 | 232 | ||
233 | /* | 233 | /* |
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig new file mode 100644 index 000000000000..578880943cf2 --- /dev/null +++ b/arch/arm/mach-omap2/Kconfig | |||
@@ -0,0 +1,22 @@ | |||
1 | comment "OMAP Core Type" | ||
2 | depends on ARCH_OMAP2 | ||
3 | |||
4 | config ARCH_OMAP24XX | ||
5 | bool "OMAP24xx Based System" | ||
6 | depends on ARCH_OMAP2 | ||
7 | |||
8 | config ARCH_OMAP2420 | ||
9 | bool "OMAP2420 support" | ||
10 | depends on ARCH_OMAP24XX | ||
11 | |||
12 | comment "OMAP Board Type" | ||
13 | depends on ARCH_OMAP2 | ||
14 | |||
15 | config MACH_OMAP_GENERIC | ||
16 | bool "Generic OMAP board" | ||
17 | depends on ARCH_OMAP2 && ARCH_OMAP24XX | ||
18 | |||
19 | config MACH_OMAP_H4 | ||
20 | bool "OMAP 2420 H4 board" | ||
21 | depends on ARCH_OMAP2 && ARCH_OMAP24XX | ||
22 | |||
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile new file mode 100644 index 000000000000..42041166435c --- /dev/null +++ b/arch/arm/mach-omap2/Makefile | |||
@@ -0,0 +1,13 @@ | |||
1 | # | ||
2 | # Makefile for the linux kernel. | ||
3 | # | ||
4 | |||
5 | # Common support | ||
6 | obj-y := irq.o id.o io.o sram-fn.o clock.o mux.o devices.o serial.o | ||
7 | |||
8 | obj-$(CONFIG_OMAP_MPU_TIMER) += timer-gp.o | ||
9 | |||
10 | # Specific board support | ||
11 | obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o | ||
12 | obj-$(CONFIG_MACH_OMAP_H4) += board-h4.o | ||
13 | |||
diff --git a/arch/arm/mach-omap2/Makefile.boot b/arch/arm/mach-omap2/Makefile.boot new file mode 100644 index 000000000000..565aff7f37a9 --- /dev/null +++ b/arch/arm/mach-omap2/Makefile.boot | |||
@@ -0,0 +1,3 @@ | |||
1 | zreladdr-y := 0x80008000 | ||
2 | params_phys-y := 0x80000100 | ||
3 | initrd_phys-y := 0x80800000 | ||
diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c new file mode 100644 index 000000000000..c602e7a3d93e --- /dev/null +++ b/arch/arm/mach-omap2/board-generic.c | |||
@@ -0,0 +1,80 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-omap/omap2/board-generic.c | ||
3 | * | ||
4 | * Copyright (C) 2005 Nokia Corporation | ||
5 | * Author: Paul Mundt <paul.mundt@nokia.com> | ||
6 | * | ||
7 | * Modified from mach-omap/omap1/board-generic.c | ||
8 | * | ||
9 | * Code for generic OMAP2 board. Should work on many OMAP2 systems where | ||
10 | * the bootloader passes the board-specific data to the kernel. | ||
11 | * Do not put any board specific code to this file; create a new machine | ||
12 | * type if you need custom low-level initializations. | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify | ||
15 | * it under the terms of the GNU General Public License version 2 as | ||
16 | * published by the Free Software Foundation. | ||
17 | */ | ||
18 | |||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/device.h> | ||
22 | |||
23 | #include <asm/hardware.h> | ||
24 | #include <asm/mach-types.h> | ||
25 | #include <asm/mach/arch.h> | ||
26 | #include <asm/mach/map.h> | ||
27 | |||
28 | #include <asm/arch/gpio.h> | ||
29 | #include <asm/arch/mux.h> | ||
30 | #include <asm/arch/usb.h> | ||
31 | #include <asm/arch/board.h> | ||
32 | #include <asm/arch/common.h> | ||
33 | |||
34 | static void __init omap_generic_init_irq(void) | ||
35 | { | ||
36 | omap_init_irq(); | ||
37 | } | ||
38 | |||
39 | static struct omap_uart_config generic_uart_config __initdata = { | ||
40 | .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)), | ||
41 | }; | ||
42 | |||
43 | static struct omap_mmc_config generic_mmc_config __initdata = { | ||
44 | .mmc [0] = { | ||
45 | .enabled = 0, | ||
46 | .wire4 = 0, | ||
47 | .wp_pin = -1, | ||
48 | .power_pin = -1, | ||
49 | .switch_pin = -1, | ||
50 | }, | ||
51 | }; | ||
52 | |||
53 | static struct omap_board_config_kernel generic_config[] = { | ||
54 | { OMAP_TAG_UART, &generic_uart_config }, | ||
55 | { OMAP_TAG_MMC, &generic_mmc_config }, | ||
56 | }; | ||
57 | |||
58 | static void __init omap_generic_init(void) | ||
59 | { | ||
60 | omap_board_config = generic_config; | ||
61 | omap_board_config_size = ARRAY_SIZE(generic_config); | ||
62 | omap_serial_init(); | ||
63 | } | ||
64 | |||
65 | static void __init omap_generic_map_io(void) | ||
66 | { | ||
67 | omap_map_common_io(); | ||
68 | } | ||
69 | |||
70 | MACHINE_START(OMAP_GENERIC, "Generic OMAP24xx") | ||
71 | /* Maintainer: Paul Mundt <paul.mundt@nokia.com> */ | ||
72 | .phys_ram = 0x80000000, | ||
73 | .phys_io = 0x48000000, | ||
74 | .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc, | ||
75 | .boot_params = 0x80000100, | ||
76 | .map_io = omap_generic_map_io, | ||
77 | .init_irq = omap_generic_init_irq, | ||
78 | .init_machine = omap_generic_init, | ||
79 | .timer = &omap_timer, | ||
80 | MACHINE_END | ||
diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c new file mode 100644 index 000000000000..f2554469a76a --- /dev/null +++ b/arch/arm/mach-omap2/board-h4.c | |||
@@ -0,0 +1,197 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-omap/omap2/board-h4.c | ||
3 | * | ||
4 | * Copyright (C) 2005 Nokia Corporation | ||
5 | * Author: Paul Mundt <paul.mundt@nokia.com> | ||
6 | * | ||
7 | * Modified from mach-omap/omap1/board-generic.c | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | #include <linux/mtd/mtd.h> | ||
18 | #include <linux/mtd/partitions.h> | ||
19 | #include <linux/delay.h> | ||
20 | |||
21 | #include <asm/hardware.h> | ||
22 | #include <asm/mach-types.h> | ||
23 | #include <asm/mach/arch.h> | ||
24 | #include <asm/mach/map.h> | ||
25 | #include <asm/mach/flash.h> | ||
26 | |||
27 | #include <asm/arch/gpio.h> | ||
28 | #include <asm/arch/mux.h> | ||
29 | #include <asm/arch/usb.h> | ||
30 | #include <asm/arch/board.h> | ||
31 | #include <asm/arch/common.h> | ||
32 | #include <asm/arch/prcm.h> | ||
33 | |||
34 | #include <asm/io.h> | ||
35 | #include <asm/delay.h> | ||
36 | |||
37 | static struct mtd_partition h4_partitions[] = { | ||
38 | /* bootloader (U-Boot, etc) in first sector */ | ||
39 | { | ||
40 | .name = "bootloader", | ||
41 | .offset = 0, | ||
42 | .size = SZ_128K, | ||
43 | .mask_flags = MTD_WRITEABLE, /* force read-only */ | ||
44 | }, | ||
45 | /* bootloader params in the next sector */ | ||
46 | { | ||
47 | .name = "params", | ||
48 | .offset = MTDPART_OFS_APPEND, | ||
49 | .size = SZ_128K, | ||
50 | .mask_flags = 0, | ||
51 | }, | ||
52 | /* kernel */ | ||
53 | { | ||
54 | .name = "kernel", | ||
55 | .offset = MTDPART_OFS_APPEND, | ||
56 | .size = SZ_2M, | ||
57 | .mask_flags = 0 | ||
58 | }, | ||
59 | /* file system */ | ||
60 | { | ||
61 | .name = "filesystem", | ||
62 | .offset = MTDPART_OFS_APPEND, | ||
63 | .size = MTDPART_SIZ_FULL, | ||
64 | .mask_flags = 0 | ||
65 | } | ||
66 | }; | ||
67 | |||
68 | static struct flash_platform_data h4_flash_data = { | ||
69 | .map_name = "cfi_probe", | ||
70 | .width = 2, | ||
71 | .parts = h4_partitions, | ||
72 | .nr_parts = ARRAY_SIZE(h4_partitions), | ||
73 | }; | ||
74 | |||
75 | static struct resource h4_flash_resource = { | ||
76 | .start = H4_CS0_BASE, | ||
77 | .end = H4_CS0_BASE + SZ_64M - 1, | ||
78 | .flags = IORESOURCE_MEM, | ||
79 | }; | ||
80 | |||
81 | static struct platform_device h4_flash_device = { | ||
82 | .name = "omapflash", | ||
83 | .id = 0, | ||
84 | .dev = { | ||
85 | .platform_data = &h4_flash_data, | ||
86 | }, | ||
87 | .num_resources = 1, | ||
88 | .resource = &h4_flash_resource, | ||
89 | }; | ||
90 | |||
91 | static struct resource h4_smc91x_resources[] = { | ||
92 | [0] = { | ||
93 | .start = OMAP24XX_ETHR_START, /* Physical */ | ||
94 | .end = OMAP24XX_ETHR_START + 0xf, | ||
95 | .flags = IORESOURCE_MEM, | ||
96 | }, | ||
97 | [1] = { | ||
98 | .start = OMAP_GPIO_IRQ(OMAP24XX_ETHR_GPIO_IRQ), | ||
99 | .end = OMAP_GPIO_IRQ(OMAP24XX_ETHR_GPIO_IRQ), | ||
100 | .flags = IORESOURCE_IRQ, | ||
101 | }, | ||
102 | }; | ||
103 | |||
104 | static struct platform_device h4_smc91x_device = { | ||
105 | .name = "smc91x", | ||
106 | .id = -1, | ||
107 | .num_resources = ARRAY_SIZE(h4_smc91x_resources), | ||
108 | .resource = h4_smc91x_resources, | ||
109 | }; | ||
110 | |||
111 | static struct platform_device *h4_devices[] __initdata = { | ||
112 | &h4_smc91x_device, | ||
113 | &h4_flash_device, | ||
114 | }; | ||
115 | |||
116 | static inline void __init h4_init_smc91x(void) | ||
117 | { | ||
118 | /* Make sure CS1 timings are correct */ | ||
119 | GPMC_CONFIG1_1 = 0x00011200; | ||
120 | GPMC_CONFIG2_1 = 0x001f1f01; | ||
121 | GPMC_CONFIG3_1 = 0x00080803; | ||
122 | GPMC_CONFIG4_1 = 0x1c091c09; | ||
123 | GPMC_CONFIG5_1 = 0x041f1f1f; | ||
124 | GPMC_CONFIG6_1 = 0x000004c4; | ||
125 | GPMC_CONFIG7_1 = 0x00000f40 | (0x08000000 >> 24); | ||
126 | udelay(100); | ||
127 | |||
128 | omap_cfg_reg(M15_24XX_GPIO92); | ||
129 | if (omap_request_gpio(OMAP24XX_ETHR_GPIO_IRQ) < 0) { | ||
130 | printk(KERN_ERR "Failed to request GPIO%d for smc91x IRQ\n", | ||
131 | OMAP24XX_ETHR_GPIO_IRQ); | ||
132 | return; | ||
133 | } | ||
134 | omap_set_gpio_direction(OMAP24XX_ETHR_GPIO_IRQ, 1); | ||
135 | } | ||
136 | |||
137 | static void __init omap_h4_init_irq(void) | ||
138 | { | ||
139 | omap_init_irq(); | ||
140 | omap_gpio_init(); | ||
141 | h4_init_smc91x(); | ||
142 | } | ||
143 | |||
144 | static struct omap_uart_config h4_uart_config __initdata = { | ||
145 | .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)), | ||
146 | }; | ||
147 | |||
148 | static struct omap_mmc_config h4_mmc_config __initdata = { | ||
149 | .mmc [0] = { | ||
150 | .enabled = 1, | ||
151 | .wire4 = 1, | ||
152 | .wp_pin = -1, | ||
153 | .power_pin = -1, | ||
154 | .switch_pin = -1, | ||
155 | }, | ||
156 | }; | ||
157 | |||
158 | static struct omap_lcd_config h4_lcd_config __initdata = { | ||
159 | .panel_name = "h4", | ||
160 | .ctrl_name = "internal", | ||
161 | }; | ||
162 | |||
163 | static struct omap_board_config_kernel h4_config[] = { | ||
164 | { OMAP_TAG_UART, &h4_uart_config }, | ||
165 | { OMAP_TAG_MMC, &h4_mmc_config }, | ||
166 | { OMAP_TAG_LCD, &h4_lcd_config }, | ||
167 | }; | ||
168 | |||
169 | static void __init omap_h4_init(void) | ||
170 | { | ||
171 | /* | ||
172 | * Make sure the serial ports are muxed on at this point. | ||
173 | * You have to mux them off in device drivers later on | ||
174 | * if not needed. | ||
175 | */ | ||
176 | platform_add_devices(h4_devices, ARRAY_SIZE(h4_devices)); | ||
177 | omap_board_config = h4_config; | ||
178 | omap_board_config_size = ARRAY_SIZE(h4_config); | ||
179 | omap_serial_init(); | ||
180 | } | ||
181 | |||
182 | static void __init omap_h4_map_io(void) | ||
183 | { | ||
184 | omap_map_common_io(); | ||
185 | } | ||
186 | |||
187 | MACHINE_START(OMAP_H4, "OMAP2420 H4 board") | ||
188 | /* Maintainer: Paul Mundt <paul.mundt@nokia.com> */ | ||
189 | .phys_ram = 0x80000000, | ||
190 | .phys_io = 0x48000000, | ||
191 | .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc, | ||
192 | .boot_params = 0x80000100, | ||
193 | .map_io = omap_h4_map_io, | ||
194 | .init_irq = omap_h4_init_irq, | ||
195 | .init_machine = omap_h4_init, | ||
196 | .timer = &omap_timer, | ||
197 | MACHINE_END | ||
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c new file mode 100644 index 000000000000..85818d9f2635 --- /dev/null +++ b/arch/arm/mach-omap2/clock.c | |||
@@ -0,0 +1,1129 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-omap2/clock.c | ||
3 | * | ||
4 | * Copyright (C) 2005 Texas Instruments Inc. | ||
5 | * Richard Woodruff <r-woodruff2@ti.com> | ||
6 | * Created for OMAP2. | ||
7 | * | ||
8 | * Cleaned up and modified to use omap shared clock framework by | ||
9 | * Tony Lindgren <tony@atomide.com> | ||
10 | * | ||
11 | * Based on omap1 clock.c, Copyright (C) 2004 - 2005 Nokia corporation | ||
12 | * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com> | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify | ||
15 | * it under the terms of the GNU General Public License version 2 as | ||
16 | * published by the Free Software Foundation. | ||
17 | */ | ||
18 | #include <linux/config.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/device.h> | ||
22 | #include <linux/list.h> | ||
23 | #include <linux/errno.h> | ||
24 | #include <linux/delay.h> | ||
25 | |||
26 | #include <asm/io.h> | ||
27 | |||
28 | #include <asm/hardware/clock.h> | ||
29 | #include <asm/arch/clock.h> | ||
30 | #include <asm/arch/sram.h> | ||
31 | #include <asm/arch/prcm.h> | ||
32 | |||
33 | #include "clock.h" | ||
34 | |||
35 | //#define DOWN_VARIABLE_DPLL 1 /* Experimental */ | ||
36 | |||
37 | static struct prcm_config *curr_prcm_set; | ||
38 | static struct memory_timings mem_timings; | ||
39 | static u32 curr_perf_level = PRCM_FULL_SPEED; | ||
40 | |||
41 | /*------------------------------------------------------------------------- | ||
42 | * Omap2 specific clock functions | ||
43 | *-------------------------------------------------------------------------*/ | ||
44 | |||
45 | /* Recalculate SYST_CLK */ | ||
46 | static void omap2_sys_clk_recalc(struct clk * clk) | ||
47 | { | ||
48 | u32 div = PRCM_CLKSRC_CTRL; | ||
49 | div &= (1 << 7) | (1 << 6); /* Test if ext clk divided by 1 or 2 */ | ||
50 | div >>= clk->rate_offset; | ||
51 | clk->rate = (clk->parent->rate / div); | ||
52 | propagate_rate(clk); | ||
53 | } | ||
54 | |||
55 | static u32 omap2_get_dpll_rate(struct clk * tclk) | ||
56 | { | ||
57 | int dpll_clk, dpll_mult, dpll_div, amult; | ||
58 | |||
59 | dpll_mult = (CM_CLKSEL1_PLL >> 12) & 0x03ff; /* 10 bits */ | ||
60 | dpll_div = (CM_CLKSEL1_PLL >> 8) & 0x0f; /* 4 bits */ | ||
61 | dpll_clk = (tclk->parent->rate * dpll_mult) / (dpll_div + 1); | ||
62 | amult = CM_CLKSEL2_PLL & 0x3; | ||
63 | dpll_clk *= amult; | ||
64 | |||
65 | return dpll_clk; | ||
66 | } | ||
67 | |||
68 | static void omap2_followparent_recalc(struct clk *clk) | ||
69 | { | ||
70 | followparent_recalc(clk); | ||
71 | } | ||
72 | |||
73 | static void omap2_propagate_rate(struct clk * clk) | ||
74 | { | ||
75 | if (!(clk->flags & RATE_FIXED)) | ||
76 | clk->rate = clk->parent->rate; | ||
77 | |||
78 | propagate_rate(clk); | ||
79 | } | ||
80 | |||
81 | /* Enable an APLL if off */ | ||
82 | static void omap2_clk_fixed_enable(struct clk *clk) | ||
83 | { | ||
84 | u32 cval, i=0; | ||
85 | |||
86 | if (clk->enable_bit == 0xff) /* Parent will do it */ | ||
87 | return; | ||
88 | |||
89 | cval = CM_CLKEN_PLL; | ||
90 | |||
91 | if ((cval & (0x3 << clk->enable_bit)) == (0x3 << clk->enable_bit)) | ||
92 | return; | ||
93 | |||
94 | cval &= ~(0x3 << clk->enable_bit); | ||
95 | cval |= (0x3 << clk->enable_bit); | ||
96 | CM_CLKEN_PLL = cval; | ||
97 | |||
98 | if (clk == &apll96_ck) | ||
99 | cval = (1 << 8); | ||
100 | else if (clk == &apll54_ck) | ||
101 | cval = (1 << 6); | ||
102 | |||
103 | while (!CM_IDLEST_CKGEN & cval) { /* Wait for lock */ | ||
104 | ++i; | ||
105 | udelay(1); | ||
106 | if (i == 100000) | ||
107 | break; | ||
108 | } | ||
109 | } | ||
110 | |||
111 | /* Enables clock without considering parent dependencies or use count | ||
112 | * REVISIT: Maybe change this to use clk->enable like on omap1? | ||
113 | */ | ||
114 | static int omap2_clk_enable(struct clk * clk) | ||
115 | { | ||
116 | u32 regval32; | ||
117 | |||
118 | if (clk->flags & ALWAYS_ENABLED) | ||
119 | return 0; | ||
120 | |||
121 | if (unlikely(clk->enable_reg == 0)) { | ||
122 | printk(KERN_ERR "clock.c: Enable for %s without enable code\n", | ||
123 | clk->name); | ||
124 | return 0; | ||
125 | } | ||
126 | |||
127 | if (clk->enable_reg == (void __iomem *)&CM_CLKEN_PLL) { | ||
128 | omap2_clk_fixed_enable(clk); | ||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | regval32 = __raw_readl(clk->enable_reg); | ||
133 | regval32 |= (1 << clk->enable_bit); | ||
134 | __raw_writel(regval32, clk->enable_reg); | ||
135 | |||
136 | return 0; | ||
137 | } | ||
138 | |||
139 | /* Stop APLL */ | ||
140 | static void omap2_clk_fixed_disable(struct clk *clk) | ||
141 | { | ||
142 | u32 cval; | ||
143 | |||
144 | if(clk->enable_bit == 0xff) /* let parent off do it */ | ||
145 | return; | ||
146 | |||
147 | cval = CM_CLKEN_PLL; | ||
148 | cval &= ~(0x3 << clk->enable_bit); | ||
149 | CM_CLKEN_PLL = cval; | ||
150 | } | ||
151 | |||
152 | /* Disables clock without considering parent dependencies or use count */ | ||
153 | static void omap2_clk_disable(struct clk *clk) | ||
154 | { | ||
155 | u32 regval32; | ||
156 | |||
157 | if (clk->enable_reg == 0) | ||
158 | return; | ||
159 | |||
160 | if (clk->enable_reg == (void __iomem *)&CM_CLKEN_PLL) { | ||
161 | omap2_clk_fixed_disable(clk); | ||
162 | return; | ||
163 | } | ||
164 | |||
165 | regval32 = __raw_readl(clk->enable_reg); | ||
166 | regval32 &= ~(1 << clk->enable_bit); | ||
167 | __raw_writel(regval32, clk->enable_reg); | ||
168 | } | ||
169 | |||
170 | static int omap2_clk_use(struct clk *clk) | ||
171 | { | ||
172 | int ret = 0; | ||
173 | |||
174 | if (clk->usecount++ == 0) { | ||
175 | if (likely((u32)clk->parent)) | ||
176 | ret = omap2_clk_use(clk->parent); | ||
177 | |||
178 | if (unlikely(ret != 0)) { | ||
179 | clk->usecount--; | ||
180 | return ret; | ||
181 | } | ||
182 | |||
183 | ret = omap2_clk_enable(clk); | ||
184 | |||
185 | if (unlikely(ret != 0) && clk->parent) { | ||
186 | omap2_clk_unuse(clk->parent); | ||
187 | clk->usecount--; | ||
188 | } | ||
189 | } | ||
190 | |||
191 | return ret; | ||
192 | } | ||
193 | |||
194 | static void omap2_clk_unuse(struct clk *clk) | ||
195 | { | ||
196 | if (clk->usecount > 0 && !(--clk->usecount)) { | ||
197 | omap2_clk_disable(clk); | ||
198 | if (likely((u32)clk->parent)) | ||
199 | omap2_clk_unuse(clk->parent); | ||
200 | } | ||
201 | } | ||
202 | |||
203 | /* | ||
204 | * Uses the current prcm set to tell if a rate is valid. | ||
205 | * You can go slower, but not faster within a given rate set. | ||
206 | */ | ||
207 | static u32 omap2_dpll_round_rate(unsigned long target_rate) | ||
208 | { | ||
209 | u32 high, low; | ||
210 | |||
211 | if ((CM_CLKSEL2_PLL & 0x3) == 1) { /* DPLL clockout */ | ||
212 | high = curr_prcm_set->dpll_speed * 2; | ||
213 | low = curr_prcm_set->dpll_speed; | ||
214 | } else { /* DPLL clockout x 2 */ | ||
215 | high = curr_prcm_set->dpll_speed; | ||
216 | low = curr_prcm_set->dpll_speed / 2; | ||
217 | } | ||
218 | |||
219 | #ifdef DOWN_VARIABLE_DPLL | ||
220 | if (target_rate > high) | ||
221 | return high; | ||
222 | else | ||
223 | return target_rate; | ||
224 | #else | ||
225 | if (target_rate > low) | ||
226 | return high; | ||
227 | else | ||
228 | return low; | ||
229 | #endif | ||
230 | |||
231 | } | ||
232 | |||
233 | /* | ||
234 | * Used for clocks that are part of CLKSEL_xyz governed clocks. | ||
235 | * REVISIT: Maybe change to use clk->enable() functions like on omap1? | ||
236 | */ | ||
237 | static void omap2_clksel_recalc(struct clk * clk) | ||
238 | { | ||
239 | u32 fixed = 0, div = 0; | ||
240 | |||
241 | if (clk == &dpll_ck) { | ||
242 | clk->rate = omap2_get_dpll_rate(clk); | ||
243 | fixed = 1; | ||
244 | div = 0; | ||
245 | } | ||
246 | |||
247 | if (clk == &iva1_mpu_int_ifck) { | ||
248 | div = 2; | ||
249 | fixed = 1; | ||
250 | } | ||
251 | |||
252 | if ((clk == &dss1_fck) && ((CM_CLKSEL1_CORE & (0x1f << 8)) == 0)) { | ||
253 | clk->rate = sys_ck.rate; | ||
254 | return; | ||
255 | } | ||
256 | |||
257 | if (!fixed) { | ||
258 | div = omap2_clksel_get_divisor(clk); | ||
259 | if (div == 0) | ||
260 | return; | ||
261 | } | ||
262 | |||
263 | if (div != 0) { | ||
264 | if (unlikely(clk->rate == clk->parent->rate / div)) | ||
265 | return; | ||
266 | clk->rate = clk->parent->rate / div; | ||
267 | } | ||
268 | |||
269 | if (unlikely(clk->flags & RATE_PROPAGATES)) | ||
270 | propagate_rate(clk); | ||
271 | } | ||
272 | |||
273 | /* | ||
274 | * Finds best divider value in an array based on the source and target | ||
275 | * rates. The divider array must be sorted with smallest divider first. | ||
276 | */ | ||
277 | static inline u32 omap2_divider_from_table(u32 size, u32 *div_array, | ||
278 | u32 src_rate, u32 tgt_rate) | ||
279 | { | ||
280 | int i, test_rate; | ||
281 | |||
282 | if (div_array == NULL) | ||
283 | return ~1; | ||
284 | |||
285 | for (i=0; i < size; i++) { | ||
286 | test_rate = src_rate / *div_array; | ||
287 | if (test_rate <= tgt_rate) | ||
288 | return *div_array; | ||
289 | ++div_array; | ||
290 | } | ||
291 | |||
292 | return ~0; /* No acceptable divider */ | ||
293 | } | ||
294 | |||
295 | /* | ||
296 | * Find divisor for the given clock and target rate. | ||
297 | * | ||
298 | * Note that this will not work for clocks which are part of CONFIG_PARTICIPANT, | ||
299 | * they are only settable as part of virtual_prcm set. | ||
300 | */ | ||
301 | static u32 omap2_clksel_round_rate(struct clk *tclk, u32 target_rate, | ||
302 | u32 *new_div) | ||
303 | { | ||
304 | u32 gfx_div[] = {2, 3, 4}; | ||
305 | u32 sysclkout_div[] = {1, 2, 4, 8, 16}; | ||
306 | u32 dss1_div[] = {1, 2, 3, 4, 5, 6, 8, 9, 12, 16}; | ||
307 | u32 vylnq_div[] = {1, 2, 3, 4, 6, 8, 9, 12, 16, 18}; | ||
308 | u32 best_div = ~0, asize = 0; | ||
309 | u32 *div_array = NULL; | ||
310 | |||
311 | switch (tclk->flags & SRC_RATE_SEL_MASK) { | ||
312 | case CM_GFX_SEL1: | ||
313 | asize = 3; | ||
314 | div_array = gfx_div; | ||
315 | break; | ||
316 | case CM_PLL_SEL1: | ||
317 | return omap2_dpll_round_rate(target_rate); | ||
318 | case CM_SYSCLKOUT_SEL1: | ||
319 | asize = 5; | ||
320 | div_array = sysclkout_div; | ||
321 | break; | ||
322 | case CM_CORE_SEL1: | ||
323 | if(tclk == &dss1_fck){ | ||
324 | if(tclk->parent == &core_ck){ | ||
325 | asize = 10; | ||
326 | div_array = dss1_div; | ||
327 | } else { | ||
328 | *new_div = 0; /* fixed clk */ | ||
329 | return(tclk->parent->rate); | ||
330 | } | ||
331 | } else if((tclk == &vlynq_fck) && cpu_is_omap2420()){ | ||
332 | if(tclk->parent == &core_ck){ | ||
333 | asize = 10; | ||
334 | div_array = vylnq_div; | ||
335 | } else { | ||
336 | *new_div = 0; /* fixed clk */ | ||
337 | return(tclk->parent->rate); | ||
338 | } | ||
339 | } | ||
340 | break; | ||
341 | } | ||
342 | |||
343 | best_div = omap2_divider_from_table(asize, div_array, | ||
344 | tclk->parent->rate, target_rate); | ||
345 | if (best_div == ~0){ | ||
346 | *new_div = 1; | ||
347 | return best_div; /* signal error */ | ||
348 | } | ||
349 | |||
350 | *new_div = best_div; | ||
351 | return (tclk->parent->rate / best_div); | ||
352 | } | ||
353 | |||
354 | /* Given a clock and a rate apply a clock specific rounding function */ | ||
355 | static long omap2_clk_round_rate(struct clk *clk, unsigned long rate) | ||
356 | { | ||
357 | u32 new_div = 0; | ||
358 | int valid_rate; | ||
359 | |||
360 | if (clk->flags & RATE_FIXED) | ||
361 | return clk->rate; | ||
362 | |||
363 | if (clk->flags & RATE_CKCTL) { | ||
364 | valid_rate = omap2_clksel_round_rate(clk, rate, &new_div); | ||
365 | return valid_rate; | ||
366 | } | ||
367 | |||
368 | if (clk->round_rate != 0) | ||
369 | return clk->round_rate(clk, rate); | ||
370 | |||
371 | return clk->rate; | ||
372 | } | ||
373 | |||
374 | /* | ||
375 | * Check the DLL lock state, and return tue if running in unlock mode. | ||
376 | * This is needed to compenste for the shifted DLL value in unlock mode. | ||
377 | */ | ||
378 | static u32 omap2_dll_force_needed(void) | ||
379 | { | ||
380 | u32 dll_state = SDRC_DLLA_CTRL; /* dlla and dllb are a set */ | ||
381 | |||
382 | if ((dll_state & (1 << 2)) == (1 << 2)) | ||
383 | return 1; | ||
384 | else | ||
385 | return 0; | ||
386 | } | ||
387 | |||
388 | static void omap2_init_memory_params(u32 force_lock_to_unlock_mode) | ||
389 | { | ||
390 | unsigned long dll_cnt; | ||
391 | u32 fast_dll = 0; | ||
392 | |||
393 | mem_timings.m_type = !((SDRC_MR_0 & 0x3) == 0x1); /* DDR = 1, SDR = 0 */ | ||
394 | |||
395 | /* 2422 es2.05 and beyond has a single SIP DDR instead of 2 like others. | ||
396 | * In the case of 2422, its ok to use CS1 instead of CS0. | ||
397 | */ | ||
398 | |||
399 | #if 0 /* FIXME: Enable after 24xx cpu detection works */ | ||
400 | ctype = get_cpu_type(); | ||
401 | if (cpu_is_omap2422()) | ||
402 | mem_timings.base_cs = 1; | ||
403 | else | ||
404 | #endif | ||
405 | mem_timings.base_cs = 0; | ||
406 | |||
407 | if (mem_timings.m_type != M_DDR) | ||
408 | return; | ||
409 | |||
410 | /* With DDR we need to determine the low frequency DLL value */ | ||
411 | if (((mem_timings.fast_dll_ctrl & (1 << 2)) == M_LOCK_CTRL)) | ||
412 | mem_timings.dll_mode = M_UNLOCK; | ||
413 | else | ||
414 | mem_timings.dll_mode = M_LOCK; | ||
415 | |||
416 | if (mem_timings.base_cs == 0) { | ||
417 | fast_dll = SDRC_DLLA_CTRL; | ||
418 | dll_cnt = SDRC_DLLA_STATUS & 0xff00; | ||
419 | } else { | ||
420 | fast_dll = SDRC_DLLB_CTRL; | ||
421 | dll_cnt = SDRC_DLLB_STATUS & 0xff00; | ||
422 | } | ||
423 | if (force_lock_to_unlock_mode) { | ||
424 | fast_dll &= ~0xff00; | ||
425 | fast_dll |= dll_cnt; /* Current lock mode */ | ||
426 | } | ||
427 | mem_timings.fast_dll_ctrl = fast_dll; | ||
428 | |||
429 | /* No disruptions, DDR will be offline & C-ABI not followed */ | ||
430 | omap2_sram_ddr_init(&mem_timings.slow_dll_ctrl, | ||
431 | mem_timings.fast_dll_ctrl, | ||
432 | mem_timings.base_cs, | ||
433 | force_lock_to_unlock_mode); | ||
434 | mem_timings.slow_dll_ctrl &= 0xff00; /* Keep lock value */ | ||
435 | |||
436 | /* Turn status into unlock ctrl */ | ||
437 | mem_timings.slow_dll_ctrl |= | ||
438 | ((mem_timings.fast_dll_ctrl & 0xF) | (1 << 2)); | ||
439 | |||
440 | /* 90 degree phase for anything below 133Mhz */ | ||
441 | mem_timings.slow_dll_ctrl |= (1 << 1); | ||
442 | } | ||
443 | |||
444 | static u32 omap2_reprogram_sdrc(u32 level, u32 force) | ||
445 | { | ||
446 | u32 prev = curr_perf_level, flags; | ||
447 | |||
448 | if ((curr_perf_level == level) && !force) | ||
449 | return prev; | ||
450 | |||
451 | if (level == PRCM_HALF_SPEED) { | ||
452 | local_irq_save(flags); | ||
453 | PRCM_VOLTSETUP = 0xffff; | ||
454 | omap2_sram_reprogram_sdrc(PRCM_HALF_SPEED, | ||
455 | mem_timings.slow_dll_ctrl, | ||
456 | mem_timings.m_type); | ||
457 | curr_perf_level = PRCM_HALF_SPEED; | ||
458 | local_irq_restore(flags); | ||
459 | } | ||
460 | if (level == PRCM_FULL_SPEED) { | ||
461 | local_irq_save(flags); | ||
462 | PRCM_VOLTSETUP = 0xffff; | ||
463 | omap2_sram_reprogram_sdrc(PRCM_FULL_SPEED, | ||
464 | mem_timings.fast_dll_ctrl, | ||
465 | mem_timings.m_type); | ||
466 | curr_perf_level = PRCM_FULL_SPEED; | ||
467 | local_irq_restore(flags); | ||
468 | } | ||
469 | |||
470 | return prev; | ||
471 | } | ||
472 | |||
473 | static int omap2_reprogram_dpll(struct clk * clk, unsigned long rate) | ||
474 | { | ||
475 | u32 flags, cur_rate, low, mult, div, valid_rate, done_rate; | ||
476 | u32 bypass = 0; | ||
477 | struct prcm_config tmpset; | ||
478 | int ret = -EINVAL; | ||
479 | |||
480 | local_irq_save(flags); | ||
481 | cur_rate = omap2_get_dpll_rate(&dpll_ck); | ||
482 | mult = CM_CLKSEL2_PLL & 0x3; | ||
483 | |||
484 | if ((rate == (cur_rate / 2)) && (mult == 2)) { | ||
485 | omap2_reprogram_sdrc(PRCM_HALF_SPEED, 1); | ||
486 | } else if ((rate == (cur_rate * 2)) && (mult == 1)) { | ||
487 | omap2_reprogram_sdrc(PRCM_FULL_SPEED, 1); | ||
488 | } else if (rate != cur_rate) { | ||
489 | valid_rate = omap2_dpll_round_rate(rate); | ||
490 | if (valid_rate != rate) | ||
491 | goto dpll_exit; | ||
492 | |||
493 | if ((CM_CLKSEL2_PLL & 0x3) == 1) | ||
494 | low = curr_prcm_set->dpll_speed; | ||
495 | else | ||
496 | low = curr_prcm_set->dpll_speed / 2; | ||
497 | |||
498 | tmpset.cm_clksel1_pll = CM_CLKSEL1_PLL; | ||
499 | tmpset.cm_clksel1_pll &= ~(0x3FFF << 8); | ||
500 | div = ((curr_prcm_set->xtal_speed / 1000000) - 1); | ||
501 | tmpset.cm_clksel2_pll = CM_CLKSEL2_PLL; | ||
502 | tmpset.cm_clksel2_pll &= ~0x3; | ||
503 | if (rate > low) { | ||
504 | tmpset.cm_clksel2_pll |= 0x2; | ||
505 | mult = ((rate / 2) / 1000000); | ||
506 | done_rate = PRCM_FULL_SPEED; | ||
507 | } else { | ||
508 | tmpset.cm_clksel2_pll |= 0x1; | ||
509 | mult = (rate / 1000000); | ||
510 | done_rate = PRCM_HALF_SPEED; | ||
511 | } | ||
512 | tmpset.cm_clksel1_pll |= ((div << 8) | (mult << 12)); | ||
513 | |||
514 | /* Worst case */ | ||
515 | tmpset.base_sdrc_rfr = V24XX_SDRC_RFR_CTRL_BYPASS; | ||
516 | |||
517 | if (rate == curr_prcm_set->xtal_speed) /* If asking for 1-1 */ | ||
518 | bypass = 1; | ||
519 | |||
520 | omap2_reprogram_sdrc(PRCM_FULL_SPEED, 1); /* For init_mem */ | ||
521 | |||
522 | /* Force dll lock mode */ | ||
523 | omap2_set_prcm(tmpset.cm_clksel1_pll, tmpset.base_sdrc_rfr, | ||
524 | bypass); | ||
525 | |||
526 | /* Errata: ret dll entry state */ | ||
527 | omap2_init_memory_params(omap2_dll_force_needed()); | ||
528 | omap2_reprogram_sdrc(done_rate, 0); | ||
529 | } | ||
530 | omap2_clksel_recalc(&dpll_ck); | ||
531 | ret = 0; | ||
532 | |||
533 | dpll_exit: | ||
534 | local_irq_restore(flags); | ||
535 | return(ret); | ||
536 | } | ||
537 | |||
538 | /* Just return the MPU speed */ | ||
539 | static void omap2_mpu_recalc(struct clk * clk) | ||
540 | { | ||
541 | clk->rate = curr_prcm_set->mpu_speed; | ||
542 | } | ||
543 | |||
544 | /* | ||
545 | * Look for a rate equal or less than the target rate given a configuration set. | ||
546 | * | ||
547 | * What's not entirely clear is "which" field represents the key field. | ||
548 | * Some might argue L3-DDR, others ARM, others IVA. This code is simple and | ||
549 | * just uses the ARM rates. | ||
550 | */ | ||
551 | static long omap2_round_to_table_rate(struct clk * clk, unsigned long rate) | ||
552 | { | ||
553 | struct prcm_config * ptr; | ||
554 | long highest_rate; | ||
555 | |||
556 | if (clk != &virt_prcm_set) | ||
557 | return -EINVAL; | ||
558 | |||
559 | highest_rate = -EINVAL; | ||
560 | |||
561 | for (ptr = rate_table; ptr->mpu_speed; ptr++) { | ||
562 | if (ptr->xtal_speed != sys_ck.rate) | ||
563 | continue; | ||
564 | |||
565 | highest_rate = ptr->mpu_speed; | ||
566 | |||
567 | /* Can check only after xtal frequency check */ | ||
568 | if (ptr->mpu_speed <= rate) | ||
569 | break; | ||
570 | } | ||
571 | return highest_rate; | ||
572 | } | ||
573 | |||
574 | /* | ||
575 | * omap2_convert_field_to_div() - turn field value into integer divider | ||
576 | */ | ||
577 | static u32 omap2_clksel_to_divisor(u32 div_sel, u32 field_val) | ||
578 | { | ||
579 | u32 i; | ||
580 | u32 clkout_array[] = {1, 2, 4, 8, 16}; | ||
581 | |||
582 | if ((div_sel & SRC_RATE_SEL_MASK) == CM_SYSCLKOUT_SEL1) { | ||
583 | for (i = 0; i < 5; i++) { | ||
584 | if (field_val == i) | ||
585 | return clkout_array[i]; | ||
586 | } | ||
587 | return ~0; | ||
588 | } else | ||
589 | return field_val; | ||
590 | } | ||
591 | |||
592 | /* | ||
593 | * Returns the CLKSEL divider register value | ||
594 | * REVISIT: This should be cleaned up to work nicely with void __iomem * | ||
595 | */ | ||
596 | static u32 omap2_get_clksel(u32 *div_sel, u32 *field_mask, | ||
597 | struct clk *clk) | ||
598 | { | ||
599 | int ret = ~0; | ||
600 | u32 reg_val, div_off; | ||
601 | u32 div_addr = 0; | ||
602 | u32 mask = ~0; | ||
603 | |||
604 | div_off = clk->rate_offset; | ||
605 | |||
606 | switch ((*div_sel & SRC_RATE_SEL_MASK)) { | ||
607 | case CM_MPU_SEL1: | ||
608 | div_addr = (u32)&CM_CLKSEL_MPU; | ||
609 | mask = 0x1f; | ||
610 | break; | ||
611 | case CM_DSP_SEL1: | ||
612 | div_addr = (u32)&CM_CLKSEL_DSP; | ||
613 | if (cpu_is_omap2420()) { | ||
614 | if ((div_off == 0) || (div_off == 8)) | ||
615 | mask = 0x1f; | ||
616 | else if (div_off == 5) | ||
617 | mask = 0x3; | ||
618 | } else if (cpu_is_omap2430()) { | ||
619 | if (div_off == 0) | ||
620 | mask = 0x1f; | ||
621 | else if (div_off == 5) | ||
622 | mask = 0x3; | ||
623 | } | ||
624 | break; | ||
625 | case CM_GFX_SEL1: | ||
626 | div_addr = (u32)&CM_CLKSEL_GFX; | ||
627 | if (div_off == 0) | ||
628 | mask = 0x7; | ||
629 | break; | ||
630 | case CM_MODEM_SEL1: | ||
631 | div_addr = (u32)&CM_CLKSEL_MDM; | ||
632 | if (div_off == 0) | ||
633 | mask = 0xf; | ||
634 | break; | ||
635 | case CM_SYSCLKOUT_SEL1: | ||
636 | div_addr = (u32)&PRCM_CLKOUT_CTRL; | ||
637 | if ((div_off == 3) || (div_off = 11)) | ||
638 | mask= 0x3; | ||
639 | break; | ||
640 | case CM_CORE_SEL1: | ||
641 | div_addr = (u32)&CM_CLKSEL1_CORE; | ||
642 | switch (div_off) { | ||
643 | case 0: /* l3 */ | ||
644 | case 8: /* dss1 */ | ||
645 | case 15: /* vylnc-2420 */ | ||
646 | case 20: /* ssi */ | ||
647 | mask = 0x1f; break; | ||
648 | case 5: /* l4 */ | ||
649 | mask = 0x3; break; | ||
650 | case 13: /* dss2 */ | ||
651 | mask = 0x1; break; | ||
652 | case 25: /* usb */ | ||
653 | mask = 0xf; break; | ||
654 | } | ||
655 | } | ||
656 | |||
657 | *field_mask = mask; | ||
658 | |||
659 | if (unlikely(mask == ~0)) | ||
660 | div_addr = 0; | ||
661 | |||
662 | *div_sel = div_addr; | ||
663 | |||
664 | if (unlikely(div_addr == 0)) | ||
665 | return ret; | ||
666 | |||
667 | /* Isolate field */ | ||
668 | reg_val = __raw_readl((void __iomem *)div_addr) & (mask << div_off); | ||
669 | |||
670 | /* Normalize back to divider value */ | ||
671 | reg_val >>= div_off; | ||
672 | |||
673 | return reg_val; | ||
674 | } | ||
675 | |||
676 | /* | ||
677 | * Return divider to be applied to parent clock. | ||
678 | * Return 0 on error. | ||
679 | */ | ||
680 | static u32 omap2_clksel_get_divisor(struct clk *clk) | ||
681 | { | ||
682 | int ret = 0; | ||
683 | u32 div, div_sel, div_off, field_mask, field_val; | ||
684 | |||
685 | /* isolate control register */ | ||
686 | div_sel = (SRC_RATE_SEL_MASK & clk->flags); | ||
687 | |||
688 | div_off = clk->rate_offset; | ||
689 | field_val = omap2_get_clksel(&div_sel, &field_mask, clk); | ||
690 | if (div_sel == 0) | ||
691 | return ret; | ||
692 | |||
693 | div_sel = (SRC_RATE_SEL_MASK & clk->flags); | ||
694 | div = omap2_clksel_to_divisor(div_sel, field_val); | ||
695 | |||
696 | return div; | ||
697 | } | ||
698 | |||
699 | /* Set the clock rate for a clock source */ | ||
700 | static int omap2_clk_set_rate(struct clk *clk, unsigned long rate) | ||
701 | |||
702 | { | ||
703 | int ret = -EINVAL; | ||
704 | void __iomem * reg; | ||
705 | u32 div_sel, div_off, field_mask, field_val, reg_val, validrate; | ||
706 | u32 new_div = 0; | ||
707 | |||
708 | if (!(clk->flags & CONFIG_PARTICIPANT) && (clk->flags & RATE_CKCTL)) { | ||
709 | if (clk == &dpll_ck) | ||
710 | return omap2_reprogram_dpll(clk, rate); | ||
711 | |||
712 | /* Isolate control register */ | ||
713 | div_sel = (SRC_RATE_SEL_MASK & clk->flags); | ||
714 | div_off = clk->src_offset; | ||
715 | |||
716 | validrate = omap2_clksel_round_rate(clk, rate, &new_div); | ||
717 | if(validrate != rate) | ||
718 | return(ret); | ||
719 | |||
720 | field_val = omap2_get_clksel(&div_sel, &field_mask, clk); | ||
721 | if (div_sel == 0) | ||
722 | return ret; | ||
723 | |||
724 | if(clk->flags & CM_SYSCLKOUT_SEL1){ | ||
725 | switch(new_div){ | ||
726 | case 16: field_val = 4; break; | ||
727 | case 8: field_val = 3; break; | ||
728 | case 4: field_val = 2; break; | ||
729 | case 2: field_val = 1; break; | ||
730 | case 1: field_val = 0; break; | ||
731 | } | ||
732 | } | ||
733 | else | ||
734 | field_val = new_div; | ||
735 | |||
736 | reg = (void __iomem *)div_sel; | ||
737 | |||
738 | reg_val = __raw_readl(reg); | ||
739 | reg_val &= ~(field_mask << div_off); | ||
740 | reg_val |= (field_val << div_off); | ||
741 | |||
742 | __raw_writel(reg_val, reg); | ||
743 | clk->rate = clk->parent->rate / field_val; | ||
744 | |||
745 | if (clk->flags & DELAYED_APP) | ||
746 | __raw_writel(0x1, (void __iomem *)&PRCM_CLKCFG_CTRL); | ||
747 | ret = 0; | ||
748 | } else if (clk->set_rate != 0) | ||
749 | ret = clk->set_rate(clk, rate); | ||
750 | |||
751 | if (unlikely(ret == 0 && (clk->flags & RATE_PROPAGATES))) | ||
752 | propagate_rate(clk); | ||
753 | |||
754 | return ret; | ||
755 | } | ||
756 | |||
757 | /* Converts encoded control register address into a full address */ | ||
758 | static u32 omap2_get_src_field(u32 *type_to_addr, u32 reg_offset, | ||
759 | struct clk *src_clk, u32 *field_mask) | ||
760 | { | ||
761 | u32 val = ~0, src_reg_addr = 0, mask = 0; | ||
762 | |||
763 | /* Find target control register.*/ | ||
764 | switch ((*type_to_addr & SRC_RATE_SEL_MASK)) { | ||
765 | case CM_CORE_SEL1: | ||
766 | src_reg_addr = (u32)&CM_CLKSEL1_CORE; | ||
767 | if (reg_offset == 13) { /* DSS2_fclk */ | ||
768 | mask = 0x1; | ||
769 | if (src_clk == &sys_ck) | ||
770 | val = 0; | ||
771 | if (src_clk == &func_48m_ck) | ||
772 | val = 1; | ||
773 | } else if (reg_offset == 8) { /* DSS1_fclk */ | ||
774 | mask = 0x1f; | ||
775 | if (src_clk == &sys_ck) | ||
776 | val = 0; | ||
777 | else if (src_clk == &core_ck) /* divided clock */ | ||
778 | val = 0x10; /* rate needs fixing */ | ||
779 | } else if ((reg_offset == 15) && cpu_is_omap2420()){ /*vlnyq*/ | ||
780 | mask = 0x1F; | ||
781 | if(src_clk == &func_96m_ck) | ||
782 | val = 0; | ||
783 | else if (src_clk == &core_ck) | ||
784 | val = 0x10; | ||
785 | } | ||
786 | break; | ||
787 | case CM_CORE_SEL2: | ||
788 | src_reg_addr = (u32)&CM_CLKSEL2_CORE; | ||
789 | mask = 0x3; | ||
790 | if (src_clk == &func_32k_ck) | ||
791 | val = 0x0; | ||
792 | if (src_clk == &sys_ck) | ||
793 | val = 0x1; | ||
794 | if (src_clk == &alt_ck) | ||
795 | val = 0x2; | ||
796 | break; | ||
797 | case CM_WKUP_SEL1: | ||
798 | src_reg_addr = (u32)&CM_CLKSEL2_CORE; | ||
799 | mask = 0x3; | ||
800 | if (src_clk == &func_32k_ck) | ||
801 | val = 0x0; | ||
802 | if (src_clk == &sys_ck) | ||
803 | val = 0x1; | ||
804 | if (src_clk == &alt_ck) | ||
805 | val = 0x2; | ||
806 | break; | ||
807 | case CM_PLL_SEL1: | ||
808 | src_reg_addr = (u32)&CM_CLKSEL1_PLL; | ||
809 | mask = 0x1; | ||
810 | if (reg_offset == 0x3) { | ||
811 | if (src_clk == &apll96_ck) | ||
812 | val = 0; | ||
813 | if (src_clk == &alt_ck) | ||
814 | val = 1; | ||
815 | } | ||
816 | else if (reg_offset == 0x5) { | ||
817 | if (src_clk == &apll54_ck) | ||
818 | val = 0; | ||
819 | if (src_clk == &alt_ck) | ||
820 | val = 1; | ||
821 | } | ||
822 | break; | ||
823 | case CM_PLL_SEL2: | ||
824 | src_reg_addr = (u32)&CM_CLKSEL2_PLL; | ||
825 | mask = 0x3; | ||
826 | if (src_clk == &func_32k_ck) | ||
827 | val = 0x0; | ||
828 | if (src_clk == &dpll_ck) | ||
829 | val = 0x2; | ||
830 | break; | ||
831 | case CM_SYSCLKOUT_SEL1: | ||
832 | src_reg_addr = (u32)&PRCM_CLKOUT_CTRL; | ||
833 | mask = 0x3; | ||
834 | if (src_clk == &dpll_ck) | ||
835 | val = 0; | ||
836 | if (src_clk == &sys_ck) | ||
837 | val = 1; | ||
838 | if (src_clk == &func_54m_ck) | ||
839 | val = 2; | ||
840 | if (src_clk == &func_96m_ck) | ||
841 | val = 3; | ||
842 | break; | ||
843 | } | ||
844 | |||
845 | if (val == ~0) /* Catch errors in offset */ | ||
846 | *type_to_addr = 0; | ||
847 | else | ||
848 | *type_to_addr = src_reg_addr; | ||
849 | *field_mask = mask; | ||
850 | |||
851 | return val; | ||
852 | } | ||
853 | |||
854 | static int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent) | ||
855 | { | ||
856 | void __iomem * reg; | ||
857 | u32 src_sel, src_off, field_val, field_mask, reg_val, rate; | ||
858 | int ret = -EINVAL; | ||
859 | |||
860 | if (unlikely(clk->flags & CONFIG_PARTICIPANT)) | ||
861 | return ret; | ||
862 | |||
863 | if (clk->flags & SRC_SEL_MASK) { /* On-chip SEL collection */ | ||
864 | src_sel = (SRC_RATE_SEL_MASK & clk->flags); | ||
865 | src_off = clk->src_offset; | ||
866 | |||
867 | if (src_sel == 0) | ||
868 | goto set_parent_error; | ||
869 | |||
870 | field_val = omap2_get_src_field(&src_sel, src_off, new_parent, | ||
871 | &field_mask); | ||
872 | |||
873 | reg = (void __iomem *)src_sel; | ||
874 | |||
875 | if (clk->usecount > 0) | ||
876 | omap2_clk_disable(clk); | ||
877 | |||
878 | /* Set new source value (previous dividers if any in effect) */ | ||
879 | reg_val = __raw_readl(reg) & ~(field_mask << src_off); | ||
880 | reg_val |= (field_val << src_off); | ||
881 | __raw_writel(reg_val, reg); | ||
882 | |||
883 | if (clk->flags & DELAYED_APP) | ||
884 | __raw_writel(0x1, (void __iomem *)&PRCM_CLKCFG_CTRL); | ||
885 | |||
886 | if (clk->usecount > 0) | ||
887 | omap2_clk_enable(clk); | ||
888 | |||
889 | clk->parent = new_parent; | ||
890 | |||
891 | /* SRC_RATE_SEL_MASK clocks follow their parents rates.*/ | ||
892 | if ((new_parent == &core_ck) && (clk == &dss1_fck)) | ||
893 | clk->rate = new_parent->rate / 0x10; | ||
894 | else | ||
895 | clk->rate = new_parent->rate; | ||
896 | |||
897 | if (unlikely(clk->flags & RATE_PROPAGATES)) | ||
898 | propagate_rate(clk); | ||
899 | |||
900 | return 0; | ||
901 | } else { | ||
902 | clk->parent = new_parent; | ||
903 | rate = new_parent->rate; | ||
904 | omap2_clk_set_rate(clk, rate); | ||
905 | ret = 0; | ||
906 | } | ||
907 | |||
908 | set_parent_error: | ||
909 | return ret; | ||
910 | } | ||
911 | |||
912 | /* Sets basic clocks based on the specified rate */ | ||
913 | static int omap2_select_table_rate(struct clk * clk, unsigned long rate) | ||
914 | { | ||
915 | u32 flags, cur_rate, done_rate, bypass = 0; | ||
916 | u8 cpu_mask = 0; | ||
917 | struct prcm_config *prcm; | ||
918 | unsigned long found_speed = 0; | ||
919 | |||
920 | if (clk != &virt_prcm_set) | ||
921 | return -EINVAL; | ||
922 | |||
923 | /* FIXME: Change cpu_is_omap2420() to cpu_is_omap242x() */ | ||
924 | if (cpu_is_omap2420()) | ||
925 | cpu_mask = RATE_IN_242X; | ||
926 | else if (cpu_is_omap2430()) | ||
927 | cpu_mask = RATE_IN_243X; | ||
928 | |||
929 | for (prcm = rate_table; prcm->mpu_speed; prcm++) { | ||
930 | if (!(prcm->flags & cpu_mask)) | ||
931 | continue; | ||
932 | |||
933 | if (prcm->xtal_speed != sys_ck.rate) | ||
934 | continue; | ||
935 | |||
936 | if (prcm->mpu_speed <= rate) { | ||
937 | found_speed = prcm->mpu_speed; | ||
938 | break; | ||
939 | } | ||
940 | } | ||
941 | |||
942 | if (!found_speed) { | ||
943 | printk(KERN_INFO "Could not set MPU rate to %luMHz\n", | ||
944 | rate / 1000000); | ||
945 | return -EINVAL; | ||
946 | } | ||
947 | |||
948 | curr_prcm_set = prcm; | ||
949 | cur_rate = omap2_get_dpll_rate(&dpll_ck); | ||
950 | |||
951 | if (prcm->dpll_speed == cur_rate / 2) { | ||
952 | omap2_reprogram_sdrc(PRCM_HALF_SPEED, 1); | ||
953 | } else if (prcm->dpll_speed == cur_rate * 2) { | ||
954 | omap2_reprogram_sdrc(PRCM_FULL_SPEED, 1); | ||
955 | } else if (prcm->dpll_speed != cur_rate) { | ||
956 | local_irq_save(flags); | ||
957 | |||
958 | if (prcm->dpll_speed == prcm->xtal_speed) | ||
959 | bypass = 1; | ||
960 | |||
961 | if ((prcm->cm_clksel2_pll & 0x3) == 2) | ||
962 | done_rate = PRCM_FULL_SPEED; | ||
963 | else | ||
964 | done_rate = PRCM_HALF_SPEED; | ||
965 | |||
966 | /* MPU divider */ | ||
967 | CM_CLKSEL_MPU = prcm->cm_clksel_mpu; | ||
968 | |||
969 | /* dsp + iva1 div(2420), iva2.1(2430) */ | ||
970 | CM_CLKSEL_DSP = prcm->cm_clksel_dsp; | ||
971 | |||
972 | CM_CLKSEL_GFX = prcm->cm_clksel_gfx; | ||
973 | |||
974 | /* Major subsystem dividers */ | ||
975 | CM_CLKSEL1_CORE = prcm->cm_clksel1_core; | ||
976 | if (cpu_is_omap2430()) | ||
977 | CM_CLKSEL_MDM = prcm->cm_clksel_mdm; | ||
978 | |||
979 | /* x2 to enter init_mem */ | ||
980 | omap2_reprogram_sdrc(PRCM_FULL_SPEED, 1); | ||
981 | |||
982 | omap2_set_prcm(prcm->cm_clksel1_pll, prcm->base_sdrc_rfr, | ||
983 | bypass); | ||
984 | |||
985 | omap2_init_memory_params(omap2_dll_force_needed()); | ||
986 | omap2_reprogram_sdrc(done_rate, 0); | ||
987 | |||
988 | local_irq_restore(flags); | ||
989 | } | ||
990 | omap2_clksel_recalc(&dpll_ck); | ||
991 | |||
992 | return 0; | ||
993 | } | ||
994 | |||
995 | /*------------------------------------------------------------------------- | ||
996 | * Omap2 clock reset and init functions | ||
997 | *-------------------------------------------------------------------------*/ | ||
998 | |||
999 | static struct clk_functions omap2_clk_functions = { | ||
1000 | .clk_enable = omap2_clk_enable, | ||
1001 | .clk_disable = omap2_clk_disable, | ||
1002 | .clk_use = omap2_clk_use, | ||
1003 | .clk_unuse = omap2_clk_unuse, | ||
1004 | .clk_round_rate = omap2_clk_round_rate, | ||
1005 | .clk_set_rate = omap2_clk_set_rate, | ||
1006 | .clk_set_parent = omap2_clk_set_parent, | ||
1007 | }; | ||
1008 | |||
1009 | static void __init omap2_get_crystal_rate(struct clk *osc, struct clk *sys) | ||
1010 | { | ||
1011 | u32 div, aplls, sclk = 13000000; | ||
1012 | |||
1013 | aplls = CM_CLKSEL1_PLL; | ||
1014 | aplls &= ((1 << 23) | (1 << 24) | (1 << 25)); | ||
1015 | aplls >>= 23; /* Isolate field, 0,2,3 */ | ||
1016 | |||
1017 | if (aplls == 0) | ||
1018 | sclk = 19200000; | ||
1019 | else if (aplls == 2) | ||
1020 | sclk = 13000000; | ||
1021 | else if (aplls == 3) | ||
1022 | sclk = 12000000; | ||
1023 | |||
1024 | div = PRCM_CLKSRC_CTRL; | ||
1025 | div &= ((1 << 7) | (1 << 6)); | ||
1026 | div >>= sys->rate_offset; | ||
1027 | |||
1028 | osc->rate = sclk * div; | ||
1029 | sys->rate = sclk; | ||
1030 | } | ||
1031 | |||
1032 | #ifdef CONFIG_OMAP_RESET_CLOCKS | ||
1033 | static void __init omap2_disable_unused_clocks(void) | ||
1034 | { | ||
1035 | struct clk *ck; | ||
1036 | u32 regval32; | ||
1037 | |||
1038 | list_for_each_entry(ck, &clocks, node) { | ||
1039 | if (ck->usecount > 0 || (ck->flags & ALWAYS_ENABLED) || | ||
1040 | ck->enable_reg == 0) | ||
1041 | continue; | ||
1042 | |||
1043 | regval32 = __raw_readl(ck->enable_reg); | ||
1044 | if ((regval32 & (1 << ck->enable_bit)) == 0) | ||
1045 | continue; | ||
1046 | |||
1047 | printk(KERN_INFO "Disabling unused clock \"%s\"\n", ck->name); | ||
1048 | omap2_clk_disable(ck); | ||
1049 | } | ||
1050 | } | ||
1051 | late_initcall(omap2_disable_unused_clocks); | ||
1052 | #endif | ||
1053 | |||
1054 | /* | ||
1055 | * Switch the MPU rate if specified on cmdline. | ||
1056 | * We cannot do this early until cmdline is parsed. | ||
1057 | */ | ||
1058 | static int __init omap2_clk_arch_init(void) | ||
1059 | { | ||
1060 | if (!mpurate) | ||
1061 | return -EINVAL; | ||
1062 | |||
1063 | if (omap2_select_table_rate(&virt_prcm_set, mpurate)) | ||
1064 | printk(KERN_ERR "Could not find matching MPU rate\n"); | ||
1065 | |||
1066 | propagate_rate(&osc_ck); /* update main root fast */ | ||
1067 | propagate_rate(&func_32k_ck); /* update main root slow */ | ||
1068 | |||
1069 | printk(KERN_INFO "Switched to new clocking rate (Crystal/DPLL/MPU): " | ||
1070 | "%ld.%01ld/%ld/%ld MHz\n", | ||
1071 | (sys_ck.rate / 1000000), (sys_ck.rate / 100000) % 10, | ||
1072 | (dpll_ck.rate / 1000000), (mpu_ck.rate / 1000000)) ; | ||
1073 | |||
1074 | return 0; | ||
1075 | } | ||
1076 | arch_initcall(omap2_clk_arch_init); | ||
1077 | |||
1078 | int __init omap2_clk_init(void) | ||
1079 | { | ||
1080 | struct prcm_config *prcm; | ||
1081 | struct clk ** clkp; | ||
1082 | u32 clkrate; | ||
1083 | |||
1084 | clk_init(&omap2_clk_functions); | ||
1085 | omap2_get_crystal_rate(&osc_ck, &sys_ck); | ||
1086 | |||
1087 | for (clkp = onchip_clks; clkp < onchip_clks + ARRAY_SIZE(onchip_clks); | ||
1088 | clkp++) { | ||
1089 | |||
1090 | if ((*clkp)->flags & CLOCK_IN_OMAP242X && cpu_is_omap2420()) { | ||
1091 | clk_register(*clkp); | ||
1092 | continue; | ||
1093 | } | ||
1094 | |||
1095 | if ((*clkp)->flags & CLOCK_IN_OMAP243X && cpu_is_omap2430()) { | ||
1096 | clk_register(*clkp); | ||
1097 | continue; | ||
1098 | } | ||
1099 | } | ||
1100 | |||
1101 | /* Check the MPU rate set by bootloader */ | ||
1102 | clkrate = omap2_get_dpll_rate(&dpll_ck); | ||
1103 | for (prcm = rate_table; prcm->mpu_speed; prcm++) { | ||
1104 | if (prcm->xtal_speed != sys_ck.rate) | ||
1105 | continue; | ||
1106 | if (prcm->dpll_speed <= clkrate) | ||
1107 | break; | ||
1108 | } | ||
1109 | curr_prcm_set = prcm; | ||
1110 | |||
1111 | propagate_rate(&osc_ck); /* update main root fast */ | ||
1112 | propagate_rate(&func_32k_ck); /* update main root slow */ | ||
1113 | |||
1114 | printk(KERN_INFO "Clocking rate (Crystal/DPLL/MPU): " | ||
1115 | "%ld.%01ld/%ld/%ld MHz\n", | ||
1116 | (sys_ck.rate / 1000000), (sys_ck.rate / 100000) % 10, | ||
1117 | (dpll_ck.rate / 1000000), (mpu_ck.rate / 1000000)) ; | ||
1118 | |||
1119 | /* | ||
1120 | * Only enable those clocks we will need, let the drivers | ||
1121 | * enable other clocks as necessary | ||
1122 | */ | ||
1123 | clk_use(&sync_32k_ick); | ||
1124 | clk_use(&omapctrl_ick); | ||
1125 | if (cpu_is_omap2430()) | ||
1126 | clk_use(&sdrc_ick); | ||
1127 | |||
1128 | return 0; | ||
1129 | } | ||
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h new file mode 100644 index 000000000000..4aeab5591bd3 --- /dev/null +++ b/arch/arm/mach-omap2/clock.h | |||
@@ -0,0 +1,2103 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-omap24xx/clock.h | ||
3 | * | ||
4 | * Copyright (C) 2005 Texas Instruments Inc. | ||
5 | * Richard Woodruff <r-woodruff2@ti.com> | ||
6 | * Created for OMAP2. | ||
7 | * | ||
8 | * Copyright (C) 2004 Nokia corporation | ||
9 | * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com> | ||
10 | * Based on clocks.h by Tony Lindgren, Gordon McNutt and RidgeRun, Inc | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License version 2 as | ||
14 | * published by the Free Software Foundation. | ||
15 | */ | ||
16 | |||
17 | #ifndef __ARCH_ARM_MACH_OMAP2_CLOCK_H | ||
18 | #define __ARCH_ARM_MACH_OMAP2_CLOCK_H | ||
19 | |||
20 | static void omap2_sys_clk_recalc(struct clk * clk); | ||
21 | static void omap2_clksel_recalc(struct clk * clk); | ||
22 | static void omap2_followparent_recalc(struct clk * clk); | ||
23 | static void omap2_propagate_rate(struct clk * clk); | ||
24 | static void omap2_mpu_recalc(struct clk * clk); | ||
25 | static int omap2_select_table_rate(struct clk * clk, unsigned long rate); | ||
26 | static long omap2_round_to_table_rate(struct clk * clk, unsigned long rate); | ||
27 | static void omap2_clk_unuse(struct clk *clk); | ||
28 | static void omap2_sys_clk_recalc(struct clk * clk); | ||
29 | static u32 omap2_clksel_to_divisor(u32 div_sel, u32 field_val); | ||
30 | static u32 omap2_clksel_get_divisor(struct clk *clk); | ||
31 | |||
32 | |||
33 | #define RATE_IN_242X (1 << 0) | ||
34 | #define RATE_IN_243X (1 << 1) | ||
35 | |||
36 | /* Memory timings */ | ||
37 | #define M_DDR 1 | ||
38 | #define M_LOCK_CTRL (1 << 2) | ||
39 | #define M_UNLOCK 0 | ||
40 | #define M_LOCK 1 | ||
41 | |||
42 | struct memory_timings { | ||
43 | u32 m_type; /* ddr = 1, sdr = 0 */ | ||
44 | u32 dll_mode; /* use lock mode = 1, unlock mode = 0 */ | ||
45 | u32 slow_dll_ctrl; /* unlock mode, dll value for slow speed */ | ||
46 | u32 fast_dll_ctrl; /* unlock mode, dll value for fast speed */ | ||
47 | u32 base_cs; /* base chip select to use for calculations */ | ||
48 | }; | ||
49 | |||
50 | /* Key dividers which make up a PRCM set. Ratio's for a PRCM are mandated. | ||
51 | * xtal_speed, dpll_speed, mpu_speed, CM_CLKSEL_MPU,CM_CLKSEL_DSP | ||
52 | * CM_CLKSEL_GFX, CM_CLKSEL1_CORE, CM_CLKSEL1_PLL CM_CLKSEL2_PLL, CM_CLKSEL_MDM | ||
53 | */ | ||
54 | struct prcm_config { | ||
55 | unsigned long xtal_speed; /* crystal rate */ | ||
56 | unsigned long dpll_speed; /* dpll: out*xtal*M/(N-1)table_recalc */ | ||
57 | unsigned long mpu_speed; /* speed of MPU */ | ||
58 | unsigned long cm_clksel_mpu; /* mpu divider */ | ||
59 | unsigned long cm_clksel_dsp; /* dsp+iva1 div(2420), iva2.1(2430) */ | ||
60 | unsigned long cm_clksel_gfx; /* gfx dividers */ | ||
61 | unsigned long cm_clksel1_core; /* major subsystem dividers */ | ||
62 | unsigned long cm_clksel1_pll; /* m,n */ | ||
63 | unsigned long cm_clksel2_pll; /* dpllx1 or x2 out */ | ||
64 | unsigned long cm_clksel_mdm; /* modem dividers 2430 only */ | ||
65 | unsigned long base_sdrc_rfr; /* base refresh timing for a set */ | ||
66 | unsigned char flags; | ||
67 | }; | ||
68 | |||
69 | /* Mask for clksel which support parent settign in set_rate */ | ||
70 | #define SRC_SEL_MASK (CM_CORE_SEL1 | CM_CORE_SEL2 | CM_WKUP_SEL1 | \ | ||
71 | CM_PLL_SEL1 | CM_PLL_SEL2 | CM_SYSCLKOUT_SEL1) | ||
72 | |||
73 | /* Mask for clksel regs which support rate operations */ | ||
74 | #define SRC_RATE_SEL_MASK (CM_MPU_SEL1 | CM_DSP_SEL1 | CM_GFX_SEL1 | \ | ||
75 | CM_MODEM_SEL1 | CM_CORE_SEL1 | CM_CORE_SEL2 | \ | ||
76 | CM_WKUP_SEL1 | CM_PLL_SEL1 | CM_PLL_SEL2 | \ | ||
77 | CM_SYSCLKOUT_SEL1) | ||
78 | |||
79 | /* | ||
80 | * The OMAP2 processor can be run at several discrete 'PRCM configurations'. | ||
81 | * These configurations are characterized by voltage and speed for clocks. | ||
82 | * The device is only validated for certain combinations. One way to express | ||
83 | * these combinations is via the 'ratio's' which the clocks operate with | ||
84 | * respect to each other. These ratio sets are for a given voltage/DPLL | ||
85 | * setting. All configurations can be described by a DPLL setting and a ratio | ||
86 | * There are 3 ratio sets for the 2430 and X ratio sets for 2420. | ||
87 | * | ||
88 | * 2430 differs from 2420 in that there are no more phase synchronizers used. | ||
89 | * They both have a slightly different clock domain setup. 2420(iva1,dsp) vs | ||
90 | * 2430 (iva2.1, NOdsp, mdm) | ||
91 | */ | ||
92 | |||
93 | /* Core fields for cm_clksel, not ratio governed */ | ||
94 | #define RX_CLKSEL_DSS1 (0x10 << 8) | ||
95 | #define RX_CLKSEL_DSS2 (0x0 << 13) | ||
96 | #define RX_CLKSEL_SSI (0x5 << 20) | ||
97 | |||
98 | /*------------------------------------------------------------------------- | ||
99 | * Voltage/DPLL ratios | ||
100 | *-------------------------------------------------------------------------*/ | ||
101 | |||
102 | /* 2430 Ratio's, 2430-Ratio Config 1 */ | ||
103 | #define R1_CLKSEL_L3 (4 << 0) | ||
104 | #define R1_CLKSEL_L4 (2 << 5) | ||
105 | #define R1_CLKSEL_USB (4 << 25) | ||
106 | #define R1_CM_CLKSEL1_CORE_VAL R1_CLKSEL_USB | RX_CLKSEL_SSI | \ | ||
107 | RX_CLKSEL_DSS2 | RX_CLKSEL_DSS1 | \ | ||
108 | R1_CLKSEL_L4 | R1_CLKSEL_L3 | ||
109 | #define R1_CLKSEL_MPU (2 << 0) | ||
110 | #define R1_CM_CLKSEL_MPU_VAL R1_CLKSEL_MPU | ||
111 | #define R1_CLKSEL_DSP (2 << 0) | ||
112 | #define R1_CLKSEL_DSP_IF (2 << 5) | ||
113 | #define R1_CM_CLKSEL_DSP_VAL R1_CLKSEL_DSP | R1_CLKSEL_DSP_IF | ||
114 | #define R1_CLKSEL_GFX (2 << 0) | ||
115 | #define R1_CM_CLKSEL_GFX_VAL R1_CLKSEL_GFX | ||
116 | #define R1_CLKSEL_MDM (4 << 0) | ||
117 | #define R1_CM_CLKSEL_MDM_VAL R1_CLKSEL_MDM | ||
118 | |||
119 | /* 2430-Ratio Config 2 */ | ||
120 | #define R2_CLKSEL_L3 (6 << 0) | ||
121 | #define R2_CLKSEL_L4 (2 << 5) | ||
122 | #define R2_CLKSEL_USB (2 << 25) | ||
123 | #define R2_CM_CLKSEL1_CORE_VAL R2_CLKSEL_USB | RX_CLKSEL_SSI | \ | ||
124 | RX_CLKSEL_DSS2 | RX_CLKSEL_DSS1 | \ | ||
125 | R2_CLKSEL_L4 | R2_CLKSEL_L3 | ||
126 | #define R2_CLKSEL_MPU (2 << 0) | ||
127 | #define R2_CM_CLKSEL_MPU_VAL R2_CLKSEL_MPU | ||
128 | #define R2_CLKSEL_DSP (2 << 0) | ||
129 | #define R2_CLKSEL_DSP_IF (3 << 5) | ||
130 | #define R2_CM_CLKSEL_DSP_VAL R2_CLKSEL_DSP | R2_CLKSEL_DSP_IF | ||
131 | #define R2_CLKSEL_GFX (2 << 0) | ||
132 | #define R2_CM_CLKSEL_GFX_VAL R2_CLKSEL_GFX | ||
133 | #define R2_CLKSEL_MDM (6 << 0) | ||
134 | #define R2_CM_CLKSEL_MDM_VAL R2_CLKSEL_MDM | ||
135 | |||
136 | /* 2430-Ratio Bootm (BYPASS) */ | ||
137 | #define RB_CLKSEL_L3 (1 << 0) | ||
138 | #define RB_CLKSEL_L4 (1 << 5) | ||
139 | #define RB_CLKSEL_USB (1 << 25) | ||
140 | #define RB_CM_CLKSEL1_CORE_VAL RB_CLKSEL_USB | RX_CLKSEL_SSI | \ | ||
141 | RX_CLKSEL_DSS2 | RX_CLKSEL_DSS1 | \ | ||
142 | RB_CLKSEL_L4 | RB_CLKSEL_L3 | ||
143 | #define RB_CLKSEL_MPU (1 << 0) | ||
144 | #define RB_CM_CLKSEL_MPU_VAL RB_CLKSEL_MPU | ||
145 | #define RB_CLKSEL_DSP (1 << 0) | ||
146 | #define RB_CLKSEL_DSP_IF (1 << 5) | ||
147 | #define RB_CM_CLKSEL_DSP_VAL RB_CLKSEL_DSP | RB_CLKSEL_DSP_IF | ||
148 | #define RB_CLKSEL_GFX (1 << 0) | ||
149 | #define RB_CM_CLKSEL_GFX_VAL RB_CLKSEL_GFX | ||
150 | #define RB_CLKSEL_MDM (1 << 0) | ||
151 | #define RB_CM_CLKSEL_MDM_VAL RB_CLKSEL_MDM | ||
152 | |||
153 | /* 2420 Ratio Equivalents */ | ||
154 | #define RXX_CLKSEL_VLYNQ (0x12 << 15) | ||
155 | #define RXX_CLKSEL_SSI (0x8 << 20) | ||
156 | |||
157 | /* 2420-PRCM III 532MHz core */ | ||
158 | #define RIII_CLKSEL_L3 (4 << 0) /* 133MHz */ | ||
159 | #define RIII_CLKSEL_L4 (2 << 5) /* 66.5MHz */ | ||
160 | #define RIII_CLKSEL_USB (4 << 25) /* 33.25MHz */ | ||
161 | #define RIII_CM_CLKSEL1_CORE_VAL RIII_CLKSEL_USB | RXX_CLKSEL_SSI | \ | ||
162 | RXX_CLKSEL_VLYNQ | RX_CLKSEL_DSS2 | \ | ||
163 | RX_CLKSEL_DSS1 | RIII_CLKSEL_L4 | \ | ||
164 | RIII_CLKSEL_L3 | ||
165 | #define RIII_CLKSEL_MPU (2 << 0) /* 266MHz */ | ||
166 | #define RIII_CM_CLKSEL_MPU_VAL RIII_CLKSEL_MPU | ||
167 | #define RIII_CLKSEL_DSP (3 << 0) /* c5x - 177.3MHz */ | ||
168 | #define RIII_CLKSEL_DSP_IF (2 << 5) /* c5x - 88.67MHz */ | ||
169 | #define RIII_SYNC_DSP (1 << 7) /* Enable sync */ | ||
170 | #define RIII_CLKSEL_IVA (6 << 8) /* iva1 - 88.67MHz */ | ||
171 | #define RIII_SYNC_IVA (1 << 13) /* Enable sync */ | ||
172 | #define RIII_CM_CLKSEL_DSP_VAL RIII_SYNC_IVA | RIII_CLKSEL_IVA | \ | ||
173 | RIII_SYNC_DSP | RIII_CLKSEL_DSP_IF | \ | ||
174 | RIII_CLKSEL_DSP | ||
175 | #define RIII_CLKSEL_GFX (2 << 0) /* 66.5MHz */ | ||
176 | #define RIII_CM_CLKSEL_GFX_VAL RIII_CLKSEL_GFX | ||
177 | |||
178 | /* 2420-PRCM II 600MHz core */ | ||
179 | #define RII_CLKSEL_L3 (6 << 0) /* 100MHz */ | ||
180 | #define RII_CLKSEL_L4 (2 << 5) /* 50MHz */ | ||
181 | #define RII_CLKSEL_USB (2 << 25) /* 50MHz */ | ||
182 | #define RII_CM_CLKSEL1_CORE_VAL RII_CLKSEL_USB | \ | ||
183 | RXX_CLKSEL_SSI | RXX_CLKSEL_VLYNQ | \ | ||
184 | RX_CLKSEL_DSS2 | RX_CLKSEL_DSS1 | \ | ||
185 | RII_CLKSEL_L4 | RII_CLKSEL_L3 | ||
186 | #define RII_CLKSEL_MPU (2 << 0) /* 300MHz */ | ||
187 | #define RII_CM_CLKSEL_MPU_VAL RII_CLKSEL_MPU | ||
188 | #define RII_CLKSEL_DSP (3 << 0) /* c5x - 200MHz */ | ||
189 | #define RII_CLKSEL_DSP_IF (2 << 5) /* c5x - 100MHz */ | ||
190 | #define RII_SYNC_DSP (0 << 7) /* Bypass sync */ | ||
191 | #define RII_CLKSEL_IVA (6 << 8) /* iva1 - 200MHz */ | ||
192 | #define RII_SYNC_IVA (0 << 13) /* Bypass sync */ | ||
193 | #define RII_CM_CLKSEL_DSP_VAL RII_SYNC_IVA | RII_CLKSEL_IVA | \ | ||
194 | RII_SYNC_DSP | RII_CLKSEL_DSP_IF | \ | ||
195 | RII_CLKSEL_DSP | ||
196 | #define RII_CLKSEL_GFX (2 << 0) /* 50MHz */ | ||
197 | #define RII_CM_CLKSEL_GFX_VAL RII_CLKSEL_GFX | ||
198 | |||
199 | /* 2420-PRCM VII (boot) */ | ||
200 | #define RVII_CLKSEL_L3 (1 << 0) | ||
201 | #define RVII_CLKSEL_L4 (1 << 5) | ||
202 | #define RVII_CLKSEL_DSS1 (1 << 8) | ||
203 | #define RVII_CLKSEL_DSS2 (0 << 13) | ||
204 | #define RVII_CLKSEL_VLYNQ (1 << 15) | ||
205 | #define RVII_CLKSEL_SSI (1 << 20) | ||
206 | #define RVII_CLKSEL_USB (1 << 25) | ||
207 | |||
208 | #define RVII_CM_CLKSEL1_CORE_VAL RVII_CLKSEL_USB | RVII_CLKSEL_SSI | \ | ||
209 | RVII_CLKSEL_VLYNQ | RVII_CLKSEL_DSS2 | \ | ||
210 | RVII_CLKSEL_DSS1 | RVII_CLKSEL_L4 | RVII_CLKSEL_L3 | ||
211 | |||
212 | #define RVII_CLKSEL_MPU (1 << 0) /* all divide by 1 */ | ||
213 | #define RVII_CM_CLKSEL_MPU_VAL RVII_CLKSEL_MPU | ||
214 | |||
215 | #define RVII_CLKSEL_DSP (1 << 0) | ||
216 | #define RVII_CLKSEL_DSP_IF (1 << 5) | ||
217 | #define RVII_SYNC_DSP (0 << 7) | ||
218 | #define RVII_CLKSEL_IVA (1 << 8) | ||
219 | #define RVII_SYNC_IVA (0 << 13) | ||
220 | #define RVII_CM_CLKSEL_DSP_VAL RVII_SYNC_IVA | RVII_CLKSEL_IVA | RVII_SYNC_DSP | \ | ||
221 | RVII_CLKSEL_DSP_IF | RVII_CLKSEL_DSP | ||
222 | |||
223 | #define RVII_CLKSEL_GFX (1 << 0) | ||
224 | #define RVII_CM_CLKSEL_GFX_VAL RVII_CLKSEL_GFX | ||
225 | |||
226 | /*------------------------------------------------------------------------- | ||
227 | * 2430 Target modes: Along with each configuration the CPU has several | ||
228 | * modes which goes along with them. Modes mainly are the addition of | ||
229 | * describe DPLL combinations to go along with a ratio. | ||
230 | *-------------------------------------------------------------------------*/ | ||
231 | |||
232 | /* Hardware governed */ | ||
233 | #define MX_48M_SRC (0 << 3) | ||
234 | #define MX_54M_SRC (0 << 5) | ||
235 | #define MX_APLLS_CLIKIN_12 (3 << 23) | ||
236 | #define MX_APLLS_CLIKIN_13 (2 << 23) | ||
237 | #define MX_APLLS_CLIKIN_19_2 (0 << 23) | ||
238 | |||
239 | /* | ||
240 | * 2430 - standalone, 2*ref*M/(n+1), M/N is for exactness not relock speed | ||
241 | * #2 (ratio1) baseport-target | ||
242 | * #5a (ratio1) baseport-target, target DPLL = 266*2 = 532MHz | ||
243 | */ | ||
244 | #define M5A_DPLL_MULT_12 (133 << 12) | ||
245 | #define M5A_DPLL_DIV_12 (5 << 8) | ||
246 | #define M5A_CM_CLKSEL1_PLL_12_VAL MX_48M_SRC | MX_54M_SRC | \ | ||
247 | M5A_DPLL_DIV_12 | M5A_DPLL_MULT_12 | \ | ||
248 | MX_APLLS_CLIKIN_12 | ||
249 | #define M5A_DPLL_MULT_13 (266 << 12) | ||
250 | #define M5A_DPLL_DIV_13 (12 << 8) | ||
251 | #define M5A_CM_CLKSEL1_PLL_13_VAL MX_48M_SRC | MX_54M_SRC | \ | ||
252 | M5A_DPLL_DIV_13 | M5A_DPLL_MULT_13 | \ | ||
253 | MX_APLLS_CLIKIN_13 | ||
254 | #define M5A_DPLL_MULT_19 (180 << 12) | ||
255 | #define M5A_DPLL_DIV_19 (12 << 8) | ||
256 | #define M5A_CM_CLKSEL1_PLL_19_VAL MX_48M_SRC | MX_54M_SRC | \ | ||
257 | M5A_DPLL_DIV_19 | M5A_DPLL_MULT_19 | \ | ||
258 | MX_APLLS_CLIKIN_19_2 | ||
259 | /* #5b (ratio1) target DPLL = 200*2 = 400MHz */ | ||
260 | #define M5B_DPLL_MULT_12 (50 << 12) | ||
261 | #define M5B_DPLL_DIV_12 (2 << 8) | ||
262 | #define M5B_CM_CLKSEL1_PLL_12_VAL MX_48M_SRC | MX_54M_SRC | \ | ||
263 | M5B_DPLL_DIV_12 | M5B_DPLL_MULT_12 | \ | ||
264 | MX_APLLS_CLIKIN_12 | ||
265 | #define M5B_DPLL_MULT_13 (200 << 12) | ||
266 | #define M5B_DPLL_DIV_13 (12 << 8) | ||
267 | |||
268 | #define M5B_CM_CLKSEL1_PLL_13_VAL MX_48M_SRC | MX_54M_SRC | \ | ||
269 | M5B_DPLL_DIV_13 | M5B_DPLL_MULT_13 | \ | ||
270 | MX_APLLS_CLIKIN_13 | ||
271 | #define M5B_DPLL_MULT_19 (125 << 12) | ||
272 | #define M5B_DPLL_DIV_19 (31 << 8) | ||
273 | #define M5B_CM_CLKSEL1_PLL_19_VAL MX_48M_SRC | MX_54M_SRC | \ | ||
274 | M5B_DPLL_DIV_19 | M5B_DPLL_MULT_19 | \ | ||
275 | MX_APLLS_CLIKIN_19_2 | ||
276 | /* | ||
277 | * #4 (ratio2) | ||
278 | * #3 (ratio2) baseport-target, target DPLL = 330*2 = 660MHz | ||
279 | */ | ||
280 | #define M3_DPLL_MULT_12 (55 << 12) | ||
281 | #define M3_DPLL_DIV_12 (1 << 8) | ||
282 | #define M3_CM_CLKSEL1_PLL_12_VAL MX_48M_SRC | MX_54M_SRC | \ | ||
283 | M3_DPLL_DIV_12 | M3_DPLL_MULT_12 | \ | ||
284 | MX_APLLS_CLIKIN_12 | ||
285 | #define M3_DPLL_MULT_13 (330 << 12) | ||
286 | #define M3_DPLL_DIV_13 (12 << 8) | ||
287 | #define M3_CM_CLKSEL1_PLL_13_VAL MX_48M_SRC | MX_54M_SRC | \ | ||
288 | M3_DPLL_DIV_13 | M3_DPLL_MULT_13 | \ | ||
289 | MX_APLLS_CLIKIN_13 | ||
290 | #define M3_DPLL_MULT_19 (275 << 12) | ||
291 | #define M3_DPLL_DIV_19 (15 << 8) | ||
292 | #define M3_CM_CLKSEL1_PLL_19_VAL MX_48M_SRC | MX_54M_SRC | \ | ||
293 | M3_DPLL_DIV_19 | M3_DPLL_MULT_19 | \ | ||
294 | MX_APLLS_CLIKIN_19_2 | ||
295 | /* boot (boot) */ | ||
296 | #define MB_DPLL_MULT (1 << 12) | ||
297 | #define MB_DPLL_DIV (0 << 8) | ||
298 | #define MB_CM_CLKSEL1_PLL_12_VAL MX_48M_SRC | MX_54M_SRC | MB_DPLL_DIV |\ | ||
299 | MB_DPLL_MULT | MX_APLLS_CLIKIN_12 | ||
300 | |||
301 | #define MB_CM_CLKSEL1_PLL_13_VAL MX_48M_SRC | MX_54M_SRC | MB_DPLL_DIV |\ | ||
302 | MB_DPLL_MULT | MX_APLLS_CLIKIN_13 | ||
303 | |||
304 | #define MB_CM_CLKSEL1_PLL_19_VAL MX_48M_SRC | MX_54M_SRC | MB_DPLL_DIV |\ | ||
305 | MB_DPLL_MULT | MX_APLLS_CLIKIN_19 | ||
306 | |||
307 | /* | ||
308 | * 2430 - chassis (sedna) | ||
309 | * 165 (ratio1) same as above #2 | ||
310 | * 150 (ratio1) | ||
311 | * 133 (ratio2) same as above #4 | ||
312 | * 110 (ratio2) same as above #3 | ||
313 | * 104 (ratio2) | ||
314 | * boot (boot) | ||
315 | */ | ||
316 | |||
317 | /* | ||
318 | * 2420 Equivalent - mode registers | ||
319 | * PRCM II , target DPLL = 2*300MHz = 600MHz | ||
320 | */ | ||
321 | #define MII_DPLL_MULT_12 (50 << 12) | ||
322 | #define MII_DPLL_DIV_12 (1 << 8) | ||
323 | #define MII_CM_CLKSEL1_PLL_12_VAL MX_48M_SRC | MX_54M_SRC | \ | ||
324 | MII_DPLL_DIV_12 | MII_DPLL_MULT_12 | \ | ||
325 | MX_APLLS_CLIKIN_12 | ||
326 | #define MII_DPLL_MULT_13 (300 << 12) | ||
327 | #define MII_DPLL_DIV_13 (12 << 8) | ||
328 | #define MII_CM_CLKSEL1_PLL_13_VAL MX_48M_SRC | MX_54M_SRC | \ | ||
329 | MII_DPLL_DIV_13 | MII_DPLL_MULT_13 | \ | ||
330 | MX_APLLS_CLIKIN_13 | ||
331 | |||
332 | /* PRCM III target DPLL = 2*266 = 532MHz*/ | ||
333 | #define MIII_DPLL_MULT_12 (133 << 12) | ||
334 | #define MIII_DPLL_DIV_12 (5 << 8) | ||
335 | #define MIII_CM_CLKSEL1_PLL_12_VAL MX_48M_SRC | MX_54M_SRC | \ | ||
336 | MIII_DPLL_DIV_12 | MIII_DPLL_MULT_12 | \ | ||
337 | MX_APLLS_CLIKIN_12 | ||
338 | #define MIII_DPLL_MULT_13 (266 << 12) | ||
339 | #define MIII_DPLL_DIV_13 (12 << 8) | ||
340 | #define MIII_CM_CLKSEL1_PLL_13_VAL MX_48M_SRC | MX_54M_SRC | \ | ||
341 | MIII_DPLL_DIV_13 | MIII_DPLL_MULT_13 | \ | ||
342 | MX_APLLS_CLIKIN_13 | ||
343 | |||
344 | /* PRCM VII (boot bypass) */ | ||
345 | #define MVII_CM_CLKSEL1_PLL_12_VAL MB_CM_CLKSEL1_PLL_12_VAL | ||
346 | #define MVII_CM_CLKSEL1_PLL_13_VAL MB_CM_CLKSEL1_PLL_13_VAL | ||
347 | |||
348 | /* High and low operation value */ | ||
349 | #define MX_CLKSEL2_PLL_2x_VAL (2 << 0) | ||
350 | #define MX_CLKSEL2_PLL_1x_VAL (1 << 0) | ||
351 | |||
352 | /* | ||
353 | * These represent optimal values for common parts, it won't work for all. | ||
354 | * As long as you scale down, most parameters are still work, they just | ||
355 | * become sub-optimal. The RFR value goes in the oppisite direction. If you | ||
356 | * don't adjust it down as your clock period increases the refresh interval | ||
357 | * will not be met. Setting all parameters for complete worst case may work, | ||
358 | * but may cut memory performance by 2x. Due to errata the DLLs need to be | ||
359 | * unlocked and their value needs run time calibration. A dynamic call is | ||
360 | * need for that as no single right value exists acorss production samples. | ||
361 | * | ||
362 | * Only the FULL speed values are given. Current code is such that rate | ||
363 | * changes must be made at DPLLoutx2. The actual value adjustment for low | ||
364 | * frequency operation will be handled by omap_set_performance() | ||
365 | * | ||
366 | * By having the boot loader boot up in the fastest L4 speed available likely | ||
367 | * will result in something which you can switch between. | ||
368 | */ | ||
369 | #define V24XX_SDRC_RFR_CTRL_133MHz (0x0003de00 | 1) | ||
370 | #define V24XX_SDRC_RFR_CTRL_100MHz (0x0002da01 | 1) | ||
371 | #define V24XX_SDRC_RFR_CTRL_110MHz (0x0002da01 | 1) /* Need to calc */ | ||
372 | #define V24XX_SDRC_RFR_CTRL_BYPASS (0x00005000 | 1) /* Need to calc */ | ||
373 | |||
374 | /* MPU speed defines */ | ||
375 | #define S12M 12000000 | ||
376 | #define S13M 13000000 | ||
377 | #define S19M 19200000 | ||
378 | #define S26M 26000000 | ||
379 | #define S100M 100000000 | ||
380 | #define S133M 133000000 | ||
381 | #define S150M 150000000 | ||
382 | #define S165M 165000000 | ||
383 | #define S200M 200000000 | ||
384 | #define S266M 266000000 | ||
385 | #define S300M 300000000 | ||
386 | #define S330M 330000000 | ||
387 | #define S400M 400000000 | ||
388 | #define S532M 532000000 | ||
389 | #define S600M 600000000 | ||
390 | #define S660M 660000000 | ||
391 | |||
392 | /*------------------------------------------------------------------------- | ||
393 | * Key dividers which make up a PRCM set. Ratio's for a PRCM are mandated. | ||
394 | * xtal_speed, dpll_speed, mpu_speed, CM_CLKSEL_MPU, | ||
395 | * CM_CLKSEL_DSP, CM_CLKSEL_GFX, CM_CLKSEL1_CORE, CM_CLKSEL1_PLL, | ||
396 | * CM_CLKSEL2_PLL, CM_CLKSEL_MDM | ||
397 | * | ||
398 | * Filling in table based on H4 boards and 2430-SDPs variants available. | ||
399 | * There are quite a few more rates combinations which could be defined. | ||
400 | * | ||
401 | * When multiple values are defiend the start up will try and choose the | ||
402 | * fastest one. If a 'fast' value is defined, then automatically, the /2 | ||
403 | * one should be included as it can be used. Generally having more that | ||
404 | * one fast set does not make sense, as static timings need to be changed | ||
405 | * to change the set. The exception is the bypass setting which is | ||
406 | * availble for low power bypass. | ||
407 | * | ||
408 | * Note: This table needs to be sorted, fastest to slowest. | ||
409 | *-------------------------------------------------------------------------*/ | ||
410 | static struct prcm_config rate_table[] = { | ||
411 | /* PRCM II - FAST */ | ||
412 | {S12M, S600M, S300M, RII_CM_CLKSEL_MPU_VAL, /* 300MHz ARM */ | ||
413 | RII_CM_CLKSEL_DSP_VAL, RII_CM_CLKSEL_GFX_VAL, | ||
414 | RII_CM_CLKSEL1_CORE_VAL, MII_CM_CLKSEL1_PLL_12_VAL, | ||
415 | MX_CLKSEL2_PLL_2x_VAL, 0, V24XX_SDRC_RFR_CTRL_100MHz, | ||
416 | RATE_IN_242X}, | ||
417 | |||
418 | {S13M, S600M, S300M, RII_CM_CLKSEL_MPU_VAL, /* 300MHz ARM */ | ||
419 | RII_CM_CLKSEL_DSP_VAL, RII_CM_CLKSEL_GFX_VAL, | ||
420 | RII_CM_CLKSEL1_CORE_VAL, MII_CM_CLKSEL1_PLL_13_VAL, | ||
421 | MX_CLKSEL2_PLL_2x_VAL, 0, V24XX_SDRC_RFR_CTRL_100MHz, | ||
422 | RATE_IN_242X}, | ||
423 | |||
424 | /* PRCM III - FAST */ | ||
425 | {S12M, S532M, S266M, RIII_CM_CLKSEL_MPU_VAL, /* 266MHz ARM */ | ||
426 | RIII_CM_CLKSEL_DSP_VAL, RIII_CM_CLKSEL_GFX_VAL, | ||
427 | RIII_CM_CLKSEL1_CORE_VAL, MIII_CM_CLKSEL1_PLL_12_VAL, | ||
428 | MX_CLKSEL2_PLL_2x_VAL, 0, V24XX_SDRC_RFR_CTRL_133MHz, | ||
429 | RATE_IN_242X}, | ||
430 | |||
431 | {S13M, S532M, S266M, RIII_CM_CLKSEL_MPU_VAL, /* 266MHz ARM */ | ||
432 | RIII_CM_CLKSEL_DSP_VAL, RIII_CM_CLKSEL_GFX_VAL, | ||
433 | RIII_CM_CLKSEL1_CORE_VAL, MIII_CM_CLKSEL1_PLL_13_VAL, | ||
434 | MX_CLKSEL2_PLL_2x_VAL, 0, V24XX_SDRC_RFR_CTRL_133MHz, | ||
435 | RATE_IN_242X}, | ||
436 | |||
437 | /* PRCM II - SLOW */ | ||
438 | {S12M, S300M, S150M, RII_CM_CLKSEL_MPU_VAL, /* 150MHz ARM */ | ||
439 | RII_CM_CLKSEL_DSP_VAL, RII_CM_CLKSEL_GFX_VAL, | ||
440 | RII_CM_CLKSEL1_CORE_VAL, MII_CM_CLKSEL1_PLL_12_VAL, | ||
441 | MX_CLKSEL2_PLL_2x_VAL, 0, V24XX_SDRC_RFR_CTRL_100MHz, | ||
442 | RATE_IN_242X}, | ||
443 | |||
444 | {S13M, S300M, S150M, RII_CM_CLKSEL_MPU_VAL, /* 150MHz ARM */ | ||
445 | RII_CM_CLKSEL_DSP_VAL, RII_CM_CLKSEL_GFX_VAL, | ||
446 | RII_CM_CLKSEL1_CORE_VAL, MII_CM_CLKSEL1_PLL_13_VAL, | ||
447 | MX_CLKSEL2_PLL_2x_VAL, 0, V24XX_SDRC_RFR_CTRL_100MHz, | ||
448 | RATE_IN_242X}, | ||
449 | |||
450 | /* PRCM III - SLOW */ | ||
451 | {S12M, S266M, S133M, RIII_CM_CLKSEL_MPU_VAL, /* 133MHz ARM */ | ||
452 | RIII_CM_CLKSEL_DSP_VAL, RIII_CM_CLKSEL_GFX_VAL, | ||
453 | RIII_CM_CLKSEL1_CORE_VAL, MIII_CM_CLKSEL1_PLL_12_VAL, | ||
454 | MX_CLKSEL2_PLL_2x_VAL, 0, V24XX_SDRC_RFR_CTRL_133MHz, | ||
455 | RATE_IN_242X}, | ||
456 | |||
457 | {S13M, S266M, S133M, RIII_CM_CLKSEL_MPU_VAL, /* 133MHz ARM */ | ||
458 | RIII_CM_CLKSEL_DSP_VAL, RIII_CM_CLKSEL_GFX_VAL, | ||
459 | RIII_CM_CLKSEL1_CORE_VAL, MIII_CM_CLKSEL1_PLL_13_VAL, | ||
460 | MX_CLKSEL2_PLL_2x_VAL, 0, V24XX_SDRC_RFR_CTRL_133MHz, | ||
461 | RATE_IN_242X}, | ||
462 | |||
463 | /* PRCM-VII (boot-bypass) */ | ||
464 | {S12M, S12M, S12M, RVII_CM_CLKSEL_MPU_VAL, /* 12MHz ARM*/ | ||
465 | RVII_CM_CLKSEL_DSP_VAL, RVII_CM_CLKSEL_GFX_VAL, | ||
466 | RVII_CM_CLKSEL1_CORE_VAL, MVII_CM_CLKSEL1_PLL_12_VAL, | ||
467 | MX_CLKSEL2_PLL_2x_VAL, 0, V24XX_SDRC_RFR_CTRL_BYPASS, | ||
468 | RATE_IN_242X}, | ||
469 | |||
470 | /* PRCM-VII (boot-bypass) */ | ||
471 | {S13M, S13M, S13M, RVII_CM_CLKSEL_MPU_VAL, /* 13MHz ARM */ | ||
472 | RVII_CM_CLKSEL_DSP_VAL, RVII_CM_CLKSEL_GFX_VAL, | ||
473 | RVII_CM_CLKSEL1_CORE_VAL, MVII_CM_CLKSEL1_PLL_13_VAL, | ||
474 | MX_CLKSEL2_PLL_2x_VAL, 0, V24XX_SDRC_RFR_CTRL_BYPASS, | ||
475 | RATE_IN_242X}, | ||
476 | |||
477 | /* PRCM #3 - ratio2 (ES2) - FAST */ | ||
478 | {S13M, S660M, S330M, R2_CM_CLKSEL_MPU_VAL, /* 330MHz ARM */ | ||
479 | R2_CM_CLKSEL_DSP_VAL, R2_CM_CLKSEL_GFX_VAL, | ||
480 | R2_CM_CLKSEL1_CORE_VAL, M3_CM_CLKSEL1_PLL_13_VAL, | ||
481 | MX_CLKSEL2_PLL_2x_VAL, R2_CM_CLKSEL_MDM_VAL, | ||
482 | V24XX_SDRC_RFR_CTRL_110MHz, | ||
483 | RATE_IN_243X}, | ||
484 | |||
485 | /* PRCM #5a - ratio1 - FAST */ | ||
486 | {S13M, S532M, S266M, R1_CM_CLKSEL_MPU_VAL, /* 266MHz ARM */ | ||
487 | R1_CM_CLKSEL_DSP_VAL, R1_CM_CLKSEL_GFX_VAL, | ||
488 | R1_CM_CLKSEL1_CORE_VAL, M5A_CM_CLKSEL1_PLL_13_VAL, | ||
489 | MX_CLKSEL2_PLL_2x_VAL, R1_CM_CLKSEL_MDM_VAL, | ||
490 | V24XX_SDRC_RFR_CTRL_133MHz, | ||
491 | RATE_IN_243X}, | ||
492 | |||
493 | /* PRCM #5b - ratio1 - FAST */ | ||
494 | {S13M, S400M, S200M, R1_CM_CLKSEL_MPU_VAL, /* 200MHz ARM */ | ||
495 | R1_CM_CLKSEL_DSP_VAL, R1_CM_CLKSEL_GFX_VAL, | ||
496 | R1_CM_CLKSEL1_CORE_VAL, M5B_CM_CLKSEL1_PLL_13_VAL, | ||
497 | MX_CLKSEL2_PLL_2x_VAL, R1_CM_CLKSEL_MDM_VAL, | ||
498 | V24XX_SDRC_RFR_CTRL_100MHz, | ||
499 | RATE_IN_243X}, | ||
500 | |||
501 | /* PRCM #3 - ratio2 (ES2) - SLOW */ | ||
502 | {S13M, S330M, S165M, R2_CM_CLKSEL_MPU_VAL, /* 165MHz ARM */ | ||
503 | R2_CM_CLKSEL_DSP_VAL, R2_CM_CLKSEL_GFX_VAL, | ||
504 | R2_CM_CLKSEL1_CORE_VAL, M3_CM_CLKSEL1_PLL_13_VAL, | ||
505 | MX_CLKSEL2_PLL_1x_VAL, R2_CM_CLKSEL_MDM_VAL, | ||
506 | V24XX_SDRC_RFR_CTRL_110MHz, | ||
507 | RATE_IN_243X}, | ||
508 | |||
509 | /* PRCM #5a - ratio1 - SLOW */ | ||
510 | {S13M, S266M, S133M, R1_CM_CLKSEL_MPU_VAL, /* 133MHz ARM */ | ||
511 | R1_CM_CLKSEL_DSP_VAL, R1_CM_CLKSEL_GFX_VAL, | ||
512 | R1_CM_CLKSEL1_CORE_VAL, M5A_CM_CLKSEL1_PLL_13_VAL, | ||
513 | MX_CLKSEL2_PLL_1x_VAL, R1_CM_CLKSEL_MDM_VAL, | ||
514 | V24XX_SDRC_RFR_CTRL_133MHz, | ||
515 | RATE_IN_243X}, | ||
516 | |||
517 | /* PRCM #5b - ratio1 - SLOW*/ | ||
518 | {S13M, S200M, S100M, R1_CM_CLKSEL_MPU_VAL, /* 100MHz ARM */ | ||
519 | R1_CM_CLKSEL_DSP_VAL, R1_CM_CLKSEL_GFX_VAL, | ||
520 | R1_CM_CLKSEL1_CORE_VAL, M5B_CM_CLKSEL1_PLL_13_VAL, | ||
521 | MX_CLKSEL2_PLL_1x_VAL, R1_CM_CLKSEL_MDM_VAL, | ||
522 | V24XX_SDRC_RFR_CTRL_100MHz, | ||
523 | RATE_IN_243X}, | ||
524 | |||
525 | /* PRCM-boot/bypass */ | ||
526 | {S13M, S13M, S13M, RB_CM_CLKSEL_MPU_VAL, /* 13Mhz */ | ||
527 | RB_CM_CLKSEL_DSP_VAL, RB_CM_CLKSEL_GFX_VAL, | ||
528 | RB_CM_CLKSEL1_CORE_VAL, MB_CM_CLKSEL1_PLL_13_VAL, | ||
529 | MX_CLKSEL2_PLL_2x_VAL, RB_CM_CLKSEL_MDM_VAL, | ||
530 | V24XX_SDRC_RFR_CTRL_BYPASS, | ||
531 | RATE_IN_243X}, | ||
532 | |||
533 | /* PRCM-boot/bypass */ | ||
534 | {S12M, S12M, S12M, RB_CM_CLKSEL_MPU_VAL, /* 12Mhz */ | ||
535 | RB_CM_CLKSEL_DSP_VAL, RB_CM_CLKSEL_GFX_VAL, | ||
536 | RB_CM_CLKSEL1_CORE_VAL, MB_CM_CLKSEL1_PLL_12_VAL, | ||
537 | MX_CLKSEL2_PLL_2x_VAL, RB_CM_CLKSEL_MDM_VAL, | ||
538 | V24XX_SDRC_RFR_CTRL_BYPASS, | ||
539 | RATE_IN_243X}, | ||
540 | |||
541 | { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, | ||
542 | }; | ||
543 | |||
544 | /*------------------------------------------------------------------------- | ||
545 | * 24xx clock tree. | ||
546 | * | ||
547 | * NOTE:In many cases here we are assigning a 'default' parent. In many | ||
548 | * cases the parent is selectable. The get/set parent calls will also | ||
549 | * switch sources. | ||
550 | * | ||
551 | * Many some clocks say always_enabled, but they can be auto idled for | ||
552 | * power savings. They will always be available upon clock request. | ||
553 | * | ||
554 | * Several sources are given initial rates which may be wrong, this will | ||
555 | * be fixed up in the init func. | ||
556 | * | ||
557 | * Things are broadly separated below by clock domains. It is | ||
558 | * noteworthy that most periferals have dependencies on multiple clock | ||
559 | * domains. Many get their interface clocks from the L4 domain, but get | ||
560 | * functional clocks from fixed sources or other core domain derived | ||
561 | * clocks. | ||
562 | *-------------------------------------------------------------------------*/ | ||
563 | |||
564 | /* Base external input clocks */ | ||
565 | static struct clk func_32k_ck = { | ||
566 | .name = "func_32k_ck", | ||
567 | .rate = 32000, | ||
568 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | | ||
569 | RATE_FIXED | ALWAYS_ENABLED, | ||
570 | }; | ||
571 | |||
572 | /* Typical 12/13MHz in standalone mode, will be 26Mhz in chassis mode */ | ||
573 | static struct clk osc_ck = { /* (*12, *13, 19.2, *26, 38.4)MHz */ | ||
574 | .name = "osc_ck", | ||
575 | .rate = 26000000, /* fixed up in clock init */ | ||
576 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | | ||
577 | RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES, | ||
578 | }; | ||
579 | |||
580 | /* With out modem likely 12MHz, with modem likely 13MHz */ | ||
581 | static struct clk sys_ck = { /* (*12, *13, 19.2, 26, 38.4)MHz */ | ||
582 | .name = "sys_ck", /* ~ ref_clk also */ | ||
583 | .parent = &osc_ck, | ||
584 | .rate = 13000000, | ||
585 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | | ||
586 | RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES, | ||
587 | .rate_offset = 6, /* sysclkdiv 1 or 2, already handled or no boot */ | ||
588 | .recalc = &omap2_sys_clk_recalc, | ||
589 | }; | ||
590 | |||
591 | static struct clk alt_ck = { /* Typical 54M or 48M, may not exist */ | ||
592 | .name = "alt_ck", | ||
593 | .rate = 54000000, | ||
594 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | | ||
595 | RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES, | ||
596 | .recalc = &omap2_propagate_rate, | ||
597 | }; | ||
598 | |||
599 | /* | ||
600 | * Analog domain root source clocks | ||
601 | */ | ||
602 | |||
603 | /* dpll_ck, is broken out in to special cases through clksel */ | ||
604 | static struct clk dpll_ck = { | ||
605 | .name = "dpll_ck", | ||
606 | .parent = &sys_ck, /* Can be func_32k also */ | ||
607 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | | ||
608 | RATE_PROPAGATES | RATE_CKCTL | CM_PLL_SEL1, | ||
609 | .recalc = &omap2_clksel_recalc, | ||
610 | }; | ||
611 | |||
612 | static struct clk apll96_ck = { | ||
613 | .name = "apll96_ck", | ||
614 | .parent = &sys_ck, | ||
615 | .rate = 96000000, | ||
616 | .flags = CLOCK_IN_OMAP242X |CLOCK_IN_OMAP243X | | ||
617 | RATE_FIXED | RATE_PROPAGATES, | ||
618 | .enable_reg = (void __iomem *)&CM_CLKEN_PLL, | ||
619 | .enable_bit = 0x2, | ||
620 | .recalc = &omap2_propagate_rate, | ||
621 | }; | ||
622 | |||
623 | static struct clk apll54_ck = { | ||
624 | .name = "apll54_ck", | ||
625 | .parent = &sys_ck, | ||
626 | .rate = 54000000, | ||
627 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | | ||
628 | RATE_FIXED | RATE_PROPAGATES, | ||
629 | .enable_reg = (void __iomem *)&CM_CLKEN_PLL, | ||
630 | .enable_bit = 0x6, | ||
631 | .recalc = &omap2_propagate_rate, | ||
632 | }; | ||
633 | |||
634 | /* | ||
635 | * PRCM digital base sources | ||
636 | */ | ||
637 | static struct clk func_54m_ck = { | ||
638 | .name = "func_54m_ck", | ||
639 | .parent = &apll54_ck, /* can also be alt_clk */ | ||
640 | .rate = 54000000, | ||
641 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | | ||
642 | RATE_FIXED | CM_PLL_SEL1 | RATE_PROPAGATES, | ||
643 | .src_offset = 5, | ||
644 | .enable_reg = (void __iomem *)&CM_CLKEN_PLL, | ||
645 | .enable_bit = 0xff, | ||
646 | .recalc = &omap2_propagate_rate, | ||
647 | }; | ||
648 | |||
649 | static struct clk core_ck = { | ||
650 | .name = "core_ck", | ||
651 | .parent = &dpll_ck, /* can also be 32k */ | ||
652 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | | ||
653 | ALWAYS_ENABLED | RATE_PROPAGATES, | ||
654 | .recalc = &omap2_propagate_rate, | ||
655 | }; | ||
656 | |||
657 | static struct clk sleep_ck = { /* sys_clk or 32k */ | ||
658 | .name = "sleep_ck", | ||
659 | .parent = &func_32k_ck, | ||
660 | .rate = 32000, | ||
661 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | ||
662 | .recalc = &omap2_propagate_rate, | ||
663 | }; | ||
664 | |||
665 | static struct clk func_96m_ck = { | ||
666 | .name = "func_96m_ck", | ||
667 | .parent = &apll96_ck, | ||
668 | .rate = 96000000, | ||
669 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | | ||
670 | RATE_FIXED | RATE_PROPAGATES, | ||
671 | .enable_reg = (void __iomem *)&CM_CLKEN_PLL, | ||
672 | .enable_bit = 0xff, | ||
673 | .recalc = &omap2_propagate_rate, | ||
674 | }; | ||
675 | |||
676 | static struct clk func_48m_ck = { | ||
677 | .name = "func_48m_ck", | ||
678 | .parent = &apll96_ck, /* 96M or Alt */ | ||
679 | .rate = 48000000, | ||
680 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | | ||
681 | RATE_FIXED | CM_PLL_SEL1 | RATE_PROPAGATES, | ||
682 | .src_offset = 3, | ||
683 | .enable_reg = (void __iomem *)&CM_CLKEN_PLL, | ||
684 | .enable_bit = 0xff, | ||
685 | .recalc = &omap2_propagate_rate, | ||
686 | }; | ||
687 | |||
688 | static struct clk func_12m_ck = { | ||
689 | .name = "func_12m_ck", | ||
690 | .parent = &func_48m_ck, | ||
691 | .rate = 12000000, | ||
692 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | | ||
693 | RATE_FIXED | RATE_PROPAGATES, | ||
694 | .recalc = &omap2_propagate_rate, | ||
695 | .enable_reg = (void __iomem *)&CM_CLKEN_PLL, | ||
696 | .enable_bit = 0xff, | ||
697 | }; | ||
698 | |||
699 | /* Secure timer, only available in secure mode */ | ||
700 | static struct clk wdt1_osc_ck = { | ||
701 | .name = "ck_wdt1_osc", | ||
702 | .parent = &osc_ck, | ||
703 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | ||
704 | .recalc = &omap2_followparent_recalc, | ||
705 | }; | ||
706 | |||
707 | static struct clk sys_clkout = { | ||
708 | .name = "sys_clkout", | ||
709 | .parent = &func_54m_ck, | ||
710 | .rate = 54000000, | ||
711 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | | ||
712 | CM_SYSCLKOUT_SEL1 | RATE_CKCTL, | ||
713 | .src_offset = 0, | ||
714 | .enable_reg = (void __iomem *)&PRCM_CLKOUT_CTRL, | ||
715 | .enable_bit = 7, | ||
716 | .rate_offset = 3, | ||
717 | .recalc = &omap2_clksel_recalc, | ||
718 | }; | ||
719 | |||
720 | /* In 2430, new in 2420 ES2 */ | ||
721 | static struct clk sys_clkout2 = { | ||
722 | .name = "sys_clkout2", | ||
723 | .parent = &func_54m_ck, | ||
724 | .rate = 54000000, | ||
725 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | | ||
726 | CM_SYSCLKOUT_SEL1 | RATE_CKCTL, | ||
727 | .src_offset = 8, | ||
728 | .enable_reg = (void __iomem *)&PRCM_CLKOUT_CTRL, | ||
729 | .enable_bit = 15, | ||
730 | .rate_offset = 11, | ||
731 | .recalc = &omap2_clksel_recalc, | ||
732 | }; | ||
733 | |||
734 | /* | ||
735 | * MPU clock domain | ||
736 | * Clocks: | ||
737 | * MPU_FCLK, MPU_ICLK | ||
738 | * INT_M_FCLK, INT_M_I_CLK | ||
739 | * | ||
740 | * - Individual clocks are hardware managed. | ||
741 | * - Base divider comes from: CM_CLKSEL_MPU | ||
742 | * | ||
743 | */ | ||
744 | static struct clk mpu_ck = { /* Control cpu */ | ||
745 | .name = "mpu_ck", | ||
746 | .parent = &core_ck, | ||
747 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | RATE_CKCTL | | ||
748 | ALWAYS_ENABLED | CM_MPU_SEL1 | DELAYED_APP | | ||
749 | CONFIG_PARTICIPANT | RATE_PROPAGATES, | ||
750 | .rate_offset = 0, /* bits 0-4 */ | ||
751 | .recalc = &omap2_clksel_recalc, | ||
752 | }; | ||
753 | |||
754 | /* | ||
755 | * DSP (2430-IVA2.1) (2420-UMA+IVA1) clock domain | ||
756 | * Clocks: | ||
757 | * 2430: IVA2.1_FCLK, IVA2.1_ICLK | ||
758 | * 2420: UMA_FCLK, UMA_ICLK, IVA_MPU, IVA_COP | ||
759 | */ | ||
760 | static struct clk iva2_1_fck = { | ||
761 | .name = "iva2_1_fck", | ||
762 | .parent = &core_ck, | ||
763 | .flags = CLOCK_IN_OMAP243X | RATE_CKCTL | CM_DSP_SEL1 | | ||
764 | DELAYED_APP | RATE_PROPAGATES | | ||
765 | CONFIG_PARTICIPANT, | ||
766 | .rate_offset = 0, | ||
767 | .enable_reg = (void __iomem *)&CM_FCLKEN_DSP, | ||
768 | .enable_bit = 0, | ||
769 | .recalc = &omap2_clksel_recalc, | ||
770 | }; | ||
771 | |||
772 | static struct clk iva2_1_ick = { | ||
773 | .name = "iva2_1_ick", | ||
774 | .parent = &iva2_1_fck, | ||
775 | .flags = CLOCK_IN_OMAP243X | RATE_CKCTL | CM_DSP_SEL1 | | ||
776 | DELAYED_APP | CONFIG_PARTICIPANT, | ||
777 | .rate_offset = 5, | ||
778 | .recalc = &omap2_clksel_recalc, | ||
779 | }; | ||
780 | |||
781 | /* | ||
782 | * Won't be too specific here. The core clock comes into this block | ||
783 | * it is divided then tee'ed. One branch goes directly to xyz enable | ||
784 | * controls. The other branch gets further divided by 2 then possibly | ||
785 | * routed into a synchronizer and out of clocks abc. | ||
786 | */ | ||
787 | static struct clk dsp_fck = { | ||
788 | .name = "dsp_fck", | ||
789 | .parent = &core_ck, | ||
790 | .flags = CLOCK_IN_OMAP242X | RATE_CKCTL | CM_DSP_SEL1 | | ||
791 | DELAYED_APP | CONFIG_PARTICIPANT | RATE_PROPAGATES, | ||
792 | .rate_offset = 0, | ||
793 | .enable_reg = (void __iomem *)&CM_FCLKEN_DSP, | ||
794 | .enable_bit = 0, | ||
795 | .recalc = &omap2_clksel_recalc, | ||
796 | }; | ||
797 | |||
798 | static struct clk dsp_ick = { | ||
799 | .name = "dsp_ick", /* apparently ipi and isp */ | ||
800 | .parent = &dsp_fck, | ||
801 | .flags = CLOCK_IN_OMAP242X | RATE_CKCTL | CM_DSP_SEL1 | | ||
802 | DELAYED_APP | CONFIG_PARTICIPANT, | ||
803 | .rate_offset = 5, | ||
804 | .enable_reg = (void __iomem *)&CM_ICLKEN_DSP, | ||
805 | .enable_bit = 1, /* for ipi */ | ||
806 | .recalc = &omap2_clksel_recalc, | ||
807 | }; | ||
808 | |||
809 | static struct clk iva1_ifck = { | ||
810 | .name = "iva1_ifck", | ||
811 | .parent = &core_ck, | ||
812 | .flags = CLOCK_IN_OMAP242X | CM_DSP_SEL1 | RATE_CKCTL | | ||
813 | CONFIG_PARTICIPANT | RATE_PROPAGATES | DELAYED_APP, | ||
814 | .rate_offset= 8, | ||
815 | .enable_reg = (void __iomem *)&CM_FCLKEN_DSP, | ||
816 | .enable_bit = 10, | ||
817 | .recalc = &omap2_clksel_recalc, | ||
818 | }; | ||
819 | |||
820 | /* IVA1 mpu/int/i/f clocks are /2 of parent */ | ||
821 | static struct clk iva1_mpu_int_ifck = { | ||
822 | .name = "iva1_mpu_int_ifck", | ||
823 | .parent = &iva1_ifck, | ||
824 | .flags = CLOCK_IN_OMAP242X | RATE_CKCTL | CM_DSP_SEL1, | ||
825 | .enable_reg = (void __iomem *)&CM_FCLKEN_DSP, | ||
826 | .enable_bit = 8, | ||
827 | .recalc = &omap2_clksel_recalc, | ||
828 | }; | ||
829 | |||
830 | /* | ||
831 | * L3 clock domain | ||
832 | * L3 clocks are used for both interface and functional clocks to | ||
833 | * multiple entities. Some of these clocks are completely managed | ||
834 | * by hardware, and some others allow software control. Hardware | ||
835 | * managed ones general are based on directly CLK_REQ signals and | ||
836 | * various auto idle settings. The functional spec sets many of these | ||
837 | * as 'tie-high' for their enables. | ||
838 | * | ||
839 | * I-CLOCKS: | ||
840 | * L3-Interconnect, SMS, GPMC, SDRC, OCM_RAM, OCM_ROM, SDMA | ||
841 | * CAM, HS-USB. | ||
842 | * F-CLOCK | ||
843 | * SSI. | ||
844 | * | ||
845 | * GPMC memories and SDRC have timing and clock sensitive registers which | ||
846 | * may very well need notification when the clock changes. Currently for low | ||
847 | * operating points, these are taken care of in sleep.S. | ||
848 | */ | ||
849 | static struct clk core_l3_ck = { /* Used for ick and fck, interconnect */ | ||
850 | .name = "core_l3_ck", | ||
851 | .parent = &core_ck, | ||
852 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | | ||
853 | RATE_CKCTL | ALWAYS_ENABLED | CM_CORE_SEL1 | | ||
854 | DELAYED_APP | CONFIG_PARTICIPANT | | ||
855 | RATE_PROPAGATES, | ||
856 | .rate_offset = 0, | ||
857 | .recalc = &omap2_clksel_recalc, | ||
858 | }; | ||
859 | |||
860 | static struct clk usb_l4_ick = { /* FS-USB interface clock */ | ||
861 | .name = "usb_l4_ick", | ||
862 | .parent = &core_ck, | ||
863 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | | ||
864 | RATE_CKCTL | CM_CORE_SEL1 | DELAYED_APP | | ||
865 | CONFIG_PARTICIPANT, | ||
866 | .enable_reg = (void __iomem *)&CM_ICLKEN2_CORE, | ||
867 | .enable_bit = 0, | ||
868 | .rate_offset = 25, | ||
869 | .recalc = &omap2_clksel_recalc, | ||
870 | }; | ||
871 | |||
872 | /* | ||
873 | * SSI is in L3 management domain, its direct parent is core not l3, | ||
874 | * many core power domain entities are grouped into the L3 clock | ||
875 | * domain. | ||
876 | * SSI_SSR_FCLK, SSI_SST_FCLK, SSI_L4_CLIK | ||
877 | * | ||
878 | * ssr = core/1/2/3/4/5, sst = 1/2 ssr. | ||
879 | */ | ||
880 | static struct clk ssi_ssr_sst_fck = { | ||
881 | .name = "ssi_fck", | ||
882 | .parent = &core_ck, | ||
883 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | | ||
884 | RATE_CKCTL | CM_CORE_SEL1 | DELAYED_APP, | ||
885 | .enable_reg = (void __iomem *)&CM_FCLKEN2_CORE, /* bit 1 */ | ||
886 | .enable_bit = 1, | ||
887 | .rate_offset = 20, | ||
888 | .recalc = &omap2_clksel_recalc, | ||
889 | }; | ||
890 | |||
891 | /* | ||
892 | * GFX clock domain | ||
893 | * Clocks: | ||
894 | * GFX_FCLK, GFX_ICLK | ||
895 | * GFX_CG1(2d), GFX_CG2(3d) | ||
896 | * | ||
897 | * GFX_FCLK runs from L3, and is divided by (1,2,3,4) | ||
898 | * The 2d and 3d clocks run at a hardware determined | ||
899 | * divided value of fclk. | ||
900 | * | ||
901 | */ | ||
902 | static struct clk gfx_3d_fck = { | ||
903 | .name = "gfx_3d_fck", | ||
904 | .parent = &core_l3_ck, | ||
905 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | | ||
906 | RATE_CKCTL | CM_GFX_SEL1, | ||
907 | .enable_reg = (void __iomem *)&CM_FCLKEN_GFX, | ||
908 | .enable_bit = 2, | ||
909 | .rate_offset= 0, | ||
910 | .recalc = &omap2_clksel_recalc, | ||
911 | }; | ||
912 | |||
913 | static struct clk gfx_2d_fck = { | ||
914 | .name = "gfx_2d_fck", | ||
915 | .parent = &core_l3_ck, | ||
916 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | | ||
917 | RATE_CKCTL | CM_GFX_SEL1, | ||
918 | .enable_reg = (void __iomem *)&CM_FCLKEN_GFX, | ||
919 | .enable_bit = 1, | ||
920 | .rate_offset= 0, | ||
921 | .recalc = &omap2_clksel_recalc, | ||
922 | }; | ||
923 | |||
924 | static struct clk gfx_ick = { | ||
925 | .name = "gfx_ick", /* From l3 */ | ||
926 | .parent = &core_l3_ck, | ||
927 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | | ||
928 | RATE_CKCTL, | ||
929 | .enable_reg = (void __iomem *)&CM_ICLKEN_GFX, /* bit 0 */ | ||
930 | .enable_bit = 0, | ||
931 | .recalc = &omap2_followparent_recalc, | ||
932 | }; | ||
933 | |||
934 | /* | ||
935 | * Modem clock domain (2430) | ||
936 | * CLOCKS: | ||
937 | * MDM_OSC_CLK | ||
938 | * MDM_ICLK | ||
939 | */ | ||
940 | static struct clk mdm_ick = { /* used both as a ick and fck */ | ||
941 | .name = "mdm_ick", | ||
942 | .parent = &core_ck, | ||
943 | .flags = CLOCK_IN_OMAP243X | RATE_CKCTL | CM_MODEM_SEL1 | | ||
944 | DELAYED_APP | CONFIG_PARTICIPANT, | ||
945 | .rate_offset = 0, | ||
946 | .enable_reg = (void __iomem *)&CM_ICLKEN_MDM, | ||
947 | .enable_bit = 0, | ||
948 | .recalc = &omap2_clksel_recalc, | ||
949 | }; | ||
950 | |||
951 | static struct clk mdm_osc_ck = { | ||
952 | .name = "mdm_osc_ck", | ||
953 | .rate = 26000000, | ||
954 | .parent = &osc_ck, | ||
955 | .flags = CLOCK_IN_OMAP243X | RATE_FIXED, | ||
956 | .enable_reg = (void __iomem *)&CM_FCLKEN_MDM, | ||
957 | .enable_bit = 1, | ||
958 | .recalc = &omap2_followparent_recalc, | ||
959 | }; | ||
960 | |||
961 | /* | ||
962 | * L4 clock management domain | ||
963 | * | ||
964 | * This domain contains lots of interface clocks from the L4 interface, some | ||
965 | * functional clocks. Fixed APLL functional source clocks are managed in | ||
966 | * this domain. | ||
967 | */ | ||
968 | static struct clk l4_ck = { /* used both as an ick and fck */ | ||
969 | .name = "l4_ck", | ||
970 | .parent = &core_l3_ck, | ||
971 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | | ||
972 | RATE_CKCTL | ALWAYS_ENABLED | CM_CORE_SEL1 | | ||
973 | DELAYED_APP | RATE_PROPAGATES, | ||
974 | .rate_offset = 5, | ||
975 | .recalc = &omap2_clksel_recalc, | ||
976 | }; | ||
977 | |||
978 | static struct clk ssi_l4_ick = { | ||
979 | .name = "ssi_l4_ick", | ||
980 | .parent = &l4_ck, | ||
981 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | RATE_CKCTL, | ||
982 | .enable_reg = (void __iomem *)&CM_ICLKEN2_CORE, /* bit 1 */ | ||
983 | .enable_bit = 1, | ||
984 | .recalc = &omap2_followparent_recalc, | ||
985 | }; | ||
986 | |||
987 | /* | ||
988 | * DSS clock domain | ||
989 | * CLOCKs: | ||
990 | * DSS_L4_ICLK, DSS_L3_ICLK, | ||
991 | * DSS_CLK1, DSS_CLK2, DSS_54MHz_CLK | ||
992 | * | ||
993 | * DSS is both initiator and target. | ||
994 | */ | ||
995 | static struct clk dss_ick = { /* Enables both L3,L4 ICLK's */ | ||
996 | .name = "dss_ick", | ||
997 | .parent = &l4_ck, /* really both l3 and l4 */ | ||
998 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | RATE_CKCTL, | ||
999 | .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, | ||
1000 | .enable_bit = 0, | ||
1001 | .recalc = &omap2_followparent_recalc, | ||
1002 | }; | ||
1003 | |||
1004 | static struct clk dss1_fck = { | ||
1005 | .name = "dss1_fck", | ||
1006 | .parent = &core_ck, /* Core or sys */ | ||
1007 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | | ||
1008 | RATE_CKCTL | CM_CORE_SEL1 | DELAYED_APP, | ||
1009 | .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE, | ||
1010 | .enable_bit = 0, | ||
1011 | .rate_offset = 8, | ||
1012 | .src_offset = 8, | ||
1013 | .recalc = &omap2_clksel_recalc, | ||
1014 | }; | ||
1015 | |||
1016 | static struct clk dss2_fck = { /* Alt clk used in power management */ | ||
1017 | .name = "dss2_fck", | ||
1018 | .parent = &sys_ck, /* fixed at sys_ck or 48MHz */ | ||
1019 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | | ||
1020 | RATE_CKCTL | CM_CORE_SEL1 | RATE_FIXED, | ||
1021 | .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE, | ||
1022 | .enable_bit = 1, | ||
1023 | .src_offset = 13, | ||
1024 | .recalc = &omap2_followparent_recalc, | ||
1025 | }; | ||
1026 | |||
1027 | static struct clk dss_54m_fck = { /* Alt clk used in power management */ | ||
1028 | .name = "dss_54m_fck", /* 54m tv clk */ | ||
1029 | .parent = &func_54m_ck, | ||
1030 | .rate = 54000000, | ||
1031 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | | ||
1032 | RATE_FIXED | RATE_PROPAGATES, | ||
1033 | .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE, | ||
1034 | .enable_bit = 2, | ||
1035 | .recalc = &omap2_propagate_rate, | ||
1036 | }; | ||
1037 | |||
1038 | /* | ||
1039 | * CORE power domain ICLK & FCLK defines. | ||
1040 | * Many of the these can have more than one possible parent. Entries | ||
1041 | * here will likely have an L4 interface parent, and may have multiple | ||
1042 | * functional clock parents. | ||
1043 | */ | ||
1044 | static struct clk gpt1_ick = { | ||
1045 | .name = "gpt1_ick", | ||
1046 | .parent = &l4_ck, | ||
1047 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | ||
1048 | .enable_reg = (void __iomem *)&CM_ICLKEN_WKUP, /* Bit4 */ | ||
1049 | .enable_bit = 0, | ||
1050 | .recalc = &omap2_followparent_recalc, | ||
1051 | }; | ||
1052 | |||
1053 | static struct clk gpt1_fck = { | ||
1054 | .name = "gpt1_fck", | ||
1055 | .parent = &func_32k_ck, | ||
1056 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | | ||
1057 | CM_WKUP_SEL1, | ||
1058 | .enable_reg = (void __iomem *)&CM_FCLKEN_WKUP, | ||
1059 | .enable_bit = 0, | ||
1060 | .src_offset = 0, | ||
1061 | .recalc = &omap2_followparent_recalc, | ||
1062 | }; | ||
1063 | |||
1064 | static struct clk gpt2_ick = { | ||
1065 | .name = "gpt2_ick", | ||
1066 | .parent = &l4_ck, | ||
1067 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | ||
1068 | .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, /* bit4 */ | ||
1069 | .enable_bit = 0, | ||
1070 | .recalc = &omap2_followparent_recalc, | ||
1071 | }; | ||
1072 | |||
1073 | static struct clk gpt2_fck = { | ||
1074 | .name = "gpt2_fck", | ||
1075 | .parent = &func_32k_ck, | ||
1076 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | | ||
1077 | CM_CORE_SEL2, | ||
1078 | .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE, | ||
1079 | .enable_bit = 4, | ||
1080 | .src_offset = 2, | ||
1081 | .recalc = &omap2_followparent_recalc, | ||
1082 | }; | ||
1083 | |||
1084 | static struct clk gpt3_ick = { | ||
1085 | .name = "gpt3_ick", | ||
1086 | .parent = &l4_ck, | ||
1087 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | ||
1088 | .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, /* Bit5 */ | ||
1089 | .enable_bit = 5, | ||
1090 | .recalc = &omap2_followparent_recalc, | ||
1091 | }; | ||
1092 | |||
1093 | static struct clk gpt3_fck = { | ||
1094 | .name = "gpt3_fck", | ||
1095 | .parent = &func_32k_ck, | ||
1096 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | | ||
1097 | CM_CORE_SEL2, | ||
1098 | .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE, | ||
1099 | .enable_bit = 5, | ||
1100 | .src_offset = 4, | ||
1101 | .recalc = &omap2_followparent_recalc, | ||
1102 | }; | ||
1103 | |||
1104 | static struct clk gpt4_ick = { | ||
1105 | .name = "gpt4_ick", | ||
1106 | .parent = &l4_ck, | ||
1107 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | ||
1108 | .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, /* Bit6 */ | ||
1109 | .enable_bit = 6, | ||
1110 | .recalc = &omap2_followparent_recalc, | ||
1111 | }; | ||
1112 | |||
1113 | static struct clk gpt4_fck = { | ||
1114 | .name = "gpt4_fck", | ||
1115 | .parent = &func_32k_ck, | ||
1116 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | | ||
1117 | CM_CORE_SEL2, | ||
1118 | .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE, | ||
1119 | .enable_bit = 6, | ||
1120 | .src_offset = 6, | ||
1121 | .recalc = &omap2_followparent_recalc, | ||
1122 | }; | ||
1123 | |||
1124 | static struct clk gpt5_ick = { | ||
1125 | .name = "gpt5_ick", | ||
1126 | .parent = &l4_ck, | ||
1127 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | ||
1128 | .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, /* Bit7 */ | ||
1129 | .enable_bit = 7, | ||
1130 | .recalc = &omap2_followparent_recalc, | ||
1131 | }; | ||
1132 | |||
1133 | static struct clk gpt5_fck = { | ||
1134 | .name = "gpt5_fck", | ||
1135 | .parent = &func_32k_ck, | ||
1136 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | | ||
1137 | CM_CORE_SEL2, | ||
1138 | .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE, | ||
1139 | .enable_bit = 7, | ||
1140 | .src_offset = 8, | ||
1141 | .recalc = &omap2_followparent_recalc, | ||
1142 | }; | ||
1143 | |||
1144 | static struct clk gpt6_ick = { | ||
1145 | .name = "gpt6_ick", | ||
1146 | .parent = &l4_ck, | ||
1147 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | ||
1148 | .enable_bit = 8, | ||
1149 | .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, /* bit8 */ | ||
1150 | .recalc = &omap2_followparent_recalc, | ||
1151 | }; | ||
1152 | |||
1153 | static struct clk gpt6_fck = { | ||
1154 | .name = "gpt6_fck", | ||
1155 | .parent = &func_32k_ck, | ||
1156 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | | ||
1157 | CM_CORE_SEL2, | ||
1158 | .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE, | ||
1159 | .enable_bit = 8, | ||
1160 | .src_offset = 10, | ||
1161 | .recalc = &omap2_followparent_recalc, | ||
1162 | }; | ||
1163 | |||
1164 | static struct clk gpt7_ick = { | ||
1165 | .name = "gpt7_ick", | ||
1166 | .parent = &l4_ck, | ||
1167 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | ||
1168 | .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, /* bit9 */ | ||
1169 | .enable_bit = 9, | ||
1170 | .recalc = &omap2_followparent_recalc, | ||
1171 | }; | ||
1172 | |||
1173 | static struct clk gpt7_fck = { | ||
1174 | .name = "gpt7_fck", | ||
1175 | .parent = &func_32k_ck, | ||
1176 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | | ||
1177 | CM_CORE_SEL2, | ||
1178 | .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE, | ||
1179 | .enable_bit = 9, | ||
1180 | .src_offset = 12, | ||
1181 | .recalc = &omap2_followparent_recalc, | ||
1182 | }; | ||
1183 | |||
1184 | static struct clk gpt8_ick = { | ||
1185 | .name = "gpt8_ick", | ||
1186 | .parent = &l4_ck, | ||
1187 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | ||
1188 | .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, /* bit10 */ | ||
1189 | .enable_bit = 10, | ||
1190 | .recalc = &omap2_followparent_recalc, | ||
1191 | }; | ||
1192 | |||
1193 | static struct clk gpt8_fck = { | ||
1194 | .name = "gpt8_fck", | ||
1195 | .parent = &func_32k_ck, | ||
1196 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | | ||
1197 | CM_CORE_SEL2, | ||
1198 | .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE, | ||
1199 | .enable_bit = 10, | ||
1200 | .src_offset = 14, | ||
1201 | .recalc = &omap2_followparent_recalc, | ||
1202 | }; | ||
1203 | |||
1204 | static struct clk gpt9_ick = { | ||
1205 | .name = "gpt9_ick", | ||
1206 | .parent = &l4_ck, | ||
1207 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | ||
1208 | .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, | ||
1209 | .enable_bit = 11, | ||
1210 | .recalc = &omap2_followparent_recalc, | ||
1211 | }; | ||
1212 | |||
1213 | static struct clk gpt9_fck = { | ||
1214 | .name = "gpt9_fck", | ||
1215 | .parent = &func_32k_ck, | ||
1216 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | | ||
1217 | CM_CORE_SEL2, | ||
1218 | .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE, | ||
1219 | .enable_bit = 11, | ||
1220 | .src_offset = 16, | ||
1221 | .recalc = &omap2_followparent_recalc, | ||
1222 | }; | ||
1223 | |||
1224 | static struct clk gpt10_ick = { | ||
1225 | .name = "gpt10_ick", | ||
1226 | .parent = &l4_ck, | ||
1227 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | ||
1228 | .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, | ||
1229 | .enable_bit = 12, | ||
1230 | .recalc = &omap2_followparent_recalc, | ||
1231 | }; | ||
1232 | |||
1233 | static struct clk gpt10_fck = { | ||
1234 | .name = "gpt10_fck", | ||
1235 | .parent = &func_32k_ck, | ||
1236 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | | ||
1237 | CM_CORE_SEL2, | ||
1238 | .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE, | ||
1239 | .enable_bit = 12, | ||
1240 | .src_offset = 18, | ||
1241 | .recalc = &omap2_followparent_recalc, | ||
1242 | }; | ||
1243 | |||
1244 | static struct clk gpt11_ick = { | ||
1245 | .name = "gpt11_ick", | ||
1246 | .parent = &l4_ck, | ||
1247 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | ||
1248 | .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, | ||
1249 | .enable_bit = 13, | ||
1250 | .recalc = &omap2_followparent_recalc, | ||
1251 | }; | ||
1252 | |||
1253 | static struct clk gpt11_fck = { | ||
1254 | .name = "gpt11_fck", | ||
1255 | .parent = &func_32k_ck, | ||
1256 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | | ||
1257 | CM_CORE_SEL2, | ||
1258 | .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE, | ||
1259 | .enable_bit = 13, | ||
1260 | .src_offset = 20, | ||
1261 | .recalc = &omap2_followparent_recalc, | ||
1262 | }; | ||
1263 | |||
1264 | static struct clk gpt12_ick = { | ||
1265 | .name = "gpt12_ick", | ||
1266 | .parent = &l4_ck, | ||
1267 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | ||
1268 | .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, /* bit14 */ | ||
1269 | .enable_bit = 14, | ||
1270 | .recalc = &omap2_followparent_recalc, | ||
1271 | }; | ||
1272 | |||
1273 | static struct clk gpt12_fck = { | ||
1274 | .name = "gpt12_fck", | ||
1275 | .parent = &func_32k_ck, | ||
1276 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | | ||
1277 | CM_CORE_SEL2, | ||
1278 | .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE, | ||
1279 | .enable_bit = 14, | ||
1280 | .src_offset = 22, | ||
1281 | .recalc = &omap2_followparent_recalc, | ||
1282 | }; | ||
1283 | |||
1284 | static struct clk mcbsp1_ick = { | ||
1285 | .name = "mcbsp1_ick", | ||
1286 | .parent = &l4_ck, | ||
1287 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | ||
1288 | .enable_bit = 15, | ||
1289 | .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, /* bit16 */ | ||
1290 | .recalc = &omap2_followparent_recalc, | ||
1291 | }; | ||
1292 | |||
1293 | static struct clk mcbsp1_fck = { | ||
1294 | .name = "mcbsp1_fck", | ||
1295 | .parent = &func_96m_ck, | ||
1296 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | ||
1297 | .enable_bit = 15, | ||
1298 | .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE, | ||
1299 | .recalc = &omap2_followparent_recalc, | ||
1300 | }; | ||
1301 | |||
1302 | static struct clk mcbsp2_ick = { | ||
1303 | .name = "mcbsp2_ick", | ||
1304 | .parent = &l4_ck, | ||
1305 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | ||
1306 | .enable_bit = 16, | ||
1307 | .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, | ||
1308 | .recalc = &omap2_followparent_recalc, | ||
1309 | }; | ||
1310 | |||
1311 | static struct clk mcbsp2_fck = { | ||
1312 | .name = "mcbsp2_fck", | ||
1313 | .parent = &func_96m_ck, | ||
1314 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | ||
1315 | .enable_bit = 16, | ||
1316 | .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE, | ||
1317 | .recalc = &omap2_followparent_recalc, | ||
1318 | }; | ||
1319 | |||
1320 | static struct clk mcbsp3_ick = { | ||
1321 | .name = "mcbsp3_ick", | ||
1322 | .parent = &l4_ck, | ||
1323 | .flags = CLOCK_IN_OMAP243X, | ||
1324 | .enable_reg = (void __iomem *)&CM_ICLKEN2_CORE, | ||
1325 | .enable_bit = 3, | ||
1326 | .recalc = &omap2_followparent_recalc, | ||
1327 | }; | ||
1328 | |||
1329 | static struct clk mcbsp3_fck = { | ||
1330 | .name = "mcbsp3_fck", | ||
1331 | .parent = &func_96m_ck, | ||
1332 | .flags = CLOCK_IN_OMAP243X, | ||
1333 | .enable_reg = (void __iomem *)&CM_FCLKEN2_CORE, | ||
1334 | .enable_bit = 3, | ||
1335 | .recalc = &omap2_followparent_recalc, | ||
1336 | }; | ||
1337 | |||
1338 | static struct clk mcbsp4_ick = { | ||
1339 | .name = "mcbsp4_ick", | ||
1340 | .parent = &l4_ck, | ||
1341 | .flags = CLOCK_IN_OMAP243X, | ||
1342 | .enable_reg = (void __iomem *)&CM_ICLKEN2_CORE, | ||
1343 | .enable_bit = 4, | ||
1344 | .recalc = &omap2_followparent_recalc, | ||
1345 | }; | ||
1346 | |||
1347 | static struct clk mcbsp4_fck = { | ||
1348 | .name = "mcbsp4_fck", | ||
1349 | .parent = &func_96m_ck, | ||
1350 | .flags = CLOCK_IN_OMAP243X, | ||
1351 | .enable_reg = (void __iomem *)&CM_FCLKEN2_CORE, | ||
1352 | .enable_bit = 4, | ||
1353 | .recalc = &omap2_followparent_recalc, | ||
1354 | }; | ||
1355 | |||
1356 | static struct clk mcbsp5_ick = { | ||
1357 | .name = "mcbsp5_ick", | ||
1358 | .parent = &l4_ck, | ||
1359 | .flags = CLOCK_IN_OMAP243X, | ||
1360 | .enable_reg = (void __iomem *)&CM_ICLKEN2_CORE, | ||
1361 | .enable_bit = 5, | ||
1362 | .recalc = &omap2_followparent_recalc, | ||
1363 | }; | ||
1364 | |||
1365 | static struct clk mcbsp5_fck = { | ||
1366 | .name = "mcbsp5_fck", | ||
1367 | .parent = &func_96m_ck, | ||
1368 | .flags = CLOCK_IN_OMAP243X, | ||
1369 | .enable_reg = (void __iomem *)&CM_FCLKEN2_CORE, | ||
1370 | .enable_bit = 5, | ||
1371 | .recalc = &omap2_followparent_recalc, | ||
1372 | }; | ||
1373 | |||
1374 | static struct clk mcspi1_ick = { | ||
1375 | .name = "mcspi1_ick", | ||
1376 | .parent = &l4_ck, | ||
1377 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | ||
1378 | .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, | ||
1379 | .enable_bit = 17, | ||
1380 | .recalc = &omap2_followparent_recalc, | ||
1381 | }; | ||
1382 | |||
1383 | static struct clk mcspi1_fck = { | ||
1384 | .name = "mcspi1_fck", | ||
1385 | .parent = &func_48m_ck, | ||
1386 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | ||
1387 | .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE, | ||
1388 | .enable_bit = 17, | ||
1389 | .recalc = &omap2_followparent_recalc, | ||
1390 | }; | ||
1391 | |||
1392 | static struct clk mcspi2_ick = { | ||
1393 | .name = "mcspi2_ick", | ||
1394 | .parent = &l4_ck, | ||
1395 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | ||
1396 | .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, | ||
1397 | .enable_bit = 18, | ||
1398 | .recalc = &omap2_followparent_recalc, | ||
1399 | }; | ||
1400 | |||
1401 | static struct clk mcspi2_fck = { | ||
1402 | .name = "mcspi2_fck", | ||
1403 | .parent = &func_48m_ck, | ||
1404 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | ||
1405 | .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE, | ||
1406 | .enable_bit = 18, | ||
1407 | .recalc = &omap2_followparent_recalc, | ||
1408 | }; | ||
1409 | |||
1410 | static struct clk mcspi3_ick = { | ||
1411 | .name = "mcspi3_ick", | ||
1412 | .parent = &l4_ck, | ||
1413 | .flags = CLOCK_IN_OMAP243X, | ||
1414 | .enable_reg = (void __iomem *)&CM_ICLKEN2_CORE, | ||
1415 | .enable_bit = 9, | ||
1416 | .recalc = &omap2_followparent_recalc, | ||
1417 | }; | ||
1418 | |||
1419 | static struct clk mcspi3_fck = { | ||
1420 | .name = "mcspi3_fck", | ||
1421 | .parent = &func_48m_ck, | ||
1422 | .flags = CLOCK_IN_OMAP243X, | ||
1423 | .enable_reg = (void __iomem *)&CM_FCLKEN2_CORE, | ||
1424 | .enable_bit = 9, | ||
1425 | .recalc = &omap2_followparent_recalc, | ||
1426 | }; | ||
1427 | |||
1428 | static struct clk uart1_ick = { | ||
1429 | .name = "uart1_ick", | ||
1430 | .parent = &l4_ck, | ||
1431 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | ||
1432 | .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, | ||
1433 | .enable_bit = 21, | ||
1434 | .recalc = &omap2_followparent_recalc, | ||
1435 | }; | ||
1436 | |||
1437 | static struct clk uart1_fck = { | ||
1438 | .name = "uart1_fck", | ||
1439 | .parent = &func_48m_ck, | ||
1440 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | ||
1441 | .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE, | ||
1442 | .enable_bit = 21, | ||
1443 | .recalc = &omap2_followparent_recalc, | ||
1444 | }; | ||
1445 | |||
1446 | static struct clk uart2_ick = { | ||
1447 | .name = "uart2_ick", | ||
1448 | .parent = &l4_ck, | ||
1449 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | ||
1450 | .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, | ||
1451 | .enable_bit = 22, | ||
1452 | .recalc = &omap2_followparent_recalc, | ||
1453 | }; | ||
1454 | |||
1455 | static struct clk uart2_fck = { | ||
1456 | .name = "uart2_fck", | ||
1457 | .parent = &func_48m_ck, | ||
1458 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | ||
1459 | .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE, | ||
1460 | .enable_bit = 22, | ||
1461 | .recalc = &omap2_followparent_recalc, | ||
1462 | }; | ||
1463 | |||
1464 | static struct clk uart3_ick = { | ||
1465 | .name = "uart3_ick", | ||
1466 | .parent = &l4_ck, | ||
1467 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | ||
1468 | .enable_reg = (void __iomem *)&CM_ICLKEN2_CORE, | ||
1469 | .enable_bit = 2, | ||
1470 | .recalc = &omap2_followparent_recalc, | ||
1471 | }; | ||
1472 | |||
1473 | static struct clk uart3_fck = { | ||
1474 | .name = "uart3_fck", | ||
1475 | .parent = &func_48m_ck, | ||
1476 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | ||
1477 | .enable_reg = (void __iomem *)&CM_FCLKEN2_CORE, | ||
1478 | .enable_bit = 2, | ||
1479 | .recalc = &omap2_followparent_recalc, | ||
1480 | }; | ||
1481 | |||
1482 | static struct clk gpios_ick = { | ||
1483 | .name = "gpios_ick", | ||
1484 | .parent = &l4_ck, | ||
1485 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | ||
1486 | .enable_reg = (void __iomem *)&CM_ICLKEN_WKUP, | ||
1487 | .enable_bit = 2, | ||
1488 | .recalc = &omap2_followparent_recalc, | ||
1489 | }; | ||
1490 | |||
1491 | static struct clk gpios_fck = { | ||
1492 | .name = "gpios_fck", | ||
1493 | .parent = &func_32k_ck, | ||
1494 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | ||
1495 | .enable_reg = (void __iomem *)&CM_FCLKEN_WKUP, | ||
1496 | .enable_bit = 2, | ||
1497 | .recalc = &omap2_followparent_recalc, | ||
1498 | }; | ||
1499 | |||
1500 | static struct clk mpu_wdt_ick = { | ||
1501 | .name = "mpu_wdt_ick", | ||
1502 | .parent = &l4_ck, | ||
1503 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | ||
1504 | .enable_reg = (void __iomem *)&CM_ICLKEN_WKUP, | ||
1505 | .enable_bit = 3, | ||
1506 | .recalc = &omap2_followparent_recalc, | ||
1507 | }; | ||
1508 | |||
1509 | static struct clk mpu_wdt_fck = { | ||
1510 | .name = "mpu_wdt_fck", | ||
1511 | .parent = &func_32k_ck, | ||
1512 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | ||
1513 | .enable_reg = (void __iomem *)&CM_FCLKEN_WKUP, | ||
1514 | .enable_bit = 3, | ||
1515 | .recalc = &omap2_followparent_recalc, | ||
1516 | }; | ||
1517 | |||
1518 | static struct clk sync_32k_ick = { | ||
1519 | .name = "sync_32k_ick", | ||
1520 | .parent = &l4_ck, | ||
1521 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | ||
1522 | .enable_reg = (void __iomem *)&CM_ICLKEN_WKUP, | ||
1523 | .enable_bit = 1, | ||
1524 | .recalc = &omap2_followparent_recalc, | ||
1525 | }; | ||
1526 | static struct clk wdt1_ick = { | ||
1527 | .name = "wdt1_ick", | ||
1528 | .parent = &l4_ck, | ||
1529 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | ||
1530 | .enable_reg = (void __iomem *)&CM_ICLKEN_WKUP, | ||
1531 | .enable_bit = 4, | ||
1532 | .recalc = &omap2_followparent_recalc, | ||
1533 | }; | ||
1534 | static struct clk omapctrl_ick = { | ||
1535 | .name = "omapctrl_ick", | ||
1536 | .parent = &l4_ck, | ||
1537 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | ||
1538 | .enable_reg = (void __iomem *)&CM_ICLKEN_WKUP, | ||
1539 | .enable_bit = 5, | ||
1540 | .recalc = &omap2_followparent_recalc, | ||
1541 | }; | ||
1542 | static struct clk icr_ick = { | ||
1543 | .name = "icr_ick", | ||
1544 | .parent = &l4_ck, | ||
1545 | .flags = CLOCK_IN_OMAP243X, | ||
1546 | .enable_reg = (void __iomem *)&CM_ICLKEN_WKUP, | ||
1547 | .enable_bit = 6, | ||
1548 | .recalc = &omap2_followparent_recalc, | ||
1549 | }; | ||
1550 | |||
1551 | static struct clk cam_ick = { | ||
1552 | .name = "cam_ick", | ||
1553 | .parent = &l4_ck, | ||
1554 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | ||
1555 | .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, | ||
1556 | .enable_bit = 31, | ||
1557 | .recalc = &omap2_followparent_recalc, | ||
1558 | }; | ||
1559 | |||
1560 | static struct clk cam_fck = { | ||
1561 | .name = "cam_fck", | ||
1562 | .parent = &func_96m_ck, | ||
1563 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | ||
1564 | .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE, | ||
1565 | .enable_bit = 31, | ||
1566 | .recalc = &omap2_followparent_recalc, | ||
1567 | }; | ||
1568 | |||
1569 | static struct clk mailboxes_ick = { | ||
1570 | .name = "mailboxes_ick", | ||
1571 | .parent = &l4_ck, | ||
1572 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | ||
1573 | .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, | ||
1574 | .enable_bit = 30, | ||
1575 | .recalc = &omap2_followparent_recalc, | ||
1576 | }; | ||
1577 | |||
1578 | static struct clk wdt4_ick = { | ||
1579 | .name = "wdt4_ick", | ||
1580 | .parent = &l4_ck, | ||
1581 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | ||
1582 | .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, | ||
1583 | .enable_bit = 29, | ||
1584 | .recalc = &omap2_followparent_recalc, | ||
1585 | }; | ||
1586 | |||
1587 | static struct clk wdt4_fck = { | ||
1588 | .name = "wdt4_fck", | ||
1589 | .parent = &func_32k_ck, | ||
1590 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | ||
1591 | .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE, | ||
1592 | .enable_bit = 29, | ||
1593 | .recalc = &omap2_followparent_recalc, | ||
1594 | }; | ||
1595 | |||
1596 | static struct clk wdt3_ick = { | ||
1597 | .name = "wdt3_ick", | ||
1598 | .parent = &l4_ck, | ||
1599 | .flags = CLOCK_IN_OMAP242X, | ||
1600 | .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, | ||
1601 | .enable_bit = 28, | ||
1602 | .recalc = &omap2_followparent_recalc, | ||
1603 | }; | ||
1604 | |||
1605 | static struct clk wdt3_fck = { | ||
1606 | .name = "wdt3_fck", | ||
1607 | .parent = &func_32k_ck, | ||
1608 | .flags = CLOCK_IN_OMAP242X, | ||
1609 | .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE, | ||
1610 | .enable_bit = 28, | ||
1611 | .recalc = &omap2_followparent_recalc, | ||
1612 | }; | ||
1613 | |||
1614 | static struct clk mspro_ick = { | ||
1615 | .name = "mspro_ick", | ||
1616 | .parent = &l4_ck, | ||
1617 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | ||
1618 | .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, | ||
1619 | .enable_bit = 27, | ||
1620 | .recalc = &omap2_followparent_recalc, | ||
1621 | }; | ||
1622 | |||
1623 | static struct clk mspro_fck = { | ||
1624 | .name = "mspro_fck", | ||
1625 | .parent = &func_96m_ck, | ||
1626 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | ||
1627 | .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE, | ||
1628 | .enable_bit = 27, | ||
1629 | .recalc = &omap2_followparent_recalc, | ||
1630 | }; | ||
1631 | |||
1632 | static struct clk mmc_ick = { | ||
1633 | .name = "mmc_ick", | ||
1634 | .parent = &l4_ck, | ||
1635 | .flags = CLOCK_IN_OMAP242X, | ||
1636 | .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, | ||
1637 | .enable_bit = 26, | ||
1638 | .recalc = &omap2_followparent_recalc, | ||
1639 | }; | ||
1640 | |||
1641 | static struct clk mmc_fck = { | ||
1642 | .name = "mmc_fck", | ||
1643 | .parent = &func_96m_ck, | ||
1644 | .flags = CLOCK_IN_OMAP242X, | ||
1645 | .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE, | ||
1646 | .enable_bit = 26, | ||
1647 | .recalc = &omap2_followparent_recalc, | ||
1648 | }; | ||
1649 | |||
1650 | static struct clk fac_ick = { | ||
1651 | .name = "fac_ick", | ||
1652 | .parent = &l4_ck, | ||
1653 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | ||
1654 | .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, | ||
1655 | .enable_bit = 25, | ||
1656 | .recalc = &omap2_followparent_recalc, | ||
1657 | }; | ||
1658 | |||
1659 | static struct clk fac_fck = { | ||
1660 | .name = "fac_fck", | ||
1661 | .parent = &func_12m_ck, | ||
1662 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | ||
1663 | .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE, | ||
1664 | .enable_bit = 25, | ||
1665 | .recalc = &omap2_followparent_recalc, | ||
1666 | }; | ||
1667 | |||
1668 | static struct clk eac_ick = { | ||
1669 | .name = "eac_ick", | ||
1670 | .parent = &l4_ck, | ||
1671 | .flags = CLOCK_IN_OMAP242X, | ||
1672 | .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, | ||
1673 | .enable_bit = 24, | ||
1674 | .recalc = &omap2_followparent_recalc, | ||
1675 | }; | ||
1676 | |||
1677 | static struct clk eac_fck = { | ||
1678 | .name = "eac_fck", | ||
1679 | .parent = &func_96m_ck, | ||
1680 | .flags = CLOCK_IN_OMAP242X, | ||
1681 | .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE, | ||
1682 | .enable_bit = 24, | ||
1683 | .recalc = &omap2_followparent_recalc, | ||
1684 | }; | ||
1685 | |||
1686 | static struct clk hdq_ick = { | ||
1687 | .name = "hdq_ick", | ||
1688 | .parent = &l4_ck, | ||
1689 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | ||
1690 | .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, | ||
1691 | .enable_bit = 23, | ||
1692 | .recalc = &omap2_followparent_recalc, | ||
1693 | }; | ||
1694 | |||
1695 | static struct clk hdq_fck = { | ||
1696 | .name = "hdq_fck", | ||
1697 | .parent = &func_12m_ck, | ||
1698 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | ||
1699 | .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE, | ||
1700 | .enable_bit = 23, | ||
1701 | .recalc = &omap2_followparent_recalc, | ||
1702 | }; | ||
1703 | |||
1704 | static struct clk i2c2_ick = { | ||
1705 | .name = "i2c2_ick", | ||
1706 | .parent = &l4_ck, | ||
1707 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | ||
1708 | .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, | ||
1709 | .enable_bit = 20, | ||
1710 | .recalc = &omap2_followparent_recalc, | ||
1711 | }; | ||
1712 | |||
1713 | static struct clk i2c2_fck = { | ||
1714 | .name = "i2c2_fck", | ||
1715 | .parent = &func_12m_ck, | ||
1716 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | ||
1717 | .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE, | ||
1718 | .enable_bit = 20, | ||
1719 | .recalc = &omap2_followparent_recalc, | ||
1720 | }; | ||
1721 | |||
1722 | static struct clk i2chs2_fck = { | ||
1723 | .name = "i2chs2_fck", | ||
1724 | .parent = &func_96m_ck, | ||
1725 | .flags = CLOCK_IN_OMAP243X, | ||
1726 | .enable_reg = (void __iomem *)&CM_FCLKEN2_CORE, | ||
1727 | .enable_bit = 20, | ||
1728 | .recalc = &omap2_followparent_recalc, | ||
1729 | }; | ||
1730 | |||
1731 | static struct clk i2c1_ick = { | ||
1732 | .name = "i2c1_ick", | ||
1733 | .parent = &l4_ck, | ||
1734 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | ||
1735 | .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, | ||
1736 | .enable_bit = 19, | ||
1737 | .recalc = &omap2_followparent_recalc, | ||
1738 | }; | ||
1739 | |||
1740 | static struct clk i2c1_fck = { | ||
1741 | .name = "i2c1_fck", | ||
1742 | .parent = &func_12m_ck, | ||
1743 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | ||
1744 | .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE, | ||
1745 | .enable_bit = 19, | ||
1746 | .recalc = &omap2_followparent_recalc, | ||
1747 | }; | ||
1748 | |||
1749 | static struct clk i2chs1_fck = { | ||
1750 | .name = "i2chs1_fck", | ||
1751 | .parent = &func_96m_ck, | ||
1752 | .flags = CLOCK_IN_OMAP243X, | ||
1753 | .enable_reg = (void __iomem *)&CM_FCLKEN2_CORE, | ||
1754 | .enable_bit = 19, | ||
1755 | .recalc = &omap2_followparent_recalc, | ||
1756 | }; | ||
1757 | |||
1758 | static struct clk vlynq_ick = { | ||
1759 | .name = "vlynq_ick", | ||
1760 | .parent = &core_l3_ck, | ||
1761 | .flags = CLOCK_IN_OMAP242X, | ||
1762 | .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, | ||
1763 | .enable_bit = 3, | ||
1764 | .recalc = &omap2_followparent_recalc, | ||
1765 | }; | ||
1766 | |||
1767 | static struct clk vlynq_fck = { | ||
1768 | .name = "vlynq_fck", | ||
1769 | .parent = &func_96m_ck, | ||
1770 | .flags = CLOCK_IN_OMAP242X | RATE_CKCTL | CM_CORE_SEL1 | DELAYED_APP, | ||
1771 | .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE, | ||
1772 | .enable_bit = 3, | ||
1773 | .src_offset = 15, | ||
1774 | .recalc = &omap2_followparent_recalc, | ||
1775 | }; | ||
1776 | |||
1777 | static struct clk sdrc_ick = { | ||
1778 | .name = "sdrc_ick", | ||
1779 | .parent = &l4_ck, | ||
1780 | .flags = CLOCK_IN_OMAP243X, | ||
1781 | .enable_reg = (void __iomem *)&CM_ICLKEN3_CORE, | ||
1782 | .enable_bit = 2, | ||
1783 | .recalc = &omap2_followparent_recalc, | ||
1784 | }; | ||
1785 | |||
1786 | static struct clk des_ick = { | ||
1787 | .name = "des_ick", | ||
1788 | .parent = &l4_ck, | ||
1789 | .flags = CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X, | ||
1790 | .enable_reg = (void __iomem *)&CM_ICLKEN4_CORE, | ||
1791 | .enable_bit = 0, | ||
1792 | .recalc = &omap2_followparent_recalc, | ||
1793 | }; | ||
1794 | |||
1795 | static struct clk sha_ick = { | ||
1796 | .name = "sha_ick", | ||
1797 | .parent = &l4_ck, | ||
1798 | .flags = CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X, | ||
1799 | .enable_reg = (void __iomem *)&CM_ICLKEN4_CORE, | ||
1800 | .enable_bit = 1, | ||
1801 | .recalc = &omap2_followparent_recalc, | ||
1802 | }; | ||
1803 | |||
1804 | static struct clk rng_ick = { | ||
1805 | .name = "rng_ick", | ||
1806 | .parent = &l4_ck, | ||
1807 | .flags = CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X, | ||
1808 | .enable_reg = (void __iomem *)&CM_ICLKEN4_CORE, | ||
1809 | .enable_bit = 2, | ||
1810 | .recalc = &omap2_followparent_recalc, | ||
1811 | }; | ||
1812 | |||
1813 | static struct clk aes_ick = { | ||
1814 | .name = "aes_ick", | ||
1815 | .parent = &l4_ck, | ||
1816 | .flags = CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X, | ||
1817 | .enable_reg = (void __iomem *)&CM_ICLKEN4_CORE, | ||
1818 | .enable_bit = 3, | ||
1819 | .recalc = &omap2_followparent_recalc, | ||
1820 | }; | ||
1821 | |||
1822 | static struct clk pka_ick = { | ||
1823 | .name = "pka_ick", | ||
1824 | .parent = &l4_ck, | ||
1825 | .flags = CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X, | ||
1826 | .enable_reg = (void __iomem *)&CM_ICLKEN4_CORE, | ||
1827 | .enable_bit = 4, | ||
1828 | .recalc = &omap2_followparent_recalc, | ||
1829 | }; | ||
1830 | |||
1831 | static struct clk usb_fck = { | ||
1832 | .name = "usb_fck", | ||
1833 | .parent = &func_48m_ck, | ||
1834 | .flags = CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X, | ||
1835 | .enable_reg = (void __iomem *)&CM_FCLKEN2_CORE, | ||
1836 | .enable_bit = 0, | ||
1837 | .recalc = &omap2_followparent_recalc, | ||
1838 | }; | ||
1839 | |||
1840 | static struct clk usbhs_ick = { | ||
1841 | .name = "usbhs_ick", | ||
1842 | .parent = &l4_ck, | ||
1843 | .flags = CLOCK_IN_OMAP243X, | ||
1844 | .enable_reg = (void __iomem *)&CM_ICLKEN2_CORE, | ||
1845 | .enable_bit = 6, | ||
1846 | .recalc = &omap2_followparent_recalc, | ||
1847 | }; | ||
1848 | |||
1849 | static struct clk mmchs1_ick = { | ||
1850 | .name = "mmchs1_ick", | ||
1851 | .parent = &l4_ck, | ||
1852 | .flags = CLOCK_IN_OMAP243X, | ||
1853 | .enable_reg = (void __iomem *)&CM_ICLKEN2_CORE, | ||
1854 | .enable_bit = 7, | ||
1855 | .recalc = &omap2_followparent_recalc, | ||
1856 | }; | ||
1857 | |||
1858 | static struct clk mmchs1_fck = { | ||
1859 | .name = "mmchs1_fck", | ||
1860 | .parent = &func_96m_ck, | ||
1861 | .flags = CLOCK_IN_OMAP243X, | ||
1862 | .enable_reg = (void __iomem *)&CM_FCLKEN2_CORE, | ||
1863 | .enable_bit = 7, | ||
1864 | .recalc = &omap2_followparent_recalc, | ||
1865 | }; | ||
1866 | |||
1867 | static struct clk mmchs2_ick = { | ||
1868 | .name = "mmchs2_ick", | ||
1869 | .parent = &l4_ck, | ||
1870 | .flags = CLOCK_IN_OMAP243X, | ||
1871 | .enable_reg = (void __iomem *)&CM_ICLKEN2_CORE, | ||
1872 | .enable_bit = 8, | ||
1873 | .recalc = &omap2_followparent_recalc, | ||
1874 | }; | ||
1875 | |||
1876 | static struct clk mmchs2_fck = { | ||
1877 | .name = "mmchs2_fck", | ||
1878 | .parent = &func_96m_ck, | ||
1879 | .flags = CLOCK_IN_OMAP243X, | ||
1880 | .enable_reg = (void __iomem *)&CM_FCLKEN2_CORE, | ||
1881 | .enable_bit = 8, | ||
1882 | .recalc = &omap2_followparent_recalc, | ||
1883 | }; | ||
1884 | |||
1885 | static struct clk gpio5_ick = { | ||
1886 | .name = "gpio5_ick", | ||
1887 | .parent = &l4_ck, | ||
1888 | .flags = CLOCK_IN_OMAP243X, | ||
1889 | .enable_reg = (void __iomem *)&CM_ICLKEN2_CORE, | ||
1890 | .enable_bit = 10, | ||
1891 | .recalc = &omap2_followparent_recalc, | ||
1892 | }; | ||
1893 | |||
1894 | static struct clk gpio5_fck = { | ||
1895 | .name = "gpio5_fck", | ||
1896 | .parent = &func_32k_ck, | ||
1897 | .flags = CLOCK_IN_OMAP243X, | ||
1898 | .enable_reg = (void __iomem *)&CM_FCLKEN2_CORE, | ||
1899 | .enable_bit = 10, | ||
1900 | .recalc = &omap2_followparent_recalc, | ||
1901 | }; | ||
1902 | |||
1903 | static struct clk mdm_intc_ick = { | ||
1904 | .name = "mdm_intc_ick", | ||
1905 | .parent = &l4_ck, | ||
1906 | .flags = CLOCK_IN_OMAP243X, | ||
1907 | .enable_reg = (void __iomem *)&CM_ICLKEN2_CORE, | ||
1908 | .enable_bit = 11, | ||
1909 | .recalc = &omap2_followparent_recalc, | ||
1910 | }; | ||
1911 | |||
1912 | static struct clk mmchsdb1_fck = { | ||
1913 | .name = "mmchsdb1_fck", | ||
1914 | .parent = &func_32k_ck, | ||
1915 | .flags = CLOCK_IN_OMAP243X, | ||
1916 | .enable_reg = (void __iomem *)&CM_FCLKEN2_CORE, | ||
1917 | .enable_bit = 16, | ||
1918 | .recalc = &omap2_followparent_recalc, | ||
1919 | }; | ||
1920 | |||
1921 | static struct clk mmchsdb2_fck = { | ||
1922 | .name = "mmchsdb2_fck", | ||
1923 | .parent = &func_32k_ck, | ||
1924 | .flags = CLOCK_IN_OMAP243X, | ||
1925 | .enable_reg = (void __iomem *)&CM_FCLKEN2_CORE, | ||
1926 | .enable_bit = 17, | ||
1927 | .recalc = &omap2_followparent_recalc, | ||
1928 | }; | ||
1929 | |||
1930 | /* | ||
1931 | * This clock is a composite clock which does entire set changes then | ||
1932 | * forces a rebalance. It keys on the MPU speed, but it really could | ||
1933 | * be any key speed part of a set in the rate table. | ||
1934 | * | ||
1935 | * to really change a set, you need memory table sets which get changed | ||
1936 | * in sram, pre-notifiers & post notifiers, changing the top set, without | ||
1937 | * having low level display recalc's won't work... this is why dpm notifiers | ||
1938 | * work, isr's off, walk a list of clocks already _off_ and not messing with | ||
1939 | * the bus. | ||
1940 | * | ||
1941 | * This clock should have no parent. It embodies the entire upper level | ||
1942 | * active set. A parent will mess up some of the init also. | ||
1943 | */ | ||
1944 | static struct clk virt_prcm_set = { | ||
1945 | .name = "virt_prcm_set", | ||
1946 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | | ||
1947 | VIRTUAL_CLOCK | ALWAYS_ENABLED | DELAYED_APP, | ||
1948 | .parent = &mpu_ck, /* Indexed by mpu speed, no parent */ | ||
1949 | .recalc = &omap2_mpu_recalc, /* sets are keyed on mpu rate */ | ||
1950 | .set_rate = &omap2_select_table_rate, | ||
1951 | .round_rate = &omap2_round_to_table_rate, | ||
1952 | }; | ||
1953 | |||
1954 | static struct clk *onchip_clks[] = { | ||
1955 | /* external root sources */ | ||
1956 | &func_32k_ck, | ||
1957 | &osc_ck, | ||
1958 | &sys_ck, | ||
1959 | &alt_ck, | ||
1960 | /* internal analog sources */ | ||
1961 | &dpll_ck, | ||
1962 | &apll96_ck, | ||
1963 | &apll54_ck, | ||
1964 | /* internal prcm root sources */ | ||
1965 | &func_54m_ck, | ||
1966 | &core_ck, | ||
1967 | &sleep_ck, | ||
1968 | &func_96m_ck, | ||
1969 | &func_48m_ck, | ||
1970 | &func_12m_ck, | ||
1971 | &wdt1_osc_ck, | ||
1972 | &sys_clkout, | ||
1973 | &sys_clkout2, | ||
1974 | /* mpu domain clocks */ | ||
1975 | &mpu_ck, | ||
1976 | /* dsp domain clocks */ | ||
1977 | &iva2_1_fck, /* 2430 */ | ||
1978 | &iva2_1_ick, | ||
1979 | &dsp_ick, /* 2420 */ | ||
1980 | &dsp_fck, | ||
1981 | &iva1_ifck, | ||
1982 | &iva1_mpu_int_ifck, | ||
1983 | /* GFX domain clocks */ | ||
1984 | &gfx_3d_fck, | ||
1985 | &gfx_2d_fck, | ||
1986 | &gfx_ick, | ||
1987 | /* Modem domain clocks */ | ||
1988 | &mdm_ick, | ||
1989 | &mdm_osc_ck, | ||
1990 | /* DSS domain clocks */ | ||
1991 | &dss_ick, | ||
1992 | &dss1_fck, | ||
1993 | &dss2_fck, | ||
1994 | &dss_54m_fck, | ||
1995 | /* L3 domain clocks */ | ||
1996 | &core_l3_ck, | ||
1997 | &ssi_ssr_sst_fck, | ||
1998 | &usb_l4_ick, | ||
1999 | /* L4 domain clocks */ | ||
2000 | &l4_ck, /* used as both core_l4 and wu_l4 */ | ||
2001 | &ssi_l4_ick, | ||
2002 | /* virtual meta-group clock */ | ||
2003 | &virt_prcm_set, | ||
2004 | /* general l4 interface ck, multi-parent functional clk */ | ||
2005 | &gpt1_ick, | ||
2006 | &gpt1_fck, | ||
2007 | &gpt2_ick, | ||
2008 | &gpt2_fck, | ||
2009 | &gpt3_ick, | ||
2010 | &gpt3_fck, | ||
2011 | &gpt4_ick, | ||
2012 | &gpt4_fck, | ||
2013 | &gpt5_ick, | ||
2014 | &gpt5_fck, | ||
2015 | &gpt6_ick, | ||
2016 | &gpt6_fck, | ||
2017 | &gpt7_ick, | ||
2018 | &gpt7_fck, | ||
2019 | &gpt8_ick, | ||
2020 | &gpt8_fck, | ||
2021 | &gpt9_ick, | ||
2022 | &gpt9_fck, | ||
2023 | &gpt10_ick, | ||
2024 | &gpt10_fck, | ||
2025 | &gpt11_ick, | ||
2026 | &gpt11_fck, | ||
2027 | &gpt12_ick, | ||
2028 | &gpt12_fck, | ||
2029 | &mcbsp1_ick, | ||
2030 | &mcbsp1_fck, | ||
2031 | &mcbsp2_ick, | ||
2032 | &mcbsp2_fck, | ||
2033 | &mcbsp3_ick, | ||
2034 | &mcbsp3_fck, | ||
2035 | &mcbsp4_ick, | ||
2036 | &mcbsp4_fck, | ||
2037 | &mcbsp5_ick, | ||
2038 | &mcbsp5_fck, | ||
2039 | &mcspi1_ick, | ||
2040 | &mcspi1_fck, | ||
2041 | &mcspi2_ick, | ||
2042 | &mcspi2_fck, | ||
2043 | &mcspi3_ick, | ||
2044 | &mcspi3_fck, | ||
2045 | &uart1_ick, | ||
2046 | &uart1_fck, | ||
2047 | &uart2_ick, | ||
2048 | &uart2_fck, | ||
2049 | &uart3_ick, | ||
2050 | &uart3_fck, | ||
2051 | &gpios_ick, | ||
2052 | &gpios_fck, | ||
2053 | &mpu_wdt_ick, | ||
2054 | &mpu_wdt_fck, | ||
2055 | &sync_32k_ick, | ||
2056 | &wdt1_ick, | ||
2057 | &omapctrl_ick, | ||
2058 | &icr_ick, | ||
2059 | &cam_fck, | ||
2060 | &cam_ick, | ||
2061 | &mailboxes_ick, | ||
2062 | &wdt4_ick, | ||
2063 | &wdt4_fck, | ||
2064 | &wdt3_ick, | ||
2065 | &wdt3_fck, | ||
2066 | &mspro_ick, | ||
2067 | &mspro_fck, | ||
2068 | &mmc_ick, | ||
2069 | &mmc_fck, | ||
2070 | &fac_ick, | ||
2071 | &fac_fck, | ||
2072 | &eac_ick, | ||
2073 | &eac_fck, | ||
2074 | &hdq_ick, | ||
2075 | &hdq_fck, | ||
2076 | &i2c1_ick, | ||
2077 | &i2c1_fck, | ||
2078 | &i2chs1_fck, | ||
2079 | &i2c2_ick, | ||
2080 | &i2c2_fck, | ||
2081 | &i2chs2_fck, | ||
2082 | &vlynq_ick, | ||
2083 | &vlynq_fck, | ||
2084 | &sdrc_ick, | ||
2085 | &des_ick, | ||
2086 | &sha_ick, | ||
2087 | &rng_ick, | ||
2088 | &aes_ick, | ||
2089 | &pka_ick, | ||
2090 | &usb_fck, | ||
2091 | &usbhs_ick, | ||
2092 | &mmchs1_ick, | ||
2093 | &mmchs1_fck, | ||
2094 | &mmchs2_ick, | ||
2095 | &mmchs2_fck, | ||
2096 | &gpio5_ick, | ||
2097 | &gpio5_fck, | ||
2098 | &mdm_intc_ick, | ||
2099 | &mmchsdb1_fck, | ||
2100 | &mmchsdb2_fck, | ||
2101 | }; | ||
2102 | |||
2103 | #endif | ||
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c new file mode 100644 index 000000000000..7181edb89352 --- /dev/null +++ b/arch/arm/mach-omap2/devices.c | |||
@@ -0,0 +1,89 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-omap2/devices.c | ||
3 | * | ||
4 | * OMAP2 platform device setup/initialization | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/config.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | |||
18 | #include <asm/hardware.h> | ||
19 | #include <asm/io.h> | ||
20 | #include <asm/mach-types.h> | ||
21 | #include <asm/mach/map.h> | ||
22 | |||
23 | #include <asm/arch/tc.h> | ||
24 | #include <asm/arch/board.h> | ||
25 | #include <asm/arch/mux.h> | ||
26 | #include <asm/arch/gpio.h> | ||
27 | |||
28 | extern void omap_nop_release(struct device *dev); | ||
29 | |||
30 | /*-------------------------------------------------------------------------*/ | ||
31 | |||
32 | #if defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE) | ||
33 | |||
34 | #define OMAP2_I2C_BASE2 0x48072000 | ||
35 | #define OMAP2_I2C_INT2 57 | ||
36 | |||
37 | static struct resource i2c_resources2[] = { | ||
38 | { | ||
39 | .start = OMAP2_I2C_BASE2, | ||
40 | .end = OMAP2_I2C_BASE2 + 0x3f, | ||
41 | .flags = IORESOURCE_MEM, | ||
42 | }, | ||
43 | { | ||
44 | .start = OMAP2_I2C_INT2, | ||
45 | .flags = IORESOURCE_IRQ, | ||
46 | }, | ||
47 | }; | ||
48 | |||
49 | static struct platform_device omap_i2c_device2 = { | ||
50 | .name = "i2c_omap", | ||
51 | .id = 2, | ||
52 | .dev = { | ||
53 | .release = omap_nop_release, | ||
54 | }, | ||
55 | .num_resources = ARRAY_SIZE(i2c_resources2), | ||
56 | .resource = i2c_resources2, | ||
57 | }; | ||
58 | |||
59 | /* See also arch/arm/plat-omap/devices.c for first I2C on 24xx */ | ||
60 | static void omap_init_i2c(void) | ||
61 | { | ||
62 | /* REVISIT: Second I2C not in use on H4? */ | ||
63 | if (machine_is_omap_h4()) | ||
64 | return; | ||
65 | |||
66 | omap_cfg_reg(J15_24XX_I2C2_SCL); | ||
67 | omap_cfg_reg(H19_24XX_I2C2_SDA); | ||
68 | (void) platform_device_register(&omap_i2c_device2); | ||
69 | } | ||
70 | |||
71 | #else | ||
72 | |||
73 | static void omap_init_i2c(void) {} | ||
74 | |||
75 | #endif | ||
76 | |||
77 | /*-------------------------------------------------------------------------*/ | ||
78 | |||
79 | static int __init omap2_init_devices(void) | ||
80 | { | ||
81 | /* please keep these calls, and their implementations above, | ||
82 | * in alphabetical order so they're easier to sort through. | ||
83 | */ | ||
84 | omap_init_i2c(); | ||
85 | |||
86 | return 0; | ||
87 | } | ||
88 | arch_initcall(omap2_init_devices); | ||
89 | |||
diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c new file mode 100644 index 000000000000..76187300f2b6 --- /dev/null +++ b/arch/arm/mach-omap2/id.c | |||
@@ -0,0 +1,124 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-omap2/id.c | ||
3 | * | ||
4 | * OMAP2 CPU identification code | ||
5 | * | ||
6 | * Copyright (C) 2005 Nokia Corporation | ||
7 | * Written by Tony Lindgren <tony@atomide.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <linux/config.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/init.h> | ||
18 | |||
19 | #include <asm/io.h> | ||
20 | |||
21 | #define OMAP24XX_TAP_BASE io_p2v(0x48014000) | ||
22 | |||
23 | #define OMAP_TAP_IDCODE 0x0204 | ||
24 | #define OMAP_TAP_PROD_ID 0x0208 | ||
25 | |||
26 | #define OMAP_TAP_DIE_ID_0 0x0218 | ||
27 | #define OMAP_TAP_DIE_ID_1 0x021C | ||
28 | #define OMAP_TAP_DIE_ID_2 0x0220 | ||
29 | #define OMAP_TAP_DIE_ID_3 0x0224 | ||
30 | |||
31 | /* system_rev fields for OMAP2 processors: | ||
32 | * CPU id bits [31:16], | ||
33 | * CPU device type [15:12], (unprg,normal,POP) | ||
34 | * CPU revision [11:08] | ||
35 | * CPU class bits [07:00] | ||
36 | */ | ||
37 | |||
38 | struct omap_id { | ||
39 | u16 hawkeye; /* Silicon type (Hawkeye id) */ | ||
40 | u8 dev; /* Device type from production_id reg */ | ||
41 | u32 type; /* combined type id copied to system_rev */ | ||
42 | }; | ||
43 | |||
44 | /* Register values to detect the OMAP version */ | ||
45 | static struct omap_id omap_ids[] __initdata = { | ||
46 | { .hawkeye = 0xb5d9, .dev = 0x0, .type = 0x24200000 }, | ||
47 | { .hawkeye = 0xb5d9, .dev = 0x1, .type = 0x24201000 }, | ||
48 | { .hawkeye = 0xb5d9, .dev = 0x2, .type = 0x24202000 }, | ||
49 | { .hawkeye = 0xb5d9, .dev = 0x4, .type = 0x24220000 }, | ||
50 | { .hawkeye = 0xb5d9, .dev = 0x8, .type = 0x24230000 }, | ||
51 | { .hawkeye = 0xb68a, .dev = 0x0, .type = 0x24300000 }, | ||
52 | }; | ||
53 | |||
54 | static u32 __init read_tap_reg(int reg) | ||
55 | { | ||
56 | return __raw_readl(OMAP24XX_TAP_BASE + reg); | ||
57 | } | ||
58 | |||
59 | void __init omap2_check_revision(void) | ||
60 | { | ||
61 | int i, j; | ||
62 | u32 idcode; | ||
63 | u32 prod_id; | ||
64 | u16 hawkeye; | ||
65 | u8 dev_type; | ||
66 | u8 rev; | ||
67 | |||
68 | idcode = read_tap_reg(OMAP_TAP_IDCODE); | ||
69 | prod_id = read_tap_reg(OMAP_TAP_PROD_ID); | ||
70 | hawkeye = (idcode >> 12) & 0xffff; | ||
71 | rev = (idcode >> 28) & 0x0f; | ||
72 | dev_type = (prod_id >> 16) & 0x0f; | ||
73 | |||
74 | #ifdef DEBUG | ||
75 | printk(KERN_DEBUG "OMAP_TAP_IDCODE 0x%08x REV %i HAWKEYE 0x%04x MANF %03x\n", | ||
76 | idcode, rev, hawkeye, (idcode >> 1) & 0x7ff); | ||
77 | printk(KERN_DEBUG "OMAP_TAP_DIE_ID_0: 0x%08x\n", | ||
78 | read_tap_reg(OMAP_TAP_DIE_ID_0)); | ||
79 | printk(KERN_DEBUG "OMAP_TAP_DIE_ID_1: 0x%08x DEV_REV: %i\n", | ||
80 | read_tap_reg(OMAP_TAP_DIE_ID_1), | ||
81 | (read_tap_reg(OMAP_TAP_DIE_ID_1) >> 28) & 0xf); | ||
82 | printk(KERN_DEBUG "OMAP_TAP_DIE_ID_2: 0x%08x\n", | ||
83 | read_tap_reg(OMAP_TAP_DIE_ID_2)); | ||
84 | printk(KERN_DEBUG "OMAP_TAP_DIE_ID_3: 0x%08x\n", | ||
85 | read_tap_reg(OMAP_TAP_DIE_ID_3)); | ||
86 | printk(KERN_DEBUG "OMAP_TAP_PROD_ID_0: 0x%08x DEV_TYPE: %i\n", | ||
87 | prod_id, dev_type); | ||
88 | #endif | ||
89 | |||
90 | /* Check hawkeye ids */ | ||
91 | for (i = 0; i < ARRAY_SIZE(omap_ids); i++) { | ||
92 | if (hawkeye == omap_ids[i].hawkeye) | ||
93 | break; | ||
94 | } | ||
95 | |||
96 | if (i == ARRAY_SIZE(omap_ids)) { | ||
97 | printk(KERN_ERR "Unknown OMAP CPU id\n"); | ||
98 | return; | ||
99 | } | ||
100 | |||
101 | for (j = i; j < ARRAY_SIZE(omap_ids); j++) { | ||
102 | if (dev_type == omap_ids[j].dev) | ||
103 | break; | ||
104 | } | ||
105 | |||
106 | if (j == ARRAY_SIZE(omap_ids)) { | ||
107 | printk(KERN_ERR "Unknown OMAP device type. " | ||
108 | "Handling it as OMAP%04x\n", | ||
109 | omap_ids[i].type >> 16); | ||
110 | j = i; | ||
111 | } | ||
112 | system_rev = omap_ids[j].type; | ||
113 | |||
114 | system_rev |= rev << 8; | ||
115 | |||
116 | /* Add the cpu class info (24xx) */ | ||
117 | system_rev |= 0x24; | ||
118 | |||
119 | pr_info("OMAP%04x", system_rev >> 16); | ||
120 | if ((system_rev >> 8) & 0x0f) | ||
121 | printk("%x", (system_rev >> 8) & 0x0f); | ||
122 | printk("\n"); | ||
123 | } | ||
124 | |||
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c new file mode 100644 index 000000000000..8ea67bf196a5 --- /dev/null +++ b/arch/arm/mach-omap2/io.c | |||
@@ -0,0 +1,53 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-omap2/io.c | ||
3 | * | ||
4 | * OMAP2 I/O mapping code | ||
5 | * | ||
6 | * Copyright (C) 2005 Nokia Corporation | ||
7 | * Author: Juha Yrjölä <juha.yrjola@nokia.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <linux/config.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/init.h> | ||
18 | |||
19 | #include <asm/mach/map.h> | ||
20 | #include <asm/io.h> | ||
21 | #include <asm/arch/mux.h> | ||
22 | |||
23 | extern void omap_sram_init(void); | ||
24 | extern int omap2_clk_init(void); | ||
25 | extern void omap2_check_revision(void); | ||
26 | |||
27 | /* | ||
28 | * The machine specific code may provide the extra mapping besides the | ||
29 | * default mapping provided here. | ||
30 | */ | ||
31 | static struct map_desc omap2_io_desc[] __initdata = { | ||
32 | { | ||
33 | .virtual = L3_24XX_VIRT, | ||
34 | .pfn = __phys_to_pfn(L3_24XX_PHYS), | ||
35 | .length = L3_24XX_SIZE, | ||
36 | .type = MT_DEVICE | ||
37 | }, | ||
38 | { | ||
39 | .virtual = L4_24XX_VIRT, | ||
40 | .pfn = __phys_to_pfn(L4_24XX_PHYS), | ||
41 | .length = L4_24XX_SIZE, | ||
42 | .type = MT_DEVICE | ||
43 | } | ||
44 | }; | ||
45 | |||
46 | void __init omap_map_common_io(void) | ||
47 | { | ||
48 | iotable_init(omap2_io_desc, ARRAY_SIZE(omap2_io_desc)); | ||
49 | omap2_check_revision(); | ||
50 | omap_sram_init(); | ||
51 | omap2_mux_init(); | ||
52 | omap2_clk_init(); | ||
53 | } | ||
diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c new file mode 100644 index 000000000000..d7baff675cfe --- /dev/null +++ b/arch/arm/mach-omap2/irq.c | |||
@@ -0,0 +1,149 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-omap/omap2/irq.c | ||
3 | * | ||
4 | * Interrupt handler for OMAP2 boards. | ||
5 | * | ||
6 | * Copyright (C) 2005 Nokia Corporation | ||
7 | * Author: Paul Mundt <paul.mundt@nokia.com> | ||
8 | * | ||
9 | * This file is subject to the terms and conditions of the GNU General Public | ||
10 | * License. See the file "COPYING" in the main directory of this archive | ||
11 | * for more details. | ||
12 | */ | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/config.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <asm/hardware.h> | ||
18 | #include <asm/mach/irq.h> | ||
19 | #include <asm/irq.h> | ||
20 | #include <asm/io.h> | ||
21 | |||
22 | #define INTC_REVISION 0x0000 | ||
23 | #define INTC_SYSCONFIG 0x0010 | ||
24 | #define INTC_SYSSTATUS 0x0014 | ||
25 | #define INTC_CONTROL 0x0048 | ||
26 | #define INTC_MIR_CLEAR0 0x0088 | ||
27 | #define INTC_MIR_SET0 0x008c | ||
28 | |||
29 | /* | ||
30 | * OMAP2 has a number of different interrupt controllers, each interrupt | ||
31 | * controller is identified as its own "bank". Register definitions are | ||
32 | * fairly consistent for each bank, but not all registers are implemented | ||
33 | * for each bank.. when in doubt, consult the TRM. | ||
34 | */ | ||
35 | static struct omap_irq_bank { | ||
36 | unsigned long base_reg; | ||
37 | unsigned int nr_irqs; | ||
38 | } __attribute__ ((aligned(4))) irq_banks[] = { | ||
39 | { | ||
40 | /* MPU INTC */ | ||
41 | .base_reg = OMAP24XX_IC_BASE, | ||
42 | .nr_irqs = 96, | ||
43 | }, { | ||
44 | /* XXX: DSP INTC */ | ||
45 | |||
46 | #if 0 | ||
47 | /* | ||
48 | * Commented out for now until we fix the IVA clocking | ||
49 | */ | ||
50 | #ifdef CONFIG_ARCH_OMAP2420 | ||
51 | }, { | ||
52 | /* IVA INTC (2420 only) */ | ||
53 | .base_reg = OMAP24XX_IVA_INTC_BASE, | ||
54 | .nr_irqs = 16, /* Actually 32, but only 16 are used */ | ||
55 | #endif | ||
56 | #endif | ||
57 | } | ||
58 | }; | ||
59 | |||
60 | /* XXX: FIQ and additional INTC support (only MPU at the moment) */ | ||
61 | static void omap_ack_irq(unsigned int irq) | ||
62 | { | ||
63 | omap_writel(0x1, irq_banks[0].base_reg + INTC_CONTROL); | ||
64 | } | ||
65 | |||
66 | static void omap_mask_irq(unsigned int irq) | ||
67 | { | ||
68 | int offset = (irq >> 5) << 5; | ||
69 | |||
70 | if (irq >= 64) { | ||
71 | irq %= 64; | ||
72 | } else if (irq >= 32) { | ||
73 | irq %= 32; | ||
74 | } | ||
75 | |||
76 | omap_writel(1 << irq, irq_banks[0].base_reg + INTC_MIR_SET0 + offset); | ||
77 | } | ||
78 | |||
79 | static void omap_unmask_irq(unsigned int irq) | ||
80 | { | ||
81 | int offset = (irq >> 5) << 5; | ||
82 | |||
83 | if (irq >= 64) { | ||
84 | irq %= 64; | ||
85 | } else if (irq >= 32) { | ||
86 | irq %= 32; | ||
87 | } | ||
88 | |||
89 | omap_writel(1 << irq, irq_banks[0].base_reg + INTC_MIR_CLEAR0 + offset); | ||
90 | } | ||
91 | |||
92 | static void omap_mask_ack_irq(unsigned int irq) | ||
93 | { | ||
94 | omap_mask_irq(irq); | ||
95 | omap_ack_irq(irq); | ||
96 | } | ||
97 | |||
98 | static struct irqchip omap_irq_chip = { | ||
99 | .ack = omap_mask_ack_irq, | ||
100 | .mask = omap_mask_irq, | ||
101 | .unmask = omap_unmask_irq, | ||
102 | }; | ||
103 | |||
104 | static void __init omap_irq_bank_init_one(struct omap_irq_bank *bank) | ||
105 | { | ||
106 | unsigned long tmp; | ||
107 | |||
108 | tmp = omap_readl(bank->base_reg + INTC_REVISION) & 0xff; | ||
109 | printk(KERN_INFO "IRQ: Found an INTC at 0x%08lx " | ||
110 | "(revision %ld.%ld) with %d interrupts\n", | ||
111 | bank->base_reg, tmp >> 4, tmp & 0xf, bank->nr_irqs); | ||
112 | |||
113 | tmp = omap_readl(bank->base_reg + INTC_SYSCONFIG); | ||
114 | tmp |= 1 << 1; /* soft reset */ | ||
115 | omap_writel(tmp, bank->base_reg + INTC_SYSCONFIG); | ||
116 | |||
117 | while (!(omap_readl(bank->base_reg + INTC_SYSSTATUS) & 0x1)) | ||
118 | /* Wait for reset to complete */; | ||
119 | } | ||
120 | |||
121 | void __init omap_init_irq(void) | ||
122 | { | ||
123 | unsigned long nr_irqs = 0; | ||
124 | unsigned int nr_banks = 0; | ||
125 | int i; | ||
126 | |||
127 | for (i = 0; i < ARRAY_SIZE(irq_banks); i++) { | ||
128 | struct omap_irq_bank *bank = irq_banks + i; | ||
129 | |||
130 | /* XXX */ | ||
131 | if (!bank->base_reg) | ||
132 | continue; | ||
133 | |||
134 | omap_irq_bank_init_one(bank); | ||
135 | |||
136 | nr_irqs += bank->nr_irqs; | ||
137 | nr_banks++; | ||
138 | } | ||
139 | |||
140 | printk(KERN_INFO "Total of %ld interrupts on %d active controller%s\n", | ||
141 | nr_irqs, nr_banks, nr_banks > 1 ? "s" : ""); | ||
142 | |||
143 | for (i = 0; i < nr_irqs; i++) { | ||
144 | set_irq_chip(i, &omap_irq_chip); | ||
145 | set_irq_handler(i, do_level_IRQ); | ||
146 | set_irq_flags(i, IRQF_VALID); | ||
147 | } | ||
148 | } | ||
149 | |||
diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c new file mode 100644 index 000000000000..ea4654815dd1 --- /dev/null +++ b/arch/arm/mach-omap2/mux.c | |||
@@ -0,0 +1,65 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-omap2/mux.c | ||
3 | * | ||
4 | * OMAP1 pin multiplexing configurations | ||
5 | * | ||
6 | * Copyright (C) 2003 - 2005 Nokia Corporation | ||
7 | * | ||
8 | * Written by Tony Lindgren <tony.lindgren@nokia.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
23 | * | ||
24 | */ | ||
25 | #include <linux/config.h> | ||
26 | #include <linux/module.h> | ||
27 | #include <linux/init.h> | ||
28 | #include <asm/system.h> | ||
29 | #include <asm/io.h> | ||
30 | #include <linux/spinlock.h> | ||
31 | |||
32 | #include <asm/arch/mux.h> | ||
33 | |||
34 | #ifdef CONFIG_OMAP_MUX | ||
35 | |||
36 | /* NOTE: See mux.h for the enumeration */ | ||
37 | |||
38 | struct pin_config __initdata_or_module omap24xx_pins[] = { | ||
39 | /* | ||
40 | * description mux mux pull pull debug | ||
41 | * offset mode ena type | ||
42 | */ | ||
43 | |||
44 | /* 24xx I2C */ | ||
45 | MUX_CFG_24XX("M19_24XX_I2C1_SCL", 0x111, 0, 0, 0, 1) | ||
46 | MUX_CFG_24XX("L15_24XX_I2C1_SDA", 0x112, 0, 0, 0, 1) | ||
47 | MUX_CFG_24XX("J15_24XX_I2C2_SCL", 0x113, 0, 0, 0, 1) | ||
48 | MUX_CFG_24XX("H19_24XX_I2C2_SDA", 0x114, 0, 0, 0, 1) | ||
49 | |||
50 | /* Menelaus interrupt */ | ||
51 | MUX_CFG_24XX("W19_24XX_SYS_NIRQ", 0x12c, 0, 1, 1, 1) | ||
52 | |||
53 | /* 24xx GPIO */ | ||
54 | MUX_CFG_24XX("Y20_24XX_GPIO60", 0x12c, 3, 0, 0, 1) | ||
55 | MUX_CFG_24XX("M15_24XX_GPIO92", 0x10a, 3, 0, 0, 1) | ||
56 | |||
57 | }; | ||
58 | |||
59 | int __init omap2_mux_init(void) | ||
60 | { | ||
61 | omap_mux_register(omap24xx_pins, ARRAY_SIZE(omap24xx_pins)); | ||
62 | return 0; | ||
63 | } | ||
64 | |||
65 | #endif | ||
diff --git a/arch/arm/mach-omap2/prcm.h b/arch/arm/mach-omap2/prcm.h new file mode 100644 index 000000000000..2eb89b936c83 --- /dev/null +++ b/arch/arm/mach-omap2/prcm.h | |||
@@ -0,0 +1,419 @@ | |||
1 | /* | ||
2 | * prcm.h - Access definations for use in OMAP24XX clock and power management | ||
3 | * | ||
4 | * Copyright (C) 2005 Texas Instruments, Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #ifndef __ASM_ARM_ARCH_DPM_PRCM_H | ||
22 | #define __ASM_ARM_ARCH_DPM_PRCM_H | ||
23 | |||
24 | /* SET_PERFORMANCE_LEVEL PARAMETERS */ | ||
25 | #define PRCM_HALF_SPEED 1 | ||
26 | #define PRCM_FULL_SPEED 2 | ||
27 | |||
28 | #ifndef __ASSEMBLER__ | ||
29 | |||
30 | #define PRCM_REG32(offset) __REG32(OMAP24XX_PRCM_BASE + (offset)) | ||
31 | |||
32 | #define PRCM_REVISION PRCM_REG32(0x000) | ||
33 | #define PRCM_SYSCONFIG PRCM_REG32(0x010) | ||
34 | #define PRCM_IRQSTATUS_MPU PRCM_REG32(0x018) | ||
35 | #define PRCM_IRQENABLE_MPU PRCM_REG32(0x01C) | ||
36 | #define PRCM_VOLTCTRL PRCM_REG32(0x050) | ||
37 | #define PRCM_VOLTST PRCM_REG32(0x054) | ||
38 | #define PRCM_CLKSRC_CTRL PRCM_REG32(0x060) | ||
39 | #define PRCM_CLKOUT_CTRL PRCM_REG32(0x070) | ||
40 | #define PRCM_CLKEMUL_CTRL PRCM_REG32(0x078) | ||
41 | #define PRCM_CLKCFG_CTRL PRCM_REG32(0x080) | ||
42 | #define PRCM_CLKCFG_STATUS PRCM_REG32(0x084) | ||
43 | #define PRCM_VOLTSETUP PRCM_REG32(0x090) | ||
44 | #define PRCM_CLKSSETUP PRCM_REG32(0x094) | ||
45 | #define PRCM_POLCTRL PRCM_REG32(0x098) | ||
46 | |||
47 | /* GENERAL PURPOSE */ | ||
48 | #define GENERAL_PURPOSE1 PRCM_REG32(0x0B0) | ||
49 | #define GENERAL_PURPOSE2 PRCM_REG32(0x0B4) | ||
50 | #define GENERAL_PURPOSE3 PRCM_REG32(0x0B8) | ||
51 | #define GENERAL_PURPOSE4 PRCM_REG32(0x0BC) | ||
52 | #define GENERAL_PURPOSE5 PRCM_REG32(0x0C0) | ||
53 | #define GENERAL_PURPOSE6 PRCM_REG32(0x0C4) | ||
54 | #define GENERAL_PURPOSE7 PRCM_REG32(0x0C8) | ||
55 | #define GENERAL_PURPOSE8 PRCM_REG32(0x0CC) | ||
56 | #define GENERAL_PURPOSE9 PRCM_REG32(0x0D0) | ||
57 | #define GENERAL_PURPOSE10 PRCM_REG32(0x0D4) | ||
58 | #define GENERAL_PURPOSE11 PRCM_REG32(0x0D8) | ||
59 | #define GENERAL_PURPOSE12 PRCM_REG32(0x0DC) | ||
60 | #define GENERAL_PURPOSE13 PRCM_REG32(0x0E0) | ||
61 | #define GENERAL_PURPOSE14 PRCM_REG32(0x0E4) | ||
62 | #define GENERAL_PURPOSE15 PRCM_REG32(0x0E8) | ||
63 | #define GENERAL_PURPOSE16 PRCM_REG32(0x0EC) | ||
64 | #define GENERAL_PURPOSE17 PRCM_REG32(0x0F0) | ||
65 | #define GENERAL_PURPOSE18 PRCM_REG32(0x0F4) | ||
66 | #define GENERAL_PURPOSE19 PRCM_REG32(0x0F8) | ||
67 | #define GENERAL_PURPOSE20 PRCM_REG32(0x0FC) | ||
68 | |||
69 | /* MPU */ | ||
70 | #define CM_CLKSEL_MPU PRCM_REG32(0x140) | ||
71 | #define CM_CLKSTCTRL_MPU PRCM_REG32(0x148) | ||
72 | #define RM_RSTST_MPU PRCM_REG32(0x158) | ||
73 | #define PM_WKDEP_MPU PRCM_REG32(0x1C8) | ||
74 | #define PM_EVGENCTRL_MPU PRCM_REG32(0x1D4) | ||
75 | #define PM_EVEGENONTIM_MPU PRCM_REG32(0x1D8) | ||
76 | #define PM_EVEGENOFFTIM_MPU PRCM_REG32(0x1DC) | ||
77 | #define PM_PWSTCTRL_MPU PRCM_REG32(0x1E0) | ||
78 | #define PM_PWSTST_MPU PRCM_REG32(0x1E4) | ||
79 | |||
80 | /* CORE */ | ||
81 | #define CM_FCLKEN1_CORE PRCM_REG32(0x200) | ||
82 | #define CM_FCLKEN2_CORE PRCM_REG32(0x204) | ||
83 | #define CM_FCLKEN3_CORE PRCM_REG32(0x208) | ||
84 | #define CM_ICLKEN1_CORE PRCM_REG32(0x210) | ||
85 | #define CM_ICLKEN2_CORE PRCM_REG32(0x214) | ||
86 | #define CM_ICLKEN3_CORE PRCM_REG32(0x218) | ||
87 | #define CM_ICLKEN4_CORE PRCM_REG32(0x21C) | ||
88 | #define CM_IDLEST1_CORE PRCM_REG32(0x220) | ||
89 | #define CM_IDLEST2_CORE PRCM_REG32(0x224) | ||
90 | #define CM_IDLEST3_CORE PRCM_REG32(0x228) | ||
91 | #define CM_IDLEST4_CORE PRCM_REG32(0x22C) | ||
92 | #define CM_AUTOIDLE1_CORE PRCM_REG32(0x230) | ||
93 | #define CM_AUTOIDLE2_CORE PRCM_REG32(0x234) | ||
94 | #define CM_AUTOIDLE3_CORE PRCM_REG32(0x238) | ||
95 | #define CM_AUTOIDLE4_CORE PRCM_REG32(0x23C) | ||
96 | #define CM_CLKSEL1_CORE PRCM_REG32(0x240) | ||
97 | #define CM_CLKSEL2_CORE PRCM_REG32(0x244) | ||
98 | #define CM_CLKSTCTRL_CORE PRCM_REG32(0x248) | ||
99 | #define PM_WKEN1_CORE PRCM_REG32(0x2A0) | ||
100 | #define PM_WKEN2_CORE PRCM_REG32(0x2A4) | ||
101 | #define PM_WKST1_CORE PRCM_REG32(0x2B0) | ||
102 | #define PM_WKST2_CORE PRCM_REG32(0x2B4) | ||
103 | #define PM_WKDEP_CORE PRCM_REG32(0x2C8) | ||
104 | #define PM_PWSTCTRL_CORE PRCM_REG32(0x2E0) | ||
105 | #define PM_PWSTST_CORE PRCM_REG32(0x2E4) | ||
106 | |||
107 | /* GFX */ | ||
108 | #define CM_FCLKEN_GFX PRCM_REG32(0x300) | ||
109 | #define CM_ICLKEN_GFX PRCM_REG32(0x310) | ||
110 | #define CM_IDLEST_GFX PRCM_REG32(0x320) | ||
111 | #define CM_CLKSEL_GFX PRCM_REG32(0x340) | ||
112 | #define CM_CLKSTCTRL_GFX PRCM_REG32(0x348) | ||
113 | #define RM_RSTCTRL_GFX PRCM_REG32(0x350) | ||
114 | #define RM_RSTST_GFX PRCM_REG32(0x358) | ||
115 | #define PM_WKDEP_GFX PRCM_REG32(0x3C8) | ||
116 | #define PM_PWSTCTRL_GFX PRCM_REG32(0x3E0) | ||
117 | #define PM_PWSTST_GFX PRCM_REG32(0x3E4) | ||
118 | |||
119 | /* WAKE-UP */ | ||
120 | #define CM_FCLKEN_WKUP PRCM_REG32(0x400) | ||
121 | #define CM_ICLKEN_WKUP PRCM_REG32(0x410) | ||
122 | #define CM_IDLEST_WKUP PRCM_REG32(0x420) | ||
123 | #define CM_AUTOIDLE_WKUP PRCM_REG32(0x430) | ||
124 | #define CM_CLKSEL_WKUP PRCM_REG32(0x440) | ||
125 | #define RM_RSTCTRL_WKUP PRCM_REG32(0x450) | ||
126 | #define RM_RSTTIME_WKUP PRCM_REG32(0x454) | ||
127 | #define RM_RSTST_WKUP PRCM_REG32(0x458) | ||
128 | #define PM_WKEN_WKUP PRCM_REG32(0x4A0) | ||
129 | #define PM_WKST_WKUP PRCM_REG32(0x4B0) | ||
130 | |||
131 | /* CLOCKS */ | ||
132 | #define CM_CLKEN_PLL PRCM_REG32(0x500) | ||
133 | #define CM_IDLEST_CKGEN PRCM_REG32(0x520) | ||
134 | #define CM_AUTOIDLE_PLL PRCM_REG32(0x530) | ||
135 | #define CM_CLKSEL1_PLL PRCM_REG32(0x540) | ||
136 | #define CM_CLKSEL2_PLL PRCM_REG32(0x544) | ||
137 | |||
138 | /* DSP */ | ||
139 | #define CM_FCLKEN_DSP PRCM_REG32(0x800) | ||
140 | #define CM_ICLKEN_DSP PRCM_REG32(0x810) | ||
141 | #define CM_IDLEST_DSP PRCM_REG32(0x820) | ||
142 | #define CM_AUTOIDLE_DSP PRCM_REG32(0x830) | ||
143 | #define CM_CLKSEL_DSP PRCM_REG32(0x840) | ||
144 | #define CM_CLKSTCTRL_DSP PRCM_REG32(0x848) | ||
145 | #define RM_RSTCTRL_DSP PRCM_REG32(0x850) | ||
146 | #define RM_RSTST_DSP PRCM_REG32(0x858) | ||
147 | #define PM_WKEN_DSP PRCM_REG32(0x8A0) | ||
148 | #define PM_WKDEP_DSP PRCM_REG32(0x8C8) | ||
149 | #define PM_PWSTCTRL_DSP PRCM_REG32(0x8E0) | ||
150 | #define PM_PWSTST_DSP PRCM_REG32(0x8E4) | ||
151 | #define PRCM_IRQSTATUS_DSP PRCM_REG32(0x8F0) | ||
152 | #define PRCM_IRQENABLE_DSP PRCM_REG32(0x8F4) | ||
153 | |||
154 | /* IVA */ | ||
155 | #define PRCM_IRQSTATUS_IVA PRCM_REG32(0x8F8) | ||
156 | #define PRCM_IRQENABLE_IVA PRCM_REG32(0x8FC) | ||
157 | |||
158 | /* Modem on 2430 */ | ||
159 | #define CM_FCLKEN_MDM PRCM_REG32(0xC00) | ||
160 | #define CM_ICLKEN_MDM PRCM_REG32(0xC10) | ||
161 | #define CM_IDLEST_MDM PRCM_REG32(0xC20) | ||
162 | #define CM_CLKSEL_MDM PRCM_REG32(0xC40) | ||
163 | |||
164 | /* FIXME: Move to header for 2430 */ | ||
165 | #define DISP_BASE (OMAP24XX_L4_IO_BASE+0x50000) | ||
166 | #define DISP_REG32(offset) __REG32(DISP_BASE + (offset)) | ||
167 | |||
168 | #define GPMC_BASE (OMAP24XX_GPMC_BASE) | ||
169 | #define GPMC_REG32(offset) __REG32(GPMC_BASE + (offset)) | ||
170 | |||
171 | #define GPT1_BASE (OMAP24XX_GPT1) | ||
172 | #define GPT1_REG32(offset) __REG32(GPT1_BASE + (offset)) | ||
173 | |||
174 | /* Misc sysconfig */ | ||
175 | #define DISPC_SYSCONFIG DISP_REG32(0x410) | ||
176 | #define SPI_BASE (OMAP24XX_L4_IO_BASE+0x98000) | ||
177 | #define MCSPI1_SYSCONFIG __REG32(SPI_BASE + 0x10) | ||
178 | #define MCSPI2_SYSCONFIG __REG32(SPI_BASE+0x2000 + 0x10) | ||
179 | |||
180 | //#define DSP_MMU_SYSCONFIG 0x5A000010 | ||
181 | #define CAMERA_MMU_SYSCONFIG __REG32(DISP_BASE+0x2C10) | ||
182 | //#define IVA_MMU_SYSCONFIG 0x5D000010 | ||
183 | //#define DSP_DMA_SYSCONFIG 0x00FCC02C | ||
184 | #define CAMERA_DMA_SYSCONFIG __REG32(DISP_BASE+0x282C) | ||
185 | #define SYSTEM_DMA_SYSCONFIG __REG32(DISP_BASE+0x602C) | ||
186 | #define GPMC_SYSCONFIG GPMC_REG32(0x010) | ||
187 | #define MAILBOXES_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE+0x94010) | ||
188 | #define UART1_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE+0x6A054) | ||
189 | #define UART2_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE+0x6C054) | ||
190 | #define UART3_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE+0x6E054) | ||
191 | //#define IVA_SYSCONFIG 0x5C060010 | ||
192 | #define SDRC_SYSCONFIG __REG32(OMAP24XX_SDRC_BASE+0x10) | ||
193 | #define SMS_SYSCONFIG __REG32(OMAP24XX_SMS_BASE+0x10) | ||
194 | #define SSI_SYSCONFIG __REG32(DISP_BASE+0x8010) | ||
195 | //#define VLYNQ_SYSCONFIG 0x67FFFE10 | ||
196 | |||
197 | /* rkw - good cannidates for PM_ to start what nm was trying */ | ||
198 | #define OMAP24XX_GPT2 (OMAP24XX_L4_IO_BASE+0x2A000) | ||
199 | #define OMAP24XX_GPT3 (OMAP24XX_L4_IO_BASE+0x78000) | ||
200 | #define OMAP24XX_GPT4 (OMAP24XX_L4_IO_BASE+0x7A000) | ||
201 | #define OMAP24XX_GPT5 (OMAP24XX_L4_IO_BASE+0x7C000) | ||
202 | #define OMAP24XX_GPT6 (OMAP24XX_L4_IO_BASE+0x7E000) | ||
203 | #define OMAP24XX_GPT7 (OMAP24XX_L4_IO_BASE+0x80000) | ||
204 | #define OMAP24XX_GPT8 (OMAP24XX_L4_IO_BASE+0x82000) | ||
205 | #define OMAP24XX_GPT9 (OMAP24XX_L4_IO_BASE+0x84000) | ||
206 | #define OMAP24XX_GPT10 (OMAP24XX_L4_IO_BASE+0x86000) | ||
207 | #define OMAP24XX_GPT11 (OMAP24XX_L4_IO_BASE+0x88000) | ||
208 | #define OMAP24XX_GPT12 (OMAP24XX_L4_IO_BASE+0x8A000) | ||
209 | |||
210 | #define GPTIMER1_SYSCONFIG GPT1_REG32(0x010) | ||
211 | #define GPTIMER2_SYSCONFIG __REG32(OMAP24XX_GPT2 + 0x10) | ||
212 | #define GPTIMER3_SYSCONFIG __REG32(OMAP24XX_GPT3 + 0x10) | ||
213 | #define GPTIMER4_SYSCONFIG __REG32(OMAP24XX_GPT4 + 0x10) | ||
214 | #define GPTIMER5_SYSCONFIG __REG32(OMAP24XX_GPT5 + 0x10) | ||
215 | #define GPTIMER6_SYSCONFIG __REG32(OMAP24XX_GPT6 + 0x10) | ||
216 | #define GPTIMER7_SYSCONFIG __REG32(OMAP24XX_GPT7 + 0x10) | ||
217 | #define GPTIMER8_SYSCONFIG __REG32(OMAP24XX_GPT8 + 0x10) | ||
218 | #define GPTIMER9_SYSCONFIG __REG32(OMAP24XX_GPT9 + 0x10) | ||
219 | #define GPTIMER10_SYSCONFIG __REG32(OMAP24XX_GPT10 + 0x10) | ||
220 | #define GPTIMER11_SYSCONFIG __REG32(OMAP24XX_GPT11 + 0x10) | ||
221 | #define GPTIMER12_SYSCONFIG __REG32(OMAP24XX_GPT12 + 0x10) | ||
222 | |||
223 | #define GPIOX_BASE(X) (OMAP24XX_GPIO_BASE+(0x2000*((X)-1))) | ||
224 | |||
225 | #define GPIO1_SYSCONFIG __REG32((GPIOX_BASE(1)+0x10)) | ||
226 | #define GPIO2_SYSCONFIG __REG32((GPIOX_BASE(2)+0x10)) | ||
227 | #define GPIO3_SYSCONFIG __REG32((GPIOX_BASE(3)+0x10)) | ||
228 | #define GPIO4_SYSCONFIG __REG32((GPIOX_BASE(4)+0x10)) | ||
229 | |||
230 | /* GP TIMER 1 */ | ||
231 | #define GPTIMER1_TISTAT GPT1_REG32(0x014) | ||
232 | #define GPTIMER1_TISR GPT1_REG32(0x018) | ||
233 | #define GPTIMER1_TIER GPT1_REG32(0x01C) | ||
234 | #define GPTIMER1_TWER GPT1_REG32(0x020) | ||
235 | #define GPTIMER1_TCLR GPT1_REG32(0x024) | ||
236 | #define GPTIMER1_TCRR GPT1_REG32(0x028) | ||
237 | #define GPTIMER1_TLDR GPT1_REG32(0x02C) | ||
238 | #define GPTIMER1_TTGR GPT1_REG32(0x030) | ||
239 | #define GPTIMER1_TWPS GPT1_REG32(0x034) | ||
240 | #define GPTIMER1_TMAR GPT1_REG32(0x038) | ||
241 | #define GPTIMER1_TCAR1 GPT1_REG32(0x03C) | ||
242 | #define GPTIMER1_TSICR GPT1_REG32(0x040) | ||
243 | #define GPTIMER1_TCAR2 GPT1_REG32(0x044) | ||
244 | |||
245 | /* rkw -- base fix up please... */ | ||
246 | #define GPTIMER3_TISR __REG32(OMAP24XX_L4_IO_BASE+0x78018) | ||
247 | |||
248 | /* SDRC */ | ||
249 | #define SDRC_DLLA_CTRL __REG32(OMAP24XX_SDRC_BASE+0x060) | ||
250 | #define SDRC_DLLA_STATUS __REG32(OMAP24XX_SDRC_BASE+0x064) | ||
251 | #define SDRC_DLLB_CTRL __REG32(OMAP24XX_SDRC_BASE+0x068) | ||
252 | #define SDRC_DLLB_STATUS __REG32(OMAP24XX_SDRC_BASE+0x06C) | ||
253 | #define SDRC_POWER __REG32(OMAP24XX_SDRC_BASE+0x070) | ||
254 | #define SDRC_MR_0 __REG32(OMAP24XX_SDRC_BASE+0x084) | ||
255 | |||
256 | /* GPIO 1 */ | ||
257 | #define GPIO1_BASE GPIOX_BASE(1) | ||
258 | #define GPIO1_REG32(offset) __REG32(GPIO1_BASE + (offset)) | ||
259 | #define GPIO1_IRQENABLE1 GPIO1_REG32(0x01C) | ||
260 | #define GPIO1_IRQSTATUS1 GPIO1_REG32(0x018) | ||
261 | #define GPIO1_IRQENABLE2 GPIO1_REG32(0x02C) | ||
262 | #define GPIO1_IRQSTATUS2 GPIO1_REG32(0x028) | ||
263 | #define GPIO1_WAKEUPENABLE GPIO1_REG32(0x020) | ||
264 | #define GPIO1_RISINGDETECT GPIO1_REG32(0x048) | ||
265 | #define GPIO1_DATAIN GPIO1_REG32(0x038) | ||
266 | #define GPIO1_OE GPIO1_REG32(0x034) | ||
267 | #define GPIO1_DATAOUT GPIO1_REG32(0x03C) | ||
268 | |||
269 | /* GPIO2 */ | ||
270 | #define GPIO2_BASE GPIOX_BASE(2) | ||
271 | #define GPIO2_REG32(offset) __REG32(GPIO2_BASE + (offset)) | ||
272 | #define GPIO2_IRQENABLE1 GPIO2_REG32(0x01C) | ||
273 | #define GPIO2_IRQSTATUS1 GPIO2_REG32(0x018) | ||
274 | #define GPIO2_IRQENABLE2 GPIO2_REG32(0x02C) | ||
275 | #define GPIO2_IRQSTATUS2 GPIO2_REG32(0x028) | ||
276 | #define GPIO2_WAKEUPENABLE GPIO2_REG32(0x020) | ||
277 | #define GPIO2_RISINGDETECT GPIO2_REG32(0x048) | ||
278 | #define GPIO2_DATAIN GPIO2_REG32(0x038) | ||
279 | #define GPIO2_OE GPIO2_REG32(0x034) | ||
280 | #define GPIO2_DATAOUT GPIO2_REG32(0x03C) | ||
281 | |||
282 | /* GPIO 3 */ | ||
283 | #define GPIO3_BASE GPIOX_BASE(3) | ||
284 | #define GPIO3_REG32(offset) __REG32(GPIO3_BASE + (offset)) | ||
285 | #define GPIO3_IRQENABLE1 GPIO3_REG32(0x01C) | ||
286 | #define GPIO3_IRQSTATUS1 GPIO3_REG32(0x018) | ||
287 | #define GPIO3_IRQENABLE2 GPIO3_REG32(0x02C) | ||
288 | #define GPIO3_IRQSTATUS2 GPIO3_REG32(0x028) | ||
289 | #define GPIO3_WAKEUPENABLE GPIO3_REG32(0x020) | ||
290 | #define GPIO3_RISINGDETECT GPIO3_REG32(0x048) | ||
291 | #define GPIO3_FALLINGDETECT GPIO3_REG32(0x04C) | ||
292 | #define GPIO3_DATAIN GPIO3_REG32(0x038) | ||
293 | #define GPIO3_OE GPIO3_REG32(0x034) | ||
294 | #define GPIO3_DATAOUT GPIO3_REG32(0x03C) | ||
295 | #define GPIO3_DEBOUNCENABLE GPIO3_REG32(0x050) | ||
296 | #define GPIO3_DEBOUNCINGTIME GPIO3_REG32(0x054) | ||
297 | |||
298 | /* GPIO 4 */ | ||
299 | #define GPIO4_BASE GPIOX_BASE(4) | ||
300 | #define GPIO4_REG32(offset) __REG32(GPIO4_BASE + (offset)) | ||
301 | #define GPIO4_IRQENABLE1 GPIO4_REG32(0x01C) | ||
302 | #define GPIO4_IRQSTATUS1 GPIO4_REG32(0x018) | ||
303 | #define GPIO4_IRQENABLE2 GPIO4_REG32(0x02C) | ||
304 | #define GPIO4_IRQSTATUS2 GPIO4_REG32(0x028) | ||
305 | #define GPIO4_WAKEUPENABLE GPIO4_REG32(0x020) | ||
306 | #define GPIO4_RISINGDETECT GPIO4_REG32(0x048) | ||
307 | #define GPIO4_FALLINGDETECT GPIO4_REG32(0x04C) | ||
308 | #define GPIO4_DATAIN GPIO4_REG32(0x038) | ||
309 | #define GPIO4_OE GPIO4_REG32(0x034) | ||
310 | #define GPIO4_DATAOUT GPIO4_REG32(0x03C) | ||
311 | #define GPIO4_DEBOUNCENABLE GPIO4_REG32(0x050) | ||
312 | #define GPIO4_DEBOUNCINGTIME GPIO4_REG32(0x054) | ||
313 | |||
314 | |||
315 | /* IO CONFIG */ | ||
316 | #define CONTROL_BASE (OMAP24XX_CTRL_BASE) | ||
317 | #define CONTROL_REG32(offset) __REG32(CONTROL_BASE + (offset)) | ||
318 | |||
319 | #define CONTROL_PADCONF_SPI1_NCS2 CONTROL_REG32(0x104) | ||
320 | #define CONTROL_PADCONF_SYS_XTALOUT CONTROL_REG32(0x134) | ||
321 | #define CONTROL_PADCONF_UART1_RX CONTROL_REG32(0x0C8) | ||
322 | #define CONTROL_PADCONF_MCBSP1_DX CONTROL_REG32(0x10C) | ||
323 | #define CONTROL_PADCONF_GPMC_NCS4 CONTROL_REG32(0x090) | ||
324 | #define CONTROL_PADCONF_DSS_D5 CONTROL_REG32(0x0B8) | ||
325 | #define CONTROL_PADCONF_DSS_D9 CONTROL_REG32(0x0BC) | ||
326 | #define CONTROL_PADCONF_DSS_D13 CONTROL_REG32(0x0C0) | ||
327 | #define CONTROL_PADCONF_DSS_VSYNC CONTROL_REG32(0x0CC) | ||
328 | |||
329 | /* CONTROL */ | ||
330 | #define CONTROL_DEVCONF CONTROL_REG32(0x274) | ||
331 | |||
332 | /* INTERRUPT CONTROLLER */ | ||
333 | #define INTC_BASE (OMAP24XX_L4_IO_BASE+0xfe000) | ||
334 | #define INTC_REG32(offset) __REG32(INTC_BASE + (offset)) | ||
335 | |||
336 | #define INTC1_U_BASE INTC_REG32(0x000) | ||
337 | #define INTC_MIR0 INTC_REG32(0x084) | ||
338 | #define INTC_MIR_SET0 INTC_REG32(0x08C) | ||
339 | #define INTC_MIR_CLEAR0 INTC_REG32(0x088) | ||
340 | #define INTC_ISR_CLEAR0 INTC_REG32(0x094) | ||
341 | #define INTC_MIR1 INTC_REG32(0x0A4) | ||
342 | #define INTC_MIR_SET1 INTC_REG32(0x0AC) | ||
343 | #define INTC_MIR_CLEAR1 INTC_REG32(0x0A8) | ||
344 | #define INTC_ISR_CLEAR1 INTC_REG32(0x0B4) | ||
345 | #define INTC_MIR2 INTC_REG32(0x0C4) | ||
346 | #define INTC_MIR_SET2 INTC_REG32(0x0CC) | ||
347 | #define INTC_MIR_CLEAR2 INTC_REG32(0x0C8) | ||
348 | #define INTC_ISR_CLEAR2 INTC_REG32(0x0D4) | ||
349 | #define INTC_SIR_IRQ INTC_REG32(0x040) | ||
350 | #define INTC_CONTROL INTC_REG32(0x048) | ||
351 | #define INTC_ILR11 INTC_REG32(0x12C) | ||
352 | #define INTC_ILR32 INTC_REG32(0x180) | ||
353 | #define INTC_ILR37 INTC_REG32(0x194) | ||
354 | #define INTC_SYSCONFIG INTC_REG32(0x010) | ||
355 | |||
356 | /* RAM FIREWALL */ | ||
357 | #define RAMFW_BASE (0x68005000) | ||
358 | #define RAMFW_REG32(offset) __REG32(RAMFW_BASE + (offset)) | ||
359 | |||
360 | #define RAMFW_REQINFOPERM0 RAMFW_REG32(0x048) | ||
361 | #define RAMFW_READPERM0 RAMFW_REG32(0x050) | ||
362 | #define RAMFW_WRITEPERM0 RAMFW_REG32(0x058) | ||
363 | |||
364 | /* GPMC CS1 FPGA ON USER INTERFACE MODULE */ | ||
365 | //#define DEBUG_BOARD_LED_REGISTER 0x04000014 | ||
366 | |||
367 | /* GPMC CS0 */ | ||
368 | #define GPMC_CONFIG1_0 GPMC_REG32(0x060) | ||
369 | #define GPMC_CONFIG2_0 GPMC_REG32(0x064) | ||
370 | #define GPMC_CONFIG3_0 GPMC_REG32(0x068) | ||
371 | #define GPMC_CONFIG4_0 GPMC_REG32(0x06C) | ||
372 | #define GPMC_CONFIG5_0 GPMC_REG32(0x070) | ||
373 | #define GPMC_CONFIG6_0 GPMC_REG32(0x074) | ||
374 | #define GPMC_CONFIG7_0 GPMC_REG32(0x078) | ||
375 | |||
376 | /* DSS */ | ||
377 | #define DSS_CONTROL DISP_REG32(0x040) | ||
378 | #define DISPC_CONTROL DISP_REG32(0x440) | ||
379 | #define DISPC_SYSSTATUS DISP_REG32(0x414) | ||
380 | #define DISPC_IRQSTATUS DISP_REG32(0x418) | ||
381 | #define DISPC_IRQENABLE DISP_REG32(0x41C) | ||
382 | #define DISPC_CONFIG DISP_REG32(0x444) | ||
383 | #define DISPC_DEFAULT_COLOR0 DISP_REG32(0x44C) | ||
384 | #define DISPC_DEFAULT_COLOR1 DISP_REG32(0x450) | ||
385 | #define DISPC_TRANS_COLOR0 DISP_REG32(0x454) | ||
386 | #define DISPC_TRANS_COLOR1 DISP_REG32(0x458) | ||
387 | #define DISPC_LINE_NUMBER DISP_REG32(0x460) | ||
388 | #define DISPC_TIMING_H DISP_REG32(0x464) | ||
389 | #define DISPC_TIMING_V DISP_REG32(0x468) | ||
390 | #define DISPC_POL_FREQ DISP_REG32(0x46C) | ||
391 | #define DISPC_DIVISOR DISP_REG32(0x470) | ||
392 | #define DISPC_SIZE_DIG DISP_REG32(0x478) | ||
393 | #define DISPC_SIZE_LCD DISP_REG32(0x47C) | ||
394 | #define DISPC_GFX_BA0 DISP_REG32(0x480) | ||
395 | #define DISPC_GFX_BA1 DISP_REG32(0x484) | ||
396 | #define DISPC_GFX_POSITION DISP_REG32(0x488) | ||
397 | #define DISPC_GFX_SIZE DISP_REG32(0x48C) | ||
398 | #define DISPC_GFX_ATTRIBUTES DISP_REG32(0x4A0) | ||
399 | #define DISPC_GFX_FIFO_THRESHOLD DISP_REG32(0x4A4) | ||
400 | #define DISPC_GFX_ROW_INC DISP_REG32(0x4AC) | ||
401 | #define DISPC_GFX_PIXEL_INC DISP_REG32(0x4B0) | ||
402 | #define DISPC_GFX_WINDOW_SKIP DISP_REG32(0x4B4) | ||
403 | #define DISPC_GFX_TABLE_BA DISP_REG32(0x4B8) | ||
404 | #define DISPC_DATA_CYCLE1 DISP_REG32(0x5D4) | ||
405 | #define DISPC_DATA_CYCLE2 DISP_REG32(0x5D8) | ||
406 | #define DISPC_DATA_CYCLE3 DISP_REG32(0x5DC) | ||
407 | |||
408 | /* Wake up define for board */ | ||
409 | #define GPIO97 (1 << 1) | ||
410 | #define GPIO88 (1 << 24) | ||
411 | |||
412 | #endif /* __ASSEMBLER__ */ | ||
413 | |||
414 | #endif | ||
415 | |||
416 | |||
417 | |||
418 | |||
419 | |||
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c new file mode 100644 index 000000000000..f4df04fe1dd8 --- /dev/null +++ b/arch/arm/mach-omap2/serial.c | |||
@@ -0,0 +1,180 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-omap/omap2/serial.c | ||
3 | * | ||
4 | * OMAP2 serial support. | ||
5 | * | ||
6 | * Copyright (C) 2005 Nokia Corporation | ||
7 | * Author: Paul Mundt <paul.mundt@nokia.com> | ||
8 | * | ||
9 | * Based off of arch/arm/mach-omap/omap1/serial.c | ||
10 | * | ||
11 | * This file is subject to the terms and conditions of the GNU General Public | ||
12 | * License. See the file "COPYING" in the main directory of this archive | ||
13 | * for more details. | ||
14 | */ | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/serial_8250.h> | ||
18 | #include <linux/serial_reg.h> | ||
19 | |||
20 | #include <asm/io.h> | ||
21 | #include <asm/hardware/clock.h> | ||
22 | |||
23 | #include <asm/arch/common.h> | ||
24 | #include <asm/arch/board.h> | ||
25 | |||
26 | static struct clk * uart1_ick = NULL; | ||
27 | static struct clk * uart1_fck = NULL; | ||
28 | static struct clk * uart2_ick = NULL; | ||
29 | static struct clk * uart2_fck = NULL; | ||
30 | static struct clk * uart3_ick = NULL; | ||
31 | static struct clk * uart3_fck = NULL; | ||
32 | |||
33 | static struct plat_serial8250_port serial_platform_data[] = { | ||
34 | { | ||
35 | .membase = (char *)IO_ADDRESS(OMAP_UART1_BASE), | ||
36 | .mapbase = (unsigned long)OMAP_UART1_BASE, | ||
37 | .irq = 72, | ||
38 | .flags = UPF_BOOT_AUTOCONF, | ||
39 | .iotype = UPIO_MEM, | ||
40 | .regshift = 2, | ||
41 | .uartclk = OMAP16XX_BASE_BAUD * 16, | ||
42 | }, { | ||
43 | .membase = (char *)IO_ADDRESS(OMAP_UART2_BASE), | ||
44 | .mapbase = (unsigned long)OMAP_UART2_BASE, | ||
45 | .irq = 73, | ||
46 | .flags = UPF_BOOT_AUTOCONF, | ||
47 | .iotype = UPIO_MEM, | ||
48 | .regshift = 2, | ||
49 | .uartclk = OMAP16XX_BASE_BAUD * 16, | ||
50 | }, { | ||
51 | .membase = (char *)IO_ADDRESS(OMAP_UART3_BASE), | ||
52 | .mapbase = (unsigned long)OMAP_UART3_BASE, | ||
53 | .irq = 74, | ||
54 | .flags = UPF_BOOT_AUTOCONF, | ||
55 | .iotype = UPIO_MEM, | ||
56 | .regshift = 2, | ||
57 | .uartclk = OMAP16XX_BASE_BAUD * 16, | ||
58 | }, { | ||
59 | .flags = 0 | ||
60 | } | ||
61 | }; | ||
62 | |||
63 | static inline unsigned int serial_read_reg(struct plat_serial8250_port *up, | ||
64 | int offset) | ||
65 | { | ||
66 | offset <<= up->regshift; | ||
67 | return (unsigned int)__raw_readb(up->membase + offset); | ||
68 | } | ||
69 | |||
70 | static inline void serial_write_reg(struct plat_serial8250_port *p, int offset, | ||
71 | int value) | ||
72 | { | ||
73 | offset <<= p->regshift; | ||
74 | __raw_writeb(value, (unsigned long)(p->membase + offset)); | ||
75 | } | ||
76 | |||
77 | /* | ||
78 | * Internal UARTs need to be initialized for the 8250 autoconfig to work | ||
79 | * properly. Note that the TX watermark initialization may not be needed | ||
80 | * once the 8250.c watermark handling code is merged. | ||
81 | */ | ||
82 | static inline void __init omap_serial_reset(struct plat_serial8250_port *p) | ||
83 | { | ||
84 | serial_write_reg(p, UART_OMAP_MDR1, 0x07); | ||
85 | serial_write_reg(p, UART_OMAP_SCR, 0x08); | ||
86 | serial_write_reg(p, UART_OMAP_MDR1, 0x00); | ||
87 | serial_write_reg(p, UART_OMAP_SYSC, 0x01); | ||
88 | } | ||
89 | |||
90 | void __init omap_serial_init() | ||
91 | { | ||
92 | int i; | ||
93 | const struct omap_uart_config *info; | ||
94 | |||
95 | /* | ||
96 | * Make sure the serial ports are muxed on at this point. | ||
97 | * You have to mux them off in device drivers later on | ||
98 | * if not needed. | ||
99 | */ | ||
100 | |||
101 | info = omap_get_config(OMAP_TAG_UART, | ||
102 | struct omap_uart_config); | ||
103 | |||
104 | if (info == NULL) | ||
105 | return; | ||
106 | |||
107 | for (i = 0; i < OMAP_MAX_NR_PORTS; i++) { | ||
108 | struct plat_serial8250_port *p = serial_platform_data + i; | ||
109 | |||
110 | if (!(info->enabled_uarts & (1 << i))) { | ||
111 | p->membase = 0; | ||
112 | p->mapbase = 0; | ||
113 | continue; | ||
114 | } | ||
115 | |||
116 | switch (i) { | ||
117 | case 0: | ||
118 | uart1_ick = clk_get(NULL, "uart1_ick"); | ||
119 | if (IS_ERR(uart1_ick)) | ||
120 | printk("Could not get uart1_ick\n"); | ||
121 | else { | ||
122 | clk_use(uart1_ick); | ||
123 | } | ||
124 | |||
125 | uart1_fck = clk_get(NULL, "uart1_fck"); | ||
126 | if (IS_ERR(uart1_fck)) | ||
127 | printk("Could not get uart1_fck\n"); | ||
128 | else { | ||
129 | clk_use(uart1_fck); | ||
130 | } | ||
131 | break; | ||
132 | case 1: | ||
133 | uart2_ick = clk_get(NULL, "uart2_ick"); | ||
134 | if (IS_ERR(uart2_ick)) | ||
135 | printk("Could not get uart2_ick\n"); | ||
136 | else { | ||
137 | clk_use(uart2_ick); | ||
138 | } | ||
139 | |||
140 | uart2_fck = clk_get(NULL, "uart2_fck"); | ||
141 | if (IS_ERR(uart2_fck)) | ||
142 | printk("Could not get uart2_fck\n"); | ||
143 | else { | ||
144 | clk_use(uart2_fck); | ||
145 | } | ||
146 | break; | ||
147 | case 2: | ||
148 | uart3_ick = clk_get(NULL, "uart3_ick"); | ||
149 | if (IS_ERR(uart3_ick)) | ||
150 | printk("Could not get uart3_ick\n"); | ||
151 | else { | ||
152 | clk_use(uart3_ick); | ||
153 | } | ||
154 | |||
155 | uart3_fck = clk_get(NULL, "uart3_fck"); | ||
156 | if (IS_ERR(uart3_fck)) | ||
157 | printk("Could not get uart3_fck\n"); | ||
158 | else { | ||
159 | clk_use(uart3_fck); | ||
160 | } | ||
161 | break; | ||
162 | } | ||
163 | |||
164 | omap_serial_reset(p); | ||
165 | } | ||
166 | } | ||
167 | |||
168 | static struct platform_device serial_device = { | ||
169 | .name = "serial8250", | ||
170 | .id = 0, | ||
171 | .dev = { | ||
172 | .platform_data = serial_platform_data, | ||
173 | }, | ||
174 | }; | ||
175 | |||
176 | static int __init omap_init(void) | ||
177 | { | ||
178 | return platform_device_register(&serial_device); | ||
179 | } | ||
180 | arch_initcall(omap_init); | ||
diff --git a/arch/arm/mach-omap2/sram-fn.S b/arch/arm/mach-omap2/sram-fn.S new file mode 100644 index 000000000000..2a869e203342 --- /dev/null +++ b/arch/arm/mach-omap2/sram-fn.S | |||
@@ -0,0 +1,333 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-omap1/sram.S | ||
3 | * | ||
4 | * Omap2 specific functions that need to be run in internal SRAM | ||
5 | * | ||
6 | * (C) Copyright 2004 | ||
7 | * Texas Instruments, <www.ti.com> | ||
8 | * Richard Woodruff <r-woodruff2@ti.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | ||
11 | * modify it under the terms of the GNU General Public License as | ||
12 | * published by the Free Software Foundation; either version 2 of | ||
13 | * the License, or (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR /PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | ||
23 | * MA 02111-1307 USA | ||
24 | */ | ||
25 | #include <linux/config.h> | ||
26 | #include <linux/linkage.h> | ||
27 | #include <asm/assembler.h> | ||
28 | #include <asm/arch/io.h> | ||
29 | #include <asm/hardware.h> | ||
30 | |||
31 | #include <asm/arch/prcm.h> | ||
32 | |||
33 | #define TIMER_32KSYNCT_CR_V IO_ADDRESS(OMAP24XX_32KSYNCT_BASE + 0x010) | ||
34 | |||
35 | #define CM_CLKSEL2_PLL_V IO_ADDRESS(OMAP24XX_PRCM_BASE + 0x544) | ||
36 | #define PRCM_VOLTCTRL_V IO_ADDRESS(OMAP24XX_PRCM_BASE + 0x050) | ||
37 | #define PRCM_CLKCFG_CTRL_V IO_ADDRESS(OMAP24XX_PRCM_BASE + 0x080) | ||
38 | #define CM_CLKEN_PLL_V IO_ADDRESS(OMAP24XX_PRCM_BASE + 0x500) | ||
39 | #define CM_IDLEST_CKGEN_V IO_ADDRESS(OMAP24XX_PRCM_BASE + 0x520) | ||
40 | #define CM_CLKSEL1_PLL_V IO_ADDRESS(OMAP24XX_PRCM_BASE + 0x540) | ||
41 | |||
42 | #define SDRC_DLLA_CTRL_V IO_ADDRESS(OMAP24XX_SDRC_BASE + 0x060) | ||
43 | #define SDRC_RFR_CTRL_V IO_ADDRESS(OMAP24XX_SDRC_BASE + 0x0a4) | ||
44 | |||
45 | .text | ||
46 | |||
47 | ENTRY(sram_ddr_init) | ||
48 | stmfd sp!, {r0 - r12, lr} @ save registers on stack | ||
49 | |||
50 | mov r12, r2 @ capture CS1 vs CS0 | ||
51 | mov r8, r3 @ capture force parameter | ||
52 | |||
53 | /* frequency shift down */ | ||
54 | ldr r2, cm_clksel2_pll @ get address of dpllout reg | ||
55 | mov r3, #0x1 @ value for 1x operation | ||
56 | str r3, [r2] @ go to L1-freq operation | ||
57 | |||
58 | /* voltage shift down */ | ||
59 | mov r9, #0x1 @ set up for L1 voltage call | ||
60 | bl voltage_shift @ go drop voltage | ||
61 | |||
62 | /* dll lock mode */ | ||
63 | ldr r11, sdrc_dlla_ctrl @ addr of dlla ctrl | ||
64 | ldr r10, [r11] @ get current val | ||
65 | cmp r12, #0x1 @ cs1 base (2422 es2.05/1) | ||
66 | addeq r11, r11, #0x8 @ if cs1 base, move to DLLB | ||
67 | mvn r9, #0x4 @ mask to get clear bit2 | ||
68 | and r10, r10, r9 @ clear bit2 for lock mode. | ||
69 | orr r10, r10, #0x8 @ make sure DLL on (es2 bit pos) | ||
70 | orr r10, r10, #0x2 @ 90 degree phase for all below 133Mhz | ||
71 | str r10, [r11] @ commit to DLLA_CTRL | ||
72 | bl i_dll_wait @ wait for dll to lock | ||
73 | |||
74 | /* get dll value */ | ||
75 | add r11, r11, #0x4 @ get addr of status reg | ||
76 | ldr r10, [r11] @ get locked value | ||
77 | |||
78 | /* voltage shift up */ | ||
79 | mov r9, #0x0 @ shift back to L0-voltage | ||
80 | bl voltage_shift @ go raise voltage | ||
81 | |||
82 | /* frequency shift up */ | ||
83 | mov r3, #0x2 @ value for 2x operation | ||
84 | str r3, [r2] @ go to L0-freq operation | ||
85 | |||
86 | /* reset entry mode for dllctrl */ | ||
87 | sub r11, r11, #0x4 @ move from status to ctrl | ||
88 | cmp r12, #0x1 @ normalize if cs1 based | ||
89 | subeq r11, r11, #0x8 @ possibly back to DLLA | ||
90 | cmp r8, #0x1 @ if forced unlock exit | ||
91 | orreq r1, r1, #0x4 @ make sure exit with unlocked value | ||
92 | str r1, [r11] @ restore DLLA_CTRL high value | ||
93 | add r11, r11, #0x8 @ move to DLLB_CTRL addr | ||
94 | str r1, [r11] @ set value DLLB_CTRL | ||
95 | bl i_dll_wait @ wait for possible lock | ||
96 | |||
97 | /* set up for return, DDR should be good */ | ||
98 | str r10, [r0] @ write dll_status and return counter | ||
99 | ldmfd sp!, {r0 - r12, pc} @ restore regs and return | ||
100 | |||
101 | /* ensure the DLL has relocked */ | ||
102 | i_dll_wait: | ||
103 | mov r4, #0x800 @ delay DLL relock, min 0x400 L3 clocks | ||
104 | i_dll_delay: | ||
105 | subs r4, r4, #0x1 | ||
106 | bne i_dll_delay | ||
107 | mov pc, lr | ||
108 | |||
109 | /* | ||
110 | * shift up or down voltage, use R9 as input to tell level. | ||
111 | * wait for it to finish, use 32k sync counter, 1tick=31uS. | ||
112 | */ | ||
113 | voltage_shift: | ||
114 | ldr r4, prcm_voltctrl @ get addr of volt ctrl. | ||
115 | ldr r5, [r4] @ get value. | ||
116 | ldr r6, prcm_mask_val @ get value of mask | ||
117 | and r5, r5, r6 @ apply mask to clear bits | ||
118 | orr r5, r5, r9 @ bulld value for L0/L1-volt operation. | ||
119 | str r5, [r4] @ set up for change. | ||
120 | mov r3, #0x4000 @ get val for force | ||
121 | orr r5, r5, r3 @ build value for force | ||
122 | str r5, [r4] @ Force transition to L1 | ||
123 | |||
124 | ldr r3, timer_32ksynct_cr @ get addr of counter | ||
125 | ldr r5, [r3] @ get value | ||
126 | add r5, r5, #0x3 @ give it at most 93uS | ||
127 | volt_delay: | ||
128 | ldr r7, [r3] @ get timer value | ||
129 | cmp r5, r7 @ time up? | ||
130 | bhi volt_delay @ not yet->branch | ||
131 | mov pc, lr @ back to caller. | ||
132 | |||
133 | /* relative load constants */ | ||
134 | cm_clksel2_pll: | ||
135 | .word CM_CLKSEL2_PLL_V | ||
136 | sdrc_dlla_ctrl: | ||
137 | .word SDRC_DLLA_CTRL_V | ||
138 | prcm_voltctrl: | ||
139 | .word PRCM_VOLTCTRL_V | ||
140 | prcm_mask_val: | ||
141 | .word 0xFFFF3FFC | ||
142 | timer_32ksynct_cr: | ||
143 | .word TIMER_32KSYNCT_CR_V | ||
144 | ENTRY(sram_ddr_init_sz) | ||
145 | .word . - sram_ddr_init | ||
146 | |||
147 | /* | ||
148 | * Reprograms memory timings. | ||
149 | * r0 = [PRCM_FULL | PRCM_HALF] r1 = SDRC_DLLA_CTRL value r2 = [DDR | SDR] | ||
150 | * PRCM_FULL = 2, PRCM_HALF = 1, DDR = 1, SDR = 0 | ||
151 | */ | ||
152 | ENTRY(sram_reprogram_sdrc) | ||
153 | stmfd sp!, {r0 - r10, lr} @ save registers on stack | ||
154 | mov r3, #0x0 @ clear for mrc call | ||
155 | mcr p15, 0, r3, c7, c10, 4 @ memory barrier, finish ARM SDR/DDR | ||
156 | nop | ||
157 | nop | ||
158 | ldr r6, ddr_sdrc_rfr_ctrl @ get addr of refresh reg | ||
159 | ldr r5, [r6] @ get value | ||
160 | mov r5, r5, lsr #8 @ isolate rfr field and drop burst | ||
161 | |||
162 | cmp r0, #0x1 @ going to half speed? | ||
163 | movne r9, #0x0 @ if up set flag up for pre up, hi volt | ||
164 | |||
165 | blne voltage_shift_c @ adjust voltage | ||
166 | |||
167 | cmp r0, #0x1 @ going to half speed (post branch link) | ||
168 | moveq r5, r5, lsr #1 @ divide by 2 if to half | ||
169 | movne r5, r5, lsl #1 @ mult by 2 if to full | ||
170 | mov r5, r5, lsl #8 @ put rfr field back into place | ||
171 | add r5, r5, #0x1 @ turn on burst of 1 | ||
172 | ldr r4, ddr_cm_clksel2_pll @ get address of out reg | ||
173 | ldr r3, [r4] @ get curr value | ||
174 | orr r3, r3, #0x3 | ||
175 | bic r3, r3, #0x3 @ clear lower bits | ||
176 | orr r3, r3, r0 @ new state value | ||
177 | str r3, [r4] @ set new state (pll/x, x=1 or 2) | ||
178 | nop | ||
179 | nop | ||
180 | |||
181 | moveq r9, #0x1 @ if speed down, post down, drop volt | ||
182 | bleq voltage_shift_c | ||
183 | |||
184 | mcr p15, 0, r3, c7, c10, 4 @ memory barrier | ||
185 | str r5, [r6] @ set new RFR_1 value | ||
186 | add r6, r6, #0x30 @ get RFR_2 addr | ||
187 | str r5, [r6] @ set RFR_2 | ||
188 | nop | ||
189 | cmp r2, #0x1 @ (SDR or DDR) do we need to adjust DLL | ||
190 | bne freq_out @ leave if SDR, no DLL function | ||
191 | |||
192 | /* With DDR, we need to take care of the DLL for the frequency change */ | ||
193 | ldr r2, ddr_sdrc_dlla_ctrl @ addr of dlla ctrl | ||
194 | str r1, [r2] @ write out new SDRC_DLLA_CTRL | ||
195 | add r2, r2, #0x8 @ addr to SDRC_DLLB_CTRL | ||
196 | str r1, [r2] @ commit to SDRC_DLLB_CTRL | ||
197 | mov r1, #0x2000 @ wait DLL relock, min 0x400 L3 clocks | ||
198 | dll_wait: | ||
199 | subs r1, r1, #0x1 | ||
200 | bne dll_wait | ||
201 | freq_out: | ||
202 | ldmfd sp!, {r0 - r10, pc} @ restore regs and return | ||
203 | |||
204 | /* | ||
205 | * shift up or down voltage, use R9 as input to tell level. | ||
206 | * wait for it to finish, use 32k sync counter, 1tick=31uS. | ||
207 | */ | ||
208 | voltage_shift_c: | ||
209 | ldr r10, ddr_prcm_voltctrl @ get addr of volt ctrl | ||
210 | ldr r8, [r10] @ get value | ||
211 | ldr r7, ddr_prcm_mask_val @ get value of mask | ||
212 | and r8, r8, r7 @ apply mask to clear bits | ||
213 | orr r8, r8, r9 @ bulld value for L0/L1-volt operation. | ||
214 | str r8, [r10] @ set up for change. | ||
215 | mov r7, #0x4000 @ get val for force | ||
216 | orr r8, r8, r7 @ build value for force | ||
217 | str r8, [r10] @ Force transition to L1 | ||
218 | |||
219 | ldr r10, ddr_timer_32ksynct @ get addr of counter | ||
220 | ldr r8, [r10] @ get value | ||
221 | add r8, r8, #0x2 @ give it at most 62uS (min 31+) | ||
222 | volt_delay_c: | ||
223 | ldr r7, [r10] @ get timer value | ||
224 | cmp r8, r7 @ time up? | ||
225 | bhi volt_delay_c @ not yet->branch | ||
226 | mov pc, lr @ back to caller | ||
227 | |||
228 | ddr_cm_clksel2_pll: | ||
229 | .word CM_CLKSEL2_PLL_V | ||
230 | ddr_sdrc_dlla_ctrl: | ||
231 | .word SDRC_DLLA_CTRL_V | ||
232 | ddr_sdrc_rfr_ctrl: | ||
233 | .word SDRC_RFR_CTRL_V | ||
234 | ddr_prcm_voltctrl: | ||
235 | .word PRCM_VOLTCTRL_V | ||
236 | ddr_prcm_mask_val: | ||
237 | .word 0xFFFF3FFC | ||
238 | ddr_timer_32ksynct: | ||
239 | .word TIMER_32KSYNCT_CR_V | ||
240 | |||
241 | ENTRY(sram_reprogram_sdrc_sz) | ||
242 | .word . - sram_reprogram_sdrc | ||
243 | |||
244 | /* | ||
245 | * Set dividers and pll. Also recalculate DLL value for DDR and unlock mode. | ||
246 | */ | ||
247 | ENTRY(sram_set_prcm) | ||
248 | stmfd sp!, {r0-r12, lr} @ regs to stack | ||
249 | adr r4, pbegin @ addr of preload start | ||
250 | adr r8, pend @ addr of preload end | ||
251 | mcrr p15, 1, r8, r4, c12 @ preload into icache | ||
252 | pbegin: | ||
253 | /* move into fast relock bypass */ | ||
254 | ldr r8, pll_ctl @ get addr | ||
255 | ldr r5, [r8] @ get val | ||
256 | mvn r6, #0x3 @ clear mask | ||
257 | and r5, r5, r6 @ clear field | ||
258 | orr r7, r5, #0x2 @ fast relock val | ||
259 | str r7, [r8] @ go to fast relock | ||
260 | ldr r4, pll_stat @ addr of stat | ||
261 | block: | ||
262 | /* wait for bypass */ | ||
263 | ldr r8, [r4] @ stat value | ||
264 | and r8, r8, #0x3 @ mask for stat | ||
265 | cmp r8, #0x1 @ there yet | ||
266 | bne block @ loop if not | ||
267 | |||
268 | /* set new dpll dividers _after_ in bypass */ | ||
269 | ldr r4, pll_div @ get addr | ||
270 | str r0, [r4] @ set dpll ctrl val | ||
271 | |||
272 | ldr r4, set_config @ get addr | ||
273 | mov r8, #1 @ valid cfg msk | ||
274 | str r8, [r4] @ make dividers take | ||
275 | |||
276 | mov r4, #100 @ dead spin a bit | ||
277 | wait_a_bit: | ||
278 | subs r4, r4, #1 @ dec loop | ||
279 | bne wait_a_bit @ delay done? | ||
280 | |||
281 | /* check if staying in bypass */ | ||
282 | cmp r2, #0x1 @ stay in bypass? | ||
283 | beq pend @ jump over dpll relock | ||
284 | |||
285 | /* relock DPLL with new vals */ | ||
286 | ldr r5, pll_stat @ get addr | ||
287 | ldr r4, pll_ctl @ get addr | ||
288 | orr r8, r7, #0x3 @ val for lock dpll | ||
289 | str r8, [r4] @ set val | ||
290 | mov r0, #1000 @ dead spin a bit | ||
291 | wait_more: | ||
292 | subs r0, r0, #1 @ dec loop | ||
293 | bne wait_more @ delay done? | ||
294 | wait_lock: | ||
295 | ldr r8, [r5] @ get lock val | ||
296 | and r8, r8, #3 @ isolate field | ||
297 | cmp r8, #2 @ locked? | ||
298 | bne wait_lock @ wait if not | ||
299 | pend: | ||
300 | /* update memory timings & briefly lock dll */ | ||
301 | ldr r4, sdrc_rfr @ get addr | ||
302 | str r1, [r4] @ update refresh timing | ||
303 | ldr r11, dlla_ctrl @ get addr of DLLA ctrl | ||
304 | ldr r10, [r11] @ get current val | ||
305 | mvn r9, #0x4 @ mask to get clear bit2 | ||
306 | and r10, r10, r9 @ clear bit2 for lock mode | ||
307 | orr r10, r10, #0x8 @ make sure DLL on (es2 bit pos) | ||
308 | str r10, [r11] @ commit to DLLA_CTRL | ||
309 | add r11, r11, #0x8 @ move to dllb | ||
310 | str r10, [r11] @ hit DLLB also | ||
311 | |||
312 | mov r4, #0x800 @ relock time (min 0x400 L3 clocks) | ||
313 | wait_dll_lock: | ||
314 | subs r4, r4, #0x1 | ||
315 | bne wait_dll_lock | ||
316 | nop | ||
317 | ldmfd sp!, {r0-r12, pc} @ restore regs and return | ||
318 | |||
319 | set_config: | ||
320 | .word PRCM_CLKCFG_CTRL_V | ||
321 | pll_ctl: | ||
322 | .word CM_CLKEN_PLL_V | ||
323 | pll_stat: | ||
324 | .word CM_IDLEST_CKGEN_V | ||
325 | pll_div: | ||
326 | .word CM_CLKSEL1_PLL_V | ||
327 | sdrc_rfr: | ||
328 | .word SDRC_RFR_CTRL_V | ||
329 | dlla_ctrl: | ||
330 | .word SDRC_DLLA_CTRL_V | ||
331 | |||
332 | ENTRY(sram_set_prcm_sz) | ||
333 | .word . - sram_set_prcm | ||
diff --git a/arch/arm/mach-omap2/timer-gp.c b/arch/arm/mach-omap2/timer-gp.c new file mode 100644 index 000000000000..9ec11443200f --- /dev/null +++ b/arch/arm/mach-omap2/timer-gp.c | |||
@@ -0,0 +1,126 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-omap2/timer-gp.c | ||
3 | * | ||
4 | * OMAP2 GP timer support. | ||
5 | * | ||
6 | * Copyright (C) 2005 Nokia Corporation | ||
7 | * Author: Paul Mundt <paul.mundt@nokia.com> | ||
8 | * Juha Yrjölä <juha.yrjola@nokia.com> | ||
9 | * | ||
10 | * Some parts based off of TI's 24xx code: | ||
11 | * | ||
12 | * Copyright (C) 2004 Texas Instruments, Inc. | ||
13 | * | ||
14 | * Roughly modelled after the OMAP1 MPU timer code. | ||
15 | * | ||
16 | * This file is subject to the terms and conditions of the GNU General Public | ||
17 | * License. See the file "COPYING" in the main directory of this archive | ||
18 | * for more details. | ||
19 | */ | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/time.h> | ||
22 | #include <linux/interrupt.h> | ||
23 | #include <linux/err.h> | ||
24 | #include <asm/mach/time.h> | ||
25 | #include <asm/delay.h> | ||
26 | #include <asm/io.h> | ||
27 | #include <asm/hardware/clock.h> | ||
28 | |||
29 | #define OMAP2_GP_TIMER1_BASE 0x48028000 | ||
30 | #define OMAP2_GP_TIMER2_BASE 0x4802a000 | ||
31 | #define OMAP2_GP_TIMER3_BASE 0x48078000 | ||
32 | #define OMAP2_GP_TIMER4_BASE 0x4807a000 | ||
33 | |||
34 | #define GP_TIMER_TIDR 0x00 | ||
35 | #define GP_TIMER_TISR 0x18 | ||
36 | #define GP_TIMER_TIER 0x1c | ||
37 | #define GP_TIMER_TCLR 0x24 | ||
38 | #define GP_TIMER_TCRR 0x28 | ||
39 | #define GP_TIMER_TLDR 0x2c | ||
40 | #define GP_TIMER_TSICR 0x40 | ||
41 | |||
42 | #define OS_TIMER_NR 1 /* GP timer 2 */ | ||
43 | |||
44 | static unsigned long timer_base[] = { | ||
45 | IO_ADDRESS(OMAP2_GP_TIMER1_BASE), | ||
46 | IO_ADDRESS(OMAP2_GP_TIMER2_BASE), | ||
47 | IO_ADDRESS(OMAP2_GP_TIMER3_BASE), | ||
48 | IO_ADDRESS(OMAP2_GP_TIMER4_BASE), | ||
49 | }; | ||
50 | |||
51 | static inline unsigned int timer_read_reg(int nr, unsigned int reg) | ||
52 | { | ||
53 | return __raw_readl(timer_base[nr] + reg); | ||
54 | } | ||
55 | |||
56 | static inline void timer_write_reg(int nr, unsigned int reg, unsigned int val) | ||
57 | { | ||
58 | __raw_writel(val, timer_base[nr] + reg); | ||
59 | } | ||
60 | |||
61 | /* Note that we always enable the clock prescale divider bit */ | ||
62 | static inline void omap2_gp_timer_start(int nr, unsigned long load_val) | ||
63 | { | ||
64 | unsigned int tmp; | ||
65 | |||
66 | tmp = 0xffffffff - load_val; | ||
67 | |||
68 | timer_write_reg(nr, GP_TIMER_TLDR, tmp); | ||
69 | timer_write_reg(nr, GP_TIMER_TCRR, tmp); | ||
70 | timer_write_reg(nr, GP_TIMER_TIER, 1 << 1); | ||
71 | timer_write_reg(nr, GP_TIMER_TCLR, (1 << 5) | (1 << 1) | 1); | ||
72 | } | ||
73 | |||
74 | static irqreturn_t omap2_gp_timer_interrupt(int irq, void *dev_id, | ||
75 | struct pt_regs *regs) | ||
76 | { | ||
77 | write_seqlock(&xtime_lock); | ||
78 | |||
79 | timer_write_reg(OS_TIMER_NR, GP_TIMER_TISR, 1 << 1); | ||
80 | timer_tick(regs); | ||
81 | |||
82 | write_sequnlock(&xtime_lock); | ||
83 | |||
84 | return IRQ_HANDLED; | ||
85 | } | ||
86 | |||
87 | static struct irqaction omap2_gp_timer_irq = { | ||
88 | .name = "gp timer", | ||
89 | .flags = SA_INTERRUPT, | ||
90 | .handler = omap2_gp_timer_interrupt, | ||
91 | }; | ||
92 | |||
93 | static void __init omap2_gp_timer_init(void) | ||
94 | { | ||
95 | struct clk * sys_ck; | ||
96 | u32 tick_period = 120000; | ||
97 | u32 l; | ||
98 | |||
99 | /* Reset clock and prescale value */ | ||
100 | timer_write_reg(OS_TIMER_NR, GP_TIMER_TCLR, 0); | ||
101 | |||
102 | sys_ck = clk_get(NULL, "sys_ck"); | ||
103 | if (IS_ERR(sys_ck)) | ||
104 | printk(KERN_ERR "Could not get sys_ck\n"); | ||
105 | else { | ||
106 | clk_use(sys_ck); | ||
107 | tick_period = clk_get_rate(sys_ck) / 100; | ||
108 | clk_put(sys_ck); | ||
109 | } | ||
110 | |||
111 | tick_period /= 2; /* Minimum prescale divider is 2 */ | ||
112 | tick_period -= 1; | ||
113 | |||
114 | l = timer_read_reg(OS_TIMER_NR, GP_TIMER_TIDR); | ||
115 | printk(KERN_INFO "OMAP2 GP timer (HW version %d.%d)\n", | ||
116 | (l >> 4) & 0x0f, l & 0x0f); | ||
117 | |||
118 | setup_irq(38, &omap2_gp_timer_irq); | ||
119 | |||
120 | omap2_gp_timer_start(OS_TIMER_NR, tick_period); | ||
121 | } | ||
122 | |||
123 | struct sys_timer omap_timer = { | ||
124 | .init = omap2_gp_timer_init, | ||
125 | }; | ||
126 | |||
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index b380a438e68f..e201aa9765b9 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig | |||
@@ -60,6 +60,7 @@ config MACH_CORGI | |||
60 | bool "Enable Sharp SL-C700 (Corgi) Support" | 60 | bool "Enable Sharp SL-C700 (Corgi) Support" |
61 | depends PXA_SHARPSL_25x | 61 | depends PXA_SHARPSL_25x |
62 | select PXA_SHARP_C7xx | 62 | select PXA_SHARP_C7xx |
63 | select PXA_SSP | ||
63 | 64 | ||
64 | config MACH_SHEPHERD | 65 | config MACH_SHEPHERD |
65 | bool "Enable Sharp SL-C750 (Shepherd) Support" | 66 | bool "Enable Sharp SL-C750 (Shepherd) Support" |
@@ -102,12 +103,18 @@ config IWMMXT | |||
102 | 103 | ||
103 | config PXA_SHARP_C7xx | 104 | config PXA_SHARP_C7xx |
104 | bool | 105 | bool |
106 | select PXA_SSP | ||
105 | help | 107 | help |
106 | Enable support for all Sharp C7xx models | 108 | Enable support for all Sharp C7xx models |
107 | 109 | ||
108 | config PXA_SHARP_Cxx00 | 110 | config PXA_SHARP_Cxx00 |
109 | bool | 111 | bool |
112 | select PXA_SSP | ||
110 | help | 113 | help |
111 | Enable common support for Sharp Cxx00 models | 114 | Enable common support for Sharp Cxx00 models |
112 | 115 | ||
116 | config PXA_SSP | ||
117 | tristate | ||
118 | help | ||
119 | Enable support for PXA2xx SSP ports | ||
113 | endif | 120 | endif |
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile index 8bc72d07cea8..d210bd5032ce 100644 --- a/arch/arm/mach-pxa/Makefile +++ b/arch/arm/mach-pxa/Makefile | |||
@@ -11,8 +11,8 @@ obj-$(CONFIG_PXA27x) += pxa27x.o | |||
11 | obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o | 11 | obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o |
12 | obj-$(CONFIG_MACH_MAINSTONE) += mainstone.o | 12 | obj-$(CONFIG_MACH_MAINSTONE) += mainstone.o |
13 | obj-$(CONFIG_ARCH_PXA_IDP) += idp.o | 13 | obj-$(CONFIG_ARCH_PXA_IDP) += idp.o |
14 | obj-$(CONFIG_PXA_SHARP_C7xx) += corgi.o corgi_ssp.o corgi_lcd.o ssp.o | 14 | obj-$(CONFIG_PXA_SHARP_C7xx) += corgi.o corgi_ssp.o corgi_lcd.o |
15 | obj-$(CONFIG_PXA_SHARP_Cxx00) += spitz.o corgi_ssp.o corgi_lcd.o ssp.o | 15 | obj-$(CONFIG_PXA_SHARP_Cxx00) += spitz.o corgi_ssp.o corgi_lcd.o |
16 | obj-$(CONFIG_MACH_POODLE) += poodle.o | 16 | obj-$(CONFIG_MACH_POODLE) += poodle.o |
17 | obj-$(CONFIG_MACH_TOSA) += tosa.o | 17 | obj-$(CONFIG_MACH_TOSA) += tosa.o |
18 | 18 | ||
@@ -26,6 +26,7 @@ obj-$(CONFIG_LEDS) += $(led-y) | |||
26 | 26 | ||
27 | # Misc features | 27 | # Misc features |
28 | obj-$(CONFIG_PM) += pm.o sleep.o | 28 | obj-$(CONFIG_PM) += pm.o sleep.o |
29 | obj-$(CONFIG_PXA_SSP) += ssp.o | ||
29 | 30 | ||
30 | ifeq ($(CONFIG_PXA27x),y) | 31 | ifeq ($(CONFIG_PXA27x),y) |
31 | obj-$(CONFIG_PM) += standby.o | 32 | obj-$(CONFIG_PM) += standby.o |
diff --git a/arch/arm/mach-pxa/corgi_ssp.c b/arch/arm/mach-pxa/corgi_ssp.c index 591e5f32dbec..bdf10cfa9440 100644 --- a/arch/arm/mach-pxa/corgi_ssp.c +++ b/arch/arm/mach-pxa/corgi_ssp.c | |||
@@ -203,7 +203,7 @@ static int __init corgi_ssp_probe(struct device *dev) | |||
203 | GPDR(ssp_machinfo->cs_ads7846) |= GPIO_bit(ssp_machinfo->cs_ads7846); /* output */ | 203 | GPDR(ssp_machinfo->cs_ads7846) |= GPIO_bit(ssp_machinfo->cs_ads7846); /* output */ |
204 | GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); /* High - Disable ADS7846*/ | 204 | GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); /* High - Disable ADS7846*/ |
205 | 205 | ||
206 | ret = ssp_init(&corgi_ssp_dev,ssp_machinfo->port); | 206 | ret = ssp_init(&corgi_ssp_dev, ssp_machinfo->port, 0); |
207 | 207 | ||
208 | if (ret) | 208 | if (ret) |
209 | printk(KERN_ERR "Unable to register SSP handler!\n"); | 209 | printk(KERN_ERR "Unable to register SSP handler!\n"); |
diff --git a/arch/arm/mach-pxa/sharpsl.h b/arch/arm/mach-pxa/sharpsl.h index 3977a77aacdd..4879c0f7da72 100644 --- a/arch/arm/mach-pxa/sharpsl.h +++ b/arch/arm/mach-pxa/sharpsl.h | |||
@@ -32,3 +32,90 @@ void corgi_put_hsync(void); | |||
32 | void spitz_put_hsync(void); | 32 | void spitz_put_hsync(void); |
33 | void corgi_wait_hsync(void); | 33 | void corgi_wait_hsync(void); |
34 | void spitz_wait_hsync(void); | 34 | void spitz_wait_hsync(void); |
35 | |||
36 | /* | ||
37 | * SharpSL Battery/PM Driver | ||
38 | */ | ||
39 | |||
40 | struct sharpsl_charger_machinfo { | ||
41 | void (*init)(void); | ||
42 | int gpio_acin; | ||
43 | int gpio_batfull; | ||
44 | int gpio_batlock; | ||
45 | int gpio_fatal; | ||
46 | int (*status_acin)(void); | ||
47 | void (*discharge)(int); | ||
48 | void (*discharge1)(int); | ||
49 | void (*charge)(int); | ||
50 | void (*chargeled)(int); | ||
51 | void (*measure_temp)(int); | ||
52 | void (*presuspend)(void); | ||
53 | void (*postsuspend)(void); | ||
54 | unsigned long (*charger_wakeup)(void); | ||
55 | int (*should_wakeup)(unsigned int resume_on_alarm); | ||
56 | int bat_levels; | ||
57 | struct battery_thresh *bat_levels_noac; | ||
58 | struct battery_thresh *bat_levels_acin; | ||
59 | int status_high_acin; | ||
60 | int status_low_acin; | ||
61 | int status_high_noac; | ||
62 | int status_low_noac; | ||
63 | }; | ||
64 | |||
65 | struct battery_thresh { | ||
66 | int voltage; | ||
67 | int percentage; | ||
68 | }; | ||
69 | |||
70 | struct battery_stat { | ||
71 | int ac_status; /* APM AC Present/Not Present */ | ||
72 | int mainbat_status; /* APM Main Battery Status */ | ||
73 | int mainbat_percent; /* Main Battery Percentage Charge */ | ||
74 | int mainbat_voltage; /* Main Battery Voltage */ | ||
75 | }; | ||
76 | |||
77 | struct sharpsl_pm_status { | ||
78 | struct device *dev; | ||
79 | struct timer_list ac_timer; | ||
80 | struct timer_list chrg_full_timer; | ||
81 | |||
82 | int charge_mode; | ||
83 | #define CHRG_ERROR (-1) | ||
84 | #define CHRG_OFF (0) | ||
85 | #define CHRG_ON (1) | ||
86 | #define CHRG_DONE (2) | ||
87 | |||
88 | unsigned int flags; | ||
89 | #define SHARPSL_SUSPENDED (1 << 0) /* Device is Suspended */ | ||
90 | #define SHARPSL_ALARM_ACTIVE (1 << 1) /* Alarm is for charging event (not user) */ | ||
91 | #define SHARPSL_BL_LIMIT (1 << 2) /* Backlight Intensity Limited */ | ||
92 | #define SHARPSL_APM_QUEUED (1 << 3) /* APM Event Queued */ | ||
93 | #define SHARPSL_DO_OFFLINE_CHRG (1 << 4) /* Trigger the offline charger */ | ||
94 | |||
95 | int full_count; | ||
96 | unsigned long charge_start_time; | ||
97 | struct sharpsl_charger_machinfo *machinfo; | ||
98 | struct battery_stat battstat; | ||
99 | }; | ||
100 | |||
101 | extern struct sharpsl_pm_status sharpsl_pm; | ||
102 | extern struct battery_thresh spitz_battery_levels_acin[]; | ||
103 | extern struct battery_thresh spitz_battery_levels_noac[]; | ||
104 | |||
105 | #define READ_GPIO_BIT(x) (GPLR(x) & GPIO_bit(x)) | ||
106 | |||
107 | #define SHARPSL_LED_ERROR 2 | ||
108 | #define SHARPSL_LED_ON 1 | ||
109 | #define SHARPSL_LED_OFF 0 | ||
110 | |||
111 | #define CHARGE_ON() sharpsl_pm.machinfo->charge(1) | ||
112 | #define CHARGE_OFF() sharpsl_pm.machinfo->charge(0) | ||
113 | #define CHARGE_LED_ON() sharpsl_pm.machinfo->chargeled(SHARPSL_LED_ON) | ||
114 | #define CHARGE_LED_OFF() sharpsl_pm.machinfo->chargeled(SHARPSL_LED_OFF) | ||
115 | #define CHARGE_LED_ERR() sharpsl_pm.machinfo->chargeled(SHARPSL_LED_ERROR) | ||
116 | #define DISCHARGE_ON() sharpsl_pm.machinfo->discharge(1) | ||
117 | #define DISCHARGE_OFF() sharpsl_pm.machinfo->discharge(0) | ||
118 | #define STATUS_AC_IN sharpsl_pm.machinfo->status_acin() | ||
119 | #define STATUS_BATT_LOCKED READ_GPIO_BIT(sharpsl_pm.machinfo->gpio_batlock) | ||
120 | #define STATUS_CHRG_FULL READ_GPIO_BIT(sharpsl_pm.machinfo->gpio_batfull) | ||
121 | #define STATUS_FATAL READ_GPIO_BIT(sharpsl_pm.machinfo->gpio_fatal) | ||
diff --git a/arch/arm/mach-pxa/sharpsl_pm.c b/arch/arm/mach-pxa/sharpsl_pm.c new file mode 100644 index 000000000000..6c9e871c53d8 --- /dev/null +++ b/arch/arm/mach-pxa/sharpsl_pm.c | |||
@@ -0,0 +1,992 @@ | |||
1 | /* | ||
2 | * Battery and Power Management code for the Sharp SL-C7xx and SL-Cxx00 | ||
3 | * series of PDAs | ||
4 | * | ||
5 | * Copyright (c) 2004-2005 Richard Purdie | ||
6 | * | ||
7 | * Based on code written by Sharp for 2.4 kernels | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #undef DEBUG | ||
16 | |||
17 | #include <linux/module.h> | ||
18 | #include <linux/timer.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/apm_bios.h> | ||
22 | #include <linux/delay.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/device.h> | ||
25 | |||
26 | #include <asm/hardware.h> | ||
27 | #include <asm/hardware/scoop.h> | ||
28 | #include <asm/mach-types.h> | ||
29 | #include <asm/irq.h> | ||
30 | #include <asm/apm.h> | ||
31 | |||
32 | #include <asm/arch/pm.h> | ||
33 | #include <asm/arch/pxa-regs.h> | ||
34 | #include <asm/arch/sharpsl.h> | ||
35 | #include "sharpsl.h" | ||
36 | |||
37 | /* | ||
38 | * Constants | ||
39 | */ | ||
40 | #define SHARPSL_CHARGE_ON_TIME_INTERVAL (msecs_to_jiffies(1*60*1000)) /* 1 min */ | ||
41 | #define SHARPSL_CHARGE_FINISH_TIME (msecs_to_jiffies(10*60*1000)) /* 10 min */ | ||
42 | #define SHARPSL_BATCHK_TIME (msecs_to_jiffies(15*1000)) /* 15 sec */ | ||
43 | #define SHARPSL_BATCHK_TIME_SUSPEND (60*10) /* 10 min */ | ||
44 | #define SHARPSL_WAIT_CO_TIME 15 /* 15 sec */ | ||
45 | #define SHARPSL_WAIT_DISCHARGE_ON 100 /* 100 msec */ | ||
46 | #define SHARPSL_CHECK_BATTERY_WAIT_TIME_TEMP 10 /* 10 msec */ | ||
47 | #define SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT 10 /* 10 msec */ | ||
48 | #define SHARPSL_CHECK_BATTERY_WAIT_TIME_JKVAD 10 /* 10 msec */ | ||
49 | #define SHARPSL_CHARGE_WAIT_TIME 15 /* 15 msec */ | ||
50 | #define SHARPSL_CHARGE_CO_CHECK_TIME 5 /* 5 msec */ | ||
51 | #define SHARPSL_CHARGE_RETRY_CNT 1 /* eqv. 10 min */ | ||
52 | |||
53 | #define SHARPSL_CHARGE_ON_VOLT 0x99 /* 2.9V */ | ||
54 | #define SHARPSL_CHARGE_ON_TEMP 0xe0 /* 2.9V */ | ||
55 | #define SHARPSL_CHARGE_ON_JKVAD_HIGH 0x9b /* 6V */ | ||
56 | #define SHARPSL_CHARGE_ON_JKVAD_LOW 0x34 /* 2V */ | ||
57 | #define SHARPSL_FATAL_ACIN_VOLT 182 /* 3.45V */ | ||
58 | #define SHARPSL_FATAL_NOACIN_VOLT 170 /* 3.40V */ | ||
59 | |||
60 | struct battery_thresh spitz_battery_levels_acin[] = { | ||
61 | { 213, 100}, | ||
62 | { 212, 98}, | ||
63 | { 211, 95}, | ||
64 | { 210, 93}, | ||
65 | { 209, 90}, | ||
66 | { 208, 88}, | ||
67 | { 207, 85}, | ||
68 | { 206, 83}, | ||
69 | { 205, 80}, | ||
70 | { 204, 78}, | ||
71 | { 203, 75}, | ||
72 | { 202, 73}, | ||
73 | { 201, 70}, | ||
74 | { 200, 68}, | ||
75 | { 199, 65}, | ||
76 | { 198, 63}, | ||
77 | { 197, 60}, | ||
78 | { 196, 58}, | ||
79 | { 195, 55}, | ||
80 | { 194, 53}, | ||
81 | { 193, 50}, | ||
82 | { 192, 48}, | ||
83 | { 192, 45}, | ||
84 | { 191, 43}, | ||
85 | { 191, 40}, | ||
86 | { 190, 38}, | ||
87 | { 190, 35}, | ||
88 | { 189, 33}, | ||
89 | { 188, 30}, | ||
90 | { 187, 28}, | ||
91 | { 186, 25}, | ||
92 | { 185, 23}, | ||
93 | { 184, 20}, | ||
94 | { 183, 18}, | ||
95 | { 182, 15}, | ||
96 | { 181, 13}, | ||
97 | { 180, 10}, | ||
98 | { 179, 8}, | ||
99 | { 178, 5}, | ||
100 | { 0, 0}, | ||
101 | }; | ||
102 | |||
103 | struct battery_thresh spitz_battery_levels_noac[] = { | ||
104 | { 213, 100}, | ||
105 | { 212, 98}, | ||
106 | { 211, 95}, | ||
107 | { 210, 93}, | ||
108 | { 209, 90}, | ||
109 | { 208, 88}, | ||
110 | { 207, 85}, | ||
111 | { 206, 83}, | ||
112 | { 205, 80}, | ||
113 | { 204, 78}, | ||
114 | { 203, 75}, | ||
115 | { 202, 73}, | ||
116 | { 201, 70}, | ||
117 | { 200, 68}, | ||
118 | { 199, 65}, | ||
119 | { 198, 63}, | ||
120 | { 197, 60}, | ||
121 | { 196, 58}, | ||
122 | { 195, 55}, | ||
123 | { 194, 53}, | ||
124 | { 193, 50}, | ||
125 | { 192, 48}, | ||
126 | { 191, 45}, | ||
127 | { 190, 43}, | ||
128 | { 189, 40}, | ||
129 | { 188, 38}, | ||
130 | { 187, 35}, | ||
131 | { 186, 33}, | ||
132 | { 185, 30}, | ||
133 | { 184, 28}, | ||
134 | { 183, 25}, | ||
135 | { 182, 23}, | ||
136 | { 181, 20}, | ||
137 | { 180, 18}, | ||
138 | { 179, 15}, | ||
139 | { 178, 13}, | ||
140 | { 177, 10}, | ||
141 | { 176, 8}, | ||
142 | { 175, 5}, | ||
143 | { 0, 0}, | ||
144 | }; | ||
145 | |||
146 | /* MAX1111 Commands */ | ||
147 | #define MAXCTRL_PD0 1u << 0 | ||
148 | #define MAXCTRL_PD1 1u << 1 | ||
149 | #define MAXCTRL_SGL 1u << 2 | ||
150 | #define MAXCTRL_UNI 1u << 3 | ||
151 | #define MAXCTRL_SEL_SH 4 | ||
152 | #define MAXCTRL_STR 1u << 7 | ||
153 | |||
154 | /* MAX1111 Channel Definitions */ | ||
155 | #define BATT_AD 4u | ||
156 | #define BATT_THM 2u | ||
157 | #define JK_VAD 6u | ||
158 | |||
159 | |||
160 | /* | ||
161 | * Prototypes | ||
162 | */ | ||
163 | static int sharpsl_read_MainBattery(void); | ||
164 | static int sharpsl_off_charge_battery(void); | ||
165 | static int sharpsl_check_battery(int mode); | ||
166 | static int sharpsl_ac_check(void); | ||
167 | static int sharpsl_fatal_check(void); | ||
168 | static int sharpsl_average_value(int ad); | ||
169 | static void sharpsl_average_clear(void); | ||
170 | static void sharpsl_charge_toggle(void *private_); | ||
171 | static void sharpsl_battery_thread(void *private_); | ||
172 | |||
173 | |||
174 | /* | ||
175 | * Variables | ||
176 | */ | ||
177 | struct sharpsl_pm_status sharpsl_pm; | ||
178 | DECLARE_WORK(toggle_charger, sharpsl_charge_toggle, NULL); | ||
179 | DECLARE_WORK(sharpsl_bat, sharpsl_battery_thread, NULL); | ||
180 | |||
181 | |||
182 | static int get_percentage(int voltage) | ||
183 | { | ||
184 | int i = sharpsl_pm.machinfo->bat_levels - 1; | ||
185 | struct battery_thresh *thresh; | ||
186 | |||
187 | if (sharpsl_pm.charge_mode == CHRG_ON) | ||
188 | thresh=sharpsl_pm.machinfo->bat_levels_acin; | ||
189 | else | ||
190 | thresh=sharpsl_pm.machinfo->bat_levels_noac; | ||
191 | |||
192 | while (i > 0 && (voltage > thresh[i].voltage)) | ||
193 | i--; | ||
194 | |||
195 | return thresh[i].percentage; | ||
196 | } | ||
197 | |||
198 | static int get_apm_status(int voltage) | ||
199 | { | ||
200 | int low_thresh, high_thresh; | ||
201 | |||
202 | if (sharpsl_pm.charge_mode == CHRG_ON) { | ||
203 | high_thresh = sharpsl_pm.machinfo->status_high_acin; | ||
204 | low_thresh = sharpsl_pm.machinfo->status_low_acin; | ||
205 | } else { | ||
206 | high_thresh = sharpsl_pm.machinfo->status_high_noac; | ||
207 | low_thresh = sharpsl_pm.machinfo->status_low_noac; | ||
208 | } | ||
209 | |||
210 | if (voltage >= high_thresh) | ||
211 | return APM_BATTERY_STATUS_HIGH; | ||
212 | if (voltage >= low_thresh) | ||
213 | return APM_BATTERY_STATUS_LOW; | ||
214 | return APM_BATTERY_STATUS_CRITICAL; | ||
215 | } | ||
216 | |||
217 | void sharpsl_battery_kick(void) | ||
218 | { | ||
219 | schedule_delayed_work(&sharpsl_bat, msecs_to_jiffies(125)); | ||
220 | } | ||
221 | EXPORT_SYMBOL(sharpsl_battery_kick); | ||
222 | |||
223 | |||
224 | static void sharpsl_battery_thread(void *private_) | ||
225 | { | ||
226 | int voltage, percent, apm_status, i = 0; | ||
227 | |||
228 | if (!sharpsl_pm.machinfo) | ||
229 | return; | ||
230 | |||
231 | sharpsl_pm.battstat.ac_status = (!(STATUS_AC_IN) ? APM_AC_OFFLINE : APM_AC_ONLINE); | ||
232 | |||
233 | /* Corgi cannot confirm when battery fully charged so periodically kick! */ | ||
234 | if (machine_is_corgi() && (sharpsl_pm.charge_mode == CHRG_ON) | ||
235 | && time_after(jiffies, sharpsl_pm.charge_start_time + SHARPSL_CHARGE_ON_TIME_INTERVAL)) | ||
236 | schedule_work(&toggle_charger); | ||
237 | |||
238 | while(1) { | ||
239 | voltage = sharpsl_read_MainBattery(); | ||
240 | if (voltage > 0) break; | ||
241 | if (i++ > 5) { | ||
242 | voltage = sharpsl_pm.machinfo->bat_levels_noac[0].voltage; | ||
243 | dev_warn(sharpsl_pm.dev, "Warning: Cannot read main battery!\n"); | ||
244 | break; | ||
245 | } | ||
246 | } | ||
247 | |||
248 | voltage = sharpsl_average_value(voltage); | ||
249 | apm_status = get_apm_status(voltage); | ||
250 | percent = get_percentage(voltage); | ||
251 | |||
252 | /* At low battery voltages, the voltage has a tendency to start | ||
253 | creeping back up so we try to avoid this here */ | ||
254 | if ((sharpsl_pm.battstat.ac_status == APM_AC_ONLINE) || (apm_status == APM_BATTERY_STATUS_HIGH) || percent <= sharpsl_pm.battstat.mainbat_percent) { | ||
255 | sharpsl_pm.battstat.mainbat_voltage = voltage; | ||
256 | sharpsl_pm.battstat.mainbat_status = apm_status; | ||
257 | sharpsl_pm.battstat.mainbat_percent = percent; | ||
258 | } | ||
259 | |||
260 | dev_dbg(sharpsl_pm.dev, "Battery: voltage: %d, status: %d, percentage: %d, time: %d\n", voltage, | ||
261 | sharpsl_pm.battstat.mainbat_status, sharpsl_pm.battstat.mainbat_percent, jiffies); | ||
262 | |||
263 | /* If battery is low. limit backlight intensity to save power. */ | ||
264 | if ((sharpsl_pm.battstat.ac_status != APM_AC_ONLINE) | ||
265 | && ((sharpsl_pm.battstat.mainbat_status == APM_BATTERY_STATUS_LOW) || | ||
266 | (sharpsl_pm.battstat.mainbat_status == APM_BATTERY_STATUS_CRITICAL))) { | ||
267 | if (!(sharpsl_pm.flags & SHARPSL_BL_LIMIT)) { | ||
268 | corgibl_limit_intensity(1); | ||
269 | sharpsl_pm.flags |= SHARPSL_BL_LIMIT; | ||
270 | } | ||
271 | } else if (sharpsl_pm.flags & SHARPSL_BL_LIMIT) { | ||
272 | corgibl_limit_intensity(0); | ||
273 | sharpsl_pm.flags &= ~SHARPSL_BL_LIMIT; | ||
274 | } | ||
275 | |||
276 | /* Suspend if critical battery level */ | ||
277 | if ((sharpsl_pm.battstat.ac_status != APM_AC_ONLINE) | ||
278 | && (sharpsl_pm.battstat.mainbat_status == APM_BATTERY_STATUS_CRITICAL) | ||
279 | && !(sharpsl_pm.flags & SHARPSL_APM_QUEUED)) { | ||
280 | sharpsl_pm.flags |= SHARPSL_APM_QUEUED; | ||
281 | dev_err(sharpsl_pm.dev, "Fatal Off\n"); | ||
282 | apm_queue_event(APM_CRITICAL_SUSPEND); | ||
283 | } | ||
284 | |||
285 | schedule_delayed_work(&sharpsl_bat, SHARPSL_BATCHK_TIME); | ||
286 | } | ||
287 | |||
288 | static void sharpsl_charge_on(void) | ||
289 | { | ||
290 | dev_dbg(sharpsl_pm.dev, "Turning Charger On\n"); | ||
291 | |||
292 | sharpsl_pm.full_count = 0; | ||
293 | sharpsl_pm.charge_mode = CHRG_ON; | ||
294 | schedule_delayed_work(&toggle_charger, msecs_to_jiffies(250)); | ||
295 | schedule_delayed_work(&sharpsl_bat, msecs_to_jiffies(500)); | ||
296 | } | ||
297 | |||
298 | static void sharpsl_charge_off(void) | ||
299 | { | ||
300 | dev_dbg(sharpsl_pm.dev, "Turning Charger Off\n"); | ||
301 | |||
302 | CHARGE_OFF(); | ||
303 | CHARGE_LED_OFF(); | ||
304 | sharpsl_pm.charge_mode = CHRG_OFF; | ||
305 | |||
306 | schedule_work(&sharpsl_bat); | ||
307 | } | ||
308 | |||
309 | static void sharpsl_charge_error(void) | ||
310 | { | ||
311 | CHARGE_LED_ERR(); | ||
312 | CHARGE_OFF(); | ||
313 | sharpsl_pm.charge_mode = CHRG_ERROR; | ||
314 | } | ||
315 | |||
316 | static void sharpsl_charge_toggle(void *private_) | ||
317 | { | ||
318 | dev_dbg(sharpsl_pm.dev, "Toogling Charger at time: %lx\n", jiffies); | ||
319 | |||
320 | if (STATUS_AC_IN == 0) { | ||
321 | sharpsl_charge_off(); | ||
322 | return; | ||
323 | } else if ((sharpsl_check_battery(1) < 0) || (sharpsl_ac_check() < 0)) { | ||
324 | sharpsl_charge_error(); | ||
325 | return; | ||
326 | } | ||
327 | |||
328 | CHARGE_LED_ON(); | ||
329 | CHARGE_OFF(); | ||
330 | mdelay(SHARPSL_CHARGE_WAIT_TIME); | ||
331 | CHARGE_ON(); | ||
332 | |||
333 | sharpsl_pm.charge_start_time = jiffies; | ||
334 | } | ||
335 | |||
336 | static void sharpsl_ac_timer(unsigned long data) | ||
337 | { | ||
338 | int acin = STATUS_AC_IN; | ||
339 | |||
340 | dev_dbg(sharpsl_pm.dev, "AC Status: %d\n",acin); | ||
341 | |||
342 | sharpsl_average_clear(); | ||
343 | if (acin && (sharpsl_pm.charge_mode != CHRG_ON)) | ||
344 | sharpsl_charge_on(); | ||
345 | else if (sharpsl_pm.charge_mode == CHRG_ON) | ||
346 | sharpsl_charge_off(); | ||
347 | |||
348 | schedule_work(&sharpsl_bat); | ||
349 | } | ||
350 | |||
351 | |||
352 | static irqreturn_t sharpsl_ac_isr(int irq, void *dev_id, struct pt_regs *fp) | ||
353 | { | ||
354 | /* Delay the event slightly to debounce */ | ||
355 | /* Must be a smaller delay than the chrg_full_isr below */ | ||
356 | mod_timer(&sharpsl_pm.ac_timer, jiffies + msecs_to_jiffies(250)); | ||
357 | |||
358 | return IRQ_HANDLED; | ||
359 | } | ||
360 | |||
361 | static void sharpsl_chrg_full_timer(unsigned long data) | ||
362 | { | ||
363 | dev_dbg(sharpsl_pm.dev, "Charge Full at time: %lx\n", jiffies); | ||
364 | |||
365 | sharpsl_pm.full_count++; | ||
366 | |||
367 | if (STATUS_AC_IN == 0) { | ||
368 | dev_dbg(sharpsl_pm.dev, "Charge Full: AC removed - stop charging!\n"); | ||
369 | if (sharpsl_pm.charge_mode == CHRG_ON) | ||
370 | sharpsl_charge_off(); | ||
371 | } else if (sharpsl_pm.full_count < 2) { | ||
372 | dev_dbg(sharpsl_pm.dev, "Charge Full: Count too low\n"); | ||
373 | schedule_work(&toggle_charger); | ||
374 | } else if (time_after(jiffies, sharpsl_pm.charge_start_time + SHARPSL_CHARGE_FINISH_TIME)) { | ||
375 | dev_dbg(sharpsl_pm.dev, "Charge Full: Interrupt generated too slowly - retry.\n"); | ||
376 | schedule_work(&toggle_charger); | ||
377 | } else { | ||
378 | sharpsl_charge_off(); | ||
379 | sharpsl_pm.charge_mode = CHRG_DONE; | ||
380 | dev_dbg(sharpsl_pm.dev, "Charge Full: Charging Finished\n"); | ||
381 | } | ||
382 | } | ||
383 | |||
384 | /* Charging Finished Interrupt (Not present on Corgi) */ | ||
385 | /* Can trigger at the same time as an AC staus change so | ||
386 | delay until after that has been processed */ | ||
387 | static irqreturn_t sharpsl_chrg_full_isr(int irq, void *dev_id, struct pt_regs *fp) | ||
388 | { | ||
389 | if (sharpsl_pm.flags & SHARPSL_SUSPENDED) | ||
390 | return IRQ_HANDLED; | ||
391 | |||
392 | /* delay until after any ac interrupt */ | ||
393 | mod_timer(&sharpsl_pm.chrg_full_timer, jiffies + msecs_to_jiffies(500)); | ||
394 | |||
395 | return IRQ_HANDLED; | ||
396 | } | ||
397 | |||
398 | static irqreturn_t sharpsl_fatal_isr(int irq, void *dev_id, struct pt_regs *fp) | ||
399 | { | ||
400 | int is_fatal = 0; | ||
401 | |||
402 | if (STATUS_BATT_LOCKED == 0) { | ||
403 | dev_err(sharpsl_pm.dev, "Battery now Unlocked! Suspending.\n"); | ||
404 | is_fatal = 1; | ||
405 | } | ||
406 | |||
407 | if (sharpsl_pm.machinfo->gpio_fatal && (STATUS_FATAL == 0)) { | ||
408 | dev_err(sharpsl_pm.dev, "Fatal Batt Error! Suspending.\n"); | ||
409 | is_fatal = 1; | ||
410 | } | ||
411 | |||
412 | if (!(sharpsl_pm.flags & SHARPSL_APM_QUEUED) && is_fatal) { | ||
413 | sharpsl_pm.flags |= SHARPSL_APM_QUEUED; | ||
414 | apm_queue_event(APM_CRITICAL_SUSPEND); | ||
415 | } | ||
416 | |||
417 | return IRQ_HANDLED; | ||
418 | } | ||
419 | |||
420 | /* | ||
421 | * Maintain an average of the last 10 readings | ||
422 | */ | ||
423 | #define SHARPSL_CNV_VALUE_NUM 10 | ||
424 | static int sharpsl_ad_index; | ||
425 | |||
426 | static void sharpsl_average_clear(void) | ||
427 | { | ||
428 | sharpsl_ad_index = 0; | ||
429 | } | ||
430 | |||
431 | static int sharpsl_average_value(int ad) | ||
432 | { | ||
433 | int i, ad_val = 0; | ||
434 | static int sharpsl_ad[SHARPSL_CNV_VALUE_NUM+1]; | ||
435 | |||
436 | if (sharpsl_pm.battstat.mainbat_status != APM_BATTERY_STATUS_HIGH) { | ||
437 | sharpsl_ad_index = 0; | ||
438 | return ad; | ||
439 | } | ||
440 | |||
441 | sharpsl_ad[sharpsl_ad_index] = ad; | ||
442 | sharpsl_ad_index++; | ||
443 | if (sharpsl_ad_index >= SHARPSL_CNV_VALUE_NUM) { | ||
444 | for (i=0; i < (SHARPSL_CNV_VALUE_NUM-1); i++) | ||
445 | sharpsl_ad[i] = sharpsl_ad[i+1]; | ||
446 | sharpsl_ad_index = SHARPSL_CNV_VALUE_NUM - 1; | ||
447 | } | ||
448 | for (i=0; i < sharpsl_ad_index; i++) | ||
449 | ad_val += sharpsl_ad[i]; | ||
450 | |||
451 | return (ad_val / sharpsl_ad_index); | ||
452 | } | ||
453 | |||
454 | |||
455 | /* | ||
456 | * Read MAX1111 ADC | ||
457 | */ | ||
458 | static int read_max1111(int channel) | ||
459 | { | ||
460 | return corgi_ssp_max1111_get((channel << MAXCTRL_SEL_SH) | MAXCTRL_PD0 | MAXCTRL_PD1 | ||
461 | | MAXCTRL_SGL | MAXCTRL_UNI | MAXCTRL_STR); | ||
462 | } | ||
463 | |||
464 | static int sharpsl_read_MainBattery(void) | ||
465 | { | ||
466 | return read_max1111(BATT_AD); | ||
467 | } | ||
468 | |||
469 | static int sharpsl_read_Temp(void) | ||
470 | { | ||
471 | int temp; | ||
472 | |||
473 | sharpsl_pm.machinfo->measure_temp(1); | ||
474 | |||
475 | mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_TEMP); | ||
476 | temp = read_max1111(BATT_THM); | ||
477 | |||
478 | sharpsl_pm.machinfo->measure_temp(0); | ||
479 | |||
480 | return temp; | ||
481 | } | ||
482 | |||
483 | static int sharpsl_read_jkvad(void) | ||
484 | { | ||
485 | return read_max1111(JK_VAD); | ||
486 | } | ||
487 | |||
488 | /* | ||
489 | * Take an array of 5 integers, remove the maximum and minimum values | ||
490 | * and return the average. | ||
491 | */ | ||
492 | static int get_select_val(int *val) | ||
493 | { | ||
494 | int i, j, k, temp, sum = 0; | ||
495 | |||
496 | /* Find MAX val */ | ||
497 | temp = val[0]; | ||
498 | j=0; | ||
499 | for (i=1; i<5; i++) { | ||
500 | if (temp < val[i]) { | ||
501 | temp = val[i]; | ||
502 | j = i; | ||
503 | } | ||
504 | } | ||
505 | |||
506 | /* Find MIN val */ | ||
507 | temp = val[4]; | ||
508 | k=4; | ||
509 | for (i=3; i>=0; i--) { | ||
510 | if (temp > val[i]) { | ||
511 | temp = val[i]; | ||
512 | k = i; | ||
513 | } | ||
514 | } | ||
515 | |||
516 | for (i=0; i<5; i++) | ||
517 | if (i != j && i != k ) | ||
518 | sum += val[i]; | ||
519 | |||
520 | dev_dbg(sharpsl_pm.dev, "Average: %d from values: %d, %d, %d, %d, %d\n", sum/3, val[0], val[1], val[2], val[3], val[4]); | ||
521 | |||
522 | return (sum/3); | ||
523 | } | ||
524 | |||
525 | /* mode 0 - Check temperature and voltage | ||
526 | * 1 - Check temperature only */ | ||
527 | static int sharpsl_check_battery(int mode) | ||
528 | { | ||
529 | int val, i, buff[5]; | ||
530 | |||
531 | /* Check battery temperature */ | ||
532 | for (i=0; i<5; i++) { | ||
533 | mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_TEMP); | ||
534 | buff[i] = sharpsl_read_Temp(); | ||
535 | } | ||
536 | |||
537 | val = get_select_val(buff); | ||
538 | |||
539 | dev_dbg(sharpsl_pm.dev, "Temperature: %d\n", val); | ||
540 | if (val > SHARPSL_CHARGE_ON_TEMP) | ||
541 | return -1; | ||
542 | if (mode == 1) | ||
543 | return 0; | ||
544 | |||
545 | /* disable charge, enable discharge */ | ||
546 | CHARGE_OFF(); | ||
547 | DISCHARGE_ON(); | ||
548 | mdelay(SHARPSL_WAIT_DISCHARGE_ON); | ||
549 | |||
550 | if (sharpsl_pm.machinfo->discharge1) | ||
551 | sharpsl_pm.machinfo->discharge1(1); | ||
552 | |||
553 | /* Check battery voltage */ | ||
554 | for (i=0; i<5; i++) { | ||
555 | buff[i] = sharpsl_read_MainBattery(); | ||
556 | mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT); | ||
557 | } | ||
558 | |||
559 | if (sharpsl_pm.machinfo->discharge1) | ||
560 | sharpsl_pm.machinfo->discharge1(0); | ||
561 | |||
562 | DISCHARGE_OFF(); | ||
563 | |||
564 | val = get_select_val(buff); | ||
565 | dev_dbg(sharpsl_pm.dev, "Battery Voltage: %d\n", val); | ||
566 | |||
567 | if (val < SHARPSL_CHARGE_ON_VOLT) | ||
568 | return -1; | ||
569 | |||
570 | return 0; | ||
571 | } | ||
572 | |||
573 | static int sharpsl_ac_check(void) | ||
574 | { | ||
575 | int temp, i, buff[5]; | ||
576 | |||
577 | for (i=0; i<5; i++) { | ||
578 | buff[i] = sharpsl_read_jkvad(); | ||
579 | mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_JKVAD); | ||
580 | } | ||
581 | |||
582 | temp = get_select_val(buff); | ||
583 | dev_dbg(sharpsl_pm.dev, "AC Voltage: %d\n",temp); | ||
584 | |||
585 | if ((temp > SHARPSL_CHARGE_ON_JKVAD_HIGH) || (temp < SHARPSL_CHARGE_ON_JKVAD_LOW)) { | ||
586 | dev_err(sharpsl_pm.dev, "Error: AC check failed.\n"); | ||
587 | return -1; | ||
588 | } | ||
589 | |||
590 | return 0; | ||
591 | } | ||
592 | |||
593 | #ifdef CONFIG_PM | ||
594 | static int sharpsl_pm_suspend(struct device *dev, pm_message_t state) | ||
595 | { | ||
596 | sharpsl_pm.flags |= SHARPSL_SUSPENDED; | ||
597 | flush_scheduled_work(); | ||
598 | |||
599 | if (sharpsl_pm.charge_mode == CHRG_ON) | ||
600 | sharpsl_pm.flags |= SHARPSL_DO_OFFLINE_CHRG; | ||
601 | else | ||
602 | sharpsl_pm.flags &= ~SHARPSL_DO_OFFLINE_CHRG; | ||
603 | |||
604 | return 0; | ||
605 | } | ||
606 | |||
607 | static int sharpsl_pm_resume(struct device *dev) | ||
608 | { | ||
609 | /* Clear the reset source indicators as they break the bootloader upon reboot */ | ||
610 | RCSR = 0x0f; | ||
611 | sharpsl_average_clear(); | ||
612 | sharpsl_pm.flags &= ~SHARPSL_APM_QUEUED; | ||
613 | sharpsl_pm.flags &= ~SHARPSL_SUSPENDED; | ||
614 | |||
615 | return 0; | ||
616 | } | ||
617 | |||
618 | static void corgi_goto_sleep(unsigned long alarm_time, unsigned int alarm_enable, suspend_state_t state) | ||
619 | { | ||
620 | dev_dbg(sharpsl_pm.dev, "Time is: %08x\n",RCNR); | ||
621 | |||
622 | dev_dbg(sharpsl_pm.dev, "Offline Charge Activate = %d\n",sharpsl_pm.flags & SHARPSL_DO_OFFLINE_CHRG); | ||
623 | /* not charging and AC-IN! */ | ||
624 | |||
625 | if ((sharpsl_pm.flags & SHARPSL_DO_OFFLINE_CHRG) && (STATUS_AC_IN != 0)) { | ||
626 | dev_dbg(sharpsl_pm.dev, "Activating Offline Charger...\n"); | ||
627 | sharpsl_pm.charge_mode = CHRG_OFF; | ||
628 | sharpsl_pm.flags &= ~SHARPSL_DO_OFFLINE_CHRG; | ||
629 | sharpsl_off_charge_battery(); | ||
630 | } | ||
631 | |||
632 | sharpsl_pm.machinfo->presuspend(); | ||
633 | |||
634 | PEDR = 0xffffffff; /* clear it */ | ||
635 | |||
636 | sharpsl_pm.flags &= ~SHARPSL_ALARM_ACTIVE; | ||
637 | if ((sharpsl_pm.charge_mode == CHRG_ON) && ((alarm_enable && ((alarm_time - RCNR) > (SHARPSL_BATCHK_TIME_SUSPEND + 30))) || !alarm_enable)) { | ||
638 | RTSR &= RTSR_ALE; | ||
639 | RTAR = RCNR + SHARPSL_BATCHK_TIME_SUSPEND; | ||
640 | dev_dbg(sharpsl_pm.dev, "Charging alarm at: %08x\n",RTAR); | ||
641 | sharpsl_pm.flags |= SHARPSL_ALARM_ACTIVE; | ||
642 | } else if (alarm_enable) { | ||
643 | RTSR &= RTSR_ALE; | ||
644 | RTAR = alarm_time; | ||
645 | dev_dbg(sharpsl_pm.dev, "User alarm at: %08x\n",RTAR); | ||
646 | } else { | ||
647 | dev_dbg(sharpsl_pm.dev, "No alarms set.\n"); | ||
648 | } | ||
649 | |||
650 | pxa_pm_enter(state); | ||
651 | |||
652 | sharpsl_pm.machinfo->postsuspend(); | ||
653 | |||
654 | dev_dbg(sharpsl_pm.dev, "Corgi woken up from suspend: %08x\n",PEDR); | ||
655 | } | ||
656 | |||
657 | static int corgi_enter_suspend(unsigned long alarm_time, unsigned int alarm_enable, suspend_state_t state) | ||
658 | { | ||
659 | if (!sharpsl_pm.machinfo->should_wakeup(!(sharpsl_pm.flags & SHARPSL_ALARM_ACTIVE) && alarm_enable) ) | ||
660 | { | ||
661 | if (!(sharpsl_pm.flags & SHARPSL_ALARM_ACTIVE)) { | ||
662 | dev_dbg(sharpsl_pm.dev, "No user triggered wakeup events and not charging. Strange. Suspend.\n"); | ||
663 | corgi_goto_sleep(alarm_time, alarm_enable, state); | ||
664 | return 1; | ||
665 | } | ||
666 | if(sharpsl_off_charge_battery()) { | ||
667 | dev_dbg(sharpsl_pm.dev, "Charging. Suspend...\n"); | ||
668 | corgi_goto_sleep(alarm_time, alarm_enable, state); | ||
669 | return 1; | ||
670 | } | ||
671 | dev_dbg(sharpsl_pm.dev, "User triggered wakeup in offline charger.\n"); | ||
672 | } | ||
673 | |||
674 | if ((STATUS_BATT_LOCKED == 0) || (sharpsl_fatal_check() < 0) ) | ||
675 | { | ||
676 | dev_err(sharpsl_pm.dev, "Fatal condition. Suspend.\n"); | ||
677 | corgi_goto_sleep(alarm_time, alarm_enable, state); | ||
678 | return 1; | ||
679 | } | ||
680 | |||
681 | return 0; | ||
682 | } | ||
683 | |||
684 | static int corgi_pxa_pm_enter(suspend_state_t state) | ||
685 | { | ||
686 | unsigned long alarm_time = RTAR; | ||
687 | unsigned int alarm_status = ((RTSR & RTSR_ALE) != 0); | ||
688 | |||
689 | dev_dbg(sharpsl_pm.dev, "SharpSL suspending for first time.\n"); | ||
690 | |||
691 | corgi_goto_sleep(alarm_time, alarm_status, state); | ||
692 | |||
693 | while (corgi_enter_suspend(alarm_time,alarm_status,state)) | ||
694 | {} | ||
695 | |||
696 | dev_dbg(sharpsl_pm.dev, "SharpSL resuming...\n"); | ||
697 | |||
698 | return 0; | ||
699 | } | ||
700 | #endif | ||
701 | |||
702 | |||
703 | /* | ||
704 | * Check for fatal battery errors | ||
705 | * Fatal returns -1 | ||
706 | */ | ||
707 | static int sharpsl_fatal_check(void) | ||
708 | { | ||
709 | int buff[5], temp, i, acin; | ||
710 | |||
711 | dev_dbg(sharpsl_pm.dev, "sharpsl_fatal_check entered\n"); | ||
712 | |||
713 | /* Check AC-Adapter */ | ||
714 | acin = STATUS_AC_IN; | ||
715 | |||
716 | if (acin && (sharpsl_pm.charge_mode == CHRG_ON)) { | ||
717 | CHARGE_OFF(); | ||
718 | udelay(100); | ||
719 | DISCHARGE_ON(); /* enable discharge */ | ||
720 | mdelay(SHARPSL_WAIT_DISCHARGE_ON); | ||
721 | } | ||
722 | |||
723 | if (sharpsl_pm.machinfo->discharge1) | ||
724 | sharpsl_pm.machinfo->discharge1(1); | ||
725 | |||
726 | /* Check battery : check inserting battery ? */ | ||
727 | for (i=0; i<5; i++) { | ||
728 | buff[i] = sharpsl_read_MainBattery(); | ||
729 | mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT); | ||
730 | } | ||
731 | |||
732 | if (sharpsl_pm.machinfo->discharge1) | ||
733 | sharpsl_pm.machinfo->discharge1(0); | ||
734 | |||
735 | if (acin && (sharpsl_pm.charge_mode == CHRG_ON)) { | ||
736 | udelay(100); | ||
737 | CHARGE_ON(); | ||
738 | DISCHARGE_OFF(); | ||
739 | } | ||
740 | |||
741 | temp = get_select_val(buff); | ||
742 | dev_dbg(sharpsl_pm.dev, "sharpsl_fatal_check: acin: %d, discharge voltage: %d, no discharge: %d\n", acin, temp, sharpsl_read_MainBattery()); | ||
743 | |||
744 | if ((acin && (temp < SHARPSL_FATAL_ACIN_VOLT)) || | ||
745 | (!acin && (temp < SHARPSL_FATAL_NOACIN_VOLT))) | ||
746 | return -1; | ||
747 | return 0; | ||
748 | } | ||
749 | |||
750 | static int sharpsl_off_charge_error(void) | ||
751 | { | ||
752 | dev_err(sharpsl_pm.dev, "Offline Charger: Error occured.\n"); | ||
753 | CHARGE_OFF(); | ||
754 | CHARGE_LED_ERR(); | ||
755 | sharpsl_pm.charge_mode = CHRG_ERROR; | ||
756 | return 1; | ||
757 | } | ||
758 | |||
759 | /* | ||
760 | * Charging Control while suspended | ||
761 | * Return 1 - go straight to sleep | ||
762 | * Return 0 - sleep or wakeup depending on other factors | ||
763 | */ | ||
764 | static int sharpsl_off_charge_battery(void) | ||
765 | { | ||
766 | int time; | ||
767 | |||
768 | dev_dbg(sharpsl_pm.dev, "Charge Mode: %d\n", sharpsl_pm.charge_mode); | ||
769 | |||
770 | if (sharpsl_pm.charge_mode == CHRG_OFF) { | ||
771 | dev_dbg(sharpsl_pm.dev, "Offline Charger: Step 1\n"); | ||
772 | |||
773 | /* AC Check */ | ||
774 | if ((sharpsl_ac_check() < 0) || (sharpsl_check_battery(1) < 0)) | ||
775 | return sharpsl_off_charge_error(); | ||
776 | |||
777 | /* Start Charging */ | ||
778 | CHARGE_LED_ON(); | ||
779 | CHARGE_OFF(); | ||
780 | mdelay(SHARPSL_CHARGE_WAIT_TIME); | ||
781 | CHARGE_ON(); | ||
782 | |||
783 | sharpsl_pm.charge_mode = CHRG_ON; | ||
784 | sharpsl_pm.full_count = 0; | ||
785 | |||
786 | return 1; | ||
787 | } else if (sharpsl_pm.charge_mode != CHRG_ON) { | ||
788 | return 1; | ||
789 | } | ||
790 | |||
791 | if (sharpsl_pm.full_count == 0) { | ||
792 | int time; | ||
793 | |||
794 | dev_dbg(sharpsl_pm.dev, "Offline Charger: Step 2\n"); | ||
795 | |||
796 | if (sharpsl_check_battery(0) < 0) | ||
797 | return sharpsl_off_charge_error(); | ||
798 | |||
799 | CHARGE_OFF(); | ||
800 | mdelay(SHARPSL_CHARGE_WAIT_TIME); | ||
801 | CHARGE_ON(); | ||
802 | sharpsl_pm.charge_mode = CHRG_ON; | ||
803 | |||
804 | mdelay(SHARPSL_CHARGE_CO_CHECK_TIME); | ||
805 | |||
806 | time = RCNR; | ||
807 | while(1) { | ||
808 | /* Check if any wakeup event had occured */ | ||
809 | if (sharpsl_pm.machinfo->charger_wakeup() != 0) | ||
810 | return 0; | ||
811 | /* Check for timeout */ | ||
812 | if ((RCNR - time) > SHARPSL_WAIT_CO_TIME) | ||
813 | return 1; | ||
814 | if (STATUS_CHRG_FULL) { | ||
815 | dev_dbg(sharpsl_pm.dev, "Offline Charger: Charge full occured. Retrying to check\n"); | ||
816 | sharpsl_pm.full_count++; | ||
817 | CHARGE_OFF(); | ||
818 | mdelay(SHARPSL_CHARGE_WAIT_TIME); | ||
819 | CHARGE_ON(); | ||
820 | return 1; | ||
821 | } | ||
822 | } | ||
823 | } | ||
824 | |||
825 | dev_dbg(sharpsl_pm.dev, "Offline Charger: Step 3\n"); | ||
826 | |||
827 | mdelay(SHARPSL_CHARGE_CO_CHECK_TIME); | ||
828 | |||
829 | time = RCNR; | ||
830 | while(1) { | ||
831 | /* Check if any wakeup event had occured */ | ||
832 | if (sharpsl_pm.machinfo->charger_wakeup() != 0) | ||
833 | return 0; | ||
834 | /* Check for timeout */ | ||
835 | if ((RCNR-time) > SHARPSL_WAIT_CO_TIME) { | ||
836 | if (sharpsl_pm.full_count > SHARPSL_CHARGE_RETRY_CNT) { | ||
837 | dev_dbg(sharpsl_pm.dev, "Offline Charger: Not charged sufficiently. Retrying.\n"); | ||
838 | sharpsl_pm.full_count = 0; | ||
839 | } | ||
840 | sharpsl_pm.full_count++; | ||
841 | return 1; | ||
842 | } | ||
843 | if (STATUS_CHRG_FULL) { | ||
844 | dev_dbg(sharpsl_pm.dev, "Offline Charger: Charging complete.\n"); | ||
845 | CHARGE_LED_OFF(); | ||
846 | CHARGE_OFF(); | ||
847 | sharpsl_pm.charge_mode = CHRG_DONE; | ||
848 | return 1; | ||
849 | } | ||
850 | } | ||
851 | } | ||
852 | |||
853 | |||
854 | static ssize_t battery_percentage_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
855 | { | ||
856 | return sprintf(buf, "%d\n",sharpsl_pm.battstat.mainbat_percent); | ||
857 | } | ||
858 | |||
859 | static ssize_t battery_voltage_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
860 | { | ||
861 | return sprintf(buf, "%d\n",sharpsl_pm.battstat.mainbat_voltage); | ||
862 | } | ||
863 | |||
864 | static DEVICE_ATTR(battery_percentage, 0444, battery_percentage_show, NULL); | ||
865 | static DEVICE_ATTR(battery_voltage, 0444, battery_voltage_show, NULL); | ||
866 | |||
867 | extern void (*apm_get_power_status)(struct apm_power_info *); | ||
868 | |||
869 | static void sharpsl_apm_get_power_status(struct apm_power_info *info) | ||
870 | { | ||
871 | info->ac_line_status = sharpsl_pm.battstat.ac_status; | ||
872 | |||
873 | if (sharpsl_pm.charge_mode == CHRG_ON) | ||
874 | info->battery_status = APM_BATTERY_STATUS_CHARGING; | ||
875 | else | ||
876 | info->battery_status = sharpsl_pm.battstat.mainbat_status; | ||
877 | |||
878 | info->battery_flag = (1 << info->battery_status); | ||
879 | info->battery_life = sharpsl_pm.battstat.mainbat_percent; | ||
880 | } | ||
881 | |||
882 | static struct pm_ops sharpsl_pm_ops = { | ||
883 | .pm_disk_mode = PM_DISK_FIRMWARE, | ||
884 | .prepare = pxa_pm_prepare, | ||
885 | .enter = corgi_pxa_pm_enter, | ||
886 | .finish = pxa_pm_finish, | ||
887 | }; | ||
888 | |||
889 | static int __init sharpsl_pm_probe(struct device *dev) | ||
890 | { | ||
891 | if (!dev->platform_data) | ||
892 | return -EINVAL; | ||
893 | |||
894 | sharpsl_pm.dev = dev; | ||
895 | sharpsl_pm.machinfo = dev->platform_data; | ||
896 | sharpsl_pm.charge_mode = CHRG_OFF; | ||
897 | sharpsl_pm.flags = 0; | ||
898 | |||
899 | sharpsl_pm.machinfo->init(); | ||
900 | |||
901 | init_timer(&sharpsl_pm.ac_timer); | ||
902 | sharpsl_pm.ac_timer.function = sharpsl_ac_timer; | ||
903 | |||
904 | init_timer(&sharpsl_pm.chrg_full_timer); | ||
905 | sharpsl_pm.chrg_full_timer.function = sharpsl_chrg_full_timer; | ||
906 | |||
907 | pxa_gpio_mode(sharpsl_pm.machinfo->gpio_acin | GPIO_IN); | ||
908 | pxa_gpio_mode(sharpsl_pm.machinfo->gpio_batfull | GPIO_IN); | ||
909 | pxa_gpio_mode(sharpsl_pm.machinfo->gpio_batlock | GPIO_IN); | ||
910 | |||
911 | /* Register interrupt handlers */ | ||
912 | if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin), sharpsl_ac_isr, SA_INTERRUPT, "AC Input Detect", sharpsl_ac_isr)) { | ||
913 | dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin)); | ||
914 | } | ||
915 | else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin),IRQT_BOTHEDGE); | ||
916 | |||
917 | if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock), sharpsl_fatal_isr, SA_INTERRUPT, "Battery Cover", sharpsl_fatal_isr)) { | ||
918 | dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock)); | ||
919 | } | ||
920 | else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock),IRQT_FALLING); | ||
921 | |||
922 | if (sharpsl_pm.machinfo->gpio_fatal) { | ||
923 | if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal), sharpsl_fatal_isr, SA_INTERRUPT, "Fatal Battery", sharpsl_fatal_isr)) { | ||
924 | dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal)); | ||
925 | } | ||
926 | else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal),IRQT_FALLING); | ||
927 | } | ||
928 | |||
929 | if (!machine_is_corgi()) | ||
930 | { | ||
931 | /* Register interrupt handler. */ | ||
932 | if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull), sharpsl_chrg_full_isr, SA_INTERRUPT, "CO", sharpsl_chrg_full_isr)) { | ||
933 | dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull)); | ||
934 | } | ||
935 | else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull),IRQT_RISING); | ||
936 | } | ||
937 | |||
938 | device_create_file(dev, &dev_attr_battery_percentage); | ||
939 | device_create_file(dev, &dev_attr_battery_voltage); | ||
940 | |||
941 | apm_get_power_status = sharpsl_apm_get_power_status; | ||
942 | |||
943 | pm_set_ops(&sharpsl_pm_ops); | ||
944 | |||
945 | mod_timer(&sharpsl_pm.ac_timer, jiffies + msecs_to_jiffies(250)); | ||
946 | |||
947 | return 0; | ||
948 | } | ||
949 | |||
950 | static int sharpsl_pm_remove(struct device *dev) | ||
951 | { | ||
952 | pm_set_ops(NULL); | ||
953 | |||
954 | device_remove_file(dev, &dev_attr_battery_percentage); | ||
955 | device_remove_file(dev, &dev_attr_battery_voltage); | ||
956 | |||
957 | free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin), sharpsl_ac_isr); | ||
958 | free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock), sharpsl_fatal_isr); | ||
959 | |||
960 | if (sharpsl_pm.machinfo->gpio_fatal) | ||
961 | free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal), sharpsl_fatal_isr); | ||
962 | |||
963 | if (!machine_is_corgi()) | ||
964 | free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull), sharpsl_chrg_full_isr); | ||
965 | |||
966 | del_timer_sync(&sharpsl_pm.chrg_full_timer); | ||
967 | del_timer_sync(&sharpsl_pm.ac_timer); | ||
968 | |||
969 | return 0; | ||
970 | } | ||
971 | |||
972 | static struct device_driver sharpsl_pm_driver = { | ||
973 | .name = "sharpsl-pm", | ||
974 | .bus = &platform_bus_type, | ||
975 | .probe = sharpsl_pm_probe, | ||
976 | .remove = sharpsl_pm_remove, | ||
977 | .suspend = sharpsl_pm_suspend, | ||
978 | .resume = sharpsl_pm_resume, | ||
979 | }; | ||
980 | |||
981 | static int __devinit sharpsl_pm_init(void) | ||
982 | { | ||
983 | return driver_register(&sharpsl_pm_driver); | ||
984 | } | ||
985 | |||
986 | static void sharpsl_pm_exit(void) | ||
987 | { | ||
988 | driver_unregister(&sharpsl_pm_driver); | ||
989 | } | ||
990 | |||
991 | late_initcall(sharpsl_pm_init); | ||
992 | module_exit(sharpsl_pm_exit); | ||
diff --git a/arch/arm/mach-pxa/ssp.c b/arch/arm/mach-pxa/ssp.c index 4d826c021315..a68b30eff4d2 100644 --- a/arch/arm/mach-pxa/ssp.c +++ b/arch/arm/mach-pxa/ssp.c | |||
@@ -19,6 +19,8 @@ | |||
19 | * 22nd Aug 2003 Initial version. | 19 | * 22nd Aug 2003 Initial version. |
20 | * 20th Dec 2004 Added ssp_config for changing port config without | 20 | * 20th Dec 2004 Added ssp_config for changing port config without |
21 | * closing the port. | 21 | * closing the port. |
22 | * 4th Aug 2005 Added option to disable irq handler registration and | ||
23 | * cleaned up irq and clock detection. | ||
22 | */ | 24 | */ |
23 | 25 | ||
24 | #include <linux/module.h> | 26 | #include <linux/module.h> |
@@ -37,6 +39,26 @@ | |||
37 | 39 | ||
38 | #define PXA_SSP_PORTS 3 | 40 | #define PXA_SSP_PORTS 3 |
39 | 41 | ||
42 | struct ssp_info_ { | ||
43 | int irq; | ||
44 | u32 clock; | ||
45 | }; | ||
46 | |||
47 | /* | ||
48 | * SSP port clock and IRQ settings | ||
49 | */ | ||
50 | static const struct ssp_info_ ssp_info[PXA_SSP_PORTS] = { | ||
51 | #if defined (CONFIG_PXA27x) | ||
52 | {IRQ_SSP, CKEN23_SSP1}, | ||
53 | {IRQ_SSP2, CKEN3_SSP2}, | ||
54 | {IRQ_SSP3, CKEN4_SSP3}, | ||
55 | #else | ||
56 | {IRQ_SSP, CKEN3_SSP}, | ||
57 | {IRQ_NSSP, CKEN9_NSSP}, | ||
58 | {IRQ_ASSP, CKEN10_ASSP}, | ||
59 | #endif | ||
60 | }; | ||
61 | |||
40 | static DECLARE_MUTEX(sem); | 62 | static DECLARE_MUTEX(sem); |
41 | static int use_count[PXA_SSP_PORTS] = {0, 0, 0}; | 63 | static int use_count[PXA_SSP_PORTS] = {0, 0, 0}; |
42 | 64 | ||
@@ -210,9 +232,9 @@ int ssp_config(struct ssp_dev *dev, u32 mode, u32 flags, u32 psp_flags, u32 spee | |||
210 | * %-EBUSY if the resources are already in use | 232 | * %-EBUSY if the resources are already in use |
211 | * %0 on success | 233 | * %0 on success |
212 | */ | 234 | */ |
213 | int ssp_init(struct ssp_dev *dev, u32 port) | 235 | int ssp_init(struct ssp_dev *dev, u32 port, u32 init_flags) |
214 | { | 236 | { |
215 | int ret, irq; | 237 | int ret; |
216 | 238 | ||
217 | if (port > PXA_SSP_PORTS || port == 0) | 239 | if (port > PXA_SSP_PORTS || port == 0) |
218 | return -ENODEV; | 240 | return -ENODEV; |
@@ -229,61 +251,20 @@ int ssp_init(struct ssp_dev *dev, u32 port) | |||
229 | up(&sem); | 251 | up(&sem); |
230 | return -EBUSY; | 252 | return -EBUSY; |
231 | } | 253 | } |
232 | |||
233 | switch (port) { | ||
234 | case 1: | ||
235 | irq = IRQ_SSP; | ||
236 | break; | ||
237 | #if defined (CONFIG_PXA27x) | ||
238 | case 2: | ||
239 | irq = IRQ_SSP2; | ||
240 | break; | ||
241 | case 3: | ||
242 | irq = IRQ_SSP3; | ||
243 | break; | ||
244 | #else | ||
245 | case 2: | ||
246 | irq = IRQ_NSSP; | ||
247 | break; | ||
248 | case 3: | ||
249 | irq = IRQ_ASSP; | ||
250 | break; | ||
251 | #endif | ||
252 | default: | ||
253 | return -ENODEV; | ||
254 | } | ||
255 | |||
256 | dev->port = port; | 254 | dev->port = port; |
257 | 255 | ||
258 | ret = request_irq(irq, ssp_interrupt, 0, "SSP", dev); | 256 | /* do we need to get irq */ |
259 | if (ret) | 257 | if (!(init_flags & SSP_NO_IRQ)) { |
260 | goto out_region; | 258 | ret = request_irq(ssp_info[port-1].irq, ssp_interrupt, |
259 | 0, "SSP", dev); | ||
260 | if (ret) | ||
261 | goto out_region; | ||
262 | dev->irq = ssp_info[port-1].irq; | ||
263 | } else | ||
264 | dev->irq = 0; | ||
261 | 265 | ||
262 | /* turn on SSP port clock */ | 266 | /* turn on SSP port clock */ |
263 | switch (dev->port) { | 267 | pxa_set_cken(ssp_info[port-1].clock, 1); |
264 | #if defined (CONFIG_PXA27x) | ||
265 | case 1: | ||
266 | pxa_set_cken(CKEN23_SSP1, 1); | ||
267 | break; | ||
268 | case 2: | ||
269 | pxa_set_cken(CKEN3_SSP2, 1); | ||
270 | break; | ||
271 | case 3: | ||
272 | pxa_set_cken(CKEN4_SSP3, 1); | ||
273 | break; | ||
274 | #else | ||
275 | case 1: | ||
276 | pxa_set_cken(CKEN3_SSP, 1); | ||
277 | break; | ||
278 | case 2: | ||
279 | pxa_set_cken(CKEN9_NSSP, 1); | ||
280 | break; | ||
281 | case 3: | ||
282 | pxa_set_cken(CKEN10_ASSP, 1); | ||
283 | break; | ||
284 | #endif | ||
285 | } | ||
286 | |||
287 | up(&sem); | 268 | up(&sem); |
288 | return 0; | 269 | return 0; |
289 | 270 | ||
@@ -301,46 +282,17 @@ out_region: | |||
301 | */ | 282 | */ |
302 | void ssp_exit(struct ssp_dev *dev) | 283 | void ssp_exit(struct ssp_dev *dev) |
303 | { | 284 | { |
304 | int irq; | ||
305 | |||
306 | down(&sem); | 285 | down(&sem); |
307 | SSCR0_P(dev->port) &= ~SSCR0_SSE; | 286 | SSCR0_P(dev->port) &= ~SSCR0_SSE; |
308 | 287 | ||
309 | /* find irq, save power and turn off SSP port clock */ | 288 | if (dev->port > PXA_SSP_PORTS || dev->port == 0) { |
310 | switch (dev->port) { | 289 | printk(KERN_WARNING "SSP: tried to close invalid port\n"); |
311 | #if defined (CONFIG_PXA27x) | 290 | return; |
312 | case 1: | ||
313 | irq = IRQ_SSP; | ||
314 | pxa_set_cken(CKEN23_SSP1, 0); | ||
315 | break; | ||
316 | case 2: | ||
317 | irq = IRQ_SSP2; | ||
318 | pxa_set_cken(CKEN3_SSP2, 0); | ||
319 | break; | ||
320 | case 3: | ||
321 | irq = IRQ_SSP3; | ||
322 | pxa_set_cken(CKEN4_SSP3, 0); | ||
323 | break; | ||
324 | #else | ||
325 | case 1: | ||
326 | irq = IRQ_SSP; | ||
327 | pxa_set_cken(CKEN3_SSP, 0); | ||
328 | break; | ||
329 | case 2: | ||
330 | irq = IRQ_NSSP; | ||
331 | pxa_set_cken(CKEN9_NSSP, 0); | ||
332 | break; | ||
333 | case 3: | ||
334 | irq = IRQ_ASSP; | ||
335 | pxa_set_cken(CKEN10_ASSP, 0); | ||
336 | break; | ||
337 | #endif | ||
338 | default: | ||
339 | printk(KERN_WARNING "SSP: tried to close invalid port\n"); | ||
340 | return; | ||
341 | } | 291 | } |
342 | 292 | ||
343 | free_irq(irq, dev); | 293 | pxa_set_cken(ssp_info[dev->port-1].clock, 0); |
294 | if (dev->irq) | ||
295 | free_irq(dev->irq, dev); | ||
344 | release_mem_region(__PREG(SSCR0_P(dev->port)), 0x2c); | 296 | release_mem_region(__PREG(SSCR0_P(dev->port)), 0x2c); |
345 | use_count[dev->port - 1]--; | 297 | use_count[dev->port - 1]--; |
346 | up(&sem); | 298 | up(&sem); |
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index e3c14d6b4328..e84fdde6edf8 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig | |||
@@ -102,8 +102,8 @@ config CPU_ARM922T | |||
102 | # ARM925T | 102 | # ARM925T |
103 | config CPU_ARM925T | 103 | config CPU_ARM925T |
104 | bool "Support ARM925T processor" if ARCH_OMAP1 | 104 | bool "Support ARM925T processor" if ARCH_OMAP1 |
105 | depends on ARCH_OMAP1510 | 105 | depends on ARCH_OMAP15XX |
106 | default y if ARCH_OMAP1510 | 106 | default y if ARCH_OMAP15XX |
107 | select CPU_32v4 | 107 | select CPU_32v4 |
108 | select CPU_ABRT_EV4T | 108 | select CPU_ABRT_EV4T |
109 | select CPU_CACHE_V4WT | 109 | select CPU_CACHE_V4WT |
@@ -242,7 +242,7 @@ config CPU_XSCALE | |||
242 | # ARMv6 | 242 | # ARMv6 |
243 | config CPU_V6 | 243 | config CPU_V6 |
244 | bool "Support ARM V6 processor" | 244 | bool "Support ARM V6 processor" |
245 | depends on ARCH_INTEGRATOR || MACH_REALVIEW_EB | 245 | depends on ARCH_INTEGRATOR || MACH_REALVIEW_EB || ARCH_OMAP2 |
246 | select CPU_32v6 | 246 | select CPU_32v6 |
247 | select CPU_ABRT_EV6 | 247 | select CPU_ABRT_EV6 |
248 | select CPU_CACHE_V6 | 248 | select CPU_CACHE_V6 |
diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile index 7e144f9cad1c..9ccf1943fc94 100644 --- a/arch/arm/plat-omap/Makefile +++ b/arch/arm/plat-omap/Makefile | |||
@@ -3,7 +3,7 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | # Common support | 5 | # Common support |
6 | obj-y := common.o sram.o sram-fn.o clock.o dma.o mux.o gpio.o mcbsp.o usb.o | 6 | obj-y := common.o sram.o sram-fn.o clock.o devices.o dma.o mux.o gpio.o mcbsp.o usb.o |
7 | obj-m := | 7 | obj-m := |
8 | obj-n := | 8 | obj-n := |
9 | obj- := | 9 | obj- := |
diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index a020fe16428f..7ce39b986e23 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c | |||
@@ -1,15 +1,20 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/arm/plat-omap/clock.c | 2 | * linux/arch/arm/plat-omap/clock.c |
3 | * | 3 | * |
4 | * Copyright (C) 2004 Nokia corporation | 4 | * Copyright (C) 2004 - 2005 Nokia corporation |
5 | * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com> | 5 | * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com> |
6 | * | 6 | * |
7 | * Modified for omap shared clock framework by Tony Lindgren <tony@atomide.com> | ||
8 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | 9 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License version 2 as | 10 | * it under the terms of the GNU General Public License version 2 as |
9 | * published by the Free Software Foundation. | 11 | * published by the Free Software Foundation. |
10 | */ | 12 | */ |
11 | #include <linux/module.h> | 13 | #include <linux/version.h> |
14 | #include <linux/config.h> | ||
12 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
16 | #include <linux/init.h> | ||
17 | #include <linux/module.h> | ||
13 | #include <linux/list.h> | 18 | #include <linux/list.h> |
14 | #include <linux/errno.h> | 19 | #include <linux/errno.h> |
15 | #include <linux/err.h> | 20 | #include <linux/err.h> |
@@ -18,562 +23,20 @@ | |||
18 | #include <asm/io.h> | 23 | #include <asm/io.h> |
19 | #include <asm/semaphore.h> | 24 | #include <asm/semaphore.h> |
20 | #include <asm/hardware/clock.h> | 25 | #include <asm/hardware/clock.h> |
21 | #include <asm/arch/board.h> | ||
22 | #include <asm/arch/usb.h> | ||
23 | 26 | ||
24 | #include "clock.h" | 27 | #include <asm/arch/clock.h> |
25 | #include "sram.h" | ||
26 | 28 | ||
27 | static LIST_HEAD(clocks); | 29 | LIST_HEAD(clocks); |
28 | static DECLARE_MUTEX(clocks_sem); | 30 | static DECLARE_MUTEX(clocks_sem); |
29 | static DEFINE_SPINLOCK(clockfw_lock); | 31 | DEFINE_SPINLOCK(clockfw_lock); |
30 | static void propagate_rate(struct clk * clk); | ||
31 | /* UART clock function */ | ||
32 | static int set_uart_rate(struct clk * clk, unsigned long rate); | ||
33 | /* External clock (MCLK & BCLK) functions */ | ||
34 | static int set_ext_clk_rate(struct clk * clk, unsigned long rate); | ||
35 | static long round_ext_clk_rate(struct clk * clk, unsigned long rate); | ||
36 | static void init_ext_clk(struct clk * clk); | ||
37 | /* MPU virtual clock functions */ | ||
38 | static int select_table_rate(struct clk * clk, unsigned long rate); | ||
39 | static long round_to_table_rate(struct clk * clk, unsigned long rate); | ||
40 | void clk_setdpll(__u16, __u16); | ||
41 | |||
42 | static struct mpu_rate rate_table[] = { | ||
43 | /* MPU MHz, xtal MHz, dpll1 MHz, CKCTL, DPLL_CTL | ||
44 | * armdiv, dspdiv, dspmmu, tcdiv, perdiv, lcddiv | ||
45 | */ | ||
46 | #if defined(CONFIG_OMAP_ARM_216MHZ) | ||
47 | { 216000000, 12000000, 216000000, 0x050d, 0x2910 }, /* 1/1/2/2/2/8 */ | ||
48 | #endif | ||
49 | #if defined(CONFIG_OMAP_ARM_195MHZ) | ||
50 | { 195000000, 13000000, 195000000, 0x050e, 0x2790 }, /* 1/1/2/2/4/8 */ | ||
51 | #endif | ||
52 | #if defined(CONFIG_OMAP_ARM_192MHZ) | ||
53 | { 192000000, 19200000, 192000000, 0x050f, 0x2510 }, /* 1/1/2/2/8/8 */ | ||
54 | { 192000000, 12000000, 192000000, 0x050f, 0x2810 }, /* 1/1/2/2/8/8 */ | ||
55 | { 96000000, 12000000, 192000000, 0x055f, 0x2810 }, /* 2/2/2/2/8/8 */ | ||
56 | { 48000000, 12000000, 192000000, 0x0baf, 0x2810 }, /* 4/8/4/4/8/8 */ | ||
57 | { 24000000, 12000000, 192000000, 0x0fff, 0x2810 }, /* 8/8/8/8/8/8 */ | ||
58 | #endif | ||
59 | #if defined(CONFIG_OMAP_ARM_182MHZ) | ||
60 | { 182000000, 13000000, 182000000, 0x050e, 0x2710 }, /* 1/1/2/2/4/8 */ | ||
61 | #endif | ||
62 | #if defined(CONFIG_OMAP_ARM_168MHZ) | ||
63 | { 168000000, 12000000, 168000000, 0x010f, 0x2710 }, /* 1/1/1/2/8/8 */ | ||
64 | #endif | ||
65 | #if defined(CONFIG_OMAP_ARM_150MHZ) | ||
66 | { 150000000, 12000000, 150000000, 0x010a, 0x2cb0 }, /* 1/1/1/2/4/4 */ | ||
67 | #endif | ||
68 | #if defined(CONFIG_OMAP_ARM_120MHZ) | ||
69 | { 120000000, 12000000, 120000000, 0x010a, 0x2510 }, /* 1/1/1/2/4/4 */ | ||
70 | #endif | ||
71 | #if defined(CONFIG_OMAP_ARM_96MHZ) | ||
72 | { 96000000, 12000000, 96000000, 0x0005, 0x2410 }, /* 1/1/1/1/2/2 */ | ||
73 | #endif | ||
74 | #if defined(CONFIG_OMAP_ARM_60MHZ) | ||
75 | { 60000000, 12000000, 60000000, 0x0005, 0x2290 }, /* 1/1/1/1/2/2 */ | ||
76 | #endif | ||
77 | #if defined(CONFIG_OMAP_ARM_30MHZ) | ||
78 | { 30000000, 12000000, 60000000, 0x0555, 0x2290 }, /* 2/2/2/2/2/2 */ | ||
79 | #endif | ||
80 | { 0, 0, 0, 0, 0 }, | ||
81 | }; | ||
82 | |||
83 | |||
84 | static void ckctl_recalc(struct clk * clk); | ||
85 | int __clk_enable(struct clk *clk); | ||
86 | void __clk_disable(struct clk *clk); | ||
87 | void __clk_unuse(struct clk *clk); | ||
88 | int __clk_use(struct clk *clk); | ||
89 | |||
90 | |||
91 | static void followparent_recalc(struct clk * clk) | ||
92 | { | ||
93 | clk->rate = clk->parent->rate; | ||
94 | } | ||
95 | |||
96 | |||
97 | static void watchdog_recalc(struct clk * clk) | ||
98 | { | ||
99 | clk->rate = clk->parent->rate / 14; | ||
100 | } | ||
101 | |||
102 | static void uart_recalc(struct clk * clk) | ||
103 | { | ||
104 | unsigned int val = omap_readl(clk->enable_reg); | ||
105 | if (val & clk->enable_bit) | ||
106 | clk->rate = 48000000; | ||
107 | else | ||
108 | clk->rate = 12000000; | ||
109 | } | ||
110 | |||
111 | static struct clk ck_ref = { | ||
112 | .name = "ck_ref", | ||
113 | .rate = 12000000, | ||
114 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | ||
115 | ALWAYS_ENABLED, | ||
116 | }; | ||
117 | |||
118 | static struct clk ck_dpll1 = { | ||
119 | .name = "ck_dpll1", | ||
120 | .parent = &ck_ref, | ||
121 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | ||
122 | RATE_PROPAGATES | ALWAYS_ENABLED, | ||
123 | }; | ||
124 | |||
125 | static struct clk ck_dpll1out = { | ||
126 | .name = "ck_dpll1out", | ||
127 | .parent = &ck_dpll1, | ||
128 | .flags = CLOCK_IN_OMAP16XX, | ||
129 | .enable_reg = ARM_IDLECT2, | ||
130 | .enable_bit = EN_CKOUT_ARM, | ||
131 | .recalc = &followparent_recalc, | ||
132 | }; | ||
133 | |||
134 | static struct clk arm_ck = { | ||
135 | .name = "arm_ck", | ||
136 | .parent = &ck_dpll1, | ||
137 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | ||
138 | RATE_CKCTL | RATE_PROPAGATES | ALWAYS_ENABLED, | ||
139 | .rate_offset = CKCTL_ARMDIV_OFFSET, | ||
140 | .recalc = &ckctl_recalc, | ||
141 | }; | ||
142 | |||
143 | static struct clk armper_ck = { | ||
144 | .name = "armper_ck", | ||
145 | .parent = &ck_dpll1, | ||
146 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | ||
147 | RATE_CKCTL, | ||
148 | .enable_reg = ARM_IDLECT2, | ||
149 | .enable_bit = EN_PERCK, | ||
150 | .rate_offset = CKCTL_PERDIV_OFFSET, | ||
151 | .recalc = &ckctl_recalc, | ||
152 | }; | ||
153 | |||
154 | static struct clk arm_gpio_ck = { | ||
155 | .name = "arm_gpio_ck", | ||
156 | .parent = &ck_dpll1, | ||
157 | .flags = CLOCK_IN_OMAP1510, | ||
158 | .enable_reg = ARM_IDLECT2, | ||
159 | .enable_bit = EN_GPIOCK, | ||
160 | .recalc = &followparent_recalc, | ||
161 | }; | ||
162 | |||
163 | static struct clk armxor_ck = { | ||
164 | .name = "armxor_ck", | ||
165 | .parent = &ck_ref, | ||
166 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX, | ||
167 | .enable_reg = ARM_IDLECT2, | ||
168 | .enable_bit = EN_XORPCK, | ||
169 | .recalc = &followparent_recalc, | ||
170 | }; | ||
171 | |||
172 | static struct clk armtim_ck = { | ||
173 | .name = "armtim_ck", | ||
174 | .parent = &ck_ref, | ||
175 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX, | ||
176 | .enable_reg = ARM_IDLECT2, | ||
177 | .enable_bit = EN_TIMCK, | ||
178 | .recalc = &followparent_recalc, | ||
179 | }; | ||
180 | |||
181 | static struct clk armwdt_ck = { | ||
182 | .name = "armwdt_ck", | ||
183 | .parent = &ck_ref, | ||
184 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX, | ||
185 | .enable_reg = ARM_IDLECT2, | ||
186 | .enable_bit = EN_WDTCK, | ||
187 | .recalc = &watchdog_recalc, | ||
188 | }; | ||
189 | |||
190 | static struct clk arminth_ck16xx = { | ||
191 | .name = "arminth_ck", | ||
192 | .parent = &arm_ck, | ||
193 | .flags = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED, | ||
194 | .recalc = &followparent_recalc, | ||
195 | /* Note: On 16xx the frequency can be divided by 2 by programming | ||
196 | * ARM_CKCTL:ARM_INTHCK_SEL(14) to 1 | ||
197 | * | ||
198 | * 1510 version is in TC clocks. | ||
199 | */ | ||
200 | }; | ||
201 | |||
202 | static struct clk dsp_ck = { | ||
203 | .name = "dsp_ck", | ||
204 | .parent = &ck_dpll1, | ||
205 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | ||
206 | RATE_CKCTL, | ||
207 | .enable_reg = ARM_CKCTL, | ||
208 | .enable_bit = EN_DSPCK, | ||
209 | .rate_offset = CKCTL_DSPDIV_OFFSET, | ||
210 | .recalc = &ckctl_recalc, | ||
211 | }; | ||
212 | |||
213 | static struct clk dspmmu_ck = { | ||
214 | .name = "dspmmu_ck", | ||
215 | .parent = &ck_dpll1, | ||
216 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | ||
217 | RATE_CKCTL | ALWAYS_ENABLED, | ||
218 | .rate_offset = CKCTL_DSPMMUDIV_OFFSET, | ||
219 | .recalc = &ckctl_recalc, | ||
220 | }; | ||
221 | |||
222 | static struct clk dspper_ck = { | ||
223 | .name = "dspper_ck", | ||
224 | .parent = &ck_dpll1, | ||
225 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | ||
226 | RATE_CKCTL | DSP_DOMAIN_CLOCK | VIRTUAL_IO_ADDRESS, | ||
227 | .enable_reg = DSP_IDLECT2, | ||
228 | .enable_bit = EN_PERCK, | ||
229 | .rate_offset = CKCTL_PERDIV_OFFSET, | ||
230 | .recalc = &followparent_recalc, | ||
231 | //.recalc = &ckctl_recalc, | ||
232 | }; | ||
233 | |||
234 | static struct clk dspxor_ck = { | ||
235 | .name = "dspxor_ck", | ||
236 | .parent = &ck_ref, | ||
237 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | ||
238 | DSP_DOMAIN_CLOCK | VIRTUAL_IO_ADDRESS, | ||
239 | .enable_reg = DSP_IDLECT2, | ||
240 | .enable_bit = EN_XORPCK, | ||
241 | .recalc = &followparent_recalc, | ||
242 | }; | ||
243 | |||
244 | static struct clk dsptim_ck = { | ||
245 | .name = "dsptim_ck", | ||
246 | .parent = &ck_ref, | ||
247 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | ||
248 | DSP_DOMAIN_CLOCK | VIRTUAL_IO_ADDRESS, | ||
249 | .enable_reg = DSP_IDLECT2, | ||
250 | .enable_bit = EN_DSPTIMCK, | ||
251 | .recalc = &followparent_recalc, | ||
252 | }; | ||
253 | |||
254 | static struct clk tc_ck = { | ||
255 | .name = "tc_ck", | ||
256 | .parent = &ck_dpll1, | ||
257 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP730 | | ||
258 | RATE_CKCTL | RATE_PROPAGATES | ALWAYS_ENABLED, | ||
259 | .rate_offset = CKCTL_TCDIV_OFFSET, | ||
260 | .recalc = &ckctl_recalc, | ||
261 | }; | ||
262 | |||
263 | static struct clk arminth_ck1510 = { | ||
264 | .name = "arminth_ck", | ||
265 | .parent = &tc_ck, | ||
266 | .flags = CLOCK_IN_OMAP1510 | ALWAYS_ENABLED, | ||
267 | .recalc = &followparent_recalc, | ||
268 | /* Note: On 1510 the frequency follows TC_CK | ||
269 | * | ||
270 | * 16xx version is in MPU clocks. | ||
271 | */ | ||
272 | }; | ||
273 | |||
274 | static struct clk tipb_ck = { | ||
275 | .name = "tibp_ck", | ||
276 | .parent = &tc_ck, | ||
277 | .flags = CLOCK_IN_OMAP1510 | ALWAYS_ENABLED, | ||
278 | .recalc = &followparent_recalc, | ||
279 | }; | ||
280 | |||
281 | static struct clk l3_ocpi_ck = { | ||
282 | .name = "l3_ocpi_ck", | ||
283 | .parent = &tc_ck, | ||
284 | .flags = CLOCK_IN_OMAP16XX, | ||
285 | .enable_reg = ARM_IDLECT3, | ||
286 | .enable_bit = EN_OCPI_CK, | ||
287 | .recalc = &followparent_recalc, | ||
288 | }; | ||
289 | 32 | ||
290 | static struct clk tc1_ck = { | 33 | static struct clk_functions *arch_clock; |
291 | .name = "tc1_ck", | ||
292 | .parent = &tc_ck, | ||
293 | .flags = CLOCK_IN_OMAP16XX, | ||
294 | .enable_reg = ARM_IDLECT3, | ||
295 | .enable_bit = EN_TC1_CK, | ||
296 | .recalc = &followparent_recalc, | ||
297 | }; | ||
298 | 34 | ||
299 | static struct clk tc2_ck = { | 35 | /*------------------------------------------------------------------------- |
300 | .name = "tc2_ck", | 36 | * Standard clock functions defined in asm/hardware/clock.h |
301 | .parent = &tc_ck, | 37 | *-------------------------------------------------------------------------*/ |
302 | .flags = CLOCK_IN_OMAP16XX, | ||
303 | .enable_reg = ARM_IDLECT3, | ||
304 | .enable_bit = EN_TC2_CK, | ||
305 | .recalc = &followparent_recalc, | ||
306 | }; | ||
307 | 38 | ||
308 | static struct clk dma_ck = { | 39 | struct clk * clk_get(struct device *dev, const char *id) |
309 | .name = "dma_ck", | ||
310 | .parent = &tc_ck, | ||
311 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | ||
312 | ALWAYS_ENABLED, | ||
313 | .recalc = &followparent_recalc, | ||
314 | }; | ||
315 | |||
316 | static struct clk dma_lcdfree_ck = { | ||
317 | .name = "dma_lcdfree_ck", | ||
318 | .parent = &tc_ck, | ||
319 | .flags = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED, | ||
320 | .recalc = &followparent_recalc, | ||
321 | }; | ||
322 | |||
323 | static struct clk api_ck = { | ||
324 | .name = "api_ck", | ||
325 | .parent = &tc_ck, | ||
326 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX, | ||
327 | .enable_reg = ARM_IDLECT2, | ||
328 | .enable_bit = EN_APICK, | ||
329 | .recalc = &followparent_recalc, | ||
330 | }; | ||
331 | |||
332 | static struct clk lb_ck = { | ||
333 | .name = "lb_ck", | ||
334 | .parent = &tc_ck, | ||
335 | .flags = CLOCK_IN_OMAP1510, | ||
336 | .enable_reg = ARM_IDLECT2, | ||
337 | .enable_bit = EN_LBCK, | ||
338 | .recalc = &followparent_recalc, | ||
339 | }; | ||
340 | |||
341 | static struct clk rhea1_ck = { | ||
342 | .name = "rhea1_ck", | ||
343 | .parent = &tc_ck, | ||
344 | .flags = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED, | ||
345 | .recalc = &followparent_recalc, | ||
346 | }; | ||
347 | |||
348 | static struct clk rhea2_ck = { | ||
349 | .name = "rhea2_ck", | ||
350 | .parent = &tc_ck, | ||
351 | .flags = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED, | ||
352 | .recalc = &followparent_recalc, | ||
353 | }; | ||
354 | |||
355 | static struct clk lcd_ck = { | ||
356 | .name = "lcd_ck", | ||
357 | .parent = &ck_dpll1, | ||
358 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP730 | | ||
359 | RATE_CKCTL, | ||
360 | .enable_reg = ARM_IDLECT2, | ||
361 | .enable_bit = EN_LCDCK, | ||
362 | .rate_offset = CKCTL_LCDDIV_OFFSET, | ||
363 | .recalc = &ckctl_recalc, | ||
364 | }; | ||
365 | |||
366 | static struct clk uart1_1510 = { | ||
367 | .name = "uart1_ck", | ||
368 | /* Direct from ULPD, no parent */ | ||
369 | .rate = 12000000, | ||
370 | .flags = CLOCK_IN_OMAP1510 | ENABLE_REG_32BIT | ALWAYS_ENABLED, | ||
371 | .enable_reg = MOD_CONF_CTRL_0, | ||
372 | .enable_bit = 29, /* Chooses between 12MHz and 48MHz */ | ||
373 | .set_rate = &set_uart_rate, | ||
374 | .recalc = &uart_recalc, | ||
375 | }; | ||
376 | |||
377 | static struct clk uart1_16xx = { | ||
378 | .name = "uart1_ck", | ||
379 | /* Direct from ULPD, no parent */ | ||
380 | .rate = 48000000, | ||
381 | .flags = CLOCK_IN_OMAP16XX | RATE_FIXED | ENABLE_REG_32BIT, | ||
382 | .enable_reg = MOD_CONF_CTRL_0, | ||
383 | .enable_bit = 29, | ||
384 | }; | ||
385 | |||
386 | static struct clk uart2_ck = { | ||
387 | .name = "uart2_ck", | ||
388 | /* Direct from ULPD, no parent */ | ||
389 | .rate = 12000000, | ||
390 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | ENABLE_REG_32BIT | | ||
391 | ALWAYS_ENABLED, | ||
392 | .enable_reg = MOD_CONF_CTRL_0, | ||
393 | .enable_bit = 30, /* Chooses between 12MHz and 48MHz */ | ||
394 | .set_rate = &set_uart_rate, | ||
395 | .recalc = &uart_recalc, | ||
396 | }; | ||
397 | |||
398 | static struct clk uart3_1510 = { | ||
399 | .name = "uart3_ck", | ||
400 | /* Direct from ULPD, no parent */ | ||
401 | .rate = 12000000, | ||
402 | .flags = CLOCK_IN_OMAP1510 | ENABLE_REG_32BIT | ALWAYS_ENABLED, | ||
403 | .enable_reg = MOD_CONF_CTRL_0, | ||
404 | .enable_bit = 31, /* Chooses between 12MHz and 48MHz */ | ||
405 | .set_rate = &set_uart_rate, | ||
406 | .recalc = &uart_recalc, | ||
407 | }; | ||
408 | |||
409 | static struct clk uart3_16xx = { | ||
410 | .name = "uart3_ck", | ||
411 | /* Direct from ULPD, no parent */ | ||
412 | .rate = 48000000, | ||
413 | .flags = CLOCK_IN_OMAP16XX | RATE_FIXED | ENABLE_REG_32BIT, | ||
414 | .enable_reg = MOD_CONF_CTRL_0, | ||
415 | .enable_bit = 31, | ||
416 | }; | ||
417 | |||
418 | static struct clk usb_clko = { /* 6 MHz output on W4_USB_CLKO */ | ||
419 | .name = "usb_clko", | ||
420 | /* Direct from ULPD, no parent */ | ||
421 | .rate = 6000000, | ||
422 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | ||
423 | RATE_FIXED | ENABLE_REG_32BIT, | ||
424 | .enable_reg = ULPD_CLOCK_CTRL, | ||
425 | .enable_bit = USB_MCLK_EN_BIT, | ||
426 | }; | ||
427 | |||
428 | static struct clk usb_hhc_ck1510 = { | ||
429 | .name = "usb_hhc_ck", | ||
430 | /* Direct from ULPD, no parent */ | ||
431 | .rate = 48000000, /* Actually 2 clocks, 12MHz and 48MHz */ | ||
432 | .flags = CLOCK_IN_OMAP1510 | | ||
433 | RATE_FIXED | ENABLE_REG_32BIT, | ||
434 | .enable_reg = MOD_CONF_CTRL_0, | ||
435 | .enable_bit = USB_HOST_HHC_UHOST_EN, | ||
436 | }; | ||
437 | |||
438 | static struct clk usb_hhc_ck16xx = { | ||
439 | .name = "usb_hhc_ck", | ||
440 | /* Direct from ULPD, no parent */ | ||
441 | .rate = 48000000, | ||
442 | /* OTG_SYSCON_2.OTG_PADEN == 0 (not 1510-compatible) */ | ||
443 | .flags = CLOCK_IN_OMAP16XX | | ||
444 | RATE_FIXED | ENABLE_REG_32BIT, | ||
445 | .enable_reg = OTG_BASE + 0x08 /* OTG_SYSCON_2 */, | ||
446 | .enable_bit = 8 /* UHOST_EN */, | ||
447 | }; | ||
448 | |||
449 | static struct clk usb_dc_ck = { | ||
450 | .name = "usb_dc_ck", | ||
451 | /* Direct from ULPD, no parent */ | ||
452 | .rate = 48000000, | ||
453 | .flags = CLOCK_IN_OMAP16XX | RATE_FIXED, | ||
454 | .enable_reg = SOFT_REQ_REG, | ||
455 | .enable_bit = 4, | ||
456 | }; | ||
457 | |||
458 | static struct clk mclk_1510 = { | ||
459 | .name = "mclk", | ||
460 | /* Direct from ULPD, no parent. May be enabled by ext hardware. */ | ||
461 | .rate = 12000000, | ||
462 | .flags = CLOCK_IN_OMAP1510 | RATE_FIXED, | ||
463 | }; | ||
464 | |||
465 | static struct clk mclk_16xx = { | ||
466 | .name = "mclk", | ||
467 | /* Direct from ULPD, no parent. May be enabled by ext hardware. */ | ||
468 | .flags = CLOCK_IN_OMAP16XX, | ||
469 | .enable_reg = COM_CLK_DIV_CTRL_SEL, | ||
470 | .enable_bit = COM_ULPD_PLL_CLK_REQ, | ||
471 | .set_rate = &set_ext_clk_rate, | ||
472 | .round_rate = &round_ext_clk_rate, | ||
473 | .init = &init_ext_clk, | ||
474 | }; | ||
475 | |||
476 | static struct clk bclk_1510 = { | ||
477 | .name = "bclk", | ||
478 | /* Direct from ULPD, no parent. May be enabled by ext hardware. */ | ||
479 | .rate = 12000000, | ||
480 | .flags = CLOCK_IN_OMAP1510 | RATE_FIXED, | ||
481 | }; | ||
482 | |||
483 | static struct clk bclk_16xx = { | ||
484 | .name = "bclk", | ||
485 | /* Direct from ULPD, no parent. May be enabled by ext hardware. */ | ||
486 | .flags = CLOCK_IN_OMAP16XX, | ||
487 | .enable_reg = SWD_CLK_DIV_CTRL_SEL, | ||
488 | .enable_bit = SWD_ULPD_PLL_CLK_REQ, | ||
489 | .set_rate = &set_ext_clk_rate, | ||
490 | .round_rate = &round_ext_clk_rate, | ||
491 | .init = &init_ext_clk, | ||
492 | }; | ||
493 | |||
494 | static struct clk mmc1_ck = { | ||
495 | .name = "mmc1_ck", | ||
496 | /* Functional clock is direct from ULPD, interface clock is ARMPER */ | ||
497 | .parent = &armper_ck, | ||
498 | .rate = 48000000, | ||
499 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | ||
500 | RATE_FIXED | ENABLE_REG_32BIT, | ||
501 | .enable_reg = MOD_CONF_CTRL_0, | ||
502 | .enable_bit = 23, | ||
503 | }; | ||
504 | |||
505 | static struct clk mmc2_ck = { | ||
506 | .name = "mmc2_ck", | ||
507 | /* Functional clock is direct from ULPD, interface clock is ARMPER */ | ||
508 | .parent = &armper_ck, | ||
509 | .rate = 48000000, | ||
510 | .flags = CLOCK_IN_OMAP16XX | | ||
511 | RATE_FIXED | ENABLE_REG_32BIT, | ||
512 | .enable_reg = MOD_CONF_CTRL_0, | ||
513 | .enable_bit = 20, | ||
514 | }; | ||
515 | |||
516 | static struct clk virtual_ck_mpu = { | ||
517 | .name = "mpu", | ||
518 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | ||
519 | VIRTUAL_CLOCK | ALWAYS_ENABLED, | ||
520 | .parent = &arm_ck, /* Is smarter alias for */ | ||
521 | .recalc = &followparent_recalc, | ||
522 | .set_rate = &select_table_rate, | ||
523 | .round_rate = &round_to_table_rate, | ||
524 | }; | ||
525 | |||
526 | |||
527 | static struct clk * onchip_clks[] = { | ||
528 | /* non-ULPD clocks */ | ||
529 | &ck_ref, | ||
530 | &ck_dpll1, | ||
531 | /* CK_GEN1 clocks */ | ||
532 | &ck_dpll1out, | ||
533 | &arm_ck, | ||
534 | &armper_ck, | ||
535 | &arm_gpio_ck, | ||
536 | &armxor_ck, | ||
537 | &armtim_ck, | ||
538 | &armwdt_ck, | ||
539 | &arminth_ck1510, &arminth_ck16xx, | ||
540 | /* CK_GEN2 clocks */ | ||
541 | &dsp_ck, | ||
542 | &dspmmu_ck, | ||
543 | &dspper_ck, | ||
544 | &dspxor_ck, | ||
545 | &dsptim_ck, | ||
546 | /* CK_GEN3 clocks */ | ||
547 | &tc_ck, | ||
548 | &tipb_ck, | ||
549 | &l3_ocpi_ck, | ||
550 | &tc1_ck, | ||
551 | &tc2_ck, | ||
552 | &dma_ck, | ||
553 | &dma_lcdfree_ck, | ||
554 | &api_ck, | ||
555 | &lb_ck, | ||
556 | &rhea1_ck, | ||
557 | &rhea2_ck, | ||
558 | &lcd_ck, | ||
559 | /* ULPD clocks */ | ||
560 | &uart1_1510, | ||
561 | &uart1_16xx, | ||
562 | &uart2_ck, | ||
563 | &uart3_1510, | ||
564 | &uart3_16xx, | ||
565 | &usb_clko, | ||
566 | &usb_hhc_ck1510, &usb_hhc_ck16xx, | ||
567 | &usb_dc_ck, | ||
568 | &mclk_1510, &mclk_16xx, | ||
569 | &bclk_1510, &bclk_16xx, | ||
570 | &mmc1_ck, | ||
571 | &mmc2_ck, | ||
572 | /* Virtual clocks */ | ||
573 | &virtual_ck_mpu, | ||
574 | }; | ||
575 | |||
576 | struct clk *clk_get(struct device *dev, const char *id) | ||
577 | { | 40 | { |
578 | struct clk *p, *clk = ERR_PTR(-ENOENT); | 41 | struct clk *p, *clk = ERR_PTR(-ENOENT); |
579 | 42 | ||
@@ -590,534 +53,200 @@ struct clk *clk_get(struct device *dev, const char *id) | |||
590 | } | 53 | } |
591 | EXPORT_SYMBOL(clk_get); | 54 | EXPORT_SYMBOL(clk_get); |
592 | 55 | ||
593 | |||
594 | void clk_put(struct clk *clk) | ||
595 | { | ||
596 | if (clk && !IS_ERR(clk)) | ||
597 | module_put(clk->owner); | ||
598 | } | ||
599 | EXPORT_SYMBOL(clk_put); | ||
600 | |||
601 | |||
602 | int __clk_enable(struct clk *clk) | ||
603 | { | ||
604 | __u16 regval16; | ||
605 | __u32 regval32; | ||
606 | |||
607 | if (clk->flags & ALWAYS_ENABLED) | ||
608 | return 0; | ||
609 | |||
610 | if (unlikely(clk->enable_reg == 0)) { | ||
611 | printk(KERN_ERR "clock.c: Enable for %s without enable code\n", | ||
612 | clk->name); | ||
613 | return 0; | ||
614 | } | ||
615 | |||
616 | if (clk->flags & DSP_DOMAIN_CLOCK) { | ||
617 | __clk_use(&api_ck); | ||
618 | } | ||
619 | |||
620 | if (clk->flags & ENABLE_REG_32BIT) { | ||
621 | if (clk->flags & VIRTUAL_IO_ADDRESS) { | ||
622 | regval32 = __raw_readl(clk->enable_reg); | ||
623 | regval32 |= (1 << clk->enable_bit); | ||
624 | __raw_writel(regval32, clk->enable_reg); | ||
625 | } else { | ||
626 | regval32 = omap_readl(clk->enable_reg); | ||
627 | regval32 |= (1 << clk->enable_bit); | ||
628 | omap_writel(regval32, clk->enable_reg); | ||
629 | } | ||
630 | } else { | ||
631 | if (clk->flags & VIRTUAL_IO_ADDRESS) { | ||
632 | regval16 = __raw_readw(clk->enable_reg); | ||
633 | regval16 |= (1 << clk->enable_bit); | ||
634 | __raw_writew(regval16, clk->enable_reg); | ||
635 | } else { | ||
636 | regval16 = omap_readw(clk->enable_reg); | ||
637 | regval16 |= (1 << clk->enable_bit); | ||
638 | omap_writew(regval16, clk->enable_reg); | ||
639 | } | ||
640 | } | ||
641 | |||
642 | if (clk->flags & DSP_DOMAIN_CLOCK) { | ||
643 | __clk_unuse(&api_ck); | ||
644 | } | ||
645 | |||
646 | return 0; | ||
647 | } | ||
648 | |||
649 | |||
650 | void __clk_disable(struct clk *clk) | ||
651 | { | ||
652 | __u16 regval16; | ||
653 | __u32 regval32; | ||
654 | |||
655 | if (clk->enable_reg == 0) | ||
656 | return; | ||
657 | |||
658 | if (clk->flags & DSP_DOMAIN_CLOCK) { | ||
659 | __clk_use(&api_ck); | ||
660 | } | ||
661 | |||
662 | if (clk->flags & ENABLE_REG_32BIT) { | ||
663 | if (clk->flags & VIRTUAL_IO_ADDRESS) { | ||
664 | regval32 = __raw_readl(clk->enable_reg); | ||
665 | regval32 &= ~(1 << clk->enable_bit); | ||
666 | __raw_writel(regval32, clk->enable_reg); | ||
667 | } else { | ||
668 | regval32 = omap_readl(clk->enable_reg); | ||
669 | regval32 &= ~(1 << clk->enable_bit); | ||
670 | omap_writel(regval32, clk->enable_reg); | ||
671 | } | ||
672 | } else { | ||
673 | if (clk->flags & VIRTUAL_IO_ADDRESS) { | ||
674 | regval16 = __raw_readw(clk->enable_reg); | ||
675 | regval16 &= ~(1 << clk->enable_bit); | ||
676 | __raw_writew(regval16, clk->enable_reg); | ||
677 | } else { | ||
678 | regval16 = omap_readw(clk->enable_reg); | ||
679 | regval16 &= ~(1 << clk->enable_bit); | ||
680 | omap_writew(regval16, clk->enable_reg); | ||
681 | } | ||
682 | } | ||
683 | |||
684 | if (clk->flags & DSP_DOMAIN_CLOCK) { | ||
685 | __clk_unuse(&api_ck); | ||
686 | } | ||
687 | } | ||
688 | |||
689 | |||
690 | void __clk_unuse(struct clk *clk) | ||
691 | { | ||
692 | if (clk->usecount > 0 && !(--clk->usecount)) { | ||
693 | __clk_disable(clk); | ||
694 | if (likely(clk->parent)) | ||
695 | __clk_unuse(clk->parent); | ||
696 | } | ||
697 | } | ||
698 | |||
699 | |||
700 | int __clk_use(struct clk *clk) | ||
701 | { | ||
702 | int ret = 0; | ||
703 | if (clk->usecount++ == 0) { | ||
704 | if (likely(clk->parent)) | ||
705 | ret = __clk_use(clk->parent); | ||
706 | |||
707 | if (unlikely(ret != 0)) { | ||
708 | clk->usecount--; | ||
709 | return ret; | ||
710 | } | ||
711 | |||
712 | ret = __clk_enable(clk); | ||
713 | |||
714 | if (unlikely(ret != 0) && clk->parent) { | ||
715 | __clk_unuse(clk->parent); | ||
716 | clk->usecount--; | ||
717 | } | ||
718 | } | ||
719 | |||
720 | return ret; | ||
721 | } | ||
722 | |||
723 | |||
724 | int clk_enable(struct clk *clk) | 56 | int clk_enable(struct clk *clk) |
725 | { | 57 | { |
726 | unsigned long flags; | 58 | unsigned long flags; |
727 | int ret; | 59 | int ret = 0; |
728 | 60 | ||
729 | spin_lock_irqsave(&clockfw_lock, flags); | 61 | spin_lock_irqsave(&clockfw_lock, flags); |
730 | ret = __clk_enable(clk); | 62 | if (clk->enable) |
63 | ret = clk->enable(clk); | ||
64 | else if (arch_clock->clk_enable) | ||
65 | ret = arch_clock->clk_enable(clk); | ||
66 | else | ||
67 | printk(KERN_ERR "Could not enable clock %s\n", clk->name); | ||
731 | spin_unlock_irqrestore(&clockfw_lock, flags); | 68 | spin_unlock_irqrestore(&clockfw_lock, flags); |
69 | |||
732 | return ret; | 70 | return ret; |
733 | } | 71 | } |
734 | EXPORT_SYMBOL(clk_enable); | 72 | EXPORT_SYMBOL(clk_enable); |
735 | 73 | ||
736 | |||
737 | void clk_disable(struct clk *clk) | 74 | void clk_disable(struct clk *clk) |
738 | { | 75 | { |
739 | unsigned long flags; | 76 | unsigned long flags; |
740 | 77 | ||
741 | spin_lock_irqsave(&clockfw_lock, flags); | 78 | spin_lock_irqsave(&clockfw_lock, flags); |
742 | __clk_disable(clk); | 79 | if (clk->disable) |
80 | clk->disable(clk); | ||
81 | else if (arch_clock->clk_disable) | ||
82 | arch_clock->clk_disable(clk); | ||
83 | else | ||
84 | printk(KERN_ERR "Could not disable clock %s\n", clk->name); | ||
743 | spin_unlock_irqrestore(&clockfw_lock, flags); | 85 | spin_unlock_irqrestore(&clockfw_lock, flags); |
744 | } | 86 | } |
745 | EXPORT_SYMBOL(clk_disable); | 87 | EXPORT_SYMBOL(clk_disable); |
746 | 88 | ||
747 | |||
748 | int clk_use(struct clk *clk) | 89 | int clk_use(struct clk *clk) |
749 | { | 90 | { |
750 | unsigned long flags; | 91 | unsigned long flags; |
751 | int ret = 0; | 92 | int ret = 0; |
752 | 93 | ||
753 | spin_lock_irqsave(&clockfw_lock, flags); | 94 | spin_lock_irqsave(&clockfw_lock, flags); |
754 | ret = __clk_use(clk); | 95 | if (arch_clock->clk_use) |
96 | ret = arch_clock->clk_use(clk); | ||
755 | spin_unlock_irqrestore(&clockfw_lock, flags); | 97 | spin_unlock_irqrestore(&clockfw_lock, flags); |
98 | |||
756 | return ret; | 99 | return ret; |
757 | } | 100 | } |
758 | EXPORT_SYMBOL(clk_use); | 101 | EXPORT_SYMBOL(clk_use); |
759 | 102 | ||
760 | |||
761 | void clk_unuse(struct clk *clk) | 103 | void clk_unuse(struct clk *clk) |
762 | { | 104 | { |
763 | unsigned long flags; | 105 | unsigned long flags; |
764 | 106 | ||
765 | spin_lock_irqsave(&clockfw_lock, flags); | 107 | spin_lock_irqsave(&clockfw_lock, flags); |
766 | __clk_unuse(clk); | 108 | if (arch_clock->clk_unuse) |
109 | arch_clock->clk_unuse(clk); | ||
767 | spin_unlock_irqrestore(&clockfw_lock, flags); | 110 | spin_unlock_irqrestore(&clockfw_lock, flags); |
768 | } | 111 | } |
769 | EXPORT_SYMBOL(clk_unuse); | 112 | EXPORT_SYMBOL(clk_unuse); |
770 | 113 | ||
771 | |||
772 | int clk_get_usecount(struct clk *clk) | 114 | int clk_get_usecount(struct clk *clk) |
773 | { | 115 | { |
774 | return clk->usecount; | 116 | unsigned long flags; |
775 | } | 117 | int ret = 0; |
776 | EXPORT_SYMBOL(clk_get_usecount); | ||
777 | |||
778 | |||
779 | unsigned long clk_get_rate(struct clk *clk) | ||
780 | { | ||
781 | return clk->rate; | ||
782 | } | ||
783 | EXPORT_SYMBOL(clk_get_rate); | ||
784 | |||
785 | |||
786 | static __u16 verify_ckctl_value(__u16 newval) | ||
787 | { | ||
788 | /* This function checks for following limitations set | ||
789 | * by the hardware (all conditions must be true): | ||
790 | * DSPMMU_CK == DSP_CK or DSPMMU_CK == DSP_CK/2 | ||
791 | * ARM_CK >= TC_CK | ||
792 | * DSP_CK >= TC_CK | ||
793 | * DSPMMU_CK >= TC_CK | ||
794 | * | ||
795 | * In addition following rules are enforced: | ||
796 | * LCD_CK <= TC_CK | ||
797 | * ARMPER_CK <= TC_CK | ||
798 | * | ||
799 | * However, maximum frequencies are not checked for! | ||
800 | */ | ||
801 | __u8 per_exp; | ||
802 | __u8 lcd_exp; | ||
803 | __u8 arm_exp; | ||
804 | __u8 dsp_exp; | ||
805 | __u8 tc_exp; | ||
806 | __u8 dspmmu_exp; | ||
807 | |||
808 | per_exp = (newval >> CKCTL_PERDIV_OFFSET) & 3; | ||
809 | lcd_exp = (newval >> CKCTL_LCDDIV_OFFSET) & 3; | ||
810 | arm_exp = (newval >> CKCTL_ARMDIV_OFFSET) & 3; | ||
811 | dsp_exp = (newval >> CKCTL_DSPDIV_OFFSET) & 3; | ||
812 | tc_exp = (newval >> CKCTL_TCDIV_OFFSET) & 3; | ||
813 | dspmmu_exp = (newval >> CKCTL_DSPMMUDIV_OFFSET) & 3; | ||
814 | |||
815 | if (dspmmu_exp < dsp_exp) | ||
816 | dspmmu_exp = dsp_exp; | ||
817 | if (dspmmu_exp > dsp_exp+1) | ||
818 | dspmmu_exp = dsp_exp+1; | ||
819 | if (tc_exp < arm_exp) | ||
820 | tc_exp = arm_exp; | ||
821 | if (tc_exp < dspmmu_exp) | ||
822 | tc_exp = dspmmu_exp; | ||
823 | if (tc_exp > lcd_exp) | ||
824 | lcd_exp = tc_exp; | ||
825 | if (tc_exp > per_exp) | ||
826 | per_exp = tc_exp; | ||
827 | 118 | ||
828 | newval &= 0xf000; | 119 | spin_lock_irqsave(&clockfw_lock, flags); |
829 | newval |= per_exp << CKCTL_PERDIV_OFFSET; | 120 | ret = clk->usecount; |
830 | newval |= lcd_exp << CKCTL_LCDDIV_OFFSET; | 121 | spin_unlock_irqrestore(&clockfw_lock, flags); |
831 | newval |= arm_exp << CKCTL_ARMDIV_OFFSET; | ||
832 | newval |= dsp_exp << CKCTL_DSPDIV_OFFSET; | ||
833 | newval |= tc_exp << CKCTL_TCDIV_OFFSET; | ||
834 | newval |= dspmmu_exp << CKCTL_DSPMMUDIV_OFFSET; | ||
835 | 122 | ||
836 | return newval; | 123 | return ret; |
837 | } | 124 | } |
125 | EXPORT_SYMBOL(clk_get_usecount); | ||
838 | 126 | ||
839 | 127 | unsigned long clk_get_rate(struct clk *clk) | |
840 | static int calc_dsor_exp(struct clk *clk, unsigned long rate) | ||
841 | { | 128 | { |
842 | /* Note: If target frequency is too low, this function will return 4, | 129 | unsigned long flags; |
843 | * which is invalid value. Caller must check for this value and act | 130 | unsigned long ret = 0; |
844 | * accordingly. | ||
845 | * | ||
846 | * Note: This function does not check for following limitations set | ||
847 | * by the hardware (all conditions must be true): | ||
848 | * DSPMMU_CK == DSP_CK or DSPMMU_CK == DSP_CK/2 | ||
849 | * ARM_CK >= TC_CK | ||
850 | * DSP_CK >= TC_CK | ||
851 | * DSPMMU_CK >= TC_CK | ||
852 | */ | ||
853 | unsigned long realrate; | ||
854 | struct clk * parent; | ||
855 | unsigned dsor_exp; | ||
856 | |||
857 | if (unlikely(!(clk->flags & RATE_CKCTL))) | ||
858 | return -EINVAL; | ||
859 | |||
860 | parent = clk->parent; | ||
861 | if (unlikely(parent == 0)) | ||
862 | return -EIO; | ||
863 | |||
864 | realrate = parent->rate; | ||
865 | for (dsor_exp=0; dsor_exp<4; dsor_exp++) { | ||
866 | if (realrate <= rate) | ||
867 | break; | ||
868 | 131 | ||
869 | realrate /= 2; | 132 | spin_lock_irqsave(&clockfw_lock, flags); |
870 | } | 133 | ret = clk->rate; |
134 | spin_unlock_irqrestore(&clockfw_lock, flags); | ||
871 | 135 | ||
872 | return dsor_exp; | 136 | return ret; |
873 | } | 137 | } |
138 | EXPORT_SYMBOL(clk_get_rate); | ||
874 | 139 | ||
875 | 140 | void clk_put(struct clk *clk) | |
876 | static void ckctl_recalc(struct clk * clk) | ||
877 | { | 141 | { |
878 | int dsor; | 142 | if (clk && !IS_ERR(clk)) |
879 | 143 | module_put(clk->owner); | |
880 | /* Calculate divisor encoded as 2-bit exponent */ | ||
881 | if (clk->flags & DSP_DOMAIN_CLOCK) { | ||
882 | /* The clock control bits are in DSP domain, | ||
883 | * so api_ck is needed for access. | ||
884 | * Note that DSP_CKCTL virt addr = phys addr, so | ||
885 | * we must use __raw_readw() instead of omap_readw(). | ||
886 | */ | ||
887 | __clk_use(&api_ck); | ||
888 | dsor = 1 << (3 & (__raw_readw(DSP_CKCTL) >> clk->rate_offset)); | ||
889 | __clk_unuse(&api_ck); | ||
890 | } else { | ||
891 | dsor = 1 << (3 & (omap_readw(ARM_CKCTL) >> clk->rate_offset)); | ||
892 | } | ||
893 | if (unlikely(clk->rate == clk->parent->rate / dsor)) | ||
894 | return; /* No change, quick exit */ | ||
895 | clk->rate = clk->parent->rate / dsor; | ||
896 | |||
897 | if (unlikely(clk->flags & RATE_PROPAGATES)) | ||
898 | propagate_rate(clk); | ||
899 | } | 144 | } |
145 | EXPORT_SYMBOL(clk_put); | ||
900 | 146 | ||
147 | /*------------------------------------------------------------------------- | ||
148 | * Optional clock functions defined in asm/hardware/clock.h | ||
149 | *-------------------------------------------------------------------------*/ | ||
901 | 150 | ||
902 | long clk_round_rate(struct clk *clk, unsigned long rate) | 151 | long clk_round_rate(struct clk *clk, unsigned long rate) |
903 | { | 152 | { |
904 | int dsor_exp; | 153 | unsigned long flags; |
905 | 154 | long ret = 0; | |
906 | if (clk->flags & RATE_FIXED) | ||
907 | return clk->rate; | ||
908 | |||
909 | if (clk->flags & RATE_CKCTL) { | ||
910 | dsor_exp = calc_dsor_exp(clk, rate); | ||
911 | if (dsor_exp < 0) | ||
912 | return dsor_exp; | ||
913 | if (dsor_exp > 3) | ||
914 | dsor_exp = 3; | ||
915 | return clk->parent->rate / (1 << dsor_exp); | ||
916 | } | ||
917 | 155 | ||
918 | if(clk->round_rate != 0) | 156 | spin_lock_irqsave(&clockfw_lock, flags); |
919 | return clk->round_rate(clk, rate); | 157 | if (arch_clock->clk_round_rate) |
158 | ret = arch_clock->clk_round_rate(clk, rate); | ||
159 | spin_unlock_irqrestore(&clockfw_lock, flags); | ||
920 | 160 | ||
921 | return clk->rate; | 161 | return ret; |
922 | } | 162 | } |
923 | EXPORT_SYMBOL(clk_round_rate); | 163 | EXPORT_SYMBOL(clk_round_rate); |
924 | 164 | ||
925 | 165 | int clk_set_rate(struct clk *clk, unsigned long rate) | |
926 | static void propagate_rate(struct clk * clk) | ||
927 | { | ||
928 | struct clk ** clkp; | ||
929 | |||
930 | for (clkp = onchip_clks; clkp < onchip_clks+ARRAY_SIZE(onchip_clks); clkp++) { | ||
931 | if (likely((*clkp)->parent != clk)) continue; | ||
932 | if (likely((*clkp)->recalc)) | ||
933 | (*clkp)->recalc(*clkp); | ||
934 | } | ||
935 | } | ||
936 | |||
937 | |||
938 | static int select_table_rate(struct clk * clk, unsigned long rate) | ||
939 | { | 166 | { |
940 | /* Find the highest supported frequency <= rate and switch to it */ | 167 | unsigned long flags; |
941 | struct mpu_rate * ptr; | 168 | int ret = 0; |
942 | |||
943 | if (clk != &virtual_ck_mpu) | ||
944 | return -EINVAL; | ||
945 | |||
946 | for (ptr = rate_table; ptr->rate; ptr++) { | ||
947 | if (ptr->xtal != ck_ref.rate) | ||
948 | continue; | ||
949 | |||
950 | /* DPLL1 cannot be reprogrammed without risking system crash */ | ||
951 | if (likely(ck_dpll1.rate!=0) && ptr->pll_rate != ck_dpll1.rate) | ||
952 | continue; | ||
953 | |||
954 | /* Can check only after xtal frequency check */ | ||
955 | if (ptr->rate <= rate) | ||
956 | break; | ||
957 | } | ||
958 | |||
959 | if (!ptr->rate) | ||
960 | return -EINVAL; | ||
961 | 169 | ||
962 | /* | 170 | spin_lock_irqsave(&clockfw_lock, flags); |
963 | * In most cases we should not need to reprogram DPLL. | 171 | if (arch_clock->clk_set_rate) |
964 | * Reprogramming the DPLL is tricky, it must be done from SRAM. | 172 | ret = arch_clock->clk_set_rate(clk, rate); |
965 | */ | 173 | spin_unlock_irqrestore(&clockfw_lock, flags); |
966 | omap_sram_reprogram_clock(ptr->dpllctl_val, ptr->ckctl_val); | ||
967 | 174 | ||
968 | ck_dpll1.rate = ptr->pll_rate; | 175 | return ret; |
969 | propagate_rate(&ck_dpll1); | ||
970 | return 0; | ||
971 | } | 176 | } |
177 | EXPORT_SYMBOL(clk_set_rate); | ||
972 | 178 | ||
973 | 179 | int clk_set_parent(struct clk *clk, struct clk *parent) | |
974 | static long round_to_table_rate(struct clk * clk, unsigned long rate) | ||
975 | { | 180 | { |
976 | /* Find the highest supported frequency <= rate */ | 181 | unsigned long flags; |
977 | struct mpu_rate * ptr; | 182 | int ret = 0; |
978 | long highest_rate; | ||
979 | |||
980 | if (clk != &virtual_ck_mpu) | ||
981 | return -EINVAL; | ||
982 | |||
983 | highest_rate = -EINVAL; | ||
984 | |||
985 | for (ptr = rate_table; ptr->rate; ptr++) { | ||
986 | if (ptr->xtal != ck_ref.rate) | ||
987 | continue; | ||
988 | |||
989 | highest_rate = ptr->rate; | ||
990 | 183 | ||
991 | /* Can check only after xtal frequency check */ | 184 | spin_lock_irqsave(&clockfw_lock, flags); |
992 | if (ptr->rate <= rate) | 185 | if (arch_clock->clk_set_parent) |
993 | break; | 186 | ret = arch_clock->clk_set_parent(clk, parent); |
994 | } | 187 | spin_unlock_irqrestore(&clockfw_lock, flags); |
995 | 188 | ||
996 | return highest_rate; | 189 | return ret; |
997 | } | 190 | } |
191 | EXPORT_SYMBOL(clk_set_parent); | ||
998 | 192 | ||
999 | 193 | struct clk *clk_get_parent(struct clk *clk) | |
1000 | int clk_set_rate(struct clk *clk, unsigned long rate) | ||
1001 | { | 194 | { |
1002 | int ret = -EINVAL; | 195 | unsigned long flags; |
1003 | int dsor_exp; | 196 | struct clk * ret = NULL; |
1004 | __u16 regval; | ||
1005 | unsigned long flags; | ||
1006 | |||
1007 | if (clk->flags & RATE_CKCTL) { | ||
1008 | dsor_exp = calc_dsor_exp(clk, rate); | ||
1009 | if (dsor_exp > 3) | ||
1010 | dsor_exp = -EINVAL; | ||
1011 | if (dsor_exp < 0) | ||
1012 | return dsor_exp; | ||
1013 | |||
1014 | spin_lock_irqsave(&clockfw_lock, flags); | ||
1015 | regval = omap_readw(ARM_CKCTL); | ||
1016 | regval &= ~(3 << clk->rate_offset); | ||
1017 | regval |= dsor_exp << clk->rate_offset; | ||
1018 | regval = verify_ckctl_value(regval); | ||
1019 | omap_writew(regval, ARM_CKCTL); | ||
1020 | clk->rate = clk->parent->rate / (1 << dsor_exp); | ||
1021 | spin_unlock_irqrestore(&clockfw_lock, flags); | ||
1022 | ret = 0; | ||
1023 | } else if(clk->set_rate != 0) { | ||
1024 | spin_lock_irqsave(&clockfw_lock, flags); | ||
1025 | ret = clk->set_rate(clk, rate); | ||
1026 | spin_unlock_irqrestore(&clockfw_lock, flags); | ||
1027 | } | ||
1028 | 197 | ||
1029 | if (unlikely(ret == 0 && (clk->flags & RATE_PROPAGATES))) | 198 | spin_lock_irqsave(&clockfw_lock, flags); |
1030 | propagate_rate(clk); | 199 | if (arch_clock->clk_get_parent) |
200 | ret = arch_clock->clk_get_parent(clk); | ||
201 | spin_unlock_irqrestore(&clockfw_lock, flags); | ||
1031 | 202 | ||
1032 | return ret; | 203 | return ret; |
1033 | } | 204 | } |
1034 | EXPORT_SYMBOL(clk_set_rate); | 205 | EXPORT_SYMBOL(clk_get_parent); |
1035 | 206 | ||
207 | /*------------------------------------------------------------------------- | ||
208 | * OMAP specific clock functions shared between omap1 and omap2 | ||
209 | *-------------------------------------------------------------------------*/ | ||
1036 | 210 | ||
1037 | static unsigned calc_ext_dsor(unsigned long rate) | 211 | unsigned int __initdata mpurate; |
1038 | { | ||
1039 | unsigned dsor; | ||
1040 | 212 | ||
1041 | /* MCLK and BCLK divisor selection is not linear: | 213 | /* |
1042 | * freq = 96MHz / dsor | 214 | * By default we use the rate set by the bootloader. |
1043 | * | 215 | * You can override this with mpurate= cmdline option. |
1044 | * RATIO_SEL range: dsor <-> RATIO_SEL | 216 | */ |
1045 | * 0..6: (RATIO_SEL+2) <-> (dsor-2) | 217 | static int __init omap_clk_setup(char *str) |
1046 | * 6..48: (8+(RATIO_SEL-6)*2) <-> ((dsor-8)/2+6) | ||
1047 | * Minimum dsor is 2 and maximum is 96. Odd divisors starting from 9 | ||
1048 | * can not be used. | ||
1049 | */ | ||
1050 | for (dsor = 2; dsor < 96; ++dsor) { | ||
1051 | if ((dsor & 1) && dsor > 8) | ||
1052 | continue; | ||
1053 | if (rate >= 96000000 / dsor) | ||
1054 | break; | ||
1055 | } | ||
1056 | return dsor; | ||
1057 | } | ||
1058 | |||
1059 | /* Only needed on 1510 */ | ||
1060 | static int set_uart_rate(struct clk * clk, unsigned long rate) | ||
1061 | { | ||
1062 | unsigned int val; | ||
1063 | |||
1064 | val = omap_readl(clk->enable_reg); | ||
1065 | if (rate == 12000000) | ||
1066 | val &= ~(1 << clk->enable_bit); | ||
1067 | else if (rate == 48000000) | ||
1068 | val |= (1 << clk->enable_bit); | ||
1069 | else | ||
1070 | return -EINVAL; | ||
1071 | omap_writel(val, clk->enable_reg); | ||
1072 | clk->rate = rate; | ||
1073 | |||
1074 | return 0; | ||
1075 | } | ||
1076 | |||
1077 | static int set_ext_clk_rate(struct clk * clk, unsigned long rate) | ||
1078 | { | 218 | { |
1079 | unsigned dsor; | 219 | get_option(&str, &mpurate); |
1080 | __u16 ratio_bits; | ||
1081 | 220 | ||
1082 | dsor = calc_ext_dsor(rate); | 221 | if (!mpurate) |
1083 | clk->rate = 96000000 / dsor; | 222 | return 1; |
1084 | if (dsor > 8) | ||
1085 | ratio_bits = ((dsor - 8) / 2 + 6) << 2; | ||
1086 | else | ||
1087 | ratio_bits = (dsor - 2) << 2; | ||
1088 | 223 | ||
1089 | ratio_bits |= omap_readw(clk->enable_reg) & ~0xfd; | 224 | if (mpurate < 1000) |
1090 | omap_writew(ratio_bits, clk->enable_reg); | 225 | mpurate *= 1000000; |
1091 | 226 | ||
1092 | return 0; | 227 | return 1; |
1093 | } | 228 | } |
229 | __setup("mpurate=", omap_clk_setup); | ||
1094 | 230 | ||
1095 | 231 | /* Used for clocks that always have same value as the parent clock */ | |
1096 | static long round_ext_clk_rate(struct clk * clk, unsigned long rate) | 232 | void followparent_recalc(struct clk *clk) |
1097 | { | 233 | { |
1098 | return 96000000 / calc_ext_dsor(rate); | 234 | clk->rate = clk->parent->rate; |
1099 | } | 235 | } |
1100 | 236 | ||
1101 | 237 | /* Propagate rate to children */ | |
1102 | static void init_ext_clk(struct clk * clk) | 238 | void propagate_rate(struct clk * tclk) |
1103 | { | 239 | { |
1104 | unsigned dsor; | 240 | struct clk *clkp; |
1105 | __u16 ratio_bits; | ||
1106 | 241 | ||
1107 | /* Determine current rate and ensure clock is based on 96MHz APLL */ | 242 | list_for_each_entry(clkp, &clocks, node) { |
1108 | ratio_bits = omap_readw(clk->enable_reg) & ~1; | 243 | if (likely(clkp->parent != tclk)) |
1109 | omap_writew(ratio_bits, clk->enable_reg); | 244 | continue; |
1110 | 245 | if (likely((u32)clkp->recalc)) | |
1111 | ratio_bits = (ratio_bits & 0xfc) >> 2; | 246 | clkp->recalc(clkp); |
1112 | if (ratio_bits > 6) | 247 | } |
1113 | dsor = (ratio_bits - 6) * 2 + 8; | ||
1114 | else | ||
1115 | dsor = ratio_bits + 2; | ||
1116 | |||
1117 | clk-> rate = 96000000 / dsor; | ||
1118 | } | 248 | } |
1119 | 249 | ||
1120 | |||
1121 | int clk_register(struct clk *clk) | 250 | int clk_register(struct clk *clk) |
1122 | { | 251 | { |
1123 | down(&clocks_sem); | 252 | down(&clocks_sem); |
@@ -1125,6 +254,7 @@ int clk_register(struct clk *clk) | |||
1125 | if (clk->init) | 254 | if (clk->init) |
1126 | clk->init(clk); | 255 | clk->init(clk); |
1127 | up(&clocks_sem); | 256 | up(&clocks_sem); |
257 | |||
1128 | return 0; | 258 | return 0; |
1129 | } | 259 | } |
1130 | EXPORT_SYMBOL(clk_register); | 260 | EXPORT_SYMBOL(clk_register); |
@@ -1137,203 +267,38 @@ void clk_unregister(struct clk *clk) | |||
1137 | } | 267 | } |
1138 | EXPORT_SYMBOL(clk_unregister); | 268 | EXPORT_SYMBOL(clk_unregister); |
1139 | 269 | ||
1140 | #ifdef CONFIG_OMAP_RESET_CLOCKS | 270 | void clk_deny_idle(struct clk *clk) |
1141 | /* | ||
1142 | * Resets some clocks that may be left on from bootloader, | ||
1143 | * but leaves serial clocks on. See also omap_late_clk_reset(). | ||
1144 | */ | ||
1145 | static inline void omap_early_clk_reset(void) | ||
1146 | { | 271 | { |
1147 | //omap_writel(0x3 << 29, MOD_CONF_CTRL_0); | 272 | unsigned long flags; |
273 | |||
274 | spin_lock_irqsave(&clockfw_lock, flags); | ||
275 | if (arch_clock->clk_deny_idle) | ||
276 | arch_clock->clk_deny_idle(clk); | ||
277 | spin_unlock_irqrestore(&clockfw_lock, flags); | ||
1148 | } | 278 | } |
1149 | #else | 279 | EXPORT_SYMBOL(clk_deny_idle); |
1150 | #define omap_early_clk_reset() {} | ||
1151 | #endif | ||
1152 | 280 | ||
1153 | int __init clk_init(void) | 281 | void clk_allow_idle(struct clk *clk) |
1154 | { | 282 | { |
1155 | struct clk ** clkp; | 283 | unsigned long flags; |
1156 | const struct omap_clock_config *info; | ||
1157 | int crystal_type = 0; /* Default 12 MHz */ | ||
1158 | |||
1159 | omap_early_clk_reset(); | ||
1160 | |||
1161 | for (clkp = onchip_clks; clkp < onchip_clks+ARRAY_SIZE(onchip_clks); clkp++) { | ||
1162 | if (((*clkp)->flags &CLOCK_IN_OMAP1510) && cpu_is_omap1510()) { | ||
1163 | clk_register(*clkp); | ||
1164 | continue; | ||
1165 | } | ||
1166 | |||
1167 | if (((*clkp)->flags &CLOCK_IN_OMAP16XX) && cpu_is_omap16xx()) { | ||
1168 | clk_register(*clkp); | ||
1169 | continue; | ||
1170 | } | ||
1171 | |||
1172 | if (((*clkp)->flags &CLOCK_IN_OMAP730) && cpu_is_omap730()) { | ||
1173 | clk_register(*clkp); | ||
1174 | continue; | ||
1175 | } | ||
1176 | } | ||
1177 | |||
1178 | info = omap_get_config(OMAP_TAG_CLOCK, struct omap_clock_config); | ||
1179 | if (info != NULL) { | ||
1180 | if (!cpu_is_omap1510()) | ||
1181 | crystal_type = info->system_clock_type; | ||
1182 | } | ||
1183 | |||
1184 | #if defined(CONFIG_ARCH_OMAP730) | ||
1185 | ck_ref.rate = 13000000; | ||
1186 | #elif defined(CONFIG_ARCH_OMAP16XX) | ||
1187 | if (crystal_type == 2) | ||
1188 | ck_ref.rate = 19200000; | ||
1189 | #endif | ||
1190 | |||
1191 | printk("Clocks: ARM_SYSST: 0x%04x DPLL_CTL: 0x%04x ARM_CKCTL: 0x%04x\n", | ||
1192 | omap_readw(ARM_SYSST), omap_readw(DPLL_CTL), | ||
1193 | omap_readw(ARM_CKCTL)); | ||
1194 | |||
1195 | /* We want to be in syncronous scalable mode */ | ||
1196 | omap_writew(0x1000, ARM_SYSST); | ||
1197 | |||
1198 | #ifdef CONFIG_OMAP_CLOCKS_SET_BY_BOOTLOADER | ||
1199 | /* Use values set by bootloader. Determine PLL rate and recalculate | ||
1200 | * dependent clocks as if kernel had changed PLL or divisors. | ||
1201 | */ | ||
1202 | { | ||
1203 | unsigned pll_ctl_val = omap_readw(DPLL_CTL); | ||
1204 | |||
1205 | ck_dpll1.rate = ck_ref.rate; /* Base xtal rate */ | ||
1206 | if (pll_ctl_val & 0x10) { | ||
1207 | /* PLL enabled, apply multiplier and divisor */ | ||
1208 | if (pll_ctl_val & 0xf80) | ||
1209 | ck_dpll1.rate *= (pll_ctl_val & 0xf80) >> 7; | ||
1210 | ck_dpll1.rate /= ((pll_ctl_val & 0x60) >> 5) + 1; | ||
1211 | } else { | ||
1212 | /* PLL disabled, apply bypass divisor */ | ||
1213 | switch (pll_ctl_val & 0xc) { | ||
1214 | case 0: | ||
1215 | break; | ||
1216 | case 0x4: | ||
1217 | ck_dpll1.rate /= 2; | ||
1218 | break; | ||
1219 | default: | ||
1220 | ck_dpll1.rate /= 4; | ||
1221 | break; | ||
1222 | } | ||
1223 | } | ||
1224 | } | ||
1225 | propagate_rate(&ck_dpll1); | ||
1226 | #else | ||
1227 | /* Find the highest supported frequency and enable it */ | ||
1228 | if (select_table_rate(&virtual_ck_mpu, ~0)) { | ||
1229 | printk(KERN_ERR "System frequencies not set. Check your config.\n"); | ||
1230 | /* Guess sane values (60MHz) */ | ||
1231 | omap_writew(0x2290, DPLL_CTL); | ||
1232 | omap_writew(0x1005, ARM_CKCTL); | ||
1233 | ck_dpll1.rate = 60000000; | ||
1234 | propagate_rate(&ck_dpll1); | ||
1235 | } | ||
1236 | #endif | ||
1237 | /* Cache rates for clocks connected to ck_ref (not dpll1) */ | ||
1238 | propagate_rate(&ck_ref); | ||
1239 | printk(KERN_INFO "Clocking rate (xtal/DPLL1/MPU): " | ||
1240 | "%ld.%01ld/%ld.%01ld/%ld.%01ld MHz\n", | ||
1241 | ck_ref.rate / 1000000, (ck_ref.rate / 100000) % 10, | ||
1242 | ck_dpll1.rate / 1000000, (ck_dpll1.rate / 100000) % 10, | ||
1243 | arm_ck.rate / 1000000, (arm_ck.rate / 100000) % 10); | ||
1244 | |||
1245 | #ifdef CONFIG_MACH_OMAP_PERSEUS2 | ||
1246 | /* Select slicer output as OMAP input clock */ | ||
1247 | omap_writew(omap_readw(OMAP730_PCC_UPLD_CTRL) & ~0x1, OMAP730_PCC_UPLD_CTRL); | ||
1248 | #endif | ||
1249 | |||
1250 | /* Turn off DSP and ARM_TIMXO. Make sure ARM_INTHCK is not divided */ | ||
1251 | omap_writew(omap_readw(ARM_CKCTL) & 0x0fff, ARM_CKCTL); | ||
1252 | |||
1253 | /* Put DSP/MPUI into reset until needed */ | ||
1254 | omap_writew(0, ARM_RSTCT1); | ||
1255 | omap_writew(1, ARM_RSTCT2); | ||
1256 | omap_writew(0x400, ARM_IDLECT1); | ||
1257 | |||
1258 | /* | ||
1259 | * According to OMAP5910 Erratum SYS_DMA_1, bit DMACK_REQ (bit 8) | ||
1260 | * of the ARM_IDLECT2 register must be set to zero. The power-on | ||
1261 | * default value of this bit is one. | ||
1262 | */ | ||
1263 | omap_writew(0x0000, ARM_IDLECT2); /* Turn LCD clock off also */ | ||
1264 | |||
1265 | /* | ||
1266 | * Only enable those clocks we will need, let the drivers | ||
1267 | * enable other clocks as necessary | ||
1268 | */ | ||
1269 | clk_use(&armper_ck); | ||
1270 | clk_use(&armxor_ck); | ||
1271 | clk_use(&armtim_ck); | ||
1272 | |||
1273 | if (cpu_is_omap1510()) | ||
1274 | clk_enable(&arm_gpio_ck); | ||
1275 | 284 | ||
1276 | return 0; | 285 | spin_lock_irqsave(&clockfw_lock, flags); |
286 | if (arch_clock->clk_allow_idle) | ||
287 | arch_clock->clk_allow_idle(clk); | ||
288 | spin_unlock_irqrestore(&clockfw_lock, flags); | ||
1277 | } | 289 | } |
290 | EXPORT_SYMBOL(clk_allow_idle); | ||
1278 | 291 | ||
292 | /*-------------------------------------------------------------------------*/ | ||
1279 | 293 | ||
1280 | #ifdef CONFIG_OMAP_RESET_CLOCKS | 294 | int __init clk_init(struct clk_functions * custom_clocks) |
1281 | |||
1282 | static int __init omap_late_clk_reset(void) | ||
1283 | { | 295 | { |
1284 | /* Turn off all unused clocks */ | 296 | if (!custom_clocks) { |
1285 | struct clk *p; | 297 | printk(KERN_ERR "No custom clock functions registered\n"); |
1286 | __u32 regval32; | 298 | BUG(); |
1287 | |||
1288 | /* USB_REQ_EN will be disabled later if necessary (usb_dc_ck) */ | ||
1289 | regval32 = omap_readw(SOFT_REQ_REG) & (1 << 4); | ||
1290 | omap_writew(regval32, SOFT_REQ_REG); | ||
1291 | omap_writew(0, SOFT_REQ_REG2); | ||
1292 | |||
1293 | list_for_each_entry(p, &clocks, node) { | ||
1294 | if (p->usecount > 0 || (p->flags & ALWAYS_ENABLED) || | ||
1295 | p->enable_reg == 0) | ||
1296 | continue; | ||
1297 | |||
1298 | /* Assume no DSP clocks have been activated by bootloader */ | ||
1299 | if (p->flags & DSP_DOMAIN_CLOCK) | ||
1300 | continue; | ||
1301 | |||
1302 | /* Is the clock already disabled? */ | ||
1303 | if (p->flags & ENABLE_REG_32BIT) { | ||
1304 | if (p->flags & VIRTUAL_IO_ADDRESS) | ||
1305 | regval32 = __raw_readl(p->enable_reg); | ||
1306 | else | ||
1307 | regval32 = omap_readl(p->enable_reg); | ||
1308 | } else { | ||
1309 | if (p->flags & VIRTUAL_IO_ADDRESS) | ||
1310 | regval32 = __raw_readw(p->enable_reg); | ||
1311 | else | ||
1312 | regval32 = omap_readw(p->enable_reg); | ||
1313 | } | ||
1314 | |||
1315 | if ((regval32 & (1 << p->enable_bit)) == 0) | ||
1316 | continue; | ||
1317 | |||
1318 | /* FIXME: This clock seems to be necessary but no-one | ||
1319 | * has asked for its activation. */ | ||
1320 | if (p == &tc2_ck // FIX: pm.c (SRAM), CCP, Camera | ||
1321 | || p == &ck_dpll1out // FIX: SoSSI, SSR | ||
1322 | || p == &arm_gpio_ck // FIX: GPIO code for 1510 | ||
1323 | ) { | ||
1324 | printk(KERN_INFO "FIXME: Clock \"%s\" seems unused\n", | ||
1325 | p->name); | ||
1326 | continue; | ||
1327 | } | ||
1328 | |||
1329 | printk(KERN_INFO "Disabling unused clock \"%s\"... ", p->name); | ||
1330 | __clk_disable(p); | ||
1331 | printk(" done\n"); | ||
1332 | } | 299 | } |
1333 | 300 | ||
301 | arch_clock = custom_clocks; | ||
302 | |||
1334 | return 0; | 303 | return 0; |
1335 | } | 304 | } |
1336 | |||
1337 | late_initcall(omap_late_clk_reset); | ||
1338 | |||
1339 | #endif | ||
diff --git a/arch/arm/plat-omap/clock.h b/arch/arm/plat-omap/clock.h deleted file mode 100644 index a89e1e8c2519..000000000000 --- a/arch/arm/plat-omap/clock.h +++ /dev/null | |||
@@ -1,120 +0,0 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/plat-omap/clock.h | ||
3 | * | ||
4 | * Copyright (C) 2004 Nokia corporation | ||
5 | * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com> | ||
6 | * Based on clocks.h by Tony Lindgren, Gordon McNutt and RidgeRun, Inc | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #ifndef __ARCH_ARM_OMAP_CLOCK_H | ||
14 | #define __ARCH_ARM_OMAP_CLOCK_H | ||
15 | |||
16 | struct module; | ||
17 | |||
18 | struct clk { | ||
19 | struct list_head node; | ||
20 | struct module *owner; | ||
21 | const char *name; | ||
22 | struct clk *parent; | ||
23 | unsigned long rate; | ||
24 | __s8 usecount; | ||
25 | __u16 flags; | ||
26 | __u32 enable_reg; | ||
27 | __u8 enable_bit; | ||
28 | __u8 rate_offset; | ||
29 | void (*recalc)(struct clk *); | ||
30 | int (*set_rate)(struct clk *, unsigned long); | ||
31 | long (*round_rate)(struct clk *, unsigned long); | ||
32 | void (*init)(struct clk *); | ||
33 | }; | ||
34 | |||
35 | |||
36 | struct mpu_rate { | ||
37 | unsigned long rate; | ||
38 | unsigned long xtal; | ||
39 | unsigned long pll_rate; | ||
40 | __u16 ckctl_val; | ||
41 | __u16 dpllctl_val; | ||
42 | }; | ||
43 | |||
44 | |||
45 | /* Clock flags */ | ||
46 | #define RATE_CKCTL 1 | ||
47 | #define RATE_FIXED 2 | ||
48 | #define RATE_PROPAGATES 4 | ||
49 | #define VIRTUAL_CLOCK 8 | ||
50 | #define ALWAYS_ENABLED 16 | ||
51 | #define ENABLE_REG_32BIT 32 | ||
52 | #define CLOCK_IN_OMAP16XX 64 | ||
53 | #define CLOCK_IN_OMAP1510 128 | ||
54 | #define CLOCK_IN_OMAP730 256 | ||
55 | #define DSP_DOMAIN_CLOCK 512 | ||
56 | #define VIRTUAL_IO_ADDRESS 1024 | ||
57 | |||
58 | /* ARM_CKCTL bit shifts */ | ||
59 | #define CKCTL_PERDIV_OFFSET 0 | ||
60 | #define CKCTL_LCDDIV_OFFSET 2 | ||
61 | #define CKCTL_ARMDIV_OFFSET 4 | ||
62 | #define CKCTL_DSPDIV_OFFSET 6 | ||
63 | #define CKCTL_TCDIV_OFFSET 8 | ||
64 | #define CKCTL_DSPMMUDIV_OFFSET 10 | ||
65 | /*#define ARM_TIMXO 12*/ | ||
66 | #define EN_DSPCK 13 | ||
67 | /*#define ARM_INTHCK_SEL 14*/ /* Divide-by-2 for mpu inth_ck */ | ||
68 | /* DSP_CKCTL bit shifts */ | ||
69 | #define CKCTL_DSPPERDIV_OFFSET 0 | ||
70 | |||
71 | /* ARM_IDLECT1 bit shifts */ | ||
72 | /*#define IDLWDT_ARM 0*/ | ||
73 | /*#define IDLXORP_ARM 1*/ | ||
74 | /*#define IDLPER_ARM 2*/ | ||
75 | /*#define IDLLCD_ARM 3*/ | ||
76 | /*#define IDLLB_ARM 4*/ | ||
77 | /*#define IDLHSAB_ARM 5*/ | ||
78 | /*#define IDLIF_ARM 6*/ | ||
79 | /*#define IDLDPLL_ARM 7*/ | ||
80 | /*#define IDLAPI_ARM 8*/ | ||
81 | /*#define IDLTIM_ARM 9*/ | ||
82 | /*#define SETARM_IDLE 11*/ | ||
83 | |||
84 | /* ARM_IDLECT2 bit shifts */ | ||
85 | #define EN_WDTCK 0 | ||
86 | #define EN_XORPCK 1 | ||
87 | #define EN_PERCK 2 | ||
88 | #define EN_LCDCK 3 | ||
89 | #define EN_LBCK 4 /* Not on 1610/1710 */ | ||
90 | /*#define EN_HSABCK 5*/ | ||
91 | #define EN_APICK 6 | ||
92 | #define EN_TIMCK 7 | ||
93 | #define DMACK_REQ 8 | ||
94 | #define EN_GPIOCK 9 /* Not on 1610/1710 */ | ||
95 | /*#define EN_LBFREECK 10*/ | ||
96 | #define EN_CKOUT_ARM 11 | ||
97 | |||
98 | /* ARM_IDLECT3 bit shifts */ | ||
99 | #define EN_OCPI_CK 0 | ||
100 | #define EN_TC1_CK 2 | ||
101 | #define EN_TC2_CK 4 | ||
102 | |||
103 | /* DSP_IDLECT2 bit shifts (0,1,2 are same as for ARM_IDLECT2) */ | ||
104 | #define EN_DSPTIMCK 5 | ||
105 | |||
106 | /* Various register defines for clock controls scattered around OMAP chip */ | ||
107 | #define USB_MCLK_EN_BIT 4 /* In ULPD_CLKC_CTRL */ | ||
108 | #define USB_HOST_HHC_UHOST_EN 9 /* In MOD_CONF_CTRL_0 */ | ||
109 | #define SWD_ULPD_PLL_CLK_REQ 1 /* In SWD_CLK_DIV_CTRL_SEL */ | ||
110 | #define COM_ULPD_PLL_CLK_REQ 1 /* In COM_CLK_DIV_CTRL_SEL */ | ||
111 | #define SWD_CLK_DIV_CTRL_SEL 0xfffe0874 | ||
112 | #define COM_CLK_DIV_CTRL_SEL 0xfffe0878 | ||
113 | #define SOFT_REQ_REG 0xfffe0834 | ||
114 | #define SOFT_REQ_REG2 0xfffe0880 | ||
115 | |||
116 | int clk_register(struct clk *clk); | ||
117 | void clk_unregister(struct clk *clk); | ||
118 | int clk_init(void); | ||
119 | |||
120 | #endif | ||
diff --git a/arch/arm/plat-omap/common.c b/arch/arm/plat-omap/common.c index 02bcc6c1cd1b..ccdb452630cf 100644 --- a/arch/arm/plat-omap/common.c +++ b/arch/arm/plat-omap/common.c | |||
@@ -31,7 +31,7 @@ | |||
31 | #include <asm/arch/mux.h> | 31 | #include <asm/arch/mux.h> |
32 | #include <asm/arch/fpga.h> | 32 | #include <asm/arch/fpga.h> |
33 | 33 | ||
34 | #include "clock.h" | 34 | #include <asm/arch/clock.h> |
35 | 35 | ||
36 | #define NO_LENGTH_CHECK 0xffffffff | 36 | #define NO_LENGTH_CHECK 0xffffffff |
37 | 37 | ||
@@ -117,19 +117,43 @@ EXPORT_SYMBOL(omap_get_var_config); | |||
117 | 117 | ||
118 | static int __init omap_add_serial_console(void) | 118 | static int __init omap_add_serial_console(void) |
119 | { | 119 | { |
120 | const struct omap_serial_console_config *info; | 120 | const struct omap_serial_console_config *con_info; |
121 | 121 | const struct omap_uart_config *uart_info; | |
122 | info = omap_get_config(OMAP_TAG_SERIAL_CONSOLE, | 122 | static char speed[11], *opt = NULL; |
123 | struct omap_serial_console_config); | 123 | int line, i, uart_idx; |
124 | if (info != NULL && info->console_uart) { | 124 | |
125 | static char speed[11], *opt = NULL; | 125 | uart_info = omap_get_config(OMAP_TAG_UART, struct omap_uart_config); |
126 | con_info = omap_get_config(OMAP_TAG_SERIAL_CONSOLE, | ||
127 | struct omap_serial_console_config); | ||
128 | if (uart_info == NULL || con_info == NULL) | ||
129 | return 0; | ||
130 | |||
131 | if (con_info->console_uart == 0) | ||
132 | return 0; | ||
133 | |||
134 | if (con_info->console_speed) { | ||
135 | snprintf(speed, sizeof(speed), "%u", con_info->console_speed); | ||
136 | opt = speed; | ||
137 | } | ||
126 | 138 | ||
127 | if (info->console_speed) { | 139 | uart_idx = con_info->console_uart - 1; |
128 | snprintf(speed, sizeof(speed), "%u", info->console_speed); | 140 | if (uart_idx >= OMAP_MAX_NR_PORTS) { |
129 | opt = speed; | 141 | printk(KERN_INFO "Console: external UART#%d. " |
130 | } | 142 | "Not adding it as console this time.\n", |
131 | return add_preferred_console("ttyS", info->console_uart - 1, opt); | 143 | uart_idx + 1); |
144 | return 0; | ||
145 | } | ||
146 | if (!(uart_info->enabled_uarts & (1 << uart_idx))) { | ||
147 | printk(KERN_ERR "Console: Selected UART#%d is " | ||
148 | "not enabled for this platform\n", | ||
149 | uart_idx + 1); | ||
150 | return -1; | ||
151 | } | ||
152 | line = 0; | ||
153 | for (i = 0; i < uart_idx; i++) { | ||
154 | if (uart_info->enabled_uarts & (1 << i)) | ||
155 | line++; | ||
132 | } | 156 | } |
133 | return 0; | 157 | return add_preferred_console("ttyS", line, opt); |
134 | } | 158 | } |
135 | console_initcall(omap_add_serial_console); | 159 | console_initcall(omap_add_serial_console); |
diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c new file mode 100644 index 000000000000..9dcce904b608 --- /dev/null +++ b/arch/arm/plat-omap/devices.c | |||
@@ -0,0 +1,381 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/plat-omap/devices.c | ||
3 | * | ||
4 | * Common platform device setup/initialization for OMAP1 and OMAP2 | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/config.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | |||
18 | #include <asm/hardware.h> | ||
19 | #include <asm/io.h> | ||
20 | #include <asm/mach-types.h> | ||
21 | #include <asm/mach/map.h> | ||
22 | |||
23 | #include <asm/arch/tc.h> | ||
24 | #include <asm/arch/board.h> | ||
25 | #include <asm/arch/mux.h> | ||
26 | #include <asm/arch/gpio.h> | ||
27 | |||
28 | |||
29 | void omap_nop_release(struct device *dev) | ||
30 | { | ||
31 | /* Nothing */ | ||
32 | } | ||
33 | |||
34 | /*-------------------------------------------------------------------------*/ | ||
35 | |||
36 | #if defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE) | ||
37 | |||
38 | #define OMAP1_I2C_BASE 0xfffb3800 | ||
39 | #define OMAP2_I2C_BASE1 0x48070000 | ||
40 | #define OMAP_I2C_SIZE 0x3f | ||
41 | #define OMAP1_I2C_INT INT_I2C | ||
42 | #define OMAP2_I2C_INT1 56 | ||
43 | |||
44 | static struct resource i2c_resources1[] = { | ||
45 | { | ||
46 | .start = 0, | ||
47 | .end = 0, | ||
48 | .flags = IORESOURCE_MEM, | ||
49 | }, | ||
50 | { | ||
51 | .start = 0, | ||
52 | .flags = IORESOURCE_IRQ, | ||
53 | }, | ||
54 | }; | ||
55 | |||
56 | /* DMA not used; works around erratum writing to non-empty i2c fifo */ | ||
57 | |||
58 | static struct platform_device omap_i2c_device1 = { | ||
59 | .name = "i2c_omap", | ||
60 | .id = 1, | ||
61 | .dev = { | ||
62 | .release = omap_nop_release, | ||
63 | }, | ||
64 | .num_resources = ARRAY_SIZE(i2c_resources1), | ||
65 | .resource = i2c_resources1, | ||
66 | }; | ||
67 | |||
68 | /* See also arch/arm/mach-omap2/devices.c for second I2C on 24xx */ | ||
69 | static void omap_init_i2c(void) | ||
70 | { | ||
71 | if (cpu_is_omap24xx()) { | ||
72 | i2c_resources1[0].start = OMAP2_I2C_BASE1; | ||
73 | i2c_resources1[0].end = OMAP2_I2C_BASE1 + OMAP_I2C_SIZE; | ||
74 | i2c_resources1[1].start = OMAP2_I2C_INT1; | ||
75 | } else { | ||
76 | i2c_resources1[0].start = OMAP1_I2C_BASE; | ||
77 | i2c_resources1[0].end = OMAP1_I2C_BASE + OMAP_I2C_SIZE; | ||
78 | i2c_resources1[1].start = OMAP1_I2C_INT; | ||
79 | } | ||
80 | |||
81 | /* FIXME define and use a boot tag, in case of boards that | ||
82 | * either don't wire up I2C, or chips that mux it differently... | ||
83 | * it can include clocking and address info, maybe more. | ||
84 | */ | ||
85 | if (cpu_is_omap24xx()) { | ||
86 | omap_cfg_reg(M19_24XX_I2C1_SCL); | ||
87 | omap_cfg_reg(L15_24XX_I2C1_SDA); | ||
88 | } else { | ||
89 | omap_cfg_reg(I2C_SCL); | ||
90 | omap_cfg_reg(I2C_SDA); | ||
91 | } | ||
92 | |||
93 | (void) platform_device_register(&omap_i2c_device1); | ||
94 | } | ||
95 | |||
96 | #else | ||
97 | static inline void omap_init_i2c(void) {} | ||
98 | #endif | ||
99 | |||
100 | /*-------------------------------------------------------------------------*/ | ||
101 | |||
102 | #if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) | ||
103 | |||
104 | #ifdef CONFIG_ARCH_OMAP24XX | ||
105 | #define OMAP_MMC1_BASE 0x4809c000 | ||
106 | #define OMAP_MMC1_INT 83 | ||
107 | #else | ||
108 | #define OMAP_MMC1_BASE 0xfffb7800 | ||
109 | #define OMAP_MMC1_INT INT_MMC | ||
110 | #endif | ||
111 | #define OMAP_MMC2_BASE 0xfffb7c00 /* omap16xx only */ | ||
112 | |||
113 | static struct omap_mmc_conf mmc1_conf; | ||
114 | |||
115 | static u64 mmc1_dmamask = 0xffffffff; | ||
116 | |||
117 | static struct resource mmc1_resources[] = { | ||
118 | { | ||
119 | .start = IO_ADDRESS(OMAP_MMC1_BASE), | ||
120 | .end = IO_ADDRESS(OMAP_MMC1_BASE) + 0x7f, | ||
121 | .flags = IORESOURCE_MEM, | ||
122 | }, | ||
123 | { | ||
124 | .start = OMAP_MMC1_INT, | ||
125 | .flags = IORESOURCE_IRQ, | ||
126 | }, | ||
127 | }; | ||
128 | |||
129 | static struct platform_device mmc_omap_device1 = { | ||
130 | .name = "mmci-omap", | ||
131 | .id = 1, | ||
132 | .dev = { | ||
133 | .release = omap_nop_release, | ||
134 | .dma_mask = &mmc1_dmamask, | ||
135 | .platform_data = &mmc1_conf, | ||
136 | }, | ||
137 | .num_resources = ARRAY_SIZE(mmc1_resources), | ||
138 | .resource = mmc1_resources, | ||
139 | }; | ||
140 | |||
141 | #ifdef CONFIG_ARCH_OMAP16XX | ||
142 | |||
143 | static struct omap_mmc_conf mmc2_conf; | ||
144 | |||
145 | static u64 mmc2_dmamask = 0xffffffff; | ||
146 | |||
147 | static struct resource mmc2_resources[] = { | ||
148 | { | ||
149 | .start = IO_ADDRESS(OMAP_MMC2_BASE), | ||
150 | .end = IO_ADDRESS(OMAP_MMC2_BASE) + 0x7f, | ||
151 | .flags = IORESOURCE_MEM, | ||
152 | }, | ||
153 | { | ||
154 | .start = INT_1610_MMC2, | ||
155 | .flags = IORESOURCE_IRQ, | ||
156 | }, | ||
157 | }; | ||
158 | |||
159 | static struct platform_device mmc_omap_device2 = { | ||
160 | .name = "mmci-omap", | ||
161 | .id = 2, | ||
162 | .dev = { | ||
163 | .release = omap_nop_release, | ||
164 | .dma_mask = &mmc2_dmamask, | ||
165 | .platform_data = &mmc2_conf, | ||
166 | }, | ||
167 | .num_resources = ARRAY_SIZE(mmc2_resources), | ||
168 | .resource = mmc2_resources, | ||
169 | }; | ||
170 | #endif | ||
171 | |||
172 | static void __init omap_init_mmc(void) | ||
173 | { | ||
174 | const struct omap_mmc_config *mmc_conf; | ||
175 | const struct omap_mmc_conf *mmc; | ||
176 | |||
177 | /* NOTE: assumes MMC was never (wrongly) enabled */ | ||
178 | mmc_conf = omap_get_config(OMAP_TAG_MMC, struct omap_mmc_config); | ||
179 | if (!mmc_conf) | ||
180 | return; | ||
181 | |||
182 | /* block 1 is always available and has just one pinout option */ | ||
183 | mmc = &mmc_conf->mmc[0]; | ||
184 | if (mmc->enabled) { | ||
185 | if (!cpu_is_omap24xx()) { | ||
186 | omap_cfg_reg(MMC_CMD); | ||
187 | omap_cfg_reg(MMC_CLK); | ||
188 | omap_cfg_reg(MMC_DAT0); | ||
189 | if (cpu_is_omap1710()) { | ||
190 | omap_cfg_reg(M15_1710_MMC_CLKI); | ||
191 | omap_cfg_reg(P19_1710_MMC_CMDDIR); | ||
192 | omap_cfg_reg(P20_1710_MMC_DATDIR0); | ||
193 | } | ||
194 | } | ||
195 | if (mmc->wire4) { | ||
196 | if (!cpu_is_omap24xx()) { | ||
197 | omap_cfg_reg(MMC_DAT1); | ||
198 | /* NOTE: DAT2 can be on W10 (here) or M15 */ | ||
199 | if (!mmc->nomux) | ||
200 | omap_cfg_reg(MMC_DAT2); | ||
201 | omap_cfg_reg(MMC_DAT3); | ||
202 | } | ||
203 | } | ||
204 | mmc1_conf = *mmc; | ||
205 | (void) platform_device_register(&mmc_omap_device1); | ||
206 | } | ||
207 | |||
208 | #ifdef CONFIG_ARCH_OMAP16XX | ||
209 | /* block 2 is on newer chips, and has many pinout options */ | ||
210 | mmc = &mmc_conf->mmc[1]; | ||
211 | if (mmc->enabled) { | ||
212 | if (!mmc->nomux) { | ||
213 | omap_cfg_reg(Y8_1610_MMC2_CMD); | ||
214 | omap_cfg_reg(Y10_1610_MMC2_CLK); | ||
215 | omap_cfg_reg(R18_1610_MMC2_CLKIN); | ||
216 | omap_cfg_reg(W8_1610_MMC2_DAT0); | ||
217 | if (mmc->wire4) { | ||
218 | omap_cfg_reg(V8_1610_MMC2_DAT1); | ||
219 | omap_cfg_reg(W15_1610_MMC2_DAT2); | ||
220 | omap_cfg_reg(R10_1610_MMC2_DAT3); | ||
221 | } | ||
222 | |||
223 | /* These are needed for the level shifter */ | ||
224 | omap_cfg_reg(V9_1610_MMC2_CMDDIR); | ||
225 | omap_cfg_reg(V5_1610_MMC2_DATDIR0); | ||
226 | omap_cfg_reg(W19_1610_MMC2_DATDIR1); | ||
227 | } | ||
228 | |||
229 | /* Feedback clock must be set on OMAP-1710 MMC2 */ | ||
230 | if (cpu_is_omap1710()) | ||
231 | omap_writel(omap_readl(MOD_CONF_CTRL_1) | (1 << 24), | ||
232 | MOD_CONF_CTRL_1); | ||
233 | mmc2_conf = *mmc; | ||
234 | (void) platform_device_register(&mmc_omap_device2); | ||
235 | } | ||
236 | #endif | ||
237 | return; | ||
238 | } | ||
239 | #else | ||
240 | static inline void omap_init_mmc(void) {} | ||
241 | #endif | ||
242 | |||
243 | #if defined(CONFIG_OMAP_WATCHDOG) || defined(CONFIG_OMAP_WATCHDOG_MODULE) | ||
244 | |||
245 | #ifdef CONFIG_ARCH_OMAP24XX | ||
246 | #define OMAP_WDT_BASE 0x48022000 | ||
247 | #else | ||
248 | #define OMAP_WDT_BASE 0xfffeb000 | ||
249 | #endif | ||
250 | |||
251 | static struct resource wdt_resources[] = { | ||
252 | { | ||
253 | .start = OMAP_WDT_BASE, | ||
254 | .end = OMAP_WDT_BASE + 0x4f, | ||
255 | .flags = IORESOURCE_MEM, | ||
256 | }, | ||
257 | }; | ||
258 | |||
259 | static struct platform_device omap_wdt_device = { | ||
260 | .name = "omap_wdt", | ||
261 | .id = -1, | ||
262 | .dev = { | ||
263 | .release = omap_nop_release, | ||
264 | }, | ||
265 | .num_resources = ARRAY_SIZE(wdt_resources), | ||
266 | .resource = wdt_resources, | ||
267 | }; | ||
268 | |||
269 | static void omap_init_wdt(void) | ||
270 | { | ||
271 | (void) platform_device_register(&omap_wdt_device); | ||
272 | } | ||
273 | #else | ||
274 | static inline void omap_init_wdt(void) {} | ||
275 | #endif | ||
276 | |||
277 | /*-------------------------------------------------------------------------*/ | ||
278 | |||
279 | #if defined(CONFIG_OMAP_RNG) || defined(CONFIG_OMAP_RNG_MODULE) | ||
280 | |||
281 | #ifdef CONFIG_ARCH_OMAP24XX | ||
282 | #define OMAP_RNG_BASE 0x480A0000 | ||
283 | #else | ||
284 | #define OMAP_RNG_BASE 0xfffe5000 | ||
285 | #endif | ||
286 | |||
287 | static struct resource rng_resources[] = { | ||
288 | { | ||
289 | .start = OMAP_RNG_BASE, | ||
290 | .end = OMAP_RNG_BASE + 0x4f, | ||
291 | .flags = IORESOURCE_MEM, | ||
292 | }, | ||
293 | }; | ||
294 | |||
295 | static struct platform_device omap_rng_device = { | ||
296 | .name = "omap_rng", | ||
297 | .id = -1, | ||
298 | .dev = { | ||
299 | .release = omap_nop_release, | ||
300 | }, | ||
301 | .num_resources = ARRAY_SIZE(rng_resources), | ||
302 | .resource = rng_resources, | ||
303 | }; | ||
304 | |||
305 | static void omap_init_rng(void) | ||
306 | { | ||
307 | (void) platform_device_register(&omap_rng_device); | ||
308 | } | ||
309 | #else | ||
310 | static inline void omap_init_rng(void) {} | ||
311 | #endif | ||
312 | |||
313 | #if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE) | ||
314 | |||
315 | static struct omap_lcd_config omap_fb_conf; | ||
316 | |||
317 | static u64 omap_fb_dma_mask = ~(u32)0; | ||
318 | |||
319 | static struct platform_device omap_fb_device = { | ||
320 | .name = "omapfb", | ||
321 | .id = -1, | ||
322 | .dev = { | ||
323 | .release = omap_nop_release, | ||
324 | .dma_mask = &omap_fb_dma_mask, | ||
325 | .coherent_dma_mask = ~(u32)0, | ||
326 | .platform_data = &omap_fb_conf, | ||
327 | }, | ||
328 | .num_resources = 0, | ||
329 | }; | ||
330 | |||
331 | static inline void omap_init_fb(void) | ||
332 | { | ||
333 | const struct omap_lcd_config *conf; | ||
334 | |||
335 | conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config); | ||
336 | if (conf != NULL) | ||
337 | omap_fb_conf = *conf; | ||
338 | platform_device_register(&omap_fb_device); | ||
339 | } | ||
340 | |||
341 | #else | ||
342 | |||
343 | static inline void omap_init_fb(void) {} | ||
344 | |||
345 | #endif | ||
346 | |||
347 | /* | ||
348 | * This gets called after board-specific INIT_MACHINE, and initializes most | ||
349 | * on-chip peripherals accessible on this board (except for few like USB): | ||
350 | * | ||
351 | * (a) Does any "standard config" pin muxing needed. Board-specific | ||
352 | * code will have muxed GPIO pins and done "nonstandard" setup; | ||
353 | * that code could live in the boot loader. | ||
354 | * (b) Populating board-specific platform_data with the data drivers | ||
355 | * rely on to handle wiring variations. | ||
356 | * (c) Creating platform devices as meaningful on this board and | ||
357 | * with this kernel configuration. | ||
358 | * | ||
359 | * Claiming GPIOs, and setting their direction and initial values, is the | ||
360 | * responsibility of the device drivers. So is responding to probe(). | ||
361 | * | ||
362 | * Board-specific knowlege like creating devices or pin setup is to be | ||
363 | * kept out of drivers as much as possible. In particular, pin setup | ||
364 | * may be handled by the boot loader, and drivers should expect it will | ||
365 | * normally have been done by the time they're probed. | ||
366 | */ | ||
367 | static int __init omap_init_devices(void) | ||
368 | { | ||
369 | /* please keep these calls, and their implementations above, | ||
370 | * in alphabetical order so they're easier to sort through. | ||
371 | */ | ||
372 | omap_init_fb(); | ||
373 | omap_init_i2c(); | ||
374 | omap_init_mmc(); | ||
375 | omap_init_wdt(); | ||
376 | omap_init_rng(); | ||
377 | |||
378 | return 0; | ||
379 | } | ||
380 | arch_initcall(omap_init_devices); | ||
381 | |||
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index da7b65145658..f5cc21ad0956 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c | |||
@@ -6,6 +6,8 @@ | |||
6 | * DMA channel linking for 1610 by Samuel Ortiz <samuel.ortiz@nokia.com> | 6 | * DMA channel linking for 1610 by Samuel Ortiz <samuel.ortiz@nokia.com> |
7 | * Graphics DMA and LCD DMA graphics tranformations | 7 | * Graphics DMA and LCD DMA graphics tranformations |
8 | * by Imre Deak <imre.deak@nokia.com> | 8 | * by Imre Deak <imre.deak@nokia.com> |
9 | * OMAP2 support Copyright (C) 2004-2005 Texas Instruments, Inc. | ||
10 | * Merged to support both OMAP1 and OMAP2 by Tony Lindgren <tony@atomide.com> | ||
9 | * Some functions based on earlier dma-omap.c Copyright (C) 2001 RidgeRun, Inc. | 11 | * Some functions based on earlier dma-omap.c Copyright (C) 2001 RidgeRun, Inc. |
10 | * | 12 | * |
11 | * Support functions for the OMAP internal DMA channels. | 13 | * Support functions for the OMAP internal DMA channels. |
@@ -31,8 +33,15 @@ | |||
31 | 33 | ||
32 | #include <asm/arch/tc.h> | 34 | #include <asm/arch/tc.h> |
33 | 35 | ||
34 | #define OMAP_DMA_ACTIVE 0x01 | 36 | #define DEBUG_PRINTS |
37 | #undef DEBUG_PRINTS | ||
38 | #ifdef DEBUG_PRINTS | ||
39 | #define debug_printk(x) printk x | ||
40 | #else | ||
41 | #define debug_printk(x) | ||
42 | #endif | ||
35 | 43 | ||
44 | #define OMAP_DMA_ACTIVE 0x01 | ||
36 | #define OMAP_DMA_CCR_EN (1 << 7) | 45 | #define OMAP_DMA_CCR_EN (1 << 7) |
37 | 46 | ||
38 | #define OMAP_FUNC_MUX_ARM_BASE (0xfffe1000 + 0xec) | 47 | #define OMAP_FUNC_MUX_ARM_BASE (0xfffe1000 + 0xec) |
@@ -55,7 +64,7 @@ static int dma_chan_count; | |||
55 | static spinlock_t dma_chan_lock; | 64 | static spinlock_t dma_chan_lock; |
56 | static struct omap_dma_lch dma_chan[OMAP_LOGICAL_DMA_CH_COUNT]; | 65 | static struct omap_dma_lch dma_chan[OMAP_LOGICAL_DMA_CH_COUNT]; |
57 | 66 | ||
58 | const static u8 dma_irq[OMAP_LOGICAL_DMA_CH_COUNT] = { | 67 | const static u8 omap1_dma_irq[OMAP_LOGICAL_DMA_CH_COUNT] = { |
59 | INT_DMA_CH0_6, INT_DMA_CH1_7, INT_DMA_CH2_8, INT_DMA_CH3, | 68 | INT_DMA_CH0_6, INT_DMA_CH1_7, INT_DMA_CH2_8, INT_DMA_CH3, |
60 | INT_DMA_CH4, INT_DMA_CH5, INT_1610_DMA_CH6, INT_1610_DMA_CH7, | 69 | INT_DMA_CH4, INT_DMA_CH5, INT_1610_DMA_CH6, INT_1610_DMA_CH7, |
61 | INT_1610_DMA_CH8, INT_1610_DMA_CH9, INT_1610_DMA_CH10, | 70 | INT_1610_DMA_CH8, INT_1610_DMA_CH9, INT_1610_DMA_CH10, |
@@ -63,6 +72,20 @@ const static u8 dma_irq[OMAP_LOGICAL_DMA_CH_COUNT] = { | |||
63 | INT_1610_DMA_CH14, INT_1610_DMA_CH15, INT_DMA_LCD | 72 | INT_1610_DMA_CH14, INT_1610_DMA_CH15, INT_DMA_LCD |
64 | }; | 73 | }; |
65 | 74 | ||
75 | #define REVISIT_24XX() printk(KERN_ERR "FIXME: no %s on 24xx\n", \ | ||
76 | __FUNCTION__); | ||
77 | |||
78 | #ifdef CONFIG_ARCH_OMAP15XX | ||
79 | /* Returns 1 if the DMA module is in OMAP1510-compatible mode, 0 otherwise */ | ||
80 | int omap_dma_in_1510_mode(void) | ||
81 | { | ||
82 | return enable_1510_mode; | ||
83 | } | ||
84 | #else | ||
85 | #define omap_dma_in_1510_mode() 0 | ||
86 | #endif | ||
87 | |||
88 | #ifdef CONFIG_ARCH_OMAP1 | ||
66 | static inline int get_gdma_dev(int req) | 89 | static inline int get_gdma_dev(int req) |
67 | { | 90 | { |
68 | u32 reg = OMAP_FUNC_MUX_ARM_BASE + ((req - 1) / 5) * 4; | 91 | u32 reg = OMAP_FUNC_MUX_ARM_BASE + ((req - 1) / 5) * 4; |
@@ -82,6 +105,9 @@ static inline void set_gdma_dev(int req, int dev) | |||
82 | l |= (dev - 1) << shift; | 105 | l |= (dev - 1) << shift; |
83 | omap_writel(l, reg); | 106 | omap_writel(l, reg); |
84 | } | 107 | } |
108 | #else | ||
109 | #define set_gdma_dev(req, dev) do {} while (0) | ||
110 | #endif | ||
85 | 111 | ||
86 | static void clear_lch_regs(int lch) | 112 | static void clear_lch_regs(int lch) |
87 | { | 113 | { |
@@ -121,38 +147,62 @@ void omap_set_dma_priority(int dst_port, int priority) | |||
121 | } | 147 | } |
122 | 148 | ||
123 | void omap_set_dma_transfer_params(int lch, int data_type, int elem_count, | 149 | void omap_set_dma_transfer_params(int lch, int data_type, int elem_count, |
124 | int frame_count, int sync_mode) | 150 | int frame_count, int sync_mode, |
151 | int dma_trigger, int src_or_dst_synch) | ||
125 | { | 152 | { |
126 | u16 w; | 153 | OMAP_DMA_CSDP_REG(lch) &= ~0x03; |
154 | OMAP_DMA_CSDP_REG(lch) |= data_type; | ||
127 | 155 | ||
128 | w = omap_readw(OMAP_DMA_CSDP(lch)); | 156 | if (cpu_class_is_omap1()) { |
129 | w &= ~0x03; | 157 | OMAP_DMA_CCR_REG(lch) &= ~(1 << 5); |
130 | w |= data_type; | 158 | if (sync_mode == OMAP_DMA_SYNC_FRAME) |
131 | omap_writew(w, OMAP_DMA_CSDP(lch)); | 159 | OMAP_DMA_CCR_REG(lch) |= 1 << 5; |
160 | |||
161 | OMAP1_DMA_CCR2_REG(lch) &= ~(1 << 2); | ||
162 | if (sync_mode == OMAP_DMA_SYNC_BLOCK) | ||
163 | OMAP1_DMA_CCR2_REG(lch) |= 1 << 2; | ||
164 | } | ||
165 | |||
166 | if (cpu_is_omap24xx() && dma_trigger) { | ||
167 | u32 val = OMAP_DMA_CCR_REG(lch); | ||
168 | |||
169 | if (dma_trigger > 63) | ||
170 | val |= 1 << 20; | ||
171 | if (dma_trigger > 31) | ||
172 | val |= 1 << 19; | ||
132 | 173 | ||
133 | w = omap_readw(OMAP_DMA_CCR(lch)); | 174 | val |= (dma_trigger & 0x1f); |
134 | w &= ~(1 << 5); | ||
135 | if (sync_mode == OMAP_DMA_SYNC_FRAME) | ||
136 | w |= 1 << 5; | ||
137 | omap_writew(w, OMAP_DMA_CCR(lch)); | ||
138 | 175 | ||
139 | w = omap_readw(OMAP_DMA_CCR2(lch)); | 176 | if (sync_mode & OMAP_DMA_SYNC_FRAME) |
140 | w &= ~(1 << 2); | 177 | val |= 1 << 5; |
141 | if (sync_mode == OMAP_DMA_SYNC_BLOCK) | ||
142 | w |= 1 << 2; | ||
143 | omap_writew(w, OMAP_DMA_CCR2(lch)); | ||
144 | 178 | ||
145 | omap_writew(elem_count, OMAP_DMA_CEN(lch)); | 179 | if (sync_mode & OMAP_DMA_SYNC_BLOCK) |
146 | omap_writew(frame_count, OMAP_DMA_CFN(lch)); | 180 | val |= 1 << 18; |
147 | 181 | ||
182 | if (src_or_dst_synch) | ||
183 | val |= 1 << 24; /* source synch */ | ||
184 | else | ||
185 | val &= ~(1 << 24); /* dest synch */ | ||
186 | |||
187 | OMAP_DMA_CCR_REG(lch) = val; | ||
188 | } | ||
189 | |||
190 | OMAP_DMA_CEN_REG(lch) = elem_count; | ||
191 | OMAP_DMA_CFN_REG(lch) = frame_count; | ||
148 | } | 192 | } |
193 | |||
149 | void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color) | 194 | void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color) |
150 | { | 195 | { |
151 | u16 w; | 196 | u16 w; |
152 | 197 | ||
153 | BUG_ON(omap_dma_in_1510_mode()); | 198 | BUG_ON(omap_dma_in_1510_mode()); |
154 | 199 | ||
155 | w = omap_readw(OMAP_DMA_CCR2(lch)) & ~0x03; | 200 | if (cpu_is_omap24xx()) { |
201 | REVISIT_24XX(); | ||
202 | return; | ||
203 | } | ||
204 | |||
205 | w = OMAP1_DMA_CCR2_REG(lch) & ~0x03; | ||
156 | switch (mode) { | 206 | switch (mode) { |
157 | case OMAP_DMA_CONSTANT_FILL: | 207 | case OMAP_DMA_CONSTANT_FILL: |
158 | w |= 0x01; | 208 | w |= 0x01; |
@@ -165,63 +215,84 @@ void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color) | |||
165 | default: | 215 | default: |
166 | BUG(); | 216 | BUG(); |
167 | } | 217 | } |
168 | omap_writew(w, OMAP_DMA_CCR2(lch)); | 218 | OMAP1_DMA_CCR2_REG(lch) = w; |
169 | 219 | ||
170 | w = omap_readw(OMAP_DMA_LCH_CTRL(lch)) & ~0x0f; | 220 | w = OMAP1_DMA_LCH_CTRL_REG(lch) & ~0x0f; |
171 | /* Default is channel type 2D */ | 221 | /* Default is channel type 2D */ |
172 | if (mode) { | 222 | if (mode) { |
173 | omap_writew((u16)color, OMAP_DMA_COLOR_L(lch)); | 223 | OMAP1_DMA_COLOR_L_REG(lch) = (u16)color; |
174 | omap_writew((u16)(color >> 16), OMAP_DMA_COLOR_U(lch)); | 224 | OMAP1_DMA_COLOR_U_REG(lch) = (u16)(color >> 16); |
175 | w |= 1; /* Channel type G */ | 225 | w |= 1; /* Channel type G */ |
176 | } | 226 | } |
177 | omap_writew(w, OMAP_DMA_LCH_CTRL(lch)); | 227 | OMAP1_DMA_LCH_CTRL_REG(lch) = w; |
178 | } | 228 | } |
179 | 229 | ||
180 | 230 | /* Note that src_port is only for omap1 */ | |
181 | void omap_set_dma_src_params(int lch, int src_port, int src_amode, | 231 | void omap_set_dma_src_params(int lch, int src_port, int src_amode, |
182 | unsigned long src_start) | 232 | unsigned long src_start, |
233 | int src_ei, int src_fi) | ||
183 | { | 234 | { |
184 | u16 w; | 235 | if (cpu_class_is_omap1()) { |
236 | OMAP_DMA_CSDP_REG(lch) &= ~(0x1f << 2); | ||
237 | OMAP_DMA_CSDP_REG(lch) |= src_port << 2; | ||
238 | } | ||
239 | |||
240 | OMAP_DMA_CCR_REG(lch) &= ~(0x03 << 12); | ||
241 | OMAP_DMA_CCR_REG(lch) |= src_amode << 12; | ||
242 | |||
243 | if (cpu_class_is_omap1()) { | ||
244 | OMAP1_DMA_CSSA_U_REG(lch) = src_start >> 16; | ||
245 | OMAP1_DMA_CSSA_L_REG(lch) = src_start; | ||
246 | } | ||
185 | 247 | ||
186 | w = omap_readw(OMAP_DMA_CSDP(lch)); | 248 | if (cpu_is_omap24xx()) |
187 | w &= ~(0x1f << 2); | 249 | OMAP2_DMA_CSSA_REG(lch) = src_start; |
188 | w |= src_port << 2; | ||
189 | omap_writew(w, OMAP_DMA_CSDP(lch)); | ||
190 | 250 | ||
191 | w = omap_readw(OMAP_DMA_CCR(lch)); | 251 | OMAP_DMA_CSEI_REG(lch) = src_ei; |
192 | w &= ~(0x03 << 12); | 252 | OMAP_DMA_CSFI_REG(lch) = src_fi; |
193 | w |= src_amode << 12; | 253 | } |
194 | omap_writew(w, OMAP_DMA_CCR(lch)); | ||
195 | 254 | ||
196 | omap_writew(src_start >> 16, OMAP_DMA_CSSA_U(lch)); | 255 | void omap_set_dma_params(int lch, struct omap_dma_channel_params * params) |
197 | omap_writew(src_start, OMAP_DMA_CSSA_L(lch)); | 256 | { |
257 | omap_set_dma_transfer_params(lch, params->data_type, | ||
258 | params->elem_count, params->frame_count, | ||
259 | params->sync_mode, params->trigger, | ||
260 | params->src_or_dst_synch); | ||
261 | omap_set_dma_src_params(lch, params->src_port, | ||
262 | params->src_amode, params->src_start, | ||
263 | params->src_ei, params->src_fi); | ||
264 | |||
265 | omap_set_dma_dest_params(lch, params->dst_port, | ||
266 | params->dst_amode, params->dst_start, | ||
267 | params->dst_ei, params->dst_fi); | ||
198 | } | 268 | } |
199 | 269 | ||
200 | void omap_set_dma_src_index(int lch, int eidx, int fidx) | 270 | void omap_set_dma_src_index(int lch, int eidx, int fidx) |
201 | { | 271 | { |
202 | omap_writew(eidx, OMAP_DMA_CSEI(lch)); | 272 | if (cpu_is_omap24xx()) { |
203 | omap_writew(fidx, OMAP_DMA_CSFI(lch)); | 273 | REVISIT_24XX(); |
274 | return; | ||
275 | } | ||
276 | OMAP_DMA_CSEI_REG(lch) = eidx; | ||
277 | OMAP_DMA_CSFI_REG(lch) = fidx; | ||
204 | } | 278 | } |
205 | 279 | ||
206 | void omap_set_dma_src_data_pack(int lch, int enable) | 280 | void omap_set_dma_src_data_pack(int lch, int enable) |
207 | { | 281 | { |
208 | u16 w; | 282 | OMAP_DMA_CSDP_REG(lch) &= ~(1 << 6); |
209 | 283 | if (enable) | |
210 | w = omap_readw(OMAP_DMA_CSDP(lch)) & ~(1 << 6); | 284 | OMAP_DMA_CSDP_REG(lch) |= (1 << 6); |
211 | w |= enable ? (1 << 6) : 0; | ||
212 | omap_writew(w, OMAP_DMA_CSDP(lch)); | ||
213 | } | 285 | } |
214 | 286 | ||
215 | void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode) | 287 | void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode) |
216 | { | 288 | { |
217 | u16 w; | 289 | OMAP_DMA_CSDP_REG(lch) &= ~(0x03 << 7); |
218 | 290 | ||
219 | w = omap_readw(OMAP_DMA_CSDP(lch)) & ~(0x03 << 7); | ||
220 | switch (burst_mode) { | 291 | switch (burst_mode) { |
221 | case OMAP_DMA_DATA_BURST_DIS: | 292 | case OMAP_DMA_DATA_BURST_DIS: |
222 | break; | 293 | break; |
223 | case OMAP_DMA_DATA_BURST_4: | 294 | case OMAP_DMA_DATA_BURST_4: |
224 | w |= (0x01 << 7); | 295 | OMAP_DMA_CSDP_REG(lch) |= (0x02 << 7); |
225 | break; | 296 | break; |
226 | case OMAP_DMA_DATA_BURST_8: | 297 | case OMAP_DMA_DATA_BURST_8: |
227 | /* not supported by current hardware | 298 | /* not supported by current hardware |
@@ -231,110 +302,283 @@ void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode) | |||
231 | default: | 302 | default: |
232 | BUG(); | 303 | BUG(); |
233 | } | 304 | } |
234 | omap_writew(w, OMAP_DMA_CSDP(lch)); | ||
235 | } | 305 | } |
236 | 306 | ||
307 | /* Note that dest_port is only for OMAP1 */ | ||
237 | void omap_set_dma_dest_params(int lch, int dest_port, int dest_amode, | 308 | void omap_set_dma_dest_params(int lch, int dest_port, int dest_amode, |
238 | unsigned long dest_start) | 309 | unsigned long dest_start, |
310 | int dst_ei, int dst_fi) | ||
239 | { | 311 | { |
240 | u16 w; | 312 | if (cpu_class_is_omap1()) { |
313 | OMAP_DMA_CSDP_REG(lch) &= ~(0x1f << 9); | ||
314 | OMAP_DMA_CSDP_REG(lch) |= dest_port << 9; | ||
315 | } | ||
241 | 316 | ||
242 | w = omap_readw(OMAP_DMA_CSDP(lch)); | 317 | OMAP_DMA_CCR_REG(lch) &= ~(0x03 << 14); |
243 | w &= ~(0x1f << 9); | 318 | OMAP_DMA_CCR_REG(lch) |= dest_amode << 14; |
244 | w |= dest_port << 9; | 319 | |
245 | omap_writew(w, OMAP_DMA_CSDP(lch)); | 320 | if (cpu_class_is_omap1()) { |
321 | OMAP1_DMA_CDSA_U_REG(lch) = dest_start >> 16; | ||
322 | OMAP1_DMA_CDSA_L_REG(lch) = dest_start; | ||
323 | } | ||
246 | 324 | ||
247 | w = omap_readw(OMAP_DMA_CCR(lch)); | 325 | if (cpu_is_omap24xx()) |
248 | w &= ~(0x03 << 14); | 326 | OMAP2_DMA_CDSA_REG(lch) = dest_start; |
249 | w |= dest_amode << 14; | ||
250 | omap_writew(w, OMAP_DMA_CCR(lch)); | ||
251 | 327 | ||
252 | omap_writew(dest_start >> 16, OMAP_DMA_CDSA_U(lch)); | 328 | OMAP_DMA_CDEI_REG(lch) = dst_ei; |
253 | omap_writew(dest_start, OMAP_DMA_CDSA_L(lch)); | 329 | OMAP_DMA_CDFI_REG(lch) = dst_fi; |
254 | } | 330 | } |
255 | 331 | ||
256 | void omap_set_dma_dest_index(int lch, int eidx, int fidx) | 332 | void omap_set_dma_dest_index(int lch, int eidx, int fidx) |
257 | { | 333 | { |
258 | omap_writew(eidx, OMAP_DMA_CDEI(lch)); | 334 | if (cpu_is_omap24xx()) { |
259 | omap_writew(fidx, OMAP_DMA_CDFI(lch)); | 335 | REVISIT_24XX(); |
336 | return; | ||
337 | } | ||
338 | OMAP_DMA_CDEI_REG(lch) = eidx; | ||
339 | OMAP_DMA_CDFI_REG(lch) = fidx; | ||
260 | } | 340 | } |
261 | 341 | ||
262 | void omap_set_dma_dest_data_pack(int lch, int enable) | 342 | void omap_set_dma_dest_data_pack(int lch, int enable) |
263 | { | 343 | { |
264 | u16 w; | 344 | OMAP_DMA_CSDP_REG(lch) &= ~(1 << 13); |
265 | 345 | if (enable) | |
266 | w = omap_readw(OMAP_DMA_CSDP(lch)) & ~(1 << 13); | 346 | OMAP_DMA_CSDP_REG(lch) |= 1 << 13; |
267 | w |= enable ? (1 << 13) : 0; | ||
268 | omap_writew(w, OMAP_DMA_CSDP(lch)); | ||
269 | } | 347 | } |
270 | 348 | ||
271 | void omap_set_dma_dest_burst_mode(int lch, enum omap_dma_burst_mode burst_mode) | 349 | void omap_set_dma_dest_burst_mode(int lch, enum omap_dma_burst_mode burst_mode) |
272 | { | 350 | { |
273 | u16 w; | 351 | OMAP_DMA_CSDP_REG(lch) &= ~(0x03 << 14); |
274 | 352 | ||
275 | w = omap_readw(OMAP_DMA_CSDP(lch)) & ~(0x03 << 14); | ||
276 | switch (burst_mode) { | 353 | switch (burst_mode) { |
277 | case OMAP_DMA_DATA_BURST_DIS: | 354 | case OMAP_DMA_DATA_BURST_DIS: |
278 | break; | 355 | break; |
279 | case OMAP_DMA_DATA_BURST_4: | 356 | case OMAP_DMA_DATA_BURST_4: |
280 | w |= (0x01 << 14); | 357 | OMAP_DMA_CSDP_REG(lch) |= (0x02 << 14); |
281 | break; | 358 | break; |
282 | case OMAP_DMA_DATA_BURST_8: | 359 | case OMAP_DMA_DATA_BURST_8: |
283 | w |= (0x03 << 14); | 360 | OMAP_DMA_CSDP_REG(lch) |= (0x03 << 14); |
284 | break; | 361 | break; |
285 | default: | 362 | default: |
286 | printk(KERN_ERR "Invalid DMA burst mode\n"); | 363 | printk(KERN_ERR "Invalid DMA burst mode\n"); |
287 | BUG(); | 364 | BUG(); |
288 | return; | 365 | return; |
289 | } | 366 | } |
290 | omap_writew(w, OMAP_DMA_CSDP(lch)); | ||
291 | } | 367 | } |
292 | 368 | ||
293 | static inline void init_intr(int lch) | 369 | static inline void omap_enable_channel_irq(int lch) |
294 | { | 370 | { |
295 | u16 w; | 371 | u32 status; |
296 | 372 | ||
297 | /* Read CSR to make sure it's cleared. */ | 373 | /* Read CSR to make sure it's cleared. */ |
298 | w = omap_readw(OMAP_DMA_CSR(lch)); | 374 | status = OMAP_DMA_CSR_REG(lch); |
375 | |||
299 | /* Enable some nice interrupts. */ | 376 | /* Enable some nice interrupts. */ |
300 | omap_writew(dma_chan[lch].enabled_irqs, OMAP_DMA_CICR(lch)); | 377 | OMAP_DMA_CICR_REG(lch) = dma_chan[lch].enabled_irqs; |
378 | |||
301 | dma_chan[lch].flags |= OMAP_DMA_ACTIVE; | 379 | dma_chan[lch].flags |= OMAP_DMA_ACTIVE; |
302 | } | 380 | } |
303 | 381 | ||
304 | static inline void enable_lnk(int lch) | 382 | static void omap_disable_channel_irq(int lch) |
305 | { | 383 | { |
306 | u16 w; | 384 | if (cpu_is_omap24xx()) |
385 | OMAP_DMA_CICR_REG(lch) = 0; | ||
386 | } | ||
387 | |||
388 | void omap_enable_dma_irq(int lch, u16 bits) | ||
389 | { | ||
390 | dma_chan[lch].enabled_irqs |= bits; | ||
391 | } | ||
307 | 392 | ||
308 | /* Clear the STOP_LNK bits */ | 393 | void omap_disable_dma_irq(int lch, u16 bits) |
309 | w = omap_readw(OMAP_DMA_CLNK_CTRL(lch)); | 394 | { |
310 | w &= ~(1 << 14); | 395 | dma_chan[lch].enabled_irqs &= ~bits; |
311 | omap_writew(w, OMAP_DMA_CLNK_CTRL(lch)); | 396 | } |
397 | |||
398 | static inline void enable_lnk(int lch) | ||
399 | { | ||
400 | if (cpu_class_is_omap1()) | ||
401 | OMAP_DMA_CLNK_CTRL_REG(lch) &= ~(1 << 14); | ||
312 | 402 | ||
313 | /* And set the ENABLE_LNK bits */ | 403 | /* Set the ENABLE_LNK bits */ |
314 | if (dma_chan[lch].next_lch != -1) | 404 | if (dma_chan[lch].next_lch != -1) |
315 | omap_writew(dma_chan[lch].next_lch | (1 << 15), | 405 | OMAP_DMA_CLNK_CTRL_REG(lch) = |
316 | OMAP_DMA_CLNK_CTRL(lch)); | 406 | dma_chan[lch].next_lch | (1 << 15); |
317 | } | 407 | } |
318 | 408 | ||
319 | static inline void disable_lnk(int lch) | 409 | static inline void disable_lnk(int lch) |
320 | { | 410 | { |
321 | u16 w; | ||
322 | |||
323 | /* Disable interrupts */ | 411 | /* Disable interrupts */ |
324 | omap_writew(0, OMAP_DMA_CICR(lch)); | 412 | if (cpu_class_is_omap1()) { |
413 | OMAP_DMA_CICR_REG(lch) = 0; | ||
414 | /* Set the STOP_LNK bit */ | ||
415 | OMAP_DMA_CLNK_CTRL_REG(lch) |= 1 << 14; | ||
416 | } | ||
325 | 417 | ||
326 | /* Set the STOP_LNK bit */ | 418 | if (cpu_is_omap24xx()) { |
327 | w = omap_readw(OMAP_DMA_CLNK_CTRL(lch)); | 419 | omap_disable_channel_irq(lch); |
328 | w |= (1 << 14); | 420 | /* Clear the ENABLE_LNK bit */ |
329 | w = omap_writew(w, OMAP_DMA_CLNK_CTRL(lch)); | 421 | OMAP_DMA_CLNK_CTRL_REG(lch) &= ~(1 << 15); |
422 | } | ||
330 | 423 | ||
331 | dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE; | 424 | dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE; |
332 | } | 425 | } |
333 | 426 | ||
334 | void omap_start_dma(int lch) | 427 | static inline void omap2_enable_irq_lch(int lch) |
335 | { | 428 | { |
336 | u16 w; | 429 | u32 val; |
430 | |||
431 | if (!cpu_is_omap24xx()) | ||
432 | return; | ||
433 | |||
434 | val = omap_readl(OMAP_DMA4_IRQENABLE_L0); | ||
435 | val |= 1 << lch; | ||
436 | omap_writel(val, OMAP_DMA4_IRQENABLE_L0); | ||
437 | } | ||
438 | |||
439 | int omap_request_dma(int dev_id, const char *dev_name, | ||
440 | void (* callback)(int lch, u16 ch_status, void *data), | ||
441 | void *data, int *dma_ch_out) | ||
442 | { | ||
443 | int ch, free_ch = -1; | ||
444 | unsigned long flags; | ||
445 | struct omap_dma_lch *chan; | ||
446 | |||
447 | spin_lock_irqsave(&dma_chan_lock, flags); | ||
448 | for (ch = 0; ch < dma_chan_count; ch++) { | ||
449 | if (free_ch == -1 && dma_chan[ch].dev_id == -1) { | ||
450 | free_ch = ch; | ||
451 | if (dev_id == 0) | ||
452 | break; | ||
453 | } | ||
454 | } | ||
455 | if (free_ch == -1) { | ||
456 | spin_unlock_irqrestore(&dma_chan_lock, flags); | ||
457 | return -EBUSY; | ||
458 | } | ||
459 | chan = dma_chan + free_ch; | ||
460 | chan->dev_id = dev_id; | ||
461 | |||
462 | if (cpu_class_is_omap1()) | ||
463 | clear_lch_regs(free_ch); | ||
337 | 464 | ||
465 | if (cpu_is_omap24xx()) | ||
466 | omap_clear_dma(free_ch); | ||
467 | |||
468 | spin_unlock_irqrestore(&dma_chan_lock, flags); | ||
469 | |||
470 | chan->dev_name = dev_name; | ||
471 | chan->callback = callback; | ||
472 | chan->data = data; | ||
473 | chan->enabled_irqs = OMAP_DMA_TOUT_IRQ | OMAP_DMA_DROP_IRQ | | ||
474 | OMAP_DMA_BLOCK_IRQ; | ||
475 | |||
476 | if (cpu_is_omap24xx()) | ||
477 | chan->enabled_irqs |= OMAP2_DMA_TRANS_ERR_IRQ; | ||
478 | |||
479 | if (cpu_is_omap16xx()) { | ||
480 | /* If the sync device is set, configure it dynamically. */ | ||
481 | if (dev_id != 0) { | ||
482 | set_gdma_dev(free_ch + 1, dev_id); | ||
483 | dev_id = free_ch + 1; | ||
484 | } | ||
485 | /* Disable the 1510 compatibility mode and set the sync device | ||
486 | * id. */ | ||
487 | OMAP_DMA_CCR_REG(free_ch) = dev_id | (1 << 10); | ||
488 | } else if (cpu_is_omap730() || cpu_is_omap15xx()) { | ||
489 | OMAP_DMA_CCR_REG(free_ch) = dev_id; | ||
490 | } | ||
491 | |||
492 | if (cpu_is_omap24xx()) { | ||
493 | omap2_enable_irq_lch(free_ch); | ||
494 | |||
495 | omap_enable_channel_irq(free_ch); | ||
496 | /* Clear the CSR register and IRQ status register */ | ||
497 | OMAP_DMA_CSR_REG(free_ch) = 0x0; | ||
498 | omap_writel(~0x0, OMAP_DMA4_IRQSTATUS_L0); | ||
499 | } | ||
500 | |||
501 | *dma_ch_out = free_ch; | ||
502 | |||
503 | return 0; | ||
504 | } | ||
505 | |||
506 | void omap_free_dma(int lch) | ||
507 | { | ||
508 | unsigned long flags; | ||
509 | |||
510 | spin_lock_irqsave(&dma_chan_lock, flags); | ||
511 | if (dma_chan[lch].dev_id == -1) { | ||
512 | printk("omap_dma: trying to free nonallocated DMA channel %d\n", | ||
513 | lch); | ||
514 | spin_unlock_irqrestore(&dma_chan_lock, flags); | ||
515 | return; | ||
516 | } | ||
517 | dma_chan[lch].dev_id = -1; | ||
518 | dma_chan[lch].next_lch = -1; | ||
519 | dma_chan[lch].callback = NULL; | ||
520 | spin_unlock_irqrestore(&dma_chan_lock, flags); | ||
521 | |||
522 | if (cpu_class_is_omap1()) { | ||
523 | /* Disable all DMA interrupts for the channel. */ | ||
524 | OMAP_DMA_CICR_REG(lch) = 0; | ||
525 | /* Make sure the DMA transfer is stopped. */ | ||
526 | OMAP_DMA_CCR_REG(lch) = 0; | ||
527 | } | ||
528 | |||
529 | if (cpu_is_omap24xx()) { | ||
530 | u32 val; | ||
531 | /* Disable interrupts */ | ||
532 | val = omap_readl(OMAP_DMA4_IRQENABLE_L0); | ||
533 | val &= ~(1 << lch); | ||
534 | omap_writel(val, OMAP_DMA4_IRQENABLE_L0); | ||
535 | |||
536 | /* Clear the CSR register and IRQ status register */ | ||
537 | OMAP_DMA_CSR_REG(lch) = 0x0; | ||
538 | |||
539 | val = omap_readl(OMAP_DMA4_IRQSTATUS_L0); | ||
540 | val |= 1 << lch; | ||
541 | omap_writel(val, OMAP_DMA4_IRQSTATUS_L0); | ||
542 | |||
543 | /* Disable all DMA interrupts for the channel. */ | ||
544 | OMAP_DMA_CICR_REG(lch) = 0; | ||
545 | |||
546 | /* Make sure the DMA transfer is stopped. */ | ||
547 | OMAP_DMA_CCR_REG(lch) = 0; | ||
548 | omap_clear_dma(lch); | ||
549 | } | ||
550 | } | ||
551 | |||
552 | /* | ||
553 | * Clears any DMA state so the DMA engine is ready to restart with new buffers | ||
554 | * through omap_start_dma(). Any buffers in flight are discarded. | ||
555 | */ | ||
556 | void omap_clear_dma(int lch) | ||
557 | { | ||
558 | unsigned long flags; | ||
559 | |||
560 | local_irq_save(flags); | ||
561 | |||
562 | if (cpu_class_is_omap1()) { | ||
563 | int status; | ||
564 | OMAP_DMA_CCR_REG(lch) &= ~OMAP_DMA_CCR_EN; | ||
565 | |||
566 | /* Clear pending interrupts */ | ||
567 | status = OMAP_DMA_CSR_REG(lch); | ||
568 | } | ||
569 | |||
570 | if (cpu_is_omap24xx()) { | ||
571 | int i; | ||
572 | u32 lch_base = OMAP24XX_DMA_BASE + lch * 0x60 + 0x80; | ||
573 | for (i = 0; i < 0x44; i += 4) | ||
574 | omap_writel(0, lch_base + i); | ||
575 | } | ||
576 | |||
577 | local_irq_restore(flags); | ||
578 | } | ||
579 | |||
580 | void omap_start_dma(int lch) | ||
581 | { | ||
338 | if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) { | 582 | if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) { |
339 | int next_lch, cur_lch; | 583 | int next_lch, cur_lch; |
340 | char dma_chan_link_map[OMAP_LOGICAL_DMA_CH_COUNT]; | 584 | char dma_chan_link_map[OMAP_LOGICAL_DMA_CH_COUNT]; |
@@ -348,31 +592,37 @@ void omap_start_dma(int lch) | |||
348 | do { | 592 | do { |
349 | next_lch = dma_chan[cur_lch].next_lch; | 593 | next_lch = dma_chan[cur_lch].next_lch; |
350 | 594 | ||
351 | /* The loop case: we've been here already */ | 595 | /* The loop case: we've been here already */ |
352 | if (dma_chan_link_map[cur_lch]) | 596 | if (dma_chan_link_map[cur_lch]) |
353 | break; | 597 | break; |
354 | /* Mark the current channel */ | 598 | /* Mark the current channel */ |
355 | dma_chan_link_map[cur_lch] = 1; | 599 | dma_chan_link_map[cur_lch] = 1; |
356 | 600 | ||
357 | enable_lnk(cur_lch); | 601 | enable_lnk(cur_lch); |
358 | init_intr(cur_lch); | 602 | omap_enable_channel_irq(cur_lch); |
359 | 603 | ||
360 | cur_lch = next_lch; | 604 | cur_lch = next_lch; |
361 | } while (next_lch != -1); | 605 | } while (next_lch != -1); |
606 | } else if (cpu_is_omap24xx()) { | ||
607 | /* Errata: Need to write lch even if not using chaining */ | ||
608 | OMAP_DMA_CLNK_CTRL_REG(lch) = lch; | ||
362 | } | 609 | } |
363 | 610 | ||
364 | init_intr(lch); | 611 | omap_enable_channel_irq(lch); |
612 | |||
613 | /* Errata: On ES2.0 BUFFERING disable must be set. | ||
614 | * This will always fail on ES1.0 */ | ||
615 | if (cpu_is_omap24xx()) { | ||
616 | OMAP_DMA_CCR_REG(lch) |= OMAP_DMA_CCR_EN; | ||
617 | } | ||
618 | |||
619 | OMAP_DMA_CCR_REG(lch) |= OMAP_DMA_CCR_EN; | ||
365 | 620 | ||
366 | w = omap_readw(OMAP_DMA_CCR(lch)); | ||
367 | w |= OMAP_DMA_CCR_EN; | ||
368 | omap_writew(w, OMAP_DMA_CCR(lch)); | ||
369 | dma_chan[lch].flags |= OMAP_DMA_ACTIVE; | 621 | dma_chan[lch].flags |= OMAP_DMA_ACTIVE; |
370 | } | 622 | } |
371 | 623 | ||
372 | void omap_stop_dma(int lch) | 624 | void omap_stop_dma(int lch) |
373 | { | 625 | { |
374 | u16 w; | ||
375 | |||
376 | if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) { | 626 | if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) { |
377 | int next_lch, cur_lch = lch; | 627 | int next_lch, cur_lch = lch; |
378 | char dma_chan_link_map[OMAP_LOGICAL_DMA_CH_COUNT]; | 628 | char dma_chan_link_map[OMAP_LOGICAL_DMA_CH_COUNT]; |
@@ -393,146 +643,83 @@ void omap_stop_dma(int lch) | |||
393 | 643 | ||
394 | return; | 644 | return; |
395 | } | 645 | } |
646 | |||
396 | /* Disable all interrupts on the channel */ | 647 | /* Disable all interrupts on the channel */ |
397 | omap_writew(0, OMAP_DMA_CICR(lch)); | 648 | if (cpu_class_is_omap1()) |
649 | OMAP_DMA_CICR_REG(lch) = 0; | ||
398 | 650 | ||
399 | w = omap_readw(OMAP_DMA_CCR(lch)); | 651 | OMAP_DMA_CCR_REG(lch) &= ~OMAP_DMA_CCR_EN; |
400 | w &= ~OMAP_DMA_CCR_EN; | ||
401 | omap_writew(w, OMAP_DMA_CCR(lch)); | ||
402 | dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE; | 652 | dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE; |
403 | } | 653 | } |
404 | 654 | ||
405 | void omap_enable_dma_irq(int lch, u16 bits) | 655 | /* |
656 | * Returns current physical source address for the given DMA channel. | ||
657 | * If the channel is running the caller must disable interrupts prior calling | ||
658 | * this function and process the returned value before re-enabling interrupt to | ||
659 | * prevent races with the interrupt handler. Note that in continuous mode there | ||
660 | * is a chance for CSSA_L register overflow inbetween the two reads resulting | ||
661 | * in incorrect return value. | ||
662 | */ | ||
663 | dma_addr_t omap_get_dma_src_pos(int lch) | ||
406 | { | 664 | { |
407 | dma_chan[lch].enabled_irqs |= bits; | 665 | dma_addr_t offset; |
408 | } | ||
409 | 666 | ||
410 | void omap_disable_dma_irq(int lch, u16 bits) | 667 | if (cpu_class_is_omap1()) |
411 | { | 668 | offset = (dma_addr_t) (OMAP1_DMA_CSSA_L_REG(lch) | |
412 | dma_chan[lch].enabled_irqs &= ~bits; | 669 | (OMAP1_DMA_CSSA_U_REG(lch) << 16)); |
413 | } | ||
414 | 670 | ||
415 | static int dma_handle_ch(int ch) | 671 | if (cpu_is_omap24xx()) |
416 | { | 672 | offset = OMAP_DMA_CSAC_REG(lch); |
417 | u16 csr; | ||
418 | 673 | ||
419 | if (enable_1510_mode && ch >= 6) { | 674 | return offset; |
420 | csr = dma_chan[ch].saved_csr; | ||
421 | dma_chan[ch].saved_csr = 0; | ||
422 | } else | ||
423 | csr = omap_readw(OMAP_DMA_CSR(ch)); | ||
424 | if (enable_1510_mode && ch <= 2 && (csr >> 7) != 0) { | ||
425 | dma_chan[ch + 6].saved_csr = csr >> 7; | ||
426 | csr &= 0x7f; | ||
427 | } | ||
428 | if ((csr & 0x3f) == 0) | ||
429 | return 0; | ||
430 | if (unlikely(dma_chan[ch].dev_id == -1)) { | ||
431 | printk(KERN_WARNING "Spurious interrupt from DMA channel %d (CSR %04x)\n", | ||
432 | ch, csr); | ||
433 | return 0; | ||
434 | } | ||
435 | if (unlikely(csr & OMAP_DMA_TOUT_IRQ)) | ||
436 | printk(KERN_WARNING "DMA timeout with device %d\n", dma_chan[ch].dev_id); | ||
437 | if (unlikely(csr & OMAP_DMA_DROP_IRQ)) | ||
438 | printk(KERN_WARNING "DMA synchronization event drop occurred with device %d\n", | ||
439 | dma_chan[ch].dev_id); | ||
440 | if (likely(csr & OMAP_DMA_BLOCK_IRQ)) | ||
441 | dma_chan[ch].flags &= ~OMAP_DMA_ACTIVE; | ||
442 | if (likely(dma_chan[ch].callback != NULL)) | ||
443 | dma_chan[ch].callback(ch, csr, dma_chan[ch].data); | ||
444 | return 1; | ||
445 | } | 675 | } |
446 | 676 | ||
447 | static irqreturn_t dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs) | 677 | /* |
678 | * Returns current physical destination address for the given DMA channel. | ||
679 | * If the channel is running the caller must disable interrupts prior calling | ||
680 | * this function and process the returned value before re-enabling interrupt to | ||
681 | * prevent races with the interrupt handler. Note that in continuous mode there | ||
682 | * is a chance for CDSA_L register overflow inbetween the two reads resulting | ||
683 | * in incorrect return value. | ||
684 | */ | ||
685 | dma_addr_t omap_get_dma_dst_pos(int lch) | ||
448 | { | 686 | { |
449 | int ch = ((int) dev_id) - 1; | 687 | dma_addr_t offset; |
450 | int handled = 0; | ||
451 | 688 | ||
452 | for (;;) { | 689 | if (cpu_class_is_omap1()) |
453 | int handled_now = 0; | 690 | offset = (dma_addr_t) (OMAP1_DMA_CDSA_L_REG(lch) | |
691 | (OMAP1_DMA_CDSA_U_REG(lch) << 16)); | ||
454 | 692 | ||
455 | handled_now += dma_handle_ch(ch); | 693 | if (cpu_is_omap24xx()) |
456 | if (enable_1510_mode && dma_chan[ch + 6].saved_csr) | 694 | offset = OMAP2_DMA_CDSA_REG(lch); |
457 | handled_now += dma_handle_ch(ch + 6); | ||
458 | if (!handled_now) | ||
459 | break; | ||
460 | handled += handled_now; | ||
461 | } | ||
462 | 695 | ||
463 | return handled ? IRQ_HANDLED : IRQ_NONE; | 696 | return offset; |
464 | } | 697 | } |
465 | 698 | ||
466 | int omap_request_dma(int dev_id, const char *dev_name, | 699 | /* |
467 | void (* callback)(int lch, u16 ch_status, void *data), | 700 | * Returns current source transfer counting for the given DMA channel. |
468 | void *data, int *dma_ch_out) | 701 | * Can be used to monitor the progress of a transfer inside a block. |
702 | * It must be called with disabled interrupts. | ||
703 | */ | ||
704 | int omap_get_dma_src_addr_counter(int lch) | ||
469 | { | 705 | { |
470 | int ch, free_ch = -1; | 706 | return (dma_addr_t) OMAP_DMA_CSAC_REG(lch); |
471 | unsigned long flags; | ||
472 | struct omap_dma_lch *chan; | ||
473 | |||
474 | spin_lock_irqsave(&dma_chan_lock, flags); | ||
475 | for (ch = 0; ch < dma_chan_count; ch++) { | ||
476 | if (free_ch == -1 && dma_chan[ch].dev_id == -1) { | ||
477 | free_ch = ch; | ||
478 | if (dev_id == 0) | ||
479 | break; | ||
480 | } | ||
481 | } | ||
482 | if (free_ch == -1) { | ||
483 | spin_unlock_irqrestore(&dma_chan_lock, flags); | ||
484 | return -EBUSY; | ||
485 | } | ||
486 | chan = dma_chan + free_ch; | ||
487 | chan->dev_id = dev_id; | ||
488 | clear_lch_regs(free_ch); | ||
489 | spin_unlock_irqrestore(&dma_chan_lock, flags); | ||
490 | |||
491 | chan->dev_id = dev_id; | ||
492 | chan->dev_name = dev_name; | ||
493 | chan->callback = callback; | ||
494 | chan->data = data; | ||
495 | chan->enabled_irqs = OMAP_DMA_TOUT_IRQ | OMAP_DMA_DROP_IRQ | OMAP_DMA_BLOCK_IRQ; | ||
496 | |||
497 | if (cpu_is_omap16xx()) { | ||
498 | /* If the sync device is set, configure it dynamically. */ | ||
499 | if (dev_id != 0) { | ||
500 | set_gdma_dev(free_ch + 1, dev_id); | ||
501 | dev_id = free_ch + 1; | ||
502 | } | ||
503 | /* Disable the 1510 compatibility mode and set the sync device | ||
504 | * id. */ | ||
505 | omap_writew(dev_id | (1 << 10), OMAP_DMA_CCR(free_ch)); | ||
506 | } else { | ||
507 | omap_writew(dev_id, OMAP_DMA_CCR(free_ch)); | ||
508 | } | ||
509 | *dma_ch_out = free_ch; | ||
510 | |||
511 | return 0; | ||
512 | } | 707 | } |
513 | 708 | ||
514 | void omap_free_dma(int ch) | 709 | int omap_dma_running(void) |
515 | { | 710 | { |
516 | unsigned long flags; | 711 | int lch; |
517 | 712 | ||
518 | spin_lock_irqsave(&dma_chan_lock, flags); | 713 | /* Check if LCD DMA is running */ |
519 | if (dma_chan[ch].dev_id == -1) { | 714 | if (cpu_is_omap16xx()) |
520 | printk("omap_dma: trying to free nonallocated DMA channel %d\n", ch); | 715 | if (omap_readw(OMAP1610_DMA_LCD_CCR) & OMAP_DMA_CCR_EN) |
521 | spin_unlock_irqrestore(&dma_chan_lock, flags); | 716 | return 1; |
522 | return; | ||
523 | } | ||
524 | dma_chan[ch].dev_id = -1; | ||
525 | spin_unlock_irqrestore(&dma_chan_lock, flags); | ||
526 | 717 | ||
527 | /* Disable all DMA interrupts for the channel. */ | 718 | for (lch = 0; lch < dma_chan_count; lch++) |
528 | omap_writew(0, OMAP_DMA_CICR(ch)); | 719 | if (OMAP_DMA_CCR_REG(lch) & OMAP_DMA_CCR_EN) |
529 | /* Make sure the DMA transfer is stopped. */ | 720 | return 1; |
530 | omap_writew(0, OMAP_DMA_CCR(ch)); | ||
531 | } | ||
532 | 721 | ||
533 | int omap_dma_in_1510_mode(void) | 722 | return 0; |
534 | { | ||
535 | return enable_1510_mode; | ||
536 | } | 723 | } |
537 | 724 | ||
538 | /* | 725 | /* |
@@ -550,7 +737,8 @@ void omap_dma_link_lch (int lch_head, int lch_queue) | |||
550 | 737 | ||
551 | if ((dma_chan[lch_head].dev_id == -1) || | 738 | if ((dma_chan[lch_head].dev_id == -1) || |
552 | (dma_chan[lch_queue].dev_id == -1)) { | 739 | (dma_chan[lch_queue].dev_id == -1)) { |
553 | printk(KERN_ERR "omap_dma: trying to link non requested channels\n"); | 740 | printk(KERN_ERR "omap_dma: trying to link " |
741 | "non requested channels\n"); | ||
554 | dump_stack(); | 742 | dump_stack(); |
555 | } | 743 | } |
556 | 744 | ||
@@ -570,20 +758,149 @@ void omap_dma_unlink_lch (int lch_head, int lch_queue) | |||
570 | 758 | ||
571 | if (dma_chan[lch_head].next_lch != lch_queue || | 759 | if (dma_chan[lch_head].next_lch != lch_queue || |
572 | dma_chan[lch_head].next_lch == -1) { | 760 | dma_chan[lch_head].next_lch == -1) { |
573 | printk(KERN_ERR "omap_dma: trying to unlink non linked channels\n"); | 761 | printk(KERN_ERR "omap_dma: trying to unlink " |
762 | "non linked channels\n"); | ||
574 | dump_stack(); | 763 | dump_stack(); |
575 | } | 764 | } |
576 | 765 | ||
577 | 766 | ||
578 | if ((dma_chan[lch_head].flags & OMAP_DMA_ACTIVE) || | 767 | if ((dma_chan[lch_head].flags & OMAP_DMA_ACTIVE) || |
579 | (dma_chan[lch_head].flags & OMAP_DMA_ACTIVE)) { | 768 | (dma_chan[lch_head].flags & OMAP_DMA_ACTIVE)) { |
580 | printk(KERN_ERR "omap_dma: You need to stop the DMA channels before unlinking\n"); | 769 | printk(KERN_ERR "omap_dma: You need to stop the DMA channels " |
770 | "before unlinking\n"); | ||
581 | dump_stack(); | 771 | dump_stack(); |
582 | } | 772 | } |
583 | 773 | ||
584 | dma_chan[lch_head].next_lch = -1; | 774 | dma_chan[lch_head].next_lch = -1; |
585 | } | 775 | } |
586 | 776 | ||
777 | /*----------------------------------------------------------------------------*/ | ||
778 | |||
779 | #ifdef CONFIG_ARCH_OMAP1 | ||
780 | |||
781 | static int omap1_dma_handle_ch(int ch) | ||
782 | { | ||
783 | u16 csr; | ||
784 | |||
785 | if (enable_1510_mode && ch >= 6) { | ||
786 | csr = dma_chan[ch].saved_csr; | ||
787 | dma_chan[ch].saved_csr = 0; | ||
788 | } else | ||
789 | csr = OMAP_DMA_CSR_REG(ch); | ||
790 | if (enable_1510_mode && ch <= 2 && (csr >> 7) != 0) { | ||
791 | dma_chan[ch + 6].saved_csr = csr >> 7; | ||
792 | csr &= 0x7f; | ||
793 | } | ||
794 | if ((csr & 0x3f) == 0) | ||
795 | return 0; | ||
796 | if (unlikely(dma_chan[ch].dev_id == -1)) { | ||
797 | printk(KERN_WARNING "Spurious interrupt from DMA channel " | ||
798 | "%d (CSR %04x)\n", ch, csr); | ||
799 | return 0; | ||
800 | } | ||
801 | if (unlikely(csr & OMAP_DMA_TOUT_IRQ)) | ||
802 | printk(KERN_WARNING "DMA timeout with device %d\n", | ||
803 | dma_chan[ch].dev_id); | ||
804 | if (unlikely(csr & OMAP_DMA_DROP_IRQ)) | ||
805 | printk(KERN_WARNING "DMA synchronization event drop occurred " | ||
806 | "with device %d\n", dma_chan[ch].dev_id); | ||
807 | if (likely(csr & OMAP_DMA_BLOCK_IRQ)) | ||
808 | dma_chan[ch].flags &= ~OMAP_DMA_ACTIVE; | ||
809 | if (likely(dma_chan[ch].callback != NULL)) | ||
810 | dma_chan[ch].callback(ch, csr, dma_chan[ch].data); | ||
811 | return 1; | ||
812 | } | ||
813 | |||
814 | static irqreturn_t omap1_dma_irq_handler(int irq, void *dev_id, | ||
815 | struct pt_regs *regs) | ||
816 | { | ||
817 | int ch = ((int) dev_id) - 1; | ||
818 | int handled = 0; | ||
819 | |||
820 | for (;;) { | ||
821 | int handled_now = 0; | ||
822 | |||
823 | handled_now += omap1_dma_handle_ch(ch); | ||
824 | if (enable_1510_mode && dma_chan[ch + 6].saved_csr) | ||
825 | handled_now += omap1_dma_handle_ch(ch + 6); | ||
826 | if (!handled_now) | ||
827 | break; | ||
828 | handled += handled_now; | ||
829 | } | ||
830 | |||
831 | return handled ? IRQ_HANDLED : IRQ_NONE; | ||
832 | } | ||
833 | |||
834 | #else | ||
835 | #define omap1_dma_irq_handler NULL | ||
836 | #endif | ||
837 | |||
838 | #ifdef CONFIG_ARCH_OMAP2 | ||
839 | |||
840 | static int omap2_dma_handle_ch(int ch) | ||
841 | { | ||
842 | u32 status = OMAP_DMA_CSR_REG(ch); | ||
843 | u32 val; | ||
844 | |||
845 | if (!status) | ||
846 | return 0; | ||
847 | if (unlikely(dma_chan[ch].dev_id == -1)) | ||
848 | return 0; | ||
849 | /* REVISIT: According to 24xx TRM, there's no TOUT_IE */ | ||
850 | if (unlikely(status & OMAP_DMA_TOUT_IRQ)) | ||
851 | printk(KERN_INFO "DMA timeout with device %d\n", | ||
852 | dma_chan[ch].dev_id); | ||
853 | if (unlikely(status & OMAP_DMA_DROP_IRQ)) | ||
854 | printk(KERN_INFO | ||
855 | "DMA synchronization event drop occurred with device " | ||
856 | "%d\n", dma_chan[ch].dev_id); | ||
857 | |||
858 | if (unlikely(status & OMAP2_DMA_TRANS_ERR_IRQ)) | ||
859 | printk(KERN_INFO "DMA transaction error with device %d\n", | ||
860 | dma_chan[ch].dev_id); | ||
861 | |||
862 | OMAP_DMA_CSR_REG(ch) = 0x20; | ||
863 | |||
864 | val = omap_readl(OMAP_DMA4_IRQSTATUS_L0); | ||
865 | /* ch in this function is from 0-31 while in register it is 1-32 */ | ||
866 | val = 1 << (ch); | ||
867 | omap_writel(val, OMAP_DMA4_IRQSTATUS_L0); | ||
868 | |||
869 | if (likely(dma_chan[ch].callback != NULL)) | ||
870 | dma_chan[ch].callback(ch, status, dma_chan[ch].data); | ||
871 | |||
872 | return 0; | ||
873 | } | ||
874 | |||
875 | /* STATUS register count is from 1-32 while our is 0-31 */ | ||
876 | static irqreturn_t omap2_dma_irq_handler(int irq, void *dev_id, | ||
877 | struct pt_regs *regs) | ||
878 | { | ||
879 | u32 val; | ||
880 | int i; | ||
881 | |||
882 | val = omap_readl(OMAP_DMA4_IRQSTATUS_L0); | ||
883 | |||
884 | for (i = 1; i <= OMAP_LOGICAL_DMA_CH_COUNT; i++) { | ||
885 | int active = val & (1 << (i - 1)); | ||
886 | if (active) | ||
887 | omap2_dma_handle_ch(i - 1); | ||
888 | } | ||
889 | |||
890 | return IRQ_HANDLED; | ||
891 | } | ||
892 | |||
893 | static struct irqaction omap24xx_dma_irq = { | ||
894 | .name = "DMA", | ||
895 | .handler = omap2_dma_irq_handler, | ||
896 | .flags = SA_INTERRUPT | ||
897 | }; | ||
898 | |||
899 | #else | ||
900 | static struct irqaction omap24xx_dma_irq; | ||
901 | #endif | ||
902 | |||
903 | /*----------------------------------------------------------------------------*/ | ||
587 | 904 | ||
588 | static struct lcd_dma_info { | 905 | static struct lcd_dma_info { |
589 | spinlock_t lock; | 906 | spinlock_t lock; |
@@ -795,7 +1112,7 @@ static void set_b1_regs(void) | |||
795 | /* Always set the source port as SDRAM for now*/ | 1112 | /* Always set the source port as SDRAM for now*/ |
796 | w &= ~(0x03 << 6); | 1113 | w &= ~(0x03 << 6); |
797 | if (lcd_dma.callback != NULL) | 1114 | if (lcd_dma.callback != NULL) |
798 | w |= 1 << 1; /* Block interrupt enable */ | 1115 | w |= 1 << 1; /* Block interrupt enable */ |
799 | else | 1116 | else |
800 | w &= ~(1 << 1); | 1117 | w &= ~(1 << 1); |
801 | omap_writew(w, OMAP1610_DMA_LCD_CTRL); | 1118 | omap_writew(w, OMAP1610_DMA_LCD_CTRL); |
@@ -814,7 +1131,8 @@ static void set_b1_regs(void) | |||
814 | omap_writew(fi, OMAP1610_DMA_LCD_SRC_FI_B1_L); | 1131 | omap_writew(fi, OMAP1610_DMA_LCD_SRC_FI_B1_L); |
815 | } | 1132 | } |
816 | 1133 | ||
817 | static irqreturn_t lcd_dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs) | 1134 | static irqreturn_t lcd_dma_irq_handler(int irq, void *dev_id, |
1135 | struct pt_regs *regs) | ||
818 | { | 1136 | { |
819 | u16 w; | 1137 | u16 w; |
820 | 1138 | ||
@@ -870,7 +1188,8 @@ void omap_free_lcd_dma(void) | |||
870 | return; | 1188 | return; |
871 | } | 1189 | } |
872 | if (!enable_1510_mode) | 1190 | if (!enable_1510_mode) |
873 | omap_writew(omap_readw(OMAP1610_DMA_LCD_CCR) & ~1, OMAP1610_DMA_LCD_CCR); | 1191 | omap_writew(omap_readw(OMAP1610_DMA_LCD_CCR) & ~1, |
1192 | OMAP1610_DMA_LCD_CCR); | ||
874 | lcd_dma.reserved = 0; | 1193 | lcd_dma.reserved = 0; |
875 | spin_unlock(&lcd_dma.lock); | 1194 | spin_unlock(&lcd_dma.lock); |
876 | } | 1195 | } |
@@ -939,93 +1258,24 @@ void omap_stop_lcd_dma(void) | |||
939 | omap_writew(w, OMAP1610_DMA_LCD_CTRL); | 1258 | omap_writew(w, OMAP1610_DMA_LCD_CTRL); |
940 | } | 1259 | } |
941 | 1260 | ||
942 | /* | 1261 | /*----------------------------------------------------------------------------*/ |
943 | * Clears any DMA state so the DMA engine is ready to restart with new buffers | ||
944 | * through omap_start_dma(). Any buffers in flight are discarded. | ||
945 | */ | ||
946 | void omap_clear_dma(int lch) | ||
947 | { | ||
948 | unsigned long flags; | ||
949 | int status; | ||
950 | |||
951 | local_irq_save(flags); | ||
952 | omap_writew(omap_readw(OMAP_DMA_CCR(lch)) & ~OMAP_DMA_CCR_EN, | ||
953 | OMAP_DMA_CCR(lch)); | ||
954 | status = OMAP_DMA_CSR(lch); /* clear pending interrupts */ | ||
955 | local_irq_restore(flags); | ||
956 | } | ||
957 | |||
958 | /* | ||
959 | * Returns current physical source address for the given DMA channel. | ||
960 | * If the channel is running the caller must disable interrupts prior calling | ||
961 | * this function and process the returned value before re-enabling interrupt to | ||
962 | * prevent races with the interrupt handler. Note that in continuous mode there | ||
963 | * is a chance for CSSA_L register overflow inbetween the two reads resulting | ||
964 | * in incorrect return value. | ||
965 | */ | ||
966 | dma_addr_t omap_get_dma_src_pos(int lch) | ||
967 | { | ||
968 | return (dma_addr_t) (omap_readw(OMAP_DMA_CSSA_L(lch)) | | ||
969 | (omap_readw(OMAP_DMA_CSSA_U(lch)) << 16)); | ||
970 | } | ||
971 | |||
972 | /* | ||
973 | * Returns current physical destination address for the given DMA channel. | ||
974 | * If the channel is running the caller must disable interrupts prior calling | ||
975 | * this function and process the returned value before re-enabling interrupt to | ||
976 | * prevent races with the interrupt handler. Note that in continuous mode there | ||
977 | * is a chance for CDSA_L register overflow inbetween the two reads resulting | ||
978 | * in incorrect return value. | ||
979 | */ | ||
980 | dma_addr_t omap_get_dma_dst_pos(int lch) | ||
981 | { | ||
982 | return (dma_addr_t) (omap_readw(OMAP_DMA_CDSA_L(lch)) | | ||
983 | (omap_readw(OMAP_DMA_CDSA_U(lch)) << 16)); | ||
984 | } | ||
985 | |||
986 | /* | ||
987 | * Returns current source transfer counting for the given DMA channel. | ||
988 | * Can be used to monitor the progress of a transfer inside a block. | ||
989 | * It must be called with disabled interrupts. | ||
990 | */ | ||
991 | int omap_get_dma_src_addr_counter(int lch) | ||
992 | { | ||
993 | return (dma_addr_t) omap_readw(OMAP_DMA_CSAC(lch)); | ||
994 | } | ||
995 | |||
996 | int omap_dma_running(void) | ||
997 | { | ||
998 | int lch; | ||
999 | |||
1000 | /* Check if LCD DMA is running */ | ||
1001 | if (cpu_is_omap16xx()) | ||
1002 | if (omap_readw(OMAP1610_DMA_LCD_CCR) & OMAP_DMA_CCR_EN) | ||
1003 | return 1; | ||
1004 | |||
1005 | for (lch = 0; lch < dma_chan_count; lch++) { | ||
1006 | u16 w; | ||
1007 | |||
1008 | w = omap_readw(OMAP_DMA_CCR(lch)); | ||
1009 | if (w & OMAP_DMA_CCR_EN) | ||
1010 | return 1; | ||
1011 | } | ||
1012 | return 0; | ||
1013 | } | ||
1014 | 1262 | ||
1015 | static int __init omap_init_dma(void) | 1263 | static int __init omap_init_dma(void) |
1016 | { | 1264 | { |
1017 | int ch, r; | 1265 | int ch, r; |
1018 | 1266 | ||
1019 | if (cpu_is_omap1510()) { | 1267 | if (cpu_is_omap15xx()) { |
1020 | printk(KERN_INFO "DMA support for OMAP1510 initialized\n"); | 1268 | printk(KERN_INFO "DMA support for OMAP15xx initialized\n"); |
1021 | dma_chan_count = 9; | 1269 | dma_chan_count = 9; |
1022 | enable_1510_mode = 1; | 1270 | enable_1510_mode = 1; |
1023 | } else if (cpu_is_omap16xx() || cpu_is_omap730()) { | 1271 | } else if (cpu_is_omap16xx() || cpu_is_omap730()) { |
1024 | printk(KERN_INFO "OMAP DMA hardware version %d\n", | 1272 | printk(KERN_INFO "OMAP DMA hardware version %d\n", |
1025 | omap_readw(OMAP_DMA_HW_ID)); | 1273 | omap_readw(OMAP_DMA_HW_ID)); |
1026 | printk(KERN_INFO "DMA capabilities: %08x:%08x:%04x:%04x:%04x\n", | 1274 | printk(KERN_INFO "DMA capabilities: %08x:%08x:%04x:%04x:%04x\n", |
1027 | (omap_readw(OMAP_DMA_CAPS_0_U) << 16) | omap_readw(OMAP_DMA_CAPS_0_L), | 1275 | (omap_readw(OMAP_DMA_CAPS_0_U) << 16) | |
1028 | (omap_readw(OMAP_DMA_CAPS_1_U) << 16) | omap_readw(OMAP_DMA_CAPS_1_L), | 1276 | omap_readw(OMAP_DMA_CAPS_0_L), |
1277 | (omap_readw(OMAP_DMA_CAPS_1_U) << 16) | | ||
1278 | omap_readw(OMAP_DMA_CAPS_1_L), | ||
1029 | omap_readw(OMAP_DMA_CAPS_2), omap_readw(OMAP_DMA_CAPS_3), | 1279 | omap_readw(OMAP_DMA_CAPS_2), omap_readw(OMAP_DMA_CAPS_3), |
1030 | omap_readw(OMAP_DMA_CAPS_4)); | 1280 | omap_readw(OMAP_DMA_CAPS_4)); |
1031 | if (!enable_1510_mode) { | 1281 | if (!enable_1510_mode) { |
@@ -1038,6 +1288,11 @@ static int __init omap_init_dma(void) | |||
1038 | dma_chan_count = 16; | 1288 | dma_chan_count = 16; |
1039 | } else | 1289 | } else |
1040 | dma_chan_count = 9; | 1290 | dma_chan_count = 9; |
1291 | } else if (cpu_is_omap24xx()) { | ||
1292 | u8 revision = omap_readb(OMAP_DMA4_REVISION); | ||
1293 | printk(KERN_INFO "OMAP DMA hardware revision %d.%d\n", | ||
1294 | revision >> 4, revision & 0xf); | ||
1295 | dma_chan_count = OMAP_LOGICAL_DMA_CH_COUNT; | ||
1041 | } else { | 1296 | } else { |
1042 | dma_chan_count = 0; | 1297 | dma_chan_count = 0; |
1043 | return 0; | 1298 | return 0; |
@@ -1049,41 +1304,56 @@ static int __init omap_init_dma(void) | |||
1049 | memset(&dma_chan, 0, sizeof(dma_chan)); | 1304 | memset(&dma_chan, 0, sizeof(dma_chan)); |
1050 | 1305 | ||
1051 | for (ch = 0; ch < dma_chan_count; ch++) { | 1306 | for (ch = 0; ch < dma_chan_count; ch++) { |
1307 | omap_clear_dma(ch); | ||
1052 | dma_chan[ch].dev_id = -1; | 1308 | dma_chan[ch].dev_id = -1; |
1053 | dma_chan[ch].next_lch = -1; | 1309 | dma_chan[ch].next_lch = -1; |
1054 | 1310 | ||
1055 | if (ch >= 6 && enable_1510_mode) | 1311 | if (ch >= 6 && enable_1510_mode) |
1056 | continue; | 1312 | continue; |
1057 | 1313 | ||
1058 | /* request_irq() doesn't like dev_id (ie. ch) being zero, | 1314 | if (cpu_class_is_omap1()) { |
1059 | * so we have to kludge around this. */ | 1315 | /* request_irq() doesn't like dev_id (ie. ch) being |
1060 | r = request_irq(dma_irq[ch], dma_irq_handler, 0, "DMA", | 1316 | * zero, so we have to kludge around this. */ |
1061 | (void *) (ch + 1)); | 1317 | r = request_irq(omap1_dma_irq[ch], |
1318 | omap1_dma_irq_handler, 0, "DMA", | ||
1319 | (void *) (ch + 1)); | ||
1320 | if (r != 0) { | ||
1321 | int i; | ||
1322 | |||
1323 | printk(KERN_ERR "unable to request IRQ %d " | ||
1324 | "for DMA (error %d)\n", | ||
1325 | omap1_dma_irq[ch], r); | ||
1326 | for (i = 0; i < ch; i++) | ||
1327 | free_irq(omap1_dma_irq[i], | ||
1328 | (void *) (i + 1)); | ||
1329 | return r; | ||
1330 | } | ||
1331 | } | ||
1332 | } | ||
1333 | |||
1334 | if (cpu_is_omap24xx()) | ||
1335 | setup_irq(INT_24XX_SDMA_IRQ0, &omap24xx_dma_irq); | ||
1336 | |||
1337 | /* FIXME: Update LCD DMA to work on 24xx */ | ||
1338 | if (cpu_class_is_omap1()) { | ||
1339 | r = request_irq(INT_DMA_LCD, lcd_dma_irq_handler, 0, | ||
1340 | "LCD DMA", NULL); | ||
1062 | if (r != 0) { | 1341 | if (r != 0) { |
1063 | int i; | 1342 | int i; |
1064 | 1343 | ||
1065 | printk(KERN_ERR "unable to request IRQ %d for DMA (error %d)\n", | 1344 | printk(KERN_ERR "unable to request IRQ for LCD DMA " |
1066 | dma_irq[ch], r); | 1345 | "(error %d)\n", r); |
1067 | for (i = 0; i < ch; i++) | 1346 | for (i = 0; i < dma_chan_count; i++) |
1068 | free_irq(dma_irq[i], (void *) (i + 1)); | 1347 | free_irq(omap1_dma_irq[i], (void *) (i + 1)); |
1069 | return r; | 1348 | return r; |
1070 | } | 1349 | } |
1071 | } | 1350 | } |
1072 | r = request_irq(INT_DMA_LCD, lcd_dma_irq_handler, 0, "LCD DMA", NULL); | ||
1073 | if (r != 0) { | ||
1074 | int i; | ||
1075 | 1351 | ||
1076 | printk(KERN_ERR "unable to request IRQ for LCD DMA (error %d)\n", r); | ||
1077 | for (i = 0; i < dma_chan_count; i++) | ||
1078 | free_irq(dma_irq[i], (void *) (i + 1)); | ||
1079 | return r; | ||
1080 | } | ||
1081 | return 0; | 1352 | return 0; |
1082 | } | 1353 | } |
1083 | 1354 | ||
1084 | arch_initcall(omap_init_dma); | 1355 | arch_initcall(omap_init_dma); |
1085 | 1356 | ||
1086 | |||
1087 | EXPORT_SYMBOL(omap_get_dma_src_pos); | 1357 | EXPORT_SYMBOL(omap_get_dma_src_pos); |
1088 | EXPORT_SYMBOL(omap_get_dma_dst_pos); | 1358 | EXPORT_SYMBOL(omap_get_dma_dst_pos); |
1089 | EXPORT_SYMBOL(omap_get_dma_src_addr_counter); | 1359 | EXPORT_SYMBOL(omap_get_dma_src_addr_counter); |
@@ -1109,6 +1379,8 @@ EXPORT_SYMBOL(omap_set_dma_dest_index); | |||
1109 | EXPORT_SYMBOL(omap_set_dma_dest_data_pack); | 1379 | EXPORT_SYMBOL(omap_set_dma_dest_data_pack); |
1110 | EXPORT_SYMBOL(omap_set_dma_dest_burst_mode); | 1380 | EXPORT_SYMBOL(omap_set_dma_dest_burst_mode); |
1111 | 1381 | ||
1382 | EXPORT_SYMBOL(omap_set_dma_params); | ||
1383 | |||
1112 | EXPORT_SYMBOL(omap_dma_link_lch); | 1384 | EXPORT_SYMBOL(omap_dma_link_lch); |
1113 | EXPORT_SYMBOL(omap_dma_unlink_lch); | 1385 | EXPORT_SYMBOL(omap_dma_unlink_lch); |
1114 | 1386 | ||
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c index 55059a24ad41..76f721d85137 100644 --- a/arch/arm/plat-omap/gpio.c +++ b/arch/arm/plat-omap/gpio.c | |||
@@ -140,7 +140,7 @@ static struct gpio_bank gpio_bank_1610[5] = { | |||
140 | }; | 140 | }; |
141 | #endif | 141 | #endif |
142 | 142 | ||
143 | #ifdef CONFIG_ARCH_OMAP1510 | 143 | #ifdef CONFIG_ARCH_OMAP15XX |
144 | static struct gpio_bank gpio_bank_1510[2] = { | 144 | static struct gpio_bank gpio_bank_1510[2] = { |
145 | { OMAP_MPUIO_BASE, INT_MPUIO, IH_MPUIO_BASE, METHOD_MPUIO }, | 145 | { OMAP_MPUIO_BASE, INT_MPUIO, IH_MPUIO_BASE, METHOD_MPUIO }, |
146 | { OMAP1510_GPIO_BASE, INT_GPIO_BANK1, IH_GPIO_BASE, METHOD_GPIO_1510 } | 146 | { OMAP1510_GPIO_BASE, INT_GPIO_BANK1, IH_GPIO_BASE, METHOD_GPIO_1510 } |
@@ -173,7 +173,7 @@ static int gpio_bank_count; | |||
173 | 173 | ||
174 | static inline struct gpio_bank *get_gpio_bank(int gpio) | 174 | static inline struct gpio_bank *get_gpio_bank(int gpio) |
175 | { | 175 | { |
176 | #ifdef CONFIG_ARCH_OMAP1510 | 176 | #ifdef CONFIG_ARCH_OMAP15XX |
177 | if (cpu_is_omap1510()) { | 177 | if (cpu_is_omap1510()) { |
178 | if (OMAP_GPIO_IS_MPUIO(gpio)) | 178 | if (OMAP_GPIO_IS_MPUIO(gpio)) |
179 | return &gpio_bank[0]; | 179 | return &gpio_bank[0]; |
@@ -222,7 +222,7 @@ static inline int gpio_valid(int gpio) | |||
222 | return -1; | 222 | return -1; |
223 | return 0; | 223 | return 0; |
224 | } | 224 | } |
225 | #ifdef CONFIG_ARCH_OMAP1510 | 225 | #ifdef CONFIG_ARCH_OMAP15XX |
226 | if (cpu_is_omap1510() && gpio < 16) | 226 | if (cpu_is_omap1510() && gpio < 16) |
227 | return 0; | 227 | return 0; |
228 | #endif | 228 | #endif |
@@ -654,7 +654,7 @@ int omap_request_gpio(int gpio) | |||
654 | /* Set trigger to none. You need to enable the trigger after request_irq */ | 654 | /* Set trigger to none. You need to enable the trigger after request_irq */ |
655 | _set_gpio_triggering(bank, get_gpio_index(gpio), IRQT_NOEDGE); | 655 | _set_gpio_triggering(bank, get_gpio_index(gpio), IRQT_NOEDGE); |
656 | 656 | ||
657 | #ifdef CONFIG_ARCH_OMAP1510 | 657 | #ifdef CONFIG_ARCH_OMAP15XX |
658 | if (bank->method == METHOD_GPIO_1510) { | 658 | if (bank->method == METHOD_GPIO_1510) { |
659 | void __iomem *reg; | 659 | void __iomem *reg; |
660 | 660 | ||
@@ -739,7 +739,7 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc, | |||
739 | bank = (struct gpio_bank *) desc->data; | 739 | bank = (struct gpio_bank *) desc->data; |
740 | if (bank->method == METHOD_MPUIO) | 740 | if (bank->method == METHOD_MPUIO) |
741 | isr_reg = bank->base + OMAP_MPUIO_GPIO_INT; | 741 | isr_reg = bank->base + OMAP_MPUIO_GPIO_INT; |
742 | #ifdef CONFIG_ARCH_OMAP1510 | 742 | #ifdef CONFIG_ARCH_OMAP15XX |
743 | if (bank->method == METHOD_GPIO_1510) | 743 | if (bank->method == METHOD_GPIO_1510) |
744 | isr_reg = bank->base + OMAP1510_GPIO_INT_STATUS; | 744 | isr_reg = bank->base + OMAP1510_GPIO_INT_STATUS; |
745 | #endif | 745 | #endif |
@@ -774,7 +774,7 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc, | |||
774 | d = irq_desc + gpio_irq; | 774 | d = irq_desc + gpio_irq; |
775 | desc_handle_irq(gpio_irq, d, regs); | 775 | desc_handle_irq(gpio_irq, d, regs); |
776 | } | 776 | } |
777 | } | 777 | } |
778 | } | 778 | } |
779 | 779 | ||
780 | static void gpio_ack_irq(unsigned int irq) | 780 | static void gpio_ack_irq(unsigned int irq) |
@@ -837,8 +837,9 @@ static struct irqchip mpuio_irq_chip = { | |||
837 | .unmask = mpuio_unmask_irq | 837 | .unmask = mpuio_unmask_irq |
838 | }; | 838 | }; |
839 | 839 | ||
840 | static int initialized = 0; | 840 | static int initialized; |
841 | static struct clk * gpio_ck = NULL; | 841 | static struct clk * gpio_ick; |
842 | static struct clk * gpio_fck; | ||
842 | 843 | ||
843 | static int __init _omap_gpio_init(void) | 844 | static int __init _omap_gpio_init(void) |
844 | { | 845 | { |
@@ -848,14 +849,26 @@ static int __init _omap_gpio_init(void) | |||
848 | initialized = 1; | 849 | initialized = 1; |
849 | 850 | ||
850 | if (cpu_is_omap1510()) { | 851 | if (cpu_is_omap1510()) { |
851 | gpio_ck = clk_get(NULL, "arm_gpio_ck"); | 852 | gpio_ick = clk_get(NULL, "arm_gpio_ck"); |
852 | if (IS_ERR(gpio_ck)) | 853 | if (IS_ERR(gpio_ick)) |
853 | printk("Could not get arm_gpio_ck\n"); | 854 | printk("Could not get arm_gpio_ck\n"); |
854 | else | 855 | else |
855 | clk_use(gpio_ck); | 856 | clk_use(gpio_ick); |
857 | } | ||
858 | if (cpu_is_omap24xx()) { | ||
859 | gpio_ick = clk_get(NULL, "gpios_ick"); | ||
860 | if (IS_ERR(gpio_ick)) | ||
861 | printk("Could not get gpios_ick\n"); | ||
862 | else | ||
863 | clk_use(gpio_ick); | ||
864 | gpio_fck = clk_get(NULL, "gpios_fck"); | ||
865 | if (IS_ERR(gpio_ick)) | ||
866 | printk("Could not get gpios_fck\n"); | ||
867 | else | ||
868 | clk_use(gpio_fck); | ||
856 | } | 869 | } |
857 | 870 | ||
858 | #ifdef CONFIG_ARCH_OMAP1510 | 871 | #ifdef CONFIG_ARCH_OMAP15XX |
859 | if (cpu_is_omap1510()) { | 872 | if (cpu_is_omap1510()) { |
860 | printk(KERN_INFO "OMAP1510 GPIO hardware\n"); | 873 | printk(KERN_INFO "OMAP1510 GPIO hardware\n"); |
861 | gpio_bank_count = 2; | 874 | gpio_bank_count = 2; |
@@ -901,7 +914,7 @@ static int __init _omap_gpio_init(void) | |||
901 | if (bank->method == METHOD_MPUIO) { | 914 | if (bank->method == METHOD_MPUIO) { |
902 | omap_writew(0xFFFF, OMAP_MPUIO_BASE + OMAP_MPUIO_GPIO_MASKIT); | 915 | omap_writew(0xFFFF, OMAP_MPUIO_BASE + OMAP_MPUIO_GPIO_MASKIT); |
903 | } | 916 | } |
904 | #ifdef CONFIG_ARCH_OMAP1510 | 917 | #ifdef CONFIG_ARCH_OMAP15XX |
905 | if (bank->method == METHOD_GPIO_1510) { | 918 | if (bank->method == METHOD_GPIO_1510) { |
906 | __raw_writew(0xffff, bank->base + OMAP1510_GPIO_INT_MASK); | 919 | __raw_writew(0xffff, bank->base + OMAP1510_GPIO_INT_MASK); |
907 | __raw_writew(0x0000, bank->base + OMAP1510_GPIO_INT_STATUS); | 920 | __raw_writew(0x0000, bank->base + OMAP1510_GPIO_INT_STATUS); |
@@ -1038,6 +1051,7 @@ static struct sys_device omap_gpio_device = { | |||
1038 | 1051 | ||
1039 | /* | 1052 | /* |
1040 | * This may get called early from board specific init | 1053 | * This may get called early from board specific init |
1054 | * for boards that have interrupts routed via FPGA. | ||
1041 | */ | 1055 | */ |
1042 | int omap_gpio_init(void) | 1056 | int omap_gpio_init(void) |
1043 | { | 1057 | { |
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c index 9c9b7df3faf6..ea9475c86656 100644 --- a/arch/arm/plat-omap/mcbsp.c +++ b/arch/arm/plat-omap/mcbsp.c | |||
@@ -491,17 +491,20 @@ int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, unsigned int leng | |||
491 | omap_set_dma_transfer_params(mcbsp[id].dma_tx_lch, | 491 | omap_set_dma_transfer_params(mcbsp[id].dma_tx_lch, |
492 | OMAP_DMA_DATA_TYPE_S16, | 492 | OMAP_DMA_DATA_TYPE_S16, |
493 | length >> 1, 1, | 493 | length >> 1, 1, |
494 | OMAP_DMA_SYNC_ELEMENT); | 494 | OMAP_DMA_SYNC_ELEMENT, |
495 | 0, 0); | ||
495 | 496 | ||
496 | omap_set_dma_dest_params(mcbsp[id].dma_tx_lch, | 497 | omap_set_dma_dest_params(mcbsp[id].dma_tx_lch, |
497 | OMAP_DMA_PORT_TIPB, | 498 | OMAP_DMA_PORT_TIPB, |
498 | OMAP_DMA_AMODE_CONSTANT, | 499 | OMAP_DMA_AMODE_CONSTANT, |
499 | mcbsp[id].io_base + OMAP_MCBSP_REG_DXR1); | 500 | mcbsp[id].io_base + OMAP_MCBSP_REG_DXR1, |
501 | 0, 0); | ||
500 | 502 | ||
501 | omap_set_dma_src_params(mcbsp[id].dma_tx_lch, | 503 | omap_set_dma_src_params(mcbsp[id].dma_tx_lch, |
502 | OMAP_DMA_PORT_EMIFF, | 504 | OMAP_DMA_PORT_EMIFF, |
503 | OMAP_DMA_AMODE_POST_INC, | 505 | OMAP_DMA_AMODE_POST_INC, |
504 | buffer); | 506 | buffer, |
507 | 0, 0); | ||
505 | 508 | ||
506 | omap_start_dma(mcbsp[id].dma_tx_lch); | 509 | omap_start_dma(mcbsp[id].dma_tx_lch); |
507 | wait_for_completion(&(mcbsp[id].tx_dma_completion)); | 510 | wait_for_completion(&(mcbsp[id].tx_dma_completion)); |
@@ -531,17 +534,20 @@ int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, unsigned int leng | |||
531 | omap_set_dma_transfer_params(mcbsp[id].dma_rx_lch, | 534 | omap_set_dma_transfer_params(mcbsp[id].dma_rx_lch, |
532 | OMAP_DMA_DATA_TYPE_S16, | 535 | OMAP_DMA_DATA_TYPE_S16, |
533 | length >> 1, 1, | 536 | length >> 1, 1, |
534 | OMAP_DMA_SYNC_ELEMENT); | 537 | OMAP_DMA_SYNC_ELEMENT, |
538 | 0, 0); | ||
535 | 539 | ||
536 | omap_set_dma_src_params(mcbsp[id].dma_rx_lch, | 540 | omap_set_dma_src_params(mcbsp[id].dma_rx_lch, |
537 | OMAP_DMA_PORT_TIPB, | 541 | OMAP_DMA_PORT_TIPB, |
538 | OMAP_DMA_AMODE_CONSTANT, | 542 | OMAP_DMA_AMODE_CONSTANT, |
539 | mcbsp[id].io_base + OMAP_MCBSP_REG_DRR1); | 543 | mcbsp[id].io_base + OMAP_MCBSP_REG_DRR1, |
544 | 0, 0); | ||
540 | 545 | ||
541 | omap_set_dma_dest_params(mcbsp[id].dma_rx_lch, | 546 | omap_set_dma_dest_params(mcbsp[id].dma_rx_lch, |
542 | OMAP_DMA_PORT_EMIFF, | 547 | OMAP_DMA_PORT_EMIFF, |
543 | OMAP_DMA_AMODE_POST_INC, | 548 | OMAP_DMA_AMODE_POST_INC, |
544 | buffer); | 549 | buffer, |
550 | 0, 0); | ||
545 | 551 | ||
546 | omap_start_dma(mcbsp[id].dma_rx_lch); | 552 | omap_start_dma(mcbsp[id].dma_rx_lch); |
547 | wait_for_completion(&(mcbsp[id].rx_dma_completion)); | 553 | wait_for_completion(&(mcbsp[id].rx_dma_completion)); |
@@ -643,7 +649,7 @@ static const struct omap_mcbsp_info mcbsp_730[] = { | |||
643 | }; | 649 | }; |
644 | #endif | 650 | #endif |
645 | 651 | ||
646 | #ifdef CONFIG_ARCH_OMAP1510 | 652 | #ifdef CONFIG_ARCH_OMAP15XX |
647 | static const struct omap_mcbsp_info mcbsp_1510[] = { | 653 | static const struct omap_mcbsp_info mcbsp_1510[] = { |
648 | [0] = { .virt_base = OMAP1510_MCBSP1_BASE, | 654 | [0] = { .virt_base = OMAP1510_MCBSP1_BASE, |
649 | .dma_rx_sync = OMAP_DMA_MCBSP1_RX, | 655 | .dma_rx_sync = OMAP_DMA_MCBSP1_RX, |
@@ -712,7 +718,7 @@ static int __init omap_mcbsp_init(void) | |||
712 | mcbsp_count = ARRAY_SIZE(mcbsp_730); | 718 | mcbsp_count = ARRAY_SIZE(mcbsp_730); |
713 | } | 719 | } |
714 | #endif | 720 | #endif |
715 | #ifdef CONFIG_ARCH_OMAP1510 | 721 | #ifdef CONFIG_ARCH_OMAP15XX |
716 | if (cpu_is_omap1510()) { | 722 | if (cpu_is_omap1510()) { |
717 | mcbsp_info = mcbsp_1510; | 723 | mcbsp_info = mcbsp_1510; |
718 | mcbsp_count = ARRAY_SIZE(mcbsp_1510); | 724 | mcbsp_count = ARRAY_SIZE(mcbsp_1510); |
diff --git a/arch/arm/plat-omap/mux.c b/arch/arm/plat-omap/mux.c index 64482040f89e..8c1c016aa689 100644 --- a/arch/arm/plat-omap/mux.c +++ b/arch/arm/plat-omap/mux.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Utility to set the Omap MUX and PULL_DWN registers from a table in mux.h | 4 | * Utility to set the Omap MUX and PULL_DWN registers from a table in mux.h |
5 | * | 5 | * |
6 | * Copyright (C) 2003 Nokia Corporation | 6 | * Copyright (C) 2003 - 2005 Nokia Corporation |
7 | * | 7 | * |
8 | * Written by Tony Lindgren <tony.lindgren@nokia.com> | 8 | * Written by Tony Lindgren <tony.lindgren@nokia.com> |
9 | * | 9 | * |
@@ -25,38 +25,74 @@ | |||
25 | #include <linux/config.h> | 25 | #include <linux/config.h> |
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <linux/init.h> | 27 | #include <linux/init.h> |
28 | #include <linux/kernel.h> | ||
28 | #include <asm/system.h> | 29 | #include <asm/system.h> |
29 | #include <asm/io.h> | 30 | #include <asm/io.h> |
30 | #include <linux/spinlock.h> | 31 | #include <linux/spinlock.h> |
31 | |||
32 | #define __MUX_C__ | ||
33 | #include <asm/arch/mux.h> | 32 | #include <asm/arch/mux.h> |
34 | 33 | ||
35 | #ifdef CONFIG_OMAP_MUX | 34 | #ifdef CONFIG_OMAP_MUX |
36 | 35 | ||
36 | #define OMAP24XX_L4_BASE 0x48000000 | ||
37 | #define OMAP24XX_PULL_ENA (1 << 3) | ||
38 | #define OMAP24XX_PULL_UP (1 << 4) | ||
39 | |||
40 | static struct pin_config * pin_table; | ||
41 | static unsigned long pin_table_sz; | ||
42 | |||
43 | extern struct pin_config * omap730_pins; | ||
44 | extern struct pin_config * omap1xxx_pins; | ||
45 | extern struct pin_config * omap24xx_pins; | ||
46 | |||
47 | int __init omap_mux_register(struct pin_config * pins, unsigned long size) | ||
48 | { | ||
49 | pin_table = pins; | ||
50 | pin_table_sz = size; | ||
51 | |||
52 | return 0; | ||
53 | } | ||
54 | |||
37 | /* | 55 | /* |
38 | * Sets the Omap MUX and PULL_DWN registers based on the table | 56 | * Sets the Omap MUX and PULL_DWN registers based on the table |
39 | */ | 57 | */ |
40 | int __init_or_module | 58 | int __init_or_module omap_cfg_reg(const unsigned long index) |
41 | omap_cfg_reg(const reg_cfg_t reg_cfg) | ||
42 | { | 59 | { |
43 | static DEFINE_SPINLOCK(mux_spin_lock); | 60 | static DEFINE_SPINLOCK(mux_spin_lock); |
44 | 61 | ||
45 | unsigned long flags; | 62 | unsigned long flags; |
46 | reg_cfg_set *cfg; | 63 | struct pin_config *cfg; |
47 | unsigned int reg_orig = 0, reg = 0, pu_pd_orig = 0, pu_pd = 0, | 64 | unsigned int reg_orig = 0, reg = 0, pu_pd_orig = 0, pu_pd = 0, |
48 | pull_orig = 0, pull = 0; | 65 | pull_orig = 0, pull = 0; |
49 | unsigned int mask, warn = 0; | 66 | unsigned int mask, warn = 0; |
50 | 67 | ||
51 | if (cpu_is_omap7xx()) | 68 | if (!pin_table) |
52 | return 0; | 69 | BUG(); |
53 | 70 | ||
54 | if (reg_cfg > ARRAY_SIZE(reg_cfg_table)) { | 71 | if (index >= pin_table_sz) { |
55 | printk(KERN_ERR "MUX: reg_cfg %d\n", reg_cfg); | 72 | printk(KERN_ERR "Invalid pin mux index: %lu (%lu)\n", |
56 | return -EINVAL; | 73 | index, pin_table_sz); |
74 | dump_stack(); | ||
75 | return -ENODEV; | ||
57 | } | 76 | } |
58 | 77 | ||
59 | cfg = (reg_cfg_set *)®_cfg_table[reg_cfg]; | 78 | cfg = (struct pin_config *)&pin_table[index]; |
79 | if (cpu_is_omap24xx()) { | ||
80 | u8 reg = 0; | ||
81 | |||
82 | reg |= cfg->mask & 0x7; | ||
83 | if (cfg->pull_val) | ||
84 | reg |= OMAP24XX_PULL_ENA; | ||
85 | if(cfg->pu_pd_val) | ||
86 | reg |= OMAP24XX_PULL_UP; | ||
87 | #ifdef CONFIG_OMAP_MUX_DEBUG | ||
88 | printk("Muxing %s (0x%08x): 0x%02x -> 0x%02x\n", | ||
89 | cfg->name, OMAP24XX_L4_BASE + cfg->mux_reg, | ||
90 | omap_readb(OMAP24XX_L4_BASE + cfg->mux_reg), reg); | ||
91 | #endif | ||
92 | omap_writeb(reg, OMAP24XX_L4_BASE + cfg->mux_reg); | ||
93 | |||
94 | return 0; | ||
95 | } | ||
60 | 96 | ||
61 | /* Check the mux register in question */ | 97 | /* Check the mux register in question */ |
62 | if (cfg->mux_reg) { | 98 | if (cfg->mux_reg) { |
@@ -157,7 +193,8 @@ omap_cfg_reg(const reg_cfg_t reg_cfg) | |||
157 | return 0; | 193 | return 0; |
158 | #endif | 194 | #endif |
159 | } | 195 | } |
160 | |||
161 | EXPORT_SYMBOL(omap_cfg_reg); | 196 | EXPORT_SYMBOL(omap_cfg_reg); |
162 | 197 | #else | |
198 | #define omap_mux_init() do {} while(0) | ||
199 | #define omap_cfg_reg(x) do {} while(0) | ||
163 | #endif /* CONFIG_OMAP_MUX */ | 200 | #endif /* CONFIG_OMAP_MUX */ |
diff --git a/arch/arm/plat-omap/pm.c b/arch/arm/plat-omap/pm.c index e15c6c1ddec9..966cca031ca7 100644 --- a/arch/arm/plat-omap/pm.c +++ b/arch/arm/plat-omap/pm.c | |||
@@ -54,11 +54,12 @@ | |||
54 | #include <asm/arch/tps65010.h> | 54 | #include <asm/arch/tps65010.h> |
55 | #include <asm/arch/dsp_common.h> | 55 | #include <asm/arch/dsp_common.h> |
56 | 56 | ||
57 | #include "clock.h" | 57 | #include <asm/arch/clock.h> |
58 | #include "sram.h" | 58 | #include <asm/arch/sram.h> |
59 | 59 | ||
60 | static unsigned int arm_sleep_save[ARM_SLEEP_SAVE_SIZE]; | 60 | static unsigned int arm_sleep_save[ARM_SLEEP_SAVE_SIZE]; |
61 | static unsigned short ulpd_sleep_save[ULPD_SLEEP_SAVE_SIZE]; | 61 | static unsigned short ulpd_sleep_save[ULPD_SLEEP_SAVE_SIZE]; |
62 | static unsigned int mpui730_sleep_save[MPUI730_SLEEP_SAVE_SIZE]; | ||
62 | static unsigned int mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_SIZE]; | 63 | static unsigned int mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_SIZE]; |
63 | static unsigned int mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_SIZE]; | 64 | static unsigned int mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_SIZE]; |
64 | 65 | ||
@@ -120,8 +121,8 @@ void omap_pm_idle(void) | |||
120 | */ | 121 | */ |
121 | static void omap_pm_wakeup_setup(void) | 122 | static void omap_pm_wakeup_setup(void) |
122 | { | 123 | { |
123 | u32 level1_wake = OMAP_IRQ_BIT(INT_IH2_IRQ); | 124 | u32 level1_wake = 0; |
124 | u32 level2_wake = OMAP_IRQ_BIT(INT_UART2) | OMAP_IRQ_BIT(INT_KEYBOARD); | 125 | u32 level2_wake = OMAP_IRQ_BIT(INT_UART2); |
125 | 126 | ||
126 | /* | 127 | /* |
127 | * Turn off all interrupts except GPIO bank 1, L1-2nd level cascade, | 128 | * Turn off all interrupts except GPIO bank 1, L1-2nd level cascade, |
@@ -129,19 +130,29 @@ static void omap_pm_wakeup_setup(void) | |||
129 | * drivers must still separately call omap_set_gpio_wakeup() to | 130 | * drivers must still separately call omap_set_gpio_wakeup() to |
130 | * wake up to a GPIO interrupt. | 131 | * wake up to a GPIO interrupt. |
131 | */ | 132 | */ |
132 | if (cpu_is_omap1510() || cpu_is_omap16xx()) | 133 | if (cpu_is_omap730()) |
133 | level1_wake |= OMAP_IRQ_BIT(INT_GPIO_BANK1); | 134 | level1_wake = OMAP_IRQ_BIT(INT_730_GPIO_BANK1) | |
134 | else if (cpu_is_omap730()) | 135 | OMAP_IRQ_BIT(INT_730_IH2_IRQ); |
135 | level1_wake |= OMAP_IRQ_BIT(INT_730_GPIO_BANK1); | 136 | else if (cpu_is_omap1510()) |
137 | level1_wake = OMAP_IRQ_BIT(INT_GPIO_BANK1) | | ||
138 | OMAP_IRQ_BIT(INT_1510_IH2_IRQ); | ||
139 | else if (cpu_is_omap16xx()) | ||
140 | level1_wake = OMAP_IRQ_BIT(INT_GPIO_BANK1) | | ||
141 | OMAP_IRQ_BIT(INT_1610_IH2_IRQ); | ||
136 | 142 | ||
137 | omap_writel(~level1_wake, OMAP_IH1_MIR); | 143 | omap_writel(~level1_wake, OMAP_IH1_MIR); |
138 | 144 | ||
139 | if (cpu_is_omap1510()) | 145 | if (cpu_is_omap730()) { |
146 | omap_writel(~level2_wake, OMAP_IH2_0_MIR); | ||
147 | omap_writel(~(OMAP_IRQ_BIT(INT_730_WAKE_UP_REQ) | OMAP_IRQ_BIT(INT_730_MPUIO_KEYPAD)), OMAP_IH2_1_MIR); | ||
148 | } else if (cpu_is_omap1510()) { | ||
149 | level2_wake |= OMAP_IRQ_BIT(INT_KEYBOARD); | ||
140 | omap_writel(~level2_wake, OMAP_IH2_MIR); | 150 | omap_writel(~level2_wake, OMAP_IH2_MIR); |
141 | 151 | } else if (cpu_is_omap16xx()) { | |
142 | /* INT_1610_WAKE_UP_REQ is needed for GPIO wakeup... */ | 152 | level2_wake |= OMAP_IRQ_BIT(INT_KEYBOARD); |
143 | if (cpu_is_omap16xx()) { | ||
144 | omap_writel(~level2_wake, OMAP_IH2_0_MIR); | 153 | omap_writel(~level2_wake, OMAP_IH2_0_MIR); |
154 | |||
155 | /* INT_1610_WAKE_UP_REQ is needed for GPIO wakeup... */ | ||
145 | omap_writel(~OMAP_IRQ_BIT(INT_1610_WAKE_UP_REQ), OMAP_IH2_1_MIR); | 156 | omap_writel(~OMAP_IRQ_BIT(INT_1610_WAKE_UP_REQ), OMAP_IH2_1_MIR); |
146 | omap_writel(~0x0, OMAP_IH2_2_MIR); | 157 | omap_writel(~0x0, OMAP_IH2_2_MIR); |
147 | omap_writel(~0x0, OMAP_IH2_3_MIR); | 158 | omap_writel(~0x0, OMAP_IH2_3_MIR); |
@@ -185,7 +196,17 @@ void omap_pm_suspend(void) | |||
185 | * Save interrupt, MPUI, ARM and UPLD control registers. | 196 | * Save interrupt, MPUI, ARM and UPLD control registers. |
186 | */ | 197 | */ |
187 | 198 | ||
188 | if (cpu_is_omap1510()) { | 199 | if (cpu_is_omap730()) { |
200 | MPUI730_SAVE(OMAP_IH1_MIR); | ||
201 | MPUI730_SAVE(OMAP_IH2_0_MIR); | ||
202 | MPUI730_SAVE(OMAP_IH2_1_MIR); | ||
203 | MPUI730_SAVE(MPUI_CTRL); | ||
204 | MPUI730_SAVE(MPUI_DSP_BOOT_CONFIG); | ||
205 | MPUI730_SAVE(MPUI_DSP_API_CONFIG); | ||
206 | MPUI730_SAVE(EMIFS_CONFIG); | ||
207 | MPUI730_SAVE(EMIFF_SDRAM_CONFIG); | ||
208 | |||
209 | } else if (cpu_is_omap1510()) { | ||
189 | MPUI1510_SAVE(OMAP_IH1_MIR); | 210 | MPUI1510_SAVE(OMAP_IH1_MIR); |
190 | MPUI1510_SAVE(OMAP_IH2_MIR); | 211 | MPUI1510_SAVE(OMAP_IH2_MIR); |
191 | MPUI1510_SAVE(MPUI_CTRL); | 212 | MPUI1510_SAVE(MPUI_CTRL); |
@@ -280,7 +301,13 @@ void omap_pm_suspend(void) | |||
280 | ULPD_RESTORE(ULPD_CLOCK_CTRL); | 301 | ULPD_RESTORE(ULPD_CLOCK_CTRL); |
281 | ULPD_RESTORE(ULPD_STATUS_REQ); | 302 | ULPD_RESTORE(ULPD_STATUS_REQ); |
282 | 303 | ||
283 | if (cpu_is_omap1510()) { | 304 | if (cpu_is_omap730()) { |
305 | MPUI730_RESTORE(EMIFS_CONFIG); | ||
306 | MPUI730_RESTORE(EMIFF_SDRAM_CONFIG); | ||
307 | MPUI730_RESTORE(OMAP_IH1_MIR); | ||
308 | MPUI730_RESTORE(OMAP_IH2_0_MIR); | ||
309 | MPUI730_RESTORE(OMAP_IH2_1_MIR); | ||
310 | } else if (cpu_is_omap1510()) { | ||
284 | MPUI1510_RESTORE(MPUI_CTRL); | 311 | MPUI1510_RESTORE(MPUI_CTRL); |
285 | MPUI1510_RESTORE(MPUI_DSP_BOOT_CONFIG); | 312 | MPUI1510_RESTORE(MPUI_DSP_BOOT_CONFIG); |
286 | MPUI1510_RESTORE(MPUI_DSP_API_CONFIG); | 313 | MPUI1510_RESTORE(MPUI_DSP_API_CONFIG); |
@@ -355,7 +382,14 @@ static int omap_pm_read_proc( | |||
355 | ULPD_SAVE(ULPD_DPLL_CTRL); | 382 | ULPD_SAVE(ULPD_DPLL_CTRL); |
356 | ULPD_SAVE(ULPD_POWER_CTRL); | 383 | ULPD_SAVE(ULPD_POWER_CTRL); |
357 | 384 | ||
358 | if (cpu_is_omap1510()) { | 385 | if (cpu_is_omap730()) { |
386 | MPUI730_SAVE(MPUI_CTRL); | ||
387 | MPUI730_SAVE(MPUI_DSP_STATUS); | ||
388 | MPUI730_SAVE(MPUI_DSP_BOOT_CONFIG); | ||
389 | MPUI730_SAVE(MPUI_DSP_API_CONFIG); | ||
390 | MPUI730_SAVE(EMIFF_SDRAM_CONFIG); | ||
391 | MPUI730_SAVE(EMIFS_CONFIG); | ||
392 | } else if (cpu_is_omap1510()) { | ||
359 | MPUI1510_SAVE(MPUI_CTRL); | 393 | MPUI1510_SAVE(MPUI_CTRL); |
360 | MPUI1510_SAVE(MPUI_DSP_STATUS); | 394 | MPUI1510_SAVE(MPUI_DSP_STATUS); |
361 | MPUI1510_SAVE(MPUI_DSP_BOOT_CONFIG); | 395 | MPUI1510_SAVE(MPUI_DSP_BOOT_CONFIG); |
@@ -404,7 +438,21 @@ static int omap_pm_read_proc( | |||
404 | ULPD_SHOW(ULPD_STATUS_REQ), | 438 | ULPD_SHOW(ULPD_STATUS_REQ), |
405 | ULPD_SHOW(ULPD_POWER_CTRL)); | 439 | ULPD_SHOW(ULPD_POWER_CTRL)); |
406 | 440 | ||
407 | if (cpu_is_omap1510()) { | 441 | if (cpu_is_omap730()) { |
442 | my_buffer_offset += sprintf(my_base + my_buffer_offset, | ||
443 | "MPUI730_CTRL_REG 0x%-8x \n" | ||
444 | "MPUI730_DSP_STATUS_REG: 0x%-8x \n" | ||
445 | "MPUI730_DSP_BOOT_CONFIG_REG: 0x%-8x \n" | ||
446 | "MPUI730_DSP_API_CONFIG_REG: 0x%-8x \n" | ||
447 | "MPUI730_SDRAM_CONFIG_REG: 0x%-8x \n" | ||
448 | "MPUI730_EMIFS_CONFIG_REG: 0x%-8x \n", | ||
449 | MPUI730_SHOW(MPUI_CTRL), | ||
450 | MPUI730_SHOW(MPUI_DSP_STATUS), | ||
451 | MPUI730_SHOW(MPUI_DSP_BOOT_CONFIG), | ||
452 | MPUI730_SHOW(MPUI_DSP_API_CONFIG), | ||
453 | MPUI730_SHOW(EMIFF_SDRAM_CONFIG), | ||
454 | MPUI730_SHOW(EMIFS_CONFIG)); | ||
455 | } else if (cpu_is_omap1510()) { | ||
408 | my_buffer_offset += sprintf(my_base + my_buffer_offset, | 456 | my_buffer_offset += sprintf(my_base + my_buffer_offset, |
409 | "MPUI1510_CTRL_REG 0x%-8x \n" | 457 | "MPUI1510_CTRL_REG 0x%-8x \n" |
410 | "MPUI1510_DSP_STATUS_REG: 0x%-8x \n" | 458 | "MPUI1510_DSP_STATUS_REG: 0x%-8x \n" |
@@ -553,7 +601,12 @@ static int __init omap_pm_init(void) | |||
553 | * These routines need to be in SRAM as that's the only | 601 | * These routines need to be in SRAM as that's the only |
554 | * memory the MPU can see when it wakes up. | 602 | * memory the MPU can see when it wakes up. |
555 | */ | 603 | */ |
556 | if (cpu_is_omap1510()) { | 604 | if (cpu_is_omap730()) { |
605 | omap_sram_idle = omap_sram_push(omap730_idle_loop_suspend, | ||
606 | omap730_idle_loop_suspend_sz); | ||
607 | omap_sram_suspend = omap_sram_push(omap730_cpu_suspend, | ||
608 | omap730_cpu_suspend_sz); | ||
609 | } else if (cpu_is_omap1510()) { | ||
557 | omap_sram_idle = omap_sram_push(omap1510_idle_loop_suspend, | 610 | omap_sram_idle = omap_sram_push(omap1510_idle_loop_suspend, |
558 | omap1510_idle_loop_suspend_sz); | 611 | omap1510_idle_loop_suspend_sz); |
559 | omap_sram_suspend = omap_sram_push(omap1510_cpu_suspend, | 612 | omap_sram_suspend = omap_sram_push(omap1510_cpu_suspend, |
@@ -572,7 +625,11 @@ static int __init omap_pm_init(void) | |||
572 | 625 | ||
573 | pm_idle = omap_pm_idle; | 626 | pm_idle = omap_pm_idle; |
574 | 627 | ||
575 | setup_irq(INT_1610_WAKE_UP_REQ, &omap_wakeup_irq); | 628 | if (cpu_is_omap730()) |
629 | setup_irq(INT_730_WAKE_UP_REQ, &omap_wakeup_irq); | ||
630 | else if (cpu_is_omap16xx()) | ||
631 | setup_irq(INT_1610_WAKE_UP_REQ, &omap_wakeup_irq); | ||
632 | |||
576 | #if 0 | 633 | #if 0 |
577 | /* --- BEGIN BOARD-DEPENDENT CODE --- */ | 634 | /* --- BEGIN BOARD-DEPENDENT CODE --- */ |
578 | /* Sleepx mask direction */ | 635 | /* Sleepx mask direction */ |
@@ -591,7 +648,9 @@ static int __init omap_pm_init(void) | |||
591 | omap_writew(ULPD_POWER_CTRL_REG_VAL, ULPD_POWER_CTRL); | 648 | omap_writew(ULPD_POWER_CTRL_REG_VAL, ULPD_POWER_CTRL); |
592 | 649 | ||
593 | /* Configure IDLECT3 */ | 650 | /* Configure IDLECT3 */ |
594 | if (cpu_is_omap16xx()) | 651 | if (cpu_is_omap730()) |
652 | omap_writel(OMAP730_IDLECT3_VAL, OMAP730_IDLECT3); | ||
653 | else if (cpu_is_omap16xx()) | ||
595 | omap_writel(OMAP1610_IDLECT3_VAL, OMAP1610_IDLECT3); | 654 | omap_writel(OMAP1610_IDLECT3_VAL, OMAP1610_IDLECT3); |
596 | 655 | ||
597 | pm_set_ops(&omap_pm_ops); | 656 | pm_set_ops(&omap_pm_ops); |
@@ -600,8 +659,10 @@ static int __init omap_pm_init(void) | |||
600 | omap_pm_init_proc(); | 659 | omap_pm_init_proc(); |
601 | #endif | 660 | #endif |
602 | 661 | ||
603 | /* configure LOW_PWR pin */ | 662 | if (cpu_is_omap16xx()) { |
604 | omap_cfg_reg(T20_1610_LOW_PWR); | 663 | /* configure LOW_PWR pin */ |
664 | omap_cfg_reg(T20_1610_LOW_PWR); | ||
665 | } | ||
605 | 666 | ||
606 | return 0; | 667 | return 0; |
607 | } | 668 | } |
diff --git a/arch/arm/plat-omap/sleep.S b/arch/arm/plat-omap/sleep.S index 9f745836f6aa..4cd7d292f854 100644 --- a/arch/arm/plat-omap/sleep.S +++ b/arch/arm/plat-omap/sleep.S | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/arm/plat-omap/sleep.S | 2 | * linux/arch/arm/plat-omap/sleep.S |
3 | * | 3 | * |
4 | * Low-level OMAP1510/1610 sleep/wakeUp support | 4 | * Low-level OMAP730/1510/1610 sleep/wakeUp support |
5 | * | 5 | * |
6 | * Initial SA1110 code: | 6 | * Initial SA1110 code: |
7 | * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com> | 7 | * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com> |
@@ -52,7 +52,57 @@ | |||
52 | * processor specific functions here. | 52 | * processor specific functions here. |
53 | */ | 53 | */ |
54 | 54 | ||
55 | #ifdef CONFIG_ARCH_OMAP1510 | 55 | #if defined(CONFIG_ARCH_OMAP730) |
56 | ENTRY(omap730_idle_loop_suspend) | ||
57 | |||
58 | stmfd sp!, {r0 - r12, lr} @ save registers on stack | ||
59 | |||
60 | @ load base address of ARM_IDLECT1 and ARM_IDLECT2 | ||
61 | mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000 | ||
62 | orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000 | ||
63 | orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00 | ||
64 | |||
65 | @ turn off clock domains | ||
66 | @ get ARM_IDLECT2 into r2 | ||
67 | ldrh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] | ||
68 | mov r5, #OMAP730_IDLECT2_SLEEP_VAL & 0xff | ||
69 | orr r5, r5, #OMAP730_IDLECT2_SLEEP_VAL & 0xff00 | ||
70 | strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] | ||
71 | |||
72 | @ request ARM idle | ||
73 | @ get ARM_IDLECT1 into r1 | ||
74 | ldrh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] | ||
75 | orr r3, r1, #OMAP730_IDLE_LOOP_REQUEST & 0xffff | ||
76 | strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] | ||
77 | |||
78 | mov r5, #IDLE_WAIT_CYCLES & 0xff | ||
79 | orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00 | ||
80 | l_730: subs r5, r5, #1 | ||
81 | bne l_730 | ||
82 | /* | ||
83 | * Let's wait for the next clock tick to wake us up. | ||
84 | */ | ||
85 | mov r0, #0 | ||
86 | mcr p15, 0, r0, c7, c0, 4 @ wait for interrupt | ||
87 | /* | ||
88 | * omap730_idle_loop_suspend()'s resume point. | ||
89 | * | ||
90 | * It will just start executing here, so we'll restore stuff from the | ||
91 | * stack, reset the ARM_IDLECT1 and ARM_IDLECT2. | ||
92 | */ | ||
93 | |||
94 | @ restore ARM_IDLECT1 and ARM_IDLECT2 and return | ||
95 | @ r1 has ARM_IDLECT1 and r2 still has ARM_IDLECT2 | ||
96 | strh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] | ||
97 | strh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] | ||
98 | |||
99 | ldmfd sp!, {r0 - r12, pc} @ restore regs and return | ||
100 | |||
101 | ENTRY(omap730_idle_loop_suspend_sz) | ||
102 | .word . - omap730_idle_loop_suspend | ||
103 | #endif /* CONFIG_ARCH_OMAP730 */ | ||
104 | |||
105 | #ifdef CONFIG_ARCH_OMAP15XX | ||
56 | ENTRY(omap1510_idle_loop_suspend) | 106 | ENTRY(omap1510_idle_loop_suspend) |
57 | 107 | ||
58 | stmfd sp!, {r0 - r12, lr} @ save registers on stack | 108 | stmfd sp!, {r0 - r12, lr} @ save registers on stack |
@@ -100,7 +150,7 @@ l_1510: subs r5, r5, #1 | |||
100 | 150 | ||
101 | ENTRY(omap1510_idle_loop_suspend_sz) | 151 | ENTRY(omap1510_idle_loop_suspend_sz) |
102 | .word . - omap1510_idle_loop_suspend | 152 | .word . - omap1510_idle_loop_suspend |
103 | #endif /* CONFIG_ARCH_OMAP1510 */ | 153 | #endif /* CONFIG_ARCH_OMAP15XX */ |
104 | 154 | ||
105 | #if defined(CONFIG_ARCH_OMAP16XX) | 155 | #if defined(CONFIG_ARCH_OMAP16XX) |
106 | ENTRY(omap1610_idle_loop_suspend) | 156 | ENTRY(omap1610_idle_loop_suspend) |
@@ -169,7 +219,86 @@ ENTRY(omap1610_idle_loop_suspend_sz) | |||
169 | * | 219 | * |
170 | */ | 220 | */ |
171 | 221 | ||
172 | #ifdef CONFIG_ARCH_OMAP1510 | 222 | #if defined(CONFIG_ARCH_OMAP730) |
223 | ENTRY(omap730_cpu_suspend) | ||
224 | |||
225 | @ save registers on stack | ||
226 | stmfd sp!, {r0 - r12, lr} | ||
227 | |||
228 | @ Drain write cache | ||
229 | mov r4, #0 | ||
230 | mcr p15, 0, r0, c7, c10, 4 | ||
231 | nop | ||
232 | |||
233 | @ load base address of Traffic Controller | ||
234 | mov r6, #TCMIF_ASM_BASE & 0xff000000 | ||
235 | orr r6, r6, #TCMIF_ASM_BASE & 0x00ff0000 | ||
236 | orr r6, r6, #TCMIF_ASM_BASE & 0x0000ff00 | ||
237 | |||
238 | @ prepare to put SDRAM into self-refresh manually | ||
239 | ldr r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] | ||
240 | orr r9, r7, #SELF_REFRESH_MODE & 0xff000000 | ||
241 | orr r9, r9, #SELF_REFRESH_MODE & 0x000000ff | ||
242 | str r9, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] | ||
243 | |||
244 | @ prepare to put EMIFS to Sleep | ||
245 | ldr r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff] | ||
246 | orr r9, r8, #IDLE_EMIFS_REQUEST & 0xff | ||
247 | str r9, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff] | ||
248 | |||
249 | @ load base address of ARM_IDLECT1 and ARM_IDLECT2 | ||
250 | mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000 | ||
251 | orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000 | ||
252 | orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00 | ||
253 | |||
254 | @ turn off clock domains | ||
255 | @ do not disable PERCK (0x04) | ||
256 | mov r5, #OMAP730_IDLECT2_SLEEP_VAL & 0xff | ||
257 | orr r5, r5, #OMAP730_IDLECT2_SLEEP_VAL & 0xff00 | ||
258 | strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] | ||
259 | |||
260 | @ request ARM idle | ||
261 | mov r3, #OMAP730_IDLECT1_SLEEP_VAL & 0xff | ||
262 | orr r3, r3, #OMAP730_IDLECT1_SLEEP_VAL & 0xff00 | ||
263 | strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] | ||
264 | |||
265 | @ disable instruction cache | ||
266 | mrc p15, 0, r9, c1, c0, 0 | ||
267 | bic r2, r9, #0x1000 | ||
268 | mcr p15, 0, r2, c1, c0, 0 | ||
269 | nop | ||
270 | |||
271 | /* | ||
272 | * Let's wait for the next wake up event to wake us up. r0 can't be | ||
273 | * used here because r0 holds ARM_IDLECT1 | ||
274 | */ | ||
275 | mov r2, #0 | ||
276 | mcr p15, 0, r2, c7, c0, 4 @ wait for interrupt | ||
277 | /* | ||
278 | * omap730_cpu_suspend()'s resume point. | ||
279 | * | ||
280 | * It will just start executing here, so we'll restore stuff from the | ||
281 | * stack. | ||
282 | */ | ||
283 | @ re-enable Icache | ||
284 | mcr p15, 0, r9, c1, c0, 0 | ||
285 | |||
286 | @ reset the ARM_IDLECT1 and ARM_IDLECT2. | ||
287 | strh r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] | ||
288 | strh r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] | ||
289 | |||
290 | @ Restore EMIFF controls | ||
291 | str r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] | ||
292 | str r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff] | ||
293 | |||
294 | @ restore regs and return | ||
295 | ldmfd sp!, {r0 - r12, pc} | ||
296 | |||
297 | ENTRY(omap730_cpu_suspend_sz) | ||
298 | .word . - omap730_cpu_suspend | ||
299 | #endif /* CONFIG_ARCH_OMAP730 */ | ||
300 | |||
301 | #ifdef CONFIG_ARCH_OMAP15XX | ||
173 | ENTRY(omap1510_cpu_suspend) | 302 | ENTRY(omap1510_cpu_suspend) |
174 | 303 | ||
175 | @ save registers on stack | 304 | @ save registers on stack |
@@ -241,7 +370,7 @@ l_1510_2: | |||
241 | 370 | ||
242 | ENTRY(omap1510_cpu_suspend_sz) | 371 | ENTRY(omap1510_cpu_suspend_sz) |
243 | .word . - omap1510_cpu_suspend | 372 | .word . - omap1510_cpu_suspend |
244 | #endif /* CONFIG_ARCH_OMAP1510 */ | 373 | #endif /* CONFIG_ARCH_OMAP15XX */ |
245 | 374 | ||
246 | #if defined(CONFIG_ARCH_OMAP16XX) | 375 | #if defined(CONFIG_ARCH_OMAP16XX) |
247 | ENTRY(omap1610_cpu_suspend) | 376 | ENTRY(omap1610_cpu_suspend) |
diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c index 7ad69f14a3e7..792f66375830 100644 --- a/arch/arm/plat-omap/sram.c +++ b/arch/arm/plat-omap/sram.c | |||
@@ -20,10 +20,13 @@ | |||
20 | #include <asm/io.h> | 20 | #include <asm/io.h> |
21 | #include <asm/cacheflush.h> | 21 | #include <asm/cacheflush.h> |
22 | 22 | ||
23 | #include "sram.h" | 23 | #include <asm/arch/sram.h> |
24 | |||
25 | #define OMAP1_SRAM_PA 0x20000000 | ||
26 | #define OMAP1_SRAM_VA 0xd0000000 | ||
27 | #define OMAP2_SRAM_PA 0x40200000 | ||
28 | #define OMAP2_SRAM_VA 0xd0000000 | ||
24 | 29 | ||
25 | #define OMAP1_SRAM_BASE 0xd0000000 | ||
26 | #define OMAP1_SRAM_START 0x20000000 | ||
27 | #define SRAM_BOOTLOADER_SZ 0x80 | 30 | #define SRAM_BOOTLOADER_SZ 0x80 |
28 | 31 | ||
29 | static unsigned long omap_sram_base; | 32 | static unsigned long omap_sram_base; |
@@ -31,37 +34,40 @@ static unsigned long omap_sram_size; | |||
31 | static unsigned long omap_sram_ceil; | 34 | static unsigned long omap_sram_ceil; |
32 | 35 | ||
33 | /* | 36 | /* |
34 | * The amount of SRAM depends on the core type: | 37 | * The amount of SRAM depends on the core type. |
35 | * 730 = 200K, 1510 = 512K, 5912 = 256K, 1610 = 16K, 1710 = 16K | ||
36 | * Note that we cannot try to test for SRAM here because writes | 38 | * Note that we cannot try to test for SRAM here because writes |
37 | * to secure SRAM will hang the system. Also the SRAM is not | 39 | * to secure SRAM will hang the system. Also the SRAM is not |
38 | * yet mapped at this point. | 40 | * yet mapped at this point. |
39 | */ | 41 | */ |
40 | void __init omap_detect_sram(void) | 42 | void __init omap_detect_sram(void) |
41 | { | 43 | { |
42 | omap_sram_base = OMAP1_SRAM_BASE; | 44 | if (!cpu_is_omap24xx()) |
45 | omap_sram_base = OMAP1_SRAM_VA; | ||
46 | else | ||
47 | omap_sram_base = OMAP2_SRAM_VA; | ||
43 | 48 | ||
44 | if (cpu_is_omap730()) | 49 | if (cpu_is_omap730()) |
45 | omap_sram_size = 0x32000; | 50 | omap_sram_size = 0x32000; /* 200K */ |
46 | else if (cpu_is_omap1510()) | 51 | else if (cpu_is_omap15xx()) |
47 | omap_sram_size = 0x80000; | 52 | omap_sram_size = 0x30000; /* 192K */ |
48 | else if (cpu_is_omap1610() || cpu_is_omap1621() || cpu_is_omap1710()) | 53 | else if (cpu_is_omap1610() || cpu_is_omap1621() || cpu_is_omap1710()) |
49 | omap_sram_size = 0x4000; | 54 | omap_sram_size = 0x4000; /* 16K */ |
50 | else if (cpu_is_omap1611()) | 55 | else if (cpu_is_omap1611()) |
51 | omap_sram_size = 0x3e800; | 56 | omap_sram_size = 0x3e800; /* 250K */ |
57 | else if (cpu_is_omap2420()) | ||
58 | omap_sram_size = 0xa0014; /* 640K */ | ||
52 | else { | 59 | else { |
53 | printk(KERN_ERR "Could not detect SRAM size\n"); | 60 | printk(KERN_ERR "Could not detect SRAM size\n"); |
54 | omap_sram_size = 0x4000; | 61 | omap_sram_size = 0x4000; |
55 | } | 62 | } |
56 | 63 | ||
57 | printk(KERN_INFO "SRAM size: 0x%lx\n", omap_sram_size); | ||
58 | omap_sram_ceil = omap_sram_base + omap_sram_size; | 64 | omap_sram_ceil = omap_sram_base + omap_sram_size; |
59 | } | 65 | } |
60 | 66 | ||
61 | static struct map_desc omap_sram_io_desc[] __initdata = { | 67 | static struct map_desc omap_sram_io_desc[] __initdata = { |
62 | { /* .length gets filled in at runtime */ | 68 | { /* .length gets filled in at runtime */ |
63 | .virtual = OMAP1_SRAM_BASE, | 69 | .virtual = OMAP1_SRAM_VA, |
64 | .pfn = __phys_to_pfn(OMAP1_SRAM_START), | 70 | .pfn = __phys_to_pfn(OMAP1_SRAM_PA), |
65 | .type = MT_DEVICE | 71 | .type = MT_DEVICE |
66 | } | 72 | } |
67 | }; | 73 | }; |
@@ -76,10 +82,19 @@ void __init omap_map_sram(void) | |||
76 | if (omap_sram_size == 0) | 82 | if (omap_sram_size == 0) |
77 | return; | 83 | return; |
78 | 84 | ||
85 | if (cpu_is_omap24xx()) { | ||
86 | omap_sram_io_desc[0].virtual = OMAP2_SRAM_VA; | ||
87 | omap_sram_io_desc[0].pfn = __phys_to_pfn(OMAP2_SRAM_PA); | ||
88 | } | ||
89 | |||
79 | omap_sram_io_desc[0].length = (omap_sram_size + PAGE_SIZE-1)/PAGE_SIZE; | 90 | omap_sram_io_desc[0].length = (omap_sram_size + PAGE_SIZE-1)/PAGE_SIZE; |
80 | omap_sram_io_desc[0].length *= PAGE_SIZE; | 91 | omap_sram_io_desc[0].length *= PAGE_SIZE; |
81 | iotable_init(omap_sram_io_desc, ARRAY_SIZE(omap_sram_io_desc)); | 92 | iotable_init(omap_sram_io_desc, ARRAY_SIZE(omap_sram_io_desc)); |
82 | 93 | ||
94 | printk(KERN_INFO "SRAM: Mapped pa 0x%08lx to va 0x%08lx size: 0x%lx\n", | ||
95 | omap_sram_io_desc[0].pfn, omap_sram_io_desc[0].virtual, | ||
96 | omap_sram_io_desc[0].length); | ||
97 | |||
83 | /* | 98 | /* |
84 | * Looks like we need to preserve some bootloader code at the | 99 | * Looks like we need to preserve some bootloader code at the |
85 | * beginning of SRAM for jumping to flash for reboot to work... | 100 | * beginning of SRAM for jumping to flash for reboot to work... |
@@ -88,16 +103,6 @@ void __init omap_map_sram(void) | |||
88 | omap_sram_size - SRAM_BOOTLOADER_SZ); | 103 | omap_sram_size - SRAM_BOOTLOADER_SZ); |
89 | } | 104 | } |
90 | 105 | ||
91 | static void (*_omap_sram_reprogram_clock)(u32 dpllctl, u32 ckctl) = NULL; | ||
92 | |||
93 | void omap_sram_reprogram_clock(u32 dpllctl, u32 ckctl) | ||
94 | { | ||
95 | if (_omap_sram_reprogram_clock == NULL) | ||
96 | panic("Cannot use SRAM"); | ||
97 | |||
98 | return _omap_sram_reprogram_clock(dpllctl, ckctl); | ||
99 | } | ||
100 | |||
101 | void * omap_sram_push(void * start, unsigned long size) | 106 | void * omap_sram_push(void * start, unsigned long size) |
102 | { | 107 | { |
103 | if (size > (omap_sram_ceil - (omap_sram_base + SRAM_BOOTLOADER_SZ))) { | 108 | if (size > (omap_sram_ceil - (omap_sram_base + SRAM_BOOTLOADER_SZ))) { |
@@ -111,10 +116,94 @@ void * omap_sram_push(void * start, unsigned long size) | |||
111 | return (void *)omap_sram_ceil; | 116 | return (void *)omap_sram_ceil; |
112 | } | 117 | } |
113 | 118 | ||
114 | void __init omap_sram_init(void) | 119 | static void omap_sram_error(void) |
120 | { | ||
121 | panic("Uninitialized SRAM function\n"); | ||
122 | } | ||
123 | |||
124 | #ifdef CONFIG_ARCH_OMAP1 | ||
125 | |||
126 | static void (*_omap_sram_reprogram_clock)(u32 dpllctl, u32 ckctl); | ||
127 | |||
128 | void omap_sram_reprogram_clock(u32 dpllctl, u32 ckctl) | ||
129 | { | ||
130 | if (!_omap_sram_reprogram_clock) | ||
131 | omap_sram_error(); | ||
132 | |||
133 | return _omap_sram_reprogram_clock(dpllctl, ckctl); | ||
134 | } | ||
135 | |||
136 | int __init omap1_sram_init(void) | ||
115 | { | 137 | { |
116 | omap_detect_sram(); | ||
117 | omap_map_sram(); | ||
118 | _omap_sram_reprogram_clock = omap_sram_push(sram_reprogram_clock, | 138 | _omap_sram_reprogram_clock = omap_sram_push(sram_reprogram_clock, |
119 | sram_reprogram_clock_sz); | 139 | sram_reprogram_clock_sz); |
140 | |||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | #else | ||
145 | #define omap1_sram_init() do {} while (0) | ||
146 | #endif | ||
147 | |||
148 | #ifdef CONFIG_ARCH_OMAP2 | ||
149 | |||
150 | static void (*_omap2_sram_ddr_init)(u32 *slow_dll_ctrl, u32 fast_dll_ctrl, | ||
151 | u32 base_cs, u32 force_unlock); | ||
152 | |||
153 | void omap2_sram_ddr_init(u32 *slow_dll_ctrl, u32 fast_dll_ctrl, | ||
154 | u32 base_cs, u32 force_unlock) | ||
155 | { | ||
156 | if (!_omap2_sram_ddr_init) | ||
157 | omap_sram_error(); | ||
158 | |||
159 | return _omap2_sram_ddr_init(slow_dll_ctrl, fast_dll_ctrl, | ||
160 | base_cs, force_unlock); | ||
161 | } | ||
162 | |||
163 | static void (*_omap2_sram_reprogram_sdrc)(u32 perf_level, u32 dll_val, | ||
164 | u32 mem_type); | ||
165 | |||
166 | void omap2_sram_reprogram_sdrc(u32 perf_level, u32 dll_val, u32 mem_type) | ||
167 | { | ||
168 | if (!_omap2_sram_reprogram_sdrc) | ||
169 | omap_sram_error(); | ||
170 | |||
171 | return _omap2_sram_reprogram_sdrc(perf_level, dll_val, mem_type); | ||
172 | } | ||
173 | |||
174 | static u32 (*_omap2_set_prcm)(u32 dpll_ctrl_val, u32 sdrc_rfr_val, int bypass); | ||
175 | |||
176 | u32 omap2_set_prcm(u32 dpll_ctrl_val, u32 sdrc_rfr_val, int bypass) | ||
177 | { | ||
178 | if (!_omap2_set_prcm) | ||
179 | omap_sram_error(); | ||
180 | |||
181 | return _omap2_set_prcm(dpll_ctrl_val, sdrc_rfr_val, bypass); | ||
182 | } | ||
183 | |||
184 | int __init omap2_sram_init(void) | ||
185 | { | ||
186 | _omap2_sram_ddr_init = omap_sram_push(sram_ddr_init, sram_ddr_init_sz); | ||
187 | |||
188 | _omap2_sram_reprogram_sdrc = omap_sram_push(sram_reprogram_sdrc, | ||
189 | sram_reprogram_sdrc_sz); | ||
190 | _omap2_set_prcm = omap_sram_push(sram_set_prcm, sram_set_prcm_sz); | ||
191 | |||
192 | return 0; | ||
193 | } | ||
194 | #else | ||
195 | #define omap2_sram_init() do {} while (0) | ||
196 | #endif | ||
197 | |||
198 | int __init omap_sram_init(void) | ||
199 | { | ||
200 | omap_detect_sram(); | ||
201 | omap_map_sram(); | ||
202 | |||
203 | if (!cpu_is_omap24xx()) | ||
204 | omap1_sram_init(); | ||
205 | else | ||
206 | omap2_sram_init(); | ||
207 | |||
208 | return 0; | ||
120 | } | 209 | } |
diff --git a/arch/arm/plat-omap/sram.h b/arch/arm/plat-omap/sram.h deleted file mode 100644 index 71984efa6ae8..000000000000 --- a/arch/arm/plat-omap/sram.h +++ /dev/null | |||
@@ -1,21 +0,0 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/plat-omap/sram.h | ||
3 | * | ||
4 | * Interface for functions that need to be run in internal SRAM | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #ifndef __ARCH_ARM_OMAP_SRAM_H | ||
12 | #define __ARCH_ARM_OMAP_SRAM_H | ||
13 | |||
14 | extern void * omap_sram_push(void * start, unsigned long size); | ||
15 | extern void omap_sram_reprogram_clock(u32 dpllctl, u32 ckctl); | ||
16 | |||
17 | /* Do not use these */ | ||
18 | extern void sram_reprogram_clock(u32 ckctl, u32 dpllctl); | ||
19 | extern unsigned long sram_reprogram_clock_sz; | ||
20 | |||
21 | #endif | ||
diff --git a/arch/arm/plat-omap/usb.c b/arch/arm/plat-omap/usb.c index 205e2d0b826d..00afc7a8c2ab 100644 --- a/arch/arm/plat-omap/usb.c +++ b/arch/arm/plat-omap/usb.c | |||
@@ -91,6 +91,8 @@ EXPORT_SYMBOL(otg_set_transceiver); | |||
91 | 91 | ||
92 | /*-------------------------------------------------------------------------*/ | 92 | /*-------------------------------------------------------------------------*/ |
93 | 93 | ||
94 | #if defined(CONFIG_ARCH_OMAP_OTG) || defined(CONFIG_ARCH_OMAP15XX) | ||
95 | |||
94 | static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device) | 96 | static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device) |
95 | { | 97 | { |
96 | u32 syscon1 = 0; | 98 | u32 syscon1 = 0; |
@@ -271,6 +273,8 @@ static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup) | |||
271 | return syscon1 << 24; | 273 | return syscon1 << 24; |
272 | } | 274 | } |
273 | 275 | ||
276 | #endif | ||
277 | |||
274 | /*-------------------------------------------------------------------------*/ | 278 | /*-------------------------------------------------------------------------*/ |
275 | 279 | ||
276 | #if defined(CONFIG_USB_GADGET_OMAP) || \ | 280 | #if defined(CONFIG_USB_GADGET_OMAP) || \ |
@@ -494,7 +498,7 @@ static inline void omap_otg_init(struct omap_usb_config *config) {} | |||
494 | 498 | ||
495 | /*-------------------------------------------------------------------------*/ | 499 | /*-------------------------------------------------------------------------*/ |
496 | 500 | ||
497 | #ifdef CONFIG_ARCH_OMAP1510 | 501 | #ifdef CONFIG_ARCH_OMAP15XX |
498 | 502 | ||
499 | #define ULPD_DPLL_CTRL_REG __REG16(ULPD_DPLL_CTRL) | 503 | #define ULPD_DPLL_CTRL_REG __REG16(ULPD_DPLL_CTRL) |
500 | #define DPLL_IOB (1 << 13) | 504 | #define DPLL_IOB (1 << 13) |
@@ -507,7 +511,6 @@ static inline void omap_otg_init(struct omap_usb_config *config) {} | |||
507 | 511 | ||
508 | static void __init omap_1510_usb_init(struct omap_usb_config *config) | 512 | static void __init omap_1510_usb_init(struct omap_usb_config *config) |
509 | { | 513 | { |
510 | int status; | ||
511 | unsigned int val; | 514 | unsigned int val; |
512 | 515 | ||
513 | omap_usb0_init(config->pins[0], is_usb0_device(config)); | 516 | omap_usb0_init(config->pins[0], is_usb0_device(config)); |
@@ -539,6 +542,8 @@ static void __init omap_1510_usb_init(struct omap_usb_config *config) | |||
539 | 542 | ||
540 | #ifdef CONFIG_USB_GADGET_OMAP | 543 | #ifdef CONFIG_USB_GADGET_OMAP |
541 | if (config->register_dev) { | 544 | if (config->register_dev) { |
545 | int status; | ||
546 | |||
542 | udc_device.dev.platform_data = config; | 547 | udc_device.dev.platform_data = config; |
543 | status = platform_device_register(&udc_device); | 548 | status = platform_device_register(&udc_device); |
544 | if (status) | 549 | if (status) |
@@ -549,6 +554,8 @@ static void __init omap_1510_usb_init(struct omap_usb_config *config) | |||
549 | 554 | ||
550 | #if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) | 555 | #if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) |
551 | if (config->register_host) { | 556 | if (config->register_host) { |
557 | int status; | ||
558 | |||
552 | ohci_device.dev.platform_data = config; | 559 | ohci_device.dev.platform_data = config; |
553 | status = platform_device_register(&ohci_device); | 560 | status = platform_device_register(&ohci_device); |
554 | if (status) | 561 | if (status) |
diff --git a/arch/i386/pci/fixup.c b/arch/i386/pci/fixup.c index 3984226a8b98..eeb1b1f2d548 100644 --- a/arch/i386/pci/fixup.c +++ b/arch/i386/pci/fixup.c | |||
@@ -433,9 +433,8 @@ static void __devinit pci_post_fixup_toshiba_ohci1394(struct pci_dev *dev) | |||
433 | return; /* only applies to certain Toshibas (so far) */ | 433 | return; /* only applies to certain Toshibas (so far) */ |
434 | 434 | ||
435 | /* Restore config space on Toshiba laptops */ | 435 | /* Restore config space on Toshiba laptops */ |
436 | mdelay(10); | ||
437 | pci_write_config_word(dev, PCI_CACHE_LINE_SIZE, toshiba_line_size); | 436 | pci_write_config_word(dev, PCI_CACHE_LINE_SIZE, toshiba_line_size); |
438 | pci_write_config_word(dev, PCI_INTERRUPT_LINE, dev->irq); | 437 | pci_read_config_byte(dev, PCI_INTERRUPT_LINE, (u8 *)&dev->irq); |
439 | pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, | 438 | pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, |
440 | pci_resource_start(dev, 0)); | 439 | pci_resource_start(dev, 0)); |
441 | pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, | 440 | pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, |
diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c index f72ea6aebcb1..a3aa45cbcfa0 100644 --- a/arch/ia64/kernel/efi.c +++ b/arch/ia64/kernel/efi.c | |||
@@ -987,7 +987,7 @@ efi_initialize_iomem_resources(struct resource *code_resource, | |||
987 | break; | 987 | break; |
988 | } | 988 | } |
989 | 989 | ||
990 | if ((res = kcalloc(1, sizeof(struct resource), GFP_KERNEL)) == NULL) { | 990 | if ((res = kzalloc(sizeof(struct resource), GFP_KERNEL)) == NULL) { |
991 | printk(KERN_ERR "failed to alocate resource for iomem\n"); | 991 | printk(KERN_ERR "failed to alocate resource for iomem\n"); |
992 | return; | 992 | return; |
993 | } | 993 | } |
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c index 96736a119c91..801eeaeaf3de 100644 --- a/arch/ia64/kernel/kprobes.c +++ b/arch/ia64/kernel/kprobes.c | |||
@@ -347,7 +347,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) | |||
347 | ((struct fnptr *)kretprobe_trampoline)->ip; | 347 | ((struct fnptr *)kretprobe_trampoline)->ip; |
348 | 348 | ||
349 | spin_lock_irqsave(&kretprobe_lock, flags); | 349 | spin_lock_irqsave(&kretprobe_lock, flags); |
350 | head = kretprobe_inst_table_head(current); | 350 | head = kretprobe_inst_table_head(current); |
351 | 351 | ||
352 | /* | 352 | /* |
353 | * It is possible to have multiple instances associated with a given | 353 | * It is possible to have multiple instances associated with a given |
@@ -363,9 +363,9 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) | |||
363 | * kretprobe_trampoline | 363 | * kretprobe_trampoline |
364 | */ | 364 | */ |
365 | hlist_for_each_entry_safe(ri, node, tmp, head, hlist) { | 365 | hlist_for_each_entry_safe(ri, node, tmp, head, hlist) { |
366 | if (ri->task != current) | 366 | if (ri->task != current) |
367 | /* another task is sharing our hash bucket */ | 367 | /* another task is sharing our hash bucket */ |
368 | continue; | 368 | continue; |
369 | 369 | ||
370 | if (ri->rp && ri->rp->handler) | 370 | if (ri->rp && ri->rp->handler) |
371 | ri->rp->handler(ri, regs); | 371 | ri->rp->handler(ri, regs); |
@@ -394,7 +394,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) | |||
394 | * kprobe_handler() that we don't want the post_handler | 394 | * kprobe_handler() that we don't want the post_handler |
395 | * to run (and have re-enabled preemption) | 395 | * to run (and have re-enabled preemption) |
396 | */ | 396 | */ |
397 | return 1; | 397 | return 1; |
398 | } | 398 | } |
399 | 399 | ||
400 | /* Called with kretprobe_lock held */ | 400 | /* Called with kretprobe_lock held */ |
@@ -739,12 +739,16 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, | |||
739 | 739 | ||
740 | switch(val) { | 740 | switch(val) { |
741 | case DIE_BREAK: | 741 | case DIE_BREAK: |
742 | if (pre_kprobes_handler(args)) | 742 | /* err is break number from ia64_bad_break() */ |
743 | ret = NOTIFY_STOP; | 743 | if (args->err == 0x80200 || args->err == 0x80300) |
744 | if (pre_kprobes_handler(args)) | ||
745 | ret = NOTIFY_STOP; | ||
744 | break; | 746 | break; |
745 | case DIE_SS: | 747 | case DIE_FAULT: |
746 | if (post_kprobes_handler(args->regs)) | 748 | /* err is vector number from ia64_fault() */ |
747 | ret = NOTIFY_STOP; | 749 | if (args->err == 36) |
750 | if (post_kprobes_handler(args->regs)) | ||
751 | ret = NOTIFY_STOP; | ||
748 | break; | 752 | break; |
749 | case DIE_PAGE_FAULT: | 753 | case DIE_PAGE_FAULT: |
750 | /* kprobe_running() needs smp_processor_id() */ | 754 | /* kprobe_running() needs smp_processor_id() */ |
diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c index 52c47da17246..355af15287c7 100644 --- a/arch/ia64/kernel/mca.c +++ b/arch/ia64/kernel/mca.c | |||
@@ -51,6 +51,9 @@ | |||
51 | * | 51 | * |
52 | * 2005-08-12 Keith Owens <kaos@sgi.com> | 52 | * 2005-08-12 Keith Owens <kaos@sgi.com> |
53 | * Convert MCA/INIT handlers to use per event stacks and SAL/OS state. | 53 | * Convert MCA/INIT handlers to use per event stacks and SAL/OS state. |
54 | * | ||
55 | * 2005-10-07 Keith Owens <kaos@sgi.com> | ||
56 | * Add notify_die() hooks. | ||
54 | */ | 57 | */ |
55 | #include <linux/config.h> | 58 | #include <linux/config.h> |
56 | #include <linux/types.h> | 59 | #include <linux/types.h> |
@@ -58,7 +61,6 @@ | |||
58 | #include <linux/sched.h> | 61 | #include <linux/sched.h> |
59 | #include <linux/interrupt.h> | 62 | #include <linux/interrupt.h> |
60 | #include <linux/irq.h> | 63 | #include <linux/irq.h> |
61 | #include <linux/kallsyms.h> | ||
62 | #include <linux/smp_lock.h> | 64 | #include <linux/smp_lock.h> |
63 | #include <linux/bootmem.h> | 65 | #include <linux/bootmem.h> |
64 | #include <linux/acpi.h> | 66 | #include <linux/acpi.h> |
@@ -69,6 +71,7 @@ | |||
69 | #include <linux/workqueue.h> | 71 | #include <linux/workqueue.h> |
70 | 72 | ||
71 | #include <asm/delay.h> | 73 | #include <asm/delay.h> |
74 | #include <asm/kdebug.h> | ||
72 | #include <asm/machvec.h> | 75 | #include <asm/machvec.h> |
73 | #include <asm/meminit.h> | 76 | #include <asm/meminit.h> |
74 | #include <asm/page.h> | 77 | #include <asm/page.h> |
@@ -132,6 +135,14 @@ extern void salinfo_log_wakeup(int type, u8 *buffer, u64 size, int irqsafe); | |||
132 | 135 | ||
133 | static int mca_init; | 136 | static int mca_init; |
134 | 137 | ||
138 | |||
139 | static void inline | ||
140 | ia64_mca_spin(const char *func) | ||
141 | { | ||
142 | printk(KERN_EMERG "%s: spinning here, not returning to SAL\n", func); | ||
143 | while (1) | ||
144 | cpu_relax(); | ||
145 | } | ||
135 | /* | 146 | /* |
136 | * IA64_MCA log support | 147 | * IA64_MCA log support |
137 | */ | 148 | */ |
@@ -526,13 +537,16 @@ ia64_mca_wakeup_all(void) | |||
526 | * Outputs : None | 537 | * Outputs : None |
527 | */ | 538 | */ |
528 | static irqreturn_t | 539 | static irqreturn_t |
529 | ia64_mca_rendez_int_handler(int rendez_irq, void *arg, struct pt_regs *ptregs) | 540 | ia64_mca_rendez_int_handler(int rendez_irq, void *arg, struct pt_regs *regs) |
530 | { | 541 | { |
531 | unsigned long flags; | 542 | unsigned long flags; |
532 | int cpu = smp_processor_id(); | 543 | int cpu = smp_processor_id(); |
533 | 544 | ||
534 | /* Mask all interrupts */ | 545 | /* Mask all interrupts */ |
535 | local_irq_save(flags); | 546 | local_irq_save(flags); |
547 | if (notify_die(DIE_MCA_RENDZVOUS_ENTER, "MCA", regs, 0, 0, 0) | ||
548 | == NOTIFY_STOP) | ||
549 | ia64_mca_spin(__FUNCTION__); | ||
536 | 550 | ||
537 | ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_DONE; | 551 | ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_DONE; |
538 | /* Register with the SAL monarch that the slave has | 552 | /* Register with the SAL monarch that the slave has |
@@ -540,10 +554,18 @@ ia64_mca_rendez_int_handler(int rendez_irq, void *arg, struct pt_regs *ptregs) | |||
540 | */ | 554 | */ |
541 | ia64_sal_mc_rendez(); | 555 | ia64_sal_mc_rendez(); |
542 | 556 | ||
557 | if (notify_die(DIE_MCA_RENDZVOUS_PROCESS, "MCA", regs, 0, 0, 0) | ||
558 | == NOTIFY_STOP) | ||
559 | ia64_mca_spin(__FUNCTION__); | ||
560 | |||
543 | /* Wait for the monarch cpu to exit. */ | 561 | /* Wait for the monarch cpu to exit. */ |
544 | while (monarch_cpu != -1) | 562 | while (monarch_cpu != -1) |
545 | cpu_relax(); /* spin until monarch leaves */ | 563 | cpu_relax(); /* spin until monarch leaves */ |
546 | 564 | ||
565 | if (notify_die(DIE_MCA_RENDZVOUS_LEAVE, "MCA", regs, 0, 0, 0) | ||
566 | == NOTIFY_STOP) | ||
567 | ia64_mca_spin(__FUNCTION__); | ||
568 | |||
547 | /* Enable all interrupts */ | 569 | /* Enable all interrupts */ |
548 | local_irq_restore(flags); | 570 | local_irq_restore(flags); |
549 | return IRQ_HANDLED; | 571 | return IRQ_HANDLED; |
@@ -933,6 +955,9 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw, | |||
933 | oops_in_progress = 1; /* FIXME: make printk NMI/MCA/INIT safe */ | 955 | oops_in_progress = 1; /* FIXME: make printk NMI/MCA/INIT safe */ |
934 | previous_current = ia64_mca_modify_original_stack(regs, sw, sos, "MCA"); | 956 | previous_current = ia64_mca_modify_original_stack(regs, sw, sos, "MCA"); |
935 | monarch_cpu = cpu; | 957 | monarch_cpu = cpu; |
958 | if (notify_die(DIE_MCA_MONARCH_ENTER, "MCA", regs, 0, 0, 0) | ||
959 | == NOTIFY_STOP) | ||
960 | ia64_mca_spin(__FUNCTION__); | ||
936 | ia64_wait_for_slaves(cpu); | 961 | ia64_wait_for_slaves(cpu); |
937 | 962 | ||
938 | /* Wakeup all the processors which are spinning in the rendezvous loop. | 963 | /* Wakeup all the processors which are spinning in the rendezvous loop. |
@@ -942,6 +967,9 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw, | |||
942 | * spinning in SAL does not work. | 967 | * spinning in SAL does not work. |
943 | */ | 968 | */ |
944 | ia64_mca_wakeup_all(); | 969 | ia64_mca_wakeup_all(); |
970 | if (notify_die(DIE_MCA_MONARCH_PROCESS, "MCA", regs, 0, 0, 0) | ||
971 | == NOTIFY_STOP) | ||
972 | ia64_mca_spin(__FUNCTION__); | ||
945 | 973 | ||
946 | /* Get the MCA error record and log it */ | 974 | /* Get the MCA error record and log it */ |
947 | ia64_mca_log_sal_error_record(SAL_INFO_TYPE_MCA); | 975 | ia64_mca_log_sal_error_record(SAL_INFO_TYPE_MCA); |
@@ -960,6 +988,9 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw, | |||
960 | ia64_sal_clear_state_info(SAL_INFO_TYPE_MCA); | 988 | ia64_sal_clear_state_info(SAL_INFO_TYPE_MCA); |
961 | sos->os_status = IA64_MCA_CORRECTED; | 989 | sos->os_status = IA64_MCA_CORRECTED; |
962 | } | 990 | } |
991 | if (notify_die(DIE_MCA_MONARCH_LEAVE, "MCA", regs, 0, 0, recover) | ||
992 | == NOTIFY_STOP) | ||
993 | ia64_mca_spin(__FUNCTION__); | ||
963 | 994 | ||
964 | set_curr_task(cpu, previous_current); | 995 | set_curr_task(cpu, previous_current); |
965 | monarch_cpu = -1; | 996 | monarch_cpu = -1; |
@@ -1188,6 +1219,37 @@ ia64_mca_cpe_poll (unsigned long dummy) | |||
1188 | 1219 | ||
1189 | #endif /* CONFIG_ACPI */ | 1220 | #endif /* CONFIG_ACPI */ |
1190 | 1221 | ||
1222 | static int | ||
1223 | default_monarch_init_process(struct notifier_block *self, unsigned long val, void *data) | ||
1224 | { | ||
1225 | int c; | ||
1226 | struct task_struct *g, *t; | ||
1227 | if (val != DIE_INIT_MONARCH_PROCESS) | ||
1228 | return NOTIFY_DONE; | ||
1229 | printk(KERN_ERR "Processes interrupted by INIT -"); | ||
1230 | for_each_online_cpu(c) { | ||
1231 | struct ia64_sal_os_state *s; | ||
1232 | t = __va(__per_cpu_mca[c] + IA64_MCA_CPU_INIT_STACK_OFFSET); | ||
1233 | s = (struct ia64_sal_os_state *)((char *)t + MCA_SOS_OFFSET); | ||
1234 | g = s->prev_task; | ||
1235 | if (g) { | ||
1236 | if (g->pid) | ||
1237 | printk(" %d", g->pid); | ||
1238 | else | ||
1239 | printk(" %d (cpu %d task 0x%p)", g->pid, task_cpu(g), g); | ||
1240 | } | ||
1241 | } | ||
1242 | printk("\n\n"); | ||
1243 | if (read_trylock(&tasklist_lock)) { | ||
1244 | do_each_thread (g, t) { | ||
1245 | printk("\nBacktrace of pid %d (%s)\n", t->pid, t->comm); | ||
1246 | show_stack(t, NULL); | ||
1247 | } while_each_thread (g, t); | ||
1248 | read_unlock(&tasklist_lock); | ||
1249 | } | ||
1250 | return NOTIFY_DONE; | ||
1251 | } | ||
1252 | |||
1191 | /* | 1253 | /* |
1192 | * C portion of the OS INIT handler | 1254 | * C portion of the OS INIT handler |
1193 | * | 1255 | * |
@@ -1212,8 +1274,7 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw, | |||
1212 | static atomic_t slaves; | 1274 | static atomic_t slaves; |
1213 | static atomic_t monarchs; | 1275 | static atomic_t monarchs; |
1214 | task_t *previous_current; | 1276 | task_t *previous_current; |
1215 | int cpu = smp_processor_id(), c; | 1277 | int cpu = smp_processor_id(); |
1216 | struct task_struct *g, *t; | ||
1217 | 1278 | ||
1218 | oops_in_progress = 1; /* FIXME: make printk NMI/MCA/INIT safe */ | 1279 | oops_in_progress = 1; /* FIXME: make printk NMI/MCA/INIT safe */ |
1219 | console_loglevel = 15; /* make sure printks make it to console */ | 1280 | console_loglevel = 15; /* make sure printks make it to console */ |
@@ -1253,8 +1314,17 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw, | |||
1253 | ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_INIT; | 1314 | ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_INIT; |
1254 | while (monarch_cpu == -1) | 1315 | while (monarch_cpu == -1) |
1255 | cpu_relax(); /* spin until monarch enters */ | 1316 | cpu_relax(); /* spin until monarch enters */ |
1317 | if (notify_die(DIE_INIT_SLAVE_ENTER, "INIT", regs, 0, 0, 0) | ||
1318 | == NOTIFY_STOP) | ||
1319 | ia64_mca_spin(__FUNCTION__); | ||
1320 | if (notify_die(DIE_INIT_SLAVE_PROCESS, "INIT", regs, 0, 0, 0) | ||
1321 | == NOTIFY_STOP) | ||
1322 | ia64_mca_spin(__FUNCTION__); | ||
1256 | while (monarch_cpu != -1) | 1323 | while (monarch_cpu != -1) |
1257 | cpu_relax(); /* spin until monarch leaves */ | 1324 | cpu_relax(); /* spin until monarch leaves */ |
1325 | if (notify_die(DIE_INIT_SLAVE_LEAVE, "INIT", regs, 0, 0, 0) | ||
1326 | == NOTIFY_STOP) | ||
1327 | ia64_mca_spin(__FUNCTION__); | ||
1258 | printk("Slave on cpu %d returning to normal service.\n", cpu); | 1328 | printk("Slave on cpu %d returning to normal service.\n", cpu); |
1259 | set_curr_task(cpu, previous_current); | 1329 | set_curr_task(cpu, previous_current); |
1260 | ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE; | 1330 | ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE; |
@@ -1263,6 +1333,9 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw, | |||
1263 | } | 1333 | } |
1264 | 1334 | ||
1265 | monarch_cpu = cpu; | 1335 | monarch_cpu = cpu; |
1336 | if (notify_die(DIE_INIT_MONARCH_ENTER, "INIT", regs, 0, 0, 0) | ||
1337 | == NOTIFY_STOP) | ||
1338 | ia64_mca_spin(__FUNCTION__); | ||
1266 | 1339 | ||
1267 | /* | 1340 | /* |
1268 | * Wait for a bit. On some machines (e.g., HP's zx2000 and zx6000, INIT can be | 1341 | * Wait for a bit. On some machines (e.g., HP's zx2000 and zx6000, INIT can be |
@@ -1273,27 +1346,16 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw, | |||
1273 | printk("Delaying for 5 seconds...\n"); | 1346 | printk("Delaying for 5 seconds...\n"); |
1274 | udelay(5*1000000); | 1347 | udelay(5*1000000); |
1275 | ia64_wait_for_slaves(cpu); | 1348 | ia64_wait_for_slaves(cpu); |
1276 | printk(KERN_ERR "Processes interrupted by INIT -"); | 1349 | /* If nobody intercepts DIE_INIT_MONARCH_PROCESS then we drop through |
1277 | for_each_online_cpu(c) { | 1350 | * to default_monarch_init_process() above and just print all the |
1278 | struct ia64_sal_os_state *s; | 1351 | * tasks. |
1279 | t = __va(__per_cpu_mca[c] + IA64_MCA_CPU_INIT_STACK_OFFSET); | 1352 | */ |
1280 | s = (struct ia64_sal_os_state *)((char *)t + MCA_SOS_OFFSET); | 1353 | if (notify_die(DIE_INIT_MONARCH_PROCESS, "INIT", regs, 0, 0, 0) |
1281 | g = s->prev_task; | 1354 | == NOTIFY_STOP) |
1282 | if (g) { | 1355 | ia64_mca_spin(__FUNCTION__); |
1283 | if (g->pid) | 1356 | if (notify_die(DIE_INIT_MONARCH_LEAVE, "INIT", regs, 0, 0, 0) |
1284 | printk(" %d", g->pid); | 1357 | == NOTIFY_STOP) |
1285 | else | 1358 | ia64_mca_spin(__FUNCTION__); |
1286 | printk(" %d (cpu %d task 0x%p)", g->pid, task_cpu(g), g); | ||
1287 | } | ||
1288 | } | ||
1289 | printk("\n\n"); | ||
1290 | if (read_trylock(&tasklist_lock)) { | ||
1291 | do_each_thread (g, t) { | ||
1292 | printk("\nBacktrace of pid %d (%s)\n", t->pid, t->comm); | ||
1293 | show_stack(t, NULL); | ||
1294 | } while_each_thread (g, t); | ||
1295 | read_unlock(&tasklist_lock); | ||
1296 | } | ||
1297 | printk("\nINIT dump complete. Monarch on cpu %d returning to normal service.\n", cpu); | 1359 | printk("\nINIT dump complete. Monarch on cpu %d returning to normal service.\n", cpu); |
1298 | atomic_dec(&monarchs); | 1360 | atomic_dec(&monarchs); |
1299 | set_curr_task(cpu, previous_current); | 1361 | set_curr_task(cpu, previous_current); |
@@ -1462,6 +1524,10 @@ ia64_mca_init(void) | |||
1462 | s64 rc; | 1524 | s64 rc; |
1463 | struct ia64_sal_retval isrv; | 1525 | struct ia64_sal_retval isrv; |
1464 | u64 timeout = IA64_MCA_RENDEZ_TIMEOUT; /* platform specific */ | 1526 | u64 timeout = IA64_MCA_RENDEZ_TIMEOUT; /* platform specific */ |
1527 | static struct notifier_block default_init_monarch_nb = { | ||
1528 | .notifier_call = default_monarch_init_process, | ||
1529 | .priority = 0/* we need to notified last */ | ||
1530 | }; | ||
1465 | 1531 | ||
1466 | IA64_MCA_DEBUG("%s: begin\n", __FUNCTION__); | 1532 | IA64_MCA_DEBUG("%s: begin\n", __FUNCTION__); |
1467 | 1533 | ||
@@ -1555,6 +1621,10 @@ ia64_mca_init(void) | |||
1555 | "(status %ld)\n", rc); | 1621 | "(status %ld)\n", rc); |
1556 | return; | 1622 | return; |
1557 | } | 1623 | } |
1624 | if (register_die_notifier(&default_init_monarch_nb)) { | ||
1625 | printk(KERN_ERR "Failed to register default monarch INIT process\n"); | ||
1626 | return; | ||
1627 | } | ||
1558 | 1628 | ||
1559 | IA64_MCA_DEBUG("%s: registered OS INIT handler with SAL\n", __FUNCTION__); | 1629 | IA64_MCA_DEBUG("%s: registered OS INIT handler with SAL\n", __FUNCTION__); |
1560 | 1630 | ||
diff --git a/arch/ia64/kernel/mca_drv.c b/arch/ia64/kernel/mca_drv.c index eb39bc9c133b..3492e3211a44 100644 --- a/arch/ia64/kernel/mca_drv.c +++ b/arch/ia64/kernel/mca_drv.c | |||
@@ -547,9 +547,20 @@ recover_from_processor_error(int platform, slidx_table_t *slidx, | |||
547 | (pal_processor_state_info_t*)peidx_psp(peidx); | 547 | (pal_processor_state_info_t*)peidx_psp(peidx); |
548 | 548 | ||
549 | /* | 549 | /* |
550 | * We cannot recover errors with other than bus_check. | 550 | * Processor recovery status must key off of the PAL recovery |
551 | * status in the Processor State Parameter. | ||
551 | */ | 552 | */ |
552 | if (psp->cc || psp->rc || psp->uc) | 553 | |
554 | /* | ||
555 | * The machine check is corrected. | ||
556 | */ | ||
557 | if (psp->cm == 1) | ||
558 | return 1; | ||
559 | |||
560 | /* | ||
561 | * The error was not contained. Software must be reset. | ||
562 | */ | ||
563 | if (psp->us || psp->ci == 0) | ||
553 | return 0; | 564 | return 0; |
554 | 565 | ||
555 | /* | 566 | /* |
@@ -570,8 +581,6 @@ recover_from_processor_error(int platform, slidx_table_t *slidx, | |||
570 | return 0; | 581 | return 0; |
571 | if (pbci->eb && pbci->bsi > 0) | 582 | if (pbci->eb && pbci->bsi > 0) |
572 | return 0; | 583 | return 0; |
573 | if (psp->ci == 0) | ||
574 | return 0; | ||
575 | 584 | ||
576 | /* | 585 | /* |
577 | * This is a local MCA and estimated as recoverble external bus error. | 586 | * This is a local MCA and estimated as recoverble external bus error. |
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index 640d6908f8ec..e92ea64d8040 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c | |||
@@ -4,6 +4,9 @@ | |||
4 | * Copyright (C) 1998-2003 Hewlett-Packard Co | 4 | * Copyright (C) 1998-2003 Hewlett-Packard Co |
5 | * David Mosberger-Tang <davidm@hpl.hp.com> | 5 | * David Mosberger-Tang <davidm@hpl.hp.com> |
6 | * 04/11/17 Ashok Raj <ashok.raj@intel.com> Added CPU Hotplug Support | 6 | * 04/11/17 Ashok Raj <ashok.raj@intel.com> Added CPU Hotplug Support |
7 | * | ||
8 | * 2005-10-07 Keith Owens <kaos@sgi.com> | ||
9 | * Add notify_die() hooks. | ||
7 | */ | 10 | */ |
8 | #define __KERNEL_SYSCALLS__ /* see <asm/unistd.h> */ | 11 | #define __KERNEL_SYSCALLS__ /* see <asm/unistd.h> */ |
9 | #include <linux/config.h> | 12 | #include <linux/config.h> |
@@ -34,6 +37,7 @@ | |||
34 | #include <asm/elf.h> | 37 | #include <asm/elf.h> |
35 | #include <asm/ia32.h> | 38 | #include <asm/ia32.h> |
36 | #include <asm/irq.h> | 39 | #include <asm/irq.h> |
40 | #include <asm/kdebug.h> | ||
37 | #include <asm/pgalloc.h> | 41 | #include <asm/pgalloc.h> |
38 | #include <asm/processor.h> | 42 | #include <asm/processor.h> |
39 | #include <asm/sal.h> | 43 | #include <asm/sal.h> |
@@ -808,12 +812,14 @@ cpu_halt (void) | |||
808 | void | 812 | void |
809 | machine_restart (char *restart_cmd) | 813 | machine_restart (char *restart_cmd) |
810 | { | 814 | { |
815 | (void) notify_die(DIE_MACHINE_RESTART, restart_cmd, NULL, 0, 0, 0); | ||
811 | (*efi.reset_system)(EFI_RESET_WARM, 0, 0, NULL); | 816 | (*efi.reset_system)(EFI_RESET_WARM, 0, 0, NULL); |
812 | } | 817 | } |
813 | 818 | ||
814 | void | 819 | void |
815 | machine_halt (void) | 820 | machine_halt (void) |
816 | { | 821 | { |
822 | (void) notify_die(DIE_MACHINE_HALT, "", NULL, 0, 0, 0); | ||
817 | cpu_halt(); | 823 | cpu_halt(); |
818 | } | 824 | } |
819 | 825 | ||
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index 3af6de36a482..5add0bcf87a7 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c | |||
@@ -461,6 +461,7 @@ setup_arch (char **cmdline_p) | |||
461 | #endif | 461 | #endif |
462 | 462 | ||
463 | cpu_init(); /* initialize the bootstrap CPU */ | 463 | cpu_init(); /* initialize the bootstrap CPU */ |
464 | mmu_context_init(); /* initialize context_id bitmap */ | ||
464 | 465 | ||
465 | #ifdef CONFIG_ACPI | 466 | #ifdef CONFIG_ACPI |
466 | acpi_boot_init(); | 467 | acpi_boot_init(); |
diff --git a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c index 774f34b675cf..58ce07efc56e 100644 --- a/arch/ia64/kernel/signal.c +++ b/arch/ia64/kernel/signal.c | |||
@@ -387,15 +387,14 @@ setup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, | |||
387 | struct sigscratch *scr) | 387 | struct sigscratch *scr) |
388 | { | 388 | { |
389 | extern char __kernel_sigtramp[]; | 389 | extern char __kernel_sigtramp[]; |
390 | unsigned long tramp_addr, new_rbs = 0; | 390 | unsigned long tramp_addr, new_rbs = 0, new_sp; |
391 | struct sigframe __user *frame; | 391 | struct sigframe __user *frame; |
392 | long err; | 392 | long err; |
393 | 393 | ||
394 | frame = (void __user *) scr->pt.r12; | 394 | new_sp = scr->pt.r12; |
395 | tramp_addr = (unsigned long) __kernel_sigtramp; | 395 | tramp_addr = (unsigned long) __kernel_sigtramp; |
396 | if ((ka->sa.sa_flags & SA_ONSTACK) && sas_ss_flags((unsigned long) frame) == 0) { | 396 | if ((ka->sa.sa_flags & SA_ONSTACK) && sas_ss_flags(new_sp) == 0) { |
397 | frame = (void __user *) ((current->sas_ss_sp + current->sas_ss_size) | 397 | new_sp = current->sas_ss_sp + current->sas_ss_size; |
398 | & ~(STACK_ALIGN - 1)); | ||
399 | /* | 398 | /* |
400 | * We need to check for the register stack being on the signal stack | 399 | * We need to check for the register stack being on the signal stack |
401 | * separately, because it's switched separately (memory stack is switched | 400 | * separately, because it's switched separately (memory stack is switched |
@@ -404,7 +403,7 @@ setup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, | |||
404 | if (!rbs_on_sig_stack(scr->pt.ar_bspstore)) | 403 | if (!rbs_on_sig_stack(scr->pt.ar_bspstore)) |
405 | new_rbs = (current->sas_ss_sp + sizeof(long) - 1) & ~(sizeof(long) - 1); | 404 | new_rbs = (current->sas_ss_sp + sizeof(long) - 1) & ~(sizeof(long) - 1); |
406 | } | 405 | } |
407 | frame = (void __user *) frame - ((sizeof(*frame) + STACK_ALIGN - 1) & ~(STACK_ALIGN - 1)); | 406 | frame = (void __user *) ((new_sp - sizeof(*frame)) & -STACK_ALIGN); |
408 | 407 | ||
409 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | 408 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
410 | return force_sigsegv_info(sig, frame); | 409 | return force_sigsegv_info(sig, frame); |
diff --git a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c index f970359e7edf..fba5fdd1f968 100644 --- a/arch/ia64/kernel/traps.c +++ b/arch/ia64/kernel/traps.c | |||
@@ -30,17 +30,20 @@ fpswa_interface_t *fpswa_interface; | |||
30 | EXPORT_SYMBOL(fpswa_interface); | 30 | EXPORT_SYMBOL(fpswa_interface); |
31 | 31 | ||
32 | struct notifier_block *ia64die_chain; | 32 | struct notifier_block *ia64die_chain; |
33 | static DEFINE_SPINLOCK(die_notifier_lock); | ||
34 | 33 | ||
35 | int register_die_notifier(struct notifier_block *nb) | 34 | int |
35 | register_die_notifier(struct notifier_block *nb) | ||
36 | { | 36 | { |
37 | int err = 0; | 37 | return notifier_chain_register(&ia64die_chain, nb); |
38 | unsigned long flags; | ||
39 | spin_lock_irqsave(&die_notifier_lock, flags); | ||
40 | err = notifier_chain_register(&ia64die_chain, nb); | ||
41 | spin_unlock_irqrestore(&die_notifier_lock, flags); | ||
42 | return err; | ||
43 | } | 38 | } |
39 | EXPORT_SYMBOL_GPL(register_die_notifier); | ||
40 | |||
41 | int | ||
42 | unregister_die_notifier(struct notifier_block *nb) | ||
43 | { | ||
44 | return notifier_chain_unregister(&ia64die_chain, nb); | ||
45 | } | ||
46 | EXPORT_SYMBOL_GPL(unregister_die_notifier); | ||
44 | 47 | ||
45 | void __init | 48 | void __init |
46 | trap_init (void) | 49 | trap_init (void) |
@@ -105,6 +108,7 @@ die (const char *str, struct pt_regs *regs, long err) | |||
105 | if (++die.lock_owner_depth < 3) { | 108 | if (++die.lock_owner_depth < 3) { |
106 | printk("%s[%d]: %s %ld [%d]\n", | 109 | printk("%s[%d]: %s %ld [%d]\n", |
107 | current->comm, current->pid, str, err, ++die_counter); | 110 | current->comm, current->pid, str, err, ++die_counter); |
111 | (void) notify_die(DIE_OOPS, (char *)str, regs, err, 255, SIGSEGV); | ||
108 | show_regs(regs); | 112 | show_regs(regs); |
109 | } else | 113 | } else |
110 | printk(KERN_ERR "Recursive die() failure, output suppressed\n"); | 114 | printk(KERN_ERR "Recursive die() failure, output suppressed\n"); |
@@ -155,9 +159,8 @@ __kprobes ia64_bad_break (unsigned long break_num, struct pt_regs *regs) | |||
155 | switch (break_num) { | 159 | switch (break_num) { |
156 | case 0: /* unknown error (used by GCC for __builtin_abort()) */ | 160 | case 0: /* unknown error (used by GCC for __builtin_abort()) */ |
157 | if (notify_die(DIE_BREAK, "break 0", regs, break_num, TRAP_BRKPT, SIGTRAP) | 161 | if (notify_die(DIE_BREAK, "break 0", regs, break_num, TRAP_BRKPT, SIGTRAP) |
158 | == NOTIFY_STOP) { | 162 | == NOTIFY_STOP) |
159 | return; | 163 | return; |
160 | } | ||
161 | die_if_kernel("bugcheck!", regs, break_num); | 164 | die_if_kernel("bugcheck!", regs, break_num); |
162 | sig = SIGILL; code = ILL_ILLOPC; | 165 | sig = SIGILL; code = ILL_ILLOPC; |
163 | break; | 166 | break; |
@@ -210,15 +213,6 @@ __kprobes ia64_bad_break (unsigned long break_num, struct pt_regs *regs) | |||
210 | sig = SIGILL; code = __ILL_BNDMOD; | 213 | sig = SIGILL; code = __ILL_BNDMOD; |
211 | break; | 214 | break; |
212 | 215 | ||
213 | case 0x80200: | ||
214 | case 0x80300: | ||
215 | if (notify_die(DIE_BREAK, "kprobe", regs, break_num, TRAP_BRKPT, SIGTRAP) | ||
216 | == NOTIFY_STOP) { | ||
217 | return; | ||
218 | } | ||
219 | sig = SIGTRAP; code = TRAP_BRKPT; | ||
220 | break; | ||
221 | |||
222 | default: | 216 | default: |
223 | if (break_num < 0x40000 || break_num > 0x100000) | 217 | if (break_num < 0x40000 || break_num > 0x100000) |
224 | die_if_kernel("Bad break", regs, break_num); | 218 | die_if_kernel("Bad break", regs, break_num); |
@@ -226,6 +220,9 @@ __kprobes ia64_bad_break (unsigned long break_num, struct pt_regs *regs) | |||
226 | if (break_num < 0x80000) { | 220 | if (break_num < 0x80000) { |
227 | sig = SIGILL; code = __ILL_BREAK; | 221 | sig = SIGILL; code = __ILL_BREAK; |
228 | } else { | 222 | } else { |
223 | if (notify_die(DIE_BREAK, "bad break", regs, break_num, TRAP_BRKPT, SIGTRAP) | ||
224 | == NOTIFY_STOP) | ||
225 | return; | ||
229 | sig = SIGTRAP; code = TRAP_BRKPT; | 226 | sig = SIGTRAP; code = TRAP_BRKPT; |
230 | } | 227 | } |
231 | } | 228 | } |
@@ -578,12 +575,11 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa, | |||
578 | #endif | 575 | #endif |
579 | break; | 576 | break; |
580 | case 35: siginfo.si_code = TRAP_BRANCH; ifa = 0; break; | 577 | case 35: siginfo.si_code = TRAP_BRANCH; ifa = 0; break; |
581 | case 36: | 578 | case 36: siginfo.si_code = TRAP_TRACE; ifa = 0; break; |
582 | if (notify_die(DIE_SS, "ss", ®s, vector, | ||
583 | vector, SIGTRAP) == NOTIFY_STOP) | ||
584 | return; | ||
585 | siginfo.si_code = TRAP_TRACE; ifa = 0; break; | ||
586 | } | 579 | } |
580 | if (notify_die(DIE_FAULT, "ia64_fault", ®s, vector, siginfo.si_code, SIGTRAP) | ||
581 | == NOTIFY_STOP) | ||
582 | return; | ||
587 | siginfo.si_signo = SIGTRAP; | 583 | siginfo.si_signo = SIGTRAP; |
588 | siginfo.si_errno = 0; | 584 | siginfo.si_errno = 0; |
589 | siginfo.si_addr = (void __user *) ifa; | 585 | siginfo.si_addr = (void __user *) ifa; |
diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c index a88cdb7232f8..0f776b032d31 100644 --- a/arch/ia64/mm/discontig.c +++ b/arch/ia64/mm/discontig.c | |||
@@ -350,14 +350,12 @@ static void __init initialize_pernode_data(void) | |||
350 | * for best. | 350 | * for best. |
351 | * @nid: node id | 351 | * @nid: node id |
352 | * @pernodesize: size of this node's pernode data | 352 | * @pernodesize: size of this node's pernode data |
353 | * @align: alignment to use for this node's pernode data | ||
354 | */ | 353 | */ |
355 | static void __init *memory_less_node_alloc(int nid, unsigned long pernodesize, | 354 | static void __init *memory_less_node_alloc(int nid, unsigned long pernodesize) |
356 | unsigned long align) | ||
357 | { | 355 | { |
358 | void *ptr = NULL; | 356 | void *ptr = NULL; |
359 | u8 best = 0xff; | 357 | u8 best = 0xff; |
360 | int bestnode = -1, node; | 358 | int bestnode = -1, node, anynode = 0; |
361 | 359 | ||
362 | for_each_online_node(node) { | 360 | for_each_online_node(node) { |
363 | if (node_isset(node, memory_less_mask)) | 361 | if (node_isset(node, memory_less_mask)) |
@@ -366,13 +364,15 @@ static void __init *memory_less_node_alloc(int nid, unsigned long pernodesize, | |||
366 | best = node_distance(nid, node); | 364 | best = node_distance(nid, node); |
367 | bestnode = node; | 365 | bestnode = node; |
368 | } | 366 | } |
367 | anynode = node; | ||
369 | } | 368 | } |
370 | 369 | ||
371 | ptr = __alloc_bootmem_node(mem_data[bestnode].pgdat, | 370 | if (bestnode == -1) |
372 | pernodesize, align, __pa(MAX_DMA_ADDRESS)); | 371 | bestnode = anynode; |
372 | |||
373 | ptr = __alloc_bootmem_node(mem_data[bestnode].pgdat, pernodesize, | ||
374 | PERCPU_PAGE_SIZE, __pa(MAX_DMA_ADDRESS)); | ||
373 | 375 | ||
374 | if (!ptr) | ||
375 | panic("NO memory for memory less node\n"); | ||
376 | return ptr; | 376 | return ptr; |
377 | } | 377 | } |
378 | 378 | ||
@@ -413,8 +413,7 @@ static void __init memory_less_nodes(void) | |||
413 | 413 | ||
414 | for_each_node_mask(node, memory_less_mask) { | 414 | for_each_node_mask(node, memory_less_mask) { |
415 | pernodesize = compute_pernodesize(node); | 415 | pernodesize = compute_pernodesize(node); |
416 | pernode = memory_less_node_alloc(node, pernodesize, | 416 | pernode = memory_less_node_alloc(node, pernodesize); |
417 | (node) ? (node * PERCPU_PAGE_SIZE) : (1024*1024)); | ||
418 | fill_pernode(node, __pa(pernode), pernodesize); | 417 | fill_pernode(node, __pa(pernode), pernodesize); |
419 | } | 418 | } |
420 | 419 | ||
diff --git a/arch/ia64/mm/tlb.c b/arch/ia64/mm/tlb.c index c79a9b96d02b..41105d454423 100644 --- a/arch/ia64/mm/tlb.c +++ b/arch/ia64/mm/tlb.c | |||
@@ -8,6 +8,8 @@ | |||
8 | * Modified RID allocation for SMP | 8 | * Modified RID allocation for SMP |
9 | * Goutham Rao <goutham.rao@intel.com> | 9 | * Goutham Rao <goutham.rao@intel.com> |
10 | * IPI based ptc implementation and A-step IPI implementation. | 10 | * IPI based ptc implementation and A-step IPI implementation. |
11 | * Rohit Seth <rohit.seth@intel.com> | ||
12 | * Ken Chen <kenneth.w.chen@intel.com> | ||
11 | */ | 13 | */ |
12 | #include <linux/config.h> | 14 | #include <linux/config.h> |
13 | #include <linux/module.h> | 15 | #include <linux/module.h> |
@@ -16,78 +18,75 @@ | |||
16 | #include <linux/sched.h> | 18 | #include <linux/sched.h> |
17 | #include <linux/smp.h> | 19 | #include <linux/smp.h> |
18 | #include <linux/mm.h> | 20 | #include <linux/mm.h> |
21 | #include <linux/bootmem.h> | ||
19 | 22 | ||
20 | #include <asm/delay.h> | 23 | #include <asm/delay.h> |
21 | #include <asm/mmu_context.h> | 24 | #include <asm/mmu_context.h> |
22 | #include <asm/pgalloc.h> | 25 | #include <asm/pgalloc.h> |
23 | #include <asm/pal.h> | 26 | #include <asm/pal.h> |
24 | #include <asm/tlbflush.h> | 27 | #include <asm/tlbflush.h> |
28 | #include <asm/dma.h> | ||
25 | 29 | ||
26 | static struct { | 30 | static struct { |
27 | unsigned long mask; /* mask of supported purge page-sizes */ | 31 | unsigned long mask; /* mask of supported purge page-sizes */ |
28 | unsigned long max_bits; /* log2() of largest supported purge page-size */ | 32 | unsigned long max_bits; /* log2 of largest supported purge page-size */ |
29 | } purge; | 33 | } purge; |
30 | 34 | ||
31 | struct ia64_ctx ia64_ctx = { | 35 | struct ia64_ctx ia64_ctx = { |
32 | .lock = SPIN_LOCK_UNLOCKED, | 36 | .lock = SPIN_LOCK_UNLOCKED, |
33 | .next = 1, | 37 | .next = 1, |
34 | .limit = (1 << 15) - 1, /* start out with the safe (architected) limit */ | ||
35 | .max_ctx = ~0U | 38 | .max_ctx = ~0U |
36 | }; | 39 | }; |
37 | 40 | ||
38 | DEFINE_PER_CPU(u8, ia64_need_tlb_flush); | 41 | DEFINE_PER_CPU(u8, ia64_need_tlb_flush); |
39 | 42 | ||
40 | /* | 43 | /* |
44 | * Initializes the ia64_ctx.bitmap array based on max_ctx+1. | ||
45 | * Called after cpu_init() has setup ia64_ctx.max_ctx based on | ||
46 | * maximum RID that is supported by boot CPU. | ||
47 | */ | ||
48 | void __init | ||
49 | mmu_context_init (void) | ||
50 | { | ||
51 | ia64_ctx.bitmap = alloc_bootmem((ia64_ctx.max_ctx+1)>>3); | ||
52 | ia64_ctx.flushmap = alloc_bootmem((ia64_ctx.max_ctx+1)>>3); | ||
53 | } | ||
54 | |||
55 | /* | ||
41 | * Acquire the ia64_ctx.lock before calling this function! | 56 | * Acquire the ia64_ctx.lock before calling this function! |
42 | */ | 57 | */ |
43 | void | 58 | void |
44 | wrap_mmu_context (struct mm_struct *mm) | 59 | wrap_mmu_context (struct mm_struct *mm) |
45 | { | 60 | { |
46 | unsigned long tsk_context, max_ctx = ia64_ctx.max_ctx; | 61 | int i, cpu; |
47 | struct task_struct *tsk; | 62 | unsigned long flush_bit; |
48 | int i; | ||
49 | 63 | ||
50 | if (ia64_ctx.next > max_ctx) | 64 | for (i=0; i <= ia64_ctx.max_ctx / BITS_PER_LONG; i++) { |
51 | ia64_ctx.next = 300; /* skip daemons */ | 65 | flush_bit = xchg(&ia64_ctx.flushmap[i], 0); |
52 | ia64_ctx.limit = max_ctx + 1; | 66 | ia64_ctx.bitmap[i] ^= flush_bit; |
67 | } | ||
68 | |||
69 | /* use offset at 300 to skip daemons */ | ||
70 | ia64_ctx.next = find_next_zero_bit(ia64_ctx.bitmap, | ||
71 | ia64_ctx.max_ctx, 300); | ||
72 | ia64_ctx.limit = find_next_bit(ia64_ctx.bitmap, | ||
73 | ia64_ctx.max_ctx, ia64_ctx.next); | ||
53 | 74 | ||
54 | /* | 75 | /* |
55 | * Scan all the task's mm->context and set proper safe range | 76 | * can't call flush_tlb_all() here because of race condition |
77 | * with O(1) scheduler [EF] | ||
56 | */ | 78 | */ |
57 | 79 | cpu = get_cpu(); /* prevent preemption/migration */ | |
58 | read_lock(&tasklist_lock); | 80 | for_each_online_cpu(i) |
59 | repeat: | 81 | if (i != cpu) |
60 | for_each_process(tsk) { | 82 | per_cpu(ia64_need_tlb_flush, i) = 1; |
61 | if (!tsk->mm) | 83 | put_cpu(); |
62 | continue; | ||
63 | tsk_context = tsk->mm->context; | ||
64 | if (tsk_context == ia64_ctx.next) { | ||
65 | if (++ia64_ctx.next >= ia64_ctx.limit) { | ||
66 | /* empty range: reset the range limit and start over */ | ||
67 | if (ia64_ctx.next > max_ctx) | ||
68 | ia64_ctx.next = 300; | ||
69 | ia64_ctx.limit = max_ctx + 1; | ||
70 | goto repeat; | ||
71 | } | ||
72 | } | ||
73 | if ((tsk_context > ia64_ctx.next) && (tsk_context < ia64_ctx.limit)) | ||
74 | ia64_ctx.limit = tsk_context; | ||
75 | } | ||
76 | read_unlock(&tasklist_lock); | ||
77 | /* can't call flush_tlb_all() here because of race condition with O(1) scheduler [EF] */ | ||
78 | { | ||
79 | int cpu = get_cpu(); /* prevent preemption/migration */ | ||
80 | for_each_online_cpu(i) { | ||
81 | if (i != cpu) | ||
82 | per_cpu(ia64_need_tlb_flush, i) = 1; | ||
83 | } | ||
84 | put_cpu(); | ||
85 | } | ||
86 | local_flush_tlb_all(); | 84 | local_flush_tlb_all(); |
87 | } | 85 | } |
88 | 86 | ||
89 | void | 87 | void |
90 | ia64_global_tlb_purge (struct mm_struct *mm, unsigned long start, unsigned long end, unsigned long nbits) | 88 | ia64_global_tlb_purge (struct mm_struct *mm, unsigned long start, |
89 | unsigned long end, unsigned long nbits) | ||
91 | { | 90 | { |
92 | static DEFINE_SPINLOCK(ptcg_lock); | 91 | static DEFINE_SPINLOCK(ptcg_lock); |
93 | 92 | ||
@@ -135,7 +134,8 @@ local_flush_tlb_all (void) | |||
135 | } | 134 | } |
136 | 135 | ||
137 | void | 136 | void |
138 | flush_tlb_range (struct vm_area_struct *vma, unsigned long start, unsigned long end) | 137 | flush_tlb_range (struct vm_area_struct *vma, unsigned long start, |
138 | unsigned long end) | ||
139 | { | 139 | { |
140 | struct mm_struct *mm = vma->vm_mm; | 140 | struct mm_struct *mm = vma->vm_mm; |
141 | unsigned long size = end - start; | 141 | unsigned long size = end - start; |
@@ -149,7 +149,8 @@ flush_tlb_range (struct vm_area_struct *vma, unsigned long start, unsigned long | |||
149 | #endif | 149 | #endif |
150 | 150 | ||
151 | nbits = ia64_fls(size + 0xfff); | 151 | nbits = ia64_fls(size + 0xfff); |
152 | while (unlikely (((1UL << nbits) & purge.mask) == 0) && (nbits < purge.max_bits)) | 152 | while (unlikely (((1UL << nbits) & purge.mask) == 0) && |
153 | (nbits < purge.max_bits)) | ||
153 | ++nbits; | 154 | ++nbits; |
154 | if (nbits > purge.max_bits) | 155 | if (nbits > purge.max_bits) |
155 | nbits = purge.max_bits; | 156 | nbits = purge.max_bits; |
@@ -191,5 +192,5 @@ ia64_tlb_init (void) | |||
191 | local_cpu_data->ptce_stride[0] = ptce_info.stride[0]; | 192 | local_cpu_data->ptce_stride[0] = ptce_info.stride[0]; |
192 | local_cpu_data->ptce_stride[1] = ptce_info.stride[1]; | 193 | local_cpu_data->ptce_stride[1] = ptce_info.stride[1]; |
193 | 194 | ||
194 | local_flush_tlb_all(); /* nuke left overs from bootstrapping... */ | 195 | local_flush_tlb_all(); /* nuke left overs from bootstrapping... */ |
195 | } | 196 | } |
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index 017cfc3f4789..20d76fae24e8 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c | |||
@@ -95,7 +95,7 @@ pci_sal_write (unsigned int seg, unsigned int bus, unsigned int devfn, | |||
95 | } | 95 | } |
96 | 96 | ||
97 | static struct pci_raw_ops pci_sal_ops = { | 97 | static struct pci_raw_ops pci_sal_ops = { |
98 | .read = pci_sal_read, | 98 | .read = pci_sal_read, |
99 | .write = pci_sal_write | 99 | .write = pci_sal_write |
100 | }; | 100 | }; |
101 | 101 | ||
@@ -137,35 +137,98 @@ alloc_pci_controller (int seg) | |||
137 | return controller; | 137 | return controller; |
138 | } | 138 | } |
139 | 139 | ||
140 | static u64 __devinit | 140 | struct pci_root_info { |
141 | add_io_space (struct acpi_resource_address64 *addr) | 141 | struct pci_controller *controller; |
142 | char *name; | ||
143 | }; | ||
144 | |||
145 | static unsigned int | ||
146 | new_space (u64 phys_base, int sparse) | ||
142 | { | 147 | { |
143 | u64 offset; | 148 | u64 mmio_base; |
144 | int sparse = 0; | ||
145 | int i; | 149 | int i; |
146 | 150 | ||
147 | if (addr->address_translation_offset == 0) | 151 | if (phys_base == 0) |
148 | return IO_SPACE_BASE(0); /* part of legacy IO space */ | 152 | return 0; /* legacy I/O port space */ |
149 | |||
150 | if (addr->attribute.io.translation_attribute == ACPI_SPARSE_TRANSLATION) | ||
151 | sparse = 1; | ||
152 | 153 | ||
153 | offset = (u64) ioremap(addr->address_translation_offset, 0); | 154 | mmio_base = (u64) ioremap(phys_base, 0); |
154 | for (i = 0; i < num_io_spaces; i++) | 155 | for (i = 0; i < num_io_spaces; i++) |
155 | if (io_space[i].mmio_base == offset && | 156 | if (io_space[i].mmio_base == mmio_base && |
156 | io_space[i].sparse == sparse) | 157 | io_space[i].sparse == sparse) |
157 | return IO_SPACE_BASE(i); | 158 | return i; |
158 | 159 | ||
159 | if (num_io_spaces == MAX_IO_SPACES) { | 160 | if (num_io_spaces == MAX_IO_SPACES) { |
160 | printk("Too many IO port spaces\n"); | 161 | printk(KERN_ERR "PCI: Too many IO port spaces " |
162 | "(MAX_IO_SPACES=%lu)\n", MAX_IO_SPACES); | ||
161 | return ~0; | 163 | return ~0; |
162 | } | 164 | } |
163 | 165 | ||
164 | i = num_io_spaces++; | 166 | i = num_io_spaces++; |
165 | io_space[i].mmio_base = offset; | 167 | io_space[i].mmio_base = mmio_base; |
166 | io_space[i].sparse = sparse; | 168 | io_space[i].sparse = sparse; |
167 | 169 | ||
168 | return IO_SPACE_BASE(i); | 170 | return i; |
171 | } | ||
172 | |||
173 | static u64 __devinit | ||
174 | add_io_space (struct pci_root_info *info, struct acpi_resource_address64 *addr) | ||
175 | { | ||
176 | struct resource *resource; | ||
177 | char *name; | ||
178 | u64 base, min, max, base_port; | ||
179 | unsigned int sparse = 0, space_nr, len; | ||
180 | |||
181 | resource = kzalloc(sizeof(*resource), GFP_KERNEL); | ||
182 | if (!resource) { | ||
183 | printk(KERN_ERR "PCI: No memory for %s I/O port space\n", | ||
184 | info->name); | ||
185 | goto out; | ||
186 | } | ||
187 | |||
188 | len = strlen(info->name) + 32; | ||
189 | name = kzalloc(len, GFP_KERNEL); | ||
190 | if (!name) { | ||
191 | printk(KERN_ERR "PCI: No memory for %s I/O port space name\n", | ||
192 | info->name); | ||
193 | goto free_resource; | ||
194 | } | ||
195 | |||
196 | min = addr->min_address_range; | ||
197 | max = min + addr->address_length - 1; | ||
198 | if (addr->attribute.io.translation_attribute == ACPI_SPARSE_TRANSLATION) | ||
199 | sparse = 1; | ||
200 | |||
201 | space_nr = new_space(addr->address_translation_offset, sparse); | ||
202 | if (space_nr == ~0) | ||
203 | goto free_name; | ||
204 | |||
205 | base = __pa(io_space[space_nr].mmio_base); | ||
206 | base_port = IO_SPACE_BASE(space_nr); | ||
207 | snprintf(name, len, "%s I/O Ports %08lx-%08lx", info->name, | ||
208 | base_port + min, base_port + max); | ||
209 | |||
210 | /* | ||
211 | * The SDM guarantees the legacy 0-64K space is sparse, but if the | ||
212 | * mapping is done by the processor (not the bridge), ACPI may not | ||
213 | * mark it as sparse. | ||
214 | */ | ||
215 | if (space_nr == 0) | ||
216 | sparse = 1; | ||
217 | |||
218 | resource->name = name; | ||
219 | resource->flags = IORESOURCE_MEM; | ||
220 | resource->start = base + (sparse ? IO_SPACE_SPARSE_ENCODING(min) : min); | ||
221 | resource->end = base + (sparse ? IO_SPACE_SPARSE_ENCODING(max) : max); | ||
222 | insert_resource(&iomem_resource, resource); | ||
223 | |||
224 | return base_port; | ||
225 | |||
226 | free_name: | ||
227 | kfree(name); | ||
228 | free_resource: | ||
229 | kfree(resource); | ||
230 | out: | ||
231 | return ~0; | ||
169 | } | 232 | } |
170 | 233 | ||
171 | static acpi_status __devinit resource_to_window(struct acpi_resource *resource, | 234 | static acpi_status __devinit resource_to_window(struct acpi_resource *resource, |
@@ -205,11 +268,6 @@ count_window (struct acpi_resource *resource, void *data) | |||
205 | return AE_OK; | 268 | return AE_OK; |
206 | } | 269 | } |
207 | 270 | ||
208 | struct pci_root_info { | ||
209 | struct pci_controller *controller; | ||
210 | char *name; | ||
211 | }; | ||
212 | |||
213 | static __devinit acpi_status add_window(struct acpi_resource *res, void *data) | 271 | static __devinit acpi_status add_window(struct acpi_resource *res, void *data) |
214 | { | 272 | { |
215 | struct pci_root_info *info = data; | 273 | struct pci_root_info *info = data; |
@@ -231,7 +289,7 @@ static __devinit acpi_status add_window(struct acpi_resource *res, void *data) | |||
231 | } else if (addr.resource_type == ACPI_IO_RANGE) { | 289 | } else if (addr.resource_type == ACPI_IO_RANGE) { |
232 | flags = IORESOURCE_IO; | 290 | flags = IORESOURCE_IO; |
233 | root = &ioport_resource; | 291 | root = &ioport_resource; |
234 | offset = add_io_space(&addr); | 292 | offset = add_io_space(info, &addr); |
235 | if (offset == ~0) | 293 | if (offset == ~0) |
236 | return AE_OK; | 294 | return AE_OK; |
237 | } else | 295 | } else |
@@ -241,7 +299,7 @@ static __devinit acpi_status add_window(struct acpi_resource *res, void *data) | |||
241 | window->resource.name = info->name; | 299 | window->resource.name = info->name; |
242 | window->resource.flags = flags; | 300 | window->resource.flags = flags; |
243 | window->resource.start = addr.min_address_range + offset; | 301 | window->resource.start = addr.min_address_range + offset; |
244 | window->resource.end = addr.max_address_range + offset; | 302 | window->resource.end = window->resource.start + addr.address_length - 1; |
245 | window->resource.child = NULL; | 303 | window->resource.child = NULL; |
246 | window->offset = offset; | 304 | window->offset = offset; |
247 | 305 | ||
@@ -739,7 +797,7 @@ int pci_vector_resources(int last, int nr_released) | |||
739 | { | 797 | { |
740 | int count = nr_released; | 798 | int count = nr_released; |
741 | 799 | ||
742 | count += (IA64_LAST_DEVICE_VECTOR - last); | 800 | count += (IA64_LAST_DEVICE_VECTOR - last); |
743 | 801 | ||
744 | return count; | 802 | return count; |
745 | } | 803 | } |
diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c index b4f5053f5e1b..05e4ea889981 100644 --- a/arch/ia64/sn/kernel/io_init.c +++ b/arch/ia64/sn/kernel/io_init.c | |||
@@ -349,7 +349,7 @@ void sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus) | |||
349 | return; /*bus # does not exist */ | 349 | return; /*bus # does not exist */ |
350 | prom_bussoft_ptr = __va(prom_bussoft_ptr); | 350 | prom_bussoft_ptr = __va(prom_bussoft_ptr); |
351 | 351 | ||
352 | controller = kcalloc(1,sizeof(struct pci_controller), GFP_KERNEL); | 352 | controller = kzalloc(sizeof(struct pci_controller), GFP_KERNEL); |
353 | controller->segment = segment; | 353 | controller->segment = segment; |
354 | if (!controller) | 354 | if (!controller) |
355 | BUG(); | 355 | BUG(); |
diff --git a/arch/ia64/sn/kernel/xpc.h b/arch/ia64/sn/kernel/xpc.h index fbcedc7c27fa..5483a9f227d4 100644 --- a/arch/ia64/sn/kernel/xpc.h +++ b/arch/ia64/sn/kernel/xpc.h | |||
@@ -163,7 +163,7 @@ struct xpc_vars { | |||
163 | u8 version; | 163 | u8 version; |
164 | u64 heartbeat; | 164 | u64 heartbeat; |
165 | u64 heartbeating_to_mask; | 165 | u64 heartbeating_to_mask; |
166 | u64 kdb_status; /* 0 = machine running */ | 166 | u64 heartbeat_offline; /* if 0, heartbeat should be changing */ |
167 | int act_nasid; | 167 | int act_nasid; |
168 | int act_phys_cpuid; | 168 | int act_phys_cpuid; |
169 | u64 vars_part_pa; | 169 | u64 vars_part_pa; |
diff --git a/arch/ia64/sn/kernel/xpc_main.c b/arch/ia64/sn/kernel/xpc_main.c index cece3c7c69be..b617236524c6 100644 --- a/arch/ia64/sn/kernel/xpc_main.c +++ b/arch/ia64/sn/kernel/xpc_main.c | |||
@@ -57,6 +57,7 @@ | |||
57 | #include <linux/reboot.h> | 57 | #include <linux/reboot.h> |
58 | #include <asm/sn/intr.h> | 58 | #include <asm/sn/intr.h> |
59 | #include <asm/sn/sn_sal.h> | 59 | #include <asm/sn/sn_sal.h> |
60 | #include <asm/kdebug.h> | ||
60 | #include <asm/uaccess.h> | 61 | #include <asm/uaccess.h> |
61 | #include "xpc.h" | 62 | #include "xpc.h" |
62 | 63 | ||
@@ -188,6 +189,11 @@ static struct notifier_block xpc_reboot_notifier = { | |||
188 | .notifier_call = xpc_system_reboot, | 189 | .notifier_call = xpc_system_reboot, |
189 | }; | 190 | }; |
190 | 191 | ||
192 | static int xpc_system_die(struct notifier_block *, unsigned long, void *); | ||
193 | static struct notifier_block xpc_die_notifier = { | ||
194 | .notifier_call = xpc_system_die, | ||
195 | }; | ||
196 | |||
191 | 197 | ||
192 | /* | 198 | /* |
193 | * Timer function to enforce the timelimit on the partition disengage request. | 199 | * Timer function to enforce the timelimit on the partition disengage request. |
@@ -997,6 +1003,9 @@ xpc_do_exit(enum xpc_retval reason) | |||
997 | /* take ourselves off of the reboot_notifier_list */ | 1003 | /* take ourselves off of the reboot_notifier_list */ |
998 | (void) unregister_reboot_notifier(&xpc_reboot_notifier); | 1004 | (void) unregister_reboot_notifier(&xpc_reboot_notifier); |
999 | 1005 | ||
1006 | /* take ourselves off of the die_notifier list */ | ||
1007 | (void) unregister_die_notifier(&xpc_die_notifier); | ||
1008 | |||
1000 | /* close down protections for IPI operations */ | 1009 | /* close down protections for IPI operations */ |
1001 | xpc_restrict_IPI_ops(); | 1010 | xpc_restrict_IPI_ops(); |
1002 | 1011 | ||
@@ -1011,6 +1020,63 @@ xpc_do_exit(enum xpc_retval reason) | |||
1011 | 1020 | ||
1012 | 1021 | ||
1013 | /* | 1022 | /* |
1023 | * Called when the system is about to be either restarted or halted. | ||
1024 | */ | ||
1025 | static void | ||
1026 | xpc_die_disengage(void) | ||
1027 | { | ||
1028 | struct xpc_partition *part; | ||
1029 | partid_t partid; | ||
1030 | unsigned long engaged; | ||
1031 | long time, print_time, disengage_request_timeout; | ||
1032 | |||
1033 | |||
1034 | /* keep xpc_hb_checker thread from doing anything (just in case) */ | ||
1035 | xpc_exiting = 1; | ||
1036 | |||
1037 | xpc_vars->heartbeating_to_mask = 0; /* indicate we're deactivated */ | ||
1038 | |||
1039 | for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) { | ||
1040 | part = &xpc_partitions[partid]; | ||
1041 | |||
1042 | if (!XPC_SUPPORTS_DISENGAGE_REQUEST(part-> | ||
1043 | remote_vars_version)) { | ||
1044 | |||
1045 | /* just in case it was left set by an earlier XPC */ | ||
1046 | xpc_clear_partition_engaged(1UL << partid); | ||
1047 | continue; | ||
1048 | } | ||
1049 | |||
1050 | if (xpc_partition_engaged(1UL << partid) || | ||
1051 | part->act_state != XPC_P_INACTIVE) { | ||
1052 | xpc_request_partition_disengage(part); | ||
1053 | xpc_mark_partition_disengaged(part); | ||
1054 | xpc_IPI_send_disengage(part); | ||
1055 | } | ||
1056 | } | ||
1057 | |||
1058 | print_time = rtc_time(); | ||
1059 | disengage_request_timeout = print_time + | ||
1060 | (xpc_disengage_request_timelimit * sn_rtc_cycles_per_second); | ||
1061 | |||
1062 | /* wait for all other partitions to disengage from us */ | ||
1063 | |||
1064 | while ((engaged = xpc_partition_engaged(-1UL)) && | ||
1065 | (time = rtc_time()) < disengage_request_timeout) { | ||
1066 | |||
1067 | if (time >= print_time) { | ||
1068 | dev_info(xpc_part, "waiting for remote partitions to " | ||
1069 | "disengage, engaged=0x%lx\n", engaged); | ||
1070 | print_time = time + (XPC_DISENGAGE_PRINTMSG_INTERVAL * | ||
1071 | sn_rtc_cycles_per_second); | ||
1072 | } | ||
1073 | } | ||
1074 | dev_info(xpc_part, "finished waiting for remote partitions to " | ||
1075 | "disengage, engaged=0x%lx\n", engaged); | ||
1076 | } | ||
1077 | |||
1078 | |||
1079 | /* | ||
1014 | * This function is called when the system is being rebooted. | 1080 | * This function is called when the system is being rebooted. |
1015 | */ | 1081 | */ |
1016 | static int | 1082 | static int |
@@ -1038,6 +1104,33 @@ xpc_system_reboot(struct notifier_block *nb, unsigned long event, void *unused) | |||
1038 | } | 1104 | } |
1039 | 1105 | ||
1040 | 1106 | ||
1107 | /* | ||
1108 | * This function is called when the system is being rebooted. | ||
1109 | */ | ||
1110 | static int | ||
1111 | xpc_system_die(struct notifier_block *nb, unsigned long event, void *unused) | ||
1112 | { | ||
1113 | switch (event) { | ||
1114 | case DIE_MACHINE_RESTART: | ||
1115 | case DIE_MACHINE_HALT: | ||
1116 | xpc_die_disengage(); | ||
1117 | break; | ||
1118 | case DIE_MCA_MONARCH_ENTER: | ||
1119 | case DIE_INIT_MONARCH_ENTER: | ||
1120 | xpc_vars->heartbeat++; | ||
1121 | xpc_vars->heartbeat_offline = 1; | ||
1122 | break; | ||
1123 | case DIE_MCA_MONARCH_LEAVE: | ||
1124 | case DIE_INIT_MONARCH_LEAVE: | ||
1125 | xpc_vars->heartbeat++; | ||
1126 | xpc_vars->heartbeat_offline = 0; | ||
1127 | break; | ||
1128 | } | ||
1129 | |||
1130 | return NOTIFY_DONE; | ||
1131 | } | ||
1132 | |||
1133 | |||
1041 | int __init | 1134 | int __init |
1042 | xpc_init(void) | 1135 | xpc_init(void) |
1043 | { | 1136 | { |
@@ -1154,6 +1247,12 @@ xpc_init(void) | |||
1154 | dev_warn(xpc_part, "can't register reboot notifier\n"); | 1247 | dev_warn(xpc_part, "can't register reboot notifier\n"); |
1155 | } | 1248 | } |
1156 | 1249 | ||
1250 | /* add ourselves to the die_notifier list (i.e., ia64die_chain) */ | ||
1251 | ret = register_die_notifier(&xpc_die_notifier); | ||
1252 | if (ret != 0) { | ||
1253 | dev_warn(xpc_part, "can't register die notifier\n"); | ||
1254 | } | ||
1255 | |||
1157 | 1256 | ||
1158 | /* | 1257 | /* |
1159 | * Set the beating to other partitions into motion. This is | 1258 | * Set the beating to other partitions into motion. This is |
@@ -1179,6 +1278,9 @@ xpc_init(void) | |||
1179 | /* take ourselves off of the reboot_notifier_list */ | 1278 | /* take ourselves off of the reboot_notifier_list */ |
1180 | (void) unregister_reboot_notifier(&xpc_reboot_notifier); | 1279 | (void) unregister_reboot_notifier(&xpc_reboot_notifier); |
1181 | 1280 | ||
1281 | /* take ourselves off of the die_notifier list */ | ||
1282 | (void) unregister_die_notifier(&xpc_die_notifier); | ||
1283 | |||
1182 | del_timer_sync(&xpc_hb_timer); | 1284 | del_timer_sync(&xpc_hb_timer); |
1183 | free_irq(SGI_XPC_ACTIVATE, NULL); | 1285 | free_irq(SGI_XPC_ACTIVATE, NULL); |
1184 | xpc_restrict_IPI_ops(); | 1286 | xpc_restrict_IPI_ops(); |
diff --git a/arch/ia64/sn/kernel/xpc_partition.c b/arch/ia64/sn/kernel/xpc_partition.c index 581e113d2d37..cdd6431853a1 100644 --- a/arch/ia64/sn/kernel/xpc_partition.c +++ b/arch/ia64/sn/kernel/xpc_partition.c | |||
@@ -436,13 +436,13 @@ xpc_check_remote_hb(void) | |||
436 | } | 436 | } |
437 | 437 | ||
438 | dev_dbg(xpc_part, "partid = %d, heartbeat = %ld, last_heartbeat" | 438 | dev_dbg(xpc_part, "partid = %d, heartbeat = %ld, last_heartbeat" |
439 | " = %ld, kdb_status = %ld, HB_mask = 0x%lx\n", partid, | 439 | " = %ld, heartbeat_offline = %ld, HB_mask = 0x%lx\n", |
440 | remote_vars->heartbeat, part->last_heartbeat, | 440 | partid, remote_vars->heartbeat, part->last_heartbeat, |
441 | remote_vars->kdb_status, | 441 | remote_vars->heartbeat_offline, |
442 | remote_vars->heartbeating_to_mask); | 442 | remote_vars->heartbeating_to_mask); |
443 | 443 | ||
444 | if (((remote_vars->heartbeat == part->last_heartbeat) && | 444 | if (((remote_vars->heartbeat == part->last_heartbeat) && |
445 | (remote_vars->kdb_status == 0)) || | 445 | (remote_vars->heartbeat_offline == 0)) || |
446 | !xpc_hb_allowed(sn_partition_id, remote_vars)) { | 446 | !xpc_hb_allowed(sn_partition_id, remote_vars)) { |
447 | 447 | ||
448 | XPC_DEACTIVATE_PARTITION(part, xpcNoHeartbeat); | 448 | XPC_DEACTIVATE_PARTITION(part, xpcNoHeartbeat); |
diff --git a/arch/ia64/sn/pci/tioce_provider.c b/arch/ia64/sn/pci/tioce_provider.c index 9f03d4e5121c..dda196c9e324 100644 --- a/arch/ia64/sn/pci/tioce_provider.c +++ b/arch/ia64/sn/pci/tioce_provider.c | |||
@@ -218,7 +218,7 @@ tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port, | |||
218 | if (i > last) | 218 | if (i > last) |
219 | return 0; | 219 | return 0; |
220 | 220 | ||
221 | map = kcalloc(1, sizeof(struct tioce_dmamap), GFP_ATOMIC); | 221 | map = kzalloc(sizeof(struct tioce_dmamap), GFP_ATOMIC); |
222 | if (!map) | 222 | if (!map) |
223 | return 0; | 223 | return 0; |
224 | 224 | ||
@@ -555,7 +555,7 @@ tioce_kern_init(struct tioce_common *tioce_common) | |||
555 | struct tioce *tioce_mmr; | 555 | struct tioce *tioce_mmr; |
556 | struct tioce_kernel *tioce_kern; | 556 | struct tioce_kernel *tioce_kern; |
557 | 557 | ||
558 | tioce_kern = kcalloc(1, sizeof(struct tioce_kernel), GFP_KERNEL); | 558 | tioce_kern = kzalloc(sizeof(struct tioce_kernel), GFP_KERNEL); |
559 | if (!tioce_kern) { | 559 | if (!tioce_kern) { |
560 | return NULL; | 560 | return NULL; |
561 | } | 561 | } |
@@ -727,7 +727,7 @@ tioce_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont | |||
727 | * Allocate kernel bus soft and copy from prom. | 727 | * Allocate kernel bus soft and copy from prom. |
728 | */ | 728 | */ |
729 | 729 | ||
730 | tioce_common = kcalloc(1, sizeof(struct tioce_common), GFP_KERNEL); | 730 | tioce_common = kzalloc(sizeof(struct tioce_common), GFP_KERNEL); |
731 | if (!tioce_common) | 731 | if (!tioce_common) |
732 | return NULL; | 732 | return NULL; |
733 | 733 | ||
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 1493c7896fe3..ed31062029f7 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
@@ -599,6 +599,10 @@ config HAVE_ARCH_EARLY_PFN_TO_NID | |||
599 | def_bool y | 599 | def_bool y |
600 | depends on NEED_MULTIPLE_NODES | 600 | depends on NEED_MULTIPLE_NODES |
601 | 601 | ||
602 | config ARCH_MEMORY_PROBE | ||
603 | def_bool y | ||
604 | depends on MEMORY_HOTPLUG | ||
605 | |||
602 | # Some NUMA nodes have memory ranges that span | 606 | # Some NUMA nodes have memory ranges that span |
603 | # other nodes. Even though a pfn is valid and | 607 | # other nodes. Even though a pfn is valid and |
604 | # between a node's start and end pfns, it may not | 608 | # between a node's start and end pfns, it may not |
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index b3ae2993efb8..c04bbd320594 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile | |||
@@ -4,6 +4,7 @@ | |||
4 | 4 | ||
5 | ifeq ($(CONFIG_PPC64),y) | 5 | ifeq ($(CONFIG_PPC64),y) |
6 | EXTRA_CFLAGS += -mno-minimal-toc | 6 | EXTRA_CFLAGS += -mno-minimal-toc |
7 | CFLAGS_ioctl32.o += -Ifs/ | ||
7 | endif | 8 | endif |
8 | ifeq ($(CONFIG_PPC32),y) | 9 | ifeq ($(CONFIG_PPC32),y) |
9 | CFLAGS_prom_init.o += -fPIC | 10 | CFLAGS_prom_init.o += -fPIC |
@@ -11,15 +12,21 @@ CFLAGS_btext.o += -fPIC | |||
11 | endif | 12 | endif |
12 | 13 | ||
13 | obj-y := semaphore.o cputable.o ptrace.o syscalls.o \ | 14 | obj-y := semaphore.o cputable.o ptrace.o syscalls.o \ |
14 | signal_32.o pmc.o | 15 | irq.o signal_32.o pmc.o |
15 | obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \ | 16 | obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \ |
16 | signal_64.o ptrace32.o systbl.o | 17 | signal_64.o ptrace32.o systbl.o \ |
18 | paca.o ioctl32.o cpu_setup_power4.o \ | ||
19 | firmware.o sysfs.o | ||
17 | obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o | 20 | obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o |
18 | obj-$(CONFIG_POWER4) += idle_power4.o | 21 | obj-$(CONFIG_POWER4) += idle_power4.o |
19 | obj-$(CONFIG_PPC_OF) += of_device.o | 22 | obj-$(CONFIG_PPC_OF) += of_device.o |
20 | obj-$(CONFIG_PPC_RTAS) += rtas.o | 23 | procfs-$(CONFIG_PPC64) := proc_ppc64.o |
24 | obj-$(CONFIG_PROC_FS) += $(procfs-y) | ||
25 | rtaspci-$(CONFIG_PPC64) := rtas_pci.o | ||
26 | obj-$(CONFIG_PPC_RTAS) += rtas.o $(rtaspci-y) | ||
21 | obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o | 27 | obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o |
22 | obj-$(CONFIG_RTAS_PROC) += rtas-proc.o | 28 | obj-$(CONFIG_RTAS_PROC) += rtas-proc.o |
29 | obj-$(CONFIG_LPARCFG) += lparcfg.o | ||
23 | obj-$(CONFIG_IBMVIO) += vio.o | 30 | obj-$(CONFIG_IBMVIO) += vio.o |
24 | obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o | 31 | obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o |
25 | 32 | ||
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index b75757251994..8793102711a8 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c | |||
@@ -106,7 +106,6 @@ int main(void) | |||
106 | DEFINE(ICACHEL1LINESIZE, offsetof(struct ppc64_caches, iline_size)); | 106 | DEFINE(ICACHEL1LINESIZE, offsetof(struct ppc64_caches, iline_size)); |
107 | DEFINE(ICACHEL1LOGLINESIZE, offsetof(struct ppc64_caches, log_iline_size)); | 107 | DEFINE(ICACHEL1LOGLINESIZE, offsetof(struct ppc64_caches, log_iline_size)); |
108 | DEFINE(ICACHEL1LINESPERPAGE, offsetof(struct ppc64_caches, ilines_per_page)); | 108 | DEFINE(ICACHEL1LINESPERPAGE, offsetof(struct ppc64_caches, ilines_per_page)); |
109 | DEFINE(PLATFORM, offsetof(struct systemcfg, platform)); | ||
110 | DEFINE(PLATFORM_LPAR, PLATFORM_LPAR); | 109 | DEFINE(PLATFORM_LPAR, PLATFORM_LPAR); |
111 | 110 | ||
112 | /* paca */ | 111 | /* paca */ |
diff --git a/arch/ppc64/kernel/cpu_setup_power4.S b/arch/powerpc/kernel/cpu_setup_power4.S index 1fb673c511ff..cca942fe6115 100644 --- a/arch/ppc64/kernel/cpu_setup_power4.S +++ b/arch/powerpc/kernel/cpu_setup_power4.S | |||
@@ -114,11 +114,11 @@ _GLOBAL(__setup_cpu_ppc970) | |||
114 | 114 | ||
115 | .data | 115 | .data |
116 | .balign L1_CACHE_BYTES,0 | 116 | .balign L1_CACHE_BYTES,0 |
117 | cpu_state_storage: | 117 | cpu_state_storage: |
118 | .space CS_SIZE | 118 | .space CS_SIZE |
119 | .balign L1_CACHE_BYTES,0 | 119 | .balign L1_CACHE_BYTES,0 |
120 | .text | 120 | .text |
121 | 121 | ||
122 | /* Called in normal context to backup CPU 0 state. This | 122 | /* Called in normal context to backup CPU 0 state. This |
123 | * does not include cache settings. This function is also | 123 | * does not include cache settings. This function is also |
124 | * called for machine sleep. This does not include the MMU | 124 | * called for machine sleep. This does not include the MMU |
@@ -151,7 +151,7 @@ _GLOBAL(__save_cpu_setup) | |||
151 | std r3,CS_HID4(r5) | 151 | std r3,CS_HID4(r5) |
152 | mfspr r3,SPRN_HID5 | 152 | mfspr r3,SPRN_HID5 |
153 | std r3,CS_HID5(r5) | 153 | std r3,CS_HID5(r5) |
154 | 154 | ||
155 | 2: | 155 | 2: |
156 | mtcr r7 | 156 | mtcr r7 |
157 | blr | 157 | blr |
@@ -213,7 +213,7 @@ _GLOBAL(__restore_cpu_setup) | |||
213 | mtspr SPRN_HID1,r3 | 213 | mtspr SPRN_HID1,r3 |
214 | sync | 214 | sync |
215 | isync | 215 | isync |
216 | 216 | ||
217 | /* Restore HID4 */ | 217 | /* Restore HID4 */ |
218 | ld r3,CS_HID4(r5) | 218 | ld r3,CS_HID4(r5) |
219 | sync | 219 | sync |
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index cc4e9eb1c13f..1d85cedbbb7b 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c | |||
@@ -52,6 +52,9 @@ extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec); | |||
52 | #define COMMON_USER (PPC_FEATURE_32 | PPC_FEATURE_HAS_FPU | \ | 52 | #define COMMON_USER (PPC_FEATURE_32 | PPC_FEATURE_HAS_FPU | \ |
53 | PPC_FEATURE_HAS_MMU) | 53 | PPC_FEATURE_HAS_MMU) |
54 | #define COMMON_USER_PPC64 (COMMON_USER | PPC_FEATURE_64) | 54 | #define COMMON_USER_PPC64 (COMMON_USER | PPC_FEATURE_64) |
55 | #define COMMON_USER_POWER4 (COMMON_USER_PPC64 | PPC_FEATURE_POWER4) | ||
56 | #define COMMON_USER_POWER5 (COMMON_USER_PPC64 | PPC_FEATURE_POWER5) | ||
57 | #define COMMON_USER_POWER5_PLUS (COMMON_USER_PPC64 | PPC_FEATURE_POWER5_PLUS) | ||
55 | 58 | ||
56 | 59 | ||
57 | /* We only set the spe features if the kernel was compiled with | 60 | /* We only set the spe features if the kernel was compiled with |
@@ -160,7 +163,7 @@ struct cpu_spec cpu_specs[] = { | |||
160 | .pvr_value = 0x00350000, | 163 | .pvr_value = 0x00350000, |
161 | .cpu_name = "POWER4 (gp)", | 164 | .cpu_name = "POWER4 (gp)", |
162 | .cpu_features = CPU_FTRS_POWER4, | 165 | .cpu_features = CPU_FTRS_POWER4, |
163 | .cpu_user_features = COMMON_USER_PPC64, | 166 | .cpu_user_features = COMMON_USER_POWER4, |
164 | .icache_bsize = 128, | 167 | .icache_bsize = 128, |
165 | .dcache_bsize = 128, | 168 | .dcache_bsize = 128, |
166 | .num_pmcs = 8, | 169 | .num_pmcs = 8, |
@@ -175,7 +178,7 @@ struct cpu_spec cpu_specs[] = { | |||
175 | .pvr_value = 0x00380000, | 178 | .pvr_value = 0x00380000, |
176 | .cpu_name = "POWER4+ (gq)", | 179 | .cpu_name = "POWER4+ (gq)", |
177 | .cpu_features = CPU_FTRS_POWER4, | 180 | .cpu_features = CPU_FTRS_POWER4, |
178 | .cpu_user_features = COMMON_USER_PPC64, | 181 | .cpu_user_features = COMMON_USER_POWER4, |
179 | .icache_bsize = 128, | 182 | .icache_bsize = 128, |
180 | .dcache_bsize = 128, | 183 | .dcache_bsize = 128, |
181 | .num_pmcs = 8, | 184 | .num_pmcs = 8, |
@@ -190,7 +193,7 @@ struct cpu_spec cpu_specs[] = { | |||
190 | .pvr_value = 0x00390000, | 193 | .pvr_value = 0x00390000, |
191 | .cpu_name = "PPC970", | 194 | .cpu_name = "PPC970", |
192 | .cpu_features = CPU_FTRS_PPC970, | 195 | .cpu_features = CPU_FTRS_PPC970, |
193 | .cpu_user_features = COMMON_USER_PPC64 | | 196 | .cpu_user_features = COMMON_USER_POWER4 | |
194 | PPC_FEATURE_HAS_ALTIVEC_COMP, | 197 | PPC_FEATURE_HAS_ALTIVEC_COMP, |
195 | .icache_bsize = 128, | 198 | .icache_bsize = 128, |
196 | .dcache_bsize = 128, | 199 | .dcache_bsize = 128, |
@@ -212,7 +215,7 @@ struct cpu_spec cpu_specs[] = { | |||
212 | #else | 215 | #else |
213 | .cpu_features = CPU_FTRS_PPC970, | 216 | .cpu_features = CPU_FTRS_PPC970, |
214 | #endif | 217 | #endif |
215 | .cpu_user_features = COMMON_USER_PPC64 | | 218 | .cpu_user_features = COMMON_USER_POWER4 | |
216 | PPC_FEATURE_HAS_ALTIVEC_COMP, | 219 | PPC_FEATURE_HAS_ALTIVEC_COMP, |
217 | .icache_bsize = 128, | 220 | .icache_bsize = 128, |
218 | .dcache_bsize = 128, | 221 | .dcache_bsize = 128, |
@@ -230,7 +233,7 @@ struct cpu_spec cpu_specs[] = { | |||
230 | .pvr_value = 0x00440000, | 233 | .pvr_value = 0x00440000, |
231 | .cpu_name = "PPC970MP", | 234 | .cpu_name = "PPC970MP", |
232 | .cpu_features = CPU_FTRS_PPC970, | 235 | .cpu_features = CPU_FTRS_PPC970, |
233 | .cpu_user_features = COMMON_USER_PPC64 | | 236 | .cpu_user_features = COMMON_USER_POWER4 | |
234 | PPC_FEATURE_HAS_ALTIVEC_COMP, | 237 | PPC_FEATURE_HAS_ALTIVEC_COMP, |
235 | .icache_bsize = 128, | 238 | .icache_bsize = 128, |
236 | .dcache_bsize = 128, | 239 | .dcache_bsize = 128, |
@@ -245,7 +248,7 @@ struct cpu_spec cpu_specs[] = { | |||
245 | .pvr_value = 0x003a0000, | 248 | .pvr_value = 0x003a0000, |
246 | .cpu_name = "POWER5 (gr)", | 249 | .cpu_name = "POWER5 (gr)", |
247 | .cpu_features = CPU_FTRS_POWER5, | 250 | .cpu_features = CPU_FTRS_POWER5, |
248 | .cpu_user_features = COMMON_USER_PPC64, | 251 | .cpu_user_features = COMMON_USER_POWER5, |
249 | .icache_bsize = 128, | 252 | .icache_bsize = 128, |
250 | .dcache_bsize = 128, | 253 | .dcache_bsize = 128, |
251 | .num_pmcs = 6, | 254 | .num_pmcs = 6, |
@@ -260,7 +263,7 @@ struct cpu_spec cpu_specs[] = { | |||
260 | .pvr_value = 0x003b0000, | 263 | .pvr_value = 0x003b0000, |
261 | .cpu_name = "POWER5 (gs)", | 264 | .cpu_name = "POWER5 (gs)", |
262 | .cpu_features = CPU_FTRS_POWER5, | 265 | .cpu_features = CPU_FTRS_POWER5, |
263 | .cpu_user_features = COMMON_USER_PPC64, | 266 | .cpu_user_features = COMMON_USER_POWER5_PLUS, |
264 | .icache_bsize = 128, | 267 | .icache_bsize = 128, |
265 | .dcache_bsize = 128, | 268 | .dcache_bsize = 128, |
266 | .num_pmcs = 6, | 269 | .num_pmcs = 6, |
@@ -276,7 +279,7 @@ struct cpu_spec cpu_specs[] = { | |||
276 | .cpu_name = "Cell Broadband Engine", | 279 | .cpu_name = "Cell Broadband Engine", |
277 | .cpu_features = CPU_FTRS_CELL, | 280 | .cpu_features = CPU_FTRS_CELL, |
278 | .cpu_user_features = COMMON_USER_PPC64 | | 281 | .cpu_user_features = COMMON_USER_PPC64 | |
279 | PPC_FEATURE_HAS_ALTIVEC_COMP, | 282 | PPC_FEATURE_CELL | PPC_FEATURE_HAS_ALTIVEC_COMP, |
280 | .icache_bsize = 128, | 283 | .icache_bsize = 128, |
281 | .dcache_bsize = 128, | 284 | .dcache_bsize = 128, |
282 | .cpu_setup = __setup_cpu_be, | 285 | .cpu_setup = __setup_cpu_be, |
diff --git a/arch/ppc64/kernel/firmware.c b/arch/powerpc/kernel/firmware.c index d8432c0fb27d..65eae752a527 100644 --- a/arch/ppc64/kernel/firmware.c +++ b/arch/powerpc/kernel/firmware.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * arch/ppc64/kernel/firmware.c | ||
3 | * | ||
4 | * Extracted from cputable.c | 2 | * Extracted from cputable.c |
5 | * | 3 | * |
6 | * Copyright (C) 2001 Ben. Herrenschmidt (benh@kernel.crashing.org) | 4 | * Copyright (C) 2001 Ben. Herrenschmidt (benh@kernel.crashing.org) |
diff --git a/arch/powerpc/kernel/fpu.S b/arch/powerpc/kernel/fpu.S index 4d6001fa1cf2..b780b42c95fc 100644 --- a/arch/powerpc/kernel/fpu.S +++ b/arch/powerpc/kernel/fpu.S | |||
@@ -41,20 +41,20 @@ _GLOBAL(load_up_fpu) | |||
41 | #ifndef CONFIG_SMP | 41 | #ifndef CONFIG_SMP |
42 | LOADBASE(r3, last_task_used_math) | 42 | LOADBASE(r3, last_task_used_math) |
43 | toreal(r3) | 43 | toreal(r3) |
44 | LDL r4,OFF(last_task_used_math)(r3) | 44 | PPC_LL r4,OFF(last_task_used_math)(r3) |
45 | CMPI 0,r4,0 | 45 | PPC_LCMPI 0,r4,0 |
46 | beq 1f | 46 | beq 1f |
47 | toreal(r4) | 47 | toreal(r4) |
48 | addi r4,r4,THREAD /* want last_task_used_math->thread */ | 48 | addi r4,r4,THREAD /* want last_task_used_math->thread */ |
49 | SAVE_32FPRS(0, r4) | 49 | SAVE_32FPRS(0, r4) |
50 | mffs fr0 | 50 | mffs fr0 |
51 | stfd fr0,THREAD_FPSCR(r4) | 51 | stfd fr0,THREAD_FPSCR(r4) |
52 | LDL r5,PT_REGS(r4) | 52 | PPC_LL r5,PT_REGS(r4) |
53 | toreal(r5) | 53 | toreal(r5) |
54 | LDL r4,_MSR-STACK_FRAME_OVERHEAD(r5) | 54 | PPC_LL r4,_MSR-STACK_FRAME_OVERHEAD(r5) |
55 | li r10,MSR_FP|MSR_FE0|MSR_FE1 | 55 | li r10,MSR_FP|MSR_FE0|MSR_FE1 |
56 | andc r4,r4,r10 /* disable FP for previous task */ | 56 | andc r4,r4,r10 /* disable FP for previous task */ |
57 | STL r4,_MSR-STACK_FRAME_OVERHEAD(r5) | 57 | PPC_STL r4,_MSR-STACK_FRAME_OVERHEAD(r5) |
58 | 1: | 58 | 1: |
59 | #endif /* CONFIG_SMP */ | 59 | #endif /* CONFIG_SMP */ |
60 | /* enable use of FP after return */ | 60 | /* enable use of FP after return */ |
@@ -77,7 +77,7 @@ _GLOBAL(load_up_fpu) | |||
77 | #ifndef CONFIG_SMP | 77 | #ifndef CONFIG_SMP |
78 | subi r4,r5,THREAD | 78 | subi r4,r5,THREAD |
79 | fromreal(r4) | 79 | fromreal(r4) |
80 | STL r4,OFF(last_task_used_math)(r3) | 80 | PPC_STL r4,OFF(last_task_used_math)(r3) |
81 | #endif /* CONFIG_SMP */ | 81 | #endif /* CONFIG_SMP */ |
82 | /* restore registers and return */ | 82 | /* restore registers and return */ |
83 | /* we haven't used ctr or xer or lr */ | 83 | /* we haven't used ctr or xer or lr */ |
@@ -97,24 +97,24 @@ _GLOBAL(giveup_fpu) | |||
97 | MTMSRD(r5) /* enable use of fpu now */ | 97 | MTMSRD(r5) /* enable use of fpu now */ |
98 | SYNC_601 | 98 | SYNC_601 |
99 | isync | 99 | isync |
100 | CMPI 0,r3,0 | 100 | PPC_LCMPI 0,r3,0 |
101 | beqlr- /* if no previous owner, done */ | 101 | beqlr- /* if no previous owner, done */ |
102 | addi r3,r3,THREAD /* want THREAD of task */ | 102 | addi r3,r3,THREAD /* want THREAD of task */ |
103 | LDL r5,PT_REGS(r3) | 103 | PPC_LL r5,PT_REGS(r3) |
104 | CMPI 0,r5,0 | 104 | PPC_LCMPI 0,r5,0 |
105 | SAVE_32FPRS(0, r3) | 105 | SAVE_32FPRS(0, r3) |
106 | mffs fr0 | 106 | mffs fr0 |
107 | stfd fr0,THREAD_FPSCR(r3) | 107 | stfd fr0,THREAD_FPSCR(r3) |
108 | beq 1f | 108 | beq 1f |
109 | LDL r4,_MSR-STACK_FRAME_OVERHEAD(r5) | 109 | PPC_LL r4,_MSR-STACK_FRAME_OVERHEAD(r5) |
110 | li r3,MSR_FP|MSR_FE0|MSR_FE1 | 110 | li r3,MSR_FP|MSR_FE0|MSR_FE1 |
111 | andc r4,r4,r3 /* disable FP for previous task */ | 111 | andc r4,r4,r3 /* disable FP for previous task */ |
112 | STL r4,_MSR-STACK_FRAME_OVERHEAD(r5) | 112 | PPC_STL r4,_MSR-STACK_FRAME_OVERHEAD(r5) |
113 | 1: | 113 | 1: |
114 | #ifndef CONFIG_SMP | 114 | #ifndef CONFIG_SMP |
115 | li r5,0 | 115 | li r5,0 |
116 | LOADBASE(r4,last_task_used_math) | 116 | LOADBASE(r4,last_task_used_math) |
117 | STL r5,OFF(last_task_used_math)(r4) | 117 | PPC_STL r5,OFF(last_task_used_math)(r4) |
118 | #endif /* CONFIG_SMP */ | 118 | #endif /* CONFIG_SMP */ |
119 | blr | 119 | blr |
120 | 120 | ||
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 16ab40daa738..8a8bf79ef044 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S | |||
@@ -28,7 +28,6 @@ | |||
28 | #include <asm/reg.h> | 28 | #include <asm/reg.h> |
29 | #include <asm/page.h> | 29 | #include <asm/page.h> |
30 | #include <asm/mmu.h> | 30 | #include <asm/mmu.h> |
31 | #include <asm/systemcfg.h> | ||
32 | #include <asm/ppc_asm.h> | 31 | #include <asm/ppc_asm.h> |
33 | #include <asm/asm-offsets.h> | 32 | #include <asm/asm-offsets.h> |
34 | #include <asm/bug.h> | 33 | #include <asm/bug.h> |
@@ -1697,25 +1696,14 @@ _GLOBAL(pmac_secondary_start) | |||
1697 | * SPRG3 = paca virtual address | 1696 | * SPRG3 = paca virtual address |
1698 | */ | 1697 | */ |
1699 | _GLOBAL(__secondary_start) | 1698 | _GLOBAL(__secondary_start) |
1699 | /* Set thread priority to MEDIUM */ | ||
1700 | HMT_MEDIUM | ||
1700 | 1701 | ||
1701 | HMT_MEDIUM /* Set thread priority to MEDIUM */ | 1702 | /* Load TOC */ |
1702 | |||
1703 | ld r2,PACATOC(r13) | 1703 | ld r2,PACATOC(r13) |
1704 | li r6,0 | 1704 | |
1705 | stb r6,PACAPROCENABLED(r13) | 1705 | /* Do early setup for that CPU (stab, slb, hash table pointer) */ |
1706 | 1706 | bl .early_setup_secondary | |
1707 | #ifndef CONFIG_PPC_ISERIES | ||
1708 | /* Initialize the page table pointer register. */ | ||
1709 | LOADADDR(r6,_SDR1) | ||
1710 | ld r6,0(r6) /* get the value of _SDR1 */ | ||
1711 | mtspr SPRN_SDR1,r6 /* set the htab location */ | ||
1712 | #endif | ||
1713 | /* Initialize the first segment table (or SLB) entry */ | ||
1714 | ld r3,PACASTABVIRT(r13) /* get addr of segment table */ | ||
1715 | BEGIN_FTR_SECTION | ||
1716 | bl .stab_initialize | ||
1717 | END_FTR_SECTION_IFCLR(CPU_FTR_SLB) | ||
1718 | bl .slb_initialize | ||
1719 | 1707 | ||
1720 | /* Initialize the kernel stack. Just a repeat for iSeries. */ | 1708 | /* Initialize the kernel stack. Just a repeat for iSeries. */ |
1721 | LOADADDR(r3,current_set) | 1709 | LOADADDR(r3,current_set) |
@@ -1724,37 +1712,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SLB) | |||
1724 | addi r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD | 1712 | addi r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD |
1725 | std r1,PACAKSAVE(r13) | 1713 | std r1,PACAKSAVE(r13) |
1726 | 1714 | ||
1727 | ld r3,PACASTABREAL(r13) /* get raddr of segment table */ | 1715 | /* Clear backchain so we get nice backtraces */ |
1728 | ori r4,r3,1 /* turn on valid bit */ | ||
1729 | |||
1730 | #ifdef CONFIG_PPC_ISERIES | ||
1731 | li r0,-1 /* hypervisor call */ | ||
1732 | li r3,1 | ||
1733 | sldi r3,r3,63 /* 0x8000000000000000 */ | ||
1734 | ori r3,r3,4 /* 0x8000000000000004 */ | ||
1735 | sc /* HvCall_setASR */ | ||
1736 | #else | ||
1737 | /* set the ASR */ | ||
1738 | ld r3,systemcfg@got(r2) /* r3 = ptr to systemcfg */ | ||
1739 | ld r3,0(r3) | ||
1740 | lwz r3,PLATFORM(r3) /* r3 = platform flags */ | ||
1741 | andi. r3,r3,PLATFORM_LPAR /* Test if bit 0 is set (LPAR bit) */ | ||
1742 | beq 98f /* branch if result is 0 */ | ||
1743 | mfspr r3,SPRN_PVR | ||
1744 | srwi r3,r3,16 | ||
1745 | cmpwi r3,0x37 /* SStar */ | ||
1746 | beq 97f | ||
1747 | cmpwi r3,0x36 /* IStar */ | ||
1748 | beq 97f | ||
1749 | cmpwi r3,0x34 /* Pulsar */ | ||
1750 | bne 98f | ||
1751 | 97: li r3,H_SET_ASR /* hcall = H_SET_ASR */ | ||
1752 | HVSC /* Invoking hcall */ | ||
1753 | b 99f | ||
1754 | 98: /* !(rpa hypervisor) || !(star) */ | ||
1755 | mtasr r4 /* set the stab location */ | ||
1756 | 99: | ||
1757 | #endif | ||
1758 | li r7,0 | 1716 | li r7,0 |
1759 | mtlr r7 | 1717 | mtlr r7 |
1760 | 1718 | ||
@@ -1777,6 +1735,7 @@ _GLOBAL(start_secondary_prolog) | |||
1777 | li r3,0 | 1735 | li r3,0 |
1778 | std r3,0(r1) /* Zero the stack frame pointer */ | 1736 | std r3,0(r1) /* Zero the stack frame pointer */ |
1779 | bl .start_secondary | 1737 | bl .start_secondary |
1738 | b . | ||
1780 | #endif | 1739 | #endif |
1781 | 1740 | ||
1782 | /* | 1741 | /* |
@@ -1896,40 +1855,6 @@ _STATIC(start_here_multiplatform) | |||
1896 | mr r3,r31 | 1855 | mr r3,r31 |
1897 | bl .early_setup | 1856 | bl .early_setup |
1898 | 1857 | ||
1899 | /* set the ASR */ | ||
1900 | ld r3,PACASTABREAL(r13) | ||
1901 | ori r4,r3,1 /* turn on valid bit */ | ||
1902 | ld r3,systemcfg@got(r2) /* r3 = ptr to systemcfg */ | ||
1903 | ld r3,0(r3) | ||
1904 | lwz r3,PLATFORM(r3) /* r3 = platform flags */ | ||
1905 | andi. r3,r3,PLATFORM_LPAR /* Test if bit 0 is set (LPAR bit) */ | ||
1906 | beq 98f /* branch if result is 0 */ | ||
1907 | mfspr r3,SPRN_PVR | ||
1908 | srwi r3,r3,16 | ||
1909 | cmpwi r3,0x37 /* SStar */ | ||
1910 | beq 97f | ||
1911 | cmpwi r3,0x36 /* IStar */ | ||
1912 | beq 97f | ||
1913 | cmpwi r3,0x34 /* Pulsar */ | ||
1914 | bne 98f | ||
1915 | 97: li r3,H_SET_ASR /* hcall = H_SET_ASR */ | ||
1916 | HVSC /* Invoking hcall */ | ||
1917 | b 99f | ||
1918 | 98: /* !(rpa hypervisor) || !(star) */ | ||
1919 | mtasr r4 /* set the stab location */ | ||
1920 | 99: | ||
1921 | /* Set SDR1 (hash table pointer) */ | ||
1922 | ld r3,systemcfg@got(r2) /* r3 = ptr to systemcfg */ | ||
1923 | ld r3,0(r3) | ||
1924 | lwz r3,PLATFORM(r3) /* r3 = platform flags */ | ||
1925 | /* Test if bit 0 is set (LPAR bit) */ | ||
1926 | andi. r3,r3,PLATFORM_LPAR | ||
1927 | bne 98f /* branch if result is !0 */ | ||
1928 | LOADADDR(r6,_SDR1) /* Only if NOT LPAR */ | ||
1929 | add r6,r6,r26 | ||
1930 | ld r6,0(r6) /* get the value of _SDR1 */ | ||
1931 | mtspr SPRN_SDR1,r6 /* set the htab location */ | ||
1932 | 98: | ||
1933 | LOADADDR(r3,.start_here_common) | 1858 | LOADADDR(r3,.start_here_common) |
1934 | SET_REG_TO_CONST(r4, MSR_KERNEL) | 1859 | SET_REG_TO_CONST(r4, MSR_KERNEL) |
1935 | mtspr SPRN_SRR0,r3 | 1860 | mtspr SPRN_SRR0,r3 |
diff --git a/arch/ppc64/kernel/ioctl32.c b/arch/powerpc/kernel/ioctl32.c index ba4a899045c2..3fa6a93adbd0 100644 --- a/arch/ppc64/kernel/ioctl32.c +++ b/arch/powerpc/kernel/ioctl32.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * ioctl32.c: Conversion between 32bit and 64bit native ioctls. | 2 | * ioctl32.c: Conversion between 32bit and 64bit native ioctls. |
3 | * | 3 | * |
4 | * Based on sparc64 ioctl32.c by: | 4 | * Based on sparc64 ioctl32.c by: |
5 | * | 5 | * |
6 | * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com) | 6 | * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com) |
diff --git a/arch/ppc64/kernel/irq.c b/arch/powerpc/kernel/irq.c index 87474584033f..4b7940693f3d 100644 --- a/arch/ppc64/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c | |||
@@ -5,12 +5,12 @@ | |||
5 | * Copyright (C) 1992 Linus Torvalds | 5 | * Copyright (C) 1992 Linus Torvalds |
6 | * Adapted from arch/i386 by Gary Thomas | 6 | * Adapted from arch/i386 by Gary Thomas |
7 | * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) | 7 | * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) |
8 | * Updated and modified by Cort Dougan (cort@cs.nmt.edu) | 8 | * Updated and modified by Cort Dougan <cort@fsmlabs.com> |
9 | * Copyright (C) 1996 Cort Dougan | 9 | * Copyright (C) 1996-2001 Cort Dougan |
10 | * Adapted for Power Macintosh by Paul Mackerras | 10 | * Adapted for Power Macintosh by Paul Mackerras |
11 | * Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au) | 11 | * Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au) |
12 | * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | 12 | * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). |
13 | * | 13 | * |
14 | * This program is free software; you can redistribute it and/or | 14 | * This program is free software; you can redistribute it and/or |
15 | * modify it under the terms of the GNU General Public License | 15 | * modify it under the terms of the GNU General Public License |
16 | * as published by the Free Software Foundation; either version | 16 | * as published by the Free Software Foundation; either version |
@@ -21,6 +21,14 @@ | |||
21 | * instead of just grabbing them. Thus setups with different IRQ numbers | 21 | * instead of just grabbing them. Thus setups with different IRQ numbers |
22 | * shouldn't result in any weird surprises, and installing new handlers | 22 | * shouldn't result in any weird surprises, and installing new handlers |
23 | * should be easier. | 23 | * should be easier. |
24 | * | ||
25 | * The MPC8xx has an interrupt mask in the SIU. If a bit is set, the | ||
26 | * interrupt is _enabled_. As expected, IRQ0 is bit 0 in the 32-bit | ||
27 | * mask register (of which only 16 are defined), hence the weird shifting | ||
28 | * and complement of the cached_irq_mask. I want to be able to stuff | ||
29 | * this right into the SIU SMASK register. | ||
30 | * Many of the prep/chrp functions are conditional compiled on CONFIG_8xx | ||
31 | * to reduce code space and undefined function references. | ||
24 | */ | 32 | */ |
25 | 33 | ||
26 | #include <linux/errno.h> | 34 | #include <linux/errno.h> |
@@ -29,6 +37,7 @@ | |||
29 | #include <linux/kernel_stat.h> | 37 | #include <linux/kernel_stat.h> |
30 | #include <linux/signal.h> | 38 | #include <linux/signal.h> |
31 | #include <linux/sched.h> | 39 | #include <linux/sched.h> |
40 | #include <linux/ptrace.h> | ||
32 | #include <linux/ioport.h> | 41 | #include <linux/ioport.h> |
33 | #include <linux/interrupt.h> | 42 | #include <linux/interrupt.h> |
34 | #include <linux/timex.h> | 43 | #include <linux/timex.h> |
@@ -40,9 +49,13 @@ | |||
40 | #include <linux/irq.h> | 49 | #include <linux/irq.h> |
41 | #include <linux/proc_fs.h> | 50 | #include <linux/proc_fs.h> |
42 | #include <linux/random.h> | 51 | #include <linux/random.h> |
43 | #include <linux/kallsyms.h> | 52 | #include <linux/seq_file.h> |
53 | #include <linux/cpumask.h> | ||
44 | #include <linux/profile.h> | 54 | #include <linux/profile.h> |
45 | #include <linux/bitops.h> | 55 | #include <linux/bitops.h> |
56 | #ifdef CONFIG_PPC64 | ||
57 | #include <linux/kallsyms.h> | ||
58 | #endif | ||
46 | 59 | ||
47 | #include <asm/uaccess.h> | 60 | #include <asm/uaccess.h> |
48 | #include <asm/system.h> | 61 | #include <asm/system.h> |
@@ -52,35 +65,54 @@ | |||
52 | #include <asm/cache.h> | 65 | #include <asm/cache.h> |
53 | #include <asm/prom.h> | 66 | #include <asm/prom.h> |
54 | #include <asm/ptrace.h> | 67 | #include <asm/ptrace.h> |
55 | #include <asm/iseries/it_lp_queue.h> | ||
56 | #include <asm/machdep.h> | 68 | #include <asm/machdep.h> |
69 | #ifdef CONFIG_PPC64 | ||
70 | #include <asm/iseries/it_lp_queue.h> | ||
57 | #include <asm/paca.h> | 71 | #include <asm/paca.h> |
72 | #endif | ||
58 | 73 | ||
59 | #ifdef CONFIG_SMP | 74 | static int ppc_spurious_interrupts; |
60 | extern void iSeries_smp_message_recv( struct pt_regs * ); | 75 | |
76 | #if defined(CONFIG_PPC_ISERIES) && defined(CONFIG_SMP) | ||
77 | extern void iSeries_smp_message_recv(struct pt_regs *); | ||
78 | #endif | ||
79 | |||
80 | #ifdef CONFIG_PPC32 | ||
81 | #define NR_MASK_WORDS ((NR_IRQS + 31) / 32) | ||
82 | |||
83 | unsigned long ppc_cached_irq_mask[NR_MASK_WORDS]; | ||
84 | atomic_t ppc_n_lost_interrupts; | ||
85 | |||
86 | #ifdef CONFIG_TAU_INT | ||
87 | extern int tau_initialized; | ||
88 | extern int tau_interrupts(int); | ||
89 | #endif | ||
90 | |||
91 | #if defined(CONFIG_SMP) && !defined(CONFIG_PPC_MERGE) | ||
92 | extern atomic_t ipi_recv; | ||
93 | extern atomic_t ipi_sent; | ||
61 | #endif | 94 | #endif |
95 | #endif /* CONFIG_PPC32 */ | ||
62 | 96 | ||
63 | extern irq_desc_t irq_desc[NR_IRQS]; | 97 | #ifdef CONFIG_PPC64 |
64 | EXPORT_SYMBOL(irq_desc); | 98 | EXPORT_SYMBOL(irq_desc); |
65 | 99 | ||
66 | int distribute_irqs = 1; | 100 | int distribute_irqs = 1; |
67 | int __irq_offset_value; | 101 | int __irq_offset_value; |
68 | int ppc_spurious_interrupts; | ||
69 | u64 ppc64_interrupt_controller; | 102 | u64 ppc64_interrupt_controller; |
103 | #endif /* CONFIG_PPC64 */ | ||
70 | 104 | ||
71 | int show_interrupts(struct seq_file *p, void *v) | 105 | int show_interrupts(struct seq_file *p, void *v) |
72 | { | 106 | { |
73 | int i = *(loff_t *) v, j; | 107 | int i = *(loff_t *)v, j; |
74 | struct irqaction * action; | 108 | struct irqaction *action; |
75 | irq_desc_t *desc; | 109 | irq_desc_t *desc; |
76 | unsigned long flags; | 110 | unsigned long flags; |
77 | 111 | ||
78 | if (i == 0) { | 112 | if (i == 0) { |
79 | seq_printf(p, " "); | 113 | seq_puts(p, " "); |
80 | for (j=0; j<NR_CPUS; j++) { | 114 | for_each_online_cpu(j) |
81 | if (cpu_online(j)) | 115 | seq_printf(p, "CPU%d ", j); |
82 | seq_printf(p, "CPU%d ",j); | ||
83 | } | ||
84 | seq_putc(p, '\n'); | 116 | seq_putc(p, '\n'); |
85 | } | 117 | } |
86 | 118 | ||
@@ -92,26 +124,41 @@ int show_interrupts(struct seq_file *p, void *v) | |||
92 | goto skip; | 124 | goto skip; |
93 | seq_printf(p, "%3d: ", i); | 125 | seq_printf(p, "%3d: ", i); |
94 | #ifdef CONFIG_SMP | 126 | #ifdef CONFIG_SMP |
95 | for (j = 0; j < NR_CPUS; j++) { | 127 | for_each_online_cpu(j) |
96 | if (cpu_online(j)) | 128 | seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); |
97 | seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); | ||
98 | } | ||
99 | #else | 129 | #else |
100 | seq_printf(p, "%10u ", kstat_irqs(i)); | 130 | seq_printf(p, "%10u ", kstat_irqs(i)); |
101 | #endif /* CONFIG_SMP */ | 131 | #endif /* CONFIG_SMP */ |
102 | if (desc->handler) | 132 | if (desc->handler) |
103 | seq_printf(p, " %s ", desc->handler->typename ); | 133 | seq_printf(p, " %s ", desc->handler->typename); |
104 | else | 134 | else |
105 | seq_printf(p, " None "); | 135 | seq_puts(p, " None "); |
106 | seq_printf(p, "%s", (desc->status & IRQ_LEVEL) ? "Level " : "Edge "); | 136 | seq_printf(p, "%s", (desc->status & IRQ_LEVEL) ? "Level " : "Edge "); |
107 | seq_printf(p, " %s",action->name); | 137 | seq_printf(p, " %s", action->name); |
108 | for (action=action->next; action; action = action->next) | 138 | for (action = action->next; action; action = action->next) |
109 | seq_printf(p, ", %s", action->name); | 139 | seq_printf(p, ", %s", action->name); |
110 | seq_putc(p, '\n'); | 140 | seq_putc(p, '\n'); |
111 | skip: | 141 | skip: |
112 | spin_unlock_irqrestore(&desc->lock, flags); | 142 | spin_unlock_irqrestore(&desc->lock, flags); |
113 | } else if (i == NR_IRQS) | 143 | } else if (i == NR_IRQS) { |
144 | #ifdef CONFIG_PPC32 | ||
145 | #ifdef CONFIG_TAU_INT | ||
146 | if (tau_initialized){ | ||
147 | seq_puts(p, "TAU: "); | ||
148 | for (j = 0; j < NR_CPUS; j++) | ||
149 | if (cpu_online(j)) | ||
150 | seq_printf(p, "%10u ", tau_interrupts(j)); | ||
151 | seq_puts(p, " PowerPC Thermal Assist (cpu temp)\n"); | ||
152 | } | ||
153 | #endif | ||
154 | #if defined(CONFIG_SMP) && !defined(CONFIG_PPC_MERGE) | ||
155 | /* should this be per processor send/receive? */ | ||
156 | seq_printf(p, "IPI (recv/sent): %10u/%u\n", | ||
157 | atomic_read(&ipi_recv), atomic_read(&ipi_sent)); | ||
158 | #endif | ||
159 | #endif /* CONFIG_PPC32 */ | ||
114 | seq_printf(p, "BAD: %10u\n", ppc_spurious_interrupts); | 160 | seq_printf(p, "BAD: %10u\n", ppc_spurious_interrupts); |
161 | } | ||
115 | return 0; | 162 | return 0; |
116 | } | 163 | } |
117 | 164 | ||
@@ -144,126 +191,6 @@ void fixup_irqs(cpumask_t map) | |||
144 | } | 191 | } |
145 | #endif | 192 | #endif |
146 | 193 | ||
147 | extern int noirqdebug; | ||
148 | |||
149 | /* | ||
150 | * Eventually, this should take an array of interrupts and an array size | ||
151 | * so it can dispatch multiple interrupts. | ||
152 | */ | ||
153 | void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq) | ||
154 | { | ||
155 | int status; | ||
156 | struct irqaction *action; | ||
157 | int cpu = smp_processor_id(); | ||
158 | irq_desc_t *desc = get_irq_desc(irq); | ||
159 | irqreturn_t action_ret; | ||
160 | #ifdef CONFIG_IRQSTACKS | ||
161 | struct thread_info *curtp, *irqtp; | ||
162 | #endif | ||
163 | |||
164 | kstat_cpu(cpu).irqs[irq]++; | ||
165 | |||
166 | if (desc->status & IRQ_PER_CPU) { | ||
167 | /* no locking required for CPU-local interrupts: */ | ||
168 | ack_irq(irq); | ||
169 | action_ret = handle_IRQ_event(irq, regs, desc->action); | ||
170 | desc->handler->end(irq); | ||
171 | return; | ||
172 | } | ||
173 | |||
174 | spin_lock(&desc->lock); | ||
175 | ack_irq(irq); | ||
176 | /* | ||
177 | REPLAY is when Linux resends an IRQ that was dropped earlier | ||
178 | WAITING is used by probe to mark irqs that are being tested | ||
179 | */ | ||
180 | status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING); | ||
181 | status |= IRQ_PENDING; /* we _want_ to handle it */ | ||
182 | |||
183 | /* | ||
184 | * If the IRQ is disabled for whatever reason, we cannot | ||
185 | * use the action we have. | ||
186 | */ | ||
187 | action = NULL; | ||
188 | if (likely(!(status & (IRQ_DISABLED | IRQ_INPROGRESS)))) { | ||
189 | action = desc->action; | ||
190 | if (!action || !action->handler) { | ||
191 | ppc_spurious_interrupts++; | ||
192 | printk(KERN_DEBUG "Unhandled interrupt %x, disabled\n", irq); | ||
193 | /* We can't call disable_irq here, it would deadlock */ | ||
194 | if (!desc->depth) | ||
195 | desc->depth = 1; | ||
196 | desc->status |= IRQ_DISABLED; | ||
197 | /* This is not a real spurrious interrupt, we | ||
198 | * have to eoi it, so we jump to out | ||
199 | */ | ||
200 | mask_irq(irq); | ||
201 | goto out; | ||
202 | } | ||
203 | status &= ~IRQ_PENDING; /* we commit to handling */ | ||
204 | status |= IRQ_INPROGRESS; /* we are handling it */ | ||
205 | } | ||
206 | desc->status = status; | ||
207 | |||
208 | /* | ||
209 | * If there is no IRQ handler or it was disabled, exit early. | ||
210 | Since we set PENDING, if another processor is handling | ||
211 | a different instance of this same irq, the other processor | ||
212 | will take care of it. | ||
213 | */ | ||
214 | if (unlikely(!action)) | ||
215 | goto out; | ||
216 | |||
217 | /* | ||
218 | * Edge triggered interrupts need to remember | ||
219 | * pending events. | ||
220 | * This applies to any hw interrupts that allow a second | ||
221 | * instance of the same irq to arrive while we are in do_IRQ | ||
222 | * or in the handler. But the code here only handles the _second_ | ||
223 | * instance of the irq, not the third or fourth. So it is mostly | ||
224 | * useful for irq hardware that does not mask cleanly in an | ||
225 | * SMP environment. | ||
226 | */ | ||
227 | for (;;) { | ||
228 | spin_unlock(&desc->lock); | ||
229 | |||
230 | #ifdef CONFIG_IRQSTACKS | ||
231 | /* Switch to the irq stack to handle this */ | ||
232 | curtp = current_thread_info(); | ||
233 | irqtp = hardirq_ctx[smp_processor_id()]; | ||
234 | if (curtp != irqtp) { | ||
235 | irqtp->task = curtp->task; | ||
236 | irqtp->flags = 0; | ||
237 | action_ret = call_handle_IRQ_event(irq, regs, action, irqtp); | ||
238 | irqtp->task = NULL; | ||
239 | if (irqtp->flags) | ||
240 | set_bits(irqtp->flags, &curtp->flags); | ||
241 | } else | ||
242 | #endif | ||
243 | action_ret = handle_IRQ_event(irq, regs, action); | ||
244 | |||
245 | spin_lock(&desc->lock); | ||
246 | if (!noirqdebug) | ||
247 | note_interrupt(irq, desc, action_ret, regs); | ||
248 | if (likely(!(desc->status & IRQ_PENDING))) | ||
249 | break; | ||
250 | desc->status &= ~IRQ_PENDING; | ||
251 | } | ||
252 | out: | ||
253 | desc->status &= ~IRQ_INPROGRESS; | ||
254 | /* | ||
255 | * The ->end() handler has to deal with interrupts which got | ||
256 | * disabled while the handler was running. | ||
257 | */ | ||
258 | if (desc->handler) { | ||
259 | if (desc->handler->end) | ||
260 | desc->handler->end(irq); | ||
261 | else if (desc->handler->enable) | ||
262 | desc->handler->enable(irq); | ||
263 | } | ||
264 | spin_unlock(&desc->lock); | ||
265 | } | ||
266 | |||
267 | #ifdef CONFIG_PPC_ISERIES | 194 | #ifdef CONFIG_PPC_ISERIES |
268 | void do_IRQ(struct pt_regs *regs) | 195 | void do_IRQ(struct pt_regs *regs) |
269 | { | 196 | { |
@@ -310,8 +237,11 @@ void do_IRQ(struct pt_regs *regs) | |||
310 | void do_IRQ(struct pt_regs *regs) | 237 | void do_IRQ(struct pt_regs *regs) |
311 | { | 238 | { |
312 | int irq; | 239 | int irq; |
240 | #ifdef CONFIG_IRQSTACKS | ||
241 | struct thread_info *curtp, *irqtp; | ||
242 | #endif | ||
313 | 243 | ||
314 | irq_enter(); | 244 | irq_enter(); |
315 | 245 | ||
316 | #ifdef CONFIG_DEBUG_STACKOVERFLOW | 246 | #ifdef CONFIG_DEBUG_STACKOVERFLOW |
317 | /* Debugging check for stack overflow: is there less than 2KB free? */ | 247 | /* Debugging check for stack overflow: is there less than 2KB free? */ |
@@ -328,20 +258,44 @@ void do_IRQ(struct pt_regs *regs) | |||
328 | } | 258 | } |
329 | #endif | 259 | #endif |
330 | 260 | ||
261 | /* | ||
262 | * Every platform is required to implement ppc_md.get_irq. | ||
263 | * This function will either return an irq number or -1 to | ||
264 | * indicate there are no more pending. | ||
265 | * The value -2 is for buggy hardware and means that this IRQ | ||
266 | * has already been handled. -- Tom | ||
267 | */ | ||
331 | irq = ppc_md.get_irq(regs); | 268 | irq = ppc_md.get_irq(regs); |
332 | 269 | ||
333 | if (irq >= 0) | 270 | if (irq >= 0) { |
334 | ppc_irq_dispatch_handler(regs, irq); | 271 | #ifdef CONFIG_IRQSTACKS |
335 | else | 272 | /* Switch to the irq stack to handle this */ |
336 | /* That's not SMP safe ... but who cares ? */ | 273 | curtp = current_thread_info(); |
337 | ppc_spurious_interrupts++; | 274 | irqtp = hardirq_ctx[smp_processor_id()]; |
338 | 275 | if (curtp != irqtp) { | |
339 | irq_exit(); | 276 | irqtp->task = curtp->task; |
277 | irqtp->flags = 0; | ||
278 | call___do_IRQ(irq, regs, irqtp); | ||
279 | irqtp->task = NULL; | ||
280 | if (irqtp->flags) | ||
281 | set_bits(irqtp->flags, &curtp->flags); | ||
282 | } else | ||
283 | #endif | ||
284 | __do_IRQ(irq, regs); | ||
285 | } else | ||
286 | #ifdef CONFIG_PPC32 | ||
287 | if (irq != -2) | ||
288 | #endif | ||
289 | /* That's not SMP safe ... but who cares ? */ | ||
290 | ppc_spurious_interrupts++; | ||
291 | irq_exit(); | ||
340 | } | 292 | } |
293 | |||
341 | #endif /* CONFIG_PPC_ISERIES */ | 294 | #endif /* CONFIG_PPC_ISERIES */ |
342 | 295 | ||
343 | void __init init_IRQ(void) | 296 | void __init init_IRQ(void) |
344 | { | 297 | { |
298 | #ifdef CONFIG_PPC64 | ||
345 | static int once = 0; | 299 | static int once = 0; |
346 | 300 | ||
347 | if (once) | 301 | if (once) |
@@ -349,10 +303,14 @@ void __init init_IRQ(void) | |||
349 | 303 | ||
350 | once++; | 304 | once++; |
351 | 305 | ||
306 | #endif | ||
352 | ppc_md.init_IRQ(); | 307 | ppc_md.init_IRQ(); |
308 | #ifdef CONFIG_PPC64 | ||
353 | irq_ctx_init(); | 309 | irq_ctx_init(); |
310 | #endif | ||
354 | } | 311 | } |
355 | 312 | ||
313 | #ifdef CONFIG_PPC64 | ||
356 | #ifndef CONFIG_PPC_ISERIES | 314 | #ifndef CONFIG_PPC_ISERIES |
357 | /* | 315 | /* |
358 | * Virtual IRQ mapping code, used on systems with XICS interrupt controllers. | 316 | * Virtual IRQ mapping code, used on systems with XICS interrupt controllers. |
@@ -517,3 +475,4 @@ static int __init setup_noirqdistrib(char *str) | |||
517 | } | 475 | } |
518 | 476 | ||
519 | __setup("noirqdistrib", setup_noirqdistrib); | 477 | __setup("noirqdistrib", setup_noirqdistrib); |
478 | #endif /* CONFIG_PPC64 */ | ||
diff --git a/arch/ppc64/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c index 3e7b2f28ec83..5e954fae031f 100644 --- a/arch/ppc64/kernel/lparcfg.c +++ b/arch/powerpc/kernel/lparcfg.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <asm/time.h> | 35 | #include <asm/time.h> |
36 | #include <asm/iseries/it_exp_vpd_panel.h> | 36 | #include <asm/iseries/it_exp_vpd_panel.h> |
37 | #include <asm/prom.h> | 37 | #include <asm/prom.h> |
38 | #include <asm/systemcfg.h> | ||
38 | 39 | ||
39 | #define MODULE_VERS "1.6" | 40 | #define MODULE_VERS "1.6" |
40 | #define MODULE_NAME "lparcfg" | 41 | #define MODULE_NAME "lparcfg" |
@@ -96,7 +97,7 @@ static unsigned long get_purr(void) | |||
96 | 97 | ||
97 | #define lparcfg_write NULL | 98 | #define lparcfg_write NULL |
98 | 99 | ||
99 | /* | 100 | /* |
100 | * Methods used to fetch LPAR data when running on an iSeries platform. | 101 | * Methods used to fetch LPAR data when running on an iSeries platform. |
101 | */ | 102 | */ |
102 | static int lparcfg_data(struct seq_file *m, void *v) | 103 | static int lparcfg_data(struct seq_file *m, void *v) |
@@ -168,7 +169,7 @@ static int lparcfg_data(struct seq_file *m, void *v) | |||
168 | #endif /* CONFIG_PPC_ISERIES */ | 169 | #endif /* CONFIG_PPC_ISERIES */ |
169 | 170 | ||
170 | #ifdef CONFIG_PPC_PSERIES | 171 | #ifdef CONFIG_PPC_PSERIES |
171 | /* | 172 | /* |
172 | * Methods used to fetch LPAR data when running on a pSeries platform. | 173 | * Methods used to fetch LPAR data when running on a pSeries platform. |
173 | */ | 174 | */ |
174 | 175 | ||
@@ -177,7 +178,7 @@ static int lparcfg_data(struct seq_file *m, void *v) | |||
177 | * entitled_capacity,unallocated_capacity, | 178 | * entitled_capacity,unallocated_capacity, |
178 | * aggregation, resource_capability). | 179 | * aggregation, resource_capability). |
179 | * | 180 | * |
180 | * R4 = Entitled Processor Capacity Percentage. | 181 | * R4 = Entitled Processor Capacity Percentage. |
181 | * R5 = Unallocated Processor Capacity Percentage. | 182 | * R5 = Unallocated Processor Capacity Percentage. |
182 | * R6 (AABBCCDDEEFFGGHH). | 183 | * R6 (AABBCCDDEEFFGGHH). |
183 | * XXXX - reserved (0) | 184 | * XXXX - reserved (0) |
@@ -190,7 +191,7 @@ static int lparcfg_data(struct seq_file *m, void *v) | |||
190 | * XX - variable processor Capacity Weight | 191 | * XX - variable processor Capacity Weight |
191 | * XX - Unallocated Variable Processor Capacity Weight. | 192 | * XX - Unallocated Variable Processor Capacity Weight. |
192 | * XXXX - Active processors in Physical Processor Pool. | 193 | * XXXX - Active processors in Physical Processor Pool. |
193 | * XXXX - Processors active on platform. | 194 | * XXXX - Processors active on platform. |
194 | */ | 195 | */ |
195 | static unsigned int h_get_ppp(unsigned long *entitled, | 196 | static unsigned int h_get_ppp(unsigned long *entitled, |
196 | unsigned long *unallocated, | 197 | unsigned long *unallocated, |
@@ -273,7 +274,7 @@ static void parse_system_parameter_string(struct seq_file *m) | |||
273 | if (!workbuffer) { | 274 | if (!workbuffer) { |
274 | printk(KERN_ERR "%s %s kmalloc failure at line %d \n", | 275 | printk(KERN_ERR "%s %s kmalloc failure at line %d \n", |
275 | __FILE__, __FUNCTION__, __LINE__); | 276 | __FILE__, __FUNCTION__, __LINE__); |
276 | kfree(local_buffer); | 277 | kfree(local_buffer); |
277 | return; | 278 | return; |
278 | } | 279 | } |
279 | #ifdef LPARCFG_DEBUG | 280 | #ifdef LPARCFG_DEBUG |
@@ -371,7 +372,7 @@ static int lparcfg_data(struct seq_file *m, void *v) | |||
371 | lrdrp = (int *)get_property(rtas_node, "ibm,lrdr-capacity", NULL); | 372 | lrdrp = (int *)get_property(rtas_node, "ibm,lrdr-capacity", NULL); |
372 | 373 | ||
373 | if (lrdrp == NULL) { | 374 | if (lrdrp == NULL) { |
374 | partition_potential_processors = systemcfg->processorCount; | 375 | partition_potential_processors = _systemcfg->processorCount; |
375 | } else { | 376 | } else { |
376 | partition_potential_processors = *(lrdrp + 4); | 377 | partition_potential_processors = *(lrdrp + 4); |
377 | } | 378 | } |
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S index 3bedb532aed9..f6d84a75ed26 100644 --- a/arch/powerpc/kernel/misc_32.S +++ b/arch/powerpc/kernel/misc_32.S | |||
@@ -519,7 +519,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) | |||
519 | * | 519 | * |
520 | * flush_icache_range(unsigned long start, unsigned long stop) | 520 | * flush_icache_range(unsigned long start, unsigned long stop) |
521 | */ | 521 | */ |
522 | _GLOBAL(flush_icache_range) | 522 | _GLOBAL(__flush_icache_range) |
523 | BEGIN_FTR_SECTION | 523 | BEGIN_FTR_SECTION |
524 | blr /* for 601, do nothing */ | 524 | blr /* for 601, do nothing */ |
525 | END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) | 525 | END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) |
@@ -607,27 +607,6 @@ _GLOBAL(invalidate_dcache_range) | |||
607 | sync /* wait for dcbi's to get to ram */ | 607 | sync /* wait for dcbi's to get to ram */ |
608 | blr | 608 | blr |
609 | 609 | ||
610 | #ifdef CONFIG_NOT_COHERENT_CACHE | ||
611 | /* | ||
612 | * 40x cores have 8K or 16K dcache and 32 byte line size. | ||
613 | * 44x has a 32K dcache and 32 byte line size. | ||
614 | * 8xx has 1, 2, 4, 8K variants. | ||
615 | * For now, cover the worst case of the 44x. | ||
616 | * Must be called with external interrupts disabled. | ||
617 | */ | ||
618 | #define CACHE_NWAYS 64 | ||
619 | #define CACHE_NLINES 16 | ||
620 | |||
621 | _GLOBAL(flush_dcache_all) | ||
622 | li r4, (2 * CACHE_NWAYS * CACHE_NLINES) | ||
623 | mtctr r4 | ||
624 | lis r5, KERNELBASE@h | ||
625 | 1: lwz r3, 0(r5) /* Load one word from every line */ | ||
626 | addi r5, r5, L1_CACHE_BYTES | ||
627 | bdnz 1b | ||
628 | blr | ||
629 | #endif /* CONFIG_NOT_COHERENT_CACHE */ | ||
630 | |||
631 | /* | 610 | /* |
632 | * Flush a particular page from the data cache to RAM. | 611 | * Flush a particular page from the data cache to RAM. |
633 | * Note: this is necessary because the instruction cache does *not* | 612 | * Note: this is necessary because the instruction cache does *not* |
diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S index ae1433da09b2..ae48a002f81a 100644 --- a/arch/powerpc/kernel/misc_64.S +++ b/arch/powerpc/kernel/misc_64.S | |||
@@ -89,12 +89,12 @@ _GLOBAL(call_do_softirq) | |||
89 | mtlr r0 | 89 | mtlr r0 |
90 | blr | 90 | blr |
91 | 91 | ||
92 | _GLOBAL(call_handle_IRQ_event) | 92 | _GLOBAL(call___do_IRQ) |
93 | mflr r0 | 93 | mflr r0 |
94 | std r0,16(r1) | 94 | std r0,16(r1) |
95 | stdu r1,THREAD_SIZE-112(r6) | 95 | stdu r1,THREAD_SIZE-112(r5) |
96 | mr r1,r6 | 96 | mr r1,r5 |
97 | bl .handle_IRQ_event | 97 | bl .__do_IRQ |
98 | ld r1,0(r1) | 98 | ld r1,0(r1) |
99 | ld r0,16(r1) | 99 | ld r0,16(r1) |
100 | mtlr r0 | 100 | mtlr r0 |
diff --git a/arch/ppc64/kernel/pacaData.c b/arch/powerpc/kernel/paca.c index 3133c72b28ec..3cf2517c5f91 100644 --- a/arch/ppc64/kernel/pacaData.c +++ b/arch/powerpc/kernel/paca.c | |||
@@ -15,7 +15,7 @@ | |||
15 | #include <asm/processor.h> | 15 | #include <asm/processor.h> |
16 | #include <asm/ptrace.h> | 16 | #include <asm/ptrace.h> |
17 | #include <asm/page.h> | 17 | #include <asm/page.h> |
18 | 18 | #include <asm/systemcfg.h> | |
19 | #include <asm/lppaca.h> | 19 | #include <asm/lppaca.h> |
20 | #include <asm/iseries/it_lp_queue.h> | 20 | #include <asm/iseries/it_lp_queue.h> |
21 | #include <asm/paca.h> | 21 | #include <asm/paca.h> |
@@ -24,15 +24,14 @@ static union { | |||
24 | struct systemcfg data; | 24 | struct systemcfg data; |
25 | u8 page[PAGE_SIZE]; | 25 | u8 page[PAGE_SIZE]; |
26 | } systemcfg_store __attribute__((__section__(".data.page.aligned"))); | 26 | } systemcfg_store __attribute__((__section__(".data.page.aligned"))); |
27 | struct systemcfg *systemcfg = &systemcfg_store.data; | 27 | struct systemcfg *_systemcfg = &systemcfg_store.data; |
28 | EXPORT_SYMBOL(systemcfg); | ||
29 | 28 | ||
30 | 29 | ||
31 | /* This symbol is provided by the linker - let it fill in the paca | 30 | /* This symbol is provided by the linker - let it fill in the paca |
32 | * field correctly */ | 31 | * field correctly */ |
33 | extern unsigned long __toc_start; | 32 | extern unsigned long __toc_start; |
34 | 33 | ||
35 | /* The Paca is an array with one entry per processor. Each contains an | 34 | /* The Paca is an array with one entry per processor. Each contains an |
36 | * lppaca, which contains the information shared between the | 35 | * lppaca, which contains the information shared between the |
37 | * hypervisor and Linux. Each also contains an ItLpRegSave area which | 36 | * hypervisor and Linux. Each also contains an ItLpRegSave area which |
38 | * is used by the hypervisor to save registers. | 37 | * is used by the hypervisor to save registers. |
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c index 47d6f7e2ea9f..5dcf4ba05ee8 100644 --- a/arch/powerpc/kernel/ppc_ksyms.c +++ b/arch/powerpc/kernel/ppc_ksyms.c | |||
@@ -44,6 +44,7 @@ | |||
44 | #include <asm/cputable.h> | 44 | #include <asm/cputable.h> |
45 | #include <asm/btext.h> | 45 | #include <asm/btext.h> |
46 | #include <asm/div64.h> | 46 | #include <asm/div64.h> |
47 | #include <asm/signal.h> | ||
47 | 48 | ||
48 | #ifdef CONFIG_8xx | 49 | #ifdef CONFIG_8xx |
49 | #include <asm/commproc.h> | 50 | #include <asm/commproc.h> |
@@ -56,7 +57,6 @@ extern void machine_check_exception(struct pt_regs *regs); | |||
56 | extern void alignment_exception(struct pt_regs *regs); | 57 | extern void alignment_exception(struct pt_regs *regs); |
57 | extern void program_check_exception(struct pt_regs *regs); | 58 | extern void program_check_exception(struct pt_regs *regs); |
58 | extern void single_step_exception(struct pt_regs *regs); | 59 | extern void single_step_exception(struct pt_regs *regs); |
59 | extern int do_signal(sigset_t *, struct pt_regs *); | ||
60 | extern int pmac_newworld; | 60 | extern int pmac_newworld; |
61 | extern int sys_sigreturn(struct pt_regs *regs); | 61 | extern int sys_sigreturn(struct pt_regs *regs); |
62 | 62 | ||
@@ -188,9 +188,6 @@ EXPORT_SYMBOL(adb_try_handler_change); | |||
188 | EXPORT_SYMBOL(cuda_request); | 188 | EXPORT_SYMBOL(cuda_request); |
189 | EXPORT_SYMBOL(cuda_poll); | 189 | EXPORT_SYMBOL(cuda_poll); |
190 | #endif /* CONFIG_ADB_CUDA */ | 190 | #endif /* CONFIG_ADB_CUDA */ |
191 | #if defined(CONFIG_PPC_MULTIPLATFORM) && defined(CONFIG_PPC32) | ||
192 | EXPORT_SYMBOL(_machine); | ||
193 | #endif | ||
194 | #ifdef CONFIG_PPC_PMAC | 191 | #ifdef CONFIG_PPC_PMAC |
195 | EXPORT_SYMBOL(sys_ctrler); | 192 | EXPORT_SYMBOL(sys_ctrler); |
196 | #endif | 193 | #endif |
diff --git a/arch/ppc64/kernel/proc_ppc64.c b/arch/powerpc/kernel/proc_ppc64.c index 24e955ee9487..a1c19502fe8b 100644 --- a/arch/ppc64/kernel/proc_ppc64.c +++ b/arch/powerpc/kernel/proc_ppc64.c | |||
@@ -1,18 +1,16 @@ | |||
1 | /* | 1 | /* |
2 | * arch/ppc64/kernel/proc_ppc64.c | ||
3 | * | ||
4 | * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen IBM Corporation | 2 | * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen IBM Corporation |
5 | * | 3 | * |
6 | * This program is free software; you can redistribute it and/or modify | 4 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by | 5 | * it under the terms of the GNU General Public License as published by |
8 | * the Free Software Foundation; either version 2 of the License, or | 6 | * the Free Software Foundation; either version 2 of the License, or |
9 | * (at your option) any later version. | 7 | * (at your option) any later version. |
10 | * | 8 | * |
11 | * This program is distributed in the hope that it will be useful, | 9 | * This program is distributed in the hope that it will be useful, |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | * GNU General Public License for more details. | 12 | * GNU General Public License for more details. |
15 | * | 13 | * |
16 | * You should have received a copy of the GNU General Public License | 14 | * You should have received a copy of the GNU General Public License |
17 | * along with this program; if not, write to the Free Software | 15 | * along with this program; if not, write to the Free Software |
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
@@ -53,7 +51,7 @@ static int __init proc_ppc64_create(void) | |||
53 | if (!root) | 51 | if (!root) |
54 | return 1; | 52 | return 1; |
55 | 53 | ||
56 | if (!(systemcfg->platform & (PLATFORM_PSERIES | PLATFORM_CELL))) | 54 | if (!(platform_is_pseries() || _machine == PLATFORM_CELL)) |
57 | return 0; | 55 | return 0; |
58 | 56 | ||
59 | if (!proc_mkdir("rtas", root)) | 57 | if (!proc_mkdir("rtas", root)) |
@@ -74,7 +72,7 @@ static int __init proc_ppc64_init(void) | |||
74 | if (!pde) | 72 | if (!pde) |
75 | return 1; | 73 | return 1; |
76 | pde->nlink = 1; | 74 | pde->nlink = 1; |
77 | pde->data = systemcfg; | 75 | pde->data = _systemcfg; |
78 | pde->size = PAGE_SIZE; | 76 | pde->size = PAGE_SIZE; |
79 | pde->proc_fops = &page_map_fops; | 77 | pde->proc_fops = &page_map_fops; |
80 | 78 | ||
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index f645adb57534..6a5b468edb4d 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c | |||
@@ -48,9 +48,6 @@ | |||
48 | #include <asm/machdep.h> | 48 | #include <asm/machdep.h> |
49 | #include <asm/pSeries_reconfig.h> | 49 | #include <asm/pSeries_reconfig.h> |
50 | #include <asm/pci-bridge.h> | 50 | #include <asm/pci-bridge.h> |
51 | #ifdef CONFIG_PPC64 | ||
52 | #include <asm/systemcfg.h> | ||
53 | #endif | ||
54 | 51 | ||
55 | #ifdef DEBUG | 52 | #ifdef DEBUG |
56 | #define DBG(fmt...) printk(KERN_ERR fmt) | 53 | #define DBG(fmt...) printk(KERN_ERR fmt) |
@@ -74,10 +71,6 @@ struct isa_reg_property { | |||
74 | typedef int interpret_func(struct device_node *, unsigned long *, | 71 | typedef int interpret_func(struct device_node *, unsigned long *, |
75 | int, int, int); | 72 | int, int, int); |
76 | 73 | ||
77 | extern struct rtas_t rtas; | ||
78 | extern struct lmb lmb; | ||
79 | extern unsigned long klimit; | ||
80 | |||
81 | static int __initdata dt_root_addr_cells; | 74 | static int __initdata dt_root_addr_cells; |
82 | static int __initdata dt_root_size_cells; | 75 | static int __initdata dt_root_size_cells; |
83 | 76 | ||
@@ -391,7 +384,7 @@ static int __devinit finish_node_interrupts(struct device_node *np, | |||
391 | 384 | ||
392 | #ifdef CONFIG_PPC64 | 385 | #ifdef CONFIG_PPC64 |
393 | /* We offset irq numbers for the u3 MPIC by 128 in PowerMac */ | 386 | /* We offset irq numbers for the u3 MPIC by 128 in PowerMac */ |
394 | if (systemcfg->platform == PLATFORM_POWERMAC && ic && ic->parent) { | 387 | if (_machine == PLATFORM_POWERMAC && ic && ic->parent) { |
395 | char *name = get_property(ic->parent, "name", NULL); | 388 | char *name = get_property(ic->parent, "name", NULL); |
396 | if (name && !strcmp(name, "u3")) | 389 | if (name && !strcmp(name, "u3")) |
397 | np->intrs[intrcount].line += 128; | 390 | np->intrs[intrcount].line += 128; |
@@ -1087,9 +1080,9 @@ void __init unflatten_device_tree(void) | |||
1087 | static int __init early_init_dt_scan_cpus(unsigned long node, | 1080 | static int __init early_init_dt_scan_cpus(unsigned long node, |
1088 | const char *uname, int depth, void *data) | 1081 | const char *uname, int depth, void *data) |
1089 | { | 1082 | { |
1090 | char *type = of_get_flat_dt_prop(node, "device_type", NULL); | ||
1091 | u32 *prop; | 1083 | u32 *prop; |
1092 | unsigned long size = 0; | 1084 | unsigned long size; |
1085 | char *type = of_get_flat_dt_prop(node, "device_type", &size); | ||
1093 | 1086 | ||
1094 | /* We are scanning "cpu" nodes only */ | 1087 | /* We are scanning "cpu" nodes only */ |
1095 | if (type == NULL || strcmp(type, "cpu") != 0) | 1088 | if (type == NULL || strcmp(type, "cpu") != 0) |
@@ -1115,7 +1108,7 @@ static int __init early_init_dt_scan_cpus(unsigned long node, | |||
1115 | 1108 | ||
1116 | #ifdef CONFIG_ALTIVEC | 1109 | #ifdef CONFIG_ALTIVEC |
1117 | /* Check if we have a VMX and eventually update CPU features */ | 1110 | /* Check if we have a VMX and eventually update CPU features */ |
1118 | prop = (u32 *)of_get_flat_dt_prop(node, "ibm,vmx", &size); | 1111 | prop = (u32 *)of_get_flat_dt_prop(node, "ibm,vmx", NULL); |
1119 | if (prop && (*prop) > 0) { | 1112 | if (prop && (*prop) > 0) { |
1120 | cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC; | 1113 | cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC; |
1121 | cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC; | 1114 | cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC; |
@@ -1161,13 +1154,9 @@ static int __init early_init_dt_scan_chosen(unsigned long node, | |||
1161 | prop = (u32 *)of_get_flat_dt_prop(node, "linux,platform", NULL); | 1154 | prop = (u32 *)of_get_flat_dt_prop(node, "linux,platform", NULL); |
1162 | if (prop == NULL) | 1155 | if (prop == NULL) |
1163 | return 0; | 1156 | return 0; |
1164 | #ifdef CONFIG_PPC64 | ||
1165 | systemcfg->platform = *prop; | ||
1166 | #else | ||
1167 | #ifdef CONFIG_PPC_MULTIPLATFORM | 1157 | #ifdef CONFIG_PPC_MULTIPLATFORM |
1168 | _machine = *prop; | 1158 | _machine = *prop; |
1169 | #endif | 1159 | #endif |
1170 | #endif | ||
1171 | 1160 | ||
1172 | #ifdef CONFIG_PPC64 | 1161 | #ifdef CONFIG_PPC64 |
1173 | /* check if iommu is forced on or off */ | 1162 | /* check if iommu is forced on or off */ |
@@ -1264,7 +1253,14 @@ static int __init early_init_dt_scan_memory(unsigned long node, | |||
1264 | unsigned long l; | 1253 | unsigned long l; |
1265 | 1254 | ||
1266 | /* We are scanning "memory" nodes only */ | 1255 | /* We are scanning "memory" nodes only */ |
1267 | if (type == NULL || strcmp(type, "memory") != 0) | 1256 | if (type == NULL) { |
1257 | /* | ||
1258 | * The longtrail doesn't have a device_type on the | ||
1259 | * /memory node, so look for the node called /memory@0. | ||
1260 | */ | ||
1261 | if (depth != 1 || strcmp(uname, "memory@0") != 0) | ||
1262 | return 0; | ||
1263 | } else if (strcmp(type, "memory") != 0) | ||
1268 | return 0; | 1264 | return 0; |
1269 | 1265 | ||
1270 | reg = (cell_t *)of_get_flat_dt_prop(node, "reg", &l); | 1266 | reg = (cell_t *)of_get_flat_dt_prop(node, "reg", &l); |
@@ -1339,9 +1335,6 @@ void __init early_init_devtree(void *params) | |||
1339 | of_scan_flat_dt(early_init_dt_scan_memory, NULL); | 1335 | of_scan_flat_dt(early_init_dt_scan_memory, NULL); |
1340 | lmb_enforce_memory_limit(memory_limit); | 1336 | lmb_enforce_memory_limit(memory_limit); |
1341 | lmb_analyze(); | 1337 | lmb_analyze(); |
1342 | #ifdef CONFIG_PPC64 | ||
1343 | systemcfg->physicalMemorySize = lmb_phys_mem_size(); | ||
1344 | #endif | ||
1345 | lmb_reserve(0, __pa(klimit)); | 1338 | lmb_reserve(0, __pa(klimit)); |
1346 | 1339 | ||
1347 | DBG("Phys. mem: %lx\n", lmb_phys_mem_size()); | 1340 | DBG("Phys. mem: %lx\n", lmb_phys_mem_size()); |
@@ -1908,7 +1901,7 @@ static int of_finish_dynamic_node(struct device_node *node, | |||
1908 | /* We don't support that function on PowerMac, at least | 1901 | /* We don't support that function on PowerMac, at least |
1909 | * not yet | 1902 | * not yet |
1910 | */ | 1903 | */ |
1911 | if (systemcfg->platform == PLATFORM_POWERMAC) | 1904 | if (_machine == PLATFORM_POWERMAC) |
1912 | return -ENODEV; | 1905 | return -ENODEV; |
1913 | 1906 | ||
1914 | /* fix up new node's linux_phandle field */ | 1907 | /* fix up new node's linux_phandle field */ |
@@ -1992,9 +1985,11 @@ int prom_add_property(struct device_node* np, struct property* prop) | |||
1992 | *next = prop; | 1985 | *next = prop; |
1993 | write_unlock(&devtree_lock); | 1986 | write_unlock(&devtree_lock); |
1994 | 1987 | ||
1988 | #ifdef CONFIG_PROC_DEVICETREE | ||
1995 | /* try to add to proc as well if it was initialized */ | 1989 | /* try to add to proc as well if it was initialized */ |
1996 | if (np->pde) | 1990 | if (np->pde) |
1997 | proc_device_tree_add_prop(np->pde, prop); | 1991 | proc_device_tree_add_prop(np->pde, prop); |
1992 | #endif /* CONFIG_PROC_DEVICETREE */ | ||
1998 | 1993 | ||
1999 | return 0; | 1994 | return 0; |
2000 | } | 1995 | } |
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index 6dc33d19fc2a..4ce0105c308e 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c | |||
@@ -94,11 +94,17 @@ extern const struct linux_logo logo_linux_clut224; | |||
94 | #ifdef CONFIG_PPC64 | 94 | #ifdef CONFIG_PPC64 |
95 | #define RELOC(x) (*PTRRELOC(&(x))) | 95 | #define RELOC(x) (*PTRRELOC(&(x))) |
96 | #define ADDR(x) (u32) add_reloc_offset((unsigned long)(x)) | 96 | #define ADDR(x) (u32) add_reloc_offset((unsigned long)(x)) |
97 | #define OF_WORKAROUNDS 0 | ||
97 | #else | 98 | #else |
98 | #define RELOC(x) (x) | 99 | #define RELOC(x) (x) |
99 | #define ADDR(x) (u32) (x) | 100 | #define ADDR(x) (u32) (x) |
101 | #define OF_WORKAROUNDS of_workarounds | ||
102 | int of_workarounds; | ||
100 | #endif | 103 | #endif |
101 | 104 | ||
105 | #define OF_WA_CLAIM 1 /* do phys/virt claim separately, then map */ | ||
106 | #define OF_WA_LONGTRAIL 2 /* work around longtrail bugs */ | ||
107 | |||
102 | #define PROM_BUG() do { \ | 108 | #define PROM_BUG() do { \ |
103 | prom_printf("kernel BUG at %s line 0x%x!\n", \ | 109 | prom_printf("kernel BUG at %s line 0x%x!\n", \ |
104 | RELOC(__FILE__), __LINE__); \ | 110 | RELOC(__FILE__), __LINE__); \ |
@@ -111,11 +117,6 @@ extern const struct linux_logo logo_linux_clut224; | |||
111 | #define prom_debug(x...) | 117 | #define prom_debug(x...) |
112 | #endif | 118 | #endif |
113 | 119 | ||
114 | #ifdef CONFIG_PPC32 | ||
115 | #define PLATFORM_POWERMAC _MACH_Pmac | ||
116 | #define PLATFORM_CHRP _MACH_chrp | ||
117 | #endif | ||
118 | |||
119 | 120 | ||
120 | typedef u32 prom_arg_t; | 121 | typedef u32 prom_arg_t; |
121 | 122 | ||
@@ -128,10 +129,11 @@ struct prom_args { | |||
128 | 129 | ||
129 | struct prom_t { | 130 | struct prom_t { |
130 | ihandle root; | 131 | ihandle root; |
131 | ihandle chosen; | 132 | phandle chosen; |
132 | int cpu; | 133 | int cpu; |
133 | ihandle stdout; | 134 | ihandle stdout; |
134 | ihandle mmumap; | 135 | ihandle mmumap; |
136 | ihandle memory; | ||
135 | }; | 137 | }; |
136 | 138 | ||
137 | struct mem_map_entry { | 139 | struct mem_map_entry { |
@@ -360,16 +362,36 @@ static void __init prom_printf(const char *format, ...) | |||
360 | static unsigned int __init prom_claim(unsigned long virt, unsigned long size, | 362 | static unsigned int __init prom_claim(unsigned long virt, unsigned long size, |
361 | unsigned long align) | 363 | unsigned long align) |
362 | { | 364 | { |
363 | int ret; | ||
364 | struct prom_t *_prom = &RELOC(prom); | 365 | struct prom_t *_prom = &RELOC(prom); |
365 | 366 | ||
366 | ret = call_prom("claim", 3, 1, (prom_arg_t)virt, (prom_arg_t)size, | 367 | if (align == 0 && (OF_WORKAROUNDS & OF_WA_CLAIM)) { |
367 | (prom_arg_t)align); | 368 | /* |
368 | if (ret != -1 && _prom->mmumap != 0) | 369 | * Old OF requires we claim physical and virtual separately |
369 | /* old pmacs need us to map as well */ | 370 | * and then map explicitly (assuming virtual mode) |
371 | */ | ||
372 | int ret; | ||
373 | prom_arg_t result; | ||
374 | |||
375 | ret = call_prom_ret("call-method", 5, 2, &result, | ||
376 | ADDR("claim"), _prom->memory, | ||
377 | align, size, virt); | ||
378 | if (ret != 0 || result == -1) | ||
379 | return -1; | ||
380 | ret = call_prom_ret("call-method", 5, 2, &result, | ||
381 | ADDR("claim"), _prom->mmumap, | ||
382 | align, size, virt); | ||
383 | if (ret != 0) { | ||
384 | call_prom("call-method", 4, 1, ADDR("release"), | ||
385 | _prom->memory, size, virt); | ||
386 | return -1; | ||
387 | } | ||
388 | /* the 0x12 is M (coherence) + PP == read/write */ | ||
370 | call_prom("call-method", 6, 1, | 389 | call_prom("call-method", 6, 1, |
371 | ADDR("map"), _prom->mmumap, 0, size, virt, virt); | 390 | ADDR("map"), _prom->mmumap, 0x12, size, virt, virt); |
372 | return ret; | 391 | return virt; |
392 | } | ||
393 | return call_prom("claim", 3, 1, (prom_arg_t)virt, (prom_arg_t)size, | ||
394 | (prom_arg_t)align); | ||
373 | } | 395 | } |
374 | 396 | ||
375 | static void __init __attribute__((noreturn)) prom_panic(const char *reason) | 397 | static void __init __attribute__((noreturn)) prom_panic(const char *reason) |
@@ -415,11 +437,52 @@ static int inline prom_getproplen(phandle node, const char *pname) | |||
415 | return call_prom("getproplen", 2, 1, node, ADDR(pname)); | 437 | return call_prom("getproplen", 2, 1, node, ADDR(pname)); |
416 | } | 438 | } |
417 | 439 | ||
418 | static int inline prom_setprop(phandle node, const char *pname, | 440 | static void add_string(char **str, const char *q) |
419 | void *value, size_t valuelen) | ||
420 | { | 441 | { |
421 | return call_prom("setprop", 4, 1, node, ADDR(pname), | 442 | char *p = *str; |
422 | (u32)(unsigned long) value, (u32) valuelen); | 443 | |
444 | while (*q) | ||
445 | *p++ = *q++; | ||
446 | *p++ = ' '; | ||
447 | *str = p; | ||
448 | } | ||
449 | |||
450 | static char *tohex(unsigned int x) | ||
451 | { | ||
452 | static char digits[] = "0123456789abcdef"; | ||
453 | static char result[9]; | ||
454 | int i; | ||
455 | |||
456 | result[8] = 0; | ||
457 | i = 8; | ||
458 | do { | ||
459 | --i; | ||
460 | result[i] = digits[x & 0xf]; | ||
461 | x >>= 4; | ||
462 | } while (x != 0 && i > 0); | ||
463 | return &result[i]; | ||
464 | } | ||
465 | |||
466 | static int __init prom_setprop(phandle node, const char *nodename, | ||
467 | const char *pname, void *value, size_t valuelen) | ||
468 | { | ||
469 | char cmd[256], *p; | ||
470 | |||
471 | if (!(OF_WORKAROUNDS & OF_WA_LONGTRAIL)) | ||
472 | return call_prom("setprop", 4, 1, node, ADDR(pname), | ||
473 | (u32)(unsigned long) value, (u32) valuelen); | ||
474 | |||
475 | /* gah... setprop doesn't work on longtrail, have to use interpret */ | ||
476 | p = cmd; | ||
477 | add_string(&p, "dev"); | ||
478 | add_string(&p, nodename); | ||
479 | add_string(&p, tohex((u32)(unsigned long) value)); | ||
480 | add_string(&p, tohex(valuelen)); | ||
481 | add_string(&p, tohex(ADDR(pname))); | ||
482 | add_string(&p, tohex(strlen(RELOC(pname)))); | ||
483 | add_string(&p, "property"); | ||
484 | *p = 0; | ||
485 | return call_prom("interpret", 1, 1, (u32)(unsigned long) cmd); | ||
423 | } | 486 | } |
424 | 487 | ||
425 | /* We can't use the standard versions because of RELOC headaches. */ | 488 | /* We can't use the standard versions because of RELOC headaches. */ |
@@ -980,7 +1043,7 @@ static void __init prom_instantiate_rtas(void) | |||
980 | 1043 | ||
981 | rtas_inst = call_prom("open", 1, 1, ADDR("/rtas")); | 1044 | rtas_inst = call_prom("open", 1, 1, ADDR("/rtas")); |
982 | if (!IHANDLE_VALID(rtas_inst)) { | 1045 | if (!IHANDLE_VALID(rtas_inst)) { |
983 | prom_printf("opening rtas package failed"); | 1046 | prom_printf("opening rtas package failed (%x)\n", rtas_inst); |
984 | return; | 1047 | return; |
985 | } | 1048 | } |
986 | 1049 | ||
@@ -988,7 +1051,7 @@ static void __init prom_instantiate_rtas(void) | |||
988 | 1051 | ||
989 | if (call_prom_ret("call-method", 3, 2, &entry, | 1052 | if (call_prom_ret("call-method", 3, 2, &entry, |
990 | ADDR("instantiate-rtas"), | 1053 | ADDR("instantiate-rtas"), |
991 | rtas_inst, base) == PROM_ERROR | 1054 | rtas_inst, base) != 0 |
992 | || entry == 0) { | 1055 | || entry == 0) { |
993 | prom_printf(" failed\n"); | 1056 | prom_printf(" failed\n"); |
994 | return; | 1057 | return; |
@@ -997,8 +1060,10 @@ static void __init prom_instantiate_rtas(void) | |||
997 | 1060 | ||
998 | reserve_mem(base, size); | 1061 | reserve_mem(base, size); |
999 | 1062 | ||
1000 | prom_setprop(rtas_node, "linux,rtas-base", &base, sizeof(base)); | 1063 | prom_setprop(rtas_node, "/rtas", "linux,rtas-base", |
1001 | prom_setprop(rtas_node, "linux,rtas-entry", &entry, sizeof(entry)); | 1064 | &base, sizeof(base)); |
1065 | prom_setprop(rtas_node, "/rtas", "linux,rtas-entry", | ||
1066 | &entry, sizeof(entry)); | ||
1002 | 1067 | ||
1003 | prom_debug("rtas base = 0x%x\n", base); | 1068 | prom_debug("rtas base = 0x%x\n", base); |
1004 | prom_debug("rtas entry = 0x%x\n", entry); | 1069 | prom_debug("rtas entry = 0x%x\n", entry); |
@@ -1089,10 +1154,6 @@ static void __init prom_initialize_tce_table(void) | |||
1089 | if (base < local_alloc_bottom) | 1154 | if (base < local_alloc_bottom) |
1090 | local_alloc_bottom = base; | 1155 | local_alloc_bottom = base; |
1091 | 1156 | ||
1092 | /* Save away the TCE table attributes for later use. */ | ||
1093 | prom_setprop(node, "linux,tce-base", &base, sizeof(base)); | ||
1094 | prom_setprop(node, "linux,tce-size", &minsize, sizeof(minsize)); | ||
1095 | |||
1096 | /* It seems OF doesn't null-terminate the path :-( */ | 1157 | /* It seems OF doesn't null-terminate the path :-( */ |
1097 | memset(path, 0, sizeof(path)); | 1158 | memset(path, 0, sizeof(path)); |
1098 | /* Call OF to setup the TCE hardware */ | 1159 | /* Call OF to setup the TCE hardware */ |
@@ -1101,6 +1162,10 @@ static void __init prom_initialize_tce_table(void) | |||
1101 | prom_printf("package-to-path failed\n"); | 1162 | prom_printf("package-to-path failed\n"); |
1102 | } | 1163 | } |
1103 | 1164 | ||
1165 | /* Save away the TCE table attributes for later use. */ | ||
1166 | prom_setprop(node, path, "linux,tce-base", &base, sizeof(base)); | ||
1167 | prom_setprop(node, path, "linux,tce-size", &minsize, sizeof(minsize)); | ||
1168 | |||
1104 | prom_debug("TCE table: %s\n", path); | 1169 | prom_debug("TCE table: %s\n", path); |
1105 | prom_debug("\tnode = 0x%x\n", node); | 1170 | prom_debug("\tnode = 0x%x\n", node); |
1106 | prom_debug("\tbase = 0x%x\n", base); | 1171 | prom_debug("\tbase = 0x%x\n", base); |
@@ -1342,6 +1407,7 @@ static void __init prom_init_client_services(unsigned long pp) | |||
1342 | /* | 1407 | /* |
1343 | * For really old powermacs, we need to map things we claim. | 1408 | * For really old powermacs, we need to map things we claim. |
1344 | * For that, we need the ihandle of the mmu. | 1409 | * For that, we need the ihandle of the mmu. |
1410 | * Also, on the longtrail, we need to work around other bugs. | ||
1345 | */ | 1411 | */ |
1346 | static void __init prom_find_mmu(void) | 1412 | static void __init prom_find_mmu(void) |
1347 | { | 1413 | { |
@@ -1355,12 +1421,19 @@ static void __init prom_find_mmu(void) | |||
1355 | if (prom_getprop(oprom, "model", version, sizeof(version)) <= 0) | 1421 | if (prom_getprop(oprom, "model", version, sizeof(version)) <= 0) |
1356 | return; | 1422 | return; |
1357 | version[sizeof(version) - 1] = 0; | 1423 | version[sizeof(version) - 1] = 0; |
1358 | prom_printf("OF version is '%s'\n", version); | ||
1359 | /* XXX might need to add other versions here */ | 1424 | /* XXX might need to add other versions here */ |
1360 | if (strcmp(version, "Open Firmware, 1.0.5") != 0) | 1425 | if (strcmp(version, "Open Firmware, 1.0.5") == 0) |
1426 | of_workarounds = OF_WA_CLAIM; | ||
1427 | else if (strncmp(version, "FirmWorks,3.", 12) == 0) { | ||
1428 | of_workarounds = OF_WA_CLAIM | OF_WA_LONGTRAIL; | ||
1429 | call_prom("interpret", 1, 1, "dev /memory 0 to allow-reclaim"); | ||
1430 | } else | ||
1361 | return; | 1431 | return; |
1432 | _prom->memory = call_prom("open", 1, 1, ADDR("/memory")); | ||
1362 | prom_getprop(_prom->chosen, "mmu", &_prom->mmumap, | 1433 | prom_getprop(_prom->chosen, "mmu", &_prom->mmumap, |
1363 | sizeof(_prom->mmumap)); | 1434 | sizeof(_prom->mmumap)); |
1435 | if (!IHANDLE_VALID(_prom->memory) || !IHANDLE_VALID(_prom->mmumap)) | ||
1436 | of_workarounds &= ~OF_WA_CLAIM; /* hmmm */ | ||
1364 | } | 1437 | } |
1365 | #else | 1438 | #else |
1366 | #define prom_find_mmu() | 1439 | #define prom_find_mmu() |
@@ -1382,16 +1455,17 @@ static void __init prom_init_stdout(void) | |||
1382 | memset(path, 0, 256); | 1455 | memset(path, 0, 256); |
1383 | call_prom("instance-to-path", 3, 1, _prom->stdout, path, 255); | 1456 | call_prom("instance-to-path", 3, 1, _prom->stdout, path, 255); |
1384 | val = call_prom("instance-to-package", 1, 1, _prom->stdout); | 1457 | val = call_prom("instance-to-package", 1, 1, _prom->stdout); |
1385 | prom_setprop(_prom->chosen, "linux,stdout-package", &val, sizeof(val)); | 1458 | prom_setprop(_prom->chosen, "/chosen", "linux,stdout-package", |
1459 | &val, sizeof(val)); | ||
1386 | prom_printf("OF stdout device is: %s\n", RELOC(of_stdout_device)); | 1460 | prom_printf("OF stdout device is: %s\n", RELOC(of_stdout_device)); |
1387 | prom_setprop(_prom->chosen, "linux,stdout-path", | 1461 | prom_setprop(_prom->chosen, "/chosen", "linux,stdout-path", |
1388 | RELOC(of_stdout_device), strlen(RELOC(of_stdout_device))+1); | 1462 | path, strlen(path) + 1); |
1389 | 1463 | ||
1390 | /* If it's a display, note it */ | 1464 | /* If it's a display, note it */ |
1391 | memset(type, 0, sizeof(type)); | 1465 | memset(type, 0, sizeof(type)); |
1392 | prom_getprop(val, "device_type", type, sizeof(type)); | 1466 | prom_getprop(val, "device_type", type, sizeof(type)); |
1393 | if (strcmp(type, RELOC("display")) == 0) | 1467 | if (strcmp(type, RELOC("display")) == 0) |
1394 | prom_setprop(val, "linux,boot-display", NULL, 0); | 1468 | prom_setprop(val, path, "linux,boot-display", NULL, 0); |
1395 | } | 1469 | } |
1396 | 1470 | ||
1397 | static void __init prom_close_stdin(void) | 1471 | static void __init prom_close_stdin(void) |
@@ -1514,7 +1588,7 @@ static void __init prom_check_displays(void) | |||
1514 | 1588 | ||
1515 | /* Success */ | 1589 | /* Success */ |
1516 | prom_printf("done\n"); | 1590 | prom_printf("done\n"); |
1517 | prom_setprop(node, "linux,opened", NULL, 0); | 1591 | prom_setprop(node, path, "linux,opened", NULL, 0); |
1518 | 1592 | ||
1519 | /* Setup a usable color table when the appropriate | 1593 | /* Setup a usable color table when the appropriate |
1520 | * method is available. Should update this to set-colors */ | 1594 | * method is available. Should update this to set-colors */ |
@@ -1884,9 +1958,11 @@ static void __init fixup_device_tree(void) | |||
1884 | /* interrupt on this revision of u3 is number 0 and level */ | 1958 | /* interrupt on this revision of u3 is number 0 and level */ |
1885 | interrupts[0] = 0; | 1959 | interrupts[0] = 0; |
1886 | interrupts[1] = 1; | 1960 | interrupts[1] = 1; |
1887 | prom_setprop(i2c, "interrupts", &interrupts, sizeof(interrupts)); | 1961 | prom_setprop(i2c, "/u3@0,f8000000/i2c@f8001000", "interrupts", |
1962 | &interrupts, sizeof(interrupts)); | ||
1888 | parent = (u32)mpic; | 1963 | parent = (u32)mpic; |
1889 | prom_setprop(i2c, "interrupt-parent", &parent, sizeof(parent)); | 1964 | prom_setprop(i2c, "/u3@0,f8000000/i2c@f8001000", "interrupt-parent", |
1965 | &parent, sizeof(parent)); | ||
1890 | #endif | 1966 | #endif |
1891 | } | 1967 | } |
1892 | 1968 | ||
@@ -1922,11 +1998,11 @@ static void __init prom_check_initrd(unsigned long r3, unsigned long r4) | |||
1922 | RELOC(prom_initrd_end) = RELOC(prom_initrd_start) + r4; | 1998 | RELOC(prom_initrd_end) = RELOC(prom_initrd_start) + r4; |
1923 | 1999 | ||
1924 | val = RELOC(prom_initrd_start); | 2000 | val = RELOC(prom_initrd_start); |
1925 | prom_setprop(_prom->chosen, "linux,initrd-start", &val, | 2001 | prom_setprop(_prom->chosen, "/chosen", "linux,initrd-start", |
1926 | sizeof(val)); | 2002 | &val, sizeof(val)); |
1927 | val = RELOC(prom_initrd_end); | 2003 | val = RELOC(prom_initrd_end); |
1928 | prom_setprop(_prom->chosen, "linux,initrd-end", &val, | 2004 | prom_setprop(_prom->chosen, "/chosen", "linux,initrd-end", |
1929 | sizeof(val)); | 2005 | &val, sizeof(val)); |
1930 | 2006 | ||
1931 | reserve_mem(RELOC(prom_initrd_start), | 2007 | reserve_mem(RELOC(prom_initrd_start), |
1932 | RELOC(prom_initrd_end) - RELOC(prom_initrd_start)); | 2008 | RELOC(prom_initrd_end) - RELOC(prom_initrd_start)); |
@@ -1969,14 +2045,15 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, | |||
1969 | prom_init_client_services(pp); | 2045 | prom_init_client_services(pp); |
1970 | 2046 | ||
1971 | /* | 2047 | /* |
1972 | * Init prom stdout device | 2048 | * See if this OF is old enough that we need to do explicit maps |
2049 | * and other workarounds | ||
1973 | */ | 2050 | */ |
1974 | prom_init_stdout(); | 2051 | prom_find_mmu(); |
1975 | 2052 | ||
1976 | /* | 2053 | /* |
1977 | * See if this OF is old enough that we need to do explicit maps | 2054 | * Init prom stdout device |
1978 | */ | 2055 | */ |
1979 | prom_find_mmu(); | 2056 | prom_init_stdout(); |
1980 | 2057 | ||
1981 | /* | 2058 | /* |
1982 | * Check for an initrd | 2059 | * Check for an initrd |
@@ -1989,14 +2066,15 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, | |||
1989 | */ | 2066 | */ |
1990 | RELOC(of_platform) = prom_find_machine_type(); | 2067 | RELOC(of_platform) = prom_find_machine_type(); |
1991 | getprop_rval = RELOC(of_platform); | 2068 | getprop_rval = RELOC(of_platform); |
1992 | prom_setprop(_prom->chosen, "linux,platform", | 2069 | prom_setprop(_prom->chosen, "/chosen", "linux,platform", |
1993 | &getprop_rval, sizeof(getprop_rval)); | 2070 | &getprop_rval, sizeof(getprop_rval)); |
1994 | 2071 | ||
1995 | #ifdef CONFIG_PPC_PSERIES | 2072 | #ifdef CONFIG_PPC_PSERIES |
1996 | /* | 2073 | /* |
1997 | * On pSeries, inform the firmware about our capabilities | 2074 | * On pSeries, inform the firmware about our capabilities |
1998 | */ | 2075 | */ |
1999 | if (RELOC(of_platform) & PLATFORM_PSERIES) | 2076 | if (RELOC(of_platform) == PLATFORM_PSERIES || |
2077 | RELOC(of_platform) == PLATFORM_PSERIES_LPAR) | ||
2000 | prom_send_capabilities(); | 2078 | prom_send_capabilities(); |
2001 | #endif | 2079 | #endif |
2002 | 2080 | ||
@@ -2050,21 +2128,23 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, | |||
2050 | * Fill in some infos for use by the kernel later on | 2128 | * Fill in some infos for use by the kernel later on |
2051 | */ | 2129 | */ |
2052 | if (RELOC(prom_memory_limit)) | 2130 | if (RELOC(prom_memory_limit)) |
2053 | prom_setprop(_prom->chosen, "linux,memory-limit", | 2131 | prom_setprop(_prom->chosen, "/chosen", "linux,memory-limit", |
2054 | &RELOC(prom_memory_limit), | 2132 | &RELOC(prom_memory_limit), |
2055 | sizeof(prom_memory_limit)); | 2133 | sizeof(prom_memory_limit)); |
2056 | #ifdef CONFIG_PPC64 | 2134 | #ifdef CONFIG_PPC64 |
2057 | if (RELOC(ppc64_iommu_off)) | 2135 | if (RELOC(ppc64_iommu_off)) |
2058 | prom_setprop(_prom->chosen, "linux,iommu-off", NULL, 0); | 2136 | prom_setprop(_prom->chosen, "/chosen", "linux,iommu-off", |
2137 | NULL, 0); | ||
2059 | 2138 | ||
2060 | if (RELOC(iommu_force_on)) | 2139 | if (RELOC(iommu_force_on)) |
2061 | prom_setprop(_prom->chosen, "linux,iommu-force-on", NULL, 0); | 2140 | prom_setprop(_prom->chosen, "/chosen", "linux,iommu-force-on", |
2141 | NULL, 0); | ||
2062 | 2142 | ||
2063 | if (RELOC(prom_tce_alloc_start)) { | 2143 | if (RELOC(prom_tce_alloc_start)) { |
2064 | prom_setprop(_prom->chosen, "linux,tce-alloc-start", | 2144 | prom_setprop(_prom->chosen, "/chosen", "linux,tce-alloc-start", |
2065 | &RELOC(prom_tce_alloc_start), | 2145 | &RELOC(prom_tce_alloc_start), |
2066 | sizeof(prom_tce_alloc_start)); | 2146 | sizeof(prom_tce_alloc_start)); |
2067 | prom_setprop(_prom->chosen, "linux,tce-alloc-end", | 2147 | prom_setprop(_prom->chosen, "/chosen", "linux,tce-alloc-end", |
2068 | &RELOC(prom_tce_alloc_end), | 2148 | &RELOC(prom_tce_alloc_end), |
2069 | sizeof(prom_tce_alloc_end)); | 2149 | sizeof(prom_tce_alloc_end)); |
2070 | } | 2150 | } |
@@ -2081,8 +2161,13 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, | |||
2081 | prom_printf("copying OF device tree ...\n"); | 2161 | prom_printf("copying OF device tree ...\n"); |
2082 | flatten_device_tree(); | 2162 | flatten_device_tree(); |
2083 | 2163 | ||
2084 | /* in case stdin is USB and still active on IBM machines... */ | 2164 | /* |
2085 | prom_close_stdin(); | 2165 | * in case stdin is USB and still active on IBM machines... |
2166 | * Unfortunately quiesce crashes on some powermacs if we have | ||
2167 | * closed stdin already (in particular the powerbook 101). | ||
2168 | */ | ||
2169 | if (RELOC(of_platform) != PLATFORM_POWERMAC) | ||
2170 | prom_close_stdin(); | ||
2086 | 2171 | ||
2087 | /* | 2172 | /* |
2088 | * Call OF "quiesce" method to shut down pending DMA's from | 2173 | * Call OF "quiesce" method to shut down pending DMA's from |
diff --git a/arch/powerpc/kernel/rtas-proc.c b/arch/powerpc/kernel/rtas-proc.c index 5bdd5b079d96..ae1a36449ccd 100644 --- a/arch/powerpc/kernel/rtas-proc.c +++ b/arch/powerpc/kernel/rtas-proc.c | |||
@@ -259,7 +259,7 @@ static int __init proc_rtas_init(void) | |||
259 | { | 259 | { |
260 | struct proc_dir_entry *entry; | 260 | struct proc_dir_entry *entry; |
261 | 261 | ||
262 | if (!(systemcfg->platform & PLATFORM_PSERIES)) | 262 | if (_machine != PLATFORM_PSERIES && _machine != PLATFORM_PSERIES_LPAR) |
263 | return 1; | 263 | return 1; |
264 | 264 | ||
265 | rtas_node = of_find_node_by_name(NULL, "rtas"); | 265 | rtas_node = of_find_node_by_name(NULL, "rtas"); |
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 9d4e07f6f1ec..4283fa33f784 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c | |||
@@ -29,9 +29,6 @@ | |||
29 | #include <asm/delay.h> | 29 | #include <asm/delay.h> |
30 | #include <asm/uaccess.h> | 30 | #include <asm/uaccess.h> |
31 | #include <asm/lmb.h> | 31 | #include <asm/lmb.h> |
32 | #ifdef CONFIG_PPC64 | ||
33 | #include <asm/systemcfg.h> | ||
34 | #endif | ||
35 | 32 | ||
36 | struct rtas_t rtas = { | 33 | struct rtas_t rtas = { |
37 | .lock = SPIN_LOCK_UNLOCKED | 34 | .lock = SPIN_LOCK_UNLOCKED |
@@ -671,7 +668,7 @@ void __init rtas_initialize(void) | |||
671 | * the stop-self token if any | 668 | * the stop-self token if any |
672 | */ | 669 | */ |
673 | #ifdef CONFIG_PPC64 | 670 | #ifdef CONFIG_PPC64 |
674 | if (systemcfg->platform == PLATFORM_PSERIES_LPAR) | 671 | if (_machine == PLATFORM_PSERIES_LPAR) |
675 | rtas_region = min(lmb.rmo_size, RTAS_INSTANTIATE_MAX); | 672 | rtas_region = min(lmb.rmo_size, RTAS_INSTANTIATE_MAX); |
676 | #endif | 673 | #endif |
677 | rtas_rmo_buf = lmb_alloc_base(RTAS_RMOBUF_MAX, PAGE_SIZE, rtas_region); | 674 | rtas_rmo_buf = lmb_alloc_base(RTAS_RMOBUF_MAX, PAGE_SIZE, rtas_region); |
diff --git a/arch/ppc64/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c index 3c3f19192fcc..0e5a8e116653 100644 --- a/arch/ppc64/kernel/rtas_pci.c +++ b/arch/powerpc/kernel/rtas_pci.c | |||
@@ -5,19 +5,19 @@ | |||
5 | * Copyright (C) 2003 Anton Blanchard <anton@au.ibm.com>, IBM | 5 | * Copyright (C) 2003 Anton Blanchard <anton@au.ibm.com>, IBM |
6 | * | 6 | * |
7 | * RTAS specific routines for PCI. | 7 | * RTAS specific routines for PCI. |
8 | * | 8 | * |
9 | * Based on code from pci.c, chrp_pci.c and pSeries_pci.c | 9 | * Based on code from pci.c, chrp_pci.c and pSeries_pci.c |
10 | * | 10 | * |
11 | * This program is free software; you can redistribute it and/or modify | 11 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of the GNU General Public License as published by | 12 | * it under the terms of the GNU General Public License as published by |
13 | * the Free Software Foundation; either version 2 of the License, or | 13 | * the Free Software Foundation; either version 2 of the License, or |
14 | * (at your option) any later version. | 14 | * (at your option) any later version. |
15 | * | 15 | * |
16 | * This program is distributed in the hope that it will be useful, | 16 | * This program is distributed in the hope that it will be useful, |
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
19 | * GNU General Public License for more details. | 19 | * GNU General Public License for more details. |
20 | * | 20 | * |
21 | * You should have received a copy of the GNU General Public License | 21 | * You should have received a copy of the GNU General Public License |
22 | * along with this program; if not, write to the Free Software | 22 | * along with this program; if not, write to the Free Software |
23 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 23 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
@@ -47,7 +47,7 @@ static int write_pci_config; | |||
47 | static int ibm_read_pci_config; | 47 | static int ibm_read_pci_config; |
48 | static int ibm_write_pci_config; | 48 | static int ibm_write_pci_config; |
49 | 49 | ||
50 | static int config_access_valid(struct pci_dn *dn, int where) | 50 | static inline int config_access_valid(struct pci_dn *dn, int where) |
51 | { | 51 | { |
52 | if (where < 256) | 52 | if (where < 256) |
53 | return 1; | 53 | return 1; |
@@ -72,16 +72,14 @@ static int of_device_available(struct device_node * dn) | |||
72 | return 0; | 72 | return 0; |
73 | } | 73 | } |
74 | 74 | ||
75 | static int rtas_read_config(struct device_node *dn, int where, int size, u32 *val) | 75 | static int rtas_read_config(struct pci_dn *pdn, int where, int size, u32 *val) |
76 | { | 76 | { |
77 | int returnval = -1; | 77 | int returnval = -1; |
78 | unsigned long buid, addr; | 78 | unsigned long buid, addr; |
79 | int ret; | 79 | int ret; |
80 | struct pci_dn *pdn; | ||
81 | 80 | ||
82 | if (!dn || !dn->data) | 81 | if (!pdn) |
83 | return PCIBIOS_DEVICE_NOT_FOUND; | 82 | return PCIBIOS_DEVICE_NOT_FOUND; |
84 | pdn = dn->data; | ||
85 | if (!config_access_valid(pdn, where)) | 83 | if (!config_access_valid(pdn, where)) |
86 | return PCIBIOS_BAD_REGISTER_NUMBER; | 84 | return PCIBIOS_BAD_REGISTER_NUMBER; |
87 | 85 | ||
@@ -90,7 +88,7 @@ static int rtas_read_config(struct device_node *dn, int where, int size, u32 *va | |||
90 | buid = pdn->phb->buid; | 88 | buid = pdn->phb->buid; |
91 | if (buid) { | 89 | if (buid) { |
92 | ret = rtas_call(ibm_read_pci_config, 4, 2, &returnval, | 90 | ret = rtas_call(ibm_read_pci_config, 4, 2, &returnval, |
93 | addr, buid >> 32, buid & 0xffffffff, size); | 91 | addr, BUID_HI(buid), BUID_LO(buid), size); |
94 | } else { | 92 | } else { |
95 | ret = rtas_call(read_pci_config, 2, 2, &returnval, addr, size); | 93 | ret = rtas_call(read_pci_config, 2, 2, &returnval, addr, size); |
96 | } | 94 | } |
@@ -100,7 +98,7 @@ static int rtas_read_config(struct device_node *dn, int where, int size, u32 *va | |||
100 | return PCIBIOS_DEVICE_NOT_FOUND; | 98 | return PCIBIOS_DEVICE_NOT_FOUND; |
101 | 99 | ||
102 | if (returnval == EEH_IO_ERROR_VALUE(size) && | 100 | if (returnval == EEH_IO_ERROR_VALUE(size) && |
103 | eeh_dn_check_failure (dn, NULL)) | 101 | eeh_dn_check_failure (pdn->node, NULL)) |
104 | return PCIBIOS_DEVICE_NOT_FOUND; | 102 | return PCIBIOS_DEVICE_NOT_FOUND; |
105 | 103 | ||
106 | return PCIBIOS_SUCCESSFUL; | 104 | return PCIBIOS_SUCCESSFUL; |
@@ -118,23 +116,23 @@ static int rtas_pci_read_config(struct pci_bus *bus, | |||
118 | busdn = bus->sysdata; /* must be a phb */ | 116 | busdn = bus->sysdata; /* must be a phb */ |
119 | 117 | ||
120 | /* Search only direct children of the bus */ | 118 | /* Search only direct children of the bus */ |
121 | for (dn = busdn->child; dn; dn = dn->sibling) | 119 | for (dn = busdn->child; dn; dn = dn->sibling) { |
122 | if (dn->data && PCI_DN(dn)->devfn == devfn | 120 | struct pci_dn *pdn = PCI_DN(dn); |
121 | if (pdn && pdn->devfn == devfn | ||
123 | && of_device_available(dn)) | 122 | && of_device_available(dn)) |
124 | return rtas_read_config(dn, where, size, val); | 123 | return rtas_read_config(pdn, where, size, val); |
124 | } | ||
125 | 125 | ||
126 | return PCIBIOS_DEVICE_NOT_FOUND; | 126 | return PCIBIOS_DEVICE_NOT_FOUND; |
127 | } | 127 | } |
128 | 128 | ||
129 | int rtas_write_config(struct device_node *dn, int where, int size, u32 val) | 129 | int rtas_write_config(struct pci_dn *pdn, int where, int size, u32 val) |
130 | { | 130 | { |
131 | unsigned long buid, addr; | 131 | unsigned long buid, addr; |
132 | int ret; | 132 | int ret; |
133 | struct pci_dn *pdn; | ||
134 | 133 | ||
135 | if (!dn || !dn->data) | 134 | if (!pdn) |
136 | return PCIBIOS_DEVICE_NOT_FOUND; | 135 | return PCIBIOS_DEVICE_NOT_FOUND; |
137 | pdn = dn->data; | ||
138 | if (!config_access_valid(pdn, where)) | 136 | if (!config_access_valid(pdn, where)) |
139 | return PCIBIOS_BAD_REGISTER_NUMBER; | 137 | return PCIBIOS_BAD_REGISTER_NUMBER; |
140 | 138 | ||
@@ -142,7 +140,8 @@ int rtas_write_config(struct device_node *dn, int where, int size, u32 val) | |||
142 | (pdn->devfn << 8) | (where & 0xff); | 140 | (pdn->devfn << 8) | (where & 0xff); |
143 | buid = pdn->phb->buid; | 141 | buid = pdn->phb->buid; |
144 | if (buid) { | 142 | if (buid) { |
145 | ret = rtas_call(ibm_write_pci_config, 5, 1, NULL, addr, buid >> 32, buid & 0xffffffff, size, (ulong) val); | 143 | ret = rtas_call(ibm_write_pci_config, 5, 1, NULL, addr, |
144 | BUID_HI(buid), BUID_LO(buid), size, (ulong) val); | ||
146 | } else { | 145 | } else { |
147 | ret = rtas_call(write_pci_config, 3, 1, NULL, addr, size, (ulong)val); | 146 | ret = rtas_call(write_pci_config, 3, 1, NULL, addr, size, (ulong)val); |
148 | } | 147 | } |
@@ -165,10 +164,12 @@ static int rtas_pci_write_config(struct pci_bus *bus, | |||
165 | busdn = bus->sysdata; /* must be a phb */ | 164 | busdn = bus->sysdata; /* must be a phb */ |
166 | 165 | ||
167 | /* Search only direct children of the bus */ | 166 | /* Search only direct children of the bus */ |
168 | for (dn = busdn->child; dn; dn = dn->sibling) | 167 | for (dn = busdn->child; dn; dn = dn->sibling) { |
169 | if (dn->data && PCI_DN(dn)->devfn == devfn | 168 | struct pci_dn *pdn = PCI_DN(dn); |
169 | if (pdn && pdn->devfn == devfn | ||
170 | && of_device_available(dn)) | 170 | && of_device_available(dn)) |
171 | return rtas_write_config(dn, where, size, val); | 171 | return rtas_write_config(pdn, where, size, val); |
172 | } | ||
172 | return PCIBIOS_DEVICE_NOT_FOUND; | 173 | return PCIBIOS_DEVICE_NOT_FOUND; |
173 | } | 174 | } |
174 | 175 | ||
@@ -221,7 +222,7 @@ static void python_countermeasures(struct device_node *dev, | |||
221 | /* Python's register file is 1 MB in size. */ | 222 | /* Python's register file is 1 MB in size. */ |
222 | chip_regs = ioremap(reg_struct.address & ~(0xfffffUL), 0x100000); | 223 | chip_regs = ioremap(reg_struct.address & ~(0xfffffUL), 0x100000); |
223 | 224 | ||
224 | /* | 225 | /* |
225 | * Firmware doesn't always clear this bit which is critical | 226 | * Firmware doesn't always clear this bit which is critical |
226 | * for good performance - Anton | 227 | * for good performance - Anton |
227 | */ | 228 | */ |
@@ -292,7 +293,7 @@ static int phb_set_bus_ranges(struct device_node *dev, | |||
292 | if (bus_range == NULL || len < 2 * sizeof(int)) { | 293 | if (bus_range == NULL || len < 2 * sizeof(int)) { |
293 | return 1; | 294 | return 1; |
294 | } | 295 | } |
295 | 296 | ||
296 | phb->first_busno = bus_range[0]; | 297 | phb->first_busno = bus_range[0]; |
297 | phb->last_busno = bus_range[1]; | 298 | phb->last_busno = bus_range[1]; |
298 | 299 | ||
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index e22856ecb5a0..bae4bff138f1 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <asm/io.h> | 33 | #include <asm/io.h> |
34 | #include <asm/prom.h> | 34 | #include <asm/prom.h> |
35 | #include <asm/processor.h> | 35 | #include <asm/processor.h> |
36 | #include <asm/systemcfg.h> | ||
36 | #include <asm/pgtable.h> | 37 | #include <asm/pgtable.h> |
37 | #include <asm/smp.h> | 38 | #include <asm/smp.h> |
38 | #include <asm/elf.h> | 39 | #include <asm/elf.h> |
@@ -51,6 +52,9 @@ | |||
51 | #include <asm/page.h> | 52 | #include <asm/page.h> |
52 | #include <asm/mmu.h> | 53 | #include <asm/mmu.h> |
53 | #include <asm/lmb.h> | 54 | #include <asm/lmb.h> |
55 | #include <asm/xmon.h> | ||
56 | |||
57 | #include "setup.h" | ||
54 | 58 | ||
55 | #undef DEBUG | 59 | #undef DEBUG |
56 | 60 | ||
@@ -60,6 +64,13 @@ | |||
60 | #define DBG(fmt...) | 64 | #define DBG(fmt...) |
61 | #endif | 65 | #endif |
62 | 66 | ||
67 | #ifdef CONFIG_PPC_MULTIPLATFORM | ||
68 | int _machine = 0; | ||
69 | EXPORT_SYMBOL(_machine); | ||
70 | #endif | ||
71 | |||
72 | unsigned long klimit = (unsigned long) _end; | ||
73 | |||
63 | /* | 74 | /* |
64 | * This still seems to be needed... -- paulus | 75 | * This still seems to be needed... -- paulus |
65 | */ | 76 | */ |
@@ -510,8 +521,8 @@ void __init smp_setup_cpu_maps(void) | |||
510 | * On pSeries LPAR, we need to know how many cpus | 521 | * On pSeries LPAR, we need to know how many cpus |
511 | * could possibly be added to this partition. | 522 | * could possibly be added to this partition. |
512 | */ | 523 | */ |
513 | if (systemcfg->platform == PLATFORM_PSERIES_LPAR && | 524 | if (_machine == PLATFORM_PSERIES_LPAR && |
514 | (dn = of_find_node_by_path("/rtas"))) { | 525 | (dn = of_find_node_by_path("/rtas"))) { |
515 | int num_addr_cell, num_size_cell, maxcpus; | 526 | int num_addr_cell, num_size_cell, maxcpus; |
516 | unsigned int *ireg; | 527 | unsigned int *ireg; |
517 | 528 | ||
@@ -555,7 +566,27 @@ void __init smp_setup_cpu_maps(void) | |||
555 | cpu_set(cpu ^ 0x1, cpu_sibling_map[cpu]); | 566 | cpu_set(cpu ^ 0x1, cpu_sibling_map[cpu]); |
556 | } | 567 | } |
557 | 568 | ||
558 | systemcfg->processorCount = num_present_cpus(); | 569 | _systemcfg->processorCount = num_present_cpus(); |
559 | #endif /* CONFIG_PPC64 */ | 570 | #endif /* CONFIG_PPC64 */ |
560 | } | 571 | } |
561 | #endif /* CONFIG_SMP */ | 572 | #endif /* CONFIG_SMP */ |
573 | |||
574 | #ifdef CONFIG_XMON | ||
575 | static int __init early_xmon(char *p) | ||
576 | { | ||
577 | /* ensure xmon is enabled */ | ||
578 | if (p) { | ||
579 | if (strncmp(p, "on", 2) == 0) | ||
580 | xmon_init(1); | ||
581 | if (strncmp(p, "off", 3) == 0) | ||
582 | xmon_init(0); | ||
583 | if (strncmp(p, "early", 5) != 0) | ||
584 | return 0; | ||
585 | } | ||
586 | xmon_init(1); | ||
587 | debugger(NULL); | ||
588 | |||
589 | return 0; | ||
590 | } | ||
591 | early_param("xmon", early_xmon); | ||
592 | #endif | ||
diff --git a/arch/powerpc/kernel/setup.h b/arch/powerpc/kernel/setup.h new file mode 100644 index 000000000000..2ebba755272e --- /dev/null +++ b/arch/powerpc/kernel/setup.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _POWERPC_KERNEL_SETUP_H | ||
2 | #define _POWERPC_KERNEL_SETUP_H | ||
3 | |||
4 | void check_for_initrd(void); | ||
5 | |||
6 | #endif /* _POWERPC_KERNEL_SETUP_H */ | ||
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index 3af2631e3fab..c98cfcc9cd9a 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c | |||
@@ -40,6 +40,8 @@ | |||
40 | #include <asm/xmon.h> | 40 | #include <asm/xmon.h> |
41 | #include <asm/time.h> | 41 | #include <asm/time.h> |
42 | 42 | ||
43 | #include "setup.h" | ||
44 | |||
43 | #define DBG(fmt...) | 45 | #define DBG(fmt...) |
44 | 46 | ||
45 | #if defined CONFIG_KGDB | 47 | #if defined CONFIG_KGDB |
@@ -70,8 +72,6 @@ unsigned int DMA_MODE_WRITE; | |||
70 | int have_of = 1; | 72 | int have_of = 1; |
71 | 73 | ||
72 | #ifdef CONFIG_PPC_MULTIPLATFORM | 74 | #ifdef CONFIG_PPC_MULTIPLATFORM |
73 | int _machine = 0; | ||
74 | |||
75 | extern void prep_init(void); | 75 | extern void prep_init(void); |
76 | extern void pmac_init(void); | 76 | extern void pmac_init(void); |
77 | extern void chrp_init(void); | 77 | extern void chrp_init(void); |
@@ -279,7 +279,6 @@ arch_initcall(ppc_init); | |||
279 | /* Warning, IO base is not yet inited */ | 279 | /* Warning, IO base is not yet inited */ |
280 | void __init setup_arch(char **cmdline_p) | 280 | void __init setup_arch(char **cmdline_p) |
281 | { | 281 | { |
282 | extern char *klimit; | ||
283 | extern void do_init_bootmem(void); | 282 | extern void do_init_bootmem(void); |
284 | 283 | ||
285 | /* so udelay does something sensible, assume <= 1000 bogomips */ | 284 | /* so udelay does something sensible, assume <= 1000 bogomips */ |
@@ -303,14 +302,9 @@ void __init setup_arch(char **cmdline_p) | |||
303 | pmac_feature_init(); /* New cool way */ | 302 | pmac_feature_init(); /* New cool way */ |
304 | #endif | 303 | #endif |
305 | 304 | ||
306 | #ifdef CONFIG_XMON | 305 | #ifdef CONFIG_XMON_DEFAULT |
307 | xmon_map_scc(); | 306 | xmon_init(1); |
308 | if (strstr(cmd_line, "xmon")) { | 307 | #endif |
309 | xmon_init(1); | ||
310 | debugger(NULL); | ||
311 | } | ||
312 | #endif /* CONFIG_XMON */ | ||
313 | if ( ppc_md.progress ) ppc_md.progress("setup_arch: enter", 0x3eab); | ||
314 | 308 | ||
315 | #if defined(CONFIG_KGDB) | 309 | #if defined(CONFIG_KGDB) |
316 | if (ppc_md.kgdb_map_scc) | 310 | if (ppc_md.kgdb_map_scc) |
@@ -343,7 +337,7 @@ void __init setup_arch(char **cmdline_p) | |||
343 | init_mm.start_code = PAGE_OFFSET; | 337 | init_mm.start_code = PAGE_OFFSET; |
344 | init_mm.end_code = (unsigned long) _etext; | 338 | init_mm.end_code = (unsigned long) _etext; |
345 | init_mm.end_data = (unsigned long) _edata; | 339 | init_mm.end_data = (unsigned long) _edata; |
346 | init_mm.brk = (unsigned long) klimit; | 340 | init_mm.brk = klimit; |
347 | 341 | ||
348 | /* Save unparsed command line copy for /proc/cmdline */ | 342 | /* Save unparsed command line copy for /proc/cmdline */ |
349 | strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE); | 343 | strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE); |
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 0471e843b6c5..6791668213e7 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c | |||
@@ -61,6 +61,8 @@ | |||
61 | #include <asm/xmon.h> | 61 | #include <asm/xmon.h> |
62 | #include <asm/udbg.h> | 62 | #include <asm/udbg.h> |
63 | 63 | ||
64 | #include "setup.h" | ||
65 | |||
64 | #ifdef DEBUG | 66 | #ifdef DEBUG |
65 | #define DBG(fmt...) udbg_printf(fmt) | 67 | #define DBG(fmt...) udbg_printf(fmt) |
66 | #else | 68 | #else |
@@ -94,15 +96,6 @@ extern void udbg_init_maple_realmode(void); | |||
94 | do { udbg_putc = call_rtas_display_status_delay; } while(0) | 96 | do { udbg_putc = call_rtas_display_status_delay; } while(0) |
95 | #endif | 97 | #endif |
96 | 98 | ||
97 | /* extern void *stab; */ | ||
98 | extern unsigned long klimit; | ||
99 | |||
100 | extern void mm_init_ppc64(void); | ||
101 | extern void stab_initialize(unsigned long stab); | ||
102 | extern void htab_initialize(void); | ||
103 | extern void early_init_devtree(void *flat_dt); | ||
104 | extern void unflatten_device_tree(void); | ||
105 | |||
106 | int have_of = 1; | 99 | int have_of = 1; |
107 | int boot_cpuid = 0; | 100 | int boot_cpuid = 0; |
108 | int boot_cpuid_phys = 0; | 101 | int boot_cpuid_phys = 0; |
@@ -254,11 +247,10 @@ void __init early_setup(unsigned long dt_ptr) | |||
254 | * Iterate all ppc_md structures until we find the proper | 247 | * Iterate all ppc_md structures until we find the proper |
255 | * one for the current machine type | 248 | * one for the current machine type |
256 | */ | 249 | */ |
257 | DBG("Probing machine type for platform %x...\n", | 250 | DBG("Probing machine type for platform %x...\n", _machine); |
258 | systemcfg->platform); | ||
259 | 251 | ||
260 | for (mach = machines; *mach; mach++) { | 252 | for (mach = machines; *mach; mach++) { |
261 | if ((*mach)->probe(systemcfg->platform)) | 253 | if ((*mach)->probe(_machine)) |
262 | break; | 254 | break; |
263 | } | 255 | } |
264 | /* What can we do if we didn't find ? */ | 256 | /* What can we do if we didn't find ? */ |
@@ -290,6 +282,28 @@ void __init early_setup(unsigned long dt_ptr) | |||
290 | DBG(" <- early_setup()\n"); | 282 | DBG(" <- early_setup()\n"); |
291 | } | 283 | } |
292 | 284 | ||
285 | #ifdef CONFIG_SMP | ||
286 | void early_setup_secondary(void) | ||
287 | { | ||
288 | struct paca_struct *lpaca = get_paca(); | ||
289 | |||
290 | /* Mark enabled in PACA */ | ||
291 | lpaca->proc_enabled = 0; | ||
292 | |||
293 | /* Initialize hash table for that CPU */ | ||
294 | htab_initialize_secondary(); | ||
295 | |||
296 | /* Initialize STAB/SLB. We use a virtual address as it works | ||
297 | * in real mode on pSeries and we want a virutal address on | ||
298 | * iSeries anyway | ||
299 | */ | ||
300 | if (cpu_has_feature(CPU_FTR_SLB)) | ||
301 | slb_initialize(); | ||
302 | else | ||
303 | stab_initialize(lpaca->stab_addr); | ||
304 | } | ||
305 | |||
306 | #endif /* CONFIG_SMP */ | ||
293 | 307 | ||
294 | #if defined(CONFIG_SMP) || defined(CONFIG_KEXEC) | 308 | #if defined(CONFIG_SMP) || defined(CONFIG_KEXEC) |
295 | void smp_release_cpus(void) | 309 | void smp_release_cpus(void) |
@@ -315,7 +329,8 @@ void smp_release_cpus(void) | |||
315 | #endif /* CONFIG_SMP || CONFIG_KEXEC */ | 329 | #endif /* CONFIG_SMP || CONFIG_KEXEC */ |
316 | 330 | ||
317 | /* | 331 | /* |
318 | * Initialize some remaining members of the ppc64_caches and systemcfg structures | 332 | * Initialize some remaining members of the ppc64_caches and systemcfg |
333 | * structures | ||
319 | * (at least until we get rid of them completely). This is mostly some | 334 | * (at least until we get rid of them completely). This is mostly some |
320 | * cache informations about the CPU that will be used by cache flush | 335 | * cache informations about the CPU that will be used by cache flush |
321 | * routines and/or provided to userland | 336 | * routines and/or provided to userland |
@@ -340,7 +355,7 @@ static void __init initialize_cache_info(void) | |||
340 | const char *dc, *ic; | 355 | const char *dc, *ic; |
341 | 356 | ||
342 | /* Then read cache informations */ | 357 | /* Then read cache informations */ |
343 | if (systemcfg->platform == PLATFORM_POWERMAC) { | 358 | if (_machine == PLATFORM_POWERMAC) { |
344 | dc = "d-cache-block-size"; | 359 | dc = "d-cache-block-size"; |
345 | ic = "i-cache-block-size"; | 360 | ic = "i-cache-block-size"; |
346 | } else { | 361 | } else { |
@@ -360,8 +375,8 @@ static void __init initialize_cache_info(void) | |||
360 | DBG("Argh, can't find dcache properties ! " | 375 | DBG("Argh, can't find dcache properties ! " |
361 | "sizep: %p, lsizep: %p\n", sizep, lsizep); | 376 | "sizep: %p, lsizep: %p\n", sizep, lsizep); |
362 | 377 | ||
363 | systemcfg->dcache_size = ppc64_caches.dsize = size; | 378 | _systemcfg->dcache_size = ppc64_caches.dsize = size; |
364 | systemcfg->dcache_line_size = | 379 | _systemcfg->dcache_line_size = |
365 | ppc64_caches.dline_size = lsize; | 380 | ppc64_caches.dline_size = lsize; |
366 | ppc64_caches.log_dline_size = __ilog2(lsize); | 381 | ppc64_caches.log_dline_size = __ilog2(lsize); |
367 | ppc64_caches.dlines_per_page = PAGE_SIZE / lsize; | 382 | ppc64_caches.dlines_per_page = PAGE_SIZE / lsize; |
@@ -378,8 +393,8 @@ static void __init initialize_cache_info(void) | |||
378 | DBG("Argh, can't find icache properties ! " | 393 | DBG("Argh, can't find icache properties ! " |
379 | "sizep: %p, lsizep: %p\n", sizep, lsizep); | 394 | "sizep: %p, lsizep: %p\n", sizep, lsizep); |
380 | 395 | ||
381 | systemcfg->icache_size = ppc64_caches.isize = size; | 396 | _systemcfg->icache_size = ppc64_caches.isize = size; |
382 | systemcfg->icache_line_size = | 397 | _systemcfg->icache_line_size = |
383 | ppc64_caches.iline_size = lsize; | 398 | ppc64_caches.iline_size = lsize; |
384 | ppc64_caches.log_iline_size = __ilog2(lsize); | 399 | ppc64_caches.log_iline_size = __ilog2(lsize); |
385 | ppc64_caches.ilines_per_page = PAGE_SIZE / lsize; | 400 | ppc64_caches.ilines_per_page = PAGE_SIZE / lsize; |
@@ -387,10 +402,12 @@ static void __init initialize_cache_info(void) | |||
387 | } | 402 | } |
388 | 403 | ||
389 | /* Add an eye catcher and the systemcfg layout version number */ | 404 | /* Add an eye catcher and the systemcfg layout version number */ |
390 | strcpy(systemcfg->eye_catcher, "SYSTEMCFG:PPC64"); | 405 | strcpy(_systemcfg->eye_catcher, "SYSTEMCFG:PPC64"); |
391 | systemcfg->version.major = SYSTEMCFG_MAJOR; | 406 | _systemcfg->version.major = SYSTEMCFG_MAJOR; |
392 | systemcfg->version.minor = SYSTEMCFG_MINOR; | 407 | _systemcfg->version.minor = SYSTEMCFG_MINOR; |
393 | systemcfg->processor = mfspr(SPRN_PVR); | 408 | _systemcfg->processor = mfspr(SPRN_PVR); |
409 | _systemcfg->platform = _machine; | ||
410 | _systemcfg->physicalMemorySize = lmb_phys_mem_size(); | ||
394 | 411 | ||
395 | DBG(" <- initialize_cache_info()\n"); | 412 | DBG(" <- initialize_cache_info()\n"); |
396 | } | 413 | } |
@@ -479,10 +496,10 @@ void __init setup_system(void) | |||
479 | printk("-----------------------------------------------------\n"); | 496 | printk("-----------------------------------------------------\n"); |
480 | printk("ppc64_pft_size = 0x%lx\n", ppc64_pft_size); | 497 | printk("ppc64_pft_size = 0x%lx\n", ppc64_pft_size); |
481 | printk("ppc64_interrupt_controller = 0x%ld\n", ppc64_interrupt_controller); | 498 | printk("ppc64_interrupt_controller = 0x%ld\n", ppc64_interrupt_controller); |
482 | printk("systemcfg = 0x%p\n", systemcfg); | 499 | printk("systemcfg = 0x%p\n", _systemcfg); |
483 | printk("systemcfg->platform = 0x%x\n", systemcfg->platform); | 500 | printk("systemcfg->platform = 0x%x\n", _systemcfg->platform); |
484 | printk("systemcfg->processorCount = 0x%lx\n", systemcfg->processorCount); | 501 | printk("systemcfg->processorCount = 0x%lx\n", _systemcfg->processorCount); |
485 | printk("systemcfg->physicalMemorySize = 0x%lx\n", systemcfg->physicalMemorySize); | 502 | printk("systemcfg->physicalMemorySize = 0x%lx\n", _systemcfg->physicalMemorySize); |
486 | printk("ppc64_caches.dcache_line_size = 0x%x\n", | 503 | printk("ppc64_caches.dcache_line_size = 0x%x\n", |
487 | ppc64_caches.dline_size); | 504 | ppc64_caches.dline_size); |
488 | printk("ppc64_caches.icache_line_size = 0x%x\n", | 505 | printk("ppc64_caches.icache_line_size = 0x%x\n", |
@@ -564,12 +581,12 @@ void __init setup_syscall_map(void) | |||
564 | for (i = 0; i < __NR_syscalls; i++) { | 581 | for (i = 0; i < __NR_syscalls; i++) { |
565 | if (sys_call_table[i*2] != sys_ni_syscall) { | 582 | if (sys_call_table[i*2] != sys_ni_syscall) { |
566 | count64++; | 583 | count64++; |
567 | systemcfg->syscall_map_64[i >> 5] |= | 584 | _systemcfg->syscall_map_64[i >> 5] |= |
568 | 0x80000000UL >> (i & 0x1f); | 585 | 0x80000000UL >> (i & 0x1f); |
569 | } | 586 | } |
570 | if (sys_call_table[i*2+1] != sys_ni_syscall) { | 587 | if (sys_call_table[i*2+1] != sys_ni_syscall) { |
571 | count32++; | 588 | count32++; |
572 | systemcfg->syscall_map_32[i >> 5] |= | 589 | _systemcfg->syscall_map_32[i >> 5] |= |
573 | 0x80000000UL >> (i & 0x1f); | 590 | 0x80000000UL >> (i & 0x1f); |
574 | } | 591 | } |
575 | } | 592 | } |
@@ -858,26 +875,6 @@ int check_legacy_ioport(unsigned long base_port) | |||
858 | } | 875 | } |
859 | EXPORT_SYMBOL(check_legacy_ioport); | 876 | EXPORT_SYMBOL(check_legacy_ioport); |
860 | 877 | ||
861 | #ifdef CONFIG_XMON | ||
862 | static int __init early_xmon(char *p) | ||
863 | { | ||
864 | /* ensure xmon is enabled */ | ||
865 | if (p) { | ||
866 | if (strncmp(p, "on", 2) == 0) | ||
867 | xmon_init(1); | ||
868 | if (strncmp(p, "off", 3) == 0) | ||
869 | xmon_init(0); | ||
870 | if (strncmp(p, "early", 5) != 0) | ||
871 | return 0; | ||
872 | } | ||
873 | xmon_init(1); | ||
874 | debugger(NULL); | ||
875 | |||
876 | return 0; | ||
877 | } | ||
878 | early_param("xmon", early_xmon); | ||
879 | #endif | ||
880 | |||
881 | void cpu_die(void) | 878 | void cpu_die(void) |
882 | { | 879 | { |
883 | if (ppc_md.cpu_die) | 880 | if (ppc_md.cpu_die) |
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index 081d931eae48..a7c4515f320f 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c | |||
@@ -42,6 +42,7 @@ | |||
42 | 42 | ||
43 | #include <asm/uaccess.h> | 43 | #include <asm/uaccess.h> |
44 | #include <asm/cacheflush.h> | 44 | #include <asm/cacheflush.h> |
45 | #include <asm/sigcontext.h> | ||
45 | #ifdef CONFIG_PPC64 | 46 | #ifdef CONFIG_PPC64 |
46 | #include "ppc32.h" | 47 | #include "ppc32.h" |
47 | #include <asm/unistd.h> | 48 | #include <asm/unistd.h> |
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 36d67a8d7cbb..e28a139c29d0 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c | |||
@@ -44,6 +44,7 @@ | |||
44 | #include <asm/cputable.h> | 44 | #include <asm/cputable.h> |
45 | #include <asm/system.h> | 45 | #include <asm/system.h> |
46 | #include <asm/mpic.h> | 46 | #include <asm/mpic.h> |
47 | #include <asm/systemcfg.h> | ||
47 | #ifdef CONFIG_PPC64 | 48 | #ifdef CONFIG_PPC64 |
48 | #include <asm/paca.h> | 49 | #include <asm/paca.h> |
49 | #endif | 50 | #endif |
@@ -368,9 +369,11 @@ int generic_cpu_disable(void) | |||
368 | if (cpu == boot_cpuid) | 369 | if (cpu == boot_cpuid) |
369 | return -EBUSY; | 370 | return -EBUSY; |
370 | 371 | ||
371 | systemcfg->processorCount--; | ||
372 | cpu_clear(cpu, cpu_online_map); | 372 | cpu_clear(cpu, cpu_online_map); |
373 | #ifdef CONFIG_PPC64 | ||
374 | _systemcfg->processorCount--; | ||
373 | fixup_irqs(cpu_online_map); | 375 | fixup_irqs(cpu_online_map); |
376 | #endif | ||
374 | return 0; | 377 | return 0; |
375 | } | 378 | } |
376 | 379 | ||
@@ -388,9 +391,11 @@ int generic_cpu_enable(unsigned int cpu) | |||
388 | while (!cpu_online(cpu)) | 391 | while (!cpu_online(cpu)) |
389 | cpu_relax(); | 392 | cpu_relax(); |
390 | 393 | ||
394 | #ifdef CONFIG_PPC64 | ||
391 | fixup_irqs(cpu_online_map); | 395 | fixup_irqs(cpu_online_map); |
392 | /* counter the irq disable in fixup_irqs */ | 396 | /* counter the irq disable in fixup_irqs */ |
393 | local_irq_enable(); | 397 | local_irq_enable(); |
398 | #endif | ||
394 | return 0; | 399 | return 0; |
395 | } | 400 | } |
396 | 401 | ||
@@ -419,7 +424,9 @@ void generic_mach_cpu_die(void) | |||
419 | while (__get_cpu_var(cpu_state) != CPU_UP_PREPARE) | 424 | while (__get_cpu_var(cpu_state) != CPU_UP_PREPARE) |
420 | cpu_relax(); | 425 | cpu_relax(); |
421 | 426 | ||
427 | #ifdef CONFIG_PPC64 | ||
422 | flush_tlb_pending(); | 428 | flush_tlb_pending(); |
429 | #endif | ||
423 | cpu_set(cpu, cpu_online_map); | 430 | cpu_set(cpu, cpu_online_map); |
424 | local_irq_enable(); | 431 | local_irq_enable(); |
425 | } | 432 | } |
diff --git a/arch/powerpc/kernel/sys_ppc32.c b/arch/powerpc/kernel/sys_ppc32.c index a8210ed5c686..9c921d1c4084 100644 --- a/arch/powerpc/kernel/sys_ppc32.c +++ b/arch/powerpc/kernel/sys_ppc32.c | |||
@@ -52,7 +52,6 @@ | |||
52 | #include <asm/semaphore.h> | 52 | #include <asm/semaphore.h> |
53 | #include <asm/time.h> | 53 | #include <asm/time.h> |
54 | #include <asm/mmu_context.h> | 54 | #include <asm/mmu_context.h> |
55 | #include <asm/systemcfg.h> | ||
56 | #include <asm/ppc-pci.h> | 55 | #include <asm/ppc-pci.h> |
57 | 56 | ||
58 | /* readdir & getdents */ | 57 | /* readdir & getdents */ |
diff --git a/arch/ppc64/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c index e99ec62c2c52..850af198fb5f 100644 --- a/arch/ppc64/kernel/sysfs.c +++ b/arch/powerpc/kernel/sysfs.c | |||
@@ -232,7 +232,7 @@ static void register_cpu_online(unsigned int cpu) | |||
232 | sysdev_create_file(s, &attr_pmc7); | 232 | sysdev_create_file(s, &attr_pmc7); |
233 | if (cur_cpu_spec->num_pmcs >= 8) | 233 | if (cur_cpu_spec->num_pmcs >= 8) |
234 | sysdev_create_file(s, &attr_pmc8); | 234 | sysdev_create_file(s, &attr_pmc8); |
235 | 235 | ||
236 | if (cpu_has_feature(CPU_FTR_SMT)) | 236 | if (cpu_has_feature(CPU_FTR_SMT)) |
237 | sysdev_create_file(s, &attr_purr); | 237 | sysdev_create_file(s, &attr_purr); |
238 | } | 238 | } |
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index a6282b625b44..260b6ecd26a9 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c | |||
@@ -271,13 +271,13 @@ static inline void update_gtod(u64 new_tb_stamp, u64 new_stamp_xsec, | |||
271 | * tb_to_xs and stamp_xsec values are consistent. If not, then it | 271 | * tb_to_xs and stamp_xsec values are consistent. If not, then it |
272 | * loops back and reads them again until this criteria is met. | 272 | * loops back and reads them again until this criteria is met. |
273 | */ | 273 | */ |
274 | ++(systemcfg->tb_update_count); | 274 | ++(_systemcfg->tb_update_count); |
275 | smp_wmb(); | 275 | smp_wmb(); |
276 | systemcfg->tb_orig_stamp = new_tb_stamp; | 276 | _systemcfg->tb_orig_stamp = new_tb_stamp; |
277 | systemcfg->stamp_xsec = new_stamp_xsec; | 277 | _systemcfg->stamp_xsec = new_stamp_xsec; |
278 | systemcfg->tb_to_xs = new_tb_to_xs; | 278 | _systemcfg->tb_to_xs = new_tb_to_xs; |
279 | smp_wmb(); | 279 | smp_wmb(); |
280 | ++(systemcfg->tb_update_count); | 280 | ++(_systemcfg->tb_update_count); |
281 | #endif | 281 | #endif |
282 | } | 282 | } |
283 | 283 | ||
@@ -357,8 +357,9 @@ static void iSeries_tb_recal(void) | |||
357 | do_gtod.tb_ticks_per_sec = tb_ticks_per_sec; | 357 | do_gtod.tb_ticks_per_sec = tb_ticks_per_sec; |
358 | tb_to_xs = divres.result_low; | 358 | tb_to_xs = divres.result_low; |
359 | do_gtod.varp->tb_to_xs = tb_to_xs; | 359 | do_gtod.varp->tb_to_xs = tb_to_xs; |
360 | systemcfg->tb_ticks_per_sec = tb_ticks_per_sec; | 360 | _systemcfg->tb_ticks_per_sec = |
361 | systemcfg->tb_to_xs = tb_to_xs; | 361 | tb_ticks_per_sec; |
362 | _systemcfg->tb_to_xs = tb_to_xs; | ||
362 | } | 363 | } |
363 | else { | 364 | else { |
364 | printk( "Titan recalibrate: FAILED (difference > 4 percent)\n" | 365 | printk( "Titan recalibrate: FAILED (difference > 4 percent)\n" |
@@ -483,6 +484,8 @@ void __init smp_space_timers(unsigned int max_cpus) | |||
483 | unsigned long offset = tb_ticks_per_jiffy / max_cpus; | 484 | unsigned long offset = tb_ticks_per_jiffy / max_cpus; |
484 | unsigned long previous_tb = per_cpu(last_jiffy, boot_cpuid); | 485 | unsigned long previous_tb = per_cpu(last_jiffy, boot_cpuid); |
485 | 486 | ||
487 | /* make sure tb > per_cpu(last_jiffy, cpu) for all cpus always */ | ||
488 | previous_tb -= tb_ticks_per_jiffy; | ||
486 | for_each_cpu(i) { | 489 | for_each_cpu(i) { |
487 | if (i != boot_cpuid) { | 490 | if (i != boot_cpuid) { |
488 | previous_tb += offset; | 491 | previous_tb += offset; |
@@ -559,8 +562,8 @@ int do_settimeofday(struct timespec *tv) | |||
559 | update_gtod(tb_last_jiffy, new_xsec, do_gtod.varp->tb_to_xs); | 562 | update_gtod(tb_last_jiffy, new_xsec, do_gtod.varp->tb_to_xs); |
560 | 563 | ||
561 | #ifdef CONFIG_PPC64 | 564 | #ifdef CONFIG_PPC64 |
562 | systemcfg->tz_minuteswest = sys_tz.tz_minuteswest; | 565 | _systemcfg->tz_minuteswest = sys_tz.tz_minuteswest; |
563 | systemcfg->tz_dsttime = sys_tz.tz_dsttime; | 566 | _systemcfg->tz_dsttime = sys_tz.tz_dsttime; |
564 | #endif | 567 | #endif |
565 | 568 | ||
566 | write_sequnlock_irqrestore(&xtime_lock, flags); | 569 | write_sequnlock_irqrestore(&xtime_lock, flags); |
@@ -711,11 +714,11 @@ void __init time_init(void) | |||
711 | do_gtod.varp->tb_to_xs = tb_to_xs; | 714 | do_gtod.varp->tb_to_xs = tb_to_xs; |
712 | do_gtod.tb_to_us = tb_to_us; | 715 | do_gtod.tb_to_us = tb_to_us; |
713 | #ifdef CONFIG_PPC64 | 716 | #ifdef CONFIG_PPC64 |
714 | systemcfg->tb_orig_stamp = tb_last_jiffy; | 717 | _systemcfg->tb_orig_stamp = tb_last_jiffy; |
715 | systemcfg->tb_update_count = 0; | 718 | _systemcfg->tb_update_count = 0; |
716 | systemcfg->tb_ticks_per_sec = tb_ticks_per_sec; | 719 | _systemcfg->tb_ticks_per_sec = tb_ticks_per_sec; |
717 | systemcfg->stamp_xsec = xtime.tv_sec * XSEC_PER_SEC; | 720 | _systemcfg->stamp_xsec = xtime.tv_sec * XSEC_PER_SEC; |
718 | systemcfg->tb_to_xs = tb_to_xs; | 721 | _systemcfg->tb_to_xs = tb_to_xs; |
719 | #endif | 722 | #endif |
720 | 723 | ||
721 | time_freq = 0; | 724 | time_freq = 0; |
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 0578f8387603..2020bb7648fb 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c | |||
@@ -129,7 +129,7 @@ int die(const char *str, struct pt_regs *regs, long err) | |||
129 | nl = 1; | 129 | nl = 1; |
130 | #endif | 130 | #endif |
131 | #ifdef CONFIG_PPC64 | 131 | #ifdef CONFIG_PPC64 |
132 | switch (systemcfg->platform) { | 132 | switch (_machine) { |
133 | case PLATFORM_PSERIES: | 133 | case PLATFORM_PSERIES: |
134 | printk("PSERIES "); | 134 | printk("PSERIES "); |
135 | nl = 1; | 135 | nl = 1; |
diff --git a/arch/powerpc/lib/bitops.c b/arch/powerpc/lib/bitops.c index b67ce3004ebf..f68ad71a0187 100644 --- a/arch/powerpc/lib/bitops.c +++ b/arch/powerpc/lib/bitops.c | |||
@@ -41,7 +41,7 @@ unsigned long find_next_bit(const unsigned long *addr, unsigned long size, | |||
41 | tmp = *p; | 41 | tmp = *p; |
42 | 42 | ||
43 | found_first: | 43 | found_first: |
44 | tmp &= (~0UL >> (64 - size)); | 44 | tmp &= (~0UL >> (BITS_PER_LONG - size)); |
45 | if (tmp == 0UL) /* Are any bits set? */ | 45 | if (tmp == 0UL) /* Are any bits set? */ |
46 | return result + size; /* Nope. */ | 46 | return result + size; /* Nope. */ |
47 | found_middle: | 47 | found_middle: |
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 22e474876133..706e8a63ced9 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c | |||
@@ -84,10 +84,11 @@ | |||
84 | extern unsigned long dart_tablebase; | 84 | extern unsigned long dart_tablebase; |
85 | #endif /* CONFIG_U3_DART */ | 85 | #endif /* CONFIG_U3_DART */ |
86 | 86 | ||
87 | static unsigned long _SDR1; | ||
88 | struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT]; | ||
89 | |||
87 | hpte_t *htab_address; | 90 | hpte_t *htab_address; |
88 | unsigned long htab_hash_mask; | 91 | unsigned long htab_hash_mask; |
89 | unsigned long _SDR1; | ||
90 | struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT]; | ||
91 | int mmu_linear_psize = MMU_PAGE_4K; | 92 | int mmu_linear_psize = MMU_PAGE_4K; |
92 | int mmu_virtual_psize = MMU_PAGE_4K; | 93 | int mmu_virtual_psize = MMU_PAGE_4K; |
93 | #ifdef CONFIG_HUGETLB_PAGE | 94 | #ifdef CONFIG_HUGETLB_PAGE |
@@ -165,7 +166,7 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend, | |||
165 | * normal insert callback here. | 166 | * normal insert callback here. |
166 | */ | 167 | */ |
167 | #ifdef CONFIG_PPC_ISERIES | 168 | #ifdef CONFIG_PPC_ISERIES |
168 | if (systemcfg->platform == PLATFORM_ISERIES_LPAR) | 169 | if (_machine == PLATFORM_ISERIES_LPAR) |
169 | ret = iSeries_hpte_insert(hpteg, va, | 170 | ret = iSeries_hpte_insert(hpteg, va, |
170 | virt_to_abs(paddr), | 171 | virt_to_abs(paddr), |
171 | tmp_mode, | 172 | tmp_mode, |
@@ -174,7 +175,7 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend, | |||
174 | else | 175 | else |
175 | #endif | 176 | #endif |
176 | #ifdef CONFIG_PPC_PSERIES | 177 | #ifdef CONFIG_PPC_PSERIES |
177 | if (systemcfg->platform & PLATFORM_LPAR) | 178 | if (_machine & PLATFORM_LPAR) |
178 | ret = pSeries_lpar_hpte_insert(hpteg, va, | 179 | ret = pSeries_lpar_hpte_insert(hpteg, va, |
179 | virt_to_abs(paddr), | 180 | virt_to_abs(paddr), |
180 | tmp_mode, | 181 | tmp_mode, |
@@ -293,7 +294,7 @@ static void __init htab_init_page_sizes(void) | |||
293 | * Not in the device-tree, let's fallback on known size | 294 | * Not in the device-tree, let's fallback on known size |
294 | * list for 16M capable GP & GR | 295 | * list for 16M capable GP & GR |
295 | */ | 296 | */ |
296 | if ((systemcfg->platform != PLATFORM_ISERIES_LPAR) && | 297 | if ((_machine != PLATFORM_ISERIES_LPAR) && |
297 | cpu_has_feature(CPU_FTR_16M_PAGE)) | 298 | cpu_has_feature(CPU_FTR_16M_PAGE)) |
298 | memcpy(mmu_psize_defs, mmu_psize_defaults_gp, | 299 | memcpy(mmu_psize_defs, mmu_psize_defaults_gp, |
299 | sizeof(mmu_psize_defaults_gp)); | 300 | sizeof(mmu_psize_defaults_gp)); |
@@ -364,7 +365,7 @@ static int __init htab_dt_scan_pftsize(unsigned long node, | |||
364 | 365 | ||
365 | static unsigned long __init htab_get_table_size(void) | 366 | static unsigned long __init htab_get_table_size(void) |
366 | { | 367 | { |
367 | unsigned long rnd_mem_size, pteg_count; | 368 | unsigned long mem_size, rnd_mem_size, pteg_count; |
368 | 369 | ||
369 | /* If hash size isn't already provided by the platform, we try to | 370 | /* If hash size isn't already provided by the platform, we try to |
370 | * retreive it from the device-tree. If it's not there neither, we | 371 | * retreive it from the device-tree. If it's not there neither, we |
@@ -376,8 +377,9 @@ static unsigned long __init htab_get_table_size(void) | |||
376 | return 1UL << ppc64_pft_size; | 377 | return 1UL << ppc64_pft_size; |
377 | 378 | ||
378 | /* round mem_size up to next power of 2 */ | 379 | /* round mem_size up to next power of 2 */ |
379 | rnd_mem_size = 1UL << __ilog2(systemcfg->physicalMemorySize); | 380 | mem_size = lmb_phys_mem_size(); |
380 | if (rnd_mem_size < systemcfg->physicalMemorySize) | 381 | rnd_mem_size = 1UL << __ilog2(mem_size); |
382 | if (rnd_mem_size < mem_size) | ||
381 | rnd_mem_size <<= 1; | 383 | rnd_mem_size <<= 1; |
382 | 384 | ||
383 | /* # pages / 2 */ | 385 | /* # pages / 2 */ |
@@ -386,6 +388,15 @@ static unsigned long __init htab_get_table_size(void) | |||
386 | return pteg_count << 7; | 388 | return pteg_count << 7; |
387 | } | 389 | } |
388 | 390 | ||
391 | #ifdef CONFIG_MEMORY_HOTPLUG | ||
392 | void create_section_mapping(unsigned long start, unsigned long end) | ||
393 | { | ||
394 | BUG_ON(htab_bolt_mapping(start, end, start, | ||
395 | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | PP_RWXX, | ||
396 | mmu_linear_psize)); | ||
397 | } | ||
398 | #endif /* CONFIG_MEMORY_HOTPLUG */ | ||
399 | |||
389 | void __init htab_initialize(void) | 400 | void __init htab_initialize(void) |
390 | { | 401 | { |
391 | unsigned long table, htab_size_bytes; | 402 | unsigned long table, htab_size_bytes; |
@@ -410,7 +421,7 @@ void __init htab_initialize(void) | |||
410 | 421 | ||
411 | htab_hash_mask = pteg_count - 1; | 422 | htab_hash_mask = pteg_count - 1; |
412 | 423 | ||
413 | if (systemcfg->platform & PLATFORM_LPAR) { | 424 | if (platform_is_lpar()) { |
414 | /* Using a hypervisor which owns the htab */ | 425 | /* Using a hypervisor which owns the htab */ |
415 | htab_address = NULL; | 426 | htab_address = NULL; |
416 | _SDR1 = 0; | 427 | _SDR1 = 0; |
@@ -431,6 +442,9 @@ void __init htab_initialize(void) | |||
431 | 442 | ||
432 | /* Initialize the HPT with no entries */ | 443 | /* Initialize the HPT with no entries */ |
433 | memset((void *)table, 0, htab_size_bytes); | 444 | memset((void *)table, 0, htab_size_bytes); |
445 | |||
446 | /* Set SDR1 */ | ||
447 | mtspr(SPRN_SDR1, _SDR1); | ||
434 | } | 448 | } |
435 | 449 | ||
436 | mode_rw = _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | PP_RWXX; | 450 | mode_rw = _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | PP_RWXX; |
@@ -500,6 +514,12 @@ void __init htab_initialize(void) | |||
500 | #undef KB | 514 | #undef KB |
501 | #undef MB | 515 | #undef MB |
502 | 516 | ||
517 | void __init htab_initialize_secondary(void) | ||
518 | { | ||
519 | if (!platform_is_lpar()) | ||
520 | mtspr(SPRN_SDR1, _SDR1); | ||
521 | } | ||
522 | |||
503 | /* | 523 | /* |
504 | * Called by asm hashtable.S for doing lazy icache flush | 524 | * Called by asm hashtable.S for doing lazy icache flush |
505 | */ | 525 | */ |
diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c index 4612a79dfb6e..7d4b8b5f0606 100644 --- a/arch/powerpc/mm/init_32.c +++ b/arch/powerpc/mm/init_32.c | |||
@@ -84,9 +84,6 @@ void MMU_init(void); | |||
84 | /* XXX should be in current.h -- paulus */ | 84 | /* XXX should be in current.h -- paulus */ |
85 | extern struct task_struct *current_set[NR_CPUS]; | 85 | extern struct task_struct *current_set[NR_CPUS]; |
86 | 86 | ||
87 | char *klimit = _end; | ||
88 | struct device_node *memory_node; | ||
89 | |||
90 | extern int init_bootmem_done; | 87 | extern int init_bootmem_done; |
91 | 88 | ||
92 | /* | 89 | /* |
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c index ce974c83d88a..1134f70f231d 100644 --- a/arch/powerpc/mm/init_64.c +++ b/arch/powerpc/mm/init_64.c | |||
@@ -20,6 +20,8 @@ | |||
20 | * | 20 | * |
21 | */ | 21 | */ |
22 | 22 | ||
23 | #undef DEBUG | ||
24 | |||
23 | #include <linux/config.h> | 25 | #include <linux/config.h> |
24 | #include <linux/signal.h> | 26 | #include <linux/signal.h> |
25 | #include <linux/sched.h> | 27 | #include <linux/sched.h> |
@@ -64,6 +66,12 @@ | |||
64 | #include <asm/vdso.h> | 66 | #include <asm/vdso.h> |
65 | #include <asm/imalloc.h> | 67 | #include <asm/imalloc.h> |
66 | 68 | ||
69 | #ifdef DEBUG | ||
70 | #define DBG(fmt...) printk(fmt) | ||
71 | #else | ||
72 | #define DBG(fmt...) | ||
73 | #endif | ||
74 | |||
67 | #if PGTABLE_RANGE > USER_VSID_RANGE | 75 | #if PGTABLE_RANGE > USER_VSID_RANGE |
68 | #warning Limited user VSID range means pagetable space is wasted | 76 | #warning Limited user VSID range means pagetable space is wasted |
69 | #endif | 77 | #endif |
@@ -72,8 +80,6 @@ | |||
72 | #warning TASK_SIZE is smaller than it needs to be. | 80 | #warning TASK_SIZE is smaller than it needs to be. |
73 | #endif | 81 | #endif |
74 | 82 | ||
75 | unsigned long klimit = (unsigned long)_end; | ||
76 | |||
77 | /* max amount of RAM to use */ | 83 | /* max amount of RAM to use */ |
78 | unsigned long __max_memory; | 84 | unsigned long __max_memory; |
79 | 85 | ||
@@ -188,14 +194,14 @@ static void zero_ctor(void *addr, kmem_cache_t *cache, unsigned long flags) | |||
188 | } | 194 | } |
189 | 195 | ||
190 | #ifdef CONFIG_PPC_64K_PAGES | 196 | #ifdef CONFIG_PPC_64K_PAGES |
191 | static const int pgtable_cache_size[2] = { | 197 | static const unsigned int pgtable_cache_size[3] = { |
192 | PTE_TABLE_SIZE, PGD_TABLE_SIZE | 198 | PTE_TABLE_SIZE, PMD_TABLE_SIZE, PGD_TABLE_SIZE |
193 | }; | 199 | }; |
194 | static const char *pgtable_cache_name[ARRAY_SIZE(pgtable_cache_size)] = { | 200 | static const char *pgtable_cache_name[ARRAY_SIZE(pgtable_cache_size)] = { |
195 | "pte_pmd_cache", "pgd_cache", | 201 | "pte_pmd_cache", "pmd_cache", "pgd_cache", |
196 | }; | 202 | }; |
197 | #else | 203 | #else |
198 | static const int pgtable_cache_size[2] = { | 204 | static const unsigned int pgtable_cache_size[2] = { |
199 | PTE_TABLE_SIZE, PMD_TABLE_SIZE | 205 | PTE_TABLE_SIZE, PMD_TABLE_SIZE |
200 | }; | 206 | }; |
201 | static const char *pgtable_cache_name[ARRAY_SIZE(pgtable_cache_size)] = { | 207 | static const char *pgtable_cache_name[ARRAY_SIZE(pgtable_cache_size)] = { |
@@ -213,6 +219,8 @@ void pgtable_cache_init(void) | |||
213 | int size = pgtable_cache_size[i]; | 219 | int size = pgtable_cache_size[i]; |
214 | const char *name = pgtable_cache_name[i]; | 220 | const char *name = pgtable_cache_name[i]; |
215 | 221 | ||
222 | DBG("Allocating page table cache %s (#%d) " | ||
223 | "for size: %08x...\n", name, i, size); | ||
216 | pgtable_cache[i] = kmem_cache_create(name, | 224 | pgtable_cache[i] = kmem_cache_create(name, |
217 | size, size, | 225 | size, size, |
218 | SLAB_HWCACHE_ALIGN | | 226 | SLAB_HWCACHE_ALIGN | |
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 6f55efd9be95..1dd3cc69a490 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c | |||
@@ -110,6 +110,7 @@ EXPORT_SYMBOL(phys_mem_access_prot); | |||
110 | void online_page(struct page *page) | 110 | void online_page(struct page *page) |
111 | { | 111 | { |
112 | ClearPageReserved(page); | 112 | ClearPageReserved(page); |
113 | set_page_count(page, 0); | ||
113 | free_cold_page(page); | 114 | free_cold_page(page); |
114 | totalram_pages++; | 115 | totalram_pages++; |
115 | num_physpages++; | 116 | num_physpages++; |
@@ -127,6 +128,9 @@ int __devinit add_memory(u64 start, u64 size) | |||
127 | unsigned long start_pfn = start >> PAGE_SHIFT; | 128 | unsigned long start_pfn = start >> PAGE_SHIFT; |
128 | unsigned long nr_pages = size >> PAGE_SHIFT; | 129 | unsigned long nr_pages = size >> PAGE_SHIFT; |
129 | 130 | ||
131 | start += KERNELBASE; | ||
132 | create_section_mapping(start, start + size); | ||
133 | |||
130 | /* this should work for most non-highmem platforms */ | 134 | /* this should work for most non-highmem platforms */ |
131 | zone = pgdata->node_zones; | 135 | zone = pgdata->node_zones; |
132 | 136 | ||
diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c index 900842451bd3..c7f7bb6f30b3 100644 --- a/arch/powerpc/mm/pgtable_64.c +++ b/arch/powerpc/mm/pgtable_64.c | |||
@@ -122,8 +122,11 @@ static int map_io_page(unsigned long ea, unsigned long pa, int flags) | |||
122 | * | 122 | * |
123 | */ | 123 | */ |
124 | if (htab_bolt_mapping(ea, ea + PAGE_SIZE, pa, flags, | 124 | if (htab_bolt_mapping(ea, ea + PAGE_SIZE, pa, flags, |
125 | mmu_virtual_psize)) | 125 | mmu_virtual_psize)) { |
126 | panic("Can't map bolted IO mapping"); | 126 | printk(KERN_ERR "Failed to do bolted mapping IO " |
127 | "memory at %016lx !\n", pa); | ||
128 | return -ENOMEM; | ||
129 | } | ||
127 | } | 130 | } |
128 | return 0; | 131 | return 0; |
129 | } | 132 | } |
diff --git a/arch/powerpc/mm/stab.c b/arch/powerpc/mm/stab.c index fa325dbf98fc..cfbb4e1f966b 100644 --- a/arch/powerpc/mm/stab.c +++ b/arch/powerpc/mm/stab.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <asm/cputable.h> | 20 | #include <asm/cputable.h> |
21 | #include <asm/lmb.h> | 21 | #include <asm/lmb.h> |
22 | #include <asm/abs_addr.h> | 22 | #include <asm/abs_addr.h> |
23 | #include <asm/firmware.h> | ||
23 | 24 | ||
24 | struct stab_entry { | 25 | struct stab_entry { |
25 | unsigned long esid_data; | 26 | unsigned long esid_data; |
@@ -256,7 +257,7 @@ void stabs_alloc(void) | |||
256 | 257 | ||
257 | paca[cpu].stab_addr = newstab; | 258 | paca[cpu].stab_addr = newstab; |
258 | paca[cpu].stab_real = virt_to_abs(newstab); | 259 | paca[cpu].stab_real = virt_to_abs(newstab); |
259 | printk(KERN_DEBUG "Segment table for CPU %d at 0x%lx " | 260 | printk(KERN_INFO "Segment table for CPU %d at 0x%lx " |
260 | "virtual, 0x%lx absolute\n", | 261 | "virtual, 0x%lx absolute\n", |
261 | cpu, paca[cpu].stab_addr, paca[cpu].stab_real); | 262 | cpu, paca[cpu].stab_addr, paca[cpu].stab_real); |
262 | } | 263 | } |
@@ -270,10 +271,28 @@ void stabs_alloc(void) | |||
270 | void stab_initialize(unsigned long stab) | 271 | void stab_initialize(unsigned long stab) |
271 | { | 272 | { |
272 | unsigned long vsid = get_kernel_vsid(KERNELBASE); | 273 | unsigned long vsid = get_kernel_vsid(KERNELBASE); |
274 | unsigned long stabreal; | ||
273 | 275 | ||
274 | asm volatile("isync; slbia; isync":::"memory"); | 276 | asm volatile("isync; slbia; isync":::"memory"); |
275 | make_ste(stab, GET_ESID(KERNELBASE), vsid); | 277 | make_ste(stab, GET_ESID(KERNELBASE), vsid); |
276 | 278 | ||
277 | /* Order update */ | 279 | /* Order update */ |
278 | asm volatile("sync":::"memory"); | 280 | asm volatile("sync":::"memory"); |
281 | |||
282 | /* Set ASR */ | ||
283 | stabreal = get_paca()->stab_real | 0x1ul; | ||
284 | |||
285 | #ifdef CONFIG_PPC_ISERIES | ||
286 | if (firmware_has_feature(FW_FEATURE_ISERIES)) { | ||
287 | HvCall1(HvCallBaseSetASR, stabreal); | ||
288 | return; | ||
289 | } | ||
290 | #endif /* CONFIG_PPC_ISERIES */ | ||
291 | #ifdef CONFIG_PPC_PSERIES | ||
292 | if (platform_is_lpar()) { | ||
293 | plpar_hcall_norets(H_SET_ASR, stabreal); | ||
294 | return; | ||
295 | } | ||
296 | #endif | ||
297 | mtspr(SPRN_ASR, stabreal); | ||
279 | } | 298 | } |
diff --git a/arch/powerpc/oprofile/op_model_power4.c b/arch/powerpc/oprofile/op_model_power4.c index c4ee5478427b..e3a024e324b6 100644 --- a/arch/powerpc/oprofile/op_model_power4.c +++ b/arch/powerpc/oprofile/op_model_power4.c | |||
@@ -233,8 +233,7 @@ static unsigned long get_pc(struct pt_regs *regs) | |||
233 | mmcra = mfspr(SPRN_MMCRA); | 233 | mmcra = mfspr(SPRN_MMCRA); |
234 | 234 | ||
235 | /* Were we in the hypervisor? */ | 235 | /* Were we in the hypervisor? */ |
236 | if ((systemcfg->platform == PLATFORM_PSERIES_LPAR) && | 236 | if (platform_is_lpar() && (mmcra & MMCRA_SIHV)) |
237 | (mmcra & MMCRA_SIHV)) | ||
238 | /* function descriptor madness */ | 237 | /* function descriptor madness */ |
239 | return *((unsigned long *)hypervisor_bucket); | 238 | return *((unsigned long *)hypervisor_bucket); |
240 | 239 | ||
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c index ecd32d5d85f4..4099ddab9205 100644 --- a/arch/powerpc/platforms/chrp/setup.c +++ b/arch/powerpc/platforms/chrp/setup.c | |||
@@ -361,7 +361,9 @@ static void __init chrp_find_openpic(void) | |||
361 | printk(KERN_INFO "OpenPIC at %lx\n", opaddr); | 361 | printk(KERN_INFO "OpenPIC at %lx\n", opaddr); |
362 | 362 | ||
363 | irq_count = NR_IRQS - NUM_ISA_INTERRUPTS - 4; /* leave room for IPIs */ | 363 | irq_count = NR_IRQS - NUM_ISA_INTERRUPTS - 4; /* leave room for IPIs */ |
364 | prom_get_irq_senses(init_senses, NUM_8259_INTERRUPTS, NR_IRQS - 4); | 364 | prom_get_irq_senses(init_senses, NUM_ISA_INTERRUPTS, NR_IRQS - 4); |
365 | /* i8259 cascade is always positive level */ | ||
366 | init_senses[0] = IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE; | ||
365 | 367 | ||
366 | iranges = (unsigned int *) get_property(np, "interrupt-ranges", &len); | 368 | iranges = (unsigned int *) get_property(np, "interrupt-ranges", &len); |
367 | if (iranges == NULL) | 369 | if (iranges == NULL) |
diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c index a06603d84a45..01090e9ce0cf 100644 --- a/arch/powerpc/platforms/iseries/irq.c +++ b/arch/powerpc/platforms/iseries/irq.c | |||
@@ -103,6 +103,9 @@ static void intReceived(struct XmPciLpEvent *eventParm, | |||
103 | struct pt_regs *regsParm) | 103 | struct pt_regs *regsParm) |
104 | { | 104 | { |
105 | int irq; | 105 | int irq; |
106 | #ifdef CONFIG_IRQSTACKS | ||
107 | struct thread_info *curtp, *irqtp; | ||
108 | #endif | ||
106 | 109 | ||
107 | ++Pci_Interrupt_Count; | 110 | ++Pci_Interrupt_Count; |
108 | 111 | ||
@@ -110,7 +113,20 @@ static void intReceived(struct XmPciLpEvent *eventParm, | |||
110 | case XmPciLpEvent_SlotInterrupt: | 113 | case XmPciLpEvent_SlotInterrupt: |
111 | irq = eventParm->hvLpEvent.xCorrelationToken; | 114 | irq = eventParm->hvLpEvent.xCorrelationToken; |
112 | /* Dispatch the interrupt handlers for this irq */ | 115 | /* Dispatch the interrupt handlers for this irq */ |
113 | ppc_irq_dispatch_handler(regsParm, irq); | 116 | #ifdef CONFIG_IRQSTACKS |
117 | /* Switch to the irq stack to handle this */ | ||
118 | curtp = current_thread_info(); | ||
119 | irqtp = hardirq_ctx[smp_processor_id()]; | ||
120 | if (curtp != irqtp) { | ||
121 | irqtp->task = curtp->task; | ||
122 | irqtp->flags = 0; | ||
123 | call___do_IRQ(irq, regsParm, irqtp); | ||
124 | irqtp->task = NULL; | ||
125 | if (irqtp->flags) | ||
126 | set_bits(irqtp->flags, &curtp->flags); | ||
127 | } else | ||
128 | #endif | ||
129 | __do_IRQ(irq, regsParm); | ||
114 | HvCallPci_eoi(eventParm->eventData.slotInterrupt.busNumber, | 130 | HvCallPci_eoi(eventParm->eventData.slotInterrupt.busNumber, |
115 | eventParm->eventData.slotInterrupt.subBusNumber, | 131 | eventParm->eventData.slotInterrupt.subBusNumber, |
116 | eventParm->eventData.slotInterrupt.deviceId); | 132 | eventParm->eventData.slotInterrupt.deviceId); |
@@ -310,10 +326,8 @@ static void iSeries_disable_IRQ(unsigned int irq) | |||
310 | } | 326 | } |
311 | 327 | ||
312 | /* | 328 | /* |
313 | * Need to define this so ppc_irq_dispatch_handler will NOT call | 329 | * This does nothing because there is not enough information |
314 | * enable_IRQ at the end of interrupt handling. However, this does | 330 | * provided to do the EOI HvCall. This is done by XmPciLpEvent.c |
315 | * nothing because there is not enough information provided to do | ||
316 | * the EOI HvCall. This is done by XmPciLpEvent.c | ||
317 | */ | 331 | */ |
318 | static void iSeries_end_IRQ(unsigned int irq) | 332 | static void iSeries_end_IRQ(unsigned int irq) |
319 | { | 333 | { |
diff --git a/arch/powerpc/platforms/iseries/misc.S b/arch/powerpc/platforms/iseries/misc.S index 09f14522e176..dfe7aa1ba098 100644 --- a/arch/powerpc/platforms/iseries/misc.S +++ b/arch/powerpc/platforms/iseries/misc.S | |||
@@ -15,6 +15,7 @@ | |||
15 | 15 | ||
16 | #include <asm/processor.h> | 16 | #include <asm/processor.h> |
17 | #include <asm/asm-offsets.h> | 17 | #include <asm/asm-offsets.h> |
18 | #include <asm/ppc_asm.h> | ||
18 | 19 | ||
19 | .text | 20 | .text |
20 | 21 | ||
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 7f8f0cda6a74..6a29f301436b 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c | |||
@@ -39,7 +39,8 @@ | |||
39 | #include <asm/sections.h> | 39 | #include <asm/sections.h> |
40 | #include <asm/iommu.h> | 40 | #include <asm/iommu.h> |
41 | #include <asm/firmware.h> | 41 | #include <asm/firmware.h> |
42 | 42 | #include <asm/systemcfg.h> | |
43 | #include <asm/system.h> | ||
43 | #include <asm/time.h> | 44 | #include <asm/time.h> |
44 | #include <asm/paca.h> | 45 | #include <asm/paca.h> |
45 | #include <asm/cache.h> | 46 | #include <asm/cache.h> |
@@ -71,7 +72,7 @@ extern void hvlog(char *fmt, ...); | |||
71 | #endif | 72 | #endif |
72 | 73 | ||
73 | /* Function Prototypes */ | 74 | /* Function Prototypes */ |
74 | static void build_iSeries_Memory_Map(void); | 75 | static unsigned long build_iSeries_Memory_Map(void); |
75 | static void iseries_shared_idle(void); | 76 | static void iseries_shared_idle(void); |
76 | static void iseries_dedicated_idle(void); | 77 | static void iseries_dedicated_idle(void); |
77 | #ifdef CONFIG_PCI | 78 | #ifdef CONFIG_PCI |
@@ -84,7 +85,6 @@ static void iSeries_pci_final_fixup(void) { } | |||
84 | int piranha_simulator; | 85 | int piranha_simulator; |
85 | 86 | ||
86 | extern int rd_size; /* Defined in drivers/block/rd.c */ | 87 | extern int rd_size; /* Defined in drivers/block/rd.c */ |
87 | extern unsigned long klimit; | ||
88 | extern unsigned long embedded_sysmap_start; | 88 | extern unsigned long embedded_sysmap_start; |
89 | extern unsigned long embedded_sysmap_end; | 89 | extern unsigned long embedded_sysmap_end; |
90 | 90 | ||
@@ -403,9 +403,11 @@ void mschunks_alloc(unsigned long num_chunks) | |||
403 | * a table used to translate Linux's physical addresses to these | 403 | * a table used to translate Linux's physical addresses to these |
404 | * absolute addresses. Absolute addresses are needed when | 404 | * absolute addresses. Absolute addresses are needed when |
405 | * communicating with the hypervisor (e.g. to build HPT entries) | 405 | * communicating with the hypervisor (e.g. to build HPT entries) |
406 | * | ||
407 | * Returns the physical memory size | ||
406 | */ | 408 | */ |
407 | 409 | ||
408 | static void __init build_iSeries_Memory_Map(void) | 410 | static unsigned long __init build_iSeries_Memory_Map(void) |
409 | { | 411 | { |
410 | u32 loadAreaFirstChunk, loadAreaLastChunk, loadAreaSize; | 412 | u32 loadAreaFirstChunk, loadAreaLastChunk, loadAreaSize; |
411 | u32 nextPhysChunk; | 413 | u32 nextPhysChunk; |
@@ -538,7 +540,7 @@ static void __init build_iSeries_Memory_Map(void) | |||
538 | * which should be equal to | 540 | * which should be equal to |
539 | * nextPhysChunk | 541 | * nextPhysChunk |
540 | */ | 542 | */ |
541 | systemcfg->physicalMemorySize = chunk_to_addr(nextPhysChunk); | 543 | return chunk_to_addr(nextPhysChunk); |
542 | } | 544 | } |
543 | 545 | ||
544 | /* | 546 | /* |
@@ -564,8 +566,8 @@ static void __init iSeries_setup_arch(void) | |||
564 | printk("Max physical processors = %d\n", | 566 | printk("Max physical processors = %d\n", |
565 | itVpdAreas.xSlicMaxPhysicalProcs); | 567 | itVpdAreas.xSlicMaxPhysicalProcs); |
566 | 568 | ||
567 | systemcfg->processor = xIoHriProcessorVpd[procIx].xPVR; | 569 | _systemcfg->processor = xIoHriProcessorVpd[procIx].xPVR; |
568 | printk("Processor version = %x\n", systemcfg->processor); | 570 | printk("Processor version = %x\n", _systemcfg->processor); |
569 | } | 571 | } |
570 | 572 | ||
571 | static void iSeries_show_cpuinfo(struct seq_file *m) | 573 | static void iSeries_show_cpuinfo(struct seq_file *m) |
@@ -702,7 +704,6 @@ static void iseries_shared_idle(void) | |||
702 | 704 | ||
703 | static void iseries_dedicated_idle(void) | 705 | static void iseries_dedicated_idle(void) |
704 | { | 706 | { |
705 | long oldval; | ||
706 | set_thread_flag(TIF_POLLING_NRFLAG); | 707 | set_thread_flag(TIF_POLLING_NRFLAG); |
707 | 708 | ||
708 | while (1) { | 709 | while (1) { |
@@ -929,7 +930,7 @@ void dt_cpus(struct iseries_flat_dt *dt) | |||
929 | dt_end_node(dt); | 930 | dt_end_node(dt); |
930 | } | 931 | } |
931 | 932 | ||
932 | void build_flat_dt(struct iseries_flat_dt *dt) | 933 | void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size) |
933 | { | 934 | { |
934 | u64 tmp[2]; | 935 | u64 tmp[2]; |
935 | 936 | ||
@@ -945,7 +946,7 @@ void build_flat_dt(struct iseries_flat_dt *dt) | |||
945 | dt_prop_str(dt, "name", "memory"); | 946 | dt_prop_str(dt, "name", "memory"); |
946 | dt_prop_str(dt, "device_type", "memory"); | 947 | dt_prop_str(dt, "device_type", "memory"); |
947 | tmp[0] = 0; | 948 | tmp[0] = 0; |
948 | tmp[1] = systemcfg->physicalMemorySize; | 949 | tmp[1] = phys_mem_size; |
949 | dt_prop_u64_list(dt, "reg", tmp, 2); | 950 | dt_prop_u64_list(dt, "reg", tmp, 2); |
950 | dt_end_node(dt); | 951 | dt_end_node(dt); |
951 | 952 | ||
@@ -965,13 +966,15 @@ void build_flat_dt(struct iseries_flat_dt *dt) | |||
965 | 966 | ||
966 | void * __init iSeries_early_setup(void) | 967 | void * __init iSeries_early_setup(void) |
967 | { | 968 | { |
969 | unsigned long phys_mem_size; | ||
970 | |||
968 | iSeries_fixup_klimit(); | 971 | iSeries_fixup_klimit(); |
969 | 972 | ||
970 | /* | 973 | /* |
971 | * Initialize the table which translate Linux physical addresses to | 974 | * Initialize the table which translate Linux physical addresses to |
972 | * AS/400 absolute addresses | 975 | * AS/400 absolute addresses |
973 | */ | 976 | */ |
974 | build_iSeries_Memory_Map(); | 977 | phys_mem_size = build_iSeries_Memory_Map(); |
975 | 978 | ||
976 | iSeries_get_cmdline(); | 979 | iSeries_get_cmdline(); |
977 | 980 | ||
@@ -981,7 +984,7 @@ void * __init iSeries_early_setup(void) | |||
981 | /* Parse early parameters, in particular mem=x */ | 984 | /* Parse early parameters, in particular mem=x */ |
982 | parse_early_param(); | 985 | parse_early_param(); |
983 | 986 | ||
984 | build_flat_dt(&iseries_dt); | 987 | build_flat_dt(&iseries_dt, phys_mem_size); |
985 | 988 | ||
986 | return (void *) __pa(&iseries_dt); | 989 | return (void *) __pa(&iseries_dt); |
987 | } | 990 | } |
diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c index 340c21caeae2..895aeb3f75d0 100644 --- a/arch/powerpc/platforms/maple/pci.c +++ b/arch/powerpc/platforms/maple/pci.c | |||
@@ -380,9 +380,6 @@ void __init maple_pcibios_fixup(void) | |||
380 | for_each_pci_dev(dev) | 380 | for_each_pci_dev(dev) |
381 | pci_read_irq_line(dev); | 381 | pci_read_irq_line(dev); |
382 | 382 | ||
383 | /* Do the mapping of the IO space */ | ||
384 | phbs_remap_io(); | ||
385 | |||
386 | DBG(" <- maple_pcibios_fixup\n"); | 383 | DBG(" <- maple_pcibios_fixup\n"); |
387 | } | 384 | } |
388 | 385 | ||
diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c index 8f818d092e2b..dfd41b9781a9 100644 --- a/arch/powerpc/platforms/powermac/pci.c +++ b/arch/powerpc/platforms/powermac/pci.c | |||
@@ -918,9 +918,6 @@ void __init pmac_pci_init(void) | |||
918 | PCI_DN(np)->busno = 0xf0; | 918 | PCI_DN(np)->busno = 0xf0; |
919 | } | 919 | } |
920 | 920 | ||
921 | /* map in PCI I/O space */ | ||
922 | phbs_remap_io(); | ||
923 | |||
924 | /* pmac_check_ht_link(); */ | 921 | /* pmac_check_ht_link(); */ |
925 | 922 | ||
926 | /* Tell pci.c to not use the common resource allocation mechanism */ | 923 | /* Tell pci.c to not use the common resource allocation mechanism */ |
diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c index 83a49e80ac29..90040c49494d 100644 --- a/arch/powerpc/platforms/powermac/pic.c +++ b/arch/powerpc/platforms/powermac/pic.c | |||
@@ -74,6 +74,9 @@ static DEFINE_SPINLOCK(pmac_pic_lock); | |||
74 | #define GATWICK_IRQ_POOL_SIZE 10 | 74 | #define GATWICK_IRQ_POOL_SIZE 10 |
75 | static struct interrupt_info gatwick_int_pool[GATWICK_IRQ_POOL_SIZE]; | 75 | static struct interrupt_info gatwick_int_pool[GATWICK_IRQ_POOL_SIZE]; |
76 | 76 | ||
77 | #define NR_MASK_WORDS ((NR_IRQS + 31) / 32) | ||
78 | static unsigned long ppc_lost_interrupts[NR_MASK_WORDS]; | ||
79 | |||
77 | /* | 80 | /* |
78 | * Mark an irq as "lost". This is only used on the pmac | 81 | * Mark an irq as "lost". This is only used on the pmac |
79 | * since it can lose interrupts (see pmac_set_irq_mask). | 82 | * since it can lose interrupts (see pmac_set_irq_mask). |
diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c index e1f9443cc872..957b09103422 100644 --- a/arch/powerpc/platforms/powermac/smp.c +++ b/arch/powerpc/platforms/powermac/smp.c | |||
@@ -305,9 +305,19 @@ static int __init smp_psurge_probe(void) | |||
305 | psurge_start = ioremap(PSURGE_START, 4); | 305 | psurge_start = ioremap(PSURGE_START, 4); |
306 | psurge_pri_intr = ioremap(PSURGE_PRI_INTR, 4); | 306 | psurge_pri_intr = ioremap(PSURGE_PRI_INTR, 4); |
307 | 307 | ||
308 | /* this is not actually strictly necessary -- paulus. */ | 308 | /* |
309 | for (i = 1; i < ncpus; ++i) | 309 | * This is necessary because OF doesn't know about the |
310 | smp_hw_index[i] = i; | 310 | * secondary cpu(s), and thus there aren't nodes in the |
311 | * device tree for them, and smp_setup_cpu_maps hasn't | ||
312 | * set their bits in cpu_possible_map and cpu_present_map. | ||
313 | */ | ||
314 | if (ncpus > NR_CPUS) | ||
315 | ncpus = NR_CPUS; | ||
316 | for (i = 1; i < ncpus ; ++i) { | ||
317 | cpu_set(i, cpu_present_map); | ||
318 | cpu_set(i, cpu_possible_map); | ||
319 | set_hard_smp_processor_id(i, i); | ||
320 | } | ||
311 | 321 | ||
312 | if (ppc_md.progress) ppc_md.progress("smp_psurge_probe - done", 0x352); | 322 | if (ppc_md.progress) ppc_md.progress("smp_psurge_probe - done", 0x352); |
313 | 323 | ||
@@ -348,6 +358,7 @@ static void __init psurge_dual_sync_tb(int cpu_nr) | |||
348 | int t; | 358 | int t; |
349 | 359 | ||
350 | set_dec(tb_ticks_per_jiffy); | 360 | set_dec(tb_ticks_per_jiffy); |
361 | /* XXX fixme */ | ||
351 | set_tb(0, 0); | 362 | set_tb(0, 0); |
352 | last_jiffy_stamp(cpu_nr) = 0; | 363 | last_jiffy_stamp(cpu_nr) = 0; |
353 | 364 | ||
@@ -363,8 +374,6 @@ static void __init psurge_dual_sync_tb(int cpu_nr) | |||
363 | 374 | ||
364 | /* now interrupt the secondary, starting both TBs */ | 375 | /* now interrupt the secondary, starting both TBs */ |
365 | psurge_set_ipi(1); | 376 | psurge_set_ipi(1); |
366 | |||
367 | smp_tb_synchronized = 1; | ||
368 | } | 377 | } |
369 | 378 | ||
370 | static struct irqaction psurge_irqaction = { | 379 | static struct irqaction psurge_irqaction = { |
@@ -625,9 +634,8 @@ void smp_core99_give_timebase(void) | |||
625 | for (t = 100000; t > 0 && sec_tb_reset; --t) | 634 | for (t = 100000; t > 0 && sec_tb_reset; --t) |
626 | udelay(10); | 635 | udelay(10); |
627 | if (sec_tb_reset) | 636 | if (sec_tb_reset) |
637 | /* XXX BUG_ON here? */ | ||
628 | printk(KERN_WARNING "Timeout waiting sync(2) on second CPU\n"); | 638 | printk(KERN_WARNING "Timeout waiting sync(2) on second CPU\n"); |
629 | else | ||
630 | smp_tb_synchronized = 1; | ||
631 | 639 | ||
632 | /* Now, restart the timebase by leaving the GPIO to an open collector */ | 640 | /* Now, restart the timebase by leaving the GPIO to an open collector */ |
633 | pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, core99_tb_gpio, 0); | 641 | pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, core99_tb_gpio, 0); |
@@ -810,19 +818,9 @@ static void __devinit smp_core99_setup_cpu(int cpu_nr) | |||
810 | } | 818 | } |
811 | 819 | ||
812 | 820 | ||
813 | /* Core99 Macs (dual G4s and G5s) */ | ||
814 | struct smp_ops_t core99_smp_ops = { | ||
815 | .message_pass = smp_mpic_message_pass, | ||
816 | .probe = smp_core99_probe, | ||
817 | .kick_cpu = smp_core99_kick_cpu, | ||
818 | .setup_cpu = smp_core99_setup_cpu, | ||
819 | .give_timebase = smp_core99_give_timebase, | ||
820 | .take_timebase = smp_core99_take_timebase, | ||
821 | }; | ||
822 | |||
823 | #if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC32) | 821 | #if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC32) |
824 | 822 | ||
825 | int __cpu_disable(void) | 823 | int smp_core99_cpu_disable(void) |
826 | { | 824 | { |
827 | cpu_clear(smp_processor_id(), cpu_online_map); | 825 | cpu_clear(smp_processor_id(), cpu_online_map); |
828 | 826 | ||
@@ -846,7 +844,7 @@ void cpu_die(void) | |||
846 | low_cpu_die(); | 844 | low_cpu_die(); |
847 | } | 845 | } |
848 | 846 | ||
849 | void __cpu_die(unsigned int cpu) | 847 | void smp_core99_cpu_die(unsigned int cpu) |
850 | { | 848 | { |
851 | int timeout; | 849 | int timeout; |
852 | 850 | ||
@@ -858,8 +856,21 @@ void __cpu_die(unsigned int cpu) | |||
858 | } | 856 | } |
859 | msleep(1); | 857 | msleep(1); |
860 | } | 858 | } |
861 | cpu_callin_map[cpu] = 0; | ||
862 | cpu_dead[cpu] = 0; | 859 | cpu_dead[cpu] = 0; |
863 | } | 860 | } |
864 | 861 | ||
865 | #endif | 862 | #endif |
863 | |||
864 | /* Core99 Macs (dual G4s and G5s) */ | ||
865 | struct smp_ops_t core99_smp_ops = { | ||
866 | .message_pass = smp_mpic_message_pass, | ||
867 | .probe = smp_core99_probe, | ||
868 | .kick_cpu = smp_core99_kick_cpu, | ||
869 | .setup_cpu = smp_core99_setup_cpu, | ||
870 | .give_timebase = smp_core99_give_timebase, | ||
871 | .take_timebase = smp_core99_take_timebase, | ||
872 | #if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC32) | ||
873 | .cpu_disable = smp_core99_cpu_disable, | ||
874 | .cpu_die = smp_core99_cpu_die, | ||
875 | #endif | ||
876 | }; | ||
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile index b9938fece781..e7ca5b1f591e 100644 --- a/arch/powerpc/platforms/pseries/Makefile +++ b/arch/powerpc/platforms/pseries/Makefile | |||
@@ -3,3 +3,5 @@ obj-y := pci.o lpar.o hvCall.o nvram.o reconfig.o \ | |||
3 | obj-$(CONFIG_SMP) += smp.o | 3 | obj-$(CONFIG_SMP) += smp.o |
4 | obj-$(CONFIG_IBMVIO) += vio.o | 4 | obj-$(CONFIG_IBMVIO) += vio.o |
5 | obj-$(CONFIG_XICS) += xics.o | 5 | obj-$(CONFIG_XICS) += xics.o |
6 | obj-$(CONFIG_SCANLOG) += scanlog.o | ||
7 | obj-$(CONFIG_EEH) += eeh.o eeh_event.o | ||
diff --git a/arch/ppc64/kernel/eeh.c b/arch/powerpc/platforms/pseries/eeh.c index 035d1b14a207..79de2310e70b 100644 --- a/arch/ppc64/kernel/eeh.c +++ b/arch/powerpc/platforms/pseries/eeh.c | |||
@@ -1,39 +1,37 @@ | |||
1 | /* | 1 | /* |
2 | * eeh.c | 2 | * eeh.c |
3 | * Copyright (C) 2001 Dave Engebretsen & Todd Inglett IBM Corporation | 3 | * Copyright (C) 2001 Dave Engebretsen & Todd Inglett IBM Corporation |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | 5 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License as published by | 6 | * it under the terms of the GNU General Public License as published by |
7 | * the Free Software Foundation; either version 2 of the License, or | 7 | * the Free Software Foundation; either version 2 of the License, or |
8 | * (at your option) any later version. | 8 | * (at your option) any later version. |
9 | * | 9 | * |
10 | * This program is distributed in the hope that it will be useful, | 10 | * This program is distributed in the hope that it will be useful, |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | * GNU General Public License for more details. | 13 | * GNU General Public License for more details. |
14 | * | 14 | * |
15 | * You should have received a copy of the GNU General Public License | 15 | * You should have received a copy of the GNU General Public License |
16 | * along with this program; if not, write to the Free Software | 16 | * along with this program; if not, write to the Free Software |
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include <linux/bootmem.h> | 20 | #include <linux/delay.h> |
21 | #include <linux/init.h> | 21 | #include <linux/init.h> |
22 | #include <linux/list.h> | 22 | #include <linux/list.h> |
23 | #include <linux/mm.h> | ||
24 | #include <linux/notifier.h> | ||
25 | #include <linux/pci.h> | 23 | #include <linux/pci.h> |
26 | #include <linux/proc_fs.h> | 24 | #include <linux/proc_fs.h> |
27 | #include <linux/rbtree.h> | 25 | #include <linux/rbtree.h> |
28 | #include <linux/seq_file.h> | 26 | #include <linux/seq_file.h> |
29 | #include <linux/spinlock.h> | 27 | #include <linux/spinlock.h> |
28 | #include <asm/atomic.h> | ||
30 | #include <asm/eeh.h> | 29 | #include <asm/eeh.h> |
30 | #include <asm/eeh_event.h> | ||
31 | #include <asm/io.h> | 31 | #include <asm/io.h> |
32 | #include <asm/machdep.h> | 32 | #include <asm/machdep.h> |
33 | #include <asm/rtas.h> | ||
34 | #include <asm/atomic.h> | ||
35 | #include <asm/systemcfg.h> | ||
36 | #include <asm/ppc-pci.h> | 33 | #include <asm/ppc-pci.h> |
34 | #include <asm/rtas.h> | ||
37 | 35 | ||
38 | #undef DEBUG | 36 | #undef DEBUG |
39 | 37 | ||
@@ -49,8 +47,8 @@ | |||
49 | * were "empty": all reads return 0xff's and all writes are silently | 47 | * were "empty": all reads return 0xff's and all writes are silently |
50 | * ignored. EEH slot isolation events can be triggered by parity | 48 | * ignored. EEH slot isolation events can be triggered by parity |
51 | * errors on the address or data busses (e.g. during posted writes), | 49 | * errors on the address or data busses (e.g. during posted writes), |
52 | * which in turn might be caused by dust, vibration, humidity, | 50 | * which in turn might be caused by low voltage on the bus, dust, |
53 | * radioactivity or plain-old failed hardware. | 51 | * vibration, humidity, radioactivity or plain-old failed hardware. |
54 | * | 52 | * |
55 | * Note, however, that one of the leading causes of EEH slot | 53 | * Note, however, that one of the leading causes of EEH slot |
56 | * freeze events are buggy device drivers, buggy device microcode, | 54 | * freeze events are buggy device drivers, buggy device microcode, |
@@ -71,26 +69,15 @@ | |||
71 | * and sent out for processing. | 69 | * and sent out for processing. |
72 | */ | 70 | */ |
73 | 71 | ||
74 | /** Bus Unit ID macros; get low and hi 32-bits of the 64-bit BUID */ | 72 | /* If a device driver keeps reading an MMIO register in an interrupt |
75 | #define BUID_HI(buid) ((buid) >> 32) | ||
76 | #define BUID_LO(buid) ((buid) & 0xffffffff) | ||
77 | |||
78 | /* EEH event workqueue setup. */ | ||
79 | static DEFINE_SPINLOCK(eeh_eventlist_lock); | ||
80 | LIST_HEAD(eeh_eventlist); | ||
81 | static void eeh_event_handler(void *); | ||
82 | DECLARE_WORK(eeh_event_wq, eeh_event_handler, NULL); | ||
83 | |||
84 | static struct notifier_block *eeh_notifier_chain; | ||
85 | |||
86 | /* | ||
87 | * If a device driver keeps reading an MMIO register in an interrupt | ||
88 | * handler after a slot isolation event has occurred, we assume it | 73 | * handler after a slot isolation event has occurred, we assume it |
89 | * is broken and panic. This sets the threshold for how many read | 74 | * is broken and panic. This sets the threshold for how many read |
90 | * attempts we allow before panicking. | 75 | * attempts we allow before panicking. |
91 | */ | 76 | */ |
92 | #define EEH_MAX_FAILS 1000 | 77 | #define EEH_MAX_FAILS 100000 |
93 | static atomic_t eeh_fail_count; | 78 | |
79 | /* Misc forward declaraions */ | ||
80 | static void eeh_save_bars(struct pci_dev * pdev, struct pci_dn *pdn); | ||
94 | 81 | ||
95 | /* RTAS tokens */ | 82 | /* RTAS tokens */ |
96 | static int ibm_set_eeh_option; | 83 | static int ibm_set_eeh_option; |
@@ -101,12 +88,19 @@ static int ibm_slot_error_detail; | |||
101 | 88 | ||
102 | static int eeh_subsystem_enabled; | 89 | static int eeh_subsystem_enabled; |
103 | 90 | ||
91 | /* Lock to avoid races due to multiple reports of an error */ | ||
92 | static DEFINE_SPINLOCK(confirm_error_lock); | ||
93 | |||
104 | /* Buffer for reporting slot-error-detail rtas calls */ | 94 | /* Buffer for reporting slot-error-detail rtas calls */ |
105 | static unsigned char slot_errbuf[RTAS_ERROR_LOG_MAX]; | 95 | static unsigned char slot_errbuf[RTAS_ERROR_LOG_MAX]; |
106 | static DEFINE_SPINLOCK(slot_errbuf_lock); | 96 | static DEFINE_SPINLOCK(slot_errbuf_lock); |
107 | static int eeh_error_buf_size; | 97 | static int eeh_error_buf_size; |
108 | 98 | ||
109 | /* System monitoring statistics */ | 99 | /* System monitoring statistics */ |
100 | static DEFINE_PER_CPU(unsigned long, no_device); | ||
101 | static DEFINE_PER_CPU(unsigned long, no_dn); | ||
102 | static DEFINE_PER_CPU(unsigned long, no_cfg_addr); | ||
103 | static DEFINE_PER_CPU(unsigned long, ignored_check); | ||
110 | static DEFINE_PER_CPU(unsigned long, total_mmio_ffs); | 104 | static DEFINE_PER_CPU(unsigned long, total_mmio_ffs); |
111 | static DEFINE_PER_CPU(unsigned long, false_positives); | 105 | static DEFINE_PER_CPU(unsigned long, false_positives); |
112 | static DEFINE_PER_CPU(unsigned long, ignored_failures); | 106 | static DEFINE_PER_CPU(unsigned long, ignored_failures); |
@@ -224,9 +218,9 @@ pci_addr_cache_insert(struct pci_dev *dev, unsigned long alo, | |||
224 | while (*p) { | 218 | while (*p) { |
225 | parent = *p; | 219 | parent = *p; |
226 | piar = rb_entry(parent, struct pci_io_addr_range, rb_node); | 220 | piar = rb_entry(parent, struct pci_io_addr_range, rb_node); |
227 | if (alo < piar->addr_lo) { | 221 | if (ahi < piar->addr_lo) { |
228 | p = &parent->rb_left; | 222 | p = &parent->rb_left; |
229 | } else if (ahi > piar->addr_hi) { | 223 | } else if (alo > piar->addr_hi) { |
230 | p = &parent->rb_right; | 224 | p = &parent->rb_right; |
231 | } else { | 225 | } else { |
232 | if (dev != piar->pcidev || | 226 | if (dev != piar->pcidev || |
@@ -245,6 +239,11 @@ pci_addr_cache_insert(struct pci_dev *dev, unsigned long alo, | |||
245 | piar->pcidev = dev; | 239 | piar->pcidev = dev; |
246 | piar->flags = flags; | 240 | piar->flags = flags; |
247 | 241 | ||
242 | #ifdef DEBUG | ||
243 | printk(KERN_DEBUG "PIAR: insert range=[%lx:%lx] dev=%s\n", | ||
244 | alo, ahi, pci_name (dev)); | ||
245 | #endif | ||
246 | |||
248 | rb_link_node(&piar->rb_node, parent, p); | 247 | rb_link_node(&piar->rb_node, parent, p); |
249 | rb_insert_color(&piar->rb_node, &pci_io_addr_cache_root.rb_root); | 248 | rb_insert_color(&piar->rb_node, &pci_io_addr_cache_root.rb_root); |
250 | 249 | ||
@@ -260,18 +259,17 @@ static void __pci_addr_cache_insert_device(struct pci_dev *dev) | |||
260 | 259 | ||
261 | dn = pci_device_to_OF_node(dev); | 260 | dn = pci_device_to_OF_node(dev); |
262 | if (!dn) { | 261 | if (!dn) { |
263 | printk(KERN_WARNING "PCI: no pci dn found for dev=%s\n", | 262 | printk(KERN_WARNING "PCI: no pci dn found for dev=%s\n", pci_name(dev)); |
264 | pci_name(dev)); | ||
265 | return; | 263 | return; |
266 | } | 264 | } |
267 | 265 | ||
268 | /* Skip any devices for which EEH is not enabled. */ | 266 | /* Skip any devices for which EEH is not enabled. */ |
269 | pdn = dn->data; | 267 | pdn = PCI_DN(dn); |
270 | if (!(pdn->eeh_mode & EEH_MODE_SUPPORTED) || | 268 | if (!(pdn->eeh_mode & EEH_MODE_SUPPORTED) || |
271 | pdn->eeh_mode & EEH_MODE_NOCHECK) { | 269 | pdn->eeh_mode & EEH_MODE_NOCHECK) { |
272 | #ifdef DEBUG | 270 | #ifdef DEBUG |
273 | printk(KERN_INFO "PCI: skip building address cache for=%s\n", | 271 | printk(KERN_INFO "PCI: skip building address cache for=%s - %s\n", |
274 | pci_name(dev)); | 272 | pci_name(dev), pdn->node->full_name); |
275 | #endif | 273 | #endif |
276 | return; | 274 | return; |
277 | } | 275 | } |
@@ -307,7 +305,7 @@ static void __pci_addr_cache_insert_device(struct pci_dev *dev) | |||
307 | * we maintain a cache of devices that can be quickly searched. | 305 | * we maintain a cache of devices that can be quickly searched. |
308 | * This routine adds a device to that cache. | 306 | * This routine adds a device to that cache. |
309 | */ | 307 | */ |
310 | void pci_addr_cache_insert_device(struct pci_dev *dev) | 308 | static void pci_addr_cache_insert_device(struct pci_dev *dev) |
311 | { | 309 | { |
312 | unsigned long flags; | 310 | unsigned long flags; |
313 | 311 | ||
@@ -350,7 +348,7 @@ restart: | |||
350 | * the tree multiple times (once per resource). | 348 | * the tree multiple times (once per resource). |
351 | * But so what; device removal doesn't need to be that fast. | 349 | * But so what; device removal doesn't need to be that fast. |
352 | */ | 350 | */ |
353 | void pci_addr_cache_remove_device(struct pci_dev *dev) | 351 | static void pci_addr_cache_remove_device(struct pci_dev *dev) |
354 | { | 352 | { |
355 | unsigned long flags; | 353 | unsigned long flags; |
356 | 354 | ||
@@ -370,8 +368,12 @@ void pci_addr_cache_remove_device(struct pci_dev *dev) | |||
370 | */ | 368 | */ |
371 | void __init pci_addr_cache_build(void) | 369 | void __init pci_addr_cache_build(void) |
372 | { | 370 | { |
371 | struct device_node *dn; | ||
373 | struct pci_dev *dev = NULL; | 372 | struct pci_dev *dev = NULL; |
374 | 373 | ||
374 | if (!eeh_subsystem_enabled) | ||
375 | return; | ||
376 | |||
375 | spin_lock_init(&pci_io_addr_cache_root.piar_lock); | 377 | spin_lock_init(&pci_io_addr_cache_root.piar_lock); |
376 | 378 | ||
377 | while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { | 379 | while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { |
@@ -380,6 +382,10 @@ void __init pci_addr_cache_build(void) | |||
380 | continue; | 382 | continue; |
381 | } | 383 | } |
382 | pci_addr_cache_insert_device(dev); | 384 | pci_addr_cache_insert_device(dev); |
385 | |||
386 | /* Save the BAR's; firmware doesn't restore these after EEH reset */ | ||
387 | dn = pci_device_to_OF_node(dev); | ||
388 | eeh_save_bars(dev, PCI_DN(dn)); | ||
383 | } | 389 | } |
384 | 390 | ||
385 | #ifdef DEBUG | 391 | #ifdef DEBUG |
@@ -391,22 +397,26 @@ void __init pci_addr_cache_build(void) | |||
391 | /* --------------------------------------------------------------- */ | 397 | /* --------------------------------------------------------------- */ |
392 | /* Above lies the PCI Address Cache. Below lies the EEH event infrastructure */ | 398 | /* Above lies the PCI Address Cache. Below lies the EEH event infrastructure */ |
393 | 399 | ||
394 | /** | 400 | void eeh_slot_error_detail (struct pci_dn *pdn, int severity) |
395 | * eeh_register_notifier - Register to find out about EEH events. | ||
396 | * @nb: notifier block to callback on events | ||
397 | */ | ||
398 | int eeh_register_notifier(struct notifier_block *nb) | ||
399 | { | 401 | { |
400 | return notifier_chain_register(&eeh_notifier_chain, nb); | 402 | unsigned long flags; |
401 | } | 403 | int rc; |
402 | 404 | ||
403 | /** | 405 | /* Log the error with the rtas logger */ |
404 | * eeh_unregister_notifier - Unregister to an EEH event notifier. | 406 | spin_lock_irqsave(&slot_errbuf_lock, flags); |
405 | * @nb: notifier block to callback on events | 407 | memset(slot_errbuf, 0, eeh_error_buf_size); |
406 | */ | 408 | |
407 | int eeh_unregister_notifier(struct notifier_block *nb) | 409 | rc = rtas_call(ibm_slot_error_detail, |
408 | { | 410 | 8, 1, NULL, pdn->eeh_config_addr, |
409 | return notifier_chain_unregister(&eeh_notifier_chain, nb); | 411 | BUID_HI(pdn->phb->buid), |
412 | BUID_LO(pdn->phb->buid), NULL, 0, | ||
413 | virt_to_phys(slot_errbuf), | ||
414 | eeh_error_buf_size, | ||
415 | severity); | ||
416 | |||
417 | if (rc == 0) | ||
418 | log_error(slot_errbuf, ERR_TYPE_RTAS_LOG, 0); | ||
419 | spin_unlock_irqrestore(&slot_errbuf_lock, flags); | ||
410 | } | 420 | } |
411 | 421 | ||
412 | /** | 422 | /** |
@@ -414,16 +424,16 @@ int eeh_unregister_notifier(struct notifier_block *nb) | |||
414 | * @dn: device node to read | 424 | * @dn: device node to read |
415 | * @rets: array to return results in | 425 | * @rets: array to return results in |
416 | */ | 426 | */ |
417 | static int read_slot_reset_state(struct device_node *dn, int rets[]) | 427 | static int read_slot_reset_state(struct pci_dn *pdn, int rets[]) |
418 | { | 428 | { |
419 | int token, outputs; | 429 | int token, outputs; |
420 | struct pci_dn *pdn = dn->data; | ||
421 | 430 | ||
422 | if (ibm_read_slot_reset_state2 != RTAS_UNKNOWN_SERVICE) { | 431 | if (ibm_read_slot_reset_state2 != RTAS_UNKNOWN_SERVICE) { |
423 | token = ibm_read_slot_reset_state2; | 432 | token = ibm_read_slot_reset_state2; |
424 | outputs = 4; | 433 | outputs = 4; |
425 | } else { | 434 | } else { |
426 | token = ibm_read_slot_reset_state; | 435 | token = ibm_read_slot_reset_state; |
436 | rets[2] = 0; /* fake PE Unavailable info */ | ||
427 | outputs = 3; | 437 | outputs = 3; |
428 | } | 438 | } |
429 | 439 | ||
@@ -432,87 +442,84 @@ static int read_slot_reset_state(struct device_node *dn, int rets[]) | |||
432 | } | 442 | } |
433 | 443 | ||
434 | /** | 444 | /** |
435 | * eeh_panic - call panic() for an eeh event that cannot be handled. | 445 | * eeh_token_to_phys - convert EEH address token to phys address |
436 | * The philosophy of this routine is that it is better to panic and | 446 | * @token i/o token, should be address in the form 0xA.... |
437 | * halt the OS than it is to risk possible data corruption by | ||
438 | * oblivious device drivers that don't know better. | ||
439 | * | ||
440 | * @dev pci device that had an eeh event | ||
441 | * @reset_state current reset state of the device slot | ||
442 | */ | 447 | */ |
443 | static void eeh_panic(struct pci_dev *dev, int reset_state) | 448 | static inline unsigned long eeh_token_to_phys(unsigned long token) |
444 | { | 449 | { |
445 | /* | 450 | pte_t *ptep; |
446 | * XXX We should create a separate sysctl for this. | 451 | unsigned long pa; |
447 | * | 452 | |
448 | * Since the panic_on_oops sysctl is used to halt the system | 453 | ptep = find_linux_pte(init_mm.pgd, token); |
449 | * in light of potential corruption, we can use it here. | 454 | if (!ptep) |
450 | */ | 455 | return token; |
451 | if (panic_on_oops) | 456 | pa = pte_pfn(*ptep) << PAGE_SHIFT; |
452 | panic("EEH: MMIO failure (%d) on device:%s\n", reset_state, | 457 | |
453 | pci_name(dev)); | 458 | return pa | (token & (PAGE_SIZE-1)); |
454 | else { | ||
455 | __get_cpu_var(ignored_failures)++; | ||
456 | printk(KERN_INFO "EEH: Ignored MMIO failure (%d) on device:%s\n", | ||
457 | reset_state, pci_name(dev)); | ||
458 | } | ||
459 | } | 459 | } |
460 | 460 | ||
461 | /** | 461 | /** |
462 | * eeh_event_handler - dispatch EEH events. The detection of a frozen | 462 | * Return the "partitionable endpoint" (pe) under which this device lies |
463 | * slot can occur inside an interrupt, where it can be hard to do | ||
464 | * anything about it. The goal of this routine is to pull these | ||
465 | * detection events out of the context of the interrupt handler, and | ||
466 | * re-dispatch them for processing at a later time in a normal context. | ||
467 | * | ||
468 | * @dummy - unused | ||
469 | */ | 463 | */ |
470 | static void eeh_event_handler(void *dummy) | 464 | static struct device_node * find_device_pe(struct device_node *dn) |
471 | { | 465 | { |
472 | unsigned long flags; | 466 | while ((dn->parent) && PCI_DN(dn->parent) && |
473 | struct eeh_event *event; | 467 | (PCI_DN(dn->parent)->eeh_mode & EEH_MODE_SUPPORTED)) { |
474 | 468 | dn = dn->parent; | |
475 | while (1) { | 469 | } |
476 | spin_lock_irqsave(&eeh_eventlist_lock, flags); | 470 | return dn; |
477 | event = NULL; | 471 | } |
478 | if (!list_empty(&eeh_eventlist)) { | ||
479 | event = list_entry(eeh_eventlist.next, struct eeh_event, list); | ||
480 | list_del(&event->list); | ||
481 | } | ||
482 | spin_unlock_irqrestore(&eeh_eventlist_lock, flags); | ||
483 | if (event == NULL) | ||
484 | break; | ||
485 | |||
486 | printk(KERN_INFO "EEH: MMIO failure (%d), notifiying device " | ||
487 | "%s\n", event->reset_state, | ||
488 | pci_name(event->dev)); | ||
489 | 472 | ||
490 | atomic_set(&eeh_fail_count, 0); | 473 | /** Mark all devices that are peers of this device as failed. |
491 | notifier_call_chain (&eeh_notifier_chain, | 474 | * Mark the device driver too, so that it can see the failure |
492 | EEH_NOTIFY_FREEZE, event); | 475 | * immediately; this is critical, since some drivers poll |
476 | * status registers in interrupts ... If a driver is polling, | ||
477 | * and the slot is frozen, then the driver can deadlock in | ||
478 | * an interrupt context, which is bad. | ||
479 | */ | ||
493 | 480 | ||
494 | __get_cpu_var(slot_resets)++; | 481 | static void __eeh_mark_slot (struct device_node *dn, int mode_flag) |
482 | { | ||
483 | while (dn) { | ||
484 | if (PCI_DN(dn)) { | ||
485 | PCI_DN(dn)->eeh_mode |= mode_flag; | ||
495 | 486 | ||
496 | pci_dev_put(event->dev); | 487 | if (dn->child) |
497 | kfree(event); | 488 | __eeh_mark_slot (dn->child, mode_flag); |
489 | } | ||
490 | dn = dn->sibling; | ||
498 | } | 491 | } |
499 | } | 492 | } |
500 | 493 | ||
501 | /** | 494 | void eeh_mark_slot (struct device_node *dn, int mode_flag) |
502 | * eeh_token_to_phys - convert EEH address token to phys address | ||
503 | * @token i/o token, should be address in the form 0xE.... | ||
504 | */ | ||
505 | static inline unsigned long eeh_token_to_phys(unsigned long token) | ||
506 | { | 495 | { |
507 | pte_t *ptep; | 496 | dn = find_device_pe (dn); |
508 | unsigned long pa; | 497 | PCI_DN(dn)->eeh_mode |= mode_flag; |
498 | __eeh_mark_slot (dn->child, mode_flag); | ||
499 | } | ||
509 | 500 | ||
510 | ptep = find_linux_pte(init_mm.pgd, token); | 501 | static void __eeh_clear_slot (struct device_node *dn, int mode_flag) |
511 | if (!ptep) | 502 | { |
512 | return token; | 503 | while (dn) { |
513 | pa = pte_pfn(*ptep) << PAGE_SHIFT; | 504 | if (PCI_DN(dn)) { |
505 | PCI_DN(dn)->eeh_mode &= ~mode_flag; | ||
506 | PCI_DN(dn)->eeh_check_count = 0; | ||
507 | if (dn->child) | ||
508 | __eeh_clear_slot (dn->child, mode_flag); | ||
509 | } | ||
510 | dn = dn->sibling; | ||
511 | } | ||
512 | } | ||
514 | 513 | ||
515 | return pa | (token & (PAGE_SIZE-1)); | 514 | void eeh_clear_slot (struct device_node *dn, int mode_flag) |
515 | { | ||
516 | unsigned long flags; | ||
517 | spin_lock_irqsave(&confirm_error_lock, flags); | ||
518 | dn = find_device_pe (dn); | ||
519 | PCI_DN(dn)->eeh_mode &= ~mode_flag; | ||
520 | PCI_DN(dn)->eeh_check_count = 0; | ||
521 | __eeh_clear_slot (dn->child, mode_flag); | ||
522 | spin_unlock_irqrestore(&confirm_error_lock, flags); | ||
516 | } | 523 | } |
517 | 524 | ||
518 | /** | 525 | /** |
@@ -526,7 +533,7 @@ static inline unsigned long eeh_token_to_phys(unsigned long token) | |||
526 | * will query firmware for the EEH status. | 533 | * will query firmware for the EEH status. |
527 | * | 534 | * |
528 | * Returns 0 if there has not been an EEH error; otherwise returns | 535 | * Returns 0 if there has not been an EEH error; otherwise returns |
529 | * a non-zero value and queues up a solt isolation event notification. | 536 | * a non-zero value and queues up a slot isolation event notification. |
530 | * | 537 | * |
531 | * It is safe to call this routine in an interrupt context. | 538 | * It is safe to call this routine in an interrupt context. |
532 | */ | 539 | */ |
@@ -535,42 +542,59 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) | |||
535 | int ret; | 542 | int ret; |
536 | int rets[3]; | 543 | int rets[3]; |
537 | unsigned long flags; | 544 | unsigned long flags; |
538 | int rc, reset_state; | ||
539 | struct eeh_event *event; | ||
540 | struct pci_dn *pdn; | 545 | struct pci_dn *pdn; |
546 | int rc = 0; | ||
541 | 547 | ||
542 | __get_cpu_var(total_mmio_ffs)++; | 548 | __get_cpu_var(total_mmio_ffs)++; |
543 | 549 | ||
544 | if (!eeh_subsystem_enabled) | 550 | if (!eeh_subsystem_enabled) |
545 | return 0; | 551 | return 0; |
546 | 552 | ||
547 | if (!dn) | 553 | if (!dn) { |
554 | __get_cpu_var(no_dn)++; | ||
548 | return 0; | 555 | return 0; |
549 | pdn = dn->data; | 556 | } |
557 | pdn = PCI_DN(dn); | ||
550 | 558 | ||
551 | /* Access to IO BARs might get this far and still not want checking. */ | 559 | /* Access to IO BARs might get this far and still not want checking. */ |
552 | if (!pdn->eeh_capable || !(pdn->eeh_mode & EEH_MODE_SUPPORTED) || | 560 | if (!(pdn->eeh_mode & EEH_MODE_SUPPORTED) || |
553 | pdn->eeh_mode & EEH_MODE_NOCHECK) { | 561 | pdn->eeh_mode & EEH_MODE_NOCHECK) { |
562 | __get_cpu_var(ignored_check)++; | ||
563 | #ifdef DEBUG | ||
564 | printk ("EEH:ignored check (%x) for %s %s\n", | ||
565 | pdn->eeh_mode, pci_name (dev), dn->full_name); | ||
566 | #endif | ||
554 | return 0; | 567 | return 0; |
555 | } | 568 | } |
556 | 569 | ||
557 | if (!pdn->eeh_config_addr) { | 570 | if (!pdn->eeh_config_addr) { |
571 | __get_cpu_var(no_cfg_addr)++; | ||
558 | return 0; | 572 | return 0; |
559 | } | 573 | } |
560 | 574 | ||
561 | /* | 575 | /* If we already have a pending isolation event for this |
562 | * If we already have a pending isolation event for this | 576 | * slot, we know it's bad already, we don't need to check. |
563 | * slot, we know it's bad already, we don't need to check... | 577 | * Do this checking under a lock; as multiple PCI devices |
578 | * in one slot might report errors simultaneously, and we | ||
579 | * only want one error recovery routine running. | ||
564 | */ | 580 | */ |
581 | spin_lock_irqsave(&confirm_error_lock, flags); | ||
582 | rc = 1; | ||
565 | if (pdn->eeh_mode & EEH_MODE_ISOLATED) { | 583 | if (pdn->eeh_mode & EEH_MODE_ISOLATED) { |
566 | atomic_inc(&eeh_fail_count); | 584 | pdn->eeh_check_count ++; |
567 | if (atomic_read(&eeh_fail_count) >= EEH_MAX_FAILS) { | 585 | if (pdn->eeh_check_count >= EEH_MAX_FAILS) { |
586 | printk (KERN_ERR "EEH: Device driver ignored %d bad reads, panicing\n", | ||
587 | pdn->eeh_check_count); | ||
588 | dump_stack(); | ||
589 | |||
568 | /* re-read the slot reset state */ | 590 | /* re-read the slot reset state */ |
569 | if (read_slot_reset_state(dn, rets) != 0) | 591 | if (read_slot_reset_state(pdn, rets) != 0) |
570 | rets[0] = -1; /* reset state unknown */ | 592 | rets[0] = -1; /* reset state unknown */ |
571 | eeh_panic(dev, rets[0]); | 593 | |
594 | /* If we are here, then we hit an infinite loop. Stop. */ | ||
595 | panic("EEH: MMIO halt (%d) on device:%s\n", rets[0], pci_name(dev)); | ||
572 | } | 596 | } |
573 | return 0; | 597 | goto dn_unlock; |
574 | } | 598 | } |
575 | 599 | ||
576 | /* | 600 | /* |
@@ -580,66 +604,69 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) | |||
580 | * function zero of a multi-function device. | 604 | * function zero of a multi-function device. |
581 | * In any case they must share a common PHB. | 605 | * In any case they must share a common PHB. |
582 | */ | 606 | */ |
583 | ret = read_slot_reset_state(dn, rets); | 607 | ret = read_slot_reset_state(pdn, rets); |
584 | if (!(ret == 0 && rets[1] == 1 && (rets[0] == 2 || rets[0] == 4))) { | 608 | |
609 | /* If the call to firmware failed, punt */ | ||
610 | if (ret != 0) { | ||
611 | printk(KERN_WARNING "EEH: read_slot_reset_state() failed; rc=%d dn=%s\n", | ||
612 | ret, dn->full_name); | ||
585 | __get_cpu_var(false_positives)++; | 613 | __get_cpu_var(false_positives)++; |
586 | return 0; | 614 | rc = 0; |
615 | goto dn_unlock; | ||
587 | } | 616 | } |
588 | 617 | ||
589 | /* prevent repeated reports of this failure */ | 618 | /* If EEH is not supported on this device, punt. */ |
590 | pdn->eeh_mode |= EEH_MODE_ISOLATED; | 619 | if (rets[1] != 1) { |
591 | 620 | printk(KERN_WARNING "EEH: event on unsupported device, rc=%d dn=%s\n", | |
592 | reset_state = rets[0]; | 621 | ret, dn->full_name); |
593 | 622 | __get_cpu_var(false_positives)++; | |
594 | spin_lock_irqsave(&slot_errbuf_lock, flags); | 623 | rc = 0; |
595 | memset(slot_errbuf, 0, eeh_error_buf_size); | 624 | goto dn_unlock; |
596 | 625 | } | |
597 | rc = rtas_call(ibm_slot_error_detail, | ||
598 | 8, 1, NULL, pdn->eeh_config_addr, | ||
599 | BUID_HI(pdn->phb->buid), | ||
600 | BUID_LO(pdn->phb->buid), NULL, 0, | ||
601 | virt_to_phys(slot_errbuf), | ||
602 | eeh_error_buf_size, | ||
603 | 1 /* Temporary Error */); | ||
604 | |||
605 | if (rc == 0) | ||
606 | log_error(slot_errbuf, ERR_TYPE_RTAS_LOG, 0); | ||
607 | spin_unlock_irqrestore(&slot_errbuf_lock, flags); | ||
608 | 626 | ||
609 | printk(KERN_INFO "EEH: MMIO failure (%d) on device: %s %s\n", | 627 | /* If not the kind of error we know about, punt. */ |
610 | rets[0], dn->name, dn->full_name); | 628 | if (rets[0] != 2 && rets[0] != 4 && rets[0] != 5) { |
611 | event = kmalloc(sizeof(*event), GFP_ATOMIC); | 629 | __get_cpu_var(false_positives)++; |
612 | if (event == NULL) { | 630 | rc = 0; |
613 | eeh_panic(dev, reset_state); | 631 | goto dn_unlock; |
614 | return 1; | 632 | } |
615 | } | ||
616 | 633 | ||
617 | event->dev = dev; | 634 | /* Note that config-io to empty slots may fail; |
618 | event->dn = dn; | 635 | * we recognize empty because they don't have children. */ |
619 | event->reset_state = reset_state; | 636 | if ((rets[0] == 5) && (dn->child == NULL)) { |
637 | __get_cpu_var(false_positives)++; | ||
638 | rc = 0; | ||
639 | goto dn_unlock; | ||
640 | } | ||
620 | 641 | ||
621 | /* We may or may not be called in an interrupt context */ | 642 | __get_cpu_var(slot_resets)++; |
622 | spin_lock_irqsave(&eeh_eventlist_lock, flags); | 643 | |
623 | list_add(&event->list, &eeh_eventlist); | 644 | /* Avoid repeated reports of this failure, including problems |
624 | spin_unlock_irqrestore(&eeh_eventlist_lock, flags); | 645 | * with other functions on this device, and functions under |
646 | * bridges. */ | ||
647 | eeh_mark_slot (dn, EEH_MODE_ISOLATED); | ||
648 | spin_unlock_irqrestore(&confirm_error_lock, flags); | ||
625 | 649 | ||
650 | eeh_send_failure_event (dn, dev, rets[0], rets[2]); | ||
651 | |||
626 | /* Most EEH events are due to device driver bugs. Having | 652 | /* Most EEH events are due to device driver bugs. Having |
627 | * a stack trace will help the device-driver authors figure | 653 | * a stack trace will help the device-driver authors figure |
628 | * out what happened. So print that out. */ | 654 | * out what happened. So print that out. */ |
629 | dump_stack(); | 655 | if (rets[0] != 5) dump_stack(); |
630 | schedule_work(&eeh_event_wq); | 656 | return 1; |
631 | 657 | ||
632 | return 0; | 658 | dn_unlock: |
659 | spin_unlock_irqrestore(&confirm_error_lock, flags); | ||
660 | return rc; | ||
633 | } | 661 | } |
634 | 662 | ||
635 | EXPORT_SYMBOL(eeh_dn_check_failure); | 663 | EXPORT_SYMBOL_GPL(eeh_dn_check_failure); |
636 | 664 | ||
637 | /** | 665 | /** |
638 | * eeh_check_failure - check if all 1's data is due to EEH slot freeze | 666 | * eeh_check_failure - check if all 1's data is due to EEH slot freeze |
639 | * @token i/o token, should be address in the form 0xA.... | 667 | * @token i/o token, should be address in the form 0xA.... |
640 | * @val value, should be all 1's (XXX why do we need this arg??) | 668 | * @val value, should be all 1's (XXX why do we need this arg??) |
641 | * | 669 | * |
642 | * Check for an eeh failure at the given token address. | ||
643 | * Check for an EEH failure at the given token address. Call this | 670 | * Check for an EEH failure at the given token address. Call this |
644 | * routine if the result of a read was all 0xff's and you want to | 671 | * routine if the result of a read was all 0xff's and you want to |
645 | * find out if this is due to an EEH slot freeze event. This routine | 672 | * find out if this is due to an EEH slot freeze event. This routine |
@@ -656,8 +683,10 @@ unsigned long eeh_check_failure(const volatile void __iomem *token, unsigned lon | |||
656 | /* Finding the phys addr + pci device; this is pretty quick. */ | 683 | /* Finding the phys addr + pci device; this is pretty quick. */ |
657 | addr = eeh_token_to_phys((unsigned long __force) token); | 684 | addr = eeh_token_to_phys((unsigned long __force) token); |
658 | dev = pci_get_device_by_addr(addr); | 685 | dev = pci_get_device_by_addr(addr); |
659 | if (!dev) | 686 | if (!dev) { |
687 | __get_cpu_var(no_device)++; | ||
660 | return val; | 688 | return val; |
689 | } | ||
661 | 690 | ||
662 | dn = pci_device_to_OF_node(dev); | 691 | dn = pci_device_to_OF_node(dev); |
663 | eeh_dn_check_failure (dn, dev); | 692 | eeh_dn_check_failure (dn, dev); |
@@ -668,6 +697,217 @@ unsigned long eeh_check_failure(const volatile void __iomem *token, unsigned lon | |||
668 | 697 | ||
669 | EXPORT_SYMBOL(eeh_check_failure); | 698 | EXPORT_SYMBOL(eeh_check_failure); |
670 | 699 | ||
700 | /* ------------------------------------------------------------- */ | ||
701 | /* The code below deals with error recovery */ | ||
702 | |||
703 | /** Return negative value if a permanent error, else return | ||
704 | * a number of milliseconds to wait until the PCI slot is | ||
705 | * ready to be used. | ||
706 | */ | ||
707 | static int | ||
708 | eeh_slot_availability(struct pci_dn *pdn) | ||
709 | { | ||
710 | int rc; | ||
711 | int rets[3]; | ||
712 | |||
713 | rc = read_slot_reset_state(pdn, rets); | ||
714 | |||
715 | if (rc) return rc; | ||
716 | |||
717 | if (rets[1] == 0) return -1; /* EEH is not supported */ | ||
718 | if (rets[0] == 0) return 0; /* Oll Korrect */ | ||
719 | if (rets[0] == 5) { | ||
720 | if (rets[2] == 0) return -1; /* permanently unavailable */ | ||
721 | return rets[2]; /* number of millisecs to wait */ | ||
722 | } | ||
723 | return -1; | ||
724 | } | ||
725 | |||
726 | /** rtas_pci_slot_reset raises/lowers the pci #RST line | ||
727 | * state: 1/0 to raise/lower the #RST | ||
728 | * | ||
729 | * Clear the EEH-frozen condition on a slot. This routine | ||
730 | * asserts the PCI #RST line if the 'state' argument is '1', | ||
731 | * and drops the #RST line if 'state is '0'. This routine is | ||
732 | * safe to call in an interrupt context. | ||
733 | * | ||
734 | */ | ||
735 | |||
736 | static void | ||
737 | rtas_pci_slot_reset(struct pci_dn *pdn, int state) | ||
738 | { | ||
739 | int rc; | ||
740 | |||
741 | BUG_ON (pdn==NULL); | ||
742 | |||
743 | if (!pdn->phb) { | ||
744 | printk (KERN_WARNING "EEH: in slot reset, device node %s has no phb\n", | ||
745 | pdn->node->full_name); | ||
746 | return; | ||
747 | } | ||
748 | |||
749 | rc = rtas_call(ibm_set_slot_reset,4,1, NULL, | ||
750 | pdn->eeh_config_addr, | ||
751 | BUID_HI(pdn->phb->buid), | ||
752 | BUID_LO(pdn->phb->buid), | ||
753 | state); | ||
754 | if (rc) { | ||
755 | printk (KERN_WARNING "EEH: Unable to reset the failed slot, (%d) #RST=%d dn=%s\n", | ||
756 | rc, state, pdn->node->full_name); | ||
757 | return; | ||
758 | } | ||
759 | } | ||
760 | |||
761 | /** rtas_set_slot_reset -- assert the pci #RST line for 1/4 second | ||
762 | * dn -- device node to be reset. | ||
763 | */ | ||
764 | |||
765 | void | ||
766 | rtas_set_slot_reset(struct pci_dn *pdn) | ||
767 | { | ||
768 | int i, rc; | ||
769 | |||
770 | rtas_pci_slot_reset (pdn, 1); | ||
771 | |||
772 | /* The PCI bus requires that the reset be held high for at least | ||
773 | * a 100 milliseconds. We wait a bit longer 'just in case'. */ | ||
774 | |||
775 | #define PCI_BUS_RST_HOLD_TIME_MSEC 250 | ||
776 | msleep (PCI_BUS_RST_HOLD_TIME_MSEC); | ||
777 | |||
778 | /* We might get hit with another EEH freeze as soon as the | ||
779 | * pci slot reset line is dropped. Make sure we don't miss | ||
780 | * these, and clear the flag now. */ | ||
781 | eeh_clear_slot (pdn->node, EEH_MODE_ISOLATED); | ||
782 | |||
783 | rtas_pci_slot_reset (pdn, 0); | ||
784 | |||
785 | /* After a PCI slot has been reset, the PCI Express spec requires | ||
786 | * a 1.5 second idle time for the bus to stabilize, before starting | ||
787 | * up traffic. */ | ||
788 | #define PCI_BUS_SETTLE_TIME_MSEC 1800 | ||
789 | msleep (PCI_BUS_SETTLE_TIME_MSEC); | ||
790 | |||
791 | /* Now double check with the firmware to make sure the device is | ||
792 | * ready to be used; if not, wait for recovery. */ | ||
793 | for (i=0; i<10; i++) { | ||
794 | rc = eeh_slot_availability (pdn); | ||
795 | if (rc <= 0) break; | ||
796 | |||
797 | msleep (rc+100); | ||
798 | } | ||
799 | } | ||
800 | |||
801 | /* ------------------------------------------------------- */ | ||
802 | /** Save and restore of PCI BARs | ||
803 | * | ||
804 | * Although firmware will set up BARs during boot, it doesn't | ||
805 | * set up device BAR's after a device reset, although it will, | ||
806 | * if requested, set up bridge configuration. Thus, we need to | ||
807 | * configure the PCI devices ourselves. | ||
808 | */ | ||
809 | |||
810 | /** | ||
811 | * __restore_bars - Restore the Base Address Registers | ||
812 | * Loads the PCI configuration space base address registers, | ||
813 | * the expansion ROM base address, the latency timer, and etc. | ||
814 | * from the saved values in the device node. | ||
815 | */ | ||
816 | static inline void __restore_bars (struct pci_dn *pdn) | ||
817 | { | ||
818 | int i; | ||
819 | |||
820 | if (NULL==pdn->phb) return; | ||
821 | for (i=4; i<10; i++) { | ||
822 | rtas_write_config(pdn, i*4, 4, pdn->config_space[i]); | ||
823 | } | ||
824 | |||
825 | /* 12 == Expansion ROM Address */ | ||
826 | rtas_write_config(pdn, 12*4, 4, pdn->config_space[12]); | ||
827 | |||
828 | #define BYTE_SWAP(OFF) (8*((OFF)/4)+3-(OFF)) | ||
829 | #define SAVED_BYTE(OFF) (((u8 *)(pdn->config_space))[BYTE_SWAP(OFF)]) | ||
830 | |||
831 | rtas_write_config (pdn, PCI_CACHE_LINE_SIZE, 1, | ||
832 | SAVED_BYTE(PCI_CACHE_LINE_SIZE)); | ||
833 | |||
834 | rtas_write_config (pdn, PCI_LATENCY_TIMER, 1, | ||
835 | SAVED_BYTE(PCI_LATENCY_TIMER)); | ||
836 | |||
837 | /* max latency, min grant, interrupt pin and line */ | ||
838 | rtas_write_config(pdn, 15*4, 4, pdn->config_space[15]); | ||
839 | } | ||
840 | |||
841 | /** | ||
842 | * eeh_restore_bars - restore the PCI config space info | ||
843 | * | ||
844 | * This routine performs a recursive walk to the children | ||
845 | * of this device as well. | ||
846 | */ | ||
847 | void eeh_restore_bars(struct pci_dn *pdn) | ||
848 | { | ||
849 | struct device_node *dn; | ||
850 | if (!pdn) | ||
851 | return; | ||
852 | |||
853 | if (! pdn->eeh_is_bridge) | ||
854 | __restore_bars (pdn); | ||
855 | |||
856 | dn = pdn->node->child; | ||
857 | while (dn) { | ||
858 | eeh_restore_bars (PCI_DN(dn)); | ||
859 | dn = dn->sibling; | ||
860 | } | ||
861 | } | ||
862 | |||
863 | /** | ||
864 | * eeh_save_bars - save device bars | ||
865 | * | ||
866 | * Save the values of the device bars. Unlike the restore | ||
867 | * routine, this routine is *not* recursive. This is because | ||
868 | * PCI devices are added individuallly; but, for the restore, | ||
869 | * an entire slot is reset at a time. | ||
870 | */ | ||
871 | static void eeh_save_bars(struct pci_dev * pdev, struct pci_dn *pdn) | ||
872 | { | ||
873 | int i; | ||
874 | |||
875 | if (!pdev || !pdn ) | ||
876 | return; | ||
877 | |||
878 | for (i = 0; i < 16; i++) | ||
879 | pci_read_config_dword(pdev, i * 4, &pdn->config_space[i]); | ||
880 | |||
881 | if (pdev->hdr_type == PCI_HEADER_TYPE_BRIDGE) | ||
882 | pdn->eeh_is_bridge = 1; | ||
883 | } | ||
884 | |||
885 | void | ||
886 | rtas_configure_bridge(struct pci_dn *pdn) | ||
887 | { | ||
888 | int token = rtas_token ("ibm,configure-bridge"); | ||
889 | int rc; | ||
890 | |||
891 | if (token == RTAS_UNKNOWN_SERVICE) | ||
892 | return; | ||
893 | rc = rtas_call(token,3,1, NULL, | ||
894 | pdn->eeh_config_addr, | ||
895 | BUID_HI(pdn->phb->buid), | ||
896 | BUID_LO(pdn->phb->buid)); | ||
897 | if (rc) { | ||
898 | printk (KERN_WARNING "EEH: Unable to configure device bridge (%d) for %s\n", | ||
899 | rc, pdn->node->full_name); | ||
900 | } | ||
901 | } | ||
902 | |||
903 | /* ------------------------------------------------------------- */ | ||
904 | /* The code below deals with enabling EEH for devices during the | ||
905 | * early boot sequence. EEH must be enabled before any PCI probing | ||
906 | * can be done. | ||
907 | */ | ||
908 | |||
909 | #define EEH_ENABLE 1 | ||
910 | |||
671 | struct eeh_early_enable_info { | 911 | struct eeh_early_enable_info { |
672 | unsigned int buid_hi; | 912 | unsigned int buid_hi; |
673 | unsigned int buid_lo; | 913 | unsigned int buid_lo; |
@@ -684,9 +924,11 @@ static void *early_enable_eeh(struct device_node *dn, void *data) | |||
684 | u32 *device_id = (u32 *)get_property(dn, "device-id", NULL); | 924 | u32 *device_id = (u32 *)get_property(dn, "device-id", NULL); |
685 | u32 *regs; | 925 | u32 *regs; |
686 | int enable; | 926 | int enable; |
687 | struct pci_dn *pdn = dn->data; | 927 | struct pci_dn *pdn = PCI_DN(dn); |
688 | 928 | ||
689 | pdn->eeh_mode = 0; | 929 | pdn->eeh_mode = 0; |
930 | pdn->eeh_check_count = 0; | ||
931 | pdn->eeh_freeze_count = 0; | ||
690 | 932 | ||
691 | if (status && strcmp(status, "ok") != 0) | 933 | if (status && strcmp(status, "ok") != 0) |
692 | return NULL; /* ignore devices with bad status */ | 934 | return NULL; /* ignore devices with bad status */ |
@@ -723,8 +965,9 @@ static void *early_enable_eeh(struct device_node *dn, void *data) | |||
723 | /* First register entry is addr (00BBSS00) */ | 965 | /* First register entry is addr (00BBSS00) */ |
724 | /* Try to enable eeh */ | 966 | /* Try to enable eeh */ |
725 | ret = rtas_call(ibm_set_eeh_option, 4, 1, NULL, | 967 | ret = rtas_call(ibm_set_eeh_option, 4, 1, NULL, |
726 | regs[0], info->buid_hi, info->buid_lo, | 968 | regs[0], info->buid_hi, info->buid_lo, |
727 | EEH_ENABLE); | 969 | EEH_ENABLE); |
970 | |||
728 | if (ret == 0) { | 971 | if (ret == 0) { |
729 | eeh_subsystem_enabled = 1; | 972 | eeh_subsystem_enabled = 1; |
730 | pdn->eeh_mode |= EEH_MODE_SUPPORTED; | 973 | pdn->eeh_mode |= EEH_MODE_SUPPORTED; |
@@ -736,7 +979,7 @@ static void *early_enable_eeh(struct device_node *dn, void *data) | |||
736 | 979 | ||
737 | /* This device doesn't support EEH, but it may have an | 980 | /* This device doesn't support EEH, but it may have an |
738 | * EEH parent, in which case we mark it as supported. */ | 981 | * EEH parent, in which case we mark it as supported. */ |
739 | if (dn->parent && dn->parent->data | 982 | if (dn->parent && PCI_DN(dn->parent) |
740 | && (PCI_DN(dn->parent)->eeh_mode & EEH_MODE_SUPPORTED)) { | 983 | && (PCI_DN(dn->parent)->eeh_mode & EEH_MODE_SUPPORTED)) { |
741 | /* Parent supports EEH. */ | 984 | /* Parent supports EEH. */ |
742 | pdn->eeh_mode |= EEH_MODE_SUPPORTED; | 985 | pdn->eeh_mode |= EEH_MODE_SUPPORTED; |
@@ -749,7 +992,7 @@ static void *early_enable_eeh(struct device_node *dn, void *data) | |||
749 | dn->full_name); | 992 | dn->full_name); |
750 | } | 993 | } |
751 | 994 | ||
752 | return NULL; | 995 | return NULL; |
753 | } | 996 | } |
754 | 997 | ||
755 | /* | 998 | /* |
@@ -770,6 +1013,9 @@ void __init eeh_init(void) | |||
770 | struct device_node *phb, *np; | 1013 | struct device_node *phb, *np; |
771 | struct eeh_early_enable_info info; | 1014 | struct eeh_early_enable_info info; |
772 | 1015 | ||
1016 | spin_lock_init(&confirm_error_lock); | ||
1017 | spin_lock_init(&slot_errbuf_lock); | ||
1018 | |||
773 | np = of_find_node_by_path("/rtas"); | 1019 | np = of_find_node_by_path("/rtas"); |
774 | if (np == NULL) | 1020 | if (np == NULL) |
775 | return; | 1021 | return; |
@@ -797,13 +1043,11 @@ void __init eeh_init(void) | |||
797 | for (phb = of_find_node_by_name(NULL, "pci"); phb; | 1043 | for (phb = of_find_node_by_name(NULL, "pci"); phb; |
798 | phb = of_find_node_by_name(phb, "pci")) { | 1044 | phb = of_find_node_by_name(phb, "pci")) { |
799 | unsigned long buid; | 1045 | unsigned long buid; |
800 | struct pci_dn *pci; | ||
801 | 1046 | ||
802 | buid = get_phb_buid(phb); | 1047 | buid = get_phb_buid(phb); |
803 | if (buid == 0 || phb->data == NULL) | 1048 | if (buid == 0 || PCI_DN(phb) == NULL) |
804 | continue; | 1049 | continue; |
805 | 1050 | ||
806 | pci = phb->data; | ||
807 | info.buid_lo = BUID_LO(buid); | 1051 | info.buid_lo = BUID_LO(buid); |
808 | info.buid_hi = BUID_HI(buid); | 1052 | info.buid_hi = BUID_HI(buid); |
809 | traverse_pci_devices(phb, early_enable_eeh, &info); | 1053 | traverse_pci_devices(phb, early_enable_eeh, &info); |
@@ -832,11 +1076,13 @@ void eeh_add_device_early(struct device_node *dn) | |||
832 | struct pci_controller *phb; | 1076 | struct pci_controller *phb; |
833 | struct eeh_early_enable_info info; | 1077 | struct eeh_early_enable_info info; |
834 | 1078 | ||
835 | if (!dn || !dn->data) | 1079 | if (!dn || !PCI_DN(dn)) |
836 | return; | 1080 | return; |
837 | phb = PCI_DN(dn)->phb; | 1081 | phb = PCI_DN(dn)->phb; |
838 | if (NULL == phb || 0 == phb->buid) { | 1082 | if (NULL == phb || 0 == phb->buid) { |
839 | printk(KERN_WARNING "EEH: Expected buid but found none\n"); | 1083 | printk(KERN_WARNING "EEH: Expected buid but found none for %s\n", |
1084 | dn->full_name); | ||
1085 | dump_stack(); | ||
840 | return; | 1086 | return; |
841 | } | 1087 | } |
842 | 1088 | ||
@@ -844,7 +1090,7 @@ void eeh_add_device_early(struct device_node *dn) | |||
844 | info.buid_lo = BUID_LO(phb->buid); | 1090 | info.buid_lo = BUID_LO(phb->buid); |
845 | early_enable_eeh(dn, &info); | 1091 | early_enable_eeh(dn, &info); |
846 | } | 1092 | } |
847 | EXPORT_SYMBOL(eeh_add_device_early); | 1093 | EXPORT_SYMBOL_GPL(eeh_add_device_early); |
848 | 1094 | ||
849 | /** | 1095 | /** |
850 | * eeh_add_device_late - perform EEH initialization for the indicated pci device | 1096 | * eeh_add_device_late - perform EEH initialization for the indicated pci device |
@@ -855,6 +1101,9 @@ EXPORT_SYMBOL(eeh_add_device_early); | |||
855 | */ | 1101 | */ |
856 | void eeh_add_device_late(struct pci_dev *dev) | 1102 | void eeh_add_device_late(struct pci_dev *dev) |
857 | { | 1103 | { |
1104 | struct device_node *dn; | ||
1105 | struct pci_dn *pdn; | ||
1106 | |||
858 | if (!dev || !eeh_subsystem_enabled) | 1107 | if (!dev || !eeh_subsystem_enabled) |
859 | return; | 1108 | return; |
860 | 1109 | ||
@@ -862,9 +1111,15 @@ void eeh_add_device_late(struct pci_dev *dev) | |||
862 | printk(KERN_DEBUG "EEH: adding device %s\n", pci_name(dev)); | 1111 | printk(KERN_DEBUG "EEH: adding device %s\n", pci_name(dev)); |
863 | #endif | 1112 | #endif |
864 | 1113 | ||
1114 | pci_dev_get (dev); | ||
1115 | dn = pci_device_to_OF_node(dev); | ||
1116 | pdn = PCI_DN(dn); | ||
1117 | pdn->pcidev = dev; | ||
1118 | |||
865 | pci_addr_cache_insert_device (dev); | 1119 | pci_addr_cache_insert_device (dev); |
1120 | eeh_save_bars(dev, pdn); | ||
866 | } | 1121 | } |
867 | EXPORT_SYMBOL(eeh_add_device_late); | 1122 | EXPORT_SYMBOL_GPL(eeh_add_device_late); |
868 | 1123 | ||
869 | /** | 1124 | /** |
870 | * eeh_remove_device - undo EEH setup for the indicated pci device | 1125 | * eeh_remove_device - undo EEH setup for the indicated pci device |
@@ -875,6 +1130,7 @@ EXPORT_SYMBOL(eeh_add_device_late); | |||
875 | */ | 1130 | */ |
876 | void eeh_remove_device(struct pci_dev *dev) | 1131 | void eeh_remove_device(struct pci_dev *dev) |
877 | { | 1132 | { |
1133 | struct device_node *dn; | ||
878 | if (!dev || !eeh_subsystem_enabled) | 1134 | if (!dev || !eeh_subsystem_enabled) |
879 | return; | 1135 | return; |
880 | 1136 | ||
@@ -883,20 +1139,29 @@ void eeh_remove_device(struct pci_dev *dev) | |||
883 | printk(KERN_DEBUG "EEH: remove device %s\n", pci_name(dev)); | 1139 | printk(KERN_DEBUG "EEH: remove device %s\n", pci_name(dev)); |
884 | #endif | 1140 | #endif |
885 | pci_addr_cache_remove_device(dev); | 1141 | pci_addr_cache_remove_device(dev); |
1142 | |||
1143 | dn = pci_device_to_OF_node(dev); | ||
1144 | PCI_DN(dn)->pcidev = NULL; | ||
1145 | pci_dev_put (dev); | ||
886 | } | 1146 | } |
887 | EXPORT_SYMBOL(eeh_remove_device); | 1147 | EXPORT_SYMBOL_GPL(eeh_remove_device); |
888 | 1148 | ||
889 | static int proc_eeh_show(struct seq_file *m, void *v) | 1149 | static int proc_eeh_show(struct seq_file *m, void *v) |
890 | { | 1150 | { |
891 | unsigned int cpu; | 1151 | unsigned int cpu; |
892 | unsigned long ffs = 0, positives = 0, failures = 0; | 1152 | unsigned long ffs = 0, positives = 0, failures = 0; |
893 | unsigned long resets = 0; | 1153 | unsigned long resets = 0; |
1154 | unsigned long no_dev = 0, no_dn = 0, no_cfg = 0, no_check = 0; | ||
894 | 1155 | ||
895 | for_each_cpu(cpu) { | 1156 | for_each_cpu(cpu) { |
896 | ffs += per_cpu(total_mmio_ffs, cpu); | 1157 | ffs += per_cpu(total_mmio_ffs, cpu); |
897 | positives += per_cpu(false_positives, cpu); | 1158 | positives += per_cpu(false_positives, cpu); |
898 | failures += per_cpu(ignored_failures, cpu); | 1159 | failures += per_cpu(ignored_failures, cpu); |
899 | resets += per_cpu(slot_resets, cpu); | 1160 | resets += per_cpu(slot_resets, cpu); |
1161 | no_dev += per_cpu(no_device, cpu); | ||
1162 | no_dn += per_cpu(no_dn, cpu); | ||
1163 | no_cfg += per_cpu(no_cfg_addr, cpu); | ||
1164 | no_check += per_cpu(ignored_check, cpu); | ||
900 | } | 1165 | } |
901 | 1166 | ||
902 | if (0 == eeh_subsystem_enabled) { | 1167 | if (0 == eeh_subsystem_enabled) { |
@@ -904,13 +1169,17 @@ static int proc_eeh_show(struct seq_file *m, void *v) | |||
904 | seq_printf(m, "eeh_total_mmio_ffs=%ld\n", ffs); | 1169 | seq_printf(m, "eeh_total_mmio_ffs=%ld\n", ffs); |
905 | } else { | 1170 | } else { |
906 | seq_printf(m, "EEH Subsystem is enabled\n"); | 1171 | seq_printf(m, "EEH Subsystem is enabled\n"); |
907 | seq_printf(m, "eeh_total_mmio_ffs=%ld\n" | 1172 | seq_printf(m, |
908 | "eeh_false_positives=%ld\n" | 1173 | "no device=%ld\n" |
909 | "eeh_ignored_failures=%ld\n" | 1174 | "no device node=%ld\n" |
910 | "eeh_slot_resets=%ld\n" | 1175 | "no config address=%ld\n" |
911 | "eeh_fail_count=%d\n", | 1176 | "check not wanted=%ld\n" |
912 | ffs, positives, failures, resets, | 1177 | "eeh_total_mmio_ffs=%ld\n" |
913 | eeh_fail_count.counter); | 1178 | "eeh_false_positives=%ld\n" |
1179 | "eeh_ignored_failures=%ld\n" | ||
1180 | "eeh_slot_resets=%ld\n", | ||
1181 | no_dev, no_dn, no_cfg, no_check, | ||
1182 | ffs, positives, failures, resets); | ||
914 | } | 1183 | } |
915 | 1184 | ||
916 | return 0; | 1185 | return 0; |
@@ -932,7 +1201,7 @@ static int __init eeh_init_proc(void) | |||
932 | { | 1201 | { |
933 | struct proc_dir_entry *e; | 1202 | struct proc_dir_entry *e; |
934 | 1203 | ||
935 | if (systemcfg->platform & PLATFORM_PSERIES) { | 1204 | if (platform_is_pseries()) { |
936 | e = create_proc_entry("ppc64/eeh", 0, NULL); | 1205 | e = create_proc_entry("ppc64/eeh", 0, NULL); |
937 | if (e) | 1206 | if (e) |
938 | e->proc_fops = &proc_eeh_operations; | 1207 | e->proc_fops = &proc_eeh_operations; |
diff --git a/arch/powerpc/platforms/pseries/eeh_event.c b/arch/powerpc/platforms/pseries/eeh_event.c new file mode 100644 index 000000000000..92497333c2b6 --- /dev/null +++ b/arch/powerpc/platforms/pseries/eeh_event.c | |||
@@ -0,0 +1,155 @@ | |||
1 | /* | ||
2 | * eeh_event.c | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
17 | * | ||
18 | * Copyright (c) 2005 Linas Vepstas <linas@linas.org> | ||
19 | */ | ||
20 | |||
21 | #include <linux/list.h> | ||
22 | #include <linux/pci.h> | ||
23 | #include <asm/eeh_event.h> | ||
24 | |||
25 | /** Overview: | ||
26 | * EEH error states may be detected within exception handlers; | ||
27 | * however, the recovery processing needs to occur asynchronously | ||
28 | * in a normal kernel context and not an interrupt context. | ||
29 | * This pair of routines creates an event and queues it onto a | ||
30 | * work-queue, where a worker thread can drive recovery. | ||
31 | */ | ||
32 | |||
33 | /* EEH event workqueue setup. */ | ||
34 | static spinlock_t eeh_eventlist_lock = SPIN_LOCK_UNLOCKED; | ||
35 | LIST_HEAD(eeh_eventlist); | ||
36 | static void eeh_thread_launcher(void *); | ||
37 | DECLARE_WORK(eeh_event_wq, eeh_thread_launcher, NULL); | ||
38 | |||
39 | /** | ||
40 | * eeh_panic - call panic() for an eeh event that cannot be handled. | ||
41 | * The philosophy of this routine is that it is better to panic and | ||
42 | * halt the OS than it is to risk possible data corruption by | ||
43 | * oblivious device drivers that don't know better. | ||
44 | * | ||
45 | * @dev pci device that had an eeh event | ||
46 | * @reset_state current reset state of the device slot | ||
47 | */ | ||
48 | static void eeh_panic(struct pci_dev *dev, int reset_state) | ||
49 | { | ||
50 | /* | ||
51 | * Since the panic_on_oops sysctl is used to halt the system | ||
52 | * in light of potential corruption, we can use it here. | ||
53 | */ | ||
54 | if (panic_on_oops) { | ||
55 | panic("EEH: MMIO failure (%d) on device:%s\n", reset_state, | ||
56 | pci_name(dev)); | ||
57 | } | ||
58 | else { | ||
59 | printk(KERN_INFO "EEH: Ignored MMIO failure (%d) on device:%s\n", | ||
60 | reset_state, pci_name(dev)); | ||
61 | } | ||
62 | } | ||
63 | |||
64 | /** | ||
65 | * eeh_event_handler - dispatch EEH events. The detection of a frozen | ||
66 | * slot can occur inside an interrupt, where it can be hard to do | ||
67 | * anything about it. The goal of this routine is to pull these | ||
68 | * detection events out of the context of the interrupt handler, and | ||
69 | * re-dispatch them for processing at a later time in a normal context. | ||
70 | * | ||
71 | * @dummy - unused | ||
72 | */ | ||
73 | static int eeh_event_handler(void * dummy) | ||
74 | { | ||
75 | unsigned long flags; | ||
76 | struct eeh_event *event; | ||
77 | |||
78 | daemonize ("eehd"); | ||
79 | |||
80 | while (1) { | ||
81 | set_current_state(TASK_INTERRUPTIBLE); | ||
82 | |||
83 | spin_lock_irqsave(&eeh_eventlist_lock, flags); | ||
84 | event = NULL; | ||
85 | if (!list_empty(&eeh_eventlist)) { | ||
86 | event = list_entry(eeh_eventlist.next, struct eeh_event, list); | ||
87 | list_del(&event->list); | ||
88 | } | ||
89 | spin_unlock_irqrestore(&eeh_eventlist_lock, flags); | ||
90 | if (event == NULL) | ||
91 | break; | ||
92 | |||
93 | printk(KERN_INFO "EEH: Detected PCI bus error on device %s\n", | ||
94 | pci_name(event->dev)); | ||
95 | |||
96 | eeh_panic (event->dev, event->state); | ||
97 | |||
98 | kfree(event); | ||
99 | } | ||
100 | |||
101 | return 0; | ||
102 | } | ||
103 | |||
104 | /** | ||
105 | * eeh_thread_launcher | ||
106 | * | ||
107 | * @dummy - unused | ||
108 | */ | ||
109 | static void eeh_thread_launcher(void *dummy) | ||
110 | { | ||
111 | if (kernel_thread(eeh_event_handler, NULL, CLONE_KERNEL) < 0) | ||
112 | printk(KERN_ERR "Failed to start EEH daemon\n"); | ||
113 | } | ||
114 | |||
115 | /** | ||
116 | * eeh_send_failure_event - generate a PCI error event | ||
117 | * @dev pci device | ||
118 | * | ||
119 | * This routine can be called within an interrupt context; | ||
120 | * the actual event will be delivered in a normal context | ||
121 | * (from a workqueue). | ||
122 | */ | ||
123 | int eeh_send_failure_event (struct device_node *dn, | ||
124 | struct pci_dev *dev, | ||
125 | int state, | ||
126 | int time_unavail) | ||
127 | { | ||
128 | unsigned long flags; | ||
129 | struct eeh_event *event; | ||
130 | |||
131 | event = kmalloc(sizeof(*event), GFP_ATOMIC); | ||
132 | if (event == NULL) { | ||
133 | printk (KERN_ERR "EEH: out of memory, event not handled\n"); | ||
134 | return 1; | ||
135 | } | ||
136 | |||
137 | if (dev) | ||
138 | pci_dev_get(dev); | ||
139 | |||
140 | event->dn = dn; | ||
141 | event->dev = dev; | ||
142 | event->state = state; | ||
143 | event->time_unavail = time_unavail; | ||
144 | |||
145 | /* We may or may not be called in an interrupt context */ | ||
146 | spin_lock_irqsave(&eeh_eventlist_lock, flags); | ||
147 | list_add(&event->list, &eeh_eventlist); | ||
148 | spin_unlock_irqrestore(&eeh_eventlist_lock, flags); | ||
149 | |||
150 | schedule_work(&eeh_event_wq); | ||
151 | |||
152 | return 0; | ||
153 | } | ||
154 | |||
155 | /********************** END OF FILE ******************************/ | ||
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index fcc50bfd43fd..97ba5214417f 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c | |||
@@ -42,7 +42,6 @@ | |||
42 | #include <asm/machdep.h> | 42 | #include <asm/machdep.h> |
43 | #include <asm/abs_addr.h> | 43 | #include <asm/abs_addr.h> |
44 | #include <asm/pSeries_reconfig.h> | 44 | #include <asm/pSeries_reconfig.h> |
45 | #include <asm/systemcfg.h> | ||
46 | #include <asm/firmware.h> | 45 | #include <asm/firmware.h> |
47 | #include <asm/tce.h> | 46 | #include <asm/tce.h> |
48 | #include <asm/ppc-pci.h> | 47 | #include <asm/ppc-pci.h> |
@@ -582,7 +581,7 @@ void iommu_init_early_pSeries(void) | |||
582 | return; | 581 | return; |
583 | } | 582 | } |
584 | 583 | ||
585 | if (systemcfg->platform & PLATFORM_LPAR) { | 584 | if (platform_is_lpar()) { |
586 | if (firmware_has_feature(FW_FEATURE_MULTITCE)) { | 585 | if (firmware_has_feature(FW_FEATURE_MULTITCE)) { |
587 | ppc_md.tce_build = tce_buildmulti_pSeriesLP; | 586 | ppc_md.tce_build = tce_buildmulti_pSeriesLP; |
588 | ppc_md.tce_free = tce_freemulti_pSeriesLP; | 587 | ppc_md.tce_free = tce_freemulti_pSeriesLP; |
diff --git a/arch/powerpc/platforms/pseries/pci.c b/arch/powerpc/platforms/pseries/pci.c index c198656a3bb5..999a9620b5ce 100644 --- a/arch/powerpc/platforms/pseries/pci.c +++ b/arch/powerpc/platforms/pseries/pci.c | |||
@@ -107,7 +107,6 @@ static void __init pSeries_request_regions(void) | |||
107 | 107 | ||
108 | void __init pSeries_final_fixup(void) | 108 | void __init pSeries_final_fixup(void) |
109 | { | 109 | { |
110 | phbs_remap_io(); | ||
111 | pSeries_request_regions(); | 110 | pSeries_request_regions(); |
112 | 111 | ||
113 | pci_addr_cache_build(); | 112 | pci_addr_cache_build(); |
@@ -123,7 +122,7 @@ static void fixup_winbond_82c105(struct pci_dev* dev) | |||
123 | int i; | 122 | int i; |
124 | unsigned int reg; | 123 | unsigned int reg; |
125 | 124 | ||
126 | if (!(systemcfg->platform & PLATFORM_PSERIES)) | 125 | if (!platform_is_pseries()) |
127 | return; | 126 | return; |
128 | 127 | ||
129 | printk("Using INTC for W82c105 IDE controller.\n"); | 128 | printk("Using INTC for W82c105 IDE controller.\n"); |
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c index d7d400339458..d8864164dbe8 100644 --- a/arch/powerpc/platforms/pseries/reconfig.c +++ b/arch/powerpc/platforms/pseries/reconfig.c | |||
@@ -408,7 +408,7 @@ static int proc_ppc64_create_ofdt(void) | |||
408 | { | 408 | { |
409 | struct proc_dir_entry *ent; | 409 | struct proc_dir_entry *ent; |
410 | 410 | ||
411 | if (!(systemcfg->platform & PLATFORM_PSERIES)) | 411 | if (!platform_is_pseries()) |
412 | return 0; | 412 | return 0; |
413 | 413 | ||
414 | ent = create_proc_entry("ppc64/ofdt", S_IWUSR, NULL); | 414 | ent = create_proc_entry("ppc64/ofdt", S_IWUSR, NULL); |
diff --git a/arch/powerpc/platforms/pseries/rtasd.c b/arch/powerpc/platforms/pseries/rtasd.c index e26b0420b6dd..00cf331a1dc4 100644 --- a/arch/powerpc/platforms/pseries/rtasd.c +++ b/arch/powerpc/platforms/pseries/rtasd.c | |||
@@ -482,10 +482,12 @@ static int __init rtas_init(void) | |||
482 | { | 482 | { |
483 | struct proc_dir_entry *entry; | 483 | struct proc_dir_entry *entry; |
484 | 484 | ||
485 | /* No RTAS, only warn if we are on a pSeries box */ | 485 | if (!platform_is_pseries()) |
486 | return 0; | ||
487 | |||
488 | /* No RTAS */ | ||
486 | if (rtas_token("event-scan") == RTAS_UNKNOWN_SERVICE) { | 489 | if (rtas_token("event-scan") == RTAS_UNKNOWN_SERVICE) { |
487 | if (systemcfg->platform & PLATFORM_PSERIES) | 490 | printk(KERN_INFO "rtasd: no event-scan on system\n"); |
488 | printk(KERN_INFO "rtasd: no event-scan on system\n"); | ||
489 | return 1; | 491 | return 1; |
490 | } | 492 | } |
491 | 493 | ||
diff --git a/arch/ppc64/kernel/scanlog.c b/arch/powerpc/platforms/pseries/scanlog.c index 2edc947f7c44..2edc947f7c44 100644 --- a/arch/ppc64/kernel/scanlog.c +++ b/arch/powerpc/platforms/pseries/scanlog.c | |||
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index a093a0d4dd69..e94247c28d42 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c | |||
@@ -249,7 +249,7 @@ static void __init pSeries_setup_arch(void) | |||
249 | ppc_md.idle_loop = default_idle; | 249 | ppc_md.idle_loop = default_idle; |
250 | } | 250 | } |
251 | 251 | ||
252 | if (systemcfg->platform & PLATFORM_LPAR) | 252 | if (platform_is_lpar()) |
253 | ppc_md.enable_pmcs = pseries_lpar_enable_pmcs; | 253 | ppc_md.enable_pmcs = pseries_lpar_enable_pmcs; |
254 | else | 254 | else |
255 | ppc_md.enable_pmcs = power4_enable_pmcs; | 255 | ppc_md.enable_pmcs = power4_enable_pmcs; |
@@ -378,7 +378,7 @@ static void __init pSeries_init_early(void) | |||
378 | 378 | ||
379 | fw_feature_init(); | 379 | fw_feature_init(); |
380 | 380 | ||
381 | if (systemcfg->platform & PLATFORM_LPAR) | 381 | if (platform_is_lpar()) |
382 | hpte_init_lpar(); | 382 | hpte_init_lpar(); |
383 | else { | 383 | else { |
384 | hpte_init_native(); | 384 | hpte_init_native(); |
@@ -388,7 +388,7 @@ static void __init pSeries_init_early(void) | |||
388 | 388 | ||
389 | generic_find_legacy_serial_ports(&physport, &default_speed); | 389 | generic_find_legacy_serial_ports(&physport, &default_speed); |
390 | 390 | ||
391 | if (systemcfg->platform & PLATFORM_LPAR) | 391 | if (platform_is_lpar()) |
392 | find_udbg_vterm(); | 392 | find_udbg_vterm(); |
393 | else if (physport) { | 393 | else if (physport) { |
394 | /* Map the uart for udbg. */ | 394 | /* Map the uart for udbg. */ |
@@ -592,7 +592,7 @@ static void pseries_shared_idle(void) | |||
592 | 592 | ||
593 | static int pSeries_pci_probe_mode(struct pci_bus *bus) | 593 | static int pSeries_pci_probe_mode(struct pci_bus *bus) |
594 | { | 594 | { |
595 | if (systemcfg->platform & PLATFORM_LPAR) | 595 | if (platform_is_lpar()) |
596 | return PCI_PROBE_DEVTREE; | 596 | return PCI_PROBE_DEVTREE; |
597 | return PCI_PROBE_NORMAL; | 597 | return PCI_PROBE_NORMAL; |
598 | } | 598 | } |
diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c index 7a243e8ccd7e..3ba794ca3288 100644 --- a/arch/powerpc/platforms/pseries/smp.c +++ b/arch/powerpc/platforms/pseries/smp.c | |||
@@ -46,6 +46,7 @@ | |||
46 | #include <asm/rtas.h> | 46 | #include <asm/rtas.h> |
47 | #include <asm/pSeries_reconfig.h> | 47 | #include <asm/pSeries_reconfig.h> |
48 | #include <asm/mpic.h> | 48 | #include <asm/mpic.h> |
49 | #include <asm/systemcfg.h> | ||
49 | 50 | ||
50 | #include "plpar_wrappers.h" | 51 | #include "plpar_wrappers.h" |
51 | 52 | ||
@@ -96,7 +97,7 @@ int pSeries_cpu_disable(void) | |||
96 | int cpu = smp_processor_id(); | 97 | int cpu = smp_processor_id(); |
97 | 98 | ||
98 | cpu_clear(cpu, cpu_online_map); | 99 | cpu_clear(cpu, cpu_online_map); |
99 | systemcfg->processorCount--; | 100 | _systemcfg->processorCount--; |
100 | 101 | ||
101 | /*fix boot_cpuid here*/ | 102 | /*fix boot_cpuid here*/ |
102 | if (cpu == boot_cpuid) | 103 | if (cpu == boot_cpuid) |
@@ -441,7 +442,7 @@ void __init smp_init_pSeries(void) | |||
441 | smp_ops->cpu_die = pSeries_cpu_die; | 442 | smp_ops->cpu_die = pSeries_cpu_die; |
442 | 443 | ||
443 | /* Processors can be added/removed only on LPAR */ | 444 | /* Processors can be added/removed only on LPAR */ |
444 | if (systemcfg->platform == PLATFORM_PSERIES_LPAR) | 445 | if (platform_is_lpar()) |
445 | pSeries_reconfig_notifier_register(&pSeries_smp_nb); | 446 | pSeries_reconfig_notifier_register(&pSeries_smp_nb); |
446 | #endif | 447 | #endif |
447 | 448 | ||
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index c72c86f05cb6..72ac18067ece 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c | |||
@@ -545,7 +545,9 @@ nextnode: | |||
545 | of_node_put(np); | 545 | of_node_put(np); |
546 | } | 546 | } |
547 | 547 | ||
548 | if (systemcfg->platform == PLATFORM_PSERIES) { | 548 | if (platform_is_lpar()) |
549 | ops = &pSeriesLP_ops; | ||
550 | else { | ||
549 | #ifdef CONFIG_SMP | 551 | #ifdef CONFIG_SMP |
550 | for_each_cpu(i) { | 552 | for_each_cpu(i) { |
551 | int hard_id; | 553 | int hard_id; |
@@ -561,12 +563,11 @@ nextnode: | |||
561 | #else | 563 | #else |
562 | xics_per_cpu[0] = ioremap(intr_base, intr_size); | 564 | xics_per_cpu[0] = ioremap(intr_base, intr_size); |
563 | #endif /* CONFIG_SMP */ | 565 | #endif /* CONFIG_SMP */ |
564 | } else if (systemcfg->platform == PLATFORM_PSERIES_LPAR) { | ||
565 | ops = &pSeriesLP_ops; | ||
566 | } | 566 | } |
567 | 567 | ||
568 | xics_8259_pic.enable = i8259_pic.enable; | 568 | xics_8259_pic.enable = i8259_pic.enable; |
569 | xics_8259_pic.disable = i8259_pic.disable; | 569 | xics_8259_pic.disable = i8259_pic.disable; |
570 | xics_8259_pic.end = i8259_pic.end; | ||
570 | for (i = 0; i < 16; ++i) | 571 | for (i = 0; i < 16; ++i) |
571 | get_irq_desc(i)->handler = &xics_8259_pic; | 572 | get_irq_desc(i)->handler = &xics_8259_pic; |
572 | for (; i < NR_IRQS; ++i) | 573 | for (; i < NR_IRQS; ++i) |
diff --git a/arch/powerpc/sysdev/u3_iommu.c b/arch/powerpc/sysdev/u3_iommu.c index 543d65909812..f32baf7f4693 100644 --- a/arch/powerpc/sysdev/u3_iommu.c +++ b/arch/powerpc/sysdev/u3_iommu.c | |||
@@ -226,7 +226,7 @@ static void iommu_table_u3_setup(void) | |||
226 | iommu_table_u3.it_busno = 0; | 226 | iommu_table_u3.it_busno = 0; |
227 | iommu_table_u3.it_offset = 0; | 227 | iommu_table_u3.it_offset = 0; |
228 | /* it_size is in number of entries */ | 228 | /* it_size is in number of entries */ |
229 | iommu_table_u3.it_size = dart_tablesize / sizeof(u32); | 229 | iommu_table_u3.it_size = (dart_tablesize / sizeof(u32)) >> DART_PAGE_FACTOR; |
230 | 230 | ||
231 | /* Initialize the common IOMMU code */ | 231 | /* Initialize the common IOMMU code */ |
232 | iommu_table_u3.it_base = (unsigned long)dart_vbase; | 232 | iommu_table_u3.it_base = (unsigned long)dart_vbase; |
diff --git a/arch/powerpc/xmon/Makefile b/arch/powerpc/xmon/Makefile index 79a784f0e7a9..b20312e5ed27 100644 --- a/arch/powerpc/xmon/Makefile +++ b/arch/powerpc/xmon/Makefile | |||
@@ -8,4 +8,4 @@ obj-$(CONFIG_8xx) += start_8xx.o | |||
8 | obj-$(CONFIG_6xx) += start_32.o | 8 | obj-$(CONFIG_6xx) += start_32.o |
9 | obj-$(CONFIG_4xx) += start_32.o | 9 | obj-$(CONFIG_4xx) += start_32.o |
10 | obj-$(CONFIG_PPC64) += start_64.o | 10 | obj-$(CONFIG_PPC64) += start_64.o |
11 | obj-y += xmon.o ppc-dis.o ppc-opc.o subr_prf.o setjmp.o | 11 | obj-y += xmon.o ppc-dis.o ppc-opc.o setjmp.o nonstdio.o |
diff --git a/arch/powerpc/xmon/nonstdio.c b/arch/powerpc/xmon/nonstdio.c new file mode 100644 index 000000000000..78765833f4c0 --- /dev/null +++ b/arch/powerpc/xmon/nonstdio.c | |||
@@ -0,0 +1,134 @@ | |||
1 | /* | ||
2 | * Copyright (C) 1996-2005 Paul Mackerras. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | */ | ||
9 | #include <linux/string.h> | ||
10 | #include <asm/time.h> | ||
11 | #include "nonstdio.h" | ||
12 | |||
13 | int xmon_putchar(int c) | ||
14 | { | ||
15 | char ch = c; | ||
16 | |||
17 | if (c == '\n') | ||
18 | xmon_putchar('\r'); | ||
19 | return xmon_write(&ch, 1) == 1? c: -1; | ||
20 | } | ||
21 | |||
22 | static char line[256]; | ||
23 | static char *lineptr; | ||
24 | static int lineleft; | ||
25 | |||
26 | int xmon_expect(const char *str, unsigned long timeout) | ||
27 | { | ||
28 | int c; | ||
29 | unsigned long t0; | ||
30 | |||
31 | /* assume 25MHz default timebase if tb_ticks_per_sec not set yet */ | ||
32 | timeout *= tb_ticks_per_sec? tb_ticks_per_sec: 25000000; | ||
33 | t0 = get_tbl(); | ||
34 | do { | ||
35 | lineptr = line; | ||
36 | for (;;) { | ||
37 | c = xmon_read_poll(); | ||
38 | if (c == -1) { | ||
39 | if (get_tbl() - t0 > timeout) | ||
40 | return 0; | ||
41 | continue; | ||
42 | } | ||
43 | if (c == '\n') | ||
44 | break; | ||
45 | if (c != '\r' && lineptr < &line[sizeof(line) - 1]) | ||
46 | *lineptr++ = c; | ||
47 | } | ||
48 | *lineptr = 0; | ||
49 | } while (strstr(line, str) == NULL); | ||
50 | return 1; | ||
51 | } | ||
52 | |||
53 | int xmon_getchar(void) | ||
54 | { | ||
55 | int c; | ||
56 | |||
57 | if (lineleft == 0) { | ||
58 | lineptr = line; | ||
59 | for (;;) { | ||
60 | c = xmon_readchar(); | ||
61 | if (c == -1 || c == 4) | ||
62 | break; | ||
63 | if (c == '\r' || c == '\n') { | ||
64 | *lineptr++ = '\n'; | ||
65 | xmon_putchar('\n'); | ||
66 | break; | ||
67 | } | ||
68 | switch (c) { | ||
69 | case 0177: | ||
70 | case '\b': | ||
71 | if (lineptr > line) { | ||
72 | xmon_putchar('\b'); | ||
73 | xmon_putchar(' '); | ||
74 | xmon_putchar('\b'); | ||
75 | --lineptr; | ||
76 | } | ||
77 | break; | ||
78 | case 'U' & 0x1F: | ||
79 | while (lineptr > line) { | ||
80 | xmon_putchar('\b'); | ||
81 | xmon_putchar(' '); | ||
82 | xmon_putchar('\b'); | ||
83 | --lineptr; | ||
84 | } | ||
85 | break; | ||
86 | default: | ||
87 | if (lineptr >= &line[sizeof(line) - 1]) | ||
88 | xmon_putchar('\a'); | ||
89 | else { | ||
90 | xmon_putchar(c); | ||
91 | *lineptr++ = c; | ||
92 | } | ||
93 | } | ||
94 | } | ||
95 | lineleft = lineptr - line; | ||
96 | lineptr = line; | ||
97 | } | ||
98 | if (lineleft == 0) | ||
99 | return -1; | ||
100 | --lineleft; | ||
101 | return *lineptr++; | ||
102 | } | ||
103 | |||
104 | char *xmon_gets(char *str, int nb) | ||
105 | { | ||
106 | char *p; | ||
107 | int c; | ||
108 | |||
109 | for (p = str; p < str + nb - 1; ) { | ||
110 | c = xmon_getchar(); | ||
111 | if (c == -1) { | ||
112 | if (p == str) | ||
113 | return NULL; | ||
114 | break; | ||
115 | } | ||
116 | *p++ = c; | ||
117 | if (c == '\n') | ||
118 | break; | ||
119 | } | ||
120 | *p = 0; | ||
121 | return str; | ||
122 | } | ||
123 | |||
124 | void xmon_printf(const char *format, ...) | ||
125 | { | ||
126 | va_list args; | ||
127 | int n; | ||
128 | static char xmon_outbuf[1024]; | ||
129 | |||
130 | va_start(args, format); | ||
131 | n = vsnprintf(xmon_outbuf, sizeof(xmon_outbuf), format, args); | ||
132 | va_end(args); | ||
133 | xmon_write(xmon_outbuf, n); | ||
134 | } | ||
diff --git a/arch/powerpc/xmon/nonstdio.h b/arch/powerpc/xmon/nonstdio.h index 84211a21c6f4..47cebbd2b1b1 100644 --- a/arch/powerpc/xmon/nonstdio.h +++ b/arch/powerpc/xmon/nonstdio.h | |||
@@ -1,22 +1,14 @@ | |||
1 | typedef int FILE; | ||
2 | extern FILE *xmon_stdin, *xmon_stdout; | ||
3 | #define EOF (-1) | 1 | #define EOF (-1) |
4 | #define stdin xmon_stdin | 2 | |
5 | #define stdout xmon_stdout | ||
6 | #define printf xmon_printf | 3 | #define printf xmon_printf |
7 | #define fprintf xmon_fprintf | ||
8 | #define fputs xmon_fputs | ||
9 | #define fgets xmon_fgets | ||
10 | #define putchar xmon_putchar | 4 | #define putchar xmon_putchar |
11 | #define getchar xmon_getchar | ||
12 | #define putc xmon_putc | ||
13 | #define getc xmon_getc | ||
14 | #define fopen(n, m) NULL | ||
15 | #define fflush(f) do {} while (0) | ||
16 | #define fclose(f) do {} while (0) | ||
17 | extern char *fgets(char *, int, void *); | ||
18 | extern void xmon_printf(const char *, ...); | ||
19 | extern void xmon_fprintf(void *, const char *, ...); | ||
20 | extern void xmon_sprintf(char *, const char *, ...); | ||
21 | 5 | ||
22 | #define perror(s) printf("%s: no files!\n", (s)) | 6 | extern int xmon_putchar(int c); |
7 | extern int xmon_getchar(void); | ||
8 | extern char *xmon_gets(char *, int); | ||
9 | extern void xmon_printf(const char *, ...); | ||
10 | extern void xmon_map_scc(void); | ||
11 | extern int xmon_expect(const char *str, unsigned long timeout); | ||
12 | extern int xmon_write(void *ptr, int nb); | ||
13 | extern int xmon_readchar(void); | ||
14 | extern int xmon_read_poll(void); | ||
diff --git a/arch/powerpc/xmon/setjmp.S b/arch/powerpc/xmon/setjmp.S index f8e40dfd2bff..96a91f10e2ec 100644 --- a/arch/powerpc/xmon/setjmp.S +++ b/arch/powerpc/xmon/setjmp.S | |||
@@ -14,61 +14,61 @@ | |||
14 | 14 | ||
15 | _GLOBAL(xmon_setjmp) | 15 | _GLOBAL(xmon_setjmp) |
16 | mflr r0 | 16 | mflr r0 |
17 | STL r0,0(r3) | 17 | PPC_STL r0,0(r3) |
18 | STL r1,SZL(r3) | 18 | PPC_STL r1,SZL(r3) |
19 | STL r2,2*SZL(r3) | 19 | PPC_STL r2,2*SZL(r3) |
20 | mfcr r0 | 20 | mfcr r0 |
21 | STL r0,3*SZL(r3) | 21 | PPC_STL r0,3*SZL(r3) |
22 | STL r13,4*SZL(r3) | 22 | PPC_STL r13,4*SZL(r3) |
23 | STL r14,5*SZL(r3) | 23 | PPC_STL r14,5*SZL(r3) |
24 | STL r15,6*SZL(r3) | 24 | PPC_STL r15,6*SZL(r3) |
25 | STL r16,7*SZL(r3) | 25 | PPC_STL r16,7*SZL(r3) |
26 | STL r17,8*SZL(r3) | 26 | PPC_STL r17,8*SZL(r3) |
27 | STL r18,9*SZL(r3) | 27 | PPC_STL r18,9*SZL(r3) |
28 | STL r19,10*SZL(r3) | 28 | PPC_STL r19,10*SZL(r3) |
29 | STL r20,11*SZL(r3) | 29 | PPC_STL r20,11*SZL(r3) |
30 | STL r21,12*SZL(r3) | 30 | PPC_STL r21,12*SZL(r3) |
31 | STL r22,13*SZL(r3) | 31 | PPC_STL r22,13*SZL(r3) |
32 | STL r23,14*SZL(r3) | 32 | PPC_STL r23,14*SZL(r3) |
33 | STL r24,15*SZL(r3) | 33 | PPC_STL r24,15*SZL(r3) |
34 | STL r25,16*SZL(r3) | 34 | PPC_STL r25,16*SZL(r3) |
35 | STL r26,17*SZL(r3) | 35 | PPC_STL r26,17*SZL(r3) |
36 | STL r27,18*SZL(r3) | 36 | PPC_STL r27,18*SZL(r3) |
37 | STL r28,19*SZL(r3) | 37 | PPC_STL r28,19*SZL(r3) |
38 | STL r29,20*SZL(r3) | 38 | PPC_STL r29,20*SZL(r3) |
39 | STL r30,21*SZL(r3) | 39 | PPC_STL r30,21*SZL(r3) |
40 | STL r31,22*SZL(r3) | 40 | PPC_STL r31,22*SZL(r3) |
41 | li r3,0 | 41 | li r3,0 |
42 | blr | 42 | blr |
43 | 43 | ||
44 | _GLOBAL(xmon_longjmp) | 44 | _GLOBAL(xmon_longjmp) |
45 | CMPI r4,0 | 45 | PPC_LCMPI r4,0 |
46 | bne 1f | 46 | bne 1f |
47 | li r4,1 | 47 | li r4,1 |
48 | 1: LDL r13,4*SZL(r3) | 48 | 1: PPC_LL r13,4*SZL(r3) |
49 | LDL r14,5*SZL(r3) | 49 | PPC_LL r14,5*SZL(r3) |
50 | LDL r15,6*SZL(r3) | 50 | PPC_LL r15,6*SZL(r3) |
51 | LDL r16,7*SZL(r3) | 51 | PPC_LL r16,7*SZL(r3) |
52 | LDL r17,8*SZL(r3) | 52 | PPC_LL r17,8*SZL(r3) |
53 | LDL r18,9*SZL(r3) | 53 | PPC_LL r18,9*SZL(r3) |
54 | LDL r19,10*SZL(r3) | 54 | PPC_LL r19,10*SZL(r3) |
55 | LDL r20,11*SZL(r3) | 55 | PPC_LL r20,11*SZL(r3) |
56 | LDL r21,12*SZL(r3) | 56 | PPC_LL r21,12*SZL(r3) |
57 | LDL r22,13*SZL(r3) | 57 | PPC_LL r22,13*SZL(r3) |
58 | LDL r23,14*SZL(r3) | 58 | PPC_LL r23,14*SZL(r3) |
59 | LDL r24,15*SZL(r3) | 59 | PPC_LL r24,15*SZL(r3) |
60 | LDL r25,16*SZL(r3) | 60 | PPC_LL r25,16*SZL(r3) |
61 | LDL r26,17*SZL(r3) | 61 | PPC_LL r26,17*SZL(r3) |
62 | LDL r27,18*SZL(r3) | 62 | PPC_LL r27,18*SZL(r3) |
63 | LDL r28,19*SZL(r3) | 63 | PPC_LL r28,19*SZL(r3) |
64 | LDL r29,20*SZL(r3) | 64 | PPC_LL r29,20*SZL(r3) |
65 | LDL r30,21*SZL(r3) | 65 | PPC_LL r30,21*SZL(r3) |
66 | LDL r31,22*SZL(r3) | 66 | PPC_LL r31,22*SZL(r3) |
67 | LDL r0,3*SZL(r3) | 67 | PPC_LL r0,3*SZL(r3) |
68 | mtcrf 0x38,r0 | 68 | mtcrf 0x38,r0 |
69 | LDL r0,0(r3) | 69 | PPC_LL r0,0(r3) |
70 | LDL r1,SZL(r3) | 70 | PPC_LL r1,SZL(r3) |
71 | LDL r2,2*SZL(r3) | 71 | PPC_LL r2,2*SZL(r3) |
72 | mtlr r0 | 72 | mtlr r0 |
73 | mr r3,r4 | 73 | mr r3,r4 |
74 | blr | 74 | blr |
@@ -84,52 +84,52 @@ _GLOBAL(xmon_longjmp) | |||
84 | * different ABIs, though). | 84 | * different ABIs, though). |
85 | */ | 85 | */ |
86 | _GLOBAL(xmon_save_regs) | 86 | _GLOBAL(xmon_save_regs) |
87 | STL r0,0*SZL(r3) | 87 | PPC_STL r0,0*SZL(r3) |
88 | STL r2,2*SZL(r3) | 88 | PPC_STL r2,2*SZL(r3) |
89 | STL r3,3*SZL(r3) | 89 | PPC_STL r3,3*SZL(r3) |
90 | STL r4,4*SZL(r3) | 90 | PPC_STL r4,4*SZL(r3) |
91 | STL r5,5*SZL(r3) | 91 | PPC_STL r5,5*SZL(r3) |
92 | STL r6,6*SZL(r3) | 92 | PPC_STL r6,6*SZL(r3) |
93 | STL r7,7*SZL(r3) | 93 | PPC_STL r7,7*SZL(r3) |
94 | STL r8,8*SZL(r3) | 94 | PPC_STL r8,8*SZL(r3) |
95 | STL r9,9*SZL(r3) | 95 | PPC_STL r9,9*SZL(r3) |
96 | STL r10,10*SZL(r3) | 96 | PPC_STL r10,10*SZL(r3) |
97 | STL r11,11*SZL(r3) | 97 | PPC_STL r11,11*SZL(r3) |
98 | STL r12,12*SZL(r3) | 98 | PPC_STL r12,12*SZL(r3) |
99 | STL r13,13*SZL(r3) | 99 | PPC_STL r13,13*SZL(r3) |
100 | STL r14,14*SZL(r3) | 100 | PPC_STL r14,14*SZL(r3) |
101 | STL r15,15*SZL(r3) | 101 | PPC_STL r15,15*SZL(r3) |
102 | STL r16,16*SZL(r3) | 102 | PPC_STL r16,16*SZL(r3) |
103 | STL r17,17*SZL(r3) | 103 | PPC_STL r17,17*SZL(r3) |
104 | STL r18,18*SZL(r3) | 104 | PPC_STL r18,18*SZL(r3) |
105 | STL r19,19*SZL(r3) | 105 | PPC_STL r19,19*SZL(r3) |
106 | STL r20,20*SZL(r3) | 106 | PPC_STL r20,20*SZL(r3) |
107 | STL r21,21*SZL(r3) | 107 | PPC_STL r21,21*SZL(r3) |
108 | STL r22,22*SZL(r3) | 108 | PPC_STL r22,22*SZL(r3) |
109 | STL r23,23*SZL(r3) | 109 | PPC_STL r23,23*SZL(r3) |
110 | STL r24,24*SZL(r3) | 110 | PPC_STL r24,24*SZL(r3) |
111 | STL r25,25*SZL(r3) | 111 | PPC_STL r25,25*SZL(r3) |
112 | STL r26,26*SZL(r3) | 112 | PPC_STL r26,26*SZL(r3) |
113 | STL r27,27*SZL(r3) | 113 | PPC_STL r27,27*SZL(r3) |
114 | STL r28,28*SZL(r3) | 114 | PPC_STL r28,28*SZL(r3) |
115 | STL r29,29*SZL(r3) | 115 | PPC_STL r29,29*SZL(r3) |
116 | STL r30,30*SZL(r3) | 116 | PPC_STL r30,30*SZL(r3) |
117 | STL r31,31*SZL(r3) | 117 | PPC_STL r31,31*SZL(r3) |
118 | /* go up one stack frame for SP */ | 118 | /* go up one stack frame for SP */ |
119 | LDL r4,0(r1) | 119 | PPC_LL r4,0(r1) |
120 | STL r4,1*SZL(r3) | 120 | PPC_STL r4,1*SZL(r3) |
121 | /* get caller's LR */ | 121 | /* get caller's LR */ |
122 | LDL r0,LRSAVE(r4) | 122 | PPC_LL r0,LRSAVE(r4) |
123 | STL r0,_NIP-STACK_FRAME_OVERHEAD(r3) | 123 | PPC_STL r0,_NIP-STACK_FRAME_OVERHEAD(r3) |
124 | STL r0,_LINK-STACK_FRAME_OVERHEAD(r3) | 124 | PPC_STL r0,_LINK-STACK_FRAME_OVERHEAD(r3) |
125 | mfmsr r0 | 125 | mfmsr r0 |
126 | STL r0,_MSR-STACK_FRAME_OVERHEAD(r3) | 126 | PPC_STL r0,_MSR-STACK_FRAME_OVERHEAD(r3) |
127 | mfctr r0 | 127 | mfctr r0 |
128 | STL r0,_CTR-STACK_FRAME_OVERHEAD(r3) | 128 | PPC_STL r0,_CTR-STACK_FRAME_OVERHEAD(r3) |
129 | mfxer r0 | 129 | mfxer r0 |
130 | STL r0,_XER-STACK_FRAME_OVERHEAD(r3) | 130 | PPC_STL r0,_XER-STACK_FRAME_OVERHEAD(r3) |
131 | mfcr r0 | 131 | mfcr r0 |
132 | STL r0,_CCR-STACK_FRAME_OVERHEAD(r3) | 132 | PPC_STL r0,_CCR-STACK_FRAME_OVERHEAD(r3) |
133 | li r0,0 | 133 | li r0,0 |
134 | STL r0,_TRAP-STACK_FRAME_OVERHEAD(r3) | 134 | PPC_STL r0,_TRAP-STACK_FRAME_OVERHEAD(r3) |
135 | blr | 135 | blr |
diff --git a/arch/powerpc/xmon/start_32.c b/arch/powerpc/xmon/start_32.c index 69b658c0f760..c2464df4217e 100644 --- a/arch/powerpc/xmon/start_32.c +++ b/arch/powerpc/xmon/start_32.c | |||
@@ -11,7 +11,6 @@ | |||
11 | #include <linux/cuda.h> | 11 | #include <linux/cuda.h> |
12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/errno.h> | 13 | #include <linux/errno.h> |
14 | #include <linux/sysrq.h> | ||
15 | #include <linux/bitops.h> | 14 | #include <linux/bitops.h> |
16 | #include <asm/xmon.h> | 15 | #include <asm/xmon.h> |
17 | #include <asm/prom.h> | 16 | #include <asm/prom.h> |
@@ -22,10 +21,11 @@ | |||
22 | #include <asm/processor.h> | 21 | #include <asm/processor.h> |
23 | #include <asm/delay.h> | 22 | #include <asm/delay.h> |
24 | #include <asm/btext.h> | 23 | #include <asm/btext.h> |
24 | #include <asm/time.h> | ||
25 | #include "nonstdio.h" | ||
25 | 26 | ||
26 | static volatile unsigned char __iomem *sccc, *sccd; | 27 | static volatile unsigned char __iomem *sccc, *sccd; |
27 | unsigned int TXRDY, RXRDY, DLAB; | 28 | unsigned int TXRDY, RXRDY, DLAB; |
28 | static int xmon_expect(const char *str, unsigned int timeout); | ||
29 | 29 | ||
30 | static int use_serial; | 30 | static int use_serial; |
31 | static int use_screen; | 31 | static int use_screen; |
@@ -33,16 +33,6 @@ static int via_modem; | |||
33 | static int xmon_use_sccb; | 33 | static int xmon_use_sccb; |
34 | static struct device_node *channel_node; | 34 | static struct device_node *channel_node; |
35 | 35 | ||
36 | #define TB_SPEED 25000000 | ||
37 | |||
38 | static inline unsigned int readtb(void) | ||
39 | { | ||
40 | unsigned int ret; | ||
41 | |||
42 | asm volatile("mftb %0" : "=r" (ret) :); | ||
43 | return ret; | ||
44 | } | ||
45 | |||
46 | void buf_access(void) | 36 | void buf_access(void) |
47 | { | 37 | { |
48 | if (DLAB) | 38 | if (DLAB) |
@@ -91,23 +81,7 @@ static unsigned long chrp_find_phys_io_base(void) | |||
91 | } | 81 | } |
92 | #endif /* CONFIG_PPC_CHRP */ | 82 | #endif /* CONFIG_PPC_CHRP */ |
93 | 83 | ||
94 | #ifdef CONFIG_MAGIC_SYSRQ | 84 | void xmon_map_scc(void) |
95 | static void sysrq_handle_xmon(int key, struct pt_regs *regs, | ||
96 | struct tty_struct *tty) | ||
97 | { | ||
98 | xmon(regs); | ||
99 | } | ||
100 | |||
101 | static struct sysrq_key_op sysrq_xmon_op = | ||
102 | { | ||
103 | .handler = sysrq_handle_xmon, | ||
104 | .help_msg = "Xmon", | ||
105 | .action_msg = "Entering xmon", | ||
106 | }; | ||
107 | #endif | ||
108 | |||
109 | void | ||
110 | xmon_map_scc(void) | ||
111 | { | 85 | { |
112 | #ifdef CONFIG_PPC_MULTIPLATFORM | 86 | #ifdef CONFIG_PPC_MULTIPLATFORM |
113 | volatile unsigned char __iomem *base; | 87 | volatile unsigned char __iomem *base; |
@@ -217,8 +191,6 @@ xmon_map_scc(void) | |||
217 | RXRDY = 1; | 191 | RXRDY = 1; |
218 | DLAB = 0x80; | 192 | DLAB = 0x80; |
219 | #endif /* platform */ | 193 | #endif /* platform */ |
220 | |||
221 | register_sysrq_key('x', &sysrq_xmon_op); | ||
222 | } | 194 | } |
223 | 195 | ||
224 | static int scc_initialized = 0; | 196 | static int scc_initialized = 0; |
@@ -238,8 +210,7 @@ static inline void do_poll_adb(void) | |||
238 | #endif /* CONFIG_ADB_CUDA */ | 210 | #endif /* CONFIG_ADB_CUDA */ |
239 | } | 211 | } |
240 | 212 | ||
241 | int | 213 | int xmon_write(void *ptr, int nb) |
242 | xmon_write(void *handle, void *ptr, int nb) | ||
243 | { | 214 | { |
244 | char *p = ptr; | 215 | char *p = ptr; |
245 | int i, c, ct; | 216 | int i, c, ct; |
@@ -311,8 +282,7 @@ static unsigned char xmon_shift_keytab[128] = | |||
311 | "\0.\0*\0+\0\0\0\0\0/\r\0-\0" /* 0x40 - 0x4f */ | 282 | "\0.\0*\0+\0\0\0\0\0/\r\0-\0" /* 0x40 - 0x4f */ |
312 | "\0\0000123456789\0\0\0"; /* 0x50 - 0x5f */ | 283 | "\0\0000123456789\0\0\0"; /* 0x50 - 0x5f */ |
313 | 284 | ||
314 | static int | 285 | static int xmon_get_adb_key(void) |
315 | xmon_get_adb_key(void) | ||
316 | { | 286 | { |
317 | int k, t, on; | 287 | int k, t, on; |
318 | 288 | ||
@@ -350,32 +320,21 @@ xmon_get_adb_key(void) | |||
350 | } | 320 | } |
351 | #endif /* CONFIG_BOOTX_TEXT */ | 321 | #endif /* CONFIG_BOOTX_TEXT */ |
352 | 322 | ||
353 | int | 323 | int xmon_readchar(void) |
354 | xmon_read(void *handle, void *ptr, int nb) | ||
355 | { | 324 | { |
356 | char *p = ptr; | ||
357 | int i; | ||
358 | |||
359 | #ifdef CONFIG_BOOTX_TEXT | 325 | #ifdef CONFIG_BOOTX_TEXT |
360 | if (use_screen) { | 326 | if (use_screen) |
361 | for (i = 0; i < nb; ++i) | 327 | return xmon_get_adb_key(); |
362 | *p++ = xmon_get_adb_key(); | ||
363 | return i; | ||
364 | } | ||
365 | #endif | 328 | #endif |
366 | if (!scc_initialized) | 329 | if (!scc_initialized) |
367 | xmon_init_scc(); | 330 | xmon_init_scc(); |
368 | for (i = 0; i < nb; ++i) { | ||
369 | while ((*sccc & RXRDY) == 0) | 331 | while ((*sccc & RXRDY) == 0) |
370 | do_poll_adb(); | 332 | do_poll_adb(); |
371 | buf_access(); | 333 | buf_access(); |
372 | *p++ = *sccd; | 334 | return *sccd; |
373 | } | ||
374 | return i; | ||
375 | } | 335 | } |
376 | 336 | ||
377 | int | 337 | int xmon_read_poll(void) |
378 | xmon_read_poll(void) | ||
379 | { | 338 | { |
380 | if ((*sccc & RXRDY) == 0) { | 339 | if ((*sccc & RXRDY) == 0) { |
381 | do_poll_adb(); | 340 | do_poll_adb(); |
@@ -395,8 +354,7 @@ static unsigned char scc_inittab[] = { | |||
395 | 3, 0xc1, /* rx enable, 8 bits */ | 354 | 3, 0xc1, /* rx enable, 8 bits */ |
396 | }; | 355 | }; |
397 | 356 | ||
398 | void | 357 | void xmon_init_scc(void) |
399 | xmon_init_scc(void) | ||
400 | { | 358 | { |
401 | if ( _machine == _MACH_chrp ) | 359 | if ( _machine == _MACH_chrp ) |
402 | { | 360 | { |
@@ -410,6 +368,7 @@ xmon_init_scc(void) | |||
410 | else if ( _machine == _MACH_Pmac ) | 368 | else if ( _machine == _MACH_Pmac ) |
411 | { | 369 | { |
412 | int i, x; | 370 | int i, x; |
371 | unsigned long timeout; | ||
413 | 372 | ||
414 | if (channel_node != 0) | 373 | if (channel_node != 0) |
415 | pmac_call_feature( | 374 | pmac_call_feature( |
@@ -424,8 +383,12 @@ xmon_init_scc(void) | |||
424 | PMAC_FTR_MODEM_ENABLE, | 383 | PMAC_FTR_MODEM_ENABLE, |
425 | channel_node, 0, 1); | 384 | channel_node, 0, 1); |
426 | printk(KERN_INFO "Modem powered up by debugger !\n"); | 385 | printk(KERN_INFO "Modem powered up by debugger !\n"); |
427 | t0 = readtb(); | 386 | t0 = get_tbl(); |
428 | while (readtb() - t0 < 3*TB_SPEED) | 387 | timeout = 3 * tb_ticks_per_sec; |
388 | if (timeout == 0) | ||
389 | /* assume 25MHz if tb_ticks_per_sec not set */ | ||
390 | timeout = 75000000; | ||
391 | while (get_tbl() - t0 < timeout) | ||
429 | eieio(); | 392 | eieio(); |
430 | } | 393 | } |
431 | /* use the B channel if requested */ | 394 | /* use the B channel if requested */ |
@@ -447,164 +410,19 @@ xmon_init_scc(void) | |||
447 | scc_initialized = 1; | 410 | scc_initialized = 1; |
448 | if (via_modem) { | 411 | if (via_modem) { |
449 | for (;;) { | 412 | for (;;) { |
450 | xmon_write(NULL, "ATE1V1\r", 7); | 413 | xmon_write("ATE1V1\r", 7); |
451 | if (xmon_expect("OK", 5)) { | 414 | if (xmon_expect("OK", 5)) { |
452 | xmon_write(NULL, "ATA\r", 4); | 415 | xmon_write("ATA\r", 4); |
453 | if (xmon_expect("CONNECT", 40)) | 416 | if (xmon_expect("CONNECT", 40)) |
454 | break; | 417 | break; |
455 | } | 418 | } |
456 | xmon_write(NULL, "+++", 3); | 419 | xmon_write("+++", 3); |
457 | xmon_expect("OK", 3); | 420 | xmon_expect("OK", 3); |
458 | } | 421 | } |
459 | } | 422 | } |
460 | } | 423 | } |
461 | 424 | ||
462 | void *xmon_stdin; | 425 | void xmon_enter(void) |
463 | void *xmon_stdout; | ||
464 | void *xmon_stderr; | ||
465 | |||
466 | int xmon_putc(int c, void *f) | ||
467 | { | ||
468 | char ch = c; | ||
469 | |||
470 | if (c == '\n') | ||
471 | xmon_putc('\r', f); | ||
472 | return xmon_write(f, &ch, 1) == 1? c: -1; | ||
473 | } | ||
474 | |||
475 | int xmon_putchar(int c) | ||
476 | { | ||
477 | return xmon_putc(c, xmon_stdout); | ||
478 | } | ||
479 | |||
480 | int xmon_fputs(char *str, void *f) | ||
481 | { | ||
482 | int n = strlen(str); | ||
483 | |||
484 | return xmon_write(f, str, n) == n? 0: -1; | ||
485 | } | ||
486 | |||
487 | int | ||
488 | xmon_readchar(void) | ||
489 | { | ||
490 | char ch; | ||
491 | |||
492 | for (;;) { | ||
493 | switch (xmon_read(xmon_stdin, &ch, 1)) { | ||
494 | case 1: | ||
495 | return ch; | ||
496 | case -1: | ||
497 | xmon_printf("read(stdin) returned -1\r\n", 0, 0); | ||
498 | return -1; | ||
499 | } | ||
500 | } | ||
501 | } | ||
502 | |||
503 | static char line[256]; | ||
504 | static char *lineptr; | ||
505 | static int lineleft; | ||
506 | |||
507 | int xmon_expect(const char *str, unsigned int timeout) | ||
508 | { | ||
509 | int c; | ||
510 | unsigned int t0; | ||
511 | |||
512 | timeout *= TB_SPEED; | ||
513 | t0 = readtb(); | ||
514 | do { | ||
515 | lineptr = line; | ||
516 | for (;;) { | ||
517 | c = xmon_read_poll(); | ||
518 | if (c == -1) { | ||
519 | if (readtb() - t0 > timeout) | ||
520 | return 0; | ||
521 | continue; | ||
522 | } | ||
523 | if (c == '\n') | ||
524 | break; | ||
525 | if (c != '\r' && lineptr < &line[sizeof(line) - 1]) | ||
526 | *lineptr++ = c; | ||
527 | } | ||
528 | *lineptr = 0; | ||
529 | } while (strstr(line, str) == NULL); | ||
530 | return 1; | ||
531 | } | ||
532 | |||
533 | int | ||
534 | xmon_getchar(void) | ||
535 | { | ||
536 | int c; | ||
537 | |||
538 | if (lineleft == 0) { | ||
539 | lineptr = line; | ||
540 | for (;;) { | ||
541 | c = xmon_readchar(); | ||
542 | if (c == -1 || c == 4) | ||
543 | break; | ||
544 | if (c == '\r' || c == '\n') { | ||
545 | *lineptr++ = '\n'; | ||
546 | xmon_putchar('\n'); | ||
547 | break; | ||
548 | } | ||
549 | switch (c) { | ||
550 | case 0177: | ||
551 | case '\b': | ||
552 | if (lineptr > line) { | ||
553 | xmon_putchar('\b'); | ||
554 | xmon_putchar(' '); | ||
555 | xmon_putchar('\b'); | ||
556 | --lineptr; | ||
557 | } | ||
558 | break; | ||
559 | case 'U' & 0x1F: | ||
560 | while (lineptr > line) { | ||
561 | xmon_putchar('\b'); | ||
562 | xmon_putchar(' '); | ||
563 | xmon_putchar('\b'); | ||
564 | --lineptr; | ||
565 | } | ||
566 | break; | ||
567 | default: | ||
568 | if (lineptr >= &line[sizeof(line) - 1]) | ||
569 | xmon_putchar('\a'); | ||
570 | else { | ||
571 | xmon_putchar(c); | ||
572 | *lineptr++ = c; | ||
573 | } | ||
574 | } | ||
575 | } | ||
576 | lineleft = lineptr - line; | ||
577 | lineptr = line; | ||
578 | } | ||
579 | if (lineleft == 0) | ||
580 | return -1; | ||
581 | --lineleft; | ||
582 | return *lineptr++; | ||
583 | } | ||
584 | |||
585 | char * | ||
586 | xmon_fgets(char *str, int nb, void *f) | ||
587 | { | ||
588 | char *p; | ||
589 | int c; | ||
590 | |||
591 | for (p = str; p < str + nb - 1; ) { | ||
592 | c = xmon_getchar(); | ||
593 | if (c == -1) { | ||
594 | if (p == str) | ||
595 | return NULL; | ||
596 | break; | ||
597 | } | ||
598 | *p++ = c; | ||
599 | if (c == '\n') | ||
600 | break; | ||
601 | } | ||
602 | *p = 0; | ||
603 | return str; | ||
604 | } | ||
605 | |||
606 | void | ||
607 | xmon_enter(void) | ||
608 | { | 426 | { |
609 | #ifdef CONFIG_ADB_PMU | 427 | #ifdef CONFIG_ADB_PMU |
610 | if (_machine == _MACH_Pmac) { | 428 | if (_machine == _MACH_Pmac) { |
@@ -613,8 +431,7 @@ xmon_enter(void) | |||
613 | #endif | 431 | #endif |
614 | } | 432 | } |
615 | 433 | ||
616 | void | 434 | void xmon_leave(void) |
617 | xmon_leave(void) | ||
618 | { | 435 | { |
619 | #ifdef CONFIG_ADB_PMU | 436 | #ifdef CONFIG_ADB_PMU |
620 | if (_machine == _MACH_Pmac) { | 437 | if (_machine == _MACH_Pmac) { |
diff --git a/arch/powerpc/xmon/start_64.c b/arch/powerpc/xmon/start_64.c index e50c158191e1..712552c4f242 100644 --- a/arch/powerpc/xmon/start_64.c +++ b/arch/powerpc/xmon/start_64.c | |||
@@ -6,182 +6,29 @@ | |||
6 | * as published by the Free Software Foundation; either version | 6 | * as published by the Free Software Foundation; either version |
7 | * 2 of the License, or (at your option) any later version. | 7 | * 2 of the License, or (at your option) any later version. |
8 | */ | 8 | */ |
9 | #include <linux/config.h> | ||
10 | #include <linux/string.h> | ||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/errno.h> | ||
13 | #include <linux/sysrq.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <asm/machdep.h> | 9 | #include <asm/machdep.h> |
16 | #include <asm/io.h> | ||
17 | #include <asm/page.h> | ||
18 | #include <asm/prom.h> | ||
19 | #include <asm/processor.h> | ||
20 | #include <asm/udbg.h> | 10 | #include <asm/udbg.h> |
21 | #include <asm/system.h> | ||
22 | #include "nonstdio.h" | 11 | #include "nonstdio.h" |
23 | 12 | ||
24 | #ifdef CONFIG_MAGIC_SYSRQ | 13 | void xmon_map_scc(void) |
25 | |||
26 | static void sysrq_handle_xmon(int key, struct pt_regs *pt_regs, | ||
27 | struct tty_struct *tty) | ||
28 | { | ||
29 | /* ensure xmon is enabled */ | ||
30 | xmon_init(1); | ||
31 | debugger(pt_regs); | ||
32 | } | ||
33 | |||
34 | static struct sysrq_key_op sysrq_xmon_op = | ||
35 | { | 14 | { |
36 | .handler = sysrq_handle_xmon, | ||
37 | .help_msg = "Xmon", | ||
38 | .action_msg = "Entering xmon", | ||
39 | }; | ||
40 | |||
41 | static int __init setup_xmon_sysrq(void) | ||
42 | { | ||
43 | register_sysrq_key('x', &sysrq_xmon_op); | ||
44 | return 0; | ||
45 | } | 15 | } |
46 | __initcall(setup_xmon_sysrq); | ||
47 | #endif /* CONFIG_MAGIC_SYSRQ */ | ||
48 | 16 | ||
49 | int | 17 | int xmon_write(void *ptr, int nb) |
50 | xmon_write(void *handle, void *ptr, int nb) | ||
51 | { | 18 | { |
52 | return udbg_write(ptr, nb); | 19 | return udbg_write(ptr, nb); |
53 | } | 20 | } |
54 | 21 | ||
55 | int | 22 | int xmon_readchar(void) |
56 | xmon_read(void *handle, void *ptr, int nb) | ||
57 | { | 23 | { |
58 | return udbg_read(ptr, nb); | 24 | if (udbg_getc) |
25 | return udbg_getc(); | ||
26 | return -1; | ||
59 | } | 27 | } |
60 | 28 | ||
61 | int | 29 | int xmon_read_poll(void) |
62 | xmon_read_poll(void) | ||
63 | { | 30 | { |
64 | if (udbg_getc_poll) | 31 | if (udbg_getc_poll) |
65 | return udbg_getc_poll(); | 32 | return udbg_getc_poll(); |
66 | return -1; | 33 | return -1; |
67 | } | 34 | } |
68 | |||
69 | FILE *xmon_stdin; | ||
70 | FILE *xmon_stdout; | ||
71 | |||
72 | int | ||
73 | xmon_putc(int c, void *f) | ||
74 | { | ||
75 | char ch = c; | ||
76 | |||
77 | if (c == '\n') | ||
78 | xmon_putc('\r', f); | ||
79 | return xmon_write(f, &ch, 1) == 1? c: -1; | ||
80 | } | ||
81 | |||
82 | int | ||
83 | xmon_putchar(int c) | ||
84 | { | ||
85 | return xmon_putc(c, xmon_stdout); | ||
86 | } | ||
87 | |||
88 | int | ||
89 | xmon_fputs(char *str, void *f) | ||
90 | { | ||
91 | int n = strlen(str); | ||
92 | |||
93 | return xmon_write(f, str, n) == n? 0: -1; | ||
94 | } | ||
95 | |||
96 | int | ||
97 | xmon_readchar(void) | ||
98 | { | ||
99 | char ch; | ||
100 | |||
101 | for (;;) { | ||
102 | switch (xmon_read(xmon_stdin, &ch, 1)) { | ||
103 | case 1: | ||
104 | return ch; | ||
105 | case -1: | ||
106 | xmon_printf("read(stdin) returned -1\r\n", 0, 0); | ||
107 | return -1; | ||
108 | } | ||
109 | } | ||
110 | } | ||
111 | |||
112 | static char line[256]; | ||
113 | static char *lineptr; | ||
114 | static int lineleft; | ||
115 | |||
116 | int | ||
117 | xmon_getchar(void) | ||
118 | { | ||
119 | int c; | ||
120 | |||
121 | if (lineleft == 0) { | ||
122 | lineptr = line; | ||
123 | for (;;) { | ||
124 | c = xmon_readchar(); | ||
125 | if (c == -1 || c == 4) | ||
126 | break; | ||
127 | if (c == '\r' || c == '\n') { | ||
128 | *lineptr++ = '\n'; | ||
129 | xmon_putchar('\n'); | ||
130 | break; | ||
131 | } | ||
132 | switch (c) { | ||
133 | case 0177: | ||
134 | case '\b': | ||
135 | if (lineptr > line) { | ||
136 | xmon_putchar('\b'); | ||
137 | xmon_putchar(' '); | ||
138 | xmon_putchar('\b'); | ||
139 | --lineptr; | ||
140 | } | ||
141 | break; | ||
142 | case 'U' & 0x1F: | ||
143 | while (lineptr > line) { | ||
144 | xmon_putchar('\b'); | ||
145 | xmon_putchar(' '); | ||
146 | xmon_putchar('\b'); | ||
147 | --lineptr; | ||
148 | } | ||
149 | break; | ||
150 | default: | ||
151 | if (lineptr >= &line[sizeof(line) - 1]) | ||
152 | xmon_putchar('\a'); | ||
153 | else { | ||
154 | xmon_putchar(c); | ||
155 | *lineptr++ = c; | ||
156 | } | ||
157 | } | ||
158 | } | ||
159 | lineleft = lineptr - line; | ||
160 | lineptr = line; | ||
161 | } | ||
162 | if (lineleft == 0) | ||
163 | return -1; | ||
164 | --lineleft; | ||
165 | return *lineptr++; | ||
166 | } | ||
167 | |||
168 | char * | ||
169 | xmon_fgets(char *str, int nb, void *f) | ||
170 | { | ||
171 | char *p; | ||
172 | int c; | ||
173 | |||
174 | for (p = str; p < str + nb - 1; ) { | ||
175 | c = xmon_getchar(); | ||
176 | if (c == -1) { | ||
177 | if (p == str) | ||
178 | return NULL; | ||
179 | break; | ||
180 | } | ||
181 | *p++ = c; | ||
182 | if (c == '\n') | ||
183 | break; | ||
184 | } | ||
185 | *p = 0; | ||
186 | return str; | ||
187 | } | ||
diff --git a/arch/powerpc/xmon/start_8xx.c b/arch/powerpc/xmon/start_8xx.c index a48bd594cf61..4c17b0486ad5 100644 --- a/arch/powerpc/xmon/start_8xx.c +++ b/arch/powerpc/xmon/start_8xx.c | |||
@@ -15,273 +15,30 @@ | |||
15 | #include <asm/8xx_immap.h> | 15 | #include <asm/8xx_immap.h> |
16 | #include <asm/mpc8xx.h> | 16 | #include <asm/mpc8xx.h> |
17 | #include <asm/commproc.h> | 17 | #include <asm/commproc.h> |
18 | #include "nonstdio.h" | ||
18 | 19 | ||
19 | extern void xmon_printf(const char *fmt, ...); | ||
20 | extern int xmon_8xx_write(char *str, int nb); | 20 | extern int xmon_8xx_write(char *str, int nb); |
21 | extern int xmon_8xx_read_poll(void); | 21 | extern int xmon_8xx_read_poll(void); |
22 | extern int xmon_8xx_read_char(void); | 22 | extern int xmon_8xx_read_char(void); |
23 | void prom_drawhex(uint); | ||
24 | void prom_drawstring(const char *str); | ||
25 | 23 | ||
26 | static int use_screen = 1; /* default */ | 24 | void xmon_map_scc(void) |
27 | |||
28 | #define TB_SPEED 25000000 | ||
29 | |||
30 | static inline unsigned int readtb(void) | ||
31 | { | ||
32 | unsigned int ret; | ||
33 | |||
34 | asm volatile("mftb %0" : "=r" (ret) :); | ||
35 | return ret; | ||
36 | } | ||
37 | |||
38 | void buf_access(void) | ||
39 | { | ||
40 | } | ||
41 | |||
42 | void | ||
43 | xmon_map_scc(void) | ||
44 | { | 25 | { |
45 | |||
46 | cpmp = (cpm8xx_t *)&(((immap_t *)IMAP_ADDR)->im_cpm); | 26 | cpmp = (cpm8xx_t *)&(((immap_t *)IMAP_ADDR)->im_cpm); |
47 | use_screen = 0; | ||
48 | |||
49 | prom_drawstring("xmon uses serial port\n"); | ||
50 | } | 27 | } |
51 | 28 | ||
52 | static int scc_initialized = 0; | ||
53 | |||
54 | void xmon_init_scc(void); | 29 | void xmon_init_scc(void); |
55 | 30 | ||
56 | int | 31 | int xmon_write(void *ptr, int nb) |
57 | xmon_write(void *handle, void *ptr, int nb) | ||
58 | { | 32 | { |
59 | char *p = ptr; | ||
60 | int i, c, ct; | ||
61 | |||
62 | if (!scc_initialized) | ||
63 | xmon_init_scc(); | ||
64 | |||
65 | return(xmon_8xx_write(ptr, nb)); | 33 | return(xmon_8xx_write(ptr, nb)); |
66 | } | 34 | } |
67 | 35 | ||
68 | int xmon_wants_key; | 36 | int xmon_readchar(void) |
69 | |||
70 | int | ||
71 | xmon_read(void *handle, void *ptr, int nb) | ||
72 | { | 37 | { |
73 | char *p = ptr; | 38 | return xmon_8xx_read_char(); |
74 | int i; | ||
75 | |||
76 | if (!scc_initialized) | ||
77 | xmon_init_scc(); | ||
78 | |||
79 | for (i = 0; i < nb; ++i) { | ||
80 | *p++ = xmon_8xx_read_char(); | ||
81 | } | ||
82 | return i; | ||
83 | } | 39 | } |
84 | 40 | ||
85 | int | 41 | int xmon_read_poll(void) |
86 | xmon_read_poll(void) | ||
87 | { | 42 | { |
88 | return(xmon_8xx_read_poll()); | 43 | return(xmon_8xx_read_poll()); |
89 | } | 44 | } |
90 | |||
91 | void | ||
92 | xmon_init_scc() | ||
93 | { | ||
94 | scc_initialized = 1; | ||
95 | } | ||
96 | |||
97 | #if 0 | ||
98 | extern int (*prom_entry)(void *); | ||
99 | |||
100 | int | ||
101 | xmon_exit(void) | ||
102 | { | ||
103 | struct prom_args { | ||
104 | char *service; | ||
105 | } args; | ||
106 | |||
107 | for (;;) { | ||
108 | args.service = "exit"; | ||
109 | (*prom_entry)(&args); | ||
110 | } | ||
111 | } | ||
112 | #endif | ||
113 | |||
114 | void *xmon_stdin; | ||
115 | void *xmon_stdout; | ||
116 | void *xmon_stderr; | ||
117 | |||
118 | void | ||
119 | xmon_init(void) | ||
120 | { | ||
121 | } | ||
122 | |||
123 | int | ||
124 | xmon_putc(int c, void *f) | ||
125 | { | ||
126 | char ch = c; | ||
127 | |||
128 | if (c == '\n') | ||
129 | xmon_putc('\r', f); | ||
130 | return xmon_write(f, &ch, 1) == 1? c: -1; | ||
131 | } | ||
132 | |||
133 | int | ||
134 | xmon_putchar(int c) | ||
135 | { | ||
136 | return xmon_putc(c, xmon_stdout); | ||
137 | } | ||
138 | |||
139 | int | ||
140 | xmon_fputs(char *str, void *f) | ||
141 | { | ||
142 | int n = strlen(str); | ||
143 | |||
144 | return xmon_write(f, str, n) == n? 0: -1; | ||
145 | } | ||
146 | |||
147 | int | ||
148 | xmon_readchar(void) | ||
149 | { | ||
150 | char ch; | ||
151 | |||
152 | for (;;) { | ||
153 | switch (xmon_read(xmon_stdin, &ch, 1)) { | ||
154 | case 1: | ||
155 | return ch; | ||
156 | case -1: | ||
157 | xmon_printf("read(stdin) returned -1\r\n", 0, 0); | ||
158 | return -1; | ||
159 | } | ||
160 | } | ||
161 | } | ||
162 | |||
163 | static char line[256]; | ||
164 | static char *lineptr; | ||
165 | static int lineleft; | ||
166 | |||
167 | #if 0 | ||
168 | int xmon_expect(const char *str, unsigned int timeout) | ||
169 | { | ||
170 | int c; | ||
171 | unsigned int t0; | ||
172 | |||
173 | timeout *= TB_SPEED; | ||
174 | t0 = readtb(); | ||
175 | do { | ||
176 | lineptr = line; | ||
177 | for (;;) { | ||
178 | c = xmon_read_poll(); | ||
179 | if (c == -1) { | ||
180 | if (readtb() - t0 > timeout) | ||
181 | return 0; | ||
182 | continue; | ||
183 | } | ||
184 | if (c == '\n') | ||
185 | break; | ||
186 | if (c != '\r' && lineptr < &line[sizeof(line) - 1]) | ||
187 | *lineptr++ = c; | ||
188 | } | ||
189 | *lineptr = 0; | ||
190 | } while (strstr(line, str) == NULL); | ||
191 | return 1; | ||
192 | } | ||
193 | #endif | ||
194 | |||
195 | int | ||
196 | xmon_getchar(void) | ||
197 | { | ||
198 | int c; | ||
199 | |||
200 | if (lineleft == 0) { | ||
201 | lineptr = line; | ||
202 | for (;;) { | ||
203 | c = xmon_readchar(); | ||
204 | if (c == -1 || c == 4) | ||
205 | break; | ||
206 | if (c == '\r' || c == '\n') { | ||
207 | *lineptr++ = '\n'; | ||
208 | xmon_putchar('\n'); | ||
209 | break; | ||
210 | } | ||
211 | switch (c) { | ||
212 | case 0177: | ||
213 | case '\b': | ||
214 | if (lineptr > line) { | ||
215 | xmon_putchar('\b'); | ||
216 | xmon_putchar(' '); | ||
217 | xmon_putchar('\b'); | ||
218 | --lineptr; | ||
219 | } | ||
220 | break; | ||
221 | case 'U' & 0x1F: | ||
222 | while (lineptr > line) { | ||
223 | xmon_putchar('\b'); | ||
224 | xmon_putchar(' '); | ||
225 | xmon_putchar('\b'); | ||
226 | --lineptr; | ||
227 | } | ||
228 | break; | ||
229 | default: | ||
230 | if (lineptr >= &line[sizeof(line) - 1]) | ||
231 | xmon_putchar('\a'); | ||
232 | else { | ||
233 | xmon_putchar(c); | ||
234 | *lineptr++ = c; | ||
235 | } | ||
236 | } | ||
237 | } | ||
238 | lineleft = lineptr - line; | ||
239 | lineptr = line; | ||
240 | } | ||
241 | if (lineleft == 0) | ||
242 | return -1; | ||
243 | --lineleft; | ||
244 | return *lineptr++; | ||
245 | } | ||
246 | |||
247 | char * | ||
248 | xmon_fgets(char *str, int nb, void *f) | ||
249 | { | ||
250 | char *p; | ||
251 | int c; | ||
252 | |||
253 | for (p = str; p < str + nb - 1; ) { | ||
254 | c = xmon_getchar(); | ||
255 | if (c == -1) { | ||
256 | if (p == str) | ||
257 | return 0; | ||
258 | break; | ||
259 | } | ||
260 | *p++ = c; | ||
261 | if (c == '\n') | ||
262 | break; | ||
263 | } | ||
264 | *p = 0; | ||
265 | return str; | ||
266 | } | ||
267 | |||
268 | void | ||
269 | prom_drawhex(uint val) | ||
270 | { | ||
271 | unsigned char buf[10]; | ||
272 | |||
273 | int i; | ||
274 | for (i = 7; i >= 0; i--) | ||
275 | { | ||
276 | buf[i] = "0123456789abcdef"[val & 0x0f]; | ||
277 | val >>= 4; | ||
278 | } | ||
279 | buf[8] = '\0'; | ||
280 | xmon_fputs(buf, xmon_stdout); | ||
281 | } | ||
282 | |||
283 | void | ||
284 | prom_drawstring(const char *str) | ||
285 | { | ||
286 | xmon_fputs(str, xmon_stdout); | ||
287 | } | ||
diff --git a/arch/powerpc/xmon/subr_prf.c b/arch/powerpc/xmon/subr_prf.c deleted file mode 100644 index b48738c6dd33..000000000000 --- a/arch/powerpc/xmon/subr_prf.c +++ /dev/null | |||
@@ -1,54 +0,0 @@ | |||
1 | /* | ||
2 | * Written by Cort Dougan to replace the version originally used | ||
3 | * by Paul Mackerras, which came from NetBSD and thus had copyright | ||
4 | * conflicts with Linux. | ||
5 | * | ||
6 | * This file makes liberal use of the standard linux utility | ||
7 | * routines to reduce the size of the binary. We assume we can | ||
8 | * trust some parts of Linux inside the debugger. | ||
9 | * -- Cort (cort@cs.nmt.edu) | ||
10 | * | ||
11 | * Copyright (C) 1999 Cort Dougan. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or | ||
14 | * modify it under the terms of the GNU General Public License | ||
15 | * as published by the Free Software Foundation; either version | ||
16 | * 2 of the License, or (at your option) any later version. | ||
17 | */ | ||
18 | |||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/string.h> | ||
21 | #include <linux/module.h> | ||
22 | #include <stdarg.h> | ||
23 | #include "nonstdio.h" | ||
24 | |||
25 | extern int xmon_write(void *, void *, int); | ||
26 | |||
27 | void xmon_vfprintf(void *f, const char *fmt, va_list ap) | ||
28 | { | ||
29 | static char xmon_buf[2048]; | ||
30 | int n; | ||
31 | |||
32 | n = vsprintf(xmon_buf, fmt, ap); | ||
33 | xmon_write(f, xmon_buf, n); | ||
34 | } | ||
35 | |||
36 | void xmon_printf(const char *fmt, ...) | ||
37 | { | ||
38 | va_list ap; | ||
39 | |||
40 | va_start(ap, fmt); | ||
41 | xmon_vfprintf(stdout, fmt, ap); | ||
42 | va_end(ap); | ||
43 | } | ||
44 | EXPORT_SYMBOL(xmon_printf); | ||
45 | |||
46 | void xmon_fprintf(void *f, const char *fmt, ...) | ||
47 | { | ||
48 | va_list ap; | ||
49 | |||
50 | va_start(ap, fmt); | ||
51 | xmon_vfprintf(f, fmt, ap); | ||
52 | va_end(ap); | ||
53 | } | ||
54 | |||
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index 1124f1146202..cfcb2a56d662 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Routines providing a simple monitor for use on the PowerMac. | 2 | * Routines providing a simple monitor for use on the PowerMac. |
3 | * | 3 | * |
4 | * Copyright (C) 1996 Paul Mackerras. | 4 | * Copyright (C) 1996-2005 Paul Mackerras. |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
7 | * modify it under the terms of the GNU General Public License | 7 | * modify it under the terms of the GNU General Public License |
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/kallsyms.h> | 18 | #include <linux/kallsyms.h> |
19 | #include <linux/cpumask.h> | 19 | #include <linux/cpumask.h> |
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/sysrq.h> | ||
21 | 22 | ||
22 | #include <asm/ptrace.h> | 23 | #include <asm/ptrace.h> |
23 | #include <asm/string.h> | 24 | #include <asm/string.h> |
@@ -144,15 +145,10 @@ static void xmon_print_symbol(unsigned long address, const char *mid, | |||
144 | static const char *getvecname(unsigned long vec); | 145 | static const char *getvecname(unsigned long vec); |
145 | 146 | ||
146 | extern int print_insn_powerpc(unsigned long, unsigned long, int); | 147 | extern int print_insn_powerpc(unsigned long, unsigned long, int); |
147 | extern void printf(const char *fmt, ...); | ||
148 | extern void xmon_vfprintf(void *f, const char *fmt, va_list ap); | ||
149 | extern int xmon_putc(int c, void *f); | ||
150 | extern int putchar(int ch); | ||
151 | 148 | ||
152 | extern void xmon_enter(void); | 149 | extern void xmon_enter(void); |
153 | extern void xmon_leave(void); | 150 | extern void xmon_leave(void); |
154 | 151 | ||
155 | extern int xmon_read_poll(void); | ||
156 | extern long setjmp(long *); | 152 | extern long setjmp(long *); |
157 | extern void longjmp(long *, long); | 153 | extern void longjmp(long *, long); |
158 | extern void xmon_save_regs(struct pt_regs *); | 154 | extern void xmon_save_regs(struct pt_regs *); |
@@ -748,7 +744,6 @@ cmds(struct pt_regs *excp) | |||
748 | printf("%x:", smp_processor_id()); | 744 | printf("%x:", smp_processor_id()); |
749 | #endif /* CONFIG_SMP */ | 745 | #endif /* CONFIG_SMP */ |
750 | printf("mon> "); | 746 | printf("mon> "); |
751 | fflush(stdout); | ||
752 | flush_input(); | 747 | flush_input(); |
753 | termch = 0; | 748 | termch = 0; |
754 | cmd = skipbl(); | 749 | cmd = skipbl(); |
@@ -1797,7 +1792,7 @@ memex(void) | |||
1797 | for(;;){ | 1792 | for(;;){ |
1798 | if (!mnoread) | 1793 | if (!mnoread) |
1799 | n = mread(adrs, val, size); | 1794 | n = mread(adrs, val, size); |
1800 | printf("%.16x%c", adrs, brev? 'r': ' '); | 1795 | printf(REG"%c", adrs, brev? 'r': ' '); |
1801 | if (!mnoread) { | 1796 | if (!mnoread) { |
1802 | if (brev) | 1797 | if (brev) |
1803 | byterev(val, size); | 1798 | byterev(val, size); |
@@ -1976,17 +1971,18 @@ prdump(unsigned long adrs, long ndump) | |||
1976 | nr = mread(adrs, temp, r); | 1971 | nr = mread(adrs, temp, r); |
1977 | adrs += nr; | 1972 | adrs += nr; |
1978 | for (m = 0; m < r; ++m) { | 1973 | for (m = 0; m < r; ++m) { |
1979 | if ((m & 7) == 0 && m > 0) | 1974 | if ((m & (sizeof(long) - 1)) == 0 && m > 0) |
1980 | putchar(' '); | 1975 | putchar(' '); |
1981 | if (m < nr) | 1976 | if (m < nr) |
1982 | printf("%.2x", temp[m]); | 1977 | printf("%.2x", temp[m]); |
1983 | else | 1978 | else |
1984 | printf("%s", fault_chars[fault_type]); | 1979 | printf("%s", fault_chars[fault_type]); |
1985 | } | 1980 | } |
1986 | if (m <= 8) | 1981 | for (; m < 16; ++m) { |
1987 | printf(" "); | 1982 | if ((m & (sizeof(long) - 1)) == 0) |
1988 | for (; m < 16; ++m) | 1983 | putchar(' '); |
1989 | printf(" "); | 1984 | printf(" "); |
1985 | } | ||
1990 | printf(" |"); | 1986 | printf(" |"); |
1991 | for (m = 0; m < r; ++m) { | 1987 | for (m = 0; m < r; ++m) { |
1992 | if (m < nr) { | 1988 | if (m < nr) { |
@@ -2151,7 +2147,6 @@ memzcan(void) | |||
2151 | ok = mread(a, &v, 1); | 2147 | ok = mread(a, &v, 1); |
2152 | if (ok && !ook) { | 2148 | if (ok && !ook) { |
2153 | printf("%.8x .. ", a); | 2149 | printf("%.8x .. ", a); |
2154 | fflush(stdout); | ||
2155 | } else if (!ok && ook) | 2150 | } else if (!ok && ook) |
2156 | printf("%.8x\n", a - mskip); | 2151 | printf("%.8x\n", a - mskip); |
2157 | ook = ok; | 2152 | ook = ok; |
@@ -2372,7 +2367,7 @@ int | |||
2372 | inchar(void) | 2367 | inchar(void) |
2373 | { | 2368 | { |
2374 | if (lineptr == NULL || *lineptr == 0) { | 2369 | if (lineptr == NULL || *lineptr == 0) { |
2375 | if (fgets(line, sizeof(line), stdin) == NULL) { | 2370 | if (xmon_gets(line, sizeof(line)) == NULL) { |
2376 | lineptr = NULL; | 2371 | lineptr = NULL; |
2377 | return EOF; | 2372 | return EOF; |
2378 | } | 2373 | } |
@@ -2526,4 +2521,29 @@ void xmon_init(int enable) | |||
2526 | __debugger_dabr_match = NULL; | 2521 | __debugger_dabr_match = NULL; |
2527 | __debugger_fault_handler = NULL; | 2522 | __debugger_fault_handler = NULL; |
2528 | } | 2523 | } |
2524 | xmon_map_scc(); | ||
2525 | } | ||
2526 | |||
2527 | #ifdef CONFIG_MAGIC_SYSRQ | ||
2528 | static void sysrq_handle_xmon(int key, struct pt_regs *pt_regs, | ||
2529 | struct tty_struct *tty) | ||
2530 | { | ||
2531 | /* ensure xmon is enabled */ | ||
2532 | xmon_init(1); | ||
2533 | debugger(pt_regs); | ||
2534 | } | ||
2535 | |||
2536 | static struct sysrq_key_op sysrq_xmon_op = | ||
2537 | { | ||
2538 | .handler = sysrq_handle_xmon, | ||
2539 | .help_msg = "Xmon", | ||
2540 | .action_msg = "Entering xmon", | ||
2541 | }; | ||
2542 | |||
2543 | static int __init setup_xmon_sysrq(void) | ||
2544 | { | ||
2545 | register_sysrq_key('x', &sysrq_xmon_op); | ||
2546 | return 0; | ||
2529 | } | 2547 | } |
2548 | __initcall(setup_xmon_sysrq); | ||
2549 | #endif /* CONFIG_MAGIC_SYSRQ */ | ||
diff --git a/arch/ppc/boot/include/of1275.h b/arch/ppc/boot/include/of1275.h index 69173df76db0..4ed88acfa73a 100644 --- a/arch/ppc/boot/include/of1275.h +++ b/arch/ppc/boot/include/of1275.h | |||
@@ -19,6 +19,9 @@ extern prom_entry of_prom_entry; | |||
19 | 19 | ||
20 | /* function declarations */ | 20 | /* function declarations */ |
21 | 21 | ||
22 | int call_prom(const char *service, int nargs, int nret, ...); | ||
23 | int call_prom_ret(const char *service, int nargs, int nret, | ||
24 | unsigned int *rets, ...); | ||
22 | void * claim(unsigned int virt, unsigned int size, unsigned int align); | 25 | void * claim(unsigned int virt, unsigned int size, unsigned int align); |
23 | int map(unsigned int phys, unsigned int virt, unsigned int size); | 26 | int map(unsigned int phys, unsigned int virt, unsigned int size); |
24 | void enter(void); | 27 | void enter(void); |
diff --git a/arch/ppc/boot/of1275/Makefile b/arch/ppc/boot/of1275/Makefile index 02e6f235d7cb..0b979c004972 100644 --- a/arch/ppc/boot/of1275/Makefile +++ b/arch/ppc/boot/of1275/Makefile | |||
@@ -3,4 +3,4 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | lib-y := claim.o enter.o exit.o finddevice.o getprop.o ofinit.o \ | 5 | lib-y := claim.o enter.o exit.o finddevice.o getprop.o ofinit.o \ |
6 | ofstdio.o read.o release.o write.o map.o | 6 | ofstdio.o read.o release.o write.o map.o call_prom.o |
diff --git a/arch/ppc/boot/of1275/call_prom.c b/arch/ppc/boot/of1275/call_prom.c new file mode 100644 index 000000000000..9479a3a2b8c7 --- /dev/null +++ b/arch/ppc/boot/of1275/call_prom.c | |||
@@ -0,0 +1,74 @@ | |||
1 | /* | ||
2 | * Copyright (C) 1996-2005 Paul Mackerras. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | */ | ||
9 | |||
10 | #include "of1275.h" | ||
11 | #include <stdarg.h> | ||
12 | |||
13 | int call_prom(const char *service, int nargs, int nret, ...) | ||
14 | { | ||
15 | int i; | ||
16 | struct prom_args { | ||
17 | const char *service; | ||
18 | int nargs; | ||
19 | int nret; | ||
20 | unsigned int args[12]; | ||
21 | } args; | ||
22 | va_list list; | ||
23 | |||
24 | args.service = service; | ||
25 | args.nargs = nargs; | ||
26 | args.nret = nret; | ||
27 | |||
28 | va_start(list, nret); | ||
29 | for (i = 0; i < nargs; i++) | ||
30 | args.args[i] = va_arg(list, unsigned int); | ||
31 | va_end(list); | ||
32 | |||
33 | for (i = 0; i < nret; i++) | ||
34 | args.args[nargs+i] = 0; | ||
35 | |||
36 | if (of_prom_entry(&args) < 0) | ||
37 | return -1; | ||
38 | |||
39 | return (nret > 0)? args.args[nargs]: 0; | ||
40 | } | ||
41 | |||
42 | int call_prom_ret(const char *service, int nargs, int nret, | ||
43 | unsigned int *rets, ...) | ||
44 | { | ||
45 | int i; | ||
46 | struct prom_args { | ||
47 | const char *service; | ||
48 | int nargs; | ||
49 | int nret; | ||
50 | unsigned int args[12]; | ||
51 | } args; | ||
52 | va_list list; | ||
53 | |||
54 | args.service = service; | ||
55 | args.nargs = nargs; | ||
56 | args.nret = nret; | ||
57 | |||
58 | va_start(list, rets); | ||
59 | for (i = 0; i < nargs; i++) | ||
60 | args.args[i] = va_arg(list, unsigned int); | ||
61 | va_end(list); | ||
62 | |||
63 | for (i = 0; i < nret; i++) | ||
64 | args.args[nargs+i] = 0; | ||
65 | |||
66 | if (of_prom_entry(&args) < 0) | ||
67 | return -1; | ||
68 | |||
69 | if (rets != (void *) 0) | ||
70 | for (i = 1; i < nret; ++i) | ||
71 | rets[i-1] = args.args[nargs+i]; | ||
72 | |||
73 | return (nret > 0)? args.args[nargs]: 0; | ||
74 | } | ||
diff --git a/arch/ppc/boot/of1275/claim.c b/arch/ppc/boot/of1275/claim.c index 13169a5c4339..1ed3aeeff8ae 100644 --- a/arch/ppc/boot/of1275/claim.c +++ b/arch/ppc/boot/of1275/claim.c | |||
@@ -9,27 +9,84 @@ | |||
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include "of1275.h" | 11 | #include "of1275.h" |
12 | #include "nonstdio.h" | ||
12 | 13 | ||
13 | void * | 14 | /* |
14 | claim(unsigned int virt, unsigned int size, unsigned int align) | 15 | * Older OF's require that when claiming a specific range of addresses, |
16 | * we claim the physical space in the /memory node and the virtual | ||
17 | * space in the chosen mmu node, and then do a map operation to | ||
18 | * map virtual to physical. | ||
19 | */ | ||
20 | static int need_map = -1; | ||
21 | static ihandle chosen_mmu; | ||
22 | static phandle memory; | ||
23 | |||
24 | /* returns true if s2 is a prefix of s1 */ | ||
25 | static int string_match(const char *s1, const char *s2) | ||
26 | { | ||
27 | for (; *s2; ++s2) | ||
28 | if (*s1++ != *s2) | ||
29 | return 0; | ||
30 | return 1; | ||
31 | } | ||
32 | |||
33 | static int check_of_version(void) | ||
34 | { | ||
35 | phandle oprom, chosen; | ||
36 | char version[64]; | ||
37 | |||
38 | oprom = finddevice("/openprom"); | ||
39 | if (oprom == OF_INVALID_HANDLE) | ||
40 | return 0; | ||
41 | if (getprop(oprom, "model", version, sizeof(version)) <= 0) | ||
42 | return 0; | ||
43 | version[sizeof(version)-1] = 0; | ||
44 | printf("OF version = '%s'\n", version); | ||
45 | if (!string_match(version, "Open Firmware, 1.") | ||
46 | && !string_match(version, "FirmWorks,3.")) | ||
47 | return 0; | ||
48 | chosen = finddevice("/chosen"); | ||
49 | if (chosen == OF_INVALID_HANDLE) { | ||
50 | chosen = finddevice("/chosen@0"); | ||
51 | if (chosen == OF_INVALID_HANDLE) { | ||
52 | printf("no chosen\n"); | ||
53 | return 0; | ||
54 | } | ||
55 | } | ||
56 | if (getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) { | ||
57 | printf("no mmu\n"); | ||
58 | return 0; | ||
59 | } | ||
60 | memory = (ihandle) call_prom("open", 1, 1, "/memory"); | ||
61 | if (memory == OF_INVALID_HANDLE) { | ||
62 | memory = (ihandle) call_prom("open", 1, 1, "/memory@0"); | ||
63 | if (memory == OF_INVALID_HANDLE) { | ||
64 | printf("no memory node\n"); | ||
65 | return 0; | ||
66 | } | ||
67 | } | ||
68 | printf("old OF detected\n"); | ||
69 | return 1; | ||
70 | } | ||
71 | |||
72 | void *claim(unsigned int virt, unsigned int size, unsigned int align) | ||
15 | { | 73 | { |
16 | struct prom_args { | 74 | int ret; |
17 | char *service; | 75 | unsigned int result; |
18 | int nargs; | ||
19 | int nret; | ||
20 | unsigned int virt; | ||
21 | unsigned int size; | ||
22 | unsigned int align; | ||
23 | void *ret; | ||
24 | } args; | ||
25 | 76 | ||
26 | args.service = "claim"; | 77 | if (need_map < 0) |
27 | args.nargs = 3; | 78 | need_map = check_of_version(); |
28 | args.nret = 1; | 79 | if (align || !need_map) |
29 | args.virt = virt; | 80 | return (void *) call_prom("claim", 3, 1, virt, size, align); |
30 | args.size = size; | 81 | |
31 | args.align = align; | 82 | ret = call_prom_ret("call-method", 5, 2, &result, "claim", memory, |
32 | args.ret = (void *) 0; | 83 | align, size, virt); |
33 | (*of_prom_entry)(&args); | 84 | if (ret != 0 || result == -1) |
34 | return args.ret; | 85 | return (void *) -1; |
86 | ret = call_prom_ret("call-method", 5, 2, &result, "claim", chosen_mmu, | ||
87 | align, size, virt); | ||
88 | /* 0x12 == coherent + read/write */ | ||
89 | ret = call_prom("call-method", 6, 1, "map", chosen_mmu, | ||
90 | 0x12, size, virt, virt); | ||
91 | return virt; | ||
35 | } | 92 | } |
diff --git a/arch/ppc/boot/of1275/finddevice.c b/arch/ppc/boot/of1275/finddevice.c index 2c0f7cbb793e..0dcb1201b772 100644 --- a/arch/ppc/boot/of1275/finddevice.c +++ b/arch/ppc/boot/of1275/finddevice.c | |||
@@ -10,22 +10,7 @@ | |||
10 | 10 | ||
11 | #include "of1275.h" | 11 | #include "of1275.h" |
12 | 12 | ||
13 | phandle | 13 | phandle finddevice(const char *name) |
14 | finddevice(const char *name) | ||
15 | { | 14 | { |
16 | struct prom_args { | 15 | return (phandle) call_prom("finddevice", 1, 1, name); |
17 | char *service; | ||
18 | int nargs; | ||
19 | int nret; | ||
20 | const char *devspec; | ||
21 | phandle device; | ||
22 | } args; | ||
23 | |||
24 | args.service = "finddevice"; | ||
25 | args.nargs = 1; | ||
26 | args.nret = 1; | ||
27 | args.devspec = name; | ||
28 | args.device = OF_INVALID_HANDLE; | ||
29 | (*of_prom_entry)(&args); | ||
30 | return args.device; | ||
31 | } | 16 | } |
diff --git a/arch/ppc/boot/openfirmware/Makefile b/arch/ppc/boot/openfirmware/Makefile index 03415238fabf..83a6433459ce 100644 --- a/arch/ppc/boot/openfirmware/Makefile +++ b/arch/ppc/boot/openfirmware/Makefile | |||
@@ -80,8 +80,7 @@ $(obj)/note: $(utils)/mknote FORCE | |||
80 | $(call if_changed,mknote) | 80 | $(call if_changed,mknote) |
81 | 81 | ||
82 | 82 | ||
83 | $(obj)/coffcrt0.o: EXTRA_AFLAGS := -traditional -DXCOFF | 83 | $(obj)/coffcrt0.o: EXTRA_AFLAGS := -DXCOFF |
84 | $(obj)/crt0.o: EXTRA_AFLAGS := -traditional | ||
85 | targets += coffcrt0.o crt0.o | 84 | targets += coffcrt0.o crt0.o |
86 | $(obj)/coffcrt0.o $(obj)/crt0.o: $(common)/crt0.S FORCE | 85 | $(obj)/coffcrt0.o $(obj)/crt0.o: $(common)/crt0.S FORCE |
87 | $(call if_changed_dep,as_o_S) | 86 | $(call if_changed_dep,as_o_S) |
diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile index 76a55a438f23..17a4da65e275 100644 --- a/arch/ppc/kernel/Makefile +++ b/arch/ppc/kernel/Makefile | |||
@@ -12,7 +12,7 @@ extra-$(CONFIG_6xx) += idle_6xx.o | |||
12 | extra-$(CONFIG_POWER4) += idle_power4.o | 12 | extra-$(CONFIG_POWER4) += idle_power4.o |
13 | extra-y += vmlinux.lds | 13 | extra-y += vmlinux.lds |
14 | 14 | ||
15 | obj-y := entry.o traps.o irq.o idle.o time.o misc.o \ | 15 | obj-y := entry.o traps.o idle.o time.o misc.o \ |
16 | process.o align.o \ | 16 | process.o align.o \ |
17 | setup.o \ | 17 | setup.o \ |
18 | ppc_htab.o | 18 | ppc_htab.o |
@@ -38,8 +38,7 @@ endif | |||
38 | # These are here while we do the architecture merge | 38 | # These are here while we do the architecture merge |
39 | 39 | ||
40 | else | 40 | else |
41 | obj-y := irq.o idle.o \ | 41 | obj-y := idle.o align.o |
42 | align.o | ||
43 | obj-$(CONFIG_6xx) += l2cr.o cpu_setup_6xx.o | 42 | obj-$(CONFIG_6xx) += l2cr.o cpu_setup_6xx.o |
44 | obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o | 43 | obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o |
45 | obj-$(CONFIG_MODULES) += module.o | 44 | obj-$(CONFIG_MODULES) += module.o |
diff --git a/arch/ppc/kernel/head_booke.h b/arch/ppc/kernel/head_booke.h index aeb349b47af3..f3d274c6b231 100644 --- a/arch/ppc/kernel/head_booke.h +++ b/arch/ppc/kernel/head_booke.h | |||
@@ -358,6 +358,6 @@ label: | |||
358 | NORMAL_EXCEPTION_PROLOG; \ | 358 | NORMAL_EXCEPTION_PROLOG; \ |
359 | bne load_up_fpu; /* if from user, just load it up */ \ | 359 | bne load_up_fpu; /* if from user, just load it up */ \ |
360 | addi r3,r1,STACK_FRAME_OVERHEAD; \ | 360 | addi r3,r1,STACK_FRAME_OVERHEAD; \ |
361 | EXC_XFER_EE_LITE(0x800, KernelFP) | 361 | EXC_XFER_EE_LITE(0x800, kernel_fp_unavailable_exception) |
362 | 362 | ||
363 | #endif /* __HEAD_BOOKE_H__ */ | 363 | #endif /* __HEAD_BOOKE_H__ */ |
diff --git a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c deleted file mode 100644 index fbb2b9f8922c..000000000000 --- a/arch/ppc/kernel/irq.c +++ /dev/null | |||
@@ -1,165 +0,0 @@ | |||
1 | /* | ||
2 | * arch/ppc/kernel/irq.c | ||
3 | * | ||
4 | * Derived from arch/i386/kernel/irq.c | ||
5 | * Copyright (C) 1992 Linus Torvalds | ||
6 | * Adapted from arch/i386 by Gary Thomas | ||
7 | * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) | ||
8 | * Updated and modified by Cort Dougan <cort@fsmlabs.com> | ||
9 | * Copyright (C) 1996-2001 Cort Dougan | ||
10 | * Adapted for Power Macintosh by Paul Mackerras | ||
11 | * Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au) | ||
12 | * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||
13 | * | ||
14 | * This file contains the code used by various IRQ handling routines: | ||
15 | * asking for different IRQ's should be done through these routines | ||
16 | * instead of just grabbing them. Thus setups with different IRQ numbers | ||
17 | * shouldn't result in any weird surprises, and installing new handlers | ||
18 | * should be easier. | ||
19 | * | ||
20 | * The MPC8xx has an interrupt mask in the SIU. If a bit is set, the | ||
21 | * interrupt is _enabled_. As expected, IRQ0 is bit 0 in the 32-bit | ||
22 | * mask register (of which only 16 are defined), hence the weird shifting | ||
23 | * and complement of the cached_irq_mask. I want to be able to stuff | ||
24 | * this right into the SIU SMASK register. | ||
25 | * Many of the prep/chrp functions are conditional compiled on CONFIG_8xx | ||
26 | * to reduce code space and undefined function references. | ||
27 | */ | ||
28 | |||
29 | #include <linux/errno.h> | ||
30 | #include <linux/module.h> | ||
31 | #include <linux/threads.h> | ||
32 | #include <linux/kernel_stat.h> | ||
33 | #include <linux/signal.h> | ||
34 | #include <linux/sched.h> | ||
35 | #include <linux/ptrace.h> | ||
36 | #include <linux/ioport.h> | ||
37 | #include <linux/interrupt.h> | ||
38 | #include <linux/timex.h> | ||
39 | #include <linux/config.h> | ||
40 | #include <linux/init.h> | ||
41 | #include <linux/slab.h> | ||
42 | #include <linux/pci.h> | ||
43 | #include <linux/delay.h> | ||
44 | #include <linux/irq.h> | ||
45 | #include <linux/proc_fs.h> | ||
46 | #include <linux/random.h> | ||
47 | #include <linux/seq_file.h> | ||
48 | #include <linux/cpumask.h> | ||
49 | #include <linux/profile.h> | ||
50 | #include <linux/bitops.h> | ||
51 | |||
52 | #include <asm/uaccess.h> | ||
53 | #include <asm/system.h> | ||
54 | #include <asm/io.h> | ||
55 | #include <asm/pgtable.h> | ||
56 | #include <asm/irq.h> | ||
57 | #include <asm/cache.h> | ||
58 | #include <asm/prom.h> | ||
59 | #include <asm/ptrace.h> | ||
60 | #include <asm/machdep.h> | ||
61 | |||
62 | #define NR_MASK_WORDS ((NR_IRQS + 31) / 32) | ||
63 | |||
64 | extern atomic_t ipi_recv; | ||
65 | extern atomic_t ipi_sent; | ||
66 | |||
67 | #define MAXCOUNT 10000000 | ||
68 | |||
69 | int ppc_spurious_interrupts = 0; | ||
70 | struct irqaction *ppc_irq_action[NR_IRQS]; | ||
71 | unsigned long ppc_cached_irq_mask[NR_MASK_WORDS]; | ||
72 | unsigned long ppc_lost_interrupts[NR_MASK_WORDS]; | ||
73 | atomic_t ppc_n_lost_interrupts; | ||
74 | |||
75 | #ifdef CONFIG_TAU_INT | ||
76 | extern int tau_initialized; | ||
77 | extern int tau_interrupts(int); | ||
78 | #endif | ||
79 | |||
80 | int show_interrupts(struct seq_file *p, void *v) | ||
81 | { | ||
82 | int i = *(loff_t *) v, j; | ||
83 | struct irqaction * action; | ||
84 | unsigned long flags; | ||
85 | |||
86 | if (i == 0) { | ||
87 | seq_puts(p, " "); | ||
88 | for (j=0; j<NR_CPUS; j++) | ||
89 | if (cpu_online(j)) | ||
90 | seq_printf(p, "CPU%d ", j); | ||
91 | seq_putc(p, '\n'); | ||
92 | } | ||
93 | |||
94 | if (i < NR_IRQS) { | ||
95 | spin_lock_irqsave(&irq_desc[i].lock, flags); | ||
96 | action = irq_desc[i].action; | ||
97 | if ( !action || !action->handler ) | ||
98 | goto skip; | ||
99 | seq_printf(p, "%3d: ", i); | ||
100 | #ifdef CONFIG_SMP | ||
101 | for (j = 0; j < NR_CPUS; j++) | ||
102 | if (cpu_online(j)) | ||
103 | seq_printf(p, "%10u ", | ||
104 | kstat_cpu(j).irqs[i]); | ||
105 | #else | ||
106 | seq_printf(p, "%10u ", kstat_irqs(i)); | ||
107 | #endif /* CONFIG_SMP */ | ||
108 | if (irq_desc[i].handler) | ||
109 | seq_printf(p, " %s ", irq_desc[i].handler->typename); | ||
110 | else | ||
111 | seq_puts(p, " None "); | ||
112 | seq_printf(p, "%s", (irq_desc[i].status & IRQ_LEVEL) ? "Level " : "Edge "); | ||
113 | seq_printf(p, " %s", action->name); | ||
114 | for (action = action->next; action; action = action->next) | ||
115 | seq_printf(p, ", %s", action->name); | ||
116 | seq_putc(p, '\n'); | ||
117 | skip: | ||
118 | spin_unlock_irqrestore(&irq_desc[i].lock, flags); | ||
119 | } else if (i == NR_IRQS) { | ||
120 | #ifdef CONFIG_TAU_INT | ||
121 | if (tau_initialized){ | ||
122 | seq_puts(p, "TAU: "); | ||
123 | for (j = 0; j < NR_CPUS; j++) | ||
124 | if (cpu_online(j)) | ||
125 | seq_printf(p, "%10u ", tau_interrupts(j)); | ||
126 | seq_puts(p, " PowerPC Thermal Assist (cpu temp)\n"); | ||
127 | } | ||
128 | #endif | ||
129 | #if defined(CONFIG_SMP) && !defined(CONFIG_PPC_MERGE) | ||
130 | /* should this be per processor send/receive? */ | ||
131 | seq_printf(p, "IPI (recv/sent): %10u/%u\n", | ||
132 | atomic_read(&ipi_recv), atomic_read(&ipi_sent)); | ||
133 | #endif | ||
134 | seq_printf(p, "BAD: %10u\n", ppc_spurious_interrupts); | ||
135 | } | ||
136 | return 0; | ||
137 | } | ||
138 | |||
139 | void do_IRQ(struct pt_regs *regs) | ||
140 | { | ||
141 | int irq, first = 1; | ||
142 | irq_enter(); | ||
143 | |||
144 | /* | ||
145 | * Every platform is required to implement ppc_md.get_irq. | ||
146 | * This function will either return an irq number or -1 to | ||
147 | * indicate there are no more pending. But the first time | ||
148 | * through the loop this means there wasn't and IRQ pending. | ||
149 | * The value -2 is for buggy hardware and means that this IRQ | ||
150 | * has already been handled. -- Tom | ||
151 | */ | ||
152 | while ((irq = ppc_md.get_irq(regs)) >= 0) { | ||
153 | __do_IRQ(irq, regs); | ||
154 | first = 0; | ||
155 | } | ||
156 | if (irq != -2 && first) | ||
157 | /* That's not SMP safe ... but who cares ? */ | ||
158 | ppc_spurious_interrupts++; | ||
159 | irq_exit(); | ||
160 | } | ||
161 | |||
162 | void __init init_IRQ(void) | ||
163 | { | ||
164 | ppc_md.init_IRQ(); | ||
165 | } | ||
diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S index ae6af29938a1..5e61124581d0 100644 --- a/arch/ppc/kernel/misc.S +++ b/arch/ppc/kernel/misc.S | |||
@@ -497,9 +497,9 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) | |||
497 | * and invalidate the corresponding instruction cache blocks. | 497 | * and invalidate the corresponding instruction cache blocks. |
498 | * This is a no-op on the 601. | 498 | * This is a no-op on the 601. |
499 | * | 499 | * |
500 | * flush_icache_range(unsigned long start, unsigned long stop) | 500 | * __flush_icache_range(unsigned long start, unsigned long stop) |
501 | */ | 501 | */ |
502 | _GLOBAL(flush_icache_range) | 502 | _GLOBAL(__flush_icache_range) |
503 | BEGIN_FTR_SECTION | 503 | BEGIN_FTR_SECTION |
504 | blr /* for 601, do nothing */ | 504 | blr /* for 601, do nothing */ |
505 | END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) | 505 | END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) |
diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c index e8f4e576750a..48ed58f995c0 100644 --- a/arch/ppc/kernel/pci.c +++ b/arch/ppc/kernel/pci.c | |||
@@ -62,20 +62,6 @@ struct pci_controller** hose_tail = &hose_head; | |||
62 | static int pci_bus_count; | 62 | static int pci_bus_count; |
63 | 63 | ||
64 | static void | 64 | static void |
65 | fixup_rev1_53c810(struct pci_dev* dev) | ||
66 | { | ||
67 | /* rev 1 ncr53c810 chips don't set the class at all which means | ||
68 | * they don't get their resources remapped. Fix that here. | ||
69 | */ | ||
70 | |||
71 | if ((dev->class == PCI_CLASS_NOT_DEFINED)) { | ||
72 | printk("NCR 53c810 rev 1 detected, setting PCI class.\n"); | ||
73 | dev->class = PCI_CLASS_STORAGE_SCSI; | ||
74 | } | ||
75 | } | ||
76 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, fixup_rev1_53c810); | ||
77 | |||
78 | static void | ||
79 | fixup_broken_pcnet32(struct pci_dev* dev) | 65 | fixup_broken_pcnet32(struct pci_dev* dev) |
80 | { | 66 | { |
81 | if ((dev->class>>8 == PCI_CLASS_NETWORK_ETHERNET)) { | 67 | if ((dev->class>>8 == PCI_CLASS_NETWORK_ETHERNET)) { |
diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c index e0ca61b37f4f..66073f775193 100644 --- a/arch/ppc/kernel/ppc_ksyms.c +++ b/arch/ppc/kernel/ppc_ksyms.c | |||
@@ -46,6 +46,7 @@ | |||
46 | #include <asm/btext.h> | 46 | #include <asm/btext.h> |
47 | #include <asm/div64.h> | 47 | #include <asm/div64.h> |
48 | #include <asm/xmon.h> | 48 | #include <asm/xmon.h> |
49 | #include <asm/signal.h> | ||
49 | 50 | ||
50 | #ifdef CONFIG_8xx | 51 | #ifdef CONFIG_8xx |
51 | #include <asm/commproc.h> | 52 | #include <asm/commproc.h> |
@@ -57,7 +58,6 @@ extern void machine_check_exception(struct pt_regs *regs); | |||
57 | extern void alignment_exception(struct pt_regs *regs); | 58 | extern void alignment_exception(struct pt_regs *regs); |
58 | extern void program_check_exception(struct pt_regs *regs); | 59 | extern void program_check_exception(struct pt_regs *regs); |
59 | extern void single_step_exception(struct pt_regs *regs); | 60 | extern void single_step_exception(struct pt_regs *regs); |
60 | extern int do_signal(sigset_t *, struct pt_regs *); | ||
61 | extern int pmac_newworld; | 61 | extern int pmac_newworld; |
62 | extern int sys_sigreturn(struct pt_regs *regs); | 62 | extern int sys_sigreturn(struct pt_regs *regs); |
63 | 63 | ||
@@ -78,7 +78,6 @@ EXPORT_SYMBOL(program_check_exception); | |||
78 | EXPORT_SYMBOL(single_step_exception); | 78 | EXPORT_SYMBOL(single_step_exception); |
79 | EXPORT_SYMBOL(sys_sigreturn); | 79 | EXPORT_SYMBOL(sys_sigreturn); |
80 | EXPORT_SYMBOL(ppc_n_lost_interrupts); | 80 | EXPORT_SYMBOL(ppc_n_lost_interrupts); |
81 | EXPORT_SYMBOL(ppc_lost_interrupts); | ||
82 | 81 | ||
83 | EXPORT_SYMBOL(ISA_DMA_THRESHOLD); | 82 | EXPORT_SYMBOL(ISA_DMA_THRESHOLD); |
84 | EXPORT_SYMBOL(DMA_MODE_READ); | 83 | EXPORT_SYMBOL(DMA_MODE_READ); |
@@ -176,6 +175,7 @@ EXPORT_SYMBOL(pci_bus_to_phys); | |||
176 | #endif /* CONFIG_PCI */ | 175 | #endif /* CONFIG_PCI */ |
177 | 176 | ||
178 | #ifdef CONFIG_NOT_COHERENT_CACHE | 177 | #ifdef CONFIG_NOT_COHERENT_CACHE |
178 | extern void flush_dcache_all(void); | ||
179 | EXPORT_SYMBOL(flush_dcache_all); | 179 | EXPORT_SYMBOL(flush_dcache_all); |
180 | #endif | 180 | #endif |
181 | 181 | ||
@@ -217,9 +217,6 @@ EXPORT_SYMBOL(adb_try_handler_change); | |||
217 | EXPORT_SYMBOL(cuda_request); | 217 | EXPORT_SYMBOL(cuda_request); |
218 | EXPORT_SYMBOL(cuda_poll); | 218 | EXPORT_SYMBOL(cuda_poll); |
219 | #endif /* CONFIG_ADB_CUDA */ | 219 | #endif /* CONFIG_ADB_CUDA */ |
220 | #ifdef CONFIG_PPC_MULTIPLATFORM | ||
221 | EXPORT_SYMBOL(_machine); | ||
222 | #endif | ||
223 | #ifdef CONFIG_PPC_PMAC | 220 | #ifdef CONFIG_PPC_PMAC |
224 | EXPORT_SYMBOL(sys_ctrler); | 221 | EXPORT_SYMBOL(sys_ctrler); |
225 | EXPORT_SYMBOL(pmac_newworld); | 222 | EXPORT_SYMBOL(pmac_newworld); |
diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c index 6bcb85d2b7fd..dc55e1abc45b 100644 --- a/arch/ppc/kernel/setup.c +++ b/arch/ppc/kernel/setup.c | |||
@@ -76,6 +76,7 @@ unsigned int DMA_MODE_WRITE; | |||
76 | 76 | ||
77 | #ifdef CONFIG_PPC_MULTIPLATFORM | 77 | #ifdef CONFIG_PPC_MULTIPLATFORM |
78 | int _machine = 0; | 78 | int _machine = 0; |
79 | EXPORT_SYMBOL(_machine); | ||
79 | 80 | ||
80 | extern void prep_init(unsigned long r3, unsigned long r4, | 81 | extern void prep_init(unsigned long r3, unsigned long r4, |
81 | unsigned long r5, unsigned long r6, unsigned long r7); | 82 | unsigned long r5, unsigned long r6, unsigned long r7); |
diff --git a/arch/ppc/platforms/pmac_pic.c b/arch/ppc/platforms/pmac_pic.c index 9f2d95ea8564..4742bf609357 100644 --- a/arch/ppc/platforms/pmac_pic.c +++ b/arch/ppc/platforms/pmac_pic.c | |||
@@ -75,6 +75,9 @@ static DEFINE_SPINLOCK(pmac_pic_lock); | |||
75 | #define GATWICK_IRQ_POOL_SIZE 10 | 75 | #define GATWICK_IRQ_POOL_SIZE 10 |
76 | static struct interrupt_info gatwick_int_pool[GATWICK_IRQ_POOL_SIZE]; | 76 | static struct interrupt_info gatwick_int_pool[GATWICK_IRQ_POOL_SIZE]; |
77 | 77 | ||
78 | #define NR_MASK_WORDS ((NR_IRQS + 31) / 32) | ||
79 | static unsigned long ppc_lost_interrupts[NR_MASK_WORDS]; | ||
80 | |||
78 | /* | 81 | /* |
79 | * Mark an irq as "lost". This is only used on the pmac | 82 | * Mark an irq as "lost". This is only used on the pmac |
80 | * since it can lose interrupts (see pmac_set_irq_mask). | 83 | * since it can lose interrupts (see pmac_set_irq_mask). |
diff --git a/arch/ppc/platforms/prep_setup.c b/arch/ppc/platforms/prep_setup.c index 067d7d53b81e..4415748071dc 100644 --- a/arch/ppc/platforms/prep_setup.c +++ b/arch/ppc/platforms/prep_setup.c | |||
@@ -61,6 +61,15 @@ | |||
61 | #include <asm/pci-bridge.h> | 61 | #include <asm/pci-bridge.h> |
62 | #include <asm/todc.h> | 62 | #include <asm/todc.h> |
63 | 63 | ||
64 | /* prep registers for L2 */ | ||
65 | #define CACHECRBA 0x80000823 /* Cache configuration register address */ | ||
66 | #define L2CACHE_MASK 0x03 /* Mask for 2 L2 Cache bits */ | ||
67 | #define L2CACHE_512KB 0x00 /* 512KB */ | ||
68 | #define L2CACHE_256KB 0x01 /* 256KB */ | ||
69 | #define L2CACHE_1MB 0x02 /* 1MB */ | ||
70 | #define L2CACHE_NONE 0x03 /* NONE */ | ||
71 | #define L2CACHE_PARITY 0x08 /* Mask for L2 Cache Parity Protected bit */ | ||
72 | |||
64 | TODC_ALLOC(); | 73 | TODC_ALLOC(); |
65 | 74 | ||
66 | unsigned char ucSystemType; | 75 | unsigned char ucSystemType; |
diff --git a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig index 29552348e581..c9d32db9d76a 100644 --- a/arch/ppc64/Kconfig +++ b/arch/ppc64/Kconfig | |||
@@ -297,6 +297,10 @@ config HAVE_ARCH_EARLY_PFN_TO_NID | |||
297 | def_bool y | 297 | def_bool y |
298 | depends on NEED_MULTIPLE_NODES | 298 | depends on NEED_MULTIPLE_NODES |
299 | 299 | ||
300 | config ARCH_MEMORY_PROBE | ||
301 | def_bool y | ||
302 | depends on MEMORY_HOTPLUG | ||
303 | |||
300 | # Some NUMA nodes have memory ranges that span | 304 | # Some NUMA nodes have memory ranges that span |
301 | # other nodes. Even though a pfn is valid and | 305 | # other nodes. Even though a pfn is valid and |
302 | # between a node's start and end pfns, it may not | 306 | # between a node's start and end pfns, it may not |
diff --git a/arch/ppc64/boot/addRamDisk.c b/arch/ppc64/boot/addRamDisk.c index 7f2c09473394..c02a99952be7 100644 --- a/arch/ppc64/boot/addRamDisk.c +++ b/arch/ppc64/boot/addRamDisk.c | |||
@@ -5,11 +5,59 @@ | |||
5 | #include <sys/types.h> | 5 | #include <sys/types.h> |
6 | #include <sys/stat.h> | 6 | #include <sys/stat.h> |
7 | #include <string.h> | 7 | #include <string.h> |
8 | #include <elf.h> | ||
8 | 9 | ||
9 | #define ElfHeaderSize (64 * 1024) | 10 | #define ElfHeaderSize (64 * 1024) |
10 | #define ElfPages (ElfHeaderSize / 4096) | 11 | #define ElfPages (ElfHeaderSize / 4096) |
11 | #define KERNELBASE (0xc000000000000000) | 12 | #define KERNELBASE (0xc000000000000000) |
13 | #define _ALIGN_UP(addr,size) (((addr)+((size)-1))&(~((size)-1))) | ||
12 | 14 | ||
15 | struct addr_range { | ||
16 | unsigned long long addr; | ||
17 | unsigned long memsize; | ||
18 | unsigned long offset; | ||
19 | }; | ||
20 | |||
21 | static int check_elf64(void *p, int size, struct addr_range *r) | ||
22 | { | ||
23 | Elf64_Ehdr *elf64 = p; | ||
24 | Elf64_Phdr *elf64ph; | ||
25 | |||
26 | if (elf64->e_ident[EI_MAG0] != ELFMAG0 || | ||
27 | elf64->e_ident[EI_MAG1] != ELFMAG1 || | ||
28 | elf64->e_ident[EI_MAG2] != ELFMAG2 || | ||
29 | elf64->e_ident[EI_MAG3] != ELFMAG3 || | ||
30 | elf64->e_ident[EI_CLASS] != ELFCLASS64 || | ||
31 | elf64->e_ident[EI_DATA] != ELFDATA2MSB || | ||
32 | elf64->e_type != ET_EXEC || elf64->e_machine != EM_PPC64) | ||
33 | return 0; | ||
34 | |||
35 | if ((elf64->e_phoff + sizeof(Elf64_Phdr)) > size) | ||
36 | return 0; | ||
37 | |||
38 | elf64ph = (Elf64_Phdr *) ((unsigned long)elf64 + | ||
39 | (unsigned long)elf64->e_phoff); | ||
40 | |||
41 | r->memsize = (unsigned long)elf64ph->p_memsz; | ||
42 | r->offset = (unsigned long)elf64ph->p_offset; | ||
43 | r->addr = (unsigned long long)elf64ph->p_vaddr; | ||
44 | |||
45 | #ifdef DEBUG | ||
46 | printf("PPC64 ELF file, ph:\n"); | ||
47 | printf("p_type 0x%08x\n", elf64ph->p_type); | ||
48 | printf("p_flags 0x%08x\n", elf64ph->p_flags); | ||
49 | printf("p_offset 0x%016llx\n", elf64ph->p_offset); | ||
50 | printf("p_vaddr 0x%016llx\n", elf64ph->p_vaddr); | ||
51 | printf("p_paddr 0x%016llx\n", elf64ph->p_paddr); | ||
52 | printf("p_filesz 0x%016llx\n", elf64ph->p_filesz); | ||
53 | printf("p_memsz 0x%016llx\n", elf64ph->p_memsz); | ||
54 | printf("p_align 0x%016llx\n", elf64ph->p_align); | ||
55 | printf("... skipping 0x%08lx bytes of ELF header\n", | ||
56 | (unsigned long)elf64ph->p_offset); | ||
57 | #endif | ||
58 | |||
59 | return 64; | ||
60 | } | ||
13 | void get4k(FILE *file, char *buf ) | 61 | void get4k(FILE *file, char *buf ) |
14 | { | 62 | { |
15 | unsigned j; | 63 | unsigned j; |
@@ -34,97 +82,92 @@ void death(const char *msg, FILE *fdesc, const char *fname) | |||
34 | int main(int argc, char **argv) | 82 | int main(int argc, char **argv) |
35 | { | 83 | { |
36 | char inbuf[4096]; | 84 | char inbuf[4096]; |
37 | FILE *ramDisk = NULL; | 85 | struct addr_range vmlinux; |
38 | FILE *sysmap = NULL; | 86 | FILE *ramDisk; |
39 | FILE *inputVmlinux = NULL; | 87 | FILE *inputVmlinux; |
40 | FILE *outputVmlinux = NULL; | 88 | FILE *outputVmlinux; |
41 | 89 | ||
42 | unsigned i = 0; | 90 | char *rd_name, *lx_name, *out_name; |
43 | unsigned long ramFileLen = 0; | 91 | |
44 | unsigned long ramLen = 0; | 92 | size_t i; |
45 | unsigned long roundR = 0; | 93 | unsigned long ramFileLen; |
46 | 94 | unsigned long ramLen; | |
47 | unsigned long sysmapFileLen = 0; | 95 | unsigned long roundR; |
48 | unsigned long sysmapLen = 0; | 96 | unsigned long offset_end; |
49 | unsigned long sysmapPages = 0; | 97 | |
50 | char* ptr_end = NULL; | 98 | unsigned long kernelLen; |
51 | unsigned long offset_end = 0; | 99 | unsigned long actualKernelLen; |
52 | 100 | unsigned long round; | |
53 | unsigned long kernelLen = 0; | 101 | unsigned long roundedKernelLen; |
54 | unsigned long actualKernelLen = 0; | 102 | unsigned long ramStartOffs; |
55 | unsigned long round = 0; | 103 | unsigned long ramPages; |
56 | unsigned long roundedKernelLen = 0; | 104 | unsigned long roundedKernelPages; |
57 | unsigned long ramStartOffs = 0; | 105 | unsigned long hvReleaseData; |
58 | unsigned long ramPages = 0; | ||
59 | unsigned long roundedKernelPages = 0; | ||
60 | unsigned long hvReleaseData = 0; | ||
61 | u_int32_t eyeCatcher = 0xc8a5d9c4; | 106 | u_int32_t eyeCatcher = 0xc8a5d9c4; |
62 | unsigned long naca = 0; | 107 | unsigned long naca; |
63 | unsigned long xRamDisk = 0; | 108 | unsigned long xRamDisk; |
64 | unsigned long xRamDiskSize = 0; | 109 | unsigned long xRamDiskSize; |
65 | long padPages = 0; | 110 | long padPages; |
66 | 111 | ||
67 | 112 | ||
68 | if (argc < 2) { | 113 | if (argc < 2) { |
69 | fprintf(stderr, "Name of RAM disk file missing.\n"); | 114 | fprintf(stderr, "Name of RAM disk file missing.\n"); |
70 | exit(1); | 115 | exit(1); |
71 | } | 116 | } |
117 | rd_name = argv[1]; | ||
72 | 118 | ||
73 | if (argc < 3) { | 119 | if (argc < 3) { |
74 | fprintf(stderr, "Name of System Map input file is missing.\n"); | ||
75 | exit(1); | ||
76 | } | ||
77 | |||
78 | if (argc < 4) { | ||
79 | fprintf(stderr, "Name of vmlinux file missing.\n"); | 120 | fprintf(stderr, "Name of vmlinux file missing.\n"); |
80 | exit(1); | 121 | exit(1); |
81 | } | 122 | } |
123 | lx_name = argv[2]; | ||
82 | 124 | ||
83 | if (argc < 5) { | 125 | if (argc < 4) { |
84 | fprintf(stderr, "Name of vmlinux output file missing.\n"); | 126 | fprintf(stderr, "Name of vmlinux output file missing.\n"); |
85 | exit(1); | 127 | exit(1); |
86 | } | 128 | } |
129 | out_name = argv[3]; | ||
87 | 130 | ||
88 | 131 | ||
89 | ramDisk = fopen(argv[1], "r"); | 132 | ramDisk = fopen(rd_name, "r"); |
90 | if ( ! ramDisk ) { | 133 | if ( ! ramDisk ) { |
91 | fprintf(stderr, "RAM disk file \"%s\" failed to open.\n", argv[1]); | 134 | fprintf(stderr, "RAM disk file \"%s\" failed to open.\n", rd_name); |
92 | exit(1); | 135 | exit(1); |
93 | } | 136 | } |
94 | 137 | ||
95 | sysmap = fopen(argv[2], "r"); | 138 | inputVmlinux = fopen(lx_name, "r"); |
96 | if ( ! sysmap ) { | ||
97 | fprintf(stderr, "System Map file \"%s\" failed to open.\n", argv[2]); | ||
98 | exit(1); | ||
99 | } | ||
100 | |||
101 | inputVmlinux = fopen(argv[3], "r"); | ||
102 | if ( ! inputVmlinux ) { | 139 | if ( ! inputVmlinux ) { |
103 | fprintf(stderr, "vmlinux file \"%s\" failed to open.\n", argv[3]); | 140 | fprintf(stderr, "vmlinux file \"%s\" failed to open.\n", lx_name); |
104 | exit(1); | 141 | exit(1); |
105 | } | 142 | } |
106 | 143 | ||
107 | outputVmlinux = fopen(argv[4], "w+"); | 144 | outputVmlinux = fopen(out_name, "w+"); |
108 | if ( ! outputVmlinux ) { | 145 | if ( ! outputVmlinux ) { |
109 | fprintf(stderr, "output vmlinux file \"%s\" failed to open.\n", argv[4]); | 146 | fprintf(stderr, "output vmlinux file \"%s\" failed to open.\n", out_name); |
110 | exit(1); | 147 | exit(1); |
111 | } | 148 | } |
112 | 149 | ||
113 | 150 | i = fread(inbuf, 1, sizeof(inbuf), inputVmlinux); | |
114 | 151 | if (i != sizeof(inbuf)) { | |
152 | fprintf(stderr, "can not read vmlinux file %s: %u\n", lx_name, i); | ||
153 | exit(1); | ||
154 | } | ||
155 | |||
156 | i = check_elf64(inbuf, sizeof(inbuf), &vmlinux); | ||
157 | if (i == 0) { | ||
158 | fprintf(stderr, "You must have a linux kernel specified as argv[2]\n"); | ||
159 | exit(1); | ||
160 | } | ||
161 | |||
115 | /* Input Vmlinux file */ | 162 | /* Input Vmlinux file */ |
116 | fseek(inputVmlinux, 0, SEEK_END); | 163 | fseek(inputVmlinux, 0, SEEK_END); |
117 | kernelLen = ftell(inputVmlinux); | 164 | kernelLen = ftell(inputVmlinux); |
118 | fseek(inputVmlinux, 0, SEEK_SET); | 165 | fseek(inputVmlinux, 0, SEEK_SET); |
119 | printf("kernel file size = %d\n", kernelLen); | 166 | printf("kernel file size = %lu\n", kernelLen); |
120 | if ( kernelLen == 0 ) { | ||
121 | fprintf(stderr, "You must have a linux kernel specified as argv[3]\n"); | ||
122 | exit(1); | ||
123 | } | ||
124 | 167 | ||
125 | actualKernelLen = kernelLen - ElfHeaderSize; | 168 | actualKernelLen = kernelLen - ElfHeaderSize; |
126 | 169 | ||
127 | printf("actual kernel length (minus ELF header) = %d\n", actualKernelLen); | 170 | printf("actual kernel length (minus ELF header) = %lu\n", actualKernelLen); |
128 | 171 | ||
129 | round = actualKernelLen % 4096; | 172 | round = actualKernelLen % 4096; |
130 | roundedKernelLen = actualKernelLen; | 173 | roundedKernelLen = actualKernelLen; |
@@ -134,39 +177,7 @@ int main(int argc, char **argv) | |||
134 | roundedKernelPages = roundedKernelLen / 4096; | 177 | roundedKernelPages = roundedKernelLen / 4096; |
135 | printf("Vmlinux pages to copy = %ld/0x%lx \n", roundedKernelPages, roundedKernelPages); | 178 | printf("Vmlinux pages to copy = %ld/0x%lx \n", roundedKernelPages, roundedKernelPages); |
136 | 179 | ||
137 | 180 | offset_end = _ALIGN_UP(vmlinux.memsize, 4096); | |
138 | |||
139 | /* Input System Map file */ | ||
140 | /* (needs to be processed simply to determine if we need to add pad pages due to the static variables not being included in the vmlinux) */ | ||
141 | fseek(sysmap, 0, SEEK_END); | ||
142 | sysmapFileLen = ftell(sysmap); | ||
143 | fseek(sysmap, 0, SEEK_SET); | ||
144 | printf("%s file size = %ld/0x%lx \n", argv[2], sysmapFileLen, sysmapFileLen); | ||
145 | |||
146 | sysmapLen = sysmapFileLen; | ||
147 | |||
148 | roundR = 4096 - (sysmapLen % 4096); | ||
149 | if (roundR) { | ||
150 | printf("Rounding System Map file up to a multiple of 4096, adding %ld/0x%lx \n", roundR, roundR); | ||
151 | sysmapLen += roundR; | ||
152 | } | ||
153 | printf("Rounded System Map size is %ld/0x%lx \n", sysmapLen, sysmapLen); | ||
154 | |||
155 | /* Process the Sysmap file to determine where _end is */ | ||
156 | sysmapPages = sysmapLen / 4096; | ||
157 | /* read the whole file line by line, expect that it doesn't fail */ | ||
158 | while ( fgets(inbuf, 4096, sysmap) ) ; | ||
159 | /* search for _end in the last page of the system map */ | ||
160 | ptr_end = strstr(inbuf, " _end"); | ||
161 | if (!ptr_end) { | ||
162 | fprintf(stderr, "Unable to find _end in the sysmap file \n"); | ||
163 | fprintf(stderr, "inbuf: \n"); | ||
164 | fprintf(stderr, "%s \n", inbuf); | ||
165 | exit(1); | ||
166 | } | ||
167 | printf("Found _end in the last page of the sysmap - backing up 10 characters it looks like %s", ptr_end-10); | ||
168 | /* convert address of _end in system map to hex offset. */ | ||
169 | offset_end = (unsigned int)strtol(ptr_end-10, NULL, 16); | ||
170 | /* calc how many pages we need to insert between the vmlinux and the start of the ram disk */ | 181 | /* calc how many pages we need to insert between the vmlinux and the start of the ram disk */ |
171 | padPages = offset_end/4096 - roundedKernelPages; | 182 | padPages = offset_end/4096 - roundedKernelPages; |
172 | 183 | ||
@@ -194,7 +205,7 @@ int main(int argc, char **argv) | |||
194 | fseek(ramDisk, 0, SEEK_END); | 205 | fseek(ramDisk, 0, SEEK_END); |
195 | ramFileLen = ftell(ramDisk); | 206 | ramFileLen = ftell(ramDisk); |
196 | fseek(ramDisk, 0, SEEK_SET); | 207 | fseek(ramDisk, 0, SEEK_SET); |
197 | printf("%s file size = %ld/0x%lx \n", argv[1], ramFileLen, ramFileLen); | 208 | printf("%s file size = %ld/0x%lx \n", rd_name, ramFileLen, ramFileLen); |
198 | 209 | ||
199 | ramLen = ramFileLen; | 210 | ramLen = ramFileLen; |
200 | 211 | ||
@@ -248,19 +259,19 @@ int main(int argc, char **argv) | |||
248 | /* fseek to the hvReleaseData pointer */ | 259 | /* fseek to the hvReleaseData pointer */ |
249 | fseek(outputVmlinux, ElfHeaderSize + 0x24, SEEK_SET); | 260 | fseek(outputVmlinux, ElfHeaderSize + 0x24, SEEK_SET); |
250 | if (fread(&hvReleaseData, 4, 1, outputVmlinux) != 1) { | 261 | if (fread(&hvReleaseData, 4, 1, outputVmlinux) != 1) { |
251 | death("Could not read hvReleaseData pointer\n", outputVmlinux, argv[4]); | 262 | death("Could not read hvReleaseData pointer\n", outputVmlinux, out_name); |
252 | } | 263 | } |
253 | hvReleaseData = ntohl(hvReleaseData); /* Convert to native int */ | 264 | hvReleaseData = ntohl(hvReleaseData); /* Convert to native int */ |
254 | printf("hvReleaseData is at %08x\n", hvReleaseData); | 265 | printf("hvReleaseData is at %08lx\n", hvReleaseData); |
255 | 266 | ||
256 | /* fseek to the hvReleaseData */ | 267 | /* fseek to the hvReleaseData */ |
257 | fseek(outputVmlinux, ElfHeaderSize + hvReleaseData, SEEK_SET); | 268 | fseek(outputVmlinux, ElfHeaderSize + hvReleaseData, SEEK_SET); |
258 | if (fread(inbuf, 0x40, 1, outputVmlinux) != 1) { | 269 | if (fread(inbuf, 0x40, 1, outputVmlinux) != 1) { |
259 | death("Could not read hvReleaseData\n", outputVmlinux, argv[4]); | 270 | death("Could not read hvReleaseData\n", outputVmlinux, out_name); |
260 | } | 271 | } |
261 | /* Check hvReleaseData sanity */ | 272 | /* Check hvReleaseData sanity */ |
262 | if (memcmp(inbuf, &eyeCatcher, 4) != 0) { | 273 | if (memcmp(inbuf, &eyeCatcher, 4) != 0) { |
263 | death("hvReleaseData is invalid\n", outputVmlinux, argv[4]); | 274 | death("hvReleaseData is invalid\n", outputVmlinux, out_name); |
264 | } | 275 | } |
265 | /* Get the naca pointer */ | 276 | /* Get the naca pointer */ |
266 | naca = ntohl(*((u_int32_t*) &inbuf[0x0C])) - KERNELBASE; | 277 | naca = ntohl(*((u_int32_t*) &inbuf[0x0C])) - KERNELBASE; |
@@ -269,13 +280,13 @@ int main(int argc, char **argv) | |||
269 | /* fseek to the naca */ | 280 | /* fseek to the naca */ |
270 | fseek(outputVmlinux, ElfHeaderSize + naca, SEEK_SET); | 281 | fseek(outputVmlinux, ElfHeaderSize + naca, SEEK_SET); |
271 | if (fread(inbuf, 0x18, 1, outputVmlinux) != 1) { | 282 | if (fread(inbuf, 0x18, 1, outputVmlinux) != 1) { |
272 | death("Could not read naca\n", outputVmlinux, argv[4]); | 283 | death("Could not read naca\n", outputVmlinux, out_name); |
273 | } | 284 | } |
274 | xRamDisk = ntohl(*((u_int32_t *) &inbuf[0x0c])); | 285 | xRamDisk = ntohl(*((u_int32_t *) &inbuf[0x0c])); |
275 | xRamDiskSize = ntohl(*((u_int32_t *) &inbuf[0x14])); | 286 | xRamDiskSize = ntohl(*((u_int32_t *) &inbuf[0x14])); |
276 | /* Make sure a RAM disk isn't already present */ | 287 | /* Make sure a RAM disk isn't already present */ |
277 | if ((xRamDisk != 0) || (xRamDiskSize != 0)) { | 288 | if ((xRamDisk != 0) || (xRamDiskSize != 0)) { |
278 | death("RAM disk is already attached to this kernel\n", outputVmlinux, argv[4]); | 289 | death("RAM disk is already attached to this kernel\n", outputVmlinux, out_name); |
279 | } | 290 | } |
280 | /* Fill in the values */ | 291 | /* Fill in the values */ |
281 | *((u_int32_t *) &inbuf[0x0c]) = htonl(ramStartOffs); | 292 | *((u_int32_t *) &inbuf[0x0c]) = htonl(ramStartOffs); |
@@ -285,15 +296,15 @@ int main(int argc, char **argv) | |||
285 | fflush(outputVmlinux); | 296 | fflush(outputVmlinux); |
286 | fseek(outputVmlinux, ElfHeaderSize + naca, SEEK_SET); | 297 | fseek(outputVmlinux, ElfHeaderSize + naca, SEEK_SET); |
287 | if (fwrite(inbuf, 0x18, 1, outputVmlinux) != 1) { | 298 | if (fwrite(inbuf, 0x18, 1, outputVmlinux) != 1) { |
288 | death("Could not write naca\n", outputVmlinux, argv[4]); | 299 | death("Could not write naca\n", outputVmlinux, out_name); |
289 | } | 300 | } |
290 | printf("Ram Disk of 0x%lx pages is attached to the kernel at offset 0x%08x\n", | 301 | printf("Ram Disk of 0x%lx pages is attached to the kernel at offset 0x%08lx\n", |
291 | ramPages, ramStartOffs); | 302 | ramPages, ramStartOffs); |
292 | 303 | ||
293 | /* Done */ | 304 | /* Done */ |
294 | fclose(outputVmlinux); | 305 | fclose(outputVmlinux); |
295 | /* Set permission to executable */ | 306 | /* Set permission to executable */ |
296 | chmod(argv[4], S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH); | 307 | chmod(out_name, S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH); |
297 | 308 | ||
298 | return 0; | 309 | return 0; |
299 | } | 310 | } |
diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile index c441aebe7648..58b19f107656 100644 --- a/arch/ppc64/kernel/Makefile +++ b/arch/ppc64/kernel/Makefile | |||
@@ -11,12 +11,11 @@ obj-y := misc.o prom.o | |||
11 | 11 | ||
12 | endif | 12 | endif |
13 | 13 | ||
14 | obj-y += irq.o idle.o dma.o \ | 14 | obj-y += idle.o dma.o \ |
15 | align.o pacaData.o \ | 15 | align.o \ |
16 | udbg.o ioctl32.o \ | 16 | udbg.o \ |
17 | rtc.o \ | 17 | rtc.o \ |
18 | cpu_setup_power4.o \ | 18 | iommu.o vdso.o |
19 | iommu.o sysfs.o vdso.o firmware.o | ||
20 | obj-y += vdso32/ vdso64/ | 19 | obj-y += vdso32/ vdso64/ |
21 | 20 | ||
22 | pci-obj-$(CONFIG_PPC_MULTIPLATFORM) += pci_dn.o pci_direct_iommu.o | 21 | pci-obj-$(CONFIG_PPC_MULTIPLATFORM) += pci_dn.o pci_direct_iommu.o |
@@ -31,15 +30,10 @@ endif | |||
31 | obj-$(CONFIG_PPC_PSERIES) += udbg_16550.o | 30 | obj-$(CONFIG_PPC_PSERIES) += udbg_16550.o |
32 | 31 | ||
33 | obj-$(CONFIG_KEXEC) += machine_kexec.o | 32 | obj-$(CONFIG_KEXEC) += machine_kexec.o |
34 | obj-$(CONFIG_EEH) += eeh.o | ||
35 | obj-$(CONFIG_PROC_FS) += proc_ppc64.o | ||
36 | obj-$(CONFIG_MODULES) += module.o | 33 | obj-$(CONFIG_MODULES) += module.o |
37 | ifneq ($(CONFIG_PPC_MERGE),y) | 34 | ifneq ($(CONFIG_PPC_MERGE),y) |
38 | obj-$(CONFIG_MODULES) += ppc_ksyms.o | 35 | obj-$(CONFIG_MODULES) += ppc_ksyms.o |
39 | endif | 36 | endif |
40 | obj-$(CONFIG_PPC_RTAS) += rtas_pci.o | ||
41 | obj-$(CONFIG_SCANLOG) += scanlog.o | ||
42 | obj-$(CONFIG_LPARCFG) += lparcfg.o | ||
43 | obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o | 37 | obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o |
44 | ifneq ($(CONFIG_PPC_MERGE),y) | 38 | ifneq ($(CONFIG_PPC_MERGE),y) |
45 | obj-$(CONFIG_BOOTX_TEXT) += btext.o | 39 | obj-$(CONFIG_BOOTX_TEXT) += btext.o |
@@ -52,8 +46,6 @@ obj-$(CONFIG_PPC_MAPLE) += udbg_16550.o | |||
52 | 46 | ||
53 | obj-$(CONFIG_KPROBES) += kprobes.o | 47 | obj-$(CONFIG_KPROBES) += kprobes.o |
54 | 48 | ||
55 | CFLAGS_ioctl32.o += -Ifs/ | ||
56 | |||
57 | ifneq ($(CONFIG_PPC_MERGE),y) | 49 | ifneq ($(CONFIG_PPC_MERGE),y) |
58 | ifeq ($(CONFIG_PPC_ISERIES),y) | 50 | ifeq ($(CONFIG_PPC_ISERIES),y) |
59 | arch/ppc64/kernel/head.o: arch/powerpc/kernel/lparmap.s | 51 | arch/ppc64/kernel/head.o: arch/powerpc/kernel/lparmap.s |
diff --git a/arch/ppc64/kernel/asm-offsets.c b/arch/ppc64/kernel/asm-offsets.c index bce9065da6cb..84ab5c18ef52 100644 --- a/arch/ppc64/kernel/asm-offsets.c +++ b/arch/ppc64/kernel/asm-offsets.c | |||
@@ -74,7 +74,6 @@ int main(void) | |||
74 | DEFINE(ICACHEL1LINESIZE, offsetof(struct ppc64_caches, iline_size)); | 74 | DEFINE(ICACHEL1LINESIZE, offsetof(struct ppc64_caches, iline_size)); |
75 | DEFINE(ICACHEL1LOGLINESIZE, offsetof(struct ppc64_caches, log_iline_size)); | 75 | DEFINE(ICACHEL1LOGLINESIZE, offsetof(struct ppc64_caches, log_iline_size)); |
76 | DEFINE(ICACHEL1LINESPERPAGE, offsetof(struct ppc64_caches, ilines_per_page)); | 76 | DEFINE(ICACHEL1LINESPERPAGE, offsetof(struct ppc64_caches, ilines_per_page)); |
77 | DEFINE(PLATFORM, offsetof(struct systemcfg, platform)); | ||
78 | DEFINE(PLATFORM_LPAR, PLATFORM_LPAR); | 77 | DEFINE(PLATFORM_LPAR, PLATFORM_LPAR); |
79 | 78 | ||
80 | /* paca */ | 79 | /* paca */ |
diff --git a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S index 9e8050ea1225..1c869ea72d28 100644 --- a/arch/ppc64/kernel/head.S +++ b/arch/ppc64/kernel/head.S | |||
@@ -28,7 +28,6 @@ | |||
28 | #include <asm/processor.h> | 28 | #include <asm/processor.h> |
29 | #include <asm/page.h> | 29 | #include <asm/page.h> |
30 | #include <asm/mmu.h> | 30 | #include <asm/mmu.h> |
31 | #include <asm/systemcfg.h> | ||
32 | #include <asm/ppc_asm.h> | 31 | #include <asm/ppc_asm.h> |
33 | #include <asm/asm-offsets.h> | 32 | #include <asm/asm-offsets.h> |
34 | #include <asm/bug.h> | 33 | #include <asm/bug.h> |
@@ -1701,21 +1700,9 @@ _GLOBAL(__secondary_start) | |||
1701 | HMT_MEDIUM /* Set thread priority to MEDIUM */ | 1700 | HMT_MEDIUM /* Set thread priority to MEDIUM */ |
1702 | 1701 | ||
1703 | ld r2,PACATOC(r13) | 1702 | ld r2,PACATOC(r13) |
1704 | li r6,0 | 1703 | |
1705 | stb r6,PACAPROCENABLED(r13) | 1704 | /* Do early setup for that CPU */ |
1706 | 1705 | bl .early_setup_secondary | |
1707 | #ifndef CONFIG_PPC_ISERIES | ||
1708 | /* Initialize the page table pointer register. */ | ||
1709 | LOADADDR(r6,_SDR1) | ||
1710 | ld r6,0(r6) /* get the value of _SDR1 */ | ||
1711 | mtspr SPRN_SDR1,r6 /* set the htab location */ | ||
1712 | #endif | ||
1713 | /* Initialize the first segment table (or SLB) entry */ | ||
1714 | ld r3,PACASTABVIRT(r13) /* get addr of segment table */ | ||
1715 | BEGIN_FTR_SECTION | ||
1716 | bl .stab_initialize | ||
1717 | END_FTR_SECTION_IFCLR(CPU_FTR_SLB) | ||
1718 | bl .slb_initialize | ||
1719 | 1706 | ||
1720 | /* Initialize the kernel stack. Just a repeat for iSeries. */ | 1707 | /* Initialize the kernel stack. Just a repeat for iSeries. */ |
1721 | LOADADDR(r3,current_set) | 1708 | LOADADDR(r3,current_set) |
@@ -1724,37 +1711,6 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SLB) | |||
1724 | addi r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD | 1711 | addi r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD |
1725 | std r1,PACAKSAVE(r13) | 1712 | std r1,PACAKSAVE(r13) |
1726 | 1713 | ||
1727 | ld r3,PACASTABREAL(r13) /* get raddr of segment table */ | ||
1728 | ori r4,r3,1 /* turn on valid bit */ | ||
1729 | |||
1730 | #ifdef CONFIG_PPC_ISERIES | ||
1731 | li r0,-1 /* hypervisor call */ | ||
1732 | li r3,1 | ||
1733 | sldi r3,r3,63 /* 0x8000000000000000 */ | ||
1734 | ori r3,r3,4 /* 0x8000000000000004 */ | ||
1735 | sc /* HvCall_setASR */ | ||
1736 | #else | ||
1737 | /* set the ASR */ | ||
1738 | ld r3,systemcfg@got(r2) /* r3 = ptr to systemcfg */ | ||
1739 | ld r3,0(r3) | ||
1740 | lwz r3,PLATFORM(r3) /* r3 = platform flags */ | ||
1741 | andi. r3,r3,PLATFORM_LPAR /* Test if bit 0 is set (LPAR bit) */ | ||
1742 | beq 98f /* branch if result is 0 */ | ||
1743 | mfspr r3,SPRN_PVR | ||
1744 | srwi r3,r3,16 | ||
1745 | cmpwi r3,0x37 /* SStar */ | ||
1746 | beq 97f | ||
1747 | cmpwi r3,0x36 /* IStar */ | ||
1748 | beq 97f | ||
1749 | cmpwi r3,0x34 /* Pulsar */ | ||
1750 | bne 98f | ||
1751 | 97: li r3,H_SET_ASR /* hcall = H_SET_ASR */ | ||
1752 | HVSC /* Invoking hcall */ | ||
1753 | b 99f | ||
1754 | 98: /* !(rpa hypervisor) || !(star) */ | ||
1755 | mtasr r4 /* set the stab location */ | ||
1756 | 99: | ||
1757 | #endif | ||
1758 | li r7,0 | 1714 | li r7,0 |
1759 | mtlr r7 | 1715 | mtlr r7 |
1760 | 1716 | ||
@@ -1896,40 +1852,6 @@ _STATIC(start_here_multiplatform) | |||
1896 | mr r3,r31 | 1852 | mr r3,r31 |
1897 | bl .early_setup | 1853 | bl .early_setup |
1898 | 1854 | ||
1899 | /* set the ASR */ | ||
1900 | ld r3,PACASTABREAL(r13) | ||
1901 | ori r4,r3,1 /* turn on valid bit */ | ||
1902 | ld r3,systemcfg@got(r2) /* r3 = ptr to systemcfg */ | ||
1903 | ld r3,0(r3) | ||
1904 | lwz r3,PLATFORM(r3) /* r3 = platform flags */ | ||
1905 | andi. r3,r3,PLATFORM_LPAR /* Test if bit 0 is set (LPAR bit) */ | ||
1906 | beq 98f /* branch if result is 0 */ | ||
1907 | mfspr r3,SPRN_PVR | ||
1908 | srwi r3,r3,16 | ||
1909 | cmpwi r3,0x37 /* SStar */ | ||
1910 | beq 97f | ||
1911 | cmpwi r3,0x36 /* IStar */ | ||
1912 | beq 97f | ||
1913 | cmpwi r3,0x34 /* Pulsar */ | ||
1914 | bne 98f | ||
1915 | 97: li r3,H_SET_ASR /* hcall = H_SET_ASR */ | ||
1916 | HVSC /* Invoking hcall */ | ||
1917 | b 99f | ||
1918 | 98: /* !(rpa hypervisor) || !(star) */ | ||
1919 | mtasr r4 /* set the stab location */ | ||
1920 | 99: | ||
1921 | /* Set SDR1 (hash table pointer) */ | ||
1922 | ld r3,systemcfg@got(r2) /* r3 = ptr to systemcfg */ | ||
1923 | ld r3,0(r3) | ||
1924 | lwz r3,PLATFORM(r3) /* r3 = platform flags */ | ||
1925 | /* Test if bit 0 is set (LPAR bit) */ | ||
1926 | andi. r3,r3,PLATFORM_LPAR | ||
1927 | bne 98f /* branch if result is !0 */ | ||
1928 | LOADADDR(r6,_SDR1) /* Only if NOT LPAR */ | ||
1929 | sub r6,r6,r26 | ||
1930 | ld r6,0(r6) /* get the value of _SDR1 */ | ||
1931 | mtspr SPRN_SDR1,r6 /* set the htab location */ | ||
1932 | 98: | ||
1933 | LOADADDR(r3,.start_here_common) | 1855 | LOADADDR(r3,.start_here_common) |
1934 | SET_REG_TO_CONST(r4, MSR_KERNEL) | 1856 | SET_REG_TO_CONST(r4, MSR_KERNEL) |
1935 | mtspr SPRN_SRR0,r3 | 1857 | mtspr SPRN_SRR0,r3 |
diff --git a/arch/ppc64/kernel/idle.c b/arch/ppc64/kernel/idle.c index 715bc0e71e0f..b879d3057ef8 100644 --- a/arch/ppc64/kernel/idle.c +++ b/arch/ppc64/kernel/idle.c | |||
@@ -26,7 +26,6 @@ | |||
26 | #include <asm/processor.h> | 26 | #include <asm/processor.h> |
27 | #include <asm/cputable.h> | 27 | #include <asm/cputable.h> |
28 | #include <asm/time.h> | 28 | #include <asm/time.h> |
29 | #include <asm/systemcfg.h> | ||
30 | #include <asm/machdep.h> | 29 | #include <asm/machdep.h> |
31 | #include <asm/smp.h> | 30 | #include <asm/smp.h> |
32 | 31 | ||
diff --git a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S index 914632ec587d..492bca6137eb 100644 --- a/arch/ppc64/kernel/misc.S +++ b/arch/ppc64/kernel/misc.S | |||
@@ -78,12 +78,12 @@ _GLOBAL(call_do_softirq) | |||
78 | mtlr r0 | 78 | mtlr r0 |
79 | blr | 79 | blr |
80 | 80 | ||
81 | _GLOBAL(call_handle_IRQ_event) | 81 | _GLOBAL(call___do_IRQ) |
82 | mflr r0 | 82 | mflr r0 |
83 | std r0,16(r1) | 83 | std r0,16(r1) |
84 | stdu r1,THREAD_SIZE-112(r6) | 84 | stdu r1,THREAD_SIZE-112(r5) |
85 | mr r1,r6 | 85 | mr r1,r5 |
86 | bl .handle_IRQ_event | 86 | bl .__do_IRQ |
87 | ld r1,0(r1) | 87 | ld r1,0(r1) |
88 | ld r0,16(r1) | 88 | ld r0,16(r1) |
89 | mtlr r0 | 89 | mtlr r0 |
diff --git a/arch/ppc64/kernel/nvram.c b/arch/ppc64/kernel/nvram.c index 4fb1a9f5060d..c0fcd29918ce 100644 --- a/arch/ppc64/kernel/nvram.c +++ b/arch/ppc64/kernel/nvram.c | |||
@@ -31,7 +31,6 @@ | |||
31 | #include <asm/rtas.h> | 31 | #include <asm/rtas.h> |
32 | #include <asm/prom.h> | 32 | #include <asm/prom.h> |
33 | #include <asm/machdep.h> | 33 | #include <asm/machdep.h> |
34 | #include <asm/systemcfg.h> | ||
35 | 34 | ||
36 | #undef DEBUG_NVRAM | 35 | #undef DEBUG_NVRAM |
37 | 36 | ||
@@ -167,7 +166,7 @@ static int dev_nvram_ioctl(struct inode *inode, struct file *file, | |||
167 | case IOC_NVRAM_GET_OFFSET: { | 166 | case IOC_NVRAM_GET_OFFSET: { |
168 | int part, offset; | 167 | int part, offset; |
169 | 168 | ||
170 | if (systemcfg->platform != PLATFORM_POWERMAC) | 169 | if (_machine != PLATFORM_POWERMAC) |
171 | return -EINVAL; | 170 | return -EINVAL; |
172 | if (copy_from_user(&part, (void __user*)arg, sizeof(part)) != 0) | 171 | if (copy_from_user(&part, (void __user*)arg, sizeof(part)) != 0) |
173 | return -EFAULT; | 172 | return -EFAULT; |
@@ -450,7 +449,7 @@ static int nvram_setup_partition(void) | |||
450 | * in our nvram, as Apple defined partitions use pretty much | 449 | * in our nvram, as Apple defined partitions use pretty much |
451 | * all of the space | 450 | * all of the space |
452 | */ | 451 | */ |
453 | if (systemcfg->platform == PLATFORM_POWERMAC) | 452 | if (_machine == PLATFORM_POWERMAC) |
454 | return -ENOSPC; | 453 | return -ENOSPC; |
455 | 454 | ||
456 | /* see if we have an OS partition that meets our needs. | 455 | /* see if we have an OS partition that meets our needs. |
diff --git a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c index 30247ff74972..3cef1b8f57f0 100644 --- a/arch/ppc64/kernel/pci.c +++ b/arch/ppc64/kernel/pci.c | |||
@@ -548,6 +548,11 @@ static int __init pcibios_init(void) | |||
548 | if (ppc64_isabridge_dev != NULL) | 548 | if (ppc64_isabridge_dev != NULL) |
549 | printk("ISA bridge at %s\n", pci_name(ppc64_isabridge_dev)); | 549 | printk("ISA bridge at %s\n", pci_name(ppc64_isabridge_dev)); |
550 | 550 | ||
551 | #ifdef CONFIG_PPC_MULTIPLATFORM | ||
552 | /* map in PCI I/O space */ | ||
553 | phbs_remap_io(); | ||
554 | #endif | ||
555 | |||
551 | printk("PCI: Probing PCI hardware done\n"); | 556 | printk("PCI: Probing PCI hardware done\n"); |
552 | 557 | ||
553 | return 0; | 558 | return 0; |
@@ -1277,12 +1282,9 @@ long sys_pciconfig_iobase(long which, unsigned long in_bus, | |||
1277 | * G5 machines... So when something asks for bus 0 io base | 1282 | * G5 machines... So when something asks for bus 0 io base |
1278 | * (bus 0 is HT root), we return the AGP one instead. | 1283 | * (bus 0 is HT root), we return the AGP one instead. |
1279 | */ | 1284 | */ |
1280 | #ifdef CONFIG_PPC_PMAC | 1285 | if (machine_is_compatible("MacRISC4")) |
1281 | if (systemcfg->platform == PLATFORM_POWERMAC && | ||
1282 | machine_is_compatible("MacRISC4")) | ||
1283 | if (in_bus == 0) | 1286 | if (in_bus == 0) |
1284 | in_bus = 0xf0; | 1287 | in_bus = 0xf0; |
1285 | #endif /* CONFIG_PPC_PMAC */ | ||
1286 | 1288 | ||
1287 | /* That syscall isn't quite compatible with PCI domains, but it's | 1289 | /* That syscall isn't quite compatible with PCI domains, but it's |
1288 | * used on pre-domains setup. We return the first match | 1290 | * used on pre-domains setup. We return the first match |
diff --git a/arch/ppc64/kernel/pci_dn.c b/arch/ppc64/kernel/pci_dn.c index 1a443a7ada4c..12c4c9e9bbc7 100644 --- a/arch/ppc64/kernel/pci_dn.c +++ b/arch/ppc64/kernel/pci_dn.c | |||
@@ -43,7 +43,7 @@ static void * __devinit update_dn_pci_info(struct device_node *dn, void *data) | |||
43 | u32 *regs; | 43 | u32 *regs; |
44 | struct pci_dn *pdn; | 44 | struct pci_dn *pdn; |
45 | 45 | ||
46 | if (phb->is_dynamic) | 46 | if (mem_init_done) |
47 | pdn = kmalloc(sizeof(*pdn), GFP_KERNEL); | 47 | pdn = kmalloc(sizeof(*pdn), GFP_KERNEL); |
48 | else | 48 | else |
49 | pdn = alloc_bootmem(sizeof(*pdn)); | 49 | pdn = alloc_bootmem(sizeof(*pdn)); |
@@ -120,6 +120,14 @@ void *traverse_pci_devices(struct device_node *start, traverse_func pre, | |||
120 | return NULL; | 120 | return NULL; |
121 | } | 121 | } |
122 | 122 | ||
123 | /** | ||
124 | * pci_devs_phb_init_dynamic - setup pci devices under this PHB | ||
125 | * phb: pci-to-host bridge (top-level bridge connecting to cpu) | ||
126 | * | ||
127 | * This routine is called both during boot, (before the memory | ||
128 | * subsystem is set up, before kmalloc is valid) and during the | ||
129 | * dynamic lpar operation of adding a PHB to a running system. | ||
130 | */ | ||
123 | void __devinit pci_devs_phb_init_dynamic(struct pci_controller *phb) | 131 | void __devinit pci_devs_phb_init_dynamic(struct pci_controller *phb) |
124 | { | 132 | { |
125 | struct device_node * dn = (struct device_node *) phb->arch_data; | 133 | struct device_node * dn = (struct device_node *) phb->arch_data; |
@@ -201,9 +209,14 @@ static struct notifier_block pci_dn_reconfig_nb = { | |||
201 | .notifier_call = pci_dn_reconfig_notifier, | 209 | .notifier_call = pci_dn_reconfig_notifier, |
202 | }; | 210 | }; |
203 | 211 | ||
204 | /* | 212 | /** |
205 | * Actually initialize the phbs. | 213 | * pci_devs_phb_init - Initialize phbs and pci devs under them. |
206 | * The buswalk on this phb has not happened yet. | 214 | * |
215 | * This routine walks over all phb's (pci-host bridges) on the | ||
216 | * system, and sets up assorted pci-related structures | ||
217 | * (including pci info in the device node structs) for each | ||
218 | * pci device found underneath. This routine runs once, | ||
219 | * early in the boot sequence. | ||
207 | */ | 220 | */ |
208 | void __init pci_devs_phb_init(void) | 221 | void __init pci_devs_phb_init(void) |
209 | { | 222 | { |
diff --git a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c index 3402fbee62c7..fbad2c360784 100644 --- a/arch/ppc64/kernel/prom.c +++ b/arch/ppc64/kernel/prom.c | |||
@@ -318,7 +318,7 @@ static int __devinit finish_node_interrupts(struct device_node *np, | |||
318 | } | 318 | } |
319 | 319 | ||
320 | /* We offset irq numbers for the u3 MPIC by 128 in PowerMac */ | 320 | /* We offset irq numbers for the u3 MPIC by 128 in PowerMac */ |
321 | if (systemcfg->platform == PLATFORM_POWERMAC && ic && ic->parent) { | 321 | if (_machine == PLATFORM_POWERMAC && ic && ic->parent) { |
322 | char *name = get_property(ic->parent, "name", NULL); | 322 | char *name = get_property(ic->parent, "name", NULL); |
323 | if (name && !strcmp(name, "u3")) | 323 | if (name && !strcmp(name, "u3")) |
324 | np->intrs[intrcount].line += 128; | 324 | np->intrs[intrcount].line += 128; |
@@ -1065,7 +1065,7 @@ static int __init early_init_dt_scan_chosen(unsigned long node, | |||
1065 | prop = (u32 *)of_get_flat_dt_prop(node, "linux,platform", NULL); | 1065 | prop = (u32 *)of_get_flat_dt_prop(node, "linux,platform", NULL); |
1066 | if (prop == NULL) | 1066 | if (prop == NULL) |
1067 | return 0; | 1067 | return 0; |
1068 | systemcfg->platform = *prop; | 1068 | _machine = *prop; |
1069 | 1069 | ||
1070 | /* check if iommu is forced on or off */ | 1070 | /* check if iommu is forced on or off */ |
1071 | if (of_get_flat_dt_prop(node, "linux,iommu-off", NULL) != NULL) | 1071 | if (of_get_flat_dt_prop(node, "linux,iommu-off", NULL) != NULL) |
@@ -1230,11 +1230,8 @@ void __init early_init_devtree(void *params) | |||
1230 | of_scan_flat_dt(early_init_dt_scan_memory, NULL); | 1230 | of_scan_flat_dt(early_init_dt_scan_memory, NULL); |
1231 | lmb_enforce_memory_limit(memory_limit); | 1231 | lmb_enforce_memory_limit(memory_limit); |
1232 | lmb_analyze(); | 1232 | lmb_analyze(); |
1233 | systemcfg->physicalMemorySize = lmb_phys_mem_size(); | ||
1234 | lmb_reserve(0, __pa(klimit)); | 1233 | lmb_reserve(0, __pa(klimit)); |
1235 | 1234 | ||
1236 | DBG("Phys. mem: %lx\n", systemcfg->physicalMemorySize); | ||
1237 | |||
1238 | /* Reserve LMB regions used by kernel, initrd, dt, etc... */ | 1235 | /* Reserve LMB regions used by kernel, initrd, dt, etc... */ |
1239 | early_reserve_mem(); | 1236 | early_reserve_mem(); |
1240 | 1237 | ||
@@ -1753,7 +1750,7 @@ static int of_finish_dynamic_node(struct device_node *node, | |||
1753 | /* We don't support that function on PowerMac, at least | 1750 | /* We don't support that function on PowerMac, at least |
1754 | * not yet | 1751 | * not yet |
1755 | */ | 1752 | */ |
1756 | if (systemcfg->platform == PLATFORM_POWERMAC) | 1753 | if (_machine == PLATFORM_POWERMAC) |
1757 | return -ENODEV; | 1754 | return -ENODEV; |
1758 | 1755 | ||
1759 | /* fix up new node's linux_phandle field */ | 1756 | /* fix up new node's linux_phandle field */ |
diff --git a/arch/ppc64/kernel/prom_init.c b/arch/ppc64/kernel/prom_init.c index e4c880dab997..6375f40b23db 100644 --- a/arch/ppc64/kernel/prom_init.c +++ b/arch/ppc64/kernel/prom_init.c | |||
@@ -1934,7 +1934,8 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, unsigned long | |||
1934 | /* | 1934 | /* |
1935 | * On pSeries, inform the firmware about our capabilities | 1935 | * On pSeries, inform the firmware about our capabilities |
1936 | */ | 1936 | */ |
1937 | if (RELOC(of_platform) & PLATFORM_PSERIES) | 1937 | if (RELOC(of_platform) == PLATFORM_PSERIES || |
1938 | RELOC(of_platform) == PLATFORM_PSERIES_LPAR) | ||
1938 | prom_send_capabilities(); | 1939 | prom_send_capabilities(); |
1939 | 1940 | ||
1940 | /* | 1941 | /* |
diff --git a/arch/ppc64/kernel/vdso.c b/arch/ppc64/kernel/vdso.c index 4aacf521e3e4..1bbacac44988 100644 --- a/arch/ppc64/kernel/vdso.c +++ b/arch/ppc64/kernel/vdso.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <asm/machdep.h> | 34 | #include <asm/machdep.h> |
35 | #include <asm/cputable.h> | 35 | #include <asm/cputable.h> |
36 | #include <asm/sections.h> | 36 | #include <asm/sections.h> |
37 | #include <asm/systemcfg.h> | ||
37 | #include <asm/vdso.h> | 38 | #include <asm/vdso.h> |
38 | 39 | ||
39 | #undef DEBUG | 40 | #undef DEBUG |
@@ -179,7 +180,7 @@ static struct page * vdso_vma_nopage(struct vm_area_struct * vma, | |||
179 | * Last page is systemcfg. | 180 | * Last page is systemcfg. |
180 | */ | 181 | */ |
181 | if ((vma->vm_end - address) <= PAGE_SIZE) | 182 | if ((vma->vm_end - address) <= PAGE_SIZE) |
182 | pg = virt_to_page(systemcfg); | 183 | pg = virt_to_page(_systemcfg); |
183 | else | 184 | else |
184 | pg = virt_to_page(vbase + offset); | 185 | pg = virt_to_page(vbase + offset); |
185 | 186 | ||
@@ -604,7 +605,7 @@ void __init vdso_init(void) | |||
604 | get_page(pg); | 605 | get_page(pg); |
605 | } | 606 | } |
606 | 607 | ||
607 | get_page(virt_to_page(systemcfg)); | 608 | get_page(virt_to_page(_systemcfg)); |
608 | } | 609 | } |
609 | 610 | ||
610 | int in_gate_area_no_task(unsigned long addr) | 611 | int in_gate_area_no_task(unsigned long addr) |
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 3937adf4e5e5..aa993715d644 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c | |||
@@ -203,6 +203,7 @@ acpi_handle acpi_get_pci_rootbridge_handle(unsigned int seg, unsigned int bus) | |||
203 | acpi_get_devices(PCI_ROOT_HID_STRING, find_pci_rootbridge, &find, NULL); | 203 | acpi_get_devices(PCI_ROOT_HID_STRING, find_pci_rootbridge, &find, NULL); |
204 | return find.handle; | 204 | return find.handle; |
205 | } | 205 | } |
206 | EXPORT_SYMBOL_GPL(acpi_get_pci_rootbridge_handle); | ||
206 | 207 | ||
207 | /* Get device's handler per its address under its parent */ | 208 | /* Get device's handler per its address under its parent */ |
208 | struct acpi_find_child { | 209 | struct acpi_find_child { |
diff --git a/drivers/atm/horizon.c b/drivers/atm/horizon.c index 0cded0468003..821c81e8cd38 100644 --- a/drivers/atm/horizon.c +++ b/drivers/atm/horizon.c | |||
@@ -1511,8 +1511,8 @@ static inline short setup_idle_tx_channel (hrz_dev * dev, hrz_vcc * vcc) { | |||
1511 | // a.k.a. prepare the channel and remember that we have done so. | 1511 | // a.k.a. prepare the channel and remember that we have done so. |
1512 | 1512 | ||
1513 | tx_ch_desc * tx_desc = &memmap->tx_descs[tx_channel]; | 1513 | tx_ch_desc * tx_desc = &memmap->tx_descs[tx_channel]; |
1514 | u16 rd_ptr; | 1514 | u32 rd_ptr; |
1515 | u16 wr_ptr; | 1515 | u32 wr_ptr; |
1516 | u16 channel = vcc->channel; | 1516 | u16 channel = vcc->channel; |
1517 | 1517 | ||
1518 | unsigned long flags; | 1518 | unsigned long flags; |
diff --git a/drivers/char/agp/ali-agp.c b/drivers/char/agp/ali-agp.c index ba54b5872578..b02fc2267159 100644 --- a/drivers/char/agp/ali-agp.c +++ b/drivers/char/agp/ali-agp.c | |||
@@ -389,7 +389,6 @@ static struct pci_device_id agp_ali_pci_table[] = { | |||
389 | MODULE_DEVICE_TABLE(pci, agp_ali_pci_table); | 389 | MODULE_DEVICE_TABLE(pci, agp_ali_pci_table); |
390 | 390 | ||
391 | static struct pci_driver agp_ali_pci_driver = { | 391 | static struct pci_driver agp_ali_pci_driver = { |
392 | .owner = THIS_MODULE, | ||
393 | .name = "agpgart-ali", | 392 | .name = "agpgart-ali", |
394 | .id_table = agp_ali_pci_table, | 393 | .id_table = agp_ali_pci_table, |
395 | .probe = agp_ali_probe, | 394 | .probe = agp_ali_probe, |
diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c index 40fcd88b2cea..1f776651ac64 100644 --- a/drivers/char/agp/amd-k7-agp.c +++ b/drivers/char/agp/amd-k7-agp.c | |||
@@ -515,7 +515,6 @@ static struct pci_device_id agp_amdk7_pci_table[] = { | |||
515 | MODULE_DEVICE_TABLE(pci, agp_amdk7_pci_table); | 515 | MODULE_DEVICE_TABLE(pci, agp_amdk7_pci_table); |
516 | 516 | ||
517 | static struct pci_driver agp_amdk7_pci_driver = { | 517 | static struct pci_driver agp_amdk7_pci_driver = { |
518 | .owner = THIS_MODULE, | ||
519 | .name = "agpgart-amdk7", | 518 | .name = "agpgart-amdk7", |
520 | .id_table = agp_amdk7_pci_table, | 519 | .id_table = agp_amdk7_pci_table, |
521 | .probe = agp_amdk7_probe, | 520 | .probe = agp_amdk7_probe, |
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index 8f748fddca94..78ce98a69f37 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c | |||
@@ -703,7 +703,6 @@ static struct pci_device_id agp_amd64_pci_table[] = { | |||
703 | MODULE_DEVICE_TABLE(pci, agp_amd64_pci_table); | 703 | MODULE_DEVICE_TABLE(pci, agp_amd64_pci_table); |
704 | 704 | ||
705 | static struct pci_driver agp_amd64_pci_driver = { | 705 | static struct pci_driver agp_amd64_pci_driver = { |
706 | .owner = THIS_MODULE, | ||
707 | .name = "agpgart-amd64", | 706 | .name = "agpgart-amd64", |
708 | .id_table = agp_amd64_pci_table, | 707 | .id_table = agp_amd64_pci_table, |
709 | .probe = agp_amd64_probe, | 708 | .probe = agp_amd64_probe, |
diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c index fbd415565463..53372a83b675 100644 --- a/drivers/char/agp/ati-agp.c +++ b/drivers/char/agp/ati-agp.c | |||
@@ -521,7 +521,6 @@ static struct pci_device_id agp_ati_pci_table[] = { | |||
521 | MODULE_DEVICE_TABLE(pci, agp_ati_pci_table); | 521 | MODULE_DEVICE_TABLE(pci, agp_ati_pci_table); |
522 | 522 | ||
523 | static struct pci_driver agp_ati_pci_driver = { | 523 | static struct pci_driver agp_ati_pci_driver = { |
524 | .owner = THIS_MODULE, | ||
525 | .name = "agpgart-ati", | 524 | .name = "agpgart-ati", |
526 | .id_table = agp_ati_pci_table, | 525 | .id_table = agp_ati_pci_table, |
527 | .probe = agp_ati_probe, | 526 | .probe = agp_ati_probe, |
diff --git a/drivers/char/agp/efficeon-agp.c b/drivers/char/agp/efficeon-agp.c index d41e0a62e32e..e7aea77a60f9 100644 --- a/drivers/char/agp/efficeon-agp.c +++ b/drivers/char/agp/efficeon-agp.c | |||
@@ -429,7 +429,6 @@ static struct pci_device_id agp_efficeon_pci_table[] = { | |||
429 | MODULE_DEVICE_TABLE(pci, agp_efficeon_pci_table); | 429 | MODULE_DEVICE_TABLE(pci, agp_efficeon_pci_table); |
430 | 430 | ||
431 | static struct pci_driver agp_efficeon_pci_driver = { | 431 | static struct pci_driver agp_efficeon_pci_driver = { |
432 | .owner = THIS_MODULE, | ||
433 | .name = "agpgart-efficeon", | 432 | .name = "agpgart-efficeon", |
434 | .id_table = agp_efficeon_pci_table, | 433 | .id_table = agp_efficeon_pci_table, |
435 | .probe = agp_efficeon_probe, | 434 | .probe = agp_efficeon_probe, |
diff --git a/drivers/char/agp/i460-agp.c b/drivers/char/agp/i460-agp.c index 34a444658ffe..8ee19a4a6bce 100644 --- a/drivers/char/agp/i460-agp.c +++ b/drivers/char/agp/i460-agp.c | |||
@@ -622,7 +622,6 @@ static struct pci_device_id agp_intel_i460_pci_table[] = { | |||
622 | MODULE_DEVICE_TABLE(pci, agp_intel_i460_pci_table); | 622 | MODULE_DEVICE_TABLE(pci, agp_intel_i460_pci_table); |
623 | 623 | ||
624 | static struct pci_driver agp_intel_i460_pci_driver = { | 624 | static struct pci_driver agp_intel_i460_pci_driver = { |
625 | .owner = THIS_MODULE, | ||
626 | .name = "agpgart-intel-i460", | 625 | .name = "agpgart-intel-i460", |
627 | .id_table = agp_intel_i460_pci_table, | 626 | .id_table = agp_intel_i460_pci_table, |
628 | .probe = agp_intel_i460_probe, | 627 | .probe = agp_intel_i460_probe, |
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index 027161ab88e9..e7bed5047dcc 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c | |||
@@ -1827,7 +1827,6 @@ static struct pci_device_id agp_intel_pci_table[] = { | |||
1827 | MODULE_DEVICE_TABLE(pci, agp_intel_pci_table); | 1827 | MODULE_DEVICE_TABLE(pci, agp_intel_pci_table); |
1828 | 1828 | ||
1829 | static struct pci_driver agp_intel_pci_driver = { | 1829 | static struct pci_driver agp_intel_pci_driver = { |
1830 | .owner = THIS_MODULE, | ||
1831 | .name = "agpgart-intel", | 1830 | .name = "agpgart-intel", |
1832 | .id_table = agp_intel_pci_table, | 1831 | .id_table = agp_intel_pci_table, |
1833 | .probe = agp_intel_probe, | 1832 | .probe = agp_intel_probe, |
diff --git a/drivers/char/agp/nvidia-agp.c b/drivers/char/agp/nvidia-agp.c index 3aed0c5e2f92..80dafa3030bd 100644 --- a/drivers/char/agp/nvidia-agp.c +++ b/drivers/char/agp/nvidia-agp.c | |||
@@ -398,7 +398,6 @@ static struct pci_device_id agp_nvidia_pci_table[] = { | |||
398 | MODULE_DEVICE_TABLE(pci, agp_nvidia_pci_table); | 398 | MODULE_DEVICE_TABLE(pci, agp_nvidia_pci_table); |
399 | 399 | ||
400 | static struct pci_driver agp_nvidia_pci_driver = { | 400 | static struct pci_driver agp_nvidia_pci_driver = { |
401 | .owner = THIS_MODULE, | ||
402 | .name = "agpgart-nvidia", | 401 | .name = "agpgart-nvidia", |
403 | .id_table = agp_nvidia_pci_table, | 402 | .id_table = agp_nvidia_pci_table, |
404 | .probe = agp_nvidia_probe, | 403 | .probe = agp_nvidia_probe, |
diff --git a/drivers/char/agp/sis-agp.c b/drivers/char/agp/sis-agp.c index a701361a8890..ebc05554045c 100644 --- a/drivers/char/agp/sis-agp.c +++ b/drivers/char/agp/sis-agp.c | |||
@@ -332,7 +332,6 @@ static struct pci_device_id agp_sis_pci_table[] = { | |||
332 | MODULE_DEVICE_TABLE(pci, agp_sis_pci_table); | 332 | MODULE_DEVICE_TABLE(pci, agp_sis_pci_table); |
333 | 333 | ||
334 | static struct pci_driver agp_sis_pci_driver = { | 334 | static struct pci_driver agp_sis_pci_driver = { |
335 | .owner = THIS_MODULE, | ||
336 | .name = "agpgart-sis", | 335 | .name = "agpgart-sis", |
337 | .id_table = agp_sis_pci_table, | 336 | .id_table = agp_sis_pci_table, |
338 | .probe = agp_sis_probe, | 337 | .probe = agp_sis_probe, |
diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c index 5a5392dd1254..3f8f7fa6b0ff 100644 --- a/drivers/char/agp/sworks-agp.c +++ b/drivers/char/agp/sworks-agp.c | |||
@@ -545,7 +545,6 @@ static struct pci_device_id agp_serverworks_pci_table[] = { | |||
545 | MODULE_DEVICE_TABLE(pci, agp_serverworks_pci_table); | 545 | MODULE_DEVICE_TABLE(pci, agp_serverworks_pci_table); |
546 | 546 | ||
547 | static struct pci_driver agp_serverworks_pci_driver = { | 547 | static struct pci_driver agp_serverworks_pci_driver = { |
548 | .owner = THIS_MODULE, | ||
549 | .name = "agpgart-serverworks", | 548 | .name = "agpgart-serverworks", |
550 | .id_table = agp_serverworks_pci_table, | 549 | .id_table = agp_serverworks_pci_table, |
551 | .probe = agp_serverworks_probe, | 550 | .probe = agp_serverworks_probe, |
diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c index 183c50acab27..c8255312b8c1 100644 --- a/drivers/char/agp/uninorth-agp.c +++ b/drivers/char/agp/uninorth-agp.c | |||
@@ -658,7 +658,6 @@ static struct pci_device_id agp_uninorth_pci_table[] = { | |||
658 | MODULE_DEVICE_TABLE(pci, agp_uninorth_pci_table); | 658 | MODULE_DEVICE_TABLE(pci, agp_uninorth_pci_table); |
659 | 659 | ||
660 | static struct pci_driver agp_uninorth_pci_driver = { | 660 | static struct pci_driver agp_uninorth_pci_driver = { |
661 | .owner = THIS_MODULE, | ||
662 | .name = "agpgart-uninorth", | 661 | .name = "agpgart-uninorth", |
663 | .id_table = agp_uninorth_pci_table, | 662 | .id_table = agp_uninorth_pci_table, |
664 | .probe = agp_uninorth_probe, | 663 | .probe = agp_uninorth_probe, |
diff --git a/drivers/char/agp/via-agp.c b/drivers/char/agp/via-agp.c index 5d9a13700074..c847df575cf5 100644 --- a/drivers/char/agp/via-agp.c +++ b/drivers/char/agp/via-agp.c | |||
@@ -518,7 +518,6 @@ MODULE_DEVICE_TABLE(pci, agp_via_pci_table); | |||
518 | 518 | ||
519 | 519 | ||
520 | static struct pci_driver agp_via_pci_driver = { | 520 | static struct pci_driver agp_via_pci_driver = { |
521 | .owner = THIS_MODULE, | ||
522 | .name = "agpgart-via", | 521 | .name = "agpgart-via", |
523 | .id_table = agp_via_pci_table, | 522 | .id_table = agp_via_pci_table, |
524 | .probe = agp_via_probe, | 523 | .probe = agp_via_probe, |
diff --git a/drivers/char/epca.c b/drivers/char/epca.c index b7a0e4d6b934..407708a001e4 100644 --- a/drivers/char/epca.c +++ b/drivers/char/epca.c | |||
@@ -3113,7 +3113,6 @@ MODULE_DEVICE_TABLE(pci, epca_pci_tbl); | |||
3113 | int __init init_PCI (void) | 3113 | int __init init_PCI (void) |
3114 | { /* Begin init_PCI */ | 3114 | { /* Begin init_PCI */ |
3115 | memset (&epca_driver, 0, sizeof (epca_driver)); | 3115 | memset (&epca_driver, 0, sizeof (epca_driver)); |
3116 | epca_driver.owner = THIS_MODULE; | ||
3117 | epca_driver.name = "epca"; | 3116 | epca_driver.name = "epca"; |
3118 | epca_driver.id_table = epca_pci_tbl; | 3117 | epca_driver.id_table = epca_pci_tbl; |
3119 | epca_driver.probe = epca_init_one; | 3118 | epca_driver.probe = epca_init_one; |
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index 5d1ffa3bd4c3..82c6abde68df 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c | |||
@@ -912,7 +912,6 @@ MODULE_DEVICE_TABLE(pci, synclink_pci_tbl); | |||
912 | MODULE_LICENSE("GPL"); | 912 | MODULE_LICENSE("GPL"); |
913 | 913 | ||
914 | static struct pci_driver synclink_pci_driver = { | 914 | static struct pci_driver synclink_pci_driver = { |
915 | .owner = THIS_MODULE, | ||
916 | .name = "synclink", | 915 | .name = "synclink", |
917 | .id_table = synclink_pci_tbl, | 916 | .id_table = synclink_pci_tbl, |
918 | .probe = synclink_init_one, | 917 | .probe = synclink_init_one, |
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index 7c063c5abc55..ee5a40be9f99 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c | |||
@@ -500,7 +500,6 @@ MODULE_DEVICE_TABLE(pci, synclinkmp_pci_tbl); | |||
500 | MODULE_LICENSE("GPL"); | 500 | MODULE_LICENSE("GPL"); |
501 | 501 | ||
502 | static struct pci_driver synclinkmp_pci_driver = { | 502 | static struct pci_driver synclinkmp_pci_driver = { |
503 | .owner = THIS_MODULE, | ||
504 | .name = "synclinkmp", | 503 | .name = "synclinkmp", |
505 | .id_table = synclinkmp_pci_tbl, | 504 | .id_table = synclinkmp_pci_tbl, |
506 | .probe = synclinkmp_init_one, | 505 | .probe = synclinkmp_init_one, |
diff --git a/drivers/char/watchdog/pcwd_pci.c b/drivers/char/watchdog/pcwd_pci.c index d9ef55bdf88a..2451edbefece 100644 --- a/drivers/char/watchdog/pcwd_pci.c +++ b/drivers/char/watchdog/pcwd_pci.c | |||
@@ -755,7 +755,6 @@ static struct pci_device_id pcipcwd_pci_tbl[] = { | |||
755 | MODULE_DEVICE_TABLE(pci, pcipcwd_pci_tbl); | 755 | MODULE_DEVICE_TABLE(pci, pcipcwd_pci_tbl); |
756 | 756 | ||
757 | static struct pci_driver pcipcwd_driver = { | 757 | static struct pci_driver pcipcwd_driver = { |
758 | .owner = THIS_MODULE, | ||
759 | .name = WATCHDOG_NAME, | 758 | .name = WATCHDOG_NAME, |
760 | .id_table = pcipcwd_pci_tbl, | 759 | .id_table = pcipcwd_pci_tbl, |
761 | .probe = pcipcwd_card_init, | 760 | .probe = pcipcwd_card_init, |
diff --git a/drivers/char/watchdog/wdt_pci.c b/drivers/char/watchdog/wdt_pci.c index dc9370f6c348..4b3311993d48 100644 --- a/drivers/char/watchdog/wdt_pci.c +++ b/drivers/char/watchdog/wdt_pci.c | |||
@@ -711,7 +711,6 @@ MODULE_DEVICE_TABLE(pci, wdtpci_pci_tbl); | |||
711 | 711 | ||
712 | 712 | ||
713 | static struct pci_driver wdtpci_driver = { | 713 | static struct pci_driver wdtpci_driver = { |
714 | .owner = THIS_MODULE, | ||
715 | .name = "wdt_pci", | 714 | .name = "wdt_pci", |
716 | .id_table = wdtpci_pci_tbl, | 715 | .id_table = wdtpci_pci_tbl, |
717 | .probe = wdtpci_init_one, | 716 | .probe = wdtpci_init_one, |
diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c index ba90f5140af6..3eb47890db40 100644 --- a/drivers/i2c/busses/i2c-ali1535.c +++ b/drivers/i2c/busses/i2c-ali1535.c | |||
@@ -513,7 +513,6 @@ static void __devexit ali1535_remove(struct pci_dev *dev) | |||
513 | } | 513 | } |
514 | 514 | ||
515 | static struct pci_driver ali1535_driver = { | 515 | static struct pci_driver ali1535_driver = { |
516 | .owner = THIS_MODULE, | ||
517 | .name = "ali1535_smbus", | 516 | .name = "ali1535_smbus", |
518 | .id_table = ali1535_ids, | 517 | .id_table = ali1535_ids, |
519 | .probe = ali1535_probe, | 518 | .probe = ali1535_probe, |
diff --git a/drivers/i2c/busses/i2c-ali1563.c b/drivers/i2c/busses/i2c-ali1563.c index f1a62d892425..e6f63208fc4a 100644 --- a/drivers/i2c/busses/i2c-ali1563.c +++ b/drivers/i2c/busses/i2c-ali1563.c | |||
@@ -408,7 +408,6 @@ static struct pci_device_id __devinitdata ali1563_id_table[] = { | |||
408 | MODULE_DEVICE_TABLE (pci, ali1563_id_table); | 408 | MODULE_DEVICE_TABLE (pci, ali1563_id_table); |
409 | 409 | ||
410 | static struct pci_driver ali1563_pci_driver = { | 410 | static struct pci_driver ali1563_pci_driver = { |
411 | .owner = THIS_MODULE, | ||
412 | .name = "ali1563_smbus", | 411 | .name = "ali1563_smbus", |
413 | .id_table = ali1563_id_table, | 412 | .id_table = ali1563_id_table, |
414 | .probe = ali1563_probe, | 413 | .probe = ali1563_probe, |
diff --git a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c index 400b08ed4299..7a5c0941dbc1 100644 --- a/drivers/i2c/busses/i2c-ali15x3.c +++ b/drivers/i2c/busses/i2c-ali15x3.c | |||
@@ -504,7 +504,6 @@ static void __devexit ali15x3_remove(struct pci_dev *dev) | |||
504 | } | 504 | } |
505 | 505 | ||
506 | static struct pci_driver ali15x3_driver = { | 506 | static struct pci_driver ali15x3_driver = { |
507 | .owner = THIS_MODULE, | ||
508 | .name = "ali15x3_smbus", | 507 | .name = "ali15x3_smbus", |
509 | .id_table = ali15x3_ids, | 508 | .id_table = ali15x3_ids, |
510 | .probe = ali15x3_probe, | 509 | .probe = ali15x3_probe, |
diff --git a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c index de035d137c3f..1750dedaf4b5 100644 --- a/drivers/i2c/busses/i2c-amd756.c +++ b/drivers/i2c/busses/i2c-amd756.c | |||
@@ -401,7 +401,6 @@ static void __devexit amd756_remove(struct pci_dev *dev) | |||
401 | } | 401 | } |
402 | 402 | ||
403 | static struct pci_driver amd756_driver = { | 403 | static struct pci_driver amd756_driver = { |
404 | .owner = THIS_MODULE, | ||
405 | .name = "amd756_smbus", | 404 | .name = "amd756_smbus", |
406 | .id_table = amd756_ids, | 405 | .id_table = amd756_ids, |
407 | .probe = amd756_probe, | 406 | .probe = amd756_probe, |
diff --git a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c index f3b79a68dbec..e5ef560e686a 100644 --- a/drivers/i2c/busses/i2c-amd8111.c +++ b/drivers/i2c/busses/i2c-amd8111.c | |||
@@ -384,7 +384,6 @@ static void __devexit amd8111_remove(struct pci_dev *dev) | |||
384 | } | 384 | } |
385 | 385 | ||
386 | static struct pci_driver amd8111_driver = { | 386 | static struct pci_driver amd8111_driver = { |
387 | .owner = THIS_MODULE, | ||
388 | .name = "amd8111_smbus2", | 387 | .name = "amd8111_smbus2", |
389 | .id_table = amd8111_ids, | 388 | .id_table = amd8111_ids, |
390 | .probe = amd8111_probe, | 389 | .probe = amd8111_probe, |
diff --git a/drivers/i2c/busses/i2c-hydra.c b/drivers/i2c/busses/i2c-hydra.c index 1b5354e24bf5..e0cb3b0f92fa 100644 --- a/drivers/i2c/busses/i2c-hydra.c +++ b/drivers/i2c/busses/i2c-hydra.c | |||
@@ -155,7 +155,6 @@ static void __devexit hydra_remove(struct pci_dev *dev) | |||
155 | 155 | ||
156 | 156 | ||
157 | static struct pci_driver hydra_driver = { | 157 | static struct pci_driver hydra_driver = { |
158 | .owner = THIS_MODULE, | ||
159 | .name = "hydra_smbus", | 158 | .name = "hydra_smbus", |
160 | .id_table = hydra_ids, | 159 | .id_table = hydra_ids, |
161 | .probe = hydra_probe, | 160 | .probe = hydra_probe, |
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 4f63195069da..ac3eafa8aac0 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c | |||
@@ -560,7 +560,6 @@ static void __devexit i801_remove(struct pci_dev *dev) | |||
560 | } | 560 | } |
561 | 561 | ||
562 | static struct pci_driver i801_driver = { | 562 | static struct pci_driver i801_driver = { |
563 | .owner = THIS_MODULE, | ||
564 | .name = "i801_smbus", | 563 | .name = "i801_smbus", |
565 | .id_table = i801_ids, | 564 | .id_table = i801_ids, |
566 | .probe = i801_probe, | 565 | .probe = i801_probe, |
diff --git a/drivers/i2c/busses/i2c-i810.c b/drivers/i2c/busses/i2c-i810.c index 52bc30593bd7..748be30f2bae 100644 --- a/drivers/i2c/busses/i2c-i810.c +++ b/drivers/i2c/busses/i2c-i810.c | |||
@@ -233,7 +233,6 @@ static void __devexit i810_remove(struct pci_dev *dev) | |||
233 | } | 233 | } |
234 | 234 | ||
235 | static struct pci_driver i810_driver = { | 235 | static struct pci_driver i810_driver = { |
236 | .owner = THIS_MODULE, | ||
237 | .name = "i810_smbus", | 236 | .name = "i810_smbus", |
238 | .id_table = i810_ids, | 237 | .id_table = i810_ids, |
239 | .probe = i810_probe, | 238 | .probe = i810_probe, |
diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c index fd26036e68a3..4d18e6e5f159 100644 --- a/drivers/i2c/busses/i2c-nforce2.c +++ b/drivers/i2c/busses/i2c-nforce2.c | |||
@@ -347,7 +347,6 @@ static void __devexit nforce2_remove(struct pci_dev *dev) | |||
347 | } | 347 | } |
348 | 348 | ||
349 | static struct pci_driver nforce2_driver = { | 349 | static struct pci_driver nforce2_driver = { |
350 | .owner = THIS_MODULE, | ||
351 | .name = "nForce2_smbus", | 350 | .name = "nForce2_smbus", |
352 | .id_table = nforce2_ids, | 351 | .id_table = nforce2_ids, |
353 | .probe = nforce2_probe, | 352 | .probe = nforce2_probe, |
diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c index 7d63eec423fe..692f47345481 100644 --- a/drivers/i2c/busses/i2c-piix4.c +++ b/drivers/i2c/busses/i2c-piix4.c | |||
@@ -462,7 +462,6 @@ static void __devexit piix4_remove(struct pci_dev *dev) | |||
462 | } | 462 | } |
463 | 463 | ||
464 | static struct pci_driver piix4_driver = { | 464 | static struct pci_driver piix4_driver = { |
465 | .owner = THIS_MODULE, | ||
466 | .name = "piix4_smbus", | 465 | .name = "piix4_smbus", |
467 | .id_table = piix4_ids, | 466 | .id_table = piix4_ids, |
468 | .probe = piix4_probe, | 467 | .probe = piix4_probe, |
diff --git a/drivers/i2c/busses/i2c-prosavage.c b/drivers/i2c/busses/i2c-prosavage.c index 42cb1d8ca659..9479525892e3 100644 --- a/drivers/i2c/busses/i2c-prosavage.c +++ b/drivers/i2c/busses/i2c-prosavage.c | |||
@@ -301,7 +301,6 @@ static struct pci_device_id prosavage_pci_tbl[] = { | |||
301 | MODULE_DEVICE_TABLE (pci, prosavage_pci_tbl); | 301 | MODULE_DEVICE_TABLE (pci, prosavage_pci_tbl); |
302 | 302 | ||
303 | static struct pci_driver prosavage_driver = { | 303 | static struct pci_driver prosavage_driver = { |
304 | .owner = THIS_MODULE, | ||
305 | .name = "prosavage_smbus", | 304 | .name = "prosavage_smbus", |
306 | .id_table = prosavage_pci_tbl, | 305 | .id_table = prosavage_pci_tbl, |
307 | .probe = prosavage_probe, | 306 | .probe = prosavage_probe, |
diff --git a/drivers/i2c/busses/i2c-savage4.c b/drivers/i2c/busses/i2c-savage4.c index aebe87ba4033..0c8518298e4d 100644 --- a/drivers/i2c/busses/i2c-savage4.c +++ b/drivers/i2c/busses/i2c-savage4.c | |||
@@ -179,7 +179,6 @@ static void __devexit savage4_remove(struct pci_dev *dev) | |||
179 | } | 179 | } |
180 | 180 | ||
181 | static struct pci_driver savage4_driver = { | 181 | static struct pci_driver savage4_driver = { |
182 | .owner = THIS_MODULE, | ||
183 | .name = "savage4_smbus", | 182 | .name = "savage4_smbus", |
184 | .id_table = savage4_ids, | 183 | .id_table = savage4_ids, |
185 | .probe = savage4_probe, | 184 | .probe = savage4_probe, |
diff --git a/drivers/i2c/busses/i2c-sis5595.c b/drivers/i2c/busses/i2c-sis5595.c index 3ad27c3ba15b..b57ab74d23ec 100644 --- a/drivers/i2c/busses/i2c-sis5595.c +++ b/drivers/i2c/busses/i2c-sis5595.c | |||
@@ -398,7 +398,6 @@ static void __devexit sis5595_remove(struct pci_dev *dev) | |||
398 | } | 398 | } |
399 | 399 | ||
400 | static struct pci_driver sis5595_driver = { | 400 | static struct pci_driver sis5595_driver = { |
401 | .owner = THIS_MODULE, | ||
402 | .name = "sis5595_smbus", | 401 | .name = "sis5595_smbus", |
403 | .id_table = sis5595_ids, | 402 | .id_table = sis5595_ids, |
404 | .probe = sis5595_probe, | 403 | .probe = sis5595_probe, |
diff --git a/drivers/i2c/busses/i2c-sis630.c b/drivers/i2c/busses/i2c-sis630.c index 7f49e5fd3ff0..acb75e282414 100644 --- a/drivers/i2c/busses/i2c-sis630.c +++ b/drivers/i2c/busses/i2c-sis630.c | |||
@@ -496,7 +496,6 @@ static void __devexit sis630_remove(struct pci_dev *dev) | |||
496 | 496 | ||
497 | 497 | ||
498 | static struct pci_driver sis630_driver = { | 498 | static struct pci_driver sis630_driver = { |
499 | .owner = THIS_MODULE, | ||
500 | .name = "sis630_smbus", | 499 | .name = "sis630_smbus", |
501 | .id_table = sis630_ids, | 500 | .id_table = sis630_ids, |
502 | .probe = sis630_probe, | 501 | .probe = sis630_probe, |
diff --git a/drivers/i2c/busses/i2c-sis96x.c b/drivers/i2c/busses/i2c-sis96x.c index 6a134c091324..3024907cdafe 100644 --- a/drivers/i2c/busses/i2c-sis96x.c +++ b/drivers/i2c/busses/i2c-sis96x.c | |||
@@ -329,7 +329,6 @@ static void __devexit sis96x_remove(struct pci_dev *dev) | |||
329 | } | 329 | } |
330 | 330 | ||
331 | static struct pci_driver sis96x_driver = { | 331 | static struct pci_driver sis96x_driver = { |
332 | .owner = THIS_MODULE, | ||
333 | .name = "sis96x_smbus", | 332 | .name = "sis96x_smbus", |
334 | .id_table = sis96x_ids, | 333 | .id_table = sis96x_ids, |
335 | .probe = sis96x_probe, | 334 | .probe = sis96x_probe, |
diff --git a/drivers/i2c/busses/i2c-via.c b/drivers/i2c/busses/i2c-via.c index 544a38e64394..484bbacfce6b 100644 --- a/drivers/i2c/busses/i2c-via.c +++ b/drivers/i2c/busses/i2c-via.c | |||
@@ -159,7 +159,6 @@ static void __devexit vt586b_remove(struct pci_dev *dev) | |||
159 | 159 | ||
160 | 160 | ||
161 | static struct pci_driver vt586b_driver = { | 161 | static struct pci_driver vt586b_driver = { |
162 | .owner = THIS_MODULE, | ||
163 | .name = "vt586b_smbus", | 162 | .name = "vt586b_smbus", |
164 | .id_table = vt586b_ids, | 163 | .id_table = vt586b_ids, |
165 | .probe = vt586b_probe, | 164 | .probe = vt586b_probe, |
diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c index a2237d4b2cf2..47e52bf2c5ec 100644 --- a/drivers/i2c/busses/i2c-viapro.c +++ b/drivers/i2c/busses/i2c-viapro.c | |||
@@ -440,7 +440,6 @@ static struct pci_device_id vt596_ids[] = { | |||
440 | MODULE_DEVICE_TABLE(pci, vt596_ids); | 440 | MODULE_DEVICE_TABLE(pci, vt596_ids); |
441 | 441 | ||
442 | static struct pci_driver vt596_driver = { | 442 | static struct pci_driver vt596_driver = { |
443 | .owner = THIS_MODULE, | ||
444 | .name = "vt596_smbus", | 443 | .name = "vt596_smbus", |
445 | .id_table = vt596_ids, | 444 | .id_table = vt596_ids, |
446 | .probe = vt596_probe, | 445 | .probe = vt596_probe, |
diff --git a/drivers/i2c/busses/i2c-voodoo3.c b/drivers/i2c/busses/i2c-voodoo3.c index 650c3ebde84c..b675773b0cc1 100644 --- a/drivers/i2c/busses/i2c-voodoo3.c +++ b/drivers/i2c/busses/i2c-voodoo3.c | |||
@@ -225,7 +225,6 @@ static void __devexit voodoo3_remove(struct pci_dev *dev) | |||
225 | } | 225 | } |
226 | 226 | ||
227 | static struct pci_driver voodoo3_driver = { | 227 | static struct pci_driver voodoo3_driver = { |
228 | .owner = THIS_MODULE, | ||
229 | .name = "voodoo3_smbus", | 228 | .name = "voodoo3_smbus", |
230 | .id_table = voodoo3_ids, | 229 | .id_table = voodoo3_ids, |
231 | .probe = voodoo3_probe, | 230 | .probe = voodoo3_probe, |
diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c index 18ed7765417c..d4f2111d4364 100644 --- a/drivers/ide/setup-pci.c +++ b/drivers/ide/setup-pci.c | |||
@@ -787,8 +787,9 @@ static int pre_init = 1; /* Before first ordered IDE scan */ | |||
787 | static LIST_HEAD(ide_pci_drivers); | 787 | static LIST_HEAD(ide_pci_drivers); |
788 | 788 | ||
789 | /* | 789 | /* |
790 | * ide_register_pci_driver - attach IDE driver | 790 | * __ide_register_pci_driver - attach IDE driver |
791 | * @driver: pci driver | 791 | * @driver: pci driver |
792 | * @module: owner module of the driver | ||
792 | * | 793 | * |
793 | * Registers a driver with the IDE layer. The IDE layer arranges that | 794 | * Registers a driver with the IDE layer. The IDE layer arranges that |
794 | * boot time setup is done in the expected device order and then | 795 | * boot time setup is done in the expected device order and then |
@@ -801,15 +802,16 @@ static LIST_HEAD(ide_pci_drivers); | |||
801 | * Returns are the same as for pci_register_driver | 802 | * Returns are the same as for pci_register_driver |
802 | */ | 803 | */ |
803 | 804 | ||
804 | int ide_pci_register_driver(struct pci_driver *driver) | 805 | int __ide_pci_register_driver(struct pci_driver *driver, struct module *module) |
805 | { | 806 | { |
806 | if(!pre_init) | 807 | if(!pre_init) |
807 | return pci_module_init(driver); | 808 | return __pci_register_driver(driver, module); |
809 | driver->driver.owner = module; | ||
808 | list_add_tail(&driver->node, &ide_pci_drivers); | 810 | list_add_tail(&driver->node, &ide_pci_drivers); |
809 | return 0; | 811 | return 0; |
810 | } | 812 | } |
811 | 813 | ||
812 | EXPORT_SYMBOL_GPL(ide_pci_register_driver); | 814 | EXPORT_SYMBOL_GPL(__ide_pci_register_driver); |
813 | 815 | ||
814 | /** | 816 | /** |
815 | * ide_unregister_pci_driver - unregister an IDE driver | 817 | * ide_unregister_pci_driver - unregister an IDE driver |
@@ -897,6 +899,6 @@ void __init ide_scan_pcibus (int scan_direction) | |||
897 | { | 899 | { |
898 | list_del(l); | 900 | list_del(l); |
899 | d = list_entry(l, struct pci_driver, node); | 901 | d = list_entry(l, struct pci_driver, node); |
900 | pci_register_driver(d); | 902 | __pci_register_driver(d, d->driver.owner); |
901 | } | 903 | } |
902 | } | 904 | } |
diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c index aed5ca23fb22..5ea741f47fc8 100644 --- a/drivers/infiniband/core/user_mad.c +++ b/drivers/infiniband/core/user_mad.c | |||
@@ -31,7 +31,7 @@ | |||
31 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | 31 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
32 | * SOFTWARE. | 32 | * SOFTWARE. |
33 | * | 33 | * |
34 | * $Id: user_mad.c 2814 2005-07-06 19:14:09Z halr $ | 34 | * $Id: user_mad.c 4010 2005-11-09 23:11:56Z roland $ |
35 | */ | 35 | */ |
36 | 36 | ||
37 | #include <linux/module.h> | 37 | #include <linux/module.h> |
@@ -110,13 +110,13 @@ struct ib_umad_device { | |||
110 | }; | 110 | }; |
111 | 111 | ||
112 | struct ib_umad_file { | 112 | struct ib_umad_file { |
113 | struct ib_umad_port *port; | 113 | struct ib_umad_port *port; |
114 | struct list_head recv_list; | 114 | struct list_head recv_list; |
115 | struct list_head port_list; | 115 | struct list_head port_list; |
116 | spinlock_t recv_lock; | 116 | spinlock_t recv_lock; |
117 | wait_queue_head_t recv_wait; | 117 | wait_queue_head_t recv_wait; |
118 | struct ib_mad_agent *agent[IB_UMAD_MAX_AGENTS]; | 118 | struct ib_mad_agent *agent[IB_UMAD_MAX_AGENTS]; |
119 | struct ib_mr *mr[IB_UMAD_MAX_AGENTS]; | 119 | int agents_dead; |
120 | }; | 120 | }; |
121 | 121 | ||
122 | struct ib_umad_packet { | 122 | struct ib_umad_packet { |
@@ -145,6 +145,12 @@ static void ib_umad_release_dev(struct kref *ref) | |||
145 | kfree(dev); | 145 | kfree(dev); |
146 | } | 146 | } |
147 | 147 | ||
148 | /* caller must hold port->mutex at least for reading */ | ||
149 | static struct ib_mad_agent *__get_agent(struct ib_umad_file *file, int id) | ||
150 | { | ||
151 | return file->agents_dead ? NULL : file->agent[id]; | ||
152 | } | ||
153 | |||
148 | static int queue_packet(struct ib_umad_file *file, | 154 | static int queue_packet(struct ib_umad_file *file, |
149 | struct ib_mad_agent *agent, | 155 | struct ib_mad_agent *agent, |
150 | struct ib_umad_packet *packet) | 156 | struct ib_umad_packet *packet) |
@@ -152,10 +158,11 @@ static int queue_packet(struct ib_umad_file *file, | |||
152 | int ret = 1; | 158 | int ret = 1; |
153 | 159 | ||
154 | down_read(&file->port->mutex); | 160 | down_read(&file->port->mutex); |
161 | |||
155 | for (packet->mad.hdr.id = 0; | 162 | for (packet->mad.hdr.id = 0; |
156 | packet->mad.hdr.id < IB_UMAD_MAX_AGENTS; | 163 | packet->mad.hdr.id < IB_UMAD_MAX_AGENTS; |
157 | packet->mad.hdr.id++) | 164 | packet->mad.hdr.id++) |
158 | if (agent == file->agent[packet->mad.hdr.id]) { | 165 | if (agent == __get_agent(file, packet->mad.hdr.id)) { |
159 | spin_lock_irq(&file->recv_lock); | 166 | spin_lock_irq(&file->recv_lock); |
160 | list_add_tail(&packet->list, &file->recv_list); | 167 | list_add_tail(&packet->list, &file->recv_list); |
161 | spin_unlock_irq(&file->recv_lock); | 168 | spin_unlock_irq(&file->recv_lock); |
@@ -327,7 +334,7 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf, | |||
327 | 334 | ||
328 | down_read(&file->port->mutex); | 335 | down_read(&file->port->mutex); |
329 | 336 | ||
330 | agent = file->agent[packet->mad.hdr.id]; | 337 | agent = __get_agent(file, packet->mad.hdr.id); |
331 | if (!agent) { | 338 | if (!agent) { |
332 | ret = -EINVAL; | 339 | ret = -EINVAL; |
333 | goto err_up; | 340 | goto err_up; |
@@ -481,7 +488,7 @@ static int ib_umad_reg_agent(struct ib_umad_file *file, unsigned long arg) | |||
481 | } | 488 | } |
482 | 489 | ||
483 | for (agent_id = 0; agent_id < IB_UMAD_MAX_AGENTS; ++agent_id) | 490 | for (agent_id = 0; agent_id < IB_UMAD_MAX_AGENTS; ++agent_id) |
484 | if (!file->agent[agent_id]) | 491 | if (!__get_agent(file, agent_id)) |
485 | goto found; | 492 | goto found; |
486 | 493 | ||
487 | ret = -ENOMEM; | 494 | ret = -ENOMEM; |
@@ -505,29 +512,15 @@ found: | |||
505 | goto out; | 512 | goto out; |
506 | } | 513 | } |
507 | 514 | ||
508 | file->agent[agent_id] = agent; | ||
509 | |||
510 | file->mr[agent_id] = ib_get_dma_mr(agent->qp->pd, IB_ACCESS_LOCAL_WRITE); | ||
511 | if (IS_ERR(file->mr[agent_id])) { | ||
512 | ret = -ENOMEM; | ||
513 | goto err; | ||
514 | } | ||
515 | |||
516 | if (put_user(agent_id, | 515 | if (put_user(agent_id, |
517 | (u32 __user *) (arg + offsetof(struct ib_user_mad_reg_req, id)))) { | 516 | (u32 __user *) (arg + offsetof(struct ib_user_mad_reg_req, id)))) { |
518 | ret = -EFAULT; | 517 | ret = -EFAULT; |
519 | goto err_mr; | 518 | ib_unregister_mad_agent(agent); |
519 | goto out; | ||
520 | } | 520 | } |
521 | 521 | ||
522 | file->agent[agent_id] = agent; | ||
522 | ret = 0; | 523 | ret = 0; |
523 | goto out; | ||
524 | |||
525 | err_mr: | ||
526 | ib_dereg_mr(file->mr[agent_id]); | ||
527 | |||
528 | err: | ||
529 | file->agent[agent_id] = NULL; | ||
530 | ib_unregister_mad_agent(agent); | ||
531 | 524 | ||
532 | out: | 525 | out: |
533 | up_write(&file->port->mutex); | 526 | up_write(&file->port->mutex); |
@@ -536,27 +529,29 @@ out: | |||
536 | 529 | ||
537 | static int ib_umad_unreg_agent(struct ib_umad_file *file, unsigned long arg) | 530 | static int ib_umad_unreg_agent(struct ib_umad_file *file, unsigned long arg) |
538 | { | 531 | { |
532 | struct ib_mad_agent *agent = NULL; | ||
539 | u32 id; | 533 | u32 id; |
540 | int ret = 0; | 534 | int ret = 0; |
541 | 535 | ||
542 | down_write(&file->port->mutex); | 536 | if (get_user(id, (u32 __user *) arg)) |
537 | return -EFAULT; | ||
543 | 538 | ||
544 | if (get_user(id, (u32 __user *) arg)) { | 539 | down_write(&file->port->mutex); |
545 | ret = -EFAULT; | ||
546 | goto out; | ||
547 | } | ||
548 | 540 | ||
549 | if (id < 0 || id >= IB_UMAD_MAX_AGENTS || !file->agent[id]) { | 541 | if (id < 0 || id >= IB_UMAD_MAX_AGENTS || !__get_agent(file, id)) { |
550 | ret = -EINVAL; | 542 | ret = -EINVAL; |
551 | goto out; | 543 | goto out; |
552 | } | 544 | } |
553 | 545 | ||
554 | ib_dereg_mr(file->mr[id]); | 546 | agent = file->agent[id]; |
555 | ib_unregister_mad_agent(file->agent[id]); | ||
556 | file->agent[id] = NULL; | 547 | file->agent[id] = NULL; |
557 | 548 | ||
558 | out: | 549 | out: |
559 | up_write(&file->port->mutex); | 550 | up_write(&file->port->mutex); |
551 | |||
552 | if (agent) | ||
553 | ib_unregister_mad_agent(agent); | ||
554 | |||
560 | return ret; | 555 | return ret; |
561 | } | 556 | } |
562 | 557 | ||
@@ -621,23 +616,29 @@ static int ib_umad_close(struct inode *inode, struct file *filp) | |||
621 | struct ib_umad_file *file = filp->private_data; | 616 | struct ib_umad_file *file = filp->private_data; |
622 | struct ib_umad_device *dev = file->port->umad_dev; | 617 | struct ib_umad_device *dev = file->port->umad_dev; |
623 | struct ib_umad_packet *packet, *tmp; | 618 | struct ib_umad_packet *packet, *tmp; |
619 | int already_dead; | ||
624 | int i; | 620 | int i; |
625 | 621 | ||
626 | down_write(&file->port->mutex); | 622 | down_write(&file->port->mutex); |
627 | for (i = 0; i < IB_UMAD_MAX_AGENTS; ++i) | 623 | |
628 | if (file->agent[i]) { | 624 | already_dead = file->agents_dead; |
629 | ib_dereg_mr(file->mr[i]); | 625 | file->agents_dead = 1; |
630 | ib_unregister_mad_agent(file->agent[i]); | ||
631 | } | ||
632 | 626 | ||
633 | list_for_each_entry_safe(packet, tmp, &file->recv_list, list) | 627 | list_for_each_entry_safe(packet, tmp, &file->recv_list, list) |
634 | kfree(packet); | 628 | kfree(packet); |
635 | 629 | ||
636 | list_del(&file->port_list); | 630 | list_del(&file->port_list); |
637 | up_write(&file->port->mutex); | ||
638 | 631 | ||
639 | kfree(file); | 632 | downgrade_write(&file->port->mutex); |
633 | |||
634 | if (!already_dead) | ||
635 | for (i = 0; i < IB_UMAD_MAX_AGENTS; ++i) | ||
636 | if (file->agent[i]) | ||
637 | ib_unregister_mad_agent(file->agent[i]); | ||
638 | |||
639 | up_read(&file->port->mutex); | ||
640 | 640 | ||
641 | kfree(file); | ||
641 | kref_put(&dev->ref, ib_umad_release_dev); | 642 | kref_put(&dev->ref, ib_umad_release_dev); |
642 | 643 | ||
643 | return 0; | 644 | return 0; |
@@ -801,7 +802,7 @@ static int ib_umad_init_port(struct ib_device *device, int port_num, | |||
801 | goto err_class; | 802 | goto err_class; |
802 | port->sm_dev->owner = THIS_MODULE; | 803 | port->sm_dev->owner = THIS_MODULE; |
803 | port->sm_dev->ops = &umad_sm_fops; | 804 | port->sm_dev->ops = &umad_sm_fops; |
804 | kobject_set_name(&port->dev->kobj, "issm%d", port->dev_num); | 805 | kobject_set_name(&port->sm_dev->kobj, "issm%d", port->dev_num); |
805 | if (cdev_add(port->sm_dev, base_dev + port->dev_num + IB_UMAD_MAX_PORTS, 1)) | 806 | if (cdev_add(port->sm_dev, base_dev + port->dev_num + IB_UMAD_MAX_PORTS, 1)) |
806 | goto err_sm_cdev; | 807 | goto err_sm_cdev; |
807 | 808 | ||
@@ -863,14 +864,36 @@ static void ib_umad_kill_port(struct ib_umad_port *port) | |||
863 | 864 | ||
864 | port->ib_dev = NULL; | 865 | port->ib_dev = NULL; |
865 | 866 | ||
866 | list_for_each_entry(file, &port->file_list, port_list) | 867 | /* |
867 | for (id = 0; id < IB_UMAD_MAX_AGENTS; ++id) { | 868 | * Now go through the list of files attached to this port and |
868 | if (!file->agent[id]) | 869 | * unregister all of their MAD agents. We need to hold |
869 | continue; | 870 | * port->mutex while doing this to avoid racing with |
870 | ib_dereg_mr(file->mr[id]); | 871 | * ib_umad_close(), but we can't hold the mutex for writing |
871 | ib_unregister_mad_agent(file->agent[id]); | 872 | * while calling ib_unregister_mad_agent(), since that might |
872 | file->agent[id] = NULL; | 873 | * deadlock by calling back into queue_packet(). So we |
873 | } | 874 | * downgrade our lock to a read lock, and then drop and |
875 | * reacquire the write lock for the next iteration. | ||
876 | * | ||
877 | * We do list_del_init() on the file's list_head so that the | ||
878 | * list_del in ib_umad_close() is still OK, even after the | ||
879 | * file is removed from the list. | ||
880 | */ | ||
881 | while (!list_empty(&port->file_list)) { | ||
882 | file = list_entry(port->file_list.next, struct ib_umad_file, | ||
883 | port_list); | ||
884 | |||
885 | file->agents_dead = 1; | ||
886 | list_del_init(&file->port_list); | ||
887 | |||
888 | downgrade_write(&port->mutex); | ||
889 | |||
890 | for (id = 0; id < IB_UMAD_MAX_AGENTS; ++id) | ||
891 | if (file->agent[id]) | ||
892 | ib_unregister_mad_agent(file->agent[id]); | ||
893 | |||
894 | up_read(&port->mutex); | ||
895 | down_write(&port->mutex); | ||
896 | } | ||
874 | 897 | ||
875 | up_write(&port->mutex); | 898 | up_write(&port->mutex); |
876 | 899 | ||
@@ -913,7 +936,7 @@ static void ib_umad_add_one(struct ib_device *device) | |||
913 | 936 | ||
914 | err: | 937 | err: |
915 | while (--i >= s) | 938 | while (--i >= s) |
916 | ib_umad_kill_port(&umad_dev->port[i]); | 939 | ib_umad_kill_port(&umad_dev->port[i - s]); |
917 | 940 | ||
918 | kref_put(&umad_dev->ref, ib_umad_release_dev); | 941 | kref_put(&umad_dev->ref, ib_umad_release_dev); |
919 | } | 942 | } |
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index 63a74151c60b..ed45da892b1c 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c | |||
@@ -708,7 +708,7 @@ ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file, | |||
708 | resp->wc[i].opcode = wc[i].opcode; | 708 | resp->wc[i].opcode = wc[i].opcode; |
709 | resp->wc[i].vendor_err = wc[i].vendor_err; | 709 | resp->wc[i].vendor_err = wc[i].vendor_err; |
710 | resp->wc[i].byte_len = wc[i].byte_len; | 710 | resp->wc[i].byte_len = wc[i].byte_len; |
711 | resp->wc[i].imm_data = wc[i].imm_data; | 711 | resp->wc[i].imm_data = (__u32 __force) wc[i].imm_data; |
712 | resp->wc[i].qp_num = wc[i].qp_num; | 712 | resp->wc[i].qp_num = wc[i].qp_num; |
713 | resp->wc[i].src_qp = wc[i].src_qp; | 713 | resp->wc[i].src_qp = wc[i].src_qp; |
714 | resp->wc[i].wc_flags = wc[i].wc_flags; | 714 | resp->wc[i].wc_flags = wc[i].wc_flags; |
@@ -908,7 +908,12 @@ retry: | |||
908 | if (ret) | 908 | if (ret) |
909 | goto err_destroy; | 909 | goto err_destroy; |
910 | 910 | ||
911 | resp.qp_handle = uobj->uobject.id; | 911 | resp.qp_handle = uobj->uobject.id; |
912 | resp.max_recv_sge = attr.cap.max_recv_sge; | ||
913 | resp.max_send_sge = attr.cap.max_send_sge; | ||
914 | resp.max_recv_wr = attr.cap.max_recv_wr; | ||
915 | resp.max_send_wr = attr.cap.max_send_wr; | ||
916 | resp.max_inline_data = attr.cap.max_inline_data; | ||
912 | 917 | ||
913 | if (copy_to_user((void __user *) (unsigned long) cmd.response, | 918 | if (copy_to_user((void __user *) (unsigned long) cmd.response, |
914 | &resp, sizeof resp)) { | 919 | &resp, sizeof resp)) { |
@@ -1135,7 +1140,7 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file, | |||
1135 | next->num_sge = user_wr->num_sge; | 1140 | next->num_sge = user_wr->num_sge; |
1136 | next->opcode = user_wr->opcode; | 1141 | next->opcode = user_wr->opcode; |
1137 | next->send_flags = user_wr->send_flags; | 1142 | next->send_flags = user_wr->send_flags; |
1138 | next->imm_data = user_wr->imm_data; | 1143 | next->imm_data = (__be32 __force) user_wr->imm_data; |
1139 | 1144 | ||
1140 | if (qp->qp_type == IB_QPT_UD) { | 1145 | if (qp->qp_type == IB_QPT_UD) { |
1141 | next->wr.ud.ah = idr_find(&ib_uverbs_ah_idr, | 1146 | next->wr.ud.ah = idr_find(&ib_uverbs_ah_idr, |
@@ -1701,7 +1706,6 @@ ssize_t ib_uverbs_modify_srq(struct ib_uverbs_file *file, | |||
1701 | } | 1706 | } |
1702 | 1707 | ||
1703 | attr.max_wr = cmd.max_wr; | 1708 | attr.max_wr = cmd.max_wr; |
1704 | attr.max_sge = cmd.max_sge; | ||
1705 | attr.srq_limit = cmd.srq_limit; | 1709 | attr.srq_limit = cmd.srq_limit; |
1706 | 1710 | ||
1707 | ret = ib_modify_srq(srq, &attr, cmd.attr_mask); | 1711 | ret = ib_modify_srq(srq, &attr, cmd.attr_mask); |
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c index 4186cc888ea5..4c15e112736c 100644 --- a/drivers/infiniband/core/verbs.c +++ b/drivers/infiniband/core/verbs.c | |||
@@ -325,16 +325,8 @@ EXPORT_SYMBOL(ib_destroy_cq); | |||
325 | int ib_resize_cq(struct ib_cq *cq, | 325 | int ib_resize_cq(struct ib_cq *cq, |
326 | int cqe) | 326 | int cqe) |
327 | { | 327 | { |
328 | int ret; | 328 | return cq->device->resize_cq ? |
329 | 329 | cq->device->resize_cq(cq, cqe) : -ENOSYS; | |
330 | if (!cq->device->resize_cq) | ||
331 | return -ENOSYS; | ||
332 | |||
333 | ret = cq->device->resize_cq(cq, &cqe); | ||
334 | if (!ret) | ||
335 | cq->cqe = cqe; | ||
336 | |||
337 | return ret; | ||
338 | } | 330 | } |
339 | EXPORT_SYMBOL(ib_resize_cq); | 331 | EXPORT_SYMBOL(ib_resize_cq); |
340 | 332 | ||
diff --git a/drivers/infiniband/hw/mthca/mthca_catas.c b/drivers/infiniband/hw/mthca/mthca_catas.c index 25ebab64bc42..c3bec7490f52 100644 --- a/drivers/infiniband/hw/mthca/mthca_catas.c +++ b/drivers/infiniband/hw/mthca/mthca_catas.c | |||
@@ -97,7 +97,7 @@ static void poll_catas(unsigned long dev_ptr) | |||
97 | } | 97 | } |
98 | 98 | ||
99 | spin_lock_irqsave(&catas_lock, flags); | 99 | spin_lock_irqsave(&catas_lock, flags); |
100 | if (dev->catas_err.stop) | 100 | if (!dev->catas_err.stop) |
101 | mod_timer(&dev->catas_err.timer, | 101 | mod_timer(&dev->catas_err.timer, |
102 | jiffies + MTHCA_CATAS_POLL_INTERVAL); | 102 | jiffies + MTHCA_CATAS_POLL_INTERVAL); |
103 | spin_unlock_irqrestore(&catas_lock, flags); | 103 | spin_unlock_irqrestore(&catas_lock, flags); |
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c index 49f211d55df7..9ed34587fc5c 100644 --- a/drivers/infiniband/hw/mthca/mthca_cmd.c +++ b/drivers/infiniband/hw/mthca/mthca_cmd.c | |||
@@ -1060,6 +1060,8 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev, | |||
1060 | dev_lim->hca.arbel.resize_srq = field & 1; | 1060 | dev_lim->hca.arbel.resize_srq = field & 1; |
1061 | MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_SG_RQ_OFFSET); | 1061 | MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_SG_RQ_OFFSET); |
1062 | dev_lim->max_sg = min_t(int, field, dev_lim->max_sg); | 1062 | dev_lim->max_sg = min_t(int, field, dev_lim->max_sg); |
1063 | MTHCA_GET(size, outbox, QUERY_DEV_LIM_MAX_DESC_SZ_RQ_OFFSET); | ||
1064 | dev_lim->max_desc_sz = min_t(int, size, dev_lim->max_desc_sz); | ||
1063 | MTHCA_GET(size, outbox, QUERY_DEV_LIM_MPT_ENTRY_SZ_OFFSET); | 1065 | MTHCA_GET(size, outbox, QUERY_DEV_LIM_MPT_ENTRY_SZ_OFFSET); |
1064 | dev_lim->mpt_entry_sz = size; | 1066 | dev_lim->mpt_entry_sz = size; |
1065 | MTHCA_GET(field, outbox, QUERY_DEV_LIM_PBL_SZ_OFFSET); | 1067 | MTHCA_GET(field, outbox, QUERY_DEV_LIM_PBL_SZ_OFFSET); |
diff --git a/drivers/infiniband/hw/mthca/mthca_cq.c b/drivers/infiniband/hw/mthca/mthca_cq.c index f98e23555826..4a8adcef2079 100644 --- a/drivers/infiniband/hw/mthca/mthca_cq.c +++ b/drivers/infiniband/hw/mthca/mthca_cq.c | |||
@@ -258,7 +258,7 @@ void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn, | |||
258 | { | 258 | { |
259 | struct mthca_cq *cq; | 259 | struct mthca_cq *cq; |
260 | struct mthca_cqe *cqe; | 260 | struct mthca_cqe *cqe; |
261 | int prod_index; | 261 | u32 prod_index; |
262 | int nfreed = 0; | 262 | int nfreed = 0; |
263 | 263 | ||
264 | spin_lock_irq(&dev->cq_table.lock); | 264 | spin_lock_irq(&dev->cq_table.lock); |
@@ -293,19 +293,15 @@ void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn, | |||
293 | * Now sweep backwards through the CQ, removing CQ entries | 293 | * Now sweep backwards through the CQ, removing CQ entries |
294 | * that match our QP by copying older entries on top of them. | 294 | * that match our QP by copying older entries on top of them. |
295 | */ | 295 | */ |
296 | while (prod_index > cq->cons_index) { | 296 | while ((int) --prod_index - (int) cq->cons_index >= 0) { |
297 | cqe = get_cqe(cq, (prod_index - 1) & cq->ibcq.cqe); | 297 | cqe = get_cqe(cq, prod_index & cq->ibcq.cqe); |
298 | if (cqe->my_qpn == cpu_to_be32(qpn)) { | 298 | if (cqe->my_qpn == cpu_to_be32(qpn)) { |
299 | if (srq) | 299 | if (srq) |
300 | mthca_free_srq_wqe(srq, be32_to_cpu(cqe->wqe)); | 300 | mthca_free_srq_wqe(srq, be32_to_cpu(cqe->wqe)); |
301 | ++nfreed; | 301 | ++nfreed; |
302 | } | 302 | } else if (nfreed) |
303 | else if (nfreed) | 303 | memcpy(get_cqe(cq, (prod_index + nfreed) & cq->ibcq.cqe), |
304 | memcpy(get_cqe(cq, (prod_index - 1 + nfreed) & | 304 | cqe, MTHCA_CQ_ENTRY_SIZE); |
305 | cq->ibcq.cqe), | ||
306 | cqe, | ||
307 | MTHCA_CQ_ENTRY_SIZE); | ||
308 | --prod_index; | ||
309 | } | 305 | } |
310 | 306 | ||
311 | if (nfreed) { | 307 | if (nfreed) { |
diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h index e7e5d3b4f004..497ff794ef6a 100644 --- a/drivers/infiniband/hw/mthca/mthca_dev.h +++ b/drivers/infiniband/hw/mthca/mthca_dev.h | |||
@@ -131,6 +131,7 @@ struct mthca_limits { | |||
131 | int max_sg; | 131 | int max_sg; |
132 | int num_qps; | 132 | int num_qps; |
133 | int max_wqes; | 133 | int max_wqes; |
134 | int max_desc_sz; | ||
134 | int max_qp_init_rdma; | 135 | int max_qp_init_rdma; |
135 | int reserved_qps; | 136 | int reserved_qps; |
136 | int num_srqs; | 137 | int num_srqs; |
@@ -154,6 +155,7 @@ struct mthca_limits { | |||
154 | int reserved_mcgs; | 155 | int reserved_mcgs; |
155 | int num_pds; | 156 | int num_pds; |
156 | int reserved_pds; | 157 | int reserved_pds; |
158 | u32 page_size_cap; | ||
157 | u32 flags; | 159 | u32 flags; |
158 | u8 port_width_cap; | 160 | u8 port_width_cap; |
159 | }; | 161 | }; |
diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c index 45c6328e780c..6f94b25f3acd 100644 --- a/drivers/infiniband/hw/mthca/mthca_main.c +++ b/drivers/infiniband/hw/mthca/mthca_main.c | |||
@@ -168,6 +168,7 @@ static int __devinit mthca_dev_lim(struct mthca_dev *mdev, struct mthca_dev_lim | |||
168 | mdev->limits.max_srq_wqes = dev_lim->max_srq_sz; | 168 | mdev->limits.max_srq_wqes = dev_lim->max_srq_sz; |
169 | mdev->limits.reserved_srqs = dev_lim->reserved_srqs; | 169 | mdev->limits.reserved_srqs = dev_lim->reserved_srqs; |
170 | mdev->limits.reserved_eecs = dev_lim->reserved_eecs; | 170 | mdev->limits.reserved_eecs = dev_lim->reserved_eecs; |
171 | mdev->limits.max_desc_sz = dev_lim->max_desc_sz; | ||
171 | /* | 172 | /* |
172 | * Subtract 1 from the limit because we need to allocate a | 173 | * Subtract 1 from the limit because we need to allocate a |
173 | * spare CQE so the HCA HW can tell the difference between an | 174 | * spare CQE so the HCA HW can tell the difference between an |
@@ -181,6 +182,7 @@ static int __devinit mthca_dev_lim(struct mthca_dev *mdev, struct mthca_dev_lim | |||
181 | mdev->limits.reserved_uars = dev_lim->reserved_uars; | 182 | mdev->limits.reserved_uars = dev_lim->reserved_uars; |
182 | mdev->limits.reserved_pds = dev_lim->reserved_pds; | 183 | mdev->limits.reserved_pds = dev_lim->reserved_pds; |
183 | mdev->limits.port_width_cap = dev_lim->max_port_width; | 184 | mdev->limits.port_width_cap = dev_lim->max_port_width; |
185 | mdev->limits.page_size_cap = ~(u32) (dev_lim->min_page_sz - 1); | ||
184 | mdev->limits.flags = dev_lim->flags; | 186 | mdev->limits.flags = dev_lim->flags; |
185 | 187 | ||
186 | /* IB_DEVICE_RESIZE_MAX_WR not supported by driver. | 188 | /* IB_DEVICE_RESIZE_MAX_WR not supported by driver. |
@@ -1196,7 +1198,6 @@ MODULE_DEVICE_TABLE(pci, mthca_pci_table); | |||
1196 | 1198 | ||
1197 | static struct pci_driver mthca_driver = { | 1199 | static struct pci_driver mthca_driver = { |
1198 | .name = DRV_NAME, | 1200 | .name = DRV_NAME, |
1199 | .owner = THIS_MODULE, | ||
1200 | .id_table = mthca_pci_table, | 1201 | .id_table = mthca_pci_table, |
1201 | .probe = mthca_init_one, | 1202 | .probe = mthca_init_one, |
1202 | .remove = __devexit_p(mthca_remove_one) | 1203 | .remove = __devexit_p(mthca_remove_one) |
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c index 6b0166668269..4cc7e2846df1 100644 --- a/drivers/infiniband/hw/mthca/mthca_provider.c +++ b/drivers/infiniband/hw/mthca/mthca_provider.c | |||
@@ -90,6 +90,7 @@ static int mthca_query_device(struct ib_device *ibdev, | |||
90 | memcpy(&props->node_guid, out_mad->data + 12, 8); | 90 | memcpy(&props->node_guid, out_mad->data + 12, 8); |
91 | 91 | ||
92 | props->max_mr_size = ~0ull; | 92 | props->max_mr_size = ~0ull; |
93 | props->page_size_cap = mdev->limits.page_size_cap; | ||
93 | props->max_qp = mdev->limits.num_qps - mdev->limits.reserved_qps; | 94 | props->max_qp = mdev->limits.num_qps - mdev->limits.reserved_qps; |
94 | props->max_qp_wr = mdev->limits.max_wqes; | 95 | props->max_qp_wr = mdev->limits.max_wqes; |
95 | props->max_sge = mdev->limits.max_sg; | 96 | props->max_sge = mdev->limits.max_sg; |
@@ -615,11 +616,11 @@ static struct ib_qp *mthca_create_qp(struct ib_pd *pd, | |||
615 | return ERR_PTR(err); | 616 | return ERR_PTR(err); |
616 | } | 617 | } |
617 | 618 | ||
618 | init_attr->cap.max_inline_data = 0; | ||
619 | init_attr->cap.max_send_wr = qp->sq.max; | 619 | init_attr->cap.max_send_wr = qp->sq.max; |
620 | init_attr->cap.max_recv_wr = qp->rq.max; | 620 | init_attr->cap.max_recv_wr = qp->rq.max; |
621 | init_attr->cap.max_send_sge = qp->sq.max_gs; | 621 | init_attr->cap.max_send_sge = qp->sq.max_gs; |
622 | init_attr->cap.max_recv_sge = qp->rq.max_gs; | 622 | init_attr->cap.max_recv_sge = qp->rq.max_gs; |
623 | init_attr->cap.max_inline_data = qp->max_inline_data; | ||
623 | 624 | ||
624 | return &qp->ibqp; | 625 | return &qp->ibqp; |
625 | } | 626 | } |
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.h b/drivers/infiniband/hw/mthca/mthca_provider.h index bcd4b01a339c..1e73947b4702 100644 --- a/drivers/infiniband/hw/mthca/mthca_provider.h +++ b/drivers/infiniband/hw/mthca/mthca_provider.h | |||
@@ -251,6 +251,7 @@ struct mthca_qp { | |||
251 | struct mthca_wq sq; | 251 | struct mthca_wq sq; |
252 | enum ib_sig_type sq_policy; | 252 | enum ib_sig_type sq_policy; |
253 | int send_wqe_offset; | 253 | int send_wqe_offset; |
254 | int max_inline_data; | ||
254 | 255 | ||
255 | u64 *wrid; | 256 | u64 *wrid; |
256 | union mthca_buf queue; | 257 | union mthca_buf queue; |
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c index 8852ea477c21..760c418d5bc9 100644 --- a/drivers/infiniband/hw/mthca/mthca_qp.c +++ b/drivers/infiniband/hw/mthca/mthca_qp.c | |||
@@ -885,6 +885,48 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) | |||
885 | return err; | 885 | return err; |
886 | } | 886 | } |
887 | 887 | ||
888 | static void mthca_adjust_qp_caps(struct mthca_dev *dev, | ||
889 | struct mthca_pd *pd, | ||
890 | struct mthca_qp *qp) | ||
891 | { | ||
892 | int max_data_size; | ||
893 | |||
894 | /* | ||
895 | * Calculate the maximum size of WQE s/g segments, excluding | ||
896 | * the next segment and other non-data segments. | ||
897 | */ | ||
898 | max_data_size = min(dev->limits.max_desc_sz, 1 << qp->sq.wqe_shift) - | ||
899 | sizeof (struct mthca_next_seg); | ||
900 | |||
901 | switch (qp->transport) { | ||
902 | case MLX: | ||
903 | max_data_size -= 2 * sizeof (struct mthca_data_seg); | ||
904 | break; | ||
905 | |||
906 | case UD: | ||
907 | if (mthca_is_memfree(dev)) | ||
908 | max_data_size -= sizeof (struct mthca_arbel_ud_seg); | ||
909 | else | ||
910 | max_data_size -= sizeof (struct mthca_tavor_ud_seg); | ||
911 | break; | ||
912 | |||
913 | default: | ||
914 | max_data_size -= sizeof (struct mthca_raddr_seg); | ||
915 | break; | ||
916 | } | ||
917 | |||
918 | /* We don't support inline data for kernel QPs (yet). */ | ||
919 | if (!pd->ibpd.uobject) | ||
920 | qp->max_inline_data = 0; | ||
921 | else | ||
922 | qp->max_inline_data = max_data_size - MTHCA_INLINE_HEADER_SIZE; | ||
923 | |||
924 | qp->sq.max_gs = max_data_size / sizeof (struct mthca_data_seg); | ||
925 | qp->rq.max_gs = (min(dev->limits.max_desc_sz, 1 << qp->rq.wqe_shift) - | ||
926 | sizeof (struct mthca_next_seg)) / | ||
927 | sizeof (struct mthca_data_seg); | ||
928 | } | ||
929 | |||
888 | /* | 930 | /* |
889 | * Allocate and register buffer for WQEs. qp->rq.max, sq.max, | 931 | * Allocate and register buffer for WQEs. qp->rq.max, sq.max, |
890 | * rq.max_gs and sq.max_gs must all be assigned. | 932 | * rq.max_gs and sq.max_gs must all be assigned. |
@@ -902,27 +944,53 @@ static int mthca_alloc_wqe_buf(struct mthca_dev *dev, | |||
902 | size = sizeof (struct mthca_next_seg) + | 944 | size = sizeof (struct mthca_next_seg) + |
903 | qp->rq.max_gs * sizeof (struct mthca_data_seg); | 945 | qp->rq.max_gs * sizeof (struct mthca_data_seg); |
904 | 946 | ||
947 | if (size > dev->limits.max_desc_sz) | ||
948 | return -EINVAL; | ||
949 | |||
905 | for (qp->rq.wqe_shift = 6; 1 << qp->rq.wqe_shift < size; | 950 | for (qp->rq.wqe_shift = 6; 1 << qp->rq.wqe_shift < size; |
906 | qp->rq.wqe_shift++) | 951 | qp->rq.wqe_shift++) |
907 | ; /* nothing */ | 952 | ; /* nothing */ |
908 | 953 | ||
909 | size = sizeof (struct mthca_next_seg) + | 954 | size = qp->sq.max_gs * sizeof (struct mthca_data_seg); |
910 | qp->sq.max_gs * sizeof (struct mthca_data_seg); | ||
911 | switch (qp->transport) { | 955 | switch (qp->transport) { |
912 | case MLX: | 956 | case MLX: |
913 | size += 2 * sizeof (struct mthca_data_seg); | 957 | size += 2 * sizeof (struct mthca_data_seg); |
914 | break; | 958 | break; |
959 | |||
915 | case UD: | 960 | case UD: |
916 | if (mthca_is_memfree(dev)) | 961 | size += mthca_is_memfree(dev) ? |
917 | size += sizeof (struct mthca_arbel_ud_seg); | 962 | sizeof (struct mthca_arbel_ud_seg) : |
918 | else | 963 | sizeof (struct mthca_tavor_ud_seg); |
919 | size += sizeof (struct mthca_tavor_ud_seg); | ||
920 | break; | 964 | break; |
965 | |||
966 | case UC: | ||
967 | size += sizeof (struct mthca_raddr_seg); | ||
968 | break; | ||
969 | |||
970 | case RC: | ||
971 | size += sizeof (struct mthca_raddr_seg); | ||
972 | /* | ||
973 | * An atomic op will require an atomic segment, a | ||
974 | * remote address segment and one scatter entry. | ||
975 | */ | ||
976 | size = max_t(int, size, | ||
977 | sizeof (struct mthca_atomic_seg) + | ||
978 | sizeof (struct mthca_raddr_seg) + | ||
979 | sizeof (struct mthca_data_seg)); | ||
980 | break; | ||
981 | |||
921 | default: | 982 | default: |
922 | /* bind seg is as big as atomic + raddr segs */ | 983 | break; |
923 | size += sizeof (struct mthca_bind_seg); | ||
924 | } | 984 | } |
925 | 985 | ||
986 | /* Make sure that we have enough space for a bind request */ | ||
987 | size = max_t(int, size, sizeof (struct mthca_bind_seg)); | ||
988 | |||
989 | size += sizeof (struct mthca_next_seg); | ||
990 | |||
991 | if (size > dev->limits.max_desc_sz) | ||
992 | return -EINVAL; | ||
993 | |||
926 | for (qp->sq.wqe_shift = 6; 1 << qp->sq.wqe_shift < size; | 994 | for (qp->sq.wqe_shift = 6; 1 << qp->sq.wqe_shift < size; |
927 | qp->sq.wqe_shift++) | 995 | qp->sq.wqe_shift++) |
928 | ; /* nothing */ | 996 | ; /* nothing */ |
@@ -1066,6 +1134,8 @@ static int mthca_alloc_qp_common(struct mthca_dev *dev, | |||
1066 | return ret; | 1134 | return ret; |
1067 | } | 1135 | } |
1068 | 1136 | ||
1137 | mthca_adjust_qp_caps(dev, pd, qp); | ||
1138 | |||
1069 | /* | 1139 | /* |
1070 | * If this is a userspace QP, we're done now. The doorbells | 1140 | * If this is a userspace QP, we're done now. The doorbells |
1071 | * will be allocated and buffers will be initialized in | 1141 | * will be allocated and buffers will be initialized in |
@@ -1486,8 +1556,8 @@ int mthca_tavor_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, | |||
1486 | } | 1556 | } |
1487 | 1557 | ||
1488 | wqe += sizeof (struct mthca_atomic_seg); | 1558 | wqe += sizeof (struct mthca_atomic_seg); |
1489 | size += sizeof (struct mthca_raddr_seg) / 16 + | 1559 | size += (sizeof (struct mthca_raddr_seg) + |
1490 | sizeof (struct mthca_atomic_seg); | 1560 | sizeof (struct mthca_atomic_seg)) / 16; |
1491 | break; | 1561 | break; |
1492 | 1562 | ||
1493 | case IB_WR_RDMA_WRITE: | 1563 | case IB_WR_RDMA_WRITE: |
@@ -1637,6 +1707,7 @@ int mthca_tavor_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr, | |||
1637 | { | 1707 | { |
1638 | struct mthca_dev *dev = to_mdev(ibqp->device); | 1708 | struct mthca_dev *dev = to_mdev(ibqp->device); |
1639 | struct mthca_qp *qp = to_mqp(ibqp); | 1709 | struct mthca_qp *qp = to_mqp(ibqp); |
1710 | __be32 doorbell[2]; | ||
1640 | unsigned long flags; | 1711 | unsigned long flags; |
1641 | int err = 0; | 1712 | int err = 0; |
1642 | int nreq; | 1713 | int nreq; |
@@ -1654,6 +1725,22 @@ int mthca_tavor_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr, | |||
1654 | ind = qp->rq.next_ind; | 1725 | ind = qp->rq.next_ind; |
1655 | 1726 | ||
1656 | for (nreq = 0; wr; ++nreq, wr = wr->next) { | 1727 | for (nreq = 0; wr; ++nreq, wr = wr->next) { |
1728 | if (unlikely(nreq == MTHCA_TAVOR_MAX_WQES_PER_RECV_DB)) { | ||
1729 | nreq = 0; | ||
1730 | |||
1731 | doorbell[0] = cpu_to_be32((qp->rq.next_ind << qp->rq.wqe_shift) | size0); | ||
1732 | doorbell[1] = cpu_to_be32(qp->qpn << 8); | ||
1733 | |||
1734 | wmb(); | ||
1735 | |||
1736 | mthca_write64(doorbell, | ||
1737 | dev->kar + MTHCA_RECEIVE_DOORBELL, | ||
1738 | MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock)); | ||
1739 | |||
1740 | qp->rq.head += MTHCA_TAVOR_MAX_WQES_PER_RECV_DB; | ||
1741 | size0 = 0; | ||
1742 | } | ||
1743 | |||
1657 | if (mthca_wq_overflow(&qp->rq, nreq, qp->ibqp.recv_cq)) { | 1744 | if (mthca_wq_overflow(&qp->rq, nreq, qp->ibqp.recv_cq)) { |
1658 | mthca_err(dev, "RQ %06x full (%u head, %u tail," | 1745 | mthca_err(dev, "RQ %06x full (%u head, %u tail," |
1659 | " %d max, %d nreq)\n", qp->qpn, | 1746 | " %d max, %d nreq)\n", qp->qpn, |
@@ -1711,8 +1798,6 @@ int mthca_tavor_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr, | |||
1711 | 1798 | ||
1712 | out: | 1799 | out: |
1713 | if (likely(nreq)) { | 1800 | if (likely(nreq)) { |
1714 | __be32 doorbell[2]; | ||
1715 | |||
1716 | doorbell[0] = cpu_to_be32((qp->rq.next_ind << qp->rq.wqe_shift) | size0); | 1801 | doorbell[0] = cpu_to_be32((qp->rq.next_ind << qp->rq.wqe_shift) | size0); |
1717 | doorbell[1] = cpu_to_be32((qp->qpn << 8) | nreq); | 1802 | doorbell[1] = cpu_to_be32((qp->qpn << 8) | nreq); |
1718 | 1803 | ||
@@ -1806,8 +1891,8 @@ int mthca_arbel_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, | |||
1806 | } | 1891 | } |
1807 | 1892 | ||
1808 | wqe += sizeof (struct mthca_atomic_seg); | 1893 | wqe += sizeof (struct mthca_atomic_seg); |
1809 | size += sizeof (struct mthca_raddr_seg) / 16 + | 1894 | size += (sizeof (struct mthca_raddr_seg) + |
1810 | sizeof (struct mthca_atomic_seg); | 1895 | sizeof (struct mthca_atomic_seg)) / 16; |
1811 | break; | 1896 | break; |
1812 | 1897 | ||
1813 | case IB_WR_RDMA_READ: | 1898 | case IB_WR_RDMA_READ: |
diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c index 26d5161fde07..f7d234295efe 100644 --- a/drivers/infiniband/hw/mthca/mthca_srq.c +++ b/drivers/infiniband/hw/mthca/mthca_srq.c | |||
@@ -417,6 +417,7 @@ int mthca_tavor_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr, | |||
417 | { | 417 | { |
418 | struct mthca_dev *dev = to_mdev(ibsrq->device); | 418 | struct mthca_dev *dev = to_mdev(ibsrq->device); |
419 | struct mthca_srq *srq = to_msrq(ibsrq); | 419 | struct mthca_srq *srq = to_msrq(ibsrq); |
420 | __be32 doorbell[2]; | ||
420 | unsigned long flags; | 421 | unsigned long flags; |
421 | int err = 0; | 422 | int err = 0; |
422 | int first_ind; | 423 | int first_ind; |
@@ -432,6 +433,25 @@ int mthca_tavor_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr, | |||
432 | first_ind = srq->first_free; | 433 | first_ind = srq->first_free; |
433 | 434 | ||
434 | for (nreq = 0; wr; ++nreq, wr = wr->next) { | 435 | for (nreq = 0; wr; ++nreq, wr = wr->next) { |
436 | if (unlikely(nreq == MTHCA_TAVOR_MAX_WQES_PER_RECV_DB)) { | ||
437 | nreq = 0; | ||
438 | |||
439 | doorbell[0] = cpu_to_be32(first_ind << srq->wqe_shift); | ||
440 | doorbell[1] = cpu_to_be32(srq->srqn << 8); | ||
441 | |||
442 | /* | ||
443 | * Make sure that descriptors are written | ||
444 | * before doorbell is rung. | ||
445 | */ | ||
446 | wmb(); | ||
447 | |||
448 | mthca_write64(doorbell, | ||
449 | dev->kar + MTHCA_RECEIVE_DOORBELL, | ||
450 | MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock)); | ||
451 | |||
452 | first_ind = srq->first_free; | ||
453 | } | ||
454 | |||
435 | ind = srq->first_free; | 455 | ind = srq->first_free; |
436 | 456 | ||
437 | if (ind < 0) { | 457 | if (ind < 0) { |
@@ -494,8 +514,6 @@ int mthca_tavor_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr, | |||
494 | } | 514 | } |
495 | 515 | ||
496 | if (likely(nreq)) { | 516 | if (likely(nreq)) { |
497 | __be32 doorbell[2]; | ||
498 | |||
499 | doorbell[0] = cpu_to_be32(first_ind << srq->wqe_shift); | 517 | doorbell[0] = cpu_to_be32(first_ind << srq->wqe_shift); |
500 | doorbell[1] = cpu_to_be32((srq->srqn << 8) | nreq); | 518 | doorbell[1] = cpu_to_be32((srq->srqn << 8) | nreq); |
501 | 519 | ||
diff --git a/drivers/infiniband/hw/mthca/mthca_wqe.h b/drivers/infiniband/hw/mthca/mthca_wqe.h index 1f4c0ff28f79..73f1c0b9021e 100644 --- a/drivers/infiniband/hw/mthca/mthca_wqe.h +++ b/drivers/infiniband/hw/mthca/mthca_wqe.h | |||
@@ -49,7 +49,8 @@ enum { | |||
49 | }; | 49 | }; |
50 | 50 | ||
51 | enum { | 51 | enum { |
52 | MTHCA_INVAL_LKEY = 0x100 | 52 | MTHCA_INVAL_LKEY = 0x100, |
53 | MTHCA_TAVOR_MAX_WQES_PER_RECV_DB = 256 | ||
53 | }; | 54 | }; |
54 | 55 | ||
55 | struct mthca_next_seg { | 56 | struct mthca_next_seg { |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h index 0095acc0fbbe..9923a15a9996 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/drivers/infiniband/ulp/ipoib/ipoib.h | |||
@@ -179,6 +179,7 @@ struct ipoib_dev_priv { | |||
179 | #ifdef CONFIG_INFINIBAND_IPOIB_DEBUG | 179 | #ifdef CONFIG_INFINIBAND_IPOIB_DEBUG |
180 | struct list_head fs_list; | 180 | struct list_head fs_list; |
181 | struct dentry *mcg_dentry; | 181 | struct dentry *mcg_dentry; |
182 | struct dentry *path_dentry; | ||
182 | #endif | 183 | #endif |
183 | }; | 184 | }; |
184 | 185 | ||
@@ -270,7 +271,6 @@ void ipoib_mcast_dev_flush(struct net_device *dev); | |||
270 | 271 | ||
271 | #ifdef CONFIG_INFINIBAND_IPOIB_DEBUG | 272 | #ifdef CONFIG_INFINIBAND_IPOIB_DEBUG |
272 | struct ipoib_mcast_iter *ipoib_mcast_iter_init(struct net_device *dev); | 273 | struct ipoib_mcast_iter *ipoib_mcast_iter_init(struct net_device *dev); |
273 | void ipoib_mcast_iter_free(struct ipoib_mcast_iter *iter); | ||
274 | int ipoib_mcast_iter_next(struct ipoib_mcast_iter *iter); | 274 | int ipoib_mcast_iter_next(struct ipoib_mcast_iter *iter); |
275 | void ipoib_mcast_iter_read(struct ipoib_mcast_iter *iter, | 275 | void ipoib_mcast_iter_read(struct ipoib_mcast_iter *iter, |
276 | union ib_gid *gid, | 276 | union ib_gid *gid, |
@@ -278,6 +278,11 @@ void ipoib_mcast_iter_read(struct ipoib_mcast_iter *iter, | |||
278 | unsigned int *queuelen, | 278 | unsigned int *queuelen, |
279 | unsigned int *complete, | 279 | unsigned int *complete, |
280 | unsigned int *send_only); | 280 | unsigned int *send_only); |
281 | |||
282 | struct ipoib_path_iter *ipoib_path_iter_init(struct net_device *dev); | ||
283 | int ipoib_path_iter_next(struct ipoib_path_iter *iter); | ||
284 | void ipoib_path_iter_read(struct ipoib_path_iter *iter, | ||
285 | struct ipoib_path *path); | ||
281 | #endif | 286 | #endif |
282 | 287 | ||
283 | int ipoib_mcast_attach(struct net_device *dev, u16 mlid, | 288 | int ipoib_mcast_attach(struct net_device *dev, u16 mlid, |
@@ -299,13 +304,13 @@ void ipoib_pkey_poll(void *dev); | |||
299 | int ipoib_pkey_dev_delay_open(struct net_device *dev); | 304 | int ipoib_pkey_dev_delay_open(struct net_device *dev); |
300 | 305 | ||
301 | #ifdef CONFIG_INFINIBAND_IPOIB_DEBUG | 306 | #ifdef CONFIG_INFINIBAND_IPOIB_DEBUG |
302 | int ipoib_create_debug_file(struct net_device *dev); | 307 | void ipoib_create_debug_files(struct net_device *dev); |
303 | void ipoib_delete_debug_file(struct net_device *dev); | 308 | void ipoib_delete_debug_files(struct net_device *dev); |
304 | int ipoib_register_debugfs(void); | 309 | int ipoib_register_debugfs(void); |
305 | void ipoib_unregister_debugfs(void); | 310 | void ipoib_unregister_debugfs(void); |
306 | #else | 311 | #else |
307 | static inline int ipoib_create_debug_file(struct net_device *dev) { return 0; } | 312 | static inline void ipoib_create_debug_files(struct net_device *dev) { } |
308 | static inline void ipoib_delete_debug_file(struct net_device *dev) { } | 313 | static inline void ipoib_delete_debug_files(struct net_device *dev) { } |
309 | static inline int ipoib_register_debugfs(void) { return 0; } | 314 | static inline int ipoib_register_debugfs(void) { return 0; } |
310 | static inline void ipoib_unregister_debugfs(void) { } | 315 | static inline void ipoib_unregister_debugfs(void) { } |
311 | #endif | 316 | #endif |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_fs.c b/drivers/infiniband/ulp/ipoib/ipoib_fs.c index 38b150f775e7..685258e34034 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_fs.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_fs.c | |||
@@ -43,6 +43,18 @@ struct file_operations; | |||
43 | 43 | ||
44 | static struct dentry *ipoib_root; | 44 | static struct dentry *ipoib_root; |
45 | 45 | ||
46 | static void format_gid(union ib_gid *gid, char *buf) | ||
47 | { | ||
48 | int i, n; | ||
49 | |||
50 | for (n = 0, i = 0; i < 8; ++i) { | ||
51 | n += sprintf(buf + n, "%x", | ||
52 | be16_to_cpu(((__be16 *) gid->raw)[i])); | ||
53 | if (i < 7) | ||
54 | buf[n++] = ':'; | ||
55 | } | ||
56 | } | ||
57 | |||
46 | static void *ipoib_mcg_seq_start(struct seq_file *file, loff_t *pos) | 58 | static void *ipoib_mcg_seq_start(struct seq_file *file, loff_t *pos) |
47 | { | 59 | { |
48 | struct ipoib_mcast_iter *iter; | 60 | struct ipoib_mcast_iter *iter; |
@@ -54,7 +66,7 @@ static void *ipoib_mcg_seq_start(struct seq_file *file, loff_t *pos) | |||
54 | 66 | ||
55 | while (n--) { | 67 | while (n--) { |
56 | if (ipoib_mcast_iter_next(iter)) { | 68 | if (ipoib_mcast_iter_next(iter)) { |
57 | ipoib_mcast_iter_free(iter); | 69 | kfree(iter); |
58 | return NULL; | 70 | return NULL; |
59 | } | 71 | } |
60 | } | 72 | } |
@@ -70,7 +82,7 @@ static void *ipoib_mcg_seq_next(struct seq_file *file, void *iter_ptr, | |||
70 | (*pos)++; | 82 | (*pos)++; |
71 | 83 | ||
72 | if (ipoib_mcast_iter_next(iter)) { | 84 | if (ipoib_mcast_iter_next(iter)) { |
73 | ipoib_mcast_iter_free(iter); | 85 | kfree(iter); |
74 | return NULL; | 86 | return NULL; |
75 | } | 87 | } |
76 | 88 | ||
@@ -87,32 +99,32 @@ static int ipoib_mcg_seq_show(struct seq_file *file, void *iter_ptr) | |||
87 | struct ipoib_mcast_iter *iter = iter_ptr; | 99 | struct ipoib_mcast_iter *iter = iter_ptr; |
88 | char gid_buf[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"]; | 100 | char gid_buf[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"]; |
89 | union ib_gid mgid; | 101 | union ib_gid mgid; |
90 | int i, n; | ||
91 | unsigned long created; | 102 | unsigned long created; |
92 | unsigned int queuelen, complete, send_only; | 103 | unsigned int queuelen, complete, send_only; |
93 | 104 | ||
94 | if (iter) { | 105 | if (!iter) |
95 | ipoib_mcast_iter_read(iter, &mgid, &created, &queuelen, | 106 | return 0; |
96 | &complete, &send_only); | ||
97 | 107 | ||
98 | for (n = 0, i = 0; i < sizeof mgid / 2; ++i) { | 108 | ipoib_mcast_iter_read(iter, &mgid, &created, &queuelen, |
99 | n += sprintf(gid_buf + n, "%x", | 109 | &complete, &send_only); |
100 | be16_to_cpu(((__be16 *) mgid.raw)[i])); | ||
101 | if (i < sizeof mgid / 2 - 1) | ||
102 | gid_buf[n++] = ':'; | ||
103 | } | ||
104 | } | ||
105 | 110 | ||
106 | seq_printf(file, "GID: %*s", -(1 + (int) sizeof gid_buf), gid_buf); | 111 | format_gid(&mgid, gid_buf); |
107 | 112 | ||
108 | seq_printf(file, | 113 | seq_printf(file, |
109 | " created: %10ld queuelen: %4d complete: %d send_only: %d\n", | 114 | "GID: %s\n" |
110 | created, queuelen, complete, send_only); | 115 | " created: %10ld\n" |
116 | " queuelen: %9d\n" | ||
117 | " complete: %9s\n" | ||
118 | " send_only: %8s\n" | ||
119 | "\n", | ||
120 | gid_buf, created, queuelen, | ||
121 | complete ? "yes" : "no", | ||
122 | send_only ? "yes" : "no"); | ||
111 | 123 | ||
112 | return 0; | 124 | return 0; |
113 | } | 125 | } |
114 | 126 | ||
115 | static struct seq_operations ipoib_seq_ops = { | 127 | static struct seq_operations ipoib_mcg_seq_ops = { |
116 | .start = ipoib_mcg_seq_start, | 128 | .start = ipoib_mcg_seq_start, |
117 | .next = ipoib_mcg_seq_next, | 129 | .next = ipoib_mcg_seq_next, |
118 | .stop = ipoib_mcg_seq_stop, | 130 | .stop = ipoib_mcg_seq_stop, |
@@ -124,7 +136,7 @@ static int ipoib_mcg_open(struct inode *inode, struct file *file) | |||
124 | struct seq_file *seq; | 136 | struct seq_file *seq; |
125 | int ret; | 137 | int ret; |
126 | 138 | ||
127 | ret = seq_open(file, &ipoib_seq_ops); | 139 | ret = seq_open(file, &ipoib_mcg_seq_ops); |
128 | if (ret) | 140 | if (ret) |
129 | return ret; | 141 | return ret; |
130 | 142 | ||
@@ -134,7 +146,7 @@ static int ipoib_mcg_open(struct inode *inode, struct file *file) | |||
134 | return 0; | 146 | return 0; |
135 | } | 147 | } |
136 | 148 | ||
137 | static struct file_operations ipoib_fops = { | 149 | static struct file_operations ipoib_mcg_fops = { |
138 | .owner = THIS_MODULE, | 150 | .owner = THIS_MODULE, |
139 | .open = ipoib_mcg_open, | 151 | .open = ipoib_mcg_open, |
140 | .read = seq_read, | 152 | .read = seq_read, |
@@ -142,25 +154,138 @@ static struct file_operations ipoib_fops = { | |||
142 | .release = seq_release | 154 | .release = seq_release |
143 | }; | 155 | }; |
144 | 156 | ||
145 | int ipoib_create_debug_file(struct net_device *dev) | 157 | static void *ipoib_path_seq_start(struct seq_file *file, loff_t *pos) |
158 | { | ||
159 | struct ipoib_path_iter *iter; | ||
160 | loff_t n = *pos; | ||
161 | |||
162 | iter = ipoib_path_iter_init(file->private); | ||
163 | if (!iter) | ||
164 | return NULL; | ||
165 | |||
166 | while (n--) { | ||
167 | if (ipoib_path_iter_next(iter)) { | ||
168 | kfree(iter); | ||
169 | return NULL; | ||
170 | } | ||
171 | } | ||
172 | |||
173 | return iter; | ||
174 | } | ||
175 | |||
176 | static void *ipoib_path_seq_next(struct seq_file *file, void *iter_ptr, | ||
177 | loff_t *pos) | ||
178 | { | ||
179 | struct ipoib_path_iter *iter = iter_ptr; | ||
180 | |||
181 | (*pos)++; | ||
182 | |||
183 | if (ipoib_path_iter_next(iter)) { | ||
184 | kfree(iter); | ||
185 | return NULL; | ||
186 | } | ||
187 | |||
188 | return iter; | ||
189 | } | ||
190 | |||
191 | static void ipoib_path_seq_stop(struct seq_file *file, void *iter_ptr) | ||
192 | { | ||
193 | /* nothing for now */ | ||
194 | } | ||
195 | |||
196 | static int ipoib_path_seq_show(struct seq_file *file, void *iter_ptr) | ||
197 | { | ||
198 | struct ipoib_path_iter *iter = iter_ptr; | ||
199 | char gid_buf[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"]; | ||
200 | struct ipoib_path path; | ||
201 | int rate; | ||
202 | |||
203 | if (!iter) | ||
204 | return 0; | ||
205 | |||
206 | ipoib_path_iter_read(iter, &path); | ||
207 | |||
208 | format_gid(&path.pathrec.dgid, gid_buf); | ||
209 | |||
210 | seq_printf(file, | ||
211 | "GID: %s\n" | ||
212 | " complete: %6s\n", | ||
213 | gid_buf, path.pathrec.dlid ? "yes" : "no"); | ||
214 | |||
215 | if (path.pathrec.dlid) { | ||
216 | rate = ib_sa_rate_enum_to_int(path.pathrec.rate) * 25; | ||
217 | |||
218 | seq_printf(file, | ||
219 | " DLID: 0x%04x\n" | ||
220 | " SL: %12d\n" | ||
221 | " rate: %*d%s Gb/sec\n", | ||
222 | be16_to_cpu(path.pathrec.dlid), | ||
223 | path.pathrec.sl, | ||
224 | 10 - ((rate % 10) ? 2 : 0), | ||
225 | rate / 10, rate % 10 ? ".5" : ""); | ||
226 | } | ||
227 | |||
228 | seq_putc(file, '\n'); | ||
229 | |||
230 | return 0; | ||
231 | } | ||
232 | |||
233 | static struct seq_operations ipoib_path_seq_ops = { | ||
234 | .start = ipoib_path_seq_start, | ||
235 | .next = ipoib_path_seq_next, | ||
236 | .stop = ipoib_path_seq_stop, | ||
237 | .show = ipoib_path_seq_show, | ||
238 | }; | ||
239 | |||
240 | static int ipoib_path_open(struct inode *inode, struct file *file) | ||
241 | { | ||
242 | struct seq_file *seq; | ||
243 | int ret; | ||
244 | |||
245 | ret = seq_open(file, &ipoib_path_seq_ops); | ||
246 | if (ret) | ||
247 | return ret; | ||
248 | |||
249 | seq = file->private_data; | ||
250 | seq->private = inode->u.generic_ip; | ||
251 | |||
252 | return 0; | ||
253 | } | ||
254 | |||
255 | static struct file_operations ipoib_path_fops = { | ||
256 | .owner = THIS_MODULE, | ||
257 | .open = ipoib_path_open, | ||
258 | .read = seq_read, | ||
259 | .llseek = seq_lseek, | ||
260 | .release = seq_release | ||
261 | }; | ||
262 | |||
263 | void ipoib_create_debug_files(struct net_device *dev) | ||
146 | { | 264 | { |
147 | struct ipoib_dev_priv *priv = netdev_priv(dev); | 265 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
148 | char name[IFNAMSIZ + sizeof "_mcg"]; | 266 | char name[IFNAMSIZ + sizeof "_path"]; |
149 | 267 | ||
150 | snprintf(name, sizeof name, "%s_mcg", dev->name); | 268 | snprintf(name, sizeof name, "%s_mcg", dev->name); |
151 | |||
152 | priv->mcg_dentry = debugfs_create_file(name, S_IFREG | S_IRUGO, | 269 | priv->mcg_dentry = debugfs_create_file(name, S_IFREG | S_IRUGO, |
153 | ipoib_root, dev, &ipoib_fops); | 270 | ipoib_root, dev, &ipoib_mcg_fops); |
154 | 271 | if (!priv->mcg_dentry) | |
155 | return priv->mcg_dentry ? 0 : -ENOMEM; | 272 | ipoib_warn(priv, "failed to create mcg debug file\n"); |
273 | |||
274 | snprintf(name, sizeof name, "%s_path", dev->name); | ||
275 | priv->path_dentry = debugfs_create_file(name, S_IFREG | S_IRUGO, | ||
276 | ipoib_root, dev, &ipoib_path_fops); | ||
277 | if (!priv->path_dentry) | ||
278 | ipoib_warn(priv, "failed to create path debug file\n"); | ||
156 | } | 279 | } |
157 | 280 | ||
158 | void ipoib_delete_debug_file(struct net_device *dev) | 281 | void ipoib_delete_debug_files(struct net_device *dev) |
159 | { | 282 | { |
160 | struct ipoib_dev_priv *priv = netdev_priv(dev); | 283 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
161 | 284 | ||
162 | if (priv->mcg_dentry) | 285 | if (priv->mcg_dentry) |
163 | debugfs_remove(priv->mcg_dentry); | 286 | debugfs_remove(priv->mcg_dentry); |
287 | if (priv->path_dentry) | ||
288 | debugfs_remove(priv->path_dentry); | ||
164 | } | 289 | } |
165 | 290 | ||
166 | int ipoib_register_debugfs(void) | 291 | int ipoib_register_debugfs(void) |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index ce0296273e76..2fa30751f362 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c | |||
@@ -58,6 +58,11 @@ module_param_named(debug_level, ipoib_debug_level, int, 0644); | |||
58 | MODULE_PARM_DESC(debug_level, "Enable debug tracing if > 0"); | 58 | MODULE_PARM_DESC(debug_level, "Enable debug tracing if > 0"); |
59 | #endif | 59 | #endif |
60 | 60 | ||
61 | struct ipoib_path_iter { | ||
62 | struct net_device *dev; | ||
63 | struct ipoib_path path; | ||
64 | }; | ||
65 | |||
61 | static const u8 ipv4_bcast_addr[] = { | 66 | static const u8 ipv4_bcast_addr[] = { |
62 | 0x00, 0xff, 0xff, 0xff, | 67 | 0x00, 0xff, 0xff, 0xff, |
63 | 0xff, 0x12, 0x40, 0x1b, 0x00, 0x00, 0x00, 0x00, | 68 | 0xff, 0x12, 0x40, 0x1b, 0x00, 0x00, 0x00, 0x00, |
@@ -250,6 +255,64 @@ static void path_free(struct net_device *dev, struct ipoib_path *path) | |||
250 | kfree(path); | 255 | kfree(path); |
251 | } | 256 | } |
252 | 257 | ||
258 | #ifdef CONFIG_INFINIBAND_IPOIB_DEBUG | ||
259 | |||
260 | struct ipoib_path_iter *ipoib_path_iter_init(struct net_device *dev) | ||
261 | { | ||
262 | struct ipoib_path_iter *iter; | ||
263 | |||
264 | iter = kmalloc(sizeof *iter, GFP_KERNEL); | ||
265 | if (!iter) | ||
266 | return NULL; | ||
267 | |||
268 | iter->dev = dev; | ||
269 | memset(iter->path.pathrec.dgid.raw, 0, 16); | ||
270 | |||
271 | if (ipoib_path_iter_next(iter)) { | ||
272 | kfree(iter); | ||
273 | return NULL; | ||
274 | } | ||
275 | |||
276 | return iter; | ||
277 | } | ||
278 | |||
279 | int ipoib_path_iter_next(struct ipoib_path_iter *iter) | ||
280 | { | ||
281 | struct ipoib_dev_priv *priv = netdev_priv(iter->dev); | ||
282 | struct rb_node *n; | ||
283 | struct ipoib_path *path; | ||
284 | int ret = 1; | ||
285 | |||
286 | spin_lock_irq(&priv->lock); | ||
287 | |||
288 | n = rb_first(&priv->path_tree); | ||
289 | |||
290 | while (n) { | ||
291 | path = rb_entry(n, struct ipoib_path, rb_node); | ||
292 | |||
293 | if (memcmp(iter->path.pathrec.dgid.raw, path->pathrec.dgid.raw, | ||
294 | sizeof (union ib_gid)) < 0) { | ||
295 | iter->path = *path; | ||
296 | ret = 0; | ||
297 | break; | ||
298 | } | ||
299 | |||
300 | n = rb_next(n); | ||
301 | } | ||
302 | |||
303 | spin_unlock_irq(&priv->lock); | ||
304 | |||
305 | return ret; | ||
306 | } | ||
307 | |||
308 | void ipoib_path_iter_read(struct ipoib_path_iter *iter, | ||
309 | struct ipoib_path *path) | ||
310 | { | ||
311 | *path = iter->path; | ||
312 | } | ||
313 | |||
314 | #endif /* CONFIG_INFINIBAND_IPOIB_DEBUG */ | ||
315 | |||
253 | void ipoib_flush_paths(struct net_device *dev) | 316 | void ipoib_flush_paths(struct net_device *dev) |
254 | { | 317 | { |
255 | struct ipoib_dev_priv *priv = netdev_priv(dev); | 318 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
@@ -763,7 +826,7 @@ void ipoib_dev_cleanup(struct net_device *dev) | |||
763 | { | 826 | { |
764 | struct ipoib_dev_priv *priv = netdev_priv(dev), *cpriv, *tcpriv; | 827 | struct ipoib_dev_priv *priv = netdev_priv(dev), *cpriv, *tcpriv; |
765 | 828 | ||
766 | ipoib_delete_debug_file(dev); | 829 | ipoib_delete_debug_files(dev); |
767 | 830 | ||
768 | /* Delete any child interfaces first */ | 831 | /* Delete any child interfaces first */ |
769 | list_for_each_entry_safe(cpriv, tcpriv, &priv->child_intfs, list) { | 832 | list_for_each_entry_safe(cpriv, tcpriv, &priv->child_intfs, list) { |
@@ -972,8 +1035,7 @@ static struct net_device *ipoib_add_port(const char *format, | |||
972 | goto register_failed; | 1035 | goto register_failed; |
973 | } | 1036 | } |
974 | 1037 | ||
975 | if (ipoib_create_debug_file(priv->dev)) | 1038 | ipoib_create_debug_files(priv->dev); |
976 | goto debug_failed; | ||
977 | 1039 | ||
978 | if (ipoib_add_pkey_attr(priv->dev)) | 1040 | if (ipoib_add_pkey_attr(priv->dev)) |
979 | goto sysfs_failed; | 1041 | goto sysfs_failed; |
@@ -987,9 +1049,7 @@ static struct net_device *ipoib_add_port(const char *format, | |||
987 | return priv->dev; | 1049 | return priv->dev; |
988 | 1050 | ||
989 | sysfs_failed: | 1051 | sysfs_failed: |
990 | ipoib_delete_debug_file(priv->dev); | 1052 | ipoib_delete_debug_files(priv->dev); |
991 | |||
992 | debug_failed: | ||
993 | unregister_netdev(priv->dev); | 1053 | unregister_netdev(priv->dev); |
994 | 1054 | ||
995 | register_failed: | 1055 | register_failed: |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index 3ecf78a9493a..c33ed87f9dff 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c | |||
@@ -120,12 +120,8 @@ static void ipoib_mcast_free(struct ipoib_mcast *mcast) | |||
120 | if (mcast->ah) | 120 | if (mcast->ah) |
121 | ipoib_put_ah(mcast->ah); | 121 | ipoib_put_ah(mcast->ah); |
122 | 122 | ||
123 | while (!skb_queue_empty(&mcast->pkt_queue)) { | 123 | while (!skb_queue_empty(&mcast->pkt_queue)) |
124 | struct sk_buff *skb = skb_dequeue(&mcast->pkt_queue); | 124 | dev_kfree_skb_any(skb_dequeue(&mcast->pkt_queue)); |
125 | |||
126 | skb->dev = dev; | ||
127 | dev_kfree_skb_any(skb); | ||
128 | } | ||
129 | 125 | ||
130 | kfree(mcast); | 126 | kfree(mcast); |
131 | } | 127 | } |
@@ -317,13 +313,8 @@ ipoib_mcast_sendonly_join_complete(int status, | |||
317 | IPOIB_GID_ARG(mcast->mcmember.mgid), status); | 313 | IPOIB_GID_ARG(mcast->mcmember.mgid), status); |
318 | 314 | ||
319 | /* Flush out any queued packets */ | 315 | /* Flush out any queued packets */ |
320 | while (!skb_queue_empty(&mcast->pkt_queue)) { | 316 | while (!skb_queue_empty(&mcast->pkt_queue)) |
321 | struct sk_buff *skb = skb_dequeue(&mcast->pkt_queue); | 317 | dev_kfree_skb_any(skb_dequeue(&mcast->pkt_queue)); |
322 | |||
323 | skb->dev = dev; | ||
324 | |||
325 | dev_kfree_skb_any(skb); | ||
326 | } | ||
327 | 318 | ||
328 | /* Clear the busy flag so we try again */ | 319 | /* Clear the busy flag so we try again */ |
329 | clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags); | 320 | clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags); |
@@ -928,21 +919,16 @@ struct ipoib_mcast_iter *ipoib_mcast_iter_init(struct net_device *dev) | |||
928 | return NULL; | 919 | return NULL; |
929 | 920 | ||
930 | iter->dev = dev; | 921 | iter->dev = dev; |
931 | memset(iter->mgid.raw, 0, sizeof iter->mgid); | 922 | memset(iter->mgid.raw, 0, 16); |
932 | 923 | ||
933 | if (ipoib_mcast_iter_next(iter)) { | 924 | if (ipoib_mcast_iter_next(iter)) { |
934 | ipoib_mcast_iter_free(iter); | 925 | kfree(iter); |
935 | return NULL; | 926 | return NULL; |
936 | } | 927 | } |
937 | 928 | ||
938 | return iter; | 929 | return iter; |
939 | } | 930 | } |
940 | 931 | ||
941 | void ipoib_mcast_iter_free(struct ipoib_mcast_iter *iter) | ||
942 | { | ||
943 | kfree(iter); | ||
944 | } | ||
945 | |||
946 | int ipoib_mcast_iter_next(struct ipoib_mcast_iter *iter) | 932 | int ipoib_mcast_iter_next(struct ipoib_mcast_iter *iter) |
947 | { | 933 | { |
948 | struct ipoib_dev_priv *priv = netdev_priv(iter->dev); | 934 | struct ipoib_dev_priv *priv = netdev_priv(iter->dev); |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c index 332d730e60c2..d280b341a37f 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c | |||
@@ -113,8 +113,7 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey) | |||
113 | 113 | ||
114 | priv->parent = ppriv->dev; | 114 | priv->parent = ppriv->dev; |
115 | 115 | ||
116 | if (ipoib_create_debug_file(priv->dev)) | 116 | ipoib_create_debug_files(priv->dev); |
117 | goto debug_failed; | ||
118 | 117 | ||
119 | if (ipoib_add_pkey_attr(priv->dev)) | 118 | if (ipoib_add_pkey_attr(priv->dev)) |
120 | goto sysfs_failed; | 119 | goto sysfs_failed; |
@@ -130,9 +129,7 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey) | |||
130 | return 0; | 129 | return 0; |
131 | 130 | ||
132 | sysfs_failed: | 131 | sysfs_failed: |
133 | ipoib_delete_debug_file(priv->dev); | 132 | ipoib_delete_debug_files(priv->dev); |
134 | |||
135 | debug_failed: | ||
136 | unregister_netdev(priv->dev); | 133 | unregister_netdev(priv->dev); |
137 | 134 | ||
138 | register_failed: | 135 | register_failed: |
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 8f464271664d..49fa1e4413fa 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c | |||
@@ -2707,7 +2707,7 @@ bnx2_init_nvram(struct bnx2 *bp) | |||
2707 | 2707 | ||
2708 | if (j == entry_count) { | 2708 | if (j == entry_count) { |
2709 | bp->flash_info = NULL; | 2709 | bp->flash_info = NULL; |
2710 | printk(KERN_ALERT "Unknown flash/EEPROM type.\n"); | 2710 | printk(KERN_ALERT PFX "Unknown flash/EEPROM type.\n"); |
2711 | rc = -ENODEV; | 2711 | rc = -ENODEV; |
2712 | } | 2712 | } |
2713 | 2713 | ||
@@ -3903,6 +3903,8 @@ bnx2_test_loopback(struct bnx2 *bp) | |||
3903 | 3903 | ||
3904 | pkt_size = 1514; | 3904 | pkt_size = 1514; |
3905 | skb = dev_alloc_skb(pkt_size); | 3905 | skb = dev_alloc_skb(pkt_size); |
3906 | if (!skb) | ||
3907 | return -ENOMEM; | ||
3906 | packet = skb_put(skb, pkt_size); | 3908 | packet = skb_put(skb, pkt_size); |
3907 | memcpy(packet, bp->mac_addr, 6); | 3909 | memcpy(packet, bp->mac_addr, 6); |
3908 | memset(packet + 6, 0x0, 8); | 3910 | memset(packet + 6, 0x0, 8); |
@@ -4798,11 +4800,7 @@ bnx2_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, | |||
4798 | struct bnx2 *bp = dev->priv; | 4800 | struct bnx2 *bp = dev->priv; |
4799 | int rc; | 4801 | int rc; |
4800 | 4802 | ||
4801 | if (eeprom->offset > bp->flash_info->total_size) | 4803 | /* parameters already validated in ethtool_get_eeprom */ |
4802 | return -EINVAL; | ||
4803 | |||
4804 | if ((eeprom->offset + eeprom->len) > bp->flash_info->total_size) | ||
4805 | eeprom->len = bp->flash_info->total_size - eeprom->offset; | ||
4806 | 4804 | ||
4807 | rc = bnx2_nvram_read(bp, eeprom->offset, eebuf, eeprom->len); | 4805 | rc = bnx2_nvram_read(bp, eeprom->offset, eebuf, eeprom->len); |
4808 | 4806 | ||
@@ -4816,11 +4814,7 @@ bnx2_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, | |||
4816 | struct bnx2 *bp = dev->priv; | 4814 | struct bnx2 *bp = dev->priv; |
4817 | int rc; | 4815 | int rc; |
4818 | 4816 | ||
4819 | if (eeprom->offset > bp->flash_info->total_size) | 4817 | /* parameters already validated in ethtool_set_eeprom */ |
4820 | return -EINVAL; | ||
4821 | |||
4822 | if ((eeprom->offset + eeprom->len) > bp->flash_info->total_size) | ||
4823 | eeprom->len = bp->flash_info->total_size - eeprom->offset; | ||
4824 | 4818 | ||
4825 | rc = bnx2_nvram_write(bp, eeprom->offset, eebuf, eeprom->len); | 4819 | rc = bnx2_nvram_write(bp, eeprom->offset, eebuf, eeprom->len); |
4826 | 4820 | ||
diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c index 9342d5bc7bb4..f5d49a110654 100644 --- a/drivers/net/fs_enet/fs_enet-main.c +++ b/drivers/net/fs_enet/fs_enet-main.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/ethtool.h> | 37 | #include <linux/ethtool.h> |
38 | #include <linux/bitops.h> | 38 | #include <linux/bitops.h> |
39 | #include <linux/fs.h> | 39 | #include <linux/fs.h> |
40 | #include <linux/platform_device.h> | ||
40 | 41 | ||
41 | #include <linux/vmalloc.h> | 42 | #include <linux/vmalloc.h> |
42 | #include <asm/pgtable.h> | 43 | #include <asm/pgtable.h> |
diff --git a/drivers/net/fs_enet/mac-fcc.c b/drivers/net/fs_enet/mac-fcc.c index a940b96433c7..e67b1d06611c 100644 --- a/drivers/net/fs_enet/mac-fcc.c +++ b/drivers/net/fs_enet/mac-fcc.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/ethtool.h> | 34 | #include <linux/ethtool.h> |
35 | #include <linux/bitops.h> | 35 | #include <linux/bitops.h> |
36 | #include <linux/fs.h> | 36 | #include <linux/fs.h> |
37 | #include <linux/platform_device.h> | ||
37 | 38 | ||
38 | #include <asm/immap_cpm2.h> | 39 | #include <asm/immap_cpm2.h> |
39 | #include <asm/mpc8260.h> | 40 | #include <asm/mpc8260.h> |
diff --git a/drivers/net/fs_enet/mac-fec.c b/drivers/net/fs_enet/mac-fec.c index 5ef4e845a387..2e8f44469699 100644 --- a/drivers/net/fs_enet/mac-fec.c +++ b/drivers/net/fs_enet/mac-fec.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/ethtool.h> | 34 | #include <linux/ethtool.h> |
35 | #include <linux/bitops.h> | 35 | #include <linux/bitops.h> |
36 | #include <linux/fs.h> | 36 | #include <linux/fs.h> |
37 | #include <linux/platform_device.h> | ||
37 | 38 | ||
38 | #include <asm/irq.h> | 39 | #include <asm/irq.h> |
39 | #include <asm/uaccess.h> | 40 | #include <asm/uaccess.h> |
diff --git a/drivers/net/fs_enet/mac-scc.c b/drivers/net/fs_enet/mac-scc.c index d8c6e9cadcf5..a3897fda71fa 100644 --- a/drivers/net/fs_enet/mac-scc.c +++ b/drivers/net/fs_enet/mac-scc.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/ethtool.h> | 34 | #include <linux/ethtool.h> |
35 | #include <linux/bitops.h> | 35 | #include <linux/bitops.h> |
36 | #include <linux/fs.h> | 36 | #include <linux/fs.h> |
37 | #include <linux/platform_device.h> | ||
37 | 38 | ||
38 | #include <asm/irq.h> | 39 | #include <asm/irq.h> |
39 | #include <asm/uaccess.h> | 40 | #include <asm/uaccess.h> |
diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c index c796f41b4a52..0d765f1733b5 100644 --- a/drivers/net/spider_net.c +++ b/drivers/net/spider_net.c | |||
@@ -2290,7 +2290,6 @@ spider_net_remove(struct pci_dev *pdev) | |||
2290 | } | 2290 | } |
2291 | 2291 | ||
2292 | static struct pci_driver spider_net_driver = { | 2292 | static struct pci_driver spider_net_driver = { |
2293 | .owner = THIS_MODULE, | ||
2294 | .name = spider_net_driver_name, | 2293 | .name = spider_net_driver_name, |
2295 | .id_table = spider_net_pci_tbl, | 2294 | .id_table = spider_net_pci_tbl, |
2296 | .probe = spider_net_probe, | 2295 | .probe = spider_net_probe, |
diff --git a/drivers/pci/access.c b/drivers/pci/access.c index 2a42add7f563..ea16805a153c 100644 --- a/drivers/pci/access.c +++ b/drivers/pci/access.c | |||
@@ -2,6 +2,8 @@ | |||
2 | #include <linux/module.h> | 2 | #include <linux/module.h> |
3 | #include <linux/ioport.h> | 3 | #include <linux/ioport.h> |
4 | 4 | ||
5 | #include "pci.h" | ||
6 | |||
5 | /* | 7 | /* |
6 | * This interrupt-safe spinlock protects all accesses to PCI | 8 | * This interrupt-safe spinlock protects all accesses to PCI |
7 | * configuration space. | 9 | * configuration space. |
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 061ead21ef14..c42b68d3aa24 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h | |||
@@ -32,8 +32,6 @@ | |||
32 | #include <linux/types.h> | 32 | #include <linux/types.h> |
33 | #include <linux/pci.h> | 33 | #include <linux/pci.h> |
34 | #include <linux/delay.h> | 34 | #include <linux/delay.h> |
35 | #include <asm/semaphore.h> | ||
36 | #include <asm/io.h> | ||
37 | #include <linux/pcieport_if.h> | 35 | #include <linux/pcieport_if.h> |
38 | #include "pci_hotplug.h" | 36 | #include "pci_hotplug.h" |
39 | 37 | ||
@@ -42,6 +40,7 @@ | |||
42 | extern int pciehp_poll_mode; | 40 | extern int pciehp_poll_mode; |
43 | extern int pciehp_poll_time; | 41 | extern int pciehp_poll_time; |
44 | extern int pciehp_debug; | 42 | extern int pciehp_debug; |
43 | extern int pciehp_force; | ||
45 | 44 | ||
46 | /*#define dbg(format, arg...) do { if (pciehp_debug) printk(KERN_DEBUG "%s: " format, MY_NAME , ## arg); } while (0)*/ | 45 | /*#define dbg(format, arg...) do { if (pciehp_debug) printk(KERN_DEBUG "%s: " format, MY_NAME , ## arg); } while (0)*/ |
47 | #define dbg(format, arg...) do { if (pciehp_debug) printk("%s: " format, MY_NAME , ## arg); } while (0) | 46 | #define dbg(format, arg...) do { if (pciehp_debug) printk("%s: " format, MY_NAME , ## arg); } while (0) |
@@ -49,39 +48,20 @@ extern int pciehp_debug; | |||
49 | #define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg) | 48 | #define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg) |
50 | #define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg) | 49 | #define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg) |
51 | 50 | ||
52 | struct pci_func { | 51 | struct hotplug_params { |
53 | struct pci_func *next; | 52 | u8 cache_line_size; |
54 | u8 bus; | 53 | u8 latency_timer; |
55 | u8 device; | 54 | u8 enable_serr; |
56 | u8 function; | 55 | u8 enable_perr; |
57 | u8 is_a_board; | ||
58 | u16 status; | ||
59 | u8 configured; | ||
60 | u8 switch_save; | ||
61 | u8 presence_save; | ||
62 | u32 base_length[0x06]; | ||
63 | u8 base_type[0x06]; | ||
64 | u16 reserved2; | ||
65 | u32 config_space[0x20]; | ||
66 | struct pci_resource *mem_head; | ||
67 | struct pci_resource *p_mem_head; | ||
68 | struct pci_resource *io_head; | ||
69 | struct pci_resource *bus_head; | ||
70 | struct pci_dev* pci_dev; | ||
71 | }; | 56 | }; |
72 | 57 | ||
73 | struct slot { | 58 | struct slot { |
74 | struct slot *next; | 59 | struct slot *next; |
75 | u8 bus; | 60 | u8 bus; |
76 | u8 device; | 61 | u8 device; |
62 | u16 status; | ||
77 | u32 number; | 63 | u32 number; |
78 | u8 is_a_board; | ||
79 | u8 configured; | ||
80 | u8 state; | 64 | u8 state; |
81 | u8 switch_save; | ||
82 | u8 presence_save; | ||
83 | u32 capabilities; | ||
84 | u16 reserved2; | ||
85 | struct timer_list task_event; | 65 | struct timer_list task_event; |
86 | u8 hp_slot; | 66 | u8 hp_slot; |
87 | struct controller *ctrl; | 67 | struct controller *ctrl; |
@@ -90,42 +70,47 @@ struct slot { | |||
90 | struct list_head slot_list; | 70 | struct list_head slot_list; |
91 | }; | 71 | }; |
92 | 72 | ||
93 | struct pci_resource { | ||
94 | struct pci_resource * next; | ||
95 | u32 base; | ||
96 | u32 length; | ||
97 | }; | ||
98 | |||
99 | struct event_info { | 73 | struct event_info { |
100 | u32 event_type; | 74 | u32 event_type; |
101 | u8 hp_slot; | 75 | u8 hp_slot; |
102 | }; | 76 | }; |
103 | 77 | ||
78 | typedef u8(*php_intr_callback_t) (u8 hp_slot, void *instance_id); | ||
79 | |||
80 | struct php_ctlr_state_s { | ||
81 | struct php_ctlr_state_s *pnext; | ||
82 | struct pci_dev *pci_dev; | ||
83 | unsigned int irq; | ||
84 | unsigned long flags; /* spinlock's */ | ||
85 | u32 slot_device_offset; | ||
86 | u32 num_slots; | ||
87 | struct timer_list int_poll_timer; /* Added for poll event */ | ||
88 | php_intr_callback_t attention_button_callback; | ||
89 | php_intr_callback_t switch_change_callback; | ||
90 | php_intr_callback_t presence_change_callback; | ||
91 | php_intr_callback_t power_fault_callback; | ||
92 | void *callback_instance_id; | ||
93 | struct ctrl_reg *creg; /* Ptr to controller register space */ | ||
94 | }; | ||
95 | |||
96 | #define MAX_EVENTS 10 | ||
104 | struct controller { | 97 | struct controller { |
105 | struct controller *next; | 98 | struct controller *next; |
106 | struct semaphore crit_sect; /* critical section semaphore */ | 99 | struct semaphore crit_sect; /* critical section semaphore */ |
107 | void *hpc_ctlr_handle; /* HPC controller handle */ | 100 | struct php_ctlr_state_s *hpc_ctlr_handle; /* HPC controller handle */ |
108 | int num_slots; /* Number of slots on ctlr */ | 101 | int num_slots; /* Number of slots on ctlr */ |
109 | int slot_num_inc; /* 1 or -1 */ | 102 | int slot_num_inc; /* 1 or -1 */ |
110 | struct pci_resource *mem_head; | ||
111 | struct pci_resource *p_mem_head; | ||
112 | struct pci_resource *io_head; | ||
113 | struct pci_resource *bus_head; | ||
114 | struct pci_dev *pci_dev; | 103 | struct pci_dev *pci_dev; |
115 | struct pci_bus *pci_bus; | 104 | struct pci_bus *pci_bus; |
116 | struct event_info event_queue[10]; | 105 | struct event_info event_queue[MAX_EVENTS]; |
117 | struct slot *slot; | 106 | struct slot *slot; |
118 | struct hpc_ops *hpc_ops; | 107 | struct hpc_ops *hpc_ops; |
119 | wait_queue_head_t queue; /* sleep & wake process */ | 108 | wait_queue_head_t queue; /* sleep & wake process */ |
120 | u8 next_event; | 109 | u8 next_event; |
121 | u8 seg; | ||
122 | u8 bus; | 110 | u8 bus; |
123 | u8 device; | 111 | u8 device; |
124 | u8 function; | 112 | u8 function; |
125 | u8 rev; | ||
126 | u8 slot_device_offset; | 113 | u8 slot_device_offset; |
127 | u8 add_support; | ||
128 | enum pci_bus_speed speed; | ||
129 | u32 first_slot; /* First physical slot number */ /* PCIE only has 1 slot */ | 114 | u32 first_slot; /* First physical slot number */ /* PCIE only has 1 slot */ |
130 | u8 slot_bus; /* Bus where the slots handled by this controller sit */ | 115 | u8 slot_bus; /* Bus where the slots handled by this controller sit */ |
131 | u8 ctrlcap; | 116 | u8 ctrlcap; |
@@ -133,20 +118,6 @@ struct controller { | |||
133 | u8 cap_base; | 118 | u8 cap_base; |
134 | }; | 119 | }; |
135 | 120 | ||
136 | struct irq_mapping { | ||
137 | u8 barber_pole; | ||
138 | u8 valid_INT; | ||
139 | u8 interrupt[4]; | ||
140 | }; | ||
141 | |||
142 | struct resource_lists { | ||
143 | struct pci_resource *mem_head; | ||
144 | struct pci_resource *p_mem_head; | ||
145 | struct pci_resource *io_head; | ||
146 | struct pci_resource *bus_head; | ||
147 | struct irq_mapping *irqs; | ||
148 | }; | ||
149 | |||
150 | #define INT_BUTTON_IGNORE 0 | 121 | #define INT_BUTTON_IGNORE 0 |
151 | #define INT_PRESENCE_ON 1 | 122 | #define INT_PRESENCE_ON 1 |
152 | #define INT_PRESENCE_OFF 2 | 123 | #define INT_PRESENCE_OFF 2 |
@@ -200,21 +171,14 @@ struct resource_lists { | |||
200 | * error Messages | 171 | * error Messages |
201 | */ | 172 | */ |
202 | #define msg_initialization_err "Initialization failure, error=%d\n" | 173 | #define msg_initialization_err "Initialization failure, error=%d\n" |
203 | #define msg_HPC_rev_error "Unsupported revision of the PCI hot plug controller found.\n" | ||
204 | #define msg_HPC_non_pcie "The PCI hot plug controller is not supported by this driver.\n" | ||
205 | #define msg_HPC_not_supported "This system is not supported by this version of pciephd module. Upgrade to a newer version of pciehpd\n" | ||
206 | #define msg_unable_to_save "Unable to store PCI hot plug add resource information. This system must be rebooted before adding any PCI devices.\n" | ||
207 | #define msg_button_on "PCI slot #%d - powering on due to button press.\n" | 174 | #define msg_button_on "PCI slot #%d - powering on due to button press.\n" |
208 | #define msg_button_off "PCI slot #%d - powering off due to button press.\n" | 175 | #define msg_button_off "PCI slot #%d - powering off due to button press.\n" |
209 | #define msg_button_cancel "PCI slot #%d - action canceled due to button press.\n" | 176 | #define msg_button_cancel "PCI slot #%d - action canceled due to button press.\n" |
210 | #define msg_button_ignore "PCI slot #%d - button press ignored. (action in progress...)\n" | 177 | #define msg_button_ignore "PCI slot #%d - button press ignored. (action in progress...)\n" |
211 | 178 | ||
212 | /* controller functions */ | 179 | /* controller functions */ |
213 | extern int pciehprm_find_available_resources (struct controller *ctrl); | ||
214 | extern int pciehp_event_start_thread (void); | 180 | extern int pciehp_event_start_thread (void); |
215 | extern void pciehp_event_stop_thread (void); | 181 | extern void pciehp_event_stop_thread (void); |
216 | extern struct pci_func *pciehp_slot_create (unsigned char busnumber); | ||
217 | extern struct pci_func *pciehp_slot_find (unsigned char bus, unsigned char device, unsigned char index); | ||
218 | extern int pciehp_enable_slot (struct slot *slot); | 182 | extern int pciehp_enable_slot (struct slot *slot); |
219 | extern int pciehp_disable_slot (struct slot *slot); | 183 | extern int pciehp_disable_slot (struct slot *slot); |
220 | 184 | ||
@@ -224,25 +188,17 @@ extern u8 pciehp_handle_presence_change (u8 hp_slot, void *inst_id); | |||
224 | extern u8 pciehp_handle_power_fault (u8 hp_slot, void *inst_id); | 188 | extern u8 pciehp_handle_power_fault (u8 hp_slot, void *inst_id); |
225 | /* extern void long_delay (int delay); */ | 189 | /* extern void long_delay (int delay); */ |
226 | 190 | ||
227 | /* resource functions */ | ||
228 | extern int pciehp_resource_sort_and_combine (struct pci_resource **head); | ||
229 | |||
230 | /* pci functions */ | 191 | /* pci functions */ |
231 | extern int pciehp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num); | 192 | extern int pciehp_configure_device (struct slot *p_slot); |
232 | /*extern int pciehp_get_bus_dev (struct controller *ctrl, u8 *bus_num, u8 *dev_num, struct slot *slot);*/ | 193 | extern int pciehp_unconfigure_device (struct slot *p_slot); |
233 | extern int pciehp_save_config (struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num); | 194 | extern int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev); |
234 | extern int pciehp_save_used_resources (struct controller *ctrl, struct pci_func * func, int flag); | 195 | extern void pciehp_get_hp_params_from_firmware(struct pci_dev *dev, |
235 | extern int pciehp_save_slot_config (struct controller *ctrl, struct pci_func * new_slot); | 196 | struct hotplug_params *hpp); |
236 | extern void pciehp_destroy_board_resources (struct pci_func * func); | 197 | |
237 | extern int pciehp_return_board_resources (struct pci_func * func, struct resource_lists * resources); | ||
238 | extern void pciehp_destroy_resource_list (struct resource_lists * resources); | ||
239 | extern int pciehp_configure_device (struct controller* ctrl, struct pci_func* func); | ||
240 | extern int pciehp_unconfigure_device (struct pci_func* func); | ||
241 | 198 | ||
242 | 199 | ||
243 | /* Global variables */ | 200 | /* Global variables */ |
244 | extern struct controller *pciehp_ctrl_list; | 201 | extern struct controller *pciehp_ctrl_list; |
245 | extern struct pci_func *pciehp_slot_list[256]; | ||
246 | 202 | ||
247 | /* Inline functions */ | 203 | /* Inline functions */ |
248 | 204 | ||
@@ -252,12 +208,9 @@ static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device) | |||
252 | 208 | ||
253 | p_slot = ctrl->slot; | 209 | p_slot = ctrl->slot; |
254 | 210 | ||
255 | dbg("p_slot = %p\n", p_slot); | ||
256 | |||
257 | while (p_slot && (p_slot->device != device)) { | 211 | while (p_slot && (p_slot->device != device)) { |
258 | tmp_slot = p_slot; | 212 | tmp_slot = p_slot; |
259 | p_slot = p_slot->next; | 213 | p_slot = p_slot->next; |
260 | dbg("In while loop, p_slot = %p\n", p_slot); | ||
261 | } | 214 | } |
262 | if (p_slot == NULL) { | 215 | if (p_slot == NULL) { |
263 | err("ERROR: pciehp_find_slot device=0x%x\n", device); | 216 | err("ERROR: pciehp_find_slot device=0x%x\n", device); |
@@ -273,7 +226,6 @@ static inline int wait_for_ctrl_irq(struct controller *ctrl) | |||
273 | 226 | ||
274 | DECLARE_WAITQUEUE(wait, current); | 227 | DECLARE_WAITQUEUE(wait, current); |
275 | 228 | ||
276 | dbg("%s : start\n", __FUNCTION__); | ||
277 | add_wait_queue(&ctrl->queue, &wait); | 229 | add_wait_queue(&ctrl->queue, &wait); |
278 | if (!pciehp_poll_mode) | 230 | if (!pciehp_poll_mode) |
279 | /* Sleep for up to 1 second */ | 231 | /* Sleep for up to 1 second */ |
@@ -285,19 +237,9 @@ static inline int wait_for_ctrl_irq(struct controller *ctrl) | |||
285 | if (signal_pending(current)) | 237 | if (signal_pending(current)) |
286 | retval = -EINTR; | 238 | retval = -EINTR; |
287 | 239 | ||
288 | dbg("%s : end\n", __FUNCTION__); | ||
289 | return retval; | 240 | return retval; |
290 | } | 241 | } |
291 | 242 | ||
292 | /* Puts node back in the resource list pointed to by head */ | ||
293 | static inline void return_resource(struct pci_resource **head, struct pci_resource *node) | ||
294 | { | ||
295 | if (!node || !head) | ||
296 | return; | ||
297 | node->next = *head; | ||
298 | *head = node; | ||
299 | } | ||
300 | |||
301 | #define SLOT_NAME_SIZE 10 | 243 | #define SLOT_NAME_SIZE 10 |
302 | 244 | ||
303 | static inline void make_slot_name(char *buffer, int buffer_size, struct slot *slot) | 245 | static inline void make_slot_name(char *buffer, int buffer_size, struct slot *slot) |
@@ -311,14 +253,7 @@ enum php_ctlr_type { | |||
311 | ACPI | 253 | ACPI |
312 | }; | 254 | }; |
313 | 255 | ||
314 | typedef u8(*php_intr_callback_t) (unsigned int change_id, void *instance_id); | 256 | int pcie_init(struct controller *ctrl, struct pcie_device *dev); |
315 | |||
316 | int pcie_init(struct controller *ctrl, struct pcie_device *dev, | ||
317 | php_intr_callback_t attention_button_callback, | ||
318 | php_intr_callback_t switch_change_callback, | ||
319 | php_intr_callback_t presence_change_callback, | ||
320 | php_intr_callback_t power_fault_callback); | ||
321 | |||
322 | 257 | ||
323 | /* This has no meaning for PCI Express, as there is only 1 slot per port */ | 258 | /* This has no meaning for PCI Express, as there is only 1 slot per port */ |
324 | int pcie_get_ctlr_slot_config(struct controller *ctrl, | 259 | int pcie_get_ctlr_slot_config(struct controller *ctrl, |
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index cafc7eadcf80..8df704860348 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c | |||
@@ -27,27 +27,20 @@ | |||
27 | * | 27 | * |
28 | */ | 28 | */ |
29 | 29 | ||
30 | #include <linux/config.h> | ||
31 | #include <linux/module.h> | 30 | #include <linux/module.h> |
32 | #include <linux/moduleparam.h> | 31 | #include <linux/moduleparam.h> |
33 | #include <linux/kernel.h> | 32 | #include <linux/kernel.h> |
34 | #include <linux/types.h> | 33 | #include <linux/types.h> |
35 | #include <linux/proc_fs.h> | ||
36 | #include <linux/slab.h> | ||
37 | #include <linux/workqueue.h> | ||
38 | #include <linux/pci.h> | 34 | #include <linux/pci.h> |
39 | #include <linux/init.h> | ||
40 | #include <asm/uaccess.h> | ||
41 | #include "pciehp.h" | 35 | #include "pciehp.h" |
42 | #include "pciehprm.h" | ||
43 | #include <linux/interrupt.h> | 36 | #include <linux/interrupt.h> |
44 | 37 | ||
45 | /* Global variables */ | 38 | /* Global variables */ |
46 | int pciehp_debug; | 39 | int pciehp_debug; |
47 | int pciehp_poll_mode; | 40 | int pciehp_poll_mode; |
48 | int pciehp_poll_time; | 41 | int pciehp_poll_time; |
42 | int pciehp_force; | ||
49 | struct controller *pciehp_ctrl_list; | 43 | struct controller *pciehp_ctrl_list; |
50 | struct pci_func *pciehp_slot_list[256]; | ||
51 | 44 | ||
52 | #define DRIVER_VERSION "0.4" | 45 | #define DRIVER_VERSION "0.4" |
53 | #define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>" | 46 | #define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>" |
@@ -60,9 +53,11 @@ MODULE_LICENSE("GPL"); | |||
60 | module_param(pciehp_debug, bool, 0644); | 53 | module_param(pciehp_debug, bool, 0644); |
61 | module_param(pciehp_poll_mode, bool, 0644); | 54 | module_param(pciehp_poll_mode, bool, 0644); |
62 | module_param(pciehp_poll_time, int, 0644); | 55 | module_param(pciehp_poll_time, int, 0644); |
56 | module_param(pciehp_force, bool, 0644); | ||
63 | MODULE_PARM_DESC(pciehp_debug, "Debugging mode enabled or not"); | 57 | MODULE_PARM_DESC(pciehp_debug, "Debugging mode enabled or not"); |
64 | MODULE_PARM_DESC(pciehp_poll_mode, "Using polling mechanism for hot-plug events or not"); | 58 | MODULE_PARM_DESC(pciehp_poll_mode, "Using polling mechanism for hot-plug events or not"); |
65 | MODULE_PARM_DESC(pciehp_poll_time, "Polling mechanism frequency, in seconds"); | 59 | MODULE_PARM_DESC(pciehp_poll_time, "Polling mechanism frequency, in seconds"); |
60 | MODULE_PARM_DESC(pciehp_force, "Force pciehp, even if _OSC and OSHP are missing"); | ||
66 | 61 | ||
67 | #define PCIE_MODULE_NAME "pciehp" | 62 | #define PCIE_MODULE_NAME "pciehp" |
68 | 63 | ||
@@ -114,8 +109,6 @@ static int init_slots(struct controller *ctrl) | |||
114 | u32 slot_number; | 109 | u32 slot_number; |
115 | int result = -ENOMEM; | 110 | int result = -ENOMEM; |
116 | 111 | ||
117 | dbg("%s\n",__FUNCTION__); | ||
118 | |||
119 | number_of_slots = ctrl->num_slots; | 112 | number_of_slots = ctrl->num_slots; |
120 | slot_device = ctrl->slot_device_offset; | 113 | slot_device = ctrl->slot_device_offset; |
121 | slot_number = ctrl->first_slot; | 114 | slot_number = ctrl->first_slot; |
@@ -370,7 +363,6 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ | |||
370 | u8 value; | 363 | u8 value; |
371 | struct pci_dev *pdev; | 364 | struct pci_dev *pdev; |
372 | 365 | ||
373 | dbg("%s: Called by hp_drv\n", __FUNCTION__); | ||
374 | ctrl = kmalloc(sizeof(*ctrl), GFP_KERNEL); | 366 | ctrl = kmalloc(sizeof(*ctrl), GFP_KERNEL); |
375 | if (!ctrl) { | 367 | if (!ctrl) { |
376 | err("%s : out of memory\n", __FUNCTION__); | 368 | err("%s : out of memory\n", __FUNCTION__); |
@@ -378,22 +370,15 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ | |||
378 | } | 370 | } |
379 | memset(ctrl, 0, sizeof(struct controller)); | 371 | memset(ctrl, 0, sizeof(struct controller)); |
380 | 372 | ||
381 | dbg("%s: DRV_thread pid = %d\n", __FUNCTION__, current->pid); | ||
382 | |||
383 | pdev = dev->port; | 373 | pdev = dev->port; |
374 | ctrl->pci_dev = pdev; | ||
384 | 375 | ||
385 | rc = pcie_init(ctrl, dev, | 376 | rc = pcie_init(ctrl, dev); |
386 | (php_intr_callback_t) pciehp_handle_attention_button, | ||
387 | (php_intr_callback_t) pciehp_handle_switch_change, | ||
388 | (php_intr_callback_t) pciehp_handle_presence_change, | ||
389 | (php_intr_callback_t) pciehp_handle_power_fault); | ||
390 | if (rc) { | 377 | if (rc) { |
391 | dbg("%s: controller initialization failed\n", PCIE_MODULE_NAME); | 378 | dbg("%s: controller initialization failed\n", PCIE_MODULE_NAME); |
392 | goto err_out_free_ctrl; | 379 | goto err_out_free_ctrl; |
393 | } | 380 | } |
394 | 381 | ||
395 | ctrl->pci_dev = pdev; | ||
396 | |||
397 | pci_set_drvdata(pdev, ctrl); | 382 | pci_set_drvdata(pdev, ctrl); |
398 | 383 | ||
399 | ctrl->pci_bus = kmalloc(sizeof(*ctrl->pci_bus), GFP_KERNEL); | 384 | ctrl->pci_bus = kmalloc(sizeof(*ctrl->pci_bus), GFP_KERNEL); |
@@ -402,7 +387,6 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ | |||
402 | rc = -ENOMEM; | 387 | rc = -ENOMEM; |
403 | goto err_out_unmap_mmio_region; | 388 | goto err_out_unmap_mmio_region; |
404 | } | 389 | } |
405 | dbg("%s: ctrl->pci_bus %p\n", __FUNCTION__, ctrl->pci_bus); | ||
406 | memcpy (ctrl->pci_bus, pdev->bus, sizeof (*ctrl->pci_bus)); | 390 | memcpy (ctrl->pci_bus, pdev->bus, sizeof (*ctrl->pci_bus)); |
407 | ctrl->bus = pdev->bus->number; /* ctrl bus */ | 391 | ctrl->bus = pdev->bus->number; /* ctrl bus */ |
408 | ctrl->slot_bus = pdev->subordinate->number; /* bus controlled by this HPC */ | 392 | ctrl->slot_bus = pdev->subordinate->number; /* bus controlled by this HPC */ |
@@ -424,25 +408,6 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ | |||
424 | first_device_num = ctrl->slot_device_offset; | 408 | first_device_num = ctrl->slot_device_offset; |
425 | num_ctlr_slots = ctrl->num_slots; | 409 | num_ctlr_slots = ctrl->num_slots; |
426 | 410 | ||
427 | /* Store PCI Config Space for all devices on this bus */ | ||
428 | dbg("%s: Before calling pciehp_save_config, ctrl->bus %x,ctrl->slot_bus %x\n", | ||
429 | __FUNCTION__,ctrl->bus, ctrl->slot_bus); | ||
430 | rc = pciehp_save_config(ctrl, ctrl->slot_bus, num_ctlr_slots, first_device_num); | ||
431 | if (rc) { | ||
432 | err("%s: unable to save PCI configuration data, error %d\n", __FUNCTION__, rc); | ||
433 | goto err_out_free_ctrl_bus; | ||
434 | } | ||
435 | |||
436 | /* Get IO, memory, and IRQ resources for new devices */ | ||
437 | rc = pciehprm_find_available_resources(ctrl); | ||
438 | ctrl->add_support = !rc; | ||
439 | |||
440 | if (rc) { | ||
441 | dbg("pciehprm_find_available_resources = %#x\n", rc); | ||
442 | err("unable to locate PCI configuration resources for hot plug add.\n"); | ||
443 | goto err_out_free_ctrl_bus; | ||
444 | } | ||
445 | |||
446 | /* Setup the slot information structures */ | 411 | /* Setup the slot information structures */ |
447 | rc = init_slots(ctrl); | 412 | rc = init_slots(ctrl); |
448 | if (rc) { | 413 | if (rc) { |
@@ -451,7 +416,6 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ | |||
451 | } | 416 | } |
452 | 417 | ||
453 | t_slot = pciehp_find_slot(ctrl, first_device_num); | 418 | t_slot = pciehp_find_slot(ctrl, first_device_num); |
454 | dbg("%s: t_slot %p\n", __FUNCTION__, t_slot); | ||
455 | 419 | ||
456 | /* Finish setting up the hot plug ctrl device */ | 420 | /* Finish setting up the hot plug ctrl device */ |
457 | ctrl->next_event = 0; | 421 | ctrl->next_event = 0; |
@@ -468,7 +432,6 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ | |||
468 | down(&ctrl->crit_sect); | 432 | down(&ctrl->crit_sect); |
469 | 433 | ||
470 | t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */ | 434 | t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */ |
471 | dbg("%s: adpater value %x\n", __FUNCTION__, value); | ||
472 | 435 | ||
473 | if ((POWER_CTRL(ctrl->ctrlcap)) && !value) { | 436 | if ((POWER_CTRL(ctrl->ctrlcap)) && !value) { |
474 | rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/ | 437 | rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/ |
@@ -501,7 +464,6 @@ err_out_none: | |||
501 | 464 | ||
502 | static int pcie_start_thread(void) | 465 | static int pcie_start_thread(void) |
503 | { | 466 | { |
504 | int loop; | ||
505 | int retval = 0; | 467 | int retval = 0; |
506 | 468 | ||
507 | dbg("Initialize + Start the notification/polling mechanism \n"); | 469 | dbg("Initialize + Start the notification/polling mechanism \n"); |
@@ -512,32 +474,11 @@ static int pcie_start_thread(void) | |||
512 | return retval; | 474 | return retval; |
513 | } | 475 | } |
514 | 476 | ||
515 | dbg("Initialize slot lists\n"); | ||
516 | /* One slot list for each bus in the system */ | ||
517 | for (loop = 0; loop < 256; loop++) { | ||
518 | pciehp_slot_list[loop] = NULL; | ||
519 | } | ||
520 | |||
521 | return retval; | 477 | return retval; |
522 | } | 478 | } |
523 | 479 | ||
524 | static inline void __exit | ||
525 | free_pciehp_res(struct pci_resource *res) | ||
526 | { | ||
527 | struct pci_resource *tres; | ||
528 | |||
529 | while (res) { | ||
530 | tres = res; | ||
531 | res = res->next; | ||
532 | kfree(tres); | ||
533 | } | ||
534 | } | ||
535 | |||
536 | static void __exit unload_pciehpd(void) | 480 | static void __exit unload_pciehpd(void) |
537 | { | 481 | { |
538 | struct pci_func *next; | ||
539 | struct pci_func *TempSlot; | ||
540 | int loop; | ||
541 | struct controller *ctrl; | 482 | struct controller *ctrl; |
542 | struct controller *tctrl; | 483 | struct controller *tctrl; |
543 | 484 | ||
@@ -546,11 +487,6 @@ static void __exit unload_pciehpd(void) | |||
546 | while (ctrl) { | 487 | while (ctrl) { |
547 | cleanup_slots(ctrl); | 488 | cleanup_slots(ctrl); |
548 | 489 | ||
549 | free_pciehp_res(ctrl->io_head); | ||
550 | free_pciehp_res(ctrl->mem_head); | ||
551 | free_pciehp_res(ctrl->p_mem_head); | ||
552 | free_pciehp_res(ctrl->bus_head); | ||
553 | |||
554 | kfree (ctrl->pci_bus); | 490 | kfree (ctrl->pci_bus); |
555 | 491 | ||
556 | ctrl->hpc_ops->release_ctlr(ctrl); | 492 | ctrl->hpc_ops->release_ctlr(ctrl); |
@@ -561,20 +497,6 @@ static void __exit unload_pciehpd(void) | |||
561 | kfree(tctrl); | 497 | kfree(tctrl); |
562 | } | 498 | } |
563 | 499 | ||
564 | for (loop = 0; loop < 256; loop++) { | ||
565 | next = pciehp_slot_list[loop]; | ||
566 | while (next != NULL) { | ||
567 | free_pciehp_res(next->io_head); | ||
568 | free_pciehp_res(next->mem_head); | ||
569 | free_pciehp_res(next->p_mem_head); | ||
570 | free_pciehp_res(next->bus_head); | ||
571 | |||
572 | TempSlot = next; | ||
573 | next = next->next; | ||
574 | kfree(TempSlot); | ||
575 | } | ||
576 | } | ||
577 | |||
578 | /* Stop the notification mechanism */ | 500 | /* Stop the notification mechanism */ |
579 | pciehp_event_stop_thread(); | 501 | pciehp_event_stop_thread(); |
580 | 502 | ||
@@ -639,21 +561,16 @@ static int __init pcied_init(void) | |||
639 | if (retval) | 561 | if (retval) |
640 | goto error_hpc_init; | 562 | goto error_hpc_init; |
641 | 563 | ||
642 | retval = pciehprm_init(PCI); | 564 | retval = pcie_port_service_register(&hpdriver_portdrv); |
643 | if (!retval) { | 565 | dbg("pcie_port_service_register = %d\n", retval); |
644 | retval = pcie_port_service_register(&hpdriver_portdrv); | 566 | info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); |
645 | dbg("pcie_port_service_register = %d\n", retval); | 567 | if (retval) |
646 | info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); | 568 | dbg("%s: Failure to register service\n", __FUNCTION__); |
647 | if (retval) | ||
648 | dbg("%s: Failure to register service\n", __FUNCTION__); | ||
649 | } | ||
650 | 569 | ||
651 | error_hpc_init: | 570 | error_hpc_init: |
652 | if (retval) { | 571 | if (retval) { |
653 | pciehprm_cleanup(); | ||
654 | pciehp_event_stop_thread(); | 572 | pciehp_event_stop_thread(); |
655 | } else | 573 | }; |
656 | pciehprm_print_pirt(); | ||
657 | 574 | ||
658 | return retval; | 575 | return retval; |
659 | } | 576 | } |
@@ -663,9 +580,6 @@ static void __exit pcied_cleanup(void) | |||
663 | dbg("unload_pciehpd()\n"); | 580 | dbg("unload_pciehpd()\n"); |
664 | unload_pciehpd(); | 581 | unload_pciehpd(); |
665 | 582 | ||
666 | pciehprm_cleanup(); | ||
667 | |||
668 | dbg("pcie_port_service_unregister\n"); | ||
669 | pcie_port_service_unregister(&hpdriver_portdrv); | 583 | pcie_port_service_unregister(&hpdriver_portdrv); |
670 | 584 | ||
671 | info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); | 585 | info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); |
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 898f6da6f0de..5e582eca21d8 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c | |||
@@ -27,25 +27,14 @@ | |||
27 | * | 27 | * |
28 | */ | 28 | */ |
29 | 29 | ||
30 | #include <linux/config.h> | ||
31 | #include <linux/module.h> | 30 | #include <linux/module.h> |
32 | #include <linux/kernel.h> | 31 | #include <linux/kernel.h> |
33 | #include <linux/types.h> | 32 | #include <linux/types.h> |
34 | #include <linux/slab.h> | ||
35 | #include <linux/workqueue.h> | ||
36 | #include <linux/interrupt.h> | ||
37 | #include <linux/delay.h> | ||
38 | #include <linux/wait.h> | ||
39 | #include <linux/smp_lock.h> | 33 | #include <linux/smp_lock.h> |
40 | #include <linux/pci.h> | 34 | #include <linux/pci.h> |
41 | #include "../pci.h" | 35 | #include "../pci.h" |
42 | #include "pciehp.h" | 36 | #include "pciehp.h" |
43 | #include "pciehprm.h" | ||
44 | 37 | ||
45 | static u32 configure_new_device(struct controller *ctrl, struct pci_func *func, | ||
46 | u8 behind_bridge, struct resource_lists *resources, u8 bridge_bus, u8 bridge_dev); | ||
47 | static int configure_new_function( struct controller *ctrl, struct pci_func *func, | ||
48 | u8 behind_bridge, struct resource_lists *resources, u8 bridge_bus, u8 bridge_dev); | ||
49 | static void interrupt_event_handler(struct controller *ctrl); | 38 | static void interrupt_event_handler(struct controller *ctrl); |
50 | 39 | ||
51 | static struct semaphore event_semaphore; /* mutex for process loop (up if something to process) */ | 40 | static struct semaphore event_semaphore; /* mutex for process loop (up if something to process) */ |
@@ -60,22 +49,18 @@ u8 pciehp_handle_attention_button(u8 hp_slot, void *inst_id) | |||
60 | struct slot *p_slot; | 49 | struct slot *p_slot; |
61 | u8 rc = 0; | 50 | u8 rc = 0; |
62 | u8 getstatus; | 51 | u8 getstatus; |
63 | struct pci_func *func; | ||
64 | struct event_info *taskInfo; | 52 | struct event_info *taskInfo; |
65 | 53 | ||
66 | /* Attention Button Change */ | 54 | /* Attention Button Change */ |
67 | dbg("pciehp: Attention button interrupt received.\n"); | 55 | dbg("pciehp: Attention button interrupt received.\n"); |
68 | 56 | ||
69 | func = pciehp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0); | ||
70 | |||
71 | /* This is the structure that tells the worker thread what to do */ | 57 | /* This is the structure that tells the worker thread what to do */ |
72 | taskInfo = &(ctrl->event_queue[ctrl->next_event]); | 58 | taskInfo = &(ctrl->event_queue[ctrl->next_event]); |
73 | p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); | 59 | p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); |
74 | 60 | ||
75 | p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save)); | ||
76 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); | 61 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); |
77 | 62 | ||
78 | ctrl->next_event = (ctrl->next_event + 1) % 10; | 63 | ctrl->next_event = (ctrl->next_event + 1) % MAX_EVENTS; |
79 | taskInfo->hp_slot = hp_slot; | 64 | taskInfo->hp_slot = hp_slot; |
80 | 65 | ||
81 | rc++; | 66 | rc++; |
@@ -117,24 +102,20 @@ u8 pciehp_handle_switch_change(u8 hp_slot, void *inst_id) | |||
117 | struct slot *p_slot; | 102 | struct slot *p_slot; |
118 | u8 rc = 0; | 103 | u8 rc = 0; |
119 | u8 getstatus; | 104 | u8 getstatus; |
120 | struct pci_func *func; | ||
121 | struct event_info *taskInfo; | 105 | struct event_info *taskInfo; |
122 | 106 | ||
123 | /* Switch Change */ | 107 | /* Switch Change */ |
124 | dbg("pciehp: Switch interrupt received.\n"); | 108 | dbg("pciehp: Switch interrupt received.\n"); |
125 | 109 | ||
126 | func = pciehp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0); | ||
127 | |||
128 | /* This is the structure that tells the worker thread | 110 | /* This is the structure that tells the worker thread |
129 | * what to do | 111 | * what to do |
130 | */ | 112 | */ |
131 | taskInfo = &(ctrl->event_queue[ctrl->next_event]); | 113 | taskInfo = &(ctrl->event_queue[ctrl->next_event]); |
132 | ctrl->next_event = (ctrl->next_event + 1) % 10; | 114 | ctrl->next_event = (ctrl->next_event + 1) % MAX_EVENTS; |
133 | taskInfo->hp_slot = hp_slot; | 115 | taskInfo->hp_slot = hp_slot; |
134 | 116 | ||
135 | rc++; | 117 | rc++; |
136 | p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); | 118 | p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); |
137 | p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save)); | ||
138 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); | 119 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); |
139 | 120 | ||
140 | if (getstatus) { | 121 | if (getstatus) { |
@@ -142,14 +123,12 @@ u8 pciehp_handle_switch_change(u8 hp_slot, void *inst_id) | |||
142 | * Switch opened | 123 | * Switch opened |
143 | */ | 124 | */ |
144 | info("Latch open on Slot(%d)\n", ctrl->first_slot + hp_slot); | 125 | info("Latch open on Slot(%d)\n", ctrl->first_slot + hp_slot); |
145 | func->switch_save = 0; | ||
146 | taskInfo->event_type = INT_SWITCH_OPEN; | 126 | taskInfo->event_type = INT_SWITCH_OPEN; |
147 | } else { | 127 | } else { |
148 | /* | 128 | /* |
149 | * Switch closed | 129 | * Switch closed |
150 | */ | 130 | */ |
151 | info("Latch close on Slot(%d)\n", ctrl->first_slot + hp_slot); | 131 | info("Latch close on Slot(%d)\n", ctrl->first_slot + hp_slot); |
152 | func->switch_save = 0x10; | ||
153 | taskInfo->event_type = INT_SWITCH_CLOSE; | 132 | taskInfo->event_type = INT_SWITCH_CLOSE; |
154 | } | 133 | } |
155 | 134 | ||
@@ -163,20 +142,17 @@ u8 pciehp_handle_presence_change(u8 hp_slot, void *inst_id) | |||
163 | { | 142 | { |
164 | struct controller *ctrl = (struct controller *) inst_id; | 143 | struct controller *ctrl = (struct controller *) inst_id; |
165 | struct slot *p_slot; | 144 | struct slot *p_slot; |
166 | u8 rc = 0; | 145 | u8 presence_save, rc = 0; |
167 | struct pci_func *func; | ||
168 | struct event_info *taskInfo; | 146 | struct event_info *taskInfo; |
169 | 147 | ||
170 | /* Presence Change */ | 148 | /* Presence Change */ |
171 | dbg("pciehp: Presence/Notify input change.\n"); | 149 | dbg("pciehp: Presence/Notify input change.\n"); |
172 | 150 | ||
173 | func = pciehp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0); | ||
174 | |||
175 | /* This is the structure that tells the worker thread | 151 | /* This is the structure that tells the worker thread |
176 | * what to do | 152 | * what to do |
177 | */ | 153 | */ |
178 | taskInfo = &(ctrl->event_queue[ctrl->next_event]); | 154 | taskInfo = &(ctrl->event_queue[ctrl->next_event]); |
179 | ctrl->next_event = (ctrl->next_event + 1) % 10; | 155 | ctrl->next_event = (ctrl->next_event + 1) % MAX_EVENTS; |
180 | taskInfo->hp_slot = hp_slot; | 156 | taskInfo->hp_slot = hp_slot; |
181 | 157 | ||
182 | rc++; | 158 | rc++; |
@@ -185,8 +161,8 @@ u8 pciehp_handle_presence_change(u8 hp_slot, void *inst_id) | |||
185 | /* Switch is open, assume a presence change | 161 | /* Switch is open, assume a presence change |
186 | * Save the presence state | 162 | * Save the presence state |
187 | */ | 163 | */ |
188 | p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save)); | 164 | p_slot->hpc_ops->get_adapter_status(p_slot, &presence_save); |
189 | if (func->presence_save) { | 165 | if (presence_save) { |
190 | /* | 166 | /* |
191 | * Card Present | 167 | * Card Present |
192 | */ | 168 | */ |
@@ -211,19 +187,16 @@ u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id) | |||
211 | struct controller *ctrl = (struct controller *) inst_id; | 187 | struct controller *ctrl = (struct controller *) inst_id; |
212 | struct slot *p_slot; | 188 | struct slot *p_slot; |
213 | u8 rc = 0; | 189 | u8 rc = 0; |
214 | struct pci_func *func; | ||
215 | struct event_info *taskInfo; | 190 | struct event_info *taskInfo; |
216 | 191 | ||
217 | /* power fault */ | 192 | /* power fault */ |
218 | dbg("pciehp: Power fault interrupt received.\n"); | 193 | dbg("pciehp: Power fault interrupt received.\n"); |
219 | 194 | ||
220 | func = pciehp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0); | ||
221 | |||
222 | /* this is the structure that tells the worker thread | 195 | /* this is the structure that tells the worker thread |
223 | * what to do | 196 | * what to do |
224 | */ | 197 | */ |
225 | taskInfo = &(ctrl->event_queue[ctrl->next_event]); | 198 | taskInfo = &(ctrl->event_queue[ctrl->next_event]); |
226 | ctrl->next_event = (ctrl->next_event + 1) % 10; | 199 | ctrl->next_event = (ctrl->next_event + 1) % MAX_EVENTS; |
227 | taskInfo->hp_slot = hp_slot; | 200 | taskInfo->hp_slot = hp_slot; |
228 | 201 | ||
229 | rc++; | 202 | rc++; |
@@ -234,7 +207,7 @@ u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id) | |||
234 | * power fault Cleared | 207 | * power fault Cleared |
235 | */ | 208 | */ |
236 | info("Power fault cleared on Slot(%d)\n", ctrl->first_slot + hp_slot); | 209 | info("Power fault cleared on Slot(%d)\n", ctrl->first_slot + hp_slot); |
237 | func->status = 0x00; | 210 | p_slot->status = 0x00; |
238 | taskInfo->event_type = INT_POWER_FAULT_CLEAR; | 211 | taskInfo->event_type = INT_POWER_FAULT_CLEAR; |
239 | } else { | 212 | } else { |
240 | /* | 213 | /* |
@@ -243,7 +216,7 @@ u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id) | |||
243 | info("Power fault on Slot(%d)\n", ctrl->first_slot + hp_slot); | 216 | info("Power fault on Slot(%d)\n", ctrl->first_slot + hp_slot); |
244 | taskInfo->event_type = INT_POWER_FAULT; | 217 | taskInfo->event_type = INT_POWER_FAULT; |
245 | /* set power fault status for this board */ | 218 | /* set power fault status for this board */ |
246 | func->status = 0xFF; | 219 | p_slot->status = 0xFF; |
247 | info("power fault bit %x set\n", hp_slot); | 220 | info("power fault bit %x set\n", hp_slot); |
248 | } | 221 | } |
249 | if (rc) | 222 | if (rc) |
@@ -252,810 +225,6 @@ u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id) | |||
252 | return rc; | 225 | return rc; |
253 | } | 226 | } |
254 | 227 | ||
255 | |||
256 | /** | ||
257 | * sort_by_size: sort nodes by their length, smallest first. | ||
258 | * | ||
259 | * @head: list to sort | ||
260 | */ | ||
261 | static int sort_by_size(struct pci_resource **head) | ||
262 | { | ||
263 | struct pci_resource *current_res; | ||
264 | struct pci_resource *next_res; | ||
265 | int out_of_order = 1; | ||
266 | |||
267 | if (!(*head)) | ||
268 | return 1; | ||
269 | |||
270 | if (!((*head)->next)) | ||
271 | return 0; | ||
272 | |||
273 | while (out_of_order) { | ||
274 | out_of_order = 0; | ||
275 | |||
276 | /* Special case for swapping list head */ | ||
277 | if (((*head)->next) && | ||
278 | ((*head)->length > (*head)->next->length)) { | ||
279 | out_of_order++; | ||
280 | current_res = *head; | ||
281 | *head = (*head)->next; | ||
282 | current_res->next = (*head)->next; | ||
283 | (*head)->next = current_res; | ||
284 | } | ||
285 | |||
286 | current_res = *head; | ||
287 | |||
288 | while (current_res->next && current_res->next->next) { | ||
289 | if (current_res->next->length > current_res->next->next->length) { | ||
290 | out_of_order++; | ||
291 | next_res = current_res->next; | ||
292 | current_res->next = current_res->next->next; | ||
293 | current_res = current_res->next; | ||
294 | next_res->next = current_res->next; | ||
295 | current_res->next = next_res; | ||
296 | } else | ||
297 | current_res = current_res->next; | ||
298 | } | ||
299 | } /* End of out_of_order loop */ | ||
300 | |||
301 | return 0; | ||
302 | } | ||
303 | |||
304 | |||
305 | /* | ||
306 | * sort_by_max_size | ||
307 | * | ||
308 | * Sorts nodes on the list by their length. | ||
309 | * Largest first. | ||
310 | * | ||
311 | */ | ||
312 | static int sort_by_max_size(struct pci_resource **head) | ||
313 | { | ||
314 | struct pci_resource *current_res; | ||
315 | struct pci_resource *next_res; | ||
316 | int out_of_order = 1; | ||
317 | |||
318 | if (!(*head)) | ||
319 | return 1; | ||
320 | |||
321 | if (!((*head)->next)) | ||
322 | return 0; | ||
323 | |||
324 | while (out_of_order) { | ||
325 | out_of_order = 0; | ||
326 | |||
327 | /* Special case for swapping list head */ | ||
328 | if (((*head)->next) && | ||
329 | ((*head)->length < (*head)->next->length)) { | ||
330 | out_of_order++; | ||
331 | current_res = *head; | ||
332 | *head = (*head)->next; | ||
333 | current_res->next = (*head)->next; | ||
334 | (*head)->next = current_res; | ||
335 | } | ||
336 | |||
337 | current_res = *head; | ||
338 | |||
339 | while (current_res->next && current_res->next->next) { | ||
340 | if (current_res->next->length < current_res->next->next->length) { | ||
341 | out_of_order++; | ||
342 | next_res = current_res->next; | ||
343 | current_res->next = current_res->next->next; | ||
344 | current_res = current_res->next; | ||
345 | next_res->next = current_res->next; | ||
346 | current_res->next = next_res; | ||
347 | } else | ||
348 | current_res = current_res->next; | ||
349 | } | ||
350 | } /* End of out_of_order loop */ | ||
351 | |||
352 | return 0; | ||
353 | } | ||
354 | |||
355 | |||
356 | /** | ||
357 | * do_pre_bridge_resource_split: return one unused resource node | ||
358 | * @head: list to scan | ||
359 | * | ||
360 | */ | ||
361 | static struct pci_resource * | ||
362 | do_pre_bridge_resource_split(struct pci_resource **head, | ||
363 | struct pci_resource **orig_head, u32 alignment) | ||
364 | { | ||
365 | struct pci_resource *prevnode = NULL; | ||
366 | struct pci_resource *node; | ||
367 | struct pci_resource *split_node; | ||
368 | u32 rc; | ||
369 | u32 temp_dword; | ||
370 | dbg("do_pre_bridge_resource_split\n"); | ||
371 | |||
372 | if (!(*head) || !(*orig_head)) | ||
373 | return NULL; | ||
374 | |||
375 | rc = pciehp_resource_sort_and_combine(head); | ||
376 | |||
377 | if (rc) | ||
378 | return NULL; | ||
379 | |||
380 | if ((*head)->base != (*orig_head)->base) | ||
381 | return NULL; | ||
382 | |||
383 | if ((*head)->length == (*orig_head)->length) | ||
384 | return NULL; | ||
385 | |||
386 | |||
387 | /* If we got here, there the bridge requires some of the resource, but | ||
388 | * we may be able to split some off of the front | ||
389 | */ | ||
390 | node = *head; | ||
391 | |||
392 | if (node->length & (alignment -1)) { | ||
393 | /* this one isn't an aligned length, so we'll make a new entry | ||
394 | * and split it up. | ||
395 | */ | ||
396 | split_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL); | ||
397 | |||
398 | if (!split_node) | ||
399 | return NULL; | ||
400 | |||
401 | temp_dword = (node->length | (alignment-1)) + 1 - alignment; | ||
402 | |||
403 | split_node->base = node->base; | ||
404 | split_node->length = temp_dword; | ||
405 | |||
406 | node->length -= temp_dword; | ||
407 | node->base += split_node->length; | ||
408 | |||
409 | /* Put it in the list */ | ||
410 | *head = split_node; | ||
411 | split_node->next = node; | ||
412 | } | ||
413 | |||
414 | if (node->length < alignment) | ||
415 | return NULL; | ||
416 | |||
417 | /* Now unlink it */ | ||
418 | if (*head == node) { | ||
419 | *head = node->next; | ||
420 | } else { | ||
421 | prevnode = *head; | ||
422 | while (prevnode->next != node) | ||
423 | prevnode = prevnode->next; | ||
424 | |||
425 | prevnode->next = node->next; | ||
426 | } | ||
427 | node->next = NULL; | ||
428 | |||
429 | return node; | ||
430 | } | ||
431 | |||
432 | |||
433 | /** | ||
434 | * do_bridge_resource_split: return one unused resource node | ||
435 | * @head: list to scan | ||
436 | * | ||
437 | */ | ||
438 | static struct pci_resource * | ||
439 | do_bridge_resource_split(struct pci_resource **head, u32 alignment) | ||
440 | { | ||
441 | struct pci_resource *prevnode = NULL; | ||
442 | struct pci_resource *node; | ||
443 | u32 rc; | ||
444 | u32 temp_dword; | ||
445 | |||
446 | if (!(*head)) | ||
447 | return NULL; | ||
448 | |||
449 | rc = pciehp_resource_sort_and_combine(head); | ||
450 | |||
451 | if (rc) | ||
452 | return NULL; | ||
453 | |||
454 | node = *head; | ||
455 | |||
456 | while (node->next) { | ||
457 | prevnode = node; | ||
458 | node = node->next; | ||
459 | kfree(prevnode); | ||
460 | } | ||
461 | |||
462 | if (node->length < alignment) { | ||
463 | kfree(node); | ||
464 | return NULL; | ||
465 | } | ||
466 | |||
467 | if (node->base & (alignment - 1)) { | ||
468 | /* Short circuit if adjusted size is too small */ | ||
469 | temp_dword = (node->base | (alignment-1)) + 1; | ||
470 | if ((node->length - (temp_dword - node->base)) < alignment) { | ||
471 | kfree(node); | ||
472 | return NULL; | ||
473 | } | ||
474 | |||
475 | node->length -= (temp_dword - node->base); | ||
476 | node->base = temp_dword; | ||
477 | } | ||
478 | |||
479 | if (node->length & (alignment - 1)) { | ||
480 | /* There's stuff in use after this node */ | ||
481 | kfree(node); | ||
482 | return NULL; | ||
483 | } | ||
484 | |||
485 | return node; | ||
486 | } | ||
487 | |||
488 | |||
489 | /* | ||
490 | * get_io_resource | ||
491 | * | ||
492 | * this function sorts the resource list by size and then | ||
493 | * returns the first node of "size" length that is not in the | ||
494 | * ISA aliasing window. If it finds a node larger than "size" | ||
495 | * it will split it up. | ||
496 | * | ||
497 | * size must be a power of two. | ||
498 | */ | ||
499 | static struct pci_resource *get_io_resource(struct pci_resource **head, u32 size) | ||
500 | { | ||
501 | struct pci_resource *prevnode; | ||
502 | struct pci_resource *node; | ||
503 | struct pci_resource *split_node = NULL; | ||
504 | u32 temp_dword; | ||
505 | |||
506 | if (!(*head)) | ||
507 | return NULL; | ||
508 | |||
509 | if ( pciehp_resource_sort_and_combine(head) ) | ||
510 | return NULL; | ||
511 | |||
512 | if ( sort_by_size(head) ) | ||
513 | return NULL; | ||
514 | |||
515 | for (node = *head; node; node = node->next) { | ||
516 | if (node->length < size) | ||
517 | continue; | ||
518 | |||
519 | if (node->base & (size - 1)) { | ||
520 | /* this one isn't base aligned properly | ||
521 | so we'll make a new entry and split it up */ | ||
522 | temp_dword = (node->base | (size-1)) + 1; | ||
523 | |||
524 | /*/ Short circuit if adjusted size is too small */ | ||
525 | if ((node->length - (temp_dword - node->base)) < size) | ||
526 | continue; | ||
527 | |||
528 | split_node = kmalloc(sizeof(struct pci_resource), | ||
529 | GFP_KERNEL); | ||
530 | |||
531 | if (!split_node) | ||
532 | return NULL; | ||
533 | |||
534 | split_node->base = node->base; | ||
535 | split_node->length = temp_dword - node->base; | ||
536 | node->base = temp_dword; | ||
537 | node->length -= split_node->length; | ||
538 | |||
539 | /* Put it in the list */ | ||
540 | split_node->next = node->next; | ||
541 | node->next = split_node; | ||
542 | } /* End of non-aligned base */ | ||
543 | |||
544 | /* Don't need to check if too small since we already did */ | ||
545 | if (node->length > size) { | ||
546 | /* this one is longer than we need | ||
547 | so we'll make a new entry and split it up */ | ||
548 | split_node = kmalloc(sizeof(struct pci_resource), | ||
549 | GFP_KERNEL); | ||
550 | |||
551 | if (!split_node) | ||
552 | return NULL; | ||
553 | |||
554 | split_node->base = node->base + size; | ||
555 | split_node->length = node->length - size; | ||
556 | node->length = size; | ||
557 | |||
558 | /* Put it in the list */ | ||
559 | split_node->next = node->next; | ||
560 | node->next = split_node; | ||
561 | } /* End of too big on top end */ | ||
562 | |||
563 | /* For IO make sure it's not in the ISA aliasing space */ | ||
564 | if (node->base & 0x300L) | ||
565 | continue; | ||
566 | |||
567 | /* If we got here, then it is the right size | ||
568 | Now take it out of the list */ | ||
569 | if (*head == node) { | ||
570 | *head = node->next; | ||
571 | } else { | ||
572 | prevnode = *head; | ||
573 | while (prevnode->next != node) | ||
574 | prevnode = prevnode->next; | ||
575 | |||
576 | prevnode->next = node->next; | ||
577 | } | ||
578 | node->next = NULL; | ||
579 | /* Stop looping */ | ||
580 | break; | ||
581 | } | ||
582 | |||
583 | return node; | ||
584 | } | ||
585 | |||
586 | |||
587 | /* | ||
588 | * get_max_resource | ||
589 | * | ||
590 | * Gets the largest node that is at least "size" big from the | ||
591 | * list pointed to by head. It aligns the node on top and bottom | ||
592 | * to "size" alignment before returning it. | ||
593 | * J.I. modified to put max size limits of; 64M->32M->16M->8M->4M->1M | ||
594 | * This is needed to avoid allocating entire ACPI _CRS res to one child bridge/slot. | ||
595 | */ | ||
596 | static struct pci_resource *get_max_resource(struct pci_resource **head, u32 size) | ||
597 | { | ||
598 | struct pci_resource *max; | ||
599 | struct pci_resource *temp; | ||
600 | struct pci_resource *split_node; | ||
601 | u32 temp_dword; | ||
602 | u32 max_size[] = { 0x4000000, 0x2000000, 0x1000000, 0x0800000, 0x0400000, 0x0200000, 0x0100000, 0x00 }; | ||
603 | int i; | ||
604 | |||
605 | if (!(*head)) | ||
606 | return NULL; | ||
607 | |||
608 | if (pciehp_resource_sort_and_combine(head)) | ||
609 | return NULL; | ||
610 | |||
611 | if (sort_by_max_size(head)) | ||
612 | return NULL; | ||
613 | |||
614 | for (max = *head;max; max = max->next) { | ||
615 | |||
616 | /* If not big enough we could probably just bail, | ||
617 | instead we'll continue to the next. */ | ||
618 | if (max->length < size) | ||
619 | continue; | ||
620 | |||
621 | if (max->base & (size - 1)) { | ||
622 | /* this one isn't base aligned properly | ||
623 | so we'll make a new entry and split it up */ | ||
624 | temp_dword = (max->base | (size-1)) + 1; | ||
625 | |||
626 | /* Short circuit if adjusted size is too small */ | ||
627 | if ((max->length - (temp_dword - max->base)) < size) | ||
628 | continue; | ||
629 | |||
630 | split_node = kmalloc(sizeof(struct pci_resource), | ||
631 | GFP_KERNEL); | ||
632 | |||
633 | if (!split_node) | ||
634 | return NULL; | ||
635 | |||
636 | split_node->base = max->base; | ||
637 | split_node->length = temp_dword - max->base; | ||
638 | max->base = temp_dword; | ||
639 | max->length -= split_node->length; | ||
640 | |||
641 | /* Put it next in the list */ | ||
642 | split_node->next = max->next; | ||
643 | max->next = split_node; | ||
644 | } | ||
645 | |||
646 | if ((max->base + max->length) & (size - 1)) { | ||
647 | /* this one isn't end aligned properly at the top | ||
648 | so we'll make a new entry and split it up */ | ||
649 | split_node = kmalloc(sizeof(struct pci_resource), | ||
650 | GFP_KERNEL); | ||
651 | |||
652 | if (!split_node) | ||
653 | return NULL; | ||
654 | temp_dword = ((max->base + max->length) & ~(size - 1)); | ||
655 | split_node->base = temp_dword; | ||
656 | split_node->length = max->length + max->base | ||
657 | - split_node->base; | ||
658 | max->length -= split_node->length; | ||
659 | |||
660 | /* Put it in the list */ | ||
661 | split_node->next = max->next; | ||
662 | max->next = split_node; | ||
663 | } | ||
664 | |||
665 | /* Make sure it didn't shrink too much when we aligned it */ | ||
666 | if (max->length < size) | ||
667 | continue; | ||
668 | |||
669 | for ( i = 0; max_size[i] > size; i++) { | ||
670 | if (max->length > max_size[i]) { | ||
671 | split_node = kmalloc(sizeof(struct pci_resource), | ||
672 | GFP_KERNEL); | ||
673 | if (!split_node) | ||
674 | break; /* return NULL; */ | ||
675 | split_node->base = max->base + max_size[i]; | ||
676 | split_node->length = max->length - max_size[i]; | ||
677 | max->length = max_size[i]; | ||
678 | /* Put it next in the list */ | ||
679 | split_node->next = max->next; | ||
680 | max->next = split_node; | ||
681 | break; | ||
682 | } | ||
683 | } | ||
684 | |||
685 | /* Now take it out of the list */ | ||
686 | temp = (struct pci_resource*) *head; | ||
687 | if (temp == max) { | ||
688 | *head = max->next; | ||
689 | } else { | ||
690 | while (temp && temp->next != max) { | ||
691 | temp = temp->next; | ||
692 | } | ||
693 | |||
694 | temp->next = max->next; | ||
695 | } | ||
696 | |||
697 | max->next = NULL; | ||
698 | return max; | ||
699 | } | ||
700 | |||
701 | /* If we get here, we couldn't find one */ | ||
702 | return NULL; | ||
703 | } | ||
704 | |||
705 | |||
706 | /* | ||
707 | * get_resource | ||
708 | * | ||
709 | * this function sorts the resource list by size and then | ||
710 | * returns the first node of "size" length. If it finds a node | ||
711 | * larger than "size" it will split it up. | ||
712 | * | ||
713 | * size must be a power of two. | ||
714 | */ | ||
715 | static struct pci_resource *get_resource(struct pci_resource **head, u32 size) | ||
716 | { | ||
717 | struct pci_resource *prevnode; | ||
718 | struct pci_resource *node; | ||
719 | struct pci_resource *split_node; | ||
720 | u32 temp_dword; | ||
721 | |||
722 | if (!(*head)) | ||
723 | return NULL; | ||
724 | |||
725 | if ( pciehp_resource_sort_and_combine(head) ) | ||
726 | return NULL; | ||
727 | |||
728 | if ( sort_by_size(head) ) | ||
729 | return NULL; | ||
730 | |||
731 | for (node = *head; node; node = node->next) { | ||
732 | dbg("%s: req_size =0x%x node=%p, base=0x%x, length=0x%x\n", | ||
733 | __FUNCTION__, size, node, node->base, node->length); | ||
734 | if (node->length < size) | ||
735 | continue; | ||
736 | |||
737 | if (node->base & (size - 1)) { | ||
738 | dbg("%s: not aligned\n", __FUNCTION__); | ||
739 | /* this one isn't base aligned properly | ||
740 | so we'll make a new entry and split it up */ | ||
741 | temp_dword = (node->base | (size-1)) + 1; | ||
742 | |||
743 | /* Short circuit if adjusted size is too small */ | ||
744 | if ((node->length - (temp_dword - node->base)) < size) | ||
745 | continue; | ||
746 | |||
747 | split_node = kmalloc(sizeof(struct pci_resource), | ||
748 | GFP_KERNEL); | ||
749 | |||
750 | if (!split_node) | ||
751 | return NULL; | ||
752 | |||
753 | split_node->base = node->base; | ||
754 | split_node->length = temp_dword - node->base; | ||
755 | node->base = temp_dword; | ||
756 | node->length -= split_node->length; | ||
757 | |||
758 | /* Put it in the list */ | ||
759 | split_node->next = node->next; | ||
760 | node->next = split_node; | ||
761 | } /* End of non-aligned base */ | ||
762 | |||
763 | /* Don't need to check if too small since we already did */ | ||
764 | if (node->length > size) { | ||
765 | dbg("%s: too big\n", __FUNCTION__); | ||
766 | /* this one is longer than we need | ||
767 | so we'll make a new entry and split it up */ | ||
768 | split_node = kmalloc(sizeof(struct pci_resource), | ||
769 | GFP_KERNEL); | ||
770 | |||
771 | if (!split_node) | ||
772 | return NULL; | ||
773 | |||
774 | split_node->base = node->base + size; | ||
775 | split_node->length = node->length - size; | ||
776 | node->length = size; | ||
777 | |||
778 | /* Put it in the list */ | ||
779 | split_node->next = node->next; | ||
780 | node->next = split_node; | ||
781 | } /* End of too big on top end */ | ||
782 | |||
783 | dbg("%s: got one!!!\n", __FUNCTION__); | ||
784 | /* If we got here, then it is the right size | ||
785 | Now take it out of the list */ | ||
786 | if (*head == node) { | ||
787 | *head = node->next; | ||
788 | } else { | ||
789 | prevnode = *head; | ||
790 | while (prevnode->next != node) | ||
791 | prevnode = prevnode->next; | ||
792 | |||
793 | prevnode->next = node->next; | ||
794 | } | ||
795 | node->next = NULL; | ||
796 | /* Stop looping */ | ||
797 | break; | ||
798 | } | ||
799 | return node; | ||
800 | } | ||
801 | |||
802 | |||
803 | /* | ||
804 | * pciehp_resource_sort_and_combine | ||
805 | * | ||
806 | * Sorts all of the nodes in the list in ascending order by | ||
807 | * their base addresses. Also does garbage collection by | ||
808 | * combining adjacent nodes. | ||
809 | * | ||
810 | * returns 0 if success | ||
811 | */ | ||
812 | int pciehp_resource_sort_and_combine(struct pci_resource **head) | ||
813 | { | ||
814 | struct pci_resource *node1; | ||
815 | struct pci_resource *node2; | ||
816 | int out_of_order = 1; | ||
817 | |||
818 | dbg("%s: head = %p, *head = %p\n", __FUNCTION__, head, *head); | ||
819 | |||
820 | if (!(*head)) | ||
821 | return 1; | ||
822 | |||
823 | dbg("*head->next = %p\n",(*head)->next); | ||
824 | |||
825 | if (!(*head)->next) | ||
826 | return 0; /* only one item on the list, already sorted! */ | ||
827 | |||
828 | dbg("*head->base = 0x%x\n",(*head)->base); | ||
829 | dbg("*head->next->base = 0x%x\n",(*head)->next->base); | ||
830 | while (out_of_order) { | ||
831 | out_of_order = 0; | ||
832 | |||
833 | /* Special case for swapping list head */ | ||
834 | if (((*head)->next) && | ||
835 | ((*head)->base > (*head)->next->base)) { | ||
836 | node1 = *head; | ||
837 | (*head) = (*head)->next; | ||
838 | node1->next = (*head)->next; | ||
839 | (*head)->next = node1; | ||
840 | out_of_order++; | ||
841 | } | ||
842 | |||
843 | node1 = (*head); | ||
844 | |||
845 | while (node1->next && node1->next->next) { | ||
846 | if (node1->next->base > node1->next->next->base) { | ||
847 | out_of_order++; | ||
848 | node2 = node1->next; | ||
849 | node1->next = node1->next->next; | ||
850 | node1 = node1->next; | ||
851 | node2->next = node1->next; | ||
852 | node1->next = node2; | ||
853 | } else | ||
854 | node1 = node1->next; | ||
855 | } | ||
856 | } /* End of out_of_order loop */ | ||
857 | |||
858 | node1 = *head; | ||
859 | |||
860 | while (node1 && node1->next) { | ||
861 | if ((node1->base + node1->length) == node1->next->base) { | ||
862 | /* Combine */ | ||
863 | dbg("8..\n"); | ||
864 | node1->length += node1->next->length; | ||
865 | node2 = node1->next; | ||
866 | node1->next = node1->next->next; | ||
867 | kfree(node2); | ||
868 | } else | ||
869 | node1 = node1->next; | ||
870 | } | ||
871 | |||
872 | return 0; | ||
873 | } | ||
874 | |||
875 | |||
876 | /** | ||
877 | * pciehp_slot_create - Creates a node and adds it to the proper bus. | ||
878 | * @busnumber - bus where new node is to be located | ||
879 | * | ||
880 | * Returns pointer to the new node or NULL if unsuccessful | ||
881 | */ | ||
882 | struct pci_func *pciehp_slot_create(u8 busnumber) | ||
883 | { | ||
884 | struct pci_func *new_slot; | ||
885 | struct pci_func *next; | ||
886 | dbg("%s: busnumber %x\n", __FUNCTION__, busnumber); | ||
887 | new_slot = kmalloc(sizeof(struct pci_func), GFP_KERNEL); | ||
888 | |||
889 | if (new_slot == NULL) | ||
890 | return new_slot; | ||
891 | |||
892 | memset(new_slot, 0, sizeof(struct pci_func)); | ||
893 | |||
894 | new_slot->next = NULL; | ||
895 | new_slot->configured = 1; | ||
896 | |||
897 | if (pciehp_slot_list[busnumber] == NULL) { | ||
898 | pciehp_slot_list[busnumber] = new_slot; | ||
899 | } else { | ||
900 | next = pciehp_slot_list[busnumber]; | ||
901 | while (next->next != NULL) | ||
902 | next = next->next; | ||
903 | next->next = new_slot; | ||
904 | } | ||
905 | return new_slot; | ||
906 | } | ||
907 | |||
908 | |||
909 | /** | ||
910 | * slot_remove - Removes a node from the linked list of slots. | ||
911 | * @old_slot: slot to remove | ||
912 | * | ||
913 | * Returns 0 if successful, !0 otherwise. | ||
914 | */ | ||
915 | static int slot_remove(struct pci_func * old_slot) | ||
916 | { | ||
917 | struct pci_func *next; | ||
918 | |||
919 | if (old_slot == NULL) | ||
920 | return 1; | ||
921 | |||
922 | next = pciehp_slot_list[old_slot->bus]; | ||
923 | |||
924 | if (next == NULL) | ||
925 | return 1; | ||
926 | |||
927 | if (next == old_slot) { | ||
928 | pciehp_slot_list[old_slot->bus] = old_slot->next; | ||
929 | pciehp_destroy_board_resources(old_slot); | ||
930 | kfree(old_slot); | ||
931 | return 0; | ||
932 | } | ||
933 | |||
934 | while ((next->next != old_slot) && (next->next != NULL)) { | ||
935 | next = next->next; | ||
936 | } | ||
937 | |||
938 | if (next->next == old_slot) { | ||
939 | next->next = old_slot->next; | ||
940 | pciehp_destroy_board_resources(old_slot); | ||
941 | kfree(old_slot); | ||
942 | return 0; | ||
943 | } else | ||
944 | return 2; | ||
945 | } | ||
946 | |||
947 | |||
948 | /** | ||
949 | * bridge_slot_remove - Removes a node from the linked list of slots. | ||
950 | * @bridge: bridge to remove | ||
951 | * | ||
952 | * Returns 0 if successful, !0 otherwise. | ||
953 | */ | ||
954 | static int bridge_slot_remove(struct pci_func *bridge) | ||
955 | { | ||
956 | u8 subordinateBus, secondaryBus; | ||
957 | u8 tempBus; | ||
958 | struct pci_func *next; | ||
959 | |||
960 | if (bridge == NULL) | ||
961 | return 1; | ||
962 | |||
963 | secondaryBus = (bridge->config_space[0x06] >> 8) & 0xFF; | ||
964 | subordinateBus = (bridge->config_space[0x06] >> 16) & 0xFF; | ||
965 | |||
966 | for (tempBus = secondaryBus; tempBus <= subordinateBus; tempBus++) { | ||
967 | next = pciehp_slot_list[tempBus]; | ||
968 | |||
969 | while (!slot_remove(next)) { | ||
970 | next = pciehp_slot_list[tempBus]; | ||
971 | } | ||
972 | } | ||
973 | |||
974 | next = pciehp_slot_list[bridge->bus]; | ||
975 | |||
976 | if (next == NULL) { | ||
977 | return 1; | ||
978 | } | ||
979 | |||
980 | if (next == bridge) { | ||
981 | pciehp_slot_list[bridge->bus] = bridge->next; | ||
982 | kfree(bridge); | ||
983 | return 0; | ||
984 | } | ||
985 | |||
986 | while ((next->next != bridge) && (next->next != NULL)) { | ||
987 | next = next->next; | ||
988 | } | ||
989 | |||
990 | if (next->next == bridge) { | ||
991 | next->next = bridge->next; | ||
992 | kfree(bridge); | ||
993 | return 0; | ||
994 | } else | ||
995 | return 2; | ||
996 | } | ||
997 | |||
998 | |||
999 | /** | ||
1000 | * pciehp_slot_find - Looks for a node by bus, and device, multiple functions accessed | ||
1001 | * @bus: bus to find | ||
1002 | * @device: device to find | ||
1003 | * @index: is 0 for first function found, 1 for the second... | ||
1004 | * | ||
1005 | * Returns pointer to the node if successful, %NULL otherwise. | ||
1006 | */ | ||
1007 | struct pci_func *pciehp_slot_find(u8 bus, u8 device, u8 index) | ||
1008 | { | ||
1009 | int found = -1; | ||
1010 | struct pci_func *func; | ||
1011 | |||
1012 | func = pciehp_slot_list[bus]; | ||
1013 | dbg("%s: bus %x device %x index %x\n", | ||
1014 | __FUNCTION__, bus, device, index); | ||
1015 | if (func != NULL) { | ||
1016 | dbg("%s: func-> bus %x device %x function %x pci_dev %p\n", | ||
1017 | __FUNCTION__, func->bus, func->device, func->function, | ||
1018 | func->pci_dev); | ||
1019 | } else | ||
1020 | dbg("%s: func == NULL\n", __FUNCTION__); | ||
1021 | |||
1022 | if ((func == NULL) || ((func->device == device) && (index == 0))) | ||
1023 | return func; | ||
1024 | |||
1025 | if (func->device == device) | ||
1026 | found++; | ||
1027 | |||
1028 | while (func->next != NULL) { | ||
1029 | func = func->next; | ||
1030 | |||
1031 | dbg("%s: In while loop, func-> bus %x device %x function %x pci_dev %p\n", | ||
1032 | __FUNCTION__, func->bus, func->device, func->function, | ||
1033 | func->pci_dev); | ||
1034 | if (func->device == device) | ||
1035 | found++; | ||
1036 | dbg("%s: while loop, found %d, index %d\n", __FUNCTION__, | ||
1037 | found, index); | ||
1038 | |||
1039 | if ((found == index) || (func->function == index)) { | ||
1040 | dbg("%s: Found bus %x dev %x func %x\n", __FUNCTION__, | ||
1041 | func->bus, func->device, func->function); | ||
1042 | return func; | ||
1043 | } | ||
1044 | } | ||
1045 | |||
1046 | return NULL; | ||
1047 | } | ||
1048 | |||
1049 | static int is_bridge(struct pci_func * func) | ||
1050 | { | ||
1051 | /* Check the header type */ | ||
1052 | if (((func->config_space[0x03] >> 16) & 0xFF) == 0x01) | ||
1053 | return 1; | ||
1054 | else | ||
1055 | return 0; | ||
1056 | } | ||
1057 | |||
1058 | |||
1059 | /* The following routines constitute the bulk of the | 228 | /* The following routines constitute the bulk of the |
1060 | hotplug controller logic | 229 | hotplug controller logic |
1061 | */ | 230 | */ |
@@ -1100,20 +269,17 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot) | |||
1100 | * Configures board | 269 | * Configures board |
1101 | * | 270 | * |
1102 | */ | 271 | */ |
1103 | static u32 board_added(struct pci_func * func, struct controller * ctrl) | 272 | static int board_added(struct slot *p_slot) |
1104 | { | 273 | { |
1105 | u8 hp_slot; | 274 | u8 hp_slot; |
1106 | int index; | 275 | int rc = 0; |
1107 | u32 temp_register = 0xFFFFFFFF; | 276 | struct controller *ctrl = p_slot->ctrl; |
1108 | u32 rc = 0; | ||
1109 | struct pci_func *new_func = NULL; | ||
1110 | struct slot *p_slot; | ||
1111 | struct resource_lists res_lists; | ||
1112 | 277 | ||
1113 | p_slot = pciehp_find_slot(ctrl, func->device); | 278 | hp_slot = p_slot->device - ctrl->slot_device_offset; |
1114 | hp_slot = func->device - ctrl->slot_device_offset; | ||
1115 | 279 | ||
1116 | dbg("%s: func->device, slot_offset, hp_slot = %d, %d ,%d\n", __FUNCTION__, func->device, ctrl->slot_device_offset, hp_slot); | 280 | dbg("%s: slot device, slot offset, hp slot = %d, %d ,%d\n", |
281 | __FUNCTION__, p_slot->device, | ||
282 | ctrl->slot_device_offset, hp_slot); | ||
1117 | 283 | ||
1118 | /* Wait for exclusive access to hardware */ | 284 | /* Wait for exclusive access to hardware */ |
1119 | down(&ctrl->crit_sect); | 285 | down(&ctrl->crit_sect); |
@@ -1141,9 +307,7 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl) | |||
1141 | up(&ctrl->crit_sect); | 307 | up(&ctrl->crit_sect); |
1142 | 308 | ||
1143 | /* Wait for ~1 second */ | 309 | /* Wait for ~1 second */ |
1144 | dbg("%s: before long_delay\n", __FUNCTION__); | ||
1145 | wait_for_ctrl_irq (ctrl); | 310 | wait_for_ctrl_irq (ctrl); |
1146 | dbg("%s: afterlong_delay\n", __FUNCTION__); | ||
1147 | 311 | ||
1148 | /* Check link training status */ | 312 | /* Check link training status */ |
1149 | rc = p_slot->hpc_ops->check_lnk_status(ctrl); | 313 | rc = p_slot->hpc_ops->check_lnk_status(ctrl); |
@@ -1153,98 +317,47 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl) | |||
1153 | return rc; | 317 | return rc; |
1154 | } | 318 | } |
1155 | 319 | ||
1156 | dbg("%s: func status = %x\n", __FUNCTION__, func->status); | 320 | dbg("%s: slot status = %x\n", __FUNCTION__, p_slot->status); |
1157 | 321 | ||
1158 | /* Check for a power fault */ | 322 | /* Check for a power fault */ |
1159 | if (func->status == 0xFF) { | 323 | if (p_slot->status == 0xFF) { |
1160 | /* power fault occurred, but it was benign */ | 324 | /* power fault occurred, but it was benign */ |
1161 | temp_register = 0xFFFFFFFF; | ||
1162 | dbg("%s: temp register set to %x by power fault\n", __FUNCTION__, temp_register); | ||
1163 | rc = POWER_FAILURE; | 325 | rc = POWER_FAILURE; |
1164 | func->status = 0; | 326 | p_slot->status = 0; |
1165 | } else { | 327 | goto err_exit; |
1166 | /* Get vendor/device ID u32 */ | ||
1167 | rc = pci_bus_read_config_dword (ctrl->pci_dev->subordinate, PCI_DEVFN(func->device, func->function), | ||
1168 | PCI_VENDOR_ID, &temp_register); | ||
1169 | dbg("%s: pci_bus_read_config_dword returns %d\n", __FUNCTION__, rc); | ||
1170 | dbg("%s: temp_register is %x\n", __FUNCTION__, temp_register); | ||
1171 | |||
1172 | if (rc != 0) { | ||
1173 | /* Something's wrong here */ | ||
1174 | temp_register = 0xFFFFFFFF; | ||
1175 | dbg("%s: temp register set to %x by error\n", __FUNCTION__, temp_register); | ||
1176 | } | ||
1177 | /* Preset return code. It will be changed later if things go okay. */ | ||
1178 | rc = NO_ADAPTER_PRESENT; | ||
1179 | } | 328 | } |
1180 | 329 | ||
1181 | /* All F's is an empty slot or an invalid board */ | 330 | rc = pciehp_configure_device(p_slot); |
1182 | if (temp_register != 0xFFFFFFFF) { /* Check for a board in the slot */ | 331 | if (rc) { |
1183 | res_lists.io_head = ctrl->io_head; | 332 | err("Cannot add device 0x%x:%x\n", p_slot->bus, |
1184 | res_lists.mem_head = ctrl->mem_head; | 333 | p_slot->device); |
1185 | res_lists.p_mem_head = ctrl->p_mem_head; | 334 | goto err_exit; |
1186 | res_lists.bus_head = ctrl->bus_head; | 335 | } |
1187 | res_lists.irqs = NULL; | ||
1188 | |||
1189 | rc = configure_new_device(ctrl, func, 0, &res_lists, 0, 0); | ||
1190 | dbg("%s: back from configure_new_device\n", __FUNCTION__); | ||
1191 | |||
1192 | ctrl->io_head = res_lists.io_head; | ||
1193 | ctrl->mem_head = res_lists.mem_head; | ||
1194 | ctrl->p_mem_head = res_lists.p_mem_head; | ||
1195 | ctrl->bus_head = res_lists.bus_head; | ||
1196 | 336 | ||
1197 | pciehp_resource_sort_and_combine(&(ctrl->mem_head)); | 337 | p_slot->status = 0; |
1198 | pciehp_resource_sort_and_combine(&(ctrl->p_mem_head)); | ||
1199 | pciehp_resource_sort_and_combine(&(ctrl->io_head)); | ||
1200 | pciehp_resource_sort_and_combine(&(ctrl->bus_head)); | ||
1201 | 338 | ||
1202 | if (rc) { | 339 | /* |
1203 | set_slot_off(ctrl, p_slot); | 340 | * Some PCI Express root ports require fixup after hot-plug operation. |
1204 | return rc; | 341 | */ |
1205 | } | 342 | if (pcie_mch_quirk) |
1206 | pciehp_save_slot_config(ctrl, func); | 343 | pci_fixup_device(pci_fixup_final, ctrl->pci_dev); |
1207 | 344 | if (PWR_LED(ctrl->ctrlcap)) { | |
1208 | func->status = 0; | 345 | /* Wait for exclusive access to hardware */ |
1209 | func->switch_save = 0x10; | 346 | down(&ctrl->crit_sect); |
1210 | func->is_a_board = 0x01; | ||
1211 | 347 | ||
1212 | /* next, we will instantiate the linux pci_dev structures | 348 | p_slot->hpc_ops->green_led_on(p_slot); |
1213 | * (with appropriate driver notification, if already present) | ||
1214 | */ | ||
1215 | index = 0; | ||
1216 | do { | ||
1217 | new_func = pciehp_slot_find(ctrl->slot_bus, func->device, index++); | ||
1218 | if (new_func && !new_func->pci_dev) { | ||
1219 | dbg("%s:call pci_hp_configure_dev, func %x\n", | ||
1220 | __FUNCTION__, index); | ||
1221 | pciehp_configure_device(ctrl, new_func); | ||
1222 | } | ||
1223 | } while (new_func); | ||
1224 | |||
1225 | /* | ||
1226 | * Some PCI Express root ports require fixup after hot-plug operation. | ||
1227 | */ | ||
1228 | if (pcie_mch_quirk) | ||
1229 | pci_fixup_device(pci_fixup_final, ctrl->pci_dev); | ||
1230 | |||
1231 | if (PWR_LED(ctrl->ctrlcap)) { | ||
1232 | /* Wait for exclusive access to hardware */ | ||
1233 | down(&ctrl->crit_sect); | ||
1234 | |||
1235 | p_slot->hpc_ops->green_led_on(p_slot); | ||
1236 | 349 | ||
1237 | /* Wait for the command to complete */ | 350 | /* Wait for the command to complete */ |
1238 | wait_for_ctrl_irq (ctrl); | 351 | wait_for_ctrl_irq (ctrl); |
1239 | 352 | ||
1240 | /* Done with exclusive hardware access */ | 353 | /* Done with exclusive hardware access */ |
1241 | up(&ctrl->crit_sect); | 354 | up(&ctrl->crit_sect); |
1242 | } | 355 | } |
1243 | } else { | ||
1244 | set_slot_off(ctrl, p_slot); | ||
1245 | return -1; | ||
1246 | } | ||
1247 | return 0; | 356 | return 0; |
357 | |||
358 | err_exit: | ||
359 | set_slot_off(ctrl, p_slot); | ||
360 | return -1; | ||
1248 | } | 361 | } |
1249 | 362 | ||
1250 | 363 | ||
@@ -1252,55 +365,25 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl) | |||
1252 | * remove_board - Turns off slot and LED's | 365 | * remove_board - Turns off slot and LED's |
1253 | * | 366 | * |
1254 | */ | 367 | */ |
1255 | static u32 remove_board(struct pci_func *func, struct controller *ctrl) | 368 | static int remove_board(struct slot *p_slot) |
1256 | { | 369 | { |
1257 | int index; | ||
1258 | u8 skip = 0; | ||
1259 | u8 device; | 370 | u8 device; |
1260 | u8 hp_slot; | 371 | u8 hp_slot; |
1261 | u32 rc; | 372 | int rc; |
1262 | struct resource_lists res_lists; | 373 | struct controller *ctrl = p_slot->ctrl; |
1263 | struct pci_func *temp_func; | ||
1264 | struct slot *p_slot; | ||
1265 | |||
1266 | if (func == NULL) | ||
1267 | return 1; | ||
1268 | 374 | ||
1269 | if (pciehp_unconfigure_device(func)) | 375 | if (pciehp_unconfigure_device(p_slot)) |
1270 | return 1; | 376 | return 1; |
1271 | 377 | ||
1272 | device = func->device; | 378 | device = p_slot->device; |
1273 | 379 | ||
1274 | hp_slot = func->device - ctrl->slot_device_offset; | 380 | hp_slot = p_slot->device - ctrl->slot_device_offset; |
1275 | p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); | 381 | p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); |
1276 | 382 | ||
1277 | dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot); | 383 | dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot); |
1278 | 384 | ||
1279 | if ((ctrl->add_support) && | ||
1280 | !(func->bus_head || func->mem_head || func->p_mem_head || func->io_head)) { | ||
1281 | /* Here we check to see if we've saved any of the board's | ||
1282 | * resources already. If so, we'll skip the attempt to | ||
1283 | * determine what's being used. | ||
1284 | */ | ||
1285 | index = 0; | ||
1286 | |||
1287 | temp_func = func; | ||
1288 | |||
1289 | while ((temp_func = pciehp_slot_find(temp_func->bus, temp_func->device, index++))) { | ||
1290 | if (temp_func->bus_head || temp_func->mem_head | ||
1291 | || temp_func->p_mem_head || temp_func->io_head) { | ||
1292 | skip = 1; | ||
1293 | break; | ||
1294 | } | ||
1295 | } | ||
1296 | |||
1297 | if (!skip) | ||
1298 | rc = pciehp_save_used_resources(ctrl, func, DISABLE_CARD); | ||
1299 | } | ||
1300 | /* Change status to shutdown */ | 385 | /* Change status to shutdown */ |
1301 | if (func->is_a_board) | 386 | p_slot->status = 0x01; |
1302 | func->status = 0x01; | ||
1303 | func->configured = 0; | ||
1304 | 387 | ||
1305 | /* Wait for exclusive access to hardware */ | 388 | /* Wait for exclusive access to hardware */ |
1306 | down(&ctrl->crit_sect); | 389 | down(&ctrl->crit_sect); |
@@ -1328,56 +411,6 @@ static u32 remove_board(struct pci_func *func, struct controller *ctrl) | |||
1328 | /* Done with exclusive hardware access */ | 411 | /* Done with exclusive hardware access */ |
1329 | up(&ctrl->crit_sect); | 412 | up(&ctrl->crit_sect); |
1330 | 413 | ||
1331 | if (ctrl->add_support) { | ||
1332 | while (func) { | ||
1333 | res_lists.io_head = ctrl->io_head; | ||
1334 | res_lists.mem_head = ctrl->mem_head; | ||
1335 | res_lists.p_mem_head = ctrl->p_mem_head; | ||
1336 | res_lists.bus_head = ctrl->bus_head; | ||
1337 | |||
1338 | dbg("Returning resources to ctlr lists for (B/D/F) = (%#x/%#x/%#x)\n", | ||
1339 | func->bus, func->device, func->function); | ||
1340 | |||
1341 | pciehp_return_board_resources(func, &res_lists); | ||
1342 | |||
1343 | ctrl->io_head = res_lists.io_head; | ||
1344 | ctrl->mem_head = res_lists.mem_head; | ||
1345 | ctrl->p_mem_head = res_lists.p_mem_head; | ||
1346 | ctrl->bus_head = res_lists.bus_head; | ||
1347 | |||
1348 | pciehp_resource_sort_and_combine(&(ctrl->mem_head)); | ||
1349 | pciehp_resource_sort_and_combine(&(ctrl->p_mem_head)); | ||
1350 | pciehp_resource_sort_and_combine(&(ctrl->io_head)); | ||
1351 | pciehp_resource_sort_and_combine(&(ctrl->bus_head)); | ||
1352 | |||
1353 | if (is_bridge(func)) { | ||
1354 | dbg("PCI Bridge Hot-Remove s:b:d:f(%02x:%02x:%02x:%02x)\n", | ||
1355 | ctrl->seg, func->bus, func->device, func->function); | ||
1356 | bridge_slot_remove(func); | ||
1357 | } else { | ||
1358 | dbg("PCI Function Hot-Remove s:b:d:f(%02x:%02x:%02x:%02x)\n", | ||
1359 | ctrl->seg, func->bus, func->device, func->function); | ||
1360 | slot_remove(func); | ||
1361 | } | ||
1362 | |||
1363 | func = pciehp_slot_find(ctrl->slot_bus, device, 0); | ||
1364 | } | ||
1365 | |||
1366 | /* Setup slot structure with entry for empty slot */ | ||
1367 | func = pciehp_slot_create(ctrl->slot_bus); | ||
1368 | |||
1369 | if (func == NULL) { | ||
1370 | return 1; | ||
1371 | } | ||
1372 | |||
1373 | func->bus = ctrl->slot_bus; | ||
1374 | func->device = device; | ||
1375 | func->function = 0; | ||
1376 | func->configured = 0; | ||
1377 | func->switch_save = 0x10; | ||
1378 | func->is_a_board = 0; | ||
1379 | } | ||
1380 | |||
1381 | return 0; | 414 | return 0; |
1382 | } | 415 | } |
1383 | 416 | ||
@@ -1411,13 +444,15 @@ static void pciehp_pushbutton_thread(unsigned long slot) | |||
1411 | p_slot->hpc_ops->get_power_status(p_slot, &getstatus); | 444 | p_slot->hpc_ops->get_power_status(p_slot, &getstatus); |
1412 | if (getstatus) { | 445 | if (getstatus) { |
1413 | p_slot->state = POWEROFF_STATE; | 446 | p_slot->state = POWEROFF_STATE; |
1414 | dbg("In power_down_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device); | 447 | dbg("%s: disabling bus:device(%x:%x)\n", __FUNCTION__, |
448 | p_slot->bus, p_slot->device); | ||
1415 | 449 | ||
1416 | pciehp_disable_slot(p_slot); | 450 | pciehp_disable_slot(p_slot); |
1417 | p_slot->state = STATIC_STATE; | 451 | p_slot->state = STATIC_STATE; |
1418 | } else { | 452 | } else { |
1419 | p_slot->state = POWERON_STATE; | 453 | p_slot->state = POWERON_STATE; |
1420 | dbg("In add_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device); | 454 | dbg("%s: adding bus:device(%x:%x)\n", __FUNCTION__, |
455 | p_slot->bus, p_slot->device); | ||
1421 | 456 | ||
1422 | if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) { | 457 | if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) { |
1423 | /* Wait for exclusive access to hardware */ | 458 | /* Wait for exclusive access to hardware */ |
@@ -1459,13 +494,15 @@ static void pciehp_surprise_rm_thread(unsigned long slot) | |||
1459 | p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); | 494 | p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); |
1460 | if (!getstatus) { | 495 | if (!getstatus) { |
1461 | p_slot->state = POWEROFF_STATE; | 496 | p_slot->state = POWEROFF_STATE; |
1462 | dbg("In removing board, b:d(%x:%x)\n", p_slot->bus, p_slot->device); | 497 | dbg("%s: removing bus:device(%x:%x)\n", |
498 | __FUNCTION__, p_slot->bus, p_slot->device); | ||
1463 | 499 | ||
1464 | pciehp_disable_slot(p_slot); | 500 | pciehp_disable_slot(p_slot); |
1465 | p_slot->state = STATIC_STATE; | 501 | p_slot->state = STATIC_STATE; |
1466 | } else { | 502 | } else { |
1467 | p_slot->state = POWERON_STATE; | 503 | p_slot->state = POWERON_STATE; |
1468 | dbg("In add_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device); | 504 | dbg("%s: adding bus:device(%x:%x)\n", |
505 | __FUNCTION__, p_slot->bus, p_slot->device); | ||
1469 | 506 | ||
1470 | if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) { | 507 | if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) { |
1471 | /* Wait for exclusive access to hardware */ | 508 | /* Wait for exclusive access to hardware */ |
@@ -1531,7 +568,6 @@ int pciehp_event_start_thread(void) | |||
1531 | err ("Can't start up our event thread\n"); | 568 | err ("Can't start up our event thread\n"); |
1532 | return -1; | 569 | return -1; |
1533 | } | 570 | } |
1534 | dbg("Our event thread pid = %d\n", pid); | ||
1535 | return 0; | 571 | return 0; |
1536 | } | 572 | } |
1537 | 573 | ||
@@ -1539,9 +575,7 @@ int pciehp_event_start_thread(void) | |||
1539 | void pciehp_event_stop_thread(void) | 575 | void pciehp_event_stop_thread(void) |
1540 | { | 576 | { |
1541 | event_finished = 1; | 577 | event_finished = 1; |
1542 | dbg("event_thread finish command given\n"); | ||
1543 | up(&event_semaphore); | 578 | up(&event_semaphore); |
1544 | dbg("wait for event_thread to exit\n"); | ||
1545 | down(&event_exit); | 579 | down(&event_exit); |
1546 | } | 580 | } |
1547 | 581 | ||
@@ -1573,7 +607,6 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
1573 | { | 607 | { |
1574 | int loop = 0; | 608 | int loop = 0; |
1575 | int change = 1; | 609 | int change = 1; |
1576 | struct pci_func *func; | ||
1577 | u8 hp_slot; | 610 | u8 hp_slot; |
1578 | u8 getstatus; | 611 | u8 getstatus; |
1579 | struct slot *p_slot; | 612 | struct slot *p_slot; |
@@ -1581,16 +614,12 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
1581 | while (change) { | 614 | while (change) { |
1582 | change = 0; | 615 | change = 0; |
1583 | 616 | ||
1584 | for (loop = 0; loop < 10; loop++) { | 617 | for (loop = 0; loop < MAX_EVENTS; loop++) { |
1585 | if (ctrl->event_queue[loop].event_type != 0) { | 618 | if (ctrl->event_queue[loop].event_type != 0) { |
1586 | hp_slot = ctrl->event_queue[loop].hp_slot; | 619 | hp_slot = ctrl->event_queue[loop].hp_slot; |
1587 | 620 | ||
1588 | func = pciehp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0); | ||
1589 | |||
1590 | p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); | 621 | p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); |
1591 | 622 | ||
1592 | dbg("hp_slot %d, func %p, p_slot %p\n", hp_slot, func, p_slot); | ||
1593 | |||
1594 | if (ctrl->event_queue[loop].event_type == INT_BUTTON_CANCEL) { | 623 | if (ctrl->event_queue[loop].event_type == INT_BUTTON_CANCEL) { |
1595 | dbg("button cancel\n"); | 624 | dbg("button cancel\n"); |
1596 | del_timer(&p_slot->task_event); | 625 | del_timer(&p_slot->task_event); |
@@ -1682,7 +711,6 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
1682 | p_slot->task_event.function = (void (*)(unsigned long)) pushbutton_helper_thread; | 711 | p_slot->task_event.function = (void (*)(unsigned long)) pushbutton_helper_thread; |
1683 | p_slot->task_event.data = (unsigned long) p_slot; | 712 | p_slot->task_event.data = (unsigned long) p_slot; |
1684 | 713 | ||
1685 | dbg("add_timer p_slot = %p\n", (void *) p_slot); | ||
1686 | add_timer(&p_slot->task_event); | 714 | add_timer(&p_slot->task_event); |
1687 | } | 715 | } |
1688 | } | 716 | } |
@@ -1737,13 +765,6 @@ int pciehp_enable_slot(struct slot *p_slot) | |||
1737 | { | 765 | { |
1738 | u8 getstatus = 0; | 766 | u8 getstatus = 0; |
1739 | int rc; | 767 | int rc; |
1740 | struct pci_func *func; | ||
1741 | |||
1742 | func = pciehp_slot_find(p_slot->bus, p_slot->device, 0); | ||
1743 | if (!func) { | ||
1744 | dbg("%s: Error! slot NULL\n", __FUNCTION__); | ||
1745 | return 1; | ||
1746 | } | ||
1747 | 768 | ||
1748 | /* Check to see if (latch closed, card present, power off) */ | 769 | /* Check to see if (latch closed, card present, power off) */ |
1749 | down(&p_slot->ctrl->crit_sect); | 770 | down(&p_slot->ctrl->crit_sect); |
@@ -1773,45 +794,11 @@ int pciehp_enable_slot(struct slot *p_slot) | |||
1773 | } | 794 | } |
1774 | up(&p_slot->ctrl->crit_sect); | 795 | up(&p_slot->ctrl->crit_sect); |
1775 | 796 | ||
1776 | slot_remove(func); | ||
1777 | |||
1778 | func = pciehp_slot_create(p_slot->bus); | ||
1779 | if (func == NULL) | ||
1780 | return 1; | ||
1781 | |||
1782 | func->bus = p_slot->bus; | ||
1783 | func->device = p_slot->device; | ||
1784 | func->function = 0; | ||
1785 | func->configured = 0; | ||
1786 | func->is_a_board = 1; | ||
1787 | |||
1788 | /* We have to save the presence info for these slots */ | ||
1789 | p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save)); | ||
1790 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); | 797 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); |
1791 | func->switch_save = !getstatus? 0x10:0; | ||
1792 | 798 | ||
1793 | rc = board_added(func, p_slot->ctrl); | 799 | rc = board_added(p_slot); |
1794 | if (rc) { | 800 | if (rc) { |
1795 | if (is_bridge(func)) | ||
1796 | bridge_slot_remove(func); | ||
1797 | else | ||
1798 | slot_remove(func); | ||
1799 | |||
1800 | /* Setup slot structure with entry for empty slot */ | ||
1801 | func = pciehp_slot_create(p_slot->bus); | ||
1802 | if (func == NULL) | ||
1803 | return 1; /* Out of memory */ | ||
1804 | |||
1805 | func->bus = p_slot->bus; | ||
1806 | func->device = p_slot->device; | ||
1807 | func->function = 0; | ||
1808 | func->configured = 0; | ||
1809 | func->is_a_board = 1; | ||
1810 | |||
1811 | /* We have to save the presence info for these slots */ | ||
1812 | p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save)); | ||
1813 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); | 801 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); |
1814 | func->switch_save = !getstatus? 0x10:0; | ||
1815 | } | 802 | } |
1816 | 803 | ||
1817 | if (p_slot) | 804 | if (p_slot) |
@@ -1823,14 +810,8 @@ int pciehp_enable_slot(struct slot *p_slot) | |||
1823 | 810 | ||
1824 | int pciehp_disable_slot(struct slot *p_slot) | 811 | int pciehp_disable_slot(struct slot *p_slot) |
1825 | { | 812 | { |
1826 | u8 class_code, header_type, BCR; | ||
1827 | u8 index = 0; | ||
1828 | u8 getstatus = 0; | 813 | u8 getstatus = 0; |
1829 | u32 rc = 0; | ||
1830 | int ret = 0; | 814 | int ret = 0; |
1831 | unsigned int devfn; | ||
1832 | struct pci_bus *pci_bus = p_slot->ctrl->pci_dev->subordinate; | ||
1833 | struct pci_func *func; | ||
1834 | 815 | ||
1835 | if (!p_slot->ctrl) | 816 | if (!p_slot->ctrl) |
1836 | return 1; | 817 | return 1; |
@@ -1867,838 +848,8 @@ int pciehp_disable_slot(struct slot *p_slot) | |||
1867 | 848 | ||
1868 | up(&p_slot->ctrl->crit_sect); | 849 | up(&p_slot->ctrl->crit_sect); |
1869 | 850 | ||
1870 | func = pciehp_slot_find(p_slot->bus, p_slot->device, index++); | 851 | ret = remove_board(p_slot); |
1871 | 852 | update_slot_info(p_slot); | |
1872 | /* Make sure there are no video controllers here | 853 | return ret; |
1873 | * for all func of p_slot | ||
1874 | */ | ||
1875 | while (func && !rc) { | ||
1876 | pci_bus->number = func->bus; | ||
1877 | devfn = PCI_DEVFN(func->device, func->function); | ||
1878 | |||
1879 | /* Check the Class Code */ | ||
1880 | rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code); | ||
1881 | if (rc) | ||
1882 | return rc; | ||
1883 | |||
1884 | if (class_code == PCI_BASE_CLASS_DISPLAY) { | ||
1885 | /* Display/Video adapter (not supported) */ | ||
1886 | rc = REMOVE_NOT_SUPPORTED; | ||
1887 | } else { | ||
1888 | /* See if it's a bridge */ | ||
1889 | rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type); | ||
1890 | if (rc) | ||
1891 | return rc; | ||
1892 | |||
1893 | /* If it's a bridge, check the VGA Enable bit */ | ||
1894 | if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { | ||
1895 | rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_BRIDGE_CONTROL, &BCR); | ||
1896 | if (rc) | ||
1897 | return rc; | ||
1898 | |||
1899 | /* If the VGA Enable bit is set, remove isn't supported */ | ||
1900 | if (BCR & PCI_BRIDGE_CTL_VGA) { | ||
1901 | rc = REMOVE_NOT_SUPPORTED; | ||
1902 | } | ||
1903 | } | ||
1904 | } | ||
1905 | |||
1906 | func = pciehp_slot_find(p_slot->bus, p_slot->device, index++); | ||
1907 | } | ||
1908 | |||
1909 | func = pciehp_slot_find(p_slot->bus, p_slot->device, 0); | ||
1910 | if ((func != NULL) && !rc) { | ||
1911 | rc = remove_board(func, p_slot->ctrl); | ||
1912 | } else if (!rc) | ||
1913 | rc = 1; | ||
1914 | |||
1915 | if (p_slot) | ||
1916 | update_slot_info(p_slot); | ||
1917 | |||
1918 | return rc; | ||
1919 | } | ||
1920 | |||
1921 | |||
1922 | /** | ||
1923 | * configure_new_device - Configures the PCI header information of one board. | ||
1924 | * | ||
1925 | * @ctrl: pointer to controller structure | ||
1926 | * @func: pointer to function structure | ||
1927 | * @behind_bridge: 1 if this is a recursive call, 0 if not | ||
1928 | * @resources: pointer to set of resource lists | ||
1929 | * | ||
1930 | * Returns 0 if success | ||
1931 | * | ||
1932 | */ | ||
1933 | static u32 configure_new_device(struct controller * ctrl, struct pci_func * func, | ||
1934 | u8 behind_bridge, struct resource_lists * resources, u8 bridge_bus, u8 bridge_dev) | ||
1935 | { | ||
1936 | u8 temp_byte, function, max_functions, stop_it; | ||
1937 | int rc; | ||
1938 | u32 ID; | ||
1939 | struct pci_func *new_slot; | ||
1940 | struct pci_bus lpci_bus, *pci_bus; | ||
1941 | int index; | ||
1942 | |||
1943 | new_slot = func; | ||
1944 | |||
1945 | dbg("%s\n", __FUNCTION__); | ||
1946 | memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus)); | ||
1947 | pci_bus = &lpci_bus; | ||
1948 | pci_bus->number = func->bus; | ||
1949 | |||
1950 | /* Check for Multi-function device */ | ||
1951 | rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(func->device, func->function), 0x0E, &temp_byte); | ||
1952 | if (rc) { | ||
1953 | dbg("%s: rc = %d\n", __FUNCTION__, rc); | ||
1954 | return rc; | ||
1955 | } | ||
1956 | |||
1957 | if (temp_byte & 0x80) /* Multi-function device */ | ||
1958 | max_functions = 8; | ||
1959 | else | ||
1960 | max_functions = 1; | ||
1961 | |||
1962 | function = 0; | ||
1963 | |||
1964 | do { | ||
1965 | rc = configure_new_function(ctrl, new_slot, behind_bridge, | ||
1966 | resources, bridge_bus, bridge_dev); | ||
1967 | |||
1968 | if (rc) { | ||
1969 | dbg("configure_new_function failed: %d\n", rc); | ||
1970 | index = 0; | ||
1971 | |||
1972 | while (new_slot) { | ||
1973 | new_slot = pciehp_slot_find(new_slot->bus, | ||
1974 | new_slot->device, index++); | ||
1975 | |||
1976 | if (new_slot) | ||
1977 | pciehp_return_board_resources(new_slot, | ||
1978 | resources); | ||
1979 | } | ||
1980 | |||
1981 | return rc; | ||
1982 | } | ||
1983 | |||
1984 | function++; | ||
1985 | |||
1986 | stop_it = 0; | ||
1987 | |||
1988 | /* The following loop skips to the next present function | ||
1989 | * and creates a board structure | ||
1990 | */ | ||
1991 | |||
1992 | while ((function < max_functions) && (!stop_it)) { | ||
1993 | pci_bus_read_config_dword(pci_bus, PCI_DEVFN(func->device, function), 0x00, &ID); | ||
1994 | |||
1995 | if (ID == 0xFFFFFFFF) { /* There's nothing there. */ | ||
1996 | function++; | ||
1997 | } else { /* There's something there */ | ||
1998 | /* Setup slot structure. */ | ||
1999 | new_slot = pciehp_slot_create(func->bus); | ||
2000 | |||
2001 | if (new_slot == NULL) { | ||
2002 | /* Out of memory */ | ||
2003 | return 1; | ||
2004 | } | ||
2005 | |||
2006 | new_slot->bus = func->bus; | ||
2007 | new_slot->device = func->device; | ||
2008 | new_slot->function = function; | ||
2009 | new_slot->is_a_board = 1; | ||
2010 | new_slot->status = 0; | ||
2011 | |||
2012 | stop_it++; | ||
2013 | } | ||
2014 | } | ||
2015 | |||
2016 | } while (function < max_functions); | ||
2017 | dbg("returning from %s\n", __FUNCTION__); | ||
2018 | |||
2019 | return 0; | ||
2020 | } | ||
2021 | |||
2022 | /* | ||
2023 | * Configuration logic that involves the hotplug data structures and | ||
2024 | * their bookkeeping | ||
2025 | */ | ||
2026 | |||
2027 | /** | ||
2028 | * configure_bridge: fill bridge's registers, either configure or disable it. | ||
2029 | */ | ||
2030 | static int | ||
2031 | configure_bridge(struct pci_bus *pci_bus, unsigned int devfn, | ||
2032 | struct pci_resource *mem_node, | ||
2033 | struct pci_resource **hold_mem_node, | ||
2034 | int base_addr, int limit_addr) | ||
2035 | { | ||
2036 | u16 temp_word; | ||
2037 | u32 rc; | ||
2038 | |||
2039 | if (mem_node) { | ||
2040 | memcpy(*hold_mem_node, mem_node, sizeof(struct pci_resource)); | ||
2041 | mem_node->next = NULL; | ||
2042 | |||
2043 | /* set Mem base and Limit registers */ | ||
2044 | RES_CHECK(mem_node->base, 16); | ||
2045 | temp_word = (u16)(mem_node->base >> 16); | ||
2046 | rc = pci_bus_write_config_word(pci_bus, devfn, base_addr, temp_word); | ||
2047 | |||
2048 | RES_CHECK(mem_node->base + mem_node->length - 1, 16); | ||
2049 | temp_word = (u16)((mem_node->base + mem_node->length - 1) >> 16); | ||
2050 | rc = pci_bus_write_config_word(pci_bus, devfn, limit_addr, temp_word); | ||
2051 | } else { | ||
2052 | temp_word = 0xFFFF; | ||
2053 | rc = pci_bus_write_config_word(pci_bus, devfn, base_addr, temp_word); | ||
2054 | |||
2055 | temp_word = 0x0000; | ||
2056 | rc = pci_bus_write_config_word(pci_bus, devfn, limit_addr, temp_word); | ||
2057 | |||
2058 | kfree(*hold_mem_node); | ||
2059 | *hold_mem_node = NULL; | ||
2060 | } | ||
2061 | return rc; | ||
2062 | } | ||
2063 | |||
2064 | static int | ||
2065 | configure_new_bridge(struct controller *ctrl, struct pci_func *func, | ||
2066 | u8 behind_bridge, struct resource_lists *resources, | ||
2067 | struct pci_bus *pci_bus) | ||
2068 | { | ||
2069 | int cloop; | ||
2070 | u8 temp_byte; | ||
2071 | u8 device; | ||
2072 | u16 temp_word; | ||
2073 | u32 rc; | ||
2074 | u32 ID; | ||
2075 | unsigned int devfn; | ||
2076 | struct pci_resource *mem_node; | ||
2077 | struct pci_resource *p_mem_node; | ||
2078 | struct pci_resource *io_node; | ||
2079 | struct pci_resource *bus_node; | ||
2080 | struct pci_resource *hold_mem_node; | ||
2081 | struct pci_resource *hold_p_mem_node; | ||
2082 | struct pci_resource *hold_IO_node; | ||
2083 | struct pci_resource *hold_bus_node; | ||
2084 | struct irq_mapping irqs; | ||
2085 | struct pci_func *new_slot; | ||
2086 | struct resource_lists temp_resources; | ||
2087 | |||
2088 | devfn = PCI_DEVFN(func->device, func->function); | ||
2089 | |||
2090 | /* set Primary bus */ | ||
2091 | dbg("set Primary bus = 0x%x\n", func->bus); | ||
2092 | rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_PRIMARY_BUS, func->bus); | ||
2093 | if (rc) | ||
2094 | return rc; | ||
2095 | |||
2096 | /* find range of busses to use */ | ||
2097 | bus_node = get_max_resource(&resources->bus_head, 1L); | ||
2098 | |||
2099 | /* If we don't have any busses to allocate, we can't continue */ | ||
2100 | if (!bus_node) { | ||
2101 | err("Got NO bus resource to use\n"); | ||
2102 | return -ENOMEM; | ||
2103 | } | ||
2104 | dbg("Got ranges of buses to use: base:len=0x%x:%x\n", bus_node->base, bus_node->length); | ||
2105 | |||
2106 | /* set Secondary bus */ | ||
2107 | temp_byte = (u8)bus_node->base; | ||
2108 | dbg("set Secondary bus = 0x%x\n", temp_byte); | ||
2109 | rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_SECONDARY_BUS, temp_byte); | ||
2110 | if (rc) | ||
2111 | return rc; | ||
2112 | |||
2113 | /* set subordinate bus */ | ||
2114 | temp_byte = (u8)(bus_node->base + bus_node->length - 1); | ||
2115 | dbg("set subordinate bus = 0x%x\n", temp_byte); | ||
2116 | rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_SUBORDINATE_BUS, temp_byte); | ||
2117 | if (rc) | ||
2118 | return rc; | ||
2119 | |||
2120 | /* Set HP parameters (Cache Line Size, Latency Timer) */ | ||
2121 | rc = pciehprm_set_hpp(ctrl, func, PCI_HEADER_TYPE_BRIDGE); | ||
2122 | if (rc) | ||
2123 | return rc; | ||
2124 | |||
2125 | /* Setup the IO, memory, and prefetchable windows */ | ||
2126 | |||
2127 | io_node = get_max_resource(&(resources->io_head), 0x1000L); | ||
2128 | if (io_node) { | ||
2129 | dbg("io_node(base, len, next) (%x, %x, %p)\n", io_node->base, | ||
2130 | io_node->length, io_node->next); | ||
2131 | } | ||
2132 | |||
2133 | mem_node = get_max_resource(&(resources->mem_head), 0x100000L); | ||
2134 | if (mem_node) { | ||
2135 | dbg("mem_node(base, len, next) (%x, %x, %p)\n", mem_node->base, | ||
2136 | mem_node->length, mem_node->next); | ||
2137 | } | ||
2138 | |||
2139 | if (resources->p_mem_head) | ||
2140 | p_mem_node = get_max_resource(&(resources->p_mem_head), 0x100000L); | ||
2141 | else { | ||
2142 | /* | ||
2143 | * In some platform implementation, MEM and PMEM are not | ||
2144 | * distinguished, and hence ACPI _CRS has only MEM entries | ||
2145 | * for both MEM and PMEM. | ||
2146 | */ | ||
2147 | dbg("using MEM for PMEM\n"); | ||
2148 | p_mem_node = get_max_resource(&(resources->mem_head), 0x100000L); | ||
2149 | } | ||
2150 | if (p_mem_node) { | ||
2151 | dbg("p_mem_node(base, len, next) (%x, %x, %p)\n", p_mem_node->base, | ||
2152 | p_mem_node->length, p_mem_node->next); | ||
2153 | } | ||
2154 | |||
2155 | /* set up the IRQ info */ | ||
2156 | if (!resources->irqs) { | ||
2157 | irqs.barber_pole = 0; | ||
2158 | irqs.interrupt[0] = 0; | ||
2159 | irqs.interrupt[1] = 0; | ||
2160 | irqs.interrupt[2] = 0; | ||
2161 | irqs.interrupt[3] = 0; | ||
2162 | irqs.valid_INT = 0; | ||
2163 | } else { | ||
2164 | irqs.barber_pole = resources->irqs->barber_pole; | ||
2165 | irqs.interrupt[0] = resources->irqs->interrupt[0]; | ||
2166 | irqs.interrupt[1] = resources->irqs->interrupt[1]; | ||
2167 | irqs.interrupt[2] = resources->irqs->interrupt[2]; | ||
2168 | irqs.interrupt[3] = resources->irqs->interrupt[3]; | ||
2169 | irqs.valid_INT = resources->irqs->valid_INT; | ||
2170 | } | ||
2171 | |||
2172 | /* set up resource lists that are now aligned on top and bottom | ||
2173 | * for anything behind the bridge. | ||
2174 | */ | ||
2175 | temp_resources.bus_head = bus_node; | ||
2176 | temp_resources.io_head = io_node; | ||
2177 | temp_resources.mem_head = mem_node; | ||
2178 | temp_resources.p_mem_head = p_mem_node; | ||
2179 | temp_resources.irqs = &irqs; | ||
2180 | |||
2181 | /* Make copies of the nodes we are going to pass down so that | ||
2182 | * if there is a problem,we can just use these to free resources | ||
2183 | */ | ||
2184 | hold_bus_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL); | ||
2185 | hold_IO_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL); | ||
2186 | hold_mem_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL); | ||
2187 | hold_p_mem_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL); | ||
2188 | |||
2189 | if (!hold_bus_node || !hold_IO_node || !hold_mem_node || !hold_p_mem_node) { | ||
2190 | kfree(hold_bus_node); | ||
2191 | kfree(hold_IO_node); | ||
2192 | kfree(hold_mem_node); | ||
2193 | kfree(hold_p_mem_node); | ||
2194 | |||
2195 | return 1; | ||
2196 | } | ||
2197 | |||
2198 | memcpy(hold_bus_node, bus_node, sizeof(struct pci_resource)); | ||
2199 | |||
2200 | bus_node->base += 1; | ||
2201 | bus_node->length -= 1; | ||
2202 | bus_node->next = NULL; | ||
2203 | |||
2204 | /* If we have IO resources copy them and fill in the bridge's | ||
2205 | * IO range registers | ||
2206 | */ | ||
2207 | if (io_node) { | ||
2208 | memcpy(hold_IO_node, io_node, sizeof(struct pci_resource)); | ||
2209 | io_node->next = NULL; | ||
2210 | |||
2211 | /* set IO base and Limit registers */ | ||
2212 | RES_CHECK(io_node->base, 8); | ||
2213 | temp_byte = (u8)(io_node->base >> 8); | ||
2214 | rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_BASE, temp_byte); | ||
2215 | |||
2216 | RES_CHECK(io_node->base + io_node->length - 1, 8); | ||
2217 | temp_byte = (u8)((io_node->base + io_node->length - 1) >> 8); | ||
2218 | rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_LIMIT, temp_byte); | ||
2219 | } else { | ||
2220 | kfree(hold_IO_node); | ||
2221 | hold_IO_node = NULL; | ||
2222 | } | ||
2223 | |||
2224 | /* If we have memory resources copy them and fill in the bridge's | ||
2225 | * memory range registers. Otherwise, fill in the range | ||
2226 | * registers with values that disable them. | ||
2227 | */ | ||
2228 | rc = configure_bridge(pci_bus, devfn, mem_node, &hold_mem_node, | ||
2229 | PCI_MEMORY_BASE, PCI_MEMORY_LIMIT); | ||
2230 | |||
2231 | /* If we have prefetchable memory resources copy them and | ||
2232 | * fill in the bridge's memory range registers. Otherwise, | ||
2233 | * fill in the range registers with values that disable them. | ||
2234 | */ | ||
2235 | rc = configure_bridge(pci_bus, devfn, p_mem_node, &hold_p_mem_node, | ||
2236 | PCI_PREF_MEMORY_BASE, PCI_PREF_MEMORY_LIMIT); | ||
2237 | |||
2238 | /* Adjust this to compensate for extra adjustment in first loop */ | ||
2239 | irqs.barber_pole--; | ||
2240 | |||
2241 | rc = 0; | ||
2242 | |||
2243 | /* Here we actually find the devices and configure them */ | ||
2244 | for (device = 0; (device <= 0x1F) && !rc; device++) { | ||
2245 | irqs.barber_pole = (irqs.barber_pole + 1) & 0x03; | ||
2246 | |||
2247 | ID = 0xFFFFFFFF; | ||
2248 | pci_bus->number = hold_bus_node->base; | ||
2249 | pci_bus_read_config_dword (pci_bus, PCI_DEVFN(device, 0), PCI_VENDOR_ID, &ID); | ||
2250 | pci_bus->number = func->bus; | ||
2251 | |||
2252 | if (ID != 0xFFFFFFFF) { /* device Present */ | ||
2253 | /* Setup slot structure. */ | ||
2254 | new_slot = pciehp_slot_create(hold_bus_node->base); | ||
2255 | |||
2256 | if (new_slot == NULL) { | ||
2257 | /* Out of memory */ | ||
2258 | rc = -ENOMEM; | ||
2259 | continue; | ||
2260 | } | ||
2261 | |||
2262 | new_slot->bus = hold_bus_node->base; | ||
2263 | new_slot->device = device; | ||
2264 | new_slot->function = 0; | ||
2265 | new_slot->is_a_board = 1; | ||
2266 | new_slot->status = 0; | ||
2267 | |||
2268 | rc = configure_new_device(ctrl, new_slot, 1, | ||
2269 | &temp_resources, func->bus, | ||
2270 | func->device); | ||
2271 | dbg("configure_new_device rc=0x%x\n",rc); | ||
2272 | } /* End of IF (device in slot?) */ | ||
2273 | } /* End of FOR loop */ | ||
2274 | |||
2275 | if (rc) { | ||
2276 | pciehp_destroy_resource_list(&temp_resources); | ||
2277 | |||
2278 | return_resource(&(resources->bus_head), hold_bus_node); | ||
2279 | return_resource(&(resources->io_head), hold_IO_node); | ||
2280 | return_resource(&(resources->mem_head), hold_mem_node); | ||
2281 | return_resource(&(resources->p_mem_head), hold_p_mem_node); | ||
2282 | return(rc); | ||
2283 | } | ||
2284 | |||
2285 | /* save the interrupt routing information */ | ||
2286 | if (resources->irqs) { | ||
2287 | resources->irqs->interrupt[0] = irqs.interrupt[0]; | ||
2288 | resources->irqs->interrupt[1] = irqs.interrupt[1]; | ||
2289 | resources->irqs->interrupt[2] = irqs.interrupt[2]; | ||
2290 | resources->irqs->interrupt[3] = irqs.interrupt[3]; | ||
2291 | resources->irqs->valid_INT = irqs.valid_INT; | ||
2292 | } else if (!behind_bridge) { | ||
2293 | /* We need to hook up the interrupts here */ | ||
2294 | for (cloop = 0; cloop < 4; cloop++) { | ||
2295 | if (irqs.valid_INT & (0x01 << cloop)) { | ||
2296 | rc = pciehp_set_irq(func->bus, func->device, | ||
2297 | 0x0A + cloop, irqs.interrupt[cloop]); | ||
2298 | if (rc) { | ||
2299 | pciehp_destroy_resource_list (&temp_resources); | ||
2300 | return_resource(&(resources->bus_head), hold_bus_node); | ||
2301 | return_resource(&(resources->io_head), hold_IO_node); | ||
2302 | return_resource(&(resources->mem_head), hold_mem_node); | ||
2303 | return_resource(&(resources->p_mem_head), hold_p_mem_node); | ||
2304 | return rc; | ||
2305 | } | ||
2306 | } | ||
2307 | } /* end of for loop */ | ||
2308 | } | ||
2309 | |||
2310 | /* Return unused bus resources | ||
2311 | * First use the temporary node to store information for the board | ||
2312 | */ | ||
2313 | if (hold_bus_node && bus_node && temp_resources.bus_head) { | ||
2314 | hold_bus_node->length = bus_node->base - hold_bus_node->base; | ||
2315 | |||
2316 | hold_bus_node->next = func->bus_head; | ||
2317 | func->bus_head = hold_bus_node; | ||
2318 | |||
2319 | temp_byte = (u8)(temp_resources.bus_head->base - 1); | ||
2320 | |||
2321 | /* set subordinate bus */ | ||
2322 | dbg("re-set subordinate bus = 0x%x\n", temp_byte); | ||
2323 | rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_SUBORDINATE_BUS, temp_byte); | ||
2324 | |||
2325 | if (temp_resources.bus_head->length == 0) { | ||
2326 | kfree(temp_resources.bus_head); | ||
2327 | temp_resources.bus_head = NULL; | ||
2328 | } else { | ||
2329 | dbg("return bus res of b:d(0x%x:%x) base:len(0x%x:%x)\n", | ||
2330 | func->bus, func->device, temp_resources.bus_head->base, temp_resources.bus_head->length); | ||
2331 | return_resource(&(resources->bus_head), temp_resources.bus_head); | ||
2332 | } | ||
2333 | } | ||
2334 | |||
2335 | /* If we have IO space available and there is some left, | ||
2336 | * return the unused portion | ||
2337 | */ | ||
2338 | if (hold_IO_node && temp_resources.io_head) { | ||
2339 | io_node = do_pre_bridge_resource_split(&(temp_resources.io_head), | ||
2340 | &hold_IO_node, 0x1000); | ||
2341 | |||
2342 | /* Check if we were able to split something off */ | ||
2343 | if (io_node) { | ||
2344 | hold_IO_node->base = io_node->base + io_node->length; | ||
2345 | |||
2346 | RES_CHECK(hold_IO_node->base, 8); | ||
2347 | temp_byte = (u8)((hold_IO_node->base) >> 8); | ||
2348 | rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_BASE, temp_byte); | ||
2349 | |||
2350 | return_resource(&(resources->io_head), io_node); | ||
2351 | } | ||
2352 | |||
2353 | io_node = do_bridge_resource_split(&(temp_resources.io_head), 0x1000); | ||
2354 | |||
2355 | /* Check if we were able to split something off */ | ||
2356 | if (io_node) { | ||
2357 | /* First use the temporary node to store information for the board */ | ||
2358 | hold_IO_node->length = io_node->base - hold_IO_node->base; | ||
2359 | |||
2360 | /* If we used any, add it to the board's list */ | ||
2361 | if (hold_IO_node->length) { | ||
2362 | hold_IO_node->next = func->io_head; | ||
2363 | func->io_head = hold_IO_node; | ||
2364 | |||
2365 | RES_CHECK(io_node->base - 1, 8); | ||
2366 | temp_byte = (u8)((io_node->base - 1) >> 8); | ||
2367 | rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_LIMIT, temp_byte); | ||
2368 | |||
2369 | return_resource(&(resources->io_head), io_node); | ||
2370 | } else { | ||
2371 | /* it doesn't need any IO */ | ||
2372 | temp_byte = 0x00; | ||
2373 | rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_LIMIT, temp_byte); | ||
2374 | |||
2375 | return_resource(&(resources->io_head), io_node); | ||
2376 | kfree(hold_IO_node); | ||
2377 | } | ||
2378 | } else { | ||
2379 | /* it used most of the range */ | ||
2380 | hold_IO_node->next = func->io_head; | ||
2381 | func->io_head = hold_IO_node; | ||
2382 | } | ||
2383 | } else if (hold_IO_node) { | ||
2384 | /* it used the whole range */ | ||
2385 | hold_IO_node->next = func->io_head; | ||
2386 | func->io_head = hold_IO_node; | ||
2387 | } | ||
2388 | |||
2389 | /* If we have memory space available and there is some left, | ||
2390 | * return the unused portion | ||
2391 | */ | ||
2392 | if (hold_mem_node && temp_resources.mem_head) { | ||
2393 | mem_node = do_pre_bridge_resource_split(&(temp_resources.mem_head), &hold_mem_node, 0x100000L); | ||
2394 | |||
2395 | /* Check if we were able to split something off */ | ||
2396 | if (mem_node) { | ||
2397 | hold_mem_node->base = mem_node->base + mem_node->length; | ||
2398 | |||
2399 | RES_CHECK(hold_mem_node->base, 16); | ||
2400 | temp_word = (u16)((hold_mem_node->base) >> 16); | ||
2401 | rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_BASE, temp_word); | ||
2402 | |||
2403 | return_resource(&(resources->mem_head), mem_node); | ||
2404 | } | ||
2405 | |||
2406 | mem_node = do_bridge_resource_split(&(temp_resources.mem_head), 0x100000L); | ||
2407 | |||
2408 | /* Check if we were able to split something off */ | ||
2409 | if (mem_node) { | ||
2410 | /* First use the temporary node to store information for the board */ | ||
2411 | hold_mem_node->length = mem_node->base - hold_mem_node->base; | ||
2412 | |||
2413 | if (hold_mem_node->length) { | ||
2414 | hold_mem_node->next = func->mem_head; | ||
2415 | func->mem_head = hold_mem_node; | ||
2416 | |||
2417 | /* configure end address */ | ||
2418 | RES_CHECK(mem_node->base - 1, 16); | ||
2419 | temp_word = (u16)((mem_node->base - 1) >> 16); | ||
2420 | rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word); | ||
2421 | |||
2422 | /* Return unused resources to the pool */ | ||
2423 | return_resource(&(resources->mem_head), mem_node); | ||
2424 | } else { | ||
2425 | /* it doesn't need any Mem */ | ||
2426 | temp_word = 0x0000; | ||
2427 | rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word); | ||
2428 | |||
2429 | return_resource(&(resources->mem_head), mem_node); | ||
2430 | kfree(hold_mem_node); | ||
2431 | } | ||
2432 | } else { | ||
2433 | /* it used most of the range */ | ||
2434 | hold_mem_node->next = func->mem_head; | ||
2435 | func->mem_head = hold_mem_node; | ||
2436 | } | ||
2437 | } else if (hold_mem_node) { | ||
2438 | /* it used the whole range */ | ||
2439 | hold_mem_node->next = func->mem_head; | ||
2440 | func->mem_head = hold_mem_node; | ||
2441 | } | ||
2442 | |||
2443 | /* If we have prefetchable memory space available and there is some | ||
2444 | * left at the end, return the unused portion | ||
2445 | */ | ||
2446 | if (hold_p_mem_node && temp_resources.p_mem_head) { | ||
2447 | p_mem_node = do_pre_bridge_resource_split(&(temp_resources.p_mem_head), | ||
2448 | &hold_p_mem_node, 0x100000L); | ||
2449 | |||
2450 | /* Check if we were able to split something off */ | ||
2451 | if (p_mem_node) { | ||
2452 | hold_p_mem_node->base = p_mem_node->base + p_mem_node->length; | ||
2453 | |||
2454 | RES_CHECK(hold_p_mem_node->base, 16); | ||
2455 | temp_word = (u16)((hold_p_mem_node->base) >> 16); | ||
2456 | rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word); | ||
2457 | |||
2458 | return_resource(&(resources->p_mem_head), p_mem_node); | ||
2459 | } | ||
2460 | |||
2461 | p_mem_node = do_bridge_resource_split(&(temp_resources.p_mem_head), 0x100000L); | ||
2462 | |||
2463 | /* Check if we were able to split something off */ | ||
2464 | if (p_mem_node) { | ||
2465 | /* First use the temporary node to store information for the board */ | ||
2466 | hold_p_mem_node->length = p_mem_node->base - hold_p_mem_node->base; | ||
2467 | |||
2468 | /* If we used any, add it to the board's list */ | ||
2469 | if (hold_p_mem_node->length) { | ||
2470 | hold_p_mem_node->next = func->p_mem_head; | ||
2471 | func->p_mem_head = hold_p_mem_node; | ||
2472 | |||
2473 | RES_CHECK(p_mem_node->base - 1, 16); | ||
2474 | temp_word = (u16)((p_mem_node->base - 1) >> 16); | ||
2475 | rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word); | ||
2476 | |||
2477 | return_resource(&(resources->p_mem_head), p_mem_node); | ||
2478 | } else { | ||
2479 | /* it doesn't need any PMem */ | ||
2480 | temp_word = 0x0000; | ||
2481 | rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word); | ||
2482 | |||
2483 | return_resource(&(resources->p_mem_head), p_mem_node); | ||
2484 | kfree(hold_p_mem_node); | ||
2485 | } | ||
2486 | } else { | ||
2487 | /* it used the most of the range */ | ||
2488 | hold_p_mem_node->next = func->p_mem_head; | ||
2489 | func->p_mem_head = hold_p_mem_node; | ||
2490 | } | ||
2491 | } else if (hold_p_mem_node) { | ||
2492 | /* it used the whole range */ | ||
2493 | hold_p_mem_node->next = func->p_mem_head; | ||
2494 | func->p_mem_head = hold_p_mem_node; | ||
2495 | } | ||
2496 | |||
2497 | /* We should be configuring an IRQ and the bridge's base address | ||
2498 | * registers if it needs them. Although we have never seen such | ||
2499 | * a device | ||
2500 | */ | ||
2501 | |||
2502 | pciehprm_enable_card(ctrl, func, PCI_HEADER_TYPE_BRIDGE); | ||
2503 | |||
2504 | dbg("PCI Bridge Hot-Added s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus, func->device, func->function); | ||
2505 | |||
2506 | return rc; | ||
2507 | } | 854 | } |
2508 | 855 | ||
2509 | /** | ||
2510 | * configure_new_function - Configures the PCI header information of one device | ||
2511 | * | ||
2512 | * @ctrl: pointer to controller structure | ||
2513 | * @func: pointer to function structure | ||
2514 | * @behind_bridge: 1 if this is a recursive call, 0 if not | ||
2515 | * @resources: pointer to set of resource lists | ||
2516 | * | ||
2517 | * Calls itself recursively for bridged devices. | ||
2518 | * Returns 0 if success | ||
2519 | * | ||
2520 | */ | ||
2521 | static int | ||
2522 | configure_new_function(struct controller *ctrl, struct pci_func *func, | ||
2523 | u8 behind_bridge, struct resource_lists *resources, | ||
2524 | u8 bridge_bus, u8 bridge_dev) | ||
2525 | { | ||
2526 | int cloop; | ||
2527 | u8 temp_byte; | ||
2528 | u8 class_code; | ||
2529 | u32 rc; | ||
2530 | u32 temp_register; | ||
2531 | u32 base; | ||
2532 | unsigned int devfn; | ||
2533 | struct pci_resource *mem_node; | ||
2534 | struct pci_resource *io_node; | ||
2535 | struct pci_bus lpci_bus, *pci_bus; | ||
2536 | |||
2537 | memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus)); | ||
2538 | pci_bus = &lpci_bus; | ||
2539 | pci_bus->number = func->bus; | ||
2540 | devfn = PCI_DEVFN(func->device, func->function); | ||
2541 | |||
2542 | /* Check for Bridge */ | ||
2543 | rc = pci_bus_read_config_byte(pci_bus, devfn, PCI_HEADER_TYPE, &temp_byte); | ||
2544 | if (rc) | ||
2545 | return rc; | ||
2546 | dbg("%s: bus %x dev %x func %x temp_byte = %x\n", __FUNCTION__, | ||
2547 | func->bus, func->device, func->function, temp_byte); | ||
2548 | |||
2549 | if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */ | ||
2550 | rc = configure_new_bridge(ctrl, func, behind_bridge, resources, | ||
2551 | pci_bus); | ||
2552 | |||
2553 | if (rc) | ||
2554 | return rc; | ||
2555 | } else if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_NORMAL) { | ||
2556 | /* Standard device */ | ||
2557 | u64 base64; | ||
2558 | rc = pci_bus_read_config_byte(pci_bus, devfn, 0x0B, &class_code); | ||
2559 | |||
2560 | if (class_code == PCI_BASE_CLASS_DISPLAY) | ||
2561 | return DEVICE_TYPE_NOT_SUPPORTED; | ||
2562 | |||
2563 | /* Figure out IO and memory needs */ | ||
2564 | for (cloop = PCI_BASE_ADDRESS_0; cloop <= PCI_BASE_ADDRESS_5; cloop += 4) { | ||
2565 | temp_register = 0xFFFFFFFF; | ||
2566 | |||
2567 | rc = pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register); | ||
2568 | rc = pci_bus_read_config_dword(pci_bus, devfn, cloop, &temp_register); | ||
2569 | dbg("Bar[%x]=0x%x on bus:dev:func(0x%x:%x:%x)\n", cloop, temp_register, | ||
2570 | func->bus, func->device, func->function); | ||
2571 | |||
2572 | if (!temp_register) | ||
2573 | continue; | ||
2574 | |||
2575 | base64 = 0L; | ||
2576 | if (temp_register & PCI_BASE_ADDRESS_SPACE_IO) { | ||
2577 | /* Map IO */ | ||
2578 | |||
2579 | /* set base = amount of IO space */ | ||
2580 | base = temp_register & 0xFFFFFFFC; | ||
2581 | base = ~base + 1; | ||
2582 | |||
2583 | dbg("NEED IO length(0x%x)\n", base); | ||
2584 | io_node = get_io_resource(&(resources->io_head),(ulong)base); | ||
2585 | |||
2586 | /* allocate the resource to the board */ | ||
2587 | if (io_node) { | ||
2588 | dbg("Got IO base=0x%x(length=0x%x)\n", io_node->base, io_node->length); | ||
2589 | base = (u32)io_node->base; | ||
2590 | io_node->next = func->io_head; | ||
2591 | func->io_head = io_node; | ||
2592 | } else { | ||
2593 | err("Got NO IO resource(length=0x%x)\n", base); | ||
2594 | return -ENOMEM; | ||
2595 | } | ||
2596 | } else { /* map MEM */ | ||
2597 | int prefetchable = 1; | ||
2598 | struct pci_resource **res_node = &func->p_mem_head; | ||
2599 | char *res_type_str = "PMEM"; | ||
2600 | u32 temp_register2; | ||
2601 | |||
2602 | if (!(temp_register & PCI_BASE_ADDRESS_MEM_PREFETCH)) { | ||
2603 | prefetchable = 0; | ||
2604 | res_node = &func->mem_head; | ||
2605 | res_type_str++; | ||
2606 | } | ||
2607 | |||
2608 | base = temp_register & 0xFFFFFFF0; | ||
2609 | base = ~base + 1; | ||
2610 | |||
2611 | switch (temp_register & PCI_BASE_ADDRESS_MEM_TYPE_MASK) { | ||
2612 | case PCI_BASE_ADDRESS_MEM_TYPE_32: | ||
2613 | dbg("NEED 32 %s bar=0x%x(length=0x%x)\n", res_type_str, temp_register, base); | ||
2614 | |||
2615 | if (prefetchable && resources->p_mem_head) | ||
2616 | mem_node=get_resource(&(resources->p_mem_head), (ulong)base); | ||
2617 | else { | ||
2618 | if (prefetchable) | ||
2619 | dbg("using MEM for PMEM\n"); | ||
2620 | mem_node = get_resource(&(resources->mem_head), (ulong)base); | ||
2621 | } | ||
2622 | |||
2623 | /* allocate the resource to the board */ | ||
2624 | if (mem_node) { | ||
2625 | base = (u32)mem_node->base; | ||
2626 | mem_node->next = *res_node; | ||
2627 | *res_node = mem_node; | ||
2628 | dbg("Got 32 %s base=0x%x(length=0x%x)\n", res_type_str, mem_node->base, | ||
2629 | mem_node->length); | ||
2630 | } else { | ||
2631 | err("Got NO 32 %s resource(length=0x%x)\n", res_type_str, base); | ||
2632 | return -ENOMEM; | ||
2633 | } | ||
2634 | break; | ||
2635 | case PCI_BASE_ADDRESS_MEM_TYPE_64: | ||
2636 | rc = pci_bus_read_config_dword(pci_bus, devfn, cloop+4, &temp_register2); | ||
2637 | dbg("NEED 64 %s bar=0x%x:%x(length=0x%x)\n", res_type_str, temp_register2, | ||
2638 | temp_register, base); | ||
2639 | |||
2640 | if (prefetchable && resources->p_mem_head) | ||
2641 | mem_node = get_resource(&(resources->p_mem_head), (ulong)base); | ||
2642 | else { | ||
2643 | if (prefetchable) | ||
2644 | dbg("using MEM for PMEM\n"); | ||
2645 | mem_node = get_resource(&(resources->mem_head), (ulong)base); | ||
2646 | } | ||
2647 | |||
2648 | /* allocate the resource to the board */ | ||
2649 | if (mem_node) { | ||
2650 | base64 = mem_node->base; | ||
2651 | mem_node->next = *res_node; | ||
2652 | *res_node = mem_node; | ||
2653 | dbg("Got 64 %s base=0x%x:%x(length=%x)\n", res_type_str, (u32)(base64 >> 32), | ||
2654 | (u32)base64, mem_node->length); | ||
2655 | } else { | ||
2656 | err("Got NO 64 %s resource(length=0x%x)\n", res_type_str, base); | ||
2657 | return -ENOMEM; | ||
2658 | } | ||
2659 | break; | ||
2660 | default: | ||
2661 | dbg("reserved BAR type=0x%x\n", temp_register); | ||
2662 | break; | ||
2663 | } | ||
2664 | |||
2665 | } | ||
2666 | |||
2667 | if (base64) { | ||
2668 | rc = pci_bus_write_config_dword(pci_bus, devfn, cloop, (u32)base64); | ||
2669 | cloop += 4; | ||
2670 | base64 >>= 32; | ||
2671 | |||
2672 | if (base64) { | ||
2673 | dbg("%s: high dword of base64(0x%x) set to 0\n", __FUNCTION__, (u32)base64); | ||
2674 | base64 = 0x0L; | ||
2675 | } | ||
2676 | |||
2677 | rc = pci_bus_write_config_dword(pci_bus, devfn, cloop, (u32)base64); | ||
2678 | } else { | ||
2679 | rc = pci_bus_write_config_dword(pci_bus, devfn, cloop, base); | ||
2680 | } | ||
2681 | } /* End of base register loop */ | ||
2682 | |||
2683 | /* disable ROM base Address */ | ||
2684 | rc = pci_bus_write_config_dword (pci_bus, devfn, PCI_ROM_ADDRESS, 0x00); | ||
2685 | |||
2686 | /* Set HP parameters (Cache Line Size, Latency Timer) */ | ||
2687 | rc = pciehprm_set_hpp(ctrl, func, PCI_HEADER_TYPE_NORMAL); | ||
2688 | if (rc) | ||
2689 | return rc; | ||
2690 | |||
2691 | pciehprm_enable_card(ctrl, func, PCI_HEADER_TYPE_NORMAL); | ||
2692 | |||
2693 | dbg("PCI function Hot-Added s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus, func->device, | ||
2694 | func->function); | ||
2695 | } /* End of Not-A-Bridge else */ | ||
2696 | else { | ||
2697 | /* It's some strange type of PCI adapter (Cardbus?) */ | ||
2698 | return DEVICE_TYPE_NOT_SUPPORTED; | ||
2699 | } | ||
2700 | |||
2701 | func->configured = 1; | ||
2702 | |||
2703 | return 0; | ||
2704 | } | ||
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 7a0e27f0e063..4a3cecca012c 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c | |||
@@ -27,16 +27,10 @@ | |||
27 | * | 27 | * |
28 | */ | 28 | */ |
29 | 29 | ||
30 | #include <linux/config.h> | ||
31 | #include <linux/kernel.h> | 30 | #include <linux/kernel.h> |
32 | #include <linux/module.h> | 31 | #include <linux/module.h> |
33 | #include <linux/types.h> | 32 | #include <linux/types.h> |
34 | #include <linux/slab.h> | ||
35 | #include <linux/vmalloc.h> | ||
36 | #include <linux/interrupt.h> | ||
37 | #include <linux/spinlock.h> | ||
38 | #include <linux/pci.h> | 33 | #include <linux/pci.h> |
39 | #include <asm/system.h> | ||
40 | #include "../pci.h" | 34 | #include "../pci.h" |
41 | #include "pciehp.h" | 35 | #include "pciehp.h" |
42 | 36 | ||
@@ -217,23 +211,6 @@ static int pcie_cap_base = 0; /* Base of the PCI Express capability item struct | |||
217 | #define MRL_STATE 0x0020 | 211 | #define MRL_STATE 0x0020 |
218 | #define PRSN_STATE 0x0040 | 212 | #define PRSN_STATE 0x0040 |
219 | 213 | ||
220 | struct php_ctlr_state_s { | ||
221 | struct php_ctlr_state_s *pnext; | ||
222 | struct pci_dev *pci_dev; | ||
223 | unsigned int irq; | ||
224 | unsigned long flags; /* spinlock's */ | ||
225 | u32 slot_device_offset; | ||
226 | u32 num_slots; | ||
227 | struct timer_list int_poll_timer; /* Added for poll event */ | ||
228 | php_intr_callback_t attention_button_callback; | ||
229 | php_intr_callback_t switch_change_callback; | ||
230 | php_intr_callback_t presence_change_callback; | ||
231 | php_intr_callback_t power_fault_callback; | ||
232 | void *callback_instance_id; | ||
233 | struct ctrl_reg *creg; /* Ptr to controller register space */ | ||
234 | }; | ||
235 | |||
236 | |||
237 | static spinlock_t hpc_event_lock; | 214 | static spinlock_t hpc_event_lock; |
238 | 215 | ||
239 | DEFINE_DBG_BUFFER /* Debug string buffer for entire HPC defined here */ | 216 | DEFINE_DBG_BUFFER /* Debug string buffer for entire HPC defined here */ |
@@ -297,7 +274,6 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd) | |||
297 | 274 | ||
298 | DBG_ENTER_ROUTINE | 275 | DBG_ENTER_ROUTINE |
299 | 276 | ||
300 | dbg("%s : Enter\n", __FUNCTION__); | ||
301 | if (!php_ctlr) { | 277 | if (!php_ctlr) { |
302 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); | 278 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); |
303 | return -1; | 279 | return -1; |
@@ -308,7 +284,6 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd) | |||
308 | err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); | 284 | err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); |
309 | return retval; | 285 | return retval; |
310 | } | 286 | } |
311 | dbg("%s : hp_register_read_word SLOT_STATUS %x\n", __FUNCTION__, slot_status); | ||
312 | 287 | ||
313 | if ((slot_status & CMD_COMPLETED) == CMD_COMPLETED ) { | 288 | if ((slot_status & CMD_COMPLETED) == CMD_COMPLETED ) { |
314 | /* After 1 sec and CMD_COMPLETED still not set, just proceed forward to issue | 289 | /* After 1 sec and CMD_COMPLETED still not set, just proceed forward to issue |
@@ -316,14 +291,11 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd) | |||
316 | dbg("%s : CMD_COMPLETED not clear after 1 sec.\n", __FUNCTION__); | 291 | dbg("%s : CMD_COMPLETED not clear after 1 sec.\n", __FUNCTION__); |
317 | } | 292 | } |
318 | 293 | ||
319 | dbg("%s: Before hp_register_write_word SLOT_CTRL %x\n", __FUNCTION__, cmd); | ||
320 | retval = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), cmd | CMD_CMPL_INTR_ENABLE); | 294 | retval = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), cmd | CMD_CMPL_INTR_ENABLE); |
321 | if (retval) { | 295 | if (retval) { |
322 | err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); | 296 | err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); |
323 | return retval; | 297 | return retval; |
324 | } | 298 | } |
325 | dbg("%s : hp_register_write_word SLOT_CTRL %x\n", __FUNCTION__, cmd | CMD_CMPL_INTR_ENABLE); | ||
326 | dbg("%s : Exit\n", __FUNCTION__); | ||
327 | 299 | ||
328 | DBG_LEAVE_ROUTINE | 300 | DBG_LEAVE_ROUTINE |
329 | return retval; | 301 | return retval; |
@@ -509,7 +481,6 @@ static int hpc_query_power_fault(struct slot * slot) | |||
509 | u16 slot_status; | 481 | u16 slot_status; |
510 | u8 pwr_fault; | 482 | u8 pwr_fault; |
511 | int retval = 0; | 483 | int retval = 0; |
512 | u8 status; | ||
513 | 484 | ||
514 | DBG_ENTER_ROUTINE | 485 | DBG_ENTER_ROUTINE |
515 | 486 | ||
@@ -521,15 +492,13 @@ static int hpc_query_power_fault(struct slot * slot) | |||
521 | retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(slot->ctrl->cap_base), slot_status); | 492 | retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(slot->ctrl->cap_base), slot_status); |
522 | 493 | ||
523 | if (retval) { | 494 | if (retval) { |
524 | err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); | 495 | err("%s : Cannot check for power fault\n", __FUNCTION__); |
525 | return retval; | 496 | return retval; |
526 | } | 497 | } |
527 | pwr_fault = (u8)((slot_status & PWR_FAULT_DETECTED) >> 1); | 498 | pwr_fault = (u8)((slot_status & PWR_FAULT_DETECTED) >> 1); |
528 | status = (pwr_fault != 1) ? 1 : 0; | ||
529 | 499 | ||
530 | DBG_LEAVE_ROUTINE | 500 | DBG_LEAVE_ROUTINE |
531 | /* Note: Logic 0 => fault */ | 501 | return pwr_fault; |
532 | return status; | ||
533 | } | 502 | } |
534 | 503 | ||
535 | static int hpc_set_attention_status(struct slot *slot, u8 value) | 504 | static int hpc_set_attention_status(struct slot *slot, u8 value) |
@@ -539,7 +508,8 @@ static int hpc_set_attention_status(struct slot *slot, u8 value) | |||
539 | u16 slot_ctrl; | 508 | u16 slot_ctrl; |
540 | int rc = 0; | 509 | int rc = 0; |
541 | 510 | ||
542 | dbg("%s: \n", __FUNCTION__); | 511 | DBG_ENTER_ROUTINE |
512 | |||
543 | if (!php_ctlr) { | 513 | if (!php_ctlr) { |
544 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); | 514 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); |
545 | return -1; | 515 | return -1; |
@@ -555,7 +525,6 @@ static int hpc_set_attention_status(struct slot *slot, u8 value) | |||
555 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); | 525 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); |
556 | return rc; | 526 | return rc; |
557 | } | 527 | } |
558 | dbg("%s : hp_register_read_word SLOT_CTRL %x\n", __FUNCTION__, slot_ctrl); | ||
559 | 528 | ||
560 | switch (value) { | 529 | switch (value) { |
561 | case 0 : /* turn off */ | 530 | case 0 : /* turn off */ |
@@ -576,6 +545,7 @@ static int hpc_set_attention_status(struct slot *slot, u8 value) | |||
576 | pcie_write_cmd(slot, slot_cmd); | 545 | pcie_write_cmd(slot, slot_cmd); |
577 | dbg("%s: SLOT_CTRL %x write cmd %x\n", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd); | 546 | dbg("%s: SLOT_CTRL %x write cmd %x\n", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd); |
578 | 547 | ||
548 | DBG_LEAVE_ROUTINE | ||
579 | return rc; | 549 | return rc; |
580 | } | 550 | } |
581 | 551 | ||
@@ -587,7 +557,8 @@ static void hpc_set_green_led_on(struct slot *slot) | |||
587 | u16 slot_ctrl; | 557 | u16 slot_ctrl; |
588 | int rc = 0; | 558 | int rc = 0; |
589 | 559 | ||
590 | dbg("%s: \n", __FUNCTION__); | 560 | DBG_ENTER_ROUTINE |
561 | |||
591 | if (!php_ctlr) { | 562 | if (!php_ctlr) { |
592 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); | 563 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); |
593 | return ; | 564 | return ; |
@@ -604,7 +575,6 @@ static void hpc_set_green_led_on(struct slot *slot) | |||
604 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); | 575 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); |
605 | return; | 576 | return; |
606 | } | 577 | } |
607 | dbg("%s : hp_register_read_word SLOT_CTRL %x\n", __FUNCTION__, slot_ctrl); | ||
608 | slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0100; | 578 | slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0100; |
609 | if (!pciehp_poll_mode) | 579 | if (!pciehp_poll_mode) |
610 | slot_cmd = slot_cmd | HP_INTR_ENABLE; | 580 | slot_cmd = slot_cmd | HP_INTR_ENABLE; |
@@ -612,6 +582,7 @@ static void hpc_set_green_led_on(struct slot *slot) | |||
612 | pcie_write_cmd(slot, slot_cmd); | 582 | pcie_write_cmd(slot, slot_cmd); |
613 | 583 | ||
614 | dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd); | 584 | dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd); |
585 | DBG_LEAVE_ROUTINE | ||
615 | return; | 586 | return; |
616 | } | 587 | } |
617 | 588 | ||
@@ -622,7 +593,8 @@ static void hpc_set_green_led_off(struct slot *slot) | |||
622 | u16 slot_ctrl; | 593 | u16 slot_ctrl; |
623 | int rc = 0; | 594 | int rc = 0; |
624 | 595 | ||
625 | dbg("%s: \n", __FUNCTION__); | 596 | DBG_ENTER_ROUTINE |
597 | |||
626 | if (!php_ctlr) { | 598 | if (!php_ctlr) { |
627 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); | 599 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); |
628 | return ; | 600 | return ; |
@@ -639,7 +611,6 @@ static void hpc_set_green_led_off(struct slot *slot) | |||
639 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); | 611 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); |
640 | return; | 612 | return; |
641 | } | 613 | } |
642 | dbg("%s : hp_register_read_word SLOT_CTRL %x\n", __FUNCTION__, slot_ctrl); | ||
643 | 614 | ||
644 | slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0300; | 615 | slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0300; |
645 | 616 | ||
@@ -648,6 +619,7 @@ static void hpc_set_green_led_off(struct slot *slot) | |||
648 | pcie_write_cmd(slot, slot_cmd); | 619 | pcie_write_cmd(slot, slot_cmd); |
649 | dbg("%s: SLOT_CTRL %x write cmd %x\n", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd); | 620 | dbg("%s: SLOT_CTRL %x write cmd %x\n", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd); |
650 | 621 | ||
622 | DBG_LEAVE_ROUTINE | ||
651 | return; | 623 | return; |
652 | } | 624 | } |
653 | 625 | ||
@@ -658,7 +630,8 @@ static void hpc_set_green_led_blink(struct slot *slot) | |||
658 | u16 slot_ctrl; | 630 | u16 slot_ctrl; |
659 | int rc = 0; | 631 | int rc = 0; |
660 | 632 | ||
661 | dbg("%s: \n", __FUNCTION__); | 633 | DBG_ENTER_ROUTINE |
634 | |||
662 | if (!php_ctlr) { | 635 | if (!php_ctlr) { |
663 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); | 636 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); |
664 | return ; | 637 | return ; |
@@ -675,7 +648,6 @@ static void hpc_set_green_led_blink(struct slot *slot) | |||
675 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); | 648 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); |
676 | return; | 649 | return; |
677 | } | 650 | } |
678 | dbg("%s : hp_register_read_word SLOT_CTRL %x\n", __FUNCTION__, slot_ctrl); | ||
679 | 651 | ||
680 | slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0200; | 652 | slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0200; |
681 | 653 | ||
@@ -684,6 +656,7 @@ static void hpc_set_green_led_blink(struct slot *slot) | |||
684 | pcie_write_cmd(slot, slot_cmd); | 656 | pcie_write_cmd(slot, slot_cmd); |
685 | 657 | ||
686 | dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd); | 658 | dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd); |
659 | DBG_LEAVE_ROUTINE | ||
687 | return; | 660 | return; |
688 | } | 661 | } |
689 | 662 | ||
@@ -780,7 +753,6 @@ static int hpc_power_on_slot(struct slot * slot) | |||
780 | int retval = 0; | 753 | int retval = 0; |
781 | 754 | ||
782 | DBG_ENTER_ROUTINE | 755 | DBG_ENTER_ROUTINE |
783 | dbg("%s: \n", __FUNCTION__); | ||
784 | 756 | ||
785 | if (!php_ctlr) { | 757 | if (!php_ctlr) { |
786 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); | 758 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); |
@@ -799,8 +771,6 @@ static int hpc_power_on_slot(struct slot * slot) | |||
799 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); | 771 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); |
800 | return retval; | 772 | return retval; |
801 | } | 773 | } |
802 | dbg("%s: SLOT_CTRL %x, value read %xn", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), | ||
803 | slot_ctrl); | ||
804 | 774 | ||
805 | slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_ON; | 775 | slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_ON; |
806 | 776 | ||
@@ -829,7 +799,6 @@ static int hpc_power_off_slot(struct slot * slot) | |||
829 | int retval = 0; | 799 | int retval = 0; |
830 | 800 | ||
831 | DBG_ENTER_ROUTINE | 801 | DBG_ENTER_ROUTINE |
832 | dbg("%s: \n", __FUNCTION__); | ||
833 | 802 | ||
834 | if (!php_ctlr) { | 803 | if (!php_ctlr) { |
835 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); | 804 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); |
@@ -848,8 +817,6 @@ static int hpc_power_off_slot(struct slot * slot) | |||
848 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); | 817 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); |
849 | return retval; | 818 | return retval; |
850 | } | 819 | } |
851 | dbg("%s: SLOT_CTRL %x, value read %x\n", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), | ||
852 | slot_ctrl); | ||
853 | 820 | ||
854 | slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_OFF; | 821 | slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_OFF; |
855 | 822 | ||
@@ -924,7 +891,6 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs) | |||
924 | return IRQ_NONE; | 891 | return IRQ_NONE; |
925 | } | 892 | } |
926 | 893 | ||
927 | dbg("%s: Set Mask Hot-plug Interrupt Enable\n", __FUNCTION__); | ||
928 | dbg("%s: hp_register_read_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word); | 894 | dbg("%s: hp_register_read_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word); |
929 | temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) | 0x00; | 895 | temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) | 0x00; |
930 | 896 | ||
@@ -933,7 +899,6 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs) | |||
933 | err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); | 899 | err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); |
934 | return IRQ_NONE; | 900 | return IRQ_NONE; |
935 | } | 901 | } |
936 | dbg("%s: hp_register_write_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word); | ||
937 | 902 | ||
938 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status); | 903 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status); |
939 | if (rc) { | 904 | if (rc) { |
@@ -949,14 +914,12 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs) | |||
949 | err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__); | 914 | err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__); |
950 | return IRQ_NONE; | 915 | return IRQ_NONE; |
951 | } | 916 | } |
952 | dbg("%s: hp_register_write_word SLOT_STATUS with value %x\n", __FUNCTION__, temp_word); | ||
953 | } | 917 | } |
954 | 918 | ||
955 | if (intr_loc & CMD_COMPLETED) { | 919 | if (intr_loc & CMD_COMPLETED) { |
956 | /* | 920 | /* |
957 | * Command Complete Interrupt Pending | 921 | * Command Complete Interrupt Pending |
958 | */ | 922 | */ |
959 | dbg("%s: In Command Complete Interrupt Pending\n", __FUNCTION__); | ||
960 | wake_up_interruptible(&ctrl->queue); | 923 | wake_up_interruptible(&ctrl->queue); |
961 | } | 924 | } |
962 | 925 | ||
@@ -989,7 +952,6 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs) | |||
989 | } | 952 | } |
990 | 953 | ||
991 | dbg("%s: Unmask Hot-plug Interrupt Enable\n", __FUNCTION__); | 954 | dbg("%s: Unmask Hot-plug Interrupt Enable\n", __FUNCTION__); |
992 | dbg("%s: hp_register_read_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word); | ||
993 | temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE; | 955 | temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE; |
994 | 956 | ||
995 | rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL(ctrl->cap_base), temp_word); | 957 | rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL(ctrl->cap_base), temp_word); |
@@ -997,14 +959,12 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs) | |||
997 | err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); | 959 | err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); |
998 | return IRQ_NONE; | 960 | return IRQ_NONE; |
999 | } | 961 | } |
1000 | dbg("%s: hp_register_write_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word); | ||
1001 | 962 | ||
1002 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status); | 963 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status); |
1003 | if (rc) { | 964 | if (rc) { |
1004 | err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); | 965 | err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); |
1005 | return IRQ_NONE; | 966 | return IRQ_NONE; |
1006 | } | 967 | } |
1007 | dbg("%s: hp_register_read_word SLOT_STATUS with value %x\n", __FUNCTION__, slot_status); | ||
1008 | 968 | ||
1009 | /* Clear command complete interrupt caused by this write */ | 969 | /* Clear command complete interrupt caused by this write */ |
1010 | temp_word = 0x1F; | 970 | temp_word = 0x1F; |
@@ -1248,12 +1208,7 @@ static struct hpc_ops pciehp_hpc_ops = { | |||
1248 | .check_lnk_status = hpc_check_lnk_status, | 1208 | .check_lnk_status = hpc_check_lnk_status, |
1249 | }; | 1209 | }; |
1250 | 1210 | ||
1251 | int pcie_init(struct controller * ctrl, | 1211 | int pcie_init(struct controller * ctrl, struct pcie_device *dev) |
1252 | struct pcie_device *dev, | ||
1253 | php_intr_callback_t attention_button_callback, | ||
1254 | php_intr_callback_t switch_change_callback, | ||
1255 | php_intr_callback_t presence_change_callback, | ||
1256 | php_intr_callback_t power_fault_callback) | ||
1257 | { | 1212 | { |
1258 | struct php_ctlr_state_s *php_ctlr, *p; | 1213 | struct php_ctlr_state_s *php_ctlr, *p; |
1259 | void *instance_id = ctrl; | 1214 | void *instance_id = ctrl; |
@@ -1282,8 +1237,8 @@ int pcie_init(struct controller * ctrl, | |||
1282 | pdev = dev->port; | 1237 | pdev = dev->port; |
1283 | php_ctlr->pci_dev = pdev; /* save pci_dev in context */ | 1238 | php_ctlr->pci_dev = pdev; /* save pci_dev in context */ |
1284 | 1239 | ||
1285 | dbg("%s: pdev->vendor %x pdev->device %x\n", __FUNCTION__, | 1240 | dbg("%s: hotplug controller vendor id 0x%x device id 0x%x\n", |
1286 | pdev->vendor, pdev->device); | 1241 | __FUNCTION__, pdev->vendor, pdev->device); |
1287 | 1242 | ||
1288 | saved_cap_base = pcie_cap_base; | 1243 | saved_cap_base = pcie_cap_base; |
1289 | 1244 | ||
@@ -1340,8 +1295,6 @@ int pcie_init(struct controller * ctrl, | |||
1340 | first = 0; | 1295 | first = 0; |
1341 | } | 1296 | } |
1342 | 1297 | ||
1343 | dbg("pdev = %p: b:d:f:irq=0x%x:%x:%x:%x\n", pdev, pdev->bus->number, | ||
1344 | PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), dev->irq); | ||
1345 | for ( rc = 0; rc < DEVICE_COUNT_RESOURCE; rc++) | 1298 | for ( rc = 0; rc < DEVICE_COUNT_RESOURCE; rc++) |
1346 | if (pci_resource_len(pdev, rc) > 0) | 1299 | if (pci_resource_len(pdev, rc) > 0) |
1347 | dbg("pci resource[%d] start=0x%lx(len=0x%lx)\n", rc, | 1300 | dbg("pci resource[%d] start=0x%lx(len=0x%lx)\n", rc, |
@@ -1359,13 +1312,12 @@ int pcie_init(struct controller * ctrl, | |||
1359 | 1312 | ||
1360 | /* find the IRQ */ | 1313 | /* find the IRQ */ |
1361 | php_ctlr->irq = dev->irq; | 1314 | php_ctlr->irq = dev->irq; |
1362 | dbg("HPC interrupt = %d\n", php_ctlr->irq); | ||
1363 | 1315 | ||
1364 | /* Save interrupt callback info */ | 1316 | /* Save interrupt callback info */ |
1365 | php_ctlr->attention_button_callback = attention_button_callback; | 1317 | php_ctlr->attention_button_callback = pciehp_handle_attention_button; |
1366 | php_ctlr->switch_change_callback = switch_change_callback; | 1318 | php_ctlr->switch_change_callback = pciehp_handle_switch_change; |
1367 | php_ctlr->presence_change_callback = presence_change_callback; | 1319 | php_ctlr->presence_change_callback = pciehp_handle_presence_change; |
1368 | php_ctlr->power_fault_callback = power_fault_callback; | 1320 | php_ctlr->power_fault_callback = pciehp_handle_power_fault; |
1369 | php_ctlr->callback_instance_id = instance_id; | 1321 | php_ctlr->callback_instance_id = instance_id; |
1370 | 1322 | ||
1371 | /* return PCI Controller Info */ | 1323 | /* return PCI Controller Info */ |
@@ -1387,15 +1339,12 @@ int pcie_init(struct controller * ctrl, | |||
1387 | err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); | 1339 | err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); |
1388 | goto abort_free_ctlr; | 1340 | goto abort_free_ctlr; |
1389 | } | 1341 | } |
1390 | dbg("%s : Mask HPIE hp_register_write_word SLOT_CTRL %x\n", __FUNCTION__, temp_word); | ||
1391 | 1342 | ||
1392 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status); | 1343 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status); |
1393 | if (rc) { | 1344 | if (rc) { |
1394 | err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); | 1345 | err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); |
1395 | goto abort_free_ctlr; | 1346 | goto abort_free_ctlr; |
1396 | } | 1347 | } |
1397 | dbg("%s: Mask HPIE SLOT_STATUS offset %x reads slot_status %x\n", __FUNCTION__, SLOT_STATUS(ctrl->cap_base) | ||
1398 | , slot_status); | ||
1399 | 1348 | ||
1400 | temp_word = 0x1F; /* Clear all events */ | 1349 | temp_word = 0x1F; /* Clear all events */ |
1401 | rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word); | 1350 | rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word); |
@@ -1403,7 +1352,6 @@ int pcie_init(struct controller * ctrl, | |||
1403 | err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__); | 1352 | err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__); |
1404 | goto abort_free_ctlr; | 1353 | goto abort_free_ctlr; |
1405 | } | 1354 | } |
1406 | dbg("%s: SLOT_STATUS offset %x writes slot_status %x\n", __FUNCTION__, SLOT_STATUS(ctrl->cap_base), temp_word); | ||
1407 | 1355 | ||
1408 | if (pciehp_poll_mode) {/* Install interrupt polling code */ | 1356 | if (pciehp_poll_mode) {/* Install interrupt polling code */ |
1409 | /* Install and start the interrupt polling timer */ | 1357 | /* Install and start the interrupt polling timer */ |
@@ -1419,13 +1367,14 @@ int pcie_init(struct controller * ctrl, | |||
1419 | } | 1367 | } |
1420 | } | 1368 | } |
1421 | 1369 | ||
1370 | dbg("pciehp ctrl b:d:f:irq=0x%x:%x:%x:%x\n", pdev->bus->number, | ||
1371 | PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), dev->irq); | ||
1372 | |||
1422 | rc = hp_register_read_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word); | 1373 | rc = hp_register_read_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word); |
1423 | if (rc) { | 1374 | if (rc) { |
1424 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); | 1375 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); |
1425 | goto abort_free_ctlr; | 1376 | goto abort_free_ctlr; |
1426 | } | 1377 | } |
1427 | dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL(ctrl->cap_base), temp_word); | ||
1428 | dbg("%s: slot_cap %x\n", __FUNCTION__, slot_cap); | ||
1429 | 1378 | ||
1430 | intr_enable = intr_enable | PRSN_DETECT_ENABLE; | 1379 | intr_enable = intr_enable | PRSN_DETECT_ENABLE; |
1431 | 1380 | ||
@@ -1445,7 +1394,6 @@ int pcie_init(struct controller * ctrl, | |||
1445 | } else { | 1394 | } else { |
1446 | temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE; | 1395 | temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE; |
1447 | } | 1396 | } |
1448 | dbg("%s: temp_word %x\n", __FUNCTION__, temp_word); | ||
1449 | 1397 | ||
1450 | /* Unmask Hot-plug Interrupt Enable for the interrupt notification mechanism case */ | 1398 | /* Unmask Hot-plug Interrupt Enable for the interrupt notification mechanism case */ |
1451 | rc = hp_register_write_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word); | 1399 | rc = hp_register_write_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word); |
@@ -1453,14 +1401,11 @@ int pcie_init(struct controller * ctrl, | |||
1453 | err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); | 1401 | err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); |
1454 | goto abort_free_ctlr; | 1402 | goto abort_free_ctlr; |
1455 | } | 1403 | } |
1456 | dbg("%s : Unmask HPIE hp_register_write_word SLOT_CTRL with %x\n", __FUNCTION__, temp_word); | ||
1457 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status); | 1404 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status); |
1458 | if (rc) { | 1405 | if (rc) { |
1459 | err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); | 1406 | err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); |
1460 | goto abort_free_ctlr; | 1407 | goto abort_free_ctlr; |
1461 | } | 1408 | } |
1462 | dbg("%s: Unmask HPIE SLOT_STATUS offset %x reads slot_status %x\n", __FUNCTION__, | ||
1463 | SLOT_STATUS(ctrl->cap_base), slot_status); | ||
1464 | 1409 | ||
1465 | temp_word = 0x1F; /* Clear all events */ | 1410 | temp_word = 0x1F; /* Clear all events */ |
1466 | rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word); | 1411 | rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word); |
@@ -1468,8 +1413,16 @@ int pcie_init(struct controller * ctrl, | |||
1468 | err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__); | 1413 | err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__); |
1469 | goto abort_free_ctlr; | 1414 | goto abort_free_ctlr; |
1470 | } | 1415 | } |
1471 | dbg("%s: SLOT_STATUS offset %x writes slot_status %x\n", __FUNCTION__, SLOT_STATUS(ctrl->cap_base), temp_word); | ||
1472 | 1416 | ||
1417 | if (pciehp_force) { | ||
1418 | dbg("Bypassing BIOS check for pciehp use on %s\n", | ||
1419 | pci_name(ctrl->pci_dev)); | ||
1420 | } else { | ||
1421 | rc = pciehp_get_hp_hw_control_from_firmware(ctrl->pci_dev); | ||
1422 | if (rc) | ||
1423 | goto abort_free_ctlr; | ||
1424 | } | ||
1425 | |||
1473 | /* Add this HPC instance into the HPC list */ | 1426 | /* Add this HPC instance into the HPC list */ |
1474 | spin_lock(&list_lock); | 1427 | spin_lock(&list_lock); |
1475 | if (php_ctlr_list_head == 0) { | 1428 | if (php_ctlr_list_head == 0) { |
diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c index ff17d8e07e94..647673a7d224 100644 --- a/drivers/pci/hotplug/pciehp_pci.c +++ b/drivers/pci/hotplug/pciehp_pci.c | |||
@@ -27,801 +27,111 @@ | |||
27 | * | 27 | * |
28 | */ | 28 | */ |
29 | 29 | ||
30 | #include <linux/config.h> | ||
31 | #include <linux/module.h> | 30 | #include <linux/module.h> |
32 | #include <linux/kernel.h> | 31 | #include <linux/kernel.h> |
33 | #include <linux/types.h> | 32 | #include <linux/types.h> |
34 | #include <linux/slab.h> | ||
35 | #include <linux/workqueue.h> | ||
36 | #include <linux/proc_fs.h> | ||
37 | #include <linux/pci.h> | 33 | #include <linux/pci.h> |
38 | #include "../pci.h" | 34 | #include "../pci.h" |
39 | #include "pciehp.h" | 35 | #include "pciehp.h" |
40 | #ifndef CONFIG_IA64 | ||
41 | #include "../../../arch/i386/pci/pci.h" /* horrible hack showing how processor dependant we are... */ | ||
42 | #endif | ||
43 | 36 | ||
44 | 37 | ||
45 | int pciehp_configure_device (struct controller* ctrl, struct pci_func* func) | 38 | int pciehp_configure_device(struct slot *p_slot) |
46 | { | 39 | { |
47 | unsigned char bus; | 40 | struct pci_dev *dev; |
48 | struct pci_bus *child; | 41 | struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate; |
49 | int num; | 42 | int num, fn; |
50 | 43 | ||
51 | if (func->pci_dev == NULL) | 44 | dev = pci_find_slot(p_slot->bus, PCI_DEVFN(p_slot->device, 0)); |
52 | func->pci_dev = pci_find_slot(func->bus, PCI_DEVFN(func->device, func->function)); | 45 | if (dev) { |
53 | 46 | err("Device %s already exists at %x:%x, cannot hot-add\n", | |
54 | /* Still NULL ? Well then scan for it ! */ | 47 | pci_name(dev), p_slot->bus, p_slot->device); |
55 | if (func->pci_dev == NULL) { | 48 | return -EINVAL; |
56 | dbg("%s: pci_dev still null. do pci_scan_slot\n", __FUNCTION__); | ||
57 | |||
58 | num = pci_scan_slot(ctrl->pci_dev->subordinate, PCI_DEVFN(func->device, func->function)); | ||
59 | |||
60 | if (num) | ||
61 | pci_bus_add_devices(ctrl->pci_dev->subordinate); | ||
62 | |||
63 | func->pci_dev = pci_find_slot(func->bus, PCI_DEVFN(func->device, func->function)); | ||
64 | if (func->pci_dev == NULL) { | ||
65 | dbg("ERROR: pci_dev still null\n"); | ||
66 | return 0; | ||
67 | } | ||
68 | } | 49 | } |
69 | 50 | ||
70 | if (func->pci_dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { | 51 | num = pci_scan_slot(parent, PCI_DEVFN(p_slot->device, 0)); |
71 | pci_read_config_byte(func->pci_dev, PCI_SECONDARY_BUS, &bus); | 52 | if (num == 0) { |
72 | child = pci_add_new_bus(func->pci_dev->bus, (func->pci_dev), bus); | 53 | err("No new device found\n"); |
73 | pci_do_scan_bus(child); | 54 | return -ENODEV; |
55 | } | ||
74 | 56 | ||
57 | for (fn = 0; fn < 8; fn++) { | ||
58 | if (!(dev = pci_find_slot(p_slot->bus, | ||
59 | PCI_DEVFN(p_slot->device, fn)))) | ||
60 | continue; | ||
61 | if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) { | ||
62 | err("Cannot hot-add display device %s\n", | ||
63 | pci_name(dev)); | ||
64 | continue; | ||
65 | } | ||
66 | if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) || | ||
67 | (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) { | ||
68 | /* Find an unused bus number for the new bridge */ | ||
69 | struct pci_bus *child; | ||
70 | unsigned char busnr, start = parent->secondary; | ||
71 | unsigned char end = parent->subordinate; | ||
72 | for (busnr = start; busnr <= end; busnr++) { | ||
73 | if (!pci_find_bus(pci_domain_nr(parent), | ||
74 | busnr)) | ||
75 | break; | ||
76 | } | ||
77 | if (busnr >= end) { | ||
78 | err("No free bus for hot-added bridge\n"); | ||
79 | continue; | ||
80 | } | ||
81 | child = pci_add_new_bus(parent, dev, busnr); | ||
82 | if (!child) { | ||
83 | err("Cannot add new bus for %s\n", | ||
84 | pci_name(dev)); | ||
85 | continue; | ||
86 | } | ||
87 | child->subordinate = pci_do_scan_bus(child); | ||
88 | pci_bus_size_bridges(child); | ||
89 | } | ||
90 | /* TBD: program firmware provided _HPP values */ | ||
91 | /* program_fw_provided_values(dev); */ | ||
75 | } | 92 | } |
76 | 93 | ||
94 | pci_bus_assign_resources(parent); | ||
95 | pci_bus_add_devices(parent); | ||
96 | pci_enable_bridges(parent); | ||
77 | return 0; | 97 | return 0; |
78 | } | 98 | } |
79 | 99 | ||
80 | 100 | int pciehp_unconfigure_device(struct slot *p_slot) | |
81 | int pciehp_unconfigure_device(struct pci_func* func) | ||
82 | { | 101 | { |
83 | int rc = 0; | 102 | int rc = 0; |
84 | int j; | 103 | int j; |
85 | struct pci_bus *pbus; | 104 | u8 bctl = 0; |
86 | 105 | ||
87 | dbg("%s: bus/dev/func = %x/%x/%x\n", __FUNCTION__, func->bus, | 106 | dbg("%s: bus/dev = %x/%x\n", __FUNCTION__, p_slot->bus, |
88 | func->device, func->function); | 107 | p_slot->device); |
89 | pbus = func->pci_dev->bus; | ||
90 | 108 | ||
91 | for (j=0; j<8 ; j++) { | 109 | for (j=0; j<8 ; j++) { |
92 | struct pci_dev* temp = pci_find_slot(func->bus, | 110 | struct pci_dev* temp = pci_find_slot(p_slot->bus, |
93 | (func->device << 3) | j); | 111 | (p_slot->device << 3) | j); |
94 | if (temp) { | 112 | if (!temp) |
95 | pci_remove_bus_device(temp); | 113 | continue; |
114 | if ((temp->class >> 16) == PCI_BASE_CLASS_DISPLAY) { | ||
115 | err("Cannot remove display device %s\n", | ||
116 | pci_name(temp)); | ||
117 | continue; | ||
96 | } | 118 | } |
119 | if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE) { | ||
120 | pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl); | ||
121 | if (bctl & PCI_BRIDGE_CTL_VGA) { | ||
122 | err("Cannot remove display device %s\n", | ||
123 | pci_name(temp)); | ||
124 | continue; | ||
125 | } | ||
126 | } | ||
127 | pci_remove_bus_device(temp); | ||
97 | } | 128 | } |
98 | /* | 129 | /* |
99 | * Some PCI Express root ports require fixup after hot-plug operation. | 130 | * Some PCI Express root ports require fixup after hot-plug operation. |
100 | */ | 131 | */ |
101 | if (pcie_mch_quirk) | 132 | if (pcie_mch_quirk) |
102 | pci_fixup_device(pci_fixup_final, pbus->self); | 133 | pci_fixup_device(pci_fixup_final, p_slot->ctrl->pci_dev); |
103 | 134 | ||
104 | return rc; | 135 | return rc; |
105 | } | 136 | } |
106 | 137 | ||
107 | /* | ||
108 | * pciehp_set_irq | ||
109 | * | ||
110 | * @bus_num: bus number of PCI device | ||
111 | * @dev_num: device number of PCI device | ||
112 | * @slot: pointer to u8 where slot number will be returned | ||
113 | */ | ||
114 | int pciehp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num) | ||
115 | { | ||
116 | #if defined(CONFIG_X86_32) && !defined(CONFIG_X86_IO_APIC) | ||
117 | int rc; | ||
118 | u16 temp_word; | ||
119 | struct pci_dev fakedev; | ||
120 | struct pci_bus fakebus; | ||
121 | |||
122 | fakedev.devfn = dev_num << 3; | ||
123 | fakedev.bus = &fakebus; | ||
124 | fakebus.number = bus_num; | ||
125 | dbg("%s: dev %d, bus %d, pin %d, num %d\n", | ||
126 | __FUNCTION__, dev_num, bus_num, int_pin, irq_num); | ||
127 | rc = pcibios_set_irq_routing(&fakedev, int_pin - 0x0a, irq_num); | ||
128 | dbg("%s: rc %d\n", __FUNCTION__, rc); | ||
129 | if (!rc) | ||
130 | return !rc; | ||
131 | |||
132 | /* set the Edge Level Control Register (ELCR) */ | ||
133 | temp_word = inb(0x4d0); | ||
134 | temp_word |= inb(0x4d1) << 8; | ||
135 | |||
136 | temp_word |= 0x01 << irq_num; | ||
137 | |||
138 | /* This should only be for x86 as it sets the Edge Level Control Register */ | ||
139 | outb((u8) (temp_word & 0xFF), 0x4d0); | ||
140 | outb((u8) ((temp_word & 0xFF00) >> 8), 0x4d1); | ||
141 | #endif | ||
142 | return 0; | ||
143 | } | ||
144 | |||
145 | /* More PCI configuration routines; this time centered around hotplug controller */ | ||
146 | |||
147 | |||
148 | /* | ||
149 | * pciehp_save_config | ||
150 | * | ||
151 | * Reads configuration for all slots in a PCI bus and saves info. | ||
152 | * | ||
153 | * Note: For non-hot plug busses, the slot # saved is the device # | ||
154 | * | ||
155 | * returns 0 if success | ||
156 | */ | ||
157 | int pciehp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num) | ||
158 | { | ||
159 | int rc; | ||
160 | u8 class_code; | ||
161 | u8 header_type; | ||
162 | u32 ID; | ||
163 | u8 secondary_bus; | ||
164 | struct pci_func *new_slot; | ||
165 | int sub_bus; | ||
166 | int max_functions; | ||
167 | int function; | ||
168 | u8 DevError; | ||
169 | int device = 0; | ||
170 | int cloop = 0; | ||
171 | int stop_it; | ||
172 | int index; | ||
173 | int is_hot_plug = num_ctlr_slots || first_device_num; | ||
174 | struct pci_bus lpci_bus, *pci_bus; | ||
175 | int FirstSupported, LastSupported; | ||
176 | |||
177 | dbg("%s: Enter\n", __FUNCTION__); | ||
178 | |||
179 | memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus)); | ||
180 | pci_bus = &lpci_bus; | ||
181 | |||
182 | dbg("%s: num_ctlr_slots = %d, first_device_num = %d\n", __FUNCTION__, | ||
183 | num_ctlr_slots, first_device_num); | ||
184 | |||
185 | /* Decide which slots are supported */ | ||
186 | if (is_hot_plug) { | ||
187 | /********************************* | ||
188 | * is_hot_plug is the slot mask | ||
189 | *********************************/ | ||
190 | FirstSupported = first_device_num; | ||
191 | LastSupported = FirstSupported + num_ctlr_slots - 1; | ||
192 | } else { | ||
193 | FirstSupported = 0; | ||
194 | LastSupported = 0x1F; | ||
195 | } | ||
196 | |||
197 | dbg("FirstSupported = %d, LastSupported = %d\n", FirstSupported, | ||
198 | LastSupported); | ||
199 | |||
200 | /* Save PCI configuration space for all devices in supported slots */ | ||
201 | dbg("%s: pci_bus->number = %x\n", __FUNCTION__, pci_bus->number); | ||
202 | pci_bus->number = busnumber; | ||
203 | dbg("%s: bus = %x, dev = %x\n", __FUNCTION__, busnumber, device); | ||
204 | for (device = FirstSupported; device <= LastSupported; device++) { | ||
205 | ID = 0xFFFFFFFF; | ||
206 | rc = pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, 0), | ||
207 | PCI_VENDOR_ID, &ID); | ||
208 | |||
209 | if (ID != 0xFFFFFFFF) { /* device in slot */ | ||
210 | dbg("%s: ID = %x\n", __FUNCTION__, ID); | ||
211 | rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0), | ||
212 | 0x0B, &class_code); | ||
213 | if (rc) | ||
214 | return rc; | ||
215 | |||
216 | rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0), | ||
217 | PCI_HEADER_TYPE, &header_type); | ||
218 | if (rc) | ||
219 | return rc; | ||
220 | |||
221 | dbg("class_code = %x, header_type = %x\n", class_code, header_type); | ||
222 | |||
223 | /* If multi-function device, set max_functions to 8 */ | ||
224 | if (header_type & 0x80) | ||
225 | max_functions = 8; | ||
226 | else | ||
227 | max_functions = 1; | ||
228 | |||
229 | function = 0; | ||
230 | |||
231 | do { | ||
232 | DevError = 0; | ||
233 | dbg("%s: In do loop\n", __FUNCTION__); | ||
234 | |||
235 | if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* P-P Bridge */ | ||
236 | /* Recurse the subordinate bus | ||
237 | * get the subordinate bus number | ||
238 | */ | ||
239 | rc = pci_bus_read_config_byte(pci_bus, | ||
240 | PCI_DEVFN(device, function), | ||
241 | PCI_SECONDARY_BUS, &secondary_bus); | ||
242 | if (rc) { | ||
243 | return rc; | ||
244 | } else { | ||
245 | sub_bus = (int) secondary_bus; | ||
246 | |||
247 | /* Save secondary bus cfg spc with this recursive call. */ | ||
248 | rc = pciehp_save_config(ctrl, sub_bus, 0, 0); | ||
249 | if (rc) | ||
250 | return rc; | ||
251 | } | ||
252 | } | ||
253 | |||
254 | index = 0; | ||
255 | new_slot = pciehp_slot_find(busnumber, device, index++); | ||
256 | |||
257 | dbg("%s: new_slot = %p bus %x dev %x fun %x\n", | ||
258 | __FUNCTION__, new_slot, busnumber, device, index-1); | ||
259 | |||
260 | while (new_slot && (new_slot->function != (u8) function)) { | ||
261 | new_slot = pciehp_slot_find(busnumber, device, index++); | ||
262 | dbg("%s: while loop, new_slot = %p bus %x dev %x fun %x\n", | ||
263 | __FUNCTION__, new_slot, busnumber, device, index-1); | ||
264 | } | ||
265 | if (!new_slot) { | ||
266 | /* Setup slot structure. */ | ||
267 | new_slot = pciehp_slot_create(busnumber); | ||
268 | dbg("%s: if, new_slot = %p bus %x dev %x fun %x\n", | ||
269 | __FUNCTION__, new_slot, busnumber, device, function); | ||
270 | |||
271 | if (new_slot == NULL) | ||
272 | return(1); | ||
273 | } | ||
274 | |||
275 | new_slot->bus = (u8) busnumber; | ||
276 | new_slot->device = (u8) device; | ||
277 | new_slot->function = (u8) function; | ||
278 | new_slot->is_a_board = 1; | ||
279 | new_slot->switch_save = 0x10; | ||
280 | /* In case of unsupported board */ | ||
281 | new_slot->status = DevError; | ||
282 | new_slot->pci_dev = pci_find_slot(new_slot->bus, | ||
283 | (new_slot->device << 3) | new_slot->function); | ||
284 | dbg("new_slot->pci_dev = %p\n", new_slot->pci_dev); | ||
285 | |||
286 | for (cloop = 0; cloop < 0x20; cloop++) { | ||
287 | rc = pci_bus_read_config_dword(pci_bus, | ||
288 | PCI_DEVFN(device, function), | ||
289 | cloop << 2, | ||
290 | (u32 *) &(new_slot->config_space [cloop])); | ||
291 | /* dbg("new_slot->config_space[%x] = %x\n", | ||
292 | cloop, new_slot->config_space[cloop]); */ | ||
293 | if (rc) | ||
294 | return rc; | ||
295 | } | ||
296 | |||
297 | function++; | ||
298 | |||
299 | stop_it = 0; | ||
300 | |||
301 | /* this loop skips to the next present function | ||
302 | * reading in Class Code and Header type. | ||
303 | */ | ||
304 | |||
305 | while ((function < max_functions)&&(!stop_it)) { | ||
306 | dbg("%s: In while loop \n", __FUNCTION__); | ||
307 | rc = pci_bus_read_config_dword(pci_bus, | ||
308 | PCI_DEVFN(device, function), | ||
309 | PCI_VENDOR_ID, &ID); | ||
310 | |||
311 | if (ID == 0xFFFFFFFF) { /* nothing there. */ | ||
312 | function++; | ||
313 | dbg("Nothing there\n"); | ||
314 | } else { /* Something there */ | ||
315 | rc = pci_bus_read_config_byte(pci_bus, | ||
316 | PCI_DEVFN(device, function), | ||
317 | 0x0B, &class_code); | ||
318 | if (rc) | ||
319 | return rc; | ||
320 | |||
321 | rc = pci_bus_read_config_byte(pci_bus, | ||
322 | PCI_DEVFN(device, function), | ||
323 | PCI_HEADER_TYPE, &header_type); | ||
324 | if (rc) | ||
325 | return rc; | ||
326 | |||
327 | dbg("class_code = %x, header_type = %x\n", class_code, header_type); | ||
328 | stop_it++; | ||
329 | } | ||
330 | } | ||
331 | |||
332 | } while (function < max_functions); | ||
333 | /* End of IF (device in slot?) */ | ||
334 | } else if (is_hot_plug) { | ||
335 | /* Setup slot structure with entry for empty slot */ | ||
336 | new_slot = pciehp_slot_create(busnumber); | ||
337 | |||
338 | if (new_slot == NULL) { | ||
339 | return(1); | ||
340 | } | ||
341 | dbg("new_slot = %p, bus = %x, dev = %x, fun = %x\n", new_slot, | ||
342 | new_slot->bus, new_slot->device, new_slot->function); | ||
343 | |||
344 | new_slot->bus = (u8) busnumber; | ||
345 | new_slot->device = (u8) device; | ||
346 | new_slot->function = 0; | ||
347 | new_slot->is_a_board = 0; | ||
348 | new_slot->presence_save = 0; | ||
349 | new_slot->switch_save = 0; | ||
350 | } | ||
351 | } /* End of FOR loop */ | ||
352 | |||
353 | dbg("%s: Exit\n", __FUNCTION__); | ||
354 | return(0); | ||
355 | } | ||
356 | |||
357 | |||
358 | /* | ||
359 | * pciehp_save_slot_config | ||
360 | * | ||
361 | * Saves configuration info for all PCI devices in a given slot | ||
362 | * including subordinate busses. | ||
363 | * | ||
364 | * returns 0 if success | ||
365 | */ | ||
366 | int pciehp_save_slot_config(struct controller *ctrl, struct pci_func * new_slot) | ||
367 | { | ||
368 | int rc; | ||
369 | u8 class_code; | ||
370 | u8 header_type; | ||
371 | u32 ID; | ||
372 | u8 secondary_bus; | ||
373 | int sub_bus; | ||
374 | int max_functions; | ||
375 | int function; | ||
376 | int cloop = 0; | ||
377 | int stop_it; | ||
378 | struct pci_bus lpci_bus, *pci_bus; | ||
379 | memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus)); | ||
380 | pci_bus = &lpci_bus; | ||
381 | pci_bus->number = new_slot->bus; | ||
382 | |||
383 | ID = 0xFFFFFFFF; | ||
384 | |||
385 | pci_bus_read_config_dword(pci_bus, PCI_DEVFN(new_slot->device, 0), | ||
386 | PCI_VENDOR_ID, &ID); | ||
387 | |||
388 | if (ID != 0xFFFFFFFF) { /* device in slot */ | ||
389 | pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0), | ||
390 | 0x0B, &class_code); | ||
391 | |||
392 | pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0), | ||
393 | PCI_HEADER_TYPE, &header_type); | ||
394 | |||
395 | if (header_type & 0x80) /* Multi-function device */ | ||
396 | max_functions = 8; | ||
397 | else | ||
398 | max_functions = 1; | ||
399 | |||
400 | function = 0; | ||
401 | |||
402 | do { | ||
403 | if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */ | ||
404 | /* Recurse the subordinate bus */ | ||
405 | pci_bus_read_config_byte(pci_bus, | ||
406 | PCI_DEVFN(new_slot->device, function), | ||
407 | PCI_SECONDARY_BUS, &secondary_bus); | ||
408 | |||
409 | sub_bus = (int) secondary_bus; | ||
410 | |||
411 | /* Save the config headers for the secondary bus. */ | ||
412 | rc = pciehp_save_config(ctrl, sub_bus, 0, 0); | ||
413 | |||
414 | if (rc) | ||
415 | return rc; | ||
416 | |||
417 | } /* End of IF */ | ||
418 | |||
419 | new_slot->status = 0; | ||
420 | |||
421 | for (cloop = 0; cloop < 0x20; cloop++) { | ||
422 | pci_bus_read_config_dword(pci_bus, | ||
423 | PCI_DEVFN(new_slot->device, function), | ||
424 | cloop << 2, | ||
425 | (u32 *) &(new_slot->config_space [cloop])); | ||
426 | } | ||
427 | |||
428 | function++; | ||
429 | |||
430 | stop_it = 0; | ||
431 | |||
432 | /* this loop skips to the next present function | ||
433 | * reading in the Class Code and the Header type. | ||
434 | */ | ||
435 | |||
436 | while ((function < max_functions) && (!stop_it)) { | ||
437 | pci_bus_read_config_dword(pci_bus, | ||
438 | PCI_DEVFN(new_slot->device, function), | ||
439 | PCI_VENDOR_ID, &ID); | ||
440 | |||
441 | if (ID == 0xFFFFFFFF) { /* nothing there. */ | ||
442 | function++; | ||
443 | } else { /* Something there */ | ||
444 | pci_bus_read_config_byte(pci_bus, | ||
445 | PCI_DEVFN(new_slot->device, function), | ||
446 | 0x0B, &class_code); | ||
447 | |||
448 | pci_bus_read_config_byte(pci_bus, | ||
449 | PCI_DEVFN(new_slot->device, function), | ||
450 | PCI_HEADER_TYPE, &header_type); | ||
451 | |||
452 | stop_it++; | ||
453 | } | ||
454 | } | ||
455 | |||
456 | } while (function < max_functions); | ||
457 | } /* End of IF (device in slot?) */ | ||
458 | else { | ||
459 | return 2; | ||
460 | } | ||
461 | |||
462 | return 0; | ||
463 | } | ||
464 | |||
465 | |||
466 | /* | ||
467 | * pciehp_save_used_resources | ||
468 | * | ||
469 | * Stores used resource information for existing boards. this is | ||
470 | * for boards that were in the system when this driver was loaded. | ||
471 | * this function is for hot plug ADD | ||
472 | * | ||
473 | * returns 0 if success | ||
474 | * if disable == 1(DISABLE_CARD), | ||
475 | * it loops for all functions of the slot and disables them. | ||
476 | * else, it just get resources of the function and return. | ||
477 | */ | ||
478 | int pciehp_save_used_resources(struct controller *ctrl, struct pci_func *func, int disable) | ||
479 | { | ||
480 | u8 cloop; | ||
481 | u8 header_type; | ||
482 | u8 secondary_bus; | ||
483 | u8 temp_byte; | ||
484 | u16 command; | ||
485 | u16 save_command; | ||
486 | u16 w_base, w_length; | ||
487 | u32 temp_register; | ||
488 | u32 save_base; | ||
489 | u32 base, length; | ||
490 | u64 base64 = 0; | ||
491 | int index = 0; | ||
492 | unsigned int devfn; | ||
493 | struct pci_resource *mem_node = NULL; | ||
494 | struct pci_resource *p_mem_node = NULL; | ||
495 | struct pci_resource *t_mem_node; | ||
496 | struct pci_resource *io_node; | ||
497 | struct pci_resource *bus_node; | ||
498 | struct pci_bus lpci_bus, *pci_bus; | ||
499 | memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus)); | ||
500 | pci_bus = &lpci_bus; | ||
501 | |||
502 | if (disable) | ||
503 | func = pciehp_slot_find(func->bus, func->device, index++); | ||
504 | |||
505 | while ((func != NULL) && func->is_a_board) { | ||
506 | pci_bus->number = func->bus; | ||
507 | devfn = PCI_DEVFN(func->device, func->function); | ||
508 | |||
509 | /* Save the command register */ | ||
510 | pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &save_command); | ||
511 | |||
512 | if (disable) { | ||
513 | /* disable card */ | ||
514 | command = 0x00; | ||
515 | pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command); | ||
516 | } | ||
517 | |||
518 | /* Check for Bridge */ | ||
519 | pci_bus_read_config_byte(pci_bus, devfn, PCI_HEADER_TYPE, &header_type); | ||
520 | |||
521 | if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */ | ||
522 | dbg("Save_used_res of PCI bridge b:d=0x%x:%x, sc=0x%x\n", | ||
523 | func->bus, func->device, save_command); | ||
524 | if (disable) { | ||
525 | /* Clear Bridge Control Register */ | ||
526 | command = 0x00; | ||
527 | pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, command); | ||
528 | } | ||
529 | |||
530 | pci_bus_read_config_byte(pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus); | ||
531 | pci_bus_read_config_byte(pci_bus, devfn, PCI_SUBORDINATE_BUS, &temp_byte); | ||
532 | |||
533 | bus_node = kmalloc(sizeof(struct pci_resource), | ||
534 | GFP_KERNEL); | ||
535 | if (!bus_node) | ||
536 | return -ENOMEM; | ||
537 | |||
538 | bus_node->base = (ulong)secondary_bus; | ||
539 | bus_node->length = (ulong)(temp_byte - secondary_bus + 1); | ||
540 | |||
541 | bus_node->next = func->bus_head; | ||
542 | func->bus_head = bus_node; | ||
543 | |||
544 | /* Save IO base and Limit registers */ | ||
545 | pci_bus_read_config_byte(pci_bus, devfn, PCI_IO_BASE, &temp_byte); | ||
546 | base = temp_byte; | ||
547 | pci_bus_read_config_byte(pci_bus, devfn, PCI_IO_LIMIT, &temp_byte); | ||
548 | length = temp_byte; | ||
549 | |||
550 | if ((base <= length) && (!disable || (save_command & PCI_COMMAND_IO))) { | ||
551 | io_node = kmalloc(sizeof(struct pci_resource), | ||
552 | GFP_KERNEL); | ||
553 | if (!io_node) | ||
554 | return -ENOMEM; | ||
555 | |||
556 | io_node->base = (ulong)(base & PCI_IO_RANGE_MASK) << 8; | ||
557 | io_node->length = (ulong)(length - base + 0x10) << 8; | ||
558 | |||
559 | io_node->next = func->io_head; | ||
560 | func->io_head = io_node; | ||
561 | } | ||
562 | |||
563 | /* Save memory base and Limit registers */ | ||
564 | pci_bus_read_config_word(pci_bus, devfn, PCI_MEMORY_BASE, &w_base); | ||
565 | pci_bus_read_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, &w_length); | ||
566 | |||
567 | if ((w_base <= w_length) && (!disable || (save_command & PCI_COMMAND_MEMORY))) { | ||
568 | mem_node = kmalloc(sizeof(struct pci_resource), | ||
569 | GFP_KERNEL); | ||
570 | if (!mem_node) | ||
571 | return -ENOMEM; | ||
572 | |||
573 | mem_node->base = (ulong)w_base << 16; | ||
574 | mem_node->length = (ulong)(w_length - w_base + 0x10) << 16; | ||
575 | |||
576 | mem_node->next = func->mem_head; | ||
577 | func->mem_head = mem_node; | ||
578 | } | ||
579 | /* Save prefetchable memory base and Limit registers */ | ||
580 | pci_bus_read_config_word(pci_bus, devfn, PCI_PREF_MEMORY_BASE, &w_base); | ||
581 | pci_bus_read_config_word(pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, &w_length); | ||
582 | |||
583 | if ((w_base <= w_length) && (!disable || (save_command & PCI_COMMAND_MEMORY))) { | ||
584 | p_mem_node = kmalloc(sizeof(struct pci_resource), | ||
585 | GFP_KERNEL); | ||
586 | if (!p_mem_node) | ||
587 | return -ENOMEM; | ||
588 | |||
589 | p_mem_node->base = (ulong)w_base << 16; | ||
590 | p_mem_node->length = (ulong)(w_length - w_base + 0x10) << 16; | ||
591 | |||
592 | p_mem_node->next = func->p_mem_head; | ||
593 | func->p_mem_head = p_mem_node; | ||
594 | } | ||
595 | } else if ((header_type & 0x7F) == PCI_HEADER_TYPE_NORMAL) { | ||
596 | dbg("Save_used_res of PCI adapter b:d=0x%x:%x, sc=0x%x\n", | ||
597 | func->bus, func->device, save_command); | ||
598 | |||
599 | /* Figure out IO and memory base lengths */ | ||
600 | for (cloop = PCI_BASE_ADDRESS_0; cloop <= PCI_BASE_ADDRESS_5; cloop += 4) { | ||
601 | pci_bus_read_config_dword(pci_bus, devfn, cloop, &save_base); | ||
602 | |||
603 | temp_register = 0xFFFFFFFF; | ||
604 | pci_bus_write_config_dword(pci_bus, devfn, cloop, temp_register); | ||
605 | pci_bus_read_config_dword(pci_bus, devfn, cloop, &temp_register); | ||
606 | |||
607 | if (!disable) | ||
608 | pci_bus_write_config_dword(pci_bus, devfn, cloop, save_base); | ||
609 | |||
610 | if (!temp_register) | ||
611 | continue; | ||
612 | |||
613 | base = temp_register; | ||
614 | |||
615 | if ((base & PCI_BASE_ADDRESS_SPACE_IO) && | ||
616 | (!disable || (save_command & PCI_COMMAND_IO))) { | ||
617 | /* IO base */ | ||
618 | /* set temp_register = amount of IO space requested */ | ||
619 | base = base & 0xFFFFFFFCL; | ||
620 | base = (~base) + 1; | ||
621 | |||
622 | io_node = kmalloc(sizeof (struct pci_resource), | ||
623 | GFP_KERNEL); | ||
624 | if (!io_node) | ||
625 | return -ENOMEM; | ||
626 | |||
627 | io_node->base = (ulong)save_base & PCI_BASE_ADDRESS_IO_MASK; | ||
628 | io_node->length = (ulong)base; | ||
629 | dbg("sur adapter: IO bar=0x%x(length=0x%x)\n", | ||
630 | io_node->base, io_node->length); | ||
631 | |||
632 | io_node->next = func->io_head; | ||
633 | func->io_head = io_node; | ||
634 | } else { /* map Memory */ | ||
635 | int prefetchable = 1; | ||
636 | /* struct pci_resources **res_node; */ | ||
637 | char *res_type_str = "PMEM"; | ||
638 | u32 temp_register2; | ||
639 | |||
640 | t_mem_node = kmalloc(sizeof (struct pci_resource), | ||
641 | GFP_KERNEL); | ||
642 | if (!t_mem_node) | ||
643 | return -ENOMEM; | ||
644 | |||
645 | if (!(base & PCI_BASE_ADDRESS_MEM_PREFETCH) && | ||
646 | (!disable || (save_command & PCI_COMMAND_MEMORY))) { | ||
647 | prefetchable = 0; | ||
648 | mem_node = t_mem_node; | ||
649 | res_type_str++; | ||
650 | } else | ||
651 | p_mem_node = t_mem_node; | ||
652 | |||
653 | base = base & 0xFFFFFFF0L; | ||
654 | base = (~base) + 1; | ||
655 | |||
656 | switch (temp_register & PCI_BASE_ADDRESS_MEM_TYPE_MASK) { | ||
657 | case PCI_BASE_ADDRESS_MEM_TYPE_32: | ||
658 | if (prefetchable) { | ||
659 | p_mem_node->base = (ulong)save_base & PCI_BASE_ADDRESS_MEM_MASK; | ||
660 | p_mem_node->length = (ulong)base; | ||
661 | dbg("sur adapter: 32 %s bar=0x%x(length=0x%x)\n", | ||
662 | res_type_str, | ||
663 | p_mem_node->base, | ||
664 | p_mem_node->length); | ||
665 | |||
666 | p_mem_node->next = func->p_mem_head; | ||
667 | func->p_mem_head = p_mem_node; | ||
668 | } else { | ||
669 | mem_node->base = (ulong)save_base & PCI_BASE_ADDRESS_MEM_MASK; | ||
670 | mem_node->length = (ulong)base; | ||
671 | dbg("sur adapter: 32 %s bar=0x%x(length=0x%x)\n", | ||
672 | res_type_str, | ||
673 | mem_node->base, | ||
674 | mem_node->length); | ||
675 | |||
676 | mem_node->next = func->mem_head; | ||
677 | func->mem_head = mem_node; | ||
678 | } | ||
679 | break; | ||
680 | case PCI_BASE_ADDRESS_MEM_TYPE_64: | ||
681 | pci_bus_read_config_dword(pci_bus, devfn, cloop+4, &temp_register2); | ||
682 | base64 = temp_register2; | ||
683 | base64 = (base64 << 32) | save_base; | ||
684 | |||
685 | if (temp_register2) { | ||
686 | dbg("sur adapter: 64 %s high dword of base64(0x%x:%x) masked to 0\n", | ||
687 | res_type_str, temp_register2, (u32)base64); | ||
688 | base64 &= 0x00000000FFFFFFFFL; | ||
689 | } | ||
690 | |||
691 | if (prefetchable) { | ||
692 | p_mem_node->base = base64 & PCI_BASE_ADDRESS_MEM_MASK; | ||
693 | p_mem_node->length = base; | ||
694 | dbg("sur adapter: 64 %s base=0x%x(len=0x%x)\n", | ||
695 | res_type_str, | ||
696 | p_mem_node->base, | ||
697 | p_mem_node->length); | ||
698 | |||
699 | p_mem_node->next = func->p_mem_head; | ||
700 | func->p_mem_head = p_mem_node; | ||
701 | } else { | ||
702 | mem_node->base = base64 & PCI_BASE_ADDRESS_MEM_MASK; | ||
703 | mem_node->length = base; | ||
704 | dbg("sur adapter: 64 %s base=0x%x(len=0x%x)\n", | ||
705 | res_type_str, | ||
706 | mem_node->base, | ||
707 | mem_node->length); | ||
708 | |||
709 | mem_node->next = func->mem_head; | ||
710 | func->mem_head = mem_node; | ||
711 | } | ||
712 | cloop += 4; | ||
713 | break; | ||
714 | default: | ||
715 | dbg("asur: reserved BAR type=0x%x\n", | ||
716 | temp_register); | ||
717 | break; | ||
718 | } | ||
719 | } | ||
720 | } /* End of base register loop */ | ||
721 | } else { /* Some other unknown header type */ | ||
722 | dbg("Save_used_res of PCI unknown type b:d=0x%x:%x. skip.\n", | ||
723 | func->bus, func->device); | ||
724 | } | ||
725 | |||
726 | /* find the next device in this slot */ | ||
727 | if (!disable) | ||
728 | break; | ||
729 | func = pciehp_slot_find(func->bus, func->device, index++); | ||
730 | } | ||
731 | |||
732 | return 0; | ||
733 | } | ||
734 | |||
735 | |||
736 | /** | ||
737 | * kfree_resource_list: release memory of all list members | ||
738 | * @res: resource list to free | ||
739 | */ | ||
740 | static inline void | ||
741 | return_resource_list(struct pci_resource **func, struct pci_resource **res) | ||
742 | { | ||
743 | struct pci_resource *node; | ||
744 | struct pci_resource *t_node; | ||
745 | |||
746 | node = *func; | ||
747 | *func = NULL; | ||
748 | while (node) { | ||
749 | t_node = node->next; | ||
750 | return_resource(res, node); | ||
751 | node = t_node; | ||
752 | } | ||
753 | } | ||
754 | |||
755 | /* | ||
756 | * pciehp_return_board_resources | ||
757 | * | ||
758 | * this routine returns all resources allocated to a board to | ||
759 | * the available pool. | ||
760 | * | ||
761 | * returns 0 if success | ||
762 | */ | ||
763 | int pciehp_return_board_resources(struct pci_func * func, | ||
764 | struct resource_lists * resources) | ||
765 | { | ||
766 | int rc; | ||
767 | |||
768 | dbg("%s\n", __FUNCTION__); | ||
769 | |||
770 | if (!func) | ||
771 | return 1; | ||
772 | |||
773 | return_resource_list(&(func->io_head),&(resources->io_head)); | ||
774 | return_resource_list(&(func->mem_head),&(resources->mem_head)); | ||
775 | return_resource_list(&(func->p_mem_head),&(resources->p_mem_head)); | ||
776 | return_resource_list(&(func->bus_head),&(resources->bus_head)); | ||
777 | |||
778 | rc = pciehp_resource_sort_and_combine(&(resources->mem_head)); | ||
779 | rc |= pciehp_resource_sort_and_combine(&(resources->p_mem_head)); | ||
780 | rc |= pciehp_resource_sort_and_combine(&(resources->io_head)); | ||
781 | rc |= pciehp_resource_sort_and_combine(&(resources->bus_head)); | ||
782 | |||
783 | return rc; | ||
784 | } | ||
785 | |||
786 | /** | ||
787 | * kfree_resource_list: release memory of all list members | ||
788 | * @res: resource list to free | ||
789 | */ | ||
790 | static inline void | ||
791 | kfree_resource_list(struct pci_resource **r) | ||
792 | { | ||
793 | struct pci_resource *res, *tres; | ||
794 | |||
795 | res = *r; | ||
796 | *r = NULL; | ||
797 | |||
798 | while (res) { | ||
799 | tres = res; | ||
800 | res = res->next; | ||
801 | kfree(tres); | ||
802 | } | ||
803 | } | ||
804 | |||
805 | /** | ||
806 | * pciehp_destroy_resource_list: put node back in the resource list | ||
807 | * @resources: list to put nodes back | ||
808 | */ | ||
809 | void pciehp_destroy_resource_list(struct resource_lists * resources) | ||
810 | { | ||
811 | kfree_resource_list(&(resources->io_head)); | ||
812 | kfree_resource_list(&(resources->mem_head)); | ||
813 | kfree_resource_list(&(resources->p_mem_head)); | ||
814 | kfree_resource_list(&(resources->bus_head)); | ||
815 | } | ||
816 | |||
817 | /** | ||
818 | * pciehp_destroy_board_resources: put node back in the resource list | ||
819 | * @resources: list to put nodes back | ||
820 | */ | ||
821 | void pciehp_destroy_board_resources(struct pci_func * func) | ||
822 | { | ||
823 | kfree_resource_list(&(func->io_head)); | ||
824 | kfree_resource_list(&(func->mem_head)); | ||
825 | kfree_resource_list(&(func->p_mem_head)); | ||
826 | kfree_resource_list(&(func->bus_head)); | ||
827 | } | ||
diff --git a/drivers/pci/hotplug/pciehprm.h b/drivers/pci/hotplug/pciehprm.h deleted file mode 100644 index 05f20fbc5f50..000000000000 --- a/drivers/pci/hotplug/pciehprm.h +++ /dev/null | |||
@@ -1,52 +0,0 @@ | |||
1 | /* | ||
2 | * PCIEHPRM : PCIEHP Resource Manager for ACPI/non-ACPI platform | ||
3 | * | ||
4 | * Copyright (C) 1995,2001 Compaq Computer Corporation | ||
5 | * Copyright (C) 2001,2003 Greg Kroah-Hartman (greg@kroah.com) | ||
6 | * Copyright (C) 2001 IBM Corp. | ||
7 | * Copyright (C) 2003-2004 Intel Corporation | ||
8 | * | ||
9 | * All rights reserved. | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 of the License, or (at | ||
14 | * your option) any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, but | ||
17 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
19 | * NON INFRINGEMENT. See the GNU General Public License for more | ||
20 | * details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | * | ||
26 | * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com> | ||
27 | * | ||
28 | */ | ||
29 | |||
30 | #ifndef _PCIEHPRM_H_ | ||
31 | #define _PCIEHPRM_H_ | ||
32 | |||
33 | #ifdef CONFIG_HOTPLUG_PCI_PCIE_PHPRM_NONACPI | ||
34 | #include "pciehprm_nonacpi.h" | ||
35 | #endif | ||
36 | |||
37 | int pciehprm_init(enum php_ctlr_type ct); | ||
38 | void pciehprm_cleanup(void); | ||
39 | int pciehprm_print_pirt(void); | ||
40 | int pciehprm_find_available_resources(struct controller *ctrl); | ||
41 | int pciehprm_set_hpp(struct controller *ctrl, struct pci_func *func, u8 card_type); | ||
42 | void pciehprm_enable_card(struct controller *ctrl, struct pci_func *func, u8 card_type); | ||
43 | |||
44 | #ifdef DEBUG | ||
45 | #define RES_CHECK(this, bits) \ | ||
46 | { if (((this) & (bits - 1))) \ | ||
47 | printk("%s:%d ERR: potential res loss!\n", __FUNCTION__, __LINE__); } | ||
48 | #else | ||
49 | #define RES_CHECK(this, bits) | ||
50 | #endif | ||
51 | |||
52 | #endif /* _PCIEHPRM_H_ */ | ||
diff --git a/drivers/pci/hotplug/pciehprm_acpi.c b/drivers/pci/hotplug/pciehprm_acpi.c index 1406db35b089..ae244e218620 100644 --- a/drivers/pci/hotplug/pciehprm_acpi.c +++ b/drivers/pci/hotplug/pciehprm_acpi.c | |||
@@ -24,100 +24,20 @@ | |||
24 | * | 24 | * |
25 | */ | 25 | */ |
26 | 26 | ||
27 | #include <linux/config.h> | ||
28 | #include <linux/module.h> | 27 | #include <linux/module.h> |
29 | #include <linux/kernel.h> | 28 | #include <linux/kernel.h> |
30 | #include <linux/types.h> | 29 | #include <linux/types.h> |
31 | #include <linux/pci.h> | 30 | #include <linux/pci.h> |
32 | #include <linux/init.h> | ||
33 | #include <linux/acpi.h> | 31 | #include <linux/acpi.h> |
34 | #include <linux/efi.h> | ||
35 | #include <linux/pci-acpi.h> | 32 | #include <linux/pci-acpi.h> |
36 | #include <asm/uaccess.h> | ||
37 | #include <asm/system.h> | ||
38 | #ifdef CONFIG_IA64 | ||
39 | #include <asm/iosapic.h> | ||
40 | #endif | ||
41 | #include <acpi/acpi.h> | ||
42 | #include <acpi/acpi_bus.h> | 33 | #include <acpi/acpi_bus.h> |
43 | #include <acpi/actypes.h> | 34 | #include <acpi/actypes.h> |
44 | #include "pciehp.h" | 35 | #include "pciehp.h" |
45 | #include "pciehprm.h" | ||
46 | |||
47 | #define PCI_MAX_BUS 0x100 | ||
48 | #define ACPI_STA_DEVICE_PRESENT 0x01 | ||
49 | 36 | ||
50 | #define METHOD_NAME__SUN "_SUN" | 37 | #define METHOD_NAME__SUN "_SUN" |
51 | #define METHOD_NAME__HPP "_HPP" | 38 | #define METHOD_NAME__HPP "_HPP" |
52 | #define METHOD_NAME_OSHP "OSHP" | 39 | #define METHOD_NAME_OSHP "OSHP" |
53 | 40 | ||
54 | /* Status code for running acpi method to gain native control */ | ||
55 | #define NC_NOT_RUN 0 | ||
56 | #define OSC_NOT_EXIST 1 | ||
57 | #define OSC_RUN_FAILED 2 | ||
58 | #define OSHP_NOT_EXIST 3 | ||
59 | #define OSHP_RUN_FAILED 4 | ||
60 | #define NC_RUN_SUCCESS 5 | ||
61 | |||
62 | #define PHP_RES_BUS 0xA0 | ||
63 | #define PHP_RES_IO 0xA1 | ||
64 | #define PHP_RES_MEM 0xA2 | ||
65 | #define PHP_RES_PMEM 0xA3 | ||
66 | |||
67 | #define BRIDGE_TYPE_P2P 0x00 | ||
68 | #define BRIDGE_TYPE_HOST 0x01 | ||
69 | |||
70 | /* this should go to drivers/acpi/include/ */ | ||
71 | struct acpi__hpp { | ||
72 | u8 cache_line_size; | ||
73 | u8 latency_timer; | ||
74 | u8 enable_serr; | ||
75 | u8 enable_perr; | ||
76 | }; | ||
77 | |||
78 | struct acpi_php_slot { | ||
79 | struct acpi_php_slot *next; | ||
80 | struct acpi_bridge *bridge; | ||
81 | acpi_handle handle; | ||
82 | int seg; | ||
83 | int bus; | ||
84 | int dev; | ||
85 | int fun; | ||
86 | u32 sun; | ||
87 | struct pci_resource *mem_head; | ||
88 | struct pci_resource *p_mem_head; | ||
89 | struct pci_resource *io_head; | ||
90 | struct pci_resource *bus_head; | ||
91 | void *slot_ops; /* _STA, _EJx, etc */ | ||
92 | struct slot *slot; | ||
93 | }; /* per func */ | ||
94 | |||
95 | struct acpi_bridge { | ||
96 | struct acpi_bridge *parent; | ||
97 | struct acpi_bridge *next; | ||
98 | struct acpi_bridge *child; | ||
99 | acpi_handle handle; | ||
100 | int seg; | ||
101 | int pbus; /* pdev->bus->number */ | ||
102 | int pdevice; /* PCI_SLOT(pdev->devfn) */ | ||
103 | int pfunction; /* PCI_DEVFN(pdev->devfn) */ | ||
104 | int bus; /* pdev->subordinate->number */ | ||
105 | struct acpi__hpp *_hpp; | ||
106 | struct acpi_php_slot *slots; | ||
107 | struct pci_resource *tmem_head; /* total from crs */ | ||
108 | struct pci_resource *tp_mem_head; /* total from crs */ | ||
109 | struct pci_resource *tio_head; /* total from crs */ | ||
110 | struct pci_resource *tbus_head; /* total from crs */ | ||
111 | struct pci_resource *mem_head; /* available */ | ||
112 | struct pci_resource *p_mem_head; /* available */ | ||
113 | struct pci_resource *io_head; /* available */ | ||
114 | struct pci_resource *bus_head; /* available */ | ||
115 | int scanned; | ||
116 | int type; | ||
117 | }; | ||
118 | |||
119 | static struct acpi_bridge *acpi_bridges_head; | ||
120 | |||
121 | static u8 * acpi_path_name( acpi_handle handle) | 41 | static u8 * acpi_path_name( acpi_handle handle) |
122 | { | 42 | { |
123 | acpi_status status; | 43 | acpi_status status; |
@@ -133,85 +53,43 @@ static u8 * acpi_path_name( acpi_handle handle) | |||
133 | return path_name; | 53 | return path_name; |
134 | } | 54 | } |
135 | 55 | ||
136 | static void acpi_get__hpp ( struct acpi_bridge *ab); | 56 | static acpi_status |
137 | static int acpi_run_oshp ( struct acpi_bridge *ab); | 57 | acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) |
138 | static int osc_run_status = NC_NOT_RUN; | ||
139 | static int oshp_run_status = NC_NOT_RUN; | ||
140 | |||
141 | static int acpi_add_slot_to_php_slots( | ||
142 | struct acpi_bridge *ab, | ||
143 | int bus_num, | ||
144 | acpi_handle handle, | ||
145 | u32 adr, | ||
146 | u32 sun | ||
147 | ) | ||
148 | { | ||
149 | struct acpi_php_slot *aps; | ||
150 | static long samesun = -1; | ||
151 | |||
152 | aps = (struct acpi_php_slot *) kmalloc (sizeof(struct acpi_php_slot), GFP_KERNEL); | ||
153 | if (!aps) { | ||
154 | err ("acpi_pciehprm: alloc for aps fail\n"); | ||
155 | return -1; | ||
156 | } | ||
157 | memset(aps, 0, sizeof(struct acpi_php_slot)); | ||
158 | |||
159 | aps->handle = handle; | ||
160 | aps->bus = bus_num; | ||
161 | aps->dev = (adr >> 16) & 0xffff; | ||
162 | aps->fun = adr & 0xffff; | ||
163 | aps->sun = sun; | ||
164 | |||
165 | aps->next = ab->slots; /* cling to the bridge */ | ||
166 | aps->bridge = ab; | ||
167 | ab->slots = aps; | ||
168 | |||
169 | ab->scanned += 1; | ||
170 | if (!ab->_hpp) | ||
171 | acpi_get__hpp(ab); | ||
172 | |||
173 | if (osc_run_status == OSC_NOT_EXIST) | ||
174 | oshp_run_status = acpi_run_oshp(ab); | ||
175 | |||
176 | if (sun != samesun) { | ||
177 | info("acpi_pciehprm: Slot sun(%x) at s:b:d:f=0x%02x:%02x:%02x:%02x\n", | ||
178 | aps->sun, ab->seg, aps->bus, aps->dev, aps->fun); | ||
179 | samesun = sun; | ||
180 | } | ||
181 | return 0; | ||
182 | } | ||
183 | |||
184 | static void acpi_get__hpp ( struct acpi_bridge *ab) | ||
185 | { | 58 | { |
186 | acpi_status status; | 59 | acpi_status status; |
187 | u8 nui[4]; | 60 | u8 nui[4]; |
188 | struct acpi_buffer ret_buf = { 0, NULL}; | 61 | struct acpi_buffer ret_buf = { 0, NULL}; |
189 | union acpi_object *ext_obj, *package; | 62 | union acpi_object *ext_obj, *package; |
190 | u8 *path_name = acpi_path_name(ab->handle); | 63 | u8 *path_name = acpi_path_name(handle); |
191 | int i, len = 0; | 64 | int i, len = 0; |
192 | 65 | ||
193 | /* get _hpp */ | 66 | /* get _hpp */ |
194 | status = acpi_evaluate_object(ab->handle, METHOD_NAME__HPP, NULL, &ret_buf); | 67 | status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf); |
195 | switch (status) { | 68 | switch (status) { |
196 | case AE_BUFFER_OVERFLOW: | 69 | case AE_BUFFER_OVERFLOW: |
197 | ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL); | 70 | ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL); |
198 | if (!ret_buf.pointer) { | 71 | if (!ret_buf.pointer) { |
199 | err ("acpi_pciehprm:%s alloc for _HPP fail\n", path_name); | 72 | err ("%s:%s alloc for _HPP fail\n", __FUNCTION__, |
200 | return; | 73 | path_name); |
74 | return AE_NO_MEMORY; | ||
201 | } | 75 | } |
202 | status = acpi_evaluate_object(ab->handle, METHOD_NAME__HPP, NULL, &ret_buf); | 76 | status = acpi_evaluate_object(handle, METHOD_NAME__HPP, |
77 | NULL, &ret_buf); | ||
203 | if (ACPI_SUCCESS(status)) | 78 | if (ACPI_SUCCESS(status)) |
204 | break; | 79 | break; |
205 | default: | 80 | default: |
206 | if (ACPI_FAILURE(status)) { | 81 | if (ACPI_FAILURE(status)) { |
207 | err("acpi_pciehprm:%s _HPP fail=0x%x\n", path_name, status); | 82 | dbg("%s:%s _HPP fail=0x%x\n", __FUNCTION__, |
208 | return; | 83 | path_name, status); |
84 | return status; | ||
209 | } | 85 | } |
210 | } | 86 | } |
211 | 87 | ||
212 | ext_obj = (union acpi_object *) ret_buf.pointer; | 88 | ext_obj = (union acpi_object *) ret_buf.pointer; |
213 | if (ext_obj->type != ACPI_TYPE_PACKAGE) { | 89 | if (ext_obj->type != ACPI_TYPE_PACKAGE) { |
214 | err ("acpi_pciehprm:%s _HPP obj not a package\n", path_name); | 90 | err ("%s:%s _HPP obj not a package\n", __FUNCTION__, |
91 | path_name); | ||
92 | status = AE_ERROR; | ||
215 | goto free_and_return; | 93 | goto free_and_return; |
216 | } | 94 | } |
217 | 95 | ||
@@ -224,1514 +102,153 @@ static void acpi_get__hpp ( struct acpi_bridge *ab) | |||
224 | nui[i] = (u8)ext_obj->integer.value; | 102 | nui[i] = (u8)ext_obj->integer.value; |
225 | break; | 103 | break; |
226 | default: | 104 | default: |
227 | err ("acpi_pciehprm:%s _HPP obj type incorrect\n", path_name); | 105 | err ("%s:%s _HPP obj type incorrect\n", __FUNCTION__, |
106 | path_name); | ||
107 | status = AE_ERROR; | ||
228 | goto free_and_return; | 108 | goto free_and_return; |
229 | } | 109 | } |
230 | } | 110 | } |
231 | 111 | ||
232 | ab->_hpp = kmalloc (sizeof (struct acpi__hpp), GFP_KERNEL); | 112 | hpp->cache_line_size = nui[0]; |
233 | if (!ab->_hpp) { | 113 | hpp->latency_timer = nui[1]; |
234 | err ("acpi_pciehprm:%s alloc for _HPP failed\n", path_name); | 114 | hpp->enable_serr = nui[2]; |
235 | goto free_and_return; | 115 | hpp->enable_perr = nui[3]; |
236 | } | ||
237 | memset(ab->_hpp, 0, sizeof(struct acpi__hpp)); | ||
238 | 116 | ||
239 | ab->_hpp->cache_line_size = nui[0]; | 117 | dbg(" _HPP: cache_line_size=0x%x\n", hpp->cache_line_size); |
240 | ab->_hpp->latency_timer = nui[1]; | 118 | dbg(" _HPP: latency timer =0x%x\n", hpp->latency_timer); |
241 | ab->_hpp->enable_serr = nui[2]; | 119 | dbg(" _HPP: enable SERR =0x%x\n", hpp->enable_serr); |
242 | ab->_hpp->enable_perr = nui[3]; | 120 | dbg(" _HPP: enable PERR =0x%x\n", hpp->enable_perr); |
243 | |||
244 | dbg(" _HPP: cache_line_size=0x%x\n", ab->_hpp->cache_line_size); | ||
245 | dbg(" _HPP: latency timer =0x%x\n", ab->_hpp->latency_timer); | ||
246 | dbg(" _HPP: enable SERR =0x%x\n", ab->_hpp->enable_serr); | ||
247 | dbg(" _HPP: enable PERR =0x%x\n", ab->_hpp->enable_perr); | ||
248 | 121 | ||
249 | free_and_return: | 122 | free_and_return: |
250 | kfree(ret_buf.pointer); | 123 | kfree(ret_buf.pointer); |
124 | return status; | ||
251 | } | 125 | } |
252 | 126 | ||
253 | static int acpi_run_oshp ( struct acpi_bridge *ab) | 127 | static acpi_status acpi_run_oshp(acpi_handle handle) |
254 | { | 128 | { |
255 | acpi_status status; | 129 | acpi_status status; |
256 | u8 *path_name = acpi_path_name(ab->handle); | 130 | u8 *path_name = acpi_path_name(handle); |
257 | 131 | ||
258 | /* run OSHP */ | 132 | /* run OSHP */ |
259 | status = acpi_evaluate_object(ab->handle, METHOD_NAME_OSHP, NULL, NULL); | 133 | status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL); |
260 | if (ACPI_FAILURE(status)) { | 134 | if (ACPI_FAILURE(status)) { |
261 | err("acpi_pciehprm:%s OSHP fails=0x%x\n", path_name, status); | 135 | dbg("%s:%s OSHP fails=0x%x\n", __FUNCTION__, path_name, |
262 | oshp_run_status = (status == AE_NOT_FOUND) ? OSHP_NOT_EXIST : OSHP_RUN_FAILED; | 136 | status); |
263 | } else { | 137 | } else { |
264 | oshp_run_status = NC_RUN_SUCCESS; | 138 | dbg("%s:%s OSHP passes\n", __FUNCTION__, path_name); |
265 | dbg("acpi_pciehprm:%s OSHP passes =0x%x\n", path_name, status); | ||
266 | dbg("acpi_pciehprm:%s oshp_run_status =0x%x\n", path_name, oshp_run_status); | ||
267 | } | ||
268 | return oshp_run_status; | ||
269 | } | ||
270 | |||
271 | static acpi_status acpi_evaluate_crs( | ||
272 | acpi_handle handle, | ||
273 | struct acpi_resource **retbuf | ||
274 | ) | ||
275 | { | ||
276 | acpi_status status; | ||
277 | struct acpi_buffer crsbuf; | ||
278 | u8 *path_name = acpi_path_name(handle); | ||
279 | |||
280 | crsbuf.length = 0; | ||
281 | crsbuf.pointer = NULL; | ||
282 | |||
283 | status = acpi_get_current_resources (handle, &crsbuf); | ||
284 | |||
285 | switch (status) { | ||
286 | case AE_BUFFER_OVERFLOW: | ||
287 | break; /* found */ | ||
288 | case AE_NOT_FOUND: | ||
289 | dbg("acpi_pciehprm:%s _CRS not found\n", path_name); | ||
290 | return status; | ||
291 | default: | ||
292 | err ("acpi_pciehprm:%s _CRS fail=0x%x\n", path_name, status); | ||
293 | return status; | ||
294 | } | 139 | } |
295 | |||
296 | crsbuf.pointer = kmalloc (crsbuf.length, GFP_KERNEL); | ||
297 | if (!crsbuf.pointer) { | ||
298 | err ("acpi_pciehprm: alloc %ld bytes for %s _CRS fail\n", (ulong)crsbuf.length, path_name); | ||
299 | return AE_NO_MEMORY; | ||
300 | } | ||
301 | |||
302 | status = acpi_get_current_resources (handle, &crsbuf); | ||
303 | if (ACPI_FAILURE(status)) { | ||
304 | err("acpi_pciehprm: %s _CRS fail=0x%x.\n", path_name, status); | ||
305 | kfree(crsbuf.pointer); | ||
306 | return status; | ||
307 | } | ||
308 | |||
309 | *retbuf = crsbuf.pointer; | ||
310 | |||
311 | return status; | 140 | return status; |
312 | } | 141 | } |
313 | 142 | ||
314 | static void free_pci_resource ( struct pci_resource *aprh) | 143 | static int is_root_bridge(acpi_handle handle) |
315 | { | 144 | { |
316 | struct pci_resource *res, *next; | 145 | acpi_status status; |
146 | struct acpi_device_info *info; | ||
147 | struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; | ||
148 | int i; | ||
317 | 149 | ||
318 | for (res = aprh; res; res = next) { | 150 | status = acpi_get_object_info(handle, &buffer); |
319 | next = res->next; | 151 | if (ACPI_SUCCESS(status)) { |
320 | kfree(res); | 152 | info = buffer.pointer; |
321 | } | 153 | if ((info->valid & ACPI_VALID_HID) && |
322 | } | 154 | !strcmp(PCI_ROOT_HID_STRING, |
323 | 155 | info->hardware_id.value)) { | |
324 | static void print_pci_resource ( struct pci_resource *aprh) | 156 | acpi_os_free(buffer.pointer); |
325 | { | 157 | return 1; |
326 | struct pci_resource *res; | 158 | } |
327 | 159 | if (info->valid & ACPI_VALID_CID) { | |
328 | for (res = aprh; res; res = res->next) | 160 | for (i=0; i < info->compatibility_id.count; i++) { |
329 | dbg(" base= 0x%x length= 0x%x\n", res->base, res->length); | 161 | if (!strcmp(PCI_ROOT_HID_STRING, |
330 | } | 162 | info->compatibility_id.id[i].value)) { |
331 | 163 | acpi_os_free(buffer.pointer); | |
332 | static void print_slot_resources( struct acpi_php_slot *aps) | 164 | return 1; |
333 | { | 165 | } |
334 | if (aps->bus_head) { | 166 | } |
335 | dbg(" BUS Resources:\n"); | ||
336 | print_pci_resource (aps->bus_head); | ||
337 | } | ||
338 | |||
339 | if (aps->io_head) { | ||
340 | dbg(" IO Resources:\n"); | ||
341 | print_pci_resource (aps->io_head); | ||
342 | } | ||
343 | |||
344 | if (aps->mem_head) { | ||
345 | dbg(" MEM Resources:\n"); | ||
346 | print_pci_resource (aps->mem_head); | ||
347 | } | ||
348 | |||
349 | if (aps->p_mem_head) { | ||
350 | dbg(" PMEM Resources:\n"); | ||
351 | print_pci_resource (aps->p_mem_head); | ||
352 | } | ||
353 | } | ||
354 | |||
355 | static void print_pci_resources( struct acpi_bridge *ab) | ||
356 | { | ||
357 | if (ab->tbus_head) { | ||
358 | dbg(" Total BUS Resources:\n"); | ||
359 | print_pci_resource (ab->tbus_head); | ||
360 | } | ||
361 | if (ab->bus_head) { | ||
362 | dbg(" BUS Resources:\n"); | ||
363 | print_pci_resource (ab->bus_head); | ||
364 | } | ||
365 | |||
366 | if (ab->tio_head) { | ||
367 | dbg(" Total IO Resources:\n"); | ||
368 | print_pci_resource (ab->tio_head); | ||
369 | } | ||
370 | if (ab->io_head) { | ||
371 | dbg(" IO Resources:\n"); | ||
372 | print_pci_resource (ab->io_head); | ||
373 | } | ||
374 | |||
375 | if (ab->tmem_head) { | ||
376 | dbg(" Total MEM Resources:\n"); | ||
377 | print_pci_resource (ab->tmem_head); | ||
378 | } | ||
379 | if (ab->mem_head) { | ||
380 | dbg(" MEM Resources:\n"); | ||
381 | print_pci_resource (ab->mem_head); | ||
382 | } | ||
383 | |||
384 | if (ab->tp_mem_head) { | ||
385 | dbg(" Total PMEM Resources:\n"); | ||
386 | print_pci_resource (ab->tp_mem_head); | ||
387 | } | ||
388 | if (ab->p_mem_head) { | ||
389 | dbg(" PMEM Resources:\n"); | ||
390 | print_pci_resource (ab->p_mem_head); | ||
391 | } | ||
392 | if (ab->_hpp) { | ||
393 | dbg(" _HPP: cache_line_size=0x%x\n", ab->_hpp->cache_line_size); | ||
394 | dbg(" _HPP: latency timer =0x%x\n", ab->_hpp->latency_timer); | ||
395 | dbg(" _HPP: enable SERR =0x%x\n", ab->_hpp->enable_serr); | ||
396 | dbg(" _HPP: enable PERR =0x%x\n", ab->_hpp->enable_perr); | ||
397 | } | ||
398 | } | ||
399 | |||
400 | static int pciehprm_delete_resource( | ||
401 | struct pci_resource **aprh, | ||
402 | ulong base, | ||
403 | ulong size) | ||
404 | { | ||
405 | struct pci_resource *res; | ||
406 | struct pci_resource *prevnode; | ||
407 | struct pci_resource *split_node; | ||
408 | ulong tbase; | ||
409 | |||
410 | pciehp_resource_sort_and_combine(aprh); | ||
411 | |||
412 | for (res = *aprh; res; res = res->next) { | ||
413 | if (res->base > base) | ||
414 | continue; | ||
415 | |||
416 | if ((res->base + res->length) < (base + size)) | ||
417 | continue; | ||
418 | |||
419 | if (res->base < base) { | ||
420 | tbase = base; | ||
421 | |||
422 | if ((res->length - (tbase - res->base)) < size) | ||
423 | continue; | ||
424 | |||
425 | split_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); | ||
426 | if (!split_node) | ||
427 | return -ENOMEM; | ||
428 | |||
429 | split_node->base = res->base; | ||
430 | split_node->length = tbase - res->base; | ||
431 | res->base = tbase; | ||
432 | res->length -= split_node->length; | ||
433 | |||
434 | split_node->next = res->next; | ||
435 | res->next = split_node; | ||
436 | } | ||
437 | |||
438 | if (res->length >= size) { | ||
439 | split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); | ||
440 | if (!split_node) | ||
441 | return -ENOMEM; | ||
442 | |||
443 | split_node->base = res->base + size; | ||
444 | split_node->length = res->length - size; | ||
445 | res->length = size; | ||
446 | |||
447 | split_node->next = res->next; | ||
448 | res->next = split_node; | ||
449 | } | ||
450 | |||
451 | if (*aprh == res) { | ||
452 | *aprh = res->next; | ||
453 | } else { | ||
454 | prevnode = *aprh; | ||
455 | while (prevnode->next != res) | ||
456 | prevnode = prevnode->next; | ||
457 | |||
458 | prevnode->next = res->next; | ||
459 | } | ||
460 | res->next = NULL; | ||
461 | kfree(res); | ||
462 | break; | ||
463 | } | ||
464 | |||
465 | return 0; | ||
466 | } | ||
467 | |||
468 | static int pciehprm_delete_resources( | ||
469 | struct pci_resource **aprh, | ||
470 | struct pci_resource *this | ||
471 | ) | ||
472 | { | ||
473 | struct pci_resource *res; | ||
474 | |||
475 | for (res = this; res; res = res->next) | ||
476 | pciehprm_delete_resource(aprh, res->base, res->length); | ||
477 | |||
478 | return 0; | ||
479 | } | ||
480 | |||
481 | static int pciehprm_add_resource( | ||
482 | struct pci_resource **aprh, | ||
483 | ulong base, | ||
484 | ulong size) | ||
485 | { | ||
486 | struct pci_resource *res; | ||
487 | |||
488 | for (res = *aprh; res; res = res->next) { | ||
489 | if ((res->base + res->length) == base) { | ||
490 | res->length += size; | ||
491 | size = 0L; | ||
492 | break; | ||
493 | } | 167 | } |
494 | if (res->next == *aprh) | ||
495 | break; | ||
496 | } | 168 | } |
497 | |||
498 | if (size) { | ||
499 | res = kmalloc(sizeof(struct pci_resource), GFP_KERNEL); | ||
500 | if (!res) { | ||
501 | err ("acpi_pciehprm: alloc for res fail\n"); | ||
502 | return -ENOMEM; | ||
503 | } | ||
504 | memset(res, 0, sizeof (struct pci_resource)); | ||
505 | |||
506 | res->base = base; | ||
507 | res->length = size; | ||
508 | res->next = *aprh; | ||
509 | *aprh = res; | ||
510 | } | ||
511 | |||
512 | return 0; | 169 | return 0; |
513 | } | 170 | } |
514 | 171 | ||
515 | static int pciehprm_add_resources( | 172 | int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev) |
516 | struct pci_resource **aprh, | ||
517 | struct pci_resource *this | ||
518 | ) | ||
519 | { | ||
520 | struct pci_resource *res; | ||
521 | int rc = 0; | ||
522 | |||
523 | for (res = this; res && !rc; res = res->next) | ||
524 | rc = pciehprm_add_resource(aprh, res->base, res->length); | ||
525 | |||
526 | return rc; | ||
527 | } | ||
528 | |||
529 | static void acpi_parse_io ( | ||
530 | struct acpi_bridge *ab, | ||
531 | union acpi_resource_data *data | ||
532 | ) | ||
533 | { | 173 | { |
534 | struct acpi_resource_io *dataio; | 174 | acpi_status status; |
535 | dataio = (struct acpi_resource_io *) data; | 175 | acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev)); |
536 | 176 | struct pci_dev *pdev = dev; | |
537 | dbg("Io Resource\n"); | 177 | u8 *path_name; |
538 | dbg(" %d bit decode\n", ACPI_DECODE_16 == dataio->io_decode ? 16:10); | 178 | /* |
539 | dbg(" Range minimum base: %08X\n", dataio->min_base_address); | 179 | * Per PCI firmware specification, we should run the ACPI _OSC |
540 | dbg(" Range maximum base: %08X\n", dataio->max_base_address); | 180 | * method to get control of hotplug hardware before using it. |
541 | dbg(" Alignment: %08X\n", dataio->alignment); | 181 | * If an _OSC is missing, we look for an OSHP to do the same thing. |
542 | dbg(" Range Length: %08X\n", dataio->range_length); | 182 | * To handle different BIOS behavior, we look for _OSC and OSHP |
543 | } | 183 | * within the scope of the hotplug controller and its parents, upto |
544 | 184 | * the host bridge under which this controller exists. | |
545 | static void acpi_parse_fixed_io ( | ||
546 | struct acpi_bridge *ab, | ||
547 | union acpi_resource_data *data | ||
548 | ) | ||
549 | { | ||
550 | struct acpi_resource_fixed_io *datafio; | ||
551 | datafio = (struct acpi_resource_fixed_io *) data; | ||
552 | |||
553 | dbg("Fixed Io Resource\n"); | ||
554 | dbg(" Range base address: %08X", datafio->base_address); | ||
555 | dbg(" Range length: %08X", datafio->range_length); | ||
556 | } | ||
557 | |||
558 | static void acpi_parse_address16_32 ( | ||
559 | struct acpi_bridge *ab, | ||
560 | union acpi_resource_data *data, | ||
561 | acpi_resource_type id | ||
562 | ) | ||
563 | { | ||
564 | /* | ||
565 | * acpi_resource_address16 == acpi_resource_address32 | ||
566 | * acpi_resource_address16 *data16 = (acpi_resource_address16 *) data; | ||
567 | */ | 185 | */ |
568 | struct acpi_resource_address32 *data32 = (struct acpi_resource_address32 *) data; | 186 | while (!handle) { |
569 | struct pci_resource **aprh, **tprh; | 187 | /* |
570 | 188 | * This hotplug controller was not listed in the ACPI name | |
571 | if (id == ACPI_RSTYPE_ADDRESS16) | 189 | * space at all. Try to get acpi handle of parent pci bus. |
572 | dbg("acpi_pciehprm:16-Bit Address Space Resource\n"); | 190 | */ |
573 | else | 191 | if (!pdev || !pdev->bus->parent) |
574 | dbg("acpi_pciehprm:32-Bit Address Space Resource\n"); | ||
575 | |||
576 | switch (data32->resource_type) { | ||
577 | case ACPI_MEMORY_RANGE: | ||
578 | dbg(" Resource Type: Memory Range\n"); | ||
579 | aprh = &ab->mem_head; | ||
580 | tprh = &ab->tmem_head; | ||
581 | |||
582 | switch (data32->attribute.memory.cache_attribute) { | ||
583 | case ACPI_NON_CACHEABLE_MEMORY: | ||
584 | dbg(" Type Specific: Noncacheable memory\n"); | ||
585 | break; | ||
586 | case ACPI_CACHABLE_MEMORY: | ||
587 | dbg(" Type Specific: Cacheable memory\n"); | ||
588 | break; | ||
589 | case ACPI_WRITE_COMBINING_MEMORY: | ||
590 | dbg(" Type Specific: Write-combining memory\n"); | ||
591 | break; | ||
592 | case ACPI_PREFETCHABLE_MEMORY: | ||
593 | aprh = &ab->p_mem_head; | ||
594 | dbg(" Type Specific: Prefetchable memory\n"); | ||
595 | break; | ||
596 | default: | ||
597 | dbg(" Type Specific: Invalid cache attribute\n"); | ||
598 | break; | 192 | break; |
599 | } | 193 | dbg("Could not find %s in acpi namespace, trying parent\n", |
600 | 194 | pci_name(pdev)); | |
601 | dbg(" Type Specific: Read%s\n", ACPI_READ_WRITE_MEMORY == data32->attribute.memory.read_write_attribute ? "/Write":" Only"); | 195 | if (!pdev->bus->parent->self) |
602 | break; | 196 | /* Parent must be a host bridge */ |
603 | 197 | handle = acpi_get_pci_rootbridge_handle( | |
604 | case ACPI_IO_RANGE: | 198 | pci_domain_nr(pdev->bus->parent), |
605 | dbg(" Resource Type: I/O Range\n"); | 199 | pdev->bus->parent->number); |
606 | aprh = &ab->io_head; | 200 | else |
607 | tprh = &ab->tio_head; | 201 | handle = DEVICE_ACPI_HANDLE( |
608 | 202 | &(pdev->bus->parent->self->dev)); | |
609 | switch (data32->attribute.io.range_attribute) { | 203 | pdev = pdev->bus->parent->self; |
610 | case ACPI_NON_ISA_ONLY_RANGES: | 204 | } |
611 | dbg(" Type Specific: Non-ISA Io Addresses\n"); | 205 | |
612 | break; | 206 | while (handle) { |
613 | case ACPI_ISA_ONLY_RANGES: | 207 | path_name = acpi_path_name(handle); |
614 | dbg(" Type Specific: ISA Io Addresses\n"); | 208 | dbg("Trying to get hotplug control for %s \n", path_name); |
615 | break; | 209 | status = pci_osc_control_set(handle, |
616 | case ACPI_ENTIRE_RANGE: | 210 | OSC_PCI_EXPRESS_NATIVE_HP_CONTROL); |
617 | dbg(" Type Specific: ISA and non-ISA Io Addresses\n"); | 211 | if (status == AE_NOT_FOUND) |
618 | break; | 212 | status = acpi_run_oshp(handle); |
619 | default: | 213 | if (ACPI_SUCCESS(status)) { |
620 | dbg(" Type Specific: Invalid range attribute\n"); | 214 | dbg("Gained control for hotplug HW for pci %s (%s)\n", |
215 | pci_name(dev), path_name); | ||
216 | return 0; | ||
217 | } | ||
218 | if (is_root_bridge(handle)) | ||
621 | break; | 219 | break; |
622 | } | 220 | chandle = handle; |
623 | break; | 221 | status = acpi_get_parent(chandle, &handle); |
624 | |||
625 | case ACPI_BUS_NUMBER_RANGE: | ||
626 | dbg(" Resource Type: Bus Number Range(fixed)\n"); | ||
627 | /* fixup to be compatible with the rest of php driver */ | ||
628 | data32->min_address_range++; | ||
629 | data32->address_length--; | ||
630 | aprh = &ab->bus_head; | ||
631 | tprh = &ab->tbus_head; | ||
632 | break; | ||
633 | default: | ||
634 | dbg(" Resource Type: Invalid resource type. Exiting.\n"); | ||
635 | return; | ||
636 | } | ||
637 | |||
638 | dbg(" Resource %s\n", ACPI_CONSUMER == data32->producer_consumer ? "Consumer":"Producer"); | ||
639 | dbg(" %s decode\n", ACPI_SUB_DECODE == data32->decode ? "Subtractive":"Positive"); | ||
640 | dbg(" Min address is %s fixed\n", ACPI_ADDRESS_FIXED == data32->min_address_fixed ? "":"not"); | ||
641 | dbg(" Max address is %s fixed\n", ACPI_ADDRESS_FIXED == data32->max_address_fixed ? "":"not"); | ||
642 | dbg(" Granularity: %08X\n", data32->granularity); | ||
643 | dbg(" Address range min: %08X\n", data32->min_address_range); | ||
644 | dbg(" Address range max: %08X\n", data32->max_address_range); | ||
645 | dbg(" Address translation offset: %08X\n", data32->address_translation_offset); | ||
646 | dbg(" Address Length: %08X\n", data32->address_length); | ||
647 | |||
648 | if (0xFF != data32->resource_source.index) { | ||
649 | dbg(" Resource Source Index: %X\n", data32->resource_source.index); | ||
650 | /* dbg(" Resource Source: %s\n", data32->resource_source.string_ptr); */ | ||
651 | } | ||
652 | |||
653 | pciehprm_add_resource(aprh, data32->min_address_range, data32->address_length); | ||
654 | } | ||
655 | |||
656 | static acpi_status acpi_parse_crs( | ||
657 | struct acpi_bridge *ab, | ||
658 | struct acpi_resource *crsbuf | ||
659 | ) | ||
660 | { | ||
661 | acpi_status status = AE_OK; | ||
662 | struct acpi_resource *resource = crsbuf; | ||
663 | u8 count = 0; | ||
664 | u8 done = 0; | ||
665 | |||
666 | while (!done) { | ||
667 | dbg("acpi_pciehprm: PCI bus 0x%x Resource structure %x.\n", ab->bus, count++); | ||
668 | switch (resource->id) { | ||
669 | case ACPI_RSTYPE_IRQ: | ||
670 | dbg("Irq -------- Resource\n"); | ||
671 | break; | ||
672 | case ACPI_RSTYPE_DMA: | ||
673 | dbg("DMA -------- Resource\n"); | ||
674 | break; | ||
675 | case ACPI_RSTYPE_START_DPF: | ||
676 | dbg("Start DPF -------- Resource\n"); | ||
677 | break; | ||
678 | case ACPI_RSTYPE_END_DPF: | ||
679 | dbg("End DPF -------- Resource\n"); | ||
680 | break; | ||
681 | case ACPI_RSTYPE_IO: | ||
682 | acpi_parse_io (ab, &resource->data); | ||
683 | break; | ||
684 | case ACPI_RSTYPE_FIXED_IO: | ||
685 | acpi_parse_fixed_io (ab, &resource->data); | ||
686 | break; | ||
687 | case ACPI_RSTYPE_VENDOR: | ||
688 | dbg("Vendor -------- Resource\n"); | ||
689 | break; | ||
690 | case ACPI_RSTYPE_END_TAG: | ||
691 | dbg("End_tag -------- Resource\n"); | ||
692 | done = 1; | ||
693 | break; | ||
694 | case ACPI_RSTYPE_MEM24: | ||
695 | dbg("Mem24 -------- Resource\n"); | ||
696 | break; | ||
697 | case ACPI_RSTYPE_MEM32: | ||
698 | dbg("Mem32 -------- Resource\n"); | ||
699 | break; | ||
700 | case ACPI_RSTYPE_FIXED_MEM32: | ||
701 | dbg("Fixed Mem32 -------- Resource\n"); | ||
702 | break; | ||
703 | case ACPI_RSTYPE_ADDRESS16: | ||
704 | acpi_parse_address16_32(ab, &resource->data, ACPI_RSTYPE_ADDRESS16); | ||
705 | break; | ||
706 | case ACPI_RSTYPE_ADDRESS32: | ||
707 | acpi_parse_address16_32(ab, &resource->data, ACPI_RSTYPE_ADDRESS32); | ||
708 | break; | ||
709 | case ACPI_RSTYPE_ADDRESS64: | ||
710 | info("Address64 -------- Resource unparsed\n"); | ||
711 | break; | ||
712 | case ACPI_RSTYPE_EXT_IRQ: | ||
713 | dbg("Ext Irq -------- Resource\n"); | ||
714 | break; | ||
715 | default: | ||
716 | dbg("Invalid -------- resource type 0x%x\n", resource->id); | ||
717 | break; | ||
718 | } | ||
719 | |||
720 | resource = (struct acpi_resource *) ((char *)resource + resource->length); | ||
721 | } | ||
722 | |||
723 | return status; | ||
724 | } | ||
725 | |||
726 | static acpi_status acpi_get_crs( struct acpi_bridge *ab) | ||
727 | { | ||
728 | acpi_status status; | ||
729 | struct acpi_resource *crsbuf; | ||
730 | |||
731 | status = acpi_evaluate_crs(ab->handle, &crsbuf); | ||
732 | if (ACPI_SUCCESS(status)) { | ||
733 | status = acpi_parse_crs(ab, crsbuf); | ||
734 | kfree(crsbuf); | ||
735 | |||
736 | pciehp_resource_sort_and_combine(&ab->bus_head); | ||
737 | pciehp_resource_sort_and_combine(&ab->io_head); | ||
738 | pciehp_resource_sort_and_combine(&ab->mem_head); | ||
739 | pciehp_resource_sort_and_combine(&ab->p_mem_head); | ||
740 | |||
741 | pciehprm_add_resources (&ab->tbus_head, ab->bus_head); | ||
742 | pciehprm_add_resources (&ab->tio_head, ab->io_head); | ||
743 | pciehprm_add_resources (&ab->tmem_head, ab->mem_head); | ||
744 | pciehprm_add_resources (&ab->tp_mem_head, ab->p_mem_head); | ||
745 | } | ||
746 | |||
747 | return status; | ||
748 | } | ||
749 | |||
750 | /* find acpi_bridge downword from ab. */ | ||
751 | static struct acpi_bridge * | ||
752 | find_acpi_bridge_by_bus( | ||
753 | struct acpi_bridge *ab, | ||
754 | int seg, | ||
755 | int bus /* pdev->subordinate->number */ | ||
756 | ) | ||
757 | { | ||
758 | struct acpi_bridge *lab = NULL; | ||
759 | |||
760 | if (!ab) | ||
761 | return NULL; | ||
762 | |||
763 | if ((ab->bus == bus) && (ab->seg == seg)) | ||
764 | return ab; | ||
765 | |||
766 | if (ab->child) | ||
767 | lab = find_acpi_bridge_by_bus(ab->child, seg, bus); | ||
768 | |||
769 | if (!lab) | ||
770 | if (ab->next) | ||
771 | lab = find_acpi_bridge_by_bus(ab->next, seg, bus); | ||
772 | |||
773 | return lab; | ||
774 | } | ||
775 | |||
776 | /* | ||
777 | * Build a device tree of ACPI PCI Bridges | ||
778 | */ | ||
779 | static void pciehprm_acpi_register_a_bridge ( | ||
780 | struct acpi_bridge **head, | ||
781 | struct acpi_bridge *pab, /* parent bridge to which child bridge is added */ | ||
782 | struct acpi_bridge *cab /* child bridge to add */ | ||
783 | ) | ||
784 | { | ||
785 | struct acpi_bridge *lpab; | ||
786 | struct acpi_bridge *lcab; | ||
787 | |||
788 | lpab = find_acpi_bridge_by_bus(*head, pab->seg, pab->bus); | ||
789 | if (!lpab) { | ||
790 | if (!(pab->type & BRIDGE_TYPE_HOST)) | ||
791 | warn("PCI parent bridge s:b(%x:%x) not in list.\n", pab->seg, pab->bus); | ||
792 | pab->next = *head; | ||
793 | *head = pab; | ||
794 | lpab = pab; | ||
795 | } | ||
796 | |||
797 | if ((cab->type & BRIDGE_TYPE_HOST) && (pab == cab)) | ||
798 | return; | ||
799 | |||
800 | lcab = find_acpi_bridge_by_bus(*head, cab->seg, cab->bus); | ||
801 | if (lcab) { | ||
802 | if ((pab->bus != lcab->parent->bus) || (lcab->bus != cab->bus)) | ||
803 | err("PCI child bridge s:b(%x:%x) in list with diff parent.\n", cab->seg, cab->bus); | ||
804 | return; | ||
805 | } else | ||
806 | lcab = cab; | ||
807 | |||
808 | lcab->parent = lpab; | ||
809 | lcab->next = lpab->child; | ||
810 | lpab->child = lcab; | ||
811 | } | ||
812 | |||
813 | static acpi_status pciehprm_acpi_build_php_slots_callback( | ||
814 | acpi_handle handle, | ||
815 | u32 Level, | ||
816 | void *context, | ||
817 | void **retval | ||
818 | ) | ||
819 | { | ||
820 | ulong bus_num; | ||
821 | ulong seg_num; | ||
822 | ulong sun, adr; | ||
823 | ulong padr = 0; | ||
824 | acpi_handle phandle = NULL; | ||
825 | struct acpi_bridge *pab = (struct acpi_bridge *)context; | ||
826 | struct acpi_bridge *lab; | ||
827 | acpi_status status; | ||
828 | u8 *path_name = acpi_path_name(handle); | ||
829 | |||
830 | /* get _SUN */ | ||
831 | status = acpi_evaluate_integer(handle, METHOD_NAME__SUN, NULL, &sun); | ||
832 | switch(status) { | ||
833 | case AE_NOT_FOUND: | ||
834 | return AE_OK; | ||
835 | default: | ||
836 | if (ACPI_FAILURE(status)) { | ||
837 | err("acpi_pciehprm:%s _SUN fail=0x%x\n", path_name, status); | ||
838 | return status; | ||
839 | } | ||
840 | } | ||
841 | |||
842 | /* get _ADR. _ADR must exist if _SUN exists */ | ||
843 | status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr); | ||
844 | if (ACPI_FAILURE(status)) { | ||
845 | err("acpi_pciehprm:%s _ADR fail=0x%x\n", path_name, status); | ||
846 | return status; | ||
847 | } | ||
848 | |||
849 | dbg("acpi_pciehprm:%s sun=0x%08x adr=0x%08x\n", path_name, (u32)sun, (u32)adr); | ||
850 | |||
851 | status = acpi_get_parent(handle, &phandle); | ||
852 | if (ACPI_FAILURE(status)) { | ||
853 | err("acpi_pciehprm:%s get_parent fail=0x%x\n", path_name, status); | ||
854 | return (status); | ||
855 | } | ||
856 | |||
857 | bus_num = pab->bus; | ||
858 | seg_num = pab->seg; | ||
859 | |||
860 | if (pab->bus == bus_num) { | ||
861 | lab = pab; | ||
862 | } else { | ||
863 | dbg("WARN: pab is not parent\n"); | ||
864 | lab = find_acpi_bridge_by_bus(pab, seg_num, bus_num); | ||
865 | if (!lab) { | ||
866 | dbg("acpi_pciehprm: alloc new P2P bridge(%x) for sun(%08x)\n", (u32)bus_num, (u32)sun); | ||
867 | lab = (struct acpi_bridge *)kmalloc(sizeof(struct acpi_bridge), GFP_KERNEL); | ||
868 | if (!lab) { | ||
869 | err("acpi_pciehprm: alloc for ab fail\n"); | ||
870 | return AE_NO_MEMORY; | ||
871 | } | ||
872 | memset(lab, 0, sizeof(struct acpi_bridge)); | ||
873 | |||
874 | lab->handle = phandle; | ||
875 | lab->pbus = pab->bus; | ||
876 | lab->pdevice = (int)(padr >> 16) & 0xffff; | ||
877 | lab->pfunction = (int)(padr & 0xffff); | ||
878 | lab->bus = (int)bus_num; | ||
879 | lab->scanned = 0; | ||
880 | lab->type = BRIDGE_TYPE_P2P; | ||
881 | |||
882 | pciehprm_acpi_register_a_bridge (&acpi_bridges_head, pab, lab); | ||
883 | } else | ||
884 | dbg("acpi_pciehprm: found P2P bridge(%x) for sun(%08x)\n", (u32)bus_num, (u32)sun); | ||
885 | } | ||
886 | |||
887 | acpi_add_slot_to_php_slots(lab, (int)bus_num, handle, (u32)adr, (u32)sun); | ||
888 | |||
889 | return (status); | ||
890 | } | ||
891 | |||
892 | static int pciehprm_acpi_build_php_slots( | ||
893 | struct acpi_bridge *ab, | ||
894 | u32 depth | ||
895 | ) | ||
896 | { | ||
897 | acpi_status status; | ||
898 | u8 *path_name = acpi_path_name(ab->handle); | ||
899 | |||
900 | /* Walk down this pci bridge to get _SUNs if any behind P2P */ | ||
901 | status = acpi_walk_namespace ( ACPI_TYPE_DEVICE, | ||
902 | ab->handle, | ||
903 | depth, | ||
904 | pciehprm_acpi_build_php_slots_callback, | ||
905 | ab, | ||
906 | NULL ); | ||
907 | if (ACPI_FAILURE(status)) { | ||
908 | dbg("acpi_pciehprm:%s walk for _SUN on pci bridge seg:bus(%x:%x) fail=0x%x\n", path_name, ab->seg, ab->bus, status); | ||
909 | return -1; | ||
910 | } | ||
911 | |||
912 | return 0; | ||
913 | } | ||
914 | |||
915 | static void build_a_bridge( | ||
916 | struct acpi_bridge *pab, | ||
917 | struct acpi_bridge *ab | ||
918 | ) | ||
919 | { | ||
920 | u8 *path_name = acpi_path_name(ab->handle); | ||
921 | |||
922 | pciehprm_acpi_register_a_bridge (&acpi_bridges_head, pab, ab); | ||
923 | |||
924 | switch (ab->type) { | ||
925 | case BRIDGE_TYPE_HOST: | ||
926 | dbg("acpi_pciehprm: Registered PCI HOST Bridge(%02x) on s:b:d:f(%02x:%02x:%02x:%02x) [%s]\n", | ||
927 | ab->bus, ab->seg, ab->pbus, ab->pdevice, ab->pfunction, path_name); | ||
928 | break; | ||
929 | case BRIDGE_TYPE_P2P: | ||
930 | dbg("acpi_pciehprm: Registered PCI P2P Bridge(%02x-%02x) on s:b:d:f(%02x:%02x:%02x:%02x) [%s]\n", | ||
931 | ab->pbus, ab->bus, ab->seg, ab->pbus, ab->pdevice, ab->pfunction, path_name); | ||
932 | break; | ||
933 | }; | ||
934 | |||
935 | /* build any immediate PHP slots under this pci bridge */ | ||
936 | pciehprm_acpi_build_php_slots(ab, 1); | ||
937 | } | ||
938 | |||
939 | static struct acpi_bridge * add_p2p_bridge( | ||
940 | acpi_handle handle, | ||
941 | struct acpi_bridge *pab, /* parent */ | ||
942 | ulong adr | ||
943 | ) | ||
944 | { | ||
945 | struct acpi_bridge *ab; | ||
946 | struct pci_dev *pdev; | ||
947 | ulong devnum, funcnum; | ||
948 | u8 *path_name = acpi_path_name(handle); | ||
949 | |||
950 | ab = (struct acpi_bridge *) kmalloc (sizeof(struct acpi_bridge), GFP_KERNEL); | ||
951 | if (!ab) { | ||
952 | err("acpi_pciehprm: alloc for ab fail\n"); | ||
953 | return NULL; | ||
954 | } | ||
955 | memset(ab, 0, sizeof(struct acpi_bridge)); | ||
956 | |||
957 | devnum = (adr >> 16) & 0xffff; | ||
958 | funcnum = adr & 0xffff; | ||
959 | |||
960 | pdev = pci_find_slot(pab->bus, PCI_DEVFN(devnum, funcnum)); | ||
961 | if (!pdev || !pdev->subordinate) { | ||
962 | err("acpi_pciehprm:%s is not a P2P Bridge\n", path_name); | ||
963 | kfree(ab); | ||
964 | return NULL; | ||
965 | } | ||
966 | |||
967 | ab->handle = handle; | ||
968 | ab->seg = pab->seg; | ||
969 | ab->pbus = pab->bus; /* or pdev->bus->number */ | ||
970 | ab->pdevice = devnum; /* or PCI_SLOT(pdev->devfn) */ | ||
971 | ab->pfunction = funcnum; /* or PCI_FUNC(pdev->devfn) */ | ||
972 | ab->bus = pdev->subordinate->number; | ||
973 | ab->scanned = 0; | ||
974 | ab->type = BRIDGE_TYPE_P2P; | ||
975 | |||
976 | dbg("acpi_pciehprm: P2P(%x-%x) on pci=b:d:f(%x:%x:%x) acpi=b:d:f(%x:%x:%x) [%s]\n", | ||
977 | pab->bus, ab->bus, pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), | ||
978 | pab->bus, (u32)devnum, (u32)funcnum, path_name); | ||
979 | |||
980 | build_a_bridge(pab, ab); | ||
981 | |||
982 | return ab; | ||
983 | } | ||
984 | |||
985 | static acpi_status scan_p2p_bridge( | ||
986 | acpi_handle handle, | ||
987 | u32 Level, | ||
988 | void *context, | ||
989 | void **retval | ||
990 | ) | ||
991 | { | ||
992 | struct acpi_bridge *pab = (struct acpi_bridge *)context; | ||
993 | struct acpi_bridge *ab; | ||
994 | acpi_status status; | ||
995 | ulong adr = 0; | ||
996 | u8 *path_name = acpi_path_name(handle); | ||
997 | ulong devnum, funcnum; | ||
998 | struct pci_dev *pdev; | ||
999 | |||
1000 | /* get device, function */ | ||
1001 | status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr); | ||
1002 | if (ACPI_FAILURE(status)) { | ||
1003 | if (status != AE_NOT_FOUND) | ||
1004 | err("acpi_pciehprm:%s _ADR fail=0x%x\n", path_name, status); | ||
1005 | return AE_OK; | ||
1006 | } | ||
1007 | |||
1008 | devnum = (adr >> 16) & 0xffff; | ||
1009 | funcnum = adr & 0xffff; | ||
1010 | |||
1011 | pdev = pci_find_slot(pab->bus, PCI_DEVFN(devnum, funcnum)); | ||
1012 | if (!pdev) | ||
1013 | return AE_OK; | ||
1014 | if (!pdev->subordinate) | ||
1015 | return AE_OK; | ||
1016 | |||
1017 | ab = add_p2p_bridge(handle, pab, adr); | ||
1018 | if (ab) { | ||
1019 | status = acpi_walk_namespace ( ACPI_TYPE_DEVICE, | ||
1020 | handle, | ||
1021 | (u32)1, | ||
1022 | scan_p2p_bridge, | ||
1023 | ab, | ||
1024 | NULL); | ||
1025 | if (ACPI_FAILURE(status)) | 222 | if (ACPI_FAILURE(status)) |
1026 | dbg("acpi_pciehprm:%s find_p2p fail=0x%x\n", path_name, status); | 223 | break; |
1027 | } | ||
1028 | |||
1029 | return AE_OK; | ||
1030 | } | ||
1031 | |||
1032 | static struct acpi_bridge * add_host_bridge( | ||
1033 | acpi_handle handle, | ||
1034 | ulong segnum, | ||
1035 | ulong busnum | ||
1036 | ) | ||
1037 | { | ||
1038 | ulong adr = 0; | ||
1039 | acpi_status status; | ||
1040 | struct acpi_bridge *ab; | ||
1041 | u8 *path_name = acpi_path_name(handle); | ||
1042 | |||
1043 | /* get device, function: host br adr is always 0000 though. */ | ||
1044 | status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr); | ||
1045 | if (ACPI_FAILURE(status)) { | ||
1046 | err("acpi_pciehprm:%s _ADR fail=0x%x\n", path_name, status); | ||
1047 | return NULL; | ||
1048 | } | ||
1049 | dbg("acpi_pciehprm: ROOT PCI seg(0x%x)bus(0x%x)dev(0x%x)func(0x%x) [%s]\n", (u32)segnum, | ||
1050 | (u32)busnum, (u32)(adr >> 16) & 0xffff, (u32)adr & 0xffff, path_name); | ||
1051 | |||
1052 | ab = (struct acpi_bridge *) kmalloc (sizeof(struct acpi_bridge), GFP_KERNEL); | ||
1053 | if (!ab) { | ||
1054 | err("acpi_pciehprm: alloc for ab fail\n"); | ||
1055 | return NULL; | ||
1056 | } | ||
1057 | memset(ab, 0, sizeof(struct acpi_bridge)); | ||
1058 | |||
1059 | ab->handle = handle; | ||
1060 | ab->seg = (int)segnum; | ||
1061 | ab->bus = ab->pbus = (int)busnum; | ||
1062 | ab->pdevice = (int)(adr >> 16) & 0xffff; | ||
1063 | ab->pfunction = (int)(adr & 0xffff); | ||
1064 | ab->scanned = 0; | ||
1065 | ab->type = BRIDGE_TYPE_HOST; | ||
1066 | |||
1067 | /* get root pci bridge's current resources */ | ||
1068 | status = acpi_get_crs(ab); | ||
1069 | if (ACPI_FAILURE(status)) { | ||
1070 | err("acpi_pciehprm:%s evaluate _CRS fail=0x%x\n", path_name, status); | ||
1071 | kfree(ab); | ||
1072 | return NULL; | ||
1073 | } | ||
1074 | |||
1075 | status = pci_osc_control_set (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL); | ||
1076 | if (ACPI_FAILURE(status)) { | ||
1077 | err("%s: status %x\n", __FUNCTION__, status); | ||
1078 | osc_run_status = (status == AE_NOT_FOUND) ? OSC_NOT_EXIST : OSC_RUN_FAILED; | ||
1079 | } else { | ||
1080 | osc_run_status = NC_RUN_SUCCESS; | ||
1081 | } | ||
1082 | dbg("%s: osc_run_status %x\n", __FUNCTION__, osc_run_status); | ||
1083 | |||
1084 | build_a_bridge(ab, ab); | ||
1085 | |||
1086 | return ab; | ||
1087 | } | ||
1088 | |||
1089 | static acpi_status acpi_scan_from_root_pci_callback ( | ||
1090 | acpi_handle handle, | ||
1091 | u32 Level, | ||
1092 | void *context, | ||
1093 | void **retval | ||
1094 | ) | ||
1095 | { | ||
1096 | ulong segnum = 0; | ||
1097 | ulong busnum = 0; | ||
1098 | acpi_status status; | ||
1099 | struct acpi_bridge *ab; | ||
1100 | u8 *path_name = acpi_path_name(handle); | ||
1101 | |||
1102 | /* get bus number of this pci root bridge */ | ||
1103 | status = acpi_evaluate_integer(handle, METHOD_NAME__SEG, NULL, &segnum); | ||
1104 | if (ACPI_FAILURE(status)) { | ||
1105 | if (status != AE_NOT_FOUND) { | ||
1106 | err("acpi_pciehprm:%s evaluate _SEG fail=0x%x\n", path_name, status); | ||
1107 | return status; | ||
1108 | } | ||
1109 | segnum = 0; | ||
1110 | } | ||
1111 | |||
1112 | /* get bus number of this pci root bridge */ | ||
1113 | status = acpi_evaluate_integer(handle, METHOD_NAME__BBN, NULL, &busnum); | ||
1114 | if (ACPI_FAILURE(status)) { | ||
1115 | err("acpi_pciehprm:%s evaluate _BBN fail=0x%x\n", path_name, status); | ||
1116 | return (status); | ||
1117 | } | ||
1118 | |||
1119 | ab = add_host_bridge(handle, segnum, busnum); | ||
1120 | if (ab) { | ||
1121 | status = acpi_walk_namespace ( ACPI_TYPE_DEVICE, | ||
1122 | handle, | ||
1123 | 1, | ||
1124 | scan_p2p_bridge, | ||
1125 | ab, | ||
1126 | NULL); | ||
1127 | if (ACPI_FAILURE(status)) | ||
1128 | dbg("acpi_pciehprm:%s find_p2p fail=0x%x\n", path_name, status); | ||
1129 | } | 224 | } |
1130 | 225 | ||
1131 | return AE_OK; | 226 | err("Cannot get control of hotplug hardware for pci %s\n", |
227 | pci_name(dev)); | ||
228 | return -1; | ||
1132 | } | 229 | } |
1133 | 230 | ||
1134 | static int pciehprm_acpi_scan_pci (void) | 231 | void pciehp_get_hp_params_from_firmware(struct pci_dev *dev, |
232 | struct hotplug_params *hpp) | ||
1135 | { | 233 | { |
1136 | acpi_status status; | 234 | acpi_status status = AE_NOT_FOUND; |
235 | struct pci_dev *pdev = dev; | ||
1137 | 236 | ||
1138 | /* | 237 | /* |
1139 | * TBD: traverse LDM device tree with the help of | 238 | * _HPP settings apply to all child buses, until another _HPP is |
1140 | * unified ACPI augmented for php device population. | 239 | * encountered. If we don't find an _HPP for the input pci dev, |
240 | * look for it in the parent device scope since that would apply to | ||
241 | * this pci dev. If we don't find any _HPP, use hardcoded defaults | ||
1141 | */ | 242 | */ |
1142 | status = acpi_get_devices ( PCI_ROOT_HID_STRING, | 243 | while (pdev && (ACPI_FAILURE(status))) { |
1143 | acpi_scan_from_root_pci_callback, | 244 | acpi_handle handle = DEVICE_ACPI_HANDLE(&(pdev->dev)); |
1144 | NULL, | 245 | if (!handle) |
1145 | NULL ); | 246 | break; |
1146 | if (ACPI_FAILURE(status)) { | 247 | status = acpi_run_hpp(handle, hpp); |
1147 | err("acpi_pciehprm:get_device PCI ROOT HID fail=0x%x\n", status); | 248 | if (!(pdev->bus->parent)) |
1148 | return -1; | 249 | break; |
1149 | } | 250 | /* Check if a parent object supports _HPP */ |
1150 | 251 | pdev = pdev->bus->parent->self; | |
1151 | return 0; | ||
1152 | } | ||
1153 | |||
1154 | int pciehprm_init(enum php_ctlr_type ctlr_type) | ||
1155 | { | ||
1156 | int rc; | ||
1157 | |||
1158 | if (ctlr_type != PCI) | ||
1159 | return -ENODEV; | ||
1160 | |||
1161 | dbg("pciehprm ACPI init <enter>\n"); | ||
1162 | acpi_bridges_head = NULL; | ||
1163 | |||
1164 | /* construct PCI bus:device tree of acpi_handles */ | ||
1165 | rc = pciehprm_acpi_scan_pci(); | ||
1166 | if (rc) | ||
1167 | return rc; | ||
1168 | |||
1169 | if ((oshp_run_status != NC_RUN_SUCCESS) && (osc_run_status != NC_RUN_SUCCESS)) { | ||
1170 | err("Fails to gain control of native hot-plug\n"); | ||
1171 | rc = -ENODEV; | ||
1172 | } | ||
1173 | |||
1174 | dbg("pciehprm ACPI init %s\n", (rc)?"fail":"success"); | ||
1175 | return rc; | ||
1176 | } | ||
1177 | |||
1178 | static void free_a_slot(struct acpi_php_slot *aps) | ||
1179 | { | ||
1180 | dbg(" free a php func of slot(0x%02x) on PCI b:d:f=0x%02x:%02x:%02x\n", aps->sun, aps->bus, aps->dev, aps->fun); | ||
1181 | |||
1182 | free_pci_resource (aps->io_head); | ||
1183 | free_pci_resource (aps->bus_head); | ||
1184 | free_pci_resource (aps->mem_head); | ||
1185 | free_pci_resource (aps->p_mem_head); | ||
1186 | |||
1187 | kfree(aps); | ||
1188 | } | ||
1189 | |||
1190 | static void free_a_bridge( struct acpi_bridge *ab) | ||
1191 | { | ||
1192 | struct acpi_php_slot *aps, *next; | ||
1193 | |||
1194 | switch (ab->type) { | ||
1195 | case BRIDGE_TYPE_HOST: | ||
1196 | dbg("Free ACPI PCI HOST Bridge(%x) [%s] on s:b:d:f(%x:%x:%x:%x)\n", | ||
1197 | ab->bus, acpi_path_name(ab->handle), ab->seg, ab->pbus, ab->pdevice, ab->pfunction); | ||
1198 | break; | ||
1199 | case BRIDGE_TYPE_P2P: | ||
1200 | dbg("Free ACPI PCI P2P Bridge(%x-%x) [%s] on s:b:d:f(%x:%x:%x:%x)\n", | ||
1201 | ab->pbus, ab->bus, acpi_path_name(ab->handle), ab->seg, ab->pbus, ab->pdevice, ab->pfunction); | ||
1202 | break; | ||
1203 | }; | ||
1204 | |||
1205 | /* free slots first */ | ||
1206 | for (aps = ab->slots; aps; aps = next) { | ||
1207 | next = aps->next; | ||
1208 | free_a_slot(aps); | ||
1209 | } | ||
1210 | |||
1211 | free_pci_resource (ab->io_head); | ||
1212 | free_pci_resource (ab->tio_head); | ||
1213 | free_pci_resource (ab->bus_head); | ||
1214 | free_pci_resource (ab->tbus_head); | ||
1215 | free_pci_resource (ab->mem_head); | ||
1216 | free_pci_resource (ab->tmem_head); | ||
1217 | free_pci_resource (ab->p_mem_head); | ||
1218 | free_pci_resource (ab->tp_mem_head); | ||
1219 | |||
1220 | kfree(ab); | ||
1221 | } | ||
1222 | |||
1223 | static void pciehprm_free_bridges ( struct acpi_bridge *ab) | ||
1224 | { | ||
1225 | if (!ab) | ||
1226 | return; | ||
1227 | |||
1228 | if (ab->child) | ||
1229 | pciehprm_free_bridges (ab->child); | ||
1230 | |||
1231 | if (ab->next) | ||
1232 | pciehprm_free_bridges (ab->next); | ||
1233 | |||
1234 | free_a_bridge(ab); | ||
1235 | } | ||
1236 | |||
1237 | void pciehprm_cleanup(void) | ||
1238 | { | ||
1239 | pciehprm_free_bridges (acpi_bridges_head); | ||
1240 | } | ||
1241 | |||
1242 | static int get_number_of_slots ( | ||
1243 | struct acpi_bridge *ab, | ||
1244 | int selfonly | ||
1245 | ) | ||
1246 | { | ||
1247 | struct acpi_php_slot *aps; | ||
1248 | int prev_slot = -1; | ||
1249 | int slot_num = 0; | ||
1250 | |||
1251 | for ( aps = ab->slots; aps; aps = aps->next) | ||
1252 | if (aps->dev != prev_slot) { | ||
1253 | prev_slot = aps->dev; | ||
1254 | slot_num++; | ||
1255 | } | ||
1256 | |||
1257 | if (ab->child) | ||
1258 | slot_num += get_number_of_slots (ab->child, 0); | ||
1259 | |||
1260 | if (selfonly) | ||
1261 | return slot_num; | ||
1262 | |||
1263 | if (ab->next) | ||
1264 | slot_num += get_number_of_slots (ab->next, 0); | ||
1265 | |||
1266 | return slot_num; | ||
1267 | } | ||
1268 | |||
1269 | static int print_acpi_resources (struct acpi_bridge *ab) | ||
1270 | { | ||
1271 | struct acpi_php_slot *aps; | ||
1272 | int i; | ||
1273 | |||
1274 | switch (ab->type) { | ||
1275 | case BRIDGE_TYPE_HOST: | ||
1276 | dbg("PCI HOST Bridge (%x) [%s]\n", ab->bus, acpi_path_name(ab->handle)); | ||
1277 | break; | ||
1278 | case BRIDGE_TYPE_P2P: | ||
1279 | dbg("PCI P2P Bridge (%x-%x) [%s]\n", ab->pbus, ab->bus, acpi_path_name(ab->handle)); | ||
1280 | break; | ||
1281 | }; | ||
1282 | |||
1283 | print_pci_resources (ab); | ||
1284 | |||
1285 | for ( i = -1, aps = ab->slots; aps; aps = aps->next) { | ||
1286 | if (aps->dev == i) | ||
1287 | continue; | ||
1288 | dbg(" Slot sun(%x) s:b:d:f(%02x:%02x:%02x:%02x)\n", aps->sun, aps->seg, aps->bus, aps->dev, aps->fun); | ||
1289 | print_slot_resources(aps); | ||
1290 | i = aps->dev; | ||
1291 | } | ||
1292 | |||
1293 | if (ab->child) | ||
1294 | print_acpi_resources (ab->child); | ||
1295 | |||
1296 | if (ab->next) | ||
1297 | print_acpi_resources (ab->next); | ||
1298 | |||
1299 | return 0; | ||
1300 | } | ||
1301 | |||
1302 | int pciehprm_print_pirt(void) | ||
1303 | { | ||
1304 | dbg("PCIEHPRM ACPI Slots\n"); | ||
1305 | if (acpi_bridges_head) | ||
1306 | print_acpi_resources (acpi_bridges_head); | ||
1307 | |||
1308 | return 0; | ||
1309 | } | ||
1310 | |||
1311 | static struct acpi_php_slot * get_acpi_slot ( | ||
1312 | struct acpi_bridge *ab, | ||
1313 | u32 sun | ||
1314 | ) | ||
1315 | { | ||
1316 | struct acpi_php_slot *aps = NULL; | ||
1317 | |||
1318 | for ( aps = ab->slots; aps; aps = aps->next) | ||
1319 | if (aps->sun == sun) | ||
1320 | return aps; | ||
1321 | |||
1322 | if (!aps && ab->child) { | ||
1323 | aps = (struct acpi_php_slot *)get_acpi_slot (ab->child, sun); | ||
1324 | if (aps) | ||
1325 | return aps; | ||
1326 | } | ||
1327 | |||
1328 | if (!aps && ab->next) { | ||
1329 | aps = (struct acpi_php_slot *)get_acpi_slot (ab->next, sun); | ||
1330 | if (aps) | ||
1331 | return aps; | ||
1332 | } | ||
1333 | |||
1334 | return aps; | ||
1335 | |||
1336 | } | ||
1337 | |||
1338 | #if 0 | ||
1339 | void * pciehprm_get_slot(struct slot *slot) | ||
1340 | { | ||
1341 | struct acpi_bridge *ab = acpi_bridges_head; | ||
1342 | struct acpi_php_slot *aps = get_acpi_slot (ab, slot->number); | ||
1343 | |||
1344 | aps->slot = slot; | ||
1345 | |||
1346 | dbg("Got acpi slot sun(%x): s:b:d:f(%x:%x:%x:%x)\n", aps->sun, aps->seg, aps->bus, aps->dev, aps->fun); | ||
1347 | |||
1348 | return (void *)aps; | ||
1349 | } | ||
1350 | #endif | ||
1351 | |||
1352 | static void pciehprm_dump_func_res( struct pci_func *fun) | ||
1353 | { | ||
1354 | struct pci_func *func = fun; | ||
1355 | |||
1356 | if (func->bus_head) { | ||
1357 | dbg(": BUS Resources:\n"); | ||
1358 | print_pci_resource (func->bus_head); | ||
1359 | } | ||
1360 | if (func->io_head) { | ||
1361 | dbg(": IO Resources:\n"); | ||
1362 | print_pci_resource (func->io_head); | ||
1363 | } | ||
1364 | if (func->mem_head) { | ||
1365 | dbg(": MEM Resources:\n"); | ||
1366 | print_pci_resource (func->mem_head); | ||
1367 | } | ||
1368 | if (func->p_mem_head) { | ||
1369 | dbg(": PMEM Resources:\n"); | ||
1370 | print_pci_resource (func->p_mem_head); | ||
1371 | } | ||
1372 | } | ||
1373 | |||
1374 | static void pciehprm_dump_ctrl_res( struct controller *ctlr) | ||
1375 | { | ||
1376 | struct controller *ctrl = ctlr; | ||
1377 | |||
1378 | if (ctrl->bus_head) { | ||
1379 | dbg(": BUS Resources:\n"); | ||
1380 | print_pci_resource (ctrl->bus_head); | ||
1381 | } | ||
1382 | if (ctrl->io_head) { | ||
1383 | dbg(": IO Resources:\n"); | ||
1384 | print_pci_resource (ctrl->io_head); | ||
1385 | } | ||
1386 | if (ctrl->mem_head) { | ||
1387 | dbg(": MEM Resources:\n"); | ||
1388 | print_pci_resource (ctrl->mem_head); | ||
1389 | } | ||
1390 | if (ctrl->p_mem_head) { | ||
1391 | dbg(": PMEM Resources:\n"); | ||
1392 | print_pci_resource (ctrl->p_mem_head); | ||
1393 | } | ||
1394 | } | ||
1395 | |||
1396 | static int pciehprm_get_used_resources ( | ||
1397 | struct controller *ctrl, | ||
1398 | struct pci_func *func | ||
1399 | ) | ||
1400 | { | ||
1401 | return pciehp_save_used_resources (ctrl, func, !DISABLE_CARD); | ||
1402 | } | ||
1403 | |||
1404 | static int configure_existing_function( | ||
1405 | struct controller *ctrl, | ||
1406 | struct pci_func *func | ||
1407 | ) | ||
1408 | { | ||
1409 | int rc; | ||
1410 | |||
1411 | /* see how much resources the func has used. */ | ||
1412 | rc = pciehprm_get_used_resources (ctrl, func); | ||
1413 | |||
1414 | if (!rc) { | ||
1415 | /* subtract the resources used by the func from ctrl resources */ | ||
1416 | rc = pciehprm_delete_resources (&ctrl->bus_head, func->bus_head); | ||
1417 | rc |= pciehprm_delete_resources (&ctrl->io_head, func->io_head); | ||
1418 | rc |= pciehprm_delete_resources (&ctrl->mem_head, func->mem_head); | ||
1419 | rc |= pciehprm_delete_resources (&ctrl->p_mem_head, func->p_mem_head); | ||
1420 | if (rc) | ||
1421 | warn("aCEF: cannot del used resources\n"); | ||
1422 | } else | ||
1423 | err("aCEF: cannot get used resources\n"); | ||
1424 | |||
1425 | return rc; | ||
1426 | } | ||
1427 | |||
1428 | static int bind_pci_resources_to_slots ( struct controller *ctrl) | ||
1429 | { | ||
1430 | struct pci_func *func, new_func; | ||
1431 | int busn = ctrl->slot_bus; | ||
1432 | int devn, funn; | ||
1433 | u32 vid; | ||
1434 | |||
1435 | for (devn = 0; devn < 32; devn++) { | ||
1436 | for (funn = 0; funn < 8; funn++) { | ||
1437 | /* | ||
1438 | if (devn == ctrl->device && funn == ctrl->function) | ||
1439 | continue; | ||
1440 | */ | ||
1441 | /* find out if this entry is for an occupied slot */ | ||
1442 | vid = 0xFFFFFFFF; | ||
1443 | pci_bus_read_config_dword(ctrl->pci_dev->subordinate, PCI_DEVFN(devn, funn), PCI_VENDOR_ID, &vid); | ||
1444 | |||
1445 | if (vid != 0xFFFFFFFF) { | ||
1446 | dbg("%s: vid = %x\n", __FUNCTION__, vid); | ||
1447 | func = pciehp_slot_find(busn, devn, funn); | ||
1448 | if (!func) { | ||
1449 | memset(&new_func, 0, sizeof(struct pci_func)); | ||
1450 | new_func.bus = busn; | ||
1451 | new_func.device = devn; | ||
1452 | new_func.function = funn; | ||
1453 | new_func.is_a_board = 1; | ||
1454 | configure_existing_function(ctrl, &new_func); | ||
1455 | pciehprm_dump_func_res(&new_func); | ||
1456 | } else { | ||
1457 | configure_existing_function(ctrl, func); | ||
1458 | pciehprm_dump_func_res(func); | ||
1459 | } | ||
1460 | dbg("aCCF:existing PCI 0x%x Func ResourceDump\n", ctrl->bus); | ||
1461 | } | ||
1462 | } | ||
1463 | } | ||
1464 | |||
1465 | return 0; | ||
1466 | } | ||
1467 | |||
1468 | static int bind_pci_resources( | ||
1469 | struct controller *ctrl, | ||
1470 | struct acpi_bridge *ab | ||
1471 | ) | ||
1472 | { | ||
1473 | int status = 0; | ||
1474 | |||
1475 | if (ab->bus_head) { | ||
1476 | dbg("bapr: BUS Resources add on PCI 0x%x\n", ab->bus); | ||
1477 | status = pciehprm_add_resources (&ctrl->bus_head, ab->bus_head); | ||
1478 | if (pciehprm_delete_resources (&ab->bus_head, ctrl->bus_head)) | ||
1479 | warn("bapr: cannot sub BUS Resource on PCI 0x%x\n", ab->bus); | ||
1480 | if (status) { | ||
1481 | err("bapr: BUS Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status); | ||
1482 | return status; | ||
1483 | } | ||
1484 | } else | ||
1485 | info("bapr: No BUS Resource on PCI 0x%x.\n", ab->bus); | ||
1486 | |||
1487 | if (ab->io_head) { | ||
1488 | dbg("bapr: IO Resources add on PCI 0x%x\n", ab->bus); | ||
1489 | status = pciehprm_add_resources (&ctrl->io_head, ab->io_head); | ||
1490 | if (pciehprm_delete_resources (&ab->io_head, ctrl->io_head)) | ||
1491 | warn("bapr: cannot sub IO Resource on PCI 0x%x\n", ab->bus); | ||
1492 | if (status) { | ||
1493 | err("bapr: IO Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status); | ||
1494 | return status; | ||
1495 | } | ||
1496 | } else | ||
1497 | info("bapr: No IO Resource on PCI 0x%x.\n", ab->bus); | ||
1498 | |||
1499 | if (ab->mem_head) { | ||
1500 | dbg("bapr: MEM Resources add on PCI 0x%x\n", ab->bus); | ||
1501 | status = pciehprm_add_resources (&ctrl->mem_head, ab->mem_head); | ||
1502 | if (pciehprm_delete_resources (&ab->mem_head, ctrl->mem_head)) | ||
1503 | warn("bapr: cannot sub MEM Resource on PCI 0x%x\n", ab->bus); | ||
1504 | if (status) { | ||
1505 | err("bapr: MEM Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status); | ||
1506 | return status; | ||
1507 | } | ||
1508 | } else | ||
1509 | info("bapr: No MEM Resource on PCI 0x%x.\n", ab->bus); | ||
1510 | |||
1511 | if (ab->p_mem_head) { | ||
1512 | dbg("bapr: PMEM Resources add on PCI 0x%x\n", ab->bus); | ||
1513 | status = pciehprm_add_resources (&ctrl->p_mem_head, ab->p_mem_head); | ||
1514 | if (pciehprm_delete_resources (&ab->p_mem_head, ctrl->p_mem_head)) | ||
1515 | warn("bapr: cannot sub PMEM Resource on PCI 0x%x\n", ab->bus); | ||
1516 | if (status) { | ||
1517 | err("bapr: PMEM Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status); | ||
1518 | return status; | ||
1519 | } | ||
1520 | } else | ||
1521 | info("bapr: No PMEM Resource on PCI 0x%x.\n", ab->bus); | ||
1522 | |||
1523 | return status; | ||
1524 | } | ||
1525 | |||
1526 | static int no_pci_resources( struct acpi_bridge *ab) | ||
1527 | { | ||
1528 | return !(ab->p_mem_head || ab->mem_head || ab->io_head || ab->bus_head); | ||
1529 | } | ||
1530 | |||
1531 | static int find_pci_bridge_resources ( | ||
1532 | struct controller *ctrl, | ||
1533 | struct acpi_bridge *ab | ||
1534 | ) | ||
1535 | { | ||
1536 | int rc = 0; | ||
1537 | struct pci_func func; | ||
1538 | |||
1539 | memset(&func, 0, sizeof(struct pci_func)); | ||
1540 | |||
1541 | func.bus = ab->pbus; | ||
1542 | func.device = ab->pdevice; | ||
1543 | func.function = ab->pfunction; | ||
1544 | func.is_a_board = 1; | ||
1545 | |||
1546 | /* Get used resources for this PCI bridge */ | ||
1547 | rc = pciehp_save_used_resources (ctrl, &func, !DISABLE_CARD); | ||
1548 | |||
1549 | ab->io_head = func.io_head; | ||
1550 | ab->mem_head = func.mem_head; | ||
1551 | ab->p_mem_head = func.p_mem_head; | ||
1552 | ab->bus_head = func.bus_head; | ||
1553 | if (ab->bus_head) | ||
1554 | pciehprm_delete_resource(&ab->bus_head, ctrl->pci_dev->subordinate->number, 1); | ||
1555 | |||
1556 | return rc; | ||
1557 | } | ||
1558 | |||
1559 | static int get_pci_resources_from_bridge( | ||
1560 | struct controller *ctrl, | ||
1561 | struct acpi_bridge *ab | ||
1562 | ) | ||
1563 | { | ||
1564 | int rc = 0; | ||
1565 | |||
1566 | dbg("grfb: Get Resources for PCI 0x%x from actual PCI bridge 0x%x.\n", ctrl->bus, ab->bus); | ||
1567 | |||
1568 | rc = find_pci_bridge_resources (ctrl, ab); | ||
1569 | |||
1570 | pciehp_resource_sort_and_combine(&ab->bus_head); | ||
1571 | pciehp_resource_sort_and_combine(&ab->io_head); | ||
1572 | pciehp_resource_sort_and_combine(&ab->mem_head); | ||
1573 | pciehp_resource_sort_and_combine(&ab->p_mem_head); | ||
1574 | |||
1575 | pciehprm_add_resources (&ab->tbus_head, ab->bus_head); | ||
1576 | pciehprm_add_resources (&ab->tio_head, ab->io_head); | ||
1577 | pciehprm_add_resources (&ab->tmem_head, ab->mem_head); | ||
1578 | pciehprm_add_resources (&ab->tp_mem_head, ab->p_mem_head); | ||
1579 | |||
1580 | return rc; | ||
1581 | } | ||
1582 | |||
1583 | static int get_pci_resources( | ||
1584 | struct controller *ctrl, | ||
1585 | struct acpi_bridge *ab | ||
1586 | ) | ||
1587 | { | ||
1588 | int rc = 0; | ||
1589 | |||
1590 | if (no_pci_resources(ab)) { | ||
1591 | dbg("spbr:PCI 0x%x has no resources. Get parent resources.\n", ab->bus); | ||
1592 | rc = get_pci_resources_from_bridge(ctrl, ab); | ||
1593 | } | ||
1594 | |||
1595 | return rc; | ||
1596 | } | ||
1597 | |||
1598 | /* | ||
1599 | * Get resources for this ctrl. | ||
1600 | * 1. get total resources from ACPI _CRS or bridge (this ctrl) | ||
1601 | * 2. find used resources of existing adapters | ||
1602 | * 3. subtract used resources from total resources | ||
1603 | */ | ||
1604 | int pciehprm_find_available_resources( struct controller *ctrl) | ||
1605 | { | ||
1606 | int rc = 0; | ||
1607 | struct acpi_bridge *ab; | ||
1608 | |||
1609 | ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->pci_dev->subordinate->number); | ||
1610 | if (!ab) { | ||
1611 | err("pfar:cannot locate acpi bridge of PCI 0x%x.\n", ctrl->pci_dev->subordinate->number); | ||
1612 | return -1; | ||
1613 | } | ||
1614 | if (no_pci_resources(ab)) { | ||
1615 | rc = get_pci_resources(ctrl, ab); | ||
1616 | if (rc) { | ||
1617 | err("pfar:cannot get pci resources of PCI 0x%x.\n", ctrl->pci_dev->subordinate->number); | ||
1618 | return -1; | ||
1619 | } | ||
1620 | } | ||
1621 | |||
1622 | rc = bind_pci_resources(ctrl, ab); | ||
1623 | dbg("pfar:pre-Bind PCI 0x%x Ctrl Resource Dump\n", ctrl->pci_dev->subordinate->number); | ||
1624 | pciehprm_dump_ctrl_res(ctrl); | ||
1625 | |||
1626 | bind_pci_resources_to_slots (ctrl); | ||
1627 | |||
1628 | dbg("pfar:post-Bind PCI 0x%x Ctrl Resource Dump\n", ctrl->pci_dev->subordinate->number); | ||
1629 | pciehprm_dump_ctrl_res(ctrl); | ||
1630 | |||
1631 | return rc; | ||
1632 | } | ||
1633 | |||
1634 | int pciehprm_set_hpp( | ||
1635 | struct controller *ctrl, | ||
1636 | struct pci_func *func, | ||
1637 | u8 card_type | ||
1638 | ) | ||
1639 | { | ||
1640 | struct acpi_bridge *ab; | ||
1641 | struct pci_bus lpci_bus, *pci_bus; | ||
1642 | int rc = 0; | ||
1643 | unsigned int devfn; | ||
1644 | u8 cls= 0x08; /* default cache line size */ | ||
1645 | u8 lt = 0x40; /* default latency timer */ | ||
1646 | u8 ep = 0; | ||
1647 | u8 es = 0; | ||
1648 | |||
1649 | memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus)); | ||
1650 | pci_bus = &lpci_bus; | ||
1651 | pci_bus->number = func->bus; | ||
1652 | devfn = PCI_DEVFN(func->device, func->function); | ||
1653 | |||
1654 | ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->bus); | ||
1655 | |||
1656 | if (ab) { | ||
1657 | if (ab->_hpp) { | ||
1658 | lt = (u8)ab->_hpp->latency_timer; | ||
1659 | cls = (u8)ab->_hpp->cache_line_size; | ||
1660 | ep = (u8)ab->_hpp->enable_perr; | ||
1661 | es = (u8)ab->_hpp->enable_serr; | ||
1662 | } else | ||
1663 | dbg("_hpp: no _hpp for B/D/F=%#x/%#x/%#x. use default value\n", func->bus, func->device, func->function); | ||
1664 | } else | ||
1665 | dbg("_hpp: no acpi bridge for B/D/F = %#x/%#x/%#x. use default value\n", func->bus, func->device, func->function); | ||
1666 | |||
1667 | |||
1668 | if (card_type == PCI_HEADER_TYPE_BRIDGE) { | ||
1669 | /* set subordinate Latency Timer */ | ||
1670 | rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_SEC_LATENCY_TIMER, lt); | ||
1671 | } | 252 | } |
1672 | |||
1673 | /* set base Latency Timer */ | ||
1674 | rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_LATENCY_TIMER, lt); | ||
1675 | dbg(" set latency timer =0x%02x: %x\n", lt, rc); | ||
1676 | |||
1677 | rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_CACHE_LINE_SIZE, cls); | ||
1678 | dbg(" set cache_line_size=0x%02x: %x\n", cls, rc); | ||
1679 | |||
1680 | return rc; | ||
1681 | } | 253 | } |
1682 | 254 | ||
1683 | void pciehprm_enable_card( | ||
1684 | struct controller *ctrl, | ||
1685 | struct pci_func *func, | ||
1686 | u8 card_type) | ||
1687 | { | ||
1688 | u16 command, cmd, bcommand, bcmd; | ||
1689 | struct pci_bus lpci_bus, *pci_bus; | ||
1690 | struct acpi_bridge *ab; | ||
1691 | unsigned int devfn; | ||
1692 | int rc; | ||
1693 | |||
1694 | memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus)); | ||
1695 | pci_bus = &lpci_bus; | ||
1696 | pci_bus->number = func->bus; | ||
1697 | devfn = PCI_DEVFN(func->device, func->function); | ||
1698 | |||
1699 | rc = pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &cmd); | ||
1700 | |||
1701 | if (card_type == PCI_HEADER_TYPE_BRIDGE) { | ||
1702 | rc = pci_bus_read_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, &bcmd); | ||
1703 | } | ||
1704 | |||
1705 | command = cmd | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE | ||
1706 | | PCI_COMMAND_IO | PCI_COMMAND_MEMORY; | ||
1707 | bcommand = bcmd | PCI_BRIDGE_CTL_NO_ISA; | ||
1708 | |||
1709 | ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->bus); | ||
1710 | if (ab) { | ||
1711 | if (ab->_hpp) { | ||
1712 | if (ab->_hpp->enable_perr) { | ||
1713 | command |= PCI_COMMAND_PARITY; | ||
1714 | bcommand |= PCI_BRIDGE_CTL_PARITY; | ||
1715 | } else { | ||
1716 | command &= ~PCI_COMMAND_PARITY; | ||
1717 | bcommand &= ~PCI_BRIDGE_CTL_PARITY; | ||
1718 | } | ||
1719 | if (ab->_hpp->enable_serr) { | ||
1720 | command |= PCI_COMMAND_SERR; | ||
1721 | bcommand |= PCI_BRIDGE_CTL_SERR; | ||
1722 | } else { | ||
1723 | command &= ~PCI_COMMAND_SERR; | ||
1724 | bcommand &= ~PCI_BRIDGE_CTL_SERR; | ||
1725 | } | ||
1726 | } else | ||
1727 | dbg("no _hpp for B/D/F = %#x/%#x/%#x.\n", func->bus, func->device, func->function); | ||
1728 | } else | ||
1729 | dbg("no acpi bridge for B/D/F = %#x/%#x/%#x.\n", func->bus, func->device, func->function); | ||
1730 | |||
1731 | if (command != cmd) { | ||
1732 | rc = pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command); | ||
1733 | } | ||
1734 | if ((card_type == PCI_HEADER_TYPE_BRIDGE) && (bcommand != bcmd)) { | ||
1735 | rc = pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, bcommand); | ||
1736 | } | ||
1737 | } | ||
diff --git a/drivers/pci/hotplug/pciehprm_nonacpi.c b/drivers/pci/hotplug/pciehprm_nonacpi.c index 76c727c74cc0..29180dfe8493 100644 --- a/drivers/pci/hotplug/pciehprm_nonacpi.c +++ b/drivers/pci/hotplug/pciehprm_nonacpi.c | |||
@@ -27,479 +27,21 @@ | |||
27 | * | 27 | * |
28 | */ | 28 | */ |
29 | 29 | ||
30 | #include <linux/config.h> | ||
31 | #include <linux/module.h> | 30 | #include <linux/module.h> |
32 | #include <linux/kernel.h> | 31 | #include <linux/kernel.h> |
33 | #include <linux/types.h> | 32 | #include <linux/types.h> |
34 | #include <linux/sched.h> | 33 | #include <linux/sched.h> |
35 | #include <linux/pci.h> | 34 | #include <linux/pci.h> |
36 | #include <linux/init.h> | ||
37 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
38 | |||
39 | #include <asm/uaccess.h> | ||
40 | #ifdef CONFIG_IA64 | ||
41 | #include <asm/iosapic.h> | ||
42 | #endif | ||
43 | |||
44 | #include "pciehp.h" | 36 | #include "pciehp.h" |
45 | #include "pciehprm.h" | ||
46 | #include "pciehprm_nonacpi.h" | ||
47 | |||
48 | 37 | ||
49 | void pciehprm_cleanup(void) | 38 | void pciehp_get_hp_params_from_firmware(struct pci_dev *dev, |
39 | struct hotplug_params *hpp) | ||
50 | { | 40 | { |
51 | return; | 41 | return; |
52 | } | 42 | } |
53 | 43 | ||
54 | int pciehprm_print_pirt(void) | 44 | int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev) |
55 | { | ||
56 | return 0; | ||
57 | } | ||
58 | |||
59 | int pciehprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum) | ||
60 | { | ||
61 | |||
62 | *sun = (u8) (ctrl->first_slot); | ||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | |||
67 | static void print_pci_resource ( struct pci_resource *aprh) | ||
68 | { | ||
69 | struct pci_resource *res; | ||
70 | |||
71 | for (res = aprh; res; res = res->next) | ||
72 | dbg(" base= 0x%x length= 0x%x\n", res->base, res->length); | ||
73 | } | ||
74 | |||
75 | |||
76 | static void phprm_dump_func_res( struct pci_func *fun) | ||
77 | { | ||
78 | struct pci_func *func = fun; | ||
79 | |||
80 | if (func->bus_head) { | ||
81 | dbg(": BUS Resources:\n"); | ||
82 | print_pci_resource (func->bus_head); | ||
83 | } | ||
84 | if (func->io_head) { | ||
85 | dbg(": IO Resources:\n"); | ||
86 | print_pci_resource (func->io_head); | ||
87 | } | ||
88 | if (func->mem_head) { | ||
89 | dbg(": MEM Resources:\n"); | ||
90 | print_pci_resource (func->mem_head); | ||
91 | } | ||
92 | if (func->p_mem_head) { | ||
93 | dbg(": PMEM Resources:\n"); | ||
94 | print_pci_resource (func->p_mem_head); | ||
95 | } | ||
96 | } | ||
97 | |||
98 | static int phprm_get_used_resources ( | ||
99 | struct controller *ctrl, | ||
100 | struct pci_func *func | ||
101 | ) | ||
102 | { | ||
103 | return pciehp_save_used_resources (ctrl, func, !DISABLE_CARD); | ||
104 | } | ||
105 | |||
106 | static int phprm_delete_resource( | ||
107 | struct pci_resource **aprh, | ||
108 | ulong base, | ||
109 | ulong size) | ||
110 | { | ||
111 | struct pci_resource *res; | ||
112 | struct pci_resource *prevnode; | ||
113 | struct pci_resource *split_node; | ||
114 | ulong tbase; | ||
115 | |||
116 | pciehp_resource_sort_and_combine(aprh); | ||
117 | |||
118 | for (res = *aprh; res; res = res->next) { | ||
119 | if (res->base > base) | ||
120 | continue; | ||
121 | |||
122 | if ((res->base + res->length) < (base + size)) | ||
123 | continue; | ||
124 | |||
125 | if (res->base < base) { | ||
126 | tbase = base; | ||
127 | |||
128 | if ((res->length - (tbase - res->base)) < size) | ||
129 | continue; | ||
130 | |||
131 | split_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); | ||
132 | if (!split_node) | ||
133 | return -ENOMEM; | ||
134 | |||
135 | split_node->base = res->base; | ||
136 | split_node->length = tbase - res->base; | ||
137 | res->base = tbase; | ||
138 | res->length -= split_node->length; | ||
139 | |||
140 | split_node->next = res->next; | ||
141 | res->next = split_node; | ||
142 | } | ||
143 | |||
144 | if (res->length >= size) { | ||
145 | split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); | ||
146 | if (!split_node) | ||
147 | return -ENOMEM; | ||
148 | |||
149 | split_node->base = res->base + size; | ||
150 | split_node->length = res->length - size; | ||
151 | res->length = size; | ||
152 | |||
153 | split_node->next = res->next; | ||
154 | res->next = split_node; | ||
155 | } | ||
156 | |||
157 | if (*aprh == res) { | ||
158 | *aprh = res->next; | ||
159 | } else { | ||
160 | prevnode = *aprh; | ||
161 | while (prevnode->next != res) | ||
162 | prevnode = prevnode->next; | ||
163 | |||
164 | prevnode->next = res->next; | ||
165 | } | ||
166 | res->next = NULL; | ||
167 | kfree(res); | ||
168 | break; | ||
169 | } | ||
170 | |||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | |||
175 | static int phprm_delete_resources( | ||
176 | struct pci_resource **aprh, | ||
177 | struct pci_resource *this | ||
178 | ) | ||
179 | { | ||
180 | struct pci_resource *res; | ||
181 | |||
182 | for (res = this; res; res = res->next) | ||
183 | phprm_delete_resource(aprh, res->base, res->length); | ||
184 | |||
185 | return 0; | ||
186 | } | ||
187 | |||
188 | |||
189 | static int configure_existing_function( | ||
190 | struct controller *ctrl, | ||
191 | struct pci_func *func | ||
192 | ) | ||
193 | { | ||
194 | int rc; | ||
195 | |||
196 | /* see how much resources the func has used. */ | ||
197 | rc = phprm_get_used_resources (ctrl, func); | ||
198 | |||
199 | if (!rc) { | ||
200 | /* subtract the resources used by the func from ctrl resources */ | ||
201 | rc = phprm_delete_resources (&ctrl->bus_head, func->bus_head); | ||
202 | rc |= phprm_delete_resources (&ctrl->io_head, func->io_head); | ||
203 | rc |= phprm_delete_resources (&ctrl->mem_head, func->mem_head); | ||
204 | rc |= phprm_delete_resources (&ctrl->p_mem_head, func->p_mem_head); | ||
205 | if (rc) | ||
206 | warn("aCEF: cannot del used resources\n"); | ||
207 | } else | ||
208 | err("aCEF: cannot get used resources\n"); | ||
209 | |||
210 | return rc; | ||
211 | } | ||
212 | |||
213 | static int pciehprm_delete_resource( | ||
214 | struct pci_resource **aprh, | ||
215 | ulong base, | ||
216 | ulong size) | ||
217 | { | ||
218 | struct pci_resource *res; | ||
219 | struct pci_resource *prevnode; | ||
220 | struct pci_resource *split_node; | ||
221 | ulong tbase; | ||
222 | |||
223 | pciehp_resource_sort_and_combine(aprh); | ||
224 | |||
225 | for (res = *aprh; res; res = res->next) { | ||
226 | if (res->base > base) | ||
227 | continue; | ||
228 | |||
229 | if ((res->base + res->length) < (base + size)) | ||
230 | continue; | ||
231 | |||
232 | if (res->base < base) { | ||
233 | tbase = base; | ||
234 | |||
235 | if ((res->length - (tbase - res->base)) < size) | ||
236 | continue; | ||
237 | |||
238 | split_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); | ||
239 | if (!split_node) | ||
240 | return -ENOMEM; | ||
241 | |||
242 | split_node->base = res->base; | ||
243 | split_node->length = tbase - res->base; | ||
244 | res->base = tbase; | ||
245 | res->length -= split_node->length; | ||
246 | |||
247 | split_node->next = res->next; | ||
248 | res->next = split_node; | ||
249 | } | ||
250 | |||
251 | if (res->length >= size) { | ||
252 | split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); | ||
253 | if (!split_node) | ||
254 | return -ENOMEM; | ||
255 | |||
256 | split_node->base = res->base + size; | ||
257 | split_node->length = res->length - size; | ||
258 | res->length = size; | ||
259 | |||
260 | split_node->next = res->next; | ||
261 | res->next = split_node; | ||
262 | } | ||
263 | |||
264 | if (*aprh == res) { | ||
265 | *aprh = res->next; | ||
266 | } else { | ||
267 | prevnode = *aprh; | ||
268 | while (prevnode->next != res) | ||
269 | prevnode = prevnode->next; | ||
270 | |||
271 | prevnode->next = res->next; | ||
272 | } | ||
273 | res->next = NULL; | ||
274 | kfree(res); | ||
275 | break; | ||
276 | } | ||
277 | |||
278 | return 0; | ||
279 | } | ||
280 | |||
281 | static int bind_pci_resources_to_slots ( struct controller *ctrl) | ||
282 | { | 45 | { |
283 | struct pci_func *func, new_func; | ||
284 | int busn = ctrl->slot_bus; | ||
285 | int devn, funn; | ||
286 | u32 vid; | ||
287 | |||
288 | for (devn = 0; devn < 32; devn++) { | ||
289 | for (funn = 0; funn < 8; funn++) { | ||
290 | /* | ||
291 | if (devn == ctrl->device && funn == ctrl->function) | ||
292 | continue; | ||
293 | */ | ||
294 | /* find out if this entry is for an occupied slot */ | ||
295 | vid = 0xFFFFFFFF; | ||
296 | |||
297 | pci_bus_read_config_dword(ctrl->pci_dev->subordinate, PCI_DEVFN(devn, funn), PCI_VENDOR_ID, &vid); | ||
298 | |||
299 | if (vid != 0xFFFFFFFF) { | ||
300 | dbg("%s: vid = %x bus %x dev %x fun %x\n", __FUNCTION__, | ||
301 | vid, busn, devn, funn); | ||
302 | func = pciehp_slot_find(busn, devn, funn); | ||
303 | dbg("%s: func = %p\n", __FUNCTION__,func); | ||
304 | if (!func) { | ||
305 | memset(&new_func, 0, sizeof(struct pci_func)); | ||
306 | new_func.bus = busn; | ||
307 | new_func.device = devn; | ||
308 | new_func.function = funn; | ||
309 | new_func.is_a_board = 1; | ||
310 | configure_existing_function(ctrl, &new_func); | ||
311 | phprm_dump_func_res(&new_func); | ||
312 | } else { | ||
313 | configure_existing_function(ctrl, func); | ||
314 | phprm_dump_func_res(func); | ||
315 | } | ||
316 | dbg("aCCF:existing PCI 0x%x Func ResourceDump\n", ctrl->bus); | ||
317 | } | ||
318 | } | ||
319 | } | ||
320 | |||
321 | return 0; | 46 | return 0; |
322 | } | 47 | } |
323 | |||
324 | static void phprm_dump_ctrl_res( struct controller *ctlr) | ||
325 | { | ||
326 | struct controller *ctrl = ctlr; | ||
327 | |||
328 | if (ctrl->bus_head) { | ||
329 | dbg(": BUS Resources:\n"); | ||
330 | print_pci_resource (ctrl->bus_head); | ||
331 | } | ||
332 | if (ctrl->io_head) { | ||
333 | dbg(": IO Resources:\n"); | ||
334 | print_pci_resource (ctrl->io_head); | ||
335 | } | ||
336 | if (ctrl->mem_head) { | ||
337 | dbg(": MEM Resources:\n"); | ||
338 | print_pci_resource (ctrl->mem_head); | ||
339 | } | ||
340 | if (ctrl->p_mem_head) { | ||
341 | dbg(": PMEM Resources:\n"); | ||
342 | print_pci_resource (ctrl->p_mem_head); | ||
343 | } | ||
344 | } | ||
345 | |||
346 | /* | ||
347 | * phprm_find_available_resources | ||
348 | * | ||
349 | * Finds available memory, IO, and IRQ resources for programming | ||
350 | * devices which may be added to the system | ||
351 | * this function is for hot plug ADD! | ||
352 | * | ||
353 | * returns 0 if success | ||
354 | */ | ||
355 | int pciehprm_find_available_resources(struct controller *ctrl) | ||
356 | { | ||
357 | struct pci_func func; | ||
358 | u32 rc; | ||
359 | |||
360 | memset(&func, 0, sizeof(struct pci_func)); | ||
361 | |||
362 | func.bus = ctrl->bus; | ||
363 | func.device = ctrl->device; | ||
364 | func.function = ctrl->function; | ||
365 | func.is_a_board = 1; | ||
366 | |||
367 | /* Get resources for this PCI bridge */ | ||
368 | rc = pciehp_save_used_resources (ctrl, &func, !DISABLE_CARD); | ||
369 | dbg("%s: pciehp_save_used_resources rc = %d\n", __FUNCTION__, rc); | ||
370 | |||
371 | if (func.mem_head) | ||
372 | func.mem_head->next = ctrl->mem_head; | ||
373 | ctrl->mem_head = func.mem_head; | ||
374 | |||
375 | if (func.p_mem_head) | ||
376 | func.p_mem_head->next = ctrl->p_mem_head; | ||
377 | ctrl->p_mem_head = func.p_mem_head; | ||
378 | |||
379 | if (func.io_head) | ||
380 | func.io_head->next = ctrl->io_head; | ||
381 | ctrl->io_head = func.io_head; | ||
382 | |||
383 | if(func.bus_head) | ||
384 | func.bus_head->next = ctrl->bus_head; | ||
385 | ctrl->bus_head = func.bus_head; | ||
386 | |||
387 | if (ctrl->bus_head) | ||
388 | pciehprm_delete_resource(&ctrl->bus_head, ctrl->pci_dev->subordinate->number, 1); | ||
389 | |||
390 | dbg("%s:pre-Bind PCI 0x%x Ctrl Resource Dump\n", __FUNCTION__, ctrl->bus); | ||
391 | phprm_dump_ctrl_res(ctrl); | ||
392 | |||
393 | dbg("%s: before bind_pci_resources_to slots\n", __FUNCTION__); | ||
394 | |||
395 | bind_pci_resources_to_slots (ctrl); | ||
396 | |||
397 | dbg("%s:post-Bind PCI 0x%x Ctrl Resource Dump\n", __FUNCTION__, ctrl->bus); | ||
398 | phprm_dump_ctrl_res(ctrl); | ||
399 | |||
400 | return (rc); | ||
401 | } | ||
402 | |||
403 | int pciehprm_set_hpp( | ||
404 | struct controller *ctrl, | ||
405 | struct pci_func *func, | ||
406 | u8 card_type) | ||
407 | { | ||
408 | u32 rc; | ||
409 | u8 temp_byte; | ||
410 | struct pci_bus lpci_bus, *pci_bus; | ||
411 | unsigned int devfn; | ||
412 | memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus)); | ||
413 | pci_bus = &lpci_bus; | ||
414 | pci_bus->number = func->bus; | ||
415 | devfn = PCI_DEVFN(func->device, func->function); | ||
416 | |||
417 | temp_byte = 0x40; /* hard coded value for LT */ | ||
418 | if (card_type == PCI_HEADER_TYPE_BRIDGE) { | ||
419 | /* set subordinate Latency Timer */ | ||
420 | rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_SEC_LATENCY_TIMER, temp_byte); | ||
421 | |||
422 | if (rc) { | ||
423 | dbg("%s: set secondary LT error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, | ||
424 | func->bus, func->device, func->function); | ||
425 | return rc; | ||
426 | } | ||
427 | } | ||
428 | |||
429 | /* set base Latency Timer */ | ||
430 | rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_LATENCY_TIMER, temp_byte); | ||
431 | |||
432 | if (rc) { | ||
433 | dbg("%s: set LT error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus, func->device, func->function); | ||
434 | return rc; | ||
435 | } | ||
436 | |||
437 | /* set Cache Line size */ | ||
438 | temp_byte = 0x08; /* hard coded value for CLS */ | ||
439 | |||
440 | rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_CACHE_LINE_SIZE, temp_byte); | ||
441 | |||
442 | if (rc) { | ||
443 | dbg("%s: set CLS error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus, func->device, func->function); | ||
444 | } | ||
445 | |||
446 | /* set enable_perr */ | ||
447 | /* set enable_serr */ | ||
448 | |||
449 | return rc; | ||
450 | } | ||
451 | |||
452 | void pciehprm_enable_card( | ||
453 | struct controller *ctrl, | ||
454 | struct pci_func *func, | ||
455 | u8 card_type) | ||
456 | { | ||
457 | u16 command, bcommand; | ||
458 | struct pci_bus lpci_bus, *pci_bus; | ||
459 | unsigned int devfn; | ||
460 | int rc; | ||
461 | |||
462 | memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus)); | ||
463 | pci_bus = &lpci_bus; | ||
464 | pci_bus->number = func->bus; | ||
465 | devfn = PCI_DEVFN(func->device, func->function); | ||
466 | |||
467 | rc = pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &command); | ||
468 | |||
469 | command |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR | ||
470 | | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE | ||
471 | | PCI_COMMAND_IO | PCI_COMMAND_MEMORY; | ||
472 | |||
473 | rc = pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command); | ||
474 | |||
475 | if (card_type == PCI_HEADER_TYPE_BRIDGE) { | ||
476 | |||
477 | rc = pci_bus_read_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, &bcommand); | ||
478 | |||
479 | bcommand |= PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR | ||
480 | | PCI_BRIDGE_CTL_NO_ISA; | ||
481 | |||
482 | rc = pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, bcommand); | ||
483 | } | ||
484 | } | ||
485 | |||
486 | static int legacy_pciehprm_init_pci(void) | ||
487 | { | ||
488 | return 0; | ||
489 | } | ||
490 | |||
491 | int pciehprm_init(enum php_ctlr_type ctrl_type) | ||
492 | { | ||
493 | int retval; | ||
494 | |||
495 | switch (ctrl_type) { | ||
496 | case PCI: | ||
497 | retval = legacy_pciehprm_init_pci(); | ||
498 | break; | ||
499 | default: | ||
500 | retval = -ENODEV; | ||
501 | break; | ||
502 | } | ||
503 | |||
504 | return retval; | ||
505 | } | ||
diff --git a/drivers/pci/hotplug/pciehprm_nonacpi.h b/drivers/pci/hotplug/pciehprm_nonacpi.h deleted file mode 100644 index b10603b0e958..000000000000 --- a/drivers/pci/hotplug/pciehprm_nonacpi.h +++ /dev/null | |||
@@ -1,56 +0,0 @@ | |||
1 | /* | ||
2 | * PCIEHPRM NONACPI: PHP Resource Manager for Non-ACPI/Legacy platform | ||
3 | * | ||
4 | * Copyright (C) 1995,2001 Compaq Computer Corporation | ||
5 | * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) | ||
6 | * Copyright (C) 2001 IBM Corp. | ||
7 | * Copyright (C) 2003-2004 Intel Corporation | ||
8 | * | ||
9 | * All rights reserved. | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 of the License, or (at | ||
14 | * your option) any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, but | ||
17 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
19 | * NON INFRINGEMENT. See the GNU General Public License for more | ||
20 | * details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | * | ||
26 | * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com> | ||
27 | * | ||
28 | */ | ||
29 | |||
30 | #ifndef _PCIEHPRM_NONACPI_H_ | ||
31 | #define _PCIEHPRM_NONACPI_H_ | ||
32 | |||
33 | struct irq_info { | ||
34 | u8 bus, devfn; /* bus, device and function */ | ||
35 | struct { | ||
36 | u8 link; /* IRQ line ID, chipset dependent, 0=not routed */ | ||
37 | u16 bitmap; /* Available IRQs */ | ||
38 | } __attribute__ ((packed)) irq[4]; | ||
39 | u8 slot; /* slot number, 0=onboard */ | ||
40 | u8 rfu; | ||
41 | } __attribute__ ((packed)); | ||
42 | |||
43 | struct irq_routing_table { | ||
44 | u32 signature; /* PIRQ_SIGNATURE should be here */ | ||
45 | u16 version; /* PIRQ_VERSION */ | ||
46 | u16 size; /* Table size in bytes */ | ||
47 | u8 rtr_bus, rtr_devfn; /* Where the interrupt router lies */ | ||
48 | u16 exclusive_irqs; /* IRQs devoted exclusively to PCI usage */ | ||
49 | u16 rtr_vendor, rtr_device; /* Vendor and device ID of interrupt router */ | ||
50 | u32 miniport_data; /* Crap */ | ||
51 | u8 rfu[11]; | ||
52 | u8 checksum; /* Modulo 256 checksum must give zero */ | ||
53 | struct irq_info slots[0]; | ||
54 | } __attribute__ ((packed)); | ||
55 | |||
56 | #endif /* _PCIEHPRM_NONACPI_H_ */ | ||
diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c index fcb66b9a0e28..cc03609f45d0 100644 --- a/drivers/pci/hotplug/rpadlpar_core.c +++ b/drivers/pci/hotplug/rpadlpar_core.c | |||
@@ -134,43 +134,6 @@ static void rpadlpar_claim_one_bus(struct pci_bus *b) | |||
134 | rpadlpar_claim_one_bus(child_bus); | 134 | rpadlpar_claim_one_bus(child_bus); |
135 | } | 135 | } |
136 | 136 | ||
137 | static int pci_add_secondary_bus(struct device_node *dn, | ||
138 | struct pci_dev *bridge_dev) | ||
139 | { | ||
140 | struct pci_dn *pdn = dn->data; | ||
141 | struct pci_controller *hose = pdn->phb; | ||
142 | struct pci_bus *child; | ||
143 | u8 sec_busno; | ||
144 | |||
145 | /* Get busno of downstream bus */ | ||
146 | pci_read_config_byte(bridge_dev, PCI_SECONDARY_BUS, &sec_busno); | ||
147 | |||
148 | /* Allocate and add to children of bridge_dev->bus */ | ||
149 | child = pci_add_new_bus(bridge_dev->bus, bridge_dev, sec_busno); | ||
150 | if (!child) { | ||
151 | printk(KERN_ERR "%s: could not add secondary bus\n", __FUNCTION__); | ||
152 | return -ENOMEM; | ||
153 | } | ||
154 | |||
155 | sprintf(child->name, "PCI Bus #%02x", child->number); | ||
156 | |||
157 | /* Fixup subordinate bridge bases and resources */ | ||
158 | pcibios_fixup_bus(child); | ||
159 | |||
160 | /* Claim new bus resources */ | ||
161 | rpadlpar_claim_one_bus(bridge_dev->bus); | ||
162 | |||
163 | if (hose->last_busno < child->number) | ||
164 | hose->last_busno = child->number; | ||
165 | |||
166 | pdn->bussubno = child->number; | ||
167 | |||
168 | /* ioremap() for child bus, which may or may not succeed */ | ||
169 | remap_bus_range(child); | ||
170 | |||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | static struct pci_dev *dlpar_find_new_dev(struct pci_bus *parent, | 137 | static struct pci_dev *dlpar_find_new_dev(struct pci_bus *parent, |
175 | struct device_node *dev_dn) | 138 | struct device_node *dev_dn) |
176 | { | 139 | { |
@@ -188,29 +151,41 @@ static struct pci_dev *dlpar_find_new_dev(struct pci_bus *parent, | |||
188 | static struct pci_dev *dlpar_pci_add_bus(struct device_node *dn) | 151 | static struct pci_dev *dlpar_pci_add_bus(struct device_node *dn) |
189 | { | 152 | { |
190 | struct pci_dn *pdn = dn->data; | 153 | struct pci_dn *pdn = dn->data; |
191 | struct pci_controller *hose = pdn->phb; | 154 | struct pci_controller *phb = pdn->phb; |
192 | struct pci_dev *dev = NULL; | 155 | struct pci_dev *dev = NULL; |
193 | 156 | ||
194 | /* Scan phb bus for EADS device, adding new one to bus->devices */ | 157 | rpaphp_eeh_init_nodes(dn); |
195 | if (!pci_scan_single_device(hose->bus, pdn->devfn)) { | 158 | /* Add EADS device to PHB bus, adding new entry to bus->devices */ |
196 | printk(KERN_ERR "%s: found no device on bus\n", __FUNCTION__); | 159 | dev = of_create_pci_dev(dn, phb->bus, pdn->devfn); |
160 | if (!dev) { | ||
161 | printk(KERN_ERR "%s: failed to create pci dev for %s\n", | ||
162 | __FUNCTION__, dn->full_name); | ||
197 | return NULL; | 163 | return NULL; |
198 | } | 164 | } |
199 | 165 | ||
166 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || | ||
167 | dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) | ||
168 | of_scan_pci_bridge(dn, dev); | ||
169 | |||
170 | rpaphp_init_new_devs(dev->subordinate); | ||
171 | |||
172 | /* Claim new bus resources */ | ||
173 | rpadlpar_claim_one_bus(dev->bus); | ||
174 | |||
175 | /* ioremap() for child bus, which may or may not succeed */ | ||
176 | (void) remap_bus_range(dev->bus); | ||
177 | |||
200 | /* Add new devices to global lists. Register in proc, sysfs. */ | 178 | /* Add new devices to global lists. Register in proc, sysfs. */ |
201 | pci_bus_add_devices(hose->bus); | 179 | pci_bus_add_devices(phb->bus); |
202 | 180 | ||
203 | /* Confirm new bridge dev was created */ | 181 | /* Confirm new bridge dev was created */ |
204 | dev = dlpar_find_new_dev(hose->bus, dn); | 182 | dev = dlpar_find_new_dev(phb->bus, dn); |
205 | if (dev) { | 183 | if (dev) { |
206 | if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) { | 184 | if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) { |
207 | printk(KERN_ERR "%s: unexpected header type %d\n", | 185 | printk(KERN_ERR "%s: unexpected header type %d\n", |
208 | __FUNCTION__, dev->hdr_type); | 186 | __FUNCTION__, dev->hdr_type); |
209 | return NULL; | 187 | return NULL; |
210 | } | 188 | } |
211 | |||
212 | if (pci_add_secondary_bus(dn, dev)) | ||
213 | return NULL; | ||
214 | } | 189 | } |
215 | 190 | ||
216 | return dev; | 191 | return dev; |
@@ -219,7 +194,6 @@ static struct pci_dev *dlpar_pci_add_bus(struct device_node *dn) | |||
219 | static int dlpar_add_pci_slot(char *drc_name, struct device_node *dn) | 194 | static int dlpar_add_pci_slot(char *drc_name, struct device_node *dn) |
220 | { | 195 | { |
221 | struct pci_dev *dev; | 196 | struct pci_dev *dev; |
222 | int rc; | ||
223 | 197 | ||
224 | if (rpaphp_find_pci_bus(dn)) | 198 | if (rpaphp_find_pci_bus(dn)) |
225 | return -EINVAL; | 199 | return -EINVAL; |
@@ -232,15 +206,6 @@ static int dlpar_add_pci_slot(char *drc_name, struct device_node *dn) | |||
232 | return -EIO; | 206 | return -EIO; |
233 | } | 207 | } |
234 | 208 | ||
235 | if (dn->child) { | ||
236 | rc = rpaphp_config_pci_adapter(dev->subordinate); | ||
237 | if (rc < 0) { | ||
238 | printk(KERN_ERR "%s: unable to enable slot %s\n", | ||
239 | __FUNCTION__, drc_name); | ||
240 | return -EIO; | ||
241 | } | ||
242 | } | ||
243 | |||
244 | /* Add hotplug slot */ | 209 | /* Add hotplug slot */ |
245 | if (rpaphp_add_slot(dn)) { | 210 | if (rpaphp_add_slot(dn)) { |
246 | printk(KERN_ERR "%s: unable to add hotplug slot %s\n", | 211 | printk(KERN_ERR "%s: unable to add hotplug slot %s\n", |
@@ -306,7 +271,7 @@ static int dlpar_add_phb(char *drc_name, struct device_node *dn) | |||
306 | { | 271 | { |
307 | struct pci_controller *phb; | 272 | struct pci_controller *phb; |
308 | 273 | ||
309 | if (PCI_DN(dn)->phb) { | 274 | if (PCI_DN(dn) && PCI_DN(dn)->phb) { |
310 | /* PHB already exists */ | 275 | /* PHB already exists */ |
311 | return -EINVAL; | 276 | return -EINVAL; |
312 | } | 277 | } |
@@ -435,6 +400,8 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn) | |||
435 | __FUNCTION__, drc_name); | 400 | __FUNCTION__, drc_name); |
436 | return -EIO; | 401 | return -EIO; |
437 | } | 402 | } |
403 | } else { | ||
404 | rpaphp_unconfig_pci_adapter(bus); | ||
438 | } | 405 | } |
439 | 406 | ||
440 | if (unmap_bus_range(bus)) { | 407 | if (unmap_bus_range(bus)) { |
diff --git a/drivers/pci/hotplug/rpaphp.h b/drivers/pci/hotplug/rpaphp.h index 71ea5f9bb284..57ea71a7bda5 100644 --- a/drivers/pci/hotplug/rpaphp.h +++ b/drivers/pci/hotplug/rpaphp.h | |||
@@ -93,6 +93,8 @@ extern int rpaphp_claim_resource(struct pci_dev *dev, int resource); | |||
93 | extern int rpaphp_enable_pci_slot(struct slot *slot); | 93 | extern int rpaphp_enable_pci_slot(struct slot *slot); |
94 | extern int register_pci_slot(struct slot *slot); | 94 | extern int register_pci_slot(struct slot *slot); |
95 | extern int rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value); | 95 | extern int rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value); |
96 | extern void rpaphp_init_new_devs(struct pci_bus *bus); | ||
97 | extern void rpaphp_eeh_init_nodes(struct device_node *dn); | ||
96 | 98 | ||
97 | extern int rpaphp_config_pci_adapter(struct pci_bus *bus); | 99 | extern int rpaphp_config_pci_adapter(struct pci_bus *bus); |
98 | extern int rpaphp_unconfig_pci_adapter(struct pci_bus *bus); | 100 | extern int rpaphp_unconfig_pci_adapter(struct pci_bus *bus); |
diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c index f7c12d7dfcfc..a7859a84d1ae 100644 --- a/drivers/pci/hotplug/rpaphp_pci.c +++ b/drivers/pci/hotplug/rpaphp_pci.c | |||
@@ -154,8 +154,7 @@ exit: | |||
154 | } | 154 | } |
155 | 155 | ||
156 | /* Must be called before pci_bus_add_devices */ | 156 | /* Must be called before pci_bus_add_devices */ |
157 | static void | 157 | void rpaphp_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus) |
158 | rpaphp_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus) | ||
159 | { | 158 | { |
160 | struct pci_dev *dev; | 159 | struct pci_dev *dev; |
161 | 160 | ||
@@ -184,6 +183,20 @@ rpaphp_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus) | |||
184 | } | 183 | } |
185 | } | 184 | } |
186 | 185 | ||
186 | static void rpaphp_eeh_add_bus_device(struct pci_bus *bus) | ||
187 | { | ||
188 | struct pci_dev *dev; | ||
189 | |||
190 | list_for_each_entry(dev, &bus->devices, bus_list) { | ||
191 | eeh_add_device_late(dev); | ||
192 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { | ||
193 | struct pci_bus *subbus = dev->subordinate; | ||
194 | if (subbus) | ||
195 | rpaphp_eeh_add_bus_device (subbus); | ||
196 | } | ||
197 | } | ||
198 | } | ||
199 | |||
187 | static int rpaphp_pci_config_bridge(struct pci_dev *dev) | 200 | static int rpaphp_pci_config_bridge(struct pci_dev *dev) |
188 | { | 201 | { |
189 | u8 sec_busno; | 202 | u8 sec_busno; |
@@ -217,6 +230,13 @@ static int rpaphp_pci_config_bridge(struct pci_dev *dev) | |||
217 | return 0; | 230 | return 0; |
218 | } | 231 | } |
219 | 232 | ||
233 | void rpaphp_init_new_devs(struct pci_bus *bus) | ||
234 | { | ||
235 | rpaphp_fixup_new_pci_devices(bus, 0); | ||
236 | rpaphp_eeh_add_bus_device(bus); | ||
237 | } | ||
238 | EXPORT_SYMBOL_GPL(rpaphp_init_new_devs); | ||
239 | |||
220 | /***************************************************************************** | 240 | /***************************************************************************** |
221 | rpaphp_pci_config_slot() will configure all devices under the | 241 | rpaphp_pci_config_slot() will configure all devices under the |
222 | given slot->dn and return the the first pci_dev. | 242 | given slot->dn and return the the first pci_dev. |
@@ -233,36 +253,51 @@ rpaphp_pci_config_slot(struct pci_bus *bus) | |||
233 | if (!dn || !dn->child) | 253 | if (!dn || !dn->child) |
234 | return NULL; | 254 | return NULL; |
235 | 255 | ||
236 | slotno = PCI_SLOT(PCI_DN(dn->child)->devfn); | 256 | if (systemcfg->platform == PLATFORM_PSERIES_LPAR) { |
257 | of_scan_bus(dn, bus); | ||
258 | if (list_empty(&bus->devices)) { | ||
259 | err("%s: No new device found\n", __FUNCTION__); | ||
260 | return NULL; | ||
261 | } | ||
237 | 262 | ||
238 | /* pci_scan_slot should find all children */ | 263 | rpaphp_init_new_devs(bus); |
239 | num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0)); | ||
240 | if (num) { | ||
241 | rpaphp_fixup_new_pci_devices(bus, 1); | ||
242 | pci_bus_add_devices(bus); | 264 | pci_bus_add_devices(bus); |
243 | } | 265 | dev = list_entry(&bus->devices, struct pci_dev, bus_list); |
244 | if (list_empty(&bus->devices)) { | 266 | } else { |
245 | err("%s: No new device found\n", __FUNCTION__); | 267 | slotno = PCI_SLOT(PCI_DN(dn->child)->devfn); |
246 | return NULL; | 268 | |
247 | } | 269 | /* pci_scan_slot should find all children */ |
248 | list_for_each_entry(dev, &bus->devices, bus_list) { | 270 | num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0)); |
249 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) | 271 | if (num) { |
250 | rpaphp_pci_config_bridge(dev); | 272 | rpaphp_fixup_new_pci_devices(bus, 1); |
273 | pci_bus_add_devices(bus); | ||
274 | } | ||
275 | if (list_empty(&bus->devices)) { | ||
276 | err("%s: No new device found\n", __FUNCTION__); | ||
277 | return NULL; | ||
278 | } | ||
279 | list_for_each_entry(dev, &bus->devices, bus_list) { | ||
280 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) | ||
281 | rpaphp_pci_config_bridge(dev); | ||
282 | |||
283 | rpaphp_eeh_add_bus_device(bus); | ||
284 | } | ||
251 | } | 285 | } |
252 | 286 | ||
253 | return dev; | 287 | return dev; |
254 | } | 288 | } |
255 | 289 | ||
256 | static void enable_eeh(struct device_node *dn) | 290 | void rpaphp_eeh_init_nodes(struct device_node *dn) |
257 | { | 291 | { |
258 | struct device_node *sib; | 292 | struct device_node *sib; |
259 | 293 | ||
260 | for (sib = dn->child; sib; sib = sib->sibling) | 294 | for (sib = dn->child; sib; sib = sib->sibling) |
261 | enable_eeh(sib); | 295 | rpaphp_eeh_init_nodes(sib); |
262 | eeh_add_device_early(dn); | 296 | eeh_add_device_early(dn); |
263 | return; | 297 | return; |
264 | 298 | ||
265 | } | 299 | } |
300 | EXPORT_SYMBOL_GPL(rpaphp_eeh_init_nodes); | ||
266 | 301 | ||
267 | static void print_slot_pci_funcs(struct pci_bus *bus) | 302 | static void print_slot_pci_funcs(struct pci_bus *bus) |
268 | { | 303 | { |
@@ -289,7 +324,7 @@ int rpaphp_config_pci_adapter(struct pci_bus *bus) | |||
289 | if (!dn) | 324 | if (!dn) |
290 | goto exit; | 325 | goto exit; |
291 | 326 | ||
292 | enable_eeh(dn); | 327 | rpaphp_eeh_init_nodes(dn); |
293 | dev = rpaphp_pci_config_slot(bus); | 328 | dev = rpaphp_pci_config_slot(bus); |
294 | if (!dev) { | 329 | if (!dev) { |
295 | err("%s: can't find any devices.\n", __FUNCTION__); | 330 | err("%s: can't find any devices.\n", __FUNCTION__); |
@@ -331,6 +366,7 @@ int rpaphp_unconfig_pci_adapter(struct pci_bus *bus) | |||
331 | } | 366 | } |
332 | return 0; | 367 | return 0; |
333 | } | 368 | } |
369 | EXPORT_SYMBOL_GPL(rpaphp_unconfig_pci_adapter); | ||
334 | 370 | ||
335 | static int setup_pci_hotplug_slot_info(struct slot *slot) | 371 | static int setup_pci_hotplug_slot_info(struct slot *slot) |
336 | { | 372 | { |
@@ -444,8 +480,8 @@ int rpaphp_enable_pci_slot(struct slot *slot) | |||
444 | retval = rpaphp_config_pci_adapter(slot->bus); | 480 | retval = rpaphp_config_pci_adapter(slot->bus); |
445 | if (!retval) { | 481 | if (!retval) { |
446 | slot->state = CONFIGURED; | 482 | slot->state = CONFIGURED; |
447 | dbg("%s: PCI devices in slot[%s] has been configured\n", | 483 | info("%s: devices in slot[%s] configured\n", |
448 | __FUNCTION__, slot->name); | 484 | __FUNCTION__, slot->name); |
449 | } else { | 485 | } else { |
450 | slot->state = NOT_CONFIGURED; | 486 | slot->state = NOT_CONFIGURED; |
451 | dbg("%s: no pci_dev struct for adapter in slot[%s]\n", | 487 | dbg("%s: no pci_dev struct for adapter in slot[%s]\n", |
diff --git a/drivers/pci/hotplug/shpchp_pci.c b/drivers/pci/hotplug/shpchp_pci.c index b8e95acea3b6..38009bc0fd5d 100644 --- a/drivers/pci/hotplug/shpchp_pci.c +++ b/drivers/pci/hotplug/shpchp_pci.c | |||
@@ -34,7 +34,7 @@ | |||
34 | #include "../pci.h" | 34 | #include "../pci.h" |
35 | #include "shpchp.h" | 35 | #include "shpchp.h" |
36 | 36 | ||
37 | void program_fw_provided_values(struct pci_dev *dev) | 37 | static void program_fw_provided_values(struct pci_dev *dev) |
38 | { | 38 | { |
39 | u16 pci_cmd, pci_bctl; | 39 | u16 pci_cmd, pci_bctl; |
40 | struct pci_dev *cdev; | 40 | struct pci_dev *cdev; |
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index a2033552423c..202b7507a357 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c | |||
@@ -23,6 +23,8 @@ | |||
23 | #include "pci.h" | 23 | #include "pci.h" |
24 | #include "msi.h" | 24 | #include "msi.h" |
25 | 25 | ||
26 | #define MSI_TARGET_CPU first_cpu(cpu_online_map) | ||
27 | |||
26 | static DEFINE_SPINLOCK(msi_lock); | 28 | static DEFINE_SPINLOCK(msi_lock); |
27 | static struct msi_desc* msi_desc[NR_IRQS] = { [0 ... NR_IRQS-1] = NULL }; | 29 | static struct msi_desc* msi_desc[NR_IRQS] = { [0 ... NR_IRQS-1] = NULL }; |
28 | static kmem_cache_t* msi_cachep; | 30 | static kmem_cache_t* msi_cachep; |
@@ -92,6 +94,7 @@ static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask) | |||
92 | struct msi_desc *entry; | 94 | struct msi_desc *entry; |
93 | struct msg_address address; | 95 | struct msg_address address; |
94 | unsigned int irq = vector; | 96 | unsigned int irq = vector; |
97 | unsigned int dest_cpu = first_cpu(cpu_mask); | ||
95 | 98 | ||
96 | entry = (struct msi_desc *)msi_desc[vector]; | 99 | entry = (struct msi_desc *)msi_desc[vector]; |
97 | if (!entry || !entry->dev) | 100 | if (!entry || !entry->dev) |
@@ -108,9 +111,9 @@ static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask) | |||
108 | pci_read_config_dword(entry->dev, msi_lower_address_reg(pos), | 111 | pci_read_config_dword(entry->dev, msi_lower_address_reg(pos), |
109 | &address.lo_address.value); | 112 | &address.lo_address.value); |
110 | address.lo_address.value &= MSI_ADDRESS_DEST_ID_MASK; | 113 | address.lo_address.value &= MSI_ADDRESS_DEST_ID_MASK; |
111 | address.lo_address.value |= (cpu_mask_to_apicid(cpu_mask) << | 114 | address.lo_address.value |= (cpu_physical_id(dest_cpu) << |
112 | MSI_TARGET_CPU_SHIFT); | 115 | MSI_TARGET_CPU_SHIFT); |
113 | entry->msi_attrib.current_cpu = cpu_mask_to_apicid(cpu_mask); | 116 | entry->msi_attrib.current_cpu = cpu_physical_id(dest_cpu); |
114 | pci_write_config_dword(entry->dev, msi_lower_address_reg(pos), | 117 | pci_write_config_dword(entry->dev, msi_lower_address_reg(pos), |
115 | address.lo_address.value); | 118 | address.lo_address.value); |
116 | set_native_irq_info(irq, cpu_mask); | 119 | set_native_irq_info(irq, cpu_mask); |
@@ -123,9 +126,9 @@ static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask) | |||
123 | 126 | ||
124 | address.lo_address.value = readl(entry->mask_base + offset); | 127 | address.lo_address.value = readl(entry->mask_base + offset); |
125 | address.lo_address.value &= MSI_ADDRESS_DEST_ID_MASK; | 128 | address.lo_address.value &= MSI_ADDRESS_DEST_ID_MASK; |
126 | address.lo_address.value |= (cpu_mask_to_apicid(cpu_mask) << | 129 | address.lo_address.value |= (cpu_physical_id(dest_cpu) << |
127 | MSI_TARGET_CPU_SHIFT); | 130 | MSI_TARGET_CPU_SHIFT); |
128 | entry->msi_attrib.current_cpu = cpu_mask_to_apicid(cpu_mask); | 131 | entry->msi_attrib.current_cpu = cpu_physical_id(dest_cpu); |
129 | writel(address.lo_address.value, entry->mask_base + offset); | 132 | writel(address.lo_address.value, entry->mask_base + offset); |
130 | set_native_irq_info(irq, cpu_mask); | 133 | set_native_irq_info(irq, cpu_mask); |
131 | break; | 134 | break; |
@@ -259,14 +262,15 @@ static void msi_data_init(struct msg_data *msi_data, | |||
259 | static void msi_address_init(struct msg_address *msi_address) | 262 | static void msi_address_init(struct msg_address *msi_address) |
260 | { | 263 | { |
261 | unsigned int dest_id; | 264 | unsigned int dest_id; |
265 | unsigned long dest_phys_id = cpu_physical_id(MSI_TARGET_CPU); | ||
262 | 266 | ||
263 | memset(msi_address, 0, sizeof(struct msg_address)); | 267 | memset(msi_address, 0, sizeof(struct msg_address)); |
264 | msi_address->hi_address = (u32)0; | 268 | msi_address->hi_address = (u32)0; |
265 | dest_id = (MSI_ADDRESS_HEADER << MSI_ADDRESS_HEADER_SHIFT); | 269 | dest_id = (MSI_ADDRESS_HEADER << MSI_ADDRESS_HEADER_SHIFT); |
266 | msi_address->lo_address.u.dest_mode = MSI_DEST_MODE; | 270 | msi_address->lo_address.u.dest_mode = MSI_PHYSICAL_MODE; |
267 | msi_address->lo_address.u.redirection_hint = MSI_REDIRECTION_HINT_MODE; | 271 | msi_address->lo_address.u.redirection_hint = MSI_REDIRECTION_HINT_MODE; |
268 | msi_address->lo_address.u.dest_id = dest_id; | 272 | msi_address->lo_address.u.dest_id = dest_id; |
269 | msi_address->lo_address.value |= (MSI_TARGET_CPU << MSI_TARGET_CPU_SHIFT); | 273 | msi_address->lo_address.value |= (dest_phys_id << MSI_TARGET_CPU_SHIFT); |
270 | } | 274 | } |
271 | 275 | ||
272 | static int msi_free_vector(struct pci_dev* dev, int vector, int reassign); | 276 | static int msi_free_vector(struct pci_dev* dev, int vector, int reassign); |
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index e9e37abe1f76..a9b00cc2d885 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c | |||
@@ -91,9 +91,7 @@ acpi_query_osc ( | |||
91 | static acpi_status | 91 | static acpi_status |
92 | acpi_run_osc ( | 92 | acpi_run_osc ( |
93 | acpi_handle handle, | 93 | acpi_handle handle, |
94 | u32 level, | 94 | void *context) |
95 | void *context, | ||
96 | void **retval ) | ||
97 | { | 95 | { |
98 | acpi_status status; | 96 | acpi_status status; |
99 | struct acpi_object_list input; | 97 | struct acpi_object_list input; |
@@ -184,7 +182,7 @@ EXPORT_SYMBOL(pci_osc_support_set); | |||
184 | * | 182 | * |
185 | * Attempt to take control from Firmware on requested control bits. | 183 | * Attempt to take control from Firmware on requested control bits. |
186 | **/ | 184 | **/ |
187 | acpi_status pci_osc_control_set(u32 flags) | 185 | acpi_status pci_osc_control_set(acpi_handle handle, u32 flags) |
188 | { | 186 | { |
189 | acpi_status status; | 187 | acpi_status status; |
190 | u32 ctrlset; | 188 | u32 ctrlset; |
@@ -198,10 +196,7 @@ acpi_status pci_osc_control_set(u32 flags) | |||
198 | return AE_SUPPORT; | 196 | return AE_SUPPORT; |
199 | } | 197 | } |
200 | ctrlset_buf[OSC_CONTROL_TYPE] |= ctrlset; | 198 | ctrlset_buf[OSC_CONTROL_TYPE] |= ctrlset; |
201 | status = acpi_get_devices ( PCI_ROOT_HID_STRING, | 199 | status = acpi_run_osc(handle, ctrlset_buf); |
202 | acpi_run_osc, | ||
203 | ctrlset_buf, | ||
204 | NULL ); | ||
205 | if (ACPI_FAILURE (status)) { | 200 | if (ACPI_FAILURE (status)) { |
206 | ctrlset_buf[OSC_CONTROL_TYPE] &= ~ctrlset; | 201 | ctrlset_buf[OSC_CONTROL_TYPE] &= ~ctrlset; |
207 | } | 202 | } |
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 94e68c54d273..a9046d4b8af3 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c | |||
@@ -37,7 +37,7 @@ struct pci_dynid { | |||
37 | * Adds a new dynamic pci device ID to this driver, | 37 | * Adds a new dynamic pci device ID to this driver, |
38 | * and causes the driver to probe for all devices again. | 38 | * and causes the driver to probe for all devices again. |
39 | */ | 39 | */ |
40 | static inline ssize_t | 40 | static ssize_t |
41 | store_new_id(struct device_driver *driver, const char *buf, size_t count) | 41 | store_new_id(struct device_driver *driver, const char *buf, size_t count) |
42 | { | 42 | { |
43 | struct pci_dynid *dynid; | 43 | struct pci_dynid *dynid; |
@@ -364,15 +364,16 @@ static struct kobj_type pci_driver_kobj_type = { | |||
364 | }; | 364 | }; |
365 | 365 | ||
366 | /** | 366 | /** |
367 | * pci_register_driver - register a new pci driver | 367 | * __pci_register_driver - register a new pci driver |
368 | * @drv: the driver structure to register | 368 | * @drv: the driver structure to register |
369 | * @owner: owner module of drv | ||
369 | * | 370 | * |
370 | * Adds the driver structure to the list of registered drivers. | 371 | * Adds the driver structure to the list of registered drivers. |
371 | * Returns a negative value on error, otherwise 0. | 372 | * Returns a negative value on error, otherwise 0. |
372 | * If no error occurred, the driver remains registered even if | 373 | * If no error occurred, the driver remains registered even if |
373 | * no device was claimed during registration. | 374 | * no device was claimed during registration. |
374 | */ | 375 | */ |
375 | int pci_register_driver(struct pci_driver *drv) | 376 | int __pci_register_driver(struct pci_driver *drv, struct module *owner) |
376 | { | 377 | { |
377 | int error; | 378 | int error; |
378 | 379 | ||
@@ -389,7 +390,7 @@ int pci_register_driver(struct pci_driver *drv) | |||
389 | printk(KERN_WARNING "Warning: PCI driver %s has a struct " | 390 | printk(KERN_WARNING "Warning: PCI driver %s has a struct " |
390 | "device_driver shutdown method, please update!\n", | 391 | "device_driver shutdown method, please update!\n", |
391 | drv->name); | 392 | drv->name); |
392 | drv->driver.owner = drv->owner; | 393 | drv->driver.owner = owner; |
393 | drv->driver.kobj.ktype = &pci_driver_kobj_type; | 394 | drv->driver.kobj.ktype = &pci_driver_kobj_type; |
394 | 395 | ||
395 | spin_lock_init(&drv->dynids.lock); | 396 | spin_lock_init(&drv->dynids.lock); |
@@ -526,7 +527,7 @@ postcore_initcall(pci_driver_init); | |||
526 | 527 | ||
527 | EXPORT_SYMBOL(pci_match_id); | 528 | EXPORT_SYMBOL(pci_match_id); |
528 | EXPORT_SYMBOL(pci_match_device); | 529 | EXPORT_SYMBOL(pci_match_device); |
529 | EXPORT_SYMBOL(pci_register_driver); | 530 | EXPORT_SYMBOL(__pci_register_driver); |
530 | EXPORT_SYMBOL(pci_unregister_driver); | 531 | EXPORT_SYMBOL(pci_unregister_driver); |
531 | EXPORT_SYMBOL(pci_dev_driver); | 532 | EXPORT_SYMBOL(pci_dev_driver); |
532 | EXPORT_SYMBOL(pci_bus_type); | 533 | EXPORT_SYMBOL(pci_bus_type); |
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index e74d75843047..8e287a828d5d 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -63,11 +63,38 @@ pci_max_busnr(void) | |||
63 | return max; | 63 | return max; |
64 | } | 64 | } |
65 | 65 | ||
66 | static int __pci_find_next_cap(struct pci_bus *bus, unsigned int devfn, u8 pos, int cap) | ||
67 | { | ||
68 | u8 id; | ||
69 | int ttl = 48; | ||
70 | |||
71 | while (ttl--) { | ||
72 | pci_bus_read_config_byte(bus, devfn, pos, &pos); | ||
73 | if (pos < 0x40) | ||
74 | break; | ||
75 | pos &= ~3; | ||
76 | pci_bus_read_config_byte(bus, devfn, pos + PCI_CAP_LIST_ID, | ||
77 | &id); | ||
78 | if (id == 0xff) | ||
79 | break; | ||
80 | if (id == cap) | ||
81 | return pos; | ||
82 | pos += PCI_CAP_LIST_NEXT; | ||
83 | } | ||
84 | return 0; | ||
85 | } | ||
86 | |||
87 | int pci_find_next_capability(struct pci_dev *dev, u8 pos, int cap) | ||
88 | { | ||
89 | return __pci_find_next_cap(dev->bus, dev->devfn, | ||
90 | pos + PCI_CAP_LIST_NEXT, cap); | ||
91 | } | ||
92 | EXPORT_SYMBOL_GPL(pci_find_next_capability); | ||
93 | |||
66 | static int __pci_bus_find_cap(struct pci_bus *bus, unsigned int devfn, u8 hdr_type, int cap) | 94 | static int __pci_bus_find_cap(struct pci_bus *bus, unsigned int devfn, u8 hdr_type, int cap) |
67 | { | 95 | { |
68 | u16 status; | 96 | u16 status; |
69 | u8 pos, id; | 97 | u8 pos; |
70 | int ttl = 48; | ||
71 | 98 | ||
72 | pci_bus_read_config_word(bus, devfn, PCI_STATUS, &status); | 99 | pci_bus_read_config_word(bus, devfn, PCI_STATUS, &status); |
73 | if (!(status & PCI_STATUS_CAP_LIST)) | 100 | if (!(status & PCI_STATUS_CAP_LIST)) |
@@ -76,24 +103,15 @@ static int __pci_bus_find_cap(struct pci_bus *bus, unsigned int devfn, u8 hdr_ty | |||
76 | switch (hdr_type) { | 103 | switch (hdr_type) { |
77 | case PCI_HEADER_TYPE_NORMAL: | 104 | case PCI_HEADER_TYPE_NORMAL: |
78 | case PCI_HEADER_TYPE_BRIDGE: | 105 | case PCI_HEADER_TYPE_BRIDGE: |
79 | pci_bus_read_config_byte(bus, devfn, PCI_CAPABILITY_LIST, &pos); | 106 | pos = PCI_CAPABILITY_LIST; |
80 | break; | 107 | break; |
81 | case PCI_HEADER_TYPE_CARDBUS: | 108 | case PCI_HEADER_TYPE_CARDBUS: |
82 | pci_bus_read_config_byte(bus, devfn, PCI_CB_CAPABILITY_LIST, &pos); | 109 | pos = PCI_CB_CAPABILITY_LIST; |
83 | break; | 110 | break; |
84 | default: | 111 | default: |
85 | return 0; | 112 | return 0; |
86 | } | 113 | } |
87 | while (ttl-- && pos >= 0x40) { | 114 | return __pci_find_next_cap(bus, devfn, pos, cap); |
88 | pos &= ~3; | ||
89 | pci_bus_read_config_byte(bus, devfn, pos + PCI_CAP_LIST_ID, &id); | ||
90 | if (id == 0xff) | ||
91 | break; | ||
92 | if (id == cap) | ||
93 | return pos; | ||
94 | pci_bus_read_config_byte(bus, devfn, pos + PCI_CAP_LIST_NEXT, &pos); | ||
95 | } | ||
96 | return 0; | ||
97 | } | 115 | } |
98 | 116 | ||
99 | /** | 117 | /** |
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 5627ce1d2b32..3a4f49f4effb 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c | |||
@@ -462,11 +462,11 @@ static void __devinit quirk_vt82c686_acpi(struct pci_dev *dev) | |||
462 | 462 | ||
463 | pci_read_config_word(dev, 0x70, &hm); | 463 | pci_read_config_word(dev, 0x70, &hm); |
464 | hm &= PCI_BASE_ADDRESS_IO_MASK; | 464 | hm &= PCI_BASE_ADDRESS_IO_MASK; |
465 | quirk_io_region(dev, hm, 128, PCI_BRIDGE_RESOURCES + 1, "vt82c868 HW-mon"); | 465 | quirk_io_region(dev, hm, 128, PCI_BRIDGE_RESOURCES + 1, "vt82c686 HW-mon"); |
466 | 466 | ||
467 | pci_read_config_dword(dev, 0x90, &smb); | 467 | pci_read_config_dword(dev, 0x90, &smb); |
468 | smb &= PCI_BASE_ADDRESS_IO_MASK; | 468 | smb &= PCI_BASE_ADDRESS_IO_MASK; |
469 | quirk_io_region(dev, smb, 16, PCI_BRIDGE_RESOURCES + 2, "vt82c868 SMB"); | 469 | quirk_io_region(dev, smb, 16, PCI_BRIDGE_RESOURCES + 2, "vt82c686 SMB"); |
470 | } | 470 | } |
471 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_vt82c686_acpi ); | 471 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_vt82c686_acpi ); |
472 | 472 | ||
@@ -1243,6 +1243,21 @@ static void __devinit quirk_netmos(struct pci_dev *dev) | |||
1243 | } | 1243 | } |
1244 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NETMOS, PCI_ANY_ID, quirk_netmos); | 1244 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NETMOS, PCI_ANY_ID, quirk_netmos); |
1245 | 1245 | ||
1246 | |||
1247 | static void __devinit fixup_rev1_53c810(struct pci_dev* dev) | ||
1248 | { | ||
1249 | /* rev 1 ncr53c810 chips don't set the class at all which means | ||
1250 | * they don't get their resources remapped. Fix that here. | ||
1251 | */ | ||
1252 | |||
1253 | if (dev->class == PCI_CLASS_NOT_DEFINED) { | ||
1254 | printk(KERN_INFO "NCR 53c810 rev 1 detected, setting PCI class.\n"); | ||
1255 | dev->class = PCI_CLASS_STORAGE_SCSI; | ||
1256 | } | ||
1257 | } | ||
1258 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, fixup_rev1_53c810); | ||
1259 | |||
1260 | |||
1246 | static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end) | 1261 | static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end) |
1247 | { | 1262 | { |
1248 | while (f < end) { | 1263 | while (f < end) { |
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig index ccf20039e909..309eb557f9a3 100644 --- a/drivers/pcmcia/Kconfig +++ b/drivers/pcmcia/Kconfig | |||
@@ -156,7 +156,7 @@ config TCIC | |||
156 | 156 | ||
157 | config PCMCIA_M8XX | 157 | config PCMCIA_M8XX |
158 | tristate "MPC8xx PCMCIA support" | 158 | tristate "MPC8xx PCMCIA support" |
159 | depends on PCMCIA && PPC | 159 | depends on PCMCIA && PPC && 8xx |
160 | select PCCARD_NONSTATIC | 160 | select PCCARD_NONSTATIC |
161 | help | 161 | help |
162 | Say Y here to include support for PowerPC 8xx series PCMCIA | 162 | Say Y here to include support for PowerPC 8xx series PCMCIA |
diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile index fe37541abbfe..bcecf5133b7e 100644 --- a/drivers/pcmcia/Makefile +++ b/drivers/pcmcia/Makefile | |||
@@ -25,7 +25,7 @@ obj-$(CONFIG_PD6729) += pd6729.o | |||
25 | obj-$(CONFIG_I82365) += i82365.o | 25 | obj-$(CONFIG_I82365) += i82365.o |
26 | obj-$(CONFIG_I82092) += i82092.o | 26 | obj-$(CONFIG_I82092) += i82092.o |
27 | obj-$(CONFIG_TCIC) += tcic.o | 27 | obj-$(CONFIG_TCIC) += tcic.o |
28 | obj-$(CONFIG_PCMCIA_M8XX) += m8xx_pcmcia.o | 28 | obj-$(CONFIG_PCMCIA_M8XX) += m8xx_pcmcia.o |
29 | obj-$(CONFIG_HD64465_PCMCIA) += hd64465_ss.o | 29 | obj-$(CONFIG_HD64465_PCMCIA) += hd64465_ss.o |
30 | obj-$(CONFIG_PCMCIA_SA1100) += sa11xx_core.o sa1100_cs.o | 30 | obj-$(CONFIG_PCMCIA_SA1100) += sa11xx_core.o sa1100_cs.o |
31 | obj-$(CONFIG_PCMCIA_SA1111) += sa11xx_core.o sa1111_cs.o | 31 | obj-$(CONFIG_PCMCIA_SA1111) += sa11xx_core.o sa1111_cs.o |
@@ -47,10 +47,10 @@ au1x00_ss-$(CONFIG_MIPS_PB1200) += au1000_db1x00.o | |||
47 | au1x00_ss-$(CONFIG_MIPS_PB1500) += au1000_pb1x00.o | 47 | au1x00_ss-$(CONFIG_MIPS_PB1500) += au1000_pb1x00.o |
48 | au1x00_ss-$(CONFIG_MIPS_DB1000) += au1000_db1x00.o | 48 | au1x00_ss-$(CONFIG_MIPS_DB1000) += au1000_db1x00.o |
49 | au1x00_ss-$(CONFIG_MIPS_DB1100) += au1000_db1x00.o | 49 | au1x00_ss-$(CONFIG_MIPS_DB1100) += au1000_db1x00.o |
50 | au1x00_ss-$(CONFIG_MIPS_DB1200) += au1000_db1x00.o | 50 | au1x00_ss-$(CONFIG_MIPS_DB1200) += au1000_db1x00.o |
51 | au1x00_ss-$(CONFIG_MIPS_DB1500) += au1000_db1x00.o | 51 | au1x00_ss-$(CONFIG_MIPS_DB1500) += au1000_db1x00.o |
52 | au1x00_ss-$(CONFIG_MIPS_DB1550) += au1000_db1x00.o | 52 | au1x00_ss-$(CONFIG_MIPS_DB1550) += au1000_db1x00.o |
53 | au1x00_ss-$(CONFIG_MIPS_XXS1500) += au1000_xxs1500.o | 53 | au1x00_ss-$(CONFIG_MIPS_XXS1500) += au1000_xxs1500.o |
54 | 54 | ||
55 | sa1111_cs-y += sa1111_generic.o | 55 | sa1111_cs-y += sa1111_generic.o |
56 | sa1111_cs-$(CONFIG_ASSABET_NEPONSET) += sa1100_neponset.o | 56 | sa1111_cs-$(CONFIG_ASSABET_NEPONSET) += sa1100_neponset.o |
diff --git a/drivers/pcmcia/au1000_db1x00.c b/drivers/pcmcia/au1000_db1x00.c index 24cfee1a412c..abc13f28ba3f 100644 --- a/drivers/pcmcia/au1000_db1x00.c +++ b/drivers/pcmcia/au1000_db1x00.c | |||
@@ -30,6 +30,7 @@ | |||
30 | * | 30 | * |
31 | */ | 31 | */ |
32 | 32 | ||
33 | #include <linux/config.h> | ||
33 | #include <linux/module.h> | 34 | #include <linux/module.h> |
34 | #include <linux/kernel.h> | 35 | #include <linux/kernel.h> |
35 | #include <linux/errno.h> | 36 | #include <linux/errno.h> |
diff --git a/drivers/pcmcia/au1000_generic.h b/drivers/pcmcia/au1000_generic.h index b0e7908392a7..f2c970b5f4ff 100644 --- a/drivers/pcmcia/au1000_generic.h +++ b/drivers/pcmcia/au1000_generic.h | |||
@@ -22,6 +22,8 @@ | |||
22 | #define __ASM_AU1000_PCMCIA_H | 22 | #define __ASM_AU1000_PCMCIA_H |
23 | 23 | ||
24 | /* include the world */ | 24 | /* include the world */ |
25 | #include <linux/config.h> | ||
26 | |||
25 | #include <pcmcia/cs_types.h> | 27 | #include <pcmcia/cs_types.h> |
26 | #include <pcmcia/cs.h> | 28 | #include <pcmcia/cs.h> |
27 | #include <pcmcia/ss.h> | 29 | #include <pcmcia/ss.h> |
diff --git a/drivers/pcmcia/au1000_pb1x00.c b/drivers/pcmcia/au1000_pb1x00.c index 86c0808d6a05..fd5522ede867 100644 --- a/drivers/pcmcia/au1000_pb1x00.c +++ b/drivers/pcmcia/au1000_pb1x00.c | |||
@@ -21,6 +21,7 @@ | |||
21 | * with this program; if not, write to the Free Software Foundation, Inc., | 21 | * with this program; if not, write to the Free Software Foundation, Inc., |
22 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | 22 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. |
23 | */ | 23 | */ |
24 | #include <linux/config.h> | ||
24 | #include <linux/module.h> | 25 | #include <linux/module.h> |
25 | #include <linux/init.h> | 26 | #include <linux/init.h> |
26 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
diff --git a/drivers/pcmcia/au1000_xxs1500.c b/drivers/pcmcia/au1000_xxs1500.c index 01a895bc9a47..01874b0bb03b 100644 --- a/drivers/pcmcia/au1000_xxs1500.c +++ b/drivers/pcmcia/au1000_xxs1500.c | |||
@@ -27,7 +27,6 @@ | |||
27 | */ | 27 | */ |
28 | #include <linux/module.h> | 28 | #include <linux/module.h> |
29 | #include <linux/init.h> | 29 | #include <linux/init.h> |
30 | #include <linux/config.h> | ||
31 | #include <linux/delay.h> | 30 | #include <linux/delay.h> |
32 | #include <linux/ioport.h> | 31 | #include <linux/ioport.h> |
33 | #include <linux/kernel.h> | 32 | #include <linux/kernel.h> |
diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c index 7ce455d01cc9..4ddd76239b34 100644 --- a/drivers/pcmcia/i82365.c +++ b/drivers/pcmcia/i82365.c | |||
@@ -1366,6 +1366,7 @@ static int __init init_i82365(void) | |||
1366 | if (sockets == 0) { | 1366 | if (sockets == 0) { |
1367 | printk("not found.\n"); | 1367 | printk("not found.\n"); |
1368 | platform_device_unregister(&i82365_device); | 1368 | platform_device_unregister(&i82365_device); |
1369 | release_region(i365_base, 2); | ||
1369 | driver_unregister(&i82365_driver); | 1370 | driver_unregister(&i82365_driver); |
1370 | return -ENODEV; | 1371 | return -ENODEV; |
1371 | } | 1372 | } |
diff --git a/drivers/pcmcia/m8xx_pcmcia.c b/drivers/pcmcia/m8xx_pcmcia.c index f8bed87cf2f1..6d9f71cfcb34 100644 --- a/drivers/pcmcia/m8xx_pcmcia.c +++ b/drivers/pcmcia/m8xx_pcmcia.c | |||
@@ -39,7 +39,6 @@ | |||
39 | 39 | ||
40 | #include <asm/io.h> | 40 | #include <asm/io.h> |
41 | #include <asm/bitops.h> | 41 | #include <asm/bitops.h> |
42 | #include <asm/segment.h> | ||
43 | #include <asm/system.h> | 42 | #include <asm/system.h> |
44 | 43 | ||
45 | #include <linux/kernel.h> | 44 | #include <linux/kernel.h> |
@@ -50,6 +49,7 @@ | |||
50 | #include <linux/ioport.h> | 49 | #include <linux/ioport.h> |
51 | #include <linux/delay.h> | 50 | #include <linux/delay.h> |
52 | #include <linux/interrupt.h> | 51 | #include <linux/interrupt.h> |
52 | #include <linux/platform_device.h> | ||
53 | 53 | ||
54 | #include <asm/mpc8xx.h> | 54 | #include <asm/mpc8xx.h> |
55 | #include <asm/8xx_immap.h> | 55 | #include <asm/8xx_immap.h> |
@@ -546,29 +546,11 @@ static void m8xx_shutdown(void) | |||
546 | free_irq(pcmcia_schlvl, NULL); | 546 | free_irq(pcmcia_schlvl, NULL); |
547 | } | 547 | } |
548 | 548 | ||
549 | /* copied from tcic.c */ | ||
550 | |||
551 | static int m8xx_drv_suspend(struct device *dev, pm_message_t state, u32 level) | ||
552 | { | ||
553 | int ret = 0; | ||
554 | if (level == SUSPEND_SAVE_STATE) | ||
555 | ret = pcmcia_socket_dev_suspend(dev, state); | ||
556 | return ret; | ||
557 | } | ||
558 | |||
559 | static int m8xx_drv_resume(struct device *dev, u32 level) | ||
560 | { | ||
561 | int ret = 0; | ||
562 | if (level == RESUME_RESTORE_STATE) | ||
563 | ret = pcmcia_socket_dev_resume(dev); | ||
564 | return ret; | ||
565 | } | ||
566 | |||
567 | static struct device_driver m8xx_driver = { | 549 | static struct device_driver m8xx_driver = { |
568 | .name = "m8xx-pcmcia", | 550 | .name = "m8xx-pcmcia", |
569 | .bus = &platform_bus_type, | 551 | .bus = &platform_bus_type, |
570 | .suspend = m8xx_drv_suspend, | 552 | .suspend = pcmcia_socket_dev_suspend, |
571 | .resume = m8xx_drv_resume, | 553 | .resume = pcmcia_socket_dev_resume, |
572 | }; | 554 | }; |
573 | 555 | ||
574 | static struct platform_device m8xx_device = { | 556 | static struct platform_device m8xx_device = { |
diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c index 2c86a4b809cd..c3a51d1fae5d 100644 --- a/drivers/sbus/char/display7seg.c +++ b/drivers/sbus/char/display7seg.c | |||
@@ -119,7 +119,7 @@ static long d7s_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
119 | { | 119 | { |
120 | __u8 regs = readb(d7s_regs); | 120 | __u8 regs = readb(d7s_regs); |
121 | __u8 ireg = 0; | 121 | __u8 ireg = 0; |
122 | int error = 0 | 122 | int error = 0; |
123 | 123 | ||
124 | if (D7S_MINOR != iminor(file->f_dentry->d_inode)) | 124 | if (D7S_MINOR != iminor(file->f_dentry->d_inode)) |
125 | return -ENODEV; | 125 | return -ENODEV; |
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index c90723860a04..07498118359d 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -1704,7 +1704,6 @@ MODULE_DEVICE_TABLE(pci, lpfc_id_table); | |||
1704 | 1704 | ||
1705 | static struct pci_driver lpfc_driver = { | 1705 | static struct pci_driver lpfc_driver = { |
1706 | .name = LPFC_DRIVER_NAME, | 1706 | .name = LPFC_DRIVER_NAME, |
1707 | .owner = THIS_MODULE, | ||
1708 | .id_table = lpfc_id_table, | 1707 | .id_table = lpfc_id_table, |
1709 | .probe = lpfc_pci_probe_one, | 1708 | .probe = lpfc_pci_probe_one, |
1710 | .remove = __devexit_p(lpfc_pci_remove_one), | 1709 | .remove = __devexit_p(lpfc_pci_remove_one), |
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c index 654469778ab5..b0f3cd63e3b9 100644 --- a/drivers/usb/gadget/goku_udc.c +++ b/drivers/usb/gadget/goku_udc.c | |||
@@ -1970,7 +1970,6 @@ MODULE_DEVICE_TABLE (pci, pci_ids); | |||
1970 | static struct pci_driver goku_pci_driver = { | 1970 | static struct pci_driver goku_pci_driver = { |
1971 | .name = (char *) driver_name, | 1971 | .name = (char *) driver_name, |
1972 | .id_table = pci_ids, | 1972 | .id_table = pci_ids, |
1973 | .owner = THIS_MODULE, | ||
1974 | 1973 | ||
1975 | .probe = goku_probe, | 1974 | .probe = goku_probe, |
1976 | .remove = goku_remove, | 1975 | .remove = goku_remove, |
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index 0dc6bb00bf72..c32e1f7476da 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c | |||
@@ -2948,7 +2948,6 @@ MODULE_DEVICE_TABLE (pci, pci_ids); | |||
2948 | static struct pci_driver net2280_pci_driver = { | 2948 | static struct pci_driver net2280_pci_driver = { |
2949 | .name = (char *) driver_name, | 2949 | .name = (char *) driver_name, |
2950 | .id_table = pci_ids, | 2950 | .id_table = pci_ids, |
2951 | .owner = THIS_MODULE, | ||
2952 | 2951 | ||
2953 | .probe = net2280_probe, | 2952 | .probe = net2280_probe, |
2954 | .remove = net2280_remove, | 2953 | .remove = net2280_remove, |
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 145008853966..dfd9bd0b1828 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c | |||
@@ -383,7 +383,6 @@ MODULE_DEVICE_TABLE (pci, pci_ids); | |||
383 | static struct pci_driver ehci_pci_driver = { | 383 | static struct pci_driver ehci_pci_driver = { |
384 | .name = (char *) hcd_name, | 384 | .name = (char *) hcd_name, |
385 | .id_table = pci_ids, | 385 | .id_table = pci_ids, |
386 | .owner = THIS_MODULE, | ||
387 | 386 | ||
388 | .probe = usb_hcd_pci_probe, | 387 | .probe = usb_hcd_pci_probe, |
389 | .remove = usb_hcd_pci_remove, | 388 | .remove = usb_hcd_pci_remove, |
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index 7ce1d9ef0289..a59e536441e1 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c | |||
@@ -218,7 +218,6 @@ MODULE_DEVICE_TABLE (pci, pci_ids); | |||
218 | static struct pci_driver ohci_pci_driver = { | 218 | static struct pci_driver ohci_pci_driver = { |
219 | .name = (char *) hcd_name, | 219 | .name = (char *) hcd_name, |
220 | .id_table = pci_ids, | 220 | .id_table = pci_ids, |
221 | .owner = THIS_MODULE, | ||
222 | 221 | ||
223 | .probe = usb_hcd_pci_probe, | 222 | .probe = usb_hcd_pci_probe, |
224 | .remove = usb_hcd_pci_remove, | 223 | .remove = usb_hcd_pci_remove, |
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 15e0a511069b..d33ce3982a5f 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c | |||
@@ -831,7 +831,6 @@ MODULE_DEVICE_TABLE(pci, uhci_pci_ids); | |||
831 | static struct pci_driver uhci_pci_driver = { | 831 | static struct pci_driver uhci_pci_driver = { |
832 | .name = (char *)hcd_name, | 832 | .name = (char *)hcd_name, |
833 | .id_table = uhci_pci_ids, | 833 | .id_table = uhci_pci_ids, |
834 | .owner = THIS_MODULE, | ||
835 | 834 | ||
836 | .probe = usb_hcd_pci_probe, | 835 | .probe = usb_hcd_pci_probe, |
837 | .remove = usb_hcd_pci_remove, | 836 | .remove = usb_hcd_pci_remove, |
diff --git a/drivers/video/backlight/corgi_bl.c b/drivers/video/backlight/corgi_bl.c index 4867498f68e8..bd9a6996aee7 100644 --- a/drivers/video/backlight/corgi_bl.c +++ b/drivers/video/backlight/corgi_bl.c | |||
@@ -48,6 +48,12 @@ static void corgibl_send_intensity(int intensity) | |||
48 | corgibl_mach_set_intensity(intensity); | 48 | corgibl_mach_set_intensity(intensity); |
49 | 49 | ||
50 | spin_unlock_irqrestore(&bl_lock, flags); | 50 | spin_unlock_irqrestore(&bl_lock, flags); |
51 | |||
52 | corgi_kick_batt = symbol_get(sharpsl_battery_kick); | ||
53 | if (corgi_kick_batt) { | ||
54 | corgi_kick_batt(); | ||
55 | symbol_put(sharpsl_battery_kick); | ||
56 | } | ||
51 | } | 57 | } |
52 | 58 | ||
53 | static void corgibl_blank(int blank) | 59 | static void corgibl_blank(int blank) |
diff --git a/fs/Kconfig b/fs/Kconfig index 7d6ae369ce44..d5255e627b5f 100644 --- a/fs/Kconfig +++ b/fs/Kconfig | |||
@@ -1601,9 +1601,10 @@ config CIFS | |||
1601 | PC operating systems. The CIFS protocol is fully supported by | 1601 | PC operating systems. The CIFS protocol is fully supported by |
1602 | file servers such as Windows 2000 (including Windows 2003, NT 4 | 1602 | file servers such as Windows 2000 (including Windows 2003, NT 4 |
1603 | and Windows XP) as well by Samba (which provides excellent CIFS | 1603 | and Windows XP) as well by Samba (which provides excellent CIFS |
1604 | server support for Linux and many other operating systems). Currently | 1604 | server support for Linux and many other operating systems). Limited |
1605 | you must use the smbfs client filesystem to access older SMB servers | 1605 | support for Windows ME and similar servers is provided as well. |
1606 | such as Windows 9x and OS/2. | 1606 | You must use the smbfs client filesystem to access older SMB servers |
1607 | such as OS/2 and DOS. | ||
1607 | 1608 | ||
1608 | The intent of the cifs module is to provide an advanced | 1609 | The intent of the cifs module is to provide an advanced |
1609 | network file system client for mounting to CIFS compliant servers, | 1610 | network file system client for mounting to CIFS compliant servers, |
@@ -1614,7 +1615,7 @@ config CIFS | |||
1614 | cifs if running only a (Samba) server. It is possible to enable both | 1615 | cifs if running only a (Samba) server. It is possible to enable both |
1615 | smbfs and cifs (e.g. if you are using CIFS for accessing Windows 2003 | 1616 | smbfs and cifs (e.g. if you are using CIFS for accessing Windows 2003 |
1616 | and Samba 3 servers, and smbfs for accessing old servers). If you need | 1617 | and Samba 3 servers, and smbfs for accessing old servers). If you need |
1617 | to mount to Samba or Windows 2003 servers from this machine, say Y. | 1618 | to mount to Samba or Windows from this machine, say Y. |
1618 | 1619 | ||
1619 | config CIFS_STATS | 1620 | config CIFS_STATS |
1620 | bool "CIFS statistics" | 1621 | bool "CIFS statistics" |
@@ -1623,8 +1624,22 @@ config CIFS_STATS | |||
1623 | Enabling this option will cause statistics for each server share | 1624 | Enabling this option will cause statistics for each server share |
1624 | mounted by the cifs client to be displayed in /proc/fs/cifs/Stats | 1625 | mounted by the cifs client to be displayed in /proc/fs/cifs/Stats |
1625 | 1626 | ||
1627 | config CIFS_STATS2 | ||
1628 | bool "CIFS extended statistics" | ||
1629 | depends on CIFS_STATS | ||
1630 | help | ||
1631 | Enabling this option will allow more detailed statistics on SMB | ||
1632 | request timing to be displayed in /proc/fs/cifs/DebugData and also | ||
1633 | allow optional logging of slow responses to dmesg (depending on the | ||
1634 | value of /proc/fs/cifs/cifsFYI, see fs/cifs/README for more details). | ||
1635 | These additional statistics may have a minor effect on performance | ||
1636 | and memory utilization. | ||
1637 | |||
1638 | Unless you are a developer or are doing network performance analysis | ||
1639 | or tuning, say N. | ||
1640 | |||
1626 | config CIFS_XATTR | 1641 | config CIFS_XATTR |
1627 | bool "CIFS extended attributes (EXPERIMENTAL)" | 1642 | bool "CIFS extended attributes" |
1628 | depends on CIFS | 1643 | depends on CIFS |
1629 | help | 1644 | help |
1630 | Extended attributes are name:value pairs associated with inodes by | 1645 | Extended attributes are name:value pairs associated with inodes by |
@@ -1636,11 +1651,11 @@ config CIFS_XATTR | |||
1636 | prefaced by the user namespace prefix. The system namespace | 1651 | prefaced by the user namespace prefix. The system namespace |
1637 | (used by some filesystems to store ACLs) is not supported at | 1652 | (used by some filesystems to store ACLs) is not supported at |
1638 | this time. | 1653 | this time. |
1639 | 1654 | ||
1640 | If unsure, say N. | 1655 | If unsure, say N. |
1641 | 1656 | ||
1642 | config CIFS_POSIX | 1657 | config CIFS_POSIX |
1643 | bool "CIFS POSIX Extensions (EXPERIMENTAL)" | 1658 | bool "CIFS POSIX Extensions" |
1644 | depends on CIFS_XATTR | 1659 | depends on CIFS_XATTR |
1645 | help | 1660 | help |
1646 | Enabling this option will cause the cifs client to attempt to | 1661 | Enabling this option will cause the cifs client to attempt to |
@@ -1653,10 +1668,28 @@ config CIFS_POSIX | |||
1653 | 1668 | ||
1654 | config CIFS_EXPERIMENTAL | 1669 | config CIFS_EXPERIMENTAL |
1655 | bool "CIFS Experimental Features (EXPERIMENTAL)" | 1670 | bool "CIFS Experimental Features (EXPERIMENTAL)" |
1656 | depends on CIFS | 1671 | depends on CIFS && EXPERIMENTAL |
1672 | help | ||
1673 | Enables cifs features under testing. These features are | ||
1674 | experimental and currently include support for writepages | ||
1675 | (multipage writebehind performance improvements) and directory | ||
1676 | change notification ie fcntl(F_DNOTIFY) as well as some security | ||
1677 | improvements. Some also depend on setting at runtime the | ||
1678 | pseudo-file /proc/fs/cifs/Experimental (which is disabled by | ||
1679 | default). See the file fs/cifs/README for more details. | ||
1680 | |||
1681 | If unsure, say N. | ||
1682 | |||
1683 | config CIFS_UPCALL | ||
1684 | bool "CIFS Kerberos/SPNEGO advanced session setup (EXPERIMENTAL)" | ||
1685 | depends on CIFS_EXPERIMENTAL | ||
1686 | select CONNECTOR | ||
1657 | help | 1687 | help |
1658 | Enables cifs features under testing. These features | 1688 | Enables an upcall mechanism for CIFS which will be used to contact |
1659 | are highly experimental. If unsure, say N. | 1689 | userspace helper utilities to provide SPNEGO packaged Kerberos |
1690 | tickets which are needed to mount to certain secure servers | ||
1691 | (for which more secure Kerberos authentication is required). If | ||
1692 | unsure, say N. | ||
1660 | 1693 | ||
1661 | config NCP_FS | 1694 | config NCP_FS |
1662 | tristate "NCP file system support (to mount NetWare volumes)" | 1695 | tristate "NCP file system support (to mount NetWare volumes)" |
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 5bab24f59053..eab3750cf304 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES | |||
@@ -2,7 +2,7 @@ Version 1.39 | |||
2 | ------------ | 2 | ------------ |
3 | Defer close of a file handle slightly if pending writes depend on that file handle | 3 | Defer close of a file handle slightly if pending writes depend on that file handle |
4 | (this reduces the EBADF bad file handle errors that can be logged under heavy | 4 | (this reduces the EBADF bad file handle errors that can be logged under heavy |
5 | stress on writes). | 5 | stress on writes). Modify cifs Kconfig options to expose CONFIG_CIFS_STATS2 |
6 | 6 | ||
7 | Version 1.38 | 7 | Version 1.38 |
8 | ------------ | 8 | ------------ |
diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c index 99a096d3f84d..4e12053f0806 100644 --- a/fs/cifs/cifs_unicode.c +++ b/fs/cifs/cifs_unicode.c | |||
@@ -74,10 +74,11 @@ cifs_strtoUCS(wchar_t * to, const char *from, int len, | |||
74 | cERROR(1, | 74 | cERROR(1, |
75 | ("cifs_strtoUCS: char2uni returned %d", | 75 | ("cifs_strtoUCS: char2uni returned %d", |
76 | charlen)); | 76 | charlen)); |
77 | to[i] = cpu_to_le16(0x003f); /* a question mark */ | 77 | /* A question mark */ |
78 | to[i] = (wchar_t)cpu_to_le16(0x003f); | ||
78 | charlen = 1; | 79 | charlen = 1; |
79 | } else | 80 | } else |
80 | to[i] = cpu_to_le16(to[i]); | 81 | to[i] = (wchar_t)cpu_to_le16(to[i]); |
81 | 82 | ||
82 | } | 83 | } |
83 | 84 | ||
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 877095a1192a..682b0235ad9a 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -405,6 +405,7 @@ static struct quotactl_ops cifs_quotactl_ops = { | |||
405 | }; | 405 | }; |
406 | #endif | 406 | #endif |
407 | 407 | ||
408 | #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
408 | static void cifs_umount_begin(struct super_block * sblock) | 409 | static void cifs_umount_begin(struct super_block * sblock) |
409 | { | 410 | { |
410 | struct cifs_sb_info *cifs_sb; | 411 | struct cifs_sb_info *cifs_sb; |
@@ -422,16 +423,18 @@ static void cifs_umount_begin(struct super_block * sblock) | |||
422 | tcon->tidStatus = CifsExiting; | 423 | tcon->tidStatus = CifsExiting; |
423 | up(&tcon->tconSem); | 424 | up(&tcon->tconSem); |
424 | 425 | ||
426 | /* cancel_brl_requests(tcon); */ | ||
427 | /* cancel_notify_requests(tcon); */ | ||
425 | if(tcon->ses && tcon->ses->server) | 428 | if(tcon->ses && tcon->ses->server) |
426 | { | 429 | { |
427 | cERROR(1,("wake up tasks now - umount begin not complete")); | 430 | cFYI(1,("wake up tasks now - umount begin not complete")); |
428 | wake_up_all(&tcon->ses->server->request_q); | 431 | wake_up_all(&tcon->ses->server->request_q); |
429 | } | 432 | } |
430 | /* BB FIXME - finish add checks for tidStatus BB */ | 433 | /* BB FIXME - finish add checks for tidStatus BB */ |
431 | 434 | ||
432 | return; | 435 | return; |
433 | } | 436 | } |
434 | 437 | #endif | |
435 | 438 | ||
436 | static int cifs_remount(struct super_block *sb, int *flags, char *data) | 439 | static int cifs_remount(struct super_block *sb, int *flags, char *data) |
437 | { | 440 | { |
@@ -450,7 +453,9 @@ struct super_operations cifs_super_ops = { | |||
450 | unless later we add lazy close of inodes or unless the kernel forgets to call | 453 | unless later we add lazy close of inodes or unless the kernel forgets to call |
451 | us with the same number of releases (closes) as opens */ | 454 | us with the same number of releases (closes) as opens */ |
452 | .show_options = cifs_show_options, | 455 | .show_options = cifs_show_options, |
453 | /* .umount_begin = cifs_umount_begin, */ /* BB finish in the future */ | 456 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
457 | .umount_begin = cifs_umount_begin, | ||
458 | #endif | ||
454 | .remount_fs = cifs_remount, | 459 | .remount_fs = cifs_remount, |
455 | }; | 460 | }; |
456 | 461 | ||
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index d301149b1bb0..1b73f4f4c5ce 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -242,11 +242,11 @@ extern int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, | |||
242 | const int netfid, const unsigned int count, | 242 | const int netfid, const unsigned int count, |
243 | const __u64 offset, unsigned int *nbytes, | 243 | const __u64 offset, unsigned int *nbytes, |
244 | struct kvec *iov, const int nvec, const int long_op); | 244 | struct kvec *iov, const int nvec, const int long_op); |
245 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | ||
245 | extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon, | 246 | extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon, |
246 | const unsigned char *searchName, __u64 * inode_number, | 247 | const unsigned char *searchName, __u64 * inode_number, |
247 | const struct nls_table *nls_codepage, | 248 | const struct nls_table *nls_codepage, |
248 | int remap_special_chars); | 249 | int remap_special_chars); |
249 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | ||
250 | extern int cifs_convertUCSpath(char *target, const __le16 *source, int maxlen, | 250 | extern int cifs_convertUCSpath(char *target, const __le16 *source, int maxlen, |
251 | const struct nls_table * codepage); | 251 | const struct nls_table * codepage); |
252 | extern int cifsConvertToUCS(__le16 * target, const char *source, int maxlen, | 252 | extern int cifsConvertToUCS(__le16 * target, const char *source, int maxlen, |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 9312bfc56682..a53c596e1082 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -2959,7 +2959,6 @@ CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle | |||
2959 | return rc; | 2959 | return rc; |
2960 | } | 2960 | } |
2961 | 2961 | ||
2962 | #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
2963 | int | 2962 | int |
2964 | CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon, | 2963 | CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon, |
2965 | const unsigned char *searchName, | 2964 | const unsigned char *searchName, |
@@ -3053,7 +3052,6 @@ GetInodeNumOut: | |||
3053 | goto GetInodeNumberRetry; | 3052 | goto GetInodeNumberRetry; |
3054 | return rc; | 3053 | return rc; |
3055 | } | 3054 | } |
3056 | #endif /* CIFS_EXPERIMENTAL */ | ||
3057 | 3055 | ||
3058 | int | 3056 | int |
3059 | CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses, | 3057 | CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses, |
diff --git a/fs/cifs/cn_cifs.h b/fs/cifs/cn_cifs.h new file mode 100644 index 000000000000..ea59ccac2eb1 --- /dev/null +++ b/fs/cifs/cn_cifs.h | |||
@@ -0,0 +1,37 @@ | |||
1 | /* | ||
2 | * fs/cifs/cn_cifs.h | ||
3 | * | ||
4 | * Copyright (c) International Business Machines Corp., 2002 | ||
5 | * Author(s): Steve French (sfrench@us.ibm.com) | ||
6 | * | ||
7 | * This library is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU Lesser General Public License as published | ||
9 | * by the Free Software Foundation; either version 2.1 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This library is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See | ||
15 | * the GNU Lesser General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU Lesser General Public License | ||
18 | * along with this library; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | |||
22 | #ifndef _CN_CIFS_H | ||
23 | #define _CN_CIFS_H | ||
24 | #ifdef CONFIG_CIFS_UPCALL | ||
25 | #include <linux/types.h> | ||
26 | #include <linux/connector.h> | ||
27 | |||
28 | struct cifs_upcall { | ||
29 | char signature[4]; /* CIFS */ | ||
30 | enum command { | ||
31 | CIFS_GET_IP = 0x00000001, /* get ip address for hostname */ | ||
32 | CIFS_GET_SECBLOB = 0x00000002, /* get SPNEGO wrapped blob */ | ||
33 | } command; | ||
34 | /* union cifs upcall data follows */ | ||
35 | }; | ||
36 | #endif /* CIFS_UPCALL */ | ||
37 | #endif /* _CN_CIFS_H */ | ||
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 450ab75d6546..2cb620716bc1 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #include "ntlmssp.h" | 42 | #include "ntlmssp.h" |
43 | #include "nterr.h" | 43 | #include "nterr.h" |
44 | #include "rfc1002pdu.h" | 44 | #include "rfc1002pdu.h" |
45 | #include "cn_cifs.h" | ||
45 | 46 | ||
46 | #define CIFS_PORT 445 | 47 | #define CIFS_PORT 445 |
47 | #define RFC1001_PORT 139 | 48 | #define RFC1001_PORT 139 |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 912d401600f6..923d071163b2 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -283,7 +283,6 @@ int cifs_get_inode_info(struct inode **pinode, | |||
283 | there Windows server or network appliances for which | 283 | there Windows server or network appliances for which |
284 | IndexNumber field is not guaranteed unique? */ | 284 | IndexNumber field is not guaranteed unique? */ |
285 | 285 | ||
286 | #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
287 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM){ | 286 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM){ |
288 | int rc1 = 0; | 287 | int rc1 = 0; |
289 | __u64 inode_num; | 288 | __u64 inode_num; |
@@ -299,7 +298,6 @@ int cifs_get_inode_info(struct inode **pinode, | |||
299 | } else /* do we need cast or hash to ino? */ | 298 | } else /* do we need cast or hash to ino? */ |
300 | (*pinode)->i_ino = inode_num; | 299 | (*pinode)->i_ino = inode_num; |
301 | } /* else ino incremented to unique num in new_inode*/ | 300 | } /* else ino incremented to unique num in new_inode*/ |
302 | #endif /* CIFS_EXPERIMENTAL */ | ||
303 | insert_inode_hash(*pinode); | 301 | insert_inode_hash(*pinode); |
304 | } | 302 | } |
305 | inode = *pinode; | 303 | inode = *pinode; |
diff --git a/include/asm-arm/arch-ixp4xx/hardware.h b/include/asm-arm/arch-ixp4xx/hardware.h index 55d85eea8c1a..cfb413c845f7 100644 --- a/include/asm-arm/arch-ixp4xx/hardware.h +++ b/include/asm-arm/arch-ixp4xx/hardware.h | |||
@@ -44,5 +44,6 @@ extern unsigned int processor_id; | |||
44 | #include "ixdp425.h" | 44 | #include "ixdp425.h" |
45 | #include "coyote.h" | 45 | #include "coyote.h" |
46 | #include "prpmc1100.h" | 46 | #include "prpmc1100.h" |
47 | #include "nslu2.h" | ||
47 | 48 | ||
48 | #endif /* _ASM_ARCH_HARDWARE_H */ | 49 | #endif /* _ASM_ARCH_HARDWARE_H */ |
diff --git a/include/asm-arm/arch-ixp4xx/irqs.h b/include/asm-arm/arch-ixp4xx/irqs.h index ca808281c7f9..2cf4930372bc 100644 --- a/include/asm-arm/arch-ixp4xx/irqs.h +++ b/include/asm-arm/arch-ixp4xx/irqs.h | |||
@@ -93,4 +93,11 @@ | |||
93 | #define IRQ_COYOTE_PCI_SLOT1 IRQ_IXP4XX_GPIO11 | 93 | #define IRQ_COYOTE_PCI_SLOT1 IRQ_IXP4XX_GPIO11 |
94 | #define IRQ_COYOTE_IDE IRQ_IXP4XX_GPIO5 | 94 | #define IRQ_COYOTE_IDE IRQ_IXP4XX_GPIO5 |
95 | 95 | ||
96 | /* | ||
97 | * NSLU2 board IRQs | ||
98 | */ | ||
99 | #define IRQ_NSLU2_PCI_INTA IRQ_IXP4XX_GPIO11 | ||
100 | #define IRQ_NSLU2_PCI_INTB IRQ_IXP4XX_GPIO10 | ||
101 | #define IRQ_NSLU2_PCI_INTC IRQ_IXP4XX_GPIO9 | ||
102 | |||
96 | #endif | 103 | #endif |
diff --git a/include/asm-arm/arch-ixp4xx/nslu2.h b/include/asm-arm/arch-ixp4xx/nslu2.h new file mode 100644 index 000000000000..b8b347a559c7 --- /dev/null +++ b/include/asm-arm/arch-ixp4xx/nslu2.h | |||
@@ -0,0 +1,96 @@ | |||
1 | /* | ||
2 | * include/asm-arm/arch-ixp4xx/nslu2.h | ||
3 | * | ||
4 | * NSLU2 platform specific definitions | ||
5 | * | ||
6 | * Author: Mark Rakes <mrakes AT mac.com> | ||
7 | * Maintainers: http://www.nslu2-linux.org | ||
8 | * | ||
9 | * based on ixdp425.h: | ||
10 | * Copyright 2004 (c) MontaVista, Software, Inc. | ||
11 | * | ||
12 | * This file is licensed under the terms of the GNU General Public | ||
13 | * License version 2. This program is licensed "as is" without any | ||
14 | * warranty of any kind, whether express or implied. | ||
15 | */ | ||
16 | |||
17 | #ifndef __ASM_ARCH_HARDWARE_H__ | ||
18 | #error "Do not include this directly, instead #include <asm/hardware.h>" | ||
19 | #endif | ||
20 | |||
21 | #define NSLU2_FLASH_BASE IXP4XX_EXP_BUS_CS0_BASE_PHYS | ||
22 | #define NSLU2_FLASH_SIZE IXP4XX_EXP_BUS_CSX_REGION_SIZE | ||
23 | |||
24 | #define NSLU2_SDA_PIN 7 | ||
25 | #define NSLU2_SCL_PIN 6 | ||
26 | |||
27 | /* | ||
28 | * NSLU2 PCI IRQs | ||
29 | */ | ||
30 | #define NSLU2_PCI_MAX_DEV 3 | ||
31 | #define NSLU2_PCI_IRQ_LINES 3 | ||
32 | |||
33 | |||
34 | /* PCI controller GPIO to IRQ pin mappings */ | ||
35 | #define NSLU2_PCI_INTA_PIN 11 | ||
36 | #define NSLU2_PCI_INTB_PIN 10 | ||
37 | #define NSLU2_PCI_INTC_PIN 9 | ||
38 | #define NSLU2_PCI_INTD_PIN 8 | ||
39 | |||
40 | |||
41 | /* NSLU2 Timer */ | ||
42 | #define NSLU2_FREQ 66000000 | ||
43 | #define NSLU2_CLOCK_TICK_RATE (((NSLU2_FREQ / HZ & ~IXP4XX_OST_RELOAD_MASK) + 1) * HZ) | ||
44 | #define NSLU2_CLOCK_TICKS_PER_USEC ((NSLU2_CLOCK_TICK_RATE + USEC_PER_SEC/2) / USEC_PER_SEC) | ||
45 | |||
46 | /* GPIO */ | ||
47 | |||
48 | #define NSLU2_GPIO0 0 | ||
49 | #define NSLU2_GPIO1 1 | ||
50 | #define NSLU2_GPIO2 2 | ||
51 | #define NSLU2_GPIO3 3 | ||
52 | #define NSLU2_GPIO4 4 | ||
53 | #define NSLU2_GPIO5 5 | ||
54 | #define NSLU2_GPIO6 6 | ||
55 | #define NSLU2_GPIO7 7 | ||
56 | #define NSLU2_GPIO8 8 | ||
57 | #define NSLU2_GPIO9 9 | ||
58 | #define NSLU2_GPIO10 10 | ||
59 | #define NSLU2_GPIO11 11 | ||
60 | #define NSLU2_GPIO12 12 | ||
61 | #define NSLU2_GPIO13 13 | ||
62 | #define NSLU2_GPIO14 14 | ||
63 | #define NSLU2_GPIO15 15 | ||
64 | |||
65 | /* Buttons */ | ||
66 | |||
67 | #define NSLU2_PB_GPIO NSLU2_GPIO5 | ||
68 | #define NSLU2_PO_GPIO NSLU2_GPIO8 /* power off */ | ||
69 | #define NSLU2_RB_GPIO NSLU2_GPIO12 | ||
70 | |||
71 | #define NSLU2_PB_IRQ IRQ_IXP4XX_GPIO5 | ||
72 | #define NSLU2_RB_IRQ IRQ_IXP4XX_GPIO12 | ||
73 | |||
74 | #define NSLU2_PB_BM (1L << NSLU2_PB_GPIO) | ||
75 | #define NSLU2_PO_BM (1L << NSLU2_PO_GPIO) | ||
76 | #define NSLU2_RB_BM (1L << NSLU2_RB_GPIO) | ||
77 | |||
78 | /* Buzzer */ | ||
79 | |||
80 | #define NSLU2_GPIO_BUZZ 4 | ||
81 | #define NSLU2_BZ_BM (1L << NSLU2_GPIO_BUZZ) | ||
82 | /* LEDs */ | ||
83 | |||
84 | #define NSLU2_LED_RED NSLU2_GPIO0 | ||
85 | #define NSLU2_LED_GRN NSLU2_GPIO1 | ||
86 | |||
87 | #define NSLU2_LED_RED_BM (1L << NSLU2_LED_RED) | ||
88 | #define NSLU2_LED_GRN_BM (1L << NSLU2_LED_GRN) | ||
89 | |||
90 | #define NSLU2_LED_DISK1 NSLU2_GPIO2 | ||
91 | #define NSLU2_LED_DISK2 NSLU2_GPIO3 | ||
92 | |||
93 | #define NSLU2_LED_DISK1_BM (1L << NSLU2_GPIO2) | ||
94 | #define NSLU2_LED_DISK2_BM (1L << NSLU2_GPIO3) | ||
95 | |||
96 | |||
diff --git a/include/asm-arm/arch-omap/board-h4.h b/include/asm-arm/arch-omap/board-h4.h index d64ee9211eed..33ea29a41654 100644 --- a/include/asm-arm/arch-omap/board-h4.h +++ b/include/asm-arm/arch-omap/board-h4.h | |||
@@ -34,5 +34,11 @@ | |||
34 | #define OMAP24XX_ETHR_START 0x08000300 | 34 | #define OMAP24XX_ETHR_START 0x08000300 |
35 | #define OMAP24XX_ETHR_GPIO_IRQ 92 | 35 | #define OMAP24XX_ETHR_GPIO_IRQ 92 |
36 | 36 | ||
37 | #define H4_CS0_BASE 0x04000000 | ||
38 | |||
39 | #define H4_CS0_BASE 0x04000000 | ||
40 | |||
41 | #define H4_CS0_BASE 0x04000000 | ||
42 | |||
37 | #endif /* __ASM_ARCH_OMAP_H4_H */ | 43 | #endif /* __ASM_ARCH_OMAP_H4_H */ |
38 | 44 | ||
diff --git a/include/asm-arm/arch-omap/board-innovator.h b/include/asm-arm/arch-omap/board-innovator.h index 79574e0ed13d..b3cf33441f6e 100644 --- a/include/asm-arm/arch-omap/board-innovator.h +++ b/include/asm-arm/arch-omap/board-innovator.h | |||
@@ -26,7 +26,7 @@ | |||
26 | #ifndef __ASM_ARCH_OMAP_INNOVATOR_H | 26 | #ifndef __ASM_ARCH_OMAP_INNOVATOR_H |
27 | #define __ASM_ARCH_OMAP_INNOVATOR_H | 27 | #define __ASM_ARCH_OMAP_INNOVATOR_H |
28 | 28 | ||
29 | #if defined (CONFIG_ARCH_OMAP1510) | 29 | #if defined (CONFIG_ARCH_OMAP15XX) |
30 | 30 | ||
31 | #ifndef OMAP_SDRAM_DEVICE | 31 | #ifndef OMAP_SDRAM_DEVICE |
32 | #define OMAP_SDRAM_DEVICE D256M_1X16_4B | 32 | #define OMAP_SDRAM_DEVICE D256M_1X16_4B |
@@ -44,7 +44,7 @@ void fpga_write(unsigned char val, int reg); | |||
44 | unsigned char fpga_read(int reg); | 44 | unsigned char fpga_read(int reg); |
45 | #endif | 45 | #endif |
46 | 46 | ||
47 | #endif /* CONFIG_ARCH_OMAP1510 */ | 47 | #endif /* CONFIG_ARCH_OMAP15XX */ |
48 | 48 | ||
49 | #if defined (CONFIG_ARCH_OMAP16XX) | 49 | #if defined (CONFIG_ARCH_OMAP16XX) |
50 | 50 | ||
diff --git a/include/asm-arm/arch-omap/clock.h b/include/asm-arm/arch-omap/clock.h new file mode 100644 index 000000000000..740c297eb11c --- /dev/null +++ b/include/asm-arm/arch-omap/clock.h | |||
@@ -0,0 +1,91 @@ | |||
1 | /* | ||
2 | * linux/include/asm-arm/arch-omap/clock.h | ||
3 | * | ||
4 | * Copyright (C) 2004 - 2005 Nokia corporation | ||
5 | * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com> | ||
6 | * Based on clocks.h by Tony Lindgren, Gordon McNutt and RidgeRun, Inc | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #ifndef __ARCH_ARM_OMAP_CLOCK_H | ||
14 | #define __ARCH_ARM_OMAP_CLOCK_H | ||
15 | |||
16 | struct module; | ||
17 | |||
18 | struct clk { | ||
19 | struct list_head node; | ||
20 | struct module *owner; | ||
21 | const char *name; | ||
22 | struct clk *parent; | ||
23 | unsigned long rate; | ||
24 | __u32 flags; | ||
25 | void __iomem *enable_reg; | ||
26 | __u8 enable_bit; | ||
27 | __u8 rate_offset; | ||
28 | __u8 src_offset; | ||
29 | __s8 usecount; | ||
30 | void (*recalc)(struct clk *); | ||
31 | int (*set_rate)(struct clk *, unsigned long); | ||
32 | long (*round_rate)(struct clk *, unsigned long); | ||
33 | void (*init)(struct clk *); | ||
34 | int (*enable)(struct clk *); | ||
35 | void (*disable)(struct clk *); | ||
36 | }; | ||
37 | |||
38 | struct clk_functions { | ||
39 | int (*clk_enable)(struct clk *clk); | ||
40 | void (*clk_disable)(struct clk *clk); | ||
41 | int (*clk_use)(struct clk *clk); | ||
42 | void (*clk_unuse)(struct clk *clk); | ||
43 | long (*clk_round_rate)(struct clk *clk, unsigned long rate); | ||
44 | int (*clk_set_rate)(struct clk *clk, unsigned long rate); | ||
45 | int (*clk_set_parent)(struct clk *clk, struct clk *parent); | ||
46 | struct clk * (*clk_get_parent)(struct clk *clk); | ||
47 | void (*clk_allow_idle)(struct clk *clk); | ||
48 | void (*clk_deny_idle)(struct clk *clk); | ||
49 | }; | ||
50 | |||
51 | extern unsigned int mpurate; | ||
52 | extern struct list_head clocks; | ||
53 | extern spinlock_t clockfw_lock; | ||
54 | |||
55 | extern int clk_init(struct clk_functions * custom_clocks); | ||
56 | extern int clk_register(struct clk *clk); | ||
57 | extern void clk_unregister(struct clk *clk); | ||
58 | extern void propagate_rate(struct clk *clk); | ||
59 | extern void followparent_recalc(struct clk * clk); | ||
60 | extern void clk_allow_idle(struct clk *clk); | ||
61 | extern void clk_deny_idle(struct clk *clk); | ||
62 | |||
63 | /* Clock flags */ | ||
64 | #define RATE_CKCTL (1 << 0) /* Main fixed ratio clocks */ | ||
65 | #define RATE_FIXED (1 << 1) /* Fixed clock rate */ | ||
66 | #define RATE_PROPAGATES (1 << 2) /* Program children too */ | ||
67 | #define VIRTUAL_CLOCK (1 << 3) /* Composite clock from table */ | ||
68 | #define ALWAYS_ENABLED (1 << 4) /* Clock cannot be disabled */ | ||
69 | #define ENABLE_REG_32BIT (1 << 5) /* Use 32-bit access */ | ||
70 | #define VIRTUAL_IO_ADDRESS (1 << 6) /* Clock in virtual address */ | ||
71 | #define CLOCK_IDLE_CONTROL (1 << 7) | ||
72 | #define CLOCK_NO_IDLE_PARENT (1 << 8) | ||
73 | #define DELAYED_APP (1 << 9) /* Delay application of clock */ | ||
74 | #define CONFIG_PARTICIPANT (1 << 10) /* Fundamental clock */ | ||
75 | #define CM_MPU_SEL1 (1 << 11) /* Domain divider/source */ | ||
76 | #define CM_DSP_SEL1 (1 << 12) | ||
77 | #define CM_GFX_SEL1 (1 << 13) | ||
78 | #define CM_MODEM_SEL1 (1 << 14) | ||
79 | #define CM_CORE_SEL1 (1 << 15) /* Sets divider for many */ | ||
80 | #define CM_CORE_SEL2 (1 << 16) /* sets parent for GPT */ | ||
81 | #define CM_WKUP_SEL1 (1 << 17) | ||
82 | #define CM_PLL_SEL1 (1 << 18) | ||
83 | #define CM_PLL_SEL2 (1 << 19) | ||
84 | #define CM_SYSCLKOUT_SEL1 (1 << 20) | ||
85 | #define CLOCK_IN_OMAP730 (1 << 21) | ||
86 | #define CLOCK_IN_OMAP1510 (1 << 22) | ||
87 | #define CLOCK_IN_OMAP16XX (1 << 23) | ||
88 | #define CLOCK_IN_OMAP242X (1 << 24) | ||
89 | #define CLOCK_IN_OMAP243X (1 << 25) | ||
90 | |||
91 | #endif | ||
diff --git a/include/asm-arm/arch-omap/common.h b/include/asm-arm/arch-omap/common.h index 2a676b4f13b5..08d58abd8218 100644 --- a/include/asm-arm/arch-omap/common.h +++ b/include/asm-arm/arch-omap/common.h | |||
@@ -31,6 +31,6 @@ struct sys_timer; | |||
31 | 31 | ||
32 | extern void omap_map_common_io(void); | 32 | extern void omap_map_common_io(void); |
33 | extern struct sys_timer omap_timer; | 33 | extern struct sys_timer omap_timer; |
34 | extern void omap_serial_init(int ports[]); | 34 | extern void omap_serial_init(void); |
35 | 35 | ||
36 | #endif /* __ARCH_ARM_MACH_OMAP_COMMON_H */ | 36 | #endif /* __ARCH_ARM_MACH_OMAP_COMMON_H */ |
diff --git a/include/asm-arm/arch-omap/cpu.h b/include/asm-arm/arch-omap/cpu.h index 1119e2b53e72..ec7eb675d922 100644 --- a/include/asm-arm/arch-omap/cpu.h +++ b/include/asm-arm/arch-omap/cpu.h | |||
@@ -28,12 +28,7 @@ | |||
28 | 28 | ||
29 | extern unsigned int system_rev; | 29 | extern unsigned int system_rev; |
30 | 30 | ||
31 | #define OMAP_DIE_ID_0 0xfffe1800 | 31 | #define omap2_cpu_rev() ((system_rev >> 8) & 0x0f) |
32 | #define OMAP_DIE_ID_1 0xfffe1804 | ||
33 | #define OMAP_PRODUCTION_ID_0 0xfffe2000 | ||
34 | #define OMAP_PRODUCTION_ID_1 0xfffe2004 | ||
35 | #define OMAP32_ID_0 0xfffed400 | ||
36 | #define OMAP32_ID_1 0xfffed404 | ||
37 | 32 | ||
38 | /* | 33 | /* |
39 | * Test if multicore OMAP support is needed | 34 | * Test if multicore OMAP support is needed |
@@ -50,7 +45,7 @@ extern unsigned int system_rev; | |||
50 | # define OMAP_NAME omap730 | 45 | # define OMAP_NAME omap730 |
51 | # endif | 46 | # endif |
52 | #endif | 47 | #endif |
53 | #ifdef CONFIG_ARCH_OMAP1510 | 48 | #ifdef CONFIG_ARCH_OMAP15XX |
54 | # ifdef OMAP_NAME | 49 | # ifdef OMAP_NAME |
55 | # undef MULTI_OMAP1 | 50 | # undef MULTI_OMAP1 |
56 | # define MULTI_OMAP1 | 51 | # define MULTI_OMAP1 |
@@ -79,9 +74,11 @@ extern unsigned int system_rev; | |||
79 | * Macros to group OMAP into cpu classes. | 74 | * Macros to group OMAP into cpu classes. |
80 | * These can be used in most places. | 75 | * These can be used in most places. |
81 | * cpu_is_omap7xx(): True for OMAP730 | 76 | * cpu_is_omap7xx(): True for OMAP730 |
82 | * cpu_is_omap15xx(): True for OMAP1510 and OMAP5910 | 77 | * cpu_is_omap15xx(): True for OMAP1510, OMAP5910 and OMAP310 |
83 | * cpu_is_omap16xx(): True for OMAP1610, OMAP5912 and OMAP1710 | 78 | * cpu_is_omap16xx(): True for OMAP1610, OMAP5912 and OMAP1710 |
84 | * cpu_is_omap24xx(): True for OMAP2420 | 79 | * cpu_is_omap24xx(): True for OMAP2420, OMAP2422, OMAP2423, OMAP2430 |
80 | * cpu_is_omap242x(): True for OMAP2420, OMAP2422, OMAP2423 | ||
81 | * cpu_is_omap243x(): True for OMAP2430 | ||
85 | */ | 82 | */ |
86 | #define GET_OMAP_CLASS (system_rev & 0xff) | 83 | #define GET_OMAP_CLASS (system_rev & 0xff) |
87 | 84 | ||
@@ -91,22 +88,35 @@ static inline int is_omap ##class (void) \ | |||
91 | return (GET_OMAP_CLASS == (id)) ? 1 : 0; \ | 88 | return (GET_OMAP_CLASS == (id)) ? 1 : 0; \ |
92 | } | 89 | } |
93 | 90 | ||
91 | #define GET_OMAP_SUBCLASS ((system_rev >> 20) & 0x0fff) | ||
92 | |||
93 | #define IS_OMAP_SUBCLASS(subclass, id) \ | ||
94 | static inline int is_omap ##subclass (void) \ | ||
95 | { \ | ||
96 | return (GET_OMAP_SUBCLASS == (id)) ? 1 : 0; \ | ||
97 | } | ||
98 | |||
94 | IS_OMAP_CLASS(7xx, 0x07) | 99 | IS_OMAP_CLASS(7xx, 0x07) |
95 | IS_OMAP_CLASS(15xx, 0x15) | 100 | IS_OMAP_CLASS(15xx, 0x15) |
96 | IS_OMAP_CLASS(16xx, 0x16) | 101 | IS_OMAP_CLASS(16xx, 0x16) |
97 | IS_OMAP_CLASS(24xx, 0x24) | 102 | IS_OMAP_CLASS(24xx, 0x24) |
98 | 103 | ||
104 | IS_OMAP_SUBCLASS(242x, 0x242) | ||
105 | IS_OMAP_SUBCLASS(243x, 0x243) | ||
106 | |||
99 | #define cpu_is_omap7xx() 0 | 107 | #define cpu_is_omap7xx() 0 |
100 | #define cpu_is_omap15xx() 0 | 108 | #define cpu_is_omap15xx() 0 |
101 | #define cpu_is_omap16xx() 0 | 109 | #define cpu_is_omap16xx() 0 |
102 | #define cpu_is_omap24xx() 0 | 110 | #define cpu_is_omap24xx() 0 |
111 | #define cpu_is_omap242x() 0 | ||
112 | #define cpu_is_omap243x() 0 | ||
103 | 113 | ||
104 | #if defined(MULTI_OMAP1) | 114 | #if defined(MULTI_OMAP1) |
105 | # if defined(CONFIG_ARCH_OMAP730) | 115 | # if defined(CONFIG_ARCH_OMAP730) |
106 | # undef cpu_is_omap7xx | 116 | # undef cpu_is_omap7xx |
107 | # define cpu_is_omap7xx() is_omap7xx() | 117 | # define cpu_is_omap7xx() is_omap7xx() |
108 | # endif | 118 | # endif |
109 | # if defined(CONFIG_ARCH_OMAP1510) | 119 | # if defined(CONFIG_ARCH_OMAP15XX) |
110 | # undef cpu_is_omap15xx | 120 | # undef cpu_is_omap15xx |
111 | # define cpu_is_omap15xx() is_omap15xx() | 121 | # define cpu_is_omap15xx() is_omap15xx() |
112 | # endif | 122 | # endif |
@@ -119,7 +129,7 @@ IS_OMAP_CLASS(24xx, 0x24) | |||
119 | # undef cpu_is_omap7xx | 129 | # undef cpu_is_omap7xx |
120 | # define cpu_is_omap7xx() 1 | 130 | # define cpu_is_omap7xx() 1 |
121 | # endif | 131 | # endif |
122 | # if defined(CONFIG_ARCH_OMAP1510) | 132 | # if defined(CONFIG_ARCH_OMAP15XX) |
123 | # undef cpu_is_omap15xx | 133 | # undef cpu_is_omap15xx |
124 | # define cpu_is_omap15xx() 1 | 134 | # define cpu_is_omap15xx() 1 |
125 | # endif | 135 | # endif |
@@ -129,13 +139,18 @@ IS_OMAP_CLASS(24xx, 0x24) | |||
129 | # endif | 139 | # endif |
130 | # if defined(CONFIG_ARCH_OMAP24XX) | 140 | # if defined(CONFIG_ARCH_OMAP24XX) |
131 | # undef cpu_is_omap24xx | 141 | # undef cpu_is_omap24xx |
142 | # undef cpu_is_omap242x | ||
143 | # undef cpu_is_omap243x | ||
132 | # define cpu_is_omap24xx() 1 | 144 | # define cpu_is_omap24xx() 1 |
145 | # define cpu_is_omap242x() is_omap242x() | ||
146 | # define cpu_is_omap243x() is_omap243x() | ||
133 | # endif | 147 | # endif |
134 | #endif | 148 | #endif |
135 | 149 | ||
136 | /* | 150 | /* |
137 | * Macros to detect individual cpu types. | 151 | * Macros to detect individual cpu types. |
138 | * These are only rarely needed. | 152 | * These are only rarely needed. |
153 | * cpu_is_omap330(): True for OMAP330 | ||
139 | * cpu_is_omap730(): True for OMAP730 | 154 | * cpu_is_omap730(): True for OMAP730 |
140 | * cpu_is_omap1510(): True for OMAP1510 | 155 | * cpu_is_omap1510(): True for OMAP1510 |
141 | * cpu_is_omap1610(): True for OMAP1610 | 156 | * cpu_is_omap1610(): True for OMAP1610 |
@@ -144,6 +159,9 @@ IS_OMAP_CLASS(24xx, 0x24) | |||
144 | * cpu_is_omap1621(): True for OMAP1621 | 159 | * cpu_is_omap1621(): True for OMAP1621 |
145 | * cpu_is_omap1710(): True for OMAP1710 | 160 | * cpu_is_omap1710(): True for OMAP1710 |
146 | * cpu_is_omap2420(): True for OMAP2420 | 161 | * cpu_is_omap2420(): True for OMAP2420 |
162 | * cpu_is_omap2422(): True for OMAP2422 | ||
163 | * cpu_is_omap2423(): True for OMAP2423 | ||
164 | * cpu_is_omap2430(): True for OMAP2430 | ||
147 | */ | 165 | */ |
148 | #define GET_OMAP_TYPE ((system_rev >> 16) & 0xffff) | 166 | #define GET_OMAP_TYPE ((system_rev >> 16) & 0xffff) |
149 | 167 | ||
@@ -153,6 +171,7 @@ static inline int is_omap ##type (void) \ | |||
153 | return (GET_OMAP_TYPE == (id)) ? 1 : 0; \ | 171 | return (GET_OMAP_TYPE == (id)) ? 1 : 0; \ |
154 | } | 172 | } |
155 | 173 | ||
174 | IS_OMAP_TYPE(310, 0x0310) | ||
156 | IS_OMAP_TYPE(730, 0x0730) | 175 | IS_OMAP_TYPE(730, 0x0730) |
157 | IS_OMAP_TYPE(1510, 0x1510) | 176 | IS_OMAP_TYPE(1510, 0x1510) |
158 | IS_OMAP_TYPE(1610, 0x1610) | 177 | IS_OMAP_TYPE(1610, 0x1610) |
@@ -161,7 +180,11 @@ IS_OMAP_TYPE(5912, 0x1611) | |||
161 | IS_OMAP_TYPE(1621, 0x1621) | 180 | IS_OMAP_TYPE(1621, 0x1621) |
162 | IS_OMAP_TYPE(1710, 0x1710) | 181 | IS_OMAP_TYPE(1710, 0x1710) |
163 | IS_OMAP_TYPE(2420, 0x2420) | 182 | IS_OMAP_TYPE(2420, 0x2420) |
183 | IS_OMAP_TYPE(2422, 0x2422) | ||
184 | IS_OMAP_TYPE(2423, 0x2423) | ||
185 | IS_OMAP_TYPE(2430, 0x2430) | ||
164 | 186 | ||
187 | #define cpu_is_omap310() 0 | ||
165 | #define cpu_is_omap730() 0 | 188 | #define cpu_is_omap730() 0 |
166 | #define cpu_is_omap1510() 0 | 189 | #define cpu_is_omap1510() 0 |
167 | #define cpu_is_omap1610() 0 | 190 | #define cpu_is_omap1610() 0 |
@@ -170,31 +193,33 @@ IS_OMAP_TYPE(2420, 0x2420) | |||
170 | #define cpu_is_omap1621() 0 | 193 | #define cpu_is_omap1621() 0 |
171 | #define cpu_is_omap1710() 0 | 194 | #define cpu_is_omap1710() 0 |
172 | #define cpu_is_omap2420() 0 | 195 | #define cpu_is_omap2420() 0 |
196 | #define cpu_is_omap2422() 0 | ||
197 | #define cpu_is_omap2423() 0 | ||
198 | #define cpu_is_omap2430() 0 | ||
173 | 199 | ||
174 | #if defined(MULTI_OMAP1) | 200 | #if defined(MULTI_OMAP1) |
175 | # if defined(CONFIG_ARCH_OMAP730) | 201 | # if defined(CONFIG_ARCH_OMAP730) |
176 | # undef cpu_is_omap730 | 202 | # undef cpu_is_omap730 |
177 | # define cpu_is_omap730() is_omap730() | 203 | # define cpu_is_omap730() is_omap730() |
178 | # endif | 204 | # endif |
179 | # if defined(CONFIG_ARCH_OMAP1510) | ||
180 | # undef cpu_is_omap1510 | ||
181 | # define cpu_is_omap1510() is_omap1510() | ||
182 | # endif | ||
183 | #else | 205 | #else |
184 | # if defined(CONFIG_ARCH_OMAP730) | 206 | # if defined(CONFIG_ARCH_OMAP730) |
185 | # undef cpu_is_omap730 | 207 | # undef cpu_is_omap730 |
186 | # define cpu_is_omap730() 1 | 208 | # define cpu_is_omap730() 1 |
187 | # endif | 209 | # endif |
188 | # if defined(CONFIG_ARCH_OMAP1510) | ||
189 | # undef cpu_is_omap1510 | ||
190 | # define cpu_is_omap1510() 1 | ||
191 | # endif | ||
192 | #endif | 210 | #endif |
193 | 211 | ||
194 | /* | 212 | /* |
195 | * Whether we have MULTI_OMAP1 or not, we still need to distinguish | 213 | * Whether we have MULTI_OMAP1 or not, we still need to distinguish |
196 | * between 1611B/5912 and 1710. | 214 | * between 330 vs. 1510 and 1611B/5912 vs. 1710. |
197 | */ | 215 | */ |
216 | #if defined(CONFIG_ARCH_OMAP15XX) | ||
217 | # undef cpu_is_omap310 | ||
218 | # undef cpu_is_omap1510 | ||
219 | # define cpu_is_omap310() is_omap310() | ||
220 | # define cpu_is_omap1510() is_omap1510() | ||
221 | #endif | ||
222 | |||
198 | #if defined(CONFIG_ARCH_OMAP16XX) | 223 | #if defined(CONFIG_ARCH_OMAP16XX) |
199 | # undef cpu_is_omap1610 | 224 | # undef cpu_is_omap1610 |
200 | # undef cpu_is_omap1611 | 225 | # undef cpu_is_omap1611 |
@@ -208,9 +233,20 @@ IS_OMAP_TYPE(2420, 0x2420) | |||
208 | # define cpu_is_omap1710() is_omap1710() | 233 | # define cpu_is_omap1710() is_omap1710() |
209 | #endif | 234 | #endif |
210 | 235 | ||
211 | #if defined(CONFIG_ARCH_OMAP2420) | 236 | #if defined(CONFIG_ARCH_OMAP24XX) |
212 | # undef cpu_is_omap2420 | 237 | # undef cpu_is_omap2420 |
213 | # define cpu_is_omap2420() 1 | 238 | # undef cpu_is_omap2422 |
239 | # undef cpu_is_omap2423 | ||
240 | # undef cpu_is_omap2430 | ||
241 | # define cpu_is_omap2420() is_omap2420() | ||
242 | # define cpu_is_omap2422() is_omap2422() | ||
243 | # define cpu_is_omap2423() is_omap2423() | ||
244 | # define cpu_is_omap2430() is_omap2430() | ||
214 | #endif | 245 | #endif |
215 | 246 | ||
247 | /* Macros to detect if we have OMAP1 or OMAP2 */ | ||
248 | #define cpu_class_is_omap1() (cpu_is_omap730() || cpu_is_omap15xx() || \ | ||
249 | cpu_is_omap16xx()) | ||
250 | #define cpu_class_is_omap2() cpu_is_omap24xx() | ||
251 | |||
216 | #endif | 252 | #endif |
diff --git a/include/asm-arm/arch-omap/dma.h b/include/asm-arm/arch-omap/dma.h index 04ebef5c6e95..ccbcb580a5c1 100644 --- a/include/asm-arm/arch-omap/dma.h +++ b/include/asm-arm/arch-omap/dma.h | |||
@@ -22,9 +22,109 @@ | |||
22 | #define __ASM_ARCH_DMA_H | 22 | #define __ASM_ARCH_DMA_H |
23 | 23 | ||
24 | #define MAX_DMA_ADDRESS 0xffffffff | 24 | #define MAX_DMA_ADDRESS 0xffffffff |
25 | #define MAX_DMA_CHANNELS 0 | ||
26 | |||
27 | /* Hardware registers for omap1 */ | ||
28 | #define OMAP_DMA_BASE (0xfffed800) | ||
29 | #define OMAP_DMA_GCR (OMAP_DMA_BASE + 0x400) | ||
30 | #define OMAP_DMA_GSCR (OMAP_DMA_BASE + 0x404) | ||
31 | #define OMAP_DMA_GRST (OMAP_DMA_BASE + 0x408) | ||
32 | #define OMAP_DMA_HW_ID (OMAP_DMA_BASE + 0x442) | ||
33 | #define OMAP_DMA_PCH2_ID (OMAP_DMA_BASE + 0x444) | ||
34 | #define OMAP_DMA_PCH0_ID (OMAP_DMA_BASE + 0x446) | ||
35 | #define OMAP_DMA_PCH1_ID (OMAP_DMA_BASE + 0x448) | ||
36 | #define OMAP_DMA_PCHG_ID (OMAP_DMA_BASE + 0x44a) | ||
37 | #define OMAP_DMA_PCHD_ID (OMAP_DMA_BASE + 0x44c) | ||
38 | #define OMAP_DMA_CAPS_0_U (OMAP_DMA_BASE + 0x44e) | ||
39 | #define OMAP_DMA_CAPS_0_L (OMAP_DMA_BASE + 0x450) | ||
40 | #define OMAP_DMA_CAPS_1_U (OMAP_DMA_BASE + 0x452) | ||
41 | #define OMAP_DMA_CAPS_1_L (OMAP_DMA_BASE + 0x454) | ||
42 | #define OMAP_DMA_CAPS_2 (OMAP_DMA_BASE + 0x456) | ||
43 | #define OMAP_DMA_CAPS_3 (OMAP_DMA_BASE + 0x458) | ||
44 | #define OMAP_DMA_CAPS_4 (OMAP_DMA_BASE + 0x45a) | ||
45 | #define OMAP_DMA_PCH2_SR (OMAP_DMA_BASE + 0x460) | ||
46 | #define OMAP_DMA_PCH0_SR (OMAP_DMA_BASE + 0x480) | ||
47 | #define OMAP_DMA_PCH1_SR (OMAP_DMA_BASE + 0x482) | ||
48 | #define OMAP_DMA_PCHD_SR (OMAP_DMA_BASE + 0x4c0) | ||
49 | |||
50 | /* Hardware registers for omap2 */ | ||
51 | #define OMAP24XX_DMA_BASE (L4_24XX_BASE + 0x56000) | ||
52 | #define OMAP_DMA4_REVISION (OMAP24XX_DMA_BASE + 0x00) | ||
53 | #define OMAP_DMA4_GCR_REG (OMAP24XX_DMA_BASE + 0x78) | ||
54 | #define OMAP_DMA4_IRQSTATUS_L0 (OMAP24XX_DMA_BASE + 0x08) | ||
55 | #define OMAP_DMA4_IRQSTATUS_L1 (OMAP24XX_DMA_BASE + 0x0c) | ||
56 | #define OMAP_DMA4_IRQSTATUS_L2 (OMAP24XX_DMA_BASE + 0x10) | ||
57 | #define OMAP_DMA4_IRQSTATUS_L3 (OMAP24XX_DMA_BASE + 0x14) | ||
58 | #define OMAP_DMA4_IRQENABLE_L0 (OMAP24XX_DMA_BASE + 0x18) | ||
59 | #define OMAP_DMA4_IRQENABLE_L1 (OMAP24XX_DMA_BASE + 0x1c) | ||
60 | #define OMAP_DMA4_IRQENABLE_L2 (OMAP24XX_DMA_BASE + 0x20) | ||
61 | #define OMAP_DMA4_IRQENABLE_L3 (OMAP24XX_DMA_BASE + 0x24) | ||
62 | #define OMAP_DMA4_SYSSTATUS (OMAP24XX_DMA_BASE + 0x28) | ||
63 | #define OMAP_DMA4_CAPS_0 (OMAP24XX_DMA_BASE + 0x64) | ||
64 | #define OMAP_DMA4_CAPS_2 (OMAP24XX_DMA_BASE + 0x6c) | ||
65 | #define OMAP_DMA4_CAPS_3 (OMAP24XX_DMA_BASE + 0x70) | ||
66 | #define OMAP_DMA4_CAPS_4 (OMAP24XX_DMA_BASE + 0x74) | ||
67 | |||
68 | #ifdef CONFIG_ARCH_OMAP1 | ||
25 | 69 | ||
26 | #define OMAP_LOGICAL_DMA_CH_COUNT 17 | 70 | #define OMAP_LOGICAL_DMA_CH_COUNT 17 |
27 | 71 | ||
72 | /* Common channel specific registers for omap1 */ | ||
73 | #define OMAP_DMA_CSDP_REG(n) __REG16(OMAP_DMA_BASE + 0x40 * (n) + 0x00) | ||
74 | #define OMAP_DMA_CCR_REG(n) __REG16(OMAP_DMA_BASE + 0x40 * (n) + 0x02) | ||
75 | #define OMAP_DMA_CICR_REG(n) __REG16(OMAP_DMA_BASE + 0x40 * (n) + 0x04) | ||
76 | #define OMAP_DMA_CSR_REG(n) __REG16(OMAP_DMA_BASE + 0x40 * (n) + 0x06) | ||
77 | #define OMAP_DMA_CEN_REG(n) __REG16(OMAP_DMA_BASE + 0x40 * (n) + 0x10) | ||
78 | #define OMAP_DMA_CFN_REG(n) __REG16(OMAP_DMA_BASE + 0x40 * (n) + 0x12) | ||
79 | #define OMAP_DMA_CSFI_REG(n) __REG16(OMAP_DMA_BASE + 0x40 * (n) + 0x14) | ||
80 | #define OMAP_DMA_CSEI_REG(n) __REG16(OMAP_DMA_BASE + 0x40 * (n) + 0x16) | ||
81 | #define OMAP_DMA_CSAC_REG(n) __REG16(OMAP_DMA_BASE + 0x40 * (n) + 0x18) | ||
82 | #define OMAP_DMA_CDAC_REG(n) __REG16(OMAP_DMA_BASE + 0x40 * (n) + 0x1a) | ||
83 | #define OMAP_DMA_CDEI_REG(n) __REG16(OMAP_DMA_BASE + 0x40 * (n) + 0x1c) | ||
84 | #define OMAP_DMA_CDFI_REG(n) __REG16(OMAP_DMA_BASE + 0x40 * (n) + 0x1e) | ||
85 | #define OMAP_DMA_CLNK_CTRL_REG(n) __REG16(OMAP_DMA_BASE + 0x40 * (n) + 0x28) | ||
86 | |||
87 | #else | ||
88 | |||
89 | #define OMAP_LOGICAL_DMA_CH_COUNT 32 /* REVISIT: Is this 32 + 2? */ | ||
90 | |||
91 | /* Common channel specific registers for omap2 */ | ||
92 | #define OMAP_DMA_CCR_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0x80) | ||
93 | #define OMAP_DMA_CLNK_CTRL_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0x84) | ||
94 | #define OMAP_DMA_CICR_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0x88) | ||
95 | #define OMAP_DMA_CSR_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0x8c) | ||
96 | #define OMAP_DMA_CSDP_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0x90) | ||
97 | #define OMAP_DMA_CEN_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0x94) | ||
98 | #define OMAP_DMA_CFN_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0x98) | ||
99 | #define OMAP_DMA_CSEI_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0xa4) | ||
100 | #define OMAP_DMA_CSFI_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0xa8) | ||
101 | #define OMAP_DMA_CDEI_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0xac) | ||
102 | #define OMAP_DMA_CDFI_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0xb0) | ||
103 | #define OMAP_DMA_CSAC_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0xb4) | ||
104 | #define OMAP_DMA_CDAC_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0xb8) | ||
105 | |||
106 | #endif | ||
107 | |||
108 | /* Channel specific registers only on omap1 */ | ||
109 | #define OMAP1_DMA_CSSA_L_REG(n) __REG16(OMAP_DMA_BASE + 0x40 * (n) + 0x08) | ||
110 | #define OMAP1_DMA_CSSA_U_REG(n) __REG16(OMAP_DMA_BASE + 0x40 * (n) + 0x0a) | ||
111 | #define OMAP1_DMA_CDSA_L_REG(n) __REG16(OMAP_DMA_BASE + 0x40 * (n) + 0x0c) | ||
112 | #define OMAP1_DMA_CDSA_U_REG(n) __REG16(OMAP_DMA_BASE + 0x40 * (n) + 0x0e) | ||
113 | #define OMAP1_DMA_COLOR_L_REG(n) __REG16(OMAP_DMA_BASE + 0x40 * (n) + 0x20) | ||
114 | #define OMAP1_DMA_CCR2_REG(n) __REG16(OMAP_DMA_BASE + 0x40 * (n) + 0x24) | ||
115 | #define OMAP1_DMA_COLOR_U_REG(n) __REG16(OMAP_DMA_BASE + 0x40 * (n) + 0x22) | ||
116 | #define OMAP1_DMA_LCH_CTRL_REG(n) __REG16(OMAP_DMA_BASE + 0x40 * (n) + 0x2a) | ||
117 | |||
118 | /* Channel specific registers only on omap2 */ | ||
119 | #define OMAP2_DMA_CSSA_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0x9c) | ||
120 | #define OMAP2_DMA_CDSA_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0xa0) | ||
121 | #define OMAP2_DMA_CCEN_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0xbc) | ||
122 | #define OMAP2_DMA_CCFN_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0xc0) | ||
123 | #define OMAP2_DMA_COLOR_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0xc4) | ||
124 | |||
125 | /*----------------------------------------------------------------------------*/ | ||
126 | |||
127 | /* DMA channels for omap1 */ | ||
28 | #define OMAP_DMA_NO_DEVICE 0 | 128 | #define OMAP_DMA_NO_DEVICE 0 |
29 | #define OMAP_DMA_MCSI1_TX 1 | 129 | #define OMAP_DMA_MCSI1_TX 1 |
30 | #define OMAP_DMA_MCSI1_RX 2 | 130 | #define OMAP_DMA_MCSI1_RX 2 |
@@ -85,29 +185,72 @@ | |||
85 | #define OMAP_DMA_MMC2_RX 55 | 185 | #define OMAP_DMA_MMC2_RX 55 |
86 | #define OMAP_DMA_CRYPTO_DES_OUT 56 | 186 | #define OMAP_DMA_CRYPTO_DES_OUT 56 |
87 | 187 | ||
188 | /* DMA channels for 24xx */ | ||
189 | #define OMAP24XX_DMA_NO_DEVICE 0 | ||
190 | #define OMAP24XX_DMA_XTI_DMA 1 /* S_DMA_0 */ | ||
191 | #define OMAP24XX_DMA_EXT_NDMA_REQ0 2 /* S_DMA_1 */ | ||
192 | #define OMAP24XX_DMA_EXT_NDMA_REQ1 3 /* S_DMA_2 */ | ||
193 | #define OMAP24XX_DMA_GPMC 4 /* S_DMA_3 */ | ||
194 | #define OMAP24XX_DMA_GFX 5 /* S_DMA_4 */ | ||
195 | #define OMAP24XX_DMA_DSS 6 /* S_DMA_5 */ | ||
196 | #define OMAP24XX_DMA_VLYNQ_TX 7 /* S_DMA_6 */ | ||
197 | #define OMAP24XX_DMA_CWT 8 /* S_DMA_7 */ | ||
198 | #define OMAP24XX_DMA_AES_TX 9 /* S_DMA_8 */ | ||
199 | #define OMAP24XX_DMA_AES_RX 10 /* S_DMA_9 */ | ||
200 | #define OMAP24XX_DMA_DES_TX 11 /* S_DMA_10 */ | ||
201 | #define OMAP24XX_DMA_DES_RX 12 /* S_DMA_11 */ | ||
202 | #define OMAP24XX_DMA_SHA1MD5_RX 13 /* S_DMA_12 */ | ||
88 | 203 | ||
89 | #define OMAP_DMA_BASE (0xfffed800) | 204 | #define OMAP24XX_DMA_EAC_AC_RD 17 /* S_DMA_16 */ |
90 | #define OMAP_DMA_GCR (OMAP_DMA_BASE + 0x400) | 205 | #define OMAP24XX_DMA_EAC_AC_WR 18 /* S_DMA_17 */ |
91 | #define OMAP_DMA_GSCR (OMAP_DMA_BASE + 0x404) | 206 | #define OMAP24XX_DMA_EAC_MD_UL_RD 19 /* S_DMA_18 */ |
92 | #define OMAP_DMA_GRST (OMAP_DMA_BASE + 0x408) | 207 | #define OMAP24XX_DMA_EAC_MD_UL_WR 20 /* S_DMA_19 */ |
93 | #define OMAP_DMA_HW_ID (OMAP_DMA_BASE + 0x442) | 208 | #define OMAP24XX_DMA_EAC_MD_DL_RD 21 /* S_DMA_20 */ |
94 | #define OMAP_DMA_PCH2_ID (OMAP_DMA_BASE + 0x444) | 209 | #define OMAP24XX_DMA_EAC_MD_DL_WR 22 /* S_DMA_21 */ |
95 | #define OMAP_DMA_PCH0_ID (OMAP_DMA_BASE + 0x446) | 210 | #define OMAP24XX_DMA_EAC_BT_UL_RD 23 /* S_DMA_22 */ |
96 | #define OMAP_DMA_PCH1_ID (OMAP_DMA_BASE + 0x448) | 211 | #define OMAP24XX_DMA_EAC_BT_UL_WR 24 /* S_DMA_23 */ |
97 | #define OMAP_DMA_PCHG_ID (OMAP_DMA_BASE + 0x44a) | 212 | #define OMAP24XX_DMA_EAC_BT_DL_RD 25 /* S_DMA_24 */ |
98 | #define OMAP_DMA_PCHD_ID (OMAP_DMA_BASE + 0x44c) | 213 | #define OMAP24XX_DMA_EAC_BT_DL_WR 26 /* S_DMA_25 */ |
99 | #define OMAP_DMA_CAPS_0_U (OMAP_DMA_BASE + 0x44e) | 214 | #define OMAP24XX_DMA_I2C1_TX 27 /* S_DMA_26 */ |
100 | #define OMAP_DMA_CAPS_0_L (OMAP_DMA_BASE + 0x450) | 215 | #define OMAP24XX_DMA_I2C1_RX 28 /* S_DMA_27 */ |
101 | #define OMAP_DMA_CAPS_1_U (OMAP_DMA_BASE + 0x452) | 216 | #define OMAP24XX_DMA_I2C2_TX 29 /* S_DMA_28 */ |
102 | #define OMAP_DMA_CAPS_1_L (OMAP_DMA_BASE + 0x454) | 217 | #define OMAP24XX_DMA_I2C2_RX 30 /* S_DMA_29 */ |
103 | #define OMAP_DMA_CAPS_2 (OMAP_DMA_BASE + 0x456) | 218 | #define OMAP24XX_DMA_MCBSP1_TX 31 /* SDMA_30 */ |
104 | #define OMAP_DMA_CAPS_3 (OMAP_DMA_BASE + 0x458) | 219 | #define OMAP24XX_DMA_MCBSP1_RX 32 /* SDMA_31 */ |
105 | #define OMAP_DMA_CAPS_4 (OMAP_DMA_BASE + 0x45a) | 220 | #define OMAP24XX_DMA_MCBSP2_TX 33 /* SDMA_32 */ |
106 | #define OMAP_DMA_PCH2_SR (OMAP_DMA_BASE + 0x460) | 221 | #define OMAP24XX_DMA_MCBSP2_RX 34 /* SDMA_33 */ |
107 | #define OMAP_DMA_PCH0_SR (OMAP_DMA_BASE + 0x480) | 222 | #define OMAP24XX_DMA_SPI1_TX0 35 /* SDMA_34 */ |
108 | #define OMAP_DMA_PCH1_SR (OMAP_DMA_BASE + 0x482) | 223 | #define OMAP24XX_DMA_SPI1_RX0 36 /* SDMA_35 */ |
109 | #define OMAP_DMA_PCHD_SR (OMAP_DMA_BASE + 0x4c0) | 224 | #define OMAP24XX_DMA_SPI1_TX1 37 /* SDMA_36 */ |
225 | #define OMAP24XX_DMA_SPI1_RX1 38 /* SDMA_37 */ | ||
226 | #define OMAP24XX_DMA_SPI1_TX2 39 /* SDMA_38 */ | ||
227 | #define OMAP24XX_DMA_SPI1_RX2 40 /* SDMA_39 */ | ||
228 | #define OMAP24XX_DMA_SPI1_TX3 41 /* SDMA_40 */ | ||
229 | #define OMAP24XX_DMA_SPI1_RX3 42 /* SDMA_41 */ | ||
230 | #define OMAP24XX_DMA_SPI2_TX0 43 /* SDMA_42 */ | ||
231 | #define OMAP24XX_DMA_SPI2_RX0 44 /* SDMA_43 */ | ||
232 | #define OMAP24XX_DMA_SPI2_TX1 45 /* SDMA_44 */ | ||
233 | #define OMAP24XX_DMA_SPI2_RX1 46 /* SDMA_45 */ | ||
110 | 234 | ||
235 | #define OMAP24XX_DMA_UART1_TX 49 /* SDMA_48 */ | ||
236 | #define OMAP24XX_DMA_UART1_RX 50 /* SDMA_49 */ | ||
237 | #define OMAP24XX_DMA_UART2_TX 51 /* SDMA_50 */ | ||
238 | #define OMAP24XX_DMA_UART2_RX 52 /* SDMA_51 */ | ||
239 | #define OMAP24XX_DMA_UART3_TX 53 /* SDMA_52 */ | ||
240 | #define OMAP24XX_DMA_UART3_RX 54 /* SDMA_53 */ | ||
241 | #define OMAP24XX_DMA_USB_W2FC_TX0 55 /* SDMA_54 */ | ||
242 | #define OMAP24XX_DMA_USB_W2FC_RX0 56 /* SDMA_55 */ | ||
243 | #define OMAP24XX_DMA_USB_W2FC_TX1 57 /* SDMA_56 */ | ||
244 | #define OMAP24XX_DMA_USB_W2FC_RX1 58 /* SDMA_57 */ | ||
245 | #define OMAP24XX_DMA_USB_W2FC_TX2 59 /* SDMA_58 */ | ||
246 | #define OMAP24XX_DMA_USB_W2FC_RX2 60 /* SDMA_59 */ | ||
247 | #define OMAP24XX_DMA_MMC1_TX 61 /* SDMA_60 */ | ||
248 | #define OMAP24XX_DMA_MMC1_RX 62 /* SDMA_61 */ | ||
249 | #define OMAP24XX_DMA_MS 63 /* SDMA_62 */ | ||
250 | |||
251 | /*----------------------------------------------------------------------------*/ | ||
252 | |||
253 | /* Hardware registers for LCD DMA */ | ||
111 | #define OMAP1510_DMA_LCD_BASE (0xfffedb00) | 254 | #define OMAP1510_DMA_LCD_BASE (0xfffedb00) |
112 | #define OMAP1510_DMA_LCD_CTRL (OMAP1510_DMA_LCD_BASE + 0x00) | 255 | #define OMAP1510_DMA_LCD_CTRL (OMAP1510_DMA_LCD_BASE + 0x00) |
113 | #define OMAP1510_DMA_LCD_TOP_F1_L (OMAP1510_DMA_LCD_BASE + 0x02) | 256 | #define OMAP1510_DMA_LCD_TOP_F1_L (OMAP1510_DMA_LCD_BASE + 0x02) |
@@ -116,7 +259,7 @@ | |||
116 | #define OMAP1510_DMA_LCD_BOT_F1_U (OMAP1510_DMA_LCD_BASE + 0x08) | 259 | #define OMAP1510_DMA_LCD_BOT_F1_U (OMAP1510_DMA_LCD_BASE + 0x08) |
117 | 260 | ||
118 | #define OMAP1610_DMA_LCD_BASE (0xfffee300) | 261 | #define OMAP1610_DMA_LCD_BASE (0xfffee300) |
119 | #define OMAP1610_DMA_LCD_CSDP (OMAP1610_DMA_LCD_BASE + 0xc0) | 262 | #define OMAP1610_DMA_LCD_CSDP (OMAP1610_DMA_LCD_BASE + 0xc0) |
120 | #define OMAP1610_DMA_LCD_CCR (OMAP1610_DMA_LCD_BASE + 0xc2) | 263 | #define OMAP1610_DMA_LCD_CCR (OMAP1610_DMA_LCD_BASE + 0xc2) |
121 | #define OMAP1610_DMA_LCD_CTRL (OMAP1610_DMA_LCD_BASE + 0xc4) | 264 | #define OMAP1610_DMA_LCD_CTRL (OMAP1610_DMA_LCD_BASE + 0xc4) |
122 | #define OMAP1610_DMA_LCD_TOP_B1_L (OMAP1610_DMA_LCD_BASE + 0xc8) | 265 | #define OMAP1610_DMA_LCD_TOP_B1_L (OMAP1610_DMA_LCD_BASE + 0xc8) |
@@ -134,37 +277,18 @@ | |||
134 | #define OMAP1610_DMA_LCD_LCH_CTRL (OMAP1610_DMA_LCD_BASE + 0xea) | 277 | #define OMAP1610_DMA_LCD_LCH_CTRL (OMAP1610_DMA_LCD_BASE + 0xea) |
135 | #define OMAP1610_DMA_LCD_SRC_FI_B1_U (OMAP1610_DMA_LCD_BASE + 0xf4) | 278 | #define OMAP1610_DMA_LCD_SRC_FI_B1_U (OMAP1610_DMA_LCD_BASE + 0xf4) |
136 | 279 | ||
137 | 280 | #define OMAP_DMA_TOUT_IRQ (1 << 0) /* Only on omap1 */ | |
138 | /* Every LCh has its own set of the registers below */ | ||
139 | #define OMAP_DMA_CSDP(n) (OMAP_DMA_BASE + 0x40 * (n) + 0x00) | ||
140 | #define OMAP_DMA_CCR(n) (OMAP_DMA_BASE + 0x40 * (n) + 0x02) | ||
141 | #define OMAP_DMA_CICR(n) (OMAP_DMA_BASE + 0x40 * (n) + 0x04) | ||
142 | #define OMAP_DMA_CSR(n) (OMAP_DMA_BASE + 0x40 * (n) + 0x06) | ||
143 | #define OMAP_DMA_CSSA_L(n) (OMAP_DMA_BASE + 0x40 * (n) + 0x08) | ||
144 | #define OMAP_DMA_CSSA_U(n) (OMAP_DMA_BASE + 0x40 * (n) + 0x0a) | ||
145 | #define OMAP_DMA_CDSA_L(n) (OMAP_DMA_BASE + 0x40 * (n) + 0x0c) | ||
146 | #define OMAP_DMA_CDSA_U(n) (OMAP_DMA_BASE + 0x40 * (n) + 0x0e) | ||
147 | #define OMAP_DMA_CEN(n) (OMAP_DMA_BASE + 0x40 * (n) + 0x10) | ||
148 | #define OMAP_DMA_CFN(n) (OMAP_DMA_BASE + 0x40 * (n) + 0x12) | ||
149 | #define OMAP_DMA_CSFI(n) (OMAP_DMA_BASE + 0x40 * (n) + 0x14) | ||
150 | #define OMAP_DMA_CSEI(n) (OMAP_DMA_BASE + 0x40 * (n) + 0x16) | ||
151 | #define OMAP_DMA_CSAC(n) (OMAP_DMA_BASE + 0x40 * (n) + 0x18) | ||
152 | #define OMAP_DMA_CDAC(n) (OMAP_DMA_BASE + 0x40 * (n) + 0x1a) | ||
153 | #define OMAP_DMA_CDEI(n) (OMAP_DMA_BASE + 0x40 * (n) + 0x1c) | ||
154 | #define OMAP_DMA_CDFI(n) (OMAP_DMA_BASE + 0x40 * (n) + 0x1e) | ||
155 | #define OMAP_DMA_COLOR_L(n) (OMAP_DMA_BASE + 0x40 * (n) + 0x20) | ||
156 | #define OMAP_DMA_COLOR_U(n) (OMAP_DMA_BASE + 0x40 * (n) + 0x22) | ||
157 | #define OMAP_DMA_CCR2(n) (OMAP_DMA_BASE + 0x40 * (n) + 0x24) | ||
158 | #define OMAP_DMA_CLNK_CTRL(n) (OMAP_DMA_BASE + 0x40 * (n) + 0x28) | ||
159 | #define OMAP_DMA_LCH_CTRL(n) (OMAP_DMA_BASE + 0x40 * (n) + 0x2a) | ||
160 | |||
161 | #define OMAP_DMA_TOUT_IRQ (1 << 0) | ||
162 | #define OMAP_DMA_DROP_IRQ (1 << 1) | 281 | #define OMAP_DMA_DROP_IRQ (1 << 1) |
163 | #define OMAP_DMA_HALF_IRQ (1 << 2) | 282 | #define OMAP_DMA_HALF_IRQ (1 << 2) |
164 | #define OMAP_DMA_FRAME_IRQ (1 << 3) | 283 | #define OMAP_DMA_FRAME_IRQ (1 << 3) |
165 | #define OMAP_DMA_LAST_IRQ (1 << 4) | 284 | #define OMAP_DMA_LAST_IRQ (1 << 4) |
166 | #define OMAP_DMA_BLOCK_IRQ (1 << 5) | 285 | #define OMAP_DMA_BLOCK_IRQ (1 << 5) |
167 | #define OMAP_DMA_SYNC_IRQ (1 << 6) | 286 | #define OMAP1_DMA_SYNC_IRQ (1 << 6) |
287 | #define OMAP2_DMA_PKT_IRQ (1 << 7) | ||
288 | #define OMAP2_DMA_TRANS_ERR_IRQ (1 << 8) | ||
289 | #define OMAP2_DMA_SECURE_ERR_IRQ (1 << 9) | ||
290 | #define OMAP2_DMA_SUPERVISOR_ERR_IRQ (1 << 10) | ||
291 | #define OMAP2_DMA_MISALIGNED_ERR_IRQ (1 << 11) | ||
168 | 292 | ||
169 | #define OMAP_DMA_DATA_TYPE_S8 0x00 | 293 | #define OMAP_DMA_DATA_TYPE_S8 0x00 |
170 | #define OMAP_DMA_DATA_TYPE_S16 0x01 | 294 | #define OMAP_DMA_DATA_TYPE_S16 0x01 |
@@ -194,6 +318,7 @@ enum { | |||
194 | OMAP_LCD_DMA_B2_BOTTOM | 318 | OMAP_LCD_DMA_B2_BOTTOM |
195 | }; | 319 | }; |
196 | 320 | ||
321 | /* REVISIT: Check if BURST_4 is really 1 (or 2) */ | ||
197 | enum omap_dma_burst_mode { | 322 | enum omap_dma_burst_mode { |
198 | OMAP_DMA_DATA_BURST_DIS = 0, | 323 | OMAP_DMA_DATA_BURST_DIS = 0, |
199 | OMAP_DMA_DATA_BURST_4, | 324 | OMAP_DMA_DATA_BURST_4, |
@@ -206,6 +331,31 @@ enum omap_dma_color_mode { | |||
206 | OMAP_DMA_TRANSPARENT_COPY | 331 | OMAP_DMA_TRANSPARENT_COPY |
207 | }; | 332 | }; |
208 | 333 | ||
334 | struct omap_dma_channel_params { | ||
335 | int data_type; /* data type 8,16,32 */ | ||
336 | int elem_count; /* number of elements in a frame */ | ||
337 | int frame_count; /* number of frames in a element */ | ||
338 | |||
339 | int src_port; /* Only on OMAP1 REVISIT: Is this needed? */ | ||
340 | int src_amode; /* constant , post increment, indexed , double indexed */ | ||
341 | int src_start; /* source address : physical */ | ||
342 | int src_ei; /* source element index */ | ||
343 | int src_fi; /* source frame index */ | ||
344 | |||
345 | int dst_port; /* Only on OMAP1 REVISIT: Is this needed? */ | ||
346 | int dst_amode; /* constant , post increment, indexed , double indexed */ | ||
347 | int dst_start; /* source address : physical */ | ||
348 | int dst_ei; /* source element index */ | ||
349 | int dst_fi; /* source frame index */ | ||
350 | |||
351 | int trigger; /* trigger attached if the channel is synchronized */ | ||
352 | int sync_mode; /* sycn on element, frame , block or packet */ | ||
353 | int src_or_dst_synch; /* source synch(1) or destination synch(0) */ | ||
354 | |||
355 | int ie; /* interrupt enabled */ | ||
356 | }; | ||
357 | |||
358 | |||
209 | extern void omap_set_dma_priority(int dst_port, int priority); | 359 | extern void omap_set_dma_priority(int dst_port, int priority); |
210 | extern int omap_request_dma(int dev_id, const char *dev_name, | 360 | extern int omap_request_dma(int dev_id, const char *dev_name, |
211 | void (* callback)(int lch, u16 ch_status, void *data), | 361 | void (* callback)(int lch, u16 ch_status, void *data), |
@@ -217,24 +367,30 @@ extern void omap_start_dma(int lch); | |||
217 | extern void omap_stop_dma(int lch); | 367 | extern void omap_stop_dma(int lch); |
218 | extern void omap_set_dma_transfer_params(int lch, int data_type, | 368 | extern void omap_set_dma_transfer_params(int lch, int data_type, |
219 | int elem_count, int frame_count, | 369 | int elem_count, int frame_count, |
220 | int sync_mode); | 370 | int sync_mode, |
371 | int dma_trigger, int src_or_dst_synch); | ||
221 | extern void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, | 372 | extern void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, |
222 | u32 color); | 373 | u32 color); |
223 | 374 | ||
224 | extern void omap_set_dma_src_params(int lch, int src_port, int src_amode, | 375 | extern void omap_set_dma_src_params(int lch, int src_port, int src_amode, |
225 | unsigned long src_start); | 376 | unsigned long src_start, |
377 | int src_ei, int src_fi); | ||
226 | extern void omap_set_dma_src_index(int lch, int eidx, int fidx); | 378 | extern void omap_set_dma_src_index(int lch, int eidx, int fidx); |
227 | extern void omap_set_dma_src_data_pack(int lch, int enable); | 379 | extern void omap_set_dma_src_data_pack(int lch, int enable); |
228 | extern void omap_set_dma_src_burst_mode(int lch, | 380 | extern void omap_set_dma_src_burst_mode(int lch, |
229 | enum omap_dma_burst_mode burst_mode); | 381 | enum omap_dma_burst_mode burst_mode); |
230 | 382 | ||
231 | extern void omap_set_dma_dest_params(int lch, int dest_port, int dest_amode, | 383 | extern void omap_set_dma_dest_params(int lch, int dest_port, int dest_amode, |
232 | unsigned long dest_start); | 384 | unsigned long dest_start, |
385 | int dst_ei, int dst_fi); | ||
233 | extern void omap_set_dma_dest_index(int lch, int eidx, int fidx); | 386 | extern void omap_set_dma_dest_index(int lch, int eidx, int fidx); |
234 | extern void omap_set_dma_dest_data_pack(int lch, int enable); | 387 | extern void omap_set_dma_dest_data_pack(int lch, int enable); |
235 | extern void omap_set_dma_dest_burst_mode(int lch, | 388 | extern void omap_set_dma_dest_burst_mode(int lch, |
236 | enum omap_dma_burst_mode burst_mode); | 389 | enum omap_dma_burst_mode burst_mode); |
237 | 390 | ||
391 | extern void omap_set_dma_params(int lch, | ||
392 | struct omap_dma_channel_params * params); | ||
393 | |||
238 | extern void omap_dma_link_lch (int lch_head, int lch_queue); | 394 | extern void omap_dma_link_lch (int lch_head, int lch_queue); |
239 | extern void omap_dma_unlink_lch (int lch_head, int lch_queue); | 395 | extern void omap_dma_unlink_lch (int lch_head, int lch_queue); |
240 | 396 | ||
@@ -244,9 +400,6 @@ extern int omap_get_dma_src_addr_counter(int lch); | |||
244 | extern void omap_clear_dma(int lch); | 400 | extern void omap_clear_dma(int lch); |
245 | extern int omap_dma_running(void); | 401 | extern int omap_dma_running(void); |
246 | 402 | ||
247 | /* Returns 1 if the DMA module is in OMAP1510-compatible mode, 0 otherwise */ | ||
248 | extern int omap_dma_in_1510_mode(void); | ||
249 | |||
250 | /* LCD DMA functions */ | 403 | /* LCD DMA functions */ |
251 | extern int omap_request_lcd_dma(void (* callback)(u16 status, void *data), | 404 | extern int omap_request_lcd_dma(void (* callback)(u16 status, void *data), |
252 | void *data); | 405 | void *data); |
diff --git a/include/asm-arm/arch-omap/entry-macro.S b/include/asm-arm/arch-omap/entry-macro.S index 0d29b9c56a95..f8814a84910e 100644 --- a/include/asm-arm/arch-omap/entry-macro.S +++ b/include/asm-arm/arch-omap/entry-macro.S | |||
@@ -10,6 +10,20 @@ | |||
10 | 10 | ||
11 | #if defined(CONFIG_ARCH_OMAP1) | 11 | #if defined(CONFIG_ARCH_OMAP1) |
12 | 12 | ||
13 | #if defined(CONFIG_ARCH_OMAP730) && \ | ||
14 | (defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX)) | ||
15 | #error "FIXME: OMAP730 doesn't support multiple-OMAP" | ||
16 | #elif defined(CONFIG_ARCH_OMAP730) | ||
17 | #define INT_IH2_IRQ INT_730_IH2_IRQ | ||
18 | #elif defined(CONFIG_ARCH_OMAP15XX) | ||
19 | #define INT_IH2_IRQ INT_1510_IH2_IRQ | ||
20 | #elif defined(CONFIG_ARCH_OMAP16XX) | ||
21 | #define INT_IH2_IRQ INT_1610_IH2_IRQ | ||
22 | #else | ||
23 | #warning "IH2 IRQ defaulted" | ||
24 | #define INT_IH2_IRQ INT_1510_IH2_IRQ | ||
25 | #endif | ||
26 | |||
13 | .macro disable_fiq | 27 | .macro disable_fiq |
14 | .endm | 28 | .endm |
15 | 29 | ||
diff --git a/include/asm-arm/arch-omap/fpga.h b/include/asm-arm/arch-omap/fpga.h index 676807dc50e1..6a883e0bdbb8 100644 --- a/include/asm-arm/arch-omap/fpga.h +++ b/include/asm-arm/arch-omap/fpga.h | |||
@@ -19,7 +19,7 @@ | |||
19 | #ifndef __ASM_ARCH_OMAP_FPGA_H | 19 | #ifndef __ASM_ARCH_OMAP_FPGA_H |
20 | #define __ASM_ARCH_OMAP_FPGA_H | 20 | #define __ASM_ARCH_OMAP_FPGA_H |
21 | 21 | ||
22 | #if defined(CONFIG_MACH_OMAP_INNOVATOR) && defined(CONFIG_ARCH_OMAP1510) | 22 | #if defined(CONFIG_MACH_OMAP_INNOVATOR) && defined(CONFIG_ARCH_OMAP15XX) |
23 | extern void omap1510_fpga_init_irq(void); | 23 | extern void omap1510_fpga_init_irq(void); |
24 | #else | 24 | #else |
25 | #define omap1510_fpga_init_irq() (0) | 25 | #define omap1510_fpga_init_irq() (0) |
@@ -77,6 +77,8 @@ struct h2p2_dbg_fpga { | |||
77 | #define H2P2_DBG_FPGA_LOAD_METER_SIZE 11 | 77 | #define H2P2_DBG_FPGA_LOAD_METER_SIZE 11 |
78 | #define H2P2_DBG_FPGA_LOAD_METER_MASK ((1 << H2P2_DBG_FPGA_LOAD_METER_SIZE) - 1) | 78 | #define H2P2_DBG_FPGA_LOAD_METER_MASK ((1 << H2P2_DBG_FPGA_LOAD_METER_SIZE) - 1) |
79 | 79 | ||
80 | #define H2P2_DBG_FPGA_P2_LED_TIMER (1 << 0) | ||
81 | #define H2P2_DBG_FPGA_P2_LED_IDLE (1 << 1) | ||
80 | 82 | ||
81 | /* | 83 | /* |
82 | * --------------------------------------------------------------------------- | 84 | * --------------------------------------------------------------------------- |
diff --git a/include/asm-arm/arch-omap/gpio.h b/include/asm-arm/arch-omap/gpio.h index 74cb2b93b700..1b3885741ac1 100644 --- a/include/asm-arm/arch-omap/gpio.h +++ b/include/asm-arm/arch-omap/gpio.h | |||
@@ -67,7 +67,7 @@ | |||
67 | 67 | ||
68 | #define OMAP_GPIO_IRQ(nr) (OMAP_GPIO_IS_MPUIO(nr) ? \ | 68 | #define OMAP_GPIO_IRQ(nr) (OMAP_GPIO_IS_MPUIO(nr) ? \ |
69 | IH_MPUIO_BASE + ((nr) & 0x0f) : \ | 69 | IH_MPUIO_BASE + ((nr) & 0x0f) : \ |
70 | IH_GPIO_BASE + ((nr) & 0x3f)) | 70 | IH_GPIO_BASE + (nr)) |
71 | 71 | ||
72 | extern int omap_gpio_init(void); /* Call from board init only */ | 72 | extern int omap_gpio_init(void); /* Call from board init only */ |
73 | extern int omap_request_gpio(int gpio); | 73 | extern int omap_request_gpio(int gpio); |
diff --git a/include/asm-arm/arch-omap/hardware.h b/include/asm-arm/arch-omap/hardware.h index 60201e1dd6ad..5406b875c422 100644 --- a/include/asm-arm/arch-omap/hardware.h +++ b/include/asm-arm/arch-omap/hardware.h | |||
@@ -267,8 +267,6 @@ | |||
267 | #define OMAP_LPG2_LCR (OMAP_LPG2_BASE + 0x00) | 267 | #define OMAP_LPG2_LCR (OMAP_LPG2_BASE + 0x00) |
268 | #define OMAP_LPG2_PMR (OMAP_LPG2_BASE + 0x04) | 268 | #define OMAP_LPG2_PMR (OMAP_LPG2_BASE + 0x04) |
269 | 269 | ||
270 | #ifndef __ASSEMBLER__ | ||
271 | |||
272 | /* | 270 | /* |
273 | * --------------------------------------------------------------------------- | 271 | * --------------------------------------------------------------------------- |
274 | * Processor specific defines | 272 | * Processor specific defines |
@@ -277,13 +275,11 @@ | |||
277 | 275 | ||
278 | #include "omap730.h" | 276 | #include "omap730.h" |
279 | #include "omap1510.h" | 277 | #include "omap1510.h" |
280 | |||
281 | #ifdef CONFIG_ARCH_OMAP24XX | ||
282 | #include "omap24xx.h" | 278 | #include "omap24xx.h" |
283 | #endif | ||
284 | |||
285 | #include "omap16xx.h" | 279 | #include "omap16xx.h" |
286 | 280 | ||
281 | #ifndef __ASSEMBLER__ | ||
282 | |||
287 | /* | 283 | /* |
288 | * --------------------------------------------------------------------------- | 284 | * --------------------------------------------------------------------------- |
289 | * Board specific defines | 285 | * Board specific defines |
diff --git a/include/asm-arm/arch-omap/io.h b/include/asm-arm/arch-omap/io.h index 3d5bcd545082..f5bcc9a1aed6 100644 --- a/include/asm-arm/arch-omap/io.h +++ b/include/asm-arm/arch-omap/io.h | |||
@@ -52,23 +52,33 @@ | |||
52 | * ---------------------------------------------------------------------------- | 52 | * ---------------------------------------------------------------------------- |
53 | */ | 53 | */ |
54 | 54 | ||
55 | #define PCIO_BASE 0 | ||
56 | |||
55 | #if defined(CONFIG_ARCH_OMAP1) | 57 | #if defined(CONFIG_ARCH_OMAP1) |
58 | |||
56 | #define IO_PHYS 0xFFFB0000 | 59 | #define IO_PHYS 0xFFFB0000 |
57 | #define IO_OFFSET -0x01000000 /* Virtual IO = 0xfefb0000 */ | 60 | #define IO_OFFSET 0x01000000 /* Virtual IO = 0xfefb0000 */ |
58 | #define IO_SIZE 0x40000 | 61 | #define IO_SIZE 0x40000 |
62 | #define IO_VIRT (IO_PHYS - IO_OFFSET) | ||
63 | #define IO_ADDRESS(pa) ((pa) - IO_OFFSET) | ||
64 | #define io_p2v(pa) ((pa) - IO_OFFSET) | ||
65 | #define io_v2p(va) ((va) + IO_OFFSET) | ||
59 | 66 | ||
60 | #elif defined(CONFIG_ARCH_OMAP2) | 67 | #elif defined(CONFIG_ARCH_OMAP2) |
61 | #define IO_PHYS 0x48000000 /* L4 peripherals; other stuff has to be mapped * | ||
62 | * manually. */ | ||
63 | #define IO_OFFSET 0x90000000 /* Virtual IO = 0xd8000000 */ | ||
64 | #define IO_SIZE 0x08000000 | ||
65 | #endif | ||
66 | 68 | ||
67 | #define IO_VIRT (IO_PHYS + IO_OFFSET) | 69 | /* We map both L3 and L4 on OMAP2 */ |
68 | #define IO_ADDRESS(x) ((x) + IO_OFFSET) | 70 | #define L3_24XX_PHYS L3_24XX_BASE /* 0x68000000 */ |
69 | #define PCIO_BASE 0 | 71 | #define L3_24XX_VIRT 0xf8000000 |
70 | #define io_p2v(x) ((x) + IO_OFFSET) | 72 | #define L3_24XX_SIZE SZ_1M /* 44kB of 128MB used, want 1MB sect */ |
71 | #define io_v2p(x) ((x) - IO_OFFSET) | 73 | #define L4_24XX_PHYS L4_24XX_BASE /* 0x48000000 */ |
74 | #define L4_24XX_VIRT 0xd8000000 | ||
75 | #define L4_24XX_SIZE SZ_1M /* 1MB of 128MB used, want 1MB sect */ | ||
76 | #define IO_OFFSET 0x90000000 | ||
77 | #define IO_ADDRESS(pa) ((pa) + IO_OFFSET) /* Works for L3 and L4 */ | ||
78 | #define io_p2v(pa) ((pa) + IO_OFFSET) /* Works for L3 and L4 */ | ||
79 | #define io_v2p(va) ((va) - IO_OFFSET) /* Works for L3 and L4 */ | ||
80 | |||
81 | #endif | ||
72 | 82 | ||
73 | #ifndef __ASSEMBLER__ | 83 | #ifndef __ASSEMBLER__ |
74 | 84 | ||
diff --git a/include/asm-arm/arch-omap/irqs.h b/include/asm-arm/arch-omap/irqs.h index 74e108ccac16..9779686bdceb 100644 --- a/include/asm-arm/arch-omap/irqs.h +++ b/include/asm-arm/arch-omap/irqs.h | |||
@@ -22,8 +22,8 @@ | |||
22 | * are different. | 22 | * are different. |
23 | */ | 23 | */ |
24 | 24 | ||
25 | #ifndef __ASM_ARCH_OMAP1510_IRQS_H | 25 | #ifndef __ASM_ARCH_OMAP15XX_IRQS_H |
26 | #define __ASM_ARCH_OMAP1510_IRQS_H | 26 | #define __ASM_ARCH_OMAP15XX_IRQS_H |
27 | 27 | ||
28 | /* | 28 | /* |
29 | * IRQ numbers for interrupt handler 1 | 29 | * IRQ numbers for interrupt handler 1 |
@@ -31,7 +31,6 @@ | |||
31 | * NOTE: See also the OMAP-1510 and 1610 specific IRQ numbers below | 31 | * NOTE: See also the OMAP-1510 and 1610 specific IRQ numbers below |
32 | * | 32 | * |
33 | */ | 33 | */ |
34 | #define INT_IH2_IRQ 0 | ||
35 | #define INT_CAMERA 1 | 34 | #define INT_CAMERA 1 |
36 | #define INT_FIQ 3 | 35 | #define INT_FIQ 3 |
37 | #define INT_RTDX 6 | 36 | #define INT_RTDX 6 |
@@ -60,6 +59,7 @@ | |||
60 | /* | 59 | /* |
61 | * OMAP-1510 specific IRQ numbers for interrupt handler 1 | 60 | * OMAP-1510 specific IRQ numbers for interrupt handler 1 |
62 | */ | 61 | */ |
62 | #define INT_1510_IH2_IRQ 0 | ||
63 | #define INT_1510_RES2 2 | 63 | #define INT_1510_RES2 2 |
64 | #define INT_1510_SPI_TX 4 | 64 | #define INT_1510_SPI_TX 4 |
65 | #define INT_1510_SPI_RX 5 | 65 | #define INT_1510_SPI_RX 5 |
@@ -71,6 +71,7 @@ | |||
71 | /* | 71 | /* |
72 | * OMAP-1610 specific IRQ numbers for interrupt handler 1 | 72 | * OMAP-1610 specific IRQ numbers for interrupt handler 1 |
73 | */ | 73 | */ |
74 | #define INT_1610_IH2_IRQ 0 | ||
74 | #define INT_1610_IH2_FIQ 2 | 75 | #define INT_1610_IH2_FIQ 2 |
75 | #define INT_1610_McBSP2_TX 4 | 76 | #define INT_1610_McBSP2_TX 4 |
76 | #define INT_1610_McBSP2_RX 5 | 77 | #define INT_1610_McBSP2_RX 5 |
@@ -231,6 +232,12 @@ | |||
231 | #define INT_730_DMA_CH15 (62 + IH2_BASE) | 232 | #define INT_730_DMA_CH15 (62 + IH2_BASE) |
232 | #define INT_730_NAND (63 + IH2_BASE) | 233 | #define INT_730_NAND (63 + IH2_BASE) |
233 | 234 | ||
235 | #define INT_24XX_SYS_NIRQ 7 | ||
236 | #define INT_24XX_SDMA_IRQ0 12 | ||
237 | #define INT_24XX_SDMA_IRQ1 13 | ||
238 | #define INT_24XX_SDMA_IRQ2 14 | ||
239 | #define INT_24XX_SDMA_IRQ3 15 | ||
240 | #define INT_24XX_DSS_IRQ 25 | ||
234 | #define INT_24XX_GPIO_BANK1 29 | 241 | #define INT_24XX_GPIO_BANK1 29 |
235 | #define INT_24XX_GPIO_BANK2 30 | 242 | #define INT_24XX_GPIO_BANK2 30 |
236 | #define INT_24XX_GPIO_BANK3 31 | 243 | #define INT_24XX_GPIO_BANK3 31 |
diff --git a/include/asm-arm/arch-omap/memory.h b/include/asm-arm/arch-omap/memory.h index bf545b6e0a26..df50dd53e1dd 100644 --- a/include/asm-arm/arch-omap/memory.h +++ b/include/asm-arm/arch-omap/memory.h | |||
@@ -61,7 +61,7 @@ | |||
61 | * Note that the is_lbus_device() test is not very efficient on 1510 | 61 | * Note that the is_lbus_device() test is not very efficient on 1510 |
62 | * because of the strncmp(). | 62 | * because of the strncmp(). |
63 | */ | 63 | */ |
64 | #ifdef CONFIG_ARCH_OMAP1510 | 64 | #ifdef CONFIG_ARCH_OMAP15XX |
65 | 65 | ||
66 | /* | 66 | /* |
67 | * OMAP-1510 Local Bus address offset | 67 | * OMAP-1510 Local Bus address offset |
@@ -84,7 +84,7 @@ | |||
84 | virt_to_lbus(addr) : \ | 84 | virt_to_lbus(addr) : \ |
85 | __virt_to_bus(addr);}) | 85 | __virt_to_bus(addr);}) |
86 | 86 | ||
87 | #endif /* CONFIG_ARCH_OMAP1510 */ | 87 | #endif /* CONFIG_ARCH_OMAP15XX */ |
88 | 88 | ||
89 | #endif | 89 | #endif |
90 | 90 | ||
diff --git a/include/asm-arm/arch-omap/menelaus.h b/include/asm-arm/arch-omap/menelaus.h new file mode 100644 index 000000000000..46be8b8d6346 --- /dev/null +++ b/include/asm-arm/arch-omap/menelaus.h | |||
@@ -0,0 +1,22 @@ | |||
1 | /* | ||
2 | * linux/include/asm-arm/arch-omap/menelaus.h | ||
3 | * | ||
4 | * Functions to access Menelaus power management chip | ||
5 | */ | ||
6 | |||
7 | #ifndef __ASM_ARCH_MENELAUS_H | ||
8 | #define __ASM_ARCH_MENELAUS_H | ||
9 | |||
10 | extern void menelaus_mmc_register(void (*callback)(u8 card_mask), | ||
11 | unsigned long data); | ||
12 | extern void menelaus_mmc_remove(void); | ||
13 | extern void menelaus_mmc_opendrain(int enable); | ||
14 | |||
15 | #if defined(CONFIG_ARCH_OMAP24XX) && defined(CONFIG_MENELAUS) | ||
16 | #define omap_has_menelaus() 1 | ||
17 | #else | ||
18 | #define omap_has_menelaus() 0 | ||
19 | #endif | ||
20 | |||
21 | #endif | ||
22 | |||
diff --git a/include/asm-arm/arch-omap/mux.h b/include/asm-arm/arch-omap/mux.h index 1b1ad4105349..13415a9aab06 100644 --- a/include/asm-arm/arch-omap/mux.h +++ b/include/asm-arm/arch-omap/mux.h | |||
@@ -4,7 +4,7 @@ | |||
4 | * Table of the Omap register configurations for the FUNC_MUX and | 4 | * Table of the Omap register configurations for the FUNC_MUX and |
5 | * PULL_DWN combinations. | 5 | * PULL_DWN combinations. |
6 | * | 6 | * |
7 | * Copyright (C) 2003 Nokia Corporation | 7 | * Copyright (C) 2003 - 2005 Nokia Corporation |
8 | * | 8 | * |
9 | * Written by Tony Lindgren <tony.lindgren@nokia.com> | 9 | * Written by Tony Lindgren <tony.lindgren@nokia.com> |
10 | * | 10 | * |
@@ -58,6 +58,16 @@ | |||
58 | .pu_pd_reg = PU_PD_SEL_##reg, \ | 58 | .pu_pd_reg = PU_PD_SEL_##reg, \ |
59 | .pu_pd_val = status, | 59 | .pu_pd_val = status, |
60 | 60 | ||
61 | #define MUX_REG_730(reg, mode_offset, mode) .mux_reg_name = "OMAP730_IO_CONF_"#reg, \ | ||
62 | .mux_reg = OMAP730_IO_CONF_##reg, \ | ||
63 | .mask_offset = mode_offset, \ | ||
64 | .mask = mode, | ||
65 | |||
66 | #define PULL_REG_730(reg, bit, status) .pull_name = "OMAP730_IO_CONF_"#reg, \ | ||
67 | .pull_reg = OMAP730_IO_CONF_##reg, \ | ||
68 | .pull_bit = bit, \ | ||
69 | .pull_val = status, | ||
70 | |||
61 | #else | 71 | #else |
62 | 72 | ||
63 | #define MUX_REG(reg, mode_offset, mode) .mux_reg = FUNC_MUX_CTRL_##reg, \ | 73 | #define MUX_REG(reg, mode_offset, mode) .mux_reg = FUNC_MUX_CTRL_##reg, \ |
@@ -71,6 +81,15 @@ | |||
71 | #define PU_PD_REG(reg, status) .pu_pd_reg = PU_PD_SEL_##reg, \ | 81 | #define PU_PD_REG(reg, status) .pu_pd_reg = PU_PD_SEL_##reg, \ |
72 | .pu_pd_val = status, | 82 | .pu_pd_val = status, |
73 | 83 | ||
84 | #define MUX_REG_730(reg, mode_offset, mode) \ | ||
85 | .mux_reg = OMAP730_IO_CONF_##reg, \ | ||
86 | .mask_offset = mode_offset, \ | ||
87 | .mask = mode, | ||
88 | |||
89 | #define PULL_REG_730(reg, bit, status) .pull_reg = OMAP730_IO_CONF_##reg, \ | ||
90 | .pull_bit = bit, \ | ||
91 | .pull_val = status, | ||
92 | |||
74 | #endif /* CONFIG_OMAP_MUX_DEBUG */ | 93 | #endif /* CONFIG_OMAP_MUX_DEBUG */ |
75 | 94 | ||
76 | #define MUX_CFG(desc, mux_reg, mode_offset, mode, \ | 95 | #define MUX_CFG(desc, mux_reg, mode_offset, mode, \ |
@@ -84,13 +103,44 @@ | |||
84 | PU_PD_REG(pu_pd_reg, pu_pd_status) \ | 103 | PU_PD_REG(pu_pd_reg, pu_pd_status) \ |
85 | }, | 104 | }, |
86 | 105 | ||
106 | |||
107 | /* | ||
108 | * OMAP730 has a slightly different config for the pin mux. | ||
109 | * - config regs are the OMAP730_IO_CONF_x regs (see omap730.h) regs and | ||
110 | * not the FUNC_MUX_CTRL_x regs from hardware.h | ||
111 | * - for pull-up/down, only has one enable bit which is is in the same register | ||
112 | * as mux config | ||
113 | */ | ||
114 | #define MUX_CFG_730(desc, mux_reg, mode_offset, mode, \ | ||
115 | pull_reg, pull_bit, pull_status, \ | ||
116 | pu_pd_reg, pu_pd_status, debug_status)\ | ||
117 | { \ | ||
118 | .name = desc, \ | ||
119 | .debug = debug_status, \ | ||
120 | MUX_REG_730(mux_reg, mode_offset, mode) \ | ||
121 | PULL_REG_730(mux_reg, pull_bit, pull_status) \ | ||
122 | PU_PD_REG(pu_pd_reg, pu_pd_status) \ | ||
123 | }, | ||
124 | |||
125 | #define MUX_CFG_24XX(desc, reg_offset, mode, \ | ||
126 | pull_en, pull_mode, dbg) \ | ||
127 | { \ | ||
128 | .name = desc, \ | ||
129 | .debug = dbg, \ | ||
130 | .mux_reg = reg_offset, \ | ||
131 | .mask = mode, \ | ||
132 | .pull_val = pull_en, \ | ||
133 | .pu_pd_val = pull_mode, \ | ||
134 | }, | ||
135 | |||
136 | |||
87 | #define PULL_DISABLED 0 | 137 | #define PULL_DISABLED 0 |
88 | #define PULL_ENABLED 1 | 138 | #define PULL_ENABLED 1 |
89 | 139 | ||
90 | #define PULL_DOWN 0 | 140 | #define PULL_DOWN 0 |
91 | #define PULL_UP 1 | 141 | #define PULL_UP 1 |
92 | 142 | ||
93 | typedef struct { | 143 | struct pin_config { |
94 | char *name; | 144 | char *name; |
95 | unsigned char busy; | 145 | unsigned char busy; |
96 | unsigned char debug; | 146 | unsigned char debug; |
@@ -108,13 +158,23 @@ typedef struct { | |||
108 | const char *pu_pd_name; | 158 | const char *pu_pd_name; |
109 | const unsigned int pu_pd_reg; | 159 | const unsigned int pu_pd_reg; |
110 | const unsigned char pu_pd_val; | 160 | const unsigned char pu_pd_val; |
111 | } reg_cfg_set; | 161 | }; |
112 | 162 | ||
113 | /* | 163 | enum omap730_index { |
114 | * Lookup table for FUNC_MUX and PULL_DWN register combinations for each | 164 | /* OMAP 730 keyboard */ |
115 | * device. See also reg_cfg_table below for the register values. | 165 | E2_730_KBR0, |
116 | */ | 166 | J7_730_KBR1, |
117 | typedef enum { | 167 | E1_730_KBR2, |
168 | F3_730_KBR3, | ||
169 | D2_730_KBR4, | ||
170 | C2_730_KBC0, | ||
171 | D3_730_KBC1, | ||
172 | E4_730_KBC2, | ||
173 | F4_730_KBC3, | ||
174 | E3_730_KBC4, | ||
175 | }; | ||
176 | |||
177 | enum omap1xxx_index { | ||
118 | /* UART1 (BT_UART_GATING)*/ | 178 | /* UART1 (BT_UART_GATING)*/ |
119 | UART1_TX = 0, | 179 | UART1_TX = 0, |
120 | UART1_RTS, | 180 | UART1_RTS, |
@@ -331,245 +391,34 @@ typedef enum { | |||
331 | V10_1610_CF_IREQ, | 391 | V10_1610_CF_IREQ, |
332 | W10_1610_CF_RESET, | 392 | W10_1610_CF_RESET, |
333 | W11_1610_CF_CD1, | 393 | W11_1610_CF_CD1, |
334 | } reg_cfg_t; | 394 | }; |
335 | 395 | ||
336 | #if defined(__MUX_C__) && defined(CONFIG_OMAP_MUX) | 396 | enum omap24xx_index { |
397 | /* 24xx I2C */ | ||
398 | M19_24XX_I2C1_SCL, | ||
399 | L15_24XX_I2C1_SDA, | ||
400 | J15_24XX_I2C2_SCL, | ||
401 | H19_24XX_I2C2_SDA, | ||
337 | 402 | ||
338 | /* | 403 | /* 24xx Menelaus interrupt */ |
339 | * Table of various FUNC_MUX and PULL_DWN combinations for each device. | 404 | W19_24XX_SYS_NIRQ, |
340 | * See also reg_cfg_t above for the lookup table. | ||
341 | */ | ||
342 | static const reg_cfg_set __initdata_or_module | ||
343 | reg_cfg_table[] = { | ||
344 | /* | ||
345 | * description mux mode mux pull pull pull pu_pd pu dbg | ||
346 | * reg offset mode reg bit ena reg | ||
347 | */ | ||
348 | MUX_CFG("UART1_TX", 9, 21, 1, 2, 3, 0, NA, 0, 0) | ||
349 | MUX_CFG("UART1_RTS", 9, 12, 1, 2, 0, 0, NA, 0, 0) | ||
350 | |||
351 | /* UART2 (COM_UART_GATING), conflicts with USB2 */ | ||
352 | MUX_CFG("UART2_TX", C, 27, 1, 3, 3, 0, NA, 0, 0) | ||
353 | MUX_CFG("UART2_RX", C, 18, 0, 3, 1, 1, NA, 0, 0) | ||
354 | MUX_CFG("UART2_CTS", C, 21, 0, 3, 1, 1, NA, 0, 0) | ||
355 | MUX_CFG("UART2_RTS", C, 24, 1, 3, 2, 0, NA, 0, 0) | ||
356 | |||
357 | /* UART3 (GIGA_UART_GATING) */ | ||
358 | MUX_CFG("UART3_TX", 6, 0, 1, 0, 30, 0, NA, 0, 0) | ||
359 | MUX_CFG("UART3_RX", 6, 3, 0, 0, 31, 1, NA, 0, 0) | ||
360 | MUX_CFG("UART3_CTS", 5, 12, 2, 0, 24, 0, NA, 0, 0) | ||
361 | MUX_CFG("UART3_RTS", 5, 15, 2, 0, 25, 0, NA, 0, 0) | ||
362 | MUX_CFG("UART3_CLKREQ", 9, 27, 0, 2, 5, 0, NA, 0, 0) | ||
363 | MUX_CFG("UART3_BCLK", A, 0, 0, 2, 6, 0, NA, 0, 0) | ||
364 | MUX_CFG("Y15_1610_UART3_RTS", A, 0, 1, 2, 6, 0, NA, 0, 0) | ||
365 | |||
366 | /* PWT & PWL, conflicts with UART3 */ | ||
367 | MUX_CFG("PWT", 6, 0, 2, 0, 30, 0, NA, 0, 0) | ||
368 | MUX_CFG("PWL", 6, 3, 1, 0, 31, 1, NA, 0, 0) | ||
369 | |||
370 | /* USB internal master generic */ | ||
371 | MUX_CFG("R18_USB_VBUS", 7, 9, 2, 1, 11, 0, NA, 0, 1) | ||
372 | MUX_CFG("R18_1510_USB_GPIO0", 7, 9, 0, 1, 11, 1, NA, 0, 1) | ||
373 | /* works around erratum: W4_USB_PUEN and W4_USB_PUDIS are switched! */ | ||
374 | MUX_CFG("W4_USB_PUEN", D, 3, 3, 3, 5, 1, NA, 0, 1) | ||
375 | MUX_CFG("W4_USB_CLKO", D, 3, 1, 3, 5, 0, NA, 0, 1) | ||
376 | MUX_CFG("W4_USB_HIGHZ", D, 3, 4, 3, 5, 0, 3, 0, 1) | ||
377 | MUX_CFG("W4_GPIO58", D, 3, 7, 3, 5, 0, 3, 0, 1) | ||
378 | |||
379 | /* USB1 master */ | ||
380 | MUX_CFG("USB1_SUSP", 8, 27, 2, 1, 27, 0, NA, 0, 1) | ||
381 | MUX_CFG("USB1_SE0", 9, 0, 2, 1, 28, 0, NA, 0, 1) | ||
382 | MUX_CFG("W13_1610_USB1_SE0", 9, 0, 4, 1, 28, 0, NA, 0, 1) | ||
383 | MUX_CFG("USB1_TXEN", 9, 3, 2, 1, 29, 0, NA, 0, 1) | ||
384 | MUX_CFG("USB1_TXD", 9, 24, 1, 2, 4, 0, NA, 0, 1) | ||
385 | MUX_CFG("USB1_VP", A, 3, 1, 2, 7, 0, NA, 0, 1) | ||
386 | MUX_CFG("USB1_VM", A, 6, 1, 2, 8, 0, NA, 0, 1) | ||
387 | MUX_CFG("USB1_RCV", A, 9, 1, 2, 9, 0, NA, 0, 1) | ||
388 | MUX_CFG("USB1_SPEED", A, 12, 2, 2, 10, 0, NA, 0, 1) | ||
389 | MUX_CFG("R13_1610_USB1_SPEED", A, 12, 5, 2, 10, 0, NA, 0, 1) | ||
390 | MUX_CFG("R13_1710_USB1_SEO", A, 12, 5, 2, 10, 0, NA, 0, 1) | ||
391 | |||
392 | /* USB2 master */ | ||
393 | MUX_CFG("USB2_SUSP", B, 3, 1, 2, 17, 0, NA, 0, 1) | ||
394 | MUX_CFG("USB2_VP", B, 6, 1, 2, 18, 0, NA, 0, 1) | ||
395 | MUX_CFG("USB2_TXEN", B, 9, 1, 2, 19, 0, NA, 0, 1) | ||
396 | MUX_CFG("USB2_VM", C, 18, 1, 3, 0, 0, NA, 0, 1) | ||
397 | MUX_CFG("USB2_RCV", C, 21, 1, 3, 1, 0, NA, 0, 1) | ||
398 | MUX_CFG("USB2_SE0", C, 24, 2, 3, 2, 0, NA, 0, 1) | ||
399 | MUX_CFG("USB2_TXD", C, 27, 2, 3, 3, 0, NA, 0, 1) | ||
400 | |||
401 | /* OMAP-1510 GPIO */ | ||
402 | MUX_CFG("R18_1510_GPIO0", 7, 9, 0, 1, 11, 1, 0, 0, 1) | ||
403 | MUX_CFG("R19_1510_GPIO1", 7, 6, 0, 1, 10, 1, 0, 0, 1) | ||
404 | MUX_CFG("M14_1510_GPIO2", 7, 3, 0, 1, 9, 1, 0, 0, 1) | ||
405 | |||
406 | /* OMAP1610 GPIO */ | ||
407 | MUX_CFG("P18_1610_GPIO3", 7, 0, 0, 1, 8, 0, NA, 0, 1) | ||
408 | MUX_CFG("Y15_1610_GPIO17", A, 0, 7, 2, 6, 0, NA, 0, 1) | ||
409 | |||
410 | /* OMAP-1710 GPIO */ | ||
411 | MUX_CFG("R18_1710_GPIO0", 7, 9, 0, 1, 11, 1, 1, 1, 1) | ||
412 | MUX_CFG("V2_1710_GPIO10", F, 27, 1, 4, 3, 1, 4, 1, 1) | ||
413 | MUX_CFG("N21_1710_GPIO14", 6, 9, 0, 1, 1, 1, 1, 1, 1) | ||
414 | MUX_CFG("W15_1710_GPIO40", 9, 27, 7, 2, 5, 1, 2, 1, 1) | ||
415 | |||
416 | /* MPUIO */ | ||
417 | MUX_CFG("MPUIO2", 7, 18, 0, 1, 14, 1, NA, 0, 1) | ||
418 | MUX_CFG("N15_1610_MPUIO2", 7, 18, 0, 1, 14, 1, 1, 0, 1) | ||
419 | MUX_CFG("MPUIO4", 7, 15, 0, 1, 13, 1, NA, 0, 1) | ||
420 | MUX_CFG("MPUIO5", 7, 12, 0, 1, 12, 1, NA, 0, 1) | ||
421 | |||
422 | MUX_CFG("T20_1610_MPUIO5", 7, 12, 0, 1, 12, 0, 3, 0, 1) | ||
423 | MUX_CFG("W11_1610_MPUIO6", 10, 15, 2, 3, 8, 0, 3, 0, 1) | ||
424 | MUX_CFG("V10_1610_MPUIO7", A, 24, 2, 2, 14, 0, 2, 0, 1) | ||
425 | MUX_CFG("W11_1610_MPUIO9", 10, 15, 1, 3, 8, 0, 3, 0, 1) | ||
426 | MUX_CFG("V10_1610_MPUIO10", A, 24, 1, 2, 14, 0, 2, 0, 1) | ||
427 | MUX_CFG("W10_1610_MPUIO11", A, 18, 2, 2, 11, 0, 2, 0, 1) | ||
428 | MUX_CFG("E20_1610_MPUIO13", 3, 21, 1, 0, 7, 0, 0, 0, 1) | ||
429 | MUX_CFG("U20_1610_MPUIO14", 9, 6, 6, 0, 30, 0, 0, 0, 1) | ||
430 | MUX_CFG("E19_1610_MPUIO15", 3, 18, 1, 0, 6, 0, 0, 0, 1) | ||
431 | |||
432 | /* MCBSP2 */ | ||
433 | MUX_CFG("MCBSP2_CLKR", C, 6, 0, 2, 27, 1, NA, 0, 1) | ||
434 | MUX_CFG("MCBSP2_CLKX", C, 9, 0, 2, 29, 1, NA, 0, 1) | ||
435 | MUX_CFG("MCBSP2_DR", C, 0, 0, 2, 26, 1, NA, 0, 1) | ||
436 | MUX_CFG("MCBSP2_DX", C, 15, 0, 2, 31, 1, NA, 0, 1) | ||
437 | MUX_CFG("MCBSP2_FSR", C, 12, 0, 2, 30, 1, NA, 0, 1) | ||
438 | MUX_CFG("MCBSP2_FSX", C, 3, 0, 2, 27, 1, NA, 0, 1) | ||
439 | |||
440 | /* MCBSP3 NOTE: Mode must 1 for clock */ | ||
441 | MUX_CFG("MCBSP3_CLKX", 9, 3, 1, 1, 29, 0, NA, 0, 1) | ||
442 | |||
443 | /* Misc ballouts */ | ||
444 | MUX_CFG("BALLOUT_V8_ARMIO3", B, 18, 0, 2, 25, 1, NA, 0, 1) | ||
445 | MUX_CFG("N20_HDQ", 6, 18, 1, 1, 4, 0, 1, 4, 0) | ||
446 | |||
447 | /* OMAP-1610 MMC2 */ | ||
448 | MUX_CFG("W8_1610_MMC2_DAT0", B, 21, 6, 2, 23, 1, 2, 1, 1) | ||
449 | MUX_CFG("V8_1610_MMC2_DAT1", B, 27, 6, 2, 25, 1, 2, 1, 1) | ||
450 | MUX_CFG("W15_1610_MMC2_DAT2", 9, 12, 6, 2, 5, 1, 2, 1, 1) | ||
451 | MUX_CFG("R10_1610_MMC2_DAT3", B, 18, 6, 2, 22, 1, 2, 1, 1) | ||
452 | MUX_CFG("Y10_1610_MMC2_CLK", B, 3, 6, 2, 17, 0, 2, 0, 1) | ||
453 | MUX_CFG("Y8_1610_MMC2_CMD", B, 24, 6, 2, 24, 1, 2, 1, 1) | ||
454 | MUX_CFG("V9_1610_MMC2_CMDDIR", B, 12, 6, 2, 20, 0, 2, 1, 1) | ||
455 | MUX_CFG("V5_1610_MMC2_DATDIR0", B, 15, 6, 2, 21, 0, 2, 1, 1) | ||
456 | MUX_CFG("W19_1610_MMC2_DATDIR1", 8, 15, 6, 1, 23, 0, 1, 1, 1) | ||
457 | MUX_CFG("R18_1610_MMC2_CLKIN", 7, 9, 6, 1, 11, 0, 1, 11, 1) | ||
458 | |||
459 | /* OMAP-1610 External Trace Interface */ | ||
460 | MUX_CFG("M19_1610_ETM_PSTAT0", 5, 27, 1, 0, 29, 0, 0, 0, 1) | ||
461 | MUX_CFG("L15_1610_ETM_PSTAT1", 5, 24, 1, 0, 28, 0, 0, 0, 1) | ||
462 | MUX_CFG("L18_1610_ETM_PSTAT2", 5, 21, 1, 0, 27, 0, 0, 0, 1) | ||
463 | MUX_CFG("L19_1610_ETM_D0", 5, 18, 1, 0, 26, 0, 0, 0, 1) | ||
464 | MUX_CFG("J19_1610_ETM_D6", 5, 0, 1, 0, 20, 0, 0, 0, 1) | ||
465 | MUX_CFG("J18_1610_ETM_D7", 5, 27, 1, 0, 19, 0, 0, 0, 1) | ||
466 | |||
467 | /* OMAP16XX GPIO */ | ||
468 | MUX_CFG("P20_1610_GPIO4", 6, 27, 0, 1, 7, 0, 1, 1, 1) | ||
469 | MUX_CFG("V9_1610_GPIO7", B, 12, 1, 2, 20, 0, 2, 1, 1) | ||
470 | MUX_CFG("W8_1610_GPIO9", B, 21, 0, 2, 23, 0, 2, 1, 1) | ||
471 | MUX_CFG("N20_1610_GPIO11", 6, 18, 0, 1, 4, 0, 1, 1, 1) | ||
472 | MUX_CFG("N19_1610_GPIO13", 6, 12, 0, 1, 2, 0, 1, 1, 1) | ||
473 | MUX_CFG("P10_1610_GPIO22", C, 0, 7, 2, 26, 0, 2, 1, 1) | ||
474 | MUX_CFG("V5_1610_GPIO24", B, 15, 7, 2, 21, 0, 2, 1, 1) | ||
475 | MUX_CFG("AA20_1610_GPIO_41", 9, 9, 7, 1, 31, 0, 1, 1, 1) | ||
476 | MUX_CFG("W19_1610_GPIO48", 8, 15, 7, 1, 23, 1, 1, 0, 1) | ||
477 | MUX_CFG("M7_1610_GPIO62", 10, 0, 0, 4, 24, 0, 4, 0, 1) | ||
478 | MUX_CFG("V14_16XX_GPIO37", 9, 18, 7, 2, 2, 0, 2, 2, 0) | ||
479 | MUX_CFG("R9_16XX_GPIO18", C, 18, 7, 3, 0, 0, 3, 0, 0) | ||
480 | MUX_CFG("L14_16XX_GPIO49", 6, 3, 7, 0, 31, 0, 0, 31, 0) | ||
481 | |||
482 | /* OMAP-1610 uWire */ | ||
483 | MUX_CFG("V19_1610_UWIRE_SCLK", 8, 6, 0, 1, 20, 0, 1, 1, 1) | ||
484 | MUX_CFG("U18_1610_UWIRE_SDI", 8, 0, 0, 1, 18, 0, 1, 1, 1) | ||
485 | MUX_CFG("W21_1610_UWIRE_SDO", 8, 3, 0, 1, 19, 0, 1, 1, 1) | ||
486 | MUX_CFG("N14_1610_UWIRE_CS0", 8, 9, 1, 1, 21, 0, 1, 1, 1) | ||
487 | MUX_CFG("P15_1610_UWIRE_CS3", 8, 12, 1, 1, 22, 0, 1, 1, 1) | ||
488 | MUX_CFG("N15_1610_UWIRE_CS1", 7, 18, 2, 1, 14, 0, NA, 0, 1) | ||
489 | |||
490 | /* OMAP-1610 Flash */ | ||
491 | MUX_CFG("L3_1610_FLASH_CS2B_OE",10, 6, 1, NA, 0, 0, NA, 0, 1) | ||
492 | MUX_CFG("M8_1610_FLASH_CS2B_WE",10, 3, 1, NA, 0, 0, NA, 0, 1) | ||
493 | |||
494 | /* First MMC interface, same on 1510, 1610 and 1710 */ | ||
495 | MUX_CFG("MMC_CMD", A, 27, 0, 2, 15, 1, 2, 1, 1) | ||
496 | MUX_CFG("MMC_DAT1", A, 24, 0, 2, 14, 1, 2, 1, 1) | ||
497 | MUX_CFG("MMC_DAT2", A, 18, 0, 2, 12, 1, 2, 1, 1) | ||
498 | MUX_CFG("MMC_DAT0", B, 0, 0, 2, 16, 1, 2, 1, 1) | ||
499 | MUX_CFG("MMC_CLK", A, 21, 0, NA, 0, 0, NA, 0, 1) | ||
500 | MUX_CFG("MMC_DAT3", 10, 15, 0, 3, 8, 1, 3, 1, 1) | ||
501 | MUX_CFG("M15_1710_MMC_CLKI", 6, 21, 2, 0, 0, 0, NA, 0, 1) | ||
502 | MUX_CFG("P19_1710_MMC_CMDDIR", 6, 24, 6, 0, 0, 0, NA, 0, 1) | ||
503 | MUX_CFG("P20_1710_MMC_DATDIR0", 6, 27, 5, 0, 0, 0, NA, 0, 1) | ||
504 | |||
505 | /* OMAP-1610 USB0 alternate configuration */ | ||
506 | MUX_CFG("W9_USB0_TXEN", B, 9, 5, 2, 19, 0, 2, 0, 1) | ||
507 | MUX_CFG("AA9_USB0_VP", B, 6, 5, 2, 18, 0, 2, 0, 1) | ||
508 | MUX_CFG("Y5_USB0_RCV", C, 21, 5, 3, 1, 0, 1, 0, 1) | ||
509 | MUX_CFG("R9_USB0_VM", C, 18, 5, 3, 0, 0, 3, 0, 1) | ||
510 | MUX_CFG("V6_USB0_TXD", C, 27, 5, 3, 3, 0, 3, 0, 1) | ||
511 | MUX_CFG("W5_USB0_SE0", C, 24, 5, 3, 2, 0, 3, 0, 1) | ||
512 | MUX_CFG("V9_USB0_SPEED", B, 12, 5, 2, 20, 0, 2, 0, 1) | ||
513 | MUX_CFG("Y10_USB0_SUSP", B, 3, 5, 2, 17, 0, 2, 0, 1) | ||
514 | |||
515 | /* USB2 interface */ | ||
516 | MUX_CFG("W9_USB2_TXEN", B, 9, 1, NA, 0, 0, NA, 0, 1) | ||
517 | MUX_CFG("AA9_USB2_VP", B, 6, 1, NA, 0, 0, NA, 0, 1) | ||
518 | MUX_CFG("Y5_USB2_RCV", C, 21, 1, NA, 0, 0, NA, 0, 1) | ||
519 | MUX_CFG("R9_USB2_VM", C, 18, 1, NA, 0, 0, NA, 0, 1) | ||
520 | MUX_CFG("V6_USB2_TXD", C, 27, 2, NA, 0, 0, NA, 0, 1) | ||
521 | MUX_CFG("W5_USB2_SE0", C, 24, 2, NA, 0, 0, NA, 0, 1) | ||
522 | |||
523 | /* 16XX UART */ | ||
524 | MUX_CFG("R13_1610_UART1_TX", A, 12, 6, 2, 10, 0, 2, 10, 1) | ||
525 | MUX_CFG("V14_16XX_UART1_RX", 9, 18, 0, 2, 2, 0, 2, 2, 1) | ||
526 | MUX_CFG("R14_1610_UART1_CTS", 9, 15, 0, 2, 1, 0, 2, 1, 1) | ||
527 | MUX_CFG("AA15_1610_UART1_RTS", 9, 12, 1, 2, 0, 0, 2, 0, 1) | ||
528 | MUX_CFG("R9_16XX_UART2_RX", C, 18, 0, 3, 0, 0, 3, 0, 1) | ||
529 | MUX_CFG("L14_16XX_UART3_RX", 6, 3, 0, 0, 31, 0, 0, 31, 1) | ||
530 | |||
531 | /* I2C interface */ | ||
532 | MUX_CFG("I2C_SCL", 7, 24, 0, NA, 0, 0, NA, 0, 0) | ||
533 | MUX_CFG("I2C_SDA", 7, 27, 0, NA, 0, 0, NA, 0, 0) | ||
534 | |||
535 | /* Keypad */ | ||
536 | MUX_CFG("F18_1610_KBC0", 3, 15, 0, 0, 5, 1, 0, 0, 0) | ||
537 | MUX_CFG("D20_1610_KBC1", 3, 12, 0, 0, 4, 1, 0, 0, 0) | ||
538 | MUX_CFG("D19_1610_KBC2", 3, 9, 0, 0, 3, 1, 0, 0, 0) | ||
539 | MUX_CFG("E18_1610_KBC3", 3, 6, 0, 0, 2, 1, 0, 0, 0) | ||
540 | MUX_CFG("C21_1610_KBC4", 3, 3, 0, 0, 1, 1, 0, 0, 0) | ||
541 | MUX_CFG("G18_1610_KBR0", 4, 0, 0, 0, 10, 1, 0, 1, 0) | ||
542 | MUX_CFG("F19_1610_KBR1", 3, 27, 0, 0, 9, 1, 0, 1, 0) | ||
543 | MUX_CFG("H14_1610_KBR2", 3, 24, 0, 0, 8, 1, 0, 1, 0) | ||
544 | MUX_CFG("E20_1610_KBR3", 3, 21, 0, 0, 7, 1, 0, 1, 0) | ||
545 | MUX_CFG("E19_1610_KBR4", 3, 18, 0, 0, 6, 1, 0, 1, 0) | ||
546 | MUX_CFG("N19_1610_KBR5", 6, 12, 1, 1, 2, 1, 1, 1, 0) | ||
547 | |||
548 | /* Power management */ | ||
549 | MUX_CFG("T20_1610_LOW_PWR", 7, 12, 1, NA, 0, 0, NA, 0, 0) | ||
550 | |||
551 | /* MCLK Settings */ | ||
552 | MUX_CFG("V5_1710_MCLK_ON", B, 15, 0, NA, 0, 0, NA, 0, 0) | ||
553 | MUX_CFG("V5_1710_MCLK_OFF", B, 15, 6, NA, 0, 0, NA, 0, 0) | ||
554 | MUX_CFG("R10_1610_MCLK_ON", B, 18, 0, NA, 22, 0, NA, 1, 0) | ||
555 | MUX_CFG("R10_1610_MCLK_OFF", B, 18, 6, 2, 22, 1, 2, 1, 1) | ||
556 | |||
557 | /* CompactFlash controller, conflicts with MMC1 */ | ||
558 | MUX_CFG("P11_1610_CF_CD2", A, 27, 3, 2, 15, 1, 2, 1, 1) | ||
559 | MUX_CFG("R11_1610_CF_IOIS16", B, 0, 3, 2, 16, 1, 2, 1, 1) | ||
560 | MUX_CFG("V10_1610_CF_IREQ", A, 24, 3, 2, 14, 0, 2, 0, 1) | ||
561 | MUX_CFG("W10_1610_CF_RESET", A, 18, 3, 2, 12, 1, 2, 1, 1) | ||
562 | MUX_CFG("W11_1610_CF_CD1", 10, 15, 3, 3, 8, 1, 3, 1, 1) | ||
563 | }; | ||
564 | 405 | ||
565 | #endif /* __MUX_C__ */ | 406 | /* 24xx GPIO */ |
407 | Y20_24XX_GPIO60, | ||
408 | M15_24XX_GPIO92, | ||
409 | }; | ||
566 | 410 | ||
567 | #ifdef CONFIG_OMAP_MUX | 411 | #ifdef CONFIG_OMAP_MUX |
568 | /* setup pin muxing in Linux */ | 412 | /* setup pin muxing in Linux */ |
569 | extern int omap_cfg_reg(reg_cfg_t reg_cfg); | 413 | extern int omap1_mux_init(void); |
414 | extern int omap2_mux_init(void); | ||
415 | extern int omap_mux_register(struct pin_config * pins, unsigned long size); | ||
416 | extern int omap_cfg_reg(unsigned long reg_cfg); | ||
570 | #else | 417 | #else |
571 | /* boot loader does it all (no warnings from CONFIG_OMAP_MUX_WARNINGS) */ | 418 | /* boot loader does it all (no warnings from CONFIG_OMAP_MUX_WARNINGS) */ |
572 | static inline int omap_cfg_reg(reg_cfg_t reg_cfg) { return 0; } | 419 | static inline int omap1_mux_init(void) { return 0; } |
420 | static inline int omap2_mux_init(void) { return 0; } | ||
421 | static inline int omap_cfg_reg(unsigned long reg_cfg) { return 0; } | ||
573 | #endif | 422 | #endif |
574 | 423 | ||
575 | #endif | 424 | #endif |
diff --git a/include/asm-arm/arch-omap/omap1510.h b/include/asm-arm/arch-omap/omap1510.h index f086a3933906..c575d354850f 100644 --- a/include/asm-arm/arch-omap/omap1510.h +++ b/include/asm-arm/arch-omap/omap1510.h | |||
@@ -25,8 +25,8 @@ | |||
25 | * 675 Mass Ave, Cambridge, MA 02139, USA. | 25 | * 675 Mass Ave, Cambridge, MA 02139, USA. |
26 | */ | 26 | */ |
27 | 27 | ||
28 | #ifndef __ASM_ARCH_OMAP1510_H | 28 | #ifndef __ASM_ARCH_OMAP15XX_H |
29 | #define __ASM_ARCH_OMAP1510_H | 29 | #define __ASM_ARCH_OMAP15XX_H |
30 | 30 | ||
31 | /* | 31 | /* |
32 | * ---------------------------------------------------------------------------- | 32 | * ---------------------------------------------------------------------------- |
@@ -44,5 +44,5 @@ | |||
44 | #define OMAP1510_DSPREG_SIZE SZ_128K | 44 | #define OMAP1510_DSPREG_SIZE SZ_128K |
45 | #define OMAP1510_DSPREG_START 0xE1000000 | 45 | #define OMAP1510_DSPREG_START 0xE1000000 |
46 | 46 | ||
47 | #endif /* __ASM_ARCH_OMAP1510_H */ | 47 | #endif /* __ASM_ARCH_OMAP15XX_H */ |
48 | 48 | ||
diff --git a/include/asm-arm/arch-omap/omap24xx.h b/include/asm-arm/arch-omap/omap24xx.h index a9105466a417..6e59805fa654 100644 --- a/include/asm-arm/arch-omap/omap24xx.h +++ b/include/asm-arm/arch-omap/omap24xx.h | |||
@@ -1,15 +1,24 @@ | |||
1 | #ifndef __ASM_ARCH_OMAP24XX_H | 1 | #ifndef __ASM_ARCH_OMAP24XX_H |
2 | #define __ASM_ARCH_OMAP24XX_H | 2 | #define __ASM_ARCH_OMAP24XX_H |
3 | 3 | ||
4 | #define OMAP24XX_L4_IO_BASE 0x48000000 | 4 | /* |
5 | * Please place only base defines here and put the rest in device | ||
6 | * specific headers. Note also that some of these defines are needed | ||
7 | * for omap1 to compile without adding ifdefs. | ||
8 | */ | ||
9 | |||
10 | #define L4_24XX_BASE 0x48000000 | ||
11 | #define L3_24XX_BASE 0x68000000 | ||
5 | 12 | ||
6 | /* interrupt controller */ | 13 | /* interrupt controller */ |
7 | #define OMAP24XX_IC_BASE (OMAP24XX_L4_IO_BASE + 0xfe000) | 14 | #define OMAP24XX_IC_BASE (L4_24XX_BASE + 0xfe000) |
8 | #define VA_IC_BASE IO_ADDRESS(OMAP24XX_IC_BASE) | 15 | #define VA_IC_BASE IO_ADDRESS(OMAP24XX_IC_BASE) |
9 | |||
10 | #define OMAP24XX_IVA_INTC_BASE 0x40000000 | 16 | #define OMAP24XX_IVA_INTC_BASE 0x40000000 |
11 | |||
12 | #define IRQ_SIR_IRQ 0x0040 | 17 | #define IRQ_SIR_IRQ 0x0040 |
13 | 18 | ||
19 | #define OMAP24XX_32KSYNCT_BASE (L4_24XX_BASE + 0x4000) | ||
20 | #define OMAP24XX_PRCM_BASE (L4_24XX_BASE + 0x8000) | ||
21 | #define OMAP24XX_SDRC_BASE (L3_24XX_BASE + 0x9000) | ||
22 | |||
14 | #endif /* __ASM_ARCH_OMAP24XX_H */ | 23 | #endif /* __ASM_ARCH_OMAP24XX_H */ |
15 | 24 | ||
diff --git a/include/asm-arm/arch-omap/omapfb.h b/include/asm-arm/arch-omap/omapfb.h new file mode 100644 index 000000000000..4ba2622cc142 --- /dev/null +++ b/include/asm-arm/arch-omap/omapfb.h | |||
@@ -0,0 +1,281 @@ | |||
1 | /* | ||
2 | * File: include/asm-arm/arch-omap/omapfb.h | ||
3 | * | ||
4 | * Framebuffer driver for TI OMAP boards | ||
5 | * | ||
6 | * Copyright (C) 2004 Nokia Corporation | ||
7 | * Author: Imre Deak <imre.deak@nokia.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
12 | * option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License along | ||
20 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
21 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
22 | */ | ||
23 | |||
24 | #ifndef __OMAPFB_H | ||
25 | #define __OMAPFB_H | ||
26 | |||
27 | /* IOCTL commands. */ | ||
28 | |||
29 | #define OMAP_IOW(num, dtype) _IOW('O', num, dtype) | ||
30 | #define OMAP_IOR(num, dtype) _IOR('O', num, dtype) | ||
31 | #define OMAP_IOWR(num, dtype) _IOWR('O', num, dtype) | ||
32 | #define OMAP_IO(num) _IO('O', num) | ||
33 | |||
34 | #define OMAPFB_MIRROR OMAP_IOW(31, int) | ||
35 | #define OMAPFB_SYNC_GFX OMAP_IO(37) | ||
36 | #define OMAPFB_VSYNC OMAP_IO(38) | ||
37 | #define OMAPFB_SET_UPDATE_MODE OMAP_IOW(40, enum omapfb_update_mode) | ||
38 | #define OMAPFB_GET_CAPS OMAP_IOR(42, unsigned long) | ||
39 | #define OMAPFB_GET_UPDATE_MODE OMAP_IOW(43, enum omapfb_update_mode) | ||
40 | #define OMAPFB_LCD_TEST OMAP_IOW(45, int) | ||
41 | #define OMAPFB_CTRL_TEST OMAP_IOW(46, int) | ||
42 | #define OMAPFB_UPDATE_WINDOW OMAP_IOW(47, struct omapfb_update_window) | ||
43 | #define OMAPFB_SETUP_PLANE OMAP_IOW(48, struct omapfb_setup_plane) | ||
44 | #define OMAPFB_ENABLE_PLANE OMAP_IOW(49, struct omapfb_enable_plane) | ||
45 | #define OMAPFB_SET_COLOR_KEY OMAP_IOW(50, struct omapfb_color_key) | ||
46 | |||
47 | #define OMAPFB_CAPS_GENERIC_MASK 0x00000fff | ||
48 | #define OMAPFB_CAPS_LCDC_MASK 0x00fff000 | ||
49 | #define OMAPFB_CAPS_PANEL_MASK 0xff000000 | ||
50 | |||
51 | #define OMAPFB_CAPS_MANUAL_UPDATE 0x00001000 | ||
52 | #define OMAPFB_CAPS_SET_BACKLIGHT 0x01000000 | ||
53 | |||
54 | /* Values from DSP must map to lower 16-bits */ | ||
55 | #define OMAPFB_FORMAT_MASK 0x00ff | ||
56 | #define OMAPFB_FORMAT_FLAG_DOUBLE 0x0100 | ||
57 | |||
58 | enum omapfb_color_format { | ||
59 | OMAPFB_COLOR_RGB565 = 0, | ||
60 | OMAPFB_COLOR_YUV422, | ||
61 | OMAPFB_COLOR_YUV420, | ||
62 | OMAPFB_COLOR_CLUT_8BPP, | ||
63 | OMAPFB_COLOR_CLUT_4BPP, | ||
64 | OMAPFB_COLOR_CLUT_2BPP, | ||
65 | OMAPFB_COLOR_CLUT_1BPP, | ||
66 | }; | ||
67 | |||
68 | struct omapfb_update_window { | ||
69 | u32 x, y; | ||
70 | u32 width, height; | ||
71 | u32 format; | ||
72 | }; | ||
73 | |||
74 | enum omapfb_plane { | ||
75 | OMAPFB_PLANE_GFX = 0, | ||
76 | OMAPFB_PLANE_VID1, | ||
77 | OMAPFB_PLANE_VID2, | ||
78 | }; | ||
79 | |||
80 | enum omapfb_channel_out { | ||
81 | OMAPFB_CHANNEL_OUT_LCD = 0, | ||
82 | OMAPFB_CHANNEL_OUT_DIGIT, | ||
83 | }; | ||
84 | |||
85 | struct omapfb_setup_plane { | ||
86 | u8 plane; | ||
87 | u8 channel_out; | ||
88 | u32 offset; | ||
89 | u32 pos_x, pos_y; | ||
90 | u32 width, height; | ||
91 | u32 color_mode; | ||
92 | }; | ||
93 | |||
94 | struct omapfb_enable_plane { | ||
95 | u8 plane; | ||
96 | u8 enable; | ||
97 | }; | ||
98 | |||
99 | enum omapfb_color_key_type { | ||
100 | OMAPFB_COLOR_KEY_DISABLED = 0, | ||
101 | OMAPFB_COLOR_KEY_GFX_DST, | ||
102 | OMAPFB_COLOR_KEY_VID_SRC, | ||
103 | }; | ||
104 | |||
105 | struct omapfb_color_key { | ||
106 | u8 channel_out; | ||
107 | u32 background; | ||
108 | u32 trans_key; | ||
109 | u8 key_type; | ||
110 | }; | ||
111 | |||
112 | enum omapfb_update_mode { | ||
113 | OMAPFB_UPDATE_DISABLED = 0, | ||
114 | OMAPFB_AUTO_UPDATE, | ||
115 | OMAPFB_MANUAL_UPDATE | ||
116 | }; | ||
117 | |||
118 | #ifdef __KERNEL__ | ||
119 | |||
120 | #include <linux/completion.h> | ||
121 | #include <linux/interrupt.h> | ||
122 | #include <linux/fb.h> | ||
123 | |||
124 | #define OMAP_LCDC_INV_VSYNC 0x0001 | ||
125 | #define OMAP_LCDC_INV_HSYNC 0x0002 | ||
126 | #define OMAP_LCDC_INV_PIX_CLOCK 0x0004 | ||
127 | #define OMAP_LCDC_INV_OUTPUT_EN 0x0008 | ||
128 | #define OMAP_LCDC_HSVS_RISING_EDGE 0x0010 | ||
129 | #define OMAP_LCDC_HSVS_OPPOSITE 0x0020 | ||
130 | |||
131 | #define OMAP_LCDC_SIGNAL_MASK 0x003f | ||
132 | |||
133 | #define OMAP_LCDC_PANEL_TFT 0x0100 | ||
134 | |||
135 | #ifdef CONFIG_ARCH_OMAP1 | ||
136 | #define OMAPFB_PLANE_NUM 1 | ||
137 | #else | ||
138 | #define OMAPFB_PLANE_NUM 3 | ||
139 | #endif | ||
140 | |||
141 | struct omapfb_device; | ||
142 | |||
143 | struct lcd_panel { | ||
144 | const char *name; | ||
145 | int config; /* TFT/STN, signal inversion */ | ||
146 | int bpp; /* Pixel format in fb mem */ | ||
147 | int data_lines; /* Lines on LCD HW interface */ | ||
148 | |||
149 | int x_res, y_res; | ||
150 | int pixel_clock; /* In kHz */ | ||
151 | int hsw; /* Horizontal synchronization | ||
152 | pulse width */ | ||
153 | int hfp; /* Horizontal front porch */ | ||
154 | int hbp; /* Horizontal back porch */ | ||
155 | int vsw; /* Vertical synchronization | ||
156 | pulse width */ | ||
157 | int vfp; /* Vertical front porch */ | ||
158 | int vbp; /* Vertical back porch */ | ||
159 | int acb; /* ac-bias pin frequency */ | ||
160 | int pcd; /* pixel clock divider. | ||
161 | Obsolete use pixel_clock instead */ | ||
162 | |||
163 | int (*init) (struct omapfb_device *fbdev); | ||
164 | void (*cleanup) (void); | ||
165 | int (*enable) (void); | ||
166 | void (*disable) (void); | ||
167 | unsigned long (*get_caps) (void); | ||
168 | int (*set_bklight_level)(unsigned int level); | ||
169 | unsigned int (*get_bklight_level)(void); | ||
170 | unsigned int (*get_bklight_max) (void); | ||
171 | int (*run_test) (int test_num); | ||
172 | }; | ||
173 | |||
174 | struct omapfb_device; | ||
175 | |||
176 | struct extif_timings { | ||
177 | int cs_on_time; | ||
178 | int cs_off_time; | ||
179 | int we_on_time; | ||
180 | int we_off_time; | ||
181 | int re_on_time; | ||
182 | int re_off_time; | ||
183 | int we_cycle_time; | ||
184 | int re_cycle_time; | ||
185 | int cs_pulse_width; | ||
186 | int access_time; | ||
187 | }; | ||
188 | |||
189 | struct lcd_ctrl_extif { | ||
190 | int (*init) (void); | ||
191 | void (*cleanup) (void); | ||
192 | void (*set_timings) (const struct extif_timings *timings); | ||
193 | void (*write_command) (u32 cmd); | ||
194 | u32 (*read_data) (void); | ||
195 | void (*write_data) (u32 data); | ||
196 | void (*transfer_area) (int width, int height, | ||
197 | void (callback)(void * data), void *data); | ||
198 | }; | ||
199 | |||
200 | struct lcd_ctrl { | ||
201 | const char *name; | ||
202 | void *data; | ||
203 | |||
204 | int (*init) (struct omapfb_device *fbdev, | ||
205 | int ext_mode, int req_vram_size); | ||
206 | void (*cleanup) (void); | ||
207 | void (*get_vram_layout)(unsigned long *size, | ||
208 | void **virt_base, | ||
209 | dma_addr_t *phys_base); | ||
210 | unsigned long (*get_caps) (void); | ||
211 | int (*set_update_mode)(enum omapfb_update_mode mode); | ||
212 | enum omapfb_update_mode (*get_update_mode)(void); | ||
213 | int (*setup_plane) (int plane, int channel_out, | ||
214 | unsigned long offset, | ||
215 | int screen_width, | ||
216 | int pos_x, int pos_y, int width, | ||
217 | int height, int color_mode); | ||
218 | int (*enable_plane) (int plane, int enable); | ||
219 | int (*update_window) (struct omapfb_update_window *win, | ||
220 | void (*callback)(void *), | ||
221 | void *callback_data); | ||
222 | void (*sync) (void); | ||
223 | void (*suspend) (void); | ||
224 | void (*resume) (void); | ||
225 | int (*run_test) (int test_num); | ||
226 | int (*setcolreg) (u_int regno, u16 red, u16 green, | ||
227 | u16 blue, u16 transp, | ||
228 | int update_hw_mem); | ||
229 | int (*set_color_key) (struct omapfb_color_key *ck); | ||
230 | |||
231 | }; | ||
232 | |||
233 | enum omapfb_state { | ||
234 | OMAPFB_DISABLED = 0, | ||
235 | OMAPFB_SUSPENDED= 99, | ||
236 | OMAPFB_ACTIVE = 100 | ||
237 | }; | ||
238 | |||
239 | struct omapfb_device { | ||
240 | int state; | ||
241 | int ext_lcdc; /* Using external | ||
242 | LCD controller */ | ||
243 | struct semaphore rqueue_sema; | ||
244 | |||
245 | void *vram_virt_base; | ||
246 | dma_addr_t vram_phys_base; | ||
247 | unsigned long vram_size; | ||
248 | |||
249 | int color_mode; | ||
250 | int palette_size; | ||
251 | int mirror; | ||
252 | u32 pseudo_palette[17]; | ||
253 | |||
254 | struct lcd_panel *panel; /* LCD panel */ | ||
255 | struct lcd_ctrl *ctrl; /* LCD controller */ | ||
256 | struct lcd_ctrl *int_ctrl; /* internal LCD ctrl */ | ||
257 | struct lcd_ctrl_extif *ext_if; /* LCD ctrl external | ||
258 | interface */ | ||
259 | struct fb_info *fb_info; | ||
260 | |||
261 | struct device *dev; | ||
262 | }; | ||
263 | |||
264 | extern struct lcd_panel h3_panel; | ||
265 | extern struct lcd_panel h2_panel; | ||
266 | extern struct lcd_panel p2_panel; | ||
267 | extern struct lcd_panel osk_panel; | ||
268 | extern struct lcd_panel innovator1610_panel; | ||
269 | extern struct lcd_panel innovator1510_panel; | ||
270 | |||
271 | #ifdef CONFIG_ARCH_OMAP1 | ||
272 | extern struct lcd_ctrl omap1_lcd_ctrl; | ||
273 | #else | ||
274 | extern struct lcd_ctrl omap2_disp_ctrl; | ||
275 | #endif | ||
276 | |||
277 | extern void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval); | ||
278 | |||
279 | #endif /* __KERNEL__ */ | ||
280 | |||
281 | #endif /* __OMAPFB_H */ | ||
diff --git a/include/asm-arm/arch-omap/pm.h b/include/asm-arm/arch-omap/pm.h index fbd742d0c499..7c790425e363 100644 --- a/include/asm-arm/arch-omap/pm.h +++ b/include/asm-arm/arch-omap/pm.h | |||
@@ -98,7 +98,14 @@ | |||
98 | #define OMAP1610_IDLECT3 0xfffece24 | 98 | #define OMAP1610_IDLECT3 0xfffece24 |
99 | #define OMAP1610_IDLE_LOOP_REQUEST 0x0400 | 99 | #define OMAP1610_IDLE_LOOP_REQUEST 0x0400 |
100 | 100 | ||
101 | #if !defined(CONFIG_ARCH_OMAP1510) && \ | 101 | #define OMAP730_IDLECT1_SLEEP_VAL 0x16c7 |
102 | #define OMAP730_IDLECT2_SLEEP_VAL 0x09c7 | ||
103 | #define OMAP730_IDLECT3_VAL 0x3f | ||
104 | #define OMAP730_IDLECT3 0xfffece24 | ||
105 | #define OMAP730_IDLE_LOOP_REQUEST 0x0C00 | ||
106 | |||
107 | #if !defined(CONFIG_ARCH_OMAP730) && \ | ||
108 | !defined(CONFIG_ARCH_OMAP15XX) && \ | ||
102 | !defined(CONFIG_ARCH_OMAP16XX) && \ | 109 | !defined(CONFIG_ARCH_OMAP16XX) && \ |
103 | !defined(CONFIG_ARCH_OMAP24XX) | 110 | !defined(CONFIG_ARCH_OMAP24XX) |
104 | #error "Power management for this processor not implemented yet" | 111 | #error "Power management for this processor not implemented yet" |
@@ -107,8 +114,10 @@ | |||
107 | #ifndef __ASSEMBLER__ | 114 | #ifndef __ASSEMBLER__ |
108 | extern void omap_pm_idle(void); | 115 | extern void omap_pm_idle(void); |
109 | extern void omap_pm_suspend(void); | 116 | extern void omap_pm_suspend(void); |
117 | extern void omap730_cpu_suspend(unsigned short, unsigned short); | ||
110 | extern void omap1510_cpu_suspend(unsigned short, unsigned short); | 118 | extern void omap1510_cpu_suspend(unsigned short, unsigned short); |
111 | extern void omap1610_cpu_suspend(unsigned short, unsigned short); | 119 | extern void omap1610_cpu_suspend(unsigned short, unsigned short); |
120 | extern void omap730_idle_loop_suspend(void); | ||
112 | extern void omap1510_idle_loop_suspend(void); | 121 | extern void omap1510_idle_loop_suspend(void); |
113 | extern void omap1610_idle_loop_suspend(void); | 122 | extern void omap1610_idle_loop_suspend(void); |
114 | 123 | ||
@@ -118,6 +127,8 @@ extern void omap_serial_wake_trigger(int enable); | |||
118 | #define omap_serial_wake_trigger(x) {} | 127 | #define omap_serial_wake_trigger(x) {} |
119 | #endif /* CONFIG_OMAP_SERIAL_WAKE */ | 128 | #endif /* CONFIG_OMAP_SERIAL_WAKE */ |
120 | 129 | ||
130 | extern unsigned int omap730_cpu_suspend_sz; | ||
131 | extern unsigned int omap730_idle_loop_suspend_sz; | ||
121 | extern unsigned int omap1510_cpu_suspend_sz; | 132 | extern unsigned int omap1510_cpu_suspend_sz; |
122 | extern unsigned int omap1510_idle_loop_suspend_sz; | 133 | extern unsigned int omap1510_idle_loop_suspend_sz; |
123 | extern unsigned int omap1610_cpu_suspend_sz; | 134 | extern unsigned int omap1610_cpu_suspend_sz; |
@@ -131,6 +142,10 @@ extern unsigned int omap1610_idle_loop_suspend_sz; | |||
131 | #define ULPD_RESTORE(x) omap_writew((ulpd_sleep_save[ULPD_SLEEP_SAVE_##x]), (x)) | 142 | #define ULPD_RESTORE(x) omap_writew((ulpd_sleep_save[ULPD_SLEEP_SAVE_##x]), (x)) |
132 | #define ULPD_SHOW(x) ulpd_sleep_save[ULPD_SLEEP_SAVE_##x] | 143 | #define ULPD_SHOW(x) ulpd_sleep_save[ULPD_SLEEP_SAVE_##x] |
133 | 144 | ||
145 | #define MPUI730_SAVE(x) mpui730_sleep_save[MPUI730_SLEEP_SAVE_##x] = omap_readl(x) | ||
146 | #define MPUI730_RESTORE(x) omap_writel((mpui730_sleep_save[MPUI730_SLEEP_SAVE_##x]), (x)) | ||
147 | #define MPUI730_SHOW(x) mpui730_sleep_save[MPUI730_SLEEP_SAVE_##x] | ||
148 | |||
134 | #define MPUI1510_SAVE(x) mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_##x] = omap_readl(x) | 149 | #define MPUI1510_SAVE(x) mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_##x] = omap_readl(x) |
135 | #define MPUI1510_RESTORE(x) omap_writel((mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_##x]), (x)) | 150 | #define MPUI1510_RESTORE(x) omap_writel((mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_##x]), (x)) |
136 | #define MPUI1510_SHOW(x) mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_##x] | 151 | #define MPUI1510_SHOW(x) mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_##x] |
@@ -188,13 +203,34 @@ enum mpui1510_save_state { | |||
188 | MPUI1510_SLEEP_SAVE_EMIFS_CONFIG, | 203 | MPUI1510_SLEEP_SAVE_EMIFS_CONFIG, |
189 | MPUI1510_SLEEP_SAVE_OMAP_IH1_MIR, | 204 | MPUI1510_SLEEP_SAVE_OMAP_IH1_MIR, |
190 | MPUI1510_SLEEP_SAVE_OMAP_IH2_MIR, | 205 | MPUI1510_SLEEP_SAVE_OMAP_IH2_MIR, |
191 | #if defined(CONFIG_ARCH_OMAP1510) | 206 | #if defined(CONFIG_ARCH_OMAP15XX) |
192 | MPUI1510_SLEEP_SAVE_SIZE | 207 | MPUI1510_SLEEP_SAVE_SIZE |
193 | #else | 208 | #else |
194 | MPUI1510_SLEEP_SAVE_SIZE = 0 | 209 | MPUI1510_SLEEP_SAVE_SIZE = 0 |
195 | #endif | 210 | #endif |
196 | }; | 211 | }; |
197 | 212 | ||
213 | enum mpui730_save_state { | ||
214 | MPUI730_SLEEP_SAVE_START = 0, | ||
215 | /* | ||
216 | * MPUI registers 32 bits | ||
217 | */ | ||
218 | MPUI730_SLEEP_SAVE_MPUI_CTRL, | ||
219 | MPUI730_SLEEP_SAVE_MPUI_DSP_BOOT_CONFIG, | ||
220 | MPUI730_SLEEP_SAVE_MPUI_DSP_API_CONFIG, | ||
221 | MPUI730_SLEEP_SAVE_MPUI_DSP_STATUS, | ||
222 | MPUI730_SLEEP_SAVE_EMIFF_SDRAM_CONFIG, | ||
223 | MPUI730_SLEEP_SAVE_EMIFS_CONFIG, | ||
224 | MPUI730_SLEEP_SAVE_OMAP_IH1_MIR, | ||
225 | MPUI730_SLEEP_SAVE_OMAP_IH2_0_MIR, | ||
226 | MPUI730_SLEEP_SAVE_OMAP_IH2_1_MIR, | ||
227 | #if defined(CONFIG_ARCH_OMAP730) | ||
228 | MPUI730_SLEEP_SAVE_SIZE | ||
229 | #else | ||
230 | MPUI730_SLEEP_SAVE_SIZE = 0 | ||
231 | #endif | ||
232 | }; | ||
233 | |||
198 | enum mpui1610_save_state { | 234 | enum mpui1610_save_state { |
199 | MPUI1610_SLEEP_SAVE_START = 0, | 235 | MPUI1610_SLEEP_SAVE_START = 0, |
200 | /* | 236 | /* |
diff --git a/include/asm-arm/arch-omap/prcm.h b/include/asm-arm/arch-omap/prcm.h new file mode 100644 index 000000000000..7b48a5cbb15f --- /dev/null +++ b/include/asm-arm/arch-omap/prcm.h | |||
@@ -0,0 +1,429 @@ | |||
1 | /* | ||
2 | * prcm.h - Access definations for use in OMAP24XX clock and power management | ||
3 | * | ||
4 | * Copyright (C) 2005 Texas Instruments, Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #ifndef __ASM_ARM_ARCH_DPM_PRCM_H | ||
22 | #define __ASM_ARM_ARCH_DPM_PRCM_H | ||
23 | |||
24 | /* SET_PERFORMANCE_LEVEL PARAMETERS */ | ||
25 | #define PRCM_HALF_SPEED 1 | ||
26 | #define PRCM_FULL_SPEED 2 | ||
27 | |||
28 | #ifndef __ASSEMBLER__ | ||
29 | |||
30 | #define PRCM_REG32(offset) __REG32(OMAP24XX_PRCM_BASE + (offset)) | ||
31 | |||
32 | #define PRCM_REVISION PRCM_REG32(0x000) | ||
33 | #define PRCM_SYSCONFIG PRCM_REG32(0x010) | ||
34 | #define PRCM_IRQSTATUS_MPU PRCM_REG32(0x018) | ||
35 | #define PRCM_IRQENABLE_MPU PRCM_REG32(0x01C) | ||
36 | #define PRCM_VOLTCTRL PRCM_REG32(0x050) | ||
37 | #define PRCM_VOLTST PRCM_REG32(0x054) | ||
38 | #define PRCM_CLKSRC_CTRL PRCM_REG32(0x060) | ||
39 | #define PRCM_CLKOUT_CTRL PRCM_REG32(0x070) | ||
40 | #define PRCM_CLKEMUL_CTRL PRCM_REG32(0x078) | ||
41 | #define PRCM_CLKCFG_CTRL PRCM_REG32(0x080) | ||
42 | #define PRCM_CLKCFG_STATUS PRCM_REG32(0x084) | ||
43 | #define PRCM_VOLTSETUP PRCM_REG32(0x090) | ||
44 | #define PRCM_CLKSSETUP PRCM_REG32(0x094) | ||
45 | #define PRCM_POLCTRL PRCM_REG32(0x098) | ||
46 | |||
47 | /* GENERAL PURPOSE */ | ||
48 | #define GENERAL_PURPOSE1 PRCM_REG32(0x0B0) | ||
49 | #define GENERAL_PURPOSE2 PRCM_REG32(0x0B4) | ||
50 | #define GENERAL_PURPOSE3 PRCM_REG32(0x0B8) | ||
51 | #define GENERAL_PURPOSE4 PRCM_REG32(0x0BC) | ||
52 | #define GENERAL_PURPOSE5 PRCM_REG32(0x0C0) | ||
53 | #define GENERAL_PURPOSE6 PRCM_REG32(0x0C4) | ||
54 | #define GENERAL_PURPOSE7 PRCM_REG32(0x0C8) | ||
55 | #define GENERAL_PURPOSE8 PRCM_REG32(0x0CC) | ||
56 | #define GENERAL_PURPOSE9 PRCM_REG32(0x0D0) | ||
57 | #define GENERAL_PURPOSE10 PRCM_REG32(0x0D4) | ||
58 | #define GENERAL_PURPOSE11 PRCM_REG32(0x0D8) | ||
59 | #define GENERAL_PURPOSE12 PRCM_REG32(0x0DC) | ||
60 | #define GENERAL_PURPOSE13 PRCM_REG32(0x0E0) | ||
61 | #define GENERAL_PURPOSE14 PRCM_REG32(0x0E4) | ||
62 | #define GENERAL_PURPOSE15 PRCM_REG32(0x0E8) | ||
63 | #define GENERAL_PURPOSE16 PRCM_REG32(0x0EC) | ||
64 | #define GENERAL_PURPOSE17 PRCM_REG32(0x0F0) | ||
65 | #define GENERAL_PURPOSE18 PRCM_REG32(0x0F4) | ||
66 | #define GENERAL_PURPOSE19 PRCM_REG32(0x0F8) | ||
67 | #define GENERAL_PURPOSE20 PRCM_REG32(0x0FC) | ||
68 | |||
69 | /* MPU */ | ||
70 | #define CM_CLKSEL_MPU PRCM_REG32(0x140) | ||
71 | #define CM_CLKSTCTRL_MPU PRCM_REG32(0x148) | ||
72 | #define RM_RSTST_MPU PRCM_REG32(0x158) | ||
73 | #define PM_WKDEP_MPU PRCM_REG32(0x1C8) | ||
74 | #define PM_EVGENCTRL_MPU PRCM_REG32(0x1D4) | ||
75 | #define PM_EVEGENONTIM_MPU PRCM_REG32(0x1D8) | ||
76 | #define PM_EVEGENOFFTIM_MPU PRCM_REG32(0x1DC) | ||
77 | #define PM_PWSTCTRL_MPU PRCM_REG32(0x1E0) | ||
78 | #define PM_PWSTST_MPU PRCM_REG32(0x1E4) | ||
79 | |||
80 | /* CORE */ | ||
81 | #define CM_FCLKEN1_CORE PRCM_REG32(0x200) | ||
82 | #define CM_FCLKEN2_CORE PRCM_REG32(0x204) | ||
83 | #define CM_FCLKEN3_CORE PRCM_REG32(0x208) | ||
84 | #define CM_ICLKEN1_CORE PRCM_REG32(0x210) | ||
85 | #define CM_ICLKEN2_CORE PRCM_REG32(0x214) | ||
86 | #define CM_ICLKEN3_CORE PRCM_REG32(0x218) | ||
87 | #define CM_ICLKEN4_CORE PRCM_REG32(0x21C) | ||
88 | #define CM_IDLEST1_CORE PRCM_REG32(0x220) | ||
89 | #define CM_IDLEST2_CORE PRCM_REG32(0x224) | ||
90 | #define CM_IDLEST3_CORE PRCM_REG32(0x228) | ||
91 | #define CM_IDLEST4_CORE PRCM_REG32(0x22C) | ||
92 | #define CM_AUTOIDLE1_CORE PRCM_REG32(0x230) | ||
93 | #define CM_AUTOIDLE2_CORE PRCM_REG32(0x234) | ||
94 | #define CM_AUTOIDLE3_CORE PRCM_REG32(0x238) | ||
95 | #define CM_AUTOIDLE4_CORE PRCM_REG32(0x23C) | ||
96 | #define CM_CLKSEL1_CORE PRCM_REG32(0x240) | ||
97 | #define CM_CLKSEL2_CORE PRCM_REG32(0x244) | ||
98 | #define CM_CLKSTCTRL_CORE PRCM_REG32(0x248) | ||
99 | #define PM_WKEN1_CORE PRCM_REG32(0x2A0) | ||
100 | #define PM_WKEN2_CORE PRCM_REG32(0x2A4) | ||
101 | #define PM_WKST1_CORE PRCM_REG32(0x2B0) | ||
102 | #define PM_WKST2_CORE PRCM_REG32(0x2B4) | ||
103 | #define PM_WKDEP_CORE PRCM_REG32(0x2C8) | ||
104 | #define PM_PWSTCTRL_CORE PRCM_REG32(0x2E0) | ||
105 | #define PM_PWSTST_CORE PRCM_REG32(0x2E4) | ||
106 | |||
107 | /* GFX */ | ||
108 | #define CM_FCLKEN_GFX PRCM_REG32(0x300) | ||
109 | #define CM_ICLKEN_GFX PRCM_REG32(0x310) | ||
110 | #define CM_IDLEST_GFX PRCM_REG32(0x320) | ||
111 | #define CM_CLKSEL_GFX PRCM_REG32(0x340) | ||
112 | #define CM_CLKSTCTRL_GFX PRCM_REG32(0x348) | ||
113 | #define RM_RSTCTRL_GFX PRCM_REG32(0x350) | ||
114 | #define RM_RSTST_GFX PRCM_REG32(0x358) | ||
115 | #define PM_WKDEP_GFX PRCM_REG32(0x3C8) | ||
116 | #define PM_PWSTCTRL_GFX PRCM_REG32(0x3E0) | ||
117 | #define PM_PWSTST_GFX PRCM_REG32(0x3E4) | ||
118 | |||
119 | /* WAKE-UP */ | ||
120 | #define CM_FCLKEN_WKUP PRCM_REG32(0x400) | ||
121 | #define CM_ICLKEN_WKUP PRCM_REG32(0x410) | ||
122 | #define CM_IDLEST_WKUP PRCM_REG32(0x420) | ||
123 | #define CM_AUTOIDLE_WKUP PRCM_REG32(0x430) | ||
124 | #define CM_CLKSEL_WKUP PRCM_REG32(0x440) | ||
125 | #define RM_RSTCTRL_WKUP PRCM_REG32(0x450) | ||
126 | #define RM_RSTTIME_WKUP PRCM_REG32(0x454) | ||
127 | #define RM_RSTST_WKUP PRCM_REG32(0x458) | ||
128 | #define PM_WKEN_WKUP PRCM_REG32(0x4A0) | ||
129 | #define PM_WKST_WKUP PRCM_REG32(0x4B0) | ||
130 | |||
131 | /* CLOCKS */ | ||
132 | #define CM_CLKEN_PLL PRCM_REG32(0x500) | ||
133 | #define CM_IDLEST_CKGEN PRCM_REG32(0x520) | ||
134 | #define CM_AUTOIDLE_PLL PRCM_REG32(0x530) | ||
135 | #define CM_CLKSEL1_PLL PRCM_REG32(0x540) | ||
136 | #define CM_CLKSEL2_PLL PRCM_REG32(0x544) | ||
137 | |||
138 | /* DSP */ | ||
139 | #define CM_FCLKEN_DSP PRCM_REG32(0x800) | ||
140 | #define CM_ICLKEN_DSP PRCM_REG32(0x810) | ||
141 | #define CM_IDLEST_DSP PRCM_REG32(0x820) | ||
142 | #define CM_AUTOIDLE_DSP PRCM_REG32(0x830) | ||
143 | #define CM_CLKSEL_DSP PRCM_REG32(0x840) | ||
144 | #define CM_CLKSTCTRL_DSP PRCM_REG32(0x848) | ||
145 | #define RM_RSTCTRL_DSP PRCM_REG32(0x850) | ||
146 | #define RM_RSTST_DSP PRCM_REG32(0x858) | ||
147 | #define PM_WKEN_DSP PRCM_REG32(0x8A0) | ||
148 | #define PM_WKDEP_DSP PRCM_REG32(0x8C8) | ||
149 | #define PM_PWSTCTRL_DSP PRCM_REG32(0x8E0) | ||
150 | #define PM_PWSTST_DSP PRCM_REG32(0x8E4) | ||
151 | #define PRCM_IRQSTATUS_DSP PRCM_REG32(0x8F0) | ||
152 | #define PRCM_IRQENABLE_DSP PRCM_REG32(0x8F4) | ||
153 | |||
154 | /* IVA */ | ||
155 | #define PRCM_IRQSTATUS_IVA PRCM_REG32(0x8F8) | ||
156 | #define PRCM_IRQENABLE_IVA PRCM_REG32(0x8FC) | ||
157 | |||
158 | /* Modem on 2430 */ | ||
159 | #define CM_FCLKEN_MDM PRCM_REG32(0xC00) | ||
160 | #define CM_ICLKEN_MDM PRCM_REG32(0xC10) | ||
161 | #define CM_IDLEST_MDM PRCM_REG32(0xC20) | ||
162 | #define CM_CLKSEL_MDM PRCM_REG32(0xC40) | ||
163 | |||
164 | /* FIXME: Move to header for 2430 */ | ||
165 | #define DISP_BASE (OMAP24XX_L4_IO_BASE+0x50000) | ||
166 | #define DISP_REG32(offset) __REG32(DISP_BASE + (offset)) | ||
167 | |||
168 | #define OMAP24XX_GPMC_BASE (L3_24XX_BASE + 0xa000) | ||
169 | #define GPMC_BASE (OMAP24XX_GPMC_BASE) | ||
170 | #define GPMC_REG32(offset) __REG32(GPMC_BASE + (offset)) | ||
171 | |||
172 | #define GPT1_BASE (OMAP24XX_GPT1) | ||
173 | #define GPT1_REG32(offset) __REG32(GPT1_BASE + (offset)) | ||
174 | |||
175 | /* Misc sysconfig */ | ||
176 | #define DISPC_SYSCONFIG DISP_REG32(0x410) | ||
177 | #define SPI_BASE (OMAP24XX_L4_IO_BASE+0x98000) | ||
178 | #define MCSPI1_SYSCONFIG __REG32(SPI_BASE + 0x10) | ||
179 | #define MCSPI2_SYSCONFIG __REG32(SPI_BASE+0x2000 + 0x10) | ||
180 | |||
181 | //#define DSP_MMU_SYSCONFIG 0x5A000010 | ||
182 | #define CAMERA_MMU_SYSCONFIG __REG32(DISP_BASE+0x2C10) | ||
183 | //#define IVA_MMU_SYSCONFIG 0x5D000010 | ||
184 | //#define DSP_DMA_SYSCONFIG 0x00FCC02C | ||
185 | #define CAMERA_DMA_SYSCONFIG __REG32(DISP_BASE+0x282C) | ||
186 | #define SYSTEM_DMA_SYSCONFIG __REG32(DISP_BASE+0x602C) | ||
187 | #define GPMC_SYSCONFIG GPMC_REG32(0x010) | ||
188 | #define MAILBOXES_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE+0x94010) | ||
189 | #define UART1_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE+0x6A054) | ||
190 | #define UART2_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE+0x6C054) | ||
191 | #define UART3_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE+0x6E054) | ||
192 | //#define IVA_SYSCONFIG 0x5C060010 | ||
193 | #define SDRC_SYSCONFIG __REG32(OMAP24XX_SDRC_BASE+0x10) | ||
194 | #define SMS_SYSCONFIG __REG32(OMAP24XX_SMS_BASE+0x10) | ||
195 | #define SSI_SYSCONFIG __REG32(DISP_BASE+0x8010) | ||
196 | //#define VLYNQ_SYSCONFIG 0x67FFFE10 | ||
197 | |||
198 | /* rkw - good cannidates for PM_ to start what nm was trying */ | ||
199 | #define OMAP24XX_GPT2 (OMAP24XX_L4_IO_BASE+0x2A000) | ||
200 | #define OMAP24XX_GPT3 (OMAP24XX_L4_IO_BASE+0x78000) | ||
201 | #define OMAP24XX_GPT4 (OMAP24XX_L4_IO_BASE+0x7A000) | ||
202 | #define OMAP24XX_GPT5 (OMAP24XX_L4_IO_BASE+0x7C000) | ||
203 | #define OMAP24XX_GPT6 (OMAP24XX_L4_IO_BASE+0x7E000) | ||
204 | #define OMAP24XX_GPT7 (OMAP24XX_L4_IO_BASE+0x80000) | ||
205 | #define OMAP24XX_GPT8 (OMAP24XX_L4_IO_BASE+0x82000) | ||
206 | #define OMAP24XX_GPT9 (OMAP24XX_L4_IO_BASE+0x84000) | ||
207 | #define OMAP24XX_GPT10 (OMAP24XX_L4_IO_BASE+0x86000) | ||
208 | #define OMAP24XX_GPT11 (OMAP24XX_L4_IO_BASE+0x88000) | ||
209 | #define OMAP24XX_GPT12 (OMAP24XX_L4_IO_BASE+0x8A000) | ||
210 | |||
211 | #define GPTIMER1_SYSCONFIG GPT1_REG32(0x010) | ||
212 | #define GPTIMER2_SYSCONFIG __REG32(OMAP24XX_GPT2 + 0x10) | ||
213 | #define GPTIMER3_SYSCONFIG __REG32(OMAP24XX_GPT3 + 0x10) | ||
214 | #define GPTIMER4_SYSCONFIG __REG32(OMAP24XX_GPT4 + 0x10) | ||
215 | #define GPTIMER5_SYSCONFIG __REG32(OMAP24XX_GPT5 + 0x10) | ||
216 | #define GPTIMER6_SYSCONFIG __REG32(OMAP24XX_GPT6 + 0x10) | ||
217 | #define GPTIMER7_SYSCONFIG __REG32(OMAP24XX_GPT7 + 0x10) | ||
218 | #define GPTIMER8_SYSCONFIG __REG32(OMAP24XX_GPT8 + 0x10) | ||
219 | #define GPTIMER9_SYSCONFIG __REG32(OMAP24XX_GPT9 + 0x10) | ||
220 | #define GPTIMER10_SYSCONFIG __REG32(OMAP24XX_GPT10 + 0x10) | ||
221 | #define GPTIMER11_SYSCONFIG __REG32(OMAP24XX_GPT11 + 0x10) | ||
222 | #define GPTIMER12_SYSCONFIG __REG32(OMAP24XX_GPT12 + 0x10) | ||
223 | |||
224 | #define GPIOX_BASE(X) (OMAP24XX_GPIO_BASE+(0x2000*((X)-1))) | ||
225 | |||
226 | #define GPIO1_SYSCONFIG __REG32((GPIOX_BASE(1)+0x10)) | ||
227 | #define GPIO2_SYSCONFIG __REG32((GPIOX_BASE(2)+0x10)) | ||
228 | #define GPIO3_SYSCONFIG __REG32((GPIOX_BASE(3)+0x10)) | ||
229 | #define GPIO4_SYSCONFIG __REG32((GPIOX_BASE(4)+0x10)) | ||
230 | |||
231 | /* GP TIMER 1 */ | ||
232 | #define GPTIMER1_TISTAT GPT1_REG32(0x014) | ||
233 | #define GPTIMER1_TISR GPT1_REG32(0x018) | ||
234 | #define GPTIMER1_TIER GPT1_REG32(0x01C) | ||
235 | #define GPTIMER1_TWER GPT1_REG32(0x020) | ||
236 | #define GPTIMER1_TCLR GPT1_REG32(0x024) | ||
237 | #define GPTIMER1_TCRR GPT1_REG32(0x028) | ||
238 | #define GPTIMER1_TLDR GPT1_REG32(0x02C) | ||
239 | #define GPTIMER1_TTGR GPT1_REG32(0x030) | ||
240 | #define GPTIMER1_TWPS GPT1_REG32(0x034) | ||
241 | #define GPTIMER1_TMAR GPT1_REG32(0x038) | ||
242 | #define GPTIMER1_TCAR1 GPT1_REG32(0x03C) | ||
243 | #define GPTIMER1_TSICR GPT1_REG32(0x040) | ||
244 | #define GPTIMER1_TCAR2 GPT1_REG32(0x044) | ||
245 | |||
246 | /* rkw -- base fix up please... */ | ||
247 | #define GPTIMER3_TISR __REG32(OMAP24XX_L4_IO_BASE+0x78018) | ||
248 | |||
249 | /* SDRC */ | ||
250 | #define SDRC_DLLA_CTRL __REG32(OMAP24XX_SDRC_BASE+0x060) | ||
251 | #define SDRC_DLLA_STATUS __REG32(OMAP24XX_SDRC_BASE+0x064) | ||
252 | #define SDRC_DLLB_CTRL __REG32(OMAP24XX_SDRC_BASE+0x068) | ||
253 | #define SDRC_DLLB_STATUS __REG32(OMAP24XX_SDRC_BASE+0x06C) | ||
254 | #define SDRC_POWER __REG32(OMAP24XX_SDRC_BASE+0x070) | ||
255 | #define SDRC_MR_0 __REG32(OMAP24XX_SDRC_BASE+0x084) | ||
256 | |||
257 | /* GPIO 1 */ | ||
258 | #define GPIO1_BASE GPIOX_BASE(1) | ||
259 | #define GPIO1_REG32(offset) __REG32(GPIO1_BASE + (offset)) | ||
260 | #define GPIO1_IRQENABLE1 GPIO1_REG32(0x01C) | ||
261 | #define GPIO1_IRQSTATUS1 GPIO1_REG32(0x018) | ||
262 | #define GPIO1_IRQENABLE2 GPIO1_REG32(0x02C) | ||
263 | #define GPIO1_IRQSTATUS2 GPIO1_REG32(0x028) | ||
264 | #define GPIO1_WAKEUPENABLE GPIO1_REG32(0x020) | ||
265 | #define GPIO1_RISINGDETECT GPIO1_REG32(0x048) | ||
266 | #define GPIO1_DATAIN GPIO1_REG32(0x038) | ||
267 | #define GPIO1_OE GPIO1_REG32(0x034) | ||
268 | #define GPIO1_DATAOUT GPIO1_REG32(0x03C) | ||
269 | |||
270 | /* GPIO2 */ | ||
271 | #define GPIO2_BASE GPIOX_BASE(2) | ||
272 | #define GPIO2_REG32(offset) __REG32(GPIO2_BASE + (offset)) | ||
273 | #define GPIO2_IRQENABLE1 GPIO2_REG32(0x01C) | ||
274 | #define GPIO2_IRQSTATUS1 GPIO2_REG32(0x018) | ||
275 | #define GPIO2_IRQENABLE2 GPIO2_REG32(0x02C) | ||
276 | #define GPIO2_IRQSTATUS2 GPIO2_REG32(0x028) | ||
277 | #define GPIO2_WAKEUPENABLE GPIO2_REG32(0x020) | ||
278 | #define GPIO2_RISINGDETECT GPIO2_REG32(0x048) | ||
279 | #define GPIO2_DATAIN GPIO2_REG32(0x038) | ||
280 | #define GPIO2_OE GPIO2_REG32(0x034) | ||
281 | #define GPIO2_DATAOUT GPIO2_REG32(0x03C) | ||
282 | |||
283 | /* GPIO 3 */ | ||
284 | #define GPIO3_BASE GPIOX_BASE(3) | ||
285 | #define GPIO3_REG32(offset) __REG32(GPIO3_BASE + (offset)) | ||
286 | #define GPIO3_IRQENABLE1 GPIO3_REG32(0x01C) | ||
287 | #define GPIO3_IRQSTATUS1 GPIO3_REG32(0x018) | ||
288 | #define GPIO3_IRQENABLE2 GPIO3_REG32(0x02C) | ||
289 | #define GPIO3_IRQSTATUS2 GPIO3_REG32(0x028) | ||
290 | #define GPIO3_WAKEUPENABLE GPIO3_REG32(0x020) | ||
291 | #define GPIO3_RISINGDETECT GPIO3_REG32(0x048) | ||
292 | #define GPIO3_FALLINGDETECT GPIO3_REG32(0x04C) | ||
293 | #define GPIO3_DATAIN GPIO3_REG32(0x038) | ||
294 | #define GPIO3_OE GPIO3_REG32(0x034) | ||
295 | #define GPIO3_DATAOUT GPIO3_REG32(0x03C) | ||
296 | #define GPIO3_DEBOUNCENABLE GPIO3_REG32(0x050) | ||
297 | #define GPIO3_DEBOUNCINGTIME GPIO3_REG32(0x054) | ||
298 | |||
299 | /* GPIO 4 */ | ||
300 | #define GPIO4_BASE GPIOX_BASE(4) | ||
301 | #define GPIO4_REG32(offset) __REG32(GPIO4_BASE + (offset)) | ||
302 | #define GPIO4_IRQENABLE1 GPIO4_REG32(0x01C) | ||
303 | #define GPIO4_IRQSTATUS1 GPIO4_REG32(0x018) | ||
304 | #define GPIO4_IRQENABLE2 GPIO4_REG32(0x02C) | ||
305 | #define GPIO4_IRQSTATUS2 GPIO4_REG32(0x028) | ||
306 | #define GPIO4_WAKEUPENABLE GPIO4_REG32(0x020) | ||
307 | #define GPIO4_RISINGDETECT GPIO4_REG32(0x048) | ||
308 | #define GPIO4_FALLINGDETECT GPIO4_REG32(0x04C) | ||
309 | #define GPIO4_DATAIN GPIO4_REG32(0x038) | ||
310 | #define GPIO4_OE GPIO4_REG32(0x034) | ||
311 | #define GPIO4_DATAOUT GPIO4_REG32(0x03C) | ||
312 | #define GPIO4_DEBOUNCENABLE GPIO4_REG32(0x050) | ||
313 | #define GPIO4_DEBOUNCINGTIME GPIO4_REG32(0x054) | ||
314 | |||
315 | |||
316 | /* IO CONFIG */ | ||
317 | #define CONTROL_BASE (OMAP24XX_CTRL_BASE) | ||
318 | #define CONTROL_REG32(offset) __REG32(CONTROL_BASE + (offset)) | ||
319 | |||
320 | #define CONTROL_PADCONF_SPI1_NCS2 CONTROL_REG32(0x104) | ||
321 | #define CONTROL_PADCONF_SYS_XTALOUT CONTROL_REG32(0x134) | ||
322 | #define CONTROL_PADCONF_UART1_RX CONTROL_REG32(0x0C8) | ||
323 | #define CONTROL_PADCONF_MCBSP1_DX CONTROL_REG32(0x10C) | ||
324 | #define CONTROL_PADCONF_GPMC_NCS4 CONTROL_REG32(0x090) | ||
325 | #define CONTROL_PADCONF_DSS_D5 CONTROL_REG32(0x0B8) | ||
326 | #define CONTROL_PADCONF_DSS_D9 CONTROL_REG32(0x0BC) | ||
327 | #define CONTROL_PADCONF_DSS_D13 CONTROL_REG32(0x0C0) | ||
328 | #define CONTROL_PADCONF_DSS_VSYNC CONTROL_REG32(0x0CC) | ||
329 | |||
330 | /* CONTROL */ | ||
331 | #define CONTROL_DEVCONF CONTROL_REG32(0x274) | ||
332 | |||
333 | /* INTERRUPT CONTROLLER */ | ||
334 | #define INTC_BASE (OMAP24XX_L4_IO_BASE+0xfe000) | ||
335 | #define INTC_REG32(offset) __REG32(INTC_BASE + (offset)) | ||
336 | |||
337 | #define INTC1_U_BASE INTC_REG32(0x000) | ||
338 | #define INTC_MIR0 INTC_REG32(0x084) | ||
339 | #define INTC_MIR_SET0 INTC_REG32(0x08C) | ||
340 | #define INTC_MIR_CLEAR0 INTC_REG32(0x088) | ||
341 | #define INTC_ISR_CLEAR0 INTC_REG32(0x094) | ||
342 | #define INTC_MIR1 INTC_REG32(0x0A4) | ||
343 | #define INTC_MIR_SET1 INTC_REG32(0x0AC) | ||
344 | #define INTC_MIR_CLEAR1 INTC_REG32(0x0A8) | ||
345 | #define INTC_ISR_CLEAR1 INTC_REG32(0x0B4) | ||
346 | #define INTC_MIR2 INTC_REG32(0x0C4) | ||
347 | #define INTC_MIR_SET2 INTC_REG32(0x0CC) | ||
348 | #define INTC_MIR_CLEAR2 INTC_REG32(0x0C8) | ||
349 | #define INTC_ISR_CLEAR2 INTC_REG32(0x0D4) | ||
350 | #define INTC_SIR_IRQ INTC_REG32(0x040) | ||
351 | #define INTC_CONTROL INTC_REG32(0x048) | ||
352 | #define INTC_ILR11 INTC_REG32(0x12C) | ||
353 | #define INTC_ILR32 INTC_REG32(0x180) | ||
354 | #define INTC_ILR37 INTC_REG32(0x194) | ||
355 | #define INTC_SYSCONFIG INTC_REG32(0x010) | ||
356 | |||
357 | /* RAM FIREWALL */ | ||
358 | #define RAMFW_BASE (0x68005000) | ||
359 | #define RAMFW_REG32(offset) __REG32(RAMFW_BASE + (offset)) | ||
360 | |||
361 | #define RAMFW_REQINFOPERM0 RAMFW_REG32(0x048) | ||
362 | #define RAMFW_READPERM0 RAMFW_REG32(0x050) | ||
363 | #define RAMFW_WRITEPERM0 RAMFW_REG32(0x058) | ||
364 | |||
365 | /* GPMC CS1 FPGA ON USER INTERFACE MODULE */ | ||
366 | //#define DEBUG_BOARD_LED_REGISTER 0x04000014 | ||
367 | |||
368 | /* GPMC CS0 */ | ||
369 | #define GPMC_CONFIG1_0 GPMC_REG32(0x060) | ||
370 | #define GPMC_CONFIG2_0 GPMC_REG32(0x064) | ||
371 | #define GPMC_CONFIG3_0 GPMC_REG32(0x068) | ||
372 | #define GPMC_CONFIG4_0 GPMC_REG32(0x06C) | ||
373 | #define GPMC_CONFIG5_0 GPMC_REG32(0x070) | ||
374 | #define GPMC_CONFIG6_0 GPMC_REG32(0x074) | ||
375 | #define GPMC_CONFIG7_0 GPMC_REG32(0x078) | ||
376 | |||
377 | /* GPMC CS1 */ | ||
378 | #define GPMC_CONFIG1_1 GPMC_REG32(0x090) | ||
379 | #define GPMC_CONFIG2_1 GPMC_REG32(0x094) | ||
380 | #define GPMC_CONFIG3_1 GPMC_REG32(0x098) | ||
381 | #define GPMC_CONFIG4_1 GPMC_REG32(0x09C) | ||
382 | #define GPMC_CONFIG5_1 GPMC_REG32(0x0a0) | ||
383 | #define GPMC_CONFIG6_1 GPMC_REG32(0x0a4) | ||
384 | #define GPMC_CONFIG7_1 GPMC_REG32(0x0a8) | ||
385 | |||
386 | /* DSS */ | ||
387 | #define DSS_CONTROL DISP_REG32(0x040) | ||
388 | #define DISPC_CONTROL DISP_REG32(0x440) | ||
389 | #define DISPC_SYSSTATUS DISP_REG32(0x414) | ||
390 | #define DISPC_IRQSTATUS DISP_REG32(0x418) | ||
391 | #define DISPC_IRQENABLE DISP_REG32(0x41C) | ||
392 | #define DISPC_CONFIG DISP_REG32(0x444) | ||
393 | #define DISPC_DEFAULT_COLOR0 DISP_REG32(0x44C) | ||
394 | #define DISPC_DEFAULT_COLOR1 DISP_REG32(0x450) | ||
395 | #define DISPC_TRANS_COLOR0 DISP_REG32(0x454) | ||
396 | #define DISPC_TRANS_COLOR1 DISP_REG32(0x458) | ||
397 | #define DISPC_LINE_NUMBER DISP_REG32(0x460) | ||
398 | #define DISPC_TIMING_H DISP_REG32(0x464) | ||
399 | #define DISPC_TIMING_V DISP_REG32(0x468) | ||
400 | #define DISPC_POL_FREQ DISP_REG32(0x46C) | ||
401 | #define DISPC_DIVISOR DISP_REG32(0x470) | ||
402 | #define DISPC_SIZE_DIG DISP_REG32(0x478) | ||
403 | #define DISPC_SIZE_LCD DISP_REG32(0x47C) | ||
404 | #define DISPC_GFX_BA0 DISP_REG32(0x480) | ||
405 | #define DISPC_GFX_BA1 DISP_REG32(0x484) | ||
406 | #define DISPC_GFX_POSITION DISP_REG32(0x488) | ||
407 | #define DISPC_GFX_SIZE DISP_REG32(0x48C) | ||
408 | #define DISPC_GFX_ATTRIBUTES DISP_REG32(0x4A0) | ||
409 | #define DISPC_GFX_FIFO_THRESHOLD DISP_REG32(0x4A4) | ||
410 | #define DISPC_GFX_ROW_INC DISP_REG32(0x4AC) | ||
411 | #define DISPC_GFX_PIXEL_INC DISP_REG32(0x4B0) | ||
412 | #define DISPC_GFX_WINDOW_SKIP DISP_REG32(0x4B4) | ||
413 | #define DISPC_GFX_TABLE_BA DISP_REG32(0x4B8) | ||
414 | #define DISPC_DATA_CYCLE1 DISP_REG32(0x5D4) | ||
415 | #define DISPC_DATA_CYCLE2 DISP_REG32(0x5D8) | ||
416 | #define DISPC_DATA_CYCLE3 DISP_REG32(0x5DC) | ||
417 | |||
418 | /* Wake up define for board */ | ||
419 | #define GPIO97 (1 << 1) | ||
420 | #define GPIO88 (1 << 24) | ||
421 | |||
422 | #endif /* __ASSEMBLER__ */ | ||
423 | |||
424 | #endif | ||
425 | |||
426 | |||
427 | |||
428 | |||
429 | |||
diff --git a/include/asm-arm/arch-omap/sram.h b/include/asm-arm/arch-omap/sram.h new file mode 100644 index 000000000000..e72ccbf0fe06 --- /dev/null +++ b/include/asm-arm/arch-omap/sram.h | |||
@@ -0,0 +1,38 @@ | |||
1 | /* | ||
2 | * linux/include/asm-arm/arch-omap/sram.h | ||
3 | * | ||
4 | * Interface for functions that need to be run in internal SRAM | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #ifndef __ARCH_ARM_OMAP_SRAM_H | ||
12 | #define __ARCH_ARM_OMAP_SRAM_H | ||
13 | |||
14 | extern void * omap_sram_push(void * start, unsigned long size); | ||
15 | extern void omap_sram_reprogram_clock(u32 dpllctl, u32 ckctl); | ||
16 | |||
17 | extern void omap2_sram_ddr_init(u32 *slow_dll_ctrl, u32 fast_dll_ctrl, | ||
18 | u32 base_cs, u32 force_unlock); | ||
19 | extern void omap2_sram_reprogram_sdrc(u32 perf_level, u32 dll_val, | ||
20 | u32 mem_type); | ||
21 | extern u32 omap2_set_prcm(u32 dpll_ctrl_val, u32 sdrc_rfr_val, int bypass); | ||
22 | |||
23 | |||
24 | /* Do not use these */ | ||
25 | extern void sram_reprogram_clock(u32 ckctl, u32 dpllctl); | ||
26 | extern unsigned long sram_reprogram_clock_sz; | ||
27 | |||
28 | extern void sram_ddr_init(u32 *slow_dll_ctrl, u32 fast_dll_ctrl, | ||
29 | u32 base_cs, u32 force_unlock); | ||
30 | extern unsigned long sram_ddr_init_sz; | ||
31 | |||
32 | extern u32 sram_set_prcm(u32 dpll_ctrl_val, u32 sdrc_rfr_val, int bypass); | ||
33 | extern unsigned long sram_set_prcm_sz; | ||
34 | |||
35 | extern void sram_reprogram_sdrc(u32 perf_level, u32 dll_val, u32 mem_type); | ||
36 | extern unsigned long sram_reprogram_sdrc_sz; | ||
37 | |||
38 | #endif | ||
diff --git a/include/asm-arm/arch-omap/system.h b/include/asm-arm/arch-omap/system.h index ff37bc27e603..b43cdd2a3874 100644 --- a/include/asm-arm/arch-omap/system.h +++ b/include/asm-arm/arch-omap/system.h | |||
@@ -6,18 +6,21 @@ | |||
6 | #define __ASM_ARCH_SYSTEM_H | 6 | #define __ASM_ARCH_SYSTEM_H |
7 | #include <linux/config.h> | 7 | #include <linux/config.h> |
8 | #include <asm/mach-types.h> | 8 | #include <asm/mach-types.h> |
9 | #include <asm/hardware/clock.h> | ||
9 | #include <asm/arch/hardware.h> | 10 | #include <asm/arch/hardware.h> |
10 | #include <asm/mach-types.h> | 11 | #include <asm/arch/prcm.h> |
12 | |||
13 | #ifndef CONFIG_MACH_VOICEBLUE | ||
14 | #define voiceblue_reset() do {} while (0) | ||
15 | #endif | ||
11 | 16 | ||
12 | static inline void arch_idle(void) | 17 | static inline void arch_idle(void) |
13 | { | 18 | { |
14 | cpu_do_idle(); | 19 | cpu_do_idle(); |
15 | } | 20 | } |
16 | 21 | ||
17 | static inline void arch_reset(char mode) | 22 | static inline void omap1_arch_reset(char mode) |
18 | { | 23 | { |
19 | |||
20 | #ifdef CONFIG_ARCH_OMAP16XX | ||
21 | /* | 24 | /* |
22 | * Workaround for 5912/1611b bug mentioned in sprz209d.pdf p. 28 | 25 | * Workaround for 5912/1611b bug mentioned in sprz209d.pdf p. 28 |
23 | * "Global Software Reset Affects Traffic Controller Frequency". | 26 | * "Global Software Reset Affects Traffic Controller Frequency". |
@@ -27,13 +30,31 @@ static inline void arch_reset(char mode) | |||
27 | DPLL_CTL); | 30 | DPLL_CTL); |
28 | omap_writew(0x8, ARM_RSTCT1); | 31 | omap_writew(0x8, ARM_RSTCT1); |
29 | } | 32 | } |
30 | #endif | 33 | |
31 | #ifdef CONFIG_MACH_VOICEBLUE | ||
32 | if (machine_is_voiceblue()) | 34 | if (machine_is_voiceblue()) |
33 | voiceblue_reset(); | 35 | voiceblue_reset(); |
34 | else | 36 | else |
35 | #endif | ||
36 | omap_writew(1, ARM_RSTCT1); | 37 | omap_writew(1, ARM_RSTCT1); |
37 | } | 38 | } |
38 | 39 | ||
40 | static inline void omap2_arch_reset(char mode) | ||
41 | { | ||
42 | u32 rate; | ||
43 | struct clk *vclk, *sclk; | ||
44 | |||
45 | vclk = clk_get(NULL, "virt_prcm_set"); | ||
46 | sclk = clk_get(NULL, "sys_ck"); | ||
47 | rate = clk_get_rate(sclk); | ||
48 | clk_set_rate(vclk, rate); /* go to bypass for OMAP limitation */ | ||
49 | RM_RSTCTRL_WKUP |= 2; | ||
50 | } | ||
51 | |||
52 | static inline void arch_reset(char mode) | ||
53 | { | ||
54 | if (!cpu_is_omap24xx()) | ||
55 | omap1_arch_reset(mode); | ||
56 | else | ||
57 | omap2_arch_reset(mode); | ||
58 | } | ||
59 | |||
39 | #endif | 60 | #endif |
diff --git a/include/asm-arm/arch-omap/timex.h b/include/asm-arm/arch-omap/timex.h index b61ddb491e83..21f2e367185a 100644 --- a/include/asm-arm/arch-omap/timex.h +++ b/include/asm-arm/arch-omap/timex.h | |||
@@ -28,6 +28,14 @@ | |||
28 | #if !defined(__ASM_ARCH_OMAP_TIMEX_H) | 28 | #if !defined(__ASM_ARCH_OMAP_TIMEX_H) |
29 | #define __ASM_ARCH_OMAP_TIMEX_H | 29 | #define __ASM_ARCH_OMAP_TIMEX_H |
30 | 30 | ||
31 | /* | ||
32 | * OMAP 32KHz timer updates time one jiffie at a time from a secondary timer, | ||
33 | * and that's why the CLOCK_TICK_RATE is not 32768. | ||
34 | */ | ||
35 | #ifdef CONFIG_OMAP_32K_TIMER | ||
36 | #define CLOCK_TICK_RATE (CONFIG_OMAP_32K_TIMER_HZ) | ||
37 | #else | ||
31 | #define CLOCK_TICK_RATE (HZ * 100000UL) | 38 | #define CLOCK_TICK_RATE (HZ * 100000UL) |
39 | #endif | ||
32 | 40 | ||
33 | #endif /* __ASM_ARCH_OMAP_TIMEX_H */ | 41 | #endif /* __ASM_ARCH_OMAP_TIMEX_H */ |
diff --git a/include/asm-arm/arch-omap/uncompress.h b/include/asm-arm/arch-omap/uncompress.h index 3545c86859cc..c718264affbd 100644 --- a/include/asm-arm/arch-omap/uncompress.h +++ b/include/asm-arm/arch-omap/uncompress.h | |||
@@ -36,10 +36,14 @@ putstr(const char *s) | |||
36 | volatile u8 * uart = 0; | 36 | volatile u8 * uart = 0; |
37 | int shift = 2; | 37 | int shift = 2; |
38 | 38 | ||
39 | #ifdef CONFIG_MACH_OMAP_PALMTE | ||
40 | return; | ||
41 | #endif | ||
42 | |||
39 | #ifdef CONFIG_ARCH_OMAP | 43 | #ifdef CONFIG_ARCH_OMAP |
40 | #ifdef CONFIG_OMAP_LL_DEBUG_UART3 | 44 | #ifdef CONFIG_OMAP_LL_DEBUG_UART3 |
41 | uart = (volatile u8 *)(OMAP_UART3_BASE); | 45 | uart = (volatile u8 *)(OMAP_UART3_BASE); |
42 | #elif CONFIG_OMAP_LL_DEBUG_UART2 | 46 | #elif defined(CONFIG_OMAP_LL_DEBUG_UART2) |
43 | uart = (volatile u8 *)(OMAP_UART2_BASE); | 47 | uart = (volatile u8 *)(OMAP_UART2_BASE); |
44 | #else | 48 | #else |
45 | uart = (volatile u8 *)(OMAP_UART1_BASE); | 49 | uart = (volatile u8 *)(OMAP_UART1_BASE); |
diff --git a/include/asm-arm/arch-pxa/sharpsl.h b/include/asm-arm/arch-pxa/sharpsl.h index 311f2bb5386a..0b43495d24b4 100644 --- a/include/asm-arm/arch-pxa/sharpsl.h +++ b/include/asm-arm/arch-pxa/sharpsl.h | |||
@@ -21,12 +21,18 @@ struct corgits_machinfo { | |||
21 | void (*wait_hsync)(void); | 21 | void (*wait_hsync)(void); |
22 | }; | 22 | }; |
23 | 23 | ||
24 | |||
24 | /* | 25 | /* |
25 | * SharpSL Backlight | 26 | * SharpSL Backlight |
26 | */ | 27 | */ |
27 | |||
28 | struct corgibl_machinfo { | 28 | struct corgibl_machinfo { |
29 | int max_intensity; | 29 | int max_intensity; |
30 | void (*set_bl_intensity)(int intensity); | 30 | void (*set_bl_intensity)(int intensity); |
31 | }; | 31 | }; |
32 | extern void corgibl_limit_intensity(int limit); | ||
33 | |||
32 | 34 | ||
35 | /* | ||
36 | * SharpSL Battery/PM Driver | ||
37 | */ | ||
38 | extern void sharpsl_battery_kick(void); | ||
diff --git a/include/asm-arm/arch-pxa/ssp.h b/include/asm-arm/arch-pxa/ssp.h index 6ec67b018c09..949878c0d908 100644 --- a/include/asm-arm/arch-pxa/ssp.h +++ b/include/asm-arm/arch-pxa/ssp.h | |||
@@ -18,6 +18,11 @@ | |||
18 | #ifndef SSP_H | 18 | #ifndef SSP_H |
19 | #define SSP_H | 19 | #define SSP_H |
20 | 20 | ||
21 | /* | ||
22 | * SSP initialisation flags | ||
23 | */ | ||
24 | #define SSP_NO_IRQ 0x1 /* don't register an irq handler in SSP driver */ | ||
25 | |||
21 | struct ssp_state { | 26 | struct ssp_state { |
22 | u32 cr0; | 27 | u32 cr0; |
23 | u32 cr1; | 28 | u32 cr1; |
@@ -31,6 +36,7 @@ struct ssp_dev { | |||
31 | u32 flags; | 36 | u32 flags; |
32 | u32 psp_flags; | 37 | u32 psp_flags; |
33 | u32 speed; | 38 | u32 speed; |
39 | int irq; | ||
34 | }; | 40 | }; |
35 | 41 | ||
36 | int ssp_write_word(struct ssp_dev *dev, u32 data); | 42 | int ssp_write_word(struct ssp_dev *dev, u32 data); |
@@ -40,7 +46,7 @@ void ssp_enable(struct ssp_dev *dev); | |||
40 | void ssp_disable(struct ssp_dev *dev); | 46 | void ssp_disable(struct ssp_dev *dev); |
41 | void ssp_save_state(struct ssp_dev *dev, struct ssp_state *ssp); | 47 | void ssp_save_state(struct ssp_dev *dev, struct ssp_state *ssp); |
42 | void ssp_restore_state(struct ssp_dev *dev, struct ssp_state *ssp); | 48 | void ssp_restore_state(struct ssp_dev *dev, struct ssp_state *ssp); |
43 | int ssp_init(struct ssp_dev *dev, u32 port); | 49 | int ssp_init(struct ssp_dev *dev, u32 port, u32 init_flags); |
44 | int ssp_config(struct ssp_dev *dev, u32 mode, u32 flags, u32 psp_flags, u32 speed); | 50 | int ssp_config(struct ssp_dev *dev, u32 mode, u32 flags, u32 psp_flags, u32 speed); |
45 | void ssp_exit(struct ssp_dev *dev); | 51 | void ssp_exit(struct ssp_dev *dev); |
46 | 52 | ||
diff --git a/include/asm-i386/msi.h b/include/asm-i386/msi.h index b85393094c83..f041d4495faf 100644 --- a/include/asm-i386/msi.h +++ b/include/asm-i386/msi.h | |||
@@ -10,13 +10,6 @@ | |||
10 | #include <mach_apic.h> | 10 | #include <mach_apic.h> |
11 | 11 | ||
12 | #define LAST_DEVICE_VECTOR 232 | 12 | #define LAST_DEVICE_VECTOR 232 |
13 | #define MSI_DEST_MODE MSI_LOGICAL_MODE | 13 | #define MSI_TARGET_CPU_SHIFT 12 |
14 | #define MSI_TARGET_CPU_SHIFT 12 | ||
15 | |||
16 | #ifdef CONFIG_SMP | ||
17 | #define MSI_TARGET_CPU logical_smp_processor_id() | ||
18 | #else | ||
19 | #define MSI_TARGET_CPU cpu_to_logical_apicid(first_cpu(cpu_online_map)) | ||
20 | #endif | ||
21 | 14 | ||
22 | #endif /* ASM_MSI_H */ | 15 | #endif /* ASM_MSI_H */ |
diff --git a/include/asm-i386/smp.h b/include/asm-i386/smp.h index 13250199976d..61d3ab9db70c 100644 --- a/include/asm-i386/smp.h +++ b/include/asm-i386/smp.h | |||
@@ -45,6 +45,8 @@ extern void unlock_ipi_call_lock(void); | |||
45 | #define MAX_APICID 256 | 45 | #define MAX_APICID 256 |
46 | extern u8 x86_cpu_to_apicid[]; | 46 | extern u8 x86_cpu_to_apicid[]; |
47 | 47 | ||
48 | #define cpu_physical_id(cpu) x86_cpu_to_apicid[cpu] | ||
49 | |||
48 | #ifdef CONFIG_HOTPLUG_CPU | 50 | #ifdef CONFIG_HOTPLUG_CPU |
49 | extern void cpu_exit_clear(void); | 51 | extern void cpu_exit_clear(void); |
50 | extern void cpu_uninit(void); | 52 | extern void cpu_uninit(void); |
@@ -92,6 +94,10 @@ extern int __cpu_disable(void); | |||
92 | extern void __cpu_die(unsigned int cpu); | 94 | extern void __cpu_die(unsigned int cpu); |
93 | #endif /* !__ASSEMBLY__ */ | 95 | #endif /* !__ASSEMBLY__ */ |
94 | 96 | ||
97 | #else /* CONFIG_SMP */ | ||
98 | |||
99 | #define cpu_physical_id(cpu) boot_cpu_physical_apicid | ||
100 | |||
95 | #define NO_PROC_ID 0xFF /* No processor magic marker */ | 101 | #define NO_PROC_ID 0xFF /* No processor magic marker */ |
96 | 102 | ||
97 | #endif | 103 | #endif |
diff --git a/include/asm-ia64/kdebug.h b/include/asm-ia64/kdebug.h index 4d376e1663f7..8b01a083dde6 100644 --- a/include/asm-ia64/kdebug.h +++ b/include/asm-ia64/kdebug.h | |||
@@ -22,6 +22,9 @@ | |||
22 | * 2005-Apr Rusty Lynch <rusty.lynch@intel.com> and Anil S Keshavamurthy | 22 | * 2005-Apr Rusty Lynch <rusty.lynch@intel.com> and Anil S Keshavamurthy |
23 | * <anil.s.keshavamurthy@intel.com> adopted from | 23 | * <anil.s.keshavamurthy@intel.com> adopted from |
24 | * include/asm-x86_64/kdebug.h | 24 | * include/asm-x86_64/kdebug.h |
25 | * | ||
26 | * 2005-Oct Keith Owens <kaos@sgi.com>. Expand notify_die to cover more | ||
27 | * events. | ||
25 | */ | 28 | */ |
26 | #include <linux/notifier.h> | 29 | #include <linux/notifier.h> |
27 | 30 | ||
@@ -35,13 +38,36 @@ struct die_args { | |||
35 | int signr; | 38 | int signr; |
36 | }; | 39 | }; |
37 | 40 | ||
38 | int register_die_notifier(struct notifier_block *nb); | 41 | extern int register_die_notifier(struct notifier_block *); |
42 | extern int unregister_die_notifier(struct notifier_block *); | ||
39 | extern struct notifier_block *ia64die_chain; | 43 | extern struct notifier_block *ia64die_chain; |
40 | 44 | ||
41 | enum die_val { | 45 | enum die_val { |
42 | DIE_BREAK = 1, | 46 | DIE_BREAK = 1, |
43 | DIE_SS, | 47 | DIE_FAULT, |
48 | DIE_OOPS, | ||
44 | DIE_PAGE_FAULT, | 49 | DIE_PAGE_FAULT, |
50 | DIE_MACHINE_HALT, | ||
51 | DIE_MACHINE_RESTART, | ||
52 | DIE_MCA_MONARCH_ENTER, | ||
53 | DIE_MCA_MONARCH_PROCESS, | ||
54 | DIE_MCA_MONARCH_LEAVE, | ||
55 | DIE_MCA_SLAVE_ENTER, | ||
56 | DIE_MCA_SLAVE_PROCESS, | ||
57 | DIE_MCA_SLAVE_LEAVE, | ||
58 | DIE_MCA_RENDZVOUS_ENTER, | ||
59 | DIE_MCA_RENDZVOUS_PROCESS, | ||
60 | DIE_MCA_RENDZVOUS_LEAVE, | ||
61 | DIE_INIT_MONARCH_ENTER, | ||
62 | DIE_INIT_MONARCH_PROCESS, | ||
63 | DIE_INIT_MONARCH_LEAVE, | ||
64 | DIE_INIT_SLAVE_ENTER, | ||
65 | DIE_INIT_SLAVE_PROCESS, | ||
66 | DIE_INIT_SLAVE_LEAVE, | ||
67 | DIE_KDEBUG_ENTER, | ||
68 | DIE_KDEBUG_LEAVE, | ||
69 | DIE_KDUMP_ENTER, | ||
70 | DIE_KDUMP_LEAVE, | ||
45 | }; | 71 | }; |
46 | 72 | ||
47 | static inline int notify_die(enum die_val val, char *str, struct pt_regs *regs, | 73 | static inline int notify_die(enum die_val val, char *str, struct pt_regs *regs, |
diff --git a/include/asm-ia64/mmu_context.h b/include/asm-ia64/mmu_context.h index 8d6e72f7b08e..b5c65081a3aa 100644 --- a/include/asm-ia64/mmu_context.h +++ b/include/asm-ia64/mmu_context.h | |||
@@ -7,12 +7,13 @@ | |||
7 | */ | 7 | */ |
8 | 8 | ||
9 | /* | 9 | /* |
10 | * Routines to manage the allocation of task context numbers. Task context numbers are | 10 | * Routines to manage the allocation of task context numbers. Task context |
11 | * used to reduce or eliminate the need to perform TLB flushes due to context switches. | 11 | * numbers are used to reduce or eliminate the need to perform TLB flushes |
12 | * Context numbers are implemented using ia-64 region ids. Since the IA-64 TLB does not | 12 | * due to context switches. Context numbers are implemented using ia-64 |
13 | * consider the region number when performing a TLB lookup, we need to assign a unique | 13 | * region ids. Since the IA-64 TLB does not consider the region number when |
14 | * region id to each region in a process. We use the least significant three bits in a | 14 | * performing a TLB lookup, we need to assign a unique region id to each |
15 | * region id for this purpose. | 15 | * region in a process. We use the least significant three bits in aregion |
16 | * id for this purpose. | ||
16 | */ | 17 | */ |
17 | 18 | ||
18 | #define IA64_REGION_ID_KERNEL 0 /* the kernel's region id (tlb.c depends on this being 0) */ | 19 | #define IA64_REGION_ID_KERNEL 0 /* the kernel's region id (tlb.c depends on this being 0) */ |
@@ -32,13 +33,17 @@ | |||
32 | struct ia64_ctx { | 33 | struct ia64_ctx { |
33 | spinlock_t lock; | 34 | spinlock_t lock; |
34 | unsigned int next; /* next context number to use */ | 35 | unsigned int next; /* next context number to use */ |
35 | unsigned int limit; /* next >= limit => must call wrap_mmu_context() */ | 36 | unsigned int limit; /* available free range */ |
36 | unsigned int max_ctx; /* max. context value supported by all CPUs */ | 37 | unsigned int max_ctx; /* max. context value supported by all CPUs */ |
38 | /* call wrap_mmu_context when next >= max */ | ||
39 | unsigned long *bitmap; /* bitmap size is max_ctx+1 */ | ||
40 | unsigned long *flushmap;/* pending rid to be flushed */ | ||
37 | }; | 41 | }; |
38 | 42 | ||
39 | extern struct ia64_ctx ia64_ctx; | 43 | extern struct ia64_ctx ia64_ctx; |
40 | DECLARE_PER_CPU(u8, ia64_need_tlb_flush); | 44 | DECLARE_PER_CPU(u8, ia64_need_tlb_flush); |
41 | 45 | ||
46 | extern void mmu_context_init (void); | ||
42 | extern void wrap_mmu_context (struct mm_struct *mm); | 47 | extern void wrap_mmu_context (struct mm_struct *mm); |
43 | 48 | ||
44 | static inline void | 49 | static inline void |
@@ -47,10 +52,10 @@ enter_lazy_tlb (struct mm_struct *mm, struct task_struct *tsk) | |||
47 | } | 52 | } |
48 | 53 | ||
49 | /* | 54 | /* |
50 | * When the context counter wraps around all TLBs need to be flushed because an old | 55 | * When the context counter wraps around all TLBs need to be flushed because |
51 | * context number might have been reused. This is signalled by the ia64_need_tlb_flush | 56 | * an old context number might have been reused. This is signalled by the |
52 | * per-CPU variable, which is checked in the routine below. Called by activate_mm(). | 57 | * ia64_need_tlb_flush per-CPU variable, which is checked in the routine |
53 | * <efocht@ess.nec.de> | 58 | * below. Called by activate_mm(). <efocht@ess.nec.de> |
54 | */ | 59 | */ |
55 | static inline void | 60 | static inline void |
56 | delayed_tlb_flush (void) | 61 | delayed_tlb_flush (void) |
@@ -60,11 +65,9 @@ delayed_tlb_flush (void) | |||
60 | 65 | ||
61 | if (unlikely(__ia64_per_cpu_var(ia64_need_tlb_flush))) { | 66 | if (unlikely(__ia64_per_cpu_var(ia64_need_tlb_flush))) { |
62 | spin_lock_irqsave(&ia64_ctx.lock, flags); | 67 | spin_lock_irqsave(&ia64_ctx.lock, flags); |
63 | { | 68 | if (__ia64_per_cpu_var(ia64_need_tlb_flush)) { |
64 | if (__ia64_per_cpu_var(ia64_need_tlb_flush)) { | 69 | local_flush_tlb_all(); |
65 | local_flush_tlb_all(); | 70 | __ia64_per_cpu_var(ia64_need_tlb_flush) = 0; |
66 | __ia64_per_cpu_var(ia64_need_tlb_flush) = 0; | ||
67 | } | ||
68 | } | 71 | } |
69 | spin_unlock_irqrestore(&ia64_ctx.lock, flags); | 72 | spin_unlock_irqrestore(&ia64_ctx.lock, flags); |
70 | } | 73 | } |
@@ -76,20 +79,27 @@ get_mmu_context (struct mm_struct *mm) | |||
76 | unsigned long flags; | 79 | unsigned long flags; |
77 | nv_mm_context_t context = mm->context; | 80 | nv_mm_context_t context = mm->context; |
78 | 81 | ||
79 | if (unlikely(!context)) { | 82 | if (likely(context)) |
80 | spin_lock_irqsave(&ia64_ctx.lock, flags); | 83 | goto out; |
81 | { | 84 | |
82 | /* re-check, now that we've got the lock: */ | 85 | spin_lock_irqsave(&ia64_ctx.lock, flags); |
83 | context = mm->context; | 86 | /* re-check, now that we've got the lock: */ |
84 | if (context == 0) { | 87 | context = mm->context; |
85 | cpus_clear(mm->cpu_vm_mask); | 88 | if (context == 0) { |
86 | if (ia64_ctx.next >= ia64_ctx.limit) | 89 | cpus_clear(mm->cpu_vm_mask); |
87 | wrap_mmu_context(mm); | 90 | if (ia64_ctx.next >= ia64_ctx.limit) { |
88 | mm->context = context = ia64_ctx.next++; | 91 | ia64_ctx.next = find_next_zero_bit(ia64_ctx.bitmap, |
89 | } | 92 | ia64_ctx.max_ctx, ia64_ctx.next); |
93 | ia64_ctx.limit = find_next_bit(ia64_ctx.bitmap, | ||
94 | ia64_ctx.max_ctx, ia64_ctx.next); | ||
95 | if (ia64_ctx.next >= ia64_ctx.max_ctx) | ||
96 | wrap_mmu_context(mm); | ||
90 | } | 97 | } |
91 | spin_unlock_irqrestore(&ia64_ctx.lock, flags); | 98 | mm->context = context = ia64_ctx.next++; |
99 | __set_bit(context, ia64_ctx.bitmap); | ||
92 | } | 100 | } |
101 | spin_unlock_irqrestore(&ia64_ctx.lock, flags); | ||
102 | out: | ||
93 | /* | 103 | /* |
94 | * Ensure we're not starting to use "context" before any old | 104 | * Ensure we're not starting to use "context" before any old |
95 | * uses of it are gone from our TLB. | 105 | * uses of it are gone from our TLB. |
@@ -100,8 +110,8 @@ get_mmu_context (struct mm_struct *mm) | |||
100 | } | 110 | } |
101 | 111 | ||
102 | /* | 112 | /* |
103 | * Initialize context number to some sane value. MM is guaranteed to be a brand-new | 113 | * Initialize context number to some sane value. MM is guaranteed to be a |
104 | * address-space, so no TLB flushing is needed, ever. | 114 | * brand-new address-space, so no TLB flushing is needed, ever. |
105 | */ | 115 | */ |
106 | static inline int | 116 | static inline int |
107 | init_new_context (struct task_struct *p, struct mm_struct *mm) | 117 | init_new_context (struct task_struct *p, struct mm_struct *mm) |
@@ -162,7 +172,10 @@ activate_context (struct mm_struct *mm) | |||
162 | if (!cpu_isset(smp_processor_id(), mm->cpu_vm_mask)) | 172 | if (!cpu_isset(smp_processor_id(), mm->cpu_vm_mask)) |
163 | cpu_set(smp_processor_id(), mm->cpu_vm_mask); | 173 | cpu_set(smp_processor_id(), mm->cpu_vm_mask); |
164 | reload_context(context); | 174 | reload_context(context); |
165 | /* in the unlikely event of a TLB-flush by another thread, redo the load: */ | 175 | /* |
176 | * in the unlikely event of a TLB-flush by another thread, | ||
177 | * redo the load. | ||
178 | */ | ||
166 | } while (unlikely(context != mm->context)); | 179 | } while (unlikely(context != mm->context)); |
167 | } | 180 | } |
168 | 181 | ||
@@ -175,8 +188,8 @@ static inline void | |||
175 | activate_mm (struct mm_struct *prev, struct mm_struct *next) | 188 | activate_mm (struct mm_struct *prev, struct mm_struct *next) |
176 | { | 189 | { |
177 | /* | 190 | /* |
178 | * We may get interrupts here, but that's OK because interrupt handlers cannot | 191 | * We may get interrupts here, but that's OK because interrupt |
179 | * touch user-space. | 192 | * handlers cannot touch user-space. |
180 | */ | 193 | */ |
181 | ia64_set_kr(IA64_KR_PT_BASE, __pa(next->pgd)); | 194 | ia64_set_kr(IA64_KR_PT_BASE, __pa(next->pgd)); |
182 | activate_context(next); | 195 | activate_context(next); |
diff --git a/include/asm-ia64/msi.h b/include/asm-ia64/msi.h index 60f2137f9278..97890f7762b3 100644 --- a/include/asm-ia64/msi.h +++ b/include/asm-ia64/msi.h | |||
@@ -12,9 +12,6 @@ | |||
12 | static inline void set_intr_gate (int nr, void *func) {} | 12 | static inline void set_intr_gate (int nr, void *func) {} |
13 | #define IO_APIC_VECTOR(irq) (irq) | 13 | #define IO_APIC_VECTOR(irq) (irq) |
14 | #define ack_APIC_irq ia64_eoi | 14 | #define ack_APIC_irq ia64_eoi |
15 | #define cpu_mask_to_apicid(mask) cpu_physical_id(first_cpu(mask)) | ||
16 | #define MSI_DEST_MODE MSI_PHYSICAL_MODE | ||
17 | #define MSI_TARGET_CPU ((ia64_getreg(_IA64_REG_CR_LID) >> 16) & 0xffff) | ||
18 | #define MSI_TARGET_CPU_SHIFT 4 | 15 | #define MSI_TARGET_CPU_SHIFT 4 |
19 | 16 | ||
20 | #endif /* ASM_MSI_H */ | 17 | #endif /* ASM_MSI_H */ |
diff --git a/include/asm-ia64/tlbflush.h b/include/asm-ia64/tlbflush.h index b65c62702724..a35b323bae4c 100644 --- a/include/asm-ia64/tlbflush.h +++ b/include/asm-ia64/tlbflush.h | |||
@@ -51,6 +51,7 @@ flush_tlb_mm (struct mm_struct *mm) | |||
51 | if (!mm) | 51 | if (!mm) |
52 | return; | 52 | return; |
53 | 53 | ||
54 | set_bit(mm->context, ia64_ctx.flushmap); | ||
54 | mm->context = 0; | 55 | mm->context = 0; |
55 | 56 | ||
56 | if (atomic_read(&mm->mm_users) == 0) | 57 | if (atomic_read(&mm->mm_users) == 0) |
diff --git a/include/asm-ppc64/abs_addr.h b/include/asm-powerpc/abs_addr.h index dc3fc3fefef2..18415108fc56 100644 --- a/include/asm-ppc64/abs_addr.h +++ b/include/asm-powerpc/abs_addr.h | |||
@@ -1,5 +1,5 @@ | |||
1 | #ifndef _ABS_ADDR_H | 1 | #ifndef _ASM_POWERPC_ABS_ADDR_H |
2 | #define _ABS_ADDR_H | 2 | #define _ASM_POWERPC_ABS_ADDR_H |
3 | 3 | ||
4 | #include <linux/config.h> | 4 | #include <linux/config.h> |
5 | 5 | ||
@@ -70,4 +70,4 @@ static inline unsigned long phys_to_abs(unsigned long pa) | |||
70 | #define iseries_hv_addr(virtaddr) \ | 70 | #define iseries_hv_addr(virtaddr) \ |
71 | (0x8000000000000000 | virt_to_abs(virtaddr)) | 71 | (0x8000000000000000 | virt_to_abs(virtaddr)) |
72 | 72 | ||
73 | #endif /* _ABS_ADDR_H */ | 73 | #endif /* _ASM_POWERPC_ABS_ADDR_H */ |
diff --git a/include/asm-powerpc/asm-compat.h b/include/asm-powerpc/asm-compat.h new file mode 100644 index 000000000000..8b133efc9f79 --- /dev/null +++ b/include/asm-powerpc/asm-compat.h | |||
@@ -0,0 +1,55 @@ | |||
1 | #ifndef _ASM_POWERPC_ASM_COMPAT_H | ||
2 | #define _ASM_POWERPC_ASM_COMPAT_H | ||
3 | |||
4 | #include <linux/config.h> | ||
5 | #include <asm/types.h> | ||
6 | |||
7 | #ifdef __ASSEMBLY__ | ||
8 | # define stringify_in_c(...) __VA_ARGS__ | ||
9 | # define ASM_CONST(x) x | ||
10 | #else | ||
11 | /* This version of stringify will deal with commas... */ | ||
12 | # define __stringify_in_c(...) #__VA_ARGS__ | ||
13 | # define stringify_in_c(...) __stringify_in_c(__VA_ARGS__) " " | ||
14 | # define __ASM_CONST(x) x##UL | ||
15 | # define ASM_CONST(x) __ASM_CONST(x) | ||
16 | #endif | ||
17 | |||
18 | #ifdef __powerpc64__ | ||
19 | |||
20 | /* operations for longs and pointers */ | ||
21 | #define PPC_LL stringify_in_c(ld) | ||
22 | #define PPC_STL stringify_in_c(std) | ||
23 | #define PPC_LCMPI stringify_in_c(cmpdi) | ||
24 | #define PPC_LONG stringify_in_c(.llong) | ||
25 | #define PPC_TLNEI stringify_in_c(tdnei) | ||
26 | #define PPC_LLARX stringify_in_c(ldarx) | ||
27 | #define PPC_STLCX stringify_in_c(stdcx.) | ||
28 | #define PPC_CNTLZL stringify_in_c(cntlzd) | ||
29 | |||
30 | #else /* 32-bit */ | ||
31 | |||
32 | /* operations for longs and pointers */ | ||
33 | #define PPC_LL stringify_in_c(lwz) | ||
34 | #define PPC_STL stringify_in_c(stw) | ||
35 | #define PPC_LCMPI stringify_in_c(cmpwi) | ||
36 | #define PPC_LONG stringify_in_c(.long) | ||
37 | #define PPC_TLNEI stringify_in_c(twnei) | ||
38 | #define PPC_LLARX stringify_in_c(lwarx) | ||
39 | #define PPC_STLCX stringify_in_c(stwcx.) | ||
40 | #define PPC_CNTLZL stringify_in_c(cntlzw) | ||
41 | |||
42 | #endif | ||
43 | |||
44 | #ifdef CONFIG_IBM405_ERR77 | ||
45 | /* Erratum #77 on the 405 means we need a sync or dcbt before every | ||
46 | * stwcx. The old ATOMIC_SYNC_FIX covered some but not all of this. | ||
47 | */ | ||
48 | #define PPC405_ERR77(ra,rb) stringify_in_c(dcbt ra, rb;) | ||
49 | #define PPC405_ERR77_SYNC stringify_in_c(sync;) | ||
50 | #else | ||
51 | #define PPC405_ERR77(ra,rb) | ||
52 | #define PPC405_ERR77_SYNC | ||
53 | #endif | ||
54 | |||
55 | #endif /* _ASM_POWERPC_ASM_COMPAT_H */ | ||
diff --git a/include/asm-powerpc/atomic.h b/include/asm-powerpc/atomic.h index ed4b345ed75d..9c0b372a46e1 100644 --- a/include/asm-powerpc/atomic.h +++ b/include/asm-powerpc/atomic.h | |||
@@ -9,21 +9,13 @@ typedef struct { volatile int counter; } atomic_t; | |||
9 | 9 | ||
10 | #ifdef __KERNEL__ | 10 | #ifdef __KERNEL__ |
11 | #include <asm/synch.h> | 11 | #include <asm/synch.h> |
12 | #include <asm/asm-compat.h> | ||
12 | 13 | ||
13 | #define ATOMIC_INIT(i) { (i) } | 14 | #define ATOMIC_INIT(i) { (i) } |
14 | 15 | ||
15 | #define atomic_read(v) ((v)->counter) | 16 | #define atomic_read(v) ((v)->counter) |
16 | #define atomic_set(v,i) (((v)->counter) = (i)) | 17 | #define atomic_set(v,i) (((v)->counter) = (i)) |
17 | 18 | ||
18 | /* Erratum #77 on the 405 means we need a sync or dcbt before every stwcx. | ||
19 | * The old ATOMIC_SYNC_FIX covered some but not all of this. | ||
20 | */ | ||
21 | #ifdef CONFIG_IBM405_ERR77 | ||
22 | #define PPC405_ERR77(ra,rb) "dcbt " #ra "," #rb ";" | ||
23 | #else | ||
24 | #define PPC405_ERR77(ra,rb) | ||
25 | #endif | ||
26 | |||
27 | static __inline__ void atomic_add(int a, atomic_t *v) | 19 | static __inline__ void atomic_add(int a, atomic_t *v) |
28 | { | 20 | { |
29 | int t; | 21 | int t; |
@@ -205,5 +197,183 @@ static __inline__ int atomic_dec_if_positive(atomic_t *v) | |||
205 | #define smp_mb__before_atomic_inc() smp_mb() | 197 | #define smp_mb__before_atomic_inc() smp_mb() |
206 | #define smp_mb__after_atomic_inc() smp_mb() | 198 | #define smp_mb__after_atomic_inc() smp_mb() |
207 | 199 | ||
200 | #ifdef __powerpc64__ | ||
201 | |||
202 | typedef struct { volatile long counter; } atomic64_t; | ||
203 | |||
204 | #define ATOMIC64_INIT(i) { (i) } | ||
205 | |||
206 | #define atomic64_read(v) ((v)->counter) | ||
207 | #define atomic64_set(v,i) (((v)->counter) = (i)) | ||
208 | |||
209 | static __inline__ void atomic64_add(long a, atomic64_t *v) | ||
210 | { | ||
211 | long t; | ||
212 | |||
213 | __asm__ __volatile__( | ||
214 | "1: ldarx %0,0,%3 # atomic64_add\n\ | ||
215 | add %0,%2,%0\n\ | ||
216 | stdcx. %0,0,%3 \n\ | ||
217 | bne- 1b" | ||
218 | : "=&r" (t), "=m" (v->counter) | ||
219 | : "r" (a), "r" (&v->counter), "m" (v->counter) | ||
220 | : "cc"); | ||
221 | } | ||
222 | |||
223 | static __inline__ long atomic64_add_return(long a, atomic64_t *v) | ||
224 | { | ||
225 | long t; | ||
226 | |||
227 | __asm__ __volatile__( | ||
228 | EIEIO_ON_SMP | ||
229 | "1: ldarx %0,0,%2 # atomic64_add_return\n\ | ||
230 | add %0,%1,%0\n\ | ||
231 | stdcx. %0,0,%2 \n\ | ||
232 | bne- 1b" | ||
233 | ISYNC_ON_SMP | ||
234 | : "=&r" (t) | ||
235 | : "r" (a), "r" (&v->counter) | ||
236 | : "cc", "memory"); | ||
237 | |||
238 | return t; | ||
239 | } | ||
240 | |||
241 | #define atomic64_add_negative(a, v) (atomic64_add_return((a), (v)) < 0) | ||
242 | |||
243 | static __inline__ void atomic64_sub(long a, atomic64_t *v) | ||
244 | { | ||
245 | long t; | ||
246 | |||
247 | __asm__ __volatile__( | ||
248 | "1: ldarx %0,0,%3 # atomic64_sub\n\ | ||
249 | subf %0,%2,%0\n\ | ||
250 | stdcx. %0,0,%3 \n\ | ||
251 | bne- 1b" | ||
252 | : "=&r" (t), "=m" (v->counter) | ||
253 | : "r" (a), "r" (&v->counter), "m" (v->counter) | ||
254 | : "cc"); | ||
255 | } | ||
256 | |||
257 | static __inline__ long atomic64_sub_return(long a, atomic64_t *v) | ||
258 | { | ||
259 | long t; | ||
260 | |||
261 | __asm__ __volatile__( | ||
262 | EIEIO_ON_SMP | ||
263 | "1: ldarx %0,0,%2 # atomic64_sub_return\n\ | ||
264 | subf %0,%1,%0\n\ | ||
265 | stdcx. %0,0,%2 \n\ | ||
266 | bne- 1b" | ||
267 | ISYNC_ON_SMP | ||
268 | : "=&r" (t) | ||
269 | : "r" (a), "r" (&v->counter) | ||
270 | : "cc", "memory"); | ||
271 | |||
272 | return t; | ||
273 | } | ||
274 | |||
275 | static __inline__ void atomic64_inc(atomic64_t *v) | ||
276 | { | ||
277 | long t; | ||
278 | |||
279 | __asm__ __volatile__( | ||
280 | "1: ldarx %0,0,%2 # atomic64_inc\n\ | ||
281 | addic %0,%0,1\n\ | ||
282 | stdcx. %0,0,%2 \n\ | ||
283 | bne- 1b" | ||
284 | : "=&r" (t), "=m" (v->counter) | ||
285 | : "r" (&v->counter), "m" (v->counter) | ||
286 | : "cc"); | ||
287 | } | ||
288 | |||
289 | static __inline__ long atomic64_inc_return(atomic64_t *v) | ||
290 | { | ||
291 | long t; | ||
292 | |||
293 | __asm__ __volatile__( | ||
294 | EIEIO_ON_SMP | ||
295 | "1: ldarx %0,0,%1 # atomic64_inc_return\n\ | ||
296 | addic %0,%0,1\n\ | ||
297 | stdcx. %0,0,%1 \n\ | ||
298 | bne- 1b" | ||
299 | ISYNC_ON_SMP | ||
300 | : "=&r" (t) | ||
301 | : "r" (&v->counter) | ||
302 | : "cc", "memory"); | ||
303 | |||
304 | return t; | ||
305 | } | ||
306 | |||
307 | /* | ||
308 | * atomic64_inc_and_test - increment and test | ||
309 | * @v: pointer of type atomic64_t | ||
310 | * | ||
311 | * Atomically increments @v by 1 | ||
312 | * and returns true if the result is zero, or false for all | ||
313 | * other cases. | ||
314 | */ | ||
315 | #define atomic64_inc_and_test(v) (atomic64_inc_return(v) == 0) | ||
316 | |||
317 | static __inline__ void atomic64_dec(atomic64_t *v) | ||
318 | { | ||
319 | long t; | ||
320 | |||
321 | __asm__ __volatile__( | ||
322 | "1: ldarx %0,0,%2 # atomic64_dec\n\ | ||
323 | addic %0,%0,-1\n\ | ||
324 | stdcx. %0,0,%2\n\ | ||
325 | bne- 1b" | ||
326 | : "=&r" (t), "=m" (v->counter) | ||
327 | : "r" (&v->counter), "m" (v->counter) | ||
328 | : "cc"); | ||
329 | } | ||
330 | |||
331 | static __inline__ long atomic64_dec_return(atomic64_t *v) | ||
332 | { | ||
333 | long t; | ||
334 | |||
335 | __asm__ __volatile__( | ||
336 | EIEIO_ON_SMP | ||
337 | "1: ldarx %0,0,%1 # atomic64_dec_return\n\ | ||
338 | addic %0,%0,-1\n\ | ||
339 | stdcx. %0,0,%1\n\ | ||
340 | bne- 1b" | ||
341 | ISYNC_ON_SMP | ||
342 | : "=&r" (t) | ||
343 | : "r" (&v->counter) | ||
344 | : "cc", "memory"); | ||
345 | |||
346 | return t; | ||
347 | } | ||
348 | |||
349 | #define atomic64_sub_and_test(a, v) (atomic64_sub_return((a), (v)) == 0) | ||
350 | #define atomic64_dec_and_test(v) (atomic64_dec_return((v)) == 0) | ||
351 | |||
352 | /* | ||
353 | * Atomically test *v and decrement if it is greater than 0. | ||
354 | * The function returns the old value of *v minus 1. | ||
355 | */ | ||
356 | static __inline__ long atomic64_dec_if_positive(atomic64_t *v) | ||
357 | { | ||
358 | long t; | ||
359 | |||
360 | __asm__ __volatile__( | ||
361 | EIEIO_ON_SMP | ||
362 | "1: ldarx %0,0,%1 # atomic64_dec_if_positive\n\ | ||
363 | addic. %0,%0,-1\n\ | ||
364 | blt- 2f\n\ | ||
365 | stdcx. %0,0,%1\n\ | ||
366 | bne- 1b" | ||
367 | ISYNC_ON_SMP | ||
368 | "\n\ | ||
369 | 2:" : "=&r" (t) | ||
370 | : "r" (&v->counter) | ||
371 | : "cc", "memory"); | ||
372 | |||
373 | return t; | ||
374 | } | ||
375 | |||
376 | #endif /* __powerpc64__ */ | ||
377 | |||
208 | #endif /* __KERNEL__ */ | 378 | #endif /* __KERNEL__ */ |
209 | #endif /* _ASM_POWERPC_ATOMIC_H_ */ | 379 | #endif /* _ASM_POWERPC_ATOMIC_H_ */ |
diff --git a/include/asm-powerpc/bitops.h b/include/asm-powerpc/bitops.h index dc25c53704d5..5727229b0444 100644 --- a/include/asm-powerpc/bitops.h +++ b/include/asm-powerpc/bitops.h | |||
@@ -40,6 +40,7 @@ | |||
40 | 40 | ||
41 | #include <linux/compiler.h> | 41 | #include <linux/compiler.h> |
42 | #include <asm/atomic.h> | 42 | #include <asm/atomic.h> |
43 | #include <asm/asm-compat.h> | ||
43 | #include <asm/synch.h> | 44 | #include <asm/synch.h> |
44 | 45 | ||
45 | /* | 46 | /* |
@@ -52,16 +53,6 @@ | |||
52 | #define BITOP_WORD(nr) ((nr) / BITS_PER_LONG) | 53 | #define BITOP_WORD(nr) ((nr) / BITS_PER_LONG) |
53 | #define BITOP_LE_SWIZZLE ((BITS_PER_LONG-1) & ~0x7) | 54 | #define BITOP_LE_SWIZZLE ((BITS_PER_LONG-1) & ~0x7) |
54 | 55 | ||
55 | #ifdef CONFIG_PPC64 | ||
56 | #define LARXL "ldarx" | ||
57 | #define STCXL "stdcx." | ||
58 | #define CNTLZL "cntlzd" | ||
59 | #else | ||
60 | #define LARXL "lwarx" | ||
61 | #define STCXL "stwcx." | ||
62 | #define CNTLZL "cntlzw" | ||
63 | #endif | ||
64 | |||
65 | static __inline__ void set_bit(int nr, volatile unsigned long *addr) | 56 | static __inline__ void set_bit(int nr, volatile unsigned long *addr) |
66 | { | 57 | { |
67 | unsigned long old; | 58 | unsigned long old; |
@@ -69,10 +60,10 @@ static __inline__ void set_bit(int nr, volatile unsigned long *addr) | |||
69 | unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); | 60 | unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); |
70 | 61 | ||
71 | __asm__ __volatile__( | 62 | __asm__ __volatile__( |
72 | "1:" LARXL " %0,0,%3 # set_bit\n" | 63 | "1:" PPC_LLARX "%0,0,%3 # set_bit\n" |
73 | "or %0,%0,%2\n" | 64 | "or %0,%0,%2\n" |
74 | PPC405_ERR77(0,%3) | 65 | PPC405_ERR77(0,%3) |
75 | STCXL " %0,0,%3\n" | 66 | PPC_STLCX "%0,0,%3\n" |
76 | "bne- 1b" | 67 | "bne- 1b" |
77 | : "=&r"(old), "=m"(*p) | 68 | : "=&r"(old), "=m"(*p) |
78 | : "r"(mask), "r"(p), "m"(*p) | 69 | : "r"(mask), "r"(p), "m"(*p) |
@@ -86,10 +77,10 @@ static __inline__ void clear_bit(int nr, volatile unsigned long *addr) | |||
86 | unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); | 77 | unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); |
87 | 78 | ||
88 | __asm__ __volatile__( | 79 | __asm__ __volatile__( |
89 | "1:" LARXL " %0,0,%3 # set_bit\n" | 80 | "1:" PPC_LLARX "%0,0,%3 # clear_bit\n" |
90 | "andc %0,%0,%2\n" | 81 | "andc %0,%0,%2\n" |
91 | PPC405_ERR77(0,%3) | 82 | PPC405_ERR77(0,%3) |
92 | STCXL " %0,0,%3\n" | 83 | PPC_STLCX "%0,0,%3\n" |
93 | "bne- 1b" | 84 | "bne- 1b" |
94 | : "=&r"(old), "=m"(*p) | 85 | : "=&r"(old), "=m"(*p) |
95 | : "r"(mask), "r"(p), "m"(*p) | 86 | : "r"(mask), "r"(p), "m"(*p) |
@@ -103,10 +94,10 @@ static __inline__ void change_bit(int nr, volatile unsigned long *addr) | |||
103 | unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); | 94 | unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); |
104 | 95 | ||
105 | __asm__ __volatile__( | 96 | __asm__ __volatile__( |
106 | "1:" LARXL " %0,0,%3 # set_bit\n" | 97 | "1:" PPC_LLARX "%0,0,%3 # change_bit\n" |
107 | "xor %0,%0,%2\n" | 98 | "xor %0,%0,%2\n" |
108 | PPC405_ERR77(0,%3) | 99 | PPC405_ERR77(0,%3) |
109 | STCXL " %0,0,%3\n" | 100 | PPC_STLCX "%0,0,%3\n" |
110 | "bne- 1b" | 101 | "bne- 1b" |
111 | : "=&r"(old), "=m"(*p) | 102 | : "=&r"(old), "=m"(*p) |
112 | : "r"(mask), "r"(p), "m"(*p) | 103 | : "r"(mask), "r"(p), "m"(*p) |
@@ -122,10 +113,10 @@ static __inline__ int test_and_set_bit(unsigned long nr, | |||
122 | 113 | ||
123 | __asm__ __volatile__( | 114 | __asm__ __volatile__( |
124 | EIEIO_ON_SMP | 115 | EIEIO_ON_SMP |
125 | "1:" LARXL " %0,0,%3 # test_and_set_bit\n" | 116 | "1:" PPC_LLARX "%0,0,%3 # test_and_set_bit\n" |
126 | "or %1,%0,%2 \n" | 117 | "or %1,%0,%2 \n" |
127 | PPC405_ERR77(0,%3) | 118 | PPC405_ERR77(0,%3) |
128 | STCXL " %1,0,%3 \n" | 119 | PPC_STLCX "%1,0,%3 \n" |
129 | "bne- 1b" | 120 | "bne- 1b" |
130 | ISYNC_ON_SMP | 121 | ISYNC_ON_SMP |
131 | : "=&r" (old), "=&r" (t) | 122 | : "=&r" (old), "=&r" (t) |
@@ -144,10 +135,10 @@ static __inline__ int test_and_clear_bit(unsigned long nr, | |||
144 | 135 | ||
145 | __asm__ __volatile__( | 136 | __asm__ __volatile__( |
146 | EIEIO_ON_SMP | 137 | EIEIO_ON_SMP |
147 | "1:" LARXL " %0,0,%3 # test_and_clear_bit\n" | 138 | "1:" PPC_LLARX "%0,0,%3 # test_and_clear_bit\n" |
148 | "andc %1,%0,%2 \n" | 139 | "andc %1,%0,%2 \n" |
149 | PPC405_ERR77(0,%3) | 140 | PPC405_ERR77(0,%3) |
150 | STCXL " %1,0,%3 \n" | 141 | PPC_STLCX "%1,0,%3 \n" |
151 | "bne- 1b" | 142 | "bne- 1b" |
152 | ISYNC_ON_SMP | 143 | ISYNC_ON_SMP |
153 | : "=&r" (old), "=&r" (t) | 144 | : "=&r" (old), "=&r" (t) |
@@ -166,10 +157,10 @@ static __inline__ int test_and_change_bit(unsigned long nr, | |||
166 | 157 | ||
167 | __asm__ __volatile__( | 158 | __asm__ __volatile__( |
168 | EIEIO_ON_SMP | 159 | EIEIO_ON_SMP |
169 | "1:" LARXL " %0,0,%3 # test_and_change_bit\n" | 160 | "1:" PPC_LLARX "%0,0,%3 # test_and_change_bit\n" |
170 | "xor %1,%0,%2 \n" | 161 | "xor %1,%0,%2 \n" |
171 | PPC405_ERR77(0,%3) | 162 | PPC405_ERR77(0,%3) |
172 | STCXL " %1,0,%3 \n" | 163 | PPC_STLCX "%1,0,%3 \n" |
173 | "bne- 1b" | 164 | "bne- 1b" |
174 | ISYNC_ON_SMP | 165 | ISYNC_ON_SMP |
175 | : "=&r" (old), "=&r" (t) | 166 | : "=&r" (old), "=&r" (t) |
@@ -184,9 +175,9 @@ static __inline__ void set_bits(unsigned long mask, unsigned long *addr) | |||
184 | unsigned long old; | 175 | unsigned long old; |
185 | 176 | ||
186 | __asm__ __volatile__( | 177 | __asm__ __volatile__( |
187 | "1:" LARXL " %0,0,%3 # set_bit\n" | 178 | "1:" PPC_LLARX "%0,0,%3 # set_bits\n" |
188 | "or %0,%0,%2\n" | 179 | "or %0,%0,%2\n" |
189 | STCXL " %0,0,%3\n" | 180 | PPC_STLCX "%0,0,%3\n" |
190 | "bne- 1b" | 181 | "bne- 1b" |
191 | : "=&r" (old), "=m" (*addr) | 182 | : "=&r" (old), "=m" (*addr) |
192 | : "r" (mask), "r" (addr), "m" (*addr) | 183 | : "r" (mask), "r" (addr), "m" (*addr) |
@@ -268,7 +259,7 @@ static __inline__ int __ilog2(unsigned long x) | |||
268 | { | 259 | { |
269 | int lz; | 260 | int lz; |
270 | 261 | ||
271 | asm (CNTLZL " %0,%1" : "=r" (lz) : "r" (x)); | 262 | asm (PPC_CNTLZL "%0,%1" : "=r" (lz) : "r" (x)); |
272 | return BITS_PER_LONG - 1 - lz; | 263 | return BITS_PER_LONG - 1 - lz; |
273 | } | 264 | } |
274 | 265 | ||
diff --git a/include/asm-powerpc/bug.h b/include/asm-powerpc/bug.h index d625ee55f957..b001ecb3cd99 100644 --- a/include/asm-powerpc/bug.h +++ b/include/asm-powerpc/bug.h | |||
@@ -1,6 +1,7 @@ | |||
1 | #ifndef _ASM_POWERPC_BUG_H | 1 | #ifndef _ASM_POWERPC_BUG_H |
2 | #define _ASM_POWERPC_BUG_H | 2 | #define _ASM_POWERPC_BUG_H |
3 | 3 | ||
4 | #include <asm/asm-compat.h> | ||
4 | /* | 5 | /* |
5 | * Define an illegal instr to trap on the bug. | 6 | * Define an illegal instr to trap on the bug. |
6 | * We don't use 0 because that marks the end of a function | 7 | * We don't use 0 because that marks the end of a function |
@@ -11,14 +12,6 @@ | |||
11 | 12 | ||
12 | #ifndef __ASSEMBLY__ | 13 | #ifndef __ASSEMBLY__ |
13 | 14 | ||
14 | #ifdef __powerpc64__ | ||
15 | #define BUG_TABLE_ENTRY ".llong" | ||
16 | #define BUG_TRAP_OP "tdnei" | ||
17 | #else | ||
18 | #define BUG_TABLE_ENTRY ".long" | ||
19 | #define BUG_TRAP_OP "twnei" | ||
20 | #endif /* __powerpc64__ */ | ||
21 | |||
22 | struct bug_entry { | 15 | struct bug_entry { |
23 | unsigned long bug_addr; | 16 | unsigned long bug_addr; |
24 | long line; | 17 | long line; |
@@ -40,16 +33,16 @@ struct bug_entry *find_bug(unsigned long bugaddr); | |||
40 | __asm__ __volatile__( \ | 33 | __asm__ __volatile__( \ |
41 | "1: twi 31,0,0\n" \ | 34 | "1: twi 31,0,0\n" \ |
42 | ".section __bug_table,\"a\"\n" \ | 35 | ".section __bug_table,\"a\"\n" \ |
43 | "\t"BUG_TABLE_ENTRY" 1b,%0,%1,%2\n" \ | 36 | "\t"PPC_LONG" 1b,%0,%1,%2\n" \ |
44 | ".previous" \ | 37 | ".previous" \ |
45 | : : "i" (__LINE__), "i" (__FILE__), "i" (__FUNCTION__)); \ | 38 | : : "i" (__LINE__), "i" (__FILE__), "i" (__FUNCTION__)); \ |
46 | } while (0) | 39 | } while (0) |
47 | 40 | ||
48 | #define BUG_ON(x) do { \ | 41 | #define BUG_ON(x) do { \ |
49 | __asm__ __volatile__( \ | 42 | __asm__ __volatile__( \ |
50 | "1: "BUG_TRAP_OP" %0,0\n" \ | 43 | "1: "PPC_TLNEI" %0,0\n" \ |
51 | ".section __bug_table,\"a\"\n" \ | 44 | ".section __bug_table,\"a\"\n" \ |
52 | "\t"BUG_TABLE_ENTRY" 1b,%1,%2,%3\n" \ | 45 | "\t"PPC_LONG" 1b,%1,%2,%3\n" \ |
53 | ".previous" \ | 46 | ".previous" \ |
54 | : : "r" ((long)(x)), "i" (__LINE__), \ | 47 | : : "r" ((long)(x)), "i" (__LINE__), \ |
55 | "i" (__FILE__), "i" (__FUNCTION__)); \ | 48 | "i" (__FILE__), "i" (__FUNCTION__)); \ |
@@ -57,9 +50,9 @@ struct bug_entry *find_bug(unsigned long bugaddr); | |||
57 | 50 | ||
58 | #define WARN_ON(x) do { \ | 51 | #define WARN_ON(x) do { \ |
59 | __asm__ __volatile__( \ | 52 | __asm__ __volatile__( \ |
60 | "1: "BUG_TRAP_OP" %0,0\n" \ | 53 | "1: "PPC_TLNEI" %0,0\n" \ |
61 | ".section __bug_table,\"a\"\n" \ | 54 | ".section __bug_table,\"a\"\n" \ |
62 | "\t"BUG_TABLE_ENTRY" 1b,%1,%2,%3\n" \ | 55 | "\t"PPC_LONG" 1b,%1,%2,%3\n" \ |
63 | ".previous" \ | 56 | ".previous" \ |
64 | : : "r" ((long)(x)), \ | 57 | : : "r" ((long)(x)), \ |
65 | "i" (__LINE__ + BUG_WARNING_TRAP), \ | 58 | "i" (__LINE__ + BUG_WARNING_TRAP), \ |
diff --git a/include/asm-powerpc/cache.h b/include/asm-powerpc/cache.h new file mode 100644 index 000000000000..26ce502e76e8 --- /dev/null +++ b/include/asm-powerpc/cache.h | |||
@@ -0,0 +1,40 @@ | |||
1 | #ifndef _ASM_POWERPC_CACHE_H | ||
2 | #define _ASM_POWERPC_CACHE_H | ||
3 | |||
4 | #ifdef __KERNEL__ | ||
5 | |||
6 | #include <linux/config.h> | ||
7 | |||
8 | /* bytes per L1 cache line */ | ||
9 | #if defined(CONFIG_8xx) || defined(CONFIG_403GCX) | ||
10 | #define L1_CACHE_SHIFT 4 | ||
11 | #define MAX_COPY_PREFETCH 1 | ||
12 | #elif defined(CONFIG_PPC32) | ||
13 | #define L1_CACHE_SHIFT 5 | ||
14 | #define MAX_COPY_PREFETCH 4 | ||
15 | #else /* CONFIG_PPC64 */ | ||
16 | #define L1_CACHE_SHIFT 7 | ||
17 | #endif | ||
18 | |||
19 | #define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) | ||
20 | |||
21 | #define SMP_CACHE_BYTES L1_CACHE_BYTES | ||
22 | #define L1_CACHE_SHIFT_MAX 7 /* largest L1 which this arch supports */ | ||
23 | |||
24 | #if defined(__powerpc64__) && !defined(__ASSEMBLY__) | ||
25 | struct ppc64_caches { | ||
26 | u32 dsize; /* L1 d-cache size */ | ||
27 | u32 dline_size; /* L1 d-cache line size */ | ||
28 | u32 log_dline_size; | ||
29 | u32 dlines_per_page; | ||
30 | u32 isize; /* L1 i-cache size */ | ||
31 | u32 iline_size; /* L1 i-cache line size */ | ||
32 | u32 log_iline_size; | ||
33 | u32 ilines_per_page; | ||
34 | }; | ||
35 | |||
36 | extern struct ppc64_caches ppc64_caches; | ||
37 | #endif /* __powerpc64__ && ! __ASSEMBLY__ */ | ||
38 | |||
39 | #endif /* __KERNEL__ */ | ||
40 | #endif /* _ASM_POWERPC_CACHE_H */ | ||
diff --git a/include/asm-ppc64/cacheflush.h b/include/asm-powerpc/cacheflush.h index ffbc08be8e52..8a740c88d93d 100644 --- a/include/asm-ppc64/cacheflush.h +++ b/include/asm-powerpc/cacheflush.h | |||
@@ -1,13 +1,20 @@ | |||
1 | #ifndef _PPC64_CACHEFLUSH_H | 1 | /* |
2 | #define _PPC64_CACHEFLUSH_H | 2 | * This program is free software; you can redistribute it and/or |
3 | * modify it under the terms of the GNU General Public License | ||
4 | * as published by the Free Software Foundation; either version | ||
5 | * 2 of the License, or (at your option) any later version. | ||
6 | */ | ||
7 | #ifndef _ASM_POWERPC_CACHEFLUSH_H | ||
8 | #define _ASM_POWERPC_CACHEFLUSH_H | ||
9 | |||
10 | #ifdef __KERNEL__ | ||
3 | 11 | ||
4 | #include <linux/mm.h> | 12 | #include <linux/mm.h> |
5 | #include <asm/cputable.h> | 13 | #include <asm/cputable.h> |
6 | 14 | ||
7 | /* | 15 | /* |
8 | * No cache flushing is required when address mappings are | 16 | * No cache flushing is required when address mappings are changed, |
9 | * changed, because the caches on PowerPCs are physically | 17 | * because the caches on PowerPCs are physically addressed. |
10 | * addressed. | ||
11 | */ | 18 | */ |
12 | #define flush_cache_all() do { } while (0) | 19 | #define flush_cache_all() do { } while (0) |
13 | #define flush_cache_mm(mm) do { } while (0) | 20 | #define flush_cache_mm(mm) do { } while (0) |
@@ -22,27 +29,40 @@ extern void flush_dcache_page(struct page *page); | |||
22 | #define flush_dcache_mmap_unlock(mapping) do { } while (0) | 29 | #define flush_dcache_mmap_unlock(mapping) do { } while (0) |
23 | 30 | ||
24 | extern void __flush_icache_range(unsigned long, unsigned long); | 31 | extern void __flush_icache_range(unsigned long, unsigned long); |
32 | static inline void flush_icache_range(unsigned long start, unsigned long stop) | ||
33 | { | ||
34 | if (!cpu_has_feature(CPU_FTR_COHERENT_ICACHE)) | ||
35 | __flush_icache_range(start, stop); | ||
36 | } | ||
37 | |||
25 | extern void flush_icache_user_range(struct vm_area_struct *vma, | 38 | extern void flush_icache_user_range(struct vm_area_struct *vma, |
26 | struct page *page, unsigned long addr, | 39 | struct page *page, unsigned long addr, |
27 | int len); | 40 | int len); |
41 | extern void __flush_dcache_icache(void *page_va); | ||
42 | extern void flush_dcache_icache_page(struct page *page); | ||
43 | #if defined(CONFIG_PPC32) && !defined(CONFIG_BOOKE) | ||
44 | extern void __flush_dcache_icache_phys(unsigned long physaddr); | ||
45 | #endif /* CONFIG_PPC32 && !CONFIG_BOOKE */ | ||
28 | 46 | ||
29 | extern void flush_dcache_range(unsigned long start, unsigned long stop); | 47 | extern void flush_dcache_range(unsigned long start, unsigned long stop); |
30 | extern void flush_dcache_phys_range(unsigned long start, unsigned long stop); | 48 | #ifdef CONFIG_PPC32 |
49 | extern void clean_dcache_range(unsigned long start, unsigned long stop); | ||
50 | extern void invalidate_dcache_range(unsigned long start, unsigned long stop); | ||
51 | #endif /* CONFIG_PPC32 */ | ||
52 | #ifdef CONFIG_PPC64 | ||
31 | extern void flush_inval_dcache_range(unsigned long start, unsigned long stop); | 53 | extern void flush_inval_dcache_range(unsigned long start, unsigned long stop); |
54 | extern void flush_dcache_phys_range(unsigned long start, unsigned long stop); | ||
55 | #endif | ||
32 | 56 | ||
33 | #define copy_to_user_page(vma, page, vaddr, dst, src, len) \ | 57 | #define copy_to_user_page(vma, page, vaddr, dst, src, len) \ |
34 | do { memcpy(dst, src, len); \ | 58 | do { \ |
35 | flush_icache_user_range(vma, page, vaddr, len); \ | 59 | memcpy(dst, src, len); \ |
36 | } while (0) | 60 | flush_icache_user_range(vma, page, vaddr, len); \ |
61 | } while (0) | ||
37 | #define copy_from_user_page(vma, page, vaddr, dst, src, len) \ | 62 | #define copy_from_user_page(vma, page, vaddr, dst, src, len) \ |
38 | memcpy(dst, src, len) | 63 | memcpy(dst, src, len) |
39 | 64 | ||
40 | extern void __flush_dcache_icache(void *page_va); | ||
41 | 65 | ||
42 | static inline void flush_icache_range(unsigned long start, unsigned long stop) | 66 | #endif /* __KERNEL__ */ |
43 | { | ||
44 | if (!cpu_has_feature(CPU_FTR_COHERENT_ICACHE)) | ||
45 | __flush_icache_range(start, stop); | ||
46 | } | ||
47 | 67 | ||
48 | #endif /* _PPC64_CACHEFLUSH_H */ | 68 | #endif /* _ASM_POWERPC_CACHEFLUSH_H */ |
diff --git a/include/asm-ppc64/compat.h b/include/asm-powerpc/compat.h index 6ec62cd2d1d1..4db4360c4d4a 100644 --- a/include/asm-ppc64/compat.h +++ b/include/asm-powerpc/compat.h | |||
@@ -1,5 +1,5 @@ | |||
1 | #ifndef _ASM_PPC64_COMPAT_H | 1 | #ifndef _ASM_POWERPC_COMPAT_H |
2 | #define _ASM_PPC64_COMPAT_H | 2 | #define _ASM_POWERPC_COMPAT_H |
3 | /* | 3 | /* |
4 | * Architecture specific compatibility types | 4 | * Architecture specific compatibility types |
5 | */ | 5 | */ |
@@ -49,7 +49,7 @@ struct compat_stat { | |||
49 | compat_dev_t st_dev; | 49 | compat_dev_t st_dev; |
50 | compat_ino_t st_ino; | 50 | compat_ino_t st_ino; |
51 | compat_mode_t st_mode; | 51 | compat_mode_t st_mode; |
52 | compat_nlink_t st_nlink; | 52 | compat_nlink_t st_nlink; |
53 | __compat_uid32_t st_uid; | 53 | __compat_uid32_t st_uid; |
54 | __compat_gid32_t st_gid; | 54 | __compat_gid32_t st_gid; |
55 | compat_dev_t st_rdev; | 55 | compat_dev_t st_rdev; |
@@ -202,4 +202,4 @@ struct compat_shmid64_ds { | |||
202 | compat_ulong_t __unused6; | 202 | compat_ulong_t __unused6; |
203 | }; | 203 | }; |
204 | 204 | ||
205 | #endif /* _ASM_PPC64_COMPAT_H */ | 205 | #endif /* _ASM_POWERPC_COMPAT_H */ |
diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h index 79a0556a0ab8..04e2726002cf 100644 --- a/include/asm-powerpc/cputable.h +++ b/include/asm-powerpc/cputable.h | |||
@@ -2,7 +2,7 @@ | |||
2 | #define __ASM_POWERPC_CPUTABLE_H | 2 | #define __ASM_POWERPC_CPUTABLE_H |
3 | 3 | ||
4 | #include <linux/config.h> | 4 | #include <linux/config.h> |
5 | #include <asm/ppc_asm.h> /* for ASM_CONST */ | 5 | #include <asm/asm-compat.h> |
6 | 6 | ||
7 | #define PPC_FEATURE_32 0x80000000 | 7 | #define PPC_FEATURE_32 0x80000000 |
8 | #define PPC_FEATURE_64 0x40000000 | 8 | #define PPC_FEATURE_64 0x40000000 |
@@ -16,6 +16,10 @@ | |||
16 | #define PPC_FEATURE_HAS_EFP_SINGLE 0x00400000 | 16 | #define PPC_FEATURE_HAS_EFP_SINGLE 0x00400000 |
17 | #define PPC_FEATURE_HAS_EFP_DOUBLE 0x00200000 | 17 | #define PPC_FEATURE_HAS_EFP_DOUBLE 0x00200000 |
18 | #define PPC_FEATURE_NO_TB 0x00100000 | 18 | #define PPC_FEATURE_NO_TB 0x00100000 |
19 | #define PPC_FEATURE_POWER4 0x00080000 | ||
20 | #define PPC_FEATURE_POWER5 0x00040000 | ||
21 | #define PPC_FEATURE_POWER5_PLUS 0x00020000 | ||
22 | #define PPC_FEATURE_CELL 0x00010000 | ||
19 | 23 | ||
20 | #ifdef __KERNEL__ | 24 | #ifdef __KERNEL__ |
21 | #ifndef __ASSEMBLY__ | 25 | #ifndef __ASSEMBLY__ |
diff --git a/include/asm-powerpc/current.h b/include/asm-powerpc/current.h new file mode 100644 index 000000000000..82cd4a9ca99a --- /dev/null +++ b/include/asm-powerpc/current.h | |||
@@ -0,0 +1,27 @@ | |||
1 | #ifndef _ASM_POWERPC_CURRENT_H | ||
2 | #define _ASM_POWERPC_CURRENT_H | ||
3 | |||
4 | /* | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License | ||
7 | * as published by the Free Software Foundation; either version | ||
8 | * 2 of the License, or (at your option) any later version. | ||
9 | */ | ||
10 | |||
11 | struct task_struct; | ||
12 | |||
13 | #ifdef __powerpc64__ | ||
14 | #include <asm/paca.h> | ||
15 | |||
16 | #define current (get_paca()->__current) | ||
17 | |||
18 | #else | ||
19 | |||
20 | /* | ||
21 | * We keep `current' in r2 for speed. | ||
22 | */ | ||
23 | register struct task_struct *current asm ("r2"); | ||
24 | |||
25 | #endif | ||
26 | |||
27 | #endif /* _ASM_POWERPC_CURRENT_H */ | ||
diff --git a/include/asm-powerpc/eeh_event.h b/include/asm-powerpc/eeh_event.h new file mode 100644 index 000000000000..d168a30b3866 --- /dev/null +++ b/include/asm-powerpc/eeh_event.h | |||
@@ -0,0 +1,52 @@ | |||
1 | /* | ||
2 | * eeh_event.h | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
17 | * | ||
18 | * Copyright (c) 2005 Linas Vepstas <linas@linas.org> | ||
19 | */ | ||
20 | |||
21 | #ifndef ASM_PPC64_EEH_EVENT_H | ||
22 | #define ASM_PPC64_EEH_EVENT_H | ||
23 | |||
24 | /** EEH event -- structure holding pci controller data that describes | ||
25 | * a change in the isolation status of a PCI slot. A pointer | ||
26 | * to this struct is passed as the data pointer in a notify callback. | ||
27 | */ | ||
28 | struct eeh_event { | ||
29 | struct list_head list; | ||
30 | struct device_node *dn; /* struct device node */ | ||
31 | struct pci_dev *dev; /* affected device */ | ||
32 | int state; | ||
33 | int time_unavail; /* milliseconds until device might be available */ | ||
34 | }; | ||
35 | |||
36 | /** | ||
37 | * eeh_send_failure_event - generate a PCI error event | ||
38 | * @dev pci device | ||
39 | * | ||
40 | * This routine builds a PCI error event which will be delivered | ||
41 | * to all listeners on the peh_notifier_chain. | ||
42 | * | ||
43 | * This routine can be called within an interrupt context; | ||
44 | * the actual event will be delivered in a normal context | ||
45 | * (from a workqueue). | ||
46 | */ | ||
47 | int eeh_send_failure_event (struct device_node *dn, | ||
48 | struct pci_dev *dev, | ||
49 | int reset_state, | ||
50 | int time_unavail); | ||
51 | |||
52 | #endif /* ASM_PPC64_EEH_EVENT_H */ | ||
diff --git a/include/asm-powerpc/firmware.h b/include/asm-powerpc/firmware.h index 806c142ae9ea..12fabbcb04f0 100644 --- a/include/asm-powerpc/firmware.h +++ b/include/asm-powerpc/firmware.h | |||
@@ -43,6 +43,7 @@ | |||
43 | #define FW_FEATURE_ISERIES (1UL<<21) | 43 | #define FW_FEATURE_ISERIES (1UL<<21) |
44 | 44 | ||
45 | enum { | 45 | enum { |
46 | #ifdef CONFIG_PPC64 | ||
46 | FW_FEATURE_PSERIES_POSSIBLE = FW_FEATURE_PFT | FW_FEATURE_TCE | | 47 | FW_FEATURE_PSERIES_POSSIBLE = FW_FEATURE_PFT | FW_FEATURE_TCE | |
47 | FW_FEATURE_SPRG0 | FW_FEATURE_DABR | FW_FEATURE_COPY | | 48 | FW_FEATURE_SPRG0 | FW_FEATURE_DABR | FW_FEATURE_COPY | |
48 | FW_FEATURE_ASR | FW_FEATURE_DEBUG | FW_FEATURE_TERM | | 49 | FW_FEATURE_ASR | FW_FEATURE_DEBUG | FW_FEATURE_TERM | |
@@ -70,6 +71,11 @@ enum { | |||
70 | FW_FEATURE_ISERIES_ALWAYS & | 71 | FW_FEATURE_ISERIES_ALWAYS & |
71 | #endif | 72 | #endif |
72 | FW_FEATURE_POSSIBLE, | 73 | FW_FEATURE_POSSIBLE, |
74 | |||
75 | #else /* CONFIG_PPC64 */ | ||
76 | FW_FEATURE_POSSIBLE = 0, | ||
77 | FW_FEATURE_ALWAYS = 0, | ||
78 | #endif | ||
73 | }; | 79 | }; |
74 | 80 | ||
75 | /* This is used to identify firmware features which are available | 81 | /* This is used to identify firmware features which are available |
diff --git a/include/asm-powerpc/futex.h b/include/asm-powerpc/futex.h index 37c94e52ab6d..f0319d50b129 100644 --- a/include/asm-powerpc/futex.h +++ b/include/asm-powerpc/futex.h | |||
@@ -7,13 +7,14 @@ | |||
7 | #include <asm/errno.h> | 7 | #include <asm/errno.h> |
8 | #include <asm/synch.h> | 8 | #include <asm/synch.h> |
9 | #include <asm/uaccess.h> | 9 | #include <asm/uaccess.h> |
10 | #include <asm/ppc_asm.h> | 10 | #include <asm/asm-compat.h> |
11 | 11 | ||
12 | #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \ | 12 | #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \ |
13 | __asm__ __volatile ( \ | 13 | __asm__ __volatile ( \ |
14 | SYNC_ON_SMP \ | 14 | SYNC_ON_SMP \ |
15 | "1: lwarx %0,0,%2\n" \ | 15 | "1: lwarx %0,0,%2\n" \ |
16 | insn \ | 16 | insn \ |
17 | PPC405_ERR77(0, %2) \ | ||
17 | "2: stwcx. %1,0,%2\n" \ | 18 | "2: stwcx. %1,0,%2\n" \ |
18 | "bne- 1b\n" \ | 19 | "bne- 1b\n" \ |
19 | "li %1,0\n" \ | 20 | "li %1,0\n" \ |
@@ -23,7 +24,7 @@ | |||
23 | ".previous\n" \ | 24 | ".previous\n" \ |
24 | ".section __ex_table,\"a\"\n" \ | 25 | ".section __ex_table,\"a\"\n" \ |
25 | ".align 3\n" \ | 26 | ".align 3\n" \ |
26 | DATAL " 1b,4b,2b,4b\n" \ | 27 | PPC_LONG "1b,4b,2b,4b\n" \ |
27 | ".previous" \ | 28 | ".previous" \ |
28 | : "=&r" (oldval), "=&r" (ret) \ | 29 | : "=&r" (oldval), "=&r" (ret) \ |
29 | : "b" (uaddr), "i" (-EFAULT), "1" (oparg) \ | 30 | : "b" (uaddr), "i" (-EFAULT), "1" (oparg) \ |
diff --git a/include/asm-ppc64/hvcall.h b/include/asm-powerpc/hvcall.h index ab7c3cf24888..d36da61dbc53 100644 --- a/include/asm-ppc64/hvcall.h +++ b/include/asm-powerpc/hvcall.h | |||
@@ -1,5 +1,5 @@ | |||
1 | #ifndef _PPC64_HVCALL_H | 1 | #ifndef _ASM_POWERPC_HVCALL_H |
2 | #define _PPC64_HVCALL_H | 2 | #define _ASM_POWERPC_HVCALL_H |
3 | 3 | ||
4 | #define HVSC .long 0x44000022 | 4 | #define HVSC .long 0x44000022 |
5 | 5 | ||
@@ -138,7 +138,7 @@ long plpar_hcall(unsigned long opcode, | |||
138 | */ | 138 | */ |
139 | long plpar_hcall_norets(unsigned long opcode, ...); | 139 | long plpar_hcall_norets(unsigned long opcode, ...); |
140 | 140 | ||
141 | /* | 141 | /* |
142 | * Special hcall interface for ibmveth support. | 142 | * Special hcall interface for ibmveth support. |
143 | * Takes 8 input parms. Returns a rc and stores the | 143 | * Takes 8 input parms. Returns a rc and stores the |
144 | * R4 return value in *out1. | 144 | * R4 return value in *out1. |
@@ -153,11 +153,11 @@ long plpar_hcall_8arg_2ret(unsigned long opcode, | |||
153 | unsigned long arg7, | 153 | unsigned long arg7, |
154 | unsigned long arg8, | 154 | unsigned long arg8, |
155 | unsigned long *out1); | 155 | unsigned long *out1); |
156 | 156 | ||
157 | /* plpar_hcall_4out() | 157 | /* plpar_hcall_4out() |
158 | * | 158 | * |
159 | * same as plpar_hcall except with 4 output arguments. | 159 | * same as plpar_hcall except with 4 output arguments. |
160 | * | 160 | * |
161 | */ | 161 | */ |
162 | long plpar_hcall_4out(unsigned long opcode, | 162 | long plpar_hcall_4out(unsigned long opcode, |
163 | unsigned long arg1, | 163 | unsigned long arg1, |
@@ -170,4 +170,4 @@ long plpar_hcall_4out(unsigned long opcode, | |||
170 | unsigned long *out4); | 170 | unsigned long *out4); |
171 | 171 | ||
172 | #endif /* __ASSEMBLY__ */ | 172 | #endif /* __ASSEMBLY__ */ |
173 | #endif /* _PPC64_HVCALL_H */ | 173 | #endif /* _ASM_POWERPC_HVCALL_H */ |
diff --git a/include/asm-powerpc/hw_irq.h b/include/asm-powerpc/hw_irq.h index c37b31b96337..26b89d859c56 100644 --- a/include/asm-powerpc/hw_irq.h +++ b/include/asm-powerpc/hw_irq.h | |||
@@ -12,7 +12,6 @@ | |||
12 | #include <asm/processor.h> | 12 | #include <asm/processor.h> |
13 | 13 | ||
14 | extern void timer_interrupt(struct pt_regs *); | 14 | extern void timer_interrupt(struct pt_regs *); |
15 | extern void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq); | ||
16 | 15 | ||
17 | #ifdef CONFIG_PPC_ISERIES | 16 | #ifdef CONFIG_PPC_ISERIES |
18 | 17 | ||
diff --git a/include/asm-powerpc/irq.h b/include/asm-powerpc/irq.h index b3935ea28fff..c9fbcede0ef9 100644 --- a/include/asm-powerpc/irq.h +++ b/include/asm-powerpc/irq.h | |||
@@ -429,7 +429,6 @@ extern u64 ppc64_interrupt_controller; | |||
429 | #define NR_MASK_WORDS ((NR_IRQS + 31) / 32) | 429 | #define NR_MASK_WORDS ((NR_IRQS + 31) / 32) |
430 | /* pedantic: these are long because they are used with set_bit --RR */ | 430 | /* pedantic: these are long because they are used with set_bit --RR */ |
431 | extern unsigned long ppc_cached_irq_mask[NR_MASK_WORDS]; | 431 | extern unsigned long ppc_cached_irq_mask[NR_MASK_WORDS]; |
432 | extern unsigned long ppc_lost_interrupts[NR_MASK_WORDS]; | ||
433 | extern atomic_t ppc_n_lost_interrupts; | 432 | extern atomic_t ppc_n_lost_interrupts; |
434 | 433 | ||
435 | #define virt_irq_create_mapping(x) (x) | 434 | #define virt_irq_create_mapping(x) (x) |
@@ -488,8 +487,8 @@ extern struct thread_info *softirq_ctx[NR_CPUS]; | |||
488 | 487 | ||
489 | extern void irq_ctx_init(void); | 488 | extern void irq_ctx_init(void); |
490 | extern void call_do_softirq(struct thread_info *tp); | 489 | extern void call_do_softirq(struct thread_info *tp); |
491 | extern int call_handle_IRQ_event(int irq, struct pt_regs *regs, | 490 | extern int call___do_IRQ(int irq, struct pt_regs *regs, |
492 | struct irqaction *action, struct thread_info *tp); | 491 | struct thread_info *tp); |
493 | 492 | ||
494 | #define __ARCH_HAS_DO_SOFTIRQ | 493 | #define __ARCH_HAS_DO_SOFTIRQ |
495 | 494 | ||
diff --git a/include/asm-ppc64/lppaca.h b/include/asm-powerpc/lppaca.h index 9e2a6c0649a0..c1bedab1515b 100644 --- a/include/asm-ppc64/lppaca.h +++ b/include/asm-powerpc/lppaca.h | |||
@@ -16,8 +16,8 @@ | |||
16 | * along with this program; if not, write to the Free Software | 16 | * along with this program; if not, write to the Free Software |
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
18 | */ | 18 | */ |
19 | #ifndef _ASM_LPPACA_H | 19 | #ifndef _ASM_POWERPC_LPPACA_H |
20 | #define _ASM_LPPACA_H | 20 | #define _ASM_POWERPC_LPPACA_H |
21 | 21 | ||
22 | //============================================================================= | 22 | //============================================================================= |
23 | // | 23 | // |
@@ -28,8 +28,7 @@ | |||
28 | //---------------------------------------------------------------------------- | 28 | //---------------------------------------------------------------------------- |
29 | #include <asm/types.h> | 29 | #include <asm/types.h> |
30 | 30 | ||
31 | struct lppaca | 31 | struct lppaca { |
32 | { | ||
33 | //============================================================================= | 32 | //============================================================================= |
34 | // CACHE_LINE_1 0x0000 - 0x007F Contains read-only data | 33 | // CACHE_LINE_1 0x0000 - 0x007F Contains read-only data |
35 | // NOTE: The xDynXyz fields are fields that will be dynamically changed by | 34 | // NOTE: The xDynXyz fields are fields that will be dynamically changed by |
@@ -129,4 +128,4 @@ struct lppaca | |||
129 | u8 pmc_save_area[256]; // PMC interrupt Area x00-xFF | 128 | u8 pmc_save_area[256]; // PMC interrupt Area x00-xFF |
130 | }; | 129 | }; |
131 | 130 | ||
132 | #endif /* _ASM_LPPACA_H */ | 131 | #endif /* _ASM_POWERPC_LPPACA_H */ |
diff --git a/include/asm-ppc64/paca.h b/include/asm-powerpc/paca.h index bccacd6aa93a..92c765c35bd0 100644 --- a/include/asm-ppc64/paca.h +++ b/include/asm-powerpc/paca.h | |||
@@ -1,11 +1,8 @@ | |||
1 | #ifndef _PPC64_PACA_H | ||
2 | #define _PPC64_PACA_H | ||
3 | |||
4 | /* | 1 | /* |
5 | * include/asm-ppc64/paca.h | 2 | * include/asm-powerpc/paca.h |
6 | * | 3 | * |
7 | * This control block defines the PACA which defines the processor | 4 | * This control block defines the PACA which defines the processor |
8 | * specific data for each logical processor on the system. | 5 | * specific data for each logical processor on the system. |
9 | * There are some pointers defined that are utilized by PLIC. | 6 | * There are some pointers defined that are utilized by PLIC. |
10 | * | 7 | * |
11 | * C 2001 PPC 64 Team, IBM Corp | 8 | * C 2001 PPC 64 Team, IBM Corp |
@@ -14,7 +11,9 @@ | |||
14 | * modify it under the terms of the GNU General Public License | 11 | * modify it under the terms of the GNU General Public License |
15 | * as published by the Free Software Foundation; either version | 12 | * as published by the Free Software Foundation; either version |
16 | * 2 of the License, or (at your option) any later version. | 13 | * 2 of the License, or (at your option) any later version. |
17 | */ | 14 | */ |
15 | #ifndef _ASM_POWERPC_PACA_H | ||
16 | #define _ASM_POWERPC_PACA_H | ||
18 | 17 | ||
19 | #include <linux/config.h> | 18 | #include <linux/config.h> |
20 | #include <asm/types.h> | 19 | #include <asm/types.h> |
@@ -118,4 +117,4 @@ struct paca_struct { | |||
118 | 117 | ||
119 | extern struct paca_struct paca[]; | 118 | extern struct paca_struct paca[]; |
120 | 119 | ||
121 | #endif /* _PPC64_PACA_H */ | 120 | #endif /* _ASM_POWERPC_PACA_H */ |
diff --git a/include/asm-powerpc/ppc-pci.h b/include/asm-powerpc/ppc-pci.h index 13aacff755f3..9896fade98a7 100644 --- a/include/asm-powerpc/ppc-pci.h +++ b/include/asm-powerpc/ppc-pci.h | |||
@@ -26,6 +26,10 @@ extern unsigned long find_and_init_phbs(void); | |||
26 | 26 | ||
27 | extern struct pci_dev *ppc64_isabridge_dev; /* may be NULL if no ISA bus */ | 27 | extern struct pci_dev *ppc64_isabridge_dev; /* may be NULL if no ISA bus */ |
28 | 28 | ||
29 | /** Bus Unit ID macros; get low and hi 32-bits of the 64-bit BUID */ | ||
30 | #define BUID_HI(buid) ((buid) >> 32) | ||
31 | #define BUID_LO(buid) ((buid) & 0xffffffff) | ||
32 | |||
29 | /* PCI device_node operations */ | 33 | /* PCI device_node operations */ |
30 | struct device_node; | 34 | struct device_node; |
31 | typedef void *(*traverse_func)(struct device_node *me, void *data); | 35 | typedef void *(*traverse_func)(struct device_node *me, void *data); |
@@ -36,10 +40,6 @@ void pci_devs_phb_init(void); | |||
36 | void pci_devs_phb_init_dynamic(struct pci_controller *phb); | 40 | void pci_devs_phb_init_dynamic(struct pci_controller *phb); |
37 | void __devinit scan_phb(struct pci_controller *hose); | 41 | void __devinit scan_phb(struct pci_controller *hose); |
38 | 42 | ||
39 | /* PCI address cache management routines */ | ||
40 | void pci_addr_cache_insert_device(struct pci_dev *dev); | ||
41 | void pci_addr_cache_remove_device(struct pci_dev *dev); | ||
42 | |||
43 | /* From rtas_pci.h */ | 43 | /* From rtas_pci.h */ |
44 | void init_pci_config_tokens (void); | 44 | void init_pci_config_tokens (void); |
45 | unsigned long get_phb_buid (struct device_node *); | 45 | unsigned long get_phb_buid (struct device_node *); |
@@ -52,4 +52,48 @@ extern unsigned long pci_probe_only; | |||
52 | extern unsigned long pci_assign_all_buses; | 52 | extern unsigned long pci_assign_all_buses; |
53 | extern int pci_read_irq_line(struct pci_dev *pci_dev); | 53 | extern int pci_read_irq_line(struct pci_dev *pci_dev); |
54 | 54 | ||
55 | /* ---- EEH internal-use-only related routines ---- */ | ||
56 | #ifdef CONFIG_EEH | ||
57 | /** | ||
58 | * rtas_set_slot_reset -- unfreeze a frozen slot | ||
59 | * | ||
60 | * Clear the EEH-frozen condition on a slot. This routine | ||
61 | * does this by asserting the PCI #RST line for 1/8th of | ||
62 | * a second; this routine will sleep while the adapter is | ||
63 | * being reset. | ||
64 | */ | ||
65 | void rtas_set_slot_reset (struct pci_dn *); | ||
66 | |||
67 | /** | ||
68 | * eeh_restore_bars - Restore device configuration info. | ||
69 | * | ||
70 | * A reset of a PCI device will clear out its config space. | ||
71 | * This routines will restore the config space for this | ||
72 | * device, and is children, to values previously obtained | ||
73 | * from the firmware. | ||
74 | */ | ||
75 | void eeh_restore_bars(struct pci_dn *); | ||
76 | |||
77 | /** | ||
78 | * rtas_configure_bridge -- firmware initialization of pci bridge | ||
79 | * | ||
80 | * Ask the firmware to configure all PCI bridges devices | ||
81 | * located behind the indicated node. Required after a | ||
82 | * pci device reset. Does essentially the same hing as | ||
83 | * eeh_restore_bars, but for brdges, and lets firmware | ||
84 | * do the work. | ||
85 | */ | ||
86 | void rtas_configure_bridge(struct pci_dn *); | ||
87 | |||
88 | int rtas_write_config(struct pci_dn *, int where, int size, u32 val); | ||
89 | |||
90 | /** | ||
91 | * mark and clear slots: find "partition endpoint" PE and set or | ||
92 | * clear the flags for each subnode of the PE. | ||
93 | */ | ||
94 | void eeh_mark_slot (struct device_node *dn, int mode_flag); | ||
95 | void eeh_clear_slot (struct device_node *dn, int mode_flag); | ||
96 | |||
97 | #endif | ||
98 | |||
55 | #endif /* _ASM_POWERPC_PPC_PCI_H */ | 99 | #endif /* _ASM_POWERPC_PPC_PCI_H */ |
diff --git a/include/asm-powerpc/ppc_asm.h b/include/asm-powerpc/ppc_asm.h index c534ca41224b..c27baa0563fe 100644 --- a/include/asm-powerpc/ppc_asm.h +++ b/include/asm-powerpc/ppc_asm.h | |||
@@ -6,8 +6,13 @@ | |||
6 | 6 | ||
7 | #include <linux/stringify.h> | 7 | #include <linux/stringify.h> |
8 | #include <linux/config.h> | 8 | #include <linux/config.h> |
9 | #include <asm/asm-compat.h> | ||
9 | 10 | ||
10 | #ifdef __ASSEMBLY__ | 11 | #ifndef __ASSEMBLY__ |
12 | #error __FILE__ should only be used in assembler files | ||
13 | #else | ||
14 | |||
15 | #define SZL (BITS_PER_LONG/8) | ||
11 | 16 | ||
12 | /* | 17 | /* |
13 | * Macros for storing registers into and loading registers from | 18 | * Macros for storing registers into and loading registers from |
@@ -184,12 +189,6 @@ n: | |||
184 | oris reg,reg,(label)@h; \ | 189 | oris reg,reg,(label)@h; \ |
185 | ori reg,reg,(label)@l; | 190 | ori reg,reg,(label)@l; |
186 | 191 | ||
187 | /* operations for longs and pointers */ | ||
188 | #define LDL ld | ||
189 | #define STL std | ||
190 | #define CMPI cmpdi | ||
191 | #define SZL 8 | ||
192 | |||
193 | /* offsets for stack frame layout */ | 192 | /* offsets for stack frame layout */ |
194 | #define LRSAVE 16 | 193 | #define LRSAVE 16 |
195 | 194 | ||
@@ -203,12 +202,6 @@ n: | |||
203 | 202 | ||
204 | #define OFF(name) name@l | 203 | #define OFF(name) name@l |
205 | 204 | ||
206 | /* operations for longs and pointers */ | ||
207 | #define LDL lwz | ||
208 | #define STL stw | ||
209 | #define CMPI cmpwi | ||
210 | #define SZL 4 | ||
211 | |||
212 | /* offsets for stack frame layout */ | 205 | /* offsets for stack frame layout */ |
213 | #define LRSAVE 4 | 206 | #define LRSAVE 4 |
214 | 207 | ||
@@ -266,15 +259,6 @@ END_FTR_SECTION_IFCLR(CPU_FTR_601) | |||
266 | #endif | 259 | #endif |
267 | 260 | ||
268 | 261 | ||
269 | #ifdef CONFIG_IBM405_ERR77 | ||
270 | #define PPC405_ERR77(ra,rb) dcbt ra, rb; | ||
271 | #define PPC405_ERR77_SYNC sync; | ||
272 | #else | ||
273 | #define PPC405_ERR77(ra,rb) | ||
274 | #define PPC405_ERR77_SYNC | ||
275 | #endif | ||
276 | |||
277 | |||
278 | #ifdef CONFIG_IBM440EP_ERR42 | 262 | #ifdef CONFIG_IBM440EP_ERR42 |
279 | #define PPC440EP_ERR42 isync | 263 | #define PPC440EP_ERR42 isync |
280 | #else | 264 | #else |
@@ -502,17 +486,6 @@ END_FTR_SECTION_IFCLR(CPU_FTR_601) | |||
502 | #define N_SLINE 68 | 486 | #define N_SLINE 68 |
503 | #define N_SO 100 | 487 | #define N_SO 100 |
504 | 488 | ||
505 | #define ASM_CONST(x) x | ||
506 | #else | ||
507 | #define __ASM_CONST(x) x##UL | ||
508 | #define ASM_CONST(x) __ASM_CONST(x) | ||
509 | |||
510 | #ifdef CONFIG_PPC64 | ||
511 | #define DATAL ".llong" | ||
512 | #else | ||
513 | #define DATAL ".long" | ||
514 | #endif | ||
515 | |||
516 | #endif /* __ASSEMBLY__ */ | 489 | #endif /* __ASSEMBLY__ */ |
517 | 490 | ||
518 | #endif /* _ASM_POWERPC_PPC_ASM_H */ | 491 | #endif /* _ASM_POWERPC_PPC_ASM_H */ |
diff --git a/include/asm-powerpc/processor.h b/include/asm-powerpc/processor.h index 1dc4bf7b52b3..f6f186b56b0f 100644 --- a/include/asm-powerpc/processor.h +++ b/include/asm-powerpc/processor.h | |||
@@ -17,65 +17,71 @@ | |||
17 | #include <linux/compiler.h> | 17 | #include <linux/compiler.h> |
18 | #include <asm/ptrace.h> | 18 | #include <asm/ptrace.h> |
19 | #include <asm/types.h> | 19 | #include <asm/types.h> |
20 | #ifdef CONFIG_PPC64 | ||
21 | #include <asm/systemcfg.h> | ||
22 | #endif | ||
23 | 20 | ||
24 | #ifdef CONFIG_PPC32 | 21 | /* We do _not_ want to define new machine types at all, those must die |
25 | /* 32-bit platform types */ | 22 | * in favor of using the device-tree |
26 | /* We only need to define a new _MACH_xxx for machines which are part of | 23 | * -- BenH. |
27 | * a configuration which supports more than one type of different machine. | ||
28 | * This is currently limited to CONFIG_PPC_MULTIPLATFORM and CHRP/PReP/PMac. | ||
29 | * -- Tom | ||
30 | */ | 24 | */ |
31 | #define _MACH_prep 0x00000001 | ||
32 | #define _MACH_Pmac 0x00000002 /* pmac or pmac clone (non-chrp) */ | ||
33 | #define _MACH_chrp 0x00000004 /* chrp machine */ | ||
34 | 25 | ||
35 | /* see residual.h for these */ | 26 | /* Platforms codes (to be obsoleted) */ |
27 | #define PLATFORM_PSERIES 0x0100 | ||
28 | #define PLATFORM_PSERIES_LPAR 0x0101 | ||
29 | #define PLATFORM_ISERIES_LPAR 0x0201 | ||
30 | #define PLATFORM_LPAR 0x0001 | ||
31 | #define PLATFORM_POWERMAC 0x0400 | ||
32 | #define PLATFORM_MAPLE 0x0500 | ||
33 | #define PLATFORM_PREP 0x0600 | ||
34 | #define PLATFORM_CHRP 0x0700 | ||
35 | #define PLATFORM_CELL 0x1000 | ||
36 | |||
37 | /* Compat platform codes for 32 bits */ | ||
38 | #define _MACH_prep PLATFORM_PREP | ||
39 | #define _MACH_Pmac PLATFORM_POWERMAC | ||
40 | #define _MACH_chrp PLATFORM_CHRP | ||
41 | |||
42 | /* PREP sub-platform types see residual.h for these */ | ||
36 | #define _PREP_Motorola 0x01 /* motorola prep */ | 43 | #define _PREP_Motorola 0x01 /* motorola prep */ |
37 | #define _PREP_Firm 0x02 /* firmworks prep */ | 44 | #define _PREP_Firm 0x02 /* firmworks prep */ |
38 | #define _PREP_IBM 0x00 /* ibm prep */ | 45 | #define _PREP_IBM 0x00 /* ibm prep */ |
39 | #define _PREP_Bull 0x03 /* bull prep */ | 46 | #define _PREP_Bull 0x03 /* bull prep */ |
40 | 47 | ||
41 | /* these are arbitrary */ | 48 | /* CHRP sub-platform types. These are arbitrary */ |
42 | #define _CHRP_Motorola 0x04 /* motorola chrp, the cobra */ | 49 | #define _CHRP_Motorola 0x04 /* motorola chrp, the cobra */ |
43 | #define _CHRP_IBM 0x05 /* IBM chrp, the longtrail and longtrail 2 */ | 50 | #define _CHRP_IBM 0x05 /* IBM chrp, the longtrail and longtrail 2 */ |
44 | #define _CHRP_Pegasos 0x06 /* Genesi/bplan's Pegasos and Pegasos2 */ | 51 | #define _CHRP_Pegasos 0x06 /* Genesi/bplan's Pegasos and Pegasos2 */ |
45 | 52 | ||
46 | #ifdef CONFIG_PPC_MULTIPLATFORM | 53 | #define platform_is_pseries() (_machine == PLATFORM_PSERIES || \ |
54 | _machine == PLATFORM_PSERIES_LPAR) | ||
55 | #define platform_is_lpar() (!!(_machine & PLATFORM_LPAR)) | ||
56 | |||
57 | #if defined(CONFIG_PPC_MULTIPLATFORM) | ||
47 | extern int _machine; | 58 | extern int _machine; |
48 | 59 | ||
60 | #ifdef CONFIG_PPC32 | ||
61 | |||
49 | /* what kind of prep workstation we are */ | 62 | /* what kind of prep workstation we are */ |
50 | extern int _prep_type; | 63 | extern int _prep_type; |
51 | extern int _chrp_type; | 64 | extern int _chrp_type; |
52 | 65 | ||
53 | /* | 66 | /* |
54 | * This is used to identify the board type from a given PReP board | 67 | * This is used to identify the board type from a given PReP board |
55 | * vendor. Board revision is also made available. | 68 | * vendor. Board revision is also made available. This will be moved |
69 | * elsewhere soon | ||
56 | */ | 70 | */ |
57 | extern unsigned char ucSystemType; | 71 | extern unsigned char ucSystemType; |
58 | extern unsigned char ucBoardRev; | 72 | extern unsigned char ucBoardRev; |
59 | extern unsigned char ucBoardRevMaj, ucBoardRevMin; | 73 | extern unsigned char ucBoardRevMaj, ucBoardRevMin; |
74 | |||
75 | #endif /* CONFIG_PPC32 */ | ||
76 | |||
77 | #elif defined(CONFIG_PPC_ISERIES) | ||
78 | /* | ||
79 | * iSeries is soon to become MULTIPLATFORM hopefully ... | ||
80 | */ | ||
81 | #define _machine PLATFORM_ISERIES_LPAR | ||
60 | #else | 82 | #else |
61 | #define _machine 0 | 83 | #define _machine 0 |
62 | #endif /* CONFIG_PPC_MULTIPLATFORM */ | 84 | #endif /* CONFIG_PPC_MULTIPLATFORM */ |
63 | #endif /* CONFIG_PPC32 */ | ||
64 | |||
65 | #ifdef CONFIG_PPC64 | ||
66 | /* Platforms supported by PPC64 */ | ||
67 | #define PLATFORM_PSERIES 0x0100 | ||
68 | #define PLATFORM_PSERIES_LPAR 0x0101 | ||
69 | #define PLATFORM_ISERIES_LPAR 0x0201 | ||
70 | #define PLATFORM_LPAR 0x0001 | ||
71 | #define PLATFORM_POWERMAC 0x0400 | ||
72 | #define PLATFORM_MAPLE 0x0500 | ||
73 | #define PLATFORM_CELL 0x1000 | ||
74 | |||
75 | /* Compatibility with drivers coming from PPC32 world */ | ||
76 | #define _machine (systemcfg->platform) | ||
77 | #define _MACH_Pmac PLATFORM_POWERMAC | ||
78 | #endif | ||
79 | 85 | ||
80 | /* | 86 | /* |
81 | * Default implementation of macro that returns current | 87 | * Default implementation of macro that returns current |
diff --git a/include/asm-powerpc/reg.h b/include/asm-powerpc/reg.h index 489cf4c99c21..eb392d038ed7 100644 --- a/include/asm-powerpc/reg.h +++ b/include/asm-powerpc/reg.h | |||
@@ -16,7 +16,11 @@ | |||
16 | /* Pickup Book E specific registers. */ | 16 | /* Pickup Book E specific registers. */ |
17 | #if defined(CONFIG_BOOKE) || defined(CONFIG_40x) | 17 | #if defined(CONFIG_BOOKE) || defined(CONFIG_40x) |
18 | #include <asm/reg_booke.h> | 18 | #include <asm/reg_booke.h> |
19 | #endif | 19 | #endif /* CONFIG_BOOKE || CONFIG_40x */ |
20 | |||
21 | #ifdef CONFIG_8xx | ||
22 | #include <asm/reg_8xx.h> | ||
23 | #endif /* CONFIG_8xx */ | ||
20 | 24 | ||
21 | #define MSR_SF_LG 63 /* Enable 64 bit mode */ | 25 | #define MSR_SF_LG 63 /* Enable 64 bit mode */ |
22 | #define MSR_ISF_LG 61 /* Interrupt 64b mode valid on 630 */ | 26 | #define MSR_ISF_LG 61 /* Interrupt 64b mode valid on 630 */ |
@@ -359,6 +363,7 @@ | |||
359 | #define SPRN_RPA 0x3D6 /* Required Physical Address Register */ | 363 | #define SPRN_RPA 0x3D6 /* Required Physical Address Register */ |
360 | #define SPRN_SDA 0x3BF /* Sampled Data Address Register */ | 364 | #define SPRN_SDA 0x3BF /* Sampled Data Address Register */ |
361 | #define SPRN_SDR1 0x019 /* MMU Hash Base Register */ | 365 | #define SPRN_SDR1 0x019 /* MMU Hash Base Register */ |
366 | #define SPRN_ASR 0x118 /* Address Space Register */ | ||
362 | #define SPRN_SIA 0x3BB /* Sampled Instruction Address Register */ | 367 | #define SPRN_SIA 0x3BB /* Sampled Instruction Address Register */ |
363 | #define SPRN_SPRG0 0x110 /* Special Purpose Register General 0 */ | 368 | #define SPRN_SPRG0 0x110 /* Special Purpose Register General 0 */ |
364 | #define SPRN_SPRG1 0x111 /* Special Purpose Register General 1 */ | 369 | #define SPRN_SPRG1 0x111 /* Special Purpose Register General 1 */ |
diff --git a/include/asm-ppc/cache.h b/include/asm-powerpc/reg_8xx.h index 7a157d0f4b5f..e8ea346b21d3 100644 --- a/include/asm-ppc/cache.h +++ b/include/asm-powerpc/reg_8xx.h | |||
@@ -1,49 +1,9 @@ | |||
1 | /* | 1 | /* |
2 | * include/asm-ppc/cache.h | 2 | * Contains register definitions common to PowerPC 8xx CPUs. Notice |
3 | */ | 3 | */ |
4 | #ifdef __KERNEL__ | 4 | #ifndef _ASM_POWERPC_REG_8xx_H |
5 | #ifndef __ARCH_PPC_CACHE_H | 5 | #define _ASM_POWERPC_REG_8xx_H |
6 | #define __ARCH_PPC_CACHE_H | ||
7 | 6 | ||
8 | #include <linux/config.h> | ||
9 | |||
10 | /* bytes per L1 cache line */ | ||
11 | #if defined(CONFIG_8xx) || defined(CONFIG_403GCX) | ||
12 | #define L1_CACHE_SHIFT 4 | ||
13 | #define MAX_COPY_PREFETCH 1 | ||
14 | #elif defined(CONFIG_PPC64BRIDGE) | ||
15 | #define L1_CACHE_SHIFT 7 | ||
16 | #define MAX_COPY_PREFETCH 1 | ||
17 | #else | ||
18 | #define L1_CACHE_SHIFT 5 | ||
19 | #define MAX_COPY_PREFETCH 4 | ||
20 | #endif | ||
21 | |||
22 | #define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) | ||
23 | |||
24 | #define SMP_CACHE_BYTES L1_CACHE_BYTES | ||
25 | #define L1_CACHE_SHIFT_MAX 7 /* largest L1 which this arch supports */ | ||
26 | |||
27 | #define L1_CACHE_ALIGN(x) (((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1)) | ||
28 | #define L1_CACHE_PAGES 8 | ||
29 | |||
30 | #ifndef __ASSEMBLY__ | ||
31 | extern void clean_dcache_range(unsigned long start, unsigned long stop); | ||
32 | extern void flush_dcache_range(unsigned long start, unsigned long stop); | ||
33 | extern void invalidate_dcache_range(unsigned long start, unsigned long stop); | ||
34 | extern void flush_dcache_all(void); | ||
35 | #endif /* __ASSEMBLY__ */ | ||
36 | |||
37 | /* prep registers for L2 */ | ||
38 | #define CACHECRBA 0x80000823 /* Cache configuration register address */ | ||
39 | #define L2CACHE_MASK 0x03 /* Mask for 2 L2 Cache bits */ | ||
40 | #define L2CACHE_512KB 0x00 /* 512KB */ | ||
41 | #define L2CACHE_256KB 0x01 /* 256KB */ | ||
42 | #define L2CACHE_1MB 0x02 /* 1MB */ | ||
43 | #define L2CACHE_NONE 0x03 /* NONE */ | ||
44 | #define L2CACHE_PARITY 0x08 /* Mask for L2 Cache Parity Protected bit */ | ||
45 | |||
46 | #ifdef CONFIG_8xx | ||
47 | /* Cache control on the MPC8xx is provided through some additional | 7 | /* Cache control on the MPC8xx is provided through some additional |
48 | * special purpose registers. | 8 | * special purpose registers. |
49 | */ | 9 | */ |
@@ -78,7 +38,5 @@ extern void flush_dcache_all(void); | |||
78 | 38 | ||
79 | #define DC_DFWT 0x40000000 /* Data cache is forced write through */ | 39 | #define DC_DFWT 0x40000000 /* Data cache is forced write through */ |
80 | #define DC_LES 0x20000000 /* Caches are little endian mode */ | 40 | #define DC_LES 0x20000000 /* Caches are little endian mode */ |
81 | #endif /* CONFIG_8xx */ | ||
82 | 41 | ||
83 | #endif | 42 | #endif /* _ASM_POWERPC_REG_8xx_H */ |
84 | #endif /* __KERNEL__ */ | ||
diff --git a/include/asm-ppc/signal.h b/include/asm-powerpc/signal.h index caf6ede3710f..694c8d2dab87 100644 --- a/include/asm-ppc/signal.h +++ b/include/asm-powerpc/signal.h | |||
@@ -1,18 +1,11 @@ | |||
1 | #ifndef _ASMPPC_SIGNAL_H | 1 | #ifndef _ASM_POWERPC_SIGNAL_H |
2 | #define _ASMPPC_SIGNAL_H | 2 | #define _ASM_POWERPC_SIGNAL_H |
3 | 3 | ||
4 | #ifdef __KERNEL__ | ||
5 | #include <linux/types.h> | 4 | #include <linux/types.h> |
6 | #endif /* __KERNEL__ */ | 5 | #include <linux/config.h> |
7 | |||
8 | /* Avoid too many header ordering problems. */ | ||
9 | struct siginfo; | ||
10 | |||
11 | /* Most things should be clean enough to redefine this at will, if care | ||
12 | is taken to make libc match. */ | ||
13 | 6 | ||
14 | #define _NSIG 64 | 7 | #define _NSIG 64 |
15 | #define _NSIG_BPW 32 | 8 | #define _NSIG_BPW BITS_PER_LONG |
16 | #define _NSIG_WORDS (_NSIG / _NSIG_BPW) | 9 | #define _NSIG_WORDS (_NSIG / _NSIG_BPW) |
17 | 10 | ||
18 | typedef unsigned long old_sigset_t; /* at least 32 bits */ | 11 | typedef unsigned long old_sigset_t; /* at least 32 bits */ |
@@ -77,19 +70,19 @@ typedef struct { | |||
77 | * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single | 70 | * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single |
78 | * Unix names RESETHAND and NODEFER respectively. | 71 | * Unix names RESETHAND and NODEFER respectively. |
79 | */ | 72 | */ |
80 | #define SA_NOCLDSTOP 0x00000001 | 73 | #define SA_NOCLDSTOP 0x00000001U |
81 | #define SA_NOCLDWAIT 0x00000002 | 74 | #define SA_NOCLDWAIT 0x00000002U |
82 | #define SA_SIGINFO 0x00000004 | 75 | #define SA_SIGINFO 0x00000004U |
83 | #define SA_ONSTACK 0x08000000 | 76 | #define SA_ONSTACK 0x08000000U |
84 | #define SA_RESTART 0x10000000 | 77 | #define SA_RESTART 0x10000000U |
85 | #define SA_NODEFER 0x40000000 | 78 | #define SA_NODEFER 0x40000000U |
86 | #define SA_RESETHAND 0x80000000 | 79 | #define SA_RESETHAND 0x80000000U |
87 | 80 | ||
88 | #define SA_NOMASK SA_NODEFER | 81 | #define SA_NOMASK SA_NODEFER |
89 | #define SA_ONESHOT SA_RESETHAND | 82 | #define SA_ONESHOT SA_RESETHAND |
90 | #define SA_INTERRUPT 0x20000000 /* dummy -- ignored */ | 83 | #define SA_INTERRUPT 0x20000000u /* dummy -- ignored */ |
91 | 84 | ||
92 | #define SA_RESTORER 0x04000000 | 85 | #define SA_RESTORER 0x04000000U |
93 | 86 | ||
94 | /* | 87 | /* |
95 | * sigaltstack controls | 88 | * sigaltstack controls |
@@ -127,10 +120,13 @@ typedef struct sigaltstack { | |||
127 | } stack_t; | 120 | } stack_t; |
128 | 121 | ||
129 | #ifdef __KERNEL__ | 122 | #ifdef __KERNEL__ |
130 | #include <asm/sigcontext.h> | 123 | struct pt_regs; |
124 | extern int do_signal(sigset_t *oldset, struct pt_regs *regs); | ||
125 | extern int do_signal32(sigset_t *oldset, struct pt_regs *regs); | ||
131 | #define ptrace_signal_deliver(regs, cookie) do { } while (0) | 126 | #define ptrace_signal_deliver(regs, cookie) do { } while (0) |
132 | #endif /* __KERNEL__ */ | 127 | #endif /* __KERNEL__ */ |
133 | 128 | ||
129 | #ifndef __powerpc64__ | ||
134 | /* | 130 | /* |
135 | * These are parameters to dbg_sigreturn syscall. They enable or | 131 | * These are parameters to dbg_sigreturn syscall. They enable or |
136 | * disable certain debugging things that can be done from signal | 132 | * disable certain debugging things that can be done from signal |
@@ -149,5 +145,6 @@ struct sig_dbg_op { | |||
149 | 145 | ||
150 | /* Enable or disable branch tracing. The value sets the state. */ | 146 | /* Enable or disable branch tracing. The value sets the state. */ |
151 | #define SIG_DBG_BRANCH_TRACING 2 | 147 | #define SIG_DBG_BRANCH_TRACING 2 |
148 | #endif /* ! __powerpc64__ */ | ||
152 | 149 | ||
153 | #endif | 150 | #endif /* _ASM_POWERPC_SIGNAL_H */ |
diff --git a/include/asm-powerpc/sparsemem.h b/include/asm-powerpc/sparsemem.h index 1c95ab99deb3..58d2aab416f8 100644 --- a/include/asm-powerpc/sparsemem.h +++ b/include/asm-powerpc/sparsemem.h | |||
@@ -11,6 +11,10 @@ | |||
11 | #define MAX_PHYSADDR_BITS 38 | 11 | #define MAX_PHYSADDR_BITS 38 |
12 | #define MAX_PHYSMEM_BITS 36 | 12 | #define MAX_PHYSMEM_BITS 36 |
13 | 13 | ||
14 | #ifdef CONFIG_MEMORY_HOTPLUG | ||
15 | extern void create_section_mapping(unsigned long start, unsigned long end); | ||
16 | #endif /* CONFIG_MEMORY_HOTPLUG */ | ||
17 | |||
14 | #endif /* CONFIG_SPARSEMEM */ | 18 | #endif /* CONFIG_SPARSEMEM */ |
15 | 19 | ||
16 | #endif /* _ASM_POWERPC_SPARSEMEM_H */ | 20 | #endif /* _ASM_POWERPC_SPARSEMEM_H */ |
diff --git a/include/asm-powerpc/system.h b/include/asm-powerpc/system.h index 3536a5cd7a2d..5341b75c75cb 100644 --- a/include/asm-powerpc/system.h +++ b/include/asm-powerpc/system.h | |||
@@ -8,7 +8,6 @@ | |||
8 | #include <linux/kernel.h> | 8 | #include <linux/kernel.h> |
9 | 9 | ||
10 | #include <asm/hw_irq.h> | 10 | #include <asm/hw_irq.h> |
11 | #include <asm/ppc_asm.h> | ||
12 | #include <asm/atomic.h> | 11 | #include <asm/atomic.h> |
13 | 12 | ||
14 | /* | 13 | /* |
@@ -180,6 +179,7 @@ extern struct task_struct *_switch(struct thread_struct *prev, | |||
180 | extern unsigned int rtas_data; | 179 | extern unsigned int rtas_data; |
181 | extern int mem_init_done; /* set on boot once kmalloc can be called */ | 180 | extern int mem_init_done; /* set on boot once kmalloc can be called */ |
182 | extern unsigned long memory_limit; | 181 | extern unsigned long memory_limit; |
182 | extern unsigned long klimit; | ||
183 | 183 | ||
184 | extern int powersave_nap; /* set if nap mode can be used in idle loop */ | 184 | extern int powersave_nap; /* set if nap mode can be used in idle loop */ |
185 | 185 | ||
diff --git a/include/asm-ppc64/systemcfg.h b/include/asm-powerpc/systemcfg.h index 9b86b53129aa..36b5cbe466f1 100644 --- a/include/asm-ppc64/systemcfg.h +++ b/include/asm-powerpc/systemcfg.h | |||
@@ -1,7 +1,7 @@ | |||
1 | #ifndef _SYSTEMCFG_H | 1 | #ifndef _SYSTEMCFG_H |
2 | #define _SYSTEMCFG_H | 2 | #define _SYSTEMCFG_H |
3 | 3 | ||
4 | /* | 4 | /* |
5 | * Copyright (C) 2002 Peter Bergner <bergner@vnet.ibm.com>, IBM | 5 | * Copyright (C) 2002 Peter Bergner <bergner@vnet.ibm.com>, IBM |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or | 7 | * This program is free software; you can redistribute it and/or |
@@ -12,7 +12,7 @@ | |||
12 | 12 | ||
13 | /* Change Activity: | 13 | /* Change Activity: |
14 | * 2002/09/30 : bergner : Created | 14 | * 2002/09/30 : bergner : Created |
15 | * End Change Activity | 15 | * End Change Activity |
16 | */ | 16 | */ |
17 | 17 | ||
18 | /* | 18 | /* |
@@ -56,7 +56,7 @@ struct systemcfg { | |||
56 | }; | 56 | }; |
57 | 57 | ||
58 | #ifdef __KERNEL__ | 58 | #ifdef __KERNEL__ |
59 | extern struct systemcfg *systemcfg; | 59 | extern struct systemcfg *_systemcfg; /* to be renamed */ |
60 | #endif | 60 | #endif |
61 | 61 | ||
62 | #endif /* __ASSEMBLY__ */ | 62 | #endif /* __ASSEMBLY__ */ |
diff --git a/include/asm-ppc64/tce.h b/include/asm-powerpc/tce.h index d40b6b42ab35..d099d5200f9b 100644 --- a/include/asm-ppc64/tce.h +++ b/include/asm-powerpc/tce.h | |||
@@ -18,8 +18,8 @@ | |||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 | */ | 19 | */ |
20 | 20 | ||
21 | #ifndef _ASM_TCE_H | 21 | #ifndef _ASM_POWERPC_TCE_H |
22 | #define _ASM_TCE_H | 22 | #define _ASM_POWERPC_TCE_H |
23 | 23 | ||
24 | /* | 24 | /* |
25 | * Tces come in two formats, one for the virtual bus and a different | 25 | * Tces come in two formats, one for the virtual bus and a different |
@@ -61,4 +61,4 @@ union tce_entry { | |||
61 | }; | 61 | }; |
62 | 62 | ||
63 | 63 | ||
64 | #endif | 64 | #endif /* _ASM_POWERPC_TCE_H */ |
diff --git a/include/asm-powerpc/uaccess.h b/include/asm-powerpc/uaccess.h index 33af730f0d19..3872e924cdd6 100644 --- a/include/asm-powerpc/uaccess.h +++ b/include/asm-powerpc/uaccess.h | |||
@@ -120,14 +120,6 @@ struct exception_table_entry { | |||
120 | 120 | ||
121 | extern long __put_user_bad(void); | 121 | extern long __put_user_bad(void); |
122 | 122 | ||
123 | #ifdef __powerpc64__ | ||
124 | #define __EX_TABLE_ALIGN "3" | ||
125 | #define __EX_TABLE_TYPE "llong" | ||
126 | #else | ||
127 | #define __EX_TABLE_ALIGN "2" | ||
128 | #define __EX_TABLE_TYPE "long" | ||
129 | #endif | ||
130 | |||
131 | /* | 123 | /* |
132 | * We don't tell gcc that we are accessing memory, but this is OK | 124 | * We don't tell gcc that we are accessing memory, but this is OK |
133 | * because we do not write to any memory gcc knows about, so there | 125 | * because we do not write to any memory gcc knows about, so there |
@@ -142,11 +134,12 @@ extern long __put_user_bad(void); | |||
142 | " b 2b\n" \ | 134 | " b 2b\n" \ |
143 | ".previous\n" \ | 135 | ".previous\n" \ |
144 | ".section __ex_table,\"a\"\n" \ | 136 | ".section __ex_table,\"a\"\n" \ |
145 | " .align " __EX_TABLE_ALIGN "\n" \ | 137 | " .balign %5\n" \ |
146 | " ."__EX_TABLE_TYPE" 1b,3b\n" \ | 138 | PPC_LONG "1b,3b\n" \ |
147 | ".previous" \ | 139 | ".previous" \ |
148 | : "=r" (err) \ | 140 | : "=r" (err) \ |
149 | : "r" (x), "b" (addr), "i" (-EFAULT), "0" (err)) | 141 | : "r" (x), "b" (addr), "i" (-EFAULT), "0" (err),\ |
142 | "i"(sizeof(unsigned long))) | ||
150 | 143 | ||
151 | #ifdef __powerpc64__ | 144 | #ifdef __powerpc64__ |
152 | #define __put_user_asm2(x, ptr, retval) \ | 145 | #define __put_user_asm2(x, ptr, retval) \ |
@@ -162,12 +155,13 @@ extern long __put_user_bad(void); | |||
162 | " b 3b\n" \ | 155 | " b 3b\n" \ |
163 | ".previous\n" \ | 156 | ".previous\n" \ |
164 | ".section __ex_table,\"a\"\n" \ | 157 | ".section __ex_table,\"a\"\n" \ |
165 | " .align " __EX_TABLE_ALIGN "\n" \ | 158 | " .balign %5\n" \ |
166 | " ." __EX_TABLE_TYPE " 1b,4b\n" \ | 159 | PPC_LONG "1b,4b\n" \ |
167 | " ." __EX_TABLE_TYPE " 2b,4b\n" \ | 160 | PPC_LONG "2b,4b\n" \ |
168 | ".previous" \ | 161 | ".previous" \ |
169 | : "=r" (err) \ | 162 | : "=r" (err) \ |
170 | : "r" (x), "b" (addr), "i" (-EFAULT), "0" (err)) | 163 | : "r" (x), "b" (addr), "i" (-EFAULT), "0" (err),\ |
164 | "i"(sizeof(unsigned long))) | ||
171 | #endif /* __powerpc64__ */ | 165 | #endif /* __powerpc64__ */ |
172 | 166 | ||
173 | #define __put_user_size(x, ptr, size, retval) \ | 167 | #define __put_user_size(x, ptr, size, retval) \ |
@@ -213,11 +207,12 @@ extern long __get_user_bad(void); | |||
213 | " b 2b\n" \ | 207 | " b 2b\n" \ |
214 | ".previous\n" \ | 208 | ".previous\n" \ |
215 | ".section __ex_table,\"a\"\n" \ | 209 | ".section __ex_table,\"a\"\n" \ |
216 | " .align "__EX_TABLE_ALIGN "\n" \ | 210 | " .balign %5\n" \ |
217 | " ." __EX_TABLE_TYPE " 1b,3b\n" \ | 211 | PPC_LONG "1b,3b\n" \ |
218 | ".previous" \ | 212 | ".previous" \ |
219 | : "=r" (err), "=r" (x) \ | 213 | : "=r" (err), "=r" (x) \ |
220 | : "b" (addr), "i" (-EFAULT), "0" (err)) | 214 | : "b" (addr), "i" (-EFAULT), "0" (err), \ |
215 | "i"(sizeof(unsigned long))) | ||
221 | 216 | ||
222 | #ifdef __powerpc64__ | 217 | #ifdef __powerpc64__ |
223 | #define __get_user_asm2(x, addr, err) \ | 218 | #define __get_user_asm2(x, addr, err) \ |
@@ -235,12 +230,13 @@ extern long __get_user_bad(void); | |||
235 | " b 3b\n" \ | 230 | " b 3b\n" \ |
236 | ".previous\n" \ | 231 | ".previous\n" \ |
237 | ".section __ex_table,\"a\"\n" \ | 232 | ".section __ex_table,\"a\"\n" \ |
238 | " .align " __EX_TABLE_ALIGN "\n" \ | 233 | " .balign %5\n" \ |
239 | " ." __EX_TABLE_TYPE " 1b,4b\n" \ | 234 | PPC_LONG "1b,4b\n" \ |
240 | " ." __EX_TABLE_TYPE " 2b,4b\n" \ | 235 | PPC_LONG "2b,4b\n" \ |
241 | ".previous" \ | 236 | ".previous" \ |
242 | : "=r" (err), "=&r" (x) \ | 237 | : "=r" (err), "=&r" (x) \ |
243 | : "b" (addr), "i" (-EFAULT), "0" (err)) | 238 | : "b" (addr), "i" (-EFAULT), "0" (err), \ |
239 | "i"(sizeof(unsigned long))) | ||
244 | #endif /* __powerpc64__ */ | 240 | #endif /* __powerpc64__ */ |
245 | 241 | ||
246 | #define __get_user_size(x, ptr, size, retval) \ | 242 | #define __get_user_size(x, ptr, size, retval) \ |
diff --git a/include/asm-powerpc/xmon.h b/include/asm-powerpc/xmon.h index ace2072d4a83..43f7129984c7 100644 --- a/include/asm-powerpc/xmon.h +++ b/include/asm-powerpc/xmon.h | |||
@@ -7,7 +7,6 @@ struct pt_regs; | |||
7 | extern int xmon(struct pt_regs *excp); | 7 | extern int xmon(struct pt_regs *excp); |
8 | extern void xmon_printf(const char *fmt, ...); | 8 | extern void xmon_printf(const char *fmt, ...); |
9 | extern void xmon_init(int); | 9 | extern void xmon_init(int); |
10 | extern void xmon_map_scc(void); | ||
11 | 10 | ||
12 | #endif | 11 | #endif |
13 | #endif | 12 | #endif |
diff --git a/include/asm-ppc/cacheflush.h b/include/asm-ppc/cacheflush.h deleted file mode 100644 index 6a243efb3317..000000000000 --- a/include/asm-ppc/cacheflush.h +++ /dev/null | |||
@@ -1,49 +0,0 @@ | |||
1 | /* | ||
2 | * include/asm-ppc/cacheflush.h | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | */ | ||
9 | #ifdef __KERNEL__ | ||
10 | #ifndef _PPC_CACHEFLUSH_H | ||
11 | #define _PPC_CACHEFLUSH_H | ||
12 | |||
13 | #include <linux/mm.h> | ||
14 | |||
15 | /* | ||
16 | * No cache flushing is required when address mappings are | ||
17 | * changed, because the caches on PowerPCs are physically | ||
18 | * addressed. -- paulus | ||
19 | * Also, when SMP we use the coherency (M) bit of the | ||
20 | * BATs and PTEs. -- Cort | ||
21 | */ | ||
22 | #define flush_cache_all() do { } while (0) | ||
23 | #define flush_cache_mm(mm) do { } while (0) | ||
24 | #define flush_cache_range(vma, a, b) do { } while (0) | ||
25 | #define flush_cache_page(vma, p, pfn) do { } while (0) | ||
26 | #define flush_icache_page(vma, page) do { } while (0) | ||
27 | #define flush_cache_vmap(start, end) do { } while (0) | ||
28 | #define flush_cache_vunmap(start, end) do { } while (0) | ||
29 | |||
30 | extern void flush_dcache_page(struct page *page); | ||
31 | #define flush_dcache_mmap_lock(mapping) do { } while (0) | ||
32 | #define flush_dcache_mmap_unlock(mapping) do { } while (0) | ||
33 | |||
34 | extern void flush_icache_range(unsigned long, unsigned long); | ||
35 | extern void flush_icache_user_range(struct vm_area_struct *vma, | ||
36 | struct page *page, unsigned long addr, int len); | ||
37 | |||
38 | #define copy_to_user_page(vma, page, vaddr, dst, src, len) \ | ||
39 | do { memcpy(dst, src, len); \ | ||
40 | flush_icache_user_range(vma, page, vaddr, len); \ | ||
41 | } while (0) | ||
42 | #define copy_from_user_page(vma, page, vaddr, dst, src, len) \ | ||
43 | memcpy(dst, src, len) | ||
44 | |||
45 | extern void __flush_dcache_icache(void *page_va); | ||
46 | extern void __flush_dcache_icache_phys(unsigned long physaddr); | ||
47 | extern void flush_dcache_icache_page(struct page *page); | ||
48 | #endif /* _PPC_CACHEFLUSH_H */ | ||
49 | #endif /* __KERNEL__ */ | ||
diff --git a/include/asm-ppc/current.h b/include/asm-ppc/current.h deleted file mode 100644 index 8d41501ba10d..000000000000 --- a/include/asm-ppc/current.h +++ /dev/null | |||
@@ -1,11 +0,0 @@ | |||
1 | #ifdef __KERNEL__ | ||
2 | #ifndef _PPC_CURRENT_H | ||
3 | #define _PPC_CURRENT_H | ||
4 | |||
5 | /* | ||
6 | * We keep `current' in r2 for speed. | ||
7 | */ | ||
8 | register struct task_struct *current asm ("r2"); | ||
9 | |||
10 | #endif /* !(_PPC_CURRENT_H) */ | ||
11 | #endif /* __KERNEL__ */ | ||
diff --git a/include/asm-ppc64/cache.h b/include/asm-ppc64/cache.h deleted file mode 100644 index 92140a7efbd1..000000000000 --- a/include/asm-ppc64/cache.h +++ /dev/null | |||
@@ -1,36 +0,0 @@ | |||
1 | /* | ||
2 | * This program is free software; you can redistribute it and/or | ||
3 | * modify it under the terms of the GNU General Public License | ||
4 | * as published by the Free Software Foundation; either version | ||
5 | * 2 of the License, or (at your option) any later version. | ||
6 | */ | ||
7 | #ifndef __ARCH_PPC64_CACHE_H | ||
8 | #define __ARCH_PPC64_CACHE_H | ||
9 | |||
10 | #include <asm/types.h> | ||
11 | |||
12 | /* bytes per L1 cache line */ | ||
13 | #define L1_CACHE_SHIFT 7 | ||
14 | #define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) | ||
15 | |||
16 | #define SMP_CACHE_BYTES L1_CACHE_BYTES | ||
17 | #define L1_CACHE_SHIFT_MAX 7 /* largest L1 which this arch supports */ | ||
18 | |||
19 | #ifndef __ASSEMBLY__ | ||
20 | |||
21 | struct ppc64_caches { | ||
22 | u32 dsize; /* L1 d-cache size */ | ||
23 | u32 dline_size; /* L1 d-cache line size */ | ||
24 | u32 log_dline_size; | ||
25 | u32 dlines_per_page; | ||
26 | u32 isize; /* L1 i-cache size */ | ||
27 | u32 iline_size; /* L1 i-cache line size */ | ||
28 | u32 log_iline_size; | ||
29 | u32 ilines_per_page; | ||
30 | }; | ||
31 | |||
32 | extern struct ppc64_caches ppc64_caches; | ||
33 | |||
34 | #endif | ||
35 | |||
36 | #endif | ||
diff --git a/include/asm-ppc64/current.h b/include/asm-ppc64/current.h deleted file mode 100644 index 52ddc60c8b65..000000000000 --- a/include/asm-ppc64/current.h +++ /dev/null | |||
@@ -1,16 +0,0 @@ | |||
1 | #ifndef _PPC64_CURRENT_H | ||
2 | #define _PPC64_CURRENT_H | ||
3 | |||
4 | #include <asm/paca.h> | ||
5 | |||
6 | /* | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; either version | ||
10 | * 2 of the License, or (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #define get_current() (get_paca()->__current) | ||
14 | #define current get_current() | ||
15 | |||
16 | #endif /* !(_PPC64_CURRENT_H) */ | ||
diff --git a/include/asm-ppc64/eeh.h b/include/asm-ppc64/eeh.h index 40c8eb57493e..89f26ab31908 100644 --- a/include/asm-ppc64/eeh.h +++ b/include/asm-ppc64/eeh.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * eeh.h | 2 | * eeh.h |
3 | * Copyright (C) 2001 Dave Engebretsen & Todd Inglett IBM Corporation. | 3 | * Copyright (C) 2001 Dave Engebretsen & Todd Inglett IBM Corporation. |
4 | * | 4 | * |
@@ -6,12 +6,12 @@ | |||
6 | * it under the terms of the GNU General Public License as published by | 6 | * it under the terms of the GNU General Public License as published by |
7 | * the Free Software Foundation; either version 2 of the License, or | 7 | * the Free Software Foundation; either version 2 of the License, or |
8 | * (at your option) any later version. | 8 | * (at your option) any later version. |
9 | * | 9 | * |
10 | * This program is distributed in the hope that it will be useful, | 10 | * This program is distributed in the hope that it will be useful, |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | * GNU General Public License for more details. | 13 | * GNU General Public License for more details. |
14 | * | 14 | * |
15 | * You should have received a copy of the GNU General Public License | 15 | * You should have received a copy of the GNU General Public License |
16 | * along with this program; if not, write to the Free Software | 16 | * along with this program; if not, write to the Free Software |
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
@@ -27,8 +27,6 @@ | |||
27 | 27 | ||
28 | struct pci_dev; | 28 | struct pci_dev; |
29 | struct device_node; | 29 | struct device_node; |
30 | struct device_node; | ||
31 | struct notifier_block; | ||
32 | 30 | ||
33 | #ifdef CONFIG_EEH | 31 | #ifdef CONFIG_EEH |
34 | 32 | ||
@@ -37,6 +35,10 @@ struct notifier_block; | |||
37 | #define EEH_MODE_NOCHECK (1<<1) | 35 | #define EEH_MODE_NOCHECK (1<<1) |
38 | #define EEH_MODE_ISOLATED (1<<2) | 36 | #define EEH_MODE_ISOLATED (1<<2) |
39 | 37 | ||
38 | /* Max number of EEH freezes allowed before we consider the device | ||
39 | * to be permanently disabled. */ | ||
40 | #define EEH_MAX_ALLOWED_FREEZES 5 | ||
41 | |||
40 | void __init eeh_init(void); | 42 | void __init eeh_init(void); |
41 | unsigned long eeh_check_failure(const volatile void __iomem *token, | 43 | unsigned long eeh_check_failure(const volatile void __iomem *token, |
42 | unsigned long val); | 44 | unsigned long val); |
@@ -59,36 +61,14 @@ void eeh_add_device_late(struct pci_dev *); | |||
59 | * eeh_remove_device - undo EEH setup for the indicated pci device | 61 | * eeh_remove_device - undo EEH setup for the indicated pci device |
60 | * @dev: pci device to be removed | 62 | * @dev: pci device to be removed |
61 | * | 63 | * |
62 | * This routine should be when a device is removed from a running | 64 | * This routine should be called when a device is removed from |
63 | * system (e.g. by hotplug or dlpar). | 65 | * a running system (e.g. by hotplug or dlpar). It unregisters |
66 | * the PCI device from the EEH subsystem. I/O errors affecting | ||
67 | * this device will no longer be detected after this call; thus, | ||
68 | * i/o errors affecting this slot may leave this device unusable. | ||
64 | */ | 69 | */ |
65 | void eeh_remove_device(struct pci_dev *); | 70 | void eeh_remove_device(struct pci_dev *); |
66 | 71 | ||
67 | #define EEH_DISABLE 0 | ||
68 | #define EEH_ENABLE 1 | ||
69 | #define EEH_RELEASE_LOADSTORE 2 | ||
70 | #define EEH_RELEASE_DMA 3 | ||
71 | |||
72 | /** | ||
73 | * Notifier event flags. | ||
74 | */ | ||
75 | #define EEH_NOTIFY_FREEZE 1 | ||
76 | |||
77 | /** EEH event -- structure holding pci slot data that describes | ||
78 | * a change in the isolation status of a PCI slot. A pointer | ||
79 | * to this struct is passed as the data pointer in a notify callback. | ||
80 | */ | ||
81 | struct eeh_event { | ||
82 | struct list_head list; | ||
83 | struct pci_dev *dev; | ||
84 | struct device_node *dn; | ||
85 | int reset_state; | ||
86 | }; | ||
87 | |||
88 | /** Register to find out about EEH events. */ | ||
89 | int eeh_register_notifier(struct notifier_block *nb); | ||
90 | int eeh_unregister_notifier(struct notifier_block *nb); | ||
91 | |||
92 | /** | 72 | /** |
93 | * EEH_POSSIBLE_ERROR() -- test for possible MMIO failure. | 73 | * EEH_POSSIBLE_ERROR() -- test for possible MMIO failure. |
94 | * | 74 | * |
@@ -129,7 +109,7 @@ static inline void eeh_remove_device(struct pci_dev *dev) { } | |||
129 | #define EEH_IO_ERROR_VALUE(size) (-1UL) | 109 | #define EEH_IO_ERROR_VALUE(size) (-1UL) |
130 | #endif /* CONFIG_EEH */ | 110 | #endif /* CONFIG_EEH */ |
131 | 111 | ||
132 | /* | 112 | /* |
133 | * MMIO read/write operations with EEH support. | 113 | * MMIO read/write operations with EEH support. |
134 | */ | 114 | */ |
135 | static inline u8 eeh_readb(const volatile void __iomem *addr) | 115 | static inline u8 eeh_readb(const volatile void __iomem *addr) |
diff --git a/include/asm-ppc64/mmu.h b/include/asm-ppc64/mmu.h index 4c18a5cb69f5..1a7e0afa2dc6 100644 --- a/include/asm-ppc64/mmu.h +++ b/include/asm-ppc64/mmu.h | |||
@@ -14,7 +14,7 @@ | |||
14 | #define _PPC64_MMU_H_ | 14 | #define _PPC64_MMU_H_ |
15 | 15 | ||
16 | #include <linux/config.h> | 16 | #include <linux/config.h> |
17 | #include <asm/ppc_asm.h> /* for ASM_CONST */ | 17 | #include <asm/asm-compat.h> |
18 | #include <asm/page.h> | 18 | #include <asm/page.h> |
19 | 19 | ||
20 | /* | 20 | /* |
@@ -224,9 +224,12 @@ extern int htab_bolt_mapping(unsigned long vstart, unsigned long vend, | |||
224 | unsigned long pstart, unsigned long mode, | 224 | unsigned long pstart, unsigned long mode, |
225 | int psize); | 225 | int psize); |
226 | 226 | ||
227 | extern void htab_initialize(void); | ||
228 | extern void htab_initialize_secondary(void); | ||
227 | extern void hpte_init_native(void); | 229 | extern void hpte_init_native(void); |
228 | extern void hpte_init_lpar(void); | 230 | extern void hpte_init_lpar(void); |
229 | extern void hpte_init_iSeries(void); | 231 | extern void hpte_init_iSeries(void); |
232 | extern void mm_init_ppc64(void); | ||
230 | 233 | ||
231 | extern long pSeries_lpar_hpte_insert(unsigned long hpte_group, | 234 | extern long pSeries_lpar_hpte_insert(unsigned long hpte_group, |
232 | unsigned long va, unsigned long prpn, | 235 | unsigned long va, unsigned long prpn, |
@@ -245,6 +248,7 @@ extern long iSeries_hpte_insert(unsigned long hpte_group, | |||
245 | 248 | ||
246 | extern void stabs_alloc(void); | 249 | extern void stabs_alloc(void); |
247 | extern void slb_initialize(void); | 250 | extern void slb_initialize(void); |
251 | extern void stab_initialize(unsigned long stab); | ||
248 | 252 | ||
249 | #endif /* __ASSEMBLY__ */ | 253 | #endif /* __ASSEMBLY__ */ |
250 | 254 | ||
diff --git a/include/asm-ppc64/mmzone.h b/include/asm-ppc64/mmzone.h index 80a708e7093a..15e777ce0f4a 100644 --- a/include/asm-ppc64/mmzone.h +++ b/include/asm-ppc64/mmzone.h | |||
@@ -33,6 +33,9 @@ extern int numa_cpu_lookup_table[]; | |||
33 | extern char *numa_memory_lookup_table; | 33 | extern char *numa_memory_lookup_table; |
34 | extern cpumask_t numa_cpumask_lookup_table[]; | 34 | extern cpumask_t numa_cpumask_lookup_table[]; |
35 | extern int nr_cpus_in_node[]; | 35 | extern int nr_cpus_in_node[]; |
36 | #ifdef CONFIG_MEMORY_HOTPLUG | ||
37 | extern unsigned long max_pfn; | ||
38 | #endif | ||
36 | 39 | ||
37 | /* 16MB regions */ | 40 | /* 16MB regions */ |
38 | #define MEMORY_INCREMENT_SHIFT 24 | 41 | #define MEMORY_INCREMENT_SHIFT 24 |
@@ -45,6 +48,11 @@ static inline int pa_to_nid(unsigned long pa) | |||
45 | { | 48 | { |
46 | int nid; | 49 | int nid; |
47 | 50 | ||
51 | #ifdef CONFIG_MEMORY_HOTPLUG | ||
52 | /* kludge hot added sections default to node 0 */ | ||
53 | if (pa >= (max_pfn << PAGE_SHIFT)) | ||
54 | return 0; | ||
55 | #endif | ||
48 | nid = numa_memory_lookup_table[pa >> MEMORY_INCREMENT_SHIFT]; | 56 | nid = numa_memory_lookup_table[pa >> MEMORY_INCREMENT_SHIFT]; |
49 | 57 | ||
50 | #ifdef DEBUG_NUMA | 58 | #ifdef DEBUG_NUMA |
diff --git a/include/asm-ppc64/page.h b/include/asm-ppc64/page.h index 82ce187e5be8..e32f1187aa29 100644 --- a/include/asm-ppc64/page.h +++ b/include/asm-ppc64/page.h | |||
@@ -11,7 +11,7 @@ | |||
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/config.h> | 13 | #include <linux/config.h> |
14 | #include <asm/ppc_asm.h> /* for ASM_CONST */ | 14 | #include <asm/asm-compat.h> |
15 | 15 | ||
16 | /* | 16 | /* |
17 | * We support either 4k or 64k software page size. When using 64k pages | 17 | * We support either 4k or 64k software page size. When using 64k pages |
diff --git a/include/asm-ppc64/pci-bridge.h b/include/asm-ppc64/pci-bridge.h index 60cf8c838af0..efbdaece0cf0 100644 --- a/include/asm-ppc64/pci-bridge.h +++ b/include/asm-ppc64/pci-bridge.h | |||
@@ -63,7 +63,6 @@ struct pci_dn { | |||
63 | int devfn; /* for pci devices */ | 63 | int devfn; /* for pci devices */ |
64 | int eeh_mode; /* See eeh.h for possible EEH_MODEs */ | 64 | int eeh_mode; /* See eeh.h for possible EEH_MODEs */ |
65 | int eeh_config_addr; | 65 | int eeh_config_addr; |
66 | int eeh_capable; /* from firmware */ | ||
67 | int eeh_check_count; /* # times driver ignored error */ | 66 | int eeh_check_count; /* # times driver ignored error */ |
68 | int eeh_freeze_count; /* # times this device froze up. */ | 67 | int eeh_freeze_count; /* # times this device froze up. */ |
69 | int eeh_is_bridge; /* device is pci-to-pci bridge */ | 68 | int eeh_is_bridge; /* device is pci-to-pci bridge */ |
diff --git a/include/asm-ppc64/pgalloc.h b/include/asm-ppc64/pgalloc.h index 98da0e4262bd..dcf3622d1946 100644 --- a/include/asm-ppc64/pgalloc.h +++ b/include/asm-ppc64/pgalloc.h | |||
@@ -10,8 +10,8 @@ extern kmem_cache_t *pgtable_cache[]; | |||
10 | 10 | ||
11 | #ifdef CONFIG_PPC_64K_PAGES | 11 | #ifdef CONFIG_PPC_64K_PAGES |
12 | #define PTE_CACHE_NUM 0 | 12 | #define PTE_CACHE_NUM 0 |
13 | #define PMD_CACHE_NUM 0 | 13 | #define PMD_CACHE_NUM 1 |
14 | #define PGD_CACHE_NUM 1 | 14 | #define PGD_CACHE_NUM 2 |
15 | #else | 15 | #else |
16 | #define PTE_CACHE_NUM 0 | 16 | #define PTE_CACHE_NUM 0 |
17 | #define PMD_CACHE_NUM 1 | 17 | #define PMD_CACHE_NUM 1 |
diff --git a/include/asm-ppc64/prom.h b/include/asm-ppc64/prom.h index 76bb0266d67c..ddfe186589fa 100644 --- a/include/asm-ppc64/prom.h +++ b/include/asm-ppc64/prom.h | |||
@@ -204,6 +204,8 @@ extern void of_detach_node(const struct device_node *); | |||
204 | extern unsigned long prom_init(unsigned long, unsigned long, unsigned long, | 204 | extern unsigned long prom_init(unsigned long, unsigned long, unsigned long, |
205 | unsigned long, unsigned long); | 205 | unsigned long, unsigned long); |
206 | extern void finish_device_tree(void); | 206 | extern void finish_device_tree(void); |
207 | extern void unflatten_device_tree(void); | ||
208 | extern void early_init_devtree(void *); | ||
207 | extern int device_is_compatible(struct device_node *device, const char *); | 209 | extern int device_is_compatible(struct device_node *device, const char *); |
208 | extern int machine_is_compatible(const char *compat); | 210 | extern int machine_is_compatible(const char *compat); |
209 | extern unsigned char *get_property(struct device_node *node, const char *name, | 211 | extern unsigned char *get_property(struct device_node *node, const char *name, |
diff --git a/include/asm-ppc64/signal.h b/include/asm-ppc64/signal.h deleted file mode 100644 index 432df7dd355d..000000000000 --- a/include/asm-ppc64/signal.h +++ /dev/null | |||
@@ -1,132 +0,0 @@ | |||
1 | #ifndef _ASMPPC64_SIGNAL_H | ||
2 | #define _ASMPPC64_SIGNAL_H | ||
3 | |||
4 | #include <linux/types.h> | ||
5 | #include <linux/compiler.h> | ||
6 | #include <asm/siginfo.h> | ||
7 | |||
8 | /* Avoid too many header ordering problems. */ | ||
9 | struct siginfo; | ||
10 | |||
11 | #define _NSIG 64 | ||
12 | #define _NSIG_BPW 64 | ||
13 | #define _NSIG_WORDS (_NSIG / _NSIG_BPW) | ||
14 | |||
15 | typedef unsigned long old_sigset_t; /* at least 32 bits */ | ||
16 | |||
17 | typedef struct { | ||
18 | unsigned long sig[_NSIG_WORDS]; | ||
19 | } sigset_t; | ||
20 | |||
21 | #define SIGHUP 1 | ||
22 | #define SIGINT 2 | ||
23 | #define SIGQUIT 3 | ||
24 | #define SIGILL 4 | ||
25 | #define SIGTRAP 5 | ||
26 | #define SIGABRT 6 | ||
27 | #define SIGIOT 6 | ||
28 | #define SIGBUS 7 | ||
29 | #define SIGFPE 8 | ||
30 | #define SIGKILL 9 | ||
31 | #define SIGUSR1 10 | ||
32 | #define SIGSEGV 11 | ||
33 | #define SIGUSR2 12 | ||
34 | #define SIGPIPE 13 | ||
35 | #define SIGALRM 14 | ||
36 | #define SIGTERM 15 | ||
37 | #define SIGSTKFLT 16 | ||
38 | #define SIGCHLD 17 | ||
39 | #define SIGCONT 18 | ||
40 | #define SIGSTOP 19 | ||
41 | #define SIGTSTP 20 | ||
42 | #define SIGTTIN 21 | ||
43 | #define SIGTTOU 22 | ||
44 | #define SIGURG 23 | ||
45 | #define SIGXCPU 24 | ||
46 | #define SIGXFSZ 25 | ||
47 | #define SIGVTALRM 26 | ||
48 | #define SIGPROF 27 | ||
49 | #define SIGWINCH 28 | ||
50 | #define SIGIO 29 | ||
51 | #define SIGPOLL SIGIO | ||
52 | /* | ||
53 | #define SIGLOST 29 | ||
54 | */ | ||
55 | #define SIGPWR 30 | ||
56 | #define SIGSYS 31 | ||
57 | #define SIGUNUSED 31 | ||
58 | |||
59 | /* These should not be considered constants from userland. */ | ||
60 | #define SIGRTMIN 32 | ||
61 | #define SIGRTMAX _NSIG | ||
62 | |||
63 | /* | ||
64 | * SA_FLAGS values: | ||
65 | * | ||
66 | * SA_ONSTACK is not currently supported, but will allow sigaltstack(2). | ||
67 | * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the | ||
68 | * SA_RESTART flag to get restarting signals (which were the default long ago) | ||
69 | * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. | ||
70 | * SA_RESETHAND clears the handler when the signal is delivered. | ||
71 | * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies. | ||
72 | * SA_NODEFER prevents the current signal from being masked in the handler. | ||
73 | * | ||
74 | * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single | ||
75 | * Unix names RESETHAND and NODEFER respectively. | ||
76 | */ | ||
77 | #define SA_NOCLDSTOP 0x00000001u | ||
78 | #define SA_NOCLDWAIT 0x00000002u | ||
79 | #define SA_SIGINFO 0x00000004u | ||
80 | #define SA_ONSTACK 0x08000000u | ||
81 | #define SA_RESTART 0x10000000u | ||
82 | #define SA_NODEFER 0x40000000u | ||
83 | #define SA_RESETHAND 0x80000000u | ||
84 | |||
85 | #define SA_NOMASK SA_NODEFER | ||
86 | #define SA_ONESHOT SA_RESETHAND | ||
87 | #define SA_INTERRUPT 0x20000000u /* dummy -- ignored */ | ||
88 | |||
89 | #define SA_RESTORER 0x04000000u | ||
90 | |||
91 | /* | ||
92 | * sigaltstack controls | ||
93 | */ | ||
94 | #define SS_ONSTACK 1 | ||
95 | #define SS_DISABLE 2 | ||
96 | |||
97 | #define MINSIGSTKSZ 2048 | ||
98 | #define SIGSTKSZ 8192 | ||
99 | |||
100 | #include <asm-generic/signal.h> | ||
101 | |||
102 | struct old_sigaction { | ||
103 | __sighandler_t sa_handler; | ||
104 | old_sigset_t sa_mask; | ||
105 | unsigned long sa_flags; | ||
106 | __sigrestore_t sa_restorer; | ||
107 | }; | ||
108 | |||
109 | struct sigaction { | ||
110 | __sighandler_t sa_handler; | ||
111 | unsigned long sa_flags; | ||
112 | __sigrestore_t sa_restorer; | ||
113 | sigset_t sa_mask; /* mask last for extensibility */ | ||
114 | }; | ||
115 | |||
116 | struct k_sigaction { | ||
117 | struct sigaction sa; | ||
118 | }; | ||
119 | |||
120 | typedef struct sigaltstack { | ||
121 | void __user *ss_sp; | ||
122 | int ss_flags; | ||
123 | size_t ss_size; | ||
124 | } stack_t; | ||
125 | |||
126 | struct pt_regs; | ||
127 | struct timespec; | ||
128 | extern int do_signal(sigset_t *oldset, struct pt_regs *regs); | ||
129 | extern int do_signal32(sigset_t *oldset, struct pt_regs *regs); | ||
130 | #define ptrace_signal_deliver(regs, cookie) do { } while (0) | ||
131 | |||
132 | #endif /* _ASMPPC64_SIGNAL_H */ | ||
diff --git a/include/asm-ppc64/system.h b/include/asm-ppc64/system.h index 0cdd66c9f4b7..bf9a6aba19c9 100644 --- a/include/asm-ppc64/system.h +++ b/include/asm-ppc64/system.h | |||
@@ -149,6 +149,8 @@ struct thread_struct; | |||
149 | extern struct task_struct * _switch(struct thread_struct *prev, | 149 | extern struct task_struct * _switch(struct thread_struct *prev, |
150 | struct thread_struct *next); | 150 | struct thread_struct *next); |
151 | 151 | ||
152 | extern unsigned long klimit; | ||
153 | |||
152 | extern int powersave_nap; /* set if nap mode can be used in idle loop */ | 154 | extern int powersave_nap; /* set if nap mode can be used in idle loop */ |
153 | 155 | ||
154 | /* | 156 | /* |
diff --git a/include/asm-x86_64/msi.h b/include/asm-x86_64/msi.h index 85c427e472bf..356e0e82f50b 100644 --- a/include/asm-x86_64/msi.h +++ b/include/asm-x86_64/msi.h | |||
@@ -11,8 +11,6 @@ | |||
11 | #include <asm/smp.h> | 11 | #include <asm/smp.h> |
12 | 12 | ||
13 | #define LAST_DEVICE_VECTOR 232 | 13 | #define LAST_DEVICE_VECTOR 232 |
14 | #define MSI_DEST_MODE MSI_LOGICAL_MODE | 14 | #define MSI_TARGET_CPU_SHIFT 12 |
15 | #define MSI_TARGET_CPU_SHIFT 12 | ||
16 | #define MSI_TARGET_CPU logical_smp_processor_id() | ||
17 | 15 | ||
18 | #endif /* ASM_MSI_H */ | 16 | #endif /* ASM_MSI_H */ |
diff --git a/include/asm-x86_64/smp.h b/include/asm-x86_64/smp.h index c57ce4071342..b9fb2173ef99 100644 --- a/include/asm-x86_64/smp.h +++ b/include/asm-x86_64/smp.h | |||
@@ -135,5 +135,11 @@ static __inline int logical_smp_processor_id(void) | |||
135 | } | 135 | } |
136 | #endif | 136 | #endif |
137 | 137 | ||
138 | #ifdef CONFIG_SMP | ||
139 | #define cpu_physical_id(cpu) x86_cpu_to_apicid[cpu] | ||
140 | #else | ||
141 | #define cpu_physical_id(cpu) boot_cpu_id | ||
142 | #endif | ||
143 | |||
138 | #endif | 144 | #endif |
139 | 145 | ||
diff --git a/include/linux/connector.h b/include/linux/connector.h index c5769c6585f4..ad1a22c1c42e 100644 --- a/include/linux/connector.h +++ b/include/linux/connector.h | |||
@@ -32,6 +32,8 @@ | |||
32 | */ | 32 | */ |
33 | #define CN_IDX_PROC 0x1 | 33 | #define CN_IDX_PROC 0x1 |
34 | #define CN_VAL_PROC 0x1 | 34 | #define CN_VAL_PROC 0x1 |
35 | #define CN_IDX_CIFS 0x2 | ||
36 | #define CN_VAL_CIFS 0x1 | ||
35 | 37 | ||
36 | #define CN_NETLINK_USERS 1 | 38 | #define CN_NETLINK_USERS 1 |
37 | 39 | ||
diff --git a/include/linux/ide.h b/include/linux/ide.h index 77ae55d4c13c..ac8b25fa6506 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h | |||
@@ -1329,7 +1329,8 @@ void ide_init_disk(struct gendisk *, ide_drive_t *); | |||
1329 | extern int ideprobe_init(void); | 1329 | extern int ideprobe_init(void); |
1330 | 1330 | ||
1331 | extern void ide_scan_pcibus(int scan_direction) __init; | 1331 | extern void ide_scan_pcibus(int scan_direction) __init; |
1332 | extern int ide_pci_register_driver(struct pci_driver *driver); | 1332 | extern int __ide_pci_register_driver(struct pci_driver *driver, struct module *owner); |
1333 | #define ide_pci_register_driver(d) __ide_pci_register_driver(d, THIS_MODULE) | ||
1333 | extern void ide_pci_unregister_driver(struct pci_driver *driver); | 1334 | extern void ide_pci_unregister_driver(struct pci_driver *driver); |
1334 | void ide_pci_setup_ports(struct pci_dev *, struct ide_pci_device_s *, int, ata_index_t *); | 1335 | void ide_pci_setup_ports(struct pci_dev *, struct ide_pci_device_s *, int, ata_index_t *); |
1335 | extern void ide_setup_pci_noise (struct pci_dev *dev, struct ide_pci_device_s *d); | 1336 | extern void ide_setup_pci_noise (struct pci_dev *dev, struct ide_pci_device_s *d); |
diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h index d21c305c6c64..fe26d431de87 100644 --- a/include/linux/if_ether.h +++ b/include/linux/if_ether.h | |||
@@ -21,6 +21,8 @@ | |||
21 | #ifndef _LINUX_IF_ETHER_H | 21 | #ifndef _LINUX_IF_ETHER_H |
22 | #define _LINUX_IF_ETHER_H | 22 | #define _LINUX_IF_ETHER_H |
23 | 23 | ||
24 | #include <linux/types.h> | ||
25 | |||
24 | /* | 26 | /* |
25 | * IEEE 802.3 Ethernet magic constants. The frame sizes omit the preamble | 27 | * IEEE 802.3 Ethernet magic constants. The frame sizes omit the preamble |
26 | * and FCS/CRC (frame check sequence). | 28 | * and FCS/CRC (frame check sequence). |
@@ -100,7 +102,7 @@ | |||
100 | struct ethhdr { | 102 | struct ethhdr { |
101 | unsigned char h_dest[ETH_ALEN]; /* destination eth addr */ | 103 | unsigned char h_dest[ETH_ALEN]; /* destination eth addr */ |
102 | unsigned char h_source[ETH_ALEN]; /* source ether addr */ | 104 | unsigned char h_source[ETH_ALEN]; /* source ether addr */ |
103 | unsigned short h_proto; /* packet type ID field */ | 105 | __be16 h_proto; /* packet type ID field */ |
104 | } __attribute__((packed)); | 106 | } __attribute__((packed)); |
105 | 107 | ||
106 | #ifdef __KERNEL__ | 108 | #ifdef __KERNEL__ |
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index c6efce4a04a4..936f8b76114e 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
@@ -927,6 +927,13 @@ extern int netdev_max_backlog; | |||
927 | extern int weight_p; | 927 | extern int weight_p; |
928 | extern int netdev_set_master(struct net_device *dev, struct net_device *master); | 928 | extern int netdev_set_master(struct net_device *dev, struct net_device *master); |
929 | extern int skb_checksum_help(struct sk_buff *skb, int inward); | 929 | extern int skb_checksum_help(struct sk_buff *skb, int inward); |
930 | #ifdef CONFIG_BUG | ||
931 | extern void netdev_rx_csum_fault(struct net_device *dev); | ||
932 | #else | ||
933 | static inline void netdev_rx_csum_fault(struct net_device *dev) | ||
934 | { | ||
935 | } | ||
936 | #endif | ||
930 | /* rx skb timestamps */ | 937 | /* rx skb timestamps */ |
931 | extern void net_enable_timestamp(void); | 938 | extern void net_enable_timestamp(void); |
932 | extern void net_disable_timestamp(void); | 939 | extern void net_disable_timestamp(void); |
diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h index 857126a36ecc..4877e35ae202 100644 --- a/include/linux/pci-acpi.h +++ b/include/linux/pci-acpi.h | |||
@@ -47,14 +47,15 @@ | |||
47 | OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL) | 47 | OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL) |
48 | 48 | ||
49 | #ifdef CONFIG_ACPI | 49 | #ifdef CONFIG_ACPI |
50 | extern acpi_status pci_osc_control_set(u32 flags); | 50 | extern acpi_status pci_osc_control_set(acpi_handle handle, u32 flags); |
51 | extern acpi_status pci_osc_support_set(u32 flags); | 51 | extern acpi_status pci_osc_support_set(u32 flags); |
52 | #else | 52 | #else |
53 | #if !defined(acpi_status) | 53 | #if !defined(acpi_status) |
54 | typedef u32 acpi_status; | 54 | typedef u32 acpi_status; |
55 | #define AE_ERROR (acpi_status) (0x0001) | 55 | #define AE_ERROR (acpi_status) (0x0001) |
56 | #endif | 56 | #endif |
57 | static inline acpi_status pci_osc_control_set(u32 flags) {return AE_ERROR;} | 57 | static inline acpi_status pci_osc_control_set(acpi_handle handle, u32 flags) |
58 | {return AE_ERROR;} | ||
58 | static inline acpi_status pci_osc_support_set(u32 flags) {return AE_ERROR;} | 59 | static inline acpi_status pci_osc_support_set(u32 flags) {return AE_ERROR;} |
59 | #endif | 60 | #endif |
60 | 61 | ||
diff --git a/include/linux/pci.h b/include/linux/pci.h index 3596ac94ecff..de690ca73d58 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
@@ -236,7 +236,6 @@ struct module; | |||
236 | struct pci_driver { | 236 | struct pci_driver { |
237 | struct list_head node; | 237 | struct list_head node; |
238 | char *name; | 238 | char *name; |
239 | struct module *owner; | ||
240 | const struct pci_device_id *id_table; /* must be non-NULL for probe to be called */ | 239 | const struct pci_device_id *id_table; /* must be non-NULL for probe to be called */ |
241 | int (*probe) (struct pci_dev *dev, const struct pci_device_id *id); /* New device inserted */ | 240 | int (*probe) (struct pci_dev *dev, const struct pci_device_id *id); /* New device inserted */ |
242 | void (*remove) (struct pci_dev *dev); /* Device removed (NULL if not a hot-plug capable driver) */ | 241 | void (*remove) (struct pci_dev *dev); /* Device removed (NULL if not a hot-plug capable driver) */ |
@@ -338,6 +337,7 @@ struct pci_dev *pci_find_device (unsigned int vendor, unsigned int device, const | |||
338 | struct pci_dev *pci_find_device_reverse (unsigned int vendor, unsigned int device, const struct pci_dev *from); | 337 | struct pci_dev *pci_find_device_reverse (unsigned int vendor, unsigned int device, const struct pci_dev *from); |
339 | struct pci_dev *pci_find_slot (unsigned int bus, unsigned int devfn); | 338 | struct pci_dev *pci_find_slot (unsigned int bus, unsigned int devfn); |
340 | int pci_find_capability (struct pci_dev *dev, int cap); | 339 | int pci_find_capability (struct pci_dev *dev, int cap); |
340 | int pci_find_next_capability (struct pci_dev *dev, u8 pos, int cap); | ||
341 | int pci_find_ext_capability (struct pci_dev *dev, int cap); | 341 | int pci_find_ext_capability (struct pci_dev *dev, int cap); |
342 | struct pci_bus * pci_find_next_bus(const struct pci_bus *from); | 342 | struct pci_bus * pci_find_next_bus(const struct pci_bus *from); |
343 | 343 | ||
@@ -432,8 +432,13 @@ int pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, | |||
432 | void *alignf_data); | 432 | void *alignf_data); |
433 | void pci_enable_bridges(struct pci_bus *bus); | 433 | void pci_enable_bridges(struct pci_bus *bus); |
434 | 434 | ||
435 | /* New-style probing supporting hot-pluggable devices */ | 435 | /* Proper probing supporting hot-pluggable devices */ |
436 | int pci_register_driver(struct pci_driver *); | 436 | int __pci_register_driver(struct pci_driver *, struct module *); |
437 | static inline int pci_register_driver(struct pci_driver *driver) | ||
438 | { | ||
439 | return __pci_register_driver(driver, THIS_MODULE); | ||
440 | } | ||
441 | |||
437 | void pci_unregister_driver(struct pci_driver *); | 442 | void pci_unregister_driver(struct pci_driver *); |
438 | void pci_remove_behind_bridge(struct pci_dev *); | 443 | void pci_remove_behind_bridge(struct pci_dev *); |
439 | struct pci_driver *pci_dev_driver(const struct pci_dev *); | 444 | struct pci_driver *pci_dev_driver(const struct pci_dev *); |
@@ -547,9 +552,11 @@ static inline int pci_enable_device(struct pci_dev *dev) { return -EIO; } | |||
547 | static inline void pci_disable_device(struct pci_dev *dev) { } | 552 | static inline void pci_disable_device(struct pci_dev *dev) { } |
548 | static inline int pci_set_dma_mask(struct pci_dev *dev, u64 mask) { return -EIO; } | 553 | static inline int pci_set_dma_mask(struct pci_dev *dev, u64 mask) { return -EIO; } |
549 | static inline int pci_assign_resource(struct pci_dev *dev, int i) { return -EBUSY;} | 554 | static inline int pci_assign_resource(struct pci_dev *dev, int i) { return -EBUSY;} |
555 | static inline int __pci_register_driver(struct pci_driver *drv, struct module *owner) { return 0;} | ||
550 | static inline int pci_register_driver(struct pci_driver *drv) { return 0;} | 556 | static inline int pci_register_driver(struct pci_driver *drv) { return 0;} |
551 | static inline void pci_unregister_driver(struct pci_driver *drv) { } | 557 | static inline void pci_unregister_driver(struct pci_driver *drv) { } |
552 | static inline int pci_find_capability (struct pci_dev *dev, int cap) {return 0; } | 558 | static inline int pci_find_capability (struct pci_dev *dev, int cap) {return 0; } |
559 | static inline int pci_find_next_capability (struct pci_dev *dev, u8 post, int cap) { return 0; } | ||
553 | static inline int pci_find_ext_capability (struct pci_dev *dev, int cap) {return 0; } | 560 | static inline int pci_find_ext_capability (struct pci_dev *dev, int cap) {return 0; } |
554 | static inline const struct pci_device_id *pci_match_device(const struct pci_device_id *ids, const struct pci_dev *dev) { return NULL; } | 561 | static inline const struct pci_device_id *pci_match_device(const struct pci_device_id *ids, const struct pci_dev *dev) { return NULL; } |
555 | 562 | ||
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 83010231db99..0a8ea8b35816 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h | |||
@@ -1236,8 +1236,7 @@ extern unsigned int datagram_poll(struct file *file, struct socket *sock, | |||
1236 | extern int skb_copy_datagram_iovec(const struct sk_buff *from, | 1236 | extern int skb_copy_datagram_iovec(const struct sk_buff *from, |
1237 | int offset, struct iovec *to, | 1237 | int offset, struct iovec *to, |
1238 | int size); | 1238 | int size); |
1239 | extern int skb_copy_and_csum_datagram_iovec(const | 1239 | extern int skb_copy_and_csum_datagram_iovec(struct sk_buff *skb, |
1240 | struct sk_buff *skb, | ||
1241 | int hlen, | 1240 | int hlen, |
1242 | struct iovec *iov); | 1241 | struct iovec *iov); |
1243 | extern void skb_free_datagram(struct sock *sk, struct sk_buff *skb); | 1242 | extern void skb_free_datagram(struct sock *sk, struct sk_buff *skb); |
@@ -1305,6 +1304,30 @@ static inline void skb_set_timestamp(struct sk_buff *skb, const struct timeval * | |||
1305 | 1304 | ||
1306 | extern void __net_timestamp(struct sk_buff *skb); | 1305 | extern void __net_timestamp(struct sk_buff *skb); |
1307 | 1306 | ||
1307 | extern unsigned int __skb_checksum_complete(struct sk_buff *skb); | ||
1308 | |||
1309 | /** | ||
1310 | * skb_checksum_complete - Calculate checksum of an entire packet | ||
1311 | * @skb: packet to process | ||
1312 | * | ||
1313 | * This function calculates the checksum over the entire packet plus | ||
1314 | * the value of skb->csum. The latter can be used to supply the | ||
1315 | * checksum of a pseudo header as used by TCP/UDP. It returns the | ||
1316 | * checksum. | ||
1317 | * | ||
1318 | * For protocols that contain complete checksums such as ICMP/TCP/UDP, | ||
1319 | * this function can be used to verify that checksum on received | ||
1320 | * packets. In that case the function should return zero if the | ||
1321 | * checksum is correct. In particular, this function will return zero | ||
1322 | * if skb->ip_summed is CHECKSUM_UNNECESSARY which indicates that the | ||
1323 | * hardware has already verified the correctness of the checksum. | ||
1324 | */ | ||
1325 | static inline unsigned int skb_checksum_complete(struct sk_buff *skb) | ||
1326 | { | ||
1327 | return skb->ip_summed != CHECKSUM_UNNECESSARY && | ||
1328 | __skb_checksum_complete(skb); | ||
1329 | } | ||
1330 | |||
1308 | #ifdef CONFIG_NETFILTER | 1331 | #ifdef CONFIG_NETFILTER |
1309 | static inline void nf_conntrack_put(struct nf_conntrack *nfct) | 1332 | static inline void nf_conntrack_put(struct nf_conntrack *nfct) |
1310 | { | 1333 | { |
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index 22cf5e1ac987..ab2791b3189d 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h | |||
@@ -390,6 +390,7 @@ enum | |||
390 | NET_TCP_BIC_BETA=108, | 390 | NET_TCP_BIC_BETA=108, |
391 | NET_IPV4_ICMP_ERRORS_USE_INBOUND_IFADDR=109, | 391 | NET_IPV4_ICMP_ERRORS_USE_INBOUND_IFADDR=109, |
392 | NET_TCP_CONG_CONTROL=110, | 392 | NET_TCP_CONG_CONTROL=110, |
393 | NET_TCP_ABC=111, | ||
393 | }; | 394 | }; |
394 | 395 | ||
395 | enum { | 396 | enum { |
diff --git a/include/linux/tcp.h b/include/linux/tcp.h index ac4ca44c75ca..0e1da6602e05 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h | |||
@@ -307,6 +307,21 @@ struct tcp_sock { | |||
307 | struct tcp_sack_block duplicate_sack[1]; /* D-SACK block */ | 307 | struct tcp_sack_block duplicate_sack[1]; /* D-SACK block */ |
308 | struct tcp_sack_block selective_acks[4]; /* The SACKS themselves*/ | 308 | struct tcp_sack_block selective_acks[4]; /* The SACKS themselves*/ |
309 | 309 | ||
310 | struct tcp_sack_block recv_sack_cache[4]; | ||
311 | |||
312 | /* from STCP, retrans queue hinting */ | ||
313 | struct sk_buff* lost_skb_hint; | ||
314 | |||
315 | struct sk_buff *scoreboard_skb_hint; | ||
316 | struct sk_buff *retransmit_skb_hint; | ||
317 | struct sk_buff *forward_skb_hint; | ||
318 | struct sk_buff *fastpath_skb_hint; | ||
319 | |||
320 | int fastpath_cnt_hint; | ||
321 | int lost_cnt_hint; | ||
322 | int retransmit_cnt_hint; | ||
323 | int forward_cnt_hint; | ||
324 | |||
310 | __u16 advmss; /* Advertised MSS */ | 325 | __u16 advmss; /* Advertised MSS */ |
311 | __u16 prior_ssthresh; /* ssthresh saved at recovery start */ | 326 | __u16 prior_ssthresh; /* ssthresh saved at recovery start */ |
312 | __u32 lost_out; /* Lost packets */ | 327 | __u32 lost_out; /* Lost packets */ |
@@ -326,6 +341,7 @@ struct tcp_sock { | |||
326 | __u32 snd_up; /* Urgent pointer */ | 341 | __u32 snd_up; /* Urgent pointer */ |
327 | 342 | ||
328 | __u32 total_retrans; /* Total retransmits for entire connection */ | 343 | __u32 total_retrans; /* Total retransmits for entire connection */ |
344 | __u32 bytes_acked; /* Appropriate Byte Counting - RFC3465 */ | ||
329 | 345 | ||
330 | unsigned int keepalive_time; /* time before keep alive takes place */ | 346 | unsigned int keepalive_time; /* time before keep alive takes place */ |
331 | unsigned int keepalive_intvl; /* time interval between keep alive probes */ | 347 | unsigned int keepalive_intvl; /* time interval between keep alive probes */ |
diff --git a/include/net/sock.h b/include/net/sock.h index ff13c4cc287a..982b4ecd187b 100644 --- a/include/net/sock.h +++ b/include/net/sock.h | |||
@@ -1247,6 +1247,12 @@ static inline struct page *sk_stream_alloc_page(struct sock *sk) | |||
1247 | (skb != (struct sk_buff *)&(sk)->sk_write_queue); \ | 1247 | (skb != (struct sk_buff *)&(sk)->sk_write_queue); \ |
1248 | skb = skb->next) | 1248 | skb = skb->next) |
1249 | 1249 | ||
1250 | /*from STCP for fast SACK Process*/ | ||
1251 | #define sk_stream_for_retrans_queue_from(skb, sk) \ | ||
1252 | for (; (skb != (sk)->sk_send_head) && \ | ||
1253 | (skb != (struct sk_buff *)&(sk)->sk_write_queue); \ | ||
1254 | skb = skb->next) | ||
1255 | |||
1250 | /* | 1256 | /* |
1251 | * Default write policy as shown to user space via poll/select/SIGIO | 1257 | * Default write policy as shown to user space via poll/select/SIGIO |
1252 | */ | 1258 | */ |
diff --git a/include/net/tcp.h b/include/net/tcp.h index c24339c4e310..0f9848011972 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <linux/cache.h> | 28 | #include <linux/cache.h> |
29 | #include <linux/percpu.h> | 29 | #include <linux/percpu.h> |
30 | #include <linux/skbuff.h> | ||
30 | 31 | ||
31 | #include <net/inet_connection_sock.h> | 32 | #include <net/inet_connection_sock.h> |
32 | #include <net/inet_timewait_sock.h> | 33 | #include <net/inet_timewait_sock.h> |
@@ -88,10 +89,10 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo); | |||
88 | */ | 89 | */ |
89 | 90 | ||
90 | #define TCP_SYN_RETRIES 5 /* number of times to retry active opening a | 91 | #define TCP_SYN_RETRIES 5 /* number of times to retry active opening a |
91 | * connection: ~180sec is RFC minumum */ | 92 | * connection: ~180sec is RFC minimum */ |
92 | 93 | ||
93 | #define TCP_SYNACK_RETRIES 5 /* number of times to retry passive opening a | 94 | #define TCP_SYNACK_RETRIES 5 /* number of times to retry passive opening a |
94 | * connection: ~180sec is RFC minumum */ | 95 | * connection: ~180sec is RFC minimum */ |
95 | 96 | ||
96 | 97 | ||
97 | #define TCP_ORPHAN_RETRIES 7 /* number of times to retry on an orphaned | 98 | #define TCP_ORPHAN_RETRIES 7 /* number of times to retry on an orphaned |
@@ -179,7 +180,7 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo); | |||
179 | /* Flags in tp->nonagle */ | 180 | /* Flags in tp->nonagle */ |
180 | #define TCP_NAGLE_OFF 1 /* Nagle's algo is disabled */ | 181 | #define TCP_NAGLE_OFF 1 /* Nagle's algo is disabled */ |
181 | #define TCP_NAGLE_CORK 2 /* Socket is corked */ | 182 | #define TCP_NAGLE_CORK 2 /* Socket is corked */ |
182 | #define TCP_NAGLE_PUSH 4 /* Cork is overriden for already queued data */ | 183 | #define TCP_NAGLE_PUSH 4 /* Cork is overridden for already queued data */ |
183 | 184 | ||
184 | extern struct inet_timewait_death_row tcp_death_row; | 185 | extern struct inet_timewait_death_row tcp_death_row; |
185 | 186 | ||
@@ -217,6 +218,7 @@ extern int sysctl_tcp_low_latency; | |||
217 | extern int sysctl_tcp_nometrics_save; | 218 | extern int sysctl_tcp_nometrics_save; |
218 | extern int sysctl_tcp_moderate_rcvbuf; | 219 | extern int sysctl_tcp_moderate_rcvbuf; |
219 | extern int sysctl_tcp_tso_win_divisor; | 220 | extern int sysctl_tcp_tso_win_divisor; |
221 | extern int sysctl_tcp_abc; | ||
220 | 222 | ||
221 | extern atomic_t tcp_memory_allocated; | 223 | extern atomic_t tcp_memory_allocated; |
222 | extern atomic_t tcp_sockets_allocated; | 224 | extern atomic_t tcp_sockets_allocated; |
@@ -550,13 +552,13 @@ extern u32 __tcp_select_window(struct sock *sk); | |||
550 | 552 | ||
551 | /* TCP timestamps are only 32-bits, this causes a slight | 553 | /* TCP timestamps are only 32-bits, this causes a slight |
552 | * complication on 64-bit systems since we store a snapshot | 554 | * complication on 64-bit systems since we store a snapshot |
553 | * of jiffies in the buffer control blocks below. We decidely | 555 | * of jiffies in the buffer control blocks below. We decidedly |
554 | * only use of the low 32-bits of jiffies and hide the ugly | 556 | * only use of the low 32-bits of jiffies and hide the ugly |
555 | * casts with the following macro. | 557 | * casts with the following macro. |
556 | */ | 558 | */ |
557 | #define tcp_time_stamp ((__u32)(jiffies)) | 559 | #define tcp_time_stamp ((__u32)(jiffies)) |
558 | 560 | ||
559 | /* This is what the send packet queueing engine uses to pass | 561 | /* This is what the send packet queuing engine uses to pass |
560 | * TCP per-packet control information to the transmission | 562 | * TCP per-packet control information to the transmission |
561 | * code. We also store the host-order sequence numbers in | 563 | * code. We also store the host-order sequence numbers in |
562 | * here too. This is 36 bytes on 32-bit architectures, | 564 | * here too. This is 36 bytes on 32-bit architectures, |
@@ -596,7 +598,7 @@ struct tcp_skb_cb { | |||
596 | #define TCPCB_EVER_RETRANS 0x80 /* Ever retransmitted frame */ | 598 | #define TCPCB_EVER_RETRANS 0x80 /* Ever retransmitted frame */ |
597 | #define TCPCB_RETRANS (TCPCB_SACKED_RETRANS|TCPCB_EVER_RETRANS) | 599 | #define TCPCB_RETRANS (TCPCB_SACKED_RETRANS|TCPCB_EVER_RETRANS) |
598 | 600 | ||
599 | #define TCPCB_URG 0x20 /* Urgent pointer advenced here */ | 601 | #define TCPCB_URG 0x20 /* Urgent pointer advanced here */ |
600 | 602 | ||
601 | #define TCPCB_AT_TAIL (TCPCB_URG) | 603 | #define TCPCB_AT_TAIL (TCPCB_URG) |
602 | 604 | ||
@@ -764,6 +766,33 @@ static inline __u32 tcp_current_ssthresh(const struct sock *sk) | |||
764 | (tp->snd_cwnd >> 2))); | 766 | (tp->snd_cwnd >> 2))); |
765 | } | 767 | } |
766 | 768 | ||
769 | /* | ||
770 | * Linear increase during slow start | ||
771 | */ | ||
772 | static inline void tcp_slow_start(struct tcp_sock *tp) | ||
773 | { | ||
774 | if (sysctl_tcp_abc) { | ||
775 | /* RFC3465: Slow Start | ||
776 | * TCP sender SHOULD increase cwnd by the number of | ||
777 | * previously unacknowledged bytes ACKed by each incoming | ||
778 | * acknowledgment, provided the increase is not more than L | ||
779 | */ | ||
780 | if (tp->bytes_acked < tp->mss_cache) | ||
781 | return; | ||
782 | |||
783 | /* We MAY increase by 2 if discovered delayed ack */ | ||
784 | if (sysctl_tcp_abc > 1 && tp->bytes_acked > 2*tp->mss_cache) { | ||
785 | if (tp->snd_cwnd < tp->snd_cwnd_clamp) | ||
786 | tp->snd_cwnd++; | ||
787 | } | ||
788 | } | ||
789 | tp->bytes_acked = 0; | ||
790 | |||
791 | if (tp->snd_cwnd < tp->snd_cwnd_clamp) | ||
792 | tp->snd_cwnd++; | ||
793 | } | ||
794 | |||
795 | |||
767 | static inline void tcp_sync_left_out(struct tcp_sock *tp) | 796 | static inline void tcp_sync_left_out(struct tcp_sock *tp) |
768 | { | 797 | { |
769 | if (tp->rx_opt.sack_ok && | 798 | if (tp->rx_opt.sack_ok && |
@@ -793,6 +822,7 @@ static inline void tcp_enter_cwr(struct sock *sk) | |||
793 | struct tcp_sock *tp = tcp_sk(sk); | 822 | struct tcp_sock *tp = tcp_sk(sk); |
794 | 823 | ||
795 | tp->prior_ssthresh = 0; | 824 | tp->prior_ssthresh = 0; |
825 | tp->bytes_acked = 0; | ||
796 | if (inet_csk(sk)->icsk_ca_state < TCP_CA_CWR) { | 826 | if (inet_csk(sk)->icsk_ca_state < TCP_CA_CWR) { |
797 | __tcp_enter_cwr(sk); | 827 | __tcp_enter_cwr(sk); |
798 | tcp_set_ca_state(sk, TCP_CA_CWR); | 828 | tcp_set_ca_state(sk, TCP_CA_CWR); |
@@ -809,6 +839,27 @@ static __inline__ __u32 tcp_max_burst(const struct tcp_sock *tp) | |||
809 | return 3; | 839 | return 3; |
810 | } | 840 | } |
811 | 841 | ||
842 | /* RFC2861 Check whether we are limited by application or congestion window | ||
843 | * This is the inverse of cwnd check in tcp_tso_should_defer | ||
844 | */ | ||
845 | static inline int tcp_is_cwnd_limited(const struct sock *sk, u32 in_flight) | ||
846 | { | ||
847 | const struct tcp_sock *tp = tcp_sk(sk); | ||
848 | u32 left; | ||
849 | |||
850 | if (in_flight >= tp->snd_cwnd) | ||
851 | return 1; | ||
852 | |||
853 | if (!(sk->sk_route_caps & NETIF_F_TSO)) | ||
854 | return 0; | ||
855 | |||
856 | left = tp->snd_cwnd - in_flight; | ||
857 | if (sysctl_tcp_tso_win_divisor) | ||
858 | return left * sysctl_tcp_tso_win_divisor < tp->snd_cwnd; | ||
859 | else | ||
860 | return left <= tcp_max_burst(tp); | ||
861 | } | ||
862 | |||
812 | static __inline__ void tcp_minshall_update(struct tcp_sock *tp, int mss, | 863 | static __inline__ void tcp_minshall_update(struct tcp_sock *tp, int mss, |
813 | const struct sk_buff *skb) | 864 | const struct sk_buff *skb) |
814 | { | 865 | { |
@@ -852,7 +903,7 @@ static __inline__ u16 tcp_v4_check(struct tcphdr *th, int len, | |||
852 | 903 | ||
853 | static __inline__ int __tcp_checksum_complete(struct sk_buff *skb) | 904 | static __inline__ int __tcp_checksum_complete(struct sk_buff *skb) |
854 | { | 905 | { |
855 | return (unsigned short)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum)); | 906 | return __skb_checksum_complete(skb); |
856 | } | 907 | } |
857 | 908 | ||
858 | static __inline__ int tcp_checksum_complete(struct sk_buff *skb) | 909 | static __inline__ int tcp_checksum_complete(struct sk_buff *skb) |
@@ -1156,6 +1207,15 @@ static inline void tcp_mib_init(void) | |||
1156 | TCP_ADD_STATS_USER(TCP_MIB_MAXCONN, -1); | 1207 | TCP_ADD_STATS_USER(TCP_MIB_MAXCONN, -1); |
1157 | } | 1208 | } |
1158 | 1209 | ||
1210 | /*from STCP */ | ||
1211 | static inline void clear_all_retrans_hints(struct tcp_sock *tp){ | ||
1212 | tp->lost_skb_hint = NULL; | ||
1213 | tp->scoreboard_skb_hint = NULL; | ||
1214 | tp->retransmit_skb_hint = NULL; | ||
1215 | tp->forward_skb_hint = NULL; | ||
1216 | tp->fastpath_skb_hint = NULL; | ||
1217 | } | ||
1218 | |||
1159 | /* /proc */ | 1219 | /* /proc */ |
1160 | enum tcp_seq_states { | 1220 | enum tcp_seq_states { |
1161 | TCP_SEQ_STATE_LISTENING, | 1221 | TCP_SEQ_STATE_LISTENING, |
diff --git a/include/rdma/ib_user_verbs.h b/include/rdma/ib_user_verbs.h index 072f3a2edace..5ff1490c08db 100644 --- a/include/rdma/ib_user_verbs.h +++ b/include/rdma/ib_user_verbs.h | |||
@@ -43,7 +43,7 @@ | |||
43 | * Increment this value if any changes that break userspace ABI | 43 | * Increment this value if any changes that break userspace ABI |
44 | * compatibility are made. | 44 | * compatibility are made. |
45 | */ | 45 | */ |
46 | #define IB_USER_VERBS_ABI_VERSION 3 | 46 | #define IB_USER_VERBS_ABI_VERSION 4 |
47 | 47 | ||
48 | enum { | 48 | enum { |
49 | IB_USER_VERBS_CMD_GET_CONTEXT, | 49 | IB_USER_VERBS_CMD_GET_CONTEXT, |
@@ -333,6 +333,11 @@ struct ib_uverbs_create_qp { | |||
333 | struct ib_uverbs_create_qp_resp { | 333 | struct ib_uverbs_create_qp_resp { |
334 | __u32 qp_handle; | 334 | __u32 qp_handle; |
335 | __u32 qpn; | 335 | __u32 qpn; |
336 | __u32 max_send_wr; | ||
337 | __u32 max_recv_wr; | ||
338 | __u32 max_send_sge; | ||
339 | __u32 max_recv_sge; | ||
340 | __u32 max_inline_data; | ||
336 | }; | 341 | }; |
337 | 342 | ||
338 | /* | 343 | /* |
@@ -552,9 +557,7 @@ struct ib_uverbs_modify_srq { | |||
552 | __u32 srq_handle; | 557 | __u32 srq_handle; |
553 | __u32 attr_mask; | 558 | __u32 attr_mask; |
554 | __u32 max_wr; | 559 | __u32 max_wr; |
555 | __u32 max_sge; | ||
556 | __u32 srq_limit; | 560 | __u32 srq_limit; |
557 | __u32 reserved; | ||
558 | __u64 driver_data[0]; | 561 | __u64 driver_data[0]; |
559 | }; | 562 | }; |
560 | 563 | ||
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h index f72d46d54e0a..a7f4c355a91f 100644 --- a/include/rdma/ib_verbs.h +++ b/include/rdma/ib_verbs.h | |||
@@ -881,7 +881,7 @@ struct ib_device { | |||
881 | struct ib_ucontext *context, | 881 | struct ib_ucontext *context, |
882 | struct ib_udata *udata); | 882 | struct ib_udata *udata); |
883 | int (*destroy_cq)(struct ib_cq *cq); | 883 | int (*destroy_cq)(struct ib_cq *cq); |
884 | int (*resize_cq)(struct ib_cq *cq, int *cqe); | 884 | int (*resize_cq)(struct ib_cq *cq, int cqe); |
885 | int (*poll_cq)(struct ib_cq *cq, int num_entries, | 885 | int (*poll_cq)(struct ib_cq *cq, int num_entries, |
886 | struct ib_wc *wc); | 886 | struct ib_wc *wc); |
887 | int (*peek_cq)(struct ib_cq *cq, int wc_cnt); | 887 | int (*peek_cq)(struct ib_cq *cq, int wc_cnt); |
diff --git a/kernel/signal.c b/kernel/signal.c index 1bf3c39d6109..80789a59b4db 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -1499,7 +1499,7 @@ void do_notify_parent(struct task_struct *tsk, int sig) | |||
1499 | 1499 | ||
1500 | psig = tsk->parent->sighand; | 1500 | psig = tsk->parent->sighand; |
1501 | spin_lock_irqsave(&psig->siglock, flags); | 1501 | spin_lock_irqsave(&psig->siglock, flags); |
1502 | if (sig == SIGCHLD && | 1502 | if (!tsk->ptrace && sig == SIGCHLD && |
1503 | (psig->action[SIGCHLD-1].sa.sa_handler == SIG_IGN || | 1503 | (psig->action[SIGCHLD-1].sa.sa_handler == SIG_IGN || |
1504 | (psig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDWAIT))) { | 1504 | (psig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDWAIT))) { |
1505 | /* | 1505 | /* |
diff --git a/kernel/sys.c b/kernel/sys.c index c43b3e22bbda..bce933ebb29f 100644 --- a/kernel/sys.c +++ b/kernel/sys.c | |||
@@ -1497,6 +1497,8 @@ EXPORT_SYMBOL(in_egroup_p); | |||
1497 | 1497 | ||
1498 | DECLARE_RWSEM(uts_sem); | 1498 | DECLARE_RWSEM(uts_sem); |
1499 | 1499 | ||
1500 | EXPORT_SYMBOL(uts_sem); | ||
1501 | |||
1500 | asmlinkage long sys_newuname(struct new_utsname __user * name) | 1502 | asmlinkage long sys_newuname(struct new_utsname __user * name) |
1501 | { | 1503 | { |
1502 | int errno = 0; | 1504 | int errno = 0; |
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index ff81b5c65511..987225bdd661 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -1330,7 +1330,7 @@ void show_free_areas(void) | |||
1330 | } else | 1330 | } else |
1331 | printk("\n"); | 1331 | printk("\n"); |
1332 | 1332 | ||
1333 | for_each_cpu(cpu) { | 1333 | for_each_online_cpu(cpu) { |
1334 | struct per_cpu_pageset *pageset; | 1334 | struct per_cpu_pageset *pageset; |
1335 | 1335 | ||
1336 | pageset = zone_pcp(zone, cpu); | 1336 | pageset = zone_pcp(zone, cpu); |
diff --git a/net/core/datagram.c b/net/core/datagram.c index d219435d086c..1bcfef51ac58 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c | |||
@@ -350,6 +350,20 @@ fault: | |||
350 | return -EFAULT; | 350 | return -EFAULT; |
351 | } | 351 | } |
352 | 352 | ||
353 | unsigned int __skb_checksum_complete(struct sk_buff *skb) | ||
354 | { | ||
355 | unsigned int sum; | ||
356 | |||
357 | sum = (u16)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum)); | ||
358 | if (likely(!sum)) { | ||
359 | if (unlikely(skb->ip_summed == CHECKSUM_HW)) | ||
360 | netdev_rx_csum_fault(skb->dev); | ||
361 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
362 | } | ||
363 | return sum; | ||
364 | } | ||
365 | EXPORT_SYMBOL(__skb_checksum_complete); | ||
366 | |||
353 | /** | 367 | /** |
354 | * skb_copy_and_csum_datagram_iovec - Copy and checkum skb to user iovec. | 368 | * skb_copy_and_csum_datagram_iovec - Copy and checkum skb to user iovec. |
355 | * @skb: skbuff | 369 | * @skb: skbuff |
@@ -363,7 +377,7 @@ fault: | |||
363 | * -EFAULT - fault during copy. Beware, in this case iovec | 377 | * -EFAULT - fault during copy. Beware, in this case iovec |
364 | * can be modified! | 378 | * can be modified! |
365 | */ | 379 | */ |
366 | int skb_copy_and_csum_datagram_iovec(const struct sk_buff *skb, | 380 | int skb_copy_and_csum_datagram_iovec(struct sk_buff *skb, |
367 | int hlen, struct iovec *iov) | 381 | int hlen, struct iovec *iov) |
368 | { | 382 | { |
369 | unsigned int csum; | 383 | unsigned int csum; |
@@ -376,8 +390,7 @@ int skb_copy_and_csum_datagram_iovec(const struct sk_buff *skb, | |||
376 | iov++; | 390 | iov++; |
377 | 391 | ||
378 | if (iov->iov_len < chunk) { | 392 | if (iov->iov_len < chunk) { |
379 | if ((unsigned short)csum_fold(skb_checksum(skb, 0, chunk + hlen, | 393 | if (__skb_checksum_complete(skb)) |
380 | skb->csum))) | ||
381 | goto csum_error; | 394 | goto csum_error; |
382 | if (skb_copy_datagram_iovec(skb, hlen, iov, chunk)) | 395 | if (skb_copy_datagram_iovec(skb, hlen, iov, chunk)) |
383 | goto fault; | 396 | goto fault; |
@@ -388,6 +401,8 @@ int skb_copy_and_csum_datagram_iovec(const struct sk_buff *skb, | |||
388 | goto fault; | 401 | goto fault; |
389 | if ((unsigned short)csum_fold(csum)) | 402 | if ((unsigned short)csum_fold(csum)) |
390 | goto csum_error; | 403 | goto csum_error; |
404 | if (unlikely(skb->ip_summed == CHECKSUM_HW)) | ||
405 | netdev_rx_csum_fault(skb->dev); | ||
391 | iov->iov_len -= chunk; | 406 | iov->iov_len -= chunk; |
392 | iov->iov_base += chunk; | 407 | iov->iov_base += chunk; |
393 | } | 408 | } |
diff --git a/net/core/dev.c b/net/core/dev.c index 8d1541595277..0b48e294aafe 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -1108,6 +1108,18 @@ out: | |||
1108 | return ret; | 1108 | return ret; |
1109 | } | 1109 | } |
1110 | 1110 | ||
1111 | /* Take action when hardware reception checksum errors are detected. */ | ||
1112 | #ifdef CONFIG_BUG | ||
1113 | void netdev_rx_csum_fault(struct net_device *dev) | ||
1114 | { | ||
1115 | if (net_ratelimit()) { | ||
1116 | printk(KERN_ERR "%s: hw csum failure.\n", dev->name); | ||
1117 | dump_stack(); | ||
1118 | } | ||
1119 | } | ||
1120 | EXPORT_SYMBOL(netdev_rx_csum_fault); | ||
1121 | #endif | ||
1122 | |||
1111 | #ifdef CONFIG_HIGHMEM | 1123 | #ifdef CONFIG_HIGHMEM |
1112 | /* Actually, we should eliminate this check as soon as we know, that: | 1124 | /* Actually, we should eliminate this check as soon as we know, that: |
1113 | * 1. IOMMU is present and allows to map all the memory. | 1125 | * 1. IOMMU is present and allows to map all the memory. |
diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 802fe11efad0..49424a42a2c0 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c | |||
@@ -101,16 +101,20 @@ void netpoll_queue(struct sk_buff *skb) | |||
101 | static int checksum_udp(struct sk_buff *skb, struct udphdr *uh, | 101 | static int checksum_udp(struct sk_buff *skb, struct udphdr *uh, |
102 | unsigned short ulen, u32 saddr, u32 daddr) | 102 | unsigned short ulen, u32 saddr, u32 daddr) |
103 | { | 103 | { |
104 | if (uh->check == 0) | 104 | unsigned int psum; |
105 | |||
106 | if (uh->check == 0 || skb->ip_summed == CHECKSUM_UNNECESSARY) | ||
105 | return 0; | 107 | return 0; |
106 | 108 | ||
107 | if (skb->ip_summed == CHECKSUM_HW) | 109 | psum = csum_tcpudp_nofold(saddr, daddr, ulen, IPPROTO_UDP, 0); |
108 | return csum_tcpudp_magic( | 110 | |
109 | saddr, daddr, ulen, IPPROTO_UDP, skb->csum); | 111 | if (skb->ip_summed == CHECKSUM_HW && |
112 | !(u16)csum_fold(csum_add(psum, skb->csum))) | ||
113 | return 0; | ||
110 | 114 | ||
111 | skb->csum = csum_tcpudp_nofold(saddr, daddr, ulen, IPPROTO_UDP, 0); | 115 | skb->csum = psum; |
112 | 116 | ||
113 | return csum_fold(skb_checksum(skb, 0, skb->len, skb->csum)); | 117 | return __skb_checksum_complete(skb); |
114 | } | 118 | } |
115 | 119 | ||
116 | /* | 120 | /* |
@@ -489,7 +493,7 @@ int __netpoll_rx(struct sk_buff *skb) | |||
489 | 493 | ||
490 | if (ulen != len) | 494 | if (ulen != len) |
491 | goto out; | 495 | goto out; |
492 | if (checksum_udp(skb, uh, ulen, iph->saddr, iph->daddr) < 0) | 496 | if (checksum_udp(skb, uh, ulen, iph->saddr, iph->daddr)) |
493 | goto out; | 497 | goto out; |
494 | if (np->local_ip && np->local_ip != ntohl(iph->daddr)) | 498 | if (np->local_ip && np->local_ip != ntohl(iph->daddr)) |
495 | goto out; | 499 | goto out; |
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 175e093ec564..e3eceecd0496 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c | |||
@@ -934,11 +934,11 @@ int icmp_rcv(struct sk_buff *skb) | |||
934 | case CHECKSUM_HW: | 934 | case CHECKSUM_HW: |
935 | if (!(u16)csum_fold(skb->csum)) | 935 | if (!(u16)csum_fold(skb->csum)) |
936 | break; | 936 | break; |
937 | LIMIT_NETDEBUG(KERN_DEBUG "icmp v4 hw csum failure\n"); | 937 | /* fall through */ |
938 | case CHECKSUM_NONE: | 938 | case CHECKSUM_NONE: |
939 | if ((u16)csum_fold(skb_checksum(skb, 0, skb->len, 0))) | 939 | skb->csum = 0; |
940 | if (__skb_checksum_complete(skb)) | ||
940 | goto error; | 941 | goto error; |
941 | default:; | ||
942 | } | 942 | } |
943 | 943 | ||
944 | if (!pskb_pull(skb, sizeof(struct icmphdr))) | 944 | if (!pskb_pull(skb, sizeof(struct icmphdr))) |
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index c6247fc84060..c04607b49212 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c | |||
@@ -872,11 +872,18 @@ int igmp_rcv(struct sk_buff *skb) | |||
872 | return 0; | 872 | return 0; |
873 | } | 873 | } |
874 | 874 | ||
875 | if (!pskb_may_pull(skb, sizeof(struct igmphdr)) || | 875 | if (!pskb_may_pull(skb, sizeof(struct igmphdr))) |
876 | (u16)csum_fold(skb_checksum(skb, 0, len, 0))) { | 876 | goto drop; |
877 | in_dev_put(in_dev); | 877 | |
878 | kfree_skb(skb); | 878 | switch (skb->ip_summed) { |
879 | return 0; | 879 | case CHECKSUM_HW: |
880 | if (!(u16)csum_fold(skb->csum)) | ||
881 | break; | ||
882 | /* fall through */ | ||
883 | case CHECKSUM_NONE: | ||
884 | skb->csum = 0; | ||
885 | if (__skb_checksum_complete(skb)) | ||
886 | goto drop; | ||
880 | } | 887 | } |
881 | 888 | ||
882 | ih = skb->h.igmph; | 889 | ih = skb->h.igmph; |
@@ -906,6 +913,8 @@ int igmp_rcv(struct sk_buff *skb) | |||
906 | default: | 913 | default: |
907 | NETDEBUG(KERN_DEBUG "New IGMP type=%d, why we do not know about it?\n", ih->type); | 914 | NETDEBUG(KERN_DEBUG "New IGMP type=%d, why we do not know about it?\n", ih->type); |
908 | } | 915 | } |
916 | |||
917 | drop: | ||
909 | in_dev_put(in_dev); | 918 | in_dev_put(in_dev); |
910 | kfree_skb(skb); | 919 | kfree_skb(skb); |
911 | return 0; | 920 | return 0; |
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 896ce3f8f53a..4e9c74b54b15 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c | |||
@@ -577,15 +577,16 @@ static int ipgre_rcv(struct sk_buff *skb) | |||
577 | goto drop_nolock; | 577 | goto drop_nolock; |
578 | 578 | ||
579 | if (flags&GRE_CSUM) { | 579 | if (flags&GRE_CSUM) { |
580 | if (skb->ip_summed == CHECKSUM_HW) { | 580 | switch (skb->ip_summed) { |
581 | case CHECKSUM_HW: | ||
581 | csum = (u16)csum_fold(skb->csum); | 582 | csum = (u16)csum_fold(skb->csum); |
582 | if (csum) | 583 | if (!csum) |
583 | skb->ip_summed = CHECKSUM_NONE; | 584 | break; |
584 | } | 585 | /* fall through */ |
585 | if (skb->ip_summed == CHECKSUM_NONE) { | 586 | case CHECKSUM_NONE: |
586 | skb->csum = skb_checksum(skb, 0, skb->len, 0); | 587 | skb->csum = 0; |
588 | csum = __skb_checksum_complete(skb); | ||
587 | skb->ip_summed = CHECKSUM_HW; | 589 | skb->ip_summed = CHECKSUM_HW; |
588 | csum = (u16)csum_fold(skb->csum); | ||
589 | } | 590 | } |
590 | offset += 4; | 591 | offset += 4; |
591 | } | 592 | } |
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c index 5198f3a1e2cd..e4d6b268e8c4 100644 --- a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c +++ b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/in.h> | 13 | #include <linux/in.h> |
14 | #include <linux/icmp.h> | 14 | #include <linux/icmp.h> |
15 | #include <linux/seq_file.h> | 15 | #include <linux/seq_file.h> |
16 | #include <linux/skbuff.h> | ||
16 | #include <net/ip.h> | 17 | #include <net/ip.h> |
17 | #include <net/checksum.h> | 18 | #include <net/checksum.h> |
18 | #include <linux/netfilter.h> | 19 | #include <linux/netfilter.h> |
@@ -230,19 +231,15 @@ icmp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo, | |||
230 | case CHECKSUM_HW: | 231 | case CHECKSUM_HW: |
231 | if (!(u16)csum_fold(skb->csum)) | 232 | if (!(u16)csum_fold(skb->csum)) |
232 | break; | 233 | break; |
233 | if (LOG_INVALID(IPPROTO_ICMP)) | 234 | /* fall through */ |
234 | nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL, | ||
235 | "ip_ct_icmp: bad HW ICMP checksum "); | ||
236 | return -NF_ACCEPT; | ||
237 | case CHECKSUM_NONE: | 235 | case CHECKSUM_NONE: |
238 | if ((u16)csum_fold(skb_checksum(skb, 0, skb->len, 0))) { | 236 | skb->csum = 0; |
237 | if (__skb_checksum_complete(skb)) { | ||
239 | if (LOG_INVALID(IPPROTO_ICMP)) | 238 | if (LOG_INVALID(IPPROTO_ICMP)) |
240 | nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL, | 239 | nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL, |
241 | "ip_ct_icmp: bad ICMP checksum "); | 240 | "ip_ct_icmp: bad ICMP checksum "); |
242 | return -NF_ACCEPT; | 241 | return -NF_ACCEPT; |
243 | } | 242 | } |
244 | default: | ||
245 | break; | ||
246 | } | 243 | } |
247 | 244 | ||
248 | checksum_skipped: | 245 | checksum_skipped: |
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index 652685623519..01444a02b48b 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c | |||
@@ -645,6 +645,14 @@ ctl_table ipv4_table[] = { | |||
645 | .proc_handler = &proc_tcp_congestion_control, | 645 | .proc_handler = &proc_tcp_congestion_control, |
646 | .strategy = &sysctl_tcp_congestion_control, | 646 | .strategy = &sysctl_tcp_congestion_control, |
647 | }, | 647 | }, |
648 | { | ||
649 | .ctl_name = NET_TCP_ABC, | ||
650 | .procname = "tcp_abc", | ||
651 | .data = &sysctl_tcp_abc, | ||
652 | .maxlen = sizeof(int), | ||
653 | .mode = 0644, | ||
654 | .proc_handler = &proc_dointvec, | ||
655 | }, | ||
648 | 656 | ||
649 | { .ctl_name = 0 } | 657 | { .ctl_name = 0 } |
650 | }; | 658 | }; |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 72b7c22e1ea5..9ac7a4f46bd8 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -1640,7 +1640,7 @@ int tcp_disconnect(struct sock *sk, int flags) | |||
1640 | } else if (tcp_need_reset(old_state) || | 1640 | } else if (tcp_need_reset(old_state) || |
1641 | (tp->snd_nxt != tp->write_seq && | 1641 | (tp->snd_nxt != tp->write_seq && |
1642 | (1 << old_state) & (TCPF_CLOSING | TCPF_LAST_ACK))) { | 1642 | (1 << old_state) & (TCPF_CLOSING | TCPF_LAST_ACK))) { |
1643 | /* The last check adjusts for discrepance of Linux wrt. RFC | 1643 | /* The last check adjusts for discrepancy of Linux wrt. RFC |
1644 | * states | 1644 | * states |
1645 | */ | 1645 | */ |
1646 | tcp_send_active_reset(sk, gfp_any()); | 1646 | tcp_send_active_reset(sk, gfp_any()); |
@@ -1669,6 +1669,7 @@ int tcp_disconnect(struct sock *sk, int flags) | |||
1669 | tp->packets_out = 0; | 1669 | tp->packets_out = 0; |
1670 | tp->snd_ssthresh = 0x7fffffff; | 1670 | tp->snd_ssthresh = 0x7fffffff; |
1671 | tp->snd_cwnd_cnt = 0; | 1671 | tp->snd_cwnd_cnt = 0; |
1672 | tp->bytes_acked = 0; | ||
1672 | tcp_set_ca_state(sk, TCP_CA_Open); | 1673 | tcp_set_ca_state(sk, TCP_CA_Open); |
1673 | tcp_clear_retrans(tp); | 1674 | tcp_clear_retrans(tp); |
1674 | inet_csk_delack_init(sk); | 1675 | inet_csk_delack_init(sk); |
diff --git a/net/ipv4/tcp_bic.c b/net/ipv4/tcp_bic.c index ae35e0609047..1d0cd86621b1 100644 --- a/net/ipv4/tcp_bic.c +++ b/net/ipv4/tcp_bic.c | |||
@@ -217,17 +217,15 @@ static void bictcp_cong_avoid(struct sock *sk, u32 ack, | |||
217 | 217 | ||
218 | bictcp_low_utilization(sk, data_acked); | 218 | bictcp_low_utilization(sk, data_acked); |
219 | 219 | ||
220 | if (in_flight < tp->snd_cwnd) | 220 | if (!tcp_is_cwnd_limited(sk, in_flight)) |
221 | return; | 221 | return; |
222 | 222 | ||
223 | if (tp->snd_cwnd <= tp->snd_ssthresh) { | 223 | if (tp->snd_cwnd <= tp->snd_ssthresh) |
224 | /* In "safe" area, increase. */ | 224 | tcp_slow_start(tp); |
225 | if (tp->snd_cwnd < tp->snd_cwnd_clamp) | 225 | else { |
226 | tp->snd_cwnd++; | ||
227 | } else { | ||
228 | bictcp_update(ca, tp->snd_cwnd); | 226 | bictcp_update(ca, tp->snd_cwnd); |
229 | 227 | ||
230 | /* In dangerous area, increase slowly. | 228 | /* In dangerous area, increase slowly. |
231 | * In theory this is tp->snd_cwnd += 1 / tp->snd_cwnd | 229 | * In theory this is tp->snd_cwnd += 1 / tp->snd_cwnd |
232 | */ | 230 | */ |
233 | if (tp->snd_cwnd_cnt >= ca->cnt) { | 231 | if (tp->snd_cwnd_cnt >= ca->cnt) { |
diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c index bbf2d6624e89..c7cc62c8dc12 100644 --- a/net/ipv4/tcp_cong.c +++ b/net/ipv4/tcp_cong.c | |||
@@ -186,24 +186,32 @@ void tcp_reno_cong_avoid(struct sock *sk, u32 ack, u32 rtt, u32 in_flight, | |||
186 | { | 186 | { |
187 | struct tcp_sock *tp = tcp_sk(sk); | 187 | struct tcp_sock *tp = tcp_sk(sk); |
188 | 188 | ||
189 | if (in_flight < tp->snd_cwnd) | 189 | if (!tcp_is_cwnd_limited(sk, in_flight)) |
190 | return; | 190 | return; |
191 | 191 | ||
192 | if (tp->snd_cwnd <= tp->snd_ssthresh) { | 192 | /* In "safe" area, increase. */ |
193 | /* In "safe" area, increase. */ | 193 | if (tp->snd_cwnd <= tp->snd_ssthresh) |
194 | if (tp->snd_cwnd < tp->snd_cwnd_clamp) | 194 | tcp_slow_start(tp); |
195 | tp->snd_cwnd++; | 195 | |
196 | } else { | 196 | /* In dangerous area, increase slowly. */ |
197 | /* In dangerous area, increase slowly. | 197 | else if (sysctl_tcp_abc) { |
198 | * In theory this is tp->snd_cwnd += 1 / tp->snd_cwnd | 198 | /* RFC3465: Apppriate Byte Count |
199 | */ | 199 | * increase once for each full cwnd acked |
200 | if (tp->snd_cwnd_cnt >= tp->snd_cwnd) { | 200 | */ |
201 | if (tp->snd_cwnd < tp->snd_cwnd_clamp) | 201 | if (tp->bytes_acked >= tp->snd_cwnd*tp->mss_cache) { |
202 | tp->snd_cwnd++; | 202 | tp->bytes_acked -= tp->snd_cwnd*tp->mss_cache; |
203 | tp->snd_cwnd_cnt = 0; | 203 | if (tp->snd_cwnd < tp->snd_cwnd_clamp) |
204 | } else | 204 | tp->snd_cwnd++; |
205 | tp->snd_cwnd_cnt++; | 205 | } |
206 | } | 206 | } else { |
207 | /* In theory this is tp->snd_cwnd += 1 / tp->snd_cwnd */ | ||
208 | if (tp->snd_cwnd_cnt >= tp->snd_cwnd) { | ||
209 | if (tp->snd_cwnd < tp->snd_cwnd_clamp) | ||
210 | tp->snd_cwnd++; | ||
211 | tp->snd_cwnd_cnt = 0; | ||
212 | } else | ||
213 | tp->snd_cwnd_cnt++; | ||
214 | } | ||
207 | } | 215 | } |
208 | EXPORT_SYMBOL_GPL(tcp_reno_cong_avoid); | 216 | EXPORT_SYMBOL_GPL(tcp_reno_cong_avoid); |
209 | 217 | ||
diff --git a/net/ipv4/tcp_highspeed.c b/net/ipv4/tcp_highspeed.c index 6acc04bde080..82b3c189bd7d 100644 --- a/net/ipv4/tcp_highspeed.c +++ b/net/ipv4/tcp_highspeed.c | |||
@@ -111,18 +111,17 @@ static void hstcp_init(struct sock *sk) | |||
111 | } | 111 | } |
112 | 112 | ||
113 | static void hstcp_cong_avoid(struct sock *sk, u32 adk, u32 rtt, | 113 | static void hstcp_cong_avoid(struct sock *sk, u32 adk, u32 rtt, |
114 | u32 in_flight, int good) | 114 | u32 in_flight, u32 pkts_acked) |
115 | { | 115 | { |
116 | struct tcp_sock *tp = tcp_sk(sk); | 116 | struct tcp_sock *tp = tcp_sk(sk); |
117 | struct hstcp *ca = inet_csk_ca(sk); | 117 | struct hstcp *ca = inet_csk_ca(sk); |
118 | 118 | ||
119 | if (in_flight < tp->snd_cwnd) | 119 | if (!tcp_is_cwnd_limited(sk, in_flight)) |
120 | return; | 120 | return; |
121 | 121 | ||
122 | if (tp->snd_cwnd <= tp->snd_ssthresh) { | 122 | if (tp->snd_cwnd <= tp->snd_ssthresh) |
123 | if (tp->snd_cwnd < tp->snd_cwnd_clamp) | 123 | tcp_slow_start(tp); |
124 | tp->snd_cwnd++; | 124 | else { |
125 | } else { | ||
126 | /* Update AIMD parameters */ | 125 | /* Update AIMD parameters */ |
127 | if (tp->snd_cwnd > hstcp_aimd_vals[ca->ai].cwnd) { | 126 | if (tp->snd_cwnd > hstcp_aimd_vals[ca->ai].cwnd) { |
128 | while (tp->snd_cwnd > hstcp_aimd_vals[ca->ai].cwnd && | 127 | while (tp->snd_cwnd > hstcp_aimd_vals[ca->ai].cwnd && |
diff --git a/net/ipv4/tcp_htcp.c b/net/ipv4/tcp_htcp.c index e47b37984e95..3284cfb993e6 100644 --- a/net/ipv4/tcp_htcp.c +++ b/net/ipv4/tcp_htcp.c | |||
@@ -207,14 +207,13 @@ static void htcp_cong_avoid(struct sock *sk, u32 ack, u32 rtt, | |||
207 | struct tcp_sock *tp = tcp_sk(sk); | 207 | struct tcp_sock *tp = tcp_sk(sk); |
208 | struct htcp *ca = inet_csk_ca(sk); | 208 | struct htcp *ca = inet_csk_ca(sk); |
209 | 209 | ||
210 | if (in_flight < tp->snd_cwnd) | 210 | if (!tcp_is_cwnd_limited(sk, in_flight)) |
211 | return; | 211 | return; |
212 | 212 | ||
213 | if (tp->snd_cwnd <= tp->snd_ssthresh) { | 213 | if (tp->snd_cwnd <= tp->snd_ssthresh) |
214 | /* In "safe" area, increase. */ | 214 | tcp_slow_start(tp); |
215 | if (tp->snd_cwnd < tp->snd_cwnd_clamp) | 215 | else { |
216 | tp->snd_cwnd++; | 216 | |
217 | } else { | ||
218 | measure_rtt(sk); | 217 | measure_rtt(sk); |
219 | 218 | ||
220 | /* keep track of number of round-trip times since last backoff event */ | 219 | /* keep track of number of round-trip times since last backoff event */ |
@@ -224,7 +223,7 @@ static void htcp_cong_avoid(struct sock *sk, u32 ack, u32 rtt, | |||
224 | htcp_alpha_update(ca); | 223 | htcp_alpha_update(ca); |
225 | } | 224 | } |
226 | 225 | ||
227 | /* In dangerous area, increase slowly. | 226 | /* In dangerous area, increase slowly. |
228 | * In theory this is tp->snd_cwnd += alpha / tp->snd_cwnd | 227 | * In theory this is tp->snd_cwnd += alpha / tp->snd_cwnd |
229 | */ | 228 | */ |
230 | if ((tp->snd_cwnd_cnt++ * ca->alpha)>>7 >= tp->snd_cwnd) { | 229 | if ((tp->snd_cwnd_cnt++ * ca->alpha)>>7 >= tp->snd_cwnd) { |
diff --git a/net/ipv4/tcp_hybla.c b/net/ipv4/tcp_hybla.c index 77add63623df..40dbb3877510 100644 --- a/net/ipv4/tcp_hybla.c +++ b/net/ipv4/tcp_hybla.c | |||
@@ -100,12 +100,12 @@ static void hybla_cong_avoid(struct sock *sk, u32 ack, u32 rtt, | |||
100 | ca->minrtt = tp->srtt; | 100 | ca->minrtt = tp->srtt; |
101 | } | 101 | } |
102 | 102 | ||
103 | if (!tcp_is_cwnd_limited(sk, in_flight)) | ||
104 | return; | ||
105 | |||
103 | if (!ca->hybla_en) | 106 | if (!ca->hybla_en) |
104 | return tcp_reno_cong_avoid(sk, ack, rtt, in_flight, flag); | 107 | return tcp_reno_cong_avoid(sk, ack, rtt, in_flight, flag); |
105 | 108 | ||
106 | if (in_flight < tp->snd_cwnd) | ||
107 | return; | ||
108 | |||
109 | if (ca->rho == 0) | 109 | if (ca->rho == 0) |
110 | hybla_recalc_param(sk); | 110 | hybla_recalc_param(sk); |
111 | 111 | ||
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 3e98b57578dc..40a26b7157b4 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -42,7 +42,7 @@ | |||
42 | * Andi Kleen : Moved open_request checking here | 42 | * Andi Kleen : Moved open_request checking here |
43 | * and process RSTs for open_requests. | 43 | * and process RSTs for open_requests. |
44 | * Andi Kleen : Better prune_queue, and other fixes. | 44 | * Andi Kleen : Better prune_queue, and other fixes. |
45 | * Andrey Savochkin: Fix RTT measurements in the presnce of | 45 | * Andrey Savochkin: Fix RTT measurements in the presence of |
46 | * timestamps. | 46 | * timestamps. |
47 | * Andrey Savochkin: Check sequence numbers correctly when | 47 | * Andrey Savochkin: Check sequence numbers correctly when |
48 | * removing SACKs due to in sequence incoming | 48 | * removing SACKs due to in sequence incoming |
@@ -89,6 +89,7 @@ int sysctl_tcp_frto; | |||
89 | int sysctl_tcp_nometrics_save; | 89 | int sysctl_tcp_nometrics_save; |
90 | 90 | ||
91 | int sysctl_tcp_moderate_rcvbuf = 1; | 91 | int sysctl_tcp_moderate_rcvbuf = 1; |
92 | int sysctl_tcp_abc = 1; | ||
92 | 93 | ||
93 | #define FLAG_DATA 0x01 /* Incoming frame contained data. */ | 94 | #define FLAG_DATA 0x01 /* Incoming frame contained data. */ |
94 | #define FLAG_WIN_UPDATE 0x02 /* Incoming ACK was a window update. */ | 95 | #define FLAG_WIN_UPDATE 0x02 /* Incoming ACK was a window update. */ |
@@ -223,7 +224,7 @@ static void tcp_fixup_sndbuf(struct sock *sk) | |||
223 | * of receiver window. Check #2. | 224 | * of receiver window. Check #2. |
224 | * | 225 | * |
225 | * The scheme does not work when sender sends good segments opening | 226 | * The scheme does not work when sender sends good segments opening |
226 | * window and then starts to feed us spagetti. But it should work | 227 | * window and then starts to feed us spaghetti. But it should work |
227 | * in common situations. Otherwise, we have to rely on queue collapsing. | 228 | * in common situations. Otherwise, we have to rely on queue collapsing. |
228 | */ | 229 | */ |
229 | 230 | ||
@@ -233,7 +234,7 @@ static int __tcp_grow_window(const struct sock *sk, struct tcp_sock *tp, | |||
233 | { | 234 | { |
234 | /* Optimize this! */ | 235 | /* Optimize this! */ |
235 | int truesize = tcp_win_from_space(skb->truesize)/2; | 236 | int truesize = tcp_win_from_space(skb->truesize)/2; |
236 | int window = tcp_full_space(sk)/2; | 237 | int window = tcp_win_from_space(sysctl_tcp_rmem[2])/2; |
237 | 238 | ||
238 | while (tp->rcv_ssthresh <= window) { | 239 | while (tp->rcv_ssthresh <= window) { |
239 | if (truesize <= skb->len) | 240 | if (truesize <= skb->len) |
@@ -277,7 +278,7 @@ static void tcp_fixup_rcvbuf(struct sock *sk) | |||
277 | int rcvmem = tp->advmss + MAX_TCP_HEADER + 16 + sizeof(struct sk_buff); | 278 | int rcvmem = tp->advmss + MAX_TCP_HEADER + 16 + sizeof(struct sk_buff); |
278 | 279 | ||
279 | /* Try to select rcvbuf so that 4 mss-sized segments | 280 | /* Try to select rcvbuf so that 4 mss-sized segments |
280 | * will fit to window and correspoding skbs will fit to our rcvbuf. | 281 | * will fit to window and corresponding skbs will fit to our rcvbuf. |
281 | * (was 3; 4 is minimum to allow fast retransmit to work.) | 282 | * (was 3; 4 is minimum to allow fast retransmit to work.) |
282 | */ | 283 | */ |
283 | while (tcp_win_from_space(rcvmem) < tp->advmss) | 284 | while (tcp_win_from_space(rcvmem) < tp->advmss) |
@@ -286,7 +287,7 @@ static void tcp_fixup_rcvbuf(struct sock *sk) | |||
286 | sk->sk_rcvbuf = min(4 * rcvmem, sysctl_tcp_rmem[2]); | 287 | sk->sk_rcvbuf = min(4 * rcvmem, sysctl_tcp_rmem[2]); |
287 | } | 288 | } |
288 | 289 | ||
289 | /* 4. Try to fixup all. It is made iimediately after connection enters | 290 | /* 4. Try to fixup all. It is made immediately after connection enters |
290 | * established state. | 291 | * established state. |
291 | */ | 292 | */ |
292 | static void tcp_init_buffer_space(struct sock *sk) | 293 | static void tcp_init_buffer_space(struct sock *sk) |
@@ -326,37 +327,18 @@ static void tcp_init_buffer_space(struct sock *sk) | |||
326 | static void tcp_clamp_window(struct sock *sk, struct tcp_sock *tp) | 327 | static void tcp_clamp_window(struct sock *sk, struct tcp_sock *tp) |
327 | { | 328 | { |
328 | struct inet_connection_sock *icsk = inet_csk(sk); | 329 | struct inet_connection_sock *icsk = inet_csk(sk); |
329 | struct sk_buff *skb; | ||
330 | unsigned int app_win = tp->rcv_nxt - tp->copied_seq; | ||
331 | int ofo_win = 0; | ||
332 | 330 | ||
333 | icsk->icsk_ack.quick = 0; | 331 | icsk->icsk_ack.quick = 0; |
334 | 332 | ||
335 | skb_queue_walk(&tp->out_of_order_queue, skb) { | 333 | if (sk->sk_rcvbuf < sysctl_tcp_rmem[2] && |
336 | ofo_win += skb->len; | 334 | !(sk->sk_userlocks & SOCK_RCVBUF_LOCK) && |
337 | } | 335 | !tcp_memory_pressure && |
338 | 336 | atomic_read(&tcp_memory_allocated) < sysctl_tcp_mem[0]) { | |
339 | /* If overcommit is due to out of order segments, | 337 | sk->sk_rcvbuf = min(atomic_read(&sk->sk_rmem_alloc), |
340 | * do not clamp window. Try to expand rcvbuf instead. | 338 | sysctl_tcp_rmem[2]); |
341 | */ | ||
342 | if (ofo_win) { | ||
343 | if (sk->sk_rcvbuf < sysctl_tcp_rmem[2] && | ||
344 | !(sk->sk_userlocks & SOCK_RCVBUF_LOCK) && | ||
345 | !tcp_memory_pressure && | ||
346 | atomic_read(&tcp_memory_allocated) < sysctl_tcp_mem[0]) | ||
347 | sk->sk_rcvbuf = min(atomic_read(&sk->sk_rmem_alloc), | ||
348 | sysctl_tcp_rmem[2]); | ||
349 | } | 339 | } |
350 | if (atomic_read(&sk->sk_rmem_alloc) > sk->sk_rcvbuf) { | 340 | if (atomic_read(&sk->sk_rmem_alloc) > sk->sk_rcvbuf) |
351 | app_win += ofo_win; | ||
352 | if (atomic_read(&sk->sk_rmem_alloc) >= 2 * sk->sk_rcvbuf) | ||
353 | app_win >>= 1; | ||
354 | if (app_win > icsk->icsk_ack.rcv_mss) | ||
355 | app_win -= icsk->icsk_ack.rcv_mss; | ||
356 | app_win = max(app_win, 2U*tp->advmss); | ||
357 | |||
358 | tp->rcv_ssthresh = min(tp->window_clamp, 2U*tp->advmss); | 341 | tp->rcv_ssthresh = min(tp->window_clamp, 2U*tp->advmss); |
359 | } | ||
360 | } | 342 | } |
361 | 343 | ||
362 | /* Receiver "autotuning" code. | 344 | /* Receiver "autotuning" code. |
@@ -385,8 +367,8 @@ static void tcp_rcv_rtt_update(struct tcp_sock *tp, u32 sample, int win_dep) | |||
385 | * are stalled on filesystem I/O. | 367 | * are stalled on filesystem I/O. |
386 | * | 368 | * |
387 | * Also, since we are only going for a minimum in the | 369 | * Also, since we are only going for a minimum in the |
388 | * non-timestamp case, we do not smoothe things out | 370 | * non-timestamp case, we do not smoother things out |
389 | * else with timestamps disabled convergance takes too | 371 | * else with timestamps disabled convergence takes too |
390 | * long. | 372 | * long. |
391 | */ | 373 | */ |
392 | if (!win_dep) { | 374 | if (!win_dep) { |
@@ -395,7 +377,7 @@ static void tcp_rcv_rtt_update(struct tcp_sock *tp, u32 sample, int win_dep) | |||
395 | } else if (m < new_sample) | 377 | } else if (m < new_sample) |
396 | new_sample = m << 3; | 378 | new_sample = m << 3; |
397 | } else { | 379 | } else { |
398 | /* No previous mesaure. */ | 380 | /* No previous measure. */ |
399 | new_sample = m << 3; | 381 | new_sample = m << 3; |
400 | } | 382 | } |
401 | 383 | ||
@@ -524,7 +506,7 @@ static void tcp_event_data_recv(struct sock *sk, struct tcp_sock *tp, struct sk_ | |||
524 | if (icsk->icsk_ack.ato > icsk->icsk_rto) | 506 | if (icsk->icsk_ack.ato > icsk->icsk_rto) |
525 | icsk->icsk_ack.ato = icsk->icsk_rto; | 507 | icsk->icsk_ack.ato = icsk->icsk_rto; |
526 | } else if (m > icsk->icsk_rto) { | 508 | } else if (m > icsk->icsk_rto) { |
527 | /* Too long gap. Apparently sender falled to | 509 | /* Too long gap. Apparently sender failed to |
528 | * restart window, so that we send ACKs quickly. | 510 | * restart window, so that we send ACKs quickly. |
529 | */ | 511 | */ |
530 | tcp_incr_quickack(sk); | 512 | tcp_incr_quickack(sk); |
@@ -548,10 +530,9 @@ static void tcp_event_data_recv(struct sock *sk, struct tcp_sock *tp, struct sk_ | |||
548 | * To save cycles in the RFC 1323 implementation it was better to break | 530 | * To save cycles in the RFC 1323 implementation it was better to break |
549 | * it up into three procedures. -- erics | 531 | * it up into three procedures. -- erics |
550 | */ | 532 | */ |
551 | static void tcp_rtt_estimator(struct sock *sk, const __u32 mrtt, u32 *usrtt) | 533 | static void tcp_rtt_estimator(struct sock *sk, const __u32 mrtt) |
552 | { | 534 | { |
553 | struct tcp_sock *tp = tcp_sk(sk); | 535 | struct tcp_sock *tp = tcp_sk(sk); |
554 | const struct inet_connection_sock *icsk = inet_csk(sk); | ||
555 | long m = mrtt; /* RTT */ | 536 | long m = mrtt; /* RTT */ |
556 | 537 | ||
557 | /* The following amusing code comes from Jacobson's | 538 | /* The following amusing code comes from Jacobson's |
@@ -565,7 +546,7 @@ static void tcp_rtt_estimator(struct sock *sk, const __u32 mrtt, u32 *usrtt) | |||
565 | * | 546 | * |
566 | * Funny. This algorithm seems to be very broken. | 547 | * Funny. This algorithm seems to be very broken. |
567 | * These formulae increase RTO, when it should be decreased, increase | 548 | * These formulae increase RTO, when it should be decreased, increase |
568 | * too slowly, when it should be incresed fastly, decrease too fastly | 549 | * too slowly, when it should be increased fastly, decrease too fastly |
569 | * etc. I guess in BSD RTO takes ONE value, so that it is absolutely | 550 | * etc. I guess in BSD RTO takes ONE value, so that it is absolutely |
570 | * does not matter how to _calculate_ it. Seems, it was trap | 551 | * does not matter how to _calculate_ it. Seems, it was trap |
571 | * that VJ failed to avoid. 8) | 552 | * that VJ failed to avoid. 8) |
@@ -610,9 +591,6 @@ static void tcp_rtt_estimator(struct sock *sk, const __u32 mrtt, u32 *usrtt) | |||
610 | tp->mdev_max = tp->rttvar = max(tp->mdev, TCP_RTO_MIN); | 591 | tp->mdev_max = tp->rttvar = max(tp->mdev, TCP_RTO_MIN); |
611 | tp->rtt_seq = tp->snd_nxt; | 592 | tp->rtt_seq = tp->snd_nxt; |
612 | } | 593 | } |
613 | |||
614 | if (icsk->icsk_ca_ops->rtt_sample) | ||
615 | icsk->icsk_ca_ops->rtt_sample(sk, *usrtt); | ||
616 | } | 594 | } |
617 | 595 | ||
618 | /* Calculate rto without backoff. This is the second half of Van Jacobson's | 596 | /* Calculate rto without backoff. This is the second half of Van Jacobson's |
@@ -629,14 +607,14 @@ static inline void tcp_set_rto(struct sock *sk) | |||
629 | * at least by solaris and freebsd. "Erratic ACKs" has _nothing_ | 607 | * at least by solaris and freebsd. "Erratic ACKs" has _nothing_ |
630 | * to do with delayed acks, because at cwnd>2 true delack timeout | 608 | * to do with delayed acks, because at cwnd>2 true delack timeout |
631 | * is invisible. Actually, Linux-2.4 also generates erratic | 609 | * is invisible. Actually, Linux-2.4 also generates erratic |
632 | * ACKs in some curcumstances. | 610 | * ACKs in some circumstances. |
633 | */ | 611 | */ |
634 | inet_csk(sk)->icsk_rto = (tp->srtt >> 3) + tp->rttvar; | 612 | inet_csk(sk)->icsk_rto = (tp->srtt >> 3) + tp->rttvar; |
635 | 613 | ||
636 | /* 2. Fixups made earlier cannot be right. | 614 | /* 2. Fixups made earlier cannot be right. |
637 | * If we do not estimate RTO correctly without them, | 615 | * If we do not estimate RTO correctly without them, |
638 | * all the algo is pure shit and should be replaced | 616 | * all the algo is pure shit and should be replaced |
639 | * with correct one. It is exaclty, which we pretend to do. | 617 | * with correct one. It is exactly, which we pretend to do. |
640 | */ | 618 | */ |
641 | } | 619 | } |
642 | 620 | ||
@@ -794,7 +772,7 @@ static void tcp_init_metrics(struct sock *sk) | |||
794 | * to make it more realistic. | 772 | * to make it more realistic. |
795 | * | 773 | * |
796 | * A bit of theory. RTT is time passed after "normal" sized packet | 774 | * A bit of theory. RTT is time passed after "normal" sized packet |
797 | * is sent until it is ACKed. In normal curcumstances sending small | 775 | * is sent until it is ACKed. In normal circumstances sending small |
798 | * packets force peer to delay ACKs and calculation is correct too. | 776 | * packets force peer to delay ACKs and calculation is correct too. |
799 | * The algorithm is adaptive and, provided we follow specs, it | 777 | * The algorithm is adaptive and, provided we follow specs, it |
800 | * NEVER underestimate RTT. BUT! If peer tries to make some clever | 778 | * NEVER underestimate RTT. BUT! If peer tries to make some clever |
@@ -919,18 +897,32 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_ | |||
919 | int prior_fackets; | 897 | int prior_fackets; |
920 | u32 lost_retrans = 0; | 898 | u32 lost_retrans = 0; |
921 | int flag = 0; | 899 | int flag = 0; |
900 | int dup_sack = 0; | ||
922 | int i; | 901 | int i; |
923 | 902 | ||
924 | if (!tp->sacked_out) | 903 | if (!tp->sacked_out) |
925 | tp->fackets_out = 0; | 904 | tp->fackets_out = 0; |
926 | prior_fackets = tp->fackets_out; | 905 | prior_fackets = tp->fackets_out; |
927 | 906 | ||
928 | for (i=0; i<num_sacks; i++, sp++) { | 907 | /* SACK fastpath: |
929 | struct sk_buff *skb; | 908 | * if the only SACK change is the increase of the end_seq of |
930 | __u32 start_seq = ntohl(sp->start_seq); | 909 | * the first block then only apply that SACK block |
931 | __u32 end_seq = ntohl(sp->end_seq); | 910 | * and use retrans queue hinting otherwise slowpath */ |
932 | int fack_count = 0; | 911 | flag = 1; |
933 | int dup_sack = 0; | 912 | for (i = 0; i< num_sacks; i++) { |
913 | __u32 start_seq = ntohl(sp[i].start_seq); | ||
914 | __u32 end_seq = ntohl(sp[i].end_seq); | ||
915 | |||
916 | if (i == 0){ | ||
917 | if (tp->recv_sack_cache[i].start_seq != start_seq) | ||
918 | flag = 0; | ||
919 | } else { | ||
920 | if ((tp->recv_sack_cache[i].start_seq != start_seq) || | ||
921 | (tp->recv_sack_cache[i].end_seq != end_seq)) | ||
922 | flag = 0; | ||
923 | } | ||
924 | tp->recv_sack_cache[i].start_seq = start_seq; | ||
925 | tp->recv_sack_cache[i].end_seq = end_seq; | ||
934 | 926 | ||
935 | /* Check for D-SACK. */ | 927 | /* Check for D-SACK. */ |
936 | if (i == 0) { | 928 | if (i == 0) { |
@@ -962,15 +954,58 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_ | |||
962 | if (before(ack, prior_snd_una - tp->max_window)) | 954 | if (before(ack, prior_snd_una - tp->max_window)) |
963 | return 0; | 955 | return 0; |
964 | } | 956 | } |
957 | } | ||
958 | |||
959 | if (flag) | ||
960 | num_sacks = 1; | ||
961 | else { | ||
962 | int j; | ||
963 | tp->fastpath_skb_hint = NULL; | ||
964 | |||
965 | /* order SACK blocks to allow in order walk of the retrans queue */ | ||
966 | for (i = num_sacks-1; i > 0; i--) { | ||
967 | for (j = 0; j < i; j++){ | ||
968 | if (after(ntohl(sp[j].start_seq), | ||
969 | ntohl(sp[j+1].start_seq))){ | ||
970 | sp[j].start_seq = htonl(tp->recv_sack_cache[j+1].start_seq); | ||
971 | sp[j].end_seq = htonl(tp->recv_sack_cache[j+1].end_seq); | ||
972 | sp[j+1].start_seq = htonl(tp->recv_sack_cache[j].start_seq); | ||
973 | sp[j+1].end_seq = htonl(tp->recv_sack_cache[j].end_seq); | ||
974 | } | ||
975 | |||
976 | } | ||
977 | } | ||
978 | } | ||
979 | |||
980 | /* clear flag as used for different purpose in following code */ | ||
981 | flag = 0; | ||
982 | |||
983 | for (i=0; i<num_sacks; i++, sp++) { | ||
984 | struct sk_buff *skb; | ||
985 | __u32 start_seq = ntohl(sp->start_seq); | ||
986 | __u32 end_seq = ntohl(sp->end_seq); | ||
987 | int fack_count; | ||
988 | |||
989 | /* Use SACK fastpath hint if valid */ | ||
990 | if (tp->fastpath_skb_hint) { | ||
991 | skb = tp->fastpath_skb_hint; | ||
992 | fack_count = tp->fastpath_cnt_hint; | ||
993 | } else { | ||
994 | skb = sk->sk_write_queue.next; | ||
995 | fack_count = 0; | ||
996 | } | ||
965 | 997 | ||
966 | /* Event "B" in the comment above. */ | 998 | /* Event "B" in the comment above. */ |
967 | if (after(end_seq, tp->high_seq)) | 999 | if (after(end_seq, tp->high_seq)) |
968 | flag |= FLAG_DATA_LOST; | 1000 | flag |= FLAG_DATA_LOST; |
969 | 1001 | ||
970 | sk_stream_for_retrans_queue(skb, sk) { | 1002 | sk_stream_for_retrans_queue_from(skb, sk) { |
971 | int in_sack, pcount; | 1003 | int in_sack, pcount; |
972 | u8 sacked; | 1004 | u8 sacked; |
973 | 1005 | ||
1006 | tp->fastpath_skb_hint = skb; | ||
1007 | tp->fastpath_cnt_hint = fack_count; | ||
1008 | |||
974 | /* The retransmission queue is always in order, so | 1009 | /* The retransmission queue is always in order, so |
975 | * we can short-circuit the walk early. | 1010 | * we can short-circuit the walk early. |
976 | */ | 1011 | */ |
@@ -1045,6 +1080,9 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_ | |||
1045 | TCP_SKB_CB(skb)->sacked &= ~(TCPCB_LOST|TCPCB_SACKED_RETRANS); | 1080 | TCP_SKB_CB(skb)->sacked &= ~(TCPCB_LOST|TCPCB_SACKED_RETRANS); |
1046 | tp->lost_out -= tcp_skb_pcount(skb); | 1081 | tp->lost_out -= tcp_skb_pcount(skb); |
1047 | tp->retrans_out -= tcp_skb_pcount(skb); | 1082 | tp->retrans_out -= tcp_skb_pcount(skb); |
1083 | |||
1084 | /* clear lost hint */ | ||
1085 | tp->retransmit_skb_hint = NULL; | ||
1048 | } | 1086 | } |
1049 | } else { | 1087 | } else { |
1050 | /* New sack for not retransmitted frame, | 1088 | /* New sack for not retransmitted frame, |
@@ -1057,6 +1095,9 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_ | |||
1057 | if (sacked & TCPCB_LOST) { | 1095 | if (sacked & TCPCB_LOST) { |
1058 | TCP_SKB_CB(skb)->sacked &= ~TCPCB_LOST; | 1096 | TCP_SKB_CB(skb)->sacked &= ~TCPCB_LOST; |
1059 | tp->lost_out -= tcp_skb_pcount(skb); | 1097 | tp->lost_out -= tcp_skb_pcount(skb); |
1098 | |||
1099 | /* clear lost hint */ | ||
1100 | tp->retransmit_skb_hint = NULL; | ||
1060 | } | 1101 | } |
1061 | } | 1102 | } |
1062 | 1103 | ||
@@ -1080,6 +1121,7 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_ | |||
1080 | (TCP_SKB_CB(skb)->sacked&TCPCB_SACKED_RETRANS)) { | 1121 | (TCP_SKB_CB(skb)->sacked&TCPCB_SACKED_RETRANS)) { |
1081 | TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_RETRANS; | 1122 | TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_RETRANS; |
1082 | tp->retrans_out -= tcp_skb_pcount(skb); | 1123 | tp->retrans_out -= tcp_skb_pcount(skb); |
1124 | tp->retransmit_skb_hint = NULL; | ||
1083 | } | 1125 | } |
1084 | } | 1126 | } |
1085 | } | 1127 | } |
@@ -1107,6 +1149,9 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_ | |||
1107 | TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_RETRANS; | 1149 | TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_RETRANS; |
1108 | tp->retrans_out -= tcp_skb_pcount(skb); | 1150 | tp->retrans_out -= tcp_skb_pcount(skb); |
1109 | 1151 | ||
1152 | /* clear lost hint */ | ||
1153 | tp->retransmit_skb_hint = NULL; | ||
1154 | |||
1110 | if (!(TCP_SKB_CB(skb)->sacked&(TCPCB_LOST|TCPCB_SACKED_ACKED))) { | 1155 | if (!(TCP_SKB_CB(skb)->sacked&(TCPCB_LOST|TCPCB_SACKED_ACKED))) { |
1111 | tp->lost_out += tcp_skb_pcount(skb); | 1156 | tp->lost_out += tcp_skb_pcount(skb); |
1112 | TCP_SKB_CB(skb)->sacked |= TCPCB_LOST; | 1157 | TCP_SKB_CB(skb)->sacked |= TCPCB_LOST; |
@@ -1214,6 +1259,8 @@ static void tcp_enter_frto_loss(struct sock *sk) | |||
1214 | tcp_set_ca_state(sk, TCP_CA_Loss); | 1259 | tcp_set_ca_state(sk, TCP_CA_Loss); |
1215 | tp->high_seq = tp->frto_highmark; | 1260 | tp->high_seq = tp->frto_highmark; |
1216 | TCP_ECN_queue_cwr(tp); | 1261 | TCP_ECN_queue_cwr(tp); |
1262 | |||
1263 | clear_all_retrans_hints(tp); | ||
1217 | } | 1264 | } |
1218 | 1265 | ||
1219 | void tcp_clear_retrans(struct tcp_sock *tp) | 1266 | void tcp_clear_retrans(struct tcp_sock *tp) |
@@ -1251,6 +1298,7 @@ void tcp_enter_loss(struct sock *sk, int how) | |||
1251 | tp->snd_cwnd_cnt = 0; | 1298 | tp->snd_cwnd_cnt = 0; |
1252 | tp->snd_cwnd_stamp = tcp_time_stamp; | 1299 | tp->snd_cwnd_stamp = tcp_time_stamp; |
1253 | 1300 | ||
1301 | tp->bytes_acked = 0; | ||
1254 | tcp_clear_retrans(tp); | 1302 | tcp_clear_retrans(tp); |
1255 | 1303 | ||
1256 | /* Push undo marker, if it was plain RTO and nothing | 1304 | /* Push undo marker, if it was plain RTO and nothing |
@@ -1279,6 +1327,8 @@ void tcp_enter_loss(struct sock *sk, int how) | |||
1279 | tcp_set_ca_state(sk, TCP_CA_Loss); | 1327 | tcp_set_ca_state(sk, TCP_CA_Loss); |
1280 | tp->high_seq = tp->snd_nxt; | 1328 | tp->high_seq = tp->snd_nxt; |
1281 | TCP_ECN_queue_cwr(tp); | 1329 | TCP_ECN_queue_cwr(tp); |
1330 | |||
1331 | clear_all_retrans_hints(tp); | ||
1282 | } | 1332 | } |
1283 | 1333 | ||
1284 | static int tcp_check_sack_reneging(struct sock *sk) | 1334 | static int tcp_check_sack_reneging(struct sock *sk) |
@@ -1503,17 +1553,37 @@ static void tcp_mark_head_lost(struct sock *sk, struct tcp_sock *tp, | |||
1503 | int packets, u32 high_seq) | 1553 | int packets, u32 high_seq) |
1504 | { | 1554 | { |
1505 | struct sk_buff *skb; | 1555 | struct sk_buff *skb; |
1506 | int cnt = packets; | 1556 | int cnt; |
1507 | 1557 | ||
1508 | BUG_TRAP(cnt <= tp->packets_out); | 1558 | BUG_TRAP(packets <= tp->packets_out); |
1559 | if (tp->lost_skb_hint) { | ||
1560 | skb = tp->lost_skb_hint; | ||
1561 | cnt = tp->lost_cnt_hint; | ||
1562 | } else { | ||
1563 | skb = sk->sk_write_queue.next; | ||
1564 | cnt = 0; | ||
1565 | } | ||
1509 | 1566 | ||
1510 | sk_stream_for_retrans_queue(skb, sk) { | 1567 | sk_stream_for_retrans_queue_from(skb, sk) { |
1511 | cnt -= tcp_skb_pcount(skb); | 1568 | /* TODO: do this better */ |
1512 | if (cnt < 0 || after(TCP_SKB_CB(skb)->end_seq, high_seq)) | 1569 | /* this is not the most efficient way to do this... */ |
1570 | tp->lost_skb_hint = skb; | ||
1571 | tp->lost_cnt_hint = cnt; | ||
1572 | cnt += tcp_skb_pcount(skb); | ||
1573 | if (cnt > packets || after(TCP_SKB_CB(skb)->end_seq, high_seq)) | ||
1513 | break; | 1574 | break; |
1514 | if (!(TCP_SKB_CB(skb)->sacked&TCPCB_TAGBITS)) { | 1575 | if (!(TCP_SKB_CB(skb)->sacked&TCPCB_TAGBITS)) { |
1515 | TCP_SKB_CB(skb)->sacked |= TCPCB_LOST; | 1576 | TCP_SKB_CB(skb)->sacked |= TCPCB_LOST; |
1516 | tp->lost_out += tcp_skb_pcount(skb); | 1577 | tp->lost_out += tcp_skb_pcount(skb); |
1578 | |||
1579 | /* clear xmit_retransmit_queue hints | ||
1580 | * if this is beyond hint */ | ||
1581 | if(tp->retransmit_skb_hint != NULL && | ||
1582 | before(TCP_SKB_CB(skb)->seq, | ||
1583 | TCP_SKB_CB(tp->retransmit_skb_hint)->seq)) { | ||
1584 | |||
1585 | tp->retransmit_skb_hint = NULL; | ||
1586 | } | ||
1517 | } | 1587 | } |
1518 | } | 1588 | } |
1519 | tcp_sync_left_out(tp); | 1589 | tcp_sync_left_out(tp); |
@@ -1540,13 +1610,28 @@ static void tcp_update_scoreboard(struct sock *sk, struct tcp_sock *tp) | |||
1540 | if (tcp_head_timedout(sk, tp)) { | 1610 | if (tcp_head_timedout(sk, tp)) { |
1541 | struct sk_buff *skb; | 1611 | struct sk_buff *skb; |
1542 | 1612 | ||
1543 | sk_stream_for_retrans_queue(skb, sk) { | 1613 | skb = tp->scoreboard_skb_hint ? tp->scoreboard_skb_hint |
1544 | if (tcp_skb_timedout(sk, skb) && | 1614 | : sk->sk_write_queue.next; |
1545 | !(TCP_SKB_CB(skb)->sacked&TCPCB_TAGBITS)) { | 1615 | |
1616 | sk_stream_for_retrans_queue_from(skb, sk) { | ||
1617 | if (!tcp_skb_timedout(sk, skb)) | ||
1618 | break; | ||
1619 | |||
1620 | if (!(TCP_SKB_CB(skb)->sacked&TCPCB_TAGBITS)) { | ||
1546 | TCP_SKB_CB(skb)->sacked |= TCPCB_LOST; | 1621 | TCP_SKB_CB(skb)->sacked |= TCPCB_LOST; |
1547 | tp->lost_out += tcp_skb_pcount(skb); | 1622 | tp->lost_out += tcp_skb_pcount(skb); |
1623 | |||
1624 | /* clear xmit_retrans hint */ | ||
1625 | if (tp->retransmit_skb_hint && | ||
1626 | before(TCP_SKB_CB(skb)->seq, | ||
1627 | TCP_SKB_CB(tp->retransmit_skb_hint)->seq)) | ||
1628 | |||
1629 | tp->retransmit_skb_hint = NULL; | ||
1548 | } | 1630 | } |
1549 | } | 1631 | } |
1632 | |||
1633 | tp->scoreboard_skb_hint = skb; | ||
1634 | |||
1550 | tcp_sync_left_out(tp); | 1635 | tcp_sync_left_out(tp); |
1551 | } | 1636 | } |
1552 | } | 1637 | } |
@@ -1626,6 +1711,10 @@ static void tcp_undo_cwr(struct sock *sk, const int undo) | |||
1626 | } | 1711 | } |
1627 | tcp_moderate_cwnd(tp); | 1712 | tcp_moderate_cwnd(tp); |
1628 | tp->snd_cwnd_stamp = tcp_time_stamp; | 1713 | tp->snd_cwnd_stamp = tcp_time_stamp; |
1714 | |||
1715 | /* There is something screwy going on with the retrans hints after | ||
1716 | an undo */ | ||
1717 | clear_all_retrans_hints(tp); | ||
1629 | } | 1718 | } |
1630 | 1719 | ||
1631 | static inline int tcp_may_undo(struct tcp_sock *tp) | 1720 | static inline int tcp_may_undo(struct tcp_sock *tp) |
@@ -1709,6 +1798,9 @@ static int tcp_try_undo_loss(struct sock *sk, struct tcp_sock *tp) | |||
1709 | sk_stream_for_retrans_queue(skb, sk) { | 1798 | sk_stream_for_retrans_queue(skb, sk) { |
1710 | TCP_SKB_CB(skb)->sacked &= ~TCPCB_LOST; | 1799 | TCP_SKB_CB(skb)->sacked &= ~TCPCB_LOST; |
1711 | } | 1800 | } |
1801 | |||
1802 | clear_all_retrans_hints(tp); | ||
1803 | |||
1712 | DBGUNDO(sk, tp, "partial loss"); | 1804 | DBGUNDO(sk, tp, "partial loss"); |
1713 | tp->lost_out = 0; | 1805 | tp->lost_out = 0; |
1714 | tp->left_out = tp->sacked_out; | 1806 | tp->left_out = tp->sacked_out; |
@@ -1908,6 +2000,7 @@ tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una, | |||
1908 | TCP_ECN_queue_cwr(tp); | 2000 | TCP_ECN_queue_cwr(tp); |
1909 | } | 2001 | } |
1910 | 2002 | ||
2003 | tp->bytes_acked = 0; | ||
1911 | tp->snd_cwnd_cnt = 0; | 2004 | tp->snd_cwnd_cnt = 0; |
1912 | tcp_set_ca_state(sk, TCP_CA_Recovery); | 2005 | tcp_set_ca_state(sk, TCP_CA_Recovery); |
1913 | } | 2006 | } |
@@ -1919,9 +2012,9 @@ tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una, | |||
1919 | } | 2012 | } |
1920 | 2013 | ||
1921 | /* Read draft-ietf-tcplw-high-performance before mucking | 2014 | /* Read draft-ietf-tcplw-high-performance before mucking |
1922 | * with this code. (Superceeds RFC1323) | 2015 | * with this code. (Supersedes RFC1323) |
1923 | */ | 2016 | */ |
1924 | static void tcp_ack_saw_tstamp(struct sock *sk, u32 *usrtt, int flag) | 2017 | static void tcp_ack_saw_tstamp(struct sock *sk, int flag) |
1925 | { | 2018 | { |
1926 | /* RTTM Rule: A TSecr value received in a segment is used to | 2019 | /* RTTM Rule: A TSecr value received in a segment is used to |
1927 | * update the averaged RTT measurement only if the segment | 2020 | * update the averaged RTT measurement only if the segment |
@@ -1932,7 +2025,7 @@ static void tcp_ack_saw_tstamp(struct sock *sk, u32 *usrtt, int flag) | |||
1932 | * 1998/04/10 Andrey V. Savochkin <saw@msu.ru> | 2025 | * 1998/04/10 Andrey V. Savochkin <saw@msu.ru> |
1933 | * | 2026 | * |
1934 | * Changed: reset backoff as soon as we see the first valid sample. | 2027 | * Changed: reset backoff as soon as we see the first valid sample. |
1935 | * If we do not, we get strongly overstimated rto. With timestamps | 2028 | * If we do not, we get strongly overestimated rto. With timestamps |
1936 | * samples are accepted even from very old segments: f.e., when rtt=1 | 2029 | * samples are accepted even from very old segments: f.e., when rtt=1 |
1937 | * increases to 8, we retransmit 5 times and after 8 seconds delayed | 2030 | * increases to 8, we retransmit 5 times and after 8 seconds delayed |
1938 | * answer arrives rto becomes 120 seconds! If at least one of segments | 2031 | * answer arrives rto becomes 120 seconds! If at least one of segments |
@@ -1940,13 +2033,13 @@ static void tcp_ack_saw_tstamp(struct sock *sk, u32 *usrtt, int flag) | |||
1940 | */ | 2033 | */ |
1941 | struct tcp_sock *tp = tcp_sk(sk); | 2034 | struct tcp_sock *tp = tcp_sk(sk); |
1942 | const __u32 seq_rtt = tcp_time_stamp - tp->rx_opt.rcv_tsecr; | 2035 | const __u32 seq_rtt = tcp_time_stamp - tp->rx_opt.rcv_tsecr; |
1943 | tcp_rtt_estimator(sk, seq_rtt, usrtt); | 2036 | tcp_rtt_estimator(sk, seq_rtt); |
1944 | tcp_set_rto(sk); | 2037 | tcp_set_rto(sk); |
1945 | inet_csk(sk)->icsk_backoff = 0; | 2038 | inet_csk(sk)->icsk_backoff = 0; |
1946 | tcp_bound_rto(sk); | 2039 | tcp_bound_rto(sk); |
1947 | } | 2040 | } |
1948 | 2041 | ||
1949 | static void tcp_ack_no_tstamp(struct sock *sk, u32 seq_rtt, u32 *usrtt, int flag) | 2042 | static void tcp_ack_no_tstamp(struct sock *sk, u32 seq_rtt, int flag) |
1950 | { | 2043 | { |
1951 | /* We don't have a timestamp. Can only use | 2044 | /* We don't have a timestamp. Can only use |
1952 | * packets that are not retransmitted to determine | 2045 | * packets that are not retransmitted to determine |
@@ -1960,21 +2053,21 @@ static void tcp_ack_no_tstamp(struct sock *sk, u32 seq_rtt, u32 *usrtt, int flag | |||
1960 | if (flag & FLAG_RETRANS_DATA_ACKED) | 2053 | if (flag & FLAG_RETRANS_DATA_ACKED) |
1961 | return; | 2054 | return; |
1962 | 2055 | ||
1963 | tcp_rtt_estimator(sk, seq_rtt, usrtt); | 2056 | tcp_rtt_estimator(sk, seq_rtt); |
1964 | tcp_set_rto(sk); | 2057 | tcp_set_rto(sk); |
1965 | inet_csk(sk)->icsk_backoff = 0; | 2058 | inet_csk(sk)->icsk_backoff = 0; |
1966 | tcp_bound_rto(sk); | 2059 | tcp_bound_rto(sk); |
1967 | } | 2060 | } |
1968 | 2061 | ||
1969 | static inline void tcp_ack_update_rtt(struct sock *sk, const int flag, | 2062 | static inline void tcp_ack_update_rtt(struct sock *sk, const int flag, |
1970 | const s32 seq_rtt, u32 *usrtt) | 2063 | const s32 seq_rtt) |
1971 | { | 2064 | { |
1972 | const struct tcp_sock *tp = tcp_sk(sk); | 2065 | const struct tcp_sock *tp = tcp_sk(sk); |
1973 | /* Note that peer MAY send zero echo. In this case it is ignored. (rfc1323) */ | 2066 | /* Note that peer MAY send zero echo. In this case it is ignored. (rfc1323) */ |
1974 | if (tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr) | 2067 | if (tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr) |
1975 | tcp_ack_saw_tstamp(sk, usrtt, flag); | 2068 | tcp_ack_saw_tstamp(sk, flag); |
1976 | else if (seq_rtt >= 0) | 2069 | else if (seq_rtt >= 0) |
1977 | tcp_ack_no_tstamp(sk, seq_rtt, usrtt, flag); | 2070 | tcp_ack_no_tstamp(sk, seq_rtt, flag); |
1978 | } | 2071 | } |
1979 | 2072 | ||
1980 | static inline void tcp_cong_avoid(struct sock *sk, u32 ack, u32 rtt, | 2073 | static inline void tcp_cong_avoid(struct sock *sk, u32 ack, u32 rtt, |
@@ -2054,20 +2147,27 @@ static int tcp_tso_acked(struct sock *sk, struct sk_buff *skb, | |||
2054 | return acked; | 2147 | return acked; |
2055 | } | 2148 | } |
2056 | 2149 | ||
2150 | static inline u32 tcp_usrtt(const struct sk_buff *skb) | ||
2151 | { | ||
2152 | struct timeval tv, now; | ||
2153 | |||
2154 | do_gettimeofday(&now); | ||
2155 | skb_get_timestamp(skb, &tv); | ||
2156 | return (now.tv_sec - tv.tv_sec) * 1000000 + (now.tv_usec - tv.tv_usec); | ||
2157 | } | ||
2057 | 2158 | ||
2058 | /* Remove acknowledged frames from the retransmission queue. */ | 2159 | /* Remove acknowledged frames from the retransmission queue. */ |
2059 | static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p, s32 *seq_usrtt) | 2160 | static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p) |
2060 | { | 2161 | { |
2061 | struct tcp_sock *tp = tcp_sk(sk); | 2162 | struct tcp_sock *tp = tcp_sk(sk); |
2163 | const struct inet_connection_sock *icsk = inet_csk(sk); | ||
2062 | struct sk_buff *skb; | 2164 | struct sk_buff *skb; |
2063 | __u32 now = tcp_time_stamp; | 2165 | __u32 now = tcp_time_stamp; |
2064 | int acked = 0; | 2166 | int acked = 0; |
2065 | __s32 seq_rtt = -1; | 2167 | __s32 seq_rtt = -1; |
2066 | struct timeval usnow; | ||
2067 | u32 pkts_acked = 0; | 2168 | u32 pkts_acked = 0; |
2068 | 2169 | void (*rtt_sample)(struct sock *sk, u32 usrtt) | |
2069 | if (seq_usrtt) | 2170 | = icsk->icsk_ca_ops->rtt_sample; |
2070 | do_gettimeofday(&usnow); | ||
2071 | 2171 | ||
2072 | while ((skb = skb_peek(&sk->sk_write_queue)) && | 2172 | while ((skb = skb_peek(&sk->sk_write_queue)) && |
2073 | skb != sk->sk_send_head) { | 2173 | skb != sk->sk_send_head) { |
@@ -2107,16 +2207,11 @@ static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p, s32 *seq_usrtt | |||
2107 | tp->retrans_out -= tcp_skb_pcount(skb); | 2207 | tp->retrans_out -= tcp_skb_pcount(skb); |
2108 | acked |= FLAG_RETRANS_DATA_ACKED; | 2208 | acked |= FLAG_RETRANS_DATA_ACKED; |
2109 | seq_rtt = -1; | 2209 | seq_rtt = -1; |
2110 | } else if (seq_rtt < 0) | 2210 | } else if (seq_rtt < 0) { |
2111 | seq_rtt = now - scb->when; | 2211 | seq_rtt = now - scb->when; |
2112 | if (seq_usrtt) { | 2212 | if (rtt_sample) |
2113 | struct timeval tv; | 2213 | (*rtt_sample)(sk, tcp_usrtt(skb)); |
2114 | |||
2115 | skb_get_timestamp(skb, &tv); | ||
2116 | *seq_usrtt = (usnow.tv_sec - tv.tv_sec) * 1000000 | ||
2117 | + (usnow.tv_usec - tv.tv_usec); | ||
2118 | } | 2214 | } |
2119 | |||
2120 | if (sacked & TCPCB_SACKED_ACKED) | 2215 | if (sacked & TCPCB_SACKED_ACKED) |
2121 | tp->sacked_out -= tcp_skb_pcount(skb); | 2216 | tp->sacked_out -= tcp_skb_pcount(skb); |
2122 | if (sacked & TCPCB_LOST) | 2217 | if (sacked & TCPCB_LOST) |
@@ -2126,17 +2221,20 @@ static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p, s32 *seq_usrtt | |||
2126 | !before(scb->end_seq, tp->snd_up)) | 2221 | !before(scb->end_seq, tp->snd_up)) |
2127 | tp->urg_mode = 0; | 2222 | tp->urg_mode = 0; |
2128 | } | 2223 | } |
2129 | } else if (seq_rtt < 0) | 2224 | } else if (seq_rtt < 0) { |
2130 | seq_rtt = now - scb->when; | 2225 | seq_rtt = now - scb->when; |
2226 | if (rtt_sample) | ||
2227 | (*rtt_sample)(sk, tcp_usrtt(skb)); | ||
2228 | } | ||
2131 | tcp_dec_pcount_approx(&tp->fackets_out, skb); | 2229 | tcp_dec_pcount_approx(&tp->fackets_out, skb); |
2132 | tcp_packets_out_dec(tp, skb); | 2230 | tcp_packets_out_dec(tp, skb); |
2133 | __skb_unlink(skb, &sk->sk_write_queue); | 2231 | __skb_unlink(skb, &sk->sk_write_queue); |
2134 | sk_stream_free_skb(sk, skb); | 2232 | sk_stream_free_skb(sk, skb); |
2233 | clear_all_retrans_hints(tp); | ||
2135 | } | 2234 | } |
2136 | 2235 | ||
2137 | if (acked&FLAG_ACKED) { | 2236 | if (acked&FLAG_ACKED) { |
2138 | const struct inet_connection_sock *icsk = inet_csk(sk); | 2237 | tcp_ack_update_rtt(sk, acked, seq_rtt); |
2139 | tcp_ack_update_rtt(sk, acked, seq_rtt, seq_usrtt); | ||
2140 | tcp_ack_packets_out(sk, tp); | 2238 | tcp_ack_packets_out(sk, tp); |
2141 | 2239 | ||
2142 | if (icsk->icsk_ca_ops->pkts_acked) | 2240 | if (icsk->icsk_ca_ops->pkts_acked) |
@@ -2284,7 +2382,7 @@ static void tcp_process_frto(struct sock *sk, u32 prior_snd_una) | |||
2284 | } | 2382 | } |
2285 | 2383 | ||
2286 | /* F-RTO affects on two new ACKs following RTO. | 2384 | /* F-RTO affects on two new ACKs following RTO. |
2287 | * At latest on third ACK the TCP behavor is back to normal. | 2385 | * At latest on third ACK the TCP behavior is back to normal. |
2288 | */ | 2386 | */ |
2289 | tp->frto_counter = (tp->frto_counter + 1) % 3; | 2387 | tp->frto_counter = (tp->frto_counter + 1) % 3; |
2290 | } | 2388 | } |
@@ -2299,7 +2397,6 @@ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag) | |||
2299 | u32 ack = TCP_SKB_CB(skb)->ack_seq; | 2397 | u32 ack = TCP_SKB_CB(skb)->ack_seq; |
2300 | u32 prior_in_flight; | 2398 | u32 prior_in_flight; |
2301 | s32 seq_rtt; | 2399 | s32 seq_rtt; |
2302 | s32 seq_usrtt = 0; | ||
2303 | int prior_packets; | 2400 | int prior_packets; |
2304 | 2401 | ||
2305 | /* If the ack is newer than sent or older than previous acks | 2402 | /* If the ack is newer than sent or older than previous acks |
@@ -2311,6 +2408,9 @@ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag) | |||
2311 | if (before(ack, prior_snd_una)) | 2408 | if (before(ack, prior_snd_una)) |
2312 | goto old_ack; | 2409 | goto old_ack; |
2313 | 2410 | ||
2411 | if (sysctl_tcp_abc && icsk->icsk_ca_state < TCP_CA_CWR) | ||
2412 | tp->bytes_acked += ack - prior_snd_una; | ||
2413 | |||
2314 | if (!(flag&FLAG_SLOWPATH) && after(ack, prior_snd_una)) { | 2414 | if (!(flag&FLAG_SLOWPATH) && after(ack, prior_snd_una)) { |
2315 | /* Window is constant, pure forward advance. | 2415 | /* Window is constant, pure forward advance. |
2316 | * No more checks are required. | 2416 | * No more checks are required. |
@@ -2352,14 +2452,13 @@ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag) | |||
2352 | prior_in_flight = tcp_packets_in_flight(tp); | 2452 | prior_in_flight = tcp_packets_in_flight(tp); |
2353 | 2453 | ||
2354 | /* See if we can take anything off of the retransmit queue. */ | 2454 | /* See if we can take anything off of the retransmit queue. */ |
2355 | flag |= tcp_clean_rtx_queue(sk, &seq_rtt, | 2455 | flag |= tcp_clean_rtx_queue(sk, &seq_rtt); |
2356 | icsk->icsk_ca_ops->rtt_sample ? &seq_usrtt : NULL); | ||
2357 | 2456 | ||
2358 | if (tp->frto_counter) | 2457 | if (tp->frto_counter) |
2359 | tcp_process_frto(sk, prior_snd_una); | 2458 | tcp_process_frto(sk, prior_snd_una); |
2360 | 2459 | ||
2361 | if (tcp_ack_is_dubious(sk, flag)) { | 2460 | if (tcp_ack_is_dubious(sk, flag)) { |
2362 | /* Advanve CWND, if state allows this. */ | 2461 | /* Advance CWND, if state allows this. */ |
2363 | if ((flag & FLAG_DATA_ACKED) && tcp_may_raise_cwnd(sk, flag)) | 2462 | if ((flag & FLAG_DATA_ACKED) && tcp_may_raise_cwnd(sk, flag)) |
2364 | tcp_cong_avoid(sk, ack, seq_rtt, prior_in_flight, 0); | 2463 | tcp_cong_avoid(sk, ack, seq_rtt, prior_in_flight, 0); |
2365 | tcp_fastretrans_alert(sk, prior_snd_una, prior_packets, flag); | 2464 | tcp_fastretrans_alert(sk, prior_snd_una, prior_packets, flag); |
@@ -3148,7 +3247,7 @@ tcp_collapse(struct sock *sk, struct sk_buff_head *list, | |||
3148 | { | 3247 | { |
3149 | struct sk_buff *skb; | 3248 | struct sk_buff *skb; |
3150 | 3249 | ||
3151 | /* First, check that queue is collapsable and find | 3250 | /* First, check that queue is collapsible and find |
3152 | * the point where collapsing can be useful. */ | 3251 | * the point where collapsing can be useful. */ |
3153 | for (skb = head; skb != tail; ) { | 3252 | for (skb = head; skb != tail; ) { |
3154 | /* No new bits? It is possible on ofo queue. */ | 3253 | /* No new bits? It is possible on ofo queue. */ |
@@ -3456,7 +3555,7 @@ static __inline__ void tcp_ack_snd_check(struct sock *sk) | |||
3456 | 3555 | ||
3457 | /* | 3556 | /* |
3458 | * This routine is only called when we have urgent data | 3557 | * This routine is only called when we have urgent data |
3459 | * signalled. Its the 'slow' part of tcp_urg. It could be | 3558 | * signaled. Its the 'slow' part of tcp_urg. It could be |
3460 | * moved inline now as tcp_urg is only called from one | 3559 | * moved inline now as tcp_urg is only called from one |
3461 | * place. We handle URGent data wrong. We have to - as | 3560 | * place. We handle URGent data wrong. We have to - as |
3462 | * BSD still doesn't use the correction from RFC961. | 3561 | * BSD still doesn't use the correction from RFC961. |
@@ -3501,7 +3600,7 @@ static void tcp_check_urg(struct sock * sk, struct tcphdr * th) | |||
3501 | * urgent. To do this requires some care. We cannot just ignore | 3600 | * urgent. To do this requires some care. We cannot just ignore |
3502 | * tp->copied_seq since we would read the last urgent byte again | 3601 | * tp->copied_seq since we would read the last urgent byte again |
3503 | * as data, nor can we alter copied_seq until this data arrives | 3602 | * as data, nor can we alter copied_seq until this data arrives |
3504 | * or we break the sematics of SIOCATMARK (and thus sockatmark()) | 3603 | * or we break the semantics of SIOCATMARK (and thus sockatmark()) |
3505 | * | 3604 | * |
3506 | * NOTE. Double Dutch. Rendering to plain English: author of comment | 3605 | * NOTE. Double Dutch. Rendering to plain English: author of comment |
3507 | * above did something sort of send("A", MSG_OOB); send("B", MSG_OOB); | 3606 | * above did something sort of send("A", MSG_OOB); send("B", MSG_OOB); |
@@ -3646,7 +3745,7 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb, | |||
3646 | tp->rx_opt.saw_tstamp = 0; | 3745 | tp->rx_opt.saw_tstamp = 0; |
3647 | 3746 | ||
3648 | /* pred_flags is 0xS?10 << 16 + snd_wnd | 3747 | /* pred_flags is 0xS?10 << 16 + snd_wnd |
3649 | * if header_predition is to be made | 3748 | * if header_prediction is to be made |
3650 | * 'S' will always be tp->tcp_header_len >> 2 | 3749 | * 'S' will always be tp->tcp_header_len >> 2 |
3651 | * '?' will be 0 for the fast path, otherwise pred_flags is 0 to | 3750 | * '?' will be 0 for the fast path, otherwise pred_flags is 0 to |
3652 | * turn it off (when there are holes in the receive | 3751 | * turn it off (when there are holes in the receive |
@@ -4242,7 +4341,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, | |||
4242 | */ | 4341 | */ |
4243 | if (tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr && | 4342 | if (tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr && |
4244 | !tp->srtt) | 4343 | !tp->srtt) |
4245 | tcp_ack_saw_tstamp(sk, NULL, 0); | 4344 | tcp_ack_saw_tstamp(sk, 0); |
4246 | 4345 | ||
4247 | if (tp->rx_opt.tstamp_ok) | 4346 | if (tp->rx_opt.tstamp_ok) |
4248 | tp->advmss -= TCPOLEN_TSTAMP_ALIGNED; | 4347 | tp->advmss -= TCPOLEN_TSTAMP_ALIGNED; |
@@ -4372,6 +4471,7 @@ discard: | |||
4372 | 4471 | ||
4373 | EXPORT_SYMBOL(sysctl_tcp_ecn); | 4472 | EXPORT_SYMBOL(sysctl_tcp_ecn); |
4374 | EXPORT_SYMBOL(sysctl_tcp_reordering); | 4473 | EXPORT_SYMBOL(sysctl_tcp_reordering); |
4474 | EXPORT_SYMBOL(sysctl_tcp_abc); | ||
4375 | EXPORT_SYMBOL(tcp_parse_options); | 4475 | EXPORT_SYMBOL(tcp_parse_options); |
4376 | EXPORT_SYMBOL(tcp_rcv_established); | 4476 | EXPORT_SYMBOL(tcp_rcv_established); |
4377 | EXPORT_SYMBOL(tcp_rcv_state_process); | 4477 | EXPORT_SYMBOL(tcp_rcv_state_process); |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 634dabb558fd..4d5021e1929b 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -39,7 +39,7 @@ | |||
39 | * request_sock handling and moved | 39 | * request_sock handling and moved |
40 | * most of it into the af independent code. | 40 | * most of it into the af independent code. |
41 | * Added tail drop and some other bugfixes. | 41 | * Added tail drop and some other bugfixes. |
42 | * Added new listen sematics. | 42 | * Added new listen semantics. |
43 | * Mike McLagan : Routing by source | 43 | * Mike McLagan : Routing by source |
44 | * Juan Jose Ciarlante: ip_dynaddr bits | 44 | * Juan Jose Ciarlante: ip_dynaddr bits |
45 | * Andi Kleen: various fixes. | 45 | * Andi Kleen: various fixes. |
@@ -1110,24 +1110,18 @@ static struct sock *tcp_v4_hnd_req(struct sock *sk, struct sk_buff *skb) | |||
1110 | static int tcp_v4_checksum_init(struct sk_buff *skb) | 1110 | static int tcp_v4_checksum_init(struct sk_buff *skb) |
1111 | { | 1111 | { |
1112 | if (skb->ip_summed == CHECKSUM_HW) { | 1112 | if (skb->ip_summed == CHECKSUM_HW) { |
1113 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
1114 | if (!tcp_v4_check(skb->h.th, skb->len, skb->nh.iph->saddr, | 1113 | if (!tcp_v4_check(skb->h.th, skb->len, skb->nh.iph->saddr, |
1115 | skb->nh.iph->daddr, skb->csum)) | 1114 | skb->nh.iph->daddr, skb->csum)) { |
1115 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
1116 | return 0; | 1116 | return 0; |
1117 | 1117 | } | |
1118 | LIMIT_NETDEBUG(KERN_DEBUG "hw tcp v4 csum failed\n"); | ||
1119 | skb->ip_summed = CHECKSUM_NONE; | ||
1120 | } | 1118 | } |
1119 | |||
1120 | skb->csum = csum_tcpudp_nofold(skb->nh.iph->saddr, skb->nh.iph->daddr, | ||
1121 | skb->len, IPPROTO_TCP, 0); | ||
1122 | |||
1121 | if (skb->len <= 76) { | 1123 | if (skb->len <= 76) { |
1122 | if (tcp_v4_check(skb->h.th, skb->len, skb->nh.iph->saddr, | 1124 | return __skb_checksum_complete(skb); |
1123 | skb->nh.iph->daddr, | ||
1124 | skb_checksum(skb, 0, skb->len, 0))) | ||
1125 | return -1; | ||
1126 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
1127 | } else { | ||
1128 | skb->csum = ~tcp_v4_check(skb->h.th, skb->len, | ||
1129 | skb->nh.iph->saddr, | ||
1130 | skb->nh.iph->daddr, 0); | ||
1131 | } | 1125 | } |
1132 | return 0; | 1126 | return 0; |
1133 | } | 1127 | } |
@@ -1216,10 +1210,10 @@ int tcp_v4_rcv(struct sk_buff *skb) | |||
1216 | 1210 | ||
1217 | /* An explanation is required here, I think. | 1211 | /* An explanation is required here, I think. |
1218 | * Packet length and doff are validated by header prediction, | 1212 | * Packet length and doff are validated by header prediction, |
1219 | * provided case of th->doff==0 is elimineted. | 1213 | * provided case of th->doff==0 is eliminated. |
1220 | * So, we defer the checks. */ | 1214 | * So, we defer the checks. */ |
1221 | if ((skb->ip_summed != CHECKSUM_UNNECESSARY && | 1215 | if ((skb->ip_summed != CHECKSUM_UNNECESSARY && |
1222 | tcp_v4_checksum_init(skb) < 0)) | 1216 | tcp_v4_checksum_init(skb))) |
1223 | goto bad_packet; | 1217 | goto bad_packet; |
1224 | 1218 | ||
1225 | th = skb->h.th; | 1219 | th = skb->h.th; |
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index b1a63b2c6b4a..1b66a2ac4321 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c | |||
@@ -158,7 +158,7 @@ kill_with_rst: | |||
158 | /* I am shamed, but failed to make it more elegant. | 158 | /* I am shamed, but failed to make it more elegant. |
159 | * Yes, it is direct reference to IP, which is impossible | 159 | * Yes, it is direct reference to IP, which is impossible |
160 | * to generalize to IPv6. Taking into account that IPv6 | 160 | * to generalize to IPv6. Taking into account that IPv6 |
161 | * do not undertsnad recycling in any case, it not | 161 | * do not understand recycling in any case, it not |
162 | * a big problem in practice. --ANK */ | 162 | * a big problem in practice. --ANK */ |
163 | if (tw->tw_family == AF_INET && | 163 | if (tw->tw_family == AF_INET && |
164 | tcp_death_row.sysctl_tw_recycle && tcptw->tw_ts_recent_stamp && | 164 | tcp_death_row.sysctl_tw_recycle && tcptw->tw_ts_recent_stamp && |
@@ -194,7 +194,7 @@ kill_with_rst: | |||
194 | /* In window segment, it may be only reset or bare ack. */ | 194 | /* In window segment, it may be only reset or bare ack. */ |
195 | 195 | ||
196 | if (th->rst) { | 196 | if (th->rst) { |
197 | /* This is TIME_WAIT assasination, in two flavors. | 197 | /* This is TIME_WAIT assassination, in two flavors. |
198 | * Oh well... nobody has a sufficient solution to this | 198 | * Oh well... nobody has a sufficient solution to this |
199 | * protocol bug yet. | 199 | * protocol bug yet. |
200 | */ | 200 | */ |
@@ -380,6 +380,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req, | |||
380 | */ | 380 | */ |
381 | newtp->snd_cwnd = 2; | 381 | newtp->snd_cwnd = 2; |
382 | newtp->snd_cwnd_cnt = 0; | 382 | newtp->snd_cwnd_cnt = 0; |
383 | newtp->bytes_acked = 0; | ||
383 | 384 | ||
384 | newtp->frto_counter = 0; | 385 | newtp->frto_counter = 0; |
385 | newtp->frto_highmark = 0; | 386 | newtp->frto_highmark = 0; |
@@ -550,7 +551,7 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb, | |||
550 | 551 | ||
551 | /* RFC793 page 36: "If the connection is in any non-synchronized state ... | 552 | /* RFC793 page 36: "If the connection is in any non-synchronized state ... |
552 | * and the incoming segment acknowledges something not yet | 553 | * and the incoming segment acknowledges something not yet |
553 | * sent (the segment carries an unaccaptable ACK) ... | 554 | * sent (the segment carries an unacceptable ACK) ... |
554 | * a reset is sent." | 555 | * a reset is sent." |
555 | * | 556 | * |
556 | * Invalid ACK: reset will be sent by listening socket | 557 | * Invalid ACK: reset will be sent by listening socket |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index b907456a79f4..029c70dfb585 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -436,6 +436,8 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss | |||
436 | u16 flags; | 436 | u16 flags; |
437 | 437 | ||
438 | BUG_ON(len > skb->len); | 438 | BUG_ON(len > skb->len); |
439 | |||
440 | clear_all_retrans_hints(tp); | ||
439 | nsize = skb_headlen(skb) - len; | 441 | nsize = skb_headlen(skb) - len; |
440 | if (nsize < 0) | 442 | if (nsize < 0) |
441 | nsize = 0; | 443 | nsize = 0; |
@@ -599,7 +601,7 @@ int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len) | |||
599 | for TCP options, but includes only bare TCP header. | 601 | for TCP options, but includes only bare TCP header. |
600 | 602 | ||
601 | tp->rx_opt.mss_clamp is mss negotiated at connection setup. | 603 | tp->rx_opt.mss_clamp is mss negotiated at connection setup. |
602 | It is minumum of user_mss and mss received with SYN. | 604 | It is minimum of user_mss and mss received with SYN. |
603 | It also does not include TCP options. | 605 | It also does not include TCP options. |
604 | 606 | ||
605 | tp->pmtu_cookie is last pmtu, seen by this function. | 607 | tp->pmtu_cookie is last pmtu, seen by this function. |
@@ -1171,7 +1173,7 @@ u32 __tcp_select_window(struct sock *sk) | |||
1171 | { | 1173 | { |
1172 | struct inet_connection_sock *icsk = inet_csk(sk); | 1174 | struct inet_connection_sock *icsk = inet_csk(sk); |
1173 | struct tcp_sock *tp = tcp_sk(sk); | 1175 | struct tcp_sock *tp = tcp_sk(sk); |
1174 | /* MSS for the peer's data. Previous verions used mss_clamp | 1176 | /* MSS for the peer's data. Previous versions used mss_clamp |
1175 | * here. I don't know if the value based on our guesses | 1177 | * here. I don't know if the value based on our guesses |
1176 | * of peer's MSS is better for the performance. It's more correct | 1178 | * of peer's MSS is better for the performance. It's more correct |
1177 | * but may be worse for the performance because of rcv_mss | 1179 | * but may be worse for the performance because of rcv_mss |
@@ -1260,7 +1262,10 @@ static void tcp_retrans_try_collapse(struct sock *sk, struct sk_buff *skb, int m | |||
1260 | BUG_ON(tcp_skb_pcount(skb) != 1 || | 1262 | BUG_ON(tcp_skb_pcount(skb) != 1 || |
1261 | tcp_skb_pcount(next_skb) != 1); | 1263 | tcp_skb_pcount(next_skb) != 1); |
1262 | 1264 | ||
1263 | /* Ok. We will be able to collapse the packet. */ | 1265 | /* changing transmit queue under us so clear hints */ |
1266 | clear_all_retrans_hints(tp); | ||
1267 | |||
1268 | /* Ok. We will be able to collapse the packet. */ | ||
1264 | __skb_unlink(next_skb, &sk->sk_write_queue); | 1269 | __skb_unlink(next_skb, &sk->sk_write_queue); |
1265 | 1270 | ||
1266 | memcpy(skb_put(skb, next_skb_size), next_skb->data, next_skb_size); | 1271 | memcpy(skb_put(skb, next_skb_size), next_skb->data, next_skb_size); |
@@ -1330,6 +1335,8 @@ void tcp_simple_retransmit(struct sock *sk) | |||
1330 | } | 1335 | } |
1331 | } | 1336 | } |
1332 | 1337 | ||
1338 | clear_all_retrans_hints(tp); | ||
1339 | |||
1333 | if (!lost) | 1340 | if (!lost) |
1334 | return; | 1341 | return; |
1335 | 1342 | ||
@@ -1361,7 +1368,7 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) | |||
1361 | int err; | 1368 | int err; |
1362 | 1369 | ||
1363 | /* Do not sent more than we queued. 1/4 is reserved for possible | 1370 | /* Do not sent more than we queued. 1/4 is reserved for possible |
1364 | * copying overhead: frgagmentation, tunneling, mangling etc. | 1371 | * copying overhead: fragmentation, tunneling, mangling etc. |
1365 | */ | 1372 | */ |
1366 | if (atomic_read(&sk->sk_wmem_alloc) > | 1373 | if (atomic_read(&sk->sk_wmem_alloc) > |
1367 | min(sk->sk_wmem_queued + (sk->sk_wmem_queued >> 2), sk->sk_sndbuf)) | 1374 | min(sk->sk_wmem_queued + (sk->sk_wmem_queued >> 2), sk->sk_sndbuf)) |
@@ -1468,13 +1475,25 @@ void tcp_xmit_retransmit_queue(struct sock *sk) | |||
1468 | const struct inet_connection_sock *icsk = inet_csk(sk); | 1475 | const struct inet_connection_sock *icsk = inet_csk(sk); |
1469 | struct tcp_sock *tp = tcp_sk(sk); | 1476 | struct tcp_sock *tp = tcp_sk(sk); |
1470 | struct sk_buff *skb; | 1477 | struct sk_buff *skb; |
1471 | int packet_cnt = tp->lost_out; | 1478 | int packet_cnt; |
1479 | |||
1480 | if (tp->retransmit_skb_hint) { | ||
1481 | skb = tp->retransmit_skb_hint; | ||
1482 | packet_cnt = tp->retransmit_cnt_hint; | ||
1483 | }else{ | ||
1484 | skb = sk->sk_write_queue.next; | ||
1485 | packet_cnt = 0; | ||
1486 | } | ||
1472 | 1487 | ||
1473 | /* First pass: retransmit lost packets. */ | 1488 | /* First pass: retransmit lost packets. */ |
1474 | if (packet_cnt) { | 1489 | if (tp->lost_out) { |
1475 | sk_stream_for_retrans_queue(skb, sk) { | 1490 | sk_stream_for_retrans_queue_from(skb, sk) { |
1476 | __u8 sacked = TCP_SKB_CB(skb)->sacked; | 1491 | __u8 sacked = TCP_SKB_CB(skb)->sacked; |
1477 | 1492 | ||
1493 | /* we could do better than to assign each time */ | ||
1494 | tp->retransmit_skb_hint = skb; | ||
1495 | tp->retransmit_cnt_hint = packet_cnt; | ||
1496 | |||
1478 | /* Assume this retransmit will generate | 1497 | /* Assume this retransmit will generate |
1479 | * only one packet for congestion window | 1498 | * only one packet for congestion window |
1480 | * calculation purposes. This works because | 1499 | * calculation purposes. This works because |
@@ -1485,10 +1504,12 @@ void tcp_xmit_retransmit_queue(struct sock *sk) | |||
1485 | if (tcp_packets_in_flight(tp) >= tp->snd_cwnd) | 1504 | if (tcp_packets_in_flight(tp) >= tp->snd_cwnd) |
1486 | return; | 1505 | return; |
1487 | 1506 | ||
1488 | if (sacked&TCPCB_LOST) { | 1507 | if (sacked & TCPCB_LOST) { |
1489 | if (!(sacked&(TCPCB_SACKED_ACKED|TCPCB_SACKED_RETRANS))) { | 1508 | if (!(sacked&(TCPCB_SACKED_ACKED|TCPCB_SACKED_RETRANS))) { |
1490 | if (tcp_retransmit_skb(sk, skb)) | 1509 | if (tcp_retransmit_skb(sk, skb)) { |
1510 | tp->retransmit_skb_hint = NULL; | ||
1491 | return; | 1511 | return; |
1512 | } | ||
1492 | if (icsk->icsk_ca_state != TCP_CA_Loss) | 1513 | if (icsk->icsk_ca_state != TCP_CA_Loss) |
1493 | NET_INC_STATS_BH(LINUX_MIB_TCPFASTRETRANS); | 1514 | NET_INC_STATS_BH(LINUX_MIB_TCPFASTRETRANS); |
1494 | else | 1515 | else |
@@ -1501,8 +1522,8 @@ void tcp_xmit_retransmit_queue(struct sock *sk) | |||
1501 | TCP_RTO_MAX); | 1522 | TCP_RTO_MAX); |
1502 | } | 1523 | } |
1503 | 1524 | ||
1504 | packet_cnt -= tcp_skb_pcount(skb); | 1525 | packet_cnt += tcp_skb_pcount(skb); |
1505 | if (packet_cnt <= 0) | 1526 | if (packet_cnt >= tp->lost_out) |
1506 | break; | 1527 | break; |
1507 | } | 1528 | } |
1508 | } | 1529 | } |
@@ -1528,9 +1549,18 @@ void tcp_xmit_retransmit_queue(struct sock *sk) | |||
1528 | if (tcp_may_send_now(sk, tp)) | 1549 | if (tcp_may_send_now(sk, tp)) |
1529 | return; | 1550 | return; |
1530 | 1551 | ||
1531 | packet_cnt = 0; | 1552 | if (tp->forward_skb_hint) { |
1553 | skb = tp->forward_skb_hint; | ||
1554 | packet_cnt = tp->forward_cnt_hint; | ||
1555 | } else{ | ||
1556 | skb = sk->sk_write_queue.next; | ||
1557 | packet_cnt = 0; | ||
1558 | } | ||
1559 | |||
1560 | sk_stream_for_retrans_queue_from(skb, sk) { | ||
1561 | tp->forward_cnt_hint = packet_cnt; | ||
1562 | tp->forward_skb_hint = skb; | ||
1532 | 1563 | ||
1533 | sk_stream_for_retrans_queue(skb, sk) { | ||
1534 | /* Similar to the retransmit loop above we | 1564 | /* Similar to the retransmit loop above we |
1535 | * can pretend that the retransmitted SKB | 1565 | * can pretend that the retransmitted SKB |
1536 | * we send out here will be composed of one | 1566 | * we send out here will be composed of one |
@@ -1547,8 +1577,10 @@ void tcp_xmit_retransmit_queue(struct sock *sk) | |||
1547 | continue; | 1577 | continue; |
1548 | 1578 | ||
1549 | /* Ok, retransmit it. */ | 1579 | /* Ok, retransmit it. */ |
1550 | if (tcp_retransmit_skb(sk, skb)) | 1580 | if (tcp_retransmit_skb(sk, skb)) { |
1581 | tp->forward_skb_hint = NULL; | ||
1551 | break; | 1582 | break; |
1583 | } | ||
1552 | 1584 | ||
1553 | if (skb == skb_peek(&sk->sk_write_queue)) | 1585 | if (skb == skb_peek(&sk->sk_write_queue)) |
1554 | inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, | 1586 | inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, |
@@ -2058,3 +2090,4 @@ EXPORT_SYMBOL(tcp_connect); | |||
2058 | EXPORT_SYMBOL(tcp_make_synack); | 2090 | EXPORT_SYMBOL(tcp_make_synack); |
2059 | EXPORT_SYMBOL(tcp_simple_retransmit); | 2091 | EXPORT_SYMBOL(tcp_simple_retransmit); |
2060 | EXPORT_SYMBOL(tcp_sync_mss); | 2092 | EXPORT_SYMBOL(tcp_sync_mss); |
2093 | EXPORT_SYMBOL(sysctl_tcp_tso_win_divisor); | ||
diff --git a/net/ipv4/tcp_scalable.c b/net/ipv4/tcp_scalable.c index 327770bf5522..26d7486ee501 100644 --- a/net/ipv4/tcp_scalable.c +++ b/net/ipv4/tcp_scalable.c | |||
@@ -20,20 +20,20 @@ static void tcp_scalable_cong_avoid(struct sock *sk, u32 ack, u32 rtt, | |||
20 | u32 in_flight, int flag) | 20 | u32 in_flight, int flag) |
21 | { | 21 | { |
22 | struct tcp_sock *tp = tcp_sk(sk); | 22 | struct tcp_sock *tp = tcp_sk(sk); |
23 | if (in_flight < tp->snd_cwnd) | 23 | |
24 | if (!tcp_is_cwnd_limited(sk, in_flight)) | ||
24 | return; | 25 | return; |
25 | 26 | ||
26 | if (tp->snd_cwnd <= tp->snd_ssthresh) { | 27 | if (tp->snd_cwnd <= tp->snd_ssthresh) |
27 | tp->snd_cwnd++; | 28 | tcp_slow_start(tp); |
28 | } else { | 29 | else { |
29 | tp->snd_cwnd_cnt++; | 30 | tp->snd_cwnd_cnt++; |
30 | if (tp->snd_cwnd_cnt > min(tp->snd_cwnd, TCP_SCALABLE_AI_CNT)){ | 31 | if (tp->snd_cwnd_cnt > min(tp->snd_cwnd, TCP_SCALABLE_AI_CNT)){ |
31 | tp->snd_cwnd++; | 32 | if (tp->snd_cwnd < tp->snd_cwnd_clamp) |
33 | tp->snd_cwnd++; | ||
32 | tp->snd_cwnd_cnt = 0; | 34 | tp->snd_cwnd_cnt = 0; |
33 | } | 35 | } |
34 | } | 36 | } |
35 | tp->snd_cwnd = min_t(u32, tp->snd_cwnd, tp->snd_cwnd_clamp); | ||
36 | tp->snd_cwnd_stamp = tcp_time_stamp; | ||
37 | } | 37 | } |
38 | 38 | ||
39 | static u32 tcp_scalable_ssthresh(struct sock *sk) | 39 | static u32 tcp_scalable_ssthresh(struct sock *sk) |
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index 415ee47ac1c5..e1880959614a 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c | |||
@@ -58,7 +58,7 @@ static void tcp_write_err(struct sock *sk) | |||
58 | * to prevent DoS attacks. It is called when a retransmission timeout | 58 | * to prevent DoS attacks. It is called when a retransmission timeout |
59 | * or zero probe timeout occurs on orphaned socket. | 59 | * or zero probe timeout occurs on orphaned socket. |
60 | * | 60 | * |
61 | * Criterium is still not confirmed experimentally and may change. | 61 | * Criteria is still not confirmed experimentally and may change. |
62 | * We kill the socket, if: | 62 | * We kill the socket, if: |
63 | * 1. If number of orphaned sockets exceeds an administratively configured | 63 | * 1. If number of orphaned sockets exceeds an administratively configured |
64 | * limit. | 64 | * limit. |
@@ -132,7 +132,7 @@ static int tcp_write_timeout(struct sock *sk) | |||
132 | hole detection. :-( | 132 | hole detection. :-( |
133 | 133 | ||
134 | It is place to make it. It is not made. I do not want | 134 | It is place to make it. It is not made. I do not want |
135 | to make it. It is disguisting. It does not work in any | 135 | to make it. It is disgusting. It does not work in any |
136 | case. Let me to cite the same draft, which requires for | 136 | case. Let me to cite the same draft, which requires for |
137 | us to implement this: | 137 | us to implement this: |
138 | 138 | ||
diff --git a/net/ipv4/tcp_vegas.c b/net/ipv4/tcp_vegas.c index 93c5f92070f9..4376814d29fb 100644 --- a/net/ipv4/tcp_vegas.c +++ b/net/ipv4/tcp_vegas.c | |||
@@ -236,8 +236,7 @@ static void tcp_vegas_cong_avoid(struct sock *sk, u32 ack, | |||
236 | /* We don't have enough RTT samples to do the Vegas | 236 | /* We don't have enough RTT samples to do the Vegas |
237 | * calculation, so we'll behave like Reno. | 237 | * calculation, so we'll behave like Reno. |
238 | */ | 238 | */ |
239 | if (tp->snd_cwnd > tp->snd_ssthresh) | 239 | tcp_reno_cong_avoid(sk, ack, seq_rtt, in_flight, cnt); |
240 | tp->snd_cwnd++; | ||
241 | } else { | 240 | } else { |
242 | u32 rtt, target_cwnd, diff; | 241 | u32 rtt, target_cwnd, diff; |
243 | 242 | ||
@@ -275,7 +274,7 @@ static void tcp_vegas_cong_avoid(struct sock *sk, u32 ack, | |||
275 | */ | 274 | */ |
276 | diff = (old_wnd << V_PARAM_SHIFT) - target_cwnd; | 275 | diff = (old_wnd << V_PARAM_SHIFT) - target_cwnd; |
277 | 276 | ||
278 | if (tp->snd_cwnd < tp->snd_ssthresh) { | 277 | if (tp->snd_cwnd <= tp->snd_ssthresh) { |
279 | /* Slow start. */ | 278 | /* Slow start. */ |
280 | if (diff > gamma) { | 279 | if (diff > gamma) { |
281 | /* Going too fast. Time to slow down | 280 | /* Going too fast. Time to slow down |
@@ -295,6 +294,7 @@ static void tcp_vegas_cong_avoid(struct sock *sk, u32 ack, | |||
295 | V_PARAM_SHIFT)+1); | 294 | V_PARAM_SHIFT)+1); |
296 | 295 | ||
297 | } | 296 | } |
297 | tcp_slow_start(tp); | ||
298 | } else { | 298 | } else { |
299 | /* Congestion avoidance. */ | 299 | /* Congestion avoidance. */ |
300 | u32 next_snd_cwnd; | 300 | u32 next_snd_cwnd; |
@@ -327,37 +327,17 @@ static void tcp_vegas_cong_avoid(struct sock *sk, u32 ack, | |||
327 | else if (next_snd_cwnd < tp->snd_cwnd) | 327 | else if (next_snd_cwnd < tp->snd_cwnd) |
328 | tp->snd_cwnd--; | 328 | tp->snd_cwnd--; |
329 | } | 329 | } |
330 | } | ||
331 | 330 | ||
332 | /* Wipe the slate clean for the next RTT. */ | 331 | if (tp->snd_cwnd < 2) |
333 | vegas->cntRTT = 0; | 332 | tp->snd_cwnd = 2; |
334 | vegas->minRTT = 0x7fffffff; | 333 | else if (tp->snd_cwnd > tp->snd_cwnd_clamp) |
334 | tp->snd_cwnd = tp->snd_cwnd_clamp; | ||
335 | } | ||
335 | } | 336 | } |
336 | 337 | ||
337 | /* The following code is executed for every ack we receive, | 338 | /* Wipe the slate clean for the next RTT. */ |
338 | * except for conditions checked in should_advance_cwnd() | 339 | vegas->cntRTT = 0; |
339 | * before the call to tcp_cong_avoid(). Mainly this means that | 340 | vegas->minRTT = 0x7fffffff; |
340 | * we only execute this code if the ack actually acked some | ||
341 | * data. | ||
342 | */ | ||
343 | |||
344 | /* If we are in slow start, increase our cwnd in response to this ACK. | ||
345 | * (If we are not in slow start then we are in congestion avoidance, | ||
346 | * and adjust our congestion window only once per RTT. See the code | ||
347 | * above.) | ||
348 | */ | ||
349 | if (tp->snd_cwnd <= tp->snd_ssthresh) | ||
350 | tp->snd_cwnd++; | ||
351 | |||
352 | /* to keep cwnd from growing without bound */ | ||
353 | tp->snd_cwnd = min_t(u32, tp->snd_cwnd, tp->snd_cwnd_clamp); | ||
354 | |||
355 | /* Make sure that we are never so timid as to reduce our cwnd below | ||
356 | * 2 MSS. | ||
357 | * | ||
358 | * Going below 2 MSS would risk huge delayed ACKs from our receiver. | ||
359 | */ | ||
360 | tp->snd_cwnd = max(tp->snd_cwnd, 2U); | ||
361 | } | 341 | } |
362 | 342 | ||
363 | /* Extract info for Tcp socket info provided via netlink. */ | 343 | /* Extract info for Tcp socket info provided via netlink. */ |
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index e0bd1013cb0d..2422a5f7195d 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -761,7 +761,7 @@ int udp_ioctl(struct sock *sk, int cmd, unsigned long arg) | |||
761 | 761 | ||
762 | static __inline__ int __udp_checksum_complete(struct sk_buff *skb) | 762 | static __inline__ int __udp_checksum_complete(struct sk_buff *skb) |
763 | { | 763 | { |
764 | return (unsigned short)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum)); | 764 | return __skb_checksum_complete(skb); |
765 | } | 765 | } |
766 | 766 | ||
767 | static __inline__ int udp_checksum_complete(struct sk_buff *skb) | 767 | static __inline__ int udp_checksum_complete(struct sk_buff *skb) |
@@ -1100,11 +1100,8 @@ static int udp_checksum_init(struct sk_buff *skb, struct udphdr *uh, | |||
1100 | if (uh->check == 0) { | 1100 | if (uh->check == 0) { |
1101 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 1101 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
1102 | } else if (skb->ip_summed == CHECKSUM_HW) { | 1102 | } else if (skb->ip_summed == CHECKSUM_HW) { |
1103 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
1104 | if (!udp_check(uh, ulen, saddr, daddr, skb->csum)) | 1103 | if (!udp_check(uh, ulen, saddr, daddr, skb->csum)) |
1105 | return 0; | 1104 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
1106 | LIMIT_NETDEBUG(KERN_DEBUG "udp v4 hw csum failure.\n"); | ||
1107 | skb->ip_summed = CHECKSUM_NONE; | ||
1108 | } | 1105 | } |
1109 | if (skb->ip_summed != CHECKSUM_UNNECESSARY) | 1106 | if (skb->ip_summed != CHECKSUM_UNNECESSARY) |
1110 | skb->csum = csum_tcpudp_nofold(saddr, daddr, ulen, IPPROTO_UDP, 0); | 1107 | skb->csum = csum_tcpudp_nofold(saddr, daddr, ulen, IPPROTO_UDP, 0); |
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 23e540365a14..1bdf0fb8bf8a 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
@@ -585,17 +585,16 @@ static int icmpv6_rcv(struct sk_buff **pskb, unsigned int *nhoffp) | |||
585 | daddr = &skb->nh.ipv6h->daddr; | 585 | daddr = &skb->nh.ipv6h->daddr; |
586 | 586 | ||
587 | /* Perform checksum. */ | 587 | /* Perform checksum. */ |
588 | if (skb->ip_summed == CHECKSUM_HW) { | 588 | switch (skb->ip_summed) { |
589 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 589 | case CHECKSUM_HW: |
590 | if (csum_ipv6_magic(saddr, daddr, skb->len, IPPROTO_ICMPV6, | 590 | if (!csum_ipv6_magic(saddr, daddr, skb->len, IPPROTO_ICMPV6, |
591 | skb->csum)) { | 591 | skb->csum)) |
592 | LIMIT_NETDEBUG(KERN_DEBUG "ICMPv6 hw checksum failed\n"); | 592 | break; |
593 | skb->ip_summed = CHECKSUM_NONE; | 593 | /* fall through */ |
594 | } | 594 | case CHECKSUM_NONE: |
595 | } | 595 | skb->csum = ~csum_ipv6_magic(saddr, daddr, skb->len, |
596 | if (skb->ip_summed == CHECKSUM_NONE) { | 596 | IPPROTO_ICMPV6, 0); |
597 | if (csum_ipv6_magic(saddr, daddr, skb->len, IPPROTO_ICMPV6, | 597 | if (__skb_checksum_complete(skb)) { |
598 | skb_checksum(skb, 0, skb->len, 0))) { | ||
599 | LIMIT_NETDEBUG(KERN_DEBUG "ICMPv6 checksum failed [%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x > %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]\n", | 598 | LIMIT_NETDEBUG(KERN_DEBUG "ICMPv6 checksum failed [%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x > %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]\n", |
600 | NIP6(*saddr), NIP6(*daddr)); | 599 | NIP6(*saddr), NIP6(*daddr)); |
601 | goto discard_it; | 600 | goto discard_it; |
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 651c79b41eeb..8e9628f1c4c5 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
@@ -298,13 +298,10 @@ void rawv6_err(struct sock *sk, struct sk_buff *skb, | |||
298 | static inline int rawv6_rcv_skb(struct sock * sk, struct sk_buff * skb) | 298 | static inline int rawv6_rcv_skb(struct sock * sk, struct sk_buff * skb) |
299 | { | 299 | { |
300 | if ((raw6_sk(sk)->checksum || sk->sk_filter) && | 300 | if ((raw6_sk(sk)->checksum || sk->sk_filter) && |
301 | skb->ip_summed != CHECKSUM_UNNECESSARY) { | 301 | skb_checksum_complete(skb)) { |
302 | if ((unsigned short)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum))) { | 302 | /* FIXME: increment a raw6 drops counter here */ |
303 | /* FIXME: increment a raw6 drops counter here */ | 303 | kfree_skb(skb); |
304 | kfree_skb(skb); | 304 | return 0; |
305 | return 0; | ||
306 | } | ||
307 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
308 | } | 305 | } |
309 | 306 | ||
310 | /* Charge it to the socket. */ | 307 | /* Charge it to the socket. */ |
@@ -337,32 +334,25 @@ int rawv6_rcv(struct sock *sk, struct sk_buff *skb) | |||
337 | if (!rp->checksum) | 334 | if (!rp->checksum) |
338 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 335 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
339 | 336 | ||
340 | if (skb->ip_summed != CHECKSUM_UNNECESSARY) { | 337 | if (skb->ip_summed == CHECKSUM_HW) { |
341 | if (skb->ip_summed == CHECKSUM_HW) { | 338 | skb_postpull_rcsum(skb, skb->nh.raw, |
342 | skb_postpull_rcsum(skb, skb->nh.raw, | 339 | skb->h.raw - skb->nh.raw); |
343 | skb->h.raw - skb->nh.raw); | 340 | if (!csum_ipv6_magic(&skb->nh.ipv6h->saddr, |
341 | &skb->nh.ipv6h->daddr, | ||
342 | skb->len, inet->num, skb->csum)) | ||
344 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 343 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
345 | if (csum_ipv6_magic(&skb->nh.ipv6h->saddr, | ||
346 | &skb->nh.ipv6h->daddr, | ||
347 | skb->len, inet->num, skb->csum)) { | ||
348 | LIMIT_NETDEBUG(KERN_DEBUG "raw v6 hw csum failure.\n"); | ||
349 | skb->ip_summed = CHECKSUM_NONE; | ||
350 | } | ||
351 | } | ||
352 | if (skb->ip_summed == CHECKSUM_NONE) | ||
353 | skb->csum = ~csum_ipv6_magic(&skb->nh.ipv6h->saddr, | ||
354 | &skb->nh.ipv6h->daddr, | ||
355 | skb->len, inet->num, 0); | ||
356 | } | 344 | } |
345 | if (skb->ip_summed != CHECKSUM_UNNECESSARY) | ||
346 | skb->csum = ~csum_ipv6_magic(&skb->nh.ipv6h->saddr, | ||
347 | &skb->nh.ipv6h->daddr, | ||
348 | skb->len, inet->num, 0); | ||
357 | 349 | ||
358 | if (inet->hdrincl) { | 350 | if (inet->hdrincl) { |
359 | if (skb->ip_summed != CHECKSUM_UNNECESSARY && | 351 | if (skb_checksum_complete(skb)) { |
360 | (unsigned short)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum))) { | ||
361 | /* FIXME: increment a raw6 drops counter here */ | 352 | /* FIXME: increment a raw6 drops counter here */ |
362 | kfree_skb(skb); | 353 | kfree_skb(skb); |
363 | return 0; | 354 | return 0; |
364 | } | 355 | } |
365 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
366 | } | 356 | } |
367 | 357 | ||
368 | rawv6_rcv_skb(sk, skb); | 358 | rawv6_rcv_skb(sk, skb); |
@@ -407,7 +397,7 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk, | |||
407 | if (skb->ip_summed==CHECKSUM_UNNECESSARY) { | 397 | if (skb->ip_summed==CHECKSUM_UNNECESSARY) { |
408 | err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); | 398 | err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); |
409 | } else if (msg->msg_flags&MSG_TRUNC) { | 399 | } else if (msg->msg_flags&MSG_TRUNC) { |
410 | if ((unsigned short)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum))) | 400 | if (__skb_checksum_complete(skb)) |
411 | goto csum_copy_err; | 401 | goto csum_copy_err; |
412 | err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); | 402 | err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); |
413 | } else { | 403 | } else { |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index d746d3b27efb..62c0e5bd931c 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -1401,20 +1401,18 @@ out: | |||
1401 | static int tcp_v6_checksum_init(struct sk_buff *skb) | 1401 | static int tcp_v6_checksum_init(struct sk_buff *skb) |
1402 | { | 1402 | { |
1403 | if (skb->ip_summed == CHECKSUM_HW) { | 1403 | if (skb->ip_summed == CHECKSUM_HW) { |
1404 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
1405 | if (!tcp_v6_check(skb->h.th,skb->len,&skb->nh.ipv6h->saddr, | 1404 | if (!tcp_v6_check(skb->h.th,skb->len,&skb->nh.ipv6h->saddr, |
1406 | &skb->nh.ipv6h->daddr,skb->csum)) | 1405 | &skb->nh.ipv6h->daddr,skb->csum)) { |
1406 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
1407 | return 0; | 1407 | return 0; |
1408 | LIMIT_NETDEBUG(KERN_DEBUG "hw tcp v6 csum failed\n"); | 1408 | } |
1409 | } | 1409 | } |
1410 | |||
1411 | skb->csum = ~tcp_v6_check(skb->h.th,skb->len,&skb->nh.ipv6h->saddr, | ||
1412 | &skb->nh.ipv6h->daddr, 0); | ||
1413 | |||
1410 | if (skb->len <= 76) { | 1414 | if (skb->len <= 76) { |
1411 | if (tcp_v6_check(skb->h.th,skb->len,&skb->nh.ipv6h->saddr, | 1415 | return __skb_checksum_complete(skb); |
1412 | &skb->nh.ipv6h->daddr,skb_checksum(skb, 0, skb->len, 0))) | ||
1413 | return -1; | ||
1414 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
1415 | } else { | ||
1416 | skb->csum = ~tcp_v6_check(skb->h.th,skb->len,&skb->nh.ipv6h->saddr, | ||
1417 | &skb->nh.ipv6h->daddr,0); | ||
1418 | } | 1416 | } |
1419 | return 0; | 1417 | return 0; |
1420 | } | 1418 | } |
@@ -1575,7 +1573,7 @@ static int tcp_v6_rcv(struct sk_buff **pskb, unsigned int *nhoffp) | |||
1575 | goto discard_it; | 1573 | goto discard_it; |
1576 | 1574 | ||
1577 | if ((skb->ip_summed != CHECKSUM_UNNECESSARY && | 1575 | if ((skb->ip_summed != CHECKSUM_UNNECESSARY && |
1578 | tcp_v6_checksum_init(skb) < 0)) | 1576 | tcp_v6_checksum_init(skb))) |
1579 | goto bad_packet; | 1577 | goto bad_packet; |
1580 | 1578 | ||
1581 | th = skb->h.th; | 1579 | th = skb->h.th; |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index bf9519341fd3..e671153b47b2 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -248,7 +248,7 @@ try_again: | |||
248 | err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov, | 248 | err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov, |
249 | copied); | 249 | copied); |
250 | } else if (msg->msg_flags&MSG_TRUNC) { | 250 | } else if (msg->msg_flags&MSG_TRUNC) { |
251 | if ((unsigned short)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum))) | 251 | if (__skb_checksum_complete(skb)) |
252 | goto csum_copy_err; | 252 | goto csum_copy_err; |
253 | err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov, | 253 | err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov, |
254 | copied); | 254 | copied); |
@@ -363,13 +363,10 @@ static inline int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) | |||
363 | return -1; | 363 | return -1; |
364 | } | 364 | } |
365 | 365 | ||
366 | if (skb->ip_summed != CHECKSUM_UNNECESSARY) { | 366 | if (skb_checksum_complete(skb)) { |
367 | if ((unsigned short)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum))) { | 367 | UDP6_INC_STATS_BH(UDP_MIB_INERRORS); |
368 | UDP6_INC_STATS_BH(UDP_MIB_INERRORS); | 368 | kfree_skb(skb); |
369 | kfree_skb(skb); | 369 | return 0; |
370 | return 0; | ||
371 | } | ||
372 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
373 | } | 370 | } |
374 | 371 | ||
375 | if (sock_queue_rcv_skb(sk,skb)<0) { | 372 | if (sock_queue_rcv_skb(sk,skb)<0) { |
@@ -491,13 +488,10 @@ static int udpv6_rcv(struct sk_buff **pskb, unsigned int *nhoffp) | |||
491 | uh = skb->h.uh; | 488 | uh = skb->h.uh; |
492 | } | 489 | } |
493 | 490 | ||
494 | if (skb->ip_summed==CHECKSUM_HW) { | 491 | if (skb->ip_summed == CHECKSUM_HW && |
492 | !csum_ipv6_magic(saddr, daddr, ulen, IPPROTO_UDP, skb->csum)) | ||
495 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 493 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
496 | if (csum_ipv6_magic(saddr, daddr, ulen, IPPROTO_UDP, skb->csum)) { | 494 | |
497 | LIMIT_NETDEBUG(KERN_DEBUG "udp v6 hw csum failure.\n"); | ||
498 | skb->ip_summed = CHECKSUM_NONE; | ||
499 | } | ||
500 | } | ||
501 | if (skb->ip_summed != CHECKSUM_UNNECESSARY) | 495 | if (skb->ip_summed != CHECKSUM_UNNECESSARY) |
502 | skb->csum = ~csum_ipv6_magic(saddr, daddr, ulen, IPPROTO_UDP, 0); | 496 | skb->csum = ~csum_ipv6_magic(saddr, daddr, ulen, IPPROTO_UDP, 0); |
503 | 497 | ||
@@ -521,8 +515,7 @@ static int udpv6_rcv(struct sk_buff **pskb, unsigned int *nhoffp) | |||
521 | if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) | 515 | if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) |
522 | goto discard; | 516 | goto discard; |
523 | 517 | ||
524 | if (skb->ip_summed != CHECKSUM_UNNECESSARY && | 518 | if (skb_checksum_complete(skb)) |
525 | (unsigned short)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum))) | ||
526 | goto discard; | 519 | goto discard; |
527 | UDP6_INC_STATS_BH(UDP_MIB_NOPORTS); | 520 | UDP6_INC_STATS_BH(UDP_MIB_NOPORTS); |
528 | 521 | ||
diff --git a/net/rxrpc/transport.c b/net/rxrpc/transport.c index 122c086ee2db..dbe6105e83a5 100644 --- a/net/rxrpc/transport.c +++ b/net/rxrpc/transport.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/in.h> | 23 | #include <linux/in.h> |
24 | #include <linux/in6.h> | 24 | #include <linux/in6.h> |
25 | #include <linux/icmp.h> | 25 | #include <linux/icmp.h> |
26 | #include <linux/skbuff.h> | ||
26 | #include <net/sock.h> | 27 | #include <net/sock.h> |
27 | #include <net/ip.h> | 28 | #include <net/ip.h> |
28 | #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) | 29 | #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) |
@@ -475,15 +476,11 @@ void rxrpc_trans_receive_packet(struct rxrpc_transport *trans) | |||
475 | 476 | ||
476 | /* we'll probably need to checksum it (didn't call | 477 | /* we'll probably need to checksum it (didn't call |
477 | * sock_recvmsg) */ | 478 | * sock_recvmsg) */ |
478 | if (pkt->ip_summed != CHECKSUM_UNNECESSARY) { | 479 | if (skb_checksum_complete(pkt)) { |
479 | if ((unsigned short) | 480 | kfree_skb(pkt); |
480 | csum_fold(skb_checksum(pkt, 0, pkt->len, | 481 | rxrpc_krxiod_queue_transport(trans); |
481 | pkt->csum))) { | 482 | _leave(" CSUM failed"); |
482 | kfree_skb(pkt); | 483 | return; |
483 | rxrpc_krxiod_queue_transport(trans); | ||
484 | _leave(" CSUM failed"); | ||
485 | return; | ||
486 | } | ||
487 | } | 484 | } |
488 | 485 | ||
489 | addr = pkt->nh.iph->saddr; | 486 | addr = pkt->nh.iph->saddr; |
diff --git a/net/sunrpc/socklib.c b/net/sunrpc/socklib.c index 8f97e90f36c8..eb330d4f66d6 100644 --- a/net/sunrpc/socklib.c +++ b/net/sunrpc/socklib.c | |||
@@ -6,6 +6,9 @@ | |||
6 | * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> | 6 | * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/compiler.h> | ||
10 | #include <linux/netdevice.h> | ||
11 | #include <linux/skbuff.h> | ||
9 | #include <linux/types.h> | 12 | #include <linux/types.h> |
10 | #include <linux/pagemap.h> | 13 | #include <linux/pagemap.h> |
11 | #include <linux/udp.h> | 14 | #include <linux/udp.h> |
@@ -165,6 +168,8 @@ int csum_partial_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb) | |||
165 | return -1; | 168 | return -1; |
166 | if ((unsigned short)csum_fold(desc.csum)) | 169 | if ((unsigned short)csum_fold(desc.csum)) |
167 | return -1; | 170 | return -1; |
171 | if (unlikely(skb->ip_summed == CHECKSUM_HW)) | ||
172 | netdev_rx_csum_fault(skb->dev); | ||
168 | return 0; | 173 | return 0; |
169 | no_checksum: | 174 | no_checksum: |
170 | if (xdr_partial_copy_from_skb(xdr, 0, &desc, skb_read_bits) < 0) | 175 | if (xdr_partial_copy_from_skb(xdr, 0, &desc, skb_read_bits) < 0) |
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index f16e7cdd6150..e50e7cf43737 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c | |||
@@ -623,12 +623,9 @@ svc_udp_recvfrom(struct svc_rqst *rqstp) | |||
623 | /* we can use it in-place */ | 623 | /* we can use it in-place */ |
624 | rqstp->rq_arg.head[0].iov_base = skb->data + sizeof(struct udphdr); | 624 | rqstp->rq_arg.head[0].iov_base = skb->data + sizeof(struct udphdr); |
625 | rqstp->rq_arg.head[0].iov_len = len; | 625 | rqstp->rq_arg.head[0].iov_len = len; |
626 | if (skb->ip_summed != CHECKSUM_UNNECESSARY) { | 626 | if (skb_checksum_complete(skb)) { |
627 | if ((unsigned short)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum))) { | 627 | skb_free_datagram(svsk->sk_sk, skb); |
628 | skb_free_datagram(svsk->sk_sk, skb); | 628 | return 0; |
629 | return 0; | ||
630 | } | ||
631 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
632 | } | 629 | } |
633 | rqstp->rq_skbuff = skb; | 630 | rqstp->rq_skbuff = skb; |
634 | } | 631 | } |
diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c index e72ccd1a004f..1fdae678a345 100644 --- a/sound/pci/ad1889.c +++ b/sound/pci/ad1889.c | |||
@@ -1067,7 +1067,6 @@ MODULE_DEVICE_TABLE(pci, snd_ad1889_ids); | |||
1067 | 1067 | ||
1068 | static struct pci_driver ad1889_pci = { | 1068 | static struct pci_driver ad1889_pci = { |
1069 | .name = "AD1889 Audio", | 1069 | .name = "AD1889 Audio", |
1070 | .owner = THIS_MODULE, | ||
1071 | .id_table = snd_ad1889_ids, | 1070 | .id_table = snd_ad1889_ids, |
1072 | .probe = snd_ad1889_probe, | 1071 | .probe = snd_ad1889_probe, |
1073 | .remove = __devexit_p(snd_ad1889_remove), | 1072 | .remove = __devexit_p(snd_ad1889_remove), |
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c index 4e76c4a636d9..feffbe73387e 100644 --- a/sound/pci/ali5451/ali5451.c +++ b/sound/pci/ali5451/ali5451.c | |||
@@ -2403,7 +2403,6 @@ static void __devexit snd_ali_remove(struct pci_dev *pci) | |||
2403 | 2403 | ||
2404 | static struct pci_driver driver = { | 2404 | static struct pci_driver driver = { |
2405 | .name = "ALI 5451", | 2405 | .name = "ALI 5451", |
2406 | .owner = THIS_MODULE, | ||
2407 | .id_table = snd_ali_ids, | 2406 | .id_table = snd_ali_ids, |
2408 | .probe = snd_ali_probe, | 2407 | .probe = snd_ali_probe, |
2409 | .remove = __devexit_p(snd_ali_remove), | 2408 | .remove = __devexit_p(snd_ali_remove), |
diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c index 7c61561f297f..1904df650265 100644 --- a/sound/pci/als4000.c +++ b/sound/pci/als4000.c | |||
@@ -768,7 +768,6 @@ static void __devexit snd_card_als4000_remove(struct pci_dev *pci) | |||
768 | 768 | ||
769 | static struct pci_driver driver = { | 769 | static struct pci_driver driver = { |
770 | .name = "ALS4000", | 770 | .name = "ALS4000", |
771 | .owner = THIS_MODULE, | ||
772 | .id_table = snd_als4000_ids, | 771 | .id_table = snd_als4000_ids, |
773 | .probe = snd_card_als4000_probe, | 772 | .probe = snd_card_als4000_probe, |
774 | .remove = __devexit_p(snd_card_als4000_remove), | 773 | .remove = __devexit_p(snd_card_als4000_remove), |
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c index f5dad9248e39..8bae10d93529 100644 --- a/sound/pci/atiixp.c +++ b/sound/pci/atiixp.c | |||
@@ -1635,7 +1635,6 @@ static void __devexit snd_atiixp_remove(struct pci_dev *pci) | |||
1635 | 1635 | ||
1636 | static struct pci_driver driver = { | 1636 | static struct pci_driver driver = { |
1637 | .name = "ATI IXP AC97 controller", | 1637 | .name = "ATI IXP AC97 controller", |
1638 | .owner = THIS_MODULE, | ||
1639 | .id_table = snd_atiixp_ids, | 1638 | .id_table = snd_atiixp_ids, |
1640 | .probe = snd_atiixp_probe, | 1639 | .probe = snd_atiixp_probe, |
1641 | .remove = __devexit_p(snd_atiixp_remove), | 1640 | .remove = __devexit_p(snd_atiixp_remove), |
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c index 0cf202079571..3174b6625419 100644 --- a/sound/pci/atiixp_modem.c +++ b/sound/pci/atiixp_modem.c | |||
@@ -1309,7 +1309,6 @@ static void __devexit snd_atiixp_remove(struct pci_dev *pci) | |||
1309 | 1309 | ||
1310 | static struct pci_driver driver = { | 1310 | static struct pci_driver driver = { |
1311 | .name = "ATI IXP MC97 controller", | 1311 | .name = "ATI IXP MC97 controller", |
1312 | .owner = THIS_MODULE, | ||
1313 | .id_table = snd_atiixp_ids, | 1312 | .id_table = snd_atiixp_ids, |
1314 | .probe = snd_atiixp_probe, | 1313 | .probe = snd_atiixp_probe, |
1315 | .remove = __devexit_p(snd_atiixp_remove), | 1314 | .remove = __devexit_p(snd_atiixp_remove), |
diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c index 6af3b13f2fd1..d965609d8b38 100644 --- a/sound/pci/au88x0/au88x0.c +++ b/sound/pci/au88x0/au88x0.c | |||
@@ -373,7 +373,6 @@ static void __devexit snd_vortex_remove(struct pci_dev *pci) | |||
373 | // pci_driver definition | 373 | // pci_driver definition |
374 | static struct pci_driver driver = { | 374 | static struct pci_driver driver = { |
375 | .name = CARD_NAME_SHORT, | 375 | .name = CARD_NAME_SHORT, |
376 | .owner = THIS_MODULE, | ||
377 | .id_table = snd_vortex_ids, | 376 | .id_table = snd_vortex_ids, |
378 | .probe = snd_vortex_probe, | 377 | .probe = snd_vortex_probe, |
379 | .remove = __devexit_p(snd_vortex_remove), | 378 | .remove = __devexit_p(snd_vortex_remove), |
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index da99b1be2e8f..ab737d6df41d 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c | |||
@@ -1838,7 +1838,6 @@ snd_azf3328_remove(struct pci_dev *pci) | |||
1838 | 1838 | ||
1839 | static struct pci_driver driver = { | 1839 | static struct pci_driver driver = { |
1840 | .name = "AZF3328", | 1840 | .name = "AZF3328", |
1841 | .owner = THIS_MODULE, | ||
1842 | .id_table = snd_azf3328_ids, | 1841 | .id_table = snd_azf3328_ids, |
1843 | .probe = snd_azf3328_probe, | 1842 | .probe = snd_azf3328_probe, |
1844 | .remove = __devexit_p(snd_azf3328_remove), | 1843 | .remove = __devexit_p(snd_azf3328_remove), |
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c index 01d98eeb242e..8feca228c6d4 100644 --- a/sound/pci/bt87x.c +++ b/sound/pci/bt87x.c | |||
@@ -897,14 +897,13 @@ static void __devexit snd_bt87x_remove(struct pci_dev *pci) | |||
897 | /* default entries for all Bt87x cards - it's not exported */ | 897 | /* default entries for all Bt87x cards - it's not exported */ |
898 | /* driver_data is set to 0 to call detection */ | 898 | /* driver_data is set to 0 to call detection */ |
899 | static struct pci_device_id snd_bt87x_default_ids[] = { | 899 | static struct pci_device_id snd_bt87x_default_ids[] = { |
900 | BT_DEVICE(878, PCI_ANY_ID, PCI_ANY_ID, 0), | 900 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, PCI_ANY_ID, PCI_ANY_ID, 0), |
901 | BT_DEVICE(879, PCI_ANY_ID, PCI_ANY_ID, 0), | 901 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_879, PCI_ANY_ID, PCI_ANY_ID, 0), |
902 | { } | 902 | { } |
903 | }; | 903 | }; |
904 | 904 | ||
905 | static struct pci_driver driver = { | 905 | static struct pci_driver driver = { |
906 | .name = "Bt87x", | 906 | .name = "Bt87x", |
907 | .owner = THIS_MODULE, | ||
908 | .id_table = snd_bt87x_ids, | 907 | .id_table = snd_bt87x_ids, |
909 | .probe = snd_bt87x_probe, | 908 | .probe = snd_bt87x_probe, |
910 | .remove = __devexit_p(snd_bt87x_remove), | 909 | .remove = __devexit_p(snd_bt87x_remove), |
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index ee58d16002e5..389d967c97f4 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c | |||
@@ -1499,7 +1499,6 @@ MODULE_DEVICE_TABLE(pci, snd_ca0106_ids); | |||
1499 | // pci_driver definition | 1499 | // pci_driver definition |
1500 | static struct pci_driver driver = { | 1500 | static struct pci_driver driver = { |
1501 | .name = "CA0106", | 1501 | .name = "CA0106", |
1502 | .owner = THIS_MODULE, | ||
1503 | .id_table = snd_ca0106_ids, | 1502 | .id_table = snd_ca0106_ids, |
1504 | .probe = snd_ca0106_probe, | 1503 | .probe = snd_ca0106_probe, |
1505 | .remove = __devexit_p(snd_ca0106_remove), | 1504 | .remove = __devexit_p(snd_ca0106_remove), |
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index 57e8e433d56f..db605373b3bc 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c | |||
@@ -3053,7 +3053,6 @@ static void __devexit snd_cmipci_remove(struct pci_dev *pci) | |||
3053 | 3053 | ||
3054 | static struct pci_driver driver = { | 3054 | static struct pci_driver driver = { |
3055 | .name = "C-Media PCI", | 3055 | .name = "C-Media PCI", |
3056 | .owner = THIS_MODULE, | ||
3057 | .id_table = snd_cmipci_ids, | 3056 | .id_table = snd_cmipci_ids, |
3058 | .probe = snd_cmipci_probe, | 3057 | .probe = snd_cmipci_probe, |
3059 | .remove = __devexit_p(snd_cmipci_remove), | 3058 | .remove = __devexit_p(snd_cmipci_remove), |
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c index aea2c47712f9..034ff3755a3b 100644 --- a/sound/pci/cs4281.c +++ b/sound/pci/cs4281.c | |||
@@ -2106,7 +2106,6 @@ static int cs4281_resume(snd_card_t *card) | |||
2106 | 2106 | ||
2107 | static struct pci_driver driver = { | 2107 | static struct pci_driver driver = { |
2108 | .name = "CS4281", | 2108 | .name = "CS4281", |
2109 | .owner = THIS_MODULE, | ||
2110 | .id_table = snd_cs4281_ids, | 2109 | .id_table = snd_cs4281_ids, |
2111 | .probe = snd_cs4281_probe, | 2110 | .probe = snd_cs4281_probe, |
2112 | .remove = __devexit_p(snd_cs4281_remove), | 2111 | .remove = __devexit_p(snd_cs4281_remove), |
diff --git a/sound/pci/cs46xx/cs46xx.c b/sound/pci/cs46xx/cs46xx.c index 32b4f8465cef..b9fff4ee6f9d 100644 --- a/sound/pci/cs46xx/cs46xx.c +++ b/sound/pci/cs46xx/cs46xx.c | |||
@@ -163,7 +163,6 @@ static void __devexit snd_card_cs46xx_remove(struct pci_dev *pci) | |||
163 | 163 | ||
164 | static struct pci_driver driver = { | 164 | static struct pci_driver driver = { |
165 | .name = "Sound Fusion CS46xx", | 165 | .name = "Sound Fusion CS46xx", |
166 | .owner = THIS_MODULE, | ||
167 | .id_table = snd_cs46xx_ids, | 166 | .id_table = snd_cs46xx_ids, |
168 | .probe = snd_card_cs46xx_probe, | 167 | .probe = snd_card_cs46xx_probe, |
169 | .remove = __devexit_p(snd_card_cs46xx_remove), | 168 | .remove = __devexit_p(snd_card_cs46xx_remove), |
diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c index dd1ea9d3b81a..78270f8710ff 100644 --- a/sound/pci/emu10k1/emu10k1.c +++ b/sound/pci/emu10k1/emu10k1.c | |||
@@ -223,7 +223,6 @@ static void __devexit snd_card_emu10k1_remove(struct pci_dev *pci) | |||
223 | 223 | ||
224 | static struct pci_driver driver = { | 224 | static struct pci_driver driver = { |
225 | .name = "EMU10K1_Audigy", | 225 | .name = "EMU10K1_Audigy", |
226 | .owner = THIS_MODULE, | ||
227 | .id_table = snd_emu10k1_ids, | 226 | .id_table = snd_emu10k1_ids, |
228 | .probe = snd_card_emu10k1_probe, | 227 | .probe = snd_card_emu10k1_probe, |
229 | .remove = __devexit_p(snd_card_emu10k1_remove), | 228 | .remove = __devexit_p(snd_card_emu10k1_remove), |
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c index cbb689474e7d..795577716a5d 100644 --- a/sound/pci/emu10k1/emu10k1x.c +++ b/sound/pci/emu10k1/emu10k1x.c | |||
@@ -1613,7 +1613,6 @@ MODULE_DEVICE_TABLE(pci, snd_emu10k1x_ids); | |||
1613 | // pci_driver definition | 1613 | // pci_driver definition |
1614 | static struct pci_driver driver = { | 1614 | static struct pci_driver driver = { |
1615 | .name = "EMU10K1X", | 1615 | .name = "EMU10K1X", |
1616 | .owner = THIS_MODULE, | ||
1617 | .id_table = snd_emu10k1x_ids, | 1616 | .id_table = snd_emu10k1x_ids, |
1618 | .probe = snd_emu10k1x_probe, | 1617 | .probe = snd_emu10k1x_probe, |
1619 | .remove = __devexit_p(snd_emu10k1x_remove), | 1618 | .remove = __devexit_p(snd_emu10k1x_remove), |
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c index 92ff7c510f2b..2daa575f43ff 100644 --- a/sound/pci/ens1370.c +++ b/sound/pci/ens1370.c | |||
@@ -2386,7 +2386,6 @@ static void __devexit snd_audiopci_remove(struct pci_dev *pci) | |||
2386 | 2386 | ||
2387 | static struct pci_driver driver = { | 2387 | static struct pci_driver driver = { |
2388 | .name = DRIVER_NAME, | 2388 | .name = DRIVER_NAME, |
2389 | .owner = THIS_MODULE, | ||
2390 | .id_table = snd_audiopci_ids, | 2389 | .id_table = snd_audiopci_ids, |
2391 | .probe = snd_audiopci_probe, | 2390 | .probe = snd_audiopci_probe, |
2392 | .remove = __devexit_p(snd_audiopci_remove), | 2391 | .remove = __devexit_p(snd_audiopci_remove), |
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c index 78f90defcab1..c134f48152b0 100644 --- a/sound/pci/es1938.c +++ b/sound/pci/es1938.c | |||
@@ -1758,7 +1758,6 @@ static void __devexit snd_es1938_remove(struct pci_dev *pci) | |||
1758 | 1758 | ||
1759 | static struct pci_driver driver = { | 1759 | static struct pci_driver driver = { |
1760 | .name = "ESS ES1938 (Solo-1)", | 1760 | .name = "ESS ES1938 (Solo-1)", |
1761 | .owner = THIS_MODULE, | ||
1762 | .id_table = snd_es1938_ids, | 1761 | .id_table = snd_es1938_ids, |
1763 | .probe = snd_es1938_probe, | 1762 | .probe = snd_es1938_probe, |
1764 | .remove = __devexit_p(snd_es1938_remove), | 1763 | .remove = __devexit_p(snd_es1938_remove), |
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index ac8294e21cc1..50079dc90743 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c | |||
@@ -2761,7 +2761,6 @@ static void __devexit snd_es1968_remove(struct pci_dev *pci) | |||
2761 | 2761 | ||
2762 | static struct pci_driver driver = { | 2762 | static struct pci_driver driver = { |
2763 | .name = "ES1968 (ESS Maestro)", | 2763 | .name = "ES1968 (ESS Maestro)", |
2764 | .owner = THIS_MODULE, | ||
2765 | .id_table = snd_es1968_ids, | 2764 | .id_table = snd_es1968_ids, |
2766 | .probe = snd_es1968_probe, | 2765 | .probe = snd_es1968_probe, |
2767 | .remove = __devexit_p(snd_es1968_remove), | 2766 | .remove = __devexit_p(snd_es1968_remove), |
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index 4c7c8d225c7f..4e1d3434888d 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c | |||
@@ -1459,7 +1459,6 @@ static void __devexit snd_card_fm801_remove(struct pci_dev *pci) | |||
1459 | 1459 | ||
1460 | static struct pci_driver driver = { | 1460 | static struct pci_driver driver = { |
1461 | .name = "FM801", | 1461 | .name = "FM801", |
1462 | .owner = THIS_MODULE, | ||
1463 | .id_table = snd_fm801_ids, | 1462 | .id_table = snd_fm801_ids, |
1464 | .probe = snd_card_fm801_probe, | 1463 | .probe = snd_card_fm801_probe, |
1465 | .remove = __devexit_p(snd_card_fm801_remove), | 1464 | .remove = __devexit_p(snd_card_fm801_remove), |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 9d1412a9f2f8..ed525c03c996 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -1616,7 +1616,6 @@ MODULE_DEVICE_TABLE(pci, azx_ids); | |||
1616 | /* pci_driver definition */ | 1616 | /* pci_driver definition */ |
1617 | static struct pci_driver driver = { | 1617 | static struct pci_driver driver = { |
1618 | .name = "HDA Intel", | 1618 | .name = "HDA Intel", |
1619 | .owner = THIS_MODULE, | ||
1620 | .id_table = azx_ids, | 1619 | .id_table = azx_ids, |
1621 | .probe = azx_probe, | 1620 | .probe = azx_probe, |
1622 | .remove = __devexit_p(azx_remove), | 1621 | .remove = __devexit_p(azx_remove), |
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index 5aca37798c32..bd71bf424549 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c | |||
@@ -2735,7 +2735,6 @@ static void __devexit snd_ice1712_remove(struct pci_dev *pci) | |||
2735 | 2735 | ||
2736 | static struct pci_driver driver = { | 2736 | static struct pci_driver driver = { |
2737 | .name = "ICE1712", | 2737 | .name = "ICE1712", |
2738 | .owner = THIS_MODULE, | ||
2739 | .id_table = snd_ice1712_ids, | 2738 | .id_table = snd_ice1712_ids, |
2740 | .probe = snd_ice1712_probe, | 2739 | .probe = snd_ice1712_probe, |
2741 | .remove = __devexit_p(snd_ice1712_remove), | 2740 | .remove = __devexit_p(snd_ice1712_remove), |
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index 5b4293f5a652..0b5389ee26d5 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c | |||
@@ -2332,7 +2332,6 @@ static void __devexit snd_vt1724_remove(struct pci_dev *pci) | |||
2332 | 2332 | ||
2333 | static struct pci_driver driver = { | 2333 | static struct pci_driver driver = { |
2334 | .name = "ICE1724", | 2334 | .name = "ICE1724", |
2335 | .owner = THIS_MODULE, | ||
2336 | .id_table = snd_vt1724_ids, | 2335 | .id_table = snd_vt1724_ids, |
2337 | .probe = snd_vt1724_probe, | 2336 | .probe = snd_vt1724_probe, |
2338 | .remove = __devexit_p(snd_vt1724_remove), | 2337 | .remove = __devexit_p(snd_vt1724_remove), |
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 0801083f32dd..cf7801d2dd10 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c | |||
@@ -2876,7 +2876,6 @@ static void __devexit snd_intel8x0_remove(struct pci_dev *pci) | |||
2876 | 2876 | ||
2877 | static struct pci_driver driver = { | 2877 | static struct pci_driver driver = { |
2878 | .name = "Intel ICH", | 2878 | .name = "Intel ICH", |
2879 | .owner = THIS_MODULE, | ||
2880 | .id_table = snd_intel8x0_ids, | 2879 | .id_table = snd_intel8x0_ids, |
2881 | .probe = snd_intel8x0_probe, | 2880 | .probe = snd_intel8x0_probe, |
2882 | .remove = __devexit_p(snd_intel8x0_remove), | 2881 | .remove = __devexit_p(snd_intel8x0_remove), |
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index acfb197a833c..a42091860da7 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c | |||
@@ -1317,7 +1317,6 @@ static void __devexit snd_intel8x0m_remove(struct pci_dev *pci) | |||
1317 | 1317 | ||
1318 | static struct pci_driver driver = { | 1318 | static struct pci_driver driver = { |
1319 | .name = "Intel ICH Modem", | 1319 | .name = "Intel ICH Modem", |
1320 | .owner = THIS_MODULE, | ||
1321 | .id_table = snd_intel8x0m_ids, | 1320 | .id_table = snd_intel8x0m_ids, |
1322 | .probe = snd_intel8x0m_probe, | 1321 | .probe = snd_intel8x0m_probe, |
1323 | .remove = __devexit_p(snd_intel8x0m_remove), | 1322 | .remove = __devexit_p(snd_intel8x0m_remove), |
diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c index 5561fd4091e8..a110d664f626 100644 --- a/sound/pci/korg1212/korg1212.c +++ b/sound/pci/korg1212/korg1212.c | |||
@@ -2534,7 +2534,6 @@ static void __devexit snd_korg1212_remove(struct pci_dev *pci) | |||
2534 | 2534 | ||
2535 | static struct pci_driver driver = { | 2535 | static struct pci_driver driver = { |
2536 | .name = "korg1212", | 2536 | .name = "korg1212", |
2537 | .owner = THIS_MODULE, | ||
2538 | .id_table = snd_korg1212_ids, | 2537 | .id_table = snd_korg1212_ids, |
2539 | .probe = snd_korg1212_probe, | 2538 | .probe = snd_korg1212_probe, |
2540 | .remove = __devexit_p(snd_korg1212_remove), | 2539 | .remove = __devexit_p(snd_korg1212_remove), |
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index 99eb76c56f81..ede7a75bfe08 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c | |||
@@ -2858,7 +2858,6 @@ static void __devexit snd_m3_remove(struct pci_dev *pci) | |||
2858 | 2858 | ||
2859 | static struct pci_driver driver = { | 2859 | static struct pci_driver driver = { |
2860 | .name = "Maestro3", | 2860 | .name = "Maestro3", |
2861 | .owner = THIS_MODULE, | ||
2862 | .id_table = snd_m3_ids, | 2861 | .id_table = snd_m3_ids, |
2863 | .probe = snd_m3_probe, | 2862 | .probe = snd_m3_probe, |
2864 | .remove = __devexit_p(snd_m3_remove), | 2863 | .remove = __devexit_p(snd_m3_remove), |
diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c index c341c99ec783..b3090a13edab 100644 --- a/sound/pci/mixart/mixart.c +++ b/sound/pci/mixart/mixart.c | |||
@@ -1423,7 +1423,6 @@ static void __devexit snd_mixart_remove(struct pci_dev *pci) | |||
1423 | 1423 | ||
1424 | static struct pci_driver driver = { | 1424 | static struct pci_driver driver = { |
1425 | .name = "Digigram miXart", | 1425 | .name = "Digigram miXart", |
1426 | .owner = THIS_MODULE, | ||
1427 | .id_table = snd_mixart_ids, | 1426 | .id_table = snd_mixart_ids, |
1428 | .probe = snd_mixart_probe, | 1427 | .probe = snd_mixart_probe, |
1429 | .remove = __devexit_p(snd_mixart_remove), | 1428 | .remove = __devexit_p(snd_mixart_remove), |
diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c index e7aa15178453..089d23b4a002 100644 --- a/sound/pci/nm256/nm256.c +++ b/sound/pci/nm256/nm256.c | |||
@@ -1673,7 +1673,6 @@ static void __devexit snd_nm256_remove(struct pci_dev *pci) | |||
1673 | 1673 | ||
1674 | static struct pci_driver driver = { | 1674 | static struct pci_driver driver = { |
1675 | .name = "NeoMagic 256", | 1675 | .name = "NeoMagic 256", |
1676 | .owner = THIS_MODULE, | ||
1677 | .id_table = snd_nm256_ids, | 1676 | .id_table = snd_nm256_ids, |
1678 | .probe = snd_nm256_probe, | 1677 | .probe = snd_nm256_probe, |
1679 | .remove = __devexit_p(snd_nm256_remove), | 1678 | .remove = __devexit_p(snd_nm256_remove), |
diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c index e6627b0e38e4..783df7625c1c 100644 --- a/sound/pci/rme32.c +++ b/sound/pci/rme32.c | |||
@@ -2012,7 +2012,6 @@ static void __devexit snd_rme32_remove(struct pci_dev *pci) | |||
2012 | 2012 | ||
2013 | static struct pci_driver driver = { | 2013 | static struct pci_driver driver = { |
2014 | .name = "RME Digi32", | 2014 | .name = "RME Digi32", |
2015 | .owner = THIS_MODULE, | ||
2016 | .id_table = snd_rme32_ids, | 2015 | .id_table = snd_rme32_ids, |
2017 | .probe = snd_rme32_probe, | 2016 | .probe = snd_rme32_probe, |
2018 | .remove = __devexit_p(snd_rme32_remove), | 2017 | .remove = __devexit_p(snd_rme32_remove), |
diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c index 0eddeb16a10f..6d422ef64999 100644 --- a/sound/pci/rme96.c +++ b/sound/pci/rme96.c | |||
@@ -2413,7 +2413,6 @@ static void __devexit snd_rme96_remove(struct pci_dev *pci) | |||
2413 | 2413 | ||
2414 | static struct pci_driver driver = { | 2414 | static struct pci_driver driver = { |
2415 | .name = "RME Digi96", | 2415 | .name = "RME Digi96", |
2416 | .owner = THIS_MODULE, | ||
2417 | .id_table = snd_rme96_ids, | 2416 | .id_table = snd_rme96_ids, |
2418 | .probe = snd_rme96_probe, | 2417 | .probe = snd_rme96_probe, |
2419 | .remove = __devexit_p(snd_rme96_remove), | 2418 | .remove = __devexit_p(snd_rme96_remove), |
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index 845158b01b02..d15ffb3e9b0a 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c | |||
@@ -5062,7 +5062,6 @@ static void __devexit snd_hdsp_remove(struct pci_dev *pci) | |||
5062 | 5062 | ||
5063 | static struct pci_driver driver = { | 5063 | static struct pci_driver driver = { |
5064 | .name = "RME Hammerfall DSP", | 5064 | .name = "RME Hammerfall DSP", |
5065 | .owner = THIS_MODULE, | ||
5066 | .id_table = snd_hdsp_ids, | 5065 | .id_table = snd_hdsp_ids, |
5067 | .probe = snd_hdsp_probe, | 5066 | .probe = snd_hdsp_probe, |
5068 | .remove = __devexit_p(snd_hdsp_remove), | 5067 | .remove = __devexit_p(snd_hdsp_remove), |
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 60a1141f1327..a1aef6f6767e 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c | |||
@@ -3639,7 +3639,6 @@ static void __devexit snd_hdspm_remove(struct pci_dev *pci) | |||
3639 | 3639 | ||
3640 | static struct pci_driver driver = { | 3640 | static struct pci_driver driver = { |
3641 | .name = "RME Hammerfall DSP MADI", | 3641 | .name = "RME Hammerfall DSP MADI", |
3642 | .owner = THIS_MODULE, | ||
3643 | .id_table = snd_hdspm_ids, | 3642 | .id_table = snd_hdspm_ids, |
3644 | .probe = snd_hdspm_probe, | 3643 | .probe = snd_hdspm_probe, |
3645 | .remove = __devexit_p(snd_hdspm_remove), | 3644 | .remove = __devexit_p(snd_hdspm_remove), |
diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c index 59fcef9b6b81..f9d0c126c213 100644 --- a/sound/pci/rme9652/rme9652.c +++ b/sound/pci/rme9652/rme9652.c | |||
@@ -2654,7 +2654,6 @@ static void __devexit snd_rme9652_remove(struct pci_dev *pci) | |||
2654 | 2654 | ||
2655 | static struct pci_driver driver = { | 2655 | static struct pci_driver driver = { |
2656 | .name = "RME Digi9652 (Hammerfall)", | 2656 | .name = "RME Digi9652 (Hammerfall)", |
2657 | .owner = THIS_MODULE, | ||
2658 | .id_table = snd_rme9652_ids, | 2657 | .id_table = snd_rme9652_ids, |
2659 | .probe = snd_rme9652_probe, | 2658 | .probe = snd_rme9652_probe, |
2660 | .remove = __devexit_p(snd_rme9652_remove), | 2659 | .remove = __devexit_p(snd_rme9652_remove), |
diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c index 9a35474aad05..e92ef3ae2ca1 100644 --- a/sound/pci/sonicvibes.c +++ b/sound/pci/sonicvibes.c | |||
@@ -1502,7 +1502,6 @@ static void __devexit snd_sonic_remove(struct pci_dev *pci) | |||
1502 | 1502 | ||
1503 | static struct pci_driver driver = { | 1503 | static struct pci_driver driver = { |
1504 | .name = "S3 SonicVibes", | 1504 | .name = "S3 SonicVibes", |
1505 | .owner = THIS_MODULE, | ||
1506 | .id_table = snd_sonic_ids, | 1505 | .id_table = snd_sonic_ids, |
1507 | .probe = snd_sonic_probe, | 1506 | .probe = snd_sonic_probe, |
1508 | .remove = __devexit_p(snd_sonic_remove), | 1507 | .remove = __devexit_p(snd_sonic_remove), |
diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c index a8ca8e17853f..940d531575c0 100644 --- a/sound/pci/trident/trident.c +++ b/sound/pci/trident/trident.c | |||
@@ -177,7 +177,6 @@ static void __devexit snd_trident_remove(struct pci_dev *pci) | |||
177 | 177 | ||
178 | static struct pci_driver driver = { | 178 | static struct pci_driver driver = { |
179 | .name = "Trident4DWaveAudio", | 179 | .name = "Trident4DWaveAudio", |
180 | .owner = THIS_MODULE, | ||
181 | .id_table = snd_trident_ids, | 180 | .id_table = snd_trident_ids, |
182 | .probe = snd_trident_probe, | 181 | .probe = snd_trident_probe, |
183 | .remove = __devexit_p(snd_trident_remove), | 182 | .remove = __devexit_p(snd_trident_remove), |
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index 523eace250f7..fad2a2413bf6 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c | |||
@@ -2478,7 +2478,6 @@ static void __devexit snd_via82xx_remove(struct pci_dev *pci) | |||
2478 | 2478 | ||
2479 | static struct pci_driver driver = { | 2479 | static struct pci_driver driver = { |
2480 | .name = "VIA 82xx Audio", | 2480 | .name = "VIA 82xx Audio", |
2481 | .owner = THIS_MODULE, | ||
2482 | .id_table = snd_via82xx_ids, | 2481 | .id_table = snd_via82xx_ids, |
2483 | .probe = snd_via82xx_probe, | 2482 | .probe = snd_via82xx_probe, |
2484 | .remove = __devexit_p(snd_via82xx_remove), | 2483 | .remove = __devexit_p(snd_via82xx_remove), |
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c index 011f0fb63bf9..b83660bd05b0 100644 --- a/sound/pci/via82xx_modem.c +++ b/sound/pci/via82xx_modem.c | |||
@@ -1198,7 +1198,6 @@ static void __devexit snd_via82xx_remove(struct pci_dev *pci) | |||
1198 | 1198 | ||
1199 | static struct pci_driver driver = { | 1199 | static struct pci_driver driver = { |
1200 | .name = "VIA 82xx Modem", | 1200 | .name = "VIA 82xx Modem", |
1201 | .owner = THIS_MODULE, | ||
1202 | .id_table = snd_via82xx_modem_ids, | 1201 | .id_table = snd_via82xx_modem_ids, |
1203 | .probe = snd_via82xx_probe, | 1202 | .probe = snd_via82xx_probe, |
1204 | .remove = __devexit_p(snd_via82xx_remove), | 1203 | .remove = __devexit_p(snd_via82xx_remove), |
diff --git a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c index 2a7ad9dec021..dca6bd2c7580 100644 --- a/sound/pci/vx222/vx222.c +++ b/sound/pci/vx222/vx222.c | |||
@@ -252,7 +252,6 @@ static void __devexit snd_vx222_remove(struct pci_dev *pci) | |||
252 | 252 | ||
253 | static struct pci_driver driver = { | 253 | static struct pci_driver driver = { |
254 | .name = "Digigram VX222", | 254 | .name = "Digigram VX222", |
255 | .owner = THIS_MODULE, | ||
256 | .id_table = snd_vx222_ids, | 255 | .id_table = snd_vx222_ids, |
257 | .probe = snd_vx222_probe, | 256 | .probe = snd_vx222_probe, |
258 | .remove = __devexit_p(snd_vx222_remove), | 257 | .remove = __devexit_p(snd_vx222_remove), |
diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c index 1bbba32517ff..d013237205d8 100644 --- a/sound/pci/ymfpci/ymfpci.c +++ b/sound/pci/ymfpci/ymfpci.c | |||
@@ -344,7 +344,6 @@ static void __devexit snd_card_ymfpci_remove(struct pci_dev *pci) | |||
344 | 344 | ||
345 | static struct pci_driver driver = { | 345 | static struct pci_driver driver = { |
346 | .name = "Yamaha DS-XG PCI", | 346 | .name = "Yamaha DS-XG PCI", |
347 | .owner = THIS_MODULE, | ||
348 | .id_table = snd_ymfpci_ids, | 347 | .id_table = snd_ymfpci_ids, |
349 | .probe = snd_card_ymfpci_probe, | 348 | .probe = snd_card_ymfpci_probe, |
350 | .remove = __devexit_p(snd_card_ymfpci_remove), | 349 | .remove = __devexit_p(snd_card_ymfpci_remove), |