1
0
Fork 0

Merge linux-2.6 with linux-acpi-2.6

hifive-unleashed-5.1
Len Brown 2005-09-08 01:45:47 -04:00
commit 64e47488c9
1968 changed files with 58374 additions and 48994 deletions

View File

@ -96,7 +96,7 @@
<chapter id="pubfunctions">
<title>Public Functions Provided</title>
!Earch/i386/kernel/mca.c
!Edrivers/mca/mca-legacy.c
</chapter>
<chapter id="dmafunctions">

View File

@ -605,12 +605,13 @@ is in the ipmi_poweroff module. When the system requests a powerdown,
it will send the proper IPMI commands to do this. This is supported on
several platforms.
There is a module parameter named "poweroff_control" that may either be zero
(do a power down) or 2 (do a power cycle, power the system off, then power
it on in a few seconds). Setting ipmi_poweroff.poweroff_control=x will do
the same thing on the kernel command line. The parameter is also available
via the proc filesystem in /proc/ipmi/poweroff_control. Note that if the
system does not support power cycling, it will always to the power off.
There is a module parameter named "poweroff_powercycle" that may
either be zero (do a power down) or non-zero (do a power cycle, power
the system off, then power it on in a few seconds). Setting
ipmi_poweroff.poweroff_control=x will do the same thing on the kernel
command line. The parameter is also available via the proc filesystem
in /proc/sys/dev/ipmi/poweroff_powercycle. Note that if the system
does not support power cycling, it will always do the power off.
Note that if you have ACPI enabled, the system will prefer using ACPI to
power off.

View File

@ -0,0 +1,112 @@
Using RCU to Protect Dynamic NMI Handlers
Although RCU is usually used to protect read-mostly data structures,
it is possible to use RCU to provide dynamic non-maskable interrupt
handlers, as well as dynamic irq handlers. This document describes
how to do this, drawing loosely from Zwane Mwaikambo's NMI-timer
work in "arch/i386/oprofile/nmi_timer_int.c" and in
"arch/i386/kernel/traps.c".
The relevant pieces of code are listed below, each followed by a
brief explanation.
static int dummy_nmi_callback(struct pt_regs *regs, int cpu)
{
return 0;
}
The dummy_nmi_callback() function is a "dummy" NMI handler that does
nothing, but returns zero, thus saying that it did nothing, allowing
the NMI handler to take the default machine-specific action.
static nmi_callback_t nmi_callback = dummy_nmi_callback;
This nmi_callback variable is a global function pointer to the current
NMI handler.
fastcall void do_nmi(struct pt_regs * regs, long error_code)
{
int cpu;
nmi_enter();
cpu = smp_processor_id();
++nmi_count(cpu);
if (!rcu_dereference(nmi_callback)(regs, cpu))
default_do_nmi(regs);
nmi_exit();
}
The do_nmi() function processes each NMI. It first disables preemption
in the same way that a hardware irq would, then increments the per-CPU
count of NMIs. It then invokes the NMI handler stored in the nmi_callback
function pointer. If this handler returns zero, do_nmi() invokes the
default_do_nmi() function to handle a machine-specific NMI. Finally,
preemption is restored.
Strictly speaking, rcu_dereference() is not needed, since this code runs
only on i386, which does not need rcu_dereference() anyway. However,
it is a good documentation aid, particularly for anyone attempting to
do something similar on Alpha.
Quick Quiz: Why might the rcu_dereference() be necessary on Alpha,
given that the code referenced by the pointer is read-only?
Back to the discussion of NMI and RCU...
void set_nmi_callback(nmi_callback_t callback)
{
rcu_assign_pointer(nmi_callback, callback);
}
The set_nmi_callback() function registers an NMI handler. Note that any
data that is to be used by the callback must be initialized up -before-
the call to set_nmi_callback(). On architectures that do not order
writes, the rcu_assign_pointer() ensures that the NMI handler sees the
initialized values.
void unset_nmi_callback(void)
{
rcu_assign_pointer(nmi_callback, dummy_nmi_callback);
}
This function unregisters an NMI handler, restoring the original
dummy_nmi_handler(). However, there may well be an NMI handler
currently executing on some other CPU. We therefore cannot free
up any data structures used by the old NMI handler until execution
of it completes on all other CPUs.
One way to accomplish this is via synchronize_sched(), perhaps as
follows:
unset_nmi_callback();
synchronize_sched();
kfree(my_nmi_data);
This works because synchronize_sched() blocks until all CPUs complete
any preemption-disabled segments of code that they were executing.
Since NMI handlers disable preemption, synchronize_sched() is guaranteed
not to return until all ongoing NMI handlers exit. It is therefore safe
to free up the handler's data as soon as synchronize_sched() returns.
Answer to Quick Quiz
Why might the rcu_dereference() be necessary on Alpha, given
that the code referenced by the pointer is read-only?
Answer: The caller to set_nmi_callback() might well have
initialized some data that is to be used by the
new NMI handler. In this case, the rcu_dereference()
would be needed, because otherwise a CPU that received
an NMI just after the new handler was set might see
the pointer to the new NMI handler, but the old
pre-initialized version of the handler's data.
More important, the rcu_dereference() makes it clear
to someone reading the code that the pointer is being
protected by RCU.

View File

@ -68,7 +68,8 @@ it a better device citizen. Further thanks to Joel Katz
Porfiri Claudio <C.Porfiri@nisms.tei.ericsson.se> for patches
to make the driver work with the older CDU-510/515 series, and
Heiko Eissfeldt <heiko@colossus.escape.de> for pointing out that
the verify_area() checks were ignoring the results of said checks.
the verify_area() checks were ignoring the results of said checks
(note: verify_area() has since been replaced by access_ok()).
(Acknowledgments from Ron Jeppesen in the 0.3 release:)
Thanks to Corey Minyard who wrote the original CDU-31A driver on which

View File

@ -60,6 +60,18 @@ all of the cpus in the system. This removes any overhead due to
load balancing code trying to pull tasks outside of the cpu exclusive
cpuset only to be prevented by the tasks' cpus_allowed mask.
A cpuset that is mem_exclusive restricts kernel allocations for
page, buffer and other data commonly shared by the kernel across
multiple users. All cpusets, whether mem_exclusive or not, restrict
allocations of memory for user space. This enables configuring a
system so that several independent jobs can share common kernel
data, such as file system pages, while isolating each jobs user
allocation in its own cpuset. To do this, construct a large
mem_exclusive cpuset to hold all the jobs, and construct child,
non-mem_exclusive cpusets for each individual job. Only a small
amount of typical kernel memory, such as requests from interrupt
handlers, is allowed to be taken outside even a mem_exclusive cpuset.
User level code may create and destroy cpusets by name in the cpuset
virtual file system, manage the attributes and permissions of these
cpusets and which CPUs and Memory Nodes are assigned to each cpuset,

View File

@ -223,6 +223,7 @@ CAST5 algorithm contributors:
TEA/XTEA algorithm contributors:
Aaron Grothe
Michael Ringe
Khazad algorithm contributors:
Aaron Grothe

View File

@ -0,0 +1,91 @@
Overview
The Dell Systems Management Base Driver provides a sysfs interface for
systems management software such as Dell OpenManage to perform system
management interrupts and host control actions (system power cycle or
power off after OS shutdown) on certain Dell systems.
Dell OpenManage requires this driver on the following Dell PowerEdge systems:
300, 1300, 1400, 400SC, 500SC, 1500SC, 1550, 600SC, 1600SC, 650, 1655MC,
700, and 750. Other Dell software such as the open source libsmbios project
is expected to make use of this driver, and it may include the use of this
driver on other Dell systems.
The Dell libsmbios project aims towards providing access to as much BIOS
information as possible. See http://linux.dell.com/libsmbios/main/ for
more information about the libsmbios project.
System Management Interrupt
On some Dell systems, systems management software must access certain
management information via a system management interrupt (SMI). The SMI data
buffer must reside in 32-bit address space, and the physical address of the
buffer is required for the SMI. The driver maintains the memory required for
the SMI and provides a way for the application to generate the SMI.
The driver creates the following sysfs entries for systems management
software to perform these system management interrupts:
/sys/devices/platform/dcdbas/smi_data
/sys/devices/platform/dcdbas/smi_data_buf_phys_addr
/sys/devices/platform/dcdbas/smi_data_buf_size
/sys/devices/platform/dcdbas/smi_request
Systems management software must perform the following steps to execute
a SMI using this driver:
1) Lock smi_data.
2) Write system management command to smi_data.
3) Write "1" to smi_request to generate a calling interface SMI or
"2" to generate a raw SMI.
4) Read system management command response from smi_data.
5) Unlock smi_data.
Host Control Action
Dell OpenManage supports a host control feature that allows the administrator
to perform a power cycle or power off of the system after the OS has finished
shutting down. On some Dell systems, this host control feature requires that
a driver perform a SMI after the OS has finished shutting down.
The driver creates the following sysfs entries for systems management software
to schedule the driver to perform a power cycle or power off host control
action after the system has finished shutting down:
/sys/devices/platform/dcdbas/host_control_action
/sys/devices/platform/dcdbas/host_control_smi_type
/sys/devices/platform/dcdbas/host_control_on_shutdown
Dell OpenManage performs the following steps to execute a power cycle or
power off host control action using this driver:
1) Write host control action to be performed to host_control_action.
2) Write type of SMI that driver needs to perform to host_control_smi_type.
3) Write "1" to host_control_on_shutdown to enable host control action.
4) Initiate OS shutdown.
(Driver will perform host control SMI when it is notified that the OS
has finished shutting down.)
Host Control SMI Type
The following table shows the value to write to host_control_smi_type to
perform a power cycle or power off host control action:
PowerEdge System Host Control SMI Type
---------------- ---------------------
300 HC_SMITYPE_TYPE1
1300 HC_SMITYPE_TYPE1
1400 HC_SMITYPE_TYPE2
500SC HC_SMITYPE_TYPE2
1500SC HC_SMITYPE_TYPE2
1550 HC_SMITYPE_TYPE2
600SC HC_SMITYPE_TYPE2
1600SC HC_SMITYPE_TYPE2
650 HC_SMITYPE_TYPE2
1655MC HC_SMITYPE_TYPE2
700 HC_SMITYPE_TYPE3
750 HC_SMITYPE_TYPE3

View File

@ -0,0 +1,74 @@
Purpose:
Demonstrate the usage of the new open sourced rbu (Remote BIOS Update) driver
for updating BIOS images on Dell servers and desktops.
Scope:
This document discusses the functionality of the rbu driver only.
It does not cover the support needed from aplications to enable the BIOS to
update itself with the image downloaded in to the memory.
Overview:
This driver works with Dell OpenManage or Dell Update Packages for updating
the BIOS on Dell servers (starting from servers sold since 1999), desktops
and notebooks (starting from those sold in 2005).
Please go to http://support.dell.com register and you can find info on
OpenManage and Dell Update packages (DUP).
Dell_RBU driver supports BIOS update using the monilothic image and packetized
image methods. In case of moniolithic the driver allocates a contiguous chunk
of physical pages having the BIOS image. In case of packetized the app
using the driver breaks the image in to packets of fixed sizes and the driver
would place each packet in contiguous physical memory. The driver also
maintains a link list of packets for reading them back.
If the dell_rbu driver is unloaded all the allocated memory is freed.
The rbu driver needs to have an application which will inform the BIOS to
enable the update in the next system reboot.
The user should not unload the rbu driver after downloading the BIOS image
or updating.
The driver load creates the following directories under the /sys file system.
/sys/class/firmware/dell_rbu/loading
/sys/class/firmware/dell_rbu/data
/sys/devices/platform/dell_rbu/image_type
/sys/devices/platform/dell_rbu/data
The driver supports two types of update mechanism; monolithic and packetized.
These update mechanism depends upon the BIOS currently running on the system.
Most of the Dell systems support a monolithic update where the BIOS image is
copied to a single contiguous block of physical memory.
In case of packet mechanism the single memory can be broken in smaller chuks
of contiguous memory and the BIOS image is scattered in these packets.
By default the driver uses monolithic memory for the update type. This can be
changed to contiguous during the driver load time by specifying the load
parameter image_type=packet. This can also be changed later as below
echo packet > /sys/devices/platform/dell_rbu/image_type
Do the steps below to download the BIOS image.
1) echo 1 > /sys/class/firmware/dell_rbu/loading
2) cp bios_image.hdr /sys/class/firmware/dell_rbu/data
3) echo 0 > /sys/class/firmware/dell_rbu/loading
The /sys/class/firmware/dell_rbu/ entries will remain till the following is
done.
echo -1 > /sys/class/firmware/dell_rbu/loading
Until this step is completed the drivr cannot be unloaded.
Also the driver provides /sys/devices/platform/dell_rbu/data readonly file to
read back the image downloaded. This is useful in case of packet update
mechanism where the above steps 1,2,3 will repeated for every packet.
By reading the /sys/devices/platform/dell_rbu/data file all packet data
downloaded can be verified in a single file.
The packets are arranged in this file one after the other in a FIFO order.
NOTE:
This driver requires a patch for firmware_class.c which has the addition
of request_firmware_nowait_nohotplug function to wortk
Also after updating the BIOS image an user mdoe application neeeds to execute
code which message the BIOS update request to the BIOS. So on the next reboot
the BIOS knows about the new image downloaded and it updates it self.
Also don't unload the rbu drive if the image has to be updated.

View File

@ -16,7 +16,7 @@ Enable the following options:
"Device drivers" => "Multimedia devices"
=> "Video For Linux" => "BT848 Video For Linux"
"Device drivers" => "Multimedia devices" => "Digital Video Broadcasting Devices"
=> "DVB for Linux" "DVB Core Support" "Nebula/Pinnacle PCTV/TwinHan PCI Cards"
=> "DVB for Linux" "DVB Core Support" "BT8xx based PCI cards"
3) Loading Modules, described by two approaches
===============================================

View File

@ -7,7 +7,7 @@ To protect itself the kernel has to verify this address.
In older versions of Linux this was done with the
int verify_area(int type, const void * addr, unsigned long size)
function.
function (which has since been replaced by access_ok()).
This function verified that the memory area starting at address
addr and of size size was accessible for the operation specified

View File

@ -51,14 +51,6 @@ Who: Adrian Bunk <bunk@stusta.de>
---------------------------
What: register_ioctl32_conversion() / unregister_ioctl32_conversion()
When: April 2005
Why: Replaced by ->compat_ioctl in file_operations and other method
vecors.
Who: Andi Kleen <ak@muc.de>, Christoph Hellwig <hch@lst.de>
---------------------------
What: RCU API moves to EXPORT_SYMBOL_GPL
When: April 2006
Files: include/linux/rcupdate.h, kernel/rcupdate.c
@ -74,14 +66,6 @@ Who: Paul E. McKenney <paulmck@us.ibm.com>
---------------------------
What: remove verify_area()
When: July 2006
Files: Various uaccess.h headers.
Why: Deprecated and redundant. access_ok() should be used instead.
Who: Jesper Juhl <juhl-lkml@dif.dk>
---------------------------
What: IEEE1394 Audio and Music Data Transmission Protocol driver,
Connection Management Procedures driver
When: November 2005
@ -102,16 +86,6 @@ Who: Jody McIntyre <scjody@steamballoon.com>
---------------------------
What: register_serial/unregister_serial
When: September 2005
Why: This interface does not allow serial ports to be registered against
a struct device, and as such does not allow correct power management
of such ports. 8250-based ports should use serial8250_register_port
and serial8250_unregister_port, or platform devices instead.
Who: Russell King <rmk@arm.linux.org.uk>
---------------------------
What: i2c sysfs name change: in1_ref, vid deprecated in favour of cpu0_vid
When: November 2005
Files: drivers/i2c/chips/adm1025.c, drivers/i2c/chips/adm1026.c

View File

@ -133,6 +133,7 @@ Table 1-1: Process specific entries in /proc
statm Process memory status information
status Process status in human readable form
wchan If CONFIG_KALLSYMS is set, a pre-decoded wchan
smaps Extension based on maps, presenting the rss size for each mapped file
..............................................................................
For example, to get the status information of a process, all you have to do is

View File

@ -0,0 +1,362 @@
relayfs - a high-speed data relay filesystem
============================================
relayfs is a filesystem designed to provide an efficient mechanism for
tools and facilities to relay large and potentially sustained streams
of data from kernel space to user space.
The main abstraction of relayfs is the 'channel'. A channel consists
of a set of per-cpu kernel buffers each represented by a file in the
relayfs filesystem. Kernel clients write into a channel using
efficient write functions which automatically log to the current cpu's
channel buffer. User space applications mmap() the per-cpu files and
retrieve the data as it becomes available.
The format of the data logged into the channel buffers is completely
up to the relayfs client; relayfs does however provide hooks which
allow clients to impose some stucture on the buffer data. Nor does
relayfs implement any form of data filtering - this also is left to
the client. The purpose is to keep relayfs as simple as possible.
This document provides an overview of the relayfs API. The details of
the function parameters are documented along with the functions in the
filesystem code - please see that for details.
Semantics
=========
Each relayfs channel has one buffer per CPU, each buffer has one or
more sub-buffers. Messages are written to the first sub-buffer until
it is too full to contain a new message, in which case it it is
written to the next (if available). Messages are never split across
sub-buffers. At this point, userspace can be notified so it empties
the first sub-buffer, while the kernel continues writing to the next.
When notified that a sub-buffer is full, the kernel knows how many
bytes of it are padding i.e. unused. Userspace can use this knowledge
to copy only valid data.
After copying it, userspace can notify the kernel that a sub-buffer
has been consumed.
relayfs can operate in a mode where it will overwrite data not yet
collected by userspace, and not wait for it to consume it.
relayfs itself does not provide for communication of such data between
userspace and kernel, allowing the kernel side to remain simple and not
impose a single interface on userspace. It does provide a separate
helper though, described below.
klog, relay-app & librelay
==========================
relayfs itself is ready to use, but to make things easier, two
additional systems are provided. klog is a simple wrapper to make
writing formatted text or raw data to a channel simpler, regardless of
whether a channel to write into exists or not, or whether relayfs is
compiled into the kernel or is configured as a module. relay-app is
the kernel counterpart of userspace librelay.c, combined these two
files provide glue to easily stream data to disk, without having to
bother with housekeeping. klog and relay-app can be used together,
with klog providing high-level logging functions to the kernel and
relay-app taking care of kernel-user control and disk-logging chores.
It is possible to use relayfs without relay-app & librelay, but you'll
have to implement communication between userspace and kernel, allowing
both to convey the state of buffers (full, empty, amount of padding).
klog, relay-app and librelay can be found in the relay-apps tarball on
http://relayfs.sourceforge.net
The relayfs user space API
==========================
relayfs implements basic file operations for user space access to
relayfs channel buffer data. Here are the file operations that are
available and some comments regarding their behavior:
open() enables user to open an _existing_ buffer.
mmap() results in channel buffer being mapped into the caller's
memory space. Note that you can't do a partial mmap - you must
map the entire file, which is NRBUF * SUBBUFSIZE.
read() read the contents of a channel buffer. The bytes read are
'consumed' by the reader i.e. they won't be available again
to subsequent reads. If the channel is being used in
no-overwrite mode (the default), it can be read at any time
even if there's an active kernel writer. If the channel is
being used in overwrite mode and there are active channel
writers, results may be unpredictable - users should make
sure that all logging to the channel has ended before using
read() with overwrite mode.
poll() POLLIN/POLLRDNORM/POLLERR supported. User applications are
notified when sub-buffer boundaries are crossed.
close() decrements the channel buffer's refcount. When the refcount
reaches 0 i.e. when no process or kernel client has the buffer
open, the channel buffer is freed.
In order for a user application to make use of relayfs files, the
relayfs filesystem must be mounted. For example,
mount -t relayfs relayfs /mnt/relay
NOTE: relayfs doesn't need to be mounted for kernel clients to create
or use channels - it only needs to be mounted when user space
applications need access to the buffer data.
The relayfs kernel API
======================
Here's a summary of the API relayfs provides to in-kernel clients:
channel management functions:
relay_open(base_filename, parent, subbuf_size, n_subbufs,
callbacks)
relay_close(chan)
relay_flush(chan)
relay_reset(chan)
relayfs_create_dir(name, parent)
relayfs_remove_dir(dentry)
channel management typically called on instigation of userspace:
relay_subbufs_consumed(chan, cpu, subbufs_consumed)
write functions:
relay_write(chan, data, length)
__relay_write(chan, data, length)
relay_reserve(chan, length)
callbacks:
subbuf_start(buf, subbuf, prev_subbuf, prev_padding)
buf_mapped(buf, filp)
buf_unmapped(buf, filp)
helper functions:
relay_buf_full(buf)
subbuf_start_reserve(buf, length)
Creating a channel
------------------
relay_open() is used to create a channel, along with its per-cpu
channel buffers. Each channel buffer will have an associated file
created for it in the relayfs filesystem, which can be opened and
mmapped from user space if desired. The files are named
basename0...basenameN-1 where N is the number of online cpus, and by
default will be created in the root of the filesystem. If you want a
directory structure to contain your relayfs files, you can create it
with relayfs_create_dir() and pass the parent directory to
relay_open(). Clients are responsible for cleaning up any directory
structure they create when the channel is closed - use
relayfs_remove_dir() for that.
The total size of each per-cpu buffer is calculated by multiplying the
number of sub-buffers by the sub-buffer size passed into relay_open().
The idea behind sub-buffers is that they're basically an extension of
double-buffering to N buffers, and they also allow applications to
easily implement random-access-on-buffer-boundary schemes, which can
be important for some high-volume applications. The number and size
of sub-buffers is completely dependent on the application and even for
the same application, different conditions will warrant different
values for these parameters at different times. Typically, the right
values to use are best decided after some experimentation; in general,
though, it's safe to assume that having only 1 sub-buffer is a bad
idea - you're guaranteed to either overwrite data or lose events
depending on the channel mode being used.
Channel 'modes'
---------------
relayfs channels can be used in either of two modes - 'overwrite' or
'no-overwrite'. The mode is entirely determined by the implementation
of the subbuf_start() callback, as described below. In 'overwrite'
mode, also known as 'flight recorder' mode, writes continuously cycle
around the buffer and will never fail, but will unconditionally
overwrite old data regardless of whether it's actually been consumed.
In no-overwrite mode, writes will fail i.e. data will be lost, if the
number of unconsumed sub-buffers equals the total number of
sub-buffers in the channel. It should be clear that if there is no
consumer or if the consumer can't consume sub-buffers fast enought,
data will be lost in either case; the only difference is whether data
is lost from the beginning or the end of a buffer.
As explained above, a relayfs channel is made of up one or more
per-cpu channel buffers, each implemented as a circular buffer
subdivided into one or more sub-buffers. Messages are written into
the current sub-buffer of the channel's current per-cpu buffer via the
write functions described below. Whenever a message can't fit into
the current sub-buffer, because there's no room left for it, the
client is notified via the subbuf_start() callback that a switch to a
new sub-buffer is about to occur. The client uses this callback to 1)
initialize the next sub-buffer if appropriate 2) finalize the previous
sub-buffer if appropriate and 3) return a boolean value indicating
whether or not to actually go ahead with the sub-buffer switch.
To implement 'no-overwrite' mode, the userspace client would provide
an implementation of the subbuf_start() callback something like the
following:
static int subbuf_start(struct rchan_buf *buf,
void *subbuf,
void *prev_subbuf,
unsigned int prev_padding)
{
if (prev_subbuf)
*((unsigned *)prev_subbuf) = prev_padding;
if (relay_buf_full(buf))
return 0;
subbuf_start_reserve(buf, sizeof(unsigned int));
return 1;
}
If the current buffer is full i.e. all sub-buffers remain unconsumed,
the callback returns 0 to indicate that the buffer switch should not
occur yet i.e. until the consumer has had a chance to read the current
set of ready sub-buffers. For the relay_buf_full() function to make
sense, the consumer is reponsible for notifying relayfs when
sub-buffers have been consumed via relay_subbufs_consumed(). Any
subsequent attempts to write into the buffer will again invoke the
subbuf_start() callback with the same parameters; only when the
consumer has consumed one or more of the ready sub-buffers will
relay_buf_full() return 0, in which case the buffer switch can
continue.
The implementation of the subbuf_start() callback for 'overwrite' mode
would be very similar:
static int subbuf_start(struct rchan_buf *buf,
void *subbuf,
void *prev_subbuf,
unsigned int prev_padding)
{
if (prev_subbuf)
*((unsigned *)prev_subbuf) = prev_padding;
subbuf_start_reserve(buf, sizeof(unsigned int));
return 1;
}
In this case, the relay_buf_full() check is meaningless and the
callback always returns 1, causing the buffer switch to occur
unconditionally. It's also meaningless for the client to use the
relay_subbufs_consumed() function in this mode, as it's never
consulted.
The default subbuf_start() implementation, used if the client doesn't
define any callbacks, or doesn't define the subbuf_start() callback,
implements the simplest possible 'no-overwrite' mode i.e. it does
nothing but return 0.
Header information can be reserved at the beginning of each sub-buffer
by calling the subbuf_start_reserve() helper function from within the
subbuf_start() callback. This reserved area can be used to store
whatever information the client wants. In the example above, room is
reserved in each sub-buffer to store the padding count for that
sub-buffer. This is filled in for the previous sub-buffer in the
subbuf_start() implementation; the padding value for the previous
sub-buffer is passed into the subbuf_start() callback along with a
pointer to the previous sub-buffer, since the padding value isn't
known until a sub-buffer is filled. The subbuf_start() callback is
also called for the first sub-buffer when the channel is opened, to
give the client a chance to reserve space in it. In this case the
previous sub-buffer pointer passed into the callback will be NULL, so
the client should check the value of the prev_subbuf pointer before
writing into the previous sub-buffer.
Writing to a channel
--------------------
kernel clients write data into the current cpu's channel buffer using
relay_write() or __relay_write(). relay_write() is the main logging
function - it uses local_irqsave() to protect the buffer and should be
used if you might be logging from interrupt context. If you know
you'll never be logging from interrupt context, you can use
__relay_write(), which only disables preemption. These functions
don't return a value, so you can't determine whether or not they
failed - the assumption is that you wouldn't want to check a return
value in the fast logging path anyway, and that they'll always succeed
unless the buffer is full and no-overwrite mode is being used, in
which case you can detect a failed write in the subbuf_start()
callback by calling the relay_buf_full() helper function.
relay_reserve() is used to reserve a slot in a channel buffer which
can be written to later. This would typically be used in applications
that need to write directly into a channel buffer without having to
stage data in a temporary buffer beforehand. Because the actual write
may not happen immediately after the slot is reserved, applications
using relay_reserve() can keep a count of the number of bytes actually
written, either in space reserved in the sub-buffers themselves or as
a separate array. See the 'reserve' example in the relay-apps tarball
at http://relayfs.sourceforge.net for an example of how this can be
done. Because the write is under control of the client and is
separated from the reserve, relay_reserve() doesn't protect the buffer
at all - it's up to the client to provide the appropriate
synchronization when using relay_reserve().
Closing a channel
-----------------
The client calls relay_close() when it's finished using the channel.
The channel and its associated buffers are destroyed when there are no
longer any references to any of the channel buffers. relay_flush()
forces a sub-buffer switch on all the channel buffers, and can be used
to finalize and process the last sub-buffers before the channel is
closed.
Misc
----
Some applications may want to keep a channel around and re-use it
rather than open and close a new channel for each use. relay_reset()
can be used for this purpose - it resets a channel to its initial
state without reallocating channel buffer memory or destroying
existing mappings. It should however only be called when it's safe to
do so i.e. when the channel isn't currently being written to.
Finally, there are a couple of utility callbacks that can be used for
different purposes. buf_mapped() is called whenever a channel buffer
is mmapped from user space and buf_unmapped() is called when it's
unmapped. The client can use this notification to trigger actions
within the kernel application, such as enabling/disabling logging to
the channel.
Resources
=========
For news, example code, mailing list, etc. see the relayfs homepage:
http://relayfs.sourceforge.net
Credits
=======
The ideas and specs for relayfs came about as a result of discussions
on tracing involving the following:
Michel Dagenais <michel.dagenais@polymtl.ca>
Richard Moore <richardj_moore@uk.ibm.com>
Bob Wisniewski <bob@watson.ibm.com>
Karim Yaghmour <karim@opersys.com>
Tom Zanussi <zanussi@us.ibm.com>
Also thanks to Hubertus Franke for a lot of useful suggestions and bug
reports.

View File

@ -90,7 +90,7 @@ void device_remove_file(struct device *, struct device_attribute *);
It also defines this helper for defining device attributes:
#define DEVICE_ATTR(_name,_mode,_show,_store) \
#define DEVICE_ATTR(_name, _mode, _show, _store) \
struct device_attribute dev_attr_##_name = { \
.attr = {.name = __stringify(_name) , .mode = _mode }, \
.show = _show, \
@ -99,14 +99,14 @@ struct device_attribute dev_attr_##_name = { \
For example, declaring
static DEVICE_ATTR(foo,0644,show_foo,store_foo);
static DEVICE_ATTR(foo, S_IWUSR | S_IRUGO, show_foo, store_foo);
is equivalent to doing:
static struct device_attribute dev_attr_foo = {
.attr = {
.name = "foo",
.mode = 0644,
.mode = S_IWUSR | S_IRUGO,
},
.show = show_foo,
.store = store_foo,
@ -121,8 +121,8 @@ set of sysfs operations for forwarding read and write calls to the
show and store methods of the attribute owners.
struct sysfs_ops {
ssize_t (*show)(struct kobject *, struct attribute *,char *);
ssize_t (*store)(struct kobject *,struct attribute *,const char *);
ssize_t (*show)(struct kobject *, struct attribute *, char *);
ssize_t (*store)(struct kobject *, struct attribute *, const char *);
};
[ Subsystems should have already defined a struct kobj_type as a
@ -137,7 +137,7 @@ calls the associated methods.
To illustrate:
#define to_dev_attr(_attr) container_of(_attr,struct device_attribute,attr)
#define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr)
#define to_dev(d) container_of(d, struct device, kobj)
static ssize_t
@ -148,7 +148,7 @@ dev_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
ssize_t ret = 0;
if (dev_attr->show)
ret = dev_attr->show(dev,buf);
ret = dev_attr->show(dev, buf);
return ret;
}
@ -216,16 +216,16 @@ A very simple (and naive) implementation of a device attribute is:
static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf)
{
return sprintf(buf,"%s\n",dev->name);
return snprintf(buf, PAGE_SIZE, "%s\n", dev->name);
}
static ssize_t store_name(struct device * dev, const char * buf)
{
sscanf(buf,"%20s",dev->name);
return strlen(buf);
sscanf(buf, "%20s", dev->name);
return strnlen(buf, PAGE_SIZE);
}
static DEVICE_ATTR(name,S_IRUGO,show_name,store_name);
static DEVICE_ATTR(name, S_IRUGO, show_name, store_name);
(Note that the real implementation doesn't allow userspace to set the
@ -290,7 +290,7 @@ struct device_attribute {
Declaring:
DEVICE_ATTR(_name,_str,_mode,_show,_store);
DEVICE_ATTR(_name, _str, _mode, _show, _store);
Creation/Removal:
@ -310,7 +310,7 @@ struct bus_attribute {
Declaring:
BUS_ATTR(_name,_mode,_show,_store)
BUS_ATTR(_name, _mode, _show, _store)
Creation/Removal:
@ -331,7 +331,7 @@ struct driver_attribute {
Declaring:
DRIVER_ATTR(_name,_mode,_show,_store)
DRIVER_ATTR(_name, _mode, _show, _store)
Creation/Removal:

View File

@ -2,16 +2,11 @@ Kernel driver lm78
==================
Supported chips:
* National Semiconductor LM78
* National Semiconductor LM78 / LM78-J
Prefix: 'lm78'
Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports)
Datasheet: Publicly available at the National Semiconductor website
http://www.national.com/
* National Semiconductor LM78-J
Prefix: 'lm78-j'
Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports)
Datasheet: Publicly available at the National Semiconductor website
http://www.national.com/
* National Semiconductor LM79
Prefix: 'lm79'
Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports)

View File

@ -0,0 +1,174 @@
Kernel driver w83792d
=====================
Supported chips:
* Winbond W83792D
Prefix: 'w83792d'
Addresses scanned: I2C 0x2c - 0x2f
Datasheet: http://www.winbond.com.tw/E-WINBONDHTM/partner/PDFresult.asp?Pname=1035
Author: Chunhao Huang
Contact: DZShen <DZShen@Winbond.com.tw>
Module Parameters
-----------------
* init int
(default 1)
Use 'init=0' to bypass initializing the chip.
Try this if your computer crashes when you load the module.
* force_subclients=bus,caddr,saddr,saddr
This is used to force the i2c addresses for subclients of
a certain chip. Example usage is `force_subclients=0,0x2f,0x4a,0x4b'
to force the subclients of chip 0x2f on bus 0 to i2c addresses
0x4a and 0x4b.
Description
-----------
This driver implements support for the Winbond W83792AD/D.
Detection of the chip can sometimes be foiled because it can be in an
internal state that allows no clean access (Bank with ID register is not
currently selected). If you know the address of the chip, use a 'force'
parameter; this will put it into a more well-behaved state first.
The driver implements three temperature sensors, seven fan rotation speed
sensors, nine voltage sensors, and two automatic fan regulation
strategies called: Smart Fan I (Thermal Cruise mode) and Smart Fan II.
Automatic fan control mode is possible only for fan1-fan3. Fan4-fan7 can run
synchronized with selected fan (fan1-fan3). This functionality and manual PWM
control for fan4-fan7 is not yet implemented.
Temperatures are measured in degrees Celsius and measurement resolution is 1
degC for temp1 and 0.5 degC for temp2 and temp3. An alarm is triggered when
the temperature gets higher than the Overtemperature Shutdown value; it stays
on until the temperature falls below the Hysteresis value.
Fan rotation speeds are reported in RPM (rotations per minute). An alarm is
triggered if the rotation speed has dropped below a programmable limit. Fan
readings can be divided by a programmable divider (1, 2, 4, 8, 16, 32, 64 or
128) to give the readings more range or accuracy.
Voltage sensors (also known as IN sensors) report their values in millivolts.
An alarm is triggered if the voltage has crossed a programmable minimum
or maximum limit.
Alarms are provided as output from "realtime status register". Following bits
are defined:
bit - alarm on:
0 - in0
1 - in1
2 - temp1
3 - temp2
4 - temp3
5 - fan1
6 - fan2
7 - fan3
8 - in2
9 - in3
10 - in4
11 - in5
12 - in6
13 - VID change
14 - chassis
15 - fan7
16 - tart1
17 - tart2
18 - tart3
19 - in7
20 - in8
21 - fan4
22 - fan5
23 - fan6
Tart will be asserted while target temperature cannot be achieved after 3 minutes
of full speed rotation of corresponding fan.
In addition to the alarms described above, there is a CHAS alarm on the chips
which triggers if your computer case is open (This one is latched, contrary
to realtime alarms).
The chips only update values each 3 seconds; reading them more often will
do no harm, but will return 'old' values.
W83792D PROBLEMS
----------------
Known problems:
- This driver is only for Winbond W83792D C version device, there
are also some motherboards with B version W83792D device. The
calculation method to in6-in7(measured value, limits) is a little
different between C and B version. C or B version can be identified
by CR[0x49h].
- The function of vid and vrm has not been finished, because I'm NOT
very familiar with them. Adding support is welcome.
  - The function of chassis open detection needs more tests.
- If you have ASUS server board and chip was not found: Then you will
need to upgrade to latest (or beta) BIOS. If it does not help please
contact us.
Fan control
-----------
Manual mode
-----------
Works as expected. You just need to specify desired PWM/DC value (fan speed)
in appropriate pwm# file.
Thermal cruise
--------------
In this mode, W83792D provides the Smart Fan system to automatically control
fan speed to keep the temperatures of CPU and the system within specific
range. At first a wanted temperature and interval must be set. This is done
via thermal_cruise# file. The tolerance# file serves to create T +- tolerance
interval. The fan speed will be lowered as long as the current temperature
remains below the thermal_cruise# +- tolerance# value. Once the temperature
exceeds the high limit (T+tolerance), the fan will be turned on with a
specific speed set by pwm# and automatically controlled its PWM duty cycle
with the temperature varying. Three conditions may occur:
(1) If the temperature still exceeds the high limit, PWM duty
cycle will increase slowly.
(2) If the temperature goes below the high limit, but still above the low
limit (T-tolerance), the fan speed will be fixed at the current speed because
the temperature is in the target range.
(3) If the temperature goes below the low limit, PWM duty cycle will decrease
slowly to 0 or a preset stop value until the temperature exceeds the low
limit. (The preset stop value handling is not yet implemented in driver)
Smart Fan II
------------
W83792D also provides a special mode for fan. Four temperature points are
available. When related temperature sensors detects the temperature in preset
temperature region (sf2_point@_fan# +- tolerance#) it will cause fans to run
on programmed value from sf2_level@_fan#. You need to set four temperatures
for each fan.
/sys files
----------
pwm[1-3] - this file stores PWM duty cycle or DC value (fan speed) in range:
0 (stop) to 255 (full)
pwm[1-3]_enable - this file controls mode of fan/temperature control:
* 0 Disabled
* 1 Manual mode
* 2 Smart Fan II
* 3 Thermal Cruise
pwm[1-3]_mode - Select PWM of DC mode
* 0 DC
* 1 PWM
thermal_cruise[1-3] - Selects the desired temperature for cruise (degC)
tolerance[1-3] - Value in degrees of Celsius (degC) for +- T
sf2_point[1-4]_fan[1-3] - four temperature points for each fan for Smart Fan II
sf2_level[1-3]_fan[1-3] - three PWM/DC levels for each fan for Smart Fan II

View File

@ -4,22 +4,13 @@ Kernel driver max6875
Supported chips:
* Maxim MAX6874, MAX6875
Prefix: 'max6875'
Addresses scanned: 0x50, 0x52
Addresses scanned: None (see below)
Datasheet:
http://pdfserv.maxim-ic.com/en/ds/MAX6874-MAX6875.pdf
Author: Ben Gardner <bgardner@wabtec.com>
Module Parameters
-----------------
* allow_write int
Set to non-zero to enable write permission:
*0: Read only
1: Read and write
Description
-----------
@ -33,34 +24,85 @@ registers.
The Maxim MAX6874 is a similar, mostly compatible device, with more intputs
and outputs:
vin gpi vout
MAX6874 6 4 8
MAX6875 4 3 5
MAX6874 chips can have four different addresses (as opposed to only two for
the MAX6875). The additional addresses (0x54 and 0x56) are not probed by
this driver by default, but the probe module parameter can be used if
needed.
See the datasheet for details on how to program the EEPROM.
See the datasheet for more information.
Sysfs entries
-------------
eeprom_user - 512 bytes of user-defined EEPROM space. Only writable if
allow_write was set and register 0x43 is 0.
eeprom_config - 70 bytes of config EEPROM. Note that changes will not get
loaded into register space until a power cycle or device reset.
reg_config - 70 bytes of register space. Any changes take affect immediately.
eeprom - 512 bytes of user-defined EEPROM space.
General Remarks
---------------
A typical application will require that the EEPROMs be programmed once and
never altered afterwards.
Valid addresses for the MAX6875 are 0x50 and 0x52.
Valid addresses for the MAX6874 are 0x50, 0x52, 0x54 and 0x56.
The driver does not probe any address, so you must force the address.
Example:
$ modprobe max6875 force=0,0x50
The MAX6874/MAX6875 ignores address bit 0, so this driver attaches to multiple
addresses. For example, for address 0x50, it also reserves 0x51.
The even-address instance is called 'max6875', the odd one is 'max6875 subclient'.
Programming the chip using i2c-dev
----------------------------------
Use the i2c-dev interface to access and program the chips.
Reads and writes are performed differently depending on the address range.
The configuration registers are at addresses 0x00 - 0x45.
Use i2c_smbus_write_byte_data() to write a register and
i2c_smbus_read_byte_data() to read a register.
The command is the register number.
Examples:
To write a 1 to register 0x45:
i2c_smbus_write_byte_data(fd, 0x45, 1);
To read register 0x45:
value = i2c_smbus_read_byte_data(fd, 0x45);
The configuration EEPROM is at addresses 0x8000 - 0x8045.
The user EEPROM is at addresses 0x8100 - 0x82ff.
Use i2c_smbus_write_word_data() to write a byte to EEPROM.
The command is the upper byte of the address: 0x80, 0x81, or 0x82.
The data word is the lower part of the address or'd with data << 8.
cmd = address >> 8;
val = (address & 0xff) | (data << 8);
Example:
To write 0x5a to address 0x8003:
i2c_smbus_write_word_data(fd, 0x80, 0x5a03);
Reading data from the EEPROM is a little more complicated.
Use i2c_smbus_write_byte_data() to set the read address and then
i2c_smbus_read_byte() or i2c_smbus_read_i2c_block_data() to read the data.
Example:
To read data starting at offset 0x8100, first set the address:
i2c_smbus_write_byte_data(fd, 0x81, 0x00);
And then read the data
value = i2c_smbus_read_byte(fd);
or
count = i2c_smbus_read_i2c_block_data(fd, 0x84, buffer);
The block read should read 16 bytes.
0x84 is the block read command.
See the datasheet for more details.

View File

@ -115,7 +115,7 @@ CHECKING THROUGH /DEV
If you try to access an adapter from a userspace program, you will have
to use the /dev interface. You will still have to check whether the
functionality you need is supported, of course. This is done using
the I2C_FUNCS ioctl. An example, adapted from the lm_sensors i2c_detect
the I2C_FUNCS ioctl. An example, adapted from the lm_sensors i2cdetect
program, is below:
int file;

View File

@ -1,4 +1,4 @@
Revision 4, 2004-03-30
Revision 5, 2005-07-29
Jean Delvare <khali@linux-fr.org>
Greg KH <greg@kroah.com>
@ -17,20 +17,22 @@ yours for best results.
Technical changes:
* [Includes] Get rid of "version.h". Replace <linux/i2c-proc.h> with
<linux/i2c-sensor.h>. Includes typically look like that:
* [Includes] Get rid of "version.h" and <linux/i2c-proc.h>.
Includes typically look like that:
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/i2c-sensor.h>
#include <linux/i2c-vid.h> /* if you need VRM support */
#include <linux/hwmon.h> /* for hardware monitoring drivers */
#include <linux/hwmon-sysfs.h>
#include <linux/hwmon-vid.h> /* if you need VRM support */
#include <asm/io.h> /* if you have I/O operations */
Please respect this inclusion order. Some extra headers may be
required for a given driver (e.g. "lm75.h").
* [Addresses] SENSORS_I2C_END becomes I2C_CLIENT_END, SENSORS_ISA_END
becomes I2C_CLIENT_ISA_END.
* [Addresses] SENSORS_I2C_END becomes I2C_CLIENT_END, ISA addresses
are no more handled by the i2c core.
SENSORS_INSMOD_<n> becomes I2C_CLIENT_INSMOD_<n>.
* [Client data] Get rid of sysctl_id. Try using standard names for
register values (for example, temp_os becomes temp_max). You're
@ -66,13 +68,15 @@ Technical changes:
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
ISA-only drivers of course don't need this.
Call i2c_probe() instead of i2c_detect().
* [Detect] As mentioned earlier, the flags parameter is gone.
The type_name and client_name strings are replaced by a single
name string, which will be filled with a lowercase, short string
(typically the driver name, e.g. "lm75").
In i2c-only drivers, drop the i2c_is_isa_adapter check, it's
useless.
useless. Same for isa-only drivers, as the test would always be
true. Only hybrid drivers (which are quite rare) still need it.
The errorN labels are reduced to the number needed. If that number
is 2 (i2c-only drivers), it is advised that the labels are named
exit and exit_free. For i2c+isa drivers, labels should be named
@ -86,6 +90,8 @@ Technical changes:
device_create_file. Move the driver initialization before any
sysfs file creation.
Drop client->id.
Drop any 24RF08 corruption prevention you find, as this is now done
at the i2c-core level, and doing it twice voids it.
* [Init] Limits must not be set by the driver (can be done later in
user-space). Chip should not be reset default (although a module
@ -93,7 +99,8 @@ Technical changes:
limited to the strictly necessary steps.
* [Detach] Get rid of data, remove the call to
i2c_deregister_entry.
i2c_deregister_entry. Do not log an error message if
i2c_detach_client fails, as i2c-core will now do it for you.
* [Update] Don't access client->data directly, use
i2c_get_clientdata(client) instead.

View File

@ -148,15 +148,15 @@ are defined in i2c.h to help you support them, as well as a generic
detection algorithm.
You do not have to use this parameter interface; but don't try to use
function i2c_probe() (or i2c_detect()) if you don't.
function i2c_probe() if you don't.
NOTE: If you want to write a `sensors' driver, the interface is slightly
different! See below.
Probing classes (i2c)
---------------------
Probing classes
---------------
All parameters are given as lists of unsigned 16-bit integers. Lists are
terminated by I2C_CLIENT_END.
@ -171,12 +171,18 @@ The following lists are used internally:
ignore: insmod parameter.
A list of pairs. The first value is a bus number (-1 for any I2C bus),
the second is the I2C address. These addresses are never probed.
This parameter overrules 'normal' and 'probe', but not the 'force' lists.
This parameter overrules the 'normal_i2c' list only.
force: insmod parameter.
A list of pairs. The first value is a bus number (-1 for any I2C bus),
the second is the I2C address. A device is blindly assumed to be on
the given address, no probing is done.
Additionally, kind-specific force lists may optionally be defined if
the driver supports several chip kinds. They are grouped in a
NULL-terminated list of pointers named forces, those first element if the
generic force list mentioned above. Each additional list correspond to an
insmod parameter of the form force_<kind>.
Fortunately, as a module writer, you just have to define the `normal_i2c'
parameter. The complete declaration could look like this:
@ -186,66 +192,17 @@ parameter. The complete declaration could look like this:
/* Magic definition of all other variables and things */
I2C_CLIENT_INSMOD;
/* Or, if your driver supports, say, 2 kind of devices: */
I2C_CLIENT_INSMOD_2(foo, bar);
If you use the multi-kind form, an enum will be defined for you:
enum chips { any_chip, foo, bar, ... }
You can then (and certainly should) use it in the driver code.
Note that you *have* to call the defined variable `normal_i2c',
without any prefix!
Probing classes (sensors)
-------------------------
If you write a `sensors' driver, you use a slightly different interface.
As well as I2C addresses, we have to cope with ISA addresses. Also, we
use a enum of chip types. Don't forget to include `sensors.h'.
The following lists are used internally. They are all lists of integers.
normal_i2c: filled in by the module writer. Terminated by SENSORS_I2C_END.
A list of I2C addresses which should normally be examined.
normal_isa: filled in by the module writer. Terminated by SENSORS_ISA_END.
A list of ISA addresses which should normally be examined.
probe: insmod parameter. Initialize this list with SENSORS_I2C_END values.
A list of pairs. The first value is a bus number (SENSORS_ISA_BUS for
the ISA bus, -1 for any I2C bus), the second is the address. These
addresses are also probed, as if they were in the 'normal' list.
ignore: insmod parameter. Initialize this list with SENSORS_I2C_END values.
A list of pairs. The first value is a bus number (SENSORS_ISA_BUS for
the ISA bus, -1 for any I2C bus), the second is the I2C address. These
addresses are never probed. This parameter overrules 'normal' and
'probe', but not the 'force' lists.
Also used is a list of pointers to sensors_force_data structures:
force_data: insmod parameters. A list, ending with an element of which
the force field is NULL.
Each element contains the type of chip and a list of pairs.
The first value is a bus number (SENSORS_ISA_BUS for the ISA bus,
-1 for any I2C bus), the second is the address.
These are automatically translated to insmod variables of the form
force_foo.
So we have a generic insmod variabled `force', and chip-specific variables
`force_CHIPNAME'.
Fortunately, as a module writer, you just have to define the `normal_i2c'
and `normal_isa' parameters, and define what chip names are used.
The complete declaration could look like this:
/* Scan i2c addresses 0x37, and 0x48 to 0x4f */
static unsigned short normal_i2c[] = { 0x37, 0x48, 0x49, 0x4a, 0x4b, 0x4c,
0x4d, 0x4e, 0x4f, I2C_CLIENT_END };
/* Scan ISA address 0x290 */
static unsigned int normal_isa[] = {0x0290,SENSORS_ISA_END};
/* Define chips foo and bar, as well as all module parameters and things */
SENSORS_INSMOD_2(foo,bar);
If you have one chip, you use macro SENSORS_INSMOD_1(chip), if you have 2
you use macro SENSORS_INSMOD_2(chip1,chip2), etc. If you do not want to
bother with chip types, you can use SENSORS_INSMOD_0.
A enum is automatically defined as follows:
enum chips { any_chip, chip1, chip2, ... }
Attaching to an adapter
-----------------------
@ -264,17 +221,10 @@ detected at a specific address, another callback is called.
return i2c_probe(adapter,&addr_data,&foo_detect_client);
}
For `sensors' drivers, use the i2c_detect function instead:
int foo_attach_adapter(struct i2c_adapter *adapter)
{
return i2c_detect(adapter,&addr_data,&foo_detect_client);
}
Remember, structure `addr_data' is defined by the macros explained above,
so you do not have to define it yourself.
The i2c_probe or i2c_detect function will call the foo_detect_client
The i2c_probe function will call the foo_detect_client
function only for those i2c addresses that actually have a device on
them (unless a `force' parameter was used). In addition, addresses that
are already in use (by some other registered client) are skipped.
@ -283,19 +233,18 @@ are already in use (by some other registered client) are skipped.
The detect client function
--------------------------
The detect client function is called by i2c_probe or i2c_detect.
The `kind' parameter contains 0 if this call is due to a `force'
parameter, and -1 otherwise (for i2c_detect, it contains 0 if
this call is due to the generic `force' parameter, and the chip type
number if it is due to a specific `force' parameter).
The detect client function is called by i2c_probe. The `kind' parameter
contains -1 for a probed detection, 0 for a forced detection, or a positive
number for a forced detection with a chip type forced.
Below, some things are only needed if this is a `sensors' driver. Those
parts are between /* SENSORS ONLY START */ and /* SENSORS ONLY END */
markers.
This function should only return an error (any value != 0) if there is
some reason why no more detection should be done anymore. If the
detection just fails for this address, return 0.
Returning an error different from -ENODEV in a detect function will cause
the detection to stop: other addresses and adapters won't be scanned.
This should only be done on fatal or internal errors, such as a memory
shortage or i2c_attach_client failing.
For now, you can ignore the `flags' parameter. It is there for future use.
@ -320,11 +269,10 @@ For now, you can ignore the `flags' parameter. It is there for future use.
const char *type_name = "";
int is_isa = i2c_is_isa_adapter(adapter);
if (is_isa) {
/* Do this only if the chip can additionally be found on the ISA bus
(hybrid chip). */
/* If this client can't be on the ISA bus at all, we can stop now
(call `goto ERROR0'). But for kicks, we will assume it is all
right. */
if (is_isa) {
/* Discard immediately if this ISA range is already used */
if (check_region(address,FOO_EXTENT))
@ -495,15 +443,13 @@ much simpler than the attachment code, fortunately!
/* SENSORS ONLY END */
/* Try to detach the client from i2c space */
if ((err = i2c_detach_client(client))) {
printk("foo.o: Client deregistration failed, client not detached.\n");
if ((err = i2c_detach_client(client)))
return err;
}
/* SENSORS ONLY START */
/* HYBRID SENSORS CHIP ONLY START */
if i2c_is_isa_client(client)
release_region(client->addr,LM78_EXTENT);
/* SENSORS ONLY END */
/* HYBRID SENSORS CHIP ONLY END */
kfree(client); /* Frees client data too, if allocated at the same time */
return 0;

View File

@ -2,7 +2,7 @@
----------------------------
H. Peter Anvin <hpa@zytor.com>
Last update 2002-01-01
Last update 2005-09-02
On the i386 platform, the Linux kernel uses a rather complicated boot
convention. This has evolved partially due to historical aspects, as
@ -34,6 +34,8 @@ Protocol 2.02: (Kernel 2.4.0-test3-pre3) New command line protocol.
Protocol 2.03: (Kernel 2.4.18-pre1) Explicitly makes the highest possible
initrd address available to the bootloader.
Protocol 2.04: (Kernel 2.6.14) Extend the syssize field to four bytes.
**** MEMORY LAYOUT
@ -103,10 +105,9 @@ The header looks like:
Offset Proto Name Meaning
/Size
01F1/1 ALL setup_sects The size of the setup in sectors
01F1/1 ALL(1 setup_sects The size of the setup in sectors
01F2/2 ALL root_flags If set, the root is mounted readonly
01F4/2 ALL syssize DO NOT USE - for bootsect.S use only
01F6/2 ALL swap_dev DO NOT USE - obsolete
01F4/4 2.04+(2 syssize The size of the 32-bit code in 16-byte paras
01F8/2 ALL ram_size DO NOT USE - for bootsect.S use only
01FA/2 ALL vid_mode Video mode control
01FC/2 ALL root_dev Default root device number
@ -129,8 +130,12 @@ Offset Proto Name Meaning
0228/4 2.02+ cmd_line_ptr 32-bit pointer to the kernel command line
022C/4 2.03+ initrd_addr_max Highest legal initrd address
For backwards compatibility, if the setup_sects field contains 0, the
real value is 4.
(1) For backwards compatibility, if the setup_sects field contains 0, the
real value is 4.
(2) For boot protocol prior to 2.04, the upper two bytes of the syssize
field are unusable, which means the size of a bzImage kernel
cannot be determined.
If the "HdrS" (0x53726448) magic number is not found at offset 0x202,
the boot protocol version is "old". Loading an old kernel, the
@ -230,12 +235,16 @@ loader to communicate with the kernel. Some of its options are also
relevant to the boot loader itself, see "special command line options"
below.
The kernel command line is a null-terminated string up to 255
characters long, plus the final null.
The kernel command line is a null-terminated string currently up to
255 characters long, plus the final null. A string that is too long
will be automatically truncated by the kernel, a boot loader may allow
a longer command line to be passed to permit future kernels to extend
this limit.
If the boot protocol version is 2.02 or later, the address of the
kernel command line is given by the header field cmd_line_ptr (see
above.)
above.) This address can be anywhere between the end of the setup
heap and 0xA0000.
If the protocol version is *not* 2.02 or higher, the kernel
command line is entered using the following protocol:
@ -255,7 +264,7 @@ command line is entered using the following protocol:
**** SAMPLE BOOT CONFIGURATION
As a sample configuration, assume the following layout of the real
mode segment:
mode segment (this is a typical, and recommended layout):
0x0000-0x7FFF Real mode kernel
0x8000-0x8FFF Stack and heap
@ -312,9 +321,9 @@ Such a boot loader should enter the following fields in the header:
**** LOADING THE REST OF THE KERNEL
The non-real-mode kernel starts at offset (setup_sects+1)*512 in the
kernel file (again, if setup_sects == 0 the real value is 4.) It
should be loaded at address 0x10000 for Image/zImage kernels and
The 32-bit (non-real-mode) kernel starts at offset (setup_sects+1)*512
in the kernel file (again, if setup_sects == 0 the real value is 4.)
It should be loaded at address 0x10000 for Image/zImage kernels and
0x100000 for bzImage kernels.
The kernel is a bzImage kernel if the protocol >= 2.00 and the 0x01

View File

@ -872,7 +872,13 @@ When kbuild executes the following steps are followed (roughly):
Assignments to $(targets) are without $(obj)/ prefix.
if_changed may be used in conjunction with custom commands as
defined in 6.7 "Custom kbuild commands".
Note: It is a typical mistake to forget the FORCE prerequisite.
Another common pitfall is that whitespace is sometimes
significant; for instance, the below will fail (note the extra space
after the comma):
target: source(s) FORCE
#WRONG!# $(call if_changed, ld/objcopy/gzip)
ld
Link target. Often LDFLAGS_$@ is used to set specific options to ld.

View File

@ -1174,6 +1174,11 @@ running once the system is up.
New name for the ramdisk parameter.
See Documentation/ramdisk.txt.
rdinit= [KNL]
Format: <full_path>
Run specified binary instead of /init from the ramdisk,
used for early userspace startup. See initrd.
reboot= [BUGS=IA-32,BUGS=ARM,BUGS=IA-64] Rebooting mode
Format: <reboot_mode>[,<reboot_mode2>[,...]]
See arch/*/kernel/reboot.c.

View File

@ -0,0 +1,138 @@
Author: Andreas Steinmetz <ast@domdv.de>
How to use dm-crypt and swsusp together:
========================================
Some prerequisites:
You know how dm-crypt works. If not, visit the following web page:
http://www.saout.de/misc/dm-crypt/
You have read Documentation/power/swsusp.txt and understand it.
You did read Documentation/initrd.txt and know how an initrd works.
You know how to create or how to modify an initrd.
Now your system is properly set up, your disk is encrypted except for
the swap device(s) and the boot partition which may contain a mini
system for crypto setup and/or rescue purposes. You may even have
an initrd that does your current crypto setup already.
At this point you want to encrypt your swap, too. Still you want to
be able to suspend using swsusp. This, however, means that you
have to be able to either enter a passphrase or that you read
the key(s) from an external device like a pcmcia flash disk
or an usb stick prior to resume. So you need an initrd, that sets
up dm-crypt and then asks swsusp to resume from the encrypted
swap device.
The most important thing is that you set up dm-crypt in such
a way that the swap device you suspend to/resume from has
always the same major/minor within the initrd as well as
within your running system. The easiest way to achieve this is
to always set up this swap device first with dmsetup, so that
it will always look like the following:
brw------- 1 root root 254, 0 Jul 28 13:37 /dev/mapper/swap0
Now set up your kernel to use /dev/mapper/swap0 as the default
resume partition, so your kernel .config contains:
CONFIG_PM_STD_PARTITION="/dev/mapper/swap0"
Prepare your boot loader to use the initrd you will create or
modify. For lilo the simplest setup looks like the following
lines:
image=/boot/vmlinuz
initrd=/boot/initrd.gz
label=linux
append="root=/dev/ram0 init=/linuxrc rw"
Finally you need to create or modify your initrd. Lets assume
you create an initrd that reads the required dm-crypt setup
from a pcmcia flash disk card. The card is formatted with an ext2
fs which resides on /dev/hde1 when the card is inserted. The
card contains at least the encrypted swap setup in a file
named "swapkey". /etc/fstab of your initrd contains something
like the following:
/dev/hda1 /mnt ext3 ro 0 0
none /proc proc defaults,noatime,nodiratime 0 0
none /sys sysfs defaults,noatime,nodiratime 0 0
/dev/hda1 contains an unencrypted mini system that sets up all
of your crypto devices, again by reading the setup from the
pcmcia flash disk. What follows now is a /linuxrc for your
initrd that allows you to resume from encrypted swap and that
continues boot with your mini system on /dev/hda1 if resume
does not happen:
#!/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
mount /proc
mount /sys
mapped=0
noresume=`grep -c noresume /proc/cmdline`
if [ "$*" != "" ]
then
noresume=1
fi
dmesg -n 1
/sbin/cardmgr -q
for i in 1 2 3 4 5 6 7 8 9 0
do
if [ -f /proc/ide/hde/media ]
then
usleep 500000
mount -t ext2 -o ro /dev/hde1 /mnt
if [ -f /mnt/swapkey ]
then
dmsetup create swap0 /mnt/swapkey > /dev/null 2>&1 && mapped=1
fi
umount /mnt
break
fi
usleep 500000
done
killproc /sbin/cardmgr
dmesg -n 6
if [ $mapped = 1 ]
then
if [ $noresume != 0 ]
then
mkswap /dev/mapper/swap0 > /dev/null 2>&1
fi
echo 254:0 > /sys/power/resume
dmsetup remove swap0
fi
umount /sys
mount /mnt
umount /proc
cd /mnt
pivot_root . mnt
mount /proc
umount -l /mnt
umount /proc
exec chroot . /sbin/init $* < dev/console > dev/console 2>&1
Please don't mind the weird loop above, busybox's msh doesn't know
the let statement. Now, what is happening in the script?
First we have to decide if we want to try to resume, or not.
We will not resume if booting with "noresume" or any parameters
for init like "single" or "emergency" as boot parameters.
Then we need to set up dmcrypt with the setup data from the
pcmcia flash disk. If this succeeds we need to reset the swap
device if we don't want to resume. The line "echo 254:0 > /sys/power/resume"
then attempts to resume from the first device mapper device.
Note that it is important to set the device in /sys/power/resume,
regardless if resuming or not, otherwise later suspend will fail.
If resume starts, script execution terminates here.
Otherwise we just remove the encrypted swap device and leave it to the
mini system on /dev/hda1 to set the whole crypto up (it is up to
you to modify this to your taste).
What then follows is the well known process to change the root
file system and continue booting from there. I prefer to unmount
the initrd prior to continue booting but it is up to you to modify
this.

View File

@ -1,22 +1,20 @@
From kernel/suspend.c:
Some warnings, first.
* BIG FAT WARNING *********************************************************
*
* If you have unsupported (*) devices using DMA...
* ...say goodbye to your data.
*
* If you touch anything on disk between suspend and resume...
* ...kiss your data goodbye.
*
* If your disk driver does not support suspend... (IDE does)
* ...you'd better find out how to get along
* without your data.
* If you do resume from initrd after your filesystems are mounted...
* ...bye bye root partition.
* [this is actually same case as above]
*
* If you change kernel command line between suspend and resume...
* ...prepare for nasty fsck or worse.
*
* If you change your hardware while system is suspended...
* ...well, it was not good idea.
* If you have unsupported (*) devices using DMA, you may have some
* problems. If your disk driver does not support suspend... (IDE does),
* it may cause some problems, too. If you change kernel command line
* between suspend and resume, it may do something wrong. If you change
* your hardware while system is suspended... well, it was not good idea;
* but it will probably only crash.
*
* (*) suspend/resume support is needed to make it safe.
@ -30,6 +28,13 @@ echo shutdown > /sys/power/disk; echo disk > /sys/power/state
echo platform > /sys/power/disk; echo disk > /sys/power/state
Encrypted suspend image:
------------------------
If you want to store your suspend image encrypted with a temporary
key to prevent data gathering after resume you must compile
crypto and the aes algorithm into the kernel - modules won't work
as they cannot be loaded at resume time.
Article about goals and implementation of Software Suspend for Linux
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -85,11 +90,6 @@ resume.
You have your server on UPS. Power died, and UPS is indicating 30
seconds to failure. What do you do? Suspend to disk.
Ethernet card in your server died. You want to replace it. Your
server is not hotplug capable. What do you do? Suspend to disk,
replace ethernet card, resume. If you are fast your users will not
even see broken connections.
Q: Maybe I'm missing something, but why don't the regular I/O paths work?
@ -117,31 +117,6 @@ Q: Does linux support ACPI S4?
A: Yes. That's what echo platform > /sys/power/disk does.
Q: My machine doesn't work with ACPI. How can I use swsusp than ?
A: Do a reboot() syscall with right parameters. Warning: glibc gets in
its way, so check with strace:
reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, 0xd000fce2)
(Thanks to Peter Osterlund:)
#include <unistd.h>
#include <syscall.h>
#define LINUX_REBOOT_MAGIC1 0xfee1dead
#define LINUX_REBOOT_MAGIC2 672274793
#define LINUX_REBOOT_CMD_SW_SUSPEND 0xD000FCE2
int main()
{
syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
LINUX_REBOOT_CMD_SW_SUSPEND, 0);
return 0;
}
Also /sys/ interface should be still present.
Q: What is 'suspend2'?
A: suspend2 is 'Software Suspend 2', a forked implementation of
@ -311,3 +286,46 @@ As a rule of thumb use encrypted swap to protect your data while your
system is shut down or suspended. Additionally use the encrypted
suspend image to prevent sensitive data from being stolen after
resume.
Q: Why can't we suspend to a swap file?
A: Because accessing swap file needs the filesystem mounted, and
filesystem might do something wrong (like replaying the journal)
during mount.
There are few ways to get that fixed:
1) Probably could be solved by modifying every filesystem to support
some kind of "really read-only!" option. Patches welcome.
2) suspend2 gets around that by storing absolute positions in on-disk
image (and blocksize), with resume parameter pointing directly to
suspend header.
Q: Is there a maximum system RAM size that is supported by swsusp?
A: It should work okay with highmem.
Q: Does swsusp (to disk) use only one swap partition or can it use
multiple swap partitions (aggregate them into one logical space)?
A: Only one swap partition, sorry.
Q: If my application(s) causes lots of memory & swap space to be used
(over half of the total system RAM), is it correct that it is likely
to be useless to try to suspend to disk while that app is running?
A: No, it should work okay, as long as your app does not mlock()
it. Just prepare big enough swap partition.
Q: What information is usefull for debugging suspend-to-disk problems?
A: Well, last messages on the screen are always useful. If something
is broken, it is usually some kernel driver, therefore trying with as
little as possible modules loaded helps a lot. I also prefer people to
suspend from console, preferably without X running. Booting with
init=/bin/bash, then swapon and starting suspend sequence manually
usually does the trick. Then it is good idea to try with latest
vanilla kernel.

View File

@ -46,6 +46,12 @@ There are a few types of systems where video works after S3 resume:
POSTing bios works. Ole Rohne has patch to do just that at
http://dev.gentoo.org/~marineam/patch-radeonfb-2.6.11-rc2-mm2.
(8) on some systems, you can use the video_post utility mentioned here:
http://bugzilla.kernel.org/show_bug.cgi?id=3670. Do echo 3 > /sys/power/state
&& /usr/sbin/video_post - which will initialize the display in console mode.
If you are in X, you can switch to a virtual terminal and back to X using
CTRL+ALT+F1 - CTRL+ALT+F7 to get the display working in graphical mode again.
Now, if you pass acpi_sleep=something, and it does not work with your
bios, you'll get a hard crash during resume. Be careful. Also it is
safest to do your experiments with plain old VGA console. The vesafb
@ -64,7 +70,8 @@ Model hack (or "how to do it")
------------------------------------------------------------------------------
Acer Aspire 1406LC ole's late BIOS init (7), turn off DRI
Acer TM 242FX vbetool (6)
Acer TM C300 vga=normal (only suspend on console, not in X), vbetool (6)
Acer TM C110 video_post (8)
Acer TM C300 vga=normal (only suspend on console, not in X), vbetool (6) or video_post (8)
Acer TM 4052LCi s3_bios (2)
Acer TM 636Lci s3_bios vga=normal (2)
Acer TM 650 (Radeon M7) vga=normal plus boot-radeon (5) gets text console back
@ -113,6 +120,7 @@ IBM ThinkPad T42p (2373-GTG) s3_bios (2)
IBM TP X20 ??? (*)
IBM TP X30 s3_bios (2)
IBM TP X31 / Type 2672-XXH none (1), use radeontool (http://fdd.com/software/radeon/) to turn off backlight.
IBM TP X32 none (1), but backlight is on and video is trashed after long suspend
IBM Thinkpad X40 Type 2371-7JG s3_bios,s3_mode (4)
Medion MD4220 ??? (*)
Samsung P35 vbetool needed (6)

View File

@ -1,5 +1,5 @@
====================================================================
= Adaptec Aic7xxx Fast -> Ultra160 Family Manager Set v6.2.28 =
= Adaptec Aic7xxx Fast -> Ultra160 Family Manager Set v7.0 =
= README for =
= The Linux Operating System =
====================================================================
@ -131,6 +131,10 @@ The following information is available in this file:
SCSI "stub" effects.
2. Version History
7.0 (4th August, 2005)
- Updated driver to use SCSI transport class infrastructure
- Upported sequencer and core fixes from last adaptec released
version of the driver.
6.2.36 (June 3rd, 2003)
- Correct code that disables PCI parity error checking.
- Correct and simplify handling of the ignore wide residue

View File

@ -373,13 +373,11 @@ Summary:
scsi_activate_tcq - turn on tag command queueing
scsi_add_device - creates new scsi device (lu) instance
scsi_add_host - perform sysfs registration and SCSI bus scan.
scsi_add_timer - (re-)start timer on a SCSI command.
scsi_adjust_queue_depth - change the queue depth on a SCSI device
scsi_assign_lock - replace default host_lock with given lock
scsi_bios_ptable - return copy of block device's partition table
scsi_block_requests - prevent further commands being queued to given host
scsi_deactivate_tcq - turn off tag command queueing
scsi_delete_timer - cancel timer on a SCSI command.
scsi_host_alloc - return a new scsi_host instance whose refcount==1
scsi_host_get - increments Scsi_Host instance's refcount
scsi_host_put - decrements Scsi_Host instance's refcount (free if 0)
@ -457,27 +455,6 @@ struct scsi_device * scsi_add_device(struct Scsi_Host *shost,
int scsi_add_host(struct Scsi_Host *shost, struct device * dev)
/**
* scsi_add_timer - (re-)start timer on a SCSI command.
* @scmd: pointer to scsi command instance
* @timeout: duration of timeout in "jiffies"
* @complete: pointer to function to call if timeout expires
*
* Returns nothing
*
* Might block: no
*
* Notes: Each scsi command has its own timer, and as it is added
* to the queue, we set up the timer. When the command completes,
* we cancel the timer. An LLD can use this function to change
* the existing timeout value.
*
* Defined in: drivers/scsi/scsi_error.c
**/
void scsi_add_timer(struct scsi_cmnd *scmd, int timeout,
void (*complete)(struct scsi_cmnd *))
/**
* scsi_adjust_queue_depth - allow LLD to change queue depth on a SCSI device
* @sdev: pointer to SCSI device to change queue depth on
@ -565,24 +542,6 @@ void scsi_block_requests(struct Scsi_Host * shost)
void scsi_deactivate_tcq(struct scsi_device *sdev, int depth)
/**
* scsi_delete_timer - cancel timer on a SCSI command.
* @scmd: pointer to scsi command instance
*
* Returns 1 if able to cancel timer else 0 (i.e. too late or already
* cancelled).
*
* Might block: no [may in the future if it invokes del_timer_sync()]
*
* Notes: All commands issued by upper levels already have a timeout
* associated with them. An LLD can use this function to cancel the
* timer.
*
* Defined in: drivers/scsi/scsi_error.c
**/
int scsi_delete_timer(struct scsi_cmnd *scmd)
/**
* scsi_host_alloc - create a scsi host adapter instance and perform basic
* initialization.

View File

@ -99,6 +99,7 @@ statically linked into the kernel). Those options are:
SONYPI_MEYE_MASK 0x0400
SONYPI_MEMORYSTICK_MASK 0x0800
SONYPI_BATTERY_MASK 0x1000
SONYPI_WIRELESS_MASK 0x2000
useinput: if set (which is the default) two input devices are
created, one which interprets the jogdial events as
@ -137,6 +138,15 @@ Bugs:
speed handling etc). Use ACPI instead of APM if it works on your
laptop.
- sonypi lacks the ability to distinguish between certain key
events on some models.
- some models with the nvidia card (geforce go 6200 tc) uses a
different way to adjust the backlighting of the screen. There
is a userspace utility to adjust the brightness on those models,
which can be downloaded from
http://www.acc.umu.se/~erikw/program/smartdimmer-0.1.tar.bz2
- since all development was done by reverse engineering, there is
_absolutely no guarantee_ that this driver will not crash your
laptop. Permanently.

View File

@ -83,19 +83,18 @@ single address space optimization, so that the zap_page_range (from
vmtruncate) does not lose sending ipi's to cloned threads that might
be spawned underneath it and go to user mode to drag in pte's into tlbs.
swap_list_lock/swap_device_lock
-------------------------------
swap_lock
--------------
The swap devices are chained in priority order from the "swap_list" header.
The "swap_list" is used for the round-robin swaphandle allocation strategy.
The #free swaphandles is maintained in "nr_swap_pages". These two together
are protected by the swap_list_lock.
are protected by the swap_lock.
The swap_device_lock, which is per swap device, protects the reference
counts on the corresponding swaphandles, maintained in the "swap_map"
array, and the "highest_bit" and "lowest_bit" fields.
The swap_lock also protects all the device reference counts on the
corresponding swaphandles, maintained in the "swap_map" array, and the
"highest_bit" and "lowest_bit" fields.
Both of these are spinlocks, and are never acquired from intr level. The
locking hierarchy is swap_list_lock -> swap_device_lock.
The swap_lock is a spinlock, and is never acquired from intr level.
To prevent races between swap space deletion or async readahead swapins
deciding whether a swap handle is being used, ie worthy of being read in

View File

@ -228,6 +228,26 @@ advantechwdt.c -- Advantech Single Board Computer
The GETSTATUS call returns if the device is open or not.
[FIXME -- silliness again?]
booke_wdt.c -- PowerPC BookE Watchdog Timer
Timeout default varies according to frequency, supports
SETTIMEOUT
Watchdog can not be turned off, CONFIG_WATCHDOG_NOWAYOUT
does not make sense
GETSUPPORT returns the watchdog_info struct, and
GETSTATUS returns the supported options. GETBOOTSTATUS
returns a 1 if the last reset was caused by the
watchdog and a 0 otherwise. This watchdog can not be
disabled once it has been started. The wdt_period kernel
parameter selects which bit of the time base changing
from 0->1 will trigger the watchdog exception. Changing
the timeout from the ioctl calls will change the
wdt_period as defined above. Finally if you would like to
replace the default Watchdog Handler you can implement the
WatchdogHandler() function in your own code.
eurotechwdt.c -- Eurotech CPU-1220/1410
The timeout can be set using the SETTIMEOUT ioctl and defaults

View File

@ -202,13 +202,6 @@ P: Colin Leroy
M: colin@colino.net
S: Maintained
ADVANSYS SCSI DRIVER
P: Bob Frey
M: linux@advansys.com
W: http://www.advansys.com/linux.html
L: linux-scsi@vger.kernel.org
S: Maintained
AEDSP16 DRIVER
P: Riccardo Facchetti
M: fizban@tin.it
@ -696,6 +689,11 @@ M: dz@debian.org
W: http://www.debian.org/~dz/i8k/
S: Maintained
DELL SYSTEMS MANAGEMENT BASE DRIVER (dcdbas)
P: Doug Warzecha
M: Douglas_Warzecha@dell.com
S: Maintained
DEVICE-MAPPER
P: Alasdair Kergon
L: dm-devel@redhat.com
@ -824,6 +822,13 @@ L: emu10k1-devel@lists.sourceforge.net
W: http://sourceforge.net/projects/emu10k1/
S: Maintained
EMULEX LPFC FC SCSI DRIVER
P: James Smart
M: james.smart@emulex.com
L: linux-scsi@vger.kernel.org
W: http://sourceforge.net/projects/lpfcxxxx
S: Supported
EPSON 1355 FRAMEBUFFER DRIVER
P: Christopher Hoover
M: ch@murgatroid.com, ch@hpl.hp.com
@ -879,7 +884,7 @@ S: Maintained
FILESYSTEMS (VFS and infrastructure)
P: Alexander Viro
M: viro@parcelfarce.linux.theplanet.co.uk
M: viro@zeniv.linux.org.uk
S: Maintained
FIRMWARE LOADER (request_firmware)
@ -933,6 +938,13 @@ M: khc@pm.waw.pl
W: http://www.kernel.org/pub/linux/utils/net/hdlc/
S: Maintained
HARDWARE MONITORING
P: Jean Delvare
M: khali@linux-fr.org
L: lm-sensors@lm-sensors.org
W: http://www.lm-sensors.nu/
S: Maintained
HARMONY SOUND DRIVER
P: Kyle McMartin
M: kyle@parisc-linux.org
@ -1014,7 +1026,7 @@ P: William Irwin
M: wli@holomorphy.com
S: Maintained
I2C AND SENSORS DRIVERS
I2C SUBSYSTEM
P: Greg Kroah-Hartman
M: greg@kroah.com
P: Jean Delvare
@ -1960,7 +1972,6 @@ S: Supported
ROCKETPORT DRIVER
P: Comtrol Corp.
M: support@comtrol.com
W: http://www.comtrol.com
S: Maintained

164
Makefile
View File

@ -109,10 +109,9 @@ $(if $(KBUILD_OUTPUT),, \
.PHONY: $(MAKECMDGOALS)
$(filter-out _all,$(MAKECMDGOALS)) _all:
$(if $(KBUILD_VERBOSE:1=),@)$(MAKE) -C $(KBUILD_OUTPUT) \
KBUILD_SRC=$(CURDIR) KBUILD_VERBOSE=$(KBUILD_VERBOSE) \
KBUILD_CHECK=$(KBUILD_CHECK) KBUILD_EXTMOD="$(KBUILD_EXTMOD)" \
-f $(CURDIR)/Makefile $@
$(if $(KBUILD_VERBOSE:1=),@)$(MAKE) -C $(KBUILD_OUTPUT) \
KBUILD_SRC=$(CURDIR) \
KBUILD_EXTMOD="$(KBUILD_EXTMOD)" -f $(CURDIR)/Makefile $@
# Leave processing to above invocation of make
skip-makefile := 1
@ -233,7 +232,7 @@ ifeq ($(MAKECMDGOALS),)
KBUILD_MODULES := 1
endif
export KBUILD_MODULES KBUILD_BUILTIN KBUILD_VERBOSE
export KBUILD_MODULES KBUILD_BUILTIN
export KBUILD_CHECKSRC KBUILD_SRC KBUILD_EXTMOD
# Beautify output
@ -309,6 +308,9 @@ cc-version = $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh \
# Look for make include files relative to root of kernel src
MAKEFLAGS += --include-dir=$(srctree)
# We need some generic definitions
include $(srctree)/scripts/Kbuild.include
# For maximum performance (+ possibly random breakage, uncomment
# the following)
@ -348,7 +350,7 @@ LINUXINCLUDE := -Iinclude \
CPPFLAGS := -D__KERNEL__ $(LINUXINCLUDE)
CFLAGS := -Wall -Wstrict-prototypes -Wno-trigraphs \
CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
-fno-strict-aliasing -fno-common \
-ffreestanding
AFLAGS := -D__ASSEMBLY__
@ -367,15 +369,10 @@ export AFLAGS AFLAGS_KERNEL AFLAGS_MODULE
# even be read-only.
export MODVERDIR := $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/).tmp_versions
# The temporary file to save gcc -MD generated dependencies must not
# contain a comma
comma := ,
depfile = $(subst $(comma),_,$(@D)/.$(@F).d)
# Files to ignore in find ... statements
RCS_FIND_IGNORE := \( -name SCCS -o -name BitKeeper -o -name .svn -o -name CVS -o -name .pc \) -prune -o
RCS_TAR_IGNORE := --exclude SCCS --exclude BitKeeper --exclude .svn --exclude CVS --exclude .pc
RCS_FIND_IGNORE := \( -name SCCS -o -name BitKeeper -o -name .svn -o -name CVS -o -name .pc -o -name .hg \) -prune -o
RCS_TAR_IGNORE := --exclude SCCS --exclude BitKeeper --exclude .svn --exclude CVS --exclude .pc --exclude .hg
# ===========================================================================
# Rules shared between *config targets and build targets
@ -551,6 +548,26 @@ export KBUILD_IMAGE ?= vmlinux
# images. Default is /boot, but you can set it to other values
export INSTALL_PATH ?= /boot
# If CONFIG_LOCALVERSION_AUTO is set, we automatically perform some tests
# and try to determine if the current source tree is a release tree, of any sort,
# or if is a pure development tree.
#
# A 'release tree' is any tree with a git TAG associated
# with it. The primary goal of this is to make it safe for a native
# git/CVS/SVN user to build a release tree (i.e, 2.6.9) and also to
# continue developing against the current Linus tree, without having the Linus
# tree overwrite the 2.6.9 tree when installed.
#
# Currently, only git is supported.
# Other SCMs can edit scripts/setlocalversion and add the appropriate
# checks as needed.
ifdef CONFIG_LOCALVERSION_AUTO
localversion-auto := $(shell $(PERL) $(srctree)/scripts/setlocalversion $(srctree))
LOCALVERSION := $(LOCALVERSION)$(localversion-auto)
endif
#
# INSTALL_MOD_PATH specifies a prefix to MODLIB for module directory
# relocations required by build roots. This is not defined in the
@ -691,8 +708,10 @@ endef
# Update vmlinux version before link
# Use + in front of this rule to silent warning about make -j1
# First command is ':' to allow us to use + in front of this rule
cmd_ksym_ld = $(cmd_vmlinux__)
define rule_ksym_ld
:
+$(call cmd,vmlinux_version)
$(call cmd,vmlinux__)
$(Q)echo 'cmd_$@ := $(cmd_vmlinux__)' > $(@D)/.$(@F).cmd
@ -722,6 +741,16 @@ quiet_cmd_kallsyms = KSYM $@
# Needs to visit scripts/ before $(KALLSYMS) can be used.
$(KALLSYMS): scripts ;
# Generate some data for debugging strange kallsyms problems
debug_kallsyms: .tmp_map$(last_kallsyms)
.tmp_map%: .tmp_vmlinux% FORCE
($(OBJDUMP) -h $< | $(AWK) '/^ +[0-9]/{print $$4 " 0 " $$2}'; $(NM) $<) | sort > $@
.tmp_map3: .tmp_map2
.tmp_map2: .tmp_map1
endif # ifdef CONFIG_KALLSYMS
# vmlinux image - including updated kernel symbols
@ -757,7 +786,7 @@ $(vmlinux-dirs): prepare-all scripts
prepare2:
ifneq ($(KBUILD_SRC),)
@echo ' Using $(srctree) as source for kernel'
$(Q)if [ -h $(srctree)/include/asm -o -f $(srctree)/.config ]; then \
$(Q)if [ -f $(srctree)/.config ]; then \
echo " $(srctree) is not clean, please run 'make mrproper'";\
echo " in the '$(srctree)' directory.";\
/bin/false; \
@ -769,7 +798,8 @@ endif
# prepare1 creates a makefile if using a separate output directory
prepare1: prepare2 outputmakefile
prepare0: prepare1 include/linux/version.h include/asm include/config/MARKER
prepare0: prepare1 include/linux/version.h include/asm \
include/config/MARKER
ifneq ($(KBUILD_MODULES),)
$(Q)rm -rf $(MODVERDIR)
$(Q)mkdir -p $(MODVERDIR)
@ -875,7 +905,7 @@ modules_install: _modinst_ _modinst_post
.PHONY: _modinst_
_modinst_:
@if [ -z "`$(DEPMOD) -V | grep module-init-tools`" ]; then \
@if [ -z "`$(DEPMOD) -V 2>/dev/null | grep module-init-tools`" ]; then \
echo "Warning: you may need to install module-init-tools"; \
echo "See http://www.codemonkey.org.uk/docs/post-halloween-2.6.txt";\
sleep 1; \
@ -1159,37 +1189,49 @@ else
__srctree = $(srctree)/
endif
ALLSOURCE_ARCHS := $(ARCH)
define all-sources
( find $(__srctree) $(RCS_FIND_IGNORE) \
\( -name include -o -name arch \) -prune -o \
-name '*.[chS]' -print; \
find $(__srctree)arch/$(ARCH) $(RCS_FIND_IGNORE) \
-name '*.[chS]' -print; \
for ARCH in $(ALLSOURCE_ARCHS) ; do \
find $(__srctree)arch/$${ARCH} $(RCS_FIND_IGNORE) \
-name '*.[chS]' -print; \
done ; \
find $(__srctree)security/selinux/include $(RCS_FIND_IGNORE) \
-name '*.[chS]' -print; \
find $(__srctree)include $(RCS_FIND_IGNORE) \
\( -name config -o -name 'asm-*' \) -prune \
-o -name '*.[chS]' -print; \
find $(__srctree)include/asm-$(ARCH) $(RCS_FIND_IGNORE) \
-name '*.[chS]' -print; \
for ARCH in $(ALLSOURCE_ARCHS) ; do \
find $(__srctree)include/asm-$${ARCH} $(RCS_FIND_IGNORE) \
-name '*.[chS]' -print; \
done ; \
find $(__srctree)include/asm-generic $(RCS_FIND_IGNORE) \
-name '*.[chS]' -print )
endef
quiet_cmd_cscope-file = FILELST cscope.files
cmd_cscope-file = $(all-sources) > cscope.files
cmd_cscope-file = (echo \-k; echo \-q; $(all-sources)) > cscope.files
quiet_cmd_cscope = MAKE cscope.out
cmd_cscope = cscope -k -b -q
cmd_cscope = cscope -b
cscope: FORCE
$(call cmd,cscope-file)
$(call cmd,cscope)
quiet_cmd_TAGS = MAKE $@
cmd_TAGS = $(all-sources) | etags -
define cmd_TAGS
rm -f $@; \
ETAGSF=`etags --version | grep -i exuberant >/dev/null && echo "-I __initdata,__exitdata,EXPORT_SYMBOL,EXPORT_SYMBOL_GPL --extra=+f"`; \
$(all-sources) | xargs etags $$ETAGSF -a
endef
TAGS: FORCE
$(call cmd,TAGS)
# Exuberant ctags works better with -I
quiet_cmd_tags = MAKE $@
define cmd_tags
@ -1198,9 +1240,6 @@ define cmd_tags
$(all-sources) | xargs ctags $$CTAGSF -a
endef
TAGS: FORCE
$(call cmd,TAGS)
tags: FORCE
$(call cmd,tags)
@ -1268,82 +1307,11 @@ ifneq ($(cmd_files),)
include $(cmd_files)
endif
# Execute command and generate cmd file
if_changed = $(if $(strip $? \
$(filter-out $(cmd_$(1)),$(cmd_$@))\
$(filter-out $(cmd_$@),$(cmd_$(1)))),\
@set -e; \
$(if $($(quiet)cmd_$(1)),echo ' $(subst ','\'',$($(quiet)cmd_$(1)))';) \
$(cmd_$(1)); \
echo 'cmd_$@ := $(subst $$,$$$$,$(subst ','\'',$(cmd_$(1))))' > $(@D)/.$(@F).cmd)
# execute the command and also postprocess generated .d dependencies
# file
if_changed_dep = $(if $(strip $? $(filter-out FORCE $(wildcard $^),$^)\
$(filter-out $(cmd_$(1)),$(cmd_$@))\
$(filter-out $(cmd_$@),$(cmd_$(1)))),\
$(Q)set -e; \
$(if $($(quiet)cmd_$(1)),echo ' $(subst ','\'',$($(quiet)cmd_$(1)))';) \
$(cmd_$(1)); \
scripts/basic/fixdep $(depfile) $@ '$(subst $$,$$$$,$(subst ','\'',$(cmd_$(1))))' > $(@D)/.$(@F).tmp; \
rm -f $(depfile); \
mv -f $(@D)/.$(@F).tmp $(@D)/.$(@F).cmd)
# Usage: $(call if_changed_rule,foo)
# will check if $(cmd_foo) changed, or any of the prequisites changed,
# and if so will execute $(rule_foo)
if_changed_rule = $(if $(strip $? \
$(filter-out $(cmd_$(1)),$(cmd_$(@F)))\
$(filter-out $(cmd_$(@F)),$(cmd_$(1)))),\
$(Q)$(rule_$(1)))
# If quiet is set, only print short version of command
cmd = @$(if $($(quiet)cmd_$(1)),echo ' $($(quiet)cmd_$(1))' &&) $(cmd_$(1))
# filechk is used to check if the content of a generated file is updated.
# Sample usage:
# define filechk_sample
# echo $KERNELRELEASE
# endef
# version.h : Makefile
# $(call filechk,sample)
# The rule defined shall write to stdout the content of the new file.
# The existing file will be compared with the new one.
# - If no file exist it is created
# - If the content differ the new file is used
# - If they are equal no change, and no timestamp update
define filechk
@set -e; \
echo ' CHK $@'; \
mkdir -p $(dir $@); \
$(filechk_$(1)) < $< > $@.tmp; \
if [ -r $@ ] && cmp -s $@ $@.tmp; then \
rm -f $@.tmp; \
else \
echo ' UPD $@'; \
mv -f $@.tmp $@; \
fi
endef
# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.build obj=dir
# Usage:
# $(Q)$(MAKE) $(build)=dir
build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj
# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.clean obj=dir
# Usage:
# $(Q)$(MAKE) $(clean)=dir
clean := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.clean obj
# $(call descend,<dir>,<target>)
# Recursively call a sub-make in <dir> with target <target>
# Usage is deprecated, because make does not see this as an invocation of make.
descend =$(Q)$(MAKE) -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj=$(1) $(2)
endif # skip-makefile
FORCE:

View File

@ -479,6 +479,9 @@ config EISA
depends on ALPHA_GENERIC || ALPHA_JENSEN || ALPHA_ALCOR || ALPHA_MIKASA || ALPHA_SABLE || ALPHA_LYNX || ALPHA_NORITAKE || ALPHA_RAWHIDE
default y
config ARCH_MAY_HAVE_PC_FDC
def_bool y
config SMP
bool "Symmetric multi-processing support"
depends on ALPHA_SABLE || ALPHA_LYNX || ALPHA_RAWHIDE || ALPHA_DP264 || ALPHA_WILDFIRE || ALPHA_TITAN || ALPHA_GENERIC || ALPHA_SHARK || ALPHA_MARVEL

View File

@ -149,7 +149,7 @@ irqreturn_t timer_interrupt(int irq, void *dev, struct pt_regs * regs)
* CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
* called as close as possible to 500 ms before the new second starts.
*/
if ((time_status & STA_UNSYNC) == 0
if (ntp_synced()
&& xtime.tv_sec > state.last_rtc_update + 660
&& xtime.tv_nsec >= 500000 - ((unsigned) TICK_SIZE) / 2
&& xtime.tv_nsec <= 500000 + ((unsigned) TICK_SIZE) / 2) {
@ -502,10 +502,7 @@ do_settimeofday(struct timespec *tv)
set_normalized_timespec(&xtime, sec, nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC;
time_maxerror = NTP_PHASE_LIMIT;
time_esterror = NTP_PHASE_LIMIT;
ntp_clear();
write_sequnlock_irq(&xtime_lock);
clock_was_set();

View File

@ -64,6 +64,9 @@ config GENERIC_CALIBRATE_DELAY
config GENERIC_BUST_SPINLOCK
bool
config ARCH_MAY_HAVE_PC_FDC
bool
config GENERIC_ISA_DMA
bool
@ -150,6 +153,7 @@ config ARCH_RPC
select ARCH_ACORN
select FIQ
select TIMER_ACORN
select ARCH_MAY_HAVE_PC_FDC
help
On the Acorn Risc-PC, Linux can support the internal IDE disk and
CD-ROM interface, serial and parallel port, and the floppy drive.

View File

@ -7,7 +7,8 @@
* so we have to figure out the machine for ourselves...
*
* Support for Poodle, Corgi (SL-C700), Shepherd (SL-C750)
* and Husky (SL-C760).
* Husky (SL-C760), Tosa (SL-C6000), Spitz (SL-C3000),
* Akita (SL-C1000) and Borzoi (SL-C3100).
*
*/
@ -23,6 +24,22 @@
__SharpSL_start:
/* Check for TC6393 - if found we have a Tosa */
ldr r7, .TOSAID
mov r1, #0x10000000 @ Base address of TC6393 chip
mov r6, #0x03
ldrh r3, [r1, #8] @ Load TC6393XB Revison: This is 0x0003
cmp r6, r3
beq .SHARPEND @ Success -> tosa
/* Check for pxa270 - if found, branch */
mrc p15, 0, r4, c0, c0 @ Get Processor ID
and r4, r4, #0xffffff00
ldr r3, .PXA270ID
cmp r4, r3
beq .PXA270
/* Check for w100 - if not found we have a Poodle */
ldr r1, .W100ADDR @ Base address of w100 chip + regs offset
mov r6, #0x31 @ Load Magic Init value
@ -30,7 +47,7 @@ __SharpSL_start:
mov r5, #0x3000
.W100LOOP:
subs r5, r5, #1
bne .W100LOOP
bne .W100LOOP
mov r6, #0x30 @ Load 2nd Magic Init value
str r6, [r1, #0x280] @ to SCRATCH_UMSK
@ -40,45 +57,52 @@ __SharpSL_start:
cmp r6, r3
bne .SHARPEND @ We have no w100 - Poodle
mrc p15, 0, r6, c0, c0 @ Get Processor ID
and r6, r6, #0xffffff00
/* Check for pxa250 - if found we have a Corgi */
ldr r7, .CORGIID
ldr r3, .PXA255ID
cmp r6, r3
cmp r4, r3
blo .SHARPEND @ We have a PXA250 - Corgi
mov r1, #0x0c000000 @ Base address of NAND chip
ldrb r3, [r1, #24] @ Load FLASHCTL
bic r3, r3, #0x11 @ SET NCE
orr r3, r3, #0x0a @ SET CLR + FLWP
strb r3, [r1, #24] @ Save to FLASHCTL
mov r2, #0x90 @ Command "readid"
strb r2, [r1, #20] @ Save to FLASHIO
bic r3, r3, #2 @ CLR CLE
orr r3, r3, #4 @ SET ALE
strb r3, [r1, #24] @ Save to FLASHCTL
mov r2, #0 @ Address 0x00
strb r2, [r1, #20] @ Save to FLASHIO
bic r3, r3, #4 @ CLR ALE
strb r3, [r1, #24] @ Save to FLASHCTL
.SHARP1:
ldrb r3, [r1, #24] @ Load FLASHCTL
tst r3, #32 @ Is chip ready?
beq .SHARP1
ldrb r2, [r1, #20] @ NAND Manufacturer ID
ldrb r3, [r1, #20] @ NAND Chip ID
/* Check for 64MiB flash - if found we have a Shepherd */
bl get_flash_ids
ldr r7, .SHEPHERDID
cmp r3, #0x76 @ 64MiB flash
beq .SHARPEND @ We have Shepherd
/* Must be a Husky */
ldr r7, .HUSKYID @ Must be Husky
b .SHARPEND
.PXA270:
/* Check for 16MiB flash - if found we have Spitz */
bl get_flash_ids
ldr r7, .SPITZID
cmp r3, #0x73 @ 16MiB flash
beq .SHARPEND @ We have Spitz
/* Check for a second SCOOP chip - if found we have Borzoi */
ldr r1, .SCOOP2ADDR
ldr r7, .BORZOIID
mov r6, #0x0140
strh r6, [r1]
ldrh r6, [r1]
cmp r6, #0x0140
beq .SHARPEND @ We have Borzoi
/* Must be Akita */
ldr r7, .AKITAID
b .SHARPEND @ We have Borzoi
.PXA255ID:
.word 0x69052d00 @ PXA255 Processor ID
.PXA270ID:
.word 0x69054100 @ PXA270 Processor ID
.W100ID:
.word 0x57411002 @ w100 Chip ID
.W100ADDR:
.word 0x08010000 @ w100 Chip ID Reg Address
.SCOOP2ADDR:
.word 0x08800040
.POODLEID:
.word MACH_TYPE_POODLE
.CORGIID:
@ -87,6 +111,41 @@ __SharpSL_start:
.word MACH_TYPE_SHEPHERD
.HUSKYID:
.word MACH_TYPE_HUSKY
.TOSAID:
.word MACH_TYPE_TOSA
.SPITZID:
.word MACH_TYPE_SPITZ
.AKITAID:
.word MACH_TYPE_AKITA
.BORZOIID:
.word MACH_TYPE_BORZOI
/*
* Return: r2 - NAND Manufacturer ID
* r3 - NAND Chip ID
* Corrupts: r1
*/
get_flash_ids:
mov r1, #0x0c000000 @ Base address of NAND chip
ldrb r3, [r1, #24] @ Load FLASHCTL
bic r3, r3, #0x11 @ SET NCE
orr r3, r3, #0x0a @ SET CLR + FLWP
strb r3, [r1, #24] @ Save to FLASHCTL
mov r2, #0x90 @ Command "readid"
strb r2, [r1, #20] @ Save to FLASHIO
bic r3, r3, #2 @ CLR CLE
orr r3, r3, #4 @ SET ALE
strb r3, [r1, #24] @ Save to FLASHCTL
mov r2, #0 @ Address 0x00
strb r2, [r1, #20] @ Save to FLASHIO
bic r3, r3, #4 @ CLR ALE
strb r3, [r1, #24] @ Save to FLASHCTL
.fids1:
ldrb r3, [r1, #24] @ Load FLASHCTL
tst r3, #32 @ Is chip ready?
beq .fids1
ldrb r2, [r1, #20] @ NAND Manufacturer ID
ldrb r3, [r1, #20] @ NAND Chip ID
mov pc, lr
.SHARPEND:

View File

@ -177,7 +177,7 @@ static void locomo_handler(unsigned int irq, struct irqdesc *desc,
d = irq_desc + irq;
for (i = 0; i <= 3; i++, d++, irq++) {
if (req & (0x0100 << i)) {
d->handle(irq, d, regs);
desc_handle_irq(irq, d, regs);
}
}
@ -220,7 +220,7 @@ static void locomo_key_handler(unsigned int irq, struct irqdesc *desc,
if (locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC) & 0x0001) {
d = irq_desc + LOCOMO_IRQ_KEY_START;
d->handle(LOCOMO_IRQ_KEY_START, d, regs);
desc_handle_irq(LOCOMO_IRQ_KEY_START, d, regs);
}
}
@ -273,7 +273,7 @@ static void locomo_gpio_handler(unsigned int irq, struct irqdesc *desc,
d = irq_desc + LOCOMO_IRQ_GPIO_START;
for (i = 0; i <= 15; i++, irq++, d++) {
if (req & (0x0001 << i)) {
d->handle(irq, d, regs);
desc_handle_irq(irq, d, regs);
}
}
}
@ -328,7 +328,7 @@ static void locomo_lt_handler(unsigned int irq, struct irqdesc *desc,
if (locomo_readl(mapbase + LOCOMO_LTINT) & 0x0001) {
d = irq_desc + LOCOMO_IRQ_LT_START;
d->handle(LOCOMO_IRQ_LT_START, d, regs);
desc_handle_irq(LOCOMO_IRQ_LT_START, d, regs);
}
}
@ -379,7 +379,7 @@ static void locomo_spi_handler(unsigned int irq, struct irqdesc *desc,
for (i = 0; i <= 3; i++, irq++, d++) {
if (req & (0x0001 << i)) {
d->handle(irq, d, regs);
desc_handle_irq(irq, d, regs);
}
}
}
@ -651,15 +651,15 @@ __locomo_probe(struct device *me, struct resource *mem, int irq)
return ret;
}
static int locomo_remove_child(struct device *dev, void *data)
{
device_unregister(dev);
return 0;
}
static void __locomo_remove(struct locomo *lchip)
{
struct list_head *l, *n;
list_for_each_safe(l, n, &lchip->dev->children) {
struct device *d = list_to_dev(l);
device_unregister(d);
}
device_for_each_child(lchip->dev, NULL, locomo_remove_child);
if (lchip->irq != NO_IRQ) {
set_irq_chained_handler(lchip->irq, NULL);

View File

@ -268,8 +268,8 @@ static struct irqchip sa1111_low_chip = {
.mask = sa1111_mask_lowirq,
.unmask = sa1111_unmask_lowirq,
.retrigger = sa1111_retrigger_lowirq,
.type = sa1111_type_lowirq,
.wake = sa1111_wake_lowirq,
.set_type = sa1111_type_lowirq,
.set_wake = sa1111_wake_lowirq,
};
static void sa1111_mask_highirq(unsigned int irq)
@ -364,8 +364,8 @@ static struct irqchip sa1111_high_chip = {
.mask = sa1111_mask_highirq,
.unmask = sa1111_unmask_highirq,
.retrigger = sa1111_retrigger_highirq,
.type = sa1111_type_highirq,
.wake = sa1111_wake_highirq,
.set_type = sa1111_type_highirq,
.set_wake = sa1111_wake_highirq,
};
static void sa1111_setup_irq(struct sa1111 *sachip)

View File

@ -17,6 +17,12 @@
#define SCOOP_REG(d,adr) (*(volatile unsigned short*)(d +(adr)))
/* PCMCIA to Scoop linkage structures for pxa2xx_sharpsl.c
There is no easy way to link multiple scoop devices into one
single entity for the pxa2xx_pcmcia device */
int scoop_num;
struct scoop_pcmcia_dev *scoop_devs;
struct scoop_dev {
void *base;
spinlock_t scoop_lock;

View File

@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
# Linux kernel version: 2.6.13-rc2
# Fri Jul 8 04:49:34 2005
# Linux kernel version: 2.6.13
# Mon Sep 5 18:07:12 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
@ -102,9 +102,11 @@ CONFIG_OMAP_MUX_WARNINGS=y
# CONFIG_OMAP_MPU_TIMER is not set
CONFIG_OMAP_32K_TIMER=y
CONFIG_OMAP_32K_TIMER_HZ=128
# CONFIG_OMAP_DM_TIMER is not set
CONFIG_OMAP_LL_DEBUG_UART1=y
# CONFIG_OMAP_LL_DEBUG_UART2 is not set
# CONFIG_OMAP_LL_DEBUG_UART3 is not set
CONFIG_OMAP_SERIAL_WAKE=y
#
# OMAP Core Type
@ -166,7 +168,6 @@ CONFIG_ISA_DMA_API=y
#
# Kernel Features
#
# CONFIG_SMP is not set
CONFIG_PREEMPT=y
CONFIG_NO_IDLE_HZ=y
# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
@ -229,6 +230,68 @@ CONFIG_BINFMT_AOUT=y
CONFIG_PM=y
# CONFIG_APM is not set
#
# Networking
#
CONFIG_NET=y
#
# Networking options
#
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
# CONFIG_NET_KEY is not set
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
# CONFIG_IP_ADVANCED_ROUTER is not set
CONFIG_IP_FIB_HASH=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
CONFIG_IP_PNP_BOOTP=y
# CONFIG_IP_PNP_RARP is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
# CONFIG_ARPD is not set
# CONFIG_SYN_COOKIES is not set
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
# CONFIG_INET_TUNNEL is not set
CONFIG_IP_TCPDIAG=y
# CONFIG_IP_TCPDIAG_IPV6 is not set
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
# CONFIG_NETFILTER is not set
#
# SCTP Configuration (EXPERIMENTAL)
#
# CONFIG_IP_SCTP is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
# CONFIG_NET_CLS_ROUTE is not set
#
# Network testing
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
#
# Device Drivers
#
@ -243,78 +306,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
#
# Memory Technology Devices (MTD)
#
CONFIG_MTD=y
CONFIG_MTD_DEBUG=y
CONFIG_MTD_DEBUG_VERBOSE=3
# CONFIG_MTD_CONCAT is not set
CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_REDBOOT_PARTS is not set
CONFIG_MTD_CMDLINE_PARTS=y
# CONFIG_MTD_AFS_PARTS is not set
#
# User Modules And Translation Layers
#
CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
# CONFIG_FTL is not set
# CONFIG_NFTL is not set
# CONFIG_INFTL is not set
#
# RAM/ROM/Flash chip drivers
#
CONFIG_MTD_CFI=y
# CONFIG_MTD_JEDECPROBE is not set
CONFIG_MTD_GEN_PROBE=y
# CONFIG_MTD_CFI_ADV_OPTIONS is not set
CONFIG_MTD_MAP_BANK_WIDTH_1=y
CONFIG_MTD_MAP_BANK_WIDTH_2=y
CONFIG_MTD_MAP_BANK_WIDTH_4=y
# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
CONFIG_MTD_CFI_I1=y
CONFIG_MTD_CFI_I2=y
# CONFIG_MTD_CFI_I4 is not set
# CONFIG_MTD_CFI_I8 is not set
CONFIG_MTD_CFI_INTELEXT=y
# CONFIG_MTD_CFI_AMDSTD is not set
# CONFIG_MTD_CFI_STAA is not set
CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
# CONFIG_MTD_XIP is not set
#
# Mapping drivers for chip access
#
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
# CONFIG_MTD_PHYSMAP is not set
# CONFIG_MTD_ARM_INTEGRATOR is not set
# CONFIG_MTD_EDB7312 is not set
#
# Self-contained MTD device drivers
#
# CONFIG_MTD_SLRAM is not set
# CONFIG_MTD_PHRAM is not set
# CONFIG_MTD_MTDRAM is not set
# CONFIG_MTD_BLKMTD is not set
# CONFIG_MTD_BLOCK2MTD is not set
#
# Disk-On-Chip Device Drivers
#
# CONFIG_MTD_DOC2000 is not set
# CONFIG_MTD_DOC2001 is not set
# CONFIG_MTD_DOC2001PLUS is not set
#
# NAND Flash Device Drivers
#
# CONFIG_MTD_NAND is not set
# CONFIG_MTD is not set
#
# Parallel port support
@ -403,72 +395,8 @@ CONFIG_SCSI_PROC_FS=y
#
#
# Networking support
# Network device support
#
CONFIG_NET=y
#
# Networking options
#
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
# CONFIG_NET_KEY is not set
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
# CONFIG_IP_ADVANCED_ROUTER is not set
CONFIG_IP_FIB_HASH=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
CONFIG_IP_PNP_BOOTP=y
# CONFIG_IP_PNP_RARP is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
# CONFIG_ARPD is not set
# CONFIG_SYN_COOKIES is not set
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
# CONFIG_INET_TUNNEL is not set
CONFIG_IP_TCPDIAG=y
# CONFIG_IP_TCPDIAG_IPV6 is not set
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
# CONFIG_NETFILTER is not set
#
# SCTP Configuration (EXPERIMENTAL)
#
# CONFIG_IP_SCTP is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
#
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
# CONFIG_NET_CLS_ROUTE is not set
#
# Network testing
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
CONFIG_NETDEVICES=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
@ -518,6 +446,8 @@ CONFIG_SLIP_COMPRESSED=y
# CONFIG_SLIP_MODE_SLIP6 is not set
# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
#
# ISDN subsystem
@ -615,77 +545,15 @@ CONFIG_WATCHDOG_NOWAYOUT=y
#
# I2C support
#
CONFIG_I2C=y
CONFIG_I2C_CHARDEV=y
#
# I2C Algorithms
#
# CONFIG_I2C_ALGOBIT is not set
# CONFIG_I2C_ALGOPCF is not set
# CONFIG_I2C_ALGOPCA is not set
#
# I2C Hardware Bus support
#
# CONFIG_I2C_ISA is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_STUB is not set
# CONFIG_I2C_PCA_ISA is not set
#
# Hardware Sensors Chip support
#
# CONFIG_I2C is not set
# CONFIG_I2C_SENSOR is not set
# CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set
# CONFIG_SENSORS_ADM1026 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
# CONFIG_SENSORS_ASB100 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_FSCHER is not set
# CONFIG_SENSORS_FSCPOS is not set
# CONFIG_SENSORS_GL518SM is not set
# CONFIG_SENSORS_GL520SM is not set
# CONFIG_SENSORS_IT87 is not set
# CONFIG_SENSORS_LM63 is not set
# CONFIG_SENSORS_LM75 is not set
# CONFIG_SENSORS_LM77 is not set
# CONFIG_SENSORS_LM78 is not set
# CONFIG_SENSORS_LM80 is not set
# CONFIG_SENSORS_LM83 is not set
# CONFIG_SENSORS_LM85 is not set
# CONFIG_SENSORS_LM87 is not set
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_PC87360 is not set
# CONFIG_SENSORS_SMSC47B397 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_W83781D is not set
# CONFIG_SENSORS_W83L785TS is not set
# CONFIG_SENSORS_W83627HF is not set
# CONFIG_SENSORS_W83627EHF is not set
CONFIG_ISP1301_OMAP=y
#
# Other I2C Chip support
# Hardware Monitoring support
#
# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_DS1374 is not set
# CONFIG_SENSORS_EEPROM is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_RTC8564 is not set
CONFIG_ISP1301_OMAP=y
CONFIG_TPS65010=y
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
# CONFIG_I2C_DEBUG_CHIP is not set
CONFIG_HWMON=y
# CONFIG_HWMON_DEBUG_CHIP is not set
#
# Misc devices
@ -756,15 +624,9 @@ CONFIG_SOUND=y
# Open Sound System
#
CONFIG_SOUND_PRIME=y
# CONFIG_SOUND_BT878 is not set
# CONFIG_SOUND_FUSION is not set
# CONFIG_SOUND_CS4281 is not set
# CONFIG_SOUND_SONICVIBES is not set
# CONFIG_SOUND_TRIDENT is not set
# CONFIG_SOUND_MSNDCLAS is not set
# CONFIG_SOUND_MSNDPIN is not set
# CONFIG_SOUND_OSS is not set
# CONFIG_SOUND_TVMIXER is not set
# CONFIG_SOUND_AD1980 is not set
#
@ -810,6 +672,7 @@ CONFIG_EXT2_FS=y
# CONFIG_JBD is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
#
# XFS support
@ -817,6 +680,7 @@ CONFIG_EXT2_FS=y
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
CONFIG_ROMFS_FS=y
CONFIG_INOTIFY=y
# CONFIG_QUOTA is not set
CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
@ -857,15 +721,6 @@ CONFIG_RAMFS=y
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
# CONFIG_JFFS_FS is not set
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=2
# CONFIG_JFFS2_FS_NAND is not set
# CONFIG_JFFS2_FS_NOR_ECC is not set
# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
# CONFIG_JFFS2_RUBIN is not set
CONFIG_CRAMFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_HPFS_FS is not set
@ -1007,4 +862,3 @@ CONFIG_CRYPTO_DES=y
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y

View File

@ -585,7 +585,7 @@ ecard_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
if (pending) {
struct irqdesc *d = irq_desc + ec->irq;
d->handle(ec->irq, d, regs);
desc_handle_irq(ec->irq, d, regs);
called ++;
}
}
@ -632,7 +632,7 @@ ecard_irqexp_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *reg
* Serial cards should go in 0/1, ethernet/scsi in 2/3
* otherwise you will lose serial data at high speeds!
*/
d->handle(ec->irq, d, regs);
desc_handle_irq(ec->irq, d, regs);
} else {
printk(KERN_WARNING "card%d: interrupt from unclaimed "
"card???\n", slot);

View File

@ -207,8 +207,8 @@ void enable_irq_wake(unsigned int irq)
unsigned long flags;
spin_lock_irqsave(&irq_controller_lock, flags);
if (desc->chip->wake)
desc->chip->wake(irq, 1);
if (desc->chip->set_wake)
desc->chip->set_wake(irq, 1);
spin_unlock_irqrestore(&irq_controller_lock, flags);
}
EXPORT_SYMBOL(enable_irq_wake);
@ -219,8 +219,8 @@ void disable_irq_wake(unsigned int irq)
unsigned long flags;
spin_lock_irqsave(&irq_controller_lock, flags);
if (desc->chip->wake)
desc->chip->wake(irq, 0);
if (desc->chip->set_wake)
desc->chip->set_wake(irq, 0);
spin_unlock_irqrestore(&irq_controller_lock, flags);
}
EXPORT_SYMBOL(disable_irq_wake);
@ -517,7 +517,7 @@ static void do_pending_irqs(struct pt_regs *regs)
list_for_each_safe(l, n, &head) {
desc = list_entry(l, struct irqdesc, pend);
list_del_init(&desc->pend);
desc->handle(desc - irq_desc, desc, regs);
desc_handle_irq(desc - irq_desc, desc, regs);
}
/*
@ -545,7 +545,7 @@ asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
irq_enter();
spin_lock(&irq_controller_lock);
desc->handle(irq, desc, regs);
desc_handle_irq(irq, desc, regs);
/*
* Now re-run any pending interrupts.
@ -624,9 +624,9 @@ int set_irq_type(unsigned int irq, unsigned int type)
}
desc = irq_desc + irq;
if (desc->chip->type) {
if (desc->chip->set_type) {
spin_lock_irqsave(&irq_controller_lock, flags);
ret = desc->chip->type(irq, type);
ret = desc->chip->set_type(irq, type);
spin_unlock_irqrestore(&irq_controller_lock, flags);
}
@ -846,8 +846,8 @@ unsigned long probe_irq_on(void)
irq_desc[i].probing = 1;
irq_desc[i].triggered = 0;
if (irq_desc[i].chip->type)
irq_desc[i].chip->type(i, IRQT_PROBE);
if (irq_desc[i].chip->set_type)
irq_desc[i].chip->set_type(i, IRQT_PROBE);
irq_desc[i].chip->unmask(i);
irqs += 1;
}

View File

@ -110,7 +110,7 @@ int __cpuinit __cpu_up(unsigned int cpu)
* 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.stack = (void *)idle->thread_info + THREAD_START_SP;
secondary_data.pgdir = virt_to_phys(pgd);
wmb();

View File

@ -102,7 +102,7 @@ static unsigned long next_rtc_update;
*/
static inline void do_set_rtc(void)
{
if (time_status & STA_UNSYNC || set_rtc == NULL)
if (!ntp_synced() || set_rtc == NULL)
return;
if (next_rtc_update &&
@ -292,10 +292,7 @@ int do_settimeofday(struct timespec *tv)
set_normalized_timespec(&xtime, sec, nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC;
time_maxerror = NTP_PHASE_LIMIT;
time_esterror = NTP_PHASE_LIMIT;
ntp_clear();
write_sequnlock_irq(&xtime_lock);
clock_was_set();
return 0;

View File

@ -87,6 +87,7 @@ config FOOTBRIDGE_ADDIN
# EBSA285 board in either host or addin mode
config ARCH_EBSA285
select ARCH_MAY_HAVE_PC_FDC
bool
endif

View File

@ -95,7 +95,7 @@ isa_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
}
desc = irq_desc + isa_irq;
desc->handle(isa_irq, desc, regs);
desc_handle_irq(isa_irq, desc, regs);
}
static struct irqaction irq_cascade = { .handler = no_action, .name = "cascade", };

View File

@ -108,7 +108,7 @@ h720x_gpio_handler(unsigned int mask, unsigned int irq,
while (mask) {
if (mask & 1) {
IRQDBG("handling irq %d\n", irq);
desc->handle(irq, desc, regs);
desc_handle_irq(irq, desc, regs);
}
irq++;
desc++;

View File

@ -126,7 +126,7 @@ h7202_timerx_demux_handler(unsigned int irq_unused, struct irqdesc *desc,
desc = irq_desc + irq;
while (mask) {
if (mask & 1)
desc->handle(irq, desc, regs);
desc_handle_irq(irq, desc, regs);
irq++;
desc++;
mask >>= 1;

View File

@ -152,7 +152,7 @@ imx_gpio_handler(unsigned int mask, unsigned int irq,
while (mask) {
if (mask & 1) {
DEBUG_IRQ("handling irq %d\n", irq);
desc->handle(irq, desc, regs);
desc_handle_irq(irq, desc, regs);
}
irq++;
desc++;
@ -214,7 +214,7 @@ static struct irqchip imx_gpio_chip = {
.ack = imx_gpio_ack_irq,
.mask = imx_gpio_mask_irq,
.unmask = imx_gpio_unmask_irq,
.type = imx_gpio_irq_type,
.set_type = imx_gpio_irq_type,
};
void __init

View File

@ -170,7 +170,7 @@ sic_handle_irq(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
irq += IRQ_SIC_START;
desc = irq_desc + irq;
desc->handle(irq, desc, regs);
desc_handle_irq(irq, desc, regs);
} while (status);
}

View File

@ -60,7 +60,7 @@ static unsigned long iop321_gettimeoffset(void)
/*
* Now convert them to usec.
*/
usec = (unsigned long)(elapsed * (tick_nsec / 1000)) / LATCH;
usec = (unsigned long)(elapsed / (CLOCK_TICK_RATE/1000000));
return usec;
}

View File

@ -58,7 +58,7 @@ static unsigned long iop331_gettimeoffset(void)
/*
* Now convert them to usec.
*/
usec = (unsigned long)(elapsed * (tick_nsec / 1000)) / LATCH;
usec = (unsigned long)(elapsed / (CLOCK_TICK_RATE/1000000));
return usec;
}

View File

@ -317,7 +317,7 @@ static void ixp2000_GPIO_irq_handler(unsigned int irq, struct irqdesc *desc, str
for (i = 0; i <= 7; i++) {
if (status & (1<<i)) {
desc = irq_desc + i + IRQ_IXP2000_GPIO0;
desc->handle(i + IRQ_IXP2000_GPIO0, desc, regs);
desc_handle_irq(i + IRQ_IXP2000_GPIO0, desc, regs);
}
}
}
@ -380,10 +380,10 @@ static void ixp2000_GPIO_irq_unmask(unsigned int irq)
}
static struct irqchip ixp2000_GPIO_irq_chip = {
.type = ixp2000_GPIO_irq_type,
.ack = ixp2000_GPIO_irq_mask_ack,
.mask = ixp2000_GPIO_irq_mask,
.unmask = ixp2000_GPIO_irq_unmask
.ack = ixp2000_GPIO_irq_mask_ack,
.mask = ixp2000_GPIO_irq_mask,
.unmask = ixp2000_GPIO_irq_unmask,
.set_type = ixp2000_GPIO_irq_type,
};
static void ixp2000_pci_irq_mask(unsigned int irq)

View File

@ -133,7 +133,7 @@ static void ixdp2x00_irq_handler(unsigned int irq, struct irqdesc *desc, struct
struct irqdesc *cpld_desc;
int cpld_irq = IXP2000_BOARD_IRQ(0) + i;
cpld_desc = irq_desc + cpld_irq;
cpld_desc->handle(cpld_irq, cpld_desc, regs);
desc_handle_irq(cpld_irq, cpld_desc, regs);
}
}

View File

@ -82,7 +82,7 @@ static void ixdp2x01_irq_handler(unsigned int irq, struct irqdesc *desc, struct
struct irqdesc *cpld_desc;
int cpld_irq = IXP2000_BOARD_IRQ(0) + i;
cpld_desc = irq_desc + cpld_irq;
cpld_desc->handle(cpld_irq, cpld_desc, regs);
desc_handle_irq(cpld_irq, cpld_desc, regs);
}
}

View File

@ -179,17 +179,17 @@ static void ixp4xx_irq_level_unmask(unsigned int irq)
}
static struct irqchip ixp4xx_irq_level_chip = {
.ack = ixp4xx_irq_mask,
.mask = ixp4xx_irq_mask,
.unmask = ixp4xx_irq_level_unmask,
.type = ixp4xx_set_irq_type
.ack = ixp4xx_irq_mask,
.mask = ixp4xx_irq_mask,
.unmask = ixp4xx_irq_level_unmask,
.set_type = ixp4xx_set_irq_type,
};
static struct irqchip ixp4xx_irq_edge_chip = {
.ack = ixp4xx_irq_ack,
.mask = ixp4xx_irq_mask,
.unmask = ixp4xx_irq_unmask,
.type = ixp4xx_set_irq_type
.ack = ixp4xx_irq_ack,
.mask = ixp4xx_irq_mask,
.unmask = ixp4xx_irq_unmask,
.set_type = ixp4xx_set_irq_type,
};
static void ixp4xx_config_irq(unsigned irq, enum ixp4xx_irq_type type)

View File

@ -13,4 +13,4 @@ extern struct sys_timer lh7a40x_timer;
extern void lh7a400_init_irq (void);
extern void lh7a404_init_irq (void);
#define IRQ_DISPATCH(irq) irq_desc[irq].handle ((irq), &irq_desc[irq], regs)
#define IRQ_DISPATCH(irq) desc_handle_irq((irq),(irq_desc + irq), regs)

View File

@ -102,7 +102,7 @@ void innovator_fpga_IRQ_demux(unsigned int irq, struct irqdesc *desc,
fpga_irq++, stat >>= 1) {
if (stat & 1) {
d = irq_desc + fpga_irq;
d->handle(fpga_irq, d, regs);
desc_handle_irq(fpga_irq, d, regs);
}
}
}

View File

@ -165,10 +165,10 @@ static struct omap_irq_bank omap1610_irq_banks[] = {
#endif
static struct irqchip omap_irq_chip = {
.ack = omap_mask_ack_irq,
.mask = omap_mask_irq,
.unmask = omap_unmask_irq,
.wake = omap_wake_irq,
.ack = omap_mask_ack_irq,
.mask = omap_mask_irq,
.unmask = omap_unmask_irq,
.set_wake = omap_wake_irq,
};
void __init omap_init_irq(void)

View File

@ -11,7 +11,7 @@ obj-$(CONFIG_PXA27x) += pxa27x.o
obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o
obj-$(CONFIG_MACH_MAINSTONE) += mainstone.o
obj-$(CONFIG_ARCH_PXA_IDP) += idp.o
obj-$(CONFIG_PXA_SHARP_C7xx) += corgi.o corgi_ssp.o ssp.o
obj-$(CONFIG_PXA_SHARP_C7xx) += corgi.o corgi_ssp.o corgi_lcd.o ssp.o
obj-$(CONFIG_MACH_POODLE) += poodle.o
# Support for blinky lights

View File

@ -39,7 +39,6 @@
#include <asm/mach/sharpsl_param.h>
#include <asm/hardware/scoop.h>
#include <video/w100fb.h>
#include "generic.h"
@ -60,6 +59,15 @@ static struct scoop_config corgi_scoop_setup = {
.io_out = CORGI_SCOOP_IO_OUT,
};
static struct scoop_pcmcia_dev corgi_pcmcia_scoop[] = {
{
.dev = &corgiscoop_device.dev,
.irq = CORGI_IRQ_GPIO_CF_IRQ,
.cd_irq = CORGI_IRQ_GPIO_CF_CD,
.cd_irq_str = "PCMCIA0 CD",
},
};
struct platform_device corgiscoop_device = {
.name = "sharp-scoop",
.id = -1,
@ -78,7 +86,7 @@ struct platform_device corgiscoop_device = {
* also use scoop functions and this makes the power up/down order
* work correctly.
*/
static struct platform_device corgissp_device = {
struct platform_device corgissp_device = {
.name = "corgi-ssp",
.dev = {
.parent = &corgiscoop_device.dev,
@ -87,35 +95,6 @@ static struct platform_device corgissp_device = {
};
/*
* Corgi w100 Frame Buffer Device
*/
static struct w100fb_mach_info corgi_fb_info = {
.w100fb_ssp_send = corgi_ssp_lcdtg_send,
.comadj = -1,
.phadadj = -1,
};
static struct resource corgi_fb_resources[] = {
[0] = {
.start = 0x08000000,
.end = 0x08ffffff,
.flags = IORESOURCE_MEM,
},
};
static struct platform_device corgifb_device = {
.name = "w100fb",
.id = -1,
.dev = {
.platform_data = &corgi_fb_info,
.parent = &corgissp_device.dev,
},
.num_resources = ARRAY_SIZE(corgi_fb_resources),
.resource = corgi_fb_resources,
};
/*
* Corgi Backlight Device
*/
@ -128,6 +107,27 @@ static struct platform_device corgibl_device = {
};
/*
* Corgi Keyboard Device
*/
static struct platform_device corgikbd_device = {
.name = "corgi-keyboard",
.id = -1,
};
/*
* Corgi Touch Screen Device
*/
static struct platform_device corgits_device = {
.name = "corgi-ts",
.dev = {
.parent = &corgissp_device.dev,
},
.id = -1,
};
/*
* MMC/SD Device
*
@ -190,6 +190,11 @@ static void corgi_mci_setpower(struct device *dev, unsigned int vdd)
}
}
static int corgi_mci_get_ro(struct device *dev)
{
return GPLR(CORGI_GPIO_nSD_WP) & GPIO_bit(CORGI_GPIO_nSD_WP);
}
static void corgi_mci_exit(struct device *dev, void *data)
{
free_irq(CORGI_IRQ_GPIO_nSD_DETECT, data);
@ -199,11 +204,13 @@ static void corgi_mci_exit(struct device *dev, void *data)
static struct pxamci_platform_data corgi_mci_platform_data = {
.ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
.init = corgi_mci_init,
.get_ro = corgi_mci_get_ro,
.setpower = corgi_mci_setpower,
.exit = corgi_mci_exit,
};
/*
* USB Device Controller
*/
@ -229,18 +236,20 @@ static struct platform_device *devices[] __initdata = {
&corgiscoop_device,
&corgissp_device,
&corgifb_device,
&corgikbd_device,
&corgibl_device,
&corgits_device,
};
static void __init corgi_init(void)
{
corgi_fb_info.comadj=sharpsl_param.comadj;
corgi_fb_info.phadadj=sharpsl_param.phadadj;
pxa_gpio_mode(CORGI_GPIO_USB_PULLUP | GPIO_OUT);
pxa_set_udc_info(&udc_info);
pxa_set_mci_info(&corgi_mci_platform_data);
scoop_num = 1;
scoop_devs = &corgi_pcmcia_scoop[0];
platform_add_devices(devices, ARRAY_SIZE(devices));
}

View File

@ -0,0 +1,396 @@
/*
* linux/drivers/video/w100fb.c
*
* Corgi LCD Specific Code for ATI Imageon w100 (Wallaby)
*
* Copyright (C) 2005 Richard Purdie
*
* 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/delay.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <asm/arch/corgi.h>
#include <asm/mach/sharpsl_param.h>
#include <video/w100fb.h>
/* Register Addresses */
#define RESCTL_ADRS 0x00
#define PHACTRL_ADRS 0x01
#define DUTYCTRL_ADRS 0x02
#define POWERREG0_ADRS 0x03
#define POWERREG1_ADRS 0x04
#define GPOR3_ADRS 0x05
#define PICTRL_ADRS 0x06
#define POLCTRL_ADRS 0x07
/* Resgister Bit Definitions */
#define RESCTL_QVGA 0x01
#define RESCTL_VGA 0x00
#define POWER1_VW_ON 0x01 /* VW Supply FET ON */
#define POWER1_GVSS_ON 0x02 /* GVSS(-8V) Power Supply ON */
#define POWER1_VDD_ON 0x04 /* VDD(8V),SVSS(-4V) Power Supply ON */
#define POWER1_VW_OFF 0x00 /* VW Supply FET OFF */
#define POWER1_GVSS_OFF 0x00 /* GVSS(-8V) Power Supply OFF */
#define POWER1_VDD_OFF 0x00 /* VDD(8V),SVSS(-4V) Power Supply OFF */
#define POWER0_COM_DCLK 0x01 /* COM Voltage DC Bias DAC Serial Data Clock */
#define POWER0_COM_DOUT 0x02 /* COM Voltage DC Bias DAC Serial Data Out */
#define POWER0_DAC_ON 0x04 /* DAC Power Supply ON */
#define POWER0_COM_ON 0x08 /* COM Powewr Supply ON */
#define POWER0_VCC5_ON 0x10 /* VCC5 Power Supply ON */
#define POWER0_DAC_OFF 0x00 /* DAC Power Supply OFF */
#define POWER0_COM_OFF 0x00 /* COM Powewr Supply OFF */
#define POWER0_VCC5_OFF 0x00 /* VCC5 Power Supply OFF */
#define PICTRL_INIT_STATE 0x01
#define PICTRL_INIOFF 0x02
#define PICTRL_POWER_DOWN 0x04
#define PICTRL_COM_SIGNAL_OFF 0x08
#define PICTRL_DAC_SIGNAL_OFF 0x10
#define POLCTRL_SYNC_POL_FALL 0x01
#define POLCTRL_EN_POL_FALL 0x02
#define POLCTRL_DATA_POL_FALL 0x04
#define POLCTRL_SYNC_ACT_H 0x08
#define POLCTRL_EN_ACT_L 0x10
#define POLCTRL_SYNC_POL_RISE 0x00
#define POLCTRL_EN_POL_RISE 0x00
#define POLCTRL_DATA_POL_RISE 0x00
#define POLCTRL_SYNC_ACT_L 0x00
#define POLCTRL_EN_ACT_H 0x00
#define PHACTRL_PHASE_MANUAL 0x01
#define DEFAULT_PHAD_QVGA (9)
#define DEFAULT_COMADJ (125)
/*
* This is only a psuedo I2C interface. We can't use the standard kernel
* routines as the interface is write only. We just assume the data is acked...
*/
static void lcdtg_ssp_i2c_send(u8 data)
{
corgi_ssp_lcdtg_send(POWERREG0_ADRS, data);
udelay(10);
}
static void lcdtg_i2c_send_bit(u8 data)
{
lcdtg_ssp_i2c_send(data);
lcdtg_ssp_i2c_send(data | POWER0_COM_DCLK);
lcdtg_ssp_i2c_send(data);
}
static void lcdtg_i2c_send_start(u8 base)
{
lcdtg_ssp_i2c_send(base | POWER0_COM_DCLK | POWER0_COM_DOUT);
lcdtg_ssp_i2c_send(base | POWER0_COM_DCLK);
lcdtg_ssp_i2c_send(base);
}
static void lcdtg_i2c_send_stop(u8 base)
{
lcdtg_ssp_i2c_send(base);
lcdtg_ssp_i2c_send(base | POWER0_COM_DCLK);
lcdtg_ssp_i2c_send(base | POWER0_COM_DCLK | POWER0_COM_DOUT);
}
static void lcdtg_i2c_send_byte(u8 base, u8 data)
{
int i;
for (i = 0; i < 8; i++) {
if (data & 0x80)
lcdtg_i2c_send_bit(base | POWER0_COM_DOUT);
else
lcdtg_i2c_send_bit(base);
data <<= 1;
}
}
static void lcdtg_i2c_wait_ack(u8 base)
{
lcdtg_i2c_send_bit(base);
}
static void lcdtg_set_common_voltage(u8 base_data, u8 data)
{
/* Set Common Voltage to M62332FP via I2C */
lcdtg_i2c_send_start(base_data);
lcdtg_i2c_send_byte(base_data, 0x9c);
lcdtg_i2c_wait_ack(base_data);
lcdtg_i2c_send_byte(base_data, 0x00);
lcdtg_i2c_wait_ack(base_data);
lcdtg_i2c_send_byte(base_data, data);
lcdtg_i2c_wait_ack(base_data);
lcdtg_i2c_send_stop(base_data);
}
/* Set Phase Adjuct */
static void lcdtg_set_phadadj(struct w100fb_par *par)
{
int adj;
switch(par->xres) {
case 480:
case 640:
/* Setting for VGA */
adj = sharpsl_param.phadadj;
if (adj < 0) {
adj = PHACTRL_PHASE_MANUAL;
} else {
adj = ((adj & 0x0f) << 1) | PHACTRL_PHASE_MANUAL;
}
break;
case 240:
case 320:
default:
/* Setting for QVGA */
adj = (DEFAULT_PHAD_QVGA << 1) | PHACTRL_PHASE_MANUAL;
break;
}
corgi_ssp_lcdtg_send(PHACTRL_ADRS, adj);
}
static int lcd_inited;
static void lcdtg_hw_init(struct w100fb_par *par)
{
if (!lcd_inited) {
int comadj;
/* Initialize Internal Logic & Port */
corgi_ssp_lcdtg_send(PICTRL_ADRS, PICTRL_POWER_DOWN | PICTRL_INIOFF | PICTRL_INIT_STATE
| PICTRL_COM_SIGNAL_OFF | PICTRL_DAC_SIGNAL_OFF);
corgi_ssp_lcdtg_send(POWERREG0_ADRS, POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_OFF
| POWER0_COM_OFF | POWER0_VCC5_OFF);
corgi_ssp_lcdtg_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_OFF);
/* VDD(+8V), SVSS(-4V) ON */
corgi_ssp_lcdtg_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_ON);
mdelay(3);
/* DAC ON */
corgi_ssp_lcdtg_send(POWERREG0_ADRS, POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_ON
| POWER0_COM_OFF | POWER0_VCC5_OFF);
/* INIB = H, INI = L */
/* PICTL[0] = H , PICTL[1] = PICTL[2] = PICTL[4] = L */
corgi_ssp_lcdtg_send(PICTRL_ADRS, PICTRL_INIT_STATE | PICTRL_COM_SIGNAL_OFF);
/* Set Common Voltage */
comadj = sharpsl_param.comadj;
if (comadj < 0)
comadj = DEFAULT_COMADJ;
lcdtg_set_common_voltage((POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_OFF), comadj);
/* VCC5 ON, DAC ON */
corgi_ssp_lcdtg_send(POWERREG0_ADRS, POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_ON |
POWER0_COM_OFF | POWER0_VCC5_ON);
/* GVSS(-8V) ON, VDD ON */
corgi_ssp_lcdtg_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_ON | POWER1_VDD_ON);
mdelay(2);
/* COM SIGNAL ON (PICTL[3] = L) */
corgi_ssp_lcdtg_send(PICTRL_ADRS, PICTRL_INIT_STATE);
/* COM ON, DAC ON, VCC5_ON */
corgi_ssp_lcdtg_send(POWERREG0_ADRS, POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_ON
| POWER0_COM_ON | POWER0_VCC5_ON);
/* VW ON, GVSS ON, VDD ON */
corgi_ssp_lcdtg_send(POWERREG1_ADRS, POWER1_VW_ON | POWER1_GVSS_ON | POWER1_VDD_ON);
/* Signals output enable */
corgi_ssp_lcdtg_send(PICTRL_ADRS, 0);
/* Set Phase Adjuct */
lcdtg_set_phadadj(par);
/* Initialize for Input Signals from ATI */
corgi_ssp_lcdtg_send(POLCTRL_ADRS, POLCTRL_SYNC_POL_RISE | POLCTRL_EN_POL_RISE
| POLCTRL_DATA_POL_RISE | POLCTRL_SYNC_ACT_L | POLCTRL_EN_ACT_H);
udelay(1000);
lcd_inited=1;
} else {
lcdtg_set_phadadj(par);
}
switch(par->xres) {
case 480:
case 640:
/* Set Lcd Resolution (VGA) */
corgi_ssp_lcdtg_send(RESCTL_ADRS, RESCTL_VGA);
break;
case 240:
case 320:
default:
/* Set Lcd Resolution (QVGA) */
corgi_ssp_lcdtg_send(RESCTL_ADRS, RESCTL_QVGA);
break;
}
}
static void lcdtg_suspend(struct w100fb_par *par)
{
/* 60Hz x 2 frame = 16.7msec x 2 = 33.4 msec */
mdelay(34);
/* (1)VW OFF */
corgi_ssp_lcdtg_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_ON | POWER1_VDD_ON);
/* (2)COM OFF */
corgi_ssp_lcdtg_send(PICTRL_ADRS, PICTRL_COM_SIGNAL_OFF);
corgi_ssp_lcdtg_send(POWERREG0_ADRS, POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_ON);
/* (3)Set Common Voltage Bias 0V */
lcdtg_set_common_voltage(POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_ON, 0);
/* (4)GVSS OFF */
corgi_ssp_lcdtg_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_ON);
/* (5)VCC5 OFF */
corgi_ssp_lcdtg_send(POWERREG0_ADRS, POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_OFF);
/* (6)Set PDWN, INIOFF, DACOFF */
corgi_ssp_lcdtg_send(PICTRL_ADRS, PICTRL_INIOFF | PICTRL_DAC_SIGNAL_OFF |
PICTRL_POWER_DOWN | PICTRL_COM_SIGNAL_OFF);
/* (7)DAC OFF */
corgi_ssp_lcdtg_send(POWERREG0_ADRS, POWER0_DAC_OFF | POWER0_COM_OFF | POWER0_VCC5_OFF);
/* (8)VDD OFF */
corgi_ssp_lcdtg_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_OFF);
lcd_inited = 0;
}
static struct w100_tg_info corgi_lcdtg_info = {
.change=lcdtg_hw_init,
.suspend=lcdtg_suspend,
.resume=lcdtg_hw_init,
};
/*
* Corgi w100 Frame Buffer Device
*/
static struct w100_mem_info corgi_fb_mem = {
.ext_cntl = 0x00040003,
.sdram_mode_reg = 0x00650021,
.ext_timing_cntl = 0x10002a4a,
.io_cntl = 0x7ff87012,
.size = 0x1fffff,
};
static struct w100_gen_regs corgi_fb_regs = {
.lcd_format = 0x00000003,
.lcdd_cntl1 = 0x01CC0000,
.lcdd_cntl2 = 0x0003FFFF,
.genlcd_cntl1 = 0x00FFFF0D,
.genlcd_cntl2 = 0x003F3003,
.genlcd_cntl3 = 0x000102aa,
};
static struct w100_gpio_regs corgi_fb_gpio = {
.init_data1 = 0x000000bf,
.init_data2 = 0x00000000,
.gpio_dir1 = 0x00000000,
.gpio_oe1 = 0x03c0feff,
.gpio_dir2 = 0x00000000,
.gpio_oe2 = 0x00000000,
};
static struct w100_mode corgi_fb_modes[] = {
{
.xres = 480,
.yres = 640,
.left_margin = 0x56,
.right_margin = 0x55,
.upper_margin = 0x03,
.lower_margin = 0x00,
.crtc_ss = 0x82360056,
.crtc_ls = 0xA0280000,
.crtc_gs = 0x80280028,
.crtc_vpos_gs = 0x02830002,
.crtc_rev = 0x00400008,
.crtc_dclk = 0xA0000000,
.crtc_gclk = 0x8015010F,
.crtc_goe = 0x80100110,
.crtc_ps1_active = 0x41060010,
.pll_freq = 75,
.fast_pll_freq = 100,
.sysclk_src = CLK_SRC_PLL,
.sysclk_divider = 0,
.pixclk_src = CLK_SRC_PLL,
.pixclk_divider = 2,
.pixclk_divider_rotated = 6,
},{
.xres = 240,
.yres = 320,
.left_margin = 0x27,
.right_margin = 0x2e,
.upper_margin = 0x01,
.lower_margin = 0x00,
.crtc_ss = 0x81170027,
.crtc_ls = 0xA0140000,
.crtc_gs = 0xC0140014,
.crtc_vpos_gs = 0x00010141,
.crtc_rev = 0x00400008,
.crtc_dclk = 0xA0000000,
.crtc_gclk = 0x8015010F,
.crtc_goe = 0x80100110,
.crtc_ps1_active = 0x41060010,
.pll_freq = 0,
.fast_pll_freq = 0,
.sysclk_src = CLK_SRC_XTAL,
.sysclk_divider = 0,
.pixclk_src = CLK_SRC_XTAL,
.pixclk_divider = 1,
.pixclk_divider_rotated = 1,
},
};
static struct w100fb_mach_info corgi_fb_info = {
.tg = &corgi_lcdtg_info,
.init_mode = INIT_MODE_ROTATED,
.mem = &corgi_fb_mem,
.regs = &corgi_fb_regs,
.modelist = &corgi_fb_modes[0],
.num_modes = 2,
.gpio = &corgi_fb_gpio,
.xtal_freq = 12500000,
.xtal_dbl = 0,
};
static struct resource corgi_fb_resources[] = {
[0] = {
.start = 0x08000000,
.end = 0x08ffffff,
.flags = IORESOURCE_MEM,
},
};
struct platform_device corgifb_device = {
.name = "w100fb",
.id = -1,
.num_resources = ARRAY_SIZE(corgi_fb_resources),
.resource = corgi_fb_resources,
.dev = {
.platform_data = &corgi_fb_info,
.parent = &corgissp_device.dev,
},
};

View File

@ -133,7 +133,7 @@ static struct irqchip pxa_low_gpio_chip = {
.ack = pxa_ack_low_gpio,
.mask = pxa_mask_low_irq,
.unmask = pxa_unmask_low_irq,
.type = pxa_gpio_irq_type,
.set_type = pxa_gpio_irq_type,
};
/*
@ -157,7 +157,7 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irqdesc *desc,
mask >>= 2;
do {
if (mask & 1)
desc->handle(irq, desc, regs);
desc_handle_irq(irq, desc, regs);
irq++;
desc++;
mask >>= 1;
@ -172,7 +172,7 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irqdesc *desc,
desc = irq_desc + irq;
do {
if (mask & 1)
desc->handle(irq, desc, regs);
desc_handle_irq(irq, desc, regs);
irq++;
desc++;
mask >>= 1;
@ -187,7 +187,7 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irqdesc *desc,
desc = irq_desc + irq;
do {
if (mask & 1)
desc->handle(irq, desc, regs);
desc_handle_irq(irq, desc, regs);
irq++;
desc++;
mask >>= 1;
@ -203,7 +203,7 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irqdesc *desc,
desc = irq_desc + irq;
do {
if (mask & 1)
desc->handle(irq, desc, regs);
desc_handle_irq(irq, desc, regs);
irq++;
desc++;
mask >>= 1;
@ -241,7 +241,7 @@ static struct irqchip pxa_muxed_gpio_chip = {
.ack = pxa_ack_muxed_gpio,
.mask = pxa_mask_muxed_gpio,
.unmask = pxa_unmask_muxed_gpio,
.type = pxa_gpio_irq_type,
.set_type = pxa_gpio_irq_type,
};

View File

@ -84,7 +84,7 @@ static void lubbock_irq_handler(unsigned int irq, struct irqdesc *desc,
if (likely(pending)) {
irq = LUBBOCK_IRQ(0) + __ffs(pending);
desc = irq_desc + irq;
desc->handle(irq, desc, regs);
desc_handle_irq(irq, desc, regs);
}
pending = LUB_IRQ_SET_CLR & lubbock_irq_enabled;
} while (pending);

View File

@ -72,7 +72,7 @@ static void mainstone_irq_handler(unsigned int irq, struct irqdesc *desc,
if (likely(pending)) {
irq = MAINSTONE_IRQ(0) + __ffs(pending);
desc = irq_desc + irq;
desc->handle(irq, desc, regs);
desc_handle_irq(irq, desc, regs);
}
pending = MST_INTSETCLR & mainstone_irq_enabled;
} while (pending);

View File

@ -62,6 +62,15 @@ struct platform_device poodle_scoop_device = {
.resource = poodle_scoop_resources,
};
static struct scoop_pcmcia_dev poodle_pcmcia_scoop[] = {
{
.dev = &poodle_scoop_device.dev,
.irq = POODLE_IRQ_GPIO_CF_IRQ,
.cd_irq = POODLE_IRQ_GPIO_CF_CD,
.cd_irq_str = "PCMCIA0 CD",
},
};
/* LoCoMo device */
static struct resource locomo_resources[] = {
@ -147,6 +156,9 @@ static void __init poodle_init(void)
set_pxa_fb_info(&poodle_fb_info);
scoop_num = 1;
scoop_devs = &poodle_pcmcia_scoop[0];
ret = platform_add_devices(devices, ARRAY_SIZE(devices));
if (ret) {
printk(KERN_WARNING "poodle: Unable to register LoCoMo device\n");

View File

@ -2,6 +2,13 @@ if ARCH_S3C2410
menu "S3C24XX Implementations"
config MACH_ANUBIS
bool "Simtec Electronics ANUBIS"
select CPU_S3C2440
help
Say Y gere if you are using the Simtec Electronics ANUBIS
development system
config ARCH_BAST
bool "Simtec Electronics BAST (EB2410ITX)"
select CPU_S3C2410
@ -11,6 +18,14 @@ config ARCH_BAST
Product page: <http://www.simtec.co.uk/products/EB2410ITX/>.
config BAST_PC104_IRQ
bool "BAST PC104 IRQ support"
depends on ARCH_BAST
default y
help
Say Y here to enable the PC104 IRQ routing on the
Simtec BAST (EB2410ITX)
config ARCH_H1940
bool "IPAQ H1940"
select CPU_S3C2410

View File

@ -26,8 +26,13 @@ obj-$(CONFIG_CPU_S3C2440) += s3c2440.o s3c2440-dsc.o
obj-$(CONFIG_CPU_S3C2440) += s3c2440-irq.o
obj-$(CONFIG_CPU_S3C2440) += s3c2440-clock.o
# bast extras
obj-$(CONFIG_BAST_PC104_IRQ) += bast-irq.o
# machine specific support
obj-$(CONFIG_MACH_ANUBIS) += mach-anubis.o
obj-$(CONFIG_ARCH_BAST) += mach-bast.o usb-simtec.o
obj-$(CONFIG_ARCH_H1940) += mach-h1940.o
obj-$(CONFIG_MACH_N30) += mach-n30.o

View File

@ -1,6 +1,6 @@
/* linux/arch/arm/mach-s3c2410/bast-irq.c
*
* Copyright (c) 2004 Simtec Electronics
* Copyright (c) 2003,2005 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
* http://www.simtec.co.uk/products/EB2410ITX/
@ -21,7 +21,8 @@
*
* Modifications:
* 08-Jan-2003 BJD Moved from central IRQ code
*/
* 21-Aug-2005 BJD Fixed missing code and compile errors
*/
#include <linux/init.h>
@ -30,12 +31,19 @@
#include <linux/ptrace.h>
#include <linux/sysdev.h>
#include <asm/mach-types.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/mach/irq.h>
#include <asm/hardware/s3c2410/irq.h>
#include <asm/arch/regs-irq.h>
#include <asm/arch/bast-map.h>
#include <asm/arch/bast-irq.h>
#include "irq.h"
#if 0
#include <asm/debug-ll.h>
@ -79,15 +87,15 @@ bast_pc104_mask(unsigned int irqno)
temp = __raw_readb(BAST_VA_PC104_IRQMASK);
temp &= ~bast_pc104_irqmasks[irqno];
__raw_writeb(temp, BAST_VA_PC104_IRQMASK);
if (temp == 0)
bast_extint_mask(IRQ_ISA);
}
static void
bast_pc104_ack(unsigned int irqno)
bast_pc104_maskack(unsigned int irqno)
{
bast_extint_ack(IRQ_ISA);
struct irqdesc *desc = irq_desc + IRQ_ISA;
bast_pc104_mask(irqno);
desc->chip->ack(IRQ_ISA);
}
static void
@ -98,14 +106,12 @@ bast_pc104_unmask(unsigned int irqno)
temp = __raw_readb(BAST_VA_PC104_IRQMASK);
temp |= bast_pc104_irqmasks[irqno];
__raw_writeb(temp, BAST_VA_PC104_IRQMASK);
bast_extint_unmask(IRQ_ISA);
}
static struct bast_pc104_chip = {
static struct irqchip bast_pc104_chip = {
.mask = bast_pc104_mask,
.unmask = bast_pc104_unmask,
.ack = bast_pc104_ack
.ack = bast_pc104_maskack
};
static void
@ -119,14 +125,49 @@ bast_irq_pc104_demux(unsigned int irq,
stat = __raw_readb(BAST_VA_PC104_IRQREQ) & 0xf;
for (i = 0; i < 4 && stat != 0; i++) {
if (stat & 1) {
irqno = bast_pc104_irqs[i];
desc = irq_desc + irqno;
if (unlikely(stat == 0)) {
/* ack if we get an irq with nothing (ie, startup) */
desc->handle(irqno, desc, regs);
desc = irq_desc + IRQ_ISA;
desc->chip->ack(IRQ_ISA);
} else {
/* handle the IRQ */
for (i = 0; stat != 0; i++, stat >>= 1) {
if (stat & 1) {
irqno = bast_pc104_irqs[i];
desc_handle_irq(irqno, irq_desc + irqno, regs);
}
}
stat >>= 1;
}
}
static __init int bast_irq_init(void)
{
unsigned int i;
if (machine_is_bast()) {
printk(KERN_INFO "BAST PC104 IRQ routing, (c) 2005 Simtec Electronics\n");
/* zap all the IRQs */
__raw_writeb(0x0, BAST_VA_PC104_IRQMASK);
set_irq_chained_handler(IRQ_ISA, bast_irq_pc104_demux);
/* reigster our IRQs */
for (i = 0; i < 4; i++) {
unsigned int irqno = bast_pc104_irqs[i];
set_irq_chip(irqno, &bast_pc104_chip);
set_irq_handler(irqno, do_level_IRQ);
set_irq_flags(irqno, IRQF_VALID);
}
}
return 0;
}
arch_initcall(bast_irq_init);

View File

@ -184,14 +184,14 @@ struct irqchip s3c_irq_level_chip = {
.ack = s3c_irq_maskack,
.mask = s3c_irq_mask,
.unmask = s3c_irq_unmask,
.wake = s3c_irq_wake
.set_wake = s3c_irq_wake
};
static struct irqchip s3c_irq_chip = {
.ack = s3c_irq_ack,
.mask = s3c_irq_mask,
.unmask = s3c_irq_unmask,
.wake = s3c_irq_wake
.set_wake = s3c_irq_wake
};
/* S3C2410_EINTMASK
@ -350,16 +350,16 @@ static struct irqchip s3c_irqext_chip = {
.mask = s3c_irqext_mask,
.unmask = s3c_irqext_unmask,
.ack = s3c_irqext_ack,
.type = s3c_irqext_type,
.wake = s3c_irqext_wake
.set_type = s3c_irqext_type,
.set_wake = s3c_irqext_wake
};
static struct irqchip s3c_irq_eint0t4 = {
.ack = s3c_irq_ack,
.mask = s3c_irq_mask,
.unmask = s3c_irq_unmask,
.wake = s3c_irq_wake,
.type = s3c_irqext_type,
.set_wake = s3c_irq_wake,
.set_type = s3c_irqext_type,
};
/* mask values for the parent registers for each of the interrupt types */
@ -496,11 +496,11 @@ static void s3c_irq_demux_adc(unsigned int irq,
if (subsrc != 0) {
if (subsrc & 1) {
mydesc = irq_desc + IRQ_TC;
mydesc->handle( IRQ_TC, mydesc, regs);
desc_handle_irq(IRQ_TC, mydesc, regs);
}
if (subsrc & 2) {
mydesc = irq_desc + IRQ_ADC;
mydesc->handle(IRQ_ADC, mydesc, regs);
desc_handle_irq(IRQ_ADC, mydesc, regs);
}
}
}
@ -529,17 +529,17 @@ static void s3c_irq_demux_uart(unsigned int start,
desc = irq_desc + start;
if (subsrc & 1)
desc->handle(start, desc, regs);
desc_handle_irq(start, desc, regs);
desc++;
if (subsrc & 2)
desc->handle(start+1, desc, regs);
desc_handle_irq(start+1, desc, regs);
desc++;
if (subsrc & 4)
desc->handle(start+2, desc, regs);
desc_handle_irq(start+2, desc, regs);
}
}

View File

@ -0,0 +1,270 @@
/* linux/arch/arm/mach-s3c2410/mach-anubis.c
*
* Copyright (c) 2003-2005 Simtec Electronics
* http://armlinux.simtec.co.uk/
* Ben Dooks <ben@simtec.co.uk>
*
*
*
* 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.
*
* Modifications:
* 02-May-2005 BJD Copied from mach-bast.c
*/
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/timer.h>
#include <linux/init.h>
#include <linux/device.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/irq.h>
#include <asm/arch/anubis-map.h>
#include <asm/arch/anubis-irq.h>
#include <asm/arch/anubis-cpld.h>
#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/mach-types.h>
#include <asm/arch/regs-serial.h>
#include <asm/arch/regs-gpio.h>
#include <asm/arch/regs-mem.h>
#include <asm/arch/regs-lcd.h>
#include <asm/arch/nand.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/nand_ecc.h>
#include <linux/mtd/partitions.h>
#include "clock.h"
#include "devs.h"
#include "cpu.h"
#define COPYRIGHT ", (c) 2005 Simtec Electronics"
static struct map_desc anubis_iodesc[] __initdata = {
/* ISA IO areas */
{ (u32)S3C24XX_VA_ISA_BYTE, 0x0, SZ_16M, MT_DEVICE },
{ (u32)S3C24XX_VA_ISA_WORD, 0x0, SZ_16M, MT_DEVICE },
/* we could possibly compress the next set down into a set of smaller tables
* pagetables, but that would mean using an L2 section, and it still means
* we cannot actually feed the same register to an LDR due to 16K spacing
*/
/* CPLD control registers */
{ (u32)ANUBIS_VA_CTRL1, ANUBIS_PA_CTRL1, SZ_4K, MT_DEVICE },
{ (u32)ANUBIS_VA_CTRL2, ANUBIS_PA_CTRL2, SZ_4K, MT_DEVICE },
/* IDE drives */
{ (u32)ANUBIS_IDEPRI, S3C2410_CS3, SZ_1M, MT_DEVICE },
{ (u32)ANUBIS_IDEPRIAUX, S3C2410_CS3+(1<<26), SZ_1M, MT_DEVICE },
{ (u32)ANUBIS_IDESEC, S3C2410_CS4, SZ_1M, MT_DEVICE },
{ (u32)ANUBIS_IDESECAUX, S3C2410_CS4+(1<<26), SZ_1M, MT_DEVICE },
};
#define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK
#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
static struct s3c24xx_uart_clksrc anubis_serial_clocks[] = {
[0] = {
.name = "uclk",
.divisor = 1,
.min_baud = 0,
.max_baud = 0,
},
[1] = {
.name = "pclk",
.divisor = 1,
.min_baud = 0,
.max_baud = 0.
}
};
static struct s3c2410_uartcfg anubis_uartcfgs[] = {
[0] = {
.hwport = 0,
.flags = 0,
.ucon = UCON,
.ulcon = ULCON,
.ufcon = UFCON,
.clocks = anubis_serial_clocks,
.clocks_size = ARRAY_SIZE(anubis_serial_clocks)
},
[1] = {
.hwport = 2,
.flags = 0,
.ucon = UCON,
.ulcon = ULCON,
.ufcon = UFCON,
.clocks = anubis_serial_clocks,
.clocks_size = ARRAY_SIZE(anubis_serial_clocks)
},
};
/* NAND Flash on Anubis board */
static int external_map[] = { 2 };
static int chip0_map[] = { 0 };
static int chip1_map[] = { 1 };
struct mtd_partition anubis_default_nand_part[] = {
[0] = {
.name = "Boot Agent",
.size = SZ_16K,
.offset = 0
},
[1] = {
.name = "/boot",
.size = SZ_4M - SZ_16K,
.offset = SZ_16K,
},
[2] = {
.name = "user1",
.offset = SZ_4M,
.size = SZ_32M - SZ_4M,
},
[3] = {
.name = "user2",
.offset = SZ_32M,
.size = MTDPART_SIZ_FULL,
}
};
/* the Anubis has 3 selectable slots for nand-flash, the two
* on-board chip areas, as well as the external slot.
*
* Note, there is no current hot-plug support for the External
* socket.
*/
static struct s3c2410_nand_set anubis_nand_sets[] = {
[1] = {
.name = "External",
.nr_chips = 1,
.nr_map = external_map,
.nr_partitions = ARRAY_SIZE(anubis_default_nand_part),
.partitions = anubis_default_nand_part
},
[0] = {
.name = "chip0",
.nr_chips = 1,
.nr_map = chip0_map,
.nr_partitions = ARRAY_SIZE(anubis_default_nand_part),
.partitions = anubis_default_nand_part
},
[2] = {
.name = "chip1",
.nr_chips = 1,
.nr_map = chip1_map,
.nr_partitions = ARRAY_SIZE(anubis_default_nand_part),
.partitions = anubis_default_nand_part
},
};
static void anubis_nand_select(struct s3c2410_nand_set *set, int slot)
{
unsigned int tmp;
slot = set->nr_map[slot] & 3;
pr_debug("anubis_nand: selecting slot %d (set %p,%p)\n",
slot, set, set->nr_map);
tmp = __raw_readb(ANUBIS_VA_CTRL1);
tmp &= ~ANUBIS_CTRL1_NANDSEL;
tmp |= slot;
pr_debug("anubis_nand: ctrl1 now %02x\n", tmp);
__raw_writeb(tmp, ANUBIS_VA_CTRL1);
}
static struct s3c2410_platform_nand anubis_nand_info = {
.tacls = 25,
.twrph0 = 80,
.twrph1 = 80,
.nr_sets = ARRAY_SIZE(anubis_nand_sets),
.sets = anubis_nand_sets,
.select_chip = anubis_nand_select,
};
/* Standard Anubis devices */
static struct platform_device *anubis_devices[] __initdata = {
&s3c_device_usb,
&s3c_device_wdt,
&s3c_device_adc,
&s3c_device_i2c,
&s3c_device_rtc,
&s3c_device_nand,
};
static struct clk *anubis_clocks[] = {
&s3c24xx_dclk0,
&s3c24xx_dclk1,
&s3c24xx_clkout0,
&s3c24xx_clkout1,
&s3c24xx_uclk,
};
static struct s3c24xx_board anubis_board __initdata = {
.devices = anubis_devices,
.devices_count = ARRAY_SIZE(anubis_devices),
.clocks = anubis_clocks,
.clocks_count = ARRAY_SIZE(anubis_clocks)
};
void __init anubis_map_io(void)
{
/* initialise the clocks */
s3c24xx_dclk0.parent = NULL;
s3c24xx_dclk0.rate = 12*1000*1000;
s3c24xx_dclk1.parent = NULL;
s3c24xx_dclk1.rate = 24*1000*1000;
s3c24xx_clkout0.parent = &s3c24xx_dclk0;
s3c24xx_clkout1.parent = &s3c24xx_dclk1;
s3c24xx_uclk.parent = &s3c24xx_clkout1;
s3c_device_nand.dev.platform_data = &anubis_nand_info;
s3c24xx_init_io(anubis_iodesc, ARRAY_SIZE(anubis_iodesc));
s3c24xx_init_clocks(0);
s3c24xx_init_uarts(anubis_uartcfgs, ARRAY_SIZE(anubis_uartcfgs));
s3c24xx_set_board(&anubis_board);
/* ensure that the GPIO is setup */
s3c2410_gpio_setpin(S3C2410_GPA0, 1);
}
MACHINE_START(ANUBIS, "Simtec-Anubis")
/* Maintainer: Ben Dooks <ben@simtec.co.uk> */
.phys_ram = S3C2410_SDRAM_PA,
.phys_io = S3C2410_PA_UART,
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
.map_io = anubis_map_io,
.init_irq = s3c24xx_init_irq,
.timer = &s3c24xx_timer,
MACHINE_END

View File

@ -110,34 +110,24 @@ void __init n30_init_irq(void)
s3c24xx_init_irq();
}
static int n30_usbstart_thread(void *unused)
{
/* Turn off suspend on both USB ports, and switch the
* selectable USB port to USB device mode. */
writel(readl(S3C2410_MISCCR) & ~0x00003008, S3C2410_MISCCR);
/* Turn off the D+ pull up for 3 seconds so that the USB host
* at the other end will do a rescan of the USB bus. */
s3c2410_gpio_setpin(S3C2410_GPB3, 0);
msleep_interruptible(3*HZ);
s3c2410_gpio_setpin(S3C2410_GPB3, 1);
return 0;
}
/* GPB3 is the line that controls the pull-up for the USB D+ line */
void __init n30_init(void)
{
s3c_device_i2c.dev.platform_data = &n30_i2ccfg;
kthread_run(n30_usbstart_thread, NULL, "n30_usbstart");
/* Turn off suspend on both USB ports, and switch the
* selectable USB port to USB device mode. */
s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST |
S3C2410_MISCCR_USBSUSPND0 |
S3C2410_MISCCR_USBSUSPND1, 0x0);
}
MACHINE_START(N30, "Acer-N30")
/* Maintainer: Christer Weinigel <christer@weinigel.se>, Ben Dooks <ben-linux@fluff.org> */
/* Maintainer: Christer Weinigel <christer@weinigel.se>,
Ben Dooks <ben-linux@fluff.org>
*/
.phys_ram = S3C2410_SDRAM_PA,
.phys_io = S3C2410_PA_UART,
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,

View File

@ -48,7 +48,7 @@ static __init int pm_simtec_init(void)
/* check which machine we are running on */
if (!machine_is_bast() && !machine_is_vr1000())
if (!machine_is_bast() && !machine_is_vr1000() && !machine_is_anubis())
return 0;
printk(KERN_INFO "Simtec Board Power Manangement" COPYRIGHT "\n");

View File

@ -585,14 +585,16 @@ static int s3c2410_pm_enter(suspend_state_t state)
s3c2410_pm_check_store();
// need to make some form of time-delta
/* send the cpu to sleep... */
__raw_writel(0x00, S3C2410_CLKCON); /* turn off clocks over sleep */
s3c2410_cpu_suspend(regs_save);
/* restore the cpu state */
cpu_init();
/* unset the return-from-sleep flag, to ensure reset */
tmp = __raw_readl(S3C2410_GSTATUS2);

View File

@ -64,11 +64,11 @@ static void s3c_irq_demux_wdtac97(unsigned int irq,
if (subsrc != 0) {
if (subsrc & 1) {
mydesc = irq_desc + IRQ_S3C2440_WDT;
mydesc->handle( IRQ_S3C2440_WDT, mydesc, regs);
desc_handle_irq(IRQ_S3C2440_WDT, mydesc, regs);
}
if (subsrc & 2) {
mydesc = irq_desc + IRQ_S3C2440_AC97;
mydesc->handle(IRQ_S3C2440_AC97, mydesc, regs);
desc_handle_irq(IRQ_S3C2440_AC97, mydesc, regs);
}
}
}
@ -122,11 +122,11 @@ static void s3c_irq_demux_cam(unsigned int irq,
if (subsrc != 0) {
if (subsrc & 1) {
mydesc = irq_desc + IRQ_S3C2440_CAM_C;
mydesc->handle( IRQ_S3C2440_WDT, mydesc, regs);
desc_handle_irq(IRQ_S3C2440_CAM_C, mydesc, regs);
}
if (subsrc & 2) {
mydesc = irq_desc + IRQ_S3C2440_CAM_P;
mydesc->handle(IRQ_S3C2440_AC97, mydesc, regs);
desc_handle_irq(IRQ_S3C2440_CAM_P, mydesc, regs);
}
}
}

View File

@ -164,7 +164,7 @@ static void s3c2410_timer_setup (void)
/* configure the system for whichever machine is in use */
if (machine_is_bast() || machine_is_vr1000()) {
if (machine_is_bast() || machine_is_vr1000() || machine_is_anubis()) {
/* timer is at 12MHz, scaler is 1 */
timer_usec_ticks = timer_mask_usec_ticks(1, 12000000);
tcnt = 12000000 / HZ;

View File

@ -98,8 +98,8 @@ static struct irqchip sa1100_low_gpio_chip = {
.ack = sa1100_low_gpio_ack,
.mask = sa1100_low_gpio_mask,
.unmask = sa1100_low_gpio_unmask,
.type = sa1100_gpio_type,
.wake = sa1100_low_gpio_wake,
.set_type = sa1100_gpio_type,
.set_wake = sa1100_low_gpio_wake,
};
/*
@ -126,7 +126,7 @@ sa1100_high_gpio_handler(unsigned int irq, struct irqdesc *desc,
mask >>= 11;
do {
if (mask & 1)
desc->handle(irq, desc, regs);
desc_handle_irq(irq, desc, regs);
mask >>= 1;
irq++;
desc++;
@ -181,8 +181,8 @@ static struct irqchip sa1100_high_gpio_chip = {
.ack = sa1100_high_gpio_ack,
.mask = sa1100_high_gpio_mask,
.unmask = sa1100_high_gpio_unmask,
.type = sa1100_gpio_type,
.wake = sa1100_high_gpio_wake,
.set_type = sa1100_gpio_type,
.set_wake = sa1100_high_gpio_wake,
};
/*

View File

@ -61,12 +61,12 @@ neponset_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *reg
if (irr & IRR_ETHERNET) {
d = irq_desc + IRQ_NEPONSET_SMC9196;
d->handle(IRQ_NEPONSET_SMC9196, d, regs);
desc_handle_irq(IRQ_NEPONSET_SMC9196, d, regs);
}
if (irr & IRR_USAR) {
d = irq_desc + IRQ_NEPONSET_USAR;
d->handle(IRQ_NEPONSET_USAR, d, regs);
desc_handle_irq(IRQ_NEPONSET_USAR, d, regs);
}
desc->chip->unmask(irq);
@ -74,7 +74,7 @@ neponset_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *reg
if (irr & IRR_SA1111) {
d = irq_desc + IRQ_NEPONSET_SA1111;
d->handle(IRQ_NEPONSET_SA1111, d, regs);
desc_handle_irq(IRQ_NEPONSET_SA1111, d, regs);
}
}
}

View File

@ -108,7 +108,7 @@ sic_handle_irq(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
irq += IRQ_SIC_START;
desc = irq_desc + irq;
desc->handle(irq, desc, regs);
desc_handle_irq(irq, desc, regs);
} while (status);
}

View File

@ -38,8 +38,8 @@ ENTRY(cpu_arm7_data_abort)
mrc p15, 0, r1, c5, c0, 0 @ get FSR
mrc p15, 0, r0, c6, c0, 0 @ get FAR
ldr r8, [r0] @ read arm instruction
tst r8, #1 << 20 @ L = 1 -> write?
orreq r1, r1, #1 << 8 @ yes.
tst r8, #1 << 20 @ L = 0 -> write?
orreq r1, r1, #1 << 11 @ yes.
and r7, r8, #15 << 24
add pc, pc, r7, lsr #22 @ Now branch to the relevant processing routine
nop
@ -71,8 +71,8 @@ ENTRY(cpu_arm6_data_abort)
mrc p15, 0, r1, c5, c0, 0 @ get FSR
mrc p15, 0, r0, c6, c0, 0 @ get FAR
ldr r8, [r2] @ read arm instruction
tst r8, #1 << 20 @ L = 1 -> write?
orreq r1, r1, #1 << 8 @ yes.
tst r8, #1 << 20 @ L = 0 -> write?
orreq r1, r1, #1 << 11 @ yes.
and r7, r8, #14 << 24
teq r7, #8 << 24 @ was it ldm/stm
movne pc, lr

View File

@ -91,6 +91,13 @@ config OMAP_32K_TIMER_HZ
Kernel internal timer frequency should be a divisor of 32768,
such as 64 or 128.
config OMAP_DM_TIMER
bool "Use dual-mode timer"
default n
depends on ARCH_OMAP16XX
help
Select this option if you want to use OMAP Dual-Mode timers.
choice
prompt "Low-level debug console UART"
depends on ARCH_OMAP
@ -107,6 +114,15 @@ config OMAP_LL_DEBUG_UART3
endchoice
config OMAP_SERIAL_WAKE
bool "Enable wake-up events for serial ports"
depends OMAP_MUX
default y
help
Select this option if you want to have your system wake up
to data on the serial RX line. This allows you to wake the
system from serial console.
endmenu
endif

View File

@ -3,7 +3,7 @@
#
# Common support
obj-y := common.o dma.o clock.o mux.o gpio.o mcbsp.o usb.o
obj-y := common.o sram.o sram-fn.o clock.o dma.o mux.o gpio.o mcbsp.o usb.o
obj-m :=
obj-n :=
obj- :=
@ -15,3 +15,5 @@ obj-$(CONFIG_ARCH_OMAP16XX) += ocpi.o
obj-$(CONFIG_PM) += pm.o sleep.o
obj-$(CONFIG_CPU_FREQ) += cpu-omap.o
obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o

View File

@ -21,6 +21,7 @@
#include <asm/arch/usb.h>
#include "clock.h"
#include "sram.h"
static LIST_HEAD(clocks);
static DECLARE_MUTEX(clocks_sem);
@ -141,7 +142,7 @@ static struct clk arm_ck = {
static struct clk armper_ck = {
.name = "armper_ck",
.parent = &ck_dpll1,
.flags = CLOCK_IN_OMAP730 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
RATE_CKCTL,
.enable_reg = ARM_IDLECT2,
.enable_bit = EN_PERCK,
@ -385,7 +386,8 @@ static struct clk uart2_ck = {
.name = "uart2_ck",
/* Direct from ULPD, no parent */
.rate = 12000000,
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | ENABLE_REG_32BIT,
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | ENABLE_REG_32BIT |
ALWAYS_ENABLED,
.enable_reg = MOD_CONF_CTRL_0,
.enable_bit = 30, /* Chooses between 12MHz and 48MHz */
.set_rate = &set_uart_rate,
@ -443,6 +445,15 @@ static struct clk usb_hhc_ck16xx = {
.enable_bit = 8 /* UHOST_EN */,
};
static struct clk usb_dc_ck = {
.name = "usb_dc_ck",
/* Direct from ULPD, no parent */
.rate = 48000000,
.flags = CLOCK_IN_OMAP16XX | RATE_FIXED,
.enable_reg = SOFT_REQ_REG,
.enable_bit = 4,
};
static struct clk mclk_1510 = {
.name = "mclk",
/* Direct from ULPD, no parent. May be enabled by ext hardware. */
@ -552,6 +563,7 @@ static struct clk * onchip_clks[] = {
&uart3_16xx,
&usb_clko,
&usb_hhc_ck1510, &usb_hhc_ck16xx,
&usb_dc_ck,
&mclk_1510, &mclk_16xx,
&bclk_1510, &bclk_16xx,
&mmc1_ck,
@ -946,14 +958,13 @@ static int select_table_rate(struct clk * clk, unsigned long rate)
if (!ptr->rate)
return -EINVAL;
if (!ptr->rate)
return -EINVAL;
/*
* In most cases we should not need to reprogram DPLL.
* Reprogramming the DPLL is tricky, it must be done from SRAM.
*/
omap_sram_reprogram_clock(ptr->dpllctl_val, ptr->ckctl_val);
if (unlikely(ck_dpll1.rate == 0)) {
omap_writew(ptr->dpllctl_val, DPLL_CTL);
ck_dpll1.rate = ptr->pll_rate;
}
omap_writew(ptr->ckctl_val, ARM_CKCTL);
ck_dpll1.rate = ptr->pll_rate;
propagate_rate(&ck_dpll1);
return 0;
}
@ -1224,9 +1235,11 @@ int __init clk_init(void)
#endif
/* Cache rates for clocks connected to ck_ref (not dpll1) */
propagate_rate(&ck_ref);
printk(KERN_INFO "Clocking rate (xtal/DPLL1/MPU): %ld.%01ld/%ld/%ld MHz\n",
printk(KERN_INFO "Clocking rate (xtal/DPLL1/MPU): "
"%ld.%01ld/%ld.%01ld/%ld.%01ld MHz\n",
ck_ref.rate / 1000000, (ck_ref.rate / 100000) % 10,
ck_dpll1.rate, arm_ck.rate);
ck_dpll1.rate / 1000000, (ck_dpll1.rate / 100000) % 10,
arm_ck.rate / 1000000, (arm_ck.rate / 100000) % 10);
#ifdef CONFIG_MACH_OMAP_PERSEUS2
/* Select slicer output as OMAP input clock */
@ -1271,7 +1284,9 @@ static int __init omap_late_clk_reset(void)
struct clk *p;
__u32 regval32;
omap_writew(0, SOFT_REQ_REG);
/* USB_REQ_EN will be disabled later if necessary (usb_dc_ck) */
regval32 = omap_readw(SOFT_REQ_REG) & (1 << 4);
omap_writew(regval32, SOFT_REQ_REG);
omap_writew(0, SOFT_REQ_REG2);
list_for_each_entry(p, &clocks, node) {

View File

@ -26,6 +26,7 @@
#include <asm/hardware/clock.h>
#include <asm/io.h>
#include <asm/mach-types.h>
#include <asm/setup.h>
#include <asm/arch/board.h>
#include <asm/arch/mux.h>
@ -35,11 +36,11 @@
#define NO_LENGTH_CHECK 0xffffffff
extern int omap_bootloader_tag_len;
extern u8 omap_bootloader_tag[];
unsigned char omap_bootloader_tag[512];
int omap_bootloader_tag_len;
struct omap_board_config_kernel *omap_board_config;
int omap_board_config_size = 0;
int omap_board_config_size;
static const void *get_config(u16 tag, size_t len, int skip, size_t *len_out)
{

View File

@ -425,7 +425,7 @@ static int dma_handle_ch(int ch)
dma_chan[ch + 6].saved_csr = csr >> 7;
csr &= 0x7f;
}
if (!csr)
if ((csr & 0x3f) == 0)
return 0;
if (unlikely(dma_chan[ch].dev_id == -1)) {
printk(KERN_WARNING "Spurious interrupt from DMA channel %d (CSR %04x)\n",
@ -890,11 +890,11 @@ void omap_enable_lcd_dma(void)
w |= 1 << 8;
omap_writew(w, OMAP1610_DMA_LCD_CTRL);
lcd_dma.active = 1;
w = omap_readw(OMAP1610_DMA_LCD_CCR);
w |= 1 << 7;
omap_writew(w, OMAP1610_DMA_LCD_CCR);
lcd_dma.active = 1;
}
void omap_setup_lcd_dma(void)
@ -965,8 +965,8 @@ void omap_clear_dma(int lch)
*/
dma_addr_t omap_get_dma_src_pos(int lch)
{
return (dma_addr_t) (OMAP_DMA_CSSA_L(lch) |
(OMAP_DMA_CSSA_U(lch) << 16));
return (dma_addr_t) (omap_readw(OMAP_DMA_CSSA_L(lch)) |
(omap_readw(OMAP_DMA_CSSA_U(lch)) << 16));
}
/*
@ -979,8 +979,18 @@ dma_addr_t omap_get_dma_src_pos(int lch)
*/
dma_addr_t omap_get_dma_dst_pos(int lch)
{
return (dma_addr_t) (OMAP_DMA_CDSA_L(lch) |
(OMAP_DMA_CDSA_U(lch) << 16));
return (dma_addr_t) (omap_readw(OMAP_DMA_CDSA_L(lch)) |
(omap_readw(OMAP_DMA_CDSA_U(lch)) << 16));
}
/*
* Returns current source transfer counting for the given DMA channel.
* Can be used to monitor the progress of a transfer inside a block.
* It must be called with disabled interrupts.
*/
int omap_get_dma_src_addr_counter(int lch)
{
return (dma_addr_t) omap_readw(OMAP_DMA_CSAC(lch));
}
int omap_dma_running(void)
@ -1076,6 +1086,7 @@ arch_initcall(omap_init_dma);
EXPORT_SYMBOL(omap_get_dma_src_pos);
EXPORT_SYMBOL(omap_get_dma_dst_pos);
EXPORT_SYMBOL(omap_get_dma_src_addr_counter);
EXPORT_SYMBOL(omap_clear_dma);
EXPORT_SYMBOL(omap_set_dma_priority);
EXPORT_SYMBOL(omap_request_dma);

View File

@ -0,0 +1,260 @@
/*
* linux/arch/arm/plat-omap/dmtimer.c
*
* OMAP Dual-Mode Timers
*
* Copyright (C) 2005 Nokia Corporation
* Author: Lauri Leukkunen <lauri.leukkunen@nokia.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* 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.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/init.h>
#include <asm/arch/hardware.h>
#include <asm/arch/dmtimer.h>
#include <asm/io.h>
#include <asm/arch/irqs.h>
#include <linux/spinlock.h>
#include <linux/list.h>
#define OMAP_TIMER_COUNT 8
#define OMAP_TIMER_ID_REG 0x00
#define OMAP_TIMER_OCP_CFG_REG 0x10
#define OMAP_TIMER_SYS_STAT_REG 0x14
#define OMAP_TIMER_STAT_REG 0x18
#define OMAP_TIMER_INT_EN_REG 0x1c
#define OMAP_TIMER_WAKEUP_EN_REG 0x20
#define OMAP_TIMER_CTRL_REG 0x24
#define OMAP_TIMER_COUNTER_REG 0x28
#define OMAP_TIMER_LOAD_REG 0x2c
#define OMAP_TIMER_TRIGGER_REG 0x30
#define OMAP_TIMER_WRITE_PEND_REG 0x34
#define OMAP_TIMER_MATCH_REG 0x38
#define OMAP_TIMER_CAPTURE_REG 0x3c
#define OMAP_TIMER_IF_CTRL_REG 0x40
static struct dmtimer_info_struct {
struct list_head unused_timers;
struct list_head reserved_timers;
} dm_timer_info;
static struct omap_dm_timer dm_timers[] = {
{ .base=0xfffb1400, .irq=INT_1610_GPTIMER1 },
{ .base=0xfffb1c00, .irq=INT_1610_GPTIMER2 },
{ .base=0xfffb2400, .irq=INT_1610_GPTIMER3 },
{ .base=0xfffb2c00, .irq=INT_1610_GPTIMER4 },
{ .base=0xfffb3400, .irq=INT_1610_GPTIMER5 },
{ .base=0xfffb3c00, .irq=INT_1610_GPTIMER6 },
{ .base=0xfffb4400, .irq=INT_1610_GPTIMER7 },
{ .base=0xfffb4c00, .irq=INT_1610_GPTIMER8 },
{ .base=0x0 },
};
static spinlock_t dm_timer_lock;
inline void omap_dm_timer_write_reg(struct omap_dm_timer *timer, int reg, u32 value)
{
omap_writel(value, timer->base + reg);
while (omap_dm_timer_read_reg(timer, OMAP_TIMER_WRITE_PEND_REG))
;
}
u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, int reg)
{
return omap_readl(timer->base + reg);
}
int omap_dm_timers_active(void)
{
struct omap_dm_timer *timer;
for (timer = &dm_timers[0]; timer->base; ++timer)
if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) &
OMAP_TIMER_CTRL_ST)
return 1;
return 0;
}
void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
{
int n = (timer - dm_timers) << 1;
u32 l;
l = omap_readl(MOD_CONF_CTRL_1) & ~(0x03 << n);
l |= source << n;
omap_writel(l, MOD_CONF_CTRL_1);
}
static void omap_dm_timer_reset(struct omap_dm_timer *timer)
{
/* Reset and set posted mode */
omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_REG, 0x02);
omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_ARMXOR);
}
struct omap_dm_timer * omap_dm_timer_request(void)
{
struct omap_dm_timer *timer = NULL;
unsigned long flags;
spin_lock_irqsave(&dm_timer_lock, flags);
if (!list_empty(&dm_timer_info.unused_timers)) {
timer = (struct omap_dm_timer *)
dm_timer_info.unused_timers.next;
list_move_tail((struct list_head *)timer,
&dm_timer_info.reserved_timers);
}
spin_unlock_irqrestore(&dm_timer_lock, flags);
return timer;
}
void omap_dm_timer_free(struct omap_dm_timer *timer)
{
unsigned long flags;
omap_dm_timer_reset(timer);
spin_lock_irqsave(&dm_timer_lock, flags);
list_move_tail((struct list_head *)timer, &dm_timer_info.unused_timers);
spin_unlock_irqrestore(&dm_timer_lock, flags);
}
void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
unsigned int value)
{
omap_dm_timer_write_reg(timer, OMAP_TIMER_INT_EN_REG, value);
}
unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
{
return omap_dm_timer_read_reg(timer, OMAP_TIMER_STAT_REG);
}
void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
{
omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG, value);
}
void omap_dm_timer_enable_autoreload(struct omap_dm_timer *timer)
{
u32 l;
l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
l |= OMAP_TIMER_CTRL_AR;
omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
}
void omap_dm_timer_trigger(struct omap_dm_timer *timer)
{
omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 1);
}
void omap_dm_timer_set_trigger(struct omap_dm_timer *timer, unsigned int value)
{
u32 l;
l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
l |= value & 0x3;
omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
}
void omap_dm_timer_start(struct omap_dm_timer *timer)
{
u32 l;
l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
l |= OMAP_TIMER_CTRL_ST;
omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
}
void omap_dm_timer_stop(struct omap_dm_timer *timer)
{
u32 l;
l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
l &= ~0x1;
omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
}
unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
{
return omap_dm_timer_read_reg(timer, OMAP_TIMER_COUNTER_REG);
}
void omap_dm_timer_reset_counter(struct omap_dm_timer *timer)
{
omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, 0);
}
void omap_dm_timer_set_load(struct omap_dm_timer *timer, unsigned int load)
{
omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
}
void omap_dm_timer_set_match(struct omap_dm_timer *timer, unsigned int match)
{
omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match);
}
void omap_dm_timer_enable_compare(struct omap_dm_timer *timer)
{
u32 l;
l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
l |= OMAP_TIMER_CTRL_CE;
omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
}
static inline void __dm_timer_init(void)
{
struct omap_dm_timer *timer;
spin_lock_init(&dm_timer_lock);
INIT_LIST_HEAD(&dm_timer_info.unused_timers);
INIT_LIST_HEAD(&dm_timer_info.reserved_timers);
timer = &dm_timers[0];
while (timer->base) {
list_add_tail((struct list_head *)timer, &dm_timer_info.unused_timers);
omap_dm_timer_reset(timer);
timer++;
}
}
static int __init omap_dm_timer_init(void)
{
if (cpu_is_omap16xx())
__dm_timer_init();
return 0;
}
arch_initcall(omap_dm_timer_init);

View File

@ -3,7 +3,7 @@
*
* Support functions for OMAP GPIO
*
* Copyright (C) 2003 Nokia Corporation
* Copyright (C) 2003-2005 Nokia Corporation
* Written by Juha Yrjölä <juha.yrjola@nokia.com>
*
* This program is free software; you can redistribute it and/or modify
@ -17,8 +17,11 @@
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/ptrace.h>
#include <linux/sysdev.h>
#include <linux/err.h>
#include <asm/hardware.h>
#include <asm/hardware/clock.h>
#include <asm/irq.h>
#include <asm/arch/irqs.h>
#include <asm/arch/gpio.h>
@ -29,7 +32,7 @@
/*
* OMAP1510 GPIO registers
*/
#define OMAP1510_GPIO_BASE 0xfffce000
#define OMAP1510_GPIO_BASE (void __iomem *)0xfffce000
#define OMAP1510_GPIO_DATA_INPUT 0x00
#define OMAP1510_GPIO_DATA_OUTPUT 0x04
#define OMAP1510_GPIO_DIR_CONTROL 0x08
@ -43,34 +46,37 @@
/*
* OMAP1610 specific GPIO registers
*/
#define OMAP1610_GPIO1_BASE 0xfffbe400
#define OMAP1610_GPIO2_BASE 0xfffbec00
#define OMAP1610_GPIO3_BASE 0xfffbb400
#define OMAP1610_GPIO4_BASE 0xfffbbc00
#define OMAP1610_GPIO1_BASE (void __iomem *)0xfffbe400
#define OMAP1610_GPIO2_BASE (void __iomem *)0xfffbec00
#define OMAP1610_GPIO3_BASE (void __iomem *)0xfffbb400
#define OMAP1610_GPIO4_BASE (void __iomem *)0xfffbbc00
#define OMAP1610_GPIO_REVISION 0x0000
#define OMAP1610_GPIO_SYSCONFIG 0x0010
#define OMAP1610_GPIO_SYSSTATUS 0x0014
#define OMAP1610_GPIO_IRQSTATUS1 0x0018
#define OMAP1610_GPIO_IRQENABLE1 0x001c
#define OMAP1610_GPIO_WAKEUPENABLE 0x0028
#define OMAP1610_GPIO_DATAIN 0x002c
#define OMAP1610_GPIO_DATAOUT 0x0030
#define OMAP1610_GPIO_DIRECTION 0x0034
#define OMAP1610_GPIO_EDGE_CTRL1 0x0038
#define OMAP1610_GPIO_EDGE_CTRL2 0x003c
#define OMAP1610_GPIO_CLEAR_IRQENABLE1 0x009c
#define OMAP1610_GPIO_CLEAR_WAKEUPENA 0x00a8
#define OMAP1610_GPIO_CLEAR_DATAOUT 0x00b0
#define OMAP1610_GPIO_SET_IRQENABLE1 0x00dc
#define OMAP1610_GPIO_SET_WAKEUPENA 0x00e8
#define OMAP1610_GPIO_SET_DATAOUT 0x00f0
/*
* OMAP730 specific GPIO registers
*/
#define OMAP730_GPIO1_BASE 0xfffbc000
#define OMAP730_GPIO2_BASE 0xfffbc800
#define OMAP730_GPIO3_BASE 0xfffbd000
#define OMAP730_GPIO4_BASE 0xfffbd800
#define OMAP730_GPIO5_BASE 0xfffbe000
#define OMAP730_GPIO6_BASE 0xfffbe800
#define OMAP730_GPIO1_BASE (void __iomem *)0xfffbc000
#define OMAP730_GPIO2_BASE (void __iomem *)0xfffbc800
#define OMAP730_GPIO3_BASE (void __iomem *)0xfffbd000
#define OMAP730_GPIO4_BASE (void __iomem *)0xfffbd800
#define OMAP730_GPIO5_BASE (void __iomem *)0xfffbe000
#define OMAP730_GPIO6_BASE (void __iomem *)0xfffbe800
#define OMAP730_GPIO_DATA_INPUT 0x00
#define OMAP730_GPIO_DATA_OUTPUT 0x04
#define OMAP730_GPIO_DIR_CONTROL 0x08
@ -78,14 +84,43 @@
#define OMAP730_GPIO_INT_MASK 0x10
#define OMAP730_GPIO_INT_STATUS 0x14
/*
* omap24xx specific GPIO registers
*/
#define OMAP24XX_GPIO1_BASE (void __iomem *)0x48018000
#define OMAP24XX_GPIO2_BASE (void __iomem *)0x4801a000
#define OMAP24XX_GPIO3_BASE (void __iomem *)0x4801c000
#define OMAP24XX_GPIO4_BASE (void __iomem *)0x4801e000
#define OMAP24XX_GPIO_REVISION 0x0000
#define OMAP24XX_GPIO_SYSCONFIG 0x0010
#define OMAP24XX_GPIO_SYSSTATUS 0x0014
#define OMAP24XX_GPIO_IRQSTATUS1 0x0018
#define OMAP24XX_GPIO_IRQENABLE1 0x001c
#define OMAP24XX_GPIO_CTRL 0x0030
#define OMAP24XX_GPIO_OE 0x0034
#define OMAP24XX_GPIO_DATAIN 0x0038
#define OMAP24XX_GPIO_DATAOUT 0x003c
#define OMAP24XX_GPIO_LEVELDETECT0 0x0040
#define OMAP24XX_GPIO_LEVELDETECT1 0x0044
#define OMAP24XX_GPIO_RISINGDETECT 0x0048
#define OMAP24XX_GPIO_FALLINGDETECT 0x004c
#define OMAP24XX_GPIO_CLEARIRQENABLE1 0x0060
#define OMAP24XX_GPIO_SETIRQENABLE1 0x0064
#define OMAP24XX_GPIO_CLEARWKUENA 0x0080
#define OMAP24XX_GPIO_SETWKUENA 0x0084
#define OMAP24XX_GPIO_CLEARDATAOUT 0x0090
#define OMAP24XX_GPIO_SETDATAOUT 0x0094
#define OMAP_MPUIO_MASK (~OMAP_MAX_GPIO_LINES & 0xff)
struct gpio_bank {
u32 base;
void __iomem *base;
u16 irq;
u16 virtual_irq_start;
u8 method;
int method;
u32 reserved_map;
u32 suspend_wakeup;
u32 saved_wakeup;
spinlock_t lock;
};
@ -93,8 +128,9 @@ struct gpio_bank {
#define METHOD_GPIO_1510 1
#define METHOD_GPIO_1610 2
#define METHOD_GPIO_730 3
#define METHOD_GPIO_24XX 4
#if defined(CONFIG_ARCH_OMAP16XX)
#ifdef CONFIG_ARCH_OMAP16XX
static struct gpio_bank gpio_bank_1610[5] = {
{ OMAP_MPUIO_BASE, INT_MPUIO, IH_MPUIO_BASE, METHOD_MPUIO},
{ OMAP1610_GPIO1_BASE, INT_GPIO_BANK1, IH_GPIO_BASE, METHOD_GPIO_1610 },
@ -123,6 +159,15 @@ static struct gpio_bank gpio_bank_730[7] = {
};
#endif
#ifdef CONFIG_ARCH_OMAP24XX
static struct gpio_bank gpio_bank_24xx[4] = {
{ OMAP24XX_GPIO1_BASE, INT_24XX_GPIO_BANK1, IH_GPIO_BASE, METHOD_GPIO_24XX },
{ OMAP24XX_GPIO2_BASE, INT_24XX_GPIO_BANK2, IH_GPIO_BASE + 32, METHOD_GPIO_24XX },
{ OMAP24XX_GPIO3_BASE, INT_24XX_GPIO_BANK3, IH_GPIO_BASE + 64, METHOD_GPIO_24XX },
{ OMAP24XX_GPIO4_BASE, INT_24XX_GPIO_BANK4, IH_GPIO_BASE + 96, METHOD_GPIO_24XX },
};
#endif
static struct gpio_bank *gpio_bank;
static int gpio_bank_count;
@ -149,14 +194,23 @@ static inline struct gpio_bank *get_gpio_bank(int gpio)
return &gpio_bank[1 + (gpio >> 5)];
}
#endif
#ifdef CONFIG_ARCH_OMAP24XX
if (cpu_is_omap24xx())
return &gpio_bank[gpio >> 5];
#endif
}
static inline int get_gpio_index(int gpio)
{
#ifdef CONFIG_ARCH_OMAP730
if (cpu_is_omap730())
return gpio & 0x1f;
else
return gpio & 0x0f;
#endif
#ifdef CONFIG_ARCH_OMAP24XX
if (cpu_is_omap24xx())
return gpio & 0x1f;
#endif
return gpio & 0x0f;
}
static inline int gpio_valid(int gpio)
@ -179,6 +233,10 @@ static inline int gpio_valid(int gpio)
#ifdef CONFIG_ARCH_OMAP730
if (cpu_is_omap730() && gpio < 192)
return 0;
#endif
#ifdef CONFIG_ARCH_OMAP24XX
if (cpu_is_omap24xx() && gpio < 128)
return 0;
#endif
return -1;
}
@ -195,7 +253,7 @@ static int check_gpio(int gpio)
static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input)
{
u32 reg = bank->base;
void __iomem *reg = bank->base;
u32 l;
switch (bank->method) {
@ -211,6 +269,9 @@ static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input)
case METHOD_GPIO_730:
reg += OMAP730_GPIO_DIR_CONTROL;
break;
case METHOD_GPIO_24XX:
reg += OMAP24XX_GPIO_OE;
break;
}
l = __raw_readl(reg);
if (is_input)
@ -234,7 +295,7 @@ void omap_set_gpio_direction(int gpio, int is_input)
static void _set_gpio_dataout(struct gpio_bank *bank, int gpio, int enable)
{
u32 reg = bank->base;
void __iomem *reg = bank->base;
u32 l = 0;
switch (bank->method) {
@ -269,6 +330,13 @@ static void _set_gpio_dataout(struct gpio_bank *bank, int gpio, int enable)
else
l &= ~(1 << gpio);
break;
case METHOD_GPIO_24XX:
if (enable)
reg += OMAP24XX_GPIO_SETDATAOUT;
else
reg += OMAP24XX_GPIO_CLEARDATAOUT;
l = 1 << gpio;
break;
default:
BUG();
return;
@ -291,7 +359,7 @@ void omap_set_gpio_dataout(int gpio, int enable)
int omap_get_gpio_datain(int gpio)
{
struct gpio_bank *bank;
u32 reg;
void __iomem *reg;
if (check_gpio(gpio) < 0)
return -1;
@ -310,109 +378,132 @@ int omap_get_gpio_datain(int gpio)
case METHOD_GPIO_730:
reg += OMAP730_GPIO_DATA_INPUT;
break;
case METHOD_GPIO_24XX:
reg += OMAP24XX_GPIO_DATAIN;
break;
default:
BUG();
return -1;
}
return (__raw_readl(reg) & (1 << get_gpio_index(gpio))) != 0;
return (__raw_readl(reg)
& (1 << get_gpio_index(gpio))) != 0;
}
static void _set_gpio_edge_ctrl(struct gpio_bank *bank, int gpio, int edge)
#define MOD_REG_BIT(reg, bit_mask, set) \
do { \
int l = __raw_readl(base + reg); \
if (set) l |= bit_mask; \
else l &= ~bit_mask; \
__raw_writel(l, base + reg); \
} while(0)
static inline void set_24xx_gpio_triggering(void __iomem *base, int gpio, int trigger)
{
u32 reg = bank->base;
u32 l;
u32 gpio_bit = 1 << gpio;
MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT0, gpio_bit,
trigger & IRQT_LOW);
MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT1, gpio_bit,
trigger & IRQT_HIGH);
MOD_REG_BIT(OMAP24XX_GPIO_RISINGDETECT, gpio_bit,
trigger & IRQT_RISING);
MOD_REG_BIT(OMAP24XX_GPIO_FALLINGDETECT, gpio_bit,
trigger & IRQT_FALLING);
/* FIXME: Possibly do 'set_irq_handler(j, do_level_IRQ)' if only level
* triggering requested. */
}
static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
{
void __iomem *reg = bank->base;
u32 l = 0;
switch (bank->method) {
case METHOD_MPUIO:
reg += OMAP_MPUIO_GPIO_INT_EDGE;
l = __raw_readl(reg);
if (edge == OMAP_GPIO_RISING_EDGE)
if (trigger == IRQT_RISING)
l |= 1 << gpio;
else
else if (trigger == IRQT_FALLING)
l &= ~(1 << gpio);
__raw_writel(l, reg);
else
goto bad;
break;
case METHOD_GPIO_1510:
reg += OMAP1510_GPIO_INT_CONTROL;
l = __raw_readl(reg);
if (edge == OMAP_GPIO_RISING_EDGE)
if (trigger == IRQT_RISING)
l |= 1 << gpio;
else
else if (trigger == IRQT_FALLING)
l &= ~(1 << gpio);
__raw_writel(l, reg);
else
goto bad;
break;
case METHOD_GPIO_1610:
edge &= 0x03;
if (gpio & 0x08)
reg += OMAP1610_GPIO_EDGE_CTRL2;
else
reg += OMAP1610_GPIO_EDGE_CTRL1;
gpio &= 0x07;
/* We allow only edge triggering, i.e. two lowest bits */
if (trigger & ~IRQT_BOTHEDGE)
BUG();
/* NOTE: knows __IRQT_{FAL,RIS}EDGE match OMAP hardware */
trigger &= 0x03;
l = __raw_readl(reg);
l &= ~(3 << (gpio << 1));
l |= edge << (gpio << 1);
__raw_writel(l, reg);
l |= trigger << (gpio << 1);
break;
case METHOD_GPIO_730:
reg += OMAP730_GPIO_INT_CONTROL;
l = __raw_readl(reg);
if (edge == OMAP_GPIO_RISING_EDGE)
if (trigger == IRQT_RISING)
l |= 1 << gpio;
else
else if (trigger == IRQT_FALLING)
l &= ~(1 << gpio);
__raw_writel(l, reg);
else
goto bad;
break;
case METHOD_GPIO_24XX:
set_24xx_gpio_triggering(reg, gpio, trigger);
break;
default:
BUG();
return;
goto bad;
}
__raw_writel(l, reg);
return 0;
bad:
return -EINVAL;
}
void omap_set_gpio_edge_ctrl(int gpio, int edge)
static int gpio_irq_type(unsigned irq, unsigned type)
{
struct gpio_bank *bank;
unsigned gpio;
int retval;
if (irq > IH_MPUIO_BASE)
gpio = OMAP_MPUIO(irq - IH_MPUIO_BASE);
else
gpio = irq - IH_GPIO_BASE;
if (check_gpio(gpio) < 0)
return;
return -EINVAL;
if (type & (__IRQT_LOWLVL|__IRQT_HIGHLVL|IRQT_PROBE))
return -EINVAL;
bank = get_gpio_bank(gpio);
spin_lock(&bank->lock);
_set_gpio_edge_ctrl(bank, get_gpio_index(gpio), edge);
retval = _set_gpio_triggering(bank, get_gpio_index(gpio), type);
spin_unlock(&bank->lock);
}
static int _get_gpio_edge_ctrl(struct gpio_bank *bank, int gpio)
{
u32 reg = bank->base, l;
switch (bank->method) {
case METHOD_MPUIO:
l = __raw_readl(reg + OMAP_MPUIO_GPIO_INT_EDGE);
return (l & (1 << gpio)) ?
OMAP_GPIO_RISING_EDGE : OMAP_GPIO_FALLING_EDGE;
case METHOD_GPIO_1510:
l = __raw_readl(reg + OMAP1510_GPIO_INT_CONTROL);
return (l & (1 << gpio)) ?
OMAP_GPIO_RISING_EDGE : OMAP_GPIO_FALLING_EDGE;
case METHOD_GPIO_1610:
if (gpio & 0x08)
reg += OMAP1610_GPIO_EDGE_CTRL2;
else
reg += OMAP1610_GPIO_EDGE_CTRL1;
return (__raw_readl(reg) >> ((gpio & 0x07) << 1)) & 0x03;
case METHOD_GPIO_730:
l = __raw_readl(reg + OMAP730_GPIO_INT_CONTROL);
return (l & (1 << gpio)) ?
OMAP_GPIO_RISING_EDGE : OMAP_GPIO_FALLING_EDGE;
default:
BUG();
return -1;
}
return retval;
}
static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
{
u32 reg = bank->base;
void __iomem *reg = bank->base;
switch (bank->method) {
case METHOD_MPUIO:
@ -428,6 +519,9 @@ static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
case METHOD_GPIO_730:
reg += OMAP730_GPIO_INT_STATUS;
break;
case METHOD_GPIO_24XX:
reg += OMAP24XX_GPIO_IRQSTATUS1;
break;
default:
BUG();
return;
@ -442,7 +536,7 @@ static inline void _clear_gpio_irqstatus(struct gpio_bank *bank, int gpio)
static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask, int enable)
{
u32 reg = bank->base;
void __iomem *reg = bank->base;
u32 l;
switch (bank->method) {
@ -477,6 +571,13 @@ static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask, int enab
else
l |= gpio_mask;
break;
case METHOD_GPIO_24XX:
if (enable)
reg += OMAP24XX_GPIO_SETIRQENABLE1;
else
reg += OMAP24XX_GPIO_CLEARIRQENABLE1;
l = gpio_mask;
break;
default:
BUG();
return;
@ -489,6 +590,50 @@ static inline void _set_gpio_irqenable(struct gpio_bank *bank, int gpio, int ena
_enable_gpio_irqbank(bank, 1 << get_gpio_index(gpio), enable);
}
/*
* Note that ENAWAKEUP needs to be enabled in GPIO_SYSCONFIG register.
* 1510 does not seem to have a wake-up register. If JTAG is connected
* to the target, system will wake up always on GPIO events. While
* system is running all registered GPIO interrupts need to have wake-up
* enabled. When system is suspended, only selected GPIO interrupts need
* to have wake-up enabled.
*/
static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable)
{
switch (bank->method) {
case METHOD_GPIO_1610:
case METHOD_GPIO_24XX:
spin_lock(&bank->lock);
if (enable)
bank->suspend_wakeup |= (1 << gpio);
else
bank->suspend_wakeup &= ~(1 << gpio);
spin_unlock(&bank->lock);
return 0;
default:
printk(KERN_ERR "Can't enable GPIO wakeup for method %i\n",
bank->method);
return -EINVAL;
}
}
/* Use disable_irq_wake() and enable_irq_wake() functions from drivers */
static int gpio_wake_enable(unsigned int irq, unsigned int enable)
{
unsigned int gpio = irq - IH_GPIO_BASE;
struct gpio_bank *bank;
int retval;
if (check_gpio(gpio) < 0)
return -ENODEV;
bank = get_gpio_bank(gpio);
spin_lock(&bank->lock);
retval = _set_gpio_wakeup(bank, get_gpio_index(gpio), enable);
spin_unlock(&bank->lock);
return retval;
}
int omap_request_gpio(int gpio)
{
struct gpio_bank *bank;
@ -505,14 +650,32 @@ int omap_request_gpio(int gpio)
return -1;
}
bank->reserved_map |= (1 << get_gpio_index(gpio));
/* Set trigger to none. You need to enable the trigger after request_irq */
_set_gpio_triggering(bank, get_gpio_index(gpio), IRQT_NOEDGE);
#ifdef CONFIG_ARCH_OMAP1510
if (bank->method == METHOD_GPIO_1510) {
u32 reg;
void __iomem *reg;
/* Claim the pin for the ARM */
/* Claim the pin for MPU */
reg = bank->base + OMAP1510_GPIO_PIN_CONTROL;
__raw_writel(__raw_readl(reg) | (1 << get_gpio_index(gpio)), reg);
}
#endif
#ifdef CONFIG_ARCH_OMAP16XX
if (bank->method == METHOD_GPIO_1610) {
/* Enable wake-up during idle for dynamic tick */
void __iomem *reg = bank->base + OMAP1610_GPIO_SET_WAKEUPENA;
__raw_writel(1 << get_gpio_index(gpio), reg);
}
#endif
#ifdef CONFIG_ARCH_OMAP24XX
if (bank->method == METHOD_GPIO_24XX) {
/* Enable wake-up during idle for dynamic tick */
void __iomem *reg = bank->base + OMAP24XX_GPIO_SETWKUENA;
__raw_writel(1 << get_gpio_index(gpio), reg);
}
#endif
spin_unlock(&bank->lock);
@ -533,6 +696,20 @@ void omap_free_gpio(int gpio)
spin_unlock(&bank->lock);
return;
}
#ifdef CONFIG_ARCH_OMAP16XX
if (bank->method == METHOD_GPIO_1610) {
/* Disable wake-up during idle for dynamic tick */
void __iomem *reg = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA;
__raw_writel(1 << get_gpio_index(gpio), reg);
}
#endif
#ifdef CONFIG_ARCH_OMAP24XX
if (bank->method == METHOD_GPIO_24XX) {
/* Disable wake-up during idle for dynamic tick */
void __iomem *reg = bank->base + OMAP24XX_GPIO_CLEARWKUENA;
__raw_writel(1 << get_gpio_index(gpio), reg);
}
#endif
bank->reserved_map &= ~(1 << get_gpio_index(gpio));
_set_gpio_direction(bank, get_gpio_index(gpio), 1);
_set_gpio_irqenable(bank, gpio, 0);
@ -552,7 +729,7 @@ void omap_free_gpio(int gpio)
static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc,
struct pt_regs *regs)
{
u32 isr_reg = 0;
void __iomem *isr_reg = NULL;
u32 isr;
unsigned int gpio_irq;
struct gpio_bank *bank;
@ -574,24 +751,30 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc,
if (bank->method == METHOD_GPIO_730)
isr_reg = bank->base + OMAP730_GPIO_INT_STATUS;
#endif
#ifdef CONFIG_ARCH_OMAP24XX
if (bank->method == METHOD_GPIO_24XX)
isr_reg = bank->base + OMAP24XX_GPIO_IRQSTATUS1;
#endif
isr = __raw_readl(isr_reg);
_enable_gpio_irqbank(bank, isr, 0);
_clear_gpio_irqbank(bank, isr);
_enable_gpio_irqbank(bank, isr, 1);
desc->chip->unmask(irq);
while(1) {
isr = __raw_readl(isr_reg);
_enable_gpio_irqbank(bank, isr, 0);
_clear_gpio_irqbank(bank, isr);
_enable_gpio_irqbank(bank, isr, 1);
desc->chip->unmask(irq);
if (unlikely(!isr))
return;
if (!isr)
break;
gpio_irq = bank->virtual_irq_start;
for (; isr != 0; isr >>= 1, gpio_irq++) {
struct irqdesc *d;
if (!(isr & 1))
continue;
d = irq_desc + gpio_irq;
d->handle(gpio_irq, d, regs);
}
gpio_irq = bank->virtual_irq_start;
for (; isr != 0; isr >>= 1, gpio_irq++) {
struct irqdesc *d;
if (!(isr & 1))
continue;
d = irq_desc + gpio_irq;
desc_handle_irq(gpio_irq, d, regs);
}
}
}
static void gpio_ack_irq(unsigned int irq)
@ -613,14 +796,10 @@ static void gpio_mask_irq(unsigned int irq)
static void gpio_unmask_irq(unsigned int irq)
{
unsigned int gpio = irq - IH_GPIO_BASE;
unsigned int gpio_idx = get_gpio_index(gpio);
struct gpio_bank *bank = get_gpio_bank(gpio);
if (_get_gpio_edge_ctrl(bank, get_gpio_index(gpio)) == OMAP_GPIO_NO_EDGE) {
printk(KERN_ERR "OMAP GPIO %d: trying to enable GPIO IRQ while no edge is set\n",
gpio);
_set_gpio_edge_ctrl(bank, get_gpio_index(gpio), OMAP_GPIO_RISING_EDGE);
}
_set_gpio_irqenable(bank, gpio, 1);
_set_gpio_irqenable(bank, gpio_idx, 1);
}
static void mpuio_ack_irq(unsigned int irq)
@ -645,9 +824,11 @@ static void mpuio_unmask_irq(unsigned int irq)
}
static struct irqchip gpio_irq_chip = {
.ack = gpio_ack_irq,
.mask = gpio_mask_irq,
.unmask = gpio_unmask_irq,
.ack = gpio_ack_irq,
.mask = gpio_mask_irq,
.unmask = gpio_unmask_irq,
.set_type = gpio_irq_type,
.set_wake = gpio_wake_enable,
};
static struct irqchip mpuio_irq_chip = {
@ -657,6 +838,7 @@ static struct irqchip mpuio_irq_chip = {
};
static int initialized = 0;
static struct clk * gpio_ck = NULL;
static int __init _omap_gpio_init(void)
{
@ -665,6 +847,14 @@ static int __init _omap_gpio_init(void)
initialized = 1;
if (cpu_is_omap1510()) {
gpio_ck = clk_get(NULL, "arm_gpio_ck");
if (IS_ERR(gpio_ck))
printk("Could not get arm_gpio_ck\n");
else
clk_use(gpio_ck);
}
#ifdef CONFIG_ARCH_OMAP1510
if (cpu_is_omap1510()) {
printk(KERN_INFO "OMAP1510 GPIO hardware\n");
@ -674,7 +864,7 @@ static int __init _omap_gpio_init(void)
#endif
#if defined(CONFIG_ARCH_OMAP16XX)
if (cpu_is_omap16xx()) {
int rev;
u32 rev;
gpio_bank_count = 5;
gpio_bank = gpio_bank_1610;
@ -689,6 +879,17 @@ static int __init _omap_gpio_init(void)
gpio_bank_count = 7;
gpio_bank = gpio_bank_730;
}
#endif
#ifdef CONFIG_ARCH_OMAP24XX
if (cpu_is_omap24xx()) {
int rev;
gpio_bank_count = 4;
gpio_bank = gpio_bank_24xx;
rev = omap_readl(gpio_bank[0].base + OMAP24XX_GPIO_REVISION);
printk(KERN_INFO "OMAP24xx GPIO hardware version %d.%d\n",
(rev >> 4) & 0x0f, rev & 0x0f);
}
#endif
for (i = 0; i < gpio_bank_count; i++) {
int j, gpio_count = 16;
@ -710,6 +911,7 @@ static int __init _omap_gpio_init(void)
if (bank->method == METHOD_GPIO_1610) {
__raw_writew(0x0000, bank->base + OMAP1610_GPIO_IRQENABLE1);
__raw_writew(0xffff, bank->base + OMAP1610_GPIO_IRQSTATUS1);
__raw_writew(0x0014, bank->base + OMAP1610_GPIO_SYSCONFIG);
}
#endif
#ifdef CONFIG_ARCH_OMAP730
@ -719,6 +921,14 @@ static int __init _omap_gpio_init(void)
gpio_count = 32; /* 730 has 32-bit GPIOs */
}
#endif
#ifdef CONFIG_ARCH_OMAP24XX
if (bank->method == METHOD_GPIO_24XX) {
__raw_writel(0x00000000, bank->base + OMAP24XX_GPIO_IRQENABLE1);
__raw_writel(0xffffffff, bank->base + OMAP24XX_GPIO_IRQSTATUS1);
gpio_count = 32;
}
#endif
for (j = bank->virtual_irq_start;
j < bank->virtual_irq_start + gpio_count; j++) {
@ -735,12 +945,97 @@ static int __init _omap_gpio_init(void)
/* Enable system clock for GPIO module.
* The CAM_CLK_CTRL *is* really the right place. */
if (cpu_is_omap1610() || cpu_is_omap1710())
if (cpu_is_omap16xx())
omap_writel(omap_readl(ULPD_CAM_CLK_CTRL) | 0x04, ULPD_CAM_CLK_CTRL);
return 0;
}
#if defined (CONFIG_ARCH_OMAP16XX) || defined (CONFIG_ARCH_OMAP24XX)
static int omap_gpio_suspend(struct sys_device *dev, pm_message_t mesg)
{
int i;
if (!cpu_is_omap24xx() && !cpu_is_omap16xx())
return 0;
for (i = 0; i < gpio_bank_count; i++) {
struct gpio_bank *bank = &gpio_bank[i];
void __iomem *wake_status;
void __iomem *wake_clear;
void __iomem *wake_set;
switch (bank->method) {
case METHOD_GPIO_1610:
wake_status = bank->base + OMAP1610_GPIO_WAKEUPENABLE;
wake_clear = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA;
wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA;
break;
case METHOD_GPIO_24XX:
wake_status = bank->base + OMAP24XX_GPIO_SETWKUENA;
wake_clear = bank->base + OMAP24XX_GPIO_CLEARWKUENA;
wake_set = bank->base + OMAP24XX_GPIO_SETWKUENA;
break;
default:
continue;
}
spin_lock(&bank->lock);
bank->saved_wakeup = __raw_readl(wake_status);
__raw_writel(0xffffffff, wake_clear);
__raw_writel(bank->suspend_wakeup, wake_set);
spin_unlock(&bank->lock);
}
return 0;
}
static int omap_gpio_resume(struct sys_device *dev)
{
int i;
if (!cpu_is_omap24xx() && !cpu_is_omap16xx())
return 0;
for (i = 0; i < gpio_bank_count; i++) {
struct gpio_bank *bank = &gpio_bank[i];
void __iomem *wake_clear;
void __iomem *wake_set;
switch (bank->method) {
case METHOD_GPIO_1610:
wake_clear = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA;
wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA;
break;
case METHOD_GPIO_24XX:
wake_clear = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA;
wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA;
break;
default:
continue;
}
spin_lock(&bank->lock);
__raw_writel(0xffffffff, wake_clear);
__raw_writel(bank->saved_wakeup, wake_set);
spin_unlock(&bank->lock);
}
return 0;
}
static struct sysdev_class omap_gpio_sysclass = {
set_kset_name("gpio"),
.suspend = omap_gpio_suspend,
.resume = omap_gpio_resume,
};
static struct sys_device omap_gpio_device = {
.id = 0,
.cls = &omap_gpio_sysclass,
};
#endif
/*
* This may get called early from board specific init
*/
@ -752,11 +1047,30 @@ int omap_gpio_init(void)
return 0;
}
static int __init omap_gpio_sysinit(void)
{
int ret = 0;
if (!initialized)
ret = _omap_gpio_init();
#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP24XX)
if (cpu_is_omap16xx() || cpu_is_omap24xx()) {
if (ret == 0) {
ret = sysdev_class_register(&omap_gpio_sysclass);
if (ret == 0)
ret = sysdev_register(&omap_gpio_device);
}
}
#endif
return ret;
}
EXPORT_SYMBOL(omap_request_gpio);
EXPORT_SYMBOL(omap_free_gpio);
EXPORT_SYMBOL(omap_set_gpio_direction);
EXPORT_SYMBOL(omap_set_gpio_dataout);
EXPORT_SYMBOL(omap_get_gpio_datain);
EXPORT_SYMBOL(omap_set_gpio_edge_ctrl);
arch_initcall(omap_gpio_init);
arch_initcall(omap_gpio_sysinit);

View File

@ -27,6 +27,7 @@
#include <asm/arch/dma.h>
#include <asm/arch/mux.h>
#include <asm/arch/irqs.h>
#include <asm/arch/dsp_common.h>
#include <asm/arch/mcbsp.h>
#include <asm/hardware/clock.h>
@ -187,9 +188,6 @@ static int omap_mcbsp_check(unsigned int id)
return -1;
}
#define EN_XORPCK 1
#define DSP_RSTCT2 0xe1008014
static void omap_mcbsp_dsp_request(void)
{
if (cpu_is_omap1510() || cpu_is_omap16xx()) {
@ -198,6 +196,11 @@ static void omap_mcbsp_dsp_request(void)
/* enable 12MHz clock to mcbsp 1 & 3 */
clk_use(mcbsp_dspxor_ck);
/*
* DSP external peripheral reset
* FIXME: This should be moved to dsp code
*/
__raw_writew(__raw_readw(DSP_RSTCT2) | 1 | 1 << 1,
DSP_RSTCT2);
}

View File

@ -48,6 +48,9 @@ omap_cfg_reg(const reg_cfg_t reg_cfg)
pull_orig = 0, pull = 0;
unsigned int mask, warn = 0;
if (cpu_is_omap7xx())
return 0;
if (reg_cfg > ARRAY_SIZE(reg_cfg_table)) {
printk(KERN_ERR "MUX: reg_cfg %d\n", reg_cfg);
return -EINVAL;

View File

@ -25,6 +25,7 @@
#include <linux/config.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/kernel.h>

View File

@ -39,24 +39,32 @@
#include <linux/sched.h>
#include <linux/proc_fs.h>
#include <linux/pm.h>
#include <linux/interrupt.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/mach/time.h>
#include <asm/mach-types.h>
#include <asm/mach/irq.h>
#include <asm/arch/omap16xx.h>
#include <asm/mach-types.h>
#include <asm/arch/irqs.h>
#include <asm/arch/tc.h>
#include <asm/arch/pm.h>
#include <asm/arch/mux.h>
#include <asm/arch/tc.h>
#include <asm/arch/tps65010.h>
#include <asm/arch/dsp_common.h>
#include "clock.h"
#include "sram.h"
static unsigned int arm_sleep_save[ARM_SLEEP_SAVE_SIZE];
static unsigned short ulpd_sleep_save[ULPD_SLEEP_SAVE_SIZE];
static unsigned int mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_SIZE];
static unsigned int mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_SIZE];
static void (*omap_sram_idle)(void) = NULL;
static void (*omap_sram_suspend)(unsigned long r0, unsigned long r1) = NULL;
/*
* Let's power down on idle, but only if we are really
* idle, because once we start down the path of
@ -65,7 +73,6 @@ static unsigned int mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_SIZE];
*/
void omap_pm_idle(void)
{
int (*func_ptr)(void) = 0;
unsigned int mask32 = 0;
/*
@ -83,6 +90,13 @@ void omap_pm_idle(void)
}
mask32 = omap_readl(ARM_SYSST);
/*
* Prevent the ULPD from entering low power state by setting
* POWER_CTRL_REG:4 = 0
*/
omap_writew(omap_readw(ULPD_POWER_CTRL) &
~ULPD_DEEP_SLEEP_TRANSITION_EN, ULPD_POWER_CTRL);
/*
* Since an interrupt may set up a timer, we don't want to
* reprogram the hardware timer with interrupts enabled.
@ -92,18 +106,9 @@ void omap_pm_idle(void)
if ((mask32 & DSP_IDLE) == 0) {
__asm__ volatile ("mcr p15, 0, r0, c7, c0, 4");
} else {
} else
omap_sram_idle();
if (cpu_is_omap1510()) {
func_ptr = (void *)(OMAP1510_SRAM_IDLE_SUSPEND);
} else if (cpu_is_omap1610() || cpu_is_omap1710()) {
func_ptr = (void *)(OMAP1610_SRAM_IDLE_SUSPEND);
} else if (cpu_is_omap5912()) {
func_ptr = (void *)(OMAP5912_SRAM_IDLE_SUSPEND);
}
func_ptr();
}
local_fiq_enable();
local_irq_enable();
}
@ -115,58 +120,55 @@ void omap_pm_idle(void)
*/
static void omap_pm_wakeup_setup(void)
{
/*
* Enable ARM XOR clock and release peripheral from reset by
* writing 1 to PER_EN bit in ARM_RSTCT2, this is required
* for UART configuration to use UART2 to wake up.
*/
omap_writel(omap_readl(ARM_IDLECT2) | ENABLE_XORCLK, ARM_IDLECT2);
omap_writel(omap_readl(ARM_RSTCT2) | PER_EN, ARM_RSTCT2);
omap_writew(MODEM_32K_EN, ULPD_CLOCK_CTRL);
u32 level1_wake = OMAP_IRQ_BIT(INT_IH2_IRQ);
u32 level2_wake = OMAP_IRQ_BIT(INT_UART2) | OMAP_IRQ_BIT(INT_KEYBOARD);
/*
* Turn off all interrupts except L1-2nd level cascade,
* and the L2 wakeup interrupts: keypad and UART2.
* Turn off all interrupts except GPIO bank 1, L1-2nd level cascade,
* and the L2 wakeup interrupts: keypad and UART2. Note that the
* drivers must still separately call omap_set_gpio_wakeup() to
* wake up to a GPIO interrupt.
*/
if (cpu_is_omap1510() || cpu_is_omap16xx())
level1_wake |= OMAP_IRQ_BIT(INT_GPIO_BANK1);
else if (cpu_is_omap730())
level1_wake |= OMAP_IRQ_BIT(INT_730_GPIO_BANK1);
omap_writel(~IRQ_LEVEL2, OMAP_IH1_MIR);
omap_writel(~level1_wake, OMAP_IH1_MIR);
if (cpu_is_omap1510()) {
omap_writel(~(IRQ_UART2 | IRQ_KEYBOARD), OMAP_IH2_MIR);
}
if (cpu_is_omap1510())
omap_writel(~level2_wake, OMAP_IH2_MIR);
/* INT_1610_WAKE_UP_REQ is needed for GPIO wakeup... */
if (cpu_is_omap16xx()) {
omap_writel(~(IRQ_UART2 | IRQ_KEYBOARD), OMAP_IH2_0_MIR);
omap_writel(~0x0, OMAP_IH2_1_MIR);
omap_writel(~level2_wake, OMAP_IH2_0_MIR);
omap_writel(~OMAP_IRQ_BIT(INT_1610_WAKE_UP_REQ), OMAP_IH2_1_MIR);
omap_writel(~0x0, OMAP_IH2_2_MIR);
omap_writel(~0x0, OMAP_IH2_3_MIR);
}
/* New IRQ agreement */
/* New IRQ agreement, recalculate in cascade order */
omap_writel(1, OMAP_IH2_CONTROL);
omap_writel(1, OMAP_IH1_CONTROL);
/* external PULL to down, bit 22 = 0 */
omap_writel(omap_readl(PULL_DWN_CTRL_2) & ~(1<<22), PULL_DWN_CTRL_2);
}
void omap_pm_suspend(void)
{
unsigned int mask32 = 0;
unsigned long arg0 = 0, arg1 = 0;
int (*func_ptr)(unsigned short, unsigned short) = 0;
unsigned short save_dsp_idlect2;
printk("PM: OMAP%x is entering deep sleep now ...\n", system_rev);
printk("PM: OMAP%x is trying to enter deep sleep...\n", system_rev);
omap_serial_wake_trigger(1);
if (machine_is_omap_osk()) {
/* Stop LED1 (D9) blink */
tps65010_set_led(LED1, OFF);
}
omap_writew(0xffff, ULPD_SOFT_DISABLE_REQ_REG);
/*
* Step 1: turn off interrupts
* Step 1: turn off interrupts (FIXME: NOTE: already disabled)
*/
local_irq_disable();
@ -207,6 +209,8 @@ void omap_pm_suspend(void)
ARM_SAVE(ARM_CKCTL);
ARM_SAVE(ARM_IDLECT1);
ARM_SAVE(ARM_IDLECT2);
if (!(cpu_is_omap1510()))
ARM_SAVE(ARM_IDLECT3);
ARM_SAVE(ARM_EWUPCT);
ARM_SAVE(ARM_RSTCT1);
ARM_SAVE(ARM_RSTCT2);
@ -214,42 +218,12 @@ void omap_pm_suspend(void)
ULPD_SAVE(ULPD_CLOCK_CTRL);
ULPD_SAVE(ULPD_STATUS_REQ);
/*
* Step 3: LOW_PWR signal enabling
*
* Allow the LOW_PWR signal to be visible on MPUIO5 ball.
*/
if (cpu_is_omap1510()) {
/* POWER_CTRL_REG = 0x1 (LOW_POWER is available) */
omap_writew(omap_readw(ULPD_POWER_CTRL) |
OMAP1510_ULPD_LOW_POWER_REQ, ULPD_POWER_CTRL);
} else if (cpu_is_omap16xx()) {
/* POWER_CTRL_REG = 0x1 (LOW_POWER is available) */
omap_writew(omap_readw(ULPD_POWER_CTRL) |
OMAP1610_ULPD_LOW_POWER_REQ, ULPD_POWER_CTRL);
}
/* configure LOW_PWR pin */
omap_cfg_reg(T20_1610_LOW_PWR);
/* (Step 3 removed - we now allow deep sleep by default) */
/*
* Step 4: OMAP DSP Shutdown
*/
/* Set DSP_RST = 1 and DSP_EN = 0, put DSP block into reset */
omap_writel((omap_readl(ARM_RSTCT1) | DSP_RST) & ~DSP_ENABLE,
ARM_RSTCT1);
/* Set DSP boot mode to DSP-IDLE, DSP_BOOT_MODE = 0x2 */
omap_writel(DSP_IDLE_MODE, MPUI_DSP_BOOT_CONFIG);
/* Set EN_DSPCK = 0, stop DSP block clock */
omap_writel(omap_readl(ARM_CKCTL) & ~DSP_CLOCK_ENABLE, ARM_CKCTL);
/* Stop any DSP domain clocks */
omap_writel(omap_readl(ARM_IDLECT2) | (1<<EN_APICK), ARM_IDLECT2);
save_dsp_idlect2 = __raw_readw(DSP_IDLECT2);
__raw_writew(0, DSP_IDLECT2);
/*
* Step 5: Wakeup Event Setup
@ -258,24 +232,9 @@ void omap_pm_suspend(void)
omap_pm_wakeup_setup();
/*
* Step 6a: ARM and Traffic controller shutdown
*
* Step 6 starts here with clock and watchdog disable
* Step 6: ARM and Traffic controller shutdown
*/
/* stop clocks */
mask32 = omap_readl(ARM_IDLECT2);
mask32 &= ~(1<<EN_WDTCK); /* bit 0 -> 0 (WDT clock) */
mask32 |= (1<<EN_XORPCK); /* bit 1 -> 1 (XORPCK clock) */
mask32 &= ~(1<<EN_PERCK); /* bit 2 -> 0 (MPUPER_CK clock) */
mask32 &= ~(1<<EN_LCDCK); /* bit 3 -> 0 (LCDC clock) */
mask32 &= ~(1<<EN_LBCK); /* bit 4 -> 0 (local bus clock) */
mask32 |= (1<<EN_APICK); /* bit 6 -> 1 (MPUI clock) */
mask32 &= ~(1<<EN_TIMCK); /* bit 7 -> 0 (MPU timer clock) */
mask32 &= ~(1<<DMACK_REQ); /* bit 8 -> 0 (DMAC clock) */
mask32 &= ~(1<<EN_GPIOCK); /* bit 9 -> 0 (GPIO clock) */
omap_writel(mask32, ARM_IDLECT2);
/* disable ARM watchdog */
omap_writel(0x00F5, OMAP_WDT_TIMER_MODE);
omap_writel(0x00A0, OMAP_WDT_TIMER_MODE);
@ -295,47 +254,24 @@ void omap_pm_suspend(void)
arg0 = arm_sleep_save[ARM_SLEEP_SAVE_ARM_IDLECT1];
arg1 = arm_sleep_save[ARM_SLEEP_SAVE_ARM_IDLECT2];
if (cpu_is_omap1510()) {
func_ptr = (void *)(OMAP1510_SRAM_API_SUSPEND);
} else if (cpu_is_omap1610() || cpu_is_omap1710()) {
func_ptr = (void *)(OMAP1610_SRAM_API_SUSPEND);
} else if (cpu_is_omap5912()) {
func_ptr = (void *)(OMAP5912_SRAM_API_SUSPEND);
}
/*
* Step 6c: ARM and Traffic controller shutdown
*
* Jump to assembly code. The processor will stay there
* until wake up.
*/
func_ptr(arg0, arg1);
omap_sram_suspend(arg0, arg1);
/*
* If we are here, processor is woken up!
*/
if (cpu_is_omap1510()) {
/* POWER_CTRL_REG = 0x0 (LOW_POWER is disabled) */
omap_writew(omap_readw(ULPD_POWER_CTRL) &
~OMAP1510_ULPD_LOW_POWER_REQ, ULPD_POWER_CTRL);
} else if (cpu_is_omap16xx()) {
/* POWER_CTRL_REG = 0x0 (LOW_POWER is disabled) */
omap_writew(omap_readw(ULPD_POWER_CTRL) &
~OMAP1610_ULPD_LOW_POWER_REQ, ULPD_POWER_CTRL);
}
/* Restore DSP clocks */
omap_writel(omap_readl(ARM_IDLECT2) | (1<<EN_APICK), ARM_IDLECT2);
__raw_writew(save_dsp_idlect2, DSP_IDLECT2);
ARM_RESTORE(ARM_IDLECT2);
/*
* Restore ARM state, except ARM_IDLECT1/2 which omap_cpu_suspend did
*/
if (!(cpu_is_omap1510()))
ARM_RESTORE(ARM_IDLECT3);
ARM_RESTORE(ARM_CKCTL);
ARM_RESTORE(ARM_EWUPCT);
ARM_RESTORE(ARM_RSTCT1);
@ -366,6 +302,8 @@ void omap_pm_suspend(void)
MPUI1610_RESTORE(OMAP_IH2_3_MIR);
}
omap_writew(0, ULPD_SOFT_DISABLE_REQ_REG);
/*
* Reenable interrupts
*/
@ -373,6 +311,8 @@ void omap_pm_suspend(void)
local_irq_enable();
local_fiq_enable();
omap_serial_wake_trigger(0);
printk("PM: OMAP%x is re-starting from deep sleep...\n", system_rev);
if (machine_is_omap_osk()) {
@ -401,6 +341,8 @@ static int omap_pm_read_proc(
ARM_SAVE(ARM_CKCTL);
ARM_SAVE(ARM_IDLECT1);
ARM_SAVE(ARM_IDLECT2);
if (!(cpu_is_omap1510()))
ARM_SAVE(ARM_IDLECT3);
ARM_SAVE(ARM_EWUPCT);
ARM_SAVE(ARM_RSTCT1);
ARM_SAVE(ARM_RSTCT2);
@ -436,6 +378,7 @@ static int omap_pm_read_proc(
"ARM_CKCTL_REG: 0x%-8x \n"
"ARM_IDLECT1_REG: 0x%-8x \n"
"ARM_IDLECT2_REG: 0x%-8x \n"
"ARM_IDLECT3_REG: 0x%-8x \n"
"ARM_EWUPCT_REG: 0x%-8x \n"
"ARM_RSTCT1_REG: 0x%-8x \n"
"ARM_RSTCT2_REG: 0x%-8x \n"
@ -449,6 +392,7 @@ static int omap_pm_read_proc(
ARM_SHOW(ARM_CKCTL),
ARM_SHOW(ARM_IDLECT1),
ARM_SHOW(ARM_IDLECT2),
ARM_SHOW(ARM_IDLECT3),
ARM_SHOW(ARM_EWUPCT),
ARM_SHOW(ARM_RSTCT1),
ARM_SHOW(ARM_RSTCT2),
@ -507,7 +451,7 @@ static void omap_pm_init_proc(void)
entry = create_proc_read_entry("driver/omap_pm",
S_IWUSR | S_IRUGO, NULL,
omap_pm_read_proc, 0);
omap_pm_read_proc, NULL);
}
#endif /* DEBUG && CONFIG_PROC_FS */
@ -580,7 +524,21 @@ static int omap_pm_finish(suspend_state_t state)
}
struct pm_ops omap_pm_ops ={
static irqreturn_t omap_wakeup_interrupt(int irq, void * dev,
struct pt_regs * regs)
{
return IRQ_HANDLED;
}
static struct irqaction omap_wakeup_irq = {
.name = "peripheral wakeup",
.flags = SA_INTERRUPT,
.handler = omap_wakeup_interrupt
};
static struct pm_ops omap_pm_ops ={
.pm_disk_mode = 0,
.prepare = omap_pm_prepare,
.enter = omap_pm_enter,
@ -590,42 +548,61 @@ struct pm_ops omap_pm_ops ={
static int __init omap_pm_init(void)
{
printk("Power Management for TI OMAP.\n");
pm_idle = omap_pm_idle;
/*
* We copy the assembler sleep/wakeup routines to SRAM.
* These routines need to be in SRAM as that's the only
* memory the MPU can see when it wakes up.
*/
#ifdef CONFIG_ARCH_OMAP1510
if (cpu_is_omap1510()) {
memcpy((void *)OMAP1510_SRAM_IDLE_SUSPEND,
omap1510_idle_loop_suspend,
omap1510_idle_loop_suspend_sz);
memcpy((void *)OMAP1510_SRAM_API_SUSPEND, omap1510_cpu_suspend,
omap1510_cpu_suspend_sz);
} else
#endif
if (cpu_is_omap1610() || cpu_is_omap1710()) {
memcpy((void *)OMAP1610_SRAM_IDLE_SUSPEND,
omap1610_idle_loop_suspend,
omap1610_idle_loop_suspend_sz);
memcpy((void *)OMAP1610_SRAM_API_SUSPEND, omap1610_cpu_suspend,
omap1610_cpu_suspend_sz);
} else if (cpu_is_omap5912()) {
memcpy((void *)OMAP5912_SRAM_IDLE_SUSPEND,
omap1610_idle_loop_suspend,
omap1610_idle_loop_suspend_sz);
memcpy((void *)OMAP5912_SRAM_API_SUSPEND, omap1610_cpu_suspend,
omap1610_cpu_suspend_sz);
omap_sram_idle = omap_sram_push(omap1510_idle_loop_suspend,
omap1510_idle_loop_suspend_sz);
omap_sram_suspend = omap_sram_push(omap1510_cpu_suspend,
omap1510_cpu_suspend_sz);
} else if (cpu_is_omap16xx()) {
omap_sram_idle = omap_sram_push(omap1610_idle_loop_suspend,
omap1610_idle_loop_suspend_sz);
omap_sram_suspend = omap_sram_push(omap1610_cpu_suspend,
omap1610_cpu_suspend_sz);
}
if (omap_sram_idle == NULL || omap_sram_suspend == NULL) {
printk(KERN_ERR "PM not initialized: Missing SRAM support\n");
return -ENODEV;
}
pm_idle = omap_pm_idle;
setup_irq(INT_1610_WAKE_UP_REQ, &omap_wakeup_irq);
#if 0
/* --- BEGIN BOARD-DEPENDENT CODE --- */
/* Sleepx mask direction */
omap_writew((omap_readw(0xfffb5008) & ~2), 0xfffb5008);
/* Unmask sleepx signal */
omap_writew((omap_readw(0xfffb5004) & ~2), 0xfffb5004);
/* --- END BOARD-DEPENDENT CODE --- */
#endif
/* Program new power ramp-up time
* (0 for most boards since we don't lower voltage when in deep sleep)
*/
omap_writew(ULPD_SETUP_ANALOG_CELL_3_VAL, ULPD_SETUP_ANALOG_CELL_3);
/* Setup ULPD POWER_CTRL_REG - enter deep sleep whenever possible */
omap_writew(ULPD_POWER_CTRL_REG_VAL, ULPD_POWER_CTRL);
/* Configure IDLECT3 */
if (cpu_is_omap16xx())
omap_writel(OMAP1610_IDLECT3_VAL, OMAP1610_IDLECT3);
pm_set_ops(&omap_pm_ops);
#if defined(DEBUG) && defined(CONFIG_PROC_FS)
omap_pm_init_proc();
#endif
/* configure LOW_PWR pin */
omap_cfg_reg(T20_1610_LOW_PWR);
return 0;
}
__initcall(omap_pm_init);

View File

@ -66,7 +66,7 @@ ENTRY(omap1510_idle_loop_suspend)
@ get ARM_IDLECT2 into r2
ldrh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
mov r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff
orr r5,r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff00
orr r5, r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff00
strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
@ request ARM idle
@ -76,7 +76,7 @@ ENTRY(omap1510_idle_loop_suspend)
strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
mov r5, #IDLE_WAIT_CYCLES & 0xff
orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00
orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00
l_1510: subs r5, r5, #1
bne l_1510
/*
@ -96,7 +96,7 @@ l_1510: subs r5, r5, #1
strh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
strh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
ldmfd sp!, {r0 - r12, pc} @ restore regs and return
ldmfd sp!, {r0 - r12, pc} @ restore regs and return
ENTRY(omap1510_idle_loop_suspend_sz)
.word . - omap1510_idle_loop_suspend
@ -115,8 +115,8 @@ ENTRY(omap1610_idle_loop_suspend)
@ turn off clock domains
@ get ARM_IDLECT2 into r2
ldrh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
mov r5, #OMAP1610_IDLE_CLOCK_DOMAINS & 0xff
orr r5,r5, #OMAP1610_IDLE_CLOCK_DOMAINS & 0xff00
mov r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff
orr r5, r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff00
strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
@ request ARM idle
@ -126,7 +126,7 @@ ENTRY(omap1610_idle_loop_suspend)
strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
mov r5, #IDLE_WAIT_CYCLES & 0xff
orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00
orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00
l_1610: subs r5, r5, #1
bne l_1610
/*
@ -146,7 +146,7 @@ l_1610: subs r5, r5, #1
strh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
strh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
ldmfd sp!, {r0 - r12, pc} @ restore regs and return
ldmfd sp!, {r0 - r12, pc} @ restore regs and return
ENTRY(omap1610_idle_loop_suspend_sz)
.word . - omap1610_idle_loop_suspend
@ -208,7 +208,7 @@ ENTRY(omap1510_cpu_suspend)
@ turn off clock domains
mov r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff
orr r5,r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff00
orr r5, r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff00
strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
@ request ARM idle
@ -217,7 +217,7 @@ ENTRY(omap1510_cpu_suspend)
strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
mov r5, #IDLE_WAIT_CYCLES & 0xff
orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00
orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00
l_1510_2:
subs r5, r5, #1
bne l_1510_2
@ -237,7 +237,7 @@ l_1510_2:
strh r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
@ restore regs and return
ldmfd sp!, {r0 - r12, pc}
ldmfd sp!, {r0 - r12, pc}
ENTRY(omap1510_cpu_suspend_sz)
.word . - omap1510_cpu_suspend
@ -249,21 +249,26 @@ ENTRY(omap1610_cpu_suspend)
@ save registers on stack
stmfd sp!, {r0 - r12, lr}
@ Drain write cache
mov r4, #0
mcr p15, 0, r0, c7, c10, 4
nop
@ load base address of Traffic Controller
mov r4, #TCMIF_ASM_BASE & 0xff000000
orr r4, r4, #TCMIF_ASM_BASE & 0x00ff0000
orr r4, r4, #TCMIF_ASM_BASE & 0x0000ff00
mov r6, #TCMIF_ASM_BASE & 0xff000000
orr r6, r6, #TCMIF_ASM_BASE & 0x00ff0000
orr r6, r6, #TCMIF_ASM_BASE & 0x0000ff00
@ prepare to put SDRAM into self-refresh manually
ldr r5, [r4, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
orr r5, r5, #SELF_REFRESH_MODE & 0xff000000
orr r5, r5, #SELF_REFRESH_MODE & 0x000000ff
str r5, [r4, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
ldr r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
orr r9, r7, #SELF_REFRESH_MODE & 0xff000000
orr r9, r9, #SELF_REFRESH_MODE & 0x000000ff
str r9, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
@ prepare to put EMIFS to Sleep
ldr r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
orr r5, r5, #IDLE_EMIFS_REQUEST & 0xff
str r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
ldr r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
orr r9, r8, #IDLE_EMIFS_REQUEST & 0xff
str r9, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
@ load base address of ARM_IDLECT1 and ARM_IDLECT2
mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000
@ -271,26 +276,22 @@ ENTRY(omap1610_cpu_suspend)
orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00
@ turn off clock domains
mov r5, #OMAP1610_IDLE_CLOCK_DOMAINS & 0xff
orr r5,r5, #OMAP1610_IDLE_CLOCK_DOMAINS & 0xff00
strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
@ work around errata of OMAP1610/5912. Enable (!) peripheral
@ clock to let the chip go into deep sleep
ldrh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
orr r5,r5, #EN_PERCK_BIT & 0xff
@ do not disable PERCK (0x04)
mov r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff
orr r5, r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff00
strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
@ request ARM idle
mov r3, #OMAP1610_DEEP_SLEEP_REQUEST & 0xff
orr r3, r3, #OMAP1610_DEEP_SLEEP_REQUEST & 0xff00
mov r3, #OMAP1610_IDLECT1_SLEEP_VAL & 0xff
orr r3, r3, #OMAP1610_IDLECT1_SLEEP_VAL & 0xff00
strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
mov r5, #IDLE_WAIT_CYCLES & 0xff
orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00
l_1610_2:
subs r5, r5, #1
bne l_1610_2
@ disable instruction cache
mrc p15, 0, r9, c1, c0, 0
bic r2, r9, #0x1000
mcr p15, 0, r2, c1, c0, 0
nop
/*
* Let's wait for the next wake up event to wake us up. r0 can't be
* used here because r0 holds ARM_IDLECT1
@ -301,13 +302,21 @@ l_1610_2:
* omap1610_cpu_suspend()'s resume point.
*
* It will just start executing here, so we'll restore stuff from the
* stack, reset the ARM_IDLECT1 and ARM_IDLECT2.
* stack.
*/
@ re-enable Icache
mcr p15, 0, r9, c1, c0, 0
@ reset the ARM_IDLECT1 and ARM_IDLECT2.
strh r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
strh r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
@ Restore EMIFF controls
str r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
str r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
@ restore regs and return
ldmfd sp!, {r0 - r12, pc}
ldmfd sp!, {r0 - r12, pc}
ENTRY(omap1610_cpu_suspend_sz)
.word . - omap1610_cpu_suspend

View File

@ -0,0 +1,58 @@
/*
* linux/arch/arm/plat-omap/sram.S
*
* Functions that need to be run in internal SRAM
*
* 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/linkage.h>
#include <asm/assembler.h>
#include <asm/arch/io.h>
#include <asm/arch/hardware.h>
.text
/*
* Reprograms ULPD and CKCTL.
*/
ENTRY(sram_reprogram_clock)
stmfd sp!, {r0 - r12, lr} @ save registers on stack
mov r2, #IO_ADDRESS(DPLL_CTL) & 0xff000000
orr r2, r2, #IO_ADDRESS(DPLL_CTL) & 0x00ff0000
orr r2, r2, #IO_ADDRESS(DPLL_CTL) & 0x0000ff00
mov r3, #IO_ADDRESS(ARM_CKCTL) & 0xff000000
orr r3, r3, #IO_ADDRESS(ARM_CKCTL) & 0x00ff0000
orr r3, r3, #IO_ADDRESS(ARM_CKCTL) & 0x0000ff00
tst r0, #1 << 4 @ want lock mode?
beq newck @ nope
bic r0, r0, #1 << 4 @ else clear lock bit
strh r0, [r2] @ set dpll into bypass mode
orr r0, r0, #1 << 4 @ set lock bit again
newck:
strh r1, [r3] @ write new ckctl value
strh r0, [r2] @ write new dpll value
mov r4, #0x0700 @ let the clocks settle
orr r4, r4, #0x00ff
delay: sub r4, r4, #1
cmp r4, #0
bne delay
lock: ldrh r4, [r2], #0 @ read back dpll value
tst r0, #1 << 4 @ want lock mode?
beq out @ nope
tst r4, #1 << 0 @ dpll rate locked?
beq lock @ try again
out:
ldmfd sp!, {r0 - r12, pc} @ restore regs and return
ENTRY(sram_reprogram_clock_sz)
.word . - sram_reprogram_clock

View File

@ -0,0 +1,116 @@
/*
* linux/arch/arm/plat-omap/sram.c
*
* OMAP SRAM detection and management
*
* Copyright (C) 2005 Nokia Corporation
* Written by Tony Lindgren <tony@atomide.com>
*
* 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 <asm/mach/map.h>
#include <asm/io.h>
#include <asm/cacheflush.h>
#include "sram.h"
#define OMAP1_SRAM_BASE 0xd0000000
#define OMAP1_SRAM_START 0x20000000
#define SRAM_BOOTLOADER_SZ 0x80
static unsigned long omap_sram_base;
static unsigned long omap_sram_size;
static unsigned long omap_sram_ceil;
/*
* The amount of SRAM depends on the core type:
* 730 = 200K, 1510 = 512K, 5912 = 256K, 1610 = 16K, 1710 = 16K
* Note that we cannot try to test for SRAM here because writes
* to secure SRAM will hang the system. Also the SRAM is not
* yet mapped at this point.
*/
void __init omap_detect_sram(void)
{
omap_sram_base = OMAP1_SRAM_BASE;
if (cpu_is_omap730())
omap_sram_size = 0x32000;
else if (cpu_is_omap1510())
omap_sram_size = 0x80000;
else if (cpu_is_omap1610() || cpu_is_omap1621() || cpu_is_omap1710())
omap_sram_size = 0x4000;
else if (cpu_is_omap1611())
omap_sram_size = 0x3e800;
else {
printk(KERN_ERR "Could not detect SRAM size\n");
omap_sram_size = 0x4000;
}
printk(KERN_INFO "SRAM size: 0x%lx\n", omap_sram_size);
omap_sram_ceil = omap_sram_base + omap_sram_size;
}
static struct map_desc omap_sram_io_desc[] __initdata = {
{ OMAP1_SRAM_BASE, OMAP1_SRAM_START, 0, MT_DEVICE }
};
/*
* In order to use last 2kB of SRAM on 1611b, we must round the size
* up to multiple of PAGE_SIZE. We cannot use ioremap for SRAM, as
* clock init needs SRAM early.
*/
void __init omap_map_sram(void)
{
if (omap_sram_size == 0)
return;
omap_sram_io_desc[0].length = (omap_sram_size + PAGE_SIZE-1)/PAGE_SIZE;
omap_sram_io_desc[0].length *= PAGE_SIZE;
iotable_init(omap_sram_io_desc, ARRAY_SIZE(omap_sram_io_desc));
/*
* Looks like we need to preserve some bootloader code at the
* beginning of SRAM for jumping to flash for reboot to work...
*/
memset((void *)omap_sram_base + SRAM_BOOTLOADER_SZ, 0,
omap_sram_size - SRAM_BOOTLOADER_SZ);
}
static void (*_omap_sram_reprogram_clock)(u32 dpllctl, u32 ckctl) = NULL;
void omap_sram_reprogram_clock(u32 dpllctl, u32 ckctl)
{
if (_omap_sram_reprogram_clock == NULL)
panic("Cannot use SRAM");
return _omap_sram_reprogram_clock(dpllctl, ckctl);
}
void * omap_sram_push(void * start, unsigned long size)
{
if (size > (omap_sram_ceil - (omap_sram_base + SRAM_BOOTLOADER_SZ))) {
printk(KERN_ERR "Not enough space in SRAM\n");
return NULL;
}
omap_sram_ceil -= size;
omap_sram_ceil &= ~0x3;
memcpy((void *)omap_sram_ceil, start, size);
return (void *)omap_sram_ceil;
}
void __init omap_sram_init(void)
{
omap_detect_sram();
omap_map_sram();
_omap_sram_reprogram_clock = omap_sram_push(sram_reprogram_clock,
sram_reprogram_clock_sz);
}

View File

@ -0,0 +1,21 @@
/*
* linux/arch/arm/plat-omap/sram.h
*
* Interface for functions that need to be run in internal SRAM
*
* 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.
*/
#ifndef __ARCH_ARM_OMAP_SRAM_H
#define __ARCH_ARM_OMAP_SRAM_H
extern void * omap_sram_push(void * start, unsigned long size);
extern void omap_sram_reprogram_clock(u32 dpllctl, u32 ckctl);
/* Do not use these */
extern void sram_reprogram_clock(u32 ckctl, u32 dpllctl);
extern unsigned long sram_reprogram_clock_sz;
#endif

View File

@ -41,6 +41,7 @@
/* These routines should handle the standard chip-specific modes
* for usb0/1/2 ports, covering basic mux and transceiver setup.
* Call omap_usb_init() once, from INIT_MACHINE().
*
* Some board-*.c files will need to set up additional mux options,
* like for suspend handling, vbus sensing, GPIOs, and the D+ pullup.

View File

@ -55,6 +55,10 @@ config GENERIC_BUST_SPINLOCK
config GENERIC_ISA_DMA
bool
config ARCH_MAY_HAVE_PC_FDC
bool
default y
source "init/Kconfig"

View File

@ -17,10 +17,6 @@ ifeq ($(CONFIG_FRAME_POINTER),y)
CFLAGS +=-fno-omit-frame-pointer -mno-sched-prolog
endif
ifeq ($(CONFIG_DEBUG_INFO),y)
CFLAGS +=-g
endif
CFLAGS_BOOT :=-mapcs-26 -mcpu=arm3 -msoft-float -Uarm
CFLAGS +=-mapcs-26 -mcpu=arm3 -msoft-float -Uarm
AFLAGS +=-mapcs-26 -mcpu=arm3 -msoft-float

View File

@ -114,7 +114,7 @@ static unsigned long next_rtc_update;
*/
static inline void do_set_rtc(void)
{
if (time_status & STA_UNSYNC || set_rtc == NULL)
if (!ntp_synced() || set_rtc == NULL)
return;
//FIXME - timespec.tv_sec is a time_t not unsigned long
@ -189,10 +189,7 @@ int do_settimeofday(struct timespec *tv)
xtime.tv_sec = tv->tv_sec;
xtime.tv_nsec = tv->tv_nsec;
time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC;
time_maxerror = NTP_PHASE_LIMIT;
time_esterror = NTP_PHASE_LIMIT;
ntp_clear();
write_sequnlock_irq(&xtime_lock);
clock_was_set();
return 0;

Some files were not shown because too many files have changed in this diff Show More