/spare/repo/netdev-2.6 branch 'master'
This commit is contained in:
Коммит
a670fcb43f
6
CREDITS
6
CREDITS
|
@ -1624,10 +1624,10 @@ E: ajoshi@shell.unixbox.com
|
|||
D: fbdev hacking
|
||||
|
||||
N: Jesper Juhl
|
||||
E: juhl-lkml@dif.dk
|
||||
D: Various small janitor fixes, cleanups etc.
|
||||
E: jesper.juhl@gmail.com
|
||||
D: Various fixes, cleanups and minor features.
|
||||
S: Lemnosvej 1, 3.tv
|
||||
S: 2300 Copenhagen S
|
||||
S: 2300 Copenhagen S.
|
||||
S: Denmark
|
||||
|
||||
N: Jozsef Kadlecsik
|
||||
|
|
|
@ -65,6 +65,7 @@ o isdn4k-utils 3.1pre1 # isdnctrl 2>&1|grep version
|
|||
o nfs-utils 1.0.5 # showmount --version
|
||||
o procps 3.2.0 # ps --version
|
||||
o oprofile 0.9 # oprofiled --version
|
||||
o udev 058 # udevinfo -V
|
||||
|
||||
Kernel compilation
|
||||
==================
|
||||
|
|
|
@ -41,6 +41,7 @@ COPYING
|
|||
CREDITS
|
||||
CVS
|
||||
ChangeSet
|
||||
Image
|
||||
Kerntypes
|
||||
MODS.txt
|
||||
Module.symvers
|
||||
|
@ -103,6 +104,7 @@ logo_*.c
|
|||
logo_*_clut224.c
|
||||
logo_*_mono.c
|
||||
lxdialog
|
||||
mach-types.h
|
||||
make_times_h
|
||||
map
|
||||
maui_boot.h
|
||||
|
|
|
@ -103,11 +103,11 @@ Who: Jody McIntyre <scjody@steamballoon.com>
|
|||
---------------------------
|
||||
|
||||
What: register_serial/unregister_serial
|
||||
When: December 2005
|
||||
When: September 2005
|
||||
Why: This interface does not allow serial ports to be registered against
|
||||
a struct device, and as such does not allow correct power management
|
||||
of such ports. 8250-based ports should use serial8250_register_port
|
||||
and serial8250_unregister_port instead.
|
||||
and serial8250_unregister_port, or platform devices instead.
|
||||
Who: Russell King <rmk@arm.linux.org.uk>
|
||||
|
||||
---------------------------
|
||||
|
|
|
@ -1,18 +1,22 @@
|
|||
inotify
|
||||
a powerful yet simple file change notification system
|
||||
inotify
|
||||
a powerful yet simple file change notification system
|
||||
|
||||
|
||||
|
||||
Document started 15 Mar 2005 by Robert Love <rml@novell.com>
|
||||
|
||||
|
||||
(i) User Interface
|
||||
|
||||
Inotify is controlled by a set of three sys calls
|
||||
Inotify is controlled by a set of three system calls and normal file I/O on a
|
||||
returned file descriptor.
|
||||
|
||||
First step in using inotify is to initialise an inotify instance
|
||||
First step in using inotify is to initialise an inotify instance:
|
||||
|
||||
int fd = inotify_init ();
|
||||
|
||||
Each instance is associated with a unique, ordered queue.
|
||||
|
||||
Change events are managed by "watches". A watch is an (object,mask) pair where
|
||||
the object is a file or directory and the mask is a bit mask of one or more
|
||||
inotify events that the application wishes to receive. See <linux/inotify.h>
|
||||
|
@ -22,43 +26,52 @@ Watches are added via a path to the file.
|
|||
|
||||
Watches on a directory will return events on any files inside of the directory.
|
||||
|
||||
Adding a watch is simple,
|
||||
Adding a watch is simple:
|
||||
|
||||
int wd = inotify_add_watch (fd, path, mask);
|
||||
|
||||
You can add a large number of files via something like
|
||||
|
||||
for each file to watch {
|
||||
int wd = inotify_add_watch (fd, file, mask);
|
||||
}
|
||||
Where "fd" is the return value from inotify_init(), path is the path to the
|
||||
object to watch, and mask is the watch mask (see <linux/inotify.h>).
|
||||
|
||||
You can update an existing watch in the same manner, by passing in a new mask.
|
||||
|
||||
An existing watch is removed via the INOTIFY_IGNORE ioctl, for example
|
||||
An existing watch is removed via
|
||||
|
||||
inotify_rm_watch (fd, wd);
|
||||
int ret = inotify_rm_watch (fd, wd);
|
||||
|
||||
Events are provided in the form of an inotify_event structure that is read(2)
|
||||
from a inotify instance fd. The filename is of dynamic length and follows the
|
||||
struct. It is of size len. The filename is padded with null bytes to ensure
|
||||
proper alignment. This padding is reflected in len.
|
||||
from a given inotify instance. The filename is of dynamic length and follows
|
||||
the struct. It is of size len. The filename is padded with null bytes to
|
||||
ensure proper alignment. This padding is reflected in len.
|
||||
|
||||
You can slurp multiple events by passing a large buffer, for example
|
||||
|
||||
size_t len = read (fd, buf, BUF_LEN);
|
||||
|
||||
Will return as many events as are available and fit in BUF_LEN.
|
||||
Where "buf" is a pointer to an array of "inotify_event" structures at least
|
||||
BUF_LEN bytes in size. The above example will return as many events as are
|
||||
available and fit in BUF_LEN.
|
||||
|
||||
each inotify instance fd is also select()- and poll()-able.
|
||||
Each inotify instance fd is also select()- and poll()-able.
|
||||
|
||||
You can find the size of the current event queue via the FIONREAD ioctl.
|
||||
You can find the size of the current event queue via the standard FIONREAD
|
||||
ioctl on the fd returned by inotify_init().
|
||||
|
||||
All watches are destroyed and cleaned up on close.
|
||||
|
||||
|
||||
(ii) Internal Kernel Implementation
|
||||
(ii)
|
||||
|
||||
Each open inotify instance is associated with an inotify_device structure.
|
||||
Prototypes:
|
||||
|
||||
int inotify_init (void);
|
||||
int inotify_add_watch (int fd, const char *path, __u32 mask);
|
||||
int inotify_rm_watch (int fd, __u32 mask);
|
||||
|
||||
|
||||
(iii) Internal Kernel Implementation
|
||||
|
||||
Each inotify instance is associated with an inotify_device structure.
|
||||
|
||||
Each watch is associated with an inotify_watch structure. Watches are chained
|
||||
off of each associated device and each associated inode.
|
||||
|
@ -66,7 +79,7 @@ off of each associated device and each associated inode.
|
|||
See fs/inotify.c for the locking and lifetime rules.
|
||||
|
||||
|
||||
(iii) Rationale
|
||||
(iv) Rationale
|
||||
|
||||
Q: What is the design decision behind not tying the watch to the open fd of
|
||||
the watched object?
|
||||
|
@ -75,9 +88,9 @@ A: Watches are associated with an open inotify device, not an open file.
|
|||
This solves the primary problem with dnotify: keeping the file open pins
|
||||
the file and thus, worse, pins the mount. Dnotify is therefore infeasible
|
||||
for use on a desktop system with removable media as the media cannot be
|
||||
unmounted.
|
||||
unmounted. Watching a file should not require that it be open.
|
||||
|
||||
Q: What is the design decision behind using an-fd-per-device as opposed to
|
||||
Q: What is the design decision behind using an-fd-per-instance as opposed to
|
||||
an fd-per-watch?
|
||||
|
||||
A: An fd-per-watch quickly consumes more file descriptors than are allowed,
|
||||
|
@ -86,8 +99,8 @@ A: An fd-per-watch quickly consumes more file descriptors than are allowed,
|
|||
can use epoll, but requiring both is a silly and extraneous requirement.
|
||||
A watch consumes less memory than an open file, separating the number
|
||||
spaces is thus sensible. The current design is what user-space developers
|
||||
want: Users initialize inotify, once, and add n watches, requiring but one fd
|
||||
and no twiddling with fd limits. Initializing an inotify instance two
|
||||
want: Users initialize inotify, once, and add n watches, requiring but one
|
||||
fd and no twiddling with fd limits. Initializing an inotify instance two
|
||||
thousand times is silly. If we can implement user-space's preferences
|
||||
cleanly--and we can, the idr layer makes stuff like this trivial--then we
|
||||
should.
|
||||
|
@ -111,9 +124,6 @@ A: An fd-per-watch quickly consumes more file descriptors than are allowed,
|
|||
example, love it. Trust me, I asked. It is not a surprise: Who'd want
|
||||
to manage and block on 1000 fd's via select?
|
||||
|
||||
- You'd have to manage the fd's, as an example: Call close() when you
|
||||
received a delete event.
|
||||
|
||||
- No way to get out of band data.
|
||||
|
||||
- 1024 is still too low. ;-)
|
||||
|
@ -122,6 +132,11 @@ A: An fd-per-watch quickly consumes more file descriptors than are allowed,
|
|||
scales to 1000s of directories, juggling 1000s of fd's just does not seem
|
||||
the right interface. It is too heavy.
|
||||
|
||||
Additionally, it _is_ possible to more than one instance and
|
||||
juggle more than one queue and thus more than one associated fd. There
|
||||
need not be a one-fd-per-process mapping; it is one-fd-per-queue and a
|
||||
process can easily want more than one queue.
|
||||
|
||||
Q: Why the system call approach?
|
||||
|
||||
A: The poor user-space interface is the second biggest problem with dnotify.
|
||||
|
@ -131,8 +146,6 @@ A: The poor user-space interface is the second biggest problem with dnotify.
|
|||
Obtaining the fd and managing the watches could have been done either via a
|
||||
device file or a family of new system calls. We decided to implement a
|
||||
family of system calls because that is the preffered approach for new kernel
|
||||
features and it means our user interface requirements.
|
||||
|
||||
Additionally, it _is_ possible to more than one instance and
|
||||
juggle more than one queue and thus more than one associated fd.
|
||||
interfaces. The only real difference was whether we wanted to use open(2)
|
||||
and ioctl(2) or a couple of new system calls. System calls beat ioctls.
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ Overview
|
|||
========
|
||||
|
||||
Linux-NTFS comes with a number of user-space programs known as ntfsprogs.
|
||||
These include mkntfs, a full-featured ntfs file system format utility,
|
||||
These include mkntfs, a full-featured ntfs filesystem format utility,
|
||||
ntfsundelete used for recovering files that were unintentionally deleted
|
||||
from an NTFS volume and ntfsresize which is used to resize an NTFS partition.
|
||||
See the web site for more information.
|
||||
|
@ -149,7 +149,14 @@ case_sensitive=<BOOL> If case_sensitive is specified, treat all file names as
|
|||
name, if it exists. If case_sensitive, you will need
|
||||
to provide the correct case of the short file name.
|
||||
|
||||
errors=opt What to do when critical file system errors are found.
|
||||
disable_sparse=<BOOL> If disable_sparse is specified, creation of sparse
|
||||
regions, i.e. holes, inside files is disabled for the
|
||||
volume (for the duration of this mount only). By
|
||||
default, creation of sparse regions is enabled, which
|
||||
is consistent with the behaviour of traditional Unix
|
||||
filesystems.
|
||||
|
||||
errors=opt What to do when critical filesystem errors are found.
|
||||
Following values can be used for "opt":
|
||||
continue: DEFAULT, try to clean-up as much as
|
||||
possible, e.g. marking a corrupt inode as
|
||||
|
@ -432,6 +439,24 @@ ChangeLog
|
|||
|
||||
Note, a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog.
|
||||
|
||||
2.1.23:
|
||||
- Stamp the user space journal, aka transaction log, aka $UsnJrnl, if
|
||||
it is present and active thus telling Windows and applications using
|
||||
the transaction log that changes can have happened on the volume
|
||||
which are not recorded in $UsnJrnl.
|
||||
- Detect the case when Windows has been hibernated (suspended to disk)
|
||||
and if this is the case do not allow (re)mounting read-write to
|
||||
prevent data corruption when you boot back into the suspended
|
||||
Windows session.
|
||||
- Implement extension of resident files using the normal file write
|
||||
code paths, i.e. most very small files can be extended to be a little
|
||||
bit bigger but not by much.
|
||||
- Add new mount option "disable_sparse". (See list of mount options
|
||||
above for details.)
|
||||
- Improve handling of ntfs volumes with errors and strange boot sectors
|
||||
in particular.
|
||||
- Fix various bugs including a nasty deadlock that appeared in recent
|
||||
kernels (around 2.6.11-2.6.12 timeframe).
|
||||
2.1.22:
|
||||
- Improve handling of ntfs volumes with errors.
|
||||
- Fix various bugs and race conditions.
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
INFINIBAND MIDLAYER LOCKING
|
||||
|
||||
This guide is an attempt to make explicit the locking assumptions
|
||||
made by the InfiniBand midlayer. It describes the requirements on
|
||||
both low-level drivers that sit below the midlayer and upper level
|
||||
protocols that use the midlayer.
|
||||
|
||||
Sleeping and interrupt context
|
||||
|
||||
With the following exceptions, a low-level driver implementation of
|
||||
all of the methods in struct ib_device may sleep. The exceptions
|
||||
are any methods from the list:
|
||||
|
||||
create_ah
|
||||
modify_ah
|
||||
query_ah
|
||||
destroy_ah
|
||||
bind_mw
|
||||
post_send
|
||||
post_recv
|
||||
poll_cq
|
||||
req_notify_cq
|
||||
map_phys_fmr
|
||||
|
||||
which may not sleep and must be callable from any context.
|
||||
|
||||
The corresponding functions exported to upper level protocol
|
||||
consumers:
|
||||
|
||||
ib_create_ah
|
||||
ib_modify_ah
|
||||
ib_query_ah
|
||||
ib_destroy_ah
|
||||
ib_bind_mw
|
||||
ib_post_send
|
||||
ib_post_recv
|
||||
ib_req_notify_cq
|
||||
ib_map_phys_fmr
|
||||
|
||||
are therefore safe to call from any context.
|
||||
|
||||
In addition, the function
|
||||
|
||||
ib_dispatch_event
|
||||
|
||||
used by low-level drivers to dispatch asynchronous events through
|
||||
the midlayer is also safe to call from any context.
|
||||
|
||||
Reentrancy
|
||||
|
||||
All of the methods in struct ib_device exported by a low-level
|
||||
driver must be fully reentrant. The low-level driver is required to
|
||||
perform all synchronization necessary to maintain consistency, even
|
||||
if multiple function calls using the same object are run
|
||||
simultaneously.
|
||||
|
||||
The IB midlayer does not perform any serialization of function calls.
|
||||
|
||||
Because low-level drivers are reentrant, upper level protocol
|
||||
consumers are not required to perform any serialization. However,
|
||||
some serialization may be required to get sensible results. For
|
||||
example, a consumer may safely call ib_poll_cq() on multiple CPUs
|
||||
simultaneously. However, the ordering of the work completion
|
||||
information between different calls of ib_poll_cq() is not defined.
|
||||
|
||||
Callbacks
|
||||
|
||||
A low-level driver must not perform a callback directly from the
|
||||
same callchain as an ib_device method call. For example, it is not
|
||||
allowed for a low-level driver to call a consumer's completion event
|
||||
handler directly from its post_send method. Instead, the low-level
|
||||
driver should defer this callback by, for example, scheduling a
|
||||
tasklet to perform the callback.
|
||||
|
||||
The low-level driver is responsible for ensuring that multiple
|
||||
completion event handlers for the same CQ are not called
|
||||
simultaneously. The driver must guarantee that only one CQ event
|
||||
handler for a given CQ is running at a time. In other words, the
|
||||
following situation is not allowed:
|
||||
|
||||
CPU1 CPU2
|
||||
|
||||
low-level driver ->
|
||||
consumer CQ event callback:
|
||||
/* ... */
|
||||
ib_req_notify_cq(cq, ...);
|
||||
low-level driver ->
|
||||
/* ... */ consumer CQ event callback:
|
||||
/* ... */
|
||||
return from CQ event handler
|
||||
|
||||
The context in which completion event and asynchronous event
|
||||
callbacks run is not defined. Depending on the low-level driver, it
|
||||
may be process context, softirq context, or interrupt context.
|
||||
Upper level protocol consumers may not sleep in a callback.
|
||||
|
||||
Hot-plug
|
||||
|
||||
A low-level driver announces that a device is ready for use by
|
||||
consumers when it calls ib_register_device(), all initialization
|
||||
must be complete before this call. The device must remain usable
|
||||
until the driver's call to ib_unregister_device() has returned.
|
||||
|
||||
A low-level driver must call ib_register_device() and
|
||||
ib_unregister_device() from process context. It must not hold any
|
||||
semaphores that could cause deadlock if a consumer calls back into
|
||||
the driver across these calls.
|
||||
|
||||
An upper level protocol consumer may begin using an IB device as
|
||||
soon as the add method of its struct ib_client is called for that
|
||||
device. A consumer must finish all cleanup and free all resources
|
||||
relating to a device before returning from the remove method.
|
||||
|
||||
A consumer is permitted to sleep in its add and remove methods.
|
|
@ -28,13 +28,37 @@ Creating MAD agents
|
|||
|
||||
Receiving MADs
|
||||
|
||||
MADs are received using read(). The buffer passed to read() must be
|
||||
large enough to hold at least one struct ib_user_mad. For example:
|
||||
MADs are received using read(). The receive side now supports
|
||||
RMPP. The buffer passed to read() must be at least one
|
||||
struct ib_user_mad + 256 bytes. For example:
|
||||
|
||||
struct ib_user_mad mad;
|
||||
ret = read(fd, &mad, sizeof mad);
|
||||
if (ret != sizeof mad)
|
||||
If the buffer passed is not large enough to hold the received
|
||||
MAD (RMPP), the errno is set to ENOSPC and the length of the
|
||||
buffer needed is set in mad.length.
|
||||
|
||||
Example for normal MAD (non RMPP) reads:
|
||||
struct ib_user_mad *mad;
|
||||
mad = malloc(sizeof *mad + 256);
|
||||
ret = read(fd, mad, sizeof *mad + 256);
|
||||
if (ret != sizeof mad + 256) {
|
||||
perror("read");
|
||||
free(mad);
|
||||
}
|
||||
|
||||
Example for RMPP reads:
|
||||
struct ib_user_mad *mad;
|
||||
mad = malloc(sizeof *mad + 256);
|
||||
ret = read(fd, mad, sizeof *mad + 256);
|
||||
if (ret == -ENOSPC)) {
|
||||
length = mad.length;
|
||||
free(mad);
|
||||
mad = malloc(sizeof *mad + length);
|
||||
ret = read(fd, mad, sizeof *mad + length);
|
||||
}
|
||||
if (ret < 0) {
|
||||
perror("read");
|
||||
free(mad);
|
||||
}
|
||||
|
||||
In addition to the actual MAD contents, the other struct ib_user_mad
|
||||
fields will be filled in with information on the received MAD. For
|
||||
|
@ -50,18 +74,21 @@ Sending MADs
|
|||
|
||||
MADs are sent using write(). The agent ID for sending should be
|
||||
filled into the id field of the MAD, the destination LID should be
|
||||
filled into the lid field, and so on. For example:
|
||||
filled into the lid field, and so on. The send side does support
|
||||
RMPP so arbitrary length MAD can be sent. For example:
|
||||
|
||||
struct ib_user_mad mad;
|
||||
struct ib_user_mad *mad;
|
||||
|
||||
/* fill in mad.data */
|
||||
mad = malloc(sizeof *mad + mad_length);
|
||||
|
||||
mad.id = my_agent; /* req.id from agent registration */
|
||||
mad.lid = my_dest; /* in network byte order... */
|
||||
/* fill in mad->data */
|
||||
|
||||
mad->hdr.id = my_agent; /* req.id from agent registration */
|
||||
mad->hdr.lid = my_dest; /* in network byte order... */
|
||||
/* etc. */
|
||||
|
||||
ret = write(fd, &mad, sizeof mad);
|
||||
if (ret != sizeof mad)
|
||||
ret = write(fd, &mad, sizeof *mad + mad_length);
|
||||
if (ret != sizeof *mad + mad_length)
|
||||
perror("write");
|
||||
|
||||
Setting IsSM Capability Bit
|
||||
|
|
|
@ -56,3 +56,12 @@ This file details changes in 2.6 which affect PCMCIA card driver authors:
|
|||
memory regions in-use. The name argument should be a pointer to
|
||||
your driver name. Eg, for pcnet_cs, name should point to the
|
||||
string "pcnet_cs".
|
||||
|
||||
* CardServices is gone
|
||||
CardServices() in 2.4 is just a big switch statement to call various
|
||||
services. In 2.6, all of those entry points are exported and called
|
||||
directly (except for pcmcia_report_error(), just use cs_error() instead).
|
||||
|
||||
* struct pcmcia_driver
|
||||
You need to use struct pcmcia_driver and pcmcia_{un,}register_driver
|
||||
instead of {un,}register_pccard_driver
|
||||
|
|
|
@ -388,7 +388,6 @@ Summary:
|
|||
scsi_remove_device - detach and remove a SCSI device
|
||||
scsi_remove_host - detach and remove all SCSI devices owned by host
|
||||
scsi_report_bus_reset - report scsi _bus_ reset observed
|
||||
scsi_set_device - place device reference in host structure
|
||||
scsi_track_queue_full - track successive QUEUE_FULL events
|
||||
scsi_unblock_requests - allow further commands to be queued to given host
|
||||
scsi_unregister - [calls scsi_host_put()]
|
||||
|
@ -740,20 +739,6 @@ int scsi_remove_host(struct Scsi_Host *shost)
|
|||
void scsi_report_bus_reset(struct Scsi_Host * shost, int channel)
|
||||
|
||||
|
||||
/**
|
||||
* scsi_set_device - place device reference in host structure
|
||||
* @shost: a pointer to a scsi host instance
|
||||
* @pdev: pointer to device instance to assign
|
||||
*
|
||||
* Returns nothing
|
||||
*
|
||||
* Might block: no
|
||||
*
|
||||
* Defined in: include/scsi/scsi_host.h .
|
||||
**/
|
||||
void scsi_set_device(struct Scsi_Host * shost, struct device * dev)
|
||||
|
||||
|
||||
/**
|
||||
* scsi_track_queue_full - track successive QUEUE_FULL events on given
|
||||
* device to determine if and when there is a need
|
||||
|
|
|
@ -636,11 +636,16 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
3stack-digout 3-jack in back, a HP out and a SPDIF out
|
||||
5stack 5-jack in back, 2-jack in front
|
||||
5stack-digout 5-jack in back, 2-jack in front, a SPDIF out
|
||||
6stack 6-jack in back, 2-jack in front
|
||||
6stack-digout 6-jack with a SPDIF out
|
||||
w810 3-jack
|
||||
z71v 3-jack (HP shared SPDIF)
|
||||
asus 3-jack
|
||||
uniwill 3-jack
|
||||
F1734 2-jack
|
||||
test for testing/debugging purpose, almost all controls can be
|
||||
adjusted. Appearing only when compiled with
|
||||
$CONFIG_SND_DEBUG=y
|
||||
|
||||
CMI9880
|
||||
minimal 3-jack in back
|
||||
|
@ -1054,6 +1059,13 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-pxa2xx-ac97 (on arm only)
|
||||
------------------------------------
|
||||
|
||||
Module for AC97 driver for the Intel PXA2xx chip
|
||||
|
||||
For ARM architecture only.
|
||||
|
||||
Module snd-rme32
|
||||
----------------
|
||||
|
||||
|
@ -1173,6 +1185,13 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
|
||||
Module supports up to 8 cards.
|
||||
|
||||
Module snd-sun-dbri (on sparc only)
|
||||
-----------------------------------
|
||||
|
||||
Module for DBRI sound chips found on Sparcs.
|
||||
|
||||
Module supports up to 8 cards.
|
||||
|
||||
Module snd-wavefront
|
||||
--------------------
|
||||
|
||||
|
@ -1371,7 +1390,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
Module snd-vxpocket
|
||||
-------------------
|
||||
|
||||
Module for Digigram VX-Pocket VX2 PCMCIA card.
|
||||
Module for Digigram VX-Pocket VX2 and 440 PCMCIA cards.
|
||||
|
||||
ibl - Capture IBL size. (default = 0, minimum size)
|
||||
|
||||
|
@ -1391,29 +1410,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
|
||||
Note: the driver is build only when CONFIG_ISA is set.
|
||||
|
||||
Module snd-vxp440
|
||||
-----------------
|
||||
|
||||
Module for Digigram VX-Pocket 440 PCMCIA card.
|
||||
|
||||
ibl - Capture IBL size. (default = 0, minimum size)
|
||||
|
||||
Module supports up to 8 cards. The module is compiled only when
|
||||
PCMCIA is supported on kernel.
|
||||
|
||||
To activate the driver via the card manager, you'll need to set
|
||||
up /etc/pcmcia/vxp440.conf. See the sound/pcmcia/vx/vxp440.c.
|
||||
|
||||
When the driver is compiled as a module and the hotplug firmware
|
||||
is supported, the firmware data is loaded via hotplug automatically.
|
||||
Install the necessary firmware files in alsa-firmware package.
|
||||
When no hotplug fw loader is available, you need to load the
|
||||
firmware via vxloader utility in alsa-tools package.
|
||||
|
||||
About capture IBL, see the description of snd-vx222 module.
|
||||
|
||||
Note: the driver is build only when CONFIG_ISA is set.
|
||||
|
||||
Module snd-ymfpci
|
||||
-----------------
|
||||
|
||||
|
|
|
@ -132,7 +132,7 @@ to extra work for the USB developers. Since all Linux USB developers do
|
|||
their work on their own time, asking programmers to do extra work for no
|
||||
gain, for free, is not a possibility.
|
||||
|
||||
Security issues are also a very important for Linux. When a
|
||||
Security issues are also very important for Linux. When a
|
||||
security issue is found, it is fixed in a very short amount of time. A
|
||||
number of times this has caused internal kernel interfaces to be
|
||||
reworked to prevent the security problem from occurring. When this
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
Everything you ever wanted to know about Linux 2.6 -stable releases.
|
||||
|
||||
Rules on what kind of patches are accepted, and what ones are not, into
|
||||
the "-stable" tree:
|
||||
|
||||
- It must be obviously correct and tested.
|
||||
- It can not bigger than 100 lines, with context.
|
||||
- It must fix only one thing.
|
||||
- It must fix a real bug that bothers people (not a, "This could be a
|
||||
problem..." type thing.)
|
||||
- It must fix a problem that causes a build error (but not for things
|
||||
marked CONFIG_BROKEN), an oops, a hang, data corruption, a real
|
||||
security issue, or some "oh, that's not good" issue. In short,
|
||||
something critical.
|
||||
- No "theoretical race condition" issues, unless an explanation of how
|
||||
the race can be exploited.
|
||||
- It can not contain any "trivial" fixes in it (spelling changes,
|
||||
whitespace cleanups, etc.)
|
||||
- It must be accepted by the relevant subsystem maintainer.
|
||||
- It must follow Documentation/SubmittingPatches rules.
|
||||
|
||||
|
||||
Procedure for submitting patches to the -stable tree:
|
||||
|
||||
- Send the patch, after verifying that it follows the above rules, to
|
||||
stable@kernel.org.
|
||||
- The sender will receive an ack when the patch has been accepted into
|
||||
the queue, or a nak if the patch is rejected. This response might
|
||||
take a few days, according to the developer's schedules.
|
||||
- If accepted, the patch will be added to the -stable queue, for review
|
||||
by other developers.
|
||||
- Security patches should not be sent to this alias, but instead to the
|
||||
documented security@kernel.org.
|
||||
|
||||
|
||||
Review cycle:
|
||||
|
||||
- When the -stable maintainers decide for a review cycle, the patches
|
||||
will be sent to the review committee, and the maintainer of the
|
||||
affected area of the patch (unless the submitter is the maintainer of
|
||||
the area) and CC: to the linux-kernel mailing list.
|
||||
- The review committee has 48 hours in which to ack or nak the patch.
|
||||
- If the patch is rejected by a member of the committee, or linux-kernel
|
||||
members object to the patch, bringing up issues that the maintainers
|
||||
and members did not realize, the patch will be dropped from the
|
||||
queue.
|
||||
- At the end of the review cycle, the acked patches will be added to
|
||||
the latest -stable release, and a new -stable release will happen.
|
||||
- Security patches will be accepted into the -stable tree directly from
|
||||
the security kernel team, and not go through the normal review cycle.
|
||||
Contact the kernel security team for more details on this procedure.
|
||||
|
||||
|
||||
Review committe:
|
||||
|
||||
- This will be made up of a number of kernel developers who have
|
||||
volunteered for this task, and a few that haven't.
|
||||
|
|
@ -47,7 +47,7 @@ Timing
|
|||
notsc
|
||||
Don't use the CPU time stamp counter to read the wall time.
|
||||
This can be used to work around timing problems on multiprocessor systems
|
||||
with not properly synchronized CPUs. Only useful with a SMP kernel
|
||||
with not properly synchronized CPUs.
|
||||
|
||||
report_lost_ticks
|
||||
Report when timer interrupts are lost because some code turned off
|
||||
|
@ -74,6 +74,9 @@ Idle loop
|
|||
event. This will make the CPUs eat a lot more power, but may be useful
|
||||
to get slightly better performance in multiprocessor benchmarks. It also
|
||||
makes some profiling using performance counters more accurate.
|
||||
Please note that on systems with MONITOR/MWAIT support (like Intel EM64T
|
||||
CPUs) this option has no performance advantage over the normal idle loop.
|
||||
It may also interact badly with hyperthreading.
|
||||
|
||||
Rebooting
|
||||
|
||||
|
@ -178,6 +181,5 @@ Debugging
|
|||
Misc
|
||||
|
||||
noreplacement Don't replace instructions with more appropiate ones
|
||||
for the CPU. This may be useful on asymmetric MP systems
|
||||
where some CPU have less capabilities than the others.
|
||||
|
||||
for the CPU. This may be useful on asymmetric MP systems
|
||||
where some CPU have less capabilities than the others.
|
||||
|
|
21
MAINTAINERS
21
MAINTAINERS
|
@ -1169,6 +1169,12 @@ L: linux-input@atrey.karlin.mff.cuni.cz
|
|||
L: linux-joystick@atrey.karlin.mff.cuni.cz
|
||||
S: Maintained
|
||||
|
||||
INOTIFY
|
||||
P: John McCutchan and Robert Love
|
||||
M: ttb@tentacle.dhs.org and rml@novell.com
|
||||
L: linux-kernel@vger.kernel.org
|
||||
S: Maintained
|
||||
|
||||
INTEL 810/815 FRAMEBUFFER DRIVER
|
||||
P: Antonino Daplas
|
||||
M: adaplas@pol.net
|
||||
|
@ -1410,13 +1416,20 @@ W: http://www.penguinppc.org/
|
|||
L: linuxppc-embedded@ozlabs.org
|
||||
S: Maintained
|
||||
|
||||
LINUX FOR POWERPC EMBEDDED PPC8XX AND BOOT CODE
|
||||
LINUX FOR POWERPC BOOT CODE
|
||||
P: Tom Rini
|
||||
M: trini@kernel.crashing.org
|
||||
W: http://www.penguinppc.org/
|
||||
L: linuxppc-embedded@ozlabs.org
|
||||
S: Maintained
|
||||
|
||||
LINUX FOR POWERPC EMBEDDED PPC8XX
|
||||
P: Marcelo Tosatti
|
||||
M: marcelo.tosatti@cyclades.com
|
||||
W: http://www.penguinppc.org/
|
||||
L: linuxppc-embedded@ozlabs.org
|
||||
S: Maintained
|
||||
|
||||
LINUX FOR POWERPC EMBEDDED PPC83XX AND PPC85XX
|
||||
P: Kumar Gala
|
||||
M: kumar.gala@freescale.com
|
||||
|
@ -2420,6 +2433,12 @@ L: linux-usb-users@lists.sourceforge.net
|
|||
L: linux-usb-devel@lists.sourceforge.net
|
||||
S: Maintained
|
||||
|
||||
USB OPTION-CARD DRIVER
|
||||
P: Matthias Urlichs
|
||||
M: smurf@smurf.noris.de
|
||||
L: linux-usb-devel@lists.sourceforge.net
|
||||
S: Maintained
|
||||
|
||||
USB OV511 DRIVER
|
||||
P: Mark McClelland
|
||||
M: mmcclell@bigfoot.com
|
||||
|
|
2
Makefile
2
Makefile
|
@ -1,7 +1,7 @@
|
|||
VERSION = 2
|
||||
PATCHLEVEL = 6
|
||||
SUBLEVEL = 13
|
||||
EXTRAVERSION =-rc3
|
||||
EXTRAVERSION =-rc4
|
||||
NAME=Woozy Numbat
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
|
10
README
10
README
|
@ -87,6 +87,16 @@ INSTALLING the kernel:
|
|||
kernel source. Patches are applied from the current directory, but
|
||||
an alternative directory can be specified as the second argument.
|
||||
|
||||
- If you are upgrading between releases using the stable series patches
|
||||
(for example, patch-2.6.xx.y), note that these "dot-releases" are
|
||||
not incremental and must be applied to the 2.6.xx base tree. For
|
||||
example, if your base kernel is 2.6.12 and you want to apply the
|
||||
2.6.12.3 patch, you do not and indeed must not first apply the
|
||||
2.6.12.1 and 2.6.12.2 patches. Similarly, if you are running kernel
|
||||
version 2.6.12.2 and want to jump to 2.6.12.3, you must first
|
||||
reverse the 2.6.12.2 patch (that is, patch -R) _before_ applying
|
||||
the 2.6.12.3 patch.
|
||||
|
||||
- Make sure you have no stale .o files and dependencies lying around:
|
||||
|
||||
cd linux
|
||||
|
|
|
@ -165,7 +165,6 @@ machine_restart(char *restart_cmd)
|
|||
common_shutdown(LINUX_REBOOT_CMD_RESTART, restart_cmd);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(machine_restart);
|
||||
|
||||
void
|
||||
machine_halt(void)
|
||||
|
@ -173,7 +172,6 @@ machine_halt(void)
|
|||
common_shutdown(LINUX_REBOOT_CMD_HALT, NULL);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(machine_halt);
|
||||
|
||||
void
|
||||
machine_power_off(void)
|
||||
|
@ -181,7 +179,6 @@ machine_power_off(void)
|
|||
common_shutdown(LINUX_REBOOT_CMD_POWER_OFF, NULL);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(machine_power_off);
|
||||
|
||||
/* Used by sysrq-p, among others. I don't believe r9-r15 are ever
|
||||
saved in the context it's used. */
|
||||
|
|
|
@ -461,6 +461,11 @@ sys_call_table:
|
|||
.quad sys_add_key
|
||||
.quad sys_request_key /* 440 */
|
||||
.quad sys_keyctl
|
||||
.quad sys_ioprio_set
|
||||
.quad sys_ioprio_get
|
||||
.quad sys_inotify_init
|
||||
.quad sys_inotify_add_watch /* 445 */
|
||||
.quad sys_inotify_rm_watch
|
||||
|
||||
.size sys_call_table, . - sys_call_table
|
||||
.type sys_call_table, @object
|
||||
|
|
|
@ -63,8 +63,8 @@ __beginning: mov r4, r0 @ save the entry to the firmware
|
|||
|
||||
mov pc, r2
|
||||
|
||||
__copy_target: .long 0x08508000
|
||||
__copy_end: .long 0x08608000
|
||||
__copy_target: .long 0x08507FFC
|
||||
__copy_end: .long 0x08607FFC
|
||||
|
||||
.word _start
|
||||
.word __bss_start
|
||||
|
@ -73,9 +73,10 @@ __copy_end: .long 0x08608000
|
|||
__temp_stack: .space 128
|
||||
|
||||
__mmu_off:
|
||||
adr r0, __ofw_data
|
||||
adr r0, __ofw_data @ read the 1. entry of the memory map
|
||||
ldr r0, [r0, #4]
|
||||
orr r0, r0, #0x00600000
|
||||
sub r0, r0, #4
|
||||
|
||||
ldr r1, __copy_end
|
||||
ldr r3, __copy_target
|
||||
|
@ -89,20 +90,43 @@ __mmu_off:
|
|||
* from 0x08500000 to 0x08508000 if we have only 8MB
|
||||
*/
|
||||
|
||||
/* As we get more 2.6-kernels it gets more and more
|
||||
* uncomfortable to be bound to kernel images of 1MB only.
|
||||
* So we add a loop here, to be able to copy some more.
|
||||
* Alexander Schulz 2005-07-17
|
||||
*/
|
||||
|
||||
mov r4, #3 @ How many megabytes to copy
|
||||
|
||||
|
||||
__MoveCode: sub r4, r4, #1
|
||||
|
||||
__Copy: ldr r2, [r0], #-4
|
||||
str r2, [r1], #-4
|
||||
teq r1, r3
|
||||
bne __Copy
|
||||
|
||||
/* The firmware maps us in blocks of 1 MB, the next block is
|
||||
_below_ the last one. So our decrementing source pointer
|
||||
ist right here, but the destination pointer must be increased
|
||||
by 2 MB */
|
||||
add r1, r1, #0x00200000
|
||||
add r3, r3, #0x00100000
|
||||
|
||||
teq r4, #0
|
||||
bne __MoveCode
|
||||
|
||||
|
||||
/* and jump to it */
|
||||
adr r2, __go_on
|
||||
adr r0, __ofw_data
|
||||
adr r2, __go_on @ where we want to jump
|
||||
adr r0, __ofw_data @ read the 1. entry of the memory map
|
||||
ldr r0, [r0, #4]
|
||||
sub r2, r2, r0
|
||||
sub r2, r2, #0x00500000
|
||||
ldr r0, __copy_target
|
||||
sub r2, r2, r0 @ we are mapped add 0e50 now, sub that (-0e00)
|
||||
sub r2, r2, #0x00500000 @ -0050
|
||||
ldr r0, __copy_target @ and add 0850 8000 instead
|
||||
add r0, r0, #4
|
||||
add r2, r2, r0
|
||||
mov pc, r2
|
||||
mov pc, r2 @ and jump there
|
||||
|
||||
__go_on:
|
||||
adr sp, __temp_stack
|
||||
|
|
|
@ -561,7 +561,6 @@ CONFIG_SERIAL_8250_SHARE_IRQ=y
|
|||
#
|
||||
CONFIG_SERIAL_S3C2410=y
|
||||
CONFIG_SERIAL_S3C2410_CONSOLE=y
|
||||
CONFIG_SERIAL_BAST_SIO=y
|
||||
CONFIG_SERIAL_CORE=y
|
||||
CONFIG_SERIAL_CORE_CONSOLE=y
|
||||
CONFIG_UNIX98_PTYS=y
|
||||
|
|
|
@ -570,7 +570,6 @@ CONFIG_SERIAL_8250_SHARE_IRQ=y
|
|||
#
|
||||
CONFIG_SERIAL_S3C2410=y
|
||||
CONFIG_SERIAL_S3C2410_CONSOLE=y
|
||||
CONFIG_SERIAL_BAST_SIO=y
|
||||
CONFIG_SERIAL_CORE=y
|
||||
CONFIG_SERIAL_CORE_CONSOLE=y
|
||||
CONFIG_UNIX98_PTYS=y
|
||||
|
|
|
@ -1,22 +1,21 @@
|
|||
#
|
||||
# Automatically generated make config: don't edit
|
||||
# Linux kernel version: 2.6.12-rc1-bk2
|
||||
# Sun Mar 27 23:59:14 2005
|
||||
# Linux kernel version: 2.6.12-git3
|
||||
# Sat Jul 16 15:21:47 2005
|
||||
#
|
||||
CONFIG_ARM=y
|
||||
CONFIG_MMU=y
|
||||
CONFIG_UID16=y
|
||||
CONFIG_RWSEM_GENERIC_SPINLOCK=y
|
||||
CONFIG_GENERIC_CALIBRATE_DELAY=y
|
||||
CONFIG_GENERIC_IOMAP=y
|
||||
|
||||
#
|
||||
# Code maturity level options
|
||||
#
|
||||
CONFIG_EXPERIMENTAL=y
|
||||
# CONFIG_CLEAN_COMPILE is not set
|
||||
CONFIG_BROKEN=y
|
||||
CONFIG_CLEAN_COMPILE=y
|
||||
CONFIG_BROKEN_ON_SMP=y
|
||||
CONFIG_INIT_ENV_ARG_LIMIT=32
|
||||
|
||||
#
|
||||
# General setup
|
||||
|
@ -33,7 +32,10 @@ CONFIG_KOBJECT_UEVENT=y
|
|||
# CONFIG_IKCONFIG is not set
|
||||
# CONFIG_EMBEDDED is not set
|
||||
CONFIG_KALLSYMS=y
|
||||
# CONFIG_KALLSYMS_ALL is not set
|
||||
# CONFIG_KALLSYMS_EXTRA_PASS is not set
|
||||
CONFIG_PRINTK=y
|
||||
CONFIG_BUG=y
|
||||
CONFIG_BASE_FULL=y
|
||||
CONFIG_FUTEX=y
|
||||
CONFIG_EPOLL=y
|
||||
|
@ -81,6 +83,7 @@ CONFIG_ARCH_SHARK=y
|
|||
# CONFIG_ARCH_VERSATILE is not set
|
||||
# CONFIG_ARCH_IMX is not set
|
||||
# CONFIG_ARCH_H720X is not set
|
||||
# CONFIG_ARCH_AAEC2000 is not set
|
||||
|
||||
#
|
||||
# Processor Type
|
||||
|
@ -103,10 +106,12 @@ CONFIG_CPU_TLB_V4WB=y
|
|||
#
|
||||
CONFIG_ISA=y
|
||||
CONFIG_ISA_DMA=y
|
||||
CONFIG_ISA_DMA_API=y
|
||||
CONFIG_PCI=y
|
||||
CONFIG_PCI_HOST_VIA82C505=y
|
||||
CONFIG_PCI_LEGACY_PROC=y
|
||||
# CONFIG_PCI_NAMES is not set
|
||||
# CONFIG_PCI_DEBUG is not set
|
||||
|
||||
#
|
||||
# PCCARD (PCMCIA/CardBus) support
|
||||
|
@ -116,7 +121,9 @@ CONFIG_PCI_LEGACY_PROC=y
|
|||
#
|
||||
# Kernel Features
|
||||
#
|
||||
# CONFIG_SMP is not set
|
||||
# CONFIG_PREEMPT is not set
|
||||
# CONFIG_DISCONTIGMEM is not set
|
||||
CONFIG_LEDS=y
|
||||
CONFIG_LEDS_TIMER=y
|
||||
# CONFIG_LEDS_CPU is not set
|
||||
|
@ -163,6 +170,7 @@ CONFIG_BINFMT_ELF=y
|
|||
# CONFIG_STANDALONE is not set
|
||||
CONFIG_PREVENT_FIRMWARE_BUILD=y
|
||||
# CONFIG_FW_LOADER is not set
|
||||
# CONFIG_DEBUG_DRIVER is not set
|
||||
|
||||
#
|
||||
# Memory Technology Devices (MTD)
|
||||
|
@ -172,8 +180,8 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
|
|||
#
|
||||
# Parallel port support
|
||||
#
|
||||
CONFIG_PARPORT=y
|
||||
CONFIG_PARPORT_PC=y
|
||||
CONFIG_PARPORT=m
|
||||
CONFIG_PARPORT_PC=m
|
||||
# CONFIG_PARPORT_SERIAL is not set
|
||||
# CONFIG_PARPORT_PC_FIFO is not set
|
||||
# CONFIG_PARPORT_PC_SUPERIO is not set
|
||||
|
@ -189,7 +197,6 @@ CONFIG_PARPORT_PC=y
|
|||
#
|
||||
# Block devices
|
||||
#
|
||||
# CONFIG_BLK_DEV_FD is not set
|
||||
# CONFIG_BLK_DEV_XD is not set
|
||||
# CONFIG_PARIDE is not set
|
||||
# CONFIG_BLK_CPQ_DA is not set
|
||||
|
@ -229,7 +236,7 @@ CONFIG_BLK_DEV_IDE=y
|
|||
# CONFIG_BLK_DEV_IDE_SATA is not set
|
||||
CONFIG_BLK_DEV_IDEDISK=y
|
||||
# CONFIG_IDEDISK_MULTI_MODE is not set
|
||||
CONFIG_BLK_DEV_IDECD=y
|
||||
CONFIG_BLK_DEV_IDECD=m
|
||||
# CONFIG_BLK_DEV_IDETAPE is not set
|
||||
CONFIG_BLK_DEV_IDEFLOPPY=y
|
||||
# CONFIG_BLK_DEV_IDESCSI is not set
|
||||
|
@ -261,6 +268,7 @@ CONFIG_CHR_DEV_ST=m
|
|||
CONFIG_BLK_DEV_SR=m
|
||||
# CONFIG_BLK_DEV_SR_VENDOR is not set
|
||||
CONFIG_CHR_DEV_SG=m
|
||||
# CONFIG_CHR_DEV_SCH is not set
|
||||
|
||||
#
|
||||
# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
|
||||
|
@ -290,17 +298,14 @@ CONFIG_CHR_DEV_SG=m
|
|||
# CONFIG_SCSI_AIC7XXX_OLD is not set
|
||||
# CONFIG_SCSI_AIC79XX is not set
|
||||
# CONFIG_SCSI_DPT_I2O is not set
|
||||
# CONFIG_SCSI_ADVANSYS is not set
|
||||
# CONFIG_SCSI_IN2000 is not set
|
||||
# CONFIG_MEGARAID_NEWGEN is not set
|
||||
# CONFIG_MEGARAID_LEGACY is not set
|
||||
# CONFIG_SCSI_SATA is not set
|
||||
# CONFIG_SCSI_BUSLOGIC is not set
|
||||
# CONFIG_SCSI_CPQFCTS is not set
|
||||
# CONFIG_SCSI_DMX3191D is not set
|
||||
# CONFIG_SCSI_DTC3280 is not set
|
||||
# CONFIG_SCSI_EATA is not set
|
||||
# CONFIG_SCSI_EATA_PIO is not set
|
||||
# CONFIG_SCSI_FUTURE_DOMAIN is not set
|
||||
# CONFIG_SCSI_GDTH is not set
|
||||
# CONFIG_SCSI_GENERIC_NCR5380 is not set
|
||||
|
@ -314,11 +319,8 @@ CONFIG_CHR_DEV_SG=m
|
|||
# CONFIG_SCSI_SYM53C8XX_2 is not set
|
||||
# CONFIG_SCSI_IPR is not set
|
||||
# CONFIG_SCSI_PAS16 is not set
|
||||
# CONFIG_SCSI_PCI2000 is not set
|
||||
# CONFIG_SCSI_PCI2220I is not set
|
||||
# CONFIG_SCSI_PSI240I is not set
|
||||
# CONFIG_SCSI_QLOGIC_FAS is not set
|
||||
# CONFIG_SCSI_QLOGIC_ISP is not set
|
||||
# CONFIG_SCSI_QLOGIC_FC is not set
|
||||
# CONFIG_SCSI_QLOGIC_1280 is not set
|
||||
CONFIG_SCSI_QLA2XXX=m
|
||||
|
@ -327,6 +329,7 @@ CONFIG_SCSI_QLA2XXX=m
|
|||
# CONFIG_SCSI_QLA2300 is not set
|
||||
# CONFIG_SCSI_QLA2322 is not set
|
||||
# CONFIG_SCSI_QLA6312 is not set
|
||||
# CONFIG_SCSI_LPFC is not set
|
||||
# CONFIG_SCSI_SYM53C416 is not set
|
||||
# CONFIG_SCSI_DC395x is not set
|
||||
# CONFIG_SCSI_DC390T is not set
|
||||
|
@ -344,6 +347,8 @@ CONFIG_SCSI_QLA2XXX=m
|
|||
# Fusion MPT device support
|
||||
#
|
||||
# CONFIG_FUSION is not set
|
||||
# CONFIG_FUSION_SPI is not set
|
||||
# CONFIG_FUSION_FC is not set
|
||||
|
||||
#
|
||||
# IEEE 1394 (FireWire) support
|
||||
|
@ -365,7 +370,6 @@ CONFIG_NET=y
|
|||
#
|
||||
CONFIG_PACKET=y
|
||||
# CONFIG_PACKET_MMAP is not set
|
||||
# CONFIG_NETLINK_DEV is not set
|
||||
CONFIG_UNIX=y
|
||||
# CONFIG_NET_KEY is not set
|
||||
CONFIG_INET=y
|
||||
|
@ -380,7 +384,7 @@ CONFIG_INET=y
|
|||
# CONFIG_INET_ESP is not set
|
||||
# CONFIG_INET_IPCOMP is not set
|
||||
# CONFIG_INET_TUNNEL is not set
|
||||
# CONFIG_IP_TCPDIAG is not set
|
||||
CONFIG_IP_TCPDIAG=y
|
||||
# CONFIG_IP_TCPDIAG_IPV6 is not set
|
||||
# CONFIG_IPV6 is not set
|
||||
# CONFIG_NETFILTER is not set
|
||||
|
@ -439,6 +443,7 @@ CONFIG_NET_ETHERNET=y
|
|||
# CONFIG_LANCE is not set
|
||||
# CONFIG_NET_VENDOR_SMC is not set
|
||||
# CONFIG_SMC91X is not set
|
||||
# CONFIG_DM9000 is not set
|
||||
# CONFIG_NET_VENDOR_RACAL is not set
|
||||
|
||||
#
|
||||
|
@ -483,9 +488,11 @@ CONFIG_CS89x0=y
|
|||
# CONFIG_HAMACHI is not set
|
||||
# CONFIG_YELLOWFIN is not set
|
||||
# CONFIG_R8169 is not set
|
||||
# CONFIG_SKGE is not set
|
||||
# CONFIG_SK98LIN is not set
|
||||
# CONFIG_VIA_VELOCITY is not set
|
||||
# CONFIG_TIGON3 is not set
|
||||
# CONFIG_BNX2 is not set
|
||||
|
||||
#
|
||||
# Ethernet (10000 Mbit)
|
||||
|
@ -569,7 +576,6 @@ CONFIG_SERIO_I8042=y
|
|||
CONFIG_SERIO_LIBPS2=y
|
||||
# CONFIG_SERIO_RAW is not set
|
||||
# CONFIG_GAMEPORT is not set
|
||||
CONFIG_SOUND_GAMEPORT=y
|
||||
|
||||
#
|
||||
# Character devices
|
||||
|
@ -592,6 +598,7 @@ CONFIG_SERIAL_8250_NR_UARTS=4
|
|||
#
|
||||
CONFIG_SERIAL_CORE=y
|
||||
CONFIG_SERIAL_CORE_CONSOLE=y
|
||||
# CONFIG_SERIAL_JSM is not set
|
||||
CONFIG_UNIX98_PTYS=y
|
||||
CONFIG_LEGACY_PTYS=y
|
||||
CONFIG_LEGACY_PTY_COUNT=256
|
||||
|
@ -653,6 +660,7 @@ CONFIG_FB_CFB_FILLRECT=y
|
|||
CONFIG_FB_CFB_COPYAREA=y
|
||||
CONFIG_FB_CFB_IMAGEBLIT=y
|
||||
CONFIG_FB_SOFT_CURSOR=y
|
||||
# CONFIG_FB_MACMODES is not set
|
||||
# CONFIG_FB_MODE_HELPERS is not set
|
||||
# CONFIG_FB_TILEBLITTING is not set
|
||||
# CONFIG_FB_CIRRUS is not set
|
||||
|
@ -674,7 +682,7 @@ CONFIG_FB_CYBER2000=y
|
|||
# CONFIG_FB_3DFX is not set
|
||||
# CONFIG_FB_VOODOO1 is not set
|
||||
# CONFIG_FB_TRIDENT is not set
|
||||
# CONFIG_FB_PM3 is not set
|
||||
# CONFIG_FB_S1D13XXX is not set
|
||||
# CONFIG_FB_VIRTUAL is not set
|
||||
|
||||
#
|
||||
|
@ -808,7 +816,7 @@ CONFIG_DNOTIFY=y
|
|||
#
|
||||
# CD-ROM/DVD Filesystems
|
||||
#
|
||||
CONFIG_ISO9660_FS=y
|
||||
CONFIG_ISO9660_FS=m
|
||||
CONFIG_JOLIET=y
|
||||
# CONFIG_ZISOFS is not set
|
||||
# CONFIG_UDF_FS is not set
|
||||
|
@ -816,9 +824,9 @@ CONFIG_JOLIET=y
|
|||
#
|
||||
# DOS/FAT/NT Filesystems
|
||||
#
|
||||
CONFIG_FAT_FS=y
|
||||
CONFIG_MSDOS_FS=y
|
||||
CONFIG_VFAT_FS=y
|
||||
CONFIG_FAT_FS=m
|
||||
CONFIG_MSDOS_FS=m
|
||||
CONFIG_VFAT_FS=m
|
||||
CONFIG_FAT_DEFAULT_CODEPAGE=437
|
||||
CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
|
||||
# CONFIG_NTFS_FS is not set
|
||||
|
@ -833,7 +841,6 @@ CONFIG_DEVFS_MOUNT=y
|
|||
# CONFIG_DEVFS_DEBUG is not set
|
||||
# CONFIG_DEVPTS_FS_XATTR is not set
|
||||
# CONFIG_TMPFS is not set
|
||||
# CONFIG_HUGETLBFS is not set
|
||||
# CONFIG_HUGETLB_PAGE is not set
|
||||
CONFIG_RAMFS=y
|
||||
|
||||
|
@ -857,13 +864,14 @@ CONFIG_RAMFS=y
|
|||
#
|
||||
# Network File Systems
|
||||
#
|
||||
CONFIG_NFS_FS=y
|
||||
# CONFIG_NFS_V3 is not set
|
||||
CONFIG_NFS_FS=m
|
||||
CONFIG_NFS_V3=y
|
||||
# CONFIG_NFS_V4 is not set
|
||||
# CONFIG_NFS_DIRECTIO is not set
|
||||
# CONFIG_NFSD is not set
|
||||
CONFIG_LOCKD=y
|
||||
CONFIG_SUNRPC=y
|
||||
CONFIG_LOCKD=m
|
||||
CONFIG_LOCKD_V4=y
|
||||
CONFIG_SUNRPC=m
|
||||
# CONFIG_RPCSEC_GSS_KRB5 is not set
|
||||
# CONFIG_RPCSEC_GSS_SPKM3 is not set
|
||||
# CONFIG_SMB_FS is not set
|
||||
|
@ -895,12 +903,12 @@ CONFIG_MSDOS_PARTITION=y
|
|||
#
|
||||
# Native Language Support
|
||||
#
|
||||
CONFIG_NLS=y
|
||||
CONFIG_NLS=m
|
||||
CONFIG_NLS_DEFAULT="iso8859-1"
|
||||
CONFIG_NLS_CODEPAGE_437=y
|
||||
CONFIG_NLS_CODEPAGE_437=m
|
||||
# CONFIG_NLS_CODEPAGE_737 is not set
|
||||
# CONFIG_NLS_CODEPAGE_775 is not set
|
||||
CONFIG_NLS_CODEPAGE_850=y
|
||||
CONFIG_NLS_CODEPAGE_850=m
|
||||
# CONFIG_NLS_CODEPAGE_852 is not set
|
||||
# CONFIG_NLS_CODEPAGE_855 is not set
|
||||
# CONFIG_NLS_CODEPAGE_857 is not set
|
||||
|
@ -921,7 +929,7 @@ CONFIG_NLS_CODEPAGE_850=y
|
|||
# CONFIG_NLS_CODEPAGE_1250 is not set
|
||||
# CONFIG_NLS_CODEPAGE_1251 is not set
|
||||
# CONFIG_NLS_ASCII is not set
|
||||
CONFIG_NLS_ISO8859_1=y
|
||||
CONFIG_NLS_ISO8859_1=m
|
||||
# CONFIG_NLS_ISO8859_2 is not set
|
||||
# CONFIG_NLS_ISO8859_3 is not set
|
||||
# CONFIG_NLS_ISO8859_4 is not set
|
||||
|
@ -945,11 +953,22 @@ CONFIG_NLS_ISO8859_1=y
|
|||
# Kernel hacking
|
||||
#
|
||||
# CONFIG_PRINTK_TIME is not set
|
||||
# CONFIG_DEBUG_KERNEL is not set
|
||||
CONFIG_DEBUG_KERNEL=y
|
||||
# CONFIG_MAGIC_SYSRQ is not set
|
||||
CONFIG_LOG_BUF_SHIFT=14
|
||||
# CONFIG_SCHEDSTATS is not set
|
||||
# CONFIG_DEBUG_SLAB is not set
|
||||
# CONFIG_DEBUG_SPINLOCK is not set
|
||||
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
|
||||
# CONFIG_DEBUG_KOBJECT is not set
|
||||
CONFIG_DEBUG_BUGVERBOSE=y
|
||||
# CONFIG_DEBUG_INFO is not set
|
||||
# CONFIG_DEBUG_FS is not set
|
||||
CONFIG_FRAME_POINTER=y
|
||||
CONFIG_DEBUG_USER=y
|
||||
# CONFIG_DEBUG_WAITQ is not set
|
||||
# CONFIG_DEBUG_ERRORS is not set
|
||||
# CONFIG_DEBUG_LL is not set
|
||||
|
||||
#
|
||||
# Security options
|
||||
|
|
|
@ -131,7 +131,6 @@ void machine_halt(void)
|
|||
{
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(machine_halt);
|
||||
|
||||
void machine_power_off(void)
|
||||
{
|
||||
|
@ -139,7 +138,6 @@ void machine_power_off(void)
|
|||
pm_power_off();
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(machine_power_off);
|
||||
|
||||
void machine_restart(char * __unused)
|
||||
{
|
||||
|
@ -169,8 +167,6 @@ void machine_restart(char * __unused)
|
|||
while (1);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(machine_restart);
|
||||
|
||||
void __show_regs(struct pt_regs *regs)
|
||||
{
|
||||
unsigned long flags = condition_codes(regs);
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
* The present bitmask indicates that the CPU is physically present.
|
||||
* The online bitmask indicates that the CPU is up and running.
|
||||
*/
|
||||
cpumask_t cpu_present_mask;
|
||||
cpumask_t cpu_possible_map;
|
||||
cpumask_t cpu_online_map;
|
||||
|
||||
/*
|
||||
|
@ -78,7 +78,7 @@ struct smp_call_struct {
|
|||
static struct smp_call_struct * volatile smp_call_function_data;
|
||||
static DEFINE_SPINLOCK(smp_call_function_lock);
|
||||
|
||||
int __init __cpu_up(unsigned int cpu)
|
||||
int __cpuinit __cpu_up(unsigned int cpu)
|
||||
{
|
||||
struct task_struct *idle;
|
||||
pgd_t *pgd;
|
||||
|
@ -159,7 +159,7 @@ int __init __cpu_up(unsigned int cpu)
|
|||
* This is the secondary CPU boot entry. We're using this CPUs
|
||||
* idle thread stack, but a set of temporary page tables.
|
||||
*/
|
||||
asmlinkage void __init secondary_start_kernel(void)
|
||||
asmlinkage void __cpuinit secondary_start_kernel(void)
|
||||
{
|
||||
struct mm_struct *mm = &init_mm;
|
||||
unsigned int cpu = smp_processor_id();
|
||||
|
@ -176,6 +176,7 @@ asmlinkage void __init secondary_start_kernel(void)
|
|||
cpu_set(cpu, mm->cpu_vm_mask);
|
||||
cpu_switch_mm(mm->pgd, mm);
|
||||
enter_lazy_tlb(mm, current);
|
||||
local_flush_tlb_all();
|
||||
|
||||
cpu_init();
|
||||
|
||||
|
@ -209,7 +210,7 @@ asmlinkage void __init secondary_start_kernel(void)
|
|||
* Called by both boot and secondaries to move global data into
|
||||
* per-processor storage.
|
||||
*/
|
||||
void __init smp_store_cpu_info(unsigned int cpuid)
|
||||
void __cpuinit smp_store_cpu_info(unsigned int cpuid)
|
||||
{
|
||||
struct cpuinfo_arm *cpu_info = &per_cpu(cpu_data, cpuid);
|
||||
|
||||
|
@ -235,7 +236,8 @@ void __init smp_prepare_boot_cpu(void)
|
|||
{
|
||||
unsigned int cpu = smp_processor_id();
|
||||
|
||||
cpu_set(cpu, cpu_present_mask);
|
||||
cpu_set(cpu, cpu_possible_map);
|
||||
cpu_set(cpu, cpu_present_map);
|
||||
cpu_set(cpu, cpu_online_map);
|
||||
}
|
||||
|
||||
|
@ -355,7 +357,7 @@ void show_ipi_list(struct seq_file *p)
|
|||
|
||||
seq_puts(p, "IPI:");
|
||||
|
||||
for_each_online_cpu(cpu)
|
||||
for_each_present_cpu(cpu)
|
||||
seq_printf(p, " %10lu", per_cpu(ipi_data, cpu).ipi_count);
|
||||
|
||||
seq_putc(p, '\n');
|
||||
|
|
|
@ -248,16 +248,20 @@ static DEFINE_SPINLOCK(undef_lock);
|
|||
|
||||
void register_undef_hook(struct undef_hook *hook)
|
||||
{
|
||||
spin_lock_irq(&undef_lock);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&undef_lock, flags);
|
||||
list_add(&hook->node, &undef_hook);
|
||||
spin_unlock_irq(&undef_lock);
|
||||
spin_unlock_irqrestore(&undef_lock, flags);
|
||||
}
|
||||
|
||||
void unregister_undef_hook(struct undef_hook *hook)
|
||||
{
|
||||
spin_lock_irq(&undef_lock);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&undef_lock, flags);
|
||||
list_del(&hook->node);
|
||||
spin_unlock_irq(&undef_lock);
|
||||
spin_unlock_irqrestore(&undef_lock, flags);
|
||||
}
|
||||
|
||||
asmlinkage void do_undefinstr(struct pt_regs *regs)
|
||||
|
|
|
@ -1,3 +1,33 @@
|
|||
#if __LINUX_ARM_ARCH__ >= 6
|
||||
.macro bitop, instr
|
||||
mov r2, #1
|
||||
and r3, r0, #7 @ Get bit offset
|
||||
add r1, r1, r0, lsr #3 @ Get byte offset
|
||||
mov r3, r2, lsl r3
|
||||
1: ldrexb r2, [r1]
|
||||
\instr r2, r2, r3
|
||||
strexb r0, r2, [r1]
|
||||
cmp r0, #0
|
||||
bne 1b
|
||||
mov pc, lr
|
||||
.endm
|
||||
|
||||
.macro testop, instr, store
|
||||
and r3, r0, #7 @ Get bit offset
|
||||
mov r2, #1
|
||||
add r1, r1, r0, lsr #3 @ Get byte offset
|
||||
mov r3, r2, lsl r3 @ create mask
|
||||
1: ldrexb r2, [r1]
|
||||
ands r0, r2, r3 @ save old value of bit
|
||||
\instr r2, r2, r3 @ toggle bit
|
||||
strexb ip, r2, [r1]
|
||||
cmp ip, #0
|
||||
bne 1b
|
||||
cmp r0, #0
|
||||
movne r0, #1
|
||||
2: mov pc, lr
|
||||
.endm
|
||||
#else
|
||||
.macro bitop, instr
|
||||
and r2, r0, #7
|
||||
mov r3, #1
|
||||
|
@ -31,3 +61,4 @@
|
|||
moveq r0, #0
|
||||
mov pc, lr
|
||||
.endm
|
||||
#endif
|
||||
|
|
|
@ -11,73 +11,3 @@
|
|||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
|
||||
void print_warning(void)
|
||||
{
|
||||
printk(KERN_WARNING "ins?/outs? not implemented on this architecture\n");
|
||||
}
|
||||
|
||||
void insl(unsigned int port, void *to, int len)
|
||||
{
|
||||
print_warning();
|
||||
}
|
||||
|
||||
void insb(unsigned int port, void *to, int len)
|
||||
{
|
||||
print_warning();
|
||||
}
|
||||
|
||||
void outsl(unsigned int port, const void *from, int len)
|
||||
{
|
||||
print_warning();
|
||||
}
|
||||
|
||||
void outsb(unsigned int port, const void *from, int len)
|
||||
{
|
||||
print_warning();
|
||||
}
|
||||
|
||||
/* these should be in assembler again */
|
||||
|
||||
/*
|
||||
* Purpose: read a block of data from a hardware register to memory.
|
||||
* Proto : insw(int from_port, void *to, int len_in_words);
|
||||
* Proto : inswb(int from_port, void *to, int len_in_bytes);
|
||||
* Notes : increment to
|
||||
*/
|
||||
|
||||
void insw(unsigned int port, void *to, int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
((unsigned short *) to)[i] = inw(port);
|
||||
}
|
||||
|
||||
void inswb(unsigned int port, void *to, int len)
|
||||
{
|
||||
insw(port, to, len >> 2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Purpose: write a block of data from memory to a hardware register.
|
||||
* Proto : outsw(int to_reg, void *from, int len_in_words);
|
||||
* Proto : outswb(int to_reg, void *from, int len_in_bytes);
|
||||
* Notes : increments from
|
||||
*/
|
||||
|
||||
void outsw(unsigned int port, const void *from, int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
outw(((unsigned short *) from)[i], port);
|
||||
}
|
||||
|
||||
void outswb(unsigned int port, const void *from, int len)
|
||||
{
|
||||
outsw(port, from, len >> 2);
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <linux/mm.h>
|
||||
|
||||
#include <asm/atomic.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/delay.h>
|
||||
#include <asm/mmu_context.h>
|
||||
#include <asm/procinfo.h>
|
||||
|
@ -27,12 +28,12 @@ extern void integrator_secondary_startup(void);
|
|||
* control for which core is the next to come out of the secondary
|
||||
* boot "holding pen"
|
||||
*/
|
||||
volatile int __initdata pen_release = -1;
|
||||
unsigned long __initdata phys_pen_release = 0;
|
||||
volatile int __cpuinitdata pen_release = -1;
|
||||
unsigned long __cpuinitdata phys_pen_release = 0;
|
||||
|
||||
static DEFINE_SPINLOCK(boot_lock);
|
||||
|
||||
void __init platform_secondary_init(unsigned int cpu)
|
||||
void __cpuinit platform_secondary_init(unsigned int cpu)
|
||||
{
|
||||
/*
|
||||
* the primary core may have used a "cross call" soft interrupt
|
||||
|
@ -61,7 +62,7 @@ void __init platform_secondary_init(unsigned int cpu)
|
|||
spin_unlock(&boot_lock);
|
||||
}
|
||||
|
||||
int __init boot_secondary(unsigned int cpu, struct task_struct *idle)
|
||||
int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
|
||||
{
|
||||
unsigned long timeout;
|
||||
|
||||
|
@ -80,6 +81,7 @@ int __init boot_secondary(unsigned int cpu, struct task_struct *idle)
|
|||
* "cpu" is Linux's internal ID.
|
||||
*/
|
||||
pen_release = cpu;
|
||||
flush_cache_all();
|
||||
|
||||
/*
|
||||
* XXX
|
||||
|
@ -174,11 +176,13 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
|
|||
max_cpus = ncores;
|
||||
|
||||
/*
|
||||
* Initialise the present mask - this tells us which CPUs should
|
||||
* be present.
|
||||
* Initialise the possible/present maps.
|
||||
* cpu_possible_map describes the set of CPUs which may be present
|
||||
* cpu_present_map describes the set of CPUs populated
|
||||
*/
|
||||
for (i = 0; i < max_cpus; i++) {
|
||||
cpu_set(i, cpu_present_mask);
|
||||
cpu_set(i, cpu_possible_map);
|
||||
cpu_set(i, cpu_present_map);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/kernel_stat.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/hardware.h>
|
||||
|
|
|
@ -23,6 +23,8 @@ obj-$(CONFIG_PM_SIMTEC) += pm-simtec.o
|
|||
# S3C2440 support
|
||||
|
||||
obj-$(CONFIG_CPU_S3C2440) += s3c2440.o s3c2440-dsc.o
|
||||
obj-$(CONFIG_CPU_S3C2440) += s3c2440-irq.o
|
||||
obj-$(CONFIG_CPU_S3C2440) += s3c2440-clock.o
|
||||
|
||||
# machine specific support
|
||||
|
||||
|
|
|
@ -448,60 +448,3 @@ int __init s3c24xx_setup_clocks(unsigned long xtal,
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* S3C2440 extended clock support */
|
||||
|
||||
#ifdef CONFIG_CPU_S3C2440
|
||||
|
||||
static struct clk s3c2440_clk_upll = {
|
||||
.name = "upll",
|
||||
.id = -1,
|
||||
};
|
||||
|
||||
static struct clk s3c2440_clk_cam = {
|
||||
.name = "camif",
|
||||
.parent = &clk_h,
|
||||
.id = -1,
|
||||
.enable = s3c24xx_clkcon_enable,
|
||||
.ctrlbit = S3C2440_CLKCON_CAMERA,
|
||||
};
|
||||
|
||||
static struct clk s3c2440_clk_ac97 = {
|
||||
.name = "ac97",
|
||||
.parent = &clk_p,
|
||||
.id = -1,
|
||||
.enable = s3c24xx_clkcon_enable,
|
||||
.ctrlbit = S3C2440_CLKCON_CAMERA,
|
||||
};
|
||||
|
||||
static int s3c2440_clk_add(struct sys_device *sysdev)
|
||||
{
|
||||
unsigned long upllcon = __raw_readl(S3C2410_UPLLCON);
|
||||
|
||||
s3c2440_clk_upll.rate = s3c2410_get_pll(upllcon, clk_xtal.rate);
|
||||
|
||||
printk("S3C2440: Clock Support, UPLL %ld.%03ld MHz\n",
|
||||
print_mhz(s3c2440_clk_upll.rate));
|
||||
|
||||
s3c24xx_register_clock(&s3c2440_clk_ac97);
|
||||
s3c24xx_register_clock(&s3c2440_clk_cam);
|
||||
s3c24xx_register_clock(&s3c2440_clk_upll);
|
||||
|
||||
clk_disable(&s3c2440_clk_ac97);
|
||||
clk_disable(&s3c2440_clk_cam);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct sysdev_driver s3c2440_clk_driver = {
|
||||
.add = s3c2440_clk_add,
|
||||
};
|
||||
|
||||
static int s3c24xx_clk_driver(void)
|
||||
{
|
||||
return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_clk_driver);
|
||||
}
|
||||
|
||||
arch_initcall(s3c24xx_clk_driver);
|
||||
|
||||
#endif /* CONFIG_CPU_S3C2440 */
|
||||
|
|
|
@ -436,7 +436,7 @@ 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 (%d alloc)\n",
|
||||
pr_debug("%s: out of memory (%ld alloc)\n",
|
||||
__FUNCTION__, sizeof(*buf));
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
|
|
@ -45,6 +45,9 @@
|
|||
*
|
||||
* 28-Jun-2005 Ben Dooks
|
||||
* Mark IRQ_LCD valid
|
||||
*
|
||||
* 25-Jul-2005 Ben Dooks
|
||||
* Split the S3C2440 IRQ code to seperate file
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
|
@ -65,11 +68,7 @@
|
|||
|
||||
#include "cpu.h"
|
||||
#include "pm.h"
|
||||
|
||||
#define irqdbf(x...)
|
||||
#define irqdbf2(x...)
|
||||
|
||||
#define EXTINT_OFF (IRQ_EINT4 - 4)
|
||||
#include "irq.h"
|
||||
|
||||
/* wakeup irq control */
|
||||
|
||||
|
@ -181,7 +180,7 @@ s3c_irq_unmask(unsigned int irqno)
|
|||
__raw_writel(mask, S3C2410_INTMSK);
|
||||
}
|
||||
|
||||
static struct irqchip s3c_irq_level_chip = {
|
||||
struct irqchip s3c_irq_level_chip = {
|
||||
.ack = s3c_irq_maskack,
|
||||
.mask = s3c_irq_mask,
|
||||
.unmask = s3c_irq_unmask,
|
||||
|
@ -370,84 +369,6 @@ static struct irqchip s3c_irq_eint0t4 = {
|
|||
#define INTMSK_UART2 (1UL << (IRQ_UART2 - IRQ_EINT0))
|
||||
#define INTMSK_ADCPARENT (1UL << (IRQ_ADCPARENT - IRQ_EINT0))
|
||||
|
||||
static inline void
|
||||
s3c_irqsub_mask(unsigned int irqno, unsigned int parentbit,
|
||||
int subcheck)
|
||||
{
|
||||
unsigned long mask;
|
||||
unsigned long submask;
|
||||
|
||||
submask = __raw_readl(S3C2410_INTSUBMSK);
|
||||
mask = __raw_readl(S3C2410_INTMSK);
|
||||
|
||||
submask |= (1UL << (irqno - IRQ_S3CUART_RX0));
|
||||
|
||||
/* check to see if we need to mask the parent IRQ */
|
||||
|
||||
if ((submask & subcheck) == subcheck) {
|
||||
__raw_writel(mask | parentbit, S3C2410_INTMSK);
|
||||
}
|
||||
|
||||
/* write back masks */
|
||||
__raw_writel(submask, S3C2410_INTSUBMSK);
|
||||
|
||||
}
|
||||
|
||||
static inline void
|
||||
s3c_irqsub_unmask(unsigned int irqno, unsigned int parentbit)
|
||||
{
|
||||
unsigned long mask;
|
||||
unsigned long submask;
|
||||
|
||||
submask = __raw_readl(S3C2410_INTSUBMSK);
|
||||
mask = __raw_readl(S3C2410_INTMSK);
|
||||
|
||||
submask &= ~(1UL << (irqno - IRQ_S3CUART_RX0));
|
||||
mask &= ~parentbit;
|
||||
|
||||
/* write back masks */
|
||||
__raw_writel(submask, S3C2410_INTSUBMSK);
|
||||
__raw_writel(mask, S3C2410_INTMSK);
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
s3c_irqsub_maskack(unsigned int irqno, unsigned int parentmask, unsigned int group)
|
||||
{
|
||||
unsigned int bit = 1UL << (irqno - IRQ_S3CUART_RX0);
|
||||
|
||||
s3c_irqsub_mask(irqno, parentmask, group);
|
||||
|
||||
__raw_writel(bit, S3C2410_SUBSRCPND);
|
||||
|
||||
/* only ack parent if we've got all the irqs (seems we must
|
||||
* ack, all and hope that the irq system retriggers ok when
|
||||
* the interrupt goes off again)
|
||||
*/
|
||||
|
||||
if (1) {
|
||||
__raw_writel(parentmask, S3C2410_SRCPND);
|
||||
__raw_writel(parentmask, S3C2410_INTPND);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
s3c_irqsub_ack(unsigned int irqno, unsigned int parentmask, unsigned int group)
|
||||
{
|
||||
unsigned int bit = 1UL << (irqno - IRQ_S3CUART_RX0);
|
||||
|
||||
__raw_writel(bit, S3C2410_SUBSRCPND);
|
||||
|
||||
/* only ack parent if we've got all the irqs (seems we must
|
||||
* ack, all and hope that the irq system retriggers ok when
|
||||
* the interrupt goes off again)
|
||||
*/
|
||||
|
||||
if (1) {
|
||||
__raw_writel(parentmask, S3C2410_SRCPND);
|
||||
__raw_writel(parentmask, S3C2410_INTPND);
|
||||
}
|
||||
}
|
||||
|
||||
/* UART0 */
|
||||
|
||||
|
@ -794,174 +715,3 @@ void __init s3c24xx_init_irq(void)
|
|||
|
||||
irqdbf("s3c2410: registered interrupt handlers\n");
|
||||
}
|
||||
|
||||
/* s3c2440 irq code
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_CPU_S3C2440
|
||||
|
||||
/* WDT/AC97 */
|
||||
|
||||
static void s3c_irq_demux_wdtac97(unsigned int irq,
|
||||
struct irqdesc *desc,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
unsigned int subsrc, submsk;
|
||||
struct irqdesc *mydesc;
|
||||
|
||||
/* read the current pending interrupts, and the mask
|
||||
* for what it is available */
|
||||
|
||||
subsrc = __raw_readl(S3C2410_SUBSRCPND);
|
||||
submsk = __raw_readl(S3C2410_INTSUBMSK);
|
||||
|
||||
subsrc &= ~submsk;
|
||||
subsrc >>= 13;
|
||||
subsrc &= 3;
|
||||
|
||||
if (subsrc != 0) {
|
||||
if (subsrc & 1) {
|
||||
mydesc = irq_desc + IRQ_S3C2440_WDT;
|
||||
mydesc->handle( IRQ_S3C2440_WDT, mydesc, regs);
|
||||
}
|
||||
if (subsrc & 2) {
|
||||
mydesc = irq_desc + IRQ_S3C2440_AC97;
|
||||
mydesc->handle(IRQ_S3C2440_AC97, mydesc, regs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define INTMSK_WDT (1UL << (IRQ_WDT - IRQ_EINT0))
|
||||
|
||||
static void
|
||||
s3c_irq_wdtac97_mask(unsigned int irqno)
|
||||
{
|
||||
s3c_irqsub_mask(irqno, INTMSK_WDT, 3<<13);
|
||||
}
|
||||
|
||||
static void
|
||||
s3c_irq_wdtac97_unmask(unsigned int irqno)
|
||||
{
|
||||
s3c_irqsub_unmask(irqno, INTMSK_WDT);
|
||||
}
|
||||
|
||||
static void
|
||||
s3c_irq_wdtac97_ack(unsigned int irqno)
|
||||
{
|
||||
s3c_irqsub_maskack(irqno, INTMSK_WDT, 3<<13);
|
||||
}
|
||||
|
||||
static struct irqchip s3c_irq_wdtac97 = {
|
||||
.mask = s3c_irq_wdtac97_mask,
|
||||
.unmask = s3c_irq_wdtac97_unmask,
|
||||
.ack = s3c_irq_wdtac97_ack,
|
||||
};
|
||||
|
||||
/* camera irq */
|
||||
|
||||
static void s3c_irq_demux_cam(unsigned int irq,
|
||||
struct irqdesc *desc,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
unsigned int subsrc, submsk;
|
||||
struct irqdesc *mydesc;
|
||||
|
||||
/* read the current pending interrupts, and the mask
|
||||
* for what it is available */
|
||||
|
||||
subsrc = __raw_readl(S3C2410_SUBSRCPND);
|
||||
submsk = __raw_readl(S3C2410_INTSUBMSK);
|
||||
|
||||
subsrc &= ~submsk;
|
||||
subsrc >>= 11;
|
||||
subsrc &= 3;
|
||||
|
||||
if (subsrc != 0) {
|
||||
if (subsrc & 1) {
|
||||
mydesc = irq_desc + IRQ_S3C2440_CAM_C;
|
||||
mydesc->handle( IRQ_S3C2440_WDT, mydesc, regs);
|
||||
}
|
||||
if (subsrc & 2) {
|
||||
mydesc = irq_desc + IRQ_S3C2440_CAM_P;
|
||||
mydesc->handle(IRQ_S3C2440_AC97, mydesc, regs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define INTMSK_CAM (1UL << (IRQ_CAM - IRQ_EINT0))
|
||||
|
||||
static void
|
||||
s3c_irq_cam_mask(unsigned int irqno)
|
||||
{
|
||||
s3c_irqsub_mask(irqno, INTMSK_CAM, 3<<11);
|
||||
}
|
||||
|
||||
static void
|
||||
s3c_irq_cam_unmask(unsigned int irqno)
|
||||
{
|
||||
s3c_irqsub_unmask(irqno, INTMSK_CAM);
|
||||
}
|
||||
|
||||
static void
|
||||
s3c_irq_cam_ack(unsigned int irqno)
|
||||
{
|
||||
s3c_irqsub_maskack(irqno, INTMSK_CAM, 3<<11);
|
||||
}
|
||||
|
||||
static struct irqchip s3c_irq_cam = {
|
||||
.mask = s3c_irq_cam_mask,
|
||||
.unmask = s3c_irq_cam_unmask,
|
||||
.ack = s3c_irq_cam_ack,
|
||||
};
|
||||
|
||||
static int s3c2440_irq_add(struct sys_device *sysdev)
|
||||
{
|
||||
unsigned int irqno;
|
||||
|
||||
printk("S3C2440: IRQ Support\n");
|
||||
|
||||
set_irq_chip(IRQ_NFCON, &s3c_irq_level_chip);
|
||||
set_irq_handler(IRQ_NFCON, do_level_IRQ);
|
||||
set_irq_flags(IRQ_NFCON, IRQF_VALID);
|
||||
|
||||
/* add new chained handler for wdt, ac7 */
|
||||
|
||||
set_irq_chip(IRQ_WDT, &s3c_irq_level_chip);
|
||||
set_irq_handler(IRQ_WDT, do_level_IRQ);
|
||||
set_irq_chained_handler(IRQ_WDT, s3c_irq_demux_wdtac97);
|
||||
|
||||
for (irqno = IRQ_S3C2440_WDT; irqno <= IRQ_S3C2440_AC97; irqno++) {
|
||||
set_irq_chip(irqno, &s3c_irq_wdtac97);
|
||||
set_irq_handler(irqno, do_level_IRQ);
|
||||
set_irq_flags(irqno, IRQF_VALID);
|
||||
}
|
||||
|
||||
/* add chained handler for camera */
|
||||
|
||||
set_irq_chip(IRQ_CAM, &s3c_irq_level_chip);
|
||||
set_irq_handler(IRQ_CAM, do_level_IRQ);
|
||||
set_irq_chained_handler(IRQ_CAM, s3c_irq_demux_cam);
|
||||
|
||||
for (irqno = IRQ_S3C2440_CAM_C; irqno <= IRQ_S3C2440_CAM_P; irqno++) {
|
||||
set_irq_chip(irqno, &s3c_irq_cam);
|
||||
set_irq_handler(irqno, do_level_IRQ);
|
||||
set_irq_flags(irqno, IRQF_VALID);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct sysdev_driver s3c2440_irq_driver = {
|
||||
.add = s3c2440_irq_add,
|
||||
};
|
||||
|
||||
static int s3c24xx_irq_driver(void)
|
||||
{
|
||||
return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_irq_driver);
|
||||
}
|
||||
|
||||
arch_initcall(s3c24xx_irq_driver);
|
||||
|
||||
#endif /* CONFIG_CPU_S3C2440 */
|
||||
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
/* arch/arm/mach-s3c2410/irq.h
|
||||
*
|
||||
* Copyright (c) 2004-2005 Simtec Electronics
|
||||
* Ben Dooks <ben@simtec.co.uk>
|
||||
*
|
||||
* Header file for S3C24XX CPU IRQ support
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Modifications:
|
||||
*/
|
||||
|
||||
#define irqdbf(x...)
|
||||
#define irqdbf2(x...)
|
||||
|
||||
#define EXTINT_OFF (IRQ_EINT4 - 4)
|
||||
|
||||
extern struct irqchip s3c_irq_level_chip;
|
||||
|
||||
static inline void
|
||||
s3c_irqsub_mask(unsigned int irqno, unsigned int parentbit,
|
||||
int subcheck)
|
||||
{
|
||||
unsigned long mask;
|
||||
unsigned long submask;
|
||||
|
||||
submask = __raw_readl(S3C2410_INTSUBMSK);
|
||||
mask = __raw_readl(S3C2410_INTMSK);
|
||||
|
||||
submask |= (1UL << (irqno - IRQ_S3CUART_RX0));
|
||||
|
||||
/* check to see if we need to mask the parent IRQ */
|
||||
|
||||
if ((submask & subcheck) == subcheck) {
|
||||
__raw_writel(mask | parentbit, S3C2410_INTMSK);
|
||||
}
|
||||
|
||||
/* write back masks */
|
||||
__raw_writel(submask, S3C2410_INTSUBMSK);
|
||||
|
||||
}
|
||||
|
||||
static inline void
|
||||
s3c_irqsub_unmask(unsigned int irqno, unsigned int parentbit)
|
||||
{
|
||||
unsigned long mask;
|
||||
unsigned long submask;
|
||||
|
||||
submask = __raw_readl(S3C2410_INTSUBMSK);
|
||||
mask = __raw_readl(S3C2410_INTMSK);
|
||||
|
||||
submask &= ~(1UL << (irqno - IRQ_S3CUART_RX0));
|
||||
mask &= ~parentbit;
|
||||
|
||||
/* write back masks */
|
||||
__raw_writel(submask, S3C2410_INTSUBMSK);
|
||||
__raw_writel(mask, S3C2410_INTMSK);
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
s3c_irqsub_maskack(unsigned int irqno, unsigned int parentmask, unsigned int group)
|
||||
{
|
||||
unsigned int bit = 1UL << (irqno - IRQ_S3CUART_RX0);
|
||||
|
||||
s3c_irqsub_mask(irqno, parentmask, group);
|
||||
|
||||
__raw_writel(bit, S3C2410_SUBSRCPND);
|
||||
|
||||
/* only ack parent if we've got all the irqs (seems we must
|
||||
* ack, all and hope that the irq system retriggers ok when
|
||||
* the interrupt goes off again)
|
||||
*/
|
||||
|
||||
if (1) {
|
||||
__raw_writel(parentmask, S3C2410_SRCPND);
|
||||
__raw_writel(parentmask, S3C2410_INTPND);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
s3c_irqsub_ack(unsigned int irqno, unsigned int parentmask, unsigned int group)
|
||||
{
|
||||
unsigned int bit = 1UL << (irqno - IRQ_S3CUART_RX0);
|
||||
|
||||
__raw_writel(bit, S3C2410_SUBSRCPND);
|
||||
|
||||
/* only ack parent if we've got all the irqs (seems we must
|
||||
* ack, all and hope that the irq system retriggers ok when
|
||||
* the interrupt goes off again)
|
||||
*/
|
||||
|
||||
if (1) {
|
||||
__raw_writel(parentmask, S3C2410_SRCPND);
|
||||
__raw_writel(parentmask, S3C2410_INTPND);
|
||||
}
|
||||
}
|
|
@ -25,9 +25,11 @@
|
|||
* 14-Jan-2005 BJD Add support for muitlple NAND devices
|
||||
* 03-Mar-2005 BJD Ensured that bast-cpld.h is included
|
||||
* 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
|
||||
* 14-Mar-2006 BJD Updated for __iomem changes
|
||||
* 22-Jun-2006 BJD Added DM9000 platform information
|
||||
* 28-Jun-2006 BJD Moved pm functionality out to common code
|
||||
* 14-Mar-2005 BJD Updated for __iomem changes
|
||||
* 22-Jun-2005 BJD Added DM9000 platform information
|
||||
* 28-Jun-2005 BJD Moved pm functionality out to common code
|
||||
* 17-Jul-2005 BJD Changed to platform device for SuperIO 16550s
|
||||
* 25-Jul-2005 BJD Removed ASIX static mappings
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
@ -64,6 +66,8 @@
|
|||
#include <linux/mtd/nand_ecc.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
|
||||
#include <linux/serial_8250.h>
|
||||
|
||||
#include "clock.h"
|
||||
#include "devs.h"
|
||||
#include "cpu.h"
|
||||
|
@ -113,7 +117,6 @@ static struct map_desc bast_iodesc[] __initdata = {
|
|||
/* slow, byte */
|
||||
{ VA_C2(BAST_VA_ISAIO), PA_CS2(BAST_PA_ISAIO), SZ_16M, MT_DEVICE },
|
||||
{ VA_C2(BAST_VA_ISAMEM), PA_CS2(BAST_PA_ISAMEM), SZ_16M, MT_DEVICE },
|
||||
{ VA_C2(BAST_VA_ASIXNET), PA_CS3(BAST_PA_ASIXNET), SZ_1M, MT_DEVICE },
|
||||
{ VA_C2(BAST_VA_SUPERIO), PA_CS2(BAST_PA_SUPERIO), SZ_1M, MT_DEVICE },
|
||||
{ VA_C2(BAST_VA_IDEPRI), PA_CS3(BAST_PA_IDEPRI), SZ_1M, MT_DEVICE },
|
||||
{ VA_C2(BAST_VA_IDESEC), PA_CS3(BAST_PA_IDESEC), SZ_1M, MT_DEVICE },
|
||||
|
@ -123,7 +126,6 @@ static struct map_desc bast_iodesc[] __initdata = {
|
|||
/* slow, word */
|
||||
{ VA_C3(BAST_VA_ISAIO), PA_CS3(BAST_PA_ISAIO), SZ_16M, MT_DEVICE },
|
||||
{ VA_C3(BAST_VA_ISAMEM), PA_CS3(BAST_PA_ISAMEM), SZ_16M, MT_DEVICE },
|
||||
{ VA_C3(BAST_VA_ASIXNET), PA_CS3(BAST_PA_ASIXNET), SZ_1M, MT_DEVICE },
|
||||
{ VA_C3(BAST_VA_SUPERIO), PA_CS3(BAST_PA_SUPERIO), SZ_1M, MT_DEVICE },
|
||||
{ VA_C3(BAST_VA_IDEPRI), PA_CS3(BAST_PA_IDEPRI), SZ_1M, MT_DEVICE },
|
||||
{ VA_C3(BAST_VA_IDESEC), PA_CS3(BAST_PA_IDESEC), SZ_1M, MT_DEVICE },
|
||||
|
@ -133,7 +135,6 @@ static struct map_desc bast_iodesc[] __initdata = {
|
|||
/* fast, byte */
|
||||
{ VA_C4(BAST_VA_ISAIO), PA_CS4(BAST_PA_ISAIO), SZ_16M, MT_DEVICE },
|
||||
{ VA_C4(BAST_VA_ISAMEM), PA_CS4(BAST_PA_ISAMEM), SZ_16M, MT_DEVICE },
|
||||
{ VA_C4(BAST_VA_ASIXNET), PA_CS5(BAST_PA_ASIXNET), SZ_1M, MT_DEVICE },
|
||||
{ VA_C4(BAST_VA_SUPERIO), PA_CS4(BAST_PA_SUPERIO), SZ_1M, MT_DEVICE },
|
||||
{ VA_C4(BAST_VA_IDEPRI), PA_CS5(BAST_PA_IDEPRI), SZ_1M, MT_DEVICE },
|
||||
{ VA_C4(BAST_VA_IDESEC), PA_CS5(BAST_PA_IDESEC), SZ_1M, MT_DEVICE },
|
||||
|
@ -143,7 +144,6 @@ static struct map_desc bast_iodesc[] __initdata = {
|
|||
/* fast, word */
|
||||
{ VA_C5(BAST_VA_ISAIO), PA_CS5(BAST_PA_ISAIO), SZ_16M, MT_DEVICE },
|
||||
{ VA_C5(BAST_VA_ISAMEM), PA_CS5(BAST_PA_ISAMEM), SZ_16M, MT_DEVICE },
|
||||
{ VA_C5(BAST_VA_ASIXNET), PA_CS5(BAST_PA_ASIXNET), SZ_1M, MT_DEVICE },
|
||||
{ VA_C5(BAST_VA_SUPERIO), PA_CS5(BAST_PA_SUPERIO), SZ_1M, MT_DEVICE },
|
||||
{ VA_C5(BAST_VA_IDEPRI), PA_CS5(BAST_PA_IDEPRI), SZ_1M, MT_DEVICE },
|
||||
{ VA_C5(BAST_VA_IDESEC), PA_CS5(BAST_PA_IDESEC), SZ_1M, MT_DEVICE },
|
||||
|
@ -351,6 +351,39 @@ static struct platform_device bast_device_dm9k = {
|
|||
}
|
||||
};
|
||||
|
||||
/* serial devices */
|
||||
|
||||
#define SERIAL_BASE (S3C2410_CS2 + BAST_PA_SUPERIO)
|
||||
#define SERIAL_FLAGS (UPF_BOOT_AUTOCONF | UPF_IOREMAP | UPF_SHARE_IRQ)
|
||||
#define SERIAL_CLK (1843200)
|
||||
|
||||
static struct plat_serial8250_port bast_sio_data[] = {
|
||||
[0] = {
|
||||
.mapbase = SERIAL_BASE + 0x2f8,
|
||||
.irq = IRQ_PCSERIAL1,
|
||||
.flags = SERIAL_FLAGS,
|
||||
.iotype = UPIO_MEM,
|
||||
.regshift = 0,
|
||||
.uartclk = SERIAL_CLK,
|
||||
},
|
||||
[1] = {
|
||||
.mapbase = SERIAL_BASE + 0x3f8,
|
||||
.irq = IRQ_PCSERIAL2,
|
||||
.flags = SERIAL_FLAGS,
|
||||
.iotype = UPIO_MEM,
|
||||
.regshift = 0,
|
||||
.uartclk = SERIAL_CLK,
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
static struct platform_device bast_sio = {
|
||||
.name = "serial8250",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.platform_data = &bast_sio_data,
|
||||
},
|
||||
};
|
||||
|
||||
/* Standard BAST devices */
|
||||
|
||||
|
@ -364,6 +397,7 @@ static struct platform_device *bast_devices[] __initdata = {
|
|||
&s3c_device_nand,
|
||||
&bast_device_nor,
|
||||
&bast_device_dm9k,
|
||||
&bast_sio,
|
||||
};
|
||||
|
||||
static struct clk *bast_clocks[] = {
|
||||
|
|
|
@ -0,0 +1,116 @@
|
|||
/* linux/arch/arm/mach-s3c2410/s3c2440-clock.c
|
||||
*
|
||||
* Copyright (c) 2004-2005 Simtec Electronics
|
||||
* http://armlinux.simtec.co.uk/
|
||||
* Ben Dooks <ben@simtec.co.uk>
|
||||
*
|
||||
* S3C2440 Clock support
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/sysdev.h>
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/ioport.h>
|
||||
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#include <asm/hardware/clock.h>
|
||||
#include <asm/arch/regs-clock.h>
|
||||
|
||||
#include "clock.h"
|
||||
#include "cpu.h"
|
||||
|
||||
/* S3C2440 extended clock support */
|
||||
|
||||
static struct clk s3c2440_clk_upll = {
|
||||
.name = "upll",
|
||||
.id = -1,
|
||||
};
|
||||
|
||||
static struct clk s3c2440_clk_cam = {
|
||||
.name = "camif",
|
||||
.id = -1,
|
||||
.enable = s3c24xx_clkcon_enable,
|
||||
.ctrlbit = S3C2440_CLKCON_CAMERA,
|
||||
};
|
||||
|
||||
static struct clk s3c2440_clk_ac97 = {
|
||||
.name = "ac97",
|
||||
.id = -1,
|
||||
.enable = s3c24xx_clkcon_enable,
|
||||
.ctrlbit = S3C2440_CLKCON_CAMERA,
|
||||
};
|
||||
|
||||
static int s3c2440_clk_add(struct sys_device *sysdev)
|
||||
{
|
||||
unsigned long upllcon = __raw_readl(S3C2410_UPLLCON);
|
||||
struct clk *clk_h;
|
||||
struct clk *clk_p;
|
||||
struct clk *clk_xtal;
|
||||
|
||||
clk_xtal = clk_get(NULL, "xtal");
|
||||
if (IS_ERR(clk_xtal)) {
|
||||
printk(KERN_ERR "S3C2440: Failed to get clk_xtal\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
s3c2440_clk_upll.rate = s3c2410_get_pll(upllcon, clk_xtal->rate);
|
||||
|
||||
printk("S3C2440: Clock Support, UPLL %ld.%03ld MHz\n",
|
||||
print_mhz(s3c2440_clk_upll.rate));
|
||||
|
||||
clk_p = clk_get(NULL, "pclk");
|
||||
clk_h = clk_get(NULL, "hclk");
|
||||
|
||||
if (IS_ERR(clk_p) || IS_ERR(clk_h)) {
|
||||
printk(KERN_ERR "S3C2440: Failed to get parent clocks\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
s3c2440_clk_cam.parent = clk_h;
|
||||
s3c2440_clk_ac97.parent = clk_p;
|
||||
|
||||
s3c24xx_register_clock(&s3c2440_clk_ac97);
|
||||
s3c24xx_register_clock(&s3c2440_clk_cam);
|
||||
s3c24xx_register_clock(&s3c2440_clk_upll);
|
||||
|
||||
clk_disable(&s3c2440_clk_ac97);
|
||||
clk_disable(&s3c2440_clk_cam);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct sysdev_driver s3c2440_clk_driver = {
|
||||
.add = s3c2440_clk_add,
|
||||
};
|
||||
|
||||
static __init int s3c24xx_clk_driver(void)
|
||||
{
|
||||
return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_clk_driver);
|
||||
}
|
||||
|
||||
arch_initcall(s3c24xx_clk_driver);
|
|
@ -0,0 +1,207 @@
|
|||
/* linux/arch/arm/mach-s3c2410/s3c2440-irq.c
|
||||
*
|
||||
* Copyright (c) 2003,2004 Simtec Electronics
|
||||
* Ben Dooks <ben@simtec.co.uk>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Changelog:
|
||||
* 25-Jul-2005 BJD Split from irq.c
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/sysdev.h>
|
||||
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#include <asm/mach/irq.h>
|
||||
|
||||
#include <asm/arch/regs-irq.h>
|
||||
#include <asm/arch/regs-gpio.h>
|
||||
|
||||
#include "cpu.h"
|
||||
#include "pm.h"
|
||||
#include "irq.h"
|
||||
|
||||
/* WDT/AC97 */
|
||||
|
||||
static void s3c_irq_demux_wdtac97(unsigned int irq,
|
||||
struct irqdesc *desc,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
unsigned int subsrc, submsk;
|
||||
struct irqdesc *mydesc;
|
||||
|
||||
/* read the current pending interrupts, and the mask
|
||||
* for what it is available */
|
||||
|
||||
subsrc = __raw_readl(S3C2410_SUBSRCPND);
|
||||
submsk = __raw_readl(S3C2410_INTSUBMSK);
|
||||
|
||||
subsrc &= ~submsk;
|
||||
subsrc >>= 13;
|
||||
subsrc &= 3;
|
||||
|
||||
if (subsrc != 0) {
|
||||
if (subsrc & 1) {
|
||||
mydesc = irq_desc + IRQ_S3C2440_WDT;
|
||||
mydesc->handle( IRQ_S3C2440_WDT, mydesc, regs);
|
||||
}
|
||||
if (subsrc & 2) {
|
||||
mydesc = irq_desc + IRQ_S3C2440_AC97;
|
||||
mydesc->handle(IRQ_S3C2440_AC97, mydesc, regs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define INTMSK_WDT (1UL << (IRQ_WDT - IRQ_EINT0))
|
||||
|
||||
static void
|
||||
s3c_irq_wdtac97_mask(unsigned int irqno)
|
||||
{
|
||||
s3c_irqsub_mask(irqno, INTMSK_WDT, 3<<13);
|
||||
}
|
||||
|
||||
static void
|
||||
s3c_irq_wdtac97_unmask(unsigned int irqno)
|
||||
{
|
||||
s3c_irqsub_unmask(irqno, INTMSK_WDT);
|
||||
}
|
||||
|
||||
static void
|
||||
s3c_irq_wdtac97_ack(unsigned int irqno)
|
||||
{
|
||||
s3c_irqsub_maskack(irqno, INTMSK_WDT, 3<<13);
|
||||
}
|
||||
|
||||
static struct irqchip s3c_irq_wdtac97 = {
|
||||
.mask = s3c_irq_wdtac97_mask,
|
||||
.unmask = s3c_irq_wdtac97_unmask,
|
||||
.ack = s3c_irq_wdtac97_ack,
|
||||
};
|
||||
|
||||
/* camera irq */
|
||||
|
||||
static void s3c_irq_demux_cam(unsigned int irq,
|
||||
struct irqdesc *desc,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
unsigned int subsrc, submsk;
|
||||
struct irqdesc *mydesc;
|
||||
|
||||
/* read the current pending interrupts, and the mask
|
||||
* for what it is available */
|
||||
|
||||
subsrc = __raw_readl(S3C2410_SUBSRCPND);
|
||||
submsk = __raw_readl(S3C2410_INTSUBMSK);
|
||||
|
||||
subsrc &= ~submsk;
|
||||
subsrc >>= 11;
|
||||
subsrc &= 3;
|
||||
|
||||
if (subsrc != 0) {
|
||||
if (subsrc & 1) {
|
||||
mydesc = irq_desc + IRQ_S3C2440_CAM_C;
|
||||
mydesc->handle( IRQ_S3C2440_WDT, mydesc, regs);
|
||||
}
|
||||
if (subsrc & 2) {
|
||||
mydesc = irq_desc + IRQ_S3C2440_CAM_P;
|
||||
mydesc->handle(IRQ_S3C2440_AC97, mydesc, regs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define INTMSK_CAM (1UL << (IRQ_CAM - IRQ_EINT0))
|
||||
|
||||
static void
|
||||
s3c_irq_cam_mask(unsigned int irqno)
|
||||
{
|
||||
s3c_irqsub_mask(irqno, INTMSK_CAM, 3<<11);
|
||||
}
|
||||
|
||||
static void
|
||||
s3c_irq_cam_unmask(unsigned int irqno)
|
||||
{
|
||||
s3c_irqsub_unmask(irqno, INTMSK_CAM);
|
||||
}
|
||||
|
||||
static void
|
||||
s3c_irq_cam_ack(unsigned int irqno)
|
||||
{
|
||||
s3c_irqsub_maskack(irqno, INTMSK_CAM, 3<<11);
|
||||
}
|
||||
|
||||
static struct irqchip s3c_irq_cam = {
|
||||
.mask = s3c_irq_cam_mask,
|
||||
.unmask = s3c_irq_cam_unmask,
|
||||
.ack = s3c_irq_cam_ack,
|
||||
};
|
||||
|
||||
static int s3c2440_irq_add(struct sys_device *sysdev)
|
||||
{
|
||||
unsigned int irqno;
|
||||
|
||||
printk("S3C2440: IRQ Support\n");
|
||||
|
||||
set_irq_chip(IRQ_NFCON, &s3c_irq_level_chip);
|
||||
set_irq_handler(IRQ_NFCON, do_level_IRQ);
|
||||
set_irq_flags(IRQ_NFCON, IRQF_VALID);
|
||||
|
||||
/* add new chained handler for wdt, ac7 */
|
||||
|
||||
set_irq_chip(IRQ_WDT, &s3c_irq_level_chip);
|
||||
set_irq_handler(IRQ_WDT, do_level_IRQ);
|
||||
set_irq_chained_handler(IRQ_WDT, s3c_irq_demux_wdtac97);
|
||||
|
||||
for (irqno = IRQ_S3C2440_WDT; irqno <= IRQ_S3C2440_AC97; irqno++) {
|
||||
set_irq_chip(irqno, &s3c_irq_wdtac97);
|
||||
set_irq_handler(irqno, do_level_IRQ);
|
||||
set_irq_flags(irqno, IRQF_VALID);
|
||||
}
|
||||
|
||||
/* add chained handler for camera */
|
||||
|
||||
set_irq_chip(IRQ_CAM, &s3c_irq_level_chip);
|
||||
set_irq_handler(IRQ_CAM, do_level_IRQ);
|
||||
set_irq_chained_handler(IRQ_CAM, s3c_irq_demux_cam);
|
||||
|
||||
for (irqno = IRQ_S3C2440_CAM_C; irqno <= IRQ_S3C2440_CAM_P; irqno++) {
|
||||
set_irq_chip(irqno, &s3c_irq_cam);
|
||||
set_irq_handler(irqno, do_level_IRQ);
|
||||
set_irq_flags(irqno, IRQF_VALID);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct sysdev_driver s3c2440_irq_driver = {
|
||||
.add = s3c2440_irq_add,
|
||||
};
|
||||
|
||||
static int s3c24xx_irq_driver(void)
|
||||
{
|
||||
return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_irq_driver);
|
||||
}
|
||||
|
||||
arch_initcall(s3c24xx_irq_driver);
|
||||
|
|
@ -24,7 +24,7 @@ static struct plat_serial8250_port serial_platform_data[] = {
|
|||
.iobase = 0x3f8,
|
||||
.irq = 4,
|
||||
.uartclk = 1843200,
|
||||
.regshift = 2,
|
||||
.regshift = 0,
|
||||
.iotype = UPIO_PORT,
|
||||
.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
|
||||
},
|
||||
|
@ -32,7 +32,7 @@ static struct plat_serial8250_port serial_platform_data[] = {
|
|||
.iobase = 0x2f8,
|
||||
.irq = 3,
|
||||
.uartclk = 1843200,
|
||||
.regshift = 2,
|
||||
.regshift = 0,
|
||||
.iotype = UPIO_PORT,
|
||||
.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
|
||||
},
|
||||
|
|
|
@ -425,6 +425,9 @@ static void __init build_mem_type_table(void)
|
|||
mem_types[MT_ROM].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
|
||||
mem_types[MT_MINICLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
|
||||
mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
|
||||
|
||||
mem_types[MT_DEVICE].prot_pte |= L_PTE_BUFFERABLE;
|
||||
mem_types[MT_DEVICE].prot_sect |= PMD_SECT_BUFFERED;
|
||||
}
|
||||
|
||||
cp = &cache_policies[cachepolicy];
|
||||
|
|
|
@ -29,9 +29,7 @@
|
|||
* stack+task struct. Use the same method as 'current' uses to
|
||||
* reach them.
|
||||
*/
|
||||
register unsigned long *user_registers asm("sl");
|
||||
|
||||
#define GET_USERREG() (user_registers)
|
||||
#define GET_USERREG() ((struct pt_regs *)(THREAD_START_SP + (unsigned long)current_thread_info()) - 1)
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/thread_info.h>
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#include "fpa11.h"
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/config.h>
|
||||
|
||||
/* XXX */
|
||||
|
@ -133,7 +132,7 @@ void float_raise(signed char flags)
|
|||
printk(KERN_DEBUG
|
||||
"NWFPE: %s[%d] takes exception %08x at %p from %08lx\n",
|
||||
current->comm, current->pid, flags,
|
||||
__builtin_return_address(0), GET_USERREG()[15]);
|
||||
__builtin_return_address(0), GET_USERREG()->ARM_pc);
|
||||
#endif
|
||||
|
||||
/* Keep SoftFloat exception flags up to date. */
|
||||
|
|
|
@ -28,8 +28,8 @@ static inline unsigned long readRegister(const unsigned int nReg)
|
|||
for this in this routine. LDF/STF instructions with Rn = PC
|
||||
depend on the PC being correct, as they use PC+8 in their
|
||||
address calculations. */
|
||||
unsigned long *userRegisters = GET_USERREG();
|
||||
unsigned int val = userRegisters[nReg];
|
||||
struct pt_regs *regs = GET_USERREG();
|
||||
unsigned int val = regs->uregs[nReg];
|
||||
if (REG_PC == nReg)
|
||||
val -= 4;
|
||||
return val;
|
||||
|
@ -38,8 +38,8 @@ static inline unsigned long readRegister(const unsigned int nReg)
|
|||
static inline void
|
||||
writeRegister(const unsigned int nReg, const unsigned long val)
|
||||
{
|
||||
unsigned long *userRegisters = GET_USERREG();
|
||||
userRegisters[nReg] = val;
|
||||
struct pt_regs *regs = GET_USERREG();
|
||||
regs->uregs[nReg] = val;
|
||||
}
|
||||
|
||||
static inline unsigned long readCPSR(void)
|
||||
|
@ -63,12 +63,12 @@ static inline unsigned long readConditionCodes(void)
|
|||
|
||||
static inline void writeConditionCodes(const unsigned long val)
|
||||
{
|
||||
unsigned long *userRegisters = GET_USERREG();
|
||||
struct pt_regs *regs = GET_USERREG();
|
||||
unsigned long rval;
|
||||
/*
|
||||
* Operate directly on userRegisters since
|
||||
* the CPSR may be the PC register itself.
|
||||
*/
|
||||
rval = userRegisters[REG_CPSR] & ~CC_MASK;
|
||||
userRegisters[REG_CPSR] = rval | (val & CC_MASK);
|
||||
rval = regs->ARM_cpsr & ~CC_MASK;
|
||||
regs->ARM_cpsr = rval | (val & CC_MASK);
|
||||
}
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
|
||||
#include <linux/config.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/kernel.h>
|
||||
|
|
|
@ -103,9 +103,6 @@ void machine_power_off(void)
|
|||
{
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(machine_halt);
|
||||
EXPORT_SYMBOL(machine_power_off);
|
||||
|
||||
void machine_restart(char * __unused)
|
||||
{
|
||||
/*
|
||||
|
@ -136,8 +133,6 @@ void machine_restart(char * __unused)
|
|||
while (1);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(machine_restart);
|
||||
|
||||
void show_regs(struct pt_regs * regs)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
|
|
@ -38,4 +38,9 @@ config FRAME_POINTER
|
|||
If you don't debug the kernel, you can say N, but we may not be able
|
||||
to solve problems without frame pointers.
|
||||
|
||||
config DEBUG_NMI_OOPS
|
||||
bool "NMI causes oops printout"
|
||||
help
|
||||
If the system locks up without any debug information you can say Y
|
||||
here to make it possible to dump an OOPS with an external NMI.
|
||||
endmenu
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $Id: Makefile,v 1.23 2004/10/19 13:07:34 starvik Exp $
|
||||
# $Id: Makefile,v 1.28 2005/03/17 10:44:37 larsv Exp $
|
||||
# cris/Makefile
|
||||
#
|
||||
# This file is included by the global makefile so that you can add your own
|
||||
|
@ -15,6 +15,7 @@
|
|||
|
||||
arch-y := v10
|
||||
arch-$(CONFIG_ETRAX_ARCH_V10) := v10
|
||||
arch-$(CONFIG_ETRAX_ARCH_V32) := v32
|
||||
|
||||
# No config avaiable for make clean etc
|
||||
ifneq ($(arch-y),)
|
||||
|
@ -46,6 +47,21 @@ core-y += arch/$(ARCH)/$(SARCH)/kernel/ arch/$(ARCH)/$(SARCH)/mm/
|
|||
drivers-y += arch/$(ARCH)/$(SARCH)/drivers/
|
||||
libs-y += arch/$(ARCH)/$(SARCH)/lib/ $(LIBGCC)
|
||||
|
||||
# cris source path
|
||||
SRC_ARCH = $(srctree)/arch/$(ARCH)
|
||||
# cris object files path
|
||||
OBJ_ARCH = $(objtree)/arch/$(ARCH)
|
||||
|
||||
target_boot_arch_dir = $(OBJ_ARCH)/$(SARCH)/boot
|
||||
target_boot_dir = $(OBJ_ARCH)/boot
|
||||
src_boot_dir = $(SRC_ARCH)/boot
|
||||
target_compressed_dir = $(OBJ_ARCH)/boot/compressed
|
||||
src_compressed_dir = $(SRC_ARCH)/boot/compressed
|
||||
target_rescue_dir = $(OBJ_ARCH)/boot/rescue
|
||||
src_rescue_dir = $(SRC_ARCH)/boot/rescue
|
||||
|
||||
export target_boot_arch_dir target_boot_dir src_boot_dir target_compressed_dir src_compressed_dir target_rescue_dir src_rescue_dir
|
||||
|
||||
vmlinux.bin: vmlinux
|
||||
$(OBJCOPY) $(OBJCOPYFLAGS) vmlinux vmlinux.bin
|
||||
|
||||
|
@ -65,44 +81,52 @@ cramfs:
|
|||
|
||||
clinux: vmlinux.bin decompress.bin rescue.bin
|
||||
|
||||
decompress.bin: FORCE
|
||||
@make -C arch/$(ARCH)/boot/compressed decompress.bin
|
||||
decompress.bin: $(target_boot_dir)
|
||||
@$(MAKE) -f $(src_compressed_dir)/Makefile $(target_compressed_dir)/decompress.bin
|
||||
|
||||
rescue.bin: FORCE
|
||||
@make -C arch/$(ARCH)/boot/rescue rescue.bin
|
||||
$(target_rescue_dir)/rescue.bin: $(target_boot_dir)
|
||||
@$(MAKE) -f $(src_rescue_dir)/Makefile $(target_rescue_dir)/rescue.bin
|
||||
|
||||
zImage: vmlinux.bin rescue.bin
|
||||
zImage: $(target_boot_dir) vmlinux.bin $(target_rescue_dir)/rescue.bin
|
||||
## zImage - Compressed kernel (gzip)
|
||||
@make -C arch/$(ARCH)/boot/ zImage
|
||||
@$(MAKE) -f $(src_boot_dir)/Makefile zImage
|
||||
|
||||
$(target_boot_dir): $(target_boot_arch_dir)
|
||||
ln -sfn $< $@
|
||||
|
||||
$(target_boot_arch_dir):
|
||||
mkdir -p $@
|
||||
|
||||
compressed: zImage
|
||||
|
||||
archmrproper:
|
||||
archclean:
|
||||
$(Q)$(MAKE) $(clean)=arch/$(ARCH)/boot
|
||||
@if [ -d arch/$(ARCH)/boot ]; then \
|
||||
$(MAKE) $(clean)=arch/$(ARCH)/boot ; \
|
||||
fi
|
||||
rm -f timage vmlinux.bin decompress.bin rescue.bin cramfs.img
|
||||
rm -rf $(LD_SCRIPT).tmp
|
||||
|
||||
prepare: arch/$(ARCH)/.links include/asm-$(ARCH)/.arch \
|
||||
prepare: $(SRC_ARCH)/.links $(srctree)/include/asm-$(ARCH)/.arch \
|
||||
include/asm-$(ARCH)/$(SARCH)/offset.h
|
||||
|
||||
# Create some links to make all tools happy
|
||||
arch/$(ARCH)/.links:
|
||||
@rm -rf arch/$(ARCH)/drivers
|
||||
@ln -sfn $(SARCH)/drivers arch/$(ARCH)/drivers
|
||||
@rm -rf arch/$(ARCH)/boot
|
||||
@ln -sfn $(SARCH)/boot arch/$(ARCH)/boot
|
||||
@rm -rf arch/$(ARCH)/lib
|
||||
@ln -sfn $(SARCH)/lib arch/$(ARCH)/lib
|
||||
@ln -sfn $(SARCH) arch/$(ARCH)/arch
|
||||
@ln -sfn ../$(SARCH)/vmlinux.lds.S arch/$(ARCH)/kernel/vmlinux.lds.S
|
||||
$(SRC_ARCH)/.links:
|
||||
@rm -rf $(SRC_ARCH)/drivers
|
||||
@ln -sfn $(SRC_ARCH)/$(SARCH)/drivers $(SRC_ARCH)/drivers
|
||||
@rm -rf $(SRC_ARCH)/boot
|
||||
@ln -sfn $(SRC_ARCH)/$(SARCH)/boot $(SRC_ARCH)/boot
|
||||
@rm -rf $(SRC_ARCH)/lib
|
||||
@ln -sfn $(SRC_ARCH)/$(SARCH)/lib $(SRC_ARCH)/lib
|
||||
@ln -sfn $(SRC_ARCH)/$(SARCH) $(SRC_ARCH)/arch
|
||||
@ln -sfn $(SRC_ARCH)/$(SARCH)/vmlinux.lds.S $(SRC_ARCH)/kernel/vmlinux.lds.S
|
||||
@touch $@
|
||||
|
||||
# Create link to sub arch includes
|
||||
include/asm-$(ARCH)/.arch: $(wildcard include/config/arch/*.h)
|
||||
@echo ' Making asm-$(ARCH)/arch -> asm-$(ARCH)/$(SARCH) symlink'
|
||||
$(srctree)/include/asm-$(ARCH)/.arch: $(wildcard include/config/arch/*.h)
|
||||
@echo ' Making $(srctree)/include/asm-$(ARCH)/arch -> $(srctree)/include/asm-$(ARCH)/$(SARCH) symlink'
|
||||
@rm -f include/asm-$(ARCH)/arch
|
||||
@ln -sf $(SARCH) include/asm-$(ARCH)/arch
|
||||
@ln -sf $(srctree)/include/asm-$(ARCH)/$(SARCH) $(srctree)/include/asm-$(ARCH)/arch
|
||||
@touch $@
|
||||
|
||||
arch/$(ARCH)/$(SARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \
|
||||
|
|
|
@ -259,6 +259,37 @@ config ETRAX_DEBUG_PORT_NULL
|
|||
|
||||
endchoice
|
||||
|
||||
choice
|
||||
prompt "Kernel GDB port"
|
||||
depends on ETRAX_KGDB
|
||||
default ETRAX_KGDB_PORT0
|
||||
help
|
||||
Choose a serial port for kernel debugging. NOTE: This port should
|
||||
not be enabled under Drivers for built-in interfaces (as it has its
|
||||
own initialization code) and should not be the same as the debug port.
|
||||
|
||||
config ETRAX_KGDB_PORT0
|
||||
bool "Serial-0"
|
||||
help
|
||||
Use serial port 0 for kernel debugging.
|
||||
|
||||
config ETRAX_KGDB_PORT1
|
||||
bool "Serial-1"
|
||||
help
|
||||
Use serial port 1 for kernel debugging.
|
||||
|
||||
config ETRAX_KGDB_PORT2
|
||||
bool "Serial-2"
|
||||
help
|
||||
Use serial port 2 for kernel debugging.
|
||||
|
||||
config ETRAX_KGDB_PORT3
|
||||
bool "Serial-3"
|
||||
help
|
||||
Use serial port 3 for kernel debugging.
|
||||
|
||||
endchoice
|
||||
|
||||
choice
|
||||
prompt "Product rescue-port"
|
||||
depends on ETRAX_ARCH_V10
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
#
|
||||
# arch/cris/boot/Makefile
|
||||
#
|
||||
target = $(target_boot_dir)
|
||||
src = $(src_boot_dir)
|
||||
|
||||
zImage: compressed/vmlinuz
|
||||
|
||||
compressed/vmlinuz: $(TOPDIR)/vmlinux
|
||||
@$(MAKE) -C compressed vmlinuz
|
||||
compressed/vmlinuz:
|
||||
@$(MAKE) -f $(src)/compressed/Makefile $(target_compressed_dir)/vmlinuz
|
||||
|
||||
clean:
|
||||
rm -f zImage tools/build compressed/vmlinux.out
|
||||
@$(MAKE) -C compressed clean
|
||||
@$(MAKE) -f $(src)/compressed/Makefile clean
|
||||
|
|
|
@ -1,40 +1,45 @@
|
|||
#
|
||||
# linux/arch/etrax100/boot/compressed/Makefile
|
||||
#
|
||||
# create a compressed vmlinux image from the original vmlinux files and romfs
|
||||
# create a compressed vmlinuz image from the binary vmlinux.bin file
|
||||
#
|
||||
target = $(target_compressed_dir)
|
||||
src = $(src_compressed_dir)
|
||||
|
||||
CC = gcc-cris -melf -I $(TOPDIR)/include
|
||||
CC = gcc-cris -melf $(LINUXINCLUDE)
|
||||
CFLAGS = -O2
|
||||
LD = ld-cris
|
||||
OBJCOPY = objcopy-cris
|
||||
OBJCOPYFLAGS = -O binary --remove-section=.bss
|
||||
OBJECTS = head.o misc.o
|
||||
OBJECTS = $(target)/head.o $(target)/misc.o
|
||||
|
||||
# files to compress
|
||||
SYSTEM = $(TOPDIR)/vmlinux.bin
|
||||
SYSTEM = $(objtree)/vmlinux.bin
|
||||
|
||||
all: vmlinuz
|
||||
all: $(target_compressed_dir)/vmlinuz
|
||||
|
||||
decompress.bin: $(OBJECTS)
|
||||
$(LD) -T decompress.ld -o decompress.o $(OBJECTS)
|
||||
$(OBJCOPY) $(OBJCOPYFLAGS) decompress.o decompress.bin
|
||||
# save it for mkprod in the topdir.
|
||||
cp decompress.bin $(TOPDIR)
|
||||
$(target)/decompress.bin: $(OBJECTS)
|
||||
$(LD) -T $(src)/decompress.ld -o $(target)/decompress.o $(OBJECTS)
|
||||
$(OBJCOPY) $(OBJCOPYFLAGS) $(target)/decompress.o $(target)/decompress.bin
|
||||
|
||||
# Create vmlinuz image in top-level build directory
|
||||
$(target_compressed_dir)/vmlinuz: $(target) piggy.img $(target)/decompress.bin
|
||||
@echo " COMPR vmlinux.bin --> vmlinuz"
|
||||
@cat $(target)/decompress.bin piggy.img > $(target_compressed_dir)/vmlinuz
|
||||
@rm -f piggy.img
|
||||
|
||||
vmlinuz: piggy.img decompress.bin
|
||||
cat decompress.bin piggy.img > vmlinuz
|
||||
rm -f piggy.img
|
||||
$(target)/head.o: $(src)/head.S
|
||||
$(CC) -D__ASSEMBLY__ -traditional -c $< -o $@
|
||||
|
||||
head.o: head.S
|
||||
$(CC) -D__ASSEMBLY__ -traditional -c head.S -o head.o
|
||||
$(target)/misc.o: $(src)/misc.c
|
||||
$(CC) -D__KERNEL__ -c $< -o $@
|
||||
|
||||
# gzip the kernel image
|
||||
|
||||
piggy.img: $(SYSTEM)
|
||||
cat $(SYSTEM) | gzip -f -9 > piggy.img
|
||||
@cat $(SYSTEM) | gzip -f -9 > piggy.img
|
||||
|
||||
$(target):
|
||||
mkdir -p $(target)
|
||||
|
||||
clean:
|
||||
rm -f piggy.img vmlinuz vmlinuz.o
|
||||
rm -f piggy.img $(objtree)/vmlinuz
|
||||
|
||||
|
|
|
@ -13,7 +13,8 @@
|
|||
#include <asm/arch/sv_addr_ag.h>
|
||||
|
||||
#define RAM_INIT_MAGIC 0x56902387
|
||||
|
||||
#define COMMAND_LINE_MAGIC 0x87109563
|
||||
|
||||
;; Exported symbols
|
||||
|
||||
.globl _input_data
|
||||
|
@ -88,6 +89,12 @@ basse: move.d pc, r5
|
|||
cmp.d r2, r1
|
||||
bcs 1b
|
||||
nop
|
||||
|
||||
;; Save command line magic and address.
|
||||
move.d _cmd_line_magic, $r12
|
||||
move.d $r10, [$r12]
|
||||
move.d _cmd_line_addr, $r12
|
||||
move.d $r11, [$r12]
|
||||
|
||||
;; Do the decompression and save compressed size in _inptr
|
||||
|
||||
|
@ -98,7 +105,13 @@ basse: move.d pc, r5
|
|||
|
||||
move.d [_input_data], r9 ; flash address of compressed kernel
|
||||
add.d [_inptr], r9 ; size of compressed kernel
|
||||
|
||||
|
||||
;; Restore command line magic and address.
|
||||
move.d _cmd_line_magic, $r10
|
||||
move.d [$r10], $r10
|
||||
move.d _cmd_line_addr, $r11
|
||||
move.d [$r11], $r11
|
||||
|
||||
;; Enter the decompressed kernel
|
||||
move.d RAM_INIT_MAGIC, r8 ; Tell kernel that DRAM is initialized
|
||||
jump 0x40004000 ; kernel is linked to this address
|
||||
|
@ -107,5 +120,8 @@ basse: move.d pc, r5
|
|||
|
||||
_input_data:
|
||||
.dword 0 ; used by the decompressor
|
||||
|
||||
_cmd_line_magic:
|
||||
.dword 0
|
||||
_cmd_line_addr:
|
||||
.dword 0
|
||||
#include "../../lib/hw_settings.S"
|
||||
|
|
|
@ -1,52 +1,53 @@
|
|||
#
|
||||
# Makefile for rescue code
|
||||
#
|
||||
ifndef TOPDIR
|
||||
TOPDIR = ../../../..
|
||||
endif
|
||||
CC = gcc-cris -mlinux -I $(TOPDIR)/include
|
||||
target = $(target_rescue_dir)
|
||||
src = $(src_rescue_dir)
|
||||
|
||||
CC = gcc-cris -mlinux $(LINUXINCLUDE)
|
||||
CFLAGS = -O2
|
||||
LD = gcc-cris -mlinux -nostdlib
|
||||
OBJCOPY = objcopy-cris
|
||||
OBJCOPYFLAGS = -O binary --remove-section=.bss
|
||||
|
||||
all: rescue.bin testrescue.bin kimagerescue.bin
|
||||
all: $(target)/rescue.bin $(target)/testrescue.bin $(target)/kimagerescue.bin
|
||||
|
||||
rescue: rescue.bin
|
||||
# do nothing
|
||||
$(target)/rescue.bin: $(target) $(target)/head.o
|
||||
$(LD) -T $(src)/rescue.ld -o $(target)/rescue.o $(target)/head.o
|
||||
$(OBJCOPY) $(OBJCOPYFLAGS) $(target)/rescue.o $(target)/rescue.bin
|
||||
# Place a copy in top-level build directory
|
||||
cp -p $(target)/rescue.bin $(objtree)
|
||||
|
||||
rescue.bin: head.o
|
||||
$(LD) -T rescue.ld -o rescue.o head.o
|
||||
$(OBJCOPY) $(OBJCOPYFLAGS) rescue.o rescue.bin
|
||||
cp rescue.bin $(TOPDIR)
|
||||
|
||||
testrescue.bin: testrescue.o
|
||||
$(OBJCOPY) $(OBJCOPYFLAGS) testrescue.o tr.bin
|
||||
$(target)/testrescue.bin: $(target) $(target)/testrescue.o
|
||||
$(OBJCOPY) $(OBJCOPYFLAGS) $(target)/testrescue.o tr.bin
|
||||
# Pad it to 784 bytes
|
||||
dd if=/dev/zero of=tmp2423 bs=1 count=784
|
||||
cat tr.bin tmp2423 >testrescue_tmp.bin
|
||||
dd if=testrescue_tmp.bin of=testrescue.bin bs=1 count=784
|
||||
dd if=testrescue_tmp.bin of=$(target)/testrescue.bin bs=1 count=784
|
||||
rm tr.bin tmp2423 testrescue_tmp.bin
|
||||
|
||||
kimagerescue.bin: kimagerescue.o
|
||||
$(OBJCOPY) $(OBJCOPYFLAGS) kimagerescue.o ktr.bin
|
||||
$(target)/kimagerescue.bin: $(target) $(target)/kimagerescue.o
|
||||
$(OBJCOPY) $(OBJCOPYFLAGS) $(target)/kimagerescue.o ktr.bin
|
||||
# Pad it to 784 bytes, that's what the rescue loader expects
|
||||
dd if=/dev/zero of=tmp2423 bs=1 count=784
|
||||
cat ktr.bin tmp2423 >kimagerescue_tmp.bin
|
||||
dd if=kimagerescue_tmp.bin of=kimagerescue.bin bs=1 count=784
|
||||
dd if=kimagerescue_tmp.bin of=$(target)/kimagerescue.bin bs=1 count=784
|
||||
rm ktr.bin tmp2423 kimagerescue_tmp.bin
|
||||
|
||||
head.o: head.S
|
||||
$(target):
|
||||
mkdir -p $(target)
|
||||
|
||||
$(target)/head.o: $(src)/head.S
|
||||
$(CC) -D__ASSEMBLY__ -traditional -c $< -o $*.o
|
||||
|
||||
testrescue.o: testrescue.S
|
||||
$(target)/testrescue.o: $(src)/testrescue.S
|
||||
$(CC) -D__ASSEMBLY__ -traditional -c $< -o $*.o
|
||||
|
||||
kimagerescue.o: kimagerescue.S
|
||||
$(target)/kimagerescue.o: $(src)/kimagerescue.S
|
||||
$(CC) -D__ASSEMBLY__ -traditional -c $< -o $*.o
|
||||
|
||||
clean:
|
||||
rm -f *.o *.bin
|
||||
rm -f $(target)/*.o $(target)/*.bin
|
||||
|
||||
fastdep:
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: head.S,v 1.6 2003/04/09 08:12:43 pkj Exp $
|
||||
/* $Id: head.S,v 1.7 2005/03/07 12:11:06 starvik Exp $
|
||||
*
|
||||
* Rescue code, made to reside at the beginning of the
|
||||
* flash-memory. when it starts, it checks a partition
|
||||
|
@ -121,12 +121,13 @@
|
|||
;; 0x80000000 if loaded in flash (as it should be)
|
||||
;; since etrax actually starts at address 2 when booting from flash, we
|
||||
;; put a nop (2 bytes) here first so we dont accidentally skip the di
|
||||
|
||||
|
||||
nop
|
||||
di
|
||||
|
||||
jump in_cache ; enter cached area instead
|
||||
in_cache:
|
||||
in_cache:
|
||||
|
||||
|
||||
;; first put a jump test to give a possibility of upgrading the rescue code
|
||||
;; without erasing/reflashing the sector. we put a longword of -1 here and if
|
||||
|
@ -325,9 +326,29 @@ flash_ok:
|
|||
;; result will be in r0
|
||||
checksum:
|
||||
moveq 0, $r0
|
||||
1: addu.b [$r1+], $r0
|
||||
subq 1, $r2
|
||||
bne 1b
|
||||
moveq CONFIG_ETRAX_FLASH1_SIZE, $r6
|
||||
|
||||
;; If the first physical flash memory is exceeded wrap to the second one.
|
||||
btstq 26, $r1 ; Are we addressing first flash?
|
||||
bpl 1f
|
||||
nop
|
||||
clear.d $r6
|
||||
|
||||
1: test.d $r6 ; 0 = no wrapping
|
||||
beq 2f
|
||||
nop
|
||||
lslq 20, $r6 ; Convert MB to bytes
|
||||
sub.d $r1, $r6
|
||||
|
||||
2: addu.b [$r1+], $r0
|
||||
subq 1, $r6 ; Flash memory left
|
||||
beq 3f
|
||||
subq 1, $r2 ; Length left
|
||||
bne 2b
|
||||
nop
|
||||
ret
|
||||
nop
|
||||
|
||||
3: move.d MEM_CSE1_START, $r1 ; wrap to second flash
|
||||
ba 2b
|
||||
nop
|
||||
|
|
|
@ -1,17 +1,11 @@
|
|||
config ETRAX_ETHERNET
|
||||
bool "Ethernet support"
|
||||
depends on ETRAX_ARCH_V10
|
||||
select NET_ETHERNET
|
||||
help
|
||||
This option enables the ETRAX 100LX built-in 10/100Mbit Ethernet
|
||||
controller.
|
||||
|
||||
# this is just so that the user does not have to go into the
|
||||
# normal ethernet driver section just to enable ethernetworking
|
||||
config NET_ETHERNET
|
||||
bool
|
||||
depends on ETRAX_ETHERNET
|
||||
default y
|
||||
|
||||
choice
|
||||
prompt "Network LED behavior"
|
||||
depends on ETRAX_ETHERNET
|
||||
|
@ -20,26 +14,26 @@ choice
|
|||
config ETRAX_NETWORK_LED_ON_WHEN_LINK
|
||||
bool "LED_on_when_link"
|
||||
help
|
||||
Selecting LED_on_when_link will light the LED when there is a
|
||||
connection and will flash off when there is activity.
|
||||
Selecting LED_on_when_link will light the LED when there is a
|
||||
connection and will flash off when there is activity.
|
||||
|
||||
Selecting LED_on_when_activity will light the LED only when
|
||||
Selecting LED_on_when_activity will light the LED only when
|
||||
there is activity.
|
||||
|
||||
This setting will also affect the behaviour of other activity LEDs
|
||||
e.g. Bluetooth.
|
||||
This setting will also affect the behaviour of other activity LEDs
|
||||
e.g. Bluetooth.
|
||||
|
||||
config ETRAX_NETWORK_LED_ON_WHEN_ACTIVITY
|
||||
bool "LED_on_when_activity"
|
||||
help
|
||||
Selecting LED_on_when_link will light the LED when there is a
|
||||
connection and will flash off when there is activity.
|
||||
Selecting LED_on_when_link will light the LED when there is a
|
||||
connection and will flash off when there is activity.
|
||||
|
||||
Selecting LED_on_when_activity will light the LED only when
|
||||
Selecting LED_on_when_activity will light the LED only when
|
||||
there is activity.
|
||||
|
||||
This setting will also affect the behaviour of other activity LEDs
|
||||
e.g. Bluetooth.
|
||||
This setting will also affect the behaviour of other activity LEDs
|
||||
e.g. Bluetooth.
|
||||
|
||||
endchoice
|
||||
|
||||
|
@ -91,11 +85,11 @@ choice
|
|||
depends on ETRAX_SERIAL_PORT0
|
||||
default ETRAX_SERIAL_PORT0_DMA6_OUT
|
||||
|
||||
config CONFIG_ETRAX_SERIAL_PORT0_NO_DMA_OUT
|
||||
bool "No DMA out"
|
||||
config ETRAX_SERIAL_PORT0_NO_DMA_OUT
|
||||
bool "No DMA out"
|
||||
|
||||
config CONFIG_ETRAX_SERIAL_PORT0_DMA6_OUT
|
||||
bool "DMA 6"
|
||||
config ETRAX_SERIAL_PORT0_DMA6_OUT
|
||||
bool "DMA 6"
|
||||
|
||||
endchoice
|
||||
|
||||
|
@ -104,11 +98,11 @@ choice
|
|||
depends on ETRAX_SERIAL_PORT0
|
||||
default ETRAX_SERIAL_PORT0_DMA7_IN
|
||||
|
||||
config CONFIG_ETRAX_SERIAL_PORT0_NO_DMA_IN
|
||||
bool "No DMA in"
|
||||
config ETRAX_SERIAL_PORT0_NO_DMA_IN
|
||||
bool "No DMA in"
|
||||
|
||||
config CONFIG_ETRAX_SERIAL_PORT0_DMA7_IN
|
||||
bool "DMA 7"
|
||||
config ETRAX_SERIAL_PORT0_DMA7_IN
|
||||
bool "DMA 7"
|
||||
|
||||
endchoice
|
||||
|
||||
|
@ -205,11 +199,11 @@ choice
|
|||
depends on ETRAX_SERIAL_PORT1
|
||||
default ETRAX_SERIAL_PORT1_DMA8_OUT
|
||||
|
||||
config CONFIG_ETRAX_SERIAL_PORT1_NO_DMA_OUT
|
||||
bool "No DMA out"
|
||||
config ETRAX_SERIAL_PORT1_NO_DMA_OUT
|
||||
bool "No DMA out"
|
||||
|
||||
config CONFIG_ETRAX_SERIAL_PORT1_DMA8_OUT
|
||||
bool "DMA 8"
|
||||
config ETRAX_SERIAL_PORT1_DMA8_OUT
|
||||
bool "DMA 8"
|
||||
|
||||
endchoice
|
||||
|
||||
|
@ -218,11 +212,11 @@ choice
|
|||
depends on ETRAX_SERIAL_PORT1
|
||||
default ETRAX_SERIAL_PORT1_DMA9_IN
|
||||
|
||||
config CONFIG_ETRAX_SERIAL_PORT1_NO_DMA_IN
|
||||
bool "No DMA in"
|
||||
config ETRAX_SERIAL_PORT1_NO_DMA_IN
|
||||
bool "No DMA in"
|
||||
|
||||
config CONFIG_ETRAX_SERIAL_PORT1_DMA9_IN
|
||||
bool "DMA 9"
|
||||
config ETRAX_SERIAL_PORT1_DMA9_IN
|
||||
bool "DMA 9"
|
||||
|
||||
endchoice
|
||||
|
||||
|
@ -308,7 +302,7 @@ config ETRAX_SER1_CD_ON_PB_BIT
|
|||
Specify the pin of the PB port to carry the CD signal for serial
|
||||
port 1.
|
||||
|
||||
comment "Make sure you dont have the same PB bits more than once!"
|
||||
comment "Make sure you do not have the same PB bits more than once!"
|
||||
depends on ETRAX_SERIAL && ETRAX_SER0_DTR_RI_DSR_CD_ON_PB && ETRAX_SER1_DTR_RI_DSR_CD_ON_PB
|
||||
|
||||
config ETRAX_SERIAL_PORT2
|
||||
|
@ -322,11 +316,11 @@ choice
|
|||
depends on ETRAX_SERIAL_PORT2
|
||||
default ETRAX_SERIAL_PORT2_DMA2_OUT
|
||||
|
||||
config CONFIG_ETRAX_SERIAL_PORT2_NO_DMA_OUT
|
||||
bool "No DMA out"
|
||||
config ETRAX_SERIAL_PORT2_NO_DMA_OUT
|
||||
bool "No DMA out"
|
||||
|
||||
config CONFIG_ETRAX_SERIAL_PORT2_DMA2_OUT
|
||||
bool "DMA 2"
|
||||
config ETRAX_SERIAL_PORT2_DMA2_OUT
|
||||
bool "DMA 2"
|
||||
|
||||
endchoice
|
||||
|
||||
|
@ -335,11 +329,11 @@ choice
|
|||
depends on ETRAX_SERIAL_PORT2
|
||||
default ETRAX_SERIAL_PORT2_DMA3_IN
|
||||
|
||||
config CONFIG_ETRAX_SERIAL_PORT2_NO_DMA_IN
|
||||
bool "No DMA in"
|
||||
config ETRAX_SERIAL_PORT2_NO_DMA_IN
|
||||
bool "No DMA in"
|
||||
|
||||
config CONFIG_ETRAX_SERIAL_PORT2_DMA3_IN
|
||||
bool "DMA 3"
|
||||
config ETRAX_SERIAL_PORT2_DMA3_IN
|
||||
bool "DMA 3"
|
||||
|
||||
endchoice
|
||||
|
||||
|
@ -436,11 +430,11 @@ choice
|
|||
depends on ETRAX_SERIAL_PORT3
|
||||
default ETRAX_SERIAL_PORT3_DMA4_OUT
|
||||
|
||||
config CONFIG_ETRAX_SERIAL_PORT3_NO_DMA_OUT
|
||||
bool "No DMA out"
|
||||
config ETRAX_SERIAL_PORT3_NO_DMA_OUT
|
||||
bool "No DMA out"
|
||||
|
||||
config CONFIG_ETRAX_SERIAL_PORT3_DMA4_OUT
|
||||
bool "DMA 4"
|
||||
config ETRAX_SERIAL_PORT3_DMA4_OUT
|
||||
bool "DMA 4"
|
||||
|
||||
endchoice
|
||||
|
||||
|
@ -449,11 +443,11 @@ choice
|
|||
depends on ETRAX_SERIAL_PORT3
|
||||
default ETRAX_SERIAL_PORT3_DMA5_IN
|
||||
|
||||
config CONFIG_ETRAX_SERIAL_PORT3_NO_DMA_IN
|
||||
bool "No DMA in"
|
||||
config ETRAX_SERIAL_PORT3_NO_DMA_IN
|
||||
bool "No DMA in"
|
||||
|
||||
config CONFIG_ETRAX_SERIAL_PORT3_DMA5_IN
|
||||
bool "DMA 5"
|
||||
config ETRAX_SERIAL_PORT3_DMA5_IN
|
||||
bool "DMA 5"
|
||||
|
||||
endchoice
|
||||
|
||||
|
@ -554,7 +548,6 @@ config ETRAX_IDE
|
|||
select BLK_DEV_IDEDISK
|
||||
select BLK_DEV_IDECD
|
||||
select BLK_DEV_IDEDMA
|
||||
select DMA_NONPCI
|
||||
help
|
||||
Enable this to get support for ATA/IDE.
|
||||
You can't use paralell ports or SCSI ports
|
||||
|
@ -579,7 +572,7 @@ config ETRAX_IDE_PB7_RESET
|
|||
IDE reset on pin 7 on port B
|
||||
|
||||
config ETRAX_IDE_G27_RESET
|
||||
bool "Port_G_Bit_27"
|
||||
bool "Port_G_Bit_27"
|
||||
help
|
||||
IDE reset on pin 27 on port G
|
||||
|
||||
|
@ -588,30 +581,36 @@ endchoice
|
|||
|
||||
config ETRAX_USB_HOST
|
||||
bool "USB host"
|
||||
select USB
|
||||
help
|
||||
This option enables the host functionality of the ETRAX 100LX
|
||||
built-in USB controller. In host mode the controller is designed
|
||||
for CTRL and BULK traffic only, INTR traffic may work as well
|
||||
however (depending on the requirements of timeliness).
|
||||
|
||||
config USB
|
||||
tristate
|
||||
depends on ETRAX_USB_HOST
|
||||
default y
|
||||
|
||||
config ETRAX_USB_HOST_PORT1
|
||||
bool " USB port 1 enabled"
|
||||
depends on ETRAX_USB_HOST
|
||||
default n
|
||||
bool "USB port 1 enabled"
|
||||
depends on ETRAX_USB_HOST
|
||||
default n
|
||||
|
||||
config ETRAX_USB_HOST_PORT2
|
||||
bool " USB port 2 enabled"
|
||||
depends on ETRAX_USB_HOST
|
||||
default n
|
||||
bool "USB port 2 enabled"
|
||||
depends on ETRAX_USB_HOST
|
||||
default n
|
||||
|
||||
config ETRAX_AXISFLASHMAP
|
||||
bool "Axis flash-map support"
|
||||
depends on ETRAX_ARCH_V10
|
||||
select MTD
|
||||
select MTD_CFI
|
||||
select MTD_CFI_AMDSTD
|
||||
select MTD_OBSOLETE_CHIPS
|
||||
select MTD_AMDSTD
|
||||
select MTD_CHAR
|
||||
select MTD_BLOCK
|
||||
select MTD_PARTITIONS
|
||||
select MTD_CONCAT
|
||||
select MTD_COMPLEX_MAPPINGS
|
||||
help
|
||||
This option enables MTD mapping of flash devices. Needed to use
|
||||
flash memories. If unsure, say Y.
|
||||
|
@ -627,119 +626,6 @@ config ETRAX_PTABLE_SECTOR
|
|||
for changing this is when the flash block size is bigger
|
||||
than 64kB (e.g. when using two parallel 16 bit flashes).
|
||||
|
||||
# here we define the CONFIG_'s necessary to enable MTD support
|
||||
# for the flash
|
||||
config MTD
|
||||
tristate
|
||||
depends on ETRAX_AXISFLASHMAP
|
||||
default y
|
||||
help
|
||||
Memory Technology Devices are flash, RAM and similar chips, often
|
||||
used for solid state file systems on embedded devices. This option
|
||||
will provide the generic support for MTD drivers to register
|
||||
themselves with the kernel and for potential users of MTD devices
|
||||
to enumerate the devices which are present and obtain a handle on
|
||||
them. It will also allow you to select individual drivers for
|
||||
particular hardware and users of MTD devices. If unsure, say N.
|
||||
|
||||
config MTD_CFI
|
||||
tristate
|
||||
depends on ETRAX_AXISFLASHMAP
|
||||
default y
|
||||
help
|
||||
The Common Flash Interface specification was developed by Intel,
|
||||
AMD and other flash manufactures that provides a universal method
|
||||
for probing the capabilities of flash devices. If you wish to
|
||||
support any device that is CFI-compliant, you need to enable this
|
||||
option. Visit <http://www.amd.com/products/nvd/overview/cfi.html>
|
||||
for more information on CFI.
|
||||
|
||||
config MTD_CFI_AMDSTD
|
||||
tristate
|
||||
depends on ETRAX_AXISFLASHMAP
|
||||
default y
|
||||
help
|
||||
The Common Flash Interface defines a number of different command
|
||||
sets which a CFI-compliant chip may claim to implement. This code
|
||||
provides support for one of those command sets, used on chips
|
||||
chips including the AMD Am29LV320.
|
||||
|
||||
config MTD_OBSOLETE_CHIPS
|
||||
bool
|
||||
depends on ETRAX_AXISFLASHMAP
|
||||
default y
|
||||
help
|
||||
This option does not enable any code directly, but will allow you to
|
||||
select some other chip drivers which are now considered obsolete,
|
||||
because the generic CONFIG_JEDEC_PROBE code above should now detect
|
||||
the chips which are supported by these drivers, and allow the generic
|
||||
CFI-compatible drivers to drive the chips. Say 'N' here unless you have
|
||||
already tried the CONFIG_JEDEC_PROBE method and reported its failure
|
||||
to the MTD mailing list at <linux-mtd@lists.infradead.org>
|
||||
|
||||
config MTD_AMDSTD
|
||||
tristate
|
||||
depends on ETRAX_AXISFLASHMAP
|
||||
default y
|
||||
help
|
||||
This option enables support for flash chips using AMD-compatible
|
||||
commands, including some which are not CFI-compatible and hence
|
||||
cannot be used with the CONFIG_MTD_CFI_AMDSTD option.
|
||||
|
||||
It also works on AMD compatible chips that do conform to CFI.
|
||||
|
||||
config MTD_CHAR
|
||||
tristate
|
||||
depends on ETRAX_AXISFLASHMAP
|
||||
default y
|
||||
help
|
||||
This provides a character device for each MTD device present in
|
||||
the system, allowing the user to read and write directly to the
|
||||
memory chips, and also use ioctl() to obtain information about
|
||||
the device, or to erase parts of it.
|
||||
|
||||
config MTD_BLOCK
|
||||
tristate
|
||||
depends on ETRAX_AXISFLASHMAP
|
||||
default y
|
||||
---help---
|
||||
Although most flash chips have an erase size too large to be useful
|
||||
as block devices, it is possible to use MTD devices which are based
|
||||
on RAM chips in this manner. This block device is a user of MTD
|
||||
devices performing that function.
|
||||
|
||||
At the moment, it is also required for the Journalling Flash File
|
||||
System(s) to obtain a handle on the MTD device when it's mounted
|
||||
(although JFFS and JFFS2 don't actually use any of the functionality
|
||||
of the mtdblock device).
|
||||
|
||||
Later, it may be extended to perform read/erase/modify/write cycles
|
||||
on flash chips to emulate a smaller block size. Needless to say,
|
||||
this is very unsafe, but could be useful for file systems which are
|
||||
almost never written to.
|
||||
|
||||
You do not need this option for use with the DiskOnChip devices. For
|
||||
those, enable NFTL support (CONFIG_NFTL) instead.
|
||||
|
||||
config MTD_PARTITIONS
|
||||
tristate
|
||||
depends on ETRAX_AXISFLASHMAP
|
||||
default y
|
||||
help
|
||||
If you have a device which needs to divide its flash chip(s) up
|
||||
into multiple 'partitions', each of which appears to the user as
|
||||
a separate MTD device, you require this option to be enabled. If
|
||||
unsure, say 'Y'.
|
||||
|
||||
Note, however, that you don't need this option for the DiskOnChip
|
||||
devices. Partitioning on NFTL 'devices' is a different - that's the
|
||||
'normal' form of partitioning used on a block device.
|
||||
|
||||
config MTD_CONCAT
|
||||
tristate
|
||||
depends on ETRAX_AXISFLASHMAP
|
||||
default y
|
||||
|
||||
config ETRAX_I2C
|
||||
bool "I2C support"
|
||||
depends on ETRAX_ARCH_V10
|
||||
|
@ -752,7 +638,7 @@ config ETRAX_I2C
|
|||
val = ioctl(fd, _IO(ETRAXI2C_IOCTYPE, I2C_READREG), i2c_arg);
|
||||
|
||||
# this is true for most products since PB-I2C seems to be somewhat
|
||||
# flawed..
|
||||
# flawed..
|
||||
config ETRAX_I2C_USES_PB_NOT_PB_I2C
|
||||
bool "I2C uses PB not PB-I2C"
|
||||
depends on ETRAX_I2C
|
||||
|
@ -886,7 +772,7 @@ config ETRAX_RTC
|
|||
bool "Real Time Clock support"
|
||||
depends on ETRAX_ARCH_V10
|
||||
help
|
||||
Enables drivers for the Real-Time Clock battery-backed chips on
|
||||
Enables drivers for the Real-Time Clock battery-backed chips on
|
||||
some products. The kernel reads the time when booting, and
|
||||
the date can be set using ioctl(fd, RTC_SET_TIME, &rt) with rt a
|
||||
rtc_time struct (see <file:include/asm-cris/rtc.h>) on the /dev/rtc
|
||||
|
@ -903,13 +789,13 @@ config ETRAX_DS1302
|
|||
bool "DS1302"
|
||||
help
|
||||
Enables the driver for the DS1302 Real-Time Clock battery-backed
|
||||
chip on some products.
|
||||
chip on some products.
|
||||
|
||||
config ETRAX_PCF8563
|
||||
bool "PCF8563"
|
||||
help
|
||||
Enables the driver for the PCF8563 Real-Time Clock battery-backed
|
||||
chip on some products.
|
||||
chip on some products.
|
||||
|
||||
endchoice
|
||||
|
||||
|
@ -954,10 +840,8 @@ config ETRAX_DS1302_TRICKLE_CHARGE
|
|||
help
|
||||
This controls the initial value of the trickle charge register.
|
||||
0 = disabled (use this if you are unsure or have a non rechargable battery)
|
||||
Otherwise the following values can be OR:ed together to control the
|
||||
Otherwise the following values can be OR:ed together to control the
|
||||
charge current:
|
||||
1 = 2kohm, 2 = 4kohm, 3 = 4kohm
|
||||
4 = 1 diode, 8 = 2 diodes
|
||||
Allowed values are (increasing current): 0, 11, 10, 9, 7, 6, 5
|
||||
|
||||
|
||||
|
|
|
@ -11,6 +11,9 @@
|
|||
* partition split defined below.
|
||||
*
|
||||
* $Log: axisflashmap.c,v $
|
||||
* Revision 1.11 2004/11/15 10:27:14 starvik
|
||||
* Corrected typo (Thanks to Milton Miller <miltonm@bga.com>).
|
||||
*
|
||||
* Revision 1.10 2004/08/16 12:37:22 starvik
|
||||
* Merge of Linux 2.6.8
|
||||
*
|
||||
|
@ -161,7 +164,7 @@
|
|||
#elif CONFIG_ETRAX_FLASH_BUSWIDTH==2
|
||||
#define flash_data __u16
|
||||
#elif CONFIG_ETRAX_FLASH_BUSWIDTH==4
|
||||
#define flash_data __u16
|
||||
#define flash_data __u32
|
||||
#endif
|
||||
|
||||
/* From head.S */
|
||||
|
|
|
@ -7,6 +7,15 @@
|
|||
*! Functions exported: ds1302_readreg, ds1302_writereg, ds1302_init
|
||||
*!
|
||||
*! $Log: ds1302.c,v $
|
||||
*! Revision 1.18 2005/01/24 09:11:26 mikaelam
|
||||
*! Minor changes to get DS1302 RTC chip driver to work
|
||||
*!
|
||||
*! Revision 1.17 2005/01/05 06:11:22 starvik
|
||||
*! No need to do local_irq_disable after local_irq_save.
|
||||
*!
|
||||
*! Revision 1.16 2004/12/13 12:21:52 starvik
|
||||
*! Added I/O and DMA allocators from Linux 2.4
|
||||
*!
|
||||
*! Revision 1.14 2004/08/24 06:48:43 starvik
|
||||
*! Whitespace cleanup
|
||||
*!
|
||||
|
@ -124,9 +133,9 @@
|
|||
*!
|
||||
*! ---------------------------------------------------------------------------
|
||||
*!
|
||||
*! (C) Copyright 1999, 2000, 2001 Axis Communications AB, LUND, SWEDEN
|
||||
*! (C) Copyright 1999, 2000, 2001, 2002, 2003, 2004 Axis Communications AB, LUND, SWEDEN
|
||||
*!
|
||||
*! $Id: ds1302.c,v 1.14 2004/08/24 06:48:43 starvik Exp $
|
||||
*! $Id: ds1302.c,v 1.18 2005/01/24 09:11:26 mikaelam Exp $
|
||||
*!
|
||||
*!***************************************************************************/
|
||||
|
||||
|
@ -145,6 +154,7 @@
|
|||
#include <asm/arch/svinto.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/rtc.h>
|
||||
#include <asm/arch/io_interface_mux.h>
|
||||
|
||||
#define RTC_MAJOR_NR 121 /* local major, change later */
|
||||
|
||||
|
@ -320,7 +330,6 @@ get_rtc_time(struct rtc_time *rtc_tm)
|
|||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
local_irq_disable();
|
||||
|
||||
rtc_tm->tm_sec = CMOS_READ(RTC_SECONDS);
|
||||
rtc_tm->tm_min = CMOS_READ(RTC_MINUTES);
|
||||
|
@ -358,7 +367,7 @@ static int
|
|||
rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned long flags;
|
||||
|
||||
switch(cmd) {
|
||||
case RTC_RD_TIME: /* read the time/date from RTC */
|
||||
|
@ -382,7 +391,7 @@ rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
|
|||
return -EPERM;
|
||||
|
||||
if (copy_from_user(&rtc_tm, (struct rtc_time*)arg, sizeof(struct rtc_time)))
|
||||
return -EFAULT;
|
||||
return -EFAULT;
|
||||
|
||||
yrs = rtc_tm.tm_year + 1900;
|
||||
mon = rtc_tm.tm_mon + 1; /* tm_mon starts at zero */
|
||||
|
@ -419,7 +428,6 @@ rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
|
|||
BIN_TO_BCD(yrs);
|
||||
|
||||
local_irq_save(flags);
|
||||
local_irq_disable();
|
||||
CMOS_WRITE(yrs, RTC_YEAR);
|
||||
CMOS_WRITE(mon, RTC_MONTH);
|
||||
CMOS_WRITE(day, RTC_DAY_OF_MONTH);
|
||||
|
@ -438,7 +446,7 @@ rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
|
|||
|
||||
case RTC_SET_CHARGE: /* set the RTC TRICKLE CHARGE register */
|
||||
{
|
||||
int tcs_val;
|
||||
int tcs_val;
|
||||
|
||||
if (!capable(CAP_SYS_TIME))
|
||||
return -EPERM;
|
||||
|
@ -492,8 +500,8 @@ print_rtc_status(void)
|
|||
/* The various file operations we support. */
|
||||
|
||||
static struct file_operations rtc_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.ioctl = rtc_ioctl,
|
||||
.owner = THIS_MODULE,
|
||||
.ioctl = rtc_ioctl,
|
||||
};
|
||||
|
||||
/* Probe for the chip by writing something to its RAM and try reading it back. */
|
||||
|
@ -532,7 +540,7 @@ ds1302_probe(void)
|
|||
"PB",
|
||||
#endif
|
||||
CONFIG_ETRAX_DS1302_RSTBIT);
|
||||
print_rtc_status();
|
||||
print_rtc_status();
|
||||
retval = 1;
|
||||
} else {
|
||||
stop();
|
||||
|
@ -548,7 +556,9 @@ ds1302_probe(void)
|
|||
int __init
|
||||
ds1302_init(void)
|
||||
{
|
||||
#ifdef CONFIG_ETRAX_I2C
|
||||
i2c_init();
|
||||
#endif
|
||||
|
||||
if (!ds1302_probe()) {
|
||||
#ifdef CONFIG_ETRAX_DS1302_RST_ON_GENERIC_PORT
|
||||
|
@ -558,25 +568,42 @@ ds1302_init(void)
|
|||
*
|
||||
* Make sure that R_GEN_CONFIG is setup correct.
|
||||
*/
|
||||
genconfig_shadow = ((genconfig_shadow &
|
||||
~IO_MASK(R_GEN_CONFIG, ata)) |
|
||||
(IO_STATE(R_GEN_CONFIG, ata, select)));
|
||||
*R_GEN_CONFIG = genconfig_shadow;
|
||||
/* Allocating the ATA interface will grab almost all
|
||||
* pins in I/O groups a, b, c and d. A consequence of
|
||||
* allocating the ATA interface is that the fixed
|
||||
* interfaces shared RAM, parallel port 0, parallel
|
||||
* port 1, parallel port W, SCSI-8 port 0, SCSI-8 port
|
||||
* 1, SCSI-W, serial port 2, serial port 3,
|
||||
* synchronous serial port 3 and USB port 2 and almost
|
||||
* all GPIO pins on port g cannot be used.
|
||||
*/
|
||||
if (cris_request_io_interface(if_ata, "ds1302/ATA")) {
|
||||
printk(KERN_WARNING "ds1302: Failed to get IO interface\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
#elif CONFIG_ETRAX_DS1302_RSTBIT == 0
|
||||
|
||||
/* Set the direction of this bit to out. */
|
||||
genconfig_shadow = ((genconfig_shadow &
|
||||
~IO_MASK(R_GEN_CONFIG, g0dir)) |
|
||||
(IO_STATE(R_GEN_CONFIG, g0dir, out)));
|
||||
*R_GEN_CONFIG = genconfig_shadow;
|
||||
if (cris_io_interface_allocate_pins(if_gpio_grp_a,
|
||||
'g',
|
||||
CONFIG_ETRAX_DS1302_RSTBIT,
|
||||
CONFIG_ETRAX_DS1302_RSTBIT)) {
|
||||
printk(KERN_WARNING "ds1302: Failed to get IO interface\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Set the direction of this bit to out. */
|
||||
genconfig_shadow = ((genconfig_shadow &
|
||||
~IO_MASK(R_GEN_CONFIG, g0dir)) |
|
||||
(IO_STATE(R_GEN_CONFIG, g0dir, out)));
|
||||
*R_GEN_CONFIG = genconfig_shadow;
|
||||
#endif
|
||||
if (!ds1302_probe()) {
|
||||
printk(KERN_WARNING "%s: RTC not found.\n", ds1302_name);
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
printk(KERN_WARNING "%s: RTC not found.\n", ds1302_name);
|
||||
return -1;
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
/* Initialise trickle charger */
|
||||
|
|
|
@ -20,6 +20,12 @@
|
|||
*! in the spin-lock.
|
||||
*!
|
||||
*! $Log: eeprom.c,v $
|
||||
*! Revision 1.12 2005/06/19 17:06:46 starvik
|
||||
*! Merge of Linux 2.6.12.
|
||||
*!
|
||||
*! Revision 1.11 2005/01/26 07:14:46 starvik
|
||||
*! Applied diff from kernel janitors (Nish Aravamudan).
|
||||
*!
|
||||
*! Revision 1.10 2003/09/11 07:29:48 starvik
|
||||
*! Merge of Linux 2.6.0-test5
|
||||
*!
|
||||
|
@ -94,6 +100,7 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/wait.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include "i2c.h"
|
||||
|
||||
|
@ -526,15 +533,10 @@ static ssize_t eeprom_read(struct file * file, char * buf, size_t count, loff_t
|
|||
return -EFAULT;
|
||||
}
|
||||
|
||||
while(eeprom.busy)
|
||||
{
|
||||
interruptible_sleep_on(&eeprom.wait_q);
|
||||
wait_event_interruptible(eeprom.wait_q, !eeprom.busy);
|
||||
if (signal_pending(current))
|
||||
return -EINTR;
|
||||
|
||||
/* bail out if we get interrupted */
|
||||
if (signal_pending(current))
|
||||
return -EINTR;
|
||||
|
||||
}
|
||||
eeprom.busy++;
|
||||
|
||||
page = (unsigned char) (p >> 8);
|
||||
|
@ -604,13 +606,10 @@ static ssize_t eeprom_write(struct file * file, const char * buf, size_t count,
|
|||
return -EFAULT;
|
||||
}
|
||||
|
||||
while(eeprom.busy)
|
||||
{
|
||||
interruptible_sleep_on(&eeprom.wait_q);
|
||||
/* bail out if we get interrupted */
|
||||
if (signal_pending(current))
|
||||
return -EINTR;
|
||||
}
|
||||
wait_event_interruptible(eeprom.wait_q, !eeprom.busy);
|
||||
/* bail out if we get interrupted */
|
||||
if (signal_pending(current))
|
||||
return -EINTR;
|
||||
eeprom.busy++;
|
||||
for(i = 0; (i < EEPROM_RETRIES) && (restart > 0); i++)
|
||||
{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: gpio.c,v 1.12 2004/08/24 07:19:59 starvik Exp $
|
||||
/* $Id: gpio.c,v 1.17 2005/06/19 17:06:46 starvik Exp $
|
||||
*
|
||||
* Etrax general port I/O device
|
||||
*
|
||||
|
@ -9,6 +9,18 @@
|
|||
* Johan Adolfsson (read/set directions, write, port G)
|
||||
*
|
||||
* $Log: gpio.c,v $
|
||||
* Revision 1.17 2005/06/19 17:06:46 starvik
|
||||
* Merge of Linux 2.6.12.
|
||||
*
|
||||
* Revision 1.16 2005/03/07 13:02:29 starvik
|
||||
* Protect driver global states with spinlock
|
||||
*
|
||||
* Revision 1.15 2005/01/05 06:08:55 starvik
|
||||
* No need to do local_irq_disable after local_irq_save.
|
||||
*
|
||||
* Revision 1.14 2004/12/13 12:21:52 starvik
|
||||
* Added I/O and DMA allocators from Linux 2.4
|
||||
*
|
||||
* Revision 1.12 2004/08/24 07:19:59 starvik
|
||||
* Whitespace cleanup
|
||||
*
|
||||
|
@ -142,6 +154,7 @@
|
|||
#include <asm/io.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/arch/io_interface_mux.h>
|
||||
|
||||
#define GPIO_MAJOR 120 /* experimental MAJOR number */
|
||||
|
||||
|
@ -194,6 +207,8 @@ static struct gpio_private *alarmlist = 0;
|
|||
static int gpio_some_alarms = 0; /* Set if someone uses alarm */
|
||||
static unsigned long gpio_pa_irq_enabled_mask = 0;
|
||||
|
||||
static DEFINE_SPINLOCK(gpio_lock); /* Protect directions etc */
|
||||
|
||||
/* Port A and B use 8 bit access, but Port G is 32 bit */
|
||||
#define NUM_PORTS (GPIO_MINOR_B+1)
|
||||
|
||||
|
@ -241,6 +256,9 @@ static volatile unsigned char *dir_shadow[NUM_PORTS] = {
|
|||
&port_pb_dir_shadow
|
||||
};
|
||||
|
||||
/* All bits in port g that can change dir. */
|
||||
static const unsigned long int changeable_dir_g_mask = 0x01FFFF01;
|
||||
|
||||
/* Port G is 32 bit, handle it special, some bits are both inputs
|
||||
and outputs at the same time, only some of the bits can change direction
|
||||
and some of them in groups of 8 bit. */
|
||||
|
@ -260,6 +278,7 @@ gpio_poll(struct file *file,
|
|||
unsigned int mask = 0;
|
||||
struct gpio_private *priv = (struct gpio_private *)file->private_data;
|
||||
unsigned long data;
|
||||
spin_lock(&gpio_lock);
|
||||
poll_wait(file, &priv->alarm_wq, wait);
|
||||
if (priv->minor == GPIO_MINOR_A) {
|
||||
unsigned long flags;
|
||||
|
@ -270,10 +289,10 @@ gpio_poll(struct file *file,
|
|||
*/
|
||||
tmp = ~data & priv->highalarm & 0xFF;
|
||||
tmp = (tmp << R_IRQ_MASK1_SET__pa0__BITNR);
|
||||
save_flags(flags); cli();
|
||||
local_irq_save(flags);
|
||||
gpio_pa_irq_enabled_mask |= tmp;
|
||||
*R_IRQ_MASK1_SET = tmp;
|
||||
restore_flags(flags);
|
||||
local_irq_restore(flags);
|
||||
|
||||
} else if (priv->minor == GPIO_MINOR_B)
|
||||
data = *R_PORT_PB_DATA;
|
||||
|
@ -286,8 +305,11 @@ gpio_poll(struct file *file,
|
|||
(~data & priv->lowalarm)) {
|
||||
mask = POLLIN|POLLRDNORM;
|
||||
}
|
||||
|
||||
spin_unlock(&gpio_lock);
|
||||
|
||||
DP(printk("gpio_poll ready: mask 0x%08X\n", mask));
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
|
@ -296,6 +318,7 @@ int etrax_gpio_wake_up_check(void)
|
|||
struct gpio_private *priv = alarmlist;
|
||||
unsigned long data = 0;
|
||||
int ret = 0;
|
||||
spin_lock(&gpio_lock);
|
||||
while (priv) {
|
||||
if (USE_PORTS(priv)) {
|
||||
data = *priv->port;
|
||||
|
@ -310,6 +333,7 @@ int etrax_gpio_wake_up_check(void)
|
|||
}
|
||||
priv = priv->next;
|
||||
}
|
||||
spin_unlock(&gpio_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -327,6 +351,7 @@ static irqreturn_t
|
|||
gpio_pa_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
unsigned long tmp;
|
||||
spin_lock(&gpio_lock);
|
||||
/* Find what PA interrupts are active */
|
||||
tmp = (*R_IRQ_READ1);
|
||||
|
||||
|
@ -337,6 +362,8 @@ gpio_pa_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
|||
*R_IRQ_MASK1_CLR = tmp;
|
||||
gpio_pa_irq_enabled_mask &= ~tmp;
|
||||
|
||||
spin_unlock(&gpio_lock);
|
||||
|
||||
if (gpio_some_alarms) {
|
||||
return IRQ_RETVAL(etrax_gpio_wake_up_check());
|
||||
}
|
||||
|
@ -350,6 +377,9 @@ static ssize_t gpio_write(struct file * file, const char * buf, size_t count,
|
|||
struct gpio_private *priv = (struct gpio_private *)file->private_data;
|
||||
unsigned char data, clk_mask, data_mask, write_msb;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock(&gpio_lock);
|
||||
|
||||
ssize_t retval = count;
|
||||
if (priv->minor !=GPIO_MINOR_A && priv->minor != GPIO_MINOR_B) {
|
||||
return -EFAULT;
|
||||
|
@ -372,7 +402,7 @@ static ssize_t gpio_write(struct file * file, const char * buf, size_t count,
|
|||
data = *buf++;
|
||||
if (priv->write_msb) {
|
||||
for (i = 7; i >= 0;i--) {
|
||||
local_irq_save(flags); local_irq_disable();
|
||||
local_irq_save(flags);
|
||||
*priv->port = *priv->shadow &= ~clk_mask;
|
||||
if (data & 1<<i)
|
||||
*priv->port = *priv->shadow |= data_mask;
|
||||
|
@ -384,7 +414,7 @@ static ssize_t gpio_write(struct file * file, const char * buf, size_t count,
|
|||
}
|
||||
} else {
|
||||
for (i = 0; i <= 7;i++) {
|
||||
local_irq_save(flags); local_irq_disable();
|
||||
local_irq_save(flags);
|
||||
*priv->port = *priv->shadow &= ~clk_mask;
|
||||
if (data & 1<<i)
|
||||
*priv->port = *priv->shadow |= data_mask;
|
||||
|
@ -396,6 +426,7 @@ static ssize_t gpio_write(struct file * file, const char * buf, size_t count,
|
|||
}
|
||||
}
|
||||
}
|
||||
spin_unlock(&gpio_lock);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -452,9 +483,14 @@ gpio_open(struct inode *inode, struct file *filp)
|
|||
static int
|
||||
gpio_release(struct inode *inode, struct file *filp)
|
||||
{
|
||||
struct gpio_private *p = alarmlist;
|
||||
struct gpio_private *todel = (struct gpio_private *)filp->private_data;
|
||||
|
||||
struct gpio_private *p;
|
||||
struct gpio_private *todel;
|
||||
|
||||
spin_lock(&gpio_lock);
|
||||
|
||||
p = alarmlist;
|
||||
todel = (struct gpio_private *)filp->private_data;
|
||||
|
||||
/* unlink from alarmlist and free the private structure */
|
||||
|
||||
if (p == todel) {
|
||||
|
@ -476,7 +512,7 @@ gpio_release(struct inode *inode, struct file *filp)
|
|||
p = p->next;
|
||||
}
|
||||
gpio_some_alarms = 0;
|
||||
|
||||
spin_unlock(&gpio_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -491,14 +527,14 @@ unsigned long inline setget_input(struct gpio_private *priv, unsigned long arg)
|
|||
*/
|
||||
unsigned long flags;
|
||||
if (USE_PORTS(priv)) {
|
||||
local_irq_save(flags); local_irq_disable();
|
||||
local_irq_save(flags);
|
||||
*priv->dir = *priv->dir_shadow &=
|
||||
~((unsigned char)arg & priv->changeable_dir);
|
||||
local_irq_restore(flags);
|
||||
return ~(*priv->dir_shadow) & 0xFF; /* Only 8 bits */
|
||||
} else if (priv->minor == GPIO_MINOR_G) {
|
||||
/* We must fiddle with R_GEN_CONFIG to change dir */
|
||||
save_flags(flags); cli();
|
||||
local_irq_save(flags);
|
||||
if (((arg & dir_g_in_bits) != arg) &&
|
||||
(arg & changeable_dir_g)) {
|
||||
arg &= changeable_dir_g;
|
||||
|
@ -533,7 +569,7 @@ unsigned long inline setget_input(struct gpio_private *priv, unsigned long arg)
|
|||
/* Must be a >120 ns delay before writing this again */
|
||||
|
||||
}
|
||||
restore_flags(flags);
|
||||
local_irq_restore(flags);
|
||||
return dir_g_in_bits;
|
||||
}
|
||||
return 0;
|
||||
|
@ -543,14 +579,14 @@ unsigned long inline setget_output(struct gpio_private *priv, unsigned long arg)
|
|||
{
|
||||
unsigned long flags;
|
||||
if (USE_PORTS(priv)) {
|
||||
local_irq_save(flags); local_irq_disable();
|
||||
local_irq_save(flags);
|
||||
*priv->dir = *priv->dir_shadow |=
|
||||
((unsigned char)arg & priv->changeable_dir);
|
||||
local_irq_restore(flags);
|
||||
return *priv->dir_shadow;
|
||||
} else if (priv->minor == GPIO_MINOR_G) {
|
||||
/* We must fiddle with R_GEN_CONFIG to change dir */
|
||||
save_flags(flags); cli();
|
||||
local_irq_save(flags);
|
||||
if (((arg & dir_g_out_bits) != arg) &&
|
||||
(arg & changeable_dir_g)) {
|
||||
/* Set bits in genconfig to set to output */
|
||||
|
@ -583,7 +619,7 @@ unsigned long inline setget_output(struct gpio_private *priv, unsigned long arg)
|
|||
*R_GEN_CONFIG = genconfig_shadow;
|
||||
/* Must be a >120 ns delay before writing this again */
|
||||
}
|
||||
restore_flags(flags);
|
||||
local_irq_restore(flags);
|
||||
return dir_g_out_bits & 0x7FFFFFFF;
|
||||
}
|
||||
return 0;
|
||||
|
@ -598,22 +634,26 @@ gpio_ioctl(struct inode *inode, struct file *file,
|
|||
{
|
||||
unsigned long flags;
|
||||
unsigned long val;
|
||||
int ret = 0;
|
||||
|
||||
struct gpio_private *priv = (struct gpio_private *)file->private_data;
|
||||
if (_IOC_TYPE(cmd) != ETRAXGPIO_IOCTYPE) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
spin_lock(&gpio_lock);
|
||||
|
||||
switch (_IOC_NR(cmd)) {
|
||||
case IO_READBITS: /* Use IO_READ_INBITS and IO_READ_OUTBITS instead */
|
||||
// read the port
|
||||
if (USE_PORTS(priv)) {
|
||||
return *priv->port;
|
||||
ret = *priv->port;
|
||||
} else if (priv->minor == GPIO_MINOR_G) {
|
||||
return (*R_PORT_G_DATA) & 0x7FFFFFFF;
|
||||
ret = (*R_PORT_G_DATA) & 0x7FFFFFFF;
|
||||
}
|
||||
break;
|
||||
case IO_SETBITS:
|
||||
local_irq_save(flags); local_irq_disable();
|
||||
local_irq_save(flags);
|
||||
// set changeable bits with a 1 in arg
|
||||
if (USE_PORTS(priv)) {
|
||||
*priv->port = *priv->shadow |=
|
||||
|
@ -624,7 +664,7 @@ gpio_ioctl(struct inode *inode, struct file *file,
|
|||
local_irq_restore(flags);
|
||||
break;
|
||||
case IO_CLRBITS:
|
||||
local_irq_save(flags); local_irq_disable();
|
||||
local_irq_save(flags);
|
||||
// clear changeable bits with a 1 in arg
|
||||
if (USE_PORTS(priv)) {
|
||||
*priv->port = *priv->shadow &=
|
||||
|
@ -666,33 +706,34 @@ gpio_ioctl(struct inode *inode, struct file *file,
|
|||
case IO_READDIR: /* Use IO_SETGET_INPUT/OUTPUT instead! */
|
||||
/* Read direction 0=input 1=output */
|
||||
if (USE_PORTS(priv)) {
|
||||
return *priv->dir_shadow;
|
||||
ret = *priv->dir_shadow;
|
||||
} else if (priv->minor == GPIO_MINOR_G) {
|
||||
/* Note: Some bits are both in and out,
|
||||
* Those that are dual is set here as well.
|
||||
*/
|
||||
return (dir_g_shadow | dir_g_out_bits) & 0x7FFFFFFF;
|
||||
ret = (dir_g_shadow | dir_g_out_bits) & 0x7FFFFFFF;
|
||||
}
|
||||
break;
|
||||
case IO_SETINPUT: /* Use IO_SETGET_INPUT instead! */
|
||||
/* Set direction 0=unchanged 1=input,
|
||||
* return mask with 1=input
|
||||
*/
|
||||
return setget_input(priv, arg) & 0x7FFFFFFF;
|
||||
ret = setget_input(priv, arg) & 0x7FFFFFFF;
|
||||
break;
|
||||
case IO_SETOUTPUT: /* Use IO_SETGET_OUTPUT instead! */
|
||||
/* Set direction 0=unchanged 1=output,
|
||||
* return mask with 1=output
|
||||
*/
|
||||
return setget_output(priv, arg) & 0x7FFFFFFF;
|
||||
|
||||
ret = setget_output(priv, arg) & 0x7FFFFFFF;
|
||||
break;
|
||||
case IO_SHUTDOWN:
|
||||
SOFT_SHUTDOWN();
|
||||
break;
|
||||
case IO_GET_PWR_BT:
|
||||
#if defined (CONFIG_ETRAX_SOFT_SHUTDOWN)
|
||||
return (*R_PORT_G_DATA & ( 1 << CONFIG_ETRAX_POWERBUTTON_BIT));
|
||||
ret = (*R_PORT_G_DATA & ( 1 << CONFIG_ETRAX_POWERBUTTON_BIT));
|
||||
#else
|
||||
return 0;
|
||||
ret = 0;
|
||||
#endif
|
||||
break;
|
||||
case IO_CFG_WRITE_MODE:
|
||||
|
@ -709,7 +750,7 @@ gpio_ioctl(struct inode *inode, struct file *file,
|
|||
{
|
||||
priv->clk_mask = 0;
|
||||
priv->data_mask = 0;
|
||||
return -EPERM;
|
||||
ret = -EPERM;
|
||||
}
|
||||
break;
|
||||
case IO_READ_INBITS:
|
||||
|
@ -720,8 +761,7 @@ gpio_ioctl(struct inode *inode, struct file *file,
|
|||
val = *R_PORT_G_DATA;
|
||||
}
|
||||
if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
ret = -EFAULT;
|
||||
break;
|
||||
case IO_READ_OUTBITS:
|
||||
/* *arg is result of reading the output shadow */
|
||||
|
@ -731,36 +771,43 @@ gpio_ioctl(struct inode *inode, struct file *file,
|
|||
val = port_g_data_shadow;
|
||||
}
|
||||
if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
|
||||
return -EFAULT;
|
||||
ret = -EFAULT;
|
||||
break;
|
||||
case IO_SETGET_INPUT:
|
||||
/* bits set in *arg is set to input,
|
||||
* *arg updated with current input pins.
|
||||
*/
|
||||
if (copy_from_user(&val, (unsigned long*)arg, sizeof(val)))
|
||||
return -EFAULT;
|
||||
{
|
||||
ret = -EFAULT;
|
||||
break;
|
||||
}
|
||||
val = setget_input(priv, val);
|
||||
if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
|
||||
return -EFAULT;
|
||||
ret = -EFAULT;
|
||||
break;
|
||||
case IO_SETGET_OUTPUT:
|
||||
/* bits set in *arg is set to output,
|
||||
* *arg updated with current output pins.
|
||||
*/
|
||||
if (copy_from_user(&val, (unsigned long*)arg, sizeof(val)))
|
||||
return -EFAULT;
|
||||
{
|
||||
ret = -EFAULT;
|
||||
break;
|
||||
}
|
||||
val = setget_output(priv, val);
|
||||
if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
|
||||
return -EFAULT;
|
||||
ret = -EFAULT;
|
||||
break;
|
||||
default:
|
||||
if (priv->minor == GPIO_MINOR_LEDS)
|
||||
return gpio_leds_ioctl(cmd, arg);
|
||||
ret = gpio_leds_ioctl(cmd, arg);
|
||||
else
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
} /* switch */
|
||||
|
||||
return 0;
|
||||
|
||||
spin_unlock(&gpio_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -802,60 +849,20 @@ struct file_operations gpio_fops = {
|
|||
};
|
||||
|
||||
|
||||
static void __init gpio_init_port_g(void)
|
||||
void ioif_watcher(const unsigned int gpio_in_available,
|
||||
const unsigned int gpio_out_available,
|
||||
const unsigned char pa_available,
|
||||
const unsigned char pb_available)
|
||||
{
|
||||
#define GROUPA (0x0000FF3F)
|
||||
#define GROUPB (1<<6 | 1<<7)
|
||||
#define GROUPC (1<<30 | 1<<31)
|
||||
#define GROUPD (0x3FFF0000)
|
||||
#define GROUPD_LOW (0x00FF0000)
|
||||
unsigned long used_in_bits = 0;
|
||||
unsigned long used_out_bits = 0;
|
||||
if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, scsi0, select)){
|
||||
used_in_bits |= GROUPA | GROUPB | 0 | 0;
|
||||
used_out_bits |= GROUPA | GROUPB | 0 | 0;
|
||||
}
|
||||
if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, ata, select)) {
|
||||
used_in_bits |= GROUPA | GROUPB | GROUPC | (GROUPD & ~(1<<25|1<<26));
|
||||
used_out_bits |= GROUPA | GROUPB | GROUPC | GROUPD;
|
||||
}
|
||||
unsigned long int flags;
|
||||
D(printk("gpio.c: ioif_watcher called\n"));
|
||||
D(printk("gpio.c: G in: 0x%08x G out: 0x%08x PA: 0x%02x PB: 0x%02x\n",
|
||||
gpio_in_available, gpio_out_available, pa_available, pb_available));
|
||||
|
||||
if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, par0, select)) {
|
||||
used_in_bits |= (GROUPA & ~(1<<0)) | 0 | 0 | 0;
|
||||
used_out_bits |= (GROUPA & ~(1<<0)) | 0 | 0 | 0;
|
||||
}
|
||||
if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, ser2, select)) {
|
||||
used_in_bits |= 0 | GROUPB | 0 | 0;
|
||||
used_out_bits |= 0 | GROUPB | 0 | 0;
|
||||
}
|
||||
/* mio same as shared RAM ? */
|
||||
if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, mio, select)) {
|
||||
used_in_bits |= (GROUPA & ~(1<<0)) | 0 |0 |GROUPD_LOW;
|
||||
used_out_bits |= (GROUPA & ~(1<<0|1<<1|1<<2)) | 0 |0 |GROUPD_LOW;
|
||||
}
|
||||
if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, scsi1, select)) {
|
||||
used_in_bits |= 0 | 0 | GROUPC | GROUPD;
|
||||
used_out_bits |= 0 | 0 | GROUPC | GROUPD;
|
||||
}
|
||||
if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, scsi0w, select)) {
|
||||
used_in_bits |= GROUPA | GROUPB | 0 | (GROUPD_LOW | 1<<24);
|
||||
used_out_bits |= GROUPA | GROUPB | 0 | (GROUPD_LOW | 1<<24 | 1<<25|1<<26);
|
||||
}
|
||||
spin_lock_irqsave(&gpio_lock, flags);
|
||||
|
||||
if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, par1, select)) {
|
||||
used_in_bits |= 0 | 0 | 0 | (GROUPD & ~(1<<24));
|
||||
used_out_bits |= 0 | 0 | 0 | (GROUPD & ~(1<<24));
|
||||
}
|
||||
if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, ser3, select)) {
|
||||
used_in_bits |= 0 | 0 | GROUPC | 0;
|
||||
used_out_bits |= 0 | 0 | GROUPC | 0;
|
||||
}
|
||||
/* mio same as shared RAM-W? */
|
||||
if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, mio_w, select)) {
|
||||
used_in_bits |= (GROUPA & ~(1<<0)) | 0 | 0 |GROUPD_LOW;
|
||||
used_out_bits |= (GROUPA & ~(1<<0|1<<1|1<<2)) | 0 | 0 |GROUPD_LOW;
|
||||
}
|
||||
/* TODO: USB p2, parw, sync ser3? */
|
||||
dir_g_in_bits = gpio_in_available;
|
||||
dir_g_out_bits = gpio_out_available;
|
||||
|
||||
/* Initialise the dir_g_shadow etc. depending on genconfig */
|
||||
/* 0=input 1=output */
|
||||
|
@ -868,10 +875,7 @@ static void __init gpio_init_port_g(void)
|
|||
if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, g24dir, out))
|
||||
dir_g_shadow |= (1 << 24);
|
||||
|
||||
dir_g_in_bits = ~used_in_bits;
|
||||
dir_g_out_bits = ~used_out_bits;
|
||||
|
||||
changeable_dir_g = 0x01FFFF01; /* all that can change dir */
|
||||
changeable_dir_g = changeable_dir_g_mask;
|
||||
changeable_dir_g &= dir_g_out_bits;
|
||||
changeable_dir_g &= dir_g_in_bits;
|
||||
/* Correct the bits that can change direction */
|
||||
|
@ -880,6 +884,7 @@ static void __init gpio_init_port_g(void)
|
|||
dir_g_in_bits &= ~changeable_dir_g;
|
||||
dir_g_in_bits |= (~dir_g_shadow & changeable_dir_g);
|
||||
|
||||
spin_unlock_irqrestore(&gpio_lock, flags);
|
||||
|
||||
printk(KERN_INFO "GPIO port G: in_bits: 0x%08lX out_bits: 0x%08lX val: %08lX\n",
|
||||
dir_g_in_bits, dir_g_out_bits, (unsigned long)*R_PORT_G_DATA);
|
||||
|
@ -896,6 +901,7 @@ gpio_init(void)
|
|||
#if defined (CONFIG_ETRAX_CSP0_LEDS)
|
||||
int i;
|
||||
#endif
|
||||
printk("gpio init\n");
|
||||
|
||||
/* do the formalities */
|
||||
|
||||
|
@ -919,8 +925,13 @@ gpio_init(void)
|
|||
#endif
|
||||
|
||||
#endif
|
||||
gpio_init_port_g();
|
||||
printk(KERN_INFO "ETRAX 100LX GPIO driver v2.5, (c) 2001, 2002 Axis Communications AB\n");
|
||||
/* The I/O interface allocation watcher will be called when
|
||||
* registering it. */
|
||||
if (cris_io_interface_register_watcher(ioif_watcher)){
|
||||
printk(KERN_WARNING "gpio_init: Failed to install IO if allocator watcher\n");
|
||||
}
|
||||
|
||||
printk(KERN_INFO "ETRAX 100LX GPIO driver v2.5, (c) 2001, 2002, 2003, 2004 Axis Communications AB\n");
|
||||
/* We call etrax_gpio_wake_up_check() from timer interrupt and
|
||||
* from cpu_idle() in kernel/process.c
|
||||
* The check in cpu_idle() reduces latency from ~15 ms to ~6 ms
|
||||
|
|
|
@ -12,6 +12,15 @@
|
|||
*! don't use PB_I2C if DS1302 uses same bits,
|
||||
*! use PB.
|
||||
*! $Log: i2c.c,v $
|
||||
*! Revision 1.13 2005/03/07 13:13:07 starvik
|
||||
*! Added spinlocks to protect states etc
|
||||
*!
|
||||
*! Revision 1.12 2005/01/05 06:11:22 starvik
|
||||
*! No need to do local_irq_disable after local_irq_save.
|
||||
*!
|
||||
*! Revision 1.11 2004/12/13 12:21:52 starvik
|
||||
*! Added I/O and DMA allocators from Linux 2.4
|
||||
*!
|
||||
*! Revision 1.9 2004/08/24 06:49:14 starvik
|
||||
*! Whitespace cleanup
|
||||
*!
|
||||
|
@ -75,7 +84,7 @@
|
|||
*! (C) Copyright 1999-2002 Axis Communications AB, LUND, SWEDEN
|
||||
*!
|
||||
*!***************************************************************************/
|
||||
/* $Id: i2c.c,v 1.9 2004/08/24 06:49:14 starvik Exp $ */
|
||||
/* $Id: i2c.c,v 1.13 2005/03/07 13:13:07 starvik Exp $ */
|
||||
|
||||
/****************** INCLUDE FILES SECTION ***********************************/
|
||||
|
||||
|
@ -95,6 +104,7 @@
|
|||
#include <asm/arch/svinto.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/delay.h>
|
||||
#include <asm/arch/io_interface_mux.h>
|
||||
|
||||
#include "i2c.h"
|
||||
|
||||
|
@ -184,6 +194,7 @@ static const char i2c_name[] = "i2c";
|
|||
|
||||
#define i2c_delay(usecs) udelay(usecs)
|
||||
|
||||
static DEFINE_SPINLOCK(i2c_lock); /* Protect directions etc */
|
||||
|
||||
/****************** FUNCTION DEFINITION SECTION *************************/
|
||||
|
||||
|
@ -488,13 +499,14 @@ i2c_writereg(unsigned char theSlave, unsigned char theReg,
|
|||
int error, cntr = 3;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock(&i2c_lock);
|
||||
|
||||
do {
|
||||
error = 0;
|
||||
/*
|
||||
* we don't like to be interrupted
|
||||
*/
|
||||
local_irq_save(flags);
|
||||
local_irq_disable();
|
||||
|
||||
i2c_start();
|
||||
/*
|
||||
|
@ -538,6 +550,8 @@ i2c_writereg(unsigned char theSlave, unsigned char theReg,
|
|||
|
||||
i2c_delay(CLOCK_LOW_TIME);
|
||||
|
||||
spin_unlock(&i2c_lock);
|
||||
|
||||
return -error;
|
||||
}
|
||||
|
||||
|
@ -555,13 +569,14 @@ i2c_readreg(unsigned char theSlave, unsigned char theReg)
|
|||
int error, cntr = 3;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock(&i2c_lock);
|
||||
|
||||
do {
|
||||
error = 0;
|
||||
/*
|
||||
* we don't like to be interrupted
|
||||
*/
|
||||
local_irq_save(flags);
|
||||
local_irq_disable();
|
||||
/*
|
||||
* generate start condition
|
||||
*/
|
||||
|
@ -620,6 +635,8 @@ i2c_readreg(unsigned char theSlave, unsigned char theReg)
|
|||
|
||||
} while(error && cntr--);
|
||||
|
||||
spin_unlock(&i2c_lock);
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
|
@ -686,15 +703,26 @@ static struct file_operations i2c_fops = {
|
|||
int __init
|
||||
i2c_init(void)
|
||||
{
|
||||
static int res = 0;
|
||||
static int first = 1;
|
||||
|
||||
if (!first) {
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Setup and enable the Port B I2C interface */
|
||||
|
||||
#ifndef CONFIG_ETRAX_I2C_USES_PB_NOT_PB_I2C
|
||||
if ((res = cris_request_io_interface(if_i2c, "I2C"))) {
|
||||
printk(KERN_CRIT "i2c_init: Failed to get IO interface\n");
|
||||
return res;
|
||||
}
|
||||
|
||||
*R_PORT_PB_I2C = port_pb_i2c_shadow |=
|
||||
IO_STATE(R_PORT_PB_I2C, i2c_en, on) |
|
||||
IO_FIELD(R_PORT_PB_I2C, i2c_d, 1) |
|
||||
IO_FIELD(R_PORT_PB_I2C, i2c_clk, 1) |
|
||||
IO_STATE(R_PORT_PB_I2C, i2c_oe_, enable);
|
||||
#endif
|
||||
|
||||
port_pb_dir_shadow &= ~IO_MASK(R_PORT_PB_DIR, dir0);
|
||||
port_pb_dir_shadow &= ~IO_MASK(R_PORT_PB_DIR, dir1);
|
||||
|
@ -702,8 +730,26 @@ i2c_init(void)
|
|||
*R_PORT_PB_DIR = (port_pb_dir_shadow |=
|
||||
IO_STATE(R_PORT_PB_DIR, dir0, input) |
|
||||
IO_STATE(R_PORT_PB_DIR, dir1, output));
|
||||
#else
|
||||
if ((res = cris_io_interface_allocate_pins(if_i2c,
|
||||
'b',
|
||||
CONFIG_ETRAX_I2C_DATA_PORT,
|
||||
CONFIG_ETRAX_I2C_DATA_PORT))) {
|
||||
printk(KERN_WARNING "i2c_init: Failed to get IO pin for I2C data port\n");
|
||||
return res;
|
||||
} else if ((res = cris_io_interface_allocate_pins(if_i2c,
|
||||
'b',
|
||||
CONFIG_ETRAX_I2C_CLK_PORT,
|
||||
CONFIG_ETRAX_I2C_CLK_PORT))) {
|
||||
cris_io_interface_free_pins(if_i2c,
|
||||
'b',
|
||||
CONFIG_ETRAX_I2C_DATA_PORT,
|
||||
CONFIG_ETRAX_I2C_DATA_PORT);
|
||||
printk(KERN_WARNING "i2c_init: Failed to get IO pin for I2C clk port\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
static int __init
|
||||
|
@ -711,14 +757,16 @@ i2c_register(void)
|
|||
{
|
||||
int res;
|
||||
|
||||
i2c_init();
|
||||
res = i2c_init();
|
||||
if (res < 0)
|
||||
return res;
|
||||
res = register_chrdev(I2C_MAJOR, i2c_name, &i2c_fops);
|
||||
if(res < 0) {
|
||||
printk(KERN_ERR "i2c: couldn't get a major number.\n");
|
||||
return res;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "I2C driver v2.2, (c) 1999-2001 Axis Communications AB\n");
|
||||
printk(KERN_INFO "I2C driver v2.2, (c) 1999-2004 Axis Communications AB\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
*
|
||||
* Author: Tobias Anderberg <tobiasa@axis.com>.
|
||||
*
|
||||
* $Id: pcf8563.c,v 1.8 2004/08/24 06:42:51 starvik Exp $
|
||||
* $Id: pcf8563.c,v 1.11 2005/03/07 13:13:07 starvik Exp $
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
|
@ -40,7 +40,7 @@
|
|||
#define PCF8563_MAJOR 121 /* Local major number. */
|
||||
#define DEVICE_NAME "rtc" /* Name which is registered in /proc/devices. */
|
||||
#define PCF8563_NAME "PCF8563"
|
||||
#define DRIVER_VERSION "$Revision: 1.8 $"
|
||||
#define DRIVER_VERSION "$Revision: 1.11 $"
|
||||
|
||||
/* I2C bus slave registers. */
|
||||
#define RTC_I2C_READ 0xa3
|
||||
|
@ -49,6 +49,8 @@
|
|||
/* Two simple wrapper macros, saves a few keystrokes. */
|
||||
#define rtc_read(x) i2c_readreg(RTC_I2C_READ, x)
|
||||
#define rtc_write(x,y) i2c_writereg(RTC_I2C_WRITE, x, y)
|
||||
|
||||
static DEFINE_SPINLOCK(rtc_lock); /* Protect state etc */
|
||||
|
||||
static const unsigned char days_in_month[] =
|
||||
{ 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||
|
@ -125,9 +127,12 @@ get_rtc_time(struct rtc_time *tm)
|
|||
int __init
|
||||
pcf8563_init(void)
|
||||
{
|
||||
unsigned char ret;
|
||||
int ret;
|
||||
|
||||
i2c_init();
|
||||
if ((ret = i2c_init())) {
|
||||
printk(KERN_CRIT "pcf8563_init: failed to init i2c\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* First of all we need to reset the chip. This is done by
|
||||
|
@ -200,12 +205,15 @@ pcf8563_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned
|
|||
{
|
||||
struct rtc_time tm;
|
||||
|
||||
spin_lock(&rtc_lock);
|
||||
get_rtc_time(&tm);
|
||||
|
||||
if (copy_to_user((struct rtc_time *) arg, &tm, sizeof(struct rtc_time))) {
|
||||
spin_unlock(&rtc_lock);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
spin_unlock(&rtc_lock);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
@ -250,6 +258,8 @@ pcf8563_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned
|
|||
BIN_TO_BCD(tm.tm_min);
|
||||
BIN_TO_BCD(tm.tm_sec);
|
||||
tm.tm_mon |= century;
|
||||
|
||||
spin_lock(&rtc_lock);
|
||||
|
||||
rtc_write(RTC_YEAR, tm.tm_year);
|
||||
rtc_write(RTC_MONTH, tm.tm_mon);
|
||||
|
@ -258,6 +268,8 @@ pcf8563_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned
|
|||
rtc_write(RTC_MINUTES, tm.tm_min);
|
||||
rtc_write(RTC_SECONDS, tm.tm_sec);
|
||||
|
||||
spin_unlock(&rtc_lock);
|
||||
|
||||
return 0;
|
||||
#endif /* !CONFIG_ETRAX_RTC_READONLY */
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $Id: Makefile,v 1.5 2004/06/02 08:24:38 starvik Exp $
|
||||
# $Id: Makefile,v 1.6 2004/12/13 12:21:51 starvik Exp $
|
||||
#
|
||||
# Makefile for the linux kernel.
|
||||
#
|
||||
|
@ -7,7 +7,8 @@ extra-y := head.o
|
|||
|
||||
|
||||
obj-y := entry.o traps.o shadows.o debugport.o irq.o \
|
||||
process.o setup.o signal.o traps.o time.o ptrace.o
|
||||
process.o setup.o signal.o traps.o time.o ptrace.o \
|
||||
dma.o io_interface_mux.o
|
||||
|
||||
obj-$(CONFIG_ETRAX_KGDB) += kgdb.o
|
||||
obj-$(CONFIG_ETRAX_FAST_TIMER) += fasttimer.o
|
||||
|
|
|
@ -12,6 +12,31 @@
|
|||
* init_etrax_debug()
|
||||
*
|
||||
* $Log: debugport.c,v $
|
||||
* Revision 1.27 2005/06/10 10:34:14 starvik
|
||||
* Real console support
|
||||
*
|
||||
* Revision 1.26 2005/06/07 07:06:07 starvik
|
||||
* Added LF->CR translation to make ETRAX customers happy.
|
||||
*
|
||||
* Revision 1.25 2005/03/08 08:56:47 mikaelam
|
||||
* Do only set index as port->index if port is defined, otherwise use the index from the command line
|
||||
*
|
||||
* Revision 1.24 2005/01/19 10:26:33 mikaelam
|
||||
* Return the cris serial driver in console device driver callback function
|
||||
*
|
||||
* Revision 1.23 2005/01/14 10:12:17 starvik
|
||||
* KGDB on separate port.
|
||||
* Console fixes from 2.4.
|
||||
*
|
||||
* Revision 1.22 2005/01/11 16:06:13 starvik
|
||||
* typo
|
||||
*
|
||||
* Revision 1.21 2005/01/11 13:49:14 starvik
|
||||
* Added raw_printk to be used where we don't trust the console.
|
||||
*
|
||||
* Revision 1.20 2004/12/27 11:18:32 starvik
|
||||
* Merge of Linux 2.6.10 (not functional yet).
|
||||
*
|
||||
* Revision 1.19 2004/10/21 07:26:16 starvik
|
||||
* Made it possible to specify console settings on kernel command line.
|
||||
*
|
||||
|
@ -114,7 +139,11 @@ struct dbg_port ports[]=
|
|||
R_SERIAL0_BAUD,
|
||||
R_SERIAL0_TR_CTRL,
|
||||
R_SERIAL0_REC_CTRL,
|
||||
IO_STATE(R_IRQ_MASK1_SET, ser0_data, set)
|
||||
IO_STATE(R_IRQ_MASK1_SET, ser0_data, set),
|
||||
0,
|
||||
115200,
|
||||
'N',
|
||||
8
|
||||
},
|
||||
{
|
||||
1,
|
||||
|
@ -124,7 +153,11 @@ struct dbg_port ports[]=
|
|||
R_SERIAL1_BAUD,
|
||||
R_SERIAL1_TR_CTRL,
|
||||
R_SERIAL1_REC_CTRL,
|
||||
IO_STATE(R_IRQ_MASK1_SET, ser1_data, set)
|
||||
IO_STATE(R_IRQ_MASK1_SET, ser1_data, set),
|
||||
0,
|
||||
115200,
|
||||
'N',
|
||||
8
|
||||
},
|
||||
{
|
||||
2,
|
||||
|
@ -134,7 +167,11 @@ struct dbg_port ports[]=
|
|||
R_SERIAL2_BAUD,
|
||||
R_SERIAL2_TR_CTRL,
|
||||
R_SERIAL2_REC_CTRL,
|
||||
IO_STATE(R_IRQ_MASK1_SET, ser2_data, set)
|
||||
IO_STATE(R_IRQ_MASK1_SET, ser2_data, set),
|
||||
0,
|
||||
115200,
|
||||
'N',
|
||||
8
|
||||
},
|
||||
{
|
||||
3,
|
||||
|
@ -144,11 +181,15 @@ struct dbg_port ports[]=
|
|||
R_SERIAL3_BAUD,
|
||||
R_SERIAL3_TR_CTRL,
|
||||
R_SERIAL3_REC_CTRL,
|
||||
IO_STATE(R_IRQ_MASK1_SET, ser3_data, set)
|
||||
IO_STATE(R_IRQ_MASK1_SET, ser3_data, set),
|
||||
0,
|
||||
115200,
|
||||
'N',
|
||||
8
|
||||
}
|
||||
};
|
||||
|
||||
static struct tty_driver *serial_driver;
|
||||
extern struct tty_driver *serial_driver;
|
||||
|
||||
struct dbg_port* port =
|
||||
#if defined(CONFIG_ETRAX_DEBUG_PORT0)
|
||||
|
@ -162,37 +203,44 @@ struct dbg_port* port =
|
|||
#else
|
||||
NULL;
|
||||
#endif
|
||||
/* Used by serial.c to register a debug_write_function so that the normal
|
||||
* serial driver is used for kernel debug output
|
||||
*/
|
||||
typedef int (*debugport_write_function)(int i, const char *buf, unsigned int len);
|
||||
|
||||
debugport_write_function debug_write_function = NULL;
|
||||
static struct dbg_port* kgdb_port =
|
||||
#if defined(CONFIG_ETRAX_KGDB_PORT0)
|
||||
&ports[0];
|
||||
#elif defined(CONFIG_ETRAX_KGDB_PORT1)
|
||||
&ports[1];
|
||||
#elif defined(CONFIG_ETRAX_KGDB_PORT2)
|
||||
&ports[2];
|
||||
#elif defined(CONFIG_ETRAX_KGDB_PORT3)
|
||||
&ports[3];
|
||||
#else
|
||||
NULL;
|
||||
#endif
|
||||
|
||||
static void
|
||||
start_port(void)
|
||||
start_port(struct dbg_port* p)
|
||||
{
|
||||
unsigned long rec_ctrl = 0;
|
||||
unsigned long tr_ctrl = 0;
|
||||
|
||||
if (!port)
|
||||
if (!p)
|
||||
return;
|
||||
|
||||
if (port->started)
|
||||
if (p->started)
|
||||
return;
|
||||
port->started = 1;
|
||||
p->started = 1;
|
||||
|
||||
if (port->index == 0)
|
||||
if (p->index == 0)
|
||||
{
|
||||
genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma6);
|
||||
genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma6, unused);
|
||||
}
|
||||
else if (port->index == 1)
|
||||
else if (p->index == 1)
|
||||
{
|
||||
genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma8);
|
||||
genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma8, usb);
|
||||
}
|
||||
else if (port->index == 2)
|
||||
else if (p->index == 2)
|
||||
{
|
||||
genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma2);
|
||||
genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma2, par0);
|
||||
|
@ -211,69 +259,69 @@ start_port(void)
|
|||
|
||||
*R_GEN_CONFIG = genconfig_shadow;
|
||||
|
||||
*port->xoff =
|
||||
*p->xoff =
|
||||
IO_STATE(R_SERIAL0_XOFF, tx_stop, enable) |
|
||||
IO_STATE(R_SERIAL0_XOFF, auto_xoff, disable) |
|
||||
IO_FIELD(R_SERIAL0_XOFF, xoff_char, 0);
|
||||
|
||||
switch (port->baudrate)
|
||||
switch (p->baudrate)
|
||||
{
|
||||
case 0:
|
||||
case 115200:
|
||||
*port->baud =
|
||||
*p->baud =
|
||||
IO_STATE(R_SERIAL0_BAUD, tr_baud, c115k2Hz) |
|
||||
IO_STATE(R_SERIAL0_BAUD, rec_baud, c115k2Hz);
|
||||
break;
|
||||
case 1200:
|
||||
*port->baud =
|
||||
*p->baud =
|
||||
IO_STATE(R_SERIAL0_BAUD, tr_baud, c1200Hz) |
|
||||
IO_STATE(R_SERIAL0_BAUD, rec_baud, c1200Hz);
|
||||
break;
|
||||
case 2400:
|
||||
*port->baud =
|
||||
*p->baud =
|
||||
IO_STATE(R_SERIAL0_BAUD, tr_baud, c2400Hz) |
|
||||
IO_STATE(R_SERIAL0_BAUD, rec_baud, c2400Hz);
|
||||
break;
|
||||
case 4800:
|
||||
*port->baud =
|
||||
*p->baud =
|
||||
IO_STATE(R_SERIAL0_BAUD, tr_baud, c4800Hz) |
|
||||
IO_STATE(R_SERIAL0_BAUD, rec_baud, c4800Hz);
|
||||
break;
|
||||
case 9600:
|
||||
*port->baud =
|
||||
*p->baud =
|
||||
IO_STATE(R_SERIAL0_BAUD, tr_baud, c9600Hz) |
|
||||
IO_STATE(R_SERIAL0_BAUD, rec_baud, c9600Hz);
|
||||
break;
|
||||
case 19200:
|
||||
*port->baud =
|
||||
*p->baud =
|
||||
IO_STATE(R_SERIAL0_BAUD, tr_baud, c19k2Hz) |
|
||||
IO_STATE(R_SERIAL0_BAUD, rec_baud, c19k2Hz);
|
||||
break;
|
||||
case 38400:
|
||||
*port->baud =
|
||||
*p->baud =
|
||||
IO_STATE(R_SERIAL0_BAUD, tr_baud, c38k4Hz) |
|
||||
IO_STATE(R_SERIAL0_BAUD, rec_baud, c38k4Hz);
|
||||
break;
|
||||
case 57600:
|
||||
*port->baud =
|
||||
*p->baud =
|
||||
IO_STATE(R_SERIAL0_BAUD, tr_baud, c57k6Hz) |
|
||||
IO_STATE(R_SERIAL0_BAUD, rec_baud, c57k6Hz);
|
||||
break;
|
||||
default:
|
||||
*port->baud =
|
||||
*p->baud =
|
||||
IO_STATE(R_SERIAL0_BAUD, tr_baud, c115k2Hz) |
|
||||
IO_STATE(R_SERIAL0_BAUD, rec_baud, c115k2Hz);
|
||||
break;
|
||||
}
|
||||
|
||||
if (port->parity == 'E') {
|
||||
if (p->parity == 'E') {
|
||||
rec_ctrl =
|
||||
IO_STATE(R_SERIAL0_REC_CTRL, rec_par, even) |
|
||||
IO_STATE(R_SERIAL0_REC_CTRL, rec_par_en, enable);
|
||||
tr_ctrl =
|
||||
IO_STATE(R_SERIAL0_TR_CTRL, tr_par, even) |
|
||||
IO_STATE(R_SERIAL0_TR_CTRL, tr_par_en, enable);
|
||||
} else if (port->parity == 'O') {
|
||||
} else if (p->parity == 'O') {
|
||||
rec_ctrl =
|
||||
IO_STATE(R_SERIAL0_REC_CTRL, rec_par, odd) |
|
||||
IO_STATE(R_SERIAL0_REC_CTRL, rec_par_en, enable);
|
||||
|
@ -288,8 +336,7 @@ start_port(void)
|
|||
IO_STATE(R_SERIAL0_TR_CTRL, tr_par, even) |
|
||||
IO_STATE(R_SERIAL0_TR_CTRL, tr_par_en, disable);
|
||||
}
|
||||
|
||||
if (port->bits == 7)
|
||||
if (p->bits == 7)
|
||||
{
|
||||
rec_ctrl |= IO_STATE(R_SERIAL0_REC_CTRL, rec_bitnr, rec_7bit);
|
||||
tr_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, tr_bitnr, tr_7bit);
|
||||
|
@ -300,7 +347,7 @@ start_port(void)
|
|||
tr_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, tr_bitnr, tr_8bit);
|
||||
}
|
||||
|
||||
*port->rec_ctrl =
|
||||
*p->rec_ctrl =
|
||||
IO_STATE(R_SERIAL0_REC_CTRL, dma_err, stop) |
|
||||
IO_STATE(R_SERIAL0_REC_CTRL, rec_enable, enable) |
|
||||
IO_STATE(R_SERIAL0_REC_CTRL, rts_, active) |
|
||||
|
@ -308,7 +355,7 @@ start_port(void)
|
|||
IO_STATE(R_SERIAL0_REC_CTRL, rec_stick_par, normal) |
|
||||
rec_ctrl;
|
||||
|
||||
*port->tr_ctrl =
|
||||
*p->tr_ctrl =
|
||||
IO_FIELD(R_SERIAL0_TR_CTRL, txd, 0) |
|
||||
IO_STATE(R_SERIAL0_TR_CTRL, tr_enable, enable) |
|
||||
IO_STATE(R_SERIAL0_TR_CTRL, auto_cts, disabled) |
|
||||
|
@ -323,8 +370,18 @@ console_write_direct(struct console *co, const char *buf, unsigned int len)
|
|||
int i;
|
||||
unsigned long flags;
|
||||
local_irq_save(flags);
|
||||
|
||||
if (!port)
|
||||
return;
|
||||
|
||||
/* Send data */
|
||||
for (i = 0; i < len; i++) {
|
||||
/* LF -> CRLF */
|
||||
if (buf[i] == '\n') {
|
||||
while (!(*port->read & IO_MASK(R_SERIAL0_READ, tr_ready)))
|
||||
;
|
||||
*port->write = '\r';
|
||||
}
|
||||
/* Wait until transmitter is ready and send.*/
|
||||
while (!(*port->read & IO_MASK(R_SERIAL0_READ, tr_ready)))
|
||||
;
|
||||
|
@ -333,6 +390,25 @@ console_write_direct(struct console *co, const char *buf, unsigned int len)
|
|||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
int raw_printk(const char *fmt, ...)
|
||||
{
|
||||
static char buf[1024];
|
||||
int printed_len;
|
||||
static int first = 1;
|
||||
if (first) {
|
||||
/* Force reinitialization of the port to get manual mode. */
|
||||
port->started = 0;
|
||||
start_port(port);
|
||||
first = 0;
|
||||
}
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
printed_len = vsnprintf(buf, sizeof(buf), fmt, args);
|
||||
va_end(args);
|
||||
console_write_direct(NULL, buf, strlen(buf));
|
||||
return printed_len;
|
||||
}
|
||||
|
||||
static void
|
||||
console_write(struct console *co, const char *buf, unsigned int len)
|
||||
{
|
||||
|
@ -345,18 +421,7 @@ console_write(struct console *co, const char *buf, unsigned int len)
|
|||
return;
|
||||
#endif
|
||||
|
||||
start_port();
|
||||
|
||||
#ifdef CONFIG_ETRAX_KGDB
|
||||
/* kgdb needs to output debug info using the gdb protocol */
|
||||
putDebugString(buf, len);
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (debug_write_function)
|
||||
debug_write_function(co->index, buf, len);
|
||||
else
|
||||
console_write_direct(co, buf, len);
|
||||
console_write_direct(co, buf, len);
|
||||
}
|
||||
|
||||
/* legacy function */
|
||||
|
@ -374,8 +439,11 @@ getDebugChar(void)
|
|||
{
|
||||
unsigned long readval;
|
||||
|
||||
if (!kgdb_port)
|
||||
return 0;
|
||||
|
||||
do {
|
||||
readval = *port->read;
|
||||
readval = *kgdb_port->read;
|
||||
} while (!(readval & IO_MASK(R_SERIAL0_READ, data_avail)));
|
||||
|
||||
return (readval & IO_MASK(R_SERIAL0_READ, data_in));
|
||||
|
@ -386,9 +454,12 @@ getDebugChar(void)
|
|||
void
|
||||
putDebugChar(int val)
|
||||
{
|
||||
while (!(*port->read & IO_MASK(R_SERIAL0_READ, tr_ready)))
|
||||
if (!kgdb_port)
|
||||
return;
|
||||
|
||||
while (!(*kgdb_port->read & IO_MASK(R_SERIAL0_READ, tr_ready)))
|
||||
;
|
||||
*port->write = val;
|
||||
*kgdb_port->write = val;
|
||||
}
|
||||
|
||||
/* Enable irq for receiving chars on the debug port, used by kgdb */
|
||||
|
@ -396,19 +467,16 @@ putDebugChar(int val)
|
|||
void
|
||||
enableDebugIRQ(void)
|
||||
{
|
||||
*R_IRQ_MASK1_SET = port->irq;
|
||||
if (!kgdb_port)
|
||||
return;
|
||||
|
||||
*R_IRQ_MASK1_SET = kgdb_port->irq;
|
||||
/* use R_VECT_MASK directly, since we really bypass Linux normal
|
||||
* IRQ handling in kgdb anyway, we don't need to use enable_irq
|
||||
*/
|
||||
*R_VECT_MASK_SET = IO_STATE(R_VECT_MASK_SET, serial, set);
|
||||
|
||||
*port->rec_ctrl = IO_STATE(R_SERIAL0_REC_CTRL, rec_enable, enable);
|
||||
}
|
||||
|
||||
static struct tty_driver*
|
||||
etrax_console_device(struct console* co, int *index)
|
||||
{
|
||||
return serial_driver;
|
||||
*kgdb_port->rec_ctrl = IO_STATE(R_SERIAL0_REC_CTRL, rec_enable, enable);
|
||||
}
|
||||
|
||||
static int __init
|
||||
|
@ -428,11 +496,69 @@ console_setup(struct console *co, char *options)
|
|||
if (*s) port->parity = *s++;
|
||||
if (*s) port->bits = *s++ - '0';
|
||||
port->started = 0;
|
||||
start_port();
|
||||
start_port(0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This is a dummy serial device that throws away anything written to it.
|
||||
* This is used when no debug output is wanted.
|
||||
*/
|
||||
static struct tty_driver dummy_driver;
|
||||
|
||||
static int dummy_open(struct tty_struct *tty, struct file * filp)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dummy_close(struct tty_struct *tty, struct file * filp)
|
||||
{
|
||||
}
|
||||
|
||||
static int dummy_write(struct tty_struct * tty,
|
||||
const unsigned char *buf, int count)
|
||||
{
|
||||
return count;
|
||||
}
|
||||
|
||||
static int
|
||||
dummy_write_room(struct tty_struct *tty)
|
||||
{
|
||||
return 8192;
|
||||
}
|
||||
|
||||
void __init
|
||||
init_dummy_console(void)
|
||||
{
|
||||
memset(&dummy_driver, 0, sizeof(struct tty_driver));
|
||||
dummy_driver.driver_name = "serial";
|
||||
dummy_driver.name = "ttyS";
|
||||
dummy_driver.major = TTY_MAJOR;
|
||||
dummy_driver.minor_start = 68;
|
||||
dummy_driver.num = 1; /* etrax100 has 4 serial ports */
|
||||
dummy_driver.type = TTY_DRIVER_TYPE_SERIAL;
|
||||
dummy_driver.subtype = SERIAL_TYPE_NORMAL;
|
||||
dummy_driver.init_termios = tty_std_termios;
|
||||
dummy_driver.init_termios.c_cflag =
|
||||
B115200 | CS8 | CREAD | HUPCL | CLOCAL; /* is normally B9600 default... */
|
||||
dummy_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
|
||||
|
||||
dummy_driver.open = dummy_open;
|
||||
dummy_driver.close = dummy_close;
|
||||
dummy_driver.write = dummy_write;
|
||||
dummy_driver.write_room = dummy_write_room;
|
||||
if (tty_register_driver(&dummy_driver))
|
||||
panic("Couldn't register dummy serial driver\n");
|
||||
}
|
||||
|
||||
static struct tty_driver*
|
||||
etrax_console_device(struct console* co, int *index)
|
||||
{
|
||||
if (port)
|
||||
*index = port->index;
|
||||
return port ? serial_driver : &dummy_driver;
|
||||
}
|
||||
|
||||
static struct console sercons = {
|
||||
name : "ttyS",
|
||||
write: console_write,
|
||||
|
@ -504,28 +630,21 @@ init_etrax_debug(void)
|
|||
static int first = 1;
|
||||
|
||||
if (!first) {
|
||||
if (!port) {
|
||||
register_console(&sercons0);
|
||||
register_console(&sercons1);
|
||||
register_console(&sercons2);
|
||||
register_console(&sercons3);
|
||||
unregister_console(&sercons);
|
||||
}
|
||||
unregister_console(&sercons);
|
||||
register_console(&sercons0);
|
||||
register_console(&sercons1);
|
||||
register_console(&sercons2);
|
||||
register_console(&sercons3);
|
||||
init_dummy_console();
|
||||
return 0;
|
||||
}
|
||||
|
||||
first = 0;
|
||||
if (port)
|
||||
register_console(&sercons);
|
||||
register_console(&sercons);
|
||||
start_port(port);
|
||||
#ifdef CONFIG_ETRAX_KGDB
|
||||
start_port(kgdb_port);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __init
|
||||
init_console(void)
|
||||
{
|
||||
serial_driver = alloc_tty_driver(1);
|
||||
if (!serial_driver)
|
||||
return -ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
__initcall(init_etrax_debug);
|
||||
|
|
|
@ -0,0 +1,287 @@
|
|||
/* Wrapper for DMA channel allocator that updates DMA client muxing.
|
||||
* Copyright 2004, Axis Communications AB
|
||||
* $Id: dma.c,v 1.1 2004/12/13 12:21:51 starvik Exp $
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/errno.h>
|
||||
|
||||
#include <asm/dma.h>
|
||||
#include <asm/arch/svinto.h>
|
||||
|
||||
/* Macro to access ETRAX 100 registers */
|
||||
#define SETS(var, reg, field, val) var = (var & ~IO_MASK_(reg##_, field##_)) | \
|
||||
IO_STATE_(reg##_, field##_, _##val)
|
||||
|
||||
|
||||
static char used_dma_channels[MAX_DMA_CHANNELS];
|
||||
static const char * used_dma_channels_users[MAX_DMA_CHANNELS];
|
||||
|
||||
int cris_request_dma(unsigned int dmanr, const char * device_id,
|
||||
unsigned options, enum dma_owner owner)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned long int gens;
|
||||
int fail = -EINVAL;
|
||||
|
||||
if ((dmanr < 0) || (dmanr >= MAX_DMA_CHANNELS)) {
|
||||
printk(KERN_CRIT "cris_request_dma: invalid DMA channel %u\n", dmanr);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
local_irq_save(flags);
|
||||
if (used_dma_channels[dmanr]) {
|
||||
local_irq_restore(flags);
|
||||
if (options & DMA_VERBOSE_ON_ERROR) {
|
||||
printk(KERN_CRIT "Failed to request DMA %i for %s, already allocated by %s\n", dmanr, device_id, used_dma_channels_users[dmanr]);
|
||||
}
|
||||
if (options & DMA_PANIC_ON_ERROR) {
|
||||
panic("request_dma error!");
|
||||
}
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
gens = genconfig_shadow;
|
||||
|
||||
switch(owner)
|
||||
{
|
||||
case dma_eth:
|
||||
if ((dmanr != NETWORK_TX_DMA_NBR) &&
|
||||
(dmanr != NETWORK_RX_DMA_NBR)) {
|
||||
printk(KERN_CRIT "Invalid DMA channel for eth\n");
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
case dma_ser0:
|
||||
if (dmanr == SER0_TX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma6, serial0);
|
||||
} else if (dmanr == SER0_RX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma7, serial0);
|
||||
} else {
|
||||
printk(KERN_CRIT "Invalid DMA channel for ser0\n");
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
case dma_ser1:
|
||||
if (dmanr == SER1_TX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma8, serial1);
|
||||
} else if (dmanr == SER1_RX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma9, serial1);
|
||||
} else {
|
||||
printk(KERN_CRIT "Invalid DMA channel for ser1\n");
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
case dma_ser2:
|
||||
if (dmanr == SER2_TX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma2, serial2);
|
||||
} else if (dmanr == SER2_RX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma3, serial2);
|
||||
} else {
|
||||
printk(KERN_CRIT "Invalid DMA channel for ser2\n");
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
case dma_ser3:
|
||||
if (dmanr == SER3_TX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma4, serial3);
|
||||
} else if (dmanr == SER3_RX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma5, serial3);
|
||||
} else {
|
||||
printk(KERN_CRIT "Invalid DMA channel for ser3\n");
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
case dma_ata:
|
||||
if (dmanr == ATA_TX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma2, ata);
|
||||
} else if (dmanr == ATA_RX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma3, ata);
|
||||
} else {
|
||||
printk(KERN_CRIT "Invalid DMA channel for ata\n");
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
case dma_ext0:
|
||||
if (dmanr == EXTDMA0_TX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma4, extdma0);
|
||||
} else if (dmanr == EXTDMA0_RX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma5, extdma0);
|
||||
} else {
|
||||
printk(KERN_CRIT "Invalid DMA channel for ext0\n");
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
case dma_ext1:
|
||||
if (dmanr == EXTDMA1_TX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma6, extdma1);
|
||||
} else if (dmanr == EXTDMA1_RX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma7, extdma1);
|
||||
} else {
|
||||
printk(KERN_CRIT "Invalid DMA channel for ext1\n");
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
case dma_int6:
|
||||
if (dmanr == MEM2MEM_RX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma7, intdma6);
|
||||
} else {
|
||||
printk(KERN_CRIT "Invalid DMA channel for int6\n");
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
case dma_int7:
|
||||
if (dmanr == MEM2MEM_TX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma6, intdma7);
|
||||
} else {
|
||||
printk(KERN_CRIT "Invalid DMA channel for int7\n");
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
case dma_usb:
|
||||
if (dmanr == USB_TX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma8, usb);
|
||||
} else if (dmanr == USB_RX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma9, usb);
|
||||
} else {
|
||||
printk(KERN_CRIT "Invalid DMA channel for usb\n");
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
case dma_scsi0:
|
||||
if (dmanr == SCSI0_TX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma2, scsi0);
|
||||
} else if (dmanr == SCSI0_RX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma3, scsi0);
|
||||
} else {
|
||||
printk(KERN_CRIT "Invalid DMA channel for scsi0\n");
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
case dma_scsi1:
|
||||
if (dmanr == SCSI1_TX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma4, scsi1);
|
||||
} else if (dmanr == SCSI1_RX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma5, scsi1);
|
||||
} else {
|
||||
printk(KERN_CRIT "Invalid DMA channel for scsi1\n");
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
case dma_par0:
|
||||
if (dmanr == PAR0_TX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma2, par0);
|
||||
} else if (dmanr == PAR0_RX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma3, par0);
|
||||
} else {
|
||||
printk(KERN_CRIT "Invalid DMA channel for par0\n");
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
case dma_par1:
|
||||
if (dmanr == PAR1_TX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma4, par1);
|
||||
} else if (dmanr == PAR1_RX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma5, par1);
|
||||
} else {
|
||||
printk(KERN_CRIT "Invalid DMA channel for par1\n");
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printk(KERN_CRIT "Invalid DMA owner.\n");
|
||||
goto bail;
|
||||
}
|
||||
|
||||
used_dma_channels[dmanr] = 1;
|
||||
used_dma_channels_users[dmanr] = device_id;
|
||||
|
||||
{
|
||||
volatile int i;
|
||||
genconfig_shadow = gens;
|
||||
*R_GEN_CONFIG = genconfig_shadow;
|
||||
/* Wait 12 cycles before doing any DMA command */
|
||||
for(i = 6; i > 0; i--)
|
||||
nop();
|
||||
}
|
||||
fail = 0;
|
||||
bail:
|
||||
local_irq_restore(flags);
|
||||
return fail;
|
||||
}
|
||||
|
||||
void cris_free_dma(unsigned int dmanr, const char * device_id)
|
||||
{
|
||||
unsigned long flags;
|
||||
if ((dmanr < 0) || (dmanr >= MAX_DMA_CHANNELS)) {
|
||||
printk(KERN_CRIT "cris_free_dma: invalid DMA channel %u\n", dmanr);
|
||||
return;
|
||||
}
|
||||
|
||||
local_irq_save(flags);
|
||||
if (!used_dma_channels[dmanr]) {
|
||||
printk(KERN_CRIT "cris_free_dma: DMA channel %u not allocated\n", dmanr);
|
||||
} else if (device_id != used_dma_channels_users[dmanr]) {
|
||||
printk(KERN_CRIT "cris_free_dma: DMA channel %u not allocated by device\n", dmanr);
|
||||
} else {
|
||||
switch(dmanr)
|
||||
{
|
||||
case 0:
|
||||
*R_DMA_CH0_CMD = IO_STATE(R_DMA_CH0_CMD, cmd, reset);
|
||||
while (IO_EXTRACT(R_DMA_CH0_CMD, cmd, *R_DMA_CH0_CMD) ==
|
||||
IO_STATE_VALUE(R_DMA_CH0_CMD, cmd, reset));
|
||||
break;
|
||||
case 1:
|
||||
*R_DMA_CH1_CMD = IO_STATE(R_DMA_CH1_CMD, cmd, reset);
|
||||
while (IO_EXTRACT(R_DMA_CH1_CMD, cmd, *R_DMA_CH1_CMD) ==
|
||||
IO_STATE_VALUE(R_DMA_CH1_CMD, cmd, reset));
|
||||
break;
|
||||
case 2:
|
||||
*R_DMA_CH2_CMD = IO_STATE(R_DMA_CH2_CMD, cmd, reset);
|
||||
while (IO_EXTRACT(R_DMA_CH2_CMD, cmd, *R_DMA_CH2_CMD) ==
|
||||
IO_STATE_VALUE(R_DMA_CH2_CMD, cmd, reset));
|
||||
break;
|
||||
case 3:
|
||||
*R_DMA_CH3_CMD = IO_STATE(R_DMA_CH3_CMD, cmd, reset);
|
||||
while (IO_EXTRACT(R_DMA_CH3_CMD, cmd, *R_DMA_CH3_CMD) ==
|
||||
IO_STATE_VALUE(R_DMA_CH3_CMD, cmd, reset));
|
||||
break;
|
||||
case 4:
|
||||
*R_DMA_CH4_CMD = IO_STATE(R_DMA_CH4_CMD, cmd, reset);
|
||||
while (IO_EXTRACT(R_DMA_CH4_CMD, cmd, *R_DMA_CH4_CMD) ==
|
||||
IO_STATE_VALUE(R_DMA_CH4_CMD, cmd, reset));
|
||||
break;
|
||||
case 5:
|
||||
*R_DMA_CH5_CMD = IO_STATE(R_DMA_CH5_CMD, cmd, reset);
|
||||
while (IO_EXTRACT(R_DMA_CH5_CMD, cmd, *R_DMA_CH5_CMD) ==
|
||||
IO_STATE_VALUE(R_DMA_CH5_CMD, cmd, reset));
|
||||
break;
|
||||
case 6:
|
||||
*R_DMA_CH6_CMD = IO_STATE(R_DMA_CH6_CMD, cmd, reset);
|
||||
while (IO_EXTRACT(R_DMA_CH6_CMD, cmd, *R_DMA_CH6_CMD) ==
|
||||
IO_STATE_VALUE(R_DMA_CH6_CMD, cmd, reset));
|
||||
break;
|
||||
case 7:
|
||||
*R_DMA_CH7_CMD = IO_STATE(R_DMA_CH7_CMD, cmd, reset);
|
||||
while (IO_EXTRACT(R_DMA_CH7_CMD, cmd, *R_DMA_CH7_CMD) ==
|
||||
IO_STATE_VALUE(R_DMA_CH7_CMD, cmd, reset));
|
||||
break;
|
||||
case 8:
|
||||
*R_DMA_CH8_CMD = IO_STATE(R_DMA_CH8_CMD, cmd, reset);
|
||||
while (IO_EXTRACT(R_DMA_CH8_CMD, cmd, *R_DMA_CH8_CMD) ==
|
||||
IO_STATE_VALUE(R_DMA_CH8_CMD, cmd, reset));
|
||||
break;
|
||||
case 9:
|
||||
*R_DMA_CH9_CMD = IO_STATE(R_DMA_CH9_CMD, cmd, reset);
|
||||
while (IO_EXTRACT(R_DMA_CH9_CMD, cmd, *R_DMA_CH9_CMD) ==
|
||||
IO_STATE_VALUE(R_DMA_CH9_CMD, cmd, reset));
|
||||
break;
|
||||
}
|
||||
used_dma_channels[dmanr] = 0;
|
||||
}
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(cris_request_dma);
|
||||
EXPORT_SYMBOL(cris_free_dma);
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: entry.S,v 1.23 2004/10/19 13:07:37 starvik Exp $
|
||||
/* $Id: entry.S,v 1.28 2005/06/20 05:06:30 starvik Exp $
|
||||
*
|
||||
* linux/arch/cris/entry.S
|
||||
*
|
||||
|
@ -7,6 +7,22 @@
|
|||
* Authors: Bjorn Wesen (bjornw@axis.com)
|
||||
*
|
||||
* $Log: entry.S,v $
|
||||
* Revision 1.28 2005/06/20 05:06:30 starvik
|
||||
* Remove unnecessary diff to kernel.org tree
|
||||
*
|
||||
* Revision 1.27 2005/03/04 08:16:16 starvik
|
||||
* Merge of Linux 2.6.11.
|
||||
*
|
||||
* Revision 1.26 2005/01/11 13:49:47 starvik
|
||||
* Added NMI handler.
|
||||
*
|
||||
* Revision 1.25 2004/12/27 11:18:32 starvik
|
||||
* Merge of Linux 2.6.10 (not functional yet).
|
||||
*
|
||||
* Revision 1.24 2004/12/22 10:41:23 starvik
|
||||
* Updates to make v10 compile with the latest SMP aware generic code (even
|
||||
* though v10 will never have SMP).
|
||||
*
|
||||
* Revision 1.23 2004/10/19 13:07:37 starvik
|
||||
* Merge of Linux 2.6.9
|
||||
*
|
||||
|
@ -279,6 +295,7 @@
|
|||
#ifdef CONFIG_PREEMPT
|
||||
; Check if preemptive kernel scheduling should be done
|
||||
_resume_kernel:
|
||||
di
|
||||
; Load current task struct
|
||||
movs.w -8192, $r0 ; THREAD_SIZE = 8192
|
||||
and.d $sp, $r0
|
||||
|
@ -291,12 +308,7 @@ _need_resched:
|
|||
bpl _Rexit
|
||||
nop
|
||||
; Ok, lets's do some preemptive kernel scheduling
|
||||
move.d PREEMPT_ACTIVE, $r10
|
||||
move.d $r10, [$r0+TI_preempt_count] ; Mark as active
|
||||
ei
|
||||
jsr schedule
|
||||
clear.d [$r0+TI_preempt_count] ; Mark as inactive
|
||||
di
|
||||
jsr preempt_schedule_irq
|
||||
; Load new task struct
|
||||
movs.w -8192, $r0 ; THREAD_SIZE = 8192
|
||||
and.d $sp, $r0
|
||||
|
@ -590,15 +602,15 @@ mmu_bus_fault:
|
|||
move.d $r0, [$sp+16]
|
||||
1: btstq 12, $r1 ; Refill?
|
||||
bpl 2f
|
||||
lsrq PMD_SHIFT, $r1 ; Get PMD index into PGD (bit 24-31)
|
||||
move.d [current_pgd], $r0 ; PGD for the current process
|
||||
lsrq 24, $r1 ; Get PGD index (bit 24-31)
|
||||
move.d [per_cpu__current_pgd], $r0 ; PGD for the current process
|
||||
move.d [$r0+$r1.d], $r0 ; Get PMD
|
||||
beq 2f
|
||||
nop
|
||||
and.w PAGE_MASK, $r0 ; Remove PMD flags
|
||||
move.d [R_MMU_CAUSE], $r1
|
||||
lsrq PAGE_SHIFT, $r1
|
||||
and.d 0x7ff, $r1 ; Get PTE index into PMD (bit 13-24)
|
||||
and.d 0x7ff, $r1 ; Get PTE index into PGD (bit 13-23)
|
||||
move.d [$r0+$r1.d], $r1 ; Get PTE
|
||||
beq 2f
|
||||
nop
|
||||
|
@ -656,11 +668,6 @@ hwbreakpoint:
|
|||
nop
|
||||
|
||||
IRQ1_interrupt:
|
||||
|
||||
#if defined(CONFIG_ETRAX_WATCHDOG) && !defined(CONFIG_SVINTO_SIM)
|
||||
;; If we receive a watchdog interrupt while it is not expected, then set
|
||||
;; up a canonical frame and dump register contents before dying.
|
||||
|
||||
;; this prologue MUST match the one in irq.h and the struct in ptregs.h!!!
|
||||
move $brp,[$sp=$sp-16]; instruction pointer and room for a fake SBFS frame
|
||||
push $srp
|
||||
|
@ -672,9 +679,16 @@ IRQ1_interrupt:
|
|||
push $r10 ; push orig_r10
|
||||
clear.d [$sp=$sp-4] ; frametype == 0, normal frame
|
||||
|
||||
;; We don't check that we actually were bit by the watchdog as opposed to
|
||||
;; an external NMI, since there is currently no handler for external NMI.
|
||||
|
||||
move.d [R_IRQ_MASK0_RD], $r1 ; External NMI or watchdog?
|
||||
and.d 0x80000000, $r1
|
||||
beq wdog
|
||||
move.d $sp, $r10
|
||||
jsr handle_nmi
|
||||
setf m ; Enable NMI again
|
||||
retb ; Return from NMI
|
||||
nop
|
||||
wdog:
|
||||
#if defined(CONFIG_ETRAX_WATCHDOG) && !defined(CONFIG_SVINTO_SIM)
|
||||
;; Check if we're waiting for reset to happen, as signalled by
|
||||
;; hard_reset_now setting cause_of_death to a magic value. If so, just
|
||||
;; get stuck until reset happens.
|
||||
|
@ -1118,6 +1132,10 @@ sys_call_table:
|
|||
.long sys_mq_getsetattr
|
||||
.long sys_ni_syscall /* reserved for kexec */
|
||||
.long sys_waitid
|
||||
.long sys_ni_syscall /* 285 */ /* available */
|
||||
.long sys_add_key
|
||||
.long sys_request_key
|
||||
.long sys_keyctl
|
||||
|
||||
/*
|
||||
* NOTE!! This doesn't have to be exact - we just have
|
||||
|
|
|
@ -1,10 +1,20 @@
|
|||
/* $Id: fasttimer.c,v 1.6 2004/05/14 10:18:39 starvik Exp $
|
||||
/* $Id: fasttimer.c,v 1.9 2005/03/04 08:16:16 starvik Exp $
|
||||
* linux/arch/cris/kernel/fasttimer.c
|
||||
*
|
||||
* Fast timers for ETRAX100/ETRAX100LX
|
||||
* This may be useful in other OS than Linux so use 2 space indentation...
|
||||
*
|
||||
* $Log: fasttimer.c,v $
|
||||
* Revision 1.9 2005/03/04 08:16:16 starvik
|
||||
* Merge of Linux 2.6.11.
|
||||
*
|
||||
* Revision 1.8 2005/01/05 06:09:29 starvik
|
||||
* cli()/sti() will be obsolete in 2.6.11.
|
||||
*
|
||||
* Revision 1.7 2005/01/03 13:35:46 starvik
|
||||
* Removed obsolete stuff.
|
||||
* Mark fast timer IRQ as not shared.
|
||||
*
|
||||
* Revision 1.6 2004/05/14 10:18:39 starvik
|
||||
* Export fast_timer_list
|
||||
*
|
||||
|
@ -148,8 +158,7 @@ static int debug_log_cnt_wrapped = 0;
|
|||
#define DEBUG_LOG(string, value) \
|
||||
{ \
|
||||
unsigned long log_flags; \
|
||||
save_flags(log_flags); \
|
||||
cli(); \
|
||||
local_irq_save(log_flags); \
|
||||
debug_log_string[debug_log_cnt] = (string); \
|
||||
debug_log_value[debug_log_cnt] = (unsigned long)(value); \
|
||||
if (++debug_log_cnt >= DEBUG_LOG_MAX) \
|
||||
|
@ -157,7 +166,7 @@ static int debug_log_cnt_wrapped = 0;
|
|||
debug_log_cnt = debug_log_cnt % DEBUG_LOG_MAX; \
|
||||
debug_log_cnt_wrapped = 1; \
|
||||
} \
|
||||
restore_flags(log_flags); \
|
||||
local_irq_restore(log_flags); \
|
||||
}
|
||||
#else
|
||||
#define DEBUG_LOG(string, value)
|
||||
|
@ -320,8 +329,7 @@ void start_one_shot_timer(struct fast_timer *t,
|
|||
|
||||
D1(printk("sft %s %d us\n", name, delay_us));
|
||||
|
||||
save_flags(flags);
|
||||
cli();
|
||||
local_irq_save(flags);
|
||||
|
||||
do_gettimeofday_fast(&t->tv_set);
|
||||
tmp = fast_timer_list;
|
||||
|
@ -395,7 +403,7 @@ void start_one_shot_timer(struct fast_timer *t,
|
|||
|
||||
D2(printk("start_one_shot_timer: %d us done\n", delay_us));
|
||||
|
||||
restore_flags(flags);
|
||||
local_irq_restore(flags);
|
||||
} /* start_one_shot_timer */
|
||||
|
||||
static inline int fast_timer_pending (const struct fast_timer * t)
|
||||
|
@ -425,11 +433,10 @@ int del_fast_timer(struct fast_timer * t)
|
|||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
save_flags(flags);
|
||||
cli();
|
||||
local_irq_save(flags);
|
||||
ret = detach_fast_timer(t);
|
||||
t->next = t->prev = NULL;
|
||||
restore_flags(flags);
|
||||
local_irq_restore(flags);
|
||||
return ret;
|
||||
} /* del_fast_timer */
|
||||
|
||||
|
@ -444,8 +451,7 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs)
|
|||
struct fast_timer *t;
|
||||
unsigned long flags;
|
||||
|
||||
save_flags(flags);
|
||||
cli();
|
||||
local_irq_save(flags);
|
||||
|
||||
/* Clear timer1 irq */
|
||||
*R_IRQ_MASK0_CLR = IO_STATE(R_IRQ_MASK0_CLR, timer1, clr);
|
||||
|
@ -462,7 +468,7 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs)
|
|||
fast_timer_running = 0;
|
||||
fast_timer_ints++;
|
||||
|
||||
restore_flags(flags);
|
||||
local_irq_restore(flags);
|
||||
|
||||
t = fast_timer_list;
|
||||
while (t)
|
||||
|
@ -482,8 +488,7 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs)
|
|||
fast_timers_expired++;
|
||||
|
||||
/* Remove this timer before call, since it may reuse the timer */
|
||||
save_flags(flags);
|
||||
cli();
|
||||
local_irq_save(flags);
|
||||
if (t->prev)
|
||||
{
|
||||
t->prev->next = t->next;
|
||||
|
@ -498,7 +503,7 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs)
|
|||
}
|
||||
t->prev = NULL;
|
||||
t->next = NULL;
|
||||
restore_flags(flags);
|
||||
local_irq_restore(flags);
|
||||
|
||||
if (t->function != NULL)
|
||||
{
|
||||
|
@ -515,8 +520,7 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs)
|
|||
D1(printk(".\n"));
|
||||
}
|
||||
|
||||
save_flags(flags);
|
||||
cli();
|
||||
local_irq_save(flags);
|
||||
if ((t = fast_timer_list) != NULL)
|
||||
{
|
||||
/* Start next timer.. */
|
||||
|
@ -535,7 +539,7 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs)
|
|||
#endif
|
||||
start_timer1(us);
|
||||
}
|
||||
restore_flags(flags);
|
||||
local_irq_restore(flags);
|
||||
break;
|
||||
}
|
||||
else
|
||||
|
@ -546,7 +550,7 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs)
|
|||
D1(printk("e! %d\n", us));
|
||||
}
|
||||
}
|
||||
restore_flags(flags);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
if (!t)
|
||||
|
@ -748,13 +752,12 @@ static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len
|
|||
#endif
|
||||
|
||||
used += sprintf(bigbuf + used, "Active timers:\n");
|
||||
save_flags(flags);
|
||||
cli();
|
||||
local_irq_save(flags);
|
||||
t = fast_timer_list;
|
||||
while (t != NULL && (used+100 < BIG_BUF_SIZE))
|
||||
{
|
||||
nextt = t->next;
|
||||
restore_flags(flags);
|
||||
local_irq_restore(flags);
|
||||
used += sprintf(bigbuf + used, "%-14s s: %6lu.%06lu e: %6lu.%06lu "
|
||||
"d: %6li us data: 0x%08lX"
|
||||
/* " func: 0x%08lX" */
|
||||
|
@ -768,14 +771,14 @@ static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len
|
|||
t->data
|
||||
/* , t->function */
|
||||
);
|
||||
cli();
|
||||
local_irq_disable();
|
||||
if (t->next != nextt)
|
||||
{
|
||||
printk(KERN_WARNING "timer removed!\n");
|
||||
}
|
||||
t = nextt;
|
||||
}
|
||||
restore_flags(flags);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
if (used - offset < len)
|
||||
|
@ -963,7 +966,7 @@ void fast_timer_init(void)
|
|||
if ((fasttimer_proc_entry = create_proc_entry( "fasttimer", 0, 0 )))
|
||||
fasttimer_proc_entry->read_proc = proc_fasttimer_read;
|
||||
#endif /* PROC_FS */
|
||||
if(request_irq(TIMER1_IRQ_NBR, timer1_handler, SA_SHIRQ,
|
||||
if(request_irq(TIMER1_IRQ_NBR, timer1_handler, 0,
|
||||
"fast timer int", NULL))
|
||||
{
|
||||
printk("err: timer1 irq\n");
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: head.S,v 1.7 2004/05/14 07:58:01 starvik Exp $
|
||||
/* $Id: head.S,v 1.10 2005/06/20 05:12:54 starvik Exp $
|
||||
*
|
||||
* Head of the kernel - alter with care
|
||||
*
|
||||
|
@ -7,6 +7,16 @@
|
|||
* Authors: Bjorn Wesen (bjornw@axis.com)
|
||||
*
|
||||
* $Log: head.S,v $
|
||||
* Revision 1.10 2005/06/20 05:12:54 starvik
|
||||
* Remove unnecessary diff to kernel.org tree
|
||||
*
|
||||
* Revision 1.9 2004/12/13 12:21:51 starvik
|
||||
* Added I/O and DMA allocators from Linux 2.4
|
||||
*
|
||||
* Revision 1.8 2004/11/22 11:41:14 starvik
|
||||
* Kernel command line may be supplied to kernel. Not used by Axis but may
|
||||
* be used by customers.
|
||||
*
|
||||
* Revision 1.7 2004/05/14 07:58:01 starvik
|
||||
* Merge of changes from 2.4
|
||||
*
|
||||
|
@ -181,6 +191,7 @@
|
|||
|
||||
#define CRAMFS_MAGIC 0x28cd3d45
|
||||
#define RAM_INIT_MAGIC 0x56902387
|
||||
#define COMMAND_LINE_MAGIC 0x87109563
|
||||
|
||||
#define START_ETHERNET_CLOCK IO_STATE(R_NETWORK_GEN_CONFIG, enable, on) |\
|
||||
IO_STATE(R_NETWORK_GEN_CONFIG, phy, mii_clk)
|
||||
|
@ -490,6 +501,23 @@ _no_romfs_in_flash:
|
|||
|
||||
_start_it:
|
||||
|
||||
;; Check if kernel command line is supplied
|
||||
cmp.d COMMAND_LINE_MAGIC, $r10
|
||||
bne no_command_line
|
||||
nop
|
||||
|
||||
move.d 256, $r13
|
||||
move.d cris_command_line, $r10
|
||||
or.d 0x80000000, $r11 ; Make it virtual
|
||||
1:
|
||||
move.b [$r11+], $r12
|
||||
move.b $r12, [$r10+]
|
||||
subq 1, $r13
|
||||
bne 1b
|
||||
nop
|
||||
|
||||
no_command_line:
|
||||
|
||||
;; the kernel stack is overlayed with the task structure for each
|
||||
;; task. thus the initial kernel stack is in the same page as the
|
||||
;; init_task (but starts in the top of the page, size 8192)
|
||||
|
@ -567,76 +595,32 @@ _start_it:
|
|||
;; Etrax product HW genconfig setup
|
||||
|
||||
moveq 0,$r0
|
||||
#if (!defined(CONFIG_ETRAX_KGDB) || !defined(CONFIG_ETRAX_DEBUG_PORT0)) \
|
||||
&& !defined(CONFIG_DMA_MEMCPY)
|
||||
; DMA channels 6 and 7 to ser0, kgdb doesnt want DMA
|
||||
or.d IO_STATE (R_GEN_CONFIG, dma7, serial0) \
|
||||
| IO_STATE (R_GEN_CONFIG, dma6, serial0),$r0
|
||||
#endif
|
||||
#if !defined(CONFIG_ETRAX_KGDB) || !defined(CONFIG_ETRAX_DEBUG_PORT1)
|
||||
; DMA channels 8 and 9 to ser1, kgdb doesnt want DMA
|
||||
or.d IO_STATE (R_GEN_CONFIG, dma9, serial1) \
|
||||
| IO_STATE (R_GEN_CONFIG, dma8, serial1),$r0
|
||||
#endif
|
||||
#ifdef CONFIG_DMA_MEMCPY
|
||||
; 6/7 memory-memory DMA
|
||||
or.d IO_STATE (R_GEN_CONFIG, dma7, intdma6) \
|
||||
| IO_STATE (R_GEN_CONFIG, dma6, intdma7),$r0
|
||||
#endif
|
||||
#ifdef CONFIG_ETRAX_SERIAL_PORT2
|
||||
; Enable serial port 2
|
||||
or.w IO_STATE (R_GEN_CONFIG, ser2, select),$r0
|
||||
#if !defined(CONFIG_ETRAX_KGDB) || !defined(CONFIG_ETRAX_DEBUG_PORT2)
|
||||
; DMA channels 2 and 3 to ser2, kgdb doesnt want DMA
|
||||
or.d IO_STATE (R_GEN_CONFIG, dma3, serial2) \
|
||||
| IO_STATE (R_GEN_CONFIG, dma2, serial2),$r0
|
||||
#endif
|
||||
#endif
|
||||
#if defined(CONFIG_ETRAX_SERIAL_PORT3) || defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT1)
|
||||
; Enable serial port 3
|
||||
or.w IO_STATE (R_GEN_CONFIG, ser3, select),$r0
|
||||
#if !defined(CONFIG_ETRAX_KGDB) || !defined(CONFIG_ETRAX_DEBUG_PORT3)
|
||||
; DMA channels 4 and 5 to ser3, kgdb doesnt want DMA
|
||||
or.d IO_STATE (R_GEN_CONFIG, dma5, serial3) \
|
||||
| IO_STATE (R_GEN_CONFIG, dma4, serial3),$r0
|
||||
#endif
|
||||
#endif
|
||||
#if defined(CONFIG_ETRAX_PARALLEL_PORT0) || defined(CONFIG_ETRAX_ETHERNET_LPSLAVE)
|
||||
; parport 0 enabled using DMA 2/3
|
||||
or.w IO_STATE (R_GEN_CONFIG, par0, select),$r0
|
||||
#endif
|
||||
#if defined(CONFIG_ETRAX_PARALLEL_PORT1) || defined(CONFIG_ETRAX_ETHERNET_LPSLAVE)
|
||||
; parport 1 enabled using DMA 4/5
|
||||
or.w IO_STATE (R_GEN_CONFIG, par1, select),$r0
|
||||
#endif
|
||||
#ifdef CONFIG_ETRAX_IDE
|
||||
; DMA channels 2 and 3 to ATA, ATA enabled
|
||||
or.d IO_STATE (R_GEN_CONFIG, dma3, ata) \
|
||||
| IO_STATE (R_GEN_CONFIG, dma2, ata) \
|
||||
| IO_STATE (R_GEN_CONFIG, ata, select),$r0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ETRAX_USB_HOST_PORT1
|
||||
; Set the USB port 1 enable bit
|
||||
or.d IO_STATE (R_GEN_CONFIG, usb1, select),$r0
|
||||
#endif
|
||||
#ifdef CONFIG_ETRAX_USB_HOST_PORT2
|
||||
; Set the USB port 2 enable bit
|
||||
or.d IO_STATE (R_GEN_CONFIG, usb2, select),$r0
|
||||
#endif
|
||||
#ifdef CONFIG_ETRAX_USB_HOST
|
||||
; Connect DMA channels 8 and 9 to USB
|
||||
and.d (~(IO_MASK (R_GEN_CONFIG, dma9) \
|
||||
| IO_MASK (R_GEN_CONFIG, dma8))) \
|
||||
| IO_STATE (R_GEN_CONFIG, dma9, usb) \
|
||||
| IO_STATE (R_GEN_CONFIG, dma8, usb),$r0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_JULIETTE
|
||||
; DMA channels 4 and 5 to EXTDMA0, for Juliette
|
||||
or.d IO_STATE (R_GEN_CONFIG, dma5, extdma0) \
|
||||
| IO_STATE (R_GEN_CONFIG, dma4, extdma0),$r0
|
||||
#endif
|
||||
|
||||
;; Init interfaces (disable them).
|
||||
or.d IO_STATE (R_GEN_CONFIG, scsi0, disable) \
|
||||
| IO_STATE (R_GEN_CONFIG, ata, disable) \
|
||||
| IO_STATE (R_GEN_CONFIG, par0, disable) \
|
||||
| IO_STATE (R_GEN_CONFIG, ser2, disable) \
|
||||
| IO_STATE (R_GEN_CONFIG, mio, disable) \
|
||||
| IO_STATE (R_GEN_CONFIG, scsi1, disable) \
|
||||
| IO_STATE (R_GEN_CONFIG, scsi0w, disable) \
|
||||
| IO_STATE (R_GEN_CONFIG, par1, disable) \
|
||||
| IO_STATE (R_GEN_CONFIG, ser3, disable) \
|
||||
| IO_STATE (R_GEN_CONFIG, mio_w, disable) \
|
||||
| IO_STATE (R_GEN_CONFIG, usb1, disable) \
|
||||
| IO_STATE (R_GEN_CONFIG, usb2, disable) \
|
||||
| IO_STATE (R_GEN_CONFIG, par_w, disable),$r0
|
||||
|
||||
;; Init DMA channel muxing (set to unused clients).
|
||||
or.d IO_STATE (R_GEN_CONFIG, dma2, ata) \
|
||||
| IO_STATE (R_GEN_CONFIG, dma3, ata) \
|
||||
| IO_STATE (R_GEN_CONFIG, dma4, scsi1) \
|
||||
| IO_STATE (R_GEN_CONFIG, dma5, scsi1) \
|
||||
| IO_STATE (R_GEN_CONFIG, dma6, unused) \
|
||||
| IO_STATE (R_GEN_CONFIG, dma7, unused) \
|
||||
| IO_STATE (R_GEN_CONFIG, dma8, usb) \
|
||||
| IO_STATE (R_GEN_CONFIG, dma9, usb),$r0
|
||||
|
||||
|
||||
#if defined(CONFIG_ETRAX_DEF_R_PORT_G0_DIR_OUT)
|
||||
or.d IO_STATE (R_GEN_CONFIG, g0dir, out),$r0
|
||||
|
|
|
@ -0,0 +1,879 @@
|
|||
/* IO interface mux allocator for ETRAX100LX.
|
||||
* Copyright 2004, Axis Communications AB
|
||||
* $Id: io_interface_mux.c,v 1.2 2004/12/21 12:08:38 starvik Exp $
|
||||
*/
|
||||
|
||||
|
||||
/* C.f. ETRAX100LX Designer's Reference 20.9 */
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <asm/arch/svinto.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/io_interface_mux.h>
|
||||
|
||||
|
||||
#define DBG(s)
|
||||
|
||||
/* Macro to access ETRAX 100 registers */
|
||||
#define SETS(var, reg, field, val) var = (var & ~IO_MASK_(reg##_, field##_)) | \
|
||||
IO_STATE_(reg##_, field##_, _##val)
|
||||
|
||||
enum io_if_group {
|
||||
group_a = (1<<0),
|
||||
group_b = (1<<1),
|
||||
group_c = (1<<2),
|
||||
group_d = (1<<3),
|
||||
group_e = (1<<4),
|
||||
group_f = (1<<5)
|
||||
};
|
||||
|
||||
struct watcher
|
||||
{
|
||||
void (*notify)(const unsigned int gpio_in_available,
|
||||
const unsigned int gpio_out_available,
|
||||
const unsigned char pa_available,
|
||||
const unsigned char pb_available);
|
||||
struct watcher *next;
|
||||
};
|
||||
|
||||
|
||||
struct if_group
|
||||
{
|
||||
enum io_if_group group;
|
||||
unsigned char used;
|
||||
enum cris_io_interface owner;
|
||||
};
|
||||
|
||||
|
||||
struct interface
|
||||
{
|
||||
enum cris_io_interface ioif;
|
||||
unsigned char groups;
|
||||
unsigned char used;
|
||||
char *owner;
|
||||
unsigned int gpio_g_in;
|
||||
unsigned int gpio_g_out;
|
||||
unsigned char gpio_b;
|
||||
};
|
||||
|
||||
static struct if_group if_groups[6] = {
|
||||
{
|
||||
.group = group_a,
|
||||
.used = 0,
|
||||
},
|
||||
{
|
||||
.group = group_b,
|
||||
.used = 0,
|
||||
},
|
||||
{
|
||||
.group = group_c,
|
||||
.used = 0,
|
||||
},
|
||||
{
|
||||
.group = group_d,
|
||||
.used = 0,
|
||||
},
|
||||
{
|
||||
.group = group_e,
|
||||
.used = 0,
|
||||
},
|
||||
{
|
||||
.group = group_f,
|
||||
.used = 0,
|
||||
}
|
||||
};
|
||||
|
||||
/* The order in the array must match the order of enum
|
||||
* cris_io_interface in io_interface_mux.h */
|
||||
static struct interface interfaces[] = {
|
||||
/* Begin Non-multiplexed interfaces */
|
||||
{
|
||||
.ioif = if_eth,
|
||||
.groups = 0,
|
||||
.gpio_g_in = 0,
|
||||
.gpio_g_out = 0,
|
||||
.gpio_b = 0
|
||||
},
|
||||
{
|
||||
.ioif = if_serial_0,
|
||||
.groups = 0,
|
||||
.gpio_g_in = 0,
|
||||
.gpio_g_out = 0,
|
||||
.gpio_b = 0
|
||||
},
|
||||
/* End Non-multiplexed interfaces */
|
||||
{
|
||||
.ioif = if_serial_1,
|
||||
.groups = group_e,
|
||||
.gpio_g_in = 0x00000000,
|
||||
.gpio_g_out = 0x00000000,
|
||||
.gpio_b = 0x00
|
||||
},
|
||||
{
|
||||
.ioif = if_serial_2,
|
||||
.groups = group_b,
|
||||
.gpio_g_in = 0x000000c0,
|
||||
.gpio_g_out = 0x000000c0,
|
||||
.gpio_b = 0x00
|
||||
},
|
||||
{
|
||||
.ioif = if_serial_3,
|
||||
.groups = group_c,
|
||||
.gpio_g_in = 0xc0000000,
|
||||
.gpio_g_out = 0xc0000000,
|
||||
.gpio_b = 0x00
|
||||
},
|
||||
{
|
||||
.ioif = if_sync_serial_1,
|
||||
.groups = group_e | group_f, /* if_sync_serial_1 and if_sync_serial_3
|
||||
can be used simultaneously */
|
||||
.gpio_g_in = 0x00000000,
|
||||
.gpio_g_out = 0x00000000,
|
||||
.gpio_b = 0x10
|
||||
},
|
||||
{
|
||||
.ioif = if_sync_serial_3,
|
||||
.groups = group_c | group_f,
|
||||
.gpio_g_in = 0xc0000000,
|
||||
.gpio_g_out = 0xc0000000,
|
||||
.gpio_b = 0x80
|
||||
},
|
||||
{
|
||||
.ioif = if_shared_ram,
|
||||
.groups = group_a,
|
||||
.gpio_g_in = 0x0000ff3e,
|
||||
.gpio_g_out = 0x0000ff38,
|
||||
.gpio_b = 0x00
|
||||
},
|
||||
{
|
||||
.ioif = if_shared_ram_w,
|
||||
.groups = group_a | group_d,
|
||||
.gpio_g_in = 0x00ffff3e,
|
||||
.gpio_g_out = 0x00ffff38,
|
||||
.gpio_b = 0x00
|
||||
},
|
||||
{
|
||||
.ioif = if_par_0,
|
||||
.groups = group_a,
|
||||
.gpio_g_in = 0x0000ff3e,
|
||||
.gpio_g_out = 0x0000ff3e,
|
||||
.gpio_b = 0x00
|
||||
},
|
||||
{
|
||||
.ioif = if_par_1,
|
||||
.groups = group_d,
|
||||
.gpio_g_in = 0x3eff0000,
|
||||
.gpio_g_out = 0x3eff0000,
|
||||
.gpio_b = 0x00
|
||||
},
|
||||
{
|
||||
.ioif = if_par_w,
|
||||
.groups = group_a | group_d,
|
||||
.gpio_g_in = 0x00ffff3e,
|
||||
.gpio_g_out = 0x00ffff3e,
|
||||
.gpio_b = 0x00
|
||||
},
|
||||
{
|
||||
.ioif = if_scsi8_0,
|
||||
.groups = group_a | group_b | group_f, /* if_scsi8_0 and if_scsi8_1
|
||||
can be used simultaneously */
|
||||
.gpio_g_in = 0x0000ffff,
|
||||
.gpio_g_out = 0x0000ffff,
|
||||
.gpio_b = 0x10
|
||||
},
|
||||
{
|
||||
.ioif = if_scsi8_1,
|
||||
.groups = group_c | group_d | group_f, /* if_scsi8_0 and if_scsi8_1
|
||||
can be used simultaneously */
|
||||
.gpio_g_in = 0xffff0000,
|
||||
.gpio_g_out = 0xffff0000,
|
||||
.gpio_b = 0x80
|
||||
},
|
||||
{
|
||||
.ioif = if_scsi_w,
|
||||
.groups = group_a | group_b | group_d | group_f,
|
||||
.gpio_g_in = 0x01ffffff,
|
||||
.gpio_g_out = 0x07ffffff,
|
||||
.gpio_b = 0x80
|
||||
},
|
||||
{
|
||||
.ioif = if_ata,
|
||||
.groups = group_a | group_b | group_c | group_d,
|
||||
.gpio_g_in = 0xf9ffffff,
|
||||
.gpio_g_out = 0xffffffff,
|
||||
.gpio_b = 0x80
|
||||
},
|
||||
{
|
||||
.ioif = if_csp,
|
||||
.groups = group_f, /* if_csp and if_i2c can be used simultaneously */
|
||||
.gpio_g_in = 0x00000000,
|
||||
.gpio_g_out = 0x00000000,
|
||||
.gpio_b = 0xfc
|
||||
},
|
||||
{
|
||||
.ioif = if_i2c,
|
||||
.groups = group_f, /* if_csp and if_i2c can be used simultaneously */
|
||||
.gpio_g_in = 0x00000000,
|
||||
.gpio_g_out = 0x00000000,
|
||||
.gpio_b = 0x03
|
||||
},
|
||||
{
|
||||
.ioif = if_usb_1,
|
||||
.groups = group_e | group_f,
|
||||
.gpio_g_in = 0x00000000,
|
||||
.gpio_g_out = 0x00000000,
|
||||
.gpio_b = 0x2c
|
||||
},
|
||||
{
|
||||
.ioif = if_usb_2,
|
||||
.groups = group_d,
|
||||
.gpio_g_in = 0x0e000000,
|
||||
.gpio_g_out = 0x3c000000,
|
||||
.gpio_b = 0x00
|
||||
},
|
||||
/* GPIO pins */
|
||||
{
|
||||
.ioif = if_gpio_grp_a,
|
||||
.groups = group_a,
|
||||
.gpio_g_in = 0x0000ff3f,
|
||||
.gpio_g_out = 0x0000ff3f,
|
||||
.gpio_b = 0x00
|
||||
},
|
||||
{
|
||||
.ioif = if_gpio_grp_b,
|
||||
.groups = group_b,
|
||||
.gpio_g_in = 0x000000c0,
|
||||
.gpio_g_out = 0x000000c0,
|
||||
.gpio_b = 0x00
|
||||
},
|
||||
{
|
||||
.ioif = if_gpio_grp_c,
|
||||
.groups = group_c,
|
||||
.gpio_g_in = 0xc0000000,
|
||||
.gpio_g_out = 0xc0000000,
|
||||
.gpio_b = 0x00
|
||||
},
|
||||
{
|
||||
.ioif = if_gpio_grp_d,
|
||||
.groups = group_d,
|
||||
.gpio_g_in = 0x3fff0000,
|
||||
.gpio_g_out = 0x3fff0000,
|
||||
.gpio_b = 0x00
|
||||
},
|
||||
{
|
||||
.ioif = if_gpio_grp_e,
|
||||
.groups = group_e,
|
||||
.gpio_g_in = 0x00000000,
|
||||
.gpio_g_out = 0x00000000,
|
||||
.gpio_b = 0x00
|
||||
},
|
||||
{
|
||||
.ioif = if_gpio_grp_f,
|
||||
.groups = group_f,
|
||||
.gpio_g_in = 0x00000000,
|
||||
.gpio_g_out = 0x00000000,
|
||||
.gpio_b = 0xff
|
||||
}
|
||||
/* Array end */
|
||||
};
|
||||
|
||||
static struct watcher *watchers = NULL;
|
||||
|
||||
static unsigned int gpio_in_pins = 0xffffffff;
|
||||
static unsigned int gpio_out_pins = 0xffffffff;
|
||||
static unsigned char gpio_pb_pins = 0xff;
|
||||
static unsigned char gpio_pa_pins = 0xff;
|
||||
|
||||
static enum cris_io_interface gpio_pa_owners[8];
|
||||
static enum cris_io_interface gpio_pb_owners[8];
|
||||
static enum cris_io_interface gpio_pg_owners[32];
|
||||
|
||||
static int cris_io_interface_init(void);
|
||||
|
||||
static unsigned char clear_group_from_set(const unsigned char groups, struct if_group *group)
|
||||
{
|
||||
return (groups & ~group->group);
|
||||
}
|
||||
|
||||
|
||||
static struct if_group *get_group(const unsigned char groups)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < sizeof(if_groups)/sizeof(struct if_group); i++) {
|
||||
if (groups & if_groups[i].group) {
|
||||
return &if_groups[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void notify_watchers(void)
|
||||
{
|
||||
struct watcher *w = watchers;
|
||||
|
||||
DBG(printk("io_interface_mux: notifying watchers\n"));
|
||||
|
||||
while (NULL != w) {
|
||||
w->notify((const unsigned int)gpio_in_pins,
|
||||
(const unsigned int)gpio_out_pins,
|
||||
(const unsigned char)gpio_pa_pins,
|
||||
(const unsigned char)gpio_pb_pins);
|
||||
w = w->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int cris_request_io_interface(enum cris_io_interface ioif, const char *device_id)
|
||||
{
|
||||
int set_gen_config = 0;
|
||||
int set_gen_config_ii = 0;
|
||||
unsigned long int gens;
|
||||
unsigned long int gens_ii;
|
||||
struct if_group *grp;
|
||||
unsigned char group_set;
|
||||
unsigned long flags;
|
||||
|
||||
(void)cris_io_interface_init();
|
||||
|
||||
DBG(printk("cris_request_io_interface(%d, \"%s\")\n", ioif, device_id));
|
||||
|
||||
if ((ioif >= if_max_interfaces) || (ioif < 0)) {
|
||||
printk(KERN_CRIT "cris_request_io_interface: Bad interface %u submitted for %s\n",
|
||||
ioif,
|
||||
device_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
if (interfaces[ioif].used) {
|
||||
local_irq_restore(flags);
|
||||
printk(KERN_CRIT "cris_io_interface: Cannot allocate interface for %s, in use by %s\n",
|
||||
device_id,
|
||||
interfaces[ioif].owner);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* Check that all required groups are free before allocating, */
|
||||
group_set = interfaces[ioif].groups;
|
||||
while (NULL != (grp = get_group(group_set))) {
|
||||
if (grp->used) {
|
||||
if (grp->group == group_f) {
|
||||
if ((if_sync_serial_1 == ioif) ||
|
||||
(if_sync_serial_3 == ioif)) {
|
||||
if ((grp->owner != if_sync_serial_1) &&
|
||||
(grp->owner != if_sync_serial_3)) {
|
||||
local_irq_restore(flags);
|
||||
return -EBUSY;
|
||||
}
|
||||
} else if ((if_scsi8_0 == ioif) ||
|
||||
(if_scsi8_1 == ioif)) {
|
||||
if ((grp->owner != if_scsi8_0) &&
|
||||
(grp->owner != if_scsi8_1)) {
|
||||
local_irq_restore(flags);
|
||||
return -EBUSY;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
local_irq_restore(flags);
|
||||
return -EBUSY;
|
||||
}
|
||||
}
|
||||
group_set = clear_group_from_set(group_set, grp);
|
||||
}
|
||||
|
||||
/* Are the required GPIO pins available too? */
|
||||
if (((interfaces[ioif].gpio_g_in & gpio_in_pins) != interfaces[ioif].gpio_g_in) ||
|
||||
((interfaces[ioif].gpio_g_out & gpio_out_pins) != interfaces[ioif].gpio_g_out) ||
|
||||
((interfaces[ioif].gpio_b & gpio_pb_pins) != interfaces[ioif].gpio_b)) {
|
||||
printk(KERN_CRIT "cris_request_io_interface: Could not get required pins for interface %u\n",
|
||||
ioif);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* All needed I/O pins and pin groups are free, allocate. */
|
||||
group_set = interfaces[ioif].groups;
|
||||
while (NULL != (grp = get_group(group_set))) {
|
||||
grp->used = 1;
|
||||
grp->owner = ioif;
|
||||
group_set = clear_group_from_set(group_set, grp);
|
||||
}
|
||||
|
||||
gens = genconfig_shadow;
|
||||
gens_ii = gen_config_ii_shadow;
|
||||
|
||||
set_gen_config = 1;
|
||||
switch (ioif)
|
||||
{
|
||||
/* Begin Non-multiplexed interfaces */
|
||||
case if_eth:
|
||||
/* fall through */
|
||||
case if_serial_0:
|
||||
set_gen_config = 0;
|
||||
break;
|
||||
/* End Non-multiplexed interfaces */
|
||||
case if_serial_1:
|
||||
set_gen_config_ii = 1;
|
||||
SETS(gens_ii, R_GEN_CONFIG_II, sermode1, async);
|
||||
break;
|
||||
case if_serial_2:
|
||||
SETS(gens, R_GEN_CONFIG, ser2, select);
|
||||
break;
|
||||
case if_serial_3:
|
||||
SETS(gens, R_GEN_CONFIG, ser3, select);
|
||||
set_gen_config_ii = 1;
|
||||
SETS(gens_ii, R_GEN_CONFIG_II, sermode3, async);
|
||||
break;
|
||||
case if_sync_serial_1:
|
||||
set_gen_config_ii = 1;
|
||||
SETS(gens_ii, R_GEN_CONFIG_II, sermode1, sync);
|
||||
break;
|
||||
case if_sync_serial_3:
|
||||
SETS(gens, R_GEN_CONFIG, ser3, select);
|
||||
set_gen_config_ii = 1;
|
||||
SETS(gens_ii, R_GEN_CONFIG_II, sermode3, sync);
|
||||
break;
|
||||
case if_shared_ram:
|
||||
SETS(gens, R_GEN_CONFIG, mio, select);
|
||||
break;
|
||||
case if_shared_ram_w:
|
||||
SETS(gens, R_GEN_CONFIG, mio_w, select);
|
||||
break;
|
||||
case if_par_0:
|
||||
SETS(gens, R_GEN_CONFIG, par0, select);
|
||||
break;
|
||||
case if_par_1:
|
||||
SETS(gens, R_GEN_CONFIG, par1, select);
|
||||
break;
|
||||
case if_par_w:
|
||||
SETS(gens, R_GEN_CONFIG, par0, select);
|
||||
SETS(gens, R_GEN_CONFIG, par_w, select);
|
||||
break;
|
||||
case if_scsi8_0:
|
||||
SETS(gens, R_GEN_CONFIG, scsi0, select);
|
||||
break;
|
||||
case if_scsi8_1:
|
||||
SETS(gens, R_GEN_CONFIG, scsi1, select);
|
||||
break;
|
||||
case if_scsi_w:
|
||||
SETS(gens, R_GEN_CONFIG, scsi0, select);
|
||||
SETS(gens, R_GEN_CONFIG, scsi0w, select);
|
||||
break;
|
||||
case if_ata:
|
||||
SETS(gens, R_GEN_CONFIG, ata, select);
|
||||
break;
|
||||
case if_csp:
|
||||
/* fall through */
|
||||
case if_i2c:
|
||||
set_gen_config = 0;
|
||||
break;
|
||||
case if_usb_1:
|
||||
SETS(gens, R_GEN_CONFIG, usb1, select);
|
||||
break;
|
||||
case if_usb_2:
|
||||
SETS(gens, R_GEN_CONFIG, usb2, select);
|
||||
break;
|
||||
case if_gpio_grp_a:
|
||||
/* GPIO groups are only accounted, don't do configuration changes. */
|
||||
/* fall through */
|
||||
case if_gpio_grp_b:
|
||||
/* fall through */
|
||||
case if_gpio_grp_c:
|
||||
/* fall through */
|
||||
case if_gpio_grp_d:
|
||||
/* fall through */
|
||||
case if_gpio_grp_e:
|
||||
/* fall through */
|
||||
case if_gpio_grp_f:
|
||||
set_gen_config = 0;
|
||||
break;
|
||||
default:
|
||||
panic("cris_request_io_interface: Bad interface %u submitted for %s\n",
|
||||
ioif,
|
||||
device_id);
|
||||
}
|
||||
|
||||
interfaces[ioif].used = 1;
|
||||
interfaces[ioif].owner = (char*)device_id;
|
||||
|
||||
if (set_gen_config) {
|
||||
volatile int i;
|
||||
genconfig_shadow = gens;
|
||||
*R_GEN_CONFIG = genconfig_shadow;
|
||||
/* Wait 12 cycles before doing any DMA command */
|
||||
for(i = 6; i > 0; i--)
|
||||
nop();
|
||||
}
|
||||
if (set_gen_config_ii) {
|
||||
gen_config_ii_shadow = gens_ii;
|
||||
*R_GEN_CONFIG_II = gen_config_ii_shadow;
|
||||
}
|
||||
|
||||
DBG(printk("GPIO pins: available before: g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
|
||||
gpio_in_pins, gpio_out_pins, gpio_pb_pins));
|
||||
DBG(printk("grabbing pins: g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
|
||||
interfaces[ioif].gpio_g_in,
|
||||
interfaces[ioif].gpio_g_out,
|
||||
interfaces[ioif].gpio_b));
|
||||
|
||||
gpio_in_pins &= ~interfaces[ioif].gpio_g_in;
|
||||
gpio_out_pins &= ~interfaces[ioif].gpio_g_out;
|
||||
gpio_pb_pins &= ~interfaces[ioif].gpio_b;
|
||||
|
||||
DBG(printk("GPIO pins: available after: g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
|
||||
gpio_in_pins, gpio_out_pins, gpio_pb_pins));
|
||||
|
||||
local_irq_restore(flags);
|
||||
|
||||
notify_watchers();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void cris_free_io_interface(enum cris_io_interface ioif)
|
||||
{
|
||||
struct if_group *grp;
|
||||
unsigned char group_set;
|
||||
unsigned long flags;
|
||||
|
||||
(void)cris_io_interface_init();
|
||||
|
||||
if ((ioif >= if_max_interfaces) || (ioif < 0)) {
|
||||
printk(KERN_CRIT "cris_free_io_interface: Bad interface %u\n",
|
||||
ioif);
|
||||
return;
|
||||
}
|
||||
local_irq_save(flags);
|
||||
if (!interfaces[ioif].used) {
|
||||
printk(KERN_CRIT "cris_free_io_interface: Freeing free interface %u\n",
|
||||
ioif);
|
||||
local_irq_restore(flags);
|
||||
return;
|
||||
}
|
||||
group_set = interfaces[ioif].groups;
|
||||
while (NULL != (grp = get_group(group_set))) {
|
||||
if (grp->group == group_f) {
|
||||
switch (ioif)
|
||||
{
|
||||
case if_sync_serial_1:
|
||||
if ((grp->owner == if_sync_serial_1) &&
|
||||
interfaces[if_sync_serial_3].used) {
|
||||
grp->owner = if_sync_serial_3;
|
||||
} else
|
||||
grp->used = 0;
|
||||
break;
|
||||
case if_sync_serial_3:
|
||||
if ((grp->owner == if_sync_serial_3) &&
|
||||
interfaces[if_sync_serial_1].used) {
|
||||
grp->owner = if_sync_serial_1;
|
||||
} else
|
||||
grp->used = 0;
|
||||
break;
|
||||
case if_scsi8_0:
|
||||
if ((grp->owner == if_scsi8_0) &&
|
||||
interfaces[if_scsi8_1].used) {
|
||||
grp->owner = if_scsi8_1;
|
||||
} else
|
||||
grp->used = 0;
|
||||
break;
|
||||
case if_scsi8_1:
|
||||
if ((grp->owner == if_scsi8_1) &&
|
||||
interfaces[if_scsi8_0].used) {
|
||||
grp->owner = if_scsi8_0;
|
||||
} else
|
||||
grp->used = 0;
|
||||
break;
|
||||
default:
|
||||
grp->used = 0;
|
||||
}
|
||||
} else {
|
||||
grp->used = 0;
|
||||
}
|
||||
group_set = clear_group_from_set(group_set, grp);
|
||||
}
|
||||
interfaces[ioif].used = 0;
|
||||
interfaces[ioif].owner = NULL;
|
||||
|
||||
DBG(printk("GPIO pins: available before: g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
|
||||
gpio_in_pins, gpio_out_pins, gpio_pb_pins));
|
||||
DBG(printk("freeing pins: g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
|
||||
interfaces[ioif].gpio_g_in,
|
||||
interfaces[ioif].gpio_g_out,
|
||||
interfaces[ioif].gpio_b));
|
||||
|
||||
gpio_in_pins |= interfaces[ioif].gpio_g_in;
|
||||
gpio_out_pins |= interfaces[ioif].gpio_g_out;
|
||||
gpio_pb_pins |= interfaces[ioif].gpio_b;
|
||||
|
||||
DBG(printk("GPIO pins: available after: g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
|
||||
gpio_in_pins, gpio_out_pins, gpio_pb_pins));
|
||||
|
||||
local_irq_restore(flags);
|
||||
|
||||
notify_watchers();
|
||||
}
|
||||
|
||||
/* Create a bitmask from bit 0 (inclusive) to bit stop_bit
|
||||
(non-inclusive). stop_bit == 0 returns 0x0 */
|
||||
static inline unsigned int create_mask(const unsigned stop_bit)
|
||||
{
|
||||
/* Avoid overflow */
|
||||
if (stop_bit >= 32) {
|
||||
return 0xffffffff;
|
||||
}
|
||||
return (1<<stop_bit)-1;
|
||||
}
|
||||
|
||||
|
||||
/* port can be 'a', 'b' or 'g' */
|
||||
int cris_io_interface_allocate_pins(const enum cris_io_interface ioif,
|
||||
const char port,
|
||||
const unsigned start_bit,
|
||||
const unsigned stop_bit)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int mask = 0;
|
||||
unsigned int tmp_mask;
|
||||
unsigned long int flags;
|
||||
enum cris_io_interface *owners;
|
||||
|
||||
(void)cris_io_interface_init();
|
||||
|
||||
DBG(printk("cris_io_interface_allocate_pins: if=%d port=%c start=%u stop=%u\n",
|
||||
ioif, port, start_bit, stop_bit));
|
||||
|
||||
if (!((start_bit <= stop_bit) &&
|
||||
((((port == 'a') || (port == 'b')) && (stop_bit < 8)) ||
|
||||
((port == 'g') && (stop_bit < 32))))) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mask = create_mask(stop_bit + 1);
|
||||
tmp_mask = create_mask(start_bit);
|
||||
mask &= ~tmp_mask;
|
||||
|
||||
DBG(printk("cris_io_interface_allocate_pins: port=%c start=%u stop=%u mask=0x%08x\n",
|
||||
port, start_bit, stop_bit, mask));
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
switch (port) {
|
||||
case 'a':
|
||||
if ((gpio_pa_pins & mask) != mask) {
|
||||
local_irq_restore(flags);
|
||||
return -EBUSY;
|
||||
}
|
||||
owners = gpio_pa_owners;
|
||||
gpio_pa_pins &= ~mask;
|
||||
break;
|
||||
case 'b':
|
||||
if ((gpio_pb_pins & mask) != mask) {
|
||||
local_irq_restore(flags);
|
||||
return -EBUSY;
|
||||
}
|
||||
owners = gpio_pb_owners;
|
||||
gpio_pb_pins &= ~mask;
|
||||
break;
|
||||
case 'g':
|
||||
if (((gpio_in_pins & mask) != mask) ||
|
||||
((gpio_out_pins & mask) != mask)) {
|
||||
local_irq_restore(flags);
|
||||
return -EBUSY;
|
||||
}
|
||||
owners = gpio_pg_owners;
|
||||
gpio_in_pins &= ~mask;
|
||||
gpio_out_pins &= ~mask;
|
||||
break;
|
||||
default:
|
||||
local_irq_restore(flags);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = start_bit; i <= stop_bit; i++) {
|
||||
owners[i] = ioif;
|
||||
}
|
||||
local_irq_restore(flags);
|
||||
|
||||
notify_watchers();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* port can be 'a', 'b' or 'g' */
|
||||
int cris_io_interface_free_pins(const enum cris_io_interface ioif,
|
||||
const char port,
|
||||
const unsigned start_bit,
|
||||
const unsigned stop_bit)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int mask = 0;
|
||||
unsigned int tmp_mask;
|
||||
unsigned long int flags;
|
||||
enum cris_io_interface *owners;
|
||||
|
||||
(void)cris_io_interface_init();
|
||||
|
||||
if (!((start_bit <= stop_bit) &&
|
||||
((((port == 'a') || (port == 'b')) && (stop_bit < 8)) ||
|
||||
((port == 'g') && (stop_bit < 32))))) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mask = create_mask(stop_bit + 1);
|
||||
tmp_mask = create_mask(start_bit);
|
||||
mask &= ~tmp_mask;
|
||||
|
||||
DBG(printk("cris_io_interface_free_pins: port=%c start=%u stop=%u mask=0x%08x\n",
|
||||
port, start_bit, stop_bit, mask));
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
switch (port) {
|
||||
case 'a':
|
||||
if ((~gpio_pa_pins & mask) != mask) {
|
||||
local_irq_restore(flags);
|
||||
printk(KERN_CRIT "cris_io_interface_free_pins: Freeing free pins");
|
||||
}
|
||||
owners = gpio_pa_owners;
|
||||
break;
|
||||
case 'b':
|
||||
if ((~gpio_pb_pins & mask) != mask) {
|
||||
local_irq_restore(flags);
|
||||
printk(KERN_CRIT "cris_io_interface_free_pins: Freeing free pins");
|
||||
}
|
||||
owners = gpio_pb_owners;
|
||||
break;
|
||||
case 'g':
|
||||
if (((~gpio_in_pins & mask) != mask) ||
|
||||
((~gpio_out_pins & mask) != mask)) {
|
||||
local_irq_restore(flags);
|
||||
printk(KERN_CRIT "cris_io_interface_free_pins: Freeing free pins");
|
||||
}
|
||||
owners = gpio_pg_owners;
|
||||
break;
|
||||
default:
|
||||
owners = NULL; /* Cannot happen. Shut up, gcc! */
|
||||
}
|
||||
|
||||
for (i = start_bit; i <= stop_bit; i++) {
|
||||
if (owners[i] != ioif) {
|
||||
printk(KERN_CRIT "cris_io_interface_free_pins: Freeing unowned pins");
|
||||
}
|
||||
}
|
||||
|
||||
/* All was ok, change data. */
|
||||
switch (port) {
|
||||
case 'a':
|
||||
gpio_pa_pins |= mask;
|
||||
break;
|
||||
case 'b':
|
||||
gpio_pb_pins |= mask;
|
||||
break;
|
||||
case 'g':
|
||||
gpio_in_pins |= mask;
|
||||
gpio_out_pins |= mask;
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = start_bit; i <= stop_bit; i++) {
|
||||
owners[i] = if_unclaimed;
|
||||
}
|
||||
local_irq_restore(flags);
|
||||
notify_watchers();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int cris_io_interface_register_watcher(void (*notify)(const unsigned int gpio_in_available,
|
||||
const unsigned int gpio_out_available,
|
||||
const unsigned char pa_available,
|
||||
const unsigned char pb_available))
|
||||
{
|
||||
struct watcher *w;
|
||||
|
||||
(void)cris_io_interface_init();
|
||||
|
||||
if (NULL == notify) {
|
||||
return -EINVAL;
|
||||
}
|
||||
w = kmalloc(sizeof(*w), GFP_KERNEL);
|
||||
if (!w) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
w->notify = notify;
|
||||
w->next = watchers;
|
||||
watchers = w;
|
||||
|
||||
w->notify((const unsigned int)gpio_in_pins,
|
||||
(const unsigned int)gpio_out_pins,
|
||||
(const unsigned char)gpio_pa_pins,
|
||||
(const unsigned char)gpio_pb_pins);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cris_io_interface_delete_watcher(void (*notify)(const unsigned int gpio_in_available,
|
||||
const unsigned int gpio_out_available,
|
||||
const unsigned char pa_available,
|
||||
const unsigned char pb_available))
|
||||
{
|
||||
struct watcher *w = watchers, *prev = NULL;
|
||||
|
||||
(void)cris_io_interface_init();
|
||||
|
||||
while ((NULL != w) && (w->notify != notify)){
|
||||
prev = w;
|
||||
w = w->next;
|
||||
}
|
||||
if (NULL != w) {
|
||||
if (NULL != prev) {
|
||||
prev->next = w->next;
|
||||
} else {
|
||||
watchers = w->next;
|
||||
}
|
||||
kfree(w);
|
||||
return;
|
||||
}
|
||||
printk(KERN_WARNING "cris_io_interface_delete_watcher: Deleting unknown watcher 0x%p\n", notify);
|
||||
}
|
||||
|
||||
|
||||
static int cris_io_interface_init(void)
|
||||
{
|
||||
static int first = 1;
|
||||
int i;
|
||||
|
||||
if (!first) {
|
||||
return 0;
|
||||
}
|
||||
first = 0;
|
||||
|
||||
for (i = 0; i<8; i++) {
|
||||
gpio_pa_owners[i] = if_unclaimed;
|
||||
gpio_pb_owners[i] = if_unclaimed;
|
||||
gpio_pg_owners[i] = if_unclaimed;
|
||||
}
|
||||
for (; i<32; i++) {
|
||||
gpio_pg_owners[i] = if_unclaimed;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
module_init(cris_io_interface_init);
|
||||
|
||||
|
||||
EXPORT_SYMBOL(cris_request_io_interface);
|
||||
EXPORT_SYMBOL(cris_free_io_interface);
|
||||
EXPORT_SYMBOL(cris_io_interface_allocate_pins);
|
||||
EXPORT_SYMBOL(cris_io_interface_free_pins);
|
||||
EXPORT_SYMBOL(cris_io_interface_register_watcher);
|
||||
EXPORT_SYMBOL(cris_io_interface_delete_watcher);
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: irq.c,v 1.2 2004/06/09 05:30:27 starvik Exp $
|
||||
/* $Id: irq.c,v 1.4 2005/01/04 12:22:28 starvik Exp $
|
||||
*
|
||||
* linux/arch/cris/kernel/irq.c
|
||||
*
|
||||
|
@ -12,11 +12,13 @@
|
|||
*/
|
||||
|
||||
#include <asm/irq.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/config.h>
|
||||
|
||||
irqvectptr irq_shortcuts[NR_IRQS]; /* vector of shortcut jumps after the irq prologue */
|
||||
#define mask_irq(irq_nr) (*R_VECT_MASK_CLR = 1 << (irq_nr));
|
||||
#define unmask_irq(irq_nr) (*R_VECT_MASK_SET = 1 << (irq_nr));
|
||||
|
||||
/* don't use set_int_vector, it bypasses the linux interrupt handlers. it is
|
||||
* global just so that the kernel gdb can use it.
|
||||
|
@ -102,41 +104,52 @@ static void (*interrupt[NR_IRQS])(void) = {
|
|||
IRQ31_interrupt
|
||||
};
|
||||
|
||||
static void (*bad_interrupt[NR_IRQS])(void) = {
|
||||
NULL, NULL,
|
||||
NULL, bad_IRQ3_interrupt,
|
||||
bad_IRQ4_interrupt, bad_IRQ5_interrupt,
|
||||
bad_IRQ6_interrupt, bad_IRQ7_interrupt,
|
||||
bad_IRQ8_interrupt, bad_IRQ9_interrupt,
|
||||
bad_IRQ10_interrupt, bad_IRQ11_interrupt,
|
||||
bad_IRQ12_interrupt, bad_IRQ13_interrupt,
|
||||
NULL, NULL,
|
||||
bad_IRQ16_interrupt, bad_IRQ17_interrupt,
|
||||
bad_IRQ18_interrupt, bad_IRQ19_interrupt,
|
||||
bad_IRQ20_interrupt, bad_IRQ21_interrupt,
|
||||
bad_IRQ22_interrupt, bad_IRQ23_interrupt,
|
||||
bad_IRQ24_interrupt, bad_IRQ25_interrupt,
|
||||
NULL, NULL, NULL, NULL, NULL,
|
||||
bad_IRQ31_interrupt
|
||||
static void enable_crisv10_irq(unsigned int irq);
|
||||
|
||||
static unsigned int startup_crisv10_irq(unsigned int irq)
|
||||
{
|
||||
enable_crisv10_irq(irq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define shutdown_crisv10_irq disable_crisv10_irq
|
||||
|
||||
static void enable_crisv10_irq(unsigned int irq)
|
||||
{
|
||||
unmask_irq(irq);
|
||||
}
|
||||
|
||||
static void disable_crisv10_irq(unsigned int irq)
|
||||
{
|
||||
mask_irq(irq);
|
||||
}
|
||||
|
||||
static void ack_crisv10_irq(unsigned int irq)
|
||||
{
|
||||
}
|
||||
|
||||
static void end_crisv10_irq(unsigned int irq)
|
||||
{
|
||||
}
|
||||
|
||||
static struct hw_interrupt_type crisv10_irq_type = {
|
||||
.typename = "CRISv10",
|
||||
.startup = startup_crisv10_irq,
|
||||
.shutdown = shutdown_crisv10_irq,
|
||||
.enable = enable_crisv10_irq,
|
||||
.disable = disable_crisv10_irq,
|
||||
.ack = ack_crisv10_irq,
|
||||
.end = end_crisv10_irq,
|
||||
.set_affinity = NULL
|
||||
};
|
||||
|
||||
void arch_setup_irq(int irq)
|
||||
{
|
||||
set_int_vector(irq, interrupt[irq]);
|
||||
}
|
||||
|
||||
void arch_free_irq(int irq)
|
||||
{
|
||||
set_int_vector(irq, bad_interrupt[irq]);
|
||||
}
|
||||
|
||||
void weird_irq(void);
|
||||
void system_call(void); /* from entry.S */
|
||||
void do_sigtrap(void); /* from entry.S */
|
||||
void gdb_handle_breakpoint(void); /* from entry.S */
|
||||
|
||||
/* init_IRQ() is called by start_kernel and is responsible for fixing IRQ masks and
|
||||
setting the irq vector table to point to bad_interrupt ptrs.
|
||||
setting the irq vector table.
|
||||
*/
|
||||
|
||||
void __init
|
||||
|
@ -154,14 +167,15 @@ init_IRQ(void)
|
|||
|
||||
*R_VECT_MASK_CLR = 0xffffffff;
|
||||
|
||||
/* clear the shortcut entry points */
|
||||
|
||||
for(i = 0; i < NR_IRQS; i++)
|
||||
irq_shortcuts[i] = NULL;
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
etrax_irv->v[i] = weird_irq;
|
||||
|
||||
/* Initialize IRQ handler descriptiors. */
|
||||
for(i = 2; i < NR_IRQS; i++) {
|
||||
irq_desc[i].handler = &crisv10_irq_type;
|
||||
set_int_vector(i, interrupt[i]);
|
||||
}
|
||||
|
||||
/* the entries in the break vector contain actual code to be
|
||||
executed by the associated break handler, rather than just a jump
|
||||
address. therefore we need to setup a default breakpoint handler
|
||||
|
@ -170,10 +184,6 @@ init_IRQ(void)
|
|||
for (i = 0; i < 16; i++)
|
||||
set_break_vector(i, do_sigtrap);
|
||||
|
||||
/* set all etrax irq's to the bad handlers */
|
||||
for (i = 2; i < NR_IRQS; i++)
|
||||
set_int_vector(i, bad_interrupt[i]);
|
||||
|
||||
/* except IRQ 15 which is the multiple-IRQ handler on Etrax100 */
|
||||
|
||||
set_int_vector(15, multiple_interrupt);
|
||||
|
|
|
@ -18,6 +18,10 @@
|
|||
*! Jul 21 1999 Bjorn Wesen eLinux port
|
||||
*!
|
||||
*! $Log: kgdb.c,v $
|
||||
*! Revision 1.6 2005/01/14 10:12:17 starvik
|
||||
*! KGDB on separate port.
|
||||
*! Console fixes from 2.4.
|
||||
*!
|
||||
*! Revision 1.5 2004/10/07 13:59:08 starvik
|
||||
*! Corrected call to set_int_vector
|
||||
*!
|
||||
|
@ -71,7 +75,7 @@
|
|||
*!
|
||||
*!---------------------------------------------------------------------------
|
||||
*!
|
||||
*! $Id: kgdb.c,v 1.5 2004/10/07 13:59:08 starvik Exp $
|
||||
*! $Id: kgdb.c,v 1.6 2005/01/14 10:12:17 starvik Exp $
|
||||
*!
|
||||
*! (C) Copyright 1999, Axis Communications AB, LUND, SWEDEN
|
||||
*!
|
||||
|
@ -225,6 +229,7 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/linkage.h>
|
||||
#include <linux/reboot.h>
|
||||
|
||||
#include <asm/setup.h>
|
||||
#include <asm/ptrace.h>
|
||||
|
@ -1344,12 +1349,11 @@ handle_exception (int sigval)
|
|||
}
|
||||
}
|
||||
|
||||
/* The jump is to the address 0x00000002. Performs a complete re-start
|
||||
from scratch. */
|
||||
/* Performs a complete re-start from scratch. */
|
||||
static void
|
||||
kill_restart ()
|
||||
{
|
||||
__asm__ volatile ("jump 2");
|
||||
machine_restart("");
|
||||
}
|
||||
|
||||
/********************************** Breakpoint *******************************/
|
||||
|
@ -1506,6 +1510,11 @@ kgdb_handle_serial:
|
|||
bne goback
|
||||
nop
|
||||
|
||||
move.d [reg+0x5E], $r10 ; Get DCCR
|
||||
btstq 8, $r10 ; Test the U-flag.
|
||||
bmi goback
|
||||
nop
|
||||
|
||||
;;
|
||||
;; Handle the communication
|
||||
;;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: process.c,v 1.9 2004/10/19 13:07:37 starvik Exp $
|
||||
/* $Id: process.c,v 1.12 2004/12/27 11:18:32 starvik Exp $
|
||||
*
|
||||
* linux/arch/cris/kernel/process.c
|
||||
*
|
||||
|
@ -101,6 +101,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
|
|||
regs.r11 = (unsigned long)fn;
|
||||
regs.r12 = (unsigned long)arg;
|
||||
regs.irp = (unsigned long)kernel_thread_helper;
|
||||
regs.dccr = 1 << I_DCCR_BITNR;
|
||||
|
||||
/* Ok, create the new process.. */
|
||||
return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL);
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <linux/ptrace.h>
|
||||
#include <linux/user.h>
|
||||
#include <linux/signal.h>
|
||||
#include <linux/security.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/page.h>
|
||||
|
@ -86,9 +87,13 @@ sys_ptrace(long request, long pid, long addr, long data)
|
|||
ret = -EPERM;
|
||||
|
||||
if (request == PTRACE_TRACEME) {
|
||||
/* are we already being traced? */
|
||||
if (current->ptrace & PT_PTRACED)
|
||||
goto out;
|
||||
|
||||
ret = security_ptrace(current->parent, current);
|
||||
if (ret)
|
||||
goto out;
|
||||
/* set the ptrace bit in the process flags. */
|
||||
current->ptrace |= PT_PTRACED;
|
||||
ret = 0;
|
||||
goto out;
|
||||
|
@ -207,7 +212,7 @@ sys_ptrace(long request, long pid, long addr, long data)
|
|||
case PTRACE_KILL:
|
||||
ret = 0;
|
||||
|
||||
if (child->state == TASK_ZOMBIE)
|
||||
if (child->exit_state == EXIT_ZOMBIE)
|
||||
break;
|
||||
|
||||
child->exit_code = SIGKILL;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: shadows.c,v 1.1 2001/12/17 13:59:27 bjornw Exp $
|
||||
/* $Id: shadows.c,v 1.2 2004/12/13 12:21:51 starvik Exp $
|
||||
*
|
||||
* Various shadow registers. Defines for these are in include/asm-etrax100/io.h
|
||||
*/
|
||||
|
@ -6,6 +6,7 @@
|
|||
/* Shadows for internal Etrax-registers */
|
||||
|
||||
unsigned long genconfig_shadow;
|
||||
unsigned long gen_config_ii_shadow;
|
||||
unsigned long port_g_data_shadow;
|
||||
unsigned char port_pa_dir_shadow;
|
||||
unsigned char port_pa_data_shadow;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: traps.c,v 1.2 2003/07/04 08:27:41 starvik Exp $
|
||||
/* $Id: traps.c,v 1.4 2005/04/24 18:47:55 starvik Exp $
|
||||
*
|
||||
* linux/arch/cris/arch-v10/traps.c
|
||||
*
|
||||
|
@ -16,6 +16,8 @@
|
|||
#include <asm/uaccess.h>
|
||||
#include <asm/arch/sv_addr_ag.h>
|
||||
|
||||
extern int raw_printk(const char *fmt, ...);
|
||||
|
||||
void
|
||||
show_registers(struct pt_regs * regs)
|
||||
{
|
||||
|
@ -26,18 +28,18 @@ show_registers(struct pt_regs * regs)
|
|||
register. */
|
||||
unsigned long usp = rdusp();
|
||||
|
||||
printk("IRP: %08lx SRP: %08lx DCCR: %08lx USP: %08lx MOF: %08lx\n",
|
||||
raw_printk("IRP: %08lx SRP: %08lx DCCR: %08lx USP: %08lx MOF: %08lx\n",
|
||||
regs->irp, regs->srp, regs->dccr, usp, regs->mof );
|
||||
printk(" r0: %08lx r1: %08lx r2: %08lx r3: %08lx\n",
|
||||
raw_printk(" r0: %08lx r1: %08lx r2: %08lx r3: %08lx\n",
|
||||
regs->r0, regs->r1, regs->r2, regs->r3);
|
||||
printk(" r4: %08lx r5: %08lx r6: %08lx r7: %08lx\n",
|
||||
raw_printk(" r4: %08lx r5: %08lx r6: %08lx r7: %08lx\n",
|
||||
regs->r4, regs->r5, regs->r6, regs->r7);
|
||||
printk(" r8: %08lx r9: %08lx r10: %08lx r11: %08lx\n",
|
||||
raw_printk(" r8: %08lx r9: %08lx r10: %08lx r11: %08lx\n",
|
||||
regs->r8, regs->r9, regs->r10, regs->r11);
|
||||
printk("r12: %08lx r13: %08lx oR10: %08lx\n",
|
||||
regs->r12, regs->r13, regs->orig_r10);
|
||||
printk("R_MMU_CAUSE: %08lx\n", (unsigned long)*R_MMU_CAUSE);
|
||||
printk("Process %s (pid: %d, stackpage=%08lx)\n",
|
||||
raw_printk("r12: %08lx r13: %08lx oR10: %08lx sp: %08lx\n",
|
||||
regs->r12, regs->r13, regs->orig_r10, regs);
|
||||
raw_printk("R_MMU_CAUSE: %08lx\n", (unsigned long)*R_MMU_CAUSE);
|
||||
raw_printk("Process %s (pid: %d, stackpage=%08lx)\n",
|
||||
current->comm, current->pid, (unsigned long)current);
|
||||
|
||||
/*
|
||||
|
@ -53,7 +55,7 @@ show_registers(struct pt_regs * regs)
|
|||
if (usp != 0)
|
||||
show_stack (NULL, NULL);
|
||||
|
||||
printk("\nCode: ");
|
||||
raw_printk("\nCode: ");
|
||||
if(regs->irp < PAGE_OFFSET)
|
||||
goto bad;
|
||||
|
||||
|
@ -70,16 +72,16 @@ show_registers(struct pt_regs * regs)
|
|||
unsigned char c;
|
||||
if(__get_user(c, &((unsigned char*)regs->irp)[i])) {
|
||||
bad:
|
||||
printk(" Bad IP value.");
|
||||
raw_printk(" Bad IP value.");
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == 0)
|
||||
printk("(%02x) ", c);
|
||||
raw_printk("(%02x) ", c);
|
||||
else
|
||||
printk("%02x ", c);
|
||||
raw_printk("%02x ", c);
|
||||
}
|
||||
printk("\n");
|
||||
raw_printk("\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -121,7 +123,7 @@ die_if_kernel(const char * str, struct pt_regs * regs, long err)
|
|||
stop_watchdog();
|
||||
#endif
|
||||
|
||||
printk("%s: %04lx\n", str, err & 0xffff);
|
||||
raw_printk("%s: %04lx\n", str, err & 0xffff);
|
||||
|
||||
show_registers(regs);
|
||||
|
||||
|
@ -130,3 +132,8 @@ die_if_kernel(const char * str, struct pt_regs * regs, long err)
|
|||
#endif
|
||||
do_exit(SIGSEGV);
|
||||
}
|
||||
|
||||
void arch_enable_nmi(void)
|
||||
{
|
||||
asm volatile("setf m");
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <asm/uaccess.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/arch/svinto.h>
|
||||
#include <asm/mmu_context.h>
|
||||
|
||||
/* debug of low-level TLB reload */
|
||||
#undef DEBUG
|
||||
|
@ -24,8 +25,6 @@
|
|||
#define D(x)
|
||||
#endif
|
||||
|
||||
extern volatile pgd_t *current_pgd;
|
||||
|
||||
extern const struct exception_table_entry
|
||||
*search_exception_tables(unsigned long addr);
|
||||
|
||||
|
@ -46,7 +45,7 @@ handle_mmu_bus_fault(struct pt_regs *regs)
|
|||
int page_id;
|
||||
int acc, inv;
|
||||
#endif
|
||||
pgd_t* pgd = (pgd_t*)current_pgd;
|
||||
pgd_t* pgd = (pgd_t*)per_cpu(current_pgd, smp_processor_id());
|
||||
pmd_t *pmd;
|
||||
pte_t pte;
|
||||
int miss, we, writeac;
|
||||
|
@ -94,24 +93,3 @@ handle_mmu_bus_fault(struct pt_regs *regs)
|
|||
*R_TLB_LO = pte_val(pte);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
/* Called from arch/cris/mm/fault.c to find fixup code. */
|
||||
int
|
||||
find_fixup_code(struct pt_regs *regs)
|
||||
{
|
||||
const struct exception_table_entry *fixup;
|
||||
|
||||
if ((fixup = search_exception_tables(regs->irp)) != 0) {
|
||||
/* Adjust the instruction pointer in the stackframe. */
|
||||
regs->irp = fixup->fixup;
|
||||
|
||||
/*
|
||||
* Don't return by restoring the CPU state, so switch
|
||||
* frame-type.
|
||||
*/
|
||||
regs->frametype = CRIS_FRAME_NORMAL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ paging_init(void)
|
|||
* switch_mm)
|
||||
*/
|
||||
|
||||
current_pgd = init_mm.pgd;
|
||||
per_cpu(current_pgd, smp_processor_id()) = init_mm.pgd;
|
||||
|
||||
/* initialise the TLB (tlb.c) */
|
||||
|
||||
|
|
|
@ -139,53 +139,6 @@ flush_tlb_page(struct vm_area_struct *vma,
|
|||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
/* invalidate a page range */
|
||||
|
||||
void
|
||||
flush_tlb_range(struct vm_area_struct *vma,
|
||||
unsigned long start,
|
||||
unsigned long end)
|
||||
{
|
||||
struct mm_struct *mm = vma->vm_mm;
|
||||
int page_id = mm->context.page_id;
|
||||
int i;
|
||||
unsigned long flags;
|
||||
|
||||
D(printk("tlb: flush range %p<->%p in context %d (%p)\n",
|
||||
start, end, page_id, mm));
|
||||
|
||||
if(page_id == NO_CONTEXT)
|
||||
return;
|
||||
|
||||
start &= PAGE_MASK; /* probably not necessary */
|
||||
end &= PAGE_MASK; /* dito */
|
||||
|
||||
/* invalidate those TLB entries that match both the mm context
|
||||
* and the virtual address range
|
||||
*/
|
||||
|
||||
local_save_flags(flags);
|
||||
local_irq_disable();
|
||||
for(i = 0; i < NUM_TLB_ENTRIES; i++) {
|
||||
unsigned long tlb_hi, vpn;
|
||||
*R_TLB_SELECT = IO_FIELD(R_TLB_SELECT, index, i);
|
||||
tlb_hi = *R_TLB_HI;
|
||||
vpn = tlb_hi & PAGE_MASK;
|
||||
if (IO_EXTRACT(R_TLB_HI, page_id, tlb_hi) == page_id &&
|
||||
vpn >= start && vpn < end) {
|
||||
*R_TLB_HI = ( IO_FIELD(R_TLB_HI, page_id, INVALID_PAGEID ) |
|
||||
IO_FIELD(R_TLB_HI, vpn, i & 0xf ) );
|
||||
|
||||
*R_TLB_LO = ( IO_STATE(R_TLB_LO, global,no ) |
|
||||
IO_STATE(R_TLB_LO, valid, no ) |
|
||||
IO_STATE(R_TLB_LO, kernel,no ) |
|
||||
IO_STATE(R_TLB_LO, we, no ) |
|
||||
IO_FIELD(R_TLB_LO, pfn, 0 ) );
|
||||
}
|
||||
}
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
/* dump the entire TLB for debug purposes */
|
||||
|
||||
#if 0
|
||||
|
@ -237,7 +190,7 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next,
|
|||
* the pgd.
|
||||
*/
|
||||
|
||||
current_pgd = next->pgd;
|
||||
per_cpu(current_pgd, smp_processor_id()) = next->pgd;
|
||||
|
||||
/* switch context in the MMU */
|
||||
|
||||
|
|
|
@ -0,0 +1,296 @@
|
|||
config ETRAX_DRAM_VIRTUAL_BASE
|
||||
hex
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "c0000000"
|
||||
|
||||
config ETRAX_LED1G
|
||||
string "First green LED bit"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "PA3"
|
||||
help
|
||||
Bit to use for the first green LED (network LED).
|
||||
Most Axis products use bit A3 here.
|
||||
|
||||
config ETRAX_LED1R
|
||||
string "First red LED bit"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "PA4"
|
||||
help
|
||||
Bit to use for the first red LED (network LED).
|
||||
Most Axis products use bit A4 here.
|
||||
|
||||
config ETRAX_LED2G
|
||||
string "Second green LED bit"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "PA5"
|
||||
help
|
||||
Bit to use for the first green LED (status LED).
|
||||
Most Axis products use bit A5 here.
|
||||
|
||||
config ETRAX_LED2R
|
||||
string "Second red LED bit"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "PA6"
|
||||
help
|
||||
Bit to use for the first red LED (network LED).
|
||||
Most Axis products use bit A6 here.
|
||||
|
||||
config ETRAX_LED3G
|
||||
string "Third green LED bit"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "PA7"
|
||||
help
|
||||
Bit to use for the first green LED (drive/power LED).
|
||||
Most Axis products use bit A7 here.
|
||||
|
||||
config ETRAX_LED3R
|
||||
string "Third red LED bit"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "PA7"
|
||||
help
|
||||
Bit to use for the first red LED (drive/power LED).
|
||||
Most Axis products use bit A7 here.
|
||||
|
||||
choice
|
||||
prompt "Product debug-port"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default ETRAX_DEBUG_PORT0
|
||||
|
||||
config ETRAX_DEBUG_PORT0
|
||||
bool "Serial-0"
|
||||
help
|
||||
Choose a serial port for the ETRAX debug console. Default to
|
||||
port 0.
|
||||
|
||||
config ETRAX_DEBUG_PORT1
|
||||
bool "Serial-1"
|
||||
help
|
||||
Use serial port 1 for the console.
|
||||
|
||||
config ETRAX_DEBUG_PORT2
|
||||
bool "Serial-2"
|
||||
help
|
||||
Use serial port 2 for the console.
|
||||
|
||||
config ETRAX_DEBUG_PORT3
|
||||
bool "Serial-3"
|
||||
help
|
||||
Use serial port 3 for the console.
|
||||
|
||||
config ETRAX_DEBUG_PORT_NULL
|
||||
bool "disabled"
|
||||
help
|
||||
Disable serial-port debugging.
|
||||
|
||||
endchoice
|
||||
|
||||
choice
|
||||
prompt "Kernel GDB port"
|
||||
depends on ETRAX_KGDB
|
||||
default ETRAX_KGDB_PORT0
|
||||
help
|
||||
Choose a serial port for kernel debugging. NOTE: This port should
|
||||
not be enabled under Drivers for built-in interfaces (as it has its
|
||||
own initialization code) and should not be the same as the debug port.
|
||||
|
||||
config ETRAX_KGDB_PORT0
|
||||
bool "Serial-0"
|
||||
help
|
||||
Use serial port 0 for kernel debugging.
|
||||
|
||||
config ETRAX_KGDB_PORT1
|
||||
bool "Serial-1"
|
||||
help
|
||||
Use serial port 1 for kernel debugging.
|
||||
|
||||
config ETRAX_KGDB_PORT2
|
||||
bool "Serial-2"
|
||||
help
|
||||
Use serial port 2 for kernel debugging.
|
||||
|
||||
config ETRAX_KGDB_PORT3
|
||||
bool "Serial-3"
|
||||
help
|
||||
Use serial port 3 for kernel debugging.
|
||||
|
||||
endchoice
|
||||
|
||||
config ETRAX_MEM_GRP1_CONFIG
|
||||
hex "MEM_GRP1_CONFIG"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "4044a"
|
||||
help
|
||||
Waitstates for flash. The default value is suitable for the
|
||||
standard flashes used in axis products (120 ns).
|
||||
|
||||
config ETRAX_MEM_GRP2_CONFIG
|
||||
hex "MEM_GRP2_CONFIG"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "0"
|
||||
help
|
||||
Waitstates for SRAM. 0 is a good choice for most Axis products.
|
||||
|
||||
config ETRAX_MEM_GRP3_CONFIG
|
||||
hex "MEM_GRP3_CONFIG"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "0"
|
||||
help
|
||||
Waitstates for CSP0-3. 0 is a good choice for most Axis products.
|
||||
It may need to be changed if external devices such as extra
|
||||
register-mapped LEDs are used.
|
||||
|
||||
config ETRAX_MEM_GRP4_CONFIG
|
||||
hex "MEM_GRP4_CONFIG"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "0"
|
||||
help
|
||||
Waitstates for CSP4-6. 0 is a good choice for most Axis products.
|
||||
|
||||
config ETRAX_SDRAM_GRP0_CONFIG
|
||||
hex "SDRAM_GRP0_CONFIG"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "336"
|
||||
help
|
||||
SDRAM configuration for group 0. The value depends on the
|
||||
hardware configuration. The default value is suitable
|
||||
for 32 MB organized as two 16 bits chips (e.g. Axis
|
||||
part number 18550) connected as one 32 bit device (i.e. in
|
||||
the same group).
|
||||
|
||||
config ETRAX_SDRAM_GRP1_CONFIG
|
||||
hex "SDRAM_GRP1_CONFIG"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "0"
|
||||
help
|
||||
SDRAM configuration for group 1. The defult value is 0
|
||||
because group 1 is not used in the default configuration,
|
||||
described in the help for SDRAM_GRP0_CONFIG.
|
||||
|
||||
config ETRAX_SDRAM_TIMING
|
||||
hex "SDRAM_TIMING"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "104a"
|
||||
help
|
||||
SDRAM timing parameters. The default value is ok for
|
||||
most hardwares but large SDRAMs may require a faster
|
||||
refresh (a.k.a 8K refresh). The default value implies
|
||||
100MHz clock and SDR mode.
|
||||
|
||||
config ETRAX_SDRAM_COMMAND
|
||||
hex "SDRAM_COMMAND"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "0"
|
||||
help
|
||||
SDRAM command. Should be 0 unless you really know what
|
||||
you are doing (may be != 0 for unusual address line
|
||||
mappings such as in a MCM)..
|
||||
|
||||
config ETRAX_DEF_GIO_PA_OE
|
||||
hex "GIO_PA_OE"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "1c"
|
||||
help
|
||||
Configures the direction of general port A bits. 1 is out, 0 is in.
|
||||
This is often totally different depending on the product used.
|
||||
There are some guidelines though - if you know that only LED's are
|
||||
connected to port PA, then they are usually connected to bits 2-4
|
||||
and you can therefore use 1c. On other boards which don't have the
|
||||
LED's at the general ports, these bits are used for all kinds of
|
||||
stuff. If you don't know what to use, it is always safe to put all
|
||||
as inputs, although floating inputs isn't good.
|
||||
|
||||
config ETRAX_DEF_GIO_PA_OUT
|
||||
hex "GIO_PA_OUT"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "00"
|
||||
help
|
||||
Configures the initial data for the general port A bits. Most
|
||||
products should use 00 here.
|
||||
|
||||
config ETRAX_DEF_GIO_PB_OE
|
||||
hex "GIO_PB_OE"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "00000"
|
||||
help
|
||||
Configures the direction of general port B bits. 1 is out, 0 is in.
|
||||
This is often totally different depending on the product used.
|
||||
There are some guidelines though - if you know that only LED's are
|
||||
connected to port PA, then they are usually connected to bits 2-4
|
||||
and you can therefore use 1c. On other boards which don't have the
|
||||
LED's at the general ports, these bits are used for all kinds of
|
||||
stuff. If you don't know what to use, it is always safe to put all
|
||||
as inputs, although floating inputs isn't good.
|
||||
|
||||
config ETRAX_DEF_GIO_PB_OUT
|
||||
hex "GIO_PB_OUT"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "00000"
|
||||
help
|
||||
Configures the initial data for the general port B bits. Most
|
||||
products should use 00000 here.
|
||||
|
||||
config ETRAX_DEF_GIO_PC_OE
|
||||
hex "GIO_PC_OE"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "00000"
|
||||
help
|
||||
Configures the direction of general port C bits. 1 is out, 0 is in.
|
||||
This is often totally different depending on the product used.
|
||||
There are some guidelines though - if you know that only LED's are
|
||||
connected to port PA, then they are usually connected to bits 2-4
|
||||
and you can therefore use 1c. On other boards which don't have the
|
||||
LED's at the general ports, these bits are used for all kinds of
|
||||
stuff. If you don't know what to use, it is always safe to put all
|
||||
as inputs, although floating inputs isn't good.
|
||||
|
||||
config ETRAX_DEF_GIO_PC_OUT
|
||||
hex "GIO_PC_OUT"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "00000"
|
||||
help
|
||||
Configures the initial data for the general port C bits. Most
|
||||
products should use 00000 here.
|
||||
|
||||
config ETRAX_DEF_GIO_PD_OE
|
||||
hex "GIO_PD_OE"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "00000"
|
||||
help
|
||||
Configures the direction of general port D bits. 1 is out, 0 is in.
|
||||
This is often totally different depending on the product used.
|
||||
There are some guidelines though - if you know that only LED's are
|
||||
connected to port PA, then they are usually connected to bits 2-4
|
||||
and you can therefore use 1c. On other boards which don't have the
|
||||
LED's at the general ports, these bits are used for all kinds of
|
||||
stuff. If you don't know what to use, it is always safe to put all
|
||||
as inputs, although floating inputs isn't good.
|
||||
|
||||
config ETRAX_DEF_GIO_PD_OUT
|
||||
hex "GIO_PD_OUT"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "00000"
|
||||
help
|
||||
Configures the initial data for the general port D bits. Most
|
||||
products should use 00000 here.
|
||||
|
||||
config ETRAX_DEF_GIO_PE_OE
|
||||
hex "GIO_PE_OE"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "00000"
|
||||
help
|
||||
Configures the direction of general port E bits. 1 is out, 0 is in.
|
||||
This is often totally different depending on the product used.
|
||||
There are some guidelines though - if you know that only LED's are
|
||||
connected to port PA, then they are usually connected to bits 2-4
|
||||
and you can therefore use 1c. On other boards which don't have the
|
||||
LED's at the general ports, these bits are used for all kinds of
|
||||
stuff. If you don't know what to use, it is always safe to put all
|
||||
as inputs, although floating inputs isn't good.
|
||||
|
||||
config ETRAX_DEF_GIO_PE_OUT
|
||||
hex "GIO_PE_OUT"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "00000"
|
||||
help
|
||||
Configures the initial data for the general port E bits. Most
|
||||
products should use 00000 here.
|
|
@ -0,0 +1,14 @@
|
|||
#
|
||||
# arch/cris/arch-v32/boot/Makefile
|
||||
#
|
||||
target = $(target_boot_dir)
|
||||
src = $(src_boot_dir)
|
||||
|
||||
zImage: compressed/vmlinuz
|
||||
|
||||
compressed/vmlinuz: $(objtree)/vmlinux
|
||||
@$(MAKE) -f $(src)/compressed/Makefile $(objtree)/vmlinuz
|
||||
|
||||
clean:
|
||||
rm -f zImage tools/build compressed/vmlinux.out
|
||||
@$(MAKE) -f $(src)/compressed/Makefile clean
|
|
@ -0,0 +1,41 @@
|
|||
#
|
||||
# lx25/arch/cris/arch-v32/boot/compressed/Makefile
|
||||
#
|
||||
# create a compressed vmlinux image from the original vmlinux files and romfs
|
||||
#
|
||||
|
||||
target = $(target_compressed_dir)
|
||||
src = $(src_compressed_dir)
|
||||
|
||||
CC = gcc-cris -mlinux -march=v32 -I $(TOPDIR)/include
|
||||
CFLAGS = -O2
|
||||
LD = gcc-cris -mlinux -march=v32 -nostdlib
|
||||
OBJCOPY = objcopy-cris
|
||||
OBJCOPYFLAGS = -O binary --remove-section=.bss
|
||||
OBJECTS = $(target)/head.o $(target)/misc.o
|
||||
|
||||
# files to compress
|
||||
SYSTEM = $(objtree)/vmlinux.bin
|
||||
|
||||
all: vmlinuz
|
||||
|
||||
$(target)/decompress.bin: $(OBJECTS)
|
||||
$(LD) -T $(src)/decompress.ld -o $(target)/decompress.o $(OBJECTS)
|
||||
$(OBJCOPY) $(OBJCOPYFLAGS) $(target)/decompress.o $(target)/decompress.bin
|
||||
|
||||
$(objtree)/vmlinuz: $(target) piggy.img $(target)/decompress.bin
|
||||
cat $(target)/decompress.bin piggy.img > $(objtree)/vmlinuz
|
||||
rm -f piggy.img
|
||||
cp $(objtree)/vmlinuz $(src)
|
||||
|
||||
$(target)/head.o: $(src)/head.S
|
||||
$(CC) -D__ASSEMBLY__ -c $< -o $@
|
||||
|
||||
# gzip the kernel image
|
||||
|
||||
piggy.img: $(SYSTEM)
|
||||
cat $(SYSTEM) | gzip -f -9 > piggy.img
|
||||
|
||||
clean:
|
||||
rm -f piggy.img $(objtree)/vmlinuz vmlinuz.o decompress.o decompress.bin $(OBJECTS)
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
Creation of the self-extracting compressed kernel image (vmlinuz)
|
||||
-----------------------------------------------------------------
|
||||
$Id: README,v 1.1 2003/08/21 09:37:03 johana Exp $
|
||||
|
||||
This can be slightly confusing because it's a process with many steps.
|
||||
|
||||
The kernel object built by the arch/etrax100/Makefile, vmlinux, is split
|
||||
by that makefile into text and data binary files, vmlinux.text and
|
||||
vmlinux.data.
|
||||
|
||||
Those files together with a ROM filesystem can be catted together and
|
||||
burned into a flash or executed directly at the DRAM origin.
|
||||
|
||||
They can also be catted together and compressed with gzip, which is what
|
||||
happens in this makefile. Together they make up piggy.img.
|
||||
|
||||
The decompressor is built into the file decompress.o. It is turned into
|
||||
the binary file decompress.bin, which is catted together with piggy.img
|
||||
into the file vmlinuz. It can be executed in an arbitrary place in flash.
|
||||
|
||||
Be careful - it assumes some things about free locations in DRAM. It
|
||||
assumes the DRAM starts at 0x40000000 and that it is at least 8 MB,
|
||||
so it puts its code at 0x40700000, and initial stack at 0x40800000.
|
||||
|
||||
-Bjorn
|
|
@ -0,0 +1,30 @@
|
|||
/*#OUTPUT_FORMAT(elf32-us-cris) */
|
||||
OUTPUT_ARCH (crisv32)
|
||||
|
||||
MEMORY
|
||||
{
|
||||
dram : ORIGIN = 0x40700000,
|
||||
LENGTH = 0x00100000
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text :
|
||||
{
|
||||
_stext = . ;
|
||||
*(.text)
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
_etext = . ;
|
||||
} > dram
|
||||
.data :
|
||||
{
|
||||
*(.data)
|
||||
_edata = . ;
|
||||
} > dram
|
||||
.bss :
|
||||
{
|
||||
*(.bss)
|
||||
_end = ALIGN( 0x10 ) ;
|
||||
} > dram
|
||||
}
|
|
@ -0,0 +1,193 @@
|
|||
/*
|
||||
* Code that sets up the DRAM registers, calls the
|
||||
* decompressor to unpack the piggybacked kernel, and jumps.
|
||||
*
|
||||
* Copyright (C) 1999 - 2003, Axis Communications AB
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#define ASSEMBLER_MACROS_ONLY
|
||||
#include <asm/arch/hwregs/asm/reg_map_asm.h>
|
||||
#include <asm/arch/hwregs/asm/gio_defs_asm.h>
|
||||
#include <asm/arch/hwregs/asm/config_defs_asm.h>
|
||||
|
||||
#define RAM_INIT_MAGIC 0x56902387
|
||||
#define COMMAND_LINE_MAGIC 0x87109563
|
||||
|
||||
;; Exported symbols
|
||||
|
||||
.globl input_data
|
||||
|
||||
.text
|
||||
start:
|
||||
di
|
||||
|
||||
;; Start clocks for used blocks.
|
||||
move.d REG_ADDR(config, regi_config, rw_clk_ctrl), $r1
|
||||
move.d [$r1], $r0
|
||||
or.d REG_STATE(config, rw_clk_ctrl, cpu, yes) | \
|
||||
REG_STATE(config, rw_clk_ctrl, bif, yes) | \
|
||||
REG_STATE(config, rw_clk_ctrl, fix_io, yes), $r0
|
||||
move.d $r0, [$r1]
|
||||
|
||||
;; If booting from NAND flash we first have to copy some
|
||||
;; data from NAND flash to internal RAM to get the code
|
||||
;; that initializes the SDRAM. Lets copy 20 KB. This
|
||||
;; code executes at 0x38010000 if booting from NAND and
|
||||
;; we are guaranted that at least 0x200 bytes are good so
|
||||
;; lets start from there. The first 8192 bytes in the nand
|
||||
;; flash is spliced with zeroes and is thus 16384 bytes.
|
||||
move.d 0x38010200, $r10
|
||||
move.d 0x14200, $r11 ; Start offset in NAND flash 0x10200 + 16384
|
||||
move.d 0x5000, $r12 ; Length of copy
|
||||
|
||||
;; Before this code the tools add a partitiontable so the PC
|
||||
;; has an offset from the linked address.
|
||||
offset1:
|
||||
lapcq ., $r13 ; get PC
|
||||
add.d first_copy_complete-offset1, $r13
|
||||
|
||||
#include "../../lib/nand_init.S"
|
||||
|
||||
first_copy_complete:
|
||||
;; Initialze the DRAM registers.
|
||||
cmp.d RAM_INIT_MAGIC, $r8 ; Already initialized?
|
||||
beq dram_init_finished
|
||||
nop
|
||||
|
||||
#include "../../lib/dram_init.S"
|
||||
|
||||
dram_init_finished:
|
||||
lapcq ., $r13 ; get PC
|
||||
add.d second_copy_complete-dram_init_finished, $r13
|
||||
|
||||
move.d REG_ADDR(config, regi_config, r_bootsel), $r0
|
||||
move.d [$r0], $r0
|
||||
and.d REG_MASK(config, r_bootsel, boot_mode), $r0
|
||||
cmp.d REG_STATE(config, r_bootsel, boot_mode, nand), $r0
|
||||
bne second_copy_complete ; No NAND boot
|
||||
nop
|
||||
|
||||
;; Copy 2MB from NAND flash to SDRAM (at 2-4MB into the SDRAM)
|
||||
move.d 0x40204000, $r10
|
||||
move.d 0x8000, $r11
|
||||
move.d 0x200000, $r12
|
||||
ba copy_nand_to_ram
|
||||
nop
|
||||
second_copy_complete:
|
||||
|
||||
;; Initiate the PA port.
|
||||
move.d CONFIG_ETRAX_DEF_GIO_PA_OUT, $r0
|
||||
move.d REG_ADDR(gio, regi_gio, rw_pa_dout), $r1
|
||||
move.d $r0, [$r1]
|
||||
|
||||
move.d CONFIG_ETRAX_DEF_GIO_PA_OE, $r0
|
||||
move.d REG_ADDR(gio, regi_gio, rw_pa_oe), $r1
|
||||
move.d $r0, [$r1]
|
||||
|
||||
;; Setup the stack to a suitably high address.
|
||||
;; We assume 8 MB is the minimum DRAM and put
|
||||
;; the SP at the top for now.
|
||||
|
||||
move.d 0x40800000, $sp
|
||||
|
||||
;; Figure out where the compressed piggyback image is
|
||||
;; in the flash (since we wont try to copy it to DRAM
|
||||
;; before unpacking). It is at _edata, but in flash.
|
||||
;; Use (_edata - herami) as offset to the current PC.
|
||||
|
||||
move.d REG_ADDR(config, regi_config, r_bootsel), $r0
|
||||
move.d [$r0], $r0
|
||||
and.d REG_MASK(config, r_bootsel, boot_mode), $r0
|
||||
cmp.d REG_STATE(config, r_bootsel, boot_mode, nand), $r0
|
||||
beq hereami2
|
||||
nop
|
||||
hereami:
|
||||
lapcq ., $r5 ; get PC
|
||||
and.d 0x7fffffff, $r5 ; strip any non-cache bit
|
||||
move.d $r5, $r0 ; save for later - flash address of 'herami'
|
||||
add.d _edata, $r5
|
||||
sub.d hereami, $r5 ; r5 = flash address of '_edata'
|
||||
move.d hereami, $r1 ; destination
|
||||
ba 2f
|
||||
nop
|
||||
hereami2:
|
||||
lapcq ., $r5 ; get PC
|
||||
and.d 0x00ffffff, $r5 ; strip any non-cache bit
|
||||
move.d $r5, $r6
|
||||
or.d 0x40200000, $r6
|
||||
move.d $r6, $r0 ; save for later - flash address of 'herami'
|
||||
add.d _edata, $r5
|
||||
sub.d hereami2, $r5 ; r5 = flash address of '_edata'
|
||||
add.d 0x40200000, $r5
|
||||
move.d hereami2, $r1 ; destination
|
||||
2:
|
||||
;; Copy text+data to DRAM
|
||||
|
||||
move.d _edata, $r2 ; end destination
|
||||
1: move.w [$r0+], $r3
|
||||
move.w $r3, [$r1+]
|
||||
cmp.d $r2, $r1
|
||||
bcs 1b
|
||||
nop
|
||||
|
||||
move.d input_data, $r0 ; for the decompressor
|
||||
move.d $r5, [$r0] ; for the decompressor
|
||||
|
||||
;; Clear the decompressors BSS (between _edata and _end)
|
||||
|
||||
moveq 0, $r0
|
||||
move.d _edata, $r1
|
||||
move.d _end, $r2
|
||||
1: move.w $r0, [$r1+]
|
||||
cmp.d $r2, $r1
|
||||
bcs 1b
|
||||
nop
|
||||
|
||||
;; Save command line magic and address.
|
||||
move.d _cmd_line_magic, $r12
|
||||
move.d $r10, [$r12]
|
||||
move.d _cmd_line_addr, $r12
|
||||
move.d $r11, [$r12]
|
||||
|
||||
;; Do the decompression and save compressed size in _inptr
|
||||
|
||||
jsr decompress_kernel
|
||||
nop
|
||||
|
||||
;; Restore command line magic and address.
|
||||
move.d _cmd_line_magic, $r10
|
||||
move.d [$r10], $r10
|
||||
move.d _cmd_line_addr, $r11
|
||||
move.d [$r11], $r11
|
||||
|
||||
;; Put start address of root partition in r9 so the kernel can use it
|
||||
;; when mounting from flash
|
||||
move.d input_data, $r0
|
||||
move.d [$r0], $r9 ; flash address of compressed kernel
|
||||
move.d inptr, $r0
|
||||
add.d [$r0], $r9 ; size of compressed kernel
|
||||
cmp.d 0x40200000, $r9
|
||||
blo enter_kernel
|
||||
nop
|
||||
sub.d 0x40200000, $r9
|
||||
add.d 0x4000, $r9
|
||||
|
||||
enter_kernel:
|
||||
;; Enter the decompressed kernel
|
||||
move.d RAM_INIT_MAGIC, $r8 ; Tell kernel that DRAM is initialized
|
||||
jump 0x40004000 ; kernel is linked to this address
|
||||
nop
|
||||
|
||||
.data
|
||||
|
||||
input_data:
|
||||
.dword 0 ; used by the decompressor
|
||||
_cmd_line_magic:
|
||||
.dword 0
|
||||
_cmd_line_addr:
|
||||
.dword 0
|
||||
is_nand_boot:
|
||||
.dword 0
|
||||
|
||||
#include "../../lib/hw_settings.S"
|
|
@ -0,0 +1,318 @@
|
|||
/*
|
||||
* misc.c
|
||||
*
|
||||
* $Id: misc.c,v 1.8 2005/04/24 18:34:29 starvik Exp $
|
||||
*
|
||||
* This is a collection of several routines from gzip-1.0.3
|
||||
* adapted for Linux.
|
||||
*
|
||||
* malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
|
||||
* puts by Nick Holloway 1993, better puts by Martin Mares 1995
|
||||
* adoptation for Linux/CRIS Axis Communications AB, 1999
|
||||
*
|
||||
*/
|
||||
|
||||
/* where the piggybacked kernel image expects itself to live.
|
||||
* it is the same address we use when we network load an uncompressed
|
||||
* image into DRAM, and it is the address the kernel is linked to live
|
||||
* at by vmlinux.lds.S
|
||||
*/
|
||||
|
||||
#define KERNEL_LOAD_ADR 0x40004000
|
||||
|
||||
#include <linux/config.h>
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <asm/arch/hwregs/reg_rdwr.h>
|
||||
#include <asm/arch/hwregs/reg_map.h>
|
||||
#include <asm/arch/hwregs/ser_defs.h>
|
||||
|
||||
/*
|
||||
* gzip declarations
|
||||
*/
|
||||
|
||||
#define OF(args) args
|
||||
#define STATIC static
|
||||
|
||||
void* memset(void* s, int c, size_t n);
|
||||
void* memcpy(void* __dest, __const void* __src,
|
||||
size_t __n);
|
||||
|
||||
#define memzero(s, n) memset ((s), 0, (n))
|
||||
|
||||
|
||||
typedef unsigned char uch;
|
||||
typedef unsigned short ush;
|
||||
typedef unsigned long ulg;
|
||||
|
||||
#define WSIZE 0x8000 /* Window size must be at least 32k, */
|
||||
/* and a power of two */
|
||||
|
||||
static uch *inbuf; /* input buffer */
|
||||
static uch window[WSIZE]; /* Sliding window buffer */
|
||||
|
||||
unsigned inptr = 0; /* index of next byte to be processed in inbuf
|
||||
* After decompression it will contain the
|
||||
* compressed size, and head.S will read it.
|
||||
*/
|
||||
|
||||
static unsigned outcnt = 0; /* bytes in output buffer */
|
||||
|
||||
/* gzip flag byte */
|
||||
#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
|
||||
#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
|
||||
#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
|
||||
#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
|
||||
#define COMMENT 0x10 /* bit 4 set: file comment present */
|
||||
#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */
|
||||
#define RESERVED 0xC0 /* bit 6,7: reserved */
|
||||
|
||||
#define get_byte() inbuf[inptr++]
|
||||
|
||||
/* Diagnostic functions */
|
||||
#ifdef DEBUG
|
||||
# define Assert(cond,msg) {if(!(cond)) error(msg);}
|
||||
# define Trace(x) fprintf x
|
||||
# define Tracev(x) {if (verbose) fprintf x ;}
|
||||
# define Tracevv(x) {if (verbose>1) fprintf x ;}
|
||||
# define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
|
||||
# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
|
||||
#else
|
||||
# define Assert(cond,msg)
|
||||
# define Trace(x)
|
||||
# define Tracev(x)
|
||||
# define Tracevv(x)
|
||||
# define Tracec(c,x)
|
||||
# define Tracecv(c,x)
|
||||
#endif
|
||||
|
||||
static int fill_inbuf(void);
|
||||
static void flush_window(void);
|
||||
static void error(char *m);
|
||||
static void gzip_mark(void **);
|
||||
static void gzip_release(void **);
|
||||
|
||||
extern char *input_data; /* lives in head.S */
|
||||
|
||||
static long bytes_out = 0;
|
||||
static uch *output_data;
|
||||
static unsigned long output_ptr = 0;
|
||||
|
||||
static void *malloc(int size);
|
||||
static void free(void *where);
|
||||
static void error(char *m);
|
||||
static void gzip_mark(void **);
|
||||
static void gzip_release(void **);
|
||||
|
||||
static void puts(const char *);
|
||||
|
||||
/* the "heap" is put directly after the BSS ends, at end */
|
||||
|
||||
extern int _end;
|
||||
static long free_mem_ptr = (long)&_end;
|
||||
|
||||
#include "../../../../../lib/inflate.c"
|
||||
|
||||
static void *malloc(int size)
|
||||
{
|
||||
void *p;
|
||||
|
||||
if (size <0) error("Malloc error");
|
||||
|
||||
free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */
|
||||
|
||||
p = (void *)free_mem_ptr;
|
||||
free_mem_ptr += size;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static void free(void *where)
|
||||
{ /* Don't care */
|
||||
}
|
||||
|
||||
static void gzip_mark(void **ptr)
|
||||
{
|
||||
*ptr = (void *) free_mem_ptr;
|
||||
}
|
||||
|
||||
static void gzip_release(void **ptr)
|
||||
{
|
||||
free_mem_ptr = (long) *ptr;
|
||||
}
|
||||
|
||||
/* decompressor info and error messages to serial console */
|
||||
|
||||
static inline void
|
||||
serout(const char *s, reg_scope_instances regi_ser)
|
||||
{
|
||||
reg_ser_rs_stat_din rs;
|
||||
reg_ser_rw_dout dout = {.data = *s};
|
||||
|
||||
do {
|
||||
rs = REG_RD(ser, regi_ser, rs_stat_din);
|
||||
}
|
||||
while (!rs.tr_rdy);/* Wait for tranceiver. */
|
||||
|
||||
REG_WR(ser, regi_ser, rw_dout, dout);
|
||||
}
|
||||
|
||||
static void
|
||||
puts(const char *s)
|
||||
{
|
||||
#ifndef CONFIG_ETRAX_DEBUG_PORT_NULL
|
||||
while (*s) {
|
||||
#ifdef CONFIG_ETRAX_DEBUG_PORT0
|
||||
serout(s, regi_ser0);
|
||||
#endif
|
||||
#ifdef CONFIG_ETRAX_DEBUG_PORT1
|
||||
serout(s, regi_ser1);
|
||||
#endif
|
||||
#ifdef CONFIG_ETRAX_DEBUG_PORT2
|
||||
serout(s, regi_ser2);
|
||||
#endif
|
||||
#ifdef CONFIG_ETRAX_DEBUG_PORT3
|
||||
serout(s, regi_ser3);
|
||||
#endif
|
||||
*s++;
|
||||
}
|
||||
/* CONFIG_ETRAX_DEBUG_PORT_NULL */
|
||||
#endif
|
||||
}
|
||||
|
||||
void*
|
||||
memset(void* s, int c, size_t n)
|
||||
{
|
||||
int i;
|
||||
char *ss = (char*)s;
|
||||
|
||||
for (i=0;i<n;i++) ss[i] = c;
|
||||
}
|
||||
|
||||
void*
|
||||
memcpy(void* __dest, __const void* __src,
|
||||
size_t __n)
|
||||
{
|
||||
int i;
|
||||
char *d = (char *)__dest, *s = (char *)__src;
|
||||
|
||||
for (i=0;i<__n;i++) d[i] = s[i];
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
* Write the output window window[0..outcnt-1] and update crc and bytes_out.
|
||||
* (Used for the decompressed data only.)
|
||||
*/
|
||||
|
||||
static void
|
||||
flush_window()
|
||||
{
|
||||
ulg c = crc; /* temporary variable */
|
||||
unsigned n;
|
||||
uch *in, *out, ch;
|
||||
|
||||
in = window;
|
||||
out = &output_data[output_ptr];
|
||||
for (n = 0; n < outcnt; n++) {
|
||||
ch = *out++ = *in++;
|
||||
c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
|
||||
}
|
||||
crc = c;
|
||||
bytes_out += (ulg)outcnt;
|
||||
output_ptr += (ulg)outcnt;
|
||||
outcnt = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
error(char *x)
|
||||
{
|
||||
puts("\n\n");
|
||||
puts(x);
|
||||
puts("\n\n -- System halted\n");
|
||||
|
||||
while(1); /* Halt */
|
||||
}
|
||||
|
||||
void
|
||||
setup_normal_output_buffer()
|
||||
{
|
||||
output_data = (char *)KERNEL_LOAD_ADR;
|
||||
}
|
||||
|
||||
static inline void
|
||||
serial_setup(reg_scope_instances regi_ser)
|
||||
{
|
||||
reg_ser_rw_xoff xoff;
|
||||
reg_ser_rw_tr_ctrl tr_ctrl;
|
||||
reg_ser_rw_rec_ctrl rec_ctrl;
|
||||
reg_ser_rw_tr_baud_div tr_baud;
|
||||
reg_ser_rw_rec_baud_div rec_baud;
|
||||
|
||||
/* Turn off XOFF. */
|
||||
xoff = REG_RD(ser, regi_ser, rw_xoff);
|
||||
|
||||
xoff.chr = 0;
|
||||
xoff.automatic = regk_ser_no;
|
||||
|
||||
REG_WR(ser, regi_ser, rw_xoff, xoff);
|
||||
|
||||
/* Set baudrate and stopbits. */
|
||||
tr_ctrl = REG_RD(ser, regi_ser, rw_tr_ctrl);
|
||||
rec_ctrl = REG_RD(ser, regi_ser, rw_rec_ctrl);
|
||||
tr_baud = REG_RD(ser, regi_ser, rw_tr_baud_div);
|
||||
rec_baud = REG_RD(ser, regi_ser, rw_rec_baud_div);
|
||||
|
||||
tr_ctrl.stop_bits = 1; /* 2 stop bits. */
|
||||
|
||||
/*
|
||||
* The baudrate setup is a bit fishy, but in the end the tranceiver is
|
||||
* set to 4800 and the receiver to 115200. The magic value is
|
||||
* 29.493 MHz.
|
||||
*/
|
||||
tr_ctrl.base_freq = regk_ser_f29_493;
|
||||
rec_ctrl.base_freq = regk_ser_f29_493;
|
||||
tr_baud.div = (29493000 / 8) / 4800;
|
||||
rec_baud.div = (29493000 / 8) / 115200;
|
||||
|
||||
REG_WR(ser, regi_ser, rw_tr_ctrl, tr_ctrl);
|
||||
REG_WR(ser, regi_ser, rw_tr_baud_div, tr_baud);
|
||||
REG_WR(ser, regi_ser, rw_rec_ctrl, rec_ctrl);
|
||||
REG_WR(ser, regi_ser, rw_rec_baud_div, rec_baud);
|
||||
}
|
||||
|
||||
void
|
||||
decompress_kernel()
|
||||
{
|
||||
char revision;
|
||||
|
||||
/* input_data is set in head.S */
|
||||
inbuf = input_data;
|
||||
|
||||
#ifdef CONFIG_ETRAX_DEBUG_PORT0
|
||||
serial_setup(regi_ser0);
|
||||
#endif
|
||||
#ifdef CONFIG_ETRAX_DEBUG_PORT1
|
||||
serial_setup(regi_ser1);
|
||||
#endif
|
||||
#ifdef CONFIG_ETRAX_DEBUG_PORT2
|
||||
serial_setup(regi_ser2);
|
||||
#endif
|
||||
#ifdef CONFIG_ETRAX_DEBUG_PORT3
|
||||
serial_setup(regi_ser3);
|
||||
#endif
|
||||
|
||||
setup_normal_output_buffer();
|
||||
|
||||
makecrc();
|
||||
|
||||
__asm__ volatile ("move $vr,%0" : "=rm" (revision));
|
||||
if (revision < 32)
|
||||
{
|
||||
puts("You need an ETRAX FS to run Linux 2.6/crisv32.\n");
|
||||
while(1);
|
||||
}
|
||||
|
||||
puts("Uncompressing Linux...\n");
|
||||
gunzip();
|
||||
puts("Done. Now booting the kernel.\n");
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
#
|
||||
# Makefile for rescue code
|
||||
#
|
||||
target = $(target_rescue_dir)
|
||||
src = $(src_rescue_dir)
|
||||
|
||||
CC = gcc-cris -mlinux -march=v32 $(LINUXINCLUDE)
|
||||
CFLAGS = -O2
|
||||
LD = gcc-cris -mlinux -march=v32 -nostdlib
|
||||
OBJCOPY = objcopy-cris
|
||||
OBJCOPYFLAGS = -O binary --remove-section=.bss
|
||||
|
||||
all: $(target)/rescue.bin
|
||||
|
||||
rescue: rescue.bin
|
||||
# do nothing
|
||||
|
||||
$(target)/rescue.bin: $(target) $(target)/head.o
|
||||
$(LD) -T $(src)/rescue.ld -o $(target)/rescue.o $(target)/head.o
|
||||
$(OBJCOPY) $(OBJCOPYFLAGS) $(target)/rescue.o $(target)/rescue.bin
|
||||
cp -p $(target)/rescue.bin $(objtree)
|
||||
|
||||
$(target):
|
||||
mkdir -p $(target)
|
||||
|
||||
$(target)/head.o: $(src)/head.S
|
||||
$(CC) -D__ASSEMBLY__ -c $< -o $*.o
|
||||
|
||||
clean:
|
||||
rm -f $(target)/*.o $(target)/*.bin
|
||||
|
||||
fastdep:
|
||||
|
||||
modules:
|
||||
|
||||
modules-install:
|
|
@ -0,0 +1,39 @@
|
|||
/* $Id: head.S,v 1.4 2004/11/01 16:10:28 starvik Exp $
|
||||
*
|
||||
* This used to be the rescue code but now that is handled by the
|
||||
* RedBoot based RFL instead. Nothing to see here, move along.
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <asm/arch/hwregs/reg_map_asm.h>
|
||||
#include <asm/arch/hwregs/config_defs_asm.h>
|
||||
|
||||
.text
|
||||
|
||||
;; Start clocks for used blocks.
|
||||
move.d REG_ADDR(config, regi_config, rw_clk_ctrl), $r1
|
||||
move.d [$r1], $r0
|
||||
or.d REG_STATE(config, rw_clk_ctrl, cpu, yes) | \
|
||||
REG_STATE(config, rw_clk_ctrl, bif, yes) | \
|
||||
REG_STATE(config, rw_clk_ctrl, fix_io, yes), $r0
|
||||
move.d $r0, [$r1]
|
||||
|
||||
;; Copy 68KB NAND flash to Internal RAM (if NAND boot)
|
||||
move.d 0x38004000, $r10
|
||||
move.d 0x8000, $r11
|
||||
move.d 0x11000, $r12
|
||||
move.d copy_complete, $r13
|
||||
and.d 0x000fffff, $r13
|
||||
or.d 0x38000000, $r13
|
||||
|
||||
#include "../../lib/nand_init.S"
|
||||
|
||||
;; No NAND found
|
||||
move.d CONFIG_ETRAX_PTABLE_SECTOR, $r10
|
||||
jump $r10 ; Jump to decompresser
|
||||
nop
|
||||
|
||||
copy_complete:
|
||||
move.d 0x38000000 + CONFIG_ETRAX_PTABLE_SECTOR, $r10
|
||||
jump $r10 ; Jump to decompresser
|
||||
nop
|
|
@ -0,0 +1,20 @@
|
|||
MEMORY
|
||||
{
|
||||
flash : ORIGIN = 0x00000000,
|
||||
LENGTH = 0x00100000
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text :
|
||||
{
|
||||
stext = . ;
|
||||
*(.text)
|
||||
etext = . ;
|
||||
} > flash
|
||||
.data :
|
||||
{
|
||||
*(.data)
|
||||
edata = . ;
|
||||
} > flash
|
||||
}
|
|
@ -0,0 +1,625 @@
|
|||
config ETRAX_ETHERNET
|
||||
bool "Ethernet support"
|
||||
depends on ETRAX_ARCH_V32
|
||||
select NET_ETHERNET
|
||||
help
|
||||
This option enables the ETRAX FS built-in 10/100Mbit Ethernet
|
||||
controller.
|
||||
|
||||
config ETRAX_ETHERNET_HW_CSUM
|
||||
bool "Hardware accelerated ethernet checksum and scatter/gather"
|
||||
depends on ETRAX_ETHERNET
|
||||
depends on ETRAX_STREAMCOPROC
|
||||
default y
|
||||
help
|
||||
Hardware acceleration of checksumming and scatter/gather
|
||||
|
||||
config ETRAX_ETHERNET_IFACE0
|
||||
depends on ETRAX_ETHERNET
|
||||
bool "Enable network interface 0"
|
||||
|
||||
config ETRAX_ETHERNET_IFACE1
|
||||
depends on ETRAX_ETHERNET
|
||||
bool "Enable network interface 1 (uses DMA6 and DMA7)"
|
||||
|
||||
choice
|
||||
prompt "Network LED behavior"
|
||||
depends on ETRAX_ETHERNET
|
||||
default ETRAX_NETWORK_LED_ON_WHEN_ACTIVITY
|
||||
|
||||
config ETRAX_NETWORK_LED_ON_WHEN_LINK
|
||||
bool "LED_on_when_link"
|
||||
help
|
||||
Selecting LED_on_when_link will light the LED when there is a
|
||||
connection and will flash off when there is activity.
|
||||
|
||||
Selecting LED_on_when_activity will light the LED only when
|
||||
there is activity.
|
||||
|
||||
This setting will also affect the behaviour of other activity LEDs
|
||||
e.g. Bluetooth.
|
||||
|
||||
config ETRAX_NETWORK_LED_ON_WHEN_ACTIVITY
|
||||
bool "LED_on_when_activity"
|
||||
help
|
||||
Selecting LED_on_when_link will light the LED when there is a
|
||||
connection and will flash off when there is activity.
|
||||
|
||||
Selecting LED_on_when_activity will light the LED only when
|
||||
there is activity.
|
||||
|
||||
This setting will also affect the behaviour of other activity LEDs
|
||||
e.g. Bluetooth.
|
||||
|
||||
endchoice
|
||||
|
||||
config ETRAXFS_SERIAL
|
||||
bool "Serial-port support"
|
||||
depends on ETRAX_ARCH_V32
|
||||
help
|
||||
Enables the ETRAX FS serial driver for ser0 (ttyS0)
|
||||
You probably want this enabled.
|
||||
|
||||
config ETRAX_SERIAL_PORT0
|
||||
bool "Serial port 0 enabled"
|
||||
depends on ETRAXFS_SERIAL
|
||||
help
|
||||
Enables the ETRAX FS serial driver for ser0 (ttyS0)
|
||||
Normally you want this on. You can control what DMA channels to use
|
||||
if you do not need DMA to something else.
|
||||
ser0 can use dma4 or dma6 for output and dma5 or dma7 for input.
|
||||
|
||||
choice
|
||||
prompt "Ser0 DMA in channel "
|
||||
depends on ETRAX_SERIAL_PORT0
|
||||
default ETRAX_SERIAL_PORT0_NO_DMA_IN
|
||||
help
|
||||
What DMA channel to use for ser0.
|
||||
|
||||
|
||||
config ETRAX_SERIAL_PORT0_NO_DMA_IN
|
||||
bool "Ser0 uses no DMA for input"
|
||||
help
|
||||
Do not use DMA for ser0 input.
|
||||
|
||||
config ETRAX_SERIAL_PORT0_DMA7_IN
|
||||
bool "Ser0 uses DMA7 for input"
|
||||
depends on ETRAX_SERIAL_PORT0
|
||||
help
|
||||
Enables the DMA7 input channel for ser0 (ttyS0).
|
||||
If you do not enable DMA, an interrupt for each character will be
|
||||
used when receiveing data.
|
||||
Normally you want to use DMA, unless you use the DMA channel for
|
||||
something else.
|
||||
|
||||
endchoice
|
||||
|
||||
choice
|
||||
prompt "Ser0 DMA out channel"
|
||||
depends on ETRAX_SERIAL_PORT0
|
||||
default ETRAX_SERIAL_PORT0_NO_DMA_OUT
|
||||
|
||||
config ETRAX_SERIAL_PORT0_NO_DMA_OUT
|
||||
bool "Ser0 uses no DMA for output"
|
||||
help
|
||||
Do not use DMA for ser0 output.
|
||||
|
||||
config ETRAX_SERIAL_PORT0_DMA6_OUT
|
||||
bool "Ser0 uses DMA6 for output"
|
||||
depends on ETRAX_SERIAL_PORT0
|
||||
help
|
||||
Enables the DMA6 output channel for ser0 (ttyS0).
|
||||
If you do not enable DMA, an interrupt for each character will be
|
||||
used when transmitting data.
|
||||
Normally you want to use DMA, unless you use the DMA channel for
|
||||
something else.
|
||||
|
||||
endchoice
|
||||
|
||||
config ETRAX_SER0_DTR_BIT
|
||||
string "Ser 0 DTR bit (empty = not used)"
|
||||
depends on ETRAX_SERIAL_PORT0
|
||||
|
||||
config ETRAX_SER0_RI_BIT
|
||||
string "Ser 0 RI bit (empty = not used)"
|
||||
depends on ETRAX_SERIAL_PORT0
|
||||
|
||||
config ETRAX_SER0_DSR_BIT
|
||||
string "Ser 0 DSR bit (empty = not used)"
|
||||
depends on ETRAX_SERIAL_PORT0
|
||||
|
||||
config ETRAX_SER0_CD_BIT
|
||||
string "Ser 0 CD bit (empty = not used)"
|
||||
depends on ETRAX_SERIAL_PORT0
|
||||
|
||||
config ETRAX_SERIAL_PORT1
|
||||
bool "Serial port 1 enabled"
|
||||
depends on ETRAXFS_SERIAL
|
||||
help
|
||||
Enables the ETRAX FS serial driver for ser1 (ttyS1).
|
||||
|
||||
choice
|
||||
prompt "Ser1 DMA in channel "
|
||||
depends on ETRAX_SERIAL_PORT1
|
||||
default ETRAX_SERIAL_PORT1_NO_DMA_IN
|
||||
help
|
||||
What DMA channel to use for ser1.
|
||||
|
||||
|
||||
config ETRAX_SERIAL_PORT1_NO_DMA_IN
|
||||
bool "Ser1 uses no DMA for input"
|
||||
help
|
||||
Do not use DMA for ser1 input.
|
||||
|
||||
config ETRAX_SERIAL_PORT1_DMA5_IN
|
||||
bool "Ser1 uses DMA5 for input"
|
||||
depends on ETRAX_SERIAL_PORT1
|
||||
help
|
||||
Enables the DMA5 input channel for ser1 (ttyS1).
|
||||
If you do not enable DMA, an interrupt for each character will be
|
||||
used when receiveing data.
|
||||
Normally you want this on, unless you use the DMA channel for
|
||||
something else.
|
||||
|
||||
endchoice
|
||||
|
||||
choice
|
||||
prompt "Ser1 DMA out channel "
|
||||
depends on ETRAX_SERIAL_PORT1
|
||||
default ETRAX_SERIAL_PORT1_NO_DMA_OUT
|
||||
help
|
||||
What DMA channel to use for ser1.
|
||||
|
||||
config ETRAX_SERIAL_PORT1_NO_DMA_OUT
|
||||
bool "Ser1 uses no DMA for output"
|
||||
help
|
||||
Do not use DMA for ser1 output.
|
||||
|
||||
config ETRAX_SERIAL_PORT1_DMA4_OUT
|
||||
bool "Ser1 uses DMA4 for output"
|
||||
depends on ETRAX_SERIAL_PORT1
|
||||
help
|
||||
Enables the DMA4 output channel for ser1 (ttyS1).
|
||||
If you do not enable DMA, an interrupt for each character will be
|
||||
used when transmitting data.
|
||||
Normally you want this on, unless you use the DMA channel for
|
||||
something else.
|
||||
|
||||
endchoice
|
||||
|
||||
config ETRAX_SER1_DTR_BIT
|
||||
string "Ser 1 DTR bit (empty = not used)"
|
||||
depends on ETRAX_SERIAL_PORT1
|
||||
|
||||
config ETRAX_SER1_RI_BIT
|
||||
string "Ser 1 RI bit (empty = not used)"
|
||||
depends on ETRAX_SERIAL_PORT1
|
||||
|
||||
config ETRAX_SER1_DSR_BIT
|
||||
string "Ser 1 DSR bit (empty = not used)"
|
||||
depends on ETRAX_SERIAL_PORT1
|
||||
|
||||
config ETRAX_SER1_CD_BIT
|
||||
string "Ser 1 CD bit (empty = not used)"
|
||||
depends on ETRAX_SERIAL_PORT1
|
||||
|
||||
config ETRAX_SERIAL_PORT2
|
||||
bool "Serial port 2 enabled"
|
||||
depends on ETRAXFS_SERIAL
|
||||
help
|
||||
Enables the ETRAX FS serial driver for ser2 (ttyS2).
|
||||
|
||||
choice
|
||||
prompt "Ser2 DMA in channel "
|
||||
depends on ETRAX_SERIAL_PORT2
|
||||
default ETRAX_SERIAL_PORT2_NO_DMA_IN
|
||||
help
|
||||
What DMA channel to use for ser2.
|
||||
|
||||
|
||||
config ETRAX_SERIAL_PORT2_NO_DMA_IN
|
||||
bool "Ser2 uses no DMA for input"
|
||||
help
|
||||
Do not use DMA for ser2 input.
|
||||
|
||||
config ETRAX_SERIAL_PORT2_DMA3_IN
|
||||
bool "Ser2 uses DMA3 for input"
|
||||
depends on ETRAX_SERIAL_PORT2
|
||||
help
|
||||
Enables the DMA3 input channel for ser2 (ttyS2).
|
||||
If you do not enable DMA, an interrupt for each character will be
|
||||
used when receiveing data.
|
||||
Normally you want to use DMA, unless you use the DMA channel for
|
||||
something else.
|
||||
|
||||
endchoice
|
||||
|
||||
choice
|
||||
prompt "Ser2 DMA out channel"
|
||||
depends on ETRAX_SERIAL_PORT2
|
||||
default ETRAX_SERIAL_PORT2_NO_DMA_OUT
|
||||
|
||||
config ETRAX_SERIAL_PORT2_NO_DMA_OUT
|
||||
bool "Ser2 uses no DMA for output"
|
||||
help
|
||||
Do not use DMA for ser2 output.
|
||||
|
||||
config ETRAX_SERIAL_PORT2_DMA2_OUT
|
||||
bool "Ser2 uses DMA2 for output"
|
||||
depends on ETRAX_SERIAL_PORT2
|
||||
help
|
||||
Enables the DMA2 output channel for ser2 (ttyS2).
|
||||
If you do not enable DMA, an interrupt for each character will be
|
||||
used when transmitting data.
|
||||
Normally you want to use DMA, unless you use the DMA channel for
|
||||
something else.
|
||||
|
||||
endchoice
|
||||
|
||||
config ETRAX_SER2_DTR_BIT
|
||||
string "Ser 2 DTR bit (empty = not used)"
|
||||
depends on ETRAX_SERIAL_PORT2
|
||||
|
||||
config ETRAX_SER2_RI_BIT
|
||||
string "Ser 2 RI bit (empty = not used)"
|
||||
depends on ETRAX_SERIAL_PORT2
|
||||
|
||||
config ETRAX_SER2_DSR_BIT
|
||||
string "Ser 2 DSR bit (empty = not used)"
|
||||
depends on ETRAX_SERIAL_PORT2
|
||||
|
||||
config ETRAX_SER2_CD_BIT
|
||||
string "Ser 2 CD bit (empty = not used)"
|
||||
depends on ETRAX_SERIAL_PORT2
|
||||
|
||||
config ETRAX_SERIAL_PORT3
|
||||
bool "Serial port 3 enabled"
|
||||
depends on ETRAXFS_SERIAL
|
||||
help
|
||||
Enables the ETRAX FS serial driver for ser3 (ttyS3).
|
||||
|
||||
choice
|
||||
prompt "Ser3 DMA in channel "
|
||||
depends on ETRAX_SERIAL_PORT3
|
||||
default ETRAX_SERIAL_PORT3_NO_DMA_IN
|
||||
help
|
||||
What DMA channel to use for ser3.
|
||||
|
||||
|
||||
config ETRAX_SERIAL_PORT3_NO_DMA_IN
|
||||
bool "Ser3 uses no DMA for input"
|
||||
help
|
||||
Do not use DMA for ser3 input.
|
||||
|
||||
config ETRAX_SERIAL_PORT3_DMA9_IN
|
||||
bool "Ser3 uses DMA9 for input"
|
||||
depends on ETRAX_SERIAL_PORT3
|
||||
help
|
||||
Enables the DMA9 input channel for ser3 (ttyS3).
|
||||
If you do not enable DMA, an interrupt for each character will be
|
||||
used when receiveing data.
|
||||
Normally you want to use DMA, unless you use the DMA channel for
|
||||
something else.
|
||||
|
||||
endchoice
|
||||
|
||||
choice
|
||||
prompt "Ser3 DMA out channel"
|
||||
depends on ETRAX_SERIAL_PORT3
|
||||
default ETRAX_SERIAL_PORT3_NO_DMA_OUT
|
||||
|
||||
config ETRAX_SERIAL_PORT3_NO_DMA_OUT
|
||||
bool "Ser3 uses no DMA for output"
|
||||
help
|
||||
Do not use DMA for ser3 output.
|
||||
|
||||
config ETRAX_SERIAL_PORT3_DMA8_OUT
|
||||
bool "Ser3 uses DMA8 for output"
|
||||
depends on ETRAX_SERIAL_PORT3
|
||||
help
|
||||
Enables the DMA8 output channel for ser3 (ttyS3).
|
||||
If you do not enable DMA, an interrupt for each character will be
|
||||
used when transmitting data.
|
||||
Normally you want to use DMA, unless you use the DMA channel for
|
||||
something else.
|
||||
|
||||
endchoice
|
||||
|
||||
config ETRAX_SER3_DTR_BIT
|
||||
string "Ser 3 DTR bit (empty = not used)"
|
||||
depends on ETRAX_SERIAL_PORT3
|
||||
|
||||
config ETRAX_SER3_RI_BIT
|
||||
string "Ser 3 RI bit (empty = not used)"
|
||||
depends on ETRAX_SERIAL_PORT3
|
||||
|
||||
config ETRAX_SER3_DSR_BIT
|
||||
string "Ser 3 DSR bit (empty = not used)"
|
||||
depends on ETRAX_SERIAL_PORT3
|
||||
|
||||
config ETRAX_SER3_CD_BIT
|
||||
string "Ser 3 CD bit (empty = not used)"
|
||||
depends on ETRAX_SERIAL_PORT3
|
||||
|
||||
config ETRAX_RS485
|
||||
bool "RS-485 support"
|
||||
depends on ETRAX_SERIAL
|
||||
help
|
||||
Enables support for RS-485 serial communication. For a primer on
|
||||
RS-485, see <http://www.hw.cz/english/docs/rs485/rs485.html>.
|
||||
|
||||
config ETRAX_RS485_DISABLE_RECEIVER
|
||||
bool "Disable serial receiver"
|
||||
depends on ETRAX_RS485
|
||||
help
|
||||
It is necessary to disable the serial receiver to avoid serial
|
||||
loopback. Not all products are able to do this in software only.
|
||||
Axis 2400/2401 must disable receiver.
|
||||
|
||||
config ETRAX_AXISFLASHMAP
|
||||
bool "Axis flash-map support"
|
||||
depends on ETRAX_ARCH_V32
|
||||
select MTD
|
||||
select MTD_CFI
|
||||
select MTD_CFI_AMDSTD
|
||||
select MTD_OBSOLETE_CHIPS
|
||||
select MTD_AMDSTD
|
||||
select MTD_CHAR
|
||||
select MTD_BLOCK
|
||||
select MTD_PARTITIONS
|
||||
select MTD_CONCAT
|
||||
select MTD_COMPLEX_MAPPINGS
|
||||
help
|
||||
This option enables MTD mapping of flash devices. Needed to use
|
||||
flash memories. If unsure, say Y.
|
||||
|
||||
config ETRAX_SYNCHRONOUS_SERIAL
|
||||
bool "Synchronous serial-port support"
|
||||
depends on ETRAX_ARCH_V32
|
||||
help
|
||||
Enables the ETRAX FS synchronous serial driver.
|
||||
|
||||
config ETRAX_SYNCHRONOUS_SERIAL_PORT0
|
||||
bool "Synchronous serial port 0 enabled"
|
||||
depends on ETRAX_SYNCHRONOUS_SERIAL
|
||||
help
|
||||
Enabled synchronous serial port 0.
|
||||
|
||||
config ETRAX_SYNCHRONOUS_SERIAL0_DMA
|
||||
bool "Enable DMA on synchronous serial port 0."
|
||||
depends on ETRAX_SYNCHRONOUS_SERIAL_PORT0
|
||||
help
|
||||
A synchronous serial port can run in manual or DMA mode.
|
||||
Selecting this option will make it run in DMA mode.
|
||||
|
||||
config ETRAX_SYNCHRONOUS_SERIAL_PORT1
|
||||
bool "Synchronous serial port 1 enabled"
|
||||
depends on ETRAX_SYNCHRONOUS_SERIAL
|
||||
help
|
||||
Enabled synchronous serial port 1.
|
||||
|
||||
config ETRAX_SYNCHRONOUS_SERIAL1_DMA
|
||||
bool "Enable DMA on synchronous serial port 1."
|
||||
depends on ETRAX_SYNCHRONOUS_SERIAL_PORT1
|
||||
help
|
||||
A synchronous serial port can run in manual or DMA mode.
|
||||
Selecting this option will make it run in DMA mode.
|
||||
|
||||
config ETRAX_PTABLE_SECTOR
|
||||
int "Byte-offset of partition table sector"
|
||||
depends on ETRAX_AXISFLASHMAP
|
||||
default "65536"
|
||||
help
|
||||
Byte-offset of the partition table in the first flash chip.
|
||||
The default value is 64kB and should not be changed unless
|
||||
you know exactly what you are doing. The only valid reason
|
||||
for changing this is when the flash block size is bigger
|
||||
than 64kB (e.g. when using two parallel 16 bit flashes).
|
||||
|
||||
config ETRAX_NANDFLASH
|
||||
bool "NAND flash support"
|
||||
depends on ETRAX_ARCH_V32
|
||||
select MTD_NAND
|
||||
select MTD_NAND_IDS
|
||||
help
|
||||
This option enables MTD mapping of NAND flash devices. Needed to use
|
||||
NAND flash memories. If unsure, say Y.
|
||||
|
||||
config ETRAX_I2C
|
||||
bool "I2C driver"
|
||||
depends on ETRAX_ARCH_V32
|
||||
help
|
||||
This option enabled the I2C driver used by e.g. the RTC driver.
|
||||
|
||||
config ETRAX_I2C_DATA_PORT
|
||||
string "I2C data pin"
|
||||
depends on ETRAX_I2C
|
||||
help
|
||||
The pin to use for I2C data.
|
||||
|
||||
config ETRAX_I2C_CLK_PORT
|
||||
string "I2C clock pin"
|
||||
depends on ETRAX_I2C
|
||||
help
|
||||
The pin to use for I2C clock.
|
||||
|
||||
config ETRAX_RTC
|
||||
bool "Real Time Clock support"
|
||||
depends on ETRAX_ARCH_V32
|
||||
help
|
||||
Enabled RTC support.
|
||||
|
||||
choice
|
||||
prompt "RTC chip"
|
||||
depends on ETRAX_RTC
|
||||
default ETRAX_PCF8563
|
||||
|
||||
config ETRAX_PCF8563
|
||||
bool "PCF8563"
|
||||
help
|
||||
Philips PCF8563 RTC
|
||||
|
||||
endchoice
|
||||
|
||||
config ETRAX_GPIO
|
||||
bool "GPIO support"
|
||||
depends on ETRAX_ARCH_V32
|
||||
---help---
|
||||
Enables the ETRAX general port device (major 120, minors 0-4).
|
||||
You can use this driver to access the general port bits. It supports
|
||||
these ioctl's:
|
||||
#include <linux/etraxgpio.h>
|
||||
fd = open("/dev/gpioa", O_RDWR); // or /dev/gpiob
|
||||
ioctl(fd, _IO(ETRAXGPIO_IOCTYPE, IO_SETBITS), bits_to_set);
|
||||
ioctl(fd, _IO(ETRAXGPIO_IOCTYPE, IO_CLRBITS), bits_to_clear);
|
||||
err = ioctl(fd, _IO(ETRAXGPIO_IOCTYPE, IO_READ_INBITS), &val);
|
||||
Remember that you need to setup the port directions appropriately in
|
||||
the General configuration.
|
||||
|
||||
config ETRAX_PA_BUTTON_BITMASK
|
||||
hex "PA-buttons bitmask"
|
||||
depends on ETRAX_GPIO
|
||||
default "0x02"
|
||||
help
|
||||
This is a bitmask (8 bits) with information about what bits on PA
|
||||
that are used for buttons.
|
||||
Most products has a so called TEST button on PA1, if that is true
|
||||
use 0x02 here.
|
||||
Use 00 if there are no buttons on PA.
|
||||
If the bitmask is <> 00 a button driver will be included in the gpio
|
||||
driver. ETRAX general I/O support must be enabled.
|
||||
|
||||
config ETRAX_PA_CHANGEABLE_DIR
|
||||
hex "PA user changeable dir mask"
|
||||
depends on ETRAX_GPIO
|
||||
default "0x00"
|
||||
help
|
||||
This is a bitmask (8 bits) with information of what bits in PA that a
|
||||
user can change direction on using ioctl's.
|
||||
Bit set = changeable.
|
||||
You probably want 0x00 here, but it depends on your hardware.
|
||||
|
||||
config ETRAX_PA_CHANGEABLE_BITS
|
||||
hex "PA user changeable bits mask"
|
||||
depends on ETRAX_GPIO
|
||||
default "0x00"
|
||||
help
|
||||
This is a bitmask (8 bits) with information of what bits in PA
|
||||
that a user can change the value on using ioctl's.
|
||||
Bit set = changeable.
|
||||
|
||||
config ETRAX_PB_CHANGEABLE_DIR
|
||||
hex "PB user changeable dir mask"
|
||||
depends on ETRAX_GPIO
|
||||
default "0x00000"
|
||||
help
|
||||
This is a bitmask (18 bits) with information of what bits in PB
|
||||
that a user can change direction on using ioctl's.
|
||||
Bit set = changeable.
|
||||
You probably want 0x00000 here, but it depends on your hardware.
|
||||
|
||||
config ETRAX_PB_CHANGEABLE_BITS
|
||||
hex "PB user changeable bits mask"
|
||||
depends on ETRAX_GPIO
|
||||
default "0x00000"
|
||||
help
|
||||
This is a bitmask (18 bits) with information of what bits in PB
|
||||
that a user can change the value on using ioctl's.
|
||||
Bit set = changeable.
|
||||
|
||||
config ETRAX_PC_CHANGEABLE_DIR
|
||||
hex "PC user changeable dir mask"
|
||||
depends on ETRAX_GPIO
|
||||
default "0x00000"
|
||||
help
|
||||
This is a bitmask (18 bits) with information of what bits in PC
|
||||
that a user can change direction on using ioctl's.
|
||||
Bit set = changeable.
|
||||
You probably want 0x00000 here, but it depends on your hardware.
|
||||
|
||||
config ETRAX_PC_CHANGEABLE_BITS
|
||||
hex "PC user changeable bits mask"
|
||||
depends on ETRAX_GPIO
|
||||
default "0x00000"
|
||||
help
|
||||
This is a bitmask (18 bits) with information of what bits in PC
|
||||
that a user can change the value on using ioctl's.
|
||||
Bit set = changeable.
|
||||
|
||||
config ETRAX_PD_CHANGEABLE_DIR
|
||||
hex "PD user changeable dir mask"
|
||||
depends on ETRAX_GPIO
|
||||
default "0x00000"
|
||||
help
|
||||
This is a bitmask (18 bits) with information of what bits in PD
|
||||
that a user can change direction on using ioctl's.
|
||||
Bit set = changeable.
|
||||
You probably want 0x00000 here, but it depends on your hardware.
|
||||
|
||||
config ETRAX_PD_CHANGEABLE_BITS
|
||||
hex "PD user changeable bits mask"
|
||||
depends on ETRAX_GPIO
|
||||
default "0x00000"
|
||||
help
|
||||
This is a bitmask (18 bits) with information of what bits in PD
|
||||
that a user can change the value on using ioctl's.
|
||||
Bit set = changeable.
|
||||
|
||||
config ETRAX_PE_CHANGEABLE_DIR
|
||||
hex "PE user changeable dir mask"
|
||||
depends on ETRAX_GPIO
|
||||
default "0x00000"
|
||||
help
|
||||
This is a bitmask (18 bits) with information of what bits in PE
|
||||
that a user can change direction on using ioctl's.
|
||||
Bit set = changeable.
|
||||
You probably want 0x00000 here, but it depends on your hardware.
|
||||
|
||||
config ETRAX_PE_CHANGEABLE_BITS
|
||||
hex "PE user changeable bits mask"
|
||||
depends on ETRAX_GPIO
|
||||
default "0x00000"
|
||||
help
|
||||
This is a bitmask (18 bits) with information of what bits in PE
|
||||
that a user can change the value on using ioctl's.
|
||||
Bit set = changeable.
|
||||
|
||||
config ETRAX_IDE
|
||||
bool "ATA/IDE support"
|
||||
depends on ETRAX_ARCH_V32
|
||||
select IDE
|
||||
select BLK_DEV_IDE
|
||||
select BLK_DEV_IDEDISK
|
||||
select BLK_DEV_IDECD
|
||||
select BLK_DEV_IDEDMA
|
||||
help
|
||||
Enables the ETRAX IDE driver.
|
||||
|
||||
config ETRAX_CARDBUS
|
||||
bool "Cardbus support"
|
||||
depends on ETRAX_ARCH_V32
|
||||
select PCCARD
|
||||
select CARDBUS
|
||||
select HOTPLUG
|
||||
select PCCARD_NONSTATIC
|
||||
help
|
||||
Enabled the ETRAX Carbus driver.
|
||||
|
||||
config PCI
|
||||
bool
|
||||
depends on ETRAX_CARDBUS
|
||||
default y
|
||||
|
||||
config ETRAX_IOP_FW_LOAD
|
||||
tristate "IO-processor hotplug firmware loading support"
|
||||
depends on ETRAX_ARCH_V32
|
||||
select FW_LOADER
|
||||
help
|
||||
Enables IO-processor hotplug firmware loading support.
|
||||
|
||||
config ETRAX_STREAMCOPROC
|
||||
tristate "Stream co-processor driver enabled"
|
||||
depends on ETRAX_ARCH_V32
|
||||
help
|
||||
This option enables a driver for the stream co-processor
|
||||
for cryptographic operations.
|
|
@ -0,0 +1,13 @@
|
|||
#
|
||||
# Makefile for Etrax-specific drivers
|
||||
#
|
||||
|
||||
obj-$(CONFIG_ETRAX_STREAMCOPROC) += cryptocop.o
|
||||
obj-$(CONFIG_ETRAX_AXISFLASHMAP) += axisflashmap.o
|
||||
obj-$(CONFIG_ETRAX_NANDFLASH) += nandflash.o
|
||||
obj-$(CONFIG_ETRAX_GPIO) += gpio.o
|
||||
obj-$(CONFIG_ETRAX_IOP_FW_LOAD) += iop_fw_load.o
|
||||
obj-$(CONFIG_ETRAX_PCF8563) += pcf8563.o
|
||||
obj-$(CONFIG_ETRAX_I2C) += i2c.o
|
||||
obj-$(CONFIG_ETRAX_SYNCHRONOUS_SERIAL) += sync_serial.o
|
||||
obj-$(CONFIG_PCI) += pci/
|
|
@ -0,0 +1,455 @@
|
|||
/*
|
||||
* Physical mapping layer for MTD using the Axis partitiontable format
|
||||
*
|
||||
* Copyright (c) 2001, 2002, 2003 Axis Communications AB
|
||||
*
|
||||
* This file is under the GPL.
|
||||
*
|
||||
* First partition is always sector 0 regardless of if we find a partitiontable
|
||||
* or not. In the start of the next sector, there can be a partitiontable that
|
||||
* tells us what other partitions to define. If there isn't, we use a default
|
||||
* partition split defined below.
|
||||
*
|
||||
* Copy of os/lx25/arch/cris/arch-v10/drivers/axisflashmap.c 1.5
|
||||
* with minor changes.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/config.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <linux/mtd/concat.h>
|
||||
#include <linux/mtd/map.h>
|
||||
#include <linux/mtd/mtd.h>
|
||||
#include <linux/mtd/mtdram.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
|
||||
#include <asm/arch/hwregs/config_defs.h>
|
||||
#include <asm/axisflashmap.h>
|
||||
#include <asm/mmu.h>
|
||||
|
||||
#define MEM_CSE0_SIZE (0x04000000)
|
||||
#define MEM_CSE1_SIZE (0x04000000)
|
||||
|
||||
#define FLASH_UNCACHED_ADDR KSEG_E
|
||||
#define FLASH_CACHED_ADDR KSEG_F
|
||||
|
||||
#if CONFIG_ETRAX_FLASH_BUSWIDTH==1
|
||||
#define flash_data __u8
|
||||
#elif CONFIG_ETRAX_FLASH_BUSWIDTH==2
|
||||
#define flash_data __u16
|
||||
#elif CONFIG_ETRAX_FLASH_BUSWIDTH==4
|
||||
#define flash_data __u16
|
||||
#endif
|
||||
|
||||
/* From head.S */
|
||||
extern unsigned long romfs_start, romfs_length, romfs_in_flash;
|
||||
|
||||
/* The master mtd for the entire flash. */
|
||||
struct mtd_info* axisflash_mtd = NULL;
|
||||
|
||||
/* Map driver functions. */
|
||||
|
||||
static map_word flash_read(struct map_info *map, unsigned long ofs)
|
||||
{
|
||||
map_word tmp;
|
||||
tmp.x[0] = *(flash_data *)(map->map_priv_1 + ofs);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static void flash_copy_from(struct map_info *map, void *to,
|
||||
unsigned long from, ssize_t len)
|
||||
{
|
||||
memcpy(to, (void *)(map->map_priv_1 + from), len);
|
||||
}
|
||||
|
||||
static void flash_write(struct map_info *map, map_word d, unsigned long adr)
|
||||
{
|
||||
*(flash_data *)(map->map_priv_1 + adr) = (flash_data)d.x[0];
|
||||
}
|
||||
|
||||
/*
|
||||
* The map for chip select e0.
|
||||
*
|
||||
* We run into tricky coherence situations if we mix cached with uncached
|
||||
* accesses to we only use the uncached version here.
|
||||
*
|
||||
* The size field is the total size where the flash chips may be mapped on the
|
||||
* chip select. MTD probes should find all devices there and it does not matter
|
||||
* if there are unmapped gaps or aliases (mirrors of flash devices). The MTD
|
||||
* probes will ignore them.
|
||||
*
|
||||
* The start address in map_priv_1 is in virtual memory so we cannot use
|
||||
* MEM_CSE0_START but must rely on that FLASH_UNCACHED_ADDR is the start
|
||||
* address of cse0.
|
||||
*/
|
||||
static struct map_info map_cse0 = {
|
||||
.name = "cse0",
|
||||
.size = MEM_CSE0_SIZE,
|
||||
.bankwidth = CONFIG_ETRAX_FLASH_BUSWIDTH,
|
||||
.read = flash_read,
|
||||
.copy_from = flash_copy_from,
|
||||
.write = flash_write,
|
||||
.map_priv_1 = FLASH_UNCACHED_ADDR
|
||||
};
|
||||
|
||||
/*
|
||||
* The map for chip select e1.
|
||||
*
|
||||
* If there was a gap between cse0 and cse1, map_priv_1 would get the wrong
|
||||
* address, but there isn't.
|
||||
*/
|
||||
static struct map_info map_cse1 = {
|
||||
.name = "cse1",
|
||||
.size = MEM_CSE1_SIZE,
|
||||
.bankwidth = CONFIG_ETRAX_FLASH_BUSWIDTH,
|
||||
.read = flash_read,
|
||||
.copy_from = flash_copy_from,
|
||||
.write = flash_write,
|
||||
.map_priv_1 = FLASH_UNCACHED_ADDR + MEM_CSE0_SIZE
|
||||
};
|
||||
|
||||
/* If no partition-table was found, we use this default-set. */
|
||||
#define MAX_PARTITIONS 7
|
||||
#define NUM_DEFAULT_PARTITIONS 3
|
||||
|
||||
/*
|
||||
* Default flash size is 2MB. CONFIG_ETRAX_PTABLE_SECTOR is most likely the
|
||||
* size of one flash block and "filesystem"-partition needs 5 blocks to be able
|
||||
* to use JFFS.
|
||||
*/
|
||||
static struct mtd_partition axis_default_partitions[NUM_DEFAULT_PARTITIONS] = {
|
||||
{
|
||||
.name = "boot firmware",
|
||||
.size = CONFIG_ETRAX_PTABLE_SECTOR,
|
||||
.offset = 0
|
||||
},
|
||||
{
|
||||
.name = "kernel",
|
||||
.size = 0x200000 - (6 * CONFIG_ETRAX_PTABLE_SECTOR),
|
||||
.offset = CONFIG_ETRAX_PTABLE_SECTOR
|
||||
},
|
||||
{
|
||||
.name = "filesystem",
|
||||
.size = 5 * CONFIG_ETRAX_PTABLE_SECTOR,
|
||||
.offset = 0x200000 - (5 * CONFIG_ETRAX_PTABLE_SECTOR)
|
||||
}
|
||||
};
|
||||
|
||||
/* Initialize the ones normally used. */
|
||||
static struct mtd_partition axis_partitions[MAX_PARTITIONS] = {
|
||||
{
|
||||
.name = "part0",
|
||||
.size = CONFIG_ETRAX_PTABLE_SECTOR,
|
||||
.offset = 0
|
||||
},
|
||||
{
|
||||
.name = "part1",
|
||||
.size = 0,
|
||||
.offset = 0
|
||||
},
|
||||
{
|
||||
.name = "part2",
|
||||
.size = 0,
|
||||
.offset = 0
|
||||
},
|
||||
{
|
||||
.name = "part3",
|
||||
.size = 0,
|
||||
.offset = 0
|
||||
},
|
||||
{
|
||||
.name = "part4",
|
||||
.size = 0,
|
||||
.offset = 0
|
||||
},
|
||||
{
|
||||
.name = "part5",
|
||||
.size = 0,
|
||||
.offset = 0
|
||||
},
|
||||
{
|
||||
.name = "part6",
|
||||
.size = 0,
|
||||
.offset = 0
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* Probe a chip select for AMD-compatible (JEDEC) or CFI-compatible flash
|
||||
* chips in that order (because the amd_flash-driver is faster).
|
||||
*/
|
||||
static struct mtd_info *probe_cs(struct map_info *map_cs)
|
||||
{
|
||||
struct mtd_info *mtd_cs = NULL;
|
||||
|
||||
printk(KERN_INFO
|
||||
"%s: Probing a 0x%08lx bytes large window at 0x%08lx.\n",
|
||||
map_cs->name, map_cs->size, map_cs->map_priv_1);
|
||||
|
||||
#ifdef CONFIG_MTD_AMDSTD
|
||||
mtd_cs = do_map_probe("amd_flash", map_cs);
|
||||
#endif
|
||||
#ifdef CONFIG_MTD_CFI
|
||||
if (!mtd_cs) {
|
||||
mtd_cs = do_map_probe("cfi_probe", map_cs);
|
||||
}
|
||||
#endif
|
||||
|
||||
return mtd_cs;
|
||||
}
|
||||
|
||||
/*
|
||||
* Probe each chip select individually for flash chips. If there are chips on
|
||||
* both cse0 and cse1, the mtd_info structs will be concatenated to one struct
|
||||
* so that MTD partitions can cross chip boundries.
|
||||
*
|
||||
* The only known restriction to how you can mount your chips is that each
|
||||
* chip select must hold similar flash chips. But you need external hardware
|
||||
* to do that anyway and you can put totally different chips on cse0 and cse1
|
||||
* so it isn't really much of a restriction.
|
||||
*/
|
||||
extern struct mtd_info* __init crisv32_nand_flash_probe (void);
|
||||
static struct mtd_info *flash_probe(void)
|
||||
{
|
||||
struct mtd_info *mtd_cse0;
|
||||
struct mtd_info *mtd_cse1;
|
||||
struct mtd_info *mtd_nand = NULL;
|
||||
struct mtd_info *mtd_total;
|
||||
struct mtd_info *mtds[3];
|
||||
int count = 0;
|
||||
|
||||
if ((mtd_cse0 = probe_cs(&map_cse0)) != NULL)
|
||||
mtds[count++] = mtd_cse0;
|
||||
if ((mtd_cse1 = probe_cs(&map_cse1)) != NULL)
|
||||
mtds[count++] = mtd_cse1;
|
||||
|
||||
#ifdef CONFIG_ETRAX_NANDFLASH
|
||||
if ((mtd_nand = crisv32_nand_flash_probe()) != NULL)
|
||||
mtds[count++] = mtd_nand;
|
||||
#endif
|
||||
|
||||
if (!mtd_cse0 && !mtd_cse1 && !mtd_nand) {
|
||||
/* No chip found. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (count > 1) {
|
||||
#ifdef CONFIG_MTD_CONCAT
|
||||
/* Since the concatenation layer adds a small overhead we
|
||||
* could try to figure out if the chips in cse0 and cse1 are
|
||||
* identical and reprobe the whole cse0+cse1 window. But since
|
||||
* flash chips are slow, the overhead is relatively small.
|
||||
* So we use the MTD concatenation layer instead of further
|
||||
* complicating the probing procedure.
|
||||
*/
|
||||
mtd_total = mtd_concat_create(mtds,
|
||||
count,
|
||||
"cse0+cse1+nand");
|
||||
#else
|
||||
printk(KERN_ERR "%s and %s: Cannot concatenate due to kernel "
|
||||
"(mis)configuration!\n", map_cse0.name, map_cse1.name);
|
||||
mtd_toal = NULL;
|
||||
#endif
|
||||
if (!mtd_total) {
|
||||
printk(KERN_ERR "%s and %s: Concatenation failed!\n",
|
||||
map_cse0.name, map_cse1.name);
|
||||
|
||||
/* The best we can do now is to only use what we found
|
||||
* at cse0.
|
||||
*/
|
||||
mtd_total = mtd_cse0;
|
||||
map_destroy(mtd_cse1);
|
||||
}
|
||||
} else {
|
||||
mtd_total = mtd_cse0? mtd_cse0 : mtd_cse1 ? mtd_cse1 : mtd_nand;
|
||||
|
||||
}
|
||||
|
||||
return mtd_total;
|
||||
}
|
||||
|
||||
extern unsigned long crisv32_nand_boot;
|
||||
extern unsigned long crisv32_nand_cramfs_offset;
|
||||
|
||||
/*
|
||||
* Probe the flash chip(s) and, if it succeeds, read the partition-table
|
||||
* and register the partitions with MTD.
|
||||
*/
|
||||
static int __init init_axis_flash(void)
|
||||
{
|
||||
struct mtd_info *mymtd;
|
||||
int err = 0;
|
||||
int pidx = 0;
|
||||
struct partitiontable_head *ptable_head = NULL;
|
||||
struct partitiontable_entry *ptable;
|
||||
int use_default_ptable = 1; /* Until proven otherwise. */
|
||||
const char *pmsg = KERN_INFO " /dev/flash%d at 0x%08x, size 0x%08x\n";
|
||||
static char page[512];
|
||||
size_t len;
|
||||
|
||||
#ifndef CONFIG_ETRAXFS_SIM
|
||||
mymtd = flash_probe();
|
||||
mymtd->read(mymtd, CONFIG_ETRAX_PTABLE_SECTOR, 512, &len, page);
|
||||
ptable_head = (struct partitiontable_head *)(page + PARTITION_TABLE_OFFSET);
|
||||
|
||||
if (!mymtd) {
|
||||
/* There's no reason to use this module if no flash chip can
|
||||
* be identified. Make sure that's understood.
|
||||
*/
|
||||
printk(KERN_INFO "axisflashmap: Found no flash chip.\n");
|
||||
} else {
|
||||
printk(KERN_INFO "%s: 0x%08x bytes of flash memory.\n",
|
||||
mymtd->name, mymtd->size);
|
||||
axisflash_mtd = mymtd;
|
||||
}
|
||||
|
||||
if (mymtd) {
|
||||
mymtd->owner = THIS_MODULE;
|
||||
}
|
||||
pidx++; /* First partition is always set to the default. */
|
||||
|
||||
if (ptable_head && (ptable_head->magic == PARTITION_TABLE_MAGIC)
|
||||
&& (ptable_head->size <
|
||||
(MAX_PARTITIONS * sizeof(struct partitiontable_entry) +
|
||||
PARTITIONTABLE_END_MARKER_SIZE))
|
||||
&& (*(unsigned long*)((void*)ptable_head + sizeof(*ptable_head) +
|
||||
ptable_head->size -
|
||||
PARTITIONTABLE_END_MARKER_SIZE)
|
||||
== PARTITIONTABLE_END_MARKER)) {
|
||||
/* Looks like a start, sane length and end of a
|
||||
* partition table, lets check csum etc.
|
||||
*/
|
||||
int ptable_ok = 0;
|
||||
struct partitiontable_entry *max_addr =
|
||||
(struct partitiontable_entry *)
|
||||
((unsigned long)ptable_head + sizeof(*ptable_head) +
|
||||
ptable_head->size);
|
||||
unsigned long offset = CONFIG_ETRAX_PTABLE_SECTOR;
|
||||
unsigned char *p;
|
||||
unsigned long csum = 0;
|
||||
|
||||
ptable = (struct partitiontable_entry *)
|
||||
((unsigned long)ptable_head + sizeof(*ptable_head));
|
||||
|
||||
/* Lets be PARANOID, and check the checksum. */
|
||||
p = (unsigned char*) ptable;
|
||||
|
||||
while (p <= (unsigned char*)max_addr) {
|
||||
csum += *p++;
|
||||
csum += *p++;
|
||||
csum += *p++;
|
||||
csum += *p++;
|
||||
}
|
||||
ptable_ok = (csum == ptable_head->checksum);
|
||||
|
||||
/* Read the entries and use/show the info. */
|
||||
printk(KERN_INFO " Found a%s partition table at 0x%p-0x%p.\n",
|
||||
(ptable_ok ? " valid" : "n invalid"), ptable_head,
|
||||
max_addr);
|
||||
|
||||
/* We have found a working bootblock. Now read the
|
||||
* partition table. Scan the table. It ends when
|
||||
* there is 0xffffffff, that is, empty flash.
|
||||
*/
|
||||
while (ptable_ok
|
||||
&& ptable->offset != 0xffffffff
|
||||
&& ptable < max_addr
|
||||
&& pidx < MAX_PARTITIONS) {
|
||||
|
||||
axis_partitions[pidx].offset = offset + ptable->offset + (crisv32_nand_boot ? 16384 : 0);
|
||||
axis_partitions[pidx].size = ptable->size;
|
||||
|
||||
printk(pmsg, pidx, axis_partitions[pidx].offset,
|
||||
axis_partitions[pidx].size);
|
||||
pidx++;
|
||||
ptable++;
|
||||
}
|
||||
use_default_ptable = !ptable_ok;
|
||||
}
|
||||
|
||||
if (romfs_in_flash) {
|
||||
/* Add an overlapping device for the root partition (romfs). */
|
||||
|
||||
axis_partitions[pidx].name = "romfs";
|
||||
if (crisv32_nand_boot) {
|
||||
char* data = kmalloc(1024, GFP_KERNEL);
|
||||
int len;
|
||||
int offset = crisv32_nand_cramfs_offset & ~(1024-1);
|
||||
char* tmp;
|
||||
|
||||
mymtd->read(mymtd, offset, 1024, &len, data);
|
||||
tmp = &data[crisv32_nand_cramfs_offset % 512];
|
||||
axis_partitions[pidx].size = *(unsigned*)(tmp + 4);
|
||||
axis_partitions[pidx].offset = crisv32_nand_cramfs_offset;
|
||||
kfree(data);
|
||||
} else {
|
||||
axis_partitions[pidx].size = romfs_length;
|
||||
axis_partitions[pidx].offset = romfs_start - FLASH_CACHED_ADDR;
|
||||
}
|
||||
|
||||
axis_partitions[pidx].mask_flags |= MTD_WRITEABLE;
|
||||
|
||||
printk(KERN_INFO
|
||||
" Adding readonly flash partition for romfs image:\n");
|
||||
printk(pmsg, pidx, axis_partitions[pidx].offset,
|
||||
axis_partitions[pidx].size);
|
||||
pidx++;
|
||||
}
|
||||
|
||||
if (mymtd) {
|
||||
if (use_default_ptable) {
|
||||
printk(KERN_INFO " Using default partition table.\n");
|
||||
err = add_mtd_partitions(mymtd, axis_default_partitions,
|
||||
NUM_DEFAULT_PARTITIONS);
|
||||
} else {
|
||||
err = add_mtd_partitions(mymtd, axis_partitions, pidx);
|
||||
}
|
||||
|
||||
if (err) {
|
||||
panic("axisflashmap could not add MTD partitions!\n");
|
||||
}
|
||||
}
|
||||
/* CONFIG_EXTRAXFS_SIM */
|
||||
#endif
|
||||
|
||||
if (!romfs_in_flash) {
|
||||
/* Create an RAM device for the root partition (romfs). */
|
||||
|
||||
#if !defined(CONFIG_MTD_MTDRAM) || (CONFIG_MTDRAM_TOTAL_SIZE != 0) || (CONFIG_MTDRAM_ABS_POS != 0)
|
||||
/* No use trying to boot this kernel from RAM. Panic! */
|
||||
printk(KERN_EMERG "axisflashmap: Cannot create an MTD RAM "
|
||||
"device due to kernel (mis)configuration!\n");
|
||||
panic("This kernel cannot boot from RAM!\n");
|
||||
#else
|
||||
struct mtd_info *mtd_ram;
|
||||
|
||||
mtd_ram = (struct mtd_info *)kmalloc(sizeof(struct mtd_info),
|
||||
GFP_KERNEL);
|
||||
if (!mtd_ram) {
|
||||
panic("axisflashmap couldn't allocate memory for "
|
||||
"mtd_info!\n");
|
||||
}
|
||||
|
||||
printk(KERN_INFO " Adding RAM partition for romfs image:\n");
|
||||
printk(pmsg, pidx, romfs_start, romfs_length);
|
||||
|
||||
err = mtdram_init_device(mtd_ram, (void*)romfs_start,
|
||||
romfs_length, "romfs");
|
||||
if (err) {
|
||||
panic("axisflashmap could not initialize MTD RAM "
|
||||
"device!\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* This adds the above to the kernels init-call chain. */
|
||||
module_init(init_axis_flash);
|
||||
|
||||
EXPORT_SYMBOL(axisflash_mtd);
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,766 @@
|
|||
/* $Id: gpio.c,v 1.16 2005/06/19 17:06:49 starvik Exp $
|
||||
*
|
||||
* ETRAX CRISv32 general port I/O device
|
||||
*
|
||||
* Copyright (c) 1999, 2000, 2001, 2002, 2003 Axis Communications AB
|
||||
*
|
||||
* Authors: Bjorn Wesen (initial version)
|
||||
* Ola Knutsson (LED handling)
|
||||
* Johan Adolfsson (read/set directions, write, port G,
|
||||
* port to ETRAX FS.
|
||||
*
|
||||
* $Log: gpio.c,v $
|
||||
* Revision 1.16 2005/06/19 17:06:49 starvik
|
||||
* Merge of Linux 2.6.12.
|
||||
*
|
||||
* Revision 1.15 2005/05/25 08:22:20 starvik
|
||||
* Changed GPIO port order to fit packages/devices/axis-2.4.
|
||||
*
|
||||
* Revision 1.14 2005/04/24 18:35:08 starvik
|
||||
* Updated with final register headers.
|
||||
*
|
||||
* Revision 1.13 2005/03/15 15:43:00 starvik
|
||||
* dev_id needs to be supplied for shared IRQs.
|
||||
*
|
||||
* Revision 1.12 2005/03/10 17:12:00 starvik
|
||||
* Protect alarm list with spinlock.
|
||||
*
|
||||
* Revision 1.11 2005/01/05 06:08:59 starvik
|
||||
* No need to do local_irq_disable after local_irq_save.
|
||||
*
|
||||
* Revision 1.10 2004/11/19 08:38:31 starvik
|
||||
* Removed old crap.
|
||||
*
|
||||
* Revision 1.9 2004/05/14 07:58:02 starvik
|
||||
* Merge of changes from 2.4
|
||||
*
|
||||
* Revision 1.8 2003/09/11 07:29:50 starvik
|
||||
* Merge of Linux 2.6.0-test5
|
||||
*
|
||||
* Revision 1.7 2003/07/10 13:25:46 starvik
|
||||
* Compiles for 2.5.74
|
||||
* Lindented ethernet.c
|
||||
*
|
||||
* Revision 1.6 2003/07/04 08:27:46 starvik
|
||||
* Merge of Linux 2.5.74
|
||||
*
|
||||
* Revision 1.5 2003/06/10 08:26:37 johana
|
||||
* Etrax -> ETRAX CRISv32
|
||||
*
|
||||
* Revision 1.4 2003/06/05 14:22:48 johana
|
||||
* Initialise some_alarms.
|
||||
*
|
||||
* Revision 1.3 2003/06/05 10:15:46 johana
|
||||
* New INTR_VECT macros.
|
||||
* Enable interrupts in global config.
|
||||
*
|
||||
* Revision 1.2 2003/06/03 15:52:50 johana
|
||||
* Initial CRIS v32 version.
|
||||
*
|
||||
* Revision 1.1 2003/06/03 08:53:15 johana
|
||||
* Copy of os/lx25/arch/cris/arch-v10/drivers/gpio.c version 1.7.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include <asm/etraxgpio.h>
|
||||
#include <asm/arch/hwregs/reg_map.h>
|
||||
#include <asm/arch/hwregs/reg_rdwr.h>
|
||||
#include <asm/arch/hwregs/gio_defs.h>
|
||||
#include <asm/arch/hwregs/intr_vect_defs.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/irq.h>
|
||||
|
||||
/* The following gio ports on ETRAX FS is available:
|
||||
* pa 8 bits, supports interrupts off, hi, low, set, posedge, negedge anyedge
|
||||
* pb 18 bits
|
||||
* pc 18 bits
|
||||
* pd 18 bits
|
||||
* pe 18 bits
|
||||
* each port has a rw_px_dout, r_px_din and rw_px_oe register.
|
||||
*/
|
||||
|
||||
#define GPIO_MAJOR 120 /* experimental MAJOR number */
|
||||
|
||||
#define D(x)
|
||||
|
||||
#if 0
|
||||
static int dp_cnt;
|
||||
#define DP(x) do { dp_cnt++; if (dp_cnt % 1000 == 0) x; }while(0)
|
||||
#else
|
||||
#define DP(x)
|
||||
#endif
|
||||
|
||||
static char gpio_name[] = "etrax gpio";
|
||||
|
||||
#if 0
|
||||
static wait_queue_head_t *gpio_wq;
|
||||
#endif
|
||||
|
||||
static int gpio_ioctl(struct inode *inode, struct file *file,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
static ssize_t gpio_write(struct file * file, const char * buf, size_t count,
|
||||
loff_t *off);
|
||||
static int gpio_open(struct inode *inode, struct file *filp);
|
||||
static int gpio_release(struct inode *inode, struct file *filp);
|
||||
static unsigned int gpio_poll(struct file *filp, struct poll_table_struct *wait);
|
||||
|
||||
/* private data per open() of this driver */
|
||||
|
||||
struct gpio_private {
|
||||
struct gpio_private *next;
|
||||
/* The IO_CFG_WRITE_MODE_VALUE only support 8 bits: */
|
||||
unsigned char clk_mask;
|
||||
unsigned char data_mask;
|
||||
unsigned char write_msb;
|
||||
unsigned char pad1;
|
||||
/* These fields are generic */
|
||||
unsigned long highalarm, lowalarm;
|
||||
wait_queue_head_t alarm_wq;
|
||||
int minor;
|
||||
};
|
||||
|
||||
/* linked list of alarms to check for */
|
||||
|
||||
static struct gpio_private *alarmlist = 0;
|
||||
|
||||
static int gpio_some_alarms = 0; /* Set if someone uses alarm */
|
||||
static unsigned long gpio_pa_high_alarms = 0;
|
||||
static unsigned long gpio_pa_low_alarms = 0;
|
||||
|
||||
static DEFINE_SPINLOCK(alarm_lock);
|
||||
|
||||
#define NUM_PORTS (GPIO_MINOR_LAST+1)
|
||||
#define GIO_REG_RD_ADDR(reg) (volatile unsigned long*) (regi_gio + REG_RD_ADDR_gio_##reg )
|
||||
#define GIO_REG_WR_ADDR(reg) (volatile unsigned long*) (regi_gio + REG_RD_ADDR_gio_##reg )
|
||||
unsigned long led_dummy;
|
||||
|
||||
static volatile unsigned long *data_out[NUM_PORTS] = {
|
||||
GIO_REG_WR_ADDR(rw_pa_dout),
|
||||
GIO_REG_WR_ADDR(rw_pb_dout),
|
||||
&led_dummy,
|
||||
GIO_REG_WR_ADDR(rw_pc_dout),
|
||||
GIO_REG_WR_ADDR(rw_pd_dout),
|
||||
GIO_REG_WR_ADDR(rw_pe_dout),
|
||||
};
|
||||
|
||||
static volatile unsigned long *data_in[NUM_PORTS] = {
|
||||
GIO_REG_RD_ADDR(r_pa_din),
|
||||
GIO_REG_RD_ADDR(r_pb_din),
|
||||
&led_dummy,
|
||||
GIO_REG_RD_ADDR(r_pc_din),
|
||||
GIO_REG_RD_ADDR(r_pd_din),
|
||||
GIO_REG_RD_ADDR(r_pe_din),
|
||||
};
|
||||
|
||||
static unsigned long changeable_dir[NUM_PORTS] = {
|
||||
CONFIG_ETRAX_PA_CHANGEABLE_DIR,
|
||||
CONFIG_ETRAX_PB_CHANGEABLE_DIR,
|
||||
0,
|
||||
CONFIG_ETRAX_PC_CHANGEABLE_DIR,
|
||||
CONFIG_ETRAX_PD_CHANGEABLE_DIR,
|
||||
CONFIG_ETRAX_PE_CHANGEABLE_DIR,
|
||||
};
|
||||
|
||||
static unsigned long changeable_bits[NUM_PORTS] = {
|
||||
CONFIG_ETRAX_PA_CHANGEABLE_BITS,
|
||||
CONFIG_ETRAX_PB_CHANGEABLE_BITS,
|
||||
0,
|
||||
CONFIG_ETRAX_PC_CHANGEABLE_BITS,
|
||||
CONFIG_ETRAX_PD_CHANGEABLE_BITS,
|
||||
CONFIG_ETRAX_PE_CHANGEABLE_BITS,
|
||||
};
|
||||
|
||||
static volatile unsigned long *dir_oe[NUM_PORTS] = {
|
||||
GIO_REG_WR_ADDR(rw_pa_oe),
|
||||
GIO_REG_WR_ADDR(rw_pb_oe),
|
||||
&led_dummy,
|
||||
GIO_REG_WR_ADDR(rw_pc_oe),
|
||||
GIO_REG_WR_ADDR(rw_pd_oe),
|
||||
GIO_REG_WR_ADDR(rw_pe_oe),
|
||||
};
|
||||
|
||||
|
||||
|
||||
static unsigned int
|
||||
gpio_poll(struct file *file,
|
||||
poll_table *wait)
|
||||
{
|
||||
unsigned int mask = 0;
|
||||
struct gpio_private *priv = (struct gpio_private *)file->private_data;
|
||||
unsigned long data;
|
||||
poll_wait(file, &priv->alarm_wq, wait);
|
||||
if (priv->minor == GPIO_MINOR_A) {
|
||||
reg_gio_rw_intr_cfg intr_cfg;
|
||||
unsigned long tmp;
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
data = REG_TYPE_CONV(unsigned long, reg_gio_r_pa_din, REG_RD(gio, regi_gio, r_pa_din));
|
||||
/* PA has support for interrupt
|
||||
* lets activate high for those low and with highalarm set
|
||||
*/
|
||||
intr_cfg = REG_RD(gio, regi_gio, rw_intr_cfg);
|
||||
|
||||
tmp = ~data & priv->highalarm & 0xFF;
|
||||
if (tmp & (1 << 0)) {
|
||||
intr_cfg.pa0 = regk_gio_hi;
|
||||
}
|
||||
if (tmp & (1 << 1)) {
|
||||
intr_cfg.pa1 = regk_gio_hi;
|
||||
}
|
||||
if (tmp & (1 << 2)) {
|
||||
intr_cfg.pa2 = regk_gio_hi;
|
||||
}
|
||||
if (tmp & (1 << 3)) {
|
||||
intr_cfg.pa3 = regk_gio_hi;
|
||||
}
|
||||
if (tmp & (1 << 4)) {
|
||||
intr_cfg.pa4 = regk_gio_hi;
|
||||
}
|
||||
if (tmp & (1 << 5)) {
|
||||
intr_cfg.pa5 = regk_gio_hi;
|
||||
}
|
||||
if (tmp & (1 << 6)) {
|
||||
intr_cfg.pa6 = regk_gio_hi;
|
||||
}
|
||||
if (tmp & (1 << 7)) {
|
||||
intr_cfg.pa7 = regk_gio_hi;
|
||||
}
|
||||
/*
|
||||
* lets activate low for those high and with lowalarm set
|
||||
*/
|
||||
tmp = data & priv->lowalarm & 0xFF;
|
||||
if (tmp & (1 << 0)) {
|
||||
intr_cfg.pa0 = regk_gio_lo;
|
||||
}
|
||||
if (tmp & (1 << 1)) {
|
||||
intr_cfg.pa1 = regk_gio_lo;
|
||||
}
|
||||
if (tmp & (1 << 2)) {
|
||||
intr_cfg.pa2 = regk_gio_lo;
|
||||
}
|
||||
if (tmp & (1 << 3)) {
|
||||
intr_cfg.pa3 = regk_gio_lo;
|
||||
}
|
||||
if (tmp & (1 << 4)) {
|
||||
intr_cfg.pa4 = regk_gio_lo;
|
||||
}
|
||||
if (tmp & (1 << 5)) {
|
||||
intr_cfg.pa5 = regk_gio_lo;
|
||||
}
|
||||
if (tmp & (1 << 6)) {
|
||||
intr_cfg.pa6 = regk_gio_lo;
|
||||
}
|
||||
if (tmp & (1 << 7)) {
|
||||
intr_cfg.pa7 = regk_gio_lo;
|
||||
}
|
||||
|
||||
REG_WR(gio, regi_gio, rw_intr_cfg, intr_cfg);
|
||||
local_irq_restore(flags);
|
||||
} else if (priv->minor <= GPIO_MINOR_E)
|
||||
data = *data_in[priv->minor];
|
||||
else
|
||||
return 0;
|
||||
|
||||
if ((data & priv->highalarm) ||
|
||||
(~data & priv->lowalarm)) {
|
||||
mask = POLLIN|POLLRDNORM;
|
||||
}
|
||||
|
||||
DP(printk("gpio_poll ready: mask 0x%08X\n", mask));
|
||||
return mask;
|
||||
}
|
||||
|
||||
int etrax_gpio_wake_up_check(void)
|
||||
{
|
||||
struct gpio_private *priv = alarmlist;
|
||||
unsigned long data = 0;
|
||||
int ret = 0;
|
||||
while (priv) {
|
||||
data = *data_in[priv->minor];
|
||||
if ((data & priv->highalarm) ||
|
||||
(~data & priv->lowalarm)) {
|
||||
DP(printk("etrax_gpio_wake_up_check %i\n",priv->minor));
|
||||
wake_up_interruptible(&priv->alarm_wq);
|
||||
ret = 1;
|
||||
}
|
||||
priv = priv->next;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static irqreturn_t
|
||||
gpio_poll_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
if (gpio_some_alarms) {
|
||||
return IRQ_RETVAL(etrax_gpio_wake_up_check());
|
||||
}
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
static irqreturn_t
|
||||
gpio_pa_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
reg_gio_rw_intr_mask intr_mask;
|
||||
reg_gio_r_masked_intr masked_intr;
|
||||
reg_gio_rw_ack_intr ack_intr;
|
||||
unsigned long tmp;
|
||||
unsigned long tmp2;
|
||||
|
||||
/* Find what PA interrupts are active */
|
||||
masked_intr = REG_RD(gio, regi_gio, r_masked_intr);
|
||||
tmp = REG_TYPE_CONV(unsigned long, reg_gio_r_masked_intr, masked_intr);
|
||||
|
||||
/* Find those that we have enabled */
|
||||
spin_lock(&alarm_lock);
|
||||
tmp &= (gpio_pa_high_alarms | gpio_pa_low_alarms);
|
||||
spin_unlock(&alarm_lock);
|
||||
|
||||
/* Ack them */
|
||||
ack_intr = REG_TYPE_CONV(reg_gio_rw_ack_intr, unsigned long, tmp);
|
||||
REG_WR(gio, regi_gio, rw_ack_intr, ack_intr);
|
||||
|
||||
/* Disable those interrupts.. */
|
||||
intr_mask = REG_RD(gio, regi_gio, rw_intr_mask);
|
||||
tmp2 = REG_TYPE_CONV(unsigned long, reg_gio_rw_intr_mask, intr_mask);
|
||||
tmp2 &= ~tmp;
|
||||
intr_mask = REG_TYPE_CONV(reg_gio_rw_intr_mask, unsigned long, tmp2);
|
||||
REG_WR(gio, regi_gio, rw_intr_mask, intr_mask);
|
||||
|
||||
if (gpio_some_alarms) {
|
||||
return IRQ_RETVAL(etrax_gpio_wake_up_check());
|
||||
}
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
|
||||
static ssize_t gpio_write(struct file * file, const char * buf, size_t count,
|
||||
loff_t *off)
|
||||
{
|
||||
struct gpio_private *priv = (struct gpio_private *)file->private_data;
|
||||
unsigned char data, clk_mask, data_mask, write_msb;
|
||||
unsigned long flags;
|
||||
unsigned long shadow;
|
||||
volatile unsigned long *port;
|
||||
ssize_t retval = count;
|
||||
/* Only bits 0-7 may be used for write operations but allow all
|
||||
devices except leds... */
|
||||
if (priv->minor == GPIO_MINOR_LEDS) {
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (!access_ok(VERIFY_READ, buf, count)) {
|
||||
return -EFAULT;
|
||||
}
|
||||
clk_mask = priv->clk_mask;
|
||||
data_mask = priv->data_mask;
|
||||
/* It must have been configured using the IO_CFG_WRITE_MODE */
|
||||
/* Perhaps a better error code? */
|
||||
if (clk_mask == 0 || data_mask == 0) {
|
||||
return -EPERM;
|
||||
}
|
||||
write_msb = priv->write_msb;
|
||||
D(printk("gpio_write: %lu to data 0x%02X clk 0x%02X msb: %i\n",count, data_mask, clk_mask, write_msb));
|
||||
port = data_out[priv->minor];
|
||||
|
||||
while (count--) {
|
||||
int i;
|
||||
data = *buf++;
|
||||
if (priv->write_msb) {
|
||||
for (i = 7; i >= 0;i--) {
|
||||
local_irq_save(flags);
|
||||
shadow = *port;
|
||||
*port = shadow &= ~clk_mask;
|
||||
if (data & 1<<i)
|
||||
*port = shadow |= data_mask;
|
||||
else
|
||||
*port = shadow &= ~data_mask;
|
||||
/* For FPGA: min 5.0ns (DCC) before CCLK high */
|
||||
*port = shadow |= clk_mask;
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i <= 7;i++) {
|
||||
local_irq_save(flags);
|
||||
shadow = *port;
|
||||
*port = shadow &= ~clk_mask;
|
||||
if (data & 1<<i)
|
||||
*port = shadow |= data_mask;
|
||||
else
|
||||
*port = shadow &= ~data_mask;
|
||||
/* For FPGA: min 5.0ns (DCC) before CCLK high */
|
||||
*port = shadow |= clk_mask;
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int
|
||||
gpio_open(struct inode *inode, struct file *filp)
|
||||
{
|
||||
struct gpio_private *priv;
|
||||
int p = MINOR(inode->i_rdev);
|
||||
|
||||
if (p > GPIO_MINOR_LAST)
|
||||
return -EINVAL;
|
||||
|
||||
priv = (struct gpio_private *)kmalloc(sizeof(struct gpio_private),
|
||||
GFP_KERNEL);
|
||||
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->minor = p;
|
||||
|
||||
/* initialize the io/alarm struct and link it into our alarmlist */
|
||||
|
||||
priv->next = alarmlist;
|
||||
alarmlist = priv;
|
||||
priv->clk_mask = 0;
|
||||
priv->data_mask = 0;
|
||||
priv->highalarm = 0;
|
||||
priv->lowalarm = 0;
|
||||
init_waitqueue_head(&priv->alarm_wq);
|
||||
|
||||
filp->private_data = (void *)priv;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
gpio_release(struct inode *inode, struct file *filp)
|
||||
{
|
||||
struct gpio_private *p = alarmlist;
|
||||
struct gpio_private *todel = (struct gpio_private *)filp->private_data;
|
||||
/* local copies while updating them: */
|
||||
unsigned long a_high, a_low;
|
||||
unsigned long some_alarms;
|
||||
|
||||
/* unlink from alarmlist and free the private structure */
|
||||
|
||||
if (p == todel) {
|
||||
alarmlist = todel->next;
|
||||
} else {
|
||||
while (p->next != todel)
|
||||
p = p->next;
|
||||
p->next = todel->next;
|
||||
}
|
||||
|
||||
kfree(todel);
|
||||
/* Check if there are still any alarms set */
|
||||
p = alarmlist;
|
||||
some_alarms = 0;
|
||||
a_high = 0;
|
||||
a_low = 0;
|
||||
while (p) {
|
||||
if (p->minor == GPIO_MINOR_A) {
|
||||
a_high |= p->highalarm;
|
||||
a_low |= p->lowalarm;
|
||||
}
|
||||
|
||||
if (p->highalarm | p->lowalarm) {
|
||||
some_alarms = 1;
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
|
||||
spin_lock(&alarm_lock);
|
||||
gpio_some_alarms = some_alarms;
|
||||
gpio_pa_high_alarms = a_high;
|
||||
gpio_pa_low_alarms = a_low;
|
||||
spin_unlock(&alarm_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Main device API. ioctl's to read/set/clear bits, as well as to
|
||||
* set alarms to wait for using a subsequent select().
|
||||
*/
|
||||
|
||||
unsigned long inline setget_input(struct gpio_private *priv, unsigned long arg)
|
||||
{
|
||||
/* Set direction 0=unchanged 1=input,
|
||||
* return mask with 1=input
|
||||
*/
|
||||
unsigned long flags;
|
||||
unsigned long dir_shadow;
|
||||
|
||||
local_irq_save(flags);
|
||||
dir_shadow = *dir_oe[priv->minor];
|
||||
dir_shadow &= ~(arg & changeable_dir[priv->minor]);
|
||||
*dir_oe[priv->minor] = dir_shadow;
|
||||
local_irq_restore(flags);
|
||||
|
||||
if (priv->minor == GPIO_MINOR_A)
|
||||
dir_shadow ^= 0xFF; /* Only 8 bits */
|
||||
else
|
||||
dir_shadow ^= 0x3FFFF; /* Only 18 bits */
|
||||
return dir_shadow;
|
||||
|
||||
} /* setget_input */
|
||||
|
||||
unsigned long inline setget_output(struct gpio_private *priv, unsigned long arg)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned long dir_shadow;
|
||||
|
||||
local_irq_save(flags);
|
||||
dir_shadow = *dir_oe[priv->minor];
|
||||
dir_shadow |= (arg & changeable_dir[priv->minor]);
|
||||
*dir_oe[priv->minor] = dir_shadow;
|
||||
local_irq_restore(flags);
|
||||
return dir_shadow;
|
||||
} /* setget_output */
|
||||
|
||||
static int
|
||||
gpio_leds_ioctl(unsigned int cmd, unsigned long arg);
|
||||
|
||||
static int
|
||||
gpio_ioctl(struct inode *inode, struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned long val;
|
||||
unsigned long shadow;
|
||||
struct gpio_private *priv = (struct gpio_private *)file->private_data;
|
||||
if (_IOC_TYPE(cmd) != ETRAXGPIO_IOCTYPE) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (_IOC_NR(cmd)) {
|
||||
case IO_READBITS: /* Use IO_READ_INBITS and IO_READ_OUTBITS instead */
|
||||
// read the port
|
||||
return *data_in[priv->minor];
|
||||
break;
|
||||
case IO_SETBITS:
|
||||
local_irq_save(flags);
|
||||
if (arg & 0x04)
|
||||
printk("GPIO SET 2\n");
|
||||
// set changeable bits with a 1 in arg
|
||||
shadow = *data_out[priv->minor];
|
||||
shadow |= (arg & changeable_bits[priv->minor]);
|
||||
*data_out[priv->minor] = shadow;
|
||||
local_irq_restore(flags);
|
||||
break;
|
||||
case IO_CLRBITS:
|
||||
local_irq_save(flags);
|
||||
if (arg & 0x04)
|
||||
printk("GPIO CLR 2\n");
|
||||
// clear changeable bits with a 1 in arg
|
||||
shadow = *data_out[priv->minor];
|
||||
shadow &= ~(arg & changeable_bits[priv->minor]);
|
||||
*data_out[priv->minor] = shadow;
|
||||
local_irq_restore(flags);
|
||||
break;
|
||||
case IO_HIGHALARM:
|
||||
// set alarm when bits with 1 in arg go high
|
||||
priv->highalarm |= arg;
|
||||
spin_lock(&alarm_lock);
|
||||
gpio_some_alarms = 1;
|
||||
if (priv->minor == GPIO_MINOR_A) {
|
||||
gpio_pa_high_alarms |= arg;
|
||||
}
|
||||
spin_unlock(&alarm_lock);
|
||||
break;
|
||||
case IO_LOWALARM:
|
||||
// set alarm when bits with 1 in arg go low
|
||||
priv->lowalarm |= arg;
|
||||
spin_lock(&alarm_lock);
|
||||
gpio_some_alarms = 1;
|
||||
if (priv->minor == GPIO_MINOR_A) {
|
||||
gpio_pa_low_alarms |= arg;
|
||||
}
|
||||
spin_unlock(&alarm_lock);
|
||||
break;
|
||||
case IO_CLRALARM:
|
||||
// clear alarm for bits with 1 in arg
|
||||
priv->highalarm &= ~arg;
|
||||
priv->lowalarm &= ~arg;
|
||||
spin_lock(&alarm_lock);
|
||||
if (priv->minor == GPIO_MINOR_A) {
|
||||
if (gpio_pa_high_alarms & arg ||
|
||||
gpio_pa_low_alarms & arg) {
|
||||
/* Must update the gpio_pa_*alarms masks */
|
||||
}
|
||||
}
|
||||
spin_unlock(&alarm_lock);
|
||||
break;
|
||||
case IO_READDIR: /* Use IO_SETGET_INPUT/OUTPUT instead! */
|
||||
/* Read direction 0=input 1=output */
|
||||
return *dir_oe[priv->minor];
|
||||
case IO_SETINPUT: /* Use IO_SETGET_INPUT instead! */
|
||||
/* Set direction 0=unchanged 1=input,
|
||||
* return mask with 1=input
|
||||
*/
|
||||
return setget_input(priv, arg);
|
||||
break;
|
||||
case IO_SETOUTPUT: /* Use IO_SETGET_OUTPUT instead! */
|
||||
/* Set direction 0=unchanged 1=output,
|
||||
* return mask with 1=output
|
||||
*/
|
||||
return setget_output(priv, arg);
|
||||
|
||||
case IO_CFG_WRITE_MODE:
|
||||
{
|
||||
unsigned long dir_shadow;
|
||||
dir_shadow = *dir_oe[priv->minor];
|
||||
|
||||
priv->clk_mask = arg & 0xFF;
|
||||
priv->data_mask = (arg >> 8) & 0xFF;
|
||||
priv->write_msb = (arg >> 16) & 0x01;
|
||||
/* Check if we're allowed to change the bits and
|
||||
* the direction is correct
|
||||
*/
|
||||
if (!((priv->clk_mask & changeable_bits[priv->minor]) &&
|
||||
(priv->data_mask & changeable_bits[priv->minor]) &&
|
||||
(priv->clk_mask & dir_shadow) &&
|
||||
(priv->data_mask & dir_shadow)))
|
||||
{
|
||||
priv->clk_mask = 0;
|
||||
priv->data_mask = 0;
|
||||
return -EPERM;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IO_READ_INBITS:
|
||||
/* *arg is result of reading the input pins */
|
||||
val = *data_in[priv->minor];
|
||||
if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
break;
|
||||
case IO_READ_OUTBITS:
|
||||
/* *arg is result of reading the output shadow */
|
||||
val = *data_out[priv->minor];
|
||||
if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
|
||||
return -EFAULT;
|
||||
break;
|
||||
case IO_SETGET_INPUT:
|
||||
/* bits set in *arg is set to input,
|
||||
* *arg updated with current input pins.
|
||||
*/
|
||||
if (copy_from_user(&val, (unsigned long*)arg, sizeof(val)))
|
||||
return -EFAULT;
|
||||
val = setget_input(priv, val);
|
||||
if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
|
||||
return -EFAULT;
|
||||
break;
|
||||
case IO_SETGET_OUTPUT:
|
||||
/* bits set in *arg is set to output,
|
||||
* *arg updated with current output pins.
|
||||
*/
|
||||
if (copy_from_user(&val, (unsigned long*)arg, sizeof(val)))
|
||||
return -EFAULT;
|
||||
val = setget_output(priv, val);
|
||||
if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
|
||||
return -EFAULT;
|
||||
break;
|
||||
default:
|
||||
if (priv->minor == GPIO_MINOR_LEDS)
|
||||
return gpio_leds_ioctl(cmd, arg);
|
||||
else
|
||||
return -EINVAL;
|
||||
} /* switch */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
gpio_leds_ioctl(unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
unsigned char green;
|
||||
unsigned char red;
|
||||
|
||||
switch (_IOC_NR(cmd)) {
|
||||
case IO_LEDACTIVE_SET:
|
||||
green = ((unsigned char) arg) & 1;
|
||||
red = (((unsigned char) arg) >> 1) & 1;
|
||||
LED_ACTIVE_SET_G(green);
|
||||
LED_ACTIVE_SET_R(red);
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
} /* switch */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct file_operations gpio_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.poll = gpio_poll,
|
||||
.ioctl = gpio_ioctl,
|
||||
.write = gpio_write,
|
||||
.open = gpio_open,
|
||||
.release = gpio_release,
|
||||
};
|
||||
|
||||
|
||||
/* main driver initialization routine, called from mem.c */
|
||||
|
||||
static __init int
|
||||
gpio_init(void)
|
||||
{
|
||||
int res;
|
||||
reg_intr_vect_rw_mask intr_mask;
|
||||
|
||||
/* do the formalities */
|
||||
|
||||
res = register_chrdev(GPIO_MAJOR, gpio_name, &gpio_fops);
|
||||
if (res < 0) {
|
||||
printk(KERN_ERR "gpio: couldn't get a major number.\n");
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Clear all leds */
|
||||
LED_NETWORK_SET(0);
|
||||
LED_ACTIVE_SET(0);
|
||||
LED_DISK_READ(0);
|
||||
LED_DISK_WRITE(0);
|
||||
|
||||
printk("ETRAX FS GPIO driver v2.5, (c) 2003-2005 Axis Communications AB\n");
|
||||
/* We call etrax_gpio_wake_up_check() from timer interrupt and
|
||||
* from cpu_idle() in kernel/process.c
|
||||
* The check in cpu_idle() reduces latency from ~15 ms to ~6 ms
|
||||
* in some tests.
|
||||
*/
|
||||
if (request_irq(TIMER_INTR_VECT, gpio_poll_timer_interrupt,
|
||||
SA_SHIRQ | SA_INTERRUPT,"gpio poll", &alarmlist)) {
|
||||
printk("err: timer0 irq for gpio\n");
|
||||
}
|
||||
if (request_irq(GEN_IO_INTR_VECT, gpio_pa_interrupt,
|
||||
SA_SHIRQ | SA_INTERRUPT,"gpio PA", &alarmlist)) {
|
||||
printk("err: PA irq for gpio\n");
|
||||
}
|
||||
/* enable the gio and timer irq in global config */
|
||||
intr_mask = REG_RD(intr_vect, regi_irq, rw_mask);
|
||||
intr_mask.timer = 1;
|
||||
intr_mask.gen_io = 1;
|
||||
REG_WR(intr_vect, regi_irq, rw_mask, intr_mask);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/* this makes sure that gpio_init is called during kernel boot */
|
||||
|
||||
module_init(gpio_init);
|
|
@ -0,0 +1,611 @@
|
|||
/*!***************************************************************************
|
||||
*!
|
||||
*! FILE NAME : i2c.c
|
||||
*!
|
||||
*! DESCRIPTION: implements an interface for IIC/I2C, both directly from other
|
||||
*! kernel modules (i2c_writereg/readreg) and from userspace using
|
||||
*! ioctl()'s
|
||||
*!
|
||||
*! Nov 30 1998 Torbjorn Eliasson Initial version.
|
||||
*! Bjorn Wesen Elinux kernel version.
|
||||
*! Jan 14 2000 Johan Adolfsson Fixed PB shadow register stuff -
|
||||
*! don't use PB_I2C if DS1302 uses same bits,
|
||||
*! use PB.
|
||||
*| June 23 2003 Pieter Grimmerink Added 'i2c_sendnack'. i2c_readreg now
|
||||
*| generates nack on last received byte,
|
||||
*| instead of ack.
|
||||
*| i2c_getack changed data level while clock
|
||||
*| was high, causing DS75 to see a stop condition
|
||||
*!
|
||||
*! ---------------------------------------------------------------------------
|
||||
*!
|
||||
*! (C) Copyright 1999-2002 Axis Communications AB, LUND, SWEDEN
|
||||
*!
|
||||
*!***************************************************************************/
|
||||
/* $Id: i2c.c,v 1.2 2005/05/09 15:29:49 starvik Exp $ */
|
||||
/****************** INCLUDE FILES SECTION ***********************************/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/config.h>
|
||||
|
||||
#include <asm/etraxi2c.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/delay.h>
|
||||
|
||||
#include "i2c.h"
|
||||
|
||||
/****************** I2C DEFINITION SECTION *************************/
|
||||
|
||||
#define D(x)
|
||||
|
||||
#define I2C_MAJOR 123 /* LOCAL/EXPERIMENTAL */
|
||||
static const char i2c_name[] = "i2c";
|
||||
|
||||
#define CLOCK_LOW_TIME 8
|
||||
#define CLOCK_HIGH_TIME 8
|
||||
#define START_CONDITION_HOLD_TIME 8
|
||||
#define STOP_CONDITION_HOLD_TIME 8
|
||||
#define ENABLE_OUTPUT 0x01
|
||||
#define ENABLE_INPUT 0x00
|
||||
#define I2C_CLOCK_HIGH 1
|
||||
#define I2C_CLOCK_LOW 0
|
||||
#define I2C_DATA_HIGH 1
|
||||
#define I2C_DATA_LOW 0
|
||||
|
||||
#define i2c_enable()
|
||||
#define i2c_disable()
|
||||
|
||||
/* enable or disable output-enable, to select output or input on the i2c bus */
|
||||
|
||||
#define i2c_dir_out() crisv32_io_set_dir(&cris_i2c_data, crisv32_io_dir_out)
|
||||
#define i2c_dir_in() crisv32_io_set_dir(&cris_i2c_data, crisv32_io_dir_in)
|
||||
|
||||
/* control the i2c clock and data signals */
|
||||
|
||||
#define i2c_clk(x) crisv32_io_set(&cris_i2c_clk, x)
|
||||
#define i2c_data(x) crisv32_io_set(&cris_i2c_data, x)
|
||||
|
||||
/* read a bit from the i2c interface */
|
||||
|
||||
#define i2c_getbit() crisv32_io_rd(&cris_i2c_data)
|
||||
|
||||
#define i2c_delay(usecs) udelay(usecs)
|
||||
|
||||
/****************** VARIABLE SECTION ************************************/
|
||||
|
||||
static struct crisv32_iopin cris_i2c_clk;
|
||||
static struct crisv32_iopin cris_i2c_data;
|
||||
|
||||
/****************** FUNCTION DEFINITION SECTION *************************/
|
||||
|
||||
|
||||
/* generate i2c start condition */
|
||||
|
||||
void
|
||||
i2c_start(void)
|
||||
{
|
||||
/*
|
||||
* SCL=1 SDA=1
|
||||
*/
|
||||
i2c_dir_out();
|
||||
i2c_delay(CLOCK_HIGH_TIME/6);
|
||||
i2c_data(I2C_DATA_HIGH);
|
||||
i2c_clk(I2C_CLOCK_HIGH);
|
||||
i2c_delay(CLOCK_HIGH_TIME);
|
||||
/*
|
||||
* SCL=1 SDA=0
|
||||
*/
|
||||
i2c_data(I2C_DATA_LOW);
|
||||
i2c_delay(START_CONDITION_HOLD_TIME);
|
||||
/*
|
||||
* SCL=0 SDA=0
|
||||
*/
|
||||
i2c_clk(I2C_CLOCK_LOW);
|
||||
i2c_delay(CLOCK_LOW_TIME);
|
||||
}
|
||||
|
||||
/* generate i2c stop condition */
|
||||
|
||||
void
|
||||
i2c_stop(void)
|
||||
{
|
||||
i2c_dir_out();
|
||||
|
||||
/*
|
||||
* SCL=0 SDA=0
|
||||
*/
|
||||
i2c_clk(I2C_CLOCK_LOW);
|
||||
i2c_data(I2C_DATA_LOW);
|
||||
i2c_delay(CLOCK_LOW_TIME*2);
|
||||
/*
|
||||
* SCL=1 SDA=0
|
||||
*/
|
||||
i2c_clk(I2C_CLOCK_HIGH);
|
||||
i2c_delay(CLOCK_HIGH_TIME*2);
|
||||
/*
|
||||
* SCL=1 SDA=1
|
||||
*/
|
||||
i2c_data(I2C_DATA_HIGH);
|
||||
i2c_delay(STOP_CONDITION_HOLD_TIME);
|
||||
|
||||
i2c_dir_in();
|
||||
}
|
||||
|
||||
/* write a byte to the i2c interface */
|
||||
|
||||
void
|
||||
i2c_outbyte(unsigned char x)
|
||||
{
|
||||
int i;
|
||||
|
||||
i2c_dir_out();
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (x & 0x80) {
|
||||
i2c_data(I2C_DATA_HIGH);
|
||||
} else {
|
||||
i2c_data(I2C_DATA_LOW);
|
||||
}
|
||||
|
||||
i2c_delay(CLOCK_LOW_TIME/2);
|
||||
i2c_clk(I2C_CLOCK_HIGH);
|
||||
i2c_delay(CLOCK_HIGH_TIME);
|
||||
i2c_clk(I2C_CLOCK_LOW);
|
||||
i2c_delay(CLOCK_LOW_TIME/2);
|
||||
x <<= 1;
|
||||
}
|
||||
i2c_data(I2C_DATA_LOW);
|
||||
i2c_delay(CLOCK_LOW_TIME/2);
|
||||
|
||||
/*
|
||||
* enable input
|
||||
*/
|
||||
i2c_dir_in();
|
||||
}
|
||||
|
||||
/* read a byte from the i2c interface */
|
||||
|
||||
unsigned char
|
||||
i2c_inbyte(void)
|
||||
{
|
||||
unsigned char aBitByte = 0;
|
||||
int i;
|
||||
|
||||
/* Switch off I2C to get bit */
|
||||
i2c_disable();
|
||||
i2c_dir_in();
|
||||
i2c_delay(CLOCK_HIGH_TIME/2);
|
||||
|
||||
/* Get bit */
|
||||
aBitByte |= i2c_getbit();
|
||||
|
||||
/* Enable I2C */
|
||||
i2c_enable();
|
||||
i2c_delay(CLOCK_LOW_TIME/2);
|
||||
|
||||
for (i = 1; i < 8; i++) {
|
||||
aBitByte <<= 1;
|
||||
/* Clock pulse */
|
||||
i2c_clk(I2C_CLOCK_HIGH);
|
||||
i2c_delay(CLOCK_HIGH_TIME);
|
||||
i2c_clk(I2C_CLOCK_LOW);
|
||||
i2c_delay(CLOCK_LOW_TIME);
|
||||
|
||||
/* Switch off I2C to get bit */
|
||||
i2c_disable();
|
||||
i2c_dir_in();
|
||||
i2c_delay(CLOCK_HIGH_TIME/2);
|
||||
|
||||
/* Get bit */
|
||||
aBitByte |= i2c_getbit();
|
||||
|
||||
/* Enable I2C */
|
||||
i2c_enable();
|
||||
i2c_delay(CLOCK_LOW_TIME/2);
|
||||
}
|
||||
i2c_clk(I2C_CLOCK_HIGH);
|
||||
i2c_delay(CLOCK_HIGH_TIME);
|
||||
|
||||
/*
|
||||
* we leave the clock low, getbyte is usually followed
|
||||
* by sendack/nack, they assume the clock to be low
|
||||
*/
|
||||
i2c_clk(I2C_CLOCK_LOW);
|
||||
return aBitByte;
|
||||
}
|
||||
|
||||
/*#---------------------------------------------------------------------------
|
||||
*#
|
||||
*# FUNCTION NAME: i2c_getack
|
||||
*#
|
||||
*# DESCRIPTION : checks if ack was received from ic2
|
||||
*#
|
||||
*#--------------------------------------------------------------------------*/
|
||||
|
||||
int
|
||||
i2c_getack(void)
|
||||
{
|
||||
int ack = 1;
|
||||
/*
|
||||
* enable output
|
||||
*/
|
||||
i2c_dir_out();
|
||||
/*
|
||||
* Release data bus by setting
|
||||
* data high
|
||||
*/
|
||||
i2c_data(I2C_DATA_HIGH);
|
||||
/*
|
||||
* enable input
|
||||
*/
|
||||
i2c_dir_in();
|
||||
i2c_delay(CLOCK_HIGH_TIME/4);
|
||||
/*
|
||||
* generate ACK clock pulse
|
||||
*/
|
||||
i2c_clk(I2C_CLOCK_HIGH);
|
||||
/*
|
||||
* Use PORT PB instead of I2C
|
||||
* for input. (I2C not working)
|
||||
*/
|
||||
i2c_clk(1);
|
||||
i2c_data(1);
|
||||
/*
|
||||
* switch off I2C
|
||||
*/
|
||||
i2c_data(1);
|
||||
i2c_disable();
|
||||
i2c_dir_in();
|
||||
/*
|
||||
* now wait for ack
|
||||
*/
|
||||
i2c_delay(CLOCK_HIGH_TIME/2);
|
||||
/*
|
||||
* check for ack
|
||||
*/
|
||||
if(i2c_getbit())
|
||||
ack = 0;
|
||||
i2c_delay(CLOCK_HIGH_TIME/2);
|
||||
if(!ack){
|
||||
if(!i2c_getbit()) /* receiver pulld SDA low */
|
||||
ack = 1;
|
||||
i2c_delay(CLOCK_HIGH_TIME/2);
|
||||
}
|
||||
|
||||
/*
|
||||
* our clock is high now, make sure data is low
|
||||
* before we enable our output. If we keep data high
|
||||
* and enable output, we would generate a stop condition.
|
||||
*/
|
||||
i2c_data(I2C_DATA_LOW);
|
||||
|
||||
/*
|
||||
* end clock pulse
|
||||
*/
|
||||
i2c_enable();
|
||||
i2c_dir_out();
|
||||
i2c_clk(I2C_CLOCK_LOW);
|
||||
i2c_delay(CLOCK_HIGH_TIME/4);
|
||||
/*
|
||||
* enable output
|
||||
*/
|
||||
i2c_dir_out();
|
||||
/*
|
||||
* remove ACK clock pulse
|
||||
*/
|
||||
i2c_data(I2C_DATA_HIGH);
|
||||
i2c_delay(CLOCK_LOW_TIME/2);
|
||||
return ack;
|
||||
}
|
||||
|
||||
/*#---------------------------------------------------------------------------
|
||||
*#
|
||||
*# FUNCTION NAME: I2C::sendAck
|
||||
*#
|
||||
*# DESCRIPTION : Send ACK on received data
|
||||
*#
|
||||
*#--------------------------------------------------------------------------*/
|
||||
void
|
||||
i2c_sendack(void)
|
||||
{
|
||||
/*
|
||||
* enable output
|
||||
*/
|
||||
i2c_delay(CLOCK_LOW_TIME);
|
||||
i2c_dir_out();
|
||||
/*
|
||||
* set ack pulse high
|
||||
*/
|
||||
i2c_data(I2C_DATA_LOW);
|
||||
/*
|
||||
* generate clock pulse
|
||||
*/
|
||||
i2c_delay(CLOCK_HIGH_TIME/6);
|
||||
i2c_clk(I2C_CLOCK_HIGH);
|
||||
i2c_delay(CLOCK_HIGH_TIME);
|
||||
i2c_clk(I2C_CLOCK_LOW);
|
||||
i2c_delay(CLOCK_LOW_TIME/6);
|
||||
/*
|
||||
* reset data out
|
||||
*/
|
||||
i2c_data(I2C_DATA_HIGH);
|
||||
i2c_delay(CLOCK_LOW_TIME);
|
||||
|
||||
i2c_dir_in();
|
||||
}
|
||||
|
||||
/*#---------------------------------------------------------------------------
|
||||
*#
|
||||
*# FUNCTION NAME: i2c_sendnack
|
||||
*#
|
||||
*# DESCRIPTION : Sends NACK on received data
|
||||
*#
|
||||
*#--------------------------------------------------------------------------*/
|
||||
void
|
||||
i2c_sendnack(void)
|
||||
{
|
||||
/*
|
||||
* enable output
|
||||
*/
|
||||
i2c_delay(CLOCK_LOW_TIME);
|
||||
i2c_dir_out();
|
||||
/*
|
||||
* set data high
|
||||
*/
|
||||
i2c_data(I2C_DATA_HIGH);
|
||||
/*
|
||||
* generate clock pulse
|
||||
*/
|
||||
i2c_delay(CLOCK_HIGH_TIME/6);
|
||||
i2c_clk(I2C_CLOCK_HIGH);
|
||||
i2c_delay(CLOCK_HIGH_TIME);
|
||||
i2c_clk(I2C_CLOCK_LOW);
|
||||
i2c_delay(CLOCK_LOW_TIME);
|
||||
|
||||
i2c_dir_in();
|
||||
}
|
||||
|
||||
/*#---------------------------------------------------------------------------
|
||||
*#
|
||||
*# FUNCTION NAME: i2c_writereg
|
||||
*#
|
||||
*# DESCRIPTION : Writes a value to an I2C device
|
||||
*#
|
||||
*#--------------------------------------------------------------------------*/
|
||||
int
|
||||
i2c_writereg(unsigned char theSlave, unsigned char theReg,
|
||||
unsigned char theValue)
|
||||
{
|
||||
int error, cntr = 3;
|
||||
unsigned long flags;
|
||||
|
||||
do {
|
||||
error = 0;
|
||||
/*
|
||||
* we don't like to be interrupted
|
||||
*/
|
||||
local_irq_save(flags);
|
||||
|
||||
i2c_start();
|
||||
/*
|
||||
* send slave address
|
||||
*/
|
||||
i2c_outbyte((theSlave & 0xfe));
|
||||
/*
|
||||
* wait for ack
|
||||
*/
|
||||
if(!i2c_getack())
|
||||
error = 1;
|
||||
/*
|
||||
* now select register
|
||||
*/
|
||||
i2c_dir_out();
|
||||
i2c_outbyte(theReg);
|
||||
/*
|
||||
* now it's time to wait for ack
|
||||
*/
|
||||
if(!i2c_getack())
|
||||
error |= 2;
|
||||
/*
|
||||
* send register register data
|
||||
*/
|
||||
i2c_outbyte(theValue);
|
||||
/*
|
||||
* now it's time to wait for ack
|
||||
*/
|
||||
if(!i2c_getack())
|
||||
error |= 4;
|
||||
/*
|
||||
* end byte stream
|
||||
*/
|
||||
i2c_stop();
|
||||
/*
|
||||
* enable interrupt again
|
||||
*/
|
||||
local_irq_restore(flags);
|
||||
|
||||
} while(error && cntr--);
|
||||
|
||||
i2c_delay(CLOCK_LOW_TIME);
|
||||
|
||||
return -error;
|
||||
}
|
||||
|
||||
/*#---------------------------------------------------------------------------
|
||||
*#
|
||||
*# FUNCTION NAME: i2c_readreg
|
||||
*#
|
||||
*# DESCRIPTION : Reads a value from the decoder registers.
|
||||
*#
|
||||
*#--------------------------------------------------------------------------*/
|
||||
unsigned char
|
||||
i2c_readreg(unsigned char theSlave, unsigned char theReg)
|
||||
{
|
||||
unsigned char b = 0;
|
||||
int error, cntr = 3;
|
||||
unsigned long flags;
|
||||
|
||||
do {
|
||||
error = 0;
|
||||
/*
|
||||
* we don't like to be interrupted
|
||||
*/
|
||||
local_irq_save(flags);
|
||||
/*
|
||||
* generate start condition
|
||||
*/
|
||||
i2c_start();
|
||||
|
||||
/*
|
||||
* send slave address
|
||||
*/
|
||||
i2c_outbyte((theSlave & 0xfe));
|
||||
/*
|
||||
* wait for ack
|
||||
*/
|
||||
if(!i2c_getack())
|
||||
error = 1;
|
||||
/*
|
||||
* now select register
|
||||
*/
|
||||
i2c_dir_out();
|
||||
i2c_outbyte(theReg);
|
||||
/*
|
||||
* now it's time to wait for ack
|
||||
*/
|
||||
if(!i2c_getack())
|
||||
error = 1;
|
||||
/*
|
||||
* repeat start condition
|
||||
*/
|
||||
i2c_delay(CLOCK_LOW_TIME);
|
||||
i2c_start();
|
||||
/*
|
||||
* send slave address
|
||||
*/
|
||||
i2c_outbyte(theSlave | 0x01);
|
||||
/*
|
||||
* wait for ack
|
||||
*/
|
||||
if(!i2c_getack())
|
||||
error = 1;
|
||||
/*
|
||||
* fetch register
|
||||
*/
|
||||
b = i2c_inbyte();
|
||||
/*
|
||||
* last received byte needs to be nacked
|
||||
* instead of acked
|
||||
*/
|
||||
i2c_sendnack();
|
||||
/*
|
||||
* end sequence
|
||||
*/
|
||||
i2c_stop();
|
||||
/*
|
||||
* enable interrupt again
|
||||
*/
|
||||
local_irq_restore(flags);
|
||||
|
||||
} while(error && cntr--);
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
static int
|
||||
i2c_open(struct inode *inode, struct file *filp)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
i2c_release(struct inode *inode, struct file *filp)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Main device API. ioctl's to write or read to/from i2c registers.
|
||||
*/
|
||||
|
||||
static int
|
||||
i2c_ioctl(struct inode *inode, struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
if(_IOC_TYPE(cmd) != ETRAXI2C_IOCTYPE) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (_IOC_NR(cmd)) {
|
||||
case I2C_WRITEREG:
|
||||
/* write to an i2c slave */
|
||||
D(printk("i2cw %d %d %d\n",
|
||||
I2C_ARGSLAVE(arg),
|
||||
I2C_ARGREG(arg),
|
||||
I2C_ARGVALUE(arg)));
|
||||
|
||||
return i2c_writereg(I2C_ARGSLAVE(arg),
|
||||
I2C_ARGREG(arg),
|
||||
I2C_ARGVALUE(arg));
|
||||
case I2C_READREG:
|
||||
{
|
||||
unsigned char val;
|
||||
/* read from an i2c slave */
|
||||
D(printk("i2cr %d %d ",
|
||||
I2C_ARGSLAVE(arg),
|
||||
I2C_ARGREG(arg)));
|
||||
val = i2c_readreg(I2C_ARGSLAVE(arg), I2C_ARGREG(arg));
|
||||
D(printk("= %d\n", val));
|
||||
return val;
|
||||
}
|
||||
default:
|
||||
return -EINVAL;
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct file_operations i2c_fops = {
|
||||
owner: THIS_MODULE,
|
||||
ioctl: i2c_ioctl,
|
||||
open: i2c_open,
|
||||
release: i2c_release,
|
||||
};
|
||||
|
||||
int __init
|
||||
i2c_init(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
/* Setup and enable the Port B I2C interface */
|
||||
|
||||
crisv32_io_get_name(&cris_i2c_data, CONFIG_ETRAX_I2C_DATA_PORT);
|
||||
crisv32_io_get_name(&cris_i2c_clk, CONFIG_ETRAX_I2C_CLK_PORT);
|
||||
|
||||
/* register char device */
|
||||
|
||||
res = register_chrdev(I2C_MAJOR, i2c_name, &i2c_fops);
|
||||
if(res < 0) {
|
||||
printk(KERN_ERR "i2c: couldn't get a major number.\n");
|
||||
return res;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "I2C driver v2.2, (c) 1999-2001 Axis Communications AB\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* this makes sure that i2c_init is called during boot */
|
||||
|
||||
module_init(i2c_init);
|
||||
|
||||
/****************** END OF FILE i2c.c ********************************/
|
|
@ -0,0 +1,15 @@
|
|||
|
||||
#include <linux/init.h>
|
||||
|
||||
/* High level I2C actions */
|
||||
int __init i2c_init(void);
|
||||
int i2c_writereg(unsigned char theSlave, unsigned char theReg, unsigned char theValue);
|
||||
unsigned char i2c_readreg(unsigned char theSlave, unsigned char theReg);
|
||||
|
||||
/* Low level I2C */
|
||||
void i2c_start(void);
|
||||
void i2c_stop(void);
|
||||
void i2c_outbyte(unsigned char x);
|
||||
unsigned char i2c_inbyte(void);
|
||||
int i2c_getack(void);
|
||||
void i2c_sendack(void);
|
|
@ -0,0 +1,219 @@
|
|||
/* $Id: iop_fw_load.c,v 1.4 2005/04/07 09:27:46 larsv Exp $
|
||||
*
|
||||
* Firmware loader for ETRAX FS IO-Processor
|
||||
*
|
||||
* Copyright (C) 2004 Axis Communications AB
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/firmware.h>
|
||||
|
||||
#include <asm/arch/hwregs/reg_map.h>
|
||||
#include <asm/arch/hwregs/iop/iop_reg_space.h>
|
||||
#include <asm/arch/hwregs/iop/iop_mpu_macros.h>
|
||||
#include <asm/arch/hwregs/iop/iop_mpu_defs.h>
|
||||
#include <asm/arch/hwregs/iop/iop_spu_defs.h>
|
||||
#include <asm/arch/hwregs/iop/iop_sw_cpu_defs.h>
|
||||
|
||||
#define IOP_TIMEOUT 100
|
||||
|
||||
static struct device iop_spu_device[2] = {
|
||||
{ .bus_id = "iop-spu0", },
|
||||
{ .bus_id = "iop-spu1", },
|
||||
};
|
||||
|
||||
static struct device iop_mpu_device = {
|
||||
.bus_id = "iop-mpu",
|
||||
};
|
||||
|
||||
static int wait_mpu_idle(void)
|
||||
{
|
||||
reg_iop_mpu_r_stat mpu_stat;
|
||||
unsigned int timeout = IOP_TIMEOUT;
|
||||
|
||||
do {
|
||||
mpu_stat = REG_RD(iop_mpu, regi_iop_mpu, r_stat);
|
||||
} while (mpu_stat.instr_reg_busy == regk_iop_mpu_yes && --timeout > 0);
|
||||
if (timeout == 0) {
|
||||
printk(KERN_ERR "Timeout waiting for MPU to be idle\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iop_fw_load_spu(const unsigned char *fw_name, unsigned int spu_inst)
|
||||
{
|
||||
reg_iop_sw_cpu_rw_mc_ctrl mc_ctrl = {
|
||||
.wr_spu0_mem = regk_iop_sw_cpu_no,
|
||||
.wr_spu1_mem = regk_iop_sw_cpu_no,
|
||||
.size = 4,
|
||||
.cmd = regk_iop_sw_cpu_reg_copy,
|
||||
.keep_owner = regk_iop_sw_cpu_yes
|
||||
};
|
||||
reg_iop_spu_rw_ctrl spu_ctrl = {
|
||||
.en = regk_iop_spu_no,
|
||||
.fsm = regk_iop_spu_no,
|
||||
};
|
||||
reg_iop_sw_cpu_r_mc_stat mc_stat;
|
||||
const struct firmware *fw_entry;
|
||||
u32 *data;
|
||||
unsigned int timeout;
|
||||
int retval, i;
|
||||
|
||||
if (spu_inst > 1)
|
||||
return -ENODEV;
|
||||
|
||||
/* get firmware */
|
||||
retval = request_firmware(&fw_entry,
|
||||
fw_name,
|
||||
&iop_spu_device[spu_inst]);
|
||||
if (retval != 0)
|
||||
{
|
||||
printk(KERN_ERR
|
||||
"iop_load_spu: Failed to load firmware \"%s\"\n",
|
||||
fw_name);
|
||||
return retval;
|
||||
}
|
||||
data = (u32 *) fw_entry->data;
|
||||
|
||||
/* acquire ownership of memory controller */
|
||||
switch (spu_inst) {
|
||||
case 0:
|
||||
mc_ctrl.wr_spu0_mem = regk_iop_sw_cpu_yes;
|
||||
REG_WR(iop_spu, regi_iop_spu0, rw_ctrl, spu_ctrl);
|
||||
break;
|
||||
case 1:
|
||||
mc_ctrl.wr_spu1_mem = regk_iop_sw_cpu_yes;
|
||||
REG_WR(iop_spu, regi_iop_spu1, rw_ctrl, spu_ctrl);
|
||||
break;
|
||||
}
|
||||
timeout = IOP_TIMEOUT;
|
||||
do {
|
||||
REG_WR(iop_sw_cpu, regi_iop_sw_cpu, rw_mc_ctrl, mc_ctrl);
|
||||
mc_stat = REG_RD(iop_sw_cpu, regi_iop_sw_cpu, r_mc_stat);
|
||||
} while (mc_stat.owned_by_cpu == regk_iop_sw_cpu_no && --timeout > 0);
|
||||
if (timeout == 0) {
|
||||
printk(KERN_ERR "Timeout waiting to acquire MC\n");
|
||||
retval = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* write to SPU memory */
|
||||
for (i = 0; i < (fw_entry->size/4); i++) {
|
||||
switch (spu_inst) {
|
||||
case 0:
|
||||
REG_WR_INT(iop_spu, regi_iop_spu0, rw_seq_pc, (i*4));
|
||||
break;
|
||||
case 1:
|
||||
REG_WR_INT(iop_spu, regi_iop_spu1, rw_seq_pc, (i*4));
|
||||
break;
|
||||
}
|
||||
REG_WR_INT(iop_sw_cpu, regi_iop_sw_cpu, rw_mc_data, *data);
|
||||
data++;
|
||||
}
|
||||
|
||||
/* release ownership of memory controller */
|
||||
(void) REG_RD(iop_sw_cpu, regi_iop_sw_cpu, rs_mc_data);
|
||||
|
||||
out:
|
||||
release_firmware(fw_entry);
|
||||
return retval;
|
||||
}
|
||||
|
||||
int iop_fw_load_mpu(unsigned char *fw_name)
|
||||
{
|
||||
const unsigned int start_addr = 0;
|
||||
reg_iop_mpu_rw_ctrl mpu_ctrl;
|
||||
const struct firmware *fw_entry;
|
||||
u32 *data;
|
||||
int retval, i;
|
||||
|
||||
/* get firmware */
|
||||
retval = request_firmware(&fw_entry, fw_name, &iop_mpu_device);
|
||||
if (retval != 0)
|
||||
{
|
||||
printk(KERN_ERR
|
||||
"iop_load_spu: Failed to load firmware \"%s\"\n",
|
||||
fw_name);
|
||||
return retval;
|
||||
}
|
||||
data = (u32 *) fw_entry->data;
|
||||
|
||||
/* disable MPU */
|
||||
mpu_ctrl.en = regk_iop_mpu_no;
|
||||
REG_WR(iop_mpu, regi_iop_mpu, rw_ctrl, mpu_ctrl);
|
||||
/* put start address in R0 */
|
||||
REG_WR_VECT(iop_mpu, regi_iop_mpu, rw_r, 0, start_addr);
|
||||
/* write to memory by executing 'SWX i, 4, R0' for each word */
|
||||
if ((retval = wait_mpu_idle()) != 0)
|
||||
goto out;
|
||||
REG_WR(iop_mpu, regi_iop_mpu, rw_instr, MPU_SWX_IIR_INSTR(0, 4, 0));
|
||||
for (i = 0; i < (fw_entry->size / 4); i++) {
|
||||
REG_WR_INT(iop_mpu, regi_iop_mpu, rw_immediate, *data);
|
||||
if ((retval = wait_mpu_idle()) != 0)
|
||||
goto out;
|
||||
data++;
|
||||
}
|
||||
|
||||
out:
|
||||
release_firmware(fw_entry);
|
||||
return retval;
|
||||
}
|
||||
|
||||
int iop_start_mpu(unsigned int start_addr)
|
||||
{
|
||||
reg_iop_mpu_rw_ctrl mpu_ctrl = { .en = regk_iop_mpu_yes };
|
||||
int retval;
|
||||
|
||||
/* disable MPU */
|
||||
if ((retval = wait_mpu_idle()) != 0)
|
||||
goto out;
|
||||
REG_WR(iop_mpu, regi_iop_mpu, rw_instr, MPU_HALT());
|
||||
if ((retval = wait_mpu_idle()) != 0)
|
||||
goto out;
|
||||
/* set PC and wait for it to bite */
|
||||
if ((retval = wait_mpu_idle()) != 0)
|
||||
goto out;
|
||||
REG_WR_INT(iop_mpu, regi_iop_mpu, rw_instr, MPU_BA_I(start_addr));
|
||||
if ((retval = wait_mpu_idle()) != 0)
|
||||
goto out;
|
||||
/* make sure the MPU starts executing with interrupts disabled */
|
||||
REG_WR(iop_mpu, regi_iop_mpu, rw_instr, MPU_DI());
|
||||
if ((retval = wait_mpu_idle()) != 0)
|
||||
goto out;
|
||||
/* enable MPU */
|
||||
REG_WR(iop_mpu, regi_iop_mpu, rw_ctrl, mpu_ctrl);
|
||||
out:
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int __init iop_fw_load_init(void)
|
||||
{
|
||||
device_initialize(&iop_spu_device[0]);
|
||||
kobject_set_name(&iop_spu_device[0].kobj, "iop-spu0");
|
||||
kobject_add(&iop_spu_device[0].kobj);
|
||||
device_initialize(&iop_spu_device[1]);
|
||||
kobject_set_name(&iop_spu_device[1].kobj, "iop-spu1");
|
||||
kobject_add(&iop_spu_device[1].kobj);
|
||||
device_initialize(&iop_mpu_device);
|
||||
kobject_set_name(&iop_mpu_device.kobj, "iop-mpu");
|
||||
kobject_add(&iop_mpu_device.kobj);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit iop_fw_load_exit(void)
|
||||
{
|
||||
}
|
||||
|
||||
module_init(iop_fw_load_init);
|
||||
module_exit(iop_fw_load_exit);
|
||||
|
||||
MODULE_DESCRIPTION("ETRAX FS IO-Processor Firmware Loader");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
EXPORT_SYMBOL(iop_fw_load_spu);
|
||||
EXPORT_SYMBOL(iop_fw_load_mpu);
|
||||
EXPORT_SYMBOL(iop_start_mpu);
|
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
* arch/cris/arch-v32/drivers/nandflash.c
|
||||
*
|
||||
* Copyright (c) 2004
|
||||
*
|
||||
* Derived from drivers/mtd/nand/spia.c
|
||||
* Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
|
||||
*
|
||||
* $Id: nandflash.c,v 1.3 2005/06/01 10:57:12 starvik Exp $
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/version.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mtd/mtd.h>
|
||||
#include <linux/mtd/nand.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
#include <asm/arch/memmap.h>
|
||||
#include <asm/arch/hwregs/reg_map.h>
|
||||
#include <asm/arch/hwregs/reg_rdwr.h>
|
||||
#include <asm/arch/hwregs/gio_defs.h>
|
||||
#include <asm/arch/hwregs/bif_core_defs.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#define CE_BIT 4
|
||||
#define CLE_BIT 5
|
||||
#define ALE_BIT 6
|
||||
#define BY_BIT 7
|
||||
|
||||
static struct mtd_info *crisv32_mtd = NULL;
|
||||
/*
|
||||
* hardware specific access to control-lines
|
||||
*/
|
||||
static void crisv32_hwcontrol(struct mtd_info *mtd, int cmd)
|
||||
{
|
||||
unsigned long flags;
|
||||
reg_gio_rw_pa_dout dout = REG_RD(gio, regi_gio, rw_pa_dout);
|
||||
|
||||
local_irq_save(flags);
|
||||
switch(cmd){
|
||||
case NAND_CTL_SETCLE:
|
||||
dout.data |= (1<<CLE_BIT);
|
||||
break;
|
||||
case NAND_CTL_CLRCLE:
|
||||
dout.data &= ~(1<<CLE_BIT);
|
||||
break;
|
||||
case NAND_CTL_SETALE:
|
||||
dout.data |= (1<<ALE_BIT);
|
||||
break;
|
||||
case NAND_CTL_CLRALE:
|
||||
dout.data &= ~(1<<ALE_BIT);
|
||||
break;
|
||||
case NAND_CTL_SETNCE:
|
||||
dout.data |= (1<<CE_BIT);
|
||||
break;
|
||||
case NAND_CTL_CLRNCE:
|
||||
dout.data &= ~(1<<CE_BIT);
|
||||
break;
|
||||
}
|
||||
REG_WR(gio, regi_gio, rw_pa_dout, dout);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* read device ready pin
|
||||
*/
|
||||
int crisv32_device_ready(struct mtd_info *mtd)
|
||||
{
|
||||
reg_gio_r_pa_din din = REG_RD(gio, regi_gio, r_pa_din);
|
||||
return ((din.data & (1 << BY_BIT)) >> BY_BIT);
|
||||
}
|
||||
|
||||
/*
|
||||
* Main initialization routine
|
||||
*/
|
||||
struct mtd_info* __init crisv32_nand_flash_probe (void)
|
||||
{
|
||||
void __iomem *read_cs;
|
||||
void __iomem *write_cs;
|
||||
|
||||
reg_bif_core_rw_grp3_cfg bif_cfg = REG_RD(bif_core, regi_bif_core, rw_grp3_cfg);
|
||||
reg_gio_rw_pa_oe pa_oe = REG_RD(gio, regi_gio, rw_pa_oe);
|
||||
struct nand_chip *this;
|
||||
int err = 0;
|
||||
|
||||
/* Allocate memory for MTD device structure and private data */
|
||||
crisv32_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip),
|
||||
GFP_KERNEL);
|
||||
if (!crisv32_mtd) {
|
||||
printk ("Unable to allocate CRISv32 NAND MTD device structure.\n");
|
||||
err = -ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
read_cs = ioremap(MEM_CSP0_START | MEM_NON_CACHEABLE, 8192);
|
||||
write_cs = ioremap(MEM_CSP1_START | MEM_NON_CACHEABLE, 8192);
|
||||
|
||||
if (!read_cs || !write_cs) {
|
||||
printk("CRISv32 NAND ioremap failed\n");
|
||||
err = -EIO;
|
||||
goto out_mtd;
|
||||
}
|
||||
|
||||
/* Get pointer to private data */
|
||||
this = (struct nand_chip *) (&crisv32_mtd[1]);
|
||||
|
||||
pa_oe.oe |= 1 << CE_BIT;
|
||||
pa_oe.oe |= 1 << ALE_BIT;
|
||||
pa_oe.oe |= 1 << CLE_BIT;
|
||||
pa_oe.oe &= ~ (1 << BY_BIT);
|
||||
REG_WR(gio, regi_gio, rw_pa_oe, pa_oe);
|
||||
|
||||
bif_cfg.gated_csp0 = regk_bif_core_rd;
|
||||
bif_cfg.gated_csp1 = regk_bif_core_wr;
|
||||
REG_WR(bif_core, regi_bif_core, rw_grp3_cfg, bif_cfg);
|
||||
|
||||
/* Initialize structures */
|
||||
memset((char *) crisv32_mtd, 0, sizeof(struct mtd_info));
|
||||
memset((char *) this, 0, sizeof(struct nand_chip));
|
||||
|
||||
/* Link the private data with the MTD structure */
|
||||
crisv32_mtd->priv = this;
|
||||
|
||||
/* Set address of NAND IO lines */
|
||||
this->IO_ADDR_R = read_cs;
|
||||
this->IO_ADDR_W = write_cs;
|
||||
this->hwcontrol = crisv32_hwcontrol;
|
||||
this->dev_ready = crisv32_device_ready;
|
||||
/* 20 us command delay time */
|
||||
this->chip_delay = 20;
|
||||
this->eccmode = NAND_ECC_SOFT;
|
||||
|
||||
/* Enable the following for a flash based bad block table */
|
||||
this->options = NAND_USE_FLASH_BBT;
|
||||
|
||||
/* Scan to find existance of the device */
|
||||
if (nand_scan (crisv32_mtd, 1)) {
|
||||
err = -ENXIO;
|
||||
goto out_ior;
|
||||
}
|
||||
|
||||
return crisv32_mtd;
|
||||
|
||||
out_ior:
|
||||
iounmap((void *)read_cs);
|
||||
iounmap((void *)write_cs);
|
||||
out_mtd:
|
||||
kfree (crisv32_mtd);
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -0,0 +1,341 @@
|
|||
/*
|
||||
* PCF8563 RTC
|
||||
*
|
||||
* From Phillips' datasheet:
|
||||
*
|
||||
* The PCF8563 is a CMOS real-time clock/calendar optimized for low power
|
||||
* consumption. A programmable clock output, interupt output and voltage
|
||||
* low detector are also provided. All address and data are transferred
|
||||
* serially via two-line bidirectional I2C-bus. Maximum bus speed is
|
||||
* 400 kbits/s. The built-in word address register is incremented
|
||||
* automatically after each written or read byte.
|
||||
*
|
||||
* Copyright (c) 2002-2003, Axis Communications AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Author: Tobias Anderberg <tobiasa@axis.com>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/ioctl.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/bcd.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/rtc.h>
|
||||
|
||||
#include "i2c.h"
|
||||
|
||||
#define PCF8563_MAJOR 121 /* Local major number. */
|
||||
#define DEVICE_NAME "rtc" /* Name which is registered in /proc/devices. */
|
||||
#define PCF8563_NAME "PCF8563"
|
||||
#define DRIVER_VERSION "$Revision: 1.1 $"
|
||||
|
||||
/* Two simple wrapper macros, saves a few keystrokes. */
|
||||
#define rtc_read(x) i2c_readreg(RTC_I2C_READ, x)
|
||||
#define rtc_write(x,y) i2c_writereg(RTC_I2C_WRITE, x, y)
|
||||
|
||||
static const unsigned char days_in_month[] =
|
||||
{ 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||
|
||||
int pcf8563_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
|
||||
int pcf8563_open(struct inode *, struct file *);
|
||||
int pcf8563_release(struct inode *, struct file *);
|
||||
|
||||
static struct file_operations pcf8563_fops = {
|
||||
owner: THIS_MODULE,
|
||||
ioctl: pcf8563_ioctl,
|
||||
open: pcf8563_open,
|
||||
release: pcf8563_release,
|
||||
};
|
||||
|
||||
unsigned char
|
||||
pcf8563_readreg(int reg)
|
||||
{
|
||||
unsigned char res = rtc_read(reg);
|
||||
|
||||
/* The PCF8563 does not return 0 for unimplemented bits */
|
||||
switch (reg) {
|
||||
case RTC_SECONDS:
|
||||
case RTC_MINUTES:
|
||||
res &= 0x7F;
|
||||
break;
|
||||
case RTC_HOURS:
|
||||
case RTC_DAY_OF_MONTH:
|
||||
res &= 0x3F;
|
||||
break;
|
||||
case RTC_WEEKDAY:
|
||||
res &= 0x07;
|
||||
break;
|
||||
case RTC_MONTH:
|
||||
res &= 0x1F;
|
||||
break;
|
||||
case RTC_CONTROL1:
|
||||
res &= 0xA8;
|
||||
break;
|
||||
case RTC_CONTROL2:
|
||||
res &= 0x1F;
|
||||
break;
|
||||
case RTC_CLOCKOUT_FREQ:
|
||||
case RTC_TIMER_CONTROL:
|
||||
res &= 0x83;
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void
|
||||
pcf8563_writereg(int reg, unsigned char val)
|
||||
{
|
||||
#ifdef CONFIG_ETRAX_RTC_READONLY
|
||||
if (reg == RTC_CONTROL1 || (reg >= RTC_SECONDS && reg <= RTC_YEAR))
|
||||
return;
|
||||
#endif
|
||||
|
||||
rtc_write(reg, val);
|
||||
}
|
||||
|
||||
void
|
||||
get_rtc_time(struct rtc_time *tm)
|
||||
{
|
||||
tm->tm_sec = rtc_read(RTC_SECONDS);
|
||||
tm->tm_min = rtc_read(RTC_MINUTES);
|
||||
tm->tm_hour = rtc_read(RTC_HOURS);
|
||||
tm->tm_mday = rtc_read(RTC_DAY_OF_MONTH);
|
||||
tm->tm_wday = rtc_read(RTC_WEEKDAY);
|
||||
tm->tm_mon = rtc_read(RTC_MONTH);
|
||||
tm->tm_year = rtc_read(RTC_YEAR);
|
||||
|
||||
if (tm->tm_sec & 0x80)
|
||||
printk(KERN_WARNING "%s: RTC Voltage Low - reliable date/time "
|
||||
"information is no longer guaranteed!\n", PCF8563_NAME);
|
||||
|
||||
tm->tm_year = BCD_TO_BIN(tm->tm_year) + ((tm->tm_mon & 0x80) ? 100 : 0);
|
||||
tm->tm_sec &= 0x7F;
|
||||
tm->tm_min &= 0x7F;
|
||||
tm->tm_hour &= 0x3F;
|
||||
tm->tm_mday &= 0x3F;
|
||||
tm->tm_wday &= 0x07; /* Not coded in BCD. */
|
||||
tm->tm_mon &= 0x1F;
|
||||
|
||||
BCD_TO_BIN(tm->tm_sec);
|
||||
BCD_TO_BIN(tm->tm_min);
|
||||
BCD_TO_BIN(tm->tm_hour);
|
||||
BCD_TO_BIN(tm->tm_mday);
|
||||
BCD_TO_BIN(tm->tm_mon);
|
||||
tm->tm_mon--; /* Month is 1..12 in RTC but 0..11 in linux */
|
||||
}
|
||||
|
||||
int __init
|
||||
pcf8563_init(void)
|
||||
{
|
||||
/* Initiate the i2c protocol. */
|
||||
i2c_init();
|
||||
|
||||
/*
|
||||
* First of all we need to reset the chip. This is done by
|
||||
* clearing control1, control2 and clk freq and resetting
|
||||
* all alarms.
|
||||
*/
|
||||
if (rtc_write(RTC_CONTROL1, 0x00) < 0)
|
||||
goto err;
|
||||
|
||||
if (rtc_write(RTC_CONTROL2, 0x00) < 0)
|
||||
goto err;
|
||||
|
||||
if (rtc_write(RTC_CLOCKOUT_FREQ, 0x00) < 0)
|
||||
goto err;
|
||||
|
||||
if (rtc_write(RTC_TIMER_CONTROL, 0x03) < 0)
|
||||
goto err;
|
||||
|
||||
/* Reset the alarms. */
|
||||
if (rtc_write(RTC_MINUTE_ALARM, 0x80) < 0)
|
||||
goto err;
|
||||
|
||||
if (rtc_write(RTC_HOUR_ALARM, 0x80) < 0)
|
||||
goto err;
|
||||
|
||||
if (rtc_write(RTC_DAY_ALARM, 0x80) < 0)
|
||||
goto err;
|
||||
|
||||
if (rtc_write(RTC_WEEKDAY_ALARM, 0x80) < 0)
|
||||
goto err;
|
||||
|
||||
if (register_chrdev(PCF8563_MAJOR, DEVICE_NAME, &pcf8563_fops) < 0) {
|
||||
printk(KERN_INFO "%s: Unable to get major numer %d for RTC device.\n",
|
||||
PCF8563_NAME, PCF8563_MAJOR);
|
||||
return -1;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "%s Real-Time Clock Driver, %s\n", PCF8563_NAME, DRIVER_VERSION);
|
||||
|
||||
/* Check for low voltage, and warn about it.. */
|
||||
if (rtc_read(RTC_SECONDS) & 0x80)
|
||||
printk(KERN_WARNING "%s: RTC Voltage Low - reliable date/time "
|
||||
"information is no longer guaranteed!\n", PCF8563_NAME);
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
printk(KERN_INFO "%s: Error initializing chip.\n", PCF8563_NAME);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void __exit
|
||||
pcf8563_exit(void)
|
||||
{
|
||||
if (unregister_chrdev(PCF8563_MAJOR, DEVICE_NAME) < 0) {
|
||||
printk(KERN_INFO "%s: Unable to unregister device.\n", PCF8563_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ioctl calls for this driver. Why return -ENOTTY upon error? Because
|
||||
* POSIX says so!
|
||||
*/
|
||||
int
|
||||
pcf8563_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
/* Some sanity checks. */
|
||||
if (_IOC_TYPE(cmd) != RTC_MAGIC)
|
||||
return -ENOTTY;
|
||||
|
||||
if (_IOC_NR(cmd) > RTC_MAX_IOCTL)
|
||||
return -ENOTTY;
|
||||
|
||||
switch (cmd) {
|
||||
case RTC_RD_TIME:
|
||||
{
|
||||
struct rtc_time tm;
|
||||
|
||||
memset(&tm, 0, sizeof (struct rtc_time));
|
||||
get_rtc_time(&tm);
|
||||
|
||||
if (copy_to_user((struct rtc_time *) arg, &tm, sizeof tm)) {
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
case RTC_SET_TIME:
|
||||
{
|
||||
#ifdef CONFIG_ETRAX_RTC_READONLY
|
||||
return -EPERM;
|
||||
#else
|
||||
int leap;
|
||||
int year;
|
||||
int century;
|
||||
struct rtc_time tm;
|
||||
|
||||
if (!capable(CAP_SYS_TIME))
|
||||
return -EPERM;
|
||||
|
||||
if (copy_from_user(&tm, (struct rtc_time *) arg, sizeof tm))
|
||||
return -EFAULT;
|
||||
|
||||
/* Convert from struct tm to struct rtc_time. */
|
||||
tm.tm_year += 1900;
|
||||
tm.tm_mon += 1;
|
||||
|
||||
/*
|
||||
* Check if tm.tm_year is a leap year. A year is a leap
|
||||
* year if it is divisible by 4 but not 100, except
|
||||
* that years divisible by 400 _are_ leap years.
|
||||
*/
|
||||
year = tm.tm_year;
|
||||
leap = (tm.tm_mon == 2) && ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0);
|
||||
|
||||
/* Perform some sanity checks. */
|
||||
if ((tm.tm_year < 1970) ||
|
||||
(tm.tm_mon > 12) ||
|
||||
(tm.tm_mday == 0) ||
|
||||
(tm.tm_mday > days_in_month[tm.tm_mon] + leap) ||
|
||||
(tm.tm_wday >= 7) ||
|
||||
(tm.tm_hour >= 24) ||
|
||||
(tm.tm_min >= 60) ||
|
||||
(tm.tm_sec >= 60))
|
||||
return -EINVAL;
|
||||
|
||||
century = (tm.tm_year >= 2000) ? 0x80 : 0;
|
||||
tm.tm_year = tm.tm_year % 100;
|
||||
|
||||
BIN_TO_BCD(tm.tm_year);
|
||||
BIN_TO_BCD(tm.tm_mday);
|
||||
BIN_TO_BCD(tm.tm_hour);
|
||||
BIN_TO_BCD(tm.tm_min);
|
||||
BIN_TO_BCD(tm.tm_sec);
|
||||
tm.tm_mon |= century;
|
||||
|
||||
rtc_write(RTC_YEAR, tm.tm_year);
|
||||
rtc_write(RTC_MONTH, tm.tm_mon);
|
||||
rtc_write(RTC_WEEKDAY, tm.tm_wday); /* Not coded in BCD. */
|
||||
rtc_write(RTC_DAY_OF_MONTH, tm.tm_mday);
|
||||
rtc_write(RTC_HOURS, tm.tm_hour);
|
||||
rtc_write(RTC_MINUTES, tm.tm_min);
|
||||
rtc_write(RTC_SECONDS, tm.tm_sec);
|
||||
|
||||
return 0;
|
||||
#endif /* !CONFIG_ETRAX_RTC_READONLY */
|
||||
}
|
||||
|
||||
case RTC_VLOW_RD:
|
||||
{
|
||||
int vl_bit = 0;
|
||||
|
||||
if (rtc_read(RTC_SECONDS) & 0x80) {
|
||||
vl_bit = 1;
|
||||
printk(KERN_WARNING "%s: RTC Voltage Low - reliable "
|
||||
"date/time information is no longer guaranteed!\n",
|
||||
PCF8563_NAME);
|
||||
}
|
||||
if (copy_to_user((int *) arg, &vl_bit, sizeof(int)))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
case RTC_VLOW_SET:
|
||||
{
|
||||
/* Clear the VL bit in the seconds register */
|
||||
int ret = rtc_read(RTC_SECONDS);
|
||||
|
||||
rtc_write(RTC_SECONDS, (ret & 0x7F));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
default:
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
pcf8563_open(struct inode *inode, struct file *filp)
|
||||
{
|
||||
MOD_INC_USE_COUNT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
pcf8563_release(struct inode *inode, struct file *filp)
|
||||
{
|
||||
MOD_DEC_USE_COUNT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
module_init(pcf8563_init);
|
||||
module_exit(pcf8563_exit);
|
|
@ -0,0 +1,5 @@
|
|||
#
|
||||
# Makefile for Etrax cardbus driver
|
||||
#
|
||||
|
||||
obj-$(CONFIG_ETRAX_CARDBUS) += bios.o dma.o
|
|
@ -0,0 +1,131 @@
|
|||
#include <linux/pci.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <asm/arch/hwregs/intr_vect.h>
|
||||
|
||||
void __devinit pcibios_fixup_bus(struct pci_bus *b)
|
||||
{
|
||||
}
|
||||
|
||||
char * __devinit pcibios_setup(char *str)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void pcibios_set_master(struct pci_dev *dev)
|
||||
{
|
||||
u8 lat;
|
||||
pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
|
||||
printk(KERN_DEBUG "PCI: Setting latency timer of device %s to %d\n", pci_name(dev), lat);
|
||||
pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
|
||||
}
|
||||
|
||||
int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
|
||||
enum pci_mmap_state mmap_state, int write_combine)
|
||||
{
|
||||
unsigned long prot;
|
||||
|
||||
/* Leave vm_pgoff as-is, the PCI space address is the physical
|
||||
* address on this platform.
|
||||
*/
|
||||
vma->vm_flags |= (VM_SHM | VM_LOCKED | VM_IO);
|
||||
|
||||
prot = pgprot_val(vma->vm_page_prot);
|
||||
vma->vm_page_prot = __pgprot(prot);
|
||||
|
||||
/* Write-combine setting is ignored, it is changed via the mtrr
|
||||
* interfaces on this platform.
|
||||
*/
|
||||
if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
|
||||
vma->vm_end - vma->vm_start,
|
||||
vma->vm_page_prot))
|
||||
return -EAGAIN;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
pcibios_align_resource(void *data, struct resource *res,
|
||||
unsigned long size, unsigned long align)
|
||||
{
|
||||
if (res->flags & IORESOURCE_IO) {
|
||||
unsigned long start = res->start;
|
||||
|
||||
if (start & 0x300) {
|
||||
start = (start + 0x3ff) & ~0x3ff;
|
||||
res->start = start;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int pcibios_enable_resources(struct pci_dev *dev, int mask)
|
||||
{
|
||||
u16 cmd, old_cmd;
|
||||
int idx;
|
||||
struct resource *r;
|
||||
|
||||
pci_read_config_word(dev, PCI_COMMAND, &cmd);
|
||||
old_cmd = cmd;
|
||||
for(idx=0; idx<6; idx++) {
|
||||
/* Only set up the requested stuff */
|
||||
if (!(mask & (1<<idx)))
|
||||
continue;
|
||||
|
||||
r = &dev->resource[idx];
|
||||
if (!r->start && r->end) {
|
||||
printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", pci_name(dev));
|
||||
return -EINVAL;
|
||||
}
|
||||
if (r->flags & IORESOURCE_IO)
|
||||
cmd |= PCI_COMMAND_IO;
|
||||
if (r->flags & IORESOURCE_MEM)
|
||||
cmd |= PCI_COMMAND_MEMORY;
|
||||
}
|
||||
if (dev->resource[PCI_ROM_RESOURCE].start)
|
||||
cmd |= PCI_COMMAND_MEMORY;
|
||||
if (cmd != old_cmd) {
|
||||
printk("PCI: Enabling device %s (%04x -> %04x)\n", pci_name(dev), old_cmd, cmd);
|
||||
pci_write_config_word(dev, PCI_COMMAND, cmd);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pcibios_enable_irq(struct pci_dev *dev)
|
||||
{
|
||||
dev->irq = EXT_INTR_VECT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pcibios_enable_device(struct pci_dev *dev, int mask)
|
||||
{
|
||||
int err;
|
||||
|
||||
if ((err = pcibios_enable_resources(dev, mask)) < 0)
|
||||
return err;
|
||||
|
||||
return pcibios_enable_irq(dev);
|
||||
}
|
||||
|
||||
int pcibios_assign_resources(void)
|
||||
{
|
||||
struct pci_dev *dev = NULL;
|
||||
int idx;
|
||||
struct resource *r;
|
||||
|
||||
while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
|
||||
int class = dev->class >> 8;
|
||||
|
||||
/* Don't touch classless devices and host bridges */
|
||||
if (!class || class == PCI_CLASS_BRIDGE_HOST)
|
||||
continue;
|
||||
|
||||
for(idx=0; idx<6; idx++) {
|
||||
r = &dev->resource[idx];
|
||||
|
||||
if (!r->start && r->end)
|
||||
pci_assign_resource(dev, idx);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(pcibios_assign_resources);
|
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
* Dynamic DMA mapping support.
|
||||
*
|
||||
* On cris there is no hardware dynamic DMA address translation,
|
||||
* so consistent alloc/free are merely page allocation/freeing.
|
||||
* The rest of the dynamic DMA mapping interface is implemented
|
||||
* in asm/pci.h.
|
||||
*
|
||||
* Borrowed from i386.
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/pci.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
struct dma_coherent_mem {
|
||||
void *virt_base;
|
||||
u32 device_base;
|
||||
int size;
|
||||
int flags;
|
||||
unsigned long *bitmap;
|
||||
};
|
||||
|
||||
void *dma_alloc_coherent(struct device *dev, size_t size,
|
||||
dma_addr_t *dma_handle, unsigned int __nocast gfp)
|
||||
{
|
||||
void *ret;
|
||||
struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
|
||||
int order = get_order(size);
|
||||
/* ignore region specifiers */
|
||||
gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
|
||||
|
||||
if (mem) {
|
||||
int page = bitmap_find_free_region(mem->bitmap, mem->size,
|
||||
order);
|
||||
if (page >= 0) {
|
||||
*dma_handle = mem->device_base + (page << PAGE_SHIFT);
|
||||
ret = mem->virt_base + (page << PAGE_SHIFT);
|
||||
memset(ret, 0, size);
|
||||
return ret;
|
||||
}
|
||||
if (mem->flags & DMA_MEMORY_EXCLUSIVE)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff))
|
||||
gfp |= GFP_DMA;
|
||||
|
||||
ret = (void *)__get_free_pages(gfp, order);
|
||||
|
||||
if (ret != NULL) {
|
||||
memset(ret, 0, size);
|
||||
*dma_handle = virt_to_phys(ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void dma_free_coherent(struct device *dev, size_t size,
|
||||
void *vaddr, dma_addr_t dma_handle)
|
||||
{
|
||||
struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
|
||||
int order = get_order(size);
|
||||
|
||||
if (mem && vaddr >= mem->virt_base && vaddr < (mem->virt_base + (mem->size << PAGE_SHIFT))) {
|
||||
int page = (vaddr - mem->virt_base) >> PAGE_SHIFT;
|
||||
|
||||
bitmap_release_region(mem->bitmap, page, order);
|
||||
} else
|
||||
free_pages((unsigned long)vaddr, order);
|
||||
}
|
||||
|
||||
int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
|
||||
dma_addr_t device_addr, size_t size, int flags)
|
||||
{
|
||||
void __iomem *mem_base;
|
||||
int pages = size >> PAGE_SHIFT;
|
||||
int bitmap_size = (pages + 31)/32;
|
||||
|
||||
if ((flags & (DMA_MEMORY_MAP | DMA_MEMORY_IO)) == 0)
|
||||
goto out;
|
||||
if (!size)
|
||||
goto out;
|
||||
if (dev->dma_mem)
|
||||
goto out;
|
||||
|
||||
/* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */
|
||||
|
||||
mem_base = ioremap(bus_addr, size);
|
||||
if (!mem_base)
|
||||
goto out;
|
||||
|
||||
dev->dma_mem = kmalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL);
|
||||
if (!dev->dma_mem)
|
||||
goto out;
|
||||
memset(dev->dma_mem, 0, sizeof(struct dma_coherent_mem));
|
||||
dev->dma_mem->bitmap = kmalloc(bitmap_size, GFP_KERNEL);
|
||||
if (!dev->dma_mem->bitmap)
|
||||
goto free1_out;
|
||||
memset(dev->dma_mem->bitmap, 0, bitmap_size);
|
||||
|
||||
dev->dma_mem->virt_base = mem_base;
|
||||
dev->dma_mem->device_base = device_addr;
|
||||
dev->dma_mem->size = pages;
|
||||
dev->dma_mem->flags = flags;
|
||||
|
||||
if (flags & DMA_MEMORY_MAP)
|
||||
return DMA_MEMORY_MAP;
|
||||
|
||||
return DMA_MEMORY_IO;
|
||||
|
||||
free1_out:
|
||||
kfree(dev->dma_mem->bitmap);
|
||||
out:
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(dma_declare_coherent_memory);
|
||||
|
||||
void dma_release_declared_memory(struct device *dev)
|
||||
{
|
||||
struct dma_coherent_mem *mem = dev->dma_mem;
|
||||
|
||||
if(!mem)
|
||||
return;
|
||||
dev->dma_mem = NULL;
|
||||
iounmap(mem->virt_base);
|
||||
kfree(mem->bitmap);
|
||||
kfree(mem);
|
||||
}
|
||||
EXPORT_SYMBOL(dma_release_declared_memory);
|
||||
|
||||
void *dma_mark_declared_memory_occupied(struct device *dev,
|
||||
dma_addr_t device_addr, size_t size)
|
||||
{
|
||||
struct dma_coherent_mem *mem = dev->dma_mem;
|
||||
int pages = (size + (device_addr & ~PAGE_MASK) + PAGE_SIZE - 1) >> PAGE_SHIFT;
|
||||
int pos, err;
|
||||
|
||||
if (!mem)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
pos = (device_addr - mem->device_base) >> PAGE_SHIFT;
|
||||
err = bitmap_allocate_region(mem->bitmap, pos, get_order(pages));
|
||||
if (err != 0)
|
||||
return ERR_PTR(err);
|
||||
return mem->virt_base + (pos << PAGE_SHIFT);
|
||||
}
|
||||
EXPORT_SYMBOL(dma_mark_declared_memory_occupied);
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче