Merge linux-2.6 with linux-acpi-2.6
This commit is contained in:
commit
64e47488c9
1968 changed files with 58374 additions and 48994 deletions
|
@ -96,7 +96,7 @@
|
||||||
|
|
||||||
<chapter id="pubfunctions">
|
<chapter id="pubfunctions">
|
||||||
<title>Public Functions Provided</title>
|
<title>Public Functions Provided</title>
|
||||||
!Earch/i386/kernel/mca.c
|
!Edrivers/mca/mca-legacy.c
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
||||||
<chapter id="dmafunctions">
|
<chapter id="dmafunctions">
|
||||||
|
|
|
@ -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
|
it will send the proper IPMI commands to do this. This is supported on
|
||||||
several platforms.
|
several platforms.
|
||||||
|
|
||||||
There is a module parameter named "poweroff_control" that may either be zero
|
There is a module parameter named "poweroff_powercycle" that may
|
||||||
(do a power down) or 2 (do a power cycle, power the system off, then power
|
either be zero (do a power down) or non-zero (do a power cycle, power
|
||||||
it on in a few seconds). Setting ipmi_poweroff.poweroff_control=x will do
|
the system off, then power it on in a few seconds). Setting
|
||||||
the same thing on the kernel command line. The parameter is also available
|
ipmi_poweroff.poweroff_control=x will do the same thing on the kernel
|
||||||
via the proc filesystem in /proc/ipmi/poweroff_control. Note that if the
|
command line. The parameter is also available via the proc filesystem
|
||||||
system does not support power cycling, it will always to the power off.
|
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
|
Note that if you have ACPI enabled, the system will prefer using ACPI to
|
||||||
power off.
|
power off.
|
||||||
|
|
112
Documentation/RCU/NMI-RCU.txt
Normal file
112
Documentation/RCU/NMI-RCU.txt
Normal 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.
|
|
@ -68,7 +68,8 @@ it a better device citizen. Further thanks to Joel Katz
|
||||||
Porfiri Claudio <C.Porfiri@nisms.tei.ericsson.se> for patches
|
Porfiri Claudio <C.Porfiri@nisms.tei.ericsson.se> for patches
|
||||||
to make the driver work with the older CDU-510/515 series, and
|
to make the driver work with the older CDU-510/515 series, and
|
||||||
Heiko Eissfeldt <heiko@colossus.escape.de> for pointing out that
|
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:)
|
(Acknowledgments from Ron Jeppesen in the 0.3 release:)
|
||||||
Thanks to Corey Minyard who wrote the original CDU-31A driver on which
|
Thanks to Corey Minyard who wrote the original CDU-31A driver on which
|
||||||
|
|
|
@ -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
|
load balancing code trying to pull tasks outside of the cpu exclusive
|
||||||
cpuset only to be prevented by the tasks' cpus_allowed mask.
|
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
|
User level code may create and destroy cpusets by name in the cpuset
|
||||||
virtual file system, manage the attributes and permissions of these
|
virtual file system, manage the attributes and permissions of these
|
||||||
cpusets and which CPUs and Memory Nodes are assigned to each cpuset,
|
cpusets and which CPUs and Memory Nodes are assigned to each cpuset,
|
||||||
|
|
|
@ -223,6 +223,7 @@ CAST5 algorithm contributors:
|
||||||
|
|
||||||
TEA/XTEA algorithm contributors:
|
TEA/XTEA algorithm contributors:
|
||||||
Aaron Grothe
|
Aaron Grothe
|
||||||
|
Michael Ringe
|
||||||
|
|
||||||
Khazad algorithm contributors:
|
Khazad algorithm contributors:
|
||||||
Aaron Grothe
|
Aaron Grothe
|
||||||
|
|
91
Documentation/dcdbas.txt
Normal file
91
Documentation/dcdbas.txt
Normal 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
|
||||||
|
|
||||||
|
|
74
Documentation/dell_rbu.txt
Normal file
74
Documentation/dell_rbu.txt
Normal 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.
|
||||||
|
|
|
@ -16,7 +16,7 @@ Enable the following options:
|
||||||
"Device drivers" => "Multimedia devices"
|
"Device drivers" => "Multimedia devices"
|
||||||
=> "Video For Linux" => "BT848 Video For Linux"
|
=> "Video For Linux" => "BT848 Video For Linux"
|
||||||
"Device drivers" => "Multimedia devices" => "Digital Video Broadcasting Devices"
|
"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
|
3) Loading Modules, described by two approaches
|
||||||
===============================================
|
===============================================
|
||||||
|
|
|
@ -7,7 +7,7 @@ To protect itself the kernel has to verify this address.
|
||||||
|
|
||||||
In older versions of Linux this was done with the
|
In older versions of Linux this was done with the
|
||||||
int verify_area(int type, const void * addr, unsigned long size)
|
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
|
This function verified that the memory area starting at address
|
||||||
addr and of size size was accessible for the operation specified
|
addr and of size size was accessible for the operation specified
|
||||||
|
|
|
@ -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
|
What: RCU API moves to EXPORT_SYMBOL_GPL
|
||||||
When: April 2006
|
When: April 2006
|
||||||
Files: include/linux/rcupdate.h, kernel/rcupdate.c
|
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,
|
What: IEEE1394 Audio and Music Data Transmission Protocol driver,
|
||||||
Connection Management Procedures driver
|
Connection Management Procedures driver
|
||||||
When: November 2005
|
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
|
What: i2c sysfs name change: in1_ref, vid deprecated in favour of cpu0_vid
|
||||||
When: November 2005
|
When: November 2005
|
||||||
Files: drivers/i2c/chips/adm1025.c, drivers/i2c/chips/adm1026.c
|
Files: drivers/i2c/chips/adm1025.c, drivers/i2c/chips/adm1026.c
|
||||||
|
|
|
@ -133,6 +133,7 @@ Table 1-1: Process specific entries in /proc
|
||||||
statm Process memory status information
|
statm Process memory status information
|
||||||
status Process status in human readable form
|
status Process status in human readable form
|
||||||
wchan If CONFIG_KALLSYMS is set, a pre-decoded wchan
|
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
|
For example, to get the status information of a process, all you have to do is
|
||||||
|
|
362
Documentation/filesystems/relayfs.txt
Normal file
362
Documentation/filesystems/relayfs.txt
Normal 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.
|
|
@ -90,7 +90,7 @@ void device_remove_file(struct device *, struct device_attribute *);
|
||||||
|
|
||||||
It also defines this helper for defining device attributes:
|
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 = { \
|
struct device_attribute dev_attr_##_name = { \
|
||||||
.attr = {.name = __stringify(_name) , .mode = _mode }, \
|
.attr = {.name = __stringify(_name) , .mode = _mode }, \
|
||||||
.show = _show, \
|
.show = _show, \
|
||||||
|
@ -99,14 +99,14 @@ struct device_attribute dev_attr_##_name = { \
|
||||||
|
|
||||||
For example, declaring
|
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:
|
is equivalent to doing:
|
||||||
|
|
||||||
static struct device_attribute dev_attr_foo = {
|
static struct device_attribute dev_attr_foo = {
|
||||||
.attr = {
|
.attr = {
|
||||||
.name = "foo",
|
.name = "foo",
|
||||||
.mode = 0644,
|
.mode = S_IWUSR | S_IRUGO,
|
||||||
},
|
},
|
||||||
.show = show_foo,
|
.show = show_foo,
|
||||||
.store = store_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.
|
show and store methods of the attribute owners.
|
||||||
|
|
||||||
struct sysfs_ops {
|
struct sysfs_ops {
|
||||||
ssize_t (*show)(struct kobject *, struct attribute *,char *);
|
ssize_t (*show)(struct kobject *, struct attribute *, char *);
|
||||||
ssize_t (*store)(struct kobject *,struct attribute *,const char *);
|
ssize_t (*store)(struct kobject *, struct attribute *, const char *);
|
||||||
};
|
};
|
||||||
|
|
||||||
[ Subsystems should have already defined a struct kobj_type as a
|
[ Subsystems should have already defined a struct kobj_type as a
|
||||||
|
@ -137,7 +137,7 @@ calls the associated methods.
|
||||||
|
|
||||||
To illustrate:
|
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)
|
#define to_dev(d) container_of(d, struct device, kobj)
|
||||||
|
|
||||||
static ssize_t
|
static ssize_t
|
||||||
|
@ -148,7 +148,7 @@ dev_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
|
||||||
ssize_t ret = 0;
|
ssize_t ret = 0;
|
||||||
|
|
||||||
if (dev_attr->show)
|
if (dev_attr->show)
|
||||||
ret = dev_attr->show(dev,buf);
|
ret = dev_attr->show(dev, buf);
|
||||||
return ret;
|
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)
|
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)
|
static ssize_t store_name(struct device * dev, const char * buf)
|
||||||
{
|
{
|
||||||
sscanf(buf,"%20s",dev->name);
|
sscanf(buf, "%20s", dev->name);
|
||||||
return strlen(buf);
|
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
|
(Note that the real implementation doesn't allow userspace to set the
|
||||||
|
@ -290,7 +290,7 @@ struct device_attribute {
|
||||||
|
|
||||||
Declaring:
|
Declaring:
|
||||||
|
|
||||||
DEVICE_ATTR(_name,_str,_mode,_show,_store);
|
DEVICE_ATTR(_name, _str, _mode, _show, _store);
|
||||||
|
|
||||||
Creation/Removal:
|
Creation/Removal:
|
||||||
|
|
||||||
|
@ -310,7 +310,7 @@ struct bus_attribute {
|
||||||
|
|
||||||
Declaring:
|
Declaring:
|
||||||
|
|
||||||
BUS_ATTR(_name,_mode,_show,_store)
|
BUS_ATTR(_name, _mode, _show, _store)
|
||||||
|
|
||||||
Creation/Removal:
|
Creation/Removal:
|
||||||
|
|
||||||
|
@ -331,7 +331,7 @@ struct driver_attribute {
|
||||||
|
|
||||||
Declaring:
|
Declaring:
|
||||||
|
|
||||||
DRIVER_ATTR(_name,_mode,_show,_store)
|
DRIVER_ATTR(_name, _mode, _show, _store)
|
||||||
|
|
||||||
Creation/Removal:
|
Creation/Removal:
|
||||||
|
|
||||||
|
|
|
@ -2,16 +2,11 @@ Kernel driver lm78
|
||||||
==================
|
==================
|
||||||
|
|
||||||
Supported chips:
|
Supported chips:
|
||||||
* National Semiconductor LM78
|
* National Semiconductor LM78 / LM78-J
|
||||||
Prefix: 'lm78'
|
Prefix: 'lm78'
|
||||||
Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports)
|
Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports)
|
||||||
Datasheet: Publicly available at the National Semiconductor website
|
Datasheet: Publicly available at the National Semiconductor website
|
||||||
http://www.national.com/
|
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
|
* National Semiconductor LM79
|
||||||
Prefix: 'lm79'
|
Prefix: 'lm79'
|
||||||
Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports)
|
Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports)
|
||||||
|
|
174
Documentation/hwmon/w83792d
Normal file
174
Documentation/hwmon/w83792d
Normal 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
|
|
@ -4,22 +4,13 @@ Kernel driver max6875
|
||||||
Supported chips:
|
Supported chips:
|
||||||
* Maxim MAX6874, MAX6875
|
* Maxim MAX6874, MAX6875
|
||||||
Prefix: 'max6875'
|
Prefix: 'max6875'
|
||||||
Addresses scanned: 0x50, 0x52
|
Addresses scanned: None (see below)
|
||||||
Datasheet:
|
Datasheet:
|
||||||
http://pdfserv.maxim-ic.com/en/ds/MAX6874-MAX6875.pdf
|
http://pdfserv.maxim-ic.com/en/ds/MAX6874-MAX6875.pdf
|
||||||
|
|
||||||
Author: Ben Gardner <bgardner@wabtec.com>
|
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
|
Description
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
|
@ -33,34 +24,85 @@ registers.
|
||||||
|
|
||||||
The Maxim MAX6874 is a similar, mostly compatible device, with more intputs
|
The Maxim MAX6874 is a similar, mostly compatible device, with more intputs
|
||||||
and outputs:
|
and outputs:
|
||||||
|
|
||||||
vin gpi vout
|
vin gpi vout
|
||||||
MAX6874 6 4 8
|
MAX6874 6 4 8
|
||||||
MAX6875 4 3 5
|
MAX6875 4 3 5
|
||||||
|
|
||||||
MAX6874 chips can have four different addresses (as opposed to only two for
|
See the datasheet for more information.
|
||||||
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.
|
|
||||||
|
|
||||||
|
|
||||||
Sysfs entries
|
Sysfs entries
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
eeprom_user - 512 bytes of user-defined EEPROM space. Only writable if
|
eeprom - 512 bytes of user-defined EEPROM space.
|
||||||
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.
|
|
||||||
|
|
||||||
|
|
||||||
General Remarks
|
General Remarks
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
A typical application will require that the EEPROMs be programmed once and
|
Valid addresses for the MAX6875 are 0x50 and 0x52.
|
||||||
never altered afterwards.
|
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.
|
||||||
|
|
||||||
|
|
|
@ -115,7 +115,7 @@ CHECKING THROUGH /DEV
|
||||||
If you try to access an adapter from a userspace program, you will have
|
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
|
to use the /dev interface. You will still have to check whether the
|
||||||
functionality you need is supported, of course. This is done using
|
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:
|
program, is below:
|
||||||
|
|
||||||
int file;
|
int file;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
Revision 4, 2004-03-30
|
Revision 5, 2005-07-29
|
||||||
Jean Delvare <khali@linux-fr.org>
|
Jean Delvare <khali@linux-fr.org>
|
||||||
Greg KH <greg@kroah.com>
|
Greg KH <greg@kroah.com>
|
||||||
|
|
||||||
|
@ -17,20 +17,22 @@ yours for best results.
|
||||||
|
|
||||||
Technical changes:
|
Technical changes:
|
||||||
|
|
||||||
* [Includes] Get rid of "version.h". Replace <linux/i2c-proc.h> with
|
* [Includes] Get rid of "version.h" and <linux/i2c-proc.h>.
|
||||||
<linux/i2c-sensor.h>. Includes typically look like that:
|
Includes typically look like that:
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/i2c.h>
|
#include <linux/i2c.h>
|
||||||
#include <linux/i2c-sensor.h>
|
#include <linux/hwmon.h> /* for hardware monitoring drivers */
|
||||||
#include <linux/i2c-vid.h> /* if you need VRM support */
|
#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 */
|
#include <asm/io.h> /* if you have I/O operations */
|
||||||
Please respect this inclusion order. Some extra headers may be
|
Please respect this inclusion order. Some extra headers may be
|
||||||
required for a given driver (e.g. "lm75.h").
|
required for a given driver (e.g. "lm75.h").
|
||||||
|
|
||||||
* [Addresses] SENSORS_I2C_END becomes I2C_CLIENT_END, SENSORS_ISA_END
|
* [Addresses] SENSORS_I2C_END becomes I2C_CLIENT_END, ISA addresses
|
||||||
becomes I2C_CLIENT_ISA_END.
|
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
|
* [Client data] Get rid of sysctl_id. Try using standard names for
|
||||||
register values (for example, temp_os becomes temp_max). You're
|
register values (for example, temp_os becomes temp_max). You're
|
||||||
|
@ -66,13 +68,15 @@ Technical changes:
|
||||||
if (!(adapter->class & I2C_CLASS_HWMON))
|
if (!(adapter->class & I2C_CLASS_HWMON))
|
||||||
return 0;
|
return 0;
|
||||||
ISA-only drivers of course don't need this.
|
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.
|
* [Detect] As mentioned earlier, the flags parameter is gone.
|
||||||
The type_name and client_name strings are replaced by a single
|
The type_name and client_name strings are replaced by a single
|
||||||
name string, which will be filled with a lowercase, short string
|
name string, which will be filled with a lowercase, short string
|
||||||
(typically the driver name, e.g. "lm75").
|
(typically the driver name, e.g. "lm75").
|
||||||
In i2c-only drivers, drop the i2c_is_isa_adapter check, it's
|
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
|
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
|
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
|
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
|
device_create_file. Move the driver initialization before any
|
||||||
sysfs file creation.
|
sysfs file creation.
|
||||||
Drop client->id.
|
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
|
* [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
|
user-space). Chip should not be reset default (although a module
|
||||||
|
@ -93,7 +99,8 @@ Technical changes:
|
||||||
limited to the strictly necessary steps.
|
limited to the strictly necessary steps.
|
||||||
|
|
||||||
* [Detach] Get rid of data, remove the call to
|
* [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
|
* [Update] Don't access client->data directly, use
|
||||||
i2c_get_clientdata(client) instead.
|
i2c_get_clientdata(client) instead.
|
||||||
|
|
|
@ -148,15 +148,15 @@ are defined in i2c.h to help you support them, as well as a generic
|
||||||
detection algorithm.
|
detection algorithm.
|
||||||
|
|
||||||
You do not have to use this parameter interface; but don't try to use
|
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
|
NOTE: If you want to write a `sensors' driver, the interface is slightly
|
||||||
different! See below.
|
different! See below.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Probing classes (i2c)
|
Probing classes
|
||||||
---------------------
|
---------------
|
||||||
|
|
||||||
All parameters are given as lists of unsigned 16-bit integers. Lists are
|
All parameters are given as lists of unsigned 16-bit integers. Lists are
|
||||||
terminated by I2C_CLIENT_END.
|
terminated by I2C_CLIENT_END.
|
||||||
|
@ -171,12 +171,18 @@ The following lists are used internally:
|
||||||
ignore: insmod parameter.
|
ignore: insmod parameter.
|
||||||
A list of pairs. The first value is a bus number (-1 for any I2C bus),
|
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.
|
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.
|
force: insmod parameter.
|
||||||
A list of pairs. The first value is a bus number (-1 for any I2C bus),
|
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 second is the I2C address. A device is blindly assumed to be on
|
||||||
the given address, no probing is done.
|
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'
|
Fortunately, as a module writer, you just have to define the `normal_i2c'
|
||||||
parameter. The complete declaration could look like this:
|
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 */
|
/* Magic definition of all other variables and things */
|
||||||
I2C_CLIENT_INSMOD;
|
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',
|
Note that you *have* to call the defined variable `normal_i2c',
|
||||||
without any prefix!
|
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
|
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);
|
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,
|
Remember, structure `addr_data' is defined by the macros explained above,
|
||||||
so you do not have to define it yourself.
|
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
|
function only for those i2c addresses that actually have a device on
|
||||||
them (unless a `force' parameter was used). In addition, addresses that
|
them (unless a `force' parameter was used). In addition, addresses that
|
||||||
are already in use (by some other registered client) are skipped.
|
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
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
The detect client function is called by i2c_probe or i2c_detect.
|
The detect client function is called by i2c_probe. The `kind' parameter
|
||||||
The `kind' parameter contains 0 if this call is due to a `force'
|
contains -1 for a probed detection, 0 for a forced detection, or a positive
|
||||||
parameter, and -1 otherwise (for i2c_detect, it contains 0 if
|
number for a forced detection with a chip type forced.
|
||||||
this call is due to the generic `force' parameter, and the chip type
|
|
||||||
number if it is due to a specific `force' parameter).
|
|
||||||
|
|
||||||
Below, some things are only needed if this is a `sensors' driver. Those
|
Below, some things are only needed if this is a `sensors' driver. Those
|
||||||
parts are between /* SENSORS ONLY START */ and /* SENSORS ONLY END */
|
parts are between /* SENSORS ONLY START */ and /* SENSORS ONLY END */
|
||||||
markers.
|
markers.
|
||||||
|
|
||||||
This function should only return an error (any value != 0) if there is
|
Returning an error different from -ENODEV in a detect function will cause
|
||||||
some reason why no more detection should be done anymore. If the
|
the detection to stop: other addresses and adapters won't be scanned.
|
||||||
detection just fails for this address, return 0.
|
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.
|
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 = "";
|
const char *type_name = "";
|
||||||
int is_isa = i2c_is_isa_adapter(adapter);
|
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
|
if (is_isa) {
|
||||||
(call `goto ERROR0'). But for kicks, we will assume it is all
|
|
||||||
right. */
|
|
||||||
|
|
||||||
/* Discard immediately if this ISA range is already used */
|
/* Discard immediately if this ISA range is already used */
|
||||||
if (check_region(address,FOO_EXTENT))
|
if (check_region(address,FOO_EXTENT))
|
||||||
|
@ -495,15 +443,13 @@ much simpler than the attachment code, fortunately!
|
||||||
/* SENSORS ONLY END */
|
/* SENSORS ONLY END */
|
||||||
|
|
||||||
/* Try to detach the client from i2c space */
|
/* Try to detach the client from i2c space */
|
||||||
if ((err = i2c_detach_client(client))) {
|
if ((err = i2c_detach_client(client)))
|
||||||
printk("foo.o: Client deregistration failed, client not detached.\n");
|
|
||||||
return err;
|
return err;
|
||||||
}
|
|
||||||
|
|
||||||
/* SENSORS ONLY START */
|
/* HYBRID SENSORS CHIP ONLY START */
|
||||||
if i2c_is_isa_client(client)
|
if i2c_is_isa_client(client)
|
||||||
release_region(client->addr,LM78_EXTENT);
|
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 */
|
kfree(client); /* Frees client data too, if allocated at the same time */
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
H. Peter Anvin <hpa@zytor.com>
|
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
|
On the i386 platform, the Linux kernel uses a rather complicated boot
|
||||||
convention. This has evolved partially due to historical aspects, as
|
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
|
Protocol 2.03: (Kernel 2.4.18-pre1) Explicitly makes the highest possible
|
||||||
initrd address available to the bootloader.
|
initrd address available to the bootloader.
|
||||||
|
|
||||||
|
Protocol 2.04: (Kernel 2.6.14) Extend the syssize field to four bytes.
|
||||||
|
|
||||||
|
|
||||||
**** MEMORY LAYOUT
|
**** MEMORY LAYOUT
|
||||||
|
|
||||||
|
@ -103,10 +105,9 @@ The header looks like:
|
||||||
Offset Proto Name Meaning
|
Offset Proto Name Meaning
|
||||||
/Size
|
/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
|
01F2/2 ALL root_flags If set, the root is mounted readonly
|
||||||
01F4/2 ALL syssize DO NOT USE - for bootsect.S use only
|
01F4/4 2.04+(2 syssize The size of the 32-bit code in 16-byte paras
|
||||||
01F6/2 ALL swap_dev DO NOT USE - obsolete
|
|
||||||
01F8/2 ALL ram_size DO NOT USE - for bootsect.S use only
|
01F8/2 ALL ram_size DO NOT USE - for bootsect.S use only
|
||||||
01FA/2 ALL vid_mode Video mode control
|
01FA/2 ALL vid_mode Video mode control
|
||||||
01FC/2 ALL root_dev Default root device number
|
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
|
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
|
022C/4 2.03+ initrd_addr_max Highest legal initrd address
|
||||||
|
|
||||||
For backwards compatibility, if the setup_sects field contains 0, the
|
(1) For backwards compatibility, if the setup_sects field contains 0, the
|
||||||
real value is 4.
|
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,
|
If the "HdrS" (0x53726448) magic number is not found at offset 0x202,
|
||||||
the boot protocol version is "old". Loading an old kernel, the
|
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"
|
relevant to the boot loader itself, see "special command line options"
|
||||||
below.
|
below.
|
||||||
|
|
||||||
The kernel command line is a null-terminated string up to 255
|
The kernel command line is a null-terminated string currently up to
|
||||||
characters long, plus the final null.
|
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
|
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
|
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
|
If the protocol version is *not* 2.02 or higher, the kernel
|
||||||
command line is entered using the following protocol:
|
command line is entered using the following protocol:
|
||||||
|
@ -255,7 +264,7 @@ command line is entered using the following protocol:
|
||||||
**** SAMPLE BOOT CONFIGURATION
|
**** SAMPLE BOOT CONFIGURATION
|
||||||
|
|
||||||
As a sample configuration, assume the following layout of the real
|
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
|
0x0000-0x7FFF Real mode kernel
|
||||||
0x8000-0x8FFF Stack and heap
|
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
|
**** LOADING THE REST OF THE KERNEL
|
||||||
|
|
||||||
The non-real-mode kernel starts at offset (setup_sects+1)*512 in the
|
The 32-bit (non-real-mode) kernel starts at offset (setup_sects+1)*512
|
||||||
kernel file (again, if setup_sects == 0 the real value is 4.) It
|
in the kernel file (again, if setup_sects == 0 the real value is 4.)
|
||||||
should be loaded at address 0x10000 for Image/zImage kernels and
|
It should be loaded at address 0x10000 for Image/zImage kernels and
|
||||||
0x100000 for bzImage kernels.
|
0x100000 for bzImage kernels.
|
||||||
|
|
||||||
The kernel is a bzImage kernel if the protocol >= 2.00 and the 0x01
|
The kernel is a bzImage kernel if the protocol >= 2.00 and the 0x01
|
||||||
|
|
|
@ -872,7 +872,13 @@ When kbuild executes the following steps are followed (roughly):
|
||||||
Assignments to $(targets) are without $(obj)/ prefix.
|
Assignments to $(targets) are without $(obj)/ prefix.
|
||||||
if_changed may be used in conjunction with custom commands as
|
if_changed may be used in conjunction with custom commands as
|
||||||
defined in 6.7 "Custom kbuild commands".
|
defined in 6.7 "Custom kbuild commands".
|
||||||
|
|
||||||
Note: It is a typical mistake to forget the FORCE prerequisite.
|
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
|
ld
|
||||||
Link target. Often LDFLAGS_$@ is used to set specific options to ld.
|
Link target. Often LDFLAGS_$@ is used to set specific options to ld.
|
||||||
|
|
|
@ -1174,6 +1174,11 @@ running once the system is up.
|
||||||
New name for the ramdisk parameter.
|
New name for the ramdisk parameter.
|
||||||
See Documentation/ramdisk.txt.
|
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
|
reboot= [BUGS=IA-32,BUGS=ARM,BUGS=IA-64] Rebooting mode
|
||||||
Format: <reboot_mode>[,<reboot_mode2>[,...]]
|
Format: <reboot_mode>[,<reboot_mode2>[,...]]
|
||||||
See arch/*/kernel/reboot.c.
|
See arch/*/kernel/reboot.c.
|
||||||
|
|
138
Documentation/power/swsusp-dmcrypt.txt
Normal file
138
Documentation/power/swsusp-dmcrypt.txt
Normal 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.
|
|
@ -1,22 +1,20 @@
|
||||||
From kernel/suspend.c:
|
Some warnings, first.
|
||||||
|
|
||||||
* BIG FAT WARNING *********************************************************
|
* 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...
|
* If you touch anything on disk between suspend and resume...
|
||||||
* ...kiss your data goodbye.
|
* ...kiss your data goodbye.
|
||||||
*
|
*
|
||||||
* If your disk driver does not support suspend... (IDE does)
|
* If you do resume from initrd after your filesystems are mounted...
|
||||||
* ...you'd better find out how to get along
|
* ...bye bye root partition.
|
||||||
* without your data.
|
* [this is actually same case as above]
|
||||||
*
|
*
|
||||||
* If you change kernel command line between suspend and resume...
|
* If you have unsupported (*) devices using DMA, you may have some
|
||||||
* ...prepare for nasty fsck or worse.
|
* problems. If your disk driver does not support suspend... (IDE does),
|
||||||
*
|
* it may cause some problems, too. If you change kernel command line
|
||||||
* If you change your hardware while system is suspended...
|
* between suspend and resume, it may do something wrong. If you change
|
||||||
* ...well, it was not good idea.
|
* 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.
|
* (*) 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
|
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
|
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
|
You have your server on UPS. Power died, and UPS is indicating 30
|
||||||
seconds to failure. What do you do? Suspend to disk.
|
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?
|
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.
|
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'?
|
Q: What is 'suspend2'?
|
||||||
|
|
||||||
A: suspend2 is 'Software Suspend 2', a forked implementation of
|
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
|
system is shut down or suspended. Additionally use the encrypted
|
||||||
suspend image to prevent sensitive data from being stolen after
|
suspend image to prevent sensitive data from being stolen after
|
||||||
resume.
|
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.
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
POSTing bios works. Ole Rohne has patch to do just that at
|
||||||
http://dev.gentoo.org/~marineam/patch-radeonfb-2.6.11-rc2-mm2.
|
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
|
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
|
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
|
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 Aspire 1406LC ole's late BIOS init (7), turn off DRI
|
||||||
Acer TM 242FX vbetool (6)
|
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 4052LCi s3_bios (2)
|
||||||
Acer TM 636Lci s3_bios vga=normal (2)
|
Acer TM 636Lci s3_bios vga=normal (2)
|
||||||
Acer TM 650 (Radeon M7) vga=normal plus boot-radeon (5) gets text console back
|
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 X20 ??? (*)
|
||||||
IBM TP X30 s3_bios (2)
|
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 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)
|
IBM Thinkpad X40 Type 2371-7JG s3_bios,s3_mode (4)
|
||||||
Medion MD4220 ??? (*)
|
Medion MD4220 ??? (*)
|
||||||
Samsung P35 vbetool needed (6)
|
Samsung P35 vbetool needed (6)
|
||||||
|
|
|
@ -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 =
|
= README for =
|
||||||
= The Linux Operating System =
|
= The Linux Operating System =
|
||||||
====================================================================
|
====================================================================
|
||||||
|
@ -131,6 +131,10 @@ The following information is available in this file:
|
||||||
SCSI "stub" effects.
|
SCSI "stub" effects.
|
||||||
|
|
||||||
2. Version History
|
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)
|
6.2.36 (June 3rd, 2003)
|
||||||
- Correct code that disables PCI parity error checking.
|
- Correct code that disables PCI parity error checking.
|
||||||
- Correct and simplify handling of the ignore wide residue
|
- Correct and simplify handling of the ignore wide residue
|
||||||
|
|
|
@ -373,13 +373,11 @@ Summary:
|
||||||
scsi_activate_tcq - turn on tag command queueing
|
scsi_activate_tcq - turn on tag command queueing
|
||||||
scsi_add_device - creates new scsi device (lu) instance
|
scsi_add_device - creates new scsi device (lu) instance
|
||||||
scsi_add_host - perform sysfs registration and SCSI bus scan.
|
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_adjust_queue_depth - change the queue depth on a SCSI device
|
||||||
scsi_assign_lock - replace default host_lock with given lock
|
scsi_assign_lock - replace default host_lock with given lock
|
||||||
scsi_bios_ptable - return copy of block device's partition table
|
scsi_bios_ptable - return copy of block device's partition table
|
||||||
scsi_block_requests - prevent further commands being queued to given host
|
scsi_block_requests - prevent further commands being queued to given host
|
||||||
scsi_deactivate_tcq - turn off tag command queueing
|
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_alloc - return a new scsi_host instance whose refcount==1
|
||||||
scsi_host_get - increments Scsi_Host instance's refcount
|
scsi_host_get - increments Scsi_Host instance's refcount
|
||||||
scsi_host_put - decrements Scsi_Host instance's refcount (free if 0)
|
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)
|
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
|
* scsi_adjust_queue_depth - allow LLD to change queue depth on a SCSI device
|
||||||
* @sdev: pointer to SCSI device to change queue depth on
|
* @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)
|
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
|
* scsi_host_alloc - create a scsi host adapter instance and perform basic
|
||||||
* initialization.
|
* initialization.
|
||||||
|
|
|
@ -99,6 +99,7 @@ statically linked into the kernel). Those options are:
|
||||||
SONYPI_MEYE_MASK 0x0400
|
SONYPI_MEYE_MASK 0x0400
|
||||||
SONYPI_MEMORYSTICK_MASK 0x0800
|
SONYPI_MEMORYSTICK_MASK 0x0800
|
||||||
SONYPI_BATTERY_MASK 0x1000
|
SONYPI_BATTERY_MASK 0x1000
|
||||||
|
SONYPI_WIRELESS_MASK 0x2000
|
||||||
|
|
||||||
useinput: if set (which is the default) two input devices are
|
useinput: if set (which is the default) two input devices are
|
||||||
created, one which interprets the jogdial events as
|
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
|
speed handling etc). Use ACPI instead of APM if it works on your
|
||||||
laptop.
|
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
|
- since all development was done by reverse engineering, there is
|
||||||
_absolutely no guarantee_ that this driver will not crash your
|
_absolutely no guarantee_ that this driver will not crash your
|
||||||
laptop. Permanently.
|
laptop. Permanently.
|
||||||
|
|
|
@ -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
|
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.
|
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 devices are chained in priority order from the "swap_list" header.
|
||||||
The "swap_list" is used for the round-robin swaphandle allocation strategy.
|
The "swap_list" is used for the round-robin swaphandle allocation strategy.
|
||||||
The #free swaphandles is maintained in "nr_swap_pages". These two together
|
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
|
The swap_lock also protects all the device reference counts on the
|
||||||
counts on the corresponding swaphandles, maintained in the "swap_map"
|
corresponding swaphandles, maintained in the "swap_map" array, and the
|
||||||
array, and the "highest_bit" and "lowest_bit" fields.
|
"highest_bit" and "lowest_bit" fields.
|
||||||
|
|
||||||
Both of these are spinlocks, and are never acquired from intr level. The
|
The swap_lock is a spinlock, and is never acquired from intr level.
|
||||||
locking hierarchy is swap_list_lock -> swap_device_lock.
|
|
||||||
|
|
||||||
To prevent races between swap space deletion or async readahead swapins
|
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
|
deciding whether a swap handle is being used, ie worthy of being read in
|
||||||
|
|
|
@ -228,6 +228,26 @@ advantechwdt.c -- Advantech Single Board Computer
|
||||||
The GETSTATUS call returns if the device is open or not.
|
The GETSTATUS call returns if the device is open or not.
|
||||||
[FIXME -- silliness again?]
|
[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
|
eurotechwdt.c -- Eurotech CPU-1220/1410
|
||||||
|
|
||||||
The timeout can be set using the SETTIMEOUT ioctl and defaults
|
The timeout can be set using the SETTIMEOUT ioctl and defaults
|
||||||
|
|
31
MAINTAINERS
31
MAINTAINERS
|
@ -202,13 +202,6 @@ P: Colin Leroy
|
||||||
M: colin@colino.net
|
M: colin@colino.net
|
||||||
S: Maintained
|
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
|
AEDSP16 DRIVER
|
||||||
P: Riccardo Facchetti
|
P: Riccardo Facchetti
|
||||||
M: fizban@tin.it
|
M: fizban@tin.it
|
||||||
|
@ -696,6 +689,11 @@ M: dz@debian.org
|
||||||
W: http://www.debian.org/~dz/i8k/
|
W: http://www.debian.org/~dz/i8k/
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
|
DELL SYSTEMS MANAGEMENT BASE DRIVER (dcdbas)
|
||||||
|
P: Doug Warzecha
|
||||||
|
M: Douglas_Warzecha@dell.com
|
||||||
|
S: Maintained
|
||||||
|
|
||||||
DEVICE-MAPPER
|
DEVICE-MAPPER
|
||||||
P: Alasdair Kergon
|
P: Alasdair Kergon
|
||||||
L: dm-devel@redhat.com
|
L: dm-devel@redhat.com
|
||||||
|
@ -824,6 +822,13 @@ L: emu10k1-devel@lists.sourceforge.net
|
||||||
W: http://sourceforge.net/projects/emu10k1/
|
W: http://sourceforge.net/projects/emu10k1/
|
||||||
S: Maintained
|
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
|
EPSON 1355 FRAMEBUFFER DRIVER
|
||||||
P: Christopher Hoover
|
P: Christopher Hoover
|
||||||
M: ch@murgatroid.com, ch@hpl.hp.com
|
M: ch@murgatroid.com, ch@hpl.hp.com
|
||||||
|
@ -879,7 +884,7 @@ S: Maintained
|
||||||
|
|
||||||
FILESYSTEMS (VFS and infrastructure)
|
FILESYSTEMS (VFS and infrastructure)
|
||||||
P: Alexander Viro
|
P: Alexander Viro
|
||||||
M: viro@parcelfarce.linux.theplanet.co.uk
|
M: viro@zeniv.linux.org.uk
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
FIRMWARE LOADER (request_firmware)
|
FIRMWARE LOADER (request_firmware)
|
||||||
|
@ -933,6 +938,13 @@ M: khc@pm.waw.pl
|
||||||
W: http://www.kernel.org/pub/linux/utils/net/hdlc/
|
W: http://www.kernel.org/pub/linux/utils/net/hdlc/
|
||||||
S: Maintained
|
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
|
HARMONY SOUND DRIVER
|
||||||
P: Kyle McMartin
|
P: Kyle McMartin
|
||||||
M: kyle@parisc-linux.org
|
M: kyle@parisc-linux.org
|
||||||
|
@ -1014,7 +1026,7 @@ P: William Irwin
|
||||||
M: wli@holomorphy.com
|
M: wli@holomorphy.com
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
I2C AND SENSORS DRIVERS
|
I2C SUBSYSTEM
|
||||||
P: Greg Kroah-Hartman
|
P: Greg Kroah-Hartman
|
||||||
M: greg@kroah.com
|
M: greg@kroah.com
|
||||||
P: Jean Delvare
|
P: Jean Delvare
|
||||||
|
@ -1960,7 +1972,6 @@ S: Supported
|
||||||
|
|
||||||
ROCKETPORT DRIVER
|
ROCKETPORT DRIVER
|
||||||
P: Comtrol Corp.
|
P: Comtrol Corp.
|
||||||
M: support@comtrol.com
|
|
||||||
W: http://www.comtrol.com
|
W: http://www.comtrol.com
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
|
|
164
Makefile
164
Makefile
|
@ -109,10 +109,9 @@ $(if $(KBUILD_OUTPUT),, \
|
||||||
.PHONY: $(MAKECMDGOALS)
|
.PHONY: $(MAKECMDGOALS)
|
||||||
|
|
||||||
$(filter-out _all,$(MAKECMDGOALS)) _all:
|
$(filter-out _all,$(MAKECMDGOALS)) _all:
|
||||||
$(if $(KBUILD_VERBOSE:1=),@)$(MAKE) -C $(KBUILD_OUTPUT) \
|
$(if $(KBUILD_VERBOSE:1=),@)$(MAKE) -C $(KBUILD_OUTPUT) \
|
||||||
KBUILD_SRC=$(CURDIR) KBUILD_VERBOSE=$(KBUILD_VERBOSE) \
|
KBUILD_SRC=$(CURDIR) \
|
||||||
KBUILD_CHECK=$(KBUILD_CHECK) KBUILD_EXTMOD="$(KBUILD_EXTMOD)" \
|
KBUILD_EXTMOD="$(KBUILD_EXTMOD)" -f $(CURDIR)/Makefile $@
|
||||||
-f $(CURDIR)/Makefile $@
|
|
||||||
|
|
||||||
# Leave processing to above invocation of make
|
# Leave processing to above invocation of make
|
||||||
skip-makefile := 1
|
skip-makefile := 1
|
||||||
|
@ -233,7 +232,7 @@ ifeq ($(MAKECMDGOALS),)
|
||||||
KBUILD_MODULES := 1
|
KBUILD_MODULES := 1
|
||||||
endif
|
endif
|
||||||
|
|
||||||
export KBUILD_MODULES KBUILD_BUILTIN KBUILD_VERBOSE
|
export KBUILD_MODULES KBUILD_BUILTIN
|
||||||
export KBUILD_CHECKSRC KBUILD_SRC KBUILD_EXTMOD
|
export KBUILD_CHECKSRC KBUILD_SRC KBUILD_EXTMOD
|
||||||
|
|
||||||
# Beautify output
|
# 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
|
# Look for make include files relative to root of kernel src
|
||||||
MAKEFLAGS += --include-dir=$(srctree)
|
MAKEFLAGS += --include-dir=$(srctree)
|
||||||
|
|
||||||
|
# We need some generic definitions
|
||||||
|
include $(srctree)/scripts/Kbuild.include
|
||||||
|
|
||||||
# For maximum performance (+ possibly random breakage, uncomment
|
# For maximum performance (+ possibly random breakage, uncomment
|
||||||
# the following)
|
# the following)
|
||||||
|
|
||||||
|
@ -348,7 +350,7 @@ LINUXINCLUDE := -Iinclude \
|
||||||
|
|
||||||
CPPFLAGS := -D__KERNEL__ $(LINUXINCLUDE)
|
CPPFLAGS := -D__KERNEL__ $(LINUXINCLUDE)
|
||||||
|
|
||||||
CFLAGS := -Wall -Wstrict-prototypes -Wno-trigraphs \
|
CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
|
||||||
-fno-strict-aliasing -fno-common \
|
-fno-strict-aliasing -fno-common \
|
||||||
-ffreestanding
|
-ffreestanding
|
||||||
AFLAGS := -D__ASSEMBLY__
|
AFLAGS := -D__ASSEMBLY__
|
||||||
|
@ -367,15 +369,10 @@ export AFLAGS AFLAGS_KERNEL AFLAGS_MODULE
|
||||||
# even be read-only.
|
# even be read-only.
|
||||||
export MODVERDIR := $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/).tmp_versions
|
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
|
# 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_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
|
RCS_TAR_IGNORE := --exclude SCCS --exclude BitKeeper --exclude .svn --exclude CVS --exclude .pc --exclude .hg
|
||||||
|
|
||||||
# ===========================================================================
|
# ===========================================================================
|
||||||
# Rules shared between *config targets and build targets
|
# 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
|
# images. Default is /boot, but you can set it to other values
|
||||||
export INSTALL_PATH ?= /boot
|
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
|
# INSTALL_MOD_PATH specifies a prefix to MODLIB for module directory
|
||||||
# relocations required by build roots. This is not defined in the
|
# relocations required by build roots. This is not defined in the
|
||||||
|
@ -691,8 +708,10 @@ endef
|
||||||
|
|
||||||
# Update vmlinux version before link
|
# Update vmlinux version before link
|
||||||
# Use + in front of this rule to silent warning about make -j1
|
# 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__)
|
cmd_ksym_ld = $(cmd_vmlinux__)
|
||||||
define rule_ksym_ld
|
define rule_ksym_ld
|
||||||
|
:
|
||||||
+$(call cmd,vmlinux_version)
|
+$(call cmd,vmlinux_version)
|
||||||
$(call cmd,vmlinux__)
|
$(call cmd,vmlinux__)
|
||||||
$(Q)echo 'cmd_$@ := $(cmd_vmlinux__)' > $(@D)/.$(@F).cmd
|
$(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.
|
# Needs to visit scripts/ before $(KALLSYMS) can be used.
|
||||||
$(KALLSYMS): scripts ;
|
$(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
|
endif # ifdef CONFIG_KALLSYMS
|
||||||
|
|
||||||
# vmlinux image - including updated kernel symbols
|
# vmlinux image - including updated kernel symbols
|
||||||
|
@ -757,7 +786,7 @@ $(vmlinux-dirs): prepare-all scripts
|
||||||
prepare2:
|
prepare2:
|
||||||
ifneq ($(KBUILD_SRC),)
|
ifneq ($(KBUILD_SRC),)
|
||||||
@echo ' Using $(srctree) as source for kernel'
|
@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 " $(srctree) is not clean, please run 'make mrproper'";\
|
||||||
echo " in the '$(srctree)' directory.";\
|
echo " in the '$(srctree)' directory.";\
|
||||||
/bin/false; \
|
/bin/false; \
|
||||||
|
@ -769,7 +798,8 @@ endif
|
||||||
# prepare1 creates a makefile if using a separate output directory
|
# prepare1 creates a makefile if using a separate output directory
|
||||||
prepare1: prepare2 outputmakefile
|
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),)
|
ifneq ($(KBUILD_MODULES),)
|
||||||
$(Q)rm -rf $(MODVERDIR)
|
$(Q)rm -rf $(MODVERDIR)
|
||||||
$(Q)mkdir -p $(MODVERDIR)
|
$(Q)mkdir -p $(MODVERDIR)
|
||||||
|
@ -875,7 +905,7 @@ modules_install: _modinst_ _modinst_post
|
||||||
|
|
||||||
.PHONY: _modinst_
|
.PHONY: _modinst_
|
||||||
_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 "Warning: you may need to install module-init-tools"; \
|
||||||
echo "See http://www.codemonkey.org.uk/docs/post-halloween-2.6.txt";\
|
echo "See http://www.codemonkey.org.uk/docs/post-halloween-2.6.txt";\
|
||||||
sleep 1; \
|
sleep 1; \
|
||||||
|
@ -1159,37 +1189,49 @@ else
|
||||||
__srctree = $(srctree)/
|
__srctree = $(srctree)/
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ALLSOURCE_ARCHS := $(ARCH)
|
||||||
|
|
||||||
define all-sources
|
define all-sources
|
||||||
( find $(__srctree) $(RCS_FIND_IGNORE) \
|
( find $(__srctree) $(RCS_FIND_IGNORE) \
|
||||||
\( -name include -o -name arch \) -prune -o \
|
\( -name include -o -name arch \) -prune -o \
|
||||||
-name '*.[chS]' -print; \
|
-name '*.[chS]' -print; \
|
||||||
find $(__srctree)arch/$(ARCH) $(RCS_FIND_IGNORE) \
|
for ARCH in $(ALLSOURCE_ARCHS) ; do \
|
||||||
-name '*.[chS]' -print; \
|
find $(__srctree)arch/$${ARCH} $(RCS_FIND_IGNORE) \
|
||||||
|
-name '*.[chS]' -print; \
|
||||||
|
done ; \
|
||||||
find $(__srctree)security/selinux/include $(RCS_FIND_IGNORE) \
|
find $(__srctree)security/selinux/include $(RCS_FIND_IGNORE) \
|
||||||
-name '*.[chS]' -print; \
|
-name '*.[chS]' -print; \
|
||||||
find $(__srctree)include $(RCS_FIND_IGNORE) \
|
find $(__srctree)include $(RCS_FIND_IGNORE) \
|
||||||
\( -name config -o -name 'asm-*' \) -prune \
|
\( -name config -o -name 'asm-*' \) -prune \
|
||||||
-o -name '*.[chS]' -print; \
|
-o -name '*.[chS]' -print; \
|
||||||
find $(__srctree)include/asm-$(ARCH) $(RCS_FIND_IGNORE) \
|
for ARCH in $(ALLSOURCE_ARCHS) ; do \
|
||||||
-name '*.[chS]' -print; \
|
find $(__srctree)include/asm-$${ARCH} $(RCS_FIND_IGNORE) \
|
||||||
|
-name '*.[chS]' -print; \
|
||||||
|
done ; \
|
||||||
find $(__srctree)include/asm-generic $(RCS_FIND_IGNORE) \
|
find $(__srctree)include/asm-generic $(RCS_FIND_IGNORE) \
|
||||||
-name '*.[chS]' -print )
|
-name '*.[chS]' -print )
|
||||||
endef
|
endef
|
||||||
|
|
||||||
quiet_cmd_cscope-file = FILELST cscope.files
|
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
|
quiet_cmd_cscope = MAKE cscope.out
|
||||||
cmd_cscope = cscope -k -b -q
|
cmd_cscope = cscope -b
|
||||||
|
|
||||||
cscope: FORCE
|
cscope: FORCE
|
||||||
$(call cmd,cscope-file)
|
$(call cmd,cscope-file)
|
||||||
$(call cmd,cscope)
|
$(call cmd,cscope)
|
||||||
|
|
||||||
quiet_cmd_TAGS = MAKE $@
|
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 $@
|
quiet_cmd_tags = MAKE $@
|
||||||
define cmd_tags
|
define cmd_tags
|
||||||
|
@ -1198,9 +1240,6 @@ define cmd_tags
|
||||||
$(all-sources) | xargs ctags $$CTAGSF -a
|
$(all-sources) | xargs ctags $$CTAGSF -a
|
||||||
endef
|
endef
|
||||||
|
|
||||||
TAGS: FORCE
|
|
||||||
$(call cmd,TAGS)
|
|
||||||
|
|
||||||
tags: FORCE
|
tags: FORCE
|
||||||
$(call cmd,tags)
|
$(call cmd,tags)
|
||||||
|
|
||||||
|
@ -1268,82 +1307,11 @@ ifneq ($(cmd_files),)
|
||||||
include $(cmd_files)
|
include $(cmd_files)
|
||||||
endif
|
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
|
# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.clean obj=dir
|
||||||
# Usage:
|
# Usage:
|
||||||
# $(Q)$(MAKE) $(clean)=dir
|
# $(Q)$(MAKE) $(clean)=dir
|
||||||
clean := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.clean obj
|
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
|
endif # skip-makefile
|
||||||
|
|
||||||
FORCE:
|
FORCE:
|
||||||
|
|
|
@ -479,6 +479,9 @@ config EISA
|
||||||
depends on ALPHA_GENERIC || ALPHA_JENSEN || ALPHA_ALCOR || ALPHA_MIKASA || ALPHA_SABLE || ALPHA_LYNX || ALPHA_NORITAKE || ALPHA_RAWHIDE
|
depends on ALPHA_GENERIC || ALPHA_JENSEN || ALPHA_ALCOR || ALPHA_MIKASA || ALPHA_SABLE || ALPHA_LYNX || ALPHA_NORITAKE || ALPHA_RAWHIDE
|
||||||
default y
|
default y
|
||||||
|
|
||||||
|
config ARCH_MAY_HAVE_PC_FDC
|
||||||
|
def_bool y
|
||||||
|
|
||||||
config SMP
|
config SMP
|
||||||
bool "Symmetric multi-processing support"
|
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
|
depends on ALPHA_SABLE || ALPHA_LYNX || ALPHA_RAWHIDE || ALPHA_DP264 || ALPHA_WILDFIRE || ALPHA_TITAN || ALPHA_GENERIC || ALPHA_SHARK || ALPHA_MARVEL
|
||||||
|
|
|
@ -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
|
* 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.
|
* 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_sec > state.last_rtc_update + 660
|
||||||
&& xtime.tv_nsec >= 500000 - ((unsigned) TICK_SIZE) / 2
|
&& xtime.tv_nsec >= 500000 - ((unsigned) TICK_SIZE) / 2
|
||||||
&& 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(&xtime, sec, nsec);
|
||||||
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
|
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
|
||||||
|
|
||||||
time_adjust = 0; /* stop active adjtime() */
|
ntp_clear();
|
||||||
time_status |= STA_UNSYNC;
|
|
||||||
time_maxerror = NTP_PHASE_LIMIT;
|
|
||||||
time_esterror = NTP_PHASE_LIMIT;
|
|
||||||
|
|
||||||
write_sequnlock_irq(&xtime_lock);
|
write_sequnlock_irq(&xtime_lock);
|
||||||
clock_was_set();
|
clock_was_set();
|
||||||
|
|
|
@ -64,6 +64,9 @@ config GENERIC_CALIBRATE_DELAY
|
||||||
config GENERIC_BUST_SPINLOCK
|
config GENERIC_BUST_SPINLOCK
|
||||||
bool
|
bool
|
||||||
|
|
||||||
|
config ARCH_MAY_HAVE_PC_FDC
|
||||||
|
bool
|
||||||
|
|
||||||
config GENERIC_ISA_DMA
|
config GENERIC_ISA_DMA
|
||||||
bool
|
bool
|
||||||
|
|
||||||
|
@ -150,6 +153,7 @@ config ARCH_RPC
|
||||||
select ARCH_ACORN
|
select ARCH_ACORN
|
||||||
select FIQ
|
select FIQ
|
||||||
select TIMER_ACORN
|
select TIMER_ACORN
|
||||||
|
select ARCH_MAY_HAVE_PC_FDC
|
||||||
help
|
help
|
||||||
On the Acorn Risc-PC, Linux can support the internal IDE disk and
|
On the Acorn Risc-PC, Linux can support the internal IDE disk and
|
||||||
CD-ROM interface, serial and parallel port, and the floppy drive.
|
CD-ROM interface, serial and parallel port, and the floppy drive.
|
||||||
|
|
|
@ -7,7 +7,8 @@
|
||||||
* so we have to figure out the machine for ourselves...
|
* so we have to figure out the machine for ourselves...
|
||||||
*
|
*
|
||||||
* Support for Poodle, Corgi (SL-C700), Shepherd (SL-C750)
|
* 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:
|
__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
|
ldr r1, .W100ADDR @ Base address of w100 chip + regs offset
|
||||||
|
|
||||||
mov r6, #0x31 @ Load Magic Init value
|
mov r6, #0x31 @ Load Magic Init value
|
||||||
|
@ -30,7 +47,7 @@ __SharpSL_start:
|
||||||
mov r5, #0x3000
|
mov r5, #0x3000
|
||||||
.W100LOOP:
|
.W100LOOP:
|
||||||
subs r5, r5, #1
|
subs r5, r5, #1
|
||||||
bne .W100LOOP
|
bne .W100LOOP
|
||||||
mov r6, #0x30 @ Load 2nd Magic Init value
|
mov r6, #0x30 @ Load 2nd Magic Init value
|
||||||
str r6, [r1, #0x280] @ to SCRATCH_UMSK
|
str r6, [r1, #0x280] @ to SCRATCH_UMSK
|
||||||
|
|
||||||
|
@ -40,45 +57,52 @@ __SharpSL_start:
|
||||||
cmp r6, r3
|
cmp r6, r3
|
||||||
bne .SHARPEND @ We have no w100 - Poodle
|
bne .SHARPEND @ We have no w100 - Poodle
|
||||||
|
|
||||||
mrc p15, 0, r6, c0, c0 @ Get Processor ID
|
/* Check for pxa250 - if found we have a Corgi */
|
||||||
and r6, r6, #0xffffff00
|
|
||||||
ldr r7, .CORGIID
|
ldr r7, .CORGIID
|
||||||
ldr r3, .PXA255ID
|
ldr r3, .PXA255ID
|
||||||
cmp r6, r3
|
cmp r4, r3
|
||||||
blo .SHARPEND @ We have a PXA250 - Corgi
|
blo .SHARPEND @ We have a PXA250 - Corgi
|
||||||
|
|
||||||
mov r1, #0x0c000000 @ Base address of NAND chip
|
/* Check for 64MiB flash - if found we have a Shepherd */
|
||||||
ldrb r3, [r1, #24] @ Load FLASHCTL
|
bl get_flash_ids
|
||||||
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
|
|
||||||
ldr r7, .SHEPHERDID
|
ldr r7, .SHEPHERDID
|
||||||
cmp r3, #0x76 @ 64MiB flash
|
cmp r3, #0x76 @ 64MiB flash
|
||||||
beq .SHARPEND @ We have Shepherd
|
beq .SHARPEND @ We have Shepherd
|
||||||
|
|
||||||
|
/* Must be a Husky */
|
||||||
ldr r7, .HUSKYID @ Must be Husky
|
ldr r7, .HUSKYID @ Must be Husky
|
||||||
b .SHARPEND
|
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:
|
.PXA255ID:
|
||||||
.word 0x69052d00 @ PXA255 Processor ID
|
.word 0x69052d00 @ PXA255 Processor ID
|
||||||
|
.PXA270ID:
|
||||||
|
.word 0x69054100 @ PXA270 Processor ID
|
||||||
.W100ID:
|
.W100ID:
|
||||||
.word 0x57411002 @ w100 Chip ID
|
.word 0x57411002 @ w100 Chip ID
|
||||||
.W100ADDR:
|
.W100ADDR:
|
||||||
.word 0x08010000 @ w100 Chip ID Reg Address
|
.word 0x08010000 @ w100 Chip ID Reg Address
|
||||||
|
.SCOOP2ADDR:
|
||||||
|
.word 0x08800040
|
||||||
.POODLEID:
|
.POODLEID:
|
||||||
.word MACH_TYPE_POODLE
|
.word MACH_TYPE_POODLE
|
||||||
.CORGIID:
|
.CORGIID:
|
||||||
|
@ -87,6 +111,41 @@ __SharpSL_start:
|
||||||
.word MACH_TYPE_SHEPHERD
|
.word MACH_TYPE_SHEPHERD
|
||||||
.HUSKYID:
|
.HUSKYID:
|
||||||
.word MACH_TYPE_HUSKY
|
.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:
|
.SHARPEND:
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -177,7 +177,7 @@ static void locomo_handler(unsigned int irq, struct irqdesc *desc,
|
||||||
d = irq_desc + irq;
|
d = irq_desc + irq;
|
||||||
for (i = 0; i <= 3; i++, d++, irq++) {
|
for (i = 0; i <= 3; i++, d++, irq++) {
|
||||||
if (req & (0x0100 << i)) {
|
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) {
|
if (locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC) & 0x0001) {
|
||||||
d = irq_desc + LOCOMO_IRQ_KEY_START;
|
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;
|
d = irq_desc + LOCOMO_IRQ_GPIO_START;
|
||||||
for (i = 0; i <= 15; i++, irq++, d++) {
|
for (i = 0; i <= 15; i++, irq++, d++) {
|
||||||
if (req & (0x0001 << i)) {
|
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) {
|
if (locomo_readl(mapbase + LOCOMO_LTINT) & 0x0001) {
|
||||||
d = irq_desc + LOCOMO_IRQ_LT_START;
|
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++) {
|
for (i = 0; i <= 3; i++, irq++, d++) {
|
||||||
if (req & (0x0001 << i)) {
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int locomo_remove_child(struct device *dev, void *data)
|
||||||
|
{
|
||||||
|
device_unregister(dev);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void __locomo_remove(struct locomo *lchip)
|
static void __locomo_remove(struct locomo *lchip)
|
||||||
{
|
{
|
||||||
struct list_head *l, *n;
|
device_for_each_child(lchip->dev, NULL, locomo_remove_child);
|
||||||
|
|
||||||
list_for_each_safe(l, n, &lchip->dev->children) {
|
|
||||||
struct device *d = list_to_dev(l);
|
|
||||||
|
|
||||||
device_unregister(d);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lchip->irq != NO_IRQ) {
|
if (lchip->irq != NO_IRQ) {
|
||||||
set_irq_chained_handler(lchip->irq, NULL);
|
set_irq_chained_handler(lchip->irq, NULL);
|
||||||
|
|
|
@ -268,8 +268,8 @@ static struct irqchip sa1111_low_chip = {
|
||||||
.mask = sa1111_mask_lowirq,
|
.mask = sa1111_mask_lowirq,
|
||||||
.unmask = sa1111_unmask_lowirq,
|
.unmask = sa1111_unmask_lowirq,
|
||||||
.retrigger = sa1111_retrigger_lowirq,
|
.retrigger = sa1111_retrigger_lowirq,
|
||||||
.type = sa1111_type_lowirq,
|
.set_type = sa1111_type_lowirq,
|
||||||
.wake = sa1111_wake_lowirq,
|
.set_wake = sa1111_wake_lowirq,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void sa1111_mask_highirq(unsigned int irq)
|
static void sa1111_mask_highirq(unsigned int irq)
|
||||||
|
@ -364,8 +364,8 @@ static struct irqchip sa1111_high_chip = {
|
||||||
.mask = sa1111_mask_highirq,
|
.mask = sa1111_mask_highirq,
|
||||||
.unmask = sa1111_unmask_highirq,
|
.unmask = sa1111_unmask_highirq,
|
||||||
.retrigger = sa1111_retrigger_highirq,
|
.retrigger = sa1111_retrigger_highirq,
|
||||||
.type = sa1111_type_highirq,
|
.set_type = sa1111_type_highirq,
|
||||||
.wake = sa1111_wake_highirq,
|
.set_wake = sa1111_wake_highirq,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void sa1111_setup_irq(struct sa1111 *sachip)
|
static void sa1111_setup_irq(struct sa1111 *sachip)
|
||||||
|
|
|
@ -17,6 +17,12 @@
|
||||||
|
|
||||||
#define SCOOP_REG(d,adr) (*(volatile unsigned short*)(d +(adr)))
|
#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 {
|
struct scoop_dev {
|
||||||
void *base;
|
void *base;
|
||||||
spinlock_t scoop_lock;
|
spinlock_t scoop_lock;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#
|
#
|
||||||
# Automatically generated make config: don't edit
|
# Automatically generated make config: don't edit
|
||||||
# Linux kernel version: 2.6.13-rc2
|
# Linux kernel version: 2.6.13
|
||||||
# Fri Jul 8 04:49:34 2005
|
# Mon Sep 5 18:07:12 2005
|
||||||
#
|
#
|
||||||
CONFIG_ARM=y
|
CONFIG_ARM=y
|
||||||
CONFIG_MMU=y
|
CONFIG_MMU=y
|
||||||
|
@ -102,9 +102,11 @@ CONFIG_OMAP_MUX_WARNINGS=y
|
||||||
# CONFIG_OMAP_MPU_TIMER is not set
|
# CONFIG_OMAP_MPU_TIMER is not set
|
||||||
CONFIG_OMAP_32K_TIMER=y
|
CONFIG_OMAP_32K_TIMER=y
|
||||||
CONFIG_OMAP_32K_TIMER_HZ=128
|
CONFIG_OMAP_32K_TIMER_HZ=128
|
||||||
|
# CONFIG_OMAP_DM_TIMER is not set
|
||||||
CONFIG_OMAP_LL_DEBUG_UART1=y
|
CONFIG_OMAP_LL_DEBUG_UART1=y
|
||||||
# CONFIG_OMAP_LL_DEBUG_UART2 is not set
|
# CONFIG_OMAP_LL_DEBUG_UART2 is not set
|
||||||
# CONFIG_OMAP_LL_DEBUG_UART3 is not set
|
# CONFIG_OMAP_LL_DEBUG_UART3 is not set
|
||||||
|
CONFIG_OMAP_SERIAL_WAKE=y
|
||||||
|
|
||||||
#
|
#
|
||||||
# OMAP Core Type
|
# OMAP Core Type
|
||||||
|
@ -166,7 +168,6 @@ CONFIG_ISA_DMA_API=y
|
||||||
#
|
#
|
||||||
# Kernel Features
|
# Kernel Features
|
||||||
#
|
#
|
||||||
# CONFIG_SMP is not set
|
|
||||||
CONFIG_PREEMPT=y
|
CONFIG_PREEMPT=y
|
||||||
CONFIG_NO_IDLE_HZ=y
|
CONFIG_NO_IDLE_HZ=y
|
||||||
# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
|
# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
|
||||||
|
@ -229,6 +230,68 @@ CONFIG_BINFMT_AOUT=y
|
||||||
CONFIG_PM=y
|
CONFIG_PM=y
|
||||||
# CONFIG_APM is not set
|
# 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
|
# Device Drivers
|
||||||
#
|
#
|
||||||
|
@ -243,78 +306,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
|
||||||
#
|
#
|
||||||
# Memory Technology Devices (MTD)
|
# Memory Technology Devices (MTD)
|
||||||
#
|
#
|
||||||
CONFIG_MTD=y
|
# CONFIG_MTD is not set
|
||||||
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
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Parallel port support
|
# 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_NETDEVICES=y
|
||||||
# CONFIG_DUMMY is not set
|
# CONFIG_DUMMY is not set
|
||||||
# CONFIG_BONDING is not set
|
# CONFIG_BONDING is not set
|
||||||
|
@ -518,6 +446,8 @@ CONFIG_SLIP_COMPRESSED=y
|
||||||
# CONFIG_SLIP_MODE_SLIP6 is not set
|
# CONFIG_SLIP_MODE_SLIP6 is not set
|
||||||
# CONFIG_SHAPER is not set
|
# CONFIG_SHAPER is not set
|
||||||
# CONFIG_NETCONSOLE is not set
|
# CONFIG_NETCONSOLE is not set
|
||||||
|
# CONFIG_NETPOLL is not set
|
||||||
|
# CONFIG_NET_POLL_CONTROLLER is not set
|
||||||
|
|
||||||
#
|
#
|
||||||
# ISDN subsystem
|
# ISDN subsystem
|
||||||
|
@ -615,77 +545,15 @@ CONFIG_WATCHDOG_NOWAYOUT=y
|
||||||
#
|
#
|
||||||
# I2C support
|
# I2C support
|
||||||
#
|
#
|
||||||
CONFIG_I2C=y
|
# CONFIG_I2C is not set
|
||||||
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_SENSOR is not set
|
# CONFIG_I2C_SENSOR is not set
|
||||||
# CONFIG_SENSORS_ADM1021 is not set
|
CONFIG_ISP1301_OMAP=y
|
||||||
# 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
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Other I2C Chip support
|
# Hardware Monitoring support
|
||||||
#
|
#
|
||||||
# CONFIG_SENSORS_DS1337 is not set
|
CONFIG_HWMON=y
|
||||||
# CONFIG_SENSORS_DS1374 is not set
|
# CONFIG_HWMON_DEBUG_CHIP 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
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Misc devices
|
# Misc devices
|
||||||
|
@ -756,15 +624,9 @@ CONFIG_SOUND=y
|
||||||
# Open Sound System
|
# Open Sound System
|
||||||
#
|
#
|
||||||
CONFIG_SOUND_PRIME=y
|
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_MSNDCLAS is not set
|
||||||
# CONFIG_SOUND_MSNDPIN is not set
|
# CONFIG_SOUND_MSNDPIN is not set
|
||||||
# CONFIG_SOUND_OSS is not set
|
# CONFIG_SOUND_OSS is not set
|
||||||
# CONFIG_SOUND_TVMIXER is not set
|
|
||||||
# CONFIG_SOUND_AD1980 is not set
|
# CONFIG_SOUND_AD1980 is not set
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -810,6 +672,7 @@ CONFIG_EXT2_FS=y
|
||||||
# CONFIG_JBD is not set
|
# CONFIG_JBD is not set
|
||||||
# CONFIG_REISERFS_FS is not set
|
# CONFIG_REISERFS_FS is not set
|
||||||
# CONFIG_JFS_FS is not set
|
# CONFIG_JFS_FS is not set
|
||||||
|
# CONFIG_FS_POSIX_ACL is not set
|
||||||
|
|
||||||
#
|
#
|
||||||
# XFS support
|
# XFS support
|
||||||
|
@ -817,6 +680,7 @@ CONFIG_EXT2_FS=y
|
||||||
# CONFIG_XFS_FS is not set
|
# CONFIG_XFS_FS is not set
|
||||||
# CONFIG_MINIX_FS is not set
|
# CONFIG_MINIX_FS is not set
|
||||||
CONFIG_ROMFS_FS=y
|
CONFIG_ROMFS_FS=y
|
||||||
|
CONFIG_INOTIFY=y
|
||||||
# CONFIG_QUOTA is not set
|
# CONFIG_QUOTA is not set
|
||||||
CONFIG_DNOTIFY=y
|
CONFIG_DNOTIFY=y
|
||||||
# CONFIG_AUTOFS_FS is not set
|
# CONFIG_AUTOFS_FS is not set
|
||||||
|
@ -857,15 +721,6 @@ CONFIG_RAMFS=y
|
||||||
# CONFIG_BEFS_FS is not set
|
# CONFIG_BEFS_FS is not set
|
||||||
# CONFIG_BFS_FS is not set
|
# CONFIG_BFS_FS is not set
|
||||||
# CONFIG_EFS_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_CRAMFS=y
|
||||||
# CONFIG_VXFS_FS is not set
|
# CONFIG_VXFS_FS is not set
|
||||||
# CONFIG_HPFS_FS is not set
|
# CONFIG_HPFS_FS is not set
|
||||||
|
@ -1007,4 +862,3 @@ CONFIG_CRYPTO_DES=y
|
||||||
CONFIG_CRC32=y
|
CONFIG_CRC32=y
|
||||||
# CONFIG_LIBCRC32C is not set
|
# CONFIG_LIBCRC32C is not set
|
||||||
CONFIG_ZLIB_INFLATE=y
|
CONFIG_ZLIB_INFLATE=y
|
||||||
CONFIG_ZLIB_DEFLATE=y
|
|
||||||
|
|
|
@ -585,7 +585,7 @@ ecard_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
|
||||||
|
|
||||||
if (pending) {
|
if (pending) {
|
||||||
struct irqdesc *d = irq_desc + ec->irq;
|
struct irqdesc *d = irq_desc + ec->irq;
|
||||||
d->handle(ec->irq, d, regs);
|
desc_handle_irq(ec->irq, d, regs);
|
||||||
called ++;
|
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
|
* Serial cards should go in 0/1, ethernet/scsi in 2/3
|
||||||
* otherwise you will lose serial data at high speeds!
|
* otherwise you will lose serial data at high speeds!
|
||||||
*/
|
*/
|
||||||
d->handle(ec->irq, d, regs);
|
desc_handle_irq(ec->irq, d, regs);
|
||||||
} else {
|
} else {
|
||||||
printk(KERN_WARNING "card%d: interrupt from unclaimed "
|
printk(KERN_WARNING "card%d: interrupt from unclaimed "
|
||||||
"card???\n", slot);
|
"card???\n", slot);
|
||||||
|
|
|
@ -207,8 +207,8 @@ void enable_irq_wake(unsigned int irq)
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
spin_lock_irqsave(&irq_controller_lock, flags);
|
spin_lock_irqsave(&irq_controller_lock, flags);
|
||||||
if (desc->chip->wake)
|
if (desc->chip->set_wake)
|
||||||
desc->chip->wake(irq, 1);
|
desc->chip->set_wake(irq, 1);
|
||||||
spin_unlock_irqrestore(&irq_controller_lock, flags);
|
spin_unlock_irqrestore(&irq_controller_lock, flags);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(enable_irq_wake);
|
EXPORT_SYMBOL(enable_irq_wake);
|
||||||
|
@ -219,8 +219,8 @@ void disable_irq_wake(unsigned int irq)
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
spin_lock_irqsave(&irq_controller_lock, flags);
|
spin_lock_irqsave(&irq_controller_lock, flags);
|
||||||
if (desc->chip->wake)
|
if (desc->chip->set_wake)
|
||||||
desc->chip->wake(irq, 0);
|
desc->chip->set_wake(irq, 0);
|
||||||
spin_unlock_irqrestore(&irq_controller_lock, flags);
|
spin_unlock_irqrestore(&irq_controller_lock, flags);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(disable_irq_wake);
|
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) {
|
list_for_each_safe(l, n, &head) {
|
||||||
desc = list_entry(l, struct irqdesc, pend);
|
desc = list_entry(l, struct irqdesc, pend);
|
||||||
list_del_init(&desc->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();
|
irq_enter();
|
||||||
spin_lock(&irq_controller_lock);
|
spin_lock(&irq_controller_lock);
|
||||||
desc->handle(irq, desc, regs);
|
desc_handle_irq(irq, desc, regs);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now re-run any pending interrupts.
|
* Now re-run any pending interrupts.
|
||||||
|
@ -624,9 +624,9 @@ int set_irq_type(unsigned int irq, unsigned int type)
|
||||||
}
|
}
|
||||||
|
|
||||||
desc = irq_desc + irq;
|
desc = irq_desc + irq;
|
||||||
if (desc->chip->type) {
|
if (desc->chip->set_type) {
|
||||||
spin_lock_irqsave(&irq_controller_lock, flags);
|
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);
|
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].probing = 1;
|
||||||
irq_desc[i].triggered = 0;
|
irq_desc[i].triggered = 0;
|
||||||
if (irq_desc[i].chip->type)
|
if (irq_desc[i].chip->set_type)
|
||||||
irq_desc[i].chip->type(i, IRQT_PROBE);
|
irq_desc[i].chip->set_type(i, IRQT_PROBE);
|
||||||
irq_desc[i].chip->unmask(i);
|
irq_desc[i].chip->unmask(i);
|
||||||
irqs += 1;
|
irqs += 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,7 +110,7 @@ int __cpuinit __cpu_up(unsigned int cpu)
|
||||||
* We need to tell the secondary core where to find
|
* We need to tell the secondary core where to find
|
||||||
* its stack and the page tables.
|
* 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);
|
secondary_data.pgdir = virt_to_phys(pgd);
|
||||||
wmb();
|
wmb();
|
||||||
|
|
||||||
|
|
|
@ -102,7 +102,7 @@ static unsigned long next_rtc_update;
|
||||||
*/
|
*/
|
||||||
static inline void do_set_rtc(void)
|
static inline void do_set_rtc(void)
|
||||||
{
|
{
|
||||||
if (time_status & STA_UNSYNC || set_rtc == NULL)
|
if (!ntp_synced() || set_rtc == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (next_rtc_update &&
|
if (next_rtc_update &&
|
||||||
|
@ -292,10 +292,7 @@ int do_settimeofday(struct timespec *tv)
|
||||||
set_normalized_timespec(&xtime, sec, nsec);
|
set_normalized_timespec(&xtime, sec, nsec);
|
||||||
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
|
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
|
||||||
|
|
||||||
time_adjust = 0; /* stop active adjtime() */
|
ntp_clear();
|
||||||
time_status |= STA_UNSYNC;
|
|
||||||
time_maxerror = NTP_PHASE_LIMIT;
|
|
||||||
time_esterror = NTP_PHASE_LIMIT;
|
|
||||||
write_sequnlock_irq(&xtime_lock);
|
write_sequnlock_irq(&xtime_lock);
|
||||||
clock_was_set();
|
clock_was_set();
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -87,6 +87,7 @@ config FOOTBRIDGE_ADDIN
|
||||||
|
|
||||||
# EBSA285 board in either host or addin mode
|
# EBSA285 board in either host or addin mode
|
||||||
config ARCH_EBSA285
|
config ARCH_EBSA285
|
||||||
|
select ARCH_MAY_HAVE_PC_FDC
|
||||||
bool
|
bool
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -95,7 +95,7 @@ isa_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
|
||||||
}
|
}
|
||||||
|
|
||||||
desc = irq_desc + isa_irq;
|
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", };
|
static struct irqaction irq_cascade = { .handler = no_action, .name = "cascade", };
|
||||||
|
|
|
@ -108,7 +108,7 @@ h720x_gpio_handler(unsigned int mask, unsigned int irq,
|
||||||
while (mask) {
|
while (mask) {
|
||||||
if (mask & 1) {
|
if (mask & 1) {
|
||||||
IRQDBG("handling irq %d\n", irq);
|
IRQDBG("handling irq %d\n", irq);
|
||||||
desc->handle(irq, desc, regs);
|
desc_handle_irq(irq, desc, regs);
|
||||||
}
|
}
|
||||||
irq++;
|
irq++;
|
||||||
desc++;
|
desc++;
|
||||||
|
|
|
@ -126,7 +126,7 @@ h7202_timerx_demux_handler(unsigned int irq_unused, struct irqdesc *desc,
|
||||||
desc = irq_desc + irq;
|
desc = irq_desc + irq;
|
||||||
while (mask) {
|
while (mask) {
|
||||||
if (mask & 1)
|
if (mask & 1)
|
||||||
desc->handle(irq, desc, regs);
|
desc_handle_irq(irq, desc, regs);
|
||||||
irq++;
|
irq++;
|
||||||
desc++;
|
desc++;
|
||||||
mask >>= 1;
|
mask >>= 1;
|
||||||
|
|
|
@ -152,7 +152,7 @@ imx_gpio_handler(unsigned int mask, unsigned int irq,
|
||||||
while (mask) {
|
while (mask) {
|
||||||
if (mask & 1) {
|
if (mask & 1) {
|
||||||
DEBUG_IRQ("handling irq %d\n", irq);
|
DEBUG_IRQ("handling irq %d\n", irq);
|
||||||
desc->handle(irq, desc, regs);
|
desc_handle_irq(irq, desc, regs);
|
||||||
}
|
}
|
||||||
irq++;
|
irq++;
|
||||||
desc++;
|
desc++;
|
||||||
|
@ -214,7 +214,7 @@ static struct irqchip imx_gpio_chip = {
|
||||||
.ack = imx_gpio_ack_irq,
|
.ack = imx_gpio_ack_irq,
|
||||||
.mask = imx_gpio_mask_irq,
|
.mask = imx_gpio_mask_irq,
|
||||||
.unmask = imx_gpio_unmask_irq,
|
.unmask = imx_gpio_unmask_irq,
|
||||||
.type = imx_gpio_irq_type,
|
.set_type = imx_gpio_irq_type,
|
||||||
};
|
};
|
||||||
|
|
||||||
void __init
|
void __init
|
||||||
|
|
|
@ -170,7 +170,7 @@ sic_handle_irq(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
|
||||||
irq += IRQ_SIC_START;
|
irq += IRQ_SIC_START;
|
||||||
|
|
||||||
desc = irq_desc + irq;
|
desc = irq_desc + irq;
|
||||||
desc->handle(irq, desc, regs);
|
desc_handle_irq(irq, desc, regs);
|
||||||
} while (status);
|
} while (status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,7 @@ static unsigned long iop321_gettimeoffset(void)
|
||||||
/*
|
/*
|
||||||
* Now convert them to usec.
|
* Now convert them to usec.
|
||||||
*/
|
*/
|
||||||
usec = (unsigned long)(elapsed * (tick_nsec / 1000)) / LATCH;
|
usec = (unsigned long)(elapsed / (CLOCK_TICK_RATE/1000000));
|
||||||
|
|
||||||
return usec;
|
return usec;
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,7 @@ static unsigned long iop331_gettimeoffset(void)
|
||||||
/*
|
/*
|
||||||
* Now convert them to usec.
|
* Now convert them to usec.
|
||||||
*/
|
*/
|
||||||
usec = (unsigned long)(elapsed * (tick_nsec / 1000)) / LATCH;
|
usec = (unsigned long)(elapsed / (CLOCK_TICK_RATE/1000000));
|
||||||
|
|
||||||
return usec;
|
return usec;
|
||||||
}
|
}
|
||||||
|
|
|
@ -317,7 +317,7 @@ static void ixp2000_GPIO_irq_handler(unsigned int irq, struct irqdesc *desc, str
|
||||||
for (i = 0; i <= 7; i++) {
|
for (i = 0; i <= 7; i++) {
|
||||||
if (status & (1<<i)) {
|
if (status & (1<<i)) {
|
||||||
desc = irq_desc + i + IRQ_IXP2000_GPIO0;
|
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 = {
|
static struct irqchip ixp2000_GPIO_irq_chip = {
|
||||||
.type = ixp2000_GPIO_irq_type,
|
.ack = ixp2000_GPIO_irq_mask_ack,
|
||||||
.ack = ixp2000_GPIO_irq_mask_ack,
|
.mask = ixp2000_GPIO_irq_mask,
|
||||||
.mask = ixp2000_GPIO_irq_mask,
|
.unmask = ixp2000_GPIO_irq_unmask,
|
||||||
.unmask = ixp2000_GPIO_irq_unmask
|
.set_type = ixp2000_GPIO_irq_type,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void ixp2000_pci_irq_mask(unsigned int irq)
|
static void ixp2000_pci_irq_mask(unsigned int irq)
|
||||||
|
|
|
@ -133,7 +133,7 @@ static void ixdp2x00_irq_handler(unsigned int irq, struct irqdesc *desc, struct
|
||||||
struct irqdesc *cpld_desc;
|
struct irqdesc *cpld_desc;
|
||||||
int cpld_irq = IXP2000_BOARD_IRQ(0) + i;
|
int cpld_irq = IXP2000_BOARD_IRQ(0) + i;
|
||||||
cpld_desc = irq_desc + cpld_irq;
|
cpld_desc = irq_desc + cpld_irq;
|
||||||
cpld_desc->handle(cpld_irq, cpld_desc, regs);
|
desc_handle_irq(cpld_irq, cpld_desc, regs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -82,7 +82,7 @@ static void ixdp2x01_irq_handler(unsigned int irq, struct irqdesc *desc, struct
|
||||||
struct irqdesc *cpld_desc;
|
struct irqdesc *cpld_desc;
|
||||||
int cpld_irq = IXP2000_BOARD_IRQ(0) + i;
|
int cpld_irq = IXP2000_BOARD_IRQ(0) + i;
|
||||||
cpld_desc = irq_desc + cpld_irq;
|
cpld_desc = irq_desc + cpld_irq;
|
||||||
cpld_desc->handle(cpld_irq, cpld_desc, regs);
|
desc_handle_irq(cpld_irq, cpld_desc, regs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -179,17 +179,17 @@ static void ixp4xx_irq_level_unmask(unsigned int irq)
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct irqchip ixp4xx_irq_level_chip = {
|
static struct irqchip ixp4xx_irq_level_chip = {
|
||||||
.ack = ixp4xx_irq_mask,
|
.ack = ixp4xx_irq_mask,
|
||||||
.mask = ixp4xx_irq_mask,
|
.mask = ixp4xx_irq_mask,
|
||||||
.unmask = ixp4xx_irq_level_unmask,
|
.unmask = ixp4xx_irq_level_unmask,
|
||||||
.type = ixp4xx_set_irq_type
|
.set_type = ixp4xx_set_irq_type,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct irqchip ixp4xx_irq_edge_chip = {
|
static struct irqchip ixp4xx_irq_edge_chip = {
|
||||||
.ack = ixp4xx_irq_ack,
|
.ack = ixp4xx_irq_ack,
|
||||||
.mask = ixp4xx_irq_mask,
|
.mask = ixp4xx_irq_mask,
|
||||||
.unmask = ixp4xx_irq_unmask,
|
.unmask = ixp4xx_irq_unmask,
|
||||||
.type = ixp4xx_set_irq_type
|
.set_type = ixp4xx_set_irq_type,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void ixp4xx_config_irq(unsigned irq, enum ixp4xx_irq_type type)
|
static void ixp4xx_config_irq(unsigned irq, enum ixp4xx_irq_type type)
|
||||||
|
|
|
@ -13,4 +13,4 @@ extern struct sys_timer lh7a40x_timer;
|
||||||
extern void lh7a400_init_irq (void);
|
extern void lh7a400_init_irq (void);
|
||||||
extern void lh7a404_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)
|
||||||
|
|
|
@ -102,7 +102,7 @@ void innovator_fpga_IRQ_demux(unsigned int irq, struct irqdesc *desc,
|
||||||
fpga_irq++, stat >>= 1) {
|
fpga_irq++, stat >>= 1) {
|
||||||
if (stat & 1) {
|
if (stat & 1) {
|
||||||
d = irq_desc + fpga_irq;
|
d = irq_desc + fpga_irq;
|
||||||
d->handle(fpga_irq, d, regs);
|
desc_handle_irq(fpga_irq, d, regs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -165,10 +165,10 @@ static struct omap_irq_bank omap1610_irq_banks[] = {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static struct irqchip omap_irq_chip = {
|
static struct irqchip omap_irq_chip = {
|
||||||
.ack = omap_mask_ack_irq,
|
.ack = omap_mask_ack_irq,
|
||||||
.mask = omap_mask_irq,
|
.mask = omap_mask_irq,
|
||||||
.unmask = omap_unmask_irq,
|
.unmask = omap_unmask_irq,
|
||||||
.wake = omap_wake_irq,
|
.set_wake = omap_wake_irq,
|
||||||
};
|
};
|
||||||
|
|
||||||
void __init omap_init_irq(void)
|
void __init omap_init_irq(void)
|
||||||
|
|
|
@ -11,7 +11,7 @@ obj-$(CONFIG_PXA27x) += pxa27x.o
|
||||||
obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o
|
obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o
|
||||||
obj-$(CONFIG_MACH_MAINSTONE) += mainstone.o
|
obj-$(CONFIG_MACH_MAINSTONE) += mainstone.o
|
||||||
obj-$(CONFIG_ARCH_PXA_IDP) += idp.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
|
obj-$(CONFIG_MACH_POODLE) += poodle.o
|
||||||
|
|
||||||
# Support for blinky lights
|
# Support for blinky lights
|
||||||
|
|
|
@ -39,7 +39,6 @@
|
||||||
|
|
||||||
#include <asm/mach/sharpsl_param.h>
|
#include <asm/mach/sharpsl_param.h>
|
||||||
#include <asm/hardware/scoop.h>
|
#include <asm/hardware/scoop.h>
|
||||||
#include <video/w100fb.h>
|
|
||||||
|
|
||||||
#include "generic.h"
|
#include "generic.h"
|
||||||
|
|
||||||
|
@ -60,6 +59,15 @@ static struct scoop_config corgi_scoop_setup = {
|
||||||
.io_out = CORGI_SCOOP_IO_OUT,
|
.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 = {
|
struct platform_device corgiscoop_device = {
|
||||||
.name = "sharp-scoop",
|
.name = "sharp-scoop",
|
||||||
.id = -1,
|
.id = -1,
|
||||||
|
@ -78,7 +86,7 @@ struct platform_device corgiscoop_device = {
|
||||||
* also use scoop functions and this makes the power up/down order
|
* also use scoop functions and this makes the power up/down order
|
||||||
* work correctly.
|
* work correctly.
|
||||||
*/
|
*/
|
||||||
static struct platform_device corgissp_device = {
|
struct platform_device corgissp_device = {
|
||||||
.name = "corgi-ssp",
|
.name = "corgi-ssp",
|
||||||
.dev = {
|
.dev = {
|
||||||
.parent = &corgiscoop_device.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
|
* 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
|
* 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)
|
static void corgi_mci_exit(struct device *dev, void *data)
|
||||||
{
|
{
|
||||||
free_irq(CORGI_IRQ_GPIO_nSD_DETECT, 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 = {
|
static struct pxamci_platform_data corgi_mci_platform_data = {
|
||||||
.ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
|
.ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
|
||||||
.init = corgi_mci_init,
|
.init = corgi_mci_init,
|
||||||
|
.get_ro = corgi_mci_get_ro,
|
||||||
.setpower = corgi_mci_setpower,
|
.setpower = corgi_mci_setpower,
|
||||||
.exit = corgi_mci_exit,
|
.exit = corgi_mci_exit,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* USB Device Controller
|
* USB Device Controller
|
||||||
*/
|
*/
|
||||||
|
@ -229,18 +236,20 @@ static struct platform_device *devices[] __initdata = {
|
||||||
&corgiscoop_device,
|
&corgiscoop_device,
|
||||||
&corgissp_device,
|
&corgissp_device,
|
||||||
&corgifb_device,
|
&corgifb_device,
|
||||||
|
&corgikbd_device,
|
||||||
&corgibl_device,
|
&corgibl_device,
|
||||||
|
&corgits_device,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void __init corgi_init(void)
|
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_gpio_mode(CORGI_GPIO_USB_PULLUP | GPIO_OUT);
|
||||||
pxa_set_udc_info(&udc_info);
|
pxa_set_udc_info(&udc_info);
|
||||||
pxa_set_mci_info(&corgi_mci_platform_data);
|
pxa_set_mci_info(&corgi_mci_platform_data);
|
||||||
|
|
||||||
|
scoop_num = 1;
|
||||||
|
scoop_devs = &corgi_pcmcia_scoop[0];
|
||||||
|
|
||||||
platform_add_devices(devices, ARRAY_SIZE(devices));
|
platform_add_devices(devices, ARRAY_SIZE(devices));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
396
arch/arm/mach-pxa/corgi_lcd.c
Normal file
396
arch/arm/mach-pxa/corgi_lcd.c
Normal 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,
|
||||||
|
},
|
||||||
|
|
||||||
|
};
|
|
@ -133,7 +133,7 @@ static struct irqchip pxa_low_gpio_chip = {
|
||||||
.ack = pxa_ack_low_gpio,
|
.ack = pxa_ack_low_gpio,
|
||||||
.mask = pxa_mask_low_irq,
|
.mask = pxa_mask_low_irq,
|
||||||
.unmask = pxa_unmask_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;
|
mask >>= 2;
|
||||||
do {
|
do {
|
||||||
if (mask & 1)
|
if (mask & 1)
|
||||||
desc->handle(irq, desc, regs);
|
desc_handle_irq(irq, desc, regs);
|
||||||
irq++;
|
irq++;
|
||||||
desc++;
|
desc++;
|
||||||
mask >>= 1;
|
mask >>= 1;
|
||||||
|
@ -172,7 +172,7 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irqdesc *desc,
|
||||||
desc = irq_desc + irq;
|
desc = irq_desc + irq;
|
||||||
do {
|
do {
|
||||||
if (mask & 1)
|
if (mask & 1)
|
||||||
desc->handle(irq, desc, regs);
|
desc_handle_irq(irq, desc, regs);
|
||||||
irq++;
|
irq++;
|
||||||
desc++;
|
desc++;
|
||||||
mask >>= 1;
|
mask >>= 1;
|
||||||
|
@ -187,7 +187,7 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irqdesc *desc,
|
||||||
desc = irq_desc + irq;
|
desc = irq_desc + irq;
|
||||||
do {
|
do {
|
||||||
if (mask & 1)
|
if (mask & 1)
|
||||||
desc->handle(irq, desc, regs);
|
desc_handle_irq(irq, desc, regs);
|
||||||
irq++;
|
irq++;
|
||||||
desc++;
|
desc++;
|
||||||
mask >>= 1;
|
mask >>= 1;
|
||||||
|
@ -203,7 +203,7 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irqdesc *desc,
|
||||||
desc = irq_desc + irq;
|
desc = irq_desc + irq;
|
||||||
do {
|
do {
|
||||||
if (mask & 1)
|
if (mask & 1)
|
||||||
desc->handle(irq, desc, regs);
|
desc_handle_irq(irq, desc, regs);
|
||||||
irq++;
|
irq++;
|
||||||
desc++;
|
desc++;
|
||||||
mask >>= 1;
|
mask >>= 1;
|
||||||
|
@ -241,7 +241,7 @@ static struct irqchip pxa_muxed_gpio_chip = {
|
||||||
.ack = pxa_ack_muxed_gpio,
|
.ack = pxa_ack_muxed_gpio,
|
||||||
.mask = pxa_mask_muxed_gpio,
|
.mask = pxa_mask_muxed_gpio,
|
||||||
.unmask = pxa_unmask_muxed_gpio,
|
.unmask = pxa_unmask_muxed_gpio,
|
||||||
.type = pxa_gpio_irq_type,
|
.set_type = pxa_gpio_irq_type,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -84,7 +84,7 @@ static void lubbock_irq_handler(unsigned int irq, struct irqdesc *desc,
|
||||||
if (likely(pending)) {
|
if (likely(pending)) {
|
||||||
irq = LUBBOCK_IRQ(0) + __ffs(pending);
|
irq = LUBBOCK_IRQ(0) + __ffs(pending);
|
||||||
desc = irq_desc + irq;
|
desc = irq_desc + irq;
|
||||||
desc->handle(irq, desc, regs);
|
desc_handle_irq(irq, desc, regs);
|
||||||
}
|
}
|
||||||
pending = LUB_IRQ_SET_CLR & lubbock_irq_enabled;
|
pending = LUB_IRQ_SET_CLR & lubbock_irq_enabled;
|
||||||
} while (pending);
|
} while (pending);
|
||||||
|
|
|
@ -72,7 +72,7 @@ static void mainstone_irq_handler(unsigned int irq, struct irqdesc *desc,
|
||||||
if (likely(pending)) {
|
if (likely(pending)) {
|
||||||
irq = MAINSTONE_IRQ(0) + __ffs(pending);
|
irq = MAINSTONE_IRQ(0) + __ffs(pending);
|
||||||
desc = irq_desc + irq;
|
desc = irq_desc + irq;
|
||||||
desc->handle(irq, desc, regs);
|
desc_handle_irq(irq, desc, regs);
|
||||||
}
|
}
|
||||||
pending = MST_INTSETCLR & mainstone_irq_enabled;
|
pending = MST_INTSETCLR & mainstone_irq_enabled;
|
||||||
} while (pending);
|
} while (pending);
|
||||||
|
|
|
@ -62,6 +62,15 @@ struct platform_device poodle_scoop_device = {
|
||||||
.resource = poodle_scoop_resources,
|
.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 */
|
/* LoCoMo device */
|
||||||
static struct resource locomo_resources[] = {
|
static struct resource locomo_resources[] = {
|
||||||
|
@ -147,6 +156,9 @@ static void __init poodle_init(void)
|
||||||
|
|
||||||
set_pxa_fb_info(&poodle_fb_info);
|
set_pxa_fb_info(&poodle_fb_info);
|
||||||
|
|
||||||
|
scoop_num = 1;
|
||||||
|
scoop_devs = &poodle_pcmcia_scoop[0];
|
||||||
|
|
||||||
ret = platform_add_devices(devices, ARRAY_SIZE(devices));
|
ret = platform_add_devices(devices, ARRAY_SIZE(devices));
|
||||||
if (ret) {
|
if (ret) {
|
||||||
printk(KERN_WARNING "poodle: Unable to register LoCoMo device\n");
|
printk(KERN_WARNING "poodle: Unable to register LoCoMo device\n");
|
||||||
|
|
|
@ -2,6 +2,13 @@ if ARCH_S3C2410
|
||||||
|
|
||||||
menu "S3C24XX Implementations"
|
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
|
config ARCH_BAST
|
||||||
bool "Simtec Electronics BAST (EB2410ITX)"
|
bool "Simtec Electronics BAST (EB2410ITX)"
|
||||||
select CPU_S3C2410
|
select CPU_S3C2410
|
||||||
|
@ -11,6 +18,14 @@ config ARCH_BAST
|
||||||
|
|
||||||
Product page: <http://www.simtec.co.uk/products/EB2410ITX/>.
|
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
|
config ARCH_H1940
|
||||||
bool "IPAQ H1940"
|
bool "IPAQ H1940"
|
||||||
select CPU_S3C2410
|
select CPU_S3C2410
|
||||||
|
|
|
@ -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-irq.o
|
||||||
obj-$(CONFIG_CPU_S3C2440) += s3c2440-clock.o
|
obj-$(CONFIG_CPU_S3C2440) += s3c2440-clock.o
|
||||||
|
|
||||||
|
# bast extras
|
||||||
|
|
||||||
|
obj-$(CONFIG_BAST_PC104_IRQ) += bast-irq.o
|
||||||
|
|
||||||
# machine specific support
|
# machine specific support
|
||||||
|
|
||||||
|
obj-$(CONFIG_MACH_ANUBIS) += mach-anubis.o
|
||||||
obj-$(CONFIG_ARCH_BAST) += mach-bast.o usb-simtec.o
|
obj-$(CONFIG_ARCH_BAST) += mach-bast.o usb-simtec.o
|
||||||
obj-$(CONFIG_ARCH_H1940) += mach-h1940.o
|
obj-$(CONFIG_ARCH_H1940) += mach-h1940.o
|
||||||
obj-$(CONFIG_MACH_N30) += mach-n30.o
|
obj-$(CONFIG_MACH_N30) += mach-n30.o
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* linux/arch/arm/mach-s3c2410/bast-irq.c
|
/* 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>
|
* Ben Dooks <ben@simtec.co.uk>
|
||||||
*
|
*
|
||||||
* http://www.simtec.co.uk/products/EB2410ITX/
|
* http://www.simtec.co.uk/products/EB2410ITX/
|
||||||
|
@ -21,7 +21,8 @@
|
||||||
*
|
*
|
||||||
* Modifications:
|
* Modifications:
|
||||||
* 08-Jan-2003 BJD Moved from central IRQ code
|
* 08-Jan-2003 BJD Moved from central IRQ code
|
||||||
*/
|
* 21-Aug-2005 BJD Fixed missing code and compile errors
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
|
@ -30,12 +31,19 @@
|
||||||
#include <linux/ptrace.h>
|
#include <linux/ptrace.h>
|
||||||
#include <linux/sysdev.h>
|
#include <linux/sysdev.h>
|
||||||
|
|
||||||
|
#include <asm/mach-types.h>
|
||||||
|
|
||||||
#include <asm/hardware.h>
|
#include <asm/hardware.h>
|
||||||
#include <asm/irq.h>
|
#include <asm/irq.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
|
|
||||||
#include <asm/mach/irq.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
|
#if 0
|
||||||
#include <asm/debug-ll.h>
|
#include <asm/debug-ll.h>
|
||||||
|
@ -79,15 +87,15 @@ bast_pc104_mask(unsigned int irqno)
|
||||||
temp = __raw_readb(BAST_VA_PC104_IRQMASK);
|
temp = __raw_readb(BAST_VA_PC104_IRQMASK);
|
||||||
temp &= ~bast_pc104_irqmasks[irqno];
|
temp &= ~bast_pc104_irqmasks[irqno];
|
||||||
__raw_writeb(temp, BAST_VA_PC104_IRQMASK);
|
__raw_writeb(temp, BAST_VA_PC104_IRQMASK);
|
||||||
|
|
||||||
if (temp == 0)
|
|
||||||
bast_extint_mask(IRQ_ISA);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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
|
static void
|
||||||
|
@ -98,14 +106,12 @@ bast_pc104_unmask(unsigned int irqno)
|
||||||
temp = __raw_readb(BAST_VA_PC104_IRQMASK);
|
temp = __raw_readb(BAST_VA_PC104_IRQMASK);
|
||||||
temp |= bast_pc104_irqmasks[irqno];
|
temp |= bast_pc104_irqmasks[irqno];
|
||||||
__raw_writeb(temp, BAST_VA_PC104_IRQMASK);
|
__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,
|
.mask = bast_pc104_mask,
|
||||||
.unmask = bast_pc104_unmask,
|
.unmask = bast_pc104_unmask,
|
||||||
.ack = bast_pc104_ack
|
.ack = bast_pc104_maskack
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -119,14 +125,49 @@ bast_irq_pc104_demux(unsigned int irq,
|
||||||
|
|
||||||
stat = __raw_readb(BAST_VA_PC104_IRQREQ) & 0xf;
|
stat = __raw_readb(BAST_VA_PC104_IRQREQ) & 0xf;
|
||||||
|
|
||||||
for (i = 0; i < 4 && stat != 0; i++) {
|
if (unlikely(stat == 0)) {
|
||||||
if (stat & 1) {
|
/* ack if we get an irq with nothing (ie, startup) */
|
||||||
irqno = bast_pc104_irqs[i];
|
|
||||||
desc = irq_desc + irqno;
|
|
||||||
|
|
||||||
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);
|
||||||
|
|
|
@ -184,14 +184,14 @@ struct irqchip s3c_irq_level_chip = {
|
||||||
.ack = s3c_irq_maskack,
|
.ack = s3c_irq_maskack,
|
||||||
.mask = s3c_irq_mask,
|
.mask = s3c_irq_mask,
|
||||||
.unmask = s3c_irq_unmask,
|
.unmask = s3c_irq_unmask,
|
||||||
.wake = s3c_irq_wake
|
.set_wake = s3c_irq_wake
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct irqchip s3c_irq_chip = {
|
static struct irqchip s3c_irq_chip = {
|
||||||
.ack = s3c_irq_ack,
|
.ack = s3c_irq_ack,
|
||||||
.mask = s3c_irq_mask,
|
.mask = s3c_irq_mask,
|
||||||
.unmask = s3c_irq_unmask,
|
.unmask = s3c_irq_unmask,
|
||||||
.wake = s3c_irq_wake
|
.set_wake = s3c_irq_wake
|
||||||
};
|
};
|
||||||
|
|
||||||
/* S3C2410_EINTMASK
|
/* S3C2410_EINTMASK
|
||||||
|
@ -350,16 +350,16 @@ static struct irqchip s3c_irqext_chip = {
|
||||||
.mask = s3c_irqext_mask,
|
.mask = s3c_irqext_mask,
|
||||||
.unmask = s3c_irqext_unmask,
|
.unmask = s3c_irqext_unmask,
|
||||||
.ack = s3c_irqext_ack,
|
.ack = s3c_irqext_ack,
|
||||||
.type = s3c_irqext_type,
|
.set_type = s3c_irqext_type,
|
||||||
.wake = s3c_irqext_wake
|
.set_wake = s3c_irqext_wake
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct irqchip s3c_irq_eint0t4 = {
|
static struct irqchip s3c_irq_eint0t4 = {
|
||||||
.ack = s3c_irq_ack,
|
.ack = s3c_irq_ack,
|
||||||
.mask = s3c_irq_mask,
|
.mask = s3c_irq_mask,
|
||||||
.unmask = s3c_irq_unmask,
|
.unmask = s3c_irq_unmask,
|
||||||
.wake = s3c_irq_wake,
|
.set_wake = s3c_irq_wake,
|
||||||
.type = s3c_irqext_type,
|
.set_type = s3c_irqext_type,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* mask values for the parent registers for each of the interrupt types */
|
/* 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 != 0) {
|
||||||
if (subsrc & 1) {
|
if (subsrc & 1) {
|
||||||
mydesc = irq_desc + IRQ_TC;
|
mydesc = irq_desc + IRQ_TC;
|
||||||
mydesc->handle( IRQ_TC, mydesc, regs);
|
desc_handle_irq(IRQ_TC, mydesc, regs);
|
||||||
}
|
}
|
||||||
if (subsrc & 2) {
|
if (subsrc & 2) {
|
||||||
mydesc = irq_desc + IRQ_ADC;
|
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;
|
desc = irq_desc + start;
|
||||||
|
|
||||||
if (subsrc & 1)
|
if (subsrc & 1)
|
||||||
desc->handle(start, desc, regs);
|
desc_handle_irq(start, desc, regs);
|
||||||
|
|
||||||
desc++;
|
desc++;
|
||||||
|
|
||||||
if (subsrc & 2)
|
if (subsrc & 2)
|
||||||
desc->handle(start+1, desc, regs);
|
desc_handle_irq(start+1, desc, regs);
|
||||||
|
|
||||||
desc++;
|
desc++;
|
||||||
|
|
||||||
if (subsrc & 4)
|
if (subsrc & 4)
|
||||||
desc->handle(start+2, desc, regs);
|
desc_handle_irq(start+2, desc, regs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
270
arch/arm/mach-s3c2410/mach-anubis.c
Normal file
270
arch/arm/mach-s3c2410/mach-anubis.c
Normal 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
|
|
@ -110,34 +110,24 @@ void __init n30_init_irq(void)
|
||||||
s3c24xx_init_irq();
|
s3c24xx_init_irq();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* GPB3 is the line that controls the pull-up for the USB D+ line */
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void __init n30_init(void)
|
void __init n30_init(void)
|
||||||
{
|
{
|
||||||
s3c_device_i2c.dev.platform_data = &n30_i2ccfg;
|
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")
|
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_ram = S3C2410_SDRAM_PA,
|
||||||
.phys_io = S3C2410_PA_UART,
|
.phys_io = S3C2410_PA_UART,
|
||||||
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
|
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
|
||||||
|
|
|
@ -48,7 +48,7 @@ static __init int pm_simtec_init(void)
|
||||||
|
|
||||||
/* check which machine we are running on */
|
/* 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;
|
return 0;
|
||||||
|
|
||||||
printk(KERN_INFO "Simtec Board Power Manangement" COPYRIGHT "\n");
|
printk(KERN_INFO "Simtec Board Power Manangement" COPYRIGHT "\n");
|
||||||
|
|
|
@ -585,14 +585,16 @@ static int s3c2410_pm_enter(suspend_state_t state)
|
||||||
|
|
||||||
s3c2410_pm_check_store();
|
s3c2410_pm_check_store();
|
||||||
|
|
||||||
// need to make some form of time-delta
|
|
||||||
|
|
||||||
/* send the cpu to sleep... */
|
/* send the cpu to sleep... */
|
||||||
|
|
||||||
__raw_writel(0x00, S3C2410_CLKCON); /* turn off clocks over sleep */
|
__raw_writel(0x00, S3C2410_CLKCON); /* turn off clocks over sleep */
|
||||||
|
|
||||||
s3c2410_cpu_suspend(regs_save);
|
s3c2410_cpu_suspend(regs_save);
|
||||||
|
|
||||||
|
/* restore the cpu state */
|
||||||
|
|
||||||
|
cpu_init();
|
||||||
|
|
||||||
/* unset the return-from-sleep flag, to ensure reset */
|
/* unset the return-from-sleep flag, to ensure reset */
|
||||||
|
|
||||||
tmp = __raw_readl(S3C2410_GSTATUS2);
|
tmp = __raw_readl(S3C2410_GSTATUS2);
|
||||||
|
|
|
@ -64,11 +64,11 @@ static void s3c_irq_demux_wdtac97(unsigned int irq,
|
||||||
if (subsrc != 0) {
|
if (subsrc != 0) {
|
||||||
if (subsrc & 1) {
|
if (subsrc & 1) {
|
||||||
mydesc = irq_desc + IRQ_S3C2440_WDT;
|
mydesc = irq_desc + IRQ_S3C2440_WDT;
|
||||||
mydesc->handle( IRQ_S3C2440_WDT, mydesc, regs);
|
desc_handle_irq(IRQ_S3C2440_WDT, mydesc, regs);
|
||||||
}
|
}
|
||||||
if (subsrc & 2) {
|
if (subsrc & 2) {
|
||||||
mydesc = irq_desc + IRQ_S3C2440_AC97;
|
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 != 0) {
|
||||||
if (subsrc & 1) {
|
if (subsrc & 1) {
|
||||||
mydesc = irq_desc + IRQ_S3C2440_CAM_C;
|
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) {
|
if (subsrc & 2) {
|
||||||
mydesc = irq_desc + IRQ_S3C2440_CAM_P;
|
mydesc = irq_desc + IRQ_S3C2440_CAM_P;
|
||||||
mydesc->handle(IRQ_S3C2440_AC97, mydesc, regs);
|
desc_handle_irq(IRQ_S3C2440_CAM_P, mydesc, regs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -164,7 +164,7 @@ static void s3c2410_timer_setup (void)
|
||||||
|
|
||||||
/* configure the system for whichever machine is in use */
|
/* 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 is at 12MHz, scaler is 1 */
|
||||||
timer_usec_ticks = timer_mask_usec_ticks(1, 12000000);
|
timer_usec_ticks = timer_mask_usec_ticks(1, 12000000);
|
||||||
tcnt = 12000000 / HZ;
|
tcnt = 12000000 / HZ;
|
||||||
|
|
|
@ -98,8 +98,8 @@ static struct irqchip sa1100_low_gpio_chip = {
|
||||||
.ack = sa1100_low_gpio_ack,
|
.ack = sa1100_low_gpio_ack,
|
||||||
.mask = sa1100_low_gpio_mask,
|
.mask = sa1100_low_gpio_mask,
|
||||||
.unmask = sa1100_low_gpio_unmask,
|
.unmask = sa1100_low_gpio_unmask,
|
||||||
.type = sa1100_gpio_type,
|
.set_type = sa1100_gpio_type,
|
||||||
.wake = sa1100_low_gpio_wake,
|
.set_wake = sa1100_low_gpio_wake,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -126,7 +126,7 @@ sa1100_high_gpio_handler(unsigned int irq, struct irqdesc *desc,
|
||||||
mask >>= 11;
|
mask >>= 11;
|
||||||
do {
|
do {
|
||||||
if (mask & 1)
|
if (mask & 1)
|
||||||
desc->handle(irq, desc, regs);
|
desc_handle_irq(irq, desc, regs);
|
||||||
mask >>= 1;
|
mask >>= 1;
|
||||||
irq++;
|
irq++;
|
||||||
desc++;
|
desc++;
|
||||||
|
@ -181,8 +181,8 @@ static struct irqchip sa1100_high_gpio_chip = {
|
||||||
.ack = sa1100_high_gpio_ack,
|
.ack = sa1100_high_gpio_ack,
|
||||||
.mask = sa1100_high_gpio_mask,
|
.mask = sa1100_high_gpio_mask,
|
||||||
.unmask = sa1100_high_gpio_unmask,
|
.unmask = sa1100_high_gpio_unmask,
|
||||||
.type = sa1100_gpio_type,
|
.set_type = sa1100_gpio_type,
|
||||||
.wake = sa1100_high_gpio_wake,
|
.set_wake = sa1100_high_gpio_wake,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -61,12 +61,12 @@ neponset_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *reg
|
||||||
|
|
||||||
if (irr & IRR_ETHERNET) {
|
if (irr & IRR_ETHERNET) {
|
||||||
d = irq_desc + IRQ_NEPONSET_SMC9196;
|
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) {
|
if (irr & IRR_USAR) {
|
||||||
d = irq_desc + IRQ_NEPONSET_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);
|
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) {
|
if (irr & IRR_SA1111) {
|
||||||
d = irq_desc + IRQ_NEPONSET_SA1111;
|
d = irq_desc + IRQ_NEPONSET_SA1111;
|
||||||
d->handle(IRQ_NEPONSET_SA1111, d, regs);
|
desc_handle_irq(IRQ_NEPONSET_SA1111, d, regs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,7 +108,7 @@ sic_handle_irq(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
|
||||||
irq += IRQ_SIC_START;
|
irq += IRQ_SIC_START;
|
||||||
|
|
||||||
desc = irq_desc + irq;
|
desc = irq_desc + irq;
|
||||||
desc->handle(irq, desc, regs);
|
desc_handle_irq(irq, desc, regs);
|
||||||
} while (status);
|
} while (status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,8 +38,8 @@ ENTRY(cpu_arm7_data_abort)
|
||||||
mrc p15, 0, r1, c5, c0, 0 @ get FSR
|
mrc p15, 0, r1, c5, c0, 0 @ get FSR
|
||||||
mrc p15, 0, r0, c6, c0, 0 @ get FAR
|
mrc p15, 0, r0, c6, c0, 0 @ get FAR
|
||||||
ldr r8, [r0] @ read arm instruction
|
ldr r8, [r0] @ read arm instruction
|
||||||
tst r8, #1 << 20 @ L = 1 -> write?
|
tst r8, #1 << 20 @ L = 0 -> write?
|
||||||
orreq r1, r1, #1 << 8 @ yes.
|
orreq r1, r1, #1 << 11 @ yes.
|
||||||
and r7, r8, #15 << 24
|
and r7, r8, #15 << 24
|
||||||
add pc, pc, r7, lsr #22 @ Now branch to the relevant processing routine
|
add pc, pc, r7, lsr #22 @ Now branch to the relevant processing routine
|
||||||
nop
|
nop
|
||||||
|
@ -71,8 +71,8 @@ ENTRY(cpu_arm6_data_abort)
|
||||||
mrc p15, 0, r1, c5, c0, 0 @ get FSR
|
mrc p15, 0, r1, c5, c0, 0 @ get FSR
|
||||||
mrc p15, 0, r0, c6, c0, 0 @ get FAR
|
mrc p15, 0, r0, c6, c0, 0 @ get FAR
|
||||||
ldr r8, [r2] @ read arm instruction
|
ldr r8, [r2] @ read arm instruction
|
||||||
tst r8, #1 << 20 @ L = 1 -> write?
|
tst r8, #1 << 20 @ L = 0 -> write?
|
||||||
orreq r1, r1, #1 << 8 @ yes.
|
orreq r1, r1, #1 << 11 @ yes.
|
||||||
and r7, r8, #14 << 24
|
and r7, r8, #14 << 24
|
||||||
teq r7, #8 << 24 @ was it ldm/stm
|
teq r7, #8 << 24 @ was it ldm/stm
|
||||||
movne pc, lr
|
movne pc, lr
|
||||||
|
|
|
@ -91,6 +91,13 @@ config OMAP_32K_TIMER_HZ
|
||||||
Kernel internal timer frequency should be a divisor of 32768,
|
Kernel internal timer frequency should be a divisor of 32768,
|
||||||
such as 64 or 128.
|
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
|
choice
|
||||||
prompt "Low-level debug console UART"
|
prompt "Low-level debug console UART"
|
||||||
depends on ARCH_OMAP
|
depends on ARCH_OMAP
|
||||||
|
@ -107,6 +114,15 @@ config OMAP_LL_DEBUG_UART3
|
||||||
|
|
||||||
endchoice
|
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
|
endmenu
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
# Common support
|
# 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-m :=
|
||||||
obj-n :=
|
obj-n :=
|
||||||
obj- :=
|
obj- :=
|
||||||
|
@ -15,3 +15,5 @@ obj-$(CONFIG_ARCH_OMAP16XX) += ocpi.o
|
||||||
obj-$(CONFIG_PM) += pm.o sleep.o
|
obj-$(CONFIG_PM) += pm.o sleep.o
|
||||||
|
|
||||||
obj-$(CONFIG_CPU_FREQ) += cpu-omap.o
|
obj-$(CONFIG_CPU_FREQ) += cpu-omap.o
|
||||||
|
obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include <asm/arch/usb.h>
|
#include <asm/arch/usb.h>
|
||||||
|
|
||||||
#include "clock.h"
|
#include "clock.h"
|
||||||
|
#include "sram.h"
|
||||||
|
|
||||||
static LIST_HEAD(clocks);
|
static LIST_HEAD(clocks);
|
||||||
static DECLARE_MUTEX(clocks_sem);
|
static DECLARE_MUTEX(clocks_sem);
|
||||||
|
@ -141,7 +142,7 @@ static struct clk arm_ck = {
|
||||||
static struct clk armper_ck = {
|
static struct clk armper_ck = {
|
||||||
.name = "armper_ck",
|
.name = "armper_ck",
|
||||||
.parent = &ck_dpll1,
|
.parent = &ck_dpll1,
|
||||||
.flags = CLOCK_IN_OMAP730 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
|
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
|
||||||
RATE_CKCTL,
|
RATE_CKCTL,
|
||||||
.enable_reg = ARM_IDLECT2,
|
.enable_reg = ARM_IDLECT2,
|
||||||
.enable_bit = EN_PERCK,
|
.enable_bit = EN_PERCK,
|
||||||
|
@ -385,7 +386,8 @@ static struct clk uart2_ck = {
|
||||||
.name = "uart2_ck",
|
.name = "uart2_ck",
|
||||||
/* Direct from ULPD, no parent */
|
/* Direct from ULPD, no parent */
|
||||||
.rate = 12000000,
|
.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_reg = MOD_CONF_CTRL_0,
|
||||||
.enable_bit = 30, /* Chooses between 12MHz and 48MHz */
|
.enable_bit = 30, /* Chooses between 12MHz and 48MHz */
|
||||||
.set_rate = &set_uart_rate,
|
.set_rate = &set_uart_rate,
|
||||||
|
@ -443,6 +445,15 @@ static struct clk usb_hhc_ck16xx = {
|
||||||
.enable_bit = 8 /* UHOST_EN */,
|
.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 = {
|
static struct clk mclk_1510 = {
|
||||||
.name = "mclk",
|
.name = "mclk",
|
||||||
/* Direct from ULPD, no parent. May be enabled by ext hardware. */
|
/* Direct from ULPD, no parent. May be enabled by ext hardware. */
|
||||||
|
@ -552,6 +563,7 @@ static struct clk * onchip_clks[] = {
|
||||||
&uart3_16xx,
|
&uart3_16xx,
|
||||||
&usb_clko,
|
&usb_clko,
|
||||||
&usb_hhc_ck1510, &usb_hhc_ck16xx,
|
&usb_hhc_ck1510, &usb_hhc_ck16xx,
|
||||||
|
&usb_dc_ck,
|
||||||
&mclk_1510, &mclk_16xx,
|
&mclk_1510, &mclk_16xx,
|
||||||
&bclk_1510, &bclk_16xx,
|
&bclk_1510, &bclk_16xx,
|
||||||
&mmc1_ck,
|
&mmc1_ck,
|
||||||
|
@ -946,14 +958,13 @@ static int select_table_rate(struct clk * clk, unsigned long rate)
|
||||||
if (!ptr->rate)
|
if (!ptr->rate)
|
||||||
return -EINVAL;
|
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)) {
|
ck_dpll1.rate = ptr->pll_rate;
|
||||||
omap_writew(ptr->dpllctl_val, DPLL_CTL);
|
|
||||||
ck_dpll1.rate = ptr->pll_rate;
|
|
||||||
}
|
|
||||||
omap_writew(ptr->ckctl_val, ARM_CKCTL);
|
|
||||||
propagate_rate(&ck_dpll1);
|
propagate_rate(&ck_dpll1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1224,9 +1235,11 @@ int __init clk_init(void)
|
||||||
#endif
|
#endif
|
||||||
/* Cache rates for clocks connected to ck_ref (not dpll1) */
|
/* Cache rates for clocks connected to ck_ref (not dpll1) */
|
||||||
propagate_rate(&ck_ref);
|
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_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
|
#ifdef CONFIG_MACH_OMAP_PERSEUS2
|
||||||
/* Select slicer output as OMAP input clock */
|
/* Select slicer output as OMAP input clock */
|
||||||
|
@ -1271,7 +1284,9 @@ static int __init omap_late_clk_reset(void)
|
||||||
struct clk *p;
|
struct clk *p;
|
||||||
__u32 regval32;
|
__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);
|
omap_writew(0, SOFT_REQ_REG2);
|
||||||
|
|
||||||
list_for_each_entry(p, &clocks, node) {
|
list_for_each_entry(p, &clocks, node) {
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <asm/hardware/clock.h>
|
#include <asm/hardware/clock.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include <asm/mach-types.h>
|
#include <asm/mach-types.h>
|
||||||
|
#include <asm/setup.h>
|
||||||
|
|
||||||
#include <asm/arch/board.h>
|
#include <asm/arch/board.h>
|
||||||
#include <asm/arch/mux.h>
|
#include <asm/arch/mux.h>
|
||||||
|
@ -35,11 +36,11 @@
|
||||||
|
|
||||||
#define NO_LENGTH_CHECK 0xffffffff
|
#define NO_LENGTH_CHECK 0xffffffff
|
||||||
|
|
||||||
extern int omap_bootloader_tag_len;
|
unsigned char omap_bootloader_tag[512];
|
||||||
extern u8 omap_bootloader_tag[];
|
int omap_bootloader_tag_len;
|
||||||
|
|
||||||
struct omap_board_config_kernel *omap_board_config;
|
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)
|
static const void *get_config(u16 tag, size_t len, int skip, size_t *len_out)
|
||||||
{
|
{
|
||||||
|
|
|
@ -425,7 +425,7 @@ static int dma_handle_ch(int ch)
|
||||||
dma_chan[ch + 6].saved_csr = csr >> 7;
|
dma_chan[ch + 6].saved_csr = csr >> 7;
|
||||||
csr &= 0x7f;
|
csr &= 0x7f;
|
||||||
}
|
}
|
||||||
if (!csr)
|
if ((csr & 0x3f) == 0)
|
||||||
return 0;
|
return 0;
|
||||||
if (unlikely(dma_chan[ch].dev_id == -1)) {
|
if (unlikely(dma_chan[ch].dev_id == -1)) {
|
||||||
printk(KERN_WARNING "Spurious interrupt from DMA channel %d (CSR %04x)\n",
|
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;
|
w |= 1 << 8;
|
||||||
omap_writew(w, OMAP1610_DMA_LCD_CTRL);
|
omap_writew(w, OMAP1610_DMA_LCD_CTRL);
|
||||||
|
|
||||||
|
lcd_dma.active = 1;
|
||||||
|
|
||||||
w = omap_readw(OMAP1610_DMA_LCD_CCR);
|
w = omap_readw(OMAP1610_DMA_LCD_CCR);
|
||||||
w |= 1 << 7;
|
w |= 1 << 7;
|
||||||
omap_writew(w, OMAP1610_DMA_LCD_CCR);
|
omap_writew(w, OMAP1610_DMA_LCD_CCR);
|
||||||
|
|
||||||
lcd_dma.active = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void omap_setup_lcd_dma(void)
|
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)
|
dma_addr_t omap_get_dma_src_pos(int lch)
|
||||||
{
|
{
|
||||||
return (dma_addr_t) (OMAP_DMA_CSSA_L(lch) |
|
return (dma_addr_t) (omap_readw(OMAP_DMA_CSSA_L(lch)) |
|
||||||
(OMAP_DMA_CSSA_U(lch) << 16));
|
(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)
|
dma_addr_t omap_get_dma_dst_pos(int lch)
|
||||||
{
|
{
|
||||||
return (dma_addr_t) (OMAP_DMA_CDSA_L(lch) |
|
return (dma_addr_t) (omap_readw(OMAP_DMA_CDSA_L(lch)) |
|
||||||
(OMAP_DMA_CDSA_U(lch) << 16));
|
(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)
|
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_src_pos);
|
||||||
EXPORT_SYMBOL(omap_get_dma_dst_pos);
|
EXPORT_SYMBOL(omap_get_dma_dst_pos);
|
||||||
|
EXPORT_SYMBOL(omap_get_dma_src_addr_counter);
|
||||||
EXPORT_SYMBOL(omap_clear_dma);
|
EXPORT_SYMBOL(omap_clear_dma);
|
||||||
EXPORT_SYMBOL(omap_set_dma_priority);
|
EXPORT_SYMBOL(omap_set_dma_priority);
|
||||||
EXPORT_SYMBOL(omap_request_dma);
|
EXPORT_SYMBOL(omap_request_dma);
|
||||||
|
|
260
arch/arm/plat-omap/dmtimer.c
Normal file
260
arch/arm/plat-omap/dmtimer.c
Normal 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);
|
|
@ -3,7 +3,7 @@
|
||||||
*
|
*
|
||||||
* Support functions for OMAP GPIO
|
* 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>
|
* Written by Juha Yrjölä <juha.yrjola@nokia.com>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
@ -17,8 +17,11 @@
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/ptrace.h>
|
#include <linux/ptrace.h>
|
||||||
|
#include <linux/sysdev.h>
|
||||||
|
#include <linux/err.h>
|
||||||
|
|
||||||
#include <asm/hardware.h>
|
#include <asm/hardware.h>
|
||||||
|
#include <asm/hardware/clock.h>
|
||||||
#include <asm/irq.h>
|
#include <asm/irq.h>
|
||||||
#include <asm/arch/irqs.h>
|
#include <asm/arch/irqs.h>
|
||||||
#include <asm/arch/gpio.h>
|
#include <asm/arch/gpio.h>
|
||||||
|
@ -29,7 +32,7 @@
|
||||||
/*
|
/*
|
||||||
* OMAP1510 GPIO registers
|
* 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_INPUT 0x00
|
||||||
#define OMAP1510_GPIO_DATA_OUTPUT 0x04
|
#define OMAP1510_GPIO_DATA_OUTPUT 0x04
|
||||||
#define OMAP1510_GPIO_DIR_CONTROL 0x08
|
#define OMAP1510_GPIO_DIR_CONTROL 0x08
|
||||||
|
@ -43,34 +46,37 @@
|
||||||
/*
|
/*
|
||||||
* OMAP1610 specific GPIO registers
|
* OMAP1610 specific GPIO registers
|
||||||
*/
|
*/
|
||||||
#define OMAP1610_GPIO1_BASE 0xfffbe400
|
#define OMAP1610_GPIO1_BASE (void __iomem *)0xfffbe400
|
||||||
#define OMAP1610_GPIO2_BASE 0xfffbec00
|
#define OMAP1610_GPIO2_BASE (void __iomem *)0xfffbec00
|
||||||
#define OMAP1610_GPIO3_BASE 0xfffbb400
|
#define OMAP1610_GPIO3_BASE (void __iomem *)0xfffbb400
|
||||||
#define OMAP1610_GPIO4_BASE 0xfffbbc00
|
#define OMAP1610_GPIO4_BASE (void __iomem *)0xfffbbc00
|
||||||
#define OMAP1610_GPIO_REVISION 0x0000
|
#define OMAP1610_GPIO_REVISION 0x0000
|
||||||
#define OMAP1610_GPIO_SYSCONFIG 0x0010
|
#define OMAP1610_GPIO_SYSCONFIG 0x0010
|
||||||
#define OMAP1610_GPIO_SYSSTATUS 0x0014
|
#define OMAP1610_GPIO_SYSSTATUS 0x0014
|
||||||
#define OMAP1610_GPIO_IRQSTATUS1 0x0018
|
#define OMAP1610_GPIO_IRQSTATUS1 0x0018
|
||||||
#define OMAP1610_GPIO_IRQENABLE1 0x001c
|
#define OMAP1610_GPIO_IRQENABLE1 0x001c
|
||||||
|
#define OMAP1610_GPIO_WAKEUPENABLE 0x0028
|
||||||
#define OMAP1610_GPIO_DATAIN 0x002c
|
#define OMAP1610_GPIO_DATAIN 0x002c
|
||||||
#define OMAP1610_GPIO_DATAOUT 0x0030
|
#define OMAP1610_GPIO_DATAOUT 0x0030
|
||||||
#define OMAP1610_GPIO_DIRECTION 0x0034
|
#define OMAP1610_GPIO_DIRECTION 0x0034
|
||||||
#define OMAP1610_GPIO_EDGE_CTRL1 0x0038
|
#define OMAP1610_GPIO_EDGE_CTRL1 0x0038
|
||||||
#define OMAP1610_GPIO_EDGE_CTRL2 0x003c
|
#define OMAP1610_GPIO_EDGE_CTRL2 0x003c
|
||||||
#define OMAP1610_GPIO_CLEAR_IRQENABLE1 0x009c
|
#define OMAP1610_GPIO_CLEAR_IRQENABLE1 0x009c
|
||||||
|
#define OMAP1610_GPIO_CLEAR_WAKEUPENA 0x00a8
|
||||||
#define OMAP1610_GPIO_CLEAR_DATAOUT 0x00b0
|
#define OMAP1610_GPIO_CLEAR_DATAOUT 0x00b0
|
||||||
#define OMAP1610_GPIO_SET_IRQENABLE1 0x00dc
|
#define OMAP1610_GPIO_SET_IRQENABLE1 0x00dc
|
||||||
|
#define OMAP1610_GPIO_SET_WAKEUPENA 0x00e8
|
||||||
#define OMAP1610_GPIO_SET_DATAOUT 0x00f0
|
#define OMAP1610_GPIO_SET_DATAOUT 0x00f0
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* OMAP730 specific GPIO registers
|
* OMAP730 specific GPIO registers
|
||||||
*/
|
*/
|
||||||
#define OMAP730_GPIO1_BASE 0xfffbc000
|
#define OMAP730_GPIO1_BASE (void __iomem *)0xfffbc000
|
||||||
#define OMAP730_GPIO2_BASE 0xfffbc800
|
#define OMAP730_GPIO2_BASE (void __iomem *)0xfffbc800
|
||||||
#define OMAP730_GPIO3_BASE 0xfffbd000
|
#define OMAP730_GPIO3_BASE (void __iomem *)0xfffbd000
|
||||||
#define OMAP730_GPIO4_BASE 0xfffbd800
|
#define OMAP730_GPIO4_BASE (void __iomem *)0xfffbd800
|
||||||
#define OMAP730_GPIO5_BASE 0xfffbe000
|
#define OMAP730_GPIO5_BASE (void __iomem *)0xfffbe000
|
||||||
#define OMAP730_GPIO6_BASE 0xfffbe800
|
#define OMAP730_GPIO6_BASE (void __iomem *)0xfffbe800
|
||||||
#define OMAP730_GPIO_DATA_INPUT 0x00
|
#define OMAP730_GPIO_DATA_INPUT 0x00
|
||||||
#define OMAP730_GPIO_DATA_OUTPUT 0x04
|
#define OMAP730_GPIO_DATA_OUTPUT 0x04
|
||||||
#define OMAP730_GPIO_DIR_CONTROL 0x08
|
#define OMAP730_GPIO_DIR_CONTROL 0x08
|
||||||
|
@ -78,14 +84,43 @@
|
||||||
#define OMAP730_GPIO_INT_MASK 0x10
|
#define OMAP730_GPIO_INT_MASK 0x10
|
||||||
#define OMAP730_GPIO_INT_STATUS 0x14
|
#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)
|
#define OMAP_MPUIO_MASK (~OMAP_MAX_GPIO_LINES & 0xff)
|
||||||
|
|
||||||
struct gpio_bank {
|
struct gpio_bank {
|
||||||
u32 base;
|
void __iomem *base;
|
||||||
u16 irq;
|
u16 irq;
|
||||||
u16 virtual_irq_start;
|
u16 virtual_irq_start;
|
||||||
u8 method;
|
int method;
|
||||||
u32 reserved_map;
|
u32 reserved_map;
|
||||||
|
u32 suspend_wakeup;
|
||||||
|
u32 saved_wakeup;
|
||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -93,8 +128,9 @@ struct gpio_bank {
|
||||||
#define METHOD_GPIO_1510 1
|
#define METHOD_GPIO_1510 1
|
||||||
#define METHOD_GPIO_1610 2
|
#define METHOD_GPIO_1610 2
|
||||||
#define METHOD_GPIO_730 3
|
#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] = {
|
static struct gpio_bank gpio_bank_1610[5] = {
|
||||||
{ OMAP_MPUIO_BASE, INT_MPUIO, IH_MPUIO_BASE, METHOD_MPUIO},
|
{ OMAP_MPUIO_BASE, INT_MPUIO, IH_MPUIO_BASE, METHOD_MPUIO},
|
||||||
{ OMAP1610_GPIO1_BASE, INT_GPIO_BANK1, IH_GPIO_BASE, METHOD_GPIO_1610 },
|
{ 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
|
#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 struct gpio_bank *gpio_bank;
|
||||||
static int gpio_bank_count;
|
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)];
|
return &gpio_bank[1 + (gpio >> 5)];
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CONFIG_ARCH_OMAP24XX
|
||||||
|
if (cpu_is_omap24xx())
|
||||||
|
return &gpio_bank[gpio >> 5];
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int get_gpio_index(int gpio)
|
static inline int get_gpio_index(int gpio)
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_ARCH_OMAP730
|
||||||
if (cpu_is_omap730())
|
if (cpu_is_omap730())
|
||||||
return gpio & 0x1f;
|
return gpio & 0x1f;
|
||||||
else
|
#endif
|
||||||
return gpio & 0x0f;
|
#ifdef CONFIG_ARCH_OMAP24XX
|
||||||
|
if (cpu_is_omap24xx())
|
||||||
|
return gpio & 0x1f;
|
||||||
|
#endif
|
||||||
|
return gpio & 0x0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int gpio_valid(int gpio)
|
static inline int gpio_valid(int gpio)
|
||||||
|
@ -179,6 +233,10 @@ static inline int gpio_valid(int gpio)
|
||||||
#ifdef CONFIG_ARCH_OMAP730
|
#ifdef CONFIG_ARCH_OMAP730
|
||||||
if (cpu_is_omap730() && gpio < 192)
|
if (cpu_is_omap730() && gpio < 192)
|
||||||
return 0;
|
return 0;
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_ARCH_OMAP24XX
|
||||||
|
if (cpu_is_omap24xx() && gpio < 128)
|
||||||
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
return -1;
|
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)
|
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;
|
u32 l;
|
||||||
|
|
||||||
switch (bank->method) {
|
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:
|
case METHOD_GPIO_730:
|
||||||
reg += OMAP730_GPIO_DIR_CONTROL;
|
reg += OMAP730_GPIO_DIR_CONTROL;
|
||||||
break;
|
break;
|
||||||
|
case METHOD_GPIO_24XX:
|
||||||
|
reg += OMAP24XX_GPIO_OE;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
l = __raw_readl(reg);
|
l = __raw_readl(reg);
|
||||||
if (is_input)
|
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)
|
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;
|
u32 l = 0;
|
||||||
|
|
||||||
switch (bank->method) {
|
switch (bank->method) {
|
||||||
|
@ -269,6 +330,13 @@ static void _set_gpio_dataout(struct gpio_bank *bank, int gpio, int enable)
|
||||||
else
|
else
|
||||||
l &= ~(1 << gpio);
|
l &= ~(1 << gpio);
|
||||||
break;
|
break;
|
||||||
|
case METHOD_GPIO_24XX:
|
||||||
|
if (enable)
|
||||||
|
reg += OMAP24XX_GPIO_SETDATAOUT;
|
||||||
|
else
|
||||||
|
reg += OMAP24XX_GPIO_CLEARDATAOUT;
|
||||||
|
l = 1 << gpio;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
BUG();
|
BUG();
|
||||||
return;
|
return;
|
||||||
|
@ -291,7 +359,7 @@ void omap_set_gpio_dataout(int gpio, int enable)
|
||||||
int omap_get_gpio_datain(int gpio)
|
int omap_get_gpio_datain(int gpio)
|
||||||
{
|
{
|
||||||
struct gpio_bank *bank;
|
struct gpio_bank *bank;
|
||||||
u32 reg;
|
void __iomem *reg;
|
||||||
|
|
||||||
if (check_gpio(gpio) < 0)
|
if (check_gpio(gpio) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -310,109 +378,132 @@ int omap_get_gpio_datain(int gpio)
|
||||||
case METHOD_GPIO_730:
|
case METHOD_GPIO_730:
|
||||||
reg += OMAP730_GPIO_DATA_INPUT;
|
reg += OMAP730_GPIO_DATA_INPUT;
|
||||||
break;
|
break;
|
||||||
|
case METHOD_GPIO_24XX:
|
||||||
|
reg += OMAP24XX_GPIO_DATAIN;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
BUG();
|
BUG();
|
||||||
return -1;
|
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 gpio_bit = 1 << gpio;
|
||||||
u32 l;
|
|
||||||
|
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) {
|
switch (bank->method) {
|
||||||
case METHOD_MPUIO:
|
case METHOD_MPUIO:
|
||||||
reg += OMAP_MPUIO_GPIO_INT_EDGE;
|
reg += OMAP_MPUIO_GPIO_INT_EDGE;
|
||||||
l = __raw_readl(reg);
|
l = __raw_readl(reg);
|
||||||
if (edge == OMAP_GPIO_RISING_EDGE)
|
if (trigger == IRQT_RISING)
|
||||||
l |= 1 << gpio;
|
l |= 1 << gpio;
|
||||||
else
|
else if (trigger == IRQT_FALLING)
|
||||||
l &= ~(1 << gpio);
|
l &= ~(1 << gpio);
|
||||||
__raw_writel(l, reg);
|
else
|
||||||
|
goto bad;
|
||||||
break;
|
break;
|
||||||
case METHOD_GPIO_1510:
|
case METHOD_GPIO_1510:
|
||||||
reg += OMAP1510_GPIO_INT_CONTROL;
|
reg += OMAP1510_GPIO_INT_CONTROL;
|
||||||
l = __raw_readl(reg);
|
l = __raw_readl(reg);
|
||||||
if (edge == OMAP_GPIO_RISING_EDGE)
|
if (trigger == IRQT_RISING)
|
||||||
l |= 1 << gpio;
|
l |= 1 << gpio;
|
||||||
else
|
else if (trigger == IRQT_FALLING)
|
||||||
l &= ~(1 << gpio);
|
l &= ~(1 << gpio);
|
||||||
__raw_writel(l, reg);
|
else
|
||||||
|
goto bad;
|
||||||
break;
|
break;
|
||||||
case METHOD_GPIO_1610:
|
case METHOD_GPIO_1610:
|
||||||
edge &= 0x03;
|
|
||||||
if (gpio & 0x08)
|
if (gpio & 0x08)
|
||||||
reg += OMAP1610_GPIO_EDGE_CTRL2;
|
reg += OMAP1610_GPIO_EDGE_CTRL2;
|
||||||
else
|
else
|
||||||
reg += OMAP1610_GPIO_EDGE_CTRL1;
|
reg += OMAP1610_GPIO_EDGE_CTRL1;
|
||||||
gpio &= 0x07;
|
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 = __raw_readl(reg);
|
||||||
l &= ~(3 << (gpio << 1));
|
l &= ~(3 << (gpio << 1));
|
||||||
l |= edge << (gpio << 1);
|
l |= trigger << (gpio << 1);
|
||||||
__raw_writel(l, reg);
|
|
||||||
break;
|
break;
|
||||||
case METHOD_GPIO_730:
|
case METHOD_GPIO_730:
|
||||||
reg += OMAP730_GPIO_INT_CONTROL;
|
reg += OMAP730_GPIO_INT_CONTROL;
|
||||||
l = __raw_readl(reg);
|
l = __raw_readl(reg);
|
||||||
if (edge == OMAP_GPIO_RISING_EDGE)
|
if (trigger == IRQT_RISING)
|
||||||
l |= 1 << gpio;
|
l |= 1 << gpio;
|
||||||
else
|
else if (trigger == IRQT_FALLING)
|
||||||
l &= ~(1 << gpio);
|
l &= ~(1 << gpio);
|
||||||
__raw_writel(l, reg);
|
else
|
||||||
|
goto bad;
|
||||||
|
break;
|
||||||
|
case METHOD_GPIO_24XX:
|
||||||
|
set_24xx_gpio_triggering(reg, gpio, trigger);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
BUG();
|
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;
|
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)
|
if (check_gpio(gpio) < 0)
|
||||||
return;
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (type & (__IRQT_LOWLVL|__IRQT_HIGHLVL|IRQT_PROBE))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
bank = get_gpio_bank(gpio);
|
bank = get_gpio_bank(gpio);
|
||||||
spin_lock(&bank->lock);
|
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);
|
spin_unlock(&bank->lock);
|
||||||
}
|
return retval;
|
||||||
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
|
static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
|
||||||
{
|
{
|
||||||
u32 reg = bank->base;
|
void __iomem *reg = bank->base;
|
||||||
|
|
||||||
switch (bank->method) {
|
switch (bank->method) {
|
||||||
case METHOD_MPUIO:
|
case METHOD_MPUIO:
|
||||||
|
@ -428,6 +519,9 @@ static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
|
||||||
case METHOD_GPIO_730:
|
case METHOD_GPIO_730:
|
||||||
reg += OMAP730_GPIO_INT_STATUS;
|
reg += OMAP730_GPIO_INT_STATUS;
|
||||||
break;
|
break;
|
||||||
|
case METHOD_GPIO_24XX:
|
||||||
|
reg += OMAP24XX_GPIO_IRQSTATUS1;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
BUG();
|
BUG();
|
||||||
return;
|
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)
|
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;
|
u32 l;
|
||||||
|
|
||||||
switch (bank->method) {
|
switch (bank->method) {
|
||||||
|
@ -477,6 +571,13 @@ static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask, int enab
|
||||||
else
|
else
|
||||||
l |= gpio_mask;
|
l |= gpio_mask;
|
||||||
break;
|
break;
|
||||||
|
case METHOD_GPIO_24XX:
|
||||||
|
if (enable)
|
||||||
|
reg += OMAP24XX_GPIO_SETIRQENABLE1;
|
||||||
|
else
|
||||||
|
reg += OMAP24XX_GPIO_CLEARIRQENABLE1;
|
||||||
|
l = gpio_mask;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
BUG();
|
BUG();
|
||||||
return;
|
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);
|
_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)
|
int omap_request_gpio(int gpio)
|
||||||
{
|
{
|
||||||
struct gpio_bank *bank;
|
struct gpio_bank *bank;
|
||||||
|
@ -505,14 +650,32 @@ int omap_request_gpio(int gpio)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
bank->reserved_map |= (1 << get_gpio_index(gpio));
|
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
|
#ifdef CONFIG_ARCH_OMAP1510
|
||||||
if (bank->method == METHOD_GPIO_1510) {
|
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;
|
reg = bank->base + OMAP1510_GPIO_PIN_CONTROL;
|
||||||
__raw_writel(__raw_readl(reg) | (1 << get_gpio_index(gpio)), reg);
|
__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
|
#endif
|
||||||
spin_unlock(&bank->lock);
|
spin_unlock(&bank->lock);
|
||||||
|
|
||||||
|
@ -533,6 +696,20 @@ void omap_free_gpio(int gpio)
|
||||||
spin_unlock(&bank->lock);
|
spin_unlock(&bank->lock);
|
||||||
return;
|
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));
|
bank->reserved_map &= ~(1 << get_gpio_index(gpio));
|
||||||
_set_gpio_direction(bank, get_gpio_index(gpio), 1);
|
_set_gpio_direction(bank, get_gpio_index(gpio), 1);
|
||||||
_set_gpio_irqenable(bank, gpio, 0);
|
_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,
|
static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc,
|
||||||
struct pt_regs *regs)
|
struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
u32 isr_reg = 0;
|
void __iomem *isr_reg = NULL;
|
||||||
u32 isr;
|
u32 isr;
|
||||||
unsigned int gpio_irq;
|
unsigned int gpio_irq;
|
||||||
struct gpio_bank *bank;
|
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)
|
if (bank->method == METHOD_GPIO_730)
|
||||||
isr_reg = bank->base + OMAP730_GPIO_INT_STATUS;
|
isr_reg = bank->base + OMAP730_GPIO_INT_STATUS;
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CONFIG_ARCH_OMAP24XX
|
||||||
|
if (bank->method == METHOD_GPIO_24XX)
|
||||||
|
isr_reg = bank->base + OMAP24XX_GPIO_IRQSTATUS1;
|
||||||
|
#endif
|
||||||
|
|
||||||
isr = __raw_readl(isr_reg);
|
while(1) {
|
||||||
_enable_gpio_irqbank(bank, isr, 0);
|
isr = __raw_readl(isr_reg);
|
||||||
_clear_gpio_irqbank(bank, isr);
|
_enable_gpio_irqbank(bank, isr, 0);
|
||||||
_enable_gpio_irqbank(bank, isr, 1);
|
_clear_gpio_irqbank(bank, isr);
|
||||||
desc->chip->unmask(irq);
|
_enable_gpio_irqbank(bank, isr, 1);
|
||||||
|
desc->chip->unmask(irq);
|
||||||
|
|
||||||
if (unlikely(!isr))
|
if (!isr)
|
||||||
return;
|
break;
|
||||||
|
|
||||||
gpio_irq = bank->virtual_irq_start;
|
gpio_irq = bank->virtual_irq_start;
|
||||||
for (; isr != 0; isr >>= 1, gpio_irq++) {
|
for (; isr != 0; isr >>= 1, gpio_irq++) {
|
||||||
struct irqdesc *d;
|
struct irqdesc *d;
|
||||||
if (!(isr & 1))
|
if (!(isr & 1))
|
||||||
continue;
|
continue;
|
||||||
d = irq_desc + gpio_irq;
|
d = irq_desc + gpio_irq;
|
||||||
d->handle(gpio_irq, d, regs);
|
desc_handle_irq(gpio_irq, d, regs);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gpio_ack_irq(unsigned int irq)
|
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)
|
static void gpio_unmask_irq(unsigned int irq)
|
||||||
{
|
{
|
||||||
unsigned int gpio = irq - IH_GPIO_BASE;
|
unsigned int gpio = irq - IH_GPIO_BASE;
|
||||||
|
unsigned int gpio_idx = get_gpio_index(gpio);
|
||||||
struct gpio_bank *bank = get_gpio_bank(gpio);
|
struct gpio_bank *bank = get_gpio_bank(gpio);
|
||||||
|
|
||||||
if (_get_gpio_edge_ctrl(bank, get_gpio_index(gpio)) == OMAP_GPIO_NO_EDGE) {
|
_set_gpio_irqenable(bank, gpio_idx, 1);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mpuio_ack_irq(unsigned int irq)
|
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 = {
|
static struct irqchip gpio_irq_chip = {
|
||||||
.ack = gpio_ack_irq,
|
.ack = gpio_ack_irq,
|
||||||
.mask = gpio_mask_irq,
|
.mask = gpio_mask_irq,
|
||||||
.unmask = gpio_unmask_irq,
|
.unmask = gpio_unmask_irq,
|
||||||
|
.set_type = gpio_irq_type,
|
||||||
|
.set_wake = gpio_wake_enable,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct irqchip mpuio_irq_chip = {
|
static struct irqchip mpuio_irq_chip = {
|
||||||
|
@ -657,6 +838,7 @@ static struct irqchip mpuio_irq_chip = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static int initialized = 0;
|
static int initialized = 0;
|
||||||
|
static struct clk * gpio_ck = NULL;
|
||||||
|
|
||||||
static int __init _omap_gpio_init(void)
|
static int __init _omap_gpio_init(void)
|
||||||
{
|
{
|
||||||
|
@ -665,6 +847,14 @@ static int __init _omap_gpio_init(void)
|
||||||
|
|
||||||
initialized = 1;
|
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
|
#ifdef CONFIG_ARCH_OMAP1510
|
||||||
if (cpu_is_omap1510()) {
|
if (cpu_is_omap1510()) {
|
||||||
printk(KERN_INFO "OMAP1510 GPIO hardware\n");
|
printk(KERN_INFO "OMAP1510 GPIO hardware\n");
|
||||||
|
@ -674,7 +864,7 @@ static int __init _omap_gpio_init(void)
|
||||||
#endif
|
#endif
|
||||||
#if defined(CONFIG_ARCH_OMAP16XX)
|
#if defined(CONFIG_ARCH_OMAP16XX)
|
||||||
if (cpu_is_omap16xx()) {
|
if (cpu_is_omap16xx()) {
|
||||||
int rev;
|
u32 rev;
|
||||||
|
|
||||||
gpio_bank_count = 5;
|
gpio_bank_count = 5;
|
||||||
gpio_bank = gpio_bank_1610;
|
gpio_bank = gpio_bank_1610;
|
||||||
|
@ -689,6 +879,17 @@ static int __init _omap_gpio_init(void)
|
||||||
gpio_bank_count = 7;
|
gpio_bank_count = 7;
|
||||||
gpio_bank = gpio_bank_730;
|
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
|
#endif
|
||||||
for (i = 0; i < gpio_bank_count; i++) {
|
for (i = 0; i < gpio_bank_count; i++) {
|
||||||
int j, gpio_count = 16;
|
int j, gpio_count = 16;
|
||||||
|
@ -710,6 +911,7 @@ static int __init _omap_gpio_init(void)
|
||||||
if (bank->method == METHOD_GPIO_1610) {
|
if (bank->method == METHOD_GPIO_1610) {
|
||||||
__raw_writew(0x0000, bank->base + OMAP1610_GPIO_IRQENABLE1);
|
__raw_writew(0x0000, bank->base + OMAP1610_GPIO_IRQENABLE1);
|
||||||
__raw_writew(0xffff, bank->base + OMAP1610_GPIO_IRQSTATUS1);
|
__raw_writew(0xffff, bank->base + OMAP1610_GPIO_IRQSTATUS1);
|
||||||
|
__raw_writew(0x0014, bank->base + OMAP1610_GPIO_SYSCONFIG);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_ARCH_OMAP730
|
#ifdef CONFIG_ARCH_OMAP730
|
||||||
|
@ -719,6 +921,14 @@ static int __init _omap_gpio_init(void)
|
||||||
|
|
||||||
gpio_count = 32; /* 730 has 32-bit GPIOs */
|
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
|
#endif
|
||||||
for (j = bank->virtual_irq_start;
|
for (j = bank->virtual_irq_start;
|
||||||
j < bank->virtual_irq_start + gpio_count; j++) {
|
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.
|
/* Enable system clock for GPIO module.
|
||||||
* The CAM_CLK_CTRL *is* really the right place. */
|
* 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);
|
omap_writel(omap_readl(ULPD_CAM_CLK_CTRL) | 0x04, ULPD_CAM_CLK_CTRL);
|
||||||
|
|
||||||
return 0;
|
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
|
* This may get called early from board specific init
|
||||||
*/
|
*/
|
||||||
|
@ -752,11 +1047,30 @@ int omap_gpio_init(void)
|
||||||
return 0;
|
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_request_gpio);
|
||||||
EXPORT_SYMBOL(omap_free_gpio);
|
EXPORT_SYMBOL(omap_free_gpio);
|
||||||
EXPORT_SYMBOL(omap_set_gpio_direction);
|
EXPORT_SYMBOL(omap_set_gpio_direction);
|
||||||
EXPORT_SYMBOL(omap_set_gpio_dataout);
|
EXPORT_SYMBOL(omap_set_gpio_dataout);
|
||||||
EXPORT_SYMBOL(omap_get_gpio_datain);
|
EXPORT_SYMBOL(omap_get_gpio_datain);
|
||||||
EXPORT_SYMBOL(omap_set_gpio_edge_ctrl);
|
|
||||||
|
|
||||||
arch_initcall(omap_gpio_init);
|
arch_initcall(omap_gpio_sysinit);
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include <asm/arch/dma.h>
|
#include <asm/arch/dma.h>
|
||||||
#include <asm/arch/mux.h>
|
#include <asm/arch/mux.h>
|
||||||
#include <asm/arch/irqs.h>
|
#include <asm/arch/irqs.h>
|
||||||
|
#include <asm/arch/dsp_common.h>
|
||||||
#include <asm/arch/mcbsp.h>
|
#include <asm/arch/mcbsp.h>
|
||||||
|
|
||||||
#include <asm/hardware/clock.h>
|
#include <asm/hardware/clock.h>
|
||||||
|
@ -187,9 +188,6 @@ static int omap_mcbsp_check(unsigned int id)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define EN_XORPCK 1
|
|
||||||
#define DSP_RSTCT2 0xe1008014
|
|
||||||
|
|
||||||
static void omap_mcbsp_dsp_request(void)
|
static void omap_mcbsp_dsp_request(void)
|
||||||
{
|
{
|
||||||
if (cpu_is_omap1510() || cpu_is_omap16xx()) {
|
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 */
|
/* enable 12MHz clock to mcbsp 1 & 3 */
|
||||||
clk_use(mcbsp_dspxor_ck);
|
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,
|
__raw_writew(__raw_readw(DSP_RSTCT2) | 1 | 1 << 1,
|
||||||
DSP_RSTCT2);
|
DSP_RSTCT2);
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,9 @@ omap_cfg_reg(const reg_cfg_t reg_cfg)
|
||||||
pull_orig = 0, pull = 0;
|
pull_orig = 0, pull = 0;
|
||||||
unsigned int mask, warn = 0;
|
unsigned int mask, warn = 0;
|
||||||
|
|
||||||
|
if (cpu_is_omap7xx())
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (reg_cfg > ARRAY_SIZE(reg_cfg_table)) {
|
if (reg_cfg > ARRAY_SIZE(reg_cfg_table)) {
|
||||||
printk(KERN_ERR "MUX: reg_cfg %d\n", reg_cfg);
|
printk(KERN_ERR "MUX: reg_cfg %d\n", reg_cfg);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
#include <linux/config.h>
|
#include <linux/config.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
#include <linux/version.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
|
|
|
@ -39,24 +39,32 @@
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/proc_fs.h>
|
#include <linux/proc_fs.h>
|
||||||
#include <linux/pm.h>
|
#include <linux/pm.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
|
#include <asm/irq.h>
|
||||||
#include <asm/mach/time.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/pm.h>
|
||||||
#include <asm/arch/mux.h>
|
#include <asm/arch/mux.h>
|
||||||
#include <asm/arch/tc.h>
|
|
||||||
#include <asm/arch/tps65010.h>
|
#include <asm/arch/tps65010.h>
|
||||||
|
#include <asm/arch/dsp_common.h>
|
||||||
|
|
||||||
#include "clock.h"
|
#include "clock.h"
|
||||||
|
#include "sram.h"
|
||||||
|
|
||||||
static unsigned int arm_sleep_save[ARM_SLEEP_SAVE_SIZE];
|
static unsigned int arm_sleep_save[ARM_SLEEP_SAVE_SIZE];
|
||||||
static unsigned short ulpd_sleep_save[ULPD_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 mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_SIZE];
|
||||||
static unsigned int mpui1610_sleep_save[MPUI1610_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
|
* Let's power down on idle, but only if we are really
|
||||||
* idle, because once we start down the path of
|
* 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)
|
void omap_pm_idle(void)
|
||||||
{
|
{
|
||||||
int (*func_ptr)(void) = 0;
|
|
||||||
unsigned int mask32 = 0;
|
unsigned int mask32 = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -83,6 +90,13 @@ void omap_pm_idle(void)
|
||||||
}
|
}
|
||||||
mask32 = omap_readl(ARM_SYSST);
|
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
|
* Since an interrupt may set up a timer, we don't want to
|
||||||
* reprogram the hardware timer with interrupts enabled.
|
* reprogram the hardware timer with interrupts enabled.
|
||||||
|
@ -92,18 +106,9 @@ void omap_pm_idle(void)
|
||||||
|
|
||||||
if ((mask32 & DSP_IDLE) == 0) {
|
if ((mask32 & DSP_IDLE) == 0) {
|
||||||
__asm__ volatile ("mcr p15, 0, r0, c7, c0, 4");
|
__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_fiq_enable();
|
||||||
local_irq_enable();
|
local_irq_enable();
|
||||||
}
|
}
|
||||||
|
@ -115,58 +120,55 @@ void omap_pm_idle(void)
|
||||||
*/
|
*/
|
||||||
static void omap_pm_wakeup_setup(void)
|
static void omap_pm_wakeup_setup(void)
|
||||||
{
|
{
|
||||||
/*
|
u32 level1_wake = OMAP_IRQ_BIT(INT_IH2_IRQ);
|
||||||
* Enable ARM XOR clock and release peripheral from reset by
|
u32 level2_wake = OMAP_IRQ_BIT(INT_UART2) | OMAP_IRQ_BIT(INT_KEYBOARD);
|
||||||
* 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);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Turn off all interrupts except L1-2nd level cascade,
|
* Turn off all interrupts except GPIO bank 1, L1-2nd level cascade,
|
||||||
* and the L2 wakeup interrupts: keypad and UART2.
|
* 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()) {
|
if (cpu_is_omap1510())
|
||||||
omap_writel(~(IRQ_UART2 | IRQ_KEYBOARD), OMAP_IH2_MIR);
|
omap_writel(~level2_wake, OMAP_IH2_MIR);
|
||||||
}
|
|
||||||
|
|
||||||
|
/* INT_1610_WAKE_UP_REQ is needed for GPIO wakeup... */
|
||||||
if (cpu_is_omap16xx()) {
|
if (cpu_is_omap16xx()) {
|
||||||
omap_writel(~(IRQ_UART2 | IRQ_KEYBOARD), OMAP_IH2_0_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_1_MIR);
|
|
||||||
omap_writel(~0x0, OMAP_IH2_2_MIR);
|
omap_writel(~0x0, OMAP_IH2_2_MIR);
|
||||||
omap_writel(~0x0, OMAP_IH2_3_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);
|
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)
|
void omap_pm_suspend(void)
|
||||||
{
|
{
|
||||||
unsigned int mask32 = 0;
|
|
||||||
unsigned long arg0 = 0, arg1 = 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()) {
|
if (machine_is_omap_osk()) {
|
||||||
/* Stop LED1 (D9) blink */
|
/* Stop LED1 (D9) blink */
|
||||||
tps65010_set_led(LED1, OFF);
|
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();
|
local_irq_disable();
|
||||||
|
@ -207,6 +209,8 @@ void omap_pm_suspend(void)
|
||||||
ARM_SAVE(ARM_CKCTL);
|
ARM_SAVE(ARM_CKCTL);
|
||||||
ARM_SAVE(ARM_IDLECT1);
|
ARM_SAVE(ARM_IDLECT1);
|
||||||
ARM_SAVE(ARM_IDLECT2);
|
ARM_SAVE(ARM_IDLECT2);
|
||||||
|
if (!(cpu_is_omap1510()))
|
||||||
|
ARM_SAVE(ARM_IDLECT3);
|
||||||
ARM_SAVE(ARM_EWUPCT);
|
ARM_SAVE(ARM_EWUPCT);
|
||||||
ARM_SAVE(ARM_RSTCT1);
|
ARM_SAVE(ARM_RSTCT1);
|
||||||
ARM_SAVE(ARM_RSTCT2);
|
ARM_SAVE(ARM_RSTCT2);
|
||||||
|
@ -214,42 +218,12 @@ void omap_pm_suspend(void)
|
||||||
ULPD_SAVE(ULPD_CLOCK_CTRL);
|
ULPD_SAVE(ULPD_CLOCK_CTRL);
|
||||||
ULPD_SAVE(ULPD_STATUS_REQ);
|
ULPD_SAVE(ULPD_STATUS_REQ);
|
||||||
|
|
||||||
/*
|
/* (Step 3 removed - we now allow deep sleep by default) */
|
||||||
* 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 4: OMAP DSP Shutdown
|
* 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
|
* Step 5: Wakeup Event Setup
|
||||||
|
@ -258,24 +232,9 @@ void omap_pm_suspend(void)
|
||||||
omap_pm_wakeup_setup();
|
omap_pm_wakeup_setup();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Step 6a: ARM and Traffic controller shutdown
|
* Step 6: ARM and Traffic controller shutdown
|
||||||
*
|
|
||||||
* Step 6 starts here with clock and watchdog disable
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* 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 */
|
/* disable ARM watchdog */
|
||||||
omap_writel(0x00F5, OMAP_WDT_TIMER_MODE);
|
omap_writel(0x00F5, OMAP_WDT_TIMER_MODE);
|
||||||
omap_writel(0x00A0, 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];
|
arg0 = arm_sleep_save[ARM_SLEEP_SAVE_ARM_IDLECT1];
|
||||||
arg1 = arm_sleep_save[ARM_SLEEP_SAVE_ARM_IDLECT2];
|
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
|
* Step 6c: ARM and Traffic controller shutdown
|
||||||
*
|
*
|
||||||
* Jump to assembly code. The processor will stay there
|
* Jump to assembly code. The processor will stay there
|
||||||
* until wake up.
|
* until wake up.
|
||||||
*/
|
*/
|
||||||
|
omap_sram_suspend(arg0, arg1);
|
||||||
func_ptr(arg0, arg1);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we are here, processor is woken up!
|
* 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
|
* 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_CKCTL);
|
||||||
ARM_RESTORE(ARM_EWUPCT);
|
ARM_RESTORE(ARM_EWUPCT);
|
||||||
ARM_RESTORE(ARM_RSTCT1);
|
ARM_RESTORE(ARM_RSTCT1);
|
||||||
|
@ -366,6 +302,8 @@ void omap_pm_suspend(void)
|
||||||
MPUI1610_RESTORE(OMAP_IH2_3_MIR);
|
MPUI1610_RESTORE(OMAP_IH2_3_MIR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
omap_writew(0, ULPD_SOFT_DISABLE_REQ_REG);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reenable interrupts
|
* Reenable interrupts
|
||||||
*/
|
*/
|
||||||
|
@ -373,6 +311,8 @@ void omap_pm_suspend(void)
|
||||||
local_irq_enable();
|
local_irq_enable();
|
||||||
local_fiq_enable();
|
local_fiq_enable();
|
||||||
|
|
||||||
|
omap_serial_wake_trigger(0);
|
||||||
|
|
||||||
printk("PM: OMAP%x is re-starting from deep sleep...\n", system_rev);
|
printk("PM: OMAP%x is re-starting from deep sleep...\n", system_rev);
|
||||||
|
|
||||||
if (machine_is_omap_osk()) {
|
if (machine_is_omap_osk()) {
|
||||||
|
@ -401,6 +341,8 @@ static int omap_pm_read_proc(
|
||||||
ARM_SAVE(ARM_CKCTL);
|
ARM_SAVE(ARM_CKCTL);
|
||||||
ARM_SAVE(ARM_IDLECT1);
|
ARM_SAVE(ARM_IDLECT1);
|
||||||
ARM_SAVE(ARM_IDLECT2);
|
ARM_SAVE(ARM_IDLECT2);
|
||||||
|
if (!(cpu_is_omap1510()))
|
||||||
|
ARM_SAVE(ARM_IDLECT3);
|
||||||
ARM_SAVE(ARM_EWUPCT);
|
ARM_SAVE(ARM_EWUPCT);
|
||||||
ARM_SAVE(ARM_RSTCT1);
|
ARM_SAVE(ARM_RSTCT1);
|
||||||
ARM_SAVE(ARM_RSTCT2);
|
ARM_SAVE(ARM_RSTCT2);
|
||||||
|
@ -436,6 +378,7 @@ static int omap_pm_read_proc(
|
||||||
"ARM_CKCTL_REG: 0x%-8x \n"
|
"ARM_CKCTL_REG: 0x%-8x \n"
|
||||||
"ARM_IDLECT1_REG: 0x%-8x \n"
|
"ARM_IDLECT1_REG: 0x%-8x \n"
|
||||||
"ARM_IDLECT2_REG: 0x%-8x \n"
|
"ARM_IDLECT2_REG: 0x%-8x \n"
|
||||||
|
"ARM_IDLECT3_REG: 0x%-8x \n"
|
||||||
"ARM_EWUPCT_REG: 0x%-8x \n"
|
"ARM_EWUPCT_REG: 0x%-8x \n"
|
||||||
"ARM_RSTCT1_REG: 0x%-8x \n"
|
"ARM_RSTCT1_REG: 0x%-8x \n"
|
||||||
"ARM_RSTCT2_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_CKCTL),
|
||||||
ARM_SHOW(ARM_IDLECT1),
|
ARM_SHOW(ARM_IDLECT1),
|
||||||
ARM_SHOW(ARM_IDLECT2),
|
ARM_SHOW(ARM_IDLECT2),
|
||||||
|
ARM_SHOW(ARM_IDLECT3),
|
||||||
ARM_SHOW(ARM_EWUPCT),
|
ARM_SHOW(ARM_EWUPCT),
|
||||||
ARM_SHOW(ARM_RSTCT1),
|
ARM_SHOW(ARM_RSTCT1),
|
||||||
ARM_SHOW(ARM_RSTCT2),
|
ARM_SHOW(ARM_RSTCT2),
|
||||||
|
@ -507,7 +451,7 @@ static void omap_pm_init_proc(void)
|
||||||
|
|
||||||
entry = create_proc_read_entry("driver/omap_pm",
|
entry = create_proc_read_entry("driver/omap_pm",
|
||||||
S_IWUSR | S_IRUGO, NULL,
|
S_IWUSR | S_IRUGO, NULL,
|
||||||
omap_pm_read_proc, 0);
|
omap_pm_read_proc, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* DEBUG && CONFIG_PROC_FS */
|
#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,
|
.pm_disk_mode = 0,
|
||||||
.prepare = omap_pm_prepare,
|
.prepare = omap_pm_prepare,
|
||||||
.enter = omap_pm_enter,
|
.enter = omap_pm_enter,
|
||||||
|
@ -590,42 +548,61 @@ struct pm_ops omap_pm_ops ={
|
||||||
static int __init omap_pm_init(void)
|
static int __init omap_pm_init(void)
|
||||||
{
|
{
|
||||||
printk("Power Management for TI OMAP.\n");
|
printk("Power Management for TI OMAP.\n");
|
||||||
pm_idle = omap_pm_idle;
|
|
||||||
/*
|
/*
|
||||||
* We copy the assembler sleep/wakeup routines to SRAM.
|
* We copy the assembler sleep/wakeup routines to SRAM.
|
||||||
* These routines need to be in SRAM as that's the only
|
* These routines need to be in SRAM as that's the only
|
||||||
* memory the MPU can see when it wakes up.
|
* memory the MPU can see when it wakes up.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef CONFIG_ARCH_OMAP1510
|
|
||||||
if (cpu_is_omap1510()) {
|
if (cpu_is_omap1510()) {
|
||||||
memcpy((void *)OMAP1510_SRAM_IDLE_SUSPEND,
|
omap_sram_idle = omap_sram_push(omap1510_idle_loop_suspend,
|
||||||
omap1510_idle_loop_suspend,
|
omap1510_idle_loop_suspend_sz);
|
||||||
omap1510_idle_loop_suspend_sz);
|
omap_sram_suspend = omap_sram_push(omap1510_cpu_suspend,
|
||||||
memcpy((void *)OMAP1510_SRAM_API_SUSPEND, omap1510_cpu_suspend,
|
omap1510_cpu_suspend_sz);
|
||||||
omap1510_cpu_suspend_sz);
|
} else if (cpu_is_omap16xx()) {
|
||||||
} else
|
omap_sram_idle = omap_sram_push(omap1610_idle_loop_suspend,
|
||||||
#endif
|
omap1610_idle_loop_suspend_sz);
|
||||||
if (cpu_is_omap1610() || cpu_is_omap1710()) {
|
omap_sram_suspend = omap_sram_push(omap1610_cpu_suspend,
|
||||||
memcpy((void *)OMAP1610_SRAM_IDLE_SUSPEND,
|
omap1610_cpu_suspend_sz);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
pm_set_ops(&omap_pm_ops);
|
||||||
|
|
||||||
#if defined(DEBUG) && defined(CONFIG_PROC_FS)
|
#if defined(DEBUG) && defined(CONFIG_PROC_FS)
|
||||||
omap_pm_init_proc();
|
omap_pm_init_proc();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* configure LOW_PWR pin */
|
||||||
|
omap_cfg_reg(T20_1610_LOW_PWR);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
__initcall(omap_pm_init);
|
__initcall(omap_pm_init);
|
||||||
|
|
|
@ -66,7 +66,7 @@ ENTRY(omap1510_idle_loop_suspend)
|
||||||
@ get ARM_IDLECT2 into r2
|
@ get ARM_IDLECT2 into r2
|
||||||
ldrh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
|
ldrh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
|
||||||
mov r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 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]
|
strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
|
||||||
|
|
||||||
@ request ARM idle
|
@ request ARM idle
|
||||||
|
@ -76,7 +76,7 @@ ENTRY(omap1510_idle_loop_suspend)
|
||||||
strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
|
strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
|
||||||
|
|
||||||
mov r5, #IDLE_WAIT_CYCLES & 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
|
l_1510: subs r5, r5, #1
|
||||||
bne l_1510
|
bne l_1510
|
||||||
/*
|
/*
|
||||||
|
@ -96,7 +96,7 @@ l_1510: subs r5, r5, #1
|
||||||
strh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
|
strh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
|
||||||
strh r1, [r4, #ARM_IDLECT1_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)
|
ENTRY(omap1510_idle_loop_suspend_sz)
|
||||||
.word . - omap1510_idle_loop_suspend
|
.word . - omap1510_idle_loop_suspend
|
||||||
|
@ -115,8 +115,8 @@ ENTRY(omap1610_idle_loop_suspend)
|
||||||
@ turn off clock domains
|
@ turn off clock domains
|
||||||
@ get ARM_IDLECT2 into r2
|
@ get ARM_IDLECT2 into r2
|
||||||
ldrh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
|
ldrh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
|
||||||
mov r5, #OMAP1610_IDLE_CLOCK_DOMAINS & 0xff
|
mov r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff
|
||||||
orr r5,r5, #OMAP1610_IDLE_CLOCK_DOMAINS & 0xff00
|
orr r5, r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff00
|
||||||
strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
|
strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
|
||||||
|
|
||||||
@ request ARM idle
|
@ request ARM idle
|
||||||
|
@ -126,7 +126,7 @@ ENTRY(omap1610_idle_loop_suspend)
|
||||||
strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
|
strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
|
||||||
|
|
||||||
mov r5, #IDLE_WAIT_CYCLES & 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
|
l_1610: subs r5, r5, #1
|
||||||
bne l_1610
|
bne l_1610
|
||||||
/*
|
/*
|
||||||
|
@ -146,7 +146,7 @@ l_1610: subs r5, r5, #1
|
||||||
strh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
|
strh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
|
||||||
strh r1, [r4, #ARM_IDLECT1_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)
|
ENTRY(omap1610_idle_loop_suspend_sz)
|
||||||
.word . - omap1610_idle_loop_suspend
|
.word . - omap1610_idle_loop_suspend
|
||||||
|
@ -208,7 +208,7 @@ ENTRY(omap1510_cpu_suspend)
|
||||||
|
|
||||||
@ turn off clock domains
|
@ turn off clock domains
|
||||||
mov r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 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]
|
strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
|
||||||
|
|
||||||
@ request ARM idle
|
@ request ARM idle
|
||||||
|
@ -217,7 +217,7 @@ ENTRY(omap1510_cpu_suspend)
|
||||||
strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
|
strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
|
||||||
|
|
||||||
mov r5, #IDLE_WAIT_CYCLES & 0xff
|
mov r5, #IDLE_WAIT_CYCLES & 0xff
|
||||||
orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00
|
orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00
|
||||||
l_1510_2:
|
l_1510_2:
|
||||||
subs r5, r5, #1
|
subs r5, r5, #1
|
||||||
bne l_1510_2
|
bne l_1510_2
|
||||||
|
@ -237,7 +237,7 @@ l_1510_2:
|
||||||
strh r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
|
strh r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
|
||||||
|
|
||||||
@ restore regs and return
|
@ restore regs and return
|
||||||
ldmfd sp!, {r0 - r12, pc}
|
ldmfd sp!, {r0 - r12, pc}
|
||||||
|
|
||||||
ENTRY(omap1510_cpu_suspend_sz)
|
ENTRY(omap1510_cpu_suspend_sz)
|
||||||
.word . - omap1510_cpu_suspend
|
.word . - omap1510_cpu_suspend
|
||||||
|
@ -249,21 +249,26 @@ ENTRY(omap1610_cpu_suspend)
|
||||||
@ save registers on stack
|
@ save registers on stack
|
||||||
stmfd sp!, {r0 - r12, lr}
|
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
|
@ load base address of Traffic Controller
|
||||||
mov r4, #TCMIF_ASM_BASE & 0xff000000
|
mov r6, #TCMIF_ASM_BASE & 0xff000000
|
||||||
orr r4, r4, #TCMIF_ASM_BASE & 0x00ff0000
|
orr r6, r6, #TCMIF_ASM_BASE & 0x00ff0000
|
||||||
orr r4, r4, #TCMIF_ASM_BASE & 0x0000ff00
|
orr r6, r6, #TCMIF_ASM_BASE & 0x0000ff00
|
||||||
|
|
||||||
@ prepare to put SDRAM into self-refresh manually
|
@ prepare to put SDRAM into self-refresh manually
|
||||||
ldr r5, [r4, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
|
ldr r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
|
||||||
orr r5, r5, #SELF_REFRESH_MODE & 0xff000000
|
orr r9, r7, #SELF_REFRESH_MODE & 0xff000000
|
||||||
orr r5, r5, #SELF_REFRESH_MODE & 0x000000ff
|
orr r9, r9, #SELF_REFRESH_MODE & 0x000000ff
|
||||||
str r5, [r4, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
|
str r9, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
|
||||||
|
|
||||||
@ prepare to put EMIFS to Sleep
|
@ prepare to put EMIFS to Sleep
|
||||||
ldr r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
|
ldr r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
|
||||||
orr r5, r5, #IDLE_EMIFS_REQUEST & 0xff
|
orr r9, r8, #IDLE_EMIFS_REQUEST & 0xff
|
||||||
str r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
|
str r9, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
|
||||||
|
|
||||||
@ load base address of ARM_IDLECT1 and ARM_IDLECT2
|
@ load base address of ARM_IDLECT1 and ARM_IDLECT2
|
||||||
mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000
|
mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000
|
||||||
|
@ -271,26 +276,22 @@ ENTRY(omap1610_cpu_suspend)
|
||||||
orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00
|
orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00
|
||||||
|
|
||||||
@ turn off clock domains
|
@ turn off clock domains
|
||||||
mov r5, #OMAP1610_IDLE_CLOCK_DOMAINS & 0xff
|
@ do not disable PERCK (0x04)
|
||||||
orr r5,r5, #OMAP1610_IDLE_CLOCK_DOMAINS & 0xff00
|
mov r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff
|
||||||
strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
|
orr r5, r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff00
|
||||||
|
|
||||||
@ 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
|
|
||||||
strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
|
strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
|
||||||
|
|
||||||
@ request ARM idle
|
@ request ARM idle
|
||||||
mov r3, #OMAP1610_DEEP_SLEEP_REQUEST & 0xff
|
mov r3, #OMAP1610_IDLECT1_SLEEP_VAL & 0xff
|
||||||
orr r3, r3, #OMAP1610_DEEP_SLEEP_REQUEST & 0xff00
|
orr r3, r3, #OMAP1610_IDLECT1_SLEEP_VAL & 0xff00
|
||||||
strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
|
strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
|
||||||
|
|
||||||
mov r5, #IDLE_WAIT_CYCLES & 0xff
|
@ disable instruction cache
|
||||||
orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00
|
mrc p15, 0, r9, c1, c0, 0
|
||||||
l_1610_2:
|
bic r2, r9, #0x1000
|
||||||
subs r5, r5, #1
|
mcr p15, 0, r2, c1, c0, 0
|
||||||
bne l_1610_2
|
nop
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Let's wait for the next wake up event to wake us up. r0 can't be
|
* Let's wait for the next wake up event to wake us up. r0 can't be
|
||||||
* used here because r0 holds ARM_IDLECT1
|
* used here because r0 holds ARM_IDLECT1
|
||||||
|
@ -301,13 +302,21 @@ l_1610_2:
|
||||||
* omap1610_cpu_suspend()'s resume point.
|
* omap1610_cpu_suspend()'s resume point.
|
||||||
*
|
*
|
||||||
* It will just start executing here, so we'll restore stuff from the
|
* 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 r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
|
||||||
strh r0, [r4, #ARM_IDLECT1_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
|
@ restore regs and return
|
||||||
ldmfd sp!, {r0 - r12, pc}
|
ldmfd sp!, {r0 - r12, pc}
|
||||||
|
|
||||||
ENTRY(omap1610_cpu_suspend_sz)
|
ENTRY(omap1610_cpu_suspend_sz)
|
||||||
.word . - omap1610_cpu_suspend
|
.word . - omap1610_cpu_suspend
|
||||||
|
|
58
arch/arm/plat-omap/sram-fn.S
Normal file
58
arch/arm/plat-omap/sram-fn.S
Normal 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
|
116
arch/arm/plat-omap/sram.c
Normal file
116
arch/arm/plat-omap/sram.c
Normal 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);
|
||||||
|
}
|
21
arch/arm/plat-omap/sram.h
Normal file
21
arch/arm/plat-omap/sram.h
Normal 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
|
|
@ -41,6 +41,7 @@
|
||||||
|
|
||||||
/* These routines should handle the standard chip-specific modes
|
/* These routines should handle the standard chip-specific modes
|
||||||
* for usb0/1/2 ports, covering basic mux and transceiver setup.
|
* 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,
|
* Some board-*.c files will need to set up additional mux options,
|
||||||
* like for suspend handling, vbus sensing, GPIOs, and the D+ pullup.
|
* like for suspend handling, vbus sensing, GPIOs, and the D+ pullup.
|
||||||
|
|
|
@ -55,6 +55,10 @@ config GENERIC_BUST_SPINLOCK
|
||||||
config GENERIC_ISA_DMA
|
config GENERIC_ISA_DMA
|
||||||
bool
|
bool
|
||||||
|
|
||||||
|
config ARCH_MAY_HAVE_PC_FDC
|
||||||
|
bool
|
||||||
|
default y
|
||||||
|
|
||||||
source "init/Kconfig"
|
source "init/Kconfig"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -17,10 +17,6 @@ ifeq ($(CONFIG_FRAME_POINTER),y)
|
||||||
CFLAGS +=-fno-omit-frame-pointer -mno-sched-prolog
|
CFLAGS +=-fno-omit-frame-pointer -mno-sched-prolog
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_DEBUG_INFO),y)
|
|
||||||
CFLAGS +=-g
|
|
||||||
endif
|
|
||||||
|
|
||||||
CFLAGS_BOOT :=-mapcs-26 -mcpu=arm3 -msoft-float -Uarm
|
CFLAGS_BOOT :=-mapcs-26 -mcpu=arm3 -msoft-float -Uarm
|
||||||
CFLAGS +=-mapcs-26 -mcpu=arm3 -msoft-float -Uarm
|
CFLAGS +=-mapcs-26 -mcpu=arm3 -msoft-float -Uarm
|
||||||
AFLAGS +=-mapcs-26 -mcpu=arm3 -msoft-float
|
AFLAGS +=-mapcs-26 -mcpu=arm3 -msoft-float
|
||||||
|
|
|
@ -114,7 +114,7 @@ static unsigned long next_rtc_update;
|
||||||
*/
|
*/
|
||||||
static inline void do_set_rtc(void)
|
static inline void do_set_rtc(void)
|
||||||
{
|
{
|
||||||
if (time_status & STA_UNSYNC || set_rtc == NULL)
|
if (!ntp_synced() || set_rtc == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
//FIXME - timespec.tv_sec is a time_t not unsigned long
|
//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_sec = tv->tv_sec;
|
||||||
xtime.tv_nsec = tv->tv_nsec;
|
xtime.tv_nsec = tv->tv_nsec;
|
||||||
time_adjust = 0; /* stop active adjtime() */
|
ntp_clear();
|
||||||
time_status |= STA_UNSYNC;
|
|
||||||
time_maxerror = NTP_PHASE_LIMIT;
|
|
||||||
time_esterror = NTP_PHASE_LIMIT;
|
|
||||||
write_sequnlock_irq(&xtime_lock);
|
write_sequnlock_irq(&xtime_lock);
|
||||||
clock_was_set();
|
clock_was_set();
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue