Merge branch 'linus'
Conflicts: drivers/scsi/ipr.c Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
This commit is contained in:
commit
81b7bbd193
2025 changed files with 128405 additions and 54039 deletions
|
@ -30,6 +30,7 @@ are not a good substitute for a solid C education and/or years of
|
||||||
experience, the following books are good for, if anything, reference:
|
experience, the following books are good for, if anything, reference:
|
||||||
- "The C Programming Language" by Kernighan and Ritchie [Prentice Hall]
|
- "The C Programming Language" by Kernighan and Ritchie [Prentice Hall]
|
||||||
- "Practical C Programming" by Steve Oualline [O'Reilly]
|
- "Practical C Programming" by Steve Oualline [O'Reilly]
|
||||||
|
- "C: A Reference Manual" by Harbison and Steele [Prentice Hall]
|
||||||
|
|
||||||
The kernel is written using GNU C and the GNU toolchain. While it
|
The kernel is written using GNU C and the GNU toolchain. While it
|
||||||
adheres to the ISO C89 standard, it uses a number of extensions that are
|
adheres to the ISO C89 standard, it uses a number of extensions that are
|
||||||
|
|
|
@ -193,6 +193,7 @@ Original developers of the crypto algorithms:
|
||||||
Kartikey Mahendra Bhatt (CAST6)
|
Kartikey Mahendra Bhatt (CAST6)
|
||||||
Jon Oberheide (ARC4)
|
Jon Oberheide (ARC4)
|
||||||
Jouni Malinen (Michael MIC)
|
Jouni Malinen (Michael MIC)
|
||||||
|
NTT(Nippon Telegraph and Telephone Corporation) (Camellia)
|
||||||
|
|
||||||
SHA1 algorithm contributors:
|
SHA1 algorithm contributors:
|
||||||
Jean-Francois Dive
|
Jean-Francois Dive
|
||||||
|
@ -246,6 +247,9 @@ Tiger algorithm contributors:
|
||||||
VIA PadLock contributors:
|
VIA PadLock contributors:
|
||||||
Michal Ludvig
|
Michal Ludvig
|
||||||
|
|
||||||
|
Camellia algorithm contributors:
|
||||||
|
NTT(Nippon Telegraph and Telephone Corporation) (Camellia)
|
||||||
|
|
||||||
Generic scatterwalk code by Adam J. Richter <adam@yggdrasil.com>
|
Generic scatterwalk code by Adam J. Richter <adam@yggdrasil.com>
|
||||||
|
|
||||||
Please send any credits updates or corrections to:
|
Please send any credits updates or corrections to:
|
||||||
|
|
268
Documentation/driver-model/devres.txt
Normal file
268
Documentation/driver-model/devres.txt
Normal file
|
@ -0,0 +1,268 @@
|
||||||
|
Devres - Managed Device Resource
|
||||||
|
================================
|
||||||
|
|
||||||
|
Tejun Heo <teheo@suse.de>
|
||||||
|
|
||||||
|
First draft 10 January 2007
|
||||||
|
|
||||||
|
|
||||||
|
1. Intro : Huh? Devres?
|
||||||
|
2. Devres : Devres in a nutshell
|
||||||
|
3. Devres Group : Group devres'es and release them together
|
||||||
|
4. Details : Life time rules, calling context, ...
|
||||||
|
5. Overhead : How much do we have to pay for this?
|
||||||
|
6. List of managed interfaces : Currently implemented managed interfaces
|
||||||
|
|
||||||
|
|
||||||
|
1. Intro
|
||||||
|
--------
|
||||||
|
|
||||||
|
devres came up while trying to convert libata to use iomap. Each
|
||||||
|
iomapped address should be kept and unmapped on driver detach. For
|
||||||
|
example, a plain SFF ATA controller (that is, good old PCI IDE) in
|
||||||
|
native mode makes use of 5 PCI BARs and all of them should be
|
||||||
|
maintained.
|
||||||
|
|
||||||
|
As with many other device drivers, libata low level drivers have
|
||||||
|
sufficient bugs in ->remove and ->probe failure path. Well, yes,
|
||||||
|
that's probably because libata low level driver developers are lazy
|
||||||
|
bunch, but aren't all low level driver developers? After spending a
|
||||||
|
day fiddling with braindamaged hardware with no document or
|
||||||
|
braindamaged document, if it's finally working, well, it's working.
|
||||||
|
|
||||||
|
For one reason or another, low level drivers don't receive as much
|
||||||
|
attention or testing as core code, and bugs on driver detach or
|
||||||
|
initilaization failure doesn't happen often enough to be noticeable.
|
||||||
|
Init failure path is worse because it's much less travelled while
|
||||||
|
needs to handle multiple entry points.
|
||||||
|
|
||||||
|
So, many low level drivers end up leaking resources on driver detach
|
||||||
|
and having half broken failure path implementation in ->probe() which
|
||||||
|
would leak resources or even cause oops when failure occurs. iomap
|
||||||
|
adds more to this mix. So do msi and msix.
|
||||||
|
|
||||||
|
|
||||||
|
2. Devres
|
||||||
|
---------
|
||||||
|
|
||||||
|
devres is basically linked list of arbitrarily sized memory areas
|
||||||
|
associated with a struct device. Each devres entry is associated with
|
||||||
|
a release function. A devres can be released in several ways. No
|
||||||
|
matter what, all devres entries are released on driver detach. On
|
||||||
|
release, the associated release function is invoked and then the
|
||||||
|
devres entry is freed.
|
||||||
|
|
||||||
|
Managed interface is created for resources commonly used by device
|
||||||
|
drivers using devres. For example, coherent DMA memory is acquired
|
||||||
|
using dma_alloc_coherent(). The managed version is called
|
||||||
|
dmam_alloc_coherent(). It is identical to dma_alloc_coherent() except
|
||||||
|
for the DMA memory allocated using it is managed and will be
|
||||||
|
automatically released on driver detach. Implementation looks like
|
||||||
|
the following.
|
||||||
|
|
||||||
|
struct dma_devres {
|
||||||
|
size_t size;
|
||||||
|
void *vaddr;
|
||||||
|
dma_addr_t dma_handle;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void dmam_coherent_release(struct device *dev, void *res)
|
||||||
|
{
|
||||||
|
struct dma_devres *this = res;
|
||||||
|
|
||||||
|
dma_free_coherent(dev, this->size, this->vaddr, this->dma_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
dmam_alloc_coherent(dev, size, dma_handle, gfp)
|
||||||
|
{
|
||||||
|
struct dma_devres *dr;
|
||||||
|
void *vaddr;
|
||||||
|
|
||||||
|
dr = devres_alloc(dmam_coherent_release, sizeof(*dr), gfp);
|
||||||
|
...
|
||||||
|
|
||||||
|
/* alloc DMA memory as usual */
|
||||||
|
vaddr = dma_alloc_coherent(...);
|
||||||
|
...
|
||||||
|
|
||||||
|
/* record size, vaddr, dma_handle in dr */
|
||||||
|
dr->vaddr = vaddr;
|
||||||
|
...
|
||||||
|
|
||||||
|
devres_add(dev, dr);
|
||||||
|
|
||||||
|
return vaddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
If a driver uses dmam_alloc_coherent(), the area is guaranteed to be
|
||||||
|
freed whether initialization fails half-way or the device gets
|
||||||
|
detached. If most resources are acquired using managed interface, a
|
||||||
|
driver can have much simpler init and exit code. Init path basically
|
||||||
|
looks like the following.
|
||||||
|
|
||||||
|
my_init_one()
|
||||||
|
{
|
||||||
|
struct mydev *d;
|
||||||
|
|
||||||
|
d = devm_kzalloc(dev, sizeof(*d), GFP_KERNEL);
|
||||||
|
if (!d)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
d->ring = dmam_alloc_coherent(...);
|
||||||
|
if (!d->ring)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
if (check something)
|
||||||
|
return -EINVAL;
|
||||||
|
...
|
||||||
|
|
||||||
|
return register_to_upper_layer(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
And exit path,
|
||||||
|
|
||||||
|
my_remove_one()
|
||||||
|
{
|
||||||
|
unregister_from_upper_layer(d);
|
||||||
|
shutdown_my_hardware();
|
||||||
|
}
|
||||||
|
|
||||||
|
As shown above, low level drivers can be simplified a lot by using
|
||||||
|
devres. Complexity is shifted from less maintained low level drivers
|
||||||
|
to better maintained higher layer. Also, as init failure path is
|
||||||
|
shared with exit path, both can get more testing.
|
||||||
|
|
||||||
|
|
||||||
|
3. Devres group
|
||||||
|
---------------
|
||||||
|
|
||||||
|
Devres entries can be grouped using devres group. When a group is
|
||||||
|
released, all contained normal devres entries and properly nested
|
||||||
|
groups are released. One usage is to rollback series of acquired
|
||||||
|
resources on failure. For example,
|
||||||
|
|
||||||
|
if (!devres_open_group(dev, NULL, GFP_KERNEL))
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
acquire A;
|
||||||
|
if (failed)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
acquire B;
|
||||||
|
if (failed)
|
||||||
|
goto err;
|
||||||
|
...
|
||||||
|
|
||||||
|
devres_remove_group(dev, NULL);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err:
|
||||||
|
devres_release_group(dev, NULL);
|
||||||
|
return err_code;
|
||||||
|
|
||||||
|
As resource acquision failure usually means probe failure, constructs
|
||||||
|
like above are usually useful in midlayer driver (e.g. libata core
|
||||||
|
layer) where interface function shouldn't have side effect on failure.
|
||||||
|
For LLDs, just returning error code suffices in most cases.
|
||||||
|
|
||||||
|
Each group is identified by void *id. It can either be explicitly
|
||||||
|
specified by @id argument to devres_open_group() or automatically
|
||||||
|
created by passing NULL as @id as in the above example. In both
|
||||||
|
cases, devres_open_group() returns the group's id. The returned id
|
||||||
|
can be passed to other devres functions to select the target group.
|
||||||
|
If NULL is given to those functions, the latest open group is
|
||||||
|
selected.
|
||||||
|
|
||||||
|
For example, you can do something like the following.
|
||||||
|
|
||||||
|
int my_midlayer_create_something()
|
||||||
|
{
|
||||||
|
if (!devres_open_group(dev, my_midlayer_create_something, GFP_KERNEL))
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
devres_close_group(dev, my_midlayer_something);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void my_midlayer_destroy_something()
|
||||||
|
{
|
||||||
|
devres_release_group(dev, my_midlayer_create_soemthing);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
4. Details
|
||||||
|
----------
|
||||||
|
|
||||||
|
Lifetime of a devres entry begins on devres allocation and finishes
|
||||||
|
when it is released or destroyed (removed and freed) - no reference
|
||||||
|
counting.
|
||||||
|
|
||||||
|
devres core guarantees atomicity to all basic devres operations and
|
||||||
|
has support for single-instance devres types (atomic
|
||||||
|
lookup-and-add-if-not-found). Other than that, synchronizing
|
||||||
|
concurrent accesses to allocated devres data is caller's
|
||||||
|
responsibility. This is usually non-issue because bus ops and
|
||||||
|
resource allocations already do the job.
|
||||||
|
|
||||||
|
For an example of single-instance devres type, read pcim_iomap_table()
|
||||||
|
in lib/iomap.c.
|
||||||
|
|
||||||
|
All devres interface functions can be called without context if the
|
||||||
|
right gfp mask is given.
|
||||||
|
|
||||||
|
|
||||||
|
5. Overhead
|
||||||
|
-----------
|
||||||
|
|
||||||
|
Each devres bookkeeping info is allocated together with requested data
|
||||||
|
area. With debug option turned off, bookkeeping info occupies 16
|
||||||
|
bytes on 32bit machines and 24 bytes on 64bit (three pointers rounded
|
||||||
|
up to ull alignment). If singly linked list is used, it can be
|
||||||
|
reduced to two pointers (8 bytes on 32bit, 16 bytes on 64bit).
|
||||||
|
|
||||||
|
Each devres group occupies 8 pointers. It can be reduced to 6 if
|
||||||
|
singly linked list is used.
|
||||||
|
|
||||||
|
Memory space overhead on ahci controller with two ports is between 300
|
||||||
|
and 400 bytes on 32bit machine after naive conversion (we can
|
||||||
|
certainly invest a bit more effort into libata core layer).
|
||||||
|
|
||||||
|
|
||||||
|
6. List of managed interfaces
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
IO region
|
||||||
|
devm_request_region()
|
||||||
|
devm_request_mem_region()
|
||||||
|
devm_release_region()
|
||||||
|
devm_release_mem_region()
|
||||||
|
|
||||||
|
IRQ
|
||||||
|
devm_request_irq()
|
||||||
|
devm_free_irq()
|
||||||
|
|
||||||
|
DMA
|
||||||
|
dmam_alloc_coherent()
|
||||||
|
dmam_free_coherent()
|
||||||
|
dmam_alloc_noncoherent()
|
||||||
|
dmam_free_noncoherent()
|
||||||
|
dmam_declare_coherent_memory()
|
||||||
|
dmam_pool_create()
|
||||||
|
dmam_pool_destroy()
|
||||||
|
|
||||||
|
PCI
|
||||||
|
pcim_enable_device() : after success, all PCI ops become managed
|
||||||
|
pcim_pin_device() : keep PCI device enabled after release
|
||||||
|
|
||||||
|
IOMAP
|
||||||
|
devm_ioport_map()
|
||||||
|
devm_ioport_unmap()
|
||||||
|
devm_ioremap()
|
||||||
|
devm_ioremap_nocache()
|
||||||
|
devm_iounmap()
|
||||||
|
pcim_iomap()
|
||||||
|
pcim_iounmap()
|
||||||
|
pcim_iomap_table() : array of mapped addresses indexed by BAR
|
||||||
|
pcim_iomap_regions() : do request_region() and iomap() on multiple BARs
|
|
@ -50,22 +50,6 @@ Who: Dan Dennedy <dan@dennedy.org>, Stefan Richter <stefanr@s5r6.in-berlin.de>
|
||||||
|
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
What: ieee1394 core's unused exports (CONFIG_IEEE1394_EXPORT_FULL_API)
|
|
||||||
When: January 2007
|
|
||||||
Why: There are no projects known to use these exported symbols, except
|
|
||||||
dfg1394 (uses one symbol whose functionality is core-internal now).
|
|
||||||
Who: Stefan Richter <stefanr@s5r6.in-berlin.de>
|
|
||||||
|
|
||||||
---------------------------
|
|
||||||
|
|
||||||
What: ieee1394's *_oui sysfs attributes (CONFIG_IEEE1394_OUI_DB)
|
|
||||||
When: January 2007
|
|
||||||
Files: drivers/ieee1394/: oui.db, oui2c.sh
|
|
||||||
Why: big size, little value
|
|
||||||
Who: Stefan Richter <stefanr@s5r6.in-berlin.de>
|
|
||||||
|
|
||||||
---------------------------
|
|
||||||
|
|
||||||
What: Video4Linux API 1 ioctls and video_decoder.h from Video devices.
|
What: Video4Linux API 1 ioctls and video_decoder.h from Video devices.
|
||||||
When: December 2006
|
When: December 2006
|
||||||
Why: V4L1 AP1 was replaced by V4L2 API. during migration from 2.4 to 2.6
|
Why: V4L1 AP1 was replaced by V4L2 API. during migration from 2.4 to 2.6
|
||||||
|
@ -186,18 +170,6 @@ Who: Greg Kroah-Hartman <gregkh@suse.de>
|
||||||
|
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
What: find_trylock_page
|
|
||||||
When: January 2007
|
|
||||||
Why: The interface no longer has any callers left in the kernel. It
|
|
||||||
is an odd interface (compared with other find_*_page functions), in
|
|
||||||
that it does not take a refcount to the page, only the page lock.
|
|
||||||
It should be replaced with find_get_page or find_lock_page if possible.
|
|
||||||
This feature removal can be reevaluated if users of the interface
|
|
||||||
cannot cleanly use something else.
|
|
||||||
Who: Nick Piggin <npiggin@suse.de>
|
|
||||||
|
|
||||||
---------------------------
|
|
||||||
|
|
||||||
What: Interrupt only SA_* flags
|
What: Interrupt only SA_* flags
|
||||||
When: Januar 2007
|
When: Januar 2007
|
||||||
Why: The interrupt related SA_* flags are replaced by IRQF_* to move them
|
Why: The interrupt related SA_* flags are replaced by IRQF_* to move them
|
||||||
|
@ -274,6 +246,7 @@ Who: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
|
||||||
|
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
|
<<<<<<< test:Documentation/feature-removal-schedule.txt
|
||||||
What: ACPI hotkey driver (CONFIG_ACPI_HOTKEY)
|
What: ACPI hotkey driver (CONFIG_ACPI_HOTKEY)
|
||||||
When: 2.6.21
|
When: 2.6.21
|
||||||
Why: hotkey.c was an attempt to consolidate multiple drivers that use
|
Why: hotkey.c was an attempt to consolidate multiple drivers that use
|
||||||
|
@ -306,11 +279,18 @@ Why: The ACPI namespace is effectively the symbol list for
|
||||||
the BIOS can be extracted and disassembled with acpidump
|
the BIOS can be extracted and disassembled with acpidump
|
||||||
and iasl as documented in the pmtools package here:
|
and iasl as documented in the pmtools package here:
|
||||||
http://ftp.kernel.org/pub/linux/kernel/people/lenb/acpi/utils
|
http://ftp.kernel.org/pub/linux/kernel/people/lenb/acpi/utils
|
||||||
|
|
||||||
Who: Len Brown <len.brown@intel.com>
|
Who: Len Brown <len.brown@intel.com>
|
||||||
|
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
|
What: ACPI procfs interface
|
||||||
|
When: July 2007
|
||||||
|
Why: After ACPI sysfs conversion, ACPI attributes will be duplicated
|
||||||
|
in sysfs and the ACPI procfs interface should be removed.
|
||||||
|
Who: Zhang Rui <rui.zhang@intel.com>
|
||||||
|
|
||||||
|
---------------------------
|
||||||
|
|
||||||
What: /proc/acpi/button
|
What: /proc/acpi/button
|
||||||
When: August 2007
|
When: August 2007
|
||||||
Why: /proc/acpi/button has been replaced by events to the input layer
|
Why: /proc/acpi/button has been replaced by events to the input layer
|
||||||
|
@ -325,3 +305,10 @@ Why: Unmaintained for years, superceded by JFFS2 for years.
|
||||||
Who: Jeff Garzik <jeff@garzik.org>
|
Who: Jeff Garzik <jeff@garzik.org>
|
||||||
|
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
|
What: sk98lin network driver
|
||||||
|
When: July 2007
|
||||||
|
Why: In kernel tree version of driver is unmaintained. Sk98lin driver
|
||||||
|
replaced by the skge driver.
|
||||||
|
Who: Stephen Hemminger <shemminger@osdl.org>
|
||||||
|
|
||||||
|
|
|
@ -480,7 +480,7 @@ r2 argument 0 / return value 0 call-clobbered
|
||||||
r3 argument 1 / return value 1 (if long long) call-clobbered
|
r3 argument 1 / return value 1 (if long long) call-clobbered
|
||||||
r4 argument 2 call-clobbered
|
r4 argument 2 call-clobbered
|
||||||
r5 argument 3 call-clobbered
|
r5 argument 3 call-clobbered
|
||||||
r6 argument 5 saved
|
r6 argument 4 saved
|
||||||
r7 pointer-to arguments 5 to ... saved
|
r7 pointer-to arguments 5 to ... saved
|
||||||
r8 this & that saved
|
r8 this & that saved
|
||||||
r9 this & that saved
|
r9 this & that saved
|
||||||
|
|
|
@ -242,6 +242,12 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||||
ac97_clock - AC'97 clock (default = 48000)
|
ac97_clock - AC'97 clock (default = 48000)
|
||||||
ac97_quirk - AC'97 workaround for strange hardware
|
ac97_quirk - AC'97 workaround for strange hardware
|
||||||
See "AC97 Quirk Option" section below.
|
See "AC97 Quirk Option" section below.
|
||||||
|
ac97_codec - Workaround to specify which AC'97 codec
|
||||||
|
instead of probing. If this works for you
|
||||||
|
file a bug with your `lspci -vn` output.
|
||||||
|
-2 -- Force probing.
|
||||||
|
-1 -- Default behavior.
|
||||||
|
0-2 -- Use the specified codec.
|
||||||
spdif_aclink - S/PDIF transfer over AC-link (default = 1)
|
spdif_aclink - S/PDIF transfer over AC-link (default = 1)
|
||||||
|
|
||||||
This module supports one card and autoprobe.
|
This module supports one card and autoprobe.
|
||||||
|
@ -779,6 +785,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||||
asus-dig ASUS with SPDIF out
|
asus-dig ASUS with SPDIF out
|
||||||
asus-dig2 ASUS with SPDIF out (using GPIO2)
|
asus-dig2 ASUS with SPDIF out (using GPIO2)
|
||||||
uniwill 3-jack
|
uniwill 3-jack
|
||||||
|
fujitsu Fujitsu Laptops (Pi1536)
|
||||||
F1734 2-jack
|
F1734 2-jack
|
||||||
lg LG laptop (m1 express dual)
|
lg LG laptop (m1 express dual)
|
||||||
lg-lw LG LW20/LW25 laptop
|
lg-lw LG LW20/LW25 laptop
|
||||||
|
@ -800,14 +807,18 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||||
ALC262
|
ALC262
|
||||||
fujitsu Fujitsu Laptop
|
fujitsu Fujitsu Laptop
|
||||||
hp-bpc HP xw4400/6400/8400/9400 laptops
|
hp-bpc HP xw4400/6400/8400/9400 laptops
|
||||||
|
hp-bpc-d7000 HP BPC D7000
|
||||||
benq Benq ED8
|
benq Benq ED8
|
||||||
|
hippo Hippo (ATI) with jack detection, Sony UX-90s
|
||||||
|
hippo_1 Hippo (Benq) with jack detection
|
||||||
basic fixed pin assignment w/o SPDIF
|
basic fixed pin assignment w/o SPDIF
|
||||||
auto auto-config reading BIOS (default)
|
auto auto-config reading BIOS (default)
|
||||||
|
|
||||||
ALC882/885
|
ALC882/885
|
||||||
3stack-dig 3-jack with SPDIF I/O
|
3stack-dig 3-jack with SPDIF I/O
|
||||||
6stck-dig 6-jack digital with SPDIF I/O
|
6stack-dig 6-jack digital with SPDIF I/O
|
||||||
arima Arima W820Di1
|
arima Arima W820Di1
|
||||||
|
macpro MacPro support
|
||||||
auto auto-config reading BIOS (default)
|
auto auto-config reading BIOS (default)
|
||||||
|
|
||||||
ALC883/888
|
ALC883/888
|
||||||
|
@ -817,6 +828,10 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||||
3stack-6ch-dig 3-jack 6-channel with SPDIF I/O
|
3stack-6ch-dig 3-jack 6-channel with SPDIF I/O
|
||||||
6stack-dig-demo 6-jack digital for Intel demo board
|
6stack-dig-demo 6-jack digital for Intel demo board
|
||||||
acer Acer laptops (Travelmate 3012WTMi, Aspire 5600, etc)
|
acer Acer laptops (Travelmate 3012WTMi, Aspire 5600, etc)
|
||||||
|
medion Medion Laptops
|
||||||
|
targa-dig Targa/MSI
|
||||||
|
targa-2ch-dig Targs/MSI with 2-channel
|
||||||
|
laptop-eapd 3-jack with SPDIF I/O and EAPD (Clevo M540JE, M550JE)
|
||||||
auto auto-config reading BIOS (default)
|
auto auto-config reading BIOS (default)
|
||||||
|
|
||||||
ALC861/660
|
ALC861/660
|
||||||
|
@ -825,6 +840,16 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||||
6stack-dig 6-jack with SPDIF I/O
|
6stack-dig 6-jack with SPDIF I/O
|
||||||
3stack-660 3-jack (for ALC660)
|
3stack-660 3-jack (for ALC660)
|
||||||
uniwill-m31 Uniwill M31 laptop
|
uniwill-m31 Uniwill M31 laptop
|
||||||
|
toshiba Toshiba laptop support
|
||||||
|
asus Asus laptop support
|
||||||
|
asus-laptop ASUS F2/F3 laptops
|
||||||
|
auto auto-config reading BIOS (default)
|
||||||
|
|
||||||
|
ALC861VD/660VD
|
||||||
|
3stack 3-jack
|
||||||
|
3stack-dig 3-jack with SPDIF OUT
|
||||||
|
6stack-dig 6-jack with SPDIF OUT
|
||||||
|
3stack-660 3-jack (for ALC660VD)
|
||||||
auto auto-config reading BIOS (default)
|
auto auto-config reading BIOS (default)
|
||||||
|
|
||||||
CMI9880
|
CMI9880
|
||||||
|
@ -845,6 +870,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||||
3stack 3-stack, shared surrounds
|
3stack 3-stack, shared surrounds
|
||||||
laptop 2-channel only (FSC V2060, Samsung M50)
|
laptop 2-channel only (FSC V2060, Samsung M50)
|
||||||
laptop-eapd 2-channel with EAPD (Samsung R65, ASUS A6J)
|
laptop-eapd 2-channel with EAPD (Samsung R65, ASUS A6J)
|
||||||
|
ultra 2-channel with EAPD (Samsung Ultra tablet PC)
|
||||||
|
|
||||||
AD1988
|
AD1988
|
||||||
6stack 6-jack
|
6stack 6-jack
|
||||||
|
@ -854,12 +880,31 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||||
laptop 3-jack with hp-jack automute
|
laptop 3-jack with hp-jack automute
|
||||||
laptop-dig ditto with SPDIF
|
laptop-dig ditto with SPDIF
|
||||||
auto auto-config reading BIOS (default)
|
auto auto-config reading BIOS (default)
|
||||||
|
|
||||||
|
Conexant 5045
|
||||||
|
laptop Laptop config
|
||||||
|
test for testing/debugging purpose, almost all controls
|
||||||
|
can be adjusted. Appearing only when compiled with
|
||||||
|
$CONFIG_SND_DEBUG=y
|
||||||
|
|
||||||
|
Conexant 5047
|
||||||
|
laptop Basic Laptop config
|
||||||
|
laptop-hp Laptop config for some HP models (subdevice 30A5)
|
||||||
|
laptop-eapd Laptop config with EAPD support
|
||||||
|
test for testing/debugging purpose, almost all controls
|
||||||
|
can be adjusted. Appearing only when compiled with
|
||||||
|
$CONFIG_SND_DEBUG=y
|
||||||
|
|
||||||
STAC9200/9205/9220/9221/9254
|
STAC9200/9205/9220/9221/9254
|
||||||
ref Reference board
|
ref Reference board
|
||||||
3stack D945 3stack
|
3stack D945 3stack
|
||||||
5stack D945 5stack + SPDIF
|
5stack D945 5stack + SPDIF
|
||||||
|
|
||||||
|
STAC9202/9250/9251
|
||||||
|
ref Reference board, base config
|
||||||
|
m2-2 Some Gateway MX series laptops
|
||||||
|
m6 Some Gateway NX series laptops
|
||||||
|
|
||||||
STAC9227/9228/9229/927x
|
STAC9227/9228/9229/927x
|
||||||
ref Reference board
|
ref Reference board
|
||||||
3stack D965 3stack
|
3stack D965 3stack
|
||||||
|
@ -974,6 +1019,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||||
Module for Envy24HT (VT/ICE1724), Envy24PT (VT1720) based PCI sound cards.
|
Module for Envy24HT (VT/ICE1724), Envy24PT (VT1720) based PCI sound cards.
|
||||||
* MidiMan M Audio Revolution 5.1
|
* MidiMan M Audio Revolution 5.1
|
||||||
* MidiMan M Audio Revolution 7.1
|
* MidiMan M Audio Revolution 7.1
|
||||||
|
* MidiMan M Audio Audiophile 192
|
||||||
* AMP Ltd AUDIO2000
|
* AMP Ltd AUDIO2000
|
||||||
* TerraTec Aureon 5.1 Sky
|
* TerraTec Aureon 5.1 Sky
|
||||||
* TerraTec Aureon 7.1 Space
|
* TerraTec Aureon 7.1 Space
|
||||||
|
@ -993,7 +1039,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||||
|
|
||||||
model - Use the given board model, one of the following:
|
model - Use the given board model, one of the following:
|
||||||
revo51, revo71, amp2000, prodigy71, prodigy71lt,
|
revo51, revo71, amp2000, prodigy71, prodigy71lt,
|
||||||
prodigy192, aureon51, aureon71, universe,
|
prodigy192, aureon51, aureon71, universe, ap192,
|
||||||
k8x800, phase22, phase28, ms300, av710
|
k8x800, phase22, phase28, ms300, av710
|
||||||
|
|
||||||
This module supports multiple cards and autoprobe.
|
This module supports multiple cards and autoprobe.
|
||||||
|
@ -1049,6 +1095,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||||
buggy_semaphore - Enable workaround for hardwares with buggy
|
buggy_semaphore - Enable workaround for hardwares with buggy
|
||||||
semaphores (e.g. on some ASUS laptops)
|
semaphores (e.g. on some ASUS laptops)
|
||||||
(default off)
|
(default off)
|
||||||
|
spdif_aclink - Use S/PDIF over AC-link instead of direct connection
|
||||||
|
from the controller chip
|
||||||
|
(0 = off, 1 = on, -1 = default)
|
||||||
|
|
||||||
This module supports one chip and autoprobe.
|
This module supports one chip and autoprobe.
|
||||||
|
|
||||||
|
@ -1371,6 +1420,13 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||||
|
|
||||||
This module supports multiple cards.
|
This module supports multiple cards.
|
||||||
|
|
||||||
|
Module snd-portman2x4
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
Module for Midiman Portman 2x4 parallel port MIDI interface
|
||||||
|
|
||||||
|
This module supports multiple cards.
|
||||||
|
|
||||||
Module snd-powermac (on ppc only)
|
Module snd-powermac (on ppc only)
|
||||||
---------------------------------
|
---------------------------------
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
</bookinfo>
|
</bookinfo>
|
||||||
|
|
||||||
<chapter><title>Management of Cards and Devices</title>
|
<chapter><title>Management of Cards and Devices</title>
|
||||||
<sect1><title>Card Managment</title>
|
<sect1><title>Card Management</title>
|
||||||
!Esound/core/init.c
|
!Esound/core/init.c
|
||||||
</sect1>
|
</sect1>
|
||||||
<sect1><title>Device Components</title>
|
<sect1><title>Device Components</title>
|
||||||
|
@ -59,7 +59,7 @@
|
||||||
<sect1><title>PCM Format Helpers</title>
|
<sect1><title>PCM Format Helpers</title>
|
||||||
!Esound/core/pcm_misc.c
|
!Esound/core/pcm_misc.c
|
||||||
</sect1>
|
</sect1>
|
||||||
<sect1><title>PCM Memory Managment</title>
|
<sect1><title>PCM Memory Management</title>
|
||||||
!Esound/core/pcm_memory.c
|
!Esound/core/pcm_memory.c
|
||||||
</sect1>
|
</sect1>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
|
@ -1360,8 +1360,7 @@
|
||||||
<informalexample>
|
<informalexample>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
<![CDATA[
|
<![CDATA[
|
||||||
static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id,
|
static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id)
|
||||||
struct pt_regs *regs)
|
|
||||||
{
|
{
|
||||||
struct mychip *chip = dev_id;
|
struct mychip *chip = dev_id;
|
||||||
....
|
....
|
||||||
|
@ -2127,7 +2126,7 @@
|
||||||
accessible via <constant>substream->runtime</constant>.
|
accessible via <constant>substream->runtime</constant>.
|
||||||
This runtime pointer holds the various information; it holds
|
This runtime pointer holds the various information; it holds
|
||||||
the copy of hw_params and sw_params configurations, the buffer
|
the copy of hw_params and sw_params configurations, the buffer
|
||||||
pointers, mmap records, spinlocks, etc. Almost everyhing you
|
pointers, mmap records, spinlocks, etc. Almost everything you
|
||||||
need for controlling the PCM can be found there.
|
need for controlling the PCM can be found there.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
@ -2340,7 +2339,7 @@ struct _snd_pcm_runtime {
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
When the PCM substreams can be synchronized (typically,
|
When the PCM substreams can be synchronized (typically,
|
||||||
synchorinized start/stop of a playback and a capture streams),
|
synchronized start/stop of a playback and a capture streams),
|
||||||
you can give <constant>SNDRV_PCM_INFO_SYNC_START</constant>,
|
you can give <constant>SNDRV_PCM_INFO_SYNC_START</constant>,
|
||||||
too. In this case, you'll need to check the linked-list of
|
too. In this case, you'll need to check the linked-list of
|
||||||
PCM substreams in the trigger callback. This will be
|
PCM substreams in the trigger callback. This will be
|
||||||
|
@ -3062,8 +3061,7 @@ struct _snd_pcm_runtime {
|
||||||
<title>Interrupt Handler Case #1</title>
|
<title>Interrupt Handler Case #1</title>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
<![CDATA[
|
<![CDATA[
|
||||||
static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id,
|
static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id)
|
||||||
struct pt_regs *regs)
|
|
||||||
{
|
{
|
||||||
struct mychip *chip = dev_id;
|
struct mychip *chip = dev_id;
|
||||||
spin_lock(&chip->lock);
|
spin_lock(&chip->lock);
|
||||||
|
@ -3106,8 +3104,7 @@ struct _snd_pcm_runtime {
|
||||||
<title>Interrupt Handler Case #2</title>
|
<title>Interrupt Handler Case #2</title>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
<![CDATA[
|
<![CDATA[
|
||||||
static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id,
|
static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id)
|
||||||
struct pt_regs *regs)
|
|
||||||
{
|
{
|
||||||
struct mychip *chip = dev_id;
|
struct mychip *chip = dev_id;
|
||||||
spin_lock(&chip->lock);
|
spin_lock(&chip->lock);
|
||||||
|
@ -3247,7 +3244,7 @@ struct _snd_pcm_runtime {
|
||||||
You can even define your own constraint rules.
|
You can even define your own constraint rules.
|
||||||
For example, let's suppose my_chip can manage a substream of 1 channel
|
For example, let's suppose my_chip can manage a substream of 1 channel
|
||||||
if and only if the format is S16_LE, otherwise it supports any format
|
if and only if the format is S16_LE, otherwise it supports any format
|
||||||
specified in the <structname>snd_pcm_hardware</structname> stucture (or in any
|
specified in the <structname>snd_pcm_hardware</structname> structure (or in any
|
||||||
other constraint_list). You can build a rule like this:
|
other constraint_list). You can build a rule like this:
|
||||||
|
|
||||||
<example>
|
<example>
|
||||||
|
@ -3690,16 +3687,6 @@ struct _snd_pcm_runtime {
|
||||||
</example>
|
</example>
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
|
||||||
Here, the chip instance is retrieved via
|
|
||||||
<function>snd_kcontrol_chip()</function> macro. This macro
|
|
||||||
just accesses to kcontrol->private_data. The
|
|
||||||
kcontrol->private_data field is
|
|
||||||
given as the argument of <function>snd_ctl_new()</function>
|
|
||||||
(see the later subsection
|
|
||||||
<link linkend="control-interface-constructor"><citetitle>Constructor</citetitle></link>).
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The <structfield>value</structfield> field is depending on
|
The <structfield>value</structfield> field is depending on
|
||||||
the type of control as well as on info callback. For example,
|
the type of control as well as on info callback. For example,
|
||||||
|
@ -3780,7 +3767,7 @@ struct _snd_pcm_runtime {
|
||||||
<para>
|
<para>
|
||||||
Like <structfield>get</structfield> callback,
|
Like <structfield>get</structfield> callback,
|
||||||
when the control has more than one elements,
|
when the control has more than one elements,
|
||||||
all elemehts must be evaluated in this callback, too.
|
all elements must be evaluated in this callback, too.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
@ -5541,12 +5528,12 @@ struct _snd_pcm_runtime {
|
||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM
|
||||||
static int snd_my_suspend(struct pci_dev *pci, pm_message_t state)
|
static int snd_my_suspend(struct pci_dev *pci, pm_message_t state)
|
||||||
{
|
{
|
||||||
.... /* do things for suspsend */
|
.... /* do things for suspend */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
static int snd_my_resume(struct pci_dev *pci)
|
static int snd_my_resume(struct pci_dev *pci)
|
||||||
{
|
{
|
||||||
.... /* do things for suspsend */
|
.... /* do things for suspend */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -6111,7 +6098,7 @@ struct _snd_pcm_runtime {
|
||||||
<!-- ****************************************************** -->
|
<!-- ****************************************************** -->
|
||||||
<!-- Acknowledgments -->
|
<!-- Acknowledgments -->
|
||||||
<!-- ****************************************************** -->
|
<!-- ****************************************************** -->
|
||||||
<chapter id="acknowledments">
|
<chapter id="acknowledgments">
|
||||||
<title>Acknowledgments</title>
|
<title>Acknowledgments</title>
|
||||||
<para>
|
<para>
|
||||||
I would like to thank Phil Kerr for his help for improvement and
|
I would like to thank Phil Kerr for his help for improvement and
|
||||||
|
|
|
@ -277,11 +277,11 @@ Helper Functions
|
||||||
snd_hda_get_codec_name() stores the codec name on the given string.
|
snd_hda_get_codec_name() stores the codec name on the given string.
|
||||||
|
|
||||||
snd_hda_check_board_config() can be used to obtain the configuration
|
snd_hda_check_board_config() can be used to obtain the configuration
|
||||||
information matching with the device. Define the table with struct
|
information matching with the device. Define the model string table
|
||||||
hda_board_config entries (zero-terminated), and pass it to the
|
and the table with struct snd_pci_quirk entries (zero-terminated),
|
||||||
function. The function checks the modelname given as a module
|
and pass it to the function. The function checks the modelname given
|
||||||
parameter, and PCI subsystem IDs. If the matching entry is found, it
|
as a module parameter, and PCI subsystem IDs. If the matching entry
|
||||||
returns the config field value.
|
is found, it returns the config field value.
|
||||||
|
|
||||||
snd_hda_add_new_ctls() can be used to create and add control entries.
|
snd_hda_add_new_ctls() can be used to create and add control entries.
|
||||||
Pass the zero-terminated array of struct snd_kcontrol_new. The same array
|
Pass the zero-terminated array of struct snd_kcontrol_new. The same array
|
||||||
|
|
56
Documentation/sound/alsa/soc/DAI.txt
Normal file
56
Documentation/sound/alsa/soc/DAI.txt
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
ASoC currently supports the three main Digital Audio Interfaces (DAI) found on
|
||||||
|
SoC controllers and portable audio CODECS today, namely AC97, I2S and PCM.
|
||||||
|
|
||||||
|
|
||||||
|
AC97
|
||||||
|
====
|
||||||
|
|
||||||
|
AC97 is a five wire interface commonly found on many PC sound cards. It is
|
||||||
|
now also popular in many portable devices. This DAI has a reset line and time
|
||||||
|
multiplexes its data on its SDATA_OUT (playback) and SDATA_IN (capture) lines.
|
||||||
|
The bit clock (BCLK) is always driven by the CODEC (usually 12.288MHz) and the
|
||||||
|
frame (FRAME) (usually 48kHz) is always driven by the controller. Each AC97
|
||||||
|
frame is 21uS long and is divided into 13 time slots.
|
||||||
|
|
||||||
|
The AC97 specification can be found at :-
|
||||||
|
http://www.intel.com/design/chipsets/audio/ac97_r23.pdf
|
||||||
|
|
||||||
|
|
||||||
|
I2S
|
||||||
|
===
|
||||||
|
|
||||||
|
I2S is a common 4 wire DAI used in HiFi, STB and portable devices. The Tx and
|
||||||
|
Rx lines are used for audio transmision, whilst the bit clock (BCLK) and
|
||||||
|
left/right clock (LRC) synchronise the link. I2S is flexible in that either the
|
||||||
|
controller or CODEC can drive (master) the BCLK and LRC clock lines. Bit clock
|
||||||
|
usually varies depending on the sample rate and the master system clock
|
||||||
|
(SYSCLK). LRCLK is the same as the sample rate. A few devices support separate
|
||||||
|
ADC and DAC LRCLK's, this allows for similtanious capture and playback at
|
||||||
|
different sample rates.
|
||||||
|
|
||||||
|
I2S has several different operating modes:-
|
||||||
|
|
||||||
|
o I2S - MSB is transmitted on the falling edge of the first BCLK after LRC
|
||||||
|
transition.
|
||||||
|
|
||||||
|
o Left Justified - MSB is transmitted on transition of LRC.
|
||||||
|
|
||||||
|
o Right Justified - MSB is transmitted sample size BCLK's before LRC
|
||||||
|
transition.
|
||||||
|
|
||||||
|
PCM
|
||||||
|
===
|
||||||
|
|
||||||
|
PCM is another 4 wire interface, very similar to I2S, that can support a more
|
||||||
|
flexible protocol. It has bit clock (BCLK) and sync (SYNC) lines that are used
|
||||||
|
to synchronise the link whilst the Tx and Rx lines are used to transmit and
|
||||||
|
receive the audio data. Bit clock usually varies depending on sample rate
|
||||||
|
whilst sync runs at the sample rate. PCM also supports Time Division
|
||||||
|
Multiplexing (TDM) in that several devices can use the bus similtaniuosly (This
|
||||||
|
is sometimes referred to as network mode).
|
||||||
|
|
||||||
|
Common PCM operating modes:-
|
||||||
|
|
||||||
|
o Mode A - MSB is transmitted on falling edge of first BCLK after FRAME/SYNC.
|
||||||
|
|
||||||
|
o Mode B - MSB is transmitted on rising edge of FRAME/SYNC.
|
51
Documentation/sound/alsa/soc/clocking.txt
Normal file
51
Documentation/sound/alsa/soc/clocking.txt
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
Audio Clocking
|
||||||
|
==============
|
||||||
|
|
||||||
|
This text describes the audio clocking terms in ASoC and digital audio in
|
||||||
|
general. Note: Audio clocking can be complex !
|
||||||
|
|
||||||
|
|
||||||
|
Master Clock
|
||||||
|
------------
|
||||||
|
|
||||||
|
Every audio subsystem is driven by a master clock (sometimes refered to as MCLK
|
||||||
|
or SYSCLK). This audio master clock can be derived from a number of sources
|
||||||
|
(e.g. crystal, PLL, CPU clock) and is responsible for producing the correct
|
||||||
|
audio playback and capture sample rates.
|
||||||
|
|
||||||
|
Some master clocks (e.g. PLL's and CPU based clocks) are configuarble in that
|
||||||
|
their speed can be altered by software (depending on the system use and to save
|
||||||
|
power). Other master clocks are fixed at at set frequency (i.e. crystals).
|
||||||
|
|
||||||
|
|
||||||
|
DAI Clocks
|
||||||
|
----------
|
||||||
|
The Digital Audio Interface is usually driven by a Bit Clock (often referred to
|
||||||
|
as BCLK). This clock is used to drive the digital audio data across the link
|
||||||
|
between the codec and CPU.
|
||||||
|
|
||||||
|
The DAI also has a frame clock to signal the start of each audio frame. This
|
||||||
|
clock is sometimes referred to as LRC (left right clock) or FRAME. This clock
|
||||||
|
runs at exactly the sample rate (LRC = Rate).
|
||||||
|
|
||||||
|
Bit Clock can be generated as follows:-
|
||||||
|
|
||||||
|
BCLK = MCLK / x
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
BCLK = LRC * x
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
BCLK = LRC * Channels * Word Size
|
||||||
|
|
||||||
|
This relationship depends on the codec or SoC CPU in particular. In general
|
||||||
|
it's best to configure BCLK to the lowest possible speed (depending on your
|
||||||
|
rate, number of channels and wordsize) to save on power.
|
||||||
|
|
||||||
|
It's also desireable to use the codec (if possible) to drive (or master) the
|
||||||
|
audio clocks as it's usually gives more accurate sample rates than the CPU.
|
||||||
|
|
||||||
|
|
||||||
|
|
197
Documentation/sound/alsa/soc/codec.txt
Normal file
197
Documentation/sound/alsa/soc/codec.txt
Normal file
|
@ -0,0 +1,197 @@
|
||||||
|
ASoC Codec Driver
|
||||||
|
=================
|
||||||
|
|
||||||
|
The codec driver is generic and hardware independent code that configures the
|
||||||
|
codec to provide audio capture and playback. It should contain no code that is
|
||||||
|
specific to the target platform or machine. All platform and machine specific
|
||||||
|
code should be added to the platform and machine drivers respectively.
|
||||||
|
|
||||||
|
Each codec driver *must* provide the following features:-
|
||||||
|
|
||||||
|
1) Codec DAI and PCM configuration
|
||||||
|
2) Codec control IO - using I2C, 3 Wire(SPI) or both API's
|
||||||
|
3) Mixers and audio controls
|
||||||
|
4) Codec audio operations
|
||||||
|
|
||||||
|
Optionally, codec drivers can also provide:-
|
||||||
|
|
||||||
|
5) DAPM description.
|
||||||
|
6) DAPM event handler.
|
||||||
|
7) DAC Digital mute control.
|
||||||
|
|
||||||
|
It's probably best to use this guide in conjuction with the existing codec
|
||||||
|
driver code in sound/soc/codecs/
|
||||||
|
|
||||||
|
ASoC Codec driver breakdown
|
||||||
|
===========================
|
||||||
|
|
||||||
|
1 - Codec DAI and PCM configuration
|
||||||
|
-----------------------------------
|
||||||
|
Each codec driver must have a struct snd_soc_codec_dai to define it's DAI and
|
||||||
|
PCM's capablities and operations. This struct is exported so that it can be
|
||||||
|
registered with the core by your machine driver.
|
||||||
|
|
||||||
|
e.g.
|
||||||
|
|
||||||
|
struct snd_soc_codec_dai wm8731_dai = {
|
||||||
|
.name = "WM8731",
|
||||||
|
/* playback capabilities */
|
||||||
|
.playback = {
|
||||||
|
.stream_name = "Playback",
|
||||||
|
.channels_min = 1,
|
||||||
|
.channels_max = 2,
|
||||||
|
.rates = WM8731_RATES,
|
||||||
|
.formats = WM8731_FORMATS,},
|
||||||
|
/* capture capabilities */
|
||||||
|
.capture = {
|
||||||
|
.stream_name = "Capture",
|
||||||
|
.channels_min = 1,
|
||||||
|
.channels_max = 2,
|
||||||
|
.rates = WM8731_RATES,
|
||||||
|
.formats = WM8731_FORMATS,},
|
||||||
|
/* pcm operations - see section 4 below */
|
||||||
|
.ops = {
|
||||||
|
.prepare = wm8731_pcm_prepare,
|
||||||
|
.hw_params = wm8731_hw_params,
|
||||||
|
.shutdown = wm8731_shutdown,
|
||||||
|
},
|
||||||
|
/* DAI operations - see DAI.txt */
|
||||||
|
.dai_ops = {
|
||||||
|
.digital_mute = wm8731_mute,
|
||||||
|
.set_sysclk = wm8731_set_dai_sysclk,
|
||||||
|
.set_fmt = wm8731_set_dai_fmt,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
EXPORT_SYMBOL_GPL(wm8731_dai);
|
||||||
|
|
||||||
|
|
||||||
|
2 - Codec control IO
|
||||||
|
--------------------
|
||||||
|
The codec can ususally be controlled via an I2C or SPI style interface (AC97
|
||||||
|
combines control with data in the DAI). The codec drivers will have to provide
|
||||||
|
functions to read and write the codec registers along with supplying a register
|
||||||
|
cache:-
|
||||||
|
|
||||||
|
/* IO control data and register cache */
|
||||||
|
void *control_data; /* codec control (i2c/3wire) data */
|
||||||
|
void *reg_cache;
|
||||||
|
|
||||||
|
Codec read/write should do any data formatting and call the hardware read write
|
||||||
|
below to perform the IO. These functions are called by the core and alsa when
|
||||||
|
performing DAPM or changing the mixer:-
|
||||||
|
|
||||||
|
unsigned int (*read)(struct snd_soc_codec *, unsigned int);
|
||||||
|
int (*write)(struct snd_soc_codec *, unsigned int, unsigned int);
|
||||||
|
|
||||||
|
Codec hardware IO functions - usually points to either the I2C, SPI or AC97
|
||||||
|
read/write:-
|
||||||
|
|
||||||
|
hw_write_t hw_write;
|
||||||
|
hw_read_t hw_read;
|
||||||
|
|
||||||
|
|
||||||
|
3 - Mixers and audio controls
|
||||||
|
-----------------------------
|
||||||
|
All the codec mixers and audio controls can be defined using the convenience
|
||||||
|
macros defined in soc.h.
|
||||||
|
|
||||||
|
#define SOC_SINGLE(xname, reg, shift, mask, invert)
|
||||||
|
|
||||||
|
Defines a single control as follows:-
|
||||||
|
|
||||||
|
xname = Control name e.g. "Playback Volume"
|
||||||
|
reg = codec register
|
||||||
|
shift = control bit(s) offset in register
|
||||||
|
mask = control bit size(s) e.g. mask of 7 = 3 bits
|
||||||
|
invert = the control is inverted
|
||||||
|
|
||||||
|
Other macros include:-
|
||||||
|
|
||||||
|
#define SOC_DOUBLE(xname, reg, shift_left, shift_right, mask, invert)
|
||||||
|
|
||||||
|
A stereo control
|
||||||
|
|
||||||
|
#define SOC_DOUBLE_R(xname, reg_left, reg_right, shift, mask, invert)
|
||||||
|
|
||||||
|
A stereo control spanning 2 registers
|
||||||
|
|
||||||
|
#define SOC_ENUM_SINGLE(xreg, xshift, xmask, xtexts)
|
||||||
|
|
||||||
|
Defines an single enumerated control as follows:-
|
||||||
|
|
||||||
|
xreg = register
|
||||||
|
xshift = control bit(s) offset in register
|
||||||
|
xmask = control bit(s) size
|
||||||
|
xtexts = pointer to array of strings that describe each setting
|
||||||
|
|
||||||
|
#define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xtexts)
|
||||||
|
|
||||||
|
Defines a stereo enumerated control
|
||||||
|
|
||||||
|
|
||||||
|
4 - Codec Audio Operations
|
||||||
|
--------------------------
|
||||||
|
The codec driver also supports the following alsa operations:-
|
||||||
|
|
||||||
|
/* SoC audio ops */
|
||||||
|
struct snd_soc_ops {
|
||||||
|
int (*startup)(struct snd_pcm_substream *);
|
||||||
|
void (*shutdown)(struct snd_pcm_substream *);
|
||||||
|
int (*hw_params)(struct snd_pcm_substream *, struct snd_pcm_hw_params *);
|
||||||
|
int (*hw_free)(struct snd_pcm_substream *);
|
||||||
|
int (*prepare)(struct snd_pcm_substream *);
|
||||||
|
};
|
||||||
|
|
||||||
|
Please refer to the alsa driver PCM documentation for details.
|
||||||
|
http://www.alsa-project.org/~iwai/writing-an-alsa-driver/c436.htm
|
||||||
|
|
||||||
|
|
||||||
|
5 - DAPM description.
|
||||||
|
---------------------
|
||||||
|
The Dynamic Audio Power Management description describes the codec's power
|
||||||
|
components, their relationships and registers to the ASoC core. Please read
|
||||||
|
dapm.txt for details of building the description.
|
||||||
|
|
||||||
|
Please also see the examples in other codec drivers.
|
||||||
|
|
||||||
|
|
||||||
|
6 - DAPM event handler
|
||||||
|
----------------------
|
||||||
|
This function is a callback that handles codec domain PM calls and system
|
||||||
|
domain PM calls (e.g. suspend and resume). It's used to put the codec to sleep
|
||||||
|
when not in use.
|
||||||
|
|
||||||
|
Power states:-
|
||||||
|
|
||||||
|
SNDRV_CTL_POWER_D0: /* full On */
|
||||||
|
/* vref/mid, clk and osc on, active */
|
||||||
|
|
||||||
|
SNDRV_CTL_POWER_D1: /* partial On */
|
||||||
|
SNDRV_CTL_POWER_D2: /* partial On */
|
||||||
|
|
||||||
|
SNDRV_CTL_POWER_D3hot: /* Off, with power */
|
||||||
|
/* everything off except vref/vmid, inactive */
|
||||||
|
|
||||||
|
SNDRV_CTL_POWER_D3cold: /* Everything Off, without power */
|
||||||
|
|
||||||
|
|
||||||
|
7 - Codec DAC digital mute control.
|
||||||
|
------------------------------------
|
||||||
|
Most codecs have a digital mute before the DAC's that can be used to minimise
|
||||||
|
any system noise. The mute stops any digital data from entering the DAC.
|
||||||
|
|
||||||
|
A callback can be created that is called by the core for each codec DAI when the
|
||||||
|
mute is applied or freed.
|
||||||
|
|
||||||
|
i.e.
|
||||||
|
|
||||||
|
static int wm8974_mute(struct snd_soc_codec *codec,
|
||||||
|
struct snd_soc_codec_dai *dai, int mute)
|
||||||
|
{
|
||||||
|
u16 mute_reg = wm8974_read_reg_cache(codec, WM8974_DAC) & 0xffbf;
|
||||||
|
if(mute)
|
||||||
|
wm8974_write(codec, WM8974_DAC, mute_reg | 0x40);
|
||||||
|
else
|
||||||
|
wm8974_write(codec, WM8974_DAC, mute_reg);
|
||||||
|
return 0;
|
||||||
|
}
|
297
Documentation/sound/alsa/soc/dapm.txt
Normal file
297
Documentation/sound/alsa/soc/dapm.txt
Normal file
|
@ -0,0 +1,297 @@
|
||||||
|
Dynamic Audio Power Management for Portable Devices
|
||||||
|
===================================================
|
||||||
|
|
||||||
|
1. Description
|
||||||
|
==============
|
||||||
|
|
||||||
|
Dynamic Audio Power Management (DAPM) is designed to allow portable Linux devices
|
||||||
|
to use the minimum amount of power within the audio subsystem at all times. It
|
||||||
|
is independent of other kernel PM and as such, can easily co-exist with the
|
||||||
|
other PM systems.
|
||||||
|
|
||||||
|
DAPM is also completely transparent to all user space applications as all power
|
||||||
|
switching is done within the ASoC core. No code changes or recompiling are
|
||||||
|
required for user space applications. DAPM makes power switching descisions based
|
||||||
|
upon any audio stream (capture/playback) activity and audio mixer settings
|
||||||
|
within the device.
|
||||||
|
|
||||||
|
DAPM spans the whole machine. It covers power control within the entire audio
|
||||||
|
subsystem, this includes internal codec power blocks and machine level power
|
||||||
|
systems.
|
||||||
|
|
||||||
|
There are 4 power domains within DAPM
|
||||||
|
|
||||||
|
1. Codec domain - VREF, VMID (core codec and audio power)
|
||||||
|
Usually controlled at codec probe/remove and suspend/resume, although
|
||||||
|
can be set at stream time if power is not needed for sidetone, etc.
|
||||||
|
|
||||||
|
2. Platform/Machine domain - physically connected inputs and outputs
|
||||||
|
Is platform/machine and user action specific, is configured by the
|
||||||
|
machine driver and responds to asynchronous events e.g when HP
|
||||||
|
are inserted
|
||||||
|
|
||||||
|
3. Path domain - audio susbsystem signal paths
|
||||||
|
Automatically set when mixer and mux settings are changed by the user.
|
||||||
|
e.g. alsamixer, amixer.
|
||||||
|
|
||||||
|
4. Stream domain - DAC's and ADC's.
|
||||||
|
Enabled and disabled when stream playback/capture is started and
|
||||||
|
stopped respectively. e.g. aplay, arecord.
|
||||||
|
|
||||||
|
All DAPM power switching descisons are made automatically by consulting an audio
|
||||||
|
routing map of the whole machine. This map is specific to each machine and
|
||||||
|
consists of the interconnections between every audio component (including
|
||||||
|
internal codec components). All audio components that effect power are called
|
||||||
|
widgets hereafter.
|
||||||
|
|
||||||
|
|
||||||
|
2. DAPM Widgets
|
||||||
|
===============
|
||||||
|
|
||||||
|
Audio DAPM widgets fall into a number of types:-
|
||||||
|
|
||||||
|
o Mixer - Mixes several analog signals into a single analog signal.
|
||||||
|
o Mux - An analog switch that outputs only 1 of it's inputs.
|
||||||
|
o PGA - A programmable gain amplifier or attenuation widget.
|
||||||
|
o ADC - Analog to Digital Converter
|
||||||
|
o DAC - Digital to Analog Converter
|
||||||
|
o Switch - An analog switch
|
||||||
|
o Input - A codec input pin
|
||||||
|
o Output - A codec output pin
|
||||||
|
o Headphone - Headphone (and optional Jack)
|
||||||
|
o Mic - Mic (and optional Jack)
|
||||||
|
o Line - Line Input/Output (and optional Jack)
|
||||||
|
o Speaker - Speaker
|
||||||
|
o Pre - Special PRE widget (exec before all others)
|
||||||
|
o Post - Special POST widget (exec after all others)
|
||||||
|
|
||||||
|
(Widgets are defined in include/sound/soc-dapm.h)
|
||||||
|
|
||||||
|
Widgets are usually added in the codec driver and the machine driver. There are
|
||||||
|
convience macros defined in soc-dapm.h that can be used to quickly build a
|
||||||
|
list of widgets of the codecs and machines DAPM widgets.
|
||||||
|
|
||||||
|
Most widgets have a name, register, shift and invert. Some widgets have extra
|
||||||
|
parameters for stream name and kcontrols.
|
||||||
|
|
||||||
|
|
||||||
|
2.1 Stream Domain Widgets
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
Stream Widgets relate to the stream power domain and only consist of ADC's
|
||||||
|
(analog to digital converters) and DAC's (digital to analog converters).
|
||||||
|
|
||||||
|
Stream widgets have the following format:-
|
||||||
|
|
||||||
|
SND_SOC_DAPM_DAC(name, stream name, reg, shift, invert),
|
||||||
|
|
||||||
|
NOTE: the stream name must match the corresponding stream name in your codecs
|
||||||
|
snd_soc_codec_dai.
|
||||||
|
|
||||||
|
e.g. stream widgets for HiFi playback and capture
|
||||||
|
|
||||||
|
SND_SOC_DAPM_DAC("HiFi DAC", "HiFi Playback", REG, 3, 1),
|
||||||
|
SND_SOC_DAPM_ADC("HiFi ADC", "HiFi Capture", REG, 2, 1),
|
||||||
|
|
||||||
|
|
||||||
|
2.2 Path Domain Widgets
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
Path domain widgets have a ability to control or effect the audio signal or
|
||||||
|
audio paths within the audio subsystem. They have the following form:-
|
||||||
|
|
||||||
|
SND_SOC_DAPM_PGA(name, reg, shift, invert, controls, num_controls)
|
||||||
|
|
||||||
|
Any widget kcontrols can be set using the controls and num_controls members.
|
||||||
|
|
||||||
|
e.g. Mixer widget (the kcontrols are declared first)
|
||||||
|
|
||||||
|
/* Output Mixer */
|
||||||
|
static const snd_kcontrol_new_t wm8731_output_mixer_controls[] = {
|
||||||
|
SOC_DAPM_SINGLE("Line Bypass Switch", WM8731_APANA, 3, 1, 0),
|
||||||
|
SOC_DAPM_SINGLE("Mic Sidetone Switch", WM8731_APANA, 5, 1, 0),
|
||||||
|
SOC_DAPM_SINGLE("HiFi Playback Switch", WM8731_APANA, 4, 1, 0),
|
||||||
|
};
|
||||||
|
|
||||||
|
SND_SOC_DAPM_MIXER("Output Mixer", WM8731_PWR, 4, 1, wm8731_output_mixer_controls,
|
||||||
|
ARRAY_SIZE(wm8731_output_mixer_controls)),
|
||||||
|
|
||||||
|
|
||||||
|
2.3 Platform/Machine domain Widgets
|
||||||
|
-----------------------------------
|
||||||
|
|
||||||
|
Machine widgets are different from codec widgets in that they don't have a
|
||||||
|
codec register bit associated with them. A machine widget is assigned to each
|
||||||
|
machine audio component (non codec) that can be independently powered. e.g.
|
||||||
|
|
||||||
|
o Speaker Amp
|
||||||
|
o Microphone Bias
|
||||||
|
o Jack connectors
|
||||||
|
|
||||||
|
A machine widget can have an optional call back.
|
||||||
|
|
||||||
|
e.g. Jack connector widget for an external Mic that enables Mic Bias
|
||||||
|
when the Mic is inserted:-
|
||||||
|
|
||||||
|
static int spitz_mic_bias(struct snd_soc_dapm_widget* w, int event)
|
||||||
|
{
|
||||||
|
if(SND_SOC_DAPM_EVENT_ON(event))
|
||||||
|
set_scoop_gpio(&spitzscoop2_device.dev, SPITZ_SCP2_MIC_BIAS);
|
||||||
|
else
|
||||||
|
reset_scoop_gpio(&spitzscoop2_device.dev, SPITZ_SCP2_MIC_BIAS);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SND_SOC_DAPM_MIC("Mic Jack", spitz_mic_bias),
|
||||||
|
|
||||||
|
|
||||||
|
2.4 Codec Domain
|
||||||
|
----------------
|
||||||
|
|
||||||
|
The Codec power domain has no widgets and is handled by the codecs DAPM event
|
||||||
|
handler. This handler is called when the codec powerstate is changed wrt to any
|
||||||
|
stream event or by kernel PM events.
|
||||||
|
|
||||||
|
|
||||||
|
2.5 Virtual Widgets
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
Sometimes widgets exist in the codec or machine audio map that don't have any
|
||||||
|
corresponding register bit for power control. In this case it's necessary to
|
||||||
|
create a virtual widget - a widget with no control bits e.g.
|
||||||
|
|
||||||
|
SND_SOC_DAPM_MIXER("AC97 Mixer", SND_SOC_DAPM_NOPM, 0, 0, NULL, 0),
|
||||||
|
|
||||||
|
This can be used to merge to signal paths together in software.
|
||||||
|
|
||||||
|
After all the widgets have been defined, they can then be added to the DAPM
|
||||||
|
subsystem individually with a call to snd_soc_dapm_new_control().
|
||||||
|
|
||||||
|
|
||||||
|
3. Codec Widget Interconnections
|
||||||
|
================================
|
||||||
|
|
||||||
|
Widgets are connected to each other within the codec and machine by audio
|
||||||
|
paths (called interconnections). Each interconnection must be defined in order
|
||||||
|
to create a map of all audio paths between widgets.
|
||||||
|
This is easiest with a diagram of the codec (and schematic of the machine audio
|
||||||
|
system), as it requires joining widgets together via their audio signal paths.
|
||||||
|
|
||||||
|
i.e. from the WM8731 codec's output mixer (wm8731.c)
|
||||||
|
|
||||||
|
The WM8731 output mixer has 3 inputs (sources)
|
||||||
|
|
||||||
|
1. Line Bypass Input
|
||||||
|
2. DAC (HiFi playback)
|
||||||
|
3. Mic Sidetone Input
|
||||||
|
|
||||||
|
Each input in this example has a kcontrol associated with it (defined in example
|
||||||
|
above) and is connected to the output mixer via it's kcontrol name. We can now
|
||||||
|
connect the destination widget (wrt audio signal) with it's source widgets.
|
||||||
|
|
||||||
|
/* output mixer */
|
||||||
|
{"Output Mixer", "Line Bypass Switch", "Line Input"},
|
||||||
|
{"Output Mixer", "HiFi Playback Switch", "DAC"},
|
||||||
|
{"Output Mixer", "Mic Sidetone Switch", "Mic Bias"},
|
||||||
|
|
||||||
|
So we have :-
|
||||||
|
|
||||||
|
Destination Widget <=== Path Name <=== Source Widget
|
||||||
|
|
||||||
|
Or:-
|
||||||
|
|
||||||
|
Sink, Path, Source
|
||||||
|
|
||||||
|
Or :-
|
||||||
|
|
||||||
|
"Output Mixer" is connected to the "DAC" via the "HiFi Playback Switch".
|
||||||
|
|
||||||
|
When there is no path name connecting widgets (e.g. a direct connection) we
|
||||||
|
pass NULL for the path name.
|
||||||
|
|
||||||
|
Interconnections are created with a call to:-
|
||||||
|
|
||||||
|
snd_soc_dapm_connect_input(codec, sink, path, source);
|
||||||
|
|
||||||
|
Finally, snd_soc_dapm_new_widgets(codec) must be called after all widgets and
|
||||||
|
interconnections have been registered with the core. This causes the core to
|
||||||
|
scan the codec and machine so that the internal DAPM state matches the
|
||||||
|
physical state of the machine.
|
||||||
|
|
||||||
|
|
||||||
|
3.1 Machine Widget Interconnections
|
||||||
|
-----------------------------------
|
||||||
|
Machine widget interconnections are created in the same way as codec ones and
|
||||||
|
directly connect the codec pins to machine level widgets.
|
||||||
|
|
||||||
|
e.g. connects the speaker out codec pins to the internal speaker.
|
||||||
|
|
||||||
|
/* ext speaker connected to codec pins LOUT2, ROUT2 */
|
||||||
|
{"Ext Spk", NULL , "ROUT2"},
|
||||||
|
{"Ext Spk", NULL , "LOUT2"},
|
||||||
|
|
||||||
|
This allows the DAPM to power on and off pins that are connected (and in use)
|
||||||
|
and pins that are NC respectively.
|
||||||
|
|
||||||
|
|
||||||
|
4 Endpoint Widgets
|
||||||
|
===================
|
||||||
|
An endpoint is a start or end point (widget) of an audio signal within the
|
||||||
|
machine and includes the codec. e.g.
|
||||||
|
|
||||||
|
o Headphone Jack
|
||||||
|
o Internal Speaker
|
||||||
|
o Internal Mic
|
||||||
|
o Mic Jack
|
||||||
|
o Codec Pins
|
||||||
|
|
||||||
|
When a codec pin is NC it can be marked as not used with a call to
|
||||||
|
|
||||||
|
snd_soc_dapm_set_endpoint(codec, "Widget Name", 0);
|
||||||
|
|
||||||
|
The last argument is 0 for inactive and 1 for active. This way the pin and its
|
||||||
|
input widget will never be powered up and consume power.
|
||||||
|
|
||||||
|
This also applies to machine widgets. e.g. if a headphone is connected to a
|
||||||
|
jack then the jack can be marked active. If the headphone is removed, then
|
||||||
|
the headphone jack can be marked inactive.
|
||||||
|
|
||||||
|
|
||||||
|
5 DAPM Widget Events
|
||||||
|
====================
|
||||||
|
|
||||||
|
Some widgets can register their interest with the DAPM core in PM events.
|
||||||
|
e.g. A Speaker with an amplifier registers a widget so the amplifier can be
|
||||||
|
powered only when the spk is in use.
|
||||||
|
|
||||||
|
/* turn speaker amplifier on/off depending on use */
|
||||||
|
static int corgi_amp_event(struct snd_soc_dapm_widget *w, int event)
|
||||||
|
{
|
||||||
|
if (SND_SOC_DAPM_EVENT_ON(event))
|
||||||
|
set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_APM_ON);
|
||||||
|
else
|
||||||
|
reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_APM_ON);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* corgi machine dapm widgets */
|
||||||
|
static const struct snd_soc_dapm_widget wm8731_dapm_widgets =
|
||||||
|
SND_SOC_DAPM_SPK("Ext Spk", corgi_amp_event);
|
||||||
|
|
||||||
|
Please see soc-dapm.h for all other widgets that support events.
|
||||||
|
|
||||||
|
|
||||||
|
5.1 Event types
|
||||||
|
---------------
|
||||||
|
|
||||||
|
The following event types are supported by event widgets.
|
||||||
|
|
||||||
|
/* dapm event types */
|
||||||
|
#define SND_SOC_DAPM_PRE_PMU 0x1 /* before widget power up */
|
||||||
|
#define SND_SOC_DAPM_POST_PMU 0x2 /* after widget power up */
|
||||||
|
#define SND_SOC_DAPM_PRE_PMD 0x4 /* before widget power down */
|
||||||
|
#define SND_SOC_DAPM_POST_PMD 0x8 /* after widget power down */
|
||||||
|
#define SND_SOC_DAPM_PRE_REG 0x10 /* before audio path setup */
|
||||||
|
#define SND_SOC_DAPM_POST_REG 0x20 /* after audio path setup */
|
113
Documentation/sound/alsa/soc/machine.txt
Normal file
113
Documentation/sound/alsa/soc/machine.txt
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
ASoC Machine Driver
|
||||||
|
===================
|
||||||
|
|
||||||
|
The ASoC machine (or board) driver is the code that glues together the platform
|
||||||
|
and codec drivers.
|
||||||
|
|
||||||
|
The machine driver can contain codec and platform specific code. It registers
|
||||||
|
the audio subsystem with the kernel as a platform device and is represented by
|
||||||
|
the following struct:-
|
||||||
|
|
||||||
|
/* SoC machine */
|
||||||
|
struct snd_soc_machine {
|
||||||
|
char *name;
|
||||||
|
|
||||||
|
int (*probe)(struct platform_device *pdev);
|
||||||
|
int (*remove)(struct platform_device *pdev);
|
||||||
|
|
||||||
|
/* the pre and post PM functions are used to do any PM work before and
|
||||||
|
* after the codec and DAI's do any PM work. */
|
||||||
|
int (*suspend_pre)(struct platform_device *pdev, pm_message_t state);
|
||||||
|
int (*suspend_post)(struct platform_device *pdev, pm_message_t state);
|
||||||
|
int (*resume_pre)(struct platform_device *pdev);
|
||||||
|
int (*resume_post)(struct platform_device *pdev);
|
||||||
|
|
||||||
|
/* machine stream operations */
|
||||||
|
struct snd_soc_ops *ops;
|
||||||
|
|
||||||
|
/* CPU <--> Codec DAI links */
|
||||||
|
struct snd_soc_dai_link *dai_link;
|
||||||
|
int num_links;
|
||||||
|
};
|
||||||
|
|
||||||
|
probe()/remove()
|
||||||
|
----------------
|
||||||
|
probe/remove are optional. Do any machine specific probe here.
|
||||||
|
|
||||||
|
|
||||||
|
suspend()/resume()
|
||||||
|
------------------
|
||||||
|
The machine driver has pre and post versions of suspend and resume to take care
|
||||||
|
of any machine audio tasks that have to be done before or after the codec, DAI's
|
||||||
|
and DMA is suspended and resumed. Optional.
|
||||||
|
|
||||||
|
|
||||||
|
Machine operations
|
||||||
|
------------------
|
||||||
|
The machine specific audio operations can be set here. Again this is optional.
|
||||||
|
|
||||||
|
|
||||||
|
Machine DAI Configuration
|
||||||
|
-------------------------
|
||||||
|
The machine DAI configuration glues all the codec and CPU DAI's together. It can
|
||||||
|
also be used to set up the DAI system clock and for any machine related DAI
|
||||||
|
initialisation e.g. the machine audio map can be connected to the codec audio
|
||||||
|
map, unconnnected codec pins can be set as such. Please see corgi.c, spitz.c
|
||||||
|
for examples.
|
||||||
|
|
||||||
|
struct snd_soc_dai_link is used to set up each DAI in your machine. e.g.
|
||||||
|
|
||||||
|
/* corgi digital audio interface glue - connects codec <--> CPU */
|
||||||
|
static struct snd_soc_dai_link corgi_dai = {
|
||||||
|
.name = "WM8731",
|
||||||
|
.stream_name = "WM8731",
|
||||||
|
.cpu_dai = &pxa_i2s_dai,
|
||||||
|
.codec_dai = &wm8731_dai,
|
||||||
|
.init = corgi_wm8731_init,
|
||||||
|
.ops = &corgi_ops,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct snd_soc_machine then sets up the machine with it's DAI's. e.g.
|
||||||
|
|
||||||
|
/* corgi audio machine driver */
|
||||||
|
static struct snd_soc_machine snd_soc_machine_corgi = {
|
||||||
|
.name = "Corgi",
|
||||||
|
.dai_link = &corgi_dai,
|
||||||
|
.num_links = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Machine Audio Subsystem
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
The machine soc device glues the platform, machine and codec driver together.
|
||||||
|
Private data can also be set here. e.g.
|
||||||
|
|
||||||
|
/* corgi audio private data */
|
||||||
|
static struct wm8731_setup_data corgi_wm8731_setup = {
|
||||||
|
.i2c_address = 0x1b,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* corgi audio subsystem */
|
||||||
|
static struct snd_soc_device corgi_snd_devdata = {
|
||||||
|
.machine = &snd_soc_machine_corgi,
|
||||||
|
.platform = &pxa2xx_soc_platform,
|
||||||
|
.codec_dev = &soc_codec_dev_wm8731,
|
||||||
|
.codec_data = &corgi_wm8731_setup,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Machine Power Map
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
The machine driver can optionally extend the codec power map and to become an
|
||||||
|
audio power map of the audio subsystem. This allows for automatic power up/down
|
||||||
|
of speaker/HP amplifiers, etc. Codec pins can be connected to the machines jack
|
||||||
|
sockets in the machine init function. See soc/pxa/spitz.c and dapm.txt for
|
||||||
|
details.
|
||||||
|
|
||||||
|
|
||||||
|
Machine Controls
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Machine specific audio mixer controls can be added in the dai init function.
|
83
Documentation/sound/alsa/soc/overview.txt
Normal file
83
Documentation/sound/alsa/soc/overview.txt
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
ALSA SoC Layer
|
||||||
|
==============
|
||||||
|
|
||||||
|
The overall project goal of the ALSA System on Chip (ASoC) layer is to provide
|
||||||
|
better ALSA support for embedded system on chip procesors (e.g. pxa2xx, au1x00,
|
||||||
|
iMX, etc) and portable audio codecs. Currently there is some support in the
|
||||||
|
kernel for SoC audio, however it has some limitations:-
|
||||||
|
|
||||||
|
* Currently, codec drivers are often tightly coupled to the underlying SoC
|
||||||
|
cpu. This is not ideal and leads to code duplication i.e. Linux now has 4
|
||||||
|
different wm8731 drivers for 4 different SoC platforms.
|
||||||
|
|
||||||
|
* There is no standard method to signal user initiated audio events.
|
||||||
|
e.g. Headphone/Mic insertion, Headphone/Mic detection after an insertion
|
||||||
|
event. These are quite common events on portable devices and ofter require
|
||||||
|
machine specific code to re route audio, enable amps etc after such an event.
|
||||||
|
|
||||||
|
* Current drivers tend to power up the entire codec when playing
|
||||||
|
(or recording) audio. This is fine for a PC, but tends to waste a lot of
|
||||||
|
power on portable devices. There is also no support for saving power via
|
||||||
|
changing codec oversampling rates, bias currents, etc.
|
||||||
|
|
||||||
|
|
||||||
|
ASoC Design
|
||||||
|
===========
|
||||||
|
|
||||||
|
The ASoC layer is designed to address these issues and provide the following
|
||||||
|
features :-
|
||||||
|
|
||||||
|
* Codec independence. Allows reuse of codec drivers on other platforms
|
||||||
|
and machines.
|
||||||
|
|
||||||
|
* Easy I2S/PCM audio interface setup between codec and SoC. Each SoC interface
|
||||||
|
and codec registers it's audio interface capabilities with the core and are
|
||||||
|
subsequently matched and configured when the application hw params are known.
|
||||||
|
|
||||||
|
* Dynamic Audio Power Management (DAPM). DAPM automatically sets the codec to
|
||||||
|
it's minimum power state at all times. This includes powering up/down
|
||||||
|
internal power blocks depending on the internal codec audio routing and any
|
||||||
|
active streams.
|
||||||
|
|
||||||
|
* Pop and click reduction. Pops and clicks can be reduced by powering the
|
||||||
|
codec up/down in the correct sequence (including using digital mute). ASoC
|
||||||
|
signals the codec when to change power states.
|
||||||
|
|
||||||
|
* Machine specific controls: Allow machines to add controls to the sound card
|
||||||
|
e.g. volume control for speaker amp.
|
||||||
|
|
||||||
|
To achieve all this, ASoC basically splits an embedded audio system into 3
|
||||||
|
components :-
|
||||||
|
|
||||||
|
* Codec driver: The codec driver is platform independent and contains audio
|
||||||
|
controls, audio interface capabilities, codec dapm definition and codec IO
|
||||||
|
functions.
|
||||||
|
|
||||||
|
* Platform driver: The platform driver contains the audio dma engine and audio
|
||||||
|
interface drivers (e.g. I2S, AC97, PCM) for that platform.
|
||||||
|
|
||||||
|
* Machine driver: The machine driver handles any machine specific controls and
|
||||||
|
audio events. i.e. turing on an amp at start of playback.
|
||||||
|
|
||||||
|
|
||||||
|
Documentation
|
||||||
|
=============
|
||||||
|
|
||||||
|
The documentation is spilt into the following sections:-
|
||||||
|
|
||||||
|
overview.txt: This file.
|
||||||
|
|
||||||
|
codec.txt: Codec driver internals.
|
||||||
|
|
||||||
|
DAI.txt: Description of Digital Audio Interface standards and how to configure
|
||||||
|
a DAI within your codec and CPU DAI drivers.
|
||||||
|
|
||||||
|
dapm.txt: Dynamic Audio Power Management
|
||||||
|
|
||||||
|
platform.txt: Platform audio DMA and DAI.
|
||||||
|
|
||||||
|
machine.txt: Machine driver internals.
|
||||||
|
|
||||||
|
pop_clicks.txt: How to minimise audio artifacts.
|
||||||
|
|
||||||
|
clocking.txt: ASoC clocking for best power performance.
|
58
Documentation/sound/alsa/soc/platform.txt
Normal file
58
Documentation/sound/alsa/soc/platform.txt
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
ASoC Platform Driver
|
||||||
|
====================
|
||||||
|
|
||||||
|
An ASoC platform driver can be divided into audio DMA and SoC DAI configuration
|
||||||
|
and control. The platform drivers only target the SoC CPU and must have no board
|
||||||
|
specific code.
|
||||||
|
|
||||||
|
Audio DMA
|
||||||
|
=========
|
||||||
|
|
||||||
|
The platform DMA driver optionally supports the following alsa operations:-
|
||||||
|
|
||||||
|
/* SoC audio ops */
|
||||||
|
struct snd_soc_ops {
|
||||||
|
int (*startup)(struct snd_pcm_substream *);
|
||||||
|
void (*shutdown)(struct snd_pcm_substream *);
|
||||||
|
int (*hw_params)(struct snd_pcm_substream *, struct snd_pcm_hw_params *);
|
||||||
|
int (*hw_free)(struct snd_pcm_substream *);
|
||||||
|
int (*prepare)(struct snd_pcm_substream *);
|
||||||
|
int (*trigger)(struct snd_pcm_substream *, int);
|
||||||
|
};
|
||||||
|
|
||||||
|
The platform driver exports it's DMA functionailty via struct snd_soc_platform:-
|
||||||
|
|
||||||
|
struct snd_soc_platform {
|
||||||
|
char *name;
|
||||||
|
|
||||||
|
int (*probe)(struct platform_device *pdev);
|
||||||
|
int (*remove)(struct platform_device *pdev);
|
||||||
|
int (*suspend)(struct platform_device *pdev, struct snd_soc_cpu_dai *cpu_dai);
|
||||||
|
int (*resume)(struct platform_device *pdev, struct snd_soc_cpu_dai *cpu_dai);
|
||||||
|
|
||||||
|
/* pcm creation and destruction */
|
||||||
|
int (*pcm_new)(struct snd_card *, struct snd_soc_codec_dai *, struct snd_pcm *);
|
||||||
|
void (*pcm_free)(struct snd_pcm *);
|
||||||
|
|
||||||
|
/* platform stream ops */
|
||||||
|
struct snd_pcm_ops *pcm_ops;
|
||||||
|
};
|
||||||
|
|
||||||
|
Please refer to the alsa driver documentation for details of audio DMA.
|
||||||
|
http://www.alsa-project.org/~iwai/writing-an-alsa-driver/c436.htm
|
||||||
|
|
||||||
|
An example DMA driver is soc/pxa/pxa2xx-pcm.c
|
||||||
|
|
||||||
|
|
||||||
|
SoC DAI Drivers
|
||||||
|
===============
|
||||||
|
|
||||||
|
Each SoC DAI driver must provide the following features:-
|
||||||
|
|
||||||
|
1) Digital audio interface (DAI) description
|
||||||
|
2) Digital audio interface configuration
|
||||||
|
3) PCM's description
|
||||||
|
4) Sysclk configuration
|
||||||
|
5) Suspend and resume (optional)
|
||||||
|
|
||||||
|
Please see codec.txt for a description of items 1 - 4.
|
52
Documentation/sound/alsa/soc/pops_clicks.txt
Normal file
52
Documentation/sound/alsa/soc/pops_clicks.txt
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
Audio Pops and Clicks
|
||||||
|
=====================
|
||||||
|
|
||||||
|
Pops and clicks are unwanted audio artifacts caused by the powering up and down
|
||||||
|
of components within the audio subsystem. This is noticable on PC's when an
|
||||||
|
audio module is either loaded or unloaded (at module load time the sound card is
|
||||||
|
powered up and causes a popping noise on the speakers).
|
||||||
|
|
||||||
|
Pops and clicks can be more frequent on portable systems with DAPM. This is
|
||||||
|
because the components within the subsystem are being dynamically powered
|
||||||
|
depending on the audio usage and this can subsequently cause a small pop or
|
||||||
|
click every time a component power state is changed.
|
||||||
|
|
||||||
|
|
||||||
|
Minimising Playback Pops and Clicks
|
||||||
|
===================================
|
||||||
|
|
||||||
|
Playback pops in portable audio subsystems cannot be completely eliminated atm,
|
||||||
|
however future audio codec hardware will have better pop and click supression.
|
||||||
|
Pops can be reduced within playback by powering the audio components in a
|
||||||
|
specific order. This order is different for startup and shutdown and follows
|
||||||
|
some basic rules:-
|
||||||
|
|
||||||
|
Startup Order :- DAC --> Mixers --> Output PGA --> Digital Unmute
|
||||||
|
|
||||||
|
Shutdown Order :- Digital Mute --> Output PGA --> Mixers --> DAC
|
||||||
|
|
||||||
|
This assumes that the codec PCM output path from the DAC is via a mixer and then
|
||||||
|
a PGA (programmable gain amplifier) before being output to the speakers.
|
||||||
|
|
||||||
|
|
||||||
|
Minimising Capture Pops and Clicks
|
||||||
|
==================================
|
||||||
|
|
||||||
|
Capture artifacts are somewhat easier to get rid as we can delay activating the
|
||||||
|
ADC until all the pops have occured. This follows similar power rules to
|
||||||
|
playback in that components are powered in a sequence depending upon stream
|
||||||
|
startup or shutdown.
|
||||||
|
|
||||||
|
Startup Order - Input PGA --> Mixers --> ADC
|
||||||
|
|
||||||
|
Shutdown Order - ADC --> Mixers --> Input PGA
|
||||||
|
|
||||||
|
|
||||||
|
Zipper Noise
|
||||||
|
============
|
||||||
|
An unwanted zipper noise can occur within the audio playback or capture stream
|
||||||
|
when a volume control is changed near its maximum gain value. The zipper noise
|
||||||
|
is heard when the gain increase or decrease changes the mean audio signal
|
||||||
|
amplitude too quickly. It can be minimised by enabling the zero cross setting
|
||||||
|
for each volume control. The ZC forces the gain change to occur when the signal
|
||||||
|
crosses the zero amplitude line.
|
|
@ -1,6 +1,6 @@
|
||||||
Linux Magic System Request Key Hacks
|
Linux Magic System Request Key Hacks
|
||||||
Documentation for sysrq.c version 1.15
|
Documentation for sysrq.c
|
||||||
Last update: $Date: 2001/01/28 10:15:59 $
|
Last update: 2007-JAN-06
|
||||||
|
|
||||||
* What is the magic SysRq key?
|
* What is the magic SysRq key?
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
@ -35,7 +35,7 @@ You can set the value in the file by the following command:
|
||||||
|
|
||||||
Note that the value of /proc/sys/kernel/sysrq influences only the invocation
|
Note that the value of /proc/sys/kernel/sysrq influences only the invocation
|
||||||
via a keyboard. Invocation of any operation via /proc/sysrq-trigger is always
|
via a keyboard. Invocation of any operation via /proc/sysrq-trigger is always
|
||||||
allowed.
|
allowed (by a user with admin privileges).
|
||||||
|
|
||||||
* How do I use the magic SysRq key?
|
* How do I use the magic SysRq key?
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
@ -58,7 +58,7 @@ On PowerPC - Press 'ALT - Print Screen (or F13) - <command key>,
|
||||||
On other - If you know of the key combos for other architectures, please
|
On other - If you know of the key combos for other architectures, please
|
||||||
let me know so I can add them to this section.
|
let me know so I can add them to this section.
|
||||||
|
|
||||||
On all - write a character to /proc/sysrq-trigger. eg:
|
On all - write a character to /proc/sysrq-trigger. e.g.:
|
||||||
|
|
||||||
echo t > /proc/sysrq-trigger
|
echo t > /proc/sysrq-trigger
|
||||||
|
|
||||||
|
@ -74,6 +74,8 @@ On all - write a character to /proc/sysrq-trigger. eg:
|
||||||
|
|
||||||
'c' - Will perform a kexec reboot in order to take a crashdump.
|
'c' - Will perform a kexec reboot in order to take a crashdump.
|
||||||
|
|
||||||
|
'd' - Shows all locks that are held.
|
||||||
|
|
||||||
'o' - Will shut your system off (if configured and supported).
|
'o' - Will shut your system off (if configured and supported).
|
||||||
|
|
||||||
's' - Will attempt to sync all mounted filesystems.
|
's' - Will attempt to sync all mounted filesystems.
|
||||||
|
@ -87,38 +89,43 @@ On all - write a character to /proc/sysrq-trigger. eg:
|
||||||
|
|
||||||
'm' - Will dump current memory info to your console.
|
'm' - Will dump current memory info to your console.
|
||||||
|
|
||||||
|
'n' - Used to make RT tasks nice-able
|
||||||
|
|
||||||
'v' - Dumps Voyager SMP processor info to your console.
|
'v' - Dumps Voyager SMP processor info to your console.
|
||||||
|
|
||||||
|
'w' - Dumps tasks that are in uninterruptable (blocked) state.
|
||||||
|
|
||||||
|
'x' - Used by xmon interface on ppc/powerpc platforms.
|
||||||
|
|
||||||
'0'-'9' - Sets the console log level, controlling which kernel messages
|
'0'-'9' - Sets the console log level, controlling which kernel messages
|
||||||
will be printed to your console. ('0', for example would make
|
will be printed to your console. ('0', for example would make
|
||||||
it so that only emergency messages like PANICs or OOPSes would
|
it so that only emergency messages like PANICs or OOPSes would
|
||||||
make it to your console.)
|
make it to your console.)
|
||||||
|
|
||||||
'f' - Will call oom_kill to kill a memory hog process
|
'f' - Will call oom_kill to kill a memory hog process.
|
||||||
|
|
||||||
'e' - Send a SIGTERM to all processes, except for init.
|
'e' - Send a SIGTERM to all processes, except for init.
|
||||||
|
|
||||||
|
'g' - Used by kgdb on ppc platforms.
|
||||||
|
|
||||||
'i' - Send a SIGKILL to all processes, except for init.
|
'i' - Send a SIGKILL to all processes, except for init.
|
||||||
|
|
||||||
'l' - Send a SIGKILL to all processes, INCLUDING init. (Your system
|
'h' - Will display help (actually any other key than those listed
|
||||||
will be non-functional after this.)
|
|
||||||
|
|
||||||
'h' - Will display help ( actually any other key than those listed
|
|
||||||
above will display help. but 'h' is easy to remember :-)
|
above will display help. but 'h' is easy to remember :-)
|
||||||
|
|
||||||
* Okay, so what can I use them for?
|
* Okay, so what can I use them for?
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
Well, un'R'aw is very handy when your X server or a svgalib program crashes.
|
Well, un'R'aw is very handy when your X server or a svgalib program crashes.
|
||||||
|
|
||||||
sa'K' (Secure Access Key) is useful when you want to be sure there are no
|
sa'K' (Secure Access Key) is useful when you want to be sure there is no
|
||||||
trojan program is running at console and which could grab your password
|
trojan program running at console which could grab your password
|
||||||
when you would try to login. It will kill all programs on given console
|
when you would try to login. It will kill all programs on given console,
|
||||||
and thus letting you make sure that the login prompt you see is actually
|
thus letting you make sure that the login prompt you see is actually
|
||||||
the one from init, not some trojan program.
|
the one from init, not some trojan program.
|
||||||
IMPORTANT: In its true form it is not a true SAK like the one in a :IMPORTANT
|
IMPORTANT: In its true form it is not a true SAK like the one in a :IMPORTANT
|
||||||
IMPORTANT: c2 compliant system, and it should not be mistaken as :IMPORTANT
|
IMPORTANT: c2 compliant system, and it should not be mistaken as :IMPORTANT
|
||||||
IMPORTANT: such. :IMPORTANT
|
IMPORTANT: such. :IMPORTANT
|
||||||
It seems other find it useful as (System Attention Key) which is
|
It seems others find it useful as (System Attention Key) which is
|
||||||
useful when you want to exit a program that will not let you switch consoles.
|
useful when you want to exit a program that will not let you switch consoles.
|
||||||
(For example, X or a svgalib program.)
|
(For example, X or a svgalib program.)
|
||||||
|
|
||||||
|
@ -139,8 +146,8 @@ OK or Done message...)
|
||||||
Again, the unmount (remount read-only) hasn't taken place until you see the
|
Again, the unmount (remount read-only) hasn't taken place until you see the
|
||||||
"OK" and "Done" message appear on the screen.
|
"OK" and "Done" message appear on the screen.
|
||||||
|
|
||||||
The loglevel'0'-'9' is useful when your console is being flooded with
|
The loglevels '0'-'9' are useful when your console is being flooded with
|
||||||
kernel messages you do not want to see. Setting '0' will prevent all but
|
kernel messages you do not want to see. Selecting '0' will prevent all but
|
||||||
the most urgent kernel messages from reaching your console. (They will
|
the most urgent kernel messages from reaching your console. (They will
|
||||||
still be logged if syslogd/klogd are alive, though.)
|
still be logged if syslogd/klogd are alive, though.)
|
||||||
|
|
||||||
|
@ -152,7 +159,7 @@ processes.
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
That happens to me, also. I've found that tapping shift, alt, and control
|
That happens to me, also. I've found that tapping shift, alt, and control
|
||||||
on both sides of the keyboard, and hitting an invalid sysrq sequence again
|
on both sides of the keyboard, and hitting an invalid sysrq sequence again
|
||||||
will fix the problem. (ie, something like alt-sysrq-z). Switching to another
|
will fix the problem. (i.e., something like alt-sysrq-z). Switching to another
|
||||||
virtual console (ALT+Fn) and then back again should also help.
|
virtual console (ALT+Fn) and then back again should also help.
|
||||||
|
|
||||||
* I hit SysRq, but nothing seems to happen, what's wrong?
|
* I hit SysRq, but nothing seems to happen, what's wrong?
|
||||||
|
@ -174,11 +181,11 @@ handler function you will use, B) a help_msg string, that will print when SysRQ
|
||||||
prints help, and C) an action_msg string, that will print right before your
|
prints help, and C) an action_msg string, that will print right before your
|
||||||
handler is called. Your handler must conform to the prototype in 'sysrq.h'.
|
handler is called. Your handler must conform to the prototype in 'sysrq.h'.
|
||||||
|
|
||||||
After the sysrq_key_op is created, you can call the macro
|
After the sysrq_key_op is created, you can call the kernel function
|
||||||
register_sysrq_key(int key, struct sysrq_key_op *op_p) that is defined in
|
register_sysrq_key(int key, struct sysrq_key_op *op_p); this will
|
||||||
sysrq.h, this will register the operation pointed to by 'op_p' at table
|
register the operation pointed to by 'op_p' at table key 'key',
|
||||||
key 'key', if that slot in the table is blank. At module unload time, you must
|
if that slot in the table is blank. At module unload time, you must call
|
||||||
call the macro unregister_sysrq_key(int key, struct sysrq_key_op *op_p), which
|
the function unregister_sysrq_key(int key, struct sysrq_key_op *op_p), which
|
||||||
will remove the key op pointed to by 'op_p' from the key 'key', if and only if
|
will remove the key op pointed to by 'op_p' from the key 'key', if and only if
|
||||||
it is currently registered in that slot. This is in case the slot has been
|
it is currently registered in that slot. This is in case the slot has been
|
||||||
overwritten since you registered it.
|
overwritten since you registered it.
|
||||||
|
@ -186,15 +193,12 @@ overwritten since you registered it.
|
||||||
The Magic SysRQ system works by registering key operations against a key op
|
The Magic SysRQ system works by registering key operations against a key op
|
||||||
lookup table, which is defined in 'drivers/char/sysrq.c'. This key table has
|
lookup table, which is defined in 'drivers/char/sysrq.c'. This key table has
|
||||||
a number of operations registered into it at compile time, but is mutable,
|
a number of operations registered into it at compile time, but is mutable,
|
||||||
and 4 functions are exported for interface to it: __sysrq_lock_table,
|
and 2 functions are exported for interface to it:
|
||||||
__sysrq_unlock_table, __sysrq_get_key_op, and __sysrq_put_key_op. The
|
register_sysrq_key and unregister_sysrq_key.
|
||||||
functions __sysrq_swap_key_ops and __sysrq_swap_key_ops_nolock are defined
|
Of course, never ever leave an invalid pointer in the table. I.e., when
|
||||||
in the header itself, and the REGISTER and UNREGISTER macros are built from
|
your module that called register_sysrq_key() exits, it must call
|
||||||
these. More complex (and dangerous!) manipulations of the table are possible
|
unregister_sysrq_key() to clean up the sysrq key table entry that it used.
|
||||||
using these functions, but you must be careful to always lock the table before
|
Null pointers in the table are always safe. :)
|
||||||
you read or write from it, and to unlock it again when you are done. (And of
|
|
||||||
course, to never ever leave an invalid pointer in the table). Null pointers in
|
|
||||||
the table are always safe :)
|
|
||||||
|
|
||||||
If for some reason you feel the need to call the handle_sysrq function from
|
If for some reason you feel the need to call the handle_sysrq function from
|
||||||
within a function called by handle_sysrq, you must be aware that you are in
|
within a function called by handle_sysrq, you must be aware that you are in
|
||||||
|
|
|
@ -213,15 +213,16 @@ C:* #Ifs=dd Cfg#=dd Atr=xx MPwr=dddmA
|
||||||
|
|
||||||
Interface descriptor info (can be multiple per Config):
|
Interface descriptor info (can be multiple per Config):
|
||||||
|
|
||||||
I: If#=dd Alt=dd #EPs=dd Cls=xx(sssss) Sub=xx Prot=xx Driver=ssss
|
I:* If#=dd Alt=dd #EPs=dd Cls=xx(sssss) Sub=xx Prot=xx Driver=ssss
|
||||||
| | | | | | | |__Driver name
|
| | | | | | | | |__Driver name
|
||||||
| | | | | | | or "(none)"
|
| | | | | | | | or "(none)"
|
||||||
| | | | | | |__InterfaceProtocol
|
| | | | | | | |__InterfaceProtocol
|
||||||
| | | | | |__InterfaceSubClass
|
| | | | | | |__InterfaceSubClass
|
||||||
| | | | |__InterfaceClass
|
| | | | | |__InterfaceClass
|
||||||
| | | |__NumberOfEndpoints
|
| | | | |__NumberOfEndpoints
|
||||||
| | |__AlternateSettingNumber
|
| | | |__AlternateSettingNumber
|
||||||
| |__InterfaceNumber
|
| | |__InterfaceNumber
|
||||||
|
| |__ "*" indicates the active altsetting (others are " ")
|
||||||
|__Interface info tag
|
|__Interface info tag
|
||||||
|
|
||||||
A given interface may have one or more "alternate" settings.
|
A given interface may have one or more "alternate" settings.
|
||||||
|
@ -277,7 +278,7 @@ of the USB devices on a system's root hub. (See more below
|
||||||
on how to do this.)
|
on how to do this.)
|
||||||
|
|
||||||
The Interface lines can be used to determine what driver is
|
The Interface lines can be used to determine what driver is
|
||||||
being used for each device.
|
being used for each device, and which altsetting it activated.
|
||||||
|
|
||||||
The Configuration lines could be used to list maximum power
|
The Configuration lines could be used to list maximum power
|
||||||
(in milliamps) that a system's USB devices are using.
|
(in milliamps) that a system's USB devices are using.
|
||||||
|
|
|
@ -77,7 +77,7 @@ that the file size is not excessive for your favourite editor.
|
||||||
|
|
||||||
The '1t' type data consists of a stream of events, such as URB submission,
|
The '1t' type data consists of a stream of events, such as URB submission,
|
||||||
URB callback, submission error. Every event is a text line, which consists
|
URB callback, submission error. Every event is a text line, which consists
|
||||||
of whitespace separated words. The number of position of words may depend
|
of whitespace separated words. The number or position of words may depend
|
||||||
on the event type, but there is a set of words, common for all types.
|
on the event type, but there is a set of words, common for all types.
|
||||||
|
|
||||||
Here is the list of words, from left to right:
|
Here is the list of words, from left to right:
|
||||||
|
@ -170,4 +170,152 @@ dd65f0e8 4128379808 C Bo:005:02 0 31 >
|
||||||
|
|
||||||
* Raw binary format and API
|
* Raw binary format and API
|
||||||
|
|
||||||
TBD
|
The overall architecture of the API is about the same as the one above,
|
||||||
|
only the events are delivered in binary format. Each event is sent in
|
||||||
|
the following structure (its name is made up, so that we can refer to it):
|
||||||
|
|
||||||
|
struct usbmon_packet {
|
||||||
|
u64 id; /* 0: URB ID - from submission to callback */
|
||||||
|
unsigned char type; /* 8: Same as text; extensible. */
|
||||||
|
unsigned char xfer_type; /* ISO (0), Intr, Control, Bulk (3) */
|
||||||
|
unsigned char epnum; /* Endpoint number and transfer direction */
|
||||||
|
unsigned char devnum; /* Device address */
|
||||||
|
u16 busnum; /* 12: Bus number */
|
||||||
|
char flag_setup; /* 14: Same as text */
|
||||||
|
char flag_data; /* 15: Same as text; Binary zero is OK. */
|
||||||
|
s64 ts_sec; /* 16: gettimeofday */
|
||||||
|
s32 ts_usec; /* 24: gettimeofday */
|
||||||
|
int status; /* 28: */
|
||||||
|
unsigned int length; /* 32: Length of data (submitted or actual) */
|
||||||
|
unsigned int len_cap; /* 36: Delivered length */
|
||||||
|
unsigned char setup[8]; /* 40: Only for Control 'S' */
|
||||||
|
}; /* 48 bytes total */
|
||||||
|
|
||||||
|
These events can be received from a character device by reading with read(2),
|
||||||
|
with an ioctl(2), or by accessing the buffer with mmap.
|
||||||
|
|
||||||
|
The character device is usually called /dev/usbmonN, where N is the USB bus
|
||||||
|
number. Number zero (/dev/usbmon0) is special and means "all buses".
|
||||||
|
However, this feature is not implemented yet. Note that specific naming
|
||||||
|
policy is set by your Linux distribution.
|
||||||
|
|
||||||
|
If you create /dev/usbmon0 by hand, make sure that it is owned by root
|
||||||
|
and has mode 0600. Otherwise, unpriviledged users will be able to snoop
|
||||||
|
keyboard traffic.
|
||||||
|
|
||||||
|
The following ioctl calls are available, with MON_IOC_MAGIC 0x92:
|
||||||
|
|
||||||
|
MON_IOCQ_URB_LEN, defined as _IO(MON_IOC_MAGIC, 1)
|
||||||
|
|
||||||
|
This call returns the length of data in the next event. Note that majority of
|
||||||
|
events contain no data, so if this call returns zero, it does not mean that
|
||||||
|
no events are available.
|
||||||
|
|
||||||
|
MON_IOCG_STATS, defined as _IOR(MON_IOC_MAGIC, 3, struct mon_bin_stats)
|
||||||
|
|
||||||
|
The argument is a pointer to the following structure:
|
||||||
|
|
||||||
|
struct mon_bin_stats {
|
||||||
|
u32 queued;
|
||||||
|
u32 dropped;
|
||||||
|
};
|
||||||
|
|
||||||
|
The member "queued" refers to the number of events currently queued in the
|
||||||
|
buffer (and not to the number of events processed since the last reset).
|
||||||
|
|
||||||
|
The member "dropped" is the number of events lost since the last call
|
||||||
|
to MON_IOCG_STATS.
|
||||||
|
|
||||||
|
MON_IOCT_RING_SIZE, defined as _IO(MON_IOC_MAGIC, 4)
|
||||||
|
|
||||||
|
This call sets the buffer size. The argument is the size in bytes.
|
||||||
|
The size may be rounded down to the next chunk (or page). If the requested
|
||||||
|
size is out of [unspecified] bounds for this kernel, the call fails with
|
||||||
|
-EINVAL.
|
||||||
|
|
||||||
|
MON_IOCQ_RING_SIZE, defined as _IO(MON_IOC_MAGIC, 5)
|
||||||
|
|
||||||
|
This call returns the current size of the buffer in bytes.
|
||||||
|
|
||||||
|
MON_IOCX_GET, defined as _IOW(MON_IOC_MAGIC, 6, struct mon_get_arg)
|
||||||
|
|
||||||
|
This call waits for events to arrive if none were in the kernel buffer,
|
||||||
|
then returns the first event. Its argument is a pointer to the following
|
||||||
|
structure:
|
||||||
|
|
||||||
|
struct mon_get_arg {
|
||||||
|
struct usbmon_packet *hdr;
|
||||||
|
void *data;
|
||||||
|
size_t alloc; /* Length of data (can be zero) */
|
||||||
|
};
|
||||||
|
|
||||||
|
Before the call, hdr, data, and alloc should be filled. Upon return, the area
|
||||||
|
pointed by hdr contains the next event structure, and the data buffer contains
|
||||||
|
the data, if any. The event is removed from the kernel buffer.
|
||||||
|
|
||||||
|
MON_IOCX_MFETCH, defined as _IOWR(MON_IOC_MAGIC, 7, struct mon_mfetch_arg)
|
||||||
|
|
||||||
|
This ioctl is primarily used when the application accesses the buffer
|
||||||
|
with mmap(2). Its argument is a pointer to the following structure:
|
||||||
|
|
||||||
|
struct mon_mfetch_arg {
|
||||||
|
uint32_t *offvec; /* Vector of events fetched */
|
||||||
|
uint32_t nfetch; /* Number of events to fetch (out: fetched) */
|
||||||
|
uint32_t nflush; /* Number of events to flush */
|
||||||
|
};
|
||||||
|
|
||||||
|
The ioctl operates in 3 stages.
|
||||||
|
|
||||||
|
First, it removes and discards up to nflush events from the kernel buffer.
|
||||||
|
The actual number of events discarded is returned in nflush.
|
||||||
|
|
||||||
|
Second, it waits for an event to be present in the buffer, unless the pseudo-
|
||||||
|
device is open with O_NONBLOCK.
|
||||||
|
|
||||||
|
Third, it extracts up to nfetch offsets into the mmap buffer, and stores
|
||||||
|
them into the offvec. The actual number of event offsets is stored into
|
||||||
|
the nfetch.
|
||||||
|
|
||||||
|
MON_IOCH_MFLUSH, defined as _IO(MON_IOC_MAGIC, 8)
|
||||||
|
|
||||||
|
This call removes a number of events from the kernel buffer. Its argument
|
||||||
|
is the number of events to remove. If the buffer contains fewer events
|
||||||
|
than requested, all events present are removed, and no error is reported.
|
||||||
|
This works when no events are available too.
|
||||||
|
|
||||||
|
FIONBIO
|
||||||
|
|
||||||
|
The ioctl FIONBIO may be implemented in the future, if there's a need.
|
||||||
|
|
||||||
|
In addition to ioctl(2) and read(2), the special file of binary API can
|
||||||
|
be polled with select(2) and poll(2). But lseek(2) does not work.
|
||||||
|
|
||||||
|
* Memory-mapped access of the kernel buffer for the binary API
|
||||||
|
|
||||||
|
The basic idea is simple:
|
||||||
|
|
||||||
|
To prepare, map the buffer by getting the current size, then using mmap(2).
|
||||||
|
Then, execute a loop similar to the one written in pseudo-code below:
|
||||||
|
|
||||||
|
struct mon_mfetch_arg fetch;
|
||||||
|
struct usbmon_packet *hdr;
|
||||||
|
int nflush = 0;
|
||||||
|
for (;;) {
|
||||||
|
fetch.offvec = vec; // Has N 32-bit words
|
||||||
|
fetch.nfetch = N; // Or less than N
|
||||||
|
fetch.nflush = nflush;
|
||||||
|
ioctl(fd, MON_IOCX_MFETCH, &fetch); // Process errors, too
|
||||||
|
nflush = fetch.nfetch; // This many packets to flush when done
|
||||||
|
for (i = 0; i < nflush; i++) {
|
||||||
|
hdr = (struct ubsmon_packet *) &mmap_area[vec[i]];
|
||||||
|
if (hdr->type == '@') // Filler packet
|
||||||
|
continue;
|
||||||
|
caddr_t data = &mmap_area[vec[i]] + 64;
|
||||||
|
process_packet(hdr, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Thus, the main idea is to execute only one ioctl per N events.
|
||||||
|
|
||||||
|
Although the buffer is circular, the returned headers and data do not cross
|
||||||
|
the end of the buffer, so the above pseudo-code does not need any gathering.
|
||||||
|
|
34
Documentation/video-output.txt
Normal file
34
Documentation/video-output.txt
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
|
||||||
|
Video Output Switcher Control
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
2006 luming.yu@intel.com
|
||||||
|
|
||||||
|
The output sysfs class driver provides an abstract video output layer that
|
||||||
|
can be used to hook platform specific methods to enable/disable video output
|
||||||
|
device through common sysfs interface. For example, on my IBM ThinkPad T42
|
||||||
|
laptop, The ACPI video driver registered its output devices and read/write
|
||||||
|
method for 'state' with output sysfs class. The user interface under sysfs is:
|
||||||
|
|
||||||
|
linux:/sys/class/video_output # tree .
|
||||||
|
.
|
||||||
|
|-- CRT0
|
||||||
|
| |-- device -> ../../../devices/pci0000:00/0000:00:01.0
|
||||||
|
| |-- state
|
||||||
|
| |-- subsystem -> ../../../class/video_output
|
||||||
|
| `-- uevent
|
||||||
|
|-- DVI0
|
||||||
|
| |-- device -> ../../../devices/pci0000:00/0000:00:01.0
|
||||||
|
| |-- state
|
||||||
|
| |-- subsystem -> ../../../class/video_output
|
||||||
|
| `-- uevent
|
||||||
|
|-- LCD0
|
||||||
|
| |-- device -> ../../../devices/pci0000:00/0000:00:01.0
|
||||||
|
| |-- state
|
||||||
|
| |-- subsystem -> ../../../class/video_output
|
||||||
|
| `-- uevent
|
||||||
|
`-- TV0
|
||||||
|
|-- device -> ../../../devices/pci0000:00/0000:00:01.0
|
||||||
|
|-- state
|
||||||
|
|-- subsystem -> ../../../class/video_output
|
||||||
|
`-- uevent
|
||||||
|
|
63
MAINTAINERS
63
MAINTAINERS
|
@ -584,12 +584,30 @@ W: http://sourceforge.net/projects/acpi4asus
|
||||||
W: http://xf.iksaif.net/acpi4asus
|
W: http://xf.iksaif.net/acpi4asus
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
|
ASUS LAPTOP EXTRAS DRIVER
|
||||||
|
P: Corentin Chary
|
||||||
|
M: corentincj@iksaif.net
|
||||||
|
L: acpi4asus-user@lists.sourceforge.net
|
||||||
|
W: http://sourceforge.net/projects/acpi4asus
|
||||||
|
W: http://xf.iksaif.net/acpi4asus
|
||||||
|
S: Maintained
|
||||||
|
|
||||||
ATA OVER ETHERNET DRIVER
|
ATA OVER ETHERNET DRIVER
|
||||||
P: Ed L. Cashin
|
P: Ed L. Cashin
|
||||||
M: ecashin@coraid.com
|
M: ecashin@coraid.com
|
||||||
W: http://www.coraid.com/support/linux
|
W: http://www.coraid.com/support/linux
|
||||||
S: Supported
|
S: Supported
|
||||||
|
|
||||||
|
ATL1 ETHERNET DRIVER
|
||||||
|
P: Jay Cliburn
|
||||||
|
M: jcliburn@gmail.com
|
||||||
|
P: Chris Snook
|
||||||
|
M: csnook@redhat.com
|
||||||
|
L: atl1-devel@lists.sourceforge.net
|
||||||
|
W: http://sourceforge.net/projects/atl1
|
||||||
|
W: http://atl1.sourceforge.net
|
||||||
|
S: Maintained
|
||||||
|
|
||||||
ATM
|
ATM
|
||||||
P: Chas Williams
|
P: Chas Williams
|
||||||
M: chas@cmf.nrl.navy.mil
|
M: chas@cmf.nrl.navy.mil
|
||||||
|
@ -598,8 +616,6 @@ W: http://linux-atm.sourceforge.net
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
ATMEL MACB ETHERNET DRIVER
|
ATMEL MACB ETHERNET DRIVER
|
||||||
P: Atmel AVR32 Support Team
|
|
||||||
M: avr32@atmel.com
|
|
||||||
P: Haavard Skinnemoen
|
P: Haavard Skinnemoen
|
||||||
M: hskinnemoen@atmel.com
|
M: hskinnemoen@atmel.com
|
||||||
S: Supported
|
S: Supported
|
||||||
|
@ -620,8 +636,6 @@ T: git kernel.org:/pub/scm/linux/kernel/git/dwmw2/audit-2.6.git
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
AVR32 ARCHITECTURE
|
AVR32 ARCHITECTURE
|
||||||
P: Atmel AVR32 Support Team
|
|
||||||
M: avr32@atmel.com
|
|
||||||
P: Haavard Skinnemoen
|
P: Haavard Skinnemoen
|
||||||
M: hskinnemoen@atmel.com
|
M: hskinnemoen@atmel.com
|
||||||
W: http://www.atmel.com/products/AVR32/
|
W: http://www.atmel.com/products/AVR32/
|
||||||
|
@ -630,8 +644,6 @@ W: http://avrfreaks.net/
|
||||||
S: Supported
|
S: Supported
|
||||||
|
|
||||||
AVR32/AT32AP MACHINE SUPPORT
|
AVR32/AT32AP MACHINE SUPPORT
|
||||||
P: Atmel AVR32 Support Team
|
|
||||||
M: avr32@atmel.com
|
|
||||||
P: Haavard Skinnemoen
|
P: Haavard Skinnemoen
|
||||||
M: hskinnemoen@atmel.com
|
M: hskinnemoen@atmel.com
|
||||||
S: Supported
|
S: Supported
|
||||||
|
@ -1102,7 +1114,7 @@ S: Supported
|
||||||
DAVICOM FAST ETHERNET (DMFE) NETWORK DRIVER
|
DAVICOM FAST ETHERNET (DMFE) NETWORK DRIVER
|
||||||
P: Tobias Ringstrom
|
P: Tobias Ringstrom
|
||||||
M: tori@unhappy.mine.nu
|
M: tori@unhappy.mine.nu
|
||||||
L: linux-kernel@vger.kernel.org
|
L: netdev@vger.kernel.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
DOCBOOK FOR DOCUMENTATION
|
DOCBOOK FOR DOCUMENTATION
|
||||||
|
@ -2288,7 +2300,7 @@ P: Jozsef Kadlecsik
|
||||||
P: Patrick McHardy
|
P: Patrick McHardy
|
||||||
M: kaber@trash.net
|
M: kaber@trash.net
|
||||||
L: netfilter-devel@lists.netfilter.org
|
L: netfilter-devel@lists.netfilter.org
|
||||||
L: netfilter@lists.netfilter.org
|
L: netfilter@lists.netfilter.org (subscribers-only)
|
||||||
L: coreteam@netfilter.org
|
L: coreteam@netfilter.org
|
||||||
W: http://www.netfilter.org/
|
W: http://www.netfilter.org/
|
||||||
W: http://www.iptables.org/
|
W: http://www.iptables.org/
|
||||||
|
@ -2349,7 +2361,7 @@ S: Maintained
|
||||||
NETWORKING [WIRELESS]
|
NETWORKING [WIRELESS]
|
||||||
P: John W. Linville
|
P: John W. Linville
|
||||||
M: linville@tuxdriver.com
|
M: linville@tuxdriver.com
|
||||||
L: netdev@vger.kernel.org
|
L: linux-wireless@vger.kernel.org
|
||||||
T: git kernel.org:/pub/scm/linux/kernel/git/linville/wireless-2.6.git
|
T: git kernel.org:/pub/scm/linux/kernel/git/linville/wireless-2.6.git
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
|
@ -2483,6 +2495,12 @@ L: orinoco-devel@lists.sourceforge.net
|
||||||
W: http://www.nongnu.org/orinoco/
|
W: http://www.nongnu.org/orinoco/
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
|
PA SEMI ETHERNET DRIVER
|
||||||
|
P: Olof Johansson
|
||||||
|
M: olof@lixom.net
|
||||||
|
L: netdev@vger.kernel.org
|
||||||
|
S: Maintained
|
||||||
|
|
||||||
PARALLEL PORT SUPPORT
|
PARALLEL PORT SUPPORT
|
||||||
P: Phil Blundell
|
P: Phil Blundell
|
||||||
M: philb@gnu.org
|
M: philb@gnu.org
|
||||||
|
@ -2652,7 +2670,7 @@ S: Supported
|
||||||
|
|
||||||
PRISM54 WIRELESS DRIVER
|
PRISM54 WIRELESS DRIVER
|
||||||
P: Prism54 Development Team
|
P: Prism54 Development Team
|
||||||
M: prism54-private@prism54.org
|
M: developers@islsm.org
|
||||||
L: netdev@vger.kernel.org
|
L: netdev@vger.kernel.org
|
||||||
W: http://prism54.org
|
W: http://prism54.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
@ -2797,7 +2815,7 @@ M: schwidefsky@de.ibm.com
|
||||||
P: Heiko Carstens
|
P: Heiko Carstens
|
||||||
M: heiko.carstens@de.ibm.com
|
M: heiko.carstens@de.ibm.com
|
||||||
M: linux390@de.ibm.com
|
M: linux390@de.ibm.com
|
||||||
L: linux-390@vm.marist.edu
|
L: linux-s390@vger.kernel.org
|
||||||
W: http://www.ibm.com/developerworks/linux/linux390/
|
W: http://www.ibm.com/developerworks/linux/linux390/
|
||||||
S: Supported
|
S: Supported
|
||||||
|
|
||||||
|
@ -2805,7 +2823,7 @@ S390 NETWORK DRIVERS
|
||||||
P: Frank Pavlic
|
P: Frank Pavlic
|
||||||
M: fpavlic@de.ibm.com
|
M: fpavlic@de.ibm.com
|
||||||
M: linux390@de.ibm.com
|
M: linux390@de.ibm.com
|
||||||
L: linux-390@vm.marist.edu
|
L: linux-s390@vger.kernel.org
|
||||||
W: http://www.ibm.com/developerworks/linux/linux390/
|
W: http://www.ibm.com/developerworks/linux/linux390/
|
||||||
S: Supported
|
S: Supported
|
||||||
|
|
||||||
|
@ -2813,7 +2831,7 @@ S390 ZFCP DRIVER
|
||||||
P: Swen Schillig
|
P: Swen Schillig
|
||||||
M: swen@vnet.ibm.com
|
M: swen@vnet.ibm.com
|
||||||
M: linux390@de.ibm.com
|
M: linux390@de.ibm.com
|
||||||
L: linux-390@vm.marist.edu
|
L: linux-s390@vger.kernel.org
|
||||||
W: http://www.ibm.com/developerworks/linux/linux390/
|
W: http://www.ibm.com/developerworks/linux/linux390/
|
||||||
S: Supported
|
S: Supported
|
||||||
|
|
||||||
|
@ -3019,6 +3037,12 @@ M: perex@suse.cz
|
||||||
L: alsa-devel@alsa-project.org
|
L: alsa-devel@alsa-project.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
|
SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT
|
||||||
|
P: Liam Girdwood
|
||||||
|
M: liam.girdwood@wolfsonmicro.com
|
||||||
|
L: alsa-devel@alsa-project.org
|
||||||
|
S: Supported
|
||||||
|
|
||||||
SPI SUBSYSTEM
|
SPI SUBSYSTEM
|
||||||
P: David Brownell
|
P: David Brownell
|
||||||
M: dbrownell@users.sourceforge.net
|
M: dbrownell@users.sourceforge.net
|
||||||
|
@ -3269,6 +3293,11 @@ L: vtun@office.satix.net
|
||||||
W: http://vtun.sourceforge.net/tun
|
W: http://vtun.sourceforge.net/tun
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
|
TURBOCHANNEL SUBSYSTEM
|
||||||
|
P: Maciej W. Rozycki
|
||||||
|
M: macro@linux-mips.org
|
||||||
|
S: Maintained
|
||||||
|
|
||||||
U14-34F SCSI DRIVER
|
U14-34F SCSI DRIVER
|
||||||
P: Dario Ballabio
|
P: Dario Ballabio
|
||||||
M: ballabio_dario@emc.com
|
M: ballabio_dario@emc.com
|
||||||
|
@ -3599,6 +3628,12 @@ M: ysato@users.sourceforge.jp
|
||||||
W: http://uclinux-h8.sourceforge.jp/
|
W: http://uclinux-h8.sourceforge.jp/
|
||||||
S: Supported
|
S: Supported
|
||||||
|
|
||||||
|
UFS FILESYSTEM
|
||||||
|
P: Evgeniy Dushistov
|
||||||
|
M: dushistov@mail.ru
|
||||||
|
L: linux-kernel@vger.kernel.org
|
||||||
|
S: Maintained
|
||||||
|
|
||||||
USB DIAMOND RIO500 DRIVER
|
USB DIAMOND RIO500 DRIVER
|
||||||
P: Cesar Miquel
|
P: Cesar Miquel
|
||||||
M: miquel@df.uba.ar
|
M: miquel@df.uba.ar
|
||||||
|
@ -3647,7 +3682,7 @@ S: Maintained
|
||||||
W83L51xD SD/MMC CARD INTERFACE DRIVER
|
W83L51xD SD/MMC CARD INTERFACE DRIVER
|
||||||
P: Pierre Ossman
|
P: Pierre Ossman
|
||||||
M: drzeus-wbsd@drzeus.cx
|
M: drzeus-wbsd@drzeus.cx
|
||||||
L: wbsd-devel@list.drzeus.cx
|
L: linux-kernel@vger.kernel.org
|
||||||
W: http://projects.drzeus.cx/wbsd
|
W: http://projects.drzeus.cx/wbsd
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
|
|
19
Makefile
19
Makefile
|
@ -1,7 +1,7 @@
|
||||||
VERSION = 2
|
VERSION = 2
|
||||||
PATCHLEVEL = 6
|
PATCHLEVEL = 6
|
||||||
SUBLEVEL = 20
|
SUBLEVEL = 20
|
||||||
EXTRAVERSION =-rc7
|
EXTRAVERSION =
|
||||||
NAME = Homicidal Dwarf Hamster
|
NAME = Homicidal Dwarf Hamster
|
||||||
|
|
||||||
# *DOCUMENTATION*
|
# *DOCUMENTATION*
|
||||||
|
@ -776,7 +776,7 @@ $(vmlinux-dirs): prepare scripts
|
||||||
# $(EXTRAVERSION) eg, -rc6
|
# $(EXTRAVERSION) eg, -rc6
|
||||||
# $(localver-full)
|
# $(localver-full)
|
||||||
# $(localver)
|
# $(localver)
|
||||||
# localversion* (all localversion* files)
|
# localversion* (files without backups, containing '~')
|
||||||
# $(CONFIG_LOCALVERSION) (from kernel config setting)
|
# $(CONFIG_LOCALVERSION) (from kernel config setting)
|
||||||
# $(localver-auto) (only if CONFIG_LOCALVERSION_AUTO is set)
|
# $(localver-auto) (only if CONFIG_LOCALVERSION_AUTO is set)
|
||||||
# ./scripts/setlocalversion (SCM tag, if one exists)
|
# ./scripts/setlocalversion (SCM tag, if one exists)
|
||||||
|
@ -787,17 +787,12 @@ $(vmlinux-dirs): prepare scripts
|
||||||
# moment, only git is supported but other SCMs can edit the script
|
# moment, only git is supported but other SCMs can edit the script
|
||||||
# scripts/setlocalversion and add the appropriate checks as needed.
|
# scripts/setlocalversion and add the appropriate checks as needed.
|
||||||
|
|
||||||
nullstring :=
|
pattern = ".*/localversion[^~]*"
|
||||||
space := $(nullstring) # end of line
|
string = $(shell cat /dev/null \
|
||||||
|
`find $(objtree) $(srctree) -maxdepth 1 -regex $(pattern) | sort`)
|
||||||
|
|
||||||
___localver = $(objtree)/localversion* $(srctree)/localversion*
|
localver = $(subst $(space),, $(string) \
|
||||||
__localver = $(sort $(wildcard $(___localver)))
|
$(patsubst "%",%,$(CONFIG_LOCALVERSION)))
|
||||||
# skip backup files (containing '~')
|
|
||||||
_localver = $(foreach f, $(__localver), $(if $(findstring ~, $(f)),,$(f)))
|
|
||||||
|
|
||||||
localver = $(subst $(space),, \
|
|
||||||
$(shell cat /dev/null $(_localver)) \
|
|
||||||
$(patsubst "%",%,$(CONFIG_LOCALVERSION)))
|
|
||||||
|
|
||||||
# If CONFIG_LOCALVERSION_AUTO is set scripts/setlocalversion is called
|
# If CONFIG_LOCALVERSION_AUTO is set scripts/setlocalversion is called
|
||||||
# and if the SCM is know a tag from the SCM is appended.
|
# and if the SCM is know a tag from the SCM is appended.
|
||||||
|
|
|
@ -575,3 +575,7 @@ void pci_iounmap(struct pci_dev *dev, void __iomem * addr)
|
||||||
|
|
||||||
EXPORT_SYMBOL(pci_iomap);
|
EXPORT_SYMBOL(pci_iomap);
|
||||||
EXPORT_SYMBOL(pci_iounmap);
|
EXPORT_SYMBOL(pci_iounmap);
|
||||||
|
|
||||||
|
/* FIXME: Some boxes have multiple ISA bridges! */
|
||||||
|
struct pci_dev *isa_bridge;
|
||||||
|
EXPORT_SYMBOL(isa_bridge);
|
||||||
|
|
|
@ -9,6 +9,7 @@ config ARM
|
||||||
bool
|
bool
|
||||||
default y
|
default y
|
||||||
select RTC_LIB
|
select RTC_LIB
|
||||||
|
select SYS_SUPPORTS_APM_EMULATION
|
||||||
help
|
help
|
||||||
The ARM series is a line of low-power-consumption RISC chip designs
|
The ARM series is a line of low-power-consumption RISC chip designs
|
||||||
licensed by ARM Ltd and targeted at embedded applications and
|
licensed by ARM Ltd and targeted at embedded applications and
|
||||||
|
@ -17,6 +18,9 @@ config ARM
|
||||||
Europe. There is an ARM Linux project with a web page at
|
Europe. There is an ARM Linux project with a web page at
|
||||||
<http://www.arm.linux.org.uk/>.
|
<http://www.arm.linux.org.uk/>.
|
||||||
|
|
||||||
|
config SYS_SUPPORTS_APM_EMULATION
|
||||||
|
bool
|
||||||
|
|
||||||
config GENERIC_TIME
|
config GENERIC_TIME
|
||||||
bool
|
bool
|
||||||
default n
|
default n
|
||||||
|
@ -856,31 +860,6 @@ menu "Power management options"
|
||||||
|
|
||||||
source "kernel/power/Kconfig"
|
source "kernel/power/Kconfig"
|
||||||
|
|
||||||
config APM
|
|
||||||
tristate "Advanced Power Management Emulation"
|
|
||||||
---help---
|
|
||||||
APM is a BIOS specification for saving power using several different
|
|
||||||
techniques. This is mostly useful for battery powered laptops with
|
|
||||||
APM compliant BIOSes. If you say Y here, the system time will be
|
|
||||||
reset after a RESUME operation, the /proc/apm device will provide
|
|
||||||
battery status information, and user-space programs will receive
|
|
||||||
notification of APM "events" (e.g. battery status change).
|
|
||||||
|
|
||||||
In order to use APM, you will need supporting software. For location
|
|
||||||
and more information, read <file:Documentation/pm.txt> and the
|
|
||||||
Battery Powered Linux mini-HOWTO, available from
|
|
||||||
<http://www.tldp.org/docs.html#howto>.
|
|
||||||
|
|
||||||
This driver does not spin down disk drives (see the hdparm(8)
|
|
||||||
manpage ("man 8 hdparm") for that), and it doesn't turn off
|
|
||||||
VESA-compliant "green" monitors.
|
|
||||||
|
|
||||||
Generally, if you don't have a battery in your machine, there isn't
|
|
||||||
much point in using this driver and you should say N. If you get
|
|
||||||
random kernel OOPSes or reboots that don't seem to be related to
|
|
||||||
anything, try disabling/enabling this option (or disabling/enabling
|
|
||||||
APM in your BIOS).
|
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|
||||||
source "net/Kconfig"
|
source "net/Kconfig"
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
#include <asm/hardware.h>
|
#include <asm/hardware.h>
|
||||||
#include <asm/mach-types.h>
|
#include <asm/mach-types.h>
|
||||||
#include <asm/irq.h>
|
#include <asm/irq.h>
|
||||||
#include <asm/apm.h>
|
#include <asm/apm-emulation.h>
|
||||||
#include <asm/arch/pm.h>
|
#include <asm/arch/pm.h>
|
||||||
#include <asm/arch/pxa-regs.h>
|
#include <asm/arch/pxa-regs.h>
|
||||||
#include <asm/arch/sharpsl.h>
|
#include <asm/arch/sharpsl.h>
|
||||||
|
|
|
@ -10,7 +10,6 @@ obj-y := compat.o entry-armv.o entry-common.o irq.o \
|
||||||
process.o ptrace.o semaphore.o setup.o signal.o sys_arm.o \
|
process.o ptrace.o semaphore.o setup.o signal.o sys_arm.o \
|
||||||
time.o traps.o
|
time.o traps.o
|
||||||
|
|
||||||
obj-$(CONFIG_APM) += apm.o
|
|
||||||
obj-$(CONFIG_ISA_DMA_API) += dma.o
|
obj-$(CONFIG_ISA_DMA_API) += dma.o
|
||||||
obj-$(CONFIG_ARCH_ACORN) += ecard.o
|
obj-$(CONFIG_ARCH_ACORN) += ecard.o
|
||||||
obj-$(CONFIG_FIQ) += fiq.o
|
obj-$(CONFIG_FIQ) += fiq.o
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <asm/apm.h>
|
#include <asm/apm-emulation.h>
|
||||||
#include <asm/irq.h>
|
#include <asm/irq.h>
|
||||||
#include <asm/mach-types.h>
|
#include <asm/mach-types.h>
|
||||||
#include <asm/hardware.h>
|
#include <asm/hardware.h>
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
|
|
||||||
#include <asm/hardware.h>
|
#include <asm/hardware.h>
|
||||||
#include <asm/mach-types.h>
|
#include <asm/mach-types.h>
|
||||||
#include <asm/apm.h>
|
#include <asm/apm-emulation.h>
|
||||||
#include <asm/arch/pm.h>
|
#include <asm/arch/pm.h>
|
||||||
#include <asm/arch/pxa-regs.h>
|
#include <asm/arch/pxa-regs.h>
|
||||||
#include <asm/arch/sharpsl.h>
|
#include <asm/arch/sharpsl.h>
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <asm/apm.h>
|
#include <asm/apm-emulation.h>
|
||||||
#include <asm/irq.h>
|
#include <asm/irq.h>
|
||||||
#include <asm/mach-types.h>
|
#include <asm/mach-types.h>
|
||||||
#include <asm/hardware.h>
|
#include <asm/hardware.h>
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
obj-y += setup.o spi.o flash.o
|
obj-y += setup.o flash.o
|
||||||
obj-$(CONFIG_BOARD_ATSTK1002) += atstk1002.o
|
obj-$(CONFIG_BOARD_ATSTK1002) += atstk1002.o
|
||||||
|
|
|
@ -8,17 +8,24 @@
|
||||||
* published by the Free Software Foundation.
|
* published by the Free Software Foundation.
|
||||||
*/
|
*/
|
||||||
#include <linux/clk.h>
|
#include <linux/clk.h>
|
||||||
|
#include <linux/device.h>
|
||||||
#include <linux/etherdevice.h>
|
#include <linux/etherdevice.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
#include <linux/spi/spi.h>
|
||||||
|
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include <asm/setup.h>
|
#include <asm/setup.h>
|
||||||
|
#include <asm/arch/at32ap7000.h>
|
||||||
#include <asm/arch/board.h>
|
#include <asm/arch/board.h>
|
||||||
#include <asm/arch/init.h>
|
#include <asm/arch/init.h>
|
||||||
|
#include <asm/arch/portmux.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define SW2_DEFAULT /* MMCI and UART_A available */
|
||||||
|
|
||||||
struct eth_addr {
|
struct eth_addr {
|
||||||
u8 addr[6];
|
u8 addr[6];
|
||||||
|
@ -29,6 +36,16 @@ static struct eth_addr __initdata hw_addr[2];
|
||||||
static struct eth_platform_data __initdata eth_data[2];
|
static struct eth_platform_data __initdata eth_data[2];
|
||||||
extern struct lcdc_platform_data atstk1000_fb0_data;
|
extern struct lcdc_platform_data atstk1000_fb0_data;
|
||||||
|
|
||||||
|
static struct spi_board_info spi_board_info[] __initdata = {
|
||||||
|
{
|
||||||
|
.modalias = "ltv350qv",
|
||||||
|
.controller_data = (void *)GPIO_PIN_PA(4),
|
||||||
|
.max_speed_hz = 16000000,
|
||||||
|
.bus_num = 0,
|
||||||
|
.chip_select = 1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The next two functions should go away as the boot loader is
|
* The next two functions should go away as the boot loader is
|
||||||
* supposed to initialize the macb address registers with a valid
|
* supposed to initialize the macb address registers with a valid
|
||||||
|
@ -86,23 +103,53 @@ static void __init set_hw_addr(struct platform_device *pdev)
|
||||||
|
|
||||||
void __init setup_board(void)
|
void __init setup_board(void)
|
||||||
{
|
{
|
||||||
at32_map_usart(1, 0); /* /dev/ttyS0 */
|
#ifdef SW2_DEFAULT
|
||||||
at32_map_usart(2, 1); /* /dev/ttyS1 */
|
at32_map_usart(1, 0); /* USART 1/A: /dev/ttyS0, DB9 */
|
||||||
at32_map_usart(3, 2); /* /dev/ttyS2 */
|
#else
|
||||||
|
at32_map_usart(0, 1); /* USART 0/B: /dev/ttyS1, IRDA */
|
||||||
|
#endif
|
||||||
|
/* USART 2/unused: expansion connector */
|
||||||
|
at32_map_usart(3, 2); /* USART 3/C: /dev/ttyS2, DB9 */
|
||||||
|
|
||||||
at32_setup_serial_console(0);
|
at32_setup_serial_console(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init atstk1002_init(void)
|
static int __init atstk1002_init(void)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* ATSTK1000 uses 32-bit SDRAM interface. Reserve the
|
||||||
|
* SDRAM-specific pins so that nobody messes with them.
|
||||||
|
*/
|
||||||
|
at32_reserve_pin(GPIO_PIN_PE(0)); /* DATA[16] */
|
||||||
|
at32_reserve_pin(GPIO_PIN_PE(1)); /* DATA[17] */
|
||||||
|
at32_reserve_pin(GPIO_PIN_PE(2)); /* DATA[18] */
|
||||||
|
at32_reserve_pin(GPIO_PIN_PE(3)); /* DATA[19] */
|
||||||
|
at32_reserve_pin(GPIO_PIN_PE(4)); /* DATA[20] */
|
||||||
|
at32_reserve_pin(GPIO_PIN_PE(5)); /* DATA[21] */
|
||||||
|
at32_reserve_pin(GPIO_PIN_PE(6)); /* DATA[22] */
|
||||||
|
at32_reserve_pin(GPIO_PIN_PE(7)); /* DATA[23] */
|
||||||
|
at32_reserve_pin(GPIO_PIN_PE(8)); /* DATA[24] */
|
||||||
|
at32_reserve_pin(GPIO_PIN_PE(9)); /* DATA[25] */
|
||||||
|
at32_reserve_pin(GPIO_PIN_PE(10)); /* DATA[26] */
|
||||||
|
at32_reserve_pin(GPIO_PIN_PE(11)); /* DATA[27] */
|
||||||
|
at32_reserve_pin(GPIO_PIN_PE(12)); /* DATA[28] */
|
||||||
|
at32_reserve_pin(GPIO_PIN_PE(13)); /* DATA[29] */
|
||||||
|
at32_reserve_pin(GPIO_PIN_PE(14)); /* DATA[30] */
|
||||||
|
at32_reserve_pin(GPIO_PIN_PE(15)); /* DATA[31] */
|
||||||
|
at32_reserve_pin(GPIO_PIN_PE(26)); /* SDCS */
|
||||||
|
|
||||||
at32_add_system_devices();
|
at32_add_system_devices();
|
||||||
|
|
||||||
|
#ifdef SW2_DEFAULT
|
||||||
at32_add_device_usart(0);
|
at32_add_device_usart(0);
|
||||||
|
#else
|
||||||
at32_add_device_usart(1);
|
at32_add_device_usart(1);
|
||||||
|
#endif
|
||||||
at32_add_device_usart(2);
|
at32_add_device_usart(2);
|
||||||
|
|
||||||
set_hw_addr(at32_add_device_eth(0, ð_data[0]));
|
set_hw_addr(at32_add_device_eth(0, ð_data[0]));
|
||||||
|
|
||||||
|
spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
|
||||||
at32_add_device_spi(0);
|
at32_add_device_spi(0);
|
||||||
at32_add_device_lcdc(0, &atstk1000_fb0_data);
|
at32_add_device_lcdc(0, &atstk1000_fb0_data);
|
||||||
|
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
/*
|
|
||||||
* ATSTK1000 SPI devices
|
|
||||||
*
|
|
||||||
* Copyright (C) 2005 Atmel Norway
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*/
|
|
||||||
#include <linux/device.h>
|
|
||||||
#include <linux/spi/spi.h>
|
|
||||||
|
|
||||||
static struct spi_board_info spi_board_info[] __initdata = {
|
|
||||||
{
|
|
||||||
.modalias = "ltv350qv",
|
|
||||||
.max_speed_hz = 16000000,
|
|
||||||
.bus_num = 0,
|
|
||||||
.chip_select = 1,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
static int board_init_spi(void)
|
|
||||||
{
|
|
||||||
spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
arch_initcall(board_init_spi);
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include <linux/sysdev.h>
|
#include <linux/sysdev.h>
|
||||||
#include <linux/seq_file.h>
|
#include <linux/seq_file.h>
|
||||||
#include <linux/cpu.h>
|
#include <linux/cpu.h>
|
||||||
|
#include <linux/module.h>
|
||||||
#include <linux/percpu.h>
|
#include <linux/percpu.h>
|
||||||
#include <linux/param.h>
|
#include <linux/param.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
|
|
|
@ -57,6 +57,7 @@ int show_interrupts(struct seq_file *p, void *v)
|
||||||
seq_printf(p, "%3d: ", i);
|
seq_printf(p, "%3d: ", i);
|
||||||
for_each_online_cpu(cpu)
|
for_each_online_cpu(cpu)
|
||||||
seq_printf(p, "%10u ", kstat_cpu(cpu).irqs[i]);
|
seq_printf(p, "%10u ", kstat_cpu(cpu).irqs[i]);
|
||||||
|
seq_printf(p, " %8s", irq_desc[i].chip->name ? : "-");
|
||||||
seq_printf(p, " %s", action->name);
|
seq_printf(p, " %s", action->name);
|
||||||
for (action = action->next; action; action = action->next)
|
for (action = action->next; action; action = action->next)
|
||||||
seq_printf(p, ", %s", action->name);
|
seq_printf(p, ", %s", action->name);
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/root_dev.h>
|
#include <linux/root_dev.h>
|
||||||
#include <linux/cpu.h>
|
#include <linux/cpu.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
|
||||||
#include <asm/sections.h>
|
#include <asm/sections.h>
|
||||||
#include <asm/processor.h>
|
#include <asm/processor.h>
|
||||||
|
@ -174,8 +175,7 @@ static int __init parse_tag_mem_range(struct tag *tag,
|
||||||
* Copy the data so the bootmem init code doesn't need to care
|
* Copy the data so the bootmem init code doesn't need to care
|
||||||
* about it.
|
* about it.
|
||||||
*/
|
*/
|
||||||
if (mem_range_next_free >=
|
if (mem_range_next_free >= ARRAY_SIZE(mem_range_cache))
|
||||||
(sizeof(mem_range_cache) / sizeof(mem_range_cache[0])))
|
|
||||||
panic("Physical memory map too complex!\n");
|
panic("Physical memory map too complex!\n");
|
||||||
|
|
||||||
new = &mem_range_cache[mem_range_next_free++];
|
new = &mem_range_cache[mem_range_next_free++];
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
/* Definitions for various functions 'borrowed' from gcc-3.4.3 */
|
|
||||||
|
|
||||||
#define BITS_PER_UNIT 8
|
|
||||||
|
|
||||||
typedef int QItype __attribute__ ((mode (QI)));
|
|
||||||
typedef unsigned int UQItype __attribute__ ((mode (QI)));
|
|
||||||
typedef int HItype __attribute__ ((mode (HI)));
|
|
||||||
typedef unsigned int UHItype __attribute__ ((mode (HI)));
|
|
||||||
typedef int SItype __attribute__ ((mode (SI)));
|
|
||||||
typedef unsigned int USItype __attribute__ ((mode (SI)));
|
|
||||||
typedef int DItype __attribute__ ((mode (DI)));
|
|
||||||
typedef unsigned int UDItype __attribute__ ((mode (DI)));
|
|
||||||
typedef float SFtype __attribute__ ((mode (SF)));
|
|
||||||
typedef float DFtype __attribute__ ((mode (DF)));
|
|
||||||
typedef int word_type __attribute__ ((mode (__word__)));
|
|
||||||
|
|
||||||
#define W_TYPE_SIZE (4 * BITS_PER_UNIT)
|
|
||||||
#define Wtype SItype
|
|
||||||
#define UWtype USItype
|
|
||||||
#define HWtype SItype
|
|
||||||
#define UHWtype USItype
|
|
||||||
#define DWtype DItype
|
|
||||||
#define UDWtype UDItype
|
|
||||||
#define __NW(a,b) __ ## a ## si ## b
|
|
||||||
#define __NDW(a,b) __ ## a ## di ## b
|
|
||||||
|
|
||||||
struct DWstruct {Wtype high, low;};
|
|
||||||
|
|
||||||
typedef union
|
|
||||||
{
|
|
||||||
struct DWstruct s;
|
|
||||||
DWtype ll;
|
|
||||||
} DWunion;
|
|
|
@ -1,98 +0,0 @@
|
||||||
/* longlong.h -- definitions for mixed size 32/64 bit arithmetic.
|
|
||||||
Copyright (C) 1991, 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2000
|
|
||||||
Free Software Foundation, Inc.
|
|
||||||
|
|
||||||
This definition file 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, or (at your option) any later version.
|
|
||||||
|
|
||||||
This definition file 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., 59 Temple Place - Suite 330,
|
|
||||||
Boston, MA 02111-1307, USA. */
|
|
||||||
|
|
||||||
/* Borrowed from gcc-3.4.3 */
|
|
||||||
|
|
||||||
#define __BITS4 (W_TYPE_SIZE / 4)
|
|
||||||
#define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2))
|
|
||||||
#define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1))
|
|
||||||
#define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2))
|
|
||||||
|
|
||||||
#define count_leading_zeros(count, x) ((count) = __builtin_clz(x))
|
|
||||||
|
|
||||||
#define __udiv_qrnnd_c(q, r, n1, n0, d) \
|
|
||||||
do { \
|
|
||||||
UWtype __d1, __d0, __q1, __q0; \
|
|
||||||
UWtype __r1, __r0, __m; \
|
|
||||||
__d1 = __ll_highpart (d); \
|
|
||||||
__d0 = __ll_lowpart (d); \
|
|
||||||
\
|
|
||||||
__r1 = (n1) % __d1; \
|
|
||||||
__q1 = (n1) / __d1; \
|
|
||||||
__m = (UWtype) __q1 * __d0; \
|
|
||||||
__r1 = __r1 * __ll_B | __ll_highpart (n0); \
|
|
||||||
if (__r1 < __m) \
|
|
||||||
{ \
|
|
||||||
__q1--, __r1 += (d); \
|
|
||||||
if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\
|
|
||||||
if (__r1 < __m) \
|
|
||||||
__q1--, __r1 += (d); \
|
|
||||||
} \
|
|
||||||
__r1 -= __m; \
|
|
||||||
\
|
|
||||||
__r0 = __r1 % __d1; \
|
|
||||||
__q0 = __r1 / __d1; \
|
|
||||||
__m = (UWtype) __q0 * __d0; \
|
|
||||||
__r0 = __r0 * __ll_B | __ll_lowpart (n0); \
|
|
||||||
if (__r0 < __m) \
|
|
||||||
{ \
|
|
||||||
__q0--, __r0 += (d); \
|
|
||||||
if (__r0 >= (d)) \
|
|
||||||
if (__r0 < __m) \
|
|
||||||
__q0--, __r0 += (d); \
|
|
||||||
} \
|
|
||||||
__r0 -= __m; \
|
|
||||||
\
|
|
||||||
(q) = (UWtype) __q1 * __ll_B | __q0; \
|
|
||||||
(r) = __r0; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define udiv_qrnnd __udiv_qrnnd_c
|
|
||||||
|
|
||||||
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
|
|
||||||
do { \
|
|
||||||
UWtype __x; \
|
|
||||||
__x = (al) - (bl); \
|
|
||||||
(sh) = (ah) - (bh) - (__x > (al)); \
|
|
||||||
(sl) = __x; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define umul_ppmm(w1, w0, u, v) \
|
|
||||||
do { \
|
|
||||||
UWtype __x0, __x1, __x2, __x3; \
|
|
||||||
UHWtype __ul, __vl, __uh, __vh; \
|
|
||||||
\
|
|
||||||
__ul = __ll_lowpart (u); \
|
|
||||||
__uh = __ll_highpart (u); \
|
|
||||||
__vl = __ll_lowpart (v); \
|
|
||||||
__vh = __ll_highpart (v); \
|
|
||||||
\
|
|
||||||
__x0 = (UWtype) __ul * __vl; \
|
|
||||||
__x1 = (UWtype) __ul * __vh; \
|
|
||||||
__x2 = (UWtype) __uh * __vl; \
|
|
||||||
__x3 = (UWtype) __uh * __vh; \
|
|
||||||
\
|
|
||||||
__x1 += __ll_highpart (__x0);/* this can't give carry */ \
|
|
||||||
__x1 += __x2; /* but this indeed can */ \
|
|
||||||
if (__x1 < __x2) /* did we get it? */ \
|
|
||||||
__x3 += __ll_B; /* yes, add it in the proper pos. */ \
|
|
||||||
\
|
|
||||||
(w1) = __x3 + __ll_highpart (__x1); \
|
|
||||||
(w0) = __ll_lowpart (__x1) * __ll_B + __ll_lowpart (__x0); \
|
|
||||||
} while (0)
|
|
|
@ -1,2 +1,2 @@
|
||||||
obj-y += at32ap.o clock.o pio.o intc.o extint.o hsmc.o
|
obj-y += at32ap.o clock.o intc.o extint.o pio.o hsmc.o
|
||||||
obj-$(CONFIG_CPU_AT32AP7000) += at32ap7000.o
|
obj-$(CONFIG_CPU_AT32AP7000) += at32ap7000.o
|
||||||
|
|
|
@ -496,9 +496,16 @@ static struct resource pio3_resource[] = {
|
||||||
DEFINE_DEV(pio, 3);
|
DEFINE_DEV(pio, 3);
|
||||||
DEV_CLK(mck, pio3, pba, 13);
|
DEV_CLK(mck, pio3, pba, 13);
|
||||||
|
|
||||||
|
static struct resource pio4_resource[] = {
|
||||||
|
PBMEM(0xffe03800),
|
||||||
|
IRQ(17),
|
||||||
|
};
|
||||||
|
DEFINE_DEV(pio, 4);
|
||||||
|
DEV_CLK(mck, pio4, pba, 14);
|
||||||
|
|
||||||
void __init at32_add_system_devices(void)
|
void __init at32_add_system_devices(void)
|
||||||
{
|
{
|
||||||
system_manager.eim_first_irq = NR_INTERNAL_IRQS;
|
system_manager.eim_first_irq = EIM_IRQ_BASE;
|
||||||
|
|
||||||
platform_device_register(&at32_sm_device);
|
platform_device_register(&at32_sm_device);
|
||||||
platform_device_register(&at32_intc0_device);
|
platform_device_register(&at32_intc0_device);
|
||||||
|
@ -509,6 +516,7 @@ void __init at32_add_system_devices(void)
|
||||||
platform_device_register(&pio1_device);
|
platform_device_register(&pio1_device);
|
||||||
platform_device_register(&pio2_device);
|
platform_device_register(&pio2_device);
|
||||||
platform_device_register(&pio3_device);
|
platform_device_register(&pio3_device);
|
||||||
|
platform_device_register(&pio4_device);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------
|
/* --------------------------------------------------------------------
|
||||||
|
@ -521,7 +529,7 @@ static struct atmel_uart_data atmel_usart0_data = {
|
||||||
};
|
};
|
||||||
static struct resource atmel_usart0_resource[] = {
|
static struct resource atmel_usart0_resource[] = {
|
||||||
PBMEM(0xffe00c00),
|
PBMEM(0xffe00c00),
|
||||||
IRQ(7),
|
IRQ(6),
|
||||||
};
|
};
|
||||||
DEFINE_DEV_DATA(atmel_usart, 0);
|
DEFINE_DEV_DATA(atmel_usart, 0);
|
||||||
DEV_CLK(usart, atmel_usart0, pba, 4);
|
DEV_CLK(usart, atmel_usart0, pba, 4);
|
||||||
|
@ -583,7 +591,7 @@ static inline void configure_usart3_pins(void)
|
||||||
select_peripheral(PB(17), PERIPH_B, 0); /* TXD */
|
select_peripheral(PB(17), PERIPH_B, 0); /* TXD */
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct platform_device *at32_usarts[4];
|
static struct platform_device *__initdata at32_usarts[4];
|
||||||
|
|
||||||
void __init at32_map_usart(unsigned int hw_id, unsigned int line)
|
void __init at32_map_usart(unsigned int hw_id, unsigned int line)
|
||||||
{
|
{
|
||||||
|
@ -728,12 +736,19 @@ at32_add_device_eth(unsigned int id, struct eth_platform_data *data)
|
||||||
/* --------------------------------------------------------------------
|
/* --------------------------------------------------------------------
|
||||||
* SPI
|
* SPI
|
||||||
* -------------------------------------------------------------------- */
|
* -------------------------------------------------------------------- */
|
||||||
static struct resource spi0_resource[] = {
|
static struct resource atmel_spi0_resource[] = {
|
||||||
PBMEM(0xffe00000),
|
PBMEM(0xffe00000),
|
||||||
IRQ(3),
|
IRQ(3),
|
||||||
};
|
};
|
||||||
DEFINE_DEV(spi, 0);
|
DEFINE_DEV(atmel_spi, 0);
|
||||||
DEV_CLK(mck, spi0, pba, 0);
|
DEV_CLK(spi_clk, atmel_spi0, pba, 0);
|
||||||
|
|
||||||
|
static struct resource atmel_spi1_resource[] = {
|
||||||
|
PBMEM(0xffe00400),
|
||||||
|
IRQ(4),
|
||||||
|
};
|
||||||
|
DEFINE_DEV(atmel_spi, 1);
|
||||||
|
DEV_CLK(spi_clk, atmel_spi1, pba, 1);
|
||||||
|
|
||||||
struct platform_device *__init at32_add_device_spi(unsigned int id)
|
struct platform_device *__init at32_add_device_spi(unsigned int id)
|
||||||
{
|
{
|
||||||
|
@ -741,13 +756,33 @@ struct platform_device *__init at32_add_device_spi(unsigned int id)
|
||||||
|
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case 0:
|
case 0:
|
||||||
pdev = &spi0_device;
|
pdev = &atmel_spi0_device;
|
||||||
select_peripheral(PA(0), PERIPH_A, 0); /* MISO */
|
select_peripheral(PA(0), PERIPH_A, 0); /* MISO */
|
||||||
select_peripheral(PA(1), PERIPH_A, 0); /* MOSI */
|
select_peripheral(PA(1), PERIPH_A, 0); /* MOSI */
|
||||||
select_peripheral(PA(2), PERIPH_A, 0); /* SCK */
|
select_peripheral(PA(2), PERIPH_A, 0); /* SCK */
|
||||||
select_peripheral(PA(3), PERIPH_A, 0); /* NPCS0 */
|
|
||||||
select_peripheral(PA(4), PERIPH_A, 0); /* NPCS1 */
|
/* NPCS[2:0] */
|
||||||
select_peripheral(PA(5), PERIPH_A, 0); /* NPCS2 */
|
at32_select_gpio(GPIO_PIN_PA(3),
|
||||||
|
AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH);
|
||||||
|
at32_select_gpio(GPIO_PIN_PA(4),
|
||||||
|
AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH);
|
||||||
|
at32_select_gpio(GPIO_PIN_PA(5),
|
||||||
|
AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
pdev = &atmel_spi1_device;
|
||||||
|
select_peripheral(PB(0), PERIPH_B, 0); /* MISO */
|
||||||
|
select_peripheral(PB(1), PERIPH_B, 0); /* MOSI */
|
||||||
|
select_peripheral(PB(5), PERIPH_B, 0); /* SCK */
|
||||||
|
|
||||||
|
/* NPCS[2:0] */
|
||||||
|
at32_select_gpio(GPIO_PIN_PB(2),
|
||||||
|
AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH);
|
||||||
|
at32_select_gpio(GPIO_PIN_PB(3),
|
||||||
|
AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH);
|
||||||
|
at32_select_gpio(GPIO_PIN_PB(4),
|
||||||
|
AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -860,6 +895,7 @@ struct clk *at32_clock_list[] = {
|
||||||
&pio1_mck,
|
&pio1_mck,
|
||||||
&pio2_mck,
|
&pio2_mck,
|
||||||
&pio3_mck,
|
&pio3_mck,
|
||||||
|
&pio4_mck,
|
||||||
&atmel_usart0_usart,
|
&atmel_usart0_usart,
|
||||||
&atmel_usart1_usart,
|
&atmel_usart1_usart,
|
||||||
&atmel_usart2_usart,
|
&atmel_usart2_usart,
|
||||||
|
@ -868,7 +904,8 @@ struct clk *at32_clock_list[] = {
|
||||||
&macb0_pclk,
|
&macb0_pclk,
|
||||||
&macb1_hclk,
|
&macb1_hclk,
|
||||||
&macb1_pclk,
|
&macb1_pclk,
|
||||||
&spi0_mck,
|
&atmel_spi0_spi_clk,
|
||||||
|
&atmel_spi1_spi_clk,
|
||||||
&lcdc0_hclk,
|
&lcdc0_hclk,
|
||||||
&lcdc0_pixclk,
|
&lcdc0_pixclk,
|
||||||
};
|
};
|
||||||
|
@ -880,6 +917,7 @@ void __init at32_portmux_init(void)
|
||||||
at32_init_pio(&pio1_device);
|
at32_init_pio(&pio1_device);
|
||||||
at32_init_pio(&pio2_device);
|
at32_init_pio(&pio2_device);
|
||||||
at32_init_pio(&pio3_device);
|
at32_init_pio(&pio3_device);
|
||||||
|
at32_init_pio(&pio4_device);
|
||||||
}
|
}
|
||||||
|
|
||||||
void __init at32_clock_init(void)
|
void __init at32_clock_init(void)
|
||||||
|
|
|
@ -55,20 +55,11 @@ static int eim_set_irq_type(unsigned int irq, unsigned int flow_type)
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
|
flow_type &= IRQ_TYPE_SENSE_MASK;
|
||||||
if (flow_type == IRQ_TYPE_NONE)
|
if (flow_type == IRQ_TYPE_NONE)
|
||||||
flow_type = IRQ_TYPE_LEVEL_LOW;
|
flow_type = IRQ_TYPE_LEVEL_LOW;
|
||||||
|
|
||||||
desc = &irq_desc[irq];
|
desc = &irq_desc[irq];
|
||||||
desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
|
|
||||||
desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
|
|
||||||
|
|
||||||
if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) {
|
|
||||||
desc->status |= IRQ_LEVEL;
|
|
||||||
set_irq_handler(irq, handle_level_irq);
|
|
||||||
} else {
|
|
||||||
set_irq_handler(irq, handle_edge_irq);
|
|
||||||
}
|
|
||||||
|
|
||||||
spin_lock_irqsave(&sm->lock, flags);
|
spin_lock_irqsave(&sm->lock, flags);
|
||||||
|
|
||||||
mode = sm_readl(sm, EIM_MODE);
|
mode = sm_readl(sm, EIM_MODE);
|
||||||
|
@ -97,9 +88,16 @@ static int eim_set_irq_type(unsigned int irq, unsigned int flow_type)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
sm_writel(sm, EIM_MODE, mode);
|
if (ret == 0) {
|
||||||
sm_writel(sm, EIM_EDGE, edge);
|
sm_writel(sm, EIM_MODE, mode);
|
||||||
sm_writel(sm, EIM_LEVEL, level);
|
sm_writel(sm, EIM_EDGE, edge);
|
||||||
|
sm_writel(sm, EIM_LEVEL, level);
|
||||||
|
|
||||||
|
if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
|
||||||
|
flow_type |= IRQ_LEVEL;
|
||||||
|
desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
|
||||||
|
desc->status |= flow_type;
|
||||||
|
}
|
||||||
|
|
||||||
spin_unlock_irqrestore(&sm->lock, flags);
|
spin_unlock_irqrestore(&sm->lock, flags);
|
||||||
|
|
||||||
|
@ -122,8 +120,6 @@ static void demux_eim_irq(unsigned int irq, struct irq_desc *desc)
|
||||||
unsigned long status, pending;
|
unsigned long status, pending;
|
||||||
unsigned int i, ext_irq;
|
unsigned int i, ext_irq;
|
||||||
|
|
||||||
spin_lock(&sm->lock);
|
|
||||||
|
|
||||||
status = sm_readl(sm, EIM_ISR);
|
status = sm_readl(sm, EIM_ISR);
|
||||||
pending = status & sm_readl(sm, EIM_IMR);
|
pending = status & sm_readl(sm, EIM_IMR);
|
||||||
|
|
||||||
|
@ -133,10 +129,11 @@ static void demux_eim_irq(unsigned int irq, struct irq_desc *desc)
|
||||||
|
|
||||||
ext_irq = i + sm->eim_first_irq;
|
ext_irq = i + sm->eim_first_irq;
|
||||||
ext_desc = irq_desc + ext_irq;
|
ext_desc = irq_desc + ext_irq;
|
||||||
ext_desc->handle_irq(ext_irq, ext_desc);
|
if (ext_desc->status & IRQ_LEVEL)
|
||||||
|
handle_level_irq(ext_irq, ext_desc);
|
||||||
|
else
|
||||||
|
handle_edge_irq(ext_irq, ext_desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_unlock(&sm->lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init eim_init(void)
|
static int __init eim_init(void)
|
||||||
|
@ -168,8 +165,9 @@ static int __init eim_init(void)
|
||||||
sm->eim_chip = &eim_chip;
|
sm->eim_chip = &eim_chip;
|
||||||
|
|
||||||
for (i = 0; i < nr_irqs; i++) {
|
for (i = 0; i < nr_irqs; i++) {
|
||||||
|
/* NOTE the handler we set here is ignored by the demux */
|
||||||
set_irq_chip_and_handler(sm->eim_first_irq + i, &eim_chip,
|
set_irq_chip_and_handler(sm->eim_first_irq + i, &eim_chip,
|
||||||
handle_edge_irq);
|
handle_level_irq);
|
||||||
set_irq_chip_data(sm->eim_first_irq + i, sm);
|
set_irq_chip_data(sm->eim_first_irq + i, sm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,9 @@
|
||||||
#include <linux/debugfs.h>
|
#include <linux/debugfs.h>
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/irq.h>
|
||||||
|
|
||||||
|
#include <asm/gpio.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
|
|
||||||
#include <asm/arch/portmux.h>
|
#include <asm/arch/portmux.h>
|
||||||
|
@ -26,7 +28,8 @@ struct pio_device {
|
||||||
const struct platform_device *pdev;
|
const struct platform_device *pdev;
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
u32 pinmux_mask;
|
u32 pinmux_mask;
|
||||||
char name[32];
|
u32 gpio_mask;
|
||||||
|
char name[8];
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct pio_device pio_dev[MAX_NR_PIO_DEVICES];
|
static struct pio_device pio_dev[MAX_NR_PIO_DEVICES];
|
||||||
|
@ -76,6 +79,9 @@ void __init at32_select_periph(unsigned int pin, unsigned int periph,
|
||||||
if (!(flags & AT32_GPIOF_PULLUP))
|
if (!(flags & AT32_GPIOF_PULLUP))
|
||||||
pio_writel(pio, PUDR, mask);
|
pio_writel(pio, PUDR, mask);
|
||||||
|
|
||||||
|
/* gpio_request NOT allowed */
|
||||||
|
set_bit(pin_index, &pio->gpio_mask);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
@ -99,19 +105,29 @@ void __init at32_select_gpio(unsigned int pin, unsigned long flags)
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
pio_writel(pio, PUER, mask);
|
if (flags & AT32_GPIOF_OUTPUT) {
|
||||||
if (flags & AT32_GPIOF_HIGH)
|
if (flags & AT32_GPIOF_HIGH)
|
||||||
pio_writel(pio, SODR, mask);
|
pio_writel(pio, SODR, mask);
|
||||||
else
|
else
|
||||||
pio_writel(pio, CODR, mask);
|
pio_writel(pio, CODR, mask);
|
||||||
if (flags & AT32_GPIOF_OUTPUT)
|
pio_writel(pio, PUDR, mask);
|
||||||
pio_writel(pio, OER, mask);
|
pio_writel(pio, OER, mask);
|
||||||
else
|
} else {
|
||||||
|
if (flags & AT32_GPIOF_PULLUP)
|
||||||
|
pio_writel(pio, PUER, mask);
|
||||||
|
else
|
||||||
|
pio_writel(pio, PUDR, mask);
|
||||||
|
if (flags & AT32_GPIOF_DEGLITCH)
|
||||||
|
pio_writel(pio, IFER, mask);
|
||||||
|
else
|
||||||
|
pio_writel(pio, IFDR, mask);
|
||||||
pio_writel(pio, ODR, mask);
|
pio_writel(pio, ODR, mask);
|
||||||
|
}
|
||||||
|
|
||||||
pio_writel(pio, PER, mask);
|
pio_writel(pio, PER, mask);
|
||||||
if (!(flags & AT32_GPIOF_PULLUP))
|
|
||||||
pio_writel(pio, PUDR, mask);
|
/* gpio_request now allowed */
|
||||||
|
clear_bit(pin_index, &pio->gpio_mask);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -119,20 +135,220 @@ fail:
|
||||||
dump_stack();
|
dump_stack();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Reserve a pin, preventing anyone else from changing its configuration. */
|
||||||
|
void __init at32_reserve_pin(unsigned int pin)
|
||||||
|
{
|
||||||
|
struct pio_device *pio;
|
||||||
|
unsigned int pin_index = pin & 0x1f;
|
||||||
|
|
||||||
|
pio = gpio_to_pio(pin);
|
||||||
|
if (unlikely(!pio)) {
|
||||||
|
printk("pio: invalid pin %u\n", pin);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unlikely(test_and_set_bit(pin_index, &pio->pinmux_mask))) {
|
||||||
|
printk("%s: pin %u is busy\n", pio->name, pin_index);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
dump_stack();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* GPIO API */
|
||||||
|
|
||||||
|
int gpio_request(unsigned int gpio, const char *label)
|
||||||
|
{
|
||||||
|
struct pio_device *pio;
|
||||||
|
unsigned int pin;
|
||||||
|
|
||||||
|
pio = gpio_to_pio(gpio);
|
||||||
|
if (!pio)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
pin = gpio & 0x1f;
|
||||||
|
if (test_and_set_bit(pin, &pio->gpio_mask))
|
||||||
|
return -EBUSY;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(gpio_request);
|
||||||
|
|
||||||
|
void gpio_free(unsigned int gpio)
|
||||||
|
{
|
||||||
|
struct pio_device *pio;
|
||||||
|
unsigned int pin;
|
||||||
|
|
||||||
|
pio = gpio_to_pio(gpio);
|
||||||
|
if (!pio) {
|
||||||
|
printk(KERN_ERR
|
||||||
|
"gpio: attempted to free invalid pin %u\n", gpio);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pin = gpio & 0x1f;
|
||||||
|
if (!test_and_clear_bit(pin, &pio->gpio_mask))
|
||||||
|
printk(KERN_ERR "gpio: freeing free or non-gpio pin %s-%u\n",
|
||||||
|
pio->name, pin);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(gpio_free);
|
||||||
|
|
||||||
|
int gpio_direction_input(unsigned int gpio)
|
||||||
|
{
|
||||||
|
struct pio_device *pio;
|
||||||
|
unsigned int pin;
|
||||||
|
|
||||||
|
pio = gpio_to_pio(gpio);
|
||||||
|
if (!pio)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
pin = gpio & 0x1f;
|
||||||
|
pio_writel(pio, ODR, 1 << pin);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(gpio_direction_input);
|
||||||
|
|
||||||
|
int gpio_direction_output(unsigned int gpio)
|
||||||
|
{
|
||||||
|
struct pio_device *pio;
|
||||||
|
unsigned int pin;
|
||||||
|
|
||||||
|
pio = gpio_to_pio(gpio);
|
||||||
|
if (!pio)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
pin = gpio & 0x1f;
|
||||||
|
pio_writel(pio, OER, 1 << pin);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(gpio_direction_output);
|
||||||
|
|
||||||
|
int gpio_get_value(unsigned int gpio)
|
||||||
|
{
|
||||||
|
struct pio_device *pio = &pio_dev[gpio >> 5];
|
||||||
|
|
||||||
|
return (pio_readl(pio, PDSR) >> (gpio & 0x1f)) & 1;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(gpio_get_value);
|
||||||
|
|
||||||
|
void gpio_set_value(unsigned int gpio, int value)
|
||||||
|
{
|
||||||
|
struct pio_device *pio = &pio_dev[gpio >> 5];
|
||||||
|
u32 mask;
|
||||||
|
|
||||||
|
mask = 1 << (gpio & 0x1f);
|
||||||
|
if (value)
|
||||||
|
pio_writel(pio, SODR, mask);
|
||||||
|
else
|
||||||
|
pio_writel(pio, CODR, mask);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(gpio_set_value);
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* GPIO IRQ support */
|
||||||
|
|
||||||
|
static void gpio_irq_mask(unsigned irq)
|
||||||
|
{
|
||||||
|
unsigned gpio = irq_to_gpio(irq);
|
||||||
|
struct pio_device *pio = &pio_dev[gpio >> 5];
|
||||||
|
|
||||||
|
pio_writel(pio, IDR, 1 << (gpio & 0x1f));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gpio_irq_unmask(unsigned irq)
|
||||||
|
{
|
||||||
|
unsigned gpio = irq_to_gpio(irq);
|
||||||
|
struct pio_device *pio = &pio_dev[gpio >> 5];
|
||||||
|
|
||||||
|
pio_writel(pio, IER, 1 << (gpio & 0x1f));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int gpio_irq_type(unsigned irq, unsigned type)
|
||||||
|
{
|
||||||
|
if (type != IRQ_TYPE_EDGE_BOTH && type != IRQ_TYPE_NONE)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct irq_chip gpio_irqchip = {
|
||||||
|
.name = "gpio",
|
||||||
|
.mask = gpio_irq_mask,
|
||||||
|
.unmask = gpio_irq_unmask,
|
||||||
|
.set_type = gpio_irq_type,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
|
||||||
|
{
|
||||||
|
struct pio_device *pio = get_irq_chip_data(irq);
|
||||||
|
unsigned gpio_irq;
|
||||||
|
|
||||||
|
gpio_irq = (unsigned) get_irq_data(irq);
|
||||||
|
for (;;) {
|
||||||
|
u32 isr;
|
||||||
|
struct irq_desc *d;
|
||||||
|
|
||||||
|
/* ack pending GPIO interrupts */
|
||||||
|
isr = pio_readl(pio, ISR) & pio_readl(pio, IMR);
|
||||||
|
if (!isr)
|
||||||
|
break;
|
||||||
|
do {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
i = ffs(isr) - 1;
|
||||||
|
isr &= ~(1 << i);
|
||||||
|
|
||||||
|
i += gpio_irq;
|
||||||
|
d = &irq_desc[i];
|
||||||
|
|
||||||
|
d->handle_irq(i, d);
|
||||||
|
} while (isr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __init
|
||||||
|
gpio_irq_setup(struct pio_device *pio, int irq, int gpio_irq)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
set_irq_chip_data(irq, pio);
|
||||||
|
set_irq_data(irq, (void *) gpio_irq);
|
||||||
|
|
||||||
|
for (i = 0; i < 32; i++, gpio_irq++) {
|
||||||
|
set_irq_chip_data(gpio_irq, pio);
|
||||||
|
set_irq_chip_and_handler(gpio_irq, &gpio_irqchip,
|
||||||
|
handle_simple_irq);
|
||||||
|
}
|
||||||
|
|
||||||
|
set_irq_chained_handler(irq, gpio_irq_handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
static int __init pio_probe(struct platform_device *pdev)
|
static int __init pio_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct pio_device *pio = NULL;
|
struct pio_device *pio = NULL;
|
||||||
|
int irq = platform_get_irq(pdev, 0);
|
||||||
|
int gpio_irq_base = GPIO_IRQ_BASE + pdev->id * 32;
|
||||||
|
|
||||||
BUG_ON(pdev->id >= MAX_NR_PIO_DEVICES);
|
BUG_ON(pdev->id >= MAX_NR_PIO_DEVICES);
|
||||||
pio = &pio_dev[pdev->id];
|
pio = &pio_dev[pdev->id];
|
||||||
BUG_ON(!pio->regs);
|
BUG_ON(!pio->regs);
|
||||||
|
|
||||||
/* TODO: Interrupts */
|
gpio_irq_setup(pio, irq, gpio_irq_base);
|
||||||
|
|
||||||
platform_set_drvdata(pdev, pio);
|
platform_set_drvdata(pdev, pio);
|
||||||
|
|
||||||
printk(KERN_INFO "%s: Atmel Port Multiplexer at 0x%p (irq %d)\n",
|
printk(KERN_DEBUG "%s: base 0x%p, irq %d chains %d..%d\n",
|
||||||
pio->name, pio->regs, platform_get_irq(pdev, 0));
|
pio->name, pio->regs, irq, gpio_irq_base, gpio_irq_base + 31);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -148,7 +364,7 @@ static int __init pio_init(void)
|
||||||
{
|
{
|
||||||
return platform_driver_register(&pio_driver);
|
return platform_driver_register(&pio_driver);
|
||||||
}
|
}
|
||||||
subsys_initcall(pio_init);
|
postcore_initcall(pio_init);
|
||||||
|
|
||||||
void __init at32_init_pio(struct platform_device *pdev)
|
void __init at32_init_pio(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
|
@ -184,6 +400,13 @@ void __init at32_init_pio(struct platform_device *pdev)
|
||||||
pio->pdev = pdev;
|
pio->pdev = pdev;
|
||||||
pio->regs = ioremap(regs->start, regs->end - regs->start + 1);
|
pio->regs = ioremap(regs->start, regs->end - regs->start + 1);
|
||||||
|
|
||||||
pio_writel(pio, ODR, ~0UL);
|
/*
|
||||||
pio_writel(pio, PER, ~0UL);
|
* request_gpio() is only valid for pins that have been
|
||||||
|
* explicitly configured as GPIO and not previously requested
|
||||||
|
*/
|
||||||
|
pio->gpio_mask = ~0UL;
|
||||||
|
|
||||||
|
/* start with irqs disabled and acked */
|
||||||
|
pio_writel(pio, IDR, ~0UL);
|
||||||
|
(void) pio_readl(pio, ISR);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,18 +22,34 @@
|
||||||
|
|
||||||
void invalidate_dcache_region(void *start, size_t size)
|
void invalidate_dcache_region(void *start, size_t size)
|
||||||
{
|
{
|
||||||
unsigned long v, begin, end, linesz;
|
unsigned long v, begin, end, linesz, mask;
|
||||||
|
int flush = 0;
|
||||||
|
|
||||||
linesz = boot_cpu_data.dcache.linesz;
|
linesz = boot_cpu_data.dcache.linesz;
|
||||||
|
mask = linesz - 1;
|
||||||
|
|
||||||
//printk("invalidate dcache: %p + %u\n", start, size);
|
/* when first and/or last cachelines are shared, flush them
|
||||||
|
* instead of invalidating ... never discard valid data!
|
||||||
|
*/
|
||||||
|
begin = (unsigned long)start;
|
||||||
|
end = begin + size - 1;
|
||||||
|
|
||||||
/* You asked for it, you got it */
|
if (begin & mask) {
|
||||||
begin = (unsigned long)start & ~(linesz - 1);
|
flush_dcache_line(start);
|
||||||
end = ((unsigned long)start + size + linesz - 1) & ~(linesz - 1);
|
begin += linesz;
|
||||||
|
flush = 1;
|
||||||
|
}
|
||||||
|
if ((end & mask) != mask) {
|
||||||
|
flush_dcache_line((void *)end);
|
||||||
|
end -= linesz;
|
||||||
|
flush = 1;
|
||||||
|
}
|
||||||
|
|
||||||
for (v = begin; v < end; v += linesz)
|
/* remaining cachelines only need invalidation */
|
||||||
|
for (v = begin; v <= end; v += linesz)
|
||||||
invalidate_dcache_line((void *)v);
|
invalidate_dcache_line((void *)v);
|
||||||
|
if (flush)
|
||||||
|
flush_write_buffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void clean_dcache_region(void *start, size_t size)
|
void clean_dcache_region(void *start, size_t size)
|
||||||
|
|
|
@ -43,6 +43,8 @@ static int is_safe_abs_reloc(const char* sym_name)
|
||||||
/* Match found */
|
/* Match found */
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
if (strncmp(sym_name, "__crc_", 6) == 0)
|
||||||
|
return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -466,7 +466,8 @@ CONFIG_FW_LOADER=y
|
||||||
#
|
#
|
||||||
# Plug and Play support
|
# Plug and Play support
|
||||||
#
|
#
|
||||||
# CONFIG_PNP is not set
|
CONFIG_PNP=y
|
||||||
|
CONFIG_PNPACPI=y
|
||||||
|
|
||||||
#
|
#
|
||||||
# Block devices
|
# Block devices
|
||||||
|
|
|
@ -66,7 +66,7 @@ static inline int acpi_madt_oem_check(char *oem_id, char *oem_table_id) { return
|
||||||
|
|
||||||
#define BAD_MADT_ENTRY(entry, end) ( \
|
#define BAD_MADT_ENTRY(entry, end) ( \
|
||||||
(!entry) || (unsigned long)entry + sizeof(*entry) > end || \
|
(!entry) || (unsigned long)entry + sizeof(*entry) > end || \
|
||||||
((acpi_table_entry_header *)entry)->length < sizeof(*entry))
|
((struct acpi_subtable_header *)entry)->length < sizeof(*entry))
|
||||||
|
|
||||||
#define PREFIX "ACPI: "
|
#define PREFIX "ACPI: "
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ int acpi_ioapic;
|
||||||
int acpi_strict;
|
int acpi_strict;
|
||||||
EXPORT_SYMBOL(acpi_strict);
|
EXPORT_SYMBOL(acpi_strict);
|
||||||
|
|
||||||
acpi_interrupt_flags acpi_sci_flags __initdata;
|
u8 acpi_sci_flags __initdata;
|
||||||
int acpi_sci_override_gsi __initdata;
|
int acpi_sci_override_gsi __initdata;
|
||||||
int acpi_skip_timer_override __initdata;
|
int acpi_skip_timer_override __initdata;
|
||||||
int acpi_use_timer_override __initdata;
|
int acpi_use_timer_override __initdata;
|
||||||
|
@ -92,11 +92,6 @@ static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
|
||||||
#warning ACPI uses CMPXCHG, i486 and later hardware
|
#warning ACPI uses CMPXCHG, i486 and later hardware
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MAX_MADT_ENTRIES 256
|
|
||||||
u8 x86_acpiid_to_apicid[MAX_MADT_ENTRIES] =
|
|
||||||
{[0 ... MAX_MADT_ENTRIES - 1] = 0xff };
|
|
||||||
EXPORT_SYMBOL(x86_acpiid_to_apicid);
|
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------
|
||||||
Boot-time Configuration
|
Boot-time Configuration
|
||||||
-------------------------------------------------------------------------- */
|
-------------------------------------------------------------------------- */
|
||||||
|
@ -166,30 +161,26 @@ char *__acpi_map_table(unsigned long phys, unsigned long size)
|
||||||
|
|
||||||
#ifdef CONFIG_PCI_MMCONFIG
|
#ifdef CONFIG_PCI_MMCONFIG
|
||||||
/* The physical address of the MMCONFIG aperture. Set from ACPI tables. */
|
/* The physical address of the MMCONFIG aperture. Set from ACPI tables. */
|
||||||
struct acpi_table_mcfg_config *pci_mmcfg_config;
|
struct acpi_mcfg_allocation *pci_mmcfg_config;
|
||||||
int pci_mmcfg_config_num;
|
int pci_mmcfg_config_num;
|
||||||
|
|
||||||
int __init acpi_parse_mcfg(unsigned long phys_addr, unsigned long size)
|
int __init acpi_parse_mcfg(struct acpi_table_header *header)
|
||||||
{
|
{
|
||||||
struct acpi_table_mcfg *mcfg;
|
struct acpi_table_mcfg *mcfg;
|
||||||
unsigned long i;
|
unsigned long i;
|
||||||
int config_size;
|
int config_size;
|
||||||
|
|
||||||
if (!phys_addr || !size)
|
if (!header)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
mcfg = (struct acpi_table_mcfg *)__acpi_map_table(phys_addr, size);
|
mcfg = (struct acpi_table_mcfg *)header;
|
||||||
if (!mcfg) {
|
|
||||||
printk(KERN_WARNING PREFIX "Unable to map MCFG\n");
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* how many config structures do we have */
|
/* how many config structures do we have */
|
||||||
pci_mmcfg_config_num = 0;
|
pci_mmcfg_config_num = 0;
|
||||||
i = size - sizeof(struct acpi_table_mcfg);
|
i = header->length - sizeof(struct acpi_table_mcfg);
|
||||||
while (i >= sizeof(struct acpi_table_mcfg_config)) {
|
while (i >= sizeof(struct acpi_mcfg_allocation)) {
|
||||||
++pci_mmcfg_config_num;
|
++pci_mmcfg_config_num;
|
||||||
i -= sizeof(struct acpi_table_mcfg_config);
|
i -= sizeof(struct acpi_mcfg_allocation);
|
||||||
};
|
};
|
||||||
if (pci_mmcfg_config_num == 0) {
|
if (pci_mmcfg_config_num == 0) {
|
||||||
printk(KERN_ERR PREFIX "MMCONFIG has no entries\n");
|
printk(KERN_ERR PREFIX "MMCONFIG has no entries\n");
|
||||||
|
@ -204,9 +195,9 @@ int __init acpi_parse_mcfg(unsigned long phys_addr, unsigned long size)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(pci_mmcfg_config, &mcfg->config, config_size);
|
memcpy(pci_mmcfg_config, &mcfg[1], config_size);
|
||||||
for (i = 0; i < pci_mmcfg_config_num; ++i) {
|
for (i = 0; i < pci_mmcfg_config_num; ++i) {
|
||||||
if (mcfg->config[i].base_reserved) {
|
if (pci_mmcfg_config[i].address > 0xFFFFFFFF) {
|
||||||
printk(KERN_ERR PREFIX
|
printk(KERN_ERR PREFIX
|
||||||
"MMCONFIG not in low 4GB of memory\n");
|
"MMCONFIG not in low 4GB of memory\n");
|
||||||
kfree(pci_mmcfg_config);
|
kfree(pci_mmcfg_config);
|
||||||
|
@ -220,24 +211,24 @@ int __init acpi_parse_mcfg(unsigned long phys_addr, unsigned long size)
|
||||||
#endif /* CONFIG_PCI_MMCONFIG */
|
#endif /* CONFIG_PCI_MMCONFIG */
|
||||||
|
|
||||||
#ifdef CONFIG_X86_LOCAL_APIC
|
#ifdef CONFIG_X86_LOCAL_APIC
|
||||||
static int __init acpi_parse_madt(unsigned long phys_addr, unsigned long size)
|
static int __init acpi_parse_madt(struct acpi_table_header *table)
|
||||||
{
|
{
|
||||||
struct acpi_table_madt *madt = NULL;
|
struct acpi_table_madt *madt = NULL;
|
||||||
|
|
||||||
if (!phys_addr || !size || !cpu_has_apic)
|
if (!cpu_has_apic)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
madt = (struct acpi_table_madt *)__acpi_map_table(phys_addr, size);
|
madt = (struct acpi_table_madt *)table;
|
||||||
if (!madt) {
|
if (!madt) {
|
||||||
printk(KERN_WARNING PREFIX "Unable to map MADT\n");
|
printk(KERN_WARNING PREFIX "Unable to map MADT\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (madt->lapic_address) {
|
if (madt->address) {
|
||||||
acpi_lapic_addr = (u64) madt->lapic_address;
|
acpi_lapic_addr = (u64) madt->address;
|
||||||
|
|
||||||
printk(KERN_DEBUG PREFIX "Local APIC address 0x%08x\n",
|
printk(KERN_DEBUG PREFIX "Local APIC address 0x%08x\n",
|
||||||
madt->lapic_address);
|
madt->address);
|
||||||
}
|
}
|
||||||
|
|
||||||
acpi_madt_oem_check(madt->header.oem_id, madt->header.oem_table_id);
|
acpi_madt_oem_check(madt->header.oem_id, madt->header.oem_table_id);
|
||||||
|
@ -246,21 +237,17 @@ static int __init acpi_parse_madt(unsigned long phys_addr, unsigned long size)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init
|
static int __init
|
||||||
acpi_parse_lapic(acpi_table_entry_header * header, const unsigned long end)
|
acpi_parse_lapic(struct acpi_subtable_header * header, const unsigned long end)
|
||||||
{
|
{
|
||||||
struct acpi_table_lapic *processor = NULL;
|
struct acpi_madt_local_apic *processor = NULL;
|
||||||
|
|
||||||
processor = (struct acpi_table_lapic *)header;
|
processor = (struct acpi_madt_local_apic *)header;
|
||||||
|
|
||||||
if (BAD_MADT_ENTRY(processor, end))
|
if (BAD_MADT_ENTRY(processor, end))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
acpi_table_print_madt_entry(header);
|
acpi_table_print_madt_entry(header);
|
||||||
|
|
||||||
/* Record local apic id only when enabled */
|
|
||||||
if (processor->flags.enabled)
|
|
||||||
x86_acpiid_to_apicid[processor->acpi_id] = processor->id;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We need to register disabled CPU as well to permit
|
* We need to register disabled CPU as well to permit
|
||||||
* counting disabled CPUs. This allows us to size
|
* counting disabled CPUs. This allows us to size
|
||||||
|
@ -269,18 +256,18 @@ acpi_parse_lapic(acpi_table_entry_header * header, const unsigned long end)
|
||||||
* when we use CPU hotplug.
|
* when we use CPU hotplug.
|
||||||
*/
|
*/
|
||||||
mp_register_lapic(processor->id, /* APIC ID */
|
mp_register_lapic(processor->id, /* APIC ID */
|
||||||
processor->flags.enabled); /* Enabled? */
|
processor->lapic_flags & ACPI_MADT_ENABLED); /* Enabled? */
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init
|
static int __init
|
||||||
acpi_parse_lapic_addr_ovr(acpi_table_entry_header * header,
|
acpi_parse_lapic_addr_ovr(struct acpi_subtable_header * header,
|
||||||
const unsigned long end)
|
const unsigned long end)
|
||||||
{
|
{
|
||||||
struct acpi_table_lapic_addr_ovr *lapic_addr_ovr = NULL;
|
struct acpi_madt_local_apic_override *lapic_addr_ovr = NULL;
|
||||||
|
|
||||||
lapic_addr_ovr = (struct acpi_table_lapic_addr_ovr *)header;
|
lapic_addr_ovr = (struct acpi_madt_local_apic_override *)header;
|
||||||
|
|
||||||
if (BAD_MADT_ENTRY(lapic_addr_ovr, end))
|
if (BAD_MADT_ENTRY(lapic_addr_ovr, end))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -291,11 +278,11 @@ acpi_parse_lapic_addr_ovr(acpi_table_entry_header * header,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init
|
static int __init
|
||||||
acpi_parse_lapic_nmi(acpi_table_entry_header * header, const unsigned long end)
|
acpi_parse_lapic_nmi(struct acpi_subtable_header * header, const unsigned long end)
|
||||||
{
|
{
|
||||||
struct acpi_table_lapic_nmi *lapic_nmi = NULL;
|
struct acpi_madt_local_apic_nmi *lapic_nmi = NULL;
|
||||||
|
|
||||||
lapic_nmi = (struct acpi_table_lapic_nmi *)header;
|
lapic_nmi = (struct acpi_madt_local_apic_nmi *)header;
|
||||||
|
|
||||||
if (BAD_MADT_ENTRY(lapic_nmi, end))
|
if (BAD_MADT_ENTRY(lapic_nmi, end))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -313,11 +300,11 @@ acpi_parse_lapic_nmi(acpi_table_entry_header * header, const unsigned long end)
|
||||||
#ifdef CONFIG_X86_IO_APIC
|
#ifdef CONFIG_X86_IO_APIC
|
||||||
|
|
||||||
static int __init
|
static int __init
|
||||||
acpi_parse_ioapic(acpi_table_entry_header * header, const unsigned long end)
|
acpi_parse_ioapic(struct acpi_subtable_header * header, const unsigned long end)
|
||||||
{
|
{
|
||||||
struct acpi_table_ioapic *ioapic = NULL;
|
struct acpi_madt_io_apic *ioapic = NULL;
|
||||||
|
|
||||||
ioapic = (struct acpi_table_ioapic *)header;
|
ioapic = (struct acpi_madt_io_apic *)header;
|
||||||
|
|
||||||
if (BAD_MADT_ENTRY(ioapic, end))
|
if (BAD_MADT_ENTRY(ioapic, end))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -342,11 +329,11 @@ static void __init acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger)
|
||||||
polarity = 3;
|
polarity = 3;
|
||||||
|
|
||||||
/* Command-line over-ride via acpi_sci= */
|
/* Command-line over-ride via acpi_sci= */
|
||||||
if (acpi_sci_flags.trigger)
|
if (acpi_sci_flags & ACPI_MADT_TRIGGER_MASK)
|
||||||
trigger = acpi_sci_flags.trigger;
|
trigger = (acpi_sci_flags & ACPI_MADT_TRIGGER_MASK) >> 2;
|
||||||
|
|
||||||
if (acpi_sci_flags.polarity)
|
if (acpi_sci_flags & ACPI_MADT_POLARITY_MASK)
|
||||||
polarity = acpi_sci_flags.polarity;
|
polarity = acpi_sci_flags & ACPI_MADT_POLARITY_MASK;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* mp_config_acpi_legacy_irqs() already setup IRQs < 16
|
* mp_config_acpi_legacy_irqs() already setup IRQs < 16
|
||||||
|
@ -357,51 +344,52 @@ static void __init acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* stash over-ride to indicate we've been here
|
* stash over-ride to indicate we've been here
|
||||||
* and for later update of acpi_fadt
|
* and for later update of acpi_gbl_FADT
|
||||||
*/
|
*/
|
||||||
acpi_sci_override_gsi = gsi;
|
acpi_sci_override_gsi = gsi;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init
|
static int __init
|
||||||
acpi_parse_int_src_ovr(acpi_table_entry_header * header,
|
acpi_parse_int_src_ovr(struct acpi_subtable_header * header,
|
||||||
const unsigned long end)
|
const unsigned long end)
|
||||||
{
|
{
|
||||||
struct acpi_table_int_src_ovr *intsrc = NULL;
|
struct acpi_madt_interrupt_override *intsrc = NULL;
|
||||||
|
|
||||||
intsrc = (struct acpi_table_int_src_ovr *)header;
|
intsrc = (struct acpi_madt_interrupt_override *)header;
|
||||||
|
|
||||||
if (BAD_MADT_ENTRY(intsrc, end))
|
if (BAD_MADT_ENTRY(intsrc, end))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
acpi_table_print_madt_entry(header);
|
acpi_table_print_madt_entry(header);
|
||||||
|
|
||||||
if (intsrc->bus_irq == acpi_fadt.sci_int) {
|
if (intsrc->source_irq == acpi_gbl_FADT.sci_interrupt) {
|
||||||
acpi_sci_ioapic_setup(intsrc->global_irq,
|
acpi_sci_ioapic_setup(intsrc->global_irq,
|
||||||
intsrc->flags.polarity,
|
intsrc->inti_flags & ACPI_MADT_POLARITY_MASK,
|
||||||
intsrc->flags.trigger);
|
(intsrc->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (acpi_skip_timer_override &&
|
if (acpi_skip_timer_override &&
|
||||||
intsrc->bus_irq == 0 && intsrc->global_irq == 2) {
|
intsrc->source_irq == 0 && intsrc->global_irq == 2) {
|
||||||
printk(PREFIX "BIOS IRQ0 pin2 override ignored.\n");
|
printk(PREFIX "BIOS IRQ0 pin2 override ignored.\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
mp_override_legacy_irq(intsrc->bus_irq,
|
mp_override_legacy_irq(intsrc->source_irq,
|
||||||
intsrc->flags.polarity,
|
intsrc->inti_flags & ACPI_MADT_POLARITY_MASK,
|
||||||
intsrc->flags.trigger, intsrc->global_irq);
|
(intsrc->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2,
|
||||||
|
intsrc->global_irq);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init
|
static int __init
|
||||||
acpi_parse_nmi_src(acpi_table_entry_header * header, const unsigned long end)
|
acpi_parse_nmi_src(struct acpi_subtable_header * header, const unsigned long end)
|
||||||
{
|
{
|
||||||
struct acpi_table_nmi_src *nmi_src = NULL;
|
struct acpi_madt_nmi_source *nmi_src = NULL;
|
||||||
|
|
||||||
nmi_src = (struct acpi_table_nmi_src *)header;
|
nmi_src = (struct acpi_madt_nmi_source *)header;
|
||||||
|
|
||||||
if (BAD_MADT_ENTRY(nmi_src, end))
|
if (BAD_MADT_ENTRY(nmi_src, end))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -417,7 +405,7 @@ acpi_parse_nmi_src(acpi_table_entry_header * header, const unsigned long end)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* acpi_pic_sci_set_trigger()
|
* acpi_pic_sci_set_trigger()
|
||||||
*
|
*
|
||||||
* use ELCR to set PIC-mode trigger type for SCI
|
* use ELCR to set PIC-mode trigger type for SCI
|
||||||
*
|
*
|
||||||
* If a PIC-mode SCI is not recognized or gives spurious IRQ7's
|
* If a PIC-mode SCI is not recognized or gives spurious IRQ7's
|
||||||
|
@ -511,7 +499,7 @@ int acpi_map_lsapic(acpi_handle handle, int *pcpu)
|
||||||
{
|
{
|
||||||
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
|
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
|
||||||
union acpi_object *obj;
|
union acpi_object *obj;
|
||||||
struct acpi_table_lapic *lapic;
|
struct acpi_madt_local_apic *lapic;
|
||||||
cpumask_t tmp_map, new_map;
|
cpumask_t tmp_map, new_map;
|
||||||
u8 physid;
|
u8 physid;
|
||||||
int cpu;
|
int cpu;
|
||||||
|
@ -529,10 +517,10 @@ int acpi_map_lsapic(acpi_handle handle, int *pcpu)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
lapic = (struct acpi_table_lapic *)obj->buffer.pointer;
|
lapic = (struct acpi_madt_local_apic *)obj->buffer.pointer;
|
||||||
|
|
||||||
if ((lapic->header.type != ACPI_MADT_LAPIC) ||
|
if (lapic->header.type != ACPI_MADT_TYPE_LOCAL_APIC ||
|
||||||
(!lapic->flags.enabled)) {
|
!(lapic->lapic_flags & ACPI_MADT_ENABLED)) {
|
||||||
kfree(buffer.pointer);
|
kfree(buffer.pointer);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -544,7 +532,7 @@ int acpi_map_lsapic(acpi_handle handle, int *pcpu)
|
||||||
buffer.pointer = NULL;
|
buffer.pointer = NULL;
|
||||||
|
|
||||||
tmp_map = cpu_present_map;
|
tmp_map = cpu_present_map;
|
||||||
mp_register_lapic(physid, lapic->flags.enabled);
|
mp_register_lapic(physid, lapic->lapic_flags & ACPI_MADT_ENABLED);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If mp_register_lapic successfully generates a new logical cpu
|
* If mp_register_lapic successfully generates a new logical cpu
|
||||||
|
@ -566,14 +554,6 @@ EXPORT_SYMBOL(acpi_map_lsapic);
|
||||||
|
|
||||||
int acpi_unmap_lsapic(int cpu)
|
int acpi_unmap_lsapic(int cpu)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
|
|
||||||
for_each_possible_cpu(i) {
|
|
||||||
if (x86_acpiid_to_apicid[i] == x86_cpu_to_apicid[cpu]) {
|
|
||||||
x86_acpiid_to_apicid[i] = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
x86_cpu_to_apicid[cpu] = -1;
|
x86_cpu_to_apicid[cpu] = -1;
|
||||||
cpu_clear(cpu, cpu_present_map);
|
cpu_clear(cpu, cpu_present_map);
|
||||||
num_processors--;
|
num_processors--;
|
||||||
|
@ -619,42 +599,36 @@ acpi_scan_rsdp(unsigned long start, unsigned long length)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init acpi_parse_sbf(unsigned long phys_addr, unsigned long size)
|
static int __init acpi_parse_sbf(struct acpi_table_header *table)
|
||||||
{
|
{
|
||||||
struct acpi_table_sbf *sb;
|
struct acpi_table_boot *sb;
|
||||||
|
|
||||||
if (!phys_addr || !size)
|
sb = (struct acpi_table_boot *)table;
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
sb = (struct acpi_table_sbf *)__acpi_map_table(phys_addr, size);
|
|
||||||
if (!sb) {
|
if (!sb) {
|
||||||
printk(KERN_WARNING PREFIX "Unable to map SBF\n");
|
printk(KERN_WARNING PREFIX "Unable to map SBF\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
sbf_port = sb->sbf_cmos; /* Save CMOS port */
|
sbf_port = sb->cmos_index; /* Save CMOS port */
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_HPET_TIMER
|
#ifdef CONFIG_HPET_TIMER
|
||||||
|
|
||||||
static int __init acpi_parse_hpet(unsigned long phys, unsigned long size)
|
static int __init acpi_parse_hpet(struct acpi_table_header *table)
|
||||||
{
|
{
|
||||||
struct acpi_table_hpet *hpet_tbl;
|
struct acpi_table_hpet *hpet_tbl;
|
||||||
struct resource *hpet_res;
|
struct resource *hpet_res;
|
||||||
resource_size_t res_start;
|
resource_size_t res_start;
|
||||||
|
|
||||||
if (!phys || !size)
|
hpet_tbl = (struct acpi_table_hpet *)table;
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
hpet_tbl = (struct acpi_table_hpet *)__acpi_map_table(phys, size);
|
|
||||||
if (!hpet_tbl) {
|
if (!hpet_tbl) {
|
||||||
printk(KERN_WARNING PREFIX "Unable to map HPET\n");
|
printk(KERN_WARNING PREFIX "Unable to map HPET\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hpet_tbl->addr.space_id != ACPI_SPACE_MEM) {
|
if (hpet_tbl->address.space_id != ACPI_SPACE_MEM) {
|
||||||
printk(KERN_WARNING PREFIX "HPET timers must be located in "
|
printk(KERN_WARNING PREFIX "HPET timers must be located in "
|
||||||
"memory.\n");
|
"memory.\n");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -667,29 +641,28 @@ static int __init acpi_parse_hpet(unsigned long phys, unsigned long size)
|
||||||
hpet_res->name = (void *)&hpet_res[1];
|
hpet_res->name = (void *)&hpet_res[1];
|
||||||
hpet_res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
|
hpet_res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
|
||||||
snprintf((char *)hpet_res->name, HPET_RESOURCE_NAME_SIZE,
|
snprintf((char *)hpet_res->name, HPET_RESOURCE_NAME_SIZE,
|
||||||
"HPET %u", hpet_tbl->number);
|
"HPET %u", hpet_tbl->sequence);
|
||||||
hpet_res->end = (1 * 1024) - 1;
|
hpet_res->end = (1 * 1024) - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_X86_64
|
#ifdef CONFIG_X86_64
|
||||||
vxtime.hpet_address = hpet_tbl->addr.addrl |
|
vxtime.hpet_address = hpet_tbl->address.address;
|
||||||
((long)hpet_tbl->addr.addrh << 32);
|
|
||||||
|
|
||||||
printk(KERN_INFO PREFIX "HPET id: %#x base: %#lx\n",
|
printk(KERN_INFO PREFIX "HPET id: %#x base: %#lx\n",
|
||||||
hpet_tbl->id, vxtime.hpet_address);
|
hpet_tbl->id, vxtime.hpet_address);
|
||||||
|
|
||||||
res_start = vxtime.hpet_address;
|
res_start = vxtime.hpet_address;
|
||||||
#else /* X86 */
|
#else /* X86 */
|
||||||
{
|
{
|
||||||
extern unsigned long hpet_address;
|
extern unsigned long hpet_address;
|
||||||
|
|
||||||
hpet_address = hpet_tbl->addr.addrl;
|
hpet_address = hpet_tbl->address.address;
|
||||||
printk(KERN_INFO PREFIX "HPET id: %#x base: %#lx\n",
|
printk(KERN_INFO PREFIX "HPET id: %#x base: %#lx\n",
|
||||||
hpet_tbl->id, hpet_address);
|
hpet_tbl->id, hpet_address);
|
||||||
|
|
||||||
res_start = hpet_address;
|
res_start = hpet_address;
|
||||||
}
|
}
|
||||||
#endif /* X86 */
|
#endif /* X86 */
|
||||||
|
|
||||||
if (hpet_res) {
|
if (hpet_res) {
|
||||||
hpet_res->start = res_start;
|
hpet_res->start = res_start;
|
||||||
|
@ -707,42 +680,28 @@ static int __init acpi_parse_hpet(unsigned long phys, unsigned long size)
|
||||||
extern u32 pmtmr_ioport;
|
extern u32 pmtmr_ioport;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int __init acpi_parse_fadt(unsigned long phys, unsigned long size)
|
static int __init acpi_parse_fadt(struct acpi_table_header *table)
|
||||||
{
|
{
|
||||||
struct fadt_descriptor *fadt = NULL;
|
|
||||||
|
|
||||||
fadt = (struct fadt_descriptor *)__acpi_map_table(phys, size);
|
|
||||||
if (!fadt) {
|
|
||||||
printk(KERN_WARNING PREFIX "Unable to map FADT\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/* initialize sci_int early for INT_SRC_OVR MADT parsing */
|
|
||||||
acpi_fadt.sci_int = fadt->sci_int;
|
|
||||||
|
|
||||||
/* initialize rev and apic_phys_dest_mode for x86_64 genapic */
|
|
||||||
acpi_fadt.revision = fadt->revision;
|
|
||||||
acpi_fadt.force_apic_physical_destination_mode =
|
|
||||||
fadt->force_apic_physical_destination_mode;
|
|
||||||
|
|
||||||
#ifdef CONFIG_X86_PM_TIMER
|
#ifdef CONFIG_X86_PM_TIMER
|
||||||
/* detect the location of the ACPI PM Timer */
|
/* detect the location of the ACPI PM Timer */
|
||||||
if (fadt->revision >= FADT2_REVISION_ID) {
|
if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID) {
|
||||||
/* FADT rev. 2 */
|
/* FADT rev. 2 */
|
||||||
if (fadt->xpm_tmr_blk.address_space_id !=
|
if (acpi_gbl_FADT.xpm_timer_block.space_id !=
|
||||||
ACPI_ADR_SPACE_SYSTEM_IO)
|
ACPI_ADR_SPACE_SYSTEM_IO)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
pmtmr_ioport = fadt->xpm_tmr_blk.address;
|
pmtmr_ioport = acpi_gbl_FADT.xpm_timer_block.address;
|
||||||
/*
|
/*
|
||||||
* "X" fields are optional extensions to the original V1.0
|
* "X" fields are optional extensions to the original V1.0
|
||||||
* fields, so we must selectively expand V1.0 fields if the
|
* fields, so we must selectively expand V1.0 fields if the
|
||||||
* corresponding X field is zero.
|
* corresponding X field is zero.
|
||||||
*/
|
*/
|
||||||
if (!pmtmr_ioport)
|
if (!pmtmr_ioport)
|
||||||
pmtmr_ioport = fadt->V1_pm_tmr_blk;
|
pmtmr_ioport = acpi_gbl_FADT.pm_timer_block;
|
||||||
} else {
|
} else {
|
||||||
/* FADT rev. 1 */
|
/* FADT rev. 1 */
|
||||||
pmtmr_ioport = fadt->V1_pm_tmr_blk;
|
pmtmr_ioport = acpi_gbl_FADT.pm_timer_block;
|
||||||
}
|
}
|
||||||
if (pmtmr_ioport)
|
if (pmtmr_ioport)
|
||||||
printk(KERN_INFO PREFIX "PM-Timer IO Port: %#x\n",
|
printk(KERN_INFO PREFIX "PM-Timer IO Port: %#x\n",
|
||||||
|
@ -784,13 +743,13 @@ static int __init acpi_parse_madt_lapic_entries(void)
|
||||||
if (!cpu_has_apic)
|
if (!cpu_has_apic)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Note that the LAPIC address is obtained from the MADT (32-bit value)
|
* Note that the LAPIC address is obtained from the MADT (32-bit value)
|
||||||
* and (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value).
|
* and (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
count =
|
count =
|
||||||
acpi_table_parse_madt(ACPI_MADT_LAPIC_ADDR_OVR,
|
acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE,
|
||||||
acpi_parse_lapic_addr_ovr, 0);
|
acpi_parse_lapic_addr_ovr, 0);
|
||||||
if (count < 0) {
|
if (count < 0) {
|
||||||
printk(KERN_ERR PREFIX
|
printk(KERN_ERR PREFIX
|
||||||
|
@ -800,7 +759,7 @@ static int __init acpi_parse_madt_lapic_entries(void)
|
||||||
|
|
||||||
mp_register_lapic_address(acpi_lapic_addr);
|
mp_register_lapic_address(acpi_lapic_addr);
|
||||||
|
|
||||||
count = acpi_table_parse_madt(ACPI_MADT_LAPIC, acpi_parse_lapic,
|
count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC, acpi_parse_lapic,
|
||||||
MAX_APICS);
|
MAX_APICS);
|
||||||
if (!count) {
|
if (!count) {
|
||||||
printk(KERN_ERR PREFIX "No LAPIC entries present\n");
|
printk(KERN_ERR PREFIX "No LAPIC entries present\n");
|
||||||
|
@ -813,7 +772,7 @@ static int __init acpi_parse_madt_lapic_entries(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
count =
|
count =
|
||||||
acpi_table_parse_madt(ACPI_MADT_LAPIC_NMI, acpi_parse_lapic_nmi, 0);
|
acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_NMI, acpi_parse_lapic_nmi, 0);
|
||||||
if (count < 0) {
|
if (count < 0) {
|
||||||
printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n");
|
printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n");
|
||||||
/* TBD: Cleanup to allow fallback to MPS */
|
/* TBD: Cleanup to allow fallback to MPS */
|
||||||
|
@ -842,7 +801,7 @@ static int __init acpi_parse_madt_ioapic_entries(void)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cpu_has_apic)
|
if (!cpu_has_apic)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -855,7 +814,7 @@ static int __init acpi_parse_madt_ioapic_entries(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
count =
|
count =
|
||||||
acpi_table_parse_madt(ACPI_MADT_IOAPIC, acpi_parse_ioapic,
|
acpi_table_parse_madt(ACPI_MADT_TYPE_IO_APIC, acpi_parse_ioapic,
|
||||||
MAX_IO_APICS);
|
MAX_IO_APICS);
|
||||||
if (!count) {
|
if (!count) {
|
||||||
printk(KERN_ERR PREFIX "No IOAPIC entries present\n");
|
printk(KERN_ERR PREFIX "No IOAPIC entries present\n");
|
||||||
|
@ -866,7 +825,7 @@ static int __init acpi_parse_madt_ioapic_entries(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
count =
|
count =
|
||||||
acpi_table_parse_madt(ACPI_MADT_INT_SRC_OVR, acpi_parse_int_src_ovr,
|
acpi_table_parse_madt(ACPI_MADT_TYPE_INTERRUPT_OVERRIDE, acpi_parse_int_src_ovr,
|
||||||
NR_IRQ_VECTORS);
|
NR_IRQ_VECTORS);
|
||||||
if (count < 0) {
|
if (count < 0) {
|
||||||
printk(KERN_ERR PREFIX
|
printk(KERN_ERR PREFIX
|
||||||
|
@ -880,13 +839,13 @@ static int __init acpi_parse_madt_ioapic_entries(void)
|
||||||
* pretend we got one so we can set the SCI flags.
|
* pretend we got one so we can set the SCI flags.
|
||||||
*/
|
*/
|
||||||
if (!acpi_sci_override_gsi)
|
if (!acpi_sci_override_gsi)
|
||||||
acpi_sci_ioapic_setup(acpi_fadt.sci_int, 0, 0);
|
acpi_sci_ioapic_setup(acpi_gbl_FADT.sci_interrupt, 0, 0);
|
||||||
|
|
||||||
/* Fill in identity legacy mapings where no override */
|
/* Fill in identity legacy mapings where no override */
|
||||||
mp_config_acpi_legacy_irqs();
|
mp_config_acpi_legacy_irqs();
|
||||||
|
|
||||||
count =
|
count =
|
||||||
acpi_table_parse_madt(ACPI_MADT_NMI_SRC, acpi_parse_nmi_src,
|
acpi_table_parse_madt(ACPI_MADT_TYPE_NMI_SOURCE, acpi_parse_nmi_src,
|
||||||
NR_IRQ_VECTORS);
|
NR_IRQ_VECTORS);
|
||||||
if (count < 0) {
|
if (count < 0) {
|
||||||
printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n");
|
printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n");
|
||||||
|
@ -908,7 +867,7 @@ static void __init acpi_process_madt(void)
|
||||||
#ifdef CONFIG_X86_LOCAL_APIC
|
#ifdef CONFIG_X86_LOCAL_APIC
|
||||||
int count, error;
|
int count, error;
|
||||||
|
|
||||||
count = acpi_table_parse(ACPI_APIC, acpi_parse_madt);
|
count = acpi_table_parse(ACPI_SIG_MADT, acpi_parse_madt);
|
||||||
if (count >= 1) {
|
if (count >= 1) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1195,7 +1154,7 @@ int __init acpi_boot_table_init(void)
|
||||||
if (acpi_disabled && !acpi_ht)
|
if (acpi_disabled && !acpi_ht)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize the ACPI boot-time table parser.
|
* Initialize the ACPI boot-time table parser.
|
||||||
*/
|
*/
|
||||||
error = acpi_table_init();
|
error = acpi_table_init();
|
||||||
|
@ -1204,7 +1163,7 @@ int __init acpi_boot_table_init(void)
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
acpi_table_parse(ACPI_BOOT, acpi_parse_sbf);
|
acpi_table_parse(ACPI_SIG_BOOT, acpi_parse_sbf);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* blacklist may disable ACPI entirely
|
* blacklist may disable ACPI entirely
|
||||||
|
@ -1232,19 +1191,19 @@ int __init acpi_boot_init(void)
|
||||||
if (acpi_disabled && !acpi_ht)
|
if (acpi_disabled && !acpi_ht)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
acpi_table_parse(ACPI_BOOT, acpi_parse_sbf);
|
acpi_table_parse(ACPI_SIG_BOOT, acpi_parse_sbf);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* set sci_int and PM timer address
|
* set sci_int and PM timer address
|
||||||
*/
|
*/
|
||||||
acpi_table_parse(ACPI_FADT, acpi_parse_fadt);
|
acpi_table_parse(ACPI_SIG_FADT, acpi_parse_fadt);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Process the Multiple APIC Description Table (MADT), if present
|
* Process the Multiple APIC Description Table (MADT), if present
|
||||||
*/
|
*/
|
||||||
acpi_process_madt();
|
acpi_process_madt();
|
||||||
|
|
||||||
acpi_table_parse(ACPI_HPET, acpi_parse_hpet);
|
acpi_table_parse(ACPI_SIG_HPET, acpi_parse_hpet);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1315,13 +1274,17 @@ static int __init setup_acpi_sci(char *s)
|
||||||
if (!s)
|
if (!s)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (!strcmp(s, "edge"))
|
if (!strcmp(s, "edge"))
|
||||||
acpi_sci_flags.trigger = 1;
|
acpi_sci_flags = ACPI_MADT_TRIGGER_EDGE |
|
||||||
|
(acpi_sci_flags & ~ACPI_MADT_TRIGGER_MASK);
|
||||||
else if (!strcmp(s, "level"))
|
else if (!strcmp(s, "level"))
|
||||||
acpi_sci_flags.trigger = 3;
|
acpi_sci_flags = ACPI_MADT_TRIGGER_LEVEL |
|
||||||
|
(acpi_sci_flags & ~ACPI_MADT_TRIGGER_MASK);
|
||||||
else if (!strcmp(s, "high"))
|
else if (!strcmp(s, "high"))
|
||||||
acpi_sci_flags.polarity = 1;
|
acpi_sci_flags = ACPI_MADT_POLARITY_ACTIVE_HIGH |
|
||||||
|
(acpi_sci_flags & ~ACPI_MADT_POLARITY_MASK);
|
||||||
else if (!strcmp(s, "low"))
|
else if (!strcmp(s, "low"))
|
||||||
acpi_sci_flags.polarity = 3;
|
acpi_sci_flags = ACPI_MADT_POLARITY_ACTIVE_LOW |
|
||||||
|
(acpi_sci_flags & ~ACPI_MADT_POLARITY_MASK);
|
||||||
else
|
else
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
static int nvidia_hpet_detected __initdata;
|
static int nvidia_hpet_detected __initdata;
|
||||||
|
|
||||||
static int __init nvidia_hpet_check(unsigned long phys, unsigned long size)
|
static int __init nvidia_hpet_check(struct acpi_table_header *header)
|
||||||
{
|
{
|
||||||
nvidia_hpet_detected = 1;
|
nvidia_hpet_detected = 1;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -30,7 +30,7 @@ static int __init check_bridge(int vendor, int device)
|
||||||
is enabled. */
|
is enabled. */
|
||||||
if (!acpi_use_timer_override && vendor == PCI_VENDOR_ID_NVIDIA) {
|
if (!acpi_use_timer_override && vendor == PCI_VENDOR_ID_NVIDIA) {
|
||||||
nvidia_hpet_detected = 0;
|
nvidia_hpet_detected = 0;
|
||||||
acpi_table_parse(ACPI_HPET, nvidia_hpet_check);
|
acpi_table_parse(ACPI_SIG_HPET, nvidia_hpet_check);
|
||||||
if (nvidia_hpet_detected == 0) {
|
if (nvidia_hpet_detected == 0) {
|
||||||
acpi_skip_timer_override = 1;
|
acpi_skip_timer_override = 1;
|
||||||
printk(KERN_INFO "Nvidia board "
|
printk(KERN_INFO "Nvidia board "
|
||||||
|
|
|
@ -190,7 +190,7 @@ static void do_powersaver(int cx_address, unsigned int clock_ratio_index)
|
||||||
/* Invoke C3 */
|
/* Invoke C3 */
|
||||||
inb(cx_address);
|
inb(cx_address);
|
||||||
/* Dummy op - must do something useless after P_LVL3 read */
|
/* Dummy op - must do something useless after P_LVL3 read */
|
||||||
t = inl(acpi_fadt.xpm_tmr_blk.address);
|
t = inl(acpi_gbl_FADT.xpm_timer_block.address);
|
||||||
}
|
}
|
||||||
/* Disable bus ratio bit */
|
/* Disable bus ratio bit */
|
||||||
local_irq_disable();
|
local_irq_disable();
|
||||||
|
@ -250,8 +250,7 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
|
||||||
outb(3, 0x22);
|
outb(3, 0x22);
|
||||||
} else if ((pr != NULL) && pr->flags.bm_control) {
|
} else if ((pr != NULL) && pr->flags.bm_control) {
|
||||||
/* Disable bus master arbitration */
|
/* Disable bus master arbitration */
|
||||||
acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1,
|
acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1);
|
||||||
ACPI_MTX_DO_NOT_LOCK);
|
|
||||||
}
|
}
|
||||||
switch (longhaul_version) {
|
switch (longhaul_version) {
|
||||||
|
|
||||||
|
@ -281,8 +280,7 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
|
||||||
case TYPE_POWERSAVER:
|
case TYPE_POWERSAVER:
|
||||||
if (longhaul_flags & USE_ACPI_C3) {
|
if (longhaul_flags & USE_ACPI_C3) {
|
||||||
/* Don't allow wakeup */
|
/* Don't allow wakeup */
|
||||||
acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0,
|
acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0);
|
||||||
ACPI_MTX_DO_NOT_LOCK);
|
|
||||||
do_powersaver(cx->address, clock_ratio_index);
|
do_powersaver(cx->address, clock_ratio_index);
|
||||||
} else {
|
} else {
|
||||||
do_powersaver(0, clock_ratio_index);
|
do_powersaver(0, clock_ratio_index);
|
||||||
|
@ -295,8 +293,7 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
|
||||||
outb(0, 0x22);
|
outb(0, 0x22);
|
||||||
} else if ((pr != NULL) && pr->flags.bm_control) {
|
} else if ((pr != NULL) && pr->flags.bm_control) {
|
||||||
/* Enable bus master arbitration */
|
/* Enable bus master arbitration */
|
||||||
acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0,
|
acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0);
|
||||||
ACPI_MTX_DO_NOT_LOCK);
|
|
||||||
}
|
}
|
||||||
outb(pic2_mask,0xA1); /* restore mask */
|
outb(pic2_mask,0xA1); /* restore mask */
|
||||||
outb(pic1_mask,0x21);
|
outb(pic1_mask,0x21);
|
||||||
|
@ -414,7 +411,7 @@ static int __init longhaul_get_ranges(void)
|
||||||
highest_speed = calc_speed(maxmult);
|
highest_speed = calc_speed(maxmult);
|
||||||
lowest_speed = calc_speed(minmult);
|
lowest_speed = calc_speed(minmult);
|
||||||
dprintk ("FSB:%dMHz Lowest speed: %s Highest speed:%s\n", fsb,
|
dprintk ("FSB:%dMHz Lowest speed: %s Highest speed:%s\n", fsb,
|
||||||
print_speed(lowest_speed/1000),
|
print_speed(lowest_speed/1000),
|
||||||
print_speed(highest_speed/1000));
|
print_speed(highest_speed/1000));
|
||||||
|
|
||||||
if (lowest_speed == highest_speed) {
|
if (lowest_speed == highest_speed) {
|
||||||
|
@ -498,7 +495,7 @@ static void __init longhaul_setup_voltagescaling(void)
|
||||||
maxvid.mV/1000, maxvid.mV%1000,
|
maxvid.mV/1000, maxvid.mV%1000,
|
||||||
minvid.mV/1000, minvid.mV%1000,
|
minvid.mV/1000, minvid.mV%1000,
|
||||||
numvscales);
|
numvscales);
|
||||||
|
|
||||||
j = 0;
|
j = 0;
|
||||||
while (longhaul_table[j].frequency != CPUFREQ_TABLE_END) {
|
while (longhaul_table[j].frequency != CPUFREQ_TABLE_END) {
|
||||||
speed = longhaul_table[j].frequency;
|
speed = longhaul_table[j].frequency;
|
||||||
|
|
|
@ -173,7 +173,7 @@ static void __cpuinit geode_configure(void)
|
||||||
ccr4 = getCx86(CX86_CCR4);
|
ccr4 = getCx86(CX86_CCR4);
|
||||||
ccr4 |= 0x38; /* FPU fast, DTE cache, Mem bypass */
|
ccr4 |= 0x38; /* FPU fast, DTE cache, Mem bypass */
|
||||||
|
|
||||||
setCx86(CX86_CCR4, ccr4);
|
setCx86(CX86_CCR3, ccr3);
|
||||||
|
|
||||||
set_cx86_memwb();
|
set_cx86_memwb();
|
||||||
set_cx86_reorder();
|
set_cx86_reorder();
|
||||||
|
|
|
@ -472,6 +472,70 @@ static inline void __init check_range_for_systab(efi_memory_desc_t *md)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wrap all the virtual calls in a way that forces the parameters on the stack.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define efi_call_virt(f, args...) \
|
||||||
|
((efi_##f##_t __attribute__((regparm(0)))*)efi.systab->runtime->f)(args)
|
||||||
|
|
||||||
|
static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
|
||||||
|
{
|
||||||
|
return efi_call_virt(get_time, tm, tc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static efi_status_t virt_efi_set_time (efi_time_t *tm)
|
||||||
|
{
|
||||||
|
return efi_call_virt(set_time, tm);
|
||||||
|
}
|
||||||
|
|
||||||
|
static efi_status_t virt_efi_get_wakeup_time (efi_bool_t *enabled,
|
||||||
|
efi_bool_t *pending,
|
||||||
|
efi_time_t *tm)
|
||||||
|
{
|
||||||
|
return efi_call_virt(get_wakeup_time, enabled, pending, tm);
|
||||||
|
}
|
||||||
|
|
||||||
|
static efi_status_t virt_efi_set_wakeup_time (efi_bool_t enabled,
|
||||||
|
efi_time_t *tm)
|
||||||
|
{
|
||||||
|
return efi_call_virt(set_wakeup_time, enabled, tm);
|
||||||
|
}
|
||||||
|
|
||||||
|
static efi_status_t virt_efi_get_variable (efi_char16_t *name,
|
||||||
|
efi_guid_t *vendor, u32 *attr,
|
||||||
|
unsigned long *data_size, void *data)
|
||||||
|
{
|
||||||
|
return efi_call_virt(get_variable, name, vendor, attr, data_size, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static efi_status_t virt_efi_get_next_variable (unsigned long *name_size,
|
||||||
|
efi_char16_t *name,
|
||||||
|
efi_guid_t *vendor)
|
||||||
|
{
|
||||||
|
return efi_call_virt(get_next_variable, name_size, name, vendor);
|
||||||
|
}
|
||||||
|
|
||||||
|
static efi_status_t virt_efi_set_variable (efi_char16_t *name,
|
||||||
|
efi_guid_t *vendor,
|
||||||
|
unsigned long attr,
|
||||||
|
unsigned long data_size, void *data)
|
||||||
|
{
|
||||||
|
return efi_call_virt(set_variable, name, vendor, attr, data_size, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static efi_status_t virt_efi_get_next_high_mono_count (u32 *count)
|
||||||
|
{
|
||||||
|
return efi_call_virt(get_next_high_mono_count, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void virt_efi_reset_system (int reset_type, efi_status_t status,
|
||||||
|
unsigned long data_size,
|
||||||
|
efi_char16_t *data)
|
||||||
|
{
|
||||||
|
efi_call_virt(reset_system, reset_type, status, data_size, data);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function will switch the EFI runtime services to virtual mode.
|
* This function will switch the EFI runtime services to virtual mode.
|
||||||
* Essentially, look through the EFI memmap and map every region that
|
* Essentially, look through the EFI memmap and map every region that
|
||||||
|
@ -525,22 +589,15 @@ void __init efi_enter_virtual_mode(void)
|
||||||
* pointers in the runtime service table to the new virtual addresses.
|
* pointers in the runtime service table to the new virtual addresses.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
efi.get_time = (efi_get_time_t *) efi.systab->runtime->get_time;
|
efi.get_time = virt_efi_get_time;
|
||||||
efi.set_time = (efi_set_time_t *) efi.systab->runtime->set_time;
|
efi.set_time = virt_efi_set_time;
|
||||||
efi.get_wakeup_time = (efi_get_wakeup_time_t *)
|
efi.get_wakeup_time = virt_efi_get_wakeup_time;
|
||||||
efi.systab->runtime->get_wakeup_time;
|
efi.set_wakeup_time = virt_efi_set_wakeup_time;
|
||||||
efi.set_wakeup_time = (efi_set_wakeup_time_t *)
|
efi.get_variable = virt_efi_get_variable;
|
||||||
efi.systab->runtime->set_wakeup_time;
|
efi.get_next_variable = virt_efi_get_next_variable;
|
||||||
efi.get_variable = (efi_get_variable_t *)
|
efi.set_variable = virt_efi_set_variable;
|
||||||
efi.systab->runtime->get_variable;
|
efi.get_next_high_mono_count = virt_efi_get_next_high_mono_count;
|
||||||
efi.get_next_variable = (efi_get_next_variable_t *)
|
efi.reset_system = virt_efi_reset_system;
|
||||||
efi.systab->runtime->get_next_variable;
|
|
||||||
efi.set_variable = (efi_set_variable_t *)
|
|
||||||
efi.systab->runtime->set_variable;
|
|
||||||
efi.get_next_high_mono_count = (efi_get_next_high_mono_count_t *)
|
|
||||||
efi.systab->runtime->get_next_high_mono_count;
|
|
||||||
efi.reset_system = (efi_reset_system_t *)
|
|
||||||
efi.systab->runtime->reset_system;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void __init
|
void __init
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
/* FSEC = 10^-15 NSEC = 10^-9 */
|
/* FSEC = 10^-15 NSEC = 10^-9 */
|
||||||
#define FSEC_PER_NSEC 1000000
|
#define FSEC_PER_NSEC 1000000
|
||||||
|
|
||||||
static void *hpet_ptr;
|
static void __iomem *hpet_ptr;
|
||||||
|
|
||||||
static cycle_t read_hpet(void)
|
static cycle_t read_hpet(void)
|
||||||
{
|
{
|
||||||
|
@ -40,8 +40,7 @@ static int __init init_hpet_clocksource(void)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
/* calculate the hpet address: */
|
/* calculate the hpet address: */
|
||||||
hpet_base =
|
hpet_base = ioremap_nocache(hpet_address, HPET_MMAP_SIZE);
|
||||||
(void __iomem*)ioremap_nocache(hpet_address, HPET_MMAP_SIZE);
|
|
||||||
hpet_ptr = hpet_base + HPET_COUNTER;
|
hpet_ptr = hpet_base + HPET_COUNTER;
|
||||||
|
|
||||||
/* calculate the frequency: */
|
/* calculate the frequency: */
|
||||||
|
|
|
@ -126,7 +126,7 @@ static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned i
|
||||||
*/
|
*/
|
||||||
static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value)
|
static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value)
|
||||||
{
|
{
|
||||||
volatile struct io_apic *io_apic = io_apic_base(apic);
|
volatile struct io_apic __iomem *io_apic = io_apic_base(apic);
|
||||||
if (sis_apic_bug)
|
if (sis_apic_bug)
|
||||||
writel(reg, &io_apic->index);
|
writel(reg, &io_apic->index);
|
||||||
writel(value, &io_apic->data);
|
writel(value, &io_apic->data);
|
||||||
|
@ -2606,25 +2606,32 @@ static struct irq_chip msi_chip = {
|
||||||
.retrigger = ioapic_retrigger_irq,
|
.retrigger = ioapic_retrigger_irq,
|
||||||
};
|
};
|
||||||
|
|
||||||
int arch_setup_msi_irq(unsigned int irq, struct pci_dev *dev)
|
int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
|
||||||
{
|
{
|
||||||
struct msi_msg msg;
|
struct msi_msg msg;
|
||||||
int ret;
|
int irq, ret;
|
||||||
|
irq = create_irq();
|
||||||
|
if (irq < 0)
|
||||||
|
return irq;
|
||||||
|
|
||||||
|
set_irq_msi(irq, desc);
|
||||||
ret = msi_compose_msg(dev, irq, &msg);
|
ret = msi_compose_msg(dev, irq, &msg);
|
||||||
if (ret < 0)
|
if (ret < 0) {
|
||||||
|
destroy_irq(irq);
|
||||||
return ret;
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
write_msi_msg(irq, &msg);
|
write_msi_msg(irq, &msg);
|
||||||
|
|
||||||
set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq,
|
set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq,
|
||||||
"edge");
|
"edge");
|
||||||
|
|
||||||
return 0;
|
return irq;
|
||||||
}
|
}
|
||||||
|
|
||||||
void arch_teardown_msi_irq(unsigned int irq)
|
void arch_teardown_msi_irq(unsigned int irq)
|
||||||
{
|
{
|
||||||
return;
|
destroy_irq(irq);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_PCI_MSI */
|
#endif /* CONFIG_PCI_MSI */
|
||||||
|
|
|
@ -1057,7 +1057,7 @@ int mp_register_gsi(u32 gsi, int triggering, int polarity)
|
||||||
static int gsi_to_irq[MAX_GSI_NUM];
|
static int gsi_to_irq[MAX_GSI_NUM];
|
||||||
|
|
||||||
/* Don't set up the ACPI SCI because it's already set up */
|
/* Don't set up the ACPI SCI because it's already set up */
|
||||||
if (acpi_fadt.sci_int == gsi)
|
if (acpi_gbl_FADT.sci_interrupt == gsi)
|
||||||
return gsi;
|
return gsi;
|
||||||
|
|
||||||
ioapic = mp_find_ioapic(gsi);
|
ioapic = mp_find_ioapic(gsi);
|
||||||
|
@ -1114,7 +1114,7 @@ int mp_register_gsi(u32 gsi, int triggering, int polarity)
|
||||||
/*
|
/*
|
||||||
* Don't assign IRQ used by ACPI SCI
|
* Don't assign IRQ used by ACPI SCI
|
||||||
*/
|
*/
|
||||||
if (gsi == acpi_fadt.sci_int)
|
if (gsi == acpi_gbl_FADT.sci_interrupt)
|
||||||
gsi = pci_irq++;
|
gsi = pci_irq++;
|
||||||
gsi_to_irq[irq] = gsi;
|
gsi_to_irq[irq] = gsi;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -62,19 +62,19 @@ extern void * boot_ioremap(unsigned long, unsigned long);
|
||||||
/* Identify CPU proximity domains */
|
/* Identify CPU proximity domains */
|
||||||
static void __init parse_cpu_affinity_structure(char *p)
|
static void __init parse_cpu_affinity_structure(char *p)
|
||||||
{
|
{
|
||||||
struct acpi_table_processor_affinity *cpu_affinity =
|
struct acpi_srat_cpu_affinity *cpu_affinity =
|
||||||
(struct acpi_table_processor_affinity *) p;
|
(struct acpi_srat_cpu_affinity *) p;
|
||||||
|
|
||||||
if (!cpu_affinity->flags.enabled)
|
if ((cpu_affinity->flags & ACPI_SRAT_CPU_ENABLED) == 0)
|
||||||
return; /* empty entry */
|
return; /* empty entry */
|
||||||
|
|
||||||
/* mark this node as "seen" in node bitmap */
|
/* mark this node as "seen" in node bitmap */
|
||||||
BMAP_SET(pxm_bitmap, cpu_affinity->proximity_domain);
|
BMAP_SET(pxm_bitmap, cpu_affinity->proximity_domain_lo);
|
||||||
|
|
||||||
apicid_to_pxm[cpu_affinity->apic_id] = cpu_affinity->proximity_domain;
|
apicid_to_pxm[cpu_affinity->apic_id] = cpu_affinity->proximity_domain_lo;
|
||||||
|
|
||||||
printk("CPU 0x%02X in proximity domain 0x%02X\n",
|
printk("CPU 0x%02X in proximity domain 0x%02X\n",
|
||||||
cpu_affinity->apic_id, cpu_affinity->proximity_domain);
|
cpu_affinity->apic_id, cpu_affinity->proximity_domain_lo);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -84,28 +84,27 @@ static void __init parse_cpu_affinity_structure(char *p)
|
||||||
static void __init parse_memory_affinity_structure (char *sratp)
|
static void __init parse_memory_affinity_structure (char *sratp)
|
||||||
{
|
{
|
||||||
unsigned long long paddr, size;
|
unsigned long long paddr, size;
|
||||||
unsigned long start_pfn, end_pfn;
|
unsigned long start_pfn, end_pfn;
|
||||||
u8 pxm;
|
u8 pxm;
|
||||||
struct node_memory_chunk_s *p, *q, *pend;
|
struct node_memory_chunk_s *p, *q, *pend;
|
||||||
struct acpi_table_memory_affinity *memory_affinity =
|
struct acpi_srat_mem_affinity *memory_affinity =
|
||||||
(struct acpi_table_memory_affinity *) sratp;
|
(struct acpi_srat_mem_affinity *) sratp;
|
||||||
|
|
||||||
if (!memory_affinity->flags.enabled)
|
if ((memory_affinity->flags & ACPI_SRAT_MEM_ENABLED) == 0)
|
||||||
return; /* empty entry */
|
return; /* empty entry */
|
||||||
|
|
||||||
|
pxm = memory_affinity->proximity_domain & 0xff;
|
||||||
|
|
||||||
/* mark this node as "seen" in node bitmap */
|
/* mark this node as "seen" in node bitmap */
|
||||||
BMAP_SET(pxm_bitmap, memory_affinity->proximity_domain);
|
BMAP_SET(pxm_bitmap, pxm);
|
||||||
|
|
||||||
/* calculate info for memory chunk structure */
|
/* calculate info for memory chunk structure */
|
||||||
paddr = memory_affinity->base_addr_hi;
|
paddr = memory_affinity->base_address;
|
||||||
paddr = (paddr << 32) | memory_affinity->base_addr_lo;
|
size = memory_affinity->length;
|
||||||
size = memory_affinity->length_hi;
|
|
||||||
size = (size << 32) | memory_affinity->length_lo;
|
|
||||||
|
|
||||||
start_pfn = paddr >> PAGE_SHIFT;
|
start_pfn = paddr >> PAGE_SHIFT;
|
||||||
end_pfn = (paddr + size) >> PAGE_SHIFT;
|
end_pfn = (paddr + size) >> PAGE_SHIFT;
|
||||||
|
|
||||||
pxm = memory_affinity->proximity_domain;
|
|
||||||
|
|
||||||
if (num_memory_chunks >= MAXCHUNKS) {
|
if (num_memory_chunks >= MAXCHUNKS) {
|
||||||
printk("Too many mem chunks in SRAT. Ignoring %lld MBytes at %llx\n",
|
printk("Too many mem chunks in SRAT. Ignoring %lld MBytes at %llx\n",
|
||||||
|
@ -132,8 +131,8 @@ static void __init parse_memory_affinity_structure (char *sratp)
|
||||||
printk("Memory range 0x%lX to 0x%lX (type 0x%X) in proximity domain 0x%02X %s\n",
|
printk("Memory range 0x%lX to 0x%lX (type 0x%X) in proximity domain 0x%02X %s\n",
|
||||||
start_pfn, end_pfn,
|
start_pfn, end_pfn,
|
||||||
memory_affinity->memory_type,
|
memory_affinity->memory_type,
|
||||||
memory_affinity->proximity_domain,
|
pxm,
|
||||||
(memory_affinity->flags.hot_pluggable ?
|
((memory_affinity->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) ?
|
||||||
"enabled and removable" : "enabled" ) );
|
"enabled and removable" : "enabled" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,10 +184,10 @@ static int __init acpi20_parse_srat(struct acpi_table_srat *sratp)
|
||||||
num_memory_chunks = 0;
|
num_memory_chunks = 0;
|
||||||
while (p < end) {
|
while (p < end) {
|
||||||
switch (*p) {
|
switch (*p) {
|
||||||
case ACPI_SRAT_PROCESSOR_AFFINITY:
|
case ACPI_SRAT_TYPE_CPU_AFFINITY:
|
||||||
parse_cpu_affinity_structure(p);
|
parse_cpu_affinity_structure(p);
|
||||||
break;
|
break;
|
||||||
case ACPI_SRAT_MEMORY_AFFINITY:
|
case ACPI_SRAT_TYPE_MEMORY_AFFINITY:
|
||||||
parse_memory_affinity_structure(p);
|
parse_memory_affinity_structure(p);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -262,31 +261,30 @@ out_fail:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct acpi_static_rsdt {
|
||||||
|
struct acpi_table_rsdt table;
|
||||||
|
u32 padding[7]; /* Allow for 7 more table entries */
|
||||||
|
};
|
||||||
|
|
||||||
int __init get_memcfg_from_srat(void)
|
int __init get_memcfg_from_srat(void)
|
||||||
{
|
{
|
||||||
struct acpi_table_header *header = NULL;
|
struct acpi_table_header *header = NULL;
|
||||||
struct acpi_table_rsdp *rsdp = NULL;
|
struct acpi_table_rsdp *rsdp = NULL;
|
||||||
struct acpi_table_rsdt *rsdt = NULL;
|
struct acpi_table_rsdt *rsdt = NULL;
|
||||||
struct acpi_pointer *rsdp_address = NULL;
|
acpi_native_uint rsdp_address = 0;
|
||||||
struct acpi_table_rsdt saved_rsdt;
|
struct acpi_static_rsdt saved_rsdt;
|
||||||
int tables = 0;
|
int tables = 0;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
if (ACPI_FAILURE(acpi_find_root_pointer(ACPI_PHYSICAL_ADDRESSING,
|
rsdp_address = acpi_find_rsdp();
|
||||||
rsdp_address))) {
|
if (!rsdp_address) {
|
||||||
printk("%s: System description tables not found\n",
|
printk("%s: System description tables not found\n",
|
||||||
__FUNCTION__);
|
__FUNCTION__);
|
||||||
goto out_err;
|
goto out_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rsdp_address->pointer_type == ACPI_PHYSICAL_POINTER) {
|
printk("%s: assigning address to rsdp\n", __FUNCTION__);
|
||||||
printk("%s: assigning address to rsdp\n", __FUNCTION__);
|
rsdp = (struct acpi_table_rsdp *)(u32)rsdp_address;
|
||||||
rsdp = (struct acpi_table_rsdp *)
|
|
||||||
(u32)rsdp_address->pointer.physical;
|
|
||||||
} else {
|
|
||||||
printk("%s: rsdp_address is not a physical pointer\n", __FUNCTION__);
|
|
||||||
goto out_err;
|
|
||||||
}
|
|
||||||
if (!rsdp) {
|
if (!rsdp) {
|
||||||
printk("%s: Didn't find ACPI root!\n", __FUNCTION__);
|
printk("%s: Didn't find ACPI root!\n", __FUNCTION__);
|
||||||
goto out_err;
|
goto out_err;
|
||||||
|
@ -295,13 +293,13 @@ int __init get_memcfg_from_srat(void)
|
||||||
printk(KERN_INFO "%.8s v%d [%.6s]\n", rsdp->signature, rsdp->revision,
|
printk(KERN_INFO "%.8s v%d [%.6s]\n", rsdp->signature, rsdp->revision,
|
||||||
rsdp->oem_id);
|
rsdp->oem_id);
|
||||||
|
|
||||||
if (strncmp(rsdp->signature, RSDP_SIG,strlen(RSDP_SIG))) {
|
if (strncmp(rsdp->signature, ACPI_SIG_RSDP,strlen(ACPI_SIG_RSDP))) {
|
||||||
printk(KERN_WARNING "%s: RSDP table signature incorrect\n", __FUNCTION__);
|
printk(KERN_WARNING "%s: RSDP table signature incorrect\n", __FUNCTION__);
|
||||||
goto out_err;
|
goto out_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
rsdt = (struct acpi_table_rsdt *)
|
rsdt = (struct acpi_table_rsdt *)
|
||||||
boot_ioremap(rsdp->rsdt_address, sizeof(struct acpi_table_rsdt));
|
boot_ioremap(rsdp->rsdt_physical_address, sizeof(struct acpi_table_rsdt));
|
||||||
|
|
||||||
if (!rsdt) {
|
if (!rsdt) {
|
||||||
printk(KERN_WARNING
|
printk(KERN_WARNING
|
||||||
|
@ -310,9 +308,9 @@ int __init get_memcfg_from_srat(void)
|
||||||
goto out_err;
|
goto out_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
header = & rsdt->header;
|
header = &rsdt->header;
|
||||||
|
|
||||||
if (strncmp(header->signature, RSDT_SIG, strlen(RSDT_SIG))) {
|
if (strncmp(header->signature, ACPI_SIG_RSDT, strlen(ACPI_SIG_RSDT))) {
|
||||||
printk(KERN_WARNING "ACPI: RSDT signature incorrect\n");
|
printk(KERN_WARNING "ACPI: RSDT signature incorrect\n");
|
||||||
goto out_err;
|
goto out_err;
|
||||||
}
|
}
|
||||||
|
@ -330,9 +328,9 @@ int __init get_memcfg_from_srat(void)
|
||||||
|
|
||||||
memcpy(&saved_rsdt, rsdt, sizeof(saved_rsdt));
|
memcpy(&saved_rsdt, rsdt, sizeof(saved_rsdt));
|
||||||
|
|
||||||
if (saved_rsdt.header.length > sizeof(saved_rsdt)) {
|
if (saved_rsdt.table.header.length > sizeof(saved_rsdt)) {
|
||||||
printk(KERN_WARNING "ACPI: Too big length in RSDT: %d\n",
|
printk(KERN_WARNING "ACPI: Too big length in RSDT: %d\n",
|
||||||
saved_rsdt.header.length);
|
saved_rsdt.table.header.length);
|
||||||
goto out_err;
|
goto out_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -341,15 +339,15 @@ int __init get_memcfg_from_srat(void)
|
||||||
for (i = 0; i < tables; i++) {
|
for (i = 0; i < tables; i++) {
|
||||||
/* Map in header, then map in full table length. */
|
/* Map in header, then map in full table length. */
|
||||||
header = (struct acpi_table_header *)
|
header = (struct acpi_table_header *)
|
||||||
boot_ioremap(saved_rsdt.entry[i], sizeof(struct acpi_table_header));
|
boot_ioremap(saved_rsdt.table.table_offset_entry[i], sizeof(struct acpi_table_header));
|
||||||
if (!header)
|
if (!header)
|
||||||
break;
|
break;
|
||||||
header = (struct acpi_table_header *)
|
header = (struct acpi_table_header *)
|
||||||
boot_ioremap(saved_rsdt.entry[i], header->length);
|
boot_ioremap(saved_rsdt.table.table_offset_entry[i], header->length);
|
||||||
if (!header)
|
if (!header)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (strncmp((char *) &header->signature, "SRAT", 4))
|
if (strncmp((char *) &header->signature, ACPI_SIG_SRAT, 4))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* we've found the srat table. don't need to look at any more tables */
|
/* we've found the srat table. don't need to look at any more tables */
|
||||||
|
|
|
@ -70,11 +70,12 @@ void enable_sep_cpu(void)
|
||||||
*/
|
*/
|
||||||
extern const char vsyscall_int80_start, vsyscall_int80_end;
|
extern const char vsyscall_int80_start, vsyscall_int80_end;
|
||||||
extern const char vsyscall_sysenter_start, vsyscall_sysenter_end;
|
extern const char vsyscall_sysenter_start, vsyscall_sysenter_end;
|
||||||
static void *syscall_page;
|
static struct page *syscall_pages[1];
|
||||||
|
|
||||||
int __init sysenter_setup(void)
|
int __init sysenter_setup(void)
|
||||||
{
|
{
|
||||||
syscall_page = (void *)get_zeroed_page(GFP_ATOMIC);
|
void *syscall_page = (void *)get_zeroed_page(GFP_ATOMIC);
|
||||||
|
syscall_pages[0] = virt_to_page(syscall_page);
|
||||||
|
|
||||||
#ifdef CONFIG_COMPAT_VDSO
|
#ifdef CONFIG_COMPAT_VDSO
|
||||||
__set_fixmap(FIX_VDSO, __pa(syscall_page), PAGE_READONLY);
|
__set_fixmap(FIX_VDSO, __pa(syscall_page), PAGE_READONLY);
|
||||||
|
@ -96,31 +97,12 @@ int __init sysenter_setup(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef CONFIG_COMPAT_VDSO
|
#ifndef CONFIG_COMPAT_VDSO
|
||||||
static struct page *syscall_nopage(struct vm_area_struct *vma,
|
|
||||||
unsigned long adr, int *type)
|
|
||||||
{
|
|
||||||
struct page *p = virt_to_page(adr - vma->vm_start + syscall_page);
|
|
||||||
get_page(p);
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Prevent VMA merging */
|
|
||||||
static void syscall_vma_close(struct vm_area_struct *vma)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct vm_operations_struct syscall_vm_ops = {
|
|
||||||
.close = syscall_vma_close,
|
|
||||||
.nopage = syscall_nopage,
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Defined in vsyscall-sysenter.S */
|
/* Defined in vsyscall-sysenter.S */
|
||||||
extern void SYSENTER_RETURN;
|
extern void SYSENTER_RETURN;
|
||||||
|
|
||||||
/* Setup a VMA at program startup for the vsyscall page */
|
/* Setup a VMA at program startup for the vsyscall page */
|
||||||
int arch_setup_additional_pages(struct linux_binprm *bprm, int exstack)
|
int arch_setup_additional_pages(struct linux_binprm *bprm, int exstack)
|
||||||
{
|
{
|
||||||
struct vm_area_struct *vma;
|
|
||||||
struct mm_struct *mm = current->mm;
|
struct mm_struct *mm = current->mm;
|
||||||
unsigned long addr;
|
unsigned long addr;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -132,38 +114,25 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int exstack)
|
||||||
goto up_fail;
|
goto up_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
|
|
||||||
if (!vma) {
|
|
||||||
ret = -ENOMEM;
|
|
||||||
goto up_fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
vma->vm_start = addr;
|
|
||||||
vma->vm_end = addr + PAGE_SIZE;
|
|
||||||
/* MAYWRITE to allow gdb to COW and set breakpoints */
|
|
||||||
vma->vm_flags = VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYEXEC|VM_MAYWRITE;
|
|
||||||
/*
|
/*
|
||||||
|
* MAYWRITE to allow gdb to COW and set breakpoints
|
||||||
|
*
|
||||||
* Make sure the vDSO gets into every core dump.
|
* Make sure the vDSO gets into every core dump.
|
||||||
* Dumping its contents makes post-mortem fully interpretable later
|
* Dumping its contents makes post-mortem fully interpretable later
|
||||||
* without matching up the same kernel and hardware config to see
|
* without matching up the same kernel and hardware config to see
|
||||||
* what PC values meant.
|
* what PC values meant.
|
||||||
*/
|
*/
|
||||||
vma->vm_flags |= VM_ALWAYSDUMP;
|
ret = install_special_mapping(mm, addr, PAGE_SIZE,
|
||||||
vma->vm_flags |= mm->def_flags;
|
VM_READ|VM_EXEC|
|
||||||
vma->vm_page_prot = protection_map[vma->vm_flags & 7];
|
VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC|
|
||||||
vma->vm_ops = &syscall_vm_ops;
|
VM_ALWAYSDUMP,
|
||||||
vma->vm_mm = mm;
|
syscall_pages);
|
||||||
|
if (ret)
|
||||||
ret = insert_vm_struct(mm, vma);
|
|
||||||
if (unlikely(ret)) {
|
|
||||||
kmem_cache_free(vm_area_cachep, vma);
|
|
||||||
goto up_fail;
|
goto up_fail;
|
||||||
}
|
|
||||||
|
|
||||||
current->mm->context.vdso = (void *)addr;
|
current->mm->context.vdso = (void *)addr;
|
||||||
current_thread_info()->sysenter_return =
|
current_thread_info()->sysenter_return =
|
||||||
(void *)VDSO_SYM(&SYSENTER_RETURN);
|
(void *)VDSO_SYM(&SYSENTER_RETURN);
|
||||||
mm->total_vm++;
|
|
||||||
up_fail:
|
up_fail:
|
||||||
up_write(&mm->mmap_sem);
|
up_write(&mm->mmap_sem);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -102,7 +102,7 @@ void __init time_init_hook(void)
|
||||||
* along the MCA bus. Use this to hook into that chain if you will need
|
* along the MCA bus. Use this to hook into that chain if you will need
|
||||||
* it.
|
* it.
|
||||||
**/
|
**/
|
||||||
void __init mca_nmi_hook(void)
|
void mca_nmi_hook(void)
|
||||||
{
|
{
|
||||||
/* If I recall correctly, there's a whole bunch of other things that
|
/* If I recall correctly, there's a whole bunch of other things that
|
||||||
* we can do to check for NMI problems, but that's all I know about
|
* we can do to check for NMI problems, but that's all I know about
|
||||||
|
|
|
@ -84,15 +84,6 @@ struct es7000_oem_table {
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_ACPI
|
#ifdef CONFIG_ACPI
|
||||||
struct acpi_table_sdt {
|
|
||||||
unsigned long pa;
|
|
||||||
unsigned long count;
|
|
||||||
struct {
|
|
||||||
unsigned long pa;
|
|
||||||
enum acpi_table_id id;
|
|
||||||
unsigned long size;
|
|
||||||
} entry[50];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct oem_table {
|
struct oem_table {
|
||||||
struct acpi_table_header Header;
|
struct acpi_table_header Header;
|
||||||
|
|
|
@ -160,51 +160,14 @@ parse_unisys_oem (char *oemptr)
|
||||||
int __init
|
int __init
|
||||||
find_unisys_acpi_oem_table(unsigned long *oem_addr)
|
find_unisys_acpi_oem_table(unsigned long *oem_addr)
|
||||||
{
|
{
|
||||||
struct acpi_table_rsdp *rsdp = NULL;
|
struct acpi_table_header *header = NULL;
|
||||||
unsigned long rsdp_phys = 0;
|
int i = 0;
|
||||||
struct acpi_table_header *header = NULL;
|
while (ACPI_SUCCESS(acpi_get_table("OEM1", i++, &header))) {
|
||||||
int i;
|
if (!memcmp((char *) &header->oem_id, "UNISYS", 6)) {
|
||||||
struct acpi_table_sdt sdt;
|
struct oem_table *t = (struct oem_table *)header;
|
||||||
|
*oem_addr = (unsigned long)__acpi_map_table(t->OEMTableAddr,
|
||||||
rsdp_phys = acpi_find_rsdp();
|
t->OEMTableSize);
|
||||||
rsdp = __va(rsdp_phys);
|
return 0;
|
||||||
if (rsdp->rsdt_address) {
|
|
||||||
struct acpi_table_rsdt *mapped_rsdt = NULL;
|
|
||||||
sdt.pa = rsdp->rsdt_address;
|
|
||||||
|
|
||||||
header = (struct acpi_table_header *)
|
|
||||||
__acpi_map_table(sdt.pa, sizeof(struct acpi_table_header));
|
|
||||||
if (!header)
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
sdt.count = (header->length - sizeof(struct acpi_table_header)) >> 3;
|
|
||||||
mapped_rsdt = (struct acpi_table_rsdt *)
|
|
||||||
__acpi_map_table(sdt.pa, header->length);
|
|
||||||
if (!mapped_rsdt)
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
header = &mapped_rsdt->header;
|
|
||||||
|
|
||||||
for (i = 0; i < sdt.count; i++)
|
|
||||||
sdt.entry[i].pa = (unsigned long) mapped_rsdt->entry[i];
|
|
||||||
};
|
|
||||||
for (i = 0; i < sdt.count; i++) {
|
|
||||||
|
|
||||||
header = (struct acpi_table_header *)
|
|
||||||
__acpi_map_table(sdt.entry[i].pa,
|
|
||||||
sizeof(struct acpi_table_header));
|
|
||||||
if (!header)
|
|
||||||
continue;
|
|
||||||
if (!strncmp((char *) &header->signature, "OEM1", 4)) {
|
|
||||||
if (!strncmp((char *) &header->oem_id, "UNISYS", 6)) {
|
|
||||||
void *addr;
|
|
||||||
struct oem_table *t;
|
|
||||||
acpi_table_print(header, sdt.entry[i].pa);
|
|
||||||
t = (struct oem_table *) __acpi_map_table(sdt.entry[i].pa, header->length);
|
|
||||||
addr = (void *) __acpi_map_table(t->OEMTableAddr, t->OEMTableSize);
|
|
||||||
*oem_addr = (unsigned long) addr;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -224,7 +224,7 @@ void global_flush_tlb(void)
|
||||||
list_replace_init(&df_list, &l);
|
list_replace_init(&df_list, &l);
|
||||||
spin_unlock_irq(&cpa_lock);
|
spin_unlock_irq(&cpa_lock);
|
||||||
if (!cpu_has_clflush)
|
if (!cpu_has_clflush)
|
||||||
flush_map(0);
|
flush_map(NULL);
|
||||||
list_for_each_entry_safe(pg, next, &l, lru) {
|
list_for_each_entry_safe(pg, next, &l, lru) {
|
||||||
if (cpu_has_clflush)
|
if (cpu_has_clflush)
|
||||||
flush_map(page_address(pg));
|
flush_map(page_address(pg));
|
||||||
|
|
|
@ -36,7 +36,7 @@ static DECLARE_BITMAP(fallback_slots, MAX_CHECK_BUS*32);
|
||||||
static u32 get_base_addr(unsigned int seg, int bus, unsigned devfn)
|
static u32 get_base_addr(unsigned int seg, int bus, unsigned devfn)
|
||||||
{
|
{
|
||||||
int cfg_num = -1;
|
int cfg_num = -1;
|
||||||
struct acpi_table_mcfg_config *cfg;
|
struct acpi_mcfg_allocation *cfg;
|
||||||
|
|
||||||
if (seg == 0 && bus < MAX_CHECK_BUS &&
|
if (seg == 0 && bus < MAX_CHECK_BUS &&
|
||||||
test_bit(PCI_SLOT(devfn) + 32*bus, fallback_slots))
|
test_bit(PCI_SLOT(devfn) + 32*bus, fallback_slots))
|
||||||
|
@ -48,11 +48,11 @@ static u32 get_base_addr(unsigned int seg, int bus, unsigned devfn)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
cfg = &pci_mmcfg_config[cfg_num];
|
cfg = &pci_mmcfg_config[cfg_num];
|
||||||
if (cfg->pci_segment_group_number != seg)
|
if (cfg->pci_segment != seg)
|
||||||
continue;
|
continue;
|
||||||
if ((cfg->start_bus_number <= bus) &&
|
if ((cfg->start_bus_number <= bus) &&
|
||||||
(cfg->end_bus_number >= bus))
|
(cfg->end_bus_number >= bus))
|
||||||
return cfg->base_address;
|
return cfg->address;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle more broken MCFG tables on Asus etc.
|
/* Handle more broken MCFG tables on Asus etc.
|
||||||
|
@ -60,9 +60,9 @@ static u32 get_base_addr(unsigned int seg, int bus, unsigned devfn)
|
||||||
this applies to all busses. */
|
this applies to all busses. */
|
||||||
cfg = &pci_mmcfg_config[0];
|
cfg = &pci_mmcfg_config[0];
|
||||||
if (pci_mmcfg_config_num == 1 &&
|
if (pci_mmcfg_config_num == 1 &&
|
||||||
cfg->pci_segment_group_number == 0 &&
|
cfg->pci_segment == 0 &&
|
||||||
(cfg->start_bus_number | cfg->end_bus_number) == 0)
|
(cfg->start_bus_number | cfg->end_bus_number) == 0)
|
||||||
return cfg->base_address;
|
return cfg->address;
|
||||||
|
|
||||||
/* Fall back to type 0 */
|
/* Fall back to type 0 */
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -125,7 +125,7 @@ static int pci_mmcfg_write(unsigned int seg, unsigned int bus,
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
u32 base;
|
u32 base;
|
||||||
|
|
||||||
if ((bus > 255) || (devfn > 255) || (reg > 4095))
|
if ((bus > 255) || (devfn > 255) || (reg > 4095))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
base = get_base_addr(seg, bus, devfn);
|
base = get_base_addr(seg, bus, devfn);
|
||||||
|
@ -199,19 +199,19 @@ void __init pci_mmcfg_init(int type)
|
||||||
if ((pci_probe & PCI_PROBE_MMCONF) == 0)
|
if ((pci_probe & PCI_PROBE_MMCONF) == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg);
|
acpi_table_parse(ACPI_SIG_MCFG, acpi_parse_mcfg);
|
||||||
if ((pci_mmcfg_config_num == 0) ||
|
if ((pci_mmcfg_config_num == 0) ||
|
||||||
(pci_mmcfg_config == NULL) ||
|
(pci_mmcfg_config == NULL) ||
|
||||||
(pci_mmcfg_config[0].base_address == 0))
|
(pci_mmcfg_config[0].address == 0))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Only do this check when type 1 works. If it doesn't work
|
/* Only do this check when type 1 works. If it doesn't work
|
||||||
assume we run on a Mac and always use MCFG */
|
assume we run on a Mac and always use MCFG */
|
||||||
if (type == 1 && !e820_all_mapped(pci_mmcfg_config[0].base_address,
|
if (type == 1 && !e820_all_mapped(pci_mmcfg_config[0].address,
|
||||||
pci_mmcfg_config[0].base_address + MMCONFIG_APER_MIN,
|
pci_mmcfg_config[0].address + MMCONFIG_APER_MIN,
|
||||||
E820_RESERVED)) {
|
E820_RESERVED)) {
|
||||||
printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %x is not E820-reserved\n",
|
printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %lx is not E820-reserved\n",
|
||||||
pci_mmcfg_config[0].base_address);
|
(unsigned long)pci_mmcfg_config[0].address);
|
||||||
printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
|
printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,8 @@ menu "Processor type and features"
|
||||||
|
|
||||||
config IA64
|
config IA64
|
||||||
bool
|
bool
|
||||||
|
select PCI if (!IA64_HP_SIM)
|
||||||
|
select ACPI if (!IA64_HP_SIM)
|
||||||
default y
|
default y
|
||||||
help
|
help
|
||||||
The Itanium Processor Family is Intel's 64-bit successor to
|
The Itanium Processor Family is Intel's 64-bit successor to
|
||||||
|
@ -28,7 +30,6 @@ config MMU
|
||||||
|
|
||||||
config SWIOTLB
|
config SWIOTLB
|
||||||
bool
|
bool
|
||||||
default y
|
|
||||||
|
|
||||||
config RWSEM_XCHGADD_ALGORITHM
|
config RWSEM_XCHGADD_ALGORITHM
|
||||||
bool
|
bool
|
||||||
|
@ -84,10 +85,9 @@ choice
|
||||||
|
|
||||||
config IA64_GENERIC
|
config IA64_GENERIC
|
||||||
bool "generic"
|
bool "generic"
|
||||||
select ACPI
|
|
||||||
select PCI
|
|
||||||
select NUMA
|
select NUMA
|
||||||
select ACPI_NUMA
|
select ACPI_NUMA
|
||||||
|
select SWIOTLB
|
||||||
help
|
help
|
||||||
This selects the system type of your hardware. A "generic" kernel
|
This selects the system type of your hardware. A "generic" kernel
|
||||||
will run on any supported IA-64 system. However, if you configure
|
will run on any supported IA-64 system. However, if you configure
|
||||||
|
@ -104,6 +104,7 @@ config IA64_GENERIC
|
||||||
|
|
||||||
config IA64_DIG
|
config IA64_DIG
|
||||||
bool "DIG-compliant"
|
bool "DIG-compliant"
|
||||||
|
select SWIOTLB
|
||||||
|
|
||||||
config IA64_HP_ZX1
|
config IA64_HP_ZX1
|
||||||
bool "HP-zx1/sx1000"
|
bool "HP-zx1/sx1000"
|
||||||
|
@ -113,6 +114,7 @@ config IA64_HP_ZX1
|
||||||
|
|
||||||
config IA64_HP_ZX1_SWIOTLB
|
config IA64_HP_ZX1_SWIOTLB
|
||||||
bool "HP-zx1/sx1000 with software I/O TLB"
|
bool "HP-zx1/sx1000 with software I/O TLB"
|
||||||
|
select SWIOTLB
|
||||||
help
|
help
|
||||||
Build a kernel that runs on HP zx1 and sx1000 systems even when they
|
Build a kernel that runs on HP zx1 and sx1000 systems even when they
|
||||||
have broken PCI devices which cannot DMA to full 32 bits. Apart
|
have broken PCI devices which cannot DMA to full 32 bits. Apart
|
||||||
|
@ -131,6 +133,7 @@ config IA64_SGI_SN2
|
||||||
|
|
||||||
config IA64_HP_SIM
|
config IA64_HP_SIM
|
||||||
bool "Ski-simulator"
|
bool "Ski-simulator"
|
||||||
|
select SWIOTLB
|
||||||
|
|
||||||
endchoice
|
endchoice
|
||||||
|
|
||||||
|
|
|
@ -192,3 +192,7 @@ EXPORT_SYMBOL(hwsw_unmap_sg);
|
||||||
EXPORT_SYMBOL(hwsw_dma_supported);
|
EXPORT_SYMBOL(hwsw_dma_supported);
|
||||||
EXPORT_SYMBOL(hwsw_alloc_coherent);
|
EXPORT_SYMBOL(hwsw_alloc_coherent);
|
||||||
EXPORT_SYMBOL(hwsw_free_coherent);
|
EXPORT_SYMBOL(hwsw_free_coherent);
|
||||||
|
EXPORT_SYMBOL(hwsw_sync_single_for_cpu);
|
||||||
|
EXPORT_SYMBOL(hwsw_sync_single_for_device);
|
||||||
|
EXPORT_SYMBOL(hwsw_sync_sg_for_cpu);
|
||||||
|
EXPORT_SYMBOL(hwsw_sync_sg_for_device);
|
||||||
|
|
|
@ -55,7 +55,7 @@
|
||||||
|
|
||||||
#define BAD_MADT_ENTRY(entry, end) ( \
|
#define BAD_MADT_ENTRY(entry, end) ( \
|
||||||
(!entry) || (unsigned long)entry + sizeof(*entry) > end || \
|
(!entry) || (unsigned long)entry + sizeof(*entry) > end || \
|
||||||
((acpi_table_entry_header *)entry)->length < sizeof(*entry))
|
((struct acpi_subtable_header *)entry)->length < sizeof(*entry))
|
||||||
|
|
||||||
#define PREFIX "ACPI: "
|
#define PREFIX "ACPI: "
|
||||||
|
|
||||||
|
@ -67,16 +67,11 @@ EXPORT_SYMBOL(pm_power_off);
|
||||||
unsigned int acpi_cpei_override;
|
unsigned int acpi_cpei_override;
|
||||||
unsigned int acpi_cpei_phys_cpuid;
|
unsigned int acpi_cpei_phys_cpuid;
|
||||||
|
|
||||||
#define MAX_SAPICS 256
|
|
||||||
u16 ia64_acpiid_to_sapicid[MAX_SAPICS] = {[0 ... MAX_SAPICS - 1] = -1 };
|
|
||||||
|
|
||||||
EXPORT_SYMBOL(ia64_acpiid_to_sapicid);
|
|
||||||
|
|
||||||
const char *acpi_get_sysname(void)
|
const char *acpi_get_sysname(void)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_IA64_GENERIC
|
#ifdef CONFIG_IA64_GENERIC
|
||||||
unsigned long rsdp_phys;
|
unsigned long rsdp_phys;
|
||||||
struct acpi20_table_rsdp *rsdp;
|
struct acpi_table_rsdp *rsdp;
|
||||||
struct acpi_table_xsdt *xsdt;
|
struct acpi_table_xsdt *xsdt;
|
||||||
struct acpi_table_header *hdr;
|
struct acpi_table_header *hdr;
|
||||||
|
|
||||||
|
@ -87,16 +82,16 @@ const char *acpi_get_sysname(void)
|
||||||
return "dig";
|
return "dig";
|
||||||
}
|
}
|
||||||
|
|
||||||
rsdp = (struct acpi20_table_rsdp *)__va(rsdp_phys);
|
rsdp = (struct acpi_table_rsdp *)__va(rsdp_phys);
|
||||||
if (strncmp(rsdp->signature, RSDP_SIG, sizeof(RSDP_SIG) - 1)) {
|
if (strncmp(rsdp->signature, ACPI_SIG_RSDP, sizeof(ACPI_SIG_RSDP) - 1)) {
|
||||||
printk(KERN_ERR
|
printk(KERN_ERR
|
||||||
"ACPI 2.0 RSDP signature incorrect, default to \"dig\"\n");
|
"ACPI 2.0 RSDP signature incorrect, default to \"dig\"\n");
|
||||||
return "dig";
|
return "dig";
|
||||||
}
|
}
|
||||||
|
|
||||||
xsdt = (struct acpi_table_xsdt *)__va(rsdp->xsdt_address);
|
xsdt = (struct acpi_table_xsdt *)__va(rsdp->xsdt_physical_address);
|
||||||
hdr = &xsdt->header;
|
hdr = &xsdt->header;
|
||||||
if (strncmp(hdr->signature, XSDT_SIG, sizeof(XSDT_SIG) - 1)) {
|
if (strncmp(hdr->signature, ACPI_SIG_XSDT, sizeof(ACPI_SIG_XSDT) - 1)) {
|
||||||
printk(KERN_ERR
|
printk(KERN_ERR
|
||||||
"ACPI 2.0 XSDT signature incorrect, default to \"dig\"\n");
|
"ACPI 2.0 XSDT signature incorrect, default to \"dig\"\n");
|
||||||
return "dig";
|
return "dig";
|
||||||
|
@ -169,12 +164,12 @@ struct acpi_table_madt *acpi_madt __initdata;
|
||||||
static u8 has_8259;
|
static u8 has_8259;
|
||||||
|
|
||||||
static int __init
|
static int __init
|
||||||
acpi_parse_lapic_addr_ovr(acpi_table_entry_header * header,
|
acpi_parse_lapic_addr_ovr(struct acpi_subtable_header * header,
|
||||||
const unsigned long end)
|
const unsigned long end)
|
||||||
{
|
{
|
||||||
struct acpi_table_lapic_addr_ovr *lapic;
|
struct acpi_madt_local_apic_override *lapic;
|
||||||
|
|
||||||
lapic = (struct acpi_table_lapic_addr_ovr *)header;
|
lapic = (struct acpi_madt_local_apic_override *)header;
|
||||||
|
|
||||||
if (BAD_MADT_ENTRY(lapic, end))
|
if (BAD_MADT_ENTRY(lapic, end))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -187,22 +182,19 @@ acpi_parse_lapic_addr_ovr(acpi_table_entry_header * header,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init
|
static int __init
|
||||||
acpi_parse_lsapic(acpi_table_entry_header * header, const unsigned long end)
|
acpi_parse_lsapic(struct acpi_subtable_header * header, const unsigned long end)
|
||||||
{
|
{
|
||||||
struct acpi_table_lsapic *lsapic;
|
struct acpi_madt_local_sapic *lsapic;
|
||||||
|
|
||||||
lsapic = (struct acpi_table_lsapic *)header;
|
lsapic = (struct acpi_madt_local_sapic *)header;
|
||||||
|
|
||||||
if (BAD_MADT_ENTRY(lsapic, end))
|
/*Skip BAD_MADT_ENTRY check, as lsapic size could vary */
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
if (lsapic->flags.enabled) {
|
if (lsapic->lapic_flags & ACPI_MADT_ENABLED) {
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
smp_boot_data.cpu_phys_id[available_cpus] =
|
smp_boot_data.cpu_phys_id[available_cpus] =
|
||||||
(lsapic->id << 8) | lsapic->eid;
|
(lsapic->id << 8) | lsapic->eid;
|
||||||
#endif
|
#endif
|
||||||
ia64_acpiid_to_sapicid[lsapic->acpi_id] =
|
|
||||||
(lsapic->id << 8) | lsapic->eid;
|
|
||||||
++available_cpus;
|
++available_cpus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,11 +203,11 @@ acpi_parse_lsapic(acpi_table_entry_header * header, const unsigned long end)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init
|
static int __init
|
||||||
acpi_parse_lapic_nmi(acpi_table_entry_header * header, const unsigned long end)
|
acpi_parse_lapic_nmi(struct acpi_subtable_header * header, const unsigned long end)
|
||||||
{
|
{
|
||||||
struct acpi_table_lapic_nmi *lacpi_nmi;
|
struct acpi_madt_local_apic_nmi *lacpi_nmi;
|
||||||
|
|
||||||
lacpi_nmi = (struct acpi_table_lapic_nmi *)header;
|
lacpi_nmi = (struct acpi_madt_local_apic_nmi *)header;
|
||||||
|
|
||||||
if (BAD_MADT_ENTRY(lacpi_nmi, end))
|
if (BAD_MADT_ENTRY(lacpi_nmi, end))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -225,11 +217,11 @@ acpi_parse_lapic_nmi(acpi_table_entry_header * header, const unsigned long end)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init
|
static int __init
|
||||||
acpi_parse_iosapic(acpi_table_entry_header * header, const unsigned long end)
|
acpi_parse_iosapic(struct acpi_subtable_header * header, const unsigned long end)
|
||||||
{
|
{
|
||||||
struct acpi_table_iosapic *iosapic;
|
struct acpi_madt_io_sapic *iosapic;
|
||||||
|
|
||||||
iosapic = (struct acpi_table_iosapic *)header;
|
iosapic = (struct acpi_madt_io_sapic *)header;
|
||||||
|
|
||||||
if (BAD_MADT_ENTRY(iosapic, end))
|
if (BAD_MADT_ENTRY(iosapic, end))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -240,13 +232,13 @@ acpi_parse_iosapic(acpi_table_entry_header * header, const unsigned long end)
|
||||||
static unsigned int __initdata acpi_madt_rev;
|
static unsigned int __initdata acpi_madt_rev;
|
||||||
|
|
||||||
static int __init
|
static int __init
|
||||||
acpi_parse_plat_int_src(acpi_table_entry_header * header,
|
acpi_parse_plat_int_src(struct acpi_subtable_header * header,
|
||||||
const unsigned long end)
|
const unsigned long end)
|
||||||
{
|
{
|
||||||
struct acpi_table_plat_int_src *plintsrc;
|
struct acpi_madt_interrupt_source *plintsrc;
|
||||||
int vector;
|
int vector;
|
||||||
|
|
||||||
plintsrc = (struct acpi_table_plat_int_src *)header;
|
plintsrc = (struct acpi_madt_interrupt_source *)header;
|
||||||
|
|
||||||
if (BAD_MADT_ENTRY(plintsrc, end))
|
if (BAD_MADT_ENTRY(plintsrc, end))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -257,19 +249,19 @@ acpi_parse_plat_int_src(acpi_table_entry_header * header,
|
||||||
*/
|
*/
|
||||||
vector = iosapic_register_platform_intr(plintsrc->type,
|
vector = iosapic_register_platform_intr(plintsrc->type,
|
||||||
plintsrc->global_irq,
|
plintsrc->global_irq,
|
||||||
plintsrc->iosapic_vector,
|
plintsrc->io_sapic_vector,
|
||||||
plintsrc->eid,
|
plintsrc->eid,
|
||||||
plintsrc->id,
|
plintsrc->id,
|
||||||
(plintsrc->flags.polarity ==
|
((plintsrc->inti_flags & ACPI_MADT_POLARITY_MASK) ==
|
||||||
1) ? IOSAPIC_POL_HIGH :
|
ACPI_MADT_POLARITY_ACTIVE_HIGH) ?
|
||||||
IOSAPIC_POL_LOW,
|
IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW,
|
||||||
(plintsrc->flags.trigger ==
|
((plintsrc->inti_flags & ACPI_MADT_TRIGGER_MASK) ==
|
||||||
1) ? IOSAPIC_EDGE :
|
ACPI_MADT_TRIGGER_EDGE) ?
|
||||||
IOSAPIC_LEVEL);
|
IOSAPIC_EDGE : IOSAPIC_LEVEL);
|
||||||
|
|
||||||
platform_intr_list[plintsrc->type] = vector;
|
platform_intr_list[plintsrc->type] = vector;
|
||||||
if (acpi_madt_rev > 1) {
|
if (acpi_madt_rev > 1) {
|
||||||
acpi_cpei_override = plintsrc->plint_flags.cpei_override_flag;
|
acpi_cpei_override = plintsrc->flags & ACPI_MADT_CPEI_OVERRIDE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -324,30 +316,32 @@ unsigned int get_cpei_target_cpu(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init
|
static int __init
|
||||||
acpi_parse_int_src_ovr(acpi_table_entry_header * header,
|
acpi_parse_int_src_ovr(struct acpi_subtable_header * header,
|
||||||
const unsigned long end)
|
const unsigned long end)
|
||||||
{
|
{
|
||||||
struct acpi_table_int_src_ovr *p;
|
struct acpi_madt_interrupt_override *p;
|
||||||
|
|
||||||
p = (struct acpi_table_int_src_ovr *)header;
|
p = (struct acpi_madt_interrupt_override *)header;
|
||||||
|
|
||||||
if (BAD_MADT_ENTRY(p, end))
|
if (BAD_MADT_ENTRY(p, end))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
iosapic_override_isa_irq(p->bus_irq, p->global_irq,
|
iosapic_override_isa_irq(p->source_irq, p->global_irq,
|
||||||
(p->flags.polarity ==
|
((p->inti_flags & ACPI_MADT_POLARITY_MASK) ==
|
||||||
1) ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW,
|
ACPI_MADT_POLARITY_ACTIVE_HIGH) ?
|
||||||
(p->flags.trigger ==
|
IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW,
|
||||||
1) ? IOSAPIC_EDGE : IOSAPIC_LEVEL);
|
((p->inti_flags & ACPI_MADT_TRIGGER_MASK) ==
|
||||||
|
ACPI_MADT_TRIGGER_EDGE) ?
|
||||||
|
IOSAPIC_EDGE : IOSAPIC_LEVEL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init
|
static int __init
|
||||||
acpi_parse_nmi_src(acpi_table_entry_header * header, const unsigned long end)
|
acpi_parse_nmi_src(struct acpi_subtable_header * header, const unsigned long end)
|
||||||
{
|
{
|
||||||
struct acpi_table_nmi_src *nmi_src;
|
struct acpi_madt_nmi_source *nmi_src;
|
||||||
|
|
||||||
nmi_src = (struct acpi_table_nmi_src *)header;
|
nmi_src = (struct acpi_madt_nmi_source *)header;
|
||||||
|
|
||||||
if (BAD_MADT_ENTRY(nmi_src, end))
|
if (BAD_MADT_ENTRY(nmi_src, end))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -371,12 +365,12 @@ static void __init acpi_madt_oem_check(char *oem_id, char *oem_table_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init acpi_parse_madt(unsigned long phys_addr, unsigned long size)
|
static int __init acpi_parse_madt(struct acpi_table_header *table)
|
||||||
{
|
{
|
||||||
if (!phys_addr || !size)
|
if (!table)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
acpi_madt = (struct acpi_table_madt *)__va(phys_addr);
|
acpi_madt = (struct acpi_table_madt *)table;
|
||||||
|
|
||||||
acpi_madt_rev = acpi_madt->header.revision;
|
acpi_madt_rev = acpi_madt->header.revision;
|
||||||
|
|
||||||
|
@ -384,14 +378,14 @@ static int __init acpi_parse_madt(unsigned long phys_addr, unsigned long size)
|
||||||
#ifdef CONFIG_ITANIUM
|
#ifdef CONFIG_ITANIUM
|
||||||
has_8259 = 1; /* Firmware on old Itanium systems is broken */
|
has_8259 = 1; /* Firmware on old Itanium systems is broken */
|
||||||
#else
|
#else
|
||||||
has_8259 = acpi_madt->flags.pcat_compat;
|
has_8259 = acpi_madt->flags & ACPI_MADT_PCAT_COMPAT;
|
||||||
#endif
|
#endif
|
||||||
iosapic_system_init(has_8259);
|
iosapic_system_init(has_8259);
|
||||||
|
|
||||||
/* Get base address of IPI Message Block */
|
/* Get base address of IPI Message Block */
|
||||||
|
|
||||||
if (acpi_madt->lapic_address)
|
if (acpi_madt->address)
|
||||||
ipi_base_addr = ioremap(acpi_madt->lapic_address, 0);
|
ipi_base_addr = ioremap(acpi_madt->address, 0);
|
||||||
|
|
||||||
printk(KERN_INFO PREFIX "Local APIC address %p\n", ipi_base_addr);
|
printk(KERN_INFO PREFIX "Local APIC address %p\n", ipi_base_addr);
|
||||||
|
|
||||||
|
@ -413,23 +407,24 @@ static u32 __devinitdata pxm_flag[PXM_FLAG_LEN];
|
||||||
#define pxm_bit_test(bit) (test_bit(bit,(void *)pxm_flag))
|
#define pxm_bit_test(bit) (test_bit(bit,(void *)pxm_flag))
|
||||||
static struct acpi_table_slit __initdata *slit_table;
|
static struct acpi_table_slit __initdata *slit_table;
|
||||||
|
|
||||||
static int get_processor_proximity_domain(struct acpi_table_processor_affinity *pa)
|
static int get_processor_proximity_domain(struct acpi_srat_cpu_affinity *pa)
|
||||||
{
|
{
|
||||||
int pxm;
|
int pxm;
|
||||||
|
|
||||||
pxm = pa->proximity_domain;
|
pxm = pa->proximity_domain_lo;
|
||||||
if (ia64_platform_is("sn2"))
|
if (ia64_platform_is("sn2"))
|
||||||
pxm += pa->reserved[0] << 8;
|
pxm += pa->proximity_domain_hi[0] << 8;
|
||||||
return pxm;
|
return pxm;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_memory_proximity_domain(struct acpi_table_memory_affinity *ma)
|
static int get_memory_proximity_domain(struct acpi_srat_mem_affinity *ma)
|
||||||
{
|
{
|
||||||
int pxm;
|
int pxm;
|
||||||
|
|
||||||
pxm = ma->proximity_domain;
|
pxm = ma->proximity_domain;
|
||||||
if (ia64_platform_is("sn2"))
|
if (!ia64_platform_is("sn2"))
|
||||||
pxm += ma->reserved1[0] << 8;
|
pxm &= 0xff;
|
||||||
|
|
||||||
return pxm;
|
return pxm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -442,7 +437,7 @@ void __init acpi_numa_slit_init(struct acpi_table_slit *slit)
|
||||||
u32 len;
|
u32 len;
|
||||||
|
|
||||||
len = sizeof(struct acpi_table_header) + 8
|
len = sizeof(struct acpi_table_header) + 8
|
||||||
+ slit->localities * slit->localities;
|
+ slit->locality_count * slit->locality_count;
|
||||||
if (slit->header.length != len) {
|
if (slit->header.length != len) {
|
||||||
printk(KERN_ERR
|
printk(KERN_ERR
|
||||||
"ACPI 2.0 SLIT: size mismatch: %d expected, %d actual\n",
|
"ACPI 2.0 SLIT: size mismatch: %d expected, %d actual\n",
|
||||||
|
@ -454,11 +449,11 @@ void __init acpi_numa_slit_init(struct acpi_table_slit *slit)
|
||||||
}
|
}
|
||||||
|
|
||||||
void __init
|
void __init
|
||||||
acpi_numa_processor_affinity_init(struct acpi_table_processor_affinity *pa)
|
acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa)
|
||||||
{
|
{
|
||||||
int pxm;
|
int pxm;
|
||||||
|
|
||||||
if (!pa->flags.enabled)
|
if (!(pa->flags & ACPI_SRAT_CPU_ENABLED))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
pxm = get_processor_proximity_domain(pa);
|
pxm = get_processor_proximity_domain(pa);
|
||||||
|
@ -467,14 +462,14 @@ acpi_numa_processor_affinity_init(struct acpi_table_processor_affinity *pa)
|
||||||
pxm_bit_set(pxm);
|
pxm_bit_set(pxm);
|
||||||
|
|
||||||
node_cpuid[srat_num_cpus].phys_id =
|
node_cpuid[srat_num_cpus].phys_id =
|
||||||
(pa->apic_id << 8) | (pa->lsapic_eid);
|
(pa->apic_id << 8) | (pa->local_sapic_eid);
|
||||||
/* nid should be overridden as logical node id later */
|
/* nid should be overridden as logical node id later */
|
||||||
node_cpuid[srat_num_cpus].nid = pxm;
|
node_cpuid[srat_num_cpus].nid = pxm;
|
||||||
srat_num_cpus++;
|
srat_num_cpus++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void __init
|
void __init
|
||||||
acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma)
|
acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
|
||||||
{
|
{
|
||||||
unsigned long paddr, size;
|
unsigned long paddr, size;
|
||||||
int pxm;
|
int pxm;
|
||||||
|
@ -483,13 +478,11 @@ acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma)
|
||||||
pxm = get_memory_proximity_domain(ma);
|
pxm = get_memory_proximity_domain(ma);
|
||||||
|
|
||||||
/* fill node memory chunk structure */
|
/* fill node memory chunk structure */
|
||||||
paddr = ma->base_addr_hi;
|
paddr = ma->base_address;
|
||||||
paddr = (paddr << 32) | ma->base_addr_lo;
|
size = ma->length;
|
||||||
size = ma->length_hi;
|
|
||||||
size = (size << 32) | ma->length_lo;
|
|
||||||
|
|
||||||
/* Ignore disabled entries */
|
/* Ignore disabled entries */
|
||||||
if (!ma->flags.enabled)
|
if (!(ma->flags & ACPI_SRAT_MEM_ENABLED))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* record this node in proximity bitmap */
|
/* record this node in proximity bitmap */
|
||||||
|
@ -560,16 +553,16 @@ void __init acpi_numa_arch_fixup(void)
|
||||||
if (!slit_table)
|
if (!slit_table)
|
||||||
return;
|
return;
|
||||||
memset(numa_slit, -1, sizeof(numa_slit));
|
memset(numa_slit, -1, sizeof(numa_slit));
|
||||||
for (i = 0; i < slit_table->localities; i++) {
|
for (i = 0; i < slit_table->locality_count; i++) {
|
||||||
if (!pxm_bit_test(i))
|
if (!pxm_bit_test(i))
|
||||||
continue;
|
continue;
|
||||||
node_from = pxm_to_node(i);
|
node_from = pxm_to_node(i);
|
||||||
for (j = 0; j < slit_table->localities; j++) {
|
for (j = 0; j < slit_table->locality_count; j++) {
|
||||||
if (!pxm_bit_test(j))
|
if (!pxm_bit_test(j))
|
||||||
continue;
|
continue;
|
||||||
node_to = pxm_to_node(j);
|
node_to = pxm_to_node(j);
|
||||||
node_distance(node_from, node_to) =
|
node_distance(node_from, node_to) =
|
||||||
slit_table->entry[i * slit_table->localities + j];
|
slit_table->entry[i * slit_table->locality_count + j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -609,26 +602,29 @@ EXPORT_SYMBOL(acpi_register_gsi);
|
||||||
|
|
||||||
void acpi_unregister_gsi(u32 gsi)
|
void acpi_unregister_gsi(u32 gsi)
|
||||||
{
|
{
|
||||||
|
if (acpi_irq_model == ACPI_IRQ_MODEL_PLATFORM)
|
||||||
|
return;
|
||||||
|
|
||||||
iosapic_unregister_intr(gsi);
|
iosapic_unregister_intr(gsi);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(acpi_unregister_gsi);
|
EXPORT_SYMBOL(acpi_unregister_gsi);
|
||||||
|
|
||||||
static int __init acpi_parse_fadt(unsigned long phys_addr, unsigned long size)
|
static int __init acpi_parse_fadt(struct acpi_table_header *table)
|
||||||
{
|
{
|
||||||
struct acpi_table_header *fadt_header;
|
struct acpi_table_header *fadt_header;
|
||||||
struct fadt_descriptor *fadt;
|
struct acpi_table_fadt *fadt;
|
||||||
|
|
||||||
if (!phys_addr || !size)
|
if (!table)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
fadt_header = (struct acpi_table_header *)__va(phys_addr);
|
fadt_header = (struct acpi_table_header *)table;
|
||||||
if (fadt_header->revision != 3)
|
if (fadt_header->revision != 3)
|
||||||
return -ENODEV; /* Only deal with ACPI 2.0 FADT */
|
return -ENODEV; /* Only deal with ACPI 2.0 FADT */
|
||||||
|
|
||||||
fadt = (struct fadt_descriptor *)fadt_header;
|
fadt = (struct acpi_table_fadt *)fadt_header;
|
||||||
|
|
||||||
acpi_register_gsi(fadt->sci_int, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW);
|
acpi_register_gsi(fadt->sci_interrupt, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -655,7 +651,7 @@ int __init acpi_boot_init(void)
|
||||||
* information -- the successor to MPS tables.
|
* information -- the successor to MPS tables.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (acpi_table_parse(ACPI_APIC, acpi_parse_madt) < 1) {
|
if (acpi_table_parse(ACPI_SIG_MADT, acpi_parse_madt) < 1) {
|
||||||
printk(KERN_ERR PREFIX "Can't find MADT\n");
|
printk(KERN_ERR PREFIX "Can't find MADT\n");
|
||||||
goto skip_madt;
|
goto skip_madt;
|
||||||
}
|
}
|
||||||
|
@ -663,40 +659,40 @@ int __init acpi_boot_init(void)
|
||||||
/* Local APIC */
|
/* Local APIC */
|
||||||
|
|
||||||
if (acpi_table_parse_madt
|
if (acpi_table_parse_madt
|
||||||
(ACPI_MADT_LAPIC_ADDR_OVR, acpi_parse_lapic_addr_ovr, 0) < 0)
|
(ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE, acpi_parse_lapic_addr_ovr, 0) < 0)
|
||||||
printk(KERN_ERR PREFIX
|
printk(KERN_ERR PREFIX
|
||||||
"Error parsing LAPIC address override entry\n");
|
"Error parsing LAPIC address override entry\n");
|
||||||
|
|
||||||
if (acpi_table_parse_madt(ACPI_MADT_LSAPIC, acpi_parse_lsapic, NR_CPUS)
|
if (acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_SAPIC, acpi_parse_lsapic, NR_CPUS)
|
||||||
< 1)
|
< 1)
|
||||||
printk(KERN_ERR PREFIX
|
printk(KERN_ERR PREFIX
|
||||||
"Error parsing MADT - no LAPIC entries\n");
|
"Error parsing MADT - no LAPIC entries\n");
|
||||||
|
|
||||||
if (acpi_table_parse_madt(ACPI_MADT_LAPIC_NMI, acpi_parse_lapic_nmi, 0)
|
if (acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_NMI, acpi_parse_lapic_nmi, 0)
|
||||||
< 0)
|
< 0)
|
||||||
printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n");
|
printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n");
|
||||||
|
|
||||||
/* I/O APIC */
|
/* I/O APIC */
|
||||||
|
|
||||||
if (acpi_table_parse_madt
|
if (acpi_table_parse_madt
|
||||||
(ACPI_MADT_IOSAPIC, acpi_parse_iosapic, NR_IOSAPICS) < 1)
|
(ACPI_MADT_TYPE_IO_SAPIC, acpi_parse_iosapic, NR_IOSAPICS) < 1)
|
||||||
printk(KERN_ERR PREFIX
|
printk(KERN_ERR PREFIX
|
||||||
"Error parsing MADT - no IOSAPIC entries\n");
|
"Error parsing MADT - no IOSAPIC entries\n");
|
||||||
|
|
||||||
/* System-Level Interrupt Routing */
|
/* System-Level Interrupt Routing */
|
||||||
|
|
||||||
if (acpi_table_parse_madt
|
if (acpi_table_parse_madt
|
||||||
(ACPI_MADT_PLAT_INT_SRC, acpi_parse_plat_int_src,
|
(ACPI_MADT_TYPE_INTERRUPT_SOURCE, acpi_parse_plat_int_src,
|
||||||
ACPI_MAX_PLATFORM_INTERRUPTS) < 0)
|
ACPI_MAX_PLATFORM_INTERRUPTS) < 0)
|
||||||
printk(KERN_ERR PREFIX
|
printk(KERN_ERR PREFIX
|
||||||
"Error parsing platform interrupt source entry\n");
|
"Error parsing platform interrupt source entry\n");
|
||||||
|
|
||||||
if (acpi_table_parse_madt
|
if (acpi_table_parse_madt
|
||||||
(ACPI_MADT_INT_SRC_OVR, acpi_parse_int_src_ovr, 0) < 0)
|
(ACPI_MADT_TYPE_INTERRUPT_OVERRIDE, acpi_parse_int_src_ovr, 0) < 0)
|
||||||
printk(KERN_ERR PREFIX
|
printk(KERN_ERR PREFIX
|
||||||
"Error parsing interrupt source overrides entry\n");
|
"Error parsing interrupt source overrides entry\n");
|
||||||
|
|
||||||
if (acpi_table_parse_madt(ACPI_MADT_NMI_SRC, acpi_parse_nmi_src, 0) < 0)
|
if (acpi_table_parse_madt(ACPI_MADT_TYPE_NMI_SOURCE, acpi_parse_nmi_src, 0) < 0)
|
||||||
printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n");
|
printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n");
|
||||||
skip_madt:
|
skip_madt:
|
||||||
|
|
||||||
|
@ -706,7 +702,7 @@ int __init acpi_boot_init(void)
|
||||||
* gets interrupts such as power and sleep buttons. If it's not
|
* gets interrupts such as power and sleep buttons. If it's not
|
||||||
* on a Legacy interrupt, it needs to be setup.
|
* on a Legacy interrupt, it needs to be setup.
|
||||||
*/
|
*/
|
||||||
if (acpi_table_parse(ACPI_FADT, acpi_parse_fadt) < 1)
|
if (acpi_table_parse(ACPI_SIG_FADT, acpi_parse_fadt) < 1)
|
||||||
printk(KERN_ERR PREFIX "Can't find FADT\n");
|
printk(KERN_ERR PREFIX "Can't find FADT\n");
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
|
@ -839,7 +835,7 @@ int acpi_map_lsapic(acpi_handle handle, int *pcpu)
|
||||||
{
|
{
|
||||||
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
|
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
|
||||||
union acpi_object *obj;
|
union acpi_object *obj;
|
||||||
struct acpi_table_lsapic *lsapic;
|
struct acpi_madt_local_sapic *lsapic;
|
||||||
cpumask_t tmp_map;
|
cpumask_t tmp_map;
|
||||||
long physid;
|
long physid;
|
||||||
int cpu;
|
int cpu;
|
||||||
|
@ -851,16 +847,16 @@ int acpi_map_lsapic(acpi_handle handle, int *pcpu)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
obj = buffer.pointer;
|
obj = buffer.pointer;
|
||||||
if (obj->type != ACPI_TYPE_BUFFER ||
|
if (obj->type != ACPI_TYPE_BUFFER)
|
||||||
obj->buffer.length < sizeof(*lsapic)) {
|
{
|
||||||
kfree(buffer.pointer);
|
kfree(buffer.pointer);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
lsapic = (struct acpi_table_lsapic *)obj->buffer.pointer;
|
lsapic = (struct acpi_madt_local_sapic *)obj->buffer.pointer;
|
||||||
|
|
||||||
if ((lsapic->header.type != ACPI_MADT_LSAPIC) ||
|
if ((lsapic->header.type != ACPI_MADT_TYPE_LOCAL_SAPIC) ||
|
||||||
(!lsapic->flags.enabled)) {
|
(!lsapic->lapic_flags & ACPI_MADT_ENABLED)) {
|
||||||
kfree(buffer.pointer);
|
kfree(buffer.pointer);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -880,7 +876,6 @@ int acpi_map_lsapic(acpi_handle handle, int *pcpu)
|
||||||
|
|
||||||
cpu_set(cpu, cpu_present_map);
|
cpu_set(cpu, cpu_present_map);
|
||||||
ia64_cpu_to_sapicid[cpu] = physid;
|
ia64_cpu_to_sapicid[cpu] = physid;
|
||||||
ia64_acpiid_to_sapicid[lsapic->acpi_id] = ia64_cpu_to_sapicid[cpu];
|
|
||||||
|
|
||||||
*pcpu = cpu;
|
*pcpu = cpu;
|
||||||
return (0);
|
return (0);
|
||||||
|
@ -890,14 +885,6 @@ EXPORT_SYMBOL(acpi_map_lsapic);
|
||||||
|
|
||||||
int acpi_unmap_lsapic(int cpu)
|
int acpi_unmap_lsapic(int cpu)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < MAX_SAPICS; i++) {
|
|
||||||
if (ia64_acpiid_to_sapicid[i] == ia64_cpu_to_sapicid[cpu]) {
|
|
||||||
ia64_acpiid_to_sapicid[i] = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ia64_cpu_to_sapicid[cpu] = -1;
|
ia64_cpu_to_sapicid[cpu] = -1;
|
||||||
cpu_clear(cpu, cpu_present_map);
|
cpu_clear(cpu, cpu_present_map);
|
||||||
|
|
||||||
|
@ -917,7 +904,7 @@ acpi_map_iosapic(acpi_handle handle, u32 depth, void *context, void **ret)
|
||||||
{
|
{
|
||||||
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
|
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
|
||||||
union acpi_object *obj;
|
union acpi_object *obj;
|
||||||
struct acpi_table_iosapic *iosapic;
|
struct acpi_madt_io_sapic *iosapic;
|
||||||
unsigned int gsi_base;
|
unsigned int gsi_base;
|
||||||
int pxm, node;
|
int pxm, node;
|
||||||
|
|
||||||
|
@ -935,9 +922,9 @@ acpi_map_iosapic(acpi_handle handle, u32 depth, void *context, void **ret)
|
||||||
return AE_OK;
|
return AE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
iosapic = (struct acpi_table_iosapic *)obj->buffer.pointer;
|
iosapic = (struct acpi_madt_io_sapic *)obj->buffer.pointer;
|
||||||
|
|
||||||
if (iosapic->header.type != ACPI_MADT_IOSAPIC) {
|
if (iosapic->header.type != ACPI_MADT_TYPE_IO_SAPIC) {
|
||||||
kfree(buffer.pointer);
|
kfree(buffer.pointer);
|
||||||
return AE_OK;
|
return AE_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ extern void ia64_dump_cpu_regs(void *);
|
||||||
static DEFINE_PER_CPU(struct elf_prstatus, elf_prstatus);
|
static DEFINE_PER_CPU(struct elf_prstatus, elf_prstatus);
|
||||||
|
|
||||||
void
|
void
|
||||||
crash_save_this_cpu()
|
crash_save_this_cpu(void)
|
||||||
{
|
{
|
||||||
void *buf;
|
void *buf;
|
||||||
unsigned long cfm, sof, sol;
|
unsigned long cfm, sof, sol;
|
||||||
|
@ -79,6 +79,7 @@ crash_save_this_cpu()
|
||||||
final_note(buf);
|
final_note(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
static int
|
static int
|
||||||
kdump_wait_cpu_freeze(void)
|
kdump_wait_cpu_freeze(void)
|
||||||
{
|
{
|
||||||
|
@ -91,6 +92,7 @@ kdump_wait_cpu_freeze(void)
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void
|
void
|
||||||
machine_crash_shutdown(struct pt_regs *pt)
|
machine_crash_shutdown(struct pt_regs *pt)
|
||||||
|
@ -116,6 +118,11 @@ machine_crash_shutdown(struct pt_regs *pt)
|
||||||
static void
|
static void
|
||||||
machine_kdump_on_init(void)
|
machine_kdump_on_init(void)
|
||||||
{
|
{
|
||||||
|
if (!ia64_kimage) {
|
||||||
|
printk(KERN_NOTICE "machine_kdump_on_init(): "
|
||||||
|
"kdump not configured\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
local_irq_disable();
|
local_irq_disable();
|
||||||
kexec_disable_iosapic();
|
kexec_disable_iosapic();
|
||||||
machine_kexec(ia64_kimage);
|
machine_kexec(ia64_kimage);
|
||||||
|
@ -132,11 +139,12 @@ kdump_cpu_freeze(struct unw_frame_info *info, void *arg)
|
||||||
atomic_inc(&kdump_cpu_freezed);
|
atomic_inc(&kdump_cpu_freezed);
|
||||||
kdump_status[cpuid] = 1;
|
kdump_status[cpuid] = 1;
|
||||||
mb();
|
mb();
|
||||||
if (cpuid == 0) {
|
#ifdef CONFIG_HOTPLUG_CPU
|
||||||
for (;;)
|
if (cpuid != 0)
|
||||||
cpu_relax();
|
|
||||||
} else
|
|
||||||
ia64_jump_to_sal(&sal_boot_rendez_state[cpuid]);
|
ia64_jump_to_sal(&sal_boot_rendez_state[cpuid]);
|
||||||
|
#endif
|
||||||
|
for (;;)
|
||||||
|
cpu_relax();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|
|
@ -9,7 +9,8 @@
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
|
||||||
#include <linux/uaccess.h>
|
#include <asm/page.h>
|
||||||
|
#include <asm/uaccess.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* copy_oldmem_page - copy one page from "oldmem"
|
* copy_oldmem_page - copy one page from "oldmem"
|
||||||
|
|
|
@ -380,7 +380,7 @@ efi_get_pal_addr (void)
|
||||||
#endif
|
#endif
|
||||||
return __va(md->phys_addr);
|
return __va(md->phys_addr);
|
||||||
}
|
}
|
||||||
printk(KERN_WARNING "%s: no PAL-code memory-descriptor found",
|
printk(KERN_WARNING "%s: no PAL-code memory-descriptor found\n",
|
||||||
__FUNCTION__);
|
__FUNCTION__);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1610,5 +1610,7 @@ sys_call_table:
|
||||||
data8 sys_sync_file_range // 1300
|
data8 sys_sync_file_range // 1300
|
||||||
data8 sys_tee
|
data8 sys_tee
|
||||||
data8 sys_vmsplice
|
data8 sys_vmsplice
|
||||||
|
data8 sys_ni_syscall // reserved for move_pages
|
||||||
|
data8 sys_getcpu
|
||||||
|
|
||||||
.org sys_call_table + 8*NR_syscalls // guard against failures to increase NR_syscalls
|
.org sys_call_table + 8*NR_syscalls // guard against failures to increase NR_syscalls
|
||||||
|
|
|
@ -925,6 +925,11 @@ iosapic_unregister_intr (unsigned int gsi)
|
||||||
/* Clear the interrupt controller descriptor */
|
/* Clear the interrupt controller descriptor */
|
||||||
idesc->chip = &no_irq_type;
|
idesc->chip = &no_irq_type;
|
||||||
|
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
/* Clear affinity */
|
||||||
|
cpus_setall(idesc->affinity);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Clear the interrupt information */
|
/* Clear the interrupt information */
|
||||||
memset(&iosapic_intr_info[vector], 0,
|
memset(&iosapic_intr_info[vector], 0,
|
||||||
sizeof(struct iosapic_intr_info));
|
sizeof(struct iosapic_intr_info));
|
||||||
|
|
|
@ -122,6 +122,9 @@ static void migrate_irqs(void)
|
||||||
for (irq=0; irq < NR_IRQS; irq++) {
|
for (irq=0; irq < NR_IRQS; irq++) {
|
||||||
desc = irq_desc + irq;
|
desc = irq_desc + irq;
|
||||||
|
|
||||||
|
if (desc->status == IRQ_DISABLED)
|
||||||
|
continue;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* No handling for now.
|
* No handling for now.
|
||||||
* TBD: Implement a disable function so we can now
|
* TBD: Implement a disable function so we can now
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include <linux/kexec.h>
|
#include <linux/kexec.h>
|
||||||
#include <linux/cpu.h>
|
#include <linux/cpu.h>
|
||||||
#include <linux/irq.h>
|
#include <linux/irq.h>
|
||||||
|
#include <linux/efi.h>
|
||||||
#include <asm/mmu_context.h>
|
#include <asm/mmu_context.h>
|
||||||
#include <asm/setup.h>
|
#include <asm/setup.h>
|
||||||
#include <asm/delay.h>
|
#include <asm/delay.h>
|
||||||
|
@ -68,22 +69,10 @@ void machine_kexec_cleanup(struct kimage *image)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void machine_shutdown(void)
|
|
||||||
{
|
|
||||||
int cpu;
|
|
||||||
|
|
||||||
for_each_online_cpu(cpu) {
|
|
||||||
if (cpu != smp_processor_id())
|
|
||||||
cpu_down(cpu);
|
|
||||||
}
|
|
||||||
kexec_disable_iosapic();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Do not allocate memory (or fail in any way) in machine_kexec().
|
* Do not allocate memory (or fail in any way) in machine_kexec().
|
||||||
* We are past the point of no return, committed to rebooting now.
|
* We are past the point of no return, committed to rebooting now.
|
||||||
*/
|
*/
|
||||||
extern void *efi_get_pal_addr(void);
|
|
||||||
static void ia64_machine_kexec(struct unw_frame_info *info, void *arg)
|
static void ia64_machine_kexec(struct unw_frame_info *info, void *arg)
|
||||||
{
|
{
|
||||||
struct kimage *image = arg;
|
struct kimage *image = arg;
|
||||||
|
@ -93,6 +82,7 @@ static void ia64_machine_kexec(struct unw_frame_info *info, void *arg)
|
||||||
unsigned long vector;
|
unsigned long vector;
|
||||||
int ii;
|
int ii;
|
||||||
|
|
||||||
|
BUG_ON(!image);
|
||||||
if (image->type == KEXEC_TYPE_CRASH) {
|
if (image->type == KEXEC_TYPE_CRASH) {
|
||||||
crash_save_this_cpu();
|
crash_save_this_cpu();
|
||||||
current->thread.ksp = (__u64)info->sw - 16;
|
current->thread.ksp = (__u64)info->sw - 16;
|
||||||
|
@ -131,6 +121,7 @@ static void ia64_machine_kexec(struct unw_frame_info *info, void *arg)
|
||||||
|
|
||||||
void machine_kexec(struct kimage *image)
|
void machine_kexec(struct kimage *image)
|
||||||
{
|
{
|
||||||
|
BUG_ON(!image);
|
||||||
unw_init_running(ia64_machine_kexec, image);
|
unw_init_running(ia64_machine_kexec, image);
|
||||||
for(;;);
|
for(;;);
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,12 +64,17 @@ static void ia64_set_msi_irq_affinity(unsigned int irq, cpumask_t cpu_mask)
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_SMP */
|
#endif /* CONFIG_SMP */
|
||||||
|
|
||||||
int ia64_setup_msi_irq(unsigned int irq, struct pci_dev *pdev)
|
int ia64_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
|
||||||
{
|
{
|
||||||
struct msi_msg msg;
|
struct msi_msg msg;
|
||||||
unsigned long dest_phys_id;
|
unsigned long dest_phys_id;
|
||||||
unsigned int vector;
|
unsigned int irq, vector;
|
||||||
|
|
||||||
|
irq = create_irq();
|
||||||
|
if (irq < 0)
|
||||||
|
return irq;
|
||||||
|
|
||||||
|
set_irq_msi(irq, desc);
|
||||||
dest_phys_id = cpu_physical_id(first_cpu(cpu_online_map));
|
dest_phys_id = cpu_physical_id(first_cpu(cpu_online_map));
|
||||||
vector = irq;
|
vector = irq;
|
||||||
|
|
||||||
|
@ -89,12 +94,12 @@ int ia64_setup_msi_irq(unsigned int irq, struct pci_dev *pdev)
|
||||||
write_msi_msg(irq, &msg);
|
write_msi_msg(irq, &msg);
|
||||||
set_irq_chip_and_handler(irq, &ia64_msi_chip, handle_edge_irq);
|
set_irq_chip_and_handler(irq, &ia64_msi_chip, handle_edge_irq);
|
||||||
|
|
||||||
return 0;
|
return irq;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ia64_teardown_msi_irq(unsigned int irq)
|
void ia64_teardown_msi_irq(unsigned int irq)
|
||||||
{
|
{
|
||||||
return; /* no-op */
|
destroy_irq(irq);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ia64_ack_msi_irq(unsigned int irq)
|
static void ia64_ack_msi_irq(unsigned int irq)
|
||||||
|
@ -126,12 +131,12 @@ static struct irq_chip ia64_msi_chip = {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
int arch_setup_msi_irq(unsigned int irq, struct pci_dev *pdev)
|
int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
|
||||||
{
|
{
|
||||||
if (platform_setup_msi_irq)
|
if (platform_setup_msi_irq)
|
||||||
return platform_setup_msi_irq(irq, pdev);
|
return platform_setup_msi_irq(pdev, desc);
|
||||||
|
|
||||||
return ia64_setup_msi_irq(irq, pdev);
|
return ia64_setup_msi_irq(pdev, desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void arch_teardown_msi_irq(unsigned int irq)
|
void arch_teardown_msi_irq(unsigned int irq)
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#include <asm/ia32.h>
|
#include <asm/ia32.h>
|
||||||
#include <asm/irq.h>
|
#include <asm/irq.h>
|
||||||
#include <asm/kdebug.h>
|
#include <asm/kdebug.h>
|
||||||
|
#include <asm/kexec.h>
|
||||||
#include <asm/pgalloc.h>
|
#include <asm/pgalloc.h>
|
||||||
#include <asm/processor.h>
|
#include <asm/processor.h>
|
||||||
#include <asm/sal.h>
|
#include <asm/sal.h>
|
||||||
|
@ -803,6 +804,21 @@ cpu_halt (void)
|
||||||
ia64_pal_halt(min_power_state);
|
ia64_pal_halt(min_power_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void machine_shutdown(void)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_HOTPLUG_CPU
|
||||||
|
int cpu;
|
||||||
|
|
||||||
|
for_each_online_cpu(cpu) {
|
||||||
|
if (cpu != smp_processor_id())
|
||||||
|
cpu_down(cpu);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_KEXEC
|
||||||
|
kexec_disable_iosapic();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
machine_restart (char *restart_cmd)
|
machine_restart (char *restart_cmd)
|
||||||
{
|
{
|
||||||
|
|
|
@ -607,7 +607,7 @@ find_thread_for_addr (struct task_struct *child, unsigned long addr)
|
||||||
*/
|
*/
|
||||||
list_for_each_safe(this, next, ¤t->children) {
|
list_for_each_safe(this, next, ¤t->children) {
|
||||||
p = list_entry(this, struct task_struct, sibling);
|
p = list_entry(this, struct task_struct, sibling);
|
||||||
if (p->mm != mm)
|
if (p->tgid != child->tgid)
|
||||||
continue;
|
continue;
|
||||||
if (thread_matches(p, addr)) {
|
if (thread_matches(p, addr)) {
|
||||||
child = p;
|
child = p;
|
||||||
|
@ -1405,6 +1405,7 @@ ptrace_disable (struct task_struct *child)
|
||||||
struct ia64_psr *child_psr = ia64_psr(task_pt_regs(child));
|
struct ia64_psr *child_psr = ia64_psr(task_pt_regs(child));
|
||||||
|
|
||||||
/* make sure the single step/taken-branch trap bits are not set: */
|
/* make sure the single step/taken-branch trap bits are not set: */
|
||||||
|
clear_tsk_thread_flag(child, TIF_SINGLESTEP);
|
||||||
child_psr->ss = 0;
|
child_psr->ss = 0;
|
||||||
child_psr->tb = 0;
|
child_psr->tb = 0;
|
||||||
}
|
}
|
||||||
|
@ -1525,6 +1526,7 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data)
|
||||||
* Make sure the single step/taken-branch trap bits
|
* Make sure the single step/taken-branch trap bits
|
||||||
* are not set:
|
* are not set:
|
||||||
*/
|
*/
|
||||||
|
clear_tsk_thread_flag(child, TIF_SINGLESTEP);
|
||||||
ia64_psr(pt)->ss = 0;
|
ia64_psr(pt)->ss = 0;
|
||||||
ia64_psr(pt)->tb = 0;
|
ia64_psr(pt)->tb = 0;
|
||||||
|
|
||||||
|
@ -1556,6 +1558,7 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data)
|
||||||
goto out_tsk;
|
goto out_tsk;
|
||||||
|
|
||||||
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
|
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
|
||||||
|
set_tsk_thread_flag(child, TIF_SINGLESTEP);
|
||||||
if (request == PTRACE_SINGLESTEP) {
|
if (request == PTRACE_SINGLESTEP) {
|
||||||
ia64_psr(pt)->ss = 1;
|
ia64_psr(pt)->ss = 1;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1595,13 +1598,9 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
static void
|
||||||
syscall_trace (void)
|
syscall_trace (void)
|
||||||
{
|
{
|
||||||
if (!test_thread_flag(TIF_SYSCALL_TRACE))
|
|
||||||
return;
|
|
||||||
if (!(current->ptrace & PT_PTRACED))
|
|
||||||
return;
|
|
||||||
/*
|
/*
|
||||||
* The 0x80 provides a way for the tracing parent to
|
* The 0x80 provides a way for the tracing parent to
|
||||||
* distinguish between a syscall stop and SIGTRAP delivery.
|
* distinguish between a syscall stop and SIGTRAP delivery.
|
||||||
|
@ -1664,7 +1663,8 @@ syscall_trace_leave (long arg0, long arg1, long arg2, long arg3,
|
||||||
audit_syscall_exit(success, result);
|
audit_syscall_exit(success, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (test_thread_flag(TIF_SYSCALL_TRACE)
|
if ((test_thread_flag(TIF_SYSCALL_TRACE)
|
||||||
|
|| test_thread_flag(TIF_SINGLESTEP))
|
||||||
&& (current->ptrace & PT_PTRACED))
|
&& (current->ptrace & PT_PTRACED))
|
||||||
syscall_trace();
|
syscall_trace();
|
||||||
}
|
}
|
||||||
|
|
|
@ -569,34 +569,31 @@ show_cpuinfo (struct seq_file *m, void *v)
|
||||||
{ 1UL << 1, "spontaneous deferral"},
|
{ 1UL << 1, "spontaneous deferral"},
|
||||||
{ 1UL << 2, "16-byte atomic ops" }
|
{ 1UL << 2, "16-byte atomic ops" }
|
||||||
};
|
};
|
||||||
char features[128], *cp, sep;
|
char features[128], *cp, *sep;
|
||||||
struct cpuinfo_ia64 *c = v;
|
struct cpuinfo_ia64 *c = v;
|
||||||
unsigned long mask;
|
unsigned long mask;
|
||||||
unsigned long proc_freq;
|
unsigned long proc_freq;
|
||||||
int i;
|
int i, size;
|
||||||
|
|
||||||
mask = c->features;
|
mask = c->features;
|
||||||
|
|
||||||
/* build the feature string: */
|
/* build the feature string: */
|
||||||
memcpy(features, " standard", 10);
|
memcpy(features, "standard", 9);
|
||||||
cp = features;
|
cp = features;
|
||||||
sep = 0;
|
size = sizeof(features);
|
||||||
for (i = 0; i < (int) ARRAY_SIZE(feature_bits); ++i) {
|
sep = "";
|
||||||
|
for (i = 0; i < ARRAY_SIZE(feature_bits) && size > 1; ++i) {
|
||||||
if (mask & feature_bits[i].mask) {
|
if (mask & feature_bits[i].mask) {
|
||||||
if (sep)
|
cp += snprintf(cp, size, "%s%s", sep,
|
||||||
*cp++ = sep;
|
feature_bits[i].feature_name),
|
||||||
sep = ',';
|
sep = ", ";
|
||||||
*cp++ = ' ';
|
|
||||||
strcpy(cp, feature_bits[i].feature_name);
|
|
||||||
cp += strlen(feature_bits[i].feature_name);
|
|
||||||
mask &= ~feature_bits[i].mask;
|
mask &= ~feature_bits[i].mask;
|
||||||
|
size = sizeof(features) - (cp - features);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mask) {
|
if (mask && size > 1) {
|
||||||
/* print unknown features as a hex value: */
|
/* print unknown features as a hex value */
|
||||||
if (sep)
|
snprintf(cp, size, "%s0x%lx", sep, mask);
|
||||||
*cp++ = sep;
|
|
||||||
sprintf(cp, " 0x%lx", mask);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
proc_freq = cpufreq_quick_get(cpunum);
|
proc_freq = cpufreq_quick_get(cpunum);
|
||||||
|
@ -612,7 +609,7 @@ show_cpuinfo (struct seq_file *m, void *v)
|
||||||
"model name : %s\n"
|
"model name : %s\n"
|
||||||
"revision : %u\n"
|
"revision : %u\n"
|
||||||
"archrev : %u\n"
|
"archrev : %u\n"
|
||||||
"features :%s\n" /* don't change this---it _is_ right! */
|
"features : %s\n"
|
||||||
"cpu number : %lu\n"
|
"cpu number : %lu\n"
|
||||||
"cpu regs : %u\n"
|
"cpu regs : %u\n"
|
||||||
"cpu MHz : %lu.%06lu\n"
|
"cpu MHz : %lu.%06lu\n"
|
||||||
|
|
|
@ -221,13 +221,13 @@ send_IPI_self (int op)
|
||||||
|
|
||||||
#ifdef CONFIG_KEXEC
|
#ifdef CONFIG_KEXEC
|
||||||
void
|
void
|
||||||
kdump_smp_send_stop()
|
kdump_smp_send_stop(void)
|
||||||
{
|
{
|
||||||
send_IPI_allbutself(IPI_KDUMP_CPU_STOP);
|
send_IPI_allbutself(IPI_KDUMP_CPU_STOP);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
kdump_smp_send_init()
|
kdump_smp_send_init(void)
|
||||||
{
|
{
|
||||||
unsigned int cpu, self_cpu;
|
unsigned int cpu, self_cpu;
|
||||||
self_cpu = smp_processor_id();
|
self_cpu = smp_processor_id();
|
||||||
|
|
|
@ -157,6 +157,7 @@ SECTIONS
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
. = ALIGN(8);
|
||||||
__con_initcall_start = .;
|
__con_initcall_start = .;
|
||||||
.con_initcall.init : AT(ADDR(.con_initcall.init) - LOAD_OFFSET)
|
.con_initcall.init : AT(ADDR(.con_initcall.init) - LOAD_OFFSET)
|
||||||
{ *(.con_initcall.init) }
|
{ *(.con_initcall.init) }
|
||||||
|
|
|
@ -30,47 +30,69 @@ static unsigned long max_gap;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* show_mem - display a memory statistics summary
|
* show_mem - give short summary of memory stats
|
||||||
*
|
*
|
||||||
* Just walks the pages in the system and describes where they're allocated.
|
* Shows a simple page count of reserved and used pages in the system.
|
||||||
|
* For discontig machines, it does this on a per-pgdat basis.
|
||||||
*/
|
*/
|
||||||
void
|
void show_mem(void)
|
||||||
show_mem (void)
|
|
||||||
{
|
{
|
||||||
int i, total = 0, reserved = 0;
|
int i, total_reserved = 0;
|
||||||
int shared = 0, cached = 0;
|
int total_shared = 0, total_cached = 0;
|
||||||
|
unsigned long total_present = 0;
|
||||||
|
pg_data_t *pgdat;
|
||||||
|
|
||||||
printk(KERN_INFO "Mem-info:\n");
|
printk(KERN_INFO "Mem-info:\n");
|
||||||
show_free_areas();
|
show_free_areas();
|
||||||
|
|
||||||
printk(KERN_INFO "Free swap: %6ldkB\n",
|
printk(KERN_INFO "Free swap: %6ldkB\n",
|
||||||
nr_swap_pages<<(PAGE_SHIFT-10));
|
nr_swap_pages<<(PAGE_SHIFT-10));
|
||||||
i = max_mapnr;
|
printk(KERN_INFO "Node memory in pages:\n");
|
||||||
for (i = 0; i < max_mapnr; i++) {
|
for_each_online_pgdat(pgdat) {
|
||||||
if (!pfn_valid(i)) {
|
unsigned long present;
|
||||||
|
unsigned long flags;
|
||||||
|
int shared = 0, cached = 0, reserved = 0;
|
||||||
|
|
||||||
|
pgdat_resize_lock(pgdat, &flags);
|
||||||
|
present = pgdat->node_present_pages;
|
||||||
|
for(i = 0; i < pgdat->node_spanned_pages; i++) {
|
||||||
|
struct page *page;
|
||||||
|
if (pfn_valid(pgdat->node_start_pfn + i))
|
||||||
|
page = pfn_to_page(pgdat->node_start_pfn + i);
|
||||||
|
else {
|
||||||
#ifdef CONFIG_VIRTUAL_MEM_MAP
|
#ifdef CONFIG_VIRTUAL_MEM_MAP
|
||||||
if (max_gap < LARGE_GAP)
|
if (max_gap < LARGE_GAP)
|
||||||
continue;
|
continue;
|
||||||
i = vmemmap_find_next_valid_pfn(0, i) - 1;
|
|
||||||
#endif
|
#endif
|
||||||
continue;
|
i = vmemmap_find_next_valid_pfn(pgdat->node_id,
|
||||||
|
i) - 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (PageReserved(page))
|
||||||
|
reserved++;
|
||||||
|
else if (PageSwapCache(page))
|
||||||
|
cached++;
|
||||||
|
else if (page_count(page))
|
||||||
|
shared += page_count(page)-1;
|
||||||
}
|
}
|
||||||
total++;
|
pgdat_resize_unlock(pgdat, &flags);
|
||||||
if (PageReserved(mem_map+i))
|
total_present += present;
|
||||||
reserved++;
|
total_reserved += reserved;
|
||||||
else if (PageSwapCache(mem_map+i))
|
total_cached += cached;
|
||||||
cached++;
|
total_shared += shared;
|
||||||
else if (page_count(mem_map + i))
|
printk(KERN_INFO "Node %4d: RAM: %11ld, rsvd: %8d, "
|
||||||
shared += page_count(mem_map + i) - 1;
|
"shrd: %10d, swpd: %10d\n", pgdat->node_id,
|
||||||
|
present, reserved, shared, cached);
|
||||||
}
|
}
|
||||||
printk(KERN_INFO "%d pages of RAM\n", total);
|
printk(KERN_INFO "%ld pages of RAM\n", total_present);
|
||||||
printk(KERN_INFO "%d reserved pages\n", reserved);
|
printk(KERN_INFO "%d reserved pages\n", total_reserved);
|
||||||
printk(KERN_INFO "%d pages shared\n", shared);
|
printk(KERN_INFO "%d pages shared\n", total_shared);
|
||||||
printk(KERN_INFO "%d pages swap cached\n", cached);
|
printk(KERN_INFO "%d pages swap cached\n", total_cached);
|
||||||
printk(KERN_INFO "%ld pages in page table cache\n",
|
printk(KERN_INFO "Total of %ld pages in page table cache\n",
|
||||||
pgtable_quicklist_total_size());
|
pgtable_quicklist_total_size());
|
||||||
|
printk(KERN_INFO "%d free buffer pages\n", nr_free_buffer_pages());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* physical address where the bootmem map is located */
|
/* physical address where the bootmem map is located */
|
||||||
unsigned long bootmap_start;
|
unsigned long bootmap_start;
|
||||||
|
|
||||||
|
@ -177,7 +199,7 @@ find_memory (void)
|
||||||
|
|
||||||
#ifdef CONFIG_CRASH_DUMP
|
#ifdef CONFIG_CRASH_DUMP
|
||||||
/* If we are doing a crash dump, we still need to know the real mem
|
/* If we are doing a crash dump, we still need to know the real mem
|
||||||
* size before original memory map is * reset. */
|
* size before original memory map is reset. */
|
||||||
saved_max_pfn = max_pfn;
|
saved_max_pfn = max_pfn;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -412,37 +412,6 @@ static void __init memory_less_nodes(void)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_SPARSEMEM
|
|
||||||
/**
|
|
||||||
* register_sparse_mem - notify SPARSEMEM that this memory range exists.
|
|
||||||
* @start: physical start of range
|
|
||||||
* @end: physical end of range
|
|
||||||
* @arg: unused
|
|
||||||
*
|
|
||||||
* Simply calls SPARSEMEM to register memory section(s).
|
|
||||||
*/
|
|
||||||
static int __init register_sparse_mem(unsigned long start, unsigned long end,
|
|
||||||
void *arg)
|
|
||||||
{
|
|
||||||
int nid;
|
|
||||||
|
|
||||||
start = __pa(start) >> PAGE_SHIFT;
|
|
||||||
end = __pa(end) >> PAGE_SHIFT;
|
|
||||||
nid = early_pfn_to_nid(start);
|
|
||||||
memory_present(nid, start, end);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __init arch_sparse_init(void)
|
|
||||||
{
|
|
||||||
efi_memmap_walk(register_sparse_mem, NULL);
|
|
||||||
sparse_init();
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#define arch_sparse_init() do {} while (0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* find_memory - walk the EFI memory map and setup the bootmem allocator
|
* find_memory - walk the EFI memory map and setup the bootmem allocator
|
||||||
*
|
*
|
||||||
|
@ -473,6 +442,9 @@ void __init find_memory(void)
|
||||||
node_clear(node, memory_less_mask);
|
node_clear(node, memory_less_mask);
|
||||||
mem_data[node].min_pfn = ~0UL;
|
mem_data[node].min_pfn = ~0UL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
efi_memmap_walk(register_active_ranges, NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize the boot memory maps in reverse order since that's
|
* Initialize the boot memory maps in reverse order since that's
|
||||||
* what the bootmem allocator expects
|
* what the bootmem allocator expects
|
||||||
|
@ -506,6 +478,12 @@ void __init find_memory(void)
|
||||||
max_pfn = max_low_pfn;
|
max_pfn = max_low_pfn;
|
||||||
|
|
||||||
find_initrd();
|
find_initrd();
|
||||||
|
|
||||||
|
#ifdef CONFIG_CRASH_DUMP
|
||||||
|
/* If we are doing a crash dump, we still need to know the real mem
|
||||||
|
* size before original memory map is reset. */
|
||||||
|
saved_max_pfn = max_pfn;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
|
@ -654,7 +632,6 @@ static __init int count_node_pages(unsigned long start, unsigned long len, int n
|
||||||
{
|
{
|
||||||
unsigned long end = start + len;
|
unsigned long end = start + len;
|
||||||
|
|
||||||
add_active_range(node, start >> PAGE_SHIFT, end >> PAGE_SHIFT);
|
|
||||||
mem_data[node].num_physpages += len >> PAGE_SHIFT;
|
mem_data[node].num_physpages += len >> PAGE_SHIFT;
|
||||||
if (start <= __pa(MAX_DMA_ADDRESS))
|
if (start <= __pa(MAX_DMA_ADDRESS))
|
||||||
mem_data[node].num_dma_physpages +=
|
mem_data[node].num_dma_physpages +=
|
||||||
|
@ -686,10 +663,11 @@ void __init paging_init(void)
|
||||||
|
|
||||||
max_dma = virt_to_phys((void *) MAX_DMA_ADDRESS) >> PAGE_SHIFT;
|
max_dma = virt_to_phys((void *) MAX_DMA_ADDRESS) >> PAGE_SHIFT;
|
||||||
|
|
||||||
arch_sparse_init();
|
|
||||||
|
|
||||||
efi_memmap_walk(filter_rsvd_memory, count_node_pages);
|
efi_memmap_walk(filter_rsvd_memory, count_node_pages);
|
||||||
|
|
||||||
|
sparse_memory_present_with_active_regions(MAX_NUMNODES);
|
||||||
|
sparse_init();
|
||||||
|
|
||||||
#ifdef CONFIG_VIRTUAL_MEM_MAP
|
#ifdef CONFIG_VIRTUAL_MEM_MAP
|
||||||
vmalloc_end -= PAGE_ALIGN(ALIGN(max_low_pfn, MAX_ORDER_NR_PAGES) *
|
vmalloc_end -= PAGE_ALIGN(ALIGN(max_low_pfn, MAX_ORDER_NR_PAGES) *
|
||||||
sizeof(struct page));
|
sizeof(struct page));
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include <linux/swap.h>
|
#include <linux/swap.h>
|
||||||
#include <linux/proc_fs.h>
|
#include <linux/proc_fs.h>
|
||||||
#include <linux/bitops.h>
|
#include <linux/bitops.h>
|
||||||
|
#include <linux/kexec.h>
|
||||||
|
|
||||||
#include <asm/a.out.h>
|
#include <asm/a.out.h>
|
||||||
#include <asm/dma.h>
|
#include <asm/dma.h>
|
||||||
|
@ -128,6 +129,25 @@ lazy_mmu_prot_update (pte_t pte)
|
||||||
set_bit(PG_arch_1, &page->flags); /* mark page as clean */
|
set_bit(PG_arch_1, &page->flags); /* mark page as clean */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Since DMA is i-cache coherent, any (complete) pages that were written via
|
||||||
|
* DMA can be marked as "clean" so that lazy_mmu_prot_update() doesn't have to
|
||||||
|
* flush them when they get mapped into an executable vm-area.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
dma_mark_clean(void *addr, size_t size)
|
||||||
|
{
|
||||||
|
unsigned long pg_addr, end;
|
||||||
|
|
||||||
|
pg_addr = PAGE_ALIGN((unsigned long) addr);
|
||||||
|
end = (unsigned long) addr + size;
|
||||||
|
while (pg_addr + PAGE_SIZE <= end) {
|
||||||
|
struct page *page = virt_to_page(pg_addr);
|
||||||
|
set_bit(PG_arch_1, &page->flags);
|
||||||
|
pg_addr += PAGE_SIZE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
ia64_set_rbs_bot (void)
|
ia64_set_rbs_bot (void)
|
||||||
{
|
{
|
||||||
|
@ -595,13 +615,27 @@ find_largest_hole (u64 start, u64 end, void *arg)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_VIRTUAL_MEM_MAP */
|
||||||
|
|
||||||
int __init
|
int __init
|
||||||
register_active_ranges(u64 start, u64 end, void *arg)
|
register_active_ranges(u64 start, u64 end, void *arg)
|
||||||
{
|
{
|
||||||
add_active_range(0, __pa(start) >> PAGE_SHIFT, __pa(end) >> PAGE_SHIFT);
|
int nid = paddr_to_nid(__pa(start));
|
||||||
|
|
||||||
|
if (nid < 0)
|
||||||
|
nid = 0;
|
||||||
|
#ifdef CONFIG_KEXEC
|
||||||
|
if (start > crashk_res.start && start < crashk_res.end)
|
||||||
|
start = crashk_res.end;
|
||||||
|
if (end > crashk_res.start && end < crashk_res.end)
|
||||||
|
end = crashk_res.start;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (start < end)
|
||||||
|
add_active_range(nid, __pa(start) >> PAGE_SHIFT,
|
||||||
|
__pa(end) >> PAGE_SHIFT);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_VIRTUAL_MEM_MAP */
|
|
||||||
|
|
||||||
static int __init
|
static int __init
|
||||||
count_reserved_pages (u64 start, u64 end, void *arg)
|
count_reserved_pages (u64 start, u64 end, void *arg)
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* License. See the file "COPYING" in the main directory of this archive
|
* License. See the file "COPYING" in the main directory of this archive
|
||||||
* for more details.
|
* for more details.
|
||||||
*
|
*
|
||||||
* Copyright (C) 1992 - 1997, 2000,2002-2005 Silicon Graphics, Inc. All rights reserved.
|
* Copyright (C) 1992 - 1997, 2000,2002-2007 Silicon Graphics, Inc. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
@ -38,12 +38,20 @@ static irqreturn_t hub_eint_handler(int irq, void *arg)
|
||||||
(u64) nasid, 0, 0, 0, 0, 0, 0);
|
(u64) nasid, 0, 0, 0, 0, 0, 0);
|
||||||
|
|
||||||
if ((int)ret_stuff.v0)
|
if ((int)ret_stuff.v0)
|
||||||
panic("hubii_eint_handler(): Fatal TIO Error");
|
panic("%s: Fatal %s Error", __FUNCTION__,
|
||||||
|
((nasid & 1) ? "TIO" : "HUBII"));
|
||||||
|
|
||||||
if (!(nasid & 1)) /* Not a TIO, handle CRB errors */
|
if (!(nasid & 1)) /* Not a TIO, handle CRB errors */
|
||||||
(void)hubiio_crb_error_handler(hubdev_info);
|
(void)hubiio_crb_error_handler(hubdev_info);
|
||||||
} else
|
} else
|
||||||
bte_error_handler((unsigned long)NODEPDA(nasid_to_cnodeid(nasid)));
|
if (nasid & 1) { /* TIO errors */
|
||||||
|
SAL_CALL_NOLOCK(ret_stuff, SN_SAL_HUB_ERROR_INTERRUPT,
|
||||||
|
(u64) nasid, 0, 0, 0, 0, 0, 0);
|
||||||
|
|
||||||
|
if ((int)ret_stuff.v0)
|
||||||
|
panic("%s: Fatal TIO Error", __FUNCTION__);
|
||||||
|
} else
|
||||||
|
bte_error_handler((unsigned long)NODEPDA(nasid_to_cnodeid(nasid)));
|
||||||
|
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <asm/sn/sn_sal.h>
|
#include <asm/sn/sn_sal.h>
|
||||||
#include "xtalk/hubdev.h"
|
#include "xtalk/hubdev.h"
|
||||||
#include <linux/acpi.h>
|
#include <linux/acpi.h>
|
||||||
|
#include <acpi/acnamesp.h>
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -31,6 +32,12 @@ struct acpi_vendor_uuid sn_uuid = {
|
||||||
0xa2, 0x7c, 0x08, 0x00, 0x69, 0x13, 0xea, 0x51 },
|
0xa2, 0x7c, 0x08, 0x00, 0x69, 0x13, 0xea, 0x51 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct sn_pcidev_match {
|
||||||
|
u8 bus;
|
||||||
|
unsigned int devfn;
|
||||||
|
acpi_handle handle;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Perform the early IO init in PROM.
|
* Perform the early IO init in PROM.
|
||||||
*/
|
*/
|
||||||
|
@ -119,9 +126,11 @@ sn_get_bussoft_ptr(struct pci_bus *bus)
|
||||||
status = acpi_get_vendor_resource(handle, METHOD_NAME__CRS,
|
status = acpi_get_vendor_resource(handle, METHOD_NAME__CRS,
|
||||||
&sn_uuid, &buffer);
|
&sn_uuid, &buffer);
|
||||||
if (ACPI_FAILURE(status)) {
|
if (ACPI_FAILURE(status)) {
|
||||||
printk(KERN_ERR "get_acpi_pcibus_ptr: "
|
printk(KERN_ERR "%s: "
|
||||||
"get_acpi_bussoft_info() failed: %d\n",
|
"acpi_get_vendor_resource() failed (0x%x) for: ",
|
||||||
status);
|
__FUNCTION__, status);
|
||||||
|
acpi_ns_print_node_pathname(handle, NULL);
|
||||||
|
printk("\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
resource = buffer.pointer;
|
resource = buffer.pointer;
|
||||||
|
@ -130,8 +139,8 @@ sn_get_bussoft_ptr(struct pci_bus *bus)
|
||||||
if ((vendor->byte_length - sizeof(struct acpi_vendor_uuid)) !=
|
if ((vendor->byte_length - sizeof(struct acpi_vendor_uuid)) !=
|
||||||
sizeof(struct pcibus_bussoft *)) {
|
sizeof(struct pcibus_bussoft *)) {
|
||||||
printk(KERN_ERR
|
printk(KERN_ERR
|
||||||
"get_acpi_bussoft_ptr: Invalid vendor data "
|
"%s: Invalid vendor data length %d\n",
|
||||||
"length %d\n", vendor->byte_length);
|
__FUNCTION__, vendor->byte_length);
|
||||||
kfree(buffer.pointer);
|
kfree(buffer.pointer);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -143,34 +152,254 @@ sn_get_bussoft_ptr(struct pci_bus *bus)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* sn_acpi_bus_fixup
|
* sn_extract_device_info - Extract the pcidev_info and the sn_irq_info
|
||||||
|
* pointers from the vendor resource using the
|
||||||
|
* provided acpi handle, and copy the structures
|
||||||
|
* into the argument buffers.
|
||||||
*/
|
*/
|
||||||
void
|
static int
|
||||||
sn_acpi_bus_fixup(struct pci_bus *bus)
|
sn_extract_device_info(acpi_handle handle, struct pcidev_info **pcidev_info,
|
||||||
|
struct sn_irq_info **sn_irq_info)
|
||||||
{
|
{
|
||||||
struct pci_dev *pci_dev = NULL;
|
u64 addr;
|
||||||
struct pcibus_bussoft *prom_bussoft_ptr;
|
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
|
||||||
extern void sn_common_bus_fixup(struct pci_bus *,
|
struct sn_irq_info *irq_info, *irq_info_prom;
|
||||||
struct pcibus_bussoft *);
|
struct pcidev_info *pcidev_ptr, *pcidev_prom_ptr;
|
||||||
|
struct acpi_resource *resource;
|
||||||
|
int ret = 0;
|
||||||
|
acpi_status status;
|
||||||
|
struct acpi_resource_vendor_typed *vendor;
|
||||||
|
|
||||||
if (!bus->parent) { /* If root bus */
|
/*
|
||||||
prom_bussoft_ptr = sn_get_bussoft_ptr(bus);
|
* The pointer to this device's pcidev_info structure in
|
||||||
if (prom_bussoft_ptr == NULL) {
|
* the PROM, is in the vendor resource.
|
||||||
printk(KERN_ERR
|
*/
|
||||||
"sn_pci_fixup_bus: 0x%04x:0x%02x Unable to "
|
status = acpi_get_vendor_resource(handle, METHOD_NAME__CRS,
|
||||||
"obtain prom_bussoft_ptr\n",
|
&sn_uuid, &buffer);
|
||||||
pci_domain_nr(bus), bus->number);
|
if (ACPI_FAILURE(status)) {
|
||||||
return;
|
printk(KERN_ERR
|
||||||
|
"%s: acpi_get_vendor_resource() failed (0x%x) for: ",
|
||||||
|
__FUNCTION__, status);
|
||||||
|
acpi_ns_print_node_pathname(handle, NULL);
|
||||||
|
printk("\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
resource = buffer.pointer;
|
||||||
|
vendor = &resource->data.vendor_typed;
|
||||||
|
if ((vendor->byte_length - sizeof(struct acpi_vendor_uuid)) !=
|
||||||
|
sizeof(struct pci_devdev_info *)) {
|
||||||
|
printk(KERN_ERR
|
||||||
|
"%s: Invalid vendor data length: %d for: ",
|
||||||
|
__FUNCTION__, vendor->byte_length);
|
||||||
|
acpi_ns_print_node_pathname(handle, NULL);
|
||||||
|
printk("\n");
|
||||||
|
ret = 1;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
pcidev_ptr = kzalloc(sizeof(struct pcidev_info), GFP_KERNEL);
|
||||||
|
if (!pcidev_ptr)
|
||||||
|
panic("%s: Unable to alloc memory for pcidev_info", __FUNCTION__);
|
||||||
|
|
||||||
|
memcpy(&addr, vendor->byte_data, sizeof(struct pcidev_info *));
|
||||||
|
pcidev_prom_ptr = __va(addr);
|
||||||
|
memcpy(pcidev_ptr, pcidev_prom_ptr, sizeof(struct pcidev_info));
|
||||||
|
|
||||||
|
/* Get the IRQ info */
|
||||||
|
irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL);
|
||||||
|
if (!irq_info)
|
||||||
|
panic("%s: Unable to alloc memory for sn_irq_info", __FUNCTION__);
|
||||||
|
|
||||||
|
if (pcidev_ptr->pdi_sn_irq_info) {
|
||||||
|
irq_info_prom = __va(pcidev_ptr->pdi_sn_irq_info);
|
||||||
|
memcpy(irq_info, irq_info_prom, sizeof(struct sn_irq_info));
|
||||||
|
}
|
||||||
|
|
||||||
|
*pcidev_info = pcidev_ptr;
|
||||||
|
*sn_irq_info = irq_info;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
kfree(buffer.pointer);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int
|
||||||
|
get_host_devfn(acpi_handle device_handle, acpi_handle rootbus_handle)
|
||||||
|
{
|
||||||
|
unsigned long adr;
|
||||||
|
acpi_handle child;
|
||||||
|
unsigned int devfn;
|
||||||
|
int function;
|
||||||
|
acpi_handle parent;
|
||||||
|
int slot;
|
||||||
|
acpi_status status;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do an upward search to find the root bus device, and
|
||||||
|
* obtain the host devfn from the previous child device.
|
||||||
|
*/
|
||||||
|
child = device_handle;
|
||||||
|
while (child) {
|
||||||
|
status = acpi_get_parent(child, &parent);
|
||||||
|
if (ACPI_FAILURE(status)) {
|
||||||
|
printk(KERN_ERR "%s: acpi_get_parent() failed "
|
||||||
|
"(0x%x) for: ", __FUNCTION__, status);
|
||||||
|
acpi_ns_print_node_pathname(child, NULL);
|
||||||
|
printk("\n");
|
||||||
|
panic("%s: Unable to find host devfn\n", __FUNCTION__);
|
||||||
}
|
}
|
||||||
sn_common_bus_fixup(bus, prom_bussoft_ptr);
|
if (parent == rootbus_handle)
|
||||||
|
break;
|
||||||
|
child = parent;
|
||||||
}
|
}
|
||||||
list_for_each_entry(pci_dev, &bus->devices, bus_list) {
|
if (!child) {
|
||||||
sn_pci_fixup_slot(pci_dev);
|
printk(KERN_ERR "%s: Unable to find root bus for: ",
|
||||||
|
__FUNCTION__);
|
||||||
|
acpi_ns_print_node_pathname(device_handle, NULL);
|
||||||
|
printk("\n");
|
||||||
|
BUG();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
status = acpi_evaluate_integer(child, METHOD_NAME__ADR, NULL, &adr);
|
||||||
|
if (ACPI_FAILURE(status)) {
|
||||||
|
printk(KERN_ERR "%s: Unable to get _ADR (0x%x) for: ",
|
||||||
|
__FUNCTION__, status);
|
||||||
|
acpi_ns_print_node_pathname(child, NULL);
|
||||||
|
printk("\n");
|
||||||
|
panic("%s: Unable to find host devfn\n", __FUNCTION__);
|
||||||
|
}
|
||||||
|
|
||||||
|
slot = (adr >> 16) & 0xffff;
|
||||||
|
function = adr & 0xffff;
|
||||||
|
devfn = PCI_DEVFN(slot, function);
|
||||||
|
return devfn;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* sn_acpi_slot_fixup - Perform any SN specific slot fixup.
|
* find_matching_device - Callback routine to find the ACPI device
|
||||||
|
* that matches up with our pci_dev device.
|
||||||
|
* Matching is done on bus number and devfn.
|
||||||
|
* To find the bus number for a particular
|
||||||
|
* ACPI device, we must look at the _BBN method
|
||||||
|
* of its parent.
|
||||||
|
*/
|
||||||
|
static acpi_status
|
||||||
|
find_matching_device(acpi_handle handle, u32 lvl, void *context, void **rv)
|
||||||
|
{
|
||||||
|
unsigned long bbn = -1;
|
||||||
|
unsigned long adr;
|
||||||
|
acpi_handle parent = NULL;
|
||||||
|
acpi_status status;
|
||||||
|
unsigned int devfn;
|
||||||
|
int function;
|
||||||
|
int slot;
|
||||||
|
struct sn_pcidev_match *info = context;
|
||||||
|
|
||||||
|
status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL,
|
||||||
|
&adr);
|
||||||
|
if (ACPI_SUCCESS(status)) {
|
||||||
|
status = acpi_get_parent(handle, &parent);
|
||||||
|
if (ACPI_FAILURE(status)) {
|
||||||
|
printk(KERN_ERR
|
||||||
|
"%s: acpi_get_parent() failed (0x%x) for: ",
|
||||||
|
__FUNCTION__, status);
|
||||||
|
acpi_ns_print_node_pathname(handle, NULL);
|
||||||
|
printk("\n");
|
||||||
|
return AE_OK;
|
||||||
|
}
|
||||||
|
status = acpi_evaluate_integer(parent, METHOD_NAME__BBN,
|
||||||
|
NULL, &bbn);
|
||||||
|
if (ACPI_FAILURE(status)) {
|
||||||
|
printk(KERN_ERR
|
||||||
|
"%s: Failed to find _BBN in parent of: ",
|
||||||
|
__FUNCTION__);
|
||||||
|
acpi_ns_print_node_pathname(handle, NULL);
|
||||||
|
printk("\n");
|
||||||
|
return AE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
slot = (adr >> 16) & 0xffff;
|
||||||
|
function = adr & 0xffff;
|
||||||
|
devfn = PCI_DEVFN(slot, function);
|
||||||
|
if ((info->devfn == devfn) && (info->bus == bbn)) {
|
||||||
|
/* We have a match! */
|
||||||
|
info->handle = handle;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return AE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* sn_acpi_get_pcidev_info - Search ACPI namespace for the acpi
|
||||||
|
* device matching the specified pci_dev,
|
||||||
|
* and return the pcidev info and irq info.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
sn_acpi_get_pcidev_info(struct pci_dev *dev, struct pcidev_info **pcidev_info,
|
||||||
|
struct sn_irq_info **sn_irq_info)
|
||||||
|
{
|
||||||
|
unsigned int host_devfn;
|
||||||
|
struct sn_pcidev_match pcidev_match;
|
||||||
|
acpi_handle rootbus_handle;
|
||||||
|
unsigned long segment;
|
||||||
|
acpi_status status;
|
||||||
|
|
||||||
|
rootbus_handle = PCI_CONTROLLER(dev)->acpi_handle;
|
||||||
|
status = acpi_evaluate_integer(rootbus_handle, METHOD_NAME__SEG, NULL,
|
||||||
|
&segment);
|
||||||
|
if (ACPI_SUCCESS(status)) {
|
||||||
|
if (segment != pci_domain_nr(dev)) {
|
||||||
|
printk(KERN_ERR
|
||||||
|
"%s: Segment number mismatch, 0x%lx vs 0x%x for: ",
|
||||||
|
__FUNCTION__, segment, pci_domain_nr(dev));
|
||||||
|
acpi_ns_print_node_pathname(rootbus_handle, NULL);
|
||||||
|
printk("\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printk(KERN_ERR "%s: Unable to get __SEG from: ",
|
||||||
|
__FUNCTION__);
|
||||||
|
acpi_ns_print_node_pathname(rootbus_handle, NULL);
|
||||||
|
printk("\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We want to search all devices in this segment/domain
|
||||||
|
* of the ACPI namespace for the matching ACPI device,
|
||||||
|
* which holds the pcidev_info pointer in its vendor resource.
|
||||||
|
*/
|
||||||
|
pcidev_match.bus = dev->bus->number;
|
||||||
|
pcidev_match.devfn = dev->devfn;
|
||||||
|
pcidev_match.handle = NULL;
|
||||||
|
|
||||||
|
acpi_walk_namespace(ACPI_TYPE_DEVICE, rootbus_handle, ACPI_UINT32_MAX,
|
||||||
|
find_matching_device, &pcidev_match, NULL);
|
||||||
|
|
||||||
|
if (!pcidev_match.handle) {
|
||||||
|
printk(KERN_ERR
|
||||||
|
"%s: Could not find matching ACPI device for %s.\n",
|
||||||
|
__FUNCTION__, pci_name(dev));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sn_extract_device_info(pcidev_match.handle, pcidev_info, sn_irq_info))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* Build up the pcidev_info.pdi_slot_host_handle */
|
||||||
|
host_devfn = get_host_devfn(pcidev_match.handle, rootbus_handle);
|
||||||
|
(*pcidev_info)->pdi_slot_host_handle =
|
||||||
|
((unsigned long) pci_domain_nr(dev) << 40) |
|
||||||
|
/* bus == 0 */
|
||||||
|
host_devfn;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* sn_acpi_slot_fixup - Obtain the pcidev_info and sn_irq_info.
|
||||||
|
* Perform any SN specific slot fixup.
|
||||||
* At present there does not appear to be
|
* At present there does not appear to be
|
||||||
* any generic way to handle a ROM image
|
* any generic way to handle a ROM image
|
||||||
* that has been shadowed by the PROM, so
|
* that has been shadowed by the PROM, so
|
||||||
|
@ -179,11 +408,18 @@ sn_acpi_bus_fixup(struct pci_bus *bus)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
sn_acpi_slot_fixup(struct pci_dev *dev, struct pcidev_info *pcidev_info)
|
sn_acpi_slot_fixup(struct pci_dev *dev)
|
||||||
{
|
{
|
||||||
void __iomem *addr;
|
void __iomem *addr;
|
||||||
|
struct pcidev_info *pcidev_info = NULL;
|
||||||
|
struct sn_irq_info *sn_irq_info = NULL;
|
||||||
size_t size;
|
size_t size;
|
||||||
|
|
||||||
|
if (sn_acpi_get_pcidev_info(dev, &pcidev_info, &sn_irq_info)) {
|
||||||
|
panic("%s: Failure obtaining pcidev_info for %s\n",
|
||||||
|
__FUNCTION__, pci_name(dev));
|
||||||
|
}
|
||||||
|
|
||||||
if (pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE]) {
|
if (pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE]) {
|
||||||
/*
|
/*
|
||||||
* A valid ROM image exists and has been shadowed by the
|
* A valid ROM image exists and has been shadowed by the
|
||||||
|
@ -200,8 +436,11 @@ sn_acpi_slot_fixup(struct pci_dev *dev, struct pcidev_info *pcidev_info)
|
||||||
(unsigned long) addr + size;
|
(unsigned long) addr + size;
|
||||||
dev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_BIOS_COPY;
|
dev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_BIOS_COPY;
|
||||||
}
|
}
|
||||||
|
sn_pci_fixup_slot(dev, pcidev_info, sn_irq_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EXPORT_SYMBOL(sn_acpi_slot_fixup);
|
||||||
|
|
||||||
static struct acpi_driver acpi_sn_hubdev_driver = {
|
static struct acpi_driver acpi_sn_hubdev_driver = {
|
||||||
.name = "SGI HUBDEV Driver",
|
.name = "SGI HUBDEV Driver",
|
||||||
.ids = "SGIHUB,SGITIO",
|
.ids = "SGIHUB,SGITIO",
|
||||||
|
@ -211,6 +450,33 @@ static struct acpi_driver acpi_sn_hubdev_driver = {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* sn_acpi_bus_fixup - Perform SN specific setup of software structs
|
||||||
|
* (pcibus_bussoft, pcidev_info) and hardware
|
||||||
|
* registers, for the specified bus and devices under it.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
sn_acpi_bus_fixup(struct pci_bus *bus)
|
||||||
|
{
|
||||||
|
struct pci_dev *pci_dev = NULL;
|
||||||
|
struct pcibus_bussoft *prom_bussoft_ptr;
|
||||||
|
|
||||||
|
if (!bus->parent) { /* If root bus */
|
||||||
|
prom_bussoft_ptr = sn_get_bussoft_ptr(bus);
|
||||||
|
if (prom_bussoft_ptr == NULL) {
|
||||||
|
printk(KERN_ERR
|
||||||
|
"%s: 0x%04x:0x%02x Unable to "
|
||||||
|
"obtain prom_bussoft_ptr\n",
|
||||||
|
__FUNCTION__, pci_domain_nr(bus), bus->number);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sn_common_bus_fixup(bus, prom_bussoft_ptr);
|
||||||
|
}
|
||||||
|
list_for_each_entry(pci_dev, &bus->devices, bus_list) {
|
||||||
|
sn_acpi_slot_fixup(pci_dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* sn_io_acpi_init - PROM has ACPI support for IO, defining at a minimum the
|
* sn_io_acpi_init - PROM has ACPI support for IO, defining at a minimum the
|
||||||
* nodes and root buses in the DSDT. As a result, bus scanning
|
* nodes and root buses in the DSDT. As a result, bus scanning
|
||||||
|
|
|
@ -26,14 +26,10 @@
|
||||||
#include <linux/acpi.h>
|
#include <linux/acpi.h>
|
||||||
#include <asm/sn/sn2/sn_hwperf.h>
|
#include <asm/sn/sn2/sn_hwperf.h>
|
||||||
#include <asm/sn/acpi.h>
|
#include <asm/sn/acpi.h>
|
||||||
|
#include "acpi/acglobal.h"
|
||||||
|
|
||||||
extern void sn_init_cpei_timer(void);
|
extern void sn_init_cpei_timer(void);
|
||||||
extern void register_sn_procfs(void);
|
extern void register_sn_procfs(void);
|
||||||
extern void sn_acpi_bus_fixup(struct pci_bus *);
|
|
||||||
extern void sn_bus_fixup(struct pci_bus *);
|
|
||||||
extern void sn_acpi_slot_fixup(struct pci_dev *, struct pcidev_info *);
|
|
||||||
extern void sn_more_slot_fixup(struct pci_dev *, struct pcidev_info *);
|
|
||||||
extern void sn_legacy_pci_window_fixup(struct pci_controller *, u64, u64);
|
|
||||||
extern void sn_io_acpi_init(void);
|
extern void sn_io_acpi_init(void);
|
||||||
extern void sn_io_init(void);
|
extern void sn_io_init(void);
|
||||||
|
|
||||||
|
@ -48,6 +44,9 @@ struct sysdata_el {
|
||||||
|
|
||||||
int sn_ioif_inited; /* SN I/O infrastructure initialized? */
|
int sn_ioif_inited; /* SN I/O infrastructure initialized? */
|
||||||
|
|
||||||
|
int sn_acpi_rev; /* SN ACPI revision */
|
||||||
|
EXPORT_SYMBOL_GPL(sn_acpi_rev);
|
||||||
|
|
||||||
struct sn_pcibus_provider *sn_pci_provider[PCIIO_ASIC_MAX_TYPES]; /* indexed by asic type */
|
struct sn_pcibus_provider *sn_pci_provider[PCIIO_ASIC_MAX_TYPES]; /* indexed by asic type */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -98,25 +97,6 @@ sal_get_device_dmaflush_list(u64 nasid, u64 widget_num, u64 device_num,
|
||||||
return ret_stuff.status;
|
return ret_stuff.status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Retrieve the pci device information given the bus and device|function number.
|
|
||||||
*/
|
|
||||||
static inline u64
|
|
||||||
sal_get_pcidev_info(u64 segment, u64 bus_number, u64 devfn, u64 pci_dev,
|
|
||||||
u64 sn_irq_info)
|
|
||||||
{
|
|
||||||
struct ia64_sal_retval ret_stuff;
|
|
||||||
ret_stuff.status = 0;
|
|
||||||
ret_stuff.v0 = 0;
|
|
||||||
|
|
||||||
SAL_CALL_NOLOCK(ret_stuff,
|
|
||||||
(u64) SN_SAL_IOIF_GET_PCIDEV_INFO,
|
|
||||||
(u64) segment, (u64) bus_number, (u64) devfn,
|
|
||||||
(u64) pci_dev,
|
|
||||||
sn_irq_info, 0, 0);
|
|
||||||
return ret_stuff.v0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* sn_pcidev_info_get() - Retrieve the pcidev_info struct for the specified
|
* sn_pcidev_info_get() - Retrieve the pcidev_info struct for the specified
|
||||||
* device.
|
* device.
|
||||||
|
@ -249,50 +229,25 @@ void sn_pci_unfixup_slot(struct pci_dev *dev)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* sn_pci_fixup_slot() - This routine sets up a slot's resources consistent
|
* sn_pci_fixup_slot()
|
||||||
* with the Linux PCI abstraction layer. Resources
|
|
||||||
* acquired from our PCI provider include PIO maps
|
|
||||||
* to BAR space and interrupt objects.
|
|
||||||
*/
|
*/
|
||||||
void sn_pci_fixup_slot(struct pci_dev *dev)
|
void sn_pci_fixup_slot(struct pci_dev *dev, struct pcidev_info *pcidev_info,
|
||||||
|
struct sn_irq_info *sn_irq_info)
|
||||||
{
|
{
|
||||||
int segment = pci_domain_nr(dev->bus);
|
int segment = pci_domain_nr(dev->bus);
|
||||||
int status = 0;
|
|
||||||
struct pcibus_bussoft *bs;
|
struct pcibus_bussoft *bs;
|
||||||
struct pci_bus *host_pci_bus;
|
struct pci_bus *host_pci_bus;
|
||||||
struct pci_dev *host_pci_dev;
|
struct pci_dev *host_pci_dev;
|
||||||
struct pcidev_info *pcidev_info;
|
unsigned int bus_no, devfn;
|
||||||
struct sn_irq_info *sn_irq_info;
|
|
||||||
unsigned int bus_no, devfn;
|
|
||||||
|
|
||||||
pci_dev_get(dev); /* for the sysdata pointer */
|
pci_dev_get(dev); /* for the sysdata pointer */
|
||||||
pcidev_info = kzalloc(sizeof(struct pcidev_info), GFP_KERNEL);
|
|
||||||
if (!pcidev_info)
|
|
||||||
BUG(); /* Cannot afford to run out of memory */
|
|
||||||
|
|
||||||
sn_irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL);
|
|
||||||
if (!sn_irq_info)
|
|
||||||
BUG(); /* Cannot afford to run out of memory */
|
|
||||||
|
|
||||||
/* Call to retrieve pci device information needed by kernel. */
|
|
||||||
status = sal_get_pcidev_info((u64) segment, (u64) dev->bus->number,
|
|
||||||
dev->devfn,
|
|
||||||
(u64) __pa(pcidev_info),
|
|
||||||
(u64) __pa(sn_irq_info));
|
|
||||||
if (status)
|
|
||||||
BUG(); /* Cannot get platform pci device information */
|
|
||||||
|
|
||||||
/* Add pcidev_info to list in pci_controller.platform_data */
|
/* Add pcidev_info to list in pci_controller.platform_data */
|
||||||
list_add_tail(&pcidev_info->pdi_list,
|
list_add_tail(&pcidev_info->pdi_list,
|
||||||
&(SN_PLATFORM_DATA(dev->bus)->pcidev_info));
|
&(SN_PLATFORM_DATA(dev->bus)->pcidev_info));
|
||||||
|
|
||||||
if (SN_ACPI_BASE_SUPPORT())
|
|
||||||
sn_acpi_slot_fixup(dev, pcidev_info);
|
|
||||||
else
|
|
||||||
sn_more_slot_fixup(dev, pcidev_info);
|
|
||||||
/*
|
/*
|
||||||
* Using the PROMs values for the PCI host bus, get the Linux
|
* Using the PROMs values for the PCI host bus, get the Linux
|
||||||
* PCI host_pci_dev struct and set up host bus linkages
|
* PCI host_pci_dev struct and set up host bus linkages
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bus_no = (pcidev_info->pdi_slot_host_handle >> 32) & 0xff;
|
bus_no = (pcidev_info->pdi_slot_host_handle >> 32) & 0xff;
|
||||||
|
@ -489,11 +444,6 @@ void sn_generate_path(struct pci_bus *pci_bus, char *address)
|
||||||
sprintf(address, "%s^%d", address, geo_slot(geoid));
|
sprintf(address, "%s^%d", address, geo_slot(geoid));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* sn_pci_fixup_bus() - Perform SN specific setup of software structs
|
|
||||||
* (pcibus_bussoft, pcidev_info) and hardware
|
|
||||||
* registers, for the specified bus and devices under it.
|
|
||||||
*/
|
|
||||||
void __devinit
|
void __devinit
|
||||||
sn_pci_fixup_bus(struct pci_bus *bus)
|
sn_pci_fixup_bus(struct pci_bus *bus)
|
||||||
{
|
{
|
||||||
|
@ -519,6 +469,15 @@ sn_io_early_init(void)
|
||||||
if (!ia64_platform_is("sn2") || IS_RUNNING_ON_FAKE_PROM())
|
if (!ia64_platform_is("sn2") || IS_RUNNING_ON_FAKE_PROM())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
/* we set the acpi revision to that of the DSDT table OEM rev. */
|
||||||
|
{
|
||||||
|
struct acpi_table_header *header = NULL;
|
||||||
|
|
||||||
|
acpi_get_table_by_index(ACPI_TABLE_INDEX_DSDT, &header);
|
||||||
|
BUG_ON(header == NULL);
|
||||||
|
sn_acpi_rev = header->oem_revision;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* prime sn_pci_provider[]. Individial provider init routines will
|
* prime sn_pci_provider[]. Individial provider init routines will
|
||||||
* override their respective default entries.
|
* override their respective default entries.
|
||||||
|
@ -544,8 +503,12 @@ sn_io_early_init(void)
|
||||||
register_sn_procfs();
|
register_sn_procfs();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
printk(KERN_INFO "ACPI DSDT OEM Rev 0x%x\n",
|
{
|
||||||
acpi_gbl_DSDT->oem_revision);
|
struct acpi_table_header *header;
|
||||||
|
(void)acpi_get_table_by_index(ACPI_TABLE_INDEX_DSDT, &header);
|
||||||
|
printk(KERN_INFO "ACPI DSDT OEM Rev 0x%x\n",
|
||||||
|
header->oem_revision);
|
||||||
|
}
|
||||||
if (SN_ACPI_BASE_SUPPORT())
|
if (SN_ACPI_BASE_SUPPORT())
|
||||||
sn_io_acpi_init();
|
sn_io_acpi_init();
|
||||||
else
|
else
|
||||||
|
@ -605,7 +568,6 @@ sn_io_late_init(void)
|
||||||
|
|
||||||
fs_initcall(sn_io_late_init);
|
fs_initcall(sn_io_late_init);
|
||||||
|
|
||||||
EXPORT_SYMBOL(sn_pci_fixup_slot);
|
|
||||||
EXPORT_SYMBOL(sn_pci_unfixup_slot);
|
EXPORT_SYMBOL(sn_pci_unfixup_slot);
|
||||||
EXPORT_SYMBOL(sn_bus_store_sysdata);
|
EXPORT_SYMBOL(sn_bus_store_sysdata);
|
||||||
EXPORT_SYMBOL(sn_bus_free_sysdata);
|
EXPORT_SYMBOL(sn_bus_free_sysdata);
|
||||||
|
|
|
@ -56,6 +56,25 @@ static inline u64 sal_get_pcibus_info(u64 segment, u64 busnum, u64 address)
|
||||||
return ret_stuff.v0;
|
return ret_stuff.v0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Retrieve the pci device information given the bus and device|function number.
|
||||||
|
*/
|
||||||
|
static inline u64
|
||||||
|
sal_get_pcidev_info(u64 segment, u64 bus_number, u64 devfn, u64 pci_dev,
|
||||||
|
u64 sn_irq_info)
|
||||||
|
{
|
||||||
|
struct ia64_sal_retval ret_stuff;
|
||||||
|
ret_stuff.status = 0;
|
||||||
|
ret_stuff.v0 = 0;
|
||||||
|
|
||||||
|
SAL_CALL_NOLOCK(ret_stuff,
|
||||||
|
(u64) SN_SAL_IOIF_GET_PCIDEV_INFO,
|
||||||
|
(u64) segment, (u64) bus_number, (u64) devfn,
|
||||||
|
(u64) pci_dev,
|
||||||
|
sn_irq_info, 0, 0);
|
||||||
|
return ret_stuff.v0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* sn_fixup_ionodes() - This routine initializes the HUB data structure for
|
* sn_fixup_ionodes() - This routine initializes the HUB data structure for
|
||||||
|
@ -172,18 +191,40 @@ sn_pci_window_fixup(struct pci_dev *dev, unsigned int count,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* sn_more_slot_fixup() - We are not running with an ACPI capable PROM,
|
* sn_io_slot_fixup() - We are not running with an ACPI capable PROM,
|
||||||
* and need to convert the pci_dev->resource
|
* and need to convert the pci_dev->resource
|
||||||
* 'start' and 'end' addresses to mapped addresses,
|
* 'start' and 'end' addresses to mapped addresses,
|
||||||
* and setup the pci_controller->window array entries.
|
* and setup the pci_controller->window array entries.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
sn_more_slot_fixup(struct pci_dev *dev, struct pcidev_info *pcidev_info)
|
sn_io_slot_fixup(struct pci_dev *dev)
|
||||||
{
|
{
|
||||||
unsigned int count = 0;
|
unsigned int count = 0;
|
||||||
int idx;
|
int idx;
|
||||||
s64 pci_addrs[PCI_ROM_RESOURCE + 1];
|
s64 pci_addrs[PCI_ROM_RESOURCE + 1];
|
||||||
unsigned long addr, end, size, start;
|
unsigned long addr, end, size, start;
|
||||||
|
struct pcidev_info *pcidev_info;
|
||||||
|
struct sn_irq_info *sn_irq_info;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
pcidev_info = kzalloc(sizeof(struct pcidev_info), GFP_KERNEL);
|
||||||
|
if (!pcidev_info)
|
||||||
|
panic("%s: Unable to alloc memory for pcidev_info", __FUNCTION__);
|
||||||
|
|
||||||
|
sn_irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL);
|
||||||
|
if (!sn_irq_info)
|
||||||
|
panic("%s: Unable to alloc memory for sn_irq_info", __FUNCTION__);
|
||||||
|
|
||||||
|
/* Call to retrieve pci device information needed by kernel. */
|
||||||
|
status = sal_get_pcidev_info((u64) pci_domain_nr(dev),
|
||||||
|
(u64) dev->bus->number,
|
||||||
|
dev->devfn,
|
||||||
|
(u64) __pa(pcidev_info),
|
||||||
|
(u64) __pa(sn_irq_info));
|
||||||
|
|
||||||
|
if (status)
|
||||||
|
BUG(); /* Cannot get platform pci device information */
|
||||||
|
|
||||||
|
|
||||||
/* Copy over PIO Mapped Addresses */
|
/* Copy over PIO Mapped Addresses */
|
||||||
for (idx = 0; idx <= PCI_ROM_RESOURCE; idx++) {
|
for (idx = 0; idx <= PCI_ROM_RESOURCE; idx++) {
|
||||||
|
@ -219,8 +260,12 @@ sn_more_slot_fixup(struct pci_dev *dev, struct pcidev_info *pcidev_info)
|
||||||
*/
|
*/
|
||||||
if (count > 0)
|
if (count > 0)
|
||||||
sn_pci_window_fixup(dev, count, pci_addrs);
|
sn_pci_window_fixup(dev, count, pci_addrs);
|
||||||
|
|
||||||
|
sn_pci_fixup_slot(dev, pcidev_info, sn_irq_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EXPORT_SYMBOL(sn_io_slot_fixup);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* sn_pci_controller_fixup() - This routine sets up a bus's resources
|
* sn_pci_controller_fixup() - This routine sets up a bus's resources
|
||||||
* consistent with the Linux PCI abstraction layer.
|
* consistent with the Linux PCI abstraction layer.
|
||||||
|
@ -272,9 +317,6 @@ sn_bus_fixup(struct pci_bus *bus)
|
||||||
{
|
{
|
||||||
struct pci_dev *pci_dev = NULL;
|
struct pci_dev *pci_dev = NULL;
|
||||||
struct pcibus_bussoft *prom_bussoft_ptr;
|
struct pcibus_bussoft *prom_bussoft_ptr;
|
||||||
extern void sn_common_bus_fixup(struct pci_bus *,
|
|
||||||
struct pcibus_bussoft *);
|
|
||||||
|
|
||||||
|
|
||||||
if (!bus->parent) { /* If root bus */
|
if (!bus->parent) { /* If root bus */
|
||||||
prom_bussoft_ptr = PCI_CONTROLLER(bus)->platform_data;
|
prom_bussoft_ptr = PCI_CONTROLLER(bus)->platform_data;
|
||||||
|
@ -291,7 +333,7 @@ sn_bus_fixup(struct pci_bus *bus)
|
||||||
prom_bussoft_ptr->bs_legacy_mem);
|
prom_bussoft_ptr->bs_legacy_mem);
|
||||||
}
|
}
|
||||||
list_for_each_entry(pci_dev, &bus->devices, bus_list) {
|
list_for_each_entry(pci_dev, &bus->devices, bus_list) {
|
||||||
sn_pci_fixup_slot(pci_dev);
|
sn_io_slot_fixup(pci_dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/*
|
/*
|
||||||
* This file is subject to the terms and conditions of the GNU General Public
|
* This file is subject to the terms and conditions of the GNU General Public
|
||||||
* License. See the file "COPYING" in the main directory of this archive
|
* License. See the file "COPYING" in the main directory of this archive
|
||||||
* for more details.
|
* for more details.
|
||||||
|
@ -26,9 +26,10 @@
|
||||||
* @port: port to convert
|
* @port: port to convert
|
||||||
*
|
*
|
||||||
* Legacy in/out instructions are converted to ld/st instructions
|
* Legacy in/out instructions are converted to ld/st instructions
|
||||||
* on IA64. This routine will convert a port number into a valid
|
* on IA64. This routine will convert a port number into a valid
|
||||||
* SN i/o address. Used by sn_in*() and sn_out*().
|
* SN i/o address. Used by sn_in*() and sn_out*().
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void *sn_io_addr(unsigned long port)
|
void *sn_io_addr(unsigned long port)
|
||||||
{
|
{
|
||||||
if (!IS_RUNNING_ON_SIMULATOR()) {
|
if (!IS_RUNNING_ON_SIMULATOR()) {
|
||||||
|
|
|
@ -59,13 +59,12 @@ void sn_teardown_msi_irq(unsigned int irq)
|
||||||
sn_intr_free(nasid, widget, sn_irq_info);
|
sn_intr_free(nasid, widget, sn_irq_info);
|
||||||
sn_msi_info[irq].sn_irq_info = NULL;
|
sn_msi_info[irq].sn_irq_info = NULL;
|
||||||
|
|
||||||
return;
|
destroy_irq(irq);
|
||||||
}
|
}
|
||||||
|
|
||||||
int sn_setup_msi_irq(unsigned int irq, struct pci_dev *pdev)
|
int sn_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *entry)
|
||||||
{
|
{
|
||||||
struct msi_msg msg;
|
struct msi_msg msg;
|
||||||
struct msi_desc *entry;
|
|
||||||
int widget;
|
int widget;
|
||||||
int status;
|
int status;
|
||||||
nasid_t nasid;
|
nasid_t nasid;
|
||||||
|
@ -73,8 +72,8 @@ int sn_setup_msi_irq(unsigned int irq, struct pci_dev *pdev)
|
||||||
struct sn_irq_info *sn_irq_info;
|
struct sn_irq_info *sn_irq_info;
|
||||||
struct pcibus_bussoft *bussoft = SN_PCIDEV_BUSSOFT(pdev);
|
struct pcibus_bussoft *bussoft = SN_PCIDEV_BUSSOFT(pdev);
|
||||||
struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
|
struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
|
||||||
|
int irq;
|
||||||
|
|
||||||
entry = get_irq_data(irq);
|
|
||||||
if (!entry->msi_attrib.is_64)
|
if (!entry->msi_attrib.is_64)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
@ -84,6 +83,11 @@ int sn_setup_msi_irq(unsigned int irq, struct pci_dev *pdev)
|
||||||
if (provider == NULL || provider->dma_map_consistent == NULL)
|
if (provider == NULL || provider->dma_map_consistent == NULL)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
irq = create_irq();
|
||||||
|
if (irq < 0)
|
||||||
|
return irq;
|
||||||
|
|
||||||
|
set_irq_msi(irq, entry);
|
||||||
/*
|
/*
|
||||||
* Set up the vector plumbing. Let the prom (via sn_intr_alloc)
|
* Set up the vector plumbing. Let the prom (via sn_intr_alloc)
|
||||||
* decide which cpu to direct this msi at by default.
|
* decide which cpu to direct this msi at by default.
|
||||||
|
@ -95,12 +99,15 @@ int sn_setup_msi_irq(unsigned int irq, struct pci_dev *pdev)
|
||||||
SWIN_WIDGETNUM(bussoft->bs_base);
|
SWIN_WIDGETNUM(bussoft->bs_base);
|
||||||
|
|
||||||
sn_irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL);
|
sn_irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL);
|
||||||
if (! sn_irq_info)
|
if (! sn_irq_info) {
|
||||||
|
destroy_irq(irq);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
status = sn_intr_alloc(nasid, widget, sn_irq_info, irq, -1, -1);
|
status = sn_intr_alloc(nasid, widget, sn_irq_info, irq, -1, -1);
|
||||||
if (status) {
|
if (status) {
|
||||||
kfree(sn_irq_info);
|
kfree(sn_irq_info);
|
||||||
|
destroy_irq(irq);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,6 +128,7 @@ int sn_setup_msi_irq(unsigned int irq, struct pci_dev *pdev)
|
||||||
if (! bus_addr) {
|
if (! bus_addr) {
|
||||||
sn_intr_free(nasid, widget, sn_irq_info);
|
sn_intr_free(nasid, widget, sn_irq_info);
|
||||||
kfree(sn_irq_info);
|
kfree(sn_irq_info);
|
||||||
|
destroy_irq(irq);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,7 +147,7 @@ int sn_setup_msi_irq(unsigned int irq, struct pci_dev *pdev)
|
||||||
write_msi_msg(irq, &msg);
|
write_msi_msg(irq, &msg);
|
||||||
set_irq_chip_and_handler(irq, &sn_msi_chip, handle_edge_irq);
|
set_irq_chip_and_handler(irq, &sn_msi_chip, handle_edge_irq);
|
||||||
|
|
||||||
return 0;
|
return irq;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
|
|
|
@ -20,7 +20,8 @@
|
||||||
#include "xtalk/hubdev.h"
|
#include "xtalk/hubdev.h"
|
||||||
|
|
||||||
int
|
int
|
||||||
sal_pcibr_slot_enable(struct pcibus_info *soft, int device, void *resp)
|
sal_pcibr_slot_enable(struct pcibus_info *soft, int device, void *resp,
|
||||||
|
char **ssdt)
|
||||||
{
|
{
|
||||||
struct ia64_sal_retval ret_stuff;
|
struct ia64_sal_retval ret_stuff;
|
||||||
u64 busnum;
|
u64 busnum;
|
||||||
|
@ -32,7 +33,8 @@ sal_pcibr_slot_enable(struct pcibus_info *soft, int device, void *resp)
|
||||||
segment = soft->pbi_buscommon.bs_persist_segment;
|
segment = soft->pbi_buscommon.bs_persist_segment;
|
||||||
busnum = soft->pbi_buscommon.bs_persist_busnum;
|
busnum = soft->pbi_buscommon.bs_persist_busnum;
|
||||||
SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_SLOT_ENABLE, segment,
|
SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_SLOT_ENABLE, segment,
|
||||||
busnum, (u64) device, (u64) resp, 0, 0, 0);
|
busnum, (u64) device, (u64) resp, (u64)ia64_tpa(ssdt),
|
||||||
|
0, 0);
|
||||||
|
|
||||||
return (int)ret_stuff.v0;
|
return (int)ret_stuff.v0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
#include <asm/machdep.h>
|
#include <asm/machdep.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
|
#include <asm/irq_regs.h>
|
||||||
|
|
||||||
#define TICK_SIZE (tick_nsec / 1000)
|
#define TICK_SIZE (tick_nsec / 1000)
|
||||||
|
|
||||||
|
@ -38,7 +39,7 @@ static inline int set_rtc_mmss(unsigned long nowtime)
|
||||||
* timer_interrupt() needs to keep up the real-time clock,
|
* timer_interrupt() needs to keep up the real-time clock,
|
||||||
* as well as call the "do_timer()" routine every clocktick
|
* as well as call the "do_timer()" routine every clocktick
|
||||||
*/
|
*/
|
||||||
static irqreturn_t timer_interrupt(int irq, void *dummy, struct pt_regs * regs)
|
static irqreturn_t timer_interrupt(int irq, void *dummy)
|
||||||
{
|
{
|
||||||
/* last time the cmos clock got updated */
|
/* last time the cmos clock got updated */
|
||||||
static long last_rtc_update=0;
|
static long last_rtc_update=0;
|
||||||
|
@ -51,7 +52,7 @@ static irqreturn_t timer_interrupt(int irq, void *dummy, struct pt_regs * regs)
|
||||||
|
|
||||||
do_timer(1);
|
do_timer(1);
|
||||||
#ifndef CONFIG_SMP
|
#ifndef CONFIG_SMP
|
||||||
update_process_times(user_mode(regs));
|
update_process_times(user_mode(get_irq_regs()));
|
||||||
#endif
|
#endif
|
||||||
if (current->pid)
|
if (current->pid)
|
||||||
profile_tick(CPU_PROFILING);
|
profile_tick(CPU_PROFILING);
|
||||||
|
|
|
@ -87,6 +87,16 @@ SECTIONS {
|
||||||
*(__ksymtab_gpl)
|
*(__ksymtab_gpl)
|
||||||
__stop___ksymtab_gpl = .;
|
__stop___ksymtab_gpl = .;
|
||||||
|
|
||||||
|
/* Kernel symbol table: Normal unused symbols */
|
||||||
|
__start___ksymtab_unused = .;
|
||||||
|
*(__ksymtab_unused)
|
||||||
|
__stop___ksymtab_unused = .;
|
||||||
|
|
||||||
|
/* Kernel symbol table: GPL-only unused symbols */
|
||||||
|
__start___ksymtab_unused_gpl = .;
|
||||||
|
*(__ksymtab_unused_gpl)
|
||||||
|
__stop___ksymtab_unused_gpl = .;
|
||||||
|
|
||||||
/* Kernel symbol table: GPL-future symbols */
|
/* Kernel symbol table: GPL-future symbols */
|
||||||
__start___ksymtab_gpl_future = .;
|
__start___ksymtab_gpl_future = .;
|
||||||
*(__ksymtab_gpl_future)
|
*(__ksymtab_gpl_future)
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
|
||||||
void coldfire_tick(void);
|
void coldfire_tick(void);
|
||||||
void coldfire_timer_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
|
void coldfire_timer_init(irq_handler_t handler);
|
||||||
unsigned long coldfire_timer_offset(void);
|
unsigned long coldfire_timer_offset(void);
|
||||||
void coldfire_trap_init(void);
|
void coldfire_trap_init(void);
|
||||||
void coldfire_reset(void);
|
void coldfire_reset(void);
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
|
||||||
void coldfire_tick(void);
|
void coldfire_tick(void);
|
||||||
void coldfire_timer_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
|
void coldfire_timer_init(irq_handler_t handler);
|
||||||
unsigned long coldfire_timer_offset(void);
|
unsigned long coldfire_timer_offset(void);
|
||||||
void coldfire_trap_init(void);
|
void coldfire_trap_init(void);
|
||||||
void coldfire_reset(void);
|
void coldfire_reset(void);
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
|
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/param.h>
|
#include <linux/param.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
#include <asm/machdep.h>
|
#include <asm/machdep.h>
|
||||||
#include <asm/dma.h>
|
#include <asm/dma.h>
|
||||||
|
|
||||||
|
@ -27,7 +28,7 @@ unsigned int dma_device_address[MAX_M68K_DMA_CHANNELS];
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
|
||||||
void coldfire_pit_tick(void);
|
void coldfire_pit_tick(void);
|
||||||
void coldfire_pit_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
|
void coldfire_pit_init(irq_handler_t handler);
|
||||||
unsigned long coldfire_pit_offset(void);
|
unsigned long coldfire_pit_offset(void);
|
||||||
void coldfire_trap_init(void);
|
void coldfire_trap_init(void);
|
||||||
void coldfire_reset(void);
|
void coldfire_reset(void);
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
|
||||||
void coldfire_pit_tick(void);
|
void coldfire_pit_tick(void);
|
||||||
void coldfire_pit_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
|
void coldfire_pit_init(irq_handler_t handler);
|
||||||
unsigned long coldfire_pit_offset(void);
|
unsigned long coldfire_pit_offset(void);
|
||||||
void coldfire_trap_init(void);
|
void coldfire_trap_init(void);
|
||||||
void coldfire_reset(void);
|
void coldfire_reset(void);
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/param.h>
|
#include <linux/param.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
#include <asm/irq.h>
|
#include <asm/irq.h>
|
||||||
#include <asm/dma.h>
|
#include <asm/dma.h>
|
||||||
#include <asm/traps.h>
|
#include <asm/traps.h>
|
||||||
|
@ -24,7 +25,7 @@
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
|
||||||
void coldfire_tick(void);
|
void coldfire_tick(void);
|
||||||
void coldfire_timer_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
|
void coldfire_timer_init(irq_handler_t handler);
|
||||||
unsigned long coldfire_timer_offset(void);
|
unsigned long coldfire_timer_offset(void);
|
||||||
void coldfire_trap_init(void);
|
void coldfire_trap_init(void);
|
||||||
void coldfire_reset(void);
|
void coldfire_reset(void);
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
|
||||||
void coldfire_tick(void);
|
void coldfire_tick(void);
|
||||||
void coldfire_timer_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
|
void coldfire_timer_init(irq_handler_t handler);
|
||||||
unsigned long coldfire_timer_offset(void);
|
unsigned long coldfire_timer_offset(void);
|
||||||
void coldfire_trap_init(void);
|
void coldfire_trap_init(void);
|
||||||
void coldfire_reset(void);
|
void coldfire_reset(void);
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
|
||||||
void coldfire_pit_tick(void);
|
void coldfire_pit_tick(void);
|
||||||
void coldfire_pit_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
|
void coldfire_pit_init(irq_handler_t handler);
|
||||||
unsigned long coldfire_pit_offset(void);
|
unsigned long coldfire_pit_offset(void);
|
||||||
void coldfire_trap_init(void);
|
void coldfire_trap_init(void);
|
||||||
void coldfire_reset(void);
|
void coldfire_reset(void);
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
|
||||||
void coldfire_pit_tick(void);
|
void coldfire_pit_tick(void);
|
||||||
void coldfire_pit_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
|
void coldfire_pit_init(irq_handler_t handler);
|
||||||
unsigned long coldfire_pit_offset(void);
|
unsigned long coldfire_pit_offset(void);
|
||||||
void coldfire_trap_init(void);
|
void coldfire_trap_init(void);
|
||||||
void coldfire_reset(void);
|
void coldfire_reset(void);
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
|
||||||
void coldfire_tick(void);
|
void coldfire_tick(void);
|
||||||
void coldfire_timer_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
|
void coldfire_timer_init(irq_handler_t handler);
|
||||||
unsigned long coldfire_timer_offset(void);
|
unsigned long coldfire_timer_offset(void);
|
||||||
void coldfire_trap_init(void);
|
void coldfire_trap_init(void);
|
||||||
void coldfire_reset(void);
|
void coldfire_reset(void);
|
||||||
|
|
|
@ -43,7 +43,7 @@ void coldfire_pit_tick(void)
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
|
||||||
void coldfire_pit_init(irqreturn_t (*handler)(int, void *, struct pt_regs *))
|
void coldfire_pit_init(irq_handler_t handler)
|
||||||
{
|
{
|
||||||
volatile unsigned char *icrp;
|
volatile unsigned char *icrp;
|
||||||
volatile unsigned long *imrp;
|
volatile unsigned long *imrp;
|
||||||
|
|
|
@ -62,7 +62,7 @@ void coldfire_tick(void)
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
|
||||||
void coldfire_timer_init(irqreturn_t (*handler)(int, void *, struct pt_regs *))
|
void coldfire_timer_init(irq_handler_t handler)
|
||||||
{
|
{
|
||||||
__raw_writew(MCFTIMER_TMR_DISABLE, TA(MCFTIMER_TMR));
|
__raw_writew(MCFTIMER_TMR_DISABLE, TA(MCFTIMER_TMR));
|
||||||
__raw_writetrr(((MCF_BUSCLK / 16) / HZ), TA(MCFTIMER_TRR));
|
__raw_writetrr(((MCF_BUSCLK / 16) / HZ), TA(MCFTIMER_TRR));
|
||||||
|
@ -111,12 +111,13 @@ unsigned long coldfire_timer_offset(void)
|
||||||
/*
|
/*
|
||||||
* Use the other timer to provide high accuracy profiling info.
|
* Use the other timer to provide high accuracy profiling info.
|
||||||
*/
|
*/
|
||||||
void coldfire_profile_tick(int irq, void *dummy, struct pt_regs *regs)
|
irqreturn_t coldfire_profile_tick(int irq, void *dummy)
|
||||||
{
|
{
|
||||||
/* Reset ColdFire timer2 */
|
/* Reset ColdFire timer2 */
|
||||||
__raw_writeb(MCFTIMER_TER_CAP | MCFTIMER_TER_REF, PA(MCFTIMER_TER));
|
__raw_writeb(MCFTIMER_TER_CAP | MCFTIMER_TER_REF, PA(MCFTIMER_TER));
|
||||||
if (current->pid)
|
if (current->pid)
|
||||||
profile_tick(CPU_PROFILING, regs);
|
profile_tick(CPU_PROFILING, regs);
|
||||||
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
|
||||||
void coldfire_tick(void);
|
void coldfire_tick(void);
|
||||||
void coldfire_timer_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
|
void coldfire_timer_init(irq_handler_t handler);
|
||||||
unsigned long coldfire_timer_offset(void);
|
unsigned long coldfire_timer_offset(void);
|
||||||
void coldfire_trap_init(void);
|
void coldfire_trap_init(void);
|
||||||
void coldfire_reset(void);
|
void coldfire_reset(void);
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue