diff options
Diffstat (limited to 'arch')
181 files changed, 12652 insertions, 4351 deletions
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) |