forked from Minki/linux
Merge /spare/repo/linux-2.6/
This commit is contained in:
commit
a2e30e529a
10
CREDITS
10
CREDITS
@ -1624,10 +1624,10 @@ E: ajoshi@shell.unixbox.com
|
||||
D: fbdev hacking
|
||||
|
||||
N: Jesper Juhl
|
||||
E: juhl-lkml@dif.dk
|
||||
D: Various small janitor fixes, cleanups etc.
|
||||
E: jesper.juhl@gmail.com
|
||||
D: Various fixes, cleanups and minor features.
|
||||
S: Lemnosvej 1, 3.tv
|
||||
S: 2300 Copenhagen S
|
||||
S: 2300 Copenhagen S.
|
||||
S: Denmark
|
||||
|
||||
N: Jozsef Kadlecsik
|
||||
@ -2380,8 +2380,8 @@ E: tmolina@cablespeed.com
|
||||
D: bug fixes, documentation, minor hackery
|
||||
|
||||
N: James Morris
|
||||
E: jmorris@redhat.com
|
||||
W: http://www.intercode.com.au/jmorris/
|
||||
E: jmorris@namei.org
|
||||
W: http://namei.org/
|
||||
D: Netfilter, Linux Security Modules (LSM), SELinux, IPSec,
|
||||
D: Crypto API, general networking, miscellaneous.
|
||||
S: PO Box 707
|
||||
|
@ -65,6 +65,7 @@ o isdn4k-utils 3.1pre1 # isdnctrl 2>&1|grep version
|
||||
o nfs-utils 1.0.5 # showmount --version
|
||||
o procps 3.2.0 # ps --version
|
||||
o oprofile 0.9 # oprofiled --version
|
||||
o udev 058 # udevinfo -V
|
||||
|
||||
Kernel compilation
|
||||
==================
|
||||
|
@ -149,6 +149,11 @@ USB, framebuffer devices, the VFS, the SCSI subsystem, etc. See the
|
||||
MAINTAINERS file for a mailing list that relates specifically to
|
||||
your change.
|
||||
|
||||
If changes affect userland-kernel interfaces, please send
|
||||
the MAN-PAGES maintainer (as listed in the MAINTAINERS file)
|
||||
a man-pages patch, or at least a notification of the change,
|
||||
so that some information makes its way into the manual pages.
|
||||
|
||||
Even if the maintainer did not respond in step #4, make sure to ALWAYS
|
||||
copy the maintainer when you change their code.
|
||||
|
||||
|
@ -33,3 +33,6 @@ The result of the execution of this aml method is
|
||||
attached to /proc/acpi/hotkey/poll_method, which is dnyamically
|
||||
created. Please use command "cat /proc/acpi/hotkey/polling_method"
|
||||
to retrieve it.
|
||||
|
||||
Note: Use cmdline "acpi_generic_hotkey" to over-ride
|
||||
loading any platform specific drivers.
|
||||
|
93
Documentation/arm/Samsung-S3C24XX/USB-Host.txt
Normal file
93
Documentation/arm/Samsung-S3C24XX/USB-Host.txt
Normal file
@ -0,0 +1,93 @@
|
||||
S3C24XX USB Host support
|
||||
========================
|
||||
|
||||
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
This document details the S3C2410/S3C2440 in-built OHCI USB host support.
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
Enable at least the following kernel options:
|
||||
|
||||
menuconfig:
|
||||
|
||||
Device Drivers --->
|
||||
USB support --->
|
||||
<*> Support for Host-side USB
|
||||
<*> OHCI HCD support
|
||||
|
||||
|
||||
.config:
|
||||
CONFIG_USB
|
||||
CONFIG_USB_OHCI_HCD
|
||||
|
||||
|
||||
Once these options are configured, the standard set of USB device
|
||||
drivers can be configured and used.
|
||||
|
||||
|
||||
Board Support
|
||||
-------------
|
||||
|
||||
The driver attaches to a platform device, which will need to be
|
||||
added by the board specific support file in linux/arch/arm/mach-s3c2410,
|
||||
such as mach-bast.c or mach-smdk2410.c
|
||||
|
||||
The platform device's platform_data field is only needed if the
|
||||
board implements extra power control or over-current monitoring.
|
||||
|
||||
The OHCI driver does not ensure the state of the S3C2410's MISCCTRL
|
||||
register, so if both ports are to be used for the host, then it is
|
||||
the board support file's responsibility to ensure that the second
|
||||
port is configured to be connected to the OHCI core.
|
||||
|
||||
|
||||
Platform Data
|
||||
-------------
|
||||
|
||||
See linux/include/asm-arm/arch-s3c2410/usb-control.h for the
|
||||
descriptions of the platform device data. An implementation
|
||||
can be found in linux/arch/arm/mach-s3c2410/usb-simtec.c .
|
||||
|
||||
The `struct s3c2410_hcd_info` contains a pair of functions
|
||||
that get called to enable over-current detection, and to
|
||||
control the port power status.
|
||||
|
||||
The ports are numbered 0 and 1.
|
||||
|
||||
power_control:
|
||||
|
||||
Called to enable or disable the power on the port.
|
||||
|
||||
enable_oc:
|
||||
|
||||
Called to enable or disable the over-current monitoring.
|
||||
This should claim or release the resources being used to
|
||||
check the power condition on the port, such as an IRQ.
|
||||
|
||||
report_oc:
|
||||
|
||||
The OHCI driver fills this field in for the over-current code
|
||||
to call when there is a change to the over-current state on
|
||||
an port. The ports argument is a bitmask of 1 bit per port,
|
||||
with bit X being 1 for an over-current on port X.
|
||||
|
||||
The function s3c2410_usb_report_oc() has been provided to
|
||||
ensure this is called correctly.
|
||||
|
||||
port[x]:
|
||||
|
||||
This is struct describes each port, 0 or 1. The platform driver
|
||||
should set the flags field of each port to S3C_HCDFLG_USED if
|
||||
the port is enabled.
|
||||
|
||||
|
||||
|
||||
Document Author
|
||||
---------------
|
||||
|
||||
Ben Dooks, (c) 2005 Simtec Electronics
|
@ -104,6 +104,7 @@ logo_*.c
|
||||
logo_*_clut224.c
|
||||
logo_*_mono.c
|
||||
lxdialog
|
||||
mach-types
|
||||
mach-types.h
|
||||
make_times_h
|
||||
map
|
||||
|
@ -144,7 +144,21 @@ vgapal Use the standard vga registers for palette changes.
|
||||
This is the default.
|
||||
pmipal Use the protected mode interface for palette changes.
|
||||
|
||||
mtrr setup memory type range registers for the vesafb framebuffer.
|
||||
mtrr:n setup memory type range registers for the vesafb framebuffer
|
||||
where n:
|
||||
0 - disabled (equivalent to nomtrr)
|
||||
1 - uncachable
|
||||
2 - write-back
|
||||
3 - write-combining (default)
|
||||
4 - write-through
|
||||
|
||||
If you see the following in dmesg, choose the type that matches the
|
||||
old one. In this example, use "mtrr:2".
|
||||
...
|
||||
mtrr: type mismatch for e0000000,8000000 old: write-back new: write-combining
|
||||
...
|
||||
|
||||
nomtrr disable mtrr
|
||||
|
||||
vremap:n
|
||||
remap 'n' MiB of video RAM. If 0 or not specified, remap memory
|
||||
|
114
Documentation/infiniband/core_locking.txt
Normal file
114
Documentation/infiniband/core_locking.txt
Normal file
@ -0,0 +1,114 @@
|
||||
INFINIBAND MIDLAYER LOCKING
|
||||
|
||||
This guide is an attempt to make explicit the locking assumptions
|
||||
made by the InfiniBand midlayer. It describes the requirements on
|
||||
both low-level drivers that sit below the midlayer and upper level
|
||||
protocols that use the midlayer.
|
||||
|
||||
Sleeping and interrupt context
|
||||
|
||||
With the following exceptions, a low-level driver implementation of
|
||||
all of the methods in struct ib_device may sleep. The exceptions
|
||||
are any methods from the list:
|
||||
|
||||
create_ah
|
||||
modify_ah
|
||||
query_ah
|
||||
destroy_ah
|
||||
bind_mw
|
||||
post_send
|
||||
post_recv
|
||||
poll_cq
|
||||
req_notify_cq
|
||||
map_phys_fmr
|
||||
|
||||
which may not sleep and must be callable from any context.
|
||||
|
||||
The corresponding functions exported to upper level protocol
|
||||
consumers:
|
||||
|
||||
ib_create_ah
|
||||
ib_modify_ah
|
||||
ib_query_ah
|
||||
ib_destroy_ah
|
||||
ib_bind_mw
|
||||
ib_post_send
|
||||
ib_post_recv
|
||||
ib_req_notify_cq
|
||||
ib_map_phys_fmr
|
||||
|
||||
are therefore safe to call from any context.
|
||||
|
||||
In addition, the function
|
||||
|
||||
ib_dispatch_event
|
||||
|
||||
used by low-level drivers to dispatch asynchronous events through
|
||||
the midlayer is also safe to call from any context.
|
||||
|
||||
Reentrancy
|
||||
|
||||
All of the methods in struct ib_device exported by a low-level
|
||||
driver must be fully reentrant. The low-level driver is required to
|
||||
perform all synchronization necessary to maintain consistency, even
|
||||
if multiple function calls using the same object are run
|
||||
simultaneously.
|
||||
|
||||
The IB midlayer does not perform any serialization of function calls.
|
||||
|
||||
Because low-level drivers are reentrant, upper level protocol
|
||||
consumers are not required to perform any serialization. However,
|
||||
some serialization may be required to get sensible results. For
|
||||
example, a consumer may safely call ib_poll_cq() on multiple CPUs
|
||||
simultaneously. However, the ordering of the work completion
|
||||
information between different calls of ib_poll_cq() is not defined.
|
||||
|
||||
Callbacks
|
||||
|
||||
A low-level driver must not perform a callback directly from the
|
||||
same callchain as an ib_device method call. For example, it is not
|
||||
allowed for a low-level driver to call a consumer's completion event
|
||||
handler directly from its post_send method. Instead, the low-level
|
||||
driver should defer this callback by, for example, scheduling a
|
||||
tasklet to perform the callback.
|
||||
|
||||
The low-level driver is responsible for ensuring that multiple
|
||||
completion event handlers for the same CQ are not called
|
||||
simultaneously. The driver must guarantee that only one CQ event
|
||||
handler for a given CQ is running at a time. In other words, the
|
||||
following situation is not allowed:
|
||||
|
||||
CPU1 CPU2
|
||||
|
||||
low-level driver ->
|
||||
consumer CQ event callback:
|
||||
/* ... */
|
||||
ib_req_notify_cq(cq, ...);
|
||||
low-level driver ->
|
||||
/* ... */ consumer CQ event callback:
|
||||
/* ... */
|
||||
return from CQ event handler
|
||||
|
||||
The context in which completion event and asynchronous event
|
||||
callbacks run is not defined. Depending on the low-level driver, it
|
||||
may be process context, softirq context, or interrupt context.
|
||||
Upper level protocol consumers may not sleep in a callback.
|
||||
|
||||
Hot-plug
|
||||
|
||||
A low-level driver announces that a device is ready for use by
|
||||
consumers when it calls ib_register_device(), all initialization
|
||||
must be complete before this call. The device must remain usable
|
||||
until the driver's call to ib_unregister_device() has returned.
|
||||
|
||||
A low-level driver must call ib_register_device() and
|
||||
ib_unregister_device() from process context. It must not hold any
|
||||
semaphores that could cause deadlock if a consumer calls back into
|
||||
the driver across these calls.
|
||||
|
||||
An upper level protocol consumer may begin using an IB device as
|
||||
soon as the add method of its struct ib_client is called for that
|
||||
device. A consumer must finish all cleanup and free all resources
|
||||
relating to a device before returning from the remove method.
|
||||
|
||||
A consumer is permitted to sleep in its add and remove methods.
|
@ -28,13 +28,37 @@ Creating MAD agents
|
||||
|
||||
Receiving MADs
|
||||
|
||||
MADs are received using read(). The buffer passed to read() must be
|
||||
large enough to hold at least one struct ib_user_mad. For example:
|
||||
MADs are received using read(). The receive side now supports
|
||||
RMPP. The buffer passed to read() must be at least one
|
||||
struct ib_user_mad + 256 bytes. For example:
|
||||
|
||||
struct ib_user_mad mad;
|
||||
ret = read(fd, &mad, sizeof mad);
|
||||
if (ret != sizeof mad)
|
||||
If the buffer passed is not large enough to hold the received
|
||||
MAD (RMPP), the errno is set to ENOSPC and the length of the
|
||||
buffer needed is set in mad.length.
|
||||
|
||||
Example for normal MAD (non RMPP) reads:
|
||||
struct ib_user_mad *mad;
|
||||
mad = malloc(sizeof *mad + 256);
|
||||
ret = read(fd, mad, sizeof *mad + 256);
|
||||
if (ret != sizeof mad + 256) {
|
||||
perror("read");
|
||||
free(mad);
|
||||
}
|
||||
|
||||
Example for RMPP reads:
|
||||
struct ib_user_mad *mad;
|
||||
mad = malloc(sizeof *mad + 256);
|
||||
ret = read(fd, mad, sizeof *mad + 256);
|
||||
if (ret == -ENOSPC)) {
|
||||
length = mad.length;
|
||||
free(mad);
|
||||
mad = malloc(sizeof *mad + length);
|
||||
ret = read(fd, mad, sizeof *mad + length);
|
||||
}
|
||||
if (ret < 0) {
|
||||
perror("read");
|
||||
free(mad);
|
||||
}
|
||||
|
||||
In addition to the actual MAD contents, the other struct ib_user_mad
|
||||
fields will be filled in with information on the received MAD. For
|
||||
@ -50,18 +74,21 @@ Sending MADs
|
||||
|
||||
MADs are sent using write(). The agent ID for sending should be
|
||||
filled into the id field of the MAD, the destination LID should be
|
||||
filled into the lid field, and so on. For example:
|
||||
filled into the lid field, and so on. The send side does support
|
||||
RMPP so arbitrary length MAD can be sent. For example:
|
||||
|
||||
struct ib_user_mad mad;
|
||||
struct ib_user_mad *mad;
|
||||
|
||||
/* fill in mad.data */
|
||||
mad = malloc(sizeof *mad + mad_length);
|
||||
|
||||
mad.id = my_agent; /* req.id from agent registration */
|
||||
mad.lid = my_dest; /* in network byte order... */
|
||||
/* fill in mad->data */
|
||||
|
||||
mad->hdr.id = my_agent; /* req.id from agent registration */
|
||||
mad->hdr.lid = my_dest; /* in network byte order... */
|
||||
/* etc. */
|
||||
|
||||
ret = write(fd, &mad, sizeof mad);
|
||||
if (ret != sizeof mad)
|
||||
ret = write(fd, &mad, sizeof *mad + mad_length);
|
||||
if (ret != sizeof *mad + mad_length)
|
||||
perror("write");
|
||||
|
||||
Setting IsSM Capability Bit
|
||||
|
@ -159,6 +159,11 @@ running once the system is up.
|
||||
|
||||
acpi_fake_ecdt [HW,ACPI] Workaround failure due to BIOS lacking ECDT
|
||||
|
||||
acpi_generic_hotkey [HW,ACPI]
|
||||
Allow consolidated generic hotkey driver to
|
||||
over-ride platform specific driver.
|
||||
See also Documentation/acpi-hotkey.txt.
|
||||
|
||||
ad1816= [HW,OSS]
|
||||
Format: <io>,<irq>,<dma>,<dma2>
|
||||
See also Documentation/sound/oss/AD1816.
|
||||
|
588
Documentation/kprobes.txt
Normal file
588
Documentation/kprobes.txt
Normal file
@ -0,0 +1,588 @@
|
||||
Title : Kernel Probes (Kprobes)
|
||||
Authors : Jim Keniston <jkenisto@us.ibm.com>
|
||||
: Prasanna S Panchamukhi <prasanna@in.ibm.com>
|
||||
|
||||
CONTENTS
|
||||
|
||||
1. Concepts: Kprobes, Jprobes, Return Probes
|
||||
2. Architectures Supported
|
||||
3. Configuring Kprobes
|
||||
4. API Reference
|
||||
5. Kprobes Features and Limitations
|
||||
6. Probe Overhead
|
||||
7. TODO
|
||||
8. Kprobes Example
|
||||
9. Jprobes Example
|
||||
10. Kretprobes Example
|
||||
|
||||
1. Concepts: Kprobes, Jprobes, Return Probes
|
||||
|
||||
Kprobes enables you to dynamically break into any kernel routine and
|
||||
collect debugging and performance information non-disruptively. You
|
||||
can trap at almost any kernel code address, specifying a handler
|
||||
routine to be invoked when the breakpoint is hit.
|
||||
|
||||
There are currently three types of probes: kprobes, jprobes, and
|
||||
kretprobes (also called return probes). A kprobe can be inserted
|
||||
on virtually any instruction in the kernel. A jprobe is inserted at
|
||||
the entry to a kernel function, and provides convenient access to the
|
||||
function's arguments. A return probe fires when a specified function
|
||||
returns.
|
||||
|
||||
In the typical case, Kprobes-based instrumentation is packaged as
|
||||
a kernel module. The module's init function installs ("registers")
|
||||
one or more probes, and the exit function unregisters them. A
|
||||
registration function such as register_kprobe() specifies where
|
||||
the probe is to be inserted and what handler is to be called when
|
||||
the probe is hit.
|
||||
|
||||
The next three subsections explain how the different types of
|
||||
probes work. They explain certain things that you'll need to
|
||||
know in order to make the best use of Kprobes -- e.g., the
|
||||
difference between a pre_handler and a post_handler, and how
|
||||
to use the maxactive and nmissed fields of a kretprobe. But
|
||||
if you're in a hurry to start using Kprobes, you can skip ahead
|
||||
to section 2.
|
||||
|
||||
1.1 How Does a Kprobe Work?
|
||||
|
||||
When a kprobe is registered, Kprobes makes a copy of the probed
|
||||
instruction and replaces the first byte(s) of the probed instruction
|
||||
with a breakpoint instruction (e.g., int3 on i386 and x86_64).
|
||||
|
||||
When a CPU hits the breakpoint instruction, a trap occurs, the CPU's
|
||||
registers are saved, and control passes to Kprobes via the
|
||||
notifier_call_chain mechanism. Kprobes executes the "pre_handler"
|
||||
associated with the kprobe, passing the handler the addresses of the
|
||||
kprobe struct and the saved registers.
|
||||
|
||||
Next, Kprobes single-steps its copy of the probed instruction.
|
||||
(It would be simpler to single-step the actual instruction in place,
|
||||
but then Kprobes would have to temporarily remove the breakpoint
|
||||
instruction. This would open a small time window when another CPU
|
||||
could sail right past the probepoint.)
|
||||
|
||||
After the instruction is single-stepped, Kprobes executes the
|
||||
"post_handler," if any, that is associated with the kprobe.
|
||||
Execution then continues with the instruction following the probepoint.
|
||||
|
||||
1.2 How Does a Jprobe Work?
|
||||
|
||||
A jprobe is implemented using a kprobe that is placed on a function's
|
||||
entry point. It employs a simple mirroring principle to allow
|
||||
seamless access to the probed function's arguments. The jprobe
|
||||
handler routine should have the same signature (arg list and return
|
||||
type) as the function being probed, and must always end by calling
|
||||
the Kprobes function jprobe_return().
|
||||
|
||||
Here's how it works. When the probe is hit, Kprobes makes a copy of
|
||||
the saved registers and a generous portion of the stack (see below).
|
||||
Kprobes then points the saved instruction pointer at the jprobe's
|
||||
handler routine, and returns from the trap. As a result, control
|
||||
passes to the handler, which is presented with the same register and
|
||||
stack contents as the probed function. When it is done, the handler
|
||||
calls jprobe_return(), which traps again to restore the original stack
|
||||
contents and processor state and switch to the probed function.
|
||||
|
||||
By convention, the callee owns its arguments, so gcc may produce code
|
||||
that unexpectedly modifies that portion of the stack. This is why
|
||||
Kprobes saves a copy of the stack and restores it after the jprobe
|
||||
handler has run. Up to MAX_STACK_SIZE bytes are copied -- e.g.,
|
||||
64 bytes on i386.
|
||||
|
||||
Note that the probed function's args may be passed on the stack
|
||||
or in registers (e.g., for x86_64 or for an i386 fastcall function).
|
||||
The jprobe will work in either case, so long as the handler's
|
||||
prototype matches that of the probed function.
|
||||
|
||||
1.3 How Does a Return Probe Work?
|
||||
|
||||
When you call register_kretprobe(), Kprobes establishes a kprobe at
|
||||
the entry to the function. When the probed function is called and this
|
||||
probe is hit, Kprobes saves a copy of the return address, and replaces
|
||||
the return address with the address of a "trampoline." The trampoline
|
||||
is an arbitrary piece of code -- typically just a nop instruction.
|
||||
At boot time, Kprobes registers a kprobe at the trampoline.
|
||||
|
||||
When the probed function executes its return instruction, control
|
||||
passes to the trampoline and that probe is hit. Kprobes' trampoline
|
||||
handler calls the user-specified handler associated with the kretprobe,
|
||||
then sets the saved instruction pointer to the saved return address,
|
||||
and that's where execution resumes upon return from the trap.
|
||||
|
||||
While the probed function is executing, its return address is
|
||||
stored in an object of type kretprobe_instance. Before calling
|
||||
register_kretprobe(), the user sets the maxactive field of the
|
||||
kretprobe struct to specify how many instances of the specified
|
||||
function can be probed simultaneously. register_kretprobe()
|
||||
pre-allocates the indicated number of kretprobe_instance objects.
|
||||
|
||||
For example, if the function is non-recursive and is called with a
|
||||
spinlock held, maxactive = 1 should be enough. If the function is
|
||||
non-recursive and can never relinquish the CPU (e.g., via a semaphore
|
||||
or preemption), NR_CPUS should be enough. If maxactive <= 0, it is
|
||||
set to a default value. If CONFIG_PREEMPT is enabled, the default
|
||||
is max(10, 2*NR_CPUS). Otherwise, the default is NR_CPUS.
|
||||
|
||||
It's not a disaster if you set maxactive too low; you'll just miss
|
||||
some probes. In the kretprobe struct, the nmissed field is set to
|
||||
zero when the return probe is registered, and is incremented every
|
||||
time the probed function is entered but there is no kretprobe_instance
|
||||
object available for establishing the return probe.
|
||||
|
||||
2. Architectures Supported
|
||||
|
||||
Kprobes, jprobes, and return probes are implemented on the following
|
||||
architectures:
|
||||
|
||||
- i386
|
||||
- x86_64 (AMD-64, E64MT)
|
||||
- ppc64
|
||||
- ia64 (Support for probes on certain instruction types is still in progress.)
|
||||
- sparc64 (Return probes not yet implemented.)
|
||||
|
||||
3. Configuring Kprobes
|
||||
|
||||
When configuring the kernel using make menuconfig/xconfig/oldconfig,
|
||||
ensure that CONFIG_KPROBES is set to "y". Under "Kernel hacking",
|
||||
look for "Kprobes". You may have to enable "Kernel debugging"
|
||||
(CONFIG_DEBUG_KERNEL) before you can enable Kprobes.
|
||||
|
||||
You may also want to ensure that CONFIG_KALLSYMS and perhaps even
|
||||
CONFIG_KALLSYMS_ALL are set to "y", since kallsyms_lookup_name()
|
||||
is a handy, version-independent way to find a function's address.
|
||||
|
||||
If you need to insert a probe in the middle of a function, you may find
|
||||
it useful to "Compile the kernel with debug info" (CONFIG_DEBUG_INFO),
|
||||
so you can use "objdump -d -l vmlinux" to see the source-to-object
|
||||
code mapping.
|
||||
|
||||
4. API Reference
|
||||
|
||||
The Kprobes API includes a "register" function and an "unregister"
|
||||
function for each type of probe. Here are terse, mini-man-page
|
||||
specifications for these functions and the associated probe handlers
|
||||
that you'll write. See the latter half of this document for examples.
|
||||
|
||||
4.1 register_kprobe
|
||||
|
||||
#include <linux/kprobes.h>
|
||||
int register_kprobe(struct kprobe *kp);
|
||||
|
||||
Sets a breakpoint at the address kp->addr. When the breakpoint is
|
||||
hit, Kprobes calls kp->pre_handler. After the probed instruction
|
||||
is single-stepped, Kprobe calls kp->post_handler. If a fault
|
||||
occurs during execution of kp->pre_handler or kp->post_handler,
|
||||
or during single-stepping of the probed instruction, Kprobes calls
|
||||
kp->fault_handler. Any or all handlers can be NULL.
|
||||
|
||||
register_kprobe() returns 0 on success, or a negative errno otherwise.
|
||||
|
||||
User's pre-handler (kp->pre_handler):
|
||||
#include <linux/kprobes.h>
|
||||
#include <linux/ptrace.h>
|
||||
int pre_handler(struct kprobe *p, struct pt_regs *regs);
|
||||
|
||||
Called with p pointing to the kprobe associated with the breakpoint,
|
||||
and regs pointing to the struct containing the registers saved when
|
||||
the breakpoint was hit. Return 0 here unless you're a Kprobes geek.
|
||||
|
||||
User's post-handler (kp->post_handler):
|
||||
#include <linux/kprobes.h>
|
||||
#include <linux/ptrace.h>
|
||||
void post_handler(struct kprobe *p, struct pt_regs *regs,
|
||||
unsigned long flags);
|
||||
|
||||
p and regs are as described for the pre_handler. flags always seems
|
||||
to be zero.
|
||||
|
||||
User's fault-handler (kp->fault_handler):
|
||||
#include <linux/kprobes.h>
|
||||
#include <linux/ptrace.h>
|
||||
int fault_handler(struct kprobe *p, struct pt_regs *regs, int trapnr);
|
||||
|
||||
p and regs are as described for the pre_handler. trapnr is the
|
||||
architecture-specific trap number associated with the fault (e.g.,
|
||||
on i386, 13 for a general protection fault or 14 for a page fault).
|
||||
Returns 1 if it successfully handled the exception.
|
||||
|
||||
4.2 register_jprobe
|
||||
|
||||
#include <linux/kprobes.h>
|
||||
int register_jprobe(struct jprobe *jp)
|
||||
|
||||
Sets a breakpoint at the address jp->kp.addr, which must be the address
|
||||
of the first instruction of a function. When the breakpoint is hit,
|
||||
Kprobes runs the handler whose address is jp->entry.
|
||||
|
||||
The handler should have the same arg list and return type as the probed
|
||||
function; and just before it returns, it must call jprobe_return().
|
||||
(The handler never actually returns, since jprobe_return() returns
|
||||
control to Kprobes.) If the probed function is declared asmlinkage,
|
||||
fastcall, or anything else that affects how args are passed, the
|
||||
handler's declaration must match.
|
||||
|
||||
register_jprobe() returns 0 on success, or a negative errno otherwise.
|
||||
|
||||
4.3 register_kretprobe
|
||||
|
||||
#include <linux/kprobes.h>
|
||||
int register_kretprobe(struct kretprobe *rp);
|
||||
|
||||
Establishes a return probe for the function whose address is
|
||||
rp->kp.addr. When that function returns, Kprobes calls rp->handler.
|
||||
You must set rp->maxactive appropriately before you call
|
||||
register_kretprobe(); see "How Does a Return Probe Work?" for details.
|
||||
|
||||
register_kretprobe() returns 0 on success, or a negative errno
|
||||
otherwise.
|
||||
|
||||
User's return-probe handler (rp->handler):
|
||||
#include <linux/kprobes.h>
|
||||
#include <linux/ptrace.h>
|
||||
int kretprobe_handler(struct kretprobe_instance *ri, struct pt_regs *regs);
|
||||
|
||||
regs is as described for kprobe.pre_handler. ri points to the
|
||||
kretprobe_instance object, of which the following fields may be
|
||||
of interest:
|
||||
- ret_addr: the return address
|
||||
- rp: points to the corresponding kretprobe object
|
||||
- task: points to the corresponding task struct
|
||||
The handler's return value is currently ignored.
|
||||
|
||||
4.4 unregister_*probe
|
||||
|
||||
#include <linux/kprobes.h>
|
||||
void unregister_kprobe(struct kprobe *kp);
|
||||
void unregister_jprobe(struct jprobe *jp);
|
||||
void unregister_kretprobe(struct kretprobe *rp);
|
||||
|
||||
Removes the specified probe. The unregister function can be called
|
||||
at any time after the probe has been registered.
|
||||
|
||||
5. Kprobes Features and Limitations
|
||||
|
||||
As of Linux v2.6.12, Kprobes allows multiple probes at the same
|
||||
address. Currently, however, there cannot be multiple jprobes on
|
||||
the same function at the same time.
|
||||
|
||||
In general, you can install a probe anywhere in the kernel.
|
||||
In particular, you can probe interrupt handlers. Known exceptions
|
||||
are discussed in this section.
|
||||
|
||||
For obvious reasons, it's a bad idea to install a probe in
|
||||
the code that implements Kprobes (mostly kernel/kprobes.c and
|
||||
arch/*/kernel/kprobes.c). A patch in the v2.6.13 timeframe instructs
|
||||
Kprobes to reject such requests.
|
||||
|
||||
If you install a probe in an inline-able function, Kprobes makes
|
||||
no attempt to chase down all inline instances of the function and
|
||||
install probes there. gcc may inline a function without being asked,
|
||||
so keep this in mind if you're not seeing the probe hits you expect.
|
||||
|
||||
A probe handler can modify the environment of the probed function
|
||||
-- e.g., by modifying kernel data structures, or by modifying the
|
||||
contents of the pt_regs struct (which are restored to the registers
|
||||
upon return from the breakpoint). So Kprobes can be used, for example,
|
||||
to install a bug fix or to inject faults for testing. Kprobes, of
|
||||
course, has no way to distinguish the deliberately injected faults
|
||||
from the accidental ones. Don't drink and probe.
|
||||
|
||||
Kprobes makes no attempt to prevent probe handlers from stepping on
|
||||
each other -- e.g., probing printk() and then calling printk() from a
|
||||
probe handler. As of Linux v2.6.12, if a probe handler hits a probe,
|
||||
that second probe's handlers won't be run in that instance.
|
||||
|
||||
In Linux v2.6.12 and previous versions, Kprobes' data structures are
|
||||
protected by a single lock that is held during probe registration and
|
||||
unregistration and while handlers are run. Thus, no two handlers
|
||||
can run simultaneously. To improve scalability on SMP systems,
|
||||
this restriction will probably be removed soon, in which case
|
||||
multiple handlers (or multiple instances of the same handler) may
|
||||
run concurrently on different CPUs. Code your handlers accordingly.
|
||||
|
||||
Kprobes does not use semaphores or allocate memory except during
|
||||
registration and unregistration.
|
||||
|
||||
Probe handlers are run with preemption disabled. Depending on the
|
||||
architecture, handlers may also run with interrupts disabled. In any
|
||||
case, your handler should not yield the CPU (e.g., by attempting to
|
||||
acquire a semaphore).
|
||||
|
||||
Since a return probe is implemented by replacing the return
|
||||
address with the trampoline's address, stack backtraces and calls
|
||||
to __builtin_return_address() will typically yield the trampoline's
|
||||
address instead of the real return address for kretprobed functions.
|
||||
(As far as we can tell, __builtin_return_address() is used only
|
||||
for instrumentation and error reporting.)
|
||||
|
||||
If the number of times a function is called does not match the
|
||||
number of times it returns, registering a return probe on that
|
||||
function may produce undesirable results. We have the do_exit()
|
||||
and do_execve() cases covered. do_fork() is not an issue. We're
|
||||
unaware of other specific cases where this could be a problem.
|
||||
|
||||
6. Probe Overhead
|
||||
|
||||
On a typical CPU in use in 2005, a kprobe hit takes 0.5 to 1.0
|
||||
microseconds to process. Specifically, a benchmark that hits the same
|
||||
probepoint repeatedly, firing a simple handler each time, reports 1-2
|
||||
million hits per second, depending on the architecture. A jprobe or
|
||||
return-probe hit typically takes 50-75% longer than a kprobe hit.
|
||||
When you have a return probe set on a function, adding a kprobe at
|
||||
the entry to that function adds essentially no overhead.
|
||||
|
||||
Here are sample overhead figures (in usec) for different architectures.
|
||||
k = kprobe; j = jprobe; r = return probe; kr = kprobe + return probe
|
||||
on same function; jr = jprobe + return probe on same function
|
||||
|
||||
i386: Intel Pentium M, 1495 MHz, 2957.31 bogomips
|
||||
k = 0.57 usec; j = 1.00; r = 0.92; kr = 0.99; jr = 1.40
|
||||
|
||||
x86_64: AMD Opteron 246, 1994 MHz, 3971.48 bogomips
|
||||
k = 0.49 usec; j = 0.76; r = 0.80; kr = 0.82; jr = 1.07
|
||||
|
||||
ppc64: POWER5 (gr), 1656 MHz (SMT disabled, 1 virtual CPU per physical CPU)
|
||||
k = 0.77 usec; j = 1.31; r = 1.26; kr = 1.45; jr = 1.99
|
||||
|
||||
7. TODO
|
||||
|
||||
a. SystemTap (http://sourceware.org/systemtap): Work in progress
|
||||
to provide a simplified programming interface for probe-based
|
||||
instrumentation.
|
||||
b. Improved SMP scalability: Currently, work is in progress to handle
|
||||
multiple kprobes in parallel.
|
||||
c. Kernel return probes for sparc64.
|
||||
d. Support for other architectures.
|
||||
e. User-space probes.
|
||||
|
||||
8. Kprobes Example
|
||||
|
||||
Here's a sample kernel module showing the use of kprobes to dump a
|
||||
stack trace and selected i386 registers when do_fork() is called.
|
||||
----- cut here -----
|
||||
/*kprobe_example.c*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kprobes.h>
|
||||
#include <linux/kallsyms.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
/*For each probe you need to allocate a kprobe structure*/
|
||||
static struct kprobe kp;
|
||||
|
||||
/*kprobe pre_handler: called just before the probed instruction is executed*/
|
||||
int handler_pre(struct kprobe *p, struct pt_regs *regs)
|
||||
{
|
||||
printk("pre_handler: p->addr=0x%p, eip=%lx, eflags=0x%lx\n",
|
||||
p->addr, regs->eip, regs->eflags);
|
||||
dump_stack();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*kprobe post_handler: called after the probed instruction is executed*/
|
||||
void handler_post(struct kprobe *p, struct pt_regs *regs, unsigned long flags)
|
||||
{
|
||||
printk("post_handler: p->addr=0x%p, eflags=0x%lx\n",
|
||||
p->addr, regs->eflags);
|
||||
}
|
||||
|
||||
/* fault_handler: this is called if an exception is generated for any
|
||||
* instruction within the pre- or post-handler, or when Kprobes
|
||||
* single-steps the probed instruction.
|
||||
*/
|
||||
int handler_fault(struct kprobe *p, struct pt_regs *regs, int trapnr)
|
||||
{
|
||||
printk("fault_handler: p->addr=0x%p, trap #%dn",
|
||||
p->addr, trapnr);
|
||||
/* Return 0 because we don't handle the fault. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int init_module(void)
|
||||
{
|
||||
int ret;
|
||||
kp.pre_handler = handler_pre;
|
||||
kp.post_handler = handler_post;
|
||||
kp.fault_handler = handler_fault;
|
||||
kp.addr = (kprobe_opcode_t*) kallsyms_lookup_name("do_fork");
|
||||
/* register the kprobe now */
|
||||
if (!kp.addr) {
|
||||
printk("Couldn't find %s to plant kprobe\n", "do_fork");
|
||||
return -1;
|
||||
}
|
||||
if ((ret = register_kprobe(&kp) < 0)) {
|
||||
printk("register_kprobe failed, returned %d\n", ret);
|
||||
return -1;
|
||||
}
|
||||
printk("kprobe registered\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cleanup_module(void)
|
||||
{
|
||||
unregister_kprobe(&kp);
|
||||
printk("kprobe unregistered\n");
|
||||
}
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
----- cut here -----
|
||||
|
||||
You can build the kernel module, kprobe-example.ko, using the following
|
||||
Makefile:
|
||||
----- cut here -----
|
||||
obj-m := kprobe-example.o
|
||||
KDIR := /lib/modules/$(shell uname -r)/build
|
||||
PWD := $(shell pwd)
|
||||
default:
|
||||
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
|
||||
clean:
|
||||
rm -f *.mod.c *.ko *.o
|
||||
----- cut here -----
|
||||
|
||||
$ make
|
||||
$ su -
|
||||
...
|
||||
# insmod kprobe-example.ko
|
||||
|
||||
You will see the trace data in /var/log/messages and on the console
|
||||
whenever do_fork() is invoked to create a new process.
|
||||
|
||||
9. Jprobes Example
|
||||
|
||||
Here's a sample kernel module showing the use of jprobes to dump
|
||||
the arguments of do_fork().
|
||||
----- cut here -----
|
||||
/*jprobe-example.c */
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/uio.h>
|
||||
#include <linux/kprobes.h>
|
||||
#include <linux/kallsyms.h>
|
||||
|
||||
/*
|
||||
* Jumper probe for do_fork.
|
||||
* Mirror principle enables access to arguments of the probed routine
|
||||
* from the probe handler.
|
||||
*/
|
||||
|
||||
/* Proxy routine having the same arguments as actual do_fork() routine */
|
||||
long jdo_fork(unsigned long clone_flags, unsigned long stack_start,
|
||||
struct pt_regs *regs, unsigned long stack_size,
|
||||
int __user * parent_tidptr, int __user * child_tidptr)
|
||||
{
|
||||
printk("jprobe: clone_flags=0x%lx, stack_size=0x%lx, regs=0x%p\n",
|
||||
clone_flags, stack_size, regs);
|
||||
/* Always end with a call to jprobe_return(). */
|
||||
jprobe_return();
|
||||
/*NOTREACHED*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct jprobe my_jprobe = {
|
||||
.entry = (kprobe_opcode_t *) jdo_fork
|
||||
};
|
||||
|
||||
int init_module(void)
|
||||
{
|
||||
int ret;
|
||||
my_jprobe.kp.addr = (kprobe_opcode_t *) kallsyms_lookup_name("do_fork");
|
||||
if (!my_jprobe.kp.addr) {
|
||||
printk("Couldn't find %s to plant jprobe\n", "do_fork");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((ret = register_jprobe(&my_jprobe)) <0) {
|
||||
printk("register_jprobe failed, returned %d\n", ret);
|
||||
return -1;
|
||||
}
|
||||
printk("Planted jprobe at %p, handler addr %p\n",
|
||||
my_jprobe.kp.addr, my_jprobe.entry);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cleanup_module(void)
|
||||
{
|
||||
unregister_jprobe(&my_jprobe);
|
||||
printk("jprobe unregistered\n");
|
||||
}
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
----- cut here -----
|
||||
|
||||
Build and insert the kernel module as shown in the above kprobe
|
||||
example. You will see the trace data in /var/log/messages and on
|
||||
the console whenever do_fork() is invoked to create a new process.
|
||||
(Some messages may be suppressed if syslogd is configured to
|
||||
eliminate duplicate messages.)
|
||||
|
||||
10. Kretprobes Example
|
||||
|
||||
Here's a sample kernel module showing the use of return probes to
|
||||
report failed calls to sys_open().
|
||||
----- cut here -----
|
||||
/*kretprobe-example.c*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kprobes.h>
|
||||
#include <linux/kallsyms.h>
|
||||
|
||||
static const char *probed_func = "sys_open";
|
||||
|
||||
/* Return-probe handler: If the probed function fails, log the return value. */
|
||||
static int ret_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
|
||||
{
|
||||
// Substitute the appropriate register name for your architecture --
|
||||
// e.g., regs->rax for x86_64, regs->gpr[3] for ppc64.
|
||||
int retval = (int) regs->eax;
|
||||
if (retval < 0) {
|
||||
printk("%s returns %d\n", probed_func, retval);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct kretprobe my_kretprobe = {
|
||||
.handler = ret_handler,
|
||||
/* Probe up to 20 instances concurrently. */
|
||||
.maxactive = 20
|
||||
};
|
||||
|
||||
int init_module(void)
|
||||
{
|
||||
int ret;
|
||||
my_kretprobe.kp.addr =
|
||||
(kprobe_opcode_t *) kallsyms_lookup_name(probed_func);
|
||||
if (!my_kretprobe.kp.addr) {
|
||||
printk("Couldn't find %s to plant return probe\n", probed_func);
|
||||
return -1;
|
||||
}
|
||||
if ((ret = register_kretprobe(&my_kretprobe)) < 0) {
|
||||
printk("register_kretprobe failed, returned %d\n", ret);
|
||||
return -1;
|
||||
}
|
||||
printk("Planted return probe at %p\n", my_kretprobe.kp.addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cleanup_module(void)
|
||||
{
|
||||
unregister_kretprobe(&my_kretprobe);
|
||||
printk("kretprobe unregistered\n");
|
||||
/* nmissed > 0 suggests that maxactive was set too low. */
|
||||
printk("Missed probing %d instances of %s\n",
|
||||
my_kretprobe.nmissed, probed_func);
|
||||
}
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
----- cut here -----
|
||||
|
||||
Build and insert the kernel module as shown in the above kprobe
|
||||
example. You will see the trace data in /var/log/messages and on the
|
||||
console whenever sys_open() returns a negative value. (Some messages
|
||||
may be suppressed if syslogd is configured to eliminate duplicate
|
||||
messages.)
|
||||
|
||||
For additional information on Kprobes, refer to the following URLs:
|
||||
http://www-106.ibm.com/developerworks/library/l-kprobes.html?ca=dgr-lnxw42Kprobe
|
||||
http://www.redhat.com/magazine/005mar05/features/kprobes/
|
File diff suppressed because it is too large
Load Diff
@ -266,20 +266,6 @@ port an old driver to the new PCI interface. They are no longer present
|
||||
in the kernel as they aren't compatible with hotplug or PCI domains or
|
||||
having sane locking.
|
||||
|
||||
pcibios_present() and Since ages, you don't need to test presence
|
||||
pci_present() of PCI subsystem when trying to talk to it.
|
||||
If it's not there, the list of PCI devices
|
||||
is empty and all functions for searching for
|
||||
devices just return NULL.
|
||||
pcibios_(read|write)_* Superseded by their pci_(read|write)_*
|
||||
counterparts.
|
||||
pcibios_find_* Superseded by their pci_get_* counterparts.
|
||||
pci_for_each_dev() Superseded by pci_get_device()
|
||||
pci_for_each_dev_reverse() Superseded by pci_find_device_reverse()
|
||||
pci_for_each_bus() Superseded by pci_find_next_bus()
|
||||
pci_find_device() Superseded by pci_get_device()
|
||||
pci_find_subsys() Superseded by pci_get_subsys()
|
||||
pci_find_slot() Superseded by pci_get_slot()
|
||||
pcibios_find_class() Superseded by pci_get_class()
|
||||
pci_find_class() Superseded by pci_get_class()
|
||||
pci_(read|write)_*_nodev() Superseded by pci_bus_(read|write)_*()
|
||||
|
@ -56,3 +56,12 @@ This file details changes in 2.6 which affect PCMCIA card driver authors:
|
||||
memory regions in-use. The name argument should be a pointer to
|
||||
your driver name. Eg, for pcnet_cs, name should point to the
|
||||
string "pcnet_cs".
|
||||
|
||||
* CardServices is gone
|
||||
CardServices() in 2.4 is just a big switch statement to call various
|
||||
services. In 2.6, all of those entry points are exported and called
|
||||
directly (except for pcmcia_report_error(), just use cs_error() instead).
|
||||
|
||||
* struct pcmcia_driver
|
||||
You need to use struct pcmcia_driver and pcmcia_{un,}register_driver
|
||||
instead of {un,}register_pccard_driver
|
||||
|
@ -388,7 +388,6 @@ Summary:
|
||||
scsi_remove_device - detach and remove a SCSI device
|
||||
scsi_remove_host - detach and remove all SCSI devices owned by host
|
||||
scsi_report_bus_reset - report scsi _bus_ reset observed
|
||||
scsi_set_device - place device reference in host structure
|
||||
scsi_track_queue_full - track successive QUEUE_FULL events
|
||||
scsi_unblock_requests - allow further commands to be queued to given host
|
||||
scsi_unregister - [calls scsi_host_put()]
|
||||
@ -740,20 +739,6 @@ int scsi_remove_host(struct Scsi_Host *shost)
|
||||
void scsi_report_bus_reset(struct Scsi_Host * shost, int channel)
|
||||
|
||||
|
||||
/**
|
||||
* scsi_set_device - place device reference in host structure
|
||||
* @shost: a pointer to a scsi host instance
|
||||
* @pdev: pointer to device instance to assign
|
||||
*
|
||||
* Returns nothing
|
||||
*
|
||||
* Might block: no
|
||||
*
|
||||
* Defined in: include/scsi/scsi_host.h .
|
||||
**/
|
||||
void scsi_set_device(struct Scsi_Host * shost, struct device * dev)
|
||||
|
||||
|
||||
/**
|
||||
* scsi_track_queue_full - track successive QUEUE_FULL events on given
|
||||
* device to determine if and when there is a need
|
||||
|
@ -636,11 +636,16 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
3stack-digout 3-jack in back, a HP out and a SPDIF out
|
||||
5stack 5-jack in back, 2-jack in front
|
||||
5stack-digout 5-jack in back, 2-jack in front, a SPDIF out
|
||||
6stack 6-jack in back, 2-jack in front
|
||||
6stack-digout 6-jack with a SPDIF out
|
||||
w810 3-jack
|
||||
z71v 3-jack (HP shared SPDIF)
|
||||
asus 3-jack
|
||||
uniwill 3-jack
|
||||
F1734 2-jack
|
||||
test for testing/debugging purpose, almost all controls can be
|
||||
adjusted. Appearing only when compiled with
|
||||
$CONFIG_SND_DEBUG=y
|
||||
|
||||
CMI9880
|
||||
minimal 3-jack in back
|
||||
@ -1054,6 +1059,13 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-pxa2xx-ac97 (on arm only)
|
||||
------------------------------------
|
||||
|
||||
Module for AC97 driver for the Intel PXA2xx chip
|
||||
|
||||
For ARM architecture only.
|
||||
|
||||
Module snd-rme32
|
||||
----------------
|
||||
|
||||
@ -1173,6 +1185,13 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
|
||||
Module supports up to 8 cards.
|
||||
|
||||
Module snd-sun-dbri (on sparc only)
|
||||
-----------------------------------
|
||||
|
||||
Module for DBRI sound chips found on Sparcs.
|
||||
|
||||
Module supports up to 8 cards.
|
||||
|
||||
Module snd-wavefront
|
||||
--------------------
|
||||
|
||||
@ -1371,7 +1390,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
Module snd-vxpocket
|
||||
-------------------
|
||||
|
||||
Module for Digigram VX-Pocket VX2 PCMCIA card.
|
||||
Module for Digigram VX-Pocket VX2 and 440 PCMCIA cards.
|
||||
|
||||
ibl - Capture IBL size. (default = 0, minimum size)
|
||||
|
||||
@ -1391,29 +1410,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
|
||||
Note: the driver is build only when CONFIG_ISA is set.
|
||||
|
||||
Module snd-vxp440
|
||||
-----------------
|
||||
|
||||
Module for Digigram VX-Pocket 440 PCMCIA card.
|
||||
|
||||
ibl - Capture IBL size. (default = 0, minimum size)
|
||||
|
||||
Module supports up to 8 cards. The module is compiled only when
|
||||
PCMCIA is supported on kernel.
|
||||
|
||||
To activate the driver via the card manager, you'll need to set
|
||||
up /etc/pcmcia/vxp440.conf. See the sound/pcmcia/vx/vxp440.c.
|
||||
|
||||
When the driver is compiled as a module and the hotplug firmware
|
||||
is supported, the firmware data is loaded via hotplug automatically.
|
||||
Install the necessary firmware files in alsa-firmware package.
|
||||
When no hotplug fw loader is available, you need to load the
|
||||
firmware via vxloader utility in alsa-tools package.
|
||||
|
||||
About capture IBL, see the description of snd-vx222 module.
|
||||
|
||||
Note: the driver is build only when CONFIG_ISA is set.
|
||||
|
||||
Module snd-ymfpci
|
||||
-----------------
|
||||
|
||||
|
@ -132,7 +132,7 @@ to extra work for the USB developers. Since all Linux USB developers do
|
||||
their work on their own time, asking programmers to do extra work for no
|
||||
gain, for free, is not a possibility.
|
||||
|
||||
Security issues are also a very important for Linux. When a
|
||||
Security issues are also very important for Linux. When a
|
||||
security issue is found, it is fixed in a very short amount of time. A
|
||||
number of times this has caused internal kernel interfaces to be
|
||||
reworked to prevent the security problem from occurring. When this
|
||||
|
58
Documentation/stable_kernel_rules.txt
Normal file
58
Documentation/stable_kernel_rules.txt
Normal file
@ -0,0 +1,58 @@
|
||||
Everything you ever wanted to know about Linux 2.6 -stable releases.
|
||||
|
||||
Rules on what kind of patches are accepted, and what ones are not, into
|
||||
the "-stable" tree:
|
||||
|
||||
- It must be obviously correct and tested.
|
||||
- It can not bigger than 100 lines, with context.
|
||||
- It must fix only one thing.
|
||||
- It must fix a real bug that bothers people (not a, "This could be a
|
||||
problem..." type thing.)
|
||||
- It must fix a problem that causes a build error (but not for things
|
||||
marked CONFIG_BROKEN), an oops, a hang, data corruption, a real
|
||||
security issue, or some "oh, that's not good" issue. In short,
|
||||
something critical.
|
||||
- No "theoretical race condition" issues, unless an explanation of how
|
||||
the race can be exploited.
|
||||
- It can not contain any "trivial" fixes in it (spelling changes,
|
||||
whitespace cleanups, etc.)
|
||||
- It must be accepted by the relevant subsystem maintainer.
|
||||
- It must follow Documentation/SubmittingPatches rules.
|
||||
|
||||
|
||||
Procedure for submitting patches to the -stable tree:
|
||||
|
||||
- Send the patch, after verifying that it follows the above rules, to
|
||||
stable@kernel.org.
|
||||
- The sender will receive an ack when the patch has been accepted into
|
||||
the queue, or a nak if the patch is rejected. This response might
|
||||
take a few days, according to the developer's schedules.
|
||||
- If accepted, the patch will be added to the -stable queue, for review
|
||||
by other developers.
|
||||
- Security patches should not be sent to this alias, but instead to the
|
||||
documented security@kernel.org.
|
||||
|
||||
|
||||
Review cycle:
|
||||
|
||||
- When the -stable maintainers decide for a review cycle, the patches
|
||||
will be sent to the review committee, and the maintainer of the
|
||||
affected area of the patch (unless the submitter is the maintainer of
|
||||
the area) and CC: to the linux-kernel mailing list.
|
||||
- The review committee has 48 hours in which to ack or nak the patch.
|
||||
- If the patch is rejected by a member of the committee, or linux-kernel
|
||||
members object to the patch, bringing up issues that the maintainers
|
||||
and members did not realize, the patch will be dropped from the
|
||||
queue.
|
||||
- At the end of the review cycle, the acked patches will be added to
|
||||
the latest -stable release, and a new -stable release will happen.
|
||||
- Security patches will be accepted into the -stable tree directly from
|
||||
the security kernel team, and not go through the normal review cycle.
|
||||
Contact the kernel security team for more details on this procedure.
|
||||
|
||||
|
||||
Review committe:
|
||||
|
||||
- This will be made up of a number of kernel developers who have
|
||||
volunteered for this task, and a few that haven't.
|
||||
|
@ -102,7 +102,7 @@ Here is the list of words, from left to right:
|
||||
- URB Status. This field makes no sense for submissions, but is present
|
||||
to help scripts with parsing. In error case, it contains the error code.
|
||||
In case of a setup packet, it contains a Setup Tag. If scripts read a number
|
||||
in this field, the proceed to read Data Length. Otherwise, they read
|
||||
in this field, they proceed to read Data Length. Otherwise, they read
|
||||
the setup packet before reading the Data Length.
|
||||
- Setup packet, if present, consists of 5 words: one of each for bmRequestType,
|
||||
bRequest, wValue, wIndex, wLength, as specified by the USB Specification 2.0.
|
||||
|
@ -29,3 +29,4 @@ card=27 - PixelView PlayTV Ultra Pro (Stereo)
|
||||
card=28 - DViCO FusionHDTV 3 Gold-T
|
||||
card=29 - ADS Tech Instant TV DVB-T PCI
|
||||
card=30 - TerraTec Cinergy 1400 DVB-T
|
||||
card=31 - DViCO FusionHDTV 5 Gold
|
||||
|
@ -62,3 +62,5 @@ tuner=60 - Thomson DDT 7611 (ATSC/NTSC)
|
||||
tuner=61 - Tena TNF9533-D/IF/TNF9533-B/DF
|
||||
tuner=62 - Philips TEA5767HN FM Radio
|
||||
tuner=63 - Philips FMD1216ME MK3 Hybrid Tuner
|
||||
tuner=64 - LG TDVS-H062F/TUA6034
|
||||
tuner=65 - Ymec TVF66T5-B/DFF
|
||||
|
@ -44,6 +44,9 @@ bttv.o
|
||||
push used by bttv. bttv will disable overlay
|
||||
by default on this hardware to avoid crashes.
|
||||
With this insmod option you can override this.
|
||||
no_overlay=1 Disable overlay. It should be used by broken
|
||||
hardware that doesn't support PCI2PCI direct
|
||||
transfers.
|
||||
automute=0/1 Automatically mutes the sound if there is
|
||||
no TV signal, on by default. You might try
|
||||
to disable this if you have bad input signal
|
||||
|
@ -6,6 +6,11 @@ only the AMD64 specific ones are listed here.
|
||||
Machine check
|
||||
|
||||
mce=off disable machine check
|
||||
mce=bootlog Enable logging of machine checks left over from booting.
|
||||
Disabled by default because some BIOS leave bogus ones.
|
||||
If your BIOS doesn't do that it's a good idea to enable though
|
||||
to make sure you log even machine check events that result
|
||||
in a reboot.
|
||||
|
||||
nomce (for compatibility with i386): same as mce=off
|
||||
|
||||
@ -47,7 +52,7 @@ Timing
|
||||
notsc
|
||||
Don't use the CPU time stamp counter to read the wall time.
|
||||
This can be used to work around timing problems on multiprocessor systems
|
||||
with not properly synchronized CPUs. Only useful with a SMP kernel
|
||||
with not properly synchronized CPUs.
|
||||
|
||||
report_lost_ticks
|
||||
Report when timer interrupts are lost because some code turned off
|
||||
@ -74,6 +79,9 @@ Idle loop
|
||||
event. This will make the CPUs eat a lot more power, but may be useful
|
||||
to get slightly better performance in multiprocessor benchmarks. It also
|
||||
makes some profiling using performance counters more accurate.
|
||||
Please note that on systems with MONITOR/MWAIT support (like Intel EM64T
|
||||
CPUs) this option has no performance advantage over the normal idle loop.
|
||||
It may also interact badly with hyperthreading.
|
||||
|
||||
Rebooting
|
||||
|
||||
@ -178,6 +186,5 @@ Debugging
|
||||
Misc
|
||||
|
||||
noreplacement Don't replace instructions with more appropiate ones
|
||||
for the CPU. This may be useful on asymmetric MP systems
|
||||
where some CPU have less capabilities than the others.
|
||||
|
||||
for the CPU. This may be useful on asymmetric MP systems
|
||||
where some CPU have less capabilities than the others.
|
||||
|
33
MAINTAINERS
33
MAINTAINERS
@ -784,7 +784,7 @@ DVB SUBSYSTEM AND DRIVERS
|
||||
P: LinuxTV.org Project
|
||||
M: linux-dvb-maintainer@linuxtv.org
|
||||
L: linux-dvb@linuxtv.org (subscription required)
|
||||
W: http://linuxtv.org/developer/dvb.xml
|
||||
W: http://linuxtv.org/
|
||||
S: Supported
|
||||
|
||||
EATA-DMA SCSI DRIVER
|
||||
@ -1416,13 +1416,20 @@ W: http://www.penguinppc.org/
|
||||
L: linuxppc-embedded@ozlabs.org
|
||||
S: Maintained
|
||||
|
||||
LINUX FOR POWERPC EMBEDDED PPC8XX AND BOOT CODE
|
||||
LINUX FOR POWERPC BOOT CODE
|
||||
P: Tom Rini
|
||||
M: trini@kernel.crashing.org
|
||||
W: http://www.penguinppc.org/
|
||||
L: linuxppc-embedded@ozlabs.org
|
||||
S: Maintained
|
||||
|
||||
LINUX FOR POWERPC EMBEDDED PPC8XX
|
||||
P: Marcelo Tosatti
|
||||
M: marcelo.tosatti@cyclades.com
|
||||
W: http://www.penguinppc.org/
|
||||
L: linuxppc-embedded@ozlabs.org
|
||||
S: Maintained
|
||||
|
||||
LINUX FOR POWERPC EMBEDDED PPC83XX AND PPC85XX
|
||||
P: Kumar Gala
|
||||
M: kumar.gala@freescale.com
|
||||
@ -1514,6 +1521,12 @@ P: Zach Brown
|
||||
M: zab@zabbo.net
|
||||
S: Odd Fixes
|
||||
|
||||
MAN-PAGES: MANUAL PAGES FOR LINUX -- Sections 2, 3, 4, 5, and 7
|
||||
P: Michael Kerrisk
|
||||
M: mtk-manpages@gmx.net
|
||||
W: ftp://ftp.kernel.org/pub/linux/docs/manpages
|
||||
S: Maintained
|
||||
|
||||
MARVELL MV64340 ETHERNET DRIVER
|
||||
P: Manish Lachwani
|
||||
M: Manish_Lachwani@pmc-sierra.com
|
||||
@ -1645,7 +1658,7 @@ M: kuznet@ms2.inr.ac.ru
|
||||
P: Pekka Savola (ipv6)
|
||||
M: pekkas@netcore.fi
|
||||
P: James Morris
|
||||
M: jmorris@redhat.com
|
||||
M: jmorris@namei.org
|
||||
P: Hideaki YOSHIFUJI
|
||||
M: yoshfuji@linux-ipv6.org
|
||||
P: Patrick McHardy
|
||||
@ -1812,6 +1825,12 @@ P: Greg Kroah-Hartman
|
||||
M: greg@kroah.com
|
||||
S: Maintained
|
||||
|
||||
PCIE HOTPLUG DRIVER
|
||||
P: Kristen Carlson Accardi
|
||||
M: kristen.c.accardi@intel.com
|
||||
L: pcihpd-discuss@lists.sourceforge.net
|
||||
S: Maintained
|
||||
|
||||
PCMCIA SUBSYSTEM
|
||||
P: Linux PCMCIA Team
|
||||
L: http://lists.infradead.org/mailman/listinfo/linux-pcmcia
|
||||
@ -2034,7 +2053,7 @@ SELINUX SECURITY MODULE
|
||||
P: Stephen Smalley
|
||||
M: sds@epoch.ncsc.mil
|
||||
P: James Morris
|
||||
M: jmorris@redhat.com
|
||||
M: jmorris@namei.org
|
||||
L: linux-kernel@vger.kernel.org (kernel issues)
|
||||
L: selinux@tycho.nsa.gov (general discussion)
|
||||
W: http://www.nsa.gov/selinux
|
||||
@ -2188,6 +2207,12 @@ W: http://projects.buici.com/arm
|
||||
L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
|
||||
S: Maintained
|
||||
|
||||
SHPC HOTPLUG DRIVER
|
||||
P: Kristen Carlson Accardi
|
||||
M: kristen.c.accardi@intel.com
|
||||
L: pcihpd-discuss@lists.sourceforge.net
|
||||
S: Maintained
|
||||
|
||||
SPARC (sparc32):
|
||||
P: William L. Irwin
|
||||
M: wli@holomorphy.com
|
||||
|
2
Makefile
2
Makefile
@ -1,7 +1,7 @@
|
||||
VERSION = 2
|
||||
PATCHLEVEL = 6
|
||||
SUBLEVEL = 13
|
||||
EXTRAVERSION =-rc3
|
||||
EXTRAVERSION =-rc6
|
||||
NAME=Woozy Numbat
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
10
README
10
README
@ -87,6 +87,16 @@ INSTALLING the kernel:
|
||||
kernel source. Patches are applied from the current directory, but
|
||||
an alternative directory can be specified as the second argument.
|
||||
|
||||
- If you are upgrading between releases using the stable series patches
|
||||
(for example, patch-2.6.xx.y), note that these "dot-releases" are
|
||||
not incremental and must be applied to the 2.6.xx base tree. For
|
||||
example, if your base kernel is 2.6.12 and you want to apply the
|
||||
2.6.12.3 patch, you do not and indeed must not first apply the
|
||||
2.6.12.1 and 2.6.12.2 patches. Similarly, if you are running kernel
|
||||
version 2.6.12.2 and want to jump to 2.6.12.3, you must first
|
||||
reverse the 2.6.12.2 patch (that is, patch -R) _before_ applying
|
||||
the 2.6.12.3 patch.
|
||||
|
||||
- Make sure you have no stale .o files and dependencies lying around:
|
||||
|
||||
cd linux
|
||||
|
@ -41,18 +41,19 @@ summary from [1.]>" for easy identification by the developers
|
||||
[2.] Full description of the problem/report:
|
||||
[3.] Keywords (i.e., modules, networking, kernel):
|
||||
[4.] Kernel version (from /proc/version):
|
||||
[5.] Output of Oops.. message (if applicable) with symbolic information
|
||||
[5.] Most recent kernel version which did not have the bug:
|
||||
[6.] Output of Oops.. message (if applicable) with symbolic information
|
||||
resolved (see Documentation/oops-tracing.txt)
|
||||
[6.] A small shell script or example program which triggers the
|
||||
[7.] A small shell script or example program which triggers the
|
||||
problem (if possible)
|
||||
[7.] Environment
|
||||
[7.1.] Software (add the output of the ver_linux script here)
|
||||
[7.2.] Processor information (from /proc/cpuinfo):
|
||||
[7.3.] Module information (from /proc/modules):
|
||||
[7.4.] Loaded driver and hardware information (/proc/ioports, /proc/iomem)
|
||||
[7.5.] PCI information ('lspci -vvv' as root)
|
||||
[7.6.] SCSI information (from /proc/scsi/scsi)
|
||||
[7.7.] Other information that might be relevant to the problem
|
||||
[8.] Environment
|
||||
[8.1.] Software (add the output of the ver_linux script here)
|
||||
[8.2.] Processor information (from /proc/cpuinfo):
|
||||
[8.3.] Module information (from /proc/modules):
|
||||
[8.4.] Loaded driver and hardware information (/proc/ioports, /proc/iomem)
|
||||
[8.5.] PCI information ('lspci -vvv' as root)
|
||||
[8.6.] SCSI information (from /proc/scsi/scsi)
|
||||
[8.7.] Other information that might be relevant to the problem
|
||||
(please look in /proc and include all information that you
|
||||
think to be relevant):
|
||||
[X.] Other notes, patches, fixes, workarounds:
|
||||
|
@ -350,8 +350,24 @@ pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
|
||||
region->end = res->end - offset;
|
||||
}
|
||||
|
||||
void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
|
||||
struct pci_bus_region *region)
|
||||
{
|
||||
struct pci_controller *hose = (struct pci_controller *)dev->sysdata;
|
||||
unsigned long offset = 0;
|
||||
|
||||
if (res->flags & IORESOURCE_IO)
|
||||
offset = hose->io_space->start;
|
||||
else if (res->flags & IORESOURCE_MEM)
|
||||
offset = hose->mem_space->start;
|
||||
|
||||
res->start = region->start + offset;
|
||||
res->end = region->end + offset;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HOTPLUG
|
||||
EXPORT_SYMBOL(pcibios_resource_to_bus);
|
||||
EXPORT_SYMBOL(pcibios_bus_to_resource);
|
||||
#endif
|
||||
|
||||
int
|
||||
|
@ -165,7 +165,6 @@ machine_restart(char *restart_cmd)
|
||||
common_shutdown(LINUX_REBOOT_CMD_RESTART, restart_cmd);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(machine_restart);
|
||||
|
||||
void
|
||||
machine_halt(void)
|
||||
@ -173,7 +172,6 @@ machine_halt(void)
|
||||
common_shutdown(LINUX_REBOOT_CMD_HALT, NULL);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(machine_halt);
|
||||
|
||||
void
|
||||
machine_power_off(void)
|
||||
@ -181,7 +179,6 @@ machine_power_off(void)
|
||||
common_shutdown(LINUX_REBOOT_CMD_POWER_OFF, NULL);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(machine_power_off);
|
||||
|
||||
/* Used by sysrq-p, among others. I don't believe r9-r15 are ever
|
||||
saved in the context it's used. */
|
||||
|
@ -461,6 +461,11 @@ sys_call_table:
|
||||
.quad sys_add_key
|
||||
.quad sys_request_key /* 440 */
|
||||
.quad sys_keyctl
|
||||
.quad sys_ioprio_set
|
||||
.quad sys_ioprio_get
|
||||
.quad sys_inotify_init
|
||||
.quad sys_inotify_add_watch /* 445 */
|
||||
.quad sys_inotify_rm_watch
|
||||
|
||||
.size sys_call_table, . - sys_call_table
|
||||
.type sys_call_table, @object
|
||||
|
@ -447,9 +447,26 @@ pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
|
||||
region->end = res->end - offset;
|
||||
}
|
||||
|
||||
void __devinit
|
||||
pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
|
||||
struct pci_bus_region *region)
|
||||
{
|
||||
struct pci_sys_data *root = dev->sysdata;
|
||||
unsigned long offset = 0;
|
||||
|
||||
if (res->flags & IORESOURCE_IO)
|
||||
offset = root->io_offset;
|
||||
if (res->flags & IORESOURCE_MEM)
|
||||
offset = root->mem_offset;
|
||||
|
||||
res->start = region->start + offset;
|
||||
res->end = region->end + offset;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HOTPLUG
|
||||
EXPORT_SYMBOL(pcibios_fixup_bus);
|
||||
EXPORT_SYMBOL(pcibios_resource_to_bus);
|
||||
EXPORT_SYMBOL(pcibios_bus_to_resource);
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -533,6 +533,13 @@ ENTRY(__switch_to)
|
||||
ldr r3, [r2, #TI_TP_VALUE]
|
||||
stmia ip!, {r4 - sl, fp, sp, lr} @ Store most regs on stack
|
||||
ldr r6, [r2, #TI_CPU_DOMAIN]!
|
||||
#if __LINUX_ARM_ARCH__ >= 6
|
||||
#ifdef CONFIG_CPU_MPCORE
|
||||
clrex
|
||||
#else
|
||||
strex r3, r4, [ip] @ Clear exclusive monitor
|
||||
#endif
|
||||
#endif
|
||||
#if defined(CONFIG_CPU_XSCALE) && !defined(CONFIG_IWMMXT)
|
||||
mra r4, r5, acc0
|
||||
stmia ip, {r4, r5}
|
||||
|
@ -131,7 +131,6 @@ void machine_halt(void)
|
||||
{
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(machine_halt);
|
||||
|
||||
void machine_power_off(void)
|
||||
{
|
||||
@ -139,7 +138,6 @@ void machine_power_off(void)
|
||||
pm_power_off();
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(machine_power_off);
|
||||
|
||||
void machine_restart(char * __unused)
|
||||
{
|
||||
@ -169,8 +167,6 @@ void machine_restart(char * __unused)
|
||||
while (1);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(machine_restart);
|
||||
|
||||
void __show_regs(struct pt_regs *regs)
|
||||
{
|
||||
unsigned long flags = condition_codes(regs);
|
||||
|
@ -176,6 +176,7 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
|
||||
cpu_set(cpu, mm->cpu_vm_mask);
|
||||
cpu_switch_mm(mm->pgd, mm);
|
||||
enter_lazy_tlb(mm, current);
|
||||
local_flush_tlb_all();
|
||||
|
||||
cpu_init();
|
||||
|
||||
|
@ -1,4 +1,6 @@
|
||||
#if __LINUX_ARM_ARCH__ >= 6
|
||||
#include <linux/config.h>
|
||||
|
||||
#if __LINUX_ARM_ARCH__ >= 6 && defined(CONFIG_CPU_MPCORE)
|
||||
.macro bitop, instr
|
||||
mov r2, #1
|
||||
and r3, r0, #7 @ Get bit offset
|
||||
@ -7,7 +9,7 @@
|
||||
1: ldrexb r2, [r1]
|
||||
\instr r2, r2, r3
|
||||
strexb r0, r2, [r1]
|
||||
cmpne r0, #0
|
||||
cmp r0, #0
|
||||
bne 1b
|
||||
mov pc, lr
|
||||
.endm
|
||||
@ -19,9 +21,9 @@
|
||||
mov r3, r2, lsl r3 @ create mask
|
||||
1: ldrexb r2, [r1]
|
||||
ands r0, r2, r3 @ save old value of bit
|
||||
\instr ip, r2, r3 @ toggle bit
|
||||
strexb r2, ip, [r1]
|
||||
cmp r2, #0
|
||||
\instr r2, r2, r3 @ toggle bit
|
||||
strexb ip, r2, [r1]
|
||||
cmp ip, #0
|
||||
bne 1b
|
||||
cmp r0, #0
|
||||
movne r0, #1
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <linux/mm.h>
|
||||
|
||||
#include <asm/atomic.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/delay.h>
|
||||
#include <asm/mmu_context.h>
|
||||
#include <asm/procinfo.h>
|
||||
@ -80,6 +81,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
|
||||
* "cpu" is Linux's internal ID.
|
||||
*/
|
||||
pen_release = cpu;
|
||||
flush_cache_all();
|
||||
|
||||
/*
|
||||
* XXX
|
||||
|
@ -61,7 +61,7 @@ static struct plat_serial8250_port coyote_uart_data[] = {
|
||||
.mapbase = IXP4XX_UART2_BASE_PHYS,
|
||||
.membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
|
||||
.irq = IRQ_IXP4XX_UART2,
|
||||
.flags = UPF_BOOT_AUTOCONF,
|
||||
.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
|
||||
.iotype = UPIO_MEM,
|
||||
.regshift = 2,
|
||||
.uartclk = IXP4XX_UART_XTAL,
|
||||
|
@ -83,7 +83,7 @@ static struct plat_serial8250_port gtwx5715_uart_platform_data[] = {
|
||||
.mapbase = IXP4XX_UART2_BASE_PHYS,
|
||||
.membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
|
||||
.irq = IRQ_IXP4XX_UART2,
|
||||
.flags = UPF_BOOT_AUTOCONF,
|
||||
.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
|
||||
.iotype = UPIO_MEM,
|
||||
.regshift = 2,
|
||||
.uartclk = IXP4XX_UART_XTAL,
|
||||
|
@ -82,7 +82,7 @@ static struct plat_serial8250_port ixdp425_uart_data[] = {
|
||||
.mapbase = IXP4XX_UART1_BASE_PHYS,
|
||||
.membase = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET,
|
||||
.irq = IRQ_IXP4XX_UART1,
|
||||
.flags = UPF_BOOT_AUTOCONF,
|
||||
.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
|
||||
.iotype = UPIO_MEM,
|
||||
.regshift = 2,
|
||||
.uartclk = IXP4XX_UART_XTAL,
|
||||
@ -91,7 +91,7 @@ static struct plat_serial8250_port ixdp425_uart_data[] = {
|
||||
.mapbase = IXP4XX_UART2_BASE_PHYS,
|
||||
.membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
|
||||
.irq = IRQ_IXP4XX_UART1,
|
||||
.flags = UPF_BOOT_AUTOCONF,
|
||||
.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
|
||||
.iotype = UPIO_MEM,
|
||||
.regshift = 2,
|
||||
.uartclk = IXP4XX_UART_XTAL,
|
||||
|
@ -23,6 +23,8 @@ obj-$(CONFIG_PM_SIMTEC) += pm-simtec.o
|
||||
# S3C2440 support
|
||||
|
||||
obj-$(CONFIG_CPU_S3C2440) += s3c2440.o s3c2440-dsc.o
|
||||
obj-$(CONFIG_CPU_S3C2440) += s3c2440-irq.o
|
||||
obj-$(CONFIG_CPU_S3C2440) += s3c2440-clock.o
|
||||
|
||||
# machine specific support
|
||||
|
||||
|
@ -448,60 +448,3 @@ int __init s3c24xx_setup_clocks(unsigned long xtal,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* S3C2440 extended clock support */
|
||||
|
||||
#ifdef CONFIG_CPU_S3C2440
|
||||
|
||||
static struct clk s3c2440_clk_upll = {
|
||||
.name = "upll",
|
||||
.id = -1,
|
||||
};
|
||||
|
||||
static struct clk s3c2440_clk_cam = {
|
||||
.name = "camif",
|
||||
.parent = &clk_h,
|
||||
.id = -1,
|
||||
.enable = s3c24xx_clkcon_enable,
|
||||
.ctrlbit = S3C2440_CLKCON_CAMERA,
|
||||
};
|
||||
|
||||
static struct clk s3c2440_clk_ac97 = {
|
||||
.name = "ac97",
|
||||
.parent = &clk_p,
|
||||
.id = -1,
|
||||
.enable = s3c24xx_clkcon_enable,
|
||||
.ctrlbit = S3C2440_CLKCON_CAMERA,
|
||||
};
|
||||
|
||||
static int s3c2440_clk_add(struct sys_device *sysdev)
|
||||
{
|
||||
unsigned long upllcon = __raw_readl(S3C2410_UPLLCON);
|
||||
|
||||
s3c2440_clk_upll.rate = s3c2410_get_pll(upllcon, clk_xtal.rate);
|
||||
|
||||
printk("S3C2440: Clock Support, UPLL %ld.%03ld MHz\n",
|
||||
print_mhz(s3c2440_clk_upll.rate));
|
||||
|
||||
s3c24xx_register_clock(&s3c2440_clk_ac97);
|
||||
s3c24xx_register_clock(&s3c2440_clk_cam);
|
||||
s3c24xx_register_clock(&s3c2440_clk_upll);
|
||||
|
||||
clk_disable(&s3c2440_clk_ac97);
|
||||
clk_disable(&s3c2440_clk_cam);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct sysdev_driver s3c2440_clk_driver = {
|
||||
.add = s3c2440_clk_add,
|
||||
};
|
||||
|
||||
static int s3c24xx_clk_driver(void)
|
||||
{
|
||||
return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_clk_driver);
|
||||
}
|
||||
|
||||
arch_initcall(s3c24xx_clk_driver);
|
||||
|
||||
#endif /* CONFIG_CPU_S3C2440 */
|
||||
|
@ -45,6 +45,9 @@
|
||||
*
|
||||
* 28-Jun-2005 Ben Dooks
|
||||
* Mark IRQ_LCD valid
|
||||
*
|
||||
* 25-Jul-2005 Ben Dooks
|
||||
* Split the S3C2440 IRQ code to seperate file
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
@ -65,11 +68,7 @@
|
||||
|
||||
#include "cpu.h"
|
||||
#include "pm.h"
|
||||
|
||||
#define irqdbf(x...)
|
||||
#define irqdbf2(x...)
|
||||
|
||||
#define EXTINT_OFF (IRQ_EINT4 - 4)
|
||||
#include "irq.h"
|
||||
|
||||
/* wakeup irq control */
|
||||
|
||||
@ -181,7 +180,7 @@ s3c_irq_unmask(unsigned int irqno)
|
||||
__raw_writel(mask, S3C2410_INTMSK);
|
||||
}
|
||||
|
||||
static struct irqchip s3c_irq_level_chip = {
|
||||
struct irqchip s3c_irq_level_chip = {
|
||||
.ack = s3c_irq_maskack,
|
||||
.mask = s3c_irq_mask,
|
||||
.unmask = s3c_irq_unmask,
|
||||
@ -370,84 +369,6 @@ static struct irqchip s3c_irq_eint0t4 = {
|
||||
#define INTMSK_UART2 (1UL << (IRQ_UART2 - IRQ_EINT0))
|
||||
#define INTMSK_ADCPARENT (1UL << (IRQ_ADCPARENT - IRQ_EINT0))
|
||||
|
||||
static inline void
|
||||
s3c_irqsub_mask(unsigned int irqno, unsigned int parentbit,
|
||||
int subcheck)
|
||||
{
|
||||
unsigned long mask;
|
||||
unsigned long submask;
|
||||
|
||||
submask = __raw_readl(S3C2410_INTSUBMSK);
|
||||
mask = __raw_readl(S3C2410_INTMSK);
|
||||
|
||||
submask |= (1UL << (irqno - IRQ_S3CUART_RX0));
|
||||
|
||||
/* check to see if we need to mask the parent IRQ */
|
||||
|
||||
if ((submask & subcheck) == subcheck) {
|
||||
__raw_writel(mask | parentbit, S3C2410_INTMSK);
|
||||
}
|
||||
|
||||
/* write back masks */
|
||||
__raw_writel(submask, S3C2410_INTSUBMSK);
|
||||
|
||||
}
|
||||
|
||||
static inline void
|
||||
s3c_irqsub_unmask(unsigned int irqno, unsigned int parentbit)
|
||||
{
|
||||
unsigned long mask;
|
||||
unsigned long submask;
|
||||
|
||||
submask = __raw_readl(S3C2410_INTSUBMSK);
|
||||
mask = __raw_readl(S3C2410_INTMSK);
|
||||
|
||||
submask &= ~(1UL << (irqno - IRQ_S3CUART_RX0));
|
||||
mask &= ~parentbit;
|
||||
|
||||
/* write back masks */
|
||||
__raw_writel(submask, S3C2410_INTSUBMSK);
|
||||
__raw_writel(mask, S3C2410_INTMSK);
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
s3c_irqsub_maskack(unsigned int irqno, unsigned int parentmask, unsigned int group)
|
||||
{
|
||||
unsigned int bit = 1UL << (irqno - IRQ_S3CUART_RX0);
|
||||
|
||||
s3c_irqsub_mask(irqno, parentmask, group);
|
||||
|
||||
__raw_writel(bit, S3C2410_SUBSRCPND);
|
||||
|
||||
/* only ack parent if we've got all the irqs (seems we must
|
||||
* ack, all and hope that the irq system retriggers ok when
|
||||
* the interrupt goes off again)
|
||||
*/
|
||||
|
||||
if (1) {
|
||||
__raw_writel(parentmask, S3C2410_SRCPND);
|
||||
__raw_writel(parentmask, S3C2410_INTPND);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
s3c_irqsub_ack(unsigned int irqno, unsigned int parentmask, unsigned int group)
|
||||
{
|
||||
unsigned int bit = 1UL << (irqno - IRQ_S3CUART_RX0);
|
||||
|
||||
__raw_writel(bit, S3C2410_SUBSRCPND);
|
||||
|
||||
/* only ack parent if we've got all the irqs (seems we must
|
||||
* ack, all and hope that the irq system retriggers ok when
|
||||
* the interrupt goes off again)
|
||||
*/
|
||||
|
||||
if (1) {
|
||||
__raw_writel(parentmask, S3C2410_SRCPND);
|
||||
__raw_writel(parentmask, S3C2410_INTPND);
|
||||
}
|
||||
}
|
||||
|
||||
/* UART0 */
|
||||
|
||||
@ -794,174 +715,3 @@ void __init s3c24xx_init_irq(void)
|
||||
|
||||
irqdbf("s3c2410: registered interrupt handlers\n");
|
||||
}
|
||||
|
||||
/* s3c2440 irq code
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_CPU_S3C2440
|
||||
|
||||
/* WDT/AC97 */
|
||||
|
||||
static void s3c_irq_demux_wdtac97(unsigned int irq,
|
||||
struct irqdesc *desc,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
unsigned int subsrc, submsk;
|
||||
struct irqdesc *mydesc;
|
||||
|
||||
/* read the current pending interrupts, and the mask
|
||||
* for what it is available */
|
||||
|
||||
subsrc = __raw_readl(S3C2410_SUBSRCPND);
|
||||
submsk = __raw_readl(S3C2410_INTSUBMSK);
|
||||
|
||||
subsrc &= ~submsk;
|
||||
subsrc >>= 13;
|
||||
subsrc &= 3;
|
||||
|
||||
if (subsrc != 0) {
|
||||
if (subsrc & 1) {
|
||||
mydesc = irq_desc + IRQ_S3C2440_WDT;
|
||||
mydesc->handle( IRQ_S3C2440_WDT, mydesc, regs);
|
||||
}
|
||||
if (subsrc & 2) {
|
||||
mydesc = irq_desc + IRQ_S3C2440_AC97;
|
||||
mydesc->handle(IRQ_S3C2440_AC97, mydesc, regs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define INTMSK_WDT (1UL << (IRQ_WDT - IRQ_EINT0))
|
||||
|
||||
static void
|
||||
s3c_irq_wdtac97_mask(unsigned int irqno)
|
||||
{
|
||||
s3c_irqsub_mask(irqno, INTMSK_WDT, 3<<13);
|
||||
}
|
||||
|
||||
static void
|
||||
s3c_irq_wdtac97_unmask(unsigned int irqno)
|
||||
{
|
||||
s3c_irqsub_unmask(irqno, INTMSK_WDT);
|
||||
}
|
||||
|
||||
static void
|
||||
s3c_irq_wdtac97_ack(unsigned int irqno)
|
||||
{
|
||||
s3c_irqsub_maskack(irqno, INTMSK_WDT, 3<<13);
|
||||
}
|
||||
|
||||
static struct irqchip s3c_irq_wdtac97 = {
|
||||
.mask = s3c_irq_wdtac97_mask,
|
||||
.unmask = s3c_irq_wdtac97_unmask,
|
||||
.ack = s3c_irq_wdtac97_ack,
|
||||
};
|
||||
|
||||
/* camera irq */
|
||||
|
||||
static void s3c_irq_demux_cam(unsigned int irq,
|
||||
struct irqdesc *desc,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
unsigned int subsrc, submsk;
|
||||
struct irqdesc *mydesc;
|
||||
|
||||
/* read the current pending interrupts, and the mask
|
||||
* for what it is available */
|
||||
|
||||
subsrc = __raw_readl(S3C2410_SUBSRCPND);
|
||||
submsk = __raw_readl(S3C2410_INTSUBMSK);
|
||||
|
||||
subsrc &= ~submsk;
|
||||
subsrc >>= 11;
|
||||
subsrc &= 3;
|
||||
|
||||
if (subsrc != 0) {
|
||||
if (subsrc & 1) {
|
||||
mydesc = irq_desc + IRQ_S3C2440_CAM_C;
|
||||
mydesc->handle( IRQ_S3C2440_WDT, mydesc, regs);
|
||||
}
|
||||
if (subsrc & 2) {
|
||||
mydesc = irq_desc + IRQ_S3C2440_CAM_P;
|
||||
mydesc->handle(IRQ_S3C2440_AC97, mydesc, regs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define INTMSK_CAM (1UL << (IRQ_CAM - IRQ_EINT0))
|
||||
|
||||
static void
|
||||
s3c_irq_cam_mask(unsigned int irqno)
|
||||
{
|
||||
s3c_irqsub_mask(irqno, INTMSK_CAM, 3<<11);
|
||||
}
|
||||
|
||||
static void
|
||||
s3c_irq_cam_unmask(unsigned int irqno)
|
||||
{
|
||||
s3c_irqsub_unmask(irqno, INTMSK_CAM);
|
||||
}
|
||||
|
||||
static void
|
||||
s3c_irq_cam_ack(unsigned int irqno)
|
||||
{
|
||||
s3c_irqsub_maskack(irqno, INTMSK_CAM, 3<<11);
|
||||
}
|
||||
|
||||
static struct irqchip s3c_irq_cam = {
|
||||
.mask = s3c_irq_cam_mask,
|
||||
.unmask = s3c_irq_cam_unmask,
|
||||
.ack = s3c_irq_cam_ack,
|
||||
};
|
||||
|
||||
static int s3c2440_irq_add(struct sys_device *sysdev)
|
||||
{
|
||||
unsigned int irqno;
|
||||
|
||||
printk("S3C2440: IRQ Support\n");
|
||||
|
||||
set_irq_chip(IRQ_NFCON, &s3c_irq_level_chip);
|
||||
set_irq_handler(IRQ_NFCON, do_level_IRQ);
|
||||
set_irq_flags(IRQ_NFCON, IRQF_VALID);
|
||||
|
||||
/* add new chained handler for wdt, ac7 */
|
||||
|
||||
set_irq_chip(IRQ_WDT, &s3c_irq_level_chip);
|
||||
set_irq_handler(IRQ_WDT, do_level_IRQ);
|
||||
set_irq_chained_handler(IRQ_WDT, s3c_irq_demux_wdtac97);
|
||||
|
||||
for (irqno = IRQ_S3C2440_WDT; irqno <= IRQ_S3C2440_AC97; irqno++) {
|
||||
set_irq_chip(irqno, &s3c_irq_wdtac97);
|
||||
set_irq_handler(irqno, do_level_IRQ);
|
||||
set_irq_flags(irqno, IRQF_VALID);
|
||||
}
|
||||
|
||||
/* add chained handler for camera */
|
||||
|
||||
set_irq_chip(IRQ_CAM, &s3c_irq_level_chip);
|
||||
set_irq_handler(IRQ_CAM, do_level_IRQ);
|
||||
set_irq_chained_handler(IRQ_CAM, s3c_irq_demux_cam);
|
||||
|
||||
for (irqno = IRQ_S3C2440_CAM_C; irqno <= IRQ_S3C2440_CAM_P; irqno++) {
|
||||
set_irq_chip(irqno, &s3c_irq_cam);
|
||||
set_irq_handler(irqno, do_level_IRQ);
|
||||
set_irq_flags(irqno, IRQF_VALID);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct sysdev_driver s3c2440_irq_driver = {
|
||||
.add = s3c2440_irq_add,
|
||||
};
|
||||
|
||||
static int s3c24xx_irq_driver(void)
|
||||
{
|
||||
return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_irq_driver);
|
||||
}
|
||||
|
||||
arch_initcall(s3c24xx_irq_driver);
|
||||
|
||||
#endif /* CONFIG_CPU_S3C2440 */
|
||||
|
||||
|
99
arch/arm/mach-s3c2410/irq.h
Normal file
99
arch/arm/mach-s3c2410/irq.h
Normal file
@ -0,0 +1,99 @@
|
||||
/* arch/arm/mach-s3c2410/irq.h
|
||||
*
|
||||
* Copyright (c) 2004-2005 Simtec Electronics
|
||||
* Ben Dooks <ben@simtec.co.uk>
|
||||
*
|
||||
* Header file for S3C24XX CPU IRQ support
|
||||
*
|
||||
* 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:
|
||||
*/
|
||||
|
||||
#define irqdbf(x...)
|
||||
#define irqdbf2(x...)
|
||||
|
||||
#define EXTINT_OFF (IRQ_EINT4 - 4)
|
||||
|
||||
extern struct irqchip s3c_irq_level_chip;
|
||||
|
||||
static inline void
|
||||
s3c_irqsub_mask(unsigned int irqno, unsigned int parentbit,
|
||||
int subcheck)
|
||||
{
|
||||
unsigned long mask;
|
||||
unsigned long submask;
|
||||
|
||||
submask = __raw_readl(S3C2410_INTSUBMSK);
|
||||
mask = __raw_readl(S3C2410_INTMSK);
|
||||
|
||||
submask |= (1UL << (irqno - IRQ_S3CUART_RX0));
|
||||
|
||||
/* check to see if we need to mask the parent IRQ */
|
||||
|
||||
if ((submask & subcheck) == subcheck) {
|
||||
__raw_writel(mask | parentbit, S3C2410_INTMSK);
|
||||
}
|
||||
|
||||
/* write back masks */
|
||||
__raw_writel(submask, S3C2410_INTSUBMSK);
|
||||
|
||||
}
|
||||
|
||||
static inline void
|
||||
s3c_irqsub_unmask(unsigned int irqno, unsigned int parentbit)
|
||||
{
|
||||
unsigned long mask;
|
||||
unsigned long submask;
|
||||
|
||||
submask = __raw_readl(S3C2410_INTSUBMSK);
|
||||
mask = __raw_readl(S3C2410_INTMSK);
|
||||
|
||||
submask &= ~(1UL << (irqno - IRQ_S3CUART_RX0));
|
||||
mask &= ~parentbit;
|
||||
|
||||
/* write back masks */
|
||||
__raw_writel(submask, S3C2410_INTSUBMSK);
|
||||
__raw_writel(mask, S3C2410_INTMSK);
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
s3c_irqsub_maskack(unsigned int irqno, unsigned int parentmask, unsigned int group)
|
||||
{
|
||||
unsigned int bit = 1UL << (irqno - IRQ_S3CUART_RX0);
|
||||
|
||||
s3c_irqsub_mask(irqno, parentmask, group);
|
||||
|
||||
__raw_writel(bit, S3C2410_SUBSRCPND);
|
||||
|
||||
/* only ack parent if we've got all the irqs (seems we must
|
||||
* ack, all and hope that the irq system retriggers ok when
|
||||
* the interrupt goes off again)
|
||||
*/
|
||||
|
||||
if (1) {
|
||||
__raw_writel(parentmask, S3C2410_SRCPND);
|
||||
__raw_writel(parentmask, S3C2410_INTPND);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
s3c_irqsub_ack(unsigned int irqno, unsigned int parentmask, unsigned int group)
|
||||
{
|
||||
unsigned int bit = 1UL << (irqno - IRQ_S3CUART_RX0);
|
||||
|
||||
__raw_writel(bit, S3C2410_SUBSRCPND);
|
||||
|
||||
/* only ack parent if we've got all the irqs (seems we must
|
||||
* ack, all and hope that the irq system retriggers ok when
|
||||
* the interrupt goes off again)
|
||||
*/
|
||||
|
||||
if (1) {
|
||||
__raw_writel(parentmask, S3C2410_SRCPND);
|
||||
__raw_writel(parentmask, S3C2410_INTPND);
|
||||
}
|
||||
}
|
@ -25,10 +25,12 @@
|
||||
* 14-Jan-2005 BJD Add support for muitlple NAND devices
|
||||
* 03-Mar-2005 BJD Ensured that bast-cpld.h is included
|
||||
* 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
|
||||
* 14-Mar-2006 BJD Updated for __iomem changes
|
||||
* 22-Jun-2006 BJD Added DM9000 platform information
|
||||
* 28-Jun-2006 BJD Moved pm functionality out to common code
|
||||
* 17-Jul-2006 BJD Changed to platform device for SuperIO 16550s
|
||||
* 14-Mar-2005 BJD Updated for __iomem changes
|
||||
* 22-Jun-2005 BJD Added DM9000 platform information
|
||||
* 28-Jun-2005 BJD Moved pm functionality out to common code
|
||||
* 17-Jul-2005 BJD Changed to platform device for SuperIO 16550s
|
||||
* 25-Jul-2005 BJD Removed ASIX static mappings
|
||||
* 27-Jul-2005 BJD Ensure maximum frequency of i2c bus
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
@ -59,6 +61,7 @@
|
||||
#include <asm/arch/regs-mem.h>
|
||||
#include <asm/arch/regs-lcd.h>
|
||||
#include <asm/arch/nand.h>
|
||||
#include <asm/arch/iic.h>
|
||||
|
||||
#include <linux/mtd/mtd.h>
|
||||
#include <linux/mtd/nand.h>
|
||||
@ -116,7 +119,6 @@ static struct map_desc bast_iodesc[] __initdata = {
|
||||
/* slow, byte */
|
||||
{ VA_C2(BAST_VA_ISAIO), PA_CS2(BAST_PA_ISAIO), SZ_16M, MT_DEVICE },
|
||||
{ VA_C2(BAST_VA_ISAMEM), PA_CS2(BAST_PA_ISAMEM), SZ_16M, MT_DEVICE },
|
||||
{ VA_C2(BAST_VA_ASIXNET), PA_CS3(BAST_PA_ASIXNET), SZ_1M, MT_DEVICE },
|
||||
{ VA_C2(BAST_VA_SUPERIO), PA_CS2(BAST_PA_SUPERIO), SZ_1M, MT_DEVICE },
|
||||
{ VA_C2(BAST_VA_IDEPRI), PA_CS3(BAST_PA_IDEPRI), SZ_1M, MT_DEVICE },
|
||||
{ VA_C2(BAST_VA_IDESEC), PA_CS3(BAST_PA_IDESEC), SZ_1M, MT_DEVICE },
|
||||
@ -126,7 +128,6 @@ static struct map_desc bast_iodesc[] __initdata = {
|
||||
/* slow, word */
|
||||
{ VA_C3(BAST_VA_ISAIO), PA_CS3(BAST_PA_ISAIO), SZ_16M, MT_DEVICE },
|
||||
{ VA_C3(BAST_VA_ISAMEM), PA_CS3(BAST_PA_ISAMEM), SZ_16M, MT_DEVICE },
|
||||
{ VA_C3(BAST_VA_ASIXNET), PA_CS3(BAST_PA_ASIXNET), SZ_1M, MT_DEVICE },
|
||||
{ VA_C3(BAST_VA_SUPERIO), PA_CS3(BAST_PA_SUPERIO), SZ_1M, MT_DEVICE },
|
||||
{ VA_C3(BAST_VA_IDEPRI), PA_CS3(BAST_PA_IDEPRI), SZ_1M, MT_DEVICE },
|
||||
{ VA_C3(BAST_VA_IDESEC), PA_CS3(BAST_PA_IDESEC), SZ_1M, MT_DEVICE },
|
||||
@ -136,7 +137,6 @@ static struct map_desc bast_iodesc[] __initdata = {
|
||||
/* fast, byte */
|
||||
{ VA_C4(BAST_VA_ISAIO), PA_CS4(BAST_PA_ISAIO), SZ_16M, MT_DEVICE },
|
||||
{ VA_C4(BAST_VA_ISAMEM), PA_CS4(BAST_PA_ISAMEM), SZ_16M, MT_DEVICE },
|
||||
{ VA_C4(BAST_VA_ASIXNET), PA_CS5(BAST_PA_ASIXNET), SZ_1M, MT_DEVICE },
|
||||
{ VA_C4(BAST_VA_SUPERIO), PA_CS4(BAST_PA_SUPERIO), SZ_1M, MT_DEVICE },
|
||||
{ VA_C4(BAST_VA_IDEPRI), PA_CS5(BAST_PA_IDEPRI), SZ_1M, MT_DEVICE },
|
||||
{ VA_C4(BAST_VA_IDESEC), PA_CS5(BAST_PA_IDESEC), SZ_1M, MT_DEVICE },
|
||||
@ -146,7 +146,6 @@ static struct map_desc bast_iodesc[] __initdata = {
|
||||
/* fast, word */
|
||||
{ VA_C5(BAST_VA_ISAIO), PA_CS5(BAST_PA_ISAIO), SZ_16M, MT_DEVICE },
|
||||
{ VA_C5(BAST_VA_ISAMEM), PA_CS5(BAST_PA_ISAMEM), SZ_16M, MT_DEVICE },
|
||||
{ VA_C5(BAST_VA_ASIXNET), PA_CS5(BAST_PA_ASIXNET), SZ_1M, MT_DEVICE },
|
||||
{ VA_C5(BAST_VA_SUPERIO), PA_CS5(BAST_PA_SUPERIO), SZ_1M, MT_DEVICE },
|
||||
{ VA_C5(BAST_VA_IDEPRI), PA_CS5(BAST_PA_IDEPRI), SZ_1M, MT_DEVICE },
|
||||
{ VA_C5(BAST_VA_IDESEC), PA_CS5(BAST_PA_IDESEC), SZ_1M, MT_DEVICE },
|
||||
@ -307,7 +306,7 @@ static void bast_nand_select(struct s3c2410_nand_set *set, int slot)
|
||||
}
|
||||
|
||||
static struct s3c2410_platform_nand bast_nand_info = {
|
||||
.tacls = 80,
|
||||
.tacls = 40,
|
||||
.twrph0 = 80,
|
||||
.twrph1 = 80,
|
||||
.nr_sets = ARRAY_SIZE(bast_nand_sets),
|
||||
@ -388,6 +387,17 @@ static struct platform_device bast_sio = {
|
||||
},
|
||||
};
|
||||
|
||||
/* we have devices on the bus which cannot work much over the
|
||||
* standard 100KHz i2c bus frequency
|
||||
*/
|
||||
|
||||
static struct s3c2410_platform_i2c bast_i2c_info = {
|
||||
.flags = 0,
|
||||
.slave_addr = 0x10,
|
||||
.bus_freq = 100*1000,
|
||||
.max_freq = 130*1000,
|
||||
};
|
||||
|
||||
/* Standard BAST devices */
|
||||
|
||||
static struct platform_device *bast_devices[] __initdata = {
|
||||
@ -434,6 +444,7 @@ void __init bast_map_io(void)
|
||||
s3c24xx_uclk.parent = &s3c24xx_clkout1;
|
||||
|
||||
s3c_device_nand.dev.platform_data = &bast_nand_info;
|
||||
s3c_device_i2c.dev.platform_data = &bast_i2c_info;
|
||||
|
||||
s3c24xx_init_io(bast_iodesc, ARRAY_SIZE(bast_iodesc));
|
||||
s3c24xx_init_clocks(0);
|
||||
|
116
arch/arm/mach-s3c2410/s3c2440-clock.c
Normal file
116
arch/arm/mach-s3c2410/s3c2440-clock.c
Normal file
@ -0,0 +1,116 @@
|
||||
/* linux/arch/arm/mach-s3c2410/s3c2440-clock.c
|
||||
*
|
||||
* Copyright (c) 2004-2005 Simtec Electronics
|
||||
* http://armlinux.simtec.co.uk/
|
||||
* Ben Dooks <ben@simtec.co.uk>
|
||||
*
|
||||
* S3C2440 Clock support
|
||||
*
|
||||
* 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 program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/sysdev.h>
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/ioport.h>
|
||||
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#include <asm/hardware/clock.h>
|
||||
#include <asm/arch/regs-clock.h>
|
||||
|
||||
#include "clock.h"
|
||||
#include "cpu.h"
|
||||
|
||||
/* S3C2440 extended clock support */
|
||||
|
||||
static struct clk s3c2440_clk_upll = {
|
||||
.name = "upll",
|
||||
.id = -1,
|
||||
};
|
||||
|
||||
static struct clk s3c2440_clk_cam = {
|
||||
.name = "camif",
|
||||
.id = -1,
|
||||
.enable = s3c24xx_clkcon_enable,
|
||||
.ctrlbit = S3C2440_CLKCON_CAMERA,
|
||||
};
|
||||
|
||||
static struct clk s3c2440_clk_ac97 = {
|
||||
.name = "ac97",
|
||||
.id = -1,
|
||||
.enable = s3c24xx_clkcon_enable,
|
||||
.ctrlbit = S3C2440_CLKCON_CAMERA,
|
||||
};
|
||||
|
||||
static int s3c2440_clk_add(struct sys_device *sysdev)
|
||||
{
|
||||
unsigned long upllcon = __raw_readl(S3C2410_UPLLCON);
|
||||
struct clk *clk_h;
|
||||
struct clk *clk_p;
|
||||
struct clk *clk_xtal;
|
||||
|
||||
clk_xtal = clk_get(NULL, "xtal");
|
||||
if (IS_ERR(clk_xtal)) {
|
||||
printk(KERN_ERR "S3C2440: Failed to get clk_xtal\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
s3c2440_clk_upll.rate = s3c2410_get_pll(upllcon, clk_xtal->rate);
|
||||
|
||||
printk("S3C2440: Clock Support, UPLL %ld.%03ld MHz\n",
|
||||
print_mhz(s3c2440_clk_upll.rate));
|
||||
|
||||
clk_p = clk_get(NULL, "pclk");
|
||||
clk_h = clk_get(NULL, "hclk");
|
||||
|
||||
if (IS_ERR(clk_p) || IS_ERR(clk_h)) {
|
||||
printk(KERN_ERR "S3C2440: Failed to get parent clocks\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
s3c2440_clk_cam.parent = clk_h;
|
||||
s3c2440_clk_ac97.parent = clk_p;
|
||||
|
||||
s3c24xx_register_clock(&s3c2440_clk_ac97);
|
||||
s3c24xx_register_clock(&s3c2440_clk_cam);
|
||||
s3c24xx_register_clock(&s3c2440_clk_upll);
|
||||
|
||||
clk_disable(&s3c2440_clk_ac97);
|
||||
clk_disable(&s3c2440_clk_cam);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct sysdev_driver s3c2440_clk_driver = {
|
||||
.add = s3c2440_clk_add,
|
||||
};
|
||||
|
||||
static __init int s3c24xx_clk_driver(void)
|
||||
{
|
||||
return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_clk_driver);
|
||||
}
|
||||
|
||||
arch_initcall(s3c24xx_clk_driver);
|
207
arch/arm/mach-s3c2410/s3c2440-irq.c
Normal file
207
arch/arm/mach-s3c2410/s3c2440-irq.c
Normal file
@ -0,0 +1,207 @@
|
||||
/* linux/arch/arm/mach-s3c2410/s3c2440-irq.c
|
||||
*
|
||||
* Copyright (c) 2003,2004 Simtec Electronics
|
||||
* 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 as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Changelog:
|
||||
* 25-Jul-2005 BJD Split from irq.c
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/sysdev.h>
|
||||
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#include <asm/mach/irq.h>
|
||||
|
||||
#include <asm/arch/regs-irq.h>
|
||||
#include <asm/arch/regs-gpio.h>
|
||||
|
||||
#include "cpu.h"
|
||||
#include "pm.h"
|
||||
#include "irq.h"
|
||||
|
||||
/* WDT/AC97 */
|
||||
|
||||
static void s3c_irq_demux_wdtac97(unsigned int irq,
|
||||
struct irqdesc *desc,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
unsigned int subsrc, submsk;
|
||||
struct irqdesc *mydesc;
|
||||
|
||||
/* read the current pending interrupts, and the mask
|
||||
* for what it is available */
|
||||
|
||||
subsrc = __raw_readl(S3C2410_SUBSRCPND);
|
||||
submsk = __raw_readl(S3C2410_INTSUBMSK);
|
||||
|
||||
subsrc &= ~submsk;
|
||||
subsrc >>= 13;
|
||||
subsrc &= 3;
|
||||
|
||||
if (subsrc != 0) {
|
||||
if (subsrc & 1) {
|
||||
mydesc = irq_desc + IRQ_S3C2440_WDT;
|
||||
mydesc->handle( IRQ_S3C2440_WDT, mydesc, regs);
|
||||
}
|
||||
if (subsrc & 2) {
|
||||
mydesc = irq_desc + IRQ_S3C2440_AC97;
|
||||
mydesc->handle(IRQ_S3C2440_AC97, mydesc, regs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define INTMSK_WDT (1UL << (IRQ_WDT - IRQ_EINT0))
|
||||
|
||||
static void
|
||||
s3c_irq_wdtac97_mask(unsigned int irqno)
|
||||
{
|
||||
s3c_irqsub_mask(irqno, INTMSK_WDT, 3<<13);
|
||||
}
|
||||
|
||||
static void
|
||||
s3c_irq_wdtac97_unmask(unsigned int irqno)
|
||||
{
|
||||
s3c_irqsub_unmask(irqno, INTMSK_WDT);
|
||||
}
|
||||
|
||||
static void
|
||||
s3c_irq_wdtac97_ack(unsigned int irqno)
|
||||
{
|
||||
s3c_irqsub_maskack(irqno, INTMSK_WDT, 3<<13);
|
||||
}
|
||||
|
||||
static struct irqchip s3c_irq_wdtac97 = {
|
||||
.mask = s3c_irq_wdtac97_mask,
|
||||
.unmask = s3c_irq_wdtac97_unmask,
|
||||
.ack = s3c_irq_wdtac97_ack,
|
||||
};
|
||||
|
||||
/* camera irq */
|
||||
|
||||
static void s3c_irq_demux_cam(unsigned int irq,
|
||||
struct irqdesc *desc,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
unsigned int subsrc, submsk;
|
||||
struct irqdesc *mydesc;
|
||||
|
||||
/* read the current pending interrupts, and the mask
|
||||
* for what it is available */
|
||||
|
||||
subsrc = __raw_readl(S3C2410_SUBSRCPND);
|
||||
submsk = __raw_readl(S3C2410_INTSUBMSK);
|
||||
|
||||
subsrc &= ~submsk;
|
||||
subsrc >>= 11;
|
||||
subsrc &= 3;
|
||||
|
||||
if (subsrc != 0) {
|
||||
if (subsrc & 1) {
|
||||
mydesc = irq_desc + IRQ_S3C2440_CAM_C;
|
||||
mydesc->handle( IRQ_S3C2440_WDT, mydesc, regs);
|
||||
}
|
||||
if (subsrc & 2) {
|
||||
mydesc = irq_desc + IRQ_S3C2440_CAM_P;
|
||||
mydesc->handle(IRQ_S3C2440_AC97, mydesc, regs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define INTMSK_CAM (1UL << (IRQ_CAM - IRQ_EINT0))
|
||||
|
||||
static void
|
||||
s3c_irq_cam_mask(unsigned int irqno)
|
||||
{
|
||||
s3c_irqsub_mask(irqno, INTMSK_CAM, 3<<11);
|
||||
}
|
||||
|
||||
static void
|
||||
s3c_irq_cam_unmask(unsigned int irqno)
|
||||
{
|
||||
s3c_irqsub_unmask(irqno, INTMSK_CAM);
|
||||
}
|
||||
|
||||
static void
|
||||
s3c_irq_cam_ack(unsigned int irqno)
|
||||
{
|
||||
s3c_irqsub_maskack(irqno, INTMSK_CAM, 3<<11);
|
||||
}
|
||||
|
||||
static struct irqchip s3c_irq_cam = {
|
||||
.mask = s3c_irq_cam_mask,
|
||||
.unmask = s3c_irq_cam_unmask,
|
||||
.ack = s3c_irq_cam_ack,
|
||||
};
|
||||
|
||||
static int s3c2440_irq_add(struct sys_device *sysdev)
|
||||
{
|
||||
unsigned int irqno;
|
||||
|
||||
printk("S3C2440: IRQ Support\n");
|
||||
|
||||
set_irq_chip(IRQ_NFCON, &s3c_irq_level_chip);
|
||||
set_irq_handler(IRQ_NFCON, do_level_IRQ);
|
||||
set_irq_flags(IRQ_NFCON, IRQF_VALID);
|
||||
|
||||
/* add new chained handler for wdt, ac7 */
|
||||
|
||||
set_irq_chip(IRQ_WDT, &s3c_irq_level_chip);
|
||||
set_irq_handler(IRQ_WDT, do_level_IRQ);
|
||||
set_irq_chained_handler(IRQ_WDT, s3c_irq_demux_wdtac97);
|
||||
|
||||
for (irqno = IRQ_S3C2440_WDT; irqno <= IRQ_S3C2440_AC97; irqno++) {
|
||||
set_irq_chip(irqno, &s3c_irq_wdtac97);
|
||||
set_irq_handler(irqno, do_level_IRQ);
|
||||
set_irq_flags(irqno, IRQF_VALID);
|
||||
}
|
||||
|
||||
/* add chained handler for camera */
|
||||
|
||||
set_irq_chip(IRQ_CAM, &s3c_irq_level_chip);
|
||||
set_irq_handler(IRQ_CAM, do_level_IRQ);
|
||||
set_irq_chained_handler(IRQ_CAM, s3c_irq_demux_cam);
|
||||
|
||||
for (irqno = IRQ_S3C2440_CAM_C; irqno <= IRQ_S3C2440_CAM_P; irqno++) {
|
||||
set_irq_chip(irqno, &s3c_irq_cam);
|
||||
set_irq_handler(irqno, do_level_IRQ);
|
||||
set_irq_flags(irqno, IRQF_VALID);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct sysdev_driver s3c2440_irq_driver = {
|
||||
.add = s3c2440_irq_add,
|
||||
};
|
||||
|
||||
static int s3c24xx_irq_driver(void)
|
||||
{
|
||||
return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_irq_driver);
|
||||
}
|
||||
|
||||
arch_initcall(s3c24xx_irq_driver);
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* linux/arch/arm/mach-s3c2410/usb-simtec.c
|
||||
*
|
||||
* Copyright (c) 2004 Simtec Electronics
|
||||
* Copyright (c) 2004,2005 Simtec Electronics
|
||||
* Ben Dooks <ben@simtec.co.uk>
|
||||
*
|
||||
* http://www.simtec.co.uk/products/EB2410ITX/
|
||||
@ -14,6 +14,8 @@
|
||||
* Modifications:
|
||||
* 14-Sep-2004 BJD Created
|
||||
* 18-Oct-2004 BJD Cleanups, and added code to report OC cleared
|
||||
* 09-Aug-2005 BJD Renamed s3c2410_report_oc to s3c2410_usb_report_oc
|
||||
* 09-Aug-2005 BJD Ports powered only if both are enabled
|
||||
*/
|
||||
|
||||
#define DEBUG
|
||||
@ -47,13 +49,19 @@
|
||||
* designed boards.
|
||||
*/
|
||||
|
||||
static unsigned int power_state[2];
|
||||
|
||||
static void
|
||||
usb_simtec_powercontrol(int port, int to)
|
||||
{
|
||||
pr_debug("usb_simtec_powercontrol(%d,%d)\n", port, to);
|
||||
|
||||
if (port == 1)
|
||||
s3c2410_gpio_setpin(S3C2410_GPB4, to ? 0:1);
|
||||
power_state[port] = to;
|
||||
|
||||
if (power_state[0] && power_state[1])
|
||||
s3c2410_gpio_setpin(S3C2410_GPB4, 0);
|
||||
else
|
||||
s3c2410_gpio_setpin(S3C2410_GPB4, 1);
|
||||
}
|
||||
|
||||
static irqreturn_t
|
||||
@ -63,10 +71,10 @@ usb_simtec_ocirq(int irq, void *pw, struct pt_regs *regs)
|
||||
|
||||
if (s3c2410_gpio_getpin(S3C2410_GPG10) == 0) {
|
||||
pr_debug("usb_simtec: over-current irq (oc detected)\n");
|
||||
s3c2410_report_oc(info, 3);
|
||||
s3c2410_usb_report_oc(info, 3);
|
||||
} else {
|
||||
pr_debug("usb_simtec: over-current irq (oc cleared)\n");
|
||||
s3c2410_report_oc(info, 0);
|
||||
s3c2410_usb_report_oc(info, 0);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
|
@ -97,6 +97,7 @@ static void __init jornada720_map_io(void)
|
||||
}
|
||||
|
||||
MACHINE_START(JORNADA720, "HP Jornada 720")
|
||||
/* Maintainer: Michael Gernoth <michael@gernoth.net> */
|
||||
.phys_ram = 0xc0000000,
|
||||
.phys_io = 0x80000000,
|
||||
.io_pg_offst = ((0xf8000000) >> 18) & 0xfffc,
|
||||
|
@ -238,9 +238,9 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
|
||||
up_read(&mm->mmap_sem);
|
||||
|
||||
/*
|
||||
* Handle the "normal" case first
|
||||
* Handle the "normal" case first - VM_FAULT_MAJOR / VM_FAULT_MINOR
|
||||
*/
|
||||
if (fault > 0)
|
||||
if (fault >= VM_FAULT_MINOR)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
@ -261,7 +261,7 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
|
||||
do_exit(SIGKILL);
|
||||
return 0;
|
||||
|
||||
case 0:
|
||||
case VM_FAULT_SIGBUS:
|
||||
/*
|
||||
* We had some memory, but were unable to
|
||||
* successfully fix up this page fault.
|
||||
|
@ -383,6 +383,7 @@ static void __init build_mem_type_table(void)
|
||||
{
|
||||
struct cachepolicy *cp;
|
||||
unsigned int cr = get_cr();
|
||||
unsigned int user_pgprot;
|
||||
int cpu_arch = cpu_architecture();
|
||||
int i;
|
||||
|
||||
@ -408,6 +409,9 @@ static void __init build_mem_type_table(void)
|
||||
}
|
||||
}
|
||||
|
||||
cp = &cache_policies[cachepolicy];
|
||||
user_pgprot = cp->pte;
|
||||
|
||||
/*
|
||||
* ARMv6 and above have extended page tables.
|
||||
*/
|
||||
@ -425,9 +429,19 @@ static void __init build_mem_type_table(void)
|
||||
mem_types[MT_ROM].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
|
||||
mem_types[MT_MINICLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
|
||||
mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
|
||||
}
|
||||
|
||||
cp = &cache_policies[cachepolicy];
|
||||
/*
|
||||
* Mark the device area as "shared device"
|
||||
*/
|
||||
mem_types[MT_DEVICE].prot_pte |= L_PTE_BUFFERABLE;
|
||||
mem_types[MT_DEVICE].prot_sect |= PMD_SECT_BUFFERED;
|
||||
|
||||
/*
|
||||
* User pages need to be mapped with the ASID
|
||||
* (iow, non-global)
|
||||
*/
|
||||
user_pgprot |= L_PTE_ASID;
|
||||
}
|
||||
|
||||
if (cpu_arch >= CPU_ARCH_ARMv5) {
|
||||
mem_types[MT_LOW_VECTORS].prot_pte |= cp->pte & PTE_CACHEABLE;
|
||||
@ -445,7 +459,7 @@ static void __init build_mem_type_table(void)
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
unsigned long v = pgprot_val(protection_map[i]);
|
||||
v &= (~(PTE_BUFFERABLE|PTE_CACHEABLE)) | cp->pte;
|
||||
v &= (~(PTE_BUFFERABLE|PTE_CACHEABLE)) | user_pgprot;
|
||||
protection_map[i] = __pgprot(v);
|
||||
}
|
||||
|
||||
|
@ -111,12 +111,6 @@ ENTRY(cpu_v6_switch_mm)
|
||||
mcr p15, 0, r1, c13, c0, 1 @ set context ID
|
||||
mov pc, lr
|
||||
|
||||
#define nG (1 << 11)
|
||||
#define APX (1 << 9)
|
||||
#define AP1 (1 << 5)
|
||||
#define AP0 (1 << 4)
|
||||
#define XN (1 << 0)
|
||||
|
||||
/*
|
||||
* cpu_v6_set_pte(ptep, pte)
|
||||
*
|
||||
@ -139,24 +133,24 @@ ENTRY(cpu_v6_switch_mm)
|
||||
ENTRY(cpu_v6_set_pte)
|
||||
str r1, [r0], #-2048 @ linux version
|
||||
|
||||
bic r2, r1, #0x00000ff0
|
||||
bic r2, r1, #0x000007f0
|
||||
bic r2, r2, #0x00000003
|
||||
orr r2, r2, #AP0 | 2
|
||||
orr r2, r2, #PTE_EXT_AP0 | 2
|
||||
|
||||
tst r1, #L_PTE_WRITE
|
||||
tstne r1, #L_PTE_DIRTY
|
||||
orreq r2, r2, #APX
|
||||
orreq r2, r2, #PTE_EXT_APX
|
||||
|
||||
tst r1, #L_PTE_USER
|
||||
orrne r2, r2, #AP1 | nG
|
||||
tstne r2, #APX
|
||||
bicne r2, r2, #APX | AP0
|
||||
orrne r2, r2, #PTE_EXT_AP1
|
||||
tstne r2, #PTE_EXT_APX
|
||||
bicne r2, r2, #PTE_EXT_APX | PTE_EXT_AP0
|
||||
|
||||
tst r1, #L_PTE_YOUNG
|
||||
biceq r2, r2, #APX | AP1 | AP0
|
||||
biceq r2, r2, #PTE_EXT_APX | PTE_EXT_AP_MASK
|
||||
|
||||
@ tst r1, #L_PTE_EXEC
|
||||
@ orreq r2, r2, #XN
|
||||
@ orreq r2, r2, #PTE_EXT_XN
|
||||
|
||||
tst r1, #L_PTE_PRESENT
|
||||
moveq r2, #0
|
||||
|
@ -370,142 +370,6 @@ ENTRY(cpu_xscale_dcache_clean_area)
|
||||
bhi 1b
|
||||
mov pc, lr
|
||||
|
||||
/* ================================ CACHE LOCKING============================
|
||||
*
|
||||
* The XScale MicroArchitecture implements support for locking entries into
|
||||
* the data and instruction cache. The following functions implement the core
|
||||
* low level instructions needed to accomplish the locking. The developer's
|
||||
* manual states that the code that performs the locking must be in non-cached
|
||||
* memory. To accomplish this, the code in xscale-cache-lock.c copies the
|
||||
* following functions from the cache into a non-cached memory region that
|
||||
* is allocated through consistent_alloc().
|
||||
*
|
||||
*/
|
||||
.align 5
|
||||
/*
|
||||
* xscale_icache_lock
|
||||
*
|
||||
* r0: starting address to lock
|
||||
* r1: end address to lock
|
||||
*/
|
||||
ENTRY(xscale_icache_lock)
|
||||
|
||||
iLockLoop:
|
||||
bic r0, r0, #CACHELINESIZE - 1
|
||||
mcr p15, 0, r0, c9, c1, 0 @ lock into cache
|
||||
cmp r0, r1 @ are we done?
|
||||
add r0, r0, #CACHELINESIZE @ advance to next cache line
|
||||
bls iLockLoop
|
||||
mov pc, lr
|
||||
|
||||
/*
|
||||
* xscale_icache_unlock
|
||||
*/
|
||||
ENTRY(xscale_icache_unlock)
|
||||
mcr p15, 0, r0, c9, c1, 1 @ Unlock icache
|
||||
mov pc, lr
|
||||
|
||||
/*
|
||||
* xscale_dcache_lock
|
||||
*
|
||||
* r0: starting address to lock
|
||||
* r1: end address to lock
|
||||
*/
|
||||
ENTRY(xscale_dcache_lock)
|
||||
mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
|
||||
mov r2, #1
|
||||
mcr p15, 0, r2, c9, c2, 0 @ Put dcache in lock mode
|
||||
cpwait ip @ Wait for completion
|
||||
|
||||
mrs r2, cpsr
|
||||
orr r3, r2, #PSR_F_BIT | PSR_I_BIT
|
||||
dLockLoop:
|
||||
msr cpsr_c, r3
|
||||
mcr p15, 0, r0, c7, c10, 1 @ Write back line if it is dirty
|
||||
mcr p15, 0, r0, c7, c6, 1 @ Flush/invalidate line
|
||||
msr cpsr_c, r2
|
||||
ldr ip, [r0], #CACHELINESIZE @ Preload 32 bytes into cache from
|
||||
@ location [r0]. Post-increment
|
||||
@ r3 to next cache line
|
||||
cmp r0, r1 @ Are we done?
|
||||
bls dLockLoop
|
||||
|
||||
mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
|
||||
mov r2, #0
|
||||
mcr p15, 0, r2, c9, c2, 0 @ Get out of lock mode
|
||||
cpwait_ret lr, ip
|
||||
|
||||
/*
|
||||
* xscale_dcache_unlock
|
||||
*/
|
||||
ENTRY(xscale_dcache_unlock)
|
||||
mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
|
||||
mcr p15, 0, ip, c9, c2, 1 @ Unlock cache
|
||||
mov pc, lr
|
||||
|
||||
/*
|
||||
* Needed to determine the length of the code that needs to be copied.
|
||||
*/
|
||||
.align 5
|
||||
ENTRY(xscale_cache_dummy)
|
||||
mov pc, lr
|
||||
|
||||
/* ================================ TLB LOCKING==============================
|
||||
*
|
||||
* The XScale MicroArchitecture implements support for locking entries into
|
||||
* the Instruction and Data TLBs. The following functions provide the
|
||||
* low level support for supporting these under Linux. xscale-lock.c
|
||||
* implements some higher level management code. Most of the following
|
||||
* is taken straight out of the Developer's Manual.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Lock I-TLB entry
|
||||
*
|
||||
* r0: Virtual address to translate and lock
|
||||
*/
|
||||
.align 5
|
||||
ENTRY(xscale_itlb_lock)
|
||||
mrs r2, cpsr
|
||||
orr r3, r2, #PSR_F_BIT | PSR_I_BIT
|
||||
msr cpsr_c, r3 @ Disable interrupts
|
||||
mcr p15, 0, r0, c8, c5, 1 @ Invalidate I-TLB entry
|
||||
mcr p15, 0, r0, c10, c4, 0 @ Translate and lock
|
||||
msr cpsr_c, r2 @ Restore interrupts
|
||||
cpwait_ret lr, ip
|
||||
|
||||
/*
|
||||
* Lock D-TLB entry
|
||||
*
|
||||
* r0: Virtual address to translate and lock
|
||||
*/
|
||||
.align 5
|
||||
ENTRY(xscale_dtlb_lock)
|
||||
mrs r2, cpsr
|
||||
orr r3, r2, #PSR_F_BIT | PSR_I_BIT
|
||||
msr cpsr_c, r3 @ Disable interrupts
|
||||
mcr p15, 0, r0, c8, c6, 1 @ Invalidate D-TLB entry
|
||||
mcr p15, 0, r0, c10, c8, 0 @ Translate and lock
|
||||
msr cpsr_c, r2 @ Restore interrupts
|
||||
cpwait_ret lr, ip
|
||||
|
||||
/*
|
||||
* Unlock all I-TLB entries
|
||||
*/
|
||||
.align 5
|
||||
ENTRY(xscale_itlb_unlock)
|
||||
mcr p15, 0, ip, c10, c4, 1 @ Unlock I-TLB
|
||||
mcr p15, 0, ip, c8, c5, 0 @ Invalidate I-TLB
|
||||
cpwait_ret lr, ip
|
||||
|
||||
/*
|
||||
* Unlock all D-TLB entries
|
||||
*/
|
||||
ENTRY(xscale_dtlb_unlock)
|
||||
mcr p15, 0, ip, c10, c8, 1 @ Unlock D-TBL
|
||||
mcr p15, 0, ip, c8, c6, 0 @ Invalidate D-TLB
|
||||
cpwait_ret lr, ip
|
||||
|
||||
/* =============================== PageTable ============================== */
|
||||
|
||||
#define PTE_CACHE_WRITE_ALLOCATE 0
|
||||
|
@ -40,17 +40,17 @@ float64 float64_arccos(float64 rFm);
|
||||
float64 float64_pow(float64 rFn, float64 rFm);
|
||||
float64 float64_pol(float64 rFn, float64 rFm);
|
||||
|
||||
static float64 float64_rsf(float64 rFn, float64 rFm)
|
||||
static float64 float64_rsf(struct roundingData *roundData, float64 rFn, float64 rFm)
|
||||
{
|
||||
return float64_sub(rFm, rFn);
|
||||
return float64_sub(roundData, rFm, rFn);
|
||||
}
|
||||
|
||||
static float64 float64_rdv(float64 rFn, float64 rFm)
|
||||
static float64 float64_rdv(struct roundingData *roundData, float64 rFn, float64 rFm)
|
||||
{
|
||||
return float64_div(rFm, rFn);
|
||||
return float64_div(roundData, rFm, rFn);
|
||||
}
|
||||
|
||||
static float64 (*const dyadic_double[16])(float64 rFn, float64 rFm) = {
|
||||
static float64 (*const dyadic_double[16])(struct roundingData*, float64 rFn, float64 rFm) = {
|
||||
[ADF_CODE >> 20] = float64_add,
|
||||
[MUF_CODE >> 20] = float64_mul,
|
||||
[SUF_CODE >> 20] = float64_sub,
|
||||
@ -65,12 +65,12 @@ static float64 (*const dyadic_double[16])(float64 rFn, float64 rFm) = {
|
||||
[FRD_CODE >> 20] = float64_rdv,
|
||||
};
|
||||
|
||||
static float64 float64_mvf(float64 rFm)
|
||||
static float64 float64_mvf(struct roundingData *roundData,float64 rFm)
|
||||
{
|
||||
return rFm;
|
||||
}
|
||||
|
||||
static float64 float64_mnf(float64 rFm)
|
||||
static float64 float64_mnf(struct roundingData *roundData,float64 rFm)
|
||||
{
|
||||
union float64_components u;
|
||||
|
||||
@ -84,7 +84,7 @@ static float64 float64_mnf(float64 rFm)
|
||||
return u.f64;
|
||||
}
|
||||
|
||||
static float64 float64_abs(float64 rFm)
|
||||
static float64 float64_abs(struct roundingData *roundData,float64 rFm)
|
||||
{
|
||||
union float64_components u;
|
||||
|
||||
@ -98,7 +98,7 @@ static float64 float64_abs(float64 rFm)
|
||||
return u.f64;
|
||||
}
|
||||
|
||||
static float64 (*const monadic_double[16])(float64 rFm) = {
|
||||
static float64 (*const monadic_double[16])(struct roundingData *, float64 rFm) = {
|
||||
[MVF_CODE >> 20] = float64_mvf,
|
||||
[MNF_CODE >> 20] = float64_mnf,
|
||||
[ABS_CODE >> 20] = float64_abs,
|
||||
@ -108,7 +108,7 @@ static float64 (*const monadic_double[16])(float64 rFm) = {
|
||||
[NRM_CODE >> 20] = float64_mvf,
|
||||
};
|
||||
|
||||
unsigned int DoubleCPDO(const unsigned int opcode, FPREG * rFd)
|
||||
unsigned int DoubleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd)
|
||||
{
|
||||
FPA11 *fpa11 = GET_FPA11();
|
||||
float64 rFm;
|
||||
@ -151,13 +151,13 @@ unsigned int DoubleCPDO(const unsigned int opcode, FPREG * rFd)
|
||||
}
|
||||
|
||||
if (dyadic_double[opc_mask_shift]) {
|
||||
rFd->fDouble = dyadic_double[opc_mask_shift](rFn, rFm);
|
||||
rFd->fDouble = dyadic_double[opc_mask_shift](roundData, rFn, rFm);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (monadic_double[opc_mask_shift]) {
|
||||
rFd->fDouble = monadic_double[opc_mask_shift](rFm);
|
||||
rFd->fDouble = monadic_double[opc_mask_shift](roundData, rFm);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
@ -35,17 +35,17 @@ floatx80 floatx80_arccos(floatx80 rFm);
|
||||
floatx80 floatx80_pow(floatx80 rFn, floatx80 rFm);
|
||||
floatx80 floatx80_pol(floatx80 rFn, floatx80 rFm);
|
||||
|
||||
static floatx80 floatx80_rsf(floatx80 rFn, floatx80 rFm)
|
||||
static floatx80 floatx80_rsf(struct roundingData *roundData, floatx80 rFn, floatx80 rFm)
|
||||
{
|
||||
return floatx80_sub(rFm, rFn);
|
||||
return floatx80_sub(roundData, rFm, rFn);
|
||||
}
|
||||
|
||||
static floatx80 floatx80_rdv(floatx80 rFn, floatx80 rFm)
|
||||
static floatx80 floatx80_rdv(struct roundingData *roundData, floatx80 rFn, floatx80 rFm)
|
||||
{
|
||||
return floatx80_div(rFm, rFn);
|
||||
return floatx80_div(roundData, rFm, rFn);
|
||||
}
|
||||
|
||||
static floatx80 (*const dyadic_extended[16])(floatx80 rFn, floatx80 rFm) = {
|
||||
static floatx80 (*const dyadic_extended[16])(struct roundingData*, floatx80 rFn, floatx80 rFm) = {
|
||||
[ADF_CODE >> 20] = floatx80_add,
|
||||
[MUF_CODE >> 20] = floatx80_mul,
|
||||
[SUF_CODE >> 20] = floatx80_sub,
|
||||
@ -60,24 +60,24 @@ static floatx80 (*const dyadic_extended[16])(floatx80 rFn, floatx80 rFm) = {
|
||||
[FRD_CODE >> 20] = floatx80_rdv,
|
||||
};
|
||||
|
||||
static floatx80 floatx80_mvf(floatx80 rFm)
|
||||
static floatx80 floatx80_mvf(struct roundingData *roundData, floatx80 rFm)
|
||||
{
|
||||
return rFm;
|
||||
}
|
||||
|
||||
static floatx80 floatx80_mnf(floatx80 rFm)
|
||||
static floatx80 floatx80_mnf(struct roundingData *roundData, floatx80 rFm)
|
||||
{
|
||||
rFm.high ^= 0x8000;
|
||||
return rFm;
|
||||
}
|
||||
|
||||
static floatx80 floatx80_abs(floatx80 rFm)
|
||||
static floatx80 floatx80_abs(struct roundingData *roundData, floatx80 rFm)
|
||||
{
|
||||
rFm.high &= 0x7fff;
|
||||
return rFm;
|
||||
}
|
||||
|
||||
static floatx80 (*const monadic_extended[16])(floatx80 rFm) = {
|
||||
static floatx80 (*const monadic_extended[16])(struct roundingData*, floatx80 rFm) = {
|
||||
[MVF_CODE >> 20] = floatx80_mvf,
|
||||
[MNF_CODE >> 20] = floatx80_mnf,
|
||||
[ABS_CODE >> 20] = floatx80_abs,
|
||||
@ -87,7 +87,7 @@ static floatx80 (*const monadic_extended[16])(floatx80 rFm) = {
|
||||
[NRM_CODE >> 20] = floatx80_mvf,
|
||||
};
|
||||
|
||||
unsigned int ExtendedCPDO(const unsigned int opcode, FPREG * rFd)
|
||||
unsigned int ExtendedCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd)
|
||||
{
|
||||
FPA11 *fpa11 = GET_FPA11();
|
||||
floatx80 rFm;
|
||||
@ -138,13 +138,13 @@ unsigned int ExtendedCPDO(const unsigned int opcode, FPREG * rFd)
|
||||
}
|
||||
|
||||
if (dyadic_extended[opc_mask_shift]) {
|
||||
rFd->fExtended = dyadic_extended[opc_mask_shift](rFn, rFm);
|
||||
rFd->fExtended = dyadic_extended[opc_mask_shift](roundData, rFn, rFm);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (monadic_extended[opc_mask_shift]) {
|
||||
rFd->fExtended = monadic_extended[opc_mask_shift](rFm);
|
||||
rFd->fExtended = monadic_extended[opc_mask_shift](roundData, rFm);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
@ -51,48 +51,42 @@ static void resetFPA11(void)
|
||||
fpa11->fpsr = FP_EMULATOR | BIT_AC;
|
||||
}
|
||||
|
||||
void SetRoundingMode(const unsigned int opcode)
|
||||
int8 SetRoundingMode(const unsigned int opcode)
|
||||
{
|
||||
switch (opcode & MASK_ROUNDING_MODE) {
|
||||
default:
|
||||
case ROUND_TO_NEAREST:
|
||||
float_rounding_mode = float_round_nearest_even;
|
||||
break;
|
||||
return float_round_nearest_even;
|
||||
|
||||
case ROUND_TO_PLUS_INFINITY:
|
||||
float_rounding_mode = float_round_up;
|
||||
break;
|
||||
return float_round_up;
|
||||
|
||||
case ROUND_TO_MINUS_INFINITY:
|
||||
float_rounding_mode = float_round_down;
|
||||
break;
|
||||
return float_round_down;
|
||||
|
||||
case ROUND_TO_ZERO:
|
||||
float_rounding_mode = float_round_to_zero;
|
||||
break;
|
||||
return float_round_to_zero;
|
||||
}
|
||||
}
|
||||
|
||||
void SetRoundingPrecision(const unsigned int opcode)
|
||||
int8 SetRoundingPrecision(const unsigned int opcode)
|
||||
{
|
||||
#ifdef CONFIG_FPE_NWFPE_XP
|
||||
switch (opcode & MASK_ROUNDING_PRECISION) {
|
||||
case ROUND_SINGLE:
|
||||
floatx80_rounding_precision = 32;
|
||||
break;
|
||||
return 32;
|
||||
|
||||
case ROUND_DOUBLE:
|
||||
floatx80_rounding_precision = 64;
|
||||
break;
|
||||
return 64;
|
||||
|
||||
case ROUND_EXTENDED:
|
||||
floatx80_rounding_precision = 80;
|
||||
break;
|
||||
return 80;
|
||||
|
||||
default:
|
||||
floatx80_rounding_precision = 80;
|
||||
return 80;
|
||||
}
|
||||
#endif
|
||||
return 80;
|
||||
}
|
||||
|
||||
void nwfpe_init_fpa(union fp_state *fp)
|
||||
@ -103,8 +97,6 @@ void nwfpe_init_fpa(union fp_state *fp)
|
||||
#endif
|
||||
memset(fpa11, 0, sizeof(FPA11));
|
||||
resetFPA11();
|
||||
SetRoundingMode(ROUND_TO_NEAREST);
|
||||
SetRoundingPrecision(ROUND_EXTENDED);
|
||||
fpa11->initflag = 1;
|
||||
}
|
||||
|
||||
|
@ -37,6 +37,13 @@
|
||||
/* includes */
|
||||
#include "fpsr.h" /* FP control and status register definitions */
|
||||
#include "milieu.h"
|
||||
|
||||
struct roundingData {
|
||||
int8 mode;
|
||||
int8 precision;
|
||||
signed char exception;
|
||||
};
|
||||
|
||||
#include "softfloat.h"
|
||||
|
||||
#define typeNone 0x00
|
||||
@ -84,8 +91,8 @@ typedef struct tagFPA11 {
|
||||
initialised. */
|
||||
} FPA11;
|
||||
|
||||
extern void SetRoundingMode(const unsigned int);
|
||||
extern void SetRoundingPrecision(const unsigned int);
|
||||
extern int8 SetRoundingMode(const unsigned int);
|
||||
extern int8 SetRoundingPrecision(const unsigned int);
|
||||
extern void nwfpe_init_fpa(union fp_state *fp);
|
||||
|
||||
#endif
|
||||
|
@ -24,15 +24,16 @@
|
||||
#include "fpa11.h"
|
||||
#include "fpopcode.h"
|
||||
|
||||
unsigned int SingleCPDO(const unsigned int opcode, FPREG * rFd);
|
||||
unsigned int DoubleCPDO(const unsigned int opcode, FPREG * rFd);
|
||||
unsigned int ExtendedCPDO(const unsigned int opcode, FPREG * rFd);
|
||||
unsigned int SingleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd);
|
||||
unsigned int DoubleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd);
|
||||
unsigned int ExtendedCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd);
|
||||
|
||||
unsigned int EmulateCPDO(const unsigned int opcode)
|
||||
{
|
||||
FPA11 *fpa11 = GET_FPA11();
|
||||
FPREG *rFd;
|
||||
unsigned int nType, nDest, nRc;
|
||||
struct roundingData roundData;
|
||||
|
||||
/* Get the destination size. If not valid let Linux perform
|
||||
an invalid instruction trap. */
|
||||
@ -40,7 +41,9 @@ unsigned int EmulateCPDO(const unsigned int opcode)
|
||||
if (typeNone == nDest)
|
||||
return 0;
|
||||
|
||||
SetRoundingMode(opcode);
|
||||
roundData.mode = SetRoundingMode(opcode);
|
||||
roundData.precision = SetRoundingPrecision(opcode);
|
||||
roundData.exception = 0;
|
||||
|
||||
/* Compare the size of the operands in Fn and Fm.
|
||||
Choose the largest size and perform operations in that size,
|
||||
@ -63,14 +66,14 @@ unsigned int EmulateCPDO(const unsigned int opcode)
|
||||
|
||||
switch (nType) {
|
||||
case typeSingle:
|
||||
nRc = SingleCPDO(opcode, rFd);
|
||||
nRc = SingleCPDO(&roundData, opcode, rFd);
|
||||
break;
|
||||
case typeDouble:
|
||||
nRc = DoubleCPDO(opcode, rFd);
|
||||
nRc = DoubleCPDO(&roundData, opcode, rFd);
|
||||
break;
|
||||
#ifdef CONFIG_FPE_NWFPE_XP
|
||||
case typeExtended:
|
||||
nRc = ExtendedCPDO(opcode, rFd);
|
||||
nRc = ExtendedCPDO(&roundData, opcode, rFd);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
@ -93,9 +96,9 @@ unsigned int EmulateCPDO(const unsigned int opcode)
|
||||
case typeSingle:
|
||||
{
|
||||
if (typeDouble == nType)
|
||||
rFd->fSingle = float64_to_float32(rFd->fDouble);
|
||||
rFd->fSingle = float64_to_float32(&roundData, rFd->fDouble);
|
||||
else
|
||||
rFd->fSingle = floatx80_to_float32(rFd->fExtended);
|
||||
rFd->fSingle = floatx80_to_float32(&roundData, rFd->fExtended);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -104,7 +107,7 @@ unsigned int EmulateCPDO(const unsigned int opcode)
|
||||
if (typeSingle == nType)
|
||||
rFd->fDouble = float32_to_float64(rFd->fSingle);
|
||||
else
|
||||
rFd->fDouble = floatx80_to_float64(rFd->fExtended);
|
||||
rFd->fDouble = floatx80_to_float64(&roundData, rFd->fExtended);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -121,12 +124,15 @@ unsigned int EmulateCPDO(const unsigned int opcode)
|
||||
#else
|
||||
if (nDest != nType) {
|
||||
if (nDest == typeSingle)
|
||||
rFd->fSingle = float64_to_float32(rFd->fDouble);
|
||||
rFd->fSingle = float64_to_float32(&roundData, rFd->fDouble);
|
||||
else
|
||||
rFd->fDouble = float32_to_float64(rFd->fSingle);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (roundData.exception)
|
||||
float_raise(roundData.exception);
|
||||
|
||||
return nRc;
|
||||
}
|
||||
|
@ -96,7 +96,7 @@ static inline void loadMultiple(const unsigned int Fn, const unsigned int __user
|
||||
}
|
||||
}
|
||||
|
||||
static inline void storeSingle(const unsigned int Fn, unsigned int __user *pMem)
|
||||
static inline void storeSingle(struct roundingData *roundData, const unsigned int Fn, unsigned int __user *pMem)
|
||||
{
|
||||
FPA11 *fpa11 = GET_FPA11();
|
||||
union {
|
||||
@ -106,12 +106,12 @@ static inline void storeSingle(const unsigned int Fn, unsigned int __user *pMem)
|
||||
|
||||
switch (fpa11->fType[Fn]) {
|
||||
case typeDouble:
|
||||
val.f = float64_to_float32(fpa11->fpreg[Fn].fDouble);
|
||||
val.f = float64_to_float32(roundData, fpa11->fpreg[Fn].fDouble);
|
||||
break;
|
||||
|
||||
#ifdef CONFIG_FPE_NWFPE_XP
|
||||
case typeExtended:
|
||||
val.f = floatx80_to_float32(fpa11->fpreg[Fn].fExtended);
|
||||
val.f = floatx80_to_float32(roundData, fpa11->fpreg[Fn].fExtended);
|
||||
break;
|
||||
#endif
|
||||
|
||||
@ -122,7 +122,7 @@ static inline void storeSingle(const unsigned int Fn, unsigned int __user *pMem)
|
||||
put_user(val.i[0], pMem);
|
||||
}
|
||||
|
||||
static inline void storeDouble(const unsigned int Fn, unsigned int __user *pMem)
|
||||
static inline void storeDouble(struct roundingData *roundData, const unsigned int Fn, unsigned int __user *pMem)
|
||||
{
|
||||
FPA11 *fpa11 = GET_FPA11();
|
||||
union {
|
||||
@ -137,7 +137,7 @@ static inline void storeDouble(const unsigned int Fn, unsigned int __user *pMem)
|
||||
|
||||
#ifdef CONFIG_FPE_NWFPE_XP
|
||||
case typeExtended:
|
||||
val.f = floatx80_to_float64(fpa11->fpreg[Fn].fExtended);
|
||||
val.f = floatx80_to_float64(roundData, fpa11->fpreg[Fn].fExtended);
|
||||
break;
|
||||
#endif
|
||||
|
||||
@ -259,8 +259,11 @@ unsigned int PerformSTF(const unsigned int opcode)
|
||||
{
|
||||
unsigned int __user *pBase, *pAddress, *pFinal;
|
||||
unsigned int nRc = 1, write_back = WRITE_BACK(opcode);
|
||||
struct roundingData roundData;
|
||||
|
||||
SetRoundingMode(ROUND_TO_NEAREST);
|
||||
roundData.mode = SetRoundingMode(opcode);
|
||||
roundData.precision = SetRoundingPrecision(opcode);
|
||||
roundData.exception = 0;
|
||||
|
||||
pBase = (unsigned int __user *) readRegister(getRn(opcode));
|
||||
if (REG_PC == getRn(opcode)) {
|
||||
@ -281,10 +284,10 @@ unsigned int PerformSTF(const unsigned int opcode)
|
||||
|
||||
switch (opcode & MASK_TRANSFER_LENGTH) {
|
||||
case TRANSFER_SINGLE:
|
||||
storeSingle(getFd(opcode), pAddress);
|
||||
storeSingle(&roundData, getFd(opcode), pAddress);
|
||||
break;
|
||||
case TRANSFER_DOUBLE:
|
||||
storeDouble(getFd(opcode), pAddress);
|
||||
storeDouble(&roundData, getFd(opcode), pAddress);
|
||||
break;
|
||||
#ifdef CONFIG_FPE_NWFPE_XP
|
||||
case TRANSFER_EXTENDED:
|
||||
@ -295,6 +298,9 @@ unsigned int PerformSTF(const unsigned int opcode)
|
||||
nRc = 0;
|
||||
}
|
||||
|
||||
if (roundData.exception)
|
||||
float_raise(roundData.exception);
|
||||
|
||||
if (write_back)
|
||||
writeRegister(getRn(opcode), (unsigned long) pFinal);
|
||||
return nRc;
|
||||
|
@ -33,8 +33,6 @@ extern flag floatx80_is_nan(floatx80);
|
||||
extern flag float64_is_nan(float64);
|
||||
extern flag float32_is_nan(float32);
|
||||
|
||||
void SetRoundingMode(const unsigned int opcode);
|
||||
|
||||
unsigned int PerformFLT(const unsigned int opcode);
|
||||
unsigned int PerformFIX(const unsigned int opcode);
|
||||
|
||||
@ -77,14 +75,17 @@ unsigned int EmulateCPRT(const unsigned int opcode)
|
||||
unsigned int PerformFLT(const unsigned int opcode)
|
||||
{
|
||||
FPA11 *fpa11 = GET_FPA11();
|
||||
SetRoundingMode(opcode);
|
||||
SetRoundingPrecision(opcode);
|
||||
struct roundingData roundData;
|
||||
|
||||
roundData.mode = SetRoundingMode(opcode);
|
||||
roundData.precision = SetRoundingPrecision(opcode);
|
||||
roundData.exception = 0;
|
||||
|
||||
switch (opcode & MASK_ROUNDING_PRECISION) {
|
||||
case ROUND_SINGLE:
|
||||
{
|
||||
fpa11->fType[getFn(opcode)] = typeSingle;
|
||||
fpa11->fpreg[getFn(opcode)].fSingle = int32_to_float32(readRegister(getRd(opcode)));
|
||||
fpa11->fpreg[getFn(opcode)].fSingle = int32_to_float32(&roundData, readRegister(getRd(opcode)));
|
||||
}
|
||||
break;
|
||||
|
||||
@ -108,6 +109,9 @@ unsigned int PerformFLT(const unsigned int opcode)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (roundData.exception)
|
||||
float_raise(roundData.exception);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -115,26 +119,29 @@ unsigned int PerformFIX(const unsigned int opcode)
|
||||
{
|
||||
FPA11 *fpa11 = GET_FPA11();
|
||||
unsigned int Fn = getFm(opcode);
|
||||
struct roundingData roundData;
|
||||
|
||||
SetRoundingMode(opcode);
|
||||
roundData.mode = SetRoundingMode(opcode);
|
||||
roundData.precision = SetRoundingPrecision(opcode);
|
||||
roundData.exception = 0;
|
||||
|
||||
switch (fpa11->fType[Fn]) {
|
||||
case typeSingle:
|
||||
{
|
||||
writeRegister(getRd(opcode), float32_to_int32(fpa11->fpreg[Fn].fSingle));
|
||||
writeRegister(getRd(opcode), float32_to_int32(&roundData, fpa11->fpreg[Fn].fSingle));
|
||||
}
|
||||
break;
|
||||
|
||||
case typeDouble:
|
||||
{
|
||||
writeRegister(getRd(opcode), float64_to_int32(fpa11->fpreg[Fn].fDouble));
|
||||
writeRegister(getRd(opcode), float64_to_int32(&roundData, fpa11->fpreg[Fn].fDouble));
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef CONFIG_FPE_NWFPE_XP
|
||||
case typeExtended:
|
||||
{
|
||||
writeRegister(getRd(opcode), floatx80_to_int32(fpa11->fpreg[Fn].fExtended));
|
||||
writeRegister(getRd(opcode), floatx80_to_int32(&roundData, fpa11->fpreg[Fn].fExtended));
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
@ -143,6 +150,9 @@ unsigned int PerformFIX(const unsigned int opcode)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (roundData.exception)
|
||||
float_raise(roundData.exception);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -116,8 +116,6 @@ fpmodule.c to integrate with the NetBSD kernel (I hope!).
|
||||
code to access data in user space in some other source files at the
|
||||
moment (grep for get_user / put_user calls). --philb]
|
||||
|
||||
float_exception_flags is a global variable in SoftFloat.
|
||||
|
||||
This function is called by the SoftFloat routines to raise a floating
|
||||
point exception. We check the trap enable byte in the FPSR, and raise
|
||||
a SIGFPE exception if necessary. If not the relevant bits in the
|
||||
@ -129,15 +127,14 @@ void float_raise(signed char flags)
|
||||
register unsigned int fpsr, cumulativeTraps;
|
||||
|
||||
#ifdef CONFIG_DEBUG_USER
|
||||
printk(KERN_DEBUG
|
||||
"NWFPE: %s[%d] takes exception %08x at %p from %08lx\n",
|
||||
current->comm, current->pid, flags,
|
||||
__builtin_return_address(0), GET_USERREG()->ARM_pc);
|
||||
/* Ignore inexact errors as there are far too many of them to log */
|
||||
if (flags & ~BIT_IXC)
|
||||
printk(KERN_DEBUG
|
||||
"NWFPE: %s[%d] takes exception %08x at %p from %08lx\n",
|
||||
current->comm, current->pid, flags,
|
||||
__builtin_return_address(0), GET_USERREG()->ARM_pc);
|
||||
#endif
|
||||
|
||||
/* Keep SoftFloat exception flags up to date. */
|
||||
float_exception_flags |= flags;
|
||||
|
||||
/* Read fpsr and initialize the cumulativeTraps. */
|
||||
fpsr = readFPSR();
|
||||
cumulativeTraps = 0;
|
||||
|
@ -36,17 +36,17 @@ float32 float32_arccos(float32 rFm);
|
||||
float32 float32_pow(float32 rFn, float32 rFm);
|
||||
float32 float32_pol(float32 rFn, float32 rFm);
|
||||
|
||||
static float32 float32_rsf(float32 rFn, float32 rFm)
|
||||
static float32 float32_rsf(struct roundingData *roundData, float32 rFn, float32 rFm)
|
||||
{
|
||||
return float32_sub(rFm, rFn);
|
||||
return float32_sub(roundData, rFm, rFn);
|
||||
}
|
||||
|
||||
static float32 float32_rdv(float32 rFn, float32 rFm)
|
||||
static float32 float32_rdv(struct roundingData *roundData, float32 rFn, float32 rFm)
|
||||
{
|
||||
return float32_div(rFm, rFn);
|
||||
return float32_div(roundData, rFm, rFn);
|
||||
}
|
||||
|
||||
static float32 (*const dyadic_single[16])(float32 rFn, float32 rFm) = {
|
||||
static float32 (*const dyadic_single[16])(struct roundingData *, float32 rFn, float32 rFm) = {
|
||||
[ADF_CODE >> 20] = float32_add,
|
||||
[MUF_CODE >> 20] = float32_mul,
|
||||
[SUF_CODE >> 20] = float32_sub,
|
||||
@ -60,22 +60,22 @@ static float32 (*const dyadic_single[16])(float32 rFn, float32 rFm) = {
|
||||
[FRD_CODE >> 20] = float32_rdv,
|
||||
};
|
||||
|
||||
static float32 float32_mvf(float32 rFm)
|
||||
static float32 float32_mvf(struct roundingData *roundData, float32 rFm)
|
||||
{
|
||||
return rFm;
|
||||
}
|
||||
|
||||
static float32 float32_mnf(float32 rFm)
|
||||
static float32 float32_mnf(struct roundingData *roundData, float32 rFm)
|
||||
{
|
||||
return rFm ^ 0x80000000;
|
||||
}
|
||||
|
||||
static float32 float32_abs(float32 rFm)
|
||||
static float32 float32_abs(struct roundingData *roundData, float32 rFm)
|
||||
{
|
||||
return rFm & 0x7fffffff;
|
||||
}
|
||||
|
||||
static float32 (*const monadic_single[16])(float32 rFm) = {
|
||||
static float32 (*const monadic_single[16])(struct roundingData*, float32 rFm) = {
|
||||
[MVF_CODE >> 20] = float32_mvf,
|
||||
[MNF_CODE >> 20] = float32_mnf,
|
||||
[ABS_CODE >> 20] = float32_abs,
|
||||
@ -85,7 +85,7 @@ static float32 (*const monadic_single[16])(float32 rFm) = {
|
||||
[NRM_CODE >> 20] = float32_mvf,
|
||||
};
|
||||
|
||||
unsigned int SingleCPDO(const unsigned int opcode, FPREG * rFd)
|
||||
unsigned int SingleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd)
|
||||
{
|
||||
FPA11 *fpa11 = GET_FPA11();
|
||||
float32 rFm;
|
||||
@ -108,13 +108,13 @@ unsigned int SingleCPDO(const unsigned int opcode, FPREG * rFd)
|
||||
if (fpa11->fType[Fn] == typeSingle &&
|
||||
dyadic_single[opc_mask_shift]) {
|
||||
rFn = fpa11->fpreg[Fn].fSingle;
|
||||
rFd->fSingle = dyadic_single[opc_mask_shift](rFn, rFm);
|
||||
rFd->fSingle = dyadic_single[opc_mask_shift](roundData, rFn, rFm);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (monadic_single[opc_mask_shift]) {
|
||||
rFd->fSingle = monadic_single[opc_mask_shift](rFm);
|
||||
rFd->fSingle = monadic_single[opc_mask_shift](roundData, rFm);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -74,7 +74,7 @@ enum {
|
||||
Software IEC/IEEE floating-point rounding mode.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
extern signed char float_rounding_mode;
|
||||
//extern int8 float_rounding_mode;
|
||||
enum {
|
||||
float_round_nearest_even = 0,
|
||||
float_round_to_zero = 1,
|
||||
@ -86,7 +86,6 @@ enum {
|
||||
-------------------------------------------------------------------------------
|
||||
Software IEC/IEEE floating-point exception flags.
|
||||
-------------------------------------------------------------------------------
|
||||
extern signed char float_exception_flags;
|
||||
enum {
|
||||
float_flag_inexact = 1,
|
||||
float_flag_underflow = 2,
|
||||
@ -99,7 +98,6 @@ ScottB: November 4, 1998
|
||||
Changed the enumeration to match the bit order in the FPA11.
|
||||
*/
|
||||
|
||||
extern signed char float_exception_flags;
|
||||
enum {
|
||||
float_flag_invalid = 1,
|
||||
float_flag_divbyzero = 2,
|
||||
@ -121,7 +119,7 @@ void float_raise( signed char );
|
||||
Software IEC/IEEE integer-to-floating-point conversion routines.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
float32 int32_to_float32( signed int );
|
||||
float32 int32_to_float32( struct roundingData *, signed int );
|
||||
float64 int32_to_float64( signed int );
|
||||
#ifdef FLOATX80
|
||||
floatx80 int32_to_floatx80( signed int );
|
||||
@ -132,7 +130,7 @@ floatx80 int32_to_floatx80( signed int );
|
||||
Software IEC/IEEE single-precision conversion routines.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
signed int float32_to_int32( float32 );
|
||||
signed int float32_to_int32( struct roundingData *, float32 );
|
||||
signed int float32_to_int32_round_to_zero( float32 );
|
||||
float64 float32_to_float64( float32 );
|
||||
#ifdef FLOATX80
|
||||
@ -144,13 +142,13 @@ floatx80 float32_to_floatx80( float32 );
|
||||
Software IEC/IEEE single-precision operations.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
float32 float32_round_to_int( float32 );
|
||||
float32 float32_add( float32, float32 );
|
||||
float32 float32_sub( float32, float32 );
|
||||
float32 float32_mul( float32, float32 );
|
||||
float32 float32_div( float32, float32 );
|
||||
float32 float32_rem( float32, float32 );
|
||||
float32 float32_sqrt( float32 );
|
||||
float32 float32_round_to_int( struct roundingData*, float32 );
|
||||
float32 float32_add( struct roundingData *, float32, float32 );
|
||||
float32 float32_sub( struct roundingData *, float32, float32 );
|
||||
float32 float32_mul( struct roundingData *, float32, float32 );
|
||||
float32 float32_div( struct roundingData *, float32, float32 );
|
||||
float32 float32_rem( struct roundingData *, float32, float32 );
|
||||
float32 float32_sqrt( struct roundingData*, float32 );
|
||||
char float32_eq( float32, float32 );
|
||||
char float32_le( float32, float32 );
|
||||
char float32_lt( float32, float32 );
|
||||
@ -164,9 +162,9 @@ char float32_is_signaling_nan( float32 );
|
||||
Software IEC/IEEE double-precision conversion routines.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
signed int float64_to_int32( float64 );
|
||||
signed int float64_to_int32( struct roundingData *, float64 );
|
||||
signed int float64_to_int32_round_to_zero( float64 );
|
||||
float32 float64_to_float32( float64 );
|
||||
float32 float64_to_float32( struct roundingData *, float64 );
|
||||
#ifdef FLOATX80
|
||||
floatx80 float64_to_floatx80( float64 );
|
||||
#endif
|
||||
@ -176,13 +174,13 @@ floatx80 float64_to_floatx80( float64 );
|
||||
Software IEC/IEEE double-precision operations.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
float64 float64_round_to_int( float64 );
|
||||
float64 float64_add( float64, float64 );
|
||||
float64 float64_sub( float64, float64 );
|
||||
float64 float64_mul( float64, float64 );
|
||||
float64 float64_div( float64, float64 );
|
||||
float64 float64_rem( float64, float64 );
|
||||
float64 float64_sqrt( float64 );
|
||||
float64 float64_round_to_int( struct roundingData *, float64 );
|
||||
float64 float64_add( struct roundingData *, float64, float64 );
|
||||
float64 float64_sub( struct roundingData *, float64, float64 );
|
||||
float64 float64_mul( struct roundingData *, float64, float64 );
|
||||
float64 float64_div( struct roundingData *, float64, float64 );
|
||||
float64 float64_rem( struct roundingData *, float64, float64 );
|
||||
float64 float64_sqrt( struct roundingData *, float64 );
|
||||
char float64_eq( float64, float64 );
|
||||
char float64_le( float64, float64 );
|
||||
char float64_lt( float64, float64 );
|
||||
@ -198,31 +196,23 @@ char float64_is_signaling_nan( float64 );
|
||||
Software IEC/IEEE extended double-precision conversion routines.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
signed int floatx80_to_int32( floatx80 );
|
||||
signed int floatx80_to_int32( struct roundingData *, floatx80 );
|
||||
signed int floatx80_to_int32_round_to_zero( floatx80 );
|
||||
float32 floatx80_to_float32( floatx80 );
|
||||
float64 floatx80_to_float64( floatx80 );
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Software IEC/IEEE extended double-precision rounding precision. Valid
|
||||
values are 32, 64, and 80.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
extern signed char floatx80_rounding_precision;
|
||||
float32 floatx80_to_float32( struct roundingData *, floatx80 );
|
||||
float64 floatx80_to_float64( struct roundingData *, floatx80 );
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Software IEC/IEEE extended double-precision operations.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
floatx80 floatx80_round_to_int( floatx80 );
|
||||
floatx80 floatx80_add( floatx80, floatx80 );
|
||||
floatx80 floatx80_sub( floatx80, floatx80 );
|
||||
floatx80 floatx80_mul( floatx80, floatx80 );
|
||||
floatx80 floatx80_div( floatx80, floatx80 );
|
||||
floatx80 floatx80_rem( floatx80, floatx80 );
|
||||
floatx80 floatx80_sqrt( floatx80 );
|
||||
floatx80 floatx80_round_to_int( struct roundingData *, floatx80 );
|
||||
floatx80 floatx80_add( struct roundingData *, floatx80, floatx80 );
|
||||
floatx80 floatx80_sub( struct roundingData *, floatx80, floatx80 );
|
||||
floatx80 floatx80_mul( struct roundingData *, floatx80, floatx80 );
|
||||
floatx80 floatx80_div( struct roundingData *, floatx80, floatx80 );
|
||||
floatx80 floatx80_rem( struct roundingData *, floatx80, floatx80 );
|
||||
floatx80 floatx80_sqrt( struct roundingData *, floatx80 );
|
||||
char floatx80_eq( floatx80, floatx80 );
|
||||
char floatx80_le( floatx80, floatx80 );
|
||||
char floatx80_lt( floatx80, floatx80 );
|
||||
|
@ -115,7 +115,7 @@ static int valid_kernel_stack(struct frame_tail *tail, struct pt_regs *regs)
|
||||
return (tailaddr > stack) && (tailaddr < stack_base);
|
||||
}
|
||||
|
||||
void arm_backtrace(struct pt_regs const *regs, unsigned int depth)
|
||||
void arm_backtrace(struct pt_regs * const regs, unsigned int depth)
|
||||
{
|
||||
struct frame_tail *tail;
|
||||
unsigned long last_address = 0;
|
||||
|
@ -770,6 +770,9 @@ vfp_double_add(struct vfp_double *vdd, struct vfp_double *vdn,
|
||||
if ((s64)m_sig < 0) {
|
||||
vdd->sign = vfp_sign_negate(vdd->sign);
|
||||
m_sig = -m_sig;
|
||||
} else if (m_sig == 0) {
|
||||
vdd->sign = (fpscr & FPSCR_RMODE_MASK) ==
|
||||
FPSCR_ROUND_MINUSINF ? 0x8000 : 0;
|
||||
}
|
||||
} else {
|
||||
m_sig += vdn->significand;
|
||||
|
@ -103,9 +103,6 @@ void machine_power_off(void)
|
||||
{
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(machine_halt);
|
||||
EXPORT_SYMBOL(machine_power_off);
|
||||
|
||||
void machine_restart(char * __unused)
|
||||
{
|
||||
/*
|
||||
@ -136,8 +133,6 @@ void machine_restart(char * __unused)
|
||||
while (1);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(machine_restart);
|
||||
|
||||
void show_regs(struct pt_regs * regs)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
@ -176,12 +176,12 @@ survive:
|
||||
* Handle the "normal" cases first - successful and sigbus
|
||||
*/
|
||||
switch (fault) {
|
||||
case 2:
|
||||
case VM_FAULT_MAJOR:
|
||||
tsk->maj_flt++;
|
||||
return fault;
|
||||
case 1:
|
||||
case VM_FAULT_MINOR:
|
||||
tsk->min_flt++;
|
||||
case 0:
|
||||
case VM_FAULT_SIGBUS:
|
||||
return fault;
|
||||
}
|
||||
|
||||
@ -226,14 +226,11 @@ int do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
|
||||
/*
|
||||
* Handle the "normal" case first
|
||||
*/
|
||||
if (fault > 0)
|
||||
switch (fault) {
|
||||
case VM_FAULT_MINOR:
|
||||
case VM_FAULT_MAJOR:
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* We had some memory, but were unable to
|
||||
* successfully fix up this page fault.
|
||||
*/
|
||||
if (fault == 0){
|
||||
case VM_FAULT_SIGBUS:
|
||||
goto do_sigbus;
|
||||
}
|
||||
|
||||
|
@ -38,4 +38,9 @@ config FRAME_POINTER
|
||||
If you don't debug the kernel, you can say N, but we may not be able
|
||||
to solve problems without frame pointers.
|
||||
|
||||
config DEBUG_NMI_OOPS
|
||||
bool "NMI causes oops printout"
|
||||
help
|
||||
If the system locks up without any debug information you can say Y
|
||||
here to make it possible to dump an OOPS with an external NMI.
|
||||
endmenu
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $Id: Makefile,v 1.23 2004/10/19 13:07:34 starvik Exp $
|
||||
# $Id: Makefile,v 1.28 2005/03/17 10:44:37 larsv Exp $
|
||||
# cris/Makefile
|
||||
#
|
||||
# This file is included by the global makefile so that you can add your own
|
||||
@ -15,6 +15,7 @@
|
||||
|
||||
arch-y := v10
|
||||
arch-$(CONFIG_ETRAX_ARCH_V10) := v10
|
||||
arch-$(CONFIG_ETRAX_ARCH_V32) := v32
|
||||
|
||||
# No config avaiable for make clean etc
|
||||
ifneq ($(arch-y),)
|
||||
@ -46,6 +47,21 @@ core-y += arch/$(ARCH)/$(SARCH)/kernel/ arch/$(ARCH)/$(SARCH)/mm/
|
||||
drivers-y += arch/$(ARCH)/$(SARCH)/drivers/
|
||||
libs-y += arch/$(ARCH)/$(SARCH)/lib/ $(LIBGCC)
|
||||
|
||||
# cris source path
|
||||
SRC_ARCH = $(srctree)/arch/$(ARCH)
|
||||
# cris object files path
|
||||
OBJ_ARCH = $(objtree)/arch/$(ARCH)
|
||||
|
||||
target_boot_arch_dir = $(OBJ_ARCH)/$(SARCH)/boot
|
||||
target_boot_dir = $(OBJ_ARCH)/boot
|
||||
src_boot_dir = $(SRC_ARCH)/boot
|
||||
target_compressed_dir = $(OBJ_ARCH)/boot/compressed
|
||||
src_compressed_dir = $(SRC_ARCH)/boot/compressed
|
||||
target_rescue_dir = $(OBJ_ARCH)/boot/rescue
|
||||
src_rescue_dir = $(SRC_ARCH)/boot/rescue
|
||||
|
||||
export target_boot_arch_dir target_boot_dir src_boot_dir target_compressed_dir src_compressed_dir target_rescue_dir src_rescue_dir
|
||||
|
||||
vmlinux.bin: vmlinux
|
||||
$(OBJCOPY) $(OBJCOPYFLAGS) vmlinux vmlinux.bin
|
||||
|
||||
@ -65,44 +81,52 @@ cramfs:
|
||||
|
||||
clinux: vmlinux.bin decompress.bin rescue.bin
|
||||
|
||||
decompress.bin: FORCE
|
||||
@make -C arch/$(ARCH)/boot/compressed decompress.bin
|
||||
decompress.bin: $(target_boot_dir)
|
||||
@$(MAKE) -f $(src_compressed_dir)/Makefile $(target_compressed_dir)/decompress.bin
|
||||
|
||||
rescue.bin: FORCE
|
||||
@make -C arch/$(ARCH)/boot/rescue rescue.bin
|
||||
$(target_rescue_dir)/rescue.bin: $(target_boot_dir)
|
||||
@$(MAKE) -f $(src_rescue_dir)/Makefile $(target_rescue_dir)/rescue.bin
|
||||
|
||||
zImage: vmlinux.bin rescue.bin
|
||||
zImage: $(target_boot_dir) vmlinux.bin $(target_rescue_dir)/rescue.bin
|
||||
## zImage - Compressed kernel (gzip)
|
||||
@make -C arch/$(ARCH)/boot/ zImage
|
||||
@$(MAKE) -f $(src_boot_dir)/Makefile zImage
|
||||
|
||||
$(target_boot_dir): $(target_boot_arch_dir)
|
||||
ln -sfn $< $@
|
||||
|
||||
$(target_boot_arch_dir):
|
||||
mkdir -p $@
|
||||
|
||||
compressed: zImage
|
||||
|
||||
archmrproper:
|
||||
archclean:
|
||||
$(Q)$(MAKE) $(clean)=arch/$(ARCH)/boot
|
||||
@if [ -d arch/$(ARCH)/boot ]; then \
|
||||
$(MAKE) $(clean)=arch/$(ARCH)/boot ; \
|
||||
fi
|
||||
rm -f timage vmlinux.bin decompress.bin rescue.bin cramfs.img
|
||||
rm -rf $(LD_SCRIPT).tmp
|
||||
|
||||
prepare: arch/$(ARCH)/.links include/asm-$(ARCH)/.arch \
|
||||
prepare: $(SRC_ARCH)/.links $(srctree)/include/asm-$(ARCH)/.arch \
|
||||
include/asm-$(ARCH)/$(SARCH)/offset.h
|
||||
|
||||
# Create some links to make all tools happy
|
||||
arch/$(ARCH)/.links:
|
||||
@rm -rf arch/$(ARCH)/drivers
|
||||
@ln -sfn $(SARCH)/drivers arch/$(ARCH)/drivers
|
||||
@rm -rf arch/$(ARCH)/boot
|
||||
@ln -sfn $(SARCH)/boot arch/$(ARCH)/boot
|
||||
@rm -rf arch/$(ARCH)/lib
|
||||
@ln -sfn $(SARCH)/lib arch/$(ARCH)/lib
|
||||
@ln -sfn $(SARCH) arch/$(ARCH)/arch
|
||||
@ln -sfn ../$(SARCH)/vmlinux.lds.S arch/$(ARCH)/kernel/vmlinux.lds.S
|
||||
$(SRC_ARCH)/.links:
|
||||
@rm -rf $(SRC_ARCH)/drivers
|
||||
@ln -sfn $(SRC_ARCH)/$(SARCH)/drivers $(SRC_ARCH)/drivers
|
||||
@rm -rf $(SRC_ARCH)/boot
|
||||
@ln -sfn $(SRC_ARCH)/$(SARCH)/boot $(SRC_ARCH)/boot
|
||||
@rm -rf $(SRC_ARCH)/lib
|
||||
@ln -sfn $(SRC_ARCH)/$(SARCH)/lib $(SRC_ARCH)/lib
|
||||
@ln -sfn $(SRC_ARCH)/$(SARCH) $(SRC_ARCH)/arch
|
||||
@ln -sfn $(SRC_ARCH)/$(SARCH)/vmlinux.lds.S $(SRC_ARCH)/kernel/vmlinux.lds.S
|
||||
@touch $@
|
||||
|
||||
# Create link to sub arch includes
|
||||
include/asm-$(ARCH)/.arch: $(wildcard include/config/arch/*.h)
|
||||
@echo ' Making asm-$(ARCH)/arch -> asm-$(ARCH)/$(SARCH) symlink'
|
||||
$(srctree)/include/asm-$(ARCH)/.arch: $(wildcard include/config/arch/*.h)
|
||||
@echo ' Making $(srctree)/include/asm-$(ARCH)/arch -> $(srctree)/include/asm-$(ARCH)/$(SARCH) symlink'
|
||||
@rm -f include/asm-$(ARCH)/arch
|
||||
@ln -sf $(SARCH) include/asm-$(ARCH)/arch
|
||||
@ln -sf $(srctree)/include/asm-$(ARCH)/$(SARCH) $(srctree)/include/asm-$(ARCH)/arch
|
||||
@touch $@
|
||||
|
||||
arch/$(ARCH)/$(SARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \
|
||||
|
@ -259,6 +259,37 @@ config ETRAX_DEBUG_PORT_NULL
|
||||
|
||||
endchoice
|
||||
|
||||
choice
|
||||
prompt "Kernel GDB port"
|
||||
depends on ETRAX_KGDB
|
||||
default ETRAX_KGDB_PORT0
|
||||
help
|
||||
Choose a serial port for kernel debugging. NOTE: This port should
|
||||
not be enabled under Drivers for built-in interfaces (as it has its
|
||||
own initialization code) and should not be the same as the debug port.
|
||||
|
||||
config ETRAX_KGDB_PORT0
|
||||
bool "Serial-0"
|
||||
help
|
||||
Use serial port 0 for kernel debugging.
|
||||
|
||||
config ETRAX_KGDB_PORT1
|
||||
bool "Serial-1"
|
||||
help
|
||||
Use serial port 1 for kernel debugging.
|
||||
|
||||
config ETRAX_KGDB_PORT2
|
||||
bool "Serial-2"
|
||||
help
|
||||
Use serial port 2 for kernel debugging.
|
||||
|
||||
config ETRAX_KGDB_PORT3
|
||||
bool "Serial-3"
|
||||
help
|
||||
Use serial port 3 for kernel debugging.
|
||||
|
||||
endchoice
|
||||
|
||||
choice
|
||||
prompt "Product rescue-port"
|
||||
depends on ETRAX_ARCH_V10
|
||||
|
@ -1,12 +1,13 @@
|
||||
#
|
||||
# arch/cris/boot/Makefile
|
||||
#
|
||||
target = $(target_boot_dir)
|
||||
src = $(src_boot_dir)
|
||||
|
||||
zImage: compressed/vmlinuz
|
||||
|
||||
compressed/vmlinuz: $(TOPDIR)/vmlinux
|
||||
@$(MAKE) -C compressed vmlinuz
|
||||
compressed/vmlinuz:
|
||||
@$(MAKE) -f $(src)/compressed/Makefile $(target_compressed_dir)/vmlinuz
|
||||
|
||||
clean:
|
||||
rm -f zImage tools/build compressed/vmlinux.out
|
||||
@$(MAKE) -C compressed clean
|
||||
@$(MAKE) -f $(src)/compressed/Makefile clean
|
||||
|
@ -1,40 +1,45 @@
|
||||
#
|
||||
# linux/arch/etrax100/boot/compressed/Makefile
|
||||
#
|
||||
# create a compressed vmlinux image from the original vmlinux files and romfs
|
||||
# create a compressed vmlinuz image from the binary vmlinux.bin file
|
||||
#
|
||||
target = $(target_compressed_dir)
|
||||
src = $(src_compressed_dir)
|
||||
|
||||
CC = gcc-cris -melf -I $(TOPDIR)/include
|
||||
CC = gcc-cris -melf $(LINUXINCLUDE)
|
||||
CFLAGS = -O2
|
||||
LD = ld-cris
|
||||
OBJCOPY = objcopy-cris
|
||||
OBJCOPYFLAGS = -O binary --remove-section=.bss
|
||||
OBJECTS = head.o misc.o
|
||||
OBJECTS = $(target)/head.o $(target)/misc.o
|
||||
|
||||
# files to compress
|
||||
SYSTEM = $(TOPDIR)/vmlinux.bin
|
||||
SYSTEM = $(objtree)/vmlinux.bin
|
||||
|
||||
all: vmlinuz
|
||||
all: $(target_compressed_dir)/vmlinuz
|
||||
|
||||
decompress.bin: $(OBJECTS)
|
||||
$(LD) -T decompress.ld -o decompress.o $(OBJECTS)
|
||||
$(OBJCOPY) $(OBJCOPYFLAGS) decompress.o decompress.bin
|
||||
# save it for mkprod in the topdir.
|
||||
cp decompress.bin $(TOPDIR)
|
||||
$(target)/decompress.bin: $(OBJECTS)
|
||||
$(LD) -T $(src)/decompress.ld -o $(target)/decompress.o $(OBJECTS)
|
||||
$(OBJCOPY) $(OBJCOPYFLAGS) $(target)/decompress.o $(target)/decompress.bin
|
||||
|
||||
# Create vmlinuz image in top-level build directory
|
||||
$(target_compressed_dir)/vmlinuz: $(target) piggy.img $(target)/decompress.bin
|
||||
@echo " COMPR vmlinux.bin --> vmlinuz"
|
||||
@cat $(target)/decompress.bin piggy.img > $(target_compressed_dir)/vmlinuz
|
||||
@rm -f piggy.img
|
||||
|
||||
vmlinuz: piggy.img decompress.bin
|
||||
cat decompress.bin piggy.img > vmlinuz
|
||||
rm -f piggy.img
|
||||
$(target)/head.o: $(src)/head.S
|
||||
$(CC) -D__ASSEMBLY__ -traditional -c $< -o $@
|
||||
|
||||
head.o: head.S
|
||||
$(CC) -D__ASSEMBLY__ -traditional -c head.S -o head.o
|
||||
$(target)/misc.o: $(src)/misc.c
|
||||
$(CC) -D__KERNEL__ -c $< -o $@
|
||||
|
||||
# gzip the kernel image
|
||||
|
||||
piggy.img: $(SYSTEM)
|
||||
cat $(SYSTEM) | gzip -f -9 > piggy.img
|
||||
@cat $(SYSTEM) | gzip -f -9 > piggy.img
|
||||
|
||||
$(target):
|
||||
mkdir -p $(target)
|
||||
|
||||
clean:
|
||||
rm -f piggy.img vmlinuz vmlinuz.o
|
||||
rm -f piggy.img $(objtree)/vmlinuz
|
||||
|
||||
|
@ -13,7 +13,8 @@
|
||||
#include <asm/arch/sv_addr_ag.h>
|
||||
|
||||
#define RAM_INIT_MAGIC 0x56902387
|
||||
|
||||
#define COMMAND_LINE_MAGIC 0x87109563
|
||||
|
||||
;; Exported symbols
|
||||
|
||||
.globl _input_data
|
||||
@ -88,6 +89,12 @@ basse: move.d pc, r5
|
||||
cmp.d r2, r1
|
||||
bcs 1b
|
||||
nop
|
||||
|
||||
;; Save command line magic and address.
|
||||
move.d _cmd_line_magic, $r12
|
||||
move.d $r10, [$r12]
|
||||
move.d _cmd_line_addr, $r12
|
||||
move.d $r11, [$r12]
|
||||
|
||||
;; Do the decompression and save compressed size in _inptr
|
||||
|
||||
@ -98,7 +105,13 @@ basse: move.d pc, r5
|
||||
|
||||
move.d [_input_data], r9 ; flash address of compressed kernel
|
||||
add.d [_inptr], r9 ; size of compressed kernel
|
||||
|
||||
|
||||
;; Restore command line magic and address.
|
||||
move.d _cmd_line_magic, $r10
|
||||
move.d [$r10], $r10
|
||||
move.d _cmd_line_addr, $r11
|
||||
move.d [$r11], $r11
|
||||
|
||||
;; Enter the decompressed kernel
|
||||
move.d RAM_INIT_MAGIC, r8 ; Tell kernel that DRAM is initialized
|
||||
jump 0x40004000 ; kernel is linked to this address
|
||||
@ -107,5 +120,8 @@ basse: move.d pc, r5
|
||||
|
||||
_input_data:
|
||||
.dword 0 ; used by the decompressor
|
||||
|
||||
_cmd_line_magic:
|
||||
.dword 0
|
||||
_cmd_line_addr:
|
||||
.dword 0
|
||||
#include "../../lib/hw_settings.S"
|
||||
|
@ -1,52 +1,53 @@
|
||||
#
|
||||
# Makefile for rescue code
|
||||
#
|
||||
ifndef TOPDIR
|
||||
TOPDIR = ../../../..
|
||||
endif
|
||||
CC = gcc-cris -mlinux -I $(TOPDIR)/include
|
||||
target = $(target_rescue_dir)
|
||||
src = $(src_rescue_dir)
|
||||
|
||||
CC = gcc-cris -mlinux $(LINUXINCLUDE)
|
||||
CFLAGS = -O2
|
||||
LD = gcc-cris -mlinux -nostdlib
|
||||
OBJCOPY = objcopy-cris
|
||||
OBJCOPYFLAGS = -O binary --remove-section=.bss
|
||||
|
||||
all: rescue.bin testrescue.bin kimagerescue.bin
|
||||
all: $(target)/rescue.bin $(target)/testrescue.bin $(target)/kimagerescue.bin
|
||||
|
||||
rescue: rescue.bin
|
||||
# do nothing
|
||||
$(target)/rescue.bin: $(target) $(target)/head.o
|
||||
$(LD) -T $(src)/rescue.ld -o $(target)/rescue.o $(target)/head.o
|
||||
$(OBJCOPY) $(OBJCOPYFLAGS) $(target)/rescue.o $(target)/rescue.bin
|
||||
# Place a copy in top-level build directory
|
||||
cp -p $(target)/rescue.bin $(objtree)
|
||||
|
||||
rescue.bin: head.o
|
||||
$(LD) -T rescue.ld -o rescue.o head.o
|
||||
$(OBJCOPY) $(OBJCOPYFLAGS) rescue.o rescue.bin
|
||||
cp rescue.bin $(TOPDIR)
|
||||
|
||||
testrescue.bin: testrescue.o
|
||||
$(OBJCOPY) $(OBJCOPYFLAGS) testrescue.o tr.bin
|
||||
$(target)/testrescue.bin: $(target) $(target)/testrescue.o
|
||||
$(OBJCOPY) $(OBJCOPYFLAGS) $(target)/testrescue.o tr.bin
|
||||
# Pad it to 784 bytes
|
||||
dd if=/dev/zero of=tmp2423 bs=1 count=784
|
||||
cat tr.bin tmp2423 >testrescue_tmp.bin
|
||||
dd if=testrescue_tmp.bin of=testrescue.bin bs=1 count=784
|
||||
dd if=testrescue_tmp.bin of=$(target)/testrescue.bin bs=1 count=784
|
||||
rm tr.bin tmp2423 testrescue_tmp.bin
|
||||
|
||||
kimagerescue.bin: kimagerescue.o
|
||||
$(OBJCOPY) $(OBJCOPYFLAGS) kimagerescue.o ktr.bin
|
||||
$(target)/kimagerescue.bin: $(target) $(target)/kimagerescue.o
|
||||
$(OBJCOPY) $(OBJCOPYFLAGS) $(target)/kimagerescue.o ktr.bin
|
||||
# Pad it to 784 bytes, that's what the rescue loader expects
|
||||
dd if=/dev/zero of=tmp2423 bs=1 count=784
|
||||
cat ktr.bin tmp2423 >kimagerescue_tmp.bin
|
||||
dd if=kimagerescue_tmp.bin of=kimagerescue.bin bs=1 count=784
|
||||
dd if=kimagerescue_tmp.bin of=$(target)/kimagerescue.bin bs=1 count=784
|
||||
rm ktr.bin tmp2423 kimagerescue_tmp.bin
|
||||
|
||||
head.o: head.S
|
||||
$(target):
|
||||
mkdir -p $(target)
|
||||
|
||||
$(target)/head.o: $(src)/head.S
|
||||
$(CC) -D__ASSEMBLY__ -traditional -c $< -o $*.o
|
||||
|
||||
testrescue.o: testrescue.S
|
||||
$(target)/testrescue.o: $(src)/testrescue.S
|
||||
$(CC) -D__ASSEMBLY__ -traditional -c $< -o $*.o
|
||||
|
||||
kimagerescue.o: kimagerescue.S
|
||||
$(target)/kimagerescue.o: $(src)/kimagerescue.S
|
||||
$(CC) -D__ASSEMBLY__ -traditional -c $< -o $*.o
|
||||
|
||||
clean:
|
||||
rm -f *.o *.bin
|
||||
rm -f $(target)/*.o $(target)/*.bin
|
||||
|
||||
fastdep:
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $Id: head.S,v 1.6 2003/04/09 08:12:43 pkj Exp $
|
||||
/* $Id: head.S,v 1.7 2005/03/07 12:11:06 starvik Exp $
|
||||
*
|
||||
* Rescue code, made to reside at the beginning of the
|
||||
* flash-memory. when it starts, it checks a partition
|
||||
@ -121,12 +121,13 @@
|
||||
;; 0x80000000 if loaded in flash (as it should be)
|
||||
;; since etrax actually starts at address 2 when booting from flash, we
|
||||
;; put a nop (2 bytes) here first so we dont accidentally skip the di
|
||||
|
||||
|
||||
nop
|
||||
di
|
||||
|
||||
jump in_cache ; enter cached area instead
|
||||
in_cache:
|
||||
in_cache:
|
||||
|
||||
|
||||
;; first put a jump test to give a possibility of upgrading the rescue code
|
||||
;; without erasing/reflashing the sector. we put a longword of -1 here and if
|
||||
@ -325,9 +326,29 @@ flash_ok:
|
||||
;; result will be in r0
|
||||
checksum:
|
||||
moveq 0, $r0
|
||||
1: addu.b [$r1+], $r0
|
||||
subq 1, $r2
|
||||
bne 1b
|
||||
moveq CONFIG_ETRAX_FLASH1_SIZE, $r6
|
||||
|
||||
;; If the first physical flash memory is exceeded wrap to the second one.
|
||||
btstq 26, $r1 ; Are we addressing first flash?
|
||||
bpl 1f
|
||||
nop
|
||||
clear.d $r6
|
||||
|
||||
1: test.d $r6 ; 0 = no wrapping
|
||||
beq 2f
|
||||
nop
|
||||
lslq 20, $r6 ; Convert MB to bytes
|
||||
sub.d $r1, $r6
|
||||
|
||||
2: addu.b [$r1+], $r0
|
||||
subq 1, $r6 ; Flash memory left
|
||||
beq 3f
|
||||
subq 1, $r2 ; Length left
|
||||
bne 2b
|
||||
nop
|
||||
ret
|
||||
nop
|
||||
|
||||
3: move.d MEM_CSE1_START, $r1 ; wrap to second flash
|
||||
ba 2b
|
||||
nop
|
||||
|
@ -1,17 +1,11 @@
|
||||
config ETRAX_ETHERNET
|
||||
bool "Ethernet support"
|
||||
depends on ETRAX_ARCH_V10
|
||||
select NET_ETHERNET
|
||||
help
|
||||
This option enables the ETRAX 100LX built-in 10/100Mbit Ethernet
|
||||
controller.
|
||||
|
||||
# this is just so that the user does not have to go into the
|
||||
# normal ethernet driver section just to enable ethernetworking
|
||||
config NET_ETHERNET
|
||||
bool
|
||||
depends on ETRAX_ETHERNET
|
||||
default y
|
||||
|
||||
choice
|
||||
prompt "Network LED behavior"
|
||||
depends on ETRAX_ETHERNET
|
||||
@ -20,26 +14,26 @@ choice
|
||||
config ETRAX_NETWORK_LED_ON_WHEN_LINK
|
||||
bool "LED_on_when_link"
|
||||
help
|
||||
Selecting LED_on_when_link will light the LED when there is a
|
||||
connection and will flash off when there is activity.
|
||||
Selecting LED_on_when_link will light the LED when there is a
|
||||
connection and will flash off when there is activity.
|
||||
|
||||
Selecting LED_on_when_activity will light the LED only when
|
||||
Selecting LED_on_when_activity will light the LED only when
|
||||
there is activity.
|
||||
|
||||
This setting will also affect the behaviour of other activity LEDs
|
||||
e.g. Bluetooth.
|
||||
This setting will also affect the behaviour of other activity LEDs
|
||||
e.g. Bluetooth.
|
||||
|
||||
config ETRAX_NETWORK_LED_ON_WHEN_ACTIVITY
|
||||
bool "LED_on_when_activity"
|
||||
help
|
||||
Selecting LED_on_when_link will light the LED when there is a
|
||||
connection and will flash off when there is activity.
|
||||
Selecting LED_on_when_link will light the LED when there is a
|
||||
connection and will flash off when there is activity.
|
||||
|
||||
Selecting LED_on_when_activity will light the LED only when
|
||||
Selecting LED_on_when_activity will light the LED only when
|
||||
there is activity.
|
||||
|
||||
This setting will also affect the behaviour of other activity LEDs
|
||||
e.g. Bluetooth.
|
||||
This setting will also affect the behaviour of other activity LEDs
|
||||
e.g. Bluetooth.
|
||||
|
||||
endchoice
|
||||
|
||||
@ -91,11 +85,11 @@ choice
|
||||
depends on ETRAX_SERIAL_PORT0
|
||||
default ETRAX_SERIAL_PORT0_DMA6_OUT
|
||||
|
||||
config CONFIG_ETRAX_SERIAL_PORT0_NO_DMA_OUT
|
||||
bool "No DMA out"
|
||||
config ETRAX_SERIAL_PORT0_NO_DMA_OUT
|
||||
bool "No DMA out"
|
||||
|
||||
config CONFIG_ETRAX_SERIAL_PORT0_DMA6_OUT
|
||||
bool "DMA 6"
|
||||
config ETRAX_SERIAL_PORT0_DMA6_OUT
|
||||
bool "DMA 6"
|
||||
|
||||
endchoice
|
||||
|
||||
@ -104,11 +98,11 @@ choice
|
||||
depends on ETRAX_SERIAL_PORT0
|
||||
default ETRAX_SERIAL_PORT0_DMA7_IN
|
||||
|
||||
config CONFIG_ETRAX_SERIAL_PORT0_NO_DMA_IN
|
||||
bool "No DMA in"
|
||||
config ETRAX_SERIAL_PORT0_NO_DMA_IN
|
||||
bool "No DMA in"
|
||||
|
||||
config CONFIG_ETRAX_SERIAL_PORT0_DMA7_IN
|
||||
bool "DMA 7"
|
||||
config ETRAX_SERIAL_PORT0_DMA7_IN
|
||||
bool "DMA 7"
|
||||
|
||||
endchoice
|
||||
|
||||
@ -205,11 +199,11 @@ choice
|
||||
depends on ETRAX_SERIAL_PORT1
|
||||
default ETRAX_SERIAL_PORT1_DMA8_OUT
|
||||
|
||||
config CONFIG_ETRAX_SERIAL_PORT1_NO_DMA_OUT
|
||||
bool "No DMA out"
|
||||
config ETRAX_SERIAL_PORT1_NO_DMA_OUT
|
||||
bool "No DMA out"
|
||||
|
||||
config CONFIG_ETRAX_SERIAL_PORT1_DMA8_OUT
|
||||
bool "DMA 8"
|
||||
config ETRAX_SERIAL_PORT1_DMA8_OUT
|
||||
bool "DMA 8"
|
||||
|
||||
endchoice
|
||||
|
||||
@ -218,11 +212,11 @@ choice
|
||||
depends on ETRAX_SERIAL_PORT1
|
||||
default ETRAX_SERIAL_PORT1_DMA9_IN
|
||||
|
||||
config CONFIG_ETRAX_SERIAL_PORT1_NO_DMA_IN
|
||||
bool "No DMA in"
|
||||
config ETRAX_SERIAL_PORT1_NO_DMA_IN
|
||||
bool "No DMA in"
|
||||
|
||||
config CONFIG_ETRAX_SERIAL_PORT1_DMA9_IN
|
||||
bool "DMA 9"
|
||||
config ETRAX_SERIAL_PORT1_DMA9_IN
|
||||
bool "DMA 9"
|
||||
|
||||
endchoice
|
||||
|
||||
@ -308,7 +302,7 @@ config ETRAX_SER1_CD_ON_PB_BIT
|
||||
Specify the pin of the PB port to carry the CD signal for serial
|
||||
port 1.
|
||||
|
||||
comment "Make sure you dont have the same PB bits more than once!"
|
||||
comment "Make sure you do not have the same PB bits more than once!"
|
||||
depends on ETRAX_SERIAL && ETRAX_SER0_DTR_RI_DSR_CD_ON_PB && ETRAX_SER1_DTR_RI_DSR_CD_ON_PB
|
||||
|
||||
config ETRAX_SERIAL_PORT2
|
||||
@ -322,11 +316,11 @@ choice
|
||||
depends on ETRAX_SERIAL_PORT2
|
||||
default ETRAX_SERIAL_PORT2_DMA2_OUT
|
||||
|
||||
config CONFIG_ETRAX_SERIAL_PORT2_NO_DMA_OUT
|
||||
bool "No DMA out"
|
||||
config ETRAX_SERIAL_PORT2_NO_DMA_OUT
|
||||
bool "No DMA out"
|
||||
|
||||
config CONFIG_ETRAX_SERIAL_PORT2_DMA2_OUT
|
||||
bool "DMA 2"
|
||||
config ETRAX_SERIAL_PORT2_DMA2_OUT
|
||||
bool "DMA 2"
|
||||
|
||||
endchoice
|
||||
|
||||
@ -335,11 +329,11 @@ choice
|
||||
depends on ETRAX_SERIAL_PORT2
|
||||
default ETRAX_SERIAL_PORT2_DMA3_IN
|
||||
|
||||
config CONFIG_ETRAX_SERIAL_PORT2_NO_DMA_IN
|
||||
bool "No DMA in"
|
||||
config ETRAX_SERIAL_PORT2_NO_DMA_IN
|
||||
bool "No DMA in"
|
||||
|
||||
config CONFIG_ETRAX_SERIAL_PORT2_DMA3_IN
|
||||
bool "DMA 3"
|
||||
config ETRAX_SERIAL_PORT2_DMA3_IN
|
||||
bool "DMA 3"
|
||||
|
||||
endchoice
|
||||
|
||||
@ -436,11 +430,11 @@ choice
|
||||
depends on ETRAX_SERIAL_PORT3
|
||||
default ETRAX_SERIAL_PORT3_DMA4_OUT
|
||||
|
||||
config CONFIG_ETRAX_SERIAL_PORT3_NO_DMA_OUT
|
||||
bool "No DMA out"
|
||||
config ETRAX_SERIAL_PORT3_NO_DMA_OUT
|
||||
bool "No DMA out"
|
||||
|
||||
config CONFIG_ETRAX_SERIAL_PORT3_DMA4_OUT
|
||||
bool "DMA 4"
|
||||
config ETRAX_SERIAL_PORT3_DMA4_OUT
|
||||
bool "DMA 4"
|
||||
|
||||
endchoice
|
||||
|
||||
@ -449,11 +443,11 @@ choice
|
||||
depends on ETRAX_SERIAL_PORT3
|
||||
default ETRAX_SERIAL_PORT3_DMA5_IN
|
||||
|
||||
config CONFIG_ETRAX_SERIAL_PORT3_NO_DMA_IN
|
||||
bool "No DMA in"
|
||||
config ETRAX_SERIAL_PORT3_NO_DMA_IN
|
||||
bool "No DMA in"
|
||||
|
||||
config CONFIG_ETRAX_SERIAL_PORT3_DMA5_IN
|
||||
bool "DMA 5"
|
||||
config ETRAX_SERIAL_PORT3_DMA5_IN
|
||||
bool "DMA 5"
|
||||
|
||||
endchoice
|
||||
|
||||
@ -554,7 +548,6 @@ config ETRAX_IDE
|
||||
select BLK_DEV_IDEDISK
|
||||
select BLK_DEV_IDECD
|
||||
select BLK_DEV_IDEDMA
|
||||
select DMA_NONPCI
|
||||
help
|
||||
Enable this to get support for ATA/IDE.
|
||||
You can't use paralell ports or SCSI ports
|
||||
@ -579,7 +572,7 @@ config ETRAX_IDE_PB7_RESET
|
||||
IDE reset on pin 7 on port B
|
||||
|
||||
config ETRAX_IDE_G27_RESET
|
||||
bool "Port_G_Bit_27"
|
||||
bool "Port_G_Bit_27"
|
||||
help
|
||||
IDE reset on pin 27 on port G
|
||||
|
||||
@ -588,30 +581,36 @@ endchoice
|
||||
|
||||
config ETRAX_USB_HOST
|
||||
bool "USB host"
|
||||
select USB
|
||||
help
|
||||
This option enables the host functionality of the ETRAX 100LX
|
||||
built-in USB controller. In host mode the controller is designed
|
||||
for CTRL and BULK traffic only, INTR traffic may work as well
|
||||
however (depending on the requirements of timeliness).
|
||||
|
||||
config USB
|
||||
tristate
|
||||
depends on ETRAX_USB_HOST
|
||||
default y
|
||||
|
||||
config ETRAX_USB_HOST_PORT1
|
||||
bool " USB port 1 enabled"
|
||||
depends on ETRAX_USB_HOST
|
||||
default n
|
||||
bool "USB port 1 enabled"
|
||||
depends on ETRAX_USB_HOST
|
||||
default n
|
||||
|
||||
config ETRAX_USB_HOST_PORT2
|
||||
bool " USB port 2 enabled"
|
||||
depends on ETRAX_USB_HOST
|
||||
default n
|
||||
bool "USB port 2 enabled"
|
||||
depends on ETRAX_USB_HOST
|
||||
default n
|
||||
|
||||
config ETRAX_AXISFLASHMAP
|
||||
bool "Axis flash-map support"
|
||||
depends on ETRAX_ARCH_V10
|
||||
select MTD
|
||||
select MTD_CFI
|
||||
select MTD_CFI_AMDSTD
|
||||
select MTD_OBSOLETE_CHIPS
|
||||
select MTD_AMDSTD
|
||||
select MTD_CHAR
|
||||
select MTD_BLOCK
|
||||
select MTD_PARTITIONS
|
||||
select MTD_CONCAT
|
||||
select MTD_COMPLEX_MAPPINGS
|
||||
help
|
||||
This option enables MTD mapping of flash devices. Needed to use
|
||||
flash memories. If unsure, say Y.
|
||||
@ -627,119 +626,6 @@ config ETRAX_PTABLE_SECTOR
|
||||
for changing this is when the flash block size is bigger
|
||||
than 64kB (e.g. when using two parallel 16 bit flashes).
|
||||
|
||||
# here we define the CONFIG_'s necessary to enable MTD support
|
||||
# for the flash
|
||||
config MTD
|
||||
tristate
|
||||
depends on ETRAX_AXISFLASHMAP
|
||||
default y
|
||||
help
|
||||
Memory Technology Devices are flash, RAM and similar chips, often
|
||||
used for solid state file systems on embedded devices. This option
|
||||
will provide the generic support for MTD drivers to register
|
||||
themselves with the kernel and for potential users of MTD devices
|
||||
to enumerate the devices which are present and obtain a handle on
|
||||
them. It will also allow you to select individual drivers for
|
||||
particular hardware and users of MTD devices. If unsure, say N.
|
||||
|
||||
config MTD_CFI
|
||||
tristate
|
||||
depends on ETRAX_AXISFLASHMAP
|
||||
default y
|
||||
help
|
||||
The Common Flash Interface specification was developed by Intel,
|
||||
AMD and other flash manufactures that provides a universal method
|
||||
for probing the capabilities of flash devices. If you wish to
|
||||
support any device that is CFI-compliant, you need to enable this
|
||||
option. Visit <http://www.amd.com/products/nvd/overview/cfi.html>
|
||||
for more information on CFI.
|
||||
|
||||
config MTD_CFI_AMDSTD
|
||||
tristate
|
||||
depends on ETRAX_AXISFLASHMAP
|
||||
default y
|
||||
help
|
||||
The Common Flash Interface defines a number of different command
|
||||
sets which a CFI-compliant chip may claim to implement. This code
|
||||
provides support for one of those command sets, used on chips
|
||||
chips including the AMD Am29LV320.
|
||||
|
||||
config MTD_OBSOLETE_CHIPS
|
||||
bool
|
||||
depends on ETRAX_AXISFLASHMAP
|
||||
default y
|
||||
help
|
||||
This option does not enable any code directly, but will allow you to
|
||||
select some other chip drivers which are now considered obsolete,
|
||||
because the generic CONFIG_JEDEC_PROBE code above should now detect
|
||||
the chips which are supported by these drivers, and allow the generic
|
||||
CFI-compatible drivers to drive the chips. Say 'N' here unless you have
|
||||
already tried the CONFIG_JEDEC_PROBE method and reported its failure
|
||||
to the MTD mailing list at <linux-mtd@lists.infradead.org>
|
||||
|
||||
config MTD_AMDSTD
|
||||
tristate
|
||||
depends on ETRAX_AXISFLASHMAP
|
||||
default y
|
||||
help
|
||||
This option enables support for flash chips using AMD-compatible
|
||||
commands, including some which are not CFI-compatible and hence
|
||||
cannot be used with the CONFIG_MTD_CFI_AMDSTD option.
|
||||
|
||||
It also works on AMD compatible chips that do conform to CFI.
|
||||
|
||||
config MTD_CHAR
|
||||
tristate
|
||||
depends on ETRAX_AXISFLASHMAP
|
||||
default y
|
||||
help
|
||||
This provides a character device for each MTD device present in
|
||||
the system, allowing the user to read and write directly to the
|
||||
memory chips, and also use ioctl() to obtain information about
|
||||
the device, or to erase parts of it.
|
||||
|
||||
config MTD_BLOCK
|
||||
tristate
|
||||
depends on ETRAX_AXISFLASHMAP
|
||||
default y
|
||||
---help---
|
||||
Although most flash chips have an erase size too large to be useful
|
||||
as block devices, it is possible to use MTD devices which are based
|
||||
on RAM chips in this manner. This block device is a user of MTD
|
||||
devices performing that function.
|
||||
|
||||
At the moment, it is also required for the Journalling Flash File
|
||||
System(s) to obtain a handle on the MTD device when it's mounted
|
||||
(although JFFS and JFFS2 don't actually use any of the functionality
|
||||
of the mtdblock device).
|
||||
|
||||
Later, it may be extended to perform read/erase/modify/write cycles
|
||||
on flash chips to emulate a smaller block size. Needless to say,
|
||||
this is very unsafe, but could be useful for file systems which are
|
||||
almost never written to.
|
||||
|
||||
You do not need this option for use with the DiskOnChip devices. For
|
||||
those, enable NFTL support (CONFIG_NFTL) instead.
|
||||
|
||||
config MTD_PARTITIONS
|
||||
tristate
|
||||
depends on ETRAX_AXISFLASHMAP
|
||||
default y
|
||||
help
|
||||
If you have a device which needs to divide its flash chip(s) up
|
||||
into multiple 'partitions', each of which appears to the user as
|
||||
a separate MTD device, you require this option to be enabled. If
|
||||
unsure, say 'Y'.
|
||||
|
||||
Note, however, that you don't need this option for the DiskOnChip
|
||||
devices. Partitioning on NFTL 'devices' is a different - that's the
|
||||
'normal' form of partitioning used on a block device.
|
||||
|
||||
config MTD_CONCAT
|
||||
tristate
|
||||
depends on ETRAX_AXISFLASHMAP
|
||||
default y
|
||||
|
||||
config ETRAX_I2C
|
||||
bool "I2C support"
|
||||
depends on ETRAX_ARCH_V10
|
||||
@ -752,7 +638,7 @@ config ETRAX_I2C
|
||||
val = ioctl(fd, _IO(ETRAXI2C_IOCTYPE, I2C_READREG), i2c_arg);
|
||||
|
||||
# this is true for most products since PB-I2C seems to be somewhat
|
||||
# flawed..
|
||||
# flawed..
|
||||
config ETRAX_I2C_USES_PB_NOT_PB_I2C
|
||||
bool "I2C uses PB not PB-I2C"
|
||||
depends on ETRAX_I2C
|
||||
@ -886,7 +772,7 @@ config ETRAX_RTC
|
||||
bool "Real Time Clock support"
|
||||
depends on ETRAX_ARCH_V10
|
||||
help
|
||||
Enables drivers for the Real-Time Clock battery-backed chips on
|
||||
Enables drivers for the Real-Time Clock battery-backed chips on
|
||||
some products. The kernel reads the time when booting, and
|
||||
the date can be set using ioctl(fd, RTC_SET_TIME, &rt) with rt a
|
||||
rtc_time struct (see <file:include/asm-cris/rtc.h>) on the /dev/rtc
|
||||
@ -903,13 +789,13 @@ config ETRAX_DS1302
|
||||
bool "DS1302"
|
||||
help
|
||||
Enables the driver for the DS1302 Real-Time Clock battery-backed
|
||||
chip on some products.
|
||||
chip on some products.
|
||||
|
||||
config ETRAX_PCF8563
|
||||
bool "PCF8563"
|
||||
help
|
||||
Enables the driver for the PCF8563 Real-Time Clock battery-backed
|
||||
chip on some products.
|
||||
chip on some products.
|
||||
|
||||
endchoice
|
||||
|
||||
@ -954,10 +840,8 @@ config ETRAX_DS1302_TRICKLE_CHARGE
|
||||
help
|
||||
This controls the initial value of the trickle charge register.
|
||||
0 = disabled (use this if you are unsure or have a non rechargable battery)
|
||||
Otherwise the following values can be OR:ed together to control the
|
||||
Otherwise the following values can be OR:ed together to control the
|
||||
charge current:
|
||||
1 = 2kohm, 2 = 4kohm, 3 = 4kohm
|
||||
4 = 1 diode, 8 = 2 diodes
|
||||
Allowed values are (increasing current): 0, 11, 10, 9, 7, 6, 5
|
||||
|
||||
|
||||
|
@ -11,6 +11,9 @@
|
||||
* partition split defined below.
|
||||
*
|
||||
* $Log: axisflashmap.c,v $
|
||||
* Revision 1.11 2004/11/15 10:27:14 starvik
|
||||
* Corrected typo (Thanks to Milton Miller <miltonm@bga.com>).
|
||||
*
|
||||
* Revision 1.10 2004/08/16 12:37:22 starvik
|
||||
* Merge of Linux 2.6.8
|
||||
*
|
||||
@ -161,7 +164,7 @@
|
||||
#elif CONFIG_ETRAX_FLASH_BUSWIDTH==2
|
||||
#define flash_data __u16
|
||||
#elif CONFIG_ETRAX_FLASH_BUSWIDTH==4
|
||||
#define flash_data __u16
|
||||
#define flash_data __u32
|
||||
#endif
|
||||
|
||||
/* From head.S */
|
||||
|
@ -7,6 +7,15 @@
|
||||
*! Functions exported: ds1302_readreg, ds1302_writereg, ds1302_init
|
||||
*!
|
||||
*! $Log: ds1302.c,v $
|
||||
*! Revision 1.18 2005/01/24 09:11:26 mikaelam
|
||||
*! Minor changes to get DS1302 RTC chip driver to work
|
||||
*!
|
||||
*! Revision 1.17 2005/01/05 06:11:22 starvik
|
||||
*! No need to do local_irq_disable after local_irq_save.
|
||||
*!
|
||||
*! Revision 1.16 2004/12/13 12:21:52 starvik
|
||||
*! Added I/O and DMA allocators from Linux 2.4
|
||||
*!
|
||||
*! Revision 1.14 2004/08/24 06:48:43 starvik
|
||||
*! Whitespace cleanup
|
||||
*!
|
||||
@ -124,9 +133,9 @@
|
||||
*!
|
||||
*! ---------------------------------------------------------------------------
|
||||
*!
|
||||
*! (C) Copyright 1999, 2000, 2001 Axis Communications AB, LUND, SWEDEN
|
||||
*! (C) Copyright 1999, 2000, 2001, 2002, 2003, 2004 Axis Communications AB, LUND, SWEDEN
|
||||
*!
|
||||
*! $Id: ds1302.c,v 1.14 2004/08/24 06:48:43 starvik Exp $
|
||||
*! $Id: ds1302.c,v 1.18 2005/01/24 09:11:26 mikaelam Exp $
|
||||
*!
|
||||
*!***************************************************************************/
|
||||
|
||||
@ -145,6 +154,7 @@
|
||||
#include <asm/arch/svinto.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/rtc.h>
|
||||
#include <asm/arch/io_interface_mux.h>
|
||||
|
||||
#define RTC_MAJOR_NR 121 /* local major, change later */
|
||||
|
||||
@ -320,7 +330,6 @@ get_rtc_time(struct rtc_time *rtc_tm)
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
local_irq_disable();
|
||||
|
||||
rtc_tm->tm_sec = CMOS_READ(RTC_SECONDS);
|
||||
rtc_tm->tm_min = CMOS_READ(RTC_MINUTES);
|
||||
@ -358,7 +367,7 @@ static int
|
||||
rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned long flags;
|
||||
|
||||
switch(cmd) {
|
||||
case RTC_RD_TIME: /* read the time/date from RTC */
|
||||
@ -382,7 +391,7 @@ rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
|
||||
return -EPERM;
|
||||
|
||||
if (copy_from_user(&rtc_tm, (struct rtc_time*)arg, sizeof(struct rtc_time)))
|
||||
return -EFAULT;
|
||||
return -EFAULT;
|
||||
|
||||
yrs = rtc_tm.tm_year + 1900;
|
||||
mon = rtc_tm.tm_mon + 1; /* tm_mon starts at zero */
|
||||
@ -419,7 +428,6 @@ rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
|
||||
BIN_TO_BCD(yrs);
|
||||
|
||||
local_irq_save(flags);
|
||||
local_irq_disable();
|
||||
CMOS_WRITE(yrs, RTC_YEAR);
|
||||
CMOS_WRITE(mon, RTC_MONTH);
|
||||
CMOS_WRITE(day, RTC_DAY_OF_MONTH);
|
||||
@ -438,7 +446,7 @@ rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
|
||||
|
||||
case RTC_SET_CHARGE: /* set the RTC TRICKLE CHARGE register */
|
||||
{
|
||||
int tcs_val;
|
||||
int tcs_val;
|
||||
|
||||
if (!capable(CAP_SYS_TIME))
|
||||
return -EPERM;
|
||||
@ -492,8 +500,8 @@ print_rtc_status(void)
|
||||
/* The various file operations we support. */
|
||||
|
||||
static struct file_operations rtc_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.ioctl = rtc_ioctl,
|
||||
.owner = THIS_MODULE,
|
||||
.ioctl = rtc_ioctl,
|
||||
};
|
||||
|
||||
/* Probe for the chip by writing something to its RAM and try reading it back. */
|
||||
@ -532,7 +540,7 @@ ds1302_probe(void)
|
||||
"PB",
|
||||
#endif
|
||||
CONFIG_ETRAX_DS1302_RSTBIT);
|
||||
print_rtc_status();
|
||||
print_rtc_status();
|
||||
retval = 1;
|
||||
} else {
|
||||
stop();
|
||||
@ -548,7 +556,9 @@ ds1302_probe(void)
|
||||
int __init
|
||||
ds1302_init(void)
|
||||
{
|
||||
#ifdef CONFIG_ETRAX_I2C
|
||||
i2c_init();
|
||||
#endif
|
||||
|
||||
if (!ds1302_probe()) {
|
||||
#ifdef CONFIG_ETRAX_DS1302_RST_ON_GENERIC_PORT
|
||||
@ -558,25 +568,42 @@ ds1302_init(void)
|
||||
*
|
||||
* Make sure that R_GEN_CONFIG is setup correct.
|
||||
*/
|
||||
genconfig_shadow = ((genconfig_shadow &
|
||||
~IO_MASK(R_GEN_CONFIG, ata)) |
|
||||
(IO_STATE(R_GEN_CONFIG, ata, select)));
|
||||
*R_GEN_CONFIG = genconfig_shadow;
|
||||
/* Allocating the ATA interface will grab almost all
|
||||
* pins in I/O groups a, b, c and d. A consequence of
|
||||
* allocating the ATA interface is that the fixed
|
||||
* interfaces shared RAM, parallel port 0, parallel
|
||||
* port 1, parallel port W, SCSI-8 port 0, SCSI-8 port
|
||||
* 1, SCSI-W, serial port 2, serial port 3,
|
||||
* synchronous serial port 3 and USB port 2 and almost
|
||||
* all GPIO pins on port g cannot be used.
|
||||
*/
|
||||
if (cris_request_io_interface(if_ata, "ds1302/ATA")) {
|
||||
printk(KERN_WARNING "ds1302: Failed to get IO interface\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
#elif CONFIG_ETRAX_DS1302_RSTBIT == 0
|
||||
|
||||
/* Set the direction of this bit to out. */
|
||||
genconfig_shadow = ((genconfig_shadow &
|
||||
~IO_MASK(R_GEN_CONFIG, g0dir)) |
|
||||
(IO_STATE(R_GEN_CONFIG, g0dir, out)));
|
||||
*R_GEN_CONFIG = genconfig_shadow;
|
||||
if (cris_io_interface_allocate_pins(if_gpio_grp_a,
|
||||
'g',
|
||||
CONFIG_ETRAX_DS1302_RSTBIT,
|
||||
CONFIG_ETRAX_DS1302_RSTBIT)) {
|
||||
printk(KERN_WARNING "ds1302: Failed to get IO interface\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Set the direction of this bit to out. */
|
||||
genconfig_shadow = ((genconfig_shadow &
|
||||
~IO_MASK(R_GEN_CONFIG, g0dir)) |
|
||||
(IO_STATE(R_GEN_CONFIG, g0dir, out)));
|
||||
*R_GEN_CONFIG = genconfig_shadow;
|
||||
#endif
|
||||
if (!ds1302_probe()) {
|
||||
printk(KERN_WARNING "%s: RTC not found.\n", ds1302_name);
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
printk(KERN_WARNING "%s: RTC not found.\n", ds1302_name);
|
||||
return -1;
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
/* Initialise trickle charger */
|
||||
|
@ -20,6 +20,12 @@
|
||||
*! in the spin-lock.
|
||||
*!
|
||||
*! $Log: eeprom.c,v $
|
||||
*! Revision 1.12 2005/06/19 17:06:46 starvik
|
||||
*! Merge of Linux 2.6.12.
|
||||
*!
|
||||
*! Revision 1.11 2005/01/26 07:14:46 starvik
|
||||
*! Applied diff from kernel janitors (Nish Aravamudan).
|
||||
*!
|
||||
*! Revision 1.10 2003/09/11 07:29:48 starvik
|
||||
*! Merge of Linux 2.6.0-test5
|
||||
*!
|
||||
@ -94,6 +100,7 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/wait.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include "i2c.h"
|
||||
|
||||
@ -526,15 +533,10 @@ static ssize_t eeprom_read(struct file * file, char * buf, size_t count, loff_t
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
while(eeprom.busy)
|
||||
{
|
||||
interruptible_sleep_on(&eeprom.wait_q);
|
||||
wait_event_interruptible(eeprom.wait_q, !eeprom.busy);
|
||||
if (signal_pending(current))
|
||||
return -EINTR;
|
||||
|
||||
/* bail out if we get interrupted */
|
||||
if (signal_pending(current))
|
||||
return -EINTR;
|
||||
|
||||
}
|
||||
eeprom.busy++;
|
||||
|
||||
page = (unsigned char) (p >> 8);
|
||||
@ -604,13 +606,10 @@ static ssize_t eeprom_write(struct file * file, const char * buf, size_t count,
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
while(eeprom.busy)
|
||||
{
|
||||
interruptible_sleep_on(&eeprom.wait_q);
|
||||
/* bail out if we get interrupted */
|
||||
if (signal_pending(current))
|
||||
return -EINTR;
|
||||
}
|
||||
wait_event_interruptible(eeprom.wait_q, !eeprom.busy);
|
||||
/* bail out if we get interrupted */
|
||||
if (signal_pending(current))
|
||||
return -EINTR;
|
||||
eeprom.busy++;
|
||||
for(i = 0; (i < EEPROM_RETRIES) && (restart > 0); i++)
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $Id: gpio.c,v 1.12 2004/08/24 07:19:59 starvik Exp $
|
||||
/* $Id: gpio.c,v 1.17 2005/06/19 17:06:46 starvik Exp $
|
||||
*
|
||||
* Etrax general port I/O device
|
||||
*
|
||||
@ -9,6 +9,18 @@
|
||||
* Johan Adolfsson (read/set directions, write, port G)
|
||||
*
|
||||
* $Log: gpio.c,v $
|
||||
* Revision 1.17 2005/06/19 17:06:46 starvik
|
||||
* Merge of Linux 2.6.12.
|
||||
*
|
||||
* Revision 1.16 2005/03/07 13:02:29 starvik
|
||||
* Protect driver global states with spinlock
|
||||
*
|
||||
* Revision 1.15 2005/01/05 06:08:55 starvik
|
||||
* No need to do local_irq_disable after local_irq_save.
|
||||
*
|
||||
* Revision 1.14 2004/12/13 12:21:52 starvik
|
||||
* Added I/O and DMA allocators from Linux 2.4
|
||||
*
|
||||
* Revision 1.12 2004/08/24 07:19:59 starvik
|
||||
* Whitespace cleanup
|
||||
*
|
||||
@ -142,6 +154,7 @@
|
||||
#include <asm/io.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/arch/io_interface_mux.h>
|
||||
|
||||
#define GPIO_MAJOR 120 /* experimental MAJOR number */
|
||||
|
||||
@ -194,6 +207,8 @@ static struct gpio_private *alarmlist = 0;
|
||||
static int gpio_some_alarms = 0; /* Set if someone uses alarm */
|
||||
static unsigned long gpio_pa_irq_enabled_mask = 0;
|
||||
|
||||
static DEFINE_SPINLOCK(gpio_lock); /* Protect directions etc */
|
||||
|
||||
/* Port A and B use 8 bit access, but Port G is 32 bit */
|
||||
#define NUM_PORTS (GPIO_MINOR_B+1)
|
||||
|
||||
@ -241,6 +256,9 @@ static volatile unsigned char *dir_shadow[NUM_PORTS] = {
|
||||
&port_pb_dir_shadow
|
||||
};
|
||||
|
||||
/* All bits in port g that can change dir. */
|
||||
static const unsigned long int changeable_dir_g_mask = 0x01FFFF01;
|
||||
|
||||
/* Port G is 32 bit, handle it special, some bits are both inputs
|
||||
and outputs at the same time, only some of the bits can change direction
|
||||
and some of them in groups of 8 bit. */
|
||||
@ -260,6 +278,7 @@ gpio_poll(struct file *file,
|
||||
unsigned int mask = 0;
|
||||
struct gpio_private *priv = (struct gpio_private *)file->private_data;
|
||||
unsigned long data;
|
||||
spin_lock(&gpio_lock);
|
||||
poll_wait(file, &priv->alarm_wq, wait);
|
||||
if (priv->minor == GPIO_MINOR_A) {
|
||||
unsigned long flags;
|
||||
@ -270,10 +289,10 @@ gpio_poll(struct file *file,
|
||||
*/
|
||||
tmp = ~data & priv->highalarm & 0xFF;
|
||||
tmp = (tmp << R_IRQ_MASK1_SET__pa0__BITNR);
|
||||
save_flags(flags); cli();
|
||||
local_irq_save(flags);
|
||||
gpio_pa_irq_enabled_mask |= tmp;
|
||||
*R_IRQ_MASK1_SET = tmp;
|
||||
restore_flags(flags);
|
||||
local_irq_restore(flags);
|
||||
|
||||
} else if (priv->minor == GPIO_MINOR_B)
|
||||
data = *R_PORT_PB_DATA;
|
||||
@ -286,8 +305,11 @@ gpio_poll(struct file *file,
|
||||
(~data & priv->lowalarm)) {
|
||||
mask = POLLIN|POLLRDNORM;
|
||||
}
|
||||
|
||||
spin_unlock(&gpio_lock);
|
||||
|
||||
DP(printk("gpio_poll ready: mask 0x%08X\n", mask));
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
@ -296,6 +318,7 @@ int etrax_gpio_wake_up_check(void)
|
||||
struct gpio_private *priv = alarmlist;
|
||||
unsigned long data = 0;
|
||||
int ret = 0;
|
||||
spin_lock(&gpio_lock);
|
||||
while (priv) {
|
||||
if (USE_PORTS(priv)) {
|
||||
data = *priv->port;
|
||||
@ -310,6 +333,7 @@ int etrax_gpio_wake_up_check(void)
|
||||
}
|
||||
priv = priv->next;
|
||||
}
|
||||
spin_unlock(&gpio_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -327,6 +351,7 @@ static irqreturn_t
|
||||
gpio_pa_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
unsigned long tmp;
|
||||
spin_lock(&gpio_lock);
|
||||
/* Find what PA interrupts are active */
|
||||
tmp = (*R_IRQ_READ1);
|
||||
|
||||
@ -337,6 +362,8 @@ gpio_pa_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
||||
*R_IRQ_MASK1_CLR = tmp;
|
||||
gpio_pa_irq_enabled_mask &= ~tmp;
|
||||
|
||||
spin_unlock(&gpio_lock);
|
||||
|
||||
if (gpio_some_alarms) {
|
||||
return IRQ_RETVAL(etrax_gpio_wake_up_check());
|
||||
}
|
||||
@ -350,6 +377,9 @@ static ssize_t gpio_write(struct file * file, const char * buf, size_t count,
|
||||
struct gpio_private *priv = (struct gpio_private *)file->private_data;
|
||||
unsigned char data, clk_mask, data_mask, write_msb;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock(&gpio_lock);
|
||||
|
||||
ssize_t retval = count;
|
||||
if (priv->minor !=GPIO_MINOR_A && priv->minor != GPIO_MINOR_B) {
|
||||
return -EFAULT;
|
||||
@ -372,7 +402,7 @@ static ssize_t gpio_write(struct file * file, const char * buf, size_t count,
|
||||
data = *buf++;
|
||||
if (priv->write_msb) {
|
||||
for (i = 7; i >= 0;i--) {
|
||||
local_irq_save(flags); local_irq_disable();
|
||||
local_irq_save(flags);
|
||||
*priv->port = *priv->shadow &= ~clk_mask;
|
||||
if (data & 1<<i)
|
||||
*priv->port = *priv->shadow |= data_mask;
|
||||
@ -384,7 +414,7 @@ static ssize_t gpio_write(struct file * file, const char * buf, size_t count,
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i <= 7;i++) {
|
||||
local_irq_save(flags); local_irq_disable();
|
||||
local_irq_save(flags);
|
||||
*priv->port = *priv->shadow &= ~clk_mask;
|
||||
if (data & 1<<i)
|
||||
*priv->port = *priv->shadow |= data_mask;
|
||||
@ -396,6 +426,7 @@ static ssize_t gpio_write(struct file * file, const char * buf, size_t count,
|
||||
}
|
||||
}
|
||||
}
|
||||
spin_unlock(&gpio_lock);
|
||||
return retval;
|
||||
}
|
||||
|
||||
@ -452,9 +483,14 @@ gpio_open(struct inode *inode, struct file *filp)
|
||||
static int
|
||||
gpio_release(struct inode *inode, struct file *filp)
|
||||
{
|
||||
struct gpio_private *p = alarmlist;
|
||||
struct gpio_private *todel = (struct gpio_private *)filp->private_data;
|
||||
|
||||
struct gpio_private *p;
|
||||
struct gpio_private *todel;
|
||||
|
||||
spin_lock(&gpio_lock);
|
||||
|
||||
p = alarmlist;
|
||||
todel = (struct gpio_private *)filp->private_data;
|
||||
|
||||
/* unlink from alarmlist and free the private structure */
|
||||
|
||||
if (p == todel) {
|
||||
@ -476,7 +512,7 @@ gpio_release(struct inode *inode, struct file *filp)
|
||||
p = p->next;
|
||||
}
|
||||
gpio_some_alarms = 0;
|
||||
|
||||
spin_unlock(&gpio_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -491,14 +527,14 @@ unsigned long inline setget_input(struct gpio_private *priv, unsigned long arg)
|
||||
*/
|
||||
unsigned long flags;
|
||||
if (USE_PORTS(priv)) {
|
||||
local_irq_save(flags); local_irq_disable();
|
||||
local_irq_save(flags);
|
||||
*priv->dir = *priv->dir_shadow &=
|
||||
~((unsigned char)arg & priv->changeable_dir);
|
||||
local_irq_restore(flags);
|
||||
return ~(*priv->dir_shadow) & 0xFF; /* Only 8 bits */
|
||||
} else if (priv->minor == GPIO_MINOR_G) {
|
||||
/* We must fiddle with R_GEN_CONFIG to change dir */
|
||||
save_flags(flags); cli();
|
||||
local_irq_save(flags);
|
||||
if (((arg & dir_g_in_bits) != arg) &&
|
||||
(arg & changeable_dir_g)) {
|
||||
arg &= changeable_dir_g;
|
||||
@ -533,7 +569,7 @@ unsigned long inline setget_input(struct gpio_private *priv, unsigned long arg)
|
||||
/* Must be a >120 ns delay before writing this again */
|
||||
|
||||
}
|
||||
restore_flags(flags);
|
||||
local_irq_restore(flags);
|
||||
return dir_g_in_bits;
|
||||
}
|
||||
return 0;
|
||||
@ -543,14 +579,14 @@ unsigned long inline setget_output(struct gpio_private *priv, unsigned long arg)
|
||||
{
|
||||
unsigned long flags;
|
||||
if (USE_PORTS(priv)) {
|
||||
local_irq_save(flags); local_irq_disable();
|
||||
local_irq_save(flags);
|
||||
*priv->dir = *priv->dir_shadow |=
|
||||
((unsigned char)arg & priv->changeable_dir);
|
||||
local_irq_restore(flags);
|
||||
return *priv->dir_shadow;
|
||||
} else if (priv->minor == GPIO_MINOR_G) {
|
||||
/* We must fiddle with R_GEN_CONFIG to change dir */
|
||||
save_flags(flags); cli();
|
||||
local_irq_save(flags);
|
||||
if (((arg & dir_g_out_bits) != arg) &&
|
||||
(arg & changeable_dir_g)) {
|
||||
/* Set bits in genconfig to set to output */
|
||||
@ -583,7 +619,7 @@ unsigned long inline setget_output(struct gpio_private *priv, unsigned long arg)
|
||||
*R_GEN_CONFIG = genconfig_shadow;
|
||||
/* Must be a >120 ns delay before writing this again */
|
||||
}
|
||||
restore_flags(flags);
|
||||
local_irq_restore(flags);
|
||||
return dir_g_out_bits & 0x7FFFFFFF;
|
||||
}
|
||||
return 0;
|
||||
@ -598,22 +634,26 @@ gpio_ioctl(struct inode *inode, struct file *file,
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned long val;
|
||||
int ret = 0;
|
||||
|
||||
struct gpio_private *priv = (struct gpio_private *)file->private_data;
|
||||
if (_IOC_TYPE(cmd) != ETRAXGPIO_IOCTYPE) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
spin_lock(&gpio_lock);
|
||||
|
||||
switch (_IOC_NR(cmd)) {
|
||||
case IO_READBITS: /* Use IO_READ_INBITS and IO_READ_OUTBITS instead */
|
||||
// read the port
|
||||
if (USE_PORTS(priv)) {
|
||||
return *priv->port;
|
||||
ret = *priv->port;
|
||||
} else if (priv->minor == GPIO_MINOR_G) {
|
||||
return (*R_PORT_G_DATA) & 0x7FFFFFFF;
|
||||
ret = (*R_PORT_G_DATA) & 0x7FFFFFFF;
|
||||
}
|
||||
break;
|
||||
case IO_SETBITS:
|
||||
local_irq_save(flags); local_irq_disable();
|
||||
local_irq_save(flags);
|
||||
// set changeable bits with a 1 in arg
|
||||
if (USE_PORTS(priv)) {
|
||||
*priv->port = *priv->shadow |=
|
||||
@ -624,7 +664,7 @@ gpio_ioctl(struct inode *inode, struct file *file,
|
||||
local_irq_restore(flags);
|
||||
break;
|
||||
case IO_CLRBITS:
|
||||
local_irq_save(flags); local_irq_disable();
|
||||
local_irq_save(flags);
|
||||
// clear changeable bits with a 1 in arg
|
||||
if (USE_PORTS(priv)) {
|
||||
*priv->port = *priv->shadow &=
|
||||
@ -666,33 +706,34 @@ gpio_ioctl(struct inode *inode, struct file *file,
|
||||
case IO_READDIR: /* Use IO_SETGET_INPUT/OUTPUT instead! */
|
||||
/* Read direction 0=input 1=output */
|
||||
if (USE_PORTS(priv)) {
|
||||
return *priv->dir_shadow;
|
||||
ret = *priv->dir_shadow;
|
||||
} else if (priv->minor == GPIO_MINOR_G) {
|
||||
/* Note: Some bits are both in and out,
|
||||
* Those that are dual is set here as well.
|
||||
*/
|
||||
return (dir_g_shadow | dir_g_out_bits) & 0x7FFFFFFF;
|
||||
ret = (dir_g_shadow | dir_g_out_bits) & 0x7FFFFFFF;
|
||||
}
|
||||
break;
|
||||
case IO_SETINPUT: /* Use IO_SETGET_INPUT instead! */
|
||||
/* Set direction 0=unchanged 1=input,
|
||||
* return mask with 1=input
|
||||
*/
|
||||
return setget_input(priv, arg) & 0x7FFFFFFF;
|
||||
ret = setget_input(priv, arg) & 0x7FFFFFFF;
|
||||
break;
|
||||
case IO_SETOUTPUT: /* Use IO_SETGET_OUTPUT instead! */
|
||||
/* Set direction 0=unchanged 1=output,
|
||||
* return mask with 1=output
|
||||
*/
|
||||
return setget_output(priv, arg) & 0x7FFFFFFF;
|
||||
|
||||
ret = setget_output(priv, arg) & 0x7FFFFFFF;
|
||||
break;
|
||||
case IO_SHUTDOWN:
|
||||
SOFT_SHUTDOWN();
|
||||
break;
|
||||
case IO_GET_PWR_BT:
|
||||
#if defined (CONFIG_ETRAX_SOFT_SHUTDOWN)
|
||||
return (*R_PORT_G_DATA & ( 1 << CONFIG_ETRAX_POWERBUTTON_BIT));
|
||||
ret = (*R_PORT_G_DATA & ( 1 << CONFIG_ETRAX_POWERBUTTON_BIT));
|
||||
#else
|
||||
return 0;
|
||||
ret = 0;
|
||||
#endif
|
||||
break;
|
||||
case IO_CFG_WRITE_MODE:
|
||||
@ -709,7 +750,7 @@ gpio_ioctl(struct inode *inode, struct file *file,
|
||||
{
|
||||
priv->clk_mask = 0;
|
||||
priv->data_mask = 0;
|
||||
return -EPERM;
|
||||
ret = -EPERM;
|
||||
}
|
||||
break;
|
||||
case IO_READ_INBITS:
|
||||
@ -720,8 +761,7 @@ gpio_ioctl(struct inode *inode, struct file *file,
|
||||
val = *R_PORT_G_DATA;
|
||||
}
|
||||
if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
ret = -EFAULT;
|
||||
break;
|
||||
case IO_READ_OUTBITS:
|
||||
/* *arg is result of reading the output shadow */
|
||||
@ -731,36 +771,43 @@ gpio_ioctl(struct inode *inode, struct file *file,
|
||||
val = port_g_data_shadow;
|
||||
}
|
||||
if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
|
||||
return -EFAULT;
|
||||
ret = -EFAULT;
|
||||
break;
|
||||
case IO_SETGET_INPUT:
|
||||
/* bits set in *arg is set to input,
|
||||
* *arg updated with current input pins.
|
||||
*/
|
||||
if (copy_from_user(&val, (unsigned long*)arg, sizeof(val)))
|
||||
return -EFAULT;
|
||||
{
|
||||
ret = -EFAULT;
|
||||
break;
|
||||
}
|
||||
val = setget_input(priv, val);
|
||||
if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
|
||||
return -EFAULT;
|
||||
ret = -EFAULT;
|
||||
break;
|
||||
case IO_SETGET_OUTPUT:
|
||||
/* bits set in *arg is set to output,
|
||||
* *arg updated with current output pins.
|
||||
*/
|
||||
if (copy_from_user(&val, (unsigned long*)arg, sizeof(val)))
|
||||
return -EFAULT;
|
||||
{
|
||||
ret = -EFAULT;
|
||||
break;
|
||||
}
|
||||
val = setget_output(priv, val);
|
||||
if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
|
||||
return -EFAULT;
|
||||
ret = -EFAULT;
|
||||
break;
|
||||
default:
|
||||
if (priv->minor == GPIO_MINOR_LEDS)
|
||||
return gpio_leds_ioctl(cmd, arg);
|
||||
ret = gpio_leds_ioctl(cmd, arg);
|
||||
else
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
} /* switch */
|
||||
|
||||
return 0;
|
||||
|
||||
spin_unlock(&gpio_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -802,60 +849,20 @@ struct file_operations gpio_fops = {
|
||||
};
|
||||
|
||||
|
||||
static void __init gpio_init_port_g(void)
|
||||
void ioif_watcher(const unsigned int gpio_in_available,
|
||||
const unsigned int gpio_out_available,
|
||||
const unsigned char pa_available,
|
||||
const unsigned char pb_available)
|
||||
{
|
||||
#define GROUPA (0x0000FF3F)
|
||||
#define GROUPB (1<<6 | 1<<7)
|
||||
#define GROUPC (1<<30 | 1<<31)
|
||||
#define GROUPD (0x3FFF0000)
|
||||
#define GROUPD_LOW (0x00FF0000)
|
||||
unsigned long used_in_bits = 0;
|
||||
unsigned long used_out_bits = 0;
|
||||
if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, scsi0, select)){
|
||||
used_in_bits |= GROUPA | GROUPB | 0 | 0;
|
||||
used_out_bits |= GROUPA | GROUPB | 0 | 0;
|
||||
}
|
||||
if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, ata, select)) {
|
||||
used_in_bits |= GROUPA | GROUPB | GROUPC | (GROUPD & ~(1<<25|1<<26));
|
||||
used_out_bits |= GROUPA | GROUPB | GROUPC | GROUPD;
|
||||
}
|
||||
unsigned long int flags;
|
||||
D(printk("gpio.c: ioif_watcher called\n"));
|
||||
D(printk("gpio.c: G in: 0x%08x G out: 0x%08x PA: 0x%02x PB: 0x%02x\n",
|
||||
gpio_in_available, gpio_out_available, pa_available, pb_available));
|
||||
|
||||
if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, par0, select)) {
|
||||
used_in_bits |= (GROUPA & ~(1<<0)) | 0 | 0 | 0;
|
||||
used_out_bits |= (GROUPA & ~(1<<0)) | 0 | 0 | 0;
|
||||
}
|
||||
if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, ser2, select)) {
|
||||
used_in_bits |= 0 | GROUPB | 0 | 0;
|
||||
used_out_bits |= 0 | GROUPB | 0 | 0;
|
||||
}
|
||||
/* mio same as shared RAM ? */
|
||||
if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, mio, select)) {
|
||||
used_in_bits |= (GROUPA & ~(1<<0)) | 0 |0 |GROUPD_LOW;
|
||||
used_out_bits |= (GROUPA & ~(1<<0|1<<1|1<<2)) | 0 |0 |GROUPD_LOW;
|
||||
}
|
||||
if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, scsi1, select)) {
|
||||
used_in_bits |= 0 | 0 | GROUPC | GROUPD;
|
||||
used_out_bits |= 0 | 0 | GROUPC | GROUPD;
|
||||
}
|
||||
if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, scsi0w, select)) {
|
||||
used_in_bits |= GROUPA | GROUPB | 0 | (GROUPD_LOW | 1<<24);
|
||||
used_out_bits |= GROUPA | GROUPB | 0 | (GROUPD_LOW | 1<<24 | 1<<25|1<<26);
|
||||
}
|
||||
spin_lock_irqsave(&gpio_lock, flags);
|
||||
|
||||
if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, par1, select)) {
|
||||
used_in_bits |= 0 | 0 | 0 | (GROUPD & ~(1<<24));
|
||||
used_out_bits |= 0 | 0 | 0 | (GROUPD & ~(1<<24));
|
||||
}
|
||||
if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, ser3, select)) {
|
||||
used_in_bits |= 0 | 0 | GROUPC | 0;
|
||||
used_out_bits |= 0 | 0 | GROUPC | 0;
|
||||
}
|
||||
/* mio same as shared RAM-W? */
|
||||
if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, mio_w, select)) {
|
||||
used_in_bits |= (GROUPA & ~(1<<0)) | 0 | 0 |GROUPD_LOW;
|
||||
used_out_bits |= (GROUPA & ~(1<<0|1<<1|1<<2)) | 0 | 0 |GROUPD_LOW;
|
||||
}
|
||||
/* TODO: USB p2, parw, sync ser3? */
|
||||
dir_g_in_bits = gpio_in_available;
|
||||
dir_g_out_bits = gpio_out_available;
|
||||
|
||||
/* Initialise the dir_g_shadow etc. depending on genconfig */
|
||||
/* 0=input 1=output */
|
||||
@ -868,10 +875,7 @@ static void __init gpio_init_port_g(void)
|
||||
if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, g24dir, out))
|
||||
dir_g_shadow |= (1 << 24);
|
||||
|
||||
dir_g_in_bits = ~used_in_bits;
|
||||
dir_g_out_bits = ~used_out_bits;
|
||||
|
||||
changeable_dir_g = 0x01FFFF01; /* all that can change dir */
|
||||
changeable_dir_g = changeable_dir_g_mask;
|
||||
changeable_dir_g &= dir_g_out_bits;
|
||||
changeable_dir_g &= dir_g_in_bits;
|
||||
/* Correct the bits that can change direction */
|
||||
@ -880,6 +884,7 @@ static void __init gpio_init_port_g(void)
|
||||
dir_g_in_bits &= ~changeable_dir_g;
|
||||
dir_g_in_bits |= (~dir_g_shadow & changeable_dir_g);
|
||||
|
||||
spin_unlock_irqrestore(&gpio_lock, flags);
|
||||
|
||||
printk(KERN_INFO "GPIO port G: in_bits: 0x%08lX out_bits: 0x%08lX val: %08lX\n",
|
||||
dir_g_in_bits, dir_g_out_bits, (unsigned long)*R_PORT_G_DATA);
|
||||
@ -896,6 +901,7 @@ gpio_init(void)
|
||||
#if defined (CONFIG_ETRAX_CSP0_LEDS)
|
||||
int i;
|
||||
#endif
|
||||
printk("gpio init\n");
|
||||
|
||||
/* do the formalities */
|
||||
|
||||
@ -919,8 +925,13 @@ gpio_init(void)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
gpio_init_port_g();
|
||||
printk(KERN_INFO "ETRAX 100LX GPIO driver v2.5, (c) 2001, 2002 Axis Communications AB\n");
|
||||
/* The I/O interface allocation watcher will be called when
|
||||
* registering it. */
|
||||
if (cris_io_interface_register_watcher(ioif_watcher)){
|
||||
printk(KERN_WARNING "gpio_init: Failed to install IO if allocator watcher\n");
|
||||
}
|
||||
|
||||
printk(KERN_INFO "ETRAX 100LX GPIO driver v2.5, (c) 2001, 2002, 2003, 2004 Axis Communications AB\n");
|
||||
/* We call etrax_gpio_wake_up_check() from timer interrupt and
|
||||
* from cpu_idle() in kernel/process.c
|
||||
* The check in cpu_idle() reduces latency from ~15 ms to ~6 ms
|
||||
|
@ -12,6 +12,15 @@
|
||||
*! don't use PB_I2C if DS1302 uses same bits,
|
||||
*! use PB.
|
||||
*! $Log: i2c.c,v $
|
||||
*! Revision 1.13 2005/03/07 13:13:07 starvik
|
||||
*! Added spinlocks to protect states etc
|
||||
*!
|
||||
*! Revision 1.12 2005/01/05 06:11:22 starvik
|
||||
*! No need to do local_irq_disable after local_irq_save.
|
||||
*!
|
||||
*! Revision 1.11 2004/12/13 12:21:52 starvik
|
||||
*! Added I/O and DMA allocators from Linux 2.4
|
||||
*!
|
||||
*! Revision 1.9 2004/08/24 06:49:14 starvik
|
||||
*! Whitespace cleanup
|
||||
*!
|
||||
@ -75,7 +84,7 @@
|
||||
*! (C) Copyright 1999-2002 Axis Communications AB, LUND, SWEDEN
|
||||
*!
|
||||
*!***************************************************************************/
|
||||
/* $Id: i2c.c,v 1.9 2004/08/24 06:49:14 starvik Exp $ */
|
||||
/* $Id: i2c.c,v 1.13 2005/03/07 13:13:07 starvik Exp $ */
|
||||
|
||||
/****************** INCLUDE FILES SECTION ***********************************/
|
||||
|
||||
@ -95,6 +104,7 @@
|
||||
#include <asm/arch/svinto.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/delay.h>
|
||||
#include <asm/arch/io_interface_mux.h>
|
||||
|
||||
#include "i2c.h"
|
||||
|
||||
@ -184,6 +194,7 @@ static const char i2c_name[] = "i2c";
|
||||
|
||||
#define i2c_delay(usecs) udelay(usecs)
|
||||
|
||||
static DEFINE_SPINLOCK(i2c_lock); /* Protect directions etc */
|
||||
|
||||
/****************** FUNCTION DEFINITION SECTION *************************/
|
||||
|
||||
@ -488,13 +499,14 @@ i2c_writereg(unsigned char theSlave, unsigned char theReg,
|
||||
int error, cntr = 3;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock(&i2c_lock);
|
||||
|
||||
do {
|
||||
error = 0;
|
||||
/*
|
||||
* we don't like to be interrupted
|
||||
*/
|
||||
local_irq_save(flags);
|
||||
local_irq_disable();
|
||||
|
||||
i2c_start();
|
||||
/*
|
||||
@ -538,6 +550,8 @@ i2c_writereg(unsigned char theSlave, unsigned char theReg,
|
||||
|
||||
i2c_delay(CLOCK_LOW_TIME);
|
||||
|
||||
spin_unlock(&i2c_lock);
|
||||
|
||||
return -error;
|
||||
}
|
||||
|
||||
@ -555,13 +569,14 @@ i2c_readreg(unsigned char theSlave, unsigned char theReg)
|
||||
int error, cntr = 3;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock(&i2c_lock);
|
||||
|
||||
do {
|
||||
error = 0;
|
||||
/*
|
||||
* we don't like to be interrupted
|
||||
*/
|
||||
local_irq_save(flags);
|
||||
local_irq_disable();
|
||||
/*
|
||||
* generate start condition
|
||||
*/
|
||||
@ -620,6 +635,8 @@ i2c_readreg(unsigned char theSlave, unsigned char theReg)
|
||||
|
||||
} while(error && cntr--);
|
||||
|
||||
spin_unlock(&i2c_lock);
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
@ -686,15 +703,26 @@ static struct file_operations i2c_fops = {
|
||||
int __init
|
||||
i2c_init(void)
|
||||
{
|
||||
static int res = 0;
|
||||
static int first = 1;
|
||||
|
||||
if (!first) {
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Setup and enable the Port B I2C interface */
|
||||
|
||||
#ifndef CONFIG_ETRAX_I2C_USES_PB_NOT_PB_I2C
|
||||
if ((res = cris_request_io_interface(if_i2c, "I2C"))) {
|
||||
printk(KERN_CRIT "i2c_init: Failed to get IO interface\n");
|
||||
return res;
|
||||
}
|
||||
|
||||
*R_PORT_PB_I2C = port_pb_i2c_shadow |=
|
||||
IO_STATE(R_PORT_PB_I2C, i2c_en, on) |
|
||||
IO_FIELD(R_PORT_PB_I2C, i2c_d, 1) |
|
||||
IO_FIELD(R_PORT_PB_I2C, i2c_clk, 1) |
|
||||
IO_STATE(R_PORT_PB_I2C, i2c_oe_, enable);
|
||||
#endif
|
||||
|
||||
port_pb_dir_shadow &= ~IO_MASK(R_PORT_PB_DIR, dir0);
|
||||
port_pb_dir_shadow &= ~IO_MASK(R_PORT_PB_DIR, dir1);
|
||||
@ -702,8 +730,26 @@ i2c_init(void)
|
||||
*R_PORT_PB_DIR = (port_pb_dir_shadow |=
|
||||
IO_STATE(R_PORT_PB_DIR, dir0, input) |
|
||||
IO_STATE(R_PORT_PB_DIR, dir1, output));
|
||||
#else
|
||||
if ((res = cris_io_interface_allocate_pins(if_i2c,
|
||||
'b',
|
||||
CONFIG_ETRAX_I2C_DATA_PORT,
|
||||
CONFIG_ETRAX_I2C_DATA_PORT))) {
|
||||
printk(KERN_WARNING "i2c_init: Failed to get IO pin for I2C data port\n");
|
||||
return res;
|
||||
} else if ((res = cris_io_interface_allocate_pins(if_i2c,
|
||||
'b',
|
||||
CONFIG_ETRAX_I2C_CLK_PORT,
|
||||
CONFIG_ETRAX_I2C_CLK_PORT))) {
|
||||
cris_io_interface_free_pins(if_i2c,
|
||||
'b',
|
||||
CONFIG_ETRAX_I2C_DATA_PORT,
|
||||
CONFIG_ETRAX_I2C_DATA_PORT);
|
||||
printk(KERN_WARNING "i2c_init: Failed to get IO pin for I2C clk port\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
static int __init
|
||||
@ -711,14 +757,16 @@ i2c_register(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
i2c_init();
|
||||
res = i2c_init();
|
||||
if (res < 0)
|
||||
return res;
|
||||
res = register_chrdev(I2C_MAJOR, i2c_name, &i2c_fops);
|
||||
if(res < 0) {
|
||||
printk(KERN_ERR "i2c: couldn't get a major number.\n");
|
||||
return res;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "I2C driver v2.2, (c) 1999-2001 Axis Communications AB\n");
|
||||
printk(KERN_INFO "I2C driver v2.2, (c) 1999-2004 Axis Communications AB\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
*
|
||||
* Author: Tobias Anderberg <tobiasa@axis.com>.
|
||||
*
|
||||
* $Id: pcf8563.c,v 1.8 2004/08/24 06:42:51 starvik Exp $
|
||||
* $Id: pcf8563.c,v 1.11 2005/03/07 13:13:07 starvik Exp $
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
@ -40,7 +40,7 @@
|
||||
#define PCF8563_MAJOR 121 /* Local major number. */
|
||||
#define DEVICE_NAME "rtc" /* Name which is registered in /proc/devices. */
|
||||
#define PCF8563_NAME "PCF8563"
|
||||
#define DRIVER_VERSION "$Revision: 1.8 $"
|
||||
#define DRIVER_VERSION "$Revision: 1.11 $"
|
||||
|
||||
/* I2C bus slave registers. */
|
||||
#define RTC_I2C_READ 0xa3
|
||||
@ -49,6 +49,8 @@
|
||||
/* Two simple wrapper macros, saves a few keystrokes. */
|
||||
#define rtc_read(x) i2c_readreg(RTC_I2C_READ, x)
|
||||
#define rtc_write(x,y) i2c_writereg(RTC_I2C_WRITE, x, y)
|
||||
|
||||
static DEFINE_SPINLOCK(rtc_lock); /* Protect state etc */
|
||||
|
||||
static const unsigned char days_in_month[] =
|
||||
{ 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||
@ -125,9 +127,12 @@ get_rtc_time(struct rtc_time *tm)
|
||||
int __init
|
||||
pcf8563_init(void)
|
||||
{
|
||||
unsigned char ret;
|
||||
int ret;
|
||||
|
||||
i2c_init();
|
||||
if ((ret = i2c_init())) {
|
||||
printk(KERN_CRIT "pcf8563_init: failed to init i2c\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* First of all we need to reset the chip. This is done by
|
||||
@ -200,12 +205,15 @@ pcf8563_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned
|
||||
{
|
||||
struct rtc_time tm;
|
||||
|
||||
spin_lock(&rtc_lock);
|
||||
get_rtc_time(&tm);
|
||||
|
||||
if (copy_to_user((struct rtc_time *) arg, &tm, sizeof(struct rtc_time))) {
|
||||
spin_unlock(&rtc_lock);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
spin_unlock(&rtc_lock);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
@ -250,6 +258,8 @@ pcf8563_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned
|
||||
BIN_TO_BCD(tm.tm_min);
|
||||
BIN_TO_BCD(tm.tm_sec);
|
||||
tm.tm_mon |= century;
|
||||
|
||||
spin_lock(&rtc_lock);
|
||||
|
||||
rtc_write(RTC_YEAR, tm.tm_year);
|
||||
rtc_write(RTC_MONTH, tm.tm_mon);
|
||||
@ -258,6 +268,8 @@ pcf8563_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned
|
||||
rtc_write(RTC_MINUTES, tm.tm_min);
|
||||
rtc_write(RTC_SECONDS, tm.tm_sec);
|
||||
|
||||
spin_unlock(&rtc_lock);
|
||||
|
||||
return 0;
|
||||
#endif /* !CONFIG_ETRAX_RTC_READONLY */
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $Id: Makefile,v 1.5 2004/06/02 08:24:38 starvik Exp $
|
||||
# $Id: Makefile,v 1.6 2004/12/13 12:21:51 starvik Exp $
|
||||
#
|
||||
# Makefile for the linux kernel.
|
||||
#
|
||||
@ -7,7 +7,8 @@ extra-y := head.o
|
||||
|
||||
|
||||
obj-y := entry.o traps.o shadows.o debugport.o irq.o \
|
||||
process.o setup.o signal.o traps.o time.o ptrace.o
|
||||
process.o setup.o signal.o traps.o time.o ptrace.o \
|
||||
dma.o io_interface_mux.o
|
||||
|
||||
obj-$(CONFIG_ETRAX_KGDB) += kgdb.o
|
||||
obj-$(CONFIG_ETRAX_FAST_TIMER) += fasttimer.o
|
||||
|
@ -12,6 +12,31 @@
|
||||
* init_etrax_debug()
|
||||
*
|
||||
* $Log: debugport.c,v $
|
||||
* Revision 1.27 2005/06/10 10:34:14 starvik
|
||||
* Real console support
|
||||
*
|
||||
* Revision 1.26 2005/06/07 07:06:07 starvik
|
||||
* Added LF->CR translation to make ETRAX customers happy.
|
||||
*
|
||||
* Revision 1.25 2005/03/08 08:56:47 mikaelam
|
||||
* Do only set index as port->index if port is defined, otherwise use the index from the command line
|
||||
*
|
||||
* Revision 1.24 2005/01/19 10:26:33 mikaelam
|
||||
* Return the cris serial driver in console device driver callback function
|
||||
*
|
||||
* Revision 1.23 2005/01/14 10:12:17 starvik
|
||||
* KGDB on separate port.
|
||||
* Console fixes from 2.4.
|
||||
*
|
||||
* Revision 1.22 2005/01/11 16:06:13 starvik
|
||||
* typo
|
||||
*
|
||||
* Revision 1.21 2005/01/11 13:49:14 starvik
|
||||
* Added raw_printk to be used where we don't trust the console.
|
||||
*
|
||||
* Revision 1.20 2004/12/27 11:18:32 starvik
|
||||
* Merge of Linux 2.6.10 (not functional yet).
|
||||
*
|
||||
* Revision 1.19 2004/10/21 07:26:16 starvik
|
||||
* Made it possible to specify console settings on kernel command line.
|
||||
*
|
||||
@ -114,7 +139,11 @@ struct dbg_port ports[]=
|
||||
R_SERIAL0_BAUD,
|
||||
R_SERIAL0_TR_CTRL,
|
||||
R_SERIAL0_REC_CTRL,
|
||||
IO_STATE(R_IRQ_MASK1_SET, ser0_data, set)
|
||||
IO_STATE(R_IRQ_MASK1_SET, ser0_data, set),
|
||||
0,
|
||||
115200,
|
||||
'N',
|
||||
8
|
||||
},
|
||||
{
|
||||
1,
|
||||
@ -124,7 +153,11 @@ struct dbg_port ports[]=
|
||||
R_SERIAL1_BAUD,
|
||||
R_SERIAL1_TR_CTRL,
|
||||
R_SERIAL1_REC_CTRL,
|
||||
IO_STATE(R_IRQ_MASK1_SET, ser1_data, set)
|
||||
IO_STATE(R_IRQ_MASK1_SET, ser1_data, set),
|
||||
0,
|
||||
115200,
|
||||
'N',
|
||||
8
|
||||
},
|
||||
{
|
||||
2,
|
||||
@ -134,7 +167,11 @@ struct dbg_port ports[]=
|
||||
R_SERIAL2_BAUD,
|
||||
R_SERIAL2_TR_CTRL,
|
||||
R_SERIAL2_REC_CTRL,
|
||||
IO_STATE(R_IRQ_MASK1_SET, ser2_data, set)
|
||||
IO_STATE(R_IRQ_MASK1_SET, ser2_data, set),
|
||||
0,
|
||||
115200,
|
||||
'N',
|
||||
8
|
||||
},
|
||||
{
|
||||
3,
|
||||
@ -144,11 +181,15 @@ struct dbg_port ports[]=
|
||||
R_SERIAL3_BAUD,
|
||||
R_SERIAL3_TR_CTRL,
|
||||
R_SERIAL3_REC_CTRL,
|
||||
IO_STATE(R_IRQ_MASK1_SET, ser3_data, set)
|
||||
IO_STATE(R_IRQ_MASK1_SET, ser3_data, set),
|
||||
0,
|
||||
115200,
|
||||
'N',
|
||||
8
|
||||
}
|
||||
};
|
||||
|
||||
static struct tty_driver *serial_driver;
|
||||
extern struct tty_driver *serial_driver;
|
||||
|
||||
struct dbg_port* port =
|
||||
#if defined(CONFIG_ETRAX_DEBUG_PORT0)
|
||||
@ -162,37 +203,44 @@ struct dbg_port* port =
|
||||
#else
|
||||
NULL;
|
||||
#endif
|
||||
/* Used by serial.c to register a debug_write_function so that the normal
|
||||
* serial driver is used for kernel debug output
|
||||
*/
|
||||
typedef int (*debugport_write_function)(int i, const char *buf, unsigned int len);
|
||||
|
||||
debugport_write_function debug_write_function = NULL;
|
||||
static struct dbg_port* kgdb_port =
|
||||
#if defined(CONFIG_ETRAX_KGDB_PORT0)
|
||||
&ports[0];
|
||||
#elif defined(CONFIG_ETRAX_KGDB_PORT1)
|
||||
&ports[1];
|
||||
#elif defined(CONFIG_ETRAX_KGDB_PORT2)
|
||||
&ports[2];
|
||||
#elif defined(CONFIG_ETRAX_KGDB_PORT3)
|
||||
&ports[3];
|
||||
#else
|
||||
NULL;
|
||||
#endif
|
||||
|
||||
static void
|
||||
start_port(void)
|
||||
start_port(struct dbg_port* p)
|
||||
{
|
||||
unsigned long rec_ctrl = 0;
|
||||
unsigned long tr_ctrl = 0;
|
||||
|
||||
if (!port)
|
||||
if (!p)
|
||||
return;
|
||||
|
||||
if (port->started)
|
||||
if (p->started)
|
||||
return;
|
||||
port->started = 1;
|
||||
p->started = 1;
|
||||
|
||||
if (port->index == 0)
|
||||
if (p->index == 0)
|
||||
{
|
||||
genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma6);
|
||||
genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma6, unused);
|
||||
}
|
||||
else if (port->index == 1)
|
||||
else if (p->index == 1)
|
||||
{
|
||||
genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma8);
|
||||
genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma8, usb);
|
||||
}
|
||||
else if (port->index == 2)
|
||||
else if (p->index == 2)
|
||||
{
|
||||
genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma2);
|
||||
genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma2, par0);
|
||||
@ -211,69 +259,69 @@ start_port(void)
|
||||
|
||||
*R_GEN_CONFIG = genconfig_shadow;
|
||||
|
||||
*port->xoff =
|
||||
*p->xoff =
|
||||
IO_STATE(R_SERIAL0_XOFF, tx_stop, enable) |
|
||||
IO_STATE(R_SERIAL0_XOFF, auto_xoff, disable) |
|
||||
IO_FIELD(R_SERIAL0_XOFF, xoff_char, 0);
|
||||
|
||||
switch (port->baudrate)
|
||||
switch (p->baudrate)
|
||||
{
|
||||
case 0:
|
||||
case 115200:
|
||||
*port->baud =
|
||||
*p->baud =
|
||||
IO_STATE(R_SERIAL0_BAUD, tr_baud, c115k2Hz) |
|
||||
IO_STATE(R_SERIAL0_BAUD, rec_baud, c115k2Hz);
|
||||
break;
|
||||
case 1200:
|
||||
*port->baud =
|
||||
*p->baud =
|
||||
IO_STATE(R_SERIAL0_BAUD, tr_baud, c1200Hz) |
|
||||
IO_STATE(R_SERIAL0_BAUD, rec_baud, c1200Hz);
|
||||
break;
|
||||
case 2400:
|
||||
*port->baud =
|
||||
*p->baud =
|
||||
IO_STATE(R_SERIAL0_BAUD, tr_baud, c2400Hz) |
|
||||
IO_STATE(R_SERIAL0_BAUD, rec_baud, c2400Hz);
|
||||
break;
|
||||
case 4800:
|
||||
*port->baud =
|
||||
*p->baud =
|
||||
IO_STATE(R_SERIAL0_BAUD, tr_baud, c4800Hz) |
|
||||
IO_STATE(R_SERIAL0_BAUD, rec_baud, c4800Hz);
|
||||
break;
|
||||
case 9600:
|
||||
*port->baud =
|
||||
*p->baud =
|
||||
IO_STATE(R_SERIAL0_BAUD, tr_baud, c9600Hz) |
|
||||
IO_STATE(R_SERIAL0_BAUD, rec_baud, c9600Hz);
|
||||
break;
|
||||
case 19200:
|
||||
*port->baud =
|
||||
*p->baud =
|
||||
IO_STATE(R_SERIAL0_BAUD, tr_baud, c19k2Hz) |
|
||||
IO_STATE(R_SERIAL0_BAUD, rec_baud, c19k2Hz);
|
||||
break;
|
||||
case 38400:
|
||||
*port->baud =
|
||||
*p->baud =
|
||||
IO_STATE(R_SERIAL0_BAUD, tr_baud, c38k4Hz) |
|
||||
IO_STATE(R_SERIAL0_BAUD, rec_baud, c38k4Hz);
|
||||
break;
|
||||
case 57600:
|
||||
*port->baud =
|
||||
*p->baud =
|
||||
IO_STATE(R_SERIAL0_BAUD, tr_baud, c57k6Hz) |
|
||||
IO_STATE(R_SERIAL0_BAUD, rec_baud, c57k6Hz);
|
||||
break;
|
||||
default:
|
||||
*port->baud =
|
||||
*p->baud =
|
||||
IO_STATE(R_SERIAL0_BAUD, tr_baud, c115k2Hz) |
|
||||
IO_STATE(R_SERIAL0_BAUD, rec_baud, c115k2Hz);
|
||||
break;
|
||||
}
|
||||
|
||||
if (port->parity == 'E') {
|
||||
if (p->parity == 'E') {
|
||||
rec_ctrl =
|
||||
IO_STATE(R_SERIAL0_REC_CTRL, rec_par, even) |
|
||||
IO_STATE(R_SERIAL0_REC_CTRL, rec_par_en, enable);
|
||||
tr_ctrl =
|
||||
IO_STATE(R_SERIAL0_TR_CTRL, tr_par, even) |
|
||||
IO_STATE(R_SERIAL0_TR_CTRL, tr_par_en, enable);
|
||||
} else if (port->parity == 'O') {
|
||||
} else if (p->parity == 'O') {
|
||||
rec_ctrl =
|
||||
IO_STATE(R_SERIAL0_REC_CTRL, rec_par, odd) |
|
||||
IO_STATE(R_SERIAL0_REC_CTRL, rec_par_en, enable);
|
||||
@ -288,8 +336,7 @@ start_port(void)
|
||||
IO_STATE(R_SERIAL0_TR_CTRL, tr_par, even) |
|
||||
IO_STATE(R_SERIAL0_TR_CTRL, tr_par_en, disable);
|
||||
}
|
||||
|
||||
if (port->bits == 7)
|
||||
if (p->bits == 7)
|
||||
{
|
||||
rec_ctrl |= IO_STATE(R_SERIAL0_REC_CTRL, rec_bitnr, rec_7bit);
|
||||
tr_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, tr_bitnr, tr_7bit);
|
||||
@ -300,7 +347,7 @@ start_port(void)
|
||||
tr_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, tr_bitnr, tr_8bit);
|
||||
}
|
||||
|
||||
*port->rec_ctrl =
|
||||
*p->rec_ctrl =
|
||||
IO_STATE(R_SERIAL0_REC_CTRL, dma_err, stop) |
|
||||
IO_STATE(R_SERIAL0_REC_CTRL, rec_enable, enable) |
|
||||
IO_STATE(R_SERIAL0_REC_CTRL, rts_, active) |
|
||||
@ -308,7 +355,7 @@ start_port(void)
|
||||
IO_STATE(R_SERIAL0_REC_CTRL, rec_stick_par, normal) |
|
||||
rec_ctrl;
|
||||
|
||||
*port->tr_ctrl =
|
||||
*p->tr_ctrl =
|
||||
IO_FIELD(R_SERIAL0_TR_CTRL, txd, 0) |
|
||||
IO_STATE(R_SERIAL0_TR_CTRL, tr_enable, enable) |
|
||||
IO_STATE(R_SERIAL0_TR_CTRL, auto_cts, disabled) |
|
||||
@ -323,8 +370,18 @@ console_write_direct(struct console *co, const char *buf, unsigned int len)
|
||||
int i;
|
||||
unsigned long flags;
|
||||
local_irq_save(flags);
|
||||
|
||||
if (!port)
|
||||
return;
|
||||
|
||||
/* Send data */
|
||||
for (i = 0; i < len; i++) {
|
||||
/* LF -> CRLF */
|
||||
if (buf[i] == '\n') {
|
||||
while (!(*port->read & IO_MASK(R_SERIAL0_READ, tr_ready)))
|
||||
;
|
||||
*port->write = '\r';
|
||||
}
|
||||
/* Wait until transmitter is ready and send.*/
|
||||
while (!(*port->read & IO_MASK(R_SERIAL0_READ, tr_ready)))
|
||||
;
|
||||
@ -333,6 +390,25 @@ console_write_direct(struct console *co, const char *buf, unsigned int len)
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
int raw_printk(const char *fmt, ...)
|
||||
{
|
||||
static char buf[1024];
|
||||
int printed_len;
|
||||
static int first = 1;
|
||||
if (first) {
|
||||
/* Force reinitialization of the port to get manual mode. */
|
||||
port->started = 0;
|
||||
start_port(port);
|
||||
first = 0;
|
||||
}
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
printed_len = vsnprintf(buf, sizeof(buf), fmt, args);
|
||||
va_end(args);
|
||||
console_write_direct(NULL, buf, strlen(buf));
|
||||
return printed_len;
|
||||
}
|
||||
|
||||
static void
|
||||
console_write(struct console *co, const char *buf, unsigned int len)
|
||||
{
|
||||
@ -345,18 +421,7 @@ console_write(struct console *co, const char *buf, unsigned int len)
|
||||
return;
|
||||
#endif
|
||||
|
||||
start_port();
|
||||
|
||||
#ifdef CONFIG_ETRAX_KGDB
|
||||
/* kgdb needs to output debug info using the gdb protocol */
|
||||
putDebugString(buf, len);
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (debug_write_function)
|
||||
debug_write_function(co->index, buf, len);
|
||||
else
|
||||
console_write_direct(co, buf, len);
|
||||
console_write_direct(co, buf, len);
|
||||
}
|
||||
|
||||
/* legacy function */
|
||||
@ -374,8 +439,11 @@ getDebugChar(void)
|
||||
{
|
||||
unsigned long readval;
|
||||
|
||||
if (!kgdb_port)
|
||||
return 0;
|
||||
|
||||
do {
|
||||
readval = *port->read;
|
||||
readval = *kgdb_port->read;
|
||||
} while (!(readval & IO_MASK(R_SERIAL0_READ, data_avail)));
|
||||
|
||||
return (readval & IO_MASK(R_SERIAL0_READ, data_in));
|
||||
@ -386,9 +454,12 @@ getDebugChar(void)
|
||||
void
|
||||
putDebugChar(int val)
|
||||
{
|
||||
while (!(*port->read & IO_MASK(R_SERIAL0_READ, tr_ready)))
|
||||
if (!kgdb_port)
|
||||
return;
|
||||
|
||||
while (!(*kgdb_port->read & IO_MASK(R_SERIAL0_READ, tr_ready)))
|
||||
;
|
||||
*port->write = val;
|
||||
*kgdb_port->write = val;
|
||||
}
|
||||
|
||||
/* Enable irq for receiving chars on the debug port, used by kgdb */
|
||||
@ -396,19 +467,16 @@ putDebugChar(int val)
|
||||
void
|
||||
enableDebugIRQ(void)
|
||||
{
|
||||
*R_IRQ_MASK1_SET = port->irq;
|
||||
if (!kgdb_port)
|
||||
return;
|
||||
|
||||
*R_IRQ_MASK1_SET = kgdb_port->irq;
|
||||
/* use R_VECT_MASK directly, since we really bypass Linux normal
|
||||
* IRQ handling in kgdb anyway, we don't need to use enable_irq
|
||||
*/
|
||||
*R_VECT_MASK_SET = IO_STATE(R_VECT_MASK_SET, serial, set);
|
||||
|
||||
*port->rec_ctrl = IO_STATE(R_SERIAL0_REC_CTRL, rec_enable, enable);
|
||||
}
|
||||
|
||||
static struct tty_driver*
|
||||
etrax_console_device(struct console* co, int *index)
|
||||
{
|
||||
return serial_driver;
|
||||
*kgdb_port->rec_ctrl = IO_STATE(R_SERIAL0_REC_CTRL, rec_enable, enable);
|
||||
}
|
||||
|
||||
static int __init
|
||||
@ -428,11 +496,69 @@ console_setup(struct console *co, char *options)
|
||||
if (*s) port->parity = *s++;
|
||||
if (*s) port->bits = *s++ - '0';
|
||||
port->started = 0;
|
||||
start_port();
|
||||
start_port(0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This is a dummy serial device that throws away anything written to it.
|
||||
* This is used when no debug output is wanted.
|
||||
*/
|
||||
static struct tty_driver dummy_driver;
|
||||
|
||||
static int dummy_open(struct tty_struct *tty, struct file * filp)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dummy_close(struct tty_struct *tty, struct file * filp)
|
||||
{
|
||||
}
|
||||
|
||||
static int dummy_write(struct tty_struct * tty,
|
||||
const unsigned char *buf, int count)
|
||||
{
|
||||
return count;
|
||||
}
|
||||
|
||||
static int
|
||||
dummy_write_room(struct tty_struct *tty)
|
||||
{
|
||||
return 8192;
|
||||
}
|
||||
|
||||
void __init
|
||||
init_dummy_console(void)
|
||||
{
|
||||
memset(&dummy_driver, 0, sizeof(struct tty_driver));
|
||||
dummy_driver.driver_name = "serial";
|
||||
dummy_driver.name = "ttyS";
|
||||
dummy_driver.major = TTY_MAJOR;
|
||||
dummy_driver.minor_start = 68;
|
||||
dummy_driver.num = 1; /* etrax100 has 4 serial ports */
|
||||
dummy_driver.type = TTY_DRIVER_TYPE_SERIAL;
|
||||
dummy_driver.subtype = SERIAL_TYPE_NORMAL;
|
||||
dummy_driver.init_termios = tty_std_termios;
|
||||
dummy_driver.init_termios.c_cflag =
|
||||
B115200 | CS8 | CREAD | HUPCL | CLOCAL; /* is normally B9600 default... */
|
||||
dummy_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
|
||||
|
||||
dummy_driver.open = dummy_open;
|
||||
dummy_driver.close = dummy_close;
|
||||
dummy_driver.write = dummy_write;
|
||||
dummy_driver.write_room = dummy_write_room;
|
||||
if (tty_register_driver(&dummy_driver))
|
||||
panic("Couldn't register dummy serial driver\n");
|
||||
}
|
||||
|
||||
static struct tty_driver*
|
||||
etrax_console_device(struct console* co, int *index)
|
||||
{
|
||||
if (port)
|
||||
*index = port->index;
|
||||
return port ? serial_driver : &dummy_driver;
|
||||
}
|
||||
|
||||
static struct console sercons = {
|
||||
name : "ttyS",
|
||||
write: console_write,
|
||||
@ -504,28 +630,21 @@ init_etrax_debug(void)
|
||||
static int first = 1;
|
||||
|
||||
if (!first) {
|
||||
if (!port) {
|
||||
register_console(&sercons0);
|
||||
register_console(&sercons1);
|
||||
register_console(&sercons2);
|
||||
register_console(&sercons3);
|
||||
unregister_console(&sercons);
|
||||
}
|
||||
unregister_console(&sercons);
|
||||
register_console(&sercons0);
|
||||
register_console(&sercons1);
|
||||
register_console(&sercons2);
|
||||
register_console(&sercons3);
|
||||
init_dummy_console();
|
||||
return 0;
|
||||
}
|
||||
|
||||
first = 0;
|
||||
if (port)
|
||||
register_console(&sercons);
|
||||
register_console(&sercons);
|
||||
start_port(port);
|
||||
#ifdef CONFIG_ETRAX_KGDB
|
||||
start_port(kgdb_port);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __init
|
||||
init_console(void)
|
||||
{
|
||||
serial_driver = alloc_tty_driver(1);
|
||||
if (!serial_driver)
|
||||
return -ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
__initcall(init_etrax_debug);
|
||||
|
287
arch/cris/arch-v10/kernel/dma.c
Normal file
287
arch/cris/arch-v10/kernel/dma.c
Normal file
@ -0,0 +1,287 @@
|
||||
/* Wrapper for DMA channel allocator that updates DMA client muxing.
|
||||
* Copyright 2004, Axis Communications AB
|
||||
* $Id: dma.c,v 1.1 2004/12/13 12:21:51 starvik Exp $
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/errno.h>
|
||||
|
||||
#include <asm/dma.h>
|
||||
#include <asm/arch/svinto.h>
|
||||
|
||||
/* Macro to access ETRAX 100 registers */
|
||||
#define SETS(var, reg, field, val) var = (var & ~IO_MASK_(reg##_, field##_)) | \
|
||||
IO_STATE_(reg##_, field##_, _##val)
|
||||
|
||||
|
||||
static char used_dma_channels[MAX_DMA_CHANNELS];
|
||||
static const char * used_dma_channels_users[MAX_DMA_CHANNELS];
|
||||
|
||||
int cris_request_dma(unsigned int dmanr, const char * device_id,
|
||||
unsigned options, enum dma_owner owner)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned long int gens;
|
||||
int fail = -EINVAL;
|
||||
|
||||
if ((dmanr < 0) || (dmanr >= MAX_DMA_CHANNELS)) {
|
||||
printk(KERN_CRIT "cris_request_dma: invalid DMA channel %u\n", dmanr);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
local_irq_save(flags);
|
||||
if (used_dma_channels[dmanr]) {
|
||||
local_irq_restore(flags);
|
||||
if (options & DMA_VERBOSE_ON_ERROR) {
|
||||
printk(KERN_CRIT "Failed to request DMA %i for %s, already allocated by %s\n", dmanr, device_id, used_dma_channels_users[dmanr]);
|
||||
}
|
||||
if (options & DMA_PANIC_ON_ERROR) {
|
||||
panic("request_dma error!");
|
||||
}
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
gens = genconfig_shadow;
|
||||
|
||||
switch(owner)
|
||||
{
|
||||
case dma_eth:
|
||||
if ((dmanr != NETWORK_TX_DMA_NBR) &&
|
||||
(dmanr != NETWORK_RX_DMA_NBR)) {
|
||||
printk(KERN_CRIT "Invalid DMA channel for eth\n");
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
case dma_ser0:
|
||||
if (dmanr == SER0_TX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma6, serial0);
|
||||
} else if (dmanr == SER0_RX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma7, serial0);
|
||||
} else {
|
||||
printk(KERN_CRIT "Invalid DMA channel for ser0\n");
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
case dma_ser1:
|
||||
if (dmanr == SER1_TX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma8, serial1);
|
||||
} else if (dmanr == SER1_RX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma9, serial1);
|
||||
} else {
|
||||
printk(KERN_CRIT "Invalid DMA channel for ser1\n");
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
case dma_ser2:
|
||||
if (dmanr == SER2_TX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma2, serial2);
|
||||
} else if (dmanr == SER2_RX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma3, serial2);
|
||||
} else {
|
||||
printk(KERN_CRIT "Invalid DMA channel for ser2\n");
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
case dma_ser3:
|
||||
if (dmanr == SER3_TX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma4, serial3);
|
||||
} else if (dmanr == SER3_RX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma5, serial3);
|
||||
} else {
|
||||
printk(KERN_CRIT "Invalid DMA channel for ser3\n");
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
case dma_ata:
|
||||
if (dmanr == ATA_TX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma2, ata);
|
||||
} else if (dmanr == ATA_RX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma3, ata);
|
||||
} else {
|
||||
printk(KERN_CRIT "Invalid DMA channel for ata\n");
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
case dma_ext0:
|
||||
if (dmanr == EXTDMA0_TX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma4, extdma0);
|
||||
} else if (dmanr == EXTDMA0_RX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma5, extdma0);
|
||||
} else {
|
||||
printk(KERN_CRIT "Invalid DMA channel for ext0\n");
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
case dma_ext1:
|
||||
if (dmanr == EXTDMA1_TX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma6, extdma1);
|
||||
} else if (dmanr == EXTDMA1_RX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma7, extdma1);
|
||||
} else {
|
||||
printk(KERN_CRIT "Invalid DMA channel for ext1\n");
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
case dma_int6:
|
||||
if (dmanr == MEM2MEM_RX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma7, intdma6);
|
||||
} else {
|
||||
printk(KERN_CRIT "Invalid DMA channel for int6\n");
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
case dma_int7:
|
||||
if (dmanr == MEM2MEM_TX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma6, intdma7);
|
||||
} else {
|
||||
printk(KERN_CRIT "Invalid DMA channel for int7\n");
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
case dma_usb:
|
||||
if (dmanr == USB_TX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma8, usb);
|
||||
} else if (dmanr == USB_RX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma9, usb);
|
||||
} else {
|
||||
printk(KERN_CRIT "Invalid DMA channel for usb\n");
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
case dma_scsi0:
|
||||
if (dmanr == SCSI0_TX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma2, scsi0);
|
||||
} else if (dmanr == SCSI0_RX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma3, scsi0);
|
||||
} else {
|
||||
printk(KERN_CRIT "Invalid DMA channel for scsi0\n");
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
case dma_scsi1:
|
||||
if (dmanr == SCSI1_TX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma4, scsi1);
|
||||
} else if (dmanr == SCSI1_RX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma5, scsi1);
|
||||
} else {
|
||||
printk(KERN_CRIT "Invalid DMA channel for scsi1\n");
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
case dma_par0:
|
||||
if (dmanr == PAR0_TX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma2, par0);
|
||||
} else if (dmanr == PAR0_RX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma3, par0);
|
||||
} else {
|
||||
printk(KERN_CRIT "Invalid DMA channel for par0\n");
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
case dma_par1:
|
||||
if (dmanr == PAR1_TX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma4, par1);
|
||||
} else if (dmanr == PAR1_RX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma5, par1);
|
||||
} else {
|
||||
printk(KERN_CRIT "Invalid DMA channel for par1\n");
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printk(KERN_CRIT "Invalid DMA owner.\n");
|
||||
goto bail;
|
||||
}
|
||||
|
||||
used_dma_channels[dmanr] = 1;
|
||||
used_dma_channels_users[dmanr] = device_id;
|
||||
|
||||
{
|
||||
volatile int i;
|
||||
genconfig_shadow = gens;
|
||||
*R_GEN_CONFIG = genconfig_shadow;
|
||||
/* Wait 12 cycles before doing any DMA command */
|
||||
for(i = 6; i > 0; i--)
|
||||
nop();
|
||||
}
|
||||
fail = 0;
|
||||
bail:
|
||||
local_irq_restore(flags);
|
||||
return fail;
|
||||
}
|
||||
|
||||
void cris_free_dma(unsigned int dmanr, const char * device_id)
|
||||
{
|
||||
unsigned long flags;
|
||||
if ((dmanr < 0) || (dmanr >= MAX_DMA_CHANNELS)) {
|
||||
printk(KERN_CRIT "cris_free_dma: invalid DMA channel %u\n", dmanr);
|
||||
return;
|
||||
}
|
||||
|
||||
local_irq_save(flags);
|
||||
if (!used_dma_channels[dmanr]) {
|
||||
printk(KERN_CRIT "cris_free_dma: DMA channel %u not allocated\n", dmanr);
|
||||
} else if (device_id != used_dma_channels_users[dmanr]) {
|
||||
printk(KERN_CRIT "cris_free_dma: DMA channel %u not allocated by device\n", dmanr);
|
||||
} else {
|
||||
switch(dmanr)
|
||||
{
|
||||
case 0:
|
||||
*R_DMA_CH0_CMD = IO_STATE(R_DMA_CH0_CMD, cmd, reset);
|
||||
while (IO_EXTRACT(R_DMA_CH0_CMD, cmd, *R_DMA_CH0_CMD) ==
|
||||
IO_STATE_VALUE(R_DMA_CH0_CMD, cmd, reset));
|
||||
break;
|
||||
case 1:
|
||||
*R_DMA_CH1_CMD = IO_STATE(R_DMA_CH1_CMD, cmd, reset);
|
||||
while (IO_EXTRACT(R_DMA_CH1_CMD, cmd, *R_DMA_CH1_CMD) ==
|
||||
IO_STATE_VALUE(R_DMA_CH1_CMD, cmd, reset));
|
||||
break;
|
||||
case 2:
|
||||
*R_DMA_CH2_CMD = IO_STATE(R_DMA_CH2_CMD, cmd, reset);
|
||||
while (IO_EXTRACT(R_DMA_CH2_CMD, cmd, *R_DMA_CH2_CMD) ==
|
||||
IO_STATE_VALUE(R_DMA_CH2_CMD, cmd, reset));
|
||||
break;
|
||||
case 3:
|
||||
*R_DMA_CH3_CMD = IO_STATE(R_DMA_CH3_CMD, cmd, reset);
|
||||
while (IO_EXTRACT(R_DMA_CH3_CMD, cmd, *R_DMA_CH3_CMD) ==
|
||||
IO_STATE_VALUE(R_DMA_CH3_CMD, cmd, reset));
|
||||
break;
|
||||
case 4:
|
||||
*R_DMA_CH4_CMD = IO_STATE(R_DMA_CH4_CMD, cmd, reset);
|
||||
while (IO_EXTRACT(R_DMA_CH4_CMD, cmd, *R_DMA_CH4_CMD) ==
|
||||
IO_STATE_VALUE(R_DMA_CH4_CMD, cmd, reset));
|
||||
break;
|
||||
case 5:
|
||||
*R_DMA_CH5_CMD = IO_STATE(R_DMA_CH5_CMD, cmd, reset);
|
||||
while (IO_EXTRACT(R_DMA_CH5_CMD, cmd, *R_DMA_CH5_CMD) ==
|
||||
IO_STATE_VALUE(R_DMA_CH5_CMD, cmd, reset));
|
||||
break;
|
||||
case 6:
|
||||
*R_DMA_CH6_CMD = IO_STATE(R_DMA_CH6_CMD, cmd, reset);
|
||||
while (IO_EXTRACT(R_DMA_CH6_CMD, cmd, *R_DMA_CH6_CMD) ==
|
||||
IO_STATE_VALUE(R_DMA_CH6_CMD, cmd, reset));
|
||||
break;
|
||||
case 7:
|
||||
*R_DMA_CH7_CMD = IO_STATE(R_DMA_CH7_CMD, cmd, reset);
|
||||
while (IO_EXTRACT(R_DMA_CH7_CMD, cmd, *R_DMA_CH7_CMD) ==
|
||||
IO_STATE_VALUE(R_DMA_CH7_CMD, cmd, reset));
|
||||
break;
|
||||
case 8:
|
||||
*R_DMA_CH8_CMD = IO_STATE(R_DMA_CH8_CMD, cmd, reset);
|
||||
while (IO_EXTRACT(R_DMA_CH8_CMD, cmd, *R_DMA_CH8_CMD) ==
|
||||
IO_STATE_VALUE(R_DMA_CH8_CMD, cmd, reset));
|
||||
break;
|
||||
case 9:
|
||||
*R_DMA_CH9_CMD = IO_STATE(R_DMA_CH9_CMD, cmd, reset);
|
||||
while (IO_EXTRACT(R_DMA_CH9_CMD, cmd, *R_DMA_CH9_CMD) ==
|
||||
IO_STATE_VALUE(R_DMA_CH9_CMD, cmd, reset));
|
||||
break;
|
||||
}
|
||||
used_dma_channels[dmanr] = 0;
|
||||
}
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(cris_request_dma);
|
||||
EXPORT_SYMBOL(cris_free_dma);
|
@ -1,4 +1,4 @@
|
||||
/* $Id: entry.S,v 1.23 2004/10/19 13:07:37 starvik Exp $
|
||||
/* $Id: entry.S,v 1.28 2005/06/20 05:06:30 starvik Exp $
|
||||
*
|
||||
* linux/arch/cris/entry.S
|
||||
*
|
||||
@ -7,6 +7,22 @@
|
||||
* Authors: Bjorn Wesen (bjornw@axis.com)
|
||||
*
|
||||
* $Log: entry.S,v $
|
||||
* Revision 1.28 2005/06/20 05:06:30 starvik
|
||||
* Remove unnecessary diff to kernel.org tree
|
||||
*
|
||||
* Revision 1.27 2005/03/04 08:16:16 starvik
|
||||
* Merge of Linux 2.6.11.
|
||||
*
|
||||
* Revision 1.26 2005/01/11 13:49:47 starvik
|
||||
* Added NMI handler.
|
||||
*
|
||||
* Revision 1.25 2004/12/27 11:18:32 starvik
|
||||
* Merge of Linux 2.6.10 (not functional yet).
|
||||
*
|
||||
* Revision 1.24 2004/12/22 10:41:23 starvik
|
||||
* Updates to make v10 compile with the latest SMP aware generic code (even
|
||||
* though v10 will never have SMP).
|
||||
*
|
||||
* Revision 1.23 2004/10/19 13:07:37 starvik
|
||||
* Merge of Linux 2.6.9
|
||||
*
|
||||
@ -279,6 +295,7 @@
|
||||
#ifdef CONFIG_PREEMPT
|
||||
; Check if preemptive kernel scheduling should be done
|
||||
_resume_kernel:
|
||||
di
|
||||
; Load current task struct
|
||||
movs.w -8192, $r0 ; THREAD_SIZE = 8192
|
||||
and.d $sp, $r0
|
||||
@ -291,12 +308,7 @@ _need_resched:
|
||||
bpl _Rexit
|
||||
nop
|
||||
; Ok, lets's do some preemptive kernel scheduling
|
||||
move.d PREEMPT_ACTIVE, $r10
|
||||
move.d $r10, [$r0+TI_preempt_count] ; Mark as active
|
||||
ei
|
||||
jsr schedule
|
||||
clear.d [$r0+TI_preempt_count] ; Mark as inactive
|
||||
di
|
||||
jsr preempt_schedule_irq
|
||||
; Load new task struct
|
||||
movs.w -8192, $r0 ; THREAD_SIZE = 8192
|
||||
and.d $sp, $r0
|
||||
@ -590,15 +602,15 @@ mmu_bus_fault:
|
||||
move.d $r0, [$sp+16]
|
||||
1: btstq 12, $r1 ; Refill?
|
||||
bpl 2f
|
||||
lsrq PMD_SHIFT, $r1 ; Get PMD index into PGD (bit 24-31)
|
||||
move.d [current_pgd], $r0 ; PGD for the current process
|
||||
lsrq 24, $r1 ; Get PGD index (bit 24-31)
|
||||
move.d [per_cpu__current_pgd], $r0 ; PGD for the current process
|
||||
move.d [$r0+$r1.d], $r0 ; Get PMD
|
||||
beq 2f
|
||||
nop
|
||||
and.w PAGE_MASK, $r0 ; Remove PMD flags
|
||||
move.d [R_MMU_CAUSE], $r1
|
||||
lsrq PAGE_SHIFT, $r1
|
||||
and.d 0x7ff, $r1 ; Get PTE index into PMD (bit 13-24)
|
||||
and.d 0x7ff, $r1 ; Get PTE index into PGD (bit 13-23)
|
||||
move.d [$r0+$r1.d], $r1 ; Get PTE
|
||||
beq 2f
|
||||
nop
|
||||
@ -656,11 +668,6 @@ hwbreakpoint:
|
||||
nop
|
||||
|
||||
IRQ1_interrupt:
|
||||
|
||||
#if defined(CONFIG_ETRAX_WATCHDOG) && !defined(CONFIG_SVINTO_SIM)
|
||||
;; If we receive a watchdog interrupt while it is not expected, then set
|
||||
;; up a canonical frame and dump register contents before dying.
|
||||
|
||||
;; this prologue MUST match the one in irq.h and the struct in ptregs.h!!!
|
||||
move $brp,[$sp=$sp-16]; instruction pointer and room for a fake SBFS frame
|
||||
push $srp
|
||||
@ -672,9 +679,16 @@ IRQ1_interrupt:
|
||||
push $r10 ; push orig_r10
|
||||
clear.d [$sp=$sp-4] ; frametype == 0, normal frame
|
||||
|
||||
;; We don't check that we actually were bit by the watchdog as opposed to
|
||||
;; an external NMI, since there is currently no handler for external NMI.
|
||||
|
||||
move.d [R_IRQ_MASK0_RD], $r1 ; External NMI or watchdog?
|
||||
and.d 0x80000000, $r1
|
||||
beq wdog
|
||||
move.d $sp, $r10
|
||||
jsr handle_nmi
|
||||
setf m ; Enable NMI again
|
||||
retb ; Return from NMI
|
||||
nop
|
||||
wdog:
|
||||
#if defined(CONFIG_ETRAX_WATCHDOG) && !defined(CONFIG_SVINTO_SIM)
|
||||
;; Check if we're waiting for reset to happen, as signalled by
|
||||
;; hard_reset_now setting cause_of_death to a magic value. If so, just
|
||||
;; get stuck until reset happens.
|
||||
@ -1118,6 +1132,10 @@ sys_call_table:
|
||||
.long sys_mq_getsetattr
|
||||
.long sys_ni_syscall /* reserved for kexec */
|
||||
.long sys_waitid
|
||||
.long sys_ni_syscall /* 285 */ /* available */
|
||||
.long sys_add_key
|
||||
.long sys_request_key
|
||||
.long sys_keyctl
|
||||
|
||||
/*
|
||||
* NOTE!! This doesn't have to be exact - we just have
|
||||
|
@ -1,10 +1,20 @@
|
||||
/* $Id: fasttimer.c,v 1.6 2004/05/14 10:18:39 starvik Exp $
|
||||
/* $Id: fasttimer.c,v 1.9 2005/03/04 08:16:16 starvik Exp $
|
||||
* linux/arch/cris/kernel/fasttimer.c
|
||||
*
|
||||
* Fast timers for ETRAX100/ETRAX100LX
|
||||
* This may be useful in other OS than Linux so use 2 space indentation...
|
||||
*
|
||||
* $Log: fasttimer.c,v $
|
||||
* Revision 1.9 2005/03/04 08:16:16 starvik
|
||||
* Merge of Linux 2.6.11.
|
||||
*
|
||||
* Revision 1.8 2005/01/05 06:09:29 starvik
|
||||
* cli()/sti() will be obsolete in 2.6.11.
|
||||
*
|
||||
* Revision 1.7 2005/01/03 13:35:46 starvik
|
||||
* Removed obsolete stuff.
|
||||
* Mark fast timer IRQ as not shared.
|
||||
*
|
||||
* Revision 1.6 2004/05/14 10:18:39 starvik
|
||||
* Export fast_timer_list
|
||||
*
|
||||
@ -148,8 +158,7 @@ static int debug_log_cnt_wrapped = 0;
|
||||
#define DEBUG_LOG(string, value) \
|
||||
{ \
|
||||
unsigned long log_flags; \
|
||||
save_flags(log_flags); \
|
||||
cli(); \
|
||||
local_irq_save(log_flags); \
|
||||
debug_log_string[debug_log_cnt] = (string); \
|
||||
debug_log_value[debug_log_cnt] = (unsigned long)(value); \
|
||||
if (++debug_log_cnt >= DEBUG_LOG_MAX) \
|
||||
@ -157,7 +166,7 @@ static int debug_log_cnt_wrapped = 0;
|
||||
debug_log_cnt = debug_log_cnt % DEBUG_LOG_MAX; \
|
||||
debug_log_cnt_wrapped = 1; \
|
||||
} \
|
||||
restore_flags(log_flags); \
|
||||
local_irq_restore(log_flags); \
|
||||
}
|
||||
#else
|
||||
#define DEBUG_LOG(string, value)
|
||||
@ -320,8 +329,7 @@ void start_one_shot_timer(struct fast_timer *t,
|
||||
|
||||
D1(printk("sft %s %d us\n", name, delay_us));
|
||||
|
||||
save_flags(flags);
|
||||
cli();
|
||||
local_irq_save(flags);
|
||||
|
||||
do_gettimeofday_fast(&t->tv_set);
|
||||
tmp = fast_timer_list;
|
||||
@ -395,7 +403,7 @@ void start_one_shot_timer(struct fast_timer *t,
|
||||
|
||||
D2(printk("start_one_shot_timer: %d us done\n", delay_us));
|
||||
|
||||
restore_flags(flags);
|
||||
local_irq_restore(flags);
|
||||
} /* start_one_shot_timer */
|
||||
|
||||
static inline int fast_timer_pending (const struct fast_timer * t)
|
||||
@ -425,11 +433,10 @@ int del_fast_timer(struct fast_timer * t)
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
save_flags(flags);
|
||||
cli();
|
||||
local_irq_save(flags);
|
||||
ret = detach_fast_timer(t);
|
||||
t->next = t->prev = NULL;
|
||||
restore_flags(flags);
|
||||
local_irq_restore(flags);
|
||||
return ret;
|
||||
} /* del_fast_timer */
|
||||
|
||||
@ -444,8 +451,7 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs)
|
||||
struct fast_timer *t;
|
||||
unsigned long flags;
|
||||
|
||||
save_flags(flags);
|
||||
cli();
|
||||
local_irq_save(flags);
|
||||
|
||||
/* Clear timer1 irq */
|
||||
*R_IRQ_MASK0_CLR = IO_STATE(R_IRQ_MASK0_CLR, timer1, clr);
|
||||
@ -462,7 +468,7 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs)
|
||||
fast_timer_running = 0;
|
||||
fast_timer_ints++;
|
||||
|
||||
restore_flags(flags);
|
||||
local_irq_restore(flags);
|
||||
|
||||
t = fast_timer_list;
|
||||
while (t)
|
||||
@ -482,8 +488,7 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs)
|
||||
fast_timers_expired++;
|
||||
|
||||
/* Remove this timer before call, since it may reuse the timer */
|
||||
save_flags(flags);
|
||||
cli();
|
||||
local_irq_save(flags);
|
||||
if (t->prev)
|
||||
{
|
||||
t->prev->next = t->next;
|
||||
@ -498,7 +503,7 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs)
|
||||
}
|
||||
t->prev = NULL;
|
||||
t->next = NULL;
|
||||
restore_flags(flags);
|
||||
local_irq_restore(flags);
|
||||
|
||||
if (t->function != NULL)
|
||||
{
|
||||
@ -515,8 +520,7 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs)
|
||||
D1(printk(".\n"));
|
||||
}
|
||||
|
||||
save_flags(flags);
|
||||
cli();
|
||||
local_irq_save(flags);
|
||||
if ((t = fast_timer_list) != NULL)
|
||||
{
|
||||
/* Start next timer.. */
|
||||
@ -535,7 +539,7 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs)
|
||||
#endif
|
||||
start_timer1(us);
|
||||
}
|
||||
restore_flags(flags);
|
||||
local_irq_restore(flags);
|
||||
break;
|
||||
}
|
||||
else
|
||||
@ -546,7 +550,7 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs)
|
||||
D1(printk("e! %d\n", us));
|
||||
}
|
||||
}
|
||||
restore_flags(flags);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
if (!t)
|
||||
@ -748,13 +752,12 @@ static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len
|
||||
#endif
|
||||
|
||||
used += sprintf(bigbuf + used, "Active timers:\n");
|
||||
save_flags(flags);
|
||||
cli();
|
||||
local_irq_save(flags);
|
||||
t = fast_timer_list;
|
||||
while (t != NULL && (used+100 < BIG_BUF_SIZE))
|
||||
{
|
||||
nextt = t->next;
|
||||
restore_flags(flags);
|
||||
local_irq_restore(flags);
|
||||
used += sprintf(bigbuf + used, "%-14s s: %6lu.%06lu e: %6lu.%06lu "
|
||||
"d: %6li us data: 0x%08lX"
|
||||
/* " func: 0x%08lX" */
|
||||
@ -768,14 +771,14 @@ static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len
|
||||
t->data
|
||||
/* , t->function */
|
||||
);
|
||||
cli();
|
||||
local_irq_disable();
|
||||
if (t->next != nextt)
|
||||
{
|
||||
printk(KERN_WARNING "timer removed!\n");
|
||||
}
|
||||
t = nextt;
|
||||
}
|
||||
restore_flags(flags);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
if (used - offset < len)
|
||||
@ -963,7 +966,7 @@ void fast_timer_init(void)
|
||||
if ((fasttimer_proc_entry = create_proc_entry( "fasttimer", 0, 0 )))
|
||||
fasttimer_proc_entry->read_proc = proc_fasttimer_read;
|
||||
#endif /* PROC_FS */
|
||||
if(request_irq(TIMER1_IRQ_NBR, timer1_handler, SA_SHIRQ,
|
||||
if(request_irq(TIMER1_IRQ_NBR, timer1_handler, 0,
|
||||
"fast timer int", NULL))
|
||||
{
|
||||
printk("err: timer1 irq\n");
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $Id: head.S,v 1.7 2004/05/14 07:58:01 starvik Exp $
|
||||
/* $Id: head.S,v 1.10 2005/06/20 05:12:54 starvik Exp $
|
||||
*
|
||||
* Head of the kernel - alter with care
|
||||
*
|
||||
@ -7,6 +7,16 @@
|
||||
* Authors: Bjorn Wesen (bjornw@axis.com)
|
||||
*
|
||||
* $Log: head.S,v $
|
||||
* Revision 1.10 2005/06/20 05:12:54 starvik
|
||||
* Remove unnecessary diff to kernel.org tree
|
||||
*
|
||||
* Revision 1.9 2004/12/13 12:21:51 starvik
|
||||
* Added I/O and DMA allocators from Linux 2.4
|
||||
*
|
||||
* Revision 1.8 2004/11/22 11:41:14 starvik
|
||||
* Kernel command line may be supplied to kernel. Not used by Axis but may
|
||||
* be used by customers.
|
||||
*
|
||||
* Revision 1.7 2004/05/14 07:58:01 starvik
|
||||
* Merge of changes from 2.4
|
||||
*
|
||||
@ -181,6 +191,7 @@
|
||||
|
||||
#define CRAMFS_MAGIC 0x28cd3d45
|
||||
#define RAM_INIT_MAGIC 0x56902387
|
||||
#define COMMAND_LINE_MAGIC 0x87109563
|
||||
|
||||
#define START_ETHERNET_CLOCK IO_STATE(R_NETWORK_GEN_CONFIG, enable, on) |\
|
||||
IO_STATE(R_NETWORK_GEN_CONFIG, phy, mii_clk)
|
||||
@ -490,6 +501,23 @@ _no_romfs_in_flash:
|
||||
|
||||
_start_it:
|
||||
|
||||
;; Check if kernel command line is supplied
|
||||
cmp.d COMMAND_LINE_MAGIC, $r10
|
||||
bne no_command_line
|
||||
nop
|
||||
|
||||
move.d 256, $r13
|
||||
move.d cris_command_line, $r10
|
||||
or.d 0x80000000, $r11 ; Make it virtual
|
||||
1:
|
||||
move.b [$r11+], $r12
|
||||
move.b $r12, [$r10+]
|
||||
subq 1, $r13
|
||||
bne 1b
|
||||
nop
|
||||
|
||||
no_command_line:
|
||||
|
||||
;; the kernel stack is overlayed with the task structure for each
|
||||
;; task. thus the initial kernel stack is in the same page as the
|
||||
;; init_task (but starts in the top of the page, size 8192)
|
||||
@ -567,76 +595,32 @@ _start_it:
|
||||
;; Etrax product HW genconfig setup
|
||||
|
||||
moveq 0,$r0
|
||||
#if (!defined(CONFIG_ETRAX_KGDB) || !defined(CONFIG_ETRAX_DEBUG_PORT0)) \
|
||||
&& !defined(CONFIG_DMA_MEMCPY)
|
||||
; DMA channels 6 and 7 to ser0, kgdb doesnt want DMA
|
||||
or.d IO_STATE (R_GEN_CONFIG, dma7, serial0) \
|
||||
| IO_STATE (R_GEN_CONFIG, dma6, serial0),$r0
|
||||
#endif
|
||||
#if !defined(CONFIG_ETRAX_KGDB) || !defined(CONFIG_ETRAX_DEBUG_PORT1)
|
||||
; DMA channels 8 and 9 to ser1, kgdb doesnt want DMA
|
||||
or.d IO_STATE (R_GEN_CONFIG, dma9, serial1) \
|
||||
| IO_STATE (R_GEN_CONFIG, dma8, serial1),$r0
|
||||
#endif
|
||||
#ifdef CONFIG_DMA_MEMCPY
|
||||
; 6/7 memory-memory DMA
|
||||
or.d IO_STATE (R_GEN_CONFIG, dma7, intdma6) \
|
||||
| IO_STATE (R_GEN_CONFIG, dma6, intdma7),$r0
|
||||
#endif
|
||||
#ifdef CONFIG_ETRAX_SERIAL_PORT2
|
||||
; Enable serial port 2
|
||||
or.w IO_STATE (R_GEN_CONFIG, ser2, select),$r0
|
||||
#if !defined(CONFIG_ETRAX_KGDB) || !defined(CONFIG_ETRAX_DEBUG_PORT2)
|
||||
; DMA channels 2 and 3 to ser2, kgdb doesnt want DMA
|
||||
or.d IO_STATE (R_GEN_CONFIG, dma3, serial2) \
|
||||
| IO_STATE (R_GEN_CONFIG, dma2, serial2),$r0
|
||||
#endif
|
||||
#endif
|
||||
#if defined(CONFIG_ETRAX_SERIAL_PORT3) || defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT1)
|
||||
; Enable serial port 3
|
||||
or.w IO_STATE (R_GEN_CONFIG, ser3, select),$r0
|
||||
#if !defined(CONFIG_ETRAX_KGDB) || !defined(CONFIG_ETRAX_DEBUG_PORT3)
|
||||
; DMA channels 4 and 5 to ser3, kgdb doesnt want DMA
|
||||
or.d IO_STATE (R_GEN_CONFIG, dma5, serial3) \
|
||||
| IO_STATE (R_GEN_CONFIG, dma4, serial3),$r0
|
||||
#endif
|
||||
#endif
|
||||
#if defined(CONFIG_ETRAX_PARALLEL_PORT0) || defined(CONFIG_ETRAX_ETHERNET_LPSLAVE)
|
||||
; parport 0 enabled using DMA 2/3
|
||||
or.w IO_STATE (R_GEN_CONFIG, par0, select),$r0
|
||||
#endif
|
||||
#if defined(CONFIG_ETRAX_PARALLEL_PORT1) || defined(CONFIG_ETRAX_ETHERNET_LPSLAVE)
|
||||
; parport 1 enabled using DMA 4/5
|
||||
or.w IO_STATE (R_GEN_CONFIG, par1, select),$r0
|
||||
#endif
|
||||
#ifdef CONFIG_ETRAX_IDE
|
||||
; DMA channels 2 and 3 to ATA, ATA enabled
|
||||
or.d IO_STATE (R_GEN_CONFIG, dma3, ata) \
|
||||
| IO_STATE (R_GEN_CONFIG, dma2, ata) \
|
||||
| IO_STATE (R_GEN_CONFIG, ata, select),$r0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ETRAX_USB_HOST_PORT1
|
||||
; Set the USB port 1 enable bit
|
||||
or.d IO_STATE (R_GEN_CONFIG, usb1, select),$r0
|
||||
#endif
|
||||
#ifdef CONFIG_ETRAX_USB_HOST_PORT2
|
||||
; Set the USB port 2 enable bit
|
||||
or.d IO_STATE (R_GEN_CONFIG, usb2, select),$r0
|
||||
#endif
|
||||
#ifdef CONFIG_ETRAX_USB_HOST
|
||||
; Connect DMA channels 8 and 9 to USB
|
||||
and.d (~(IO_MASK (R_GEN_CONFIG, dma9) \
|
||||
| IO_MASK (R_GEN_CONFIG, dma8))) \
|
||||
| IO_STATE (R_GEN_CONFIG, dma9, usb) \
|
||||
| IO_STATE (R_GEN_CONFIG, dma8, usb),$r0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_JULIETTE
|
||||
; DMA channels 4 and 5 to EXTDMA0, for Juliette
|
||||
or.d IO_STATE (R_GEN_CONFIG, dma5, extdma0) \
|
||||
| IO_STATE (R_GEN_CONFIG, dma4, extdma0),$r0
|
||||
#endif
|
||||
|
||||
;; Init interfaces (disable them).
|
||||
or.d IO_STATE (R_GEN_CONFIG, scsi0, disable) \
|
||||
| IO_STATE (R_GEN_CONFIG, ata, disable) \
|
||||
| IO_STATE (R_GEN_CONFIG, par0, disable) \
|
||||
| IO_STATE (R_GEN_CONFIG, ser2, disable) \
|
||||
| IO_STATE (R_GEN_CONFIG, mio, disable) \
|
||||
| IO_STATE (R_GEN_CONFIG, scsi1, disable) \
|
||||
| IO_STATE (R_GEN_CONFIG, scsi0w, disable) \
|
||||
| IO_STATE (R_GEN_CONFIG, par1, disable) \
|
||||
| IO_STATE (R_GEN_CONFIG, ser3, disable) \
|
||||
| IO_STATE (R_GEN_CONFIG, mio_w, disable) \
|
||||
| IO_STATE (R_GEN_CONFIG, usb1, disable) \
|
||||
| IO_STATE (R_GEN_CONFIG, usb2, disable) \
|
||||
| IO_STATE (R_GEN_CONFIG, par_w, disable),$r0
|
||||
|
||||
;; Init DMA channel muxing (set to unused clients).
|
||||
or.d IO_STATE (R_GEN_CONFIG, dma2, ata) \
|
||||
| IO_STATE (R_GEN_CONFIG, dma3, ata) \
|
||||
| IO_STATE (R_GEN_CONFIG, dma4, scsi1) \
|
||||
| IO_STATE (R_GEN_CONFIG, dma5, scsi1) \
|
||||
| IO_STATE (R_GEN_CONFIG, dma6, unused) \
|
||||
| IO_STATE (R_GEN_CONFIG, dma7, unused) \
|
||||
| IO_STATE (R_GEN_CONFIG, dma8, usb) \
|
||||
| IO_STATE (R_GEN_CONFIG, dma9, usb),$r0
|
||||
|
||||
|
||||
#if defined(CONFIG_ETRAX_DEF_R_PORT_G0_DIR_OUT)
|
||||
or.d IO_STATE (R_GEN_CONFIG, g0dir, out),$r0
|
||||
|
879
arch/cris/arch-v10/kernel/io_interface_mux.c
Normal file
879
arch/cris/arch-v10/kernel/io_interface_mux.c
Normal file
@ -0,0 +1,879 @@
|
||||
/* IO interface mux allocator for ETRAX100LX.
|
||||
* Copyright 2004, Axis Communications AB
|
||||
* $Id: io_interface_mux.c,v 1.2 2004/12/21 12:08:38 starvik Exp $
|
||||
*/
|
||||
|
||||
|
||||
/* C.f. ETRAX100LX Designer's Reference 20.9 */
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <asm/arch/svinto.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/io_interface_mux.h>
|
||||
|
||||
|
||||
#define DBG(s)
|
||||
|
||||
/* Macro to access ETRAX 100 registers */
|
||||
#define SETS(var, reg, field, val) var = (var & ~IO_MASK_(reg##_, field##_)) | \
|
||||
IO_STATE_(reg##_, field##_, _##val)
|
||||
|
||||
enum io_if_group {
|
||||
group_a = (1<<0),
|
||||
group_b = (1<<1),
|
||||
group_c = (1<<2),
|
||||
group_d = (1<<3),
|
||||
group_e = (1<<4),
|
||||
group_f = (1<<5)
|
||||
};
|
||||
|
||||
struct watcher
|
||||
{
|
||||
void (*notify)(const unsigned int gpio_in_available,
|
||||
const unsigned int gpio_out_available,
|
||||
const unsigned char pa_available,
|
||||
const unsigned char pb_available);
|
||||
struct watcher *next;
|
||||
};
|
||||
|
||||
|
||||
struct if_group
|
||||
{
|
||||
enum io_if_group group;
|
||||
unsigned char used;
|
||||
enum cris_io_interface owner;
|
||||
};
|
||||
|
||||
|
||||
struct interface
|
||||
{
|
||||
enum cris_io_interface ioif;
|
||||
unsigned char groups;
|
||||
unsigned char used;
|
||||
char *owner;
|
||||
unsigned int gpio_g_in;
|
||||
unsigned int gpio_g_out;
|
||||
unsigned char gpio_b;
|
||||
};
|
||||
|
||||
static struct if_group if_groups[6] = {
|
||||
{
|
||||
.group = group_a,
|
||||
.used = 0,
|
||||
},
|
||||
{
|
||||
.group = group_b,
|
||||
.used = 0,
|
||||
},
|
||||
{
|
||||
.group = group_c,
|
||||
.used = 0,
|
||||
},
|
||||
{
|
||||
.group = group_d,
|
||||
.used = 0,
|
||||
},
|
||||
{
|
||||
.group = group_e,
|
||||
.used = 0,
|
||||
},
|
||||
{
|
||||
.group = group_f,
|
||||
.used = 0,
|
||||
}
|
||||
};
|
||||
|
||||
/* The order in the array must match the order of enum
|
||||
* cris_io_interface in io_interface_mux.h */
|
||||
static struct interface interfaces[] = {
|
||||
/* Begin Non-multiplexed interfaces */
|
||||
{
|
||||
.ioif = if_eth,
|
||||
.groups = 0,
|
||||
.gpio_g_in = 0,
|
||||
.gpio_g_out = 0,
|
||||
.gpio_b = 0
|
||||
},
|
||||
{
|
||||
.ioif = if_serial_0,
|
||||
.groups = 0,
|
||||
.gpio_g_in = 0,
|
||||
.gpio_g_out = 0,
|
||||
.gpio_b = 0
|
||||
},
|
||||
/* End Non-multiplexed interfaces */
|
||||
{
|
||||
.ioif = if_serial_1,
|
||||
.groups = group_e,
|
||||
.gpio_g_in = 0x00000000,
|
||||
.gpio_g_out = 0x00000000,
|
||||
.gpio_b = 0x00
|
||||
},
|
||||
{
|
||||
.ioif = if_serial_2,
|
||||
.groups = group_b,
|
||||
.gpio_g_in = 0x000000c0,
|
||||
.gpio_g_out = 0x000000c0,
|
||||
.gpio_b = 0x00
|
||||
},
|
||||
{
|
||||
.ioif = if_serial_3,
|
||||
.groups = group_c,
|
||||
.gpio_g_in = 0xc0000000,
|
||||
.gpio_g_out = 0xc0000000,
|
||||
.gpio_b = 0x00
|
||||
},
|
||||
{
|
||||
.ioif = if_sync_serial_1,
|
||||
.groups = group_e | group_f, /* if_sync_serial_1 and if_sync_serial_3
|
||||
can be used simultaneously */
|
||||
.gpio_g_in = 0x00000000,
|
||||
.gpio_g_out = 0x00000000,
|
||||
.gpio_b = 0x10
|
||||
},
|
||||
{
|
||||
.ioif = if_sync_serial_3,
|
||||
.groups = group_c | group_f,
|
||||
.gpio_g_in = 0xc0000000,
|
||||
.gpio_g_out = 0xc0000000,
|
||||
.gpio_b = 0x80
|
||||
},
|
||||
{
|
||||
.ioif = if_shared_ram,
|
||||
.groups = group_a,
|
||||
.gpio_g_in = 0x0000ff3e,
|
||||
.gpio_g_out = 0x0000ff38,
|
||||
.gpio_b = 0x00
|
||||
},
|
||||
{
|
||||
.ioif = if_shared_ram_w,
|
||||
.groups = group_a | group_d,
|
||||
.gpio_g_in = 0x00ffff3e,
|
||||
.gpio_g_out = 0x00ffff38,
|
||||
.gpio_b = 0x00
|
||||
},
|
||||
{
|
||||
.ioif = if_par_0,
|
||||
.groups = group_a,
|
||||
.gpio_g_in = 0x0000ff3e,
|
||||
.gpio_g_out = 0x0000ff3e,
|
||||
.gpio_b = 0x00
|
||||
},
|
||||
{
|
||||
.ioif = if_par_1,
|
||||
.groups = group_d,
|
||||
.gpio_g_in = 0x3eff0000,
|
||||
.gpio_g_out = 0x3eff0000,
|
||||
.gpio_b = 0x00
|
||||
},
|
||||
{
|
||||
.ioif = if_par_w,
|
||||
.groups = group_a | group_d,
|
||||
.gpio_g_in = 0x00ffff3e,
|
||||
.gpio_g_out = 0x00ffff3e,
|
||||
.gpio_b = 0x00
|
||||
},
|
||||
{
|
||||
.ioif = if_scsi8_0,
|
||||
.groups = group_a | group_b | group_f, /* if_scsi8_0 and if_scsi8_1
|
||||
can be used simultaneously */
|
||||
.gpio_g_in = 0x0000ffff,
|
||||
.gpio_g_out = 0x0000ffff,
|
||||
.gpio_b = 0x10
|
||||
},
|
||||
{
|
||||
.ioif = if_scsi8_1,
|
||||
.groups = group_c | group_d | group_f, /* if_scsi8_0 and if_scsi8_1
|
||||
can be used simultaneously */
|
||||
.gpio_g_in = 0xffff0000,
|
||||
.gpio_g_out = 0xffff0000,
|
||||
.gpio_b = 0x80
|
||||
},
|
||||
{
|
||||
.ioif = if_scsi_w,
|
||||
.groups = group_a | group_b | group_d | group_f,
|
||||
.gpio_g_in = 0x01ffffff,
|
||||
.gpio_g_out = 0x07ffffff,
|
||||
.gpio_b = 0x80
|
||||
},
|
||||
{
|
||||
.ioif = if_ata,
|
||||
.groups = group_a | group_b | group_c | group_d,
|
||||
.gpio_g_in = 0xf9ffffff,
|
||||
.gpio_g_out = 0xffffffff,
|
||||
.gpio_b = 0x80
|
||||
},
|
||||
{
|
||||
.ioif = if_csp,
|
||||
.groups = group_f, /* if_csp and if_i2c can be used simultaneously */
|
||||
.gpio_g_in = 0x00000000,
|
||||
.gpio_g_out = 0x00000000,
|
||||
.gpio_b = 0xfc
|
||||
},
|
||||
{
|
||||
.ioif = if_i2c,
|
||||
.groups = group_f, /* if_csp and if_i2c can be used simultaneously */
|
||||
.gpio_g_in = 0x00000000,
|
||||
.gpio_g_out = 0x00000000,
|
||||
.gpio_b = 0x03
|
||||
},
|
||||
{
|
||||
.ioif = if_usb_1,
|
||||
.groups = group_e | group_f,
|
||||
.gpio_g_in = 0x00000000,
|
||||
.gpio_g_out = 0x00000000,
|
||||
.gpio_b = 0x2c
|
||||
},
|
||||
{
|
||||
.ioif = if_usb_2,
|
||||
.groups = group_d,
|
||||
.gpio_g_in = 0x0e000000,
|
||||
.gpio_g_out = 0x3c000000,
|
||||
.gpio_b = 0x00
|
||||
},
|
||||
/* GPIO pins */
|
||||
{
|
||||
.ioif = if_gpio_grp_a,
|
||||
.groups = group_a,
|
||||
.gpio_g_in = 0x0000ff3f,
|
||||
.gpio_g_out = 0x0000ff3f,
|
||||
.gpio_b = 0x00
|
||||
},
|
||||
{
|
||||
.ioif = if_gpio_grp_b,
|
||||
.groups = group_b,
|
||||
.gpio_g_in = 0x000000c0,
|
||||
.gpio_g_out = 0x000000c0,
|
||||
.gpio_b = 0x00
|
||||
},
|
||||
{
|
||||
.ioif = if_gpio_grp_c,
|
||||
.groups = group_c,
|
||||
.gpio_g_in = 0xc0000000,
|
||||
.gpio_g_out = 0xc0000000,
|
||||
.gpio_b = 0x00
|
||||
},
|
||||
{
|
||||
.ioif = if_gpio_grp_d,
|
||||
.groups = group_d,
|
||||
.gpio_g_in = 0x3fff0000,
|
||||
.gpio_g_out = 0x3fff0000,
|
||||
.gpio_b = 0x00
|
||||
},
|
||||
{
|
||||
.ioif = if_gpio_grp_e,
|
||||
.groups = group_e,
|
||||
.gpio_g_in = 0x00000000,
|
||||
.gpio_g_out = 0x00000000,
|
||||
.gpio_b = 0x00
|
||||
},
|
||||
{
|
||||
.ioif = if_gpio_grp_f,
|
||||
.groups = group_f,
|
||||
.gpio_g_in = 0x00000000,
|
||||
.gpio_g_out = 0x00000000,
|
||||
.gpio_b = 0xff
|
||||
}
|
||||
/* Array end */
|
||||
};
|
||||
|
||||
static struct watcher *watchers = NULL;
|
||||
|
||||
static unsigned int gpio_in_pins = 0xffffffff;
|
||||
static unsigned int gpio_out_pins = 0xffffffff;
|
||||
static unsigned char gpio_pb_pins = 0xff;
|
||||
static unsigned char gpio_pa_pins = 0xff;
|
||||
|
||||
static enum cris_io_interface gpio_pa_owners[8];
|
||||
static enum cris_io_interface gpio_pb_owners[8];
|
||||
static enum cris_io_interface gpio_pg_owners[32];
|
||||
|
||||
static int cris_io_interface_init(void);
|
||||
|
||||
static unsigned char clear_group_from_set(const unsigned char groups, struct if_group *group)
|
||||
{
|
||||
return (groups & ~group->group);
|
||||
}
|
||||
|
||||
|
||||
static struct if_group *get_group(const unsigned char groups)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < sizeof(if_groups)/sizeof(struct if_group); i++) {
|
||||
if (groups & if_groups[i].group) {
|
||||
return &if_groups[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void notify_watchers(void)
|
||||
{
|
||||
struct watcher *w = watchers;
|
||||
|
||||
DBG(printk("io_interface_mux: notifying watchers\n"));
|
||||
|
||||
while (NULL != w) {
|
||||
w->notify((const unsigned int)gpio_in_pins,
|
||||
(const unsigned int)gpio_out_pins,
|
||||
(const unsigned char)gpio_pa_pins,
|
||||
(const unsigned char)gpio_pb_pins);
|
||||
w = w->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int cris_request_io_interface(enum cris_io_interface ioif, const char *device_id)
|
||||
{
|
||||
int set_gen_config = 0;
|
||||
int set_gen_config_ii = 0;
|
||||
unsigned long int gens;
|
||||
unsigned long int gens_ii;
|
||||
struct if_group *grp;
|
||||
unsigned char group_set;
|
||||
unsigned long flags;
|
||||
|
||||
(void)cris_io_interface_init();
|
||||
|
||||
DBG(printk("cris_request_io_interface(%d, \"%s\")\n", ioif, device_id));
|
||||
|
||||
if ((ioif >= if_max_interfaces) || (ioif < 0)) {
|
||||
printk(KERN_CRIT "cris_request_io_interface: Bad interface %u submitted for %s\n",
|
||||
ioif,
|
||||
device_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
if (interfaces[ioif].used) {
|
||||
local_irq_restore(flags);
|
||||
printk(KERN_CRIT "cris_io_interface: Cannot allocate interface for %s, in use by %s\n",
|
||||
device_id,
|
||||
interfaces[ioif].owner);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* Check that all required groups are free before allocating, */
|
||||
group_set = interfaces[ioif].groups;
|
||||
while (NULL != (grp = get_group(group_set))) {
|
||||
if (grp->used) {
|
||||
if (grp->group == group_f) {
|
||||
if ((if_sync_serial_1 == ioif) ||
|
||||
(if_sync_serial_3 == ioif)) {
|
||||
if ((grp->owner != if_sync_serial_1) &&
|
||||
(grp->owner != if_sync_serial_3)) {
|
||||
local_irq_restore(flags);
|
||||
return -EBUSY;
|
||||
}
|
||||
} else if ((if_scsi8_0 == ioif) ||
|
||||
(if_scsi8_1 == ioif)) {
|
||||
if ((grp->owner != if_scsi8_0) &&
|
||||
(grp->owner != if_scsi8_1)) {
|
||||
local_irq_restore(flags);
|
||||
return -EBUSY;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
local_irq_restore(flags);
|
||||
return -EBUSY;
|
||||
}
|
||||
}
|
||||
group_set = clear_group_from_set(group_set, grp);
|
||||
}
|
||||
|
||||
/* Are the required GPIO pins available too? */
|
||||
if (((interfaces[ioif].gpio_g_in & gpio_in_pins) != interfaces[ioif].gpio_g_in) ||
|
||||
((interfaces[ioif].gpio_g_out & gpio_out_pins) != interfaces[ioif].gpio_g_out) ||
|
||||
((interfaces[ioif].gpio_b & gpio_pb_pins) != interfaces[ioif].gpio_b)) {
|
||||
printk(KERN_CRIT "cris_request_io_interface: Could not get required pins for interface %u\n",
|
||||
ioif);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* All needed I/O pins and pin groups are free, allocate. */
|
||||
group_set = interfaces[ioif].groups;
|
||||
while (NULL != (grp = get_group(group_set))) {
|
||||
grp->used = 1;
|
||||
grp->owner = ioif;
|
||||
group_set = clear_group_from_set(group_set, grp);
|
||||
}
|
||||
|
||||
gens = genconfig_shadow;
|
||||
gens_ii = gen_config_ii_shadow;
|
||||
|
||||
set_gen_config = 1;
|
||||
switch (ioif)
|
||||
{
|
||||
/* Begin Non-multiplexed interfaces */
|
||||
case if_eth:
|
||||
/* fall through */
|
||||
case if_serial_0:
|
||||
set_gen_config = 0;
|
||||
break;
|
||||
/* End Non-multiplexed interfaces */
|
||||
case if_serial_1:
|
||||
set_gen_config_ii = 1;
|
||||
SETS(gens_ii, R_GEN_CONFIG_II, sermode1, async);
|
||||
break;
|
||||
case if_serial_2:
|
||||
SETS(gens, R_GEN_CONFIG, ser2, select);
|
||||
break;
|
||||
case if_serial_3:
|
||||
SETS(gens, R_GEN_CONFIG, ser3, select);
|
||||
set_gen_config_ii = 1;
|
||||
SETS(gens_ii, R_GEN_CONFIG_II, sermode3, async);
|
||||
break;
|
||||
case if_sync_serial_1:
|
||||
set_gen_config_ii = 1;
|
||||
SETS(gens_ii, R_GEN_CONFIG_II, sermode1, sync);
|
||||
break;
|
||||
case if_sync_serial_3:
|
||||
SETS(gens, R_GEN_CONFIG, ser3, select);
|
||||
set_gen_config_ii = 1;
|
||||
SETS(gens_ii, R_GEN_CONFIG_II, sermode3, sync);
|
||||
break;
|
||||
case if_shared_ram:
|
||||
SETS(gens, R_GEN_CONFIG, mio, select);
|
||||
break;
|
||||
case if_shared_ram_w:
|
||||
SETS(gens, R_GEN_CONFIG, mio_w, select);
|
||||
break;
|
||||
case if_par_0:
|
||||
SETS(gens, R_GEN_CONFIG, par0, select);
|
||||
break;
|
||||
case if_par_1:
|
||||
SETS(gens, R_GEN_CONFIG, par1, select);
|
||||
break;
|
||||
case if_par_w:
|
||||
SETS(gens, R_GEN_CONFIG, par0, select);
|
||||
SETS(gens, R_GEN_CONFIG, par_w, select);
|
||||
break;
|
||||
case if_scsi8_0:
|
||||
SETS(gens, R_GEN_CONFIG, scsi0, select);
|
||||
break;
|
||||
case if_scsi8_1:
|
||||
SETS(gens, R_GEN_CONFIG, scsi1, select);
|
||||
break;
|
||||
case if_scsi_w:
|
||||
SETS(gens, R_GEN_CONFIG, scsi0, select);
|
||||
SETS(gens, R_GEN_CONFIG, scsi0w, select);
|
||||
break;
|
||||
case if_ata:
|
||||
SETS(gens, R_GEN_CONFIG, ata, select);
|
||||
break;
|
||||
case if_csp:
|
||||
/* fall through */
|
||||
case if_i2c:
|
||||
set_gen_config = 0;
|
||||
break;
|
||||
case if_usb_1:
|
||||
SETS(gens, R_GEN_CONFIG, usb1, select);
|
||||
break;
|
||||
case if_usb_2:
|
||||
SETS(gens, R_GEN_CONFIG, usb2, select);
|
||||
break;
|
||||
case if_gpio_grp_a:
|
||||
/* GPIO groups are only accounted, don't do configuration changes. */
|
||||
/* fall through */
|
||||
case if_gpio_grp_b:
|
||||
/* fall through */
|
||||
case if_gpio_grp_c:
|
||||
/* fall through */
|
||||
case if_gpio_grp_d:
|
||||
/* fall through */
|
||||
case if_gpio_grp_e:
|
||||
/* fall through */
|
||||
case if_gpio_grp_f:
|
||||
set_gen_config = 0;
|
||||
break;
|
||||
default:
|
||||
panic("cris_request_io_interface: Bad interface %u submitted for %s\n",
|
||||
ioif,
|
||||
device_id);
|
||||
}
|
||||
|
||||
interfaces[ioif].used = 1;
|
||||
interfaces[ioif].owner = (char*)device_id;
|
||||
|
||||
if (set_gen_config) {
|
||||
volatile int i;
|
||||
genconfig_shadow = gens;
|
||||
*R_GEN_CONFIG = genconfig_shadow;
|
||||
/* Wait 12 cycles before doing any DMA command */
|
||||
for(i = 6; i > 0; i--)
|
||||
nop();
|
||||
}
|
||||
if (set_gen_config_ii) {
|
||||
gen_config_ii_shadow = gens_ii;
|
||||
*R_GEN_CONFIG_II = gen_config_ii_shadow;
|
||||
}
|
||||
|
||||
DBG(printk("GPIO pins: available before: g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
|
||||
gpio_in_pins, gpio_out_pins, gpio_pb_pins));
|
||||
DBG(printk("grabbing pins: g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
|
||||
interfaces[ioif].gpio_g_in,
|
||||
interfaces[ioif].gpio_g_out,
|
||||
interfaces[ioif].gpio_b));
|
||||
|
||||
gpio_in_pins &= ~interfaces[ioif].gpio_g_in;
|
||||
gpio_out_pins &= ~interfaces[ioif].gpio_g_out;
|
||||
gpio_pb_pins &= ~interfaces[ioif].gpio_b;
|
||||
|
||||
DBG(printk("GPIO pins: available after: g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
|
||||
gpio_in_pins, gpio_out_pins, gpio_pb_pins));
|
||||
|
||||
local_irq_restore(flags);
|
||||
|
||||
notify_watchers();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void cris_free_io_interface(enum cris_io_interface ioif)
|
||||
{
|
||||
struct if_group *grp;
|
||||
unsigned char group_set;
|
||||
unsigned long flags;
|
||||
|
||||
(void)cris_io_interface_init();
|
||||
|
||||
if ((ioif >= if_max_interfaces) || (ioif < 0)) {
|
||||
printk(KERN_CRIT "cris_free_io_interface: Bad interface %u\n",
|
||||
ioif);
|
||||
return;
|
||||
}
|
||||
local_irq_save(flags);
|
||||
if (!interfaces[ioif].used) {
|
||||
printk(KERN_CRIT "cris_free_io_interface: Freeing free interface %u\n",
|
||||
ioif);
|
||||
local_irq_restore(flags);
|
||||
return;
|
||||
}
|
||||
group_set = interfaces[ioif].groups;
|
||||
while (NULL != (grp = get_group(group_set))) {
|
||||
if (grp->group == group_f) {
|
||||
switch (ioif)
|
||||
{
|
||||
case if_sync_serial_1:
|
||||
if ((grp->owner == if_sync_serial_1) &&
|
||||
interfaces[if_sync_serial_3].used) {
|
||||
grp->owner = if_sync_serial_3;
|
||||
} else
|
||||
grp->used = 0;
|
||||
break;
|
||||
case if_sync_serial_3:
|
||||
if ((grp->owner == if_sync_serial_3) &&
|
||||
interfaces[if_sync_serial_1].used) {
|
||||
grp->owner = if_sync_serial_1;
|
||||
} else
|
||||
grp->used = 0;
|
||||
break;
|
||||
case if_scsi8_0:
|
||||
if ((grp->owner == if_scsi8_0) &&
|
||||
interfaces[if_scsi8_1].used) {
|
||||
grp->owner = if_scsi8_1;
|
||||
} else
|
||||
grp->used = 0;
|
||||
break;
|
||||
case if_scsi8_1:
|
||||
if ((grp->owner == if_scsi8_1) &&
|
||||
interfaces[if_scsi8_0].used) {
|
||||
grp->owner = if_scsi8_0;
|
||||
} else
|
||||
grp->used = 0;
|
||||
break;
|
||||
default:
|
||||
grp->used = 0;
|
||||
}
|
||||
} else {
|
||||
grp->used = 0;
|
||||
}
|
||||
group_set = clear_group_from_set(group_set, grp);
|
||||
}
|
||||
interfaces[ioif].used = 0;
|
||||
interfaces[ioif].owner = NULL;
|
||||
|
||||
DBG(printk("GPIO pins: available before: g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
|
||||
gpio_in_pins, gpio_out_pins, gpio_pb_pins));
|
||||
DBG(printk("freeing pins: g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
|
||||
interfaces[ioif].gpio_g_in,
|
||||
interfaces[ioif].gpio_g_out,
|
||||
interfaces[ioif].gpio_b));
|
||||
|
||||
gpio_in_pins |= interfaces[ioif].gpio_g_in;
|
||||
gpio_out_pins |= interfaces[ioif].gpio_g_out;
|
||||
gpio_pb_pins |= interfaces[ioif].gpio_b;
|
||||
|
||||
DBG(printk("GPIO pins: available after: g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
|
||||
gpio_in_pins, gpio_out_pins, gpio_pb_pins));
|
||||
|
||||
local_irq_restore(flags);
|
||||
|
||||
notify_watchers();
|
||||
}
|
||||
|
||||
/* Create a bitmask from bit 0 (inclusive) to bit stop_bit
|
||||
(non-inclusive). stop_bit == 0 returns 0x0 */
|
||||
static inline unsigned int create_mask(const unsigned stop_bit)
|
||||
{
|
||||
/* Avoid overflow */
|
||||
if (stop_bit >= 32) {
|
||||
return 0xffffffff;
|
||||
}
|
||||
return (1<<stop_bit)-1;
|
||||
}
|
||||
|
||||
|
||||
/* port can be 'a', 'b' or 'g' */
|
||||
int cris_io_interface_allocate_pins(const enum cris_io_interface ioif,
|
||||
const char port,
|
||||
const unsigned start_bit,
|
||||
const unsigned stop_bit)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int mask = 0;
|
||||
unsigned int tmp_mask;
|
||||
unsigned long int flags;
|
||||
enum cris_io_interface *owners;
|
||||
|
||||
(void)cris_io_interface_init();
|
||||
|
||||
DBG(printk("cris_io_interface_allocate_pins: if=%d port=%c start=%u stop=%u\n",
|
||||
ioif, port, start_bit, stop_bit));
|
||||
|
||||
if (!((start_bit <= stop_bit) &&
|
||||
((((port == 'a') || (port == 'b')) && (stop_bit < 8)) ||
|
||||
((port == 'g') && (stop_bit < 32))))) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mask = create_mask(stop_bit + 1);
|
||||
tmp_mask = create_mask(start_bit);
|
||||
mask &= ~tmp_mask;
|
||||
|
||||
DBG(printk("cris_io_interface_allocate_pins: port=%c start=%u stop=%u mask=0x%08x\n",
|
||||
port, start_bit, stop_bit, mask));
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
switch (port) {
|
||||
case 'a':
|
||||
if ((gpio_pa_pins & mask) != mask) {
|
||||
local_irq_restore(flags);
|
||||
return -EBUSY;
|
||||
}
|
||||
owners = gpio_pa_owners;
|
||||
gpio_pa_pins &= ~mask;
|
||||
break;
|
||||
case 'b':
|
||||
if ((gpio_pb_pins & mask) != mask) {
|
||||
local_irq_restore(flags);
|
||||
return -EBUSY;
|
||||
}
|
||||
owners = gpio_pb_owners;
|
||||
gpio_pb_pins &= ~mask;
|
||||
break;
|
||||
case 'g':
|
||||
if (((gpio_in_pins & mask) != mask) ||
|
||||
((gpio_out_pins & mask) != mask)) {
|
||||
local_irq_restore(flags);
|
||||
return -EBUSY;
|
||||
}
|
||||
owners = gpio_pg_owners;
|
||||
gpio_in_pins &= ~mask;
|
||||
gpio_out_pins &= ~mask;
|
||||
break;
|
||||
default:
|
||||
local_irq_restore(flags);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = start_bit; i <= stop_bit; i++) {
|
||||
owners[i] = ioif;
|
||||
}
|
||||
local_irq_restore(flags);
|
||||
|
||||
notify_watchers();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* port can be 'a', 'b' or 'g' */
|
||||
int cris_io_interface_free_pins(const enum cris_io_interface ioif,
|
||||
const char port,
|
||||
const unsigned start_bit,
|
||||
const unsigned stop_bit)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int mask = 0;
|
||||
unsigned int tmp_mask;
|
||||
unsigned long int flags;
|
||||
enum cris_io_interface *owners;
|
||||
|
||||
(void)cris_io_interface_init();
|
||||
|
||||
if (!((start_bit <= stop_bit) &&
|
||||
((((port == 'a') || (port == 'b')) && (stop_bit < 8)) ||
|
||||
((port == 'g') && (stop_bit < 32))))) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mask = create_mask(stop_bit + 1);
|
||||
tmp_mask = create_mask(start_bit);
|
||||
mask &= ~tmp_mask;
|
||||
|
||||
DBG(printk("cris_io_interface_free_pins: port=%c start=%u stop=%u mask=0x%08x\n",
|
||||
port, start_bit, stop_bit, mask));
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
switch (port) {
|
||||
case 'a':
|
||||
if ((~gpio_pa_pins & mask) != mask) {
|
||||
local_irq_restore(flags);
|
||||
printk(KERN_CRIT "cris_io_interface_free_pins: Freeing free pins");
|
||||
}
|
||||
owners = gpio_pa_owners;
|
||||
break;
|
||||
case 'b':
|
||||
if ((~gpio_pb_pins & mask) != mask) {
|
||||
local_irq_restore(flags);
|
||||
printk(KERN_CRIT "cris_io_interface_free_pins: Freeing free pins");
|
||||
}
|
||||
owners = gpio_pb_owners;
|
||||
break;
|
||||
case 'g':
|
||||
if (((~gpio_in_pins & mask) != mask) ||
|
||||
((~gpio_out_pins & mask) != mask)) {
|
||||
local_irq_restore(flags);
|
||||
printk(KERN_CRIT "cris_io_interface_free_pins: Freeing free pins");
|
||||
}
|
||||
owners = gpio_pg_owners;
|
||||
break;
|
||||
default:
|
||||
owners = NULL; /* Cannot happen. Shut up, gcc! */
|
||||
}
|
||||
|
||||
for (i = start_bit; i <= stop_bit; i++) {
|
||||
if (owners[i] != ioif) {
|
||||
printk(KERN_CRIT "cris_io_interface_free_pins: Freeing unowned pins");
|
||||
}
|
||||
}
|
||||
|
||||
/* All was ok, change data. */
|
||||
switch (port) {
|
||||
case 'a':
|
||||
gpio_pa_pins |= mask;
|
||||
break;
|
||||
case 'b':
|
||||
gpio_pb_pins |= mask;
|
||||
break;
|
||||
case 'g':
|
||||
gpio_in_pins |= mask;
|
||||
gpio_out_pins |= mask;
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = start_bit; i <= stop_bit; i++) {
|
||||
owners[i] = if_unclaimed;
|
||||
}
|
||||
local_irq_restore(flags);
|
||||
notify_watchers();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int cris_io_interface_register_watcher(void (*notify)(const unsigned int gpio_in_available,
|
||||
const unsigned int gpio_out_available,
|
||||
const unsigned char pa_available,
|
||||
const unsigned char pb_available))
|
||||
{
|
||||
struct watcher *w;
|
||||
|
||||
(void)cris_io_interface_init();
|
||||
|
||||
if (NULL == notify) {
|
||||
return -EINVAL;
|
||||
}
|
||||
w = kmalloc(sizeof(*w), GFP_KERNEL);
|
||||
if (!w) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
w->notify = notify;
|
||||
w->next = watchers;
|
||||
watchers = w;
|
||||
|
||||
w->notify((const unsigned int)gpio_in_pins,
|
||||
(const unsigned int)gpio_out_pins,
|
||||
(const unsigned char)gpio_pa_pins,
|
||||
(const unsigned char)gpio_pb_pins);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cris_io_interface_delete_watcher(void (*notify)(const unsigned int gpio_in_available,
|
||||
const unsigned int gpio_out_available,
|
||||
const unsigned char pa_available,
|
||||
const unsigned char pb_available))
|
||||
{
|
||||
struct watcher *w = watchers, *prev = NULL;
|
||||
|
||||
(void)cris_io_interface_init();
|
||||
|
||||
while ((NULL != w) && (w->notify != notify)){
|
||||
prev = w;
|
||||
w = w->next;
|
||||
}
|
||||
if (NULL != w) {
|
||||
if (NULL != prev) {
|
||||
prev->next = w->next;
|
||||
} else {
|
||||
watchers = w->next;
|
||||
}
|
||||
kfree(w);
|
||||
return;
|
||||
}
|
||||
printk(KERN_WARNING "cris_io_interface_delete_watcher: Deleting unknown watcher 0x%p\n", notify);
|
||||
}
|
||||
|
||||
|
||||
static int cris_io_interface_init(void)
|
||||
{
|
||||
static int first = 1;
|
||||
int i;
|
||||
|
||||
if (!first) {
|
||||
return 0;
|
||||
}
|
||||
first = 0;
|
||||
|
||||
for (i = 0; i<8; i++) {
|
||||
gpio_pa_owners[i] = if_unclaimed;
|
||||
gpio_pb_owners[i] = if_unclaimed;
|
||||
gpio_pg_owners[i] = if_unclaimed;
|
||||
}
|
||||
for (; i<32; i++) {
|
||||
gpio_pg_owners[i] = if_unclaimed;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
module_init(cris_io_interface_init);
|
||||
|
||||
|
||||
EXPORT_SYMBOL(cris_request_io_interface);
|
||||
EXPORT_SYMBOL(cris_free_io_interface);
|
||||
EXPORT_SYMBOL(cris_io_interface_allocate_pins);
|
||||
EXPORT_SYMBOL(cris_io_interface_free_pins);
|
||||
EXPORT_SYMBOL(cris_io_interface_register_watcher);
|
||||
EXPORT_SYMBOL(cris_io_interface_delete_watcher);
|
@ -1,4 +1,4 @@
|
||||
/* $Id: irq.c,v 1.2 2004/06/09 05:30:27 starvik Exp $
|
||||
/* $Id: irq.c,v 1.4 2005/01/04 12:22:28 starvik Exp $
|
||||
*
|
||||
* linux/arch/cris/kernel/irq.c
|
||||
*
|
||||
@ -12,11 +12,13 @@
|
||||
*/
|
||||
|
||||
#include <asm/irq.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/config.h>
|
||||
|
||||
irqvectptr irq_shortcuts[NR_IRQS]; /* vector of shortcut jumps after the irq prologue */
|
||||
#define mask_irq(irq_nr) (*R_VECT_MASK_CLR = 1 << (irq_nr));
|
||||
#define unmask_irq(irq_nr) (*R_VECT_MASK_SET = 1 << (irq_nr));
|
||||
|
||||
/* don't use set_int_vector, it bypasses the linux interrupt handlers. it is
|
||||
* global just so that the kernel gdb can use it.
|
||||
@ -102,41 +104,52 @@ static void (*interrupt[NR_IRQS])(void) = {
|
||||
IRQ31_interrupt
|
||||
};
|
||||
|
||||
static void (*bad_interrupt[NR_IRQS])(void) = {
|
||||
NULL, NULL,
|
||||
NULL, bad_IRQ3_interrupt,
|
||||
bad_IRQ4_interrupt, bad_IRQ5_interrupt,
|
||||
bad_IRQ6_interrupt, bad_IRQ7_interrupt,
|
||||
bad_IRQ8_interrupt, bad_IRQ9_interrupt,
|
||||
bad_IRQ10_interrupt, bad_IRQ11_interrupt,
|
||||
bad_IRQ12_interrupt, bad_IRQ13_interrupt,
|
||||
NULL, NULL,
|
||||
bad_IRQ16_interrupt, bad_IRQ17_interrupt,
|
||||
bad_IRQ18_interrupt, bad_IRQ19_interrupt,
|
||||
bad_IRQ20_interrupt, bad_IRQ21_interrupt,
|
||||
bad_IRQ22_interrupt, bad_IRQ23_interrupt,
|
||||
bad_IRQ24_interrupt, bad_IRQ25_interrupt,
|
||||
NULL, NULL, NULL, NULL, NULL,
|
||||
bad_IRQ31_interrupt
|
||||
static void enable_crisv10_irq(unsigned int irq);
|
||||
|
||||
static unsigned int startup_crisv10_irq(unsigned int irq)
|
||||
{
|
||||
enable_crisv10_irq(irq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define shutdown_crisv10_irq disable_crisv10_irq
|
||||
|
||||
static void enable_crisv10_irq(unsigned int irq)
|
||||
{
|
||||
unmask_irq(irq);
|
||||
}
|
||||
|
||||
static void disable_crisv10_irq(unsigned int irq)
|
||||
{
|
||||
mask_irq(irq);
|
||||
}
|
||||
|
||||
static void ack_crisv10_irq(unsigned int irq)
|
||||
{
|
||||
}
|
||||
|
||||
static void end_crisv10_irq(unsigned int irq)
|
||||
{
|
||||
}
|
||||
|
||||
static struct hw_interrupt_type crisv10_irq_type = {
|
||||
.typename = "CRISv10",
|
||||
.startup = startup_crisv10_irq,
|
||||
.shutdown = shutdown_crisv10_irq,
|
||||
.enable = enable_crisv10_irq,
|
||||
.disable = disable_crisv10_irq,
|
||||
.ack = ack_crisv10_irq,
|
||||
.end = end_crisv10_irq,
|
||||
.set_affinity = NULL
|
||||
};
|
||||
|
||||
void arch_setup_irq(int irq)
|
||||
{
|
||||
set_int_vector(irq, interrupt[irq]);
|
||||
}
|
||||
|
||||
void arch_free_irq(int irq)
|
||||
{
|
||||
set_int_vector(irq, bad_interrupt[irq]);
|
||||
}
|
||||
|
||||
void weird_irq(void);
|
||||
void system_call(void); /* from entry.S */
|
||||
void do_sigtrap(void); /* from entry.S */
|
||||
void gdb_handle_breakpoint(void); /* from entry.S */
|
||||
|
||||
/* init_IRQ() is called by start_kernel and is responsible for fixing IRQ masks and
|
||||
setting the irq vector table to point to bad_interrupt ptrs.
|
||||
setting the irq vector table.
|
||||
*/
|
||||
|
||||
void __init
|
||||
@ -154,14 +167,15 @@ init_IRQ(void)
|
||||
|
||||
*R_VECT_MASK_CLR = 0xffffffff;
|
||||
|
||||
/* clear the shortcut entry points */
|
||||
|
||||
for(i = 0; i < NR_IRQS; i++)
|
||||
irq_shortcuts[i] = NULL;
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
etrax_irv->v[i] = weird_irq;
|
||||
|
||||
/* Initialize IRQ handler descriptiors. */
|
||||
for(i = 2; i < NR_IRQS; i++) {
|
||||
irq_desc[i].handler = &crisv10_irq_type;
|
||||
set_int_vector(i, interrupt[i]);
|
||||
}
|
||||
|
||||
/* the entries in the break vector contain actual code to be
|
||||
executed by the associated break handler, rather than just a jump
|
||||
address. therefore we need to setup a default breakpoint handler
|
||||
@ -170,10 +184,6 @@ init_IRQ(void)
|
||||
for (i = 0; i < 16; i++)
|
||||
set_break_vector(i, do_sigtrap);
|
||||
|
||||
/* set all etrax irq's to the bad handlers */
|
||||
for (i = 2; i < NR_IRQS; i++)
|
||||
set_int_vector(i, bad_interrupt[i]);
|
||||
|
||||
/* except IRQ 15 which is the multiple-IRQ handler on Etrax100 */
|
||||
|
||||
set_int_vector(15, multiple_interrupt);
|
||||
|
@ -18,6 +18,10 @@
|
||||
*! Jul 21 1999 Bjorn Wesen eLinux port
|
||||
*!
|
||||
*! $Log: kgdb.c,v $
|
||||
*! Revision 1.6 2005/01/14 10:12:17 starvik
|
||||
*! KGDB on separate port.
|
||||
*! Console fixes from 2.4.
|
||||
*!
|
||||
*! Revision 1.5 2004/10/07 13:59:08 starvik
|
||||
*! Corrected call to set_int_vector
|
||||
*!
|
||||
@ -71,7 +75,7 @@
|
||||
*!
|
||||
*!---------------------------------------------------------------------------
|
||||
*!
|
||||
*! $Id: kgdb.c,v 1.5 2004/10/07 13:59:08 starvik Exp $
|
||||
*! $Id: kgdb.c,v 1.6 2005/01/14 10:12:17 starvik Exp $
|
||||
*!
|
||||
*! (C) Copyright 1999, Axis Communications AB, LUND, SWEDEN
|
||||
*!
|
||||
@ -225,6 +229,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/linkage.h>
|
||||
#include <linux/reboot.h>
|
||||
|
||||
#include <asm/setup.h>
|
||||
#include <asm/ptrace.h>
|
||||
@ -1344,12 +1349,11 @@ handle_exception (int sigval)
|
||||
}
|
||||
}
|
||||
|
||||
/* The jump is to the address 0x00000002. Performs a complete re-start
|
||||
from scratch. */
|
||||
/* Performs a complete re-start from scratch. */
|
||||
static void
|
||||
kill_restart ()
|
||||
{
|
||||
__asm__ volatile ("jump 2");
|
||||
machine_restart("");
|
||||
}
|
||||
|
||||
/********************************** Breakpoint *******************************/
|
||||
@ -1506,6 +1510,11 @@ kgdb_handle_serial:
|
||||
bne goback
|
||||
nop
|
||||
|
||||
move.d [reg+0x5E], $r10 ; Get DCCR
|
||||
btstq 8, $r10 ; Test the U-flag.
|
||||
bmi goback
|
||||
nop
|
||||
|
||||
;;
|
||||
;; Handle the communication
|
||||
;;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $Id: process.c,v 1.9 2004/10/19 13:07:37 starvik Exp $
|
||||
/* $Id: process.c,v 1.12 2004/12/27 11:18:32 starvik Exp $
|
||||
*
|
||||
* linux/arch/cris/kernel/process.c
|
||||
*
|
||||
@ -101,6 +101,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
|
||||
regs.r11 = (unsigned long)fn;
|
||||
regs.r12 = (unsigned long)arg;
|
||||
regs.irp = (unsigned long)kernel_thread_helper;
|
||||
regs.dccr = 1 << I_DCCR_BITNR;
|
||||
|
||||
/* Ok, create the new process.. */
|
||||
return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL);
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/user.h>
|
||||
#include <linux/signal.h>
|
||||
#include <linux/security.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/page.h>
|
||||
@ -86,9 +87,13 @@ sys_ptrace(long request, long pid, long addr, long data)
|
||||
ret = -EPERM;
|
||||
|
||||
if (request == PTRACE_TRACEME) {
|
||||
/* are we already being traced? */
|
||||
if (current->ptrace & PT_PTRACED)
|
||||
goto out;
|
||||
|
||||
ret = security_ptrace(current->parent, current);
|
||||
if (ret)
|
||||
goto out;
|
||||
/* set the ptrace bit in the process flags. */
|
||||
current->ptrace |= PT_PTRACED;
|
||||
ret = 0;
|
||||
goto out;
|
||||
@ -207,7 +212,7 @@ sys_ptrace(long request, long pid, long addr, long data)
|
||||
case PTRACE_KILL:
|
||||
ret = 0;
|
||||
|
||||
if (child->state == TASK_ZOMBIE)
|
||||
if (child->exit_state == EXIT_ZOMBIE)
|
||||
break;
|
||||
|
||||
child->exit_code = SIGKILL;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $Id: shadows.c,v 1.1 2001/12/17 13:59:27 bjornw Exp $
|
||||
/* $Id: shadows.c,v 1.2 2004/12/13 12:21:51 starvik Exp $
|
||||
*
|
||||
* Various shadow registers. Defines for these are in include/asm-etrax100/io.h
|
||||
*/
|
||||
@ -6,6 +6,7 @@
|
||||
/* Shadows for internal Etrax-registers */
|
||||
|
||||
unsigned long genconfig_shadow;
|
||||
unsigned long gen_config_ii_shadow;
|
||||
unsigned long port_g_data_shadow;
|
||||
unsigned char port_pa_dir_shadow;
|
||||
unsigned char port_pa_data_shadow;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $Id: traps.c,v 1.2 2003/07/04 08:27:41 starvik Exp $
|
||||
/* $Id: traps.c,v 1.4 2005/04/24 18:47:55 starvik Exp $
|
||||
*
|
||||
* linux/arch/cris/arch-v10/traps.c
|
||||
*
|
||||
@ -16,6 +16,8 @@
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/arch/sv_addr_ag.h>
|
||||
|
||||
extern int raw_printk(const char *fmt, ...);
|
||||
|
||||
void
|
||||
show_registers(struct pt_regs * regs)
|
||||
{
|
||||
@ -26,18 +28,18 @@ show_registers(struct pt_regs * regs)
|
||||
register. */
|
||||
unsigned long usp = rdusp();
|
||||
|
||||
printk("IRP: %08lx SRP: %08lx DCCR: %08lx USP: %08lx MOF: %08lx\n",
|
||||
raw_printk("IRP: %08lx SRP: %08lx DCCR: %08lx USP: %08lx MOF: %08lx\n",
|
||||
regs->irp, regs->srp, regs->dccr, usp, regs->mof );
|
||||
printk(" r0: %08lx r1: %08lx r2: %08lx r3: %08lx\n",
|
||||
raw_printk(" r0: %08lx r1: %08lx r2: %08lx r3: %08lx\n",
|
||||
regs->r0, regs->r1, regs->r2, regs->r3);
|
||||
printk(" r4: %08lx r5: %08lx r6: %08lx r7: %08lx\n",
|
||||
raw_printk(" r4: %08lx r5: %08lx r6: %08lx r7: %08lx\n",
|
||||
regs->r4, regs->r5, regs->r6, regs->r7);
|
||||
printk(" r8: %08lx r9: %08lx r10: %08lx r11: %08lx\n",
|
||||
raw_printk(" r8: %08lx r9: %08lx r10: %08lx r11: %08lx\n",
|
||||
regs->r8, regs->r9, regs->r10, regs->r11);
|
||||
printk("r12: %08lx r13: %08lx oR10: %08lx\n",
|
||||
regs->r12, regs->r13, regs->orig_r10);
|
||||
printk("R_MMU_CAUSE: %08lx\n", (unsigned long)*R_MMU_CAUSE);
|
||||
printk("Process %s (pid: %d, stackpage=%08lx)\n",
|
||||
raw_printk("r12: %08lx r13: %08lx oR10: %08lx sp: %08lx\n",
|
||||
regs->r12, regs->r13, regs->orig_r10, regs);
|
||||
raw_printk("R_MMU_CAUSE: %08lx\n", (unsigned long)*R_MMU_CAUSE);
|
||||
raw_printk("Process %s (pid: %d, stackpage=%08lx)\n",
|
||||
current->comm, current->pid, (unsigned long)current);
|
||||
|
||||
/*
|
||||
@ -53,7 +55,7 @@ show_registers(struct pt_regs * regs)
|
||||
if (usp != 0)
|
||||
show_stack (NULL, NULL);
|
||||
|
||||
printk("\nCode: ");
|
||||
raw_printk("\nCode: ");
|
||||
if(regs->irp < PAGE_OFFSET)
|
||||
goto bad;
|
||||
|
||||
@ -70,16 +72,16 @@ show_registers(struct pt_regs * regs)
|
||||
unsigned char c;
|
||||
if(__get_user(c, &((unsigned char*)regs->irp)[i])) {
|
||||
bad:
|
||||
printk(" Bad IP value.");
|
||||
raw_printk(" Bad IP value.");
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == 0)
|
||||
printk("(%02x) ", c);
|
||||
raw_printk("(%02x) ", c);
|
||||
else
|
||||
printk("%02x ", c);
|
||||
raw_printk("%02x ", c);
|
||||
}
|
||||
printk("\n");
|
||||
raw_printk("\n");
|
||||
}
|
||||
}
|
||||
|
||||
@ -121,7 +123,7 @@ die_if_kernel(const char * str, struct pt_regs * regs, long err)
|
||||
stop_watchdog();
|
||||
#endif
|
||||
|
||||
printk("%s: %04lx\n", str, err & 0xffff);
|
||||
raw_printk("%s: %04lx\n", str, err & 0xffff);
|
||||
|
||||
show_registers(regs);
|
||||
|
||||
@ -130,3 +132,8 @@ die_if_kernel(const char * str, struct pt_regs * regs, long err)
|
||||
#endif
|
||||
do_exit(SIGSEGV);
|
||||
}
|
||||
|
||||
void arch_enable_nmi(void)
|
||||
{
|
||||
asm volatile("setf m");
|
||||
}
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/arch/svinto.h>
|
||||
#include <asm/mmu_context.h>
|
||||
|
||||
/* debug of low-level TLB reload */
|
||||
#undef DEBUG
|
||||
@ -24,8 +25,6 @@
|
||||
#define D(x)
|
||||
#endif
|
||||
|
||||
extern volatile pgd_t *current_pgd;
|
||||
|
||||
extern const struct exception_table_entry
|
||||
*search_exception_tables(unsigned long addr);
|
||||
|
||||
@ -46,7 +45,7 @@ handle_mmu_bus_fault(struct pt_regs *regs)
|
||||
int page_id;
|
||||
int acc, inv;
|
||||
#endif
|
||||
pgd_t* pgd = (pgd_t*)current_pgd;
|
||||
pgd_t* pgd = (pgd_t*)per_cpu(current_pgd, smp_processor_id());
|
||||
pmd_t *pmd;
|
||||
pte_t pte;
|
||||
int miss, we, writeac;
|
||||
@ -94,24 +93,3 @@ handle_mmu_bus_fault(struct pt_regs *regs)
|
||||
*R_TLB_LO = pte_val(pte);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
/* Called from arch/cris/mm/fault.c to find fixup code. */
|
||||
int
|
||||
find_fixup_code(struct pt_regs *regs)
|
||||
{
|
||||
const struct exception_table_entry *fixup;
|
||||
|
||||
if ((fixup = search_exception_tables(regs->irp)) != 0) {
|
||||
/* Adjust the instruction pointer in the stackframe. */
|
||||
regs->irp = fixup->fixup;
|
||||
|
||||
/*
|
||||
* Don't return by restoring the CPU state, so switch
|
||||
* frame-type.
|
||||
*/
|
||||
regs->frametype = CRIS_FRAME_NORMAL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ paging_init(void)
|
||||
* switch_mm)
|
||||
*/
|
||||
|
||||
current_pgd = init_mm.pgd;
|
||||
per_cpu(current_pgd, smp_processor_id()) = init_mm.pgd;
|
||||
|
||||
/* initialise the TLB (tlb.c) */
|
||||
|
||||
|
@ -139,53 +139,6 @@ flush_tlb_page(struct vm_area_struct *vma,
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
/* invalidate a page range */
|
||||
|
||||
void
|
||||
flush_tlb_range(struct vm_area_struct *vma,
|
||||
unsigned long start,
|
||||
unsigned long end)
|
||||
{
|
||||
struct mm_struct *mm = vma->vm_mm;
|
||||
int page_id = mm->context.page_id;
|
||||
int i;
|
||||
unsigned long flags;
|
||||
|
||||
D(printk("tlb: flush range %p<->%p in context %d (%p)\n",
|
||||
start, end, page_id, mm));
|
||||
|
||||
if(page_id == NO_CONTEXT)
|
||||
return;
|
||||
|
||||
start &= PAGE_MASK; /* probably not necessary */
|
||||
end &= PAGE_MASK; /* dito */
|
||||
|
||||
/* invalidate those TLB entries that match both the mm context
|
||||
* and the virtual address range
|
||||
*/
|
||||
|
||||
local_save_flags(flags);
|
||||
local_irq_disable();
|
||||
for(i = 0; i < NUM_TLB_ENTRIES; i++) {
|
||||
unsigned long tlb_hi, vpn;
|
||||
*R_TLB_SELECT = IO_FIELD(R_TLB_SELECT, index, i);
|
||||
tlb_hi = *R_TLB_HI;
|
||||
vpn = tlb_hi & PAGE_MASK;
|
||||
if (IO_EXTRACT(R_TLB_HI, page_id, tlb_hi) == page_id &&
|
||||
vpn >= start && vpn < end) {
|
||||
*R_TLB_HI = ( IO_FIELD(R_TLB_HI, page_id, INVALID_PAGEID ) |
|
||||
IO_FIELD(R_TLB_HI, vpn, i & 0xf ) );
|
||||
|
||||
*R_TLB_LO = ( IO_STATE(R_TLB_LO, global,no ) |
|
||||
IO_STATE(R_TLB_LO, valid, no ) |
|
||||
IO_STATE(R_TLB_LO, kernel,no ) |
|
||||
IO_STATE(R_TLB_LO, we, no ) |
|
||||
IO_FIELD(R_TLB_LO, pfn, 0 ) );
|
||||
}
|
||||
}
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
/* dump the entire TLB for debug purposes */
|
||||
|
||||
#if 0
|
||||
@ -237,7 +190,7 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next,
|
||||
* the pgd.
|
||||
*/
|
||||
|
||||
current_pgd = next->pgd;
|
||||
per_cpu(current_pgd, smp_processor_id()) = next->pgd;
|
||||
|
||||
/* switch context in the MMU */
|
||||
|
||||
|
296
arch/cris/arch-v32/Kconfig
Normal file
296
arch/cris/arch-v32/Kconfig
Normal file
@ -0,0 +1,296 @@
|
||||
config ETRAX_DRAM_VIRTUAL_BASE
|
||||
hex
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "c0000000"
|
||||
|
||||
config ETRAX_LED1G
|
||||
string "First green LED bit"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "PA3"
|
||||
help
|
||||
Bit to use for the first green LED (network LED).
|
||||
Most Axis products use bit A3 here.
|
||||
|
||||
config ETRAX_LED1R
|
||||
string "First red LED bit"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "PA4"
|
||||
help
|
||||
Bit to use for the first red LED (network LED).
|
||||
Most Axis products use bit A4 here.
|
||||
|
||||
config ETRAX_LED2G
|
||||
string "Second green LED bit"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "PA5"
|
||||
help
|
||||
Bit to use for the first green LED (status LED).
|
||||
Most Axis products use bit A5 here.
|
||||
|
||||
config ETRAX_LED2R
|
||||
string "Second red LED bit"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "PA6"
|
||||
help
|
||||
Bit to use for the first red LED (network LED).
|
||||
Most Axis products use bit A6 here.
|
||||
|
||||
config ETRAX_LED3G
|
||||
string "Third green LED bit"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "PA7"
|
||||
help
|
||||
Bit to use for the first green LED (drive/power LED).
|
||||
Most Axis products use bit A7 here.
|
||||
|
||||
config ETRAX_LED3R
|
||||
string "Third red LED bit"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "PA7"
|
||||
help
|
||||
Bit to use for the first red LED (drive/power LED).
|
||||
Most Axis products use bit A7 here.
|
||||
|
||||
choice
|
||||
prompt "Product debug-port"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default ETRAX_DEBUG_PORT0
|
||||
|
||||
config ETRAX_DEBUG_PORT0
|
||||
bool "Serial-0"
|
||||
help
|
||||
Choose a serial port for the ETRAX debug console. Default to
|
||||
port 0.
|
||||
|
||||
config ETRAX_DEBUG_PORT1
|
||||
bool "Serial-1"
|
||||
help
|
||||
Use serial port 1 for the console.
|
||||
|
||||
config ETRAX_DEBUG_PORT2
|
||||
bool "Serial-2"
|
||||
help
|
||||
Use serial port 2 for the console.
|
||||
|
||||
config ETRAX_DEBUG_PORT3
|
||||
bool "Serial-3"
|
||||
help
|
||||
Use serial port 3 for the console.
|
||||
|
||||
config ETRAX_DEBUG_PORT_NULL
|
||||
bool "disabled"
|
||||
help
|
||||
Disable serial-port debugging.
|
||||
|
||||
endchoice
|
||||
|
||||
choice
|
||||
prompt "Kernel GDB port"
|
||||
depends on ETRAX_KGDB
|
||||
default ETRAX_KGDB_PORT0
|
||||
help
|
||||
Choose a serial port for kernel debugging. NOTE: This port should
|
||||
not be enabled under Drivers for built-in interfaces (as it has its
|
||||
own initialization code) and should not be the same as the debug port.
|
||||
|
||||
config ETRAX_KGDB_PORT0
|
||||
bool "Serial-0"
|
||||
help
|
||||
Use serial port 0 for kernel debugging.
|
||||
|
||||
config ETRAX_KGDB_PORT1
|
||||
bool "Serial-1"
|
||||
help
|
||||
Use serial port 1 for kernel debugging.
|
||||
|
||||
config ETRAX_KGDB_PORT2
|
||||
bool "Serial-2"
|
||||
help
|
||||
Use serial port 2 for kernel debugging.
|
||||
|
||||
config ETRAX_KGDB_PORT3
|
||||
bool "Serial-3"
|
||||
help
|
||||
Use serial port 3 for kernel debugging.
|
||||
|
||||
endchoice
|
||||
|
||||
config ETRAX_MEM_GRP1_CONFIG
|
||||
hex "MEM_GRP1_CONFIG"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "4044a"
|
||||
help
|
||||
Waitstates for flash. The default value is suitable for the
|
||||
standard flashes used in axis products (120 ns).
|
||||
|
||||
config ETRAX_MEM_GRP2_CONFIG
|
||||
hex "MEM_GRP2_CONFIG"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "0"
|
||||
help
|
||||
Waitstates for SRAM. 0 is a good choice for most Axis products.
|
||||
|
||||
config ETRAX_MEM_GRP3_CONFIG
|
||||
hex "MEM_GRP3_CONFIG"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "0"
|
||||
help
|
||||
Waitstates for CSP0-3. 0 is a good choice for most Axis products.
|
||||
It may need to be changed if external devices such as extra
|
||||
register-mapped LEDs are used.
|
||||
|
||||
config ETRAX_MEM_GRP4_CONFIG
|
||||
hex "MEM_GRP4_CONFIG"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "0"
|
||||
help
|
||||
Waitstates for CSP4-6. 0 is a good choice for most Axis products.
|
||||
|
||||
config ETRAX_SDRAM_GRP0_CONFIG
|
||||
hex "SDRAM_GRP0_CONFIG"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "336"
|
||||
help
|
||||
SDRAM configuration for group 0. The value depends on the
|
||||
hardware configuration. The default value is suitable
|
||||
for 32 MB organized as two 16 bits chips (e.g. Axis
|
||||
part number 18550) connected as one 32 bit device (i.e. in
|
||||
the same group).
|
||||
|
||||
config ETRAX_SDRAM_GRP1_CONFIG
|
||||
hex "SDRAM_GRP1_CONFIG"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "0"
|
||||
help
|
||||
SDRAM configuration for group 1. The defult value is 0
|
||||
because group 1 is not used in the default configuration,
|
||||
described in the help for SDRAM_GRP0_CONFIG.
|
||||
|
||||
config ETRAX_SDRAM_TIMING
|
||||
hex "SDRAM_TIMING"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "104a"
|
||||
help
|
||||
SDRAM timing parameters. The default value is ok for
|
||||
most hardwares but large SDRAMs may require a faster
|
||||
refresh (a.k.a 8K refresh). The default value implies
|
||||
100MHz clock and SDR mode.
|
||||
|
||||
config ETRAX_SDRAM_COMMAND
|
||||
hex "SDRAM_COMMAND"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "0"
|
||||
help
|
||||
SDRAM command. Should be 0 unless you really know what
|
||||
you are doing (may be != 0 for unusual address line
|
||||
mappings such as in a MCM)..
|
||||
|
||||
config ETRAX_DEF_GIO_PA_OE
|
||||
hex "GIO_PA_OE"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "1c"
|
||||
help
|
||||
Configures the direction of general port A bits. 1 is out, 0 is in.
|
||||
This is often totally different depending on the product used.
|
||||
There are some guidelines though - if you know that only LED's are
|
||||
connected to port PA, then they are usually connected to bits 2-4
|
||||
and you can therefore use 1c. On other boards which don't have the
|
||||
LED's at the general ports, these bits are used for all kinds of
|
||||
stuff. If you don't know what to use, it is always safe to put all
|
||||
as inputs, although floating inputs isn't good.
|
||||
|
||||
config ETRAX_DEF_GIO_PA_OUT
|
||||
hex "GIO_PA_OUT"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "00"
|
||||
help
|
||||
Configures the initial data for the general port A bits. Most
|
||||
products should use 00 here.
|
||||
|
||||
config ETRAX_DEF_GIO_PB_OE
|
||||
hex "GIO_PB_OE"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "00000"
|
||||
help
|
||||
Configures the direction of general port B bits. 1 is out, 0 is in.
|
||||
This is often totally different depending on the product used.
|
||||
There are some guidelines though - if you know that only LED's are
|
||||
connected to port PA, then they are usually connected to bits 2-4
|
||||
and you can therefore use 1c. On other boards which don't have the
|
||||
LED's at the general ports, these bits are used for all kinds of
|
||||
stuff. If you don't know what to use, it is always safe to put all
|
||||
as inputs, although floating inputs isn't good.
|
||||
|
||||
config ETRAX_DEF_GIO_PB_OUT
|
||||
hex "GIO_PB_OUT"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "00000"
|
||||
help
|
||||
Configures the initial data for the general port B bits. Most
|
||||
products should use 00000 here.
|
||||
|
||||
config ETRAX_DEF_GIO_PC_OE
|
||||
hex "GIO_PC_OE"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "00000"
|
||||
help
|
||||
Configures the direction of general port C bits. 1 is out, 0 is in.
|
||||
This is often totally different depending on the product used.
|
||||
There are some guidelines though - if you know that only LED's are
|
||||
connected to port PA, then they are usually connected to bits 2-4
|
||||
and you can therefore use 1c. On other boards which don't have the
|
||||
LED's at the general ports, these bits are used for all kinds of
|
||||
stuff. If you don't know what to use, it is always safe to put all
|
||||
as inputs, although floating inputs isn't good.
|
||||
|
||||
config ETRAX_DEF_GIO_PC_OUT
|
||||
hex "GIO_PC_OUT"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "00000"
|
||||
help
|
||||
Configures the initial data for the general port C bits. Most
|
||||
products should use 00000 here.
|
||||
|
||||
config ETRAX_DEF_GIO_PD_OE
|
||||
hex "GIO_PD_OE"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "00000"
|
||||
help
|
||||
Configures the direction of general port D bits. 1 is out, 0 is in.
|
||||
This is often totally different depending on the product used.
|
||||
There are some guidelines though - if you know that only LED's are
|
||||
connected to port PA, then they are usually connected to bits 2-4
|
||||
and you can therefore use 1c. On other boards which don't have the
|
||||
LED's at the general ports, these bits are used for all kinds of
|
||||
stuff. If you don't know what to use, it is always safe to put all
|
||||
as inputs, although floating inputs isn't good.
|
||||
|
||||
config ETRAX_DEF_GIO_PD_OUT
|
||||
hex "GIO_PD_OUT"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "00000"
|
||||
help
|
||||
Configures the initial data for the general port D bits. Most
|
||||
products should use 00000 here.
|
||||
|
||||
config ETRAX_DEF_GIO_PE_OE
|
||||
hex "GIO_PE_OE"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "00000"
|
||||
help
|
||||
Configures the direction of general port E bits. 1 is out, 0 is in.
|
||||
This is often totally different depending on the product used.
|
||||
There are some guidelines though - if you know that only LED's are
|
||||
connected to port PA, then they are usually connected to bits 2-4
|
||||
and you can therefore use 1c. On other boards which don't have the
|
||||
LED's at the general ports, these bits are used for all kinds of
|
||||
stuff. If you don't know what to use, it is always safe to put all
|
||||
as inputs, although floating inputs isn't good.
|
||||
|
||||
config ETRAX_DEF_GIO_PE_OUT
|
||||
hex "GIO_PE_OUT"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "00000"
|
||||
help
|
||||
Configures the initial data for the general port E bits. Most
|
||||
products should use 00000 here.
|
14
arch/cris/arch-v32/boot/Makefile
Normal file
14
arch/cris/arch-v32/boot/Makefile
Normal file
@ -0,0 +1,14 @@
|
||||
#
|
||||
# arch/cris/arch-v32/boot/Makefile
|
||||
#
|
||||
target = $(target_boot_dir)
|
||||
src = $(src_boot_dir)
|
||||
|
||||
zImage: compressed/vmlinuz
|
||||
|
||||
compressed/vmlinuz: $(objtree)/vmlinux
|
||||
@$(MAKE) -f $(src)/compressed/Makefile $(objtree)/vmlinuz
|
||||
|
||||
clean:
|
||||
rm -f zImage tools/build compressed/vmlinux.out
|
||||
@$(MAKE) -f $(src)/compressed/Makefile clean
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user