mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-24 05:04:00 +08:00
Merge branch 'master' of /pub/scm/linux/kernel/git/torvalds/linux-2.6
This commit is contained in:
commit
404e86e155
1
.gitignore
vendored
1
.gitignore
vendored
@ -27,6 +27,7 @@ TAGS
|
||||
vmlinux*
|
||||
!vmlinux.lds.S
|
||||
System.map
|
||||
Module.markers
|
||||
Module.symvers
|
||||
!.gitignore
|
||||
|
||||
|
212
Documentation/ABI/stable/sysfs-class-ubi
Normal file
212
Documentation/ABI/stable/sysfs-class-ubi
Normal file
@ -0,0 +1,212 @@
|
||||
What: /sys/class/ubi/
|
||||
Date: July 2006
|
||||
KernelVersion: 2.6.22
|
||||
Contact: Artem Bityutskiy <dedekind@infradead.org>
|
||||
Description:
|
||||
The ubi/ class sub-directory belongs to the UBI subsystem and
|
||||
provides general UBI information, per-UBI device information
|
||||
and per-UBI volume information.
|
||||
|
||||
What: /sys/class/ubi/version
|
||||
Date: July 2006
|
||||
KernelVersion: 2.6.22
|
||||
Contact: Artem Bityutskiy <dedekind@infradead.org>
|
||||
Description:
|
||||
This file contains version of the latest supported UBI on-media
|
||||
format. Currently it is 1, and there is no plan to change this.
|
||||
However, if in the future UBI needs on-flash format changes
|
||||
which cannot be done in a compatible manner, a new format
|
||||
version will be added. So this is a mechanism for possible
|
||||
future backward-compatible (but forward-incompatible)
|
||||
improvements.
|
||||
|
||||
What: /sys/class/ubiX/
|
||||
Date: July 2006
|
||||
KernelVersion: 2.6.22
|
||||
Contact: Artem Bityutskiy <dedekind@infradead.org>
|
||||
Description:
|
||||
The /sys/class/ubi0, /sys/class/ubi1, etc directories describe
|
||||
UBI devices (UBI device 0, 1, etc). They contain general UBI
|
||||
device information and per UBI volume information (each UBI
|
||||
device may have many UBI volumes)
|
||||
|
||||
What: /sys/class/ubi/ubiX/avail_eraseblocks
|
||||
Date: July 2006
|
||||
KernelVersion: 2.6.22
|
||||
Contact: Artem Bityutskiy <dedekind@infradead.org>
|
||||
Description:
|
||||
Amount of available logical eraseblock. For example, one may
|
||||
create a new UBI volume which has this amount of logical
|
||||
eraseblocks.
|
||||
|
||||
What: /sys/class/ubi/ubiX/bad_peb_count
|
||||
Date: July 2006
|
||||
KernelVersion: 2.6.22
|
||||
Contact: Artem Bityutskiy <dedekind@infradead.org>
|
||||
Description:
|
||||
Count of bad physical eraseblocks on the underlying MTD device.
|
||||
|
||||
What: /sys/class/ubi/ubiX/bgt_enabled
|
||||
Date: July 2006
|
||||
KernelVersion: 2.6.22
|
||||
Contact: Artem Bityutskiy <dedekind@infradead.org>
|
||||
Description:
|
||||
Contains ASCII "0\n" if the UBI background thread is disabled,
|
||||
and ASCII "1\n" if it is enabled.
|
||||
|
||||
What: /sys/class/ubi/ubiX/dev
|
||||
Date: July 2006
|
||||
KernelVersion: 2.6.22
|
||||
Contact: Artem Bityutskiy <dedekind@infradead.org>
|
||||
Description:
|
||||
Major and minor numbers of the character device corresponding
|
||||
to this UBI device (in <major>:<minor> format).
|
||||
|
||||
What: /sys/class/ubi/ubiX/eraseblock_size
|
||||
Date: July 2006
|
||||
KernelVersion: 2.6.22
|
||||
Contact: Artem Bityutskiy <dedekind@infradead.org>
|
||||
Description:
|
||||
Maximum logical eraseblock size this UBI device may provide. UBI
|
||||
volumes may have smaller logical eraseblock size because of their
|
||||
alignment.
|
||||
|
||||
What: /sys/class/ubi/ubiX/max_ec
|
||||
Date: July 2006
|
||||
KernelVersion: 2.6.22
|
||||
Contact: Artem Bityutskiy <dedekind@infradead.org>
|
||||
Description:
|
||||
Maximum physical eraseblock erase counter value.
|
||||
|
||||
What: /sys/class/ubi/ubiX/max_vol_count
|
||||
Date: July 2006
|
||||
KernelVersion: 2.6.22
|
||||
Contact: Artem Bityutskiy <dedekind@infradead.org>
|
||||
Description:
|
||||
Maximum number of volumes which this UBI device may have.
|
||||
|
||||
What: /sys/class/ubi/ubiX/min_io_size
|
||||
Date: July 2006
|
||||
KernelVersion: 2.6.22
|
||||
Contact: Artem Bityutskiy <dedekind@infradead.org>
|
||||
Description:
|
||||
Minimum input/output unit size. All the I/O may only be done
|
||||
in fractions of the contained number.
|
||||
|
||||
What: /sys/class/ubi/ubiX/mtd_num
|
||||
Date: January 2008
|
||||
KernelVersion: 2.6.25
|
||||
Contact: Artem Bityutskiy <dedekind@infradead.org>
|
||||
Description:
|
||||
Number of the underlying MTD device.
|
||||
|
||||
What: /sys/class/ubi/ubiX/reserved_for_bad
|
||||
Date: July 2006
|
||||
KernelVersion: 2.6.22
|
||||
Contact: Artem Bityutskiy <dedekind@infradead.org>
|
||||
Description:
|
||||
Number of physical eraseblocks reserved for bad block handling.
|
||||
|
||||
What: /sys/class/ubi/ubiX/total_eraseblocks
|
||||
Date: July 2006
|
||||
KernelVersion: 2.6.22
|
||||
Contact: Artem Bityutskiy <dedekind@infradead.org>
|
||||
Description:
|
||||
Total number of good (not marked as bad) physical eraseblocks on
|
||||
the underlying MTD device.
|
||||
|
||||
What: /sys/class/ubi/ubiX/volumes_count
|
||||
Date: July 2006
|
||||
KernelVersion: 2.6.22
|
||||
Contact: Artem Bityutskiy <dedekind@infradead.org>
|
||||
Description:
|
||||
Count of volumes on this UBI device.
|
||||
|
||||
What: /sys/class/ubi/ubiX/ubiX_Y/
|
||||
Date: July 2006
|
||||
KernelVersion: 2.6.22
|
||||
Contact: Artem Bityutskiy <dedekind@infradead.org>
|
||||
Description:
|
||||
The /sys/class/ubi/ubiX/ubiX_0/, /sys/class/ubi/ubiX/ubiX_1/,
|
||||
etc directories describe UBI volumes on UBI device X (volumes
|
||||
0, 1, etc).
|
||||
|
||||
What: /sys/class/ubi/ubiX/ubiX_Y/alignment
|
||||
Date: July 2006
|
||||
KernelVersion: 2.6.22
|
||||
Contact: Artem Bityutskiy <dedekind@infradead.org>
|
||||
Description:
|
||||
Volume alignment - the value the logical eraseblock size of
|
||||
this volume has to be aligned on. For example, 2048 means that
|
||||
logical eraseblock size is multiple of 2048. In other words,
|
||||
volume logical eraseblock size is UBI device logical eraseblock
|
||||
size aligned to the alignment value.
|
||||
|
||||
What: /sys/class/ubi/ubiX/ubiX_Y/corrupted
|
||||
Date: July 2006
|
||||
KernelVersion: 2.6.22
|
||||
Contact: Artem Bityutskiy <dedekind@infradead.org>
|
||||
Description:
|
||||
Contains ASCII "0\n" if the UBI volume is OK, and ASCII "1\n"
|
||||
if it is corrupted (e.g., due to an interrupted volume update).
|
||||
|
||||
What: /sys/class/ubi/ubiX/ubiX_Y/data_bytes
|
||||
Date: July 2006
|
||||
KernelVersion: 2.6.22
|
||||
Contact: Artem Bityutskiy <dedekind@infradead.org>
|
||||
Description:
|
||||
The amount of data this volume contains. This value makes sense
|
||||
only for static volumes, and for dynamic volume it equivalent
|
||||
to the total volume size in bytes.
|
||||
|
||||
What: /sys/class/ubi/ubiX/ubiX_Y/dev
|
||||
Date: July 2006
|
||||
KernelVersion: 2.6.22
|
||||
Contact: Artem Bityutskiy <dedekind@infradead.org>
|
||||
Description:
|
||||
Major and minor numbers of the character device corresponding
|
||||
to this UBI volume (in <major>:<minor> format).
|
||||
|
||||
What: /sys/class/ubi/ubiX/ubiX_Y/name
|
||||
Date: July 2006
|
||||
KernelVersion: 2.6.22
|
||||
Contact: Artem Bityutskiy <dedekind@infradead.org>
|
||||
Description:
|
||||
Volume name.
|
||||
|
||||
What: /sys/class/ubi/ubiX/ubiX_Y/reserved_ebs
|
||||
Date: July 2006
|
||||
KernelVersion: 2.6.22
|
||||
Contact: Artem Bityutskiy <dedekind@infradead.org>
|
||||
Description:
|
||||
Count of physical eraseblock reserved for this volume.
|
||||
Equivalent to the volume size in logical eraseblocks.
|
||||
|
||||
What: /sys/class/ubi/ubiX/ubiX_Y/type
|
||||
Date: July 2006
|
||||
KernelVersion: 2.6.22
|
||||
Contact: Artem Bityutskiy <dedekind@infradead.org>
|
||||
Description:
|
||||
Volume type. Contains ASCII "dynamic\n" for dynamic volumes and
|
||||
"static\n" for static volumes.
|
||||
|
||||
What: /sys/class/ubi/ubiX/ubiX_Y/upd_marker
|
||||
Date: July 2006
|
||||
KernelVersion: 2.6.22
|
||||
Contact: Artem Bityutskiy <dedekind@infradead.org>
|
||||
Description:
|
||||
Contains ASCII "0\n" if the update marker is not set for this
|
||||
volume, and "1\n" if it is set. The update marker is set when
|
||||
volume update starts, and cleaned when it ends. So the presence
|
||||
of the update marker indicates that the volume is being updated
|
||||
at the moment of the update was interrupted. The later may be
|
||||
checked using the "corrupted" sysfs file.
|
||||
|
||||
What: /sys/class/ubi/ubiX/ubiX_Y/usable_eb_size
|
||||
Date: July 2006
|
||||
KernelVersion: 2.6.22
|
||||
Contact: Artem Bityutskiy <dedekind@infradead.org>
|
||||
Description:
|
||||
Logical eraseblock size of this volume. Equivalent to logical
|
||||
eraseblock size of the device aligned on the volume alignment
|
||||
value.
|
@ -187,8 +187,11 @@ quiet_cmd_fig2png = FIG2PNG $@
|
||||
|
||||
###
|
||||
# Rule to convert a .c file to inline XML documentation
|
||||
gen_xml = :
|
||||
quiet_gen_xml = echo ' GEN $@'
|
||||
silent_gen_xml = :
|
||||
%.xml: %.c
|
||||
@echo ' GEN $@'
|
||||
@$($(quiet)gen_xml)
|
||||
@( \
|
||||
echo "<programlisting>"; \
|
||||
expand --tabs=8 < $< | \
|
||||
|
@ -249,9 +249,11 @@ process is as follows:
|
||||
release a new -rc kernel every week.
|
||||
- Process continues until the kernel is considered "ready", the
|
||||
process should last around 6 weeks.
|
||||
- A list of known regressions present in each -rc release is
|
||||
tracked at the following URI:
|
||||
http://kernelnewbies.org/known_regressions
|
||||
- Known regressions in each release are periodically posted to the
|
||||
linux-kernel mailing list. The goal is to reduce the length of
|
||||
that list to zero before declaring the kernel to be "ready," but, in
|
||||
the real world, a small number of regressions often remain at
|
||||
release time.
|
||||
|
||||
It is worth mentioning what Andrew Morton wrote on the linux-kernel
|
||||
mailing list about kernel releases:
|
||||
@ -261,7 +263,7 @@ mailing list about kernel releases:
|
||||
|
||||
2.6.x.y -stable kernel tree
|
||||
---------------------------
|
||||
Kernels with 4 digit versions are -stable kernels. They contain
|
||||
Kernels with 4-part versions are -stable kernels. They contain
|
||||
relatively small and critical fixes for security problems or significant
|
||||
regressions discovered in a given 2.6.x kernel.
|
||||
|
||||
@ -273,7 +275,10 @@ If no 2.6.x.y kernel is available, then the highest numbered 2.6.x
|
||||
kernel is the current stable kernel.
|
||||
|
||||
2.6.x.y are maintained by the "stable" team <stable@kernel.org>, and are
|
||||
released almost every other week.
|
||||
released as needs dictate. The normal release period is approximately
|
||||
two weeks, but it can be longer if there are no pressing problems. A
|
||||
security-related problem, instead, can cause a release to happen almost
|
||||
instantly.
|
||||
|
||||
The file Documentation/stable_kernel_rules.txt in the kernel tree
|
||||
documents what kinds of changes are acceptable for the -stable tree, and
|
||||
@ -298,7 +303,9 @@ a while Andrew or the subsystem maintainer pushes it on to Linus for
|
||||
inclusion in mainline.
|
||||
|
||||
It is heavily encouraged that all new patches get tested in the -mm tree
|
||||
before they are sent to Linus for inclusion in the main kernel tree.
|
||||
before they are sent to Linus for inclusion in the main kernel tree. Code
|
||||
which does not make an appearance in -mm before the opening of the merge
|
||||
window will prove hard to merge into the mainline.
|
||||
|
||||
These kernels are not appropriate for use on systems that are supposed
|
||||
to be stable and they are more risky to run than any of the other
|
||||
@ -354,11 +361,12 @@ Here is a list of some of the different kernel trees available:
|
||||
- SCSI, James Bottomley <James.Bottomley@SteelEye.com>
|
||||
git.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git
|
||||
|
||||
- x86, Ingo Molnar <mingo@elte.hu>
|
||||
git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86.git
|
||||
|
||||
quilt trees:
|
||||
- USB, PCI, Driver Core, and I2C, Greg Kroah-Hartman <gregkh@suse.de>
|
||||
- USB, Driver Core, and I2C, Greg Kroah-Hartman <gregkh@suse.de>
|
||||
kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
|
||||
- x86-64, partly i386, Andi Kleen <ak@suse.de>
|
||||
ftp.firstfloor.org:/pub/ak/x86_64/quilt/
|
||||
|
||||
Other kernel trees can be found listed at http://git.kernel.org/ and in
|
||||
the MAINTAINERS file.
|
||||
@ -392,8 +400,8 @@ If you want to be advised of the future bug reports, you can subscribe to the
|
||||
bugme-new mailing list (only new bug reports are mailed here) or to the
|
||||
bugme-janitor mailing list (every change in the bugzilla is mailed here)
|
||||
|
||||
http://lists.osdl.org/mailman/listinfo/bugme-new
|
||||
http://lists.osdl.org/mailman/listinfo/bugme-janitors
|
||||
http://lists.linux-foundation.org/mailman/listinfo/bugme-new
|
||||
http://lists.linux-foundation.org/mailman/listinfo/bugme-janitors
|
||||
|
||||
|
||||
|
||||
|
30
Documentation/arm/Samsung-S3C24XX/NAND.txt
Normal file
30
Documentation/arm/Samsung-S3C24XX/NAND.txt
Normal file
@ -0,0 +1,30 @@
|
||||
S3C24XX NAND Support
|
||||
====================
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
Small Page NAND
|
||||
---------------
|
||||
|
||||
The driver uses a 512 byte (1 page) ECC code for this setup. The
|
||||
ECC code is not directly compatible with the default kernel ECC
|
||||
code, so the driver enforces its own OOB layout and ECC parameters
|
||||
|
||||
Large Page NAND
|
||||
---------------
|
||||
|
||||
The driver is capable of handling NAND flash with a 2KiB page
|
||||
size, with support for hardware ECC generation and correction.
|
||||
|
||||
Unlike the 512byte page mode, the driver generates ECC data for
|
||||
each 256 byte block in an 2KiB page. This means that more than
|
||||
one error in a page can be rectified. It also means that the
|
||||
OOB layout remains the default kernel layout for these flashes.
|
||||
|
||||
|
||||
Document Author
|
||||
---------------
|
||||
|
||||
Ben Dooks, Copyright 2007 Simtec Electronics
|
||||
|
@ -156,6 +156,8 @@ NAND
|
||||
controller. If there are any problems the latest linux-mtd
|
||||
code can be found from http://www.linux-mtd.infradead.org/
|
||||
|
||||
For more information see Documentation/arm/Samsung-S3C24XX/NAND.txt
|
||||
|
||||
|
||||
Serial
|
||||
------
|
||||
|
52
Documentation/device-mapper/dm-crypt.txt
Normal file
52
Documentation/device-mapper/dm-crypt.txt
Normal file
@ -0,0 +1,52 @@
|
||||
dm-crypt
|
||||
=========
|
||||
|
||||
Device-Mapper's "crypt" target provides transparent encryption of block devices
|
||||
using the kernel crypto API.
|
||||
|
||||
Parameters: <cipher> <key> <iv_offset> <device path> <offset>
|
||||
|
||||
<cipher>
|
||||
Encryption cipher and an optional IV generation mode.
|
||||
(In format cipher-chainmode-ivopts:ivmode).
|
||||
Examples:
|
||||
des
|
||||
aes-cbc-essiv:sha256
|
||||
twofish-ecb
|
||||
|
||||
/proc/crypto contains supported crypto modes
|
||||
|
||||
<key>
|
||||
Key used for encryption. It is encoded as a hexadecimal number.
|
||||
You can only use key sizes that are valid for the selected cipher.
|
||||
|
||||
<iv_offset>
|
||||
The IV offset is a sector count that is added to the sector number
|
||||
before creating the IV.
|
||||
|
||||
<device path>
|
||||
This is the device that is going to be used as backend and contains the
|
||||
encrypted data. You can specify it as a path like /dev/xxx or a device
|
||||
number <major>:<minor>.
|
||||
|
||||
<offset>
|
||||
Starting sector within the device where the encrypted data begins.
|
||||
|
||||
Example scripts
|
||||
===============
|
||||
LUKS (Linux Unified Key Setup) is now the preferred way to set up disk
|
||||
encryption with dm-crypt using the 'cryptsetup' utility, see
|
||||
http://luks.endorphin.org/
|
||||
|
||||
[[
|
||||
#!/bin/sh
|
||||
# Create a crypt device using dmsetup
|
||||
dmsetup create crypt1 --table "0 `blockdev --getsize $1` crypt aes-cbc-essiv:sha256 babebabebabebabebabebabebabebabe 0 $1 0"
|
||||
]]
|
||||
|
||||
[[
|
||||
#!/bin/sh
|
||||
# Create a crypt device using cryptsetup and LUKS header with default cipher
|
||||
cryptsetup luksFormat $1
|
||||
cryptsetup luksOpen $1 crypt1
|
||||
]]
|
@ -5,7 +5,7 @@
|
||||
################################################################################
|
||||
|
||||
Author: NetApp and Open Grid Computing
|
||||
Date: February 25, 2008
|
||||
Date: April 15, 2008
|
||||
|
||||
Table of Contents
|
||||
~~~~~~~~~~~~~~~~~
|
||||
@ -197,12 +197,16 @@ NFS/RDMA Setup
|
||||
- On the server system, configure the /etc/exports file and
|
||||
start the NFS/RDMA server.
|
||||
|
||||
Exports entries with the following format have been tested:
|
||||
Exports entries with the following formats have been tested:
|
||||
|
||||
/vol0 10.97.103.47(rw,async) 192.168.0.47(rw,async,insecure,no_root_squash)
|
||||
/vol0 192.168.0.47(fsid=0,rw,async,insecure,no_root_squash)
|
||||
/vol0 192.168.0.0/255.255.255.0(fsid=0,rw,async,insecure,no_root_squash)
|
||||
|
||||
Here the first IP address is the client's Ethernet address and the second
|
||||
IP address is the clients IPoIB address.
|
||||
The IP address(es) is(are) the client's IPoIB address for an InfiniBand HCA or the
|
||||
cleint's iWARP address(es) for an RNIC.
|
||||
|
||||
NOTE: The "insecure" option must be used because the NFS/RDMA client does not
|
||||
use a reserved port.
|
||||
|
||||
Each time a machine boots:
|
||||
|
||||
|
@ -122,8 +122,7 @@ stop() is the place to free it.
|
||||
}
|
||||
|
||||
Finally, the show() function should format the object currently pointed to
|
||||
by the iterator for output. It should return zero, or an error code if
|
||||
something goes wrong. The example module's show() function is:
|
||||
by the iterator for output. The example module's show() function is:
|
||||
|
||||
static int ct_seq_show(struct seq_file *s, void *v)
|
||||
{
|
||||
@ -132,6 +131,12 @@ something goes wrong. The example module's show() function is:
|
||||
return 0;
|
||||
}
|
||||
|
||||
If all is well, the show() function should return zero. A negative error
|
||||
code in the usual manner indicates that something went wrong; it will be
|
||||
passed back to user space. This function can also return SEQ_SKIP, which
|
||||
causes the current item to be skipped; if the show() function has already
|
||||
generated output before returning SEQ_SKIP, that output will be dropped.
|
||||
|
||||
We will look at seq_printf() in a moment. But first, the definition of the
|
||||
seq_file iterator is finished by creating a seq_operations structure with
|
||||
the four functions we have just defined:
|
||||
@ -182,12 +187,18 @@ The first two output a single character and a string, just like one would
|
||||
expect. seq_escape() is like seq_puts(), except that any character in s
|
||||
which is in the string esc will be represented in octal form in the output.
|
||||
|
||||
There is also a function for printing filenames:
|
||||
There is also a pair of functions for printing filenames:
|
||||
|
||||
int seq_path(struct seq_file *m, struct path *path, char *esc);
|
||||
int seq_path_root(struct seq_file *m, struct path *path,
|
||||
struct path *root, char *esc)
|
||||
|
||||
Here, path indicates the file of interest, and esc is a set of characters
|
||||
which should be escaped in the output.
|
||||
which should be escaped in the output. A call to seq_path() will output
|
||||
the path relative to the current process's filesystem root. If a different
|
||||
root is desired, it can be used with seq_path_root(). Note that, if it
|
||||
turns out that path cannot be reached from root, the value of root will be
|
||||
changed in seq_file_root() to a root which *does* work.
|
||||
|
||||
|
||||
Making it all work
|
||||
|
@ -486,7 +486,7 @@ Module.symvers contains a list of all exported symbols from a kernel build.
|
||||
Sometimes, an external module uses exported symbols from another
|
||||
external module. Kbuild needs to have full knowledge on all symbols
|
||||
to avoid spitting out warnings about undefined symbols.
|
||||
Two solutions exist to let kbuild know all symbols of more than
|
||||
Three solutions exist to let kbuild know all symbols of more than
|
||||
one external module.
|
||||
The method with a top-level kbuild file is recommended but may be
|
||||
impractical in certain situations.
|
||||
@ -523,6 +523,13 @@ Module.symvers contains a list of all exported symbols from a kernel build.
|
||||
containing the sum of all symbols defined and not part of the
|
||||
kernel.
|
||||
|
||||
Use make variable KBUILD_EXTRA_SYMBOLS in the Makefile
|
||||
If it is impractical to copy Module.symvers from another
|
||||
module, you can assign a space separated list of files to
|
||||
KBUILD_EXTRA_SYMBOLS in your Makfile. These files will be
|
||||
loaded by modpost during the initialisation of its symbol
|
||||
tables.
|
||||
|
||||
=== 8. Tips & Tricks
|
||||
|
||||
--- 8.1 Testing for CONFIG_FOO_BAR
|
||||
|
@ -19,6 +19,12 @@ optimises away.
|
||||
|
||||
Complex triggers whilst available to all LEDs have LED specific
|
||||
parameters and work on a per LED basis. The timer trigger is an example.
|
||||
The timer trigger will periodically change the LED brightness between
|
||||
LED_OFF and the current brightness setting. The "on" and "off" time can
|
||||
be specified via /sys/class/leds/<device>/delay_{on,off} in milliseconds.
|
||||
You can change the brightness value of a LED independently of the timer
|
||||
trigger. However, if you set the brightness value to LED_OFF it will
|
||||
also disable the timer trigger.
|
||||
|
||||
You can change triggers in a similar manner to the way an IO scheduler
|
||||
is chosen (via /sys/class/leds/<device>/trigger). Trigger specific
|
||||
@ -63,9 +69,9 @@ value if it is called with *delay_on==0 && *delay_off==0 parameters. In
|
||||
this case the driver should give back the chosen value through delay_on
|
||||
and delay_off parameters to the leds subsystem.
|
||||
|
||||
Any call to the brightness_set() callback function should cancel the
|
||||
previously programmed hardware blinking function so setting the brightness
|
||||
to 0 can also cancel the blinking of the LED.
|
||||
Setting the brightness to zero with brightness_set() callback function
|
||||
should completely turn off the LED and cancel the previously programmed
|
||||
hardware blinking function, if any.
|
||||
|
||||
|
||||
Known Issues
|
||||
|
@ -1,7 +1,7 @@
|
||||
|
||||
-------
|
||||
PHY Abstraction Layer
|
||||
(Updated 2006-11-30)
|
||||
(Updated 2008-04-08)
|
||||
|
||||
Purpose
|
||||
|
||||
@ -291,3 +291,39 @@ Writing a PHY driver
|
||||
Feel free to look at the Marvell, Cicada, and Davicom drivers in
|
||||
drivers/net/phy/ for examples (the lxt and qsemi drivers have
|
||||
not been tested as of this writing)
|
||||
|
||||
Board Fixups
|
||||
|
||||
Sometimes the specific interaction between the platform and the PHY requires
|
||||
special handling. For instance, to change where the PHY's clock input is,
|
||||
or to add a delay to account for latency issues in the data path. In order
|
||||
to support such contingencies, the PHY Layer allows platform code to register
|
||||
fixups to be run when the PHY is brought up (or subsequently reset).
|
||||
|
||||
When the PHY Layer brings up a PHY it checks to see if there are any fixups
|
||||
registered for it, matching based on UID (contained in the PHY device's phy_id
|
||||
field) and the bus identifier (contained in phydev->dev.bus_id). Both must
|
||||
match, however two constants, PHY_ANY_ID and PHY_ANY_UID, are provided as
|
||||
wildcards for the bus ID and UID, respectively.
|
||||
|
||||
When a match is found, the PHY layer will invoke the run function associated
|
||||
with the fixup. This function is passed a pointer to the phy_device of
|
||||
interest. It should therefore only operate on that PHY.
|
||||
|
||||
The platform code can either register the fixup using phy_register_fixup():
|
||||
|
||||
int phy_register_fixup(const char *phy_id,
|
||||
u32 phy_uid, u32 phy_uid_mask,
|
||||
int (*run)(struct phy_device *));
|
||||
|
||||
Or using one of the two stubs, phy_register_fixup_for_uid() and
|
||||
phy_register_fixup_for_id():
|
||||
|
||||
int phy_register_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask,
|
||||
int (*run)(struct phy_device *));
|
||||
int phy_register_fixup_for_id(const char *phy_id,
|
||||
int (*run)(struct phy_device *));
|
||||
|
||||
The stubs set one of the two matching criteria, and set the other one to
|
||||
match anything.
|
||||
|
||||
|
@ -2601,6 +2601,17 @@ platforms are moved over to use the flattened-device-tree model.
|
||||
differ between different families. May be
|
||||
'virtex2p', 'virtex4', or 'virtex5'.
|
||||
|
||||
vi) Xilinx Uart 16550
|
||||
|
||||
Xilinx UART 16550 devices are very similar to the NS16550 but with
|
||||
different register spacing and an offset from the base address.
|
||||
|
||||
Requred properties:
|
||||
- clock-frequency : Frequency of the clock input
|
||||
- reg-offset : A value of 3 is required
|
||||
- reg-shift : A value of 2 is required
|
||||
|
||||
|
||||
p) Freescale Synchronous Serial Interface
|
||||
|
||||
The SSI is a serial device that communicates with audio codecs. It can
|
||||
|
50
Documentation/usb/anchors.txt
Normal file
50
Documentation/usb/anchors.txt
Normal file
@ -0,0 +1,50 @@
|
||||
What is anchor?
|
||||
===============
|
||||
|
||||
A USB driver needs to support some callbacks requiring
|
||||
a driver to cease all IO to an interface. To do so, a
|
||||
driver has to keep track of the URBs it has submitted
|
||||
to know they've all completed or to call usb_kill_urb
|
||||
for them. The anchor is a data structure takes care of
|
||||
keeping track of URBs and provides methods to deal with
|
||||
multiple URBs.
|
||||
|
||||
Allocation and Initialisation
|
||||
=============================
|
||||
|
||||
There's no API to allocate an anchor. It is simply declared
|
||||
as struct usb_anchor. init_usb_anchor() must be called to
|
||||
initialise the data structure.
|
||||
|
||||
Deallocation
|
||||
============
|
||||
|
||||
Once it has no more URBs associated with it, the anchor can be
|
||||
freed with normal memory management operations.
|
||||
|
||||
Association and disassociation of URBs with anchors
|
||||
===================================================
|
||||
|
||||
An association of URBs to an anchor is made by an explicit
|
||||
call to usb_anchor_urb(). The association is maintained until
|
||||
an URB is finished by (successfull) completion. Thus disassociation
|
||||
is automatic. A function is provided to forcibly finish (kill)
|
||||
all URBs associated with an anchor.
|
||||
Furthermore, disassociation can be made with usb_unanchor_urb()
|
||||
|
||||
Operations on multitudes of URBs
|
||||
================================
|
||||
|
||||
usb_kill_anchored_urbs()
|
||||
------------------------
|
||||
|
||||
This function kills all URBs associated with an anchor. The URBs
|
||||
are called in the reverse temporal order they were submitted.
|
||||
This way no data can be reordered.
|
||||
|
||||
usb_wait_anchor_empty_timeout()
|
||||
-------------------------------
|
||||
|
||||
This function waits for all URBs associated with an anchor to finish
|
||||
or a timeout, whichever comes first. Its return value will tell you
|
||||
whether the timeout was reached.
|
132
Documentation/usb/callbacks.txt
Normal file
132
Documentation/usb/callbacks.txt
Normal file
@ -0,0 +1,132 @@
|
||||
What callbacks will usbcore do?
|
||||
===============================
|
||||
|
||||
Usbcore will call into a driver through callbacks defined in the driver
|
||||
structure and through the completion handler of URBs a driver submits.
|
||||
Only the former are in the scope of this document. These two kinds of
|
||||
callbacks are completely independent of each other. Information on the
|
||||
completion callback can be found in Documentation/usb/URB.txt.
|
||||
|
||||
The callbacks defined in the driver structure are:
|
||||
|
||||
1. Hotplugging callbacks:
|
||||
|
||||
* @probe: Called to see if the driver is willing to manage a particular
|
||||
* interface on a device.
|
||||
* @disconnect: Called when the interface is no longer accessible, usually
|
||||
* because its device has been (or is being) disconnected or the
|
||||
* driver module is being unloaded.
|
||||
|
||||
2. Odd backdoor through usbfs:
|
||||
|
||||
* @ioctl: Used for drivers that want to talk to userspace through
|
||||
* the "usbfs" filesystem. This lets devices provide ways to
|
||||
* expose information to user space regardless of where they
|
||||
* do (or don't) show up otherwise in the filesystem.
|
||||
|
||||
3. Power management (PM) callbacks:
|
||||
|
||||
* @suspend: Called when the device is going to be suspended.
|
||||
* @resume: Called when the device is being resumed.
|
||||
* @reset_resume: Called when the suspended device has been reset instead
|
||||
* of being resumed.
|
||||
|
||||
4. Device level operations:
|
||||
|
||||
* @pre_reset: Called when the device is about to be reset.
|
||||
* @post_reset: Called after the device has been reset
|
||||
|
||||
The ioctl interface (2) should be used only if you have a very good
|
||||
reason. Sysfs is preferred these days. The PM callbacks are covered
|
||||
separately in Documentation/usb/power-management.txt.
|
||||
|
||||
Calling conventions
|
||||
===================
|
||||
|
||||
All callbacks are mutually exclusive. There's no need for locking
|
||||
against other USB callbacks. All callbacks are called from a task
|
||||
context. You may sleep. However, it is important that all sleeps have a
|
||||
small fixed upper limit in time. In particular you must not call out to
|
||||
user space and await results.
|
||||
|
||||
Hotplugging callbacks
|
||||
=====================
|
||||
|
||||
These callbacks are intended to associate and disassociate a driver with
|
||||
an interface. A driver's bond to an interface is exclusive.
|
||||
|
||||
The probe() callback
|
||||
--------------------
|
||||
|
||||
int (*probe) (struct usb_interface *intf,
|
||||
const struct usb_device_id *id);
|
||||
|
||||
Accept or decline an interface. If you accept the device return 0,
|
||||
otherwise -ENODEV or -ENXIO. Other error codes should be used only if a
|
||||
genuine error occurred during initialisation which prevented a driver
|
||||
from accepting a device that would else have been accepted.
|
||||
You are strongly encouraged to use usbcore'sfacility,
|
||||
usb_set_intfdata(), to associate a data structure with an interface, so
|
||||
that you know which internal state and identity you associate with a
|
||||
particular interface. The device will not be suspended and you may do IO
|
||||
to the interface you are called for and endpoint 0 of the device. Device
|
||||
initialisation that doesn't take too long is a good idea here.
|
||||
|
||||
The disconnect() callback
|
||||
-------------------------
|
||||
|
||||
void (*disconnect) (struct usb_interface *intf);
|
||||
|
||||
This callback is a signal to break any connection with an interface.
|
||||
You are not allowed any IO to a device after returning from this
|
||||
callback. You also may not do any other operation that may interfere
|
||||
with another driver bound the interface, eg. a power management
|
||||
operation.
|
||||
If you are called due to a physical disconnection, all your URBs will be
|
||||
killed by usbcore. Note that in this case disconnect will be called some
|
||||
time after the physical disconnection. Thus your driver must be prepared
|
||||
to deal with failing IO even prior to the callback.
|
||||
|
||||
Device level callbacks
|
||||
======================
|
||||
|
||||
pre_reset
|
||||
---------
|
||||
|
||||
int (*pre_reset)(struct usb_interface *intf);
|
||||
|
||||
Another driver or user space is triggering a reset on the device which
|
||||
contains the interface passed as an argument. Cease IO and save any
|
||||
device state you need to restore.
|
||||
|
||||
If you need to allocate memory here, use GFP_NOIO or GFP_ATOMIC, if you
|
||||
are in atomic context.
|
||||
|
||||
post_reset
|
||||
----------
|
||||
|
||||
int (*post_reset)(struct usb_interface *intf);
|
||||
|
||||
The reset has completed. Restore any saved device state and begin
|
||||
using the device again.
|
||||
|
||||
If you need to allocate memory here, use GFP_NOIO or GFP_ATOMIC, if you
|
||||
are in atomic context.
|
||||
|
||||
Call sequences
|
||||
==============
|
||||
|
||||
No callbacks other than probe will be invoked for an interface
|
||||
that isn't bound to your driver.
|
||||
|
||||
Probe will never be called for an interface bound to a driver.
|
||||
Hence following a successful probe, disconnect will be called
|
||||
before there is another probe for the same interface.
|
||||
|
||||
Once your driver is bound to an interface, disconnect can be
|
||||
called at any time except in between pre_reset and post_reset.
|
||||
pre_reset is always followed by post_reset, even if the reset
|
||||
failed or the device has been unplugged.
|
||||
|
||||
suspend is always followed by one of: resume, reset_resume, or
|
||||
disconnect.
|
@ -2,7 +2,7 @@
|
||||
|
||||
Alan Stern <stern@rowland.harvard.edu>
|
||||
|
||||
September 2, 2006 (Updated May 29, 2007)
|
||||
September 2, 2006 (Updated February 25, 2008)
|
||||
|
||||
|
||||
What is the problem?
|
||||
@ -65,9 +65,10 @@ much better.)
|
||||
|
||||
What is the solution?
|
||||
|
||||
Setting CONFIG_USB_PERSIST will cause the kernel to work around these
|
||||
issues. It enables a mode in which the core USB device data
|
||||
structures are allowed to persist across a power-session disruption.
|
||||
The kernel includes a feature called USB-persist. It tries to work
|
||||
around these issues by allowing the core USB device data structures to
|
||||
persist across a power-session disruption.
|
||||
|
||||
It works like this. If the kernel sees that a USB host controller is
|
||||
not in the expected state during resume (i.e., if the controller was
|
||||
reset or otherwise had lost power) then it applies a persistence check
|
||||
@ -80,28 +81,30 @@ re-enumeration shows that the device now attached to that port has the
|
||||
same descriptors as before, including the Vendor and Product IDs, then
|
||||
the kernel continues to use the same device structure. In effect, the
|
||||
kernel treats the device as though it had merely been reset instead of
|
||||
unplugged.
|
||||
unplugged. The same thing happens if the host controller is in the
|
||||
expected state but a USB device was unplugged and then replugged.
|
||||
|
||||
If no device is now attached to the port, or if the descriptors are
|
||||
different from what the kernel remembers, then the treatment is what
|
||||
you would expect. The kernel destroys the old device structure and
|
||||
behaves as though the old device had been unplugged and a new device
|
||||
plugged in, just as it would without the CONFIG_USB_PERSIST option.
|
||||
plugged in.
|
||||
|
||||
The end result is that the USB device remains available and usable.
|
||||
Filesystem mounts and memory mappings are unaffected, and the world is
|
||||
now a good and happy place.
|
||||
|
||||
Note that even when CONFIG_USB_PERSIST is set, the "persist" feature
|
||||
will be applied only to those devices for which it is enabled. You
|
||||
can enable the feature by doing (as root):
|
||||
Note that the "USB-persist" feature will be applied only to those
|
||||
devices for which it is enabled. You can enable the feature by doing
|
||||
(as root):
|
||||
|
||||
echo 1 >/sys/bus/usb/devices/.../power/persist
|
||||
|
||||
where the "..." should be filled in the with the device's ID. Disable
|
||||
the feature by writing 0 instead of 1. For hubs the feature is
|
||||
automatically and permanently enabled, so you only have to worry about
|
||||
setting it for devices where it really matters.
|
||||
automatically and permanently enabled and the power/persist file
|
||||
doesn't even exist, so you only have to worry about setting it for
|
||||
devices where it really matters.
|
||||
|
||||
|
||||
Is this the best solution?
|
||||
@ -112,19 +115,19 @@ centralized Logical Volume Manager. Such a solution would allow you
|
||||
to plug in a USB flash device, create a persistent volume associated
|
||||
with it, unplug the flash device, plug it back in later, and still
|
||||
have the same persistent volume associated with the device. As such
|
||||
it would be more far-reaching than CONFIG_USB_PERSIST.
|
||||
it would be more far-reaching than USB-persist.
|
||||
|
||||
On the other hand, writing a persistent volume manager would be a big
|
||||
job and using it would require significant input from the user. This
|
||||
solution is much quicker and easier -- and it exists now, a giant
|
||||
point in its favor!
|
||||
|
||||
Furthermore, the USB_PERSIST option applies to _all_ USB devices, not
|
||||
Furthermore, the USB-persist feature applies to _all_ USB devices, not
|
||||
just mass-storage devices. It might turn out to be equally useful for
|
||||
other device types, such as network interfaces.
|
||||
|
||||
|
||||
WARNING: Using CONFIG_USB_PERSIST can be dangerous!!
|
||||
WARNING: USB-persist can be dangerous!!
|
||||
|
||||
When recovering an interrupted power session the kernel does its best
|
||||
to make sure the USB device hasn't been changed; that is, the same
|
||||
@ -133,10 +136,10 @@ aren't guaranteed to be 100% accurate.
|
||||
|
||||
If you replace one USB device with another of the same type (same
|
||||
manufacturer, same IDs, and so on) there's an excellent chance the
|
||||
kernel won't detect the change. Serial numbers and other strings are
|
||||
not compared. In many cases it wouldn't help if they were, because
|
||||
manufacturers frequently omit serial numbers entirely in their
|
||||
devices.
|
||||
kernel won't detect the change. The serial number string and other
|
||||
descriptors are compared with the kernel's stored values, but this
|
||||
might not help since manufacturers frequently omit serial numbers
|
||||
entirely in their devices.
|
||||
|
||||
Furthermore it's quite possible to leave a USB device exactly the same
|
||||
while changing its media. If you replace the flash memory card in a
|
||||
@ -152,5 +155,5 @@ but yourself.
|
||||
YOU HAVE BEEN WARNED! USE AT YOUR OWN RISK!
|
||||
|
||||
That having been said, most of the time there shouldn't be any trouble
|
||||
at all. The "persist" feature can be extremely useful. Make the most
|
||||
of it.
|
||||
at all. The USB-persist feature can be extremely useful. Make the
|
||||
most of it.
|
||||
|
@ -192,12 +192,9 @@ Keyspan USA-series Serial Adapters
|
||||
|
||||
FTDI Single Port Serial Driver
|
||||
|
||||
This is a single port DB-25 serial adapter. More information about this
|
||||
device and the Linux driver can be found at:
|
||||
http://reality.sgi.com/bryder_wellington/ftdi_sio/
|
||||
This is a single port DB-25 serial adapter.
|
||||
|
||||
For any questions or problems with this driver, please contact Bill Ryder
|
||||
at bryder@sgi.com
|
||||
For any questions or problems with this driver, please contact Bill Ryder.
|
||||
|
||||
|
||||
ZyXEL omni.net lcd plus ISDN TA
|
||||
|
35
MAINTAINERS
35
MAINTAINERS
@ -1106,6 +1106,12 @@ M: kernel@wantstofly.org
|
||||
L: linux-usb@vger.kernel.org
|
||||
S: Maintained
|
||||
|
||||
CIRRUS LOGIC CS4270 SOUND DRIVER
|
||||
P: Timur Tabi
|
||||
M: timur@freescale.com
|
||||
L: alsa-devel@alsa-project.org
|
||||
S: Supported
|
||||
|
||||
CIRRUS LOGIC CS4280/CS461x SOUNDDRIVER
|
||||
P: Cirrus Logic Corporation (kernel 2.2 driver)
|
||||
M: Cirrus Logic Corporation, Thomas Woller <twoller@crystal.cirrus.com>
|
||||
@ -1628,6 +1634,12 @@ L: linuxppc-dev@ozlabs.org
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
|
||||
FREESCALE QUICC ENGINE LIBRARY
|
||||
P: Timur Tabi
|
||||
M: timur@freescale.com
|
||||
L: linuxppc-dev@ozlabs.org
|
||||
S: Supported
|
||||
|
||||
FREESCALE HIGHSPEED USB DEVICE DRIVER
|
||||
P: Li Yang
|
||||
M: leoli@freescale.com
|
||||
@ -1642,6 +1654,19 @@ L: netdev@vger.kernel.org
|
||||
L: linuxppc-dev@ozlabs.org
|
||||
S: Maintained
|
||||
|
||||
FREESCALE QUICC ENGINE UCC UART DRIVER
|
||||
P: Timur Tabi
|
||||
M: timur@freescale.com
|
||||
L: linuxppc-dev@ozlabs.org
|
||||
S: Supported
|
||||
|
||||
FREESCALE SOC SOUND DRIVERS
|
||||
P: Timur Tabi
|
||||
M: timur@freescale.com
|
||||
L: alsa-devel@alsa-project.org
|
||||
L: linuxppc-dev@ozlabs.org
|
||||
S: Supported
|
||||
|
||||
FILE LOCKING (flock() and fcntl()/lockf())
|
||||
P: Matthew Wilcox
|
||||
M: matthew@wil.cx
|
||||
@ -4356,6 +4381,16 @@ L: linux-wireless@vger.kernel.org
|
||||
W: http://oops.ghostprotocols.net:81/blog
|
||||
S: Maintained
|
||||
|
||||
WM97XX TOUCHSCREEN DRIVERS
|
||||
P: Mark Brown
|
||||
M: broonie@opensource.wolfsonmicro.com
|
||||
P: Liam Girdwood
|
||||
M: liam.girdwood@wolfsonmicro.com
|
||||
L: linux-input@vger.kernel.org
|
||||
T: git git://opensource.wolfsonmicro.com/linux-2.6-touch
|
||||
W: http://opensource.wolfsonmicro.com/node/7
|
||||
S: Supported
|
||||
|
||||
X.25 NETWORK LAYER
|
||||
P: Henner Eisen
|
||||
M: eis@baty.hanse.de
|
||||
|
9
Makefile
9
Makefile
@ -507,6 +507,10 @@ else
|
||||
KBUILD_CFLAGS += -O2
|
||||
endif
|
||||
|
||||
ifneq (CONFIG_FRAME_WARN,0)
|
||||
KBUILD_CFLAGS += $(call cc-option,-Wframe-larger-than=${CONFIG_FRAME_WARN})
|
||||
endif
|
||||
|
||||
# Force gcc to behave correct even for buggy distributions
|
||||
# Arch Makefiles may override this setting
|
||||
KBUILD_CFLAGS += $(call cc-option, -fno-stack-protector)
|
||||
@ -1396,7 +1400,7 @@ define xtags
|
||||
$(all-kconfigs) | xargs $1 -a \
|
||||
--langdef=kconfig \
|
||||
--language-force=kconfig \
|
||||
--regex-kconfig='/^[[:blank:]]*config[[:blank:]]+([[:alnum:]_]+)/\1/'; \
|
||||
--regex-kconfig='/^[[:blank:]]*(menu|)config[[:blank:]]+([[:alnum:]_]+)/\2/'; \
|
||||
$(all-defconfigs) | xargs -r $1 -a \
|
||||
--langdef=dotconfig \
|
||||
--language-force=dotconfig \
|
||||
@ -1404,7 +1408,7 @@ define xtags
|
||||
elif $1 --version 2>&1 | grep -iq emacs; then \
|
||||
$(all-sources) | xargs $1 -a; \
|
||||
$(all-kconfigs) | xargs $1 -a \
|
||||
--regex='/^[ \t]*config[ \t]+\([a-zA-Z0-9_]+\)/\1/'; \
|
||||
--regex='/^[ \t]*(menu|)config[ \t]+\([a-zA-Z0-9_]+\)/\2/'; \
|
||||
$(all-defconfigs) | xargs -r $1 -a \
|
||||
--regex='/^#?[ \t]?\(CONFIG_[a-zA-Z0-9_]+\)/\1/'; \
|
||||
else \
|
||||
@ -1539,7 +1543,6 @@ quiet_cmd_rmfiles = $(if $(wildcard $(rm-files)),CLEAN $(wildcard $(rm-files))
|
||||
cmd_rmfiles = rm -f $(rm-files)
|
||||
|
||||
# Run depmod only if we have System.map and depmod is executable
|
||||
# and we build for the host arch
|
||||
quiet_cmd_depmod = DEPMOD $(KERNELRELEASE)
|
||||
cmd_depmod = \
|
||||
if [ -r System.map -a -x $(DEPMOD) ]; then \
|
||||
|
@ -626,20 +626,6 @@ config ADVANCED_OPTIONS
|
||||
comment "Default settings for advanced configuration options are used"
|
||||
depends on !ADVANCED_OPTIONS
|
||||
|
||||
config HIGHMEM_START_BOOL
|
||||
bool "Set high memory pool address"
|
||||
depends on ADVANCED_OPTIONS && HIGHMEM
|
||||
help
|
||||
This option allows you to set the base address of the kernel virtual
|
||||
area used to map high memory pages. This can be useful in
|
||||
optimizing the layout of kernel virtual memory.
|
||||
|
||||
Say N here unless you know what you are doing.
|
||||
|
||||
config HIGHMEM_START
|
||||
hex "Virtual start address of high memory pool" if HIGHMEM_START_BOOL
|
||||
default "0xfe000000"
|
||||
|
||||
config LOWMEM_SIZE_BOOL
|
||||
bool "Set maximum low memory"
|
||||
depends on ADVANCED_OPTIONS
|
||||
@ -656,21 +642,76 @@ config LOWMEM_SIZE
|
||||
hex "Maximum low memory size (in bytes)" if LOWMEM_SIZE_BOOL
|
||||
default "0x30000000"
|
||||
|
||||
config RELOCATABLE
|
||||
bool "Build a relocatable kernel (EXPERIMENTAL)"
|
||||
depends on EXPERIMENTAL && ADVANCED_OPTIONS && FLATMEM && FSL_BOOKE
|
||||
help
|
||||
This builds a kernel image that is capable of running at the
|
||||
location the kernel is loaded at (some alignment restrictions may
|
||||
exist).
|
||||
|
||||
One use is for the kexec on panic case where the recovery kernel
|
||||
must live at a different physical address than the primary
|
||||
kernel.
|
||||
|
||||
Note: If CONFIG_RELOCATABLE=y, then the kernel runs from the address
|
||||
it has been loaded at and the compile time physical addresses
|
||||
CONFIG_PHYSICAL_START is ignored. However CONFIG_PHYSICAL_START
|
||||
setting can still be useful to bootwrappers that need to know the
|
||||
load location of the kernel (eg. u-boot/mkimage).
|
||||
|
||||
config PAGE_OFFSET_BOOL
|
||||
bool "Set custom page offset address"
|
||||
depends on ADVANCED_OPTIONS
|
||||
help
|
||||
This option allows you to set the kernel virtual address at which
|
||||
the kernel will map low memory. This can be useful in optimizing
|
||||
the virtual memory layout of the system.
|
||||
|
||||
Say N here unless you know what you are doing.
|
||||
|
||||
config PAGE_OFFSET
|
||||
hex "Virtual address of memory base" if PAGE_OFFSET_BOOL
|
||||
default "0xc0000000"
|
||||
|
||||
config KERNEL_START_BOOL
|
||||
bool "Set custom kernel base address"
|
||||
depends on ADVANCED_OPTIONS
|
||||
help
|
||||
This option allows you to set the kernel virtual address at which
|
||||
the kernel will map low memory (the kernel image will be linked at
|
||||
this address). This can be useful in optimizing the virtual memory
|
||||
layout of the system.
|
||||
the kernel will be loaded. Normally this should match PAGE_OFFSET
|
||||
however there are times (like kdump) that one might not want them
|
||||
to be the same.
|
||||
|
||||
Say N here unless you know what you are doing.
|
||||
|
||||
config KERNEL_START
|
||||
hex "Virtual address of kernel base" if KERNEL_START_BOOL
|
||||
default PAGE_OFFSET if PAGE_OFFSET_BOOL
|
||||
default "0xc2000000" if CRASH_DUMP
|
||||
default "0xc0000000"
|
||||
|
||||
config PHYSICAL_START_BOOL
|
||||
bool "Set physical address where the kernel is loaded"
|
||||
depends on ADVANCED_OPTIONS && FLATMEM && FSL_BOOKE
|
||||
help
|
||||
This gives the physical address where the kernel is loaded.
|
||||
|
||||
Say N here unless you know what you are doing.
|
||||
|
||||
config PHYSICAL_START
|
||||
hex "Physical address where the kernel is loaded" if PHYSICAL_START_BOOL
|
||||
default "0x02000000" if PPC_STD_MMU && CRASH_DUMP
|
||||
default "0x00000000"
|
||||
|
||||
config PHYSICAL_ALIGN
|
||||
hex
|
||||
default "0x10000000" if FSL_BOOKE
|
||||
help
|
||||
This value puts the alignment restrictions on physical address
|
||||
where kernel is loaded and run from. Kernel is compiled for an
|
||||
address which meets above alignment restriction.
|
||||
|
||||
config TASK_SIZE_BOOL
|
||||
bool "Set custom user task size"
|
||||
depends on ADVANCED_OPTIONS
|
||||
@ -717,9 +758,17 @@ config PIN_TLB
|
||||
endmenu
|
||||
|
||||
if PPC64
|
||||
config KERNEL_START
|
||||
config PAGE_OFFSET
|
||||
hex
|
||||
default "0xc000000000000000"
|
||||
config KERNEL_START
|
||||
hex
|
||||
default "0xc000000002000000" if CRASH_DUMP
|
||||
default "0xc000000000000000"
|
||||
config PHYSICAL_START
|
||||
hex
|
||||
default "0x02000000" if CRASH_DUMP
|
||||
default "0x00000000"
|
||||
endif
|
||||
|
||||
source "net/Kconfig"
|
||||
|
1
arch/powerpc/boot/.gitignore
vendored
1
arch/powerpc/boot/.gitignore
vendored
@ -27,6 +27,7 @@ zImage.chrp
|
||||
zImage.coff
|
||||
zImage.coff.lds
|
||||
zImage.ep*
|
||||
zImage.iseries
|
||||
zImage.*lds
|
||||
zImage.miboot
|
||||
zImage.pmac
|
||||
|
@ -40,7 +40,7 @@ $(obj)/ebony.o: BOOTCFLAGS += -mcpu=405
|
||||
$(obj)/cuboot-taishan.o: BOOTCFLAGS += -mcpu=405
|
||||
$(obj)/cuboot-katmai.o: BOOTCFLAGS += -mcpu=405
|
||||
$(obj)/treeboot-walnut.o: BOOTCFLAGS += -mcpu=405
|
||||
$(obj)/virtex405-head.o: BOOTCFLAGS += -mcpu=405
|
||||
$(obj)/virtex405-head.o: BOOTAFLAGS += -mcpu=405
|
||||
|
||||
|
||||
zlib := inffast.c inflate.c inftrees.c
|
||||
|
@ -142,8 +142,45 @@
|
||||
#address-cells = <2>;
|
||||
#size-cells = <1>;
|
||||
clock-frequency = <0>; /* Filled in by U-Boot */
|
||||
/* ranges property is supplied by U-Boot */
|
||||
interrupts = <6 4>;
|
||||
interrupt-parent = <&UIC1>;
|
||||
|
||||
nor_flash@0,0 {
|
||||
compatible = "amd,s29gl512n", "cfi-flash";
|
||||
bank-width = <2>;
|
||||
reg = <0 000000 4000000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
partition@0 {
|
||||
label = "kernel";
|
||||
reg = <0 1e0000>;
|
||||
};
|
||||
partition@1e0000 {
|
||||
label = "dtb";
|
||||
reg = <1e0000 20000>;
|
||||
};
|
||||
partition@200000 {
|
||||
label = "ramdisk";
|
||||
reg = <200000 1400000>;
|
||||
};
|
||||
partition@1600000 {
|
||||
label = "jffs2";
|
||||
reg = <1600000 400000>;
|
||||
};
|
||||
partition@1a00000 {
|
||||
label = "user";
|
||||
reg = <1a00000 2560000>;
|
||||
};
|
||||
partition@3f60000 {
|
||||
label = "env";
|
||||
reg = <3f60000 40000>;
|
||||
};
|
||||
partition@3fa0000 {
|
||||
label = "u-boot";
|
||||
reg = <3fa0000 60000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
UART0: serial@ef600300 {
|
||||
|
@ -145,8 +145,45 @@
|
||||
#address-cells = <2>;
|
||||
#size-cells = <1>;
|
||||
clock-frequency = <0>; /* Filled in by U-Boot */
|
||||
/* ranges property is supplied by U-Boot */
|
||||
interrupts = <6 4>;
|
||||
interrupt-parent = <&UIC1>;
|
||||
|
||||
nor_flash@0,0 {
|
||||
compatible = "amd,s29gl512n", "cfi-flash";
|
||||
bank-width = <2>;
|
||||
reg = <0 000000 4000000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
partition@0 {
|
||||
label = "kernel";
|
||||
reg = <0 1e0000>;
|
||||
};
|
||||
partition@1e0000 {
|
||||
label = "dtb";
|
||||
reg = <1e0000 20000>;
|
||||
};
|
||||
partition@200000 {
|
||||
label = "ramdisk";
|
||||
reg = <200000 1400000>;
|
||||
};
|
||||
partition@1600000 {
|
||||
label = "jffs2";
|
||||
reg = <1600000 400000>;
|
||||
};
|
||||
partition@1a00000 {
|
||||
label = "user";
|
||||
reg = <1a00000 2560000>;
|
||||
};
|
||||
partition@3f60000 {
|
||||
label = "env";
|
||||
reg = <3f60000 40000>;
|
||||
};
|
||||
partition@3fa0000 {
|
||||
label = "u-boot";
|
||||
reg = <3fa0000 60000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
UART0: serial@ef600300 {
|
||||
|
@ -55,10 +55,15 @@ static u8 ns16550_tstc(void)
|
||||
int ns16550_console_init(void *devp, struct serial_console_data *scdp)
|
||||
{
|
||||
int n;
|
||||
u32 reg_offset;
|
||||
|
||||
if (dt_get_virtual_reg(devp, (void **)®_base, 1) < 1)
|
||||
return -1;
|
||||
|
||||
n = getprop(devp, "reg-offset", ®_offset, sizeof(reg_offset));
|
||||
if (n == sizeof(reg_offset))
|
||||
reg_base += reg_offset;
|
||||
|
||||
n = getprop(devp, "reg-shift", ®_shift, sizeof(reg_shift));
|
||||
if (n != sizeof(reg_shift))
|
||||
reg_shift = 0;
|
||||
|
@ -106,4 +106,13 @@ PHONY += systbl_chk
|
||||
systbl_chk: $(src)/systbl_chk.sh $(obj)/systbl_chk.i
|
||||
$(call cmd,systbl_chk)
|
||||
|
||||
$(obj)/built-in.o: prom_init_check
|
||||
|
||||
quiet_cmd_prom_init_check = CALL $<
|
||||
cmd_prom_init_check = $(CONFIG_SHELL) $< "$(NM)" "$(obj)/prom_init.o"
|
||||
|
||||
PHONY += prom_init_check
|
||||
prom_init_check: $(src)/prom_init_check.sh $(obj)/prom_init.o
|
||||
$(call cmd,prom_init_check)
|
||||
|
||||
clean-files := vmlinux.lds
|
||||
|
@ -93,10 +93,7 @@ int main(void)
|
||||
DEFINE(TI_LOCAL_FLAGS, offsetof(struct thread_info, local_flags));
|
||||
DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
|
||||
DEFINE(TI_TASK, offsetof(struct thread_info, task));
|
||||
#ifdef CONFIG_PPC32
|
||||
DEFINE(TI_EXECDOMAIN, offsetof(struct thread_info, exec_domain));
|
||||
DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
|
||||
#endif /* CONFIG_PPC32 */
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
DEFINE(DCACHEL1LINESIZE, offsetof(struct ppc64_caches, dline_size));
|
||||
@ -165,13 +162,9 @@ int main(void)
|
||||
|
||||
/* Interrupt register frame */
|
||||
DEFINE(STACK_FRAME_OVERHEAD, STACK_FRAME_OVERHEAD);
|
||||
#ifndef CONFIG_PPC64
|
||||
DEFINE(INT_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs));
|
||||
#else /* CONFIG_PPC64 */
|
||||
DEFINE(INT_FRAME_SIZE, STACK_INT_FRAME_SIZE);
|
||||
#ifdef CONFIG_PPC64
|
||||
DEFINE(SWITCH_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs));
|
||||
/* 288 = # of volatile regs, int & fp, for leaf routines */
|
||||
/* which do not stack a frame. See the PPC64 ABI. */
|
||||
DEFINE(INT_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 288);
|
||||
/* Create extra stack space for SRR0 and SRR1 when calling prom/rtas. */
|
||||
DEFINE(PROM_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 16);
|
||||
DEFINE(RTAS_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 16);
|
||||
|
@ -33,7 +33,6 @@ _GLOBAL(__setup_cpu_440grx)
|
||||
mtlr r4
|
||||
blr
|
||||
_GLOBAL(__setup_cpu_460ex)
|
||||
_GLOBAL(__setup_cpu_460gt)
|
||||
b __init_fpu_44x
|
||||
_GLOBAL(__setup_cpu_440gx)
|
||||
_GLOBAL(__setup_cpu_440spe)
|
||||
|
@ -17,7 +17,13 @@
|
||||
#include <asm/cache.h>
|
||||
|
||||
_GLOBAL(__setup_cpu_603)
|
||||
b setup_common_caches
|
||||
mflr r4
|
||||
BEGIN_FTR_SECTION
|
||||
bl __init_fpu_registers
|
||||
END_FTR_SECTION_IFCLR(CPU_FTR_FPU_UNAVAILABLE)
|
||||
bl setup_common_caches
|
||||
mtlr r4
|
||||
blr
|
||||
_GLOBAL(__setup_cpu_604)
|
||||
mflr r4
|
||||
bl setup_common_caches
|
||||
|
@ -37,7 +37,6 @@ extern void __setup_cpu_440gx(unsigned long offset, struct cpu_spec* spec);
|
||||
extern void __setup_cpu_440grx(unsigned long offset, struct cpu_spec* spec);
|
||||
extern void __setup_cpu_440spe(unsigned long offset, struct cpu_spec* spec);
|
||||
extern void __setup_cpu_460ex(unsigned long offset, struct cpu_spec* spec);
|
||||
extern void __setup_cpu_460gt(unsigned long offset, struct cpu_spec* spec);
|
||||
extern void __setup_cpu_603(unsigned long offset, struct cpu_spec* spec);
|
||||
extern void __setup_cpu_604(unsigned long offset, struct cpu_spec* spec);
|
||||
extern void __setup_cpu_750(unsigned long offset, struct cpu_spec* spec);
|
||||
@ -1416,10 +1415,9 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.pvr_value = 0x13020000,
|
||||
.cpu_name = "460GT",
|
||||
.cpu_features = CPU_FTRS_44X,
|
||||
.cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU,
|
||||
.cpu_user_features = COMMON_USER_BOOKE,
|
||||
.icache_bsize = 32,
|
||||
.dcache_bsize = 32,
|
||||
.cpu_setup = __setup_cpu_460gt,
|
||||
.machine_check = machine_check_440A,
|
||||
.platform = "ppc440",
|
||||
},
|
||||
|
@ -371,6 +371,17 @@ skpinv: addi r6,r6,1 /* Increment */
|
||||
|
||||
bl early_init
|
||||
|
||||
#ifdef CONFIG_RELOCATABLE
|
||||
lis r3,kernstart_addr@ha
|
||||
la r3,kernstart_addr@l(r3)
|
||||
#ifdef CONFIG_PHYS_64BIT
|
||||
stw r23,0(r3)
|
||||
stw r25,4(r3)
|
||||
#else
|
||||
stw r25,0(r3)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
mfspr r3,SPRN_TLB1CFG
|
||||
andi. r3,r3,0xfff
|
||||
lis r4,num_tlbcam_entries@ha
|
||||
|
@ -152,7 +152,7 @@ _GLOBAL(low_choose_750fx_pll)
|
||||
mtspr SPRN_HID1,r4
|
||||
|
||||
/* Store new HID1 image */
|
||||
rlwinm r6,r1,0,0,18
|
||||
rlwinm r6,r1,0,0,(31-THREAD_SHIFT)
|
||||
lwz r6,TI_CPU(r6)
|
||||
slwi r6,r6,2
|
||||
addis r6,r6,nap_save_hid1@ha
|
||||
@ -281,7 +281,7 @@ _GLOBAL(_tlbia)
|
||||
#endif /* CONFIG_SMP */
|
||||
#else /* !(CONFIG_40x || CONFIG_44x || CONFIG_FSL_BOOKE) */
|
||||
#if defined(CONFIG_SMP)
|
||||
rlwinm r8,r1,0,0,18
|
||||
rlwinm r8,r1,0,0,(31-THREAD_SHIFT)
|
||||
lwz r8,TI_CPU(r8)
|
||||
oris r8,r8,10
|
||||
mfmsr r10
|
||||
@ -377,7 +377,7 @@ _GLOBAL(_tlbie)
|
||||
#endif /* CONFIG_SMP */
|
||||
#else /* !(CONFIG_40x || CONFIG_44x || CONFIG_FSL_BOOKE) */
|
||||
#if defined(CONFIG_SMP)
|
||||
rlwinm r8,r1,0,0,18
|
||||
rlwinm r8,r1,0,0,(31-THREAD_SHIFT)
|
||||
lwz r8,TI_CPU(r8)
|
||||
oris r8,r8,11
|
||||
mfmsr r10
|
||||
|
@ -27,23 +27,11 @@
|
||||
|
||||
.text
|
||||
|
||||
_GLOBAL(get_msr)
|
||||
mfmsr r3
|
||||
blr
|
||||
|
||||
_GLOBAL(get_srr0)
|
||||
mfsrr0 r3
|
||||
blr
|
||||
|
||||
_GLOBAL(get_srr1)
|
||||
mfsrr1 r3
|
||||
blr
|
||||
|
||||
#ifdef CONFIG_IRQSTACKS
|
||||
_GLOBAL(call_do_softirq)
|
||||
mflr r0
|
||||
std r0,16(r1)
|
||||
stdu r1,THREAD_SIZE-112(r3)
|
||||
stdu r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r3)
|
||||
mr r1,r3
|
||||
bl .__do_softirq
|
||||
ld r1,0(r1)
|
||||
@ -56,7 +44,7 @@ _GLOBAL(call_handle_irq)
|
||||
mflr r0
|
||||
std r0,16(r1)
|
||||
mtctr r8
|
||||
stdu r1,THREAD_SIZE-112(r5)
|
||||
stdu r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r5)
|
||||
mr r1,r5
|
||||
bctrl
|
||||
ld r1,0(r1)
|
||||
@ -599,7 +587,7 @@ _GLOBAL(kexec_sequence)
|
||||
std r0,16(r1)
|
||||
|
||||
/* switch stacks to newstack -- &kexec_stack.stack */
|
||||
stdu r1,THREAD_SIZE-112(r3)
|
||||
stdu r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r3)
|
||||
mr r1,r3
|
||||
|
||||
li r0,0
|
||||
@ -616,7 +604,7 @@ _GLOBAL(kexec_sequence)
|
||||
std r26,-48(r1)
|
||||
std r25,-56(r1)
|
||||
|
||||
stdu r1,-112-64(r1)
|
||||
stdu r1,-STACK_FRAME_OVERHEAD-64(r1)
|
||||
|
||||
/* save args into preserved regs */
|
||||
mr r31,r3 /* newstack (both) */
|
||||
|
@ -275,6 +275,8 @@ static int __devinit of_pci_phb_probe(struct of_device *dev,
|
||||
|
||||
/* Scan the bus */
|
||||
scan_phb(phb);
|
||||
if (phb->bus == NULL)
|
||||
return -ENXIO;
|
||||
|
||||
/* Claim resources. This might need some rework as well depending
|
||||
* wether we are doing probe-only or not, like assigning unassigned
|
||||
|
@ -7,17 +7,11 @@
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/threads.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <asm/processor.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/lppaca.h>
|
||||
#include <asm/paca.h>
|
||||
#include <asm/mmu.h>
|
||||
|
||||
|
||||
/* This symbol is provided by the linker - let it fill in the paca
|
||||
* field correctly */
|
||||
@ -65,60 +59,29 @@ struct slb_shadow slb_shadow[] __cacheline_aligned = {
|
||||
* processors. The processor VPD array needs one entry per physical
|
||||
* processor (not thread).
|
||||
*/
|
||||
#define PACA_INIT(number) \
|
||||
{ \
|
||||
.lppaca_ptr = &lppaca[number], \
|
||||
.lock_token = 0x8000, \
|
||||
.paca_index = (number), /* Paca Index */ \
|
||||
.kernel_toc = (unsigned long)(&__toc_start) + 0x8000UL, \
|
||||
.hw_cpu_id = 0xffff, \
|
||||
.slb_shadow_ptr = &slb_shadow[number], \
|
||||
.__current = &init_task, \
|
||||
}
|
||||
|
||||
struct paca_struct paca[] = {
|
||||
PACA_INIT(0),
|
||||
#if NR_CPUS > 1
|
||||
PACA_INIT( 1), PACA_INIT( 2), PACA_INIT( 3),
|
||||
#if NR_CPUS > 4
|
||||
PACA_INIT( 4), PACA_INIT( 5), PACA_INIT( 6), PACA_INIT( 7),
|
||||
#if NR_CPUS > 8
|
||||
PACA_INIT( 8), PACA_INIT( 9), PACA_INIT( 10), PACA_INIT( 11),
|
||||
PACA_INIT( 12), PACA_INIT( 13), PACA_INIT( 14), PACA_INIT( 15),
|
||||
PACA_INIT( 16), PACA_INIT( 17), PACA_INIT( 18), PACA_INIT( 19),
|
||||
PACA_INIT( 20), PACA_INIT( 21), PACA_INIT( 22), PACA_INIT( 23),
|
||||
PACA_INIT( 24), PACA_INIT( 25), PACA_INIT( 26), PACA_INIT( 27),
|
||||
PACA_INIT( 28), PACA_INIT( 29), PACA_INIT( 30), PACA_INIT( 31),
|
||||
#if NR_CPUS > 32
|
||||
PACA_INIT( 32), PACA_INIT( 33), PACA_INIT( 34), PACA_INIT( 35),
|
||||
PACA_INIT( 36), PACA_INIT( 37), PACA_INIT( 38), PACA_INIT( 39),
|
||||
PACA_INIT( 40), PACA_INIT( 41), PACA_INIT( 42), PACA_INIT( 43),
|
||||
PACA_INIT( 44), PACA_INIT( 45), PACA_INIT( 46), PACA_INIT( 47),
|
||||
PACA_INIT( 48), PACA_INIT( 49), PACA_INIT( 50), PACA_INIT( 51),
|
||||
PACA_INIT( 52), PACA_INIT( 53), PACA_INIT( 54), PACA_INIT( 55),
|
||||
PACA_INIT( 56), PACA_INIT( 57), PACA_INIT( 58), PACA_INIT( 59),
|
||||
PACA_INIT( 60), PACA_INIT( 61), PACA_INIT( 62), PACA_INIT( 63),
|
||||
#if NR_CPUS > 64
|
||||
PACA_INIT( 64), PACA_INIT( 65), PACA_INIT( 66), PACA_INIT( 67),
|
||||
PACA_INIT( 68), PACA_INIT( 69), PACA_INIT( 70), PACA_INIT( 71),
|
||||
PACA_INIT( 72), PACA_INIT( 73), PACA_INIT( 74), PACA_INIT( 75),
|
||||
PACA_INIT( 76), PACA_INIT( 77), PACA_INIT( 78), PACA_INIT( 79),
|
||||
PACA_INIT( 80), PACA_INIT( 81), PACA_INIT( 82), PACA_INIT( 83),
|
||||
PACA_INIT( 84), PACA_INIT( 85), PACA_INIT( 86), PACA_INIT( 87),
|
||||
PACA_INIT( 88), PACA_INIT( 89), PACA_INIT( 90), PACA_INIT( 91),
|
||||
PACA_INIT( 92), PACA_INIT( 93), PACA_INIT( 94), PACA_INIT( 95),
|
||||
PACA_INIT( 96), PACA_INIT( 97), PACA_INIT( 98), PACA_INIT( 99),
|
||||
PACA_INIT(100), PACA_INIT(101), PACA_INIT(102), PACA_INIT(103),
|
||||
PACA_INIT(104), PACA_INIT(105), PACA_INIT(106), PACA_INIT(107),
|
||||
PACA_INIT(108), PACA_INIT(109), PACA_INIT(110), PACA_INIT(111),
|
||||
PACA_INIT(112), PACA_INIT(113), PACA_INIT(114), PACA_INIT(115),
|
||||
PACA_INIT(116), PACA_INIT(117), PACA_INIT(118), PACA_INIT(119),
|
||||
PACA_INIT(120), PACA_INIT(121), PACA_INIT(122), PACA_INIT(123),
|
||||
PACA_INIT(124), PACA_INIT(125), PACA_INIT(126), PACA_INIT(127),
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
struct paca_struct paca[NR_CPUS];
|
||||
EXPORT_SYMBOL(paca);
|
||||
|
||||
void __init initialise_pacas(void)
|
||||
{
|
||||
int cpu;
|
||||
|
||||
/* The TOC register (GPR2) points 32kB into the TOC, so that 64kB
|
||||
* of the TOC can be addressed using a single machine instruction.
|
||||
*/
|
||||
unsigned long kernel_toc = (unsigned long)(&__toc_start) + 0x8000UL;
|
||||
|
||||
/* Can't use for_each_*_cpu, as they aren't functional yet */
|
||||
for (cpu = 0; cpu < NR_CPUS; cpu++) {
|
||||
struct paca_struct *new_paca = &paca[cpu];
|
||||
|
||||
new_paca->lppaca_ptr = &lppaca[cpu];
|
||||
new_paca->lock_token = 0x8000;
|
||||
new_paca->paca_index = cpu;
|
||||
new_paca->kernel_toc = kernel_toc;
|
||||
new_paca->hw_cpu_id = 0xffff;
|
||||
new_paca->slb_shadow_ptr = &slb_shadow[cpu];
|
||||
new_paca->__current = &init_task;
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -135,6 +135,4 @@ struct ucontext32 {
|
||||
struct mcontext32 uc_mcontext;
|
||||
};
|
||||
|
||||
extern int copy_siginfo_to_user32(struct compat_siginfo __user *d, siginfo_t *s);
|
||||
|
||||
#endif /* _PPC64_PPC32_H */
|
||||
|
@ -1033,3 +1033,34 @@ void ppc64_runlatch_off(void)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if THREAD_SHIFT < PAGE_SHIFT
|
||||
|
||||
static struct kmem_cache *thread_info_cache;
|
||||
|
||||
struct thread_info *alloc_thread_info(struct task_struct *tsk)
|
||||
{
|
||||
struct thread_info *ti;
|
||||
|
||||
ti = kmem_cache_alloc(thread_info_cache, GFP_KERNEL);
|
||||
if (unlikely(ti == NULL))
|
||||
return NULL;
|
||||
#ifdef CONFIG_DEBUG_STACK_USAGE
|
||||
memset(ti, 0, THREAD_SIZE);
|
||||
#endif
|
||||
return ti;
|
||||
}
|
||||
|
||||
void free_thread_info(struct thread_info *ti)
|
||||
{
|
||||
kmem_cache_free(thread_info_cache, ti);
|
||||
}
|
||||
|
||||
void thread_info_cache_init(void)
|
||||
{
|
||||
thread_info_cache = kmem_cache_create("thread_info", THREAD_SIZE,
|
||||
THREAD_SIZE, 0, NULL);
|
||||
BUG_ON(thread_info_cache == NULL);
|
||||
}
|
||||
|
||||
#endif /* THREAD_SHIFT < PAGE_SHIFT */
|
||||
|
@ -53,6 +53,7 @@
|
||||
#include <asm/pci-bridge.h>
|
||||
#include <asm/phyp_dump.h>
|
||||
#include <asm/kexec.h>
|
||||
#include <mm/mmu_decl.h>
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DBG(fmt...) printk(KERN_ERR fmt)
|
||||
@ -978,7 +979,10 @@ static int __init early_init_dt_scan_memory(unsigned long node,
|
||||
}
|
||||
#endif
|
||||
lmb_add(base, size);
|
||||
|
||||
memstart_addr = min((u64)memstart_addr, base);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
58
arch/powerpc/kernel/prom_init_check.sh
Normal file
58
arch/powerpc/kernel/prom_init_check.sh
Normal file
@ -0,0 +1,58 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright © 2008 IBM Corporation
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version
|
||||
# 2 of the License, or (at your option) any later version.
|
||||
|
||||
# This script checks prom_init.o to see what external symbols it
|
||||
# is using, if it finds symbols not in the whitelist it returns
|
||||
# an error. The point of this is to discourage people from
|
||||
# intentionally or accidentally adding new code to prom_init.c
|
||||
# which has side effects on other parts of the kernel.
|
||||
|
||||
# If you really need to reference something from prom_init.o add
|
||||
# it to the list below:
|
||||
|
||||
WHITELIST="add_reloc_offset __bss_start __bss_stop copy_and_flush
|
||||
_end enter_prom memcpy memset reloc_offset __secondary_hold
|
||||
__secondary_hold_acknowledge __secondary_hold_spinloop __start
|
||||
strcmp strcpy strlcpy strlen strncmp strstr logo_linux_clut224
|
||||
reloc_got2"
|
||||
|
||||
NM="$1"
|
||||
OBJ="$2"
|
||||
|
||||
ERROR=0
|
||||
|
||||
for UNDEF in $($NM -u $OBJ | awk '{print $2}')
|
||||
do
|
||||
# On 64-bit nm gives us the function descriptors, which have
|
||||
# a leading . on the name, so strip it off here.
|
||||
UNDEF="${UNDEF#.}"
|
||||
|
||||
if [ $KBUILD_VERBOSE ]; then
|
||||
if [ $KBUILD_VERBOSE -ne 0 ]; then
|
||||
echo "Checking prom_init.o symbol '$UNDEF'"
|
||||
fi
|
||||
fi
|
||||
|
||||
OK=0
|
||||
for WHITE in $WHITELIST
|
||||
do
|
||||
if [ "$UNDEF" = "$WHITE" ]; then
|
||||
OK=1
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [ $OK -eq 0 ]; then
|
||||
ERROR=1
|
||||
echo "Error: External symbol '$UNDEF' referenced" \
|
||||
"from prom_init.c" >&2
|
||||
fi
|
||||
done
|
||||
|
||||
exit $ERROR
|
@ -29,15 +29,12 @@
|
||||
#include <linux/security.h>
|
||||
#include <linux/signal.h>
|
||||
#include <linux/compat.h>
|
||||
#include <linux/elf.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/system.h>
|
||||
|
||||
#include "ppc32.h"
|
||||
|
||||
/*
|
||||
* does not yet catch signals sent when the child dies.
|
||||
* in exit.c or in signal.c.
|
||||
@ -67,27 +64,6 @@ static long compat_ptrace_old(struct task_struct *child, long request,
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
static int compat_ptrace_getsiginfo(struct task_struct *child, compat_siginfo_t __user *data)
|
||||
{
|
||||
siginfo_t lastinfo;
|
||||
int error = -ESRCH;
|
||||
|
||||
read_lock(&tasklist_lock);
|
||||
if (likely(child->sighand != NULL)) {
|
||||
error = -EINVAL;
|
||||
spin_lock_irq(&child->sighand->siglock);
|
||||
if (likely(child->last_siginfo != NULL)) {
|
||||
lastinfo = *child->last_siginfo;
|
||||
error = 0;
|
||||
}
|
||||
spin_unlock_irq(&child->sighand->siglock);
|
||||
}
|
||||
read_unlock(&tasklist_lock);
|
||||
if (!error)
|
||||
return copy_siginfo_to_user32(data, &lastinfo);
|
||||
return error;
|
||||
}
|
||||
|
||||
long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
|
||||
compat_ulong_t caddr, compat_ulong_t cdata)
|
||||
{
|
||||
@ -306,9 +282,6 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
|
||||
0, PT_REGS_COUNT * sizeof(compat_long_t),
|
||||
compat_ptr(data));
|
||||
|
||||
case PTRACE_GETSIGINFO:
|
||||
return compat_ptrace_getsiginfo(child, compat_ptr(data));
|
||||
|
||||
case PTRACE_GETFPREGS:
|
||||
case PTRACE_SETFPREGS:
|
||||
case PTRACE_GETVRREGS:
|
||||
|
@ -170,6 +170,9 @@ void __init setup_paca(int cpu)
|
||||
|
||||
void __init early_setup(unsigned long dt_ptr)
|
||||
{
|
||||
/* Fill in any unititialised pacas */
|
||||
initialise_pacas();
|
||||
|
||||
/* Identify CPU type */
|
||||
identify_cpu(0, mfspr(SPRN_PVR));
|
||||
|
||||
@ -435,7 +438,7 @@ void __init setup_system(void)
|
||||
printk("htab_address = 0x%p\n", htab_address);
|
||||
printk("htab_hash_mask = 0x%lx\n", htab_hash_mask);
|
||||
#if PHYSICAL_START > 0
|
||||
printk("physical_start = 0x%x\n", PHYSICAL_START);
|
||||
printk("physical_start = 0x%lx\n", PHYSICAL_START);
|
||||
#endif
|
||||
printk("-----------------------------------------------------\n");
|
||||
|
||||
|
@ -13,7 +13,6 @@
|
||||
#include <linux/sched.h>
|
||||
#include <linux/stacktrace.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/asm-offsets.h>
|
||||
|
||||
/*
|
||||
* Save stack-backtrace addresses into a stack_trace buffer.
|
||||
|
@ -154,8 +154,8 @@ static void udbg_console_write(struct console *con, const char *s,
|
||||
static struct console udbg_console = {
|
||||
.name = "udbg",
|
||||
.write = udbg_console_write,
|
||||
.flags = CON_PRINTBUFFER | CON_ENABLED | CON_BOOT,
|
||||
.index = -1,
|
||||
.flags = CON_PRINTBUFFER | CON_ENABLED | CON_BOOT | CON_ANYTIME,
|
||||
.index = 0,
|
||||
};
|
||||
|
||||
static int early_console_initialized;
|
||||
|
@ -202,7 +202,7 @@ adjust_total_lowmem(void)
|
||||
cam_max_size = max_lowmem_size;
|
||||
|
||||
/* adjust lowmem size to max_lowmem_size */
|
||||
ram = min(max_lowmem_size, total_lowmem);
|
||||
ram = min(max_lowmem_size, (phys_addr_t)total_lowmem);
|
||||
|
||||
/* Calculate CAM values */
|
||||
__cam0 = 1UL << 2 * (__ilog2(ram) / 2);
|
||||
|
@ -191,7 +191,7 @@ _GLOBAL(add_hash_page)
|
||||
add r3,r3,r0 /* note create_hpte trims to 24 bits */
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
rlwinm r8,r1,0,0,18 /* use cpu number to make tag */
|
||||
rlwinm r8,r1,0,0,(31-THREAD_SHIFT) /* use cpu number to make tag */
|
||||
lwz r8,TI_CPU(r8) /* to go in mmu_hash_lock */
|
||||
oris r8,r8,12
|
||||
#endif /* CONFIG_SMP */
|
||||
@ -526,7 +526,7 @@ _GLOBAL(flush_hash_pages)
|
||||
#ifdef CONFIG_SMP
|
||||
addis r9,r7,mmu_hash_lock@ha
|
||||
addi r9,r9,mmu_hash_lock@l
|
||||
rlwinm r8,r1,0,0,18
|
||||
rlwinm r8,r1,0,0,(31-THREAD_SHIFT)
|
||||
add r8,r8,r7
|
||||
lwz r8,TI_CPU(r8)
|
||||
oris r8,r8,9
|
||||
|
@ -59,7 +59,10 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
|
||||
unsigned long total_memory;
|
||||
unsigned long total_lowmem;
|
||||
|
||||
phys_addr_t memstart_addr;
|
||||
phys_addr_t memstart_addr = (phys_addr_t)~0ull;
|
||||
EXPORT_SYMBOL(memstart_addr);
|
||||
phys_addr_t kernstart_addr;
|
||||
EXPORT_SYMBOL(kernstart_addr);
|
||||
phys_addr_t lowmem_end_addr;
|
||||
|
||||
int boot_mapsize;
|
||||
@ -68,14 +71,6 @@ unsigned long agp_special_page;
|
||||
EXPORT_SYMBOL(agp_special_page);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_HIGHMEM
|
||||
pte_t *kmap_pte;
|
||||
pgprot_t kmap_prot;
|
||||
|
||||
EXPORT_SYMBOL(kmap_prot);
|
||||
EXPORT_SYMBOL(kmap_pte);
|
||||
#endif
|
||||
|
||||
void MMU_init(void);
|
||||
|
||||
/* XXX should be in current.h -- paulus */
|
||||
|
@ -72,7 +72,8 @@
|
||||
#warning TASK_SIZE is smaller than it needs to be.
|
||||
#endif
|
||||
|
||||
phys_addr_t memstart_addr;
|
||||
phys_addr_t memstart_addr = ~0;
|
||||
phys_addr_t kernstart_addr;
|
||||
|
||||
void free_initmem(void)
|
||||
{
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include <asm/tlb.h>
|
||||
#include <asm/sections.h>
|
||||
#include <asm/vdso.h>
|
||||
#include <asm/fixmap.h>
|
||||
|
||||
#include "mmu_decl.h"
|
||||
|
||||
@ -57,6 +58,20 @@ int init_bootmem_done;
|
||||
int mem_init_done;
|
||||
unsigned long memory_limit;
|
||||
|
||||
#ifdef CONFIG_HIGHMEM
|
||||
pte_t *kmap_pte;
|
||||
pgprot_t kmap_prot;
|
||||
|
||||
EXPORT_SYMBOL(kmap_prot);
|
||||
EXPORT_SYMBOL(kmap_pte);
|
||||
|
||||
static inline pte_t *virt_to_kpte(unsigned long vaddr)
|
||||
{
|
||||
return pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr),
|
||||
vaddr), vaddr), vaddr);
|
||||
}
|
||||
#endif
|
||||
|
||||
int page_is_ram(unsigned long pfn)
|
||||
{
|
||||
unsigned long paddr = (pfn << PAGE_SHIFT);
|
||||
@ -216,7 +231,7 @@ void __init do_init_bootmem(void)
|
||||
unsigned long total_pages;
|
||||
int boot_mapsize;
|
||||
|
||||
max_pfn = lmb_end_of_DRAM() >> PAGE_SHIFT;
|
||||
max_low_pfn = max_pfn = lmb_end_of_DRAM() >> PAGE_SHIFT;
|
||||
total_pages = (lmb_end_of_DRAM() - memstart_addr) >> PAGE_SHIFT;
|
||||
#ifdef CONFIG_HIGHMEM
|
||||
total_pages = total_lowmem >> PAGE_SHIFT;
|
||||
@ -232,7 +247,8 @@ void __init do_init_bootmem(void)
|
||||
|
||||
start = lmb_alloc(bootmap_pages << PAGE_SHIFT, PAGE_SIZE);
|
||||
|
||||
boot_mapsize = init_bootmem(start >> PAGE_SHIFT, total_pages);
|
||||
min_low_pfn = MEMORY_START >> PAGE_SHIFT;
|
||||
boot_mapsize = init_bootmem_node(NODE_DATA(0), start >> PAGE_SHIFT, min_low_pfn, max_low_pfn);
|
||||
|
||||
/* Add active regions with valid PFNs */
|
||||
for (i = 0; i < lmb.memory.cnt; i++) {
|
||||
@ -310,14 +326,19 @@ void __init paging_init(void)
|
||||
unsigned long top_of_ram = lmb_end_of_DRAM();
|
||||
unsigned long max_zone_pfns[MAX_NR_ZONES];
|
||||
|
||||
#ifdef CONFIG_PPC32
|
||||
unsigned long v = __fix_to_virt(__end_of_fixed_addresses - 1);
|
||||
unsigned long end = __fix_to_virt(FIX_HOLE);
|
||||
|
||||
for (; v < end; v += PAGE_SIZE)
|
||||
map_page(v, 0, 0); /* XXX gross */
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_HIGHMEM
|
||||
map_page(PKMAP_BASE, 0, 0); /* XXX gross */
|
||||
pkmap_page_table = pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k
|
||||
(PKMAP_BASE), PKMAP_BASE), PKMAP_BASE), PKMAP_BASE);
|
||||
map_page(KMAP_FIX_BEGIN, 0, 0); /* XXX gross */
|
||||
kmap_pte = pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k
|
||||
(KMAP_FIX_BEGIN), KMAP_FIX_BEGIN), KMAP_FIX_BEGIN),
|
||||
KMAP_FIX_BEGIN);
|
||||
pkmap_page_table = virt_to_kpte(PKMAP_BASE);
|
||||
|
||||
kmap_pte = virt_to_kpte(__fix_to_virt(FIX_KMAP_BEGIN));
|
||||
kmap_prot = PAGE_KERNEL;
|
||||
#endif /* CONFIG_HIGHMEM */
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/lmb.h>
|
||||
#include <linux/of.h>
|
||||
#include <asm/sparsemem.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/system.h>
|
||||
|
@ -29,6 +29,7 @@
|
||||
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/pgalloc.h>
|
||||
#include <asm/fixmap.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#include "mmu_decl.h"
|
||||
@ -387,3 +388,25 @@ void kernel_map_pages(struct page *page, int numpages, int enable)
|
||||
change_page_attr(page, numpages, enable ? PAGE_KERNEL : __pgprot(0));
|
||||
}
|
||||
#endif /* CONFIG_DEBUG_PAGEALLOC */
|
||||
|
||||
static int fixmaps;
|
||||
unsigned long FIXADDR_TOP = 0xfffff000;
|
||||
EXPORT_SYMBOL(FIXADDR_TOP);
|
||||
|
||||
void __set_fixmap (enum fixed_addresses idx, phys_addr_t phys, pgprot_t flags)
|
||||
{
|
||||
unsigned long address = __fix_to_virt(idx);
|
||||
|
||||
if (idx >= __end_of_fixed_addresses) {
|
||||
BUG();
|
||||
return;
|
||||
}
|
||||
|
||||
map_page(address, phys, flags);
|
||||
fixmaps++;
|
||||
}
|
||||
|
||||
void __this_fixmap_does_not_exist(void)
|
||||
{
|
||||
WARN_ON(1);
|
||||
}
|
||||
|
@ -45,7 +45,6 @@ source "arch/powerpc/platforms/powermac/Kconfig"
|
||||
source "arch/powerpc/platforms/prep/Kconfig"
|
||||
source "arch/powerpc/platforms/maple/Kconfig"
|
||||
source "arch/powerpc/platforms/pasemi/Kconfig"
|
||||
source "arch/powerpc/platforms/celleb/Kconfig"
|
||||
source "arch/powerpc/platforms/ps3/Kconfig"
|
||||
source "arch/powerpc/platforms/cell/Kconfig"
|
||||
source "arch/powerpc/platforms/8xx/Kconfig"
|
||||
|
@ -220,8 +220,8 @@ config SMP
|
||||
If you don't know what to do here, say N.
|
||||
|
||||
config NR_CPUS
|
||||
int "Maximum number of CPUs (2-128)"
|
||||
range 2 128
|
||||
int "Maximum number of CPUs (2-1024)"
|
||||
range 2 1024
|
||||
depends on SMP
|
||||
default "32" if PPC64
|
||||
default "4"
|
||||
|
@ -24,5 +24,4 @@ obj-$(CONFIG_PPC_MAPLE) += maple/
|
||||
obj-$(CONFIG_PPC_PASEMI) += pasemi/
|
||||
obj-$(CONFIG_PPC_CELL) += cell/
|
||||
obj-$(CONFIG_PPC_PS3) += ps3/
|
||||
obj-$(CONFIG_PPC_CELLEB) += celleb/
|
||||
obj-$(CONFIG_EMBEDDED6xx) += embedded6xx/
|
||||
|
@ -25,6 +25,19 @@ config PPC_IBM_CELL_BLADE
|
||||
select PPC_UDBG_16550
|
||||
select UDBG_RTAS_CONSOLE
|
||||
|
||||
config PPC_CELLEB
|
||||
bool "Toshiba's Cell Reference Set 'Celleb' Architecture"
|
||||
depends on PPC_MULTIPLATFORM && PPC64
|
||||
select PPC_CELL
|
||||
select PPC_CELL_NATIVE
|
||||
select PPC_RTAS
|
||||
select PPC_INDIRECT_IO
|
||||
select PPC_OF_PLATFORM_PCI
|
||||
select HAS_TXX9_SERIAL
|
||||
select PPC_UDBG_BEAT
|
||||
select USB_OHCI_BIG_ENDIAN_MMIO
|
||||
select USB_EHCI_BIG_ENDIAN_MMIO
|
||||
|
||||
menu "Cell Broadband Engine options"
|
||||
depends on PPC_CELL
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
obj-$(CONFIG_PPC_CELL_NATIVE) += interrupt.o iommu.o setup.o \
|
||||
cbe_regs.o spider-pic.o \
|
||||
pervasive.o pmu.o io-workarounds.o
|
||||
pervasive.o pmu.o io-workarounds.o \
|
||||
spider-pci.o
|
||||
obj-$(CONFIG_CBE_RAS) += ras.o
|
||||
|
||||
obj-$(CONFIG_CBE_THERM) += cbe_thermal.o
|
||||
@ -26,3 +27,20 @@ obj-$(CONFIG_SPU_BASE) += spu_callbacks.o spu_base.o \
|
||||
spufs/
|
||||
|
||||
obj-$(CONFIG_PCI_MSI) += axon_msi.o
|
||||
|
||||
|
||||
# celleb stuff
|
||||
ifeq ($(CONFIG_PPC_CELLEB),y)
|
||||
obj-y += celleb_setup.o \
|
||||
celleb_pci.o celleb_scc_epci.o \
|
||||
celleb_scc_pciex.o \
|
||||
celleb_scc_uhc.o \
|
||||
io-workarounds.o spider-pci.o \
|
||||
beat.o beat_htab.o beat_hvCall.o \
|
||||
beat_interrupt.o beat_iommu.o
|
||||
|
||||
obj-$(CONFIG_SMP) += beat_smp.o
|
||||
obj-$(CONFIG_PPC_UDBG_BEAT) += beat_udbg.o
|
||||
obj-$(CONFIG_SERIAL_TXX9) += celleb_scc_sio.o
|
||||
obj-$(CONFIG_SPU_BASE) += beat_spu_priv1.o
|
||||
endif
|
||||
|
@ -123,7 +123,7 @@ static struct axon_msic *find_msi_translator(struct pci_dev *dev)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (; dn; tmp = of_get_parent(dn), of_node_put(dn), dn = tmp) {
|
||||
for (; dn; dn = of_get_next_parent(dn)) {
|
||||
ph = of_get_property(dn, "msi-translator", NULL);
|
||||
if (ph)
|
||||
break;
|
||||
@ -169,7 +169,7 @@ static int axon_msi_check_device(struct pci_dev *dev, int nvec, int type)
|
||||
|
||||
static int setup_msi_msg_address(struct pci_dev *dev, struct msi_msg *msg)
|
||||
{
|
||||
struct device_node *dn, *tmp;
|
||||
struct device_node *dn;
|
||||
struct msi_desc *entry;
|
||||
int len;
|
||||
const u32 *prop;
|
||||
@ -182,7 +182,7 @@ static int setup_msi_msg_address(struct pci_dev *dev, struct msi_msg *msg)
|
||||
|
||||
entry = list_first_entry(&dev->msi_list, struct msi_desc, list);
|
||||
|
||||
for (; dn; tmp = of_get_parent(dn), of_node_put(dn), dn = tmp) {
|
||||
for (; dn; dn = of_get_next_parent(dn)) {
|
||||
if (entry->msi_attrib.is_64) {
|
||||
prop = of_get_property(dn, "msi-address-64", &len);
|
||||
if (prop)
|
||||
|
@ -33,7 +33,7 @@
|
||||
|
||||
#include "beat_wrapper.h"
|
||||
#include "beat.h"
|
||||
#include "interrupt.h"
|
||||
#include "beat_interrupt.h"
|
||||
|
||||
static int beat_pm_poweroff_flag;
|
||||
|
@ -26,7 +26,7 @@
|
||||
|
||||
#include <asm/machdep.h>
|
||||
|
||||
#include "interrupt.h"
|
||||
#include "beat_interrupt.h"
|
||||
#include "beat_wrapper.h"
|
||||
|
||||
#define MAX_IRQS NR_IRQS
|
@ -37,7 +37,7 @@
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/udbg.h>
|
||||
|
||||
#include "interrupt.h"
|
||||
#include "beat_interrupt.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DBG(fmt...) udbg_printf(fmt)
|
@ -37,12 +37,11 @@
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/pci-bridge.h>
|
||||
#include <asm/ppc-pci.h>
|
||||
|
||||
#include "pci.h"
|
||||
#include "interrupt.h"
|
||||
#include "io-workarounds.h"
|
||||
#include "celleb_pci.h"
|
||||
|
||||
#define MAX_PCI_DEVICES 32
|
||||
#define MAX_PCI_FUNCTIONS 8
|
||||
@ -190,7 +189,7 @@ static int celleb_fake_pci_read_config(struct pci_bus *bus,
|
||||
|
||||
|
||||
static int celleb_fake_pci_write_config(struct pci_bus *bus,
|
||||
unsigned int devfn, int where, int size, u32 val)
|
||||
unsigned int devfn, int where, int size, u32 val)
|
||||
{
|
||||
char *config;
|
||||
struct device_node *node;
|
||||
@ -457,33 +456,42 @@ static int __init celleb_setup_fake_pci(struct device_node *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __init fake_pci_workaround_init(struct pci_controller *phb)
|
||||
{
|
||||
/**
|
||||
* We will add fake pci bus to scc_pci_bus for the purpose to improve
|
||||
* I/O Macro performance. But device-tree and device drivers
|
||||
* are not ready to use address with a token.
|
||||
*/
|
||||
|
||||
/* celleb_pci_add_one(phb, NULL); */
|
||||
}
|
||||
static struct celleb_phb_spec celleb_fake_pci_spec __initdata = {
|
||||
.setup = celleb_setup_fake_pci,
|
||||
};
|
||||
|
||||
static struct of_device_id celleb_phb_match[] __initdata = {
|
||||
{
|
||||
.name = "pci-pseudo",
|
||||
.data = celleb_setup_fake_pci,
|
||||
.data = &celleb_fake_pci_spec,
|
||||
}, {
|
||||
.name = "epci",
|
||||
.data = celleb_setup_epci,
|
||||
.data = &celleb_epci_spec,
|
||||
}, {
|
||||
.name = "pcie",
|
||||
.data = &celleb_pciex_spec,
|
||||
}, {
|
||||
},
|
||||
};
|
||||
|
||||
static int __init celleb_io_workaround_init(struct pci_controller *phb,
|
||||
struct celleb_phb_spec *phb_spec)
|
||||
{
|
||||
if (phb_spec->ops) {
|
||||
iowa_register_bus(phb, phb_spec->ops, phb_spec->iowa_init,
|
||||
phb_spec->iowa_data);
|
||||
io_workaround_init();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __init celleb_setup_phb(struct pci_controller *phb)
|
||||
{
|
||||
struct device_node *dev = phb->dn;
|
||||
const struct of_device_id *match;
|
||||
int (*setup_func)(struct device_node *, struct pci_controller *);
|
||||
struct celleb_phb_spec *phb_spec;
|
||||
int rc;
|
||||
|
||||
match = of_match_node(celleb_phb_match, dev);
|
||||
if (!match)
|
||||
@ -492,8 +500,12 @@ int __init celleb_setup_phb(struct pci_controller *phb)
|
||||
phb_set_bus_ranges(dev, phb);
|
||||
phb->buid = 1;
|
||||
|
||||
setup_func = match->data;
|
||||
return (*setup_func)(dev, phb);
|
||||
phb_spec = match->data;
|
||||
rc = (*phb_spec->setup)(dev, phb);
|
||||
if (rc)
|
||||
return 1;
|
||||
|
||||
return celleb_io_workaround_init(phb, phb_spec);
|
||||
}
|
||||
|
||||
int celleb_pci_probe_mode(struct pci_bus *bus)
|
@ -27,16 +27,19 @@
|
||||
#include <asm/prom.h>
|
||||
#include <asm/ppc-pci.h>
|
||||
|
||||
#include "io-workarounds.h"
|
||||
|
||||
struct celleb_phb_spec {
|
||||
int (*setup)(struct device_node *, struct pci_controller *);
|
||||
struct ppc_pci_io *ops;
|
||||
int (*iowa_init)(struct iowa_bus *, void *);
|
||||
void *iowa_data;
|
||||
};
|
||||
|
||||
extern int celleb_setup_phb(struct pci_controller *);
|
||||
extern int celleb_pci_probe_mode(struct pci_bus *);
|
||||
|
||||
extern int celleb_setup_epci(struct device_node *, struct pci_controller *);
|
||||
|
||||
extern void *celleb_dummy_page_va;
|
||||
extern int __init celleb_pci_workaround_init(void);
|
||||
extern void __init celleb_pci_add_one(struct pci_controller *,
|
||||
void (*)(struct pci_controller *));
|
||||
extern void fake_pci_workaround_init(struct pci_controller *);
|
||||
extern void epci_workaround_init(struct pci_controller *);
|
||||
extern struct celleb_phb_spec celleb_epci_spec;
|
||||
extern struct celleb_phb_spec celleb_pciex_spec;
|
||||
|
||||
#endif /* _CELLEB_PCI_H */
|
@ -125,6 +125,93 @@
|
||||
/* bits for SCC_EPCI_CNTOPT */
|
||||
#define SCC_EPCI_CNTOPT_O2PMB 0x00000002
|
||||
|
||||
/* SCC PCIEXC SMMIO registers */
|
||||
#define PEXCADRS 0x000
|
||||
#define PEXCWDATA 0x004
|
||||
#define PEXCRDATA 0x008
|
||||
#define PEXDADRS 0x010
|
||||
#define PEXDCMND 0x014
|
||||
#define PEXDWDATA 0x018
|
||||
#define PEXDRDATA 0x01c
|
||||
#define PEXREQID 0x020
|
||||
#define PEXTIDMAP 0x024
|
||||
#define PEXINTMASK 0x028
|
||||
#define PEXINTSTS 0x02c
|
||||
#define PEXAERRMASK 0x030
|
||||
#define PEXAERRSTS 0x034
|
||||
#define PEXPRERRMASK 0x040
|
||||
#define PEXPRERRSTS 0x044
|
||||
#define PEXPRERRID01 0x048
|
||||
#define PEXPRERRID23 0x04c
|
||||
#define PEXVDMASK 0x050
|
||||
#define PEXVDSTS 0x054
|
||||
#define PEXRCVCPLIDA 0x060
|
||||
#define PEXLENERRIDA 0x068
|
||||
#define PEXPHYPLLST 0x070
|
||||
#define PEXDMRDEN0 0x100
|
||||
#define PEXDMRDADR0 0x104
|
||||
#define PEXDMRDENX 0x110
|
||||
#define PEXDMRDADRX 0x114
|
||||
#define PEXECMODE 0xf00
|
||||
#define PEXMAEA(n) (0xf50 + (8 * n))
|
||||
#define PEXMAEC(n) (0xf54 + (8 * n))
|
||||
#define PEXCCRCTRL 0xff0
|
||||
|
||||
/* SCC PCIEXC bits and shifts for PEXCADRS */
|
||||
#define PEXCADRS_BYTE_EN_SHIFT 20
|
||||
#define PEXCADRS_CMD_SHIFT 16
|
||||
#define PEXCADRS_CMD_READ (0xa << PEXCADRS_CMD_SHIFT)
|
||||
#define PEXCADRS_CMD_WRITE (0xb << PEXCADRS_CMD_SHIFT)
|
||||
|
||||
/* SCC PCIEXC shifts for PEXDADRS */
|
||||
#define PEXDADRS_BUSNO_SHIFT 20
|
||||
#define PEXDADRS_DEVNO_SHIFT 15
|
||||
#define PEXDADRS_FUNCNO_SHIFT 12
|
||||
|
||||
/* SCC PCIEXC bits and shifts for PEXDCMND */
|
||||
#define PEXDCMND_BYTE_EN_SHIFT 4
|
||||
#define PEXDCMND_IO_READ 0x2
|
||||
#define PEXDCMND_IO_WRITE 0x3
|
||||
#define PEXDCMND_CONFIG_READ 0xa
|
||||
#define PEXDCMND_CONFIG_WRITE 0xb
|
||||
|
||||
/* SCC PCIEXC bits for PEXPHYPLLST */
|
||||
#define PEXPHYPLLST_PEXPHYAPLLST 0x00000001
|
||||
|
||||
/* SCC PCIEXC bits for PEXECMODE */
|
||||
#define PEXECMODE_ALL_THROUGH 0x00000000
|
||||
#define PEXECMODE_ALL_8BIT 0x00550155
|
||||
#define PEXECMODE_ALL_16BIT 0x00aa02aa
|
||||
|
||||
/* SCC PCIEXC bits for PEXCCRCTRL */
|
||||
#define PEXCCRCTRL_PEXIPCOREEN 0x00040000
|
||||
#define PEXCCRCTRL_PEXIPCONTEN 0x00020000
|
||||
#define PEXCCRCTRL_PEXPHYPLLEN 0x00010000
|
||||
#define PEXCCRCTRL_PCIEXCAOCKEN 0x00000100
|
||||
|
||||
/* SCC PCIEXC port configuration registers */
|
||||
#define PEXTCERRCHK 0x21c
|
||||
#define PEXTAMAPB0 0x220
|
||||
#define PEXTAMAPL0 0x224
|
||||
#define PEXTAMAPB(n) (PEXTAMAPB0 + 8 * (n))
|
||||
#define PEXTAMAPL(n) (PEXTAMAPL0 + 8 * (n))
|
||||
#define PEXCHVC0P 0x500
|
||||
#define PEXCHVC0NP 0x504
|
||||
#define PEXCHVC0C 0x508
|
||||
#define PEXCDVC0P 0x50c
|
||||
#define PEXCDVC0NP 0x510
|
||||
#define PEXCDVC0C 0x514
|
||||
#define PEXCHVCXP 0x518
|
||||
#define PEXCHVCXNP 0x51c
|
||||
#define PEXCHVCXC 0x520
|
||||
#define PEXCDVCXP 0x524
|
||||
#define PEXCDVCXNP 0x528
|
||||
#define PEXCDVCXC 0x52c
|
||||
#define PEXCTTRG 0x530
|
||||
#define PEXTSCTRL 0x700
|
||||
#define PEXTSSTS 0x704
|
||||
#define PEXSKPCTRL 0x708
|
||||
|
||||
/* UHC registers */
|
||||
#define SCC_UHC_CKRCTRL 0xff0
|
||||
#define SCC_UHC_ECMODE 0xf00
|
@ -30,23 +30,17 @@
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/pci-bridge.h>
|
||||
#include <asm/ppc-pci.h>
|
||||
|
||||
#include "scc.h"
|
||||
#include "pci.h"
|
||||
#include "interrupt.h"
|
||||
#include "celleb_scc.h"
|
||||
#include "celleb_pci.h"
|
||||
|
||||
#define MAX_PCI_DEVICES 32
|
||||
#define MAX_PCI_FUNCTIONS 8
|
||||
|
||||
#define iob() __asm__ __volatile__("eieio; sync":::"memory")
|
||||
|
||||
struct epci_private {
|
||||
dma_addr_t dummy_page_da;
|
||||
};
|
||||
|
||||
static inline PCI_IO_ADDR celleb_epci_get_epci_base(
|
||||
struct pci_controller *hose)
|
||||
{
|
||||
@ -71,42 +65,6 @@ static inline PCI_IO_ADDR celleb_epci_get_epci_cfg(
|
||||
return hose->cfg_data;
|
||||
}
|
||||
|
||||
static void scc_epci_dummy_read(struct pci_controller *hose)
|
||||
{
|
||||
PCI_IO_ADDR epci_base;
|
||||
u32 val;
|
||||
|
||||
epci_base = celleb_epci_get_epci_base(hose);
|
||||
|
||||
val = in_be32(epci_base + SCC_EPCI_WATRP);
|
||||
iosync();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void __init epci_workaround_init(struct pci_controller *hose)
|
||||
{
|
||||
PCI_IO_ADDR epci_base;
|
||||
PCI_IO_ADDR reg;
|
||||
struct epci_private *private = hose->private_data;
|
||||
|
||||
BUG_ON(!private);
|
||||
|
||||
private->dummy_page_da = dma_map_single(hose->parent,
|
||||
celleb_dummy_page_va, PAGE_SIZE, DMA_FROM_DEVICE);
|
||||
if (private->dummy_page_da == DMA_ERROR_CODE) {
|
||||
printk(KERN_ERR "EPCI: dummy read disabled. "
|
||||
"Map dummy page failed.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
celleb_pci_add_one(hose, scc_epci_dummy_read);
|
||||
epci_base = celleb_epci_get_epci_base(hose);
|
||||
|
||||
reg = epci_base + SCC_EPCI_DUMYRADR;
|
||||
out_be32(reg, private->dummy_page_da);
|
||||
}
|
||||
|
||||
static inline void clear_and_disable_master_abort_interrupt(
|
||||
struct pci_controller *hose)
|
||||
{
|
||||
@ -151,10 +109,8 @@ static int celleb_epci_check_abort(struct pci_controller *hose,
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
static PCI_IO_ADDR celleb_epci_make_config_addr(
|
||||
struct pci_bus *bus,
|
||||
struct pci_controller *hose,
|
||||
unsigned int devfn, int where)
|
||||
static PCI_IO_ADDR celleb_epci_make_config_addr(struct pci_bus *bus,
|
||||
struct pci_controller *hose, unsigned int devfn, int where)
|
||||
{
|
||||
PCI_IO_ADDR addr;
|
||||
|
||||
@ -425,8 +381,8 @@ static int __init celleb_epci_init(struct pci_controller *hose)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __init celleb_setup_epci(struct device_node *node,
|
||||
struct pci_controller *hose)
|
||||
static int __init celleb_setup_epci(struct device_node *node,
|
||||
struct pci_controller *hose)
|
||||
{
|
||||
struct resource r;
|
||||
|
||||
@ -450,8 +406,7 @@ int __init celleb_setup_epci(struct device_node *node,
|
||||
if (!hose->cfg_addr)
|
||||
goto error;
|
||||
pr_debug("EPCI: cfg_addr map 0x%016lx->0x%016lx + 0x%016lx\n",
|
||||
r.start, (unsigned long)hose->cfg_addr,
|
||||
(r.end - r.start + 1));
|
||||
r.start, (unsigned long)hose->cfg_addr, (r.end - r.start + 1));
|
||||
|
||||
if (of_address_to_resource(node, 2, &r))
|
||||
goto error;
|
||||
@ -459,14 +414,7 @@ int __init celleb_setup_epci(struct device_node *node,
|
||||
if (!hose->cfg_data)
|
||||
goto error;
|
||||
pr_debug("EPCI: cfg_data map 0x%016lx->0x%016lx + 0x%016lx\n",
|
||||
r.start, (unsigned long)hose->cfg_data,
|
||||
(r.end - r.start + 1));
|
||||
|
||||
hose->private_data = kzalloc(sizeof(struct epci_private), GFP_KERNEL);
|
||||
if (hose->private_data == NULL) {
|
||||
printk(KERN_ERR "EPCI: no memory for private data.\n");
|
||||
goto error;
|
||||
}
|
||||
r.start, (unsigned long)hose->cfg_data, (r.end - r.start + 1));
|
||||
|
||||
hose->ops = &celleb_epci_ops;
|
||||
celleb_epci_init(hose);
|
||||
@ -474,8 +422,6 @@ int __init celleb_setup_epci(struct device_node *node,
|
||||
return 0;
|
||||
|
||||
error:
|
||||
kfree(hose->private_data);
|
||||
|
||||
if (hose->cfg_addr)
|
||||
iounmap(hose->cfg_addr);
|
||||
|
||||
@ -483,3 +429,10 @@ error:
|
||||
iounmap(hose->cfg_data);
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct celleb_phb_spec celleb_epci_spec __initdata = {
|
||||
.setup = celleb_setup_epci,
|
||||
.ops = &spiderpci_ops,
|
||||
.iowa_init = &spiderpci_iowa_init,
|
||||
.iowa_data = (void *)0,
|
||||
};
|
547
arch/powerpc/platforms/cell/celleb_scc_pciex.c
Normal file
547
arch/powerpc/platforms/cell/celleb_scc_pciex.c
Normal file
@ -0,0 +1,547 @@
|
||||
/*
|
||||
* Support for Celleb PCI-Express.
|
||||
*
|
||||
* (C) Copyright 2007-2008 TOSHIBA CORPORATION
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#undef DEBUG
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/bootmem.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/iommu.h>
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
#include "celleb_scc.h"
|
||||
#include "celleb_pci.h"
|
||||
|
||||
#define PEX_IN(base, off) in_be32((void *)(base) + (off))
|
||||
#define PEX_OUT(base, off, data) out_be32((void *)(base) + (off), (data))
|
||||
|
||||
static void scc_pciex_io_flush(struct iowa_bus *bus)
|
||||
{
|
||||
(void)PEX_IN(bus->phb->cfg_addr, PEXDMRDEN0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Memory space access to device on PCIEX
|
||||
*/
|
||||
#define PCIEX_MMIO_READ(name, ret) \
|
||||
static ret scc_pciex_##name(const PCI_IO_ADDR addr) \
|
||||
{ \
|
||||
ret val = __do_##name(addr); \
|
||||
scc_pciex_io_flush(iowa_mem_find_bus(addr)); \
|
||||
return val; \
|
||||
}
|
||||
|
||||
#define PCIEX_MMIO_READ_STR(name) \
|
||||
static void scc_pciex_##name(const PCI_IO_ADDR addr, void *buf, \
|
||||
unsigned long count) \
|
||||
{ \
|
||||
__do_##name(addr, buf, count); \
|
||||
scc_pciex_io_flush(iowa_mem_find_bus(addr)); \
|
||||
}
|
||||
|
||||
PCIEX_MMIO_READ(readb, u8)
|
||||
PCIEX_MMIO_READ(readw, u16)
|
||||
PCIEX_MMIO_READ(readl, u32)
|
||||
PCIEX_MMIO_READ(readq, u64)
|
||||
PCIEX_MMIO_READ(readw_be, u16)
|
||||
PCIEX_MMIO_READ(readl_be, u32)
|
||||
PCIEX_MMIO_READ(readq_be, u64)
|
||||
PCIEX_MMIO_READ_STR(readsb)
|
||||
PCIEX_MMIO_READ_STR(readsw)
|
||||
PCIEX_MMIO_READ_STR(readsl)
|
||||
|
||||
static void scc_pciex_memcpy_fromio(void *dest, const PCI_IO_ADDR src,
|
||||
unsigned long n)
|
||||
{
|
||||
__do_memcpy_fromio(dest, src, n);
|
||||
scc_pciex_io_flush(iowa_mem_find_bus(src));
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O port access to devices on PCIEX.
|
||||
*/
|
||||
|
||||
static inline unsigned long get_bus_address(struct pci_controller *phb,
|
||||
unsigned long port)
|
||||
{
|
||||
return port - ((unsigned long)(phb->io_base_virt) - _IO_BASE);
|
||||
}
|
||||
|
||||
static u32 scc_pciex_read_port(struct pci_controller *phb,
|
||||
unsigned long port, int size)
|
||||
{
|
||||
unsigned int byte_enable;
|
||||
unsigned int cmd, shift;
|
||||
unsigned long addr;
|
||||
u32 data, ret;
|
||||
|
||||
BUG_ON(((port & 0x3ul) + size) > 4);
|
||||
|
||||
addr = get_bus_address(phb, port);
|
||||
shift = addr & 0x3ul;
|
||||
byte_enable = ((1 << size) - 1) << shift;
|
||||
cmd = PEXDCMND_IO_READ | (byte_enable << PEXDCMND_BYTE_EN_SHIFT);
|
||||
PEX_OUT(phb->cfg_addr, PEXDADRS, (addr & ~0x3ul));
|
||||
PEX_OUT(phb->cfg_addr, PEXDCMND, cmd);
|
||||
data = PEX_IN(phb->cfg_addr, PEXDRDATA);
|
||||
ret = (data >> (shift * 8)) & (0xFFFFFFFF >> ((4 - size) * 8));
|
||||
|
||||
pr_debug("PCIEX:PIO READ:port=0x%lx, addr=0x%lx, size=%d, be=%x,"
|
||||
" cmd=%x, data=%x, ret=%x\n", port, addr, size, byte_enable,
|
||||
cmd, data, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void scc_pciex_write_port(struct pci_controller *phb,
|
||||
unsigned long port, int size, u32 val)
|
||||
{
|
||||
unsigned int byte_enable;
|
||||
unsigned int cmd, shift;
|
||||
unsigned long addr;
|
||||
u32 data;
|
||||
|
||||
BUG_ON(((port & 0x3ul) + size) > 4);
|
||||
|
||||
addr = get_bus_address(phb, port);
|
||||
shift = addr & 0x3ul;
|
||||
byte_enable = ((1 << size) - 1) << shift;
|
||||
cmd = PEXDCMND_IO_WRITE | (byte_enable << PEXDCMND_BYTE_EN_SHIFT);
|
||||
data = (val & (0xFFFFFFFF >> (4 - size) * 8)) << (shift * 8);
|
||||
PEX_OUT(phb->cfg_addr, PEXDADRS, (addr & ~0x3ul));
|
||||
PEX_OUT(phb->cfg_addr, PEXDCMND, cmd);
|
||||
PEX_OUT(phb->cfg_addr, PEXDWDATA, data);
|
||||
|
||||
pr_debug("PCIEX:PIO WRITE:port=0x%lx, addr=%lx, size=%d, val=%x,"
|
||||
" be=%x, cmd=%x, data=%x\n", port, addr, size, val,
|
||||
byte_enable, cmd, data);
|
||||
}
|
||||
|
||||
static u8 __scc_pciex_inb(struct pci_controller *phb, unsigned long port)
|
||||
{
|
||||
return (u8)scc_pciex_read_port(phb, port, 1);
|
||||
}
|
||||
|
||||
static u16 __scc_pciex_inw(struct pci_controller *phb, unsigned long port)
|
||||
{
|
||||
u32 data;
|
||||
if ((port & 0x3ul) < 3)
|
||||
data = scc_pciex_read_port(phb, port, 2);
|
||||
else {
|
||||
u32 d1 = scc_pciex_read_port(phb, port, 1);
|
||||
u32 d2 = scc_pciex_read_port(phb, port + 1, 1);
|
||||
data = d1 | (d2 << 8);
|
||||
}
|
||||
return (u16)data;
|
||||
}
|
||||
|
||||
static u32 __scc_pciex_inl(struct pci_controller *phb, unsigned long port)
|
||||
{
|
||||
unsigned int mod = port & 0x3ul;
|
||||
u32 data;
|
||||
if (mod == 0)
|
||||
data = scc_pciex_read_port(phb, port, 4);
|
||||
else {
|
||||
u32 d1 = scc_pciex_read_port(phb, port, 4 - mod);
|
||||
u32 d2 = scc_pciex_read_port(phb, port + 1, mod);
|
||||
data = d1 | (d2 << (mod * 8));
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
static void __scc_pciex_outb(struct pci_controller *phb,
|
||||
u8 val, unsigned long port)
|
||||
{
|
||||
scc_pciex_write_port(phb, port, 1, (u32)val);
|
||||
}
|
||||
|
||||
static void __scc_pciex_outw(struct pci_controller *phb,
|
||||
u16 val, unsigned long port)
|
||||
{
|
||||
if ((port & 0x3ul) < 3)
|
||||
scc_pciex_write_port(phb, port, 2, (u32)val);
|
||||
else {
|
||||
u32 d1 = val & 0x000000FF;
|
||||
u32 d2 = (val & 0x0000FF00) >> 8;
|
||||
scc_pciex_write_port(phb, port, 1, d1);
|
||||
scc_pciex_write_port(phb, port + 1, 1, d2);
|
||||
}
|
||||
}
|
||||
|
||||
static void __scc_pciex_outl(struct pci_controller *phb,
|
||||
u32 val, unsigned long port)
|
||||
{
|
||||
unsigned int mod = port & 0x3ul;
|
||||
if (mod == 0)
|
||||
scc_pciex_write_port(phb, port, 4, val);
|
||||
else {
|
||||
u32 d1 = val & (0xFFFFFFFFul >> (mod * 8));
|
||||
u32 d2 = val >> ((4 - mod) * 8);
|
||||
scc_pciex_write_port(phb, port, 4 - mod, d1);
|
||||
scc_pciex_write_port(phb, port + 1, mod, d2);
|
||||
}
|
||||
}
|
||||
|
||||
#define PCIEX_PIO_FUNC(size, name) \
|
||||
static u##size scc_pciex_in##name(unsigned long port) \
|
||||
{ \
|
||||
struct iowa_bus *bus = iowa_pio_find_bus(port); \
|
||||
u##size data = __scc_pciex_in##name(bus->phb, port); \
|
||||
scc_pciex_io_flush(bus); \
|
||||
return data; \
|
||||
} \
|
||||
static void scc_pciex_ins##name(unsigned long p, void *b, unsigned long c) \
|
||||
{ \
|
||||
struct iowa_bus *bus = iowa_pio_find_bus(p); \
|
||||
u##size *dst = b; \
|
||||
for (; c != 0; c--, dst++) \
|
||||
*dst = cpu_to_le##size(__scc_pciex_in##name(bus->phb, p)); \
|
||||
scc_pciex_io_flush(bus); \
|
||||
} \
|
||||
static void scc_pciex_out##name(u##size val, unsigned long port) \
|
||||
{ \
|
||||
struct iowa_bus *bus = iowa_pio_find_bus(port); \
|
||||
__scc_pciex_out##name(bus->phb, val, port); \
|
||||
} \
|
||||
static void scc_pciex_outs##name(unsigned long p, const void *b, \
|
||||
unsigned long c) \
|
||||
{ \
|
||||
struct iowa_bus *bus = iowa_pio_find_bus(p); \
|
||||
const u##size *src = b; \
|
||||
for (; c != 0; c--, src++) \
|
||||
__scc_pciex_out##name(bus->phb, le##size##_to_cpu(*src), p); \
|
||||
}
|
||||
#define cpu_to_le8(x) (x)
|
||||
#define le8_to_cpu(x) (x)
|
||||
PCIEX_PIO_FUNC(8, b)
|
||||
PCIEX_PIO_FUNC(16, w)
|
||||
PCIEX_PIO_FUNC(32, l)
|
||||
|
||||
static struct ppc_pci_io scc_pciex_ops = {
|
||||
.readb = scc_pciex_readb,
|
||||
.readw = scc_pciex_readw,
|
||||
.readl = scc_pciex_readl,
|
||||
.readq = scc_pciex_readq,
|
||||
.readw_be = scc_pciex_readw_be,
|
||||
.readl_be = scc_pciex_readl_be,
|
||||
.readq_be = scc_pciex_readq_be,
|
||||
.readsb = scc_pciex_readsb,
|
||||
.readsw = scc_pciex_readsw,
|
||||
.readsl = scc_pciex_readsl,
|
||||
.memcpy_fromio = scc_pciex_memcpy_fromio,
|
||||
.inb = scc_pciex_inb,
|
||||
.inw = scc_pciex_inw,
|
||||
.inl = scc_pciex_inl,
|
||||
.outb = scc_pciex_outb,
|
||||
.outw = scc_pciex_outw,
|
||||
.outl = scc_pciex_outl,
|
||||
.insb = scc_pciex_insb,
|
||||
.insw = scc_pciex_insw,
|
||||
.insl = scc_pciex_insl,
|
||||
.outsb = scc_pciex_outsb,
|
||||
.outsw = scc_pciex_outsw,
|
||||
.outsl = scc_pciex_outsl,
|
||||
};
|
||||
|
||||
static int __init scc_pciex_iowa_init(struct iowa_bus *bus, void *data)
|
||||
{
|
||||
dma_addr_t dummy_page_da;
|
||||
void *dummy_page_va;
|
||||
|
||||
dummy_page_va = kmalloc(PAGE_SIZE, GFP_KERNEL);
|
||||
if (!dummy_page_va) {
|
||||
pr_err("PCIEX:Alloc dummy_page_va failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
dummy_page_da = dma_map_single(bus->phb->parent, dummy_page_va,
|
||||
PAGE_SIZE, DMA_FROM_DEVICE);
|
||||
if (dma_mapping_error(dummy_page_da)) {
|
||||
pr_err("PCIEX:Map dummy page failed.\n");
|
||||
kfree(dummy_page_va);
|
||||
return -1;
|
||||
}
|
||||
|
||||
PEX_OUT(bus->phb->cfg_addr, PEXDMRDADR0, dummy_page_da);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* config space access
|
||||
*/
|
||||
#define MK_PEXDADRS(bus_no, dev_no, func_no, addr) \
|
||||
((uint32_t)(((addr) & ~0x3UL) | \
|
||||
((bus_no) << PEXDADRS_BUSNO_SHIFT) | \
|
||||
((dev_no) << PEXDADRS_DEVNO_SHIFT) | \
|
||||
((func_no) << PEXDADRS_FUNCNO_SHIFT)))
|
||||
|
||||
#define MK_PEXDCMND_BYTE_EN(addr, size) \
|
||||
((((0x1 << (size))-1) << ((addr) & 0x3)) << PEXDCMND_BYTE_EN_SHIFT)
|
||||
#define MK_PEXDCMND(cmd, addr, size) ((cmd) | MK_PEXDCMND_BYTE_EN(addr, size))
|
||||
|
||||
static uint32_t config_read_pciex_dev(unsigned int *base,
|
||||
uint64_t bus_no, uint64_t dev_no, uint64_t func_no,
|
||||
uint64_t off, uint64_t size)
|
||||
{
|
||||
uint32_t ret;
|
||||
uint32_t addr, cmd;
|
||||
|
||||
addr = MK_PEXDADRS(bus_no, dev_no, func_no, off);
|
||||
cmd = MK_PEXDCMND(PEXDCMND_CONFIG_READ, off, size);
|
||||
PEX_OUT(base, PEXDADRS, addr);
|
||||
PEX_OUT(base, PEXDCMND, cmd);
|
||||
ret = (PEX_IN(base, PEXDRDATA)
|
||||
>> ((off & (4-size)) * 8)) & ((0x1 << (size * 8)) - 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void config_write_pciex_dev(unsigned int *base, uint64_t bus_no,
|
||||
uint64_t dev_no, uint64_t func_no, uint64_t off, uint64_t size,
|
||||
uint32_t data)
|
||||
{
|
||||
uint32_t addr, cmd;
|
||||
|
||||
addr = MK_PEXDADRS(bus_no, dev_no, func_no, off);
|
||||
cmd = MK_PEXDCMND(PEXDCMND_CONFIG_WRITE, off, size);
|
||||
PEX_OUT(base, PEXDADRS, addr);
|
||||
PEX_OUT(base, PEXDCMND, cmd);
|
||||
PEX_OUT(base, PEXDWDATA,
|
||||
(data & ((0x1 << (size * 8)) - 1)) << ((off & (4-size)) * 8));
|
||||
}
|
||||
|
||||
#define MK_PEXCADRS_BYTE_EN(off, len) \
|
||||
((((0x1 << (len)) - 1) << ((off) & 0x3)) << PEXCADRS_BYTE_EN_SHIFT)
|
||||
#define MK_PEXCADRS(cmd, addr, size) \
|
||||
((cmd) | MK_PEXCADRS_BYTE_EN(addr, size) | ((addr) & ~0x3))
|
||||
static uint32_t config_read_pciex_rc(unsigned int *base,
|
||||
uint32_t where, uint32_t size)
|
||||
{
|
||||
PEX_OUT(base, PEXCADRS, MK_PEXCADRS(PEXCADRS_CMD_READ, where, size));
|
||||
return (PEX_IN(base, PEXCRDATA)
|
||||
>> ((where & (4 - size)) * 8)) & ((0x1 << (size * 8)) - 1);
|
||||
}
|
||||
|
||||
static void config_write_pciex_rc(unsigned int *base, uint32_t where,
|
||||
uint32_t size, uint32_t val)
|
||||
{
|
||||
uint32_t data;
|
||||
|
||||
data = (val & ((0x1 << (size * 8)) - 1)) << ((where & (4 - size)) * 8);
|
||||
PEX_OUT(base, PEXCADRS, MK_PEXCADRS(PEXCADRS_CMD_WRITE, where, size));
|
||||
PEX_OUT(base, PEXCWDATA, data);
|
||||
}
|
||||
|
||||
/* Interfaces */
|
||||
/* Note: Work-around
|
||||
* On SCC PCIEXC, one device is seen on all 32 dev_no.
|
||||
* As SCC PCIEXC can have only one device on the bus, we look only one dev_no.
|
||||
* (dev_no = 1)
|
||||
*/
|
||||
static int scc_pciex_read_config(struct pci_bus *bus, unsigned int devfn,
|
||||
int where, int size, unsigned int *val)
|
||||
{
|
||||
struct device_node *dn;
|
||||
struct pci_controller *phb;
|
||||
|
||||
dn = bus->sysdata;
|
||||
phb = pci_find_hose_for_OF_device(dn);
|
||||
|
||||
if (bus->number == phb->first_busno && PCI_SLOT(devfn) != 1) {
|
||||
*val = ~0;
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (bus->number == 0 && PCI_SLOT(devfn) == 0)
|
||||
*val = config_read_pciex_rc(phb->cfg_addr, where, size);
|
||||
else
|
||||
*val = config_read_pciex_dev(phb->cfg_addr, bus->number,
|
||||
PCI_SLOT(devfn), PCI_FUNC(devfn), where, size);
|
||||
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
static int scc_pciex_write_config(struct pci_bus *bus, unsigned int devfn,
|
||||
int where, int size, unsigned int val)
|
||||
{
|
||||
struct device_node *dn;
|
||||
struct pci_controller *phb;
|
||||
|
||||
dn = bus->sysdata;
|
||||
phb = pci_find_hose_for_OF_device(dn);
|
||||
|
||||
if (bus->number == phb->first_busno && PCI_SLOT(devfn) != 1)
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
|
||||
if (bus->number == 0 && PCI_SLOT(devfn) == 0)
|
||||
config_write_pciex_rc(phb->cfg_addr, where, size, val);
|
||||
else
|
||||
config_write_pciex_dev(phb->cfg_addr, bus->number,
|
||||
PCI_SLOT(devfn), PCI_FUNC(devfn), where, size, val);
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
static struct pci_ops scc_pciex_pci_ops = {
|
||||
scc_pciex_read_config,
|
||||
scc_pciex_write_config,
|
||||
};
|
||||
|
||||
static void pciex_clear_intr_all(unsigned int *base)
|
||||
{
|
||||
PEX_OUT(base, PEXAERRSTS, 0xffffffff);
|
||||
PEX_OUT(base, PEXPRERRSTS, 0xffffffff);
|
||||
PEX_OUT(base, PEXINTSTS, 0xffffffff);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void pciex_disable_intr_all(unsigned int *base)
|
||||
{
|
||||
PEX_OUT(base, PEXINTMASK, 0x0);
|
||||
PEX_OUT(base, PEXAERRMASK, 0x0);
|
||||
PEX_OUT(base, PEXPRERRMASK, 0x0);
|
||||
PEX_OUT(base, PEXVDMASK, 0x0);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void pciex_enable_intr_all(unsigned int *base)
|
||||
{
|
||||
PEX_OUT(base, PEXINTMASK, 0x0000e7f1);
|
||||
PEX_OUT(base, PEXAERRMASK, 0x03ff01ff);
|
||||
PEX_OUT(base, PEXPRERRMASK, 0x0001010f);
|
||||
PEX_OUT(base, PEXVDMASK, 0x00000001);
|
||||
}
|
||||
|
||||
static void pciex_check_status(unsigned int *base)
|
||||
{
|
||||
uint32_t err = 0;
|
||||
uint32_t intsts, aerr, prerr, rcvcp, lenerr;
|
||||
uint32_t maea, maec;
|
||||
|
||||
intsts = PEX_IN(base, PEXINTSTS);
|
||||
aerr = PEX_IN(base, PEXAERRSTS);
|
||||
prerr = PEX_IN(base, PEXPRERRSTS);
|
||||
rcvcp = PEX_IN(base, PEXRCVCPLIDA);
|
||||
lenerr = PEX_IN(base, PEXLENERRIDA);
|
||||
|
||||
if (intsts || aerr || prerr || rcvcp || lenerr)
|
||||
err = 1;
|
||||
|
||||
pr_info("PCEXC interrupt!!\n");
|
||||
pr_info("PEXINTSTS :0x%08x\n", intsts);
|
||||
pr_info("PEXAERRSTS :0x%08x\n", aerr);
|
||||
pr_info("PEXPRERRSTS :0x%08x\n", prerr);
|
||||
pr_info("PEXRCVCPLIDA :0x%08x\n", rcvcp);
|
||||
pr_info("PEXLENERRIDA :0x%08x\n", lenerr);
|
||||
|
||||
/* print detail of Protection Error */
|
||||
if (intsts & 0x00004000) {
|
||||
uint32_t i, n;
|
||||
for (i = 0; i < 4; i++) {
|
||||
n = 1 << i;
|
||||
if (prerr & n) {
|
||||
maea = PEX_IN(base, PEXMAEA(i));
|
||||
maec = PEX_IN(base, PEXMAEC(i));
|
||||
pr_info("PEXMAEC%d :0x%08x\n", i, maec);
|
||||
pr_info("PEXMAEA%d :0x%08x\n", i, maea);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (err)
|
||||
pciex_clear_intr_all(base);
|
||||
}
|
||||
|
||||
static irqreturn_t pciex_handle_internal_irq(int irq, void *dev_id)
|
||||
{
|
||||
struct pci_controller *phb = dev_id;
|
||||
|
||||
pr_debug("PCIEX:pciex_handle_internal_irq(irq=%d)\n", irq);
|
||||
|
||||
BUG_ON(phb->cfg_addr == NULL);
|
||||
|
||||
pciex_check_status(phb->cfg_addr);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static __init int celleb_setup_pciex(struct device_node *node,
|
||||
struct pci_controller *phb)
|
||||
{
|
||||
struct resource r;
|
||||
struct of_irq oirq;
|
||||
int virq;
|
||||
|
||||
/* SMMIO registers; used inside this file */
|
||||
if (of_address_to_resource(node, 0, &r)) {
|
||||
pr_err("PCIEXC:Failed to get config resource.\n");
|
||||
return 1;
|
||||
}
|
||||
phb->cfg_addr = ioremap(r.start, r.end - r.start + 1);
|
||||
if (!phb->cfg_addr) {
|
||||
pr_err("PCIEXC:Failed to remap SMMIO region.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Not use cfg_data, cmd and data regs are near address reg */
|
||||
phb->cfg_data = NULL;
|
||||
|
||||
/* set pci_ops */
|
||||
phb->ops = &scc_pciex_pci_ops;
|
||||
|
||||
/* internal interrupt handler */
|
||||
if (of_irq_map_one(node, 1, &oirq)) {
|
||||
pr_err("PCIEXC:Failed to map irq\n");
|
||||
goto error;
|
||||
}
|
||||
virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
|
||||
oirq.size);
|
||||
if (request_irq(virq, pciex_handle_internal_irq,
|
||||
IRQF_DISABLED, "pciex", (void *)phb)) {
|
||||
pr_err("PCIEXC:Failed to request irq\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* enable all interrupts */
|
||||
pciex_clear_intr_all(phb->cfg_addr);
|
||||
pciex_enable_intr_all(phb->cfg_addr);
|
||||
/* MSI: TBD */
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
phb->cfg_data = NULL;
|
||||
if (phb->cfg_addr)
|
||||
iounmap(phb->cfg_addr);
|
||||
phb->cfg_addr = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct celleb_phb_spec celleb_pciex_spec __initdata = {
|
||||
.setup = celleb_setup_pciex,
|
||||
.ops = &scc_pciex_ops,
|
||||
.iowa_init = &scc_pciex_iowa_init,
|
||||
};
|
@ -25,7 +25,7 @@
|
||||
#include <asm/io.h>
|
||||
#include <asm/machdep.h>
|
||||
|
||||
#include "scc.h"
|
||||
#include "celleb_scc.h"
|
||||
|
||||
#define UHC_RESET_WAIT_MAX 10000
|
||||
|
@ -56,13 +56,13 @@
|
||||
#include <asm/rtas.h>
|
||||
#include <asm/cell-regs.h>
|
||||
|
||||
#include "interrupt.h"
|
||||
#include "beat_interrupt.h"
|
||||
#include "beat_wrapper.h"
|
||||
#include "beat.h"
|
||||
#include "pci.h"
|
||||
#include "../cell/interrupt.h"
|
||||
#include "../cell/pervasive.h"
|
||||
#include "../cell/ras.h"
|
||||
#include "celleb_pci.h"
|
||||
#include "interrupt.h"
|
||||
#include "pervasive.h"
|
||||
#include "ras.h"
|
||||
|
||||
static char celleb_machine_type[128] = "Celleb";
|
||||
|
||||
@ -114,8 +114,6 @@ static int __init celleb_publish_devices(void)
|
||||
/* Publish OF platform devices for southbridge IOs */
|
||||
of_platform_bus_probe(NULL, celleb_bus_ids, NULL);
|
||||
|
||||
celleb_pci_workaround_init();
|
||||
|
||||
return 0;
|
||||
}
|
||||
machine_device_initcall(celleb_beat, celleb_publish_devices);
|
@ -1,6 +1,9 @@
|
||||
/*
|
||||
* Support PCI IO workaround
|
||||
*
|
||||
* Copyright (C) 2006 Benjamin Herrenschmidt <benh@kernel.crashing.org>
|
||||
* IBM, Corp.
|
||||
* (C) Copyright 2007-2008 TOSHIBA CORPORATION
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@ -9,335 +12,174 @@
|
||||
#undef DEBUG
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/pci-bridge.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/ppc-pci.h>
|
||||
|
||||
#include "io-workarounds.h"
|
||||
|
||||
#define SPIDER_PCI_REG_BASE 0xd000
|
||||
#define SPIDER_PCI_VCI_CNTL_STAT 0x0110
|
||||
#define SPIDER_PCI_DUMMY_READ 0x0810
|
||||
#define SPIDER_PCI_DUMMY_READ_BASE 0x0814
|
||||
#define IOWA_MAX_BUS 8
|
||||
|
||||
/* Undefine that to re-enable bogus prefetch
|
||||
*
|
||||
* Without that workaround, the chip will do bogus prefetch past
|
||||
* page boundary from system memory. This setting will disable that,
|
||||
* though the documentation is unclear as to the consequences of doing
|
||||
* so, either purely performances, or possible misbehaviour... It's not
|
||||
* clear wether the chip can handle unaligned accesses at all without
|
||||
* prefetching enabled.
|
||||
*
|
||||
* For now, things appear to be behaving properly with that prefetching
|
||||
* disabled and IDE, possibly because IDE isn't doing any unaligned
|
||||
* access.
|
||||
*/
|
||||
#define SPIDER_DISABLE_PREFETCH
|
||||
static struct iowa_bus iowa_busses[IOWA_MAX_BUS];
|
||||
static unsigned int iowa_bus_count;
|
||||
|
||||
#define MAX_SPIDERS 3
|
||||
|
||||
static struct spider_pci_bus {
|
||||
void __iomem *regs;
|
||||
unsigned long mmio_start;
|
||||
unsigned long mmio_end;
|
||||
unsigned long pio_vstart;
|
||||
unsigned long pio_vend;
|
||||
} spider_pci_busses[MAX_SPIDERS];
|
||||
static int spider_pci_count;
|
||||
|
||||
static struct spider_pci_bus *spider_pci_find(unsigned long vaddr,
|
||||
unsigned long paddr)
|
||||
static struct iowa_bus *iowa_pci_find(unsigned long vaddr, unsigned long paddr)
|
||||
{
|
||||
int i;
|
||||
int i, j;
|
||||
struct resource *res;
|
||||
unsigned long vstart, vend;
|
||||
|
||||
for (i = 0; i < spider_pci_count; i++) {
|
||||
struct spider_pci_bus *bus = &spider_pci_busses[i];
|
||||
if (paddr && paddr >= bus->mmio_start && paddr < bus->mmio_end)
|
||||
return bus;
|
||||
if (vaddr && vaddr >= bus->pio_vstart && vaddr < bus->pio_vend)
|
||||
return bus;
|
||||
for (i = 0; i < iowa_bus_count; i++) {
|
||||
struct iowa_bus *bus = &iowa_busses[i];
|
||||
struct pci_controller *phb = bus->phb;
|
||||
|
||||
if (vaddr) {
|
||||
vstart = (unsigned long)phb->io_base_virt;
|
||||
vend = vstart + phb->pci_io_size - 1;
|
||||
if ((vaddr >= vstart) && (vaddr <= vend))
|
||||
return bus;
|
||||
}
|
||||
|
||||
if (paddr)
|
||||
for (j = 0; j < 3; j++) {
|
||||
res = &phb->mem_resources[j];
|
||||
if (paddr >= res->start && paddr <= res->end)
|
||||
return bus;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void spider_io_flush(const volatile void __iomem *addr)
|
||||
struct iowa_bus *iowa_mem_find_bus(const PCI_IO_ADDR addr)
|
||||
{
|
||||
struct spider_pci_bus *bus;
|
||||
struct iowa_bus *bus;
|
||||
int token;
|
||||
|
||||
/* Get platform token (set by ioremap) from address */
|
||||
token = PCI_GET_ADDR_TOKEN(addr);
|
||||
|
||||
/* Fast path if we have a non-0 token, it indicates which bus we
|
||||
* are on.
|
||||
*
|
||||
* If the token is 0, that means either that the ioremap was done
|
||||
* before we initialized this layer, or it's a PIO operation. We
|
||||
* fallback to a low path in this case. Hopefully, internal devices
|
||||
* which are ioremap'ed early should use in_XX/out_XX functions
|
||||
* instead of the PCI ones and thus not suffer from the slowdown.
|
||||
*
|
||||
* Also note that currently, the workaround will not work for areas
|
||||
* that are not mapped with PTEs (bolted in the hash table). This
|
||||
* is the case for ioremaps done very early at boot (before
|
||||
* mem_init_done) and includes the mapping of the ISA IO space.
|
||||
*
|
||||
* Fortunately, none of the affected devices is expected to do DMA
|
||||
* and thus there should be no problem in practice.
|
||||
*
|
||||
* In order to improve performances, we only do the PTE search for
|
||||
* addresses falling in the PHB IO space area. That means it will
|
||||
* not work for hotplug'ed PHBs but those don't exist with Spider.
|
||||
*/
|
||||
if (token && token <= spider_pci_count)
|
||||
bus = &spider_pci_busses[token - 1];
|
||||
if (token && token <= iowa_bus_count)
|
||||
bus = &iowa_busses[token - 1];
|
||||
else {
|
||||
unsigned long vaddr, paddr;
|
||||
pte_t *ptep;
|
||||
|
||||
/* Fixup physical address */
|
||||
vaddr = (unsigned long)PCI_FIX_ADDR(addr);
|
||||
if (vaddr < PHB_IO_BASE || vaddr >= PHB_IO_END)
|
||||
return NULL;
|
||||
|
||||
/* Check if it's in allowed range for PIO */
|
||||
if (vaddr < PHB_IO_BASE || vaddr > PHB_IO_END)
|
||||
return;
|
||||
|
||||
/* Try to find a PTE. If not, clear the paddr, we'll do
|
||||
* a vaddr only lookup (PIO only)
|
||||
*/
|
||||
ptep = find_linux_pte(init_mm.pgd, vaddr);
|
||||
if (ptep == NULL)
|
||||
paddr = 0;
|
||||
else
|
||||
paddr = pte_pfn(*ptep) << PAGE_SHIFT;
|
||||
bus = iowa_pci_find(vaddr, paddr);
|
||||
|
||||
bus = spider_pci_find(vaddr, paddr);
|
||||
if (bus == NULL)
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Now do the workaround
|
||||
*/
|
||||
(void)in_be32(bus->regs + SPIDER_PCI_DUMMY_READ);
|
||||
return bus;
|
||||
}
|
||||
|
||||
static u8 spider_readb(const volatile void __iomem *addr)
|
||||
struct iowa_bus *iowa_pio_find_bus(unsigned long port)
|
||||
{
|
||||
u8 val = __do_readb(addr);
|
||||
spider_io_flush(addr);
|
||||
return val;
|
||||
}
|
||||
|
||||
static u16 spider_readw(const volatile void __iomem *addr)
|
||||
{
|
||||
u16 val = __do_readw(addr);
|
||||
spider_io_flush(addr);
|
||||
return val;
|
||||
}
|
||||
|
||||
static u32 spider_readl(const volatile void __iomem *addr)
|
||||
{
|
||||
u32 val = __do_readl(addr);
|
||||
spider_io_flush(addr);
|
||||
return val;
|
||||
}
|
||||
|
||||
static u64 spider_readq(const volatile void __iomem *addr)
|
||||
{
|
||||
u64 val = __do_readq(addr);
|
||||
spider_io_flush(addr);
|
||||
return val;
|
||||
}
|
||||
|
||||
static u16 spider_readw_be(const volatile void __iomem *addr)
|
||||
{
|
||||
u16 val = __do_readw_be(addr);
|
||||
spider_io_flush(addr);
|
||||
return val;
|
||||
}
|
||||
|
||||
static u32 spider_readl_be(const volatile void __iomem *addr)
|
||||
{
|
||||
u32 val = __do_readl_be(addr);
|
||||
spider_io_flush(addr);
|
||||
return val;
|
||||
}
|
||||
|
||||
static u64 spider_readq_be(const volatile void __iomem *addr)
|
||||
{
|
||||
u64 val = __do_readq_be(addr);
|
||||
spider_io_flush(addr);
|
||||
return val;
|
||||
}
|
||||
|
||||
static void spider_readsb(const volatile void __iomem *addr, void *buf,
|
||||
unsigned long count)
|
||||
{
|
||||
__do_readsb(addr, buf, count);
|
||||
spider_io_flush(addr);
|
||||
}
|
||||
|
||||
static void spider_readsw(const volatile void __iomem *addr, void *buf,
|
||||
unsigned long count)
|
||||
{
|
||||
__do_readsw(addr, buf, count);
|
||||
spider_io_flush(addr);
|
||||
}
|
||||
|
||||
static void spider_readsl(const volatile void __iomem *addr, void *buf,
|
||||
unsigned long count)
|
||||
{
|
||||
__do_readsl(addr, buf, count);
|
||||
spider_io_flush(addr);
|
||||
}
|
||||
|
||||
static void spider_memcpy_fromio(void *dest, const volatile void __iomem *src,
|
||||
unsigned long n)
|
||||
{
|
||||
__do_memcpy_fromio(dest, src, n);
|
||||
spider_io_flush(src);
|
||||
unsigned long vaddr = (unsigned long)pci_io_base + port;
|
||||
return iowa_pci_find(vaddr, 0);
|
||||
}
|
||||
|
||||
|
||||
static void __iomem * spider_ioremap(unsigned long addr, unsigned long size,
|
||||
unsigned long flags)
|
||||
#define DEF_PCI_AC_RET(name, ret, at, al, space, aa) \
|
||||
static ret iowa_##name at \
|
||||
{ \
|
||||
struct iowa_bus *bus; \
|
||||
bus = iowa_##space##_find_bus(aa); \
|
||||
if (bus && bus->ops && bus->ops->name) \
|
||||
return bus->ops->name al; \
|
||||
return __do_##name al; \
|
||||
}
|
||||
|
||||
#define DEF_PCI_AC_NORET(name, at, al, space, aa) \
|
||||
static void iowa_##name at \
|
||||
{ \
|
||||
struct iowa_bus *bus; \
|
||||
bus = iowa_##space##_find_bus(aa); \
|
||||
if (bus && bus->ops && bus->ops->name) { \
|
||||
bus->ops->name al; \
|
||||
return; \
|
||||
} \
|
||||
__do_##name al; \
|
||||
}
|
||||
|
||||
#include <asm/io-defs.h>
|
||||
|
||||
#undef DEF_PCI_AC_RET
|
||||
#undef DEF_PCI_AC_NORET
|
||||
|
||||
static struct ppc_pci_io __initdata iowa_pci_io = {
|
||||
|
||||
#define DEF_PCI_AC_RET(name, ret, at, al, space, aa) .name = iowa_##name,
|
||||
#define DEF_PCI_AC_NORET(name, at, al, space, aa) .name = iowa_##name,
|
||||
|
||||
#include <asm/io-defs.h>
|
||||
|
||||
#undef DEF_PCI_AC_RET
|
||||
#undef DEF_PCI_AC_NORET
|
||||
|
||||
};
|
||||
|
||||
static void __iomem *iowa_ioremap(unsigned long addr, unsigned long size,
|
||||
unsigned long flags)
|
||||
{
|
||||
struct spider_pci_bus *bus;
|
||||
struct iowa_bus *bus;
|
||||
void __iomem *res = __ioremap(addr, size, flags);
|
||||
int busno;
|
||||
|
||||
pr_debug("spider_ioremap(0x%lx, 0x%lx, 0x%lx) -> 0x%p\n",
|
||||
addr, size, flags, res);
|
||||
|
||||
bus = spider_pci_find(0, addr);
|
||||
bus = iowa_pci_find(0, addr);
|
||||
if (bus != NULL) {
|
||||
busno = bus - spider_pci_busses;
|
||||
pr_debug(" found bus %d, setting token\n", busno);
|
||||
busno = bus - iowa_busses;
|
||||
PCI_SET_ADDR_TOKEN(res, busno + 1);
|
||||
}
|
||||
pr_debug(" result=0x%p\n", res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static void __init spider_pci_setup_chip(struct spider_pci_bus *bus)
|
||||
/* Regist new bus to support workaround */
|
||||
void __init iowa_register_bus(struct pci_controller *phb,
|
||||
struct ppc_pci_io *ops,
|
||||
int (*initfunc)(struct iowa_bus *, void *), void *data)
|
||||
{
|
||||
#ifdef SPIDER_DISABLE_PREFETCH
|
||||
u32 val = in_be32(bus->regs + SPIDER_PCI_VCI_CNTL_STAT);
|
||||
pr_debug(" PVCI_Control_Status was 0x%08x\n", val);
|
||||
out_be32(bus->regs + SPIDER_PCI_VCI_CNTL_STAT, val | 0x8);
|
||||
#endif
|
||||
|
||||
/* Configure the dummy address for the workaround */
|
||||
out_be32(bus->regs + SPIDER_PCI_DUMMY_READ_BASE, 0x80000000);
|
||||
}
|
||||
|
||||
static void __init spider_pci_add_one(struct pci_controller *phb)
|
||||
{
|
||||
struct spider_pci_bus *bus = &spider_pci_busses[spider_pci_count];
|
||||
struct iowa_bus *bus;
|
||||
struct device_node *np = phb->dn;
|
||||
struct resource rsrc;
|
||||
void __iomem *regs;
|
||||
|
||||
if (spider_pci_count >= MAX_SPIDERS) {
|
||||
printk(KERN_ERR "Too many spider bridges, workarounds"
|
||||
" disabled for %s\n", np->full_name);
|
||||
if (iowa_bus_count >= IOWA_MAX_BUS) {
|
||||
pr_err("IOWA:Too many pci bridges, "
|
||||
"workarounds disabled for %s\n", np->full_name);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get the registers for the beast */
|
||||
if (of_address_to_resource(np, 0, &rsrc)) {
|
||||
printk(KERN_ERR "Failed to get registers for spider %s"
|
||||
" workarounds disabled\n", np->full_name);
|
||||
return;
|
||||
}
|
||||
bus = &iowa_busses[iowa_bus_count];
|
||||
bus->phb = phb;
|
||||
bus->ops = ops;
|
||||
|
||||
/* Mask out some useless bits in there to get to the base of the
|
||||
* spider chip
|
||||
*/
|
||||
rsrc.start &= ~0xfffffffful;
|
||||
if (initfunc)
|
||||
if ((*initfunc)(bus, data))
|
||||
return;
|
||||
|
||||
/* Map them */
|
||||
regs = ioremap(rsrc.start + SPIDER_PCI_REG_BASE, 0x1000);
|
||||
if (regs == NULL) {
|
||||
printk(KERN_ERR "Failed to map registers for spider %s"
|
||||
" workarounds disabled\n", np->full_name);
|
||||
return;
|
||||
}
|
||||
iowa_bus_count++;
|
||||
|
||||
spider_pci_count++;
|
||||
|
||||
/* We assume spiders only have one MMIO resource */
|
||||
bus->mmio_start = phb->mem_resources[0].start;
|
||||
bus->mmio_end = phb->mem_resources[0].end + 1;
|
||||
|
||||
bus->pio_vstart = (unsigned long)phb->io_base_virt;
|
||||
bus->pio_vend = bus->pio_vstart + phb->pci_io_size;
|
||||
|
||||
bus->regs = regs;
|
||||
|
||||
printk(KERN_INFO "PCI: Spider MMIO workaround for %s\n",np->full_name);
|
||||
|
||||
pr_debug(" mmio (P) = 0x%016lx..0x%016lx\n",
|
||||
bus->mmio_start, bus->mmio_end);
|
||||
pr_debug(" pio (V) = 0x%016lx..0x%016lx\n",
|
||||
bus->pio_vstart, bus->pio_vend);
|
||||
pr_debug(" regs (P) = 0x%016lx (V) = 0x%p\n",
|
||||
rsrc.start + SPIDER_PCI_REG_BASE, bus->regs);
|
||||
|
||||
spider_pci_setup_chip(bus);
|
||||
pr_debug("IOWA:[%d]Add bus, %s.\n", iowa_bus_count-1, np->full_name);
|
||||
}
|
||||
|
||||
static struct ppc_pci_io __initdata spider_pci_io = {
|
||||
.readb = spider_readb,
|
||||
.readw = spider_readw,
|
||||
.readl = spider_readl,
|
||||
.readq = spider_readq,
|
||||
.readw_be = spider_readw_be,
|
||||
.readl_be = spider_readl_be,
|
||||
.readq_be = spider_readq_be,
|
||||
.readsb = spider_readsb,
|
||||
.readsw = spider_readsw,
|
||||
.readsl = spider_readsl,
|
||||
.memcpy_fromio = spider_memcpy_fromio,
|
||||
};
|
||||
|
||||
static int __init spider_pci_workaround_init(void)
|
||||
/* enable IO workaround */
|
||||
void __init io_workaround_init(void)
|
||||
{
|
||||
struct pci_controller *phb;
|
||||
static int io_workaround_inited;
|
||||
|
||||
/* Find spider bridges. We assume they have been all probed
|
||||
* in setup_arch(). If that was to change, we would need to
|
||||
* update this code to cope with dynamically added busses
|
||||
*/
|
||||
list_for_each_entry(phb, &hose_list, list_node) {
|
||||
struct device_node *np = phb->dn;
|
||||
const char *model = of_get_property(np, "model", NULL);
|
||||
|
||||
/* If no model property or name isn't exactly "pci", skip */
|
||||
if (model == NULL || strcmp(np->name, "pci"))
|
||||
continue;
|
||||
/* If model is not "Spider", skip */
|
||||
if (strcmp(model, "Spider"))
|
||||
continue;
|
||||
spider_pci_add_one(phb);
|
||||
}
|
||||
|
||||
/* No Spider PCI found, exit */
|
||||
if (spider_pci_count == 0)
|
||||
return 0;
|
||||
|
||||
/* Setup IO callbacks. We only setup MMIO reads. PIO reads will
|
||||
* fallback to MMIO reads (though without a token, thus slower)
|
||||
*/
|
||||
ppc_pci_io = spider_pci_io;
|
||||
|
||||
/* Setup ioremap callback */
|
||||
ppc_md.ioremap = spider_ioremap;
|
||||
|
||||
return 0;
|
||||
if (io_workaround_inited)
|
||||
return;
|
||||
ppc_pci_io = iowa_pci_io;
|
||||
ppc_md.ioremap = iowa_ioremap;
|
||||
io_workaround_inited = 1;
|
||||
}
|
||||
machine_arch_initcall(cell, spider_pci_workaround_init);
|
||||
|
49
arch/powerpc/platforms/cell/io-workarounds.h
Normal file
49
arch/powerpc/platforms/cell/io-workarounds.h
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Support PCI IO workaround
|
||||
*
|
||||
* (C) Copyright 2007-2008 TOSHIBA CORPORATION
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef _IO_WORKAROUNDS_H
|
||||
#define _IO_WORKAROUNDS_H
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <asm/pci-bridge.h>
|
||||
|
||||
/* Bus info */
|
||||
struct iowa_bus {
|
||||
struct pci_controller *phb;
|
||||
struct ppc_pci_io *ops;
|
||||
void *private;
|
||||
};
|
||||
|
||||
void __init io_workaround_init(void);
|
||||
void __init iowa_register_bus(struct pci_controller *, struct ppc_pci_io *,
|
||||
int (*)(struct iowa_bus *, void *), void *);
|
||||
struct iowa_bus *iowa_mem_find_bus(const PCI_IO_ADDR);
|
||||
struct iowa_bus *iowa_pio_find_bus(unsigned long);
|
||||
|
||||
extern struct ppc_pci_io spiderpci_ops;
|
||||
extern int spiderpci_iowa_init(struct iowa_bus *, void *);
|
||||
|
||||
#define SPIDER_PCI_REG_BASE 0xd000
|
||||
#define SPIDER_PCI_REG_SIZE 0x1000
|
||||
#define SPIDER_PCI_VCI_CNTL_STAT 0x0110
|
||||
#define SPIDER_PCI_DUMMY_READ 0x0810
|
||||
#define SPIDER_PCI_DUMMY_READ_BASE 0x0814
|
||||
|
||||
#endif /* _IO_WORKAROUNDS_H */
|
@ -57,6 +57,7 @@
|
||||
#include "interrupt.h"
|
||||
#include "pervasive.h"
|
||||
#include "ras.h"
|
||||
#include "io-workarounds.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DBG(fmt...) udbg_printf(fmt)
|
||||
@ -117,13 +118,50 @@ static void cell_fixup_pcie_rootcomplex(struct pci_dev *dev)
|
||||
}
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, cell_fixup_pcie_rootcomplex);
|
||||
|
||||
static int __devinit cell_setup_phb(struct pci_controller *phb)
|
||||
{
|
||||
const char *model;
|
||||
struct device_node *np;
|
||||
|
||||
int rc = rtas_setup_phb(phb);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
np = phb->dn;
|
||||
model = of_get_property(np, "model", NULL);
|
||||
if (model == NULL || strcmp(np->name, "pci"))
|
||||
return 0;
|
||||
|
||||
/* Setup workarounds for spider */
|
||||
if (strcmp(model, "Spider"))
|
||||
return 0;
|
||||
|
||||
iowa_register_bus(phb, &spiderpci_ops, &spiderpci_iowa_init,
|
||||
(void *)SPIDER_PCI_REG_BASE);
|
||||
io_workaround_init();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init cell_publish_devices(void)
|
||||
{
|
||||
struct device_node *root = of_find_node_by_path("/");
|
||||
struct device_node *np;
|
||||
int node;
|
||||
|
||||
/* Publish OF platform devices for southbridge IOs */
|
||||
of_platform_bus_probe(NULL, NULL, NULL);
|
||||
|
||||
/* On spider based blades, we need to manually create the OF
|
||||
* platform devices for the PCI host bridges
|
||||
*/
|
||||
for_each_child_of_node(root, np) {
|
||||
if (np->type == NULL || (strcmp(np->type, "pci") != 0 &&
|
||||
strcmp(np->type, "pciex") != 0))
|
||||
continue;
|
||||
of_platform_device_create(np, NULL, NULL);
|
||||
}
|
||||
|
||||
/* There is no device for the MIC memory controller, thus we create
|
||||
* a platform device for it to attach the EDAC driver to.
|
||||
*/
|
||||
@ -132,6 +170,7 @@ static int __init cell_publish_devices(void)
|
||||
continue;
|
||||
platform_device_register_simple("cbe-mic", node, NULL, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
machine_subsys_initcall(cell, cell_publish_devices);
|
||||
@ -213,7 +252,7 @@ static void __init cell_setup_arch(void)
|
||||
|
||||
/* Find and initialize PCI host bridges */
|
||||
init_pci_config_tokens();
|
||||
find_and_init_phbs();
|
||||
|
||||
cbe_pervasive_init();
|
||||
#ifdef CONFIG_DUMMY_CONSOLE
|
||||
conswitchp = &dummy_con;
|
||||
@ -249,7 +288,7 @@ define_machine(cell) {
|
||||
.calibrate_decr = generic_calibrate_decr,
|
||||
.progress = cell_progress,
|
||||
.init_IRQ = cell_init_irq,
|
||||
.pci_setup_phb = rtas_setup_phb,
|
||||
.pci_setup_phb = cell_setup_phb,
|
||||
#ifdef CONFIG_KEXEC
|
||||
.machine_kexec = default_machine_kexec,
|
||||
.machine_kexec_prepare = default_machine_kexec_prepare,
|
||||
|
184
arch/powerpc/platforms/cell/spider-pci.c
Normal file
184
arch/powerpc/platforms/cell/spider-pci.c
Normal file
@ -0,0 +1,184 @@
|
||||
/*
|
||||
* IO workarounds for PCI on Celleb/Cell platform
|
||||
*
|
||||
* (C) Copyright 2006-2007 TOSHIBA CORPORATION
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#undef DEBUG
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <asm/ppc-pci.h>
|
||||
#include <asm/pci-bridge.h>
|
||||
|
||||
#include "io-workarounds.h"
|
||||
|
||||
#define SPIDER_PCI_DISABLE_PREFETCH
|
||||
|
||||
struct spiderpci_iowa_private {
|
||||
void __iomem *regs;
|
||||
};
|
||||
|
||||
static void spiderpci_io_flush(struct iowa_bus *bus)
|
||||
{
|
||||
struct spiderpci_iowa_private *priv;
|
||||
u32 val;
|
||||
|
||||
priv = bus->private;
|
||||
val = in_be32(priv->regs + SPIDER_PCI_DUMMY_READ);
|
||||
iosync();
|
||||
}
|
||||
|
||||
#define SPIDER_PCI_MMIO_READ(name, ret) \
|
||||
static ret spiderpci_##name(const PCI_IO_ADDR addr) \
|
||||
{ \
|
||||
ret val = __do_##name(addr); \
|
||||
spiderpci_io_flush(iowa_mem_find_bus(addr)); \
|
||||
return val; \
|
||||
}
|
||||
|
||||
#define SPIDER_PCI_MMIO_READ_STR(name) \
|
||||
static void spiderpci_##name(const PCI_IO_ADDR addr, void *buf, \
|
||||
unsigned long count) \
|
||||
{ \
|
||||
__do_##name(addr, buf, count); \
|
||||
spiderpci_io_flush(iowa_mem_find_bus(addr)); \
|
||||
}
|
||||
|
||||
SPIDER_PCI_MMIO_READ(readb, u8)
|
||||
SPIDER_PCI_MMIO_READ(readw, u16)
|
||||
SPIDER_PCI_MMIO_READ(readl, u32)
|
||||
SPIDER_PCI_MMIO_READ(readq, u64)
|
||||
SPIDER_PCI_MMIO_READ(readw_be, u16)
|
||||
SPIDER_PCI_MMIO_READ(readl_be, u32)
|
||||
SPIDER_PCI_MMIO_READ(readq_be, u64)
|
||||
SPIDER_PCI_MMIO_READ_STR(readsb)
|
||||
SPIDER_PCI_MMIO_READ_STR(readsw)
|
||||
SPIDER_PCI_MMIO_READ_STR(readsl)
|
||||
|
||||
static void spiderpci_memcpy_fromio(void *dest, const PCI_IO_ADDR src,
|
||||
unsigned long n)
|
||||
{
|
||||
__do_memcpy_fromio(dest, src, n);
|
||||
spiderpci_io_flush(iowa_mem_find_bus(src));
|
||||
}
|
||||
|
||||
static int __init spiderpci_pci_setup_chip(struct pci_controller *phb,
|
||||
void __iomem *regs)
|
||||
{
|
||||
void *dummy_page_va;
|
||||
dma_addr_t dummy_page_da;
|
||||
|
||||
#ifdef SPIDER_PCI_DISABLE_PREFETCH
|
||||
u32 val = in_be32(regs + SPIDER_PCI_VCI_CNTL_STAT);
|
||||
pr_debug("SPIDER_IOWA:PVCI_Control_Status was 0x%08x\n", val);
|
||||
out_be32(regs + SPIDER_PCI_VCI_CNTL_STAT, val | 0x8);
|
||||
#endif /* SPIDER_PCI_DISABLE_PREFETCH */
|
||||
|
||||
/* setup dummy read */
|
||||
/*
|
||||
* On CellBlade, we can't know that which XDR memory is used by
|
||||
* kmalloc() to allocate dummy_page_va.
|
||||
* In order to imporve the performance, the XDR which is used to
|
||||
* allocate dummy_page_va is the nearest the spider-pci.
|
||||
* We have to select the CBE which is the nearest the spider-pci
|
||||
* to allocate memory from the best XDR, but I don't know that
|
||||
* how to do.
|
||||
*
|
||||
* Celleb does not have this problem, because it has only one XDR.
|
||||
*/
|
||||
dummy_page_va = kmalloc(PAGE_SIZE, GFP_KERNEL);
|
||||
if (!dummy_page_va) {
|
||||
pr_err("SPIDERPCI-IOWA:Alloc dummy_page_va failed.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
dummy_page_da = dma_map_single(phb->parent, dummy_page_va,
|
||||
PAGE_SIZE, DMA_FROM_DEVICE);
|
||||
if (dma_mapping_error(dummy_page_da)) {
|
||||
pr_err("SPIDER-IOWA:Map dummy page filed.\n");
|
||||
kfree(dummy_page_va);
|
||||
return -1;
|
||||
}
|
||||
|
||||
out_be32(regs + SPIDER_PCI_DUMMY_READ_BASE, dummy_page_da);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __init spiderpci_iowa_init(struct iowa_bus *bus, void *data)
|
||||
{
|
||||
void __iomem *regs = NULL;
|
||||
struct spiderpci_iowa_private *priv;
|
||||
struct device_node *np = bus->phb->dn;
|
||||
struct resource r;
|
||||
unsigned long offset = (unsigned long)data;
|
||||
|
||||
pr_debug("SPIDERPCI-IOWA:Bus initialize for spider(%s)\n",
|
||||
np->full_name);
|
||||
|
||||
priv = kzalloc(sizeof(struct spiderpci_iowa_private), GFP_KERNEL);
|
||||
if (!priv) {
|
||||
pr_err("SPIDERPCI-IOWA:"
|
||||
"Can't allocate struct spiderpci_iowa_private");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (of_address_to_resource(np, 0, &r)) {
|
||||
pr_err("SPIDERPCI-IOWA:Can't get resource.\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
regs = ioremap(r.start + offset, SPIDER_PCI_REG_SIZE);
|
||||
if (!regs) {
|
||||
pr_err("SPIDERPCI-IOWA:ioremap failed.\n");
|
||||
goto error;
|
||||
}
|
||||
priv->regs = regs;
|
||||
bus->private = priv;
|
||||
|
||||
if (spiderpci_pci_setup_chip(bus->phb, regs))
|
||||
goto error;
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
kfree(priv);
|
||||
bus->private = NULL;
|
||||
|
||||
if (regs)
|
||||
iounmap(regs);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct ppc_pci_io spiderpci_ops = {
|
||||
.readb = spiderpci_readb,
|
||||
.readw = spiderpci_readw,
|
||||
.readl = spiderpci_readl,
|
||||
.readq = spiderpci_readq,
|
||||
.readw_be = spiderpci_readw_be,
|
||||
.readl_be = spiderpci_readl_be,
|
||||
.readq_be = spiderpci_readq_be,
|
||||
.readsb = spiderpci_readsb,
|
||||
.readsw = spiderpci_readsw,
|
||||
.readsl = spiderpci_readsl,
|
||||
.memcpy_fromio = spiderpci_memcpy_fromio,
|
||||
};
|
||||
|
@ -1,12 +0,0 @@
|
||||
config PPC_CELLEB
|
||||
bool "Toshiba's Cell Reference Set 'Celleb' Architecture"
|
||||
depends on PPC_MULTIPLATFORM && PPC64
|
||||
select PPC_CELL
|
||||
select PPC_CELL_NATIVE
|
||||
select PPC_RTAS
|
||||
select PPC_INDIRECT_IO
|
||||
select PPC_OF_PLATFORM_PCI
|
||||
select HAS_TXX9_SERIAL
|
||||
select PPC_UDBG_BEAT
|
||||
select USB_OHCI_BIG_ENDIAN_MMIO
|
||||
select USB_EHCI_BIG_ENDIAN_MMIO
|
@ -1,9 +0,0 @@
|
||||
obj-y += interrupt.o iommu.o setup.o \
|
||||
htab.o beat.o hvCall.o pci.o \
|
||||
scc_epci.o scc_uhc.o \
|
||||
io-workarounds.o
|
||||
|
||||
obj-$(CONFIG_SMP) += smp.o
|
||||
obj-$(CONFIG_PPC_UDBG_BEAT) += udbg_beat.o
|
||||
obj-$(CONFIG_SERIAL_TXX9) += scc_sio.o
|
||||
obj-$(CONFIG_SPU_BASE) += spu_priv1.o
|
@ -1,280 +0,0 @@
|
||||
/*
|
||||
* Support for Celleb io workarounds
|
||||
*
|
||||
* (C) Copyright 2006-2007 TOSHIBA CORPORATION
|
||||
*
|
||||
* This file is based to arch/powerpc/platform/cell/io-workarounds.c
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#undef DEBUG
|
||||
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/irq.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/pci-bridge.h>
|
||||
#include <asm/ppc-pci.h>
|
||||
|
||||
#include "pci.h"
|
||||
|
||||
#define MAX_CELLEB_PCI_BUS 4
|
||||
|
||||
void *celleb_dummy_page_va;
|
||||
|
||||
static struct celleb_pci_bus {
|
||||
struct pci_controller *phb;
|
||||
void (*dummy_read)(struct pci_controller *);
|
||||
} celleb_pci_busses[MAX_CELLEB_PCI_BUS];
|
||||
|
||||
static int celleb_pci_count = 0;
|
||||
|
||||
static struct celleb_pci_bus *celleb_pci_find(unsigned long vaddr,
|
||||
unsigned long paddr)
|
||||
{
|
||||
int i, j;
|
||||
struct resource *res;
|
||||
|
||||
for (i = 0; i < celleb_pci_count; i++) {
|
||||
struct celleb_pci_bus *bus = &celleb_pci_busses[i];
|
||||
struct pci_controller *phb = bus->phb;
|
||||
if (paddr)
|
||||
for (j = 0; j < 3; j++) {
|
||||
res = &phb->mem_resources[j];
|
||||
if (paddr >= res->start && paddr <= res->end)
|
||||
return bus;
|
||||
}
|
||||
res = &phb->io_resource;
|
||||
if (vaddr && vaddr >= res->start && vaddr <= res->end)
|
||||
return bus;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void celleb_io_flush(const PCI_IO_ADDR addr)
|
||||
{
|
||||
struct celleb_pci_bus *bus;
|
||||
int token;
|
||||
|
||||
token = PCI_GET_ADDR_TOKEN(addr);
|
||||
|
||||
if (token && token <= celleb_pci_count)
|
||||
bus = &celleb_pci_busses[token - 1];
|
||||
else {
|
||||
unsigned long vaddr, paddr;
|
||||
pte_t *ptep;
|
||||
|
||||
vaddr = (unsigned long)PCI_FIX_ADDR(addr);
|
||||
if (vaddr < PHB_IO_BASE || vaddr >= PHB_IO_END)
|
||||
return;
|
||||
|
||||
ptep = find_linux_pte(init_mm.pgd, vaddr);
|
||||
if (ptep == NULL)
|
||||
paddr = 0;
|
||||
else
|
||||
paddr = pte_pfn(*ptep) << PAGE_SHIFT;
|
||||
bus = celleb_pci_find(vaddr, paddr);
|
||||
|
||||
if (bus == NULL)
|
||||
return;
|
||||
}
|
||||
|
||||
if (bus->dummy_read)
|
||||
bus->dummy_read(bus->phb);
|
||||
}
|
||||
|
||||
static u8 celleb_readb(const PCI_IO_ADDR addr)
|
||||
{
|
||||
u8 val;
|
||||
val = __do_readb(addr);
|
||||
celleb_io_flush(addr);
|
||||
return val;
|
||||
}
|
||||
|
||||
static u16 celleb_readw(const PCI_IO_ADDR addr)
|
||||
{
|
||||
u16 val;
|
||||
val = __do_readw(addr);
|
||||
celleb_io_flush(addr);
|
||||
return val;
|
||||
}
|
||||
|
||||
static u32 celleb_readl(const PCI_IO_ADDR addr)
|
||||
{
|
||||
u32 val;
|
||||
val = __do_readl(addr);
|
||||
celleb_io_flush(addr);
|
||||
return val;
|
||||
}
|
||||
|
||||
static u64 celleb_readq(const PCI_IO_ADDR addr)
|
||||
{
|
||||
u64 val;
|
||||
val = __do_readq(addr);
|
||||
celleb_io_flush(addr);
|
||||
return val;
|
||||
}
|
||||
|
||||
static u16 celleb_readw_be(const PCI_IO_ADDR addr)
|
||||
{
|
||||
u16 val;
|
||||
val = __do_readw_be(addr);
|
||||
celleb_io_flush(addr);
|
||||
return val;
|
||||
}
|
||||
|
||||
static u32 celleb_readl_be(const PCI_IO_ADDR addr)
|
||||
{
|
||||
u32 val;
|
||||
val = __do_readl_be(addr);
|
||||
celleb_io_flush(addr);
|
||||
return val;
|
||||
}
|
||||
|
||||
static u64 celleb_readq_be(const PCI_IO_ADDR addr)
|
||||
{
|
||||
u64 val;
|
||||
val = __do_readq_be(addr);
|
||||
celleb_io_flush(addr);
|
||||
return val;
|
||||
}
|
||||
|
||||
static void celleb_readsb(const PCI_IO_ADDR addr,
|
||||
void *buf, unsigned long count)
|
||||
{
|
||||
__do_readsb(addr, buf, count);
|
||||
celleb_io_flush(addr);
|
||||
}
|
||||
|
||||
static void celleb_readsw(const PCI_IO_ADDR addr,
|
||||
void *buf, unsigned long count)
|
||||
{
|
||||
__do_readsw(addr, buf, count);
|
||||
celleb_io_flush(addr);
|
||||
}
|
||||
|
||||
static void celleb_readsl(const PCI_IO_ADDR addr,
|
||||
void *buf, unsigned long count)
|
||||
{
|
||||
__do_readsl(addr, buf, count);
|
||||
celleb_io_flush(addr);
|
||||
}
|
||||
|
||||
static void celleb_memcpy_fromio(void *dest,
|
||||
const PCI_IO_ADDR src,
|
||||
unsigned long n)
|
||||
{
|
||||
__do_memcpy_fromio(dest, src, n);
|
||||
celleb_io_flush(src);
|
||||
}
|
||||
|
||||
static void __iomem *celleb_ioremap(unsigned long addr,
|
||||
unsigned long size,
|
||||
unsigned long flags)
|
||||
{
|
||||
struct celleb_pci_bus *bus;
|
||||
void __iomem *res = __ioremap(addr, size, flags);
|
||||
int busno;
|
||||
|
||||
bus = celleb_pci_find(0, addr);
|
||||
if (bus != NULL) {
|
||||
busno = bus - celleb_pci_busses;
|
||||
PCI_SET_ADDR_TOKEN(res, busno + 1);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static void celleb_iounmap(volatile void __iomem *addr)
|
||||
{
|
||||
return __iounmap(PCI_FIX_ADDR(addr));
|
||||
}
|
||||
|
||||
static struct ppc_pci_io celleb_pci_io __initdata = {
|
||||
.readb = celleb_readb,
|
||||
.readw = celleb_readw,
|
||||
.readl = celleb_readl,
|
||||
.readq = celleb_readq,
|
||||
.readw_be = celleb_readw_be,
|
||||
.readl_be = celleb_readl_be,
|
||||
.readq_be = celleb_readq_be,
|
||||
.readsb = celleb_readsb,
|
||||
.readsw = celleb_readsw,
|
||||
.readsl = celleb_readsl,
|
||||
.memcpy_fromio = celleb_memcpy_fromio,
|
||||
};
|
||||
|
||||
void __init celleb_pci_add_one(struct pci_controller *phb,
|
||||
void (*dummy_read)(struct pci_controller *))
|
||||
{
|
||||
struct celleb_pci_bus *bus = &celleb_pci_busses[celleb_pci_count];
|
||||
struct device_node *np = phb->dn;
|
||||
|
||||
if (celleb_pci_count >= MAX_CELLEB_PCI_BUS) {
|
||||
printk(KERN_ERR "Too many pci bridges, workarounds"
|
||||
" disabled for %s\n", np->full_name);
|
||||
return;
|
||||
}
|
||||
|
||||
celleb_pci_count++;
|
||||
|
||||
bus->phb = phb;
|
||||
bus->dummy_read = dummy_read;
|
||||
}
|
||||
|
||||
static struct of_device_id celleb_pci_workaround_match[] __initdata = {
|
||||
{
|
||||
.name = "pci-pseudo",
|
||||
.data = fake_pci_workaround_init,
|
||||
}, {
|
||||
.name = "epci",
|
||||
.data = epci_workaround_init,
|
||||
}, {
|
||||
},
|
||||
};
|
||||
|
||||
int __init celleb_pci_workaround_init(void)
|
||||
{
|
||||
struct pci_controller *phb;
|
||||
struct device_node *node;
|
||||
const struct of_device_id *match;
|
||||
void (*init_func)(struct pci_controller *);
|
||||
|
||||
celleb_dummy_page_va = kmalloc(PAGE_SIZE, GFP_KERNEL);
|
||||
if (!celleb_dummy_page_va) {
|
||||
printk(KERN_ERR "Celleb: dummy read disabled. "
|
||||
"Alloc celleb_dummy_page_va failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
list_for_each_entry(phb, &hose_list, list_node) {
|
||||
node = phb->dn;
|
||||
match = of_match_node(celleb_pci_workaround_match, node);
|
||||
|
||||
if (match) {
|
||||
init_func = match->data;
|
||||
(*init_func)(phb);
|
||||
}
|
||||
}
|
||||
|
||||
ppc_pci_io = celleb_pci_io;
|
||||
ppc_md.ioremap = celleb_ioremap;
|
||||
ppc_md.iounmap = celleb_iounmap;
|
||||
|
||||
return 0;
|
||||
}
|
@ -59,8 +59,33 @@ system_reset_iSeries:
|
||||
andc r4,r4,r5
|
||||
mtspr SPRN_CTRLT,r4
|
||||
|
||||
/* Spin on __secondary_hold_spinloop until it is updated by the boot cpu. */
|
||||
/* In the UP case we'll yeild() later, and we will not access the paca anyway */
|
||||
#ifdef CONFIG_SMP
|
||||
1:
|
||||
HMT_LOW
|
||||
LOAD_REG_IMMEDIATE(r23, __secondary_hold_spinloop)
|
||||
ld r23,0(r23)
|
||||
sync
|
||||
LOAD_REG_IMMEDIATE(r3,current_set)
|
||||
sldi r28,r24,3 /* get current_set[cpu#] */
|
||||
ldx r3,r3,r28
|
||||
addi r1,r3,THREAD_SIZE
|
||||
subi r1,r1,STACK_FRAME_OVERHEAD
|
||||
|
||||
cmpwi 0,r23,0 /* Keep poking the Hypervisor until */
|
||||
bne 2f /* we're released */
|
||||
/* Let the Hypervisor know we are alive */
|
||||
/* 8002 is a call to HvCallCfg::getLps, a harmless Hypervisor function */
|
||||
lis r3,0x8002
|
||||
rldicr r3,r3,32,15 /* r0 = (r3 << 32) & 0xffff000000000000 */
|
||||
li r0,-1 /* r0=-1 indicates a Hypervisor call */
|
||||
sc /* Invoke the hypervisor via a system call */
|
||||
b 1b
|
||||
#endif
|
||||
|
||||
2:
|
||||
HMT_LOW
|
||||
#ifdef CONFIG_SMP
|
||||
lbz r23,PACAPROCSTART(r13) /* Test if this processor
|
||||
* should start */
|
||||
@ -91,7 +116,7 @@ iSeries_secondary_smp_loop:
|
||||
li r0,-1 /* r0=-1 indicates a Hypervisor call */
|
||||
sc /* Invoke the hypervisor via a system call */
|
||||
mfspr r13,SPRN_SPRG3 /* Put r13 back ???? */
|
||||
b 1b /* If SMP not configured, secondaries
|
||||
b 2b /* If SMP not configured, secondaries
|
||||
* loop forever */
|
||||
|
||||
/*** ISeries-LPAR interrupt handlers ***/
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <linux/syscalls.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/lmb.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <asm/prom.h>
|
||||
|
||||
|
@ -34,3 +34,8 @@ config LPARCFG
|
||||
help
|
||||
Provide system capacity information via human readable
|
||||
<key word>=<value> pairs through a /proc/ppc64/lparcfg interface.
|
||||
|
||||
config PPC_PSERIES_DEBUG
|
||||
depends on PPC_PSERIES && PPC_EARLY_DEBUG
|
||||
bool "Enable extra debug logging in platforms/pseries"
|
||||
default y
|
||||
|
@ -2,6 +2,10 @@ ifeq ($(CONFIG_PPC64),y)
|
||||
EXTRA_CFLAGS += -mno-minimal-toc
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_PPC_PSERIES_DEBUG),y)
|
||||
EXTRA_CFLAGS += -DDEBUG
|
||||
endif
|
||||
|
||||
obj-y := lpar.o hvCall.o nvram.o reconfig.o \
|
||||
setup.o iommu.o ras.o rtasd.o \
|
||||
firmware.o power.o
|
||||
|
@ -39,7 +39,6 @@
|
||||
#include <asm/ppc-pci.h>
|
||||
#include <asm/rtas.h>
|
||||
|
||||
#undef DEBUG
|
||||
|
||||
/** Overview:
|
||||
* EEH, or "Extended Error Handling" is a PCI bridge technology for
|
||||
|
@ -28,7 +28,6 @@
|
||||
#include <asm/pci-bridge.h>
|
||||
#include <asm/ppc-pci.h>
|
||||
|
||||
#undef DEBUG
|
||||
|
||||
/**
|
||||
* The pci address cache subsystem. This subsystem places
|
||||
|
@ -21,17 +21,11 @@
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#undef DEBUG
|
||||
|
||||
#include <asm/firmware.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/udbg.h>
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DBG(fmt...) udbg_printf(fmt)
|
||||
#else
|
||||
#define DBG(fmt...)
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
unsigned long val;
|
||||
@ -72,7 +66,7 @@ void __init fw_feature_init(const char *hypertas, unsigned long len)
|
||||
const char *s;
|
||||
int i;
|
||||
|
||||
DBG(" -> fw_feature_init()\n");
|
||||
pr_debug(" -> fw_feature_init()\n");
|
||||
|
||||
for (s = hypertas; s < hypertas + len; s += strlen(s) + 1) {
|
||||
for (i = 0; i < FIRMWARE_MAX_FEATURES; i++) {
|
||||
@ -88,5 +82,5 @@ void __init fw_feature_init(const char *hypertas, unsigned long len)
|
||||
}
|
||||
}
|
||||
|
||||
DBG(" <- fw_feature_init()\n");
|
||||
pr_debug(" <- fw_feature_init()\n");
|
||||
}
|
||||
|
@ -47,7 +47,6 @@
|
||||
|
||||
#include "plpar_wrappers.h"
|
||||
|
||||
#define DBG(fmt...)
|
||||
|
||||
static void tce_build_pSeries(struct iommu_table *tbl, long index,
|
||||
long npages, unsigned long uaddr,
|
||||
@ -322,7 +321,7 @@ static void pci_dma_bus_setup_pSeries(struct pci_bus *bus)
|
||||
|
||||
dn = pci_bus_to_OF_node(bus);
|
||||
|
||||
DBG("pci_dma_bus_setup_pSeries: setting up bus %s\n", dn->full_name);
|
||||
pr_debug("pci_dma_bus_setup_pSeries: setting up bus %s\n", dn->full_name);
|
||||
|
||||
if (bus->self) {
|
||||
/* This is not a root bus, any setup will be done for the
|
||||
@ -347,7 +346,7 @@ static void pci_dma_bus_setup_pSeries(struct pci_bus *bus)
|
||||
for (children = 0, tmp = dn->child; tmp; tmp = tmp->sibling)
|
||||
children++;
|
||||
|
||||
DBG("Children: %d\n", children);
|
||||
pr_debug("Children: %d\n", children);
|
||||
|
||||
/* Calculate amount of DMA window per slot. Each window must be
|
||||
* a power of two (due to pci_alloc_consistent requirements).
|
||||
@ -361,8 +360,8 @@ static void pci_dma_bus_setup_pSeries(struct pci_bus *bus)
|
||||
|
||||
while (pci->phb->dma_window_size * children > 0x80000000ul)
|
||||
pci->phb->dma_window_size >>= 1;
|
||||
DBG("No ISA/IDE, window size is 0x%lx\n",
|
||||
pci->phb->dma_window_size);
|
||||
pr_debug("No ISA/IDE, window size is 0x%lx\n",
|
||||
pci->phb->dma_window_size);
|
||||
pci->phb->dma_window_base_cur = 0;
|
||||
|
||||
return;
|
||||
@ -387,8 +386,7 @@ static void pci_dma_bus_setup_pSeries(struct pci_bus *bus)
|
||||
while (pci->phb->dma_window_size * children > 0x70000000ul)
|
||||
pci->phb->dma_window_size >>= 1;
|
||||
|
||||
DBG("ISA/IDE, window size is 0x%lx\n", pci->phb->dma_window_size);
|
||||
|
||||
pr_debug("ISA/IDE, window size is 0x%lx\n", pci->phb->dma_window_size);
|
||||
}
|
||||
|
||||
|
||||
@ -401,7 +399,8 @@ static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus)
|
||||
|
||||
dn = pci_bus_to_OF_node(bus);
|
||||
|
||||
DBG("pci_dma_bus_setup_pSeriesLP: setting up bus %s\n", dn->full_name);
|
||||
pr_debug("pci_dma_bus_setup_pSeriesLP: setting up bus %s\n",
|
||||
dn->full_name);
|
||||
|
||||
/* Find nearest ibm,dma-window, walking up the device tree */
|
||||
for (pdn = dn; pdn != NULL; pdn = pdn->parent) {
|
||||
@ -411,14 +410,14 @@ static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus)
|
||||
}
|
||||
|
||||
if (dma_window == NULL) {
|
||||
DBG(" no ibm,dma-window property !\n");
|
||||
pr_debug(" no ibm,dma-window property !\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ppci = PCI_DN(pdn);
|
||||
|
||||
DBG(" parent is %s, iommu_table: 0x%p\n",
|
||||
pdn->full_name, ppci->iommu_table);
|
||||
pr_debug(" parent is %s, iommu_table: 0x%p\n",
|
||||
pdn->full_name, ppci->iommu_table);
|
||||
|
||||
if (!ppci->iommu_table) {
|
||||
tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL,
|
||||
@ -426,7 +425,7 @@ static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus)
|
||||
iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window,
|
||||
bus->number);
|
||||
ppci->iommu_table = iommu_init_table(tbl, ppci->phb->node);
|
||||
DBG(" created table: %p\n", ppci->iommu_table);
|
||||
pr_debug(" created table: %p\n", ppci->iommu_table);
|
||||
}
|
||||
|
||||
if (pdn != dn)
|
||||
@ -439,7 +438,7 @@ static void pci_dma_dev_setup_pSeries(struct pci_dev *dev)
|
||||
struct device_node *dn;
|
||||
struct iommu_table *tbl;
|
||||
|
||||
DBG("pci_dma_dev_setup_pSeries: %s\n", pci_name(dev));
|
||||
pr_debug("pci_dma_dev_setup_pSeries: %s\n", pci_name(dev));
|
||||
|
||||
dn = dev->dev.archdata.of_node;
|
||||
|
||||
@ -450,7 +449,7 @@ static void pci_dma_dev_setup_pSeries(struct pci_dev *dev)
|
||||
if (!dev->bus->self) {
|
||||
struct pci_controller *phb = PCI_DN(dn)->phb;
|
||||
|
||||
DBG(" --> first child, no bridge. Allocating iommu table.\n");
|
||||
pr_debug(" --> first child, no bridge. Allocating iommu table.\n");
|
||||
tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL,
|
||||
phb->node);
|
||||
iommu_table_setparms(phb, dn, tbl);
|
||||
@ -480,7 +479,7 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
|
||||
const void *dma_window = NULL;
|
||||
struct pci_dn *pci;
|
||||
|
||||
DBG("pci_dma_dev_setup_pSeriesLP: %s\n", pci_name(dev));
|
||||
pr_debug("pci_dma_dev_setup_pSeriesLP: %s\n", pci_name(dev));
|
||||
|
||||
/* dev setup for LPAR is a little tricky, since the device tree might
|
||||
* contain the dma-window properties per-device and not neccesarily
|
||||
@ -489,7 +488,7 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
|
||||
* already allocated.
|
||||
*/
|
||||
dn = pci_device_to_OF_node(dev);
|
||||
DBG(" node is %s\n", dn->full_name);
|
||||
pr_debug(" node is %s\n", dn->full_name);
|
||||
|
||||
for (pdn = dn; pdn && PCI_DN(pdn) && !PCI_DN(pdn)->iommu_table;
|
||||
pdn = pdn->parent) {
|
||||
@ -504,13 +503,13 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
|
||||
pci_name(dev), dn? dn->full_name : "<null>");
|
||||
return;
|
||||
}
|
||||
DBG(" parent is %s\n", pdn->full_name);
|
||||
pr_debug(" parent is %s\n", pdn->full_name);
|
||||
|
||||
/* Check for parent == NULL so we don't try to setup the empty EADS
|
||||
* slots on POWER4 machines.
|
||||
*/
|
||||
if (dma_window == NULL || pdn->parent == NULL) {
|
||||
DBG(" no dma window for device, linking to parent\n");
|
||||
pr_debug(" no dma window for device, linking to parent\n");
|
||||
dev->dev.archdata.dma_data = PCI_DN(pdn)->iommu_table;
|
||||
return;
|
||||
}
|
||||
@ -522,9 +521,9 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
|
||||
iommu_table_setparms_lpar(pci->phb, pdn, tbl, dma_window,
|
||||
pci->phb->bus->number);
|
||||
pci->iommu_table = iommu_init_table(tbl, pci->phb->node);
|
||||
DBG(" created table: %p\n", pci->iommu_table);
|
||||
pr_debug(" created table: %p\n", pci->iommu_table);
|
||||
} else {
|
||||
DBG(" found DMA window, table: %p\n", pci->iommu_table);
|
||||
pr_debug(" found DMA window, table: %p\n", pci->iommu_table);
|
||||
}
|
||||
|
||||
dev->dev.archdata.dma_data = pci->iommu_table;
|
||||
|
@ -19,7 +19,8 @@
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#undef DEBUG_LOW
|
||||
/* Enables debugging of low-level hash table routines - careful! */
|
||||
#undef DEBUG
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
@ -42,11 +43,6 @@
|
||||
#include "plpar_wrappers.h"
|
||||
#include "pseries.h"
|
||||
|
||||
#ifdef DEBUG_LOW
|
||||
#define DBG_LOW(fmt...) do { udbg_printf(fmt); } while(0)
|
||||
#else
|
||||
#define DBG_LOW(fmt...) do { } while(0)
|
||||
#endif
|
||||
|
||||
/* in hvCall.S */
|
||||
EXPORT_SYMBOL(plpar_hcall);
|
||||
@ -196,6 +192,8 @@ void __init udbg_init_debug_lpar(void)
|
||||
udbg_putc = udbg_putcLP;
|
||||
udbg_getc = udbg_getcLP;
|
||||
udbg_getc_poll = udbg_getc_pollLP;
|
||||
|
||||
register_early_udbg_console();
|
||||
}
|
||||
|
||||
/* returns 0 if couldn't find or use /chosen/stdout as console */
|
||||
@ -288,15 +286,15 @@ static long pSeries_lpar_hpte_insert(unsigned long hpte_group,
|
||||
unsigned long hpte_v, hpte_r;
|
||||
|
||||
if (!(vflags & HPTE_V_BOLTED))
|
||||
DBG_LOW("hpte_insert(group=%lx, va=%016lx, pa=%016lx, "
|
||||
"rflags=%lx, vflags=%lx, psize=%d)\n",
|
||||
hpte_group, va, pa, rflags, vflags, psize);
|
||||
pr_debug("hpte_insert(group=%lx, va=%016lx, pa=%016lx, "
|
||||
"rflags=%lx, vflags=%lx, psize=%d)\n",
|
||||
hpte_group, va, pa, rflags, vflags, psize);
|
||||
|
||||
hpte_v = hpte_encode_v(va, psize, ssize) | vflags | HPTE_V_VALID;
|
||||
hpte_r = hpte_encode_r(pa, psize) | rflags;
|
||||
|
||||
if (!(vflags & HPTE_V_BOLTED))
|
||||
DBG_LOW(" hpte_v=%016lx, hpte_r=%016lx\n", hpte_v, hpte_r);
|
||||
pr_debug(" hpte_v=%016lx, hpte_r=%016lx\n", hpte_v, hpte_r);
|
||||
|
||||
/* Now fill in the actual HPTE */
|
||||
/* Set CEC cookie to 0 */
|
||||
@ -313,7 +311,7 @@ static long pSeries_lpar_hpte_insert(unsigned long hpte_group,
|
||||
lpar_rc = plpar_pte_enter(flags, hpte_group, hpte_v, hpte_r, &slot);
|
||||
if (unlikely(lpar_rc == H_PTEG_FULL)) {
|
||||
if (!(vflags & HPTE_V_BOLTED))
|
||||
DBG_LOW(" full\n");
|
||||
pr_debug(" full\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -324,11 +322,11 @@ static long pSeries_lpar_hpte_insert(unsigned long hpte_group,
|
||||
*/
|
||||
if (unlikely(lpar_rc != H_SUCCESS)) {
|
||||
if (!(vflags & HPTE_V_BOLTED))
|
||||
DBG_LOW(" lpar err %d\n", lpar_rc);
|
||||
pr_debug(" lpar err %lu\n", lpar_rc);
|
||||
return -2;
|
||||
}
|
||||
if (!(vflags & HPTE_V_BOLTED))
|
||||
DBG_LOW(" -> slot: %d\n", slot & 7);
|
||||
pr_debug(" -> slot: %lu\n", slot & 7);
|
||||
|
||||
/* Because of iSeries, we have to pass down the secondary
|
||||
* bucket bit here as well
|
||||
@ -420,17 +418,17 @@ static long pSeries_lpar_hpte_updatepp(unsigned long slot,
|
||||
|
||||
want_v = hpte_encode_avpn(va, psize, ssize);
|
||||
|
||||
DBG_LOW(" update: avpnv=%016lx, hash=%016lx, f=%x, psize: %d ... ",
|
||||
want_v, slot, flags, psize);
|
||||
pr_debug(" update: avpnv=%016lx, hash=%016lx, f=%lx, psize: %d ...",
|
||||
want_v, slot, flags, psize);
|
||||
|
||||
lpar_rc = plpar_pte_protect(flags, slot, want_v);
|
||||
|
||||
if (lpar_rc == H_NOT_FOUND) {
|
||||
DBG_LOW("not found !\n");
|
||||
pr_debug("not found !\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
DBG_LOW("ok\n");
|
||||
pr_debug("ok\n");
|
||||
|
||||
BUG_ON(lpar_rc != H_SUCCESS);
|
||||
|
||||
@ -505,8 +503,8 @@ static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
|
||||
unsigned long lpar_rc;
|
||||
unsigned long dummy1, dummy2;
|
||||
|
||||
DBG_LOW(" inval : slot=%lx, va=%016lx, psize: %d, local: %d",
|
||||
slot, va, psize, local);
|
||||
pr_debug(" inval : slot=%lx, va=%016lx, psize: %d, local: %d\n",
|
||||
slot, va, psize, local);
|
||||
|
||||
want_v = hpte_encode_avpn(va, psize, ssize);
|
||||
lpar_rc = plpar_pte_remove(H_AVPN, slot, want_v, &dummy1, &dummy2);
|
||||
|
@ -67,8 +67,6 @@ static int ras_check_exception_token;
|
||||
static irqreturn_t ras_epow_interrupt(int irq, void *dev_id);
|
||||
static irqreturn_t ras_error_interrupt(int irq, void *dev_id);
|
||||
|
||||
/* #define DEBUG */
|
||||
|
||||
|
||||
static void request_ras_irqs(struct device_node *np,
|
||||
irq_handler_t handler,
|
||||
@ -237,7 +235,7 @@ static irqreturn_t ras_error_interrupt(int irq, void *dev_id)
|
||||
printk(KERN_EMERG "Error: Fatal hardware error <0x%lx 0x%x>\n",
|
||||
*((unsigned long *)&ras_log_buf), status);
|
||||
|
||||
#ifndef DEBUG
|
||||
#ifndef DEBUG_RTAS_POWER_OFF
|
||||
/* Don't actually power off when debugging so we can test
|
||||
* without actually failing while injecting errors.
|
||||
* Error data will not be logged to syslog.
|
||||
|
@ -29,11 +29,6 @@
|
||||
#include <asm/atomic.h>
|
||||
#include <asm/machdep.h>
|
||||
|
||||
#if 0
|
||||
#define DEBUG(A...) printk(KERN_ERR A)
|
||||
#else
|
||||
#define DEBUG(A...)
|
||||
#endif
|
||||
|
||||
static DEFINE_SPINLOCK(rtasd_log_lock);
|
||||
|
||||
@ -198,7 +193,7 @@ void pSeries_log_error(char *buf, unsigned int err_type, int fatal)
|
||||
unsigned long s;
|
||||
int len = 0;
|
||||
|
||||
DEBUG("logging event\n");
|
||||
pr_debug("rtasd: logging event\n");
|
||||
if (buf == NULL)
|
||||
return;
|
||||
|
||||
@ -409,7 +404,8 @@ static int rtasd(void *unused)
|
||||
daemonize("rtasd");
|
||||
|
||||
printk(KERN_DEBUG "RTAS daemon started\n");
|
||||
DEBUG("will sleep for %d milliseconds\n", (30000/rtas_event_scan_rate));
|
||||
pr_debug("rtasd: will sleep for %d milliseconds\n",
|
||||
(30000 / rtas_event_scan_rate));
|
||||
|
||||
/* See if we have any error stored in NVRAM */
|
||||
memset(logdata, 0, rtas_error_log_max);
|
||||
@ -428,9 +424,9 @@ static int rtasd(void *unused)
|
||||
do_event_scan_all_cpus(1000);
|
||||
|
||||
if (surveillance_timeout != -1) {
|
||||
DEBUG("enabling surveillance\n");
|
||||
pr_debug("rtasd: enabling surveillance\n");
|
||||
enable_surveillance(surveillance_timeout);
|
||||
DEBUG("surveillance enabled\n");
|
||||
pr_debug("rtasd: surveillance enabled\n");
|
||||
}
|
||||
|
||||
/* Delay should be at least one second since some
|
||||
|
@ -38,9 +38,7 @@
|
||||
#define SCANLOG_HWERROR -1
|
||||
#define SCANLOG_CONTINUE 1
|
||||
|
||||
#define DEBUG(A...) do { if (scanlog_debug) printk(KERN_ERR "scanlog: " A); } while (0)
|
||||
|
||||
static int scanlog_debug;
|
||||
static unsigned int ibm_scan_log_dump; /* RTAS token */
|
||||
static struct proc_dir_entry *proc_ppc64_scan_log_dump; /* The proc file */
|
||||
|
||||
@ -86,14 +84,14 @@ static ssize_t scanlog_read(struct file *file, char __user *buf,
|
||||
memcpy(data, rtas_data_buf, RTAS_DATA_BUF_SIZE);
|
||||
spin_unlock(&rtas_data_buf_lock);
|
||||
|
||||
DEBUG("status=%d, data[0]=%x, data[1]=%x, data[2]=%x\n",
|
||||
status, data[0], data[1], data[2]);
|
||||
pr_debug("scanlog: status=%d, data[0]=%x, data[1]=%x, " \
|
||||
"data[2]=%x\n", status, data[0], data[1], data[2]);
|
||||
switch (status) {
|
||||
case SCANLOG_COMPLETE:
|
||||
DEBUG("hit eof\n");
|
||||
pr_debug("scanlog: hit eof\n");
|
||||
return 0;
|
||||
case SCANLOG_HWERROR:
|
||||
DEBUG("hardware error reading scan log data\n");
|
||||
pr_debug("scanlog: hardware error reading data\n");
|
||||
return -EIO;
|
||||
case SCANLOG_CONTINUE:
|
||||
/* We may or may not have data yet */
|
||||
@ -110,7 +108,8 @@ static ssize_t scanlog_read(struct file *file, char __user *buf,
|
||||
/* Assume extended busy */
|
||||
wait_time = rtas_busy_delay_time(status);
|
||||
if (!wait_time) {
|
||||
printk(KERN_ERR "scanlog: unknown error from rtas: %d\n", status);
|
||||
printk(KERN_ERR "scanlog: unknown error " \
|
||||
"from rtas: %d\n", status);
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
@ -134,15 +133,9 @@ static ssize_t scanlog_write(struct file * file, const char __user * buf,
|
||||
|
||||
if (buf) {
|
||||
if (strncmp(stkbuf, "reset", 5) == 0) {
|
||||
DEBUG("reset scanlog\n");
|
||||
pr_debug("scanlog: reset scanlog\n");
|
||||
status = rtas_call(ibm_scan_log_dump, 2, 1, NULL, 0, 0);
|
||||
DEBUG("rtas returns %d\n", status);
|
||||
} else if (strncmp(stkbuf, "debugon", 7) == 0) {
|
||||
printk(KERN_ERR "scanlog: debug on\n");
|
||||
scanlog_debug = 1;
|
||||
} else if (strncmp(stkbuf, "debugoff", 8) == 0) {
|
||||
printk(KERN_ERR "scanlog: debug off\n");
|
||||
scanlog_debug = 0;
|
||||
pr_debug("scanlog: rtas returns %d\n", status);
|
||||
}
|
||||
}
|
||||
return count;
|
||||
|
@ -16,8 +16,6 @@
|
||||
* bootup setup stuff..
|
||||
*/
|
||||
|
||||
#undef DEBUG
|
||||
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/sched.h>
|
||||
@ -70,11 +68,6 @@
|
||||
#include "plpar_wrappers.h"
|
||||
#include "pseries.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DBG(fmt...) udbg_printf(fmt)
|
||||
#else
|
||||
#define DBG(fmt...)
|
||||
#endif
|
||||
|
||||
int fwnmi_active; /* TRUE if an FWNMI handler is present */
|
||||
|
||||
@ -326,7 +319,7 @@ static int pseries_set_xdabr(unsigned long dabr)
|
||||
*/
|
||||
static void __init pSeries_init_early(void)
|
||||
{
|
||||
DBG(" -> pSeries_init_early()\n");
|
||||
pr_debug(" -> pSeries_init_early()\n");
|
||||
|
||||
if (firmware_has_feature(FW_FEATURE_LPAR))
|
||||
find_udbg_vterm();
|
||||
@ -338,7 +331,7 @@ static void __init pSeries_init_early(void)
|
||||
|
||||
iommu_init_early_pSeries();
|
||||
|
||||
DBG(" <- pSeries_init_early()\n");
|
||||
pr_debug(" <- pSeries_init_early()\n");
|
||||
}
|
||||
|
||||
/*
|
||||
@ -383,7 +376,7 @@ static int __init pSeries_probe(void)
|
||||
of_flat_dt_is_compatible(root, "IBM,CBEA"))
|
||||
return 0;
|
||||
|
||||
DBG("pSeries detected, looking for LPAR capability...\n");
|
||||
pr_debug("pSeries detected, looking for LPAR capability...\n");
|
||||
|
||||
/* Now try to figure out if we are running on LPAR */
|
||||
of_scan_flat_dt(pSeries_probe_hypertas, NULL);
|
||||
@ -393,8 +386,8 @@ static int __init pSeries_probe(void)
|
||||
else
|
||||
hpte_init_native();
|
||||
|
||||
DBG("Machine is%s LPAR !\n",
|
||||
(powerpc_firmware_features & FW_FEATURE_LPAR) ? "" : " not");
|
||||
pr_debug("Machine is%s LPAR !\n",
|
||||
(powerpc_firmware_features & FW_FEATURE_LPAR) ? "" : " not");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -12,7 +12,6 @@
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#undef DEBUG
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
@ -51,12 +50,6 @@
|
||||
#include "plpar_wrappers.h"
|
||||
#include "pseries.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#include <asm/udbg.h>
|
||||
#define DBG(fmt...) udbg_printf(fmt)
|
||||
#else
|
||||
#define DBG(fmt...)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The primary thread of each non-boot processor is recorded here before
|
||||
@ -231,7 +224,7 @@ static void __init smp_init_pseries(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
DBG(" -> smp_init_pSeries()\n");
|
||||
pr_debug(" -> smp_init_pSeries()\n");
|
||||
|
||||
/* Mark threads which are still spinning in hold loops. */
|
||||
if (cpu_has_feature(CPU_FTR_SMT)) {
|
||||
@ -255,7 +248,7 @@ static void __init smp_init_pseries(void)
|
||||
smp_ops->take_timebase = pSeries_take_timebase;
|
||||
}
|
||||
|
||||
DBG(" <- smp_init_pSeries()\n");
|
||||
pr_debug(" <- smp_init_pSeries()\n");
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MPIC
|
||||
|
@ -9,7 +9,6 @@
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#undef DEBUG
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/threads.h>
|
||||
|
@ -338,15 +338,13 @@ static int __init mv64x60_i2c_device_setup(struct device_node *np, int id)
|
||||
|
||||
pdata.freq_m = 8; /* default */
|
||||
prop = of_get_property(np, "freq_m", NULL);
|
||||
if (!prop)
|
||||
return -ENODEV;
|
||||
pdata.freq_m = *prop;
|
||||
if (prop)
|
||||
pdata.freq_m = *prop;
|
||||
|
||||
pdata.freq_m = 3; /* default */
|
||||
prop = of_get_property(np, "freq_n", NULL);
|
||||
if (!prop)
|
||||
return -ENODEV;
|
||||
pdata.freq_n = *prop;
|
||||
if (prop)
|
||||
pdata.freq_n = *prop;
|
||||
|
||||
pdata.timeout = 1000; /* default: 1 second */
|
||||
|
||||
@ -433,9 +431,13 @@ static int __init mv64x60_device_setup(void)
|
||||
int err;
|
||||
|
||||
id = 0;
|
||||
for_each_compatible_node(np, "serial", "marvell,mv64360-mpsc")
|
||||
if ((err = mv64x60_mpsc_device_setup(np, id++)))
|
||||
goto error;
|
||||
for_each_compatible_node(np, "serial", "marvell,mv64360-mpsc") {
|
||||
err = mv64x60_mpsc_device_setup(np, id++);
|
||||
if (err)
|
||||
printk(KERN_ERR "Failed to initialize MV64x60 "
|
||||
"serial device %s: error %d.\n",
|
||||
np->full_name, err);
|
||||
}
|
||||
|
||||
id = 0;
|
||||
id2 = 0;
|
||||
@ -443,38 +445,44 @@ static int __init mv64x60_device_setup(void)
|
||||
pdev = mv64x60_eth_register_shared_pdev(np, id++);
|
||||
if (IS_ERR(pdev)) {
|
||||
err = PTR_ERR(pdev);
|
||||
goto error;
|
||||
printk(KERN_ERR "Failed to initialize MV64x60 "
|
||||
"network block %s: error %d.\n",
|
||||
np->full_name, err);
|
||||
continue;
|
||||
}
|
||||
for_each_child_of_node(np, np2) {
|
||||
if (!of_device_is_compatible(np2,
|
||||
"marvell,mv64360-eth"))
|
||||
continue;
|
||||
err = mv64x60_eth_device_setup(np2, id2++, pdev);
|
||||
if (err) {
|
||||
of_node_put(np2);
|
||||
goto error;
|
||||
}
|
||||
if (err)
|
||||
printk(KERN_ERR "Failed to initialize "
|
||||
"MV64x60 network device %s: "
|
||||
"error %d.\n",
|
||||
np2->full_name, err);
|
||||
}
|
||||
}
|
||||
|
||||
id = 0;
|
||||
for_each_compatible_node(np, "i2c", "marvell,mv64360-i2c")
|
||||
if ((err = mv64x60_i2c_device_setup(np, id++)))
|
||||
goto error;
|
||||
for_each_compatible_node(np, "i2c", "marvell,mv64360-i2c") {
|
||||
err = mv64x60_i2c_device_setup(np, id++);
|
||||
if (err)
|
||||
printk(KERN_ERR "Failed to initialize MV64x60 I2C "
|
||||
"bus %s: error %d.\n",
|
||||
np->full_name, err);
|
||||
}
|
||||
|
||||
/* support up to one watchdog timer */
|
||||
np = of_find_compatible_node(np, NULL, "marvell,mv64360-wdt");
|
||||
if (np) {
|
||||
if ((err = mv64x60_wdt_device_setup(np, id)))
|
||||
goto error;
|
||||
printk(KERN_ERR "Failed to initialize MV64x60 "
|
||||
"Watchdog %s: error %d.\n",
|
||||
np->full_name, err);
|
||||
of_node_put(np);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
of_node_put(np);
|
||||
return err;
|
||||
}
|
||||
arch_initcall(mv64x60_device_setup);
|
||||
|
||||
|
@ -94,7 +94,7 @@ static void mv64x60_udbg_init(void)
|
||||
if (!np)
|
||||
return;
|
||||
|
||||
block_index = of_get_property(np, "block-index", NULL);
|
||||
block_index = of_get_property(np, "cell-index", NULL);
|
||||
if (!block_index)
|
||||
goto error;
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user