/spare/repo/netdev-2.6 branch 'master'
This commit is contained in:
commit
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.
|
||||
|
|
114
Documentation/infiniband/core_locking.txt
Normal file
114
Documentation/infiniband/core_locking.txt
Normal file
|
@ -0,0 +1,114 @@
|
|||
INFINIBAND MIDLAYER LOCKING
|
||||
|
||||
This guide is an attempt to make explicit the locking assumptions
|
||||
made by the InfiniBand midlayer. It describes the requirements on
|
||||
both low-level drivers that sit below the midlayer and upper level
|
||||
protocols that use the midlayer.
|
||||
|
||||
Sleeping and interrupt context
|
||||
|
||||
With the following exceptions, a low-level driver implementation of
|
||||
all of the methods in struct ib_device may sleep. The exceptions
|
||||
are any methods from the list:
|
||||
|
||||
create_ah
|
||||
modify_ah
|
||||
query_ah
|
||||
destroy_ah
|
||||
bind_mw
|
||||
post_send
|
||||
post_recv
|
||||
poll_cq
|
||||
req_notify_cq
|
||||
map_phys_fmr
|
||||
|
||||
which may not sleep and must be callable from any context.
|
||||
|
||||
The corresponding functions exported to upper level protocol
|
||||
consumers:
|
||||
|
||||
ib_create_ah
|
||||
ib_modify_ah
|
||||
ib_query_ah
|
||||
ib_destroy_ah
|
||||
ib_bind_mw
|
||||
ib_post_send
|
||||
ib_post_recv
|
||||
ib_req_notify_cq
|
||||
ib_map_phys_fmr
|
||||
|
||||
are therefore safe to call from any context.
|
||||
|
||||
In addition, the function
|
||||
|
||||
ib_dispatch_event
|
||||
|
||||
used by low-level drivers to dispatch asynchronous events through
|
||||
the midlayer is also safe to call from any context.
|
||||
|
||||
Reentrancy
|
||||
|
||||
All of the methods in struct ib_device exported by a low-level
|
||||
driver must be fully reentrant. The low-level driver is required to
|
||||
perform all synchronization necessary to maintain consistency, even
|
||||
if multiple function calls using the same object are run
|
||||
simultaneously.
|
||||
|
||||
The IB midlayer does not perform any serialization of function calls.
|
||||
|
||||
Because low-level drivers are reentrant, upper level protocol
|
||||
consumers are not required to perform any serialization. However,
|
||||
some serialization may be required to get sensible results. For
|
||||
example, a consumer may safely call ib_poll_cq() on multiple CPUs
|
||||
simultaneously. However, the ordering of the work completion
|
||||
information between different calls of ib_poll_cq() is not defined.
|
||||
|
||||
Callbacks
|
||||
|
||||
A low-level driver must not perform a callback directly from the
|
||||
same callchain as an ib_device method call. For example, it is not
|
||||
allowed for a low-level driver to call a consumer's completion event
|
||||
handler directly from its post_send method. Instead, the low-level
|
||||
driver should defer this callback by, for example, scheduling a
|
||||
tasklet to perform the callback.
|
||||
|
||||
The low-level driver is responsible for ensuring that multiple
|
||||
completion event handlers for the same CQ are not called
|
||||
simultaneously. The driver must guarantee that only one CQ event
|
||||
handler for a given CQ is running at a time. In other words, the
|
||||
following situation is not allowed:
|
||||
|
||||
CPU1 CPU2
|
||||
|
||||
low-level driver ->
|
||||
consumer CQ event callback:
|
||||
/* ... */
|
||||
ib_req_notify_cq(cq, ...);
|
||||
low-level driver ->
|
||||
/* ... */ consumer CQ event callback:
|
||||
/* ... */
|
||||
return from CQ event handler
|
||||
|
||||
The context in which completion event and asynchronous event
|
||||
callbacks run is not defined. Depending on the low-level driver, it
|
||||
may be process context, softirq context, or interrupt context.
|
||||
Upper level protocol consumers may not sleep in a callback.
|
||||
|
||||
Hot-plug
|
||||
|
||||
A low-level driver announces that a device is ready for use by
|
||||
consumers when it calls ib_register_device(), all initialization
|
||||
must be complete before this call. The device must remain usable
|
||||
until the driver's call to ib_unregister_device() has returned.
|
||||
|
||||
A low-level driver must call ib_register_device() and
|
||||
ib_unregister_device() from process context. It must not hold any
|
||||
semaphores that could cause deadlock if a consumer calls back into
|
||||
the driver across these calls.
|
||||
|
||||
An upper level protocol consumer may begin using an IB device as
|
||||
soon as the add method of its struct ib_client is called for that
|
||||
device. A consumer must finish all cleanup and free all resources
|
||||
relating to a device before returning from the remove method.
|
||||
|
||||
A consumer is permitted to sleep in its add and remove methods.
|
|
@ -28,13 +28,37 @@ Creating MAD agents
|
|||
|
||||
Receiving MADs
|
||||
|
||||
MADs are received using read(). The buffer passed to read() must be
|
||||
large enough to hold at least one struct ib_user_mad. For example:
|
||||
MADs are received using read(). The receive side now supports
|
||||
RMPP. The buffer passed to read() must be at least one
|
||||
struct ib_user_mad + 256 bytes. For example:
|
||||
|
||||
struct ib_user_mad mad;
|
||||
ret = read(fd, &mad, sizeof mad);
|
||||
if (ret != sizeof mad)
|
||||
If the buffer passed is not large enough to hold the received
|
||||
MAD (RMPP), the errno is set to ENOSPC and the length of the
|
||||
buffer needed is set in mad.length.
|
||||
|
||||
Example for normal MAD (non RMPP) reads:
|
||||
struct ib_user_mad *mad;
|
||||
mad = malloc(sizeof *mad + 256);
|
||||
ret = read(fd, mad, sizeof *mad + 256);
|
||||
if (ret != sizeof mad + 256) {
|
||||
perror("read");
|
||||
free(mad);
|
||||
}
|
||||
|
||||
Example for RMPP reads:
|
||||
struct ib_user_mad *mad;
|
||||
mad = malloc(sizeof *mad + 256);
|
||||
ret = read(fd, mad, sizeof *mad + 256);
|
||||
if (ret == -ENOSPC)) {
|
||||
length = mad.length;
|
||||
free(mad);
|
||||
mad = malloc(sizeof *mad + length);
|
||||
ret = read(fd, mad, sizeof *mad + length);
|
||||
}
|
||||
if (ret < 0) {
|
||||
perror("read");
|
||||
free(mad);
|
||||
}
|
||||
|
||||
In addition to the actual MAD contents, the other struct ib_user_mad
|
||||
fields will be filled in with information on the received MAD. For
|
||||
|
@ -50,18 +74,21 @@ Sending MADs
|
|||
|
||||
MADs are sent using write(). The agent ID for sending should be
|
||||
filled into the id field of the MAD, the destination LID should be
|
||||
filled into the lid field, and so on. For example:
|
||||
filled into the lid field, and so on. The send side does support
|
||||
RMPP so arbitrary length MAD can be sent. For example:
|
||||
|
||||
struct ib_user_mad mad;
|
||||
struct ib_user_mad *mad;
|
||||
|
||||
/* fill in mad.data */
|
||||
mad = malloc(sizeof *mad + mad_length);
|
||||
|
||||
mad.id = my_agent; /* req.id from agent registration */
|
||||
mad.lid = my_dest; /* in network byte order... */
|
||||
/* fill in mad->data */
|
||||
|
||||
mad->hdr.id = my_agent; /* req.id from agent registration */
|
||||
mad->hdr.lid = my_dest; /* in network byte order... */
|
||||
/* etc. */
|
||||
|
||||
ret = write(fd, &mad, sizeof mad);
|
||||
if (ret != sizeof mad)
|
||||
ret = write(fd, &mad, sizeof *mad + mad_length);
|
||||
if (ret != sizeof *mad + mad_length)
|
||||
perror("write");
|
||||
|
||||
Setting IsSM Capability Bit
|
||||
|
|
|
@ -56,3 +56,12 @@ This file details changes in 2.6 which affect PCMCIA card driver authors:
|
|||
memory regions in-use. The name argument should be a pointer to
|
||||
your driver name. Eg, for pcnet_cs, name should point to the
|
||||
string "pcnet_cs".
|
||||
|
||||
* CardServices is gone
|
||||
CardServices() in 2.4 is just a big switch statement to call various
|
||||
services. In 2.6, all of those entry points are exported and called
|
||||
directly (except for pcmcia_report_error(), just use cs_error() instead).
|
||||
|
||||
* struct pcmcia_driver
|
||||
You need to use struct pcmcia_driver and pcmcia_{un,}register_driver
|
||||
instead of {un,}register_pccard_driver
|
||||
|
|
|
@ -388,7 +388,6 @@ Summary:
|
|||
scsi_remove_device - detach and remove a SCSI device
|
||||
scsi_remove_host - detach and remove all SCSI devices owned by host
|
||||
scsi_report_bus_reset - report scsi _bus_ reset observed
|
||||
scsi_set_device - place device reference in host structure
|
||||
scsi_track_queue_full - track successive QUEUE_FULL events
|
||||
scsi_unblock_requests - allow further commands to be queued to given host
|
||||
scsi_unregister - [calls scsi_host_put()]
|
||||
|
@ -740,20 +739,6 @@ int scsi_remove_host(struct Scsi_Host *shost)
|
|||
void scsi_report_bus_reset(struct Scsi_Host * shost, int channel)
|
||||
|
||||
|
||||
/**
|
||||
* scsi_set_device - place device reference in host structure
|
||||
* @shost: a pointer to a scsi host instance
|
||||
* @pdev: pointer to device instance to assign
|
||||
*
|
||||
* Returns nothing
|
||||
*
|
||||
* Might block: no
|
||||
*
|
||||
* Defined in: include/scsi/scsi_host.h .
|
||||
**/
|
||||
void scsi_set_device(struct Scsi_Host * shost, struct device * dev)
|
||||
|
||||
|
||||
/**
|
||||
* scsi_track_queue_full - track successive QUEUE_FULL events on given
|
||||
* device to determine if and when there is a need
|
||||
|
|
|
@ -636,11 +636,16 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
3stack-digout 3-jack in back, a HP out and a SPDIF out
|
||||
5stack 5-jack in back, 2-jack in front
|
||||
5stack-digout 5-jack in back, 2-jack in front, a SPDIF out
|
||||
6stack 6-jack in back, 2-jack in front
|
||||
6stack-digout 6-jack with a SPDIF out
|
||||
w810 3-jack
|
||||
z71v 3-jack (HP shared SPDIF)
|
||||
asus 3-jack
|
||||
uniwill 3-jack
|
||||
F1734 2-jack
|
||||
test for testing/debugging purpose, almost all controls can be
|
||||
adjusted. Appearing only when compiled with
|
||||
$CONFIG_SND_DEBUG=y
|
||||
|
||||
CMI9880
|
||||
minimal 3-jack in back
|
||||
|
@ -1054,6 +1059,13 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-pxa2xx-ac97 (on arm only)
|
||||
------------------------------------
|
||||
|
||||
Module for AC97 driver for the Intel PXA2xx chip
|
||||
|
||||
For ARM architecture only.
|
||||
|
||||
Module snd-rme32
|
||||
----------------
|
||||
|
||||
|
@ -1173,6 +1185,13 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
|
||||
Module supports up to 8 cards.
|
||||
|
||||
Module snd-sun-dbri (on sparc only)
|
||||
-----------------------------------
|
||||
|
||||
Module for DBRI sound chips found on Sparcs.
|
||||
|
||||
Module supports up to 8 cards.
|
||||
|
||||
Module snd-wavefront
|
||||
--------------------
|
||||
|
||||
|
@ -1371,7 +1390,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
Module snd-vxpocket
|
||||
-------------------
|
||||
|
||||
Module for Digigram VX-Pocket VX2 PCMCIA card.
|
||||
Module for Digigram VX-Pocket VX2 and 440 PCMCIA cards.
|
||||
|
||||
ibl - Capture IBL size. (default = 0, minimum size)
|
||||
|
||||
|
@ -1391,29 +1410,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
|
||||
Note: the driver is build only when CONFIG_ISA is set.
|
||||
|
||||
Module snd-vxp440
|
||||
-----------------
|
||||
|
||||
Module for Digigram VX-Pocket 440 PCMCIA card.
|
||||
|
||||
ibl - Capture IBL size. (default = 0, minimum size)
|
||||
|
||||
Module supports up to 8 cards. The module is compiled only when
|
||||
PCMCIA is supported on kernel.
|
||||
|
||||
To activate the driver via the card manager, you'll need to set
|
||||
up /etc/pcmcia/vxp440.conf. See the sound/pcmcia/vx/vxp440.c.
|
||||
|
||||
When the driver is compiled as a module and the hotplug firmware
|
||||
is supported, the firmware data is loaded via hotplug automatically.
|
||||
Install the necessary firmware files in alsa-firmware package.
|
||||
When no hotplug fw loader is available, you need to load the
|
||||
firmware via vxloader utility in alsa-tools package.
|
||||
|
||||
About capture IBL, see the description of snd-vx222 module.
|
||||
|
||||
Note: the driver is build only when CONFIG_ISA is set.
|
||||
|
||||
Module snd-ymfpci
|
||||
-----------------
|
||||
|
||||
|
|
|
@ -132,7 +132,7 @@ to extra work for the USB developers. Since all Linux USB developers do
|
|||
their work on their own time, asking programmers to do extra work for no
|
||||
gain, for free, is not a possibility.
|
||||
|
||||
Security issues are also a very important for Linux. When a
|
||||
Security issues are also very important for Linux. When a
|
||||
security issue is found, it is fixed in a very short amount of time. A
|
||||
number of times this has caused internal kernel interfaces to be
|
||||
reworked to prevent the security problem from occurring. When this
|
||||
|
|
58
Documentation/stable_kernel_rules.txt
Normal file
58
Documentation/stable_kernel_rules.txt
Normal file
|
@ -0,0 +1,58 @@
|
|||
Everything you ever wanted to know about Linux 2.6 -stable releases.
|
||||
|
||||
Rules on what kind of patches are accepted, and what ones are not, into
|
||||
the "-stable" tree:
|
||||
|
||||
- It must be obviously correct and tested.
|
||||
- It can not bigger than 100 lines, with context.
|
||||
- It must fix only one thing.
|
||||
- It must fix a real bug that bothers people (not a, "This could be a
|
||||
problem..." type thing.)
|
||||
- It must fix a problem that causes a build error (but not for things
|
||||
marked CONFIG_BROKEN), an oops, a hang, data corruption, a real
|
||||
security issue, or some "oh, that's not good" issue. In short,
|
||||
something critical.
|
||||
- No "theoretical race condition" issues, unless an explanation of how
|
||||
the race can be exploited.
|
||||
- It can not contain any "trivial" fixes in it (spelling changes,
|
||||
whitespace cleanups, etc.)
|
||||
- It must be accepted by the relevant subsystem maintainer.
|
||||
- It must follow Documentation/SubmittingPatches rules.
|
||||
|
||||
|
||||
Procedure for submitting patches to the -stable tree:
|
||||
|
||||
- Send the patch, after verifying that it follows the above rules, to
|
||||
stable@kernel.org.
|
||||
- The sender will receive an ack when the patch has been accepted into
|
||||
the queue, or a nak if the patch is rejected. This response might
|
||||
take a few days, according to the developer's schedules.
|
||||
- If accepted, the patch will be added to the -stable queue, for review
|
||||
by other developers.
|
||||
- Security patches should not be sent to this alias, but instead to the
|
||||
documented security@kernel.org.
|
||||
|
||||
|
||||
Review cycle:
|
||||
|
||||
- When the -stable maintainers decide for a review cycle, the patches
|
||||
will be sent to the review committee, and the maintainer of the
|
||||
affected area of the patch (unless the submitter is the maintainer of
|
||||
the area) and CC: to the linux-kernel mailing list.
|
||||
- The review committee has 48 hours in which to ack or nak the patch.
|
||||
- If the patch is rejected by a member of the committee, or linux-kernel
|
||||
members object to the patch, bringing up issues that the maintainers
|
||||
and members did not realize, the patch will be dropped from the
|
||||
queue.
|
||||
- At the end of the review cycle, the acked patches will be added to
|
||||
the latest -stable release, and a new -stable release will happen.
|
||||
- Security patches will be accepted into the -stable tree directly from
|
||||
the security kernel team, and not go through the normal review cycle.
|
||||
Contact the kernel security team for more details on this procedure.
|
||||
|
||||
|
||||
Review committe:
|
||||
|
||||
- This will be made up of a number of kernel developers who have
|
||||
volunteered for this task, and a few that haven't.
|
||||
|
|
@ -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 */
|
||||
|
||||
|
|
99
arch/arm/mach-s3c2410/irq.h
Normal file
99
arch/arm/mach-s3c2410/irq.h
Normal file
|
@ -0,0 +1,99 @@
|
|||
/* arch/arm/mach-s3c2410/irq.h
|
||||
*
|
||||
* Copyright (c) 2004-2005 Simtec Electronics
|
||||
* Ben Dooks <ben@simtec.co.uk>
|
||||
*
|
||||
* Header file for S3C24XX CPU IRQ support
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Modifications:
|
||||
*/
|
||||
|
||||
#define irqdbf(x...)
|
||||
#define irqdbf2(x...)
|
||||
|
||||
#define EXTINT_OFF (IRQ_EINT4 - 4)
|
||||
|
||||
extern struct irqchip s3c_irq_level_chip;
|
||||
|
||||
static inline void
|
||||
s3c_irqsub_mask(unsigned int irqno, unsigned int parentbit,
|
||||
int subcheck)
|
||||
{
|
||||
unsigned long mask;
|
||||
unsigned long submask;
|
||||
|
||||
submask = __raw_readl(S3C2410_INTSUBMSK);
|
||||
mask = __raw_readl(S3C2410_INTMSK);
|
||||
|
||||
submask |= (1UL << (irqno - IRQ_S3CUART_RX0));
|
||||
|
||||
/* check to see if we need to mask the parent IRQ */
|
||||
|
||||
if ((submask & subcheck) == subcheck) {
|
||||
__raw_writel(mask | parentbit, S3C2410_INTMSK);
|
||||
}
|
||||
|
||||
/* write back masks */
|
||||
__raw_writel(submask, S3C2410_INTSUBMSK);
|
||||
|
||||
}
|
||||
|
||||
static inline void
|
||||
s3c_irqsub_unmask(unsigned int irqno, unsigned int parentbit)
|
||||
{
|
||||
unsigned long mask;
|
||||
unsigned long submask;
|
||||
|
||||
submask = __raw_readl(S3C2410_INTSUBMSK);
|
||||
mask = __raw_readl(S3C2410_INTMSK);
|
||||
|
||||
submask &= ~(1UL << (irqno - IRQ_S3CUART_RX0));
|
||||
mask &= ~parentbit;
|
||||
|
||||
/* write back masks */
|
||||
__raw_writel(submask, S3C2410_INTSUBMSK);
|
||||
__raw_writel(mask, S3C2410_INTMSK);
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
s3c_irqsub_maskack(unsigned int irqno, unsigned int parentmask, unsigned int group)
|
||||
{
|
||||
unsigned int bit = 1UL << (irqno - IRQ_S3CUART_RX0);
|
||||
|
||||
s3c_irqsub_mask(irqno, parentmask, group);
|
||||
|
||||
__raw_writel(bit, S3C2410_SUBSRCPND);
|
||||
|
||||
/* only ack parent if we've got all the irqs (seems we must
|
||||
* ack, all and hope that the irq system retriggers ok when
|
||||
* the interrupt goes off again)
|
||||
*/
|
||||
|
||||
if (1) {
|
||||
__raw_writel(parentmask, S3C2410_SRCPND);
|
||||
__raw_writel(parentmask, S3C2410_INTPND);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
s3c_irqsub_ack(unsigned int irqno, unsigned int parentmask, unsigned int group)
|
||||
{
|
||||
unsigned int bit = 1UL << (irqno - IRQ_S3CUART_RX0);
|
||||
|
||||
__raw_writel(bit, S3C2410_SUBSRCPND);
|
||||
|
||||
/* only ack parent if we've got all the irqs (seems we must
|
||||
* ack, all and hope that the irq system retriggers ok when
|
||||
* the interrupt goes off again)
|
||||
*/
|
||||
|
||||
if (1) {
|
||||
__raw_writel(parentmask, S3C2410_SRCPND);
|
||||
__raw_writel(parentmask, S3C2410_INTPND);
|
||||
}
|
||||
}
|
|
@ -25,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[] = {
|
||||
|
|
116
arch/arm/mach-s3c2410/s3c2440-clock.c
Normal file
116
arch/arm/mach-s3c2410/s3c2440-clock.c
Normal file
|
@ -0,0 +1,116 @@
|
|||
/* linux/arch/arm/mach-s3c2410/s3c2440-clock.c
|
||||
*
|
||||
* Copyright (c) 2004-2005 Simtec Electronics
|
||||
* http://armlinux.simtec.co.uk/
|
||||
* Ben Dooks <ben@simtec.co.uk>
|
||||
*
|
||||
* S3C2440 Clock support
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/sysdev.h>
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/ioport.h>
|
||||
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#include <asm/hardware/clock.h>
|
||||
#include <asm/arch/regs-clock.h>
|
||||
|
||||
#include "clock.h"
|
||||
#include "cpu.h"
|
||||
|
||||
/* S3C2440 extended clock support */
|
||||
|
||||
static struct clk s3c2440_clk_upll = {
|
||||
.name = "upll",
|
||||
.id = -1,
|
||||
};
|
||||
|
||||
static struct clk s3c2440_clk_cam = {
|
||||
.name = "camif",
|
||||
.id = -1,
|
||||
.enable = s3c24xx_clkcon_enable,
|
||||
.ctrlbit = S3C2440_CLKCON_CAMERA,
|
||||
};
|
||||
|
||||
static struct clk s3c2440_clk_ac97 = {
|
||||
.name = "ac97",
|
||||
.id = -1,
|
||||
.enable = s3c24xx_clkcon_enable,
|
||||
.ctrlbit = S3C2440_CLKCON_CAMERA,
|
||||
};
|
||||
|
||||
static int s3c2440_clk_add(struct sys_device *sysdev)
|
||||
{
|
||||
unsigned long upllcon = __raw_readl(S3C2410_UPLLCON);
|
||||
struct clk *clk_h;
|
||||
struct clk *clk_p;
|
||||
struct clk *clk_xtal;
|
||||
|
||||
clk_xtal = clk_get(NULL, "xtal");
|
||||
if (IS_ERR(clk_xtal)) {
|
||||
printk(KERN_ERR "S3C2440: Failed to get clk_xtal\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
s3c2440_clk_upll.rate = s3c2410_get_pll(upllcon, clk_xtal->rate);
|
||||
|
||||
printk("S3C2440: Clock Support, UPLL %ld.%03ld MHz\n",
|
||||
print_mhz(s3c2440_clk_upll.rate));
|
||||
|
||||
clk_p = clk_get(NULL, "pclk");
|
||||
clk_h = clk_get(NULL, "hclk");
|
||||
|
||||
if (IS_ERR(clk_p) || IS_ERR(clk_h)) {
|
||||
printk(KERN_ERR "S3C2440: Failed to get parent clocks\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
s3c2440_clk_cam.parent = clk_h;
|
||||
s3c2440_clk_ac97.parent = clk_p;
|
||||
|
||||
s3c24xx_register_clock(&s3c2440_clk_ac97);
|
||||
s3c24xx_register_clock(&s3c2440_clk_cam);
|
||||
s3c24xx_register_clock(&s3c2440_clk_upll);
|
||||
|
||||
clk_disable(&s3c2440_clk_ac97);
|
||||
clk_disable(&s3c2440_clk_cam);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct sysdev_driver s3c2440_clk_driver = {
|
||||
.add = s3c2440_clk_add,
|
||||
};
|
||||
|
||||
static __init int s3c24xx_clk_driver(void)
|
||||
{
|
||||
return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_clk_driver);
|
||||
}
|
||||
|
||||
arch_initcall(s3c24xx_clk_driver);
|
207
arch/arm/mach-s3c2410/s3c2440-irq.c
Normal file
207
arch/arm/mach-s3c2410/s3c2440-irq.c
Normal file
|
@ -0,0 +1,207 @@
|
|||
/* linux/arch/arm/mach-s3c2410/s3c2440-irq.c
|
||||
*
|
||||
* Copyright (c) 2003,2004 Simtec Electronics
|
||||
* Ben Dooks <ben@simtec.co.uk>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Changelog:
|
||||
* 25-Jul-2005 BJD Split from irq.c
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/sysdev.h>
|
||||
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#include <asm/mach/irq.h>
|
||||
|
||||
#include <asm/arch/regs-irq.h>
|
||||
#include <asm/arch/regs-gpio.h>
|
||||
|
||||
#include "cpu.h"
|
||||
#include "pm.h"
|
||||
#include "irq.h"
|
||||
|
||||
/* WDT/AC97 */
|
||||
|
||||
static void s3c_irq_demux_wdtac97(unsigned int irq,
|
||||
struct irqdesc *desc,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
unsigned int subsrc, submsk;
|
||||
struct irqdesc *mydesc;
|
||||
|
||||
/* read the current pending interrupts, and the mask
|
||||
* for what it is available */
|
||||
|
||||
subsrc = __raw_readl(S3C2410_SUBSRCPND);
|
||||
submsk = __raw_readl(S3C2410_INTSUBMSK);
|
||||
|
||||
subsrc &= ~submsk;
|
||||
subsrc >>= 13;
|
||||
subsrc &= 3;
|
||||
|
||||
if (subsrc != 0) {
|
||||
if (subsrc & 1) {
|
||||
mydesc = irq_desc + IRQ_S3C2440_WDT;
|
||||
mydesc->handle( IRQ_S3C2440_WDT, mydesc, regs);
|
||||
}
|
||||
if (subsrc & 2) {
|
||||
mydesc = irq_desc + IRQ_S3C2440_AC97;
|
||||
mydesc->handle(IRQ_S3C2440_AC97, mydesc, regs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define INTMSK_WDT (1UL << (IRQ_WDT - IRQ_EINT0))
|
||||
|
||||
static void
|
||||
s3c_irq_wdtac97_mask(unsigned int irqno)
|
||||
{
|
||||
s3c_irqsub_mask(irqno, INTMSK_WDT, 3<<13);
|
||||
}
|
||||
|
||||
static void
|
||||
s3c_irq_wdtac97_unmask(unsigned int irqno)
|
||||
{
|
||||
s3c_irqsub_unmask(irqno, INTMSK_WDT);
|
||||
}
|
||||
|
||||
static void
|
||||
s3c_irq_wdtac97_ack(unsigned int irqno)
|
||||
{
|
||||
s3c_irqsub_maskack(irqno, INTMSK_WDT, 3<<13);
|
||||
}
|
||||
|
||||
static struct irqchip s3c_irq_wdtac97 = {
|
||||
.mask = s3c_irq_wdtac97_mask,
|
||||
.unmask = s3c_irq_wdtac97_unmask,
|
||||
.ack = s3c_irq_wdtac97_ack,
|
||||
};
|
||||
|
||||
/* camera irq */
|
||||
|
||||
static void s3c_irq_demux_cam(unsigned int irq,
|
||||
struct irqdesc *desc,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
unsigned int subsrc, submsk;
|
||||
struct irqdesc *mydesc;
|
||||
|
||||
/* read the current pending interrupts, and the mask
|
||||
* for what it is available */
|
||||
|
||||
subsrc = __raw_readl(S3C2410_SUBSRCPND);
|
||||
submsk = __raw_readl(S3C2410_INTSUBMSK);
|
||||
|
||||
subsrc &= ~submsk;
|
||||
subsrc >>= 11;
|
||||
subsrc &= 3;
|
||||
|
||||
if (subsrc != 0) {
|
||||
if (subsrc & 1) {
|
||||
mydesc = irq_desc + IRQ_S3C2440_CAM_C;
|
||||
mydesc->handle( IRQ_S3C2440_WDT, mydesc, regs);
|
||||
}
|
||||
if (subsrc & 2) {
|
||||
mydesc = irq_desc + IRQ_S3C2440_CAM_P;
|
||||
mydesc->handle(IRQ_S3C2440_AC97, mydesc, regs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define INTMSK_CAM (1UL << (IRQ_CAM - IRQ_EINT0))
|
||||
|
||||
static void
|
||||
s3c_irq_cam_mask(unsigned int irqno)
|
||||
{
|
||||
s3c_irqsub_mask(irqno, INTMSK_CAM, 3<<11);
|
||||
}
|
||||
|
||||
static void
|
||||
s3c_irq_cam_unmask(unsigned int irqno)
|
||||
{
|
||||
s3c_irqsub_unmask(irqno, INTMSK_CAM);
|
||||
}
|
||||
|
||||
static void
|
||||
s3c_irq_cam_ack(unsigned int irqno)
|
||||
{
|
||||
s3c_irqsub_maskack(irqno, INTMSK_CAM, 3<<11);
|
||||
}
|
||||
|
||||
static struct irqchip s3c_irq_cam = {
|
||||
.mask = s3c_irq_cam_mask,
|
||||
.unmask = s3c_irq_cam_unmask,
|
||||
.ack = s3c_irq_cam_ack,
|
||||
};
|
||||
|
||||
static int s3c2440_irq_add(struct sys_device *sysdev)
|
||||
{
|
||||
unsigned int irqno;
|
||||
|
||||
printk("S3C2440: IRQ Support\n");
|
||||
|
||||
set_irq_chip(IRQ_NFCON, &s3c_irq_level_chip);
|
||||
set_irq_handler(IRQ_NFCON, do_level_IRQ);
|
||||
set_irq_flags(IRQ_NFCON, IRQF_VALID);
|
||||
|
||||
/* add new chained handler for wdt, ac7 */
|
||||
|
||||
set_irq_chip(IRQ_WDT, &s3c_irq_level_chip);
|
||||
set_irq_handler(IRQ_WDT, do_level_IRQ);
|
||||
set_irq_chained_handler(IRQ_WDT, s3c_irq_demux_wdtac97);
|
||||
|
||||
for (irqno = IRQ_S3C2440_WDT; irqno <= IRQ_S3C2440_AC97; irqno++) {
|
||||
set_irq_chip(irqno, &s3c_irq_wdtac97);
|
||||
set_irq_handler(irqno, do_level_IRQ);
|
||||
set_irq_flags(irqno, IRQF_VALID);
|
||||
}
|
||||
|
||||
/* add chained handler for camera */
|
||||
|
||||
set_irq_chip(IRQ_CAM, &s3c_irq_level_chip);
|
||||
set_irq_handler(IRQ_CAM, do_level_IRQ);
|
||||
set_irq_chained_handler(IRQ_CAM, s3c_irq_demux_cam);
|
||||
|
||||
for (irqno = IRQ_S3C2440_CAM_C; irqno <= IRQ_S3C2440_CAM_P; irqno++) {
|
||||
set_irq_chip(irqno, &s3c_irq_cam);
|
||||
set_irq_handler(irqno, do_level_IRQ);
|
||||
set_irq_flags(irqno, IRQF_VALID);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct sysdev_driver s3c2440_irq_driver = {
|
||||
.add = s3c2440_irq_add,
|
||||
};
|
||||
|
||||
static int s3c24xx_irq_driver(void)
|
||||
{
|
||||
return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_irq_driver);
|
||||
}
|
||||
|
||||
arch_initcall(s3c24xx_irq_driver);
|
||||
|
|
@ -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);
|
||||
|
|
287
arch/cris/arch-v10/kernel/dma.c
Normal file
287
arch/cris/arch-v10/kernel/dma.c
Normal file
|
@ -0,0 +1,287 @@
|
|||
/* Wrapper for DMA channel allocator that updates DMA client muxing.
|
||||
* Copyright 2004, Axis Communications AB
|
||||
* $Id: dma.c,v 1.1 2004/12/13 12:21:51 starvik Exp $
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/errno.h>
|
||||
|
||||
#include <asm/dma.h>
|
||||
#include <asm/arch/svinto.h>
|
||||
|
||||
/* Macro to access ETRAX 100 registers */
|
||||
#define SETS(var, reg, field, val) var = (var & ~IO_MASK_(reg##_, field##_)) | \
|
||||
IO_STATE_(reg##_, field##_, _##val)
|
||||
|
||||
|
||||
static char used_dma_channels[MAX_DMA_CHANNELS];
|
||||
static const char * used_dma_channels_users[MAX_DMA_CHANNELS];
|
||||
|
||||
int cris_request_dma(unsigned int dmanr, const char * device_id,
|
||||
unsigned options, enum dma_owner owner)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned long int gens;
|
||||
int fail = -EINVAL;
|
||||
|
||||
if ((dmanr < 0) || (dmanr >= MAX_DMA_CHANNELS)) {
|
||||
printk(KERN_CRIT "cris_request_dma: invalid DMA channel %u\n", dmanr);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
local_irq_save(flags);
|
||||
if (used_dma_channels[dmanr]) {
|
||||
local_irq_restore(flags);
|
||||
if (options & DMA_VERBOSE_ON_ERROR) {
|
||||
printk(KERN_CRIT "Failed to request DMA %i for %s, already allocated by %s\n", dmanr, device_id, used_dma_channels_users[dmanr]);
|
||||
}
|
||||
if (options & DMA_PANIC_ON_ERROR) {
|
||||
panic("request_dma error!");
|
||||
}
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
gens = genconfig_shadow;
|
||||
|
||||
switch(owner)
|
||||
{
|
||||
case dma_eth:
|
||||
if ((dmanr != NETWORK_TX_DMA_NBR) &&
|
||||
(dmanr != NETWORK_RX_DMA_NBR)) {
|
||||
printk(KERN_CRIT "Invalid DMA channel for eth\n");
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
case dma_ser0:
|
||||
if (dmanr == SER0_TX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma6, serial0);
|
||||
} else if (dmanr == SER0_RX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma7, serial0);
|
||||
} else {
|
||||
printk(KERN_CRIT "Invalid DMA channel for ser0\n");
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
case dma_ser1:
|
||||
if (dmanr == SER1_TX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma8, serial1);
|
||||
} else if (dmanr == SER1_RX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma9, serial1);
|
||||
} else {
|
||||
printk(KERN_CRIT "Invalid DMA channel for ser1\n");
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
case dma_ser2:
|
||||
if (dmanr == SER2_TX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma2, serial2);
|
||||
} else if (dmanr == SER2_RX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma3, serial2);
|
||||
} else {
|
||||
printk(KERN_CRIT "Invalid DMA channel for ser2\n");
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
case dma_ser3:
|
||||
if (dmanr == SER3_TX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma4, serial3);
|
||||
} else if (dmanr == SER3_RX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma5, serial3);
|
||||
} else {
|
||||
printk(KERN_CRIT "Invalid DMA channel for ser3\n");
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
case dma_ata:
|
||||
if (dmanr == ATA_TX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma2, ata);
|
||||
} else if (dmanr == ATA_RX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma3, ata);
|
||||
} else {
|
||||
printk(KERN_CRIT "Invalid DMA channel for ata\n");
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
case dma_ext0:
|
||||
if (dmanr == EXTDMA0_TX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma4, extdma0);
|
||||
} else if (dmanr == EXTDMA0_RX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma5, extdma0);
|
||||
} else {
|
||||
printk(KERN_CRIT "Invalid DMA channel for ext0\n");
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
case dma_ext1:
|
||||
if (dmanr == EXTDMA1_TX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma6, extdma1);
|
||||
} else if (dmanr == EXTDMA1_RX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma7, extdma1);
|
||||
} else {
|
||||
printk(KERN_CRIT "Invalid DMA channel for ext1\n");
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
case dma_int6:
|
||||
if (dmanr == MEM2MEM_RX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma7, intdma6);
|
||||
} else {
|
||||
printk(KERN_CRIT "Invalid DMA channel for int6\n");
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
case dma_int7:
|
||||
if (dmanr == MEM2MEM_TX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma6, intdma7);
|
||||
} else {
|
||||
printk(KERN_CRIT "Invalid DMA channel for int7\n");
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
case dma_usb:
|
||||
if (dmanr == USB_TX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma8, usb);
|
||||
} else if (dmanr == USB_RX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma9, usb);
|
||||
} else {
|
||||
printk(KERN_CRIT "Invalid DMA channel for usb\n");
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
case dma_scsi0:
|
||||
if (dmanr == SCSI0_TX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma2, scsi0);
|
||||
} else if (dmanr == SCSI0_RX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma3, scsi0);
|
||||
} else {
|
||||
printk(KERN_CRIT "Invalid DMA channel for scsi0\n");
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
case dma_scsi1:
|
||||
if (dmanr == SCSI1_TX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma4, scsi1);
|
||||
} else if (dmanr == SCSI1_RX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma5, scsi1);
|
||||
} else {
|
||||
printk(KERN_CRIT "Invalid DMA channel for scsi1\n");
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
case dma_par0:
|
||||
if (dmanr == PAR0_TX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma2, par0);
|
||||
} else if (dmanr == PAR0_RX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma3, par0);
|
||||
} else {
|
||||
printk(KERN_CRIT "Invalid DMA channel for par0\n");
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
case dma_par1:
|
||||
if (dmanr == PAR1_TX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma4, par1);
|
||||
} else if (dmanr == PAR1_RX_DMA_NBR) {
|
||||
SETS(gens, R_GEN_CONFIG, dma5, par1);
|
||||
} else {
|
||||
printk(KERN_CRIT "Invalid DMA channel for par1\n");
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printk(KERN_CRIT "Invalid DMA owner.\n");
|
||||
goto bail;
|
||||
}
|
||||
|
||||
used_dma_channels[dmanr] = 1;
|
||||
used_dma_channels_users[dmanr] = device_id;
|
||||
|
||||
{
|
||||
volatile int i;
|
||||
genconfig_shadow = gens;
|
||||
*R_GEN_CONFIG = genconfig_shadow;
|
||||
/* Wait 12 cycles before doing any DMA command */
|
||||
for(i = 6; i > 0; i--)
|
||||
nop();
|
||||
}
|
||||
fail = 0;
|
||||
bail:
|
||||
local_irq_restore(flags);
|
||||
return fail;
|
||||
}
|
||||
|
||||
void cris_free_dma(unsigned int dmanr, const char * device_id)
|
||||
{
|
||||
unsigned long flags;
|
||||
if ((dmanr < 0) || (dmanr >= MAX_DMA_CHANNELS)) {
|
||||
printk(KERN_CRIT "cris_free_dma: invalid DMA channel %u\n", dmanr);
|
||||
return;
|
||||
}
|
||||
|
||||
local_irq_save(flags);
|
||||
if (!used_dma_channels[dmanr]) {
|
||||
printk(KERN_CRIT "cris_free_dma: DMA channel %u not allocated\n", dmanr);
|
||||
} else if (device_id != used_dma_channels_users[dmanr]) {
|
||||
printk(KERN_CRIT "cris_free_dma: DMA channel %u not allocated by device\n", dmanr);
|
||||
} else {
|
||||
switch(dmanr)
|
||||
{
|
||||
case 0:
|
||||
*R_DMA_CH0_CMD = IO_STATE(R_DMA_CH0_CMD, cmd, reset);
|
||||
while (IO_EXTRACT(R_DMA_CH0_CMD, cmd, *R_DMA_CH0_CMD) ==
|
||||
IO_STATE_VALUE(R_DMA_CH0_CMD, cmd, reset));
|
||||
break;
|
||||
case 1:
|
||||
*R_DMA_CH1_CMD = IO_STATE(R_DMA_CH1_CMD, cmd, reset);
|
||||
while (IO_EXTRACT(R_DMA_CH1_CMD, cmd, *R_DMA_CH1_CMD) ==
|
||||
IO_STATE_VALUE(R_DMA_CH1_CMD, cmd, reset));
|
||||
break;
|
||||
case 2:
|
||||
*R_DMA_CH2_CMD = IO_STATE(R_DMA_CH2_CMD, cmd, reset);
|
||||
while (IO_EXTRACT(R_DMA_CH2_CMD, cmd, *R_DMA_CH2_CMD) ==
|
||||
IO_STATE_VALUE(R_DMA_CH2_CMD, cmd, reset));
|
||||
break;
|
||||
case 3:
|
||||
*R_DMA_CH3_CMD = IO_STATE(R_DMA_CH3_CMD, cmd, reset);
|
||||
while (IO_EXTRACT(R_DMA_CH3_CMD, cmd, *R_DMA_CH3_CMD) ==
|
||||
IO_STATE_VALUE(R_DMA_CH3_CMD, cmd, reset));
|
||||
break;
|
||||
case 4:
|
||||
*R_DMA_CH4_CMD = IO_STATE(R_DMA_CH4_CMD, cmd, reset);
|
||||
while (IO_EXTRACT(R_DMA_CH4_CMD, cmd, *R_DMA_CH4_CMD) ==
|
||||
IO_STATE_VALUE(R_DMA_CH4_CMD, cmd, reset));
|
||||
break;
|
||||
case 5:
|
||||
*R_DMA_CH5_CMD = IO_STATE(R_DMA_CH5_CMD, cmd, reset);
|
||||
while (IO_EXTRACT(R_DMA_CH5_CMD, cmd, *R_DMA_CH5_CMD) ==
|
||||
IO_STATE_VALUE(R_DMA_CH5_CMD, cmd, reset));
|
||||
break;
|
||||
case 6:
|
||||
*R_DMA_CH6_CMD = IO_STATE(R_DMA_CH6_CMD, cmd, reset);
|
||||
while (IO_EXTRACT(R_DMA_CH6_CMD, cmd, *R_DMA_CH6_CMD) ==
|
||||
IO_STATE_VALUE(R_DMA_CH6_CMD, cmd, reset));
|
||||
break;
|
||||
case 7:
|
||||
*R_DMA_CH7_CMD = IO_STATE(R_DMA_CH7_CMD, cmd, reset);
|
||||
while (IO_EXTRACT(R_DMA_CH7_CMD, cmd, *R_DMA_CH7_CMD) ==
|
||||
IO_STATE_VALUE(R_DMA_CH7_CMD, cmd, reset));
|
||||
break;
|
||||
case 8:
|
||||
*R_DMA_CH8_CMD = IO_STATE(R_DMA_CH8_CMD, cmd, reset);
|
||||
while (IO_EXTRACT(R_DMA_CH8_CMD, cmd, *R_DMA_CH8_CMD) ==
|
||||
IO_STATE_VALUE(R_DMA_CH8_CMD, cmd, reset));
|
||||
break;
|
||||
case 9:
|
||||
*R_DMA_CH9_CMD = IO_STATE(R_DMA_CH9_CMD, cmd, reset);
|
||||
while (IO_EXTRACT(R_DMA_CH9_CMD, cmd, *R_DMA_CH9_CMD) ==
|
||||
IO_STATE_VALUE(R_DMA_CH9_CMD, cmd, reset));
|
||||
break;
|
||||
}
|
||||
used_dma_channels[dmanr] = 0;
|
||||
}
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(cris_request_dma);
|
||||
EXPORT_SYMBOL(cris_free_dma);
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: entry.S,v 1.23 2004/10/19 13:07:37 starvik Exp $
|
||||
/* $Id: entry.S,v 1.28 2005/06/20 05:06:30 starvik Exp $
|
||||
*
|
||||
* linux/arch/cris/entry.S
|
||||
*
|
||||
|
@ -7,6 +7,22 @@
|
|||
* Authors: Bjorn Wesen (bjornw@axis.com)
|
||||
*
|
||||
* $Log: entry.S,v $
|
||||
* Revision 1.28 2005/06/20 05:06:30 starvik
|
||||
* Remove unnecessary diff to kernel.org tree
|
||||
*
|
||||
* Revision 1.27 2005/03/04 08:16:16 starvik
|
||||
* Merge of Linux 2.6.11.
|
||||
*
|
||||
* Revision 1.26 2005/01/11 13:49:47 starvik
|
||||
* Added NMI handler.
|
||||
*
|
||||
* Revision 1.25 2004/12/27 11:18:32 starvik
|
||||
* Merge of Linux 2.6.10 (not functional yet).
|
||||
*
|
||||
* Revision 1.24 2004/12/22 10:41:23 starvik
|
||||
* Updates to make v10 compile with the latest SMP aware generic code (even
|
||||
* though v10 will never have SMP).
|
||||
*
|
||||
* Revision 1.23 2004/10/19 13:07:37 starvik
|
||||
* Merge of Linux 2.6.9
|
||||
*
|
||||
|
@ -279,6 +295,7 @@
|
|||
#ifdef CONFIG_PREEMPT
|
||||
; Check if preemptive kernel scheduling should be done
|
||||
_resume_kernel:
|
||||
di
|
||||
; Load current task struct
|
||||
movs.w -8192, $r0 ; THREAD_SIZE = 8192
|
||||
and.d $sp, $r0
|
||||
|
@ -291,12 +308,7 @@ _need_resched:
|
|||
bpl _Rexit
|
||||
nop
|
||||
; Ok, lets's do some preemptive kernel scheduling
|
||||
move.d PREEMPT_ACTIVE, $r10
|
||||
move.d $r10, [$r0+TI_preempt_count] ; Mark as active
|
||||
ei
|
||||
jsr schedule
|
||||
clear.d [$r0+TI_preempt_count] ; Mark as inactive
|
||||
di
|
||||
jsr preempt_schedule_irq
|
||||
; Load new task struct
|
||||
movs.w -8192, $r0 ; THREAD_SIZE = 8192
|
||||
and.d $sp, $r0
|
||||
|
@ -590,15 +602,15 @@ mmu_bus_fault:
|
|||
move.d $r0, [$sp+16]
|
||||
1: btstq 12, $r1 ; Refill?
|
||||
bpl 2f
|
||||
lsrq PMD_SHIFT, $r1 ; Get PMD index into PGD (bit 24-31)
|
||||
move.d [current_pgd], $r0 ; PGD for the current process
|
||||
lsrq 24, $r1 ; Get PGD index (bit 24-31)
|
||||
move.d [per_cpu__current_pgd], $r0 ; PGD for the current process
|
||||
move.d [$r0+$r1.d], $r0 ; Get PMD
|
||||
beq 2f
|
||||
nop
|
||||
and.w PAGE_MASK, $r0 ; Remove PMD flags
|
||||
move.d [R_MMU_CAUSE], $r1
|
||||
lsrq PAGE_SHIFT, $r1
|
||||
and.d 0x7ff, $r1 ; Get PTE index into PMD (bit 13-24)
|
||||
and.d 0x7ff, $r1 ; Get PTE index into PGD (bit 13-23)
|
||||
move.d [$r0+$r1.d], $r1 ; Get PTE
|
||||
beq 2f
|
||||
nop
|
||||
|
@ -656,11 +668,6 @@ hwbreakpoint:
|
|||
nop
|
||||
|
||||
IRQ1_interrupt:
|
||||
|
||||
#if defined(CONFIG_ETRAX_WATCHDOG) && !defined(CONFIG_SVINTO_SIM)
|
||||
;; If we receive a watchdog interrupt while it is not expected, then set
|
||||
;; up a canonical frame and dump register contents before dying.
|
||||
|
||||
;; this prologue MUST match the one in irq.h and the struct in ptregs.h!!!
|
||||
move $brp,[$sp=$sp-16]; instruction pointer and room for a fake SBFS frame
|
||||
push $srp
|
||||
|
@ -672,9 +679,16 @@ IRQ1_interrupt:
|
|||
push $r10 ; push orig_r10
|
||||
clear.d [$sp=$sp-4] ; frametype == 0, normal frame
|
||||
|
||||
;; We don't check that we actually were bit by the watchdog as opposed to
|
||||
;; an external NMI, since there is currently no handler for external NMI.
|
||||
|
||||
move.d [R_IRQ_MASK0_RD], $r1 ; External NMI or watchdog?
|
||||
and.d 0x80000000, $r1
|
||||
beq wdog
|
||||
move.d $sp, $r10
|
||||
jsr handle_nmi
|
||||
setf m ; Enable NMI again
|
||||
retb ; Return from NMI
|
||||
nop
|
||||
wdog:
|
||||
#if defined(CONFIG_ETRAX_WATCHDOG) && !defined(CONFIG_SVINTO_SIM)
|
||||
;; Check if we're waiting for reset to happen, as signalled by
|
||||
;; hard_reset_now setting cause_of_death to a magic value. If so, just
|
||||
;; get stuck until reset happens.
|
||||
|
@ -1118,6 +1132,10 @@ sys_call_table:
|
|||
.long sys_mq_getsetattr
|
||||
.long sys_ni_syscall /* reserved for kexec */
|
||||
.long sys_waitid
|
||||
.long sys_ni_syscall /* 285 */ /* available */
|
||||
.long sys_add_key
|
||||
.long sys_request_key
|
||||
.long sys_keyctl
|
||||
|
||||
/*
|
||||
* NOTE!! This doesn't have to be exact - we just have
|
||||
|
|
|
@ -1,10 +1,20 @@
|
|||
/* $Id: fasttimer.c,v 1.6 2004/05/14 10:18:39 starvik Exp $
|
||||
/* $Id: fasttimer.c,v 1.9 2005/03/04 08:16:16 starvik Exp $
|
||||
* linux/arch/cris/kernel/fasttimer.c
|
||||
*
|
||||
* Fast timers for ETRAX100/ETRAX100LX
|
||||
* This may be useful in other OS than Linux so use 2 space indentation...
|
||||
*
|
||||
* $Log: fasttimer.c,v $
|
||||
* Revision 1.9 2005/03/04 08:16:16 starvik
|
||||
* Merge of Linux 2.6.11.
|
||||
*
|
||||
* Revision 1.8 2005/01/05 06:09:29 starvik
|
||||
* cli()/sti() will be obsolete in 2.6.11.
|
||||
*
|
||||
* Revision 1.7 2005/01/03 13:35:46 starvik
|
||||
* Removed obsolete stuff.
|
||||
* Mark fast timer IRQ as not shared.
|
||||
*
|
||||
* Revision 1.6 2004/05/14 10:18:39 starvik
|
||||
* Export fast_timer_list
|
||||
*
|
||||
|
@ -148,8 +158,7 @@ static int debug_log_cnt_wrapped = 0;
|
|||
#define DEBUG_LOG(string, value) \
|
||||
{ \
|
||||
unsigned long log_flags; \
|
||||
save_flags(log_flags); \
|
||||
cli(); \
|
||||
local_irq_save(log_flags); \
|
||||
debug_log_string[debug_log_cnt] = (string); \
|
||||
debug_log_value[debug_log_cnt] = (unsigned long)(value); \
|
||||
if (++debug_log_cnt >= DEBUG_LOG_MAX) \
|
||||
|
@ -157,7 +166,7 @@ static int debug_log_cnt_wrapped = 0;
|
|||
debug_log_cnt = debug_log_cnt % DEBUG_LOG_MAX; \
|
||||
debug_log_cnt_wrapped = 1; \
|
||||
} \
|
||||
restore_flags(log_flags); \
|
||||
local_irq_restore(log_flags); \
|
||||
}
|
||||
#else
|
||||
#define DEBUG_LOG(string, value)
|
||||
|
@ -320,8 +329,7 @@ void start_one_shot_timer(struct fast_timer *t,
|
|||
|
||||
D1(printk("sft %s %d us\n", name, delay_us));
|
||||
|
||||
save_flags(flags);
|
||||
cli();
|
||||
local_irq_save(flags);
|
||||
|
||||
do_gettimeofday_fast(&t->tv_set);
|
||||
tmp = fast_timer_list;
|
||||
|
@ -395,7 +403,7 @@ void start_one_shot_timer(struct fast_timer *t,
|
|||
|
||||
D2(printk("start_one_shot_timer: %d us done\n", delay_us));
|
||||
|
||||
restore_flags(flags);
|
||||
local_irq_restore(flags);
|
||||
} /* start_one_shot_timer */
|
||||
|
||||
static inline int fast_timer_pending (const struct fast_timer * t)
|
||||
|
@ -425,11 +433,10 @@ int del_fast_timer(struct fast_timer * t)
|
|||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
save_flags(flags);
|
||||
cli();
|
||||
local_irq_save(flags);
|
||||
ret = detach_fast_timer(t);
|
||||
t->next = t->prev = NULL;
|
||||
restore_flags(flags);
|
||||
local_irq_restore(flags);
|
||||
return ret;
|
||||
} /* del_fast_timer */
|
||||
|
||||
|
@ -444,8 +451,7 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs)
|
|||
struct fast_timer *t;
|
||||
unsigned long flags;
|
||||
|
||||
save_flags(flags);
|
||||
cli();
|
||||
local_irq_save(flags);
|
||||
|
||||
/* Clear timer1 irq */
|
||||
*R_IRQ_MASK0_CLR = IO_STATE(R_IRQ_MASK0_CLR, timer1, clr);
|
||||
|
@ -462,7 +468,7 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs)
|
|||
fast_timer_running = 0;
|
||||
fast_timer_ints++;
|
||||
|
||||
restore_flags(flags);
|
||||
local_irq_restore(flags);
|
||||
|
||||
t = fast_timer_list;
|
||||
while (t)
|
||||
|
@ -482,8 +488,7 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs)
|
|||
fast_timers_expired++;
|
||||
|
||||
/* Remove this timer before call, since it may reuse the timer */
|
||||
save_flags(flags);
|
||||
cli();
|
||||
local_irq_save(flags);
|
||||
if (t->prev)
|
||||
{
|
||||
t->prev->next = t->next;
|
||||
|
@ -498,7 +503,7 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs)
|
|||
}
|
||||
t->prev = NULL;
|
||||
t->next = NULL;
|
||||
restore_flags(flags);
|
||||
local_irq_restore(flags);
|
||||
|
||||
if (t->function != NULL)
|
||||
{
|
||||
|
@ -515,8 +520,7 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs)
|
|||
D1(printk(".\n"));
|
||||
}
|
||||
|
||||
save_flags(flags);
|
||||
cli();
|
||||
local_irq_save(flags);
|
||||
if ((t = fast_timer_list) != NULL)
|
||||
{
|
||||
/* Start next timer.. */
|
||||
|
@ -535,7 +539,7 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs)
|
|||
#endif
|
||||
start_timer1(us);
|
||||
}
|
||||
restore_flags(flags);
|
||||
local_irq_restore(flags);
|
||||
break;
|
||||
}
|
||||
else
|
||||
|
@ -546,7 +550,7 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs)
|
|||
D1(printk("e! %d\n", us));
|
||||
}
|
||||
}
|
||||
restore_flags(flags);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
if (!t)
|
||||
|
@ -748,13 +752,12 @@ static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len
|
|||
#endif
|
||||
|
||||
used += sprintf(bigbuf + used, "Active timers:\n");
|
||||
save_flags(flags);
|
||||
cli();
|
||||
local_irq_save(flags);
|
||||
t = fast_timer_list;
|
||||
while (t != NULL && (used+100 < BIG_BUF_SIZE))
|
||||
{
|
||||
nextt = t->next;
|
||||
restore_flags(flags);
|
||||
local_irq_restore(flags);
|
||||
used += sprintf(bigbuf + used, "%-14s s: %6lu.%06lu e: %6lu.%06lu "
|
||||
"d: %6li us data: 0x%08lX"
|
||||
/* " func: 0x%08lX" */
|
||||
|
@ -768,14 +771,14 @@ static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len
|
|||
t->data
|
||||
/* , t->function */
|
||||
);
|
||||
cli();
|
||||
local_irq_disable();
|
||||
if (t->next != nextt)
|
||||
{
|
||||
printk(KERN_WARNING "timer removed!\n");
|
||||
}
|
||||
t = nextt;
|
||||
}
|
||||
restore_flags(flags);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
if (used - offset < len)
|
||||
|
@ -963,7 +966,7 @@ void fast_timer_init(void)
|
|||
if ((fasttimer_proc_entry = create_proc_entry( "fasttimer", 0, 0 )))
|
||||
fasttimer_proc_entry->read_proc = proc_fasttimer_read;
|
||||
#endif /* PROC_FS */
|
||||
if(request_irq(TIMER1_IRQ_NBR, timer1_handler, SA_SHIRQ,
|
||||
if(request_irq(TIMER1_IRQ_NBR, timer1_handler, 0,
|
||||
"fast timer int", NULL))
|
||||
{
|
||||
printk("err: timer1 irq\n");
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: head.S,v 1.7 2004/05/14 07:58:01 starvik Exp $
|
||||
/* $Id: head.S,v 1.10 2005/06/20 05:12:54 starvik Exp $
|
||||
*
|
||||
* Head of the kernel - alter with care
|
||||
*
|
||||
|
@ -7,6 +7,16 @@
|
|||
* Authors: Bjorn Wesen (bjornw@axis.com)
|
||||
*
|
||||
* $Log: head.S,v $
|
||||
* Revision 1.10 2005/06/20 05:12:54 starvik
|
||||
* Remove unnecessary diff to kernel.org tree
|
||||
*
|
||||
* Revision 1.9 2004/12/13 12:21:51 starvik
|
||||
* Added I/O and DMA allocators from Linux 2.4
|
||||
*
|
||||
* Revision 1.8 2004/11/22 11:41:14 starvik
|
||||
* Kernel command line may be supplied to kernel. Not used by Axis but may
|
||||
* be used by customers.
|
||||
*
|
||||
* Revision 1.7 2004/05/14 07:58:01 starvik
|
||||
* Merge of changes from 2.4
|
||||
*
|
||||
|
@ -181,6 +191,7 @@
|
|||
|
||||
#define CRAMFS_MAGIC 0x28cd3d45
|
||||
#define RAM_INIT_MAGIC 0x56902387
|
||||
#define COMMAND_LINE_MAGIC 0x87109563
|
||||
|
||||
#define START_ETHERNET_CLOCK IO_STATE(R_NETWORK_GEN_CONFIG, enable, on) |\
|
||||
IO_STATE(R_NETWORK_GEN_CONFIG, phy, mii_clk)
|
||||
|
@ -490,6 +501,23 @@ _no_romfs_in_flash:
|
|||
|
||||
_start_it:
|
||||
|
||||
;; Check if kernel command line is supplied
|
||||
cmp.d COMMAND_LINE_MAGIC, $r10
|
||||
bne no_command_line
|
||||
nop
|
||||
|
||||
move.d 256, $r13
|
||||
move.d cris_command_line, $r10
|
||||
or.d 0x80000000, $r11 ; Make it virtual
|
||||
1:
|
||||
move.b [$r11+], $r12
|
||||
move.b $r12, [$r10+]
|
||||
subq 1, $r13
|
||||
bne 1b
|
||||
nop
|
||||
|
||||
no_command_line:
|
||||
|
||||
;; the kernel stack is overlayed with the task structure for each
|
||||
;; task. thus the initial kernel stack is in the same page as the
|
||||
;; init_task (but starts in the top of the page, size 8192)
|
||||
|
@ -567,76 +595,32 @@ _start_it:
|
|||
;; Etrax product HW genconfig setup
|
||||
|
||||
moveq 0,$r0
|
||||
#if (!defined(CONFIG_ETRAX_KGDB) || !defined(CONFIG_ETRAX_DEBUG_PORT0)) \
|
||||
&& !defined(CONFIG_DMA_MEMCPY)
|
||||
; DMA channels 6 and 7 to ser0, kgdb doesnt want DMA
|
||||
or.d IO_STATE (R_GEN_CONFIG, dma7, serial0) \
|
||||
| IO_STATE (R_GEN_CONFIG, dma6, serial0),$r0
|
||||
#endif
|
||||
#if !defined(CONFIG_ETRAX_KGDB) || !defined(CONFIG_ETRAX_DEBUG_PORT1)
|
||||
; DMA channels 8 and 9 to ser1, kgdb doesnt want DMA
|
||||
or.d IO_STATE (R_GEN_CONFIG, dma9, serial1) \
|
||||
| IO_STATE (R_GEN_CONFIG, dma8, serial1),$r0
|
||||
#endif
|
||||
#ifdef CONFIG_DMA_MEMCPY
|
||||
; 6/7 memory-memory DMA
|
||||
or.d IO_STATE (R_GEN_CONFIG, dma7, intdma6) \
|
||||
| IO_STATE (R_GEN_CONFIG, dma6, intdma7),$r0
|
||||
#endif
|
||||
#ifdef CONFIG_ETRAX_SERIAL_PORT2
|
||||
; Enable serial port 2
|
||||
or.w IO_STATE (R_GEN_CONFIG, ser2, select),$r0
|
||||
#if !defined(CONFIG_ETRAX_KGDB) || !defined(CONFIG_ETRAX_DEBUG_PORT2)
|
||||
; DMA channels 2 and 3 to ser2, kgdb doesnt want DMA
|
||||
or.d IO_STATE (R_GEN_CONFIG, dma3, serial2) \
|
||||
| IO_STATE (R_GEN_CONFIG, dma2, serial2),$r0
|
||||
#endif
|
||||
#endif
|
||||
#if defined(CONFIG_ETRAX_SERIAL_PORT3) || defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT1)
|
||||
; Enable serial port 3
|
||||
or.w IO_STATE (R_GEN_CONFIG, ser3, select),$r0
|
||||
#if !defined(CONFIG_ETRAX_KGDB) || !defined(CONFIG_ETRAX_DEBUG_PORT3)
|
||||
; DMA channels 4 and 5 to ser3, kgdb doesnt want DMA
|
||||
or.d IO_STATE (R_GEN_CONFIG, dma5, serial3) \
|
||||
| IO_STATE (R_GEN_CONFIG, dma4, serial3),$r0
|
||||
#endif
|
||||
#endif
|
||||
#if defined(CONFIG_ETRAX_PARALLEL_PORT0) || defined(CONFIG_ETRAX_ETHERNET_LPSLAVE)
|
||||
; parport 0 enabled using DMA 2/3
|
||||
or.w IO_STATE (R_GEN_CONFIG, par0, select),$r0
|
||||
#endif
|
||||
#if defined(CONFIG_ETRAX_PARALLEL_PORT1) || defined(CONFIG_ETRAX_ETHERNET_LPSLAVE)
|
||||
; parport 1 enabled using DMA 4/5
|
||||
or.w IO_STATE (R_GEN_CONFIG, par1, select),$r0
|
||||
#endif
|
||||
#ifdef CONFIG_ETRAX_IDE
|
||||
; DMA channels 2 and 3 to ATA, ATA enabled
|
||||
or.d IO_STATE (R_GEN_CONFIG, dma3, ata) \
|
||||
| IO_STATE (R_GEN_CONFIG, dma2, ata) \
|
||||
| IO_STATE (R_GEN_CONFIG, ata, select),$r0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ETRAX_USB_HOST_PORT1
|
||||
; Set the USB port 1 enable bit
|
||||
or.d IO_STATE (R_GEN_CONFIG, usb1, select),$r0
|
||||
#endif
|
||||
#ifdef CONFIG_ETRAX_USB_HOST_PORT2
|
||||
; Set the USB port 2 enable bit
|
||||
or.d IO_STATE (R_GEN_CONFIG, usb2, select),$r0
|
||||
#endif
|
||||
#ifdef CONFIG_ETRAX_USB_HOST
|
||||
; Connect DMA channels 8 and 9 to USB
|
||||
and.d (~(IO_MASK (R_GEN_CONFIG, dma9) \
|
||||
| IO_MASK (R_GEN_CONFIG, dma8))) \
|
||||
| IO_STATE (R_GEN_CONFIG, dma9, usb) \
|
||||
| IO_STATE (R_GEN_CONFIG, dma8, usb),$r0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_JULIETTE
|
||||
; DMA channels 4 and 5 to EXTDMA0, for Juliette
|
||||
or.d IO_STATE (R_GEN_CONFIG, dma5, extdma0) \
|
||||
| IO_STATE (R_GEN_CONFIG, dma4, extdma0),$r0
|
||||
#endif
|
||||
|
||||
;; Init interfaces (disable them).
|
||||
or.d IO_STATE (R_GEN_CONFIG, scsi0, disable) \
|
||||
| IO_STATE (R_GEN_CONFIG, ata, disable) \
|
||||
| IO_STATE (R_GEN_CONFIG, par0, disable) \
|
||||
| IO_STATE (R_GEN_CONFIG, ser2, disable) \
|
||||
| IO_STATE (R_GEN_CONFIG, mio, disable) \
|
||||
| IO_STATE (R_GEN_CONFIG, scsi1, disable) \
|
||||
| IO_STATE (R_GEN_CONFIG, scsi0w, disable) \
|
||||
| IO_STATE (R_GEN_CONFIG, par1, disable) \
|
||||
| IO_STATE (R_GEN_CONFIG, ser3, disable) \
|
||||
| IO_STATE (R_GEN_CONFIG, mio_w, disable) \
|
||||
| IO_STATE (R_GEN_CONFIG, usb1, disable) \
|
||||
| IO_STATE (R_GEN_CONFIG, usb2, disable) \
|
||||
| IO_STATE (R_GEN_CONFIG, par_w, disable),$r0
|
||||
|
||||
;; Init DMA channel muxing (set to unused clients).
|
||||
or.d IO_STATE (R_GEN_CONFIG, dma2, ata) \
|
||||
| IO_STATE (R_GEN_CONFIG, dma3, ata) \
|
||||
| IO_STATE (R_GEN_CONFIG, dma4, scsi1) \
|
||||
| IO_STATE (R_GEN_CONFIG, dma5, scsi1) \
|
||||
| IO_STATE (R_GEN_CONFIG, dma6, unused) \
|
||||
| IO_STATE (R_GEN_CONFIG, dma7, unused) \
|
||||
| IO_STATE (R_GEN_CONFIG, dma8, usb) \
|
||||
| IO_STATE (R_GEN_CONFIG, dma9, usb),$r0
|
||||
|
||||
|
||||
#if defined(CONFIG_ETRAX_DEF_R_PORT_G0_DIR_OUT)
|
||||
or.d IO_STATE (R_GEN_CONFIG, g0dir, out),$r0
|
||||
|
|
879
arch/cris/arch-v10/kernel/io_interface_mux.c
Normal file
879
arch/cris/arch-v10/kernel/io_interface_mux.c
Normal file
|
@ -0,0 +1,879 @@
|
|||
/* IO interface mux allocator for ETRAX100LX.
|
||||
* Copyright 2004, Axis Communications AB
|
||||
* $Id: io_interface_mux.c,v 1.2 2004/12/21 12:08:38 starvik Exp $
|
||||
*/
|
||||
|
||||
|
||||
/* C.f. ETRAX100LX Designer's Reference 20.9 */
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <asm/arch/svinto.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/io_interface_mux.h>
|
||||
|
||||
|
||||
#define DBG(s)
|
||||
|
||||
/* Macro to access ETRAX 100 registers */
|
||||
#define SETS(var, reg, field, val) var = (var & ~IO_MASK_(reg##_, field##_)) | \
|
||||
IO_STATE_(reg##_, field##_, _##val)
|
||||
|
||||
enum io_if_group {
|
||||
group_a = (1<<0),
|
||||
group_b = (1<<1),
|
||||
group_c = (1<<2),
|
||||
group_d = (1<<3),
|
||||
group_e = (1<<4),
|
||||
group_f = (1<<5)
|
||||
};
|
||||
|
||||
struct watcher
|
||||
{
|
||||
void (*notify)(const unsigned int gpio_in_available,
|
||||
const unsigned int gpio_out_available,
|
||||
const unsigned char pa_available,
|
||||
const unsigned char pb_available);
|
||||
struct watcher *next;
|
||||
};
|
||||
|
||||
|
||||
struct if_group
|
||||
{
|
||||
enum io_if_group group;
|
||||
unsigned char used;
|
||||
enum cris_io_interface owner;
|
||||
};
|
||||
|
||||
|
||||
struct interface
|
||||
{
|
||||
enum cris_io_interface ioif;
|
||||
unsigned char groups;
|
||||
unsigned char used;
|
||||
char *owner;
|
||||
unsigned int gpio_g_in;
|
||||
unsigned int gpio_g_out;
|
||||
unsigned char gpio_b;
|
||||
};
|
||||
|
||||
static struct if_group if_groups[6] = {
|
||||
{
|
||||
.group = group_a,
|
||||
.used = 0,
|
||||
},
|
||||
{
|
||||
.group = group_b,
|
||||
.used = 0,
|
||||
},
|
||||
{
|
||||
.group = group_c,
|
||||
.used = 0,
|
||||
},
|
||||
{
|
||||
.group = group_d,
|
||||
.used = 0,
|
||||
},
|
||||
{
|
||||
.group = group_e,
|
||||
.used = 0,
|
||||
},
|
||||
{
|
||||
.group = group_f,
|
||||
.used = 0,
|
||||
}
|
||||
};
|
||||
|
||||
/* The order in the array must match the order of enum
|
||||
* cris_io_interface in io_interface_mux.h */
|
||||
static struct interface interfaces[] = {
|
||||
/* Begin Non-multiplexed interfaces */
|
||||
{
|
||||
.ioif = if_eth,
|
||||
.groups = 0,
|
||||
.gpio_g_in = 0,
|
||||
.gpio_g_out = 0,
|
||||
.gpio_b = 0
|
||||
},
|
||||
{
|
||||
.ioif = if_serial_0,
|
||||
.groups = 0,
|
||||
.gpio_g_in = 0,
|
||||
.gpio_g_out = 0,
|
||||
.gpio_b = 0
|
||||
},
|
||||
/* End Non-multiplexed interfaces */
|
||||
{
|
||||
.ioif = if_serial_1,
|
||||
.groups = group_e,
|
||||
.gpio_g_in = 0x00000000,
|
||||
.gpio_g_out = 0x00000000,
|
||||
.gpio_b = 0x00
|
||||
},
|
||||
{
|
||||
.ioif = if_serial_2,
|
||||
.groups = group_b,
|
||||
.gpio_g_in = 0x000000c0,
|
||||
.gpio_g_out = 0x000000c0,
|
||||
.gpio_b = 0x00
|
||||
},
|
||||
{
|
||||
.ioif = if_serial_3,
|
||||
.groups = group_c,
|
||||
.gpio_g_in = 0xc0000000,
|
||||
.gpio_g_out = 0xc0000000,
|
||||
.gpio_b = 0x00
|
||||
},
|
||||
{
|
||||
.ioif = if_sync_serial_1,
|
||||
.groups = group_e | group_f, /* if_sync_serial_1 and if_sync_serial_3
|
||||
can be used simultaneously */
|
||||
.gpio_g_in = 0x00000000,
|
||||
.gpio_g_out = 0x00000000,
|
||||
.gpio_b = 0x10
|
||||
},
|
||||
{
|
||||
.ioif = if_sync_serial_3,
|
||||
.groups = group_c | group_f,
|
||||
.gpio_g_in = 0xc0000000,
|
||||
.gpio_g_out = 0xc0000000,
|
||||
.gpio_b = 0x80
|
||||
},
|
||||
{
|
||||
.ioif = if_shared_ram,
|
||||
.groups = group_a,
|
||||
.gpio_g_in = 0x0000ff3e,
|
||||
.gpio_g_out = 0x0000ff38,
|
||||
.gpio_b = 0x00
|
||||
},
|
||||
{
|
||||
.ioif = if_shared_ram_w,
|
||||
.groups = group_a | group_d,
|
||||
.gpio_g_in = 0x00ffff3e,
|
||||
.gpio_g_out = 0x00ffff38,
|
||||
.gpio_b = 0x00
|
||||
},
|
||||
{
|
||||
.ioif = if_par_0,
|
||||
.groups = group_a,
|
||||
.gpio_g_in = 0x0000ff3e,
|
||||
.gpio_g_out = 0x0000ff3e,
|
||||
.gpio_b = 0x00
|
||||
},
|
||||
{
|
||||
.ioif = if_par_1,
|
||||
.groups = group_d,
|
||||
.gpio_g_in = 0x3eff0000,
|
||||
.gpio_g_out = 0x3eff0000,
|
||||
.gpio_b = 0x00
|
||||
},
|
||||
{
|
||||
.ioif = if_par_w,
|
||||
.groups = group_a | group_d,
|
||||
.gpio_g_in = 0x00ffff3e,
|
||||
.gpio_g_out = 0x00ffff3e,
|
||||
.gpio_b = 0x00
|
||||
},
|
||||
{
|
||||
.ioif = if_scsi8_0,
|
||||
.groups = group_a | group_b | group_f, /* if_scsi8_0 and if_scsi8_1
|
||||
can be used simultaneously */
|
||||
.gpio_g_in = 0x0000ffff,
|
||||
.gpio_g_out = 0x0000ffff,
|
||||
.gpio_b = 0x10
|
||||
},
|
||||
{
|
||||
.ioif = if_scsi8_1,
|
||||
.groups = group_c | group_d | group_f, /* if_scsi8_0 and if_scsi8_1
|
||||
can be used simultaneously */
|
||||
.gpio_g_in = 0xffff0000,
|
||||
.gpio_g_out = 0xffff0000,
|
||||
.gpio_b = 0x80
|
||||
},
|
||||
{
|
||||
.ioif = if_scsi_w,
|
||||
.groups = group_a | group_b | group_d | group_f,
|
||||
.gpio_g_in = 0x01ffffff,
|
||||
.gpio_g_out = 0x07ffffff,
|
||||
.gpio_b = 0x80
|
||||
},
|
||||
{
|
||||
.ioif = if_ata,
|
||||
.groups = group_a | group_b | group_c | group_d,
|
||||
.gpio_g_in = 0xf9ffffff,
|
||||
.gpio_g_out = 0xffffffff,
|
||||
.gpio_b = 0x80
|
||||
},
|
||||
{
|
||||
.ioif = if_csp,
|
||||
.groups = group_f, /* if_csp and if_i2c can be used simultaneously */
|
||||
.gpio_g_in = 0x00000000,
|
||||
.gpio_g_out = 0x00000000,
|
||||
.gpio_b = 0xfc
|
||||
},
|
||||
{
|
||||
.ioif = if_i2c,
|
||||
.groups = group_f, /* if_csp and if_i2c can be used simultaneously */
|
||||
.gpio_g_in = 0x00000000,
|
||||
.gpio_g_out = 0x00000000,
|
||||
.gpio_b = 0x03
|
||||
},
|
||||
{
|
||||
.ioif = if_usb_1,
|
||||
.groups = group_e | group_f,
|
||||
.gpio_g_in = 0x00000000,
|
||||
.gpio_g_out = 0x00000000,
|
||||
.gpio_b = 0x2c
|
||||
},
|
||||
{
|
||||
.ioif = if_usb_2,
|
||||
.groups = group_d,
|
||||
.gpio_g_in = 0x0e000000,
|
||||
.gpio_g_out = 0x3c000000,
|
||||
.gpio_b = 0x00
|
||||
},
|
||||
/* GPIO pins */
|
||||
{
|
||||
.ioif = if_gpio_grp_a,
|
||||
.groups = group_a,
|
||||
.gpio_g_in = 0x0000ff3f,
|
||||
.gpio_g_out = 0x0000ff3f,
|
||||
.gpio_b = 0x00
|
||||
},
|
||||
{
|
||||
.ioif = if_gpio_grp_b,
|
||||
.groups = group_b,
|
||||
.gpio_g_in = 0x000000c0,
|
||||
.gpio_g_out = 0x000000c0,
|
||||
.gpio_b = 0x00
|
||||
},
|
||||
{
|
||||
.ioif = if_gpio_grp_c,
|
||||
.groups = group_c,
|
||||
.gpio_g_in = 0xc0000000,
|
||||
.gpio_g_out = 0xc0000000,
|
||||
.gpio_b = 0x00
|
||||
},
|
||||
{
|
||||
.ioif = if_gpio_grp_d,
|
||||
.groups = group_d,
|
||||
.gpio_g_in = 0x3fff0000,
|
||||
.gpio_g_out = 0x3fff0000,
|
||||
.gpio_b = 0x00
|
||||
},
|
||||
{
|
||||
.ioif = if_gpio_grp_e,
|
||||
.groups = group_e,
|
||||
.gpio_g_in = 0x00000000,
|
||||
.gpio_g_out = 0x00000000,
|
||||
.gpio_b = 0x00
|
||||
},
|
||||
{
|
||||
.ioif = if_gpio_grp_f,
|
||||
.groups = group_f,
|
||||
.gpio_g_in = 0x00000000,
|
||||
.gpio_g_out = 0x00000000,
|
||||
.gpio_b = 0xff
|
||||
}
|
||||
/* Array end */
|
||||
};
|
||||
|
||||
static struct watcher *watchers = NULL;
|
||||
|
||||
static unsigned int gpio_in_pins = 0xffffffff;
|
||||
static unsigned int gpio_out_pins = 0xffffffff;
|
||||
static unsigned char gpio_pb_pins = 0xff;
|
||||
static unsigned char gpio_pa_pins = 0xff;
|
||||
|
||||
static enum cris_io_interface gpio_pa_owners[8];
|
||||
static enum cris_io_interface gpio_pb_owners[8];
|
||||
static enum cris_io_interface gpio_pg_owners[32];
|
||||
|
||||
static int cris_io_interface_init(void);
|
||||
|
||||
static unsigned char clear_group_from_set(const unsigned char groups, struct if_group *group)
|
||||
{
|
||||
return (groups & ~group->group);
|
||||
}
|
||||
|
||||
|
||||
static struct if_group *get_group(const unsigned char groups)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < sizeof(if_groups)/sizeof(struct if_group); i++) {
|
||||
if (groups & if_groups[i].group) {
|
||||
return &if_groups[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void notify_watchers(void)
|
||||
{
|
||||
struct watcher *w = watchers;
|
||||
|
||||
DBG(printk("io_interface_mux: notifying watchers\n"));
|
||||
|
||||
while (NULL != w) {
|
||||
w->notify((const unsigned int)gpio_in_pins,
|
||||
(const unsigned int)gpio_out_pins,
|
||||
(const unsigned char)gpio_pa_pins,
|
||||
(const unsigned char)gpio_pb_pins);
|
||||
w = w->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int cris_request_io_interface(enum cris_io_interface ioif, const char *device_id)
|
||||
{
|
||||
int set_gen_config = 0;
|
||||
int set_gen_config_ii = 0;
|
||||
unsigned long int gens;
|
||||
unsigned long int gens_ii;
|
||||
struct if_group *grp;
|
||||
unsigned char group_set;
|
||||
unsigned long flags;
|
||||
|
||||
(void)cris_io_interface_init();
|
||||
|
||||
DBG(printk("cris_request_io_interface(%d, \"%s\")\n", ioif, device_id));
|
||||
|
||||
if ((ioif >= if_max_interfaces) || (ioif < 0)) {
|
||||
printk(KERN_CRIT "cris_request_io_interface: Bad interface %u submitted for %s\n",
|
||||
ioif,
|
||||
device_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
if (interfaces[ioif].used) {
|
||||
local_irq_restore(flags);
|
||||
printk(KERN_CRIT "cris_io_interface: Cannot allocate interface for %s, in use by %s\n",
|
||||
device_id,
|
||||
interfaces[ioif].owner);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* Check that all required groups are free before allocating, */
|
||||
group_set = interfaces[ioif].groups;
|
||||
while (NULL != (grp = get_group(group_set))) {
|
||||
if (grp->used) {
|
||||
if (grp->group == group_f) {
|
||||
if ((if_sync_serial_1 == ioif) ||
|
||||
(if_sync_serial_3 == ioif)) {
|
||||
if ((grp->owner != if_sync_serial_1) &&
|
||||
(grp->owner != if_sync_serial_3)) {
|
||||
local_irq_restore(flags);
|
||||
return -EBUSY;
|
||||
}
|
||||
} else if ((if_scsi8_0 == ioif) ||
|
||||
(if_scsi8_1 == ioif)) {
|
||||
if ((grp->owner != if_scsi8_0) &&
|
||||
(grp->owner != if_scsi8_1)) {
|
||||
local_irq_restore(flags);
|
||||
return -EBUSY;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
local_irq_restore(flags);
|
||||
return -EBUSY;
|
||||
}
|
||||
}
|
||||
group_set = clear_group_from_set(group_set, grp);
|
||||
}
|
||||
|
||||
/* Are the required GPIO pins available too? */
|
||||
if (((interfaces[ioif].gpio_g_in & gpio_in_pins) != interfaces[ioif].gpio_g_in) ||
|
||||
((interfaces[ioif].gpio_g_out & gpio_out_pins) != interfaces[ioif].gpio_g_out) ||
|
||||
((interfaces[ioif].gpio_b & gpio_pb_pins) != interfaces[ioif].gpio_b)) {
|
||||
printk(KERN_CRIT "cris_request_io_interface: Could not get required pins for interface %u\n",
|
||||
ioif);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* All needed I/O pins and pin groups are free, allocate. */
|
||||
group_set = interfaces[ioif].groups;
|
||||
while (NULL != (grp = get_group(group_set))) {
|
||||
grp->used = 1;
|
||||
grp->owner = ioif;
|
||||
group_set = clear_group_from_set(group_set, grp);
|
||||
}
|
||||
|
||||
gens = genconfig_shadow;
|
||||
gens_ii = gen_config_ii_shadow;
|
||||
|
||||
set_gen_config = 1;
|
||||
switch (ioif)
|
||||
{
|
||||
/* Begin Non-multiplexed interfaces */
|
||||
case if_eth:
|
||||
/* fall through */
|
||||
case if_serial_0:
|
||||
set_gen_config = 0;
|
||||
break;
|
||||
/* End Non-multiplexed interfaces */
|
||||
case if_serial_1:
|
||||
set_gen_config_ii = 1;
|
||||
SETS(gens_ii, R_GEN_CONFIG_II, sermode1, async);
|
||||
break;
|
||||
case if_serial_2:
|
||||
SETS(gens, R_GEN_CONFIG, ser2, select);
|
||||
break;
|
||||
case if_serial_3:
|
||||
SETS(gens, R_GEN_CONFIG, ser3, select);
|
||||
set_gen_config_ii = 1;
|
||||
SETS(gens_ii, R_GEN_CONFIG_II, sermode3, async);
|
||||
break;
|
||||
case if_sync_serial_1:
|
||||
set_gen_config_ii = 1;
|
||||
SETS(gens_ii, R_GEN_CONFIG_II, sermode1, sync);
|
||||
break;
|
||||
case if_sync_serial_3:
|
||||
SETS(gens, R_GEN_CONFIG, ser3, select);
|
||||
set_gen_config_ii = 1;
|
||||
SETS(gens_ii, R_GEN_CONFIG_II, sermode3, sync);
|
||||
break;
|
||||
case if_shared_ram:
|
||||
SETS(gens, R_GEN_CONFIG, mio, select);
|
||||
break;
|
||||
case if_shared_ram_w:
|
||||
SETS(gens, R_GEN_CONFIG, mio_w, select);
|
||||
break;
|
||||
case if_par_0:
|
||||
SETS(gens, R_GEN_CONFIG, par0, select);
|
||||
break;
|
||||
case if_par_1:
|
||||
SETS(gens, R_GEN_CONFIG, par1, select);
|
||||
break;
|
||||
case if_par_w:
|
||||
SETS(gens, R_GEN_CONFIG, par0, select);
|
||||
SETS(gens, R_GEN_CONFIG, par_w, select);
|
||||
break;
|
||||
case if_scsi8_0:
|
||||
SETS(gens, R_GEN_CONFIG, scsi0, select);
|
||||
break;
|
||||
case if_scsi8_1:
|
||||
SETS(gens, R_GEN_CONFIG, scsi1, select);
|
||||
break;
|
||||
case if_scsi_w:
|
||||
SETS(gens, R_GEN_CONFIG, scsi0, select);
|
||||
SETS(gens, R_GEN_CONFIG, scsi0w, select);
|
||||
break;
|
||||
case if_ata:
|
||||
SETS(gens, R_GEN_CONFIG, ata, select);
|
||||
break;
|
||||
case if_csp:
|
||||
/* fall through */
|
||||
case if_i2c:
|
||||
set_gen_config = 0;
|
||||
break;
|
||||
case if_usb_1:
|
||||
SETS(gens, R_GEN_CONFIG, usb1, select);
|
||||
break;
|
||||
case if_usb_2:
|
||||
SETS(gens, R_GEN_CONFIG, usb2, select);
|
||||
break;
|
||||
case if_gpio_grp_a:
|
||||
/* GPIO groups are only accounted, don't do configuration changes. */
|
||||
/* fall through */
|
||||
case if_gpio_grp_b:
|
||||
/* fall through */
|
||||
case if_gpio_grp_c:
|
||||
/* fall through */
|
||||
case if_gpio_grp_d:
|
||||
/* fall through */
|
||||
case if_gpio_grp_e:
|
||||
/* fall through */
|
||||
case if_gpio_grp_f:
|
||||
set_gen_config = 0;
|
||||
break;
|
||||
default:
|
||||
panic("cris_request_io_interface: Bad interface %u submitted for %s\n",
|
||||
ioif,
|
||||
device_id);
|
||||
}
|
||||
|
||||
interfaces[ioif].used = 1;
|
||||
interfaces[ioif].owner = (char*)device_id;
|
||||
|
||||
if (set_gen_config) {
|
||||
volatile int i;
|
||||
genconfig_shadow = gens;
|
||||
*R_GEN_CONFIG = genconfig_shadow;
|
||||
/* Wait 12 cycles before doing any DMA command */
|
||||
for(i = 6; i > 0; i--)
|
||||
nop();
|
||||
}
|
||||
if (set_gen_config_ii) {
|
||||
gen_config_ii_shadow = gens_ii;
|
||||
*R_GEN_CONFIG_II = gen_config_ii_shadow;
|
||||
}
|
||||
|
||||
DBG(printk("GPIO pins: available before: g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
|
||||
gpio_in_pins, gpio_out_pins, gpio_pb_pins));
|
||||
DBG(printk("grabbing pins: g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
|
||||
interfaces[ioif].gpio_g_in,
|
||||
interfaces[ioif].gpio_g_out,
|
||||
interfaces[ioif].gpio_b));
|
||||
|
||||
gpio_in_pins &= ~interfaces[ioif].gpio_g_in;
|
||||
gpio_out_pins &= ~interfaces[ioif].gpio_g_out;
|
||||
gpio_pb_pins &= ~interfaces[ioif].gpio_b;
|
||||
|
||||
DBG(printk("GPIO pins: available after: g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
|
||||
gpio_in_pins, gpio_out_pins, gpio_pb_pins));
|
||||
|
||||
local_irq_restore(flags);
|
||||
|
||||
notify_watchers();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void cris_free_io_interface(enum cris_io_interface ioif)
|
||||
{
|
||||
struct if_group *grp;
|
||||
unsigned char group_set;
|
||||
unsigned long flags;
|
||||
|
||||
(void)cris_io_interface_init();
|
||||
|
||||
if ((ioif >= if_max_interfaces) || (ioif < 0)) {
|
||||
printk(KERN_CRIT "cris_free_io_interface: Bad interface %u\n",
|
||||
ioif);
|
||||
return;
|
||||
}
|
||||
local_irq_save(flags);
|
||||
if (!interfaces[ioif].used) {
|
||||
printk(KERN_CRIT "cris_free_io_interface: Freeing free interface %u\n",
|
||||
ioif);
|
||||
local_irq_restore(flags);
|
||||
return;
|
||||
}
|
||||
group_set = interfaces[ioif].groups;
|
||||
while (NULL != (grp = get_group(group_set))) {
|
||||
if (grp->group == group_f) {
|
||||
switch (ioif)
|
||||
{
|
||||
case if_sync_serial_1:
|
||||
if ((grp->owner == if_sync_serial_1) &&
|
||||
interfaces[if_sync_serial_3].used) {
|
||||
grp->owner = if_sync_serial_3;
|
||||
} else
|
||||
grp->used = 0;
|
||||
break;
|
||||
case if_sync_serial_3:
|
||||
if ((grp->owner == if_sync_serial_3) &&
|
||||
interfaces[if_sync_serial_1].used) {
|
||||
grp->owner = if_sync_serial_1;
|
||||
} else
|
||||
grp->used = 0;
|
||||
break;
|
||||
case if_scsi8_0:
|
||||
if ((grp->owner == if_scsi8_0) &&
|
||||
interfaces[if_scsi8_1].used) {
|
||||
grp->owner = if_scsi8_1;
|
||||
} else
|
||||
grp->used = 0;
|
||||
break;
|
||||
case if_scsi8_1:
|
||||
if ((grp->owner == if_scsi8_1) &&
|
||||
interfaces[if_scsi8_0].used) {
|
||||
grp->owner = if_scsi8_0;
|
||||
} else
|
||||
grp->used = 0;
|
||||
break;
|
||||
default:
|
||||
grp->used = 0;
|
||||
}
|
||||
} else {
|
||||
grp->used = 0;
|
||||
}
|
||||
group_set = clear_group_from_set(group_set, grp);
|
||||
}
|
||||
interfaces[ioif].used = 0;
|
||||
interfaces[ioif].owner = NULL;
|
||||
|
||||
DBG(printk("GPIO pins: available before: g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
|
||||
gpio_in_pins, gpio_out_pins, gpio_pb_pins));
|
||||
DBG(printk("freeing pins: g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
|
||||
interfaces[ioif].gpio_g_in,
|
||||
interfaces[ioif].gpio_g_out,
|
||||
interfaces[ioif].gpio_b));
|
||||
|
||||
gpio_in_pins |= interfaces[ioif].gpio_g_in;
|
||||
gpio_out_pins |= interfaces[ioif].gpio_g_out;
|
||||
gpio_pb_pins |= interfaces[ioif].gpio_b;
|
||||
|
||||
DBG(printk("GPIO pins: available after: g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
|
||||
gpio_in_pins, gpio_out_pins, gpio_pb_pins));
|
||||
|
||||
local_irq_restore(flags);
|
||||
|
||||
notify_watchers();
|
||||
}
|
||||
|
||||
/* Create a bitmask from bit 0 (inclusive) to bit stop_bit
|
||||
(non-inclusive). stop_bit == 0 returns 0x0 */
|
||||
static inline unsigned int create_mask(const unsigned stop_bit)
|
||||
{
|
||||
/* Avoid overflow */
|
||||
if (stop_bit >= 32) {
|
||||
return 0xffffffff;
|
||||
}
|
||||
return (1<<stop_bit)-1;
|
||||
}
|
||||
|
||||
|
||||
/* port can be 'a', 'b' or 'g' */
|
||||
int cris_io_interface_allocate_pins(const enum cris_io_interface ioif,
|
||||
const char port,
|
||||
const unsigned start_bit,
|
||||
const unsigned stop_bit)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int mask = 0;
|
||||
unsigned int tmp_mask;
|
||||
unsigned long int flags;
|
||||
enum cris_io_interface *owners;
|
||||
|
||||
(void)cris_io_interface_init();
|
||||
|
||||
DBG(printk("cris_io_interface_allocate_pins: if=%d port=%c start=%u stop=%u\n",
|
||||
ioif, port, start_bit, stop_bit));
|
||||
|
||||
if (!((start_bit <= stop_bit) &&
|
||||
((((port == 'a') || (port == 'b')) && (stop_bit < 8)) ||
|
||||
((port == 'g') && (stop_bit < 32))))) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mask = create_mask(stop_bit + 1);
|
||||
tmp_mask = create_mask(start_bit);
|
||||
mask &= ~tmp_mask;
|
||||
|
||||
DBG(printk("cris_io_interface_allocate_pins: port=%c start=%u stop=%u mask=0x%08x\n",
|
||||
port, start_bit, stop_bit, mask));
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
switch (port) {
|
||||
case 'a':
|
||||
if ((gpio_pa_pins & mask) != mask) {
|
||||
local_irq_restore(flags);
|
||||
return -EBUSY;
|
||||
}
|
||||
owners = gpio_pa_owners;
|
||||
gpio_pa_pins &= ~mask;
|
||||
break;
|
||||
case 'b':
|
||||
if ((gpio_pb_pins & mask) != mask) {
|
||||
local_irq_restore(flags);
|
||||
return -EBUSY;
|
||||
}
|
||||
owners = gpio_pb_owners;
|
||||
gpio_pb_pins &= ~mask;
|
||||
break;
|
||||
case 'g':
|
||||
if (((gpio_in_pins & mask) != mask) ||
|
||||
((gpio_out_pins & mask) != mask)) {
|
||||
local_irq_restore(flags);
|
||||
return -EBUSY;
|
||||
}
|
||||
owners = gpio_pg_owners;
|
||||
gpio_in_pins &= ~mask;
|
||||
gpio_out_pins &= ~mask;
|
||||
break;
|
||||
default:
|
||||
local_irq_restore(flags);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = start_bit; i <= stop_bit; i++) {
|
||||
owners[i] = ioif;
|
||||
}
|
||||
local_irq_restore(flags);
|
||||
|
||||
notify_watchers();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* port can be 'a', 'b' or 'g' */
|
||||
int cris_io_interface_free_pins(const enum cris_io_interface ioif,
|
||||
const char port,
|
||||
const unsigned start_bit,
|
||||
const unsigned stop_bit)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int mask = 0;
|
||||
unsigned int tmp_mask;
|
||||
unsigned long int flags;
|
||||
enum cris_io_interface *owners;
|
||||
|
||||
(void)cris_io_interface_init();
|
||||
|
||||
if (!((start_bit <= stop_bit) &&
|
||||
((((port == 'a') || (port == 'b')) && (stop_bit < 8)) ||
|
||||
((port == 'g') && (stop_bit < 32))))) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mask = create_mask(stop_bit + 1);
|
||||
tmp_mask = create_mask(start_bit);
|
||||
mask &= ~tmp_mask;
|
||||
|
||||
DBG(printk("cris_io_interface_free_pins: port=%c start=%u stop=%u mask=0x%08x\n",
|
||||
port, start_bit, stop_bit, mask));
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
switch (port) {
|
||||
case 'a':
|
||||
if ((~gpio_pa_pins & mask) != mask) {
|
||||
local_irq_restore(flags);
|
||||
printk(KERN_CRIT "cris_io_interface_free_pins: Freeing free pins");
|
||||
}
|
||||
owners = gpio_pa_owners;
|
||||
break;
|
||||
case 'b':
|
||||
if ((~gpio_pb_pins & mask) != mask) {
|
||||
local_irq_restore(flags);
|
||||
printk(KERN_CRIT "cris_io_interface_free_pins: Freeing free pins");
|
||||
}
|
||||
owners = gpio_pb_owners;
|
||||
break;
|
||||
case 'g':
|
||||
if (((~gpio_in_pins & mask) != mask) ||
|
||||
((~gpio_out_pins & mask) != mask)) {
|
||||
local_irq_restore(flags);
|
||||
printk(KERN_CRIT "cris_io_interface_free_pins: Freeing free pins");
|
||||
}
|
||||
owners = gpio_pg_owners;
|
||||
break;
|
||||
default:
|
||||
owners = NULL; /* Cannot happen. Shut up, gcc! */
|
||||
}
|
||||
|
||||
for (i = start_bit; i <= stop_bit; i++) {
|
||||
if (owners[i] != ioif) {
|
||||
printk(KERN_CRIT "cris_io_interface_free_pins: Freeing unowned pins");
|
||||
}
|
||||
}
|
||||
|
||||
/* All was ok, change data. */
|
||||
switch (port) {
|
||||
case 'a':
|
||||
gpio_pa_pins |= mask;
|
||||
break;
|
||||
case 'b':
|
||||
gpio_pb_pins |= mask;
|
||||
break;
|
||||
case 'g':
|
||||
gpio_in_pins |= mask;
|
||||
gpio_out_pins |= mask;
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = start_bit; i <= stop_bit; i++) {
|
||||
owners[i] = if_unclaimed;
|
||||
}
|
||||
local_irq_restore(flags);
|
||||
notify_watchers();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int cris_io_interface_register_watcher(void (*notify)(const unsigned int gpio_in_available,
|
||||
const unsigned int gpio_out_available,
|
||||
const unsigned char pa_available,
|
||||
const unsigned char pb_available))
|
||||
{
|
||||
struct watcher *w;
|
||||
|
||||
(void)cris_io_interface_init();
|
||||
|
||||
if (NULL == notify) {
|
||||
return -EINVAL;
|
||||
}
|
||||
w = kmalloc(sizeof(*w), GFP_KERNEL);
|
||||
if (!w) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
w->notify = notify;
|
||||
w->next = watchers;
|
||||
watchers = w;
|
||||
|
||||
w->notify((const unsigned int)gpio_in_pins,
|
||||
(const unsigned int)gpio_out_pins,
|
||||
(const unsigned char)gpio_pa_pins,
|
||||
(const unsigned char)gpio_pb_pins);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cris_io_interface_delete_watcher(void (*notify)(const unsigned int gpio_in_available,
|
||||
const unsigned int gpio_out_available,
|
||||
const unsigned char pa_available,
|
||||
const unsigned char pb_available))
|
||||
{
|
||||
struct watcher *w = watchers, *prev = NULL;
|
||||
|
||||
(void)cris_io_interface_init();
|
||||
|
||||
while ((NULL != w) && (w->notify != notify)){
|
||||
prev = w;
|
||||
w = w->next;
|
||||
}
|
||||
if (NULL != w) {
|
||||
if (NULL != prev) {
|
||||
prev->next = w->next;
|
||||
} else {
|
||||
watchers = w->next;
|
||||
}
|
||||
kfree(w);
|
||||
return;
|
||||
}
|
||||
printk(KERN_WARNING "cris_io_interface_delete_watcher: Deleting unknown watcher 0x%p\n", notify);
|
||||
}
|
||||
|
||||
|
||||
static int cris_io_interface_init(void)
|
||||
{
|
||||
static int first = 1;
|
||||
int i;
|
||||
|
||||
if (!first) {
|
||||
return 0;
|
||||
}
|
||||
first = 0;
|
||||
|
||||
for (i = 0; i<8; i++) {
|
||||
gpio_pa_owners[i] = if_unclaimed;
|
||||
gpio_pb_owners[i] = if_unclaimed;
|
||||
gpio_pg_owners[i] = if_unclaimed;
|
||||
}
|
||||
for (; i<32; i++) {
|
||||
gpio_pg_owners[i] = if_unclaimed;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
module_init(cris_io_interface_init);
|
||||
|
||||
|
||||
EXPORT_SYMBOL(cris_request_io_interface);
|
||||
EXPORT_SYMBOL(cris_free_io_interface);
|
||||
EXPORT_SYMBOL(cris_io_interface_allocate_pins);
|
||||
EXPORT_SYMBOL(cris_io_interface_free_pins);
|
||||
EXPORT_SYMBOL(cris_io_interface_register_watcher);
|
||||
EXPORT_SYMBOL(cris_io_interface_delete_watcher);
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: irq.c,v 1.2 2004/06/09 05:30:27 starvik Exp $
|
||||
/* $Id: irq.c,v 1.4 2005/01/04 12:22:28 starvik Exp $
|
||||
*
|
||||
* linux/arch/cris/kernel/irq.c
|
||||
*
|
||||
|
@ -12,11 +12,13 @@
|
|||
*/
|
||||
|
||||
#include <asm/irq.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/config.h>
|
||||
|
||||
irqvectptr irq_shortcuts[NR_IRQS]; /* vector of shortcut jumps after the irq prologue */
|
||||
#define mask_irq(irq_nr) (*R_VECT_MASK_CLR = 1 << (irq_nr));
|
||||
#define unmask_irq(irq_nr) (*R_VECT_MASK_SET = 1 << (irq_nr));
|
||||
|
||||
/* don't use set_int_vector, it bypasses the linux interrupt handlers. it is
|
||||
* global just so that the kernel gdb can use it.
|
||||
|
@ -102,41 +104,52 @@ static void (*interrupt[NR_IRQS])(void) = {
|
|||
IRQ31_interrupt
|
||||
};
|
||||
|
||||
static void (*bad_interrupt[NR_IRQS])(void) = {
|
||||
NULL, NULL,
|
||||
NULL, bad_IRQ3_interrupt,
|
||||
bad_IRQ4_interrupt, bad_IRQ5_interrupt,
|
||||
bad_IRQ6_interrupt, bad_IRQ7_interrupt,
|
||||
bad_IRQ8_interrupt, bad_IRQ9_interrupt,
|
||||
bad_IRQ10_interrupt, bad_IRQ11_interrupt,
|
||||
bad_IRQ12_interrupt, bad_IRQ13_interrupt,
|
||||
NULL, NULL,
|
||||
bad_IRQ16_interrupt, bad_IRQ17_interrupt,
|
||||
bad_IRQ18_interrupt, bad_IRQ19_interrupt,
|
||||
bad_IRQ20_interrupt, bad_IRQ21_interrupt,
|
||||
bad_IRQ22_interrupt, bad_IRQ23_interrupt,
|
||||
bad_IRQ24_interrupt, bad_IRQ25_interrupt,
|
||||
NULL, NULL, NULL, NULL, NULL,
|
||||
bad_IRQ31_interrupt
|
||||
static void enable_crisv10_irq(unsigned int irq);
|
||||
|
||||
static unsigned int startup_crisv10_irq(unsigned int irq)
|
||||
{
|
||||
enable_crisv10_irq(irq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define shutdown_crisv10_irq disable_crisv10_irq
|
||||
|
||||
static void enable_crisv10_irq(unsigned int irq)
|
||||
{
|
||||
unmask_irq(irq);
|
||||
}
|
||||
|
||||
static void disable_crisv10_irq(unsigned int irq)
|
||||
{
|
||||
mask_irq(irq);
|
||||
}
|
||||
|
||||
static void ack_crisv10_irq(unsigned int irq)
|
||||
{
|
||||
}
|
||||
|
||||
static void end_crisv10_irq(unsigned int irq)
|
||||
{
|
||||
}
|
||||
|
||||
static struct hw_interrupt_type crisv10_irq_type = {
|
||||
.typename = "CRISv10",
|
||||
.startup = startup_crisv10_irq,
|
||||
.shutdown = shutdown_crisv10_irq,
|
||||
.enable = enable_crisv10_irq,
|
||||
.disable = disable_crisv10_irq,
|
||||
.ack = ack_crisv10_irq,
|
||||
.end = end_crisv10_irq,
|
||||
.set_affinity = NULL
|
||||
};
|
||||
|
||||
void arch_setup_irq(int irq)
|
||||
{
|
||||
set_int_vector(irq, interrupt[irq]);
|
||||
}
|
||||
|
||||
void arch_free_irq(int irq)
|
||||
{
|
||||
set_int_vector(irq, bad_interrupt[irq]);
|
||||
}
|
||||
|
||||
void weird_irq(void);
|
||||
void system_call(void); /* from entry.S */
|
||||
void do_sigtrap(void); /* from entry.S */
|
||||
void gdb_handle_breakpoint(void); /* from entry.S */
|
||||
|
||||
/* init_IRQ() is called by start_kernel and is responsible for fixing IRQ masks and
|
||||
setting the irq vector table to point to bad_interrupt ptrs.
|
||||
setting the irq vector table.
|
||||
*/
|
||||
|
||||
void __init
|
||||
|
@ -154,14 +167,15 @@ init_IRQ(void)
|
|||
|
||||
*R_VECT_MASK_CLR = 0xffffffff;
|
||||
|
||||
/* clear the shortcut entry points */
|
||||
|
||||
for(i = 0; i < NR_IRQS; i++)
|
||||
irq_shortcuts[i] = NULL;
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
etrax_irv->v[i] = weird_irq;
|
||||
|
||||
/* Initialize IRQ handler descriptiors. */
|
||||
for(i = 2; i < NR_IRQS; i++) {
|
||||
irq_desc[i].handler = &crisv10_irq_type;
|
||||
set_int_vector(i, interrupt[i]);
|
||||
}
|
||||
|
||||
/* the entries in the break vector contain actual code to be
|
||||
executed by the associated break handler, rather than just a jump
|
||||
address. therefore we need to setup a default breakpoint handler
|
||||
|
@ -170,10 +184,6 @@ init_IRQ(void)
|
|||
for (i = 0; i < 16; i++)
|
||||
set_break_vector(i, do_sigtrap);
|
||||
|
||||
/* set all etrax irq's to the bad handlers */
|
||||
for (i = 2; i < NR_IRQS; i++)
|
||||
set_int_vector(i, bad_interrupt[i]);
|
||||
|
||||
/* except IRQ 15 which is the multiple-IRQ handler on Etrax100 */
|
||||
|
||||
set_int_vector(15, multiple_interrupt);
|
||||
|
|
|
@ -18,6 +18,10 @@
|
|||
*! Jul 21 1999 Bjorn Wesen eLinux port
|
||||
*!
|
||||
*! $Log: kgdb.c,v $
|
||||
*! Revision 1.6 2005/01/14 10:12:17 starvik
|
||||
*! KGDB on separate port.
|
||||
*! Console fixes from 2.4.
|
||||
*!
|
||||
*! Revision 1.5 2004/10/07 13:59:08 starvik
|
||||
*! Corrected call to set_int_vector
|
||||
*!
|
||||
|
@ -71,7 +75,7 @@
|
|||
*!
|
||||
*!---------------------------------------------------------------------------
|
||||
*!
|
||||
*! $Id: kgdb.c,v 1.5 2004/10/07 13:59:08 starvik Exp $
|
||||
*! $Id: kgdb.c,v 1.6 2005/01/14 10:12:17 starvik Exp $
|
||||
*!
|
||||
*! (C) Copyright 1999, Axis Communications AB, LUND, SWEDEN
|
||||
*!
|
||||
|
@ -225,6 +229,7 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/linkage.h>
|
||||
#include <linux/reboot.h>
|
||||
|
||||
#include <asm/setup.h>
|
||||
#include <asm/ptrace.h>
|
||||
|
@ -1344,12 +1349,11 @@ handle_exception (int sigval)
|
|||
}
|
||||
}
|
||||
|
||||
/* The jump is to the address 0x00000002. Performs a complete re-start
|
||||
from scratch. */
|
||||
/* Performs a complete re-start from scratch. */
|
||||
static void
|
||||
kill_restart ()
|
||||
{
|
||||
__asm__ volatile ("jump 2");
|
||||
machine_restart("");
|
||||
}
|
||||
|
||||
/********************************** Breakpoint *******************************/
|
||||
|
@ -1506,6 +1510,11 @@ kgdb_handle_serial:
|
|||
bne goback
|
||||
nop
|
||||
|
||||
move.d [reg+0x5E], $r10 ; Get DCCR
|
||||
btstq 8, $r10 ; Test the U-flag.
|
||||
bmi goback
|
||||
nop
|
||||
|
||||
;;
|
||||
;; Handle the communication
|
||||
;;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: process.c,v 1.9 2004/10/19 13:07:37 starvik Exp $
|
||||
/* $Id: process.c,v 1.12 2004/12/27 11:18:32 starvik Exp $
|
||||
*
|
||||
* linux/arch/cris/kernel/process.c
|
||||
*
|
||||
|
@ -101,6 +101,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
|
|||
regs.r11 = (unsigned long)fn;
|
||||
regs.r12 = (unsigned long)arg;
|
||||
regs.irp = (unsigned long)kernel_thread_helper;
|
||||
regs.dccr = 1 << I_DCCR_BITNR;
|
||||
|
||||
/* Ok, create the new process.. */
|
||||
return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL);
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <linux/ptrace.h>
|
||||
#include <linux/user.h>
|
||||
#include <linux/signal.h>
|
||||
#include <linux/security.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/page.h>
|
||||
|
@ -86,9 +87,13 @@ sys_ptrace(long request, long pid, long addr, long data)
|
|||
ret = -EPERM;
|
||||
|
||||
if (request == PTRACE_TRACEME) {
|
||||
/* are we already being traced? */
|
||||
if (current->ptrace & PT_PTRACED)
|
||||
goto out;
|
||||
|
||||
ret = security_ptrace(current->parent, current);
|
||||
if (ret)
|
||||
goto out;
|
||||
/* set the ptrace bit in the process flags. */
|
||||
current->ptrace |= PT_PTRACED;
|
||||
ret = 0;
|
||||
goto out;
|
||||
|
@ -207,7 +212,7 @@ sys_ptrace(long request, long pid, long addr, long data)
|
|||
case PTRACE_KILL:
|
||||
ret = 0;
|
||||
|
||||
if (child->state == TASK_ZOMBIE)
|
||||
if (child->exit_state == EXIT_ZOMBIE)
|
||||
break;
|
||||
|
||||
child->exit_code = SIGKILL;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: shadows.c,v 1.1 2001/12/17 13:59:27 bjornw Exp $
|
||||
/* $Id: shadows.c,v 1.2 2004/12/13 12:21:51 starvik Exp $
|
||||
*
|
||||
* Various shadow registers. Defines for these are in include/asm-etrax100/io.h
|
||||
*/
|
||||
|
@ -6,6 +6,7 @@
|
|||
/* Shadows for internal Etrax-registers */
|
||||
|
||||
unsigned long genconfig_shadow;
|
||||
unsigned long gen_config_ii_shadow;
|
||||
unsigned long port_g_data_shadow;
|
||||
unsigned char port_pa_dir_shadow;
|
||||
unsigned char port_pa_data_shadow;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: traps.c,v 1.2 2003/07/04 08:27:41 starvik Exp $
|
||||
/* $Id: traps.c,v 1.4 2005/04/24 18:47:55 starvik Exp $
|
||||
*
|
||||
* linux/arch/cris/arch-v10/traps.c
|
||||
*
|
||||
|
@ -16,6 +16,8 @@
|
|||
#include <asm/uaccess.h>
|
||||
#include <asm/arch/sv_addr_ag.h>
|
||||
|
||||
extern int raw_printk(const char *fmt, ...);
|
||||
|
||||
void
|
||||
show_registers(struct pt_regs * regs)
|
||||
{
|
||||
|
@ -26,18 +28,18 @@ show_registers(struct pt_regs * regs)
|
|||
register. */
|
||||
unsigned long usp = rdusp();
|
||||
|
||||
printk("IRP: %08lx SRP: %08lx DCCR: %08lx USP: %08lx MOF: %08lx\n",
|
||||
raw_printk("IRP: %08lx SRP: %08lx DCCR: %08lx USP: %08lx MOF: %08lx\n",
|
||||
regs->irp, regs->srp, regs->dccr, usp, regs->mof );
|
||||
printk(" r0: %08lx r1: %08lx r2: %08lx r3: %08lx\n",
|
||||
raw_printk(" r0: %08lx r1: %08lx r2: %08lx r3: %08lx\n",
|
||||
regs->r0, regs->r1, regs->r2, regs->r3);
|
||||
printk(" r4: %08lx r5: %08lx r6: %08lx r7: %08lx\n",
|
||||
raw_printk(" r4: %08lx r5: %08lx r6: %08lx r7: %08lx\n",
|
||||
regs->r4, regs->r5, regs->r6, regs->r7);
|
||||
printk(" r8: %08lx r9: %08lx r10: %08lx r11: %08lx\n",
|
||||
raw_printk(" r8: %08lx r9: %08lx r10: %08lx r11: %08lx\n",
|
||||
regs->r8, regs->r9, regs->r10, regs->r11);
|
||||
printk("r12: %08lx r13: %08lx oR10: %08lx\n",
|
||||
regs->r12, regs->r13, regs->orig_r10);
|
||||
printk("R_MMU_CAUSE: %08lx\n", (unsigned long)*R_MMU_CAUSE);
|
||||
printk("Process %s (pid: %d, stackpage=%08lx)\n",
|
||||
raw_printk("r12: %08lx r13: %08lx oR10: %08lx sp: %08lx\n",
|
||||
regs->r12, regs->r13, regs->orig_r10, regs);
|
||||
raw_printk("R_MMU_CAUSE: %08lx\n", (unsigned long)*R_MMU_CAUSE);
|
||||
raw_printk("Process %s (pid: %d, stackpage=%08lx)\n",
|
||||
current->comm, current->pid, (unsigned long)current);
|
||||
|
||||
/*
|
||||
|
@ -53,7 +55,7 @@ show_registers(struct pt_regs * regs)
|
|||
if (usp != 0)
|
||||
show_stack (NULL, NULL);
|
||||
|
||||
printk("\nCode: ");
|
||||
raw_printk("\nCode: ");
|
||||
if(regs->irp < PAGE_OFFSET)
|
||||
goto bad;
|
||||
|
||||
|
@ -70,16 +72,16 @@ show_registers(struct pt_regs * regs)
|
|||
unsigned char c;
|
||||
if(__get_user(c, &((unsigned char*)regs->irp)[i])) {
|
||||
bad:
|
||||
printk(" Bad IP value.");
|
||||
raw_printk(" Bad IP value.");
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == 0)
|
||||
printk("(%02x) ", c);
|
||||
raw_printk("(%02x) ", c);
|
||||
else
|
||||
printk("%02x ", c);
|
||||
raw_printk("%02x ", c);
|
||||
}
|
||||
printk("\n");
|
||||
raw_printk("\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -121,7 +123,7 @@ die_if_kernel(const char * str, struct pt_regs * regs, long err)
|
|||
stop_watchdog();
|
||||
#endif
|
||||
|
||||
printk("%s: %04lx\n", str, err & 0xffff);
|
||||
raw_printk("%s: %04lx\n", str, err & 0xffff);
|
||||
|
||||
show_registers(regs);
|
||||
|
||||
|
@ -130,3 +132,8 @@ die_if_kernel(const char * str, struct pt_regs * regs, long err)
|
|||
#endif
|
||||
do_exit(SIGSEGV);
|
||||
}
|
||||
|
||||
void arch_enable_nmi(void)
|
||||
{
|
||||
asm volatile("setf m");
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <asm/uaccess.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/arch/svinto.h>
|
||||
#include <asm/mmu_context.h>
|
||||
|
||||
/* debug of low-level TLB reload */
|
||||
#undef DEBUG
|
||||
|
@ -24,8 +25,6 @@
|
|||
#define D(x)
|
||||
#endif
|
||||
|
||||
extern volatile pgd_t *current_pgd;
|
||||
|
||||
extern const struct exception_table_entry
|
||||
*search_exception_tables(unsigned long addr);
|
||||
|
||||
|
@ -46,7 +45,7 @@ handle_mmu_bus_fault(struct pt_regs *regs)
|
|||
int page_id;
|
||||
int acc, inv;
|
||||
#endif
|
||||
pgd_t* pgd = (pgd_t*)current_pgd;
|
||||
pgd_t* pgd = (pgd_t*)per_cpu(current_pgd, smp_processor_id());
|
||||
pmd_t *pmd;
|
||||
pte_t pte;
|
||||
int miss, we, writeac;
|
||||
|
@ -94,24 +93,3 @@ handle_mmu_bus_fault(struct pt_regs *regs)
|
|||
*R_TLB_LO = pte_val(pte);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
/* Called from arch/cris/mm/fault.c to find fixup code. */
|
||||
int
|
||||
find_fixup_code(struct pt_regs *regs)
|
||||
{
|
||||
const struct exception_table_entry *fixup;
|
||||
|
||||
if ((fixup = search_exception_tables(regs->irp)) != 0) {
|
||||
/* Adjust the instruction pointer in the stackframe. */
|
||||
regs->irp = fixup->fixup;
|
||||
|
||||
/*
|
||||
* Don't return by restoring the CPU state, so switch
|
||||
* frame-type.
|
||||
*/
|
||||
regs->frametype = CRIS_FRAME_NORMAL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ paging_init(void)
|
|||
* switch_mm)
|
||||
*/
|
||||
|
||||
current_pgd = init_mm.pgd;
|
||||
per_cpu(current_pgd, smp_processor_id()) = init_mm.pgd;
|
||||
|
||||
/* initialise the TLB (tlb.c) */
|
||||
|
||||
|
|
|
@ -139,53 +139,6 @@ flush_tlb_page(struct vm_area_struct *vma,
|
|||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
/* invalidate a page range */
|
||||
|
||||
void
|
||||
flush_tlb_range(struct vm_area_struct *vma,
|
||||
unsigned long start,
|
||||
unsigned long end)
|
||||
{
|
||||
struct mm_struct *mm = vma->vm_mm;
|
||||
int page_id = mm->context.page_id;
|
||||
int i;
|
||||
unsigned long flags;
|
||||
|
||||
D(printk("tlb: flush range %p<->%p in context %d (%p)\n",
|
||||
start, end, page_id, mm));
|
||||
|
||||
if(page_id == NO_CONTEXT)
|
||||
return;
|
||||
|
||||
start &= PAGE_MASK; /* probably not necessary */
|
||||
end &= PAGE_MASK; /* dito */
|
||||
|
||||
/* invalidate those TLB entries that match both the mm context
|
||||
* and the virtual address range
|
||||
*/
|
||||
|
||||
local_save_flags(flags);
|
||||
local_irq_disable();
|
||||
for(i = 0; i < NUM_TLB_ENTRIES; i++) {
|
||||
unsigned long tlb_hi, vpn;
|
||||
*R_TLB_SELECT = IO_FIELD(R_TLB_SELECT, index, i);
|
||||
tlb_hi = *R_TLB_HI;
|
||||
vpn = tlb_hi & PAGE_MASK;
|
||||
if (IO_EXTRACT(R_TLB_HI, page_id, tlb_hi) == page_id &&
|
||||
vpn >= start && vpn < end) {
|
||||
*R_TLB_HI = ( IO_FIELD(R_TLB_HI, page_id, INVALID_PAGEID ) |
|
||||
IO_FIELD(R_TLB_HI, vpn, i & 0xf ) );
|
||||
|
||||
*R_TLB_LO = ( IO_STATE(R_TLB_LO, global,no ) |
|
||||
IO_STATE(R_TLB_LO, valid, no ) |
|
||||
IO_STATE(R_TLB_LO, kernel,no ) |
|
||||
IO_STATE(R_TLB_LO, we, no ) |
|
||||
IO_FIELD(R_TLB_LO, pfn, 0 ) );
|
||||
}
|
||||
}
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
/* dump the entire TLB for debug purposes */
|
||||
|
||||
#if 0
|
||||
|
@ -237,7 +190,7 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next,
|
|||
* the pgd.
|
||||
*/
|
||||
|
||||
current_pgd = next->pgd;
|
||||
per_cpu(current_pgd, smp_processor_id()) = next->pgd;
|
||||
|
||||
/* switch context in the MMU */
|
||||
|
||||
|
|
296
arch/cris/arch-v32/Kconfig
Normal file
296
arch/cris/arch-v32/Kconfig
Normal file
|
@ -0,0 +1,296 @@
|
|||
config ETRAX_DRAM_VIRTUAL_BASE
|
||||
hex
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "c0000000"
|
||||
|
||||
config ETRAX_LED1G
|
||||
string "First green LED bit"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "PA3"
|
||||
help
|
||||
Bit to use for the first green LED (network LED).
|
||||
Most Axis products use bit A3 here.
|
||||
|
||||
config ETRAX_LED1R
|
||||
string "First red LED bit"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "PA4"
|
||||
help
|
||||
Bit to use for the first red LED (network LED).
|
||||
Most Axis products use bit A4 here.
|
||||
|
||||
config ETRAX_LED2G
|
||||
string "Second green LED bit"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "PA5"
|
||||
help
|
||||
Bit to use for the first green LED (status LED).
|
||||
Most Axis products use bit A5 here.
|
||||
|
||||
config ETRAX_LED2R
|
||||
string "Second red LED bit"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "PA6"
|
||||
help
|
||||
Bit to use for the first red LED (network LED).
|
||||
Most Axis products use bit A6 here.
|
||||
|
||||
config ETRAX_LED3G
|
||||
string "Third green LED bit"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "PA7"
|
||||
help
|
||||
Bit to use for the first green LED (drive/power LED).
|
||||
Most Axis products use bit A7 here.
|
||||
|
||||
config ETRAX_LED3R
|
||||
string "Third red LED bit"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "PA7"
|
||||
help
|
||||
Bit to use for the first red LED (drive/power LED).
|
||||
Most Axis products use bit A7 here.
|
||||
|
||||
choice
|
||||
prompt "Product debug-port"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default ETRAX_DEBUG_PORT0
|
||||
|
||||
config ETRAX_DEBUG_PORT0
|
||||
bool "Serial-0"
|
||||
help
|
||||
Choose a serial port for the ETRAX debug console. Default to
|
||||
port 0.
|
||||
|
||||
config ETRAX_DEBUG_PORT1
|
||||
bool "Serial-1"
|
||||
help
|
||||
Use serial port 1 for the console.
|
||||
|
||||
config ETRAX_DEBUG_PORT2
|
||||
bool "Serial-2"
|
||||
help
|
||||
Use serial port 2 for the console.
|
||||
|
||||
config ETRAX_DEBUG_PORT3
|
||||
bool "Serial-3"
|
||||
help
|
||||
Use serial port 3 for the console.
|
||||
|
||||
config ETRAX_DEBUG_PORT_NULL
|
||||
bool "disabled"
|
||||
help
|
||||
Disable serial-port debugging.
|
||||
|
||||
endchoice
|
||||
|
||||
choice
|
||||
prompt "Kernel GDB port"
|
||||
depends on ETRAX_KGDB
|
||||
default ETRAX_KGDB_PORT0
|
||||
help
|
||||
Choose a serial port for kernel debugging. NOTE: This port should
|
||||
not be enabled under Drivers for built-in interfaces (as it has its
|
||||
own initialization code) and should not be the same as the debug port.
|
||||
|
||||
config ETRAX_KGDB_PORT0
|
||||
bool "Serial-0"
|
||||
help
|
||||
Use serial port 0 for kernel debugging.
|
||||
|
||||
config ETRAX_KGDB_PORT1
|
||||
bool "Serial-1"
|
||||
help
|
||||
Use serial port 1 for kernel debugging.
|
||||
|
||||
config ETRAX_KGDB_PORT2
|
||||
bool "Serial-2"
|
||||
help
|
||||
Use serial port 2 for kernel debugging.
|
||||
|
||||
config ETRAX_KGDB_PORT3
|
||||
bool "Serial-3"
|
||||
help
|
||||
Use serial port 3 for kernel debugging.
|
||||
|
||||
endchoice
|
||||
|
||||
config ETRAX_MEM_GRP1_CONFIG
|
||||
hex "MEM_GRP1_CONFIG"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "4044a"
|
||||
help
|
||||
Waitstates for flash. The default value is suitable for the
|
||||
standard flashes used in axis products (120 ns).
|
||||
|
||||
config ETRAX_MEM_GRP2_CONFIG
|
||||
hex "MEM_GRP2_CONFIG"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "0"
|
||||
help
|
||||
Waitstates for SRAM. 0 is a good choice for most Axis products.
|
||||
|
||||
config ETRAX_MEM_GRP3_CONFIG
|
||||
hex "MEM_GRP3_CONFIG"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "0"
|
||||
help
|
||||
Waitstates for CSP0-3. 0 is a good choice for most Axis products.
|
||||
It may need to be changed if external devices such as extra
|
||||
register-mapped LEDs are used.
|
||||
|
||||
config ETRAX_MEM_GRP4_CONFIG
|
||||
hex "MEM_GRP4_CONFIG"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "0"
|
||||
help
|
||||
Waitstates for CSP4-6. 0 is a good choice for most Axis products.
|
||||
|
||||
config ETRAX_SDRAM_GRP0_CONFIG
|
||||
hex "SDRAM_GRP0_CONFIG"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "336"
|
||||
help
|
||||
SDRAM configuration for group 0. The value depends on the
|
||||
hardware configuration. The default value is suitable
|
||||
for 32 MB organized as two 16 bits chips (e.g. Axis
|
||||
part number 18550) connected as one 32 bit device (i.e. in
|
||||
the same group).
|
||||
|
||||
config ETRAX_SDRAM_GRP1_CONFIG
|
||||
hex "SDRAM_GRP1_CONFIG"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "0"
|
||||
help
|
||||
SDRAM configuration for group 1. The defult value is 0
|
||||
because group 1 is not used in the default configuration,
|
||||
described in the help for SDRAM_GRP0_CONFIG.
|
||||
|
||||
config ETRAX_SDRAM_TIMING
|
||||
hex "SDRAM_TIMING"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "104a"
|
||||
help
|
||||
SDRAM timing parameters. The default value is ok for
|
||||
most hardwares but large SDRAMs may require a faster
|
||||
refresh (a.k.a 8K refresh). The default value implies
|
||||
100MHz clock and SDR mode.
|
||||
|
||||
config ETRAX_SDRAM_COMMAND
|
||||
hex "SDRAM_COMMAND"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "0"
|
||||
help
|
||||
SDRAM command. Should be 0 unless you really know what
|
||||
you are doing (may be != 0 for unusual address line
|
||||
mappings such as in a MCM)..
|
||||
|
||||
config ETRAX_DEF_GIO_PA_OE
|
||||
hex "GIO_PA_OE"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "1c"
|
||||
help
|
||||
Configures the direction of general port A bits. 1 is out, 0 is in.
|
||||
This is often totally different depending on the product used.
|
||||
There are some guidelines though - if you know that only LED's are
|
||||
connected to port PA, then they are usually connected to bits 2-4
|
||||
and you can therefore use 1c. On other boards which don't have the
|
||||
LED's at the general ports, these bits are used for all kinds of
|
||||
stuff. If you don't know what to use, it is always safe to put all
|
||||
as inputs, although floating inputs isn't good.
|
||||
|
||||
config ETRAX_DEF_GIO_PA_OUT
|
||||
hex "GIO_PA_OUT"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "00"
|
||||
help
|
||||
Configures the initial data for the general port A bits. Most
|
||||
products should use 00 here.
|
||||
|
||||
config ETRAX_DEF_GIO_PB_OE
|
||||
hex "GIO_PB_OE"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "00000"
|
||||
help
|
||||
Configures the direction of general port B bits. 1 is out, 0 is in.
|
||||
This is often totally different depending on the product used.
|
||||
There are some guidelines though - if you know that only LED's are
|
||||
connected to port PA, then they are usually connected to bits 2-4
|
||||
and you can therefore use 1c. On other boards which don't have the
|
||||
LED's at the general ports, these bits are used for all kinds of
|
||||
stuff. If you don't know what to use, it is always safe to put all
|
||||
as inputs, although floating inputs isn't good.
|
||||
|
||||
config ETRAX_DEF_GIO_PB_OUT
|
||||
hex "GIO_PB_OUT"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "00000"
|
||||
help
|
||||
Configures the initial data for the general port B bits. Most
|
||||
products should use 00000 here.
|
||||
|
||||
config ETRAX_DEF_GIO_PC_OE
|
||||
hex "GIO_PC_OE"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "00000"
|
||||
help
|
||||
Configures the direction of general port C bits. 1 is out, 0 is in.
|
||||
This is often totally different depending on the product used.
|
||||
There are some guidelines though - if you know that only LED's are
|
||||
connected to port PA, then they are usually connected to bits 2-4
|
||||
and you can therefore use 1c. On other boards which don't have the
|
||||
LED's at the general ports, these bits are used for all kinds of
|
||||
stuff. If you don't know what to use, it is always safe to put all
|
||||
as inputs, although floating inputs isn't good.
|
||||
|
||||
config ETRAX_DEF_GIO_PC_OUT
|
||||
hex "GIO_PC_OUT"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "00000"
|
||||
help
|
||||
Configures the initial data for the general port C bits. Most
|
||||
products should use 00000 here.
|
||||
|
||||
config ETRAX_DEF_GIO_PD_OE
|
||||
hex "GIO_PD_OE"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "00000"
|
||||
help
|
||||
Configures the direction of general port D bits. 1 is out, 0 is in.
|
||||
This is often totally different depending on the product used.
|
||||
There are some guidelines though - if you know that only LED's are
|
||||
connected to port PA, then they are usually connected to bits 2-4
|
||||
and you can therefore use 1c. On other boards which don't have the
|
||||
LED's at the general ports, these bits are used for all kinds of
|
||||
stuff. If you don't know what to use, it is always safe to put all
|
||||
as inputs, although floating inputs isn't good.
|
||||
|
||||
config ETRAX_DEF_GIO_PD_OUT
|
||||
hex "GIO_PD_OUT"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "00000"
|
||||
help
|
||||
Configures the initial data for the general port D bits. Most
|
||||
products should use 00000 here.
|
||||
|
||||
config ETRAX_DEF_GIO_PE_OE
|
||||
hex "GIO_PE_OE"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "00000"
|
||||
help
|
||||
Configures the direction of general port E bits. 1 is out, 0 is in.
|
||||
This is often totally different depending on the product used.
|
||||
There are some guidelines though - if you know that only LED's are
|
||||
connected to port PA, then they are usually connected to bits 2-4
|
||||
and you can therefore use 1c. On other boards which don't have the
|
||||
LED's at the general ports, these bits are used for all kinds of
|
||||
stuff. If you don't know what to use, it is always safe to put all
|
||||
as inputs, although floating inputs isn't good.
|
||||
|
||||
config ETRAX_DEF_GIO_PE_OUT
|
||||
hex "GIO_PE_OUT"
|
||||
depends on ETRAX_ARCH_V32
|
||||
default "00000"
|
||||
help
|
||||
Configures the initial data for the general port E bits. Most
|
||||
products should use 00000 here.
|
14
arch/cris/arch-v32/boot/Makefile
Normal file
14
arch/cris/arch-v32/boot/Makefile
Normal file
|
@ -0,0 +1,14 @@
|
|||
#
|
||||
# arch/cris/arch-v32/boot/Makefile
|
||||
#
|
||||
target = $(target_boot_dir)
|
||||
src = $(src_boot_dir)
|
||||
|
||||
zImage: compressed/vmlinuz
|
||||
|
||||
compressed/vmlinuz: $(objtree)/vmlinux
|
||||
@$(MAKE) -f $(src)/compressed/Makefile $(objtree)/vmlinuz
|
||||
|
||||
clean:
|
||||
rm -f zImage tools/build compressed/vmlinux.out
|
||||
@$(MAKE) -f $(src)/compressed/Makefile clean
|
41
arch/cris/arch-v32/boot/compressed/Makefile
Normal file
41
arch/cris/arch-v32/boot/compressed/Makefile
Normal file
|
@ -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)
|
||||
|
25
arch/cris/arch-v32/boot/compressed/README
Normal file
25
arch/cris/arch-v32/boot/compressed/README
Normal file
|
@ -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
|
30
arch/cris/arch-v32/boot/compressed/decompress.ld
Normal file
30
arch/cris/arch-v32/boot/compressed/decompress.ld
Normal file
|
@ -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
|
||||
}
|
193
arch/cris/arch-v32/boot/compressed/head.S
Normal file
193
arch/cris/arch-v32/boot/compressed/head.S
Normal file
|
@ -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"
|
318
arch/cris/arch-v32/boot/compressed/misc.c
Normal file
318
arch/cris/arch-v32/boot/compressed/misc.c
Normal file
|
@ -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");
|
||||
}
|
36
arch/cris/arch-v32/boot/rescue/Makefile
Normal file
36
arch/cris/arch-v32/boot/rescue/Makefile
Normal file
|
@ -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:
|
39
arch/cris/arch-v32/boot/rescue/head.S
Normal file
39
arch/cris/arch-v32/boot/rescue/head.S
Normal file
|
@ -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
|
20
arch/cris/arch-v32/boot/rescue/rescue.ld
Normal file
20
arch/cris/arch-v32/boot/rescue/rescue.ld
Normal file
|
@ -0,0 +1,20 @@
|
|||
MEMORY
|
||||
{
|
||||
flash : ORIGIN = 0x00000000,
|
||||
LENGTH = 0x00100000
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text :
|
||||
{
|
||||
stext = . ;
|
||||
*(.text)
|
||||
etext = . ;
|
||||
} > flash
|
||||
.data :
|
||||
{
|
||||
*(.data)
|
||||
edata = . ;
|
||||
} > flash
|
||||
}
|
625
arch/cris/arch-v32/drivers/Kconfig
Normal file
625
arch/cris/arch-v32/drivers/Kconfig
Normal file
|
@ -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.
|
13
arch/cris/arch-v32/drivers/Makefile
Normal file
13
arch/cris/arch-v32/drivers/Makefile
Normal file
|
@ -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/
|
455
arch/cris/arch-v32/drivers/axisflashmap.c
Normal file
455
arch/cris/arch-v32/drivers/axisflashmap.c
Normal file
|
@ -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);
|
3522
arch/cris/arch-v32/drivers/cryptocop.c
Normal file
3522
arch/cris/arch-v32/drivers/cryptocop.c
Normal file
File diff suppressed because it is too large
Load diff
766
arch/cris/arch-v32/drivers/gpio.c
Normal file
766
arch/cris/arch-v32/drivers/gpio.c
Normal file
|
@ -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);
|
611
arch/cris/arch-v32/drivers/i2c.c
Normal file
611
arch/cris/arch-v32/drivers/i2c.c
Normal file
|
@ -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 ********************************/
|
15
arch/cris/arch-v32/drivers/i2c.h
Normal file
15
arch/cris/arch-v32/drivers/i2c.h
Normal file
|
@ -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);
|
219
arch/cris/arch-v32/drivers/iop_fw_load.c
Normal file
219
arch/cris/arch-v32/drivers/iop_fw_load.c
Normal file
|
@ -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);
|
157
arch/cris/arch-v32/drivers/nandflash.c
Normal file
157
arch/cris/arch-v32/drivers/nandflash.c
Normal file
|
@ -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;
|
||||
}
|
||||
|
341
arch/cris/arch-v32/drivers/pcf8563.c
Normal file
341
arch/cris/arch-v32/drivers/pcf8563.c
Normal file
|
@ -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);
|
5
arch/cris/arch-v32/drivers/pci/Makefile
Normal file
5
arch/cris/arch-v32/drivers/pci/Makefile
Normal file
|
@ -0,0 +1,5 @@
|
|||
#
|
||||
# Makefile for Etrax cardbus driver
|
||||
#
|
||||
|
||||
obj-$(CONFIG_ETRAX_CARDBUS) += bios.o dma.o
|
131
arch/cris/arch-v32/drivers/pci/bios.c
Normal file
131
arch/cris/arch-v32/drivers/pci/bios.c
Normal file
|
@ -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);
|
149
arch/cris/arch-v32/drivers/pci/dma.c
Normal file
149
arch/cris/arch-v32/drivers/pci/dma.c
Normal file
|
@ -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);
|
1283
arch/cris/arch-v32/drivers/sync_serial.c
Normal file
1283
arch/cris/arch-v32/drivers/sync_serial.c
Normal file
File diff suppressed because it is too large
Load diff
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue