forked from Minki/linux
Merge with /pub/scm/linux/kernel/git/torvalds/linux-2.6.git
This commit is contained in:
commit
fae6ec69c8
6
CREDITS
6
CREDITS
@ -2475,13 +2475,9 @@ S: Potsdam, New York 13676
|
||||
S: USA
|
||||
|
||||
N: Dave Neuer
|
||||
E: dneuer@innovation-charter.com
|
||||
E: mr_fred_smoothie@yahoo.com
|
||||
E: dave.neuer@pobox.com
|
||||
D: Helped implement support for Compaq's H31xx series iPAQs
|
||||
D: Other mostly minor tweaks & bugfixes
|
||||
S: 325 E. Main St., Suite 3
|
||||
S: Carnegie, PA 15105
|
||||
S: USA
|
||||
|
||||
N: Michael Neuffer
|
||||
E: mike@i-Connect.Net
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
DOCBOOKS := wanbook.xml z8530book.xml mcabook.xml videobook.xml \
|
||||
kernel-hacking.xml kernel-locking.xml deviceiobook.xml \
|
||||
procfs-guide.xml writing_usb_driver.xml scsidrivers.xml \
|
||||
procfs-guide.xml writing_usb_driver.xml \
|
||||
sis900.xml kernel-api.xml journal-api.xml lsm.xml usb.xml \
|
||||
gadget.xml libata.xml mtdnand.xml librs.xml
|
||||
|
||||
|
@ -338,7 +338,6 @@ X!Earch/i386/kernel/mca.c
|
||||
X!Iinclude/linux/device.h
|
||||
-->
|
||||
!Edrivers/base/driver.c
|
||||
!Edrivers/base/class_simple.c
|
||||
!Edrivers/base/core.c
|
||||
!Edrivers/base/firmware_class.c
|
||||
!Edrivers/base/transport_class.c
|
||||
|
@ -14,7 +14,7 @@
|
||||
</authorgroup>
|
||||
|
||||
<copyright>
|
||||
<year>2003</year>
|
||||
<year>2003-2005</year>
|
||||
<holder>Jeff Garzik</holder>
|
||||
</copyright>
|
||||
|
||||
@ -44,30 +44,38 @@
|
||||
|
||||
<toc></toc>
|
||||
|
||||
<chapter id="libataThanks">
|
||||
<title>Thanks</title>
|
||||
<chapter id="libataIntroduction">
|
||||
<title>Introduction</title>
|
||||
<para>
|
||||
The bulk of the ATA knowledge comes thanks to long conversations with
|
||||
Andre Hedrick (www.linux-ide.org).
|
||||
libATA is a library used inside the Linux kernel to support ATA host
|
||||
controllers and devices. libATA provides an ATA driver API, class
|
||||
transports for ATA and ATAPI devices, and SCSI<->ATA translation
|
||||
for ATA devices according to the T10 SAT specification.
|
||||
</para>
|
||||
<para>
|
||||
Thanks to Alan Cox for pointing out similarities
|
||||
between SATA and SCSI, and in general for motivation to hack on
|
||||
libata.
|
||||
</para>
|
||||
<para>
|
||||
libata's device detection
|
||||
method, ata_pio_devchk, and in general all the early probing was
|
||||
based on extensive study of Hale Landis's probe/reset code in his
|
||||
ATADRVR driver (www.ata-atapi.com).
|
||||
This Guide documents the libATA driver API, library functions, library
|
||||
internals, and a couple sample ATA low-level drivers.
|
||||
</para>
|
||||
</chapter>
|
||||
|
||||
<chapter id="libataDriverApi">
|
||||
<title>libata Driver API</title>
|
||||
<para>
|
||||
struct ata_port_operations is defined for every low-level libata
|
||||
hardware driver, and it controls how the low-level driver
|
||||
interfaces with the ATA and SCSI layers.
|
||||
</para>
|
||||
<para>
|
||||
FIS-based drivers will hook into the system with ->qc_prep() and
|
||||
->qc_issue() high-level hooks. Hardware which behaves in a manner
|
||||
similar to PCI IDE hardware may utilize several generic helpers,
|
||||
defining at a bare minimum the bus I/O addresses of the ATA shadow
|
||||
register blocks.
|
||||
</para>
|
||||
<sect1>
|
||||
<title>struct ata_port_operations</title>
|
||||
|
||||
<sect2><title>Disable ATA port</title>
|
||||
<programlisting>
|
||||
void (*port_disable) (struct ata_port *);
|
||||
</programlisting>
|
||||
@ -78,6 +86,9 @@ void (*port_disable) (struct ata_port *);
|
||||
unplug).
|
||||
</para>
|
||||
|
||||
</sect2>
|
||||
|
||||
<sect2><title>Post-IDENTIFY device configuration</title>
|
||||
<programlisting>
|
||||
void (*dev_config) (struct ata_port *, struct ata_device *);
|
||||
</programlisting>
|
||||
@ -88,6 +99,9 @@ void (*dev_config) (struct ata_port *, struct ata_device *);
|
||||
issue of SET FEATURES - XFER MODE, and prior to operation.
|
||||
</para>
|
||||
|
||||
</sect2>
|
||||
|
||||
<sect2><title>Set PIO/DMA mode</title>
|
||||
<programlisting>
|
||||
void (*set_piomode) (struct ata_port *, struct ata_device *);
|
||||
void (*set_dmamode) (struct ata_port *, struct ata_device *);
|
||||
@ -108,6 +122,9 @@ void (*post_set_mode) (struct ata_port *ap);
|
||||
->set_dma_mode() is only called if DMA is possible.
|
||||
</para>
|
||||
|
||||
</sect2>
|
||||
|
||||
<sect2><title>Taskfile read/write</title>
|
||||
<programlisting>
|
||||
void (*tf_load) (struct ata_port *ap, struct ata_taskfile *tf);
|
||||
void (*tf_read) (struct ata_port *ap, struct ata_taskfile *tf);
|
||||
@ -120,6 +137,9 @@ void (*tf_read) (struct ata_port *ap, struct ata_taskfile *tf);
|
||||
taskfile register values.
|
||||
</para>
|
||||
|
||||
</sect2>
|
||||
|
||||
<sect2><title>ATA command execute</title>
|
||||
<programlisting>
|
||||
void (*exec_command)(struct ata_port *ap, struct ata_taskfile *tf);
|
||||
</programlisting>
|
||||
@ -129,17 +149,37 @@ void (*exec_command)(struct ata_port *ap, struct ata_taskfile *tf);
|
||||
->tf_load(), to be initiated in hardware.
|
||||
</para>
|
||||
|
||||
</sect2>
|
||||
|
||||
<sect2><title>Per-cmd ATAPI DMA capabilities filter</title>
|
||||
<programlisting>
|
||||
u8 (*check_status)(struct ata_port *ap);
|
||||
void (*dev_select)(struct ata_port *ap, unsigned int device);
|
||||
int (*check_atapi_dma) (struct ata_queued_cmd *qc);
|
||||
</programlisting>
|
||||
|
||||
<para>
|
||||
Reads the Status ATA shadow register from hardware. On some
|
||||
hardware, this has the side effect of clearing the interrupt
|
||||
condition.
|
||||
Allow low-level driver to filter ATA PACKET commands, returning a status
|
||||
indicating whether or not it is OK to use DMA for the supplied PACKET
|
||||
command.
|
||||
</para>
|
||||
|
||||
</sect2>
|
||||
|
||||
<sect2><title>Read specific ATA shadow registers</title>
|
||||
<programlisting>
|
||||
u8 (*check_status)(struct ata_port *ap);
|
||||
u8 (*check_altstatus)(struct ata_port *ap);
|
||||
u8 (*check_err)(struct ata_port *ap);
|
||||
</programlisting>
|
||||
|
||||
<para>
|
||||
Reads the Status/AltStatus/Error ATA shadow register from
|
||||
hardware. On some hardware, reading the Status register has
|
||||
the side effect of clearing the interrupt condition.
|
||||
</para>
|
||||
|
||||
</sect2>
|
||||
|
||||
<sect2><title>Select ATA device on bus</title>
|
||||
<programlisting>
|
||||
void (*dev_select)(struct ata_port *ap, unsigned int device);
|
||||
</programlisting>
|
||||
@ -147,9 +187,13 @@ void (*dev_select)(struct ata_port *ap, unsigned int device);
|
||||
<para>
|
||||
Issues the low-level hardware command(s) that causes one of N
|
||||
hardware devices to be considered 'selected' (active and
|
||||
available for use) on the ATA bus.
|
||||
available for use) on the ATA bus. This generally has no
|
||||
meaning on FIS-based devices.
|
||||
</para>
|
||||
|
||||
</sect2>
|
||||
|
||||
<sect2><title>Reset ATA bus</title>
|
||||
<programlisting>
|
||||
void (*phy_reset) (struct ata_port *ap);
|
||||
</programlisting>
|
||||
@ -162,17 +206,31 @@ void (*phy_reset) (struct ata_port *ap);
|
||||
functions ata_bus_reset() or sata_phy_reset() for this hook.
|
||||
</para>
|
||||
|
||||
</sect2>
|
||||
|
||||
<sect2><title>Control PCI IDE BMDMA engine</title>
|
||||
<programlisting>
|
||||
void (*bmdma_setup) (struct ata_queued_cmd *qc);
|
||||
void (*bmdma_start) (struct ata_queued_cmd *qc);
|
||||
void (*bmdma_stop) (struct ata_port *ap);
|
||||
u8 (*bmdma_status) (struct ata_port *ap);
|
||||
</programlisting>
|
||||
|
||||
<para>
|
||||
When setting up an IDE BMDMA transaction, these hooks arm
|
||||
(->bmdma_setup) and fire (->bmdma_start) the hardware's DMA
|
||||
engine.
|
||||
When setting up an IDE BMDMA transaction, these hooks arm
|
||||
(->bmdma_setup), fire (->bmdma_start), and halt (->bmdma_stop)
|
||||
the hardware's DMA engine. ->bmdma_status is used to read the standard
|
||||
PCI IDE DMA Status register.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
These hooks are typically either no-ops, or simply not implemented, in
|
||||
FIS-based drivers.
|
||||
</para>
|
||||
|
||||
</sect2>
|
||||
|
||||
<sect2><title>High-level taskfile hooks</title>
|
||||
<programlisting>
|
||||
void (*qc_prep) (struct ata_queued_cmd *qc);
|
||||
int (*qc_issue) (struct ata_queued_cmd *qc);
|
||||
@ -190,20 +248,26 @@ int (*qc_issue) (struct ata_queued_cmd *qc);
|
||||
->qc_issue is used to make a command active, once the hardware
|
||||
and S/G tables have been prepared. IDE BMDMA drivers use the
|
||||
helper function ata_qc_issue_prot() for taskfile protocol-based
|
||||
dispatch. More advanced drivers roll their own ->qc_issue
|
||||
implementation, using this as the "issue new ATA command to
|
||||
hardware" hook.
|
||||
dispatch. More advanced drivers implement their own ->qc_issue.
|
||||
</para>
|
||||
|
||||
</sect2>
|
||||
|
||||
<sect2><title>Timeout (error) handling</title>
|
||||
<programlisting>
|
||||
void (*eng_timeout) (struct ata_port *ap);
|
||||
</programlisting>
|
||||
|
||||
<para>
|
||||
This is a high level error handling function, called from the
|
||||
error handling thread, when a command times out.
|
||||
This is a high level error handling function, called from the
|
||||
error handling thread, when a command times out. Most newer
|
||||
hardware will implement its own error handling code here. IDE BMDMA
|
||||
drivers may use the helper function ata_eng_timeout().
|
||||
</para>
|
||||
|
||||
</sect2>
|
||||
|
||||
<sect2><title>Hardware interrupt handling</title>
|
||||
<programlisting>
|
||||
irqreturn_t (*irq_handler)(int, void *, struct pt_regs *);
|
||||
void (*irq_clear) (struct ata_port *);
|
||||
@ -216,6 +280,9 @@ void (*irq_clear) (struct ata_port *);
|
||||
is quiet.
|
||||
</para>
|
||||
|
||||
</sect2>
|
||||
|
||||
<sect2><title>SATA phy read/write</title>
|
||||
<programlisting>
|
||||
u32 (*scr_read) (struct ata_port *ap, unsigned int sc_reg);
|
||||
void (*scr_write) (struct ata_port *ap, unsigned int sc_reg,
|
||||
@ -227,6 +294,9 @@ void (*scr_write) (struct ata_port *ap, unsigned int sc_reg,
|
||||
if ->phy_reset hook called the sata_phy_reset() helper function.
|
||||
</para>
|
||||
|
||||
</sect2>
|
||||
|
||||
<sect2><title>Init and shutdown</title>
|
||||
<programlisting>
|
||||
int (*port_start) (struct ata_port *ap);
|
||||
void (*port_stop) (struct ata_port *ap);
|
||||
@ -240,15 +310,17 @@ void (*host_stop) (struct ata_host_set *host_set);
|
||||
tasks.
|
||||
</para>
|
||||
<para>
|
||||
->host_stop() is called when the rmmod or hot unplug process
|
||||
begins. The hook must stop all hardware interrupts, DMA
|
||||
engines, etc.
|
||||
</para>
|
||||
<para>
|
||||
->port_stop() is called after ->host_stop(). It's sole function
|
||||
is to release DMA/memory resources, now that they are no longer
|
||||
actively being used.
|
||||
</para>
|
||||
<para>
|
||||
->host_stop() is called after all ->port_stop() calls
|
||||
have completed. The hook must finalize hardware shutdown, release DMA
|
||||
and other resources, etc.
|
||||
</para>
|
||||
|
||||
</sect2>
|
||||
|
||||
</sect1>
|
||||
</chapter>
|
||||
@ -279,4 +351,24 @@ void (*host_stop) (struct ata_host_set *host_set);
|
||||
!Idrivers/scsi/sata_sil.c
|
||||
</chapter>
|
||||
|
||||
<chapter id="libataThanks">
|
||||
<title>Thanks</title>
|
||||
<para>
|
||||
The bulk of the ATA knowledge comes thanks to long conversations with
|
||||
Andre Hedrick (www.linux-ide.org), and long hours pondering the ATA
|
||||
and SCSI specifications.
|
||||
</para>
|
||||
<para>
|
||||
Thanks to Alan Cox for pointing out similarities
|
||||
between SATA and SCSI, and in general for motivation to hack on
|
||||
libata.
|
||||
</para>
|
||||
<para>
|
||||
libata's device detection
|
||||
method, ata_pio_devchk, and in general all the early probing was
|
||||
based on extensive study of Hale Landis's probe/reset code in his
|
||||
ATADRVR driver (www.ata-atapi.com).
|
||||
</para>
|
||||
</chapter>
|
||||
|
||||
</book>
|
||||
|
@ -1,193 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
|
||||
|
||||
<book id="scsidrivers">
|
||||
<bookinfo>
|
||||
<title>SCSI Subsystem Interfaces</title>
|
||||
|
||||
<authorgroup>
|
||||
<author>
|
||||
<firstname>Douglas</firstname>
|
||||
<surname>Gilbert</surname>
|
||||
<affiliation>
|
||||
<address>
|
||||
<email>dgilbert@interlog.com</email>
|
||||
</address>
|
||||
</affiliation>
|
||||
</author>
|
||||
</authorgroup>
|
||||
<pubdate>2003-08-11</pubdate>
|
||||
|
||||
<copyright>
|
||||
<year>2002</year>
|
||||
<year>2003</year>
|
||||
<holder>Douglas Gilbert</holder>
|
||||
</copyright>
|
||||
|
||||
<legalnotice>
|
||||
<para>
|
||||
This documentation is free software; you can redistribute
|
||||
it and/or modify it under the terms of the GNU General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
This program is distributed in the hope that it will be
|
||||
useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
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
|
||||
</para>
|
||||
|
||||
<para>
|
||||
For more details see the file COPYING in the source
|
||||
distribution of Linux.
|
||||
</para>
|
||||
</legalnotice>
|
||||
|
||||
</bookinfo>
|
||||
|
||||
<toc></toc>
|
||||
|
||||
<chapter id="intro">
|
||||
<title>Introduction</title>
|
||||
<para>
|
||||
This document outlines the interface between the Linux scsi mid level
|
||||
and lower level drivers. Lower level drivers are variously called HBA
|
||||
(host bus adapter) drivers, host drivers (HD) or pseudo adapter drivers.
|
||||
The latter alludes to the fact that a lower level driver may be a
|
||||
bridge to another IO subsystem (and the "ide-scsi" driver is an example
|
||||
of this). There can be many lower level drivers active in a running
|
||||
system, but only one per hardware type. For example, the aic7xxx driver
|
||||
controls adaptec controllers based on the 7xxx chip series. Most lower
|
||||
level drivers can control one or more scsi hosts (a.k.a. scsi initiators).
|
||||
</para>
|
||||
<para>
|
||||
This document can been found in an ASCII text file in the linux kernel
|
||||
source: <filename>Documentation/scsi/scsi_mid_low_api.txt</filename> .
|
||||
It currently hold a little more information than this document. The
|
||||
<filename>drivers/scsi/hosts.h</filename> and <filename>
|
||||
drivers/scsi/scsi.h</filename> headers contain descriptions of members
|
||||
of important structures for the scsi subsystem.
|
||||
</para>
|
||||
</chapter>
|
||||
|
||||
<chapter id="driver-struct">
|
||||
<title>Driver structure</title>
|
||||
<para>
|
||||
Traditionally a lower level driver for the scsi subsystem has been
|
||||
at least two files in the drivers/scsi directory. For example, a
|
||||
driver called "xyz" has a header file "xyz.h" and a source file
|
||||
"xyz.c". [Actually there is no good reason why this couldn't all
|
||||
be in one file.] Some drivers that have been ported to several operating
|
||||
systems (e.g. aic7xxx which has separate files for generic and
|
||||
OS-specific code) have more than two files. Such drivers tend to have
|
||||
their own directory under the drivers/scsi directory.
|
||||
</para>
|
||||
<para>
|
||||
scsi_module.c is normally included at the end of a lower
|
||||
level driver. For it to work a declaration like this is needed before
|
||||
it is included:
|
||||
<programlisting>
|
||||
static Scsi_Host_Template driver_template = DRIVER_TEMPLATE;
|
||||
/* DRIVER_TEMPLATE should contain pointers to supported interface
|
||||
functions. Scsi_Host_Template is defined hosts.h */
|
||||
#include "scsi_module.c"
|
||||
</programlisting>
|
||||
</para>
|
||||
<para>
|
||||
The scsi_module.c assumes the name "driver_template" is appropriately
|
||||
defined. It contains 2 functions:
|
||||
<orderedlist>
|
||||
<listitem><para>
|
||||
init_this_scsi_driver() called during builtin and module driver
|
||||
initialization: invokes mid level's scsi_register_host()
|
||||
</para></listitem>
|
||||
<listitem><para>
|
||||
exit_this_scsi_driver() called during closedown: invokes
|
||||
mid level's scsi_unregister_host()
|
||||
</para></listitem>
|
||||
</orderedlist>
|
||||
</para>
|
||||
<para>
|
||||
When a new, lower level driver is being added to Linux, the following
|
||||
files (all found in the drivers/scsi directory) will need some attention:
|
||||
Makefile, Config.help and Config.in . It is probably best to look at what
|
||||
an existing lower level driver does in this regard.
|
||||
</para>
|
||||
</chapter>
|
||||
|
||||
<chapter id="intfunctions">
|
||||
<title>Interface Functions</title>
|
||||
!EDocumentation/scsi/scsi_mid_low_api.txt
|
||||
</chapter>
|
||||
|
||||
<chapter id="locks">
|
||||
<title>Locks</title>
|
||||
<para>
|
||||
Each Scsi_Host instance has a spin_lock called Scsi_Host::default_lock
|
||||
which is initialized in scsi_register() [found in hosts.c]. Within the
|
||||
same function the Scsi_Host::host_lock pointer is initialized to point
|
||||
at default_lock with the scsi_assign_lock() function. Thereafter
|
||||
lock and unlock operations performed by the mid level use the
|
||||
Scsi_Host::host_lock pointer.
|
||||
</para>
|
||||
<para>
|
||||
Lower level drivers can override the use of Scsi_Host::default_lock by
|
||||
using scsi_assign_lock(). The earliest opportunity to do this would
|
||||
be in the detect() function after it has invoked scsi_register(). It
|
||||
could be replaced by a coarser grain lock (e.g. per driver) or a
|
||||
lock of equal granularity (i.e. per host). Using finer grain locks
|
||||
(e.g. per scsi device) may be possible by juggling locks in
|
||||
queuecommand().
|
||||
</para>
|
||||
</chapter>
|
||||
|
||||
<chapter id="changes">
|
||||
<title>Changes since lk 2.4 series</title>
|
||||
<para>
|
||||
io_request_lock has been replaced by several finer grained locks. The lock
|
||||
relevant to lower level drivers is Scsi_Host::host_lock and there is one
|
||||
per scsi host.
|
||||
</para>
|
||||
<para>
|
||||
The older error handling mechanism has been removed. This means the
|
||||
lower level interface functions abort() and reset() have been removed.
|
||||
</para>
|
||||
<para>
|
||||
In the 2.4 series the scsi subsystem configuration descriptions were
|
||||
aggregated with the configuration descriptions from all other Linux
|
||||
subsystems in the Documentation/Configure.help file. In the 2.5 series,
|
||||
the scsi subsystem now has its own (much smaller) drivers/scsi/Config.help
|
||||
file.
|
||||
</para>
|
||||
</chapter>
|
||||
|
||||
<chapter id="credits">
|
||||
<title>Credits</title>
|
||||
<para>
|
||||
The following people have contributed to this document:
|
||||
<orderedlist>
|
||||
<listitem><para>
|
||||
Mike Anderson <email>andmike@us.ibm.com</email>
|
||||
</para></listitem>
|
||||
<listitem><para>
|
||||
James Bottomley <email>James.Bottomley@steeleye.com</email>
|
||||
</para></listitem>
|
||||
<listitem><para>
|
||||
Patrick Mansfield <email>patmans@us.ibm.com</email>
|
||||
</para></listitem>
|
||||
</orderedlist>
|
||||
</para>
|
||||
</chapter>
|
||||
|
||||
</book>
|
@ -271,7 +271,7 @@ patch, which certifies that you wrote it or otherwise have the right to
|
||||
pass it on as a open-source patch. The rules are pretty simple: if you
|
||||
can certify the below:
|
||||
|
||||
Developer's Certificate of Origin 1.0
|
||||
Developer's Certificate of Origin 1.1
|
||||
|
||||
By making a contribution to this project, I certify that:
|
||||
|
||||
@ -291,6 +291,12 @@ can certify the below:
|
||||
person who certified (a), (b) or (c) and I have not modified
|
||||
it.
|
||||
|
||||
(d) I understand and agree that this project and the contribution
|
||||
are public and that a record of the contribution (including all
|
||||
personal information I submit with it, including my sign-off) is
|
||||
maintained indefinitely and may be redistributed consistent with
|
||||
this project or the open source license(s) involved.
|
||||
|
||||
then you just add a line saying
|
||||
|
||||
Signed-off-by: Random J Developer <random@developer.org>
|
||||
|
128
Documentation/cpu-freq/cpufreq-stats.txt
Normal file
128
Documentation/cpu-freq/cpufreq-stats.txt
Normal file
@ -0,0 +1,128 @@
|
||||
|
||||
CPU frequency and voltage scaling statictics in the Linux(TM) kernel
|
||||
|
||||
|
||||
L i n u x c p u f r e q - s t a t s d r i v e r
|
||||
|
||||
- information for users -
|
||||
|
||||
|
||||
Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
|
||||
|
||||
Contents
|
||||
1. Introduction
|
||||
2. Statistics Provided (with example)
|
||||
3. Configuring cpufreq-stats
|
||||
|
||||
|
||||
1. Introduction
|
||||
|
||||
cpufreq-stats is a driver that provices CPU frequency statistics for each CPU.
|
||||
This statistics is provided in /sysfs as a bunch of read_only interfaces. This
|
||||
interface (when configured) will appear in a seperate directory under cpufreq
|
||||
in /sysfs (<sysfs root>/devices/system/cpu/cpuX/cpufreq/stats/) for each CPU.
|
||||
Various statistics will form read_only files under this directory.
|
||||
|
||||
This driver is designed to be independent of any particular cpufreq_driver
|
||||
that may be running on your CPU. So, it will work with any cpufreq_driver.
|
||||
|
||||
|
||||
2. Statistics Provided (with example)
|
||||
|
||||
cpufreq stats provides following statistics (explained in detail below).
|
||||
- time_in_state
|
||||
- total_trans
|
||||
- trans_table
|
||||
|
||||
All the statistics will be from the time the stats driver has been inserted
|
||||
to the time when a read of a particular statistic is done. Obviously, stats
|
||||
driver will not have any information about the the frequcny transitions before
|
||||
the stats driver insertion.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
<mysystem>:/sys/devices/system/cpu/cpu0/cpufreq/stats # ls -l
|
||||
total 0
|
||||
drwxr-xr-x 2 root root 0 May 14 16:06 .
|
||||
drwxr-xr-x 3 root root 0 May 14 15:58 ..
|
||||
-r--r--r-- 1 root root 4096 May 14 16:06 time_in_state
|
||||
-r--r--r-- 1 root root 4096 May 14 16:06 total_trans
|
||||
-r--r--r-- 1 root root 4096 May 14 16:06 trans_table
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
- time_in_state
|
||||
This gives the amount of time spent in each of the frequencies supported by
|
||||
this CPU. The cat output will have "<frequency> <time>" pair in each line, which
|
||||
will mean this CPU spent <time> usertime units of time at <frequency>. Output
|
||||
will have one line for each of the supported freuencies. usertime units here
|
||||
is 10mS (similar to other time exported in /proc).
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
<mysystem>:/sys/devices/system/cpu/cpu0/cpufreq/stats # cat time_in_state
|
||||
3600000 2089
|
||||
3400000 136
|
||||
3200000 34
|
||||
3000000 67
|
||||
2800000 172488
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
||||
- total_trans
|
||||
This gives the total number of frequency transitions on this CPU. The cat
|
||||
output will have a single count which is the total number of frequency
|
||||
transitions.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
<mysystem>:/sys/devices/system/cpu/cpu0/cpufreq/stats # cat total_trans
|
||||
20
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
- trans_table
|
||||
This will give a fine grained information about all the CPU frequency
|
||||
transitions. The cat output here is a two dimensional matrix, where an entry
|
||||
<i,j> (row i, column j) represents the count of number of transitions from
|
||||
Freq_i to Freq_j. Freq_i is in descending order with increasing rows and
|
||||
Freq_j is in descending order with increasing columns. The output here also
|
||||
contains the actual freq values for each row and column for better readability.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
<mysystem>:/sys/devices/system/cpu/cpu0/cpufreq/stats # cat trans_table
|
||||
From : To
|
||||
: 3600000 3400000 3200000 3000000 2800000
|
||||
3600000: 0 5 0 0 0
|
||||
3400000: 4 0 2 0 0
|
||||
3200000: 0 1 0 2 0
|
||||
3000000: 0 0 1 0 3
|
||||
2800000: 0 0 0 2 0
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
||||
3. Configuring cpufreq-stats
|
||||
|
||||
To configure cpufreq-stats in your kernel
|
||||
Config Main Menu
|
||||
Power management options (ACPI, APM) --->
|
||||
CPU Frequency scaling --->
|
||||
[*] CPU Frequency scaling
|
||||
<*> CPU frequency translation statistics
|
||||
[*] CPU frequency translation statistics details
|
||||
|
||||
|
||||
"CPU Frequency scaling" (CONFIG_CPU_FREQ) should be enabled to configure
|
||||
cpufreq-stats.
|
||||
|
||||
"CPU frequency translation statistics" (CONFIG_CPU_FREQ_STAT) provides the
|
||||
basic statistics which includes time_in_state and total_trans.
|
||||
|
||||
"CPU frequency translation statistics details" (CONFIG_CPU_FREQ_STAT_DETAILS)
|
||||
provides fine grained cpufreq stats by trans_table. The reason for having a
|
||||
seperate config option for trans_table is:
|
||||
- trans_table goes against the traditional /sysfs rule of one value per
|
||||
interface. It provides a whole bunch of value in a 2 dimensional matrix
|
||||
form.
|
||||
|
||||
Once these two options are enabled and your CPU supports cpufrequency, you
|
||||
will be able to see the CPU frequency statistics in /sysfs.
|
||||
|
||||
|
||||
|
||||
|
@ -76,6 +76,14 @@ driver_data: Driver-specific data.
|
||||
|
||||
platform_data: Platform data specific to the device.
|
||||
|
||||
Example: for devices on custom boards, as typical of embedded
|
||||
and SOC based hardware, Linux often uses platform_data to point
|
||||
to board-specific structures describing devices and how they
|
||||
are wired. That can include what ports are available, chip
|
||||
variants, which GPIO pins act in what additional roles, and so
|
||||
on. This shrinks the "Board Support Packages" (BSPs) and
|
||||
minimizes board-specific #ifdefs in drivers.
|
||||
|
||||
current_state: Current power state of the device.
|
||||
|
||||
saved_state: Pointer to saved state of the device. This is usable by
|
||||
|
@ -5,21 +5,17 @@ struct device_driver {
|
||||
char * name;
|
||||
struct bus_type * bus;
|
||||
|
||||
rwlock_t lock;
|
||||
atomic_t refcount;
|
||||
|
||||
list_t bus_list;
|
||||
struct completion unloaded;
|
||||
struct kobject kobj;
|
||||
list_t devices;
|
||||
|
||||
struct driver_dir_entry dir;
|
||||
struct module *owner;
|
||||
|
||||
int (*probe) (struct device * dev);
|
||||
int (*remove) (struct device * dev);
|
||||
|
||||
int (*suspend) (struct device * dev, pm_message_t state, u32 level);
|
||||
int (*resume) (struct device * dev, u32 level);
|
||||
|
||||
void (*release) (struct device_driver * drv);
|
||||
};
|
||||
|
||||
|
||||
@ -51,7 +47,6 @@ being converted completely to the new model.
|
||||
static struct device_driver eepro100_driver = {
|
||||
.name = "eepro100",
|
||||
.bus = &pci_bus_type,
|
||||
.devclass = ðernet_devclass, /* when it's implemented */
|
||||
|
||||
.probe = eepro100_probe,
|
||||
.remove = eepro100_remove,
|
||||
@ -85,7 +80,6 @@ static struct pci_driver eepro100_driver = {
|
||||
.driver = {
|
||||
.name = "eepro100",
|
||||
.bus = &pci_bus_type,
|
||||
.devclass = ðernet_devclass, /* when it's implemented */
|
||||
.probe = eepro100_probe,
|
||||
.remove = eepro100_remove,
|
||||
.suspend = eepro100_suspend,
|
||||
@ -166,27 +160,32 @@ Callbacks
|
||||
|
||||
int (*probe) (struct device * dev);
|
||||
|
||||
probe is called to verify the existence of a certain type of
|
||||
hardware. This is called during the driver binding process, after the
|
||||
bus has verified that the device ID of a device matches one of the
|
||||
device IDs supported by the driver.
|
||||
The probe() entry is called in task context, with the bus's rwsem locked
|
||||
and the driver partially bound to the device. Drivers commonly use
|
||||
container_of() to convert "dev" to a bus-specific type, both in probe()
|
||||
and other routines. That type often provides device resource data, such
|
||||
as pci_dev.resource[] or platform_device.resources, which is used in
|
||||
addition to dev->platform_data to initialize the driver.
|
||||
|
||||
This callback only verifies that there actually is supported hardware
|
||||
present. It may allocate a driver-specific structure, but it should
|
||||
not do any initialization of the hardware itself. The device-specific
|
||||
structure may be stored in the device's driver_data field.
|
||||
This callback holds the driver-specific logic to bind the driver to a
|
||||
given device. That includes verifying that the device is present, that
|
||||
it's a version the driver can handle, that driver data structures can
|
||||
be allocated and initialized, and that any hardware can be initialized.
|
||||
Drivers often store a pointer to their state with dev_set_drvdata().
|
||||
When the driver has successfully bound itself to that device, then probe()
|
||||
returns zero and the driver model code will finish its part of binding
|
||||
the driver to that device.
|
||||
|
||||
int (*init) (struct device * dev);
|
||||
|
||||
init is called during the binding stage. It is called after probe has
|
||||
successfully returned and the device has been registered with its
|
||||
class. It is responsible for initializing the hardware.
|
||||
A driver's probe() may return a negative errno value to indicate that
|
||||
the driver did not bind to this device, in which case it should have
|
||||
released all reasources it allocated.
|
||||
|
||||
int (*remove) (struct device * dev);
|
||||
|
||||
remove is called to dissociate a driver with a device. This may be
|
||||
remove is called to unbind a driver from a device. This may be
|
||||
called if a device is physically removed from the system, if the
|
||||
driver module is being unloaded, or during a reboot sequence.
|
||||
driver module is being unloaded, during a reboot sequence, or
|
||||
in other cases.
|
||||
|
||||
It is up to the driver to determine if the device is present or
|
||||
not. It should free any resources allocated specifically for the
|
||||
|
@ -214,7 +214,7 @@ Other notes:
|
||||
|
||||
A very simple (and naive) implementation of a device attribute is:
|
||||
|
||||
static ssize_t show_name(struct device * dev, char * buf)
|
||||
static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return sprintf(buf,"%s\n",dev->name);
|
||||
}
|
||||
|
@ -1,21 +1,21 @@
|
||||
Generic HDLC layer
|
||||
Krzysztof Halasa <khc@pm.waw.pl>
|
||||
January, 2003
|
||||
|
||||
|
||||
Generic HDLC layer currently supports:
|
||||
- Frame Relay (ANSI, CCITT and no LMI), with ARP support (no InARP).
|
||||
Normal (routed) and Ethernet-bridged (Ethernet device emulation)
|
||||
interfaces can share a single PVC.
|
||||
- raw HDLC - either IP (IPv4) interface or Ethernet device emulation.
|
||||
- Cisco HDLC,
|
||||
- PPP (uses syncppp.c),
|
||||
- X.25 (uses X.25 routines).
|
||||
1. Frame Relay (ANSI, CCITT, Cisco and no LMI).
|
||||
- Normal (routed) and Ethernet-bridged (Ethernet device emulation)
|
||||
interfaces can share a single PVC.
|
||||
- ARP support (no InARP support in the kernel - there is an
|
||||
experimental InARP user-space daemon available on:
|
||||
http://www.kernel.org/pub/linux/utils/net/hdlc/).
|
||||
2. raw HDLC - either IP (IPv4) interface or Ethernet device emulation.
|
||||
3. Cisco HDLC.
|
||||
4. PPP (uses syncppp.c).
|
||||
5. X.25 (uses X.25 routines).
|
||||
|
||||
There are hardware drivers for the following cards:
|
||||
- C101 by Moxa Technologies Co., Ltd.
|
||||
- RISCom/N2 by SDL Communications Inc.
|
||||
- and others, some not in the official kernel.
|
||||
Generic HDLC is a protocol driver only - it needs a low-level driver
|
||||
for your particular hardware.
|
||||
|
||||
Ethernet device emulation (using HDLC or Frame-Relay PVC) is compatible
|
||||
with IEEE 802.1Q (VLANs) and 802.1D (Ethernet bridging).
|
||||
@ -24,7 +24,7 @@ with IEEE 802.1Q (VLANs) and 802.1D (Ethernet bridging).
|
||||
Make sure the hdlc.o and the hardware driver are loaded. It should
|
||||
create a number of "hdlc" (hdlc0 etc) network devices, one for each
|
||||
WAN port. You'll need the "sethdlc" utility, get it from:
|
||||
http://hq.pm.waw.pl/hdlc/
|
||||
http://www.kernel.org/pub/linux/utils/net/hdlc/
|
||||
|
||||
Compile sethdlc.c utility:
|
||||
gcc -O2 -Wall -o sethdlc sethdlc.c
|
||||
@ -52,12 +52,12 @@ Setting interface:
|
||||
* v35 | rs232 | x21 | t1 | e1 - sets physical interface for a given port
|
||||
if the card has software-selectable interfaces
|
||||
loopback - activate hardware loopback (for testing only)
|
||||
* clock ext - external clock (uses DTE RX and TX clock)
|
||||
* clock int - internal clock (provides clock signal on DCE clock output)
|
||||
* clock txint - TX internal, RX external (provides TX clock on DCE output)
|
||||
* clock txfromrx - TX clock derived from RX clock (TX clock on DCE output)
|
||||
* rate - sets clock rate in bps (not required for external clock or
|
||||
for txfromrx)
|
||||
* clock ext - both RX clock and TX clock external
|
||||
* clock int - both RX clock and TX clock internal
|
||||
* clock txint - RX clock external, TX clock internal
|
||||
* clock txfromrx - RX clock external, TX clock derived from RX clock
|
||||
* rate - sets clock rate in bps (for "int" or "txint" clock only)
|
||||
|
||||
|
||||
Setting protocol:
|
||||
|
||||
@ -79,7 +79,7 @@ Setting protocol:
|
||||
* x25 - sets X.25 mode
|
||||
|
||||
* fr - Frame Relay mode
|
||||
lmi ansi / ccitt / none - LMI (link management) type
|
||||
lmi ansi / ccitt / cisco / none - LMI (link management) type
|
||||
dce - Frame Relay DCE (network) side LMI instead of default DTE (user).
|
||||
It has nothing to do with clocks!
|
||||
t391 - link integrity verification polling timer (in seconds) - user
|
||||
@ -119,13 +119,14 @@ or
|
||||
|
||||
|
||||
|
||||
If you have a problem with N2 or C101 card, you can issue the "private"
|
||||
command to see port's packet descriptor rings (in kernel logs):
|
||||
If you have a problem with N2, C101 or PLX200SYN card, you can issue the
|
||||
"private" command to see port's packet descriptor rings (in kernel logs):
|
||||
|
||||
sethdlc hdlc0 private
|
||||
|
||||
The hardware driver has to be build with CONFIG_HDLC_DEBUG_RINGS.
|
||||
The hardware driver has to be build with #define DEBUG_RINGS.
|
||||
Attaching this info to bug reports would be helpful. Anyway, let me know
|
||||
if you have problems using this.
|
||||
|
||||
For patches and other info look at http://hq.pm.waw.pl/hdlc/
|
||||
For patches and other info look at:
|
||||
<http://www.kernel.org/pub/linux/utils/net/hdlc/>.
|
||||
|
@ -47,7 +47,6 @@ ni52 <------------------ Buggy ------------------>
|
||||
ni65 YES YES YES Software(#)
|
||||
seeq NO NO NO N/A
|
||||
sgiseek <------------------ Buggy ------------------>
|
||||
sk_g16 NO NO YES N/A
|
||||
smc-ultra YES YES YES Hardware
|
||||
sunlance YES YES YES Hardware
|
||||
tulip YES YES YES Hardware
|
||||
|
@ -284,9 +284,6 @@ ppp.c:
|
||||
seeq8005.c: *Not modularized*
|
||||
(Probes ports: 0x300, 0x320, 0x340, 0x360)
|
||||
|
||||
sk_g16.c: *Not modularized*
|
||||
(Probes ports: 0x100, 0x180, 0x208, 0x220m 0x288, 0x320, 0x328, 0x390)
|
||||
|
||||
skeleton.c: *Skeleton*
|
||||
|
||||
slhc.c:
|
||||
|
@ -12,7 +12,7 @@ Don is no longer the prime maintainer of this version of the driver.
|
||||
Please report problems to one or more of:
|
||||
|
||||
Andrew Morton <andrewm@uow.edu.au>
|
||||
Netdev mailing list <netdev@oss.sgi.com>
|
||||
Netdev mailing list <netdev@vger.kernel.org>
|
||||
Linux kernel mailing list <linux-kernel@vger.kernel.org>
|
||||
|
||||
Please note the 'Reporting and Diagnosing Problems' section at the end
|
||||
|
@ -1,3 +1,69 @@
|
||||
Release Date : Mon Mar 07 12:27:22 EST 2005 - Seokmann Ju <sju@lsil.com>
|
||||
Current Version : 2.20.4.6 (scsi module), 2.20.2.6 (cmm module)
|
||||
Older Version : 2.20.4.5 (scsi module), 2.20.2.5 (cmm module)
|
||||
|
||||
1. Added IOCTL backward compatibility.
|
||||
Convert megaraid_mm driver to new compat_ioctl entry points.
|
||||
I don't have easy access to hardware, so only compile tested.
|
||||
- Signed-off-by:Andi Kleen <ak@muc.de>
|
||||
|
||||
2. megaraid_mbox fix: wrong order of arguments in memset()
|
||||
That, BTW, shows why cross-builds are useful-the only indication of
|
||||
problem had been a new warning showing up in sparse output on alpha
|
||||
build (number of exceeding 256 got truncated).
|
||||
- Signed-off-by: Al Viro
|
||||
<viro@parcelfarce.linux.theplanet.co.uk>
|
||||
|
||||
3. Convert pci_module_init to pci_register_driver
|
||||
Convert from pci_module_init to pci_register_driver
|
||||
(from:http://kerneljanitors.org/TODO)
|
||||
- Signed-off-by: Domen Puncer <domen@coderock.org>
|
||||
|
||||
4. Use the pre defined DMA mask constants from dma-mapping.h
|
||||
Use the DMA_{64,32}BIT_MASK constants from dma-mapping.h when calling
|
||||
pci_set_dma_mask() or pci_set_consistend_dma_mask(). See
|
||||
http://marc.theaimsgroup.com/?t=108001993000001&r=1&w=2 for more
|
||||
details.
|
||||
Signed-off-by: Tobias Klauser <tklauser@nuerscht.ch>
|
||||
Signed-off-by: Domen Puncer <domen@coderock.org>
|
||||
|
||||
5. Remove SSID checking for Dobson, Lindsay, and Verde based products.
|
||||
Checking the SSVID/SSID for controllers which have Dobson, Lindsay,
|
||||
and Verde is unnecessary because device ID has been assigned by LSI
|
||||
and it is unique value. So, all controllers with these IOPs have to be
|
||||
supported by the driver regardless SSVID/SSID.
|
||||
|
||||
6. Date Thu, 27 Jan 2005 04:31:09 +0100
|
||||
From Herbert Poetzl <>
|
||||
Subject RFC: assert_spin_locked() for 2.6
|
||||
|
||||
Greetings!
|
||||
|
||||
overcautious programming will kill your kernel ;)
|
||||
ever thought about checking a spin_lock or even
|
||||
asserting that it must be held (maybe just for
|
||||
spinlock debugging?) ...
|
||||
|
||||
there are several checks present in the kernel
|
||||
where somebody does a variation on the following:
|
||||
|
||||
BUG_ON(!spin_is_locked(&some_lock));
|
||||
|
||||
so what's wrong about that? nothing, unless you
|
||||
compile the code with CONFIG_DEBUG_SPINLOCK but
|
||||
without CONFIG_SMP ... in which case the BUG()
|
||||
will kill your kernel ...
|
||||
|
||||
maybe it's not advised to make such assertions,
|
||||
but here is a solution which works for me ...
|
||||
(compile tested for sh, x86_64 and x86, boot/run
|
||||
tested for x86 only)
|
||||
|
||||
best,
|
||||
Herbert
|
||||
|
||||
- Herbert Poetzl <herbert@13thfloor.at>, Thu, 27 Jan 2005
|
||||
|
||||
Release Date : Thu Feb 03 12:27:22 EST 2005 - Seokmann Ju <sju@lsil.com>
|
||||
Current Version : 2.20.4.5 (scsi module), 2.20.2.5 (cmm module)
|
||||
Older Version : 2.20.4.4 (scsi module), 2.20.2.4 (cmm module)
|
||||
|
180
Documentation/scsi/scsi-changer.txt
Normal file
180
Documentation/scsi/scsi-changer.txt
Normal file
@ -0,0 +1,180 @@
|
||||
|
||||
README for the SCSI media changer driver
|
||||
========================================
|
||||
|
||||
This is a driver for SCSI Medium Changer devices, which are listed
|
||||
with "Type: Medium Changer" in /proc/scsi/scsi.
|
||||
|
||||
This is for *real* Jukeboxes. It is *not* supported to work with
|
||||
common small CD-ROM changers, neither one-lun-per-slot SCSI changers
|
||||
nor IDE drives.
|
||||
|
||||
Userland tools available from here:
|
||||
http://linux.bytesex.org/misc/changer.html
|
||||
|
||||
|
||||
General Information
|
||||
-------------------
|
||||
|
||||
First some words about how changers work: A changer has 2 (possibly
|
||||
more) SCSI ID's. One for the changer device which controls the robot,
|
||||
and one for the device which actually reads and writes the data. The
|
||||
later may be anything, a MOD, a CD-ROM, a tape or whatever. For the
|
||||
changer device this is a "don't care", he *only* shuffles around the
|
||||
media, nothing else.
|
||||
|
||||
|
||||
The SCSI changer model is complex, compared to - for example - IDE-CD
|
||||
changers. But it allows to handle nearly all possible cases. It knows
|
||||
4 different types of changer elements:
|
||||
|
||||
media transport - this one shuffles around the media, i.e. the
|
||||
transport arm. Also known as "picker".
|
||||
storage - a slot which can hold a media.
|
||||
import/export - the same as above, but is accessable from outside,
|
||||
i.e. there the operator (you !) can use this to
|
||||
fill in and remove media from the changer.
|
||||
Sometimes named "mailslot".
|
||||
data transfer - this is the device which reads/writes, i.e. the
|
||||
CD-ROM / Tape / whatever drive.
|
||||
|
||||
None of these is limited to one: A huge Jukebox could have slots for
|
||||
123 CD-ROM's, 5 CD-ROM readers (and therefore 6 SCSI ID's: the changer
|
||||
and each CD-ROM) and 2 transport arms. No problem to handle.
|
||||
|
||||
|
||||
How it is implemented
|
||||
---------------------
|
||||
|
||||
I implemented the driver as character device driver with a NetBSD-like
|
||||
ioctl interface. Just grabbed NetBSD's header file and one of the
|
||||
other linux SCSI device drivers as starting point. The interface
|
||||
should be source code compatible with NetBSD. So if there is any
|
||||
software (anybody knows ???) which supports a BSDish changer driver,
|
||||
it should work with this driver too.
|
||||
|
||||
Over time a few more ioctls where added, volume tag support for example
|
||||
wasn't covered by the NetBSD ioctl API.
|
||||
|
||||
|
||||
Current State
|
||||
-------------
|
||||
|
||||
Support for more than one transport arm is not implemented yet (and
|
||||
nobody asked for it so far...).
|
||||
|
||||
I test and use the driver myself with a 35 slot cdrom jukebox from
|
||||
Grundig. I got some reports telling it works ok with tape autoloaders
|
||||
(Exabyte, HP and DEC). Some People use this driver with amanda. It
|
||||
works fine with small (11 slots) and a huge (4 MOs, 88 slots)
|
||||
magneto-optical Jukebox. Probably with lots of other changers too, most
|
||||
(but not all :-) people mail me only if it does *not* work...
|
||||
|
||||
I don't have any device lists, neither black-list nor white-list. Thus
|
||||
it is quite useless to ask me whenever a specific device is supported or
|
||||
not. In theory every changer device which supports the SCSI-2 media
|
||||
changer command set should work out-of-the-box with this driver. If it
|
||||
doesn't, it is a bug. Either within the driver or within the firmware
|
||||
of the changer device.
|
||||
|
||||
|
||||
Using it
|
||||
--------
|
||||
|
||||
This is a character device with major number is 86, so use
|
||||
"mknod /dev/sch0 c 86 0" to create the special file for the driver.
|
||||
|
||||
If the module finds the changer, it prints some messages about the
|
||||
device [ try "dmesg" if you don't see anything ] and should show up in
|
||||
/proc/devices. If not.... some changers use ID ? / LUN 0 for the
|
||||
device and ID ? / LUN 1 for the robot mechanism. But Linux does *not*
|
||||
look for LUN's other than 0 as default, becauce there are to many
|
||||
broken devices. So you can try:
|
||||
|
||||
1) echo "scsi add-single-device 0 0 ID 1" > /proc/scsi/scsi
|
||||
(replace ID with the SCSI-ID of the device)
|
||||
2) boot the kernel with "max_scsi_luns=1" on the command line
|
||||
(append="max_scsi_luns=1" in lilo.conf should do the trick)
|
||||
|
||||
|
||||
Trouble?
|
||||
--------
|
||||
|
||||
If you insmod the driver with "insmod debug=1", it will be verbose and
|
||||
prints a lot of stuff to the syslog. Compiling the kernel with
|
||||
CONFIG_SCSI_CONSTANTS=y improves the quality of the error messages alot
|
||||
because the kernel will translate the error codes into human-readable
|
||||
strings then.
|
||||
|
||||
You can display these messages with the dmesg command (or check the
|
||||
logfiles). If you email me some question becauce of a problem with the
|
||||
driver, please include these messages.
|
||||
|
||||
|
||||
Insmod options
|
||||
--------------
|
||||
|
||||
debug=0/1
|
||||
Enable debug messages (see above, default: 0).
|
||||
|
||||
verbose=0/1
|
||||
Be verbose (default: 1).
|
||||
|
||||
init=0/1
|
||||
Send INITIALIZE ELEMENT STATUS command to the changer
|
||||
at insmod time (default: 1).
|
||||
|
||||
timeout_init=<seconds>
|
||||
timeout for the INITIALIZE ELEMENT STATUS command
|
||||
(default: 3600).
|
||||
|
||||
timeout_move=<seconds>
|
||||
timeout for all other commands (default: 120).
|
||||
|
||||
dt_id=<id1>,<id2>,...
|
||||
dt_lun=<lun1>,<lun2>,...
|
||||
These two allow to specify the SCSI ID and LUN for the data
|
||||
transfer elements. You likely don't need this as the jukebox
|
||||
should provide this information. But some devices don't ...
|
||||
|
||||
vendor_firsts=
|
||||
vendor_counts=
|
||||
vendor_labels=
|
||||
These insmod options can be used to tell the driver that there
|
||||
are some vendor-specific element types. Grundig for example
|
||||
does this. Some jukeboxes have a printer to label fresh burned
|
||||
CDs, which is addressed as element 0xc000 (type 5). To tell the
|
||||
driver about this vendor-specific element, use this:
|
||||
$ insmod ch \
|
||||
vendor_firsts=0xc000 \
|
||||
vendor_counts=1 \
|
||||
vendor_labels=printer
|
||||
All three insmod options accept up to four comma-separated
|
||||
values, this way you can configure the element types 5-8.
|
||||
You likely need the SCSI specs for the device in question to
|
||||
find the correct values as they are not covered by the SCSI-2
|
||||
standard.
|
||||
|
||||
|
||||
Credits
|
||||
-------
|
||||
|
||||
I wrote this driver using the famous mailing-patches-around-the-world
|
||||
method. With (more or less) help from:
|
||||
|
||||
Daniel Moehwald <moehwald@hdg.de>
|
||||
Dane Jasper <dane@sonic.net>
|
||||
R. Scott Bailey <sbailey@dsddi.eds.com>
|
||||
Jonathan Corbet <corbet@lwn.net>
|
||||
|
||||
Special thanks go to
|
||||
Martin Kuehne <martin.kuehne@bnbt.de>
|
||||
for a old, second-hand (but full functional) cdrom jukebox which I use
|
||||
to develop/test driver and tools now.
|
||||
|
||||
Have fun,
|
||||
|
||||
Gerd
|
||||
|
||||
--
|
||||
Gerd Knorr <kraxel@bytesex.org>
|
@ -936,8 +936,7 @@ Details:
|
||||
*
|
||||
* Returns SUCCESS if command aborted else FAILED
|
||||
*
|
||||
* Locks: struct Scsi_Host::host_lock held (with irqsave) on entry
|
||||
* and assumed to be held on return.
|
||||
* Locks: None held
|
||||
*
|
||||
* Calling context: kernel thread
|
||||
*
|
||||
@ -955,8 +954,7 @@ Details:
|
||||
*
|
||||
* Returns SUCCESS if command aborted else FAILED
|
||||
*
|
||||
* Locks: struct Scsi_Host::host_lock held (with irqsave) on entry
|
||||
* and assumed to be held on return.
|
||||
* Locks: None held
|
||||
*
|
||||
* Calling context: kernel thread
|
||||
*
|
||||
@ -974,8 +972,7 @@ Details:
|
||||
*
|
||||
* Returns SUCCESS if command aborted else FAILED
|
||||
*
|
||||
* Locks: struct Scsi_Host::host_lock held (with irqsave) on entry
|
||||
* and assumed to be held on return.
|
||||
* Locks: None held
|
||||
*
|
||||
* Calling context: kernel thread
|
||||
*
|
||||
@ -993,8 +990,7 @@ Details:
|
||||
*
|
||||
* Returns SUCCESS if command aborted else FAILED
|
||||
*
|
||||
* Locks: struct Scsi_Host::host_lock held (with irqsave) on entry
|
||||
* and assumed to be held on return.
|
||||
* Locks: None held
|
||||
*
|
||||
* Calling context: kernel thread
|
||||
*
|
||||
|
63
MAINTAINERS
63
MAINTAINERS
@ -73,7 +73,7 @@ S: Status, one of the following:
|
||||
3C359 NETWORK DRIVER
|
||||
P: Mike Phillips
|
||||
M: mikep@linuxtr.net
|
||||
L: netdev@oss.sgi.com
|
||||
L: netdev@vger.kernel.org
|
||||
L: linux-tr@linuxtr.net
|
||||
W: http://www.linuxtr.net
|
||||
S: Maintained
|
||||
@ -81,13 +81,13 @@ S: Maintained
|
||||
3C505 NETWORK DRIVER
|
||||
P: Philip Blundell
|
||||
M: philb@gnu.org
|
||||
L: netdev@oss.sgi.com
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
|
||||
3CR990 NETWORK DRIVER
|
||||
P: David Dillow
|
||||
M: dave@thedillows.org
|
||||
L: netdev@oss.sgi.com
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
|
||||
3W-XXXX ATA-RAID CONTROLLER DRIVER
|
||||
@ -130,7 +130,7 @@ S: Maintained
|
||||
8169 10/100/1000 GIGABIT ETHERNET DRIVER
|
||||
P: Francois Romieu
|
||||
M: romieu@fr.zoreil.com
|
||||
L: netdev@oss.sgi.com
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
|
||||
8250/16?50 (AND CLONE UARTS) SERIAL DRIVER
|
||||
@ -143,7 +143,7 @@ S: Maintained
|
||||
8390 NETWORK DRIVERS [WD80x3/SMC-ELITE, SMC-ULTRA, NE2000, 3C503, etc.]
|
||||
P: Paul Gortmaker
|
||||
M: p_gortmaker@yahoo.com
|
||||
L: netdev@oss.sgi.com
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
|
||||
A2232 SERIAL BOARD DRIVER
|
||||
@ -239,6 +239,12 @@ L: linux-usb-devel@lists.sourceforge.net
|
||||
W: http://www.linux-usb.org/SpeedTouch/
|
||||
S: Maintained
|
||||
|
||||
ALI1563 I2C DRIVER
|
||||
P: Rudolf Marek
|
||||
M: r.marek@sh.cvut.cz
|
||||
L: sensors@stimpy.netroedge.com
|
||||
S: Maintained
|
||||
|
||||
ALPHA PORT
|
||||
P: Richard Henderson
|
||||
M: rth@twiddle.net
|
||||
@ -326,7 +332,7 @@ S: Maintained
|
||||
|
||||
ARPD SUPPORT
|
||||
P: Jonathan Layes
|
||||
L: netdev@oss.sgi.com
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
|
||||
ASUS ACPI EXTRAS DRIVER
|
||||
@ -700,7 +706,7 @@ S: Orphaned
|
||||
|
||||
DIGI RIGHTSWITCH NETWORK DRIVER
|
||||
P: Rick Richardson
|
||||
L: netdev@oss.sgi.com
|
||||
L: netdev@vger.kernel.org
|
||||
W: http://www.digi.com
|
||||
S: Orphaned
|
||||
|
||||
@ -730,6 +736,11 @@ M: tori@unhappy.mine.nu
|
||||
L: linux-kernel@vger.kernel.org
|
||||
S: Maintained
|
||||
|
||||
DOCBOOK FOR DOCUMENTATION
|
||||
P: Martin Waitz
|
||||
M: tali@admingilde.org
|
||||
S: Maintained
|
||||
|
||||
DOUBLETALK DRIVER
|
||||
P: James R. Van Zandt
|
||||
M: jrv@vanzandt.mv.com
|
||||
@ -806,7 +817,7 @@ S: Maintained
|
||||
ETHEREXPRESS-16 NETWORK DRIVER
|
||||
P: Philip Blundell
|
||||
M: philb@gnu.org
|
||||
L: netdev@oss.sgi.com
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
|
||||
ETHERNET BRIDGE
|
||||
@ -869,7 +880,7 @@ S: Maintained
|
||||
FRAME RELAY DLCI/FRAD (Sangoma drivers too)
|
||||
P: Mike McLagan
|
||||
M: mike.mclagan@linux.org
|
||||
L: netdev@oss.sgi.com
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
|
||||
FREEVXFS FILESYSTEM
|
||||
@ -1023,8 +1034,8 @@ W: http://www.ia64-linux.org/
|
||||
S: Maintained
|
||||
|
||||
SN-IA64 (Itanium) SUB-PLATFORM
|
||||
P: Jesse Barnes
|
||||
M: jbarnes@sgi.com
|
||||
P: Greg Edwards
|
||||
M: edwardsg@sgi.com
|
||||
L: linux-altix@sgi.com
|
||||
L: linux-ia64@vger.kernel.org
|
||||
W: http://www.sgi.com/altix
|
||||
@ -1209,7 +1220,7 @@ S: Maintained
|
||||
IPX NETWORK LAYER
|
||||
P: Arnaldo Carvalho de Melo
|
||||
M: acme@conectiva.com.br
|
||||
L: netdev@oss.sgi.com
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
|
||||
IRDA SUBSYSTEM
|
||||
@ -1476,7 +1487,7 @@ MARVELL MV64340 ETHERNET DRIVER
|
||||
P: Manish Lachwani
|
||||
M: Manish_Lachwani@pmc-sierra.com
|
||||
L: linux-mips@linux-mips.org
|
||||
L: netdev@oss.sgi.com
|
||||
L: netdev@vger.kernel.org
|
||||
S: Supported
|
||||
|
||||
MATROX FRAMEBUFFER DRIVER
|
||||
@ -1586,13 +1597,13 @@ P: Andrew Morton
|
||||
M: akpm@osdl.org
|
||||
P: Jeff Garzik
|
||||
M: jgarzik@pobox.com
|
||||
L: netdev@oss.sgi.com
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
|
||||
NETWORKING [GENERAL]
|
||||
P: Networking Team
|
||||
M: netdev@oss.sgi.com
|
||||
L: netdev@oss.sgi.com
|
||||
M: netdev@vger.kernel.org
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
|
||||
NETWORKING [IPv4/IPv6]
|
||||
@ -1608,7 +1619,7 @@ P: Hideaki YOSHIFUJI
|
||||
M: yoshfuji@linux-ipv6.org
|
||||
P: Patrick McHardy
|
||||
M: kaber@coreworks.de
|
||||
L: netdev@oss.sgi.com
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
|
||||
IPVS
|
||||
@ -1628,7 +1639,7 @@ NI5010 NETWORK DRIVER
|
||||
P: Jan-Pascal van Best and Andreas Mohr
|
||||
M: Jan-Pascal van Best <jvbest@qv3pluto.leidenuniv.nl>
|
||||
M: Andreas Mohr <100.30936@germany.net>
|
||||
L: netdev@oss.sgi.com
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
|
||||
NINJA SCSI-3 / NINJA SCSI-32Bi (16bit/CardBus) PCMCIA SCSI HOST ADAPTER DRIVER
|
||||
@ -1670,7 +1681,7 @@ P: Peter De Shrijver
|
||||
M: p2@ace.ulyssis.student.kuleuven.ac.be
|
||||
P: Mike Phillips
|
||||
M: mikep@linuxtr.net
|
||||
L: netdev@oss.sgi.com
|
||||
L: netdev@vger.kernel.org
|
||||
L: linux-tr@linuxtr.net
|
||||
W: http://www.linuxtr.net
|
||||
S: Maintained
|
||||
@ -1777,7 +1788,7 @@ S: Unmaintained
|
||||
PCNET32 NETWORK DRIVER
|
||||
P: Thomas Bogendörfer
|
||||
M: tsbogend@alpha.franken.de
|
||||
L: netdev@oss.sgi.com
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
|
||||
PHRAM MTD DRIVER
|
||||
@ -1789,7 +1800,7 @@ S: Maintained
|
||||
POSIX CLOCKS and TIMERS
|
||||
P: George Anzinger
|
||||
M: george@mvista.com
|
||||
L: netdev@oss.sgi.com
|
||||
L: netdev@vger.kernel.org
|
||||
S: Supported
|
||||
|
||||
PNP SUPPORT
|
||||
@ -1824,7 +1835,7 @@ S: Supported
|
||||
PRISM54 WIRELESS DRIVER
|
||||
P: Prism54 Development Team
|
||||
M: prism54-private@prism54.org
|
||||
L: netdev@oss.sgi.com
|
||||
L: netdev@vger.kernel.org
|
||||
W: http://prism54.org
|
||||
S: Maintained
|
||||
|
||||
@ -2041,7 +2052,7 @@ SIS 900/7016 FAST ETHERNET DRIVER
|
||||
P: Daniele Venzano
|
||||
M: venza@brownhat.org
|
||||
W: http://www.brownhat.org/sis900.html
|
||||
L: netdev@oss.sgi.com
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
|
||||
SIS FRAMEBUFFER DRIVER
|
||||
@ -2100,7 +2111,7 @@ S: Maintained
|
||||
SONIC NETWORK DRIVER
|
||||
P: Thomas Bogendoerfer
|
||||
M: tsbogend@alpha.franken.de
|
||||
L: netdev@oss.sgi.com
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
|
||||
SONY VAIO CONTROL DEVICE DRIVER
|
||||
@ -2157,7 +2168,7 @@ S: Supported
|
||||
SPX NETWORK LAYER
|
||||
P: Jay Schulist
|
||||
M: jschlst@samba.org
|
||||
L: netdev@oss.sgi.com
|
||||
L: netdev@vger.kernel.org
|
||||
S: Supported
|
||||
|
||||
SRM (Alpha) environment access
|
||||
@ -2236,7 +2247,7 @@ S: Maintained
|
||||
TOKEN-RING NETWORK DRIVER
|
||||
P: Mike Phillips
|
||||
M: mikep@linuxtr.net
|
||||
L: netdev@oss.sgi.com
|
||||
L: netdev@vger.kernel.org
|
||||
L: linux-tr@linuxtr.net
|
||||
W: http://www.linuxtr.net
|
||||
S: Maintained
|
||||
|
2
Makefile
2
Makefile
@ -1,7 +1,7 @@
|
||||
VERSION = 2
|
||||
PATCHLEVEL = 6
|
||||
SUBLEVEL = 12
|
||||
EXTRAVERSION =-rc5
|
||||
EXTRAVERSION =
|
||||
NAME=Woozy Numbat
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
@ -67,10 +67,6 @@ config GENERIC_BUST_SPINLOCK
|
||||
config GENERIC_ISA_DMA
|
||||
bool
|
||||
|
||||
config GENERIC_IOMAP
|
||||
bool
|
||||
default y
|
||||
|
||||
config FIQ
|
||||
bool
|
||||
|
||||
@ -202,6 +198,11 @@ config ARCH_H720X
|
||||
help
|
||||
This enables support for systems based on the Hynix HMS720x
|
||||
|
||||
config ARCH_AAEC2000
|
||||
bool "Agilent AAEC-2000 based"
|
||||
help
|
||||
This enables support for systems based on the Agilent AAEC-2000
|
||||
|
||||
endchoice
|
||||
|
||||
source "arch/arm/mach-clps711x/Kconfig"
|
||||
@ -234,6 +235,8 @@ source "arch/arm/mach-h720x/Kconfig"
|
||||
|
||||
source "arch/arm/mach-versatile/Kconfig"
|
||||
|
||||
source "arch/arm/mach-aaec2000/Kconfig"
|
||||
|
||||
# Definitions to make life easier
|
||||
config ARCH_ACORN
|
||||
bool
|
||||
@ -277,7 +280,7 @@ config ISA_DMA_API
|
||||
default y
|
||||
|
||||
config PCI
|
||||
bool "PCI support" if ARCH_INTEGRATOR_AP
|
||||
bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB
|
||||
help
|
||||
Find out whether you have a PCI motherboard. PCI is the name of a
|
||||
bus system, i.e. the way the CPU talks to the other stuff inside
|
||||
@ -497,7 +500,7 @@ source "drivers/cpufreq/Kconfig"
|
||||
|
||||
config CPU_FREQ_SA1100
|
||||
bool
|
||||
depends on CPU_FREQ && (SA1100_LART || SA1100_PLEB)
|
||||
depends on CPU_FREQ && (SA1100_H3100 || SA1100_H3600 || SA1100_H3800 || SA1100_LART || SA1100_PLEB || SA1100_BADGE4 || SA1100_HACKKIT)
|
||||
default y
|
||||
|
||||
config CPU_FREQ_SA1110
|
||||
@ -689,7 +692,9 @@ source "drivers/block/Kconfig"
|
||||
|
||||
source "drivers/acorn/block/Kconfig"
|
||||
|
||||
if ARCH_CLPS7500 || ARCH_IOP3XX || ARCH_IXP4XX || ARCH_L7200 || ARCH_LH7A40X || ARCH_PXA || ARCH_RPC || ARCH_S3C2410 || ARCH_SA1100 || ARCH_SHARK || FOOTBRIDGE
|
||||
if PCMCIA || ARCH_CLPS7500 || ARCH_IOP3XX || ARCH_IXP4XX \
|
||||
|| ARCH_L7200 || ARCH_LH7A40X || ARCH_PXA || ARCH_RPC \
|
||||
|| ARCH_S3C2410 || ARCH_SA1100 || ARCH_SHARK || FOOTBRIDGE
|
||||
source "drivers/ide/Kconfig"
|
||||
endif
|
||||
|
||||
|
@ -97,6 +97,7 @@ textaddr-$(CONFIG_ARCH_FORTUNET) := 0xc0008000
|
||||
machine-$(CONFIG_ARCH_VERSATILE) := versatile
|
||||
machine-$(CONFIG_ARCH_IMX) := imx
|
||||
machine-$(CONFIG_ARCH_H720X) := h720x
|
||||
machine-$(CONFIG_ARCH_AAEC2000) := aaec2000
|
||||
|
||||
ifeq ($(CONFIG_ARCH_EBSA110),y)
|
||||
# This is what happens if you forget the IOCS16 line.
|
||||
|
@ -47,3 +47,10 @@ __XScale_start:
|
||||
orr r7, r7, #(MACH_TYPE_GTWX5715 & 0xff00)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARCH_IXP2000
|
||||
mov r1, #-1
|
||||
mov r0, #0xd6000000
|
||||
str r1, [r0, #0x14]
|
||||
str r1, [r0, #0x18]
|
||||
#endif
|
||||
|
||||
|
@ -169,7 +169,7 @@ static void amba_device_release(struct device *dev)
|
||||
}
|
||||
|
||||
#define amba_attr(name,fmt,arg...) \
|
||||
static ssize_t show_##name(struct device *_dev, char *buf) \
|
||||
static ssize_t show_##name(struct device *_dev, struct device_attribute *attr, char *buf) \
|
||||
{ \
|
||||
struct amba_device *dev = to_amba_device(_dev); \
|
||||
return sprintf(buf, fmt, arg); \
|
||||
|
@ -30,6 +30,8 @@
|
||||
#include <linux/dmapool.h>
|
||||
#include <linux/list.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
|
||||
#undef DEBUG
|
||||
|
||||
#undef STATS
|
||||
@ -302,12 +304,24 @@ unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
|
||||
|
||||
DO_STATS ( device_info->bounce_count++ );
|
||||
|
||||
if ((dir == DMA_FROM_DEVICE) ||
|
||||
(dir == DMA_BIDIRECTIONAL)) {
|
||||
if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) {
|
||||
unsigned long ptr;
|
||||
|
||||
dev_dbg(dev,
|
||||
"%s: copy back safe %p to unsafe %p size %d\n",
|
||||
__func__, buf->safe, buf->ptr, size);
|
||||
memcpy(buf->ptr, buf->safe, size);
|
||||
|
||||
/*
|
||||
* DMA buffers must have the same cache properties
|
||||
* as if they were really used for DMA - which means
|
||||
* data must be written back to RAM. Note that
|
||||
* we don't use dmac_flush_range() here for the
|
||||
* bidirectional case because we know the cache
|
||||
* lines will be coherent with the data written.
|
||||
*/
|
||||
ptr = (unsigned long)buf->ptr;
|
||||
dmac_clean_range(ptr, ptr + size);
|
||||
}
|
||||
free_safe_buffer(device_info, buf);
|
||||
}
|
||||
|
@ -22,7 +22,7 @@
|
||||
* them early in the boot process, then pass them to the appropriate drivers.
|
||||
* Not all devices use all paramaters but the format is common to all.
|
||||
*/
|
||||
#ifdef ARCH_SA1100
|
||||
#ifdef CONFIG_ARCH_SA1100
|
||||
#define PARAM_BASE 0xe8ffc000
|
||||
#else
|
||||
#define PARAM_BASE 0xa0000a00
|
||||
|
@ -1,7 +1,7 @@
|
||||
#
|
||||
# Automatically generated make config: don't edit
|
||||
# Linux kernel version: 2.6.12-rc1-bk2
|
||||
# Sat Mar 26 21:32:26 2005
|
||||
# Linux kernel version: 2.6.12-rc6-git3
|
||||
# Thu Jun 9 19:00:50 2005
|
||||
#
|
||||
CONFIG_ARM=y
|
||||
CONFIG_MMU=y
|
||||
@ -16,6 +16,7 @@ CONFIG_GENERIC_IOMAP=y
|
||||
CONFIG_EXPERIMENTAL=y
|
||||
CONFIG_CLEAN_COMPILE=y
|
||||
CONFIG_BROKEN_ON_SMP=y
|
||||
CONFIG_INIT_ENV_ARG_LIMIT=32
|
||||
|
||||
#
|
||||
# General setup
|
||||
@ -34,6 +35,8 @@ CONFIG_EMBEDDED=y
|
||||
CONFIG_KALLSYMS=y
|
||||
# CONFIG_KALLSYMS_ALL is not set
|
||||
# CONFIG_KALLSYMS_EXTRA_PASS is not set
|
||||
CONFIG_PRINTK=y
|
||||
CONFIG_BUG=y
|
||||
CONFIG_BASE_FULL=y
|
||||
CONFIG_FUTEX=y
|
||||
CONFIG_EPOLL=y
|
||||
@ -109,7 +112,6 @@ CONFIG_CPU_ABRT_EV4=y
|
||||
CONFIG_CPU_CACHE_V4WB=y
|
||||
CONFIG_CPU_CACHE_VIVT=y
|
||||
CONFIG_CPU_TLB_V4WB=y
|
||||
CONFIG_CPU_MINICACHE=y
|
||||
|
||||
#
|
||||
# Processor Features
|
||||
@ -122,6 +124,7 @@ CONFIG_FORCE_MAX_ZONEORDER=9
|
||||
# Bus support
|
||||
#
|
||||
CONFIG_ISA=y
|
||||
CONFIG_ISA_DMA_API=y
|
||||
|
||||
#
|
||||
# PCCARD (PCMCIA/CardBus) support
|
||||
@ -131,6 +134,7 @@ CONFIG_ISA=y
|
||||
#
|
||||
# Kernel Features
|
||||
#
|
||||
# CONFIG_SMP is not set
|
||||
# CONFIG_PREEMPT is not set
|
||||
CONFIG_DISCONTIGMEM=y
|
||||
# CONFIG_LEDS is not set
|
||||
@ -152,12 +156,14 @@ CONFIG_CPU_FREQ_TABLE=y
|
||||
# CONFIG_CPU_FREQ_DEBUG is not set
|
||||
CONFIG_CPU_FREQ_STAT=y
|
||||
# CONFIG_CPU_FREQ_STAT_DETAILS is not set
|
||||
CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
|
||||
# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
|
||||
# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
|
||||
CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
|
||||
CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
|
||||
# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
|
||||
# CONFIG_CPU_FREQ_GOV_USERSPACE is not set
|
||||
CONFIG_CPU_FREQ_GOV_USERSPACE=y
|
||||
# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set
|
||||
# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
|
||||
CONFIG_CPU_FREQ_SA1100=y
|
||||
|
||||
#
|
||||
# Floating point emulation
|
||||
@ -294,7 +300,6 @@ CONFIG_PARPORT_NOT_PC=y
|
||||
#
|
||||
# Block devices
|
||||
#
|
||||
# CONFIG_BLK_DEV_FD is not set
|
||||
# CONFIG_BLK_DEV_XD is not set
|
||||
# CONFIG_PARIDE is not set
|
||||
# CONFIG_BLK_DEV_COW_COMMON is not set
|
||||
@ -428,7 +433,6 @@ CONFIG_NET=y
|
||||
#
|
||||
CONFIG_PACKET=y
|
||||
# CONFIG_PACKET_MMAP is not set
|
||||
# CONFIG_NETLINK_DEV is not set
|
||||
CONFIG_UNIX=y
|
||||
# CONFIG_NET_KEY is not set
|
||||
CONFIG_INET=y
|
||||
@ -526,6 +530,7 @@ CONFIG_IRDA_ULTRA=y
|
||||
# CONFIG_SMC_IRCC_FIR is not set
|
||||
# CONFIG_ALI_FIR is not set
|
||||
CONFIG_SA1100_FIR=y
|
||||
# CONFIG_VIA_FIR is not set
|
||||
CONFIG_BT=m
|
||||
CONFIG_BT_L2CAP=m
|
||||
# CONFIG_BT_SCO is not set
|
||||
@ -618,7 +623,6 @@ CONFIG_NET_WIRELESS=y
|
||||
#
|
||||
# CONFIG_SERIO is not set
|
||||
# CONFIG_GAMEPORT is not set
|
||||
CONFIG_SOUND_GAMEPORT=y
|
||||
|
||||
#
|
||||
# Character devices
|
||||
@ -687,7 +691,6 @@ CONFIG_RTC=m
|
||||
#
|
||||
# TPM devices
|
||||
#
|
||||
# CONFIG_TCG_TPM is not set
|
||||
|
||||
#
|
||||
# I2C support
|
||||
@ -736,6 +739,7 @@ CONFIG_I2C_ELEKTOR=m
|
||||
# CONFIG_SENSORS_LM85 is not set
|
||||
# CONFIG_SENSORS_LM87 is not set
|
||||
# CONFIG_SENSORS_LM90 is not set
|
||||
# CONFIG_SENSORS_LM92 is not set
|
||||
# CONFIG_SENSORS_MAX1619 is not set
|
||||
# CONFIG_SENSORS_PC87360 is not set
|
||||
# CONFIG_SENSORS_SMSC47B397 is not set
|
||||
@ -747,6 +751,7 @@ CONFIG_I2C_ELEKTOR=m
|
||||
#
|
||||
# Other I2C Chip support
|
||||
#
|
||||
# CONFIG_SENSORS_DS1337 is not set
|
||||
# CONFIG_SENSORS_EEPROM is not set
|
||||
# CONFIG_SENSORS_PCF8574 is not set
|
||||
# CONFIG_SENSORS_PCF8591 is not set
|
||||
@ -871,7 +876,6 @@ CONFIG_USB_PRINTER=m
|
||||
#
|
||||
CONFIG_USB_STORAGE=y
|
||||
CONFIG_USB_STORAGE_DEBUG=y
|
||||
# CONFIG_USB_STORAGE_RW_DETECT is not set
|
||||
# CONFIG_USB_STORAGE_DATAFAB is not set
|
||||
# CONFIG_USB_STORAGE_FREECOM is not set
|
||||
# CONFIG_USB_STORAGE_ISD200 is not set
|
||||
@ -954,9 +958,11 @@ CONFIG_USB_USS720=m
|
||||
#
|
||||
CONFIG_USB_SERIAL=m
|
||||
CONFIG_USB_SERIAL_GENERIC=y
|
||||
# CONFIG_USB_SERIAL_AIRPRIME is not set
|
||||
CONFIG_USB_SERIAL_BELKIN=m
|
||||
CONFIG_USB_SERIAL_WHITEHEAT=m
|
||||
CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
|
||||
# CONFIG_USB_SERIAL_CP2101 is not set
|
||||
# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
|
||||
CONFIG_USB_SERIAL_EMPEG=m
|
||||
CONFIG_USB_SERIAL_FTDI_SIO=m
|
||||
@ -985,6 +991,7 @@ CONFIG_USB_SERIAL_KEYSPAN=m
|
||||
# CONFIG_USB_SERIAL_KOBIL_SCT is not set
|
||||
CONFIG_USB_SERIAL_MCT_U232=m
|
||||
CONFIG_USB_SERIAL_PL2303=m
|
||||
# CONFIG_USB_SERIAL_HP4X is not set
|
||||
# CONFIG_USB_SERIAL_SAFE is not set
|
||||
# CONFIG_USB_SERIAL_TI is not set
|
||||
CONFIG_USB_SERIAL_CYBERJACK=m
|
||||
|
@ -50,7 +50,13 @@ CONFIG_BASE_SMALL=0
|
||||
#
|
||||
# Loadable module support
|
||||
#
|
||||
# CONFIG_MODULES is not set
|
||||
CONFIG_MODULES=y
|
||||
CONFIG_MODULE_UNLOAD=y
|
||||
# CONFIG_MODULE_FORCE_UNLOAD is not set
|
||||
CONFIG_OBSOLETE_MODPARM=y
|
||||
# CONFIG_MODVERSIONS is not set
|
||||
# CONFIG_MODULE_SRCVERSION_ALL is not set
|
||||
CONFIG_KMOD=y
|
||||
|
||||
#
|
||||
# System Type
|
||||
|
@ -1,7 +1,7 @@
|
||||
#
|
||||
# Automatically generated make config: don't edit
|
||||
# Linux kernel version: 2.6.12-rc1-bk2
|
||||
# Mon Mar 28 00:02:26 2005
|
||||
# Linux kernel version: 2.6.12-rc4
|
||||
# Thu Jun 9 01:59:03 2005
|
||||
#
|
||||
CONFIG_ARM=y
|
||||
CONFIG_MMU=y
|
||||
@ -16,6 +16,7 @@ CONFIG_GENERIC_IOMAP=y
|
||||
CONFIG_EXPERIMENTAL=y
|
||||
CONFIG_CLEAN_COMPILE=y
|
||||
CONFIG_BROKEN_ON_SMP=y
|
||||
CONFIG_INIT_ENV_ARG_LIMIT=32
|
||||
|
||||
#
|
||||
# General setup
|
||||
@ -33,6 +34,8 @@ CONFIG_KOBJECT_UEVENT=y
|
||||
# CONFIG_EMBEDDED is not set
|
||||
CONFIG_KALLSYMS=y
|
||||
# CONFIG_KALLSYMS_EXTRA_PASS is not set
|
||||
CONFIG_PRINTK=y
|
||||
CONFIG_BUG=y
|
||||
CONFIG_BASE_FULL=y
|
||||
CONFIG_FUTEX=y
|
||||
CONFIG_EPOLL=y
|
||||
@ -120,6 +123,7 @@ CONFIG_CPU_MINICACHE=y
|
||||
# Bus support
|
||||
#
|
||||
CONFIG_ISA=y
|
||||
CONFIG_ISA_DMA_API=y
|
||||
|
||||
#
|
||||
# PCCARD (PCMCIA/CardBus) support
|
||||
@ -138,6 +142,7 @@ CONFIG_PCMCIA_SA1100=y
|
||||
#
|
||||
# Kernel Features
|
||||
#
|
||||
# CONFIG_SMP is not set
|
||||
# CONFIG_PREEMPT is not set
|
||||
CONFIG_DISCONTIGMEM=y
|
||||
# CONFIG_LEDS is not set
|
||||
@ -159,12 +164,13 @@ CONFIG_CPU_FREQ_TABLE=y
|
||||
# CONFIG_CPU_FREQ_DEBUG is not set
|
||||
CONFIG_CPU_FREQ_STAT=y
|
||||
# CONFIG_CPU_FREQ_STAT_DETAILS is not set
|
||||
CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
|
||||
# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
|
||||
CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
|
||||
# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
|
||||
CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
|
||||
# CONFIG_CPU_FREQ_GOV_PERFORMANCE is not set
|
||||
# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
|
||||
# CONFIG_CPU_FREQ_GOV_USERSPACE is not set
|
||||
CONFIG_CPU_FREQ_GOV_USERSPACE=y
|
||||
# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set
|
||||
CONFIG_CPU_FREQ_SA1100=y
|
||||
|
||||
#
|
||||
# Floating point emulation
|
||||
@ -298,7 +304,6 @@ CONFIG_MTD_SA1100=y
|
||||
#
|
||||
# Block devices
|
||||
#
|
||||
# CONFIG_BLK_DEV_FD is not set
|
||||
# CONFIG_BLK_DEV_XD is not set
|
||||
# CONFIG_BLK_DEV_COW_COMMON is not set
|
||||
CONFIG_BLK_DEV_LOOP=m
|
||||
@ -379,7 +384,6 @@ CONFIG_NET=y
|
||||
# Networking options
|
||||
#
|
||||
# CONFIG_PACKET is not set
|
||||
# CONFIG_NETLINK_DEV is not set
|
||||
CONFIG_UNIX=y
|
||||
# CONFIG_NET_KEY is not set
|
||||
CONFIG_INET=y
|
||||
@ -476,6 +480,7 @@ CONFIG_IRCOMM=m
|
||||
# CONFIG_SMC_IRCC_FIR is not set
|
||||
# CONFIG_ALI_FIR is not set
|
||||
CONFIG_SA1100_FIR=m
|
||||
# CONFIG_VIA_FIR is not set
|
||||
# CONFIG_BT is not set
|
||||
CONFIG_NETDEVICES=y
|
||||
# CONFIG_DUMMY is not set
|
||||
@ -647,7 +652,6 @@ CONFIG_LEGACY_PTY_COUNT=256
|
||||
#
|
||||
# TPM devices
|
||||
#
|
||||
# CONFIG_TCG_TPM is not set
|
||||
|
||||
#
|
||||
# I2C support
|
||||
@ -676,9 +680,11 @@ CONFIG_FB_CFB_FILLRECT=y
|
||||
CONFIG_FB_CFB_COPYAREA=y
|
||||
CONFIG_FB_CFB_IMAGEBLIT=y
|
||||
CONFIG_FB_SOFT_CURSOR=y
|
||||
# CONFIG_FB_MACMODES is not set
|
||||
# CONFIG_FB_MODE_HELPERS is not set
|
||||
# CONFIG_FB_TILEBLITTING is not set
|
||||
CONFIG_FB_SA1100=y
|
||||
# CONFIG_FB_S1D13XXX is not set
|
||||
# CONFIG_FB_VIRTUAL is not set
|
||||
|
||||
#
|
||||
|
@ -1,7 +1,7 @@
|
||||
#
|
||||
# Automatically generated make config: don't edit
|
||||
# Linux kernel version: 2.6.12-rc1-bk2
|
||||
# Mon Mar 28 00:22:34 2005
|
||||
# Linux kernel version: 2.6.12-rc6-git3
|
||||
# Thu Jun 9 20:58:58 2005
|
||||
#
|
||||
CONFIG_ARM=y
|
||||
CONFIG_MMU=y
|
||||
@ -16,6 +16,7 @@ CONFIG_GENERIC_IOMAP=y
|
||||
CONFIG_EXPERIMENTAL=y
|
||||
CONFIG_CLEAN_COMPILE=y
|
||||
CONFIG_BROKEN_ON_SMP=y
|
||||
CONFIG_INIT_ENV_ARG_LIMIT=32
|
||||
|
||||
#
|
||||
# General setup
|
||||
@ -34,6 +35,8 @@ CONFIG_KOBJECT_UEVENT=y
|
||||
CONFIG_KALLSYMS=y
|
||||
# CONFIG_KALLSYMS_ALL is not set
|
||||
# CONFIG_KALLSYMS_EXTRA_PASS is not set
|
||||
CONFIG_PRINTK=y
|
||||
CONFIG_BUG=y
|
||||
CONFIG_BASE_FULL=y
|
||||
CONFIG_FUTEX=y
|
||||
CONFIG_EPOLL=y
|
||||
@ -109,7 +112,6 @@ CONFIG_CPU_ABRT_EV4=y
|
||||
CONFIG_CPU_CACHE_V4WB=y
|
||||
CONFIG_CPU_CACHE_VIVT=y
|
||||
CONFIG_CPU_TLB_V4WB=y
|
||||
CONFIG_CPU_MINICACHE=y
|
||||
|
||||
#
|
||||
# Processor Features
|
||||
@ -119,6 +121,7 @@ CONFIG_CPU_MINICACHE=y
|
||||
# Bus support
|
||||
#
|
||||
CONFIG_ISA=y
|
||||
CONFIG_ISA_DMA_API=y
|
||||
|
||||
#
|
||||
# PCCARD (PCMCIA/CardBus) support
|
||||
@ -128,6 +131,7 @@ CONFIG_ISA=y
|
||||
#
|
||||
# Kernel Features
|
||||
#
|
||||
# CONFIG_SMP is not set
|
||||
# CONFIG_PREEMPT is not set
|
||||
CONFIG_DISCONTIGMEM=y
|
||||
CONFIG_LEDS=y
|
||||
@ -151,12 +155,14 @@ CONFIG_CPU_FREQ_TABLE=y
|
||||
# CONFIG_CPU_FREQ_DEBUG is not set
|
||||
CONFIG_CPU_FREQ_STAT=y
|
||||
# CONFIG_CPU_FREQ_STAT_DETAILS is not set
|
||||
CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
|
||||
# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
|
||||
# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
|
||||
CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
|
||||
CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
|
||||
# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
|
||||
# CONFIG_CPU_FREQ_GOV_USERSPACE is not set
|
||||
CONFIG_CPU_FREQ_GOV_USERSPACE=y
|
||||
# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set
|
||||
# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
|
||||
CONFIG_CPU_FREQ_SA1100=y
|
||||
|
||||
#
|
||||
# Floating point emulation
|
||||
@ -280,7 +286,6 @@ CONFIG_MTD_CFI_UTIL=y
|
||||
#
|
||||
# Block devices
|
||||
#
|
||||
# CONFIG_BLK_DEV_FD is not set
|
||||
# CONFIG_BLK_DEV_XD is not set
|
||||
# CONFIG_BLK_DEV_COW_COMMON is not set
|
||||
# CONFIG_BLK_DEV_LOOP is not set
|
||||
@ -338,7 +343,6 @@ CONFIG_NET=y
|
||||
#
|
||||
CONFIG_PACKET=y
|
||||
# CONFIG_PACKET_MMAP is not set
|
||||
# CONFIG_NETLINK_DEV is not set
|
||||
CONFIG_UNIX=y
|
||||
# CONFIG_NET_KEY is not set
|
||||
CONFIG_INET=y
|
||||
@ -484,7 +488,6 @@ CONFIG_SERIO=y
|
||||
CONFIG_SERIO_SERPORT=y
|
||||
# CONFIG_SERIO_RAW is not set
|
||||
# CONFIG_GAMEPORT is not set
|
||||
CONFIG_SOUND_GAMEPORT=y
|
||||
|
||||
#
|
||||
# Character devices
|
||||
@ -533,7 +536,6 @@ CONFIG_LEGACY_PTY_COUNT=256
|
||||
#
|
||||
# TPM devices
|
||||
#
|
||||
# CONFIG_TCG_TPM is not set
|
||||
|
||||
#
|
||||
# I2C support
|
||||
|
@ -50,7 +50,13 @@ CONFIG_BASE_SMALL=0
|
||||
#
|
||||
# Loadable module support
|
||||
#
|
||||
# CONFIG_MODULES is not set
|
||||
CONFIG_MODULES=y
|
||||
CONFIG_MODULE_UNLOAD=y
|
||||
# CONFIG_MODULE_FORCE_UNLOAD is not set
|
||||
CONFIG_OBSOLETE_MODPARM=y
|
||||
# CONFIG_MODVERSIONS is not set
|
||||
# CONFIG_MODULE_SRCVERSION_ALL is not set
|
||||
CONFIG_KMOD=y
|
||||
|
||||
#
|
||||
# System Type
|
||||
|
@ -50,7 +50,13 @@ CONFIG_BASE_SMALL=0
|
||||
#
|
||||
# Loadable module support
|
||||
#
|
||||
# CONFIG_MODULES is not set
|
||||
CONFIG_MODULES=y
|
||||
CONFIG_MODULE_UNLOAD=y
|
||||
# CONFIG_MODULE_FORCE_UNLOAD is not set
|
||||
CONFIG_OBSOLETE_MODPARM=y
|
||||
# CONFIG_MODVERSIONS is not set
|
||||
# CONFIG_MODULE_SRCVERSION_ALL is not set
|
||||
CONFIG_KMOD=y
|
||||
|
||||
#
|
||||
# System Type
|
||||
|
@ -50,7 +50,13 @@ CONFIG_BASE_SMALL=0
|
||||
#
|
||||
# Loadable module support
|
||||
#
|
||||
# CONFIG_MODULES is not set
|
||||
CONFIG_MODULES=y
|
||||
CONFIG_MODULE_UNLOAD=y
|
||||
# CONFIG_MODULE_FORCE_UNLOAD is not set
|
||||
CONFIG_OBSOLETE_MODPARM=y
|
||||
# CONFIG_MODVERSIONS is not set
|
||||
# CONFIG_MODULE_SRCVERSION_ALL is not set
|
||||
CONFIG_KMOD=y
|
||||
|
||||
#
|
||||
# System Type
|
||||
|
@ -50,7 +50,13 @@ CONFIG_BASE_SMALL=0
|
||||
#
|
||||
# Loadable module support
|
||||
#
|
||||
# CONFIG_MODULES is not set
|
||||
CONFIG_MODULES=y
|
||||
CONFIG_MODULE_UNLOAD=y
|
||||
# CONFIG_MODULE_FORCE_UNLOAD is not set
|
||||
CONFIG_OBSOLETE_MODPARM=y
|
||||
# CONFIG_MODVERSIONS is not set
|
||||
# CONFIG_MODULE_SRCVERSION_ALL is not set
|
||||
CONFIG_KMOD=y
|
||||
|
||||
#
|
||||
# System Type
|
||||
|
@ -6,7 +6,7 @@ AFLAGS_head.o := -DTEXTADDR=$(TEXTADDR) -DDATAADDR=$(DATAADDR)
|
||||
|
||||
# Object file lists.
|
||||
|
||||
obj-y := arch.o compat.o dma.o entry-armv.o entry-common.o irq.o \
|
||||
obj-y := compat.o dma.o entry-armv.o entry-common.o irq.o \
|
||||
process.o ptrace.o semaphore.o setup.o signal.o sys_arm.o \
|
||||
time.o traps.o
|
||||
|
||||
|
@ -1,46 +0,0 @@
|
||||
/*
|
||||
* linux/arch/arm/kernel/arch.c
|
||||
*
|
||||
* Architecture specific fixups.
|
||||
*/
|
||||
#include <linux/config.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <asm/elf.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/mach/arch.h>
|
||||
|
||||
unsigned int vram_size;
|
||||
|
||||
#ifdef CONFIG_ARCH_ACORN
|
||||
|
||||
unsigned int memc_ctrl_reg;
|
||||
unsigned int number_mfm_drives;
|
||||
|
||||
static int __init parse_tag_acorn(const struct tag *tag)
|
||||
{
|
||||
memc_ctrl_reg = tag->u.acorn.memc_control_reg;
|
||||
number_mfm_drives = tag->u.acorn.adfsdrives;
|
||||
|
||||
switch (tag->u.acorn.vram_pages) {
|
||||
case 512:
|
||||
vram_size += PAGE_SIZE * 256;
|
||||
case 256:
|
||||
vram_size += PAGE_SIZE * 256;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#if 0
|
||||
if (vram_size) {
|
||||
desc->video_start = 0x02000000;
|
||||
desc->video_end = 0x02000000 + vram_size;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
__tagtable(ATAG_ACORN, parse_tag_acorn);
|
||||
|
||||
#endif
|
@ -866,19 +866,19 @@ static struct expansion_card *__init ecard_alloc_card(int type, int slot)
|
||||
return ec;
|
||||
}
|
||||
|
||||
static ssize_t ecard_show_irq(struct device *dev, char *buf)
|
||||
static ssize_t ecard_show_irq(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct expansion_card *ec = ECARD_DEV(dev);
|
||||
return sprintf(buf, "%u\n", ec->irq);
|
||||
}
|
||||
|
||||
static ssize_t ecard_show_dma(struct device *dev, char *buf)
|
||||
static ssize_t ecard_show_dma(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct expansion_card *ec = ECARD_DEV(dev);
|
||||
return sprintf(buf, "%u\n", ec->dma);
|
||||
}
|
||||
|
||||
static ssize_t ecard_show_resources(struct device *dev, char *buf)
|
||||
static ssize_t ecard_show_resources(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct expansion_card *ec = ECARD_DEV(dev);
|
||||
char *str = buf;
|
||||
@ -893,19 +893,19 @@ static ssize_t ecard_show_resources(struct device *dev, char *buf)
|
||||
return str - buf;
|
||||
}
|
||||
|
||||
static ssize_t ecard_show_vendor(struct device *dev, char *buf)
|
||||
static ssize_t ecard_show_vendor(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct expansion_card *ec = ECARD_DEV(dev);
|
||||
return sprintf(buf, "%u\n", ec->cid.manufacturer);
|
||||
}
|
||||
|
||||
static ssize_t ecard_show_device(struct device *dev, char *buf)
|
||||
static ssize_t ecard_show_device(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct expansion_card *ec = ECARD_DEV(dev);
|
||||
return sprintf(buf, "%u\n", ec->cid.product);
|
||||
}
|
||||
|
||||
static ssize_t ecard_show_type(struct device *dev, char *buf)
|
||||
static ssize_t ecard_show_type(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct expansion_card *ec = ECARD_DEV(dev);
|
||||
return sprintf(buf, "%s\n", ec->type == ECARD_EASI ? "EASI" : "IOC");
|
||||
|
@ -23,49 +23,92 @@
|
||||
|
||||
#include "entry-header.S"
|
||||
|
||||
/*
|
||||
* Interrupt handling. Preserves r7, r8, r9
|
||||
*/
|
||||
.macro irq_handler
|
||||
1: get_irqnr_and_base r0, r6, r5, lr
|
||||
movne r1, sp
|
||||
@
|
||||
@ routine called with r0 = irq number, r1 = struct pt_regs *
|
||||
@
|
||||
adrne lr, 1b
|
||||
bne asm_do_IRQ
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
/*
|
||||
* XXX
|
||||
*
|
||||
* this macro assumes that irqstat (r6) and base (r5) are
|
||||
* preserved from get_irqnr_and_base above
|
||||
*/
|
||||
test_for_ipi r0, r6, r5, lr
|
||||
movne r0, sp
|
||||
adrne lr, 1b
|
||||
bne do_IPI
|
||||
#endif
|
||||
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Invalid mode handlers
|
||||
*/
|
||||
.macro inv_entry, sym, reason
|
||||
sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go
|
||||
stmia sp, {r0 - lr} @ Save XXX r0 - lr
|
||||
ldr r4, .LC\sym
|
||||
.macro inv_entry, reason
|
||||
sub sp, sp, #S_FRAME_SIZE
|
||||
stmib sp, {r1 - lr}
|
||||
mov r1, #\reason
|
||||
.endm
|
||||
|
||||
__pabt_invalid:
|
||||
inv_entry abt, BAD_PREFETCH
|
||||
b 1f
|
||||
inv_entry BAD_PREFETCH
|
||||
b common_invalid
|
||||
|
||||
__dabt_invalid:
|
||||
inv_entry abt, BAD_DATA
|
||||
b 1f
|
||||
inv_entry BAD_DATA
|
||||
b common_invalid
|
||||
|
||||
__irq_invalid:
|
||||
inv_entry irq, BAD_IRQ
|
||||
b 1f
|
||||
inv_entry BAD_IRQ
|
||||
b common_invalid
|
||||
|
||||
__und_invalid:
|
||||
inv_entry und, BAD_UNDEFINSTR
|
||||
inv_entry BAD_UNDEFINSTR
|
||||
|
||||
@
|
||||
@ XXX fall through to common_invalid
|
||||
@
|
||||
|
||||
@
|
||||
@ common_invalid - generic code for failed exception (re-entrant version of handlers)
|
||||
@
|
||||
common_invalid:
|
||||
zero_fp
|
||||
|
||||
ldmia r0, {r4 - r6}
|
||||
add r0, sp, #S_PC @ here for interlock avoidance
|
||||
mov r7, #-1 @ "" "" "" ""
|
||||
str r4, [sp] @ save preserved r0
|
||||
stmia r0, {r5 - r7} @ lr_<exception>,
|
||||
@ cpsr_<exception>, "old_r0"
|
||||
|
||||
1: zero_fp
|
||||
ldmia r4, {r5 - r7} @ Get XXX pc, cpsr, old_r0
|
||||
add r4, sp, #S_PC
|
||||
stmia r4, {r5 - r7} @ Save XXX pc, cpsr, old_r0
|
||||
mov r0, sp
|
||||
and r2, r6, #31 @ int mode
|
||||
and r2, r6, #0x1f
|
||||
b bad_mode
|
||||
|
||||
/*
|
||||
* SVC mode handlers
|
||||
*/
|
||||
.macro svc_entry, sym
|
||||
.macro svc_entry
|
||||
sub sp, sp, #S_FRAME_SIZE
|
||||
stmia sp, {r0 - r12} @ save r0 - r12
|
||||
ldr r2, .LC\sym
|
||||
add r0, sp, #S_FRAME_SIZE
|
||||
ldmia r2, {r2 - r4} @ get pc, cpsr
|
||||
add r5, sp, #S_SP
|
||||
stmib sp, {r1 - r12}
|
||||
|
||||
ldmia r0, {r1 - r3}
|
||||
add r5, sp, #S_SP @ here for interlock avoidance
|
||||
mov r4, #-1 @ "" "" "" ""
|
||||
add r0, sp, #S_FRAME_SIZE @ "" "" "" ""
|
||||
str r1, [sp] @ save the "real" r0 copied
|
||||
@ from the exception stack
|
||||
|
||||
mov r1, lr
|
||||
|
||||
@
|
||||
@ -82,7 +125,7 @@ __und_invalid:
|
||||
|
||||
.align 5
|
||||
__dabt_svc:
|
||||
svc_entry abt
|
||||
svc_entry
|
||||
|
||||
@
|
||||
@ get ready to re-enable interrupts if appropriate
|
||||
@ -129,28 +172,24 @@ __dabt_svc:
|
||||
|
||||
.align 5
|
||||
__irq_svc:
|
||||
svc_entry irq
|
||||
svc_entry
|
||||
|
||||
#ifdef CONFIG_PREEMPT
|
||||
get_thread_info r8
|
||||
ldr r9, [r8, #TI_PREEMPT] @ get preempt count
|
||||
add r7, r9, #1 @ increment it
|
||||
str r7, [r8, #TI_PREEMPT]
|
||||
get_thread_info tsk
|
||||
ldr r8, [tsk, #TI_PREEMPT] @ get preempt count
|
||||
add r7, r8, #1 @ increment it
|
||||
str r7, [tsk, #TI_PREEMPT]
|
||||
#endif
|
||||
1: get_irqnr_and_base r0, r6, r5, lr
|
||||
movne r1, sp
|
||||
@
|
||||
@ routine called with r0 = irq number, r1 = struct pt_regs *
|
||||
@
|
||||
adrne lr, 1b
|
||||
bne asm_do_IRQ
|
||||
|
||||
irq_handler
|
||||
#ifdef CONFIG_PREEMPT
|
||||
ldr r0, [r8, #TI_FLAGS] @ get flags
|
||||
ldr r0, [tsk, #TI_FLAGS] @ get flags
|
||||
tst r0, #_TIF_NEED_RESCHED
|
||||
blne svc_preempt
|
||||
preempt_return:
|
||||
ldr r0, [r8, #TI_PREEMPT] @ read preempt value
|
||||
ldr r0, [tsk, #TI_PREEMPT] @ read preempt value
|
||||
str r8, [tsk, #TI_PREEMPT] @ restore preempt count
|
||||
teq r0, r7
|
||||
str r9, [r8, #TI_PREEMPT] @ restore preempt count
|
||||
strne r0, [r0, -r0] @ bug()
|
||||
#endif
|
||||
ldr r0, [sp, #S_PSR] @ irqs are already disabled
|
||||
@ -161,7 +200,7 @@ preempt_return:
|
||||
|
||||
#ifdef CONFIG_PREEMPT
|
||||
svc_preempt:
|
||||
teq r9, #0 @ was preempt count = 0
|
||||
teq r8, #0 @ was preempt count = 0
|
||||
ldreq r6, .LCirq_stat
|
||||
movne pc, lr @ no
|
||||
ldr r0, [r6, #4] @ local_irq_count
|
||||
@ -169,9 +208,9 @@ svc_preempt:
|
||||
adds r0, r0, r1
|
||||
movne pc, lr
|
||||
mov r7, #0 @ preempt_schedule_irq
|
||||
str r7, [r8, #TI_PREEMPT] @ expects preempt_count == 0
|
||||
str r7, [tsk, #TI_PREEMPT] @ expects preempt_count == 0
|
||||
1: bl preempt_schedule_irq @ irq en/disable is done inside
|
||||
ldr r0, [r8, #TI_FLAGS] @ get new tasks TI_FLAGS
|
||||
ldr r0, [tsk, #TI_FLAGS] @ get new tasks TI_FLAGS
|
||||
tst r0, #_TIF_NEED_RESCHED
|
||||
beq preempt_return @ go again
|
||||
b 1b
|
||||
@ -179,7 +218,7 @@ svc_preempt:
|
||||
|
||||
.align 5
|
||||
__und_svc:
|
||||
svc_entry und
|
||||
svc_entry
|
||||
|
||||
@
|
||||
@ call emulation code, which returns using r9 if it has emulated
|
||||
@ -209,7 +248,7 @@ __und_svc:
|
||||
|
||||
.align 5
|
||||
__pabt_svc:
|
||||
svc_entry abt
|
||||
svc_entry
|
||||
|
||||
@
|
||||
@ re-enable interrupts if appropriate
|
||||
@ -242,12 +281,8 @@ __pabt_svc:
|
||||
ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr
|
||||
|
||||
.align 5
|
||||
.LCirq:
|
||||
.word __temp_irq
|
||||
.LCund:
|
||||
.word __temp_und
|
||||
.LCabt:
|
||||
.word __temp_abt
|
||||
.LCcralign:
|
||||
.word cr_alignment
|
||||
#ifdef MULTI_ABORT
|
||||
.LCprocfns:
|
||||
.word processor
|
||||
@ -262,14 +297,18 @@ __pabt_svc:
|
||||
/*
|
||||
* User mode handlers
|
||||
*/
|
||||
.macro usr_entry, sym
|
||||
sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go
|
||||
stmia sp, {r0 - r12} @ save r0 - r12
|
||||
ldr r7, .LC\sym
|
||||
add r5, sp, #S_PC
|
||||
ldmia r7, {r2 - r4} @ Get USR pc, cpsr
|
||||
.macro usr_entry
|
||||
sub sp, sp, #S_FRAME_SIZE
|
||||
stmib sp, {r1 - r12}
|
||||
|
||||
#if __LINUX_ARM_ARCH__ < 6
|
||||
ldmia r0, {r1 - r3}
|
||||
add r0, sp, #S_PC @ here for interlock avoidance
|
||||
mov r4, #-1 @ "" "" "" ""
|
||||
|
||||
str r1, [sp] @ save the "real" r0 copied
|
||||
@ from the exception stack
|
||||
|
||||
#if __LINUX_ARM_ARCH__ < 6 && !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG)
|
||||
@ make sure our user space atomic helper is aborted
|
||||
cmp r2, #VIRT_OFFSET
|
||||
bichs r3, r3, #PSR_Z_BIT
|
||||
@ -284,13 +323,13 @@ __pabt_svc:
|
||||
@
|
||||
@ Also, separately save sp_usr and lr_usr
|
||||
@
|
||||
stmia r5, {r2 - r4}
|
||||
stmdb r5, {sp, lr}^
|
||||
stmia r0, {r2 - r4}
|
||||
stmdb r0, {sp, lr}^
|
||||
|
||||
@
|
||||
@ Enable the alignment trap while in kernel mode
|
||||
@
|
||||
alignment_trap r7, r0, __temp_\sym
|
||||
alignment_trap r0
|
||||
|
||||
@
|
||||
@ Clear FP to mark the first stack frame
|
||||
@ -300,7 +339,7 @@ __pabt_svc:
|
||||
|
||||
.align 5
|
||||
__dabt_usr:
|
||||
usr_entry abt
|
||||
usr_entry
|
||||
|
||||
@
|
||||
@ Call the processor-specific abort handler:
|
||||
@ -329,30 +368,23 @@ __dabt_usr:
|
||||
|
||||
.align 5
|
||||
__irq_usr:
|
||||
usr_entry irq
|
||||
usr_entry
|
||||
|
||||
#ifdef CONFIG_PREEMPT
|
||||
get_thread_info r8
|
||||
ldr r9, [r8, #TI_PREEMPT] @ get preempt count
|
||||
add r7, r9, #1 @ increment it
|
||||
str r7, [r8, #TI_PREEMPT]
|
||||
#endif
|
||||
1: get_irqnr_and_base r0, r6, r5, lr
|
||||
movne r1, sp
|
||||
adrne lr, 1b
|
||||
@
|
||||
@ routine called with r0 = irq number, r1 = struct pt_regs *
|
||||
@
|
||||
bne asm_do_IRQ
|
||||
#ifdef CONFIG_PREEMPT
|
||||
ldr r0, [r8, #TI_PREEMPT]
|
||||
teq r0, r7
|
||||
str r9, [r8, #TI_PREEMPT]
|
||||
strne r0, [r0, -r0]
|
||||
mov tsk, r8
|
||||
#else
|
||||
get_thread_info tsk
|
||||
#ifdef CONFIG_PREEMPT
|
||||
ldr r8, [tsk, #TI_PREEMPT] @ get preempt count
|
||||
add r7, r8, #1 @ increment it
|
||||
str r7, [tsk, #TI_PREEMPT]
|
||||
#endif
|
||||
|
||||
irq_handler
|
||||
#ifdef CONFIG_PREEMPT
|
||||
ldr r0, [tsk, #TI_PREEMPT]
|
||||
str r8, [tsk, #TI_PREEMPT]
|
||||
teq r0, r7
|
||||
strne r0, [r0, -r0]
|
||||
#endif
|
||||
|
||||
mov why, #0
|
||||
b ret_to_user
|
||||
|
||||
@ -360,7 +392,7 @@ __irq_usr:
|
||||
|
||||
.align 5
|
||||
__und_usr:
|
||||
usr_entry und
|
||||
usr_entry
|
||||
|
||||
tst r3, #PSR_T_BIT @ Thumb mode?
|
||||
bne fpundefinstr @ ignore FP
|
||||
@ -476,7 +508,7 @@ fpundefinstr:
|
||||
|
||||
.align 5
|
||||
__pabt_usr:
|
||||
usr_entry abt
|
||||
usr_entry
|
||||
|
||||
enable_irq @ Enable interrupts
|
||||
mov r0, r2 @ address (pc)
|
||||
@ -616,11 +648,17 @@ __kuser_helper_start:
|
||||
|
||||
__kuser_cmpxchg: @ 0xffff0fc0
|
||||
|
||||
#if __LINUX_ARM_ARCH__ < 6
|
||||
#if defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG)
|
||||
|
||||
#ifdef CONFIG_SMP /* sanity check */
|
||||
#error "CONFIG_SMP on a machine supporting pre-ARMv6 processors?"
|
||||
#endif
|
||||
/*
|
||||
* Poor you. No fast solution possible...
|
||||
* The kernel itself must perform the operation.
|
||||
* A special ghost syscall is used for that (see traps.c).
|
||||
*/
|
||||
swi #0x9ffff0
|
||||
mov pc, lr
|
||||
|
||||
#elif __LINUX_ARM_ARCH__ < 6
|
||||
|
||||
/*
|
||||
* Theory of operation:
|
||||
@ -735,29 +773,41 @@ __kuser_helper_end:
|
||||
*
|
||||
* Common stub entry macro:
|
||||
* Enter in IRQ mode, spsr = SVC/USR CPSR, lr = SVC/USR PC
|
||||
*
|
||||
* SP points to a minimal amount of processor-private memory, the address
|
||||
* of which is copied into r0 for the mode specific abort handler.
|
||||
*/
|
||||
.macro vector_stub, name, sym, correction=0
|
||||
.macro vector_stub, name, correction=0
|
||||
.align 5
|
||||
|
||||
vector_\name:
|
||||
ldr r13, .LCs\sym
|
||||
.if \correction
|
||||
sub lr, lr, #\correction
|
||||
.endif
|
||||
str lr, [r13] @ save lr_IRQ
|
||||
mrs lr, spsr
|
||||
str lr, [r13, #4] @ save spsr_IRQ
|
||||
@
|
||||
@ now branch to the relevant MODE handling routine
|
||||
@
|
||||
mrs r13, cpsr
|
||||
bic r13, r13, #MODE_MASK
|
||||
orr r13, r13, #SVC_MODE
|
||||
msr spsr_cxsf, r13 @ switch to SVC_32 mode
|
||||
|
||||
and lr, lr, #15
|
||||
@
|
||||
@ Save r0, lr_<exception> (parent PC) and spsr_<exception>
|
||||
@ (parent CPSR)
|
||||
@
|
||||
stmia sp, {r0, lr} @ save r0, lr
|
||||
mrs lr, spsr
|
||||
str lr, [sp, #8] @ save spsr
|
||||
|
||||
@
|
||||
@ Prepare for SVC32 mode. IRQs remain disabled.
|
||||
@
|
||||
mrs r0, cpsr
|
||||
bic r0, r0, #MODE_MASK
|
||||
orr r0, r0, #SVC_MODE
|
||||
msr spsr_cxsf, r0
|
||||
|
||||
@
|
||||
@ the branch table must immediately follow this code
|
||||
@
|
||||
mov r0, sp
|
||||
and lr, lr, #0x0f
|
||||
ldr lr, [pc, lr, lsl #2]
|
||||
movs pc, lr @ Changes mode and branches
|
||||
movs pc, lr @ branch to handler in SVC mode
|
||||
.endm
|
||||
|
||||
.globl __stubs_start
|
||||
@ -765,7 +815,7 @@ __stubs_start:
|
||||
/*
|
||||
* Interrupt dispatcher
|
||||
*/
|
||||
vector_stub irq, irq, 4
|
||||
vector_stub irq, 4
|
||||
|
||||
.long __irq_usr @ 0 (USR_26 / USR_32)
|
||||
.long __irq_invalid @ 1 (FIQ_26 / FIQ_32)
|
||||
@ -788,7 +838,7 @@ __stubs_start:
|
||||
* Data abort dispatcher
|
||||
* Enter in ABT mode, spsr = USR CPSR, lr = USR PC
|
||||
*/
|
||||
vector_stub dabt, abt, 8
|
||||
vector_stub dabt, 8
|
||||
|
||||
.long __dabt_usr @ 0 (USR_26 / USR_32)
|
||||
.long __dabt_invalid @ 1 (FIQ_26 / FIQ_32)
|
||||
@ -811,7 +861,7 @@ __stubs_start:
|
||||
* Prefetch abort dispatcher
|
||||
* Enter in ABT mode, spsr = USR CPSR, lr = USR PC
|
||||
*/
|
||||
vector_stub pabt, abt, 4
|
||||
vector_stub pabt, 4
|
||||
|
||||
.long __pabt_usr @ 0 (USR_26 / USR_32)
|
||||
.long __pabt_invalid @ 1 (FIQ_26 / FIQ_32)
|
||||
@ -834,7 +884,7 @@ __stubs_start:
|
||||
* Undef instr entry dispatcher
|
||||
* Enter in UND mode, spsr = SVC/USR CPSR, lr = SVC/USR PC
|
||||
*/
|
||||
vector_stub und, und
|
||||
vector_stub und
|
||||
|
||||
.long __und_usr @ 0 (USR_26 / USR_32)
|
||||
.long __und_invalid @ 1 (FIQ_26 / FIQ_32)
|
||||
@ -888,13 +938,6 @@ vector_addrexcptn:
|
||||
.LCvswi:
|
||||
.word vector_swi
|
||||
|
||||
.LCsirq:
|
||||
.word __temp_irq
|
||||
.LCsund:
|
||||
.word __temp_und
|
||||
.LCsabt:
|
||||
.word __temp_abt
|
||||
|
||||
.globl __stubs_end
|
||||
__stubs_end:
|
||||
|
||||
@ -916,23 +959,6 @@ __vectors_end:
|
||||
|
||||
.data
|
||||
|
||||
/*
|
||||
* Do not reorder these, and do not insert extra data between...
|
||||
*/
|
||||
|
||||
__temp_irq:
|
||||
.word 0 @ saved lr_irq
|
||||
.word 0 @ saved spsr_irq
|
||||
.word -1 @ old_r0
|
||||
__temp_und:
|
||||
.word 0 @ Saved lr_und
|
||||
.word 0 @ Saved spsr_und
|
||||
.word -1 @ old_r0
|
||||
__temp_abt:
|
||||
.word 0 @ Saved lr_abt
|
||||
.word 0 @ Saved spsr_abt
|
||||
.word -1 @ old_r0
|
||||
|
||||
.globl cr_alignment
|
||||
.globl cr_no_alignment
|
||||
cr_alignment:
|
||||
|
@ -59,11 +59,10 @@
|
||||
mov \rd, \rd, lsl #13
|
||||
.endm
|
||||
|
||||
.macro alignment_trap, rbase, rtemp, sym
|
||||
.macro alignment_trap, rtemp
|
||||
#ifdef CONFIG_ALIGNMENT_TRAP
|
||||
#define OFF_CR_ALIGNMENT(x) cr_alignment - x
|
||||
|
||||
ldr \rtemp, [\rbase, #OFF_CR_ALIGNMENT(\sym)]
|
||||
ldr \rtemp, .LCcralign
|
||||
ldr \rtemp, [\rtemp]
|
||||
mcr p15, 0, \rtemp, c1, c0
|
||||
#endif
|
||||
.endm
|
||||
|
@ -2,6 +2,8 @@
|
||||
* linux/arch/arm/kernel/head.S
|
||||
*
|
||||
* Copyright (C) 1994-2002 Russell King
|
||||
* Copyright (c) 2003 ARM Limited
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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
|
||||
@ -165,6 +167,48 @@ __mmap_switched:
|
||||
stmia r6, {r0, r4} @ Save control register values
|
||||
b start_kernel
|
||||
|
||||
#if defined(CONFIG_SMP)
|
||||
.type secondary_startup, #function
|
||||
ENTRY(secondary_startup)
|
||||
/*
|
||||
* Common entry point for secondary CPUs.
|
||||
*
|
||||
* Ensure that we're in SVC mode, and IRQs are disabled. Lookup
|
||||
* the processor type - there is no need to check the machine type
|
||||
* as it has already been validated by the primary processor.
|
||||
*/
|
||||
msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | MODE_SVC
|
||||
bl __lookup_processor_type
|
||||
movs r10, r5 @ invalid processor?
|
||||
moveq r0, #'p' @ yes, error 'p'
|
||||
beq __error
|
||||
|
||||
/*
|
||||
* Use the page tables supplied from __cpu_up.
|
||||
*/
|
||||
adr r4, __secondary_data
|
||||
ldmia r4, {r5, r6, r13} @ address to jump to after
|
||||
sub r4, r4, r5 @ mmu has been enabled
|
||||
ldr r4, [r6, r4] @ get secondary_data.pgdir
|
||||
adr lr, __enable_mmu @ return address
|
||||
add pc, r10, #12 @ initialise processor
|
||||
@ (return control reg)
|
||||
|
||||
/*
|
||||
* r6 = &secondary_data
|
||||
*/
|
||||
ENTRY(__secondary_switched)
|
||||
ldr sp, [r6, #4] @ get secondary_data.stack
|
||||
mov fp, #0
|
||||
b secondary_start_kernel
|
||||
|
||||
.type __secondary_data, %object
|
||||
__secondary_data:
|
||||
.long .
|
||||
.long secondary_data
|
||||
.long __secondary_switched
|
||||
#endif /* defined(CONFIG_SMP) */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
@ -92,6 +92,14 @@ struct cpu_user_fns cpu_user;
|
||||
struct cpu_cache_fns cpu_cache;
|
||||
#endif
|
||||
|
||||
struct stack {
|
||||
u32 irq[3];
|
||||
u32 abt[3];
|
||||
u32 und[3];
|
||||
} ____cacheline_aligned;
|
||||
|
||||
static struct stack stacks[NR_CPUS];
|
||||
|
||||
char elf_platform[ELF_PLATFORM_SIZE];
|
||||
EXPORT_SYMBOL(elf_platform);
|
||||
|
||||
@ -307,8 +315,6 @@ static void __init setup_processor(void)
|
||||
cpu_name, processor_id, (int)processor_id & 15,
|
||||
proc_arch[cpu_architecture()]);
|
||||
|
||||
dump_cpu_info(smp_processor_id());
|
||||
|
||||
sprintf(system_utsname.machine, "%s%c", list->arch_name, ENDIANNESS);
|
||||
sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS);
|
||||
elf_hwcap = list->elf_hwcap;
|
||||
@ -316,6 +322,46 @@ static void __init setup_processor(void)
|
||||
cpu_proc_init();
|
||||
}
|
||||
|
||||
/*
|
||||
* cpu_init - initialise one CPU.
|
||||
*
|
||||
* cpu_init dumps the cache information, initialises SMP specific
|
||||
* information, and sets up the per-CPU stacks.
|
||||
*/
|
||||
void cpu_init(void)
|
||||
{
|
||||
unsigned int cpu = smp_processor_id();
|
||||
struct stack *stk = &stacks[cpu];
|
||||
|
||||
if (cpu >= NR_CPUS) {
|
||||
printk(KERN_CRIT "CPU%u: bad primary CPU number\n", cpu);
|
||||
BUG();
|
||||
}
|
||||
|
||||
dump_cpu_info(cpu);
|
||||
|
||||
/*
|
||||
* setup stacks for re-entrant exception handlers
|
||||
*/
|
||||
__asm__ (
|
||||
"msr cpsr_c, %1\n\t"
|
||||
"add sp, %0, %2\n\t"
|
||||
"msr cpsr_c, %3\n\t"
|
||||
"add sp, %0, %4\n\t"
|
||||
"msr cpsr_c, %5\n\t"
|
||||
"add sp, %0, %6\n\t"
|
||||
"msr cpsr_c, %7"
|
||||
:
|
||||
: "r" (stk),
|
||||
"I" (PSR_F_BIT | PSR_I_BIT | IRQ_MODE),
|
||||
"I" (offsetof(struct stack, irq[0])),
|
||||
"I" (PSR_F_BIT | PSR_I_BIT | ABT_MODE),
|
||||
"I" (offsetof(struct stack, abt[0])),
|
||||
"I" (PSR_F_BIT | PSR_I_BIT | UND_MODE),
|
||||
"I" (offsetof(struct stack, und[0])),
|
||||
"I" (PSR_F_BIT | PSR_I_BIT | SVC_MODE));
|
||||
}
|
||||
|
||||
static struct machine_desc * __init setup_machine(unsigned int nr)
|
||||
{
|
||||
struct machine_desc *list;
|
||||
@ -715,6 +761,8 @@ void __init setup_arch(char **cmdline_p)
|
||||
paging_init(&meminfo, mdesc);
|
||||
request_standard_resources(&meminfo, mdesc);
|
||||
|
||||
cpu_init();
|
||||
|
||||
/*
|
||||
* Set up various architecture-specific pointers
|
||||
*/
|
||||
|
@ -24,6 +24,9 @@
|
||||
#include <asm/atomic.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/mmu_context.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/pgalloc.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/tlbflush.h>
|
||||
#include <asm/ptrace.h>
|
||||
@ -36,6 +39,13 @@
|
||||
cpumask_t cpu_present_mask;
|
||||
cpumask_t cpu_online_map;
|
||||
|
||||
/*
|
||||
* as from 2.5, kernels no longer have an init_tasks structure
|
||||
* so we need some other way of telling a new secondary core
|
||||
* where to place its SVC stack
|
||||
*/
|
||||
struct secondary_data secondary_data;
|
||||
|
||||
/*
|
||||
* structures for inter-processor calls
|
||||
* - A collection of single bit ipi messages.
|
||||
@ -71,6 +81,8 @@ static DEFINE_SPINLOCK(smp_call_function_lock);
|
||||
int __init __cpu_up(unsigned int cpu)
|
||||
{
|
||||
struct task_struct *idle;
|
||||
pgd_t *pgd;
|
||||
pmd_t *pmd;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
@ -83,12 +95,58 @@ int __init __cpu_up(unsigned int cpu)
|
||||
return PTR_ERR(idle);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate initial page tables to allow the new CPU to
|
||||
* enable the MMU safely. This essentially means a set
|
||||
* of our "standard" page tables, with the addition of
|
||||
* a 1:1 mapping for the physical address of the kernel.
|
||||
*/
|
||||
pgd = pgd_alloc(&init_mm);
|
||||
pmd = pmd_offset(pgd, PHYS_OFFSET);
|
||||
*pmd = __pmd((PHYS_OFFSET & PGDIR_MASK) |
|
||||
PMD_TYPE_SECT | PMD_SECT_AP_WRITE);
|
||||
|
||||
/*
|
||||
* We need to tell the secondary core where to find
|
||||
* its stack and the page tables.
|
||||
*/
|
||||
secondary_data.stack = (void *)idle->thread_info + THREAD_SIZE - 8;
|
||||
secondary_data.pgdir = virt_to_phys(pgd);
|
||||
wmb();
|
||||
|
||||
/*
|
||||
* Now bring the CPU into our world.
|
||||
*/
|
||||
ret = boot_secondary(cpu, idle);
|
||||
if (ret == 0) {
|
||||
unsigned long timeout;
|
||||
|
||||
/*
|
||||
* CPU was successfully started, wait for it
|
||||
* to come online or time out.
|
||||
*/
|
||||
timeout = jiffies + HZ;
|
||||
while (time_before(jiffies, timeout)) {
|
||||
if (cpu_online(cpu))
|
||||
break;
|
||||
|
||||
udelay(10);
|
||||
barrier();
|
||||
}
|
||||
|
||||
if (!cpu_online(cpu))
|
||||
ret = -EIO;
|
||||
}
|
||||
|
||||
secondary_data.stack = 0;
|
||||
secondary_data.pgdir = 0;
|
||||
|
||||
*pmd_offset(pgd, PHYS_OFFSET) = __pmd(0);
|
||||
pgd_free(pgd);
|
||||
|
||||
if (ret) {
|
||||
printk(KERN_CRIT "cpu_up: processor %d failed to boot\n", cpu);
|
||||
printk(KERN_CRIT "CPU%u: processor failed to boot\n", cpu);
|
||||
|
||||
/*
|
||||
* FIXME: We need to clean up the new idle thread. --rmk
|
||||
*/
|
||||
@ -97,6 +155,56 @@ int __init __cpu_up(unsigned int cpu)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the secondary CPU boot entry. We're using this CPUs
|
||||
* idle thread stack, but a set of temporary page tables.
|
||||
*/
|
||||
asmlinkage void __init secondary_start_kernel(void)
|
||||
{
|
||||
struct mm_struct *mm = &init_mm;
|
||||
unsigned int cpu = smp_processor_id();
|
||||
|
||||
printk("CPU%u: Booted secondary processor\n", cpu);
|
||||
|
||||
/*
|
||||
* All kernel threads share the same mm context; grab a
|
||||
* reference and switch to it.
|
||||
*/
|
||||
atomic_inc(&mm->mm_users);
|
||||
atomic_inc(&mm->mm_count);
|
||||
current->active_mm = mm;
|
||||
cpu_set(cpu, mm->cpu_vm_mask);
|
||||
cpu_switch_mm(mm->pgd, mm);
|
||||
enter_lazy_tlb(mm, current);
|
||||
|
||||
cpu_init();
|
||||
|
||||
/*
|
||||
* Give the platform a chance to do its own initialisation.
|
||||
*/
|
||||
platform_secondary_init(cpu);
|
||||
|
||||
/*
|
||||
* Enable local interrupts.
|
||||
*/
|
||||
local_irq_enable();
|
||||
local_fiq_enable();
|
||||
|
||||
calibrate_delay();
|
||||
|
||||
smp_store_cpu_info(cpu);
|
||||
|
||||
/*
|
||||
* OK, now it's safe to let the boot CPU continue
|
||||
*/
|
||||
cpu_set(cpu, cpu_online_map);
|
||||
|
||||
/*
|
||||
* OK, it's off to the idle thread for us
|
||||
*/
|
||||
cpu_idle();
|
||||
}
|
||||
|
||||
/*
|
||||
* Called by both boot and secondaries to move global data into
|
||||
* per-processor storage.
|
||||
|
@ -464,6 +464,55 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs)
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
#ifdef CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG
|
||||
/*
|
||||
* Atomically store r1 in *r2 if *r2 is equal to r0 for user space.
|
||||
* Return zero in r0 if *MEM was changed or non-zero if no exchange
|
||||
* happened. Also set the user C flag accordingly.
|
||||
* If access permissions have to be fixed up then non-zero is
|
||||
* returned and the operation has to be re-attempted.
|
||||
*
|
||||
* *NOTE*: This is a ghost syscall private to the kernel. Only the
|
||||
* __kuser_cmpxchg code in entry-armv.S should be aware of its
|
||||
* existence. Don't ever use this from user code.
|
||||
*/
|
||||
case 0xfff0:
|
||||
{
|
||||
extern void do_DataAbort(unsigned long addr, unsigned int fsr,
|
||||
struct pt_regs *regs);
|
||||
unsigned long val;
|
||||
unsigned long addr = regs->ARM_r2;
|
||||
struct mm_struct *mm = current->mm;
|
||||
pgd_t *pgd; pmd_t *pmd; pte_t *pte;
|
||||
|
||||
regs->ARM_cpsr &= ~PSR_C_BIT;
|
||||
spin_lock(&mm->page_table_lock);
|
||||
pgd = pgd_offset(mm, addr);
|
||||
if (!pgd_present(*pgd))
|
||||
goto bad_access;
|
||||
pmd = pmd_offset(pgd, addr);
|
||||
if (!pmd_present(*pmd))
|
||||
goto bad_access;
|
||||
pte = pte_offset_map(pmd, addr);
|
||||
if (!pte_present(*pte) || !pte_write(*pte))
|
||||
goto bad_access;
|
||||
val = *(unsigned long *)addr;
|
||||
val -= regs->ARM_r0;
|
||||
if (val == 0) {
|
||||
*(unsigned long *)addr = regs->ARM_r1;
|
||||
regs->ARM_cpsr |= PSR_C_BIT;
|
||||
}
|
||||
spin_unlock(&mm->page_table_lock);
|
||||
return val;
|
||||
|
||||
bad_access:
|
||||
spin_unlock(&mm->page_table_lock);
|
||||
/* simulate a read access fault */
|
||||
do_DataAbort(addr, 15 + (1 << 11), regs);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
default:
|
||||
/* Calls 9f00xx..9f07ff are defined to return -ENOSYS
|
||||
if not implemented, rather than raising SIGILL. This
|
||||
|
@ -31,31 +31,26 @@ Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "gcclib.h"
|
||||
|
||||
DItype
|
||||
__ashldi3 (DItype u, word_type b)
|
||||
s64 __ashldi3(s64 u, int b)
|
||||
{
|
||||
DIunion w;
|
||||
word_type bm;
|
||||
DIunion uu;
|
||||
DIunion w;
|
||||
int bm;
|
||||
DIunion uu;
|
||||
|
||||
if (b == 0)
|
||||
return u;
|
||||
if (b == 0)
|
||||
return u;
|
||||
|
||||
uu.ll = u;
|
||||
uu.ll = u;
|
||||
|
||||
bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
|
||||
if (bm <= 0)
|
||||
{
|
||||
w.s.low = 0;
|
||||
w.s.high = (USItype)uu.s.low << -bm;
|
||||
}
|
||||
else
|
||||
{
|
||||
USItype carries = (USItype)uu.s.low >> bm;
|
||||
w.s.low = (USItype)uu.s.low << b;
|
||||
w.s.high = ((USItype)uu.s.high << b) | carries;
|
||||
}
|
||||
bm = (sizeof(s32) * BITS_PER_UNIT) - b;
|
||||
if (bm <= 0) {
|
||||
w.s.low = 0;
|
||||
w.s.high = (u32) uu.s.low << -bm;
|
||||
} else {
|
||||
u32 carries = (u32) uu.s.low >> bm;
|
||||
w.s.low = (u32) uu.s.low << b;
|
||||
w.s.high = ((u32) uu.s.high << b) | carries;
|
||||
}
|
||||
|
||||
return w.ll;
|
||||
return w.ll;
|
||||
}
|
||||
|
||||
|
@ -31,31 +31,27 @@ Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "gcclib.h"
|
||||
|
||||
DItype
|
||||
__ashrdi3 (DItype u, word_type b)
|
||||
s64 __ashrdi3(s64 u, int b)
|
||||
{
|
||||
DIunion w;
|
||||
word_type bm;
|
||||
DIunion uu;
|
||||
DIunion w;
|
||||
int bm;
|
||||
DIunion uu;
|
||||
|
||||
if (b == 0)
|
||||
return u;
|
||||
if (b == 0)
|
||||
return u;
|
||||
|
||||
uu.ll = u;
|
||||
uu.ll = u;
|
||||
|
||||
bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
|
||||
if (bm <= 0)
|
||||
{
|
||||
/* w.s.high = 1..1 or 0..0 */
|
||||
w.s.high = uu.s.high >> (sizeof (SItype) * BITS_PER_UNIT - 1);
|
||||
w.s.low = uu.s.high >> -bm;
|
||||
}
|
||||
else
|
||||
{
|
||||
USItype carries = (USItype)uu.s.high << bm;
|
||||
w.s.high = uu.s.high >> b;
|
||||
w.s.low = ((USItype)uu.s.low >> b) | carries;
|
||||
}
|
||||
bm = (sizeof(s32) * BITS_PER_UNIT) - b;
|
||||
if (bm <= 0) {
|
||||
/* w.s.high = 1..1 or 0..0 */
|
||||
w.s.high = uu.s.high >> (sizeof(s32) * BITS_PER_UNIT - 1);
|
||||
w.s.low = uu.s.high >> -bm;
|
||||
} else {
|
||||
u32 carries = (u32) uu.s.high << bm;
|
||||
w.s.high = uu.s.high >> b;
|
||||
w.s.low = ((u32) uu.s.low >> b) | carries;
|
||||
}
|
||||
|
||||
return w.ll;
|
||||
return w.ll;
|
||||
}
|
||||
|
@ -1,25 +1,22 @@
|
||||
/* gcclib.h -- definitions for various functions 'borrowed' from gcc-2.95.3 */
|
||||
/* I Molton 29/07/01 */
|
||||
|
||||
#define BITS_PER_UNIT 8
|
||||
#define SI_TYPE_SIZE (sizeof (SItype) * BITS_PER_UNIT)
|
||||
#include <linux/types.h>
|
||||
|
||||
typedef unsigned int UQItype __attribute__ ((mode (QI)));
|
||||
typedef int SItype __attribute__ ((mode (SI)));
|
||||
typedef unsigned int USItype __attribute__ ((mode (SI)));
|
||||
typedef int DItype __attribute__ ((mode (DI)));
|
||||
typedef int word_type __attribute__ ((mode (__word__)));
|
||||
typedef unsigned int UDItype __attribute__ ((mode (DI)));
|
||||
#define BITS_PER_UNIT 8
|
||||
#define SI_TYPE_SIZE (sizeof(s32) * BITS_PER_UNIT)
|
||||
|
||||
#ifdef __ARMEB__
|
||||
struct DIstruct {SItype high, low;};
|
||||
struct DIstruct {
|
||||
s32 high, low;
|
||||
};
|
||||
#else
|
||||
struct DIstruct {SItype low, high;};
|
||||
struct DIstruct {
|
||||
s32 low, high;
|
||||
};
|
||||
#endif
|
||||
|
||||
typedef union
|
||||
{
|
||||
struct DIstruct s;
|
||||
DItype ll;
|
||||
typedef union {
|
||||
struct DIstruct s;
|
||||
s64 ll;
|
||||
} DIunion;
|
||||
|
||||
|
@ -87,9 +87,9 @@ ENTRY(__raw_writesw)
|
||||
subs r2, r2, #2
|
||||
orr ip, ip, r3, push_hbyte1
|
||||
strh ip, [r0]
|
||||
bpl 2b
|
||||
bpl 1b
|
||||
|
||||
3: tst r2, #1
|
||||
2: movne ip, r3, lsr #8
|
||||
tst r2, #1
|
||||
3: movne ip, r3, lsr #8
|
||||
strneh ip, [r0]
|
||||
mov pc, lr
|
||||
|
@ -26,18 +26,18 @@
|
||||
|
||||
#define __BITS4 (SI_TYPE_SIZE / 4)
|
||||
#define __ll_B (1L << (SI_TYPE_SIZE / 2))
|
||||
#define __ll_lowpart(t) ((USItype) (t) % __ll_B)
|
||||
#define __ll_highpart(t) ((USItype) (t) / __ll_B)
|
||||
#define __ll_lowpart(t) ((u32) (t) % __ll_B)
|
||||
#define __ll_highpart(t) ((u32) (t) / __ll_B)
|
||||
|
||||
/* Define auxiliary asm macros.
|
||||
|
||||
1) umul_ppmm(high_prod, low_prod, multipler, multiplicand)
|
||||
multiplies two USItype integers MULTIPLER and MULTIPLICAND,
|
||||
and generates a two-part USItype product in HIGH_PROD and
|
||||
multiplies two u32 integers MULTIPLER and MULTIPLICAND,
|
||||
and generates a two-part u32 product in HIGH_PROD and
|
||||
LOW_PROD.
|
||||
|
||||
2) __umulsidi3(a,b) multiplies two USItype integers A and B,
|
||||
and returns a UDItype product. This is just a variant of umul_ppmm.
|
||||
2) __umulsidi3(a,b) multiplies two u32 integers A and B,
|
||||
and returns a u64 product. This is just a variant of umul_ppmm.
|
||||
|
||||
3) udiv_qrnnd(quotient, remainder, high_numerator, low_numerator,
|
||||
denominator) divides a two-word unsigned integer, composed by the
|
||||
@ -77,23 +77,23 @@
|
||||
#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
|
||||
__asm__ ("adds %1, %4, %5 \n\
|
||||
adc %0, %2, %3" \
|
||||
: "=r" ((USItype) (sh)), \
|
||||
"=&r" ((USItype) (sl)) \
|
||||
: "%r" ((USItype) (ah)), \
|
||||
"rI" ((USItype) (bh)), \
|
||||
"%r" ((USItype) (al)), \
|
||||
"rI" ((USItype) (bl)))
|
||||
: "=r" ((u32) (sh)), \
|
||||
"=&r" ((u32) (sl)) \
|
||||
: "%r" ((u32) (ah)), \
|
||||
"rI" ((u32) (bh)), \
|
||||
"%r" ((u32) (al)), \
|
||||
"rI" ((u32) (bl)))
|
||||
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
|
||||
__asm__ ("subs %1, %4, %5 \n\
|
||||
sbc %0, %2, %3" \
|
||||
: "=r" ((USItype) (sh)), \
|
||||
"=&r" ((USItype) (sl)) \
|
||||
: "r" ((USItype) (ah)), \
|
||||
"rI" ((USItype) (bh)), \
|
||||
"r" ((USItype) (al)), \
|
||||
"rI" ((USItype) (bl)))
|
||||
: "=r" ((u32) (sh)), \
|
||||
"=&r" ((u32) (sl)) \
|
||||
: "r" ((u32) (ah)), \
|
||||
"rI" ((u32) (bh)), \
|
||||
"r" ((u32) (al)), \
|
||||
"rI" ((u32) (bl)))
|
||||
#define umul_ppmm(xh, xl, a, b) \
|
||||
{register USItype __t0, __t1, __t2; \
|
||||
{register u32 __t0, __t1, __t2; \
|
||||
__asm__ ("%@ Inlined umul_ppmm \n\
|
||||
mov %2, %5, lsr #16 \n\
|
||||
mov %0, %6, lsr #16 \n\
|
||||
@ -107,14 +107,14 @@
|
||||
addcs %0, %0, #65536 \n\
|
||||
adds %1, %1, %3, lsl #16 \n\
|
||||
adc %0, %0, %3, lsr #16" \
|
||||
: "=&r" ((USItype) (xh)), \
|
||||
"=r" ((USItype) (xl)), \
|
||||
: "=&r" ((u32) (xh)), \
|
||||
"=r" ((u32) (xl)), \
|
||||
"=&r" (__t0), "=&r" (__t1), "=r" (__t2) \
|
||||
: "r" ((USItype) (a)), \
|
||||
"r" ((USItype) (b)));}
|
||||
: "r" ((u32) (a)), \
|
||||
"r" ((u32) (b)));}
|
||||
#define UMUL_TIME 20
|
||||
#define UDIV_TIME 100
|
||||
#endif /* __arm__ */
|
||||
#endif /* __arm__ */
|
||||
|
||||
#define __umulsidi3(u, v) \
|
||||
({DIunion __w; \
|
||||
@ -123,14 +123,14 @@
|
||||
|
||||
#define __udiv_qrnnd_c(q, r, n1, n0, d) \
|
||||
do { \
|
||||
USItype __d1, __d0, __q1, __q0; \
|
||||
USItype __r1, __r0, __m; \
|
||||
u32 __d1, __d0, __q1, __q0; \
|
||||
u32 __r1, __r0, __m; \
|
||||
__d1 = __ll_highpart (d); \
|
||||
__d0 = __ll_lowpart (d); \
|
||||
\
|
||||
__r1 = (n1) % __d1; \
|
||||
__q1 = (n1) / __d1; \
|
||||
__m = (USItype) __q1 * __d0; \
|
||||
__m = (u32) __q1 * __d0; \
|
||||
__r1 = __r1 * __ll_B | __ll_highpart (n0); \
|
||||
if (__r1 < __m) \
|
||||
{ \
|
||||
@ -143,7 +143,7 @@
|
||||
\
|
||||
__r0 = __r1 % __d1; \
|
||||
__q0 = __r1 / __d1; \
|
||||
__m = (USItype) __q0 * __d0; \
|
||||
__m = (u32) __q0 * __d0; \
|
||||
__r0 = __r0 * __ll_B | __ll_lowpart (n0); \
|
||||
if (__r0 < __m) \
|
||||
{ \
|
||||
@ -154,7 +154,7 @@
|
||||
} \
|
||||
__r0 -= __m; \
|
||||
\
|
||||
(q) = (USItype) __q1 * __ll_B | __q0; \
|
||||
(q) = (u32) __q1 * __ll_B | __q0; \
|
||||
(r) = __r0; \
|
||||
} while (0)
|
||||
|
||||
@ -163,14 +163,14 @@
|
||||
|
||||
#define count_leading_zeros(count, x) \
|
||||
do { \
|
||||
USItype __xr = (x); \
|
||||
USItype __a; \
|
||||
u32 __xr = (x); \
|
||||
u32 __a; \
|
||||
\
|
||||
if (SI_TYPE_SIZE <= 32) \
|
||||
{ \
|
||||
__a = __xr < ((USItype)1<<2*__BITS4) \
|
||||
? (__xr < ((USItype)1<<__BITS4) ? 0 : __BITS4) \
|
||||
: (__xr < ((USItype)1<<3*__BITS4) ? 2*__BITS4 : 3*__BITS4); \
|
||||
__a = __xr < ((u32)1<<2*__BITS4) \
|
||||
? (__xr < ((u32)1<<__BITS4) ? 0 : __BITS4) \
|
||||
: (__xr < ((u32)1<<3*__BITS4) ? 2*__BITS4 : 3*__BITS4); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
|
@ -31,31 +31,26 @@ Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "gcclib.h"
|
||||
|
||||
DItype
|
||||
__lshrdi3 (DItype u, word_type b)
|
||||
s64 __lshrdi3(s64 u, int b)
|
||||
{
|
||||
DIunion w;
|
||||
word_type bm;
|
||||
DIunion uu;
|
||||
DIunion w;
|
||||
int bm;
|
||||
DIunion uu;
|
||||
|
||||
if (b == 0)
|
||||
return u;
|
||||
if (b == 0)
|
||||
return u;
|
||||
|
||||
uu.ll = u;
|
||||
uu.ll = u;
|
||||
|
||||
bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
|
||||
if (bm <= 0)
|
||||
{
|
||||
w.s.high = 0;
|
||||
w.s.low = (USItype)uu.s.high >> -bm;
|
||||
}
|
||||
else
|
||||
{
|
||||
USItype carries = (USItype)uu.s.high << bm;
|
||||
w.s.high = (USItype)uu.s.high >> b;
|
||||
w.s.low = ((USItype)uu.s.low >> b) | carries;
|
||||
}
|
||||
bm = (sizeof(s32) * BITS_PER_UNIT) - b;
|
||||
if (bm <= 0) {
|
||||
w.s.high = 0;
|
||||
w.s.low = (u32) uu.s.high >> -bm;
|
||||
} else {
|
||||
u32 carries = (u32) uu.s.high << bm;
|
||||
w.s.high = (u32) uu.s.high >> b;
|
||||
w.s.low = ((u32) uu.s.low >> b) | carries;
|
||||
}
|
||||
|
||||
return w.ll;
|
||||
return w.ll;
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,7 @@ Boston, MA 02111-1307, USA. */
|
||||
#include "gcclib.h"
|
||||
|
||||
#define umul_ppmm(xh, xl, a, b) \
|
||||
{register USItype __t0, __t1, __t2; \
|
||||
{register u32 __t0, __t1, __t2; \
|
||||
__asm__ ("%@ Inlined umul_ppmm \n\
|
||||
mov %2, %5, lsr #16 \n\
|
||||
mov %0, %6, lsr #16 \n\
|
||||
@ -46,32 +46,27 @@ Boston, MA 02111-1307, USA. */
|
||||
addcs %0, %0, #65536 \n\
|
||||
adds %1, %1, %3, lsl #16 \n\
|
||||
adc %0, %0, %3, lsr #16" \
|
||||
: "=&r" ((USItype) (xh)), \
|
||||
"=r" ((USItype) (xl)), \
|
||||
: "=&r" ((u32) (xh)), \
|
||||
"=r" ((u32) (xl)), \
|
||||
"=&r" (__t0), "=&r" (__t1), "=r" (__t2) \
|
||||
: "r" ((USItype) (a)), \
|
||||
"r" ((USItype) (b)));}
|
||||
|
||||
: "r" ((u32) (a)), \
|
||||
"r" ((u32) (b)));}
|
||||
|
||||
#define __umulsidi3(u, v) \
|
||||
({DIunion __w; \
|
||||
umul_ppmm (__w.s.high, __w.s.low, u, v); \
|
||||
__w.ll; })
|
||||
|
||||
|
||||
DItype
|
||||
__muldi3 (DItype u, DItype v)
|
||||
s64 __muldi3(s64 u, s64 v)
|
||||
{
|
||||
DIunion w;
|
||||
DIunion uu, vv;
|
||||
DIunion w;
|
||||
DIunion uu, vv;
|
||||
|
||||
uu.ll = u,
|
||||
vv.ll = v;
|
||||
uu.ll = u, vv.ll = v;
|
||||
|
||||
w.ll = __umulsidi3 (uu.s.low, vv.s.low);
|
||||
w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high
|
||||
+ (USItype) uu.s.high * (USItype) vv.s.low);
|
||||
w.ll = __umulsidi3(uu.s.low, vv.s.low);
|
||||
w.s.high += ((u32) uu.s.low * (u32) vv.s.high
|
||||
+ (u32) uu.s.high * (u32) vv.s.low);
|
||||
|
||||
return w.ll;
|
||||
return w.ll;
|
||||
}
|
||||
|
||||
|
@ -31,21 +31,19 @@ Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "gcclib.h"
|
||||
|
||||
word_type
|
||||
__ucmpdi2 (DItype a, DItype b)
|
||||
int __ucmpdi2(s64 a, s64 b)
|
||||
{
|
||||
DIunion au, bu;
|
||||
DIunion au, bu;
|
||||
|
||||
au.ll = a, bu.ll = b;
|
||||
au.ll = a, bu.ll = b;
|
||||
|
||||
if ((USItype) au.s.high < (USItype) bu.s.high)
|
||||
return 0;
|
||||
else if ((USItype) au.s.high > (USItype) bu.s.high)
|
||||
return 2;
|
||||
if ((USItype) au.s.low < (USItype) bu.s.low)
|
||||
return 0;
|
||||
else if ((USItype) au.s.low > (USItype) bu.s.low)
|
||||
return 2;
|
||||
return 1;
|
||||
if ((u32) au.s.high < (u32) bu.s.high)
|
||||
return 0;
|
||||
else if ((u32) au.s.high > (u32) bu.s.high)
|
||||
return 2;
|
||||
if ((u32) au.s.low < (u32) bu.s.low)
|
||||
return 0;
|
||||
else if ((u32) au.s.low > (u32) bu.s.low)
|
||||
return 2;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -32,211 +32,191 @@ Boston, MA 02111-1307, USA. */
|
||||
#include "gcclib.h"
|
||||
#include "longlong.h"
|
||||
|
||||
static const UQItype __clz_tab[] =
|
||||
{
|
||||
0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
|
||||
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
|
||||
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
|
||||
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
|
||||
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
|
||||
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
|
||||
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
|
||||
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
|
||||
static const u8 __clz_tab[] = {
|
||||
0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||
5, 5, 5, 5, 5, 5, 5, 5,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6,
|
||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8,
|
||||
};
|
||||
|
||||
UDItype
|
||||
__udivmoddi4 (UDItype n, UDItype d, UDItype *rp)
|
||||
u64 __udivmoddi4(u64 n, u64 d, u64 * rp)
|
||||
{
|
||||
DIunion ww;
|
||||
DIunion nn, dd;
|
||||
DIunion rr;
|
||||
USItype d0, d1, n0, n1, n2;
|
||||
USItype q0, q1;
|
||||
USItype b, bm;
|
||||
DIunion ww;
|
||||
DIunion nn, dd;
|
||||
DIunion rr;
|
||||
u32 d0, d1, n0, n1, n2;
|
||||
u32 q0, q1;
|
||||
u32 b, bm;
|
||||
|
||||
nn.ll = n;
|
||||
dd.ll = d;
|
||||
nn.ll = n;
|
||||
dd.ll = d;
|
||||
|
||||
d0 = dd.s.low;
|
||||
d1 = dd.s.high;
|
||||
n0 = nn.s.low;
|
||||
n1 = nn.s.high;
|
||||
d0 = dd.s.low;
|
||||
d1 = dd.s.high;
|
||||
n0 = nn.s.low;
|
||||
n1 = nn.s.high;
|
||||
|
||||
if (d1 == 0)
|
||||
{
|
||||
if (d0 > n1)
|
||||
{
|
||||
/* 0q = nn / 0D */
|
||||
if (d1 == 0) {
|
||||
if (d0 > n1) {
|
||||
/* 0q = nn / 0D */
|
||||
|
||||
count_leading_zeros (bm, d0);
|
||||
count_leading_zeros(bm, d0);
|
||||
|
||||
if (bm != 0)
|
||||
{
|
||||
/* Normalize, i.e. make the most significant bit of the
|
||||
denominator set. */
|
||||
if (bm != 0) {
|
||||
/* Normalize, i.e. make the most significant bit of the
|
||||
denominator set. */
|
||||
|
||||
d0 = d0 << bm;
|
||||
n1 = (n1 << bm) | (n0 >> (SI_TYPE_SIZE - bm));
|
||||
n0 = n0 << bm;
|
||||
}
|
||||
d0 = d0 << bm;
|
||||
n1 = (n1 << bm) | (n0 >> (SI_TYPE_SIZE - bm));
|
||||
n0 = n0 << bm;
|
||||
}
|
||||
|
||||
udiv_qrnnd (q0, n0, n1, n0, d0);
|
||||
q1 = 0;
|
||||
udiv_qrnnd(q0, n0, n1, n0, d0);
|
||||
q1 = 0;
|
||||
|
||||
/* Remainder in n0 >> bm. */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* qq = NN / 0d */
|
||||
/* Remainder in n0 >> bm. */
|
||||
} else {
|
||||
/* qq = NN / 0d */
|
||||
|
||||
if (d0 == 0)
|
||||
d0 = 1 / d0; /* Divide intentionally by zero. */
|
||||
if (d0 == 0)
|
||||
d0 = 1 / d0; /* Divide intentionally by zero. */
|
||||
|
||||
count_leading_zeros (bm, d0);
|
||||
count_leading_zeros(bm, d0);
|
||||
|
||||
if (bm == 0)
|
||||
{
|
||||
/* From (n1 >= d0) /\ (the most significant bit of d0 is set),
|
||||
conclude (the most significant bit of n1 is set) /\ (the
|
||||
leading quotient digit q1 = 1).
|
||||
if (bm == 0) {
|
||||
/* From (n1 >= d0) /\ (the most significant bit of d0 is set),
|
||||
conclude (the most significant bit of n1 is set) /\ (the
|
||||
leading quotient digit q1 = 1).
|
||||
|
||||
This special case is necessary, not an optimization.
|
||||
(Shifts counts of SI_TYPE_SIZE are undefined.) */
|
||||
This special case is necessary, not an optimization.
|
||||
(Shifts counts of SI_TYPE_SIZE are undefined.) */
|
||||
|
||||
n1 -= d0;
|
||||
q1 = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Normalize. */
|
||||
n1 -= d0;
|
||||
q1 = 1;
|
||||
} else {
|
||||
/* Normalize. */
|
||||
|
||||
b = SI_TYPE_SIZE - bm;
|
||||
b = SI_TYPE_SIZE - bm;
|
||||
|
||||
d0 = d0 << bm;
|
||||
n2 = n1 >> b;
|
||||
n1 = (n1 << bm) | (n0 >> b);
|
||||
n0 = n0 << bm;
|
||||
d0 = d0 << bm;
|
||||
n2 = n1 >> b;
|
||||
n1 = (n1 << bm) | (n0 >> b);
|
||||
n0 = n0 << bm;
|
||||
|
||||
udiv_qrnnd (q1, n1, n2, n1, d0);
|
||||
}
|
||||
udiv_qrnnd(q1, n1, n2, n1, d0);
|
||||
}
|
||||
|
||||
/* n1 != d0... */
|
||||
/* n1 != d0... */
|
||||
|
||||
udiv_qrnnd (q0, n0, n1, n0, d0);
|
||||
udiv_qrnnd(q0, n0, n1, n0, d0);
|
||||
|
||||
/* Remainder in n0 >> bm. */
|
||||
}
|
||||
/* Remainder in n0 >> bm. */
|
||||
}
|
||||
|
||||
if (rp != 0)
|
||||
{
|
||||
rr.s.low = n0 >> bm;
|
||||
rr.s.high = 0;
|
||||
*rp = rr.ll;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (d1 > n1)
|
||||
{
|
||||
/* 00 = nn / DD */
|
||||
if (rp != 0) {
|
||||
rr.s.low = n0 >> bm;
|
||||
rr.s.high = 0;
|
||||
*rp = rr.ll;
|
||||
}
|
||||
} else {
|
||||
if (d1 > n1) {
|
||||
/* 00 = nn / DD */
|
||||
|
||||
q0 = 0;
|
||||
q1 = 0;
|
||||
q0 = 0;
|
||||
q1 = 0;
|
||||
|
||||
/* Remainder in n1n0. */
|
||||
if (rp != 0)
|
||||
{
|
||||
rr.s.low = n0;
|
||||
rr.s.high = n1;
|
||||
*rp = rr.ll;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 0q = NN / dd */
|
||||
/* Remainder in n1n0. */
|
||||
if (rp != 0) {
|
||||
rr.s.low = n0;
|
||||
rr.s.high = n1;
|
||||
*rp = rr.ll;
|
||||
}
|
||||
} else {
|
||||
/* 0q = NN / dd */
|
||||
|
||||
count_leading_zeros (bm, d1);
|
||||
if (bm == 0)
|
||||
{
|
||||
/* From (n1 >= d1) /\ (the most significant bit of d1 is set),
|
||||
conclude (the most significant bit of n1 is set) /\ (the
|
||||
quotient digit q0 = 0 or 1).
|
||||
count_leading_zeros(bm, d1);
|
||||
if (bm == 0) {
|
||||
/* From (n1 >= d1) /\ (the most significant bit of d1 is set),
|
||||
conclude (the most significant bit of n1 is set) /\ (the
|
||||
quotient digit q0 = 0 or 1).
|
||||
|
||||
This special case is necessary, not an optimization. */
|
||||
This special case is necessary, not an optimization. */
|
||||
|
||||
/* The condition on the next line takes advantage of that
|
||||
n1 >= d1 (true due to program flow). */
|
||||
if (n1 > d1 || n0 >= d0)
|
||||
{
|
||||
q0 = 1;
|
||||
sub_ddmmss (n1, n0, n1, n0, d1, d0);
|
||||
}
|
||||
else
|
||||
q0 = 0;
|
||||
/* The condition on the next line takes advantage of that
|
||||
n1 >= d1 (true due to program flow). */
|
||||
if (n1 > d1 || n0 >= d0) {
|
||||
q0 = 1;
|
||||
sub_ddmmss(n1, n0, n1, n0, d1, d0);
|
||||
} else
|
||||
q0 = 0;
|
||||
|
||||
q1 = 0;
|
||||
q1 = 0;
|
||||
|
||||
if (rp != 0)
|
||||
{
|
||||
rr.s.low = n0;
|
||||
rr.s.high = n1;
|
||||
*rp = rr.ll;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
USItype m1, m0;
|
||||
/* Normalize. */
|
||||
if (rp != 0) {
|
||||
rr.s.low = n0;
|
||||
rr.s.high = n1;
|
||||
*rp = rr.ll;
|
||||
}
|
||||
} else {
|
||||
u32 m1, m0;
|
||||
/* Normalize. */
|
||||
|
||||
b = SI_TYPE_SIZE - bm;
|
||||
b = SI_TYPE_SIZE - bm;
|
||||
|
||||
d1 = (d1 << bm) | (d0 >> b);
|
||||
d0 = d0 << bm;
|
||||
n2 = n1 >> b;
|
||||
n1 = (n1 << bm) | (n0 >> b);
|
||||
n0 = n0 << bm;
|
||||
d1 = (d1 << bm) | (d0 >> b);
|
||||
d0 = d0 << bm;
|
||||
n2 = n1 >> b;
|
||||
n1 = (n1 << bm) | (n0 >> b);
|
||||
n0 = n0 << bm;
|
||||
|
||||
udiv_qrnnd (q0, n1, n2, n1, d1);
|
||||
umul_ppmm (m1, m0, q0, d0);
|
||||
udiv_qrnnd(q0, n1, n2, n1, d1);
|
||||
umul_ppmm(m1, m0, q0, d0);
|
||||
|
||||
if (m1 > n1 || (m1 == n1 && m0 > n0))
|
||||
{
|
||||
q0--;
|
||||
sub_ddmmss (m1, m0, m1, m0, d1, d0);
|
||||
}
|
||||
if (m1 > n1 || (m1 == n1 && m0 > n0)) {
|
||||
q0--;
|
||||
sub_ddmmss(m1, m0, m1, m0, d1, d0);
|
||||
}
|
||||
|
||||
q1 = 0;
|
||||
q1 = 0;
|
||||
|
||||
/* Remainder in (n1n0 - m1m0) >> bm. */
|
||||
if (rp != 0)
|
||||
{
|
||||
sub_ddmmss (n1, n0, n1, n0, m1, m0);
|
||||
rr.s.low = (n1 << b) | (n0 >> bm);
|
||||
rr.s.high = n1 >> bm;
|
||||
*rp = rr.ll;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Remainder in (n1n0 - m1m0) >> bm. */
|
||||
if (rp != 0) {
|
||||
sub_ddmmss(n1, n0, n1, n0, m1, m0);
|
||||
rr.s.low = (n1 << b) | (n0 >> bm);
|
||||
rr.s.high = n1 >> bm;
|
||||
*rp = rr.ll;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ww.s.low = q0;
|
||||
ww.s.high = q1;
|
||||
return ww.ll;
|
||||
ww.s.low = q0;
|
||||
ww.s.high = q1;
|
||||
return ww.ll;
|
||||
}
|
||||
|
||||
UDItype
|
||||
__udivdi3 (UDItype n, UDItype d)
|
||||
u64 __udivdi3(u64 n, u64 d)
|
||||
{
|
||||
return __udivmoddi4 (n, d, (UDItype *) 0);
|
||||
return __udivmoddi4(n, d, (u64 *) 0);
|
||||
}
|
||||
|
||||
UDItype
|
||||
__umoddi3 (UDItype u, UDItype v)
|
||||
u64 __umoddi3(u64 u, u64 v)
|
||||
{
|
||||
UDItype w;
|
||||
u64 w;
|
||||
|
||||
(void) __udivmoddi4 (u ,v, &w);
|
||||
(void)__udivmoddi4(u, v, &w);
|
||||
|
||||
return w;
|
||||
return w;
|
||||
}
|
||||
|
||||
|
11
arch/arm/mach-aaec2000/Kconfig
Normal file
11
arch/arm/mach-aaec2000/Kconfig
Normal file
@ -0,0 +1,11 @@
|
||||
if ARCH_AAEC2000
|
||||
|
||||
menu "Agilent AAEC-2000 Implementations"
|
||||
|
||||
config MACH_AAED2000
|
||||
bool "Agilent AAED-2000 Development Platform"
|
||||
select CPU_ARM920T
|
||||
|
||||
endmenu
|
||||
|
||||
endif
|
9
arch/arm/mach-aaec2000/Makefile
Normal file
9
arch/arm/mach-aaec2000/Makefile
Normal file
@ -0,0 +1,9 @@
|
||||
#
|
||||
# Makefile for the linux kernel.
|
||||
#
|
||||
|
||||
# Common support (must be linked before board specific support)
|
||||
obj-y += core.o
|
||||
|
||||
# Specific board support
|
||||
obj-$(CONFIG_MACH_AAED2000) += aaed2000.o
|
48
arch/arm/mach-aaec2000/aaed2000.c
Normal file
48
arch/arm/mach-aaec2000/aaed2000.c
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* linux/arch/arm/mach-aaec2000/aaed2000.c
|
||||
*
|
||||
* Support for the Agilent AAED-2000 Development Platform.
|
||||
*
|
||||
* Copyright (c) 2005 Nicolas Bellido Y Ortega
|
||||
*
|
||||
* 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/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include <asm/setup.h>
|
||||
#include <asm/memory.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/irq.h>
|
||||
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/map.h>
|
||||
#include <asm/mach/irq.h>
|
||||
|
||||
#include "core.h"
|
||||
|
||||
static void __init aaed2000_init_irq(void)
|
||||
{
|
||||
aaec2000_init_irq();
|
||||
}
|
||||
|
||||
static void __init aaed2000_map_io(void)
|
||||
{
|
||||
aaec2000_map_io();
|
||||
}
|
||||
|
||||
MACHINE_START(AAED2000, "Agilent AAED-2000 Development Platform")
|
||||
MAINTAINER("Nicolas Bellido Y Ortega")
|
||||
BOOT_MEM(0xf0000000, PIO_BASE, VIO_BASE)
|
||||
MAPIO(aaed2000_map_io)
|
||||
INITIRQ(aaed2000_init_irq)
|
||||
.timer = &aaec2000_timer,
|
||||
MACHINE_END
|
157
arch/arm/mach-aaec2000/core.c
Normal file
157
arch/arm/mach-aaec2000/core.c
Normal file
@ -0,0 +1,157 @@
|
||||
/*
|
||||
* linux/arch/arm/mach-aaec2000/core.c
|
||||
*
|
||||
* Code common to all AAEC-2000 machines
|
||||
*
|
||||
* Copyright (c) 2005 Nicolas Bellido Y Ortega
|
||||
*
|
||||
* 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/config.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/timex.h>
|
||||
#include <linux/signal.h>
|
||||
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/irq.h>
|
||||
|
||||
#include <asm/mach/irq.h>
|
||||
#include <asm/mach/time.h>
|
||||
#include <asm/mach/map.h>
|
||||
|
||||
/*
|
||||
* Common I/O mapping:
|
||||
*
|
||||
* Static virtual address mappings are as follow:
|
||||
*
|
||||
* 0xf8000000-0xf8001ffff: Devices connected to APB bus
|
||||
* 0xf8002000-0xf8003ffff: Devices connected to AHB bus
|
||||
*
|
||||
* Below 0xe8000000 is reserved for vm allocation.
|
||||
*
|
||||
* The machine specific code must provide the extra mapping beside the
|
||||
* default mapping provided here.
|
||||
*/
|
||||
static struct map_desc standard_io_desc[] __initdata = {
|
||||
/* virtual physical length type */
|
||||
{ VIO_APB_BASE, PIO_APB_BASE, IO_APB_LENGTH, MT_DEVICE },
|
||||
{ VIO_AHB_BASE, PIO_AHB_BASE, IO_AHB_LENGTH, MT_DEVICE }
|
||||
};
|
||||
|
||||
void __init aaec2000_map_io(void)
|
||||
{
|
||||
iotable_init(standard_io_desc, ARRAY_SIZE(standard_io_desc));
|
||||
}
|
||||
|
||||
/*
|
||||
* Interrupt handling routines
|
||||
*/
|
||||
static void aaec2000_int_ack(unsigned int irq)
|
||||
{
|
||||
IRQ_INTSR = 1 << irq;
|
||||
}
|
||||
|
||||
static void aaec2000_int_mask(unsigned int irq)
|
||||
{
|
||||
IRQ_INTENC |= (1 << irq);
|
||||
}
|
||||
|
||||
static void aaec2000_int_unmask(unsigned int irq)
|
||||
{
|
||||
IRQ_INTENS |= (1 << irq);
|
||||
}
|
||||
|
||||
static struct irqchip aaec2000_irq_chip = {
|
||||
.ack = aaec2000_int_ack,
|
||||
.mask = aaec2000_int_mask,
|
||||
.unmask = aaec2000_int_unmask,
|
||||
};
|
||||
|
||||
void __init aaec2000_init_irq(void)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < NR_IRQS; i++) {
|
||||
set_irq_handler(i, do_level_IRQ);
|
||||
set_irq_chip(i, &aaec2000_irq_chip);
|
||||
set_irq_flags(i, IRQF_VALID);
|
||||
}
|
||||
|
||||
/* Disable all interrupts */
|
||||
IRQ_INTENC = 0xffffffff;
|
||||
|
||||
/* Clear any pending interrupts */
|
||||
IRQ_INTSR = IRQ_INTSR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Time keeping
|
||||
*/
|
||||
/* IRQs are disabled before entering here from do_gettimeofday() */
|
||||
static unsigned long aaec2000_gettimeoffset(void)
|
||||
{
|
||||
unsigned long ticks_to_match, elapsed, usec;
|
||||
|
||||
/* Get ticks before next timer match */
|
||||
ticks_to_match = TIMER1_LOAD - TIMER1_VAL;
|
||||
|
||||
/* We need elapsed ticks since last match */
|
||||
elapsed = LATCH - ticks_to_match;
|
||||
|
||||
/* Now, convert them to usec */
|
||||
usec = (unsigned long)(elapsed * (tick_nsec / 1000))/LATCH;
|
||||
|
||||
return usec;
|
||||
}
|
||||
|
||||
/* We enter here with IRQs enabled */
|
||||
static irqreturn_t
|
||||
aaec2000_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
/* TODO: Check timer accuracy */
|
||||
write_seqlock(&xtime_lock);
|
||||
|
||||
timer_tick(regs);
|
||||
TIMER1_CLEAR = 1;
|
||||
|
||||
write_sequnlock(&xtime_lock);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static struct irqaction aaec2000_timer_irq = {
|
||||
.name = "AAEC-2000 Timer Tick",
|
||||
.flags = SA_INTERRUPT,
|
||||
.handler = aaec2000_timer_interrupt
|
||||
};
|
||||
|
||||
static void __init aaec2000_timer_init(void)
|
||||
{
|
||||
/* Disable timer 1 */
|
||||
TIMER1_CTRL = 0;
|
||||
|
||||
/* We have somehow to generate a 100Hz clock.
|
||||
* We then use the 508KHz timer in periodic mode.
|
||||
*/
|
||||
TIMER1_LOAD = LATCH;
|
||||
TIMER1_CLEAR = 1; /* Clear interrupt */
|
||||
|
||||
setup_irq(INT_TMR1_OFL, &aaec2000_timer_irq);
|
||||
|
||||
TIMER1_CTRL = TIMER_CTRL_ENABLE |
|
||||
TIMER_CTRL_PERIODIC |
|
||||
TIMER_CTRL_CLKSEL_508K;
|
||||
}
|
||||
|
||||
struct sys_timer aaec2000_timer = {
|
||||
.init = aaec2000_timer_init,
|
||||
.offset = aaec2000_gettimeoffset,
|
||||
};
|
||||
|
16
arch/arm/mach-aaec2000/core.h
Normal file
16
arch/arm/mach-aaec2000/core.h
Normal file
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* linux/arch/arm/mach-aaec2000/core.h
|
||||
*
|
||||
* Copyright (c) 2005 Nicolas Bellido Y Ortega
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
struct sys_timer;
|
||||
|
||||
extern struct sys_timer aaec2000_timer;
|
||||
extern void __init aaec2000_map_io(void);
|
||||
extern void __init aaec2000_init_irq(void);
|
@ -12,3 +12,4 @@ obj-$(CONFIG_LEDS) += leds.o
|
||||
obj-$(CONFIG_PCI) += pci_v3.o pci.o
|
||||
obj-$(CONFIG_CPU_FREQ_INTEGRATOR) += cpu.o
|
||||
obj-$(CONFIG_INTEGRATOR_IMPD1) += impd1.o
|
||||
obj-$(CONFIG_SMP) += platsmp.o headsmp.o
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/smp.h>
|
||||
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/irq.h>
|
||||
@ -221,7 +222,23 @@ integrator_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
||||
*/
|
||||
timer1->TimerClear = 1;
|
||||
|
||||
timer_tick(regs);
|
||||
/*
|
||||
* the clock tick routines are only processed on the
|
||||
* primary CPU
|
||||
*/
|
||||
if (hard_smp_processor_id() == 0) {
|
||||
timer_tick(regs);
|
||||
#ifdef CONFIG_SMP
|
||||
smp_send_timer();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
/*
|
||||
* this is the ARM equivalent of the APIC timer interrupt
|
||||
*/
|
||||
update_process_times(user_mode(regs));
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
write_sequnlock(&xtime_lock);
|
||||
|
||||
|
37
arch/arm/mach-integrator/headsmp.S
Normal file
37
arch/arm/mach-integrator/headsmp.S
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* linux/arch/arm/mach-integrator/headsmp.S
|
||||
*
|
||||
* Copyright (c) 2003 ARM Limited
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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/linkage.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
__INIT
|
||||
|
||||
/*
|
||||
* Integrator specific entry point for secondary CPUs. This provides
|
||||
* a "holding pen" into which all secondary cores are held until we're
|
||||
* ready for them to initialise.
|
||||
*/
|
||||
ENTRY(integrator_secondary_startup)
|
||||
adr r4, 1f
|
||||
ldmia r4, {r5, r6}
|
||||
sub r4, r4, r5
|
||||
ldr r6, [r6, r4]
|
||||
pen: ldr r7, [r6]
|
||||
cmp r7, r0
|
||||
bne pen
|
||||
|
||||
/*
|
||||
* we've been released from the holding pen: secondary_stack
|
||||
* should now contain the SVC stack for this core
|
||||
*/
|
||||
b secondary_startup
|
||||
|
||||
1: .long .
|
||||
.long phys_pen_release
|
@ -83,7 +83,6 @@ static struct map_desc intcp_io_desc[] __initdata = {
|
||||
{ IO_ADDRESS(INTEGRATOR_UART1_BASE), INTEGRATOR_UART1_BASE, SZ_4K, MT_DEVICE },
|
||||
{ IO_ADDRESS(INTEGRATOR_DBG_BASE), INTEGRATOR_DBG_BASE, SZ_4K, MT_DEVICE },
|
||||
{ IO_ADDRESS(INTEGRATOR_GPIO_BASE), INTEGRATOR_GPIO_BASE, SZ_4K, MT_DEVICE },
|
||||
{ 0xfc900000, 0xc9000000, SZ_4K, MT_DEVICE },
|
||||
{ 0xfca00000, 0xca000000, SZ_4K, MT_DEVICE },
|
||||
{ 0xfcb00000, 0xcb000000, SZ_4K, MT_DEVICE },
|
||||
};
|
||||
|
@ -22,6 +22,8 @@
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/io.h>
|
||||
@ -85,4 +87,4 @@ static int __init leds_init(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
__initcall(leds_init);
|
||||
core_initcall(leds_init);
|
||||
|
192
arch/arm/mach-integrator/platsmp.c
Normal file
192
arch/arm/mach-integrator/platsmp.c
Normal file
@ -0,0 +1,192 @@
|
||||
/*
|
||||
* linux/arch/arm/mach-cintegrator/platsmp.c
|
||||
*
|
||||
* Copyright (C) 2002 ARM Ltd.
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/mm.h>
|
||||
|
||||
#include <asm/atomic.h>
|
||||
#include <asm/delay.h>
|
||||
#include <asm/mmu_context.h>
|
||||
#include <asm/procinfo.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/smp.h>
|
||||
|
||||
extern void integrator_secondary_startup(void);
|
||||
|
||||
/*
|
||||
* control for which core is the next to come out of the secondary
|
||||
* boot "holding pen"
|
||||
*/
|
||||
volatile int __initdata pen_release = -1;
|
||||
unsigned long __initdata phys_pen_release = 0;
|
||||
|
||||
static DEFINE_SPINLOCK(boot_lock);
|
||||
|
||||
void __init platform_secondary_init(unsigned int cpu)
|
||||
{
|
||||
/*
|
||||
* the primary core may have used a "cross call" soft interrupt
|
||||
* to get this processor out of WFI in the BootMonitor - make
|
||||
* sure that we are no longer being sent this soft interrupt
|
||||
*/
|
||||
smp_cross_call_done(cpumask_of_cpu(cpu));
|
||||
|
||||
/*
|
||||
* if any interrupts are already enabled for the primary
|
||||
* core (e.g. timer irq), then they will not have been enabled
|
||||
* for us: do so
|
||||
*/
|
||||
secondary_scan_irqs();
|
||||
|
||||
/*
|
||||
* let the primary processor know we're out of the
|
||||
* pen, then head off into the C entry point
|
||||
*/
|
||||
pen_release = -1;
|
||||
|
||||
/*
|
||||
* Synchronise with the boot thread.
|
||||
*/
|
||||
spin_lock(&boot_lock);
|
||||
spin_unlock(&boot_lock);
|
||||
}
|
||||
|
||||
int __init boot_secondary(unsigned int cpu, struct task_struct *idle)
|
||||
{
|
||||
unsigned long timeout;
|
||||
|
||||
/*
|
||||
* set synchronisation state between this boot processor
|
||||
* and the secondary one
|
||||
*/
|
||||
spin_lock(&boot_lock);
|
||||
|
||||
/*
|
||||
* The secondary processor is waiting to be released from
|
||||
* the holding pen - release it, then wait for it to flag
|
||||
* that it has been released by resetting pen_release.
|
||||
*
|
||||
* Note that "pen_release" is the hardware CPU ID, whereas
|
||||
* "cpu" is Linux's internal ID.
|
||||
*/
|
||||
pen_release = cpu;
|
||||
|
||||
/*
|
||||
* XXX
|
||||
*
|
||||
* This is a later addition to the booting protocol: the
|
||||
* bootMonitor now puts secondary cores into WFI, so
|
||||
* poke_milo() no longer gets the cores moving; we need
|
||||
* to send a soft interrupt to wake the secondary core.
|
||||
* Use smp_cross_call() for this, since there's little
|
||||
* point duplicating the code here
|
||||
*/
|
||||
smp_cross_call(cpumask_of_cpu(cpu));
|
||||
|
||||
timeout = jiffies + (1 * HZ);
|
||||
while (time_before(jiffies, timeout)) {
|
||||
if (pen_release == -1)
|
||||
break;
|
||||
|
||||
udelay(10);
|
||||
}
|
||||
|
||||
/*
|
||||
* now the secondary core is starting up let it run its
|
||||
* calibrations, then wait for it to finish
|
||||
*/
|
||||
spin_unlock(&boot_lock);
|
||||
|
||||
return pen_release != -1 ? -ENOSYS : 0;
|
||||
}
|
||||
|
||||
static void __init poke_milo(void)
|
||||
{
|
||||
extern void secondary_startup(void);
|
||||
|
||||
/* nobody is to be released from the pen yet */
|
||||
pen_release = -1;
|
||||
|
||||
phys_pen_release = virt_to_phys(&pen_release);
|
||||
|
||||
/*
|
||||
* write the address of secondary startup into the system-wide
|
||||
* flags register, then clear the bottom two bits, which is what
|
||||
* BootMonitor is waiting for
|
||||
*/
|
||||
#if 1
|
||||
#define CINTEGRATOR_HDR_FLAGSS_OFFSET 0x30
|
||||
__raw_writel(virt_to_phys(integrator_secondary_startup),
|
||||
(IO_ADDRESS(INTEGRATOR_HDR_BASE) +
|
||||
CINTEGRATOR_HDR_FLAGSS_OFFSET));
|
||||
#define CINTEGRATOR_HDR_FLAGSC_OFFSET 0x34
|
||||
__raw_writel(3,
|
||||
(IO_ADDRESS(INTEGRATOR_HDR_BASE) +
|
||||
CINTEGRATOR_HDR_FLAGSC_OFFSET));
|
||||
#endif
|
||||
|
||||
mb();
|
||||
}
|
||||
|
||||
void __init smp_prepare_cpus(unsigned int max_cpus)
|
||||
{
|
||||
unsigned int ncores = get_core_count();
|
||||
unsigned int cpu = smp_processor_id();
|
||||
int i;
|
||||
|
||||
/* sanity check */
|
||||
if (ncores == 0) {
|
||||
printk(KERN_ERR
|
||||
"Integrator/CP: strange CM count of 0? Default to 1\n");
|
||||
|
||||
ncores = 1;
|
||||
}
|
||||
|
||||
if (ncores > NR_CPUS) {
|
||||
printk(KERN_WARNING
|
||||
"Integrator/CP: no. of cores (%d) greater than configured "
|
||||
"maximum of %d - clipping\n",
|
||||
ncores, NR_CPUS);
|
||||
ncores = NR_CPUS;
|
||||
}
|
||||
|
||||
/*
|
||||
* start with some more config for the Boot CPU, now that
|
||||
* the world is a bit more alive (which was not the case
|
||||
* when smp_prepare_boot_cpu() was called)
|
||||
*/
|
||||
smp_store_cpu_info(cpu);
|
||||
|
||||
/*
|
||||
* are we trying to boot more cores than exist?
|
||||
*/
|
||||
if (max_cpus > ncores)
|
||||
max_cpus = ncores;
|
||||
|
||||
/*
|
||||
* Initialise the present mask - this tells us which CPUs should
|
||||
* be present.
|
||||
*/
|
||||
for (i = 0; i < max_cpus; i++) {
|
||||
cpu_set(i, cpu_present_mask);
|
||||
}
|
||||
|
||||
/*
|
||||
* Do we need any more CPUs? If so, then let them know where
|
||||
* to start. Note that, on modern versions of MILO, the "poke"
|
||||
* doesn't actually do anything until each individual core is
|
||||
* sent a soft interrupt to get it out of WFI
|
||||
*/
|
||||
if (max_cpus > 1)
|
||||
poke_milo();
|
||||
}
|
@ -162,12 +162,13 @@ void __init ixp2000_map_io(void)
|
||||
static unsigned ticks_per_jiffy;
|
||||
static unsigned ticks_per_usec;
|
||||
static unsigned next_jiffy_time;
|
||||
static volatile unsigned long *missing_jiffy_timer_csr;
|
||||
|
||||
unsigned long ixp2000_gettimeoffset (void)
|
||||
{
|
||||
unsigned long offset;
|
||||
|
||||
offset = next_jiffy_time - *IXP2000_T4_CSR;
|
||||
offset = next_jiffy_time - *missing_jiffy_timer_csr;
|
||||
|
||||
return offset / ticks_per_usec;
|
||||
}
|
||||
@ -179,7 +180,7 @@ static int ixp2000_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
||||
/* clear timer 1 */
|
||||
ixp2000_reg_write(IXP2000_T1_CLR, 1);
|
||||
|
||||
while ((next_jiffy_time - *IXP2000_T4_CSR) > ticks_per_jiffy) {
|
||||
while ((next_jiffy_time - *missing_jiffy_timer_csr) > ticks_per_jiffy) {
|
||||
timer_tick(regs);
|
||||
next_jiffy_time -= ticks_per_jiffy;
|
||||
}
|
||||
@ -197,20 +198,37 @@ static struct irqaction ixp2000_timer_irq = {
|
||||
|
||||
void __init ixp2000_init_time(unsigned long tick_rate)
|
||||
{
|
||||
ixp2000_reg_write(IXP2000_T1_CLR, 0);
|
||||
ixp2000_reg_write(IXP2000_T4_CLR, 0);
|
||||
|
||||
ticks_per_jiffy = (tick_rate + HZ/2) / HZ;
|
||||
ticks_per_usec = tick_rate / 1000000;
|
||||
|
||||
/*
|
||||
* We use timer 1 as our timer interrupt.
|
||||
*/
|
||||
ixp2000_reg_write(IXP2000_T1_CLR, 0);
|
||||
ixp2000_reg_write(IXP2000_T1_CLD, ticks_per_jiffy - 1);
|
||||
ixp2000_reg_write(IXP2000_T1_CTL, (1 << 7));
|
||||
|
||||
/*
|
||||
* We use T4 as a monotonic counter to track missed jiffies
|
||||
* We use a second timer as a monotonic counter for tracking
|
||||
* missed jiffies. The IXP2000 has four timers, but if we're
|
||||
* on an A-step IXP2800, timer 2 and 3 don't work, so on those
|
||||
* chips we use timer 4. Timer 4 is the only timer that can
|
||||
* be used for the watchdog, so we use timer 2 if we're on a
|
||||
* non-buggy chip.
|
||||
*/
|
||||
ixp2000_reg_write(IXP2000_T4_CLD, -1);
|
||||
ixp2000_reg_write(IXP2000_T4_CTL, (1 << 7));
|
||||
if ((*IXP2000_PRODUCT_ID & 0x001ffef0) == 0x00000000) {
|
||||
printk(KERN_INFO "Enabling IXP2800 erratum #25 workaround\n");
|
||||
|
||||
ixp2000_reg_write(IXP2000_T4_CLR, 0);
|
||||
ixp2000_reg_write(IXP2000_T4_CLD, -1);
|
||||
ixp2000_reg_write(IXP2000_T4_CTL, (1 << 7));
|
||||
missing_jiffy_timer_csr = IXP2000_T4_CSR;
|
||||
} else {
|
||||
ixp2000_reg_write(IXP2000_T2_CLR, 0);
|
||||
ixp2000_reg_write(IXP2000_T2_CLD, -1);
|
||||
ixp2000_reg_write(IXP2000_T2_CTL, (1 << 7));
|
||||
missing_jiffy_timer_csr = IXP2000_T2_CSR;
|
||||
}
|
||||
next_jiffy_time = 0xffffffff;
|
||||
|
||||
/* register for interrupt */
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/sysdev.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/interrupt.h>
|
||||
@ -106,6 +107,35 @@ static void __init lubbock_init_irq(void)
|
||||
set_irq_type(IRQ_GPIO(0), IRQT_FALLING);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
static int lubbock_irq_resume(struct sys_device *dev)
|
||||
{
|
||||
LUB_IRQ_MASK_EN = lubbock_irq_enabled;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct sysdev_class lubbock_irq_sysclass = {
|
||||
set_kset_name("cpld_irq"),
|
||||
.resume = lubbock_irq_resume,
|
||||
};
|
||||
|
||||
static struct sys_device lubbock_irq_device = {
|
||||
.cls = &lubbock_irq_sysclass,
|
||||
};
|
||||
|
||||
static int __init lubbock_irq_device_init(void)
|
||||
{
|
||||
int ret = sysdev_class_register(&lubbock_irq_sysclass);
|
||||
if (ret == 0)
|
||||
ret = sysdev_register(&lubbock_irq_device);
|
||||
return ret;
|
||||
}
|
||||
|
||||
device_initcall(lubbock_irq_device_init);
|
||||
|
||||
#endif
|
||||
|
||||
static int lubbock_udc_is_connected(void)
|
||||
{
|
||||
return (LUB_MISC_RD & (1 << 9)) == 0;
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/sysdev.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/bitops.h>
|
||||
@ -62,7 +63,6 @@ static struct irqchip mainstone_irq_chip = {
|
||||
.unmask = mainstone_unmask_irq,
|
||||
};
|
||||
|
||||
|
||||
static void mainstone_irq_handler(unsigned int irq, struct irqdesc *desc,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
@ -100,6 +100,35 @@ static void __init mainstone_init_irq(void)
|
||||
set_irq_type(IRQ_GPIO(0), IRQT_FALLING);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
static int mainstone_irq_resume(struct sys_device *dev)
|
||||
{
|
||||
MST_INTMSKENA = mainstone_irq_enabled;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct sysdev_class mainstone_irq_sysclass = {
|
||||
set_kset_name("cpld_irq"),
|
||||
.resume = mainstone_irq_resume,
|
||||
};
|
||||
|
||||
static struct sys_device mainstone_irq_device = {
|
||||
.cls = &mainstone_irq_sysclass,
|
||||
};
|
||||
|
||||
static int __init mainstone_irq_device_init(void)
|
||||
{
|
||||
int ret = sysdev_class_register(&mainstone_irq_sysclass);
|
||||
if (ret == 0)
|
||||
ret = sysdev_register(&mainstone_irq_device);
|
||||
return ret;
|
||||
}
|
||||
|
||||
device_initcall(mainstone_irq_device_init);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static struct resource smc91x_resources[] = {
|
||||
[0] = {
|
||||
@ -304,6 +333,15 @@ static void __init mainstone_map_io(void)
|
||||
PWER = 0xC0000002;
|
||||
PRER = 0x00000002;
|
||||
PFER = 0x00000002;
|
||||
/* for use I SRAM as framebuffer. */
|
||||
PSLR |= 0xF04;
|
||||
PCFR = 0x66;
|
||||
/* For Keypad wakeup. */
|
||||
KPC &=~KPC_ASACT;
|
||||
KPC |=KPC_AS;
|
||||
PKWR = 0x000FD000;
|
||||
/* Need read PKWR back after set it. */
|
||||
PKWR;
|
||||
}
|
||||
|
||||
MACHINE_START(MAINSTONE, "Intel HCDDBBVA0 Development Platform (aka Mainstone)")
|
||||
|
@ -29,9 +29,6 @@
|
||||
*/
|
||||
#undef DEBUG
|
||||
|
||||
extern void pxa_cpu_suspend(void);
|
||||
extern void pxa_cpu_resume(void);
|
||||
|
||||
#define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x
|
||||
#define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x]
|
||||
|
||||
@ -63,6 +60,12 @@ enum { SLEEP_SAVE_START = 0,
|
||||
SLEEP_SAVE_ICMR,
|
||||
SLEEP_SAVE_CKEN,
|
||||
|
||||
#ifdef CONFIG_PXA27x
|
||||
SLEEP_SAVE_MDREFR,
|
||||
SLEEP_SAVE_PWER, SLEEP_SAVE_PCFR, SLEEP_SAVE_PRER,
|
||||
SLEEP_SAVE_PFER, SLEEP_SAVE_PKWR,
|
||||
#endif
|
||||
|
||||
SLEEP_SAVE_CKSUM,
|
||||
|
||||
SLEEP_SAVE_SIZE
|
||||
@ -75,9 +78,7 @@ static int pxa_pm_enter(suspend_state_t state)
|
||||
unsigned long checksum = 0;
|
||||
struct timespec delta, rtc;
|
||||
int i;
|
||||
|
||||
if (state != PM_SUSPEND_MEM)
|
||||
return -EINVAL;
|
||||
extern void pxa_cpu_pm_enter(suspend_state_t state);
|
||||
|
||||
#ifdef CONFIG_IWMMXT
|
||||
/* force any iWMMXt context to ram **/
|
||||
@ -100,16 +101,17 @@ static int pxa_pm_enter(suspend_state_t state)
|
||||
SAVE(GAFR2_L); SAVE(GAFR2_U);
|
||||
|
||||
#ifdef CONFIG_PXA27x
|
||||
SAVE(MDREFR);
|
||||
SAVE(GPLR3); SAVE(GPDR3); SAVE(GRER3); SAVE(GFER3); SAVE(PGSR3);
|
||||
SAVE(GAFR3_L); SAVE(GAFR3_U);
|
||||
SAVE(PWER); SAVE(PCFR); SAVE(PRER);
|
||||
SAVE(PFER); SAVE(PKWR);
|
||||
#endif
|
||||
|
||||
SAVE(ICMR);
|
||||
ICMR = 0;
|
||||
|
||||
SAVE(CKEN);
|
||||
CKEN = 0;
|
||||
|
||||
SAVE(PSTR);
|
||||
|
||||
/* Note: wake up source are set up in each machine specific files */
|
||||
@ -123,16 +125,15 @@ static int pxa_pm_enter(suspend_state_t state)
|
||||
/* Clear sleep reset status */
|
||||
RCSR = RCSR_SMR;
|
||||
|
||||
/* set resume return address */
|
||||
PSPR = virt_to_phys(pxa_cpu_resume);
|
||||
|
||||
/* before sleeping, calculate and save a checksum */
|
||||
for (i = 0; i < SLEEP_SAVE_SIZE - 1; i++)
|
||||
checksum += sleep_save[i];
|
||||
sleep_save[SLEEP_SAVE_CKSUM] = checksum;
|
||||
|
||||
/* *** go zzz *** */
|
||||
pxa_cpu_suspend();
|
||||
pxa_cpu_pm_enter(state);
|
||||
|
||||
cpu_init();
|
||||
|
||||
/* after sleeping, validate the checksum */
|
||||
checksum = 0;
|
||||
@ -145,7 +146,7 @@ static int pxa_pm_enter(suspend_state_t state)
|
||||
LUB_HEXLED = 0xbadbadc5;
|
||||
#endif
|
||||
while (1)
|
||||
pxa_cpu_suspend();
|
||||
pxa_cpu_pm_enter(state);
|
||||
}
|
||||
|
||||
/* ensure not to come back here if it wasn't intended */
|
||||
@ -162,8 +163,11 @@ static int pxa_pm_enter(suspend_state_t state)
|
||||
RESTORE(PGSR0); RESTORE(PGSR1); RESTORE(PGSR2);
|
||||
|
||||
#ifdef CONFIG_PXA27x
|
||||
RESTORE(MDREFR);
|
||||
RESTORE(GAFR3_L); RESTORE(GAFR3_U); RESTORE_GPLEVEL(3);
|
||||
RESTORE(GPDR3); RESTORE(GRER3); RESTORE(GFER3); RESTORE(PGSR3);
|
||||
RESTORE(PWER); RESTORE(PCFR); RESTORE(PRER);
|
||||
RESTORE(PFER); RESTORE(PKWR);
|
||||
#endif
|
||||
|
||||
PSSR = PSSR_RDH | PSSR_PH;
|
||||
@ -197,7 +201,9 @@ unsigned long sleep_phys_sp(void *sp)
|
||||
*/
|
||||
static int pxa_pm_prepare(suspend_state_t state)
|
||||
{
|
||||
return 0;
|
||||
extern int pxa_cpu_pm_prepare(suspend_state_t state);
|
||||
|
||||
return pxa_cpu_pm_prepare(state);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -16,6 +16,7 @@
|
||||
* initialization stuff for PXA machines which can be overridden later if
|
||||
* need be.
|
||||
*/
|
||||
#include <linux/config.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
@ -102,3 +103,35 @@ unsigned int get_lcdclk_frequency_10khz(void)
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(get_lcdclk_frequency_10khz);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
int pxa_cpu_pm_prepare(suspend_state_t state)
|
||||
{
|
||||
switch (state) {
|
||||
case PM_SUSPEND_MEM:
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void pxa_cpu_pm_enter(suspend_state_t state)
|
||||
{
|
||||
extern void pxa_cpu_suspend(unsigned int);
|
||||
extern void pxa_cpu_resume(void);
|
||||
|
||||
CKEN = 0;
|
||||
|
||||
switch (state) {
|
||||
case PM_SUSPEND_MEM:
|
||||
/* set resume return address */
|
||||
PSPR = virt_to_phys(pxa_cpu_resume);
|
||||
pxa_cpu_suspend(3);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -120,6 +120,42 @@ EXPORT_SYMBOL(get_clk_frequency_khz);
|
||||
EXPORT_SYMBOL(get_memclk_frequency_10khz);
|
||||
EXPORT_SYMBOL(get_lcdclk_frequency_10khz);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
int pxa_cpu_pm_prepare(suspend_state_t state)
|
||||
{
|
||||
switch (state) {
|
||||
case PM_SUSPEND_MEM:
|
||||
return 0;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
void pxa_cpu_pm_enter(suspend_state_t state)
|
||||
{
|
||||
extern void pxa_cpu_standby(void);
|
||||
extern void pxa_cpu_suspend(unsigned int);
|
||||
extern void pxa_cpu_resume(void);
|
||||
|
||||
CKEN = CKEN22_MEMC | CKEN9_OSTIMER;
|
||||
|
||||
/* ensure voltage-change sequencer not initiated, which hangs */
|
||||
PCFR &= ~PCFR_FVC;
|
||||
|
||||
/* Clear edge-detect status register. */
|
||||
PEDR = 0xDF12FE1B;
|
||||
|
||||
switch (state) {
|
||||
case PM_SUSPEND_MEM:
|
||||
/* set resume return address */
|
||||
PSPR = virt_to_phys(pxa_cpu_resume);
|
||||
pxa_cpu_suspend(3);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* device registration specific to PXA27x.
|
||||
|
@ -785,6 +785,10 @@ int s3c2410_dma_free(dmach_t channel, s3c2410_dma_client_t *client)
|
||||
chan->client = NULL;
|
||||
chan->in_use = 0;
|
||||
|
||||
if (chan->irq_claimed)
|
||||
free_irq(chan->irq, (void *)chan);
|
||||
chan->irq_claimed = 0;
|
||||
|
||||
local_irq_restore(flags);
|
||||
|
||||
return 0;
|
||||
|
@ -150,7 +150,7 @@ config SA1100_SSP
|
||||
|
||||
config H3600_SLEEVE
|
||||
tristate "Compaq iPAQ Handheld sleeve support"
|
||||
depends on SA1100_H3600
|
||||
depends on SA1100_H3100 || SA1100_H3600
|
||||
help
|
||||
Choose this option to enable support for extension packs (sleeves)
|
||||
for the Compaq iPAQ H3XXX series of handheld computers. This option
|
||||
|
@ -88,6 +88,8 @@ static int sa11x0_pm_enter(suspend_state_t state)
|
||||
/* go zzz */
|
||||
sa1100_cpu_suspend();
|
||||
|
||||
cpu_init();
|
||||
|
||||
/*
|
||||
* Ensure not to come back here if it wasn't intended
|
||||
*/
|
||||
|
@ -5,3 +5,4 @@
|
||||
obj-y := core.o clock.o
|
||||
obj-$(CONFIG_ARCH_VERSATILE_PB) += versatile_pb.o
|
||||
obj-$(CONFIG_MACH_VERSATILE_AB) += versatile_ab.o
|
||||
obj-$(CONFIG_PCI) += pci.o
|
||||
|
@ -196,11 +196,15 @@ static struct map_desc versatile_io_desc[] __initdata = {
|
||||
#ifdef CONFIG_DEBUG_LL
|
||||
{ IO_ADDRESS(VERSATILE_UART0_BASE), VERSATILE_UART0_BASE, SZ_4K, MT_DEVICE },
|
||||
#endif
|
||||
#ifdef FIXME
|
||||
{ PCI_MEMORY_VADDR, PHYS_PCI_MEM_BASE, SZ_16M, MT_DEVICE },
|
||||
{ PCI_CONFIG_VADDR, PHYS_PCI_CONFIG_BASE, SZ_16M, MT_DEVICE },
|
||||
{ PCI_V3_VADDR, PHYS_PCI_V3_BASE, SZ_512K, MT_DEVICE },
|
||||
{ PCI_IO_VADDR, PHYS_PCI_IO_BASE, SZ_64K, MT_DEVICE },
|
||||
#ifdef CONFIG_PCI
|
||||
{ IO_ADDRESS(VERSATILE_PCI_CORE_BASE), VERSATILE_PCI_CORE_BASE, SZ_4K, MT_DEVICE },
|
||||
{ VERSATILE_PCI_VIRT_BASE, VERSATILE_PCI_BASE, VERSATILE_PCI_BASE_SIZE, MT_DEVICE },
|
||||
{ VERSATILE_PCI_CFG_VIRT_BASE, VERSATILE_PCI_CFG_BASE, VERSATILE_PCI_CFG_BASE_SIZE, MT_DEVICE },
|
||||
#if 0
|
||||
{ VERSATILE_PCI_VIRT_MEM_BASE0, VERSATILE_PCI_MEM_BASE0, SZ_16M, MT_DEVICE },
|
||||
{ VERSATILE_PCI_VIRT_MEM_BASE1, VERSATILE_PCI_MEM_BASE1, SZ_16M, MT_DEVICE },
|
||||
{ VERSATILE_PCI_VIRT_MEM_BASE2, VERSATILE_PCI_MEM_BASE2, SZ_16M, MT_DEVICE },
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -543,7 +547,7 @@ static void versatile_clcd_enable(struct clcd_fb *fb)
|
||||
val |= SYS_CLCD_MODE_5551;
|
||||
break;
|
||||
case 6:
|
||||
val |= SYS_CLCD_MODE_565_BLSB;
|
||||
val |= SYS_CLCD_MODE_565_RLSB;
|
||||
break;
|
||||
case 8:
|
||||
val |= SYS_CLCD_MODE_888;
|
||||
|
360
arch/arm/mach-versatile/pci.c
Normal file
360
arch/arm/mach-versatile/pci.c
Normal file
@ -0,0 +1,360 @@
|
||||
/*
|
||||
* linux/arch/arm/mach-versatile/pci.c
|
||||
*
|
||||
* (C) Copyright Koninklijke Philips Electronics NV 2004. All rights reserved.
|
||||
* You can redistribute and/or modify this software under the terms of version 2
|
||||
* of the GNU General Public License as published by the Free Software Foundation.
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS" 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.
|
||||
* Koninklijke Philips Electronics nor its subsidiaries is obligated to provide any support for this software.
|
||||
*
|
||||
* ARM Versatile PCI driver.
|
||||
*
|
||||
* 14/04/2005 Initial version, colin.king@philips.com
|
||||
*
|
||||
*/
|
||||
#include <linux/config.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/mach/pci.h>
|
||||
#include <asm/mach-types.h>
|
||||
|
||||
/*
|
||||
* these spaces are mapped using the following base registers:
|
||||
*
|
||||
* Usage Local Bus Memory Base/Map registers used
|
||||
*
|
||||
* Mem 50000000 - 5FFFFFFF LB_BASE0/LB_MAP0, non prefetch
|
||||
* Mem 60000000 - 6FFFFFFF LB_BASE1/LB_MAP1, prefetch
|
||||
* IO 44000000 - 4FFFFFFF LB_BASE2/LB_MAP2, IO
|
||||
* Cfg 42000000 - 42FFFFFF PCI config
|
||||
*
|
||||
*/
|
||||
#define SYS_PCICTL IO_ADDRESS(VERSATILE_SYS_PCICTL)
|
||||
#define PCI_IMAP0 IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x0)
|
||||
#define PCI_IMAP1 IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x4)
|
||||
#define PCI_IMAP2 IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x8)
|
||||
#define PCI_SMAP0 IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x10)
|
||||
#define PCI_SMAP1 IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x14)
|
||||
#define PCI_SMAP2 IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x18)
|
||||
#define PCI_SELFID IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0xc)
|
||||
|
||||
#define DEVICE_ID_OFFSET 0x00
|
||||
#define CSR_OFFSET 0x04
|
||||
#define CLASS_ID_OFFSET 0x08
|
||||
|
||||
#define VP_PCI_DEVICE_ID 0x030010ee
|
||||
#define VP_PCI_CLASS_ID 0x0b400000
|
||||
|
||||
static unsigned long pci_slot_ignore = 0;
|
||||
|
||||
static int __init versatile_pci_slot_ignore(char *str)
|
||||
{
|
||||
int retval;
|
||||
int slot;
|
||||
|
||||
while ((retval = get_option(&str,&slot))) {
|
||||
if ((slot < 0) || (slot > 31)) {
|
||||
printk("Illegal slot value: %d\n",slot);
|
||||
} else {
|
||||
pci_slot_ignore |= (1 << slot);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
__setup("pci_slot_ignore=", versatile_pci_slot_ignore);
|
||||
|
||||
|
||||
static unsigned long __pci_addr(struct pci_bus *bus,
|
||||
unsigned int devfn, int offset)
|
||||
{
|
||||
unsigned int busnr = bus->number;
|
||||
|
||||
/*
|
||||
* Trap out illegal values
|
||||
*/
|
||||
if (offset > 255)
|
||||
BUG();
|
||||
if (busnr > 255)
|
||||
BUG();
|
||||
if (devfn > 255)
|
||||
BUG();
|
||||
|
||||
return (VERSATILE_PCI_CFG_VIRT_BASE | (busnr << 16) |
|
||||
(PCI_SLOT(devfn) << 11) | (PCI_FUNC(devfn) << 8) | offset);
|
||||
}
|
||||
|
||||
static int versatile_read_config(struct pci_bus *bus, unsigned int devfn, int where,
|
||||
int size, u32 *val)
|
||||
{
|
||||
unsigned long addr = __pci_addr(bus, devfn, where);
|
||||
u32 v;
|
||||
int slot = PCI_SLOT(devfn);
|
||||
|
||||
if (pci_slot_ignore & (1 << slot)) {
|
||||
/* Ignore this slot */
|
||||
switch (size) {
|
||||
case 1:
|
||||
v = 0xff;
|
||||
break;
|
||||
case 2:
|
||||
v = 0xffff;
|
||||
break;
|
||||
default:
|
||||
v = 0xffffffff;
|
||||
}
|
||||
} else {
|
||||
switch (size) {
|
||||
case 1:
|
||||
addr &= ~3;
|
||||
v = __raw_readb(addr);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
v = __raw_readl(addr & ~3);
|
||||
if (addr & 2) v >>= 16;
|
||||
v &= 0xffff;
|
||||
break;
|
||||
|
||||
default:
|
||||
addr &= ~3;
|
||||
v = __raw_readl(addr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*val = v;
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
static int versatile_write_config(struct pci_bus *bus, unsigned int devfn, int where,
|
||||
int size, u32 val)
|
||||
{
|
||||
unsigned long addr = __pci_addr(bus, devfn, where);
|
||||
int slot = PCI_SLOT(devfn);
|
||||
|
||||
if (pci_slot_ignore & (1 << slot)) {
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
switch (size) {
|
||||
case 1:
|
||||
__raw_writeb((u8)val, addr);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
__raw_writew((u16)val, addr);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
__raw_writel(val, addr);
|
||||
break;
|
||||
}
|
||||
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
static struct pci_ops pci_versatile_ops = {
|
||||
.read = versatile_read_config,
|
||||
.write = versatile_write_config,
|
||||
};
|
||||
|
||||
static struct resource io_mem = {
|
||||
.name = "PCI I/O space",
|
||||
.start = VERSATILE_PCI_MEM_BASE0,
|
||||
.end = VERSATILE_PCI_MEM_BASE0+VERSATILE_PCI_MEM_BASE0_SIZE-1,
|
||||
.flags = IORESOURCE_IO,
|
||||
};
|
||||
|
||||
static struct resource non_mem = {
|
||||
.name = "PCI non-prefetchable",
|
||||
.start = VERSATILE_PCI_MEM_BASE1,
|
||||
.end = VERSATILE_PCI_MEM_BASE1+VERSATILE_PCI_MEM_BASE1_SIZE-1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
};
|
||||
|
||||
static struct resource pre_mem = {
|
||||
.name = "PCI prefetchable",
|
||||
.start = VERSATILE_PCI_MEM_BASE2,
|
||||
.end = VERSATILE_PCI_MEM_BASE2+VERSATILE_PCI_MEM_BASE2_SIZE-1,
|
||||
.flags = IORESOURCE_MEM | IORESOURCE_PREFETCH,
|
||||
};
|
||||
|
||||
static int __init pci_versatile_setup_resources(struct resource **resource)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = request_resource(&iomem_resource, &io_mem);
|
||||
if (ret) {
|
||||
printk(KERN_ERR "PCI: unable to allocate I/O "
|
||||
"memory region (%d)\n", ret);
|
||||
goto out;
|
||||
}
|
||||
ret = request_resource(&iomem_resource, &non_mem);
|
||||
if (ret) {
|
||||
printk(KERN_ERR "PCI: unable to allocate non-prefetchable "
|
||||
"memory region (%d)\n", ret);
|
||||
goto release_io_mem;
|
||||
}
|
||||
ret = request_resource(&iomem_resource, &pre_mem);
|
||||
if (ret) {
|
||||
printk(KERN_ERR "PCI: unable to allocate prefetchable "
|
||||
"memory region (%d)\n", ret);
|
||||
goto release_non_mem;
|
||||
}
|
||||
|
||||
/*
|
||||
* bus->resource[0] is the IO resource for this bus
|
||||
* bus->resource[1] is the mem resource for this bus
|
||||
* bus->resource[2] is the prefetch mem resource for this bus
|
||||
*/
|
||||
resource[0] = &io_mem;
|
||||
resource[1] = &non_mem;
|
||||
resource[2] = &pre_mem;
|
||||
|
||||
goto out;
|
||||
|
||||
release_non_mem:
|
||||
release_resource(&non_mem);
|
||||
release_io_mem:
|
||||
release_resource(&io_mem);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int __init pci_versatile_setup(int nr, struct pci_sys_data *sys)
|
||||
{
|
||||
int ret = 0;
|
||||
int i;
|
||||
int myslot = -1;
|
||||
unsigned long val;
|
||||
|
||||
if (nr == 0) {
|
||||
sys->mem_offset = 0;
|
||||
ret = pci_versatile_setup_resources(sys->resource);
|
||||
if (ret < 0) {
|
||||
printk("pci_versatile_setup: resources... oops?\n");
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
printk("pci_versatile_setup: resources... nr == 0??\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
__raw_writel(VERSATILE_PCI_MEM_BASE0 >> 28,PCI_IMAP0);
|
||||
__raw_writel(VERSATILE_PCI_MEM_BASE1 >> 28,PCI_IMAP1);
|
||||
__raw_writel(VERSATILE_PCI_MEM_BASE2 >> 28,PCI_IMAP2);
|
||||
|
||||
__raw_writel(1, SYS_PCICTL);
|
||||
|
||||
val = __raw_readl(SYS_PCICTL);
|
||||
if (!(val & 1)) {
|
||||
printk("Not plugged into PCI backplane!\n");
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* We need to discover the PCI core first to configure itself
|
||||
* before the main PCI probing is performed
|
||||
*/
|
||||
for (i=0; i<32; i++) {
|
||||
if ((__raw_readl(VERSATILE_PCI_VIRT_BASE+(i<<11)+DEVICE_ID_OFFSET) == VP_PCI_DEVICE_ID) &&
|
||||
(__raw_readl(VERSATILE_PCI_VIRT_BASE+(i<<11)+CLASS_ID_OFFSET) == VP_PCI_CLASS_ID)) {
|
||||
myslot = i;
|
||||
|
||||
__raw_writel(myslot, PCI_SELFID);
|
||||
val = __raw_readl(VERSATILE_PCI_CFG_VIRT_BASE+(myslot<<11)+CSR_OFFSET);
|
||||
val |= (1<<2);
|
||||
__raw_writel(val, VERSATILE_PCI_CFG_VIRT_BASE+(myslot<<11)+CSR_OFFSET);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (myslot == -1) {
|
||||
printk("Cannot find PCI core!\n");
|
||||
ret = -EIO;
|
||||
} else {
|
||||
printk("PCI core found (slot %d)\n",myslot);
|
||||
/* Do not to map Versatile FPGA PCI device
|
||||
into memory space as we are short of
|
||||
mappable memory */
|
||||
pci_slot_ignore |= (1 << myslot);
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
struct pci_bus *pci_versatile_scan_bus(int nr, struct pci_sys_data *sys)
|
||||
{
|
||||
return pci_scan_bus(sys->busnr, &pci_versatile_ops, sys);
|
||||
}
|
||||
|
||||
/*
|
||||
* V3_LB_BASE? - local bus address
|
||||
* V3_LB_MAP? - pci bus address
|
||||
*/
|
||||
void __init pci_versatile_preinit(void)
|
||||
{
|
||||
}
|
||||
|
||||
void __init pci_versatile_postinit(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* map the specified device/slot/pin to an IRQ. Different backplanes may need to modify this.
|
||||
*/
|
||||
static int __init versatile_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
|
||||
{
|
||||
int irq;
|
||||
int devslot = PCI_SLOT(dev->devfn);
|
||||
|
||||
/* slot, pin, irq
|
||||
24 1 27
|
||||
25 1 28 untested
|
||||
26 1 29
|
||||
27 1 30 untested
|
||||
*/
|
||||
|
||||
irq = 27 + ((slot + pin + 2) % 3); /* Fudged */
|
||||
|
||||
printk("map irq: slot %d, pin %d, devslot %d, irq: %d\n",slot,pin,devslot,irq);
|
||||
|
||||
return irq;
|
||||
}
|
||||
|
||||
static struct hw_pci versatile_pci __initdata = {
|
||||
.swizzle = NULL,
|
||||
.map_irq = versatile_map_irq,
|
||||
.nr_controllers = 1,
|
||||
.setup = pci_versatile_setup,
|
||||
.scan = pci_versatile_scan_bus,
|
||||
.preinit = pci_versatile_preinit,
|
||||
.postinit = pci_versatile_postinit,
|
||||
};
|
||||
|
||||
static int __init versatile_pci_init(void)
|
||||
{
|
||||
pci_common_init(&versatile_pci);
|
||||
return 0;
|
||||
}
|
||||
|
||||
subsys_initcall(versatile_pci_init);
|
@ -62,7 +62,7 @@ config CPU_ARM720T
|
||||
# ARM920T
|
||||
config CPU_ARM920T
|
||||
bool "Support ARM920T processor" if !ARCH_S3C2410
|
||||
depends on ARCH_INTEGRATOR || ARCH_S3C2410 || ARCH_IMX
|
||||
depends on ARCH_INTEGRATOR || ARCH_S3C2410 || ARCH_IMX || ARCH_AAEC2000
|
||||
default y if ARCH_S3C2410
|
||||
select CPU_32v4
|
||||
select CPU_ABRT_EV4T
|
||||
@ -228,7 +228,6 @@ config CPU_SA1100
|
||||
select CPU_CACHE_V4WB
|
||||
select CPU_CACHE_VIVT
|
||||
select CPU_TLB_V4WB
|
||||
select CPU_MINICACHE
|
||||
|
||||
# XScale
|
||||
config CPU_XSCALE
|
||||
@ -239,7 +238,6 @@ config CPU_XSCALE
|
||||
select CPU_ABRT_EV5T
|
||||
select CPU_CACHE_VIVT
|
||||
select CPU_TLB_V4WBI
|
||||
select CPU_MINICACHE
|
||||
|
||||
# ARMv6
|
||||
config CPU_V6
|
||||
@ -345,11 +343,6 @@ config CPU_TLB_V4WBI
|
||||
config CPU_TLB_V6
|
||||
bool
|
||||
|
||||
config CPU_MINICACHE
|
||||
bool
|
||||
help
|
||||
Processor has a minicache.
|
||||
|
||||
comment "Processor Features"
|
||||
|
||||
config ARM_THUMB
|
||||
@ -429,3 +422,11 @@ config HAS_TLS_REG
|
||||
assume directly accessing that register and always obtain the
|
||||
expected value only on ARMv7 and above.
|
||||
|
||||
config NEEDS_SYSCALL_FOR_CMPXCHG
|
||||
bool
|
||||
default y if SMP && (CPU_32v5 || CPU_32v4 || CPU_32v3)
|
||||
help
|
||||
SMP on a pre-ARMv6 processor? Well OK then.
|
||||
Forget about fast user space cmpxchg support.
|
||||
It is just not possible.
|
||||
|
||||
|
@ -31,8 +31,6 @@ obj-$(CONFIG_CPU_COPY_V6) += copypage-v6.o mmu.o
|
||||
obj-$(CONFIG_CPU_SA1100) += copypage-v4mc.o
|
||||
obj-$(CONFIG_CPU_XSCALE) += copypage-xscale.o
|
||||
|
||||
obj-$(CONFIG_CPU_MINICACHE) += minicache.o
|
||||
|
||||
obj-$(CONFIG_CPU_TLB_V3) += tlb-v3.o
|
||||
obj-$(CONFIG_CPU_TLB_V4WT) += tlb-v4.o
|
||||
obj-$(CONFIG_CPU_TLB_V4WB) += tlb-v4wb.o
|
||||
|
@ -30,8 +30,6 @@
|
||||
|
||||
static DEFINE_SPINLOCK(v6_lock);
|
||||
|
||||
#define DCACHE_COLOUR(vaddr) ((vaddr & (SHMLBA - 1)) >> PAGE_SHIFT)
|
||||
|
||||
/*
|
||||
* Copy the user page. No aliasing to deal with so we can just
|
||||
* attack the kernel's existing mapping of these pages.
|
||||
@ -55,7 +53,7 @@ void v6_clear_user_page_nonaliasing(void *kaddr, unsigned long vaddr)
|
||||
*/
|
||||
void v6_copy_user_page_aliasing(void *kto, const void *kfrom, unsigned long vaddr)
|
||||
{
|
||||
unsigned int offset = DCACHE_COLOUR(vaddr);
|
||||
unsigned int offset = CACHE_COLOUR(vaddr);
|
||||
unsigned long from, to;
|
||||
|
||||
/*
|
||||
@ -95,7 +93,7 @@ void v6_copy_user_page_aliasing(void *kto, const void *kfrom, unsigned long vadd
|
||||
*/
|
||||
void v6_clear_user_page_aliasing(void *kaddr, unsigned long vaddr)
|
||||
{
|
||||
unsigned int offset = DCACHE_COLOUR(vaddr);
|
||||
unsigned int offset = CACHE_COLOUR(vaddr);
|
||||
unsigned long to = to_address + (offset << PAGE_SHIFT);
|
||||
|
||||
/*
|
||||
|
@ -1,113 +0,0 @@
|
||||
/*
|
||||
* linux/arch/arm/lib/copypage-xscale.S
|
||||
*
|
||||
* Copyright (C) 2001 Russell King
|
||||
*
|
||||
* 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/linkage.h>
|
||||
#include <linux/init.h>
|
||||
#include <asm/constants.h>
|
||||
|
||||
/*
|
||||
* General note:
|
||||
* We don't really want write-allocate cache behaviour for these functions
|
||||
* since that will just eat through 8K of the cache.
|
||||
*/
|
||||
|
||||
.text
|
||||
.align 5
|
||||
/*
|
||||
* XScale optimised copy_user_page
|
||||
* r0 = destination
|
||||
* r1 = source
|
||||
* r2 = virtual user address of ultimate destination page
|
||||
*
|
||||
* The source page may have some clean entries in the cache already, but we
|
||||
* can safely ignore them - break_cow() will flush them out of the cache
|
||||
* if we eventually end up using our copied page.
|
||||
*
|
||||
* What we could do is use the mini-cache to buffer reads from the source
|
||||
* page. We rely on the mini-cache being smaller than one page, so we'll
|
||||
* cycle through the complete cache anyway.
|
||||
*/
|
||||
ENTRY(xscale_mc_copy_user_page)
|
||||
stmfd sp!, {r4, r5, lr}
|
||||
mov r5, r0
|
||||
mov r0, r1
|
||||
bl map_page_minicache
|
||||
mov r1, r5
|
||||
mov lr, #PAGE_SZ/64-1
|
||||
|
||||
/*
|
||||
* Strangely enough, best performance is achieved
|
||||
* when prefetching destination as well. (NP)
|
||||
*/
|
||||
pld [r0, #0]
|
||||
pld [r0, #32]
|
||||
pld [r1, #0]
|
||||
pld [r1, #32]
|
||||
|
||||
1: pld [r0, #64]
|
||||
pld [r0, #96]
|
||||
pld [r1, #64]
|
||||
pld [r1, #96]
|
||||
|
||||
2: ldrd r2, [r0], #8
|
||||
ldrd r4, [r0], #8
|
||||
mov ip, r1
|
||||
strd r2, [r1], #8
|
||||
ldrd r2, [r0], #8
|
||||
strd r4, [r1], #8
|
||||
ldrd r4, [r0], #8
|
||||
strd r2, [r1], #8
|
||||
strd r4, [r1], #8
|
||||
mcr p15, 0, ip, c7, c10, 1 @ clean D line
|
||||
ldrd r2, [r0], #8
|
||||
mcr p15, 0, ip, c7, c6, 1 @ invalidate D line
|
||||
ldrd r4, [r0], #8
|
||||
mov ip, r1
|
||||
strd r2, [r1], #8
|
||||
ldrd r2, [r0], #8
|
||||
strd r4, [r1], #8
|
||||
ldrd r4, [r0], #8
|
||||
strd r2, [r1], #8
|
||||
strd r4, [r1], #8
|
||||
mcr p15, 0, ip, c7, c10, 1 @ clean D line
|
||||
subs lr, lr, #1
|
||||
mcr p15, 0, ip, c7, c6, 1 @ invalidate D line
|
||||
bgt 1b
|
||||
beq 2b
|
||||
|
||||
ldmfd sp!, {r4, r5, pc}
|
||||
|
||||
.align 5
|
||||
/*
|
||||
* XScale optimised clear_user_page
|
||||
* r0 = destination
|
||||
* r1 = virtual user address of ultimate destination page
|
||||
*/
|
||||
ENTRY(xscale_mc_clear_user_page)
|
||||
mov r1, #PAGE_SZ/32
|
||||
mov r2, #0
|
||||
mov r3, #0
|
||||
1: mov ip, r0
|
||||
strd r2, [r0], #8
|
||||
strd r2, [r0], #8
|
||||
strd r2, [r0], #8
|
||||
strd r2, [r0], #8
|
||||
mcr p15, 0, ip, c7, c10, 1 @ clean D line
|
||||
subs r1, r1, #1
|
||||
mcr p15, 0, ip, c7, c6, 1 @ invalidate D line
|
||||
bne 1b
|
||||
mov pc, lr
|
||||
|
||||
__INITDATA
|
||||
|
||||
.type xscale_mc_user_fns, #object
|
||||
ENTRY(xscale_mc_user_fns)
|
||||
.long xscale_mc_clear_user_page
|
||||
.long xscale_mc_copy_user_page
|
||||
.size xscale_mc_user_fns, . - xscale_mc_user_fns
|
131
arch/arm/mm/copypage-xscale.c
Normal file
131
arch/arm/mm/copypage-xscale.c
Normal file
@ -0,0 +1,131 @@
|
||||
/*
|
||||
* linux/arch/arm/lib/copypage-xscale.S
|
||||
*
|
||||
* Copyright (C) 1995-2005 Russell King
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This handles the mini data cache, as found on SA11x0 and XScale
|
||||
* processors. When we copy a user page page, we map it in such a way
|
||||
* that accesses to this page will not touch the main data cache, but
|
||||
* will be cached in the mini data cache. This prevents us thrashing
|
||||
* the main data cache on page faults.
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/mm.h>
|
||||
|
||||
#include <asm/page.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/tlbflush.h>
|
||||
|
||||
/*
|
||||
* 0xffff8000 to 0xffffffff is reserved for any ARM architecture
|
||||
* specific hacks for copying pages efficiently.
|
||||
*/
|
||||
#define COPYPAGE_MINICACHE 0xffff8000
|
||||
|
||||
#define minicache_pgprot __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | \
|
||||
L_PTE_CACHEABLE)
|
||||
|
||||
#define TOP_PTE(x) pte_offset_kernel(top_pmd, x)
|
||||
|
||||
static DEFINE_SPINLOCK(minicache_lock);
|
||||
|
||||
/*
|
||||
* XScale mini-dcache optimised copy_user_page
|
||||
*
|
||||
* We flush the destination cache lines just before we write the data into the
|
||||
* corresponding address. Since the Dcache is read-allocate, this removes the
|
||||
* Dcache aliasing issue. The writes will be forwarded to the write buffer,
|
||||
* and merged as appropriate.
|
||||
*/
|
||||
static void __attribute__((naked))
|
||||
mc_copy_user_page(void *from, void *to)
|
||||
{
|
||||
/*
|
||||
* Strangely enough, best performance is achieved
|
||||
* when prefetching destination as well. (NP)
|
||||
*/
|
||||
asm volatile(
|
||||
"stmfd sp!, {r4, r5, lr} \n\
|
||||
mov lr, %2 \n\
|
||||
pld [r0, #0] \n\
|
||||
pld [r0, #32] \n\
|
||||
pld [r1, #0] \n\
|
||||
pld [r1, #32] \n\
|
||||
1: pld [r0, #64] \n\
|
||||
pld [r0, #96] \n\
|
||||
pld [r1, #64] \n\
|
||||
pld [r1, #96] \n\
|
||||
2: ldrd r2, [r0], #8 \n\
|
||||
ldrd r4, [r0], #8 \n\
|
||||
mov ip, r1 \n\
|
||||
strd r2, [r1], #8 \n\
|
||||
ldrd r2, [r0], #8 \n\
|
||||
strd r4, [r1], #8 \n\
|
||||
ldrd r4, [r0], #8 \n\
|
||||
strd r2, [r1], #8 \n\
|
||||
strd r4, [r1], #8 \n\
|
||||
mcr p15, 0, ip, c7, c10, 1 @ clean D line\n\
|
||||
ldrd r2, [r0], #8 \n\
|
||||
mcr p15, 0, ip, c7, c6, 1 @ invalidate D line\n\
|
||||
ldrd r4, [r0], #8 \n\
|
||||
mov ip, r1 \n\
|
||||
strd r2, [r1], #8 \n\
|
||||
ldrd r2, [r0], #8 \n\
|
||||
strd r4, [r1], #8 \n\
|
||||
ldrd r4, [r0], #8 \n\
|
||||
strd r2, [r1], #8 \n\
|
||||
strd r4, [r1], #8 \n\
|
||||
mcr p15, 0, ip, c7, c10, 1 @ clean D line\n\
|
||||
subs lr, lr, #1 \n\
|
||||
mcr p15, 0, ip, c7, c6, 1 @ invalidate D line\n\
|
||||
bgt 1b \n\
|
||||
beq 2b \n\
|
||||
ldmfd sp!, {r4, r5, pc} "
|
||||
:
|
||||
: "r" (from), "r" (to), "I" (PAGE_SIZE / 64 - 1));
|
||||
}
|
||||
|
||||
void xscale_mc_copy_user_page(void *kto, const void *kfrom, unsigned long vaddr)
|
||||
{
|
||||
spin_lock(&minicache_lock);
|
||||
|
||||
set_pte(TOP_PTE(COPYPAGE_MINICACHE), pfn_pte(__pa(kfrom) >> PAGE_SHIFT, minicache_pgprot));
|
||||
flush_tlb_kernel_page(COPYPAGE_MINICACHE);
|
||||
|
||||
mc_copy_user_page((void *)COPYPAGE_MINICACHE, kto);
|
||||
|
||||
spin_unlock(&minicache_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* XScale optimised clear_user_page
|
||||
*/
|
||||
void __attribute__((naked))
|
||||
xscale_mc_clear_user_page(void *kaddr, unsigned long vaddr)
|
||||
{
|
||||
asm volatile(
|
||||
"mov r1, %0 \n\
|
||||
mov r2, #0 \n\
|
||||
mov r3, #0 \n\
|
||||
1: mov ip, r0 \n\
|
||||
strd r2, [r0], #8 \n\
|
||||
strd r2, [r0], #8 \n\
|
||||
strd r2, [r0], #8 \n\
|
||||
strd r2, [r0], #8 \n\
|
||||
mcr p15, 0, ip, c7, c10, 1 @ clean D line\n\
|
||||
subs r1, r1, #1 \n\
|
||||
mcr p15, 0, ip, c7, c6, 1 @ invalidate D line\n\
|
||||
bne 1b \n\
|
||||
mov pc, lr"
|
||||
:
|
||||
: "I" (PAGE_SIZE / 32));
|
||||
}
|
||||
|
||||
struct cpu_user_fns xscale_mc_user_fns __initdata = {
|
||||
.cpu_clear_user_page = xscale_mc_clear_user_page,
|
||||
.cpu_copy_user_page = xscale_mc_copy_user_page,
|
||||
};
|
@ -77,9 +77,8 @@ no_pmd:
|
||||
}
|
||||
|
||||
static void
|
||||
make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page, int dirty)
|
||||
make_coherent(struct address_space *mapping, struct vm_area_struct *vma, unsigned long addr, unsigned long pfn)
|
||||
{
|
||||
struct address_space *mapping = page_mapping(page);
|
||||
struct mm_struct *mm = vma->vm_mm;
|
||||
struct vm_area_struct *mpnt;
|
||||
struct prio_tree_iter iter;
|
||||
@ -87,9 +86,6 @@ make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page,
|
||||
pgoff_t pgoff;
|
||||
int aliases = 0;
|
||||
|
||||
if (!mapping)
|
||||
return;
|
||||
|
||||
pgoff = vma->vm_pgoff + ((addr - vma->vm_start) >> PAGE_SHIFT);
|
||||
|
||||
/*
|
||||
@ -115,9 +111,11 @@ make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page,
|
||||
if (aliases)
|
||||
adjust_pte(vma, addr);
|
||||
else
|
||||
flush_cache_page(vma, addr, page_to_pfn(page));
|
||||
flush_cache_page(vma, addr, pfn);
|
||||
}
|
||||
|
||||
void __flush_dcache_page(struct address_space *mapping, struct page *page);
|
||||
|
||||
/*
|
||||
* Take care of architecture specific things when placing a new PTE into
|
||||
* a page table, or changing an existing PTE. Basically, there are two
|
||||
@ -134,29 +132,22 @@ make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page,
|
||||
void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte_t pte)
|
||||
{
|
||||
unsigned long pfn = pte_pfn(pte);
|
||||
struct address_space *mapping;
|
||||
struct page *page;
|
||||
|
||||
if (!pfn_valid(pfn))
|
||||
return;
|
||||
|
||||
page = pfn_to_page(pfn);
|
||||
if (page_mapping(page)) {
|
||||
mapping = page_mapping(page);
|
||||
if (mapping) {
|
||||
int dirty = test_and_clear_bit(PG_dcache_dirty, &page->flags);
|
||||
|
||||
if (dirty) {
|
||||
/*
|
||||
* This is our first userspace mapping of this page.
|
||||
* Ensure that the physical page is coherent with
|
||||
* the kernel mapping.
|
||||
*
|
||||
* FIXME: only need to do this on VIVT and aliasing
|
||||
* VIPT cache architectures. We can do that
|
||||
* by choosing whether to set this bit...
|
||||
*/
|
||||
__cpuc_flush_dcache_page(page_address(page));
|
||||
}
|
||||
if (dirty)
|
||||
__flush_dcache_page(mapping, page);
|
||||
|
||||
if (cache_is_vivt())
|
||||
make_coherent(vma, addr, page, dirty);
|
||||
make_coherent(mapping, vma, addr, pfn);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,13 +37,8 @@ static void flush_pfn_alias(unsigned long pfn, unsigned long vaddr)
|
||||
#define flush_pfn_alias(pfn,vaddr) do { } while (0)
|
||||
#endif
|
||||
|
||||
static void __flush_dcache_page(struct address_space *mapping, struct page *page)
|
||||
void __flush_dcache_page(struct address_space *mapping, struct page *page)
|
||||
{
|
||||
struct mm_struct *mm = current->active_mm;
|
||||
struct vm_area_struct *mpnt;
|
||||
struct prio_tree_iter iter;
|
||||
pgoff_t pgoff;
|
||||
|
||||
/*
|
||||
* Writeback any data associated with the kernel mapping of this
|
||||
* page. This ensures that data in the physical page is mutually
|
||||
@ -52,24 +47,21 @@ static void __flush_dcache_page(struct address_space *mapping, struct page *page
|
||||
__cpuc_flush_dcache_page(page_address(page));
|
||||
|
||||
/*
|
||||
* If there's no mapping pointer here, then this page isn't
|
||||
* visible to userspace yet, so there are no cache lines
|
||||
* associated with any other aliases.
|
||||
*/
|
||||
if (!mapping)
|
||||
return;
|
||||
|
||||
/*
|
||||
* This is a page cache page. If we have a VIPT cache, we
|
||||
* only need to do one flush - which would be at the relevant
|
||||
* If this is a page cache page, and we have an aliasing VIPT cache,
|
||||
* we only need to do one flush - which would be at the relevant
|
||||
* userspace colour, which is congruent with page->index.
|
||||
*/
|
||||
if (cache_is_vipt()) {
|
||||
if (cache_is_vipt_aliasing())
|
||||
flush_pfn_alias(page_to_pfn(page),
|
||||
page->index << PAGE_CACHE_SHIFT);
|
||||
return;
|
||||
}
|
||||
if (mapping && cache_is_vipt_aliasing())
|
||||
flush_pfn_alias(page_to_pfn(page),
|
||||
page->index << PAGE_CACHE_SHIFT);
|
||||
}
|
||||
|
||||
static void __flush_dcache_aliases(struct address_space *mapping, struct page *page)
|
||||
{
|
||||
struct mm_struct *mm = current->active_mm;
|
||||
struct vm_area_struct *mpnt;
|
||||
struct prio_tree_iter iter;
|
||||
pgoff_t pgoff;
|
||||
|
||||
/*
|
||||
* There are possible user space mappings of this page:
|
||||
@ -116,12 +108,12 @@ void flush_dcache_page(struct page *page)
|
||||
{
|
||||
struct address_space *mapping = page_mapping(page);
|
||||
|
||||
if (cache_is_vipt_nonaliasing())
|
||||
return;
|
||||
|
||||
if (mapping && !mapping_mapped(mapping))
|
||||
set_bit(PG_dcache_dirty, &page->flags);
|
||||
else
|
||||
else {
|
||||
__flush_dcache_page(mapping, page);
|
||||
if (mapping && cache_is_vivt())
|
||||
__flush_dcache_aliases(mapping, page);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(flush_dcache_page);
|
||||
|
@ -170,3 +170,50 @@ void __iounmap(void __iomem *addr)
|
||||
vfree((void *) (PAGE_MASK & (unsigned long) addr));
|
||||
}
|
||||
EXPORT_SYMBOL(__iounmap);
|
||||
|
||||
#ifdef __io
|
||||
void __iomem *ioport_map(unsigned long port, unsigned int nr)
|
||||
{
|
||||
return __io(port);
|
||||
}
|
||||
EXPORT_SYMBOL(ioport_map);
|
||||
|
||||
void ioport_unmap(void __iomem *addr)
|
||||
{
|
||||
}
|
||||
EXPORT_SYMBOL(ioport_unmap);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
#include <linux/pci.h>
|
||||
#include <linux/ioport.h>
|
||||
|
||||
void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
|
||||
{
|
||||
unsigned long start = pci_resource_start(dev, bar);
|
||||
unsigned long len = pci_resource_len(dev, bar);
|
||||
unsigned long flags = pci_resource_flags(dev, bar);
|
||||
|
||||
if (!len || !start)
|
||||
return NULL;
|
||||
if (maxlen && len > maxlen)
|
||||
len = maxlen;
|
||||
if (flags & IORESOURCE_IO)
|
||||
return ioport_map(start, len);
|
||||
if (flags & IORESOURCE_MEM) {
|
||||
if (flags & IORESOURCE_CACHEABLE)
|
||||
return ioremap(start, len);
|
||||
return ioremap_nocache(start, len);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(pci_iomap);
|
||||
|
||||
void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
|
||||
{
|
||||
if ((unsigned long)addr >= VMALLOC_START &&
|
||||
(unsigned long)addr < VMALLOC_END)
|
||||
iounmap(addr);
|
||||
}
|
||||
EXPORT_SYMBOL(pci_iounmap);
|
||||
#endif
|
||||
|
@ -1,73 +0,0 @@
|
||||
/*
|
||||
* linux/arch/arm/mm/minicache.c
|
||||
*
|
||||
* Copyright (C) 2001 Russell King
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This handles the mini data cache, as found on SA11x0 and XScale
|
||||
* processors. When we copy a user page page, we map it in such a way
|
||||
* that accesses to this page will not touch the main data cache, but
|
||||
* will be cached in the mini data cache. This prevents us thrashing
|
||||
* the main data cache on page faults.
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/mm.h>
|
||||
|
||||
#include <asm/page.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/tlbflush.h>
|
||||
|
||||
/*
|
||||
* 0xffff8000 to 0xffffffff is reserved for any ARM architecture
|
||||
* specific hacks for copying pages efficiently.
|
||||
*/
|
||||
#define minicache_address (0xffff8000)
|
||||
#define minicache_pgprot __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | \
|
||||
L_PTE_CACHEABLE)
|
||||
|
||||
static pte_t *minicache_pte;
|
||||
|
||||
/*
|
||||
* Note that this is intended to be called only from the copy_user_page
|
||||
* asm code; anything else will require special locking to prevent the
|
||||
* mini-cache space being re-used. (Note: probably preempt unsafe).
|
||||
*
|
||||
* We rely on the fact that the minicache is 2K, and we'll be pushing
|
||||
* 4K of data through it, so we don't actually have to specifically
|
||||
* flush the minicache when we change the mapping.
|
||||
*
|
||||
* Note also: assert(PAGE_OFFSET <= virt < high_memory).
|
||||
* Unsafe: preempt, kmap.
|
||||
*/
|
||||
unsigned long map_page_minicache(unsigned long virt)
|
||||
{
|
||||
set_pte(minicache_pte, pfn_pte(__pa(virt) >> PAGE_SHIFT, minicache_pgprot));
|
||||
flush_tlb_kernel_page(minicache_address);
|
||||
|
||||
return minicache_address;
|
||||
}
|
||||
|
||||
static int __init minicache_init(void)
|
||||
{
|
||||
pgd_t *pgd;
|
||||
pmd_t *pmd;
|
||||
|
||||
spin_lock(&init_mm.page_table_lock);
|
||||
|
||||
pgd = pgd_offset_k(minicache_address);
|
||||
pmd = pmd_alloc(&init_mm, pgd, minicache_address);
|
||||
if (!pmd)
|
||||
BUG();
|
||||
minicache_pte = pte_alloc_kernel(&init_mm, pmd, minicache_address);
|
||||
if (!minicache_pte)
|
||||
BUG();
|
||||
|
||||
spin_unlock(&init_mm.page_table_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
core_initcall(minicache_init);
|
@ -562,31 +562,31 @@ static void __init ecard_init_resources(struct expansion_card *ec)
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t ecard_show_irq(struct device *dev, char *buf)
|
||||
static ssize_t ecard_show_irq(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct expansion_card *ec = ECARD_DEV(dev);
|
||||
return sprintf(buf, "%u\n", ec->irq);
|
||||
}
|
||||
|
||||
static ssize_t ecard_show_vendor(struct device *dev, char *buf)
|
||||
static ssize_t ecard_show_vendor(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct expansion_card *ec = ECARD_DEV(dev);
|
||||
return sprintf(buf, "%u\n", ec->cid.manufacturer);
|
||||
}
|
||||
|
||||
static ssize_t ecard_show_device(struct device *dev, char *buf)
|
||||
static ssize_t ecard_show_device(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct expansion_card *ec = ECARD_DEV(dev);
|
||||
return sprintf(buf, "%u\n", ec->cid.product);
|
||||
}
|
||||
|
||||
static ssize_t ecard_show_dma(struct device *dev, char *buf)
|
||||
static ssize_t ecard_show_dma(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct expansion_card *ec = ECARD_DEV(dev);
|
||||
return sprintf(buf, "%u\n", ec->dma);
|
||||
}
|
||||
|
||||
static ssize_t ecard_show_resources(struct device *dev, char *buf)
|
||||
static ssize_t ecard_show_resources(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct expansion_card *ec = ECARD_DEV(dev);
|
||||
char *str = buf;
|
||||
|
@ -54,7 +54,7 @@ asmlinkage void ret_from_fork(void);
|
||||
void default_idle(void)
|
||||
{
|
||||
while(1) {
|
||||
if (need_resched()) {
|
||||
if (!need_resched()) {
|
||||
local_irq_enable();
|
||||
__asm__("sleep");
|
||||
local_irq_disable();
|
||||
|
@ -43,7 +43,7 @@ obj-$(CONFIG_SCx200) += scx200.o
|
||||
# Note: kbuild does not track this dependency due to usage of .incbin
|
||||
$(obj)/vsyscall.o: $(obj)/vsyscall-int80.so $(obj)/vsyscall-sysenter.so
|
||||
targets += $(foreach F,int80 sysenter,vsyscall-$F.o vsyscall-$F.so)
|
||||
targets += vsyscall.lds
|
||||
targets += vsyscall-note.o vsyscall.lds
|
||||
|
||||
# The DSO images are built using a special linker script.
|
||||
quiet_cmd_syscall = SYSCALL $@
|
||||
|
@ -1222,6 +1222,7 @@ static int suspend(int vetoable)
|
||||
|
||||
save_processor_state();
|
||||
err = set_system_power_state(APM_STATE_SUSPEND);
|
||||
ignore_normal_resume = 1;
|
||||
restore_processor_state();
|
||||
|
||||
local_irq_disable();
|
||||
@ -1229,7 +1230,6 @@ static int suspend(int vetoable)
|
||||
spin_lock(&i8253_lock);
|
||||
reinit_timer();
|
||||
set_time();
|
||||
ignore_normal_resume = 1;
|
||||
|
||||
spin_unlock(&i8253_lock);
|
||||
write_sequnlock(&xtime_lock);
|
||||
|
@ -23,7 +23,7 @@ config X86_ACPI_CPUFREQ
|
||||
If in doubt, say N.
|
||||
|
||||
config ELAN_CPUFREQ
|
||||
tristate "AMD Elan"
|
||||
tristate "AMD Elan SC400 and SC410"
|
||||
select CPU_FREQ_TABLE
|
||||
depends on X86_ELAN
|
||||
---help---
|
||||
@ -38,6 +38,18 @@ config ELAN_CPUFREQ
|
||||
|
||||
If in doubt, say N.
|
||||
|
||||
config SC520_CPUFREQ
|
||||
tristate "AMD Elan SC520"
|
||||
select CPU_FREQ_TABLE
|
||||
depends on X86_ELAN
|
||||
---help---
|
||||
This adds the CPUFreq driver for AMD Elan SC520 processor.
|
||||
|
||||
For details, take a look at <file:Documentation/cpu-freq/>.
|
||||
|
||||
If in doubt, say N.
|
||||
|
||||
|
||||
config X86_POWERNOW_K6
|
||||
tristate "AMD Mobile K6-2/K6-3 PowerNow!"
|
||||
select CPU_FREQ_TABLE
|
||||
|
@ -3,6 +3,7 @@ obj-$(CONFIG_X86_POWERNOW_K7) += powernow-k7.o
|
||||
obj-$(CONFIG_X86_POWERNOW_K8) += powernow-k8.o
|
||||
obj-$(CONFIG_X86_LONGHAUL) += longhaul.o
|
||||
obj-$(CONFIG_ELAN_CPUFREQ) += elanfreq.o
|
||||
obj-$(CONFIG_SC520_CPUFREQ) += sc520_freq.o
|
||||
obj-$(CONFIG_X86_LONGRUN) += longrun.o
|
||||
obj-$(CONFIG_X86_GX_SUSPMOD) += gx-suspmod.o
|
||||
obj-$(CONFIG_X86_SPEEDSTEP_ICH) += speedstep-ich.o
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include <linux/cpufreq.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
#include <asm/msr.h>
|
||||
#include <asm/timex.h>
|
||||
@ -119,7 +120,13 @@ static int longhaul_get_cpu_mult(void)
|
||||
static void do_powersaver(union msr_longhaul *longhaul,
|
||||
unsigned int clock_ratio_index)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
unsigned long flags;
|
||||
unsigned int tmp_mask;
|
||||
int version;
|
||||
int i;
|
||||
u16 pci_cmd;
|
||||
u16 cmd_state[64];
|
||||
|
||||
switch (cpu_model) {
|
||||
case CPU_EZRA_T:
|
||||
@ -137,17 +144,58 @@ static void do_powersaver(union msr_longhaul *longhaul,
|
||||
longhaul->bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
|
||||
longhaul->bits.EnableSoftBusRatio = 1;
|
||||
longhaul->bits.RevisionKey = 0;
|
||||
local_irq_disable();
|
||||
wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
|
||||
|
||||
preempt_disable();
|
||||
local_irq_save(flags);
|
||||
|
||||
/*
|
||||
* get current pci bus master state for all devices
|
||||
* and clear bus master bit
|
||||
*/
|
||||
dev = NULL;
|
||||
i = 0;
|
||||
do {
|
||||
dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
|
||||
if (dev != NULL) {
|
||||
pci_read_config_word(dev, PCI_COMMAND, &pci_cmd);
|
||||
cmd_state[i++] = pci_cmd;
|
||||
pci_cmd &= ~PCI_COMMAND_MASTER;
|
||||
pci_write_config_word(dev, PCI_COMMAND, pci_cmd);
|
||||
}
|
||||
} while (dev != NULL);
|
||||
|
||||
tmp_mask=inb(0x21); /* works on C3. save mask. */
|
||||
outb(0xFE,0x21); /* TMR0 only */
|
||||
outb(0xFF,0x80); /* delay */
|
||||
|
||||
local_irq_enable();
|
||||
|
||||
__hlt();
|
||||
wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
|
||||
__hlt();
|
||||
|
||||
local_irq_disable();
|
||||
|
||||
outb(tmp_mask,0x21); /* restore mask */
|
||||
|
||||
/* restore pci bus master state for all devices */
|
||||
dev = NULL;
|
||||
i = 0;
|
||||
do {
|
||||
dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
|
||||
if (dev != NULL) {
|
||||
pci_cmd = cmd_state[i++];
|
||||
pci_write_config_byte(dev, PCI_COMMAND, pci_cmd);
|
||||
}
|
||||
} while (dev != NULL);
|
||||
local_irq_restore(flags);
|
||||
preempt_enable();
|
||||
|
||||
/* disable bus ratio bit */
|
||||
rdmsrl(MSR_VIA_LONGHAUL, longhaul->val);
|
||||
longhaul->bits.EnableSoftBusRatio = 0;
|
||||
longhaul->bits.RevisionKey = version;
|
||||
local_irq_disable();
|
||||
wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
|
||||
local_irq_enable();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -578,7 +626,7 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
|
||||
longhaul_setup_voltagescaling();
|
||||
|
||||
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
|
||||
policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
|
||||
policy->cpuinfo.transition_latency = 200000; /* nsec */
|
||||
policy->cur = calc_speed(longhaul_get_cpu_mult());
|
||||
|
||||
ret = cpufreq_frequency_table_cpuinfo(policy, longhaul_table);
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include <linux/dmi.h>
|
||||
|
||||
#include <asm/msr.h>
|
||||
#include <asm/timer.h>
|
||||
#include <asm/timex.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/system.h>
|
||||
@ -586,13 +587,17 @@ static int __init powernow_cpu_init (struct cpufreq_policy *policy)
|
||||
|
||||
rdmsrl (MSR_K7_FID_VID_STATUS, fidvidstatus.val);
|
||||
|
||||
/* A K7 with powernow technology is set to max frequency by BIOS */
|
||||
fsb = (10 * cpu_khz) / fid_codes[fidvidstatus.bits.MFID];
|
||||
/* recalibrate cpu_khz */
|
||||
result = recalibrate_cpu_khz();
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
fsb = (10 * cpu_khz) / fid_codes[fidvidstatus.bits.CFID];
|
||||
if (!fsb) {
|
||||
printk(KERN_WARNING PFX "can not determine bus frequency\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
dprintk("FSB: %3d.%03d MHz\n", fsb/1000, fsb%1000);
|
||||
dprintk("FSB: %3dMHz\n", fsb/1000);
|
||||
|
||||
if (dmi_check_system(powernow_dmi_table) || acpi_force) {
|
||||
printk (KERN_INFO PFX "PSB/PST known to be broken. Trying ACPI instead\n");
|
||||
|
@ -4,7 +4,7 @@
|
||||
* GNU general public license version 2. See "COPYING" or
|
||||
* http://www.gnu.org/licenses/gpl.html
|
||||
*
|
||||
* Support : paul.devriendt@amd.com
|
||||
* Support : mark.langsdorf@amd.com
|
||||
*
|
||||
* Based on the powernow-k7.c module written by Dave Jones.
|
||||
* (C) 2003 Dave Jones <davej@codemonkey.org.uk> on behalf of SuSE Labs
|
||||
@ -15,12 +15,13 @@
|
||||
*
|
||||
* Valuable input gratefully received from Dave Jones, Pavel Machek,
|
||||
* Dominik Brodowski, and others.
|
||||
* Originally developed by Paul Devriendt.
|
||||
* Processor information obtained from Chapter 9 (Power and Thermal Management)
|
||||
* of the "BIOS and Kernel Developer's Guide for the AMD Athlon 64 and AMD
|
||||
* Opteron Processors" available for download from www.amd.com
|
||||
*
|
||||
* Tables for specific CPUs can be infrerred from
|
||||
* http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/30430.pdf
|
||||
* http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/30430.pdf
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
@ -30,6 +31,7 @@
|
||||
#include <linux/cpufreq.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/cpumask.h>
|
||||
|
||||
#include <asm/msr.h>
|
||||
#include <asm/io.h>
|
||||
@ -42,7 +44,7 @@
|
||||
|
||||
#define PFX "powernow-k8: "
|
||||
#define BFX PFX "BIOS error: "
|
||||
#define VERSION "version 1.00.09e"
|
||||
#define VERSION "version 1.40.2"
|
||||
#include "powernow-k8.h"
|
||||
|
||||
/* serialize freq changes */
|
||||
@ -50,6 +52,10 @@ static DECLARE_MUTEX(fidvid_sem);
|
||||
|
||||
static struct powernow_k8_data *powernow_data[NR_CPUS];
|
||||
|
||||
#ifndef CONFIG_SMP
|
||||
static cpumask_t cpu_core_map[1];
|
||||
#endif
|
||||
|
||||
/* Return a frequency in MHz, given an input fid */
|
||||
static u32 find_freq_from_fid(u32 fid)
|
||||
{
|
||||
@ -274,11 +280,18 @@ static int core_voltage_pre_transition(struct powernow_k8_data *data, u32 reqvid
|
||||
{
|
||||
u32 rvosteps = data->rvo;
|
||||
u32 savefid = data->currfid;
|
||||
u32 maxvid, lo;
|
||||
|
||||
dprintk("ph1 (cpu%d): start, currfid 0x%x, currvid 0x%x, reqvid 0x%x, rvo 0x%x\n",
|
||||
smp_processor_id(),
|
||||
data->currfid, data->currvid, reqvid, data->rvo);
|
||||
|
||||
rdmsr(MSR_FIDVID_STATUS, lo, maxvid);
|
||||
maxvid = 0x1f & (maxvid >> 16);
|
||||
dprintk("ph1 maxvid=0x%x\n", maxvid);
|
||||
if (reqvid < maxvid) /* lower numbers are higher voltages */
|
||||
reqvid = maxvid;
|
||||
|
||||
while (data->currvid > reqvid) {
|
||||
dprintk("ph1: curr 0x%x, req vid 0x%x\n",
|
||||
data->currvid, reqvid);
|
||||
@ -286,8 +299,8 @@ static int core_voltage_pre_transition(struct powernow_k8_data *data, u32 reqvid
|
||||
return 1;
|
||||
}
|
||||
|
||||
while ((rvosteps > 0) && ((data->rvo + data->currvid) > reqvid)) {
|
||||
if (data->currvid == 0) {
|
||||
while ((rvosteps > 0) && ((data->rvo + data->currvid) > reqvid)) {
|
||||
if (data->currvid == maxvid) {
|
||||
rvosteps = 0;
|
||||
} else {
|
||||
dprintk("ph1: changing vid for rvo, req 0x%x\n",
|
||||
@ -671,7 +684,7 @@ static int find_psb_table(struct powernow_k8_data *data)
|
||||
* BIOS and Kernel Developer's Guide, which is available on
|
||||
* www.amd.com
|
||||
*/
|
||||
printk(KERN_ERR PFX "BIOS error - no PSB\n");
|
||||
printk(KERN_INFO PFX "BIOS error - no PSB or ACPI _PSS objects\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
@ -695,7 +708,7 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
|
||||
struct cpufreq_frequency_table *powernow_table;
|
||||
|
||||
if (acpi_processor_register_performance(&data->acpi_data, data->cpu)) {
|
||||
dprintk("register performance failed\n");
|
||||
dprintk("register performance failed: bad ACPI data\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@ -746,22 +759,23 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fid < HI_FID_TABLE_BOTTOM) {
|
||||
if (cntlofreq) {
|
||||
/* if both entries are the same, ignore this
|
||||
* one...
|
||||
*/
|
||||
if ((powernow_table[i].frequency != powernow_table[cntlofreq].frequency) ||
|
||||
(powernow_table[i].index != powernow_table[cntlofreq].index)) {
|
||||
printk(KERN_ERR PFX "Too many lo freq table entries\n");
|
||||
goto err_out_mem;
|
||||
}
|
||||
|
||||
dprintk("double low frequency table entry, ignoring it.\n");
|
||||
powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID;
|
||||
continue;
|
||||
} else
|
||||
cntlofreq = i;
|
||||
/* verify only 1 entry from the lo frequency table */
|
||||
if (fid < HI_FID_TABLE_BOTTOM) {
|
||||
if (cntlofreq) {
|
||||
/* if both entries are the same, ignore this
|
||||
* one...
|
||||
*/
|
||||
if ((powernow_table[i].frequency != powernow_table[cntlofreq].frequency) ||
|
||||
(powernow_table[i].index != powernow_table[cntlofreq].index)) {
|
||||
printk(KERN_ERR PFX "Too many lo freq table entries\n");
|
||||
goto err_out_mem;
|
||||
}
|
||||
|
||||
dprintk("double low frequency table entry, ignoring it.\n");
|
||||
powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID;
|
||||
continue;
|
||||
} else
|
||||
cntlofreq = i;
|
||||
}
|
||||
|
||||
if (powernow_table[i].frequency != (data->acpi_data.states[i].core_frequency * 1000)) {
|
||||
@ -816,7 +830,7 @@ static int transition_frequency(struct powernow_k8_data *data, unsigned int inde
|
||||
{
|
||||
u32 fid;
|
||||
u32 vid;
|
||||
int res;
|
||||
int res, i;
|
||||
struct cpufreq_freqs freqs;
|
||||
|
||||
dprintk("cpu %d transition to index %u\n", smp_processor_id(), index);
|
||||
@ -841,7 +855,8 @@ static int transition_frequency(struct powernow_k8_data *data, unsigned int inde
|
||||
}
|
||||
|
||||
if ((fid < HI_FID_TABLE_BOTTOM) && (data->currfid < HI_FID_TABLE_BOTTOM)) {
|
||||
printk("ignoring illegal change in lo freq table-%x to 0x%x\n",
|
||||
printk(KERN_ERR PFX
|
||||
"ignoring illegal change in lo freq table-%x to 0x%x\n",
|
||||
data->currfid, fid);
|
||||
return 1;
|
||||
}
|
||||
@ -850,18 +865,20 @@ static int transition_frequency(struct powernow_k8_data *data, unsigned int inde
|
||||
smp_processor_id(), fid, vid);
|
||||
|
||||
freqs.cpu = data->cpu;
|
||||
|
||||
freqs.old = find_khz_freq_from_fid(data->currfid);
|
||||
freqs.new = find_khz_freq_from_fid(fid);
|
||||
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
|
||||
for_each_cpu_mask(i, cpu_core_map[data->cpu]) {
|
||||
freqs.cpu = i;
|
||||
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
|
||||
}
|
||||
|
||||
down(&fidvid_sem);
|
||||
res = transition_fid_vid(data, fid, vid);
|
||||
up(&fidvid_sem);
|
||||
|
||||
freqs.new = find_khz_freq_from_fid(data->currfid);
|
||||
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
|
||||
|
||||
for_each_cpu_mask(i, cpu_core_map[data->cpu]) {
|
||||
freqs.cpu = i;
|
||||
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -874,6 +891,7 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi
|
||||
u32 checkvid = data->currvid;
|
||||
unsigned int newstate;
|
||||
int ret = -EIO;
|
||||
int i;
|
||||
|
||||
/* only run on specific CPU from here on */
|
||||
oldmask = current->cpus_allowed;
|
||||
@ -902,22 +920,41 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi
|
||||
data->currfid, data->currvid);
|
||||
|
||||
if ((checkvid != data->currvid) || (checkfid != data->currfid)) {
|
||||
printk(KERN_ERR PFX
|
||||
"error - out of sync, fid 0x%x 0x%x, vid 0x%x 0x%x\n",
|
||||
checkfid, data->currfid, checkvid, data->currvid);
|
||||
printk(KERN_INFO PFX
|
||||
"error - out of sync, fix 0x%x 0x%x, vid 0x%x 0x%x\n",
|
||||
checkfid, data->currfid, checkvid, data->currvid);
|
||||
}
|
||||
|
||||
if (cpufreq_frequency_table_target(pol, data->powernow_table, targfreq, relation, &newstate))
|
||||
goto err_out;
|
||||
|
||||
down(&fidvid_sem);
|
||||
|
||||
for_each_cpu_mask(i, cpu_core_map[pol->cpu]) {
|
||||
/* make sure the sibling is initialized */
|
||||
if (!powernow_data[i]) {
|
||||
ret = 0;
|
||||
up(&fidvid_sem);
|
||||
goto err_out;
|
||||
}
|
||||
}
|
||||
|
||||
powernow_k8_acpi_pst_values(data, newstate);
|
||||
|
||||
if (transition_frequency(data, newstate)) {
|
||||
printk(KERN_ERR PFX "transition frequency failed\n");
|
||||
ret = 1;
|
||||
up(&fidvid_sem);
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
/* Update all the fid/vids of our siblings */
|
||||
for_each_cpu_mask(i, cpu_core_map[pol->cpu]) {
|
||||
powernow_data[i]->currvid = data->currvid;
|
||||
powernow_data[i]->currfid = data->currfid;
|
||||
}
|
||||
up(&fidvid_sem);
|
||||
|
||||
pol->cur = find_khz_freq_from_fid(data->currfid);
|
||||
ret = 0;
|
||||
|
||||
@ -962,7 +999,7 @@ static int __init powernowk8_cpu_init(struct cpufreq_policy *pol)
|
||||
*/
|
||||
|
||||
if ((num_online_cpus() != 1) || (num_possible_cpus() != 1)) {
|
||||
printk(KERN_INFO PFX "MP systems not supported by PSB BIOS structure\n");
|
||||
printk(KERN_ERR PFX "MP systems not supported by PSB BIOS structure\n");
|
||||
kfree(data);
|
||||
return -ENODEV;
|
||||
}
|
||||
@ -1003,6 +1040,7 @@ static int __init powernowk8_cpu_init(struct cpufreq_policy *pol)
|
||||
schedule();
|
||||
|
||||
pol->governor = CPUFREQ_DEFAULT_GOVERNOR;
|
||||
pol->cpus = cpu_core_map[pol->cpu];
|
||||
|
||||
/* Take a crude guess here.
|
||||
* That guess was in microseconds, so multiply with 1000 */
|
||||
@ -1069,7 +1107,7 @@ static unsigned int powernowk8_get (unsigned int cpu)
|
||||
return 0;
|
||||
}
|
||||
preempt_disable();
|
||||
|
||||
|
||||
if (query_current_values_with_pending_wait(data))
|
||||
goto out;
|
||||
|
||||
@ -1127,9 +1165,10 @@ static void __exit powernowk8_exit(void)
|
||||
cpufreq_unregister_driver(&cpufreq_amd64_driver);
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Paul Devriendt <paul.devriendt@amd.com>");
|
||||
MODULE_AUTHOR("Paul Devriendt <paul.devriendt@amd.com> and Mark Langsdorf <mark.langsdorf@amd.com.");
|
||||
MODULE_DESCRIPTION("AMD Athlon 64 and Opteron processor frequency driver.");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
late_initcall(powernowk8_init);
|
||||
module_exit(powernowk8_exit);
|
||||
|
||||
|
@ -174,3 +174,18 @@ static int core_voltage_post_transition(struct powernow_k8_data *data, u32 reqvi
|
||||
static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid);
|
||||
|
||||
static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned int index);
|
||||
|
||||
#ifndef for_each_cpu_mask
|
||||
#define for_each_cpu_mask(i,mask) for (i=0;i<1;i++)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
static inline void define_siblings(int cpu, cpumask_t cpu_sharedcore_mask[])
|
||||
{
|
||||
}
|
||||
#else
|
||||
static inline void define_siblings(int cpu, cpumask_t cpu_sharedcore_mask[])
|
||||
{
|
||||
cpu_set(0, cpu_sharedcore_mask[0]);
|
||||
}
|
||||
#endif
|
||||
|
186
arch/i386/kernel/cpu/cpufreq/sc520_freq.c
Normal file
186
arch/i386/kernel/cpu/cpufreq/sc520_freq.c
Normal file
@ -0,0 +1,186 @@
|
||||
/*
|
||||
* sc520_freq.c: cpufreq driver for the AMD Elan sc520
|
||||
*
|
||||
* Copyright (C) 2005 Sean Young <sean@mess.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* Based on elanfreq.c
|
||||
*
|
||||
* 2005-03-30: - initial revision
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/cpufreq.h>
|
||||
|
||||
#include <asm/msr.h>
|
||||
#include <asm/timex.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#define MMCR_BASE 0xfffef000 /* The default base address */
|
||||
#define OFFS_CPUCTL 0x2 /* CPU Control Register */
|
||||
|
||||
static __u8 __iomem *cpuctl;
|
||||
|
||||
#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "sc520_freq", msg)
|
||||
|
||||
static struct cpufreq_frequency_table sc520_freq_table[] = {
|
||||
{0x01, 100000},
|
||||
{0x02, 133000},
|
||||
{0, CPUFREQ_TABLE_END},
|
||||
};
|
||||
|
||||
static unsigned int sc520_freq_get_cpu_frequency(unsigned int cpu)
|
||||
{
|
||||
u8 clockspeed_reg = *cpuctl;
|
||||
|
||||
switch (clockspeed_reg & 0x03) {
|
||||
default:
|
||||
printk(KERN_ERR "sc520_freq: error: cpuctl register has unexpected value %02x\n", clockspeed_reg);
|
||||
case 0x01:
|
||||
return 100000;
|
||||
case 0x02:
|
||||
return 133000;
|
||||
}
|
||||
}
|
||||
|
||||
static void sc520_freq_set_cpu_state (unsigned int state)
|
||||
{
|
||||
|
||||
struct cpufreq_freqs freqs;
|
||||
u8 clockspeed_reg;
|
||||
|
||||
freqs.old = sc520_freq_get_cpu_frequency(0);
|
||||
freqs.new = sc520_freq_table[state].frequency;
|
||||
freqs.cpu = 0; /* AMD Elan is UP */
|
||||
|
||||
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
|
||||
|
||||
dprintk("attempting to set frequency to %i kHz\n",
|
||||
sc520_freq_table[state].frequency);
|
||||
|
||||
local_irq_disable();
|
||||
|
||||
clockspeed_reg = *cpuctl & ~0x03;
|
||||
*cpuctl = clockspeed_reg | sc520_freq_table[state].index;
|
||||
|
||||
local_irq_enable();
|
||||
|
||||
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
|
||||
};
|
||||
|
||||
static int sc520_freq_verify (struct cpufreq_policy *policy)
|
||||
{
|
||||
return cpufreq_frequency_table_verify(policy, &sc520_freq_table[0]);
|
||||
}
|
||||
|
||||
static int sc520_freq_target (struct cpufreq_policy *policy,
|
||||
unsigned int target_freq,
|
||||
unsigned int relation)
|
||||
{
|
||||
unsigned int newstate = 0;
|
||||
|
||||
if (cpufreq_frequency_table_target(policy, sc520_freq_table, target_freq, relation, &newstate))
|
||||
return -EINVAL;
|
||||
|
||||
sc520_freq_set_cpu_state(newstate);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Module init and exit code
|
||||
*/
|
||||
|
||||
static int sc520_freq_cpu_init(struct cpufreq_policy *policy)
|
||||
{
|
||||
struct cpuinfo_x86 *c = cpu_data;
|
||||
int result;
|
||||
|
||||
/* capability check */
|
||||
if (c->x86_vendor != X86_VENDOR_AMD ||
|
||||
c->x86 != 4 || c->x86_model != 9)
|
||||
return -ENODEV;
|
||||
|
||||
/* cpuinfo and default policy values */
|
||||
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
|
||||
policy->cpuinfo.transition_latency = 1000000; /* 1ms */
|
||||
policy->cur = sc520_freq_get_cpu_frequency(0);
|
||||
|
||||
result = cpufreq_frequency_table_cpuinfo(policy, sc520_freq_table);
|
||||
if (result)
|
||||
return (result);
|
||||
|
||||
cpufreq_frequency_table_get_attr(sc520_freq_table, policy->cpu);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int sc520_freq_cpu_exit(struct cpufreq_policy *policy)
|
||||
{
|
||||
cpufreq_frequency_table_put_attr(policy->cpu);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static struct freq_attr* sc520_freq_attr[] = {
|
||||
&cpufreq_freq_attr_scaling_available_freqs,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
||||
static struct cpufreq_driver sc520_freq_driver = {
|
||||
.get = sc520_freq_get_cpu_frequency,
|
||||
.verify = sc520_freq_verify,
|
||||
.target = sc520_freq_target,
|
||||
.init = sc520_freq_cpu_init,
|
||||
.exit = sc520_freq_cpu_exit,
|
||||
.name = "sc520_freq",
|
||||
.owner = THIS_MODULE,
|
||||
.attr = sc520_freq_attr,
|
||||
};
|
||||
|
||||
|
||||
static int __init sc520_freq_init(void)
|
||||
{
|
||||
struct cpuinfo_x86 *c = cpu_data;
|
||||
|
||||
/* Test if we have the right hardware */
|
||||
if(c->x86_vendor != X86_VENDOR_AMD ||
|
||||
c->x86 != 4 || c->x86_model != 9) {
|
||||
dprintk("no Elan SC520 processor found!\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
cpuctl = ioremap((unsigned long)(MMCR_BASE + OFFS_CPUCTL), 1);
|
||||
if(!cpuctl) {
|
||||
printk(KERN_ERR "sc520_freq: error: failed to remap memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return cpufreq_register_driver(&sc520_freq_driver);
|
||||
}
|
||||
|
||||
|
||||
static void __exit sc520_freq_exit(void)
|
||||
{
|
||||
cpufreq_unregister_driver(&sc520_freq_driver);
|
||||
iounmap(cpuctl);
|
||||
}
|
||||
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Sean Young <sean@mess.org>");
|
||||
MODULE_DESCRIPTION("cpufreq driver for AMD's Elan sc520 CPU");
|
||||
|
||||
module_init(sc520_freq_init);
|
||||
module_exit(sc520_freq_exit);
|
||||
|
@ -54,6 +54,8 @@ enum {
|
||||
CPU_DOTHAN_A1,
|
||||
CPU_DOTHAN_A2,
|
||||
CPU_DOTHAN_B0,
|
||||
CPU_MP4HT_D0,
|
||||
CPU_MP4HT_E0,
|
||||
};
|
||||
|
||||
static const struct cpu_id cpu_ids[] = {
|
||||
@ -61,6 +63,8 @@ static const struct cpu_id cpu_ids[] = {
|
||||
[CPU_DOTHAN_A1] = { 6, 13, 1 },
|
||||
[CPU_DOTHAN_A2] = { 6, 13, 2 },
|
||||
[CPU_DOTHAN_B0] = { 6, 13, 6 },
|
||||
[CPU_MP4HT_D0] = {15, 3, 4 },
|
||||
[CPU_MP4HT_E0] = {15, 4, 1 },
|
||||
};
|
||||
#define N_IDS (sizeof(cpu_ids)/sizeof(cpu_ids[0]))
|
||||
|
||||
@ -226,6 +230,8 @@ static struct cpu_model models[] =
|
||||
{ &cpu_ids[CPU_DOTHAN_A1], NULL, 0, NULL },
|
||||
{ &cpu_ids[CPU_DOTHAN_A2], NULL, 0, NULL },
|
||||
{ &cpu_ids[CPU_DOTHAN_B0], NULL, 0, NULL },
|
||||
{ &cpu_ids[CPU_MP4HT_D0], NULL, 0, NULL },
|
||||
{ &cpu_ids[CPU_MP4HT_E0], NULL, 0, NULL },
|
||||
|
||||
{ NULL, }
|
||||
};
|
||||
|
@ -336,7 +336,7 @@ unsigned int speedstep_get_freqs(unsigned int processor,
|
||||
if (!prev_speed)
|
||||
return -EIO;
|
||||
|
||||
dprintk("previous seped is %u\n", prev_speed);
|
||||
dprintk("previous speed is %u\n", prev_speed);
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
@ -348,7 +348,7 @@ unsigned int speedstep_get_freqs(unsigned int processor,
|
||||
goto out;
|
||||
}
|
||||
|
||||
dprintk("low seped is %u\n", *low_speed);
|
||||
dprintk("low speed is %u\n", *low_speed);
|
||||
|
||||
/* switch to high state */
|
||||
set_state(SPEEDSTEP_HIGH);
|
||||
@ -358,7 +358,7 @@ unsigned int speedstep_get_freqs(unsigned int processor,
|
||||
goto out;
|
||||
}
|
||||
|
||||
dprintk("high seped is %u\n", *high_speed);
|
||||
dprintk("high speed is %u\n", *high_speed);
|
||||
|
||||
if (*low_speed == *high_speed) {
|
||||
ret = -ENODEV;
|
||||
|
@ -357,6 +357,9 @@ static int __init speedstep_init(void)
|
||||
case SPEEDSTEP_PROCESSOR_PIII_C:
|
||||
case SPEEDSTEP_PROCESSOR_PIII_C_EARLY:
|
||||
break;
|
||||
case SPEEDSTEP_PROCESSOR_P4M:
|
||||
printk(KERN_INFO "speedstep-smi: you're trying to use this cpufreq driver on a Pentium 4-based CPU. Most likely it will not work.\n");
|
||||
break;
|
||||
default:
|
||||
speedstep_processor = 0;
|
||||
}
|
||||
|
@ -118,7 +118,7 @@ struct _cpuid4_info {
|
||||
};
|
||||
|
||||
#define MAX_CACHE_LEAVES 4
|
||||
static unsigned short __devinitdata num_cache_leaves;
|
||||
static unsigned short num_cache_leaves;
|
||||
|
||||
static int __devinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf)
|
||||
{
|
||||
|
@ -45,7 +45,7 @@
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/system.h>
|
||||
|
||||
static struct class_simple *cpuid_class;
|
||||
static struct class *cpuid_class;
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
|
||||
@ -158,12 +158,12 @@ static struct file_operations cpuid_fops = {
|
||||
.open = cpuid_open,
|
||||
};
|
||||
|
||||
static int cpuid_class_simple_device_add(int i)
|
||||
static int cpuid_class_device_create(int i)
|
||||
{
|
||||
int err = 0;
|
||||
struct class_device *class_err;
|
||||
|
||||
class_err = class_simple_device_add(cpuid_class, MKDEV(CPUID_MAJOR, i), NULL, "cpu%d",i);
|
||||
class_err = class_device_create(cpuid_class, MKDEV(CPUID_MAJOR, i), NULL, "cpu%d",i);
|
||||
if (IS_ERR(class_err))
|
||||
err = PTR_ERR(class_err);
|
||||
return err;
|
||||
@ -175,10 +175,10 @@ static int __devinit cpuid_class_cpu_callback(struct notifier_block *nfb, unsign
|
||||
|
||||
switch (action) {
|
||||
case CPU_ONLINE:
|
||||
cpuid_class_simple_device_add(cpu);
|
||||
cpuid_class_device_create(cpu);
|
||||
break;
|
||||
case CPU_DEAD:
|
||||
class_simple_device_remove(MKDEV(CPUID_MAJOR, cpu));
|
||||
class_device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, cpu));
|
||||
break;
|
||||
}
|
||||
return NOTIFY_OK;
|
||||
@ -200,13 +200,13 @@ static int __init cpuid_init(void)
|
||||
err = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
cpuid_class = class_simple_create(THIS_MODULE, "cpuid");
|
||||
cpuid_class = class_create(THIS_MODULE, "cpuid");
|
||||
if (IS_ERR(cpuid_class)) {
|
||||
err = PTR_ERR(cpuid_class);
|
||||
goto out_chrdev;
|
||||
}
|
||||
for_each_online_cpu(i) {
|
||||
err = cpuid_class_simple_device_add(i);
|
||||
err = cpuid_class_device_create(i);
|
||||
if (err != 0)
|
||||
goto out_class;
|
||||
}
|
||||
@ -218,9 +218,9 @@ static int __init cpuid_init(void)
|
||||
out_class:
|
||||
i = 0;
|
||||
for_each_online_cpu(i) {
|
||||
class_simple_device_remove(MKDEV(CPUID_MAJOR, i));
|
||||
class_device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, i));
|
||||
}
|
||||
class_simple_destroy(cpuid_class);
|
||||
class_destroy(cpuid_class);
|
||||
out_chrdev:
|
||||
unregister_chrdev(CPUID_MAJOR, "cpu/cpuid");
|
||||
out:
|
||||
@ -232,8 +232,8 @@ static void __exit cpuid_exit(void)
|
||||
int cpu = 0;
|
||||
|
||||
for_each_online_cpu(cpu)
|
||||
class_simple_device_remove(MKDEV(CPUID_MAJOR, cpu));
|
||||
class_simple_destroy(cpuid_class);
|
||||
class_device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, cpu));
|
||||
class_destroy(cpuid_class);
|
||||
unregister_chrdev(CPUID_MAJOR, "cpu/cpuid");
|
||||
unregister_cpu_notifier(&cpuid_class_cpu_notifier);
|
||||
}
|
||||
|
@ -44,7 +44,7 @@
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/system.h>
|
||||
|
||||
static struct class_simple *msr_class;
|
||||
static struct class *msr_class;
|
||||
|
||||
/* Note: "err" is handled in a funny way below. Otherwise one version
|
||||
of gcc or another breaks. */
|
||||
@ -260,12 +260,12 @@ static struct file_operations msr_fops = {
|
||||
.open = msr_open,
|
||||
};
|
||||
|
||||
static int msr_class_simple_device_add(int i)
|
||||
static int msr_class_device_create(int i)
|
||||
{
|
||||
int err = 0;
|
||||
struct class_device *class_err;
|
||||
|
||||
class_err = class_simple_device_add(msr_class, MKDEV(MSR_MAJOR, i), NULL, "msr%d",i);
|
||||
class_err = class_device_create(msr_class, MKDEV(MSR_MAJOR, i), NULL, "msr%d",i);
|
||||
if (IS_ERR(class_err))
|
||||
err = PTR_ERR(class_err);
|
||||
return err;
|
||||
@ -277,10 +277,10 @@ static int __devinit msr_class_cpu_callback(struct notifier_block *nfb, unsigned
|
||||
|
||||
switch (action) {
|
||||
case CPU_ONLINE:
|
||||
msr_class_simple_device_add(cpu);
|
||||
msr_class_device_create(cpu);
|
||||
break;
|
||||
case CPU_DEAD:
|
||||
class_simple_device_remove(MKDEV(MSR_MAJOR, cpu));
|
||||
class_device_destroy(msr_class, MKDEV(MSR_MAJOR, cpu));
|
||||
break;
|
||||
}
|
||||
return NOTIFY_OK;
|
||||
@ -302,13 +302,13 @@ static int __init msr_init(void)
|
||||
err = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
msr_class = class_simple_create(THIS_MODULE, "msr");
|
||||
msr_class = class_create(THIS_MODULE, "msr");
|
||||
if (IS_ERR(msr_class)) {
|
||||
err = PTR_ERR(msr_class);
|
||||
goto out_chrdev;
|
||||
}
|
||||
for_each_online_cpu(i) {
|
||||
err = msr_class_simple_device_add(i);
|
||||
err = msr_class_device_create(i);
|
||||
if (err != 0)
|
||||
goto out_class;
|
||||
}
|
||||
@ -320,8 +320,8 @@ static int __init msr_init(void)
|
||||
out_class:
|
||||
i = 0;
|
||||
for_each_online_cpu(i)
|
||||
class_simple_device_remove(MKDEV(MSR_MAJOR, i));
|
||||
class_simple_destroy(msr_class);
|
||||
class_device_destroy(msr_class, MKDEV(MSR_MAJOR, i));
|
||||
class_destroy(msr_class);
|
||||
out_chrdev:
|
||||
unregister_chrdev(MSR_MAJOR, "cpu/msr");
|
||||
out:
|
||||
@ -332,8 +332,8 @@ static void __exit msr_exit(void)
|
||||
{
|
||||
int cpu = 0;
|
||||
for_each_online_cpu(cpu)
|
||||
class_simple_device_remove(MKDEV(MSR_MAJOR, cpu));
|
||||
class_simple_destroy(msr_class);
|
||||
class_device_destroy(msr_class, MKDEV(MSR_MAJOR, cpu));
|
||||
class_destroy(msr_class);
|
||||
unregister_chrdev(MSR_MAJOR, "cpu/msr");
|
||||
unregister_cpu_notifier(&msr_class_cpu_notifier);
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user