dect
/
linux-2.6
Archived
13
0
Fork 0

Merge /spare/repo/linux-2.6/

This commit is contained in:
Jeff Garzik 2005-08-17 00:51:31 -04:00
commit a2e30e529a
1374 changed files with 126285 additions and 44623 deletions

10
CREDITS
View File

@ -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

View File

@ -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
==================

View File

@ -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.

View File

@ -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.

View 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

View File

@ -104,6 +104,7 @@ logo_*.c
logo_*_clut224.c
logo_*_mono.c
lxdialog
mach-types
mach-types.h
make_times_h
map

View File

@ -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

View 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.

View File

@ -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

View File

@ -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
View 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

View File

@ -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)_*()

View File

@ -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

View File

@ -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

View File

@ -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
-----------------

View File

@ -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

View 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.

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 13
EXTRAVERSION =-rc3
EXTRAVERSION =-rc6
NAME=Woozy Numbat
# *DOCUMENTATION*

10
README
View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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. */

View File

@ -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

View File

@ -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
/*

View File

@ -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}

View File

@ -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);

View File

@ -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();

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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

View File

@ -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 */

View File

@ -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 */

View 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);
}
}

View File

@ -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);

View 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);

View 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);

View File

@ -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;

View File

@ -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,

View File

@ -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.

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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

View File

@ -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 );

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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

View File

@ -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 \

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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 */

View File

@ -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++)
{

View File

@ -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

View File

@ -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;
}

View File

@ -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 */
}

View File

@ -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

View File

@ -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);

View 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);

View File

@ -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

View File

@ -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");

View File

@ -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

View 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);

View File

@ -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);

View File

@ -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
;;

View File

@ -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, &regs, 0, NULL, NULL);

View File

@ -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;

View File

@ -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;

View File

@ -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");
}

View File

@ -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;
}

View File

@ -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) */

View File

@ -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
View 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.

View 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