Merge branch 'merge'
This commit is contained in:
Коммит
aa43f77939
2
CREDITS
2
CREDITS
|
@ -2209,7 +2209,7 @@ S: (address available on request)
|
|||
S: USA
|
||||
|
||||
N: Ian McDonald
|
||||
E: iam4@cs.waikato.ac.nz
|
||||
E: ian.mcdonald@jandi.co.nz
|
||||
E: imcdnzl@gmail.com
|
||||
W: http://wand.net.nz/~iam4
|
||||
W: http://imcdnzl.blogspot.com
|
||||
|
|
|
@ -0,0 +1,206 @@
|
|||
/*
|
||||
* ucon.c
|
||||
*
|
||||
* Copyright (c) 2004+ Evgeniy Polyakov <johnpol@2ka.mipt.ru>
|
||||
*
|
||||
*
|
||||
* 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 <asm/types.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/poll.h>
|
||||
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <linux/connector.h>
|
||||
|
||||
#define DEBUG
|
||||
#define NETLINK_CONNECTOR 11
|
||||
|
||||
#ifdef DEBUG
|
||||
#define ulog(f, a...) fprintf(stdout, f, ##a)
|
||||
#else
|
||||
#define ulog(f, a...) do {} while (0)
|
||||
#endif
|
||||
|
||||
static int need_exit;
|
||||
static __u32 seq;
|
||||
|
||||
static int netlink_send(int s, struct cn_msg *msg)
|
||||
{
|
||||
struct nlmsghdr *nlh;
|
||||
unsigned int size;
|
||||
int err;
|
||||
char buf[128];
|
||||
struct cn_msg *m;
|
||||
|
||||
size = NLMSG_SPACE(sizeof(struct cn_msg) + msg->len);
|
||||
|
||||
nlh = (struct nlmsghdr *)buf;
|
||||
nlh->nlmsg_seq = seq++;
|
||||
nlh->nlmsg_pid = getpid();
|
||||
nlh->nlmsg_type = NLMSG_DONE;
|
||||
nlh->nlmsg_len = NLMSG_LENGTH(size - sizeof(*nlh));
|
||||
nlh->nlmsg_flags = 0;
|
||||
|
||||
m = NLMSG_DATA(nlh);
|
||||
#if 0
|
||||
ulog("%s: [%08x.%08x] len=%u, seq=%u, ack=%u.\n",
|
||||
__func__, msg->id.idx, msg->id.val, msg->len, msg->seq, msg->ack);
|
||||
#endif
|
||||
memcpy(m, msg, sizeof(*m) + msg->len);
|
||||
|
||||
err = send(s, nlh, size, 0);
|
||||
if (err == -1)
|
||||
ulog("Failed to send: %s [%d].\n",
|
||||
strerror(errno), errno);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int s;
|
||||
char buf[1024];
|
||||
int len;
|
||||
struct nlmsghdr *reply;
|
||||
struct sockaddr_nl l_local;
|
||||
struct cn_msg *data;
|
||||
FILE *out;
|
||||
time_t tm;
|
||||
struct pollfd pfd;
|
||||
|
||||
if (argc < 2)
|
||||
out = stdout;
|
||||
else {
|
||||
out = fopen(argv[1], "a+");
|
||||
if (!out) {
|
||||
ulog("Unable to open %s for writing: %s\n",
|
||||
argv[1], strerror(errno));
|
||||
out = stdout;
|
||||
}
|
||||
}
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
|
||||
if (s == -1) {
|
||||
perror("socket");
|
||||
return -1;
|
||||
}
|
||||
|
||||
l_local.nl_family = AF_NETLINK;
|
||||
l_local.nl_groups = 0x123; /* bitmask of requested groups */
|
||||
l_local.nl_pid = 0;
|
||||
|
||||
if (bind(s, (struct sockaddr *)&l_local, sizeof(struct sockaddr_nl)) == -1) {
|
||||
perror("bind");
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if 0
|
||||
{
|
||||
int on = 0x57; /* Additional group number */
|
||||
setsockopt(s, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &on, sizeof(on));
|
||||
}
|
||||
#endif
|
||||
if (0) {
|
||||
int i, j;
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
data = (struct cn_msg *)buf;
|
||||
|
||||
data->id.idx = 0x123;
|
||||
data->id.val = 0x456;
|
||||
data->seq = seq++;
|
||||
data->ack = 0;
|
||||
data->len = 0;
|
||||
|
||||
for (j=0; j<10; ++j) {
|
||||
for (i=0; i<1000; ++i) {
|
||||
len = netlink_send(s, data);
|
||||
}
|
||||
|
||||
ulog("%d messages have been sent to %08x.%08x.\n", i, data->id.idx, data->id.val);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
pfd.fd = s;
|
||||
|
||||
while (!need_exit) {
|
||||
pfd.events = POLLIN;
|
||||
pfd.revents = 0;
|
||||
switch (poll(&pfd, 1, -1)) {
|
||||
case 0:
|
||||
need_exit = 1;
|
||||
break;
|
||||
case -1:
|
||||
if (errno != EINTR) {
|
||||
need_exit = 1;
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (need_exit)
|
||||
break;
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
len = recv(s, buf, sizeof(buf), 0);
|
||||
if (len == -1) {
|
||||
perror("recv buf");
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
reply = (struct nlmsghdr *)buf;
|
||||
|
||||
switch (reply->nlmsg_type) {
|
||||
case NLMSG_ERROR:
|
||||
fprintf(out, "Error message received.\n");
|
||||
fflush(out);
|
||||
break;
|
||||
case NLMSG_DONE:
|
||||
data = (struct cn_msg *)NLMSG_DATA(reply);
|
||||
|
||||
time(&tm);
|
||||
fprintf(out, "%.24s : [%x.%x] [%08u.%08u].\n",
|
||||
ctime(&tm), data->id.idx, data->id.val, data->seq, data->ack);
|
||||
fflush(out);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
close(s);
|
||||
return 0;
|
||||
}
|
|
@ -217,6 +217,12 @@ exclusive cpuset. Also, the use of a Linux virtual file system (vfs)
|
|||
to represent the cpuset hierarchy provides for a familiar permission
|
||||
and name space for cpusets, with a minimum of additional kernel code.
|
||||
|
||||
The cpus file in the root (top_cpuset) cpuset is read-only.
|
||||
It automatically tracks the value of cpu_online_map, using a CPU
|
||||
hotplug notifier. If and when memory nodes can be hotplugged,
|
||||
we expect to make the mems file in the root cpuset read-only
|
||||
as well, and have it track the value of node_online_map.
|
||||
|
||||
|
||||
1.4 What are exclusive cpusets ?
|
||||
--------------------------------
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
|
||||
What is imacfb?
|
||||
===============
|
||||
|
||||
This is a generic EFI platform driver for Intel based Apple computers.
|
||||
Imacfb is only for EFI booted Intel Macs.
|
||||
|
||||
Supported Hardware
|
||||
==================
|
||||
|
||||
iMac 17"/20"
|
||||
Macbook
|
||||
Macbook Pro 15"/17"
|
||||
MacMini
|
||||
|
||||
How to use it?
|
||||
==============
|
||||
|
||||
Imacfb does not have any kind of autodetection of your machine.
|
||||
You have to add the fillowing kernel parameters in your elilo.conf:
|
||||
Macbook :
|
||||
video=imacfb:macbook
|
||||
MacMini :
|
||||
video=imacfb:mini
|
||||
Macbook Pro 15", iMac 17" :
|
||||
video=imacfb:i17
|
||||
Macbook Pro 17", iMac 20" :
|
||||
video=imacfb:i20
|
||||
|
||||
--
|
||||
Edgar Hucek <gimli@dark-green.com>
|
|
@ -62,8 +62,8 @@ ramfs-rootfs-initramfs.txt
|
|||
- info on the 'in memory' filesystems ramfs, rootfs and initramfs.
|
||||
reiser4.txt
|
||||
- info on the Reiser4 filesystem based on dancing tree algorithms.
|
||||
relayfs.txt
|
||||
- info on relayfs, for efficient streaming from kernel to user space.
|
||||
relay.txt
|
||||
- info on relay, for efficient streaming from kernel to user space.
|
||||
romfs.txt
|
||||
- description of the ROMFS filesystem.
|
||||
smbfs.txt
|
||||
|
|
|
@ -0,0 +1,479 @@
|
|||
relay interface (formerly relayfs)
|
||||
==================================
|
||||
|
||||
The relay interface provides a means for kernel applications to
|
||||
efficiently log and transfer large quantities of data from the kernel
|
||||
to userspace via user-defined 'relay channels'.
|
||||
|
||||
A 'relay channel' is a kernel->user data relay mechanism implemented
|
||||
as a set of per-cpu kernel buffers ('channel buffers'), each
|
||||
represented as a regular file ('relay file') in user space. Kernel
|
||||
clients write into the channel buffers using efficient write
|
||||
functions; these automatically log into the current cpu's channel
|
||||
buffer. User space applications mmap() or read() from the relay files
|
||||
and retrieve the data as it becomes available. The relay files
|
||||
themselves are files created in a host filesystem, e.g. debugfs, and
|
||||
are associated with the channel buffers using the API described below.
|
||||
|
||||
The format of the data logged into the channel buffers is completely
|
||||
up to the kernel client; the relay interface does however provide
|
||||
hooks which allow kernel clients to impose some structure on the
|
||||
buffer data. The relay interface doesn't implement any form of data
|
||||
filtering - this also is left to the kernel client. The purpose is to
|
||||
keep things as simple as possible.
|
||||
|
||||
This document provides an overview of the relay interface API. The
|
||||
details of the function parameters are documented along with the
|
||||
functions in the relay interface code - please see that for details.
|
||||
|
||||
Semantics
|
||||
=========
|
||||
|
||||
Each relay channel has one buffer per CPU, each buffer has one or more
|
||||
sub-buffers. Messages are written to the first sub-buffer until it is
|
||||
too full to contain a new message, in which case it it is written to
|
||||
the next (if available). Messages are never split across sub-buffers.
|
||||
At this point, userspace can be notified so it empties the first
|
||||
sub-buffer, while the kernel continues writing to the next.
|
||||
|
||||
When notified that a sub-buffer is full, the kernel knows how many
|
||||
bytes of it are padding i.e. unused space occurring because a complete
|
||||
message couldn't fit into a sub-buffer. Userspace can use this
|
||||
knowledge to copy only valid data.
|
||||
|
||||
After copying it, userspace can notify the kernel that a sub-buffer
|
||||
has been consumed.
|
||||
|
||||
A relay channel can operate in a mode where it will overwrite data not
|
||||
yet collected by userspace, and not wait for it to be consumed.
|
||||
|
||||
The relay channel itself does not provide for communication of such
|
||||
data between userspace and kernel, allowing the kernel side to remain
|
||||
simple and not impose a single interface on userspace. It does
|
||||
provide a set of examples and a separate helper though, described
|
||||
below.
|
||||
|
||||
The read() interface both removes padding and internally consumes the
|
||||
read sub-buffers; thus in cases where read(2) is being used to drain
|
||||
the channel buffers, special-purpose communication between kernel and
|
||||
user isn't necessary for basic operation.
|
||||
|
||||
One of the major goals of the relay interface is to provide a low
|
||||
overhead mechanism for conveying kernel data to userspace. While the
|
||||
read() interface is easy to use, it's not as efficient as the mmap()
|
||||
approach; the example code attempts to make the tradeoff between the
|
||||
two approaches as small as possible.
|
||||
|
||||
klog and relay-apps example code
|
||||
================================
|
||||
|
||||
The relay interface itself is ready to use, but to make things easier,
|
||||
a couple simple utility functions and a set of examples are provided.
|
||||
|
||||
The relay-apps example tarball, available on the relay sourceforge
|
||||
site, contains a set of self-contained examples, each consisting of a
|
||||
pair of .c files containing boilerplate code for each of the user and
|
||||
kernel sides of a relay application. When combined these two sets of
|
||||
boilerplate code provide glue to easily stream data to disk, without
|
||||
having to bother with mundane housekeeping chores.
|
||||
|
||||
The 'klog debugging functions' patch (klog.patch in the relay-apps
|
||||
tarball) provides a couple of high-level logging functions to the
|
||||
kernel which allow writing formatted text or raw data to a channel,
|
||||
regardless of whether a channel to write into exists or not, or even
|
||||
whether the relay interface is compiled into the kernel or not. These
|
||||
functions allow you to put unconditional 'trace' statements anywhere
|
||||
in the kernel or kernel modules; only when there is a 'klog handler'
|
||||
registered will data actually be logged (see the klog and kleak
|
||||
examples for details).
|
||||
|
||||
It is of course possible to use the relay interface from scratch,
|
||||
i.e. without using any of the relay-apps example code or klog, but
|
||||
you'll have to implement communication between userspace and kernel,
|
||||
allowing both to convey the state of buffers (full, empty, amount of
|
||||
padding). The read() interface both removes padding and internally
|
||||
consumes the read sub-buffers; thus in cases where read(2) is being
|
||||
used to drain the channel buffers, special-purpose communication
|
||||
between kernel and user isn't necessary for basic operation. Things
|
||||
such as buffer-full conditions would still need to be communicated via
|
||||
some channel though.
|
||||
|
||||
klog and the relay-apps examples can be found in the relay-apps
|
||||
tarball on http://relayfs.sourceforge.net
|
||||
|
||||
The relay interface user space API
|
||||
==================================
|
||||
|
||||
The relay interface implements basic file operations for user space
|
||||
access to relay channel buffer data. Here are the file operations
|
||||
that are available and some comments regarding their behavior:
|
||||
|
||||
open() enables user to open an _existing_ channel buffer.
|
||||
|
||||
mmap() results in channel buffer being mapped into the caller's
|
||||
memory space. Note that you can't do a partial mmap - you
|
||||
must map the entire file, which is NRBUF * SUBBUFSIZE.
|
||||
|
||||
read() read the contents of a channel buffer. The bytes read are
|
||||
'consumed' by the reader, i.e. they won't be available
|
||||
again to subsequent reads. If the channel is being used
|
||||
in no-overwrite mode (the default), it can be read at any
|
||||
time even if there's an active kernel writer. If the
|
||||
channel is being used in overwrite mode and there are
|
||||
active channel writers, results may be unpredictable -
|
||||
users should make sure that all logging to the channel has
|
||||
ended before using read() with overwrite mode. Sub-buffer
|
||||
padding is automatically removed and will not be seen by
|
||||
the reader.
|
||||
|
||||
sendfile() transfer data from a channel buffer to an output file
|
||||
descriptor. Sub-buffer padding is automatically removed
|
||||
and will not be seen by the reader.
|
||||
|
||||
poll() POLLIN/POLLRDNORM/POLLERR supported. User applications are
|
||||
notified when sub-buffer boundaries are crossed.
|
||||
|
||||
close() decrements the channel buffer's refcount. When the refcount
|
||||
reaches 0, i.e. when no process or kernel client has the
|
||||
buffer open, the channel buffer is freed.
|
||||
|
||||
In order for a user application to make use of relay files, the
|
||||
host filesystem must be mounted. For example,
|
||||
|
||||
mount -t debugfs debugfs /debug
|
||||
|
||||
NOTE: the host filesystem doesn't need to be mounted for kernel
|
||||
clients to create or use channels - it only needs to be
|
||||
mounted when user space applications need access to the buffer
|
||||
data.
|
||||
|
||||
|
||||
The relay interface kernel API
|
||||
==============================
|
||||
|
||||
Here's a summary of the API the relay interface provides to in-kernel clients:
|
||||
|
||||
TBD(curr. line MT:/API/)
|
||||
channel management functions:
|
||||
|
||||
relay_open(base_filename, parent, subbuf_size, n_subbufs,
|
||||
callbacks)
|
||||
relay_close(chan)
|
||||
relay_flush(chan)
|
||||
relay_reset(chan)
|
||||
|
||||
channel management typically called on instigation of userspace:
|
||||
|
||||
relay_subbufs_consumed(chan, cpu, subbufs_consumed)
|
||||
|
||||
write functions:
|
||||
|
||||
relay_write(chan, data, length)
|
||||
__relay_write(chan, data, length)
|
||||
relay_reserve(chan, length)
|
||||
|
||||
callbacks:
|
||||
|
||||
subbuf_start(buf, subbuf, prev_subbuf, prev_padding)
|
||||
buf_mapped(buf, filp)
|
||||
buf_unmapped(buf, filp)
|
||||
create_buf_file(filename, parent, mode, buf, is_global)
|
||||
remove_buf_file(dentry)
|
||||
|
||||
helper functions:
|
||||
|
||||
relay_buf_full(buf)
|
||||
subbuf_start_reserve(buf, length)
|
||||
|
||||
|
||||
Creating a channel
|
||||
------------------
|
||||
|
||||
relay_open() is used to create a channel, along with its per-cpu
|
||||
channel buffers. Each channel buffer will have an associated file
|
||||
created for it in the host filesystem, which can be and mmapped or
|
||||
read from in user space. The files are named basename0...basenameN-1
|
||||
where N is the number of online cpus, and by default will be created
|
||||
in the root of the filesystem (if the parent param is NULL). If you
|
||||
want a directory structure to contain your relay files, you should
|
||||
create it using the host filesystem's directory creation function,
|
||||
e.g. debugfs_create_dir(), and pass the parent directory to
|
||||
relay_open(). Users are responsible for cleaning up any directory
|
||||
structure they create, when the channel is closed - again the host
|
||||
filesystem's directory removal functions should be used for that,
|
||||
e.g. debugfs_remove().
|
||||
|
||||
In order for a channel to be created and the host filesystem's files
|
||||
associated with its channel buffers, the user must provide definitions
|
||||
for two callback functions, create_buf_file() and remove_buf_file().
|
||||
create_buf_file() is called once for each per-cpu buffer from
|
||||
relay_open() and allows the user to create the file which will be used
|
||||
to represent the corresponding channel buffer. The callback should
|
||||
return the dentry of the file created to represent the channel buffer.
|
||||
remove_buf_file() must also be defined; it's responsible for deleting
|
||||
the file(s) created in create_buf_file() and is called during
|
||||
relay_close().
|
||||
|
||||
Here are some typical definitions for these callbacks, in this case
|
||||
using debugfs:
|
||||
|
||||
/*
|
||||
* create_buf_file() callback. Creates relay file in debugfs.
|
||||
*/
|
||||
static struct dentry *create_buf_file_handler(const char *filename,
|
||||
struct dentry *parent,
|
||||
int mode,
|
||||
struct rchan_buf *buf,
|
||||
int *is_global)
|
||||
{
|
||||
return debugfs_create_file(filename, mode, parent, buf,
|
||||
&relay_file_operations);
|
||||
}
|
||||
|
||||
/*
|
||||
* remove_buf_file() callback. Removes relay file from debugfs.
|
||||
*/
|
||||
static int remove_buf_file_handler(struct dentry *dentry)
|
||||
{
|
||||
debugfs_remove(dentry);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* relay interface callbacks
|
||||
*/
|
||||
static struct rchan_callbacks relay_callbacks =
|
||||
{
|
||||
.create_buf_file = create_buf_file_handler,
|
||||
.remove_buf_file = remove_buf_file_handler,
|
||||
};
|
||||
|
||||
And an example relay_open() invocation using them:
|
||||
|
||||
chan = relay_open("cpu", NULL, SUBBUF_SIZE, N_SUBBUFS, &relay_callbacks);
|
||||
|
||||
If the create_buf_file() callback fails, or isn't defined, channel
|
||||
creation and thus relay_open() will fail.
|
||||
|
||||
The total size of each per-cpu buffer is calculated by multiplying the
|
||||
number of sub-buffers by the sub-buffer size passed into relay_open().
|
||||
The idea behind sub-buffers is that they're basically an extension of
|
||||
double-buffering to N buffers, and they also allow applications to
|
||||
easily implement random-access-on-buffer-boundary schemes, which can
|
||||
be important for some high-volume applications. The number and size
|
||||
of sub-buffers is completely dependent on the application and even for
|
||||
the same application, different conditions will warrant different
|
||||
values for these parameters at different times. Typically, the right
|
||||
values to use are best decided after some experimentation; in general,
|
||||
though, it's safe to assume that having only 1 sub-buffer is a bad
|
||||
idea - you're guaranteed to either overwrite data or lose events
|
||||
depending on the channel mode being used.
|
||||
|
||||
The create_buf_file() implementation can also be defined in such a way
|
||||
as to allow the creation of a single 'global' buffer instead of the
|
||||
default per-cpu set. This can be useful for applications interested
|
||||
mainly in seeing the relative ordering of system-wide events without
|
||||
the need to bother with saving explicit timestamps for the purpose of
|
||||
merging/sorting per-cpu files in a postprocessing step.
|
||||
|
||||
To have relay_open() create a global buffer, the create_buf_file()
|
||||
implementation should set the value of the is_global outparam to a
|
||||
non-zero value in addition to creating the file that will be used to
|
||||
represent the single buffer. In the case of a global buffer,
|
||||
create_buf_file() and remove_buf_file() will be called only once. The
|
||||
normal channel-writing functions, e.g. relay_write(), can still be
|
||||
used - writes from any cpu will transparently end up in the global
|
||||
buffer - but since it is a global buffer, callers should make sure
|
||||
they use the proper locking for such a buffer, either by wrapping
|
||||
writes in a spinlock, or by copying a write function from relay.h and
|
||||
creating a local version that internally does the proper locking.
|
||||
|
||||
Channel 'modes'
|
||||
---------------
|
||||
|
||||
relay channels can be used in either of two modes - 'overwrite' or
|
||||
'no-overwrite'. The mode is entirely determined by the implementation
|
||||
of the subbuf_start() callback, as described below. The default if no
|
||||
subbuf_start() callback is defined is 'no-overwrite' mode. If the
|
||||
default mode suits your needs, and you plan to use the read()
|
||||
interface to retrieve channel data, you can ignore the details of this
|
||||
section, as it pertains mainly to mmap() implementations.
|
||||
|
||||
In 'overwrite' mode, also known as 'flight recorder' mode, writes
|
||||
continuously cycle around the buffer and will never fail, but will
|
||||
unconditionally overwrite old data regardless of whether it's actually
|
||||
been consumed. In no-overwrite mode, writes will fail, i.e. data will
|
||||
be lost, if the number of unconsumed sub-buffers equals the total
|
||||
number of sub-buffers in the channel. It should be clear that if
|
||||
there is no consumer or if the consumer can't consume sub-buffers fast
|
||||
enough, data will be lost in either case; the only difference is
|
||||
whether data is lost from the beginning or the end of a buffer.
|
||||
|
||||
As explained above, a relay channel is made of up one or more
|
||||
per-cpu channel buffers, each implemented as a circular buffer
|
||||
subdivided into one or more sub-buffers. Messages are written into
|
||||
the current sub-buffer of the channel's current per-cpu buffer via the
|
||||
write functions described below. Whenever a message can't fit into
|
||||
the current sub-buffer, because there's no room left for it, the
|
||||
client is notified via the subbuf_start() callback that a switch to a
|
||||
new sub-buffer is about to occur. The client uses this callback to 1)
|
||||
initialize the next sub-buffer if appropriate 2) finalize the previous
|
||||
sub-buffer if appropriate and 3) return a boolean value indicating
|
||||
whether or not to actually move on to the next sub-buffer.
|
||||
|
||||
To implement 'no-overwrite' mode, the userspace client would provide
|
||||
an implementation of the subbuf_start() callback something like the
|
||||
following:
|
||||
|
||||
static int subbuf_start(struct rchan_buf *buf,
|
||||
void *subbuf,
|
||||
void *prev_subbuf,
|
||||
unsigned int prev_padding)
|
||||
{
|
||||
if (prev_subbuf)
|
||||
*((unsigned *)prev_subbuf) = prev_padding;
|
||||
|
||||
if (relay_buf_full(buf))
|
||||
return 0;
|
||||
|
||||
subbuf_start_reserve(buf, sizeof(unsigned int));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
If the current buffer is full, i.e. all sub-buffers remain unconsumed,
|
||||
the callback returns 0 to indicate that the buffer switch should not
|
||||
occur yet, i.e. until the consumer has had a chance to read the
|
||||
current set of ready sub-buffers. For the relay_buf_full() function
|
||||
to make sense, the consumer is reponsible for notifying the relay
|
||||
interface when sub-buffers have been consumed via
|
||||
relay_subbufs_consumed(). Any subsequent attempts to write into the
|
||||
buffer will again invoke the subbuf_start() callback with the same
|
||||
parameters; only when the consumer has consumed one or more of the
|
||||
ready sub-buffers will relay_buf_full() return 0, in which case the
|
||||
buffer switch can continue.
|
||||
|
||||
The implementation of the subbuf_start() callback for 'overwrite' mode
|
||||
would be very similar:
|
||||
|
||||
static int subbuf_start(struct rchan_buf *buf,
|
||||
void *subbuf,
|
||||
void *prev_subbuf,
|
||||
unsigned int prev_padding)
|
||||
{
|
||||
if (prev_subbuf)
|
||||
*((unsigned *)prev_subbuf) = prev_padding;
|
||||
|
||||
subbuf_start_reserve(buf, sizeof(unsigned int));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
In this case, the relay_buf_full() check is meaningless and the
|
||||
callback always returns 1, causing the buffer switch to occur
|
||||
unconditionally. It's also meaningless for the client to use the
|
||||
relay_subbufs_consumed() function in this mode, as it's never
|
||||
consulted.
|
||||
|
||||
The default subbuf_start() implementation, used if the client doesn't
|
||||
define any callbacks, or doesn't define the subbuf_start() callback,
|
||||
implements the simplest possible 'no-overwrite' mode, i.e. it does
|
||||
nothing but return 0.
|
||||
|
||||
Header information can be reserved at the beginning of each sub-buffer
|
||||
by calling the subbuf_start_reserve() helper function from within the
|
||||
subbuf_start() callback. This reserved area can be used to store
|
||||
whatever information the client wants. In the example above, room is
|
||||
reserved in each sub-buffer to store the padding count for that
|
||||
sub-buffer. This is filled in for the previous sub-buffer in the
|
||||
subbuf_start() implementation; the padding value for the previous
|
||||
sub-buffer is passed into the subbuf_start() callback along with a
|
||||
pointer to the previous sub-buffer, since the padding value isn't
|
||||
known until a sub-buffer is filled. The subbuf_start() callback is
|
||||
also called for the first sub-buffer when the channel is opened, to
|
||||
give the client a chance to reserve space in it. In this case the
|
||||
previous sub-buffer pointer passed into the callback will be NULL, so
|
||||
the client should check the value of the prev_subbuf pointer before
|
||||
writing into the previous sub-buffer.
|
||||
|
||||
Writing to a channel
|
||||
--------------------
|
||||
|
||||
Kernel clients write data into the current cpu's channel buffer using
|
||||
relay_write() or __relay_write(). relay_write() is the main logging
|
||||
function - it uses local_irqsave() to protect the buffer and should be
|
||||
used if you might be logging from interrupt context. If you know
|
||||
you'll never be logging from interrupt context, you can use
|
||||
__relay_write(), which only disables preemption. These functions
|
||||
don't return a value, so you can't determine whether or not they
|
||||
failed - the assumption is that you wouldn't want to check a return
|
||||
value in the fast logging path anyway, and that they'll always succeed
|
||||
unless the buffer is full and no-overwrite mode is being used, in
|
||||
which case you can detect a failed write in the subbuf_start()
|
||||
callback by calling the relay_buf_full() helper function.
|
||||
|
||||
relay_reserve() is used to reserve a slot in a channel buffer which
|
||||
can be written to later. This would typically be used in applications
|
||||
that need to write directly into a channel buffer without having to
|
||||
stage data in a temporary buffer beforehand. Because the actual write
|
||||
may not happen immediately after the slot is reserved, applications
|
||||
using relay_reserve() can keep a count of the number of bytes actually
|
||||
written, either in space reserved in the sub-buffers themselves or as
|
||||
a separate array. See the 'reserve' example in the relay-apps tarball
|
||||
at http://relayfs.sourceforge.net for an example of how this can be
|
||||
done. Because the write is under control of the client and is
|
||||
separated from the reserve, relay_reserve() doesn't protect the buffer
|
||||
at all - it's up to the client to provide the appropriate
|
||||
synchronization when using relay_reserve().
|
||||
|
||||
Closing a channel
|
||||
-----------------
|
||||
|
||||
The client calls relay_close() when it's finished using the channel.
|
||||
The channel and its associated buffers are destroyed when there are no
|
||||
longer any references to any of the channel buffers. relay_flush()
|
||||
forces a sub-buffer switch on all the channel buffers, and can be used
|
||||
to finalize and process the last sub-buffers before the channel is
|
||||
closed.
|
||||
|
||||
Misc
|
||||
----
|
||||
|
||||
Some applications may want to keep a channel around and re-use it
|
||||
rather than open and close a new channel for each use. relay_reset()
|
||||
can be used for this purpose - it resets a channel to its initial
|
||||
state without reallocating channel buffer memory or destroying
|
||||
existing mappings. It should however only be called when it's safe to
|
||||
do so, i.e. when the channel isn't currently being written to.
|
||||
|
||||
Finally, there are a couple of utility callbacks that can be used for
|
||||
different purposes. buf_mapped() is called whenever a channel buffer
|
||||
is mmapped from user space and buf_unmapped() is called when it's
|
||||
unmapped. The client can use this notification to trigger actions
|
||||
within the kernel application, such as enabling/disabling logging to
|
||||
the channel.
|
||||
|
||||
|
||||
Resources
|
||||
=========
|
||||
|
||||
For news, example code, mailing list, etc. see the relay interface homepage:
|
||||
|
||||
http://relayfs.sourceforge.net
|
||||
|
||||
|
||||
Credits
|
||||
=======
|
||||
|
||||
The ideas and specs for the relay interface came about as a result of
|
||||
discussions on tracing involving the following:
|
||||
|
||||
Michel Dagenais <michel.dagenais@polymtl.ca>
|
||||
Richard Moore <richardj_moore@uk.ibm.com>
|
||||
Bob Wisniewski <bob@watson.ibm.com>
|
||||
Karim Yaghmour <karim@opersys.com>
|
||||
Tom Zanussi <zanussi@us.ibm.com>
|
||||
|
||||
Also thanks to Hubertus Franke for a lot of useful suggestions and bug
|
||||
reports.
|
|
@ -1,442 +0,0 @@
|
|||
|
||||
relayfs - a high-speed data relay filesystem
|
||||
============================================
|
||||
|
||||
relayfs is a filesystem designed to provide an efficient mechanism for
|
||||
tools and facilities to relay large and potentially sustained streams
|
||||
of data from kernel space to user space.
|
||||
|
||||
The main abstraction of relayfs is the 'channel'. A channel consists
|
||||
of a set of per-cpu kernel buffers each represented by a file in the
|
||||
relayfs filesystem. Kernel clients write into a channel using
|
||||
efficient write functions which automatically log to the current cpu's
|
||||
channel buffer. User space applications mmap() the per-cpu files and
|
||||
retrieve the data as it becomes available.
|
||||
|
||||
The format of the data logged into the channel buffers is completely
|
||||
up to the relayfs client; relayfs does however provide hooks which
|
||||
allow clients to impose some structure on the buffer data. Nor does
|
||||
relayfs implement any form of data filtering - this also is left to
|
||||
the client. The purpose is to keep relayfs as simple as possible.
|
||||
|
||||
This document provides an overview of the relayfs API. The details of
|
||||
the function parameters are documented along with the functions in the
|
||||
filesystem code - please see that for details.
|
||||
|
||||
Semantics
|
||||
=========
|
||||
|
||||
Each relayfs channel has one buffer per CPU, each buffer has one or
|
||||
more sub-buffers. Messages are written to the first sub-buffer until
|
||||
it is too full to contain a new message, in which case it it is
|
||||
written to the next (if available). Messages are never split across
|
||||
sub-buffers. At this point, userspace can be notified so it empties
|
||||
the first sub-buffer, while the kernel continues writing to the next.
|
||||
|
||||
When notified that a sub-buffer is full, the kernel knows how many
|
||||
bytes of it are padding i.e. unused. Userspace can use this knowledge
|
||||
to copy only valid data.
|
||||
|
||||
After copying it, userspace can notify the kernel that a sub-buffer
|
||||
has been consumed.
|
||||
|
||||
relayfs can operate in a mode where it will overwrite data not yet
|
||||
collected by userspace, and not wait for it to consume it.
|
||||
|
||||
relayfs itself does not provide for communication of such data between
|
||||
userspace and kernel, allowing the kernel side to remain simple and
|
||||
not impose a single interface on userspace. It does provide a set of
|
||||
examples and a separate helper though, described below.
|
||||
|
||||
klog and relay-apps example code
|
||||
================================
|
||||
|
||||
relayfs itself is ready to use, but to make things easier, a couple
|
||||
simple utility functions and a set of examples are provided.
|
||||
|
||||
The relay-apps example tarball, available on the relayfs sourceforge
|
||||
site, contains a set of self-contained examples, each consisting of a
|
||||
pair of .c files containing boilerplate code for each of the user and
|
||||
kernel sides of a relayfs application; combined these two sets of
|
||||
boilerplate code provide glue to easily stream data to disk, without
|
||||
having to bother with mundane housekeeping chores.
|
||||
|
||||
The 'klog debugging functions' patch (klog.patch in the relay-apps
|
||||
tarball) provides a couple of high-level logging functions to the
|
||||
kernel which allow writing formatted text or raw data to a channel,
|
||||
regardless of whether a channel to write into exists or not, or
|
||||
whether relayfs is compiled into the kernel or is configured as a
|
||||
module. These functions allow you to put unconditional 'trace'
|
||||
statements anywhere in the kernel or kernel modules; only when there
|
||||
is a 'klog handler' registered will data actually be logged (see the
|
||||
klog and kleak examples for details).
|
||||
|
||||
It is of course possible to use relayfs from scratch i.e. without
|
||||
using any of the relay-apps example code or klog, but you'll have to
|
||||
implement communication between userspace and kernel, allowing both to
|
||||
convey the state of buffers (full, empty, amount of padding).
|
||||
|
||||
klog and the relay-apps examples can be found in the relay-apps
|
||||
tarball on http://relayfs.sourceforge.net
|
||||
|
||||
|
||||
The relayfs user space API
|
||||
==========================
|
||||
|
||||
relayfs implements basic file operations for user space access to
|
||||
relayfs channel buffer data. Here are the file operations that are
|
||||
available and some comments regarding their behavior:
|
||||
|
||||
open() enables user to open an _existing_ buffer.
|
||||
|
||||
mmap() results in channel buffer being mapped into the caller's
|
||||
memory space. Note that you can't do a partial mmap - you must
|
||||
map the entire file, which is NRBUF * SUBBUFSIZE.
|
||||
|
||||
read() read the contents of a channel buffer. The bytes read are
|
||||
'consumed' by the reader i.e. they won't be available again
|
||||
to subsequent reads. If the channel is being used in
|
||||
no-overwrite mode (the default), it can be read at any time
|
||||
even if there's an active kernel writer. If the channel is
|
||||
being used in overwrite mode and there are active channel
|
||||
writers, results may be unpredictable - users should make
|
||||
sure that all logging to the channel has ended before using
|
||||
read() with overwrite mode.
|
||||
|
||||
poll() POLLIN/POLLRDNORM/POLLERR supported. User applications are
|
||||
notified when sub-buffer boundaries are crossed.
|
||||
|
||||
close() decrements the channel buffer's refcount. When the refcount
|
||||
reaches 0 i.e. when no process or kernel client has the buffer
|
||||
open, the channel buffer is freed.
|
||||
|
||||
|
||||
In order for a user application to make use of relayfs files, the
|
||||
relayfs filesystem must be mounted. For example,
|
||||
|
||||
mount -t relayfs relayfs /mnt/relay
|
||||
|
||||
NOTE: relayfs doesn't need to be mounted for kernel clients to create
|
||||
or use channels - it only needs to be mounted when user space
|
||||
applications need access to the buffer data.
|
||||
|
||||
|
||||
The relayfs kernel API
|
||||
======================
|
||||
|
||||
Here's a summary of the API relayfs provides to in-kernel clients:
|
||||
|
||||
|
||||
channel management functions:
|
||||
|
||||
relay_open(base_filename, parent, subbuf_size, n_subbufs,
|
||||
callbacks)
|
||||
relay_close(chan)
|
||||
relay_flush(chan)
|
||||
relay_reset(chan)
|
||||
relayfs_create_dir(name, parent)
|
||||
relayfs_remove_dir(dentry)
|
||||
relayfs_create_file(name, parent, mode, fops, data)
|
||||
relayfs_remove_file(dentry)
|
||||
|
||||
channel management typically called on instigation of userspace:
|
||||
|
||||
relay_subbufs_consumed(chan, cpu, subbufs_consumed)
|
||||
|
||||
write functions:
|
||||
|
||||
relay_write(chan, data, length)
|
||||
__relay_write(chan, data, length)
|
||||
relay_reserve(chan, length)
|
||||
|
||||
callbacks:
|
||||
|
||||
subbuf_start(buf, subbuf, prev_subbuf, prev_padding)
|
||||
buf_mapped(buf, filp)
|
||||
buf_unmapped(buf, filp)
|
||||
create_buf_file(filename, parent, mode, buf, is_global)
|
||||
remove_buf_file(dentry)
|
||||
|
||||
helper functions:
|
||||
|
||||
relay_buf_full(buf)
|
||||
subbuf_start_reserve(buf, length)
|
||||
|
||||
|
||||
Creating a channel
|
||||
------------------
|
||||
|
||||
relay_open() is used to create a channel, along with its per-cpu
|
||||
channel buffers. Each channel buffer will have an associated file
|
||||
created for it in the relayfs filesystem, which can be opened and
|
||||
mmapped from user space if desired. The files are named
|
||||
basename0...basenameN-1 where N is the number of online cpus, and by
|
||||
default will be created in the root of the filesystem. If you want a
|
||||
directory structure to contain your relayfs files, you can create it
|
||||
with relayfs_create_dir() and pass the parent directory to
|
||||
relay_open(). Clients are responsible for cleaning up any directory
|
||||
structure they create when the channel is closed - use
|
||||
relayfs_remove_dir() for that.
|
||||
|
||||
The total size of each per-cpu buffer is calculated by multiplying the
|
||||
number of sub-buffers by the sub-buffer size passed into relay_open().
|
||||
The idea behind sub-buffers is that they're basically an extension of
|
||||
double-buffering to N buffers, and they also allow applications to
|
||||
easily implement random-access-on-buffer-boundary schemes, which can
|
||||
be important for some high-volume applications. The number and size
|
||||
of sub-buffers is completely dependent on the application and even for
|
||||
the same application, different conditions will warrant different
|
||||
values for these parameters at different times. Typically, the right
|
||||
values to use are best decided after some experimentation; in general,
|
||||
though, it's safe to assume that having only 1 sub-buffer is a bad
|
||||
idea - you're guaranteed to either overwrite data or lose events
|
||||
depending on the channel mode being used.
|
||||
|
||||
Channel 'modes'
|
||||
---------------
|
||||
|
||||
relayfs channels can be used in either of two modes - 'overwrite' or
|
||||
'no-overwrite'. The mode is entirely determined by the implementation
|
||||
of the subbuf_start() callback, as described below. In 'overwrite'
|
||||
mode, also known as 'flight recorder' mode, writes continuously cycle
|
||||
around the buffer and will never fail, but will unconditionally
|
||||
overwrite old data regardless of whether it's actually been consumed.
|
||||
In no-overwrite mode, writes will fail i.e. data will be lost, if the
|
||||
number of unconsumed sub-buffers equals the total number of
|
||||
sub-buffers in the channel. It should be clear that if there is no
|
||||
consumer or if the consumer can't consume sub-buffers fast enought,
|
||||
data will be lost in either case; the only difference is whether data
|
||||
is lost from the beginning or the end of a buffer.
|
||||
|
||||
As explained above, a relayfs channel is made of up one or more
|
||||
per-cpu channel buffers, each implemented as a circular buffer
|
||||
subdivided into one or more sub-buffers. Messages are written into
|
||||
the current sub-buffer of the channel's current per-cpu buffer via the
|
||||
write functions described below. Whenever a message can't fit into
|
||||
the current sub-buffer, because there's no room left for it, the
|
||||
client is notified via the subbuf_start() callback that a switch to a
|
||||
new sub-buffer is about to occur. The client uses this callback to 1)
|
||||
initialize the next sub-buffer if appropriate 2) finalize the previous
|
||||
sub-buffer if appropriate and 3) return a boolean value indicating
|
||||
whether or not to actually go ahead with the sub-buffer switch.
|
||||
|
||||
To implement 'no-overwrite' mode, the userspace client would provide
|
||||
an implementation of the subbuf_start() callback something like the
|
||||
following:
|
||||
|
||||
static int subbuf_start(struct rchan_buf *buf,
|
||||
void *subbuf,
|
||||
void *prev_subbuf,
|
||||
unsigned int prev_padding)
|
||||
{
|
||||
if (prev_subbuf)
|
||||
*((unsigned *)prev_subbuf) = prev_padding;
|
||||
|
||||
if (relay_buf_full(buf))
|
||||
return 0;
|
||||
|
||||
subbuf_start_reserve(buf, sizeof(unsigned int));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
If the current buffer is full i.e. all sub-buffers remain unconsumed,
|
||||
the callback returns 0 to indicate that the buffer switch should not
|
||||
occur yet i.e. until the consumer has had a chance to read the current
|
||||
set of ready sub-buffers. For the relay_buf_full() function to make
|
||||
sense, the consumer is reponsible for notifying relayfs when
|
||||
sub-buffers have been consumed via relay_subbufs_consumed(). Any
|
||||
subsequent attempts to write into the buffer will again invoke the
|
||||
subbuf_start() callback with the same parameters; only when the
|
||||
consumer has consumed one or more of the ready sub-buffers will
|
||||
relay_buf_full() return 0, in which case the buffer switch can
|
||||
continue.
|
||||
|
||||
The implementation of the subbuf_start() callback for 'overwrite' mode
|
||||
would be very similar:
|
||||
|
||||
static int subbuf_start(struct rchan_buf *buf,
|
||||
void *subbuf,
|
||||
void *prev_subbuf,
|
||||
unsigned int prev_padding)
|
||||
{
|
||||
if (prev_subbuf)
|
||||
*((unsigned *)prev_subbuf) = prev_padding;
|
||||
|
||||
subbuf_start_reserve(buf, sizeof(unsigned int));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
In this case, the relay_buf_full() check is meaningless and the
|
||||
callback always returns 1, causing the buffer switch to occur
|
||||
unconditionally. It's also meaningless for the client to use the
|
||||
relay_subbufs_consumed() function in this mode, as it's never
|
||||
consulted.
|
||||
|
||||
The default subbuf_start() implementation, used if the client doesn't
|
||||
define any callbacks, or doesn't define the subbuf_start() callback,
|
||||
implements the simplest possible 'no-overwrite' mode i.e. it does
|
||||
nothing but return 0.
|
||||
|
||||
Header information can be reserved at the beginning of each sub-buffer
|
||||
by calling the subbuf_start_reserve() helper function from within the
|
||||
subbuf_start() callback. This reserved area can be used to store
|
||||
whatever information the client wants. In the example above, room is
|
||||
reserved in each sub-buffer to store the padding count for that
|
||||
sub-buffer. This is filled in for the previous sub-buffer in the
|
||||
subbuf_start() implementation; the padding value for the previous
|
||||
sub-buffer is passed into the subbuf_start() callback along with a
|
||||
pointer to the previous sub-buffer, since the padding value isn't
|
||||
known until a sub-buffer is filled. The subbuf_start() callback is
|
||||
also called for the first sub-buffer when the channel is opened, to
|
||||
give the client a chance to reserve space in it. In this case the
|
||||
previous sub-buffer pointer passed into the callback will be NULL, so
|
||||
the client should check the value of the prev_subbuf pointer before
|
||||
writing into the previous sub-buffer.
|
||||
|
||||
Writing to a channel
|
||||
--------------------
|
||||
|
||||
kernel clients write data into the current cpu's channel buffer using
|
||||
relay_write() or __relay_write(). relay_write() is the main logging
|
||||
function - it uses local_irqsave() to protect the buffer and should be
|
||||
used if you might be logging from interrupt context. If you know
|
||||
you'll never be logging from interrupt context, you can use
|
||||
__relay_write(), which only disables preemption. These functions
|
||||
don't return a value, so you can't determine whether or not they
|
||||
failed - the assumption is that you wouldn't want to check a return
|
||||
value in the fast logging path anyway, and that they'll always succeed
|
||||
unless the buffer is full and no-overwrite mode is being used, in
|
||||
which case you can detect a failed write in the subbuf_start()
|
||||
callback by calling the relay_buf_full() helper function.
|
||||
|
||||
relay_reserve() is used to reserve a slot in a channel buffer which
|
||||
can be written to later. This would typically be used in applications
|
||||
that need to write directly into a channel buffer without having to
|
||||
stage data in a temporary buffer beforehand. Because the actual write
|
||||
may not happen immediately after the slot is reserved, applications
|
||||
using relay_reserve() can keep a count of the number of bytes actually
|
||||
written, either in space reserved in the sub-buffers themselves or as
|
||||
a separate array. See the 'reserve' example in the relay-apps tarball
|
||||
at http://relayfs.sourceforge.net for an example of how this can be
|
||||
done. Because the write is under control of the client and is
|
||||
separated from the reserve, relay_reserve() doesn't protect the buffer
|
||||
at all - it's up to the client to provide the appropriate
|
||||
synchronization when using relay_reserve().
|
||||
|
||||
Closing a channel
|
||||
-----------------
|
||||
|
||||
The client calls relay_close() when it's finished using the channel.
|
||||
The channel and its associated buffers are destroyed when there are no
|
||||
longer any references to any of the channel buffers. relay_flush()
|
||||
forces a sub-buffer switch on all the channel buffers, and can be used
|
||||
to finalize and process the last sub-buffers before the channel is
|
||||
closed.
|
||||
|
||||
Creating non-relay files
|
||||
------------------------
|
||||
|
||||
relay_open() automatically creates files in the relayfs filesystem to
|
||||
represent the per-cpu kernel buffers; it's often useful for
|
||||
applications to be able to create their own files alongside the relay
|
||||
files in the relayfs filesystem as well e.g. 'control' files much like
|
||||
those created in /proc or debugfs for similar purposes, used to
|
||||
communicate control information between the kernel and user sides of a
|
||||
relayfs application. For this purpose the relayfs_create_file() and
|
||||
relayfs_remove_file() API functions exist. For relayfs_create_file(),
|
||||
the caller passes in a set of user-defined file operations to be used
|
||||
for the file and an optional void * to a user-specified data item,
|
||||
which will be accessible via inode->u.generic_ip (see the relay-apps
|
||||
tarball for examples). The file_operations are a required parameter
|
||||
to relayfs_create_file() and thus the semantics of these files are
|
||||
completely defined by the caller.
|
||||
|
||||
See the relay-apps tarball at http://relayfs.sourceforge.net for
|
||||
examples of how these non-relay files are meant to be used.
|
||||
|
||||
Creating relay files in other filesystems
|
||||
-----------------------------------------
|
||||
|
||||
By default of course, relay_open() creates relay files in the relayfs
|
||||
filesystem. Because relay_file_operations is exported, however, it's
|
||||
also possible to create and use relay files in other pseudo-filesytems
|
||||
such as debugfs.
|
||||
|
||||
For this purpose, two callback functions are provided,
|
||||
create_buf_file() and remove_buf_file(). create_buf_file() is called
|
||||
once for each per-cpu buffer from relay_open() to allow the client to
|
||||
create a file to be used to represent the corresponding buffer; if
|
||||
this callback is not defined, the default implementation will create
|
||||
and return a file in the relayfs filesystem to represent the buffer.
|
||||
The callback should return the dentry of the file created to represent
|
||||
the relay buffer. Note that the parent directory passed to
|
||||
relay_open() (and passed along to the callback), if specified, must
|
||||
exist in the same filesystem the new relay file is created in. If
|
||||
create_buf_file() is defined, remove_buf_file() must also be defined;
|
||||
it's responsible for deleting the file(s) created in create_buf_file()
|
||||
and is called during relay_close().
|
||||
|
||||
The create_buf_file() implementation can also be defined in such a way
|
||||
as to allow the creation of a single 'global' buffer instead of the
|
||||
default per-cpu set. This can be useful for applications interested
|
||||
mainly in seeing the relative ordering of system-wide events without
|
||||
the need to bother with saving explicit timestamps for the purpose of
|
||||
merging/sorting per-cpu files in a postprocessing step.
|
||||
|
||||
To have relay_open() create a global buffer, the create_buf_file()
|
||||
implementation should set the value of the is_global outparam to a
|
||||
non-zero value in addition to creating the file that will be used to
|
||||
represent the single buffer. In the case of a global buffer,
|
||||
create_buf_file() and remove_buf_file() will be called only once. The
|
||||
normal channel-writing functions e.g. relay_write() can still be used
|
||||
- writes from any cpu will transparently end up in the global buffer -
|
||||
but since it is a global buffer, callers should make sure they use the
|
||||
proper locking for such a buffer, either by wrapping writes in a
|
||||
spinlock, or by copying a write function from relayfs_fs.h and
|
||||
creating a local version that internally does the proper locking.
|
||||
|
||||
See the 'exported-relayfile' examples in the relay-apps tarball for
|
||||
examples of creating and using relay files in debugfs.
|
||||
|
||||
Misc
|
||||
----
|
||||
|
||||
Some applications may want to keep a channel around and re-use it
|
||||
rather than open and close a new channel for each use. relay_reset()
|
||||
can be used for this purpose - it resets a channel to its initial
|
||||
state without reallocating channel buffer memory or destroying
|
||||
existing mappings. It should however only be called when it's safe to
|
||||
do so i.e. when the channel isn't currently being written to.
|
||||
|
||||
Finally, there are a couple of utility callbacks that can be used for
|
||||
different purposes. buf_mapped() is called whenever a channel buffer
|
||||
is mmapped from user space and buf_unmapped() is called when it's
|
||||
unmapped. The client can use this notification to trigger actions
|
||||
within the kernel application, such as enabling/disabling logging to
|
||||
the channel.
|
||||
|
||||
|
||||
Resources
|
||||
=========
|
||||
|
||||
For news, example code, mailing list, etc. see the relayfs homepage:
|
||||
|
||||
http://relayfs.sourceforge.net
|
||||
|
||||
|
||||
Credits
|
||||
=======
|
||||
|
||||
The ideas and specs for relayfs came about as a result of discussions
|
||||
on tracing involving the following:
|
||||
|
||||
Michel Dagenais <michel.dagenais@polymtl.ca>
|
||||
Richard Moore <richardj_moore@uk.ibm.com>
|
||||
Bob Wisniewski <bob@watson.ibm.com>
|
||||
Karim Yaghmour <karim@opersys.com>
|
||||
Tom Zanussi <zanussi@us.ibm.com>
|
||||
|
||||
Also thanks to Hubertus Franke for a lot of useful suggestions and bug
|
||||
reports.
|
|
@ -39,7 +39,6 @@ them. Bug reports and success stories are also welcome.
|
|||
|
||||
The input project website is at:
|
||||
|
||||
http://www.suse.cz/development/input/
|
||||
http://atrey.karlin.mff.cuni.cz/~vojtech/input/
|
||||
|
||||
There is also a mailing list for the driver at:
|
||||
|
|
|
@ -1183,6 +1183,8 @@ running once the system is up.
|
|||
Mechanism 2.
|
||||
nommconf [IA-32,X86_64] Disable use of MMCONFIG for PCI
|
||||
Configuration
|
||||
mmconf [IA-32,X86_64] Force MMCONFIG. This is useful
|
||||
to override the builtin blacklist.
|
||||
nomsi [MSI] If the PCI_MSI kernel config parameter is
|
||||
enabled, this kernel boot option can be used to
|
||||
disable the use of MSI interrupts system-wide.
|
||||
|
|
|
@ -247,7 +247,7 @@ the object-specific fields, which include:
|
|||
- default_attrs: Default attributes to be exported via sysfs when the
|
||||
object is registered.Note that the last attribute has to be
|
||||
initialized to NULL ! You can find a complete implementation
|
||||
in drivers/block/genhd.c
|
||||
in block/genhd.c
|
||||
|
||||
|
||||
Instances of struct kobj_type are not registered; only referenced by
|
||||
|
|
|
@ -294,15 +294,15 @@ tcp_rmem - vector of 3 INTEGERs: min, default, max
|
|||
Default: 87380*2 bytes.
|
||||
|
||||
tcp_mem - vector of 3 INTEGERs: min, pressure, max
|
||||
low: below this number of pages TCP is not bothered about its
|
||||
min: below this number of pages TCP is not bothered about its
|
||||
memory appetite.
|
||||
|
||||
pressure: when amount of memory allocated by TCP exceeds this number
|
||||
of pages, TCP moderates its memory consumption and enters memory
|
||||
pressure mode, which is exited when memory consumption falls
|
||||
under "low".
|
||||
under "min".
|
||||
|
||||
high: number of pages allowed for queueing by all TCP sockets.
|
||||
max: number of pages allowed for queueing by all TCP sockets.
|
||||
|
||||
Defaults are calculated at boot time from amount of available
|
||||
memory.
|
||||
|
|
|
@ -1136,10 +1136,10 @@ Sense and level information should be encoded as follows:
|
|||
Devices connected to openPIC-compatible controllers should encode
|
||||
sense and polarity as follows:
|
||||
|
||||
0 = high to low edge sensitive type enabled
|
||||
0 = low to high edge sensitive type enabled
|
||||
1 = active low level sensitive type enabled
|
||||
2 = low to high edge sensitive type enabled
|
||||
3 = active high level sensitive type enabled
|
||||
2 = active high level sensitive type enabled
|
||||
3 = high to low edge sensitive type enabled
|
||||
|
||||
ISA PIC interrupt controllers should adhere to the ISA PIC
|
||||
encodings listed below:
|
||||
|
|
|
@ -1,3 +1,126 @@
|
|||
Release Date : Fri May 19 09:31:45 EST 2006 - Seokmann Ju <sju@lsil.com>
|
||||
Current Version : 2.20.4.9 (scsi module), 2.20.2.6 (cmm module)
|
||||
Older Version : 2.20.4.8 (scsi module), 2.20.2.6 (cmm module)
|
||||
|
||||
1. Fixed a bug in megaraid_init_mbox().
|
||||
Customer reported "garbage in file on x86_64 platform".
|
||||
Root Cause: the driver registered controllers as 64-bit DMA capable
|
||||
for those which are not support it.
|
||||
Fix: Made change in the function inserting identification machanism
|
||||
identifying 64-bit DMA capable controllers.
|
||||
|
||||
> -----Original Message-----
|
||||
> From: Vasily Averin [mailto:vvs@sw.ru]
|
||||
> Sent: Thursday, May 04, 2006 2:49 PM
|
||||
> To: linux-scsi@vger.kernel.org; Kolli, Neela; Mukker, Atul;
|
||||
> Ju, Seokmann; Bagalkote, Sreenivas;
|
||||
> James.Bottomley@SteelEye.com; devel@openvz.org
|
||||
> Subject: megaraid_mbox: garbage in file
|
||||
>
|
||||
> Hello all,
|
||||
>
|
||||
> I've investigated customers claim on the unstable work of
|
||||
> their node and found a
|
||||
> strange effect: reading from some files leads to the
|
||||
> "attempt to access beyond end of device" messages.
|
||||
>
|
||||
> I've checked filesystem, memory on the node, motherboard BIOS
|
||||
> version, but it
|
||||
> does not help and issue still has been reproduced by simple
|
||||
> file reading.
|
||||
>
|
||||
> Reproducer is simple:
|
||||
>
|
||||
> echo 0xffffffff >/proc/sys/dev/scsi/logging_level ;
|
||||
> cat /vz/private/101/root/etc/ld.so.cache >/tmp/ttt ;
|
||||
> echo 0 >/proc/sys/dev/scsi/logging
|
||||
>
|
||||
> It leads to the following messages in dmesg
|
||||
>
|
||||
> sd_init_command: disk=sda, block=871769260, count=26
|
||||
> sda : block=871769260
|
||||
> sda : reading 26/26 512 byte blocks.
|
||||
> scsi_add_timer: scmd: f79ed980, time: 7500, (c02b1420)
|
||||
> sd 0:1:0:0: send 0xf79ed980 sd 0:1:0:0:
|
||||
> command: Read (10): 28 00 33 f6 24 ac 00 00 1a 00
|
||||
> buffer = 0xf7cfb540, bufflen = 13312, done = 0xc0366b40,
|
||||
> queuecommand 0xc0344010
|
||||
> leaving scsi_dispatch_cmnd()
|
||||
> scsi_delete_timer: scmd: f79ed980, rtn: 1
|
||||
> sd 0:1:0:0: done 0xf79ed980 SUCCESS 0 sd 0:1:0:0:
|
||||
> command: Read (10): 28 00 33 f6 24 ac 00 00 1a 00
|
||||
> scsi host busy 1 failed 0
|
||||
> sd 0:1:0:0: Notifying upper driver of completion (result 0)
|
||||
> sd_rw_intr: sda: res=0x0
|
||||
> 26 sectors total, 13312 bytes done.
|
||||
> use_sg is 4
|
||||
> attempt to access beyond end of device
|
||||
> sda6: rw=0, want=1044134458, limit=951401367
|
||||
> Buffer I/O error on device sda6, logical block 522067228
|
||||
> attempt to access beyond end of device
|
||||
|
||||
2. When INQUIRY with EVPD bit set issued to the MegaRAID controller,
|
||||
system memory gets corrupted.
|
||||
Root Cause: MegaRAID F/W handle the INQUIRY with EVPD bit set
|
||||
incorrectly.
|
||||
Fix: MegaRAID F/W has fixed the problem and being process of release,
|
||||
soon. Meanwhile, driver will filter out the request.
|
||||
|
||||
3. One of member in the data structure of the driver leads unaligne
|
||||
issue on 64-bit platform.
|
||||
Customer reporeted "kernel unaligned access addrss" issue when
|
||||
application communicates with MegaRAID HBA driver.
|
||||
Root Cause: in uioc_t structure, one of member had misaligned and it
|
||||
led system to display the error message.
|
||||
Fix: A patch submitted to community from following folk.
|
||||
|
||||
> -----Original Message-----
|
||||
> From: linux-scsi-owner@vger.kernel.org
|
||||
> [mailto:linux-scsi-owner@vger.kernel.org] On Behalf Of Sakurai Hiroomi
|
||||
> Sent: Wednesday, July 12, 2006 4:20 AM
|
||||
> To: linux-scsi@vger.kernel.org; linux-kernel@vger.kernel.org
|
||||
> Subject: Re: Help: strange messages from kernel on IA64 platform
|
||||
>
|
||||
> Hi,
|
||||
>
|
||||
> I saw same message.
|
||||
>
|
||||
> When GAM(Global Array Manager) is started, The following
|
||||
> message output.
|
||||
> kernel: kernel unaligned access to 0xe0000001fe1080d4,
|
||||
> ip=0xa000000200053371
|
||||
>
|
||||
> The uioc structure used by ioctl is defined by packed,
|
||||
> the allignment of each member are disturbed.
|
||||
> In a 64 bit structure, the allignment of member doesn't fit 64 bit
|
||||
> boundary. this causes this messages.
|
||||
> In a 32 bit structure, we don't see the message because the allinment
|
||||
> of member fit 32 bit boundary even if packed is specified.
|
||||
>
|
||||
> patch
|
||||
> I Add 32 bit dummy member to fit 64 bit boundary. I tested.
|
||||
> We confirmed this patch fix the problem by IA64 server.
|
||||
>
|
||||
> **************************************************************
|
||||
> ****************
|
||||
> --- linux-2.6.9/drivers/scsi/megaraid/megaraid_ioctl.h.orig
|
||||
> 2006-04-03 17:13:03.000000000 +0900
|
||||
> +++ linux-2.6.9/drivers/scsi/megaraid/megaraid_ioctl.h
|
||||
> 2006-04-03 17:14:09.000000000 +0900
|
||||
> @@ -132,6 +132,10 @@
|
||||
> /* Driver Data: */
|
||||
> void __user * user_data;
|
||||
> uint32_t user_data_len;
|
||||
> +
|
||||
> + /* 64bit alignment */
|
||||
> + uint32_t pad_0xBC;
|
||||
> +
|
||||
> mraid_passthru_t __user *user_pthru;
|
||||
>
|
||||
> mraid_passthru_t *pthru32;
|
||||
> **************************************************************
|
||||
> ****************
|
||||
|
||||
Release Date : Mon Apr 11 12:27:22 EST 2006 - Seokmann Ju <sju@lsil.com>
|
||||
Current Version : 2.20.4.8 (scsi module), 2.20.2.6 (cmm module)
|
||||
Older Version : 2.20.4.7 (scsi module), 2.20.2.6 (cmm module)
|
||||
|
|
|
@ -25,6 +25,7 @@ Currently, these files are in /proc/sys/fs:
|
|||
- inode-state
|
||||
- overflowuid
|
||||
- overflowgid
|
||||
- suid_dumpable
|
||||
- super-max
|
||||
- super-nr
|
||||
|
||||
|
@ -131,6 +132,25 @@ The default is 65534.
|
|||
|
||||
==============================================================
|
||||
|
||||
suid_dumpable:
|
||||
|
||||
This value can be used to query and set the core dump mode for setuid
|
||||
or otherwise protected/tainted binaries. The modes are
|
||||
|
||||
0 - (default) - traditional behaviour. Any process which has changed
|
||||
privilege levels or is execute only will not be dumped
|
||||
1 - (debug) - all processes dump core when possible. The core dump is
|
||||
owned by the current user and no security is applied. This is
|
||||
intended for system debugging situations only. Ptrace is unchecked.
|
||||
2 - (suidsafe) - any binary which normally would not be dumped is dumped
|
||||
readable by root only. This allows the end user to remove
|
||||
such a dump but not access it directly. For security reasons
|
||||
core dumps in this mode will not overwrite one another or
|
||||
other files. This mode is appropriate when adminstrators are
|
||||
attempting to debug problems in a normal environment.
|
||||
|
||||
==============================================================
|
||||
|
||||
super-max & super-nr:
|
||||
|
||||
These numbers control the maximum number of superblocks, and
|
||||
|
|
|
@ -50,7 +50,6 @@ show up in /proc/sys/kernel:
|
|||
- shmmax [ sysv ipc ]
|
||||
- shmmni
|
||||
- stop-a [ SPARC only ]
|
||||
- suid_dumpable
|
||||
- sysrq ==> Documentation/sysrq.txt
|
||||
- tainted
|
||||
- threads-max
|
||||
|
@ -310,25 +309,6 @@ kernel. This value defaults to SHMMAX.
|
|||
|
||||
==============================================================
|
||||
|
||||
suid_dumpable:
|
||||
|
||||
This value can be used to query and set the core dump mode for setuid
|
||||
or otherwise protected/tainted binaries. The modes are
|
||||
|
||||
0 - (default) - traditional behaviour. Any process which has changed
|
||||
privilege levels or is execute only will not be dumped
|
||||
1 - (debug) - all processes dump core when possible. The core dump is
|
||||
owned by the current user and no security is applied. This is
|
||||
intended for system debugging situations only. Ptrace is unchecked.
|
||||
2 - (suidsafe) - any binary which normally would not be dumped is dumped
|
||||
readable by root only. This allows the end user to remove
|
||||
such a dump but not access it directly. For security reasons
|
||||
core dumps in this mode will not overwrite one another or
|
||||
other files. This mode is appropriate when adminstrators are
|
||||
attempting to debug problems in a normal environment.
|
||||
|
||||
==============================================================
|
||||
|
||||
tainted:
|
||||
|
||||
Non-zero if the kernel has been tainted. Numeric values, which
|
||||
|
|
17
MAINTAINERS
17
MAINTAINERS
|
@ -889,6 +889,12 @@ M: rdunlap@xenotime.net
|
|||
T: git http://tali.admingilde.org/git/linux-docbook.git
|
||||
S: Maintained
|
||||
|
||||
DOCKING STATION DRIVER
|
||||
P: Kristen Carlson Accardi
|
||||
M: kristen.c.accardi@intel.com
|
||||
L: linux-acpi@vger.kernel.org
|
||||
S: Maintained
|
||||
|
||||
DOUBLETALK DRIVER
|
||||
P: James R. Van Zandt
|
||||
M: jrv@vanzandt.mv.com
|
||||
|
@ -2656,6 +2662,14 @@ M: chrisw@sous-sol.org
|
|||
L: stable@kernel.org
|
||||
S: Maintained
|
||||
|
||||
STABLE BRANCH:
|
||||
P: Greg Kroah-Hartman
|
||||
M: greg@kroah.com
|
||||
P: Chris Wright
|
||||
M: chrisw@sous-sol.org
|
||||
L: stable@kernel.org
|
||||
S: Maintained
|
||||
|
||||
TPM DEVICE DRIVER
|
||||
P: Kylene Hall
|
||||
M: kjhall@us.ibm.com
|
||||
|
@ -3282,10 +3296,11 @@ S: Maintained
|
|||
|
||||
XFS FILESYSTEM
|
||||
P: Silicon Graphics Inc
|
||||
P: Tim Shimmin, David Chatterton
|
||||
M: xfs-masters@oss.sgi.com
|
||||
M: nathans@sgi.com
|
||||
L: xfs@oss.sgi.com
|
||||
W: http://oss.sgi.com/projects/xfs
|
||||
T: git git://oss.sgi.com:8090/xfs/xfs-2.6
|
||||
S: Supported
|
||||
|
||||
X86 3-LEVEL PAGING (PAE) SUPPORT
|
||||
|
|
34
Makefile
34
Makefile
|
@ -1,7 +1,7 @@
|
|||
VERSION = 2
|
||||
PATCHLEVEL = 6
|
||||
SUBLEVEL = 18
|
||||
EXTRAVERSION = -rc4
|
||||
EXTRAVERSION = -rc5
|
||||
NAME=Crazed Snow-Weasel
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
@ -309,9 +309,6 @@ CPPFLAGS := -D__KERNEL__ $(LINUXINCLUDE)
|
|||
|
||||
CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
|
||||
-fno-strict-aliasing -fno-common
|
||||
# Force gcc to behave correct even for buggy distributions
|
||||
CFLAGS += $(call cc-option, -fno-stack-protector)
|
||||
|
||||
AFLAGS := -D__ASSEMBLY__
|
||||
|
||||
# Read KERNELRELEASE from include/config/kernel.release (if it exists)
|
||||
|
@ -436,12 +433,13 @@ core-y := usr/
|
|||
endif # KBUILD_EXTMOD
|
||||
|
||||
ifeq ($(dot-config),1)
|
||||
# In this section, we need .config
|
||||
# Read in config
|
||||
-include include/config/auto.conf
|
||||
|
||||
ifeq ($(KBUILD_EXTMOD),)
|
||||
# Read in dependencies to all Kconfig* files, make sure to run
|
||||
# oldconfig if changes are detected.
|
||||
-include include/config/auto.conf.cmd
|
||||
-include include/config/auto.conf
|
||||
|
||||
# To avoid any implicit rule to kick in, define an empty command
|
||||
$(KCONFIG_CONFIG) include/config/auto.conf.cmd: ;
|
||||
|
@ -451,16 +449,27 @@ $(KCONFIG_CONFIG) include/config/auto.conf.cmd: ;
|
|||
# if auto.conf.cmd is missing then we are probably in a cleaned tree so
|
||||
# we execute the config step to be sure to catch updated Kconfig files
|
||||
include/config/auto.conf: $(KCONFIG_CONFIG) include/config/auto.conf.cmd
|
||||
ifeq ($(KBUILD_EXTMOD),)
|
||||
$(Q)$(MAKE) -f $(srctree)/Makefile silentoldconfig
|
||||
else
|
||||
$(error kernel configuration not valid - run 'make prepare' in $(srctree) to update it)
|
||||
endif
|
||||
# external modules needs include/linux/autoconf.h and include/config/auto.conf
|
||||
# but do not care if they are up-to-date. Use auto.conf to trigger the test
|
||||
PHONY += include/config/auto.conf
|
||||
|
||||
include/config/auto.conf:
|
||||
$(Q)test -e include/linux/autoconf.h -a -e $@ || ( \
|
||||
echo; \
|
||||
echo " ERROR: Kernel configuration is invalid."; \
|
||||
echo " include/linux/autoconf.h or $@ are missing."; \
|
||||
echo " Run 'make oldconfig && make prepare' on kernel src to fix it."; \
|
||||
echo; \
|
||||
/bin/false)
|
||||
|
||||
endif # KBUILD_EXTMOD
|
||||
|
||||
else
|
||||
# Dummy target needed, because used as prerequisite
|
||||
include/config/auto.conf: ;
|
||||
endif
|
||||
endif # $(dot-config)
|
||||
|
||||
# The all: target is the default when no target is given on the
|
||||
# command line.
|
||||
|
@ -474,6 +483,8 @@ else
|
|||
CFLAGS += -O2
|
||||
endif
|
||||
|
||||
include $(srctree)/arch/$(ARCH)/Makefile
|
||||
|
||||
ifdef CONFIG_FRAME_POINTER
|
||||
CFLAGS += -fno-omit-frame-pointer $(call cc-option,-fno-optimize-sibling-calls,)
|
||||
else
|
||||
|
@ -488,7 +499,8 @@ ifdef CONFIG_DEBUG_INFO
|
|||
CFLAGS += -g
|
||||
endif
|
||||
|
||||
include $(srctree)/arch/$(ARCH)/Makefile
|
||||
# Force gcc to behave correct even for buggy distributions
|
||||
CFLAGS += $(call cc-option, -fno-stack-protector)
|
||||
|
||||
# arch Makefile may override CC so keep this after arch Makefile is included
|
||||
NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include)
|
||||
|
|
|
@ -47,7 +47,8 @@ comma = ,
|
|||
# testing for a specific architecture or later rather impossible.
|
||||
arch-$(CONFIG_CPU_32v6) :=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6,-march=armv5t -Wa$(comma)-march=armv6)
|
||||
arch-$(CONFIG_CPU_32v6K) :=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6k,-march=armv5t -Wa$(comma)-march=armv6k)
|
||||
arch-$(CONFIG_CPU_32v5) :=-D__LINUX_ARM_ARCH__=5 $(call cc-option,-march=armv5te,-march=armv4)
|
||||
arch-$(CONFIG_CPU_32v5) :=-D__LINUX_ARM_ARCH__=5 $(call cc-option,-march=armv5te,-march=armv4t)
|
||||
arch-$(CONFIG_CPU_32v4T) :=-D__LINUX_ARM_ARCH__=4 -march=armv4t
|
||||
arch-$(CONFIG_CPU_32v4) :=-D__LINUX_ARM_ARCH__=4 -march=armv4
|
||||
arch-$(CONFIG_CPU_32v3) :=-D__LINUX_ARM_ARCH__=3 -march=armv3
|
||||
|
||||
|
|
|
@ -179,17 +179,19 @@ alloc_safe_buffer(struct dmabounce_device_info *device_info, void *ptr,
|
|||
static inline struct safe_buffer *
|
||||
find_safe_buffer(struct dmabounce_device_info *device_info, dma_addr_t safe_dma_addr)
|
||||
{
|
||||
struct safe_buffer *b = NULL;
|
||||
struct safe_buffer *b, *rb = NULL;
|
||||
unsigned long flags;
|
||||
|
||||
read_lock_irqsave(&device_info->lock, flags);
|
||||
|
||||
list_for_each_entry(b, &device_info->safe_buffers, node)
|
||||
if (b->safe_dma_addr == safe_dma_addr)
|
||||
if (b->safe_dma_addr == safe_dma_addr) {
|
||||
rb = b;
|
||||
break;
|
||||
}
|
||||
|
||||
read_unlock_irqrestore(&device_info->lock, flags);
|
||||
return b;
|
||||
return rb;
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
|
|
@ -68,6 +68,7 @@ void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now, struct rtc
|
|||
rtc_time_to_tm(next_time, next);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(rtc_next_alarm_time);
|
||||
|
||||
static inline int rtc_arm_read_time(struct rtc_ops *ops, struct rtc_time *tm)
|
||||
{
|
||||
|
|
|
@ -618,7 +618,7 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq)
|
|||
{
|
||||
struct sa1111 *sachip;
|
||||
unsigned long id;
|
||||
unsigned int has_devs, val;
|
||||
unsigned int has_devs;
|
||||
int i, ret = -ENODEV;
|
||||
|
||||
sachip = kzalloc(sizeof(struct sa1111), GFP_KERNEL);
|
||||
|
@ -669,6 +669,9 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq)
|
|||
sa1111_wake(sachip);
|
||||
|
||||
#ifdef CONFIG_ARCH_SA1100
|
||||
{
|
||||
unsigned int val;
|
||||
|
||||
/*
|
||||
* The SDRAM configuration of the SA1110 and the SA1111 must
|
||||
* match. This is very important to ensure that SA1111 accesses
|
||||
|
@ -692,6 +695,7 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq)
|
|||
* Enable the SA1110 memory bus request and grant signals.
|
||||
*/
|
||||
sa1110_mb_enable();
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
|
@ -13,12 +13,11 @@ obj-y := compat.o entry-armv.o entry-common.o irq.o \
|
|||
obj-$(CONFIG_APM) += apm.o
|
||||
obj-$(CONFIG_ISA_DMA_API) += dma.o
|
||||
obj-$(CONFIG_ARCH_ACORN) += ecard.o
|
||||
obj-$(CONFIG_FOOTBRIDGE) += isa.o
|
||||
obj-$(CONFIG_FIQ) += fiq.o
|
||||
obj-$(CONFIG_MODULES) += armksyms.o module.o
|
||||
obj-$(CONFIG_ARTHUR) += arthur.o
|
||||
obj-$(CONFIG_ISA_DMA) += dma-isa.o
|
||||
obj-$(CONFIG_PCI) += bios32.o
|
||||
obj-$(CONFIG_PCI) += bios32.o isa.o
|
||||
obj-$(CONFIG_SMP) += smp.o
|
||||
obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o
|
||||
|
||||
|
|
|
@ -634,6 +634,14 @@ ENTRY(__switch_to)
|
|||
* purpose.
|
||||
*/
|
||||
|
||||
.macro usr_ret, reg
|
||||
#ifdef CONFIG_ARM_THUMB
|
||||
bx \reg
|
||||
#else
|
||||
mov pc, \reg
|
||||
#endif
|
||||
.endm
|
||||
|
||||
.align 5
|
||||
.globl __kuser_helper_start
|
||||
__kuser_helper_start:
|
||||
|
@ -675,7 +683,7 @@ __kuser_memory_barrier: @ 0xffff0fa0
|
|||
#if __LINUX_ARM_ARCH__ >= 6 && defined(CONFIG_SMP)
|
||||
mcr p15, 0, r0, c7, c10, 5 @ dmb
|
||||
#endif
|
||||
mov pc, lr
|
||||
usr_ret lr
|
||||
|
||||
.align 5
|
||||
|
||||
|
@ -778,7 +786,7 @@ __kuser_cmpxchg: @ 0xffff0fc0
|
|||
mov r0, #-1
|
||||
adds r0, r0, #0
|
||||
#endif
|
||||
mov pc, lr
|
||||
usr_ret lr
|
||||
|
||||
#else
|
||||
|
||||
|
@ -792,7 +800,7 @@ __kuser_cmpxchg: @ 0xffff0fc0
|
|||
#ifdef CONFIG_SMP
|
||||
mcr p15, 0, r0, c7, c10, 5 @ dmb
|
||||
#endif
|
||||
mov pc, lr
|
||||
usr_ret lr
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -834,16 +842,11 @@ __kuser_cmpxchg: @ 0xffff0fc0
|
|||
__kuser_get_tls: @ 0xffff0fe0
|
||||
|
||||
#if !defined(CONFIG_HAS_TLS_REG) && !defined(CONFIG_TLS_REG_EMUL)
|
||||
|
||||
ldr r0, [pc, #(16 - 8)] @ TLS stored at 0xffff0ff0
|
||||
mov pc, lr
|
||||
|
||||
#else
|
||||
|
||||
mrc p15, 0, r0, c13, c0, 3 @ read TLS register
|
||||
mov pc, lr
|
||||
|
||||
#endif
|
||||
usr_ret lr
|
||||
|
||||
.rep 5
|
||||
.word 0 @ pad up to __kuser_helper_version
|
||||
|
|
|
@ -118,7 +118,7 @@ ENTRY(secondary_startup)
|
|||
sub r4, r4, r5 @ mmu has been enabled
|
||||
ldr r4, [r7, r4] @ get secondary_data.pgdir
|
||||
adr lr, __enable_mmu @ return address
|
||||
add pc, r10, #12 @ initialise processor
|
||||
add pc, r10, #PROCINFO_INITFUNC @ initialise processor
|
||||
@ (return control reg)
|
||||
|
||||
/*
|
||||
|
|
|
@ -3,21 +3,14 @@
|
|||
*
|
||||
* Copyright (C) 1999 Phil Blundell
|
||||
*
|
||||
* ISA shared memory and I/O port 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.
|
||||
*
|
||||
* ISA shared memory and I/O port support, and is required to support
|
||||
* iopl, inb, outb and friends in userspace via glibc emulation.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Nothing about this is actually ARM specific. One day we could move
|
||||
* it into kernel/resource.c or some place like that.
|
||||
*/
|
||||
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/fs.h>
|
||||
|
@ -27,21 +20,49 @@
|
|||
static unsigned int isa_membase, isa_portbase, isa_portshift;
|
||||
|
||||
static ctl_table ctl_isa_vars[4] = {
|
||||
{BUS_ISA_MEM_BASE, "membase", &isa_membase,
|
||||
sizeof(isa_membase), 0444, NULL, &proc_dointvec},
|
||||
{BUS_ISA_PORT_BASE, "portbase", &isa_portbase,
|
||||
sizeof(isa_portbase), 0444, NULL, &proc_dointvec},
|
||||
{BUS_ISA_PORT_SHIFT, "portshift", &isa_portshift,
|
||||
sizeof(isa_portshift), 0444, NULL, &proc_dointvec},
|
||||
{0}
|
||||
{
|
||||
.ctl_name = BUS_ISA_MEM_BASE,
|
||||
.procname = "membase",
|
||||
.data = &isa_membase,
|
||||
.maxlen = sizeof(isa_membase),
|
||||
.mode = 0444,
|
||||
.proc_handler = &proc_dointvec,
|
||||
}, {
|
||||
.ctl_name = BUS_ISA_PORT_BASE,
|
||||
.procname = "portbase",
|
||||
.data = &isa_portbase,
|
||||
.maxlen = sizeof(isa_portbase),
|
||||
.mode = 0444,
|
||||
.proc_handler = &proc_dointvec,
|
||||
}, {
|
||||
.ctl_name = BUS_ISA_PORT_SHIFT,
|
||||
.procname = "portshift",
|
||||
.data = &isa_portshift,
|
||||
.maxlen = sizeof(isa_portshift),
|
||||
.mode = 0444,
|
||||
.proc_handler = &proc_dointvec,
|
||||
}, {0}
|
||||
};
|
||||
|
||||
static struct ctl_table_header *isa_sysctl_header;
|
||||
|
||||
static ctl_table ctl_isa[2] = {{CTL_BUS_ISA, "isa", NULL, 0, 0555, ctl_isa_vars},
|
||||
{0}};
|
||||
static ctl_table ctl_bus[2] = {{CTL_BUS, "bus", NULL, 0, 0555, ctl_isa},
|
||||
{0}};
|
||||
static ctl_table ctl_isa[2] = {
|
||||
{
|
||||
.ctl_name = CTL_BUS_ISA,
|
||||
.procname = "isa",
|
||||
.mode = 0555,
|
||||
.child = ctl_isa_vars,
|
||||
}, {0}
|
||||
};
|
||||
|
||||
static ctl_table ctl_bus[2] = {
|
||||
{
|
||||
.ctl_name = CTL_BUS,
|
||||
.procname = "bus",
|
||||
.mode = 0555,
|
||||
.child = ctl_isa,
|
||||
}, {0}
|
||||
};
|
||||
|
||||
void __init
|
||||
register_isa_ports(unsigned int membase, unsigned int portbase, unsigned int portshift)
|
||||
|
|
|
@ -233,7 +233,7 @@ NORET_TYPE void die(const char *str, struct pt_regs *regs, int err)
|
|||
spin_unlock_irq(&die_lock);
|
||||
|
||||
if (panic_on_oops)
|
||||
panic("Fatal exception: panic_on_oops");
|
||||
panic("Fatal exception");
|
||||
|
||||
do_exit(SIGSEGV);
|
||||
}
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
|
||||
extern int setup_arm_irq(int, struct irqaction *);
|
||||
extern void pcibios_report_status(u_int status_mask, int warn);
|
||||
extern void register_isa_ports(unsigned int, unsigned int, unsigned int);
|
||||
|
||||
static unsigned long
|
||||
dc21285_base_address(struct pci_bus *bus, unsigned int devfn)
|
||||
|
|
|
@ -600,4 +600,6 @@ void __init pci_v3_postinit(void)
|
|||
printk(KERN_ERR "PCI: unable to grab local bus timeout "
|
||||
"interrupt: %d\n", ret);
|
||||
#endif
|
||||
|
||||
register_isa_ports(PHYS_PCI_MEM_BASE, PHYS_PCI_IO_BASE, 0);
|
||||
}
|
||||
|
|
|
@ -532,8 +532,6 @@ pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask)
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(pci_set_dma_mask);
|
||||
EXPORT_SYMBOL(pci_set_consistent_dma_mask);
|
||||
EXPORT_SYMBOL(ixp4xx_pci_read);
|
||||
EXPORT_SYMBOL(ixp4xx_pci_write);
|
||||
|
||||
|
|
|
@ -107,9 +107,9 @@ static struct flash_platform_data gtwx5715_flash_data = {
|
|||
.width = 2,
|
||||
};
|
||||
|
||||
static struct gtw5715_flash_resource = {
|
||||
static struct resource gtwx5715_flash_resource = {
|
||||
.flags = IORESOURCE_MEM,
|
||||
}
|
||||
};
|
||||
|
||||
static struct platform_device gtwx5715_flash = {
|
||||
.name = "IXP4XX-Flash",
|
||||
|
@ -130,9 +130,6 @@ static void __init gtwx5715_init(void)
|
|||
{
|
||||
ixp4xx_sys_init();
|
||||
|
||||
if (!flash_resource)
|
||||
printk(KERN_ERR "Could not allocate flash resource\n");
|
||||
|
||||
gtwx5715_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
|
||||
gtwx5715_flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + SZ_8M - 1;
|
||||
|
||||
|
|
|
@ -47,14 +47,15 @@ static struct corgissp_machinfo *ssp_machinfo;
|
|||
*/
|
||||
unsigned long corgi_ssp_ads7846_putget(ulong data)
|
||||
{
|
||||
unsigned long ret,flag;
|
||||
unsigned long flag;
|
||||
u32 ret = 0;
|
||||
|
||||
spin_lock_irqsave(&corgi_ssp_lock, flag);
|
||||
if (ssp_machinfo->cs_ads7846 >= 0)
|
||||
GPCR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846);
|
||||
|
||||
ssp_write_word(&corgi_ssp_dev,data);
|
||||
ret = ssp_read_word(&corgi_ssp_dev);
|
||||
ssp_read_word(&corgi_ssp_dev, &ret);
|
||||
|
||||
if (ssp_machinfo->cs_ads7846 >= 0)
|
||||
GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846);
|
||||
|
@ -88,7 +89,9 @@ void corgi_ssp_ads7846_put(ulong data)
|
|||
|
||||
unsigned long corgi_ssp_ads7846_get(void)
|
||||
{
|
||||
return ssp_read_word(&corgi_ssp_dev);
|
||||
u32 ret = 0;
|
||||
ssp_read_word(&corgi_ssp_dev, &ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(corgi_ssp_ads7846_putget);
|
||||
|
@ -104,6 +107,7 @@ EXPORT_SYMBOL(corgi_ssp_ads7846_get);
|
|||
unsigned long corgi_ssp_dac_put(ulong data)
|
||||
{
|
||||
unsigned long flag, sscr1 = SSCR1_SPH;
|
||||
u32 tmp;
|
||||
|
||||
spin_lock_irqsave(&corgi_ssp_lock, flag);
|
||||
|
||||
|
@ -118,7 +122,7 @@ unsigned long corgi_ssp_dac_put(ulong data)
|
|||
GPCR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon);
|
||||
ssp_write_word(&corgi_ssp_dev,data);
|
||||
/* Read null data back from device to prevent SSP overflow */
|
||||
ssp_read_word(&corgi_ssp_dev);
|
||||
ssp_read_word(&corgi_ssp_dev, &tmp);
|
||||
if (ssp_machinfo->cs_lcdcon >= 0)
|
||||
GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon);
|
||||
|
||||
|
@ -150,7 +154,7 @@ EXPORT_SYMBOL(corgi_ssp_blduty_set);
|
|||
int corgi_ssp_max1111_get(ulong data)
|
||||
{
|
||||
unsigned long flag;
|
||||
int voltage,voltage1,voltage2;
|
||||
long voltage = 0, voltage1 = 0, voltage2 = 0;
|
||||
|
||||
spin_lock_irqsave(&corgi_ssp_lock, flag);
|
||||
if (ssp_machinfo->cs_max1111 >= 0)
|
||||
|
@ -163,15 +167,15 @@ int corgi_ssp_max1111_get(ulong data)
|
|||
|
||||
/* TB1/RB1 */
|
||||
ssp_write_word(&corgi_ssp_dev,data);
|
||||
ssp_read_word(&corgi_ssp_dev); /* null read */
|
||||
ssp_read_word(&corgi_ssp_dev, (u32*)&voltage1); /* null read */
|
||||
|
||||
/* TB12/RB2 */
|
||||
ssp_write_word(&corgi_ssp_dev,0);
|
||||
voltage1=ssp_read_word(&corgi_ssp_dev);
|
||||
ssp_read_word(&corgi_ssp_dev, (u32*)&voltage1);
|
||||
|
||||
/* TB13/RB3*/
|
||||
ssp_write_word(&corgi_ssp_dev,0);
|
||||
voltage2=ssp_read_word(&corgi_ssp_dev);
|
||||
ssp_read_word(&corgi_ssp_dev, (u32*)&voltage2);
|
||||
|
||||
ssp_disable(&corgi_ssp_dev);
|
||||
ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_ads7846));
|
||||
|
|
|
@ -40,6 +40,8 @@
|
|||
|
||||
#define PXA_SSP_PORTS 3
|
||||
|
||||
#define TIMEOUT 100000
|
||||
|
||||
struct ssp_info_ {
|
||||
int irq;
|
||||
u32 clock;
|
||||
|
@ -92,13 +94,18 @@ static irqreturn_t ssp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
|||
* The caller is expected to perform the necessary locking.
|
||||
*
|
||||
* Returns:
|
||||
* %-ETIMEDOUT timeout occurred (for future)
|
||||
* %-ETIMEDOUT timeout occurred
|
||||
* 0 success
|
||||
*/
|
||||
int ssp_write_word(struct ssp_dev *dev, u32 data)
|
||||
{
|
||||
while (!(SSSR_P(dev->port) & SSSR_TNF))
|
||||
int timeout = TIMEOUT;
|
||||
|
||||
while (!(SSSR_P(dev->port) & SSSR_TNF)) {
|
||||
if (!--timeout)
|
||||
return -ETIMEDOUT;
|
||||
cpu_relax();
|
||||
}
|
||||
|
||||
SSDR_P(dev->port) = data;
|
||||
|
||||
|
@ -117,15 +124,21 @@ int ssp_write_word(struct ssp_dev *dev, u32 data)
|
|||
* The caller is expected to perform the necessary locking.
|
||||
*
|
||||
* Returns:
|
||||
* %-ETIMEDOUT timeout occurred (for future)
|
||||
* %-ETIMEDOUT timeout occurred
|
||||
* 32-bit data success
|
||||
*/
|
||||
int ssp_read_word(struct ssp_dev *dev)
|
||||
int ssp_read_word(struct ssp_dev *dev, u32 *data)
|
||||
{
|
||||
while (!(SSSR_P(dev->port) & SSSR_RNE))
|
||||
cpu_relax();
|
||||
int timeout = TIMEOUT;
|
||||
|
||||
return SSDR_P(dev->port);
|
||||
while (!(SSSR_P(dev->port) & SSSR_RNE)) {
|
||||
if (!--timeout)
|
||||
return -ETIMEDOUT;
|
||||
cpu_relax();
|
||||
}
|
||||
|
||||
*data = SSDR_P(dev->port);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -136,13 +149,21 @@ int ssp_read_word(struct ssp_dev *dev)
|
|||
*
|
||||
* The caller is expected to perform the necessary locking.
|
||||
*/
|
||||
void ssp_flush(struct ssp_dev *dev)
|
||||
int ssp_flush(struct ssp_dev *dev)
|
||||
{
|
||||
int timeout = TIMEOUT * 2;
|
||||
|
||||
do {
|
||||
while (SSSR_P(dev->port) & SSSR_RNE) {
|
||||
if (!--timeout)
|
||||
return -ETIMEDOUT;
|
||||
(void) SSDR_P(dev->port);
|
||||
}
|
||||
if (!--timeout)
|
||||
return -ETIMEDOUT;
|
||||
} while (SSSR_P(dev->port) & SSSR_BSY);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -10,6 +10,9 @@ obj-m :=
|
|||
obj-n :=
|
||||
obj- :=
|
||||
|
||||
# DMA
|
||||
obj-$(CONFIG_S3C2410_DMA) += dma.o
|
||||
|
||||
# S3C2400 support files
|
||||
obj-$(CONFIG_CPU_S3C2400) += s3c2400-gpio.o
|
||||
|
||||
|
@ -17,7 +20,6 @@ obj-$(CONFIG_CPU_S3C2400) += s3c2400-gpio.o
|
|||
|
||||
obj-$(CONFIG_CPU_S3C2410) += s3c2410.o
|
||||
obj-$(CONFIG_CPU_S3C2410) += s3c2410-gpio.o
|
||||
obj-$(CONFIG_S3C2410_DMA) += dma.o
|
||||
|
||||
# Power Management support
|
||||
|
||||
|
|
|
@ -112,7 +112,7 @@ dmadbg_capture(s3c2410_dma_chan_t *chan, struct s3c2410_dma_regstate *regs)
|
|||
}
|
||||
|
||||
static void
|
||||
dmadbg_showregs(const char *fname, int line, s3c2410_dma_chan_t *chan,
|
||||
dmadbg_dumpregs(const char *fname, int line, s3c2410_dma_chan_t *chan,
|
||||
struct s3c2410_dma_regstate *regs)
|
||||
{
|
||||
printk(KERN_DEBUG "dma%d: %s:%d: DCSRC=%08lx, DISRC=%08lx, DSTAT=%08lx DMT=%02lx, DCON=%08lx\n",
|
||||
|
@ -132,7 +132,16 @@ dmadbg_showchan(const char *fname, int line, s3c2410_dma_chan_t *chan)
|
|||
chan->number, fname, line, chan->load_state,
|
||||
chan->curr, chan->next, chan->end);
|
||||
|
||||
dmadbg_showregs(fname, line, chan, &state);
|
||||
dmadbg_dumpregs(fname, line, chan, &state);
|
||||
}
|
||||
|
||||
static void
|
||||
dmadbg_showregs(const char *fname, int line, s3c2410_dma_chan_t *chan)
|
||||
{
|
||||
struct s3c2410_dma_regstate state;
|
||||
|
||||
dmadbg_capture(chan, &state);
|
||||
dmadbg_dumpregs(fname, line, chan, &state);
|
||||
}
|
||||
|
||||
#define dbg_showregs(chan) dmadbg_showregs(__FUNCTION__, __LINE__, (chan))
|
||||
|
@ -253,10 +262,14 @@ s3c2410_dma_loadbuffer(s3c2410_dma_chan_t *chan,
|
|||
buf->next);
|
||||
reload = (buf->next == NULL) ? S3C2410_DCON_NORELOAD : 0;
|
||||
} else {
|
||||
pr_debug("load_state is %d => autoreload\n", chan->load_state);
|
||||
//pr_debug("load_state is %d => autoreload\n", chan->load_state);
|
||||
reload = S3C2410_DCON_AUTORELOAD;
|
||||
}
|
||||
|
||||
if ((buf->data & 0xf0000000) != 0x30000000) {
|
||||
dmawarn("dmaload: buffer is %p\n", (void *)buf->data);
|
||||
}
|
||||
|
||||
writel(buf->data, chan->addr_reg);
|
||||
|
||||
dma_wrreg(chan, S3C2410_DMA_DCON,
|
||||
|
@ -370,7 +383,7 @@ static int s3c2410_dma_start(s3c2410_dma_chan_t *chan)
|
|||
tmp |= S3C2410_DMASKTRIG_ON;
|
||||
dma_wrreg(chan, S3C2410_DMA_DMASKTRIG, tmp);
|
||||
|
||||
pr_debug("wrote %08lx to DMASKTRIG\n", tmp);
|
||||
pr_debug("dma%d: %08lx to DMASKTRIG\n", chan->number, tmp);
|
||||
|
||||
#if 0
|
||||
/* the dma buffer loads should take care of clearing the AUTO
|
||||
|
@ -384,7 +397,30 @@ static int s3c2410_dma_start(s3c2410_dma_chan_t *chan)
|
|||
|
||||
dbg_showchan(chan);
|
||||
|
||||
/* if we've only loaded one buffer onto the channel, then chec
|
||||
* to see if we have another, and if so, try and load it so when
|
||||
* the first buffer is finished, the new one will be loaded onto
|
||||
* the channel */
|
||||
|
||||
if (chan->next != NULL) {
|
||||
if (chan->load_state == S3C2410_DMALOAD_1LOADED) {
|
||||
|
||||
if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
|
||||
pr_debug("%s: buff not yet loaded, no more todo\n",
|
||||
__FUNCTION__);
|
||||
} else {
|
||||
chan->load_state = S3C2410_DMALOAD_1RUNNING;
|
||||
s3c2410_dma_loadbuffer(chan, chan->next);
|
||||
}
|
||||
|
||||
} else if (chan->load_state == S3C2410_DMALOAD_1RUNNING) {
|
||||
s3c2410_dma_loadbuffer(chan, chan->next);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
local_irq_restore(flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -436,12 +472,11 @@ int s3c2410_dma_enqueue(unsigned int channel, void *id,
|
|||
buf = kmem_cache_alloc(dma_kmem, GFP_ATOMIC);
|
||||
if (buf == NULL) {
|
||||
pr_debug("%s: out of memory (%ld alloc)\n",
|
||||
__FUNCTION__, sizeof(*buf));
|
||||
__FUNCTION__, (long)sizeof(*buf));
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
pr_debug("%s: new buffer %p\n", __FUNCTION__, buf);
|
||||
|
||||
//pr_debug("%s: new buffer %p\n", __FUNCTION__, buf);
|
||||
//dbg_showchan(chan);
|
||||
|
||||
buf->next = NULL;
|
||||
|
@ -537,14 +572,20 @@ s3c2410_dma_lastxfer(s3c2410_dma_chan_t *chan)
|
|||
case S3C2410_DMALOAD_1LOADED:
|
||||
if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
|
||||
/* flag error? */
|
||||
printk(KERN_ERR "dma%d: timeout waiting for load\n",
|
||||
chan->number);
|
||||
printk(KERN_ERR "dma%d: timeout waiting for load (%s)\n",
|
||||
chan->number, __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case S3C2410_DMALOAD_1LOADED_1RUNNING:
|
||||
/* I belive in this case we do not have anything to do
|
||||
* until the next buffer comes along, and we turn off the
|
||||
* reload */
|
||||
return;
|
||||
|
||||
default:
|
||||
pr_debug("dma%d: lastxfer: unhandled load_state %d with no next",
|
||||
pr_debug("dma%d: lastxfer: unhandled load_state %d with no next\n",
|
||||
chan->number, chan->load_state);
|
||||
return;
|
||||
|
||||
|
@ -629,7 +670,14 @@ s3c2410_dma_irq(int irq, void *devpw, struct pt_regs *regs)
|
|||
} else {
|
||||
}
|
||||
|
||||
if (chan->next != NULL) {
|
||||
/* only reload if the channel is still running... our buffer done
|
||||
* routine may have altered the state by requesting the dma channel
|
||||
* to stop or shutdown... */
|
||||
|
||||
/* todo: check that when the channel is shut-down from inside this
|
||||
* function, we cope with unsetting reload, etc */
|
||||
|
||||
if (chan->next != NULL && chan->state != S3C2410_DMA_IDLE) {
|
||||
unsigned long flags;
|
||||
|
||||
switch (chan->load_state) {
|
||||
|
@ -644,8 +692,8 @@ s3c2410_dma_irq(int irq, void *devpw, struct pt_regs *regs)
|
|||
case S3C2410_DMALOAD_1LOADED:
|
||||
if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
|
||||
/* flag error? */
|
||||
printk(KERN_ERR "dma%d: timeout waiting for load\n",
|
||||
chan->number);
|
||||
printk(KERN_ERR "dma%d: timeout waiting for load (%s)\n",
|
||||
chan->number, __FUNCTION__);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
@ -678,8 +726,6 @@ s3c2410_dma_irq(int irq, void *devpw, struct pt_regs *regs)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* s3c2410_request_dma
|
||||
*
|
||||
* get control of an dma channel
|
||||
|
@ -718,11 +764,17 @@ int s3c2410_dma_request(unsigned int channel, s3c2410_dma_client_t *client,
|
|||
pr_debug("dma%d: %s : requesting irq %d\n",
|
||||
channel, __FUNCTION__, chan->irq);
|
||||
|
||||
chan->irq_claimed = 1;
|
||||
local_irq_restore(flags);
|
||||
|
||||
err = request_irq(chan->irq, s3c2410_dma_irq, IRQF_DISABLED,
|
||||
client->name, (void *)chan);
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
if (err) {
|
||||
chan->in_use = 0;
|
||||
chan->irq_claimed = 0;
|
||||
local_irq_restore(flags);
|
||||
|
||||
printk(KERN_ERR "%s: cannot get IRQ %d for DMA %d\n",
|
||||
|
@ -730,7 +782,6 @@ int s3c2410_dma_request(unsigned int channel, s3c2410_dma_client_t *client,
|
|||
return err;
|
||||
}
|
||||
|
||||
chan->irq_claimed = 1;
|
||||
chan->irq_enabled = 1;
|
||||
}
|
||||
|
||||
|
@ -810,6 +861,7 @@ static int s3c2410_dma_dostop(s3c2410_dma_chan_t *chan)
|
|||
|
||||
tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
|
||||
tmp |= S3C2410_DMASKTRIG_STOP;
|
||||
//tmp &= ~S3C2410_DMASKTRIG_ON;
|
||||
dma_wrreg(chan, S3C2410_DMA_DMASKTRIG, tmp);
|
||||
|
||||
#if 0
|
||||
|
@ -819,6 +871,7 @@ static int s3c2410_dma_dostop(s3c2410_dma_chan_t *chan)
|
|||
dma_wrreg(chan, S3C2410_DMA_DCON, tmp);
|
||||
#endif
|
||||
|
||||
/* should stop do this, or should we wait for flush? */
|
||||
chan->state = S3C2410_DMA_IDLE;
|
||||
chan->load_state = S3C2410_DMALOAD_NONE;
|
||||
|
||||
|
@ -827,6 +880,22 @@ static int s3c2410_dma_dostop(s3c2410_dma_chan_t *chan)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void s3c2410_dma_waitforstop(s3c2410_dma_chan_t *chan)
|
||||
{
|
||||
unsigned long tmp;
|
||||
unsigned int timeout = 0x10000;
|
||||
|
||||
while (timeout-- > 0) {
|
||||
tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
|
||||
|
||||
if (!(tmp & S3C2410_DMASKTRIG_ON))
|
||||
return;
|
||||
}
|
||||
|
||||
pr_debug("dma%d: failed to stop?\n", chan->number);
|
||||
}
|
||||
|
||||
|
||||
/* s3c2410_dma_flush
|
||||
*
|
||||
* stop the channel, and remove all current and pending transfers
|
||||
|
@ -837,7 +906,9 @@ static int s3c2410_dma_flush(s3c2410_dma_chan_t *chan)
|
|||
s3c2410_dma_buf_t *buf, *next;
|
||||
unsigned long flags;
|
||||
|
||||
pr_debug("%s:\n", __FUNCTION__);
|
||||
pr_debug("%s: chan %p (%d)\n", __FUNCTION__, chan, chan->number);
|
||||
|
||||
dbg_showchan(chan);
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
|
@ -864,11 +935,64 @@ static int s3c2410_dma_flush(s3c2410_dma_chan_t *chan)
|
|||
}
|
||||
}
|
||||
|
||||
dbg_showregs(chan);
|
||||
|
||||
s3c2410_dma_waitforstop(chan);
|
||||
|
||||
#if 0
|
||||
/* should also clear interrupts, according to WinCE BSP */
|
||||
{
|
||||
unsigned long tmp;
|
||||
|
||||
tmp = dma_rdreg(chan, S3C2410_DMA_DCON);
|
||||
tmp |= S3C2410_DCON_NORELOAD;
|
||||
dma_wrreg(chan, S3C2410_DMA_DCON, tmp);
|
||||
}
|
||||
#endif
|
||||
|
||||
dbg_showregs(chan);
|
||||
|
||||
local_irq_restore(flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
s3c2410_dma_started(s3c2410_dma_chan_t *chan)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
dbg_showchan(chan);
|
||||
|
||||
/* if we've only loaded one buffer onto the channel, then chec
|
||||
* to see if we have another, and if so, try and load it so when
|
||||
* the first buffer is finished, the new one will be loaded onto
|
||||
* the channel */
|
||||
|
||||
if (chan->next != NULL) {
|
||||
if (chan->load_state == S3C2410_DMALOAD_1LOADED) {
|
||||
|
||||
if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
|
||||
pr_debug("%s: buff not yet loaded, no more todo\n",
|
||||
__FUNCTION__);
|
||||
} else {
|
||||
chan->load_state = S3C2410_DMALOAD_1RUNNING;
|
||||
s3c2410_dma_loadbuffer(chan, chan->next);
|
||||
}
|
||||
|
||||
} else if (chan->load_state == S3C2410_DMALOAD_1RUNNING) {
|
||||
s3c2410_dma_loadbuffer(chan, chan->next);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
local_irq_restore(flags);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
s3c2410_dma_ctrl(dmach_t channel, s3c2410_chan_op_t op)
|
||||
|
@ -885,14 +1009,15 @@ s3c2410_dma_ctrl(dmach_t channel, s3c2410_chan_op_t op)
|
|||
return s3c2410_dma_dostop(chan);
|
||||
|
||||
case S3C2410_DMAOP_PAUSE:
|
||||
return -ENOENT;
|
||||
|
||||
case S3C2410_DMAOP_RESUME:
|
||||
return -ENOENT;
|
||||
|
||||
case S3C2410_DMAOP_FLUSH:
|
||||
return s3c2410_dma_flush(chan);
|
||||
|
||||
case S3C2410_DMAOP_STARTED:
|
||||
return s3c2410_dma_started(chan);
|
||||
|
||||
case S3C2410_DMAOP_TIMEOUT:
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#include <asm/hardware.h>
|
||||
#include <asm/hardware/ssp.h>
|
||||
|
||||
#define TIMEOUT 100000
|
||||
|
||||
static irqreturn_t ssp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
unsigned int status = Ser4SSSR;
|
||||
|
@ -47,18 +49,27 @@ static irqreturn_t ssp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
|||
* The caller is expected to perform the necessary locking.
|
||||
*
|
||||
* Returns:
|
||||
* %-ETIMEDOUT timeout occurred (for future)
|
||||
* %-ETIMEDOUT timeout occurred
|
||||
* 0 success
|
||||
*/
|
||||
int ssp_write_word(u16 data)
|
||||
{
|
||||
while (!(Ser4SSSR & SSSR_TNF))
|
||||
int timeout = TIMEOUT;
|
||||
|
||||
while (!(Ser4SSSR & SSSR_TNF)) {
|
||||
if (!--timeout)
|
||||
return -ETIMEDOUT;
|
||||
cpu_relax();
|
||||
}
|
||||
|
||||
Ser4SSDR = data;
|
||||
|
||||
while (!(Ser4SSSR & SSSR_BSY))
|
||||
timeout = TIMEOUT;
|
||||
while (!(Ser4SSSR & SSSR_BSY)) {
|
||||
if (!--timeout)
|
||||
return -ETIMEDOUT;
|
||||
cpu_relax();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -75,15 +86,22 @@ int ssp_write_word(u16 data)
|
|||
* The caller is expected to perform the necessary locking.
|
||||
*
|
||||
* Returns:
|
||||
* %-ETIMEDOUT timeout occurred (for future)
|
||||
* %-ETIMEDOUT timeout occurred
|
||||
* 16-bit data success
|
||||
*/
|
||||
int ssp_read_word(void)
|
||||
int ssp_read_word(u16 *data)
|
||||
{
|
||||
while (!(Ser4SSSR & SSSR_RNE))
|
||||
cpu_relax();
|
||||
int timeout = TIMEOUT;
|
||||
|
||||
return Ser4SSDR;
|
||||
while (!(Ser4SSSR & SSSR_RNE)) {
|
||||
if (!--timeout)
|
||||
return -ETIMEDOUT;
|
||||
cpu_relax();
|
||||
}
|
||||
|
||||
*data = (u16)Ser4SSDR;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -93,14 +111,26 @@ int ssp_read_word(void)
|
|||
* is empty.
|
||||
*
|
||||
* The caller is expected to perform the necessary locking.
|
||||
*
|
||||
* Returns:
|
||||
* %-ETIMEDOUT timeout occurred
|
||||
* 0 success
|
||||
*/
|
||||
void ssp_flush(void)
|
||||
int ssp_flush(void)
|
||||
{
|
||||
int timeout = TIMEOUT * 2;
|
||||
|
||||
do {
|
||||
while (Ser4SSSR & SSSR_RNE) {
|
||||
if (!--timeout)
|
||||
return -ETIMEDOUT;
|
||||
(void) Ser4SSDR;
|
||||
}
|
||||
if (!--timeout)
|
||||
return -ETIMEDOUT;
|
||||
} while (Ser4SSSR & SSSR_BSY);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -285,7 +285,7 @@ static struct flash_platform_data versatile_flash_data = {
|
|||
|
||||
static struct resource versatile_flash_resource = {
|
||||
.start = VERSATILE_FLASH_BASE,
|
||||
.end = VERSATILE_FLASH_BASE + VERSATILE_FLASH_SIZE,
|
||||
.end = VERSATILE_FLASH_BASE + VERSATILE_FLASH_SIZE - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
};
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ config CPU_ARM710
|
|||
config CPU_ARM720T
|
||||
bool "Support ARM720T processor" if !ARCH_CLPS711X && !ARCH_L7200 && !ARCH_CDB89712 && ARCH_INTEGRATOR
|
||||
default y if ARCH_CLPS711X || ARCH_L7200 || ARCH_CDB89712 || ARCH_H720X
|
||||
select CPU_32v4
|
||||
select CPU_32v4T
|
||||
select CPU_ABRT_LV4T
|
||||
select CPU_CACHE_V4
|
||||
select CPU_CACHE_VIVT
|
||||
|
@ -64,7 +64,7 @@ config CPU_ARM920T
|
|||
bool "Support ARM920T processor"
|
||||
depends on ARCH_EP93XX || ARCH_INTEGRATOR || CPU_S3C2410 || CPU_S3C2440 || CPU_S3C2442 || ARCH_IMX || ARCH_AAEC2000 || ARCH_AT91RM9200
|
||||
default y if CPU_S3C2410 || CPU_S3C2440 || CPU_S3C2442 || ARCH_AT91RM9200
|
||||
select CPU_32v4
|
||||
select CPU_32v4T
|
||||
select CPU_ABRT_EV4T
|
||||
select CPU_CACHE_V4WT
|
||||
select CPU_CACHE_VIVT
|
||||
|
@ -85,7 +85,7 @@ config CPU_ARM922T
|
|||
bool "Support ARM922T processor" if ARCH_INTEGRATOR
|
||||
depends on ARCH_LH7A40X || ARCH_INTEGRATOR
|
||||
default y if ARCH_LH7A40X
|
||||
select CPU_32v4
|
||||
select CPU_32v4T
|
||||
select CPU_ABRT_EV4T
|
||||
select CPU_CACHE_V4WT
|
||||
select CPU_CACHE_VIVT
|
||||
|
@ -104,7 +104,7 @@ config CPU_ARM925T
|
|||
bool "Support ARM925T processor" if ARCH_OMAP1
|
||||
depends on ARCH_OMAP15XX
|
||||
default y if ARCH_OMAP15XX
|
||||
select CPU_32v4
|
||||
select CPU_32v4T
|
||||
select CPU_ABRT_EV4T
|
||||
select CPU_CACHE_V4WT
|
||||
select CPU_CACHE_VIVT
|
||||
|
@ -285,6 +285,11 @@ config CPU_32v4
|
|||
select TLS_REG_EMUL if SMP || !MMU
|
||||
select NEEDS_SYSCALL_FOR_CMPXCHG if SMP
|
||||
|
||||
config CPU_32v4T
|
||||
bool
|
||||
select TLS_REG_EMUL if SMP || !MMU
|
||||
select NEEDS_SYSCALL_FOR_CMPXCHG if SMP
|
||||
|
||||
config CPU_32v5
|
||||
bool
|
||||
select TLS_REG_EMUL if SMP || !MMU
|
||||
|
|
|
@ -353,3 +353,11 @@ u32 vfp_estimate_sqrt_significand(u32 exponent, u32 significand);
|
|||
* A special flag to tell the normalisation code not to normalise.
|
||||
*/
|
||||
#define VFP_NAN_FLAG 0x100
|
||||
|
||||
/*
|
||||
* A bit pattern used to indicate the initial (unset) value of the
|
||||
* exception mask, in case nothing handles an instruction. This
|
||||
* doesn't include the NAN flag, which get masked out before
|
||||
* we check for an error.
|
||||
*/
|
||||
#define VFP_EXCEPTION_ERROR ((u32)-1 & ~VFP_NAN_FLAG)
|
||||
|
|
|
@ -465,7 +465,7 @@ static u32 vfp_double_fcvts(int sd, int unused, int dm, u32 fpscr)
|
|||
*/
|
||||
if (tm & (VFP_INFINITY|VFP_NAN)) {
|
||||
vsd.exponent = 255;
|
||||
if (tm & VFP_NAN)
|
||||
if (tm == VFP_QNAN)
|
||||
vsd.significand |= VFP_SINGLE_SIGNIFICAND_QNAN;
|
||||
goto pack_nan;
|
||||
} else if (tm & VFP_ZERO)
|
||||
|
@ -1127,7 +1127,7 @@ u32 vfp_double_cpdo(u32 inst, u32 fpscr)
|
|||
{
|
||||
u32 op = inst & FOP_MASK;
|
||||
u32 exceptions = 0;
|
||||
unsigned int dd = vfp_get_dd(inst);
|
||||
unsigned int dest;
|
||||
unsigned int dn = vfp_get_dn(inst);
|
||||
unsigned int dm = vfp_get_dm(inst);
|
||||
unsigned int vecitr, veclen, vecstride;
|
||||
|
@ -1136,11 +1136,21 @@ u32 vfp_double_cpdo(u32 inst, u32 fpscr)
|
|||
veclen = fpscr & FPSCR_LENGTH_MASK;
|
||||
vecstride = (1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK)) * 2;
|
||||
|
||||
/*
|
||||
* fcvtds takes an sN register number as destination, not dN.
|
||||
* It also always operates on scalars.
|
||||
*/
|
||||
if ((inst & FEXT_MASK) == FEXT_FCVT) {
|
||||
veclen = 0;
|
||||
dest = vfp_get_sd(inst);
|
||||
} else
|
||||
dest = vfp_get_dd(inst);
|
||||
|
||||
/*
|
||||
* If destination bank is zero, vector length is always '1'.
|
||||
* ARM DDI0100F C5.1.3, C5.3.2.
|
||||
*/
|
||||
if (FREG_BANK(dd) == 0)
|
||||
if (FREG_BANK(dest) == 0)
|
||||
veclen = 0;
|
||||
|
||||
pr_debug("VFP: vecstride=%u veclen=%u\n", vecstride,
|
||||
|
@ -1153,16 +1163,20 @@ u32 vfp_double_cpdo(u32 inst, u32 fpscr)
|
|||
for (vecitr = 0; vecitr <= veclen; vecitr += 1 << FPSCR_LENGTH_BIT) {
|
||||
u32 except;
|
||||
|
||||
if (op == FOP_EXT)
|
||||
if (op == FOP_EXT && (inst & FEXT_MASK) == FEXT_FCVT)
|
||||
pr_debug("VFP: itr%d (s%u) = op[%u] (d%u)\n",
|
||||
vecitr >> FPSCR_LENGTH_BIT,
|
||||
dest, dn, dm);
|
||||
else if (op == FOP_EXT)
|
||||
pr_debug("VFP: itr%d (d%u) = op[%u] (d%u)\n",
|
||||
vecitr >> FPSCR_LENGTH_BIT,
|
||||
dd, dn, dm);
|
||||
dest, dn, dm);
|
||||
else
|
||||
pr_debug("VFP: itr%d (d%u) = (d%u) op[%u] (d%u)\n",
|
||||
vecitr >> FPSCR_LENGTH_BIT,
|
||||
dd, dn, FOP_TO_IDX(op), dm);
|
||||
dest, dn, FOP_TO_IDX(op), dm);
|
||||
|
||||
except = fop(dd, dn, dm, fpscr);
|
||||
except = fop(dest, dn, dm, fpscr);
|
||||
pr_debug("VFP: itr%d: exceptions=%08x\n",
|
||||
vecitr >> FPSCR_LENGTH_BIT, except);
|
||||
|
||||
|
@ -1180,7 +1194,7 @@ u32 vfp_double_cpdo(u32 inst, u32 fpscr)
|
|||
* we encounter an exception. We continue.
|
||||
*/
|
||||
|
||||
dd = FREG_BANK(dd) + ((FREG_IDX(dd) + vecstride) & 6);
|
||||
dest = FREG_BANK(dest) + ((FREG_IDX(dest) + vecstride) & 6);
|
||||
dn = FREG_BANK(dn) + ((FREG_IDX(dn) + vecstride) & 6);
|
||||
if (FREG_BANK(dm) != 0)
|
||||
dm = FREG_BANK(dm) + ((FREG_IDX(dm) + vecstride) & 6);
|
||||
|
|
|
@ -131,7 +131,7 @@ static void vfp_raise_exceptions(u32 exceptions, u32 inst, u32 fpscr, struct pt_
|
|||
|
||||
pr_debug("VFP: raising exceptions %08x\n", exceptions);
|
||||
|
||||
if (exceptions == (u32)-1) {
|
||||
if (exceptions == VFP_EXCEPTION_ERROR) {
|
||||
vfp_panic("unhandled bounce");
|
||||
vfp_raise_sigfpe(0, regs);
|
||||
return;
|
||||
|
@ -170,7 +170,7 @@ static void vfp_raise_exceptions(u32 exceptions, u32 inst, u32 fpscr, struct pt_
|
|||
*/
|
||||
static u32 vfp_emulate_instruction(u32 inst, u32 fpscr, struct pt_regs *regs)
|
||||
{
|
||||
u32 exceptions = (u32)-1;
|
||||
u32 exceptions = VFP_EXCEPTION_ERROR;
|
||||
|
||||
pr_debug("VFP: emulate: INST=0x%08x SCR=0x%08x\n", inst, fpscr);
|
||||
|
||||
|
|
|
@ -506,7 +506,7 @@ static u32 vfp_single_fcvtd(int dd, int unused, s32 m, u32 fpscr)
|
|||
*/
|
||||
if (tm & (VFP_INFINITY|VFP_NAN)) {
|
||||
vdd.exponent = 2047;
|
||||
if (tm & VFP_NAN)
|
||||
if (tm == VFP_QNAN)
|
||||
vdd.significand |= VFP_DOUBLE_SIGNIFICAND_QNAN;
|
||||
goto pack_nan;
|
||||
} else if (tm & VFP_ZERO)
|
||||
|
@ -514,10 +514,6 @@ static u32 vfp_single_fcvtd(int dd, int unused, s32 m, u32 fpscr)
|
|||
else
|
||||
vdd.exponent = vsm.exponent + (1023 - 127);
|
||||
|
||||
/*
|
||||
* Technically, if bit 0 of dd is set, this is an invalid
|
||||
* instruction. However, we ignore this for efficiency.
|
||||
*/
|
||||
return vfp_double_normaliseround(dd, &vdd, fpscr, exceptions, "fcvtd");
|
||||
|
||||
pack_nan:
|
||||
|
@ -1174,7 +1170,7 @@ u32 vfp_single_cpdo(u32 inst, u32 fpscr)
|
|||
{
|
||||
u32 op = inst & FOP_MASK;
|
||||
u32 exceptions = 0;
|
||||
unsigned int sd = vfp_get_sd(inst);
|
||||
unsigned int dest;
|
||||
unsigned int sn = vfp_get_sn(inst);
|
||||
unsigned int sm = vfp_get_sm(inst);
|
||||
unsigned int vecitr, veclen, vecstride;
|
||||
|
@ -1183,11 +1179,23 @@ u32 vfp_single_cpdo(u32 inst, u32 fpscr)
|
|||
veclen = fpscr & FPSCR_LENGTH_MASK;
|
||||
vecstride = 1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK);
|
||||
|
||||
/*
|
||||
* fcvtsd takes a dN register number as destination, not sN.
|
||||
* Technically, if bit 0 of dd is set, this is an invalid
|
||||
* instruction. However, we ignore this for efficiency.
|
||||
* It also only operates on scalars.
|
||||
*/
|
||||
if ((inst & FEXT_MASK) == FEXT_FCVT) {
|
||||
veclen = 0;
|
||||
dest = vfp_get_dd(inst);
|
||||
} else
|
||||
dest = vfp_get_sd(inst);
|
||||
|
||||
/*
|
||||
* If destination bank is zero, vector length is always '1'.
|
||||
* ARM DDI0100F C5.1.3, C5.3.2.
|
||||
*/
|
||||
if (FREG_BANK(sd) == 0)
|
||||
if (FREG_BANK(dest) == 0)
|
||||
veclen = 0;
|
||||
|
||||
pr_debug("VFP: vecstride=%u veclen=%u\n", vecstride,
|
||||
|
@ -1201,15 +1209,18 @@ u32 vfp_single_cpdo(u32 inst, u32 fpscr)
|
|||
s32 m = vfp_get_float(sm);
|
||||
u32 except;
|
||||
|
||||
if (op == FOP_EXT)
|
||||
if (op == FOP_EXT && (inst & FEXT_MASK) == FEXT_FCVT)
|
||||
pr_debug("VFP: itr%d (d%u) = op[%u] (s%u=%08x)\n",
|
||||
vecitr >> FPSCR_LENGTH_BIT, dest, sn, sm, m);
|
||||
else if (op == FOP_EXT)
|
||||
pr_debug("VFP: itr%d (s%u) = op[%u] (s%u=%08x)\n",
|
||||
vecitr >> FPSCR_LENGTH_BIT, sd, sn, sm, m);
|
||||
vecitr >> FPSCR_LENGTH_BIT, dest, sn, sm, m);
|
||||
else
|
||||
pr_debug("VFP: itr%d (s%u) = (s%u) op[%u] (s%u=%08x)\n",
|
||||
vecitr >> FPSCR_LENGTH_BIT, sd, sn,
|
||||
vecitr >> FPSCR_LENGTH_BIT, dest, sn,
|
||||
FOP_TO_IDX(op), sm, m);
|
||||
|
||||
except = fop(sd, sn, m, fpscr);
|
||||
except = fop(dest, sn, m, fpscr);
|
||||
pr_debug("VFP: itr%d: exceptions=%08x\n",
|
||||
vecitr >> FPSCR_LENGTH_BIT, except);
|
||||
|
||||
|
@ -1227,7 +1238,7 @@ u32 vfp_single_cpdo(u32 inst, u32 fpscr)
|
|||
* we encounter an exception. We continue.
|
||||
*/
|
||||
|
||||
sd = FREG_BANK(sd) + ((FREG_IDX(sd) + vecstride) & 7);
|
||||
dest = FREG_BANK(dest) + ((FREG_IDX(dest) + vecstride) & 7);
|
||||
sn = FREG_BANK(sn) + ((FREG_IDX(sn) + vecstride) & 7);
|
||||
if (FREG_BANK(sm) != 0)
|
||||
sm = FREG_BANK(sm) + ((FREG_IDX(sm) + vecstride) & 7);
|
||||
|
|
|
@ -142,6 +142,7 @@ config X86_SUMMIT
|
|||
In particular, it is needed for the x440.
|
||||
|
||||
If you don't have one of these computers, you should say N here.
|
||||
If you want to build a NUMA kernel, you must select ACPI.
|
||||
|
||||
config X86_BIGSMP
|
||||
bool "Support for other sub-arch SMP systems with more than 8 CPUs"
|
||||
|
@ -169,6 +170,7 @@ config X86_GENERICARCH
|
|||
help
|
||||
This option compiles in the Summit, bigsmp, ES7000, default subarchitectures.
|
||||
It is intended for a generic binary kernel.
|
||||
If you want a NUMA kernel, select ACPI. We need SRAT for NUMA.
|
||||
|
||||
config X86_ES7000
|
||||
bool "Support for Unisys ES7000 IA32 series"
|
||||
|
@ -542,7 +544,7 @@ config X86_PAE
|
|||
# Common NUMA Features
|
||||
config NUMA
|
||||
bool "Numa Memory Allocation and Scheduler Support"
|
||||
depends on SMP && HIGHMEM64G && (X86_NUMAQ || X86_GENERICARCH || (X86_SUMMIT && ACPI))
|
||||
depends on SMP && HIGHMEM64G && (X86_NUMAQ || (X86_SUMMIT || X86_GENERICARCH) && ACPI)
|
||||
default n if X86_PC
|
||||
default y if (X86_NUMAQ || X86_SUMMIT)
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ static inline int gsi_irq_sharing(int gsi) { return gsi; }
|
|||
|
||||
#define BAD_MADT_ENTRY(entry, end) ( \
|
||||
(!entry) || (unsigned long)entry + sizeof(*entry) > end || \
|
||||
((acpi_table_entry_header *)entry)->length != sizeof(*entry))
|
||||
((acpi_table_entry_header *)entry)->length < sizeof(*entry))
|
||||
|
||||
#define PREFIX "ACPI: "
|
||||
|
||||
|
|
|
@ -292,7 +292,10 @@ ENTRY(do_suspend_lowlevel)
|
|||
pushl $3
|
||||
call acpi_enter_sleep_state
|
||||
addl $4, %esp
|
||||
ret
|
||||
|
||||
# In case of S3 failure, we'll emerge here. Jump
|
||||
# to ret_point to recover
|
||||
jmp ret_point
|
||||
.p2align 4,,7
|
||||
ret_point:
|
||||
call restore_registers
|
||||
|
|
|
@ -567,16 +567,11 @@ static struct cpufreq_driver acpi_cpufreq_driver = {
|
|||
static int __init
|
||||
acpi_cpufreq_init (void)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
dprintk("acpi_cpufreq_init\n");
|
||||
|
||||
result = acpi_cpufreq_early_init_acpi();
|
||||
acpi_cpufreq_early_init_acpi();
|
||||
|
||||
if (!result)
|
||||
result = cpufreq_register_driver(&acpi_cpufreq_driver);
|
||||
|
||||
return (result);
|
||||
return cpufreq_register_driver(&acpi_cpufreq_driver);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -317,20 +317,14 @@ is386: movl $2,%ecx # set MP
|
|||
movl %eax,%gs
|
||||
lldt %ax
|
||||
cld # gcc2 wants the direction flag cleared at all times
|
||||
pushl %eax # fake return address
|
||||
#ifdef CONFIG_SMP
|
||||
movb ready, %cl
|
||||
movb $1, ready
|
||||
cmpb $0,%cl
|
||||
je 1f # the first CPU calls start_kernel
|
||||
# all other CPUs call initialize_secondary
|
||||
call initialize_secondary
|
||||
jmp L6
|
||||
1:
|
||||
cmpb $0,%cl # the first CPU calls start_kernel
|
||||
jne initialize_secondary # all other CPUs call initialize_secondary
|
||||
#endif /* CONFIG_SMP */
|
||||
call start_kernel
|
||||
L6:
|
||||
jmp L6 # main should never return here, but
|
||||
# just in case, we know what happens.
|
||||
jmp start_kernel
|
||||
|
||||
/*
|
||||
* We depend on ET to be correct. This checks for 287/387.
|
||||
|
|
|
@ -82,10 +82,6 @@ fastcall unsigned int do_IRQ(struct pt_regs *regs)
|
|||
}
|
||||
#endif
|
||||
|
||||
if (!irq_desc[irq].handle_irq) {
|
||||
__do_IRQ(irq, regs);
|
||||
goto out_exit;
|
||||
}
|
||||
#ifdef CONFIG_4KSTACKS
|
||||
|
||||
curctx = (union irq_ctx *) current_thread_info();
|
||||
|
@ -125,7 +121,6 @@ fastcall unsigned int do_IRQ(struct pt_regs *regs)
|
|||
#endif
|
||||
__do_IRQ(irq, regs);
|
||||
|
||||
out_exit:
|
||||
irq_exit();
|
||||
|
||||
return 1;
|
||||
|
|
|
@ -956,38 +956,6 @@ efi_memory_present_wrapper(unsigned long start, unsigned long end, void *arg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function checks if the entire range <start,end> is mapped with type.
|
||||
*
|
||||
* Note: this function only works correct if the e820 table is sorted and
|
||||
* not-overlapping, which is the case
|
||||
*/
|
||||
int __init
|
||||
e820_all_mapped(unsigned long s, unsigned long e, unsigned type)
|
||||
{
|
||||
u64 start = s;
|
||||
u64 end = e;
|
||||
int i;
|
||||
for (i = 0; i < e820.nr_map; i++) {
|
||||
struct e820entry *ei = &e820.map[i];
|
||||
if (type && ei->type != type)
|
||||
continue;
|
||||
/* is the region (part) in overlap with the current region ?*/
|
||||
if (ei->addr >= end || ei->addr + ei->size <= start)
|
||||
continue;
|
||||
/* if the region is at the beginning of <start,end> we move
|
||||
* start to the end of the region since it's ok until there
|
||||
*/
|
||||
if (ei->addr <= start)
|
||||
start = ei->addr + ei->size;
|
||||
/* if start is now at or beyond end, we're done, full
|
||||
* coverage */
|
||||
if (start >= end)
|
||||
return 1; /* we're done */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the highest page frame number we have available
|
||||
*/
|
||||
|
|
|
@ -92,7 +92,11 @@ asmlinkage void spurious_interrupt_bug(void);
|
|||
asmlinkage void machine_check(void);
|
||||
|
||||
static int kstack_depth_to_print = 24;
|
||||
#ifdef CONFIG_STACK_UNWIND
|
||||
static int call_trace = 1;
|
||||
#else
|
||||
#define call_trace (-1)
|
||||
#endif
|
||||
ATOMIC_NOTIFIER_HEAD(i386die_chain);
|
||||
|
||||
int register_die_notifier(struct notifier_block *nb)
|
||||
|
@ -187,22 +191,21 @@ static void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
|
|||
if (unwind_init_blocked(&info, task) == 0)
|
||||
unw_ret = show_trace_unwind(&info, log_lvl);
|
||||
}
|
||||
if (unw_ret > 0 && !arch_unw_user_mode(&info)) {
|
||||
#ifdef CONFIG_STACK_UNWIND
|
||||
if (unw_ret > 0) {
|
||||
if (call_trace == 1 && !arch_unw_user_mode(&info)) {
|
||||
print_symbol("DWARF2 unwinder stuck at %s\n",
|
||||
UNW_PC(&info));
|
||||
if (call_trace == 1) {
|
||||
if (UNW_SP(&info) >= PAGE_OFFSET) {
|
||||
printk("Leftover inexact backtrace:\n");
|
||||
if (UNW_SP(&info))
|
||||
stack = (void *)UNW_SP(&info);
|
||||
} else if (call_trace > 1)
|
||||
} else
|
||||
printk("Full inexact backtrace again:\n");
|
||||
} else if (call_trace >= 1)
|
||||
return;
|
||||
else
|
||||
printk("Full inexact backtrace again:\n");
|
||||
#else
|
||||
} else
|
||||
printk("Inexact backtrace:\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (task == current) {
|
||||
|
@ -454,7 +457,7 @@ void die(const char * str, struct pt_regs * regs, long err)
|
|||
panic("Fatal exception in interrupt");
|
||||
|
||||
if (panic_on_oops)
|
||||
panic("Fatal exception: panic_on_oops");
|
||||
panic("Fatal exception");
|
||||
|
||||
oops_exit();
|
||||
do_exit(SIGSEGV);
|
||||
|
@ -1241,6 +1244,7 @@ static int __init kstack_setup(char *s)
|
|||
}
|
||||
__setup("kstack=", kstack_setup);
|
||||
|
||||
#ifdef CONFIG_STACK_UNWIND
|
||||
static int __init call_trace_setup(char *s)
|
||||
{
|
||||
if (strcmp(s, "old") == 0)
|
||||
|
@ -1254,3 +1258,4 @@ static int __init call_trace_setup(char *s)
|
|||
return 1;
|
||||
}
|
||||
__setup("call_trace=", call_trace_setup);
|
||||
#endif
|
||||
|
|
|
@ -237,6 +237,11 @@ char * __devinit pcibios_setup(char *str)
|
|||
pci_probe &= ~PCI_PROBE_MMCONF;
|
||||
return NULL;
|
||||
}
|
||||
/* override DMI blacklist */
|
||||
else if (!strcmp(str, "mmconf")) {
|
||||
pci_probe |= PCI_PROBE_MMCONF_FORCE;
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
else if (!strcmp(str, "noacpi")) {
|
||||
acpi_noirq_set();
|
||||
|
|
|
@ -14,8 +14,12 @@ static __init int pci_access_init(void)
|
|||
#ifdef CONFIG_PCI_BIOS
|
||||
pci_pcbios_init();
|
||||
#endif
|
||||
if (raw_pci_ops)
|
||||
return 0;
|
||||
/*
|
||||
* don't check for raw_pci_ops here because we want pcbios as last
|
||||
* fallback, yet it's needed to run first to set pcibios_last_bus
|
||||
* in case legacy PCI probing is used. otherwise detecting peer busses
|
||||
* fails.
|
||||
*/
|
||||
#ifdef CONFIG_PCI_DIRECT
|
||||
pci_direct_init();
|
||||
#endif
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <linux/pci.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <asm/e820.h>
|
||||
#include "pci.h"
|
||||
|
||||
|
@ -178,7 +179,7 @@ static __init void unreachable_devices(void)
|
|||
pci_exp_set_dev_base(addr, k, PCI_DEVFN(i, 0));
|
||||
if (addr == 0 ||
|
||||
readl((u32 __iomem *)mmcfg_virt_addr) != val1) {
|
||||
set_bit(i, fallback_slots);
|
||||
set_bit(i + 32*k, fallback_slots);
|
||||
printk(KERN_NOTICE
|
||||
"PCI: No mmconfig possible on %x:%x\n", k, i);
|
||||
}
|
||||
|
@ -187,9 +188,31 @@ static __init void unreachable_devices(void)
|
|||
}
|
||||
}
|
||||
|
||||
static int disable_mcfg(struct dmi_system_id *d)
|
||||
{
|
||||
printk("PCI: %s detected. Disabling MCFG.\n", d->ident);
|
||||
pci_probe &= ~PCI_PROBE_MMCONF;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dmi_system_id __initdata dmi_bad_mcfg[] = {
|
||||
/* Has broken MCFG table that makes the system hang when used */
|
||||
{
|
||||
.callback = disable_mcfg,
|
||||
.ident = "Intel D3C5105 SDV",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BIOS_VENDOR, "Intel"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "D26928"),
|
||||
},
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
void __init pci_mmcfg_init(void)
|
||||
{
|
||||
if ((pci_probe & PCI_PROBE_MMCONF) == 0)
|
||||
dmi_check_system(dmi_bad_mcfg);
|
||||
|
||||
if ((pci_probe & (PCI_PROBE_MMCONF_FORCE|PCI_PROBE_MMCONF)) == 0)
|
||||
return;
|
||||
|
||||
acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg);
|
||||
|
@ -198,15 +221,6 @@ void __init pci_mmcfg_init(void)
|
|||
(pci_mmcfg_config[0].base_address == 0))
|
||||
return;
|
||||
|
||||
if (!e820_all_mapped(pci_mmcfg_config[0].base_address,
|
||||
pci_mmcfg_config[0].base_address + MMCONFIG_APER_MIN,
|
||||
E820_RESERVED)) {
|
||||
printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %x is not E820-reserved\n",
|
||||
pci_mmcfg_config[0].base_address);
|
||||
printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "PCI: Using MMCONFIG\n");
|
||||
raw_pci_ops = &pci_mmcfg;
|
||||
pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
|
||||
|
|
|
@ -16,7 +16,8 @@
|
|||
#define PCI_PROBE_CONF1 0x0002
|
||||
#define PCI_PROBE_CONF2 0x0004
|
||||
#define PCI_PROBE_MMCONF 0x0008
|
||||
#define PCI_PROBE_MASK 0x000f
|
||||
#define PCI_PROBE_MMCONF_FORCE 0x0010
|
||||
#define PCI_PROBE_MASK 0x00ff
|
||||
|
||||
#define PCI_NO_SORT 0x0100
|
||||
#define PCI_BIOS_SORT 0x0200
|
||||
|
|
|
@ -258,7 +258,7 @@ config NR_CPUS
|
|||
int "Maximum number of CPUs (2-1024)"
|
||||
range 2 1024
|
||||
depends on SMP
|
||||
default "64"
|
||||
default "1024"
|
||||
help
|
||||
You should set this to the number of CPUs in your system, but
|
||||
keep in mind that a kernel compiled for, e.g., 2 CPUs will boot but
|
||||
|
@ -354,7 +354,7 @@ config NUMA
|
|||
config NODES_SHIFT
|
||||
int "Max num nodes shift(3-10)"
|
||||
range 3 10
|
||||
default "8"
|
||||
default "10"
|
||||
depends on NEED_MULTIPLE_NODES
|
||||
help
|
||||
This option specifies the maximum number of nodes in your SSI system.
|
||||
|
|
|
@ -244,7 +244,8 @@ static void simscsi_fillresult(struct scsi_cmnd *sc, char *buf, unsigned len)
|
|||
|
||||
if (scatterlen == 0)
|
||||
memcpy(sc->request_buffer, buf, len);
|
||||
else for (slp = (struct scatterlist *)sc->request_buffer; scatterlen-- > 0 && len > 0; slp++) {
|
||||
else for (slp = (struct scatterlist *)sc->request_buffer;
|
||||
scatterlen-- > 0 && len > 0; slp++) {
|
||||
unsigned thislen = min(len, slp->length);
|
||||
|
||||
memcpy(page_address(slp->page) + slp->offset, buf, thislen);
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
|
||||
#define BAD_MADT_ENTRY(entry, end) ( \
|
||||
(!entry) || (unsigned long)entry + sizeof(*entry) > end || \
|
||||
((acpi_table_entry_header *)entry)->length != sizeof(*entry))
|
||||
((acpi_table_entry_header *)entry)->length < sizeof(*entry))
|
||||
|
||||
#define PREFIX "ACPI: "
|
||||
|
||||
|
|
|
@ -67,10 +67,8 @@ static int __init topology_init(void)
|
|||
#endif
|
||||
|
||||
sysfs_cpus = kzalloc(sizeof(struct ia64_cpu) * NR_CPUS, GFP_KERNEL);
|
||||
if (!sysfs_cpus) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
if (!sysfs_cpus)
|
||||
panic("kzalloc in topology_init failed - NR_CPUS too big?");
|
||||
|
||||
for_each_present_cpu(i) {
|
||||
if((err = arch_register_cpu(i)))
|
||||
|
|
|
@ -118,7 +118,7 @@ die (const char *str, struct pt_regs *regs, long err)
|
|||
spin_unlock_irq(&die.lock);
|
||||
|
||||
if (panic_on_oops)
|
||||
panic("Fatal exception: panic_on_oops");
|
||||
panic("Fatal exception");
|
||||
|
||||
do_exit(SIGSEGV);
|
||||
}
|
||||
|
|
|
@ -279,8 +279,8 @@ xpc_pull_remote_cachelines(struct xpc_partition *part, void *dst,
|
|||
return part->reason;
|
||||
}
|
||||
|
||||
bte_ret = xp_bte_copy((u64) src, (u64) ia64_tpa((u64) dst),
|
||||
(u64) cnt, (BTE_NORMAL | BTE_WACQUIRE), NULL);
|
||||
bte_ret = xp_bte_copy((u64) src, (u64) dst, (u64) cnt,
|
||||
(BTE_NORMAL | BTE_WACQUIRE), NULL);
|
||||
if (bte_ret == BTE_SUCCESS) {
|
||||
return xpcSuccess;
|
||||
}
|
||||
|
|
|
@ -1052,6 +1052,8 @@ xpc_do_exit(enum xpc_retval reason)
|
|||
if (xpc_sysctl) {
|
||||
unregister_sysctl_table(xpc_sysctl);
|
||||
}
|
||||
|
||||
kfree(xpc_remote_copy_buffer_base);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1212,24 +1214,20 @@ xpc_init(void)
|
|||
partid_t partid;
|
||||
struct xpc_partition *part;
|
||||
pid_t pid;
|
||||
size_t buf_size;
|
||||
|
||||
|
||||
if (!ia64_platform_is("sn2")) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/*
|
||||
* xpc_remote_copy_buffer is used as a temporary buffer for bte_copy'ng
|
||||
* various portions of a partition's reserved page. Its size is based
|
||||
* on the size of the reserved page header and part_nasids mask. So we
|
||||
* need to ensure that the other items will fit as well.
|
||||
*/
|
||||
if (XPC_RP_VARS_SIZE > XPC_RP_HEADER_SIZE + XP_NASID_MASK_BYTES) {
|
||||
dev_err(xpc_part, "xpc_remote_copy_buffer is not big enough\n");
|
||||
return -EPERM;
|
||||
}
|
||||
DBUG_ON((u64) xpc_remote_copy_buffer !=
|
||||
L1_CACHE_ALIGN((u64) xpc_remote_copy_buffer));
|
||||
|
||||
buf_size = max(XPC_RP_VARS_SIZE,
|
||||
XPC_RP_HEADER_SIZE + XP_NASID_MASK_BYTES);
|
||||
xpc_remote_copy_buffer = xpc_kmalloc_cacheline_aligned(buf_size,
|
||||
GFP_KERNEL, &xpc_remote_copy_buffer_base);
|
||||
if (xpc_remote_copy_buffer == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
snprintf(xpc_part->bus_id, BUS_ID_SIZE, "part");
|
||||
snprintf(xpc_chan->bus_id, BUS_ID_SIZE, "chan");
|
||||
|
@ -1293,6 +1291,8 @@ xpc_init(void)
|
|||
if (xpc_sysctl) {
|
||||
unregister_sysctl_table(xpc_sysctl);
|
||||
}
|
||||
|
||||
kfree(xpc_remote_copy_buffer_base);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
|
@ -1311,6 +1311,8 @@ xpc_init(void)
|
|||
if (xpc_sysctl) {
|
||||
unregister_sysctl_table(xpc_sysctl);
|
||||
}
|
||||
|
||||
kfree(xpc_remote_copy_buffer_base);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
|
@ -1362,6 +1364,8 @@ xpc_init(void)
|
|||
if (xpc_sysctl) {
|
||||
unregister_sysctl_table(xpc_sysctl);
|
||||
}
|
||||
|
||||
kfree(xpc_remote_copy_buffer_base);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
|
|
|
@ -71,19 +71,15 @@ struct xpc_partition xpc_partitions[XP_MAX_PARTITIONS + 1];
|
|||
* Generic buffer used to store a local copy of portions of a remote
|
||||
* partition's reserved page (either its header and part_nasids mask,
|
||||
* or its vars).
|
||||
*
|
||||
* xpc_discovery runs only once and is a seperate thread that is
|
||||
* very likely going to be processing in parallel with receiving
|
||||
* interrupts.
|
||||
*/
|
||||
char ____cacheline_aligned xpc_remote_copy_buffer[XPC_RP_HEADER_SIZE +
|
||||
XP_NASID_MASK_BYTES];
|
||||
char *xpc_remote_copy_buffer;
|
||||
void *xpc_remote_copy_buffer_base;
|
||||
|
||||
|
||||
/*
|
||||
* Guarantee that the kmalloc'd memory is cacheline aligned.
|
||||
*/
|
||||
static void *
|
||||
void *
|
||||
xpc_kmalloc_cacheline_aligned(size_t size, gfp_t flags, void **base)
|
||||
{
|
||||
/* see if kmalloc will give us cachline aligned memory by default */
|
||||
|
@ -148,7 +144,7 @@ xpc_get_rsvd_page_pa(int nasid)
|
|||
}
|
||||
}
|
||||
|
||||
bte_res = xp_bte_copy(rp_pa, ia64_tpa(buf), buf_len,
|
||||
bte_res = xp_bte_copy(rp_pa, buf, buf_len,
|
||||
(BTE_NOTIFY | BTE_WACQUIRE), NULL);
|
||||
if (bte_res != BTE_SUCCESS) {
|
||||
dev_dbg(xpc_part, "xp_bte_copy failed %i\n", bte_res);
|
||||
|
@ -447,7 +443,7 @@ xpc_check_remote_hb(void)
|
|||
|
||||
/* pull the remote_hb cache line */
|
||||
bres = xp_bte_copy(part->remote_vars_pa,
|
||||
ia64_tpa((u64) remote_vars),
|
||||
(u64) remote_vars,
|
||||
XPC_RP_VARS_SIZE,
|
||||
(BTE_NOTIFY | BTE_WACQUIRE), NULL);
|
||||
if (bres != BTE_SUCCESS) {
|
||||
|
@ -498,8 +494,7 @@ xpc_get_remote_rp(int nasid, u64 *discovered_nasids,
|
|||
|
||||
|
||||
/* pull over the reserved page header and part_nasids mask */
|
||||
|
||||
bres = xp_bte_copy(*remote_rp_pa, ia64_tpa((u64) remote_rp),
|
||||
bres = xp_bte_copy(*remote_rp_pa, (u64) remote_rp,
|
||||
XPC_RP_HEADER_SIZE + xp_nasid_mask_bytes,
|
||||
(BTE_NOTIFY | BTE_WACQUIRE), NULL);
|
||||
if (bres != BTE_SUCCESS) {
|
||||
|
@ -554,11 +549,8 @@ xpc_get_remote_vars(u64 remote_vars_pa, struct xpc_vars *remote_vars)
|
|||
return xpcVarsNotSet;
|
||||
}
|
||||
|
||||
|
||||
/* pull over the cross partition variables */
|
||||
|
||||
bres = xp_bte_copy(remote_vars_pa, ia64_tpa((u64) remote_vars),
|
||||
XPC_RP_VARS_SIZE,
|
||||
bres = xp_bte_copy(remote_vars_pa, (u64) remote_vars, XPC_RP_VARS_SIZE,
|
||||
(BTE_NOTIFY | BTE_WACQUIRE), NULL);
|
||||
if (bres != BTE_SUCCESS) {
|
||||
return xpc_map_bte_errors(bres);
|
||||
|
@ -1239,7 +1231,7 @@ xpc_initiate_partid_to_nasids(partid_t partid, void *nasid_mask)
|
|||
|
||||
part_nasid_pa = (u64) XPC_RP_PART_NASIDS(part->remote_rp_pa);
|
||||
|
||||
bte_res = xp_bte_copy(part_nasid_pa, ia64_tpa((u64) nasid_mask),
|
||||
bte_res = xp_bte_copy(part_nasid_pa, (u64) nasid_mask,
|
||||
xp_nasid_mask_bytes, (BTE_NOTIFY | BTE_WACQUIRE), NULL);
|
||||
|
||||
return xpc_map_bte_errors(bte_res);
|
||||
|
|
|
@ -354,6 +354,7 @@ endchoice
|
|||
config PPC_PSERIES
|
||||
depends on PPC_MULTIPLATFORM && PPC64
|
||||
bool "IBM pSeries & new (POWER5-based) iSeries"
|
||||
select MPIC
|
||||
select PPC_I8259
|
||||
select PPC_RTAS
|
||||
select RTAS_ERROR_LOGGING
|
||||
|
@ -363,6 +364,7 @@ config PPC_PSERIES
|
|||
config PPC_CHRP
|
||||
bool "Common Hardware Reference Platform (CHRP) based machines"
|
||||
depends on PPC_MULTIPLATFORM && PPC32
|
||||
select MPIC
|
||||
select PPC_I8259
|
||||
select PPC_INDIRECT_PCI
|
||||
select PPC_RTAS
|
||||
|
@ -373,6 +375,7 @@ config PPC_CHRP
|
|||
config PPC_PMAC
|
||||
bool "Apple PowerMac based machines"
|
||||
depends on PPC_MULTIPLATFORM
|
||||
select MPIC
|
||||
select PPC_INDIRECT_PCI if PPC32
|
||||
select PPC_MPC106 if PPC32
|
||||
default y
|
||||
|
@ -380,6 +383,7 @@ config PPC_PMAC
|
|||
config PPC_PMAC64
|
||||
bool
|
||||
depends on PPC_PMAC && POWER4
|
||||
select MPIC
|
||||
select U3_DART
|
||||
select MPIC_BROKEN_U3
|
||||
select GENERIC_TBSYNC
|
||||
|
@ -389,6 +393,7 @@ config PPC_PMAC64
|
|||
config PPC_PREP
|
||||
bool "PowerPC Reference Platform (PReP) based machines"
|
||||
depends on PPC_MULTIPLATFORM && PPC32 && BROKEN
|
||||
select MPIC
|
||||
select PPC_I8259
|
||||
select PPC_INDIRECT_PCI
|
||||
select PPC_UDBG_16550
|
||||
|
@ -397,6 +402,7 @@ config PPC_PREP
|
|||
config PPC_MAPLE
|
||||
depends on PPC_MULTIPLATFORM && PPC64
|
||||
bool "Maple 970FX Evaluation Board"
|
||||
select MPIC
|
||||
select U3_DART
|
||||
select MPIC_BROKEN_U3
|
||||
select GENERIC_TBSYNC
|
||||
|
@ -440,12 +446,6 @@ config U3_DART
|
|||
depends on PPC_MULTIPLATFORM && PPC64
|
||||
default n
|
||||
|
||||
config MPIC
|
||||
depends on PPC_PSERIES || PPC_PMAC || PPC_MAPLE || PPC_CHRP \
|
||||
|| MPC7448HPC2
|
||||
bool
|
||||
default y
|
||||
|
||||
config PPC_RTAS
|
||||
bool
|
||||
default n
|
||||
|
@ -813,6 +813,14 @@ config GENERIC_ISA_DMA
|
|||
depends on PPC64 || POWER4 || 6xx && !CPM2
|
||||
default y
|
||||
|
||||
config MPIC
|
||||
bool
|
||||
default n
|
||||
|
||||
config MPIC_WEIRD
|
||||
bool
|
||||
default n
|
||||
|
||||
config PPC_I8259
|
||||
bool
|
||||
default n
|
||||
|
|
|
@ -0,0 +1,190 @@
|
|||
/*
|
||||
* MPC7448HPC2 (Taiga) board Device Tree Source
|
||||
*
|
||||
* Copyright 2006 Freescale Semiconductor Inc.
|
||||
* 2006 Roy Zang <Roy Zang at freescale.com>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
|
||||
/ {
|
||||
model = "mpc7448hpc2";
|
||||
compatible = "mpc74xx";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
linux,phandle = <100>;
|
||||
|
||||
cpus {
|
||||
#cpus = <1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells =<0>;
|
||||
linux,phandle = <200>;
|
||||
|
||||
PowerPC,7448@0 {
|
||||
device_type = "cpu";
|
||||
reg = <0>;
|
||||
d-cache-line-size = <20>; // 32 bytes
|
||||
i-cache-line-size = <20>; // 32 bytes
|
||||
d-cache-size = <8000>; // L1, 32K bytes
|
||||
i-cache-size = <8000>; // L1, 32K bytes
|
||||
timebase-frequency = <0>; // 33 MHz, from uboot
|
||||
clock-frequency = <0>; // From U-Boot
|
||||
bus-frequency = <0>; // From U-Boot
|
||||
32-bit;
|
||||
linux,phandle = <201>;
|
||||
linux,boot-cpu;
|
||||
};
|
||||
};
|
||||
|
||||
memory {
|
||||
device_type = "memory";
|
||||
linux,phandle = <300>;
|
||||
reg = <00000000 20000000 // DDR2 512M at 0
|
||||
>;
|
||||
};
|
||||
|
||||
tsi108@c0000000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
#interrupt-cells = <2>;
|
||||
device_type = "tsi-bridge";
|
||||
ranges = <00000000 c0000000 00010000>;
|
||||
reg = <c0000000 00010000>;
|
||||
bus-frequency = <0>;
|
||||
|
||||
i2c@7000 {
|
||||
interrupt-parent = <7400>;
|
||||
interrupts = <E 0>;
|
||||
reg = <7000 400>;
|
||||
device_type = "i2c";
|
||||
compatible = "tsi-i2c";
|
||||
};
|
||||
|
||||
mdio@6000 {
|
||||
device_type = "mdio";
|
||||
compatible = "tsi-ethernet";
|
||||
|
||||
ethernet-phy@6000 {
|
||||
linux,phandle = <6000>;
|
||||
interrupt-parent = <7400>;
|
||||
interrupts = <2 1>;
|
||||
reg = <6000 50>;
|
||||
phy-id = <8>;
|
||||
device_type = "ethernet-phy";
|
||||
};
|
||||
|
||||
ethernet-phy@6400 {
|
||||
linux,phandle = <6400>;
|
||||
interrupt-parent = <7400>;
|
||||
interrupts = <2 1>;
|
||||
reg = <6000 50>;
|
||||
phy-id = <9>;
|
||||
device_type = "ethernet-phy";
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
ethernet@6200 {
|
||||
#size-cells = <0>;
|
||||
device_type = "network";
|
||||
model = "TSI-ETH";
|
||||
compatible = "tsi-ethernet";
|
||||
reg = <6000 200>;
|
||||
address = [ 00 06 D2 00 00 01 ];
|
||||
interrupts = <10 2>;
|
||||
interrupt-parent = <7400>;
|
||||
phy-handle = <6000>;
|
||||
};
|
||||
|
||||
ethernet@6600 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
device_type = "network";
|
||||
model = "TSI-ETH";
|
||||
compatible = "tsi-ethernet";
|
||||
reg = <6400 200>;
|
||||
address = [ 00 06 D2 00 00 02 ];
|
||||
interrupts = <11 2>;
|
||||
interrupt-parent = <7400>;
|
||||
phy-handle = <6400>;
|
||||
};
|
||||
|
||||
serial@7808 {
|
||||
device_type = "serial";
|
||||
compatible = "ns16550";
|
||||
reg = <7808 200>;
|
||||
clock-frequency = <3f6b5a00>;
|
||||
interrupts = <c 0>;
|
||||
interrupt-parent = <7400>;
|
||||
};
|
||||
|
||||
serial@7c08 {
|
||||
device_type = "serial";
|
||||
compatible = "ns16550";
|
||||
reg = <7c08 200>;
|
||||
clock-frequency = <3f6b5a00>;
|
||||
interrupts = <d 0>;
|
||||
interrupt-parent = <7400>;
|
||||
};
|
||||
|
||||
pic@7400 {
|
||||
linux,phandle = <7400>;
|
||||
clock-frequency = <0>;
|
||||
interrupt-controller;
|
||||
#address-cells = <0>;
|
||||
#interrupt-cells = <2>;
|
||||
reg = <7400 400>;
|
||||
built-in;
|
||||
compatible = "chrp,open-pic";
|
||||
device_type = "open-pic";
|
||||
big-endian;
|
||||
};
|
||||
pci@1000 {
|
||||
compatible = "tsi10x";
|
||||
device_type = "pci";
|
||||
linux,phandle = <1000>;
|
||||
#interrupt-cells = <1>;
|
||||
#size-cells = <2>;
|
||||
#address-cells = <3>;
|
||||
reg = <1000 1000>;
|
||||
bus-range = <0 0>;
|
||||
ranges = <02000000 0 e0000000 e0000000 0 1A000000
|
||||
01000000 0 00000000 fa000000 0 00010000>;
|
||||
clock-frequency = <7f28154>;
|
||||
interrupt-parent = <7400>;
|
||||
interrupts = <17 2>;
|
||||
interrupt-map-mask = <f800 0 0 7>;
|
||||
interrupt-map = <
|
||||
|
||||
/* IDSEL 0x11 */
|
||||
0800 0 0 1 7400 24 0
|
||||
0800 0 0 2 7400 25 0
|
||||
0800 0 0 3 7400 26 0
|
||||
0800 0 0 4 7400 27 0
|
||||
|
||||
/* IDSEL 0x12 */
|
||||
1000 0 0 1 7400 25 0
|
||||
1000 0 0 2 7400 26 0
|
||||
1000 0 0 3 7400 27 0
|
||||
1000 0 0 4 7400 24 0
|
||||
|
||||
/* IDSEL 0x13 */
|
||||
1800 0 0 1 7400 26 0
|
||||
1800 0 0 2 7400 27 0
|
||||
1800 0 0 3 7400 24 0
|
||||
1800 0 0 4 7400 25 0
|
||||
|
||||
/* IDSEL 0x14 */
|
||||
2000 0 0 1 7400 27 0
|
||||
2000 0 0 2 7400 24 0
|
||||
2000 0 0 3 7400 25 0
|
||||
2000 0 0 4 7400 26 0
|
||||
>;
|
||||
};
|
||||
};
|
||||
|
||||
};
|
|
@ -0,0 +1,328 @@
|
|||
/*
|
||||
* MPC8349E MDS Device Tree Source
|
||||
*
|
||||
* Copyright 2005, 2006 Freescale Semiconductor Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/ {
|
||||
model = "MPC8349EMDS";
|
||||
compatible = "MPC834xMDS";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
cpus {
|
||||
#cpus = <1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
PowerPC,8349@0 {
|
||||
device_type = "cpu";
|
||||
reg = <0>;
|
||||
d-cache-line-size = <20>; // 32 bytes
|
||||
i-cache-line-size = <20>; // 32 bytes
|
||||
d-cache-size = <8000>; // L1, 32K
|
||||
i-cache-size = <8000>; // L1, 32K
|
||||
timebase-frequency = <0>; // from bootloader
|
||||
bus-frequency = <0>; // from bootloader
|
||||
clock-frequency = <0>; // from bootloader
|
||||
32-bit;
|
||||
};
|
||||
};
|
||||
|
||||
memory {
|
||||
device_type = "memory";
|
||||
reg = <00000000 10000000>; // 256MB at 0
|
||||
};
|
||||
|
||||
soc8349@e0000000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
#interrupt-cells = <2>;
|
||||
device_type = "soc";
|
||||
ranges = <0 e0000000 00100000>;
|
||||
reg = <e0000000 00000200>;
|
||||
bus-frequency = <0>;
|
||||
|
||||
wdt@200 {
|
||||
device_type = "watchdog";
|
||||
compatible = "mpc83xx_wdt";
|
||||
reg = <200 100>;
|
||||
};
|
||||
|
||||
i2c@3000 {
|
||||
device_type = "i2c";
|
||||
compatible = "fsl-i2c";
|
||||
reg = <3000 100>;
|
||||
interrupts = <e 8>;
|
||||
interrupt-parent = <700>;
|
||||
dfsrr;
|
||||
};
|
||||
|
||||
i2c@3100 {
|
||||
device_type = "i2c";
|
||||
compatible = "fsl-i2c";
|
||||
reg = <3100 100>;
|
||||
interrupts = <f 8>;
|
||||
interrupt-parent = <700>;
|
||||
dfsrr;
|
||||
};
|
||||
|
||||
spi@7000 {
|
||||
device_type = "spi";
|
||||
compatible = "mpc83xx_spi";
|
||||
reg = <7000 1000>;
|
||||
interrupts = <10 8>;
|
||||
interrupt-parent = <700>;
|
||||
mode = <0>;
|
||||
};
|
||||
|
||||
/* phy type (ULPI or SERIAL) are only types supportted for MPH */
|
||||
/* port = 0 or 1 */
|
||||
usb@22000 {
|
||||
device_type = "usb";
|
||||
compatible = "fsl-usb2-mph";
|
||||
reg = <22000 1000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
interrupt-parent = <700>;
|
||||
interrupts = <27 2>;
|
||||
phy_type = "ulpi";
|
||||
port1;
|
||||
};
|
||||
/* phy type (ULPI, UTMI, UTMI_WIDE, SERIAL) */
|
||||
usb@23000 {
|
||||
device_type = "usb";
|
||||
compatible = "fsl-usb2-dr";
|
||||
reg = <23000 1000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
interrupt-parent = <700>;
|
||||
interrupts = <26 2>;
|
||||
phy_type = "ulpi";
|
||||
};
|
||||
|
||||
mdio@24520 {
|
||||
device_type = "mdio";
|
||||
compatible = "gianfar";
|
||||
reg = <24520 20>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
linux,phandle = <24520>;
|
||||
ethernet-phy@0 {
|
||||
linux,phandle = <2452000>;
|
||||
interrupt-parent = <700>;
|
||||
interrupts = <11 2>;
|
||||
reg = <0>;
|
||||
device_type = "ethernet-phy";
|
||||
};
|
||||
ethernet-phy@1 {
|
||||
linux,phandle = <2452001>;
|
||||
interrupt-parent = <700>;
|
||||
interrupts = <12 2>;
|
||||
reg = <1>;
|
||||
device_type = "ethernet-phy";
|
||||
};
|
||||
};
|
||||
|
||||
ethernet@24000 {
|
||||
device_type = "network";
|
||||
model = "TSEC";
|
||||
compatible = "gianfar";
|
||||
reg = <24000 1000>;
|
||||
address = [ 00 00 00 00 00 00 ];
|
||||
local-mac-address = [ 00 00 00 00 00 00 ];
|
||||
interrupts = <20 8 21 8 22 8>;
|
||||
interrupt-parent = <700>;
|
||||
phy-handle = <2452000>;
|
||||
};
|
||||
|
||||
ethernet@25000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
device_type = "network";
|
||||
model = "TSEC";
|
||||
compatible = "gianfar";
|
||||
reg = <25000 1000>;
|
||||
address = [ 00 00 00 00 00 00 ];
|
||||
local-mac-address = [ 00 00 00 00 00 00 ];
|
||||
interrupts = <23 8 24 8 25 8>;
|
||||
interrupt-parent = <700>;
|
||||
phy-handle = <2452001>;
|
||||
};
|
||||
|
||||
serial@4500 {
|
||||
device_type = "serial";
|
||||
compatible = "ns16550";
|
||||
reg = <4500 100>;
|
||||
clock-frequency = <0>;
|
||||
interrupts = <9 8>;
|
||||
interrupt-parent = <700>;
|
||||
};
|
||||
|
||||
serial@4600 {
|
||||
device_type = "serial";
|
||||
compatible = "ns16550";
|
||||
reg = <4600 100>;
|
||||
clock-frequency = <0>;
|
||||
interrupts = <a 8>;
|
||||
interrupt-parent = <700>;
|
||||
};
|
||||
|
||||
pci@8500 {
|
||||
interrupt-map-mask = <f800 0 0 7>;
|
||||
interrupt-map = <
|
||||
|
||||
/* IDSEL 0x11 */
|
||||
8800 0 0 1 700 14 8
|
||||
8800 0 0 2 700 15 8
|
||||
8800 0 0 3 700 16 8
|
||||
8800 0 0 4 700 17 8
|
||||
|
||||
/* IDSEL 0x12 */
|
||||
9000 0 0 1 700 16 8
|
||||
9000 0 0 2 700 17 8
|
||||
9000 0 0 3 700 14 8
|
||||
9000 0 0 4 700 15 8
|
||||
|
||||
/* IDSEL 0x13 */
|
||||
9800 0 0 1 700 17 8
|
||||
9800 0 0 2 700 14 8
|
||||
9800 0 0 3 700 15 8
|
||||
9800 0 0 4 700 16 8
|
||||
|
||||
/* IDSEL 0x15 */
|
||||
a800 0 0 1 700 14 8
|
||||
a800 0 0 2 700 15 8
|
||||
a800 0 0 3 700 16 8
|
||||
a800 0 0 4 700 17 8
|
||||
|
||||
/* IDSEL 0x16 */
|
||||
b000 0 0 1 700 17 8
|
||||
b000 0 0 2 700 14 8
|
||||
b000 0 0 3 700 15 8
|
||||
b000 0 0 4 700 16 8
|
||||
|
||||
/* IDSEL 0x17 */
|
||||
b800 0 0 1 700 16 8
|
||||
b800 0 0 2 700 17 8
|
||||
b800 0 0 3 700 14 8
|
||||
b800 0 0 4 700 15 8
|
||||
|
||||
/* IDSEL 0x18 */
|
||||
b000 0 0 1 700 15 8
|
||||
b000 0 0 2 700 16 8
|
||||
b000 0 0 3 700 17 8
|
||||
b000 0 0 4 700 14 8>;
|
||||
interrupt-parent = <700>;
|
||||
interrupts = <42 8>;
|
||||
bus-range = <0 0>;
|
||||
ranges = <02000000 0 a0000000 a0000000 0 10000000
|
||||
42000000 0 80000000 80000000 0 10000000
|
||||
01000000 0 00000000 e2000000 0 00100000>;
|
||||
clock-frequency = <3f940aa>;
|
||||
#interrupt-cells = <1>;
|
||||
#size-cells = <2>;
|
||||
#address-cells = <3>;
|
||||
reg = <8500 100>;
|
||||
compatible = "83xx";
|
||||
device_type = "pci";
|
||||
};
|
||||
|
||||
pci@8600 {
|
||||
interrupt-map-mask = <f800 0 0 7>;
|
||||
interrupt-map = <
|
||||
|
||||
/* IDSEL 0x11 */
|
||||
8800 0 0 1 700 14 8
|
||||
8800 0 0 2 700 15 8
|
||||
8800 0 0 3 700 16 8
|
||||
8800 0 0 4 700 17 8
|
||||
|
||||
/* IDSEL 0x12 */
|
||||
9000 0 0 1 700 16 8
|
||||
9000 0 0 2 700 17 8
|
||||
9000 0 0 3 700 14 8
|
||||
9000 0 0 4 700 15 8
|
||||
|
||||
/* IDSEL 0x13 */
|
||||
9800 0 0 1 700 17 8
|
||||
9800 0 0 2 700 14 8
|
||||
9800 0 0 3 700 15 8
|
||||
9800 0 0 4 700 16 8
|
||||
|
||||
/* IDSEL 0x15 */
|
||||
a800 0 0 1 700 14 8
|
||||
a800 0 0 2 700 15 8
|
||||
a800 0 0 3 700 16 8
|
||||
a800 0 0 4 700 17 8
|
||||
|
||||
/* IDSEL 0x16 */
|
||||
b000 0 0 1 700 17 8
|
||||
b000 0 0 2 700 14 8
|
||||
b000 0 0 3 700 15 8
|
||||
b000 0 0 4 700 16 8
|
||||
|
||||
/* IDSEL 0x17 */
|
||||
b800 0 0 1 700 16 8
|
||||
b800 0 0 2 700 17 8
|
||||
b800 0 0 3 700 14 8
|
||||
b800 0 0 4 700 15 8
|
||||
|
||||
/* IDSEL 0x18 */
|
||||
b000 0 0 1 700 15 8
|
||||
b000 0 0 2 700 16 8
|
||||
b000 0 0 3 700 17 8
|
||||
b000 0 0 4 700 14 8>;
|
||||
interrupt-parent = <700>;
|
||||
interrupts = <42 8>;
|
||||
bus-range = <0 0>;
|
||||
ranges = <02000000 0 b0000000 b0000000 0 10000000
|
||||
42000000 0 90000000 90000000 0 10000000
|
||||
01000000 0 00000000 e2100000 0 00100000>;
|
||||
clock-frequency = <3f940aa>;
|
||||
#interrupt-cells = <1>;
|
||||
#size-cells = <2>;
|
||||
#address-cells = <3>;
|
||||
reg = <8600 100>;
|
||||
compatible = "83xx";
|
||||
device_type = "pci";
|
||||
};
|
||||
|
||||
/* May need to remove if on a part without crypto engine */
|
||||
crypto@30000 {
|
||||
device_type = "crypto";
|
||||
model = "SEC2";
|
||||
compatible = "talitos";
|
||||
reg = <30000 10000>;
|
||||
interrupts = <b 8>;
|
||||
interrupt-parent = <700>;
|
||||
num-channels = <4>;
|
||||
channel-fifo-len = <18>;
|
||||
exec-units-mask = <0000007e>;
|
||||
/* desc mask is for rev2.0,
|
||||
* we need runtime fixup for >2.0 */
|
||||
descriptor-types-mask = <01010ebf>;
|
||||
};
|
||||
|
||||
/* IPIC
|
||||
* interrupts cell = <intr #, sense>
|
||||
* sense values match linux IORESOURCE_IRQ_* defines:
|
||||
* sense == 8: Level, low assertion
|
||||
* sense == 2: Edge, high-to-low change
|
||||
*/
|
||||
pic@700 {
|
||||
linux,phandle = <700>;
|
||||
interrupt-controller;
|
||||
#address-cells = <0>;
|
||||
#interrupt-cells = <2>;
|
||||
reg = <700 100>;
|
||||
built-in;
|
||||
device_type = "ipic";
|
||||
};
|
||||
};
|
||||
};
|
|
@ -2,6 +2,11 @@
|
|||
* FPU support code, moved here from head.S so that it can be used
|
||||
* by chips which use other head-whatever.S files.
|
||||
*
|
||||
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
|
||||
* Copyright (C) 1996 Cort Dougan <cort@cs.nmt.edu>
|
||||
* Copyright (C) 1996 Paul Mackerras.
|
||||
* Copyright (C) 1997 Dan Malek (dmalek@jlc.net).
|
||||
*
|
||||
* 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
|
||||
|
|
|
@ -323,7 +323,8 @@ EXPORT_SYMBOL(do_softirq);
|
|||
|
||||
static LIST_HEAD(irq_hosts);
|
||||
static spinlock_t irq_big_lock = SPIN_LOCK_UNLOCKED;
|
||||
|
||||
static DEFINE_PER_CPU(unsigned int, irq_radix_reader);
|
||||
static unsigned int irq_radix_writer;
|
||||
struct irq_map_entry irq_map[NR_IRQS];
|
||||
static unsigned int irq_virq_count = NR_IRQS;
|
||||
static struct irq_host *irq_default_host;
|
||||
|
@ -456,6 +457,58 @@ void irq_set_virq_count(unsigned int count)
|
|||
irq_virq_count = count;
|
||||
}
|
||||
|
||||
/* radix tree not lockless safe ! we use a brlock-type mecanism
|
||||
* for now, until we can use a lockless radix tree
|
||||
*/
|
||||
static void irq_radix_wrlock(unsigned long *flags)
|
||||
{
|
||||
unsigned int cpu, ok;
|
||||
|
||||
spin_lock_irqsave(&irq_big_lock, *flags);
|
||||
irq_radix_writer = 1;
|
||||
smp_mb();
|
||||
do {
|
||||
barrier();
|
||||
ok = 1;
|
||||
for_each_possible_cpu(cpu) {
|
||||
if (per_cpu(irq_radix_reader, cpu)) {
|
||||
ok = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!ok)
|
||||
cpu_relax();
|
||||
} while(!ok);
|
||||
}
|
||||
|
||||
static void irq_radix_wrunlock(unsigned long flags)
|
||||
{
|
||||
smp_wmb();
|
||||
irq_radix_writer = 0;
|
||||
spin_unlock_irqrestore(&irq_big_lock, flags);
|
||||
}
|
||||
|
||||
static void irq_radix_rdlock(unsigned long *flags)
|
||||
{
|
||||
local_irq_save(*flags);
|
||||
__get_cpu_var(irq_radix_reader) = 1;
|
||||
smp_mb();
|
||||
if (likely(irq_radix_writer == 0))
|
||||
return;
|
||||
__get_cpu_var(irq_radix_reader) = 0;
|
||||
smp_wmb();
|
||||
spin_lock(&irq_big_lock);
|
||||
__get_cpu_var(irq_radix_reader) = 1;
|
||||
spin_unlock(&irq_big_lock);
|
||||
}
|
||||
|
||||
static void irq_radix_rdunlock(unsigned long flags)
|
||||
{
|
||||
__get_cpu_var(irq_radix_reader) = 0;
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
|
||||
unsigned int irq_create_mapping(struct irq_host *host,
|
||||
irq_hw_number_t hwirq)
|
||||
{
|
||||
|
@ -605,13 +658,9 @@ void irq_dispose_mapping(unsigned int virq)
|
|||
/* Check if radix tree allocated yet */
|
||||
if (host->revmap_data.tree.gfp_mask == 0)
|
||||
break;
|
||||
/* XXX radix tree not safe ! remove lock whem it becomes safe
|
||||
* and use some RCU sync to make sure everything is ok before we
|
||||
* can re-use that map entry
|
||||
*/
|
||||
spin_lock_irqsave(&irq_big_lock, flags);
|
||||
irq_radix_wrlock(&flags);
|
||||
radix_tree_delete(&host->revmap_data.tree, hwirq);
|
||||
spin_unlock_irqrestore(&irq_big_lock, flags);
|
||||
irq_radix_wrunlock(flags);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -678,25 +727,24 @@ unsigned int irq_radix_revmap(struct irq_host *host,
|
|||
if (tree->gfp_mask == 0)
|
||||
return irq_find_mapping(host, hwirq);
|
||||
|
||||
/* XXX Current radix trees are NOT SMP safe !!! Remove that lock
|
||||
* when that is fixed (when Nick's patch gets in
|
||||
*/
|
||||
spin_lock_irqsave(&irq_big_lock, flags);
|
||||
|
||||
/* Now try to resolve */
|
||||
irq_radix_rdlock(&flags);
|
||||
ptr = radix_tree_lookup(tree, hwirq);
|
||||
irq_radix_rdunlock(flags);
|
||||
|
||||
/* Found it, return */
|
||||
if (ptr) {
|
||||
virq = ptr - irq_map;
|
||||
goto bail;
|
||||
return virq;
|
||||
}
|
||||
|
||||
/* If not there, try to insert it */
|
||||
virq = irq_find_mapping(host, hwirq);
|
||||
if (virq != NO_IRQ)
|
||||
if (virq != NO_IRQ) {
|
||||
irq_radix_wrlock(&flags);
|
||||
radix_tree_insert(tree, hwirq, &irq_map[virq]);
|
||||
bail:
|
||||
spin_unlock_irqrestore(&irq_big_lock, flags);
|
||||
irq_radix_wrunlock(flags);
|
||||
}
|
||||
return virq;
|
||||
}
|
||||
|
||||
|
@ -807,12 +855,12 @@ static int irq_late_init(void)
|
|||
struct irq_host *h;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&irq_big_lock, flags);
|
||||
irq_radix_wrlock(&flags);
|
||||
list_for_each_entry(h, &irq_hosts, link) {
|
||||
if (h->revmap_type == IRQ_HOST_MAP_TREE)
|
||||
INIT_RADIX_TREE(&h->revmap_data.tree, GFP_ATOMIC);
|
||||
}
|
||||
spin_unlock_irqrestore(&irq_big_lock, flags);
|
||||
irq_radix_wrunlock(flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1254,6 +1254,9 @@ int pci_read_irq_line(struct pci_dev *pci_dev)
|
|||
|
||||
DBG("Try to map irq for %s...\n", pci_name(pci_dev));
|
||||
|
||||
#ifdef DEBUG
|
||||
memset(&oirq, 0xff, sizeof(oirq));
|
||||
#endif
|
||||
/* Try to get a mapping from the device-tree */
|
||||
if (of_irq_map_pci(pci_dev, &oirq)) {
|
||||
u8 line, pin;
|
||||
|
@ -1279,8 +1282,9 @@ int pci_read_irq_line(struct pci_dev *pci_dev)
|
|||
if (virq != NO_IRQ)
|
||||
set_irq_type(virq, IRQ_TYPE_LEVEL_LOW);
|
||||
} else {
|
||||
DBG(" -> got one, spec %d cells (0x%08x...) on %s\n",
|
||||
oirq.size, oirq.specifier[0], oirq.controller->full_name);
|
||||
DBG(" -> got one, spec %d cells (0x%08x 0x%08x...) on %s\n",
|
||||
oirq.size, oirq.specifier[0], oirq.specifier[1],
|
||||
oirq.controller->full_name);
|
||||
|
||||
virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
|
||||
oirq.size);
|
||||
|
@ -1289,6 +1293,9 @@ int pci_read_irq_line(struct pci_dev *pci_dev)
|
|||
DBG(" -> failed to map !\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
DBG(" -> mapped to linux irq %d\n", virq);
|
||||
|
||||
pci_dev->irq = virq;
|
||||
pci_write_config_byte(pci_dev, PCI_INTERRUPT_LINE, virq);
|
||||
|
||||
|
|
|
@ -646,13 +646,13 @@ static unsigned char ibm_architecture_vec[] = {
|
|||
5 - 1, /* 5 option vectors */
|
||||
|
||||
/* option vector 1: processor architectures supported */
|
||||
3 - 1, /* length */
|
||||
3 - 2, /* length */
|
||||
0, /* don't ignore, don't halt */
|
||||
OV1_PPC_2_00 | OV1_PPC_2_01 | OV1_PPC_2_02 | OV1_PPC_2_03 |
|
||||
OV1_PPC_2_04 | OV1_PPC_2_05,
|
||||
|
||||
/* option vector 2: Open Firmware options supported */
|
||||
34 - 1, /* length */
|
||||
34 - 2, /* length */
|
||||
OV2_REAL_MODE,
|
||||
0, 0,
|
||||
W(0xffffffff), /* real_base */
|
||||
|
@ -666,16 +666,16 @@ static unsigned char ibm_architecture_vec[] = {
|
|||
48, /* max log_2(hash table size) */
|
||||
|
||||
/* option vector 3: processor options supported */
|
||||
3 - 1, /* length */
|
||||
3 - 2, /* length */
|
||||
0, /* don't ignore, don't halt */
|
||||
OV3_FP | OV3_VMX,
|
||||
|
||||
/* option vector 4: IBM PAPR implementation */
|
||||
2 - 1, /* length */
|
||||
2 - 2, /* length */
|
||||
0, /* don't halt */
|
||||
|
||||
/* option vector 5: PAPR/OF options */
|
||||
3 - 1, /* length */
|
||||
3 - 2, /* length */
|
||||
0, /* don't ignore, don't halt */
|
||||
OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES,
|
||||
};
|
||||
|
|
|
@ -642,7 +642,7 @@ void of_irq_map_init(unsigned int flags)
|
|||
|
||||
}
|
||||
|
||||
int of_irq_map_raw(struct device_node *parent, const u32 *intspec,
|
||||
int of_irq_map_raw(struct device_node *parent, const u32 *intspec, u32 ointsize,
|
||||
const u32 *addr, struct of_irq *out_irq)
|
||||
{
|
||||
struct device_node *ipar, *tnode, *old = NULL, *newpar = NULL;
|
||||
|
@ -650,6 +650,9 @@ int of_irq_map_raw(struct device_node *parent, const u32 *intspec,
|
|||
u32 intsize = 1, addrsize, newintsize = 0, newaddrsize = 0;
|
||||
int imaplen, match, i;
|
||||
|
||||
DBG("of_irq_map_raw: par=%s,intspec=[0x%08x 0x%08x...],ointsize=%d\n",
|
||||
parent->full_name, intspec[0], intspec[1], ointsize);
|
||||
|
||||
ipar = of_node_get(parent);
|
||||
|
||||
/* First get the #interrupt-cells property of the current cursor
|
||||
|
@ -673,6 +676,9 @@ int of_irq_map_raw(struct device_node *parent, const u32 *intspec,
|
|||
|
||||
DBG("of_irq_map_raw: ipar=%s, size=%d\n", ipar->full_name, intsize);
|
||||
|
||||
if (ointsize != intsize)
|
||||
return -EINVAL;
|
||||
|
||||
/* Look for this #address-cells. We have to implement the old linux
|
||||
* trick of looking for the parent here as some device-trees rely on it
|
||||
*/
|
||||
|
@ -879,12 +885,15 @@ int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq
|
|||
}
|
||||
intsize = *tmp;
|
||||
|
||||
DBG(" intsize=%d intlen=%d\n", intsize, intlen);
|
||||
|
||||
/* Check index */
|
||||
if ((index + 1) * intsize > intlen)
|
||||
return -EINVAL;
|
||||
|
||||
/* Get new specifier and map it */
|
||||
res = of_irq_map_raw(p, intspec + index * intsize, addr, out_irq);
|
||||
res = of_irq_map_raw(p, intspec + index * intsize, intsize,
|
||||
addr, out_irq);
|
||||
of_node_put(p);
|
||||
return res;
|
||||
}
|
||||
|
@ -969,7 +978,7 @@ int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
|
|||
laddr[0] = (pdev->bus->number << 16)
|
||||
| (pdev->devfn << 8);
|
||||
laddr[1] = laddr[2] = 0;
|
||||
return of_irq_map_raw(ppnode, &lspec, laddr, out_irq);
|
||||
return of_irq_map_raw(ppnode, &lspec, 1, laddr, out_irq);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_irq_map_pci);
|
||||
#endif /* CONFIG_PCI */
|
||||
|
|
|
@ -45,8 +45,9 @@ void __devinit smp_generic_take_timebase(void)
|
|||
{
|
||||
int cmd;
|
||||
u64 tb;
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_disable();
|
||||
local_irq_save(flags);
|
||||
while (!running)
|
||||
barrier();
|
||||
rmb();
|
||||
|
@ -70,7 +71,7 @@ void __devinit smp_generic_take_timebase(void)
|
|||
set_tb(tb >> 32, tb & 0xfffffffful);
|
||||
enter_contest(tbsync->mark, -1);
|
||||
}
|
||||
local_irq_enable();
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static int __devinit start_contest(int cmd, long offset, int num)
|
||||
|
|
|
@ -125,15 +125,8 @@ static long timezone_offset;
|
|||
unsigned long ppc_proc_freq;
|
||||
unsigned long ppc_tb_freq;
|
||||
|
||||
u64 tb_last_jiffy __cacheline_aligned_in_smp;
|
||||
unsigned long tb_last_stamp;
|
||||
|
||||
/*
|
||||
* Note that on ppc32 this only stores the bottom 32 bits of
|
||||
* the timebase value, but that's enough to tell when a jiffy
|
||||
* has passed.
|
||||
*/
|
||||
DEFINE_PER_CPU(unsigned long, last_jiffy);
|
||||
static u64 tb_last_jiffy __cacheline_aligned_in_smp;
|
||||
static DEFINE_PER_CPU(u64, last_jiffy);
|
||||
|
||||
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
|
||||
/*
|
||||
|
@ -458,7 +451,7 @@ void do_gettimeofday(struct timeval *tv)
|
|||
do {
|
||||
seq = read_seqbegin_irqsave(&xtime_lock, flags);
|
||||
sec = xtime.tv_sec;
|
||||
nsec = xtime.tv_nsec + tb_ticks_since(tb_last_stamp);
|
||||
nsec = xtime.tv_nsec + tb_ticks_since(tb_last_jiffy);
|
||||
} while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
|
||||
usec = nsec / 1000;
|
||||
while (usec >= 1000000) {
|
||||
|
@ -700,7 +693,6 @@ void timer_interrupt(struct pt_regs * regs)
|
|||
tb_next_jiffy = tb_last_jiffy + tb_ticks_per_jiffy;
|
||||
if (per_cpu(last_jiffy, cpu) >= tb_next_jiffy) {
|
||||
tb_last_jiffy = tb_next_jiffy;
|
||||
tb_last_stamp = per_cpu(last_jiffy, cpu);
|
||||
do_timer(regs);
|
||||
timer_recalc_offset(tb_last_jiffy);
|
||||
timer_check_rtc();
|
||||
|
@ -749,7 +741,7 @@ void __init smp_space_timers(unsigned int max_cpus)
|
|||
int i;
|
||||
unsigned long half = tb_ticks_per_jiffy / 2;
|
||||
unsigned long offset = tb_ticks_per_jiffy / max_cpus;
|
||||
unsigned long previous_tb = per_cpu(last_jiffy, boot_cpuid);
|
||||
u64 previous_tb = per_cpu(last_jiffy, boot_cpuid);
|
||||
|
||||
/* make sure tb > per_cpu(last_jiffy, cpu) for all cpus always */
|
||||
previous_tb -= tb_ticks_per_jiffy;
|
||||
|
@ -830,7 +822,7 @@ int do_settimeofday(struct timespec *tv)
|
|||
* and therefore the (jiffies - wall_jiffies) computation
|
||||
* has been removed.
|
||||
*/
|
||||
tb_delta = tb_ticks_since(tb_last_stamp);
|
||||
tb_delta = tb_ticks_since(tb_last_jiffy);
|
||||
tb_delta = mulhdu(tb_delta, do_gtod.varp->tb_to_xs); /* in xsec */
|
||||
new_nsec -= SCALE_XSEC(tb_delta, 1000000000);
|
||||
|
||||
|
@ -950,8 +942,7 @@ void __init time_init(void)
|
|||
if (__USE_RTC()) {
|
||||
/* 601 processor: dec counts down by 128 every 128ns */
|
||||
ppc_tb_freq = 1000000000;
|
||||
tb_last_stamp = get_rtcl();
|
||||
tb_last_jiffy = tb_last_stamp;
|
||||
tb_last_jiffy = get_rtcl();
|
||||
} else {
|
||||
/* Normal PowerPC with timebase register */
|
||||
ppc_md.calibrate_decr();
|
||||
|
@ -959,7 +950,7 @@ void __init time_init(void)
|
|||
ppc_tb_freq / 1000000, ppc_tb_freq % 1000000);
|
||||
printk(KERN_DEBUG "time_init: processor frequency = %lu.%.6lu MHz\n",
|
||||
ppc_proc_freq / 1000000, ppc_proc_freq % 1000000);
|
||||
tb_last_stamp = tb_last_jiffy = get_tb();
|
||||
tb_last_jiffy = get_tb();
|
||||
}
|
||||
|
||||
tb_ticks_per_jiffy = ppc_tb_freq / HZ;
|
||||
|
@ -1036,7 +1027,7 @@ void __init time_init(void)
|
|||
do_gtod.varp = &do_gtod.vars[0];
|
||||
do_gtod.var_idx = 0;
|
||||
do_gtod.varp->tb_orig_stamp = tb_last_jiffy;
|
||||
__get_cpu_var(last_jiffy) = tb_last_stamp;
|
||||
__get_cpu_var(last_jiffy) = tb_last_jiffy;
|
||||
do_gtod.varp->stamp_xsec = (u64) xtime.tv_sec * XSEC_PER_SEC;
|
||||
do_gtod.tb_ticks_per_sec = tb_ticks_per_sec;
|
||||
do_gtod.varp->tb_to_xs = tb_to_xs;
|
||||
|
|
|
@ -148,7 +148,7 @@ int die(const char *str, struct pt_regs *regs, long err)
|
|||
panic("Fatal exception in interrupt");
|
||||
|
||||
if (panic_on_oops)
|
||||
panic("Fatal exception: panic_on_oops");
|
||||
panic("Fatal exception");
|
||||
|
||||
do_exit(err);
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
.align 7
|
||||
_GLOBAL(memcpy)
|
||||
std r3,48(r1) /* save destination pointer for return value */
|
||||
mtcrf 0x01,r5
|
||||
cmpldi cr1,r5,16
|
||||
neg r6,r3 # LS 3 bits = # bytes to 8-byte dest bdry
|
||||
|
@ -38,7 +39,7 @@ _GLOBAL(memcpy)
|
|||
stdu r9,16(r3)
|
||||
bdnz 1b
|
||||
3: std r8,8(r3)
|
||||
beqlr
|
||||
beq 3f
|
||||
addi r3,r3,16
|
||||
ld r9,8(r4)
|
||||
.Ldo_tail:
|
||||
|
@ -53,7 +54,8 @@ _GLOBAL(memcpy)
|
|||
2: bf cr7*4+3,3f
|
||||
rotldi r9,r9,8
|
||||
stb r9,0(r3)
|
||||
3: blr
|
||||
3: ld r3,48(r1) /* return dest pointer */
|
||||
blr
|
||||
|
||||
.Lsrc_unaligned:
|
||||
srdi r6,r5,3
|
||||
|
@ -115,7 +117,7 @@ _GLOBAL(memcpy)
|
|||
5: srd r12,r9,r11
|
||||
or r12,r8,r12
|
||||
std r12,24(r3)
|
||||
beqlr
|
||||
beq 4f
|
||||
cmpwi cr1,r5,8
|
||||
addi r3,r3,32
|
||||
sld r9,r9,r10
|
||||
|
@ -167,4 +169,5 @@ _GLOBAL(memcpy)
|
|||
3: bf cr7*4+3,4f
|
||||
lbz r0,0(r4)
|
||||
stb r0,0(r3)
|
||||
4: blr
|
||||
4: ld r3,48(r1) /* return dest pointer */
|
||||
blr
|
||||
|
|
|
@ -46,26 +46,6 @@ unsigned long isa_io_base = 0;
|
|||
unsigned long isa_mem_base = 0;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
static int
|
||||
mpc83xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
|
||||
{
|
||||
static char pci_irq_table[][4] =
|
||||
/*
|
||||
* PCI IDSEL/INTPIN->INTLINE
|
||||
* A B C D
|
||||
*/
|
||||
{
|
||||
{PIRQB, PIRQC, PIRQD, PIRQA}, /* idsel 0x0e */
|
||||
{PIRQA, PIRQB, PIRQC, PIRQD}, /* idsel 0x0f */
|
||||
{PIRQC, PIRQD, PIRQA, PIRQB}, /* idsel 0x10 */
|
||||
};
|
||||
|
||||
const long min_idsel = 0x0e, max_idsel = 0x10, irqs_per_slot = 4;
|
||||
return PCI_IRQ_TABLE_LOOKUP;
|
||||
}
|
||||
#endif /* CONFIG_PCI */
|
||||
|
||||
/* ************************************************************************
|
||||
*
|
||||
* Setup the architecture
|
||||
|
@ -92,8 +72,6 @@ static void __init mpc834x_itx_setup_arch(void)
|
|||
for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
|
||||
add_bridge(np);
|
||||
|
||||
ppc_md.pci_swizzle = common_swizzle;
|
||||
ppc_md.pci_map_irq = mpc83xx_map_irq;
|
||||
ppc_md.pci_exclude_device = mpc83xx_exclude_device;
|
||||
#endif
|
||||
|
||||
|
@ -106,25 +84,13 @@ static void __init mpc834x_itx_setup_arch(void)
|
|||
|
||||
void __init mpc834x_itx_init_IRQ(void)
|
||||
{
|
||||
u8 senses[8] = {
|
||||
0, /* EXT 0 */
|
||||
IRQ_SENSE_LEVEL, /* EXT 1 */
|
||||
IRQ_SENSE_LEVEL, /* EXT 2 */
|
||||
0, /* EXT 3 */
|
||||
#ifdef CONFIG_PCI
|
||||
IRQ_SENSE_LEVEL, /* EXT 4 */
|
||||
IRQ_SENSE_LEVEL, /* EXT 5 */
|
||||
IRQ_SENSE_LEVEL, /* EXT 6 */
|
||||
IRQ_SENSE_LEVEL, /* EXT 7 */
|
||||
#else
|
||||
0, /* EXT 4 */
|
||||
0, /* EXT 5 */
|
||||
0, /* EXT 6 */
|
||||
0, /* EXT 7 */
|
||||
#endif
|
||||
};
|
||||
struct device_node *np;
|
||||
|
||||
ipic_init(get_immrbase() + 0x00700, 0, 0, senses, 8);
|
||||
np = of_find_node_by_type(NULL, "ipic");
|
||||
if (!np)
|
||||
return;
|
||||
|
||||
ipic_init(np, 0);
|
||||
|
||||
/* Initialize the default interrupt mapping priorities,
|
||||
* in case the boot rom changed something on us.
|
||||
|
@ -153,4 +119,7 @@ define_machine(mpc834x_itx) {
|
|||
.time_init = mpc83xx_time_init,
|
||||
.calibrate_decr = generic_calibrate_decr,
|
||||
.progress = udbg_progress,
|
||||
#ifdef CONFIG_PCI
|
||||
.pcibios_fixup = mpc83xx_pcibios_fixup,
|
||||
#endif
|
||||
};
|
||||
|
|
|
@ -43,33 +43,6 @@ unsigned long isa_io_base = 0;
|
|||
unsigned long isa_mem_base = 0;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
static int
|
||||
mpc83xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
|
||||
{
|
||||
static char pci_irq_table[][4] =
|
||||
/*
|
||||
* PCI IDSEL/INTPIN->INTLINE
|
||||
* A B C D
|
||||
*/
|
||||
{
|
||||
{PIRQA, PIRQB, PIRQC, PIRQD}, /* idsel 0x11 */
|
||||
{PIRQC, PIRQD, PIRQA, PIRQB}, /* idsel 0x12 */
|
||||
{PIRQD, PIRQA, PIRQB, PIRQC}, /* idsel 0x13 */
|
||||
{0, 0, 0, 0},
|
||||
{PIRQA, PIRQB, PIRQC, PIRQD}, /* idsel 0x15 */
|
||||
{PIRQD, PIRQA, PIRQB, PIRQC}, /* idsel 0x16 */
|
||||
{PIRQC, PIRQD, PIRQA, PIRQB}, /* idsel 0x17 */
|
||||
{PIRQB, PIRQC, PIRQD, PIRQA}, /* idsel 0x18 */
|
||||
{0, 0, 0, 0}, /* idsel 0x19 */
|
||||
{0, 0, 0, 0}, /* idsel 0x20 */
|
||||
};
|
||||
|
||||
const long min_idsel = 0x11, max_idsel = 0x20, irqs_per_slot = 4;
|
||||
return PCI_IRQ_TABLE_LOOKUP;
|
||||
}
|
||||
#endif /* CONFIG_PCI */
|
||||
|
||||
/* ************************************************************************
|
||||
*
|
||||
* Setup the architecture
|
||||
|
@ -96,8 +69,6 @@ static void __init mpc834x_sys_setup_arch(void)
|
|||
for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
|
||||
add_bridge(np);
|
||||
|
||||
ppc_md.pci_swizzle = common_swizzle;
|
||||
ppc_md.pci_map_irq = mpc83xx_map_irq;
|
||||
ppc_md.pci_exclude_device = mpc83xx_exclude_device;
|
||||
#endif
|
||||
|
||||
|
@ -110,25 +81,13 @@ static void __init mpc834x_sys_setup_arch(void)
|
|||
|
||||
void __init mpc834x_sys_init_IRQ(void)
|
||||
{
|
||||
u8 senses[8] = {
|
||||
0, /* EXT 0 */
|
||||
IRQ_SENSE_LEVEL, /* EXT 1 */
|
||||
IRQ_SENSE_LEVEL, /* EXT 2 */
|
||||
0, /* EXT 3 */
|
||||
#ifdef CONFIG_PCI
|
||||
IRQ_SENSE_LEVEL, /* EXT 4 */
|
||||
IRQ_SENSE_LEVEL, /* EXT 5 */
|
||||
IRQ_SENSE_LEVEL, /* EXT 6 */
|
||||
IRQ_SENSE_LEVEL, /* EXT 7 */
|
||||
#else
|
||||
0, /* EXT 4 */
|
||||
0, /* EXT 5 */
|
||||
0, /* EXT 6 */
|
||||
0, /* EXT 7 */
|
||||
#endif
|
||||
};
|
||||
struct device_node *np;
|
||||
|
||||
ipic_init(get_immrbase() + 0x00700, 0, 0, senses, 8);
|
||||
np = of_find_node_by_type(NULL, "ipic");
|
||||
if (!np)
|
||||
return;
|
||||
|
||||
ipic_init(np, 0);
|
||||
|
||||
/* Initialize the default interrupt mapping priorities,
|
||||
* in case the boot rom changed something on us.
|
||||
|
@ -178,4 +137,7 @@ define_machine(mpc834x_sys) {
|
|||
.time_init = mpc83xx_time_init,
|
||||
.calibrate_decr = generic_calibrate_decr,
|
||||
.progress = udbg_progress,
|
||||
#ifdef CONFIG_PCI
|
||||
.pcibios_fixup = mpc83xx_pcibios_fixup,
|
||||
#endif
|
||||
};
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
extern int add_bridge(struct device_node *dev);
|
||||
extern int mpc83xx_exclude_device(u_char bus, u_char devfn);
|
||||
extern void mpc83xx_pcibios_fixup(void);
|
||||
extern void mpc83xx_restart(char *cmd);
|
||||
extern long mpc83xx_time_init(void);
|
||||
|
||||
|
|
|
@ -45,6 +45,15 @@ int mpc83xx_exclude_device(u_char bus, u_char devfn)
|
|||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
void __init mpc83xx_pcibios_fixup(void)
|
||||
{
|
||||
struct pci_dev *dev = NULL;
|
||||
|
||||
/* map all the PCI irqs */
|
||||
for_each_pci_dev(dev)
|
||||
pci_read_irq_line(dev);
|
||||
}
|
||||
|
||||
int __init add_bridge(struct device_node *dev)
|
||||
{
|
||||
int len;
|
||||
|
|
|
@ -80,6 +80,7 @@ config MPC7448HPC2
|
|||
select DEFAULT_UIMAGE
|
||||
select PPC_UDBG_16550
|
||||
select MPIC
|
||||
select MPIC_WEIRD
|
||||
help
|
||||
Select MPC7448HPC2 if configuring for Freescale MPC7448HPC2 (Taiga)
|
||||
platform
|
||||
|
|
|
@ -215,7 +215,7 @@ static void __init mpc7448_hpc2_init_IRQ(void)
|
|||
|
||||
mpic = mpic_alloc(tsi_pic, mpic_paddr,
|
||||
MPIC_PRIMARY | MPIC_BIG_ENDIAN | MPIC_WANTS_RESET |
|
||||
MPIC_SPV_EOI | MPIC_MOD_ID(MPIC_ID_TSI108),
|
||||
MPIC_SPV_EOI | MPIC_NO_PTHROU_DIS | MPIC_REGSET_TSI108,
|
||||
0, /* num_sources used */
|
||||
0, /* num_sources used */
|
||||
"Tsi108_PIC");
|
||||
|
|
|
@ -9,11 +9,11 @@ obj-$(CONFIG_BOOKE) += dcr.o
|
|||
obj-$(CONFIG_40x) += dcr.o
|
||||
obj-$(CONFIG_U3_DART) += dart_iommu.o
|
||||
obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o
|
||||
obj-$(CONFIG_PPC_83xx) += ipic.o
|
||||
obj-$(CONFIG_FSL_SOC) += fsl_soc.o
|
||||
obj-$(CONFIG_PPC_TODC) += todc.o
|
||||
obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o
|
||||
|
||||
ifeq ($(CONFIG_PPC_MERGE),y)
|
||||
obj-$(CONFIG_PPC_I8259) += i8259.o
|
||||
obj-$(CONFIG_PPC_83xx) += ipic.o
|
||||
endif
|
||||
|
|
|
@ -19,15 +19,18 @@
|
|||
#include <linux/sched.h>
|
||||
#include <linux/signal.h>
|
||||
#include <linux/sysdev.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/bootmem.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/ipic.h>
|
||||
#include <asm/mpc83xx.h>
|
||||
|
||||
#include "ipic.h"
|
||||
|
||||
static struct ipic p_ipic;
|
||||
static struct ipic * primary_ipic;
|
||||
static DEFINE_SPINLOCK(ipic_lock);
|
||||
|
||||
static struct ipic_info ipic_info[] = {
|
||||
[9] = {
|
||||
|
@ -373,74 +376,220 @@ static inline void ipic_write(volatile u32 __iomem *base, unsigned int reg, u32
|
|||
out_be32(base + (reg >> 2), value);
|
||||
}
|
||||
|
||||
static inline struct ipic * ipic_from_irq(unsigned int irq)
|
||||
static inline struct ipic * ipic_from_irq(unsigned int virq)
|
||||
{
|
||||
return primary_ipic;
|
||||
}
|
||||
|
||||
static void ipic_enable_irq(unsigned int irq)
|
||||
#define ipic_irq_to_hw(virq) ((unsigned int)irq_map[virq].hwirq)
|
||||
|
||||
static void ipic_unmask_irq(unsigned int virq)
|
||||
{
|
||||
struct ipic *ipic = ipic_from_irq(irq);
|
||||
unsigned int src = irq - ipic->irq_offset;
|
||||
struct ipic *ipic = ipic_from_irq(virq);
|
||||
unsigned int src = ipic_irq_to_hw(virq);
|
||||
unsigned long flags;
|
||||
u32 temp;
|
||||
|
||||
spin_lock_irqsave(&ipic_lock, flags);
|
||||
|
||||
temp = ipic_read(ipic->regs, ipic_info[src].mask);
|
||||
temp |= (1 << (31 - ipic_info[src].bit));
|
||||
ipic_write(ipic->regs, ipic_info[src].mask, temp);
|
||||
|
||||
spin_unlock_irqrestore(&ipic_lock, flags);
|
||||
}
|
||||
|
||||
static void ipic_disable_irq(unsigned int irq)
|
||||
static void ipic_mask_irq(unsigned int virq)
|
||||
{
|
||||
struct ipic *ipic = ipic_from_irq(irq);
|
||||
unsigned int src = irq - ipic->irq_offset;
|
||||
struct ipic *ipic = ipic_from_irq(virq);
|
||||
unsigned int src = ipic_irq_to_hw(virq);
|
||||
unsigned long flags;
|
||||
u32 temp;
|
||||
|
||||
spin_lock_irqsave(&ipic_lock, flags);
|
||||
|
||||
temp = ipic_read(ipic->regs, ipic_info[src].mask);
|
||||
temp &= ~(1 << (31 - ipic_info[src].bit));
|
||||
ipic_write(ipic->regs, ipic_info[src].mask, temp);
|
||||
|
||||
spin_unlock_irqrestore(&ipic_lock, flags);
|
||||
}
|
||||
|
||||
static void ipic_disable_irq_and_ack(unsigned int irq)
|
||||
static void ipic_ack_irq(unsigned int virq)
|
||||
{
|
||||
struct ipic *ipic = ipic_from_irq(irq);
|
||||
unsigned int src = irq - ipic->irq_offset;
|
||||
struct ipic *ipic = ipic_from_irq(virq);
|
||||
unsigned int src = ipic_irq_to_hw(virq);
|
||||
unsigned long flags;
|
||||
u32 temp;
|
||||
|
||||
ipic_disable_irq(irq);
|
||||
spin_lock_irqsave(&ipic_lock, flags);
|
||||
|
||||
temp = ipic_read(ipic->regs, ipic_info[src].pend);
|
||||
temp |= (1 << (31 - ipic_info[src].bit));
|
||||
ipic_write(ipic->regs, ipic_info[src].pend, temp);
|
||||
|
||||
spin_unlock_irqrestore(&ipic_lock, flags);
|
||||
}
|
||||
|
||||
static void ipic_end_irq(unsigned int irq)
|
||||
static void ipic_mask_irq_and_ack(unsigned int virq)
|
||||
{
|
||||
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
|
||||
ipic_enable_irq(irq);
|
||||
struct ipic *ipic = ipic_from_irq(virq);
|
||||
unsigned int src = ipic_irq_to_hw(virq);
|
||||
unsigned long flags;
|
||||
u32 temp;
|
||||
|
||||
spin_lock_irqsave(&ipic_lock, flags);
|
||||
|
||||
temp = ipic_read(ipic->regs, ipic_info[src].mask);
|
||||
temp &= ~(1 << (31 - ipic_info[src].bit));
|
||||
ipic_write(ipic->regs, ipic_info[src].mask, temp);
|
||||
|
||||
temp = ipic_read(ipic->regs, ipic_info[src].pend);
|
||||
temp |= (1 << (31 - ipic_info[src].bit));
|
||||
ipic_write(ipic->regs, ipic_info[src].pend, temp);
|
||||
|
||||
spin_unlock_irqrestore(&ipic_lock, flags);
|
||||
}
|
||||
|
||||
struct hw_interrupt_type ipic = {
|
||||
static int ipic_set_irq_type(unsigned int virq, unsigned int flow_type)
|
||||
{
|
||||
struct ipic *ipic = ipic_from_irq(virq);
|
||||
unsigned int src = ipic_irq_to_hw(virq);
|
||||
struct irq_desc *desc = get_irq_desc(virq);
|
||||
unsigned int vold, vnew, edibit;
|
||||
|
||||
if (flow_type == IRQ_TYPE_NONE)
|
||||
flow_type = IRQ_TYPE_LEVEL_LOW;
|
||||
|
||||
/* ipic supports only low assertion and high-to-low change senses
|
||||
*/
|
||||
if (!(flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING))) {
|
||||
printk(KERN_ERR "ipic: sense type 0x%x not supported\n",
|
||||
flow_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
|
||||
desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
|
||||
if (flow_type & IRQ_TYPE_LEVEL_LOW) {
|
||||
desc->status |= IRQ_LEVEL;
|
||||
set_irq_handler(virq, handle_level_irq);
|
||||
} else {
|
||||
set_irq_handler(virq, handle_edge_irq);
|
||||
}
|
||||
|
||||
/* only EXT IRQ senses are programmable on ipic
|
||||
* internal IRQ senses are LEVEL_LOW
|
||||
*/
|
||||
if (src == IPIC_IRQ_EXT0)
|
||||
edibit = 15;
|
||||
else
|
||||
if (src >= IPIC_IRQ_EXT1 && src <= IPIC_IRQ_EXT7)
|
||||
edibit = (14 - (src - IPIC_IRQ_EXT1));
|
||||
else
|
||||
return (flow_type & IRQ_TYPE_LEVEL_LOW) ? 0 : -EINVAL;
|
||||
|
||||
vold = ipic_read(ipic->regs, IPIC_SECNR);
|
||||
if ((flow_type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_FALLING) {
|
||||
vnew = vold | (1 << edibit);
|
||||
} else {
|
||||
vnew = vold & ~(1 << edibit);
|
||||
}
|
||||
if (vold != vnew)
|
||||
ipic_write(ipic->regs, IPIC_SECNR, vnew);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct irq_chip ipic_irq_chip = {
|
||||
.typename = " IPIC ",
|
||||
.enable = ipic_enable_irq,
|
||||
.disable = ipic_disable_irq,
|
||||
.ack = ipic_disable_irq_and_ack,
|
||||
.end = ipic_end_irq,
|
||||
.unmask = ipic_unmask_irq,
|
||||
.mask = ipic_mask_irq,
|
||||
.mask_ack = ipic_mask_irq_and_ack,
|
||||
.ack = ipic_ack_irq,
|
||||
.set_type = ipic_set_irq_type,
|
||||
};
|
||||
|
||||
void __init ipic_init(phys_addr_t phys_addr,
|
||||
unsigned int flags,
|
||||
unsigned int irq_offset,
|
||||
unsigned char *senses,
|
||||
unsigned int senses_count)
|
||||
static int ipic_host_match(struct irq_host *h, struct device_node *node)
|
||||
{
|
||||
u32 i, temp = 0;
|
||||
struct ipic *ipic = h->host_data;
|
||||
|
||||
primary_ipic = &p_ipic;
|
||||
primary_ipic->regs = ioremap(phys_addr, MPC83xx_IPIC_SIZE);
|
||||
/* Exact match, unless ipic node is NULL */
|
||||
return ipic->of_node == NULL || ipic->of_node == node;
|
||||
}
|
||||
|
||||
primary_ipic->irq_offset = irq_offset;
|
||||
static int ipic_host_map(struct irq_host *h, unsigned int virq,
|
||||
irq_hw_number_t hw)
|
||||
{
|
||||
struct ipic *ipic = h->host_data;
|
||||
struct irq_chip *chip;
|
||||
|
||||
ipic_write(primary_ipic->regs, IPIC_SICNR, 0x0);
|
||||
/* Default chip */
|
||||
chip = &ipic->hc_irq;
|
||||
|
||||
set_irq_chip_data(virq, ipic);
|
||||
set_irq_chip_and_handler(virq, chip, handle_level_irq);
|
||||
|
||||
/* Set default irq type */
|
||||
set_irq_type(virq, IRQ_TYPE_NONE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ipic_host_xlate(struct irq_host *h, struct device_node *ct,
|
||||
u32 *intspec, unsigned int intsize,
|
||||
irq_hw_number_t *out_hwirq, unsigned int *out_flags)
|
||||
|
||||
{
|
||||
/* interrupt sense values coming from the device tree equal either
|
||||
* LEVEL_LOW (low assertion) or EDGE_FALLING (high-to-low change)
|
||||
*/
|
||||
*out_hwirq = intspec[0];
|
||||
if (intsize > 1)
|
||||
*out_flags = intspec[1];
|
||||
else
|
||||
*out_flags = IRQ_TYPE_NONE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct irq_host_ops ipic_host_ops = {
|
||||
.match = ipic_host_match,
|
||||
.map = ipic_host_map,
|
||||
.xlate = ipic_host_xlate,
|
||||
};
|
||||
|
||||
void __init ipic_init(struct device_node *node,
|
||||
unsigned int flags)
|
||||
{
|
||||
struct ipic *ipic;
|
||||
struct resource res;
|
||||
u32 temp = 0, ret;
|
||||
|
||||
ipic = alloc_bootmem(sizeof(struct ipic));
|
||||
if (ipic == NULL)
|
||||
return;
|
||||
|
||||
memset(ipic, 0, sizeof(struct ipic));
|
||||
ipic->of_node = node ? of_node_get(node) : NULL;
|
||||
|
||||
ipic->irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR,
|
||||
NR_IPIC_INTS,
|
||||
&ipic_host_ops, 0);
|
||||
if (ipic->irqhost == NULL) {
|
||||
of_node_put(node);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = of_address_to_resource(node, 0, &res);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
ipic->regs = ioremap(res.start, res.end - res.start + 1);
|
||||
|
||||
ipic->irqhost->host_data = ipic;
|
||||
ipic->hc_irq = ipic_irq_chip;
|
||||
|
||||
/* init hw */
|
||||
ipic_write(ipic->regs, IPIC_SICNR, 0x0);
|
||||
|
||||
/* default priority scheme is grouped. If spread mode is required
|
||||
* configure SICFR accordingly */
|
||||
|
@ -453,49 +602,35 @@ void __init ipic_init(phys_addr_t phys_addr,
|
|||
if (flags & IPIC_SPREADMODE_MIX_B)
|
||||
temp |= SICFR_MPSB;
|
||||
|
||||
ipic_write(primary_ipic->regs, IPIC_SICNR, temp);
|
||||
ipic_write(ipic->regs, IPIC_SICNR, temp);
|
||||
|
||||
/* handle MCP route */
|
||||
temp = 0;
|
||||
if (flags & IPIC_DISABLE_MCP_OUT)
|
||||
temp = SERCR_MCPR;
|
||||
ipic_write(primary_ipic->regs, IPIC_SERCR, temp);
|
||||
ipic_write(ipic->regs, IPIC_SERCR, temp);
|
||||
|
||||
/* handle routing of IRQ0 to MCP */
|
||||
temp = ipic_read(primary_ipic->regs, IPIC_SEMSR);
|
||||
temp = ipic_read(ipic->regs, IPIC_SEMSR);
|
||||
|
||||
if (flags & IPIC_IRQ0_MCP)
|
||||
temp |= SEMSR_SIRQ0;
|
||||
else
|
||||
temp &= ~SEMSR_SIRQ0;
|
||||
|
||||
ipic_write(primary_ipic->regs, IPIC_SEMSR, temp);
|
||||
ipic_write(ipic->regs, IPIC_SEMSR, temp);
|
||||
|
||||
for (i = 0 ; i < NR_IPIC_INTS ; i++) {
|
||||
irq_desc[i+irq_offset].chip = &ipic;
|
||||
irq_desc[i+irq_offset].status = IRQ_LEVEL;
|
||||
primary_ipic = ipic;
|
||||
irq_set_default_host(primary_ipic->irqhost);
|
||||
|
||||
printk ("IPIC (%d IRQ sources) at %p\n", NR_IPIC_INTS,
|
||||
primary_ipic->regs);
|
||||
}
|
||||
|
||||
temp = 0;
|
||||
for (i = 0 ; i < senses_count ; i++) {
|
||||
if ((senses[i] & IRQ_SENSE_MASK) == IRQ_SENSE_EDGE) {
|
||||
temp |= 1 << (15 - i);
|
||||
if (i != 0)
|
||||
irq_desc[i + irq_offset + MPC83xx_IRQ_EXT1 - 1].status = 0;
|
||||
else
|
||||
irq_desc[irq_offset + MPC83xx_IRQ_EXT0].status = 0;
|
||||
}
|
||||
}
|
||||
ipic_write(primary_ipic->regs, IPIC_SECNR, temp);
|
||||
|
||||
printk ("IPIC (%d IRQ sources, %d External IRQs) at %p\n", NR_IPIC_INTS,
|
||||
senses_count, primary_ipic->regs);
|
||||
}
|
||||
|
||||
int ipic_set_priority(unsigned int irq, unsigned int priority)
|
||||
int ipic_set_priority(unsigned int virq, unsigned int priority)
|
||||
{
|
||||
struct ipic *ipic = ipic_from_irq(irq);
|
||||
unsigned int src = irq - ipic->irq_offset;
|
||||
struct ipic *ipic = ipic_from_irq(virq);
|
||||
unsigned int src = ipic_irq_to_hw(virq);
|
||||
u32 temp;
|
||||
|
||||
if (priority > 7)
|
||||
|
@ -520,10 +655,10 @@ int ipic_set_priority(unsigned int irq, unsigned int priority)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void ipic_set_highest_priority(unsigned int irq)
|
||||
void ipic_set_highest_priority(unsigned int virq)
|
||||
{
|
||||
struct ipic *ipic = ipic_from_irq(irq);
|
||||
unsigned int src = irq - ipic->irq_offset;
|
||||
struct ipic *ipic = ipic_from_irq(virq);
|
||||
unsigned int src = ipic_irq_to_hw(virq);
|
||||
u32 temp;
|
||||
|
||||
temp = ipic_read(ipic->regs, IPIC_SICFR);
|
||||
|
@ -537,37 +672,10 @@ void ipic_set_highest_priority(unsigned int irq)
|
|||
|
||||
void ipic_set_default_priority(void)
|
||||
{
|
||||
ipic_set_priority(MPC83xx_IRQ_TSEC1_TX, 0);
|
||||
ipic_set_priority(MPC83xx_IRQ_TSEC1_RX, 1);
|
||||
ipic_set_priority(MPC83xx_IRQ_TSEC1_ERROR, 2);
|
||||
ipic_set_priority(MPC83xx_IRQ_TSEC2_TX, 3);
|
||||
ipic_set_priority(MPC83xx_IRQ_TSEC2_RX, 4);
|
||||
ipic_set_priority(MPC83xx_IRQ_TSEC2_ERROR, 5);
|
||||
ipic_set_priority(MPC83xx_IRQ_USB2_DR, 6);
|
||||
ipic_set_priority(MPC83xx_IRQ_USB2_MPH, 7);
|
||||
|
||||
ipic_set_priority(MPC83xx_IRQ_UART1, 0);
|
||||
ipic_set_priority(MPC83xx_IRQ_UART2, 1);
|
||||
ipic_set_priority(MPC83xx_IRQ_SEC2, 2);
|
||||
ipic_set_priority(MPC83xx_IRQ_IIC1, 5);
|
||||
ipic_set_priority(MPC83xx_IRQ_IIC2, 6);
|
||||
ipic_set_priority(MPC83xx_IRQ_SPI, 7);
|
||||
ipic_set_priority(MPC83xx_IRQ_RTC_SEC, 0);
|
||||
ipic_set_priority(MPC83xx_IRQ_PIT, 1);
|
||||
ipic_set_priority(MPC83xx_IRQ_PCI1, 2);
|
||||
ipic_set_priority(MPC83xx_IRQ_PCI2, 3);
|
||||
ipic_set_priority(MPC83xx_IRQ_EXT0, 4);
|
||||
ipic_set_priority(MPC83xx_IRQ_EXT1, 5);
|
||||
ipic_set_priority(MPC83xx_IRQ_EXT2, 6);
|
||||
ipic_set_priority(MPC83xx_IRQ_EXT3, 7);
|
||||
ipic_set_priority(MPC83xx_IRQ_RTC_ALR, 0);
|
||||
ipic_set_priority(MPC83xx_IRQ_MU, 1);
|
||||
ipic_set_priority(MPC83xx_IRQ_SBA, 2);
|
||||
ipic_set_priority(MPC83xx_IRQ_DMA, 3);
|
||||
ipic_set_priority(MPC83xx_IRQ_EXT4, 4);
|
||||
ipic_set_priority(MPC83xx_IRQ_EXT5, 5);
|
||||
ipic_set_priority(MPC83xx_IRQ_EXT6, 6);
|
||||
ipic_set_priority(MPC83xx_IRQ_EXT7, 7);
|
||||
ipic_write(primary_ipic->regs, IPIC_SIPRR_A, IPIC_SIPRR_A_DEFAULT);
|
||||
ipic_write(primary_ipic->regs, IPIC_SIPRR_D, IPIC_SIPRR_D_DEFAULT);
|
||||
ipic_write(primary_ipic->regs, IPIC_SMPRR_A, IPIC_SMPRR_A_DEFAULT);
|
||||
ipic_write(primary_ipic->regs, IPIC_SMPRR_B, IPIC_SMPRR_B_DEFAULT);
|
||||
}
|
||||
|
||||
void ipic_enable_mcp(enum ipic_mcp_irq mcp_irq)
|
||||
|
@ -600,17 +708,20 @@ void ipic_clear_mcp_status(u32 mask)
|
|||
ipic_write(primary_ipic->regs, IPIC_SERMR, mask);
|
||||
}
|
||||
|
||||
/* Return an interrupt vector or -1 if no interrupt is pending. */
|
||||
int ipic_get_irq(struct pt_regs *regs)
|
||||
/* Return an interrupt vector or NO_IRQ if no interrupt is pending. */
|
||||
unsigned int ipic_get_irq(struct pt_regs *regs)
|
||||
{
|
||||
int irq;
|
||||
|
||||
irq = ipic_read(primary_ipic->regs, IPIC_SIVCR) & 0x7f;
|
||||
BUG_ON(primary_ipic == NULL);
|
||||
|
||||
#define IPIC_SIVCR_VECTOR_MASK 0x7f
|
||||
irq = ipic_read(primary_ipic->regs, IPIC_SIVCR) & IPIC_SIVCR_VECTOR_MASK;
|
||||
|
||||
if (irq == 0) /* 0 --> no irq is pending */
|
||||
irq = -1;
|
||||
return NO_IRQ;
|
||||
|
||||
return irq;
|
||||
return irq_linear_revmap(primary_ipic->irqhost, irq);
|
||||
}
|
||||
|
||||
static struct sysdev_class ipic_sysclass = {
|
||||
|
|
|
@ -15,7 +15,18 @@
|
|||
|
||||
#include <asm/ipic.h>
|
||||
|
||||
#define MPC83xx_IPIC_SIZE (0x00100)
|
||||
#define NR_IPIC_INTS 128
|
||||
|
||||
/* External IRQS */
|
||||
#define IPIC_IRQ_EXT0 48
|
||||
#define IPIC_IRQ_EXT1 17
|
||||
#define IPIC_IRQ_EXT7 23
|
||||
|
||||
/* Default Priority Registers */
|
||||
#define IPIC_SIPRR_A_DEFAULT 0x05309770
|
||||
#define IPIC_SIPRR_D_DEFAULT 0x05309770
|
||||
#define IPIC_SMPRR_A_DEFAULT 0x05309770
|
||||
#define IPIC_SMPRR_B_DEFAULT 0x05309770
|
||||
|
||||
/* System Global Interrupt Configuration Register */
|
||||
#define SICFR_IPSA 0x00010000
|
||||
|
@ -31,7 +42,15 @@
|
|||
|
||||
struct ipic {
|
||||
volatile u32 __iomem *regs;
|
||||
unsigned int irq_offset;
|
||||
|
||||
/* The remapper for this IPIC */
|
||||
struct irq_host *irqhost;
|
||||
|
||||
/* The "linux" controller struct */
|
||||
struct irq_chip hc_irq;
|
||||
|
||||
/* The device node of the interrupt controller */
|
||||
struct device_node *of_node;
|
||||
};
|
||||
|
||||
struct ipic_info {
|
||||
|
|
|
@ -54,6 +54,94 @@ static DEFINE_SPINLOCK(mpic_lock);
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MPIC_WEIRD
|
||||
static u32 mpic_infos[][MPIC_IDX_END] = {
|
||||
[0] = { /* Original OpenPIC compatible MPIC */
|
||||
MPIC_GREG_BASE,
|
||||
MPIC_GREG_FEATURE_0,
|
||||
MPIC_GREG_GLOBAL_CONF_0,
|
||||
MPIC_GREG_VENDOR_ID,
|
||||
MPIC_GREG_IPI_VECTOR_PRI_0,
|
||||
MPIC_GREG_IPI_STRIDE,
|
||||
MPIC_GREG_SPURIOUS,
|
||||
MPIC_GREG_TIMER_FREQ,
|
||||
|
||||
MPIC_TIMER_BASE,
|
||||
MPIC_TIMER_STRIDE,
|
||||
MPIC_TIMER_CURRENT_CNT,
|
||||
MPIC_TIMER_BASE_CNT,
|
||||
MPIC_TIMER_VECTOR_PRI,
|
||||
MPIC_TIMER_DESTINATION,
|
||||
|
||||
MPIC_CPU_BASE,
|
||||
MPIC_CPU_STRIDE,
|
||||
MPIC_CPU_IPI_DISPATCH_0,
|
||||
MPIC_CPU_IPI_DISPATCH_STRIDE,
|
||||
MPIC_CPU_CURRENT_TASK_PRI,
|
||||
MPIC_CPU_WHOAMI,
|
||||
MPIC_CPU_INTACK,
|
||||
MPIC_CPU_EOI,
|
||||
|
||||
MPIC_IRQ_BASE,
|
||||
MPIC_IRQ_STRIDE,
|
||||
MPIC_IRQ_VECTOR_PRI,
|
||||
MPIC_VECPRI_VECTOR_MASK,
|
||||
MPIC_VECPRI_POLARITY_POSITIVE,
|
||||
MPIC_VECPRI_POLARITY_NEGATIVE,
|
||||
MPIC_VECPRI_SENSE_LEVEL,
|
||||
MPIC_VECPRI_SENSE_EDGE,
|
||||
MPIC_VECPRI_POLARITY_MASK,
|
||||
MPIC_VECPRI_SENSE_MASK,
|
||||
MPIC_IRQ_DESTINATION
|
||||
},
|
||||
[1] = { /* Tsi108/109 PIC */
|
||||
TSI108_GREG_BASE,
|
||||
TSI108_GREG_FEATURE_0,
|
||||
TSI108_GREG_GLOBAL_CONF_0,
|
||||
TSI108_GREG_VENDOR_ID,
|
||||
TSI108_GREG_IPI_VECTOR_PRI_0,
|
||||
TSI108_GREG_IPI_STRIDE,
|
||||
TSI108_GREG_SPURIOUS,
|
||||
TSI108_GREG_TIMER_FREQ,
|
||||
|
||||
TSI108_TIMER_BASE,
|
||||
TSI108_TIMER_STRIDE,
|
||||
TSI108_TIMER_CURRENT_CNT,
|
||||
TSI108_TIMER_BASE_CNT,
|
||||
TSI108_TIMER_VECTOR_PRI,
|
||||
TSI108_TIMER_DESTINATION,
|
||||
|
||||
TSI108_CPU_BASE,
|
||||
TSI108_CPU_STRIDE,
|
||||
TSI108_CPU_IPI_DISPATCH_0,
|
||||
TSI108_CPU_IPI_DISPATCH_STRIDE,
|
||||
TSI108_CPU_CURRENT_TASK_PRI,
|
||||
TSI108_CPU_WHOAMI,
|
||||
TSI108_CPU_INTACK,
|
||||
TSI108_CPU_EOI,
|
||||
|
||||
TSI108_IRQ_BASE,
|
||||
TSI108_IRQ_STRIDE,
|
||||
TSI108_IRQ_VECTOR_PRI,
|
||||
TSI108_VECPRI_VECTOR_MASK,
|
||||
TSI108_VECPRI_POLARITY_POSITIVE,
|
||||
TSI108_VECPRI_POLARITY_NEGATIVE,
|
||||
TSI108_VECPRI_SENSE_LEVEL,
|
||||
TSI108_VECPRI_SENSE_EDGE,
|
||||
TSI108_VECPRI_POLARITY_MASK,
|
||||
TSI108_VECPRI_SENSE_MASK,
|
||||
TSI108_IRQ_DESTINATION
|
||||
},
|
||||
};
|
||||
|
||||
#define MPIC_INFO(name) mpic->hw_set[MPIC_IDX_##name]
|
||||
|
||||
#else /* CONFIG_MPIC_WEIRD */
|
||||
|
||||
#define MPIC_INFO(name) MPIC_##name
|
||||
|
||||
#endif /* CONFIG_MPIC_WEIRD */
|
||||
|
||||
/*
|
||||
* Register accessor functions
|
||||
*/
|
||||
|
@ -80,7 +168,8 @@ static inline void _mpic_write(unsigned int be, volatile u32 __iomem *base,
|
|||
static inline u32 _mpic_ipi_read(struct mpic *mpic, unsigned int ipi)
|
||||
{
|
||||
unsigned int be = (mpic->flags & MPIC_BIG_ENDIAN) != 0;
|
||||
unsigned int offset = MPIC_GREG_IPI_VECTOR_PRI_0 + (ipi * 0x10);
|
||||
unsigned int offset = MPIC_INFO(GREG_IPI_VECTOR_PRI_0) +
|
||||
(ipi * MPIC_INFO(GREG_IPI_STRIDE));
|
||||
|
||||
if (mpic->flags & MPIC_BROKEN_IPI)
|
||||
be = !be;
|
||||
|
@ -89,7 +178,8 @@ static inline u32 _mpic_ipi_read(struct mpic *mpic, unsigned int ipi)
|
|||
|
||||
static inline void _mpic_ipi_write(struct mpic *mpic, unsigned int ipi, u32 value)
|
||||
{
|
||||
unsigned int offset = MPIC_GREG_IPI_VECTOR_PRI_0 + (ipi * 0x10);
|
||||
unsigned int offset = MPIC_INFO(GREG_IPI_VECTOR_PRI_0) +
|
||||
(ipi * MPIC_INFO(GREG_IPI_STRIDE));
|
||||
|
||||
_mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->gregs, offset, value);
|
||||
}
|
||||
|
@ -120,7 +210,7 @@ static inline u32 _mpic_irq_read(struct mpic *mpic, unsigned int src_no, unsigne
|
|||
unsigned int idx = src_no & mpic->isu_mask;
|
||||
|
||||
return _mpic_read(mpic->flags & MPIC_BIG_ENDIAN, mpic->isus[isu],
|
||||
reg + (idx * MPIC_IRQ_STRIDE));
|
||||
reg + (idx * MPIC_INFO(IRQ_STRIDE)));
|
||||
}
|
||||
|
||||
static inline void _mpic_irq_write(struct mpic *mpic, unsigned int src_no,
|
||||
|
@ -130,7 +220,7 @@ static inline void _mpic_irq_write(struct mpic *mpic, unsigned int src_no,
|
|||
unsigned int idx = src_no & mpic->isu_mask;
|
||||
|
||||
_mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->isus[isu],
|
||||
reg + (idx * MPIC_IRQ_STRIDE), value);
|
||||
reg + (idx * MPIC_INFO(IRQ_STRIDE)), value);
|
||||
}
|
||||
|
||||
#define mpic_read(b,r) _mpic_read(mpic->flags & MPIC_BIG_ENDIAN,(b),(r))
|
||||
|
@ -156,8 +246,8 @@ static void __init mpic_test_broken_ipi(struct mpic *mpic)
|
|||
{
|
||||
u32 r;
|
||||
|
||||
mpic_write(mpic->gregs, MPIC_GREG_IPI_VECTOR_PRI_0, MPIC_VECPRI_MASK);
|
||||
r = mpic_read(mpic->gregs, MPIC_GREG_IPI_VECTOR_PRI_0);
|
||||
mpic_write(mpic->gregs, MPIC_INFO(GREG_IPI_VECTOR_PRI_0), MPIC_VECPRI_MASK);
|
||||
r = mpic_read(mpic->gregs, MPIC_INFO(GREG_IPI_VECTOR_PRI_0));
|
||||
|
||||
if (r == le32_to_cpu(MPIC_VECPRI_MASK)) {
|
||||
printk(KERN_INFO "mpic: Detected reversed IPI registers\n");
|
||||
|
@ -394,8 +484,8 @@ static inline struct mpic * mpic_from_irq(unsigned int irq)
|
|||
/* Send an EOI */
|
||||
static inline void mpic_eoi(struct mpic *mpic)
|
||||
{
|
||||
mpic_cpu_write(MPIC_CPU_EOI, 0);
|
||||
(void)mpic_cpu_read(MPIC_CPU_WHOAMI);
|
||||
mpic_cpu_write(MPIC_INFO(CPU_EOI), 0);
|
||||
(void)mpic_cpu_read(MPIC_INFO(CPU_WHOAMI));
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
|
@ -419,8 +509,8 @@ static void mpic_unmask_irq(unsigned int irq)
|
|||
|
||||
DBG("%p: %s: enable_irq: %d (src %d)\n", mpic, mpic->name, irq, src);
|
||||
|
||||
mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI,
|
||||
mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) &
|
||||
mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI),
|
||||
mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) &
|
||||
~MPIC_VECPRI_MASK);
|
||||
/* make sure mask gets to controller before we return to user */
|
||||
do {
|
||||
|
@ -428,7 +518,7 @@ static void mpic_unmask_irq(unsigned int irq)
|
|||
printk(KERN_ERR "mpic_enable_irq timeout\n");
|
||||
break;
|
||||
}
|
||||
} while(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK);
|
||||
} while(mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) & MPIC_VECPRI_MASK);
|
||||
}
|
||||
|
||||
static void mpic_mask_irq(unsigned int irq)
|
||||
|
@ -439,8 +529,8 @@ static void mpic_mask_irq(unsigned int irq)
|
|||
|
||||
DBG("%s: disable_irq: %d (src %d)\n", mpic->name, irq, src);
|
||||
|
||||
mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI,
|
||||
mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) |
|
||||
mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI),
|
||||
mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) |
|
||||
MPIC_VECPRI_MASK);
|
||||
|
||||
/* make sure mask gets to controller before we return to user */
|
||||
|
@ -449,7 +539,7 @@ static void mpic_mask_irq(unsigned int irq)
|
|||
printk(KERN_ERR "mpic_enable_irq timeout\n");
|
||||
break;
|
||||
}
|
||||
} while(!(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK));
|
||||
} while(!(mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) & MPIC_VECPRI_MASK));
|
||||
}
|
||||
|
||||
static void mpic_end_irq(unsigned int irq)
|
||||
|
@ -560,24 +650,28 @@ static void mpic_set_affinity(unsigned int irq, cpumask_t cpumask)
|
|||
|
||||
cpus_and(tmp, cpumask, cpu_online_map);
|
||||
|
||||
mpic_irq_write(src, MPIC_IRQ_DESTINATION,
|
||||
mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION),
|
||||
mpic_physmask(cpus_addr(tmp)[0]));
|
||||
}
|
||||
|
||||
static unsigned int mpic_type_to_vecpri(unsigned int type)
|
||||
static unsigned int mpic_type_to_vecpri(struct mpic *mpic, unsigned int type)
|
||||
{
|
||||
/* Now convert sense value */
|
||||
switch(type & IRQ_TYPE_SENSE_MASK) {
|
||||
case IRQ_TYPE_EDGE_RISING:
|
||||
return MPIC_VECPRI_SENSE_EDGE | MPIC_VECPRI_POLARITY_POSITIVE;
|
||||
return MPIC_INFO(VECPRI_SENSE_EDGE) |
|
||||
MPIC_INFO(VECPRI_POLARITY_POSITIVE);
|
||||
case IRQ_TYPE_EDGE_FALLING:
|
||||
case IRQ_TYPE_EDGE_BOTH:
|
||||
return MPIC_VECPRI_SENSE_EDGE | MPIC_VECPRI_POLARITY_NEGATIVE;
|
||||
return MPIC_INFO(VECPRI_SENSE_EDGE) |
|
||||
MPIC_INFO(VECPRI_POLARITY_NEGATIVE);
|
||||
case IRQ_TYPE_LEVEL_HIGH:
|
||||
return MPIC_VECPRI_SENSE_LEVEL | MPIC_VECPRI_POLARITY_POSITIVE;
|
||||
return MPIC_INFO(VECPRI_SENSE_LEVEL) |
|
||||
MPIC_INFO(VECPRI_POLARITY_POSITIVE);
|
||||
case IRQ_TYPE_LEVEL_LOW:
|
||||
default:
|
||||
return MPIC_VECPRI_SENSE_LEVEL | MPIC_VECPRI_POLARITY_NEGATIVE;
|
||||
return MPIC_INFO(VECPRI_SENSE_LEVEL) |
|
||||
MPIC_INFO(VECPRI_POLARITY_NEGATIVE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -609,13 +703,14 @@ static int mpic_set_irq_type(unsigned int virq, unsigned int flow_type)
|
|||
vecpri = MPIC_VECPRI_POLARITY_POSITIVE |
|
||||
MPIC_VECPRI_SENSE_EDGE;
|
||||
else
|
||||
vecpri = mpic_type_to_vecpri(flow_type);
|
||||
vecpri = mpic_type_to_vecpri(mpic, flow_type);
|
||||
|
||||
vold = mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI);
|
||||
vnew = vold & ~(MPIC_VECPRI_POLARITY_MASK | MPIC_VECPRI_SENSE_MASK);
|
||||
vold = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI));
|
||||
vnew = vold & ~(MPIC_INFO(VECPRI_POLARITY_MASK) |
|
||||
MPIC_INFO(VECPRI_SENSE_MASK));
|
||||
vnew |= vecpri;
|
||||
if (vold != vnew)
|
||||
mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI, vnew);
|
||||
mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI), vnew);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -798,17 +893,22 @@ struct mpic * __init mpic_alloc(struct device_node *node,
|
|||
mpic->irq_count = irq_count;
|
||||
mpic->num_sources = 0; /* so far */
|
||||
|
||||
#ifdef CONFIG_MPIC_WEIRD
|
||||
mpic->hw_set = mpic_infos[MPIC_GET_REGSET(flags)];
|
||||
#endif
|
||||
|
||||
/* Map the global registers */
|
||||
mpic->gregs = ioremap(phys_addr + MPIC_GREG_BASE, 0x1000);
|
||||
mpic->tmregs = mpic->gregs + ((MPIC_TIMER_BASE - MPIC_GREG_BASE) >> 2);
|
||||
mpic->gregs = ioremap(phys_addr + MPIC_INFO(GREG_BASE), 0x1000);
|
||||
mpic->tmregs = mpic->gregs +
|
||||
((MPIC_INFO(TIMER_BASE) - MPIC_INFO(GREG_BASE)) >> 2);
|
||||
BUG_ON(mpic->gregs == NULL);
|
||||
|
||||
/* Reset */
|
||||
if (flags & MPIC_WANTS_RESET) {
|
||||
mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0,
|
||||
mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0)
|
||||
mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0),
|
||||
mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
|
||||
| MPIC_GREG_GCONF_RESET);
|
||||
while( mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0)
|
||||
while( mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
|
||||
& MPIC_GREG_GCONF_RESET)
|
||||
mb();
|
||||
}
|
||||
|
@ -817,7 +917,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,
|
|||
* MPICs, num sources as well. On ISU MPICs, sources are counted
|
||||
* as ISUs are added
|
||||
*/
|
||||
reg = mpic_read(mpic->gregs, MPIC_GREG_FEATURE_0);
|
||||
reg = mpic_read(mpic->gregs, MPIC_INFO(GREG_FEATURE_0));
|
||||
mpic->num_cpus = ((reg & MPIC_GREG_FEATURE_LAST_CPU_MASK)
|
||||
>> MPIC_GREG_FEATURE_LAST_CPU_SHIFT) + 1;
|
||||
if (isu_size == 0)
|
||||
|
@ -826,16 +926,16 @@ struct mpic * __init mpic_alloc(struct device_node *node,
|
|||
|
||||
/* Map the per-CPU registers */
|
||||
for (i = 0; i < mpic->num_cpus; i++) {
|
||||
mpic->cpuregs[i] = ioremap(phys_addr + MPIC_CPU_BASE +
|
||||
i * MPIC_CPU_STRIDE, 0x1000);
|
||||
mpic->cpuregs[i] = ioremap(phys_addr + MPIC_INFO(CPU_BASE) +
|
||||
i * MPIC_INFO(CPU_STRIDE), 0x1000);
|
||||
BUG_ON(mpic->cpuregs[i] == NULL);
|
||||
}
|
||||
|
||||
/* Initialize main ISU if none provided */
|
||||
if (mpic->isu_size == 0) {
|
||||
mpic->isu_size = mpic->num_sources;
|
||||
mpic->isus[0] = ioremap(phys_addr + MPIC_IRQ_BASE,
|
||||
MPIC_IRQ_STRIDE * mpic->isu_size);
|
||||
mpic->isus[0] = ioremap(phys_addr + MPIC_INFO(IRQ_BASE),
|
||||
MPIC_INFO(IRQ_STRIDE) * mpic->isu_size);
|
||||
BUG_ON(mpic->isus[0] == NULL);
|
||||
}
|
||||
mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1);
|
||||
|
@ -879,7 +979,8 @@ void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num,
|
|||
|
||||
BUG_ON(isu_num >= MPIC_MAX_ISU);
|
||||
|
||||
mpic->isus[isu_num] = ioremap(phys_addr, MPIC_IRQ_STRIDE * mpic->isu_size);
|
||||
mpic->isus[isu_num] = ioremap(phys_addr,
|
||||
MPIC_INFO(IRQ_STRIDE) * mpic->isu_size);
|
||||
if ((isu_first + mpic->isu_size) > mpic->num_sources)
|
||||
mpic->num_sources = isu_first + mpic->isu_size;
|
||||
}
|
||||
|
@ -904,14 +1005,16 @@ void __init mpic_init(struct mpic *mpic)
|
|||
printk(KERN_INFO "mpic: Initializing for %d sources\n", mpic->num_sources);
|
||||
|
||||
/* Set current processor priority to max */
|
||||
mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0xf);
|
||||
mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0xf);
|
||||
|
||||
/* Initialize timers: just disable them all */
|
||||
for (i = 0; i < 4; i++) {
|
||||
mpic_write(mpic->tmregs,
|
||||
i * MPIC_TIMER_STRIDE + MPIC_TIMER_DESTINATION, 0);
|
||||
i * MPIC_INFO(TIMER_STRIDE) +
|
||||
MPIC_INFO(TIMER_DESTINATION), 0);
|
||||
mpic_write(mpic->tmregs,
|
||||
i * MPIC_TIMER_STRIDE + MPIC_TIMER_VECTOR_PRI,
|
||||
i * MPIC_INFO(TIMER_STRIDE) +
|
||||
MPIC_INFO(TIMER_VECTOR_PRI),
|
||||
MPIC_VECPRI_MASK |
|
||||
(MPIC_VEC_TIMER_0 + i));
|
||||
}
|
||||
|
@ -940,21 +1043,22 @@ void __init mpic_init(struct mpic *mpic)
|
|||
(8 << MPIC_VECPRI_PRIORITY_SHIFT);
|
||||
|
||||
/* init hw */
|
||||
mpic_irq_write(i, MPIC_IRQ_VECTOR_PRI, vecpri);
|
||||
mpic_irq_write(i, MPIC_IRQ_DESTINATION,
|
||||
mpic_irq_write(i, MPIC_INFO(IRQ_VECTOR_PRI), vecpri);
|
||||
mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION),
|
||||
1 << hard_smp_processor_id());
|
||||
}
|
||||
|
||||
/* Init spurrious vector */
|
||||
mpic_write(mpic->gregs, MPIC_GREG_SPURIOUS, MPIC_VEC_SPURRIOUS);
|
||||
mpic_write(mpic->gregs, MPIC_INFO(GREG_SPURIOUS), MPIC_VEC_SPURRIOUS);
|
||||
|
||||
/* Disable 8259 passthrough */
|
||||
mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0,
|
||||
mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0)
|
||||
/* Disable 8259 passthrough, if supported */
|
||||
if (!(mpic->flags & MPIC_NO_PTHROU_DIS))
|
||||
mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0),
|
||||
mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
|
||||
| MPIC_GREG_GCONF_8259_PTHROU_DIS);
|
||||
|
||||
/* Set current processor priority to 0 */
|
||||
mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0);
|
||||
mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0);
|
||||
}
|
||||
|
||||
void __init mpic_set_clk_ratio(struct mpic *mpic, u32 clock_ratio)
|
||||
|
@ -997,9 +1101,9 @@ void mpic_irq_set_priority(unsigned int irq, unsigned int pri)
|
|||
mpic_ipi_write(src - MPIC_VEC_IPI_0,
|
||||
reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT));
|
||||
} else {
|
||||
reg = mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI)
|
||||
reg = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI))
|
||||
& ~MPIC_VECPRI_PRIORITY_MASK;
|
||||
mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI,
|
||||
mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI),
|
||||
reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT));
|
||||
}
|
||||
spin_unlock_irqrestore(&mpic_lock, flags);
|
||||
|
@ -1017,7 +1121,7 @@ unsigned int mpic_irq_get_priority(unsigned int irq)
|
|||
if (is_ipi)
|
||||
reg = mpic_ipi_read(src = MPIC_VEC_IPI_0);
|
||||
else
|
||||
reg = mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI);
|
||||
reg = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI));
|
||||
spin_unlock_irqrestore(&mpic_lock, flags);
|
||||
return (reg & MPIC_VECPRI_PRIORITY_MASK) >> MPIC_VECPRI_PRIORITY_SHIFT;
|
||||
}
|
||||
|
@ -1043,12 +1147,12 @@ void mpic_setup_this_cpu(void)
|
|||
*/
|
||||
if (distribute_irqs) {
|
||||
for (i = 0; i < mpic->num_sources ; i++)
|
||||
mpic_irq_write(i, MPIC_IRQ_DESTINATION,
|
||||
mpic_irq_read(i, MPIC_IRQ_DESTINATION) | msk);
|
||||
mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION),
|
||||
mpic_irq_read(i, MPIC_INFO(IRQ_DESTINATION)) | msk);
|
||||
}
|
||||
|
||||
/* Set current processor priority to 0 */
|
||||
mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0);
|
||||
mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0);
|
||||
|
||||
spin_unlock_irqrestore(&mpic_lock, flags);
|
||||
#endif /* CONFIG_SMP */
|
||||
|
@ -1058,7 +1162,7 @@ int mpic_cpu_get_priority(void)
|
|||
{
|
||||
struct mpic *mpic = mpic_primary;
|
||||
|
||||
return mpic_cpu_read(MPIC_CPU_CURRENT_TASK_PRI);
|
||||
return mpic_cpu_read(MPIC_INFO(CPU_CURRENT_TASK_PRI));
|
||||
}
|
||||
|
||||
void mpic_cpu_set_priority(int prio)
|
||||
|
@ -1066,7 +1170,7 @@ void mpic_cpu_set_priority(int prio)
|
|||
struct mpic *mpic = mpic_primary;
|
||||
|
||||
prio &= MPIC_CPU_TASKPRI_MASK;
|
||||
mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, prio);
|
||||
mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), prio);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1088,11 +1192,11 @@ void mpic_teardown_this_cpu(int secondary)
|
|||
|
||||
/* let the mpic know we don't want intrs. */
|
||||
for (i = 0; i < mpic->num_sources ; i++)
|
||||
mpic_irq_write(i, MPIC_IRQ_DESTINATION,
|
||||
mpic_irq_read(i, MPIC_IRQ_DESTINATION) & ~msk);
|
||||
mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION),
|
||||
mpic_irq_read(i, MPIC_INFO(IRQ_DESTINATION)) & ~msk);
|
||||
|
||||
/* Set current processor priority to max */
|
||||
mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0xf);
|
||||
mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0xf);
|
||||
|
||||
spin_unlock_irqrestore(&mpic_lock, flags);
|
||||
}
|
||||
|
@ -1108,7 +1212,8 @@ void mpic_send_ipi(unsigned int ipi_no, unsigned int cpu_mask)
|
|||
DBG("%s: send_ipi(ipi_no: %d)\n", mpic->name, ipi_no);
|
||||
#endif
|
||||
|
||||
mpic_cpu_write(MPIC_CPU_IPI_DISPATCH_0 + ipi_no * 0x10,
|
||||
mpic_cpu_write(MPIC_INFO(CPU_IPI_DISPATCH_0) +
|
||||
ipi_no * MPIC_INFO(CPU_IPI_DISPATCH_STRIDE),
|
||||
mpic_physmask(cpu_mask & cpus_addr(cpu_online_map)[0]));
|
||||
}
|
||||
|
||||
|
@ -1116,7 +1221,7 @@ unsigned int mpic_get_one_irq(struct mpic *mpic, struct pt_regs *regs)
|
|||
{
|
||||
u32 src;
|
||||
|
||||
src = mpic_cpu_read(MPIC_CPU_INTACK) & MPIC_VECPRI_VECTOR_MASK;
|
||||
src = mpic_cpu_read(MPIC_INFO(CPU_INTACK)) & MPIC_INFO(VECPRI_VECTOR_MASK);
|
||||
#ifdef DEBUG_LOW
|
||||
DBG("%s: get_one_irq(): %d\n", mpic->name, src);
|
||||
#endif
|
||||
|
|
|
@ -47,8 +47,9 @@ void __devinit
|
|||
smp_generic_take_timebase( void )
|
||||
{
|
||||
int cmd, tbl, tbu;
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_disable();
|
||||
local_irq_save(flags);
|
||||
while( !running )
|
||||
;
|
||||
rmb();
|
||||
|
@ -64,7 +65,7 @@ smp_generic_take_timebase( void )
|
|||
tbu = tbsync->tbu;
|
||||
tbsync->ack = 0;
|
||||
if( cmd == kExit )
|
||||
return;
|
||||
break;
|
||||
|
||||
if( cmd == kSetAndTest ) {
|
||||
while( tbsync->handshake )
|
||||
|
@ -77,7 +78,7 @@ smp_generic_take_timebase( void )
|
|||
}
|
||||
enter_contest( tbsync->mark, -1 );
|
||||
}
|
||||
local_irq_enable();
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static int __devinit
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <linux/initrd.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/fsl_devices.h>
|
||||
#include <linux/fs_enet_pd.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <asm/pgtable.h>
|
||||
|
@ -58,6 +59,71 @@
|
|||
* Setup the architecture
|
||||
*
|
||||
*/
|
||||
static void init_fcc_ioports(void)
|
||||
{
|
||||
struct immap *immap;
|
||||
struct io_port *io;
|
||||
u32 tempval;
|
||||
|
||||
immap = cpm2_immr;
|
||||
|
||||
io = &immap->im_ioport;
|
||||
/* FCC2/3 are on the ports B/C. */
|
||||
tempval = in_be32(&io->iop_pdirb);
|
||||
tempval &= ~PB2_DIRB0;
|
||||
tempval |= PB2_DIRB1;
|
||||
out_be32(&io->iop_pdirb, tempval);
|
||||
|
||||
tempval = in_be32(&io->iop_psorb);
|
||||
tempval &= ~PB2_PSORB0;
|
||||
tempval |= PB2_PSORB1;
|
||||
out_be32(&io->iop_psorb, tempval);
|
||||
|
||||
tempval = in_be32(&io->iop_pparb);
|
||||
tempval |= (PB2_DIRB0 | PB2_DIRB1);
|
||||
out_be32(&io->iop_pparb, tempval);
|
||||
|
||||
tempval = in_be32(&io->iop_pdirb);
|
||||
tempval &= ~PB3_DIRB0;
|
||||
tempval |= PB3_DIRB1;
|
||||
out_be32(&io->iop_pdirb, tempval);
|
||||
|
||||
tempval = in_be32(&io->iop_psorb);
|
||||
tempval &= ~PB3_PSORB0;
|
||||
tempval |= PB3_PSORB1;
|
||||
out_be32(&io->iop_psorb, tempval);
|
||||
|
||||
tempval = in_be32(&io->iop_pparb);
|
||||
tempval |= (PB3_DIRB0 | PB3_DIRB1);
|
||||
out_be32(&io->iop_pparb, tempval);
|
||||
|
||||
tempval = in_be32(&io->iop_pdirc);
|
||||
tempval |= PC3_DIRC1;
|
||||
out_be32(&io->iop_pdirc, tempval);
|
||||
|
||||
tempval = in_be32(&io->iop_pparc);
|
||||
tempval |= PC3_DIRC1;
|
||||
out_be32(&io->iop_pparc, tempval);
|
||||
|
||||
/* Port C has clocks...... */
|
||||
tempval = in_be32(&io->iop_psorc);
|
||||
tempval &= ~(CLK_TRX);
|
||||
out_be32(&io->iop_psorc, tempval);
|
||||
|
||||
tempval = in_be32(&io->iop_pdirc);
|
||||
tempval &= ~(CLK_TRX);
|
||||
out_be32(&io->iop_pdirc, tempval);
|
||||
tempval = in_be32(&io->iop_pparc);
|
||||
tempval |= (CLK_TRX);
|
||||
out_be32(&io->iop_pparc, tempval);
|
||||
|
||||
/* Configure Serial Interface clock routing.
|
||||
* First, clear all FCC bits to zero,
|
||||
* then set the ones we want.
|
||||
*/
|
||||
immap->im_cpmux.cmx_fcr &= ~(CPMUX_CLK_MASK);
|
||||
immap->im_cpmux.cmx_fcr |= CPMUX_CLK_ROUTE;
|
||||
}
|
||||
|
||||
static void __init
|
||||
mpc8560ads_setup_arch(void)
|
||||
|
@ -66,6 +132,7 @@ mpc8560ads_setup_arch(void)
|
|||
unsigned int freq;
|
||||
struct gianfar_platform_data *pdata;
|
||||
struct gianfar_mdio_data *mdata;
|
||||
struct fs_platform_info *fpi;
|
||||
|
||||
cpm2_reset();
|
||||
|
||||
|
@ -110,6 +177,28 @@ mpc8560ads_setup_arch(void)
|
|||
memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
|
||||
}
|
||||
|
||||
init_fcc_ioports();
|
||||
ppc_sys_device_remove(MPC85xx_CPM_FCC1);
|
||||
|
||||
fpi = (struct fs_platform_info *) ppc_sys_get_pdata(MPC85xx_CPM_FCC2);
|
||||
if (fpi) {
|
||||
memcpy(fpi->macaddr, binfo->bi_enet2addr, 6);
|
||||
fpi->bus_id = "0:02";
|
||||
fpi->phy_addr = 2;
|
||||
fpi->dpram_offset = (u32)cpm2_immr->im_dprambase;
|
||||
fpi->fcc_regs_c = (u32)&cpm2_immr->im_fcc_c[1];
|
||||
}
|
||||
|
||||
fpi = (struct fs_platform_info *) ppc_sys_get_pdata(MPC85xx_CPM_FCC3);
|
||||
if (fpi) {
|
||||
memcpy(fpi->macaddr, binfo->bi_enet2addr, 6);
|
||||
fpi->macaddr[5] += 1;
|
||||
fpi->bus_id = "0:03";
|
||||
fpi->phy_addr = 3;
|
||||
fpi->dpram_offset = (u32)cpm2_immr->im_dprambase;
|
||||
fpi->fcc_regs_c = (u32)&cpm2_immr->im_fcc_c[2];
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_INITRD
|
||||
if (initrd_start)
|
||||
ROOT_DEV = Root_RAM0;
|
||||
|
|
|
@ -45,4 +45,23 @@ extern void mpc85xx_ads_map_io(void) __init;
|
|||
|
||||
#define MPC85XX_PCI1_IO_SIZE 0x01000000
|
||||
|
||||
/* FCC1 Clock Source Configuration. These can be
|
||||
* redefined in the board specific file.
|
||||
* Can only choose from CLK9-12 */
|
||||
#define F1_RXCLK 12
|
||||
#define F1_TXCLK 11
|
||||
|
||||
/* FCC2 Clock Source Configuration. These can be
|
||||
* redefined in the board specific file.
|
||||
* Can only choose from CLK13-16 */
|
||||
#define F2_RXCLK 13
|
||||
#define F2_TXCLK 14
|
||||
|
||||
/* FCC3 Clock Source Configuration. These can be
|
||||
* redefined in the board specific file.
|
||||
* Can only choose from CLK13-16 */
|
||||
#define F3_RXCLK 15
|
||||
#define F3_TXCLK 16
|
||||
|
||||
|
||||
#endif /* __MACH_MPC85XX_ADS_H__ */
|
||||
|
|
|
@ -56,43 +56,34 @@ static struct fs_uart_platform_info mpc8272_uart_pdata[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct fs_mii_bus_info mii_bus_info = {
|
||||
.method = fsmii_bitbang,
|
||||
.id = 0,
|
||||
.i.bitbang = {
|
||||
.mdio_port = fsiop_portc,
|
||||
.mdio_bit = 18,
|
||||
.mdc_port = fsiop_portc,
|
||||
.mdc_bit = 19,
|
||||
static struct fs_mii_bb_platform_info m82xx_mii_bb_pdata = {
|
||||
.mdio_dat.bit = 18,
|
||||
.mdio_dir.bit = 18,
|
||||
.mdc_dat.bit = 19,
|
||||
.delay = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct fs_platform_info mpc82xx_fcc1_pdata = {
|
||||
static struct fs_platform_info mpc82xx_enet_pdata[] = {
|
||||
[fsid_fcc1] = {
|
||||
.fs_no = fsid_fcc1,
|
||||
.cp_page = CPM_CR_FCC1_PAGE,
|
||||
.cp_block = CPM_CR_FCC1_SBLOCK,
|
||||
|
||||
.clk_trx = (PC_F1RXCLK | PC_F1TXCLK),
|
||||
.clk_route = CMX1_CLK_ROUTE,
|
||||
.clk_mask = CMX1_CLK_MASK,
|
||||
.init_ioports = init_fcc1_ioports,
|
||||
|
||||
.phy_addr = 0,
|
||||
#ifdef PHY_INTERRUPT
|
||||
.phy_irq = PHY_INTERRUPT,
|
||||
#else
|
||||
.phy_irq = -1;
|
||||
#endif
|
||||
.mem_offset = FCC1_MEM_OFFSET,
|
||||
.bus_info = &mii_bus_info,
|
||||
|
||||
.rx_ring = 32,
|
||||
.tx_ring = 32,
|
||||
.rx_copybreak = 240,
|
||||
.use_napi = 0,
|
||||
.napi_weight = 17,
|
||||
};
|
||||
|
||||
static struct fs_platform_info mpc82xx_fcc2_pdata = {
|
||||
.bus_id = "0:00",
|
||||
},
|
||||
[fsid_fcc2] = {
|
||||
.fs_no = fsid_fcc2,
|
||||
.cp_page = CPM_CR_FCC2_PAGE,
|
||||
.cp_block = CPM_CR_FCC2_SBLOCK,
|
||||
|
@ -101,19 +92,15 @@ static struct fs_platform_info mpc82xx_fcc2_pdata = {
|
|||
.clk_mask = CMX2_CLK_MASK,
|
||||
.init_ioports = init_fcc2_ioports,
|
||||
|
||||
.phy_addr = 3,
|
||||
#ifdef PHY_INTERRUPT
|
||||
.phy_irq = PHY_INTERRUPT,
|
||||
#else
|
||||
.phy_irq = -1;
|
||||
#endif
|
||||
.mem_offset = FCC2_MEM_OFFSET,
|
||||
.bus_info = &mii_bus_info,
|
||||
|
||||
.rx_ring = 32,
|
||||
.tx_ring = 32,
|
||||
.rx_copybreak = 240,
|
||||
.use_napi = 0,
|
||||
.napi_weight = 17,
|
||||
.bus_id = "0:03",
|
||||
},
|
||||
};
|
||||
|
||||
static void init_fcc1_ioports(void)
|
||||
|
@ -209,20 +196,21 @@ static void __init mpc8272ads_fixup_enet_pdata(struct platform_device *pdev,
|
|||
bd_t* bi = (void*)__res;
|
||||
int fs_no = fsid_fcc1+pdev->id-1;
|
||||
|
||||
mpc82xx_fcc1_pdata.dpram_offset = mpc82xx_fcc2_pdata.dpram_offset = (u32)cpm2_immr->im_dprambase;
|
||||
mpc82xx_fcc1_pdata.fcc_regs_c = mpc82xx_fcc2_pdata.fcc_regs_c = (u32)cpm2_immr->im_fcc_c;
|
||||
|
||||
switch(fs_no) {
|
||||
case fsid_fcc1:
|
||||
memcpy(&mpc82xx_fcc1_pdata.macaddr,bi->bi_enetaddr,6);
|
||||
pdev->dev.platform_data = &mpc82xx_fcc1_pdata;
|
||||
break;
|
||||
case fsid_fcc2:
|
||||
memcpy(&mpc82xx_fcc2_pdata.macaddr,bi->bi_enetaddr,6);
|
||||
mpc82xx_fcc2_pdata.macaddr[5] ^= 1;
|
||||
pdev->dev.platform_data = &mpc82xx_fcc2_pdata;
|
||||
break;
|
||||
if(fs_no > ARRAY_SIZE(mpc82xx_enet_pdata)) {
|
||||
return;
|
||||
}
|
||||
|
||||
mpc82xx_enet_pdata[fs_no].dpram_offset=
|
||||
(u32)cpm2_immr->im_dprambase;
|
||||
mpc82xx_enet_pdata[fs_no].fcc_regs_c =
|
||||
(u32)cpm2_immr->im_fcc_c;
|
||||
memcpy(&mpc82xx_enet_pdata[fs_no].macaddr,bi->bi_enetaddr,6);
|
||||
|
||||
/* prevent dup mac */
|
||||
if(fs_no == fsid_fcc2)
|
||||
mpc82xx_enet_pdata[fs_no].macaddr[5] ^= 1;
|
||||
|
||||
pdev->dev.platform_data = &mpc82xx_enet_pdata[fs_no];
|
||||
}
|
||||
|
||||
static void mpc8272ads_fixup_uart_pdata(struct platform_device *pdev,
|
||||
|
@ -274,6 +262,29 @@ static void init_scc4_uart_ioports(void)
|
|||
iounmap(immap);
|
||||
}
|
||||
|
||||
static void __init mpc8272ads_fixup_mdio_pdata(struct platform_device *pdev,
|
||||
int idx)
|
||||
{
|
||||
m82xx_mii_bb_pdata.irq[0] = PHY_INTERRUPT;
|
||||
m82xx_mii_bb_pdata.irq[1] = -1;
|
||||
m82xx_mii_bb_pdata.irq[2] = -1;
|
||||
m82xx_mii_bb_pdata.irq[3] = PHY_INTERRUPT;
|
||||
m82xx_mii_bb_pdata.irq[31] = -1;
|
||||
|
||||
|
||||
m82xx_mii_bb_pdata.mdio_dat.offset =
|
||||
(u32)&cpm2_immr->im_ioport.iop_pdatc;
|
||||
|
||||
m82xx_mii_bb_pdata.mdio_dir.offset =
|
||||
(u32)&cpm2_immr->im_ioport.iop_pdirc;
|
||||
|
||||
m82xx_mii_bb_pdata.mdc_dat.offset =
|
||||
(u32)&cpm2_immr->im_ioport.iop_pdatc;
|
||||
|
||||
|
||||
pdev->dev.platform_data = &m82xx_mii_bb_pdata;
|
||||
}
|
||||
|
||||
static int mpc8272ads_platform_notify(struct device *dev)
|
||||
{
|
||||
static const struct platform_notify_dev_map dev_map[] = {
|
||||
|
@ -285,6 +296,10 @@ static int mpc8272ads_platform_notify(struct device *dev)
|
|||
.bus_id = "fsl-cpm-scc:uart",
|
||||
.rtn = mpc8272ads_fixup_uart_pdata,
|
||||
},
|
||||
{
|
||||
.bus_id = "fsl-bb-mdio",
|
||||
.rtn = mpc8272ads_fixup_mdio_pdata,
|
||||
},
|
||||
{
|
||||
.bus_id = NULL
|
||||
}
|
||||
|
@ -319,6 +334,7 @@ int __init mpc8272ads_init(void)
|
|||
ppc_sys_device_enable(MPC82xx_CPM_SCC4);
|
||||
#endif
|
||||
|
||||
ppc_sys_device_enable(MPC82xx_MDIO_BB);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/*arch/ppc/platforms/mpc885ads-setup.c
|
||||
/*arch/ppc/platforms/mpc866ads-setup.c
|
||||
*
|
||||
* Platform setup for the Freescale mpc885ads board
|
||||
* Platform setup for the Freescale mpc866ads board
|
||||
*
|
||||
* Vitaly Bordug <vbordug@ru.mvista.com>
|
||||
*
|
||||
* Copyright 2005 MontaVista Software Inc.
|
||||
* Copyright 2005-2006 MontaVista Software Inc.
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public License
|
||||
* version 2. This program is licensed "as is" without any warranty of any
|
||||
|
@ -42,20 +42,12 @@ static void setup_scc1_ioports(void);
|
|||
static void setup_smc1_ioports(void);
|
||||
static void setup_smc2_ioports(void);
|
||||
|
||||
static struct fs_mii_bus_info fec_mii_bus_info = {
|
||||
.method = fsmii_fec,
|
||||
.id = 0,
|
||||
};
|
||||
static struct fs_mii_fec_platform_info mpc8xx_mdio_fec_pdata;
|
||||
|
||||
static struct fs_mii_bus_info scc_mii_bus_info = {
|
||||
.method = fsmii_fixed,
|
||||
.id = 0,
|
||||
.i.fixed.speed = 10,
|
||||
.i.fixed.duplex = 0,
|
||||
};
|
||||
static struct fs_mii_fec_platform_info mpc8xx_mdio_fec_pdata;
|
||||
|
||||
static struct fs_platform_info mpc8xx_fec_pdata[] = {
|
||||
{
|
||||
static struct fs_platform_info mpc8xx_enet_pdata[] = {
|
||||
[fsid_fec1] = {
|
||||
.rx_ring = 128,
|
||||
.tx_ring = 16,
|
||||
.rx_copybreak = 240,
|
||||
|
@ -63,28 +55,23 @@ static struct fs_platform_info mpc8xx_fec_pdata[] = {
|
|||
.use_napi = 1,
|
||||
.napi_weight = 17,
|
||||
|
||||
.phy_addr = 15,
|
||||
.phy_irq = -1,
|
||||
.init_ioports = setup_fec1_ioports,
|
||||
|
||||
.use_rmii = 0,
|
||||
|
||||
.bus_info = &fec_mii_bus_info,
|
||||
}
|
||||
};
|
||||
|
||||
static struct fs_platform_info mpc8xx_scc_pdata = {
|
||||
.bus_id = "0:0f",
|
||||
.has_phy = 1,
|
||||
},
|
||||
[fsid_scc1] = {
|
||||
.rx_ring = 64,
|
||||
.tx_ring = 8,
|
||||
.rx_copybreak = 240,
|
||||
|
||||
.use_napi = 1,
|
||||
.napi_weight = 17,
|
||||
|
||||
.phy_addr = -1,
|
||||
.phy_irq = -1,
|
||||
|
||||
.bus_info = &scc_mii_bus_info,
|
||||
.init_ioports = setup_scc1_ioports,
|
||||
|
||||
.bus_id = "fixed@100:1",
|
||||
},
|
||||
};
|
||||
|
||||
static struct fs_uart_platform_info mpc866_uart_pdata[] = {
|
||||
|
@ -207,63 +194,6 @@ static void setup_scc1_ioports(void)
|
|||
|
||||
}
|
||||
|
||||
static void mpc866ads_fixup_enet_pdata(struct platform_device *pdev, int fs_no)
|
||||
{
|
||||
struct fs_platform_info *fpi = pdev->dev.platform_data;
|
||||
|
||||
volatile cpm8xx_t *cp;
|
||||
bd_t *bd = (bd_t *) __res;
|
||||
char *e;
|
||||
int i;
|
||||
|
||||
/* Get pointer to Communication Processor */
|
||||
cp = cpmp;
|
||||
switch (fs_no) {
|
||||
case fsid_fec1:
|
||||
fpi = &mpc8xx_fec_pdata[0];
|
||||
fpi->init_ioports = &setup_fec1_ioports;
|
||||
|
||||
break;
|
||||
case fsid_scc1:
|
||||
fpi = &mpc8xx_scc_pdata;
|
||||
fpi->init_ioports = &setup_scc1_ioports;
|
||||
|
||||
break;
|
||||
default:
|
||||
printk(KERN_WARNING"Device %s is not supported!\n", pdev->name);
|
||||
return;
|
||||
}
|
||||
|
||||
pdev->dev.platform_data = fpi;
|
||||
fpi->fs_no = fs_no;
|
||||
|
||||
e = (unsigned char *)&bd->bi_enetaddr;
|
||||
for (i = 0; i < 6; i++)
|
||||
fpi->macaddr[i] = *e++;
|
||||
|
||||
fpi->macaddr[5 - pdev->id]++;
|
||||
|
||||
}
|
||||
|
||||
static void mpc866ads_fixup_fec_enet_pdata(struct platform_device *pdev,
|
||||
int idx)
|
||||
{
|
||||
/* This is for FEC devices only */
|
||||
if (!pdev || !pdev->name || (!strstr(pdev->name, "fsl-cpm-fec")))
|
||||
return;
|
||||
mpc866ads_fixup_enet_pdata(pdev, fsid_fec1 + pdev->id - 1);
|
||||
}
|
||||
|
||||
static void mpc866ads_fixup_scc_enet_pdata(struct platform_device *pdev,
|
||||
int idx)
|
||||
{
|
||||
/* This is for SCC devices only */
|
||||
if (!pdev || !pdev->name || (!strstr(pdev->name, "fsl-cpm-scc")))
|
||||
return;
|
||||
|
||||
mpc866ads_fixup_enet_pdata(pdev, fsid_scc1 + pdev->id - 1);
|
||||
}
|
||||
|
||||
static void setup_smc1_ioports(void)
|
||||
{
|
||||
immap_t *immap = (immap_t *) IMAP_ADDR;
|
||||
|
@ -315,6 +245,56 @@ static void setup_smc2_ioports(void)
|
|||
|
||||
}
|
||||
|
||||
static int ma_count = 0;
|
||||
|
||||
static void mpc866ads_fixup_enet_pdata(struct platform_device *pdev, int fs_no)
|
||||
{
|
||||
struct fs_platform_info *fpi;
|
||||
|
||||
volatile cpm8xx_t *cp;
|
||||
bd_t *bd = (bd_t *) __res;
|
||||
char *e;
|
||||
int i;
|
||||
|
||||
/* Get pointer to Communication Processor */
|
||||
cp = cpmp;
|
||||
|
||||
if(fs_no > ARRAY_SIZE(mpc8xx_enet_pdata)) {
|
||||
printk(KERN_ERR"No network-suitable #%d device on bus", fs_no);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
fpi = &mpc8xx_enet_pdata[fs_no];
|
||||
fpi->fs_no = fs_no;
|
||||
pdev->dev.platform_data = fpi;
|
||||
|
||||
e = (unsigned char *)&bd->bi_enetaddr;
|
||||
for (i = 0; i < 6; i++)
|
||||
fpi->macaddr[i] = *e++;
|
||||
|
||||
fpi->macaddr[5] += ma_count++;
|
||||
}
|
||||
|
||||
static void mpc866ads_fixup_fec_enet_pdata(struct platform_device *pdev,
|
||||
int idx)
|
||||
{
|
||||
/* This is for FEC devices only */
|
||||
if (!pdev || !pdev->name || (!strstr(pdev->name, "fsl-cpm-fec")))
|
||||
return;
|
||||
mpc866ads_fixup_enet_pdata(pdev, fsid_fec1 + pdev->id - 1);
|
||||
}
|
||||
|
||||
static void mpc866ads_fixup_scc_enet_pdata(struct platform_device *pdev,
|
||||
int idx)
|
||||
{
|
||||
/* This is for SCC devices only */
|
||||
if (!pdev || !pdev->name || (!strstr(pdev->name, "fsl-cpm-scc")))
|
||||
return;
|
||||
|
||||
mpc866ads_fixup_enet_pdata(pdev, fsid_scc1 + pdev->id - 1);
|
||||
}
|
||||
|
||||
static void __init mpc866ads_fixup_uart_pdata(struct platform_device *pdev,
|
||||
int idx)
|
||||
{
|
||||
|
@ -359,6 +339,9 @@ static int mpc866ads_platform_notify(struct device *dev)
|
|||
|
||||
int __init mpc866ads_init(void)
|
||||
{
|
||||
bd_t *bd = (bd_t *) __res;
|
||||
struct fs_mii_fec_platform_info* fmpi;
|
||||
|
||||
printk(KERN_NOTICE "mpc866ads: Init\n");
|
||||
|
||||
platform_notify = mpc866ads_platform_notify;
|
||||
|
@ -366,11 +349,20 @@ int __init mpc866ads_init(void)
|
|||
ppc_sys_device_initfunc();
|
||||
ppc_sys_device_disable_all();
|
||||
|
||||
#ifdef MPC8xx_SECOND_ETH_SCC1
|
||||
#ifdef CONFIG_MPC8xx_SECOND_ETH_SCC1
|
||||
ppc_sys_device_enable(MPC8xx_CPM_SCC1);
|
||||
#endif
|
||||
ppc_sys_device_enable(MPC8xx_CPM_FEC1);
|
||||
|
||||
ppc_sys_device_enable(MPC8xx_MDIO_FEC);
|
||||
|
||||
fmpi = ppc_sys_platform_devices[MPC8xx_MDIO_FEC].dev.platform_data =
|
||||
&mpc8xx_mdio_fec_pdata;
|
||||
|
||||
fmpi->mii_speed = ((((bd->bi_intfreq + 4999999) / 2500000) / 2) & 0x3F) << 1;
|
||||
/* No PHY interrupt line here */
|
||||
fmpi->irq[0xf] = -1;
|
||||
|
||||
/* Since either of the uarts could be used as console, they need to ready */
|
||||
#ifdef CONFIG_SERIAL_CPM_SMC1
|
||||
ppc_sys_device_enable(MPC8xx_CPM_SMC1);
|
||||
|
@ -381,6 +373,14 @@ int __init mpc866ads_init(void)
|
|||
ppc_sys_device_enable(MPC8xx_CPM_SMC2);
|
||||
ppc_sys_device_setfunc(MPC8xx_CPM_SMC2, PPC_SYS_FUNC_UART);
|
||||
#endif
|
||||
ppc_sys_device_enable(MPC8xx_MDIO_FEC);
|
||||
|
||||
fmpi = ppc_sys_platform_devices[MPC8xx_MDIO_FEC].dev.platform_data =
|
||||
&mpc8xx_mdio_fec_pdata;
|
||||
|
||||
fmpi->mii_speed = ((((bd->bi_intfreq + 4999999) / 2500000) / 2) & 0x3F) << 1;
|
||||
/* No PHY interrupt line here */
|
||||
fmpi->irq[0xf] = -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -38,7 +38,10 @@ extern unsigned char __res[];
|
|||
static void setup_smc1_ioports(void);
|
||||
static void setup_smc2_ioports(void);
|
||||
|
||||
static void __init mpc885ads_scc_phy_init(char);
|
||||
static struct fs_mii_fec_platform_info mpc8xx_mdio_fec_pdata;
|
||||
static void setup_fec1_ioports(void);
|
||||
static void setup_fec2_ioports(void);
|
||||
static void setup_scc3_ioports(void);
|
||||
|
||||
static struct fs_uart_platform_info mpc885_uart_pdata[] = {
|
||||
[fsid_smc1_uart] = {
|
||||
|
@ -61,23 +64,8 @@ static struct fs_uart_platform_info mpc885_uart_pdata[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct fs_mii_bus_info fec_mii_bus_info = {
|
||||
.method = fsmii_fec,
|
||||
.id = 0,
|
||||
};
|
||||
|
||||
static struct fs_mii_bus_info scc_mii_bus_info = {
|
||||
#ifdef CONFIG_SCC_ENET_8xx_FIXED
|
||||
.method = fsmii_fixed,
|
||||
#else
|
||||
.method = fsmii_fec,
|
||||
#endif
|
||||
|
||||
.id = 0,
|
||||
};
|
||||
|
||||
static struct fs_platform_info mpc8xx_fec_pdata[] = {
|
||||
{
|
||||
static struct fs_platform_info mpc8xx_enet_pdata[] = {
|
||||
[fsid_fec1] = {
|
||||
.rx_ring = 128,
|
||||
.tx_ring = 16,
|
||||
.rx_copybreak = 240,
|
||||
|
@ -85,11 +73,12 @@ static struct fs_platform_info mpc8xx_fec_pdata[] = {
|
|||
.use_napi = 1,
|
||||
.napi_weight = 17,
|
||||
|
||||
.phy_addr = 0,
|
||||
.phy_irq = SIU_IRQ7,
|
||||
.init_ioports = setup_fec1_ioports,
|
||||
|
||||
.bus_info = &fec_mii_bus_info,
|
||||
}, {
|
||||
.bus_id = "0:00",
|
||||
.has_phy = 1,
|
||||
},
|
||||
[fsid_fec2] = {
|
||||
.rx_ring = 128,
|
||||
.tx_ring = 16,
|
||||
.rx_copybreak = 240,
|
||||
|
@ -97,14 +86,12 @@ static struct fs_platform_info mpc8xx_fec_pdata[] = {
|
|||
.use_napi = 1,
|
||||
.napi_weight = 17,
|
||||
|
||||
.phy_addr = 1,
|
||||
.phy_irq = SIU_IRQ7,
|
||||
.init_ioports = setup_fec2_ioports,
|
||||
|
||||
.bus_info = &fec_mii_bus_info,
|
||||
}
|
||||
};
|
||||
|
||||
static struct fs_platform_info mpc8xx_scc_pdata = {
|
||||
.bus_id = "0:01",
|
||||
.has_phy = 1,
|
||||
},
|
||||
[fsid_scc3] = {
|
||||
.rx_ring = 64,
|
||||
.tx_ring = 8,
|
||||
.rx_copybreak = 240,
|
||||
|
@ -112,19 +99,18 @@ static struct fs_platform_info mpc8xx_scc_pdata = {
|
|||
.use_napi = 1,
|
||||
.napi_weight = 17,
|
||||
|
||||
.phy_addr = 2,
|
||||
#ifdef CONFIG_MPC8xx_SCC_ENET_FIXED
|
||||
.phy_irq = -1,
|
||||
.init_ioports = setup_scc3_ioports,
|
||||
#ifdef CONFIG_FIXED_MII_10_FDX
|
||||
.bus_id = "fixed@100:1",
|
||||
#else
|
||||
.phy_irq = SIU_IRQ7,
|
||||
.bus_id = "0:02",
|
||||
#endif
|
||||
|
||||
.bus_info = &scc_mii_bus_info,
|
||||
},
|
||||
};
|
||||
|
||||
void __init board_init(void)
|
||||
{
|
||||
volatile cpm8xx_t *cp = cpmp;
|
||||
cpm8xx_t *cp = cpmp;
|
||||
unsigned int *bcsr_io;
|
||||
|
||||
#ifdef CONFIG_FS_ENET
|
||||
|
@ -164,6 +150,14 @@ void __init board_init(void)
|
|||
/* use MDC for MII (common) */
|
||||
setbits16(&immap->im_ioport.iop_pdpar, 0x0080);
|
||||
clrbits16(&immap->im_ioport.iop_pddir, 0x0080);
|
||||
bcsr_io = ioremap(BCSR5, sizeof(unsigned long));
|
||||
clrbits32(bcsr_io,BCSR5_MII1_EN);
|
||||
clrbits32(bcsr_io,BCSR5_MII1_RST);
|
||||
#ifdef CONFIG_MPC8xx_SECOND_ETH_FEC2
|
||||
clrbits32(bcsr_io,BCSR5_MII2_EN);
|
||||
clrbits32(bcsr_io,BCSR5_MII2_RST);
|
||||
#endif
|
||||
iounmap(bcsr_io);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -194,8 +188,8 @@ static void setup_fec2_ioports(void)
|
|||
/* configure FEC2 pins */
|
||||
setbits32(&immap->im_cpm.cp_pepar, 0x0003fffc);
|
||||
setbits32(&immap->im_cpm.cp_pedir, 0x0003fffc);
|
||||
setbits32(&immap->im_cpm.cp_peso, 0x00037800);
|
||||
clrbits32(&immap->im_cpm.cp_peso, 0x000087fc);
|
||||
setbits32(&immap->im_cpm.cp_peso, 0x00037800);
|
||||
clrbits32(&immap->im_cpm.cp_cptr, 0x00000080);
|
||||
}
|
||||
|
||||
|
@ -213,6 +207,8 @@ static void setup_scc3_ioports(void)
|
|||
|
||||
/* Enable the PHY.
|
||||
*/
|
||||
clrbits32(bcsr_io+4, BCSR4_ETH10_RST);
|
||||
udelay(1000);
|
||||
setbits32(bcsr_io+4, BCSR4_ETH10_RST);
|
||||
/* Configure port A pins for Txd and Rxd.
|
||||
*/
|
||||
|
@ -254,34 +250,35 @@ static void setup_scc3_ioports(void)
|
|||
clrbits32(&immap->im_cpm.cp_pedir, PE_ENET_TENA);
|
||||
setbits32(&immap->im_cpm.cp_peso, PE_ENET_TENA);
|
||||
|
||||
setbits32(bcsr_io+1, BCSR1_ETHEN);
|
||||
setbits32(bcsr_io+4, BCSR1_ETHEN);
|
||||
iounmap(bcsr_io);
|
||||
}
|
||||
|
||||
static int mac_count = 0;
|
||||
|
||||
static void mpc885ads_fixup_enet_pdata(struct platform_device *pdev, int fs_no)
|
||||
{
|
||||
struct fs_platform_info *fpi = pdev->dev.platform_data;
|
||||
|
||||
volatile cpm8xx_t *cp;
|
||||
struct fs_platform_info *fpi;
|
||||
bd_t *bd = (bd_t *) __res;
|
||||
char *e;
|
||||
int i;
|
||||
|
||||
/* Get pointer to Communication Processor */
|
||||
cp = cpmp;
|
||||
if(fs_no > ARRAY_SIZE(mpc8xx_enet_pdata)) {
|
||||
printk(KERN_ERR"No network-suitable #%d device on bus", fs_no);
|
||||
return;
|
||||
}
|
||||
|
||||
fpi = &mpc8xx_enet_pdata[fs_no];
|
||||
|
||||
switch (fs_no) {
|
||||
case fsid_fec1:
|
||||
fpi = &mpc8xx_fec_pdata[0];
|
||||
fpi->init_ioports = &setup_fec1_ioports;
|
||||
break;
|
||||
case fsid_fec2:
|
||||
fpi = &mpc8xx_fec_pdata[1];
|
||||
fpi->init_ioports = &setup_fec2_ioports;
|
||||
break;
|
||||
case fsid_scc3:
|
||||
fpi = &mpc8xx_scc_pdata;
|
||||
fpi->init_ioports = &setup_scc3_ioports;
|
||||
mpc885ads_scc_phy_init(fpi->phy_addr);
|
||||
break;
|
||||
default:
|
||||
printk(KERN_WARNING "Device %s is not supported!\n", pdev->name);
|
||||
|
@ -295,7 +292,7 @@ static void mpc885ads_fixup_enet_pdata(struct platform_device *pdev, int fs_no)
|
|||
for (i = 0; i < 6; i++)
|
||||
fpi->macaddr[i] = *e++;
|
||||
|
||||
fpi->macaddr[5 - pdev->id]++;
|
||||
fpi->macaddr[5] += mac_count++;
|
||||
|
||||
}
|
||||
|
||||
|
@ -318,58 +315,6 @@ static void __init mpc885ads_fixup_scc_enet_pdata(struct platform_device *pdev,
|
|||
mpc885ads_fixup_enet_pdata(pdev, fsid_scc1 + pdev->id - 1);
|
||||
}
|
||||
|
||||
/* SCC ethernet controller does not have MII management channel. FEC1 MII
|
||||
* channel is used to communicate with the 10Mbit PHY.
|
||||
*/
|
||||
|
||||
#define MII_ECNTRL_PINMUX 0x4
|
||||
#define FEC_ECNTRL_PINMUX 0x00000004
|
||||
#define FEC_RCNTRL_MII_MODE 0x00000004
|
||||
|
||||
/* Make MII read/write commands.
|
||||
*/
|
||||
#define mk_mii_write(REG, VAL, PHY_ADDR) (0x50020000 | (((REG) & 0x1f) << 18) | \
|
||||
((VAL) & 0xffff) | ((PHY_ADDR) << 23))
|
||||
|
||||
static void mpc885ads_scc_phy_init(char phy_addr)
|
||||
{
|
||||
volatile immap_t *immap;
|
||||
volatile fec_t *fecp;
|
||||
bd_t *bd;
|
||||
|
||||
bd = (bd_t *) __res;
|
||||
immap = (immap_t *) IMAP_ADDR; /* pointer to internal registers */
|
||||
fecp = &(immap->im_cpm.cp_fec);
|
||||
|
||||
/* Enable MII pins of the FEC1
|
||||
*/
|
||||
setbits16(&immap->im_ioport.iop_pdpar, 0x0080);
|
||||
clrbits16(&immap->im_ioport.iop_pddir, 0x0080);
|
||||
/* Set MII speed to 2.5 MHz
|
||||
*/
|
||||
out_be32(&fecp->fec_mii_speed,
|
||||
((((bd->bi_intfreq + 4999999) / 2500000) / 2) & 0x3F) << 1);
|
||||
|
||||
/* Enable FEC pin MUX
|
||||
*/
|
||||
setbits32(&fecp->fec_ecntrl, MII_ECNTRL_PINMUX);
|
||||
setbits32(&fecp->fec_r_cntrl, FEC_RCNTRL_MII_MODE);
|
||||
|
||||
out_be32(&fecp->fec_mii_data,
|
||||
mk_mii_write(MII_BMCR, BMCR_ISOLATE, phy_addr));
|
||||
udelay(100);
|
||||
out_be32(&fecp->fec_mii_data,
|
||||
mk_mii_write(MII_ADVERTISE,
|
||||
ADVERTISE_10HALF | ADVERTISE_CSMA, phy_addr));
|
||||
udelay(100);
|
||||
|
||||
/* Disable FEC MII settings
|
||||
*/
|
||||
clrbits32(&fecp->fec_ecntrl, MII_ECNTRL_PINMUX);
|
||||
clrbits32(&fecp->fec_r_cntrl, FEC_RCNTRL_MII_MODE);
|
||||
out_be32(&fecp->fec_mii_speed, 0);
|
||||
}
|
||||
|
||||
static void setup_smc1_ioports(void)
|
||||
{
|
||||
immap_t *immap = (immap_t *) IMAP_ADDR;
|
||||
|
@ -462,6 +407,9 @@ static int mpc885ads_platform_notify(struct device *dev)
|
|||
|
||||
int __init mpc885ads_init(void)
|
||||
{
|
||||
struct fs_mii_fec_platform_info* fmpi;
|
||||
bd_t *bd = (bd_t *) __res;
|
||||
|
||||
printk(KERN_NOTICE "mpc885ads: Init\n");
|
||||
|
||||
platform_notify = mpc885ads_platform_notify;
|
||||
|
@ -471,8 +419,17 @@ int __init mpc885ads_init(void)
|
|||
|
||||
ppc_sys_device_enable(MPC8xx_CPM_FEC1);
|
||||
|
||||
ppc_sys_device_enable(MPC8xx_MDIO_FEC);
|
||||
fmpi = ppc_sys_platform_devices[MPC8xx_MDIO_FEC].dev.platform_data =
|
||||
&mpc8xx_mdio_fec_pdata;
|
||||
|
||||
fmpi->mii_speed = ((((bd->bi_intfreq + 4999999) / 2500000) / 2) & 0x3F) << 1;
|
||||
|
||||
/* No PHY interrupt line here */
|
||||
fmpi->irq[0xf] = SIU_IRQ7;
|
||||
|
||||
#ifdef CONFIG_MPC8xx_SECOND_ETH_SCC3
|
||||
ppc_sys_device_enable(MPC8xx_CPM_SCC1);
|
||||
ppc_sys_device_enable(MPC8xx_CPM_SCC3);
|
||||
|
||||
#endif
|
||||
#ifdef CONFIG_MPC8xx_SECOND_ETH_FEC2
|
||||
|
|
|
@ -29,86 +29,4 @@
|
|||
#define F3_RXCLK 13
|
||||
#define F3_TXCLK 14
|
||||
|
||||
/* Automatically generates register configurations */
|
||||
#define PC_CLK(x) ((uint)(1<<(x-1))) /* FCC CLK I/O ports */
|
||||
|
||||
#define CMXFCR_RF1CS(x) ((uint)((x-5)<<27)) /* FCC1 Receive Clock Source */
|
||||
#define CMXFCR_TF1CS(x) ((uint)((x-5)<<24)) /* FCC1 Transmit Clock Source */
|
||||
#define CMXFCR_RF2CS(x) ((uint)((x-9)<<19)) /* FCC2 Receive Clock Source */
|
||||
#define CMXFCR_TF2CS(x) ((uint)((x-9)<<16)) /* FCC2 Transmit Clock Source */
|
||||
#define CMXFCR_RF3CS(x) ((uint)((x-9)<<11)) /* FCC3 Receive Clock Source */
|
||||
#define CMXFCR_TF3CS(x) ((uint)((x-9)<<8)) /* FCC3 Transmit Clock Source */
|
||||
|
||||
#define PC_F1RXCLK PC_CLK(F1_RXCLK)
|
||||
#define PC_F1TXCLK PC_CLK(F1_TXCLK)
|
||||
#define CMX1_CLK_ROUTE (CMXFCR_RF1CS(F1_RXCLK) | CMXFCR_TF1CS(F1_TXCLK))
|
||||
#define CMX1_CLK_MASK ((uint)0xff000000)
|
||||
|
||||
#define PC_F2RXCLK PC_CLK(F2_RXCLK)
|
||||
#define PC_F2TXCLK PC_CLK(F2_TXCLK)
|
||||
#define CMX2_CLK_ROUTE (CMXFCR_RF2CS(F2_RXCLK) | CMXFCR_TF2CS(F2_TXCLK))
|
||||
#define CMX2_CLK_MASK ((uint)0x00ff0000)
|
||||
|
||||
#define PC_F3RXCLK PC_CLK(F3_RXCLK)
|
||||
#define PC_F3TXCLK PC_CLK(F3_TXCLK)
|
||||
#define CMX3_CLK_ROUTE (CMXFCR_RF3CS(F3_RXCLK) | CMXFCR_TF3CS(F3_TXCLK))
|
||||
#define CMX3_CLK_MASK ((uint)0x0000ff00)
|
||||
|
||||
/* I/O Pin assignment for FCC1. I don't yet know the best way to do this,
|
||||
* but there is little variation among the choices.
|
||||
*/
|
||||
#define PA1_COL 0x00000001U
|
||||
#define PA1_CRS 0x00000002U
|
||||
#define PA1_TXER 0x00000004U
|
||||
#define PA1_TXEN 0x00000008U
|
||||
#define PA1_RXDV 0x00000010U
|
||||
#define PA1_RXER 0x00000020U
|
||||
#define PA1_TXDAT 0x00003c00U
|
||||
#define PA1_RXDAT 0x0003c000U
|
||||
#define PA1_PSORA0 (PA1_RXDAT | PA1_TXDAT)
|
||||
#define PA1_PSORA1 (PA1_COL | PA1_CRS | PA1_TXER | PA1_TXEN | \
|
||||
PA1_RXDV | PA1_RXER)
|
||||
#define PA1_DIRA0 (PA1_RXDAT | PA1_CRS | PA1_COL | PA1_RXER | PA1_RXDV)
|
||||
#define PA1_DIRA1 (PA1_TXDAT | PA1_TXEN | PA1_TXER)
|
||||
|
||||
|
||||
/* I/O Pin assignment for FCC2. I don't yet know the best way to do this,
|
||||
* but there is little variation among the choices.
|
||||
*/
|
||||
#define PB2_TXER 0x00000001U
|
||||
#define PB2_RXDV 0x00000002U
|
||||
#define PB2_TXEN 0x00000004U
|
||||
#define PB2_RXER 0x00000008U
|
||||
#define PB2_COL 0x00000010U
|
||||
#define PB2_CRS 0x00000020U
|
||||
#define PB2_TXDAT 0x000003c0U
|
||||
#define PB2_RXDAT 0x00003c00U
|
||||
#define PB2_PSORB0 (PB2_RXDAT | PB2_TXDAT | PB2_CRS | PB2_COL | \
|
||||
PB2_RXER | PB2_RXDV | PB2_TXER)
|
||||
#define PB2_PSORB1 (PB2_TXEN)
|
||||
#define PB2_DIRB0 (PB2_RXDAT | PB2_CRS | PB2_COL | PB2_RXER | PB2_RXDV)
|
||||
#define PB2_DIRB1 (PB2_TXDAT | PB2_TXEN | PB2_TXER)
|
||||
|
||||
|
||||
/* I/O Pin assignment for FCC3. I don't yet know the best way to do this,
|
||||
* but there is little variation among the choices.
|
||||
*/
|
||||
#define PB3_RXDV 0x00004000U
|
||||
#define PB3_RXER 0x00008000U
|
||||
#define PB3_TXER 0x00010000U
|
||||
#define PB3_TXEN 0x00020000U
|
||||
#define PB3_COL 0x00040000U
|
||||
#define PB3_CRS 0x00080000U
|
||||
#define PB3_TXDAT 0x0f000000U
|
||||
#define PB3_RXDAT 0x00f00000U
|
||||
#define PB3_PSORB0 (PB3_RXDAT | PB3_TXDAT | PB3_CRS | PB3_COL | \
|
||||
PB3_RXER | PB3_RXDV | PB3_TXER | PB3_TXEN)
|
||||
#define PB3_PSORB1 0
|
||||
#define PB3_DIRB0 (PB3_RXDAT | PB3_CRS | PB3_COL | PB3_RXER | PB3_RXDV)
|
||||
#define PB3_DIRB1 (PB3_TXDAT | PB3_TXEN | PB3_TXER)
|
||||
|
||||
#define FCC_MEM_OFFSET(x) (CPM_FCC_SPECIAL_BASE + (x*128))
|
||||
#define FCC1_MEM_OFFSET FCC_MEM_OFFSET(0)
|
||||
#define FCC2_MEM_OFFSET FCC_MEM_OFFSET(1)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -93,7 +93,7 @@ obj-$(CONFIG_PCI) += pci_auto.o
|
|||
endif
|
||||
obj-$(CONFIG_RAPIDIO) += ppc85xx_rio.o
|
||||
obj-$(CONFIG_83xx) += ppc83xx_setup.o ppc_sys.o \
|
||||
mpc83xx_sys.o mpc83xx_devices.o
|
||||
mpc83xx_sys.o mpc83xx_devices.o ipic.o
|
||||
ifeq ($(CONFIG_83xx),y)
|
||||
obj-$(CONFIG_PCI) += pci_auto.o
|
||||
endif
|
||||
|
|
|
@ -0,0 +1,646 @@
|
|||
/*
|
||||
* include/asm-ppc/ipic.c
|
||||
*
|
||||
* IPIC routines implementations.
|
||||
*
|
||||
* Copyright 2005 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/signal.h>
|
||||
#include <linux/sysdev.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/ipic.h>
|
||||
#include <asm/mpc83xx.h>
|
||||
|
||||
#include "ipic.h"
|
||||
|
||||
static struct ipic p_ipic;
|
||||
static struct ipic * primary_ipic;
|
||||
|
||||
static struct ipic_info ipic_info[] = {
|
||||
[9] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_H,
|
||||
.prio = IPIC_SIPRR_D,
|
||||
.force = IPIC_SIFCR_H,
|
||||
.bit = 24,
|
||||
.prio_mask = 0,
|
||||
},
|
||||
[10] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_H,
|
||||
.prio = IPIC_SIPRR_D,
|
||||
.force = IPIC_SIFCR_H,
|
||||
.bit = 25,
|
||||
.prio_mask = 1,
|
||||
},
|
||||
[11] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_H,
|
||||
.prio = IPIC_SIPRR_D,
|
||||
.force = IPIC_SIFCR_H,
|
||||
.bit = 26,
|
||||
.prio_mask = 2,
|
||||
},
|
||||
[14] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_H,
|
||||
.prio = IPIC_SIPRR_D,
|
||||
.force = IPIC_SIFCR_H,
|
||||
.bit = 29,
|
||||
.prio_mask = 5,
|
||||
},
|
||||
[15] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_H,
|
||||
.prio = IPIC_SIPRR_D,
|
||||
.force = IPIC_SIFCR_H,
|
||||
.bit = 30,
|
||||
.prio_mask = 6,
|
||||
},
|
||||
[16] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_H,
|
||||
.prio = IPIC_SIPRR_D,
|
||||
.force = IPIC_SIFCR_H,
|
||||
.bit = 31,
|
||||
.prio_mask = 7,
|
||||
},
|
||||
[17] = {
|
||||
.pend = IPIC_SEPNR,
|
||||
.mask = IPIC_SEMSR,
|
||||
.prio = IPIC_SMPRR_A,
|
||||
.force = IPIC_SEFCR,
|
||||
.bit = 1,
|
||||
.prio_mask = 5,
|
||||
},
|
||||
[18] = {
|
||||
.pend = IPIC_SEPNR,
|
||||
.mask = IPIC_SEMSR,
|
||||
.prio = IPIC_SMPRR_A,
|
||||
.force = IPIC_SEFCR,
|
||||
.bit = 2,
|
||||
.prio_mask = 6,
|
||||
},
|
||||
[19] = {
|
||||
.pend = IPIC_SEPNR,
|
||||
.mask = IPIC_SEMSR,
|
||||
.prio = IPIC_SMPRR_A,
|
||||
.force = IPIC_SEFCR,
|
||||
.bit = 3,
|
||||
.prio_mask = 7,
|
||||
},
|
||||
[20] = {
|
||||
.pend = IPIC_SEPNR,
|
||||
.mask = IPIC_SEMSR,
|
||||
.prio = IPIC_SMPRR_B,
|
||||
.force = IPIC_SEFCR,
|
||||
.bit = 4,
|
||||
.prio_mask = 4,
|
||||
},
|
||||
[21] = {
|
||||
.pend = IPIC_SEPNR,
|
||||
.mask = IPIC_SEMSR,
|
||||
.prio = IPIC_SMPRR_B,
|
||||
.force = IPIC_SEFCR,
|
||||
.bit = 5,
|
||||
.prio_mask = 5,
|
||||
},
|
||||
[22] = {
|
||||
.pend = IPIC_SEPNR,
|
||||
.mask = IPIC_SEMSR,
|
||||
.prio = IPIC_SMPRR_B,
|
||||
.force = IPIC_SEFCR,
|
||||
.bit = 6,
|
||||
.prio_mask = 6,
|
||||
},
|
||||
[23] = {
|
||||
.pend = IPIC_SEPNR,
|
||||
.mask = IPIC_SEMSR,
|
||||
.prio = IPIC_SMPRR_B,
|
||||
.force = IPIC_SEFCR,
|
||||
.bit = 7,
|
||||
.prio_mask = 7,
|
||||
},
|
||||
[32] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_H,
|
||||
.prio = IPIC_SIPRR_A,
|
||||
.force = IPIC_SIFCR_H,
|
||||
.bit = 0,
|
||||
.prio_mask = 0,
|
||||
},
|
||||
[33] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_H,
|
||||
.prio = IPIC_SIPRR_A,
|
||||
.force = IPIC_SIFCR_H,
|
||||
.bit = 1,
|
||||
.prio_mask = 1,
|
||||
},
|
||||
[34] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_H,
|
||||
.prio = IPIC_SIPRR_A,
|
||||
.force = IPIC_SIFCR_H,
|
||||
.bit = 2,
|
||||
.prio_mask = 2,
|
||||
},
|
||||
[35] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_H,
|
||||
.prio = IPIC_SIPRR_A,
|
||||
.force = IPIC_SIFCR_H,
|
||||
.bit = 3,
|
||||
.prio_mask = 3,
|
||||
},
|
||||
[36] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_H,
|
||||
.prio = IPIC_SIPRR_A,
|
||||
.force = IPIC_SIFCR_H,
|
||||
.bit = 4,
|
||||
.prio_mask = 4,
|
||||
},
|
||||
[37] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_H,
|
||||
.prio = IPIC_SIPRR_A,
|
||||
.force = IPIC_SIFCR_H,
|
||||
.bit = 5,
|
||||
.prio_mask = 5,
|
||||
},
|
||||
[38] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_H,
|
||||
.prio = IPIC_SIPRR_A,
|
||||
.force = IPIC_SIFCR_H,
|
||||
.bit = 6,
|
||||
.prio_mask = 6,
|
||||
},
|
||||
[39] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_H,
|
||||
.prio = IPIC_SIPRR_A,
|
||||
.force = IPIC_SIFCR_H,
|
||||
.bit = 7,
|
||||
.prio_mask = 7,
|
||||
},
|
||||
[48] = {
|
||||
.pend = IPIC_SEPNR,
|
||||
.mask = IPIC_SEMSR,
|
||||
.prio = IPIC_SMPRR_A,
|
||||
.force = IPIC_SEFCR,
|
||||
.bit = 0,
|
||||
.prio_mask = 4,
|
||||
},
|
||||
[64] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_L,
|
||||
.prio = IPIC_SMPRR_A,
|
||||
.force = IPIC_SIFCR_L,
|
||||
.bit = 0,
|
||||
.prio_mask = 0,
|
||||
},
|
||||
[65] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_L,
|
||||
.prio = IPIC_SMPRR_A,
|
||||
.force = IPIC_SIFCR_L,
|
||||
.bit = 1,
|
||||
.prio_mask = 1,
|
||||
},
|
||||
[66] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_L,
|
||||
.prio = IPIC_SMPRR_A,
|
||||
.force = IPIC_SIFCR_L,
|
||||
.bit = 2,
|
||||
.prio_mask = 2,
|
||||
},
|
||||
[67] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_L,
|
||||
.prio = IPIC_SMPRR_A,
|
||||
.force = IPIC_SIFCR_L,
|
||||
.bit = 3,
|
||||
.prio_mask = 3,
|
||||
},
|
||||
[68] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_L,
|
||||
.prio = IPIC_SMPRR_B,
|
||||
.force = IPIC_SIFCR_L,
|
||||
.bit = 4,
|
||||
.prio_mask = 0,
|
||||
},
|
||||
[69] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_L,
|
||||
.prio = IPIC_SMPRR_B,
|
||||
.force = IPIC_SIFCR_L,
|
||||
.bit = 5,
|
||||
.prio_mask = 1,
|
||||
},
|
||||
[70] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_L,
|
||||
.prio = IPIC_SMPRR_B,
|
||||
.force = IPIC_SIFCR_L,
|
||||
.bit = 6,
|
||||
.prio_mask = 2,
|
||||
},
|
||||
[71] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_L,
|
||||
.prio = IPIC_SMPRR_B,
|
||||
.force = IPIC_SIFCR_L,
|
||||
.bit = 7,
|
||||
.prio_mask = 3,
|
||||
},
|
||||
[72] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_L,
|
||||
.prio = 0,
|
||||
.force = IPIC_SIFCR_L,
|
||||
.bit = 8,
|
||||
},
|
||||
[73] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_L,
|
||||
.prio = 0,
|
||||
.force = IPIC_SIFCR_L,
|
||||
.bit = 9,
|
||||
},
|
||||
[74] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_L,
|
||||
.prio = 0,
|
||||
.force = IPIC_SIFCR_L,
|
||||
.bit = 10,
|
||||
},
|
||||
[75] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_L,
|
||||
.prio = 0,
|
||||
.force = IPIC_SIFCR_L,
|
||||
.bit = 11,
|
||||
},
|
||||
[76] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_L,
|
||||
.prio = 0,
|
||||
.force = IPIC_SIFCR_L,
|
||||
.bit = 12,
|
||||
},
|
||||
[77] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_L,
|
||||
.prio = 0,
|
||||
.force = IPIC_SIFCR_L,
|
||||
.bit = 13,
|
||||
},
|
||||
[78] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_L,
|
||||
.prio = 0,
|
||||
.force = IPIC_SIFCR_L,
|
||||
.bit = 14,
|
||||
},
|
||||
[79] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_L,
|
||||
.prio = 0,
|
||||
.force = IPIC_SIFCR_L,
|
||||
.bit = 15,
|
||||
},
|
||||
[80] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_L,
|
||||
.prio = 0,
|
||||
.force = IPIC_SIFCR_L,
|
||||
.bit = 16,
|
||||
},
|
||||
[84] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_L,
|
||||
.prio = 0,
|
||||
.force = IPIC_SIFCR_L,
|
||||
.bit = 20,
|
||||
},
|
||||
[85] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_L,
|
||||
.prio = 0,
|
||||
.force = IPIC_SIFCR_L,
|
||||
.bit = 21,
|
||||
},
|
||||
[90] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_L,
|
||||
.prio = 0,
|
||||
.force = IPIC_SIFCR_L,
|
||||
.bit = 26,
|
||||
},
|
||||
[91] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_L,
|
||||
.prio = 0,
|
||||
.force = IPIC_SIFCR_L,
|
||||
.bit = 27,
|
||||
},
|
||||
};
|
||||
|
||||
static inline u32 ipic_read(volatile u32 __iomem *base, unsigned int reg)
|
||||
{
|
||||
return in_be32(base + (reg >> 2));
|
||||
}
|
||||
|
||||
static inline void ipic_write(volatile u32 __iomem *base, unsigned int reg, u32 value)
|
||||
{
|
||||
out_be32(base + (reg >> 2), value);
|
||||
}
|
||||
|
||||
static inline struct ipic * ipic_from_irq(unsigned int irq)
|
||||
{
|
||||
return primary_ipic;
|
||||
}
|
||||
|
||||
static void ipic_enable_irq(unsigned int irq)
|
||||
{
|
||||
struct ipic *ipic = ipic_from_irq(irq);
|
||||
unsigned int src = irq - ipic->irq_offset;
|
||||
u32 temp;
|
||||
|
||||
temp = ipic_read(ipic->regs, ipic_info[src].mask);
|
||||
temp |= (1 << (31 - ipic_info[src].bit));
|
||||
ipic_write(ipic->regs, ipic_info[src].mask, temp);
|
||||
}
|
||||
|
||||
static void ipic_disable_irq(unsigned int irq)
|
||||
{
|
||||
struct ipic *ipic = ipic_from_irq(irq);
|
||||
unsigned int src = irq - ipic->irq_offset;
|
||||
u32 temp;
|
||||
|
||||
temp = ipic_read(ipic->regs, ipic_info[src].mask);
|
||||
temp &= ~(1 << (31 - ipic_info[src].bit));
|
||||
ipic_write(ipic->regs, ipic_info[src].mask, temp);
|
||||
}
|
||||
|
||||
static void ipic_disable_irq_and_ack(unsigned int irq)
|
||||
{
|
||||
struct ipic *ipic = ipic_from_irq(irq);
|
||||
unsigned int src = irq - ipic->irq_offset;
|
||||
u32 temp;
|
||||
|
||||
ipic_disable_irq(irq);
|
||||
|
||||
temp = ipic_read(ipic->regs, ipic_info[src].pend);
|
||||
temp |= (1 << (31 - ipic_info[src].bit));
|
||||
ipic_write(ipic->regs, ipic_info[src].pend, temp);
|
||||
}
|
||||
|
||||
static void ipic_end_irq(unsigned int irq)
|
||||
{
|
||||
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
|
||||
ipic_enable_irq(irq);
|
||||
}
|
||||
|
||||
struct hw_interrupt_type ipic = {
|
||||
.typename = " IPIC ",
|
||||
.enable = ipic_enable_irq,
|
||||
.disable = ipic_disable_irq,
|
||||
.ack = ipic_disable_irq_and_ack,
|
||||
.end = ipic_end_irq,
|
||||
};
|
||||
|
||||
void __init ipic_init(phys_addr_t phys_addr,
|
||||
unsigned int flags,
|
||||
unsigned int irq_offset,
|
||||
unsigned char *senses,
|
||||
unsigned int senses_count)
|
||||
{
|
||||
u32 i, temp = 0;
|
||||
|
||||
primary_ipic = &p_ipic;
|
||||
primary_ipic->regs = ioremap(phys_addr, MPC83xx_IPIC_SIZE);
|
||||
|
||||
primary_ipic->irq_offset = irq_offset;
|
||||
|
||||
ipic_write(primary_ipic->regs, IPIC_SICNR, 0x0);
|
||||
|
||||
/* default priority scheme is grouped. If spread mode is required
|
||||
* configure SICFR accordingly */
|
||||
if (flags & IPIC_SPREADMODE_GRP_A)
|
||||
temp |= SICFR_IPSA;
|
||||
if (flags & IPIC_SPREADMODE_GRP_D)
|
||||
temp |= SICFR_IPSD;
|
||||
if (flags & IPIC_SPREADMODE_MIX_A)
|
||||
temp |= SICFR_MPSA;
|
||||
if (flags & IPIC_SPREADMODE_MIX_B)
|
||||
temp |= SICFR_MPSB;
|
||||
|
||||
ipic_write(primary_ipic->regs, IPIC_SICNR, temp);
|
||||
|
||||
/* handle MCP route */
|
||||
temp = 0;
|
||||
if (flags & IPIC_DISABLE_MCP_OUT)
|
||||
temp = SERCR_MCPR;
|
||||
ipic_write(primary_ipic->regs, IPIC_SERCR, temp);
|
||||
|
||||
/* handle routing of IRQ0 to MCP */
|
||||
temp = ipic_read(primary_ipic->regs, IPIC_SEMSR);
|
||||
|
||||
if (flags & IPIC_IRQ0_MCP)
|
||||
temp |= SEMSR_SIRQ0;
|
||||
else
|
||||
temp &= ~SEMSR_SIRQ0;
|
||||
|
||||
ipic_write(primary_ipic->regs, IPIC_SEMSR, temp);
|
||||
|
||||
for (i = 0 ; i < NR_IPIC_INTS ; i++) {
|
||||
irq_desc[i+irq_offset].chip = &ipic;
|
||||
irq_desc[i+irq_offset].status = IRQ_LEVEL;
|
||||
}
|
||||
|
||||
temp = 0;
|
||||
for (i = 0 ; i < senses_count ; i++) {
|
||||
if ((senses[i] & IRQ_SENSE_MASK) == IRQ_SENSE_EDGE) {
|
||||
temp |= 1 << (15 - i);
|
||||
if (i != 0)
|
||||
irq_desc[i + irq_offset + MPC83xx_IRQ_EXT1 - 1].status = 0;
|
||||
else
|
||||
irq_desc[irq_offset + MPC83xx_IRQ_EXT0].status = 0;
|
||||
}
|
||||
}
|
||||
ipic_write(primary_ipic->regs, IPIC_SECNR, temp);
|
||||
|
||||
printk ("IPIC (%d IRQ sources, %d External IRQs) at %p\n", NR_IPIC_INTS,
|
||||
senses_count, primary_ipic->regs);
|
||||
}
|
||||
|
||||
int ipic_set_priority(unsigned int irq, unsigned int priority)
|
||||
{
|
||||
struct ipic *ipic = ipic_from_irq(irq);
|
||||
unsigned int src = irq - ipic->irq_offset;
|
||||
u32 temp;
|
||||
|
||||
if (priority > 7)
|
||||
return -EINVAL;
|
||||
if (src > 127)
|
||||
return -EINVAL;
|
||||
if (ipic_info[src].prio == 0)
|
||||
return -EINVAL;
|
||||
|
||||
temp = ipic_read(ipic->regs, ipic_info[src].prio);
|
||||
|
||||
if (priority < 4) {
|
||||
temp &= ~(0x7 << (20 + (3 - priority) * 3));
|
||||
temp |= ipic_info[src].prio_mask << (20 + (3 - priority) * 3);
|
||||
} else {
|
||||
temp &= ~(0x7 << (4 + (7 - priority) * 3));
|
||||
temp |= ipic_info[src].prio_mask << (4 + (7 - priority) * 3);
|
||||
}
|
||||
|
||||
ipic_write(ipic->regs, ipic_info[src].prio, temp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ipic_set_highest_priority(unsigned int irq)
|
||||
{
|
||||
struct ipic *ipic = ipic_from_irq(irq);
|
||||
unsigned int src = irq - ipic->irq_offset;
|
||||
u32 temp;
|
||||
|
||||
temp = ipic_read(ipic->regs, IPIC_SICFR);
|
||||
|
||||
/* clear and set HPI */
|
||||
temp &= 0x7f000000;
|
||||
temp |= (src & 0x7f) << 24;
|
||||
|
||||
ipic_write(ipic->regs, IPIC_SICFR, temp);
|
||||
}
|
||||
|
||||
void ipic_set_default_priority(void)
|
||||
{
|
||||
ipic_set_priority(MPC83xx_IRQ_TSEC1_TX, 0);
|
||||
ipic_set_priority(MPC83xx_IRQ_TSEC1_RX, 1);
|
||||
ipic_set_priority(MPC83xx_IRQ_TSEC1_ERROR, 2);
|
||||
ipic_set_priority(MPC83xx_IRQ_TSEC2_TX, 3);
|
||||
ipic_set_priority(MPC83xx_IRQ_TSEC2_RX, 4);
|
||||
ipic_set_priority(MPC83xx_IRQ_TSEC2_ERROR, 5);
|
||||
ipic_set_priority(MPC83xx_IRQ_USB2_DR, 6);
|
||||
ipic_set_priority(MPC83xx_IRQ_USB2_MPH, 7);
|
||||
|
||||
ipic_set_priority(MPC83xx_IRQ_UART1, 0);
|
||||
ipic_set_priority(MPC83xx_IRQ_UART2, 1);
|
||||
ipic_set_priority(MPC83xx_IRQ_SEC2, 2);
|
||||
ipic_set_priority(MPC83xx_IRQ_IIC1, 5);
|
||||
ipic_set_priority(MPC83xx_IRQ_IIC2, 6);
|
||||
ipic_set_priority(MPC83xx_IRQ_SPI, 7);
|
||||
ipic_set_priority(MPC83xx_IRQ_RTC_SEC, 0);
|
||||
ipic_set_priority(MPC83xx_IRQ_PIT, 1);
|
||||
ipic_set_priority(MPC83xx_IRQ_PCI1, 2);
|
||||
ipic_set_priority(MPC83xx_IRQ_PCI2, 3);
|
||||
ipic_set_priority(MPC83xx_IRQ_EXT0, 4);
|
||||
ipic_set_priority(MPC83xx_IRQ_EXT1, 5);
|
||||
ipic_set_priority(MPC83xx_IRQ_EXT2, 6);
|
||||
ipic_set_priority(MPC83xx_IRQ_EXT3, 7);
|
||||
ipic_set_priority(MPC83xx_IRQ_RTC_ALR, 0);
|
||||
ipic_set_priority(MPC83xx_IRQ_MU, 1);
|
||||
ipic_set_priority(MPC83xx_IRQ_SBA, 2);
|
||||
ipic_set_priority(MPC83xx_IRQ_DMA, 3);
|
||||
ipic_set_priority(MPC83xx_IRQ_EXT4, 4);
|
||||
ipic_set_priority(MPC83xx_IRQ_EXT5, 5);
|
||||
ipic_set_priority(MPC83xx_IRQ_EXT6, 6);
|
||||
ipic_set_priority(MPC83xx_IRQ_EXT7, 7);
|
||||
}
|
||||
|
||||
void ipic_enable_mcp(enum ipic_mcp_irq mcp_irq)
|
||||
{
|
||||
struct ipic *ipic = primary_ipic;
|
||||
u32 temp;
|
||||
|
||||
temp = ipic_read(ipic->regs, IPIC_SERMR);
|
||||
temp |= (1 << (31 - mcp_irq));
|
||||
ipic_write(ipic->regs, IPIC_SERMR, temp);
|
||||
}
|
||||
|
||||
void ipic_disable_mcp(enum ipic_mcp_irq mcp_irq)
|
||||
{
|
||||
struct ipic *ipic = primary_ipic;
|
||||
u32 temp;
|
||||
|
||||
temp = ipic_read(ipic->regs, IPIC_SERMR);
|
||||
temp &= (1 << (31 - mcp_irq));
|
||||
ipic_write(ipic->regs, IPIC_SERMR, temp);
|
||||
}
|
||||
|
||||
u32 ipic_get_mcp_status(void)
|
||||
{
|
||||
return ipic_read(primary_ipic->regs, IPIC_SERMR);
|
||||
}
|
||||
|
||||
void ipic_clear_mcp_status(u32 mask)
|
||||
{
|
||||
ipic_write(primary_ipic->regs, IPIC_SERMR, mask);
|
||||
}
|
||||
|
||||
/* Return an interrupt vector or -1 if no interrupt is pending. */
|
||||
int ipic_get_irq(struct pt_regs *regs)
|
||||
{
|
||||
int irq;
|
||||
|
||||
irq = ipic_read(primary_ipic->regs, IPIC_SIVCR) & 0x7f;
|
||||
|
||||
if (irq == 0) /* 0 --> no irq is pending */
|
||||
irq = -1;
|
||||
|
||||
return irq;
|
||||
}
|
||||
|
||||
static struct sysdev_class ipic_sysclass = {
|
||||
set_kset_name("ipic"),
|
||||
};
|
||||
|
||||
static struct sys_device device_ipic = {
|
||||
.id = 0,
|
||||
.cls = &ipic_sysclass,
|
||||
};
|
||||
|
||||
static int __init init_ipic_sysfs(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (!primary_ipic->regs)
|
||||
return -ENODEV;
|
||||
printk(KERN_DEBUG "Registering ipic with sysfs...\n");
|
||||
|
||||
rc = sysdev_class_register(&ipic_sysclass);
|
||||
if (rc) {
|
||||
printk(KERN_ERR "Failed registering ipic sys class\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
rc = sysdev_register(&device_ipic);
|
||||
if (rc) {
|
||||
printk(KERN_ERR "Failed registering ipic sys device\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
subsys_initcall(init_ipic_sysfs);
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* IPIC private definitions and structure.
|
||||
*
|
||||
* Maintainer: Kumar Gala <galak@kernel.crashing.org>
|
||||
*
|
||||
* Copyright 2005 Freescale Semiconductor, Inc
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef __IPIC_H__
|
||||
#define __IPIC_H__
|
||||
|
||||
#include <asm/ipic.h>
|
||||
|
||||
#define MPC83xx_IPIC_SIZE (0x00100)
|
||||
|
||||
/* System Global Interrupt Configuration Register */
|
||||
#define SICFR_IPSA 0x00010000
|
||||
#define SICFR_IPSD 0x00080000
|
||||
#define SICFR_MPSA 0x00200000
|
||||
#define SICFR_MPSB 0x00400000
|
||||
|
||||
/* System External Interrupt Mask Register */
|
||||
#define SEMSR_SIRQ0 0x00008000
|
||||
|
||||
/* System Error Control Register */
|
||||
#define SERCR_MCPR 0x00000001
|
||||
|
||||
struct ipic {
|
||||
volatile u32 __iomem *regs;
|
||||
unsigned int irq_offset;
|
||||
};
|
||||
|
||||
struct ipic_info {
|
||||
u8 pend; /* pending register offset from base */
|
||||
u8 mask; /* mask register offset from base */
|
||||
u8 prio; /* priority register offset from base */
|
||||
u8 force; /* force register offset from base */
|
||||
u8 bit; /* register bit position (as per doc)
|
||||
bit mask = 1 << (31 - bit) */
|
||||
u8 prio_mask; /* priority mask value */
|
||||
};
|
||||
|
||||
#endif /* __IPIC_H__ */
|
|
@ -16,9 +16,11 @@
|
|||
#include <linux/device.h>
|
||||
#include <linux/serial_8250.h>
|
||||
#include <linux/fsl_devices.h>
|
||||
#include <linux/fs_enet_pd.h>
|
||||
#include <asm/mpc85xx.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/ppc_sys.h>
|
||||
#include <asm/cpm2.h>
|
||||
|
||||
/* We use offsets for IORESOURCE_MEM since we do not know at compile time
|
||||
* what CCSRBAR is, will get fixed up by mach_mpc85xx_fixup
|
||||
|
@ -82,6 +84,60 @@ static struct fsl_i2c_platform_data mpc85xx_fsl_i2c2_pdata = {
|
|||
.device_flags = FSL_I2C_DEV_SEPARATE_DFSRR,
|
||||
};
|
||||
|
||||
static struct fs_platform_info mpc85xx_fcc1_pdata = {
|
||||
.fs_no = fsid_fcc1,
|
||||
.cp_page = CPM_CR_FCC1_PAGE,
|
||||
.cp_block = CPM_CR_FCC1_SBLOCK,
|
||||
|
||||
.rx_ring = 32,
|
||||
.tx_ring = 32,
|
||||
.rx_copybreak = 240,
|
||||
.use_napi = 0,
|
||||
.napi_weight = 17,
|
||||
|
||||
.clk_mask = CMX1_CLK_MASK,
|
||||
.clk_route = CMX1_CLK_ROUTE,
|
||||
.clk_trx = (PC_F1RXCLK | PC_F1TXCLK),
|
||||
|
||||
.mem_offset = FCC1_MEM_OFFSET,
|
||||
};
|
||||
|
||||
static struct fs_platform_info mpc85xx_fcc2_pdata = {
|
||||
.fs_no = fsid_fcc2,
|
||||
.cp_page = CPM_CR_FCC2_PAGE,
|
||||
.cp_block = CPM_CR_FCC2_SBLOCK,
|
||||
|
||||
.rx_ring = 32,
|
||||
.tx_ring = 32,
|
||||
.rx_copybreak = 240,
|
||||
.use_napi = 0,
|
||||
.napi_weight = 17,
|
||||
|
||||
.clk_mask = CMX2_CLK_MASK,
|
||||
.clk_route = CMX2_CLK_ROUTE,
|
||||
.clk_trx = (PC_F2RXCLK | PC_F2TXCLK),
|
||||
|
||||
.mem_offset = FCC2_MEM_OFFSET,
|
||||
};
|
||||
|
||||
static struct fs_platform_info mpc85xx_fcc3_pdata = {
|
||||
.fs_no = fsid_fcc3,
|
||||
.cp_page = CPM_CR_FCC3_PAGE,
|
||||
.cp_block = CPM_CR_FCC3_SBLOCK,
|
||||
|
||||
.rx_ring = 32,
|
||||
.tx_ring = 32,
|
||||
.rx_copybreak = 240,
|
||||
.use_napi = 0,
|
||||
.napi_weight = 17,
|
||||
|
||||
.clk_mask = CMX3_CLK_MASK,
|
||||
.clk_route = CMX3_CLK_ROUTE,
|
||||
.clk_trx = (PC_F3RXCLK | PC_F3TXCLK),
|
||||
|
||||
.mem_offset = FCC3_MEM_OFFSET,
|
||||
};
|
||||
|
||||
static struct plat_serial8250_port serial_platform_data[] = {
|
||||
[0] = {
|
||||
.mapbase = 0x4500,
|
||||
|
@ -318,18 +374,27 @@ struct platform_device ppc_sys_platform_devices[] = {
|
|||
[MPC85xx_CPM_FCC1] = {
|
||||
.name = "fsl-cpm-fcc",
|
||||
.id = 1,
|
||||
.num_resources = 3,
|
||||
.num_resources = 4,
|
||||
.dev.platform_data = &mpc85xx_fcc1_pdata,
|
||||
.resource = (struct resource[]) {
|
||||
{
|
||||
.name = "fcc_regs",
|
||||
.start = 0x91300,
|
||||
.end = 0x9131F,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.name = "fcc_regs_c",
|
||||
.start = 0x91380,
|
||||
.end = 0x9139F,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.name = "fcc_pram",
|
||||
.start = 0x88400,
|
||||
.end = 0x884ff,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = SIU_INT_FCC1,
|
||||
.end = SIU_INT_FCC1,
|
||||
|
@ -340,18 +405,27 @@ struct platform_device ppc_sys_platform_devices[] = {
|
|||
[MPC85xx_CPM_FCC2] = {
|
||||
.name = "fsl-cpm-fcc",
|
||||
.id = 2,
|
||||
.num_resources = 3,
|
||||
.num_resources = 4,
|
||||
.dev.platform_data = &mpc85xx_fcc2_pdata,
|
||||
.resource = (struct resource[]) {
|
||||
{
|
||||
.name = "fcc_regs",
|
||||
.start = 0x91320,
|
||||
.end = 0x9133F,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.name = "fcc_regs_c",
|
||||
.start = 0x913A0,
|
||||
.end = 0x913CF,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.name = "fcc_pram",
|
||||
.start = 0x88500,
|
||||
.end = 0x885ff,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = SIU_INT_FCC2,
|
||||
.end = SIU_INT_FCC2,
|
||||
|
@ -362,18 +436,27 @@ struct platform_device ppc_sys_platform_devices[] = {
|
|||
[MPC85xx_CPM_FCC3] = {
|
||||
.name = "fsl-cpm-fcc",
|
||||
.id = 3,
|
||||
.num_resources = 3,
|
||||
.num_resources = 4,
|
||||
.dev.platform_data = &mpc85xx_fcc3_pdata,
|
||||
.resource = (struct resource[]) {
|
||||
{
|
||||
.name = "fcc_regs",
|
||||
.start = 0x91340,
|
||||
.end = 0x9135F,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.name = "fcc_regs_c",
|
||||
.start = 0x913D0,
|
||||
.end = 0x913FF,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.name = "fcc_pram",
|
||||
.start = 0x88600,
|
||||
.end = 0x886ff,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = SIU_INT_FCC3,
|
||||
.end = SIU_INT_FCC3,
|
||||
|
|
|
@ -218,6 +218,14 @@ struct platform_device ppc_sys_platform_devices[] = {
|
|||
},
|
||||
},
|
||||
},
|
||||
|
||||
[MPC8xx_MDIO_FEC] = {
|
||||
.name = "fsl-cpm-fec-mdio",
|
||||
.id = 0,
|
||||
.num_resources = 0,
|
||||
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
static int __init mach_mpc8xx_fixup(struct platform_device *pdev)
|
||||
|
|
|
@ -22,7 +22,7 @@ struct ppc_sys_spec ppc_sys_specs[] = {
|
|||
.ppc_sys_name = "MPC86X",
|
||||
.mask = 0xFFFFFFFF,
|
||||
.value = 0x00000000,
|
||||
.num_devices = 7,
|
||||
.num_devices = 8,
|
||||
.device_list = (enum ppc_sys_devices[])
|
||||
{
|
||||
MPC8xx_CPM_FEC1,
|
||||
|
@ -32,13 +32,14 @@ struct ppc_sys_spec ppc_sys_specs[] = {
|
|||
MPC8xx_CPM_SCC4,
|
||||
MPC8xx_CPM_SMC1,
|
||||
MPC8xx_CPM_SMC2,
|
||||
MPC8xx_MDIO_FEC,
|
||||
},
|
||||
},
|
||||
{
|
||||
.ppc_sys_name = "MPC885",
|
||||
.mask = 0xFFFFFFFF,
|
||||
.value = 0x00000000,
|
||||
.num_devices = 8,
|
||||
.num_devices = 9,
|
||||
.device_list = (enum ppc_sys_devices[])
|
||||
{
|
||||
MPC8xx_CPM_FEC1,
|
||||
|
@ -49,6 +50,7 @@ struct ppc_sys_spec ppc_sys_specs[] = {
|
|||
MPC8xx_CPM_SCC4,
|
||||
MPC8xx_CPM_SMC1,
|
||||
MPC8xx_CPM_SMC2,
|
||||
MPC8xx_MDIO_FEC,
|
||||
},
|
||||
},
|
||||
{ /* default match */
|
||||
|
|
|
@ -369,6 +369,11 @@ struct platform_device ppc_sys_platform_devices[] = {
|
|||
},
|
||||
},
|
||||
},
|
||||
[MPC82xx_MDIO_BB] = {
|
||||
.name = "fsl-bb-mdio",
|
||||
.id = 0,
|
||||
.num_resources = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init mach_mpc82xx_fixup(struct platform_device *pdev)
|
||||
|
|
|
@ -139,13 +139,14 @@ struct ppc_sys_spec ppc_sys_specs[] = {
|
|||
.ppc_sys_name = "8272",
|
||||
.mask = 0x0000ff00,
|
||||
.value = 0x00000c00,
|
||||
.num_devices = 12,
|
||||
.num_devices = 13,
|
||||
.device_list = (enum ppc_sys_devices[])
|
||||
{
|
||||
MPC82xx_CPM_FCC1, MPC82xx_CPM_FCC2, MPC82xx_CPM_SCC1,
|
||||
MPC82xx_CPM_SCC2, MPC82xx_CPM_SCC3, MPC82xx_CPM_SCC4,
|
||||
MPC82xx_CPM_SMC1, MPC82xx_CPM_SMC2, MPC82xx_CPM_SPI,
|
||||
MPC82xx_CPM_I2C, MPC82xx_CPM_USB, MPC82xx_SEC1,
|
||||
MPC82xx_MDIO_BB,
|
||||
},
|
||||
},
|
||||
/* below is a list of the 8280 family of processors */
|
||||
|
|
|
@ -618,7 +618,7 @@ appldata_offline_cpu(int cpu)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
static int
|
||||
static int __cpuinit
|
||||
appldata_cpu_notify(struct notifier_block *self,
|
||||
unsigned long action, void *hcpu)
|
||||
{
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче