Commit c5fc9c4b authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://cifs.bkbits.net/linux-2.5cifs

into ppc970.osdl.org:/home/torvalds/v2.6/linux
parents a7c47e51 e79b352d
......@@ -1284,8 +1284,8 @@ P: 1024D/77D4FC9B F5C5 1C20 1DFC DEC3 3107 54A4 2332 ADFC 77D4 FC9B
D: National Language Support
D: Linux Internationalization Project
D: German Localization for Linux and GNU software
S: Helenenstrasse 18
S: 65183 Wiesbaden
S: Kriemhildring 12a
S: 65795 Hattersheim am Main
S: Germany
N: Christoph Hellwig
......
-------------------------------------------------------------------------
Release Notes for Linux on Intel's IXP4xx Network Processor
Maintained by Deepak Saxena <dsaxena@plexity.net>
-------------------------------------------------------------------------
1. Overview
Intel's IXP4xx network processor is a highly integrated SOC that
is targeted for network applications, though it has become popular
in industrial control and other areas due to low cost and power
consumption. The IXP4xx family currently consists of several processors
that support different network offload functions such as encryption,
routing, firewalling, etc. For more information on the various
versions of the CPU, see:
http://developer.intel.com/design/network/products/npfamily/ixp4xx.htm
Intel also made the IXCP1100 CPU for sometime which is an IXP4xx
stripped of much of the network intelligence.
2. Linux Support
Linux currently supports the following features on the IXP4xx chips:
- Dual serial ports
- PCI interface
- Flash access (MTD/JFFS)
- I2C through GPIO
- GPIO for input/output/interrupts
See include/asm-arm/arch-ixp4xx/platform.h for access functions.
- Timers (watchdog, OS)
The following components of the chips are not supported by Linux and
require the use of Intel's propietary CSR softare:
- USB device interface
- Network interfaces (HSS, Utopia, NPEs, etc)
- Network offload functionality
If you need to use any of the above, you need to download Intel's
software from:
http://developer.intel.com/design/network/products/npfamily/ixp425swr1.htm
DO NOT POST QUESTIONS TO THE LINUX MAILING LISTS REGARDING THE PROPIETARY
SOFTWARE.
There are several websites that provide directions/pointers on using
Intel's software:
http://ixp4xx-osdg.sourceforge.net/
Open Source Developer's Guide for using uClinux and the Intel libraries
http://gatewaymaker.sourceforge.net/
Simple one page summary of building a gateway using an IXP425 and Linux
http://ixp425.sourceforge.net/
ATM device driver for IXP425 that relies on Intel's libraries
3. Known Issues/Limitations
3a. Limited inbound PCI window
The IXP4xx family allows for up to 256MB of memory but the PCI interface
can only expose 64MB of that memory to the PCI bus. This means that if
you are running with > 64MB, all PCI buffers outside of the accessible
range will be bounced using the routines in arch/arm/common/dmabounce.c.
3b. Limited outbound PCI window
IXP4xx provides two methods of accessing PCI memory space:
1) A direct mapped window from 0x48000000 to 0x4bffffff (64MB).
To access PCI via this space, we simply ioremap() the BAR
into the kernel and we can use the standard read[bwl]/write[bwl]
macros. This is the preffered method due to speed but it
limits the system to just 64MB of PCI memory. This can be
problamatic if using video cards and other memory-heavy devices.
2) If > 64MB of memory space is required, the IXP4xx can be
configured to use indirect registers to access PCI This allows
for up to 128MB (0x48000000 to 0x4fffffff) of memory on the bus.
The disadvantadge of this is that every PCI access requires
three local register accesses plus a spinlock, but in some
cases the performance hit is acceptable. In addition, you cannot
mmap() PCI devices in this case due to the indirect nature
of the PCI window.
By default, the direct method is used for performance reasons. If
you need more PCI memory, enable the IXP4XX_INDIRECT_PCI config option.
3c. GPIO as Interrupts
Currently the code only handles level-sensitive GPIO interrupts
4. Supported platforms
ADI Engineering Coyote Gateway Reference Platform
http://www.adiengineering.com/productsCoyote.html
The ADI Coyote platform is reference design for those building
small residential/office gateways. One NPE is connected to a 10/100
interface, one to 4-port 10/100 switch, and the third to and ADSL
interface. In addition, it also supports to POTs interfaces connected
via SLICs. Note that those are not supported by Linux ATM. Finally,
the platform has two mini-PCI slots used for 802.11[bga] cards.
Finally, there is an IDE port hanging off the expansion bus.
Gateworks Avila Network Platform
http://www.gateworks.com/avila_sbc.htm
The Avila platform is basically and IXDP425 with the 4 PCI slots
replaced with mini-PCI slots and a CF IDE interface hanging off
the expansion bus.
Intel IXDP425 Development Platform
http://developer.intel.com/design/network/products/npfamily/ixdp425.htm
This is Intel's standard reference platform for the IXDP425 and is
also known as the Richfield board. It contains 4 PCI slots, 16MB
of flash, two 10/100 ports and one ADSL port.
Motorola PrPMC1100 Processor Mezanine Card
http://www.fountainsys.com/datasheet/PrPMC1100.pdf
The PrPMC1100 is based on the IXCP1100 and is meant to plug into
and IXP2400/2800 system to act as the system controller. It simply
contains a CPU and 16MB of flash on the board and needs to be
plugged into a carrier board to function. Currently Linux only
supports the Motorola PrPMC carrier board for this platform.
See https://mcg.motorola.com/us/ds/pdf/ds0144.pdf for info
on the carrier board.
5. TODO LIST
- Add support for Coyote IDE
- Add support for edge-based GPIO interrupts
- Add support for CF IDE on expansion bus
6. Thanks
The IXP4xx work has been funded by Intel Corp. and MontaVista Software, Inc.
The following people have contributed patches/comments/etc:
Lutz Jaenicke
Justin Mayfield
Robert E. Ranslam
[I know I've forgotten others, please email me to be added]
-------------------------------------------------------------------------
Last Update: 5/13/2004
Board Overview
-----------------------------
This is an beta release of the Xscale Linux port to the ADI 80200EVB
evaluation board.
The 80200EVB is an evaluation platform for ADI Engineering's high-performance
80200FCC chipset for the Intel 80200 XScale CPU. The 80200FCC is an open
source FPGA based system that contains a PCI unit and a high performance
memory controller.
In addition to the 80200FCC, the board also contains a 16C550 UART, and 4MB
of flash.
The board is still under development and currently only the UART is functional
as the PCI bits have not been programmed into the FPGA.
For more information on the board, see http://www.adiengineering.com
Port Status
-----------------------------
Supported:
- Onboard UART (Polled operation only)
- Cache/TLB locking on 80200 CPU
TODO:
- PCI when hardware supports it
Building the Kernel
-----------------------------
change Linux makefile
make adi_evb_config
make oldconfig
make zImage
Loading Linux
-----------------------------
Before you can use Linux on the ADI board, you need to grab the following:
ADI 80200EVB Monitor:
ftp://source.mvista.com/pub/xscale/ADI_EVB/monitor.srec
ADI JFFS2 Image:
ftp://source.mvista.com/pub/xscale/ADI_EVB/adi.jffs2
Once you've got the Cygnus prompt, type in the following command:
load
On another terminal window:
cat monitor.srec > /dev/ttyS0
(replace ttyS0 with the serial port you are using)
Once completed, just type 'go' at the cygmon prompt and you should see:
MontaVista IQ80310 Monitor Version 0.1
monitor>
Type 'b 115200' at the prompt and change your terminal speed to 115200
The first thing to do is to upload and burn the jffs2 filesystem image
onto the boards 4MB of flash:
monitor> u c1000000
Uploading file at 0xc1000000
Now send file with ymodem
Do as the monitor says and transfer the file adi.jffs2. Once complete,
the following will copy the jffs2 image to location 0x80000 in the flash.
monitor> f 8000 c1000000 200000
Erasing sector 0x00080000
Writing sector 0x00080000 with data at 0xC1000000
Erasing sector 0x000A0000
Writing sector 0x000A0000 with data at 0xC1020000
Erasing sector 0x000C0000
...
Now use the same command as above to upload your zImage to location c1000000.
When you've done that, type 'j c1000000' to run Linux. Login as
root and you're all set to go.
Misc Notes
-----------------------------
The current version of the HW does not have an onboard timer, so the 80200
PMU is not available for general use as it is being used for a timer source.
By default, the MTD driver reserves the first 512K for bootloaders and
the remaining 3.5MB for the filesystem. You can edit drivers/mtd/map/adi_evb.c
to change this as needed for your application.
Contributors
-----------------------------
Thanks to ADI Engineering for providing the hardware for development
Deepak Saxena <dsaxena@mvista.com> - Initial port
-----------------------------
Enjoy. If you have any problem please contact Deepak Saxena
dsaxena@mvista.com
Board Overview
-----------------------------
The Cyclone IQ80310 board is an evaluation platform for Intel's 80200 Xscale
CPU and 80312 Intelligent I/O chipset (collectively called IOP310 chipset).
The 80312 contains dual PCI hoses (called the ATUs), a PCI-to-PCI bridge,
three DMA channels (1 on secondary PCI, one on primary PCI ), I2C, I2O
messaging unit, XOR unit for RAID operations, a bus performance monitoring
unit, and a memory controller with ECC features.
For more information on the board, see http://developer.intel.com/iio
Port Status
-----------------------------
Supported:
- MTD/JFFS/JFFS2
- NFS root
- RAMDISK root
- 2ndary PCI slots
- Onboard ethernet
- Serial ports (ttyS0/S1)
- Cache/TLB locking on 80200 CPU
- Performance monitoring unit on 80200 CPU
- 80200 Performance Monitoring Unit
- Acting as a system controller on Cyclone 80303BP PCI backplane
- DMA engines (EXPERIMENTAL)
- 80312 Bus Performance Monitor (EXPERIMENTAL)
- Application Accelerator Unit (XOR engine for RAID) (EXPERIMENTAL)
- Messaging Unit (EXPERIMENTAL)
TODO:
- I2C
Building the Kernel
-----------------------------
make iq80310_config
make oldconfig
make zImage
This will build an image setup for BOOTP/NFS root support. To change this,
just run make menuconfig and disable nfs root or add a "root=" option.
Preparing the Hardware
-----------------------------
This document assumes you're using a Rev D or newer board running
Redboot as the bootloader. Note that the version of RedBoot provided
with the boards has a major issue and you need to replace it with the
latest RedBoot. You can grab the source from the ECOS CVS or you can
get a prebuilt image and burn it in using FRU at:
ftp://source.mvista.com/pub/xscale/iq80310/redboot.bin
Make sure you do an 'fis init' command once you boot with the new
RedBoot image.
Downloading Linux
-----------------------------
Assuming you have your development system setup to act as a bootp/dhcp
server and running tftp:
RedBoot> load -r -b 0xa1008000 /tftpboot/zImage.xs
Raw file loaded 0xa1008000-0xa1094bd8
If you're not using dhcp/tftp, you can use y-modem instead:
RedBoot> load -r -b 0xa1008000 -m y
Note that on Rev D. of the board, tftp does not work due to intermittent
interrupt issues, so you need to download using ymodem.
Once the download is completed:
RedBoot> go 0xa1008000
Root Devices
-----------------------------
A kernel is not useful without a root filesystem, and you have several
choices with this board: NFS root, RAMDISK, or JFFS/JFFS2. For development
purposes, it is suggested that you use NFS root for easy access to various
tools. Once you're ready to deploy, probably want to utilize JFFS/JFFS2 on
the flash device.
MTD on the IQ80310
-----------------------------
Linux on the IQ80310 supports RedBoot FIS paritioning if it is enabled.
Out of the box, once you've done 'fis init' on RedBoot, you will get
the following partitioning scheme:
root@192.168.0.14:~# cat /proc/mtd
dev: size erasesize name
mtd0: 00040000 00020000 "RedBoot"
mtd1: 00040000 00020000 "RedBoot[backup]"
mtd2: 0075f000 00020000 "unallocated space"
mtd3: 00001000 00020000 "RedBoot config"
mtd4: 00020000 00020000 "FIS directory"
To create an FIS directory, you need to use the fis command in RedBoot.
As an example, you can burn the kernel into the flash once it's downloaded:
RedBoot> fis create -b 0xa1008000 -l 0x8CBAC -r 0xa1008000 -f 0x80000 kernel
... Erase from 0x00080000-0x00120000: .....
... Program from 0xa1008000-0xa1094bac at 0x00080000: .....
... Unlock from 0x007e0000-0x00800000: .
... Erase from 0x007e0000-0x00800000: .
... Program from 0xa1fdf000-0xa1fff000 at 0x007e0000: .
... Lock from 0x007e0000-0x00800000: .
RedBoot> fis list
Name FLASH addr Mem addr Length Entry point
RedBoot 0x00000000 0x00000000 0x00040000 0x00000000
RedBoot[backup] 0x00040000 0x00040000 0x00040000 0x00000000
RedBoot config 0x007DF000 0x007DF000 0x00001000 0x00000000
FIS directory 0x007E0000 0x007E0000 0x00020000 0x00000000
kernel 0x00080000 0xA1008000 0x000A0000 0x00000000
This leads to the following Linux MTD setup:
mtroot@192.168.0.14:~# cat /proc/mtd
dev: size erasesize name
mtd0: 00040000 00020000 "RedBoot"
mtd1: 00040000 00020000 "RedBoot[backup]"
mtd2: 000a0000 00020000 "kernel"
mtd3: 006bf000 00020000 "unallocated space"
mtd4: 00001000 00020000 "RedBoot config"
mtd5: 00020000 00020000 "FIS directory"
Note that there is not a 1:1 mapping to the number of RedBoot paritions to
MTD partitions as unused space also gets allocated into MTD partitions.
As an aside, the -r option when creating the Kernel entry allows you to
simply do an 'fis load kernel' to copy the image from flash into memory.
You can then do an 'fis go 0xa1008000' to start Linux.
If you choose to use static partitioning instead of the RedBoot partioning:
/dev/mtd0 0x00000000 - 0x0007ffff: Boot Monitor (512k)
/dev/mtd1 0x00080000 - 0x0011ffff: Kernel Image (640K)
/dev/mtd2 0x00120000 - 0x0071ffff: File System (6M)
/dev/mtd3 0x00720000 - 0x00800000: RedBoot Reserved (896K)
To use a JFFS1/2 root FS, you need to donwload the JFFS image using either
tftp or ymodem, and then copy it to flash:
RedBoot> load -r -b 0xa1000000 /tftpboot/jffs.img
Raw file loaded 0xa1000000-0xa1600000
RedBoot> fis create -b 0xa1000000 -l 0x600000 -f 0x120000 jffs
... Erase from 0x00120000-0x00720000: ..................................
... Program from 0xa1000000-0xa1600000 at 0x00120000: ..................
......................
... Unlock from 0x007e0000-0x00800000: .
... Erase from 0x007e0000-0x00800000: .
... Program from 0xa1fdf000-0xa1fff000 at 0x007e0000: .
... Lock from 0x007e0000-0x00800000: .
RedBoot> fis list
Name FLASH addr Mem addr Length Entry point
RedBoot 0x00000000 0x00000000 0x00040000 0x00000000
RedBoot[backup] 0x00040000 0x00040000 0x00040000 0x00000000
RedBoot config 0x007DF000 0x007DF000 0x00001000 0x00000000
FIS directory 0x007E0000 0x007E0000 0x00020000 0x00000000
kernel 0x00080000 0xA1008000 0x000A0000 0xA1008000
jffs 0x00120000 0x00120000 0x00600000 0x00000000
This looks like this in Linux:
root@192.168.0.14:~# cat /proc/mtd
dev: size erasesize name
mtd0: 00040000 00020000 "RedBoot"
mtd1: 00040000 00020000 "RedBoot[backup]"
mtd2: 000a0000 00020000 "kernel"
mtd3: 00600000 00020000 "jffs"
mtd4: 000bf000 00020000 "unallocated space"
mtd5: 00001000 00020000 "RedBoot config"
mtd6: 00020000 00020000 "FIS directory"
You need to boot the kernel once and watch the boot messages to see how the
JFFS RedBoot partition mapped into the MTD partition scheme.
You can grab a pre-built JFFS image to use as a root file system at:
ftp://source.mvista.com/pub/xscale/iq80310/jffs.img
For detailed info on using MTD and creating a JFFS image go to:
http://www.linux-mtd.infradead.org.
For details on using RedBoot's FIS commands, type 'fis help' or consult
your RedBoot manual.
Contributors
-----------------------------
Thanks to Intel Corporation for providing the hardware.
John Clark <jclark@teamasa.com> - Initial discovery of RedBoot issues
Dave Jiang <dave.jiang@intel.com> - IRQ demux fixes, AAU, DMA, MU
Nicolas Pitre <nico@cam.org> - Initial port, cleanup, debugging
Matt Porter <mporter@mvista.com> - PCI subsystem development, debugging
Tim Sanders <tsanders@sanders.org> - Initial PCI code
Mark Salter <msalter@redhat.com> - RedBoot fixes
Deepak Saxena <dsaxena@mvista.com> - Cleanup, debug, cache lock, PMU
-----------------------------
Enjoy.
If you have any problems please contact Deepak Saxena <dsaxena@mvista.com>
A few notes from rmk
-----------------------------
These are notes of my initial experience getting the IQ80310 Rev D up and
running. In total, it has taken many hours to work out what's going on...
The version of redboot used is:
RedBoot(tm) bootstrap and debug environment, version UNKNOWN - built 14:58:21, Aug 15 2001
1. I've had a corrupted download of the redboot.bin file from Montavista's
FTP site. It would be a good idea if there were md5sums, sum or gpg
signatures available to ensure the integrity of the downloaded files.
The result of this was an apparantly 100% dead card.
2. RedBoot Intel EtherExpress Pro 100 driver seems to be very unstable -
I've had it take out the whole of a 100mbit network for several minutes.
The Hub indiates ZERO activity, despite machines attempting to communicate.
Further to this, while tftping the kernel, the transfer will stall regularly,
and might even drop the link LED.
3. There appears to be a bug in the Intel Documentation Pack that comes with
the IQ80310 board. Serial port 1, which is the socket next to the LEDs
is address 0xfe810000, not 0xfe800000.
Note that RedBoot uses either serial port 1 OR serial port 2, so if you
have your console connected to the wrong port, you'll see redboot messages
but not kernel boot messages.
4. Trying to use fconfig to setup a boot script fails - it hangs when trying
to erase the flash.
Board Overview
-----------------------------
The Worcester IQ80321 board is an evaluation platform for Intel's 80321 Xscale
CPU (sometimes called IOP321 chipset).
The 80321 contains a single PCI hose (called the ATUs), a PCI-to-PCI bridge,
two DMA channels, I2C, I2O messaging unit, XOR unit for RAID operations,
a bus performance monitoring unit, and a memory controller with ECC features.
For more information on the board, see http://developer.intel.com/iio
Port Status
-----------------------------
Supported:
- MTD/JFFS/JFFS2 root
- NFS root
- RAMDISK root
- Serial port (ttyS0)
- Cache/TLB locking on 80321 CPU
- Performance monitoring unit on 80321 CPU
TODO:
- DMA engines
- I2C
- 80321 Bus Performance Monitor
- Application Accelerator Unit (XOR engine for RAID)
- I2O Messaging Unit
- I2C unit
- SSP
Building the Kernel
-----------------------------
make iq80321_config
make oldconfig
make zImage
This will build an image setup for BOOTP/NFS root support. To change this,
just run make menuconfig and disable nfs root or add a "root=" option.
Preparing the Hardware
-----------------------------
Make sure you do an 'fis init' command once you boot with the new
RedBoot image.
Downloading Linux
-----------------------------
Assuming you have your development system setup to act as a bootp/dhcp
server and running tftp:
NOTE: The 80321 board uses a different default memory map than the 80310.
RedBoot> load -r -b 0x01008000 -m y
Once the download is completed:
RedBoot> go 0x01008000
There is a version of RedBoot floating around that has DHCP support, but
I've never been able to cleanly transfer a kernel image and have it run.
Root Devices
-----------------------------
A kernel is not useful without a root filesystem, and you have several
choices with this board: NFS root, RAMDISK, or JFFS/JFFS2. For development
purposes, it is suggested that you use NFS root for easy access to various
tools. Once you're ready to deploy, probably want to utilize JFFS/JFFS2 on
the flash device.
MTD on the IQ80321
-----------------------------
Linux on the IQ80321 supports RedBoot FIS paritioning if it is enabled.
Out of the box, once you've done 'fis init' on RedBoot, you will get
the following partitioning scheme:
root@192.168.0.14:~# cat /proc/mtd
dev: size erasesize name
mtd0: 00040000 00020000 "RedBoot"
mtd1: 00040000 00020000 "RedBoot[backup]"
mtd2: 0075f000 00020000 "unallocated space"
mtd3: 00001000 00020000 "RedBoot config"
mtd4: 00020000 00020000 "FIS directory"
To create an FIS directory, you need to use the fis command in RedBoot.
As an example, you can burn the kernel into the flash once it's downloaded:
RedBoot> fis create -b 0x01008000 -l 0x8CBAC -r 0x01008000 -f 0x80000 kernel
... Erase from 0x00080000-0x00120000: .....
... Program from 0x01008000-0x01094bac at 0x00080000: .....
... Unlock from 0x007e0000-0x00800000: .
... Erase from 0x007e0000-0x00800000: .
... Program from 0x01fdf000-0x01fff000 at 0x007e0000: .
... Lock from 0x007e0000-0x00800000: .
RedBoot> fis list
Name FLASH addr Mem addr Length Entry point
RedBoot 0x00000000 0x00000000 0x00040000 0x00000000
RedBoot[backup] 0x00040000 0x00040000 0x00040000 0x00000000
RedBoot config 0x007DF000 0x007DF000 0x00001000 0x00000000
FIS directory 0x007E0000 0x007E0000 0x00020000 0x00000000
kernel 0x00080000 0x01008000 0x000A0000 0x00000000
This leads to the following Linux MTD setup:
mtroot@192.168.0.14:~# cat /proc/mtd
dev: size erasesize name
mtd0: 00040000 00020000 "RedBoot"
mtd1: 00040000 00020000 "RedBoot[backup]"
mtd2: 000a0000 00020000 "kernel"
mtd3: 006bf000 00020000 "unallocated space"
mtd4: 00001000 00020000 "RedBoot config"
mtd5: 00020000 00020000 "FIS directory"
Note that there is not a 1:1 mapping to the number of RedBoot paritions to
MTD partitions as unused space also gets allocated into MTD partitions.
As an aside, the -r option when creating the Kernel entry allows you to
simply do an 'fis load kernel' to copy the image from flash into memory.
You can then do an 'fis go 0x01008000' to start Linux.
If you choose to use static partitioning instead of the RedBoot partioning:
/dev/mtd0 0x00000000 - 0x0007ffff: Boot Monitor (512k)
/dev/mtd1 0x00080000 - 0x0011ffff: Kernel Image (640K)
/dev/mtd2 0x00120000 - 0x0071ffff: File System (6M)
/dev/mtd3 0x00720000 - 0x00800000: RedBoot Reserved (896K)
To use a JFFS1/2 root FS, you need to donwload the JFFS image using either
tftp or ymodem, and then copy it to flash:
RedBoot> load -r -b 0x01000000 /tftpboot/jffs.img
Raw file loaded 0x01000000-0x01600000
RedBoot> fis create -b 0x01000000 -l 0x600000 -f 0x120000 jffs
... Erase from 0x00120000-0x00720000: ..................................
... Program from 0x01000000-0x01600000 at 0x00120000: ..................
......................
... Unlock from 0x007e0000-0x00800000: .
... Erase from 0x007e0000-0x00800000: .
... Program from 0x01fdf000-0x01fff000 at 0x007e0000: .
... Lock from 0x007e0000-0x00800000: .
RedBoot> fis list
Name FLASH addr Mem addr Length Entry point
RedBoot 0x00000000 0x00000000 0x00040000 0x00000000
RedBoot[backup] 0x00040000 0x00040000 0x00040000 0x00000000
RedBoot config 0x007DF000 0x007DF000 0x00001000 0x00000000
FIS directory 0x007E0000 0x007E0000 0x00020000 0x00000000
kernel 0x00080000 0x01008000 0x000A0000 0x01008000
jffs 0x00120000 0x00120000 0x00600000 0x00000000
This looks like this in Linux:
root@192.168.0.14:~# cat /proc/mtd
dev: size erasesize name
mtd0: 00040000 00020000 "RedBoot"
mtd1: 00040000 00020000 "RedBoot[backup]"
mtd2: 000a0000 00020000 "kernel"
mtd3: 00600000 00020000 "jffs"
mtd4: 000bf000 00020000 "unallocated space"
mtd5: 00001000 00020000 "RedBoot config"
mtd6: 00020000 00020000 "FIS directory"
You need to boot the kernel once and watch the boot messages to see how the
JFFS RedBoot partition mapped into the MTD partition scheme.
You can grab a pre-built JFFS image to use as a root file system at:
ftp://source.mvista.com/pub/xscale/iq80310/jffs.img
For detailed info on using MTD and creating a JFFS image go to:
http://www.linux-mtd.infradead.org.
For details on using RedBoot's FIS commands, type 'fis help' or consult
your RedBoot manual.
BUGS and ISSUES
-----------------------------
* As shipped from Intel, pre-production boards have two issues:
- The on board ethernet is disabled S8E1-2 is off. You will need to turn it on.
- The PCIXCAPs are configured for a 100Mhz clock, but the clock selected is
actually only 66Mhz. This causes the wrong PPL multiplier to be used and the
board only runs at 400Mhz instead of 600Mhz. The way to observe this is to
use a independent clock to time a "sleep 10" command from the prompt. If it
takes 15 seconds instead of 10, you are running at 400Mhz.
- The experimental IOP310 drivers for the AAU, DMA, etc. are not supported yet.
Contributors
-----------------------------
The port to the IQ80321 was performed by:
Rory Bolt <rorybolt@pacbell.net> - Initial port, debugging.
This port was based on the IQ80310 port with the following contributors:
Nicolas Pitre <nico@cam.org> - Initial port, cleanup, debugging
Matt Porter <mporter@mvista.com> - PCI subsystem development, debugging
Tim Sanders <tsanders@sanders.org> - Initial PCI code
Deepak Saxena <dsaxena@mvista.com> - Cleanup, debug, cache lock, PMU
The port is currently maintained by Deepak Saxena <dsaxena@mvista.com>
-----------------------------
Enjoy.
Support functions for the Intel 80310 AAU
===========================================
Dave Jiang <dave.jiang@intel.com>
Last updated: 09/18/2001
The Intel 80312 companion chip in the 80310 chipset contains an AAU. The
AAU is capable of processing up to 8 data block sources and perform XOR
operations on them. This unit is typically used to accelerated XOR
operations utilized by RAID storage device drivers such as RAID 5. This
API is designed to provide a set of functions to take adventage of the
AAU. The AAU can also be used to transfer data blocks and used as a memory
copier. The AAU transfer the memory faster than the operation performed by
using CPU copy therefore it is recommended to use the AAU for memory copy.
------------------
int aau_request(u32 *aau_context, const char *device_id);
This function allows the user the acquire the control of the the AAU. The
function will return a context of AAU to the user and allocate
an interrupt for the AAU. The user must pass the context as a parameter to
various AAU API calls.
int aau_queue_buffer(u32 aau_context, aau_head_t *listhead);
This function starts the AAU operation. The user must create a SGL
header with a SGL attached. The format is presented below. The SGL is
built from kernel memory.
/* hardware descriptor */
typedef struct _aau_desc
{
u32 NDA; /* next descriptor address [READONLY] */
u32 SAR[AAU_SAR_GROUP]; /* src addrs */
u32 DAR; /* destination addr */
u32 BC; /* byte count */
u32 DC; /* descriptor control */
u32 SARE[AAU_SAR_GROUP]; /* extended src addrs */
} aau_desc_t;
/* user SGL format */
typedef struct _aau_sgl
{
aau_desc_t aau_desc; /* AAU HW Desc */
u32 status; /* status of SGL [READONLY] */
struct _aau_sgl *next; /* pointer to next SG [READONLY] */
void *dest; /* destination addr */
void *src[AAU_SAR_GROUP]; /* source addr[4] */
void *ext_src[AAU_SAR_GROUP]; /* ext src addr[4] */
u32 total_src; /* total number of source */
} aau_sgl_t;
/* header for user SGL */
typedef struct _aau_head
{
u32 total; /* total descriptors allocated */
u32 status; /* SGL status */
aau_sgl_t *list; /* ptr to head of list */
aau_callback_t callback; /* callback func ptr */
} aau_head_t;
The function will call aau_start() and start the AAU after it queues
the SGL to the processing queue. When the function will either
a. Sleep on the wait queue aau->wait_q if no callback has been provided, or
b. Continue and then call the provided callback function when DMA interrupt
has been triggered.
int aau_suspend(u32 aau_context);
Stops/Suspends the AAU operation
int aau_free(u32 aau_context);
Frees the ownership of AAU. Called when no longer need AAU service.
aau_sgl_t * aau_get_buffer(u32 aau_context, int num_buf);
This function obtains an AAU SGL for the user. User must specify the number
of descriptors to be allocated in the chain that is returned.
void aau_return_buffer(u32 aau_context, aau_sgl_t *list);
This function returns all SGL back to the API after user is done.
int aau_memcpy(void *dest, void *src, u32 size);
This function is a short cut for user to do memory copy utilizing the AAU for
better large block memory copy vs using the CPU. This is similar to using
typical memcpy() call.
* User is responsible for the source address(es) and the destination address.
The source and destination should all be cached memory.
void aau_test()
{
u32 aau;
char dev_id[] = "AAU";
int size = 2;
int err = 0;
aau_head_t *head;
aau_sgl_t *list;
u32 i;
u32 result = 0;
void *src, *dest;
printk("Starting AAU test\n");
if((err = aau_request(&aau, dev_id))<0)
{
printk("test - AAU request failed: %d\n", err);
return;
}
else
{
printk("test - AAU request successful\n");
}
head = kmalloc(sizeof(aau_head_t), GFP_KERNEL);
head->total = size;
head->status = 0;
head->callback = NULL;
list = aau_get_buffer(aau, size);
if(!list)
{
printk("Can't get buffers\n");
return;
}
head->list = list;
src = kmalloc(1024, GFP_KERNEL);
dest = kmalloc(1024, GFP_KERNEL);
while(list)
{
list->status = 0;
list->aau_desc->SAR[0] = (u32)src;
list->aau_desc->DAR = (u32)dest;
list->aau_desc->BC = 1024;
/* see iop310-aau.h for more DCR commands */
list->aau_desc->DC = AAU_DCR_WRITE | AAU_DCR_BLKCTRL_1_DF;
if(!list->next)
{
list->aau_desc->DC = AAU_DCR_IE;
break;
}
list = list->next;
}
printk("test- Queueing buffer for AAU operation\n");
err = aau_queue_buffer(aau, head);
if(err >= 0)
{
printk("AAU Queue Buffer is done...\n");
}
else
{
printk("AAU Queue Buffer failed...: %d\n", err);
}
#if 1
printk("freeing the AAU\n");
aau_return_buffer(aau, head->list);
aau_free(aau);
kfree(src);
kfree(dest);
kfree((void *)head);
#endif
}
All Disclaimers apply. Use this at your own discretion. Neither Intel nor I
will be responsible if anything goes wrong. =)
TODO
____
* Testing
* Do zero-size AAU transfer/channel at init
so all we have to do is chainining
Support functions forthe Intel 80310 DMA channels
==================================================
Dave Jiang <dave.jiang@intel.com>
Last updated: 09/18/2001
The Intel 80310 XScale chipset provides 3 DMA channels via the 80312 I/O
companion chip. Two of them resides on the primary PCI bus and one on the
secondary PCI bus.
The DMA API provided is not compatible with the generic interface in the
ARM tree unfortunately due to how the 80312 DMACs work. Hopefully some time
in the near future a software interface can be done to bridge the differences.
The DMA API has been modeled after Nicholas Pitre's SA11x0 DMA API therefore
they will look somewhat similar.
80310 DMA API
-------------
int dma_request(dmach_t channel, const char *device_id);
This function will attempt to allocate the channel depending on what the
user requests:
IOP310_DMA_P0: PCI Primary 1
IOP310_DMA_P1: PCI Primary 2
IOP310_DMA_S0: PCI Secondary 1
/*EOF*/
Once the user allocates the DMA channel it is owned until released. Although
other users can also use the same DMA channel, but no new resources will be
allocated. The function will return the allocated channel number if successful.
int dma_queue_buffer(dmach_t channel, dma_sghead_t *listhead);
The user will construct a SGL in the form of below:
/*
* Scattered Gather DMA List for user
*/
typedef struct _dma_desc
{
u32 NDAR; /* next descriptor adress [READONLY] */
u32 PDAR; /* PCI address */
u32 PUADR; /* upper PCI address */
u32 LADR; /* local address */
u32 BC; /* byte count */
u32 DC; /* descriptor control */
} dma_desc_t;
typedef struct _dma_sgl
{
dma_desc_t dma_desc; /* DMA descriptor */
u32 status; /* descriptor status [READONLY] */
u32 data; /* user defined data */
struct _dma_sgl *next; /* next descriptor [READONLY] */
} dma_sgl_t;
/* dma sgl head */
typedef struct _dma_head
{
u32 total; /* total elements in SGL */
u32 status; /* status of sgl */
u32 mode; /* read or write mode */
dma_sgl_t *list; /* pointer to list */
dma_callback_t callback; /* callback function */
} dma_head_t;
The user shall allocate user SGL elements by calling the function:
dma_get_buffer(). This function will give the user an SGL element. The user
is responsible for creating the SGL head however. The user is also
responsible for allocating the memory for DMA data. The following code segment
shows how a DMA operation can be performed:
#include <asm/arch/iop310-dma.h>
void dma_test(void)
{
char dev_id[] = "Primary 0";
dma_head_t *sgl_head = NULL;
dma_sgl_t *sgl = NULL;
int err = 0;
int channel = -1;
u32 *test_ptr = 0;
DECLARE_WAIT_QUEUE_HEAD(wait_q);
*(IOP310_ATUCR) = (IOP310_ATUCR_PRIM_OUT_ENAB |
IOP310_ATUCR_DIR_ADDR_ENAB);
channel = dma_request(IOP310_DMA_P0, dev_id);
sgl_head = (dma_head_t *)kmalloc(sizeof(dma_head_t), GFP_KERNEL);
sgl_head->callback = NULL; /* no callback created */
sgl_head->total = 2; /* allocating 2 DMA descriptors */
sgl_head->mode = (DMA_MOD_WRITE);
sgl_head->status = 0;
/* now we get the two descriptors */
sgl = dma_get_buffer(channel, 2);
/* we set the header to point to the list we allocated */
sgl_head->list = sgl;
/* allocate 1k of DMA data */
sgl->data = (u32)kmalloc(1024, GFP_KERNEL);
/* Local address is physical */
sgl->dma_desc.LADR = (u32)virt_to_phys(sgl->data);
/* write to arbitrary location over the PCI bus */
sgl->dma_desc.PDAR = 0x00600000;
sgl->dma_desc.PUADR = 0;
sgl->dma_desc.BC = 1024;
/* set write & invalidate PCI command */
sgl->dma_desc.DC = DMA_DCR_PCI_MWI;
sgl->status = 0;
/* set a pattern */
memset(sgl->data, 0xFF, 1024);
/* User's responsibility to keep buffers cached coherent */
cpu_dcache_clean(sgl->data, sgl->data + 1024);
sgl = sgl->next;
sgl->data = (u32)kmalloc(1024, GFP_KERNEL);
sgl->dma_desc.LADR = (u32)virt_to_phys(sgl->data);
sgl->dma_desc.PDAR = 0x00610000;
sgl->dma_desc.PUADR = 0;
sgl->dma_desc.BC = 1024;
/* second descriptor has interrupt flag enabled */
sgl->dma_desc.DC = (DMA_DCR_PCI_MWI | DMA_DCR_IE);
/* must set end of chain flag */
sgl->status = DMA_END_CHAIN; /* DO NOT FORGET THIS!!!! */
memset(sgl->data, 0x0f, 1024);
/* User's responsibility to keep buffers cached coherent */
cpu_dcache_clean(sgl->data, sgl->data + 1024);
/* queuing the buffer, this function will sleep since no callback */
err = dma_queue_buffer(channel, sgl_head);
/* now we are woken from DMA complete */
/* do data operations here */
/* free DMA data if necessary */
/* return the descriptors */
dma_return_buffer(channel, sgl_head->list);
/* free the DMA */
dma_free(channel);
kfree((void *)sgl_head);
}
dma_sgl_t * dma_get_buffer(dmach_t channel, int buf_num);
This call allocates DMA descriptors for the user.
void dma_return_buffer(dmach_t channel, dma_sgl_t *list);
This call returns the allocated descriptors back to the API.
int dma_suspend(dmach_t channel);
This call suspends any DMA transfer on the given channel.
int dma_resume(dmach_t channel);
This call resumes a DMA transfer which would have been stopped through
dma_suspend().
int dma_flush_all(dmach_t channel);
This completely flushes all queued buffers and on-going DMA transfers on a
given channel. This is called when DMA channel errors have occurred.
void dma_free(dmach_t channel);
This clears all activities on a given DMA channel and releases it for future
requests.
Buffer Allocation
-----------------
It is the user's responsibility to allocate, free, and keep track of the
allocated DMA data memory. Upon calling dma_queue_buffer() the user must
relinquish the control of the buffers to the kernel and not change the
state of the buffers that it has passed to the kernel. The user will regain
the control of the buffers when it has been woken up by the bottom half of
the DMA interrupt handler. The user can allocate cached buffers or non-cached
via pci_alloc_consistent(). It is the user's responsibility to ensure that
the data is cache coherent.
*Reminder*
The user is responsble to ensure the ATU is setup properly for DMA transfers.
All Disclaimers apply. Use this at your own discretion. Neither Intel nor I
will be responsible ifanything goes wrong.
Support functions for the Intel 80310 MU
===========================================
Dave Jiang <dave.jiang@intel.com>
Last updated: 10/11/2001
The messaging unit of the IOP310 contains 4 components and is utilized for
passing messages between the PCI agents on the primary bus and the Intel(R)
80200 CPU. The four components are:
Messaging Component
Doorbell Component
Circular Queues Component
Index Registers Component
Messaging Component:
Contains 4 32bit registers, 2 in and 2 out. Writing to the registers assert
interrupt on the PCI bus or to the 80200 depend on incoming or outgoing.
int mu_msg_request(u32 *mu_context);
Request the usage of Messaging Component. mu_context is written back by the
API. The MU context is passed to other Messaging calls as a parameter.
int mu_msg_set_callback(u32 mu_context, u8 reg, mu_msg_cb_t func);
Setup the callback function for incoming messages. Callback can be setup for
outbound 0, 1, or both outbound registers.
int mu_msg_post(u32 mu_context, u32 val, u8 reg);
Posting a message in the val parameter. The reg parameter denotes whether
to use register 0, 1.
int mu_msg_free(u32 mu_context, u8 mode);
Free the usage of messaging component. mode can be specified soft or hard. In
hardmode all resources are unallocated.
Doorbell Component:
The doorbell registers contains 1 inbound and 1 outbound. Depending on the bits
being set different interrupts are asserted.
int mu_db_request(u32 *mu_context);
Request the usage of the doorbell register.
int mu_db_set_callback(u32 mu_context, mu_db_cb_t func);
Setting up the inbound callback.
void mu_db_ring(u32 mu_context, u32 mask);
Write to the outbound db register with mask.
int mu_db_free(u32 mu_context);
Free the usage of doorbell component.
Circular Queues Component:
The circular queue component has 4 circular queues. Inbound post, inbound free,
outbound post, outbound free. These queues are used to pass messages.
int mu_cq_request(u32 *mu_context, u32 q_size);
Request the usage of the queue. See code comment header for q_size. It tells
the API how big of queues to setup.
int mu_cq_inbound_init(u32 mu_context, mfa_list_t *list, u32 size,
mu_cq_cb_t func);
Init inbound queues. The user must provide a list of free message frames to
be put in inbound free queue and the callback function to handle the inbound
messages.
int mu_cq_enable(u32 mu_context);
Enables the circular queues mechanism. Called once all the setup functions
are called.
u32 mu_cq_get_frame(u32 mu_context);
Obtain the address of an outbound free frame for the user.
int mu_cq_post_frame(u32 mu_context, u32 mfa);
The user can post the frame once getting the frame and put information in the
frame.
int mu_cq_free(u32 mu_context);
Free the usage of circular queues mechanism.
Index Registers Component:
The index register provides the mechanism to receive inbound messages.
int mu_ir_request(u32 *mu_context);
Request of Index Register component usage.
int mu_ir_set_callback(u32 mu_context, mu_ir_cb_t callback);
Setting up callback for inbound messages. The callback will receive the
value of the register that IAR offsets to.
int mu_ir_free(u32 mu_context);
Free the usage of Index Registers component.
void mu_set_irq_threshold(u32 mu_context, int thresh);
Setup the IRQ threshold before relinquish processing in IRQ space. Default
is set at 10 loops.
*NOTE: Example of host driver that utilize the MU can be found in the Linux I2O
driver. Specifically i2o_pci and some functions of i2o_core. The I2O driver
only utilize the circular queues mechanism. The other 3 components are simple
enough that they can be easily setup. The MU API provides no flow control for
the messaging mechanism. Flow control of the messaging needs to be established
by a higher layer of software on the IOP or the host driver.
All Disclaimers apply. Use this at your own discretion. Neither Intel nor I
will be responsible if anything goes wrong. =)
TODO
____
Intel's XScale Microarchitecture 80312 companion processor provides a
Performance Monitoring Unit (PMON) that can be utilized to provide
information that can be useful for fine tuning of code. This text
file describes the API that's been developed for use by Linux kernel
programmers. Note that to get the most usage out of the PMON,
I highly reccomend getting the XScale reference manual from Intel[1]
and looking at chapter 12.
To use the PMON, you must #include <asm-arm/arch-iop310/pmon.h> in your
source file.
Since there's only one PMON, only one user can currently use the PMON
at a given time. To claim the PMON for usage, call iop310_pmon_claim() which
returns an identifier. When you are done using the PMON, call
iop310_pmon_release() with the id you were given earlier.
The PMON consists of 14 registers that can be used for performance measurements.
By combining different statistics, you can derive complex performance metrics.
To start the PMON, just call iop310_pmon_start(mode). Mode tells the PMON what
statistics to capture and can each be one of:
IOP310_PMU_MODE0
Performance Monitoring Disabled
IOP310_PMU_MODE1
Primary PCI bus and internal agents (bridge, dma Ch0, dam Ch1, patu)
IOP310_PMU_MODE2
Secondary PCI bus and internal agents (bridge, dma Ch0, dam Ch1, patu)
IOP310_PMU_MODE3
Secondary PCI bus and internal agents (external masters 0..2 and Intel
80312 I/O companion chip)
IOP310_PMU_MODE4
Secondary PCI bus and internal agents (external masters 3..5 and Intel
80312 I/O companion chip)
IOP310_PMU_MODE5
Intel 80312 I/O companion chip internal bus, DMA Channels and Application
Accelerator
IOP310_PMU_MODE6
Intel 80312 I/O companion chip internal bus, PATU, SATU and Intel 80200
processor
IOP310_PMU_MODE7
Intel 80312 I/O companion chip internal bus, Primary PCI bus, Secondary
PCI bus and Secondary PCI agents (external masters 0..5 & Intel 80312 I/O
companion chip)
To get the results back, call iop310_pmon_stop(&results) where results is
defined as follows:
typedef struct _iop310_pmon_result
{
u32 timestamp; /* Global Time Stamp Register */
u32 timestamp_overflow; /* Time Stamp overflow count */
u32 event_count[14]; /* Programmable Event Counter
Registers 1-14 */
u32 event_overflow[14]; /* Overflow counter for PECR1-14 */
} iop310_pmon_res_t;
--
This code is still under development, so please feel free to send patches,
questions, comments, etc to me.
Deepak Saxena <dsaxena@mvista.com>
Intel's XScale Microarchitecture provides support for locking of data
and instructions into the appropriate caches. This file provides
an overview of the API that has been developed to take advantage of this
feature from kernel space. Note that there is NO support for user space
cache locking.
For example usage of this code, grab:
ftp://source.mvista.com/pub/xscale/cache-test.c
If you have any questions, comments, patches, etc, please contact me.
Deepak Saxena <dsaxena@mvista.com>
API DESCRIPTION
I. Header File
#include <asm/xscale-lock.h>
II. Cache Capability Discovery
SYNOPSIS
int cache_query(u8 cache_type,
struct cache_capabilities *pcache);
struct cache_capabilities
{
u32 flags; /* Flags defining capabilities */
u32 cache_size; /* Cache size in K (1024 bytes) */
u32 max_lock; /* Maximum lockable region in K */
}
/*
* Flags
*/
/*
* Bit 0: Cache lockability
* Bits 1-31: Reserved for future use
*/
#define CACHE_LOCKABLE 0x00000001 /* Cache can be locked */
/*
* Cache Types
*/
#define ICACHE 0x00
#define DCACHE 0x01
DESCRIPTION
This function fills out the pcache capability identifier for the
requested cache. cache_type is either DCACHE or ICACHE. This
function is not very useful at the moment as all XScale CPU's
have the same size Cache, but is is provided for future XScale
based processors that may have larger cache sizes.
RETURN VALUE
This function returns 0 if no error occurs, otherwise it returns
a negative, errno compatible value.
-EIO Unknown hardware error
III. Cache Locking
SYNOPSIS
int cache_lock(void *addr, u32 len, u8 cache_type, const char *desc);
DESCRIPTION
This function locks a physically contigous portion of memory starting
at the virtual address pointed to by addr into the cache referenced
by cache_type.
The address of the data/instruction that is to be locked must be
aligned on a cache line boundary (L1_CACHE_ALIGNEMENT).
The desc parameter is an optional (pass NULL if not used) human readable
descriptor of the locked memory region that is used by the cache
management code to build the /proc/cache_locks table.
Note that this function does not check whether the address is valid
or not before locking it into the cache. That duty is up to the
caller. Also, it does not check for duplicate or overlaping
entries.
RETURN VALUE
If the function is successful in locking the entry into cache, a
zero is returned.
If an error occurs, an appropriate error value is returned.
-EINVAL The memory address provided was not cache line aligned
-ENOMEM Could not allocate memory to complete operation
-ENOSPC Not enough space left on cache to lock in requested region
-EIO Unknown error
III. Cache Unlocking
SYNOPSIS
int cache_unlock(void *addr)
DESCRIPTION
This function unlocks a portion of memory that was previously locked
into either the I or D cache.
RETURN VALUE
If the entry is cleanly unlocked from the cache, a 0 is returned.
In the case of an error, an appropriate error is returned.
-ENOENT No entry with given address associated with this cache
-EIO Unknown error
Intel's XScale Microarchitecture processors provide a Performance
Monitoring Unit (PMU) that can be utilized to provide information
that can be useful for fine tuning of code. This text file describes
the API that's been developed for use by Linux kernel programmers.
When I have some extra time on my hand, I will extend the code to
provide support for user mode performance monitoring (which is
probably much more useful). Note that to get the most usage out
of the PMU, I highly reccomend getting the XScale reference manual
from Intel and looking at chapter 12.
To use the PMU, you must #include <asm/xscale-pmu.h> in your source file.
Since there's only one PMU, only one user can currently use the PMU
at a given time. To claim the PMU for usage, call pmu_claim() which
returns an identifier. When you are done using the PMU, call
pmu_release() with the identifier that you were given by pmu_claim.
In addition, the PMU can only be used on XScale based systems that
provide an external timer. Systems that the PMU is currently supported
on are:
- Cyclone IQ80310
Before delving into how to use the PMU code, let's do a quick overview
of the PMU itself. The PMU consists of three registers that can be
used for performance measurements. The first is the CCNT register with
provides the number of clock cycles elapsed since the PMU was started.
The next two register, PMN0 and PMN1, are eace user programmable to
provide 1 of 20 different performance statistics. By combining different
statistics, you can derive complex performance metrics.
To start the PMU, just call pmu_start(pm0, pmn1). pmn0 and pmn1 tell
the PMU what statistics to capture and can each be one of:
EVT_ICACHE_MISS
Instruction fetches requiring access to external memory
EVT_ICACHE_NO_DELIVER
Instruction cache could not deliver an instruction. Either an
ICACHE miss or an instruction TLB miss.
EVT_ICACHE_DATA_STALL
Stall in execution due to a data dependency. This counter is
incremented each cycle in which the condition is present.
EVT_ITLB_MISS
Instruction TLB miss
EVT_DTLB_MISS
Data TLB miss
EVT_BRANCH
A branch instruction was executed and it may or may not have
changed program flow
EVT_BRANCH_MISS
A branch (B or BL instructions only) was mispredicted
EVT_INSTRUCTION
An instruction was executed
EVT_DCACHE_FULL_STALL
Stall because data cache buffers are full. Incremented on every
cycle in which condition is present.
EVT_DCACHE_FULL_STALL_CONTIG
Stall because data cache buffers are full. Incremented on every
cycle in which condition is contigous.
EVT_DCACHE_ACCESS
Data cache access (data fetch)
EVT_DCACHE_MISS
Data cache miss
EVT_DCACHE_WRITE_BACK
Data cache write back. This counter is incremented for every
1/2 line (four words) that are written back.
EVT_PC_CHANGED
Software changed the PC. This is incremented only when the
software changes the PC and there is no mode change. For example,
a MOV instruction that targets the PC would increment the counter.
An SWI would not as it triggers a mode change.
EVT_BCU_REQUEST
The Bus Control Unit(BCU) received a request from the core
EVT_BCU_FULL
The BCU request queue if full. A high value for this event means
that the BCU is often waiting for to complete on the external bus.
EVT_BCU_DRAIN
The BCU queues were drained due to either a Drain Write Buffer
command or an I/O transaction for a page that was marked as
uncacheable and unbufferable.
EVT_BCU_ECC_NO_ELOG
The BCU detected an ECC error on the memory bus but noe ELOG
register was available to to log the errors.
EVT_BCU_1_BIT_ERR
The BCU detected a 1-bit error while reading from the bus.
EVT_RMW
An RMW cycle occurred due to narrow write on ECC protected memory.
To get the results back, call pmu_stop(&results) where results is defined
as a struct pmu_results:
struct pmu_results
{
u32 ccnt; /* Clock Counter Register */
u32 ccnt_of; /
u32 pmn0; /* Performance Counter Register 0 */
u32 pmn0_of;
u32 pmn1; /* Performance Counter Register 1 */
u32 pmn1_of;
};
Pretty simple huh? Following are some examples of how to get some commonly
wanted numbers out of the PMU data. Note that since you will be dividing
things, this isn't super useful from the kernel and you need to printk the
data out to syslog. See [1] for more examples.
Instruction Cache Efficiency
pmu_start(EVT_INSTRUCTION, EVT_ICACHE_MISS);
...
pmu_stop(&results);
icache_miss_rage = results.pmn1 / results.pmn0;
cycles_per_instruction = results.ccnt / results.pmn0;
Data Cache Efficiency
pmu_start(EVT_DCACHE_ACCESS, EVT_DCACHE_MISS);
...
pmu_stop(&results);
dcache_miss_rage = results.pmn1 / results.pmn0;
Instruction Fetch Latency
pmu_start(EVT_ICACHE_NO_DELIVER, EVT_ICACHE_MISS);
...
pmu_stop(&results);
average_stall_waiting_for_instruction_fetch =
results.pmn0 / results.pmn1;
percent_stall_cycles_due_to_instruction_fetch =
results.pmn0 / results.ccnt;
ToDo:
- Add support for usermode PMU usage. This might require hooking into
the scheduler so that we pause the PMU when the task that requested
statistics is scheduled out.
--
This code is still under development, so please feel free to send patches,
questions, comments, etc to me.
Deepak Saxena <dsaxena@mvista.com>
Intel's XScale Microarchitecture provides support for locking of TLB
entries in both the instruction and data TLBs. This file provides
an overview of the API that has been developed to take advantage of this
feature from kernel space. Note that there is NO support for user space.
In general, this feature should be used in conjunction with locking
data or instructions into the appropriate caches. See the file
cache-lock.txt in this directory.
If you have any questions, comments, patches, etc, please contact me.
Deepak Saxena <dsaxena@mvista.com>
API DESCRIPTION
I. Header file
#include <asm/xscale-lock.h>
II. Locking an entry into the TLB
SYNOPSIS
xscale_tlb_lock(u8 tlb_type, u32 addr);
/*
* TLB types
*/
#define ITLB 0x0
#define DTLB 0x1
DESCRIPTION
This function locks the virtual to physical mapping for virtual
address addr into the requested TLB.
RETURN VALUE
If the entry is properly locked into the TLB, a 0 is returned.
In case of an error, an appropriate error is returned.
-ENOSPC No more entries left in the TLB
-EIO Unknown error
III. Unlocking an entry from a TLB
SYNOPSIS
xscale_tlb_unlock(u8 tlb_type, u32 addr);
DESCRIPTION
This function unlocks the entry for virtual address addr from the
specified cache.
RETURN VALUE
If the TLB entry is properly unlocked, a 0 is returned.
In case of an error, an appropriate error is returned.
-ENOENT No entry for given address in specified TLB
......@@ -92,3 +92,7 @@ values:
cpu - number of the affected CPU
old - old frequency
new - new frequency
If the cpufreq core detects the frequency has changed while the system
was suspended, these notifiers are called with CPUFREQ_RESUMECHANGE as
second argument.
......@@ -609,7 +609,9 @@ source "drivers/acorn/block/Kconfig"
source "net/Kconfig"
if ARCH_CLPS7500 || ARCH_IOP3XX || ARCH_IXP4XX || ARCH_L7200 || ARCH_LH7A40X || ARCH_FTVPCI || ARCH_PXA || ARCH_RPC || ARCH_S3C2410 || ARCH_SA1100 || ARCH_SHARK || FOOTBRIDGE
source "drivers/ide/Kconfig"
endif
source "drivers/scsi/Kconfig"
......
......@@ -47,7 +47,7 @@
#define MAX_IRQ_CNT 100000
static volatile unsigned long irq_err_count;
static spinlock_t irq_controller_lock;
static spinlock_t irq_controller_lock = SPIN_LOCK_UNLOCKED;
static LIST_HEAD(irq_pending);
struct irqdesc irq_desc[NR_IRQS];
......
......@@ -152,10 +152,10 @@ static int integrator_set_target(struct cpufreq_policy *policy,
return 0;
}
static int integrator_cpufreq_init(struct cpufreq_policy *policy)
static unsigned int integrator_get(unsigned int cpu)
{
unsigned long cpus_allowed;
unsigned int cpu = policy->cpu;
unsigned int current_freq;
u_int cm_osc;
struct icst525_vco vco;
......@@ -175,15 +175,22 @@ static int integrator_cpufreq_init(struct cpufreq_policy *policy)
vco.v = cm_osc & 255;
vco.r = 22;
current_freq = icst525_khz(&cclk_params, vco); /* current freq */
set_cpus_allowed(current, cpus_allowed);
return current_freq;
}
static int integrator_cpufreq_init(struct cpufreq_policy *policy)
{
/* set default policy and cpuinfo */
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
policy->cpuinfo.max_freq = 160000;
policy->cpuinfo.min_freq = 12000;
policy->cpuinfo.transition_latency = 1000000; /* 1 ms, assumed */
policy->cur = policy->min = policy->max =
icst525_khz(&cclk_params, vco); /* current freq */
set_cpus_allowed(current, cpus_allowed);
policy->cur = policy->min = policy->max = integrator_get(policy->cpu);
return 0;
}
......@@ -191,6 +198,7 @@ static int integrator_cpufreq_init(struct cpufreq_policy *policy)
static struct cpufreq_driver integrator_driver = {
.verify = integrator_verify_policy,
.target = integrator_set_target,
.get = integrator_get,
.init = integrator_cpufreq_init,
.name = "integrator",
};
......
......@@ -8,10 +8,30 @@ menu "Intel IXP4xx Implementation Options"
comment "IXP4xx Platforms"
config ARCH_AVILA
bool "Avila"
depends on ARCH_IXP4XX
help
Say 'Y' here if you want your kernel to support the Gateworks
Avila Network Platform. For more information on this platform,
see Documentation/arm/IXP4xx.
config ARCH_ADI_COYOTE
bool "Coyote"
depends on ARCH_IXP4XX
help
Say 'Y' here if you want your kernel to support the ADI
Engineering Coyote Gateway Reference Platform. For more
information on this platform, see Documentation/arm/IXP4xx.
config ARCH_IXDP425
bool "Support for Intel IXDP425 (Richfield) Development Platform"
bool "IXDP425"
depends on ARCH_IXP4XX
help
Say 'Y' here if you want your kernel to support Intel's
IXDP425 Development Platform (Also known as Richfield).
For more information on this platform, see Documentation/arm/IXP4xx.
#
# IXCDP1100 is the exact same HW as IXDP425, but with a different machine
# number from the bootloader due to marketing monkeys, so we just enable it
......@@ -23,16 +43,12 @@ config ARCH_IXCDP1100
default y
config ARCH_PRPMC1100
bool "Support for Motorola PrPMC 1100 Platform"
depends on ARCH_IXP4XX
config ARCH_ADI_COYOTE
bool "Support for ADI Engineering Coyote Gateway Reference Platform"
depends on ARCH_IXP4XX
config ARCH_AVILA
bool "Support for Gateworks Avila Network Platform"
bool "PrPMC1100"
depends on ARCH_IXP4XX
help
Say 'Y' here if you want your kernel to support the Motorola
PrPCM1100 Processor Mezanine Module. For more information on
this platform, see Documentation/arm/IXP4xx.
#
# Avila and IXDP share the same source for now. Will change in future
......
......@@ -168,7 +168,7 @@ static void ixp4xx_irq_unmask(unsigned int irq)
* manual. If edge-triggered, need to move it to the mask_ack.
* Nobody seems to be using the edge-triggered mode on the GPIOs.
*/
if (line > 0)
if (line >= 0)
gpio_line_isr_clear(line);
*IXP4XX_ICMR |= (1 << irq);
......
......@@ -180,7 +180,7 @@ static int sa1100_target(struct cpufreq_policy *policy,
unsigned int target_freq,
unsigned int relation)
{
unsigned int cur = sa11x0_getspeed();
unsigned int cur = sa11x0_getspeed(0);
unsigned int new_ppcr;
struct cpufreq_freqs freqs;
......@@ -221,7 +221,7 @@ static int __init sa1100_cpu_init(struct cpufreq_policy *policy)
{
if (policy->cpu != 0)
return -EINVAL;
policy->cur = policy->min = policy->max = sa11x0_getspeed();
policy->cur = policy->min = policy->max = sa11x0_getspeed(0);
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
policy->cpuinfo.min_freq = 59000;
policy->cpuinfo.max_freq = 287000;
......@@ -230,15 +230,17 @@ static int __init sa1100_cpu_init(struct cpufreq_policy *policy)
}
static struct cpufreq_driver sa1100_driver = {
.flags = (CPUFREQ_PANIC_OUTOFSYNC |
CPUFREQ_PANIC_RESUME_OUTOFSYNC),
.verify = sa11x0_verify_speed,
.target = sa1100_target,
.get = sa11x0_getspeed,
.init = sa1100_cpu_init,
.name = "sa1100",
};
static int __init sa1100_dram_init(void)
{
cpufreq_gov_userspace_init();
if ((processor_id & CPU_SA1100_MASK) == CPU_SA1100_ID)
return cpufreq_register_driver(&sa1100_driver);
else
......
......@@ -238,7 +238,7 @@ static int sa1110_target(struct cpufreq_policy *policy,
return -EINVAL;
}
freqs.old = sa11x0_getspeed();
freqs.old = sa11x0_getspeed(0);
freqs.new = sa11x0_ppcr_to_freq(ppcr);
freqs.cpu = 0;
......@@ -320,7 +320,7 @@ static int __init sa1110_cpu_init(struct cpufreq_policy *policy)
{
if (policy->cpu != 0)
return -EINVAL;
policy->cur = policy->min = policy->max = sa11x0_getspeed();
policy->cur = policy->min = policy->max = sa11x0_getspeed(0);
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
policy->cpuinfo.min_freq = 59000;
policy->cpuinfo.max_freq = 287000;
......@@ -329,8 +329,11 @@ static int __init sa1110_cpu_init(struct cpufreq_policy *policy)
}
static struct cpufreq_driver sa1110_driver = {
.flags = (CPUFREQ_PANIC_OUTOFSYNC |
CPUFREQ_PANIC_RESUME_OUTOFSYNC),
.verify = sa11x0_verify_speed,
.target = sa1110_target,
.get = sa11x0_getspeed,
.init = sa1110_cpu_init,
.name = "sa1110",
};
......@@ -354,8 +357,6 @@ static int __init sa1110_clk_init(void)
sdram->tck, sdram->trcd, sdram->trp,
sdram->twr, sdram->refresh, sdram->cas_latency);
cpufreq_gov_userspace_init();
memcpy(&sdram_params, sdram, sizeof(sdram_params));
return cpufreq_register_driver(&sa1110_driver);
......
......@@ -96,11 +96,13 @@ int sa11x0_verify_speed(struct cpufreq_policy *policy)
return 0;
}
unsigned int sa11x0_getspeed(void)
unsigned int sa11x0_getspeed(unsigned int cpu)
{
if (cpu)
return 0;
return cclk_frequency_100khz[PPCR & 0xf] * 100;
}
EXPORT_SYMBOL(sa11x0_getspeed);
#else
/*
* We still need to provide this so building without cpufreq works.
......
......@@ -22,5 +22,5 @@ struct cpufreq_policy;
extern unsigned int sa11x0_freq_to_ppcr(unsigned int khz);
extern int sa11x0_verify_speed(struct cpufreq_policy *policy);
extern unsigned int sa11x0_getspeed(void);
extern unsigned int sa11x0_getspeed(unsigned int cpu);
extern unsigned int sa11x0_ppcr_to_freq(unsigned int idx);
......@@ -77,7 +77,7 @@ void show_mem(void)
else if (!page_count(page))
free++;
else
shared += atomic_read(&page->count) - 1;
shared += page_count(page) - 1;
page++;
} while (page < end);
}
......
......@@ -20,6 +20,7 @@
* We use MMU protection domains to trap any attempt to access the bank
* that is not currently mapped. (This isn't fully implemented yet.)
*/
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/vmalloc.h>
......
......@@ -2,15 +2,15 @@ obj-$(CONFIG_X86_POWERNOW_K6) += powernow-k6.o
obj-$(CONFIG_X86_POWERNOW_K7) += powernow-k7.o
obj-$(CONFIG_X86_POWERNOW_K8) += powernow-k8.o
obj-$(CONFIG_X86_LONGHAUL) += longhaul.o
obj-$(CONFIG_X86_P4_CLOCKMOD) += p4-clockmod.o
obj-$(CONFIG_ELAN_CPUFREQ) += elanfreq.o
obj-$(CONFIG_X86_LONGRUN) += longrun.o
obj-$(CONFIG_X86_GX_SUSPMOD) += gx-suspmod.o
obj-$(CONFIG_X86_ACPI_CPUFREQ) += acpi.o
obj-$(CONFIG_X86_SPEEDSTEP_ICH) += speedstep-ich.o
obj-$(CONFIG_X86_SPEEDSTEP_CENTRINO) += speedstep-centrino.o
obj-$(CONFIG_X86_SPEEDSTEP_LIB) += speedstep-lib.o
obj-$(CONFIG_X86_SPEEDSTEP_SMI) += speedstep-smi.o
obj-$(CONFIG_X86_ACPI_CPUFREQ) += acpi.o
obj-$(CONFIG_X86_P4_CLOCKMOD) += p4-clockmod.o
ifdef CONFIG_X86_ACPI_CPUFREQ
ifdef CONFIG_ACPI_DEBUG
......
......@@ -77,7 +77,7 @@ static struct cpufreq_frequency_table elanfreq_table[] = {
* and have the rest of the chip running with 33 MHz.
*/
static unsigned int elanfreq_get_cpu_frequency(void)
static unsigned int elanfreq_get_cpu_frequency(unsigned int cpu)
{
u8 clockspeed_reg; /* Clock Speed Register */
......@@ -121,7 +121,7 @@ static void elanfreq_set_cpu_state (unsigned int state) {
struct cpufreq_freqs freqs;
freqs.old = elanfreq_get_cpu_frequency();
freqs.old = elanfreq_get_cpu_frequency(0);
freqs.new = elan_multiplier[state].clock;
freqs.cpu = 0; /* elanfreq.c is UP only driver */
......@@ -209,7 +209,7 @@ static int elanfreq_cpu_init(struct cpufreq_policy *policy)
/* max freq */
if (!max_freq)
max_freq = elanfreq_get_cpu_frequency();
max_freq = elanfreq_get_cpu_frequency(0);
/* table init */
for (i=0; (elanfreq_table[i].frequency != CPUFREQ_TABLE_END); i++) {
......@@ -220,7 +220,7 @@ static int elanfreq_cpu_init(struct cpufreq_policy *policy)
/* cpuinfo and default policy values */
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
policy->cur = elanfreq_get_cpu_frequency();
policy->cur = elanfreq_get_cpu_frequency(0);
result = cpufreq_frequency_table_cpuinfo(policy, elanfreq_table);
if (result)
......@@ -267,6 +267,7 @@ static struct freq_attr* elanfreq_attr[] = {
static struct cpufreq_driver elanfreq_driver = {
.get = elanfreq_get_cpu_frequency,
.verify = elanfreq_verify,
.target = elanfreq_target,
.init = elanfreq_cpu_init,
......
......@@ -215,7 +215,7 @@ static __init struct pci_dev *gx_detect_chipset(void)
*
* Finds out at which efficient frequency the Cyrix MediaGX/NatSemi Geode CPU runs.
*/
static int gx_get_cpuspeed(void)
static unsigned int gx_get_cpuspeed(unsigned int cpu)
{
if ((gx_params->pci_suscfg & SUSMOD) == 0)
return stock_freq;
......@@ -271,7 +271,7 @@ static void gx_set_cpuspeed(unsigned int khz)
freqs.cpu = 0;
freqs.old = gx_get_cpuspeed();
freqs.old = gx_get_cpuspeed(0);
new_khz = gx_validate_speed(khz, &gx_params->on_duration, &gx_params->off_duration);
......@@ -405,7 +405,7 @@ static int cpufreq_gx_target(struct cpufreq_policy *policy,
static int cpufreq_gx_cpu_init(struct cpufreq_policy *policy)
{
int maxfreq, curfreq;
unsigned int maxfreq, curfreq;
if (!policy || policy->cpu != 0)
return -ENODEV;
......@@ -419,7 +419,7 @@ static int cpufreq_gx_cpu_init(struct cpufreq_policy *policy)
maxfreq = 30000 * gx_freq_mult[getCx86(CX86_DIR1) & 0x0f];
}
stock_freq = maxfreq;
curfreq = gx_get_cpuspeed();
curfreq = gx_get_cpuspeed(0);
dprintk("cpu max frequency is %d.\n", maxfreq);
dprintk("cpu current frequency is %dkHz.\n",curfreq);
......@@ -446,6 +446,7 @@ static int cpufreq_gx_cpu_init(struct cpufreq_policy *policy)
* MediaGX/Geode GX initialize cpufreq driver
*/
static struct cpufreq_driver gx_suspmod_driver = {
.get = gx_get_cpuspeed,
.verify = cpufreq_gx_verify,
.target = cpufreq_gx_target,
.init = cpufreq_gx_cpu_init,
......
......@@ -82,6 +82,10 @@ static int longhaul_get_cpu_mult (void)
if (lo & (1<<27))
invalue+=16;
}
if (longhaul_version==4) {
if (lo & (1<<27))
invalue+=16;
}
return eblcr_table[invalue];
}
......@@ -158,6 +162,22 @@ static void longhaul_setstate (unsigned int clock_ratio_index)
longhaul.bits.RevisionKey = 3;
wrmsrl (MSR_VIA_LONGHAUL, longhaul.val);
break;
case 4:
rdmsrl (MSR_VIA_LONGHAUL, longhaul.val);
longhaul.bits.SoftBusRatio = clock_ratio_index & 0xf;
longhaul.bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
longhaul.bits.EnableSoftBusRatio = 1;
longhaul.bits.RevisionKey = 0x0;
wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
__hlt();
rdmsrl (MSR_VIA_LONGHAUL, longhaul.val);
longhaul.bits.EnableSoftBusRatio = 0;
longhaul.bits.RevisionKey = 0xf;
wrmsrl (MSR_VIA_LONGHAUL, longhaul.val);
break;
}
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
......@@ -207,7 +227,7 @@ static int guess_fsb(int maxmult)
static int __init longhaul_get_ranges (void)
{
struct cpuinfo_x86 *c = cpu_data;
unsigned long invalue;
unsigned long invalue,invalue2;
unsigned int minmult=0, maxmult=0;
unsigned int multipliers[32]= {
50,30,40,100,55,35,45,95,90,70,80,60,120,75,85,65,
......@@ -234,8 +254,6 @@ static int __init longhaul_get_ranges (void)
case 2:
rdmsrl (MSR_VIA_LONGHAUL, longhaul.val);
//TODO: Nehemiah may have borken MaxMHzBR.
// need to extrapolate from FSB.
invalue = longhaul.bits.MaxMHzBR;
if (longhaul.bits.MaxMHzBR4)
invalue += 16;
......@@ -258,6 +276,38 @@ static int __init longhaul_get_ranges (void)
break;
}
break;
case 4:
rdmsrl (MSR_VIA_LONGHAUL, longhaul.val);
//TODO: Nehemiah may have borken MaxMHzBR.
// need to extrapolate from FSB.
invalue2 = longhaul.bits.MinMHzBR;
invalue = longhaul.bits.MaxMHzBR;
if (longhaul.bits.MaxMHzBR4)
invalue += 16;
maxmult=multipliers[invalue];
maxmult=longhaul_get_cpu_mult();
printk(KERN_INFO PFX " invalue: %ld maxmult: %d \n", invalue, maxmult);
printk(KERN_INFO PFX " invalue2: %ld \n", invalue2);
minmult=50;
switch (longhaul.bits.MaxMHzFSB) {
case 0x0: fsb=133;
break;
case 0x1: fsb=100;
break;
case 0x2: printk (KERN_INFO PFX "Invalid (reserved) FSB!\n");
return -EINVAL;
case 0x3: fsb=66;
break;
}
break;
}
dprintk (KERN_INFO PFX "MinMult=%d.%dx MaxMult=%d.%dx\n",
......@@ -380,6 +430,13 @@ static int longhaul_target (struct cpufreq_policy *policy,
return 0;
}
static unsigned int longhaul_get(unsigned int cpu)
{
if (cpu)
return 0;
return (calc_speed (longhaul_get_cpu_mult(), fsb));
}
static int __init longhaul_cpu_init (struct cpufreq_policy *policy)
{
struct cpuinfo_x86 *c = cpu_data;
......@@ -423,12 +480,27 @@ static int __init longhaul_cpu_init (struct cpufreq_policy *policy)
break;
case 9:
cpuname = "C3 'Nehemiah' [C5N]";
longhaul_version=2;
longhaul_version=4;
numscales=32;
memcpy (clock_ratio, nehemiah_clock_ratio, sizeof(nehemiah_clock_ratio));
memcpy (eblcr_table, nehemiah_eblcr, sizeof(nehemiah_eblcr));
switch (c->x86_mask) {
case 0 ... 1:
cpuname = "C3 'Nehemiah A' [C5N]";
memcpy (clock_ratio, nehemiah_a_clock_ratio, sizeof(nehemiah_a_clock_ratio));
memcpy (eblcr_table, nehemiah_a_eblcr, sizeof(nehemiah_a_eblcr));
break;
case 2 ... 4:
cpuname = "C3 'Nehemiah B' [C5N]";
memcpy (clock_ratio, nehemiah_b_clock_ratio, sizeof(nehemiah_b_clock_ratio));
memcpy (eblcr_table, nehemiah_b_eblcr, sizeof(nehemiah_b_eblcr));
break;
case 5 ... 15:
cpuname = "C3 'Nehemiah C' [C5N]";
memcpy (clock_ratio, nehemiah_c_clock_ratio, sizeof(nehemiah_c_clock_ratio));
memcpy (eblcr_table, nehemiah_c_eblcr, sizeof(nehemiah_c_eblcr));
break;
}
break;
default:
cpuname = "Unknown";
......@@ -472,6 +544,7 @@ static struct freq_attr* longhaul_attr[] = {
static struct cpufreq_driver longhaul_driver = {
.verify = longhaul_verify,
.target = longhaul_target,
.get = longhaul_get,
.init = longhaul_cpu_init,
.exit = longhaul_cpu_exit,
.name = "longhaul",
......
......@@ -234,14 +234,15 @@ static int __initdata ezrat_eblcr[32] = {
/*
* VIA C3 Nehemiah */
static int __initdata nehemiah_clock_ratio[32] = {
static int __initdata nehemiah_a_clock_ratio[32] = {
100, /* 0000 -> 10.0x */
160, /* 0001 -> 16.0x */
-1, /* 0010 -> RESERVED */
-1, /* 0010 -> RESERVED */
90, /* 0011 -> 9.0x */
95, /* 0100 -> 9.5x */
-1, /* 0101 -> RESERVED */
-1, /* 0110 -> RESERVED */
-1, /* 0101 -> RESERVED */
-1, /* 0110 -> RESERVED */
55, /* 0111 -> 5.5x */
60, /* 1000 -> 6.0x */
70, /* 1001 -> 7.0x */
......@@ -250,8 +251,42 @@ static int __initdata nehemiah_clock_ratio[32] = {
65, /* 1100 -> 6.5x */
75, /* 1101 -> 7.5x */
85, /* 1110 -> 8.5x */
120, /* 1111 -> 12.0x */
120, /* 1111 -> 12.0x */
100, /* 0000 -> 10.0x */
-1, /* 0001 -> RESERVED */
120, /* 0010 -> 12.0x */
90, /* 0011 -> 9.0x */
105, /* 0100 -> 10.5x */
115, /* 0101 -> 11.5x */
125, /* 0110 -> 12.5x */
135, /* 0111 -> 13.5x */
140, /* 1000 -> 14.0x */
150, /* 1001 -> 15.0x */
160, /* 1010 -> 16.0x */
130, /* 1011 -> 13.0x */
145, /* 1100 -> 14.5x */
155, /* 1101 -> 15.5x */
-1, /* 1110 -> RESERVED (13.0x) */
120, /* 1111 -> 12.0x */
};
static int __initdata nehemiah_b_clock_ratio[32] = {
100, /* 0000 -> 10.0x */
160, /* 0001 -> 16.0x */
-1, /* 0010 -> RESERVED */
90, /* 0011 -> 9.0x */
95, /* 0100 -> 9.5x */
-1, /* 0101 -> RESERVED */
-1, /* 0110 -> RESERVED */
55, /* 0111 -> 5.5x */
60, /* 1000 -> 6.0x */
70, /* 1001 -> 7.0x */
80, /* 1010 -> 8.0x */
50, /* 1011 -> 5.0x */
65, /* 1100 -> 6.5x */
75, /* 1101 -> 7.5x */
85, /* 1110 -> 8.5x */
120, /* 1111 -> 12.0x */
100, /* 0000 -> 10.0x */
110, /* 0001 -> 11.0x */
120, /* 0010 -> 12.0x */
......@@ -266,18 +301,88 @@ static int __initdata nehemiah_clock_ratio[32] = {
130, /* 1011 -> 13.0x */
145, /* 1100 -> 14.5x */
155, /* 1101 -> 15.5x */
-1, /* 1110 -> RESERVED */
-1, /* 1110 -> RESERVED (13.0x) */
120, /* 1111 -> 12.0x */
};
static int __initdata nehemiah_eblcr[32] = {
static int __initdata nehemiah_c_clock_ratio[32] = {
100, /* 0000 -> 10.0x */
160, /* 0001 -> 16.0x */
40, /* 0010 -> RESERVED */
90, /* 0011 -> 9.0x */
95, /* 0100 -> 9.5x */
-1, /* 0101 -> RESERVED */
45, /* 0110 -> RESERVED */
55, /* 0111 -> 5.5x */
60, /* 1000 -> 6.0x */
70, /* 1001 -> 7.0x */
80, /* 1010 -> 8.0x */
50, /* 1011 -> 5.0x */
65, /* 1100 -> 6.5x */
75, /* 1101 -> 7.5x */
85, /* 1110 -> 8.5x */
120, /* 1111 -> 12.0x */
100, /* 0000 -> 10.0x */
110, /* 0001 -> 11.0x */
120, /* 0010 -> 12.0x */
90, /* 0011 -> 9.0x */
105, /* 0100 -> 10.5x */
115, /* 0101 -> 11.5x */
125, /* 0110 -> 12.5x */
135, /* 0111 -> 13.5x */
140, /* 1000 -> 14.0x */
150, /* 1001 -> 15.0x */
160, /* 1010 -> 16.0x */
130, /* 1011 -> 13.0x */
145, /* 1100 -> 14.5x */
155, /* 1101 -> 15.5x */
-1, /* 1110 -> RESERVED (13.0x) */
120, /* 1111 -> 12.0x */
};
static int __initdata nehemiah_a_eblcr[32] = {
50, /* 0000 -> 5.0x */
160, /* 0001 -> 16.0x */
-1, /* 0010 -> RESERVED */
-1, /* 0010 -> RESERVED */
100, /* 0011 -> 10.0x */
55, /* 0100 -> 5.5x */
-1, /* 0101 -> RESERVED */
-1, /* 0110 -> RESERVED */
-1, /* 0101 -> RESERVED */
-1, /* 0110 -> RESERVED */
95, /* 0111 -> 9.5x */
90, /* 1000 -> 9.0x */
70, /* 1001 -> 7.0x */
80, /* 1010 -> 8.0x */
60, /* 1011 -> 6.0x */
120, /* 1100 -> 12.0x */
75, /* 1101 -> 7.5x */
85, /* 1110 -> 8.5x */
65, /* 1111 -> 6.5x */
90, /* 0000 -> 9.0x */
-1, /* 0001 -> RESERVED */
120, /* 0010 -> 12.0x */
100, /* 0011 -> 10.0x */
135, /* 0100 -> 13.5x */
115, /* 0101 -> 11.5x */
125, /* 0110 -> 12.5x */
105, /* 0111 -> 10.5x */
130, /* 1000 -> 13.0x */
150, /* 1001 -> 15.0x */
160, /* 1010 -> 16.0x */
140, /* 1011 -> 14.0x */
120, /* 1100 -> 12.0x */
155, /* 1101 -> 15.5x */
-1, /* 1110 -> RESERVED (13.0x) */
145 /* 1111 -> 14.5x */
/* end of table */
};
static int __initdata nehemiah_b_eblcr[32] = {
50, /* 0000 -> 5.0x */
160, /* 0001 -> 16.0x */
-1, /* 0010 -> RESERVED */
100, /* 0011 -> 10.0x */
55, /* 0100 -> 5.5x */
-1, /* 0101 -> RESERVED */
-1, /* 0110 -> RESERVED */
95, /* 0111 -> 9.5x */
90, /* 1000 -> 9.0x */
70, /* 1001 -> 7.0x */
......@@ -287,7 +392,6 @@ static int __initdata nehemiah_eblcr[32] = {
75, /* 1101 -> 7.5x */
85, /* 1110 -> 8.5x */
65, /* 1111 -> 6.5x */
90, /* 0000 -> 9.0x */
110, /* 0001 -> 11.0x */
120, /* 0010 -> 12.0x */
......@@ -302,9 +406,46 @@ static int __initdata nehemiah_eblcr[32] = {
140, /* 1011 -> 14.0x */
120, /* 1100 -> 12.0x */
155, /* 1101 -> 15.5x */
-1, /* 1110 -> RESERVED */
-1, /* 1111 -> RESERVED */
-1, /* 1110 -> RESERVED (13.0x) */
145 /* 1111 -> 14.5x */
/* end of table */
};
static int __initdata nehemiah_c_eblcr[32] = {
50, /* 0000 -> 5.0x */
160, /* 0001 -> 16.0x */
40, /* 0010 -> RESERVED */
100, /* 0011 -> 10.0x */
55, /* 0100 -> 5.5x */
-1, /* 0101 -> RESERVED */
45, /* 0110 -> RESERVED */
95, /* 0111 -> 9.5x */
90, /* 1000 -> 9.0x */
70, /* 1001 -> 7.0x */
80, /* 1010 -> 8.0x */
60, /* 1011 -> 6.0x */
120, /* 1100 -> 12.0x */
75, /* 1101 -> 7.5x */
85, /* 1110 -> 8.5x */
65, /* 1111 -> 6.5x */
90, /* 0000 -> 9.0x */
110, /* 0001 -> 11.0x */
120, /* 0010 -> 12.0x */
100, /* 0011 -> 10.0x */
135, /* 0100 -> 13.5x */
115, /* 0101 -> 11.5x */
125, /* 0110 -> 12.5x */
105, /* 0111 -> 10.5x */
130, /* 1000 -> 13.0x */
150, /* 1001 -> 15.0x */
160, /* 1010 -> 16.0x */
140, /* 1011 -> 14.0x */
120, /* 1100 -> 12.0x */
155, /* 1101 -> 15.5x */
-1, /* 1110 -> RESERVED (13.0x) */
145 /* 1111 -> 14.5x */
/* end of table */
};
/*
* Voltage scales. Div/Mod by 1000 to get actual voltage.
* Which scale to use depends on the VRM type in use.
......
......@@ -46,11 +46,16 @@ static void __init longrun_get_policy(struct cpufreq_policy *policy)
rdmsr(MSR_TMTA_LONGRUN_CTRL, msr_lo, msr_hi);
msr_lo &= 0x0000007F;
msr_hi &= 0x0000007F;
policy->min = longrun_low_freq + msr_lo *
((longrun_high_freq - longrun_low_freq) / 100);
policy->max = longrun_low_freq + msr_hi *
((longrun_high_freq - longrun_low_freq) / 100);
if ( longrun_high_freq <= longrun_low_freq ) {
/* Assume degenerate Longrun table */
policy->min = policy->max = longrun_high_freq;
} else {
policy->min = longrun_low_freq + msr_lo *
((longrun_high_freq - longrun_low_freq) / 100);
policy->max = longrun_low_freq + msr_hi *
((longrun_high_freq - longrun_low_freq) / 100);
}
policy->cpu = 0;
}
......@@ -70,10 +75,15 @@ static int longrun_set_policy(struct cpufreq_policy *policy)
if (!policy)
return -EINVAL;
pctg_lo = (policy->min - longrun_low_freq) /
((longrun_high_freq - longrun_low_freq) / 100);
pctg_hi = (policy->max - longrun_low_freq) /
((longrun_high_freq - longrun_low_freq) / 100);
if ( longrun_high_freq <= longrun_low_freq ) {
/* Assume degenerate Longrun table */
pctg_lo = pctg_hi = 100;
} else {
pctg_lo = (policy->min - longrun_low_freq) /
((longrun_high_freq - longrun_low_freq) / 100);
pctg_hi = (policy->max - longrun_low_freq) /
((longrun_high_freq - longrun_low_freq) / 100);
}
if (pctg_hi > 100)
pctg_hi = 100;
......@@ -128,6 +138,17 @@ static int longrun_verify_policy(struct cpufreq_policy *policy)
return 0;
}
static unsigned int longrun_get(unsigned int cpu)
{
u32 eax, ebx, ecx, edx;
if (cpu)
return 0;
cpuid(0x80860007, &eax, &ebx, &ecx, &edx);
return (eax * 1000);
}
/**
* longrun_determine_freqs - determines the lowest and highest possible core frequency
......@@ -250,8 +271,10 @@ static int __init longrun_cpu_init(struct cpufreq_policy *policy)
static struct cpufreq_driver longrun_driver = {
.flags = CPUFREQ_CONST_LOOPS,
.verify = longrun_verify_policy,
.setpolicy = longrun_set_policy,
.get = longrun_get,
.init = longrun_cpu_init,
.name = "longrun",
.owner = THIS_MODULE,
......
......@@ -51,55 +51,16 @@ enum {
static int has_N44_O17_errata[NR_CPUS];
static unsigned int stock_freq;
static struct cpufreq_driver p4clockmod_driver;
static unsigned int cpufreq_p4_get(unsigned int cpu);
static int cpufreq_p4_setdc(unsigned int cpu, unsigned int newstate)
{
u32 l, h;
cpumask_t cpus_allowed, affected_cpu_map;
struct cpufreq_freqs freqs;
int j;
if (!cpu_online(cpu) || (newstate > DC_DISABLE) ||
(newstate == DC_RESV))
if (!cpu_online(cpu) || (newstate > DC_DISABLE) || (newstate == DC_RESV))
return -EINVAL;
/* switch to physical CPU where state is to be changed*/
cpus_allowed = current->cpus_allowed;
/* only run on CPU to be set, or on its sibling */
#ifdef CONFIG_SMP
affected_cpu_map = cpu_sibling_map[cpu];
#else
affected_cpu_map = cpumask_of_cpu(cpu);
#endif
set_cpus_allowed(current, affected_cpu_map);
BUG_ON(!cpu_isset(smp_processor_id(), affected_cpu_map));
/* get current state */
rdmsr(MSR_IA32_THERM_CONTROL, l, h);
if (l & 0x10) {
l = l >> 1;
l &= 0x7;
} else
l = DC_DISABLE;
if (l == newstate) {
set_cpus_allowed(current, cpus_allowed);
return 0;
} else if (l == DC_RESV) {
printk(KERN_ERR PFX "BIG FAT WARNING: currently in invalid setting\n");
}
/* notifiers */
freqs.old = stock_freq * l / 8;
freqs.new = stock_freq * newstate / 8;
for_each_cpu(j) {
if (cpu_isset(j, affected_cpu_map)) {
freqs.cpu = j;
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
}
}
rdmsr(MSR_IA32_THERM_STATUS, l, h);
#if 0
if (l & 0x01)
......@@ -125,16 +86,6 @@ static int cpufreq_p4_setdc(unsigned int cpu, unsigned int newstate)
wrmsr(MSR_IA32_THERM_CONTROL, l, h);
}
set_cpus_allowed(current, cpus_allowed);
/* notifiers */
for_each_cpu(j) {
if (cpu_isset(j, affected_cpu_map)) {
freqs.cpu = j;
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
}
}
return 0;
}
......@@ -158,11 +109,59 @@ static int cpufreq_p4_target(struct cpufreq_policy *policy,
unsigned int relation)
{
unsigned int newstate = DC_RESV;
struct cpufreq_freqs freqs;
cpumask_t cpus_allowed, affected_cpu_map;
int i;
if (cpufreq_frequency_table_target(policy, &p4clockmod_table[0], target_freq, relation, &newstate))
return -EINVAL;
cpufreq_p4_setdc(policy->cpu, p4clockmod_table[newstate].index);
freqs.old = cpufreq_p4_get(policy->cpu);
freqs.new = stock_freq * p4clockmod_table[newstate].index / 8;
if (freqs.new == freqs.old)
return 0;
/* switch to physical CPU where state is to be changed*/
cpus_allowed = current->cpus_allowed;
/* only run on CPU to be set, or on its sibling */
#ifdef CONFIG_SMP
affected_cpu_map = cpu_sibling_map[policy->cpu];
#else
affected_cpu_map = cpumask_of_cpu(policy->cpu);
#endif
/* notifiers */
for_each_cpu(i) {
if (cpu_isset(i, affected_cpu_map)) {
freqs.cpu = i;
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
}
}
/* run on each logical CPU, see section 13.15.3 of IA32 Intel Architecture Software
* Developer's Manual, Volume 3
*/
for_each_cpu(i) {
if (cpu_isset(i, affected_cpu_map)) {
cpumask_t this_cpu = cpumask_of_cpu(i);
set_cpus_allowed(current, this_cpu);
BUG_ON(smp_processor_id() != i);
cpufreq_p4_setdc(i, p4clockmod_table[newstate].index);
}
}
set_cpus_allowed(current, cpus_allowed);
/* notifiers */
for_each_cpu(i) {
if (cpu_isset(i, affected_cpu_map)) {
freqs.cpu = i;
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
}
}
return 0;
}
......@@ -177,11 +176,23 @@ static int cpufreq_p4_verify(struct cpufreq_policy *policy)
static unsigned int cpufreq_p4_get_frequency(struct cpuinfo_x86 *c)
{
if ((c->x86 == 0x06) && (c->x86_model == 0x09)) {
/* Pentium M */
/* Pentium M (Banias) */
printk(KERN_WARNING PFX "Warning: Pentium M detected. "
"The speedstep_centrino module offers voltage scaling"
" in addition of frequency scaling. You should use "
"that instead of p4-clockmod, if possible.\n");
return speedstep_get_processor_frequency(SPEEDSTEP_PROCESSOR_PM);
}
if ((c->x86 == 0x06) && (c->x86_model == 0x13)) {
/* Pentium M (Dothan) */
printk(KERN_WARNING PFX "Warning: Pentium M detected. "
"The speedstep_centrino module offers voltage scaling"
" in addition of frequency scaling. You should use "
"that instead of p4-clockmod, if possible.\n");
/* on P-4s, the TSC runs with constant frequency independent wether
* throttling is active or not. */
p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS;
return speedstep_get_processor_frequency(SPEEDSTEP_PROCESSOR_PM);
}
......@@ -190,6 +201,10 @@ static unsigned int cpufreq_p4_get_frequency(struct cpuinfo_x86 *c)
return 0;
}
/* on P-4s, the TSC runs with constant frequency independent wether
* throttling is active or not. */
p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS;
if (speedstep_detect_processor() == SPEEDSTEP_PROCESSOR_P4M) {
printk(KERN_WARNING PFX "Warning: Pentium 4-M detected. "
"The speedstep-ich or acpi cpufreq modules offer "
......@@ -249,6 +264,33 @@ static int cpufreq_p4_cpu_exit(struct cpufreq_policy *policy)
return 0;
}
static unsigned int cpufreq_p4_get(unsigned int cpu)
{
cpumask_t cpus_allowed, affected_cpu_map;
u32 l, h;
cpus_allowed = current->cpus_allowed;
affected_cpu_map = cpumask_of_cpu(cpu);
set_cpus_allowed(current, affected_cpu_map);
BUG_ON(!cpu_isset(smp_processor_id(), affected_cpu_map));
rdmsr(MSR_IA32_THERM_CONTROL, l, h);
set_cpus_allowed(current, cpus_allowed);
if (l & 0x10) {
l = l >> 1;
l &= 0x7;
} else
l = DC_DISABLE;
if (l != DC_DISABLE)
return (stock_freq * l / 8);
return stock_freq;
}
static struct freq_attr* p4clockmod_attr[] = {
&cpufreq_freq_attr_scaling_available_freqs,
NULL,
......@@ -259,6 +301,7 @@ static struct cpufreq_driver p4clockmod_driver = {
.target = cpufreq_p4_target,
.init = cpufreq_p4_cpu_init,
.exit = cpufreq_p4_cpu_exit,
.get = cpufreq_p4_get,
.name = "p4-clockmod",
.owner = THIS_MODULE,
.attr = p4clockmod_attr,
......
......@@ -185,6 +185,11 @@ static int powernow_k6_cpu_exit(struct cpufreq_policy *policy)
return 0;
}
static unsigned int powernow_k6_get(unsigned int cpu)
{
return busfreq * powernow_k6_get_cpu_multiplier();
}
static struct freq_attr* powernow_k6_attr[] = {
&cpufreq_freq_attr_scaling_available_freqs,
NULL,
......@@ -195,6 +200,7 @@ static struct cpufreq_driver powernow_k6_driver = {
.target = powernow_k6_target,
.init = powernow_k6_cpu_init,
.exit = powernow_k6_cpu_exit,
.get = powernow_k6_get,
.name = "powernow-k6",
.owner = THIS_MODULE,
.attr = powernow_k6_attr,
......
......@@ -540,6 +540,20 @@ static int __init fixup_sgtc(void)
return sgtc;
}
static unsigned int powernow_get(unsigned int cpu)
{
union msr_fidvidstatus fidvidstatus;
unsigned int cfid;
if (cpu)
return 0;
rdmsrl (MSR_K7_FID_VID_STATUS, fidvidstatus.val);
cfid = fidvidstatus.bits.CFID;
return (fsb * fid_codes[cfid] / 10);
}
static int __init powernow_cpu_init (struct cpufreq_policy *policy)
{
union msr_fidvidstatus fidvidstatus;
......@@ -590,7 +604,7 @@ static int __init powernow_cpu_init (struct cpufreq_policy *policy)
policy->cpuinfo.transition_latency = 20 * latency / fsb;
policy->cur = maximum_speed;
policy->cur = powernow_get(0);
cpufreq_frequency_table_get_attr(powernow_table, policy->cpu);
......@@ -610,6 +624,7 @@ static struct freq_attr* powernow_table_attr[] = {
static struct cpufreq_driver powernow_driver = {
.verify = powernow_verify,
.target = powernow_target,
.get = powernow_get,
.init = powernow_cpu_init,
.exit = powernow_cpu_exit,
.name = "powernow-k7",
......
......@@ -32,14 +32,14 @@
#include <asm/io.h>
#include <asm/delay.h>
#ifdef CONFIG_ACPI_PROCESSOR
#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE)
#include <linux/acpi.h>
#include <acpi/processor.h>
#endif
#define PFX "powernow-k8: "
#define BFX PFX "BIOS error: "
#define VERSION "version 1.00.08b"
#define VERSION "version 1.00.09b"
#include "powernow-k8.h"
/* serialize freq changes */
......@@ -450,13 +450,10 @@ static int check_supported_cpu(unsigned int cpu)
goto out;
eax = cpuid_eax(CPUID_PROCESSOR_SIGNATURE);
if ((eax & CPUID_XFAM_MOD) == ATHLON64_XFAM_MOD) {
dprintk(KERN_DEBUG PFX "AMD Althon 64 Processor found\n");
} else if ((eax & CPUID_XFAM_MOD) == OPTERON_XFAM_MOD) {
dprintk(KERN_DEBUG PFX "AMD Opteron Processor found\n");
} else {
printk(KERN_INFO PFX
"AMD Athlon 64 or AMD Opteron processor required\n");
if (((eax & CPUID_USE_XFAM_XMOD) != CPUID_USE_XFAM_XMOD) ||
((eax & CPUID_XFAM) != CPUID_XFAM_K8) ||
((eax & CPUID_XMOD) > CPUID_XMOD_REV_E)) {
printk(KERN_INFO PFX "Processor cpuid %x not supported\n", eax);
goto out;
}
......@@ -524,11 +521,12 @@ static void print_basics(struct powernow_k8_data *data)
{
int j;
for (j = 0; j < data->numps; j++) {
printk(KERN_INFO PFX " %d : fid 0x%x (%d MHz), vid 0x%x (%d mV)\n", j,
data->powernow_table[j].index & 0xff,
data->powernow_table[j].frequency/1000,
data->powernow_table[j].index >> 8,
find_millivolts_from_vid(data, data->powernow_table[j].index >> 8));
if (data->powernow_table[j].frequency != CPUFREQ_ENTRY_INVALID)
printk(KERN_INFO PFX " %d : fid 0x%x (%d MHz), vid 0x%x (%d mV)\n", j,
data->powernow_table[j].index & 0xff,
data->powernow_table[j].frequency/1000,
data->powernow_table[j].index >> 8,
find_millivolts_from_vid(data, data->powernow_table[j].index >> 8));
}
if (data->batps)
printk(KERN_INFO PFX "Only %d pstates on battery\n", data->batps);
......@@ -666,7 +664,7 @@ static int find_psb_table(struct powernow_k8_data *data)
return -ENODEV;
}
#ifdef CONFIG_ACPI_PROCESSOR
#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE)
static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned int index)
{
if (!data->acpi_data.state_count)
......@@ -723,7 +721,14 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
/* verify frequency is OK */
if ((powernow_table[i].frequency > (MAX_FREQ * 1000)) ||
(powernow_table[i].frequency < (MIN_FREQ * 1000))) {
dprintk(KERN_INFO PFX "invalid freq %u kHz\n", powernow_table[i].frequency);
dprintk(KERN_INFO PFX "invalid freq %u kHz, ignoring\n", powernow_table[i].frequency);
powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID;
continue;
}
/* verify voltage is OK - BIOSs are using "off" to indicate invalid */
if (vid == 0x1f) {
dprintk(KERN_INFO PFX "invalid vid %u, ignoring\n", vid);
powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID;
continue;
}
......@@ -1025,6 +1030,32 @@ static int __exit powernowk8_cpu_exit (struct cpufreq_policy *pol)
return 0;
}
static unsigned int powernowk8_get (unsigned int cpu)
{
struct powernow_k8_data *data = powernow_data[cpu];
cpumask_t oldmask = current->cpus_allowed;
unsigned int khz = 0;
set_cpus_allowed(current, cpumask_of_cpu(cpu));
if (smp_processor_id() != cpu) {
printk(KERN_ERR PFX "limiting to CPU %d failed in powernowk8_get\n", cpu);
set_cpus_allowed(current, oldmask);
return 0;
}
preempt_disable();
if (query_current_values_with_pending_wait(data))
goto out;
khz = find_khz_freq_from_fid(data->currfid);
out:
preempt_enable_no_resched();
set_cpus_allowed(current, oldmask);
return khz;
}
static struct freq_attr* powernow_k8_attr[] = {
&cpufreq_freq_attr_scaling_available_freqs,
NULL,
......@@ -1035,6 +1066,7 @@ static struct cpufreq_driver cpufreq_amd64_driver = {
.target = powernowk8_target,
.init = powernowk8_cpu_init,
.exit = powernowk8_cpu_exit,
.get = powernowk8_get,
.name = "powernow-k8",
.owner = THIS_MODULE,
.attr = powernow_k8_attr,
......
......@@ -29,7 +29,7 @@ struct powernow_k8_data {
* frequency is in kHz */
struct cpufreq_frequency_table *powernow_table;
#ifdef CONFIG_ACPI_PROCESSOR
#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE)
/* the acpi table needs to be kept. it's only available if ACPI was
* used to determine valid frequency/vid/fid states */
struct acpi_processor_performance acpi_data;
......@@ -38,13 +38,15 @@ struct powernow_k8_data {
/* processor's cpuid instruction support */
#define CPUID_PROCESSOR_SIGNATURE 1 /* function 1 */
#define CPUID_XFAM_MOD 0x0ff00ff0 /* extended fam, fam + model */
#define ATHLON64_XFAM_MOD 0x00000f40 /* extended fam, fam + model */
#define OPTERON_XFAM_MOD 0x00000f50 /* extended fam, fam + model */
#define CPUID_GET_MAX_CAPABILITIES 0x80000000
#define CPUID_FREQ_VOLT_CAPABILITIES 0x80000007
#define P_STATE_TRANSITION_CAPABLE 6
#define CPUID_PROCESSOR_SIGNATURE 1 /* function 1 */
#define CPUID_XFAM 0x0ff00000 /* extended family */
#define CPUID_XFAM_K8 0
#define CPUID_XMOD 0x000f0000 /* extended model */
#define CPUID_XMOD_REV_E 0x00020000
#define CPUID_USE_XFAM_XMOD 0x00000f00
#define CPUID_GET_MAX_CAPABILITIES 0x80000000
#define CPUID_FREQ_VOLT_CAPABILITIES 0x80000007
#define P_STATE_TRANSITION_CAPABLE 6
/* Model Specific Registers for p-state transitions. MSRs are 64-bit. For */
/* writes (wrmsr - opcode 0f 30), the register number is placed in ecx, and */
......
......@@ -38,13 +38,37 @@
#define dprintk(msg...) do { } while(0)
#endif
struct cpu_id
{
__u8 x86; /* CPU family */
__u8 x86_vendor; /* CPU vendor */
__u8 x86_model; /* model */
__u8 x86_mask; /* stepping */
};
static const struct cpu_id cpu_id_banias = {
.x86_vendor = X86_VENDOR_INTEL,
.x86 = 6,
.x86_model = 9,
.x86_mask = 5,
};
static const struct cpu_id cpu_id_dothan_a1 = {
.x86_vendor = X86_VENDOR_INTEL,
.x86 = 6,
.x86_model = 13,
.x86_mask = 1,
};
struct cpu_model
{
const struct cpu_id *cpu_id;
const char *model_name;
unsigned max_freq; /* max clock in kHz */
struct cpufreq_frequency_table *op_points; /* clock/voltage pairs */
};
static int centrino_verify_cpu_id(struct cpuinfo_x86 *c, const struct cpu_id *x);
/* Operating points for current CPU */
static struct cpu_model *centrino_model;
......@@ -67,8 +91,8 @@ static struct cpu_model *centrino_model;
* M.
*/
/* Ultra Low Voltage Intel Pentium M processor 900MHz */
static struct cpufreq_frequency_table op_900[] =
/* Ultra Low Voltage Intel Pentium M processor 900MHz (Banias) */
static struct cpufreq_frequency_table banias_900[] =
{
OP(600, 844),
OP(800, 988),
......@@ -76,8 +100,8 @@ static struct cpufreq_frequency_table op_900[] =
{ .frequency = CPUFREQ_TABLE_END }
};
/* Ultra Low Voltage Intel Pentium M processor 1000MHz */
static struct cpufreq_frequency_table op_1000[] =
/* Ultra Low Voltage Intel Pentium M processor 1000MHz (Banias) */
static struct cpufreq_frequency_table banias_1000[] =
{
OP(600, 844),
OP(800, 972),
......@@ -86,8 +110,8 @@ static struct cpufreq_frequency_table op_1000[] =
{ .frequency = CPUFREQ_TABLE_END }
};
/* Low Voltage Intel Pentium M processor 1.10GHz */
static struct cpufreq_frequency_table op_1100[] =
/* Low Voltage Intel Pentium M processor 1.10GHz (Banias) */
static struct cpufreq_frequency_table banias_1100[] =
{
OP( 600, 956),
OP( 800, 1020),
......@@ -98,8 +122,8 @@ static struct cpufreq_frequency_table op_1100[] =
};
/* Low Voltage Intel Pentium M processor 1.20GHz */
static struct cpufreq_frequency_table op_1200[] =
/* Low Voltage Intel Pentium M processor 1.20GHz (Banias) */
static struct cpufreq_frequency_table banias_1200[] =
{
OP( 600, 956),
OP( 800, 1004),
......@@ -110,8 +134,8 @@ static struct cpufreq_frequency_table op_1200[] =
{ .frequency = CPUFREQ_TABLE_END }
};
/* Intel Pentium M processor 1.30GHz */
static struct cpufreq_frequency_table op_1300[] =
/* Intel Pentium M processor 1.30GHz (Banias) */
static struct cpufreq_frequency_table banias_1300[] =
{
OP( 600, 956),
OP( 800, 1260),
......@@ -121,8 +145,8 @@ static struct cpufreq_frequency_table op_1300[] =
{ .frequency = CPUFREQ_TABLE_END }
};
/* Intel Pentium M processor 1.40GHz */
static struct cpufreq_frequency_table op_1400[] =
/* Intel Pentium M processor 1.40GHz (Banias) */
static struct cpufreq_frequency_table banias_1400[] =
{
OP( 600, 956),
OP( 800, 1180),
......@@ -132,8 +156,8 @@ static struct cpufreq_frequency_table op_1400[] =
{ .frequency = CPUFREQ_TABLE_END }
};
/* Intel Pentium M processor 1.50GHz */
static struct cpufreq_frequency_table op_1500[] =
/* Intel Pentium M processor 1.50GHz (Banias) */
static struct cpufreq_frequency_table banias_1500[] =
{
OP( 600, 956),
OP( 800, 1116),
......@@ -144,8 +168,8 @@ static struct cpufreq_frequency_table op_1500[] =
{ .frequency = CPUFREQ_TABLE_END }
};
/* Intel Pentium M processor 1.60GHz */
static struct cpufreq_frequency_table op_1600[] =
/* Intel Pentium M processor 1.60GHz (Banias) */
static struct cpufreq_frequency_table banias_1600[] =
{
OP( 600, 956),
OP( 800, 1036),
......@@ -156,8 +180,8 @@ static struct cpufreq_frequency_table op_1600[] =
{ .frequency = CPUFREQ_TABLE_END }
};
/* Intel Pentium M processor 1.70GHz */
static struct cpufreq_frequency_table op_1700[] =
/* Intel Pentium M processor 1.70GHz (Banias) */
static struct cpufreq_frequency_table banias_1700[] =
{
OP( 600, 956),
OP( 800, 1004),
......@@ -169,26 +193,31 @@ static struct cpufreq_frequency_table op_1700[] =
};
#undef OP
#define _CPU(max, name) \
{ "Intel(R) Pentium(R) M processor " name "MHz", (max)*1000, op_##max }
#define CPU(max) _CPU(max, #max)
#define _BANIAS(cpuid, max, name) \
{ .cpu_id = cpuid, \
.model_name = "Intel(R) Pentium(R) M processor " name "MHz", \
.max_freq = (max)*1000, \
.op_points = banias_##max, \
}
#define BANIAS(max) _BANIAS(&cpu_id_banias, max, #max)
/* CPU models, their operating frequency range, and freq/voltage
operating points */
static struct cpu_model models[] =
{
_CPU( 900, " 900"),
CPU(1000),
CPU(1100),
CPU(1200),
CPU(1300),
CPU(1400),
CPU(1500),
CPU(1600),
CPU(1700),
_BANIAS(&cpu_id_banias, 900, " 900"),
BANIAS(1000),
BANIAS(1100),
BANIAS(1200),
BANIAS(1300),
BANIAS(1400),
BANIAS(1500),
BANIAS(1600),
BANIAS(1700),
{ 0, }
};
#undef CPU
#undef _BANIAS
#undef BANIAS
static int centrino_cpu_init_table(struct cpufreq_policy *policy)
{
......@@ -196,7 +225,8 @@ static int centrino_cpu_init_table(struct cpufreq_policy *policy)
struct cpu_model *model;
for(model = models; model->model_name != NULL; model++)
if (strcmp(cpu->x86_model_id, model->model_name) == 0)
if ((strcmp(cpu->x86_model_id, model->model_name) == 0) &&
(!centrino_verify_cpu_id(cpu, model->cpu_id)))
break;
if (model->model_name == NULL) {
printk(KERN_INFO PFX "no support for CPU model \"%s\": "
......@@ -217,6 +247,16 @@ static int centrino_cpu_init_table(struct cpufreq_policy *policy)
static inline int centrino_cpu_init_table(struct cpufreq_policy *policy) { return -ENODEV; }
#endif /* CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE */
static int centrino_verify_cpu_id(struct cpuinfo_x86 *c, const struct cpu_id *x)
{
if ((c->x86 == x->x86) &&
(c->x86_vendor == x->x86_vendor) &&
(c->x86_model == x->x86_model) &&
(c->x86_mask == x->x86_mask))
return 0;
return -ENODEV;
}
/* Extract clock in kHz from PERF_CTL value */
static unsigned extract_clock(unsigned msr)
{
......@@ -225,9 +265,11 @@ static unsigned extract_clock(unsigned msr)
}
/* Return the current CPU frequency in kHz */
static unsigned get_cur_freq(void)
static unsigned int get_cur_freq(unsigned int cpu)
{
unsigned l, h;
if (cpu)
return 0;
rdmsr(MSR_IA32_PERF_STATUS, l, h);
return extract_clock(l);
......@@ -322,7 +364,7 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy)
goto err_kfree;
}
cur_freq = get_cur_freq();
cur_freq = get_cur_freq(0);
for (i=0; i<p.state_count; i++) {
centrino_model->op_points[i].index = p.states[i].control;
......@@ -357,13 +399,8 @@ static int centrino_cpu_init(struct cpufreq_policy *policy)
if (!cpu_has(cpu, X86_FEATURE_EST))
return -ENODEV;
/* Only Intel Pentium M stepping 5 for now - add new CPUs as
they appear after making sure they use PERF_CTL in the same
way. */
if (cpu->x86_vendor != X86_VENDOR_INTEL ||
cpu->x86 != 6 ||
cpu->x86_model != 9 ||
cpu->x86_mask != 5) {
if ((centrino_verify_cpu_id(cpu, &cpu_id_banias)) &&
(centrino_verify_cpu_id(cpu, &cpu_id_dothan_a1))) {
printk(KERN_INFO PFX "found unsupported CPU with Enhanced SpeedStep: "
"send /proc/cpuinfo to " MAINTAINER "\n");
return -ENODEV;
......@@ -391,10 +428,10 @@ static int centrino_cpu_init(struct cpufreq_policy *policy)
}
}
freq = get_cur_freq();
freq = get_cur_freq(0);
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
policy->cpuinfo.transition_latency = 10; /* 10uS transition latency */
policy->cpuinfo.transition_latency = 10000; /* 10uS transition latency */
policy->cur = freq;
dprintk(KERN_INFO PFX "centrino_cpu_init: policy=%d cur=%dkHz\n",
......@@ -516,6 +553,7 @@ static struct cpufreq_driver centrino_driver = {
.exit = centrino_cpu_exit,
.verify = centrino_verify,
.target = centrino_target,
.get = get_cur_freq,
.attr = centrino_attr,
.owner = THIS_MODULE,
};
......
......@@ -179,7 +179,7 @@ static int speedstep_activate (void)
/**
* speedstep_detect_chipset - detect the Southbridge which contains SpeedStep logic
*
* Detects PIIX4, ICH2-M and ICH3-M so far. The pci_dev points to
* Detects ICH2-M, ICH3-M and ICH4-M so far. The pci_dev points to
* the LPC bridge / PM module which contains all power-management
* functions. Returns the SPEEDSTEP_CHIPSET_-number for the detected
* chipset, or zero on failure.
......@@ -322,6 +322,10 @@ static int speedstep_cpu_exit(struct cpufreq_policy *policy)
return 0;
}
static unsigned int speedstep_get(unsigned int cpu)
{
return speedstep_get_processor_frequency(speedstep_processor);
}
static struct freq_attr* speedstep_attr[] = {
&cpufreq_freq_attr_scaling_available_freqs,
......@@ -335,6 +339,7 @@ static struct cpufreq_driver speedstep_driver = {
.target = speedstep_target,
.init = speedstep_cpu_init,
.exit = speedstep_cpu_exit,
.get = speedstep_get,
.owner = THIS_MODULE,
.attr = speedstep_attr,
};
......
......@@ -36,6 +36,8 @@ static int smi_port = 0;
static int smi_cmd = 0;
static unsigned int smi_sig = 0;
/* info about the processor */
static unsigned int speedstep_processor = 0;
/*
* There are only two frequency states for each processor. Values
......@@ -258,9 +260,10 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy)
&speedstep_freqs[SPEEDSTEP_HIGH].frequency);
if (result) {
/* fall back to speedstep_lib.c dection mechanism: try both states out */
unsigned int speedstep_processor = speedstep_detect_processor();
dprintk(KERN_INFO PFX "could not detect low and high frequencies by SMI call.\n");
if (!speedstep_processor)
speedstep_processor = speedstep_detect_processor();
if (!speedstep_processor)
return -ENODEV;
......@@ -298,13 +301,23 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy)
return 0;
}
static int speedstep_cpu_exit(struct cpufreq_policy *policy)
{
cpufreq_frequency_table_put_attr(policy->cpu);
return 0;
}
static unsigned int speedstep_get(unsigned int cpu)
{
if (cpu)
return -ENODEV;
if (!speedstep_processor)
speedstep_processor = speedstep_detect_processor();
if (!speedstep_processor)
return 0;
return speedstep_get_processor_frequency(speedstep_processor);
}
static int speedstep_resume(struct cpufreq_policy *policy)
{
......@@ -327,6 +340,7 @@ static struct cpufreq_driver speedstep_driver = {
.target = speedstep_target,
.init = speedstep_cpu_init,
.exit = speedstep_cpu_exit,
.get = speedstep_get,
.resume = speedstep_resume,
.owner = THIS_MODULE,
.attr = speedstep_attr,
......
......@@ -27,6 +27,8 @@ static unsigned long hpet_last;
struct timer_opts timer_tsc;
#endif
static inline void cpufreq_delayed_get(void);
int tsc_disable __initdata = 0;
extern spinlock_t i8253_lock;
......@@ -241,6 +243,9 @@ static void mark_offset_tsc(void)
clock_fallback();
}
/* ... but give the TSC a fair chance */
if (lost_count > 25)
cpufreq_delayed_get();
} else
lost_count = 0;
/* update the monotonic base value */
......@@ -324,15 +329,40 @@ static void mark_offset_tsc_hpet(void)
#ifdef CONFIG_CPU_FREQ
#include <linux/workqueue.h>
static unsigned int cpufreq_delayed_issched = 0;
static unsigned int cpufreq_init = 0;
static struct work_struct cpufreq_delayed_get_work;
static void handle_cpufreq_delayed_get(void *v)
{
unsigned int cpu;
for_each_online_cpu(cpu) {
cpufreq_get(cpu);
}
cpufreq_delayed_issched = 0;
}
/* if we notice lost ticks, schedule a call to cpufreq_get() as it tries
* to verify the CPU frequency the timing core thinks the CPU is running
* at is still correct.
*/
static inline void cpufreq_delayed_get(void)
{
if (cpufreq_init && !cpufreq_delayed_issched) {
cpufreq_delayed_issched = 1;
printk(KERN_DEBUG "Losing some ticks... checking if CPU frequency changed.\n");
schedule_work(&cpufreq_delayed_get_work);
}
}
/* If the CPU frequency is scaled, TSC-based delays will need a different
* loops_per_jiffy value to function properly. An exception to this
* are modern Intel Pentium 4 processors, where the TSC runs at a constant
* speed independent of frequency scaling.
* loops_per_jiffy value to function properly.
*/
static unsigned int ref_freq = 0;
static unsigned long loops_per_jiffy_ref = 0;
static unsigned int variable_tsc = 1;
#ifndef CONFIG_SMP
static unsigned long fast_gettimeoffset_ref = 0;
......@@ -356,14 +386,15 @@ time_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
}
if ((val == CPUFREQ_PRECHANGE && freq->old < freq->new) ||
(val == CPUFREQ_POSTCHANGE && freq->old > freq->new)) {
if (variable_tsc)
(val == CPUFREQ_POSTCHANGE && freq->old > freq->new) ||
(val == CPUFREQ_RESUMECHANGE)) {
if (!(freq->flags & CPUFREQ_CONST_LOOPS))
cpu_data[freq->cpu].loops_per_jiffy = cpufreq_scale(loops_per_jiffy_ref, ref_freq, freq->new);
#ifndef CONFIG_SMP
if (cpu_khz)
cpu_khz = cpufreq_scale(cpu_khz_ref, ref_freq, freq->new);
if (use_tsc) {
if (variable_tsc) {
if (!(freq->flags & CPUFREQ_CONST_LOOPS)) {
fast_gettimeoffset_quotient = cpufreq_scale(fast_gettimeoffset_ref, freq->new, ref_freq);
set_cyc2ns_scale(cpu_khz/1000);
}
......@@ -382,14 +413,17 @@ static struct notifier_block time_cpufreq_notifier_block = {
static int __init cpufreq_tsc(void)
{
/* P4 and above CPU TSC freq doesn't change when CPU frequency changes*/
if ((boot_cpu_data.x86 >= 15) && (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL))
variable_tsc = 0;
return cpufreq_register_notifier(&time_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER);
int ret;
INIT_WORK(&cpufreq_delayed_get_work, handle_cpufreq_delayed_get, NULL);
ret = cpufreq_register_notifier(&time_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER);
if (!ret)
cpufreq_init = 1;
return ret;
}
core_initcall(cpufreq_tsc);
#else /* CONFIG_CPU_FREQ */
static inline void cpufreq_delayed_get(void) { return; }
#endif
......
......@@ -897,7 +897,7 @@ static int __init pcibios_irq_init(void)
{
DBG("PCI: IRQ init\n");
if (pcibios_enable_irq)
if (pcibios_enable_irq || raw_pci_ops == NULL)
return 0;
pirq_table = pirq_find_routing_table();
......
......@@ -1431,7 +1431,6 @@ static void siccuart_close(struct tty_struct *tty, struct file *filp)
save_flags(flags); cli();
if (tty_hung_up_p(filp)) {
MOD_DEC_USE_COUNT;
restore_flags(flags);
return;
}
......@@ -1452,7 +1451,6 @@ static void siccuart_close(struct tty_struct *tty, struct file *filp)
state->count = 0;
}
if (state->count) {
MOD_DEC_USE_COUNT;
restore_flags(flags);
return;
}
......@@ -1495,7 +1493,6 @@ static void siccuart_close(struct tty_struct *tty, struct file *filp)
}
info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
wake_up_interruptible(&info->close_wait);
MOD_DEC_USE_COUNT;
}
static void siccuart_wait_until_sent(struct tty_struct *tty, int timeout)
......@@ -1685,9 +1682,7 @@ static int siccuart_open(struct tty_struct *tty, struct file *filp)
// is this a line that we've got?
MOD_INC_USE_COUNT;
if (line >= SERIAL_SICC_NR) {
MOD_DEC_USE_COUNT;
return -ENODEV;
}
......@@ -1707,7 +1702,6 @@ static int siccuart_open(struct tty_struct *tty, struct file *filp)
if (tmp_buf)
free_page(page);
else if (!page) {
MOD_DEC_USE_COUNT;
return -ENOMEM;
}
tmp_buf = (u_char *)page;
......@@ -1720,7 +1714,6 @@ static int siccuart_open(struct tty_struct *tty, struct file *filp)
(info->flags & ASYNC_CLOSING)) {
if (info->flags & ASYNC_CLOSING)
interruptible_sleep_on(&info->close_wait);
MOD_DEC_USE_COUNT;
return -EAGAIN;
}
......@@ -1729,13 +1722,11 @@ static int siccuart_open(struct tty_struct *tty, struct file *filp)
*/
retval = siccuart_startup(info);
if (retval) {
MOD_DEC_USE_COUNT;
return retval;
}
retval = block_til_ready(tty, filp, info);
if (retval) {
MOD_DEC_USE_COUNT;
return retval;
}
......@@ -1778,6 +1769,7 @@ int __init siccuart_init(void)
return -ENOMEM;
printk("IBM Vesta SICC serial port driver V 0.1 by Yudong Yang and Yi Ge / IBM CRL .\n");
siccnormal_driver->driver_name = "serial_sicc";
siccnormal_driver->owner = THIS_MODULE;
siccnormal_driver->name = SERIAL_SICC_NAME;
siccnormal_driver->major = SERIAL_SICC_MAJOR;
siccnormal_driver->minor_start = SERIAL_SICC_MINOR;
......
......@@ -592,9 +592,7 @@ static _INLINE_ void check_modem_status(struct async_struct *info)
#ifdef SERIAL_DEBUG_OPEN
printk("scheduling hangup...");
#endif
MOD_INC_USE_COUNT;
if (schedule_work(&info->tqueue_hangup) == 0)
MOD_DEC_USE_COUNT;
schedule_work(&info->tqueue_hangup);
}
}
if (info->flags & ASYNC_CTS_FLOW) {
......@@ -723,7 +721,6 @@ static void do_serial_hangup(void *private_)
tty = info->tty;
if (tty)
tty_hangup(tty);
MOD_DEC_USE_COUNT;
}
/*static void rs_8xx_timer(void)
......@@ -1689,7 +1686,6 @@ static void rs_8xx_close(struct tty_struct *tty, struct file * filp)
if (tty_hung_up_p(filp)) {
DBG_CNT("before DEC-hung");
MOD_DEC_USE_COUNT;
restore_flags(flags);
return;
}
......@@ -1716,7 +1712,6 @@ static void rs_8xx_close(struct tty_struct *tty, struct file * filp)
}
if (state->count) {
DBG_CNT("before DEC-2");
MOD_DEC_USE_COUNT;
restore_flags(flags);
return;
}
......@@ -1770,7 +1765,6 @@ static void rs_8xx_close(struct tty_struct *tty, struct file * filp)
}
info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
wake_up_interruptible(&info->close_wait);
MOD_DEC_USE_COUNT;
restore_flags(flags);
}
......@@ -2021,7 +2015,6 @@ static int rs_8xx_open(struct tty_struct *tty, struct file * filp)
if (retval)
return retval;
MOD_INC_USE_COUNT;
retval = block_til_ready(tty, filp, info);
if (retval) {
#ifdef SERIAL_DEBUG_OPEN
......@@ -2530,6 +2523,7 @@ static int __init rs_8xx_init(void)
/* Initialize the tty_driver structure */
serial_driver->owner = THIS_MODULE;
serial_driver->driver_name = "serial";
serial_driver->devfs_name = "tts/";
serial_driver->name = "ttyS";
......
......@@ -1456,21 +1456,10 @@ static void cs_mksound(unsigned int hz, unsigned int ticks)
restore_flags(flags);
}
static void CS_open(void)
{
MOD_INC_USE_COUNT;
}
static void CS_release(void)
{
MOD_DEC_USE_COUNT;
}
static MACHINE mach_cs4218 = {
.owner = THIS_MODULE,
.name = "HIOX CS4218",
.name2 = "Built-in Sound",
.open = CS_open,
.release = CS_release,
.dma_alloc = CS_Alloc,
.dma_free = CS_Free,
.irqinit = CS_IrqInit,
......
......@@ -583,9 +583,7 @@ static _INLINE_ void check_modem_status(struct async_struct *info)
#ifdef SERIAL_DEBUG_OPEN
printk("scheduling hangup...");
#endif
MOD_INC_USE_COUNT;
if (schedule_task(&info->tqueue_hangup) == 0)
MOD_DEC_USE_COUNT;
schedule_task(&info->tqueue_hangup);
}
}
if (info->flags & ASYNC_CTS_FLOW) {
......@@ -719,7 +717,6 @@ static void do_serial_hangup(void *private_)
tty = info->tty;
if (tty)
tty_hangup(tty);
MOD_DEC_USE_COUNT;
}
/*static void rs_8xx_timer(void)
......@@ -1664,7 +1661,6 @@ static void rs_8xx_close(struct tty_struct *tty, struct file * filp)
if (tty_hung_up_p(filp)) {
DBG_CNT("before DEC-hung");
MOD_DEC_USE_COUNT;
restore_flags(flags);
return;
}
......@@ -1691,7 +1687,6 @@ static void rs_8xx_close(struct tty_struct *tty, struct file * filp)
}
if (state->count) {
DBG_CNT("before DEC-2");
MOD_DEC_USE_COUNT;
restore_flags(flags);
return;
}
......@@ -1746,7 +1741,6 @@ static void rs_8xx_close(struct tty_struct *tty, struct file * filp)
}
info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
wake_up_interruptible(&info->close_wait);
MOD_DEC_USE_COUNT;
restore_flags(flags);
}
......@@ -2008,14 +2002,12 @@ static int rs_8xx_open(struct tty_struct *tty, struct file * filp)
if (retval)
return retval;
MOD_INC_USE_COUNT;
retval = block_til_ready(tty, filp, info);
if (retval) {
#ifdef SERIAL_DEBUG_OPEN
printk("rs_open returning after block_til_ready with %d\n",
retval);
#endif
MOD_DEC_USE_COUNT;
return retval;
}
......@@ -2520,6 +2512,7 @@ static int __init rs_8xx_init(void)
/* Initialize the tty_driver structure */
serial_driver->owner = THIS_MODULE;
serial_driver->driver_name = "serial";
serial_driver->devfs_name = "tts/";
serial_driver->name = "ttyS";
......
......@@ -41,7 +41,7 @@ end-y := elf
# if present on 'classic' PPC.
cacheflag-y := -DCLEAR_CACHES=""
# This file will flush / disable the L2, and L3 if present.
clear_L2_L3 := $(boot)/simple/clear.S
clear_L2_L3 := $(srctree)/$(boot)/simple/clear.S
#
# See arch/ppc/kconfig and arch/ppc/platforms/Kconfig
......@@ -125,7 +125,7 @@ EXTRA_AFLAGS := $(extra-aflags-y)
AFLAGS_head.o += $(cacheflag-y)
# Linker args. This specifies where the image will be run at.
LD_ARGS := -T $(boot)/ld.script \
LD_ARGS := -T $(srctree)/$(boot)/ld.script \
-Ttext $(CONFIG_BOOT_LOAD) -Bstatic
OBJCOPY_ARGS := -O elf32-powerpc
......@@ -159,8 +159,8 @@ MKTREE := $(utils)/mktree
targets := dummy.o
$(obj)/zvmlinux: $(OBJS) $(LIBS) $(boot)/ld.script $(images)/vmlinux.gz \
$(obj)/dummy.o
$(obj)/zvmlinux: $(OBJS) $(LIBS) $(srctree)/$(boot)/ld.script \
$(images)/vmlinux.gz $(obj)/dummy.o
$(OBJCOPY) $(OBJCOPY_ARGS) \
--add-section=.image=$(images)/vmlinux.gz \
--set-section-flags=.image=contents,alloc,load,readonly,data \
......@@ -169,7 +169,7 @@ $(obj)/zvmlinux: $(OBJS) $(LIBS) $(boot)/ld.script $(images)/vmlinux.gz \
$(OBJCOPY) $(OBJCOPY_ARGS) $@ $@ -R .comment -R .stab \
-R .stabstr -R .ramdisk -R .sysmap
$(obj)/zvmlinux.initrd: $(OBJS) $(LIBS) $(boot)/ld.script \
$(obj)/zvmlinux.initrd: $(OBJS) $(LIBS) $(srctree)/$(boot)/ld.script \
$(images)/vmlinux.gz $(obj)/dummy.o
$(OBJCOPY) $(OBJCOPY_ARGS) \
--add-section=.ramdisk=$(images)/ramdisk.image.gz \
......@@ -210,10 +210,10 @@ $(images)/zImage.initrd-TREE: $(obj)/zvmlinux.initrd $(MKTREE)
$(MKTREE) $(obj)/zvmlinux.initrd $(images)/zImage.initrd.$(end-y) \
$(ENTRYPOINT)
$(images)/zImage-PPLUS: $(obj)/zvmlinux $(utils)/mkprep $(MKBUGBOOT)
$(images)/zImage-PPLUS: $(obj)/zvmlinux $(MKPREP) $(MKBUGBOOT)
$(MKPREP) -pbp $(obj)/zvmlinux $(images)/zImage.$(end-y)
$(MKBUGBOOT) $(obj)/zvmlinux $(images)/zImage.bugboot
$(images)/zImage.initrd-PPLUS: $(obj)/zvmlinux.initrd $(utils)/mkprep $(MKBUGBOOT)
$(images)/zImage.initrd-PPLUS: $(obj)/zvmlinux.initrd $(MKPREP) $(MKBUGBOOT)
$(MKPREP) -pbp $(obj)/zvmlinux.initrd $(images)/zImage.initrd.$(end-y)
$(MKBUGBOOT) $(obj)/zvmlinux.initrd $(images)/zImage.initrd.bugboot
This diff is collapsed.
......@@ -21,8 +21,10 @@ CONFIG_BROKEN_ON_SMP=y
#
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_HOTPLUG is not set
# CONFIG_IKCONFIG is not set
......@@ -33,6 +35,7 @@ CONFIG_EPOLL=y
CONFIG_IOSCHED_NOOP=y
CONFIG_IOSCHED_AS=y
CONFIG_IOSCHED_DEADLINE=y
CONFIG_IOSCHED_CFQ=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
#
......@@ -67,7 +70,6 @@ CONFIG_440GP=y
CONFIG_440=y
CONFIG_BOOKE=y
CONFIG_IBM_OCP=y
CONFIG_PPC_OCP=y
# CONFIG_PM is not set
CONFIG_NOT_COHERENT_CACHE=y
......@@ -161,7 +163,6 @@ CONFIG_LBD=y
#
# Fusion MPT device support
#
# CONFIG_FUSION is not set
#
# IEEE 1394 (FireWire) support
......@@ -210,8 +211,6 @@ CONFIG_IP_PNP_BOOTP=y
#
# CONFIG_IP_VS is not set
# CONFIG_IPV6 is not set
# CONFIG_DECNET is not set
# CONFIG_BRIDGE is not set
CONFIG_NETFILTER=y
# CONFIG_NETFILTER_DEBUG is not set
......@@ -230,7 +229,9 @@ CONFIG_NETFILTER=y
#
# CONFIG_IP_SCTP is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
......@@ -251,16 +252,21 @@ CONFIG_NETFILTER=y
# Network testing
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
CONFIG_NETDEVICES=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
#
# ARCnet devices
#
# CONFIG_ARCNET is not set
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
#
# Ethernet (10 or 100Mbit)
......@@ -277,7 +283,6 @@ CONFIG_NETDEVICES=y
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
# CONFIG_R8169 is not set
# CONFIG_SIS190 is not set
# CONFIG_SK98LIN is not set
# CONFIG_TIGON3 is not set
......@@ -285,51 +290,29 @@ CONFIG_NETDEVICES=y
# Ethernet (10000 Mbit)
#
# CONFIG_IXGB is not set
CONFIG_IBM_EMAC=y
# CONFIG_IBM_EMAC_ERRMSG is not set
CONFIG_IBM_EMAC_RXB=64
CONFIG_IBM_EMAC_TXB=8
CONFIG_IBM_EMAC_FGAP=8
CONFIG_IBM_EMAC_SKBRES=0
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
#
# Wireless LAN (non-hamradio)
#
# CONFIG_NET_RADIO is not set
# CONFIG_S2IO is not set
#
# Token Ring devices
#
# CONFIG_TR is not set
# CONFIG_RCPCI is not set
# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
#
# Wan interfaces
#
# CONFIG_WAN is not set
#
# Amateur Radio support
#
# CONFIG_HAMRADIO is not set
#
# IrDA (infrared) support
# Wireless LAN (non-hamradio)
#
# CONFIG_IRDA is not set
# CONFIG_NET_RADIO is not set
#
# Bluetooth support
# Wan interfaces
#
# CONFIG_BT is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
# CONFIG_RCPCI is not set
# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
#
# ISDN subsystem
......@@ -501,6 +484,7 @@ CONFIG_LEGACY_PTY_COUNT=256
#
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_SYSFS=y
# CONFIG_DEVFS_FS is not set
# CONFIG_DEVPTS_FS_XATTR is not set
# CONFIG_TMPFS is not set
......@@ -541,7 +525,6 @@ CONFIG_SUNRPC=y
# CONFIG_CIFS is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
# CONFIG_INTERMEZZO_FS is not set
# CONFIG_AFS_FS is not set
#
......@@ -559,6 +542,7 @@ CONFIG_MSDOS_PARTITION=y
# Library routines
#
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
#
# Kernel hacking
......@@ -573,7 +557,7 @@ CONFIG_DEBUG_KERNEL=y
CONFIG_BDI_SWITCH=y
# CONFIG_DEBUG_INFO is not set
# CONFIG_SERIAL_TEXT_DEBUG is not set
CONFIG_OCP=y
CONFIG_PPC_OCP=y
#
# Security options
......
......@@ -21,8 +21,10 @@ CONFIG_BROKEN_ON_SMP=y
#
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_HOTPLUG is not set
# CONFIG_IKCONFIG is not set
......@@ -33,6 +35,7 @@ CONFIG_EPOLL=y
CONFIG_IOSCHED_NOOP=y
CONFIG_IOSCHED_AS=y
CONFIG_IOSCHED_DEADLINE=y
CONFIG_IOSCHED_CFQ=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
#
......@@ -62,9 +65,9 @@ CONFIG_4xx=y
# IBM 4xx options
#
# CONFIG_ASH is not set
# CONFIG_BUBINGA is not set
# CONFIG_CPCI405 is not set
CONFIG_EP405=y
# CONFIG_EVB405EP is not set
# CONFIG_OAK is not set
# CONFIG_REDWOOD_5 is not set
# CONFIG_REDWOOD_6 is not set
......@@ -74,7 +77,6 @@ CONFIG_EP405=y
CONFIG_IBM405_ERR77=y
CONFIG_IBM405_ERR51=y
CONFIG_IBM_OCP=y
CONFIG_PPC_OCP=y
CONFIG_BIOS_FIXUP=y
CONFIG_405GP=y
CONFIG_EMBEDDEDBOOT=y
......@@ -175,7 +177,6 @@ CONFIG_BLK_DEV_INITRD=y
#
# Fusion MPT device support
#
# CONFIG_FUSION is not set
#
# IEEE 1394 (FireWire) support
......@@ -219,8 +220,6 @@ CONFIG_SYN_COOKIES=y
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
# CONFIG_IPV6 is not set
# CONFIG_DECNET is not set
# CONFIG_BRIDGE is not set
# CONFIG_NETFILTER is not set
#
......@@ -228,7 +227,9 @@ CONFIG_SYN_COOKIES=y
#
# CONFIG_IP_SCTP is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
......@@ -249,16 +250,21 @@ CONFIG_SYN_COOKIES=y
# Network testing
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
CONFIG_NETDEVICES=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
#
# ARCnet devices
#
# CONFIG_ARCNET is not set
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
#
# Ethernet (10 or 100Mbit)
......@@ -287,7 +293,6 @@ CONFIG_NET_ETHERNET=y
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
# CONFIG_R8169 is not set
# CONFIG_SIS190 is not set
# CONFIG_SK98LIN is not set
# CONFIG_TIGON3 is not set
......@@ -295,51 +300,29 @@ CONFIG_NET_ETHERNET=y
# Ethernet (10000 Mbit)
#
# CONFIG_IXGB is not set
CONFIG_IBM_EMAC=y
# CONFIG_IBM_EMAC_ERRMSG is not set
CONFIG_IBM_EMAC_RXB=64
CONFIG_IBM_EMAC_TXB=8
CONFIG_IBM_EMAC_FGAP=8
CONFIG_IBM_EMAC_SKBRES=0
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
#
# Wireless LAN (non-hamradio)
#
# CONFIG_NET_RADIO is not set
# CONFIG_S2IO is not set
#
# Token Ring devices
#
# CONFIG_TR is not set
# CONFIG_RCPCI is not set
# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
#
# Wan interfaces
#
# CONFIG_WAN is not set
#
# Amateur Radio support
#
# CONFIG_HAMRADIO is not set
#
# IrDA (infrared) support
# Wireless LAN (non-hamradio)
#
# CONFIG_IRDA is not set
# CONFIG_NET_RADIO is not set
#
# Bluetooth support
# Wan interfaces
#
# CONFIG_BT is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
# CONFIG_RCPCI is not set
# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
#
# ISDN subsystem
......@@ -508,6 +491,7 @@ CONFIG_EXT2_FS=y
#
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_SYSFS=y
# CONFIG_DEVFS_FS is not set
# CONFIG_DEVPTS_FS_XATTR is not set
CONFIG_TMPFS=y
......@@ -548,7 +532,6 @@ CONFIG_SUNRPC=y
# CONFIG_CIFS is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
# CONFIG_INTERMEZZO_FS is not set
# CONFIG_AFS_FS is not set
#
......@@ -570,13 +553,14 @@ CONFIG_MSDOS_PARTITION=y
# Library routines
#
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
#
# Kernel hacking
#
# CONFIG_DEBUG_KERNEL is not set
# CONFIG_SERIAL_TEXT_DEBUG is not set
CONFIG_OCP=y
CONFIG_PPC_OCP=y
#
# Security options
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -29,6 +29,7 @@ obj-$(CONFIG_PCI) += pci-dma.o
obj-$(CONFIG_KGDB) += ppc-stub.o
obj-$(CONFIG_SMP) += smp.o smp-tbsync.o
obj-$(CONFIG_TAU) += temp.o
obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o
ifdef CONFIG_MATH_EMULATION
obj-$(CONFIG_8xx) += softemu8xx.o
......
......@@ -209,7 +209,15 @@ struct cpu_spec cpu_specs[] = {
32, 32,
__setup_cpu_750fx
},
{ /* 750GX */
0xffff0000, 0x70020000, "750GX",
CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_CAN_NAP |
CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS,
COMMON_PPC,
32, 32,
__setup_cpu_750fx
},
{ /* 740/750 (L2CR bit need fixup for 740) */
0xffff0000, 0x00080000, "740/750",
CPU_FTR_COMMON |
......@@ -537,8 +545,8 @@ struct cpu_spec cpu_specs[] = {
32, 32,
0, /*__setup_cpu_440 */
},
{ /* 440GX Rev. B1 (2.1) */
0xf0000fff, 0x50000852, "440GX Rev. B1 (2.1)",
{ /* 440GX Rev. C */
0xf0000fff, 0x50000892, "440GX Rev. C",
CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB,
PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
32, 32,
......
......@@ -491,14 +491,16 @@ SystemCall:
/*
* The Altivec unavailable trap is at 0x0f20. Foo.
* We effectively remap it to 0x3000.
* We include an altivec unavailable exception vector even if
* not configured for Altivec, so that you can't panic a
* non-altivec kernel running on a machine with altivec just
* by executing an altivec instruction.
*/
. = 0xf00
b Trap_0f
. = 0xf20
#ifdef CONFIG_ALTIVEC
b AltiVecUnavailable
#endif
Trap_0f:
EXCEPTION_PROLOG
......@@ -705,6 +707,7 @@ DataStoreTLBMiss:
#ifndef CONFIG_ALTIVEC
#define AltivecAssistException UnknownException
#endif
EXCEPTION(0x1300, Trap_13, InstructionBreakpoint, EXC_XFER_EE)
EXCEPTION(0x1400, SMI, SMIException, EXC_XFER_EE)
EXCEPTION(0x1500, Trap_15, UnknownException, EXC_XFER_EE)
......@@ -746,12 +749,12 @@ DataStoreTLBMiss:
. = 0x3000
#ifdef CONFIG_ALTIVEC
AltiVecUnavailable:
EXCEPTION_PROLOG
#ifdef CONFIG_ALTIVEC
bne load_up_altivec /* if from user, just load it up */
EXC_XFER_EE_LITE(0xf20, KernelAltiVec)
#endif /* CONFIG_ALTIVEC */
EXC_XFER_EE_LITE(0xf20, AltivecUnavailException)
#ifdef CONFIG_PPC64BRIDGE
DataAccess:
......@@ -1633,7 +1636,7 @@ initial_mm_power4:
blr
#endif /* CONFIG_POWER4 */
#ifdef CONFIG_8260
/* Jump into the system reset for the rom.
* We first disable the MMU, and then jump to the ROM reset address.
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -120,23 +120,6 @@ mem_pieces_print(struct mem_pieces *mp)
printk("\n");
}
#if defined(CONFIG_APUS) || defined(CONFIG_PPC_OF)
/*
* Add some memory to an array of pieces
*/
void __init
mem_pieces_append(struct mem_pieces *mp, unsigned int start, unsigned int size)
{
struct reg_property *rp;
if (mp->n_regions >= MEM_PIECES_MAX)
return;
rp = &mp->regions[mp->n_regions++];
rp->address = start;
rp->size = size;
}
#endif /* CONFIG_APUS || CONFIG_PPC_OF */
void __init
mem_pieces_sort(struct mem_pieces *mp)
{
......
......@@ -38,8 +38,6 @@ struct mem_pieces {
extern void *mem_pieces_find(unsigned int size, unsigned int align);
extern void mem_pieces_remove(struct mem_pieces *mp, unsigned int start,
unsigned int size, int must_exist);
extern void mem_pieces_append(struct mem_pieces *mp, unsigned int start,
unsigned int size);
extern void mem_pieces_coalesce(struct mem_pieces *mp);
extern void mem_pieces_sort(struct mem_pieces *mp);
......
......@@ -125,7 +125,7 @@ struct ocp_def core_ocp[] = {
{ .vendor = OCP_VENDOR_IBM,
.function = OCP_FUNC_EMAC,
.index = 0,
.paddr = 0x0000000140000800UL,
.paddr = 0x0000000140000800ULL,
.irq = 60,
.pm = OCP_CPM_NA,
.additions = &ibm440gp_emac0_def,
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -800,8 +800,7 @@ prom_init(int r3, int r4, prom_entry pp)
/* First get a handle for the stdout device */
prom = pp;
prom_chosen = call_prom("finddevice", 1, 1,
"/chosen");
prom_chosen = call_prom("finddevice", 1, 1, "/chosen");
if (prom_chosen == (void *)-1)
prom_exit();
if ((int) call_prom("getprop", 4, 1, prom_chosen,
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment