mirror of
https://github.com/torvalds/linux.git
synced 2024-11-15 08:31:55 +00:00
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
|
S: USA
|
||||||
|
|
||||||
N: Dave Neuer
|
N: Dave Neuer
|
||||||
E: dneuer@innovation-charter.com
|
E: dave.neuer@pobox.com
|
||||||
E: mr_fred_smoothie@yahoo.com
|
|
||||||
D: Helped implement support for Compaq's H31xx series iPAQs
|
D: Helped implement support for Compaq's H31xx series iPAQs
|
||||||
D: Other mostly minor tweaks & bugfixes
|
D: Other mostly minor tweaks & bugfixes
|
||||||
S: 325 E. Main St., Suite 3
|
|
||||||
S: Carnegie, PA 15105
|
|
||||||
S: USA
|
|
||||||
|
|
||||||
N: Michael Neuffer
|
N: Michael Neuffer
|
||||||
E: mike@i-Connect.Net
|
E: mike@i-Connect.Net
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
DOCBOOKS := wanbook.xml z8530book.xml mcabook.xml videobook.xml \
|
DOCBOOKS := wanbook.xml z8530book.xml mcabook.xml videobook.xml \
|
||||||
kernel-hacking.xml kernel-locking.xml deviceiobook.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 \
|
sis900.xml kernel-api.xml journal-api.xml lsm.xml usb.xml \
|
||||||
gadget.xml libata.xml mtdnand.xml librs.xml
|
gadget.xml libata.xml mtdnand.xml librs.xml
|
||||||
|
|
||||||
|
@ -338,7 +338,6 @@ X!Earch/i386/kernel/mca.c
|
|||||||
X!Iinclude/linux/device.h
|
X!Iinclude/linux/device.h
|
||||||
-->
|
-->
|
||||||
!Edrivers/base/driver.c
|
!Edrivers/base/driver.c
|
||||||
!Edrivers/base/class_simple.c
|
|
||||||
!Edrivers/base/core.c
|
!Edrivers/base/core.c
|
||||||
!Edrivers/base/firmware_class.c
|
!Edrivers/base/firmware_class.c
|
||||||
!Edrivers/base/transport_class.c
|
!Edrivers/base/transport_class.c
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
</authorgroup>
|
</authorgroup>
|
||||||
|
|
||||||
<copyright>
|
<copyright>
|
||||||
<year>2003</year>
|
<year>2003-2005</year>
|
||||||
<holder>Jeff Garzik</holder>
|
<holder>Jeff Garzik</holder>
|
||||||
</copyright>
|
</copyright>
|
||||||
|
|
||||||
@ -44,30 +44,38 @@
|
|||||||
|
|
||||||
<toc></toc>
|
<toc></toc>
|
||||||
|
|
||||||
<chapter id="libataThanks">
|
<chapter id="libataIntroduction">
|
||||||
<title>Thanks</title>
|
<title>Introduction</title>
|
||||||
<para>
|
<para>
|
||||||
The bulk of the ATA knowledge comes thanks to long conversations with
|
libATA is a library used inside the Linux kernel to support ATA host
|
||||||
Andre Hedrick (www.linux-ide.org).
|
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>
|
||||||
<para>
|
<para>
|
||||||
Thanks to Alan Cox for pointing out similarities
|
This Guide documents the libATA driver API, library functions, library
|
||||||
between SATA and SCSI, and in general for motivation to hack on
|
internals, and a couple sample ATA low-level drivers.
|
||||||
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>
|
</para>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
||||||
<chapter id="libataDriverApi">
|
<chapter id="libataDriverApi">
|
||||||
<title>libata Driver API</title>
|
<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>
|
<sect1>
|
||||||
<title>struct ata_port_operations</title>
|
<title>struct ata_port_operations</title>
|
||||||
|
|
||||||
|
<sect2><title>Disable ATA port</title>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
void (*port_disable) (struct ata_port *);
|
void (*port_disable) (struct ata_port *);
|
||||||
</programlisting>
|
</programlisting>
|
||||||
@ -78,6 +86,9 @@ void (*port_disable) (struct ata_port *);
|
|||||||
unplug).
|
unplug).
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2><title>Post-IDENTIFY device configuration</title>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
void (*dev_config) (struct ata_port *, struct ata_device *);
|
void (*dev_config) (struct ata_port *, struct ata_device *);
|
||||||
</programlisting>
|
</programlisting>
|
||||||
@ -88,6 +99,9 @@ void (*dev_config) (struct ata_port *, struct ata_device *);
|
|||||||
issue of SET FEATURES - XFER MODE, and prior to operation.
|
issue of SET FEATURES - XFER MODE, and prior to operation.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2><title>Set PIO/DMA mode</title>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
void (*set_piomode) (struct ata_port *, struct ata_device *);
|
void (*set_piomode) (struct ata_port *, struct ata_device *);
|
||||||
void (*set_dmamode) (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.
|
->set_dma_mode() is only called if DMA is possible.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2><title>Taskfile read/write</title>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
void (*tf_load) (struct ata_port *ap, struct ata_taskfile *tf);
|
void (*tf_load) (struct ata_port *ap, struct ata_taskfile *tf);
|
||||||
void (*tf_read) (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.
|
taskfile register values.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2><title>ATA command execute</title>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
void (*exec_command)(struct ata_port *ap, struct ata_taskfile *tf);
|
void (*exec_command)(struct ata_port *ap, struct ata_taskfile *tf);
|
||||||
</programlisting>
|
</programlisting>
|
||||||
@ -129,17 +149,37 @@ void (*exec_command)(struct ata_port *ap, struct ata_taskfile *tf);
|
|||||||
->tf_load(), to be initiated in hardware.
|
->tf_load(), to be initiated in hardware.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2><title>Per-cmd ATAPI DMA capabilities filter</title>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
u8 (*check_status)(struct ata_port *ap);
|
int (*check_atapi_dma) (struct ata_queued_cmd *qc);
|
||||||
void (*dev_select)(struct ata_port *ap, unsigned int device);
|
|
||||||
</programlisting>
|
</programlisting>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Reads the Status ATA shadow register from hardware. On some
|
Allow low-level driver to filter ATA PACKET commands, returning a status
|
||||||
hardware, this has the side effect of clearing the interrupt
|
indicating whether or not it is OK to use DMA for the supplied PACKET
|
||||||
condition.
|
command.
|
||||||
</para>
|
</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>
|
<programlisting>
|
||||||
void (*dev_select)(struct ata_port *ap, unsigned int device);
|
void (*dev_select)(struct ata_port *ap, unsigned int device);
|
||||||
</programlisting>
|
</programlisting>
|
||||||
@ -147,9 +187,13 @@ void (*dev_select)(struct ata_port *ap, unsigned int device);
|
|||||||
<para>
|
<para>
|
||||||
Issues the low-level hardware command(s) that causes one of N
|
Issues the low-level hardware command(s) that causes one of N
|
||||||
hardware devices to be considered 'selected' (active and
|
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>
|
</para>
|
||||||
|
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2><title>Reset ATA bus</title>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
void (*phy_reset) (struct ata_port *ap);
|
void (*phy_reset) (struct ata_port *ap);
|
||||||
</programlisting>
|
</programlisting>
|
||||||
@ -162,17 +206,31 @@ void (*phy_reset) (struct ata_port *ap);
|
|||||||
functions ata_bus_reset() or sata_phy_reset() for this hook.
|
functions ata_bus_reset() or sata_phy_reset() for this hook.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2><title>Control PCI IDE BMDMA engine</title>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
void (*bmdma_setup) (struct ata_queued_cmd *qc);
|
void (*bmdma_setup) (struct ata_queued_cmd *qc);
|
||||||
void (*bmdma_start) (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>
|
</programlisting>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
When setting up an IDE BMDMA transaction, these hooks arm
|
When setting up an IDE BMDMA transaction, these hooks arm
|
||||||
(->bmdma_setup) and fire (->bmdma_start) the hardware's DMA
|
(->bmdma_setup), fire (->bmdma_start), and halt (->bmdma_stop)
|
||||||
engine.
|
the hardware's DMA engine. ->bmdma_status is used to read the standard
|
||||||
|
PCI IDE DMA Status register.
|
||||||
</para>
|
</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>
|
<programlisting>
|
||||||
void (*qc_prep) (struct ata_queued_cmd *qc);
|
void (*qc_prep) (struct ata_queued_cmd *qc);
|
||||||
int (*qc_issue) (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
|
->qc_issue is used to make a command active, once the hardware
|
||||||
and S/G tables have been prepared. IDE BMDMA drivers use the
|
and S/G tables have been prepared. IDE BMDMA drivers use the
|
||||||
helper function ata_qc_issue_prot() for taskfile protocol-based
|
helper function ata_qc_issue_prot() for taskfile protocol-based
|
||||||
dispatch. More advanced drivers roll their own ->qc_issue
|
dispatch. More advanced drivers implement their own ->qc_issue.
|
||||||
implementation, using this as the "issue new ATA command to
|
|
||||||
hardware" hook.
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2><title>Timeout (error) handling</title>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
void (*eng_timeout) (struct ata_port *ap);
|
void (*eng_timeout) (struct ata_port *ap);
|
||||||
</programlisting>
|
</programlisting>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
This is a high level error handling function, called from the
|
This is a high level error handling function, called from the
|
||||||
error handling thread, when a command times out.
|
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>
|
</para>
|
||||||
|
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2><title>Hardware interrupt handling</title>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
irqreturn_t (*irq_handler)(int, void *, struct pt_regs *);
|
irqreturn_t (*irq_handler)(int, void *, struct pt_regs *);
|
||||||
void (*irq_clear) (struct ata_port *);
|
void (*irq_clear) (struct ata_port *);
|
||||||
@ -216,6 +280,9 @@ void (*irq_clear) (struct ata_port *);
|
|||||||
is quiet.
|
is quiet.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2><title>SATA phy read/write</title>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
u32 (*scr_read) (struct ata_port *ap, unsigned int sc_reg);
|
u32 (*scr_read) (struct ata_port *ap, unsigned int sc_reg);
|
||||||
void (*scr_write) (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.
|
if ->phy_reset hook called the sata_phy_reset() helper function.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2><title>Init and shutdown</title>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
int (*port_start) (struct ata_port *ap);
|
int (*port_start) (struct ata_port *ap);
|
||||||
void (*port_stop) (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.
|
tasks.
|
||||||
</para>
|
</para>
|
||||||
<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
|
->port_stop() is called after ->host_stop(). It's sole function
|
||||||
is to release DMA/memory resources, now that they are no longer
|
is to release DMA/memory resources, now that they are no longer
|
||||||
actively being used.
|
actively being used.
|
||||||
</para>
|
</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>
|
</sect1>
|
||||||
</chapter>
|
</chapter>
|
||||||
@ -279,4 +351,24 @@ void (*host_stop) (struct ata_host_set *host_set);
|
|||||||
!Idrivers/scsi/sata_sil.c
|
!Idrivers/scsi/sata_sil.c
|
||||||
</chapter>
|
</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>
|
</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
|
pass it on as a open-source patch. The rules are pretty simple: if you
|
||||||
can certify the below:
|
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:
|
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
|
person who certified (a), (b) or (c) and I have not modified
|
||||||
it.
|
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
|
then you just add a line saying
|
||||||
|
|
||||||
Signed-off-by: Random J Developer <random@developer.org>
|
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.
|
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.
|
current_state: Current power state of the device.
|
||||||
|
|
||||||
saved_state: Pointer to saved state of the device. This is usable by
|
saved_state: Pointer to saved state of the device. This is usable by
|
||||||
|
@ -5,21 +5,17 @@ struct device_driver {
|
|||||||
char * name;
|
char * name;
|
||||||
struct bus_type * bus;
|
struct bus_type * bus;
|
||||||
|
|
||||||
rwlock_t lock;
|
struct completion unloaded;
|
||||||
atomic_t refcount;
|
struct kobject kobj;
|
||||||
|
|
||||||
list_t bus_list;
|
|
||||||
list_t devices;
|
list_t devices;
|
||||||
|
|
||||||
struct driver_dir_entry dir;
|
struct module *owner;
|
||||||
|
|
||||||
int (*probe) (struct device * dev);
|
int (*probe) (struct device * dev);
|
||||||
int (*remove) (struct device * dev);
|
int (*remove) (struct device * dev);
|
||||||
|
|
||||||
int (*suspend) (struct device * dev, pm_message_t state, u32 level);
|
int (*suspend) (struct device * dev, pm_message_t state, u32 level);
|
||||||
int (*resume) (struct device * dev, 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 = {
|
static struct device_driver eepro100_driver = {
|
||||||
.name = "eepro100",
|
.name = "eepro100",
|
||||||
.bus = &pci_bus_type,
|
.bus = &pci_bus_type,
|
||||||
.devclass = ðernet_devclass, /* when it's implemented */
|
|
||||||
|
|
||||||
.probe = eepro100_probe,
|
.probe = eepro100_probe,
|
||||||
.remove = eepro100_remove,
|
.remove = eepro100_remove,
|
||||||
@ -85,7 +80,6 @@ static struct pci_driver eepro100_driver = {
|
|||||||
.driver = {
|
.driver = {
|
||||||
.name = "eepro100",
|
.name = "eepro100",
|
||||||
.bus = &pci_bus_type,
|
.bus = &pci_bus_type,
|
||||||
.devclass = ðernet_devclass, /* when it's implemented */
|
|
||||||
.probe = eepro100_probe,
|
.probe = eepro100_probe,
|
||||||
.remove = eepro100_remove,
|
.remove = eepro100_remove,
|
||||||
.suspend = eepro100_suspend,
|
.suspend = eepro100_suspend,
|
||||||
@ -166,27 +160,32 @@ Callbacks
|
|||||||
|
|
||||||
int (*probe) (struct device * dev);
|
int (*probe) (struct device * dev);
|
||||||
|
|
||||||
probe is called to verify the existence of a certain type of
|
The probe() entry is called in task context, with the bus's rwsem locked
|
||||||
hardware. This is called during the driver binding process, after the
|
and the driver partially bound to the device. Drivers commonly use
|
||||||
bus has verified that the device ID of a device matches one of the
|
container_of() to convert "dev" to a bus-specific type, both in probe()
|
||||||
device IDs supported by the driver.
|
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
|
This callback holds the driver-specific logic to bind the driver to a
|
||||||
present. It may allocate a driver-specific structure, but it should
|
given device. That includes verifying that the device is present, that
|
||||||
not do any initialization of the hardware itself. The device-specific
|
it's a version the driver can handle, that driver data structures can
|
||||||
structure may be stored in the device's driver_data field.
|
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);
|
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
|
||||||
init is called during the binding stage. It is called after probe has
|
released all reasources it allocated.
|
||||||
successfully returned and the device has been registered with its
|
|
||||||
class. It is responsible for initializing the hardware.
|
|
||||||
|
|
||||||
int (*remove) (struct device * dev);
|
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
|
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
|
It is up to the driver to determine if the device is present or
|
||||||
not. It should free any resources allocated specifically for the
|
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:
|
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);
|
return sprintf(buf,"%s\n",dev->name);
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,21 @@
|
|||||||
Generic HDLC layer
|
Generic HDLC layer
|
||||||
Krzysztof Halasa <khc@pm.waw.pl>
|
Krzysztof Halasa <khc@pm.waw.pl>
|
||||||
January, 2003
|
|
||||||
|
|
||||||
|
|
||||||
Generic HDLC layer currently supports:
|
Generic HDLC layer currently supports:
|
||||||
- Frame Relay (ANSI, CCITT and no LMI), with ARP support (no InARP).
|
1. Frame Relay (ANSI, CCITT, Cisco and no LMI).
|
||||||
Normal (routed) and Ethernet-bridged (Ethernet device emulation)
|
- Normal (routed) and Ethernet-bridged (Ethernet device emulation)
|
||||||
interfaces can share a single PVC.
|
interfaces can share a single PVC.
|
||||||
- raw HDLC - either IP (IPv4) interface or Ethernet device emulation.
|
- ARP support (no InARP support in the kernel - there is an
|
||||||
- Cisco HDLC,
|
experimental InARP user-space daemon available on:
|
||||||
- PPP (uses syncppp.c),
|
http://www.kernel.org/pub/linux/utils/net/hdlc/).
|
||||||
- X.25 (uses X.25 routines).
|
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:
|
Generic HDLC is a protocol driver only - it needs a low-level driver
|
||||||
- C101 by Moxa Technologies Co., Ltd.
|
for your particular hardware.
|
||||||
- RISCom/N2 by SDL Communications Inc.
|
|
||||||
- and others, some not in the official kernel.
|
|
||||||
|
|
||||||
Ethernet device emulation (using HDLC or Frame-Relay PVC) is compatible
|
Ethernet device emulation (using HDLC or Frame-Relay PVC) is compatible
|
||||||
with IEEE 802.1Q (VLANs) and 802.1D (Ethernet bridging).
|
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
|
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
|
create a number of "hdlc" (hdlc0 etc) network devices, one for each
|
||||||
WAN port. You'll need the "sethdlc" utility, get it from:
|
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:
|
Compile sethdlc.c utility:
|
||||||
gcc -O2 -Wall -o sethdlc sethdlc.c
|
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
|
* v35 | rs232 | x21 | t1 | e1 - sets physical interface for a given port
|
||||||
if the card has software-selectable interfaces
|
if the card has software-selectable interfaces
|
||||||
loopback - activate hardware loopback (for testing only)
|
loopback - activate hardware loopback (for testing only)
|
||||||
* clock ext - external clock (uses DTE RX and TX clock)
|
* clock ext - both RX clock and TX clock external
|
||||||
* clock int - internal clock (provides clock signal on DCE clock output)
|
* clock int - both RX clock and TX clock internal
|
||||||
* clock txint - TX internal, RX external (provides TX clock on DCE output)
|
* clock txint - RX clock external, TX clock internal
|
||||||
* clock txfromrx - TX clock derived from RX clock (TX clock on DCE output)
|
* clock txfromrx - RX clock external, TX clock derived from RX clock
|
||||||
* rate - sets clock rate in bps (not required for external clock or
|
* rate - sets clock rate in bps (for "int" or "txint" clock only)
|
||||||
for txfromrx)
|
|
||||||
|
|
||||||
Setting protocol:
|
Setting protocol:
|
||||||
|
|
||||||
@ -79,7 +79,7 @@ Setting protocol:
|
|||||||
* x25 - sets X.25 mode
|
* x25 - sets X.25 mode
|
||||||
|
|
||||||
* fr - Frame Relay 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).
|
dce - Frame Relay DCE (network) side LMI instead of default DTE (user).
|
||||||
It has nothing to do with clocks!
|
It has nothing to do with clocks!
|
||||||
t391 - link integrity verification polling timer (in seconds) - user
|
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"
|
If you have a problem with N2, C101 or PLX200SYN card, you can issue the
|
||||||
command to see port's packet descriptor rings (in kernel logs):
|
"private" command to see port's packet descriptor rings (in kernel logs):
|
||||||
|
|
||||||
sethdlc hdlc0 private
|
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
|
Attaching this info to bug reports would be helpful. Anyway, let me know
|
||||||
if you have problems using this.
|
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(#)
|
ni65 YES YES YES Software(#)
|
||||||
seeq NO NO NO N/A
|
seeq NO NO NO N/A
|
||||||
sgiseek <------------------ Buggy ------------------>
|
sgiseek <------------------ Buggy ------------------>
|
||||||
sk_g16 NO NO YES N/A
|
|
||||||
smc-ultra YES YES YES Hardware
|
smc-ultra YES YES YES Hardware
|
||||||
sunlance YES YES YES Hardware
|
sunlance YES YES YES Hardware
|
||||||
tulip YES YES YES Hardware
|
tulip YES YES YES Hardware
|
||||||
|
@ -284,9 +284,6 @@ ppp.c:
|
|||||||
seeq8005.c: *Not modularized*
|
seeq8005.c: *Not modularized*
|
||||||
(Probes ports: 0x300, 0x320, 0x340, 0x360)
|
(Probes ports: 0x300, 0x320, 0x340, 0x360)
|
||||||
|
|
||||||
sk_g16.c: *Not modularized*
|
|
||||||
(Probes ports: 0x100, 0x180, 0x208, 0x220m 0x288, 0x320, 0x328, 0x390)
|
|
||||||
|
|
||||||
skeleton.c: *Skeleton*
|
skeleton.c: *Skeleton*
|
||||||
|
|
||||||
slhc.c:
|
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:
|
Please report problems to one or more of:
|
||||||
|
|
||||||
Andrew Morton <andrewm@uow.edu.au>
|
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>
|
Linux kernel mailing list <linux-kernel@vger.kernel.org>
|
||||||
|
|
||||||
Please note the 'Reporting and Diagnosing Problems' section at the end
|
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>
|
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)
|
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)
|
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
|
* Returns SUCCESS if command aborted else FAILED
|
||||||
*
|
*
|
||||||
* Locks: struct Scsi_Host::host_lock held (with irqsave) on entry
|
* Locks: None held
|
||||||
* and assumed to be held on return.
|
|
||||||
*
|
*
|
||||||
* Calling context: kernel thread
|
* Calling context: kernel thread
|
||||||
*
|
*
|
||||||
@ -955,8 +954,7 @@ Details:
|
|||||||
*
|
*
|
||||||
* Returns SUCCESS if command aborted else FAILED
|
* Returns SUCCESS if command aborted else FAILED
|
||||||
*
|
*
|
||||||
* Locks: struct Scsi_Host::host_lock held (with irqsave) on entry
|
* Locks: None held
|
||||||
* and assumed to be held on return.
|
|
||||||
*
|
*
|
||||||
* Calling context: kernel thread
|
* Calling context: kernel thread
|
||||||
*
|
*
|
||||||
@ -974,8 +972,7 @@ Details:
|
|||||||
*
|
*
|
||||||
* Returns SUCCESS if command aborted else FAILED
|
* Returns SUCCESS if command aborted else FAILED
|
||||||
*
|
*
|
||||||
* Locks: struct Scsi_Host::host_lock held (with irqsave) on entry
|
* Locks: None held
|
||||||
* and assumed to be held on return.
|
|
||||||
*
|
*
|
||||||
* Calling context: kernel thread
|
* Calling context: kernel thread
|
||||||
*
|
*
|
||||||
@ -993,8 +990,7 @@ Details:
|
|||||||
*
|
*
|
||||||
* Returns SUCCESS if command aborted else FAILED
|
* Returns SUCCESS if command aborted else FAILED
|
||||||
*
|
*
|
||||||
* Locks: struct Scsi_Host::host_lock held (with irqsave) on entry
|
* Locks: None held
|
||||||
* and assumed to be held on return.
|
|
||||||
*
|
*
|
||||||
* Calling context: kernel thread
|
* Calling context: kernel thread
|
||||||
*
|
*
|
||||||
|
63
MAINTAINERS
63
MAINTAINERS
@ -73,7 +73,7 @@ S: Status, one of the following:
|
|||||||
3C359 NETWORK DRIVER
|
3C359 NETWORK DRIVER
|
||||||
P: Mike Phillips
|
P: Mike Phillips
|
||||||
M: mikep@linuxtr.net
|
M: mikep@linuxtr.net
|
||||||
L: netdev@oss.sgi.com
|
L: netdev@vger.kernel.org
|
||||||
L: linux-tr@linuxtr.net
|
L: linux-tr@linuxtr.net
|
||||||
W: http://www.linuxtr.net
|
W: http://www.linuxtr.net
|
||||||
S: Maintained
|
S: Maintained
|
||||||
@ -81,13 +81,13 @@ S: Maintained
|
|||||||
3C505 NETWORK DRIVER
|
3C505 NETWORK DRIVER
|
||||||
P: Philip Blundell
|
P: Philip Blundell
|
||||||
M: philb@gnu.org
|
M: philb@gnu.org
|
||||||
L: netdev@oss.sgi.com
|
L: netdev@vger.kernel.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
3CR990 NETWORK DRIVER
|
3CR990 NETWORK DRIVER
|
||||||
P: David Dillow
|
P: David Dillow
|
||||||
M: dave@thedillows.org
|
M: dave@thedillows.org
|
||||||
L: netdev@oss.sgi.com
|
L: netdev@vger.kernel.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
3W-XXXX ATA-RAID CONTROLLER DRIVER
|
3W-XXXX ATA-RAID CONTROLLER DRIVER
|
||||||
@ -130,7 +130,7 @@ S: Maintained
|
|||||||
8169 10/100/1000 GIGABIT ETHERNET DRIVER
|
8169 10/100/1000 GIGABIT ETHERNET DRIVER
|
||||||
P: Francois Romieu
|
P: Francois Romieu
|
||||||
M: romieu@fr.zoreil.com
|
M: romieu@fr.zoreil.com
|
||||||
L: netdev@oss.sgi.com
|
L: netdev@vger.kernel.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
8250/16?50 (AND CLONE UARTS) SERIAL DRIVER
|
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.]
|
8390 NETWORK DRIVERS [WD80x3/SMC-ELITE, SMC-ULTRA, NE2000, 3C503, etc.]
|
||||||
P: Paul Gortmaker
|
P: Paul Gortmaker
|
||||||
M: p_gortmaker@yahoo.com
|
M: p_gortmaker@yahoo.com
|
||||||
L: netdev@oss.sgi.com
|
L: netdev@vger.kernel.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
A2232 SERIAL BOARD DRIVER
|
A2232 SERIAL BOARD DRIVER
|
||||||
@ -239,6 +239,12 @@ L: linux-usb-devel@lists.sourceforge.net
|
|||||||
W: http://www.linux-usb.org/SpeedTouch/
|
W: http://www.linux-usb.org/SpeedTouch/
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
|
ALI1563 I2C DRIVER
|
||||||
|
P: Rudolf Marek
|
||||||
|
M: r.marek@sh.cvut.cz
|
||||||
|
L: sensors@stimpy.netroedge.com
|
||||||
|
S: Maintained
|
||||||
|
|
||||||
ALPHA PORT
|
ALPHA PORT
|
||||||
P: Richard Henderson
|
P: Richard Henderson
|
||||||
M: rth@twiddle.net
|
M: rth@twiddle.net
|
||||||
@ -326,7 +332,7 @@ S: Maintained
|
|||||||
|
|
||||||
ARPD SUPPORT
|
ARPD SUPPORT
|
||||||
P: Jonathan Layes
|
P: Jonathan Layes
|
||||||
L: netdev@oss.sgi.com
|
L: netdev@vger.kernel.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
ASUS ACPI EXTRAS DRIVER
|
ASUS ACPI EXTRAS DRIVER
|
||||||
@ -700,7 +706,7 @@ S: Orphaned
|
|||||||
|
|
||||||
DIGI RIGHTSWITCH NETWORK DRIVER
|
DIGI RIGHTSWITCH NETWORK DRIVER
|
||||||
P: Rick Richardson
|
P: Rick Richardson
|
||||||
L: netdev@oss.sgi.com
|
L: netdev@vger.kernel.org
|
||||||
W: http://www.digi.com
|
W: http://www.digi.com
|
||||||
S: Orphaned
|
S: Orphaned
|
||||||
|
|
||||||
@ -730,6 +736,11 @@ M: tori@unhappy.mine.nu
|
|||||||
L: linux-kernel@vger.kernel.org
|
L: linux-kernel@vger.kernel.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
|
DOCBOOK FOR DOCUMENTATION
|
||||||
|
P: Martin Waitz
|
||||||
|
M: tali@admingilde.org
|
||||||
|
S: Maintained
|
||||||
|
|
||||||
DOUBLETALK DRIVER
|
DOUBLETALK DRIVER
|
||||||
P: James R. Van Zandt
|
P: James R. Van Zandt
|
||||||
M: jrv@vanzandt.mv.com
|
M: jrv@vanzandt.mv.com
|
||||||
@ -806,7 +817,7 @@ S: Maintained
|
|||||||
ETHEREXPRESS-16 NETWORK DRIVER
|
ETHEREXPRESS-16 NETWORK DRIVER
|
||||||
P: Philip Blundell
|
P: Philip Blundell
|
||||||
M: philb@gnu.org
|
M: philb@gnu.org
|
||||||
L: netdev@oss.sgi.com
|
L: netdev@vger.kernel.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
ETHERNET BRIDGE
|
ETHERNET BRIDGE
|
||||||
@ -869,7 +880,7 @@ S: Maintained
|
|||||||
FRAME RELAY DLCI/FRAD (Sangoma drivers too)
|
FRAME RELAY DLCI/FRAD (Sangoma drivers too)
|
||||||
P: Mike McLagan
|
P: Mike McLagan
|
||||||
M: mike.mclagan@linux.org
|
M: mike.mclagan@linux.org
|
||||||
L: netdev@oss.sgi.com
|
L: netdev@vger.kernel.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
FREEVXFS FILESYSTEM
|
FREEVXFS FILESYSTEM
|
||||||
@ -1023,8 +1034,8 @@ W: http://www.ia64-linux.org/
|
|||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
SN-IA64 (Itanium) SUB-PLATFORM
|
SN-IA64 (Itanium) SUB-PLATFORM
|
||||||
P: Jesse Barnes
|
P: Greg Edwards
|
||||||
M: jbarnes@sgi.com
|
M: edwardsg@sgi.com
|
||||||
L: linux-altix@sgi.com
|
L: linux-altix@sgi.com
|
||||||
L: linux-ia64@vger.kernel.org
|
L: linux-ia64@vger.kernel.org
|
||||||
W: http://www.sgi.com/altix
|
W: http://www.sgi.com/altix
|
||||||
@ -1209,7 +1220,7 @@ S: Maintained
|
|||||||
IPX NETWORK LAYER
|
IPX NETWORK LAYER
|
||||||
P: Arnaldo Carvalho de Melo
|
P: Arnaldo Carvalho de Melo
|
||||||
M: acme@conectiva.com.br
|
M: acme@conectiva.com.br
|
||||||
L: netdev@oss.sgi.com
|
L: netdev@vger.kernel.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
IRDA SUBSYSTEM
|
IRDA SUBSYSTEM
|
||||||
@ -1476,7 +1487,7 @@ MARVELL MV64340 ETHERNET DRIVER
|
|||||||
P: Manish Lachwani
|
P: Manish Lachwani
|
||||||
M: Manish_Lachwani@pmc-sierra.com
|
M: Manish_Lachwani@pmc-sierra.com
|
||||||
L: linux-mips@linux-mips.org
|
L: linux-mips@linux-mips.org
|
||||||
L: netdev@oss.sgi.com
|
L: netdev@vger.kernel.org
|
||||||
S: Supported
|
S: Supported
|
||||||
|
|
||||||
MATROX FRAMEBUFFER DRIVER
|
MATROX FRAMEBUFFER DRIVER
|
||||||
@ -1586,13 +1597,13 @@ P: Andrew Morton
|
|||||||
M: akpm@osdl.org
|
M: akpm@osdl.org
|
||||||
P: Jeff Garzik
|
P: Jeff Garzik
|
||||||
M: jgarzik@pobox.com
|
M: jgarzik@pobox.com
|
||||||
L: netdev@oss.sgi.com
|
L: netdev@vger.kernel.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
NETWORKING [GENERAL]
|
NETWORKING [GENERAL]
|
||||||
P: Networking Team
|
P: Networking Team
|
||||||
M: netdev@oss.sgi.com
|
M: netdev@vger.kernel.org
|
||||||
L: netdev@oss.sgi.com
|
L: netdev@vger.kernel.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
NETWORKING [IPv4/IPv6]
|
NETWORKING [IPv4/IPv6]
|
||||||
@ -1608,7 +1619,7 @@ P: Hideaki YOSHIFUJI
|
|||||||
M: yoshfuji@linux-ipv6.org
|
M: yoshfuji@linux-ipv6.org
|
||||||
P: Patrick McHardy
|
P: Patrick McHardy
|
||||||
M: kaber@coreworks.de
|
M: kaber@coreworks.de
|
||||||
L: netdev@oss.sgi.com
|
L: netdev@vger.kernel.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
IPVS
|
IPVS
|
||||||
@ -1628,7 +1639,7 @@ NI5010 NETWORK DRIVER
|
|||||||
P: Jan-Pascal van Best and Andreas Mohr
|
P: Jan-Pascal van Best and Andreas Mohr
|
||||||
M: Jan-Pascal van Best <jvbest@qv3pluto.leidenuniv.nl>
|
M: Jan-Pascal van Best <jvbest@qv3pluto.leidenuniv.nl>
|
||||||
M: Andreas Mohr <100.30936@germany.net>
|
M: Andreas Mohr <100.30936@germany.net>
|
||||||
L: netdev@oss.sgi.com
|
L: netdev@vger.kernel.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
NINJA SCSI-3 / NINJA SCSI-32Bi (16bit/CardBus) PCMCIA SCSI HOST ADAPTER DRIVER
|
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
|
M: p2@ace.ulyssis.student.kuleuven.ac.be
|
||||||
P: Mike Phillips
|
P: Mike Phillips
|
||||||
M: mikep@linuxtr.net
|
M: mikep@linuxtr.net
|
||||||
L: netdev@oss.sgi.com
|
L: netdev@vger.kernel.org
|
||||||
L: linux-tr@linuxtr.net
|
L: linux-tr@linuxtr.net
|
||||||
W: http://www.linuxtr.net
|
W: http://www.linuxtr.net
|
||||||
S: Maintained
|
S: Maintained
|
||||||
@ -1777,7 +1788,7 @@ S: Unmaintained
|
|||||||
PCNET32 NETWORK DRIVER
|
PCNET32 NETWORK DRIVER
|
||||||
P: Thomas Bogendörfer
|
P: Thomas Bogendörfer
|
||||||
M: tsbogend@alpha.franken.de
|
M: tsbogend@alpha.franken.de
|
||||||
L: netdev@oss.sgi.com
|
L: netdev@vger.kernel.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
PHRAM MTD DRIVER
|
PHRAM MTD DRIVER
|
||||||
@ -1789,7 +1800,7 @@ S: Maintained
|
|||||||
POSIX CLOCKS and TIMERS
|
POSIX CLOCKS and TIMERS
|
||||||
P: George Anzinger
|
P: George Anzinger
|
||||||
M: george@mvista.com
|
M: george@mvista.com
|
||||||
L: netdev@oss.sgi.com
|
L: netdev@vger.kernel.org
|
||||||
S: Supported
|
S: Supported
|
||||||
|
|
||||||
PNP SUPPORT
|
PNP SUPPORT
|
||||||
@ -1824,7 +1835,7 @@ S: Supported
|
|||||||
PRISM54 WIRELESS DRIVER
|
PRISM54 WIRELESS DRIVER
|
||||||
P: Prism54 Development Team
|
P: Prism54 Development Team
|
||||||
M: prism54-private@prism54.org
|
M: prism54-private@prism54.org
|
||||||
L: netdev@oss.sgi.com
|
L: netdev@vger.kernel.org
|
||||||
W: http://prism54.org
|
W: http://prism54.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
@ -2041,7 +2052,7 @@ SIS 900/7016 FAST ETHERNET DRIVER
|
|||||||
P: Daniele Venzano
|
P: Daniele Venzano
|
||||||
M: venza@brownhat.org
|
M: venza@brownhat.org
|
||||||
W: http://www.brownhat.org/sis900.html
|
W: http://www.brownhat.org/sis900.html
|
||||||
L: netdev@oss.sgi.com
|
L: netdev@vger.kernel.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
SIS FRAMEBUFFER DRIVER
|
SIS FRAMEBUFFER DRIVER
|
||||||
@ -2100,7 +2111,7 @@ S: Maintained
|
|||||||
SONIC NETWORK DRIVER
|
SONIC NETWORK DRIVER
|
||||||
P: Thomas Bogendoerfer
|
P: Thomas Bogendoerfer
|
||||||
M: tsbogend@alpha.franken.de
|
M: tsbogend@alpha.franken.de
|
||||||
L: netdev@oss.sgi.com
|
L: netdev@vger.kernel.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
SONY VAIO CONTROL DEVICE DRIVER
|
SONY VAIO CONTROL DEVICE DRIVER
|
||||||
@ -2157,7 +2168,7 @@ S: Supported
|
|||||||
SPX NETWORK LAYER
|
SPX NETWORK LAYER
|
||||||
P: Jay Schulist
|
P: Jay Schulist
|
||||||
M: jschlst@samba.org
|
M: jschlst@samba.org
|
||||||
L: netdev@oss.sgi.com
|
L: netdev@vger.kernel.org
|
||||||
S: Supported
|
S: Supported
|
||||||
|
|
||||||
SRM (Alpha) environment access
|
SRM (Alpha) environment access
|
||||||
@ -2236,7 +2247,7 @@ S: Maintained
|
|||||||
TOKEN-RING NETWORK DRIVER
|
TOKEN-RING NETWORK DRIVER
|
||||||
P: Mike Phillips
|
P: Mike Phillips
|
||||||
M: mikep@linuxtr.net
|
M: mikep@linuxtr.net
|
||||||
L: netdev@oss.sgi.com
|
L: netdev@vger.kernel.org
|
||||||
L: linux-tr@linuxtr.net
|
L: linux-tr@linuxtr.net
|
||||||
W: http://www.linuxtr.net
|
W: http://www.linuxtr.net
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
2
Makefile
2
Makefile
@ -1,7 +1,7 @@
|
|||||||
VERSION = 2
|
VERSION = 2
|
||||||
PATCHLEVEL = 6
|
PATCHLEVEL = 6
|
||||||
SUBLEVEL = 12
|
SUBLEVEL = 12
|
||||||
EXTRAVERSION =-rc5
|
EXTRAVERSION =
|
||||||
NAME=Woozy Numbat
|
NAME=Woozy Numbat
|
||||||
|
|
||||||
# *DOCUMENTATION*
|
# *DOCUMENTATION*
|
||||||
|
@ -67,10 +67,6 @@ config GENERIC_BUST_SPINLOCK
|
|||||||
config GENERIC_ISA_DMA
|
config GENERIC_ISA_DMA
|
||||||
bool
|
bool
|
||||||
|
|
||||||
config GENERIC_IOMAP
|
|
||||||
bool
|
|
||||||
default y
|
|
||||||
|
|
||||||
config FIQ
|
config FIQ
|
||||||
bool
|
bool
|
||||||
|
|
||||||
@ -202,6 +198,11 @@ config ARCH_H720X
|
|||||||
help
|
help
|
||||||
This enables support for systems based on the Hynix HMS720x
|
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
|
endchoice
|
||||||
|
|
||||||
source "arch/arm/mach-clps711x/Kconfig"
|
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-versatile/Kconfig"
|
||||||
|
|
||||||
|
source "arch/arm/mach-aaec2000/Kconfig"
|
||||||
|
|
||||||
# Definitions to make life easier
|
# Definitions to make life easier
|
||||||
config ARCH_ACORN
|
config ARCH_ACORN
|
||||||
bool
|
bool
|
||||||
@ -277,7 +280,7 @@ config ISA_DMA_API
|
|||||||
default y
|
default y
|
||||||
|
|
||||||
config PCI
|
config PCI
|
||||||
bool "PCI support" if ARCH_INTEGRATOR_AP
|
bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB
|
||||||
help
|
help
|
||||||
Find out whether you have a PCI motherboard. PCI is the name of a
|
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
|
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
|
config CPU_FREQ_SA1100
|
||||||
bool
|
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
|
default y
|
||||||
|
|
||||||
config CPU_FREQ_SA1110
|
config CPU_FREQ_SA1110
|
||||||
@ -689,7 +692,9 @@ source "drivers/block/Kconfig"
|
|||||||
|
|
||||||
source "drivers/acorn/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"
|
source "drivers/ide/Kconfig"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
@ -97,6 +97,7 @@ textaddr-$(CONFIG_ARCH_FORTUNET) := 0xc0008000
|
|||||||
machine-$(CONFIG_ARCH_VERSATILE) := versatile
|
machine-$(CONFIG_ARCH_VERSATILE) := versatile
|
||||||
machine-$(CONFIG_ARCH_IMX) := imx
|
machine-$(CONFIG_ARCH_IMX) := imx
|
||||||
machine-$(CONFIG_ARCH_H720X) := h720x
|
machine-$(CONFIG_ARCH_H720X) := h720x
|
||||||
|
machine-$(CONFIG_ARCH_AAEC2000) := aaec2000
|
||||||
|
|
||||||
ifeq ($(CONFIG_ARCH_EBSA110),y)
|
ifeq ($(CONFIG_ARCH_EBSA110),y)
|
||||||
# This is what happens if you forget the IOCS16 line.
|
# This is what happens if you forget the IOCS16 line.
|
||||||
|
@ -47,3 +47,10 @@ __XScale_start:
|
|||||||
orr r7, r7, #(MACH_TYPE_GTWX5715 & 0xff00)
|
orr r7, r7, #(MACH_TYPE_GTWX5715 & 0xff00)
|
||||||
#endif
|
#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...) \
|
#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); \
|
struct amba_device *dev = to_amba_device(_dev); \
|
||||||
return sprintf(buf, fmt, arg); \
|
return sprintf(buf, fmt, arg); \
|
||||||
|
@ -30,6 +30,8 @@
|
|||||||
#include <linux/dmapool.h>
|
#include <linux/dmapool.h>
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
|
|
||||||
|
#include <asm/cacheflush.h>
|
||||||
|
|
||||||
#undef DEBUG
|
#undef DEBUG
|
||||||
|
|
||||||
#undef STATS
|
#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++ );
|
DO_STATS ( device_info->bounce_count++ );
|
||||||
|
|
||||||
if ((dir == DMA_FROM_DEVICE) ||
|
if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) {
|
||||||
(dir == DMA_BIDIRECTIONAL)) {
|
unsigned long ptr;
|
||||||
|
|
||||||
dev_dbg(dev,
|
dev_dbg(dev,
|
||||||
"%s: copy back safe %p to unsafe %p size %d\n",
|
"%s: copy back safe %p to unsafe %p size %d\n",
|
||||||
__func__, buf->safe, buf->ptr, size);
|
__func__, buf->safe, buf->ptr, size);
|
||||||
memcpy(buf->ptr, buf->safe, 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);
|
free_safe_buffer(device_info, buf);
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
* them early in the boot process, then pass them to the appropriate drivers.
|
* 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.
|
* Not all devices use all paramaters but the format is common to all.
|
||||||
*/
|
*/
|
||||||
#ifdef ARCH_SA1100
|
#ifdef CONFIG_ARCH_SA1100
|
||||||
#define PARAM_BASE 0xe8ffc000
|
#define PARAM_BASE 0xe8ffc000
|
||||||
#else
|
#else
|
||||||
#define PARAM_BASE 0xa0000a00
|
#define PARAM_BASE 0xa0000a00
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#
|
#
|
||||||
# Automatically generated make config: don't edit
|
# Automatically generated make config: don't edit
|
||||||
# Linux kernel version: 2.6.12-rc1-bk2
|
# Linux kernel version: 2.6.12-rc6-git3
|
||||||
# Sat Mar 26 21:32:26 2005
|
# Thu Jun 9 19:00:50 2005
|
||||||
#
|
#
|
||||||
CONFIG_ARM=y
|
CONFIG_ARM=y
|
||||||
CONFIG_MMU=y
|
CONFIG_MMU=y
|
||||||
@ -16,6 +16,7 @@ CONFIG_GENERIC_IOMAP=y
|
|||||||
CONFIG_EXPERIMENTAL=y
|
CONFIG_EXPERIMENTAL=y
|
||||||
CONFIG_CLEAN_COMPILE=y
|
CONFIG_CLEAN_COMPILE=y
|
||||||
CONFIG_BROKEN_ON_SMP=y
|
CONFIG_BROKEN_ON_SMP=y
|
||||||
|
CONFIG_INIT_ENV_ARG_LIMIT=32
|
||||||
|
|
||||||
#
|
#
|
||||||
# General setup
|
# General setup
|
||||||
@ -34,6 +35,8 @@ CONFIG_EMBEDDED=y
|
|||||||
CONFIG_KALLSYMS=y
|
CONFIG_KALLSYMS=y
|
||||||
# CONFIG_KALLSYMS_ALL is not set
|
# CONFIG_KALLSYMS_ALL is not set
|
||||||
# CONFIG_KALLSYMS_EXTRA_PASS is not set
|
# CONFIG_KALLSYMS_EXTRA_PASS is not set
|
||||||
|
CONFIG_PRINTK=y
|
||||||
|
CONFIG_BUG=y
|
||||||
CONFIG_BASE_FULL=y
|
CONFIG_BASE_FULL=y
|
||||||
CONFIG_FUTEX=y
|
CONFIG_FUTEX=y
|
||||||
CONFIG_EPOLL=y
|
CONFIG_EPOLL=y
|
||||||
@ -109,7 +112,6 @@ CONFIG_CPU_ABRT_EV4=y
|
|||||||
CONFIG_CPU_CACHE_V4WB=y
|
CONFIG_CPU_CACHE_V4WB=y
|
||||||
CONFIG_CPU_CACHE_VIVT=y
|
CONFIG_CPU_CACHE_VIVT=y
|
||||||
CONFIG_CPU_TLB_V4WB=y
|
CONFIG_CPU_TLB_V4WB=y
|
||||||
CONFIG_CPU_MINICACHE=y
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Processor Features
|
# Processor Features
|
||||||
@ -122,6 +124,7 @@ CONFIG_FORCE_MAX_ZONEORDER=9
|
|||||||
# Bus support
|
# Bus support
|
||||||
#
|
#
|
||||||
CONFIG_ISA=y
|
CONFIG_ISA=y
|
||||||
|
CONFIG_ISA_DMA_API=y
|
||||||
|
|
||||||
#
|
#
|
||||||
# PCCARD (PCMCIA/CardBus) support
|
# PCCARD (PCMCIA/CardBus) support
|
||||||
@ -131,6 +134,7 @@ CONFIG_ISA=y
|
|||||||
#
|
#
|
||||||
# Kernel Features
|
# Kernel Features
|
||||||
#
|
#
|
||||||
|
# CONFIG_SMP is not set
|
||||||
# CONFIG_PREEMPT is not set
|
# CONFIG_PREEMPT is not set
|
||||||
CONFIG_DISCONTIGMEM=y
|
CONFIG_DISCONTIGMEM=y
|
||||||
# CONFIG_LEDS is not set
|
# CONFIG_LEDS is not set
|
||||||
@ -152,12 +156,14 @@ CONFIG_CPU_FREQ_TABLE=y
|
|||||||
# CONFIG_CPU_FREQ_DEBUG is not set
|
# CONFIG_CPU_FREQ_DEBUG is not set
|
||||||
CONFIG_CPU_FREQ_STAT=y
|
CONFIG_CPU_FREQ_STAT=y
|
||||||
# CONFIG_CPU_FREQ_STAT_DETAILS is not set
|
# CONFIG_CPU_FREQ_STAT_DETAILS is not set
|
||||||
CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
|
# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
|
||||||
# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
|
CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
|
||||||
CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
|
CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
|
||||||
# CONFIG_CPU_FREQ_GOV_POWERSAVE 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_GOV_ONDEMAND is not set
|
||||||
|
# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
|
||||||
|
CONFIG_CPU_FREQ_SA1100=y
|
||||||
|
|
||||||
#
|
#
|
||||||
# Floating point emulation
|
# Floating point emulation
|
||||||
@ -294,7 +300,6 @@ CONFIG_PARPORT_NOT_PC=y
|
|||||||
#
|
#
|
||||||
# Block devices
|
# Block devices
|
||||||
#
|
#
|
||||||
# CONFIG_BLK_DEV_FD is not set
|
|
||||||
# CONFIG_BLK_DEV_XD is not set
|
# CONFIG_BLK_DEV_XD is not set
|
||||||
# CONFIG_PARIDE is not set
|
# CONFIG_PARIDE is not set
|
||||||
# CONFIG_BLK_DEV_COW_COMMON is not set
|
# CONFIG_BLK_DEV_COW_COMMON is not set
|
||||||
@ -428,7 +433,6 @@ CONFIG_NET=y
|
|||||||
#
|
#
|
||||||
CONFIG_PACKET=y
|
CONFIG_PACKET=y
|
||||||
# CONFIG_PACKET_MMAP is not set
|
# CONFIG_PACKET_MMAP is not set
|
||||||
# CONFIG_NETLINK_DEV is not set
|
|
||||||
CONFIG_UNIX=y
|
CONFIG_UNIX=y
|
||||||
# CONFIG_NET_KEY is not set
|
# CONFIG_NET_KEY is not set
|
||||||
CONFIG_INET=y
|
CONFIG_INET=y
|
||||||
@ -526,6 +530,7 @@ CONFIG_IRDA_ULTRA=y
|
|||||||
# CONFIG_SMC_IRCC_FIR is not set
|
# CONFIG_SMC_IRCC_FIR is not set
|
||||||
# CONFIG_ALI_FIR is not set
|
# CONFIG_ALI_FIR is not set
|
||||||
CONFIG_SA1100_FIR=y
|
CONFIG_SA1100_FIR=y
|
||||||
|
# CONFIG_VIA_FIR is not set
|
||||||
CONFIG_BT=m
|
CONFIG_BT=m
|
||||||
CONFIG_BT_L2CAP=m
|
CONFIG_BT_L2CAP=m
|
||||||
# CONFIG_BT_SCO is not set
|
# CONFIG_BT_SCO is not set
|
||||||
@ -618,7 +623,6 @@ CONFIG_NET_WIRELESS=y
|
|||||||
#
|
#
|
||||||
# CONFIG_SERIO is not set
|
# CONFIG_SERIO is not set
|
||||||
# CONFIG_GAMEPORT is not set
|
# CONFIG_GAMEPORT is not set
|
||||||
CONFIG_SOUND_GAMEPORT=y
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Character devices
|
# Character devices
|
||||||
@ -687,7 +691,6 @@ CONFIG_RTC=m
|
|||||||
#
|
#
|
||||||
# TPM devices
|
# TPM devices
|
||||||
#
|
#
|
||||||
# CONFIG_TCG_TPM is not set
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# I2C support
|
# I2C support
|
||||||
@ -736,6 +739,7 @@ CONFIG_I2C_ELEKTOR=m
|
|||||||
# CONFIG_SENSORS_LM85 is not set
|
# CONFIG_SENSORS_LM85 is not set
|
||||||
# CONFIG_SENSORS_LM87 is not set
|
# CONFIG_SENSORS_LM87 is not set
|
||||||
# CONFIG_SENSORS_LM90 is not set
|
# CONFIG_SENSORS_LM90 is not set
|
||||||
|
# CONFIG_SENSORS_LM92 is not set
|
||||||
# CONFIG_SENSORS_MAX1619 is not set
|
# CONFIG_SENSORS_MAX1619 is not set
|
||||||
# CONFIG_SENSORS_PC87360 is not set
|
# CONFIG_SENSORS_PC87360 is not set
|
||||||
# CONFIG_SENSORS_SMSC47B397 is not set
|
# CONFIG_SENSORS_SMSC47B397 is not set
|
||||||
@ -747,6 +751,7 @@ CONFIG_I2C_ELEKTOR=m
|
|||||||
#
|
#
|
||||||
# Other I2C Chip support
|
# Other I2C Chip support
|
||||||
#
|
#
|
||||||
|
# CONFIG_SENSORS_DS1337 is not set
|
||||||
# CONFIG_SENSORS_EEPROM is not set
|
# CONFIG_SENSORS_EEPROM is not set
|
||||||
# CONFIG_SENSORS_PCF8574 is not set
|
# CONFIG_SENSORS_PCF8574 is not set
|
||||||
# CONFIG_SENSORS_PCF8591 is not set
|
# CONFIG_SENSORS_PCF8591 is not set
|
||||||
@ -871,7 +876,6 @@ CONFIG_USB_PRINTER=m
|
|||||||
#
|
#
|
||||||
CONFIG_USB_STORAGE=y
|
CONFIG_USB_STORAGE=y
|
||||||
CONFIG_USB_STORAGE_DEBUG=y
|
CONFIG_USB_STORAGE_DEBUG=y
|
||||||
# CONFIG_USB_STORAGE_RW_DETECT is not set
|
|
||||||
# CONFIG_USB_STORAGE_DATAFAB is not set
|
# CONFIG_USB_STORAGE_DATAFAB is not set
|
||||||
# CONFIG_USB_STORAGE_FREECOM is not set
|
# CONFIG_USB_STORAGE_FREECOM is not set
|
||||||
# CONFIG_USB_STORAGE_ISD200 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=m
|
||||||
CONFIG_USB_SERIAL_GENERIC=y
|
CONFIG_USB_SERIAL_GENERIC=y
|
||||||
|
# CONFIG_USB_SERIAL_AIRPRIME is not set
|
||||||
CONFIG_USB_SERIAL_BELKIN=m
|
CONFIG_USB_SERIAL_BELKIN=m
|
||||||
CONFIG_USB_SERIAL_WHITEHEAT=m
|
CONFIG_USB_SERIAL_WHITEHEAT=m
|
||||||
CONFIG_USB_SERIAL_DIGI_ACCELEPORT=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_CYPRESS_M8 is not set
|
||||||
CONFIG_USB_SERIAL_EMPEG=m
|
CONFIG_USB_SERIAL_EMPEG=m
|
||||||
CONFIG_USB_SERIAL_FTDI_SIO=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_KOBIL_SCT is not set
|
||||||
CONFIG_USB_SERIAL_MCT_U232=m
|
CONFIG_USB_SERIAL_MCT_U232=m
|
||||||
CONFIG_USB_SERIAL_PL2303=m
|
CONFIG_USB_SERIAL_PL2303=m
|
||||||
|
# CONFIG_USB_SERIAL_HP4X is not set
|
||||||
# CONFIG_USB_SERIAL_SAFE is not set
|
# CONFIG_USB_SERIAL_SAFE is not set
|
||||||
# CONFIG_USB_SERIAL_TI is not set
|
# CONFIG_USB_SERIAL_TI is not set
|
||||||
CONFIG_USB_SERIAL_CYBERJACK=m
|
CONFIG_USB_SERIAL_CYBERJACK=m
|
||||||
|
@ -50,7 +50,13 @@ CONFIG_BASE_SMALL=0
|
|||||||
#
|
#
|
||||||
# Loadable module support
|
# 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
|
# System Type
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#
|
#
|
||||||
# Automatically generated make config: don't edit
|
# Automatically generated make config: don't edit
|
||||||
# Linux kernel version: 2.6.12-rc1-bk2
|
# Linux kernel version: 2.6.12-rc4
|
||||||
# Mon Mar 28 00:02:26 2005
|
# Thu Jun 9 01:59:03 2005
|
||||||
#
|
#
|
||||||
CONFIG_ARM=y
|
CONFIG_ARM=y
|
||||||
CONFIG_MMU=y
|
CONFIG_MMU=y
|
||||||
@ -16,6 +16,7 @@ CONFIG_GENERIC_IOMAP=y
|
|||||||
CONFIG_EXPERIMENTAL=y
|
CONFIG_EXPERIMENTAL=y
|
||||||
CONFIG_CLEAN_COMPILE=y
|
CONFIG_CLEAN_COMPILE=y
|
||||||
CONFIG_BROKEN_ON_SMP=y
|
CONFIG_BROKEN_ON_SMP=y
|
||||||
|
CONFIG_INIT_ENV_ARG_LIMIT=32
|
||||||
|
|
||||||
#
|
#
|
||||||
# General setup
|
# General setup
|
||||||
@ -33,6 +34,8 @@ CONFIG_KOBJECT_UEVENT=y
|
|||||||
# CONFIG_EMBEDDED is not set
|
# CONFIG_EMBEDDED is not set
|
||||||
CONFIG_KALLSYMS=y
|
CONFIG_KALLSYMS=y
|
||||||
# CONFIG_KALLSYMS_EXTRA_PASS is not set
|
# CONFIG_KALLSYMS_EXTRA_PASS is not set
|
||||||
|
CONFIG_PRINTK=y
|
||||||
|
CONFIG_BUG=y
|
||||||
CONFIG_BASE_FULL=y
|
CONFIG_BASE_FULL=y
|
||||||
CONFIG_FUTEX=y
|
CONFIG_FUTEX=y
|
||||||
CONFIG_EPOLL=y
|
CONFIG_EPOLL=y
|
||||||
@ -120,6 +123,7 @@ CONFIG_CPU_MINICACHE=y
|
|||||||
# Bus support
|
# Bus support
|
||||||
#
|
#
|
||||||
CONFIG_ISA=y
|
CONFIG_ISA=y
|
||||||
|
CONFIG_ISA_DMA_API=y
|
||||||
|
|
||||||
#
|
#
|
||||||
# PCCARD (PCMCIA/CardBus) support
|
# PCCARD (PCMCIA/CardBus) support
|
||||||
@ -138,6 +142,7 @@ CONFIG_PCMCIA_SA1100=y
|
|||||||
#
|
#
|
||||||
# Kernel Features
|
# Kernel Features
|
||||||
#
|
#
|
||||||
|
# CONFIG_SMP is not set
|
||||||
# CONFIG_PREEMPT is not set
|
# CONFIG_PREEMPT is not set
|
||||||
CONFIG_DISCONTIGMEM=y
|
CONFIG_DISCONTIGMEM=y
|
||||||
# CONFIG_LEDS is not set
|
# CONFIG_LEDS is not set
|
||||||
@ -159,12 +164,13 @@ CONFIG_CPU_FREQ_TABLE=y
|
|||||||
# CONFIG_CPU_FREQ_DEBUG is not set
|
# CONFIG_CPU_FREQ_DEBUG is not set
|
||||||
CONFIG_CPU_FREQ_STAT=y
|
CONFIG_CPU_FREQ_STAT=y
|
||||||
# CONFIG_CPU_FREQ_STAT_DETAILS is not set
|
# CONFIG_CPU_FREQ_STAT_DETAILS is not set
|
||||||
CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
|
# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
|
||||||
# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
|
CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
|
||||||
CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
|
# CONFIG_CPU_FREQ_GOV_PERFORMANCE is not set
|
||||||
# CONFIG_CPU_FREQ_GOV_POWERSAVE 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_GOV_ONDEMAND is not set
|
||||||
|
CONFIG_CPU_FREQ_SA1100=y
|
||||||
|
|
||||||
#
|
#
|
||||||
# Floating point emulation
|
# Floating point emulation
|
||||||
@ -298,7 +304,6 @@ CONFIG_MTD_SA1100=y
|
|||||||
#
|
#
|
||||||
# Block devices
|
# Block devices
|
||||||
#
|
#
|
||||||
# CONFIG_BLK_DEV_FD is not set
|
|
||||||
# CONFIG_BLK_DEV_XD is not set
|
# CONFIG_BLK_DEV_XD is not set
|
||||||
# CONFIG_BLK_DEV_COW_COMMON is not set
|
# CONFIG_BLK_DEV_COW_COMMON is not set
|
||||||
CONFIG_BLK_DEV_LOOP=m
|
CONFIG_BLK_DEV_LOOP=m
|
||||||
@ -379,7 +384,6 @@ CONFIG_NET=y
|
|||||||
# Networking options
|
# Networking options
|
||||||
#
|
#
|
||||||
# CONFIG_PACKET is not set
|
# CONFIG_PACKET is not set
|
||||||
# CONFIG_NETLINK_DEV is not set
|
|
||||||
CONFIG_UNIX=y
|
CONFIG_UNIX=y
|
||||||
# CONFIG_NET_KEY is not set
|
# CONFIG_NET_KEY is not set
|
||||||
CONFIG_INET=y
|
CONFIG_INET=y
|
||||||
@ -476,6 +480,7 @@ CONFIG_IRCOMM=m
|
|||||||
# CONFIG_SMC_IRCC_FIR is not set
|
# CONFIG_SMC_IRCC_FIR is not set
|
||||||
# CONFIG_ALI_FIR is not set
|
# CONFIG_ALI_FIR is not set
|
||||||
CONFIG_SA1100_FIR=m
|
CONFIG_SA1100_FIR=m
|
||||||
|
# CONFIG_VIA_FIR is not set
|
||||||
# CONFIG_BT is not set
|
# CONFIG_BT is not set
|
||||||
CONFIG_NETDEVICES=y
|
CONFIG_NETDEVICES=y
|
||||||
# CONFIG_DUMMY is not set
|
# CONFIG_DUMMY is not set
|
||||||
@ -647,7 +652,6 @@ CONFIG_LEGACY_PTY_COUNT=256
|
|||||||
#
|
#
|
||||||
# TPM devices
|
# TPM devices
|
||||||
#
|
#
|
||||||
# CONFIG_TCG_TPM is not set
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# I2C support
|
# I2C support
|
||||||
@ -676,9 +680,11 @@ CONFIG_FB_CFB_FILLRECT=y
|
|||||||
CONFIG_FB_CFB_COPYAREA=y
|
CONFIG_FB_CFB_COPYAREA=y
|
||||||
CONFIG_FB_CFB_IMAGEBLIT=y
|
CONFIG_FB_CFB_IMAGEBLIT=y
|
||||||
CONFIG_FB_SOFT_CURSOR=y
|
CONFIG_FB_SOFT_CURSOR=y
|
||||||
|
# CONFIG_FB_MACMODES is not set
|
||||||
# CONFIG_FB_MODE_HELPERS is not set
|
# CONFIG_FB_MODE_HELPERS is not set
|
||||||
# CONFIG_FB_TILEBLITTING is not set
|
# CONFIG_FB_TILEBLITTING is not set
|
||||||
CONFIG_FB_SA1100=y
|
CONFIG_FB_SA1100=y
|
||||||
|
# CONFIG_FB_S1D13XXX is not set
|
||||||
# CONFIG_FB_VIRTUAL is not set
|
# CONFIG_FB_VIRTUAL is not set
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#
|
#
|
||||||
# Automatically generated make config: don't edit
|
# Automatically generated make config: don't edit
|
||||||
# Linux kernel version: 2.6.12-rc1-bk2
|
# Linux kernel version: 2.6.12-rc6-git3
|
||||||
# Mon Mar 28 00:22:34 2005
|
# Thu Jun 9 20:58:58 2005
|
||||||
#
|
#
|
||||||
CONFIG_ARM=y
|
CONFIG_ARM=y
|
||||||
CONFIG_MMU=y
|
CONFIG_MMU=y
|
||||||
@ -16,6 +16,7 @@ CONFIG_GENERIC_IOMAP=y
|
|||||||
CONFIG_EXPERIMENTAL=y
|
CONFIG_EXPERIMENTAL=y
|
||||||
CONFIG_CLEAN_COMPILE=y
|
CONFIG_CLEAN_COMPILE=y
|
||||||
CONFIG_BROKEN_ON_SMP=y
|
CONFIG_BROKEN_ON_SMP=y
|
||||||
|
CONFIG_INIT_ENV_ARG_LIMIT=32
|
||||||
|
|
||||||
#
|
#
|
||||||
# General setup
|
# General setup
|
||||||
@ -34,6 +35,8 @@ CONFIG_KOBJECT_UEVENT=y
|
|||||||
CONFIG_KALLSYMS=y
|
CONFIG_KALLSYMS=y
|
||||||
# CONFIG_KALLSYMS_ALL is not set
|
# CONFIG_KALLSYMS_ALL is not set
|
||||||
# CONFIG_KALLSYMS_EXTRA_PASS is not set
|
# CONFIG_KALLSYMS_EXTRA_PASS is not set
|
||||||
|
CONFIG_PRINTK=y
|
||||||
|
CONFIG_BUG=y
|
||||||
CONFIG_BASE_FULL=y
|
CONFIG_BASE_FULL=y
|
||||||
CONFIG_FUTEX=y
|
CONFIG_FUTEX=y
|
||||||
CONFIG_EPOLL=y
|
CONFIG_EPOLL=y
|
||||||
@ -109,7 +112,6 @@ CONFIG_CPU_ABRT_EV4=y
|
|||||||
CONFIG_CPU_CACHE_V4WB=y
|
CONFIG_CPU_CACHE_V4WB=y
|
||||||
CONFIG_CPU_CACHE_VIVT=y
|
CONFIG_CPU_CACHE_VIVT=y
|
||||||
CONFIG_CPU_TLB_V4WB=y
|
CONFIG_CPU_TLB_V4WB=y
|
||||||
CONFIG_CPU_MINICACHE=y
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Processor Features
|
# Processor Features
|
||||||
@ -119,6 +121,7 @@ CONFIG_CPU_MINICACHE=y
|
|||||||
# Bus support
|
# Bus support
|
||||||
#
|
#
|
||||||
CONFIG_ISA=y
|
CONFIG_ISA=y
|
||||||
|
CONFIG_ISA_DMA_API=y
|
||||||
|
|
||||||
#
|
#
|
||||||
# PCCARD (PCMCIA/CardBus) support
|
# PCCARD (PCMCIA/CardBus) support
|
||||||
@ -128,6 +131,7 @@ CONFIG_ISA=y
|
|||||||
#
|
#
|
||||||
# Kernel Features
|
# Kernel Features
|
||||||
#
|
#
|
||||||
|
# CONFIG_SMP is not set
|
||||||
# CONFIG_PREEMPT is not set
|
# CONFIG_PREEMPT is not set
|
||||||
CONFIG_DISCONTIGMEM=y
|
CONFIG_DISCONTIGMEM=y
|
||||||
CONFIG_LEDS=y
|
CONFIG_LEDS=y
|
||||||
@ -151,12 +155,14 @@ CONFIG_CPU_FREQ_TABLE=y
|
|||||||
# CONFIG_CPU_FREQ_DEBUG is not set
|
# CONFIG_CPU_FREQ_DEBUG is not set
|
||||||
CONFIG_CPU_FREQ_STAT=y
|
CONFIG_CPU_FREQ_STAT=y
|
||||||
# CONFIG_CPU_FREQ_STAT_DETAILS is not set
|
# CONFIG_CPU_FREQ_STAT_DETAILS is not set
|
||||||
CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
|
# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
|
||||||
# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
|
CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
|
||||||
CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
|
CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
|
||||||
# CONFIG_CPU_FREQ_GOV_POWERSAVE 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_GOV_ONDEMAND is not set
|
||||||
|
# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
|
||||||
|
CONFIG_CPU_FREQ_SA1100=y
|
||||||
|
|
||||||
#
|
#
|
||||||
# Floating point emulation
|
# Floating point emulation
|
||||||
@ -280,7 +286,6 @@ CONFIG_MTD_CFI_UTIL=y
|
|||||||
#
|
#
|
||||||
# Block devices
|
# Block devices
|
||||||
#
|
#
|
||||||
# CONFIG_BLK_DEV_FD is not set
|
|
||||||
# CONFIG_BLK_DEV_XD is not set
|
# CONFIG_BLK_DEV_XD is not set
|
||||||
# CONFIG_BLK_DEV_COW_COMMON is not set
|
# CONFIG_BLK_DEV_COW_COMMON is not set
|
||||||
# CONFIG_BLK_DEV_LOOP is not set
|
# CONFIG_BLK_DEV_LOOP is not set
|
||||||
@ -338,7 +343,6 @@ CONFIG_NET=y
|
|||||||
#
|
#
|
||||||
CONFIG_PACKET=y
|
CONFIG_PACKET=y
|
||||||
# CONFIG_PACKET_MMAP is not set
|
# CONFIG_PACKET_MMAP is not set
|
||||||
# CONFIG_NETLINK_DEV is not set
|
|
||||||
CONFIG_UNIX=y
|
CONFIG_UNIX=y
|
||||||
# CONFIG_NET_KEY is not set
|
# CONFIG_NET_KEY is not set
|
||||||
CONFIG_INET=y
|
CONFIG_INET=y
|
||||||
@ -484,7 +488,6 @@ CONFIG_SERIO=y
|
|||||||
CONFIG_SERIO_SERPORT=y
|
CONFIG_SERIO_SERPORT=y
|
||||||
# CONFIG_SERIO_RAW is not set
|
# CONFIG_SERIO_RAW is not set
|
||||||
# CONFIG_GAMEPORT is not set
|
# CONFIG_GAMEPORT is not set
|
||||||
CONFIG_SOUND_GAMEPORT=y
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Character devices
|
# Character devices
|
||||||
@ -533,7 +536,6 @@ CONFIG_LEGACY_PTY_COUNT=256
|
|||||||
#
|
#
|
||||||
# TPM devices
|
# TPM devices
|
||||||
#
|
#
|
||||||
# CONFIG_TCG_TPM is not set
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# I2C support
|
# I2C support
|
||||||
|
@ -50,7 +50,13 @@ CONFIG_BASE_SMALL=0
|
|||||||
#
|
#
|
||||||
# Loadable module support
|
# 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
|
# System Type
|
||||||
|
@ -50,7 +50,13 @@ CONFIG_BASE_SMALL=0
|
|||||||
#
|
#
|
||||||
# Loadable module support
|
# 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
|
# System Type
|
||||||
|
@ -50,7 +50,13 @@ CONFIG_BASE_SMALL=0
|
|||||||
#
|
#
|
||||||
# Loadable module support
|
# 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
|
# System Type
|
||||||
|
@ -50,7 +50,13 @@ CONFIG_BASE_SMALL=0
|
|||||||
#
|
#
|
||||||
# Loadable module support
|
# 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
|
# System Type
|
||||||
|
@ -6,7 +6,7 @@ AFLAGS_head.o := -DTEXTADDR=$(TEXTADDR) -DDATAADDR=$(DATAADDR)
|
|||||||
|
|
||||||
# Object file lists.
|
# 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 \
|
process.o ptrace.o semaphore.o setup.o signal.o sys_arm.o \
|
||||||
time.o traps.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;
|
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);
|
struct expansion_card *ec = ECARD_DEV(dev);
|
||||||
return sprintf(buf, "%u\n", ec->irq);
|
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);
|
struct expansion_card *ec = ECARD_DEV(dev);
|
||||||
return sprintf(buf, "%u\n", ec->dma);
|
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);
|
struct expansion_card *ec = ECARD_DEV(dev);
|
||||||
char *str = buf;
|
char *str = buf;
|
||||||
@ -893,19 +893,19 @@ static ssize_t ecard_show_resources(struct device *dev, char *buf)
|
|||||||
return str - 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);
|
struct expansion_card *ec = ECARD_DEV(dev);
|
||||||
return sprintf(buf, "%u\n", ec->cid.manufacturer);
|
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);
|
struct expansion_card *ec = ECARD_DEV(dev);
|
||||||
return sprintf(buf, "%u\n", ec->cid.product);
|
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);
|
struct expansion_card *ec = ECARD_DEV(dev);
|
||||||
return sprintf(buf, "%s\n", ec->type == ECARD_EASI ? "EASI" : "IOC");
|
return sprintf(buf, "%s\n", ec->type == ECARD_EASI ? "EASI" : "IOC");
|
||||||
|
@ -23,49 +23,92 @@
|
|||||||
|
|
||||||
#include "entry-header.S"
|
#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
|
* Invalid mode handlers
|
||||||
*/
|
*/
|
||||||
.macro inv_entry, sym, reason
|
.macro inv_entry, reason
|
||||||
sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go
|
sub sp, sp, #S_FRAME_SIZE
|
||||||
stmia sp, {r0 - lr} @ Save XXX r0 - lr
|
stmib sp, {r1 - lr}
|
||||||
ldr r4, .LC\sym
|
|
||||||
mov r1, #\reason
|
mov r1, #\reason
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
__pabt_invalid:
|
__pabt_invalid:
|
||||||
inv_entry abt, BAD_PREFETCH
|
inv_entry BAD_PREFETCH
|
||||||
b 1f
|
b common_invalid
|
||||||
|
|
||||||
__dabt_invalid:
|
__dabt_invalid:
|
||||||
inv_entry abt, BAD_DATA
|
inv_entry BAD_DATA
|
||||||
b 1f
|
b common_invalid
|
||||||
|
|
||||||
__irq_invalid:
|
__irq_invalid:
|
||||||
inv_entry irq, BAD_IRQ
|
inv_entry BAD_IRQ
|
||||||
b 1f
|
b common_invalid
|
||||||
|
|
||||||
__und_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
|
mov r0, sp
|
||||||
and r2, r6, #31 @ int mode
|
and r2, r6, #0x1f
|
||||||
b bad_mode
|
b bad_mode
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SVC mode handlers
|
* SVC mode handlers
|
||||||
*/
|
*/
|
||||||
.macro svc_entry, sym
|
.macro svc_entry
|
||||||
sub sp, sp, #S_FRAME_SIZE
|
sub sp, sp, #S_FRAME_SIZE
|
||||||
stmia sp, {r0 - r12} @ save r0 - r12
|
stmib sp, {r1 - r12}
|
||||||
ldr r2, .LC\sym
|
|
||||||
add r0, sp, #S_FRAME_SIZE
|
ldmia r0, {r1 - r3}
|
||||||
ldmia r2, {r2 - r4} @ get pc, cpsr
|
add r5, sp, #S_SP @ here for interlock avoidance
|
||||||
add r5, sp, #S_SP
|
mov r4, #-1 @ "" "" "" ""
|
||||||
|
add r0, sp, #S_FRAME_SIZE @ "" "" "" ""
|
||||||
|
str r1, [sp] @ save the "real" r0 copied
|
||||||
|
@ from the exception stack
|
||||||
|
|
||||||
mov r1, lr
|
mov r1, lr
|
||||||
|
|
||||||
@
|
@
|
||||||
@ -82,7 +125,7 @@ __und_invalid:
|
|||||||
|
|
||||||
.align 5
|
.align 5
|
||||||
__dabt_svc:
|
__dabt_svc:
|
||||||
svc_entry abt
|
svc_entry
|
||||||
|
|
||||||
@
|
@
|
||||||
@ get ready to re-enable interrupts if appropriate
|
@ get ready to re-enable interrupts if appropriate
|
||||||
@ -129,28 +172,24 @@ __dabt_svc:
|
|||||||
|
|
||||||
.align 5
|
.align 5
|
||||||
__irq_svc:
|
__irq_svc:
|
||||||
svc_entry irq
|
svc_entry
|
||||||
|
|
||||||
#ifdef CONFIG_PREEMPT
|
#ifdef CONFIG_PREEMPT
|
||||||
get_thread_info r8
|
get_thread_info tsk
|
||||||
ldr r9, [r8, #TI_PREEMPT] @ get preempt count
|
ldr r8, [tsk, #TI_PREEMPT] @ get preempt count
|
||||||
add r7, r9, #1 @ increment it
|
add r7, r8, #1 @ increment it
|
||||||
str r7, [r8, #TI_PREEMPT]
|
str r7, [tsk, #TI_PREEMPT]
|
||||||
#endif
|
#endif
|
||||||
1: get_irqnr_and_base r0, r6, r5, lr
|
|
||||||
movne r1, sp
|
irq_handler
|
||||||
@
|
|
||||||
@ routine called with r0 = irq number, r1 = struct pt_regs *
|
|
||||||
@
|
|
||||||
adrne lr, 1b
|
|
||||||
bne asm_do_IRQ
|
|
||||||
#ifdef CONFIG_PREEMPT
|
#ifdef CONFIG_PREEMPT
|
||||||
ldr r0, [r8, #TI_FLAGS] @ get flags
|
ldr r0, [tsk, #TI_FLAGS] @ get flags
|
||||||
tst r0, #_TIF_NEED_RESCHED
|
tst r0, #_TIF_NEED_RESCHED
|
||||||
blne svc_preempt
|
blne svc_preempt
|
||||||
preempt_return:
|
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
|
teq r0, r7
|
||||||
str r9, [r8, #TI_PREEMPT] @ restore preempt count
|
|
||||||
strne r0, [r0, -r0] @ bug()
|
strne r0, [r0, -r0] @ bug()
|
||||||
#endif
|
#endif
|
||||||
ldr r0, [sp, #S_PSR] @ irqs are already disabled
|
ldr r0, [sp, #S_PSR] @ irqs are already disabled
|
||||||
@ -161,7 +200,7 @@ preempt_return:
|
|||||||
|
|
||||||
#ifdef CONFIG_PREEMPT
|
#ifdef CONFIG_PREEMPT
|
||||||
svc_preempt:
|
svc_preempt:
|
||||||
teq r9, #0 @ was preempt count = 0
|
teq r8, #0 @ was preempt count = 0
|
||||||
ldreq r6, .LCirq_stat
|
ldreq r6, .LCirq_stat
|
||||||
movne pc, lr @ no
|
movne pc, lr @ no
|
||||||
ldr r0, [r6, #4] @ local_irq_count
|
ldr r0, [r6, #4] @ local_irq_count
|
||||||
@ -169,9 +208,9 @@ svc_preempt:
|
|||||||
adds r0, r0, r1
|
adds r0, r0, r1
|
||||||
movne pc, lr
|
movne pc, lr
|
||||||
mov r7, #0 @ preempt_schedule_irq
|
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
|
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
|
tst r0, #_TIF_NEED_RESCHED
|
||||||
beq preempt_return @ go again
|
beq preempt_return @ go again
|
||||||
b 1b
|
b 1b
|
||||||
@ -179,7 +218,7 @@ svc_preempt:
|
|||||||
|
|
||||||
.align 5
|
.align 5
|
||||||
__und_svc:
|
__und_svc:
|
||||||
svc_entry und
|
svc_entry
|
||||||
|
|
||||||
@
|
@
|
||||||
@ call emulation code, which returns using r9 if it has emulated
|
@ call emulation code, which returns using r9 if it has emulated
|
||||||
@ -209,7 +248,7 @@ __und_svc:
|
|||||||
|
|
||||||
.align 5
|
.align 5
|
||||||
__pabt_svc:
|
__pabt_svc:
|
||||||
svc_entry abt
|
svc_entry
|
||||||
|
|
||||||
@
|
@
|
||||||
@ re-enable interrupts if appropriate
|
@ re-enable interrupts if appropriate
|
||||||
@ -242,12 +281,8 @@ __pabt_svc:
|
|||||||
ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr
|
ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr
|
||||||
|
|
||||||
.align 5
|
.align 5
|
||||||
.LCirq:
|
.LCcralign:
|
||||||
.word __temp_irq
|
.word cr_alignment
|
||||||
.LCund:
|
|
||||||
.word __temp_und
|
|
||||||
.LCabt:
|
|
||||||
.word __temp_abt
|
|
||||||
#ifdef MULTI_ABORT
|
#ifdef MULTI_ABORT
|
||||||
.LCprocfns:
|
.LCprocfns:
|
||||||
.word processor
|
.word processor
|
||||||
@ -262,14 +297,18 @@ __pabt_svc:
|
|||||||
/*
|
/*
|
||||||
* User mode handlers
|
* User mode handlers
|
||||||
*/
|
*/
|
||||||
.macro usr_entry, sym
|
.macro usr_entry
|
||||||
sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go
|
sub sp, sp, #S_FRAME_SIZE
|
||||||
stmia sp, {r0 - r12} @ save r0 - r12
|
stmib sp, {r1 - r12}
|
||||||
ldr r7, .LC\sym
|
|
||||||
add r5, sp, #S_PC
|
|
||||||
ldmia r7, {r2 - r4} @ Get USR pc, cpsr
|
|
||||||
|
|
||||||
#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
|
@ make sure our user space atomic helper is aborted
|
||||||
cmp r2, #VIRT_OFFSET
|
cmp r2, #VIRT_OFFSET
|
||||||
bichs r3, r3, #PSR_Z_BIT
|
bichs r3, r3, #PSR_Z_BIT
|
||||||
@ -284,13 +323,13 @@ __pabt_svc:
|
|||||||
@
|
@
|
||||||
@ Also, separately save sp_usr and lr_usr
|
@ Also, separately save sp_usr and lr_usr
|
||||||
@
|
@
|
||||||
stmia r5, {r2 - r4}
|
stmia r0, {r2 - r4}
|
||||||
stmdb r5, {sp, lr}^
|
stmdb r0, {sp, lr}^
|
||||||
|
|
||||||
@
|
@
|
||||||
@ Enable the alignment trap while in kernel mode
|
@ 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
|
@ Clear FP to mark the first stack frame
|
||||||
@ -300,7 +339,7 @@ __pabt_svc:
|
|||||||
|
|
||||||
.align 5
|
.align 5
|
||||||
__dabt_usr:
|
__dabt_usr:
|
||||||
usr_entry abt
|
usr_entry
|
||||||
|
|
||||||
@
|
@
|
||||||
@ Call the processor-specific abort handler:
|
@ Call the processor-specific abort handler:
|
||||||
@ -329,30 +368,23 @@ __dabt_usr:
|
|||||||
|
|
||||||
.align 5
|
.align 5
|
||||||
__irq_usr:
|
__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
|
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
|
#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
|
mov why, #0
|
||||||
b ret_to_user
|
b ret_to_user
|
||||||
|
|
||||||
@ -360,7 +392,7 @@ __irq_usr:
|
|||||||
|
|
||||||
.align 5
|
.align 5
|
||||||
__und_usr:
|
__und_usr:
|
||||||
usr_entry und
|
usr_entry
|
||||||
|
|
||||||
tst r3, #PSR_T_BIT @ Thumb mode?
|
tst r3, #PSR_T_BIT @ Thumb mode?
|
||||||
bne fpundefinstr @ ignore FP
|
bne fpundefinstr @ ignore FP
|
||||||
@ -476,7 +508,7 @@ fpundefinstr:
|
|||||||
|
|
||||||
.align 5
|
.align 5
|
||||||
__pabt_usr:
|
__pabt_usr:
|
||||||
usr_entry abt
|
usr_entry
|
||||||
|
|
||||||
enable_irq @ Enable interrupts
|
enable_irq @ Enable interrupts
|
||||||
mov r0, r2 @ address (pc)
|
mov r0, r2 @ address (pc)
|
||||||
@ -616,11 +648,17 @@ __kuser_helper_start:
|
|||||||
|
|
||||||
__kuser_cmpxchg: @ 0xffff0fc0
|
__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?"
|
* Poor you. No fast solution possible...
|
||||||
#endif
|
* 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:
|
* Theory of operation:
|
||||||
@ -735,29 +773,41 @@ __kuser_helper_end:
|
|||||||
*
|
*
|
||||||
* Common stub entry macro:
|
* Common stub entry macro:
|
||||||
* Enter in IRQ mode, spsr = SVC/USR CPSR, lr = SVC/USR PC
|
* 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
|
.align 5
|
||||||
|
|
||||||
vector_\name:
|
vector_\name:
|
||||||
ldr r13, .LCs\sym
|
|
||||||
.if \correction
|
.if \correction
|
||||||
sub lr, lr, #\correction
|
sub lr, lr, #\correction
|
||||||
.endif
|
.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]
|
ldr lr, [pc, lr, lsl #2]
|
||||||
movs pc, lr @ Changes mode and branches
|
movs pc, lr @ branch to handler in SVC mode
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
.globl __stubs_start
|
.globl __stubs_start
|
||||||
@ -765,7 +815,7 @@ __stubs_start:
|
|||||||
/*
|
/*
|
||||||
* Interrupt dispatcher
|
* Interrupt dispatcher
|
||||||
*/
|
*/
|
||||||
vector_stub irq, irq, 4
|
vector_stub irq, 4
|
||||||
|
|
||||||
.long __irq_usr @ 0 (USR_26 / USR_32)
|
.long __irq_usr @ 0 (USR_26 / USR_32)
|
||||||
.long __irq_invalid @ 1 (FIQ_26 / FIQ_32)
|
.long __irq_invalid @ 1 (FIQ_26 / FIQ_32)
|
||||||
@ -788,7 +838,7 @@ __stubs_start:
|
|||||||
* Data abort dispatcher
|
* Data abort dispatcher
|
||||||
* Enter in ABT mode, spsr = USR CPSR, lr = USR PC
|
* 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_usr @ 0 (USR_26 / USR_32)
|
||||||
.long __dabt_invalid @ 1 (FIQ_26 / FIQ_32)
|
.long __dabt_invalid @ 1 (FIQ_26 / FIQ_32)
|
||||||
@ -811,7 +861,7 @@ __stubs_start:
|
|||||||
* Prefetch abort dispatcher
|
* Prefetch abort dispatcher
|
||||||
* Enter in ABT mode, spsr = USR CPSR, lr = USR PC
|
* 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_usr @ 0 (USR_26 / USR_32)
|
||||||
.long __pabt_invalid @ 1 (FIQ_26 / FIQ_32)
|
.long __pabt_invalid @ 1 (FIQ_26 / FIQ_32)
|
||||||
@ -834,7 +884,7 @@ __stubs_start:
|
|||||||
* Undef instr entry dispatcher
|
* Undef instr entry dispatcher
|
||||||
* Enter in UND mode, spsr = SVC/USR CPSR, lr = SVC/USR PC
|
* 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_usr @ 0 (USR_26 / USR_32)
|
||||||
.long __und_invalid @ 1 (FIQ_26 / FIQ_32)
|
.long __und_invalid @ 1 (FIQ_26 / FIQ_32)
|
||||||
@ -888,13 +938,6 @@ vector_addrexcptn:
|
|||||||
.LCvswi:
|
.LCvswi:
|
||||||
.word vector_swi
|
.word vector_swi
|
||||||
|
|
||||||
.LCsirq:
|
|
||||||
.word __temp_irq
|
|
||||||
.LCsund:
|
|
||||||
.word __temp_und
|
|
||||||
.LCsabt:
|
|
||||||
.word __temp_abt
|
|
||||||
|
|
||||||
.globl __stubs_end
|
.globl __stubs_end
|
||||||
__stubs_end:
|
__stubs_end:
|
||||||
|
|
||||||
@ -916,23 +959,6 @@ __vectors_end:
|
|||||||
|
|
||||||
.data
|
.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_alignment
|
||||||
.globl cr_no_alignment
|
.globl cr_no_alignment
|
||||||
cr_alignment:
|
cr_alignment:
|
||||||
|
@ -59,11 +59,10 @@
|
|||||||
mov \rd, \rd, lsl #13
|
mov \rd, \rd, lsl #13
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
.macro alignment_trap, rbase, rtemp, sym
|
.macro alignment_trap, rtemp
|
||||||
#ifdef CONFIG_ALIGNMENT_TRAP
|
#ifdef CONFIG_ALIGNMENT_TRAP
|
||||||
#define OFF_CR_ALIGNMENT(x) cr_alignment - x
|
ldr \rtemp, .LCcralign
|
||||||
|
ldr \rtemp, [\rtemp]
|
||||||
ldr \rtemp, [\rbase, #OFF_CR_ALIGNMENT(\sym)]
|
|
||||||
mcr p15, 0, \rtemp, c1, c0
|
mcr p15, 0, \rtemp, c1, c0
|
||||||
#endif
|
#endif
|
||||||
.endm
|
.endm
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
* linux/arch/arm/kernel/head.S
|
* linux/arch/arm/kernel/head.S
|
||||||
*
|
*
|
||||||
* Copyright (C) 1994-2002 Russell King
|
* 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
|
* 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
|
* 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
|
stmia r6, {r0, r4} @ Save control register values
|
||||||
b start_kernel
|
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;
|
struct cpu_cache_fns cpu_cache;
|
||||||
#endif
|
#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];
|
char elf_platform[ELF_PLATFORM_SIZE];
|
||||||
EXPORT_SYMBOL(elf_platform);
|
EXPORT_SYMBOL(elf_platform);
|
||||||
|
|
||||||
@ -307,8 +315,6 @@ static void __init setup_processor(void)
|
|||||||
cpu_name, processor_id, (int)processor_id & 15,
|
cpu_name, processor_id, (int)processor_id & 15,
|
||||||
proc_arch[cpu_architecture()]);
|
proc_arch[cpu_architecture()]);
|
||||||
|
|
||||||
dump_cpu_info(smp_processor_id());
|
|
||||||
|
|
||||||
sprintf(system_utsname.machine, "%s%c", list->arch_name, ENDIANNESS);
|
sprintf(system_utsname.machine, "%s%c", list->arch_name, ENDIANNESS);
|
||||||
sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS);
|
sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS);
|
||||||
elf_hwcap = list->elf_hwcap;
|
elf_hwcap = list->elf_hwcap;
|
||||||
@ -316,6 +322,46 @@ static void __init setup_processor(void)
|
|||||||
cpu_proc_init();
|
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)
|
static struct machine_desc * __init setup_machine(unsigned int nr)
|
||||||
{
|
{
|
||||||
struct machine_desc *list;
|
struct machine_desc *list;
|
||||||
@ -715,6 +761,8 @@ void __init setup_arch(char **cmdline_p)
|
|||||||
paging_init(&meminfo, mdesc);
|
paging_init(&meminfo, mdesc);
|
||||||
request_standard_resources(&meminfo, mdesc);
|
request_standard_resources(&meminfo, mdesc);
|
||||||
|
|
||||||
|
cpu_init();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set up various architecture-specific pointers
|
* Set up various architecture-specific pointers
|
||||||
*/
|
*/
|
||||||
|
@ -24,6 +24,9 @@
|
|||||||
#include <asm/atomic.h>
|
#include <asm/atomic.h>
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
#include <asm/cpu.h>
|
#include <asm/cpu.h>
|
||||||
|
#include <asm/mmu_context.h>
|
||||||
|
#include <asm/pgtable.h>
|
||||||
|
#include <asm/pgalloc.h>
|
||||||
#include <asm/processor.h>
|
#include <asm/processor.h>
|
||||||
#include <asm/tlbflush.h>
|
#include <asm/tlbflush.h>
|
||||||
#include <asm/ptrace.h>
|
#include <asm/ptrace.h>
|
||||||
@ -36,6 +39,13 @@
|
|||||||
cpumask_t cpu_present_mask;
|
cpumask_t cpu_present_mask;
|
||||||
cpumask_t cpu_online_map;
|
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
|
* structures for inter-processor calls
|
||||||
* - A collection of single bit ipi messages.
|
* - 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)
|
int __init __cpu_up(unsigned int cpu)
|
||||||
{
|
{
|
||||||
struct task_struct *idle;
|
struct task_struct *idle;
|
||||||
|
pgd_t *pgd;
|
||||||
|
pmd_t *pmd;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -83,12 +95,58 @@ int __init __cpu_up(unsigned int cpu)
|
|||||||
return PTR_ERR(idle);
|
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.
|
* Now bring the CPU into our world.
|
||||||
*/
|
*/
|
||||||
ret = boot_secondary(cpu, idle);
|
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) {
|
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
|
* FIXME: We need to clean up the new idle thread. --rmk
|
||||||
*/
|
*/
|
||||||
@ -97,6 +155,56 @@ int __init __cpu_up(unsigned int cpu)
|
|||||||
return ret;
|
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
|
* Called by both boot and secondaries to move global data into
|
||||||
* per-processor storage.
|
* per-processor storage.
|
||||||
|
@ -464,6 +464,55 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs)
|
|||||||
#endif
|
#endif
|
||||||
return 0;
|
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:
|
default:
|
||||||
/* Calls 9f00xx..9f07ff are defined to return -ENOSYS
|
/* Calls 9f00xx..9f07ff are defined to return -ENOSYS
|
||||||
if not implemented, rather than raising SIGILL. This
|
if not implemented, rather than raising SIGILL. This
|
||||||
|
@ -31,31 +31,26 @@ Boston, MA 02111-1307, USA. */
|
|||||||
|
|
||||||
#include "gcclib.h"
|
#include "gcclib.h"
|
||||||
|
|
||||||
DItype
|
s64 __ashldi3(s64 u, int b)
|
||||||
__ashldi3 (DItype u, word_type b)
|
|
||||||
{
|
{
|
||||||
DIunion w;
|
DIunion w;
|
||||||
word_type bm;
|
int bm;
|
||||||
DIunion uu;
|
DIunion uu;
|
||||||
|
|
||||||
if (b == 0)
|
if (b == 0)
|
||||||
return u;
|
return u;
|
||||||
|
|
||||||
uu.ll = u;
|
uu.ll = u;
|
||||||
|
|
||||||
bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
|
bm = (sizeof(s32) * BITS_PER_UNIT) - b;
|
||||||
if (bm <= 0)
|
if (bm <= 0) {
|
||||||
{
|
w.s.low = 0;
|
||||||
w.s.low = 0;
|
w.s.high = (u32) uu.s.low << -bm;
|
||||||
w.s.high = (USItype)uu.s.low << -bm;
|
} else {
|
||||||
}
|
u32 carries = (u32) uu.s.low >> bm;
|
||||||
else
|
w.s.low = (u32) uu.s.low << b;
|
||||||
{
|
w.s.high = ((u32) uu.s.high << b) | carries;
|
||||||
USItype carries = (USItype)uu.s.low >> bm;
|
}
|
||||||
w.s.low = (USItype)uu.s.low << b;
|
|
||||||
w.s.high = ((USItype)uu.s.high << b) | carries;
|
|
||||||
}
|
|
||||||
|
|
||||||
return w.ll;
|
return w.ll;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,31 +31,27 @@ Boston, MA 02111-1307, USA. */
|
|||||||
|
|
||||||
#include "gcclib.h"
|
#include "gcclib.h"
|
||||||
|
|
||||||
DItype
|
s64 __ashrdi3(s64 u, int b)
|
||||||
__ashrdi3 (DItype u, word_type b)
|
|
||||||
{
|
{
|
||||||
DIunion w;
|
DIunion w;
|
||||||
word_type bm;
|
int bm;
|
||||||
DIunion uu;
|
DIunion uu;
|
||||||
|
|
||||||
if (b == 0)
|
if (b == 0)
|
||||||
return u;
|
return u;
|
||||||
|
|
||||||
uu.ll = u;
|
uu.ll = u;
|
||||||
|
|
||||||
bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
|
bm = (sizeof(s32) * BITS_PER_UNIT) - b;
|
||||||
if (bm <= 0)
|
if (bm <= 0) {
|
||||||
{
|
/* w.s.high = 1..1 or 0..0 */
|
||||||
/* w.s.high = 1..1 or 0..0 */
|
w.s.high = uu.s.high >> (sizeof(s32) * BITS_PER_UNIT - 1);
|
||||||
w.s.high = uu.s.high >> (sizeof (SItype) * BITS_PER_UNIT - 1);
|
w.s.low = uu.s.high >> -bm;
|
||||||
w.s.low = uu.s.high >> -bm;
|
} else {
|
||||||
}
|
u32 carries = (u32) uu.s.high << bm;
|
||||||
else
|
w.s.high = uu.s.high >> b;
|
||||||
{
|
w.s.low = ((u32) uu.s.low >> b) | carries;
|
||||||
USItype carries = (USItype)uu.s.high << bm;
|
}
|
||||||
w.s.high = uu.s.high >> b;
|
|
||||||
w.s.low = ((USItype)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 */
|
/* gcclib.h -- definitions for various functions 'borrowed' from gcc-2.95.3 */
|
||||||
/* I Molton 29/07/01 */
|
/* I Molton 29/07/01 */
|
||||||
|
|
||||||
#define BITS_PER_UNIT 8
|
#include <linux/types.h>
|
||||||
#define SI_TYPE_SIZE (sizeof (SItype) * BITS_PER_UNIT)
|
|
||||||
|
|
||||||
typedef unsigned int UQItype __attribute__ ((mode (QI)));
|
#define BITS_PER_UNIT 8
|
||||||
typedef int SItype __attribute__ ((mode (SI)));
|
#define SI_TYPE_SIZE (sizeof(s32) * BITS_PER_UNIT)
|
||||||
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)));
|
|
||||||
|
|
||||||
#ifdef __ARMEB__
|
#ifdef __ARMEB__
|
||||||
struct DIstruct {SItype high, low;};
|
struct DIstruct {
|
||||||
|
s32 high, low;
|
||||||
|
};
|
||||||
#else
|
#else
|
||||||
struct DIstruct {SItype low, high;};
|
struct DIstruct {
|
||||||
|
s32 low, high;
|
||||||
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef union
|
typedef union {
|
||||||
{
|
struct DIstruct s;
|
||||||
struct DIstruct s;
|
s64 ll;
|
||||||
DItype ll;
|
|
||||||
} DIunion;
|
} DIunion;
|
||||||
|
|
||||||
|
@ -87,9 +87,9 @@ ENTRY(__raw_writesw)
|
|||||||
subs r2, r2, #2
|
subs r2, r2, #2
|
||||||
orr ip, ip, r3, push_hbyte1
|
orr ip, ip, r3, push_hbyte1
|
||||||
strh ip, [r0]
|
strh ip, [r0]
|
||||||
bpl 2b
|
bpl 1b
|
||||||
|
|
||||||
3: tst r2, #1
|
tst r2, #1
|
||||||
2: movne ip, r3, lsr #8
|
3: movne ip, r3, lsr #8
|
||||||
strneh ip, [r0]
|
strneh ip, [r0]
|
||||||
mov pc, lr
|
mov pc, lr
|
||||||
|
@ -26,18 +26,18 @@
|
|||||||
|
|
||||||
#define __BITS4 (SI_TYPE_SIZE / 4)
|
#define __BITS4 (SI_TYPE_SIZE / 4)
|
||||||
#define __ll_B (1L << (SI_TYPE_SIZE / 2))
|
#define __ll_B (1L << (SI_TYPE_SIZE / 2))
|
||||||
#define __ll_lowpart(t) ((USItype) (t) % __ll_B)
|
#define __ll_lowpart(t) ((u32) (t) % __ll_B)
|
||||||
#define __ll_highpart(t) ((USItype) (t) / __ll_B)
|
#define __ll_highpart(t) ((u32) (t) / __ll_B)
|
||||||
|
|
||||||
/* Define auxiliary asm macros.
|
/* Define auxiliary asm macros.
|
||||||
|
|
||||||
1) umul_ppmm(high_prod, low_prod, multipler, multiplicand)
|
1) umul_ppmm(high_prod, low_prod, multipler, multiplicand)
|
||||||
multiplies two USItype integers MULTIPLER and MULTIPLICAND,
|
multiplies two u32 integers MULTIPLER and MULTIPLICAND,
|
||||||
and generates a two-part USItype product in HIGH_PROD and
|
and generates a two-part u32 product in HIGH_PROD and
|
||||||
LOW_PROD.
|
LOW_PROD.
|
||||||
|
|
||||||
2) __umulsidi3(a,b) multiplies two USItype integers A and B,
|
2) __umulsidi3(a,b) multiplies two u32 integers A and B,
|
||||||
and returns a UDItype product. This is just a variant of umul_ppmm.
|
and returns a u64 product. This is just a variant of umul_ppmm.
|
||||||
|
|
||||||
3) udiv_qrnnd(quotient, remainder, high_numerator, low_numerator,
|
3) udiv_qrnnd(quotient, remainder, high_numerator, low_numerator,
|
||||||
denominator) divides a two-word unsigned integer, composed by the
|
denominator) divides a two-word unsigned integer, composed by the
|
||||||
@ -77,23 +77,23 @@
|
|||||||
#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
|
#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
|
||||||
__asm__ ("adds %1, %4, %5 \n\
|
__asm__ ("adds %1, %4, %5 \n\
|
||||||
adc %0, %2, %3" \
|
adc %0, %2, %3" \
|
||||||
: "=r" ((USItype) (sh)), \
|
: "=r" ((u32) (sh)), \
|
||||||
"=&r" ((USItype) (sl)) \
|
"=&r" ((u32) (sl)) \
|
||||||
: "%r" ((USItype) (ah)), \
|
: "%r" ((u32) (ah)), \
|
||||||
"rI" ((USItype) (bh)), \
|
"rI" ((u32) (bh)), \
|
||||||
"%r" ((USItype) (al)), \
|
"%r" ((u32) (al)), \
|
||||||
"rI" ((USItype) (bl)))
|
"rI" ((u32) (bl)))
|
||||||
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
|
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
|
||||||
__asm__ ("subs %1, %4, %5 \n\
|
__asm__ ("subs %1, %4, %5 \n\
|
||||||
sbc %0, %2, %3" \
|
sbc %0, %2, %3" \
|
||||||
: "=r" ((USItype) (sh)), \
|
: "=r" ((u32) (sh)), \
|
||||||
"=&r" ((USItype) (sl)) \
|
"=&r" ((u32) (sl)) \
|
||||||
: "r" ((USItype) (ah)), \
|
: "r" ((u32) (ah)), \
|
||||||
"rI" ((USItype) (bh)), \
|
"rI" ((u32) (bh)), \
|
||||||
"r" ((USItype) (al)), \
|
"r" ((u32) (al)), \
|
||||||
"rI" ((USItype) (bl)))
|
"rI" ((u32) (bl)))
|
||||||
#define umul_ppmm(xh, xl, a, b) \
|
#define umul_ppmm(xh, xl, a, b) \
|
||||||
{register USItype __t0, __t1, __t2; \
|
{register u32 __t0, __t1, __t2; \
|
||||||
__asm__ ("%@ Inlined umul_ppmm \n\
|
__asm__ ("%@ Inlined umul_ppmm \n\
|
||||||
mov %2, %5, lsr #16 \n\
|
mov %2, %5, lsr #16 \n\
|
||||||
mov %0, %6, lsr #16 \n\
|
mov %0, %6, lsr #16 \n\
|
||||||
@ -107,14 +107,14 @@
|
|||||||
addcs %0, %0, #65536 \n\
|
addcs %0, %0, #65536 \n\
|
||||||
adds %1, %1, %3, lsl #16 \n\
|
adds %1, %1, %3, lsl #16 \n\
|
||||||
adc %0, %0, %3, lsr #16" \
|
adc %0, %0, %3, lsr #16" \
|
||||||
: "=&r" ((USItype) (xh)), \
|
: "=&r" ((u32) (xh)), \
|
||||||
"=r" ((USItype) (xl)), \
|
"=r" ((u32) (xl)), \
|
||||||
"=&r" (__t0), "=&r" (__t1), "=r" (__t2) \
|
"=&r" (__t0), "=&r" (__t1), "=r" (__t2) \
|
||||||
: "r" ((USItype) (a)), \
|
: "r" ((u32) (a)), \
|
||||||
"r" ((USItype) (b)));}
|
"r" ((u32) (b)));}
|
||||||
#define UMUL_TIME 20
|
#define UMUL_TIME 20
|
||||||
#define UDIV_TIME 100
|
#define UDIV_TIME 100
|
||||||
#endif /* __arm__ */
|
#endif /* __arm__ */
|
||||||
|
|
||||||
#define __umulsidi3(u, v) \
|
#define __umulsidi3(u, v) \
|
||||||
({DIunion __w; \
|
({DIunion __w; \
|
||||||
@ -123,14 +123,14 @@
|
|||||||
|
|
||||||
#define __udiv_qrnnd_c(q, r, n1, n0, d) \
|
#define __udiv_qrnnd_c(q, r, n1, n0, d) \
|
||||||
do { \
|
do { \
|
||||||
USItype __d1, __d0, __q1, __q0; \
|
u32 __d1, __d0, __q1, __q0; \
|
||||||
USItype __r1, __r0, __m; \
|
u32 __r1, __r0, __m; \
|
||||||
__d1 = __ll_highpart (d); \
|
__d1 = __ll_highpart (d); \
|
||||||
__d0 = __ll_lowpart (d); \
|
__d0 = __ll_lowpart (d); \
|
||||||
\
|
\
|
||||||
__r1 = (n1) % __d1; \
|
__r1 = (n1) % __d1; \
|
||||||
__q1 = (n1) / __d1; \
|
__q1 = (n1) / __d1; \
|
||||||
__m = (USItype) __q1 * __d0; \
|
__m = (u32) __q1 * __d0; \
|
||||||
__r1 = __r1 * __ll_B | __ll_highpart (n0); \
|
__r1 = __r1 * __ll_B | __ll_highpart (n0); \
|
||||||
if (__r1 < __m) \
|
if (__r1 < __m) \
|
||||||
{ \
|
{ \
|
||||||
@ -143,7 +143,7 @@
|
|||||||
\
|
\
|
||||||
__r0 = __r1 % __d1; \
|
__r0 = __r1 % __d1; \
|
||||||
__q0 = __r1 / __d1; \
|
__q0 = __r1 / __d1; \
|
||||||
__m = (USItype) __q0 * __d0; \
|
__m = (u32) __q0 * __d0; \
|
||||||
__r0 = __r0 * __ll_B | __ll_lowpart (n0); \
|
__r0 = __r0 * __ll_B | __ll_lowpart (n0); \
|
||||||
if (__r0 < __m) \
|
if (__r0 < __m) \
|
||||||
{ \
|
{ \
|
||||||
@ -154,7 +154,7 @@
|
|||||||
} \
|
} \
|
||||||
__r0 -= __m; \
|
__r0 -= __m; \
|
||||||
\
|
\
|
||||||
(q) = (USItype) __q1 * __ll_B | __q0; \
|
(q) = (u32) __q1 * __ll_B | __q0; \
|
||||||
(r) = __r0; \
|
(r) = __r0; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
@ -163,14 +163,14 @@
|
|||||||
|
|
||||||
#define count_leading_zeros(count, x) \
|
#define count_leading_zeros(count, x) \
|
||||||
do { \
|
do { \
|
||||||
USItype __xr = (x); \
|
u32 __xr = (x); \
|
||||||
USItype __a; \
|
u32 __a; \
|
||||||
\
|
\
|
||||||
if (SI_TYPE_SIZE <= 32) \
|
if (SI_TYPE_SIZE <= 32) \
|
||||||
{ \
|
{ \
|
||||||
__a = __xr < ((USItype)1<<2*__BITS4) \
|
__a = __xr < ((u32)1<<2*__BITS4) \
|
||||||
? (__xr < ((USItype)1<<__BITS4) ? 0 : __BITS4) \
|
? (__xr < ((u32)1<<__BITS4) ? 0 : __BITS4) \
|
||||||
: (__xr < ((USItype)1<<3*__BITS4) ? 2*__BITS4 : 3*__BITS4); \
|
: (__xr < ((u32)1<<3*__BITS4) ? 2*__BITS4 : 3*__BITS4); \
|
||||||
} \
|
} \
|
||||||
else \
|
else \
|
||||||
{ \
|
{ \
|
||||||
|
@ -31,31 +31,26 @@ Boston, MA 02111-1307, USA. */
|
|||||||
|
|
||||||
#include "gcclib.h"
|
#include "gcclib.h"
|
||||||
|
|
||||||
DItype
|
s64 __lshrdi3(s64 u, int b)
|
||||||
__lshrdi3 (DItype u, word_type b)
|
|
||||||
{
|
{
|
||||||
DIunion w;
|
DIunion w;
|
||||||
word_type bm;
|
int bm;
|
||||||
DIunion uu;
|
DIunion uu;
|
||||||
|
|
||||||
if (b == 0)
|
if (b == 0)
|
||||||
return u;
|
return u;
|
||||||
|
|
||||||
uu.ll = u;
|
uu.ll = u;
|
||||||
|
|
||||||
bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
|
bm = (sizeof(s32) * BITS_PER_UNIT) - b;
|
||||||
if (bm <= 0)
|
if (bm <= 0) {
|
||||||
{
|
w.s.high = 0;
|
||||||
w.s.high = 0;
|
w.s.low = (u32) uu.s.high >> -bm;
|
||||||
w.s.low = (USItype)uu.s.high >> -bm;
|
} else {
|
||||||
}
|
u32 carries = (u32) uu.s.high << bm;
|
||||||
else
|
w.s.high = (u32) uu.s.high >> b;
|
||||||
{
|
w.s.low = ((u32) uu.s.low >> b) | carries;
|
||||||
USItype carries = (USItype)uu.s.high << bm;
|
}
|
||||||
w.s.high = (USItype)uu.s.high >> b;
|
|
||||||
w.s.low = ((USItype)uu.s.low >> b) | carries;
|
|
||||||
}
|
|
||||||
|
|
||||||
return w.ll;
|
return w.ll;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ Boston, MA 02111-1307, USA. */
|
|||||||
#include "gcclib.h"
|
#include "gcclib.h"
|
||||||
|
|
||||||
#define umul_ppmm(xh, xl, a, b) \
|
#define umul_ppmm(xh, xl, a, b) \
|
||||||
{register USItype __t0, __t1, __t2; \
|
{register u32 __t0, __t1, __t2; \
|
||||||
__asm__ ("%@ Inlined umul_ppmm \n\
|
__asm__ ("%@ Inlined umul_ppmm \n\
|
||||||
mov %2, %5, lsr #16 \n\
|
mov %2, %5, lsr #16 \n\
|
||||||
mov %0, %6, lsr #16 \n\
|
mov %0, %6, lsr #16 \n\
|
||||||
@ -46,32 +46,27 @@ Boston, MA 02111-1307, USA. */
|
|||||||
addcs %0, %0, #65536 \n\
|
addcs %0, %0, #65536 \n\
|
||||||
adds %1, %1, %3, lsl #16 \n\
|
adds %1, %1, %3, lsl #16 \n\
|
||||||
adc %0, %0, %3, lsr #16" \
|
adc %0, %0, %3, lsr #16" \
|
||||||
: "=&r" ((USItype) (xh)), \
|
: "=&r" ((u32) (xh)), \
|
||||||
"=r" ((USItype) (xl)), \
|
"=r" ((u32) (xl)), \
|
||||||
"=&r" (__t0), "=&r" (__t1), "=r" (__t2) \
|
"=&r" (__t0), "=&r" (__t1), "=r" (__t2) \
|
||||||
: "r" ((USItype) (a)), \
|
: "r" ((u32) (a)), \
|
||||||
"r" ((USItype) (b)));}
|
"r" ((u32) (b)));}
|
||||||
|
|
||||||
|
|
||||||
#define __umulsidi3(u, v) \
|
#define __umulsidi3(u, v) \
|
||||||
({DIunion __w; \
|
({DIunion __w; \
|
||||||
umul_ppmm (__w.s.high, __w.s.low, u, v); \
|
umul_ppmm (__w.s.high, __w.s.low, u, v); \
|
||||||
__w.ll; })
|
__w.ll; })
|
||||||
|
|
||||||
|
s64 __muldi3(s64 u, s64 v)
|
||||||
DItype
|
|
||||||
__muldi3 (DItype u, DItype v)
|
|
||||||
{
|
{
|
||||||
DIunion w;
|
DIunion w;
|
||||||
DIunion uu, vv;
|
DIunion uu, vv;
|
||||||
|
|
||||||
uu.ll = u,
|
uu.ll = u, vv.ll = v;
|
||||||
vv.ll = v;
|
|
||||||
|
|
||||||
w.ll = __umulsidi3 (uu.s.low, vv.s.low);
|
w.ll = __umulsidi3(uu.s.low, vv.s.low);
|
||||||
w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high
|
w.s.high += ((u32) uu.s.low * (u32) vv.s.high
|
||||||
+ (USItype) uu.s.high * (USItype) vv.s.low);
|
+ (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"
|
#include "gcclib.h"
|
||||||
|
|
||||||
word_type
|
int __ucmpdi2(s64 a, s64 b)
|
||||||
__ucmpdi2 (DItype a, DItype 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)
|
if ((u32) au.s.high < (u32) bu.s.high)
|
||||||
return 0;
|
return 0;
|
||||||
else if ((USItype) au.s.high > (USItype) bu.s.high)
|
else if ((u32) au.s.high > (u32) bu.s.high)
|
||||||
return 2;
|
return 2;
|
||||||
if ((USItype) au.s.low < (USItype) bu.s.low)
|
if ((u32) au.s.low < (u32) bu.s.low)
|
||||||
return 0;
|
return 0;
|
||||||
else if ((USItype) au.s.low > (USItype) bu.s.low)
|
else if ((u32) au.s.low > (u32) bu.s.low)
|
||||||
return 2;
|
return 2;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,211 +32,191 @@ Boston, MA 02111-1307, USA. */
|
|||||||
#include "gcclib.h"
|
#include "gcclib.h"
|
||||||
#include "longlong.h"
|
#include "longlong.h"
|
||||||
|
|
||||||
static const UQItype __clz_tab[] =
|
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,
|
||||||
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,
|
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,
|
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,
|
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,
|
||||||
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,
|
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,
|
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,
|
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,
|
||||||
|
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
|
u64 __udivmoddi4(u64 n, u64 d, u64 * rp)
|
||||||
__udivmoddi4 (UDItype n, UDItype d, UDItype *rp)
|
|
||||||
{
|
{
|
||||||
DIunion ww;
|
DIunion ww;
|
||||||
DIunion nn, dd;
|
DIunion nn, dd;
|
||||||
DIunion rr;
|
DIunion rr;
|
||||||
USItype d0, d1, n0, n1, n2;
|
u32 d0, d1, n0, n1, n2;
|
||||||
USItype q0, q1;
|
u32 q0, q1;
|
||||||
USItype b, bm;
|
u32 b, bm;
|
||||||
|
|
||||||
nn.ll = n;
|
nn.ll = n;
|
||||||
dd.ll = d;
|
dd.ll = d;
|
||||||
|
|
||||||
d0 = dd.s.low;
|
d0 = dd.s.low;
|
||||||
d1 = dd.s.high;
|
d1 = dd.s.high;
|
||||||
n0 = nn.s.low;
|
n0 = nn.s.low;
|
||||||
n1 = nn.s.high;
|
n1 = nn.s.high;
|
||||||
|
|
||||||
if (d1 == 0)
|
if (d1 == 0) {
|
||||||
{
|
if (d0 > n1) {
|
||||||
if (d0 > n1)
|
/* 0q = nn / 0D */
|
||||||
{
|
|
||||||
/* 0q = nn / 0D */
|
|
||||||
|
|
||||||
count_leading_zeros (bm, d0);
|
count_leading_zeros(bm, d0);
|
||||||
|
|
||||||
if (bm != 0)
|
if (bm != 0) {
|
||||||
{
|
/* Normalize, i.e. make the most significant bit of the
|
||||||
/* Normalize, i.e. make the most significant bit of the
|
denominator set. */
|
||||||
denominator set. */
|
|
||||||
|
|
||||||
d0 = d0 << bm;
|
d0 = d0 << bm;
|
||||||
n1 = (n1 << bm) | (n0 >> (SI_TYPE_SIZE - bm));
|
n1 = (n1 << bm) | (n0 >> (SI_TYPE_SIZE - bm));
|
||||||
n0 = n0 << bm;
|
n0 = n0 << bm;
|
||||||
}
|
}
|
||||||
|
|
||||||
udiv_qrnnd (q0, n0, n1, n0, d0);
|
udiv_qrnnd(q0, n0, n1, n0, d0);
|
||||||
q1 = 0;
|
q1 = 0;
|
||||||
|
|
||||||
/* Remainder in n0 >> bm. */
|
/* Remainder in n0 >> bm. */
|
||||||
}
|
} else {
|
||||||
else
|
/* qq = NN / 0d */
|
||||||
{
|
|
||||||
/* qq = NN / 0d */
|
|
||||||
|
|
||||||
if (d0 == 0)
|
if (d0 == 0)
|
||||||
d0 = 1 / d0; /* Divide intentionally by zero. */
|
d0 = 1 / d0; /* Divide intentionally by zero. */
|
||||||
|
|
||||||
count_leading_zeros (bm, d0);
|
count_leading_zeros(bm, d0);
|
||||||
|
|
||||||
if (bm == 0)
|
if (bm == 0) {
|
||||||
{
|
/* From (n1 >= d0) /\ (the most significant bit of d0 is set),
|
||||||
/* From (n1 >= d0) /\ (the most significant bit of d0 is set),
|
conclude (the most significant bit of n1 is set) /\ (the
|
||||||
conclude (the most significant bit of n1 is set) /\ (the
|
leading quotient digit q1 = 1).
|
||||||
leading quotient digit q1 = 1).
|
|
||||||
|
|
||||||
This special case is necessary, not an optimization.
|
This special case is necessary, not an optimization.
|
||||||
(Shifts counts of SI_TYPE_SIZE are undefined.) */
|
(Shifts counts of SI_TYPE_SIZE are undefined.) */
|
||||||
|
|
||||||
n1 -= d0;
|
n1 -= d0;
|
||||||
q1 = 1;
|
q1 = 1;
|
||||||
}
|
} else {
|
||||||
else
|
/* Normalize. */
|
||||||
{
|
|
||||||
/* Normalize. */
|
|
||||||
|
|
||||||
b = SI_TYPE_SIZE - bm;
|
b = SI_TYPE_SIZE - bm;
|
||||||
|
|
||||||
d0 = d0 << bm;
|
d0 = d0 << bm;
|
||||||
n2 = n1 >> b;
|
n2 = n1 >> b;
|
||||||
n1 = (n1 << bm) | (n0 >> b);
|
n1 = (n1 << bm) | (n0 >> b);
|
||||||
n0 = n0 << bm;
|
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)
|
if (rp != 0) {
|
||||||
{
|
rr.s.low = n0 >> bm;
|
||||||
rr.s.low = n0 >> bm;
|
rr.s.high = 0;
|
||||||
rr.s.high = 0;
|
*rp = rr.ll;
|
||||||
*rp = rr.ll;
|
}
|
||||||
}
|
} else {
|
||||||
}
|
if (d1 > n1) {
|
||||||
else
|
/* 00 = nn / DD */
|
||||||
{
|
|
||||||
if (d1 > n1)
|
|
||||||
{
|
|
||||||
/* 00 = nn / DD */
|
|
||||||
|
|
||||||
q0 = 0;
|
q0 = 0;
|
||||||
q1 = 0;
|
q1 = 0;
|
||||||
|
|
||||||
/* Remainder in n1n0. */
|
/* Remainder in n1n0. */
|
||||||
if (rp != 0)
|
if (rp != 0) {
|
||||||
{
|
rr.s.low = n0;
|
||||||
rr.s.low = n0;
|
rr.s.high = n1;
|
||||||
rr.s.high = n1;
|
*rp = rr.ll;
|
||||||
*rp = rr.ll;
|
}
|
||||||
}
|
} else {
|
||||||
}
|
/* 0q = NN / dd */
|
||||||
else
|
|
||||||
{
|
|
||||||
/* 0q = NN / dd */
|
|
||||||
|
|
||||||
count_leading_zeros (bm, d1);
|
count_leading_zeros(bm, d1);
|
||||||
if (bm == 0)
|
if (bm == 0) {
|
||||||
{
|
/* From (n1 >= d1) /\ (the most significant bit of d1 is set),
|
||||||
/* From (n1 >= d1) /\ (the most significant bit of d1 is set),
|
conclude (the most significant bit of n1 is set) /\ (the
|
||||||
conclude (the most significant bit of n1 is set) /\ (the
|
quotient digit q0 = 0 or 1).
|
||||||
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
|
/* The condition on the next line takes advantage of that
|
||||||
n1 >= d1 (true due to program flow). */
|
n1 >= d1 (true due to program flow). */
|
||||||
if (n1 > d1 || n0 >= d0)
|
if (n1 > d1 || n0 >= d0) {
|
||||||
{
|
q0 = 1;
|
||||||
q0 = 1;
|
sub_ddmmss(n1, n0, n1, n0, d1, d0);
|
||||||
sub_ddmmss (n1, n0, n1, n0, d1, d0);
|
} else
|
||||||
}
|
q0 = 0;
|
||||||
else
|
|
||||||
q0 = 0;
|
|
||||||
|
|
||||||
q1 = 0;
|
q1 = 0;
|
||||||
|
|
||||||
if (rp != 0)
|
if (rp != 0) {
|
||||||
{
|
rr.s.low = n0;
|
||||||
rr.s.low = n0;
|
rr.s.high = n1;
|
||||||
rr.s.high = n1;
|
*rp = rr.ll;
|
||||||
*rp = rr.ll;
|
}
|
||||||
}
|
} else {
|
||||||
}
|
u32 m1, m0;
|
||||||
else
|
/* Normalize. */
|
||||||
{
|
|
||||||
USItype m1, m0;
|
|
||||||
/* Normalize. */
|
|
||||||
|
|
||||||
b = SI_TYPE_SIZE - bm;
|
b = SI_TYPE_SIZE - bm;
|
||||||
|
|
||||||
d1 = (d1 << bm) | (d0 >> b);
|
d1 = (d1 << bm) | (d0 >> b);
|
||||||
d0 = d0 << bm;
|
d0 = d0 << bm;
|
||||||
n2 = n1 >> b;
|
n2 = n1 >> b;
|
||||||
n1 = (n1 << bm) | (n0 >> b);
|
n1 = (n1 << bm) | (n0 >> b);
|
||||||
n0 = n0 << bm;
|
n0 = n0 << bm;
|
||||||
|
|
||||||
udiv_qrnnd (q0, n1, n2, n1, d1);
|
udiv_qrnnd(q0, n1, n2, n1, d1);
|
||||||
umul_ppmm (m1, m0, q0, d0);
|
umul_ppmm(m1, m0, q0, d0);
|
||||||
|
|
||||||
if (m1 > n1 || (m1 == n1 && m0 > n0))
|
if (m1 > n1 || (m1 == n1 && m0 > n0)) {
|
||||||
{
|
q0--;
|
||||||
q0--;
|
sub_ddmmss(m1, m0, m1, m0, d1, d0);
|
||||||
sub_ddmmss (m1, m0, m1, m0, d1, d0);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
q1 = 0;
|
q1 = 0;
|
||||||
|
|
||||||
/* Remainder in (n1n0 - m1m0) >> bm. */
|
/* Remainder in (n1n0 - m1m0) >> bm. */
|
||||||
if (rp != 0)
|
if (rp != 0) {
|
||||||
{
|
sub_ddmmss(n1, n0, n1, n0, m1, m0);
|
||||||
sub_ddmmss (n1, n0, n1, n0, m1, m0);
|
rr.s.low = (n1 << b) | (n0 >> bm);
|
||||||
rr.s.low = (n1 << b) | (n0 >> bm);
|
rr.s.high = n1 >> bm;
|
||||||
rr.s.high = n1 >> bm;
|
*rp = rr.ll;
|
||||||
*rp = rr.ll;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
ww.s.low = q0;
|
ww.s.low = q0;
|
||||||
ww.s.high = q1;
|
ww.s.high = q1;
|
||||||
return ww.ll;
|
return ww.ll;
|
||||||
}
|
}
|
||||||
|
|
||||||
UDItype
|
u64 __udivdi3(u64 n, u64 d)
|
||||||
__udivdi3 (UDItype n, UDItype d)
|
|
||||||
{
|
{
|
||||||
return __udivmoddi4 (n, d, (UDItype *) 0);
|
return __udivmoddi4(n, d, (u64 *) 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
UDItype
|
u64 __umoddi3(u64 u, u64 v)
|
||||||
__umoddi3 (UDItype u, UDItype 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_PCI) += pci_v3.o pci.o
|
||||||
obj-$(CONFIG_CPU_FREQ_INTEGRATOR) += cpu.o
|
obj-$(CONFIG_CPU_FREQ_INTEGRATOR) += cpu.o
|
||||||
obj-$(CONFIG_INTEGRATOR_IMPD1) += impd1.o
|
obj-$(CONFIG_INTEGRATOR_IMPD1) += impd1.o
|
||||||
|
obj-$(CONFIG_SMP) += platsmp.o headsmp.o
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
|
#include <linux/smp.h>
|
||||||
|
|
||||||
#include <asm/hardware.h>
|
#include <asm/hardware.h>
|
||||||
#include <asm/irq.h>
|
#include <asm/irq.h>
|
||||||
@ -221,7 +222,23 @@ integrator_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
|||||||
*/
|
*/
|
||||||
timer1->TimerClear = 1;
|
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);
|
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_UART1_BASE), INTEGRATOR_UART1_BASE, SZ_4K, MT_DEVICE },
|
||||||
{ IO_ADDRESS(INTEGRATOR_DBG_BASE), INTEGRATOR_DBG_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 },
|
{ IO_ADDRESS(INTEGRATOR_GPIO_BASE), INTEGRATOR_GPIO_BASE, SZ_4K, MT_DEVICE },
|
||||||
{ 0xfc900000, 0xc9000000, SZ_4K, MT_DEVICE },
|
|
||||||
{ 0xfca00000, 0xca000000, SZ_4K, MT_DEVICE },
|
{ 0xfca00000, 0xca000000, SZ_4K, MT_DEVICE },
|
||||||
{ 0xfcb00000, 0xcb000000, SZ_4K, MT_DEVICE },
|
{ 0xfcb00000, 0xcb000000, SZ_4K, MT_DEVICE },
|
||||||
};
|
};
|
||||||
|
@ -22,6 +22,8 @@
|
|||||||
*/
|
*/
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
|
#include <linux/smp.h>
|
||||||
|
#include <linux/spinlock.h>
|
||||||
|
|
||||||
#include <asm/hardware.h>
|
#include <asm/hardware.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
@ -85,4 +87,4 @@ static int __init leds_init(void)
|
|||||||
return 0;
|
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_jiffy;
|
||||||
static unsigned ticks_per_usec;
|
static unsigned ticks_per_usec;
|
||||||
static unsigned next_jiffy_time;
|
static unsigned next_jiffy_time;
|
||||||
|
static volatile unsigned long *missing_jiffy_timer_csr;
|
||||||
|
|
||||||
unsigned long ixp2000_gettimeoffset (void)
|
unsigned long ixp2000_gettimeoffset (void)
|
||||||
{
|
{
|
||||||
unsigned long offset;
|
unsigned long offset;
|
||||||
|
|
||||||
offset = next_jiffy_time - *IXP2000_T4_CSR;
|
offset = next_jiffy_time - *missing_jiffy_timer_csr;
|
||||||
|
|
||||||
return offset / ticks_per_usec;
|
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 */
|
/* clear timer 1 */
|
||||||
ixp2000_reg_write(IXP2000_T1_CLR, 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);
|
timer_tick(regs);
|
||||||
next_jiffy_time -= ticks_per_jiffy;
|
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)
|
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_jiffy = (tick_rate + HZ/2) / HZ;
|
||||||
ticks_per_usec = tick_rate / 1000000;
|
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_CLD, ticks_per_jiffy - 1);
|
||||||
ixp2000_reg_write(IXP2000_T1_CTL, (1 << 7));
|
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);
|
if ((*IXP2000_PRODUCT_ID & 0x001ffef0) == 0x00000000) {
|
||||||
ixp2000_reg_write(IXP2000_T4_CTL, (1 << 7));
|
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;
|
next_jiffy_time = 0xffffffff;
|
||||||
|
|
||||||
/* register for interrupt */
|
/* register for interrupt */
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
|
#include <linux/sysdev.h>
|
||||||
#include <linux/major.h>
|
#include <linux/major.h>
|
||||||
#include <linux/fb.h>
|
#include <linux/fb.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
@ -106,6 +107,35 @@ static void __init lubbock_init_irq(void)
|
|||||||
set_irq_type(IRQ_GPIO(0), IRQT_FALLING);
|
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)
|
static int lubbock_udc_is_connected(void)
|
||||||
{
|
{
|
||||||
return (LUB_MISC_RD & (1 << 9)) == 0;
|
return (LUB_MISC_RD & (1 << 9)) == 0;
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
|
#include <linux/sysdev.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/bitops.h>
|
#include <linux/bitops.h>
|
||||||
@ -62,7 +63,6 @@ static struct irqchip mainstone_irq_chip = {
|
|||||||
.unmask = mainstone_unmask_irq,
|
.unmask = mainstone_unmask_irq,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static void mainstone_irq_handler(unsigned int irq, struct irqdesc *desc,
|
static void mainstone_irq_handler(unsigned int irq, struct irqdesc *desc,
|
||||||
struct pt_regs *regs)
|
struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
@ -100,6 +100,35 @@ static void __init mainstone_init_irq(void)
|
|||||||
set_irq_type(IRQ_GPIO(0), IRQT_FALLING);
|
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[] = {
|
static struct resource smc91x_resources[] = {
|
||||||
[0] = {
|
[0] = {
|
||||||
@ -304,6 +333,15 @@ static void __init mainstone_map_io(void)
|
|||||||
PWER = 0xC0000002;
|
PWER = 0xC0000002;
|
||||||
PRER = 0x00000002;
|
PRER = 0x00000002;
|
||||||
PFER = 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)")
|
MACHINE_START(MAINSTONE, "Intel HCDDBBVA0 Development Platform (aka Mainstone)")
|
||||||
|
@ -29,9 +29,6 @@
|
|||||||
*/
|
*/
|
||||||
#undef DEBUG
|
#undef DEBUG
|
||||||
|
|
||||||
extern void pxa_cpu_suspend(void);
|
|
||||||
extern void pxa_cpu_resume(void);
|
|
||||||
|
|
||||||
#define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x
|
#define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x
|
||||||
#define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x]
|
#define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x]
|
||||||
|
|
||||||
@ -63,6 +60,12 @@ enum { SLEEP_SAVE_START = 0,
|
|||||||
SLEEP_SAVE_ICMR,
|
SLEEP_SAVE_ICMR,
|
||||||
SLEEP_SAVE_CKEN,
|
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_CKSUM,
|
||||||
|
|
||||||
SLEEP_SAVE_SIZE
|
SLEEP_SAVE_SIZE
|
||||||
@ -75,9 +78,7 @@ static int pxa_pm_enter(suspend_state_t state)
|
|||||||
unsigned long checksum = 0;
|
unsigned long checksum = 0;
|
||||||
struct timespec delta, rtc;
|
struct timespec delta, rtc;
|
||||||
int i;
|
int i;
|
||||||
|
extern void pxa_cpu_pm_enter(suspend_state_t state);
|
||||||
if (state != PM_SUSPEND_MEM)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
#ifdef CONFIG_IWMMXT
|
#ifdef CONFIG_IWMMXT
|
||||||
/* force any iWMMXt context to ram **/
|
/* 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);
|
SAVE(GAFR2_L); SAVE(GAFR2_U);
|
||||||
|
|
||||||
#ifdef CONFIG_PXA27x
|
#ifdef CONFIG_PXA27x
|
||||||
|
SAVE(MDREFR);
|
||||||
SAVE(GPLR3); SAVE(GPDR3); SAVE(GRER3); SAVE(GFER3); SAVE(PGSR3);
|
SAVE(GPLR3); SAVE(GPDR3); SAVE(GRER3); SAVE(GFER3); SAVE(PGSR3);
|
||||||
SAVE(GAFR3_L); SAVE(GAFR3_U);
|
SAVE(GAFR3_L); SAVE(GAFR3_U);
|
||||||
|
SAVE(PWER); SAVE(PCFR); SAVE(PRER);
|
||||||
|
SAVE(PFER); SAVE(PKWR);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
SAVE(ICMR);
|
SAVE(ICMR);
|
||||||
ICMR = 0;
|
ICMR = 0;
|
||||||
|
|
||||||
SAVE(CKEN);
|
SAVE(CKEN);
|
||||||
CKEN = 0;
|
|
||||||
|
|
||||||
SAVE(PSTR);
|
SAVE(PSTR);
|
||||||
|
|
||||||
/* Note: wake up source are set up in each machine specific files */
|
/* 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 */
|
/* Clear sleep reset status */
|
||||||
RCSR = RCSR_SMR;
|
RCSR = RCSR_SMR;
|
||||||
|
|
||||||
/* set resume return address */
|
|
||||||
PSPR = virt_to_phys(pxa_cpu_resume);
|
|
||||||
|
|
||||||
/* before sleeping, calculate and save a checksum */
|
/* before sleeping, calculate and save a checksum */
|
||||||
for (i = 0; i < SLEEP_SAVE_SIZE - 1; i++)
|
for (i = 0; i < SLEEP_SAVE_SIZE - 1; i++)
|
||||||
checksum += sleep_save[i];
|
checksum += sleep_save[i];
|
||||||
sleep_save[SLEEP_SAVE_CKSUM] = checksum;
|
sleep_save[SLEEP_SAVE_CKSUM] = checksum;
|
||||||
|
|
||||||
/* *** go zzz *** */
|
/* *** go zzz *** */
|
||||||
pxa_cpu_suspend();
|
pxa_cpu_pm_enter(state);
|
||||||
|
|
||||||
|
cpu_init();
|
||||||
|
|
||||||
/* after sleeping, validate the checksum */
|
/* after sleeping, validate the checksum */
|
||||||
checksum = 0;
|
checksum = 0;
|
||||||
@ -145,7 +146,7 @@ static int pxa_pm_enter(suspend_state_t state)
|
|||||||
LUB_HEXLED = 0xbadbadc5;
|
LUB_HEXLED = 0xbadbadc5;
|
||||||
#endif
|
#endif
|
||||||
while (1)
|
while (1)
|
||||||
pxa_cpu_suspend();
|
pxa_cpu_pm_enter(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ensure not to come back here if it wasn't intended */
|
/* 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);
|
RESTORE(PGSR0); RESTORE(PGSR1); RESTORE(PGSR2);
|
||||||
|
|
||||||
#ifdef CONFIG_PXA27x
|
#ifdef CONFIG_PXA27x
|
||||||
|
RESTORE(MDREFR);
|
||||||
RESTORE(GAFR3_L); RESTORE(GAFR3_U); RESTORE_GPLEVEL(3);
|
RESTORE(GAFR3_L); RESTORE(GAFR3_U); RESTORE_GPLEVEL(3);
|
||||||
RESTORE(GPDR3); RESTORE(GRER3); RESTORE(GFER3); RESTORE(PGSR3);
|
RESTORE(GPDR3); RESTORE(GRER3); RESTORE(GFER3); RESTORE(PGSR3);
|
||||||
|
RESTORE(PWER); RESTORE(PCFR); RESTORE(PRER);
|
||||||
|
RESTORE(PFER); RESTORE(PKWR);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
PSSR = PSSR_RDH | PSSR_PH;
|
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)
|
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
|
* initialization stuff for PXA machines which can be overridden later if
|
||||||
* need be.
|
* need be.
|
||||||
*/
|
*/
|
||||||
|
#include <linux/config.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
@ -102,3 +103,35 @@ unsigned int get_lcdclk_frequency_10khz(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(get_lcdclk_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:
|
||||||
|
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_memclk_frequency_10khz);
|
||||||
EXPORT_SYMBOL(get_lcdclk_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.
|
* 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->client = NULL;
|
||||||
chan->in_use = 0;
|
chan->in_use = 0;
|
||||||
|
|
||||||
|
if (chan->irq_claimed)
|
||||||
|
free_irq(chan->irq, (void *)chan);
|
||||||
|
chan->irq_claimed = 0;
|
||||||
|
|
||||||
local_irq_restore(flags);
|
local_irq_restore(flags);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -150,7 +150,7 @@ config SA1100_SSP
|
|||||||
|
|
||||||
config H3600_SLEEVE
|
config H3600_SLEEVE
|
||||||
tristate "Compaq iPAQ Handheld sleeve support"
|
tristate "Compaq iPAQ Handheld sleeve support"
|
||||||
depends on SA1100_H3600
|
depends on SA1100_H3100 || SA1100_H3600
|
||||||
help
|
help
|
||||||
Choose this option to enable support for extension packs (sleeves)
|
Choose this option to enable support for extension packs (sleeves)
|
||||||
for the Compaq iPAQ H3XXX series of handheld computers. This option
|
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 */
|
/* go zzz */
|
||||||
sa1100_cpu_suspend();
|
sa1100_cpu_suspend();
|
||||||
|
|
||||||
|
cpu_init();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ensure not to come back here if it wasn't intended
|
* Ensure not to come back here if it wasn't intended
|
||||||
*/
|
*/
|
||||||
|
@ -5,3 +5,4 @@
|
|||||||
obj-y := core.o clock.o
|
obj-y := core.o clock.o
|
||||||
obj-$(CONFIG_ARCH_VERSATILE_PB) += versatile_pb.o
|
obj-$(CONFIG_ARCH_VERSATILE_PB) += versatile_pb.o
|
||||||
obj-$(CONFIG_MACH_VERSATILE_AB) += versatile_ab.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
|
#ifdef CONFIG_DEBUG_LL
|
||||||
{ IO_ADDRESS(VERSATILE_UART0_BASE), VERSATILE_UART0_BASE, SZ_4K, MT_DEVICE },
|
{ IO_ADDRESS(VERSATILE_UART0_BASE), VERSATILE_UART0_BASE, SZ_4K, MT_DEVICE },
|
||||||
#endif
|
#endif
|
||||||
#ifdef FIXME
|
#ifdef CONFIG_PCI
|
||||||
{ PCI_MEMORY_VADDR, PHYS_PCI_MEM_BASE, SZ_16M, MT_DEVICE },
|
{ IO_ADDRESS(VERSATILE_PCI_CORE_BASE), VERSATILE_PCI_CORE_BASE, SZ_4K, MT_DEVICE },
|
||||||
{ PCI_CONFIG_VADDR, PHYS_PCI_CONFIG_BASE, SZ_16M, MT_DEVICE },
|
{ VERSATILE_PCI_VIRT_BASE, VERSATILE_PCI_BASE, VERSATILE_PCI_BASE_SIZE, MT_DEVICE },
|
||||||
{ PCI_V3_VADDR, PHYS_PCI_V3_BASE, SZ_512K, MT_DEVICE },
|
{ VERSATILE_PCI_CFG_VIRT_BASE, VERSATILE_PCI_CFG_BASE, VERSATILE_PCI_CFG_BASE_SIZE, MT_DEVICE },
|
||||||
{ PCI_IO_VADDR, PHYS_PCI_IO_BASE, SZ_64K, 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
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -543,7 +547,7 @@ static void versatile_clcd_enable(struct clcd_fb *fb)
|
|||||||
val |= SYS_CLCD_MODE_5551;
|
val |= SYS_CLCD_MODE_5551;
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
val |= SYS_CLCD_MODE_565_BLSB;
|
val |= SYS_CLCD_MODE_565_RLSB;
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
val |= SYS_CLCD_MODE_888;
|
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
|
# ARM920T
|
||||||
config CPU_ARM920T
|
config CPU_ARM920T
|
||||||
bool "Support ARM920T processor" if !ARCH_S3C2410
|
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
|
default y if ARCH_S3C2410
|
||||||
select CPU_32v4
|
select CPU_32v4
|
||||||
select CPU_ABRT_EV4T
|
select CPU_ABRT_EV4T
|
||||||
@ -228,7 +228,6 @@ config CPU_SA1100
|
|||||||
select CPU_CACHE_V4WB
|
select CPU_CACHE_V4WB
|
||||||
select CPU_CACHE_VIVT
|
select CPU_CACHE_VIVT
|
||||||
select CPU_TLB_V4WB
|
select CPU_TLB_V4WB
|
||||||
select CPU_MINICACHE
|
|
||||||
|
|
||||||
# XScale
|
# XScale
|
||||||
config CPU_XSCALE
|
config CPU_XSCALE
|
||||||
@ -239,7 +238,6 @@ config CPU_XSCALE
|
|||||||
select CPU_ABRT_EV5T
|
select CPU_ABRT_EV5T
|
||||||
select CPU_CACHE_VIVT
|
select CPU_CACHE_VIVT
|
||||||
select CPU_TLB_V4WBI
|
select CPU_TLB_V4WBI
|
||||||
select CPU_MINICACHE
|
|
||||||
|
|
||||||
# ARMv6
|
# ARMv6
|
||||||
config CPU_V6
|
config CPU_V6
|
||||||
@ -345,11 +343,6 @@ config CPU_TLB_V4WBI
|
|||||||
config CPU_TLB_V6
|
config CPU_TLB_V6
|
||||||
bool
|
bool
|
||||||
|
|
||||||
config CPU_MINICACHE
|
|
||||||
bool
|
|
||||||
help
|
|
||||||
Processor has a minicache.
|
|
||||||
|
|
||||||
comment "Processor Features"
|
comment "Processor Features"
|
||||||
|
|
||||||
config ARM_THUMB
|
config ARM_THUMB
|
||||||
@ -429,3 +422,11 @@ config HAS_TLS_REG
|
|||||||
assume directly accessing that register and always obtain the
|
assume directly accessing that register and always obtain the
|
||||||
expected value only on ARMv7 and above.
|
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_SA1100) += copypage-v4mc.o
|
||||||
obj-$(CONFIG_CPU_XSCALE) += copypage-xscale.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_V3) += tlb-v3.o
|
||||||
obj-$(CONFIG_CPU_TLB_V4WT) += tlb-v4.o
|
obj-$(CONFIG_CPU_TLB_V4WT) += tlb-v4.o
|
||||||
obj-$(CONFIG_CPU_TLB_V4WB) += tlb-v4wb.o
|
obj-$(CONFIG_CPU_TLB_V4WB) += tlb-v4wb.o
|
||||||
|
@ -30,8 +30,6 @@
|
|||||||
|
|
||||||
static DEFINE_SPINLOCK(v6_lock);
|
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
|
* Copy the user page. No aliasing to deal with so we can just
|
||||||
* attack the kernel's existing mapping of these pages.
|
* 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)
|
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;
|
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)
|
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);
|
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
|
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 mm_struct *mm = vma->vm_mm;
|
||||||
struct vm_area_struct *mpnt;
|
struct vm_area_struct *mpnt;
|
||||||
struct prio_tree_iter iter;
|
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;
|
pgoff_t pgoff;
|
||||||
int aliases = 0;
|
int aliases = 0;
|
||||||
|
|
||||||
if (!mapping)
|
|
||||||
return;
|
|
||||||
|
|
||||||
pgoff = vma->vm_pgoff + ((addr - vma->vm_start) >> PAGE_SHIFT);
|
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)
|
if (aliases)
|
||||||
adjust_pte(vma, addr);
|
adjust_pte(vma, addr);
|
||||||
else
|
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
|
* Take care of architecture specific things when placing a new PTE into
|
||||||
* a page table, or changing an existing PTE. Basically, there are two
|
* 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)
|
void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte_t pte)
|
||||||
{
|
{
|
||||||
unsigned long pfn = pte_pfn(pte);
|
unsigned long pfn = pte_pfn(pte);
|
||||||
|
struct address_space *mapping;
|
||||||
struct page *page;
|
struct page *page;
|
||||||
|
|
||||||
if (!pfn_valid(pfn))
|
if (!pfn_valid(pfn))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
page = pfn_to_page(pfn);
|
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);
|
int dirty = test_and_clear_bit(PG_dcache_dirty, &page->flags);
|
||||||
|
|
||||||
if (dirty) {
|
if (dirty)
|
||||||
/*
|
__flush_dcache_page(mapping, page);
|
||||||
* 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 (cache_is_vivt())
|
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)
|
#define flush_pfn_alias(pfn,vaddr) do { } while (0)
|
||||||
#endif
|
#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
|
* Writeback any data associated with the kernel mapping of this
|
||||||
* page. This ensures that data in the physical page is mutually
|
* 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));
|
__cpuc_flush_dcache_page(page_address(page));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If there's no mapping pointer here, then this page isn't
|
* If this is a page cache page, and we have an aliasing VIPT cache,
|
||||||
* visible to userspace yet, so there are no cache lines
|
* we only need to do one flush - which would be at the relevant
|
||||||
* 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
|
|
||||||
* userspace colour, which is congruent with page->index.
|
* userspace colour, which is congruent with page->index.
|
||||||
*/
|
*/
|
||||||
if (cache_is_vipt()) {
|
if (mapping && cache_is_vipt_aliasing())
|
||||||
if (cache_is_vipt_aliasing())
|
flush_pfn_alias(page_to_pfn(page),
|
||||||
flush_pfn_alias(page_to_pfn(page),
|
page->index << PAGE_CACHE_SHIFT);
|
||||||
page->index << PAGE_CACHE_SHIFT);
|
}
|
||||||
return;
|
|
||||||
}
|
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:
|
* 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);
|
struct address_space *mapping = page_mapping(page);
|
||||||
|
|
||||||
if (cache_is_vipt_nonaliasing())
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (mapping && !mapping_mapped(mapping))
|
if (mapping && !mapping_mapped(mapping))
|
||||||
set_bit(PG_dcache_dirty, &page->flags);
|
set_bit(PG_dcache_dirty, &page->flags);
|
||||||
else
|
else {
|
||||||
__flush_dcache_page(mapping, page);
|
__flush_dcache_page(mapping, page);
|
||||||
|
if (mapping && cache_is_vivt())
|
||||||
|
__flush_dcache_aliases(mapping, page);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(flush_dcache_page);
|
EXPORT_SYMBOL(flush_dcache_page);
|
||||||
|
@ -170,3 +170,50 @@ void __iounmap(void __iomem *addr)
|
|||||||
vfree((void *) (PAGE_MASK & (unsigned long) addr));
|
vfree((void *) (PAGE_MASK & (unsigned long) addr));
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(__iounmap);
|
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);
|
struct expansion_card *ec = ECARD_DEV(dev);
|
||||||
return sprintf(buf, "%u\n", ec->irq);
|
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);
|
struct expansion_card *ec = ECARD_DEV(dev);
|
||||||
return sprintf(buf, "%u\n", ec->cid.manufacturer);
|
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);
|
struct expansion_card *ec = ECARD_DEV(dev);
|
||||||
return sprintf(buf, "%u\n", ec->cid.product);
|
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);
|
struct expansion_card *ec = ECARD_DEV(dev);
|
||||||
return sprintf(buf, "%u\n", ec->dma);
|
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);
|
struct expansion_card *ec = ECARD_DEV(dev);
|
||||||
char *str = buf;
|
char *str = buf;
|
||||||
|
@ -54,7 +54,7 @@ asmlinkage void ret_from_fork(void);
|
|||||||
void default_idle(void)
|
void default_idle(void)
|
||||||
{
|
{
|
||||||
while(1) {
|
while(1) {
|
||||||
if (need_resched()) {
|
if (!need_resched()) {
|
||||||
local_irq_enable();
|
local_irq_enable();
|
||||||
__asm__("sleep");
|
__asm__("sleep");
|
||||||
local_irq_disable();
|
local_irq_disable();
|
||||||
|
@ -43,7 +43,7 @@ obj-$(CONFIG_SCx200) += scx200.o
|
|||||||
# Note: kbuild does not track this dependency due to usage of .incbin
|
# Note: kbuild does not track this dependency due to usage of .incbin
|
||||||
$(obj)/vsyscall.o: $(obj)/vsyscall-int80.so $(obj)/vsyscall-sysenter.so
|
$(obj)/vsyscall.o: $(obj)/vsyscall-int80.so $(obj)/vsyscall-sysenter.so
|
||||||
targets += $(foreach F,int80 sysenter,vsyscall-$F.o vsyscall-$F.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.
|
# The DSO images are built using a special linker script.
|
||||||
quiet_cmd_syscall = SYSCALL $@
|
quiet_cmd_syscall = SYSCALL $@
|
||||||
|
@ -1222,6 +1222,7 @@ static int suspend(int vetoable)
|
|||||||
|
|
||||||
save_processor_state();
|
save_processor_state();
|
||||||
err = set_system_power_state(APM_STATE_SUSPEND);
|
err = set_system_power_state(APM_STATE_SUSPEND);
|
||||||
|
ignore_normal_resume = 1;
|
||||||
restore_processor_state();
|
restore_processor_state();
|
||||||
|
|
||||||
local_irq_disable();
|
local_irq_disable();
|
||||||
@ -1229,7 +1230,6 @@ static int suspend(int vetoable)
|
|||||||
spin_lock(&i8253_lock);
|
spin_lock(&i8253_lock);
|
||||||
reinit_timer();
|
reinit_timer();
|
||||||
set_time();
|
set_time();
|
||||||
ignore_normal_resume = 1;
|
|
||||||
|
|
||||||
spin_unlock(&i8253_lock);
|
spin_unlock(&i8253_lock);
|
||||||
write_sequnlock(&xtime_lock);
|
write_sequnlock(&xtime_lock);
|
||||||
|
@ -23,7 +23,7 @@ config X86_ACPI_CPUFREQ
|
|||||||
If in doubt, say N.
|
If in doubt, say N.
|
||||||
|
|
||||||
config ELAN_CPUFREQ
|
config ELAN_CPUFREQ
|
||||||
tristate "AMD Elan"
|
tristate "AMD Elan SC400 and SC410"
|
||||||
select CPU_FREQ_TABLE
|
select CPU_FREQ_TABLE
|
||||||
depends on X86_ELAN
|
depends on X86_ELAN
|
||||||
---help---
|
---help---
|
||||||
@ -38,6 +38,18 @@ config ELAN_CPUFREQ
|
|||||||
|
|
||||||
If in doubt, say N.
|
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
|
config X86_POWERNOW_K6
|
||||||
tristate "AMD Mobile K6-2/K6-3 PowerNow!"
|
tristate "AMD Mobile K6-2/K6-3 PowerNow!"
|
||||||
select CPU_FREQ_TABLE
|
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_POWERNOW_K8) += powernow-k8.o
|
||||||
obj-$(CONFIG_X86_LONGHAUL) += longhaul.o
|
obj-$(CONFIG_X86_LONGHAUL) += longhaul.o
|
||||||
obj-$(CONFIG_ELAN_CPUFREQ) += elanfreq.o
|
obj-$(CONFIG_ELAN_CPUFREQ) += elanfreq.o
|
||||||
|
obj-$(CONFIG_SC520_CPUFREQ) += sc520_freq.o
|
||||||
obj-$(CONFIG_X86_LONGRUN) += longrun.o
|
obj-$(CONFIG_X86_LONGRUN) += longrun.o
|
||||||
obj-$(CONFIG_X86_GX_SUSPMOD) += gx-suspmod.o
|
obj-$(CONFIG_X86_GX_SUSPMOD) += gx-suspmod.o
|
||||||
obj-$(CONFIG_X86_SPEEDSTEP_ICH) += speedstep-ich.o
|
obj-$(CONFIG_X86_SPEEDSTEP_ICH) += speedstep-ich.o
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#include <linux/cpufreq.h>
|
#include <linux/cpufreq.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
|
#include <linux/pci.h>
|
||||||
|
|
||||||
#include <asm/msr.h>
|
#include <asm/msr.h>
|
||||||
#include <asm/timex.h>
|
#include <asm/timex.h>
|
||||||
@ -119,7 +120,13 @@ static int longhaul_get_cpu_mult(void)
|
|||||||
static void do_powersaver(union msr_longhaul *longhaul,
|
static void do_powersaver(union msr_longhaul *longhaul,
|
||||||
unsigned int clock_ratio_index)
|
unsigned int clock_ratio_index)
|
||||||
{
|
{
|
||||||
|
struct pci_dev *dev;
|
||||||
|
unsigned long flags;
|
||||||
|
unsigned int tmp_mask;
|
||||||
int version;
|
int version;
|
||||||
|
int i;
|
||||||
|
u16 pci_cmd;
|
||||||
|
u16 cmd_state[64];
|
||||||
|
|
||||||
switch (cpu_model) {
|
switch (cpu_model) {
|
||||||
case CPU_EZRA_T:
|
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.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
|
||||||
longhaul->bits.EnableSoftBusRatio = 1;
|
longhaul->bits.EnableSoftBusRatio = 1;
|
||||||
longhaul->bits.RevisionKey = 0;
|
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();
|
local_irq_enable();
|
||||||
|
|
||||||
|
__hlt();
|
||||||
|
wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
|
||||||
__hlt();
|
__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);
|
rdmsrl(MSR_VIA_LONGHAUL, longhaul->val);
|
||||||
longhaul->bits.EnableSoftBusRatio = 0;
|
longhaul->bits.EnableSoftBusRatio = 0;
|
||||||
longhaul->bits.RevisionKey = version;
|
longhaul->bits.RevisionKey = version;
|
||||||
local_irq_disable();
|
|
||||||
wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
|
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();
|
longhaul_setup_voltagescaling();
|
||||||
|
|
||||||
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
|
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());
|
policy->cur = calc_speed(longhaul_get_cpu_mult());
|
||||||
|
|
||||||
ret = cpufreq_frequency_table_cpuinfo(policy, longhaul_table);
|
ret = cpufreq_frequency_table_cpuinfo(policy, longhaul_table);
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include <linux/dmi.h>
|
#include <linux/dmi.h>
|
||||||
|
|
||||||
#include <asm/msr.h>
|
#include <asm/msr.h>
|
||||||
|
#include <asm/timer.h>
|
||||||
#include <asm/timex.h>
|
#include <asm/timex.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include <asm/system.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);
|
rdmsrl (MSR_K7_FID_VID_STATUS, fidvidstatus.val);
|
||||||
|
|
||||||
/* A K7 with powernow technology is set to max frequency by BIOS */
|
/* recalibrate cpu_khz */
|
||||||
fsb = (10 * cpu_khz) / fid_codes[fidvidstatus.bits.MFID];
|
result = recalibrate_cpu_khz();
|
||||||
|
if (result)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
fsb = (10 * cpu_khz) / fid_codes[fidvidstatus.bits.CFID];
|
||||||
if (!fsb) {
|
if (!fsb) {
|
||||||
printk(KERN_WARNING PFX "can not determine bus frequency\n");
|
printk(KERN_WARNING PFX "can not determine bus frequency\n");
|
||||||
return -EINVAL;
|
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) {
|
if (dmi_check_system(powernow_dmi_table) || acpi_force) {
|
||||||
printk (KERN_INFO PFX "PSB/PST known to be broken. Trying ACPI instead\n");
|
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
|
* GNU general public license version 2. See "COPYING" or
|
||||||
* http://www.gnu.org/licenses/gpl.html
|
* 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.
|
* Based on the powernow-k7.c module written by Dave Jones.
|
||||||
* (C) 2003 Dave Jones <davej@codemonkey.org.uk> on behalf of SuSE Labs
|
* (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,
|
* Valuable input gratefully received from Dave Jones, Pavel Machek,
|
||||||
* Dominik Brodowski, and others.
|
* Dominik Brodowski, and others.
|
||||||
|
* Originally developed by Paul Devriendt.
|
||||||
* Processor information obtained from Chapter 9 (Power and Thermal Management)
|
* 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
|
* of the "BIOS and Kernel Developer's Guide for the AMD Athlon 64 and AMD
|
||||||
* Opteron Processors" available for download from www.amd.com
|
* Opteron Processors" available for download from www.amd.com
|
||||||
*
|
*
|
||||||
* Tables for specific CPUs can be infrerred from
|
* 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>
|
#include <linux/kernel.h>
|
||||||
@ -30,6 +31,7 @@
|
|||||||
#include <linux/cpufreq.h>
|
#include <linux/cpufreq.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
|
#include <linux/cpumask.h>
|
||||||
|
|
||||||
#include <asm/msr.h>
|
#include <asm/msr.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
@ -42,7 +44,7 @@
|
|||||||
|
|
||||||
#define PFX "powernow-k8: "
|
#define PFX "powernow-k8: "
|
||||||
#define BFX PFX "BIOS error: "
|
#define BFX PFX "BIOS error: "
|
||||||
#define VERSION "version 1.00.09e"
|
#define VERSION "version 1.40.2"
|
||||||
#include "powernow-k8.h"
|
#include "powernow-k8.h"
|
||||||
|
|
||||||
/* serialize freq changes */
|
/* serialize freq changes */
|
||||||
@ -50,6 +52,10 @@ static DECLARE_MUTEX(fidvid_sem);
|
|||||||
|
|
||||||
static struct powernow_k8_data *powernow_data[NR_CPUS];
|
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 */
|
/* Return a frequency in MHz, given an input fid */
|
||||||
static u32 find_freq_from_fid(u32 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 rvosteps = data->rvo;
|
||||||
u32 savefid = data->currfid;
|
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",
|
dprintk("ph1 (cpu%d): start, currfid 0x%x, currvid 0x%x, reqvid 0x%x, rvo 0x%x\n",
|
||||||
smp_processor_id(),
|
smp_processor_id(),
|
||||||
data->currfid, data->currvid, reqvid, data->rvo);
|
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) {
|
while (data->currvid > reqvid) {
|
||||||
dprintk("ph1: curr 0x%x, req vid 0x%x\n",
|
dprintk("ph1: curr 0x%x, req vid 0x%x\n",
|
||||||
data->currvid, reqvid);
|
data->currvid, reqvid);
|
||||||
@ -286,8 +299,8 @@ static int core_voltage_pre_transition(struct powernow_k8_data *data, u32 reqvid
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((rvosteps > 0) && ((data->rvo + data->currvid) > reqvid)) {
|
while ((rvosteps > 0) && ((data->rvo + data->currvid) > reqvid)) {
|
||||||
if (data->currvid == 0) {
|
if (data->currvid == maxvid) {
|
||||||
rvosteps = 0;
|
rvosteps = 0;
|
||||||
} else {
|
} else {
|
||||||
dprintk("ph1: changing vid for rvo, req 0x%x\n",
|
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
|
* BIOS and Kernel Developer's Guide, which is available on
|
||||||
* www.amd.com
|
* 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;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -695,7 +708,7 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
|
|||||||
struct cpufreq_frequency_table *powernow_table;
|
struct cpufreq_frequency_table *powernow_table;
|
||||||
|
|
||||||
if (acpi_processor_register_performance(&data->acpi_data, data->cpu)) {
|
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;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -746,22 +759,23 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fid < HI_FID_TABLE_BOTTOM) {
|
/* verify only 1 entry from the lo frequency table */
|
||||||
if (cntlofreq) {
|
if (fid < HI_FID_TABLE_BOTTOM) {
|
||||||
/* if both entries are the same, ignore this
|
if (cntlofreq) {
|
||||||
* one...
|
/* 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)) {
|
if ((powernow_table[i].frequency != powernow_table[cntlofreq].frequency) ||
|
||||||
printk(KERN_ERR PFX "Too many lo freq table entries\n");
|
(powernow_table[i].index != powernow_table[cntlofreq].index)) {
|
||||||
goto err_out_mem;
|
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;
|
dprintk("double low frequency table entry, ignoring it.\n");
|
||||||
continue;
|
powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID;
|
||||||
} else
|
continue;
|
||||||
cntlofreq = i;
|
} else
|
||||||
|
cntlofreq = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (powernow_table[i].frequency != (data->acpi_data.states[i].core_frequency * 1000)) {
|
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 fid;
|
||||||
u32 vid;
|
u32 vid;
|
||||||
int res;
|
int res, i;
|
||||||
struct cpufreq_freqs freqs;
|
struct cpufreq_freqs freqs;
|
||||||
|
|
||||||
dprintk("cpu %d transition to index %u\n", smp_processor_id(), index);
|
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)) {
|
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);
|
data->currfid, fid);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -850,18 +865,20 @@ static int transition_frequency(struct powernow_k8_data *data, unsigned int inde
|
|||||||
smp_processor_id(), fid, vid);
|
smp_processor_id(), fid, vid);
|
||||||
|
|
||||||
freqs.cpu = data->cpu;
|
freqs.cpu = data->cpu;
|
||||||
|
|
||||||
freqs.old = find_khz_freq_from_fid(data->currfid);
|
freqs.old = find_khz_freq_from_fid(data->currfid);
|
||||||
freqs.new = find_khz_freq_from_fid(fid);
|
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);
|
res = transition_fid_vid(data, fid, vid);
|
||||||
up(&fidvid_sem);
|
|
||||||
|
|
||||||
freqs.new = find_khz_freq_from_fid(data->currfid);
|
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;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -874,6 +891,7 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi
|
|||||||
u32 checkvid = data->currvid;
|
u32 checkvid = data->currvid;
|
||||||
unsigned int newstate;
|
unsigned int newstate;
|
||||||
int ret = -EIO;
|
int ret = -EIO;
|
||||||
|
int i;
|
||||||
|
|
||||||
/* only run on specific CPU from here on */
|
/* only run on specific CPU from here on */
|
||||||
oldmask = current->cpus_allowed;
|
oldmask = current->cpus_allowed;
|
||||||
@ -902,22 +920,41 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi
|
|||||||
data->currfid, data->currvid);
|
data->currfid, data->currvid);
|
||||||
|
|
||||||
if ((checkvid != data->currvid) || (checkfid != data->currfid)) {
|
if ((checkvid != data->currvid) || (checkfid != data->currfid)) {
|
||||||
printk(KERN_ERR PFX
|
printk(KERN_INFO PFX
|
||||||
"error - out of sync, fid 0x%x 0x%x, vid 0x%x 0x%x\n",
|
"error - out of sync, fix 0x%x 0x%x, vid 0x%x 0x%x\n",
|
||||||
checkfid, data->currfid, checkvid, data->currvid);
|
checkfid, data->currfid, checkvid, data->currvid);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cpufreq_frequency_table_target(pol, data->powernow_table, targfreq, relation, &newstate))
|
if (cpufreq_frequency_table_target(pol, data->powernow_table, targfreq, relation, &newstate))
|
||||||
goto err_out;
|
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);
|
powernow_k8_acpi_pst_values(data, newstate);
|
||||||
|
|
||||||
if (transition_frequency(data, newstate)) {
|
if (transition_frequency(data, newstate)) {
|
||||||
printk(KERN_ERR PFX "transition frequency failed\n");
|
printk(KERN_ERR PFX "transition frequency failed\n");
|
||||||
ret = 1;
|
ret = 1;
|
||||||
|
up(&fidvid_sem);
|
||||||
goto err_out;
|
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);
|
pol->cur = find_khz_freq_from_fid(data->currfid);
|
||||||
ret = 0;
|
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)) {
|
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);
|
kfree(data);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
@ -1003,6 +1040,7 @@ static int __init powernowk8_cpu_init(struct cpufreq_policy *pol)
|
|||||||
schedule();
|
schedule();
|
||||||
|
|
||||||
pol->governor = CPUFREQ_DEFAULT_GOVERNOR;
|
pol->governor = CPUFREQ_DEFAULT_GOVERNOR;
|
||||||
|
pol->cpus = cpu_core_map[pol->cpu];
|
||||||
|
|
||||||
/* Take a crude guess here.
|
/* Take a crude guess here.
|
||||||
* That guess was in microseconds, so multiply with 1000 */
|
* That guess was in microseconds, so multiply with 1000 */
|
||||||
@ -1069,7 +1107,7 @@ static unsigned int powernowk8_get (unsigned int cpu)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
preempt_disable();
|
preempt_disable();
|
||||||
|
|
||||||
if (query_current_values_with_pending_wait(data))
|
if (query_current_values_with_pending_wait(data))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
@ -1127,9 +1165,10 @@ static void __exit powernowk8_exit(void)
|
|||||||
cpufreq_unregister_driver(&cpufreq_amd64_driver);
|
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_DESCRIPTION("AMD Athlon 64 and Opteron processor frequency driver.");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
late_initcall(powernowk8_init);
|
late_initcall(powernowk8_init);
|
||||||
module_exit(powernowk8_exit);
|
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 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);
|
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_A1,
|
||||||
CPU_DOTHAN_A2,
|
CPU_DOTHAN_A2,
|
||||||
CPU_DOTHAN_B0,
|
CPU_DOTHAN_B0,
|
||||||
|
CPU_MP4HT_D0,
|
||||||
|
CPU_MP4HT_E0,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct cpu_id cpu_ids[] = {
|
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_A1] = { 6, 13, 1 },
|
||||||
[CPU_DOTHAN_A2] = { 6, 13, 2 },
|
[CPU_DOTHAN_A2] = { 6, 13, 2 },
|
||||||
[CPU_DOTHAN_B0] = { 6, 13, 6 },
|
[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]))
|
#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_A1], NULL, 0, NULL },
|
||||||
{ &cpu_ids[CPU_DOTHAN_A2], NULL, 0, NULL },
|
{ &cpu_ids[CPU_DOTHAN_A2], NULL, 0, NULL },
|
||||||
{ &cpu_ids[CPU_DOTHAN_B0], 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, }
|
{ NULL, }
|
||||||
};
|
};
|
||||||
|
@ -336,7 +336,7 @@ unsigned int speedstep_get_freqs(unsigned int processor,
|
|||||||
if (!prev_speed)
|
if (!prev_speed)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
dprintk("previous seped is %u\n", prev_speed);
|
dprintk("previous speed is %u\n", prev_speed);
|
||||||
|
|
||||||
local_irq_save(flags);
|
local_irq_save(flags);
|
||||||
|
|
||||||
@ -348,7 +348,7 @@ unsigned int speedstep_get_freqs(unsigned int processor,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
dprintk("low seped is %u\n", *low_speed);
|
dprintk("low speed is %u\n", *low_speed);
|
||||||
|
|
||||||
/* switch to high state */
|
/* switch to high state */
|
||||||
set_state(SPEEDSTEP_HIGH);
|
set_state(SPEEDSTEP_HIGH);
|
||||||
@ -358,7 +358,7 @@ unsigned int speedstep_get_freqs(unsigned int processor,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
dprintk("high seped is %u\n", *high_speed);
|
dprintk("high speed is %u\n", *high_speed);
|
||||||
|
|
||||||
if (*low_speed == *high_speed) {
|
if (*low_speed == *high_speed) {
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
|
@ -357,6 +357,9 @@ static int __init speedstep_init(void)
|
|||||||
case SPEEDSTEP_PROCESSOR_PIII_C:
|
case SPEEDSTEP_PROCESSOR_PIII_C:
|
||||||
case SPEEDSTEP_PROCESSOR_PIII_C_EARLY:
|
case SPEEDSTEP_PROCESSOR_PIII_C_EARLY:
|
||||||
break;
|
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:
|
default:
|
||||||
speedstep_processor = 0;
|
speedstep_processor = 0;
|
||||||
}
|
}
|
||||||
|
@ -118,7 +118,7 @@ struct _cpuid4_info {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#define MAX_CACHE_LEAVES 4
|
#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)
|
static int __devinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf)
|
||||||
{
|
{
|
||||||
|
@ -45,7 +45,7 @@
|
|||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
#include <asm/system.h>
|
#include <asm/system.h>
|
||||||
|
|
||||||
static struct class_simple *cpuid_class;
|
static struct class *cpuid_class;
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
|
|
||||||
@ -158,12 +158,12 @@ static struct file_operations cpuid_fops = {
|
|||||||
.open = cpuid_open,
|
.open = cpuid_open,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int cpuid_class_simple_device_add(int i)
|
static int cpuid_class_device_create(int i)
|
||||||
{
|
{
|
||||||
int err = 0;
|
int err = 0;
|
||||||
struct class_device *class_err;
|
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))
|
if (IS_ERR(class_err))
|
||||||
err = PTR_ERR(class_err);
|
err = PTR_ERR(class_err);
|
||||||
return err;
|
return err;
|
||||||
@ -175,10 +175,10 @@ static int __devinit cpuid_class_cpu_callback(struct notifier_block *nfb, unsign
|
|||||||
|
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case CPU_ONLINE:
|
case CPU_ONLINE:
|
||||||
cpuid_class_simple_device_add(cpu);
|
cpuid_class_device_create(cpu);
|
||||||
break;
|
break;
|
||||||
case CPU_DEAD:
|
case CPU_DEAD:
|
||||||
class_simple_device_remove(MKDEV(CPUID_MAJOR, cpu));
|
class_device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, cpu));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return NOTIFY_OK;
|
return NOTIFY_OK;
|
||||||
@ -200,13 +200,13 @@ static int __init cpuid_init(void)
|
|||||||
err = -EBUSY;
|
err = -EBUSY;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
cpuid_class = class_simple_create(THIS_MODULE, "cpuid");
|
cpuid_class = class_create(THIS_MODULE, "cpuid");
|
||||||
if (IS_ERR(cpuid_class)) {
|
if (IS_ERR(cpuid_class)) {
|
||||||
err = PTR_ERR(cpuid_class);
|
err = PTR_ERR(cpuid_class);
|
||||||
goto out_chrdev;
|
goto out_chrdev;
|
||||||
}
|
}
|
||||||
for_each_online_cpu(i) {
|
for_each_online_cpu(i) {
|
||||||
err = cpuid_class_simple_device_add(i);
|
err = cpuid_class_device_create(i);
|
||||||
if (err != 0)
|
if (err != 0)
|
||||||
goto out_class;
|
goto out_class;
|
||||||
}
|
}
|
||||||
@ -218,9 +218,9 @@ static int __init cpuid_init(void)
|
|||||||
out_class:
|
out_class:
|
||||||
i = 0;
|
i = 0;
|
||||||
for_each_online_cpu(i) {
|
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:
|
out_chrdev:
|
||||||
unregister_chrdev(CPUID_MAJOR, "cpu/cpuid");
|
unregister_chrdev(CPUID_MAJOR, "cpu/cpuid");
|
||||||
out:
|
out:
|
||||||
@ -232,8 +232,8 @@ static void __exit cpuid_exit(void)
|
|||||||
int cpu = 0;
|
int cpu = 0;
|
||||||
|
|
||||||
for_each_online_cpu(cpu)
|
for_each_online_cpu(cpu)
|
||||||
class_simple_device_remove(MKDEV(CPUID_MAJOR, cpu));
|
class_device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, cpu));
|
||||||
class_simple_destroy(cpuid_class);
|
class_destroy(cpuid_class);
|
||||||
unregister_chrdev(CPUID_MAJOR, "cpu/cpuid");
|
unregister_chrdev(CPUID_MAJOR, "cpu/cpuid");
|
||||||
unregister_cpu_notifier(&cpuid_class_cpu_notifier);
|
unregister_cpu_notifier(&cpuid_class_cpu_notifier);
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@
|
|||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
#include <asm/system.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
|
/* Note: "err" is handled in a funny way below. Otherwise one version
|
||||||
of gcc or another breaks. */
|
of gcc or another breaks. */
|
||||||
@ -260,12 +260,12 @@ static struct file_operations msr_fops = {
|
|||||||
.open = msr_open,
|
.open = msr_open,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int msr_class_simple_device_add(int i)
|
static int msr_class_device_create(int i)
|
||||||
{
|
{
|
||||||
int err = 0;
|
int err = 0;
|
||||||
struct class_device *class_err;
|
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))
|
if (IS_ERR(class_err))
|
||||||
err = PTR_ERR(class_err);
|
err = PTR_ERR(class_err);
|
||||||
return err;
|
return err;
|
||||||
@ -277,10 +277,10 @@ static int __devinit msr_class_cpu_callback(struct notifier_block *nfb, unsigned
|
|||||||
|
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case CPU_ONLINE:
|
case CPU_ONLINE:
|
||||||
msr_class_simple_device_add(cpu);
|
msr_class_device_create(cpu);
|
||||||
break;
|
break;
|
||||||
case CPU_DEAD:
|
case CPU_DEAD:
|
||||||
class_simple_device_remove(MKDEV(MSR_MAJOR, cpu));
|
class_device_destroy(msr_class, MKDEV(MSR_MAJOR, cpu));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return NOTIFY_OK;
|
return NOTIFY_OK;
|
||||||
@ -302,13 +302,13 @@ static int __init msr_init(void)
|
|||||||
err = -EBUSY;
|
err = -EBUSY;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
msr_class = class_simple_create(THIS_MODULE, "msr");
|
msr_class = class_create(THIS_MODULE, "msr");
|
||||||
if (IS_ERR(msr_class)) {
|
if (IS_ERR(msr_class)) {
|
||||||
err = PTR_ERR(msr_class);
|
err = PTR_ERR(msr_class);
|
||||||
goto out_chrdev;
|
goto out_chrdev;
|
||||||
}
|
}
|
||||||
for_each_online_cpu(i) {
|
for_each_online_cpu(i) {
|
||||||
err = msr_class_simple_device_add(i);
|
err = msr_class_device_create(i);
|
||||||
if (err != 0)
|
if (err != 0)
|
||||||
goto out_class;
|
goto out_class;
|
||||||
}
|
}
|
||||||
@ -320,8 +320,8 @@ static int __init msr_init(void)
|
|||||||
out_class:
|
out_class:
|
||||||
i = 0;
|
i = 0;
|
||||||
for_each_online_cpu(i)
|
for_each_online_cpu(i)
|
||||||
class_simple_device_remove(MKDEV(MSR_MAJOR, i));
|
class_device_destroy(msr_class, MKDEV(MSR_MAJOR, i));
|
||||||
class_simple_destroy(msr_class);
|
class_destroy(msr_class);
|
||||||
out_chrdev:
|
out_chrdev:
|
||||||
unregister_chrdev(MSR_MAJOR, "cpu/msr");
|
unregister_chrdev(MSR_MAJOR, "cpu/msr");
|
||||||
out:
|
out:
|
||||||
@ -332,8 +332,8 @@ static void __exit msr_exit(void)
|
|||||||
{
|
{
|
||||||
int cpu = 0;
|
int cpu = 0;
|
||||||
for_each_online_cpu(cpu)
|
for_each_online_cpu(cpu)
|
||||||
class_simple_device_remove(MKDEV(MSR_MAJOR, cpu));
|
class_device_destroy(msr_class, MKDEV(MSR_MAJOR, cpu));
|
||||||
class_simple_destroy(msr_class);
|
class_destroy(msr_class);
|
||||||
unregister_chrdev(MSR_MAJOR, "cpu/msr");
|
unregister_chrdev(MSR_MAJOR, "cpu/msr");
|
||||||
unregister_cpu_notifier(&msr_class_cpu_notifier);
|
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