Merge branch 'master'
This commit is contained in:
commit
2ff4782374
342 changed files with 12227 additions and 14370 deletions
271
Documentation/block/barrier.txt
Normal file
271
Documentation/block/barrier.txt
Normal file
|
@ -0,0 +1,271 @@
|
|||
I/O Barriers
|
||||
============
|
||||
Tejun Heo <htejun@gmail.com>, July 22 2005
|
||||
|
||||
I/O barrier requests are used to guarantee ordering around the barrier
|
||||
requests. Unless you're crazy enough to use disk drives for
|
||||
implementing synchronization constructs (wow, sounds interesting...),
|
||||
the ordering is meaningful only for write requests for things like
|
||||
journal checkpoints. All requests queued before a barrier request
|
||||
must be finished (made it to the physical medium) before the barrier
|
||||
request is started, and all requests queued after the barrier request
|
||||
must be started only after the barrier request is finished (again,
|
||||
made it to the physical medium).
|
||||
|
||||
In other words, I/O barrier requests have the following two properties.
|
||||
|
||||
1. Request ordering
|
||||
|
||||
Requests cannot pass the barrier request. Preceding requests are
|
||||
processed before the barrier and following requests after.
|
||||
|
||||
Depending on what features a drive supports, this can be done in one
|
||||
of the following three ways.
|
||||
|
||||
i. For devices which have queue depth greater than 1 (TCQ devices) and
|
||||
support ordered tags, block layer can just issue the barrier as an
|
||||
ordered request and the lower level driver, controller and drive
|
||||
itself are responsible for making sure that the ordering contraint is
|
||||
met. Most modern SCSI controllers/drives should support this.
|
||||
|
||||
NOTE: SCSI ordered tag isn't currently used due to limitation in the
|
||||
SCSI midlayer, see the following random notes section.
|
||||
|
||||
ii. For devices which have queue depth greater than 1 but don't
|
||||
support ordered tags, block layer ensures that the requests preceding
|
||||
a barrier request finishes before issuing the barrier request. Also,
|
||||
it defers requests following the barrier until the barrier request is
|
||||
finished. Older SCSI controllers/drives and SATA drives fall in this
|
||||
category.
|
||||
|
||||
iii. Devices which have queue depth of 1. This is a degenerate case
|
||||
of ii. Just keeping issue order suffices. Ancient SCSI
|
||||
controllers/drives and IDE drives are in this category.
|
||||
|
||||
2. Forced flushing to physcial medium
|
||||
|
||||
Again, if you're not gonna do synchronization with disk drives (dang,
|
||||
it sounds even more appealing now!), the reason you use I/O barriers
|
||||
is mainly to protect filesystem integrity when power failure or some
|
||||
other events abruptly stop the drive from operating and possibly make
|
||||
the drive lose data in its cache. So, I/O barriers need to guarantee
|
||||
that requests actually get written to non-volatile medium in order.
|
||||
|
||||
There are four cases,
|
||||
|
||||
i. No write-back cache. Keeping requests ordered is enough.
|
||||
|
||||
ii. Write-back cache but no flush operation. There's no way to
|
||||
gurantee physical-medium commit order. This kind of devices can't to
|
||||
I/O barriers.
|
||||
|
||||
iii. Write-back cache and flush operation but no FUA (forced unit
|
||||
access). We need two cache flushes - before and after the barrier
|
||||
request.
|
||||
|
||||
iv. Write-back cache, flush operation and FUA. We still need one
|
||||
flush to make sure requests preceding a barrier are written to medium,
|
||||
but post-barrier flush can be avoided by using FUA write on the
|
||||
barrier itself.
|
||||
|
||||
|
||||
How to support barrier requests in drivers
|
||||
------------------------------------------
|
||||
|
||||
All barrier handling is done inside block layer proper. All low level
|
||||
drivers have to are implementing its prepare_flush_fn and using one
|
||||
the following two functions to indicate what barrier type it supports
|
||||
and how to prepare flush requests. Note that the term 'ordered' is
|
||||
used to indicate the whole sequence of performing barrier requests
|
||||
including draining and flushing.
|
||||
|
||||
typedef void (prepare_flush_fn)(request_queue_t *q, struct request *rq);
|
||||
|
||||
int blk_queue_ordered(request_queue_t *q, unsigned ordered,
|
||||
prepare_flush_fn *prepare_flush_fn,
|
||||
unsigned gfp_mask);
|
||||
|
||||
int blk_queue_ordered_locked(request_queue_t *q, unsigned ordered,
|
||||
prepare_flush_fn *prepare_flush_fn,
|
||||
unsigned gfp_mask);
|
||||
|
||||
The only difference between the two functions is whether or not the
|
||||
caller is holding q->queue_lock on entry. The latter expects the
|
||||
caller is holding the lock.
|
||||
|
||||
@q : the queue in question
|
||||
@ordered : the ordered mode the driver/device supports
|
||||
@prepare_flush_fn : this function should prepare @rq such that it
|
||||
flushes cache to physical medium when executed
|
||||
@gfp_mask : gfp_mask used when allocating data structures
|
||||
for ordered processing
|
||||
|
||||
For example, SCSI disk driver's prepare_flush_fn looks like the
|
||||
following.
|
||||
|
||||
static void sd_prepare_flush(request_queue_t *q, struct request *rq)
|
||||
{
|
||||
memset(rq->cmd, 0, sizeof(rq->cmd));
|
||||
rq->flags |= REQ_BLOCK_PC;
|
||||
rq->timeout = SD_TIMEOUT;
|
||||
rq->cmd[0] = SYNCHRONIZE_CACHE;
|
||||
}
|
||||
|
||||
The following seven ordered modes are supported. The following table
|
||||
shows which mode should be used depending on what features a
|
||||
device/driver supports. In the leftmost column of table,
|
||||
QUEUE_ORDERED_ prefix is omitted from the mode names to save space.
|
||||
|
||||
The table is followed by description of each mode. Note that in the
|
||||
descriptions of QUEUE_ORDERED_DRAIN*, '=>' is used whereas '->' is
|
||||
used for QUEUE_ORDERED_TAG* descriptions. '=>' indicates that the
|
||||
preceding step must be complete before proceeding to the next step.
|
||||
'->' indicates that the next step can start as soon as the previous
|
||||
step is issued.
|
||||
|
||||
write-back cache ordered tag flush FUA
|
||||
-----------------------------------------------------------------------
|
||||
NONE yes/no N/A no N/A
|
||||
DRAIN no no N/A N/A
|
||||
DRAIN_FLUSH yes no yes no
|
||||
DRAIN_FUA yes no yes yes
|
||||
TAG no yes N/A N/A
|
||||
TAG_FLUSH yes yes yes no
|
||||
TAG_FUA yes yes yes yes
|
||||
|
||||
|
||||
QUEUE_ORDERED_NONE
|
||||
I/O barriers are not needed and/or supported.
|
||||
|
||||
Sequence: N/A
|
||||
|
||||
QUEUE_ORDERED_DRAIN
|
||||
Requests are ordered by draining the request queue and cache
|
||||
flushing isn't needed.
|
||||
|
||||
Sequence: drain => barrier
|
||||
|
||||
QUEUE_ORDERED_DRAIN_FLUSH
|
||||
Requests are ordered by draining the request queue and both
|
||||
pre-barrier and post-barrier cache flushings are needed.
|
||||
|
||||
Sequence: drain => preflush => barrier => postflush
|
||||
|
||||
QUEUE_ORDERED_DRAIN_FUA
|
||||
Requests are ordered by draining the request queue and
|
||||
pre-barrier cache flushing is needed. By using FUA on barrier
|
||||
request, post-barrier flushing can be skipped.
|
||||
|
||||
Sequence: drain => preflush => barrier
|
||||
|
||||
QUEUE_ORDERED_TAG
|
||||
Requests are ordered by ordered tag and cache flushing isn't
|
||||
needed.
|
||||
|
||||
Sequence: barrier
|
||||
|
||||
QUEUE_ORDERED_TAG_FLUSH
|
||||
Requests are ordered by ordered tag and both pre-barrier and
|
||||
post-barrier cache flushings are needed.
|
||||
|
||||
Sequence: preflush -> barrier -> postflush
|
||||
|
||||
QUEUE_ORDERED_TAG_FUA
|
||||
Requests are ordered by ordered tag and pre-barrier cache
|
||||
flushing is needed. By using FUA on barrier request,
|
||||
post-barrier flushing can be skipped.
|
||||
|
||||
Sequence: preflush -> barrier
|
||||
|
||||
|
||||
Random notes/caveats
|
||||
--------------------
|
||||
|
||||
* SCSI layer currently can't use TAG ordering even if the drive,
|
||||
controller and driver support it. The problem is that SCSI midlayer
|
||||
request dispatch function is not atomic. It releases queue lock and
|
||||
switch to SCSI host lock during issue and it's possible and likely to
|
||||
happen in time that requests change their relative positions. Once
|
||||
this problem is solved, TAG ordering can be enabled.
|
||||
|
||||
* Currently, no matter which ordered mode is used, there can be only
|
||||
one barrier request in progress. All I/O barriers are held off by
|
||||
block layer until the previous I/O barrier is complete. This doesn't
|
||||
make any difference for DRAIN ordered devices, but, for TAG ordered
|
||||
devices with very high command latency, passing multiple I/O barriers
|
||||
to low level *might* be helpful if they are very frequent. Well, this
|
||||
certainly is a non-issue. I'm writing this just to make clear that no
|
||||
two I/O barrier is ever passed to low-level driver.
|
||||
|
||||
* Completion order. Requests in ordered sequence are issued in order
|
||||
but not required to finish in order. Barrier implementation can
|
||||
handle out-of-order completion of ordered sequence. IOW, the requests
|
||||
MUST be processed in order but the hardware/software completion paths
|
||||
are allowed to reorder completion notifications - eg. current SCSI
|
||||
midlayer doesn't preserve completion order during error handling.
|
||||
|
||||
* Requeueing order. Low-level drivers are free to requeue any request
|
||||
after they removed it from the request queue with
|
||||
blkdev_dequeue_request(). As barrier sequence should be kept in order
|
||||
when requeued, generic elevator code takes care of putting requests in
|
||||
order around barrier. See blk_ordered_req_seq() and
|
||||
ELEVATOR_INSERT_REQUEUE handling in __elv_add_request() for details.
|
||||
|
||||
Note that block drivers must not requeue preceding requests while
|
||||
completing latter requests in an ordered sequence. Currently, no
|
||||
error checking is done against this.
|
||||
|
||||
* Error handling. Currently, block layer will report error to upper
|
||||
layer if any of requests in an ordered sequence fails. Unfortunately,
|
||||
this doesn't seem to be enough. Look at the following request flow.
|
||||
QUEUE_ORDERED_TAG_FLUSH is in use.
|
||||
|
||||
[0] [1] [2] [3] [pre] [barrier] [post] < [4] [5] [6] ... >
|
||||
still in elevator
|
||||
|
||||
Let's say request [2], [3] are write requests to update file system
|
||||
metadata (journal or whatever) and [barrier] is used to mark that
|
||||
those updates are valid. Consider the following sequence.
|
||||
|
||||
i. Requests [0] ~ [post] leaves the request queue and enters
|
||||
low-level driver.
|
||||
ii. After a while, unfortunately, something goes wrong and the
|
||||
drive fails [2]. Note that any of [0], [1] and [3] could have
|
||||
completed by this time, but [pre] couldn't have been finished
|
||||
as the drive must process it in order and it failed before
|
||||
processing that command.
|
||||
iii. Error handling kicks in and determines that the error is
|
||||
unrecoverable and fails [2], and resumes operation.
|
||||
iv. [pre] [barrier] [post] gets processed.
|
||||
v. *BOOM* power fails
|
||||
|
||||
The problem here is that the barrier request is *supposed* to indicate
|
||||
that filesystem update requests [2] and [3] made it safely to the
|
||||
physical medium and, if the machine crashes after the barrier is
|
||||
written, filesystem recovery code can depend on that. Sadly, that
|
||||
isn't true in this case anymore. IOW, the success of a I/O barrier
|
||||
should also be dependent on success of some of the preceding requests,
|
||||
where only upper layer (filesystem) knows what 'some' is.
|
||||
|
||||
This can be solved by implementing a way to tell the block layer which
|
||||
requests affect the success of the following barrier request and
|
||||
making lower lever drivers to resume operation on error only after
|
||||
block layer tells it to do so.
|
||||
|
||||
As the probability of this happening is very low and the drive should
|
||||
be faulty, implementing the fix is probably an overkill. But, still,
|
||||
it's there.
|
||||
|
||||
* In previous drafts of barrier implementation, there was fallback
|
||||
mechanism such that, if FUA or ordered TAG fails, less fancy ordered
|
||||
mode can be selected and the failed barrier request is retried
|
||||
automatically. The rationale for this feature was that as FUA is
|
||||
pretty new in ATA world and ordered tag was never used widely, there
|
||||
could be devices which report to support those features but choke when
|
||||
actually given such requests.
|
||||
|
||||
This was removed for two reasons 1. it's an overkill 2. it's
|
||||
impossible to implement properly when TAG ordering is used as low
|
||||
level drivers resume after an error automatically. If it's ever
|
||||
needed adding it back and modifying low level drivers accordingly
|
||||
shouldn't be difficult.
|
|
@ -86,6 +86,62 @@ Mount options
|
|||
The default is infinite. Note that the size of read requests is
|
||||
limited anyway to 32 pages (which is 128kbyte on i386).
|
||||
|
||||
Sysfs
|
||||
~~~~~
|
||||
|
||||
FUSE sets up the following hierarchy in sysfs:
|
||||
|
||||
/sys/fs/fuse/connections/N/
|
||||
|
||||
where N is an increasing number allocated to each new connection.
|
||||
|
||||
For each connection the following attributes are defined:
|
||||
|
||||
'waiting'
|
||||
|
||||
The number of requests which are waiting to be transfered to
|
||||
userspace or being processed by the filesystem daemon. If there is
|
||||
no filesystem activity and 'waiting' is non-zero, then the
|
||||
filesystem is hung or deadlocked.
|
||||
|
||||
'abort'
|
||||
|
||||
Writing anything into this file will abort the filesystem
|
||||
connection. This means that all waiting requests will be aborted an
|
||||
error returned for all aborted and new requests.
|
||||
|
||||
Only a privileged user may read or write these attributes.
|
||||
|
||||
Aborting a filesystem connection
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
It is possible to get into certain situations where the filesystem is
|
||||
not responding. Reasons for this may be:
|
||||
|
||||
a) Broken userspace filesystem implementation
|
||||
|
||||
b) Network connection down
|
||||
|
||||
c) Accidental deadlock
|
||||
|
||||
d) Malicious deadlock
|
||||
|
||||
(For more on c) and d) see later sections)
|
||||
|
||||
In either of these cases it may be useful to abort the connection to
|
||||
the filesystem. There are several ways to do this:
|
||||
|
||||
- Kill the filesystem daemon. Works in case of a) and b)
|
||||
|
||||
- Kill the filesystem daemon and all users of the filesystem. Works
|
||||
in all cases except some malicious deadlocks
|
||||
|
||||
- Use forced umount (umount -f). Works in all cases but only if
|
||||
filesystem is still attached (it hasn't been lazy unmounted)
|
||||
|
||||
- Abort filesystem through the sysfs interface. Most powerful
|
||||
method, always works.
|
||||
|
||||
How do non-privileged mounts work?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -313,3 +369,10 @@ faulted with get_user_pages(). The 'req->locked' flag indicates
|
|||
when the copy is taking place, and interruption is delayed until
|
||||
this flag is unset.
|
||||
|
||||
Scenario 3 - Tricky deadlock with asynchronous read
|
||||
---------------------------------------------------
|
||||
|
||||
The same situation as above, except thread-1 will wait on page lock
|
||||
and hence it will be uninterruptible as well. The solution is to
|
||||
abort the connection with forced umount (if mount is attached) or
|
||||
through the abort attribute in sysfs.
|
||||
|
|
|
@ -68,3 +68,4 @@ tuner=66 - LG NTSC (TALN mini series)
|
|||
tuner=67 - Philips TD1316 Hybrid Tuner
|
||||
tuner=68 - Philips TUV1236D ATSC/NTSC dual in
|
||||
tuner=69 - Tena TNF 5335 MF
|
||||
tuner=70 - Samsung TCPN 2121P30A
|
||||
|
|
|
@ -1696,11 +1696,13 @@ M: mtk-manpages@gmx.net
|
|||
W: ftp://ftp.kernel.org/pub/linux/docs/manpages
|
||||
S: Maintained
|
||||
|
||||
MARVELL MV64340 ETHERNET DRIVER
|
||||
MARVELL MV643XX ETHERNET DRIVER
|
||||
P: Dale Farnsworth
|
||||
M: dale@farnsworth.org
|
||||
P: Manish Lachwani
|
||||
L: linux-mips@linux-mips.org
|
||||
M: mlachwani@mvista.com
|
||||
L: netdev@vger.kernel.org
|
||||
S: Supported
|
||||
S: Odd Fixes for 2.4; Maintained for 2.6.
|
||||
|
||||
MATROX FRAMEBUFFER DRIVER
|
||||
P: Petr Vandrovec
|
||||
|
|
39
Makefile
39
Makefile
|
@ -1,7 +1,7 @@
|
|||
VERSION = 2
|
||||
PATCHLEVEL = 6
|
||||
SUBLEVEL = 15
|
||||
EXTRAVERSION =
|
||||
SUBLEVEL = 16
|
||||
EXTRAVERSION =-rc1
|
||||
NAME=Sliding Snow Leopard
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
@ -106,12 +106,13 @@ KBUILD_OUTPUT := $(shell cd $(KBUILD_OUTPUT) && /bin/pwd)
|
|||
$(if $(KBUILD_OUTPUT),, \
|
||||
$(error output directory "$(saved-output)" does not exist))
|
||||
|
||||
.PHONY: $(MAKECMDGOALS)
|
||||
.PHONY: $(MAKECMDGOALS) cdbuilddir
|
||||
$(MAKECMDGOALS) _all: cdbuilddir
|
||||
|
||||
$(filter-out _all,$(MAKECMDGOALS)) _all:
|
||||
cdbuilddir:
|
||||
$(if $(KBUILD_VERBOSE:1=),@)$(MAKE) -C $(KBUILD_OUTPUT) \
|
||||
KBUILD_SRC=$(CURDIR) \
|
||||
KBUILD_EXTMOD="$(KBUILD_EXTMOD)" -f $(CURDIR)/Makefile $@
|
||||
KBUILD_EXTMOD="$(KBUILD_EXTMOD)" -f $(CURDIR)/Makefile $(MAKECMDGOALS)
|
||||
|
||||
# Leave processing to above invocation of make
|
||||
skip-makefile := 1
|
||||
|
@ -262,6 +263,13 @@ export quiet Q KBUILD_VERBOSE
|
|||
# cc support functions to be used (only) in arch/$(ARCH)/Makefile
|
||||
# See documentation in Documentation/kbuild/makefiles.txt
|
||||
|
||||
# as-option
|
||||
# Usage: cflags-y += $(call as-option, -Wa$(comma)-isa=foo,)
|
||||
|
||||
as-option = $(shell if $(CC) $(CFLAGS) $(1) -Wa,-Z -c -o /dev/null \
|
||||
-xassembler /dev/null > /dev/null 2>&1; then echo "$(1)"; \
|
||||
else echo "$(2)"; fi ;)
|
||||
|
||||
# cc-option
|
||||
# Usage: cflags-y += $(call cc-option, -march=winchip-c6, -march=i586)
|
||||
|
||||
|
@ -337,8 +345,9 @@ AFLAGS := -D__ASSEMBLY__
|
|||
|
||||
# Read KERNELRELEASE from .kernelrelease (if it exists)
|
||||
KERNELRELEASE = $(shell cat .kernelrelease 2> /dev/null)
|
||||
KERNELVERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
|
||||
|
||||
export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE \
|
||||
export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION \
|
||||
ARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC \
|
||||
CPP AR NM STRIP OBJCOPY OBJDUMP MAKE AWK GENKSYMS PERL UTS_MACHINE \
|
||||
HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS
|
||||
|
@ -433,6 +442,7 @@ export KBUILD_DEFCONFIG
|
|||
config %config: scripts_basic outputmakefile FORCE
|
||||
$(Q)mkdir -p include/linux
|
||||
$(Q)$(MAKE) $(build)=scripts/kconfig $@
|
||||
$(Q)$(MAKE) .kernelrelease
|
||||
|
||||
else
|
||||
# ===========================================================================
|
||||
|
@ -542,7 +552,7 @@ export INSTALL_PATH ?= /boot
|
|||
# makefile but the arguement can be passed to make if needed.
|
||||
#
|
||||
|
||||
MODLIB := $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE)
|
||||
MODLIB = $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE)
|
||||
export MODLIB
|
||||
|
||||
|
||||
|
@ -783,12 +793,10 @@ endif
|
|||
localver-full = $(localver)$(localver-auto)
|
||||
|
||||
# Store (new) KERNELRELASE string in .kernelrelease
|
||||
kernelrelease = \
|
||||
$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)$(localver-full)
|
||||
kernelrelease = $(KERNELVERSION)$(localver-full)
|
||||
.kernelrelease: FORCE
|
||||
$(Q)rm -f .kernelrelease
|
||||
$(Q)echo $(kernelrelease) > .kernelrelease
|
||||
$(Q)echo " Building kernel $(kernelrelease)"
|
||||
$(Q)rm -f $@
|
||||
$(Q)echo $(kernelrelease) > $@
|
||||
|
||||
|
||||
# Things we need to do before we recursively start building the kernel
|
||||
|
@ -898,7 +906,7 @@ define filechk_version.h
|
|||
)
|
||||
endef
|
||||
|
||||
include/linux/version.h: $(srctree)/Makefile FORCE
|
||||
include/linux/version.h: $(srctree)/Makefile .config FORCE
|
||||
$(call filechk,version.h)
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
@ -1301,9 +1309,10 @@ checkstack:
|
|||
$(PERL) $(src)/scripts/checkstack.pl $(ARCH)
|
||||
|
||||
kernelrelease:
|
||||
@echo $(KERNELRELEASE)
|
||||
$(if $(wildcard .kernelrelease), $(Q)echo $(KERNELRELEASE), \
|
||||
$(error kernelrelease not valid - run 'make *config' to update it))
|
||||
kernelversion:
|
||||
@echo $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
|
||||
@echo $(KERNELVERSION)
|
||||
|
||||
# FIXME Should go into a make.lib or something
|
||||
# ===========================================================================
|
||||
|
|
30
README
30
README
|
@ -1,4 +1,4 @@
|
|||
Linux kernel release 2.6.xx
|
||||
Linux kernel release 2.6.xx <http://kernel.org>
|
||||
|
||||
These are the release notes for Linux version 2.6. Read them carefully,
|
||||
as they tell you what this is all about, explain how to install the
|
||||
|
@ -6,23 +6,31 @@ kernel, and what to do if something goes wrong.
|
|||
|
||||
WHAT IS LINUX?
|
||||
|
||||
Linux is a Unix clone written from scratch by Linus Torvalds with
|
||||
assistance from a loosely-knit team of hackers across the Net.
|
||||
It aims towards POSIX compliance.
|
||||
Linux is a clone of the operating system Unix, written from scratch by
|
||||
Linus Torvalds with assistance from a loosely-knit team of hackers across
|
||||
the Net. It aims towards POSIX and Single UNIX Specification compliance.
|
||||
|
||||
It has all the features you would expect in a modern fully-fledged
|
||||
Unix, including true multitasking, virtual memory, shared libraries,
|
||||
demand loading, shared copy-on-write executables, proper memory
|
||||
management and TCP/IP networking.
|
||||
It has all the features you would expect in a modern fully-fledged Unix,
|
||||
including true multitasking, virtual memory, shared libraries, demand
|
||||
loading, shared copy-on-write executables, proper memory management,
|
||||
and multistack networking including IPv4 and IPv6.
|
||||
|
||||
It is distributed under the GNU General Public License - see the
|
||||
accompanying COPYING file for more details.
|
||||
|
||||
ON WHAT HARDWARE DOES IT RUN?
|
||||
|
||||
Linux was first developed for 386/486-based PCs. These days it also
|
||||
runs on ARMs, DEC Alphas, SUN Sparcs, M68000 machines (like Atari and
|
||||
Amiga), MIPS and PowerPC, and others.
|
||||
Although originally developed first for 32-bit x86-based PCs (386 or higher),
|
||||
today Linux also runs on (at least) the Compaq Alpha AXP, Sun SPARC and
|
||||
UltraSPARC, Motorola 68000, PowerPC, PowerPC64, ARM, Hitachi SuperH,
|
||||
IBM S/390, MIPS, HP PA-RISC, Intel IA-64, DEC VAX, AMD x86-64, AXIS CRIS,
|
||||
and Renesas M32R architectures.
|
||||
|
||||
Linux is easily portable to most general-purpose 32- or 64-bit architectures
|
||||
as long as they have a paged memory management unit (PMMU) and a port of the
|
||||
GNU C compiler (gcc) (part of The GNU Compiler Collection, GCC). Linux has
|
||||
also been ported to a number of architectures without a PMMU, although
|
||||
functionality is then obviously somewhat limited.
|
||||
|
||||
DOCUMENTATION:
|
||||
|
||||
|
|
|
@ -141,7 +141,7 @@ int show_interrupts(struct seq_file *p, void *v)
|
|||
if (i < NR_IRQS) {
|
||||
action = irq_desc[i].action;
|
||||
if (!action)
|
||||
continue;
|
||||
goto out;
|
||||
seq_printf(p, "%3d: %10u ", i, kstat_irqs(i));
|
||||
seq_printf(p, " %s", action->name);
|
||||
for (action = action->next; action; action = action->next) {
|
||||
|
@ -152,6 +152,7 @@ int show_interrupts(struct seq_file *p, void *v)
|
|||
show_fiq_list(p, v);
|
||||
seq_printf(p, "Err: %10lu\n", irq_err_count);
|
||||
}
|
||||
out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -527,7 +527,7 @@ static int ptrace_getfpregs(struct task_struct *tsk, void *ufp)
|
|||
static int ptrace_setfpregs(struct task_struct *tsk, void *ufp)
|
||||
{
|
||||
set_stopped_child_used_math(tsk);
|
||||
return copy_from_user(&task_threas_info(tsk)->fpstate, ufp,
|
||||
return copy_from_user(&task_thread_info(tsk)->fpstate, ufp,
|
||||
sizeof(struct user_fp)) ? -EFAULT : 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,10 +37,7 @@ CFLAGS += $(call cc-option,-mpreferred-stack-boundary=2)
|
|||
# CPU-specific tuning. Anything which can be shared with UML should go here.
|
||||
include $(srctree)/arch/i386/Makefile.cpu
|
||||
|
||||
# -mregparm=3 works ok on gcc-3.0 and later
|
||||
#
|
||||
cflags-$(CONFIG_REGPARM) += $(shell if [ $(call cc-version) -ge 0300 ] ; then \
|
||||
echo "-mregparm=3"; fi ;)
|
||||
cflags-$(CONFIG_REGPARM) += -mregparm=3
|
||||
|
||||
# Disable unit-at-a-time mode on pre-gcc-4.0 compilers, it makes gcc use
|
||||
# a lot more stack due to the lack of sharing of stacklots:
|
||||
|
|
|
@ -980,7 +980,7 @@ static int powernowk8_verify(struct cpufreq_policy *pol)
|
|||
}
|
||||
|
||||
/* per CPU init entry point to the driver */
|
||||
static int __init powernowk8_cpu_init(struct cpufreq_policy *pol)
|
||||
static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
|
||||
{
|
||||
struct powernow_k8_data *data;
|
||||
cpumask_t oldmask = CPU_MASK_ALL;
|
||||
|
@ -1141,7 +1141,7 @@ static struct cpufreq_driver cpufreq_amd64_driver = {
|
|||
};
|
||||
|
||||
/* driver entry point for init */
|
||||
static int __init powernowk8_init(void)
|
||||
static int __cpuinit powernowk8_init(void)
|
||||
{
|
||||
unsigned int i, supported_cpus = 0;
|
||||
|
||||
|
|
|
@ -268,7 +268,7 @@ static void __init permanent_kmaps_init(pgd_t *pgd_base)
|
|||
pkmap_page_table = pte;
|
||||
}
|
||||
|
||||
static void __devinit free_new_highpage(struct page *page)
|
||||
static void __meminit free_new_highpage(struct page *page)
|
||||
{
|
||||
set_page_count(page, 1);
|
||||
__free_page(page);
|
||||
|
|
|
@ -628,9 +628,11 @@ static int pfm_write_ibr_dbr(int mode, pfm_context_t *ctx, void *arg, int count,
|
|||
|
||||
#include "perfmon_itanium.h"
|
||||
#include "perfmon_mckinley.h"
|
||||
#include "perfmon_montecito.h"
|
||||
#include "perfmon_generic.h"
|
||||
|
||||
static pmu_config_t *pmu_confs[]={
|
||||
&pmu_conf_mont,
|
||||
&pmu_conf_mck,
|
||||
&pmu_conf_ita,
|
||||
&pmu_conf_gen, /* must be last */
|
||||
|
|
269
arch/ia64/kernel/perfmon_montecito.h
Normal file
269
arch/ia64/kernel/perfmon_montecito.h
Normal file
|
@ -0,0 +1,269 @@
|
|||
/*
|
||||
* This file contains the Montecito PMU register description tables
|
||||
* and pmc checker used by perfmon.c.
|
||||
*
|
||||
* Copyright (c) 2005-2006 Hewlett-Packard Development Company, L.P.
|
||||
* Contributed by Stephane Eranian <eranian@hpl.hp.com>
|
||||
*/
|
||||
static int pfm_mont_pmc_check(struct task_struct *task, pfm_context_t *ctx, unsigned int cnum, unsigned long *val, struct pt_regs *regs);
|
||||
|
||||
#define RDEP_MONT_ETB (RDEP(38)|RDEP(39)|RDEP(48)|RDEP(49)|RDEP(50)|RDEP(51)|RDEP(52)|RDEP(53)|RDEP(54)|\
|
||||
RDEP(55)|RDEP(56)|RDEP(57)|RDEP(58)|RDEP(59)|RDEP(60)|RDEP(61)|RDEP(62)|RDEP(63))
|
||||
#define RDEP_MONT_DEAR (RDEP(32)|RDEP(33)|RDEP(36))
|
||||
#define RDEP_MONT_IEAR (RDEP(34)|RDEP(35))
|
||||
|
||||
static pfm_reg_desc_t pfm_mont_pmc_desc[PMU_MAX_PMCS]={
|
||||
/* pmc0 */ { PFM_REG_CONTROL , 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {0,0, 0, 0}},
|
||||
/* pmc1 */ { PFM_REG_CONTROL , 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {0,0, 0, 0}},
|
||||
/* pmc2 */ { PFM_REG_CONTROL , 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {0,0, 0, 0}},
|
||||
/* pmc3 */ { PFM_REG_CONTROL , 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {0,0, 0, 0}},
|
||||
/* pmc4 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(4),0, 0, 0}, {0,0, 0, 0}},
|
||||
/* pmc5 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(5),0, 0, 0}, {0,0, 0, 0}},
|
||||
/* pmc6 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(6),0, 0, 0}, {0,0, 0, 0}},
|
||||
/* pmc7 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(7),0, 0, 0}, {0,0, 0, 0}},
|
||||
/* pmc8 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(8),0, 0, 0}, {0,0, 0, 0}},
|
||||
/* pmc9 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(9),0, 0, 0}, {0,0, 0, 0}},
|
||||
/* pmc10 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(10),0, 0, 0}, {0,0, 0, 0}},
|
||||
/* pmc11 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(11),0, 0, 0}, {0,0, 0, 0}},
|
||||
/* pmc12 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(12),0, 0, 0}, {0,0, 0, 0}},
|
||||
/* pmc13 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(13),0, 0, 0}, {0,0, 0, 0}},
|
||||
/* pmc14 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(14),0, 0, 0}, {0,0, 0, 0}},
|
||||
/* pmc15 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(15),0, 0, 0}, {0,0, 0, 0}},
|
||||
/* pmc16 */ { PFM_REG_NOTIMPL, },
|
||||
/* pmc17 */ { PFM_REG_NOTIMPL, },
|
||||
/* pmc18 */ { PFM_REG_NOTIMPL, },
|
||||
/* pmc19 */ { PFM_REG_NOTIMPL, },
|
||||
/* pmc20 */ { PFM_REG_NOTIMPL, },
|
||||
/* pmc21 */ { PFM_REG_NOTIMPL, },
|
||||
/* pmc22 */ { PFM_REG_NOTIMPL, },
|
||||
/* pmc23 */ { PFM_REG_NOTIMPL, },
|
||||
/* pmc24 */ { PFM_REG_NOTIMPL, },
|
||||
/* pmc25 */ { PFM_REG_NOTIMPL, },
|
||||
/* pmc26 */ { PFM_REG_NOTIMPL, },
|
||||
/* pmc27 */ { PFM_REG_NOTIMPL, },
|
||||
/* pmc28 */ { PFM_REG_NOTIMPL, },
|
||||
/* pmc29 */ { PFM_REG_NOTIMPL, },
|
||||
/* pmc30 */ { PFM_REG_NOTIMPL, },
|
||||
/* pmc31 */ { PFM_REG_NOTIMPL, },
|
||||
/* pmc32 */ { PFM_REG_CONFIG, 0, 0x30f01ffffffffff, 0x30f01ffffffffff, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}},
|
||||
/* pmc33 */ { PFM_REG_CONFIG, 0, 0x0, 0x1ffffffffff, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}},
|
||||
/* pmc34 */ { PFM_REG_CONFIG, 0, 0xf01ffffffffff, 0xf01ffffffffff, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}},
|
||||
/* pmc35 */ { PFM_REG_CONFIG, 0, 0x0, 0x1ffffffffff, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}},
|
||||
/* pmc36 */ { PFM_REG_CONFIG, 0, 0xfffffff0, 0xf, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}},
|
||||
/* pmc37 */ { PFM_REG_MONITOR, 4, 0x0, 0x3fff, NULL, pfm_mont_pmc_check, {RDEP_MONT_IEAR, 0, 0, 0}, {0, 0, 0, 0}},
|
||||
/* pmc38 */ { PFM_REG_CONFIG, 0, 0xdb6, 0x2492, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}},
|
||||
/* pmc39 */ { PFM_REG_MONITOR, 6, 0x0, 0xffcf, NULL, pfm_mont_pmc_check, {RDEP_MONT_ETB,0, 0, 0}, {0,0, 0, 0}},
|
||||
/* pmc40 */ { PFM_REG_MONITOR, 6, 0x2000000, 0xf01cf, NULL, pfm_mont_pmc_check, {RDEP_MONT_DEAR,0, 0, 0}, {0,0, 0, 0}},
|
||||
/* pmc41 */ { PFM_REG_CONFIG, 0, 0x00002078fefefefe, 0x1e00018181818, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}},
|
||||
/* pmc42 */ { PFM_REG_MONITOR, 6, 0x0, 0x7ff4f, NULL, pfm_mont_pmc_check, {RDEP_MONT_ETB,0, 0, 0}, {0,0, 0, 0}},
|
||||
{ PFM_REG_END , 0, 0x0, -1, NULL, NULL, {0,}, {0,}}, /* end marker */
|
||||
};
|
||||
|
||||
static pfm_reg_desc_t pfm_mont_pmd_desc[PMU_MAX_PMDS]={
|
||||
/* pmd0 */ { PFM_REG_NOTIMPL, },
|
||||
/* pmd1 */ { PFM_REG_NOTIMPL, },
|
||||
/* pmd2 */ { PFM_REG_NOTIMPL, },
|
||||
/* pmd3 */ { PFM_REG_NOTIMPL, },
|
||||
/* pmd4 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(4),0, 0, 0}},
|
||||
/* pmd5 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(5),0, 0, 0}},
|
||||
/* pmd6 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(6),0, 0, 0}},
|
||||
/* pmd7 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(7),0, 0, 0}},
|
||||
/* pmd8 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(8),0, 0, 0}},
|
||||
/* pmd9 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(9),0, 0, 0}},
|
||||
/* pmd10 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(10),0, 0, 0}},
|
||||
/* pmd11 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(11),0, 0, 0}},
|
||||
/* pmd12 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(12),0, 0, 0}},
|
||||
/* pmd13 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(13),0, 0, 0}},
|
||||
/* pmd14 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(14),0, 0, 0}},
|
||||
/* pmd15 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(15),0, 0, 0}},
|
||||
/* pmd16 */ { PFM_REG_NOTIMPL, },
|
||||
/* pmd17 */ { PFM_REG_NOTIMPL, },
|
||||
/* pmd18 */ { PFM_REG_NOTIMPL, },
|
||||
/* pmd19 */ { PFM_REG_NOTIMPL, },
|
||||
/* pmd20 */ { PFM_REG_NOTIMPL, },
|
||||
/* pmd21 */ { PFM_REG_NOTIMPL, },
|
||||
/* pmd22 */ { PFM_REG_NOTIMPL, },
|
||||
/* pmd23 */ { PFM_REG_NOTIMPL, },
|
||||
/* pmd24 */ { PFM_REG_NOTIMPL, },
|
||||
/* pmd25 */ { PFM_REG_NOTIMPL, },
|
||||
/* pmd26 */ { PFM_REG_NOTIMPL, },
|
||||
/* pmd27 */ { PFM_REG_NOTIMPL, },
|
||||
/* pmd28 */ { PFM_REG_NOTIMPL, },
|
||||
/* pmd29 */ { PFM_REG_NOTIMPL, },
|
||||
/* pmd30 */ { PFM_REG_NOTIMPL, },
|
||||
/* pmd31 */ { PFM_REG_NOTIMPL, },
|
||||
/* pmd32 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP(33)|RDEP(36),0, 0, 0}, {RDEP(40),0, 0, 0}},
|
||||
/* pmd33 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP(32)|RDEP(36),0, 0, 0}, {RDEP(40),0, 0, 0}},
|
||||
/* pmd34 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP(35),0, 0, 0}, {RDEP(37),0, 0, 0}},
|
||||
/* pmd35 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP(34),0, 0, 0}, {RDEP(37),0, 0, 0}},
|
||||
/* pmd36 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP(32)|RDEP(33),0, 0, 0}, {RDEP(40),0, 0, 0}},
|
||||
/* pmd37 */ { PFM_REG_NOTIMPL, },
|
||||
/* pmd38 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}},
|
||||
/* pmd39 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}},
|
||||
/* pmd40 */ { PFM_REG_NOTIMPL, },
|
||||
/* pmd41 */ { PFM_REG_NOTIMPL, },
|
||||
/* pmd42 */ { PFM_REG_NOTIMPL, },
|
||||
/* pmd43 */ { PFM_REG_NOTIMPL, },
|
||||
/* pmd44 */ { PFM_REG_NOTIMPL, },
|
||||
/* pmd45 */ { PFM_REG_NOTIMPL, },
|
||||
/* pmd46 */ { PFM_REG_NOTIMPL, },
|
||||
/* pmd47 */ { PFM_REG_NOTIMPL, },
|
||||
/* pmd48 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}},
|
||||
/* pmd49 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}},
|
||||
/* pmd50 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}},
|
||||
/* pmd51 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}},
|
||||
/* pmd52 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}},
|
||||
/* pmd53 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}},
|
||||
/* pmd54 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}},
|
||||
/* pmd55 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}},
|
||||
/* pmd56 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}},
|
||||
/* pmd57 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}},
|
||||
/* pmd58 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}},
|
||||
/* pmd59 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}},
|
||||
/* pmd60 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}},
|
||||
/* pmd61 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}},
|
||||
/* pmd62 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}},
|
||||
/* pmd63 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}},
|
||||
{ PFM_REG_END , 0, 0x0, -1, NULL, NULL, {0,}, {0,}}, /* end marker */
|
||||
};
|
||||
|
||||
/*
|
||||
* PMC reserved fields must have their power-up values preserved
|
||||
*/
|
||||
static int
|
||||
pfm_mont_reserved(unsigned int cnum, unsigned long *val, struct pt_regs *regs)
|
||||
{
|
||||
unsigned long tmp1, tmp2, ival = *val;
|
||||
|
||||
/* remove reserved areas from user value */
|
||||
tmp1 = ival & PMC_RSVD_MASK(cnum);
|
||||
|
||||
/* get reserved fields values */
|
||||
tmp2 = PMC_DFL_VAL(cnum) & ~PMC_RSVD_MASK(cnum);
|
||||
|
||||
*val = tmp1 | tmp2;
|
||||
|
||||
DPRINT(("pmc[%d]=0x%lx, mask=0x%lx, reset=0x%lx, val=0x%lx\n",
|
||||
cnum, ival, PMC_RSVD_MASK(cnum), PMC_DFL_VAL(cnum), *val));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* task can be NULL if the context is unloaded
|
||||
*/
|
||||
static int
|
||||
pfm_mont_pmc_check(struct task_struct *task, pfm_context_t *ctx, unsigned int cnum, unsigned long *val, struct pt_regs *regs)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long val32 = 0, val38 = 0, val41 = 0;
|
||||
unsigned long tmpval;
|
||||
int check_case1 = 0;
|
||||
int is_loaded;
|
||||
|
||||
/* first preserve the reserved fields */
|
||||
pfm_mont_reserved(cnum, val, regs);
|
||||
|
||||
tmpval = *val;
|
||||
|
||||
/* sanity check */
|
||||
if (ctx == NULL) return -EINVAL;
|
||||
|
||||
is_loaded = ctx->ctx_state == PFM_CTX_LOADED || ctx->ctx_state == PFM_CTX_MASKED;
|
||||
|
||||
/*
|
||||
* we must clear the debug registers if pmc41 has a value which enable
|
||||
* memory pipeline event constraints. In this case we need to clear the
|
||||
* the debug registers if they have not yet been accessed. This is required
|
||||
* to avoid picking stale state.
|
||||
* PMC41 is "active" if:
|
||||
* one of the pmc41.cfg_dtagXX field is different from 0x3
|
||||
* AND
|
||||
* at the corresponding pmc41.en_dbrpXX is set.
|
||||
* AND
|
||||
* ctx_fl_using_dbreg == 0 (i.e., dbr not yet used)
|
||||
*/
|
||||
DPRINT(("cnum=%u val=0x%lx, using_dbreg=%d loaded=%d\n", cnum, tmpval, ctx->ctx_fl_using_dbreg, is_loaded));
|
||||
|
||||
if (cnum == 41 && is_loaded
|
||||
&& (tmpval & 0x1e00000000000) && (tmpval & 0x18181818UL) != 0x18181818UL && ctx->ctx_fl_using_dbreg == 0) {
|
||||
|
||||
DPRINT(("pmc[%d]=0x%lx has active pmc41 settings, clearing dbr\n", cnum, tmpval));
|
||||
|
||||
/* don't mix debug with perfmon */
|
||||
if (task && (task->thread.flags & IA64_THREAD_DBG_VALID) != 0) return -EINVAL;
|
||||
|
||||
/*
|
||||
* a count of 0 will mark the debug registers if:
|
||||
* AND
|
||||
*/
|
||||
ret = pfm_write_ibr_dbr(PFM_DATA_RR, ctx, NULL, 0, regs);
|
||||
if (ret) return ret;
|
||||
}
|
||||
/*
|
||||
* we must clear the (instruction) debug registers if:
|
||||
* pmc38.ig_ibrpX is 0 (enabled)
|
||||
* AND
|
||||
* ctx_fl_using_dbreg == 0 (i.e., dbr not yet used)
|
||||
*/
|
||||
if (cnum == 38 && is_loaded && ((tmpval & 0x492UL) != 0x492UL) && ctx->ctx_fl_using_dbreg == 0) {
|
||||
|
||||
DPRINT(("pmc38=0x%lx has active pmc38 settings, clearing ibr\n", tmpval));
|
||||
|
||||
/* don't mix debug with perfmon */
|
||||
if (task && (task->thread.flags & IA64_THREAD_DBG_VALID) != 0) return -EINVAL;
|
||||
|
||||
/*
|
||||
* a count of 0 will mark the debug registers as in use and also
|
||||
* ensure that they are properly cleared.
|
||||
*/
|
||||
ret = pfm_write_ibr_dbr(PFM_CODE_RR, ctx, NULL, 0, regs);
|
||||
if (ret) return ret;
|
||||
|
||||
}
|
||||
switch(cnum) {
|
||||
case 32: val32 = *val;
|
||||
val38 = ctx->ctx_pmcs[38];
|
||||
val41 = ctx->ctx_pmcs[41];
|
||||
check_case1 = 1;
|
||||
break;
|
||||
case 38: val38 = *val;
|
||||
val32 = ctx->ctx_pmcs[32];
|
||||
val41 = ctx->ctx_pmcs[41];
|
||||
check_case1 = 1;
|
||||
break;
|
||||
case 41: val41 = *val;
|
||||
val32 = ctx->ctx_pmcs[32];
|
||||
val38 = ctx->ctx_pmcs[38];
|
||||
check_case1 = 1;
|
||||
break;
|
||||
}
|
||||
/* check illegal configuration which can produce inconsistencies in tagging
|
||||
* i-side events in L1D and L2 caches
|
||||
*/
|
||||
if (check_case1) {
|
||||
ret = (((val41 >> 45) & 0xf) == 0 && ((val32>>57) & 0x1) == 0)
|
||||
&& ((((val38>>1) & 0x3) == 0x2 || ((val38>>1) & 0x3) == 0)
|
||||
|| (((val38>>4) & 0x3) == 0x2 || ((val38>>4) & 0x3) == 0));
|
||||
if (ret) {
|
||||
DPRINT(("invalid config pmc38=0x%lx pmc41=0x%lx pmc32=0x%lx\n", val38, val41, val32));
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
*val = tmpval;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* impl_pmcs, impl_pmds are computed at runtime to minimize errors!
|
||||
*/
|
||||
static pmu_config_t pmu_conf_mont={
|
||||
.pmu_name = "Montecito",
|
||||
.pmu_family = 0x20,
|
||||
.flags = PFM_PMU_IRQ_RESEND,
|
||||
.ovfl_val = (1UL << 47) - 1,
|
||||
.pmd_desc = pfm_mont_pmd_desc,
|
||||
.pmc_desc = pfm_mont_pmc_desc,
|
||||
.num_ibrs = 8,
|
||||
.num_dbrs = 8,
|
||||
.use_rr_dbregs = 1 /* debug register are use for range retrictions */
|
||||
};
|
|
@ -635,3 +635,39 @@ mem_init (void)
|
|||
ia32_mem_init();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MEMORY_HOTPLUG
|
||||
void online_page(struct page *page)
|
||||
{
|
||||
ClearPageReserved(page);
|
||||
set_page_count(page, 1);
|
||||
__free_page(page);
|
||||
totalram_pages++;
|
||||
num_physpages++;
|
||||
}
|
||||
|
||||
int add_memory(u64 start, u64 size)
|
||||
{
|
||||
pg_data_t *pgdat;
|
||||
struct zone *zone;
|
||||
unsigned long start_pfn = start >> PAGE_SHIFT;
|
||||
unsigned long nr_pages = size >> PAGE_SHIFT;
|
||||
int ret;
|
||||
|
||||
pgdat = NODE_DATA(0);
|
||||
|
||||
zone = pgdat->node_zones + ZONE_NORMAL;
|
||||
ret = __add_pages(zone, start_pfn, nr_pages);
|
||||
|
||||
if (ret)
|
||||
printk("%s: Problem encountered in __add_pages() as ret=%d\n",
|
||||
__FUNCTION__, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int remove_memory(u64 start, u64 size)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -454,14 +454,13 @@ static int __devinit is_valid_resource(struct pci_dev *dev, int idx)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev)
|
||||
static void __devinit
|
||||
pcibios_fixup_resources(struct pci_dev *dev, int start, int limit)
|
||||
{
|
||||
struct pci_bus_region region;
|
||||
int i;
|
||||
int limit = (dev->hdr_type == PCI_HEADER_TYPE_NORMAL) ? \
|
||||
PCI_BRIDGE_RESOURCES : PCI_NUM_RESOURCES;
|
||||
|
||||
for (i = 0; i < limit; i++) {
|
||||
for (i = start; i < limit; i++) {
|
||||
if (!dev->resource[i].flags)
|
||||
continue;
|
||||
region.start = dev->resource[i].start;
|
||||
|
@ -472,6 +471,16 @@ static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev)
|
|||
}
|
||||
}
|
||||
|
||||
static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev)
|
||||
{
|
||||
pcibios_fixup_resources(dev, 0, PCI_BRIDGE_RESOURCES);
|
||||
}
|
||||
|
||||
static void __devinit pcibios_fixup_bridge_resources(struct pci_dev *dev)
|
||||
{
|
||||
pcibios_fixup_resources(dev, PCI_BRIDGE_RESOURCES, PCI_NUM_RESOURCES);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called after each bus is probed, but before its children are examined.
|
||||
*/
|
||||
|
@ -482,7 +491,7 @@ pcibios_fixup_bus (struct pci_bus *b)
|
|||
|
||||
if (b->self) {
|
||||
pci_read_bridge_bases(b);
|
||||
pcibios_fixup_device_resources(b->self);
|
||||
pcibios_fixup_bridge_resources(b->self);
|
||||
}
|
||||
list_for_each_entry(dev, &b->devices, bus_list)
|
||||
pcibios_fixup_device_resources(dev);
|
||||
|
|
|
@ -40,8 +40,8 @@ struct sn_flush_device_common {
|
|||
unsigned long sfdl_force_int_addr;
|
||||
unsigned long sfdl_flush_value;
|
||||
volatile unsigned long *sfdl_flush_addr;
|
||||
uint32_t sfdl_persistent_busnum;
|
||||
uint32_t sfdl_persistent_segment;
|
||||
u32 sfdl_persistent_busnum;
|
||||
u32 sfdl_persistent_segment;
|
||||
struct pcibus_info *sfdl_pcibus_info;
|
||||
};
|
||||
|
||||
|
@ -56,7 +56,7 @@ struct sn_flush_device_kernel {
|
|||
*/
|
||||
struct sn_flush_nasid_entry {
|
||||
struct sn_flush_device_kernel **widget_p; // Used as an array of wid_num
|
||||
uint64_t iio_itte[8];
|
||||
u64 iio_itte[8];
|
||||
};
|
||||
|
||||
struct hubdev_info {
|
||||
|
@ -70,8 +70,8 @@ struct hubdev_info {
|
|||
|
||||
void *hdi_nodepda;
|
||||
void *hdi_node_vertex;
|
||||
uint32_t max_segment_number;
|
||||
uint32_t max_pcibus_number;
|
||||
u32 max_segment_number;
|
||||
u32 max_pcibus_number;
|
||||
};
|
||||
|
||||
extern void hubdev_init_node(nodepda_t *, cnodeid_t);
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* Copyright (C) 1992-1997,2000-2004 Silicon Graphics, Inc. All Rights Reserved.
|
||||
* Copyright (C) 1992-1997,2000-2006 Silicon Graphics, Inc. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
#ifndef _ASM_IA64_SN_XTALK_XBOW_H
|
||||
#define _ASM_IA64_SN_XTALK_XBOW_H
|
||||
|
@ -21,94 +22,94 @@
|
|||
|
||||
/* Register set for each xbow link */
|
||||
typedef volatile struct xb_linkregs_s {
|
||||
/*
|
||||
/*
|
||||
* we access these through synergy unswizzled space, so the address
|
||||
* gets twiddled (i.e. references to 0x4 actually go to 0x0 and vv.)
|
||||
* That's why we put the register first and filler second.
|
||||
*/
|
||||
uint32_t link_ibf;
|
||||
uint32_t filler0; /* filler for proper alignment */
|
||||
uint32_t link_control;
|
||||
uint32_t filler1;
|
||||
uint32_t link_status;
|
||||
uint32_t filler2;
|
||||
uint32_t link_arb_upper;
|
||||
uint32_t filler3;
|
||||
uint32_t link_arb_lower;
|
||||
uint32_t filler4;
|
||||
uint32_t link_status_clr;
|
||||
uint32_t filler5;
|
||||
uint32_t link_reset;
|
||||
uint32_t filler6;
|
||||
uint32_t link_aux_status;
|
||||
uint32_t filler7;
|
||||
u32 link_ibf;
|
||||
u32 filler0; /* filler for proper alignment */
|
||||
u32 link_control;
|
||||
u32 filler1;
|
||||
u32 link_status;
|
||||
u32 filler2;
|
||||
u32 link_arb_upper;
|
||||
u32 filler3;
|
||||
u32 link_arb_lower;
|
||||
u32 filler4;
|
||||
u32 link_status_clr;
|
||||
u32 filler5;
|
||||
u32 link_reset;
|
||||
u32 filler6;
|
||||
u32 link_aux_status;
|
||||
u32 filler7;
|
||||
} xb_linkregs_t;
|
||||
|
||||
typedef volatile struct xbow_s {
|
||||
/* standard widget configuration 0x000000-0x000057 */
|
||||
struct widget_cfg xb_widget; /* 0x000000 */
|
||||
/* standard widget configuration 0x000000-0x000057 */
|
||||
struct widget_cfg xb_widget; /* 0x000000 */
|
||||
|
||||
/* helper fieldnames for accessing bridge widget */
|
||||
/* helper fieldnames for accessing bridge widget */
|
||||
|
||||
#define xb_wid_id xb_widget.w_id
|
||||
#define xb_wid_stat xb_widget.w_status
|
||||
#define xb_wid_err_upper xb_widget.w_err_upper_addr
|
||||
#define xb_wid_err_lower xb_widget.w_err_lower_addr
|
||||
#define xb_wid_control xb_widget.w_control
|
||||
#define xb_wid_req_timeout xb_widget.w_req_timeout
|
||||
#define xb_wid_int_upper xb_widget.w_intdest_upper_addr
|
||||
#define xb_wid_int_lower xb_widget.w_intdest_lower_addr
|
||||
#define xb_wid_err_cmdword xb_widget.w_err_cmd_word
|
||||
#define xb_wid_llp xb_widget.w_llp_cfg
|
||||
#define xb_wid_stat_clr xb_widget.w_tflush
|
||||
#define xb_wid_id xb_widget.w_id
|
||||
#define xb_wid_stat xb_widget.w_status
|
||||
#define xb_wid_err_upper xb_widget.w_err_upper_addr
|
||||
#define xb_wid_err_lower xb_widget.w_err_lower_addr
|
||||
#define xb_wid_control xb_widget.w_control
|
||||
#define xb_wid_req_timeout xb_widget.w_req_timeout
|
||||
#define xb_wid_int_upper xb_widget.w_intdest_upper_addr
|
||||
#define xb_wid_int_lower xb_widget.w_intdest_lower_addr
|
||||
#define xb_wid_err_cmdword xb_widget.w_err_cmd_word
|
||||
#define xb_wid_llp xb_widget.w_llp_cfg
|
||||
#define xb_wid_stat_clr xb_widget.w_tflush
|
||||
|
||||
/*
|
||||
/*
|
||||
* we access these through synergy unswizzled space, so the address
|
||||
* gets twiddled (i.e. references to 0x4 actually go to 0x0 and vv.)
|
||||
* That's why we put the register first and filler second.
|
||||
*/
|
||||
/* xbow-specific widget configuration 0x000058-0x0000FF */
|
||||
uint32_t xb_wid_arb_reload; /* 0x00005C */
|
||||
uint32_t _pad_000058;
|
||||
uint32_t xb_perf_ctr_a; /* 0x000064 */
|
||||
uint32_t _pad_000060;
|
||||
uint32_t xb_perf_ctr_b; /* 0x00006c */
|
||||
uint32_t _pad_000068;
|
||||
uint32_t xb_nic; /* 0x000074 */
|
||||
uint32_t _pad_000070;
|
||||
/* xbow-specific widget configuration 0x000058-0x0000FF */
|
||||
u32 xb_wid_arb_reload; /* 0x00005C */
|
||||
u32 _pad_000058;
|
||||
u32 xb_perf_ctr_a; /* 0x000064 */
|
||||
u32 _pad_000060;
|
||||
u32 xb_perf_ctr_b; /* 0x00006c */
|
||||
u32 _pad_000068;
|
||||
u32 xb_nic; /* 0x000074 */
|
||||
u32 _pad_000070;
|
||||
|
||||
/* Xbridge only */
|
||||
uint32_t xb_w0_rst_fnc; /* 0x00007C */
|
||||
uint32_t _pad_000078;
|
||||
uint32_t xb_l8_rst_fnc; /* 0x000084 */
|
||||
uint32_t _pad_000080;
|
||||
uint32_t xb_l9_rst_fnc; /* 0x00008c */
|
||||
uint32_t _pad_000088;
|
||||
uint32_t xb_la_rst_fnc; /* 0x000094 */
|
||||
uint32_t _pad_000090;
|
||||
uint32_t xb_lb_rst_fnc; /* 0x00009c */
|
||||
uint32_t _pad_000098;
|
||||
uint32_t xb_lc_rst_fnc; /* 0x0000a4 */
|
||||
uint32_t _pad_0000a0;
|
||||
uint32_t xb_ld_rst_fnc; /* 0x0000ac */
|
||||
uint32_t _pad_0000a8;
|
||||
uint32_t xb_le_rst_fnc; /* 0x0000b4 */
|
||||
uint32_t _pad_0000b0;
|
||||
uint32_t xb_lf_rst_fnc; /* 0x0000bc */
|
||||
uint32_t _pad_0000b8;
|
||||
uint32_t xb_lock; /* 0x0000c4 */
|
||||
uint32_t _pad_0000c0;
|
||||
uint32_t xb_lock_clr; /* 0x0000cc */
|
||||
uint32_t _pad_0000c8;
|
||||
/* end of Xbridge only */
|
||||
uint32_t _pad_0000d0[12];
|
||||
|
||||
/* Link Specific Registers, port 8..15 0x000100-0x000300 */
|
||||
xb_linkregs_t xb_link_raw[MAX_XBOW_PORTS];
|
||||
#define xb_link(p) xb_link_raw[(p) & (MAX_XBOW_PORTS - 1)]
|
||||
/* Xbridge only */
|
||||
u32 xb_w0_rst_fnc; /* 0x00007C */
|
||||
u32 _pad_000078;
|
||||
u32 xb_l8_rst_fnc; /* 0x000084 */
|
||||
u32 _pad_000080;
|
||||
u32 xb_l9_rst_fnc; /* 0x00008c */
|
||||
u32 _pad_000088;
|
||||
u32 xb_la_rst_fnc; /* 0x000094 */
|
||||
u32 _pad_000090;
|
||||
u32 xb_lb_rst_fnc; /* 0x00009c */
|
||||
u32 _pad_000098;
|
||||
u32 xb_lc_rst_fnc; /* 0x0000a4 */
|
||||
u32 _pad_0000a0;
|
||||
u32 xb_ld_rst_fnc; /* 0x0000ac */
|
||||
u32 _pad_0000a8;
|
||||
u32 xb_le_rst_fnc; /* 0x0000b4 */
|
||||
u32 _pad_0000b0;
|
||||
u32 xb_lf_rst_fnc; /* 0x0000bc */
|
||||
u32 _pad_0000b8;
|
||||
u32 xb_lock; /* 0x0000c4 */
|
||||
u32 _pad_0000c0;
|
||||
u32 xb_lock_clr; /* 0x0000cc */
|
||||
u32 _pad_0000c8;
|
||||
/* end of Xbridge only */
|
||||
u32 _pad_0000d0[12];
|
||||
|
||||
/* Link Specific Registers, port 8..15 0x000100-0x000300 */
|
||||
xb_linkregs_t xb_link_raw[MAX_XBOW_PORTS];
|
||||
} xbow_t;
|
||||
|
||||
#define xb_link(p) xb_link_raw[(p) & (MAX_XBOW_PORTS - 1)]
|
||||
|
||||
#define XB_FLAGS_EXISTS 0x1 /* device exists */
|
||||
#define XB_FLAGS_MASTER 0x2
|
||||
#define XB_FLAGS_SLAVE 0x0
|
||||
|
@ -160,7 +161,7 @@ typedef volatile struct xbow_s {
|
|||
/* End of Xbridge only */
|
||||
|
||||
/* used only in ide, but defined here within the reserved portion */
|
||||
/* of the widget0 address space (before 0xf4) */
|
||||
/* of the widget0 address space (before 0xf4) */
|
||||
#define XBOW_WID_UNDEF 0xe4
|
||||
|
||||
/* xbow link register set base, legal value for x is 0x8..0xf */
|
||||
|
@ -179,29 +180,37 @@ typedef volatile struct xbow_s {
|
|||
|
||||
/* link_control(x) */
|
||||
#define XB_CTRL_LINKALIVE_IE 0x80000000 /* link comes alive */
|
||||
/* reserved: 0x40000000 */
|
||||
/* reserved: 0x40000000 */
|
||||
#define XB_CTRL_PERF_CTR_MODE_MSK 0x30000000 /* perf counter mode */
|
||||
#define XB_CTRL_IBUF_LEVEL_MSK 0x0e000000 /* input packet buffer level */
|
||||
#define XB_CTRL_8BIT_MODE 0x01000000 /* force link into 8 bit mode */
|
||||
#define XB_CTRL_BAD_LLP_PKT 0x00800000 /* force bad LLP packet */
|
||||
#define XB_CTRL_WIDGET_CR_MSK 0x007c0000 /* LLP widget credit mask */
|
||||
#define XB_CTRL_WIDGET_CR_SHFT 18 /* LLP widget credit shift */
|
||||
#define XB_CTRL_ILLEGAL_DST_IE 0x00020000 /* illegal destination */
|
||||
#define XB_CTRL_OALLOC_IBUF_IE 0x00010000 /* overallocated input buffer */
|
||||
/* reserved: 0x0000fe00 */
|
||||
#define XB_CTRL_IBUF_LEVEL_MSK 0x0e000000 /* input packet buffer
|
||||
level */
|
||||
#define XB_CTRL_8BIT_MODE 0x01000000 /* force link into 8
|
||||
bit mode */
|
||||
#define XB_CTRL_BAD_LLP_PKT 0x00800000 /* force bad LLP
|
||||
packet */
|
||||
#define XB_CTRL_WIDGET_CR_MSK 0x007c0000 /* LLP widget credit
|
||||
mask */
|
||||
#define XB_CTRL_WIDGET_CR_SHFT 18 /* LLP widget credit
|
||||
shift */
|
||||
#define XB_CTRL_ILLEGAL_DST_IE 0x00020000 /* illegal destination
|
||||
*/
|
||||
#define XB_CTRL_OALLOC_IBUF_IE 0x00010000 /* overallocated input
|
||||
buffer */
|
||||
/* reserved: 0x0000fe00 */
|
||||
#define XB_CTRL_BNDWDTH_ALLOC_IE 0x00000100 /* bandwidth alloc */
|
||||
#define XB_CTRL_RCV_CNT_OFLOW_IE 0x00000080 /* rcv retry overflow */
|
||||
#define XB_CTRL_XMT_CNT_OFLOW_IE 0x00000040 /* xmt retry overflow */
|
||||
#define XB_CTRL_XMT_MAX_RTRY_IE 0x00000020 /* max transmit retry */
|
||||
#define XB_CTRL_RCV_IE 0x00000010 /* receive */
|
||||
#define XB_CTRL_XMT_RTRY_IE 0x00000008 /* transmit retry */
|
||||
/* reserved: 0x00000004 */
|
||||
#define XB_CTRL_MAXREQ_TOUT_IE 0x00000002 /* maximum request timeout */
|
||||
/* reserved: 0x00000004 */
|
||||
#define XB_CTRL_MAXREQ_TOUT_IE 0x00000002 /* maximum request
|
||||
timeout */
|
||||
#define XB_CTRL_SRC_TOUT_IE 0x00000001 /* source timeout */
|
||||
|
||||
/* link_status(x) */
|
||||
#define XB_STAT_LINKALIVE XB_CTRL_LINKALIVE_IE
|
||||
/* reserved: 0x7ff80000 */
|
||||
/* reserved: 0x7ff80000 */
|
||||
#define XB_STAT_MULTI_ERR 0x00040000 /* multi error */
|
||||
#define XB_STAT_ILLEGAL_DST_ERR XB_CTRL_ILLEGAL_DST_IE
|
||||
#define XB_STAT_OALLOC_IBUF_ERR XB_CTRL_OALLOC_IBUF_IE
|
||||
|
@ -211,7 +220,7 @@ typedef volatile struct xbow_s {
|
|||
#define XB_STAT_XMT_MAX_RTRY_ERR XB_CTRL_XMT_MAX_RTRY_IE
|
||||
#define XB_STAT_RCV_ERR XB_CTRL_RCV_IE
|
||||
#define XB_STAT_XMT_RTRY_ERR XB_CTRL_XMT_RTRY_IE
|
||||
/* reserved: 0x00000004 */
|
||||
/* reserved: 0x00000004 */
|
||||
#define XB_STAT_MAXREQ_TOUT_ERR XB_CTRL_MAXREQ_TOUT_IE
|
||||
#define XB_STAT_SRC_TOUT_ERR XB_CTRL_SRC_TOUT_IE
|
||||
|
||||
|
@ -222,7 +231,7 @@ typedef volatile struct xbow_s {
|
|||
#define XB_AUX_LINKFAIL_RST_BAD 0x00000040
|
||||
#define XB_AUX_STAT_PRESENT 0x00000020
|
||||
#define XB_AUX_STAT_PORT_WIDTH 0x00000010
|
||||
/* reserved: 0x0000000f */
|
||||
/* reserved: 0x0000000f */
|
||||
|
||||
/*
|
||||
* link_arb_upper/link_arb_lower(x), (reg) should be the link_arb_upper
|
||||
|
@ -238,7 +247,8 @@ typedef volatile struct xbow_s {
|
|||
/* XBOW_WID_STAT */
|
||||
#define XB_WID_STAT_LINK_INTR_SHFT (24)
|
||||
#define XB_WID_STAT_LINK_INTR_MASK (0xFF << XB_WID_STAT_LINK_INTR_SHFT)
|
||||
#define XB_WID_STAT_LINK_INTR(x) (0x1 << (((x)&7) + XB_WID_STAT_LINK_INTR_SHFT))
|
||||
#define XB_WID_STAT_LINK_INTR(x) \
|
||||
(0x1 << (((x)&7) + XB_WID_STAT_LINK_INTR_SHFT))
|
||||
#define XB_WID_STAT_WIDGET0_INTR 0x00800000
|
||||
#define XB_WID_STAT_SRCID_MASK 0x000003c0 /* Xbridge only */
|
||||
#define XB_WID_STAT_REG_ACC_ERR 0x00000020
|
||||
|
@ -264,7 +274,7 @@ typedef volatile struct xbow_s {
|
|||
#define XXBOW_WIDGET_PART_NUM 0xd000 /* Xbridge */
|
||||
#define XBOW_WIDGET_MFGR_NUM 0x0
|
||||
#define XXBOW_WIDGET_MFGR_NUM 0x0
|
||||
#define PXBOW_WIDGET_PART_NUM 0xd100 /* PIC */
|
||||
#define PXBOW_WIDGET_PART_NUM 0xd100 /* PIC */
|
||||
|
||||
#define XBOW_REV_1_0 0x1 /* xbow rev 1.0 is "1" */
|
||||
#define XBOW_REV_1_1 0x2 /* xbow rev 1.1 is "2" */
|
||||
|
@ -279,13 +289,13 @@ typedef volatile struct xbow_s {
|
|||
#define XBOW_WID_ARB_RELOAD_INT 0x3f /* GBR reload interval */
|
||||
|
||||
#define IS_XBRIDGE_XBOW(wid) \
|
||||
(XWIDGET_PART_NUM(wid) == XXBOW_WIDGET_PART_NUM && \
|
||||
XWIDGET_MFG_NUM(wid) == XXBOW_WIDGET_MFGR_NUM)
|
||||
(XWIDGET_PART_NUM(wid) == XXBOW_WIDGET_PART_NUM && \
|
||||
XWIDGET_MFG_NUM(wid) == XXBOW_WIDGET_MFGR_NUM)
|
||||
|
||||
#define IS_PIC_XBOW(wid) \
|
||||
(XWIDGET_PART_NUM(wid) == PXBOW_WIDGET_PART_NUM && \
|
||||
XWIDGET_MFG_NUM(wid) == XXBOW_WIDGET_MFGR_NUM)
|
||||
(XWIDGET_PART_NUM(wid) == PXBOW_WIDGET_PART_NUM && \
|
||||
XWIDGET_MFG_NUM(wid) == XXBOW_WIDGET_MFGR_NUM)
|
||||
|
||||
#define XBOW_WAR_ENABLED(pv, widid) ((1 << XWIDGET_REV_NUM(widid)) & pv)
|
||||
|
||||
#endif /* _ASM_IA64_SN_XTALK_XBOW_H */
|
||||
#endif /* _ASM_IA64_SN_XTALK_XBOW_H */
|
||||
|
|
|
@ -25,28 +25,28 @@
|
|||
|
||||
/* widget configuration registers */
|
||||
struct widget_cfg{
|
||||
uint32_t w_id; /* 0x04 */
|
||||
uint32_t w_pad_0; /* 0x00 */
|
||||
uint32_t w_status; /* 0x0c */
|
||||
uint32_t w_pad_1; /* 0x08 */
|
||||
uint32_t w_err_upper_addr; /* 0x14 */
|
||||
uint32_t w_pad_2; /* 0x10 */
|
||||
uint32_t w_err_lower_addr; /* 0x1c */
|
||||
uint32_t w_pad_3; /* 0x18 */
|
||||
uint32_t w_control; /* 0x24 */
|
||||
uint32_t w_pad_4; /* 0x20 */
|
||||
uint32_t w_req_timeout; /* 0x2c */
|
||||
uint32_t w_pad_5; /* 0x28 */
|
||||
uint32_t w_intdest_upper_addr; /* 0x34 */
|
||||
uint32_t w_pad_6; /* 0x30 */
|
||||
uint32_t w_intdest_lower_addr; /* 0x3c */
|
||||
uint32_t w_pad_7; /* 0x38 */
|
||||
uint32_t w_err_cmd_word; /* 0x44 */
|
||||
uint32_t w_pad_8; /* 0x40 */
|
||||
uint32_t w_llp_cfg; /* 0x4c */
|
||||
uint32_t w_pad_9; /* 0x48 */
|
||||
uint32_t w_tflush; /* 0x54 */
|
||||
uint32_t w_pad_10; /* 0x50 */
|
||||
u32 w_id; /* 0x04 */
|
||||
u32 w_pad_0; /* 0x00 */
|
||||
u32 w_status; /* 0x0c */
|
||||
u32 w_pad_1; /* 0x08 */
|
||||
u32 w_err_upper_addr; /* 0x14 */
|
||||
u32 w_pad_2; /* 0x10 */
|
||||
u32 w_err_lower_addr; /* 0x1c */
|
||||
u32 w_pad_3; /* 0x18 */
|
||||
u32 w_control; /* 0x24 */
|
||||
u32 w_pad_4; /* 0x20 */
|
||||
u32 w_req_timeout; /* 0x2c */
|
||||
u32 w_pad_5; /* 0x28 */
|
||||
u32 w_intdest_upper_addr; /* 0x34 */
|
||||
u32 w_pad_6; /* 0x30 */
|
||||
u32 w_intdest_lower_addr; /* 0x3c */
|
||||
u32 w_pad_7; /* 0x38 */
|
||||
u32 w_err_cmd_word; /* 0x44 */
|
||||
u32 w_pad_8; /* 0x40 */
|
||||
u32 w_llp_cfg; /* 0x4c */
|
||||
u32 w_pad_9; /* 0x48 */
|
||||
u32 w_tflush; /* 0x54 */
|
||||
u32 w_pad_10; /* 0x50 */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -63,7 +63,7 @@ struct xwidget_info{
|
|||
struct xwidget_hwid xwi_hwid; /* Widget Identification */
|
||||
char xwi_masterxid; /* Hub's Widget Port Number */
|
||||
void *xwi_hubinfo; /* Hub's provider private info */
|
||||
uint64_t *xwi_hub_provider; /* prom provider functions */
|
||||
u64 *xwi_hub_provider; /* prom provider functions */
|
||||
void *xwi_vertex;
|
||||
};
|
||||
|
||||
|
|
|
@ -132,8 +132,8 @@ static inline u64 sal_get_pcibus_info(u64 segment, u64 busnum, u64 address)
|
|||
* Retrieve the pci device information given the bus and device|function number.
|
||||
*/
|
||||
static inline u64
|
||||
sal_get_pcidev_info(u64 segment, u64 bus_number, u64 devfn, u64 pci_dev,
|
||||
u64 sn_irq_info)
|
||||
sal_get_pcidev_info(u64 segment, u64 bus_number, u64 devfn, u64 pci_dev,
|
||||
u64 sn_irq_info)
|
||||
{
|
||||
struct ia64_sal_retval ret_stuff;
|
||||
ret_stuff.status = 0;
|
||||
|
@ -141,7 +141,7 @@ sal_get_pcidev_info(u64 segment, u64 bus_number, u64 devfn, u64 pci_dev,
|
|||
|
||||
SAL_CALL_NOLOCK(ret_stuff,
|
||||
(u64) SN_SAL_IOIF_GET_PCIDEV_INFO,
|
||||
(u64) segment, (u64) bus_number, (u64) devfn,
|
||||
(u64) segment, (u64) bus_number, (u64) devfn,
|
||||
(u64) pci_dev,
|
||||
sn_irq_info, 0, 0);
|
||||
return ret_stuff.v0;
|
||||
|
@ -268,7 +268,7 @@ static void sn_fixup_ionodes(void)
|
|||
*/
|
||||
static void
|
||||
sn_pci_window_fixup(struct pci_dev *dev, unsigned int count,
|
||||
int64_t * pci_addrs)
|
||||
s64 * pci_addrs)
|
||||
{
|
||||
struct pci_controller *controller = PCI_CONTROLLER(dev->bus);
|
||||
unsigned int i;
|
||||
|
@ -328,7 +328,7 @@ void sn_pci_fixup_slot(struct pci_dev *dev)
|
|||
struct pci_bus *host_pci_bus;
|
||||
struct pci_dev *host_pci_dev;
|
||||
struct pcidev_info *pcidev_info;
|
||||
int64_t pci_addrs[PCI_ROM_RESOURCE + 1];
|
||||
s64 pci_addrs[PCI_ROM_RESOURCE + 1];
|
||||
struct sn_irq_info *sn_irq_info;
|
||||
unsigned long size;
|
||||
unsigned int bus_no, devfn;
|
||||
|
|
|
@ -28,7 +28,7 @@ extern int sn_ioif_inited;
|
|||
static struct list_head **sn_irq_lh;
|
||||
static spinlock_t sn_irq_info_lock = SPIN_LOCK_UNLOCKED; /* non-IRQ lock */
|
||||
|
||||
static inline uint64_t sn_intr_alloc(nasid_t local_nasid, int local_widget,
|
||||
static inline u64 sn_intr_alloc(nasid_t local_nasid, int local_widget,
|
||||
u64 sn_irq_info,
|
||||
int req_irq, nasid_t req_nasid,
|
||||
int req_slice)
|
||||
|
@ -123,7 +123,7 @@ static void sn_set_affinity_irq(unsigned int irq, cpumask_t mask)
|
|||
|
||||
list_for_each_entry_safe(sn_irq_info, sn_irq_info_safe,
|
||||
sn_irq_lh[irq], list) {
|
||||
uint64_t bridge;
|
||||
u64 bridge;
|
||||
int local_widget, status;
|
||||
nasid_t local_nasid;
|
||||
struct sn_irq_info *new_irq_info;
|
||||
|
@ -134,7 +134,7 @@ static void sn_set_affinity_irq(unsigned int irq, cpumask_t mask)
|
|||
break;
|
||||
memcpy(new_irq_info, sn_irq_info, sizeof(struct sn_irq_info));
|
||||
|
||||
bridge = (uint64_t) new_irq_info->irq_bridge;
|
||||
bridge = (u64) new_irq_info->irq_bridge;
|
||||
if (!bridge) {
|
||||
kfree(new_irq_info);
|
||||
break; /* irq is not a device interrupt */
|
||||
|
@ -349,10 +349,10 @@ static void force_interrupt(int irq)
|
|||
*/
|
||||
static void sn_check_intr(int irq, struct sn_irq_info *sn_irq_info)
|
||||
{
|
||||
uint64_t regval;
|
||||
u64 regval;
|
||||
int irr_reg_num;
|
||||
int irr_bit;
|
||||
uint64_t irr_reg;
|
||||
u64 irr_reg;
|
||||
struct pcidev_info *pcidev_info;
|
||||
struct pcibus_info *pcibus_info;
|
||||
|
||||
|
|
|
@ -245,7 +245,7 @@ static int cx_device_reload(struct cx_dev *cx_dev)
|
|||
cx_dev->bt);
|
||||
}
|
||||
|
||||
static inline uint64_t tiocx_intr_alloc(nasid_t nasid, int widget,
|
||||
static inline u64 tiocx_intr_alloc(nasid_t nasid, int widget,
|
||||
u64 sn_irq_info,
|
||||
int req_irq, nasid_t req_nasid,
|
||||
int req_slice)
|
||||
|
@ -302,7 +302,7 @@ struct sn_irq_info *tiocx_irq_alloc(nasid_t nasid, int widget, int irq,
|
|||
|
||||
void tiocx_irq_free(struct sn_irq_info *sn_irq_info)
|
||||
{
|
||||
uint64_t bridge = (uint64_t) sn_irq_info->irq_bridge;
|
||||
u64 bridge = (u64) sn_irq_info->irq_bridge;
|
||||
nasid_t nasid = NASID_GET(bridge);
|
||||
int widget;
|
||||
|
||||
|
@ -313,12 +313,12 @@ void tiocx_irq_free(struct sn_irq_info *sn_irq_info)
|
|||
}
|
||||
}
|
||||
|
||||
uint64_t tiocx_dma_addr(uint64_t addr)
|
||||
u64 tiocx_dma_addr(u64 addr)
|
||||
{
|
||||
return PHYS_TO_TIODMA(addr);
|
||||
}
|
||||
|
||||
uint64_t tiocx_swin_base(int nasid)
|
||||
u64 tiocx_swin_base(int nasid)
|
||||
{
|
||||
return TIO_SWIN_BASE(nasid, TIOCX_CORELET);
|
||||
}
|
||||
|
@ -335,8 +335,8 @@ EXPORT_SYMBOL(tiocx_swin_base);
|
|||
|
||||
static void tio_conveyor_set(nasid_t nasid, int enable_flag)
|
||||
{
|
||||
uint64_t ice_frz;
|
||||
uint64_t disable_cb = (1ull << 61);
|
||||
u64 ice_frz;
|
||||
u64 disable_cb = (1ull << 61);
|
||||
|
||||
if (!(nasid & 1))
|
||||
return;
|
||||
|
@ -388,7 +388,7 @@ static int is_fpga_tio(int nasid, int *bt)
|
|||
|
||||
static int bitstream_loaded(nasid_t nasid)
|
||||
{
|
||||
uint64_t cx_credits;
|
||||
u64 cx_credits;
|
||||
|
||||
cx_credits = REMOTE_HUB_L(nasid, TIO_ICE_PMI_TX_DYN_CREDIT_STAT_CB3);
|
||||
cx_credits &= TIO_ICE_PMI_TX_DYN_CREDIT_STAT_CB3_CREDIT_CNT_MASK;
|
||||
|
@ -404,14 +404,14 @@ static int tiocx_reload(struct cx_dev *cx_dev)
|
|||
nasid_t nasid = cx_dev->cx_id.nasid;
|
||||
|
||||
if (bitstream_loaded(nasid)) {
|
||||
uint64_t cx_id;
|
||||
u64 cx_id;
|
||||
int rv;
|
||||
|
||||
rv = ia64_sn_sysctl_tio_clock_reset(nasid);
|
||||
if (rv) {
|
||||
printk(KERN_ALERT "CX port JTAG reset failed.\n");
|
||||
} else {
|
||||
cx_id = *(volatile uint64_t *)
|
||||
cx_id = *(volatile u64 *)
|
||||
(TIO_SWIN_BASE(nasid, TIOCX_CORELET) +
|
||||
WIDGET_ID);
|
||||
part_num = XWIDGET_PART_NUM(cx_id);
|
||||
|
|
|
@ -18,10 +18,10 @@ int pcibr_invalidate_ate = 0; /* by default don't invalidate ATE on free */
|
|||
* mark_ate: Mark the ate as either free or inuse.
|
||||
*/
|
||||
static void mark_ate(struct ate_resource *ate_resource, int start, int number,
|
||||
uint64_t value)
|
||||
u64 value)
|
||||
{
|
||||
|
||||
uint64_t *ate = ate_resource->ate;
|
||||
u64 *ate = ate_resource->ate;
|
||||
int index;
|
||||
int length = 0;
|
||||
|
||||
|
@ -38,7 +38,7 @@ static int find_free_ate(struct ate_resource *ate_resource, int start,
|
|||
int count)
|
||||
{
|
||||
|
||||
uint64_t *ate = ate_resource->ate;
|
||||
u64 *ate = ate_resource->ate;
|
||||
int index;
|
||||
int start_free;
|
||||
|
||||
|
@ -119,7 +119,7 @@ static inline int alloc_ate_resource(struct ate_resource *ate_resource,
|
|||
int pcibr_ate_alloc(struct pcibus_info *pcibus_info, int count)
|
||||
{
|
||||
int status = 0;
|
||||
uint64_t flag;
|
||||
u64 flag;
|
||||
|
||||
flag = pcibr_lock(pcibus_info);
|
||||
status = alloc_ate_resource(&pcibus_info->pbi_int_ate_resource, count);
|
||||
|
@ -139,7 +139,7 @@ int pcibr_ate_alloc(struct pcibus_info *pcibus_info, int count)
|
|||
* Setup an Address Translation Entry as specified. Use either the Bridge
|
||||
* internal maps or the external map RAM, as appropriate.
|
||||
*/
|
||||
static inline uint64_t *pcibr_ate_addr(struct pcibus_info *pcibus_info,
|
||||
static inline u64 *pcibr_ate_addr(struct pcibus_info *pcibus_info,
|
||||
int ate_index)
|
||||
{
|
||||
if (ate_index < pcibus_info->pbi_int_ate_size) {
|
||||
|
@ -153,7 +153,7 @@ static inline uint64_t *pcibr_ate_addr(struct pcibus_info *pcibus_info,
|
|||
*/
|
||||
void inline
|
||||
ate_write(struct pcibus_info *pcibus_info, int ate_index, int count,
|
||||
volatile uint64_t ate)
|
||||
volatile u64 ate)
|
||||
{
|
||||
while (count-- > 0) {
|
||||
if (ate_index < pcibus_info->pbi_int_ate_size) {
|
||||
|
@ -171,9 +171,9 @@ ate_write(struct pcibus_info *pcibus_info, int ate_index, int count,
|
|||
void pcibr_ate_free(struct pcibus_info *pcibus_info, int index)
|
||||
{
|
||||
|
||||
volatile uint64_t ate;
|
||||
volatile u64 ate;
|
||||
int count;
|
||||
uint64_t flags;
|
||||
u64 flags;
|
||||
|
||||
if (pcibr_invalidate_ate) {
|
||||
/* For debugging purposes, clear the valid bit in the ATE */
|
||||
|
|
|
@ -41,21 +41,21 @@ extern int sn_ioif_inited;
|
|||
|
||||
static dma_addr_t
|
||||
pcibr_dmamap_ate32(struct pcidev_info *info,
|
||||
uint64_t paddr, size_t req_size, uint64_t flags)
|
||||
u64 paddr, size_t req_size, u64 flags)
|
||||
{
|
||||
|
||||
struct pcidev_info *pcidev_info = info->pdi_host_pcidev_info;
|
||||
struct pcibus_info *pcibus_info = (struct pcibus_info *)pcidev_info->
|
||||
pdi_pcibus_info;
|
||||
uint8_t internal_device = (PCI_SLOT(pcidev_info->pdi_host_pcidev_info->
|
||||
u8 internal_device = (PCI_SLOT(pcidev_info->pdi_host_pcidev_info->
|
||||
pdi_linux_pcidev->devfn)) - 1;
|
||||
int ate_count;
|
||||
int ate_index;
|
||||
uint64_t ate_flags = flags | PCI32_ATE_V;
|
||||
uint64_t ate;
|
||||
uint64_t pci_addr;
|
||||
uint64_t xio_addr;
|
||||
uint64_t offset;
|
||||
u64 ate_flags = flags | PCI32_ATE_V;
|
||||
u64 ate;
|
||||
u64 pci_addr;
|
||||
u64 xio_addr;
|
||||
u64 offset;
|
||||
|
||||
/* PIC in PCI-X mode does not supports 32bit PageMap mode */
|
||||
if (IS_PIC_SOFT(pcibus_info) && IS_PCIX(pcibus_info)) {
|
||||
|
@ -109,12 +109,12 @@ pcibr_dmamap_ate32(struct pcidev_info *info,
|
|||
}
|
||||
|
||||
static dma_addr_t
|
||||
pcibr_dmatrans_direct64(struct pcidev_info * info, uint64_t paddr,
|
||||
uint64_t dma_attributes)
|
||||
pcibr_dmatrans_direct64(struct pcidev_info * info, u64 paddr,
|
||||
u64 dma_attributes)
|
||||
{
|
||||
struct pcibus_info *pcibus_info = (struct pcibus_info *)
|
||||
((info->pdi_host_pcidev_info)->pdi_pcibus_info);
|
||||
uint64_t pci_addr;
|
||||
u64 pci_addr;
|
||||
|
||||
/* Translate to Crosstalk View of Physical Address */
|
||||
pci_addr = (IS_PIC_SOFT(pcibus_info) ? PHYS_TO_DMA(paddr) :
|
||||
|
@ -127,7 +127,7 @@ pcibr_dmatrans_direct64(struct pcidev_info * info, uint64_t paddr,
|
|||
/* Handle Bridge Chipset differences */
|
||||
if (IS_PIC_SOFT(pcibus_info)) {
|
||||
pci_addr |=
|
||||
((uint64_t) pcibus_info->
|
||||
((u64) pcibus_info->
|
||||
pbi_hub_xid << PIC_PCI64_ATTR_TARG_SHFT);
|
||||
} else
|
||||
pci_addr |= TIOCP_PCI64_CMDTYPE_MEM;
|
||||
|
@ -142,17 +142,17 @@ pcibr_dmatrans_direct64(struct pcidev_info * info, uint64_t paddr,
|
|||
|
||||
static dma_addr_t
|
||||
pcibr_dmatrans_direct32(struct pcidev_info * info,
|
||||
uint64_t paddr, size_t req_size, uint64_t flags)
|
||||
u64 paddr, size_t req_size, u64 flags)
|
||||
{
|
||||
|
||||
struct pcidev_info *pcidev_info = info->pdi_host_pcidev_info;
|
||||
struct pcibus_info *pcibus_info = (struct pcibus_info *)pcidev_info->
|
||||
pdi_pcibus_info;
|
||||
uint64_t xio_addr;
|
||||
u64 xio_addr;
|
||||
|
||||
uint64_t xio_base;
|
||||
uint64_t offset;
|
||||
uint64_t endoff;
|
||||
u64 xio_base;
|
||||
u64 offset;
|
||||
u64 endoff;
|
||||
|
||||
if (IS_PCIX(pcibus_info)) {
|
||||
return 0;
|
||||
|
@ -209,14 +209,14 @@ pcibr_dma_unmap(struct pci_dev *hwdev, dma_addr_t dma_handle, int direction)
|
|||
* unlike the PIC Device(x) Write Request Buffer Flush register.
|
||||
*/
|
||||
|
||||
void sn_dma_flush(uint64_t addr)
|
||||
void sn_dma_flush(u64 addr)
|
||||
{
|
||||
nasid_t nasid;
|
||||
int is_tio;
|
||||
int wid_num;
|
||||
int i, j;
|
||||
uint64_t flags;
|
||||
uint64_t itte;
|
||||
u64 flags;
|
||||
u64 itte;
|
||||
struct hubdev_info *hubinfo;
|
||||
volatile struct sn_flush_device_kernel *p;
|
||||
volatile struct sn_flush_device_common *common;
|
||||
|
@ -299,8 +299,8 @@ void sn_dma_flush(uint64_t addr)
|
|||
* If CE ever needs the sn_dma_flush mechanism, we will have
|
||||
* to account for that here and in tioce_bus_fixup().
|
||||
*/
|
||||
uint32_t tio_id = HUB_L(TIO_IOSPACE_ADDR(nasid, TIO_NODE_ID));
|
||||
uint32_t revnum = XWIDGET_PART_REV_NUM(tio_id);
|
||||
u32 tio_id = HUB_L(TIO_IOSPACE_ADDR(nasid, TIO_NODE_ID));
|
||||
u32 revnum = XWIDGET_PART_REV_NUM(tio_id);
|
||||
|
||||
/* TIOCP BRINGUP WAR (PV907516): Don't write buffer flush reg */
|
||||
if ((1 << XWIDGET_PART_REV_NUM_REV(revnum)) & PV907516) {
|
||||
|
@ -315,7 +315,7 @@ void sn_dma_flush(uint64_t addr)
|
|||
*common->sfdl_flush_addr = 0;
|
||||
|
||||
/* force an interrupt. */
|
||||
*(volatile uint32_t *)(common->sfdl_force_int_addr) = 1;
|
||||
*(volatile u32 *)(common->sfdl_force_int_addr) = 1;
|
||||
|
||||
/* wait for the interrupt to come back. */
|
||||
while (*(common->sfdl_flush_addr) != 0x10f)
|
||||
|
|
|
@ -23,7 +23,7 @@ int
|
|||
sal_pcibr_slot_enable(struct pcibus_info *soft, int device, void *resp)
|
||||
{
|
||||
struct ia64_sal_retval ret_stuff;
|
||||
uint64_t busnum;
|
||||
u64 busnum;
|
||||
|
||||
ret_stuff.status = 0;
|
||||
ret_stuff.v0 = 0;
|
||||
|
@ -40,7 +40,7 @@ sal_pcibr_slot_disable(struct pcibus_info *soft, int device, int action,
|
|||
void *resp)
|
||||
{
|
||||
struct ia64_sal_retval ret_stuff;
|
||||
uint64_t busnum;
|
||||
u64 busnum;
|
||||
|
||||
ret_stuff.status = 0;
|
||||
ret_stuff.v0 = 0;
|
||||
|
@ -56,7 +56,7 @@ sal_pcibr_slot_disable(struct pcibus_info *soft, int device, int action,
|
|||
static int sal_pcibr_error_interrupt(struct pcibus_info *soft)
|
||||
{
|
||||
struct ia64_sal_retval ret_stuff;
|
||||
uint64_t busnum;
|
||||
u64 busnum;
|
||||
int segment;
|
||||
ret_stuff.status = 0;
|
||||
ret_stuff.v0 = 0;
|
||||
|
@ -159,9 +159,9 @@ pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont
|
|||
/* Setup the PMU ATE map */
|
||||
soft->pbi_int_ate_resource.lowest_free_index = 0;
|
||||
soft->pbi_int_ate_resource.ate =
|
||||
kmalloc(soft->pbi_int_ate_size * sizeof(uint64_t), GFP_KERNEL);
|
||||
kmalloc(soft->pbi_int_ate_size * sizeof(u64), GFP_KERNEL);
|
||||
memset(soft->pbi_int_ate_resource.ate, 0,
|
||||
(soft->pbi_int_ate_size * sizeof(uint64_t)));
|
||||
(soft->pbi_int_ate_size * sizeof(u64)));
|
||||
|
||||
if (prom_bussoft->bs_asic_type == PCIIO_ASIC_TYPE_TIOCP) {
|
||||
/* TIO PCI Bridge: find nearest node with CPUs */
|
||||
|
@ -203,7 +203,7 @@ void pcibr_target_interrupt(struct sn_irq_info *sn_irq_info)
|
|||
struct pcidev_info *pcidev_info;
|
||||
struct pcibus_info *pcibus_info;
|
||||
int bit = sn_irq_info->irq_int_bit;
|
||||
uint64_t xtalk_addr = sn_irq_info->irq_xtalkaddr;
|
||||
u64 xtalk_addr = sn_irq_info->irq_xtalkaddr;
|
||||
|
||||
pcidev_info = (struct pcidev_info *)sn_irq_info->irq_pciioinfo;
|
||||
if (pcidev_info) {
|
||||
|
|
|
@ -23,7 +23,7 @@ union br_ptr {
|
|||
/*
|
||||
* Control Register Access -- Read/Write 0000_0020
|
||||
*/
|
||||
void pcireg_control_bit_clr(struct pcibus_info *pcibus_info, uint64_t bits)
|
||||
void pcireg_control_bit_clr(struct pcibus_info *pcibus_info, u64 bits)
|
||||
{
|
||||
union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
|
||||
|
||||
|
@ -43,7 +43,7 @@ void pcireg_control_bit_clr(struct pcibus_info *pcibus_info, uint64_t bits)
|
|||
}
|
||||
}
|
||||
|
||||
void pcireg_control_bit_set(struct pcibus_info *pcibus_info, uint64_t bits)
|
||||
void pcireg_control_bit_set(struct pcibus_info *pcibus_info, u64 bits)
|
||||
{
|
||||
union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
|
||||
|
||||
|
@ -66,10 +66,10 @@ void pcireg_control_bit_set(struct pcibus_info *pcibus_info, uint64_t bits)
|
|||
/*
|
||||
* PCI/PCIX Target Flush Register Access -- Read Only 0000_0050
|
||||
*/
|
||||
uint64_t pcireg_tflush_get(struct pcibus_info *pcibus_info)
|
||||
u64 pcireg_tflush_get(struct pcibus_info *pcibus_info)
|
||||
{
|
||||
union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
|
||||
uint64_t ret = 0;
|
||||
u64 ret = 0;
|
||||
|
||||
if (pcibus_info) {
|
||||
switch (pcibus_info->pbi_bridge_type) {
|
||||
|
@ -96,10 +96,10 @@ uint64_t pcireg_tflush_get(struct pcibus_info *pcibus_info)
|
|||
/*
|
||||
* Interrupt Status Register Access -- Read Only 0000_0100
|
||||
*/
|
||||
uint64_t pcireg_intr_status_get(struct pcibus_info * pcibus_info)
|
||||
u64 pcireg_intr_status_get(struct pcibus_info * pcibus_info)
|
||||
{
|
||||
union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
|
||||
uint64_t ret = 0;
|
||||
u64 ret = 0;
|
||||
|
||||
if (pcibus_info) {
|
||||
switch (pcibus_info->pbi_bridge_type) {
|
||||
|
@ -121,7 +121,7 @@ uint64_t pcireg_intr_status_get(struct pcibus_info * pcibus_info)
|
|||
/*
|
||||
* Interrupt Enable Register Access -- Read/Write 0000_0108
|
||||
*/
|
||||
void pcireg_intr_enable_bit_clr(struct pcibus_info *pcibus_info, uint64_t bits)
|
||||
void pcireg_intr_enable_bit_clr(struct pcibus_info *pcibus_info, u64 bits)
|
||||
{
|
||||
union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
|
||||
|
||||
|
@ -141,7 +141,7 @@ void pcireg_intr_enable_bit_clr(struct pcibus_info *pcibus_info, uint64_t bits)
|
|||
}
|
||||
}
|
||||
|
||||
void pcireg_intr_enable_bit_set(struct pcibus_info *pcibus_info, uint64_t bits)
|
||||
void pcireg_intr_enable_bit_set(struct pcibus_info *pcibus_info, u64 bits)
|
||||
{
|
||||
union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
|
||||
|
||||
|
@ -165,7 +165,7 @@ void pcireg_intr_enable_bit_set(struct pcibus_info *pcibus_info, uint64_t bits)
|
|||
* Intr Host Address Register (int_addr) -- Read/Write 0000_0130 - 0000_0168
|
||||
*/
|
||||
void pcireg_intr_addr_addr_set(struct pcibus_info *pcibus_info, int int_n,
|
||||
uint64_t addr)
|
||||
u64 addr)
|
||||
{
|
||||
union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
|
||||
|
||||
|
@ -217,10 +217,10 @@ void pcireg_force_intr_set(struct pcibus_info *pcibus_info, int int_n)
|
|||
/*
|
||||
* Device(x) Write Buffer Flush Reg Access -- Read Only 0000_0240 - 0000_0258
|
||||
*/
|
||||
uint64_t pcireg_wrb_flush_get(struct pcibus_info *pcibus_info, int device)
|
||||
u64 pcireg_wrb_flush_get(struct pcibus_info *pcibus_info, int device)
|
||||
{
|
||||
union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
|
||||
uint64_t ret = 0;
|
||||
u64 ret = 0;
|
||||
|
||||
if (pcibus_info) {
|
||||
switch (pcibus_info->pbi_bridge_type) {
|
||||
|
@ -242,7 +242,7 @@ uint64_t pcireg_wrb_flush_get(struct pcibus_info *pcibus_info, int device)
|
|||
}
|
||||
|
||||
void pcireg_int_ate_set(struct pcibus_info *pcibus_info, int ate_index,
|
||||
uint64_t val)
|
||||
u64 val)
|
||||
{
|
||||
union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
|
||||
|
||||
|
@ -262,10 +262,10 @@ void pcireg_int_ate_set(struct pcibus_info *pcibus_info, int ate_index,
|
|||
}
|
||||
}
|
||||
|
||||
uint64_t __iomem *pcireg_int_ate_addr(struct pcibus_info *pcibus_info, int ate_index)
|
||||
u64 __iomem *pcireg_int_ate_addr(struct pcibus_info *pcibus_info, int ate_index)
|
||||
{
|
||||
union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
|
||||
uint64_t __iomem *ret = NULL;
|
||||
u64 __iomem *ret = NULL;
|
||||
|
||||
if (pcibus_info) {
|
||||
switch (pcibus_info->pbi_bridge_type) {
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#include <asm/sn/pcibus_provider_defs.h>
|
||||
#include <asm/sn/tioca_provider.h>
|
||||
|
||||
uint32_t tioca_gart_found;
|
||||
u32 tioca_gart_found;
|
||||
EXPORT_SYMBOL(tioca_gart_found); /* used by agp-sgi */
|
||||
|
||||
LIST_HEAD(tioca_list);
|
||||
|
@ -34,8 +34,8 @@ static int tioca_gart_init(struct tioca_kernel *);
|
|||
static int
|
||||
tioca_gart_init(struct tioca_kernel *tioca_kern)
|
||||
{
|
||||
uint64_t ap_reg;
|
||||
uint64_t offset;
|
||||
u64 ap_reg;
|
||||
u64 offset;
|
||||
struct page *tmp;
|
||||
struct tioca_common *tioca_common;
|
||||
struct tioca __iomem *ca_base;
|
||||
|
@ -214,7 +214,7 @@ void
|
|||
tioca_fastwrite_enable(struct tioca_kernel *tioca_kern)
|
||||
{
|
||||
int cap_ptr;
|
||||
uint32_t reg;
|
||||
u32 reg;
|
||||
struct tioca __iomem *tioca_base;
|
||||
struct pci_dev *pdev;
|
||||
struct tioca_common *common;
|
||||
|
@ -276,7 +276,7 @@ EXPORT_SYMBOL(tioca_fastwrite_enable); /* used by agp-sgi */
|
|||
* We will always use 0x1
|
||||
* 55:55 - Swap bytes Currently unused
|
||||
*/
|
||||
static uint64_t
|
||||
static u64
|
||||
tioca_dma_d64(unsigned long paddr)
|
||||
{
|
||||
dma_addr_t bus_addr;
|
||||
|
@ -318,15 +318,15 @@ tioca_dma_d64(unsigned long paddr)
|
|||
* and so a given CA can only directly target nodes in the range
|
||||
* xxx - xxx+255.
|
||||
*/
|
||||
static uint64_t
|
||||
tioca_dma_d48(struct pci_dev *pdev, uint64_t paddr)
|
||||
static u64
|
||||
tioca_dma_d48(struct pci_dev *pdev, u64 paddr)
|
||||
{
|
||||
struct tioca_common *tioca_common;
|
||||
struct tioca __iomem *ca_base;
|
||||
uint64_t ct_addr;
|
||||
u64 ct_addr;
|
||||
dma_addr_t bus_addr;
|
||||
uint32_t node_upper;
|
||||
uint64_t agp_dma_extn;
|
||||
u32 node_upper;
|
||||
u64 agp_dma_extn;
|
||||
struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(pdev);
|
||||
|
||||
tioca_common = (struct tioca_common *)pcidev_info->pdi_pcibus_info;
|
||||
|
@ -367,10 +367,10 @@ tioca_dma_d48(struct pci_dev *pdev, uint64_t paddr)
|
|||
* dma_addr_t is guarenteed to be contiguous in CA bus space.
|
||||
*/
|
||||
static dma_addr_t
|
||||
tioca_dma_mapped(struct pci_dev *pdev, uint64_t paddr, size_t req_size)
|
||||
tioca_dma_mapped(struct pci_dev *pdev, u64 paddr, size_t req_size)
|
||||
{
|
||||
int i, ps, ps_shift, entry, entries, mapsize, last_entry;
|
||||
uint64_t xio_addr, end_xio_addr;
|
||||
u64 xio_addr, end_xio_addr;
|
||||
struct tioca_common *tioca_common;
|
||||
struct tioca_kernel *tioca_kern;
|
||||
dma_addr_t bus_addr = 0;
|
||||
|
@ -514,10 +514,10 @@ tioca_dma_unmap(struct pci_dev *pdev, dma_addr_t bus_addr, int dir)
|
|||
* The mapping mode used is based on the devices dma_mask. As a last resort
|
||||
* use the GART mapped mode.
|
||||
*/
|
||||
static uint64_t
|
||||
tioca_dma_map(struct pci_dev *pdev, uint64_t paddr, size_t byte_count)
|
||||
static u64
|
||||
tioca_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count)
|
||||
{
|
||||
uint64_t mapaddr;
|
||||
u64 mapaddr;
|
||||
|
||||
/*
|
||||
* If card is 64 or 48 bit addresable, use a direct mapping. 32
|
||||
|
@ -554,8 +554,8 @@ tioca_error_intr_handler(int irq, void *arg, struct pt_regs *pt)
|
|||
{
|
||||
struct tioca_common *soft = arg;
|
||||
struct ia64_sal_retval ret_stuff;
|
||||
uint64_t segment;
|
||||
uint64_t busnum;
|
||||
u64 segment;
|
||||
u64 busnum;
|
||||
ret_stuff.status = 0;
|
||||
ret_stuff.v0 = 0;
|
||||
|
||||
|
@ -620,7 +620,7 @@ tioca_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont
|
|||
INIT_LIST_HEAD(&tioca_kern->ca_dmamaps);
|
||||
tioca_kern->ca_closest_node =
|
||||
nasid_to_cnodeid(tioca_common->ca_closest_nasid);
|
||||
tioca_common->ca_kernel_private = (uint64_t) tioca_kern;
|
||||
tioca_common->ca_kernel_private = (u64) tioca_kern;
|
||||
|
||||
bus = pci_find_bus(tioca_common->ca_common.bs_persist_segment,
|
||||
tioca_common->ca_common.bs_persist_busnum);
|
||||
|
|
|
@ -81,10 +81,10 @@
|
|||
* 61 - 0 since this is not an MSI transaction
|
||||
* 60:54 - reserved, MBZ
|
||||
*/
|
||||
static uint64_t
|
||||
static u64
|
||||
tioce_dma_d64(unsigned long ct_addr)
|
||||
{
|
||||
uint64_t bus_addr;
|
||||
u64 bus_addr;
|
||||
|
||||
bus_addr = ct_addr | (1UL << 63);
|
||||
|
||||
|
@ -141,9 +141,9 @@ pcidev_to_tioce(struct pci_dev *pdev, struct tioce **base,
|
|||
* length, and if enough resources exist, fill in the ATE's and construct a
|
||||
* tioce_dmamap struct to track the mapping.
|
||||
*/
|
||||
static uint64_t
|
||||
static u64
|
||||
tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port,
|
||||
uint64_t ct_addr, int len)
|
||||
u64 ct_addr, int len)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
|
@ -152,11 +152,11 @@ tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port,
|
|||
int entries;
|
||||
int nates;
|
||||
int pagesize;
|
||||
uint64_t *ate_shadow;
|
||||
uint64_t *ate_reg;
|
||||
uint64_t addr;
|
||||
u64 *ate_shadow;
|
||||
u64 *ate_reg;
|
||||
u64 addr;
|
||||
struct tioce *ce_mmr;
|
||||
uint64_t bus_base;
|
||||
u64 bus_base;
|
||||
struct tioce_dmamap *map;
|
||||
|
||||
ce_mmr = (struct tioce *)ce_kern->ce_common->ce_pcibus.bs_base;
|
||||
|
@ -224,7 +224,7 @@ tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port,
|
|||
|
||||
addr = ct_addr;
|
||||
for (j = 0; j < nates; j++) {
|
||||
uint64_t ate;
|
||||
u64 ate;
|
||||
|
||||
ate = ATE_MAKE(addr, pagesize);
|
||||
ate_shadow[i + j] = ate;
|
||||
|
@ -252,15 +252,15 @@ tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port,
|
|||
*
|
||||
* Map @paddr into 32-bit bus space of the CE associated with @pcidev_info.
|
||||
*/
|
||||
static uint64_t
|
||||
tioce_dma_d32(struct pci_dev *pdev, uint64_t ct_addr)
|
||||
static u64
|
||||
tioce_dma_d32(struct pci_dev *pdev, u64 ct_addr)
|
||||
{
|
||||
int dma_ok;
|
||||
int port;
|
||||
struct tioce *ce_mmr;
|
||||
struct tioce_kernel *ce_kern;
|
||||
uint64_t ct_upper;
|
||||
uint64_t ct_lower;
|
||||
u64 ct_upper;
|
||||
u64 ct_lower;
|
||||
dma_addr_t bus_addr;
|
||||
|
||||
ct_upper = ct_addr & ~0x3fffffffUL;
|
||||
|
@ -269,7 +269,7 @@ tioce_dma_d32(struct pci_dev *pdev, uint64_t ct_addr)
|
|||
pcidev_to_tioce(pdev, &ce_mmr, &ce_kern, &port);
|
||||
|
||||
if (ce_kern->ce_port[port].dirmap_refcnt == 0) {
|
||||
uint64_t tmp;
|
||||
u64 tmp;
|
||||
|
||||
ce_kern->ce_port[port].dirmap_shadow = ct_upper;
|
||||
writeq(ct_upper, &ce_mmr->ce_ure_dir_map[port]);
|
||||
|
@ -295,10 +295,10 @@ tioce_dma_d32(struct pci_dev *pdev, uint64_t ct_addr)
|
|||
* Given a TIOCE bus address, set the appropriate bit to indicate barrier
|
||||
* attributes.
|
||||
*/
|
||||
static uint64_t
|
||||
tioce_dma_barrier(uint64_t bus_addr, int on)
|
||||
static u64
|
||||
tioce_dma_barrier(u64 bus_addr, int on)
|
||||
{
|
||||
uint64_t barrier_bit;
|
||||
u64 barrier_bit;
|
||||
|
||||
/* barrier not supported in M40/M40S mode */
|
||||
if (TIOCE_M40_ADDR(bus_addr) || TIOCE_M40S_ADDR(bus_addr))
|
||||
|
@ -351,7 +351,7 @@ tioce_dma_unmap(struct pci_dev *pdev, dma_addr_t bus_addr, int dir)
|
|||
|
||||
list_for_each_entry(map, &ce_kern->ce_dmamap_list,
|
||||
ce_dmamap_list) {
|
||||
uint64_t last;
|
||||
u64 last;
|
||||
|
||||
last = map->pci_start + map->nbytes - 1;
|
||||
if (bus_addr >= map->pci_start && bus_addr <= last)
|
||||
|
@ -385,17 +385,17 @@ tioce_dma_unmap(struct pci_dev *pdev, dma_addr_t bus_addr, int dir)
|
|||
* This is the main wrapper for mapping host physical pages to CE PCI space.
|
||||
* The mapping mode used is based on the device's dma_mask.
|
||||
*/
|
||||
static uint64_t
|
||||
tioce_do_dma_map(struct pci_dev *pdev, uint64_t paddr, size_t byte_count,
|
||||
static u64
|
||||
tioce_do_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count,
|
||||
int barrier)
|
||||
{
|
||||
unsigned long flags;
|
||||
uint64_t ct_addr;
|
||||
uint64_t mapaddr = 0;
|
||||
u64 ct_addr;
|
||||
u64 mapaddr = 0;
|
||||
struct tioce_kernel *ce_kern;
|
||||
struct tioce_dmamap *map;
|
||||
int port;
|
||||
uint64_t dma_mask;
|
||||
u64 dma_mask;
|
||||
|
||||
dma_mask = (barrier) ? pdev->dev.coherent_dma_mask : pdev->dma_mask;
|
||||
|
||||
|
@ -425,7 +425,7 @@ tioce_do_dma_map(struct pci_dev *pdev, uint64_t paddr, size_t byte_count,
|
|||
* address bits than this device can support.
|
||||
*/
|
||||
list_for_each_entry(map, &ce_kern->ce_dmamap_list, ce_dmamap_list) {
|
||||
uint64_t last;
|
||||
u64 last;
|
||||
|
||||
last = map->ct_start + map->nbytes - 1;
|
||||
if (ct_addr >= map->ct_start &&
|
||||
|
@ -501,8 +501,8 @@ tioce_do_dma_map(struct pci_dev *pdev, uint64_t paddr, size_t byte_count,
|
|||
* Simply call tioce_do_dma_map() to create a map with the barrier bit clear
|
||||
* in the address.
|
||||
*/
|
||||
static uint64_t
|
||||
tioce_dma(struct pci_dev *pdev, uint64_t paddr, size_t byte_count)
|
||||
static u64
|
||||
tioce_dma(struct pci_dev *pdev, u64 paddr, size_t byte_count)
|
||||
{
|
||||
return tioce_do_dma_map(pdev, paddr, byte_count, 0);
|
||||
}
|
||||
|
@ -515,8 +515,8 @@ tioce_dma(struct pci_dev *pdev, uint64_t paddr, size_t byte_count)
|
|||
*
|
||||
* Simply call tioce_do_dma_map() to create a map with the barrier bit set
|
||||
* in the address.
|
||||
*/ static uint64_t
|
||||
tioce_dma_consistent(struct pci_dev *pdev, uint64_t paddr, size_t byte_count)
|
||||
*/ static u64
|
||||
tioce_dma_consistent(struct pci_dev *pdev, u64 paddr, size_t byte_count)
|
||||
{
|
||||
return tioce_do_dma_map(pdev, paddr, byte_count, 1);
|
||||
}
|
||||
|
@ -551,7 +551,7 @@ tioce_error_intr_handler(int irq, void *arg, struct pt_regs *pt)
|
|||
tioce_kern_init(struct tioce_common *tioce_common)
|
||||
{
|
||||
int i;
|
||||
uint32_t tmp;
|
||||
u32 tmp;
|
||||
struct tioce *tioce_mmr;
|
||||
struct tioce_kernel *tioce_kern;
|
||||
|
||||
|
@ -563,7 +563,7 @@ tioce_kern_init(struct tioce_common *tioce_common)
|
|||
tioce_kern->ce_common = tioce_common;
|
||||
spin_lock_init(&tioce_kern->ce_lock);
|
||||
INIT_LIST_HEAD(&tioce_kern->ce_dmamap_list);
|
||||
tioce_common->ce_kernel_private = (uint64_t) tioce_kern;
|
||||
tioce_common->ce_kernel_private = (u64) tioce_kern;
|
||||
|
||||
/*
|
||||
* Determine the secondary bus number of the port2 logical PPB.
|
||||
|
@ -575,7 +575,7 @@ tioce_kern_init(struct tioce_common *tioce_common)
|
|||
raw_pci_ops->read(tioce_common->ce_pcibus.bs_persist_segment,
|
||||
tioce_common->ce_pcibus.bs_persist_busnum,
|
||||
PCI_DEVFN(2, 0), PCI_SECONDARY_BUS, 1, &tmp);
|
||||
tioce_kern->ce_port1_secondary = (uint8_t) tmp;
|
||||
tioce_kern->ce_port1_secondary = (u8) tmp;
|
||||
|
||||
/*
|
||||
* Set PMU pagesize to the largest size available, and zero out
|
||||
|
@ -615,7 +615,7 @@ tioce_force_interrupt(struct sn_irq_info *sn_irq_info)
|
|||
struct pcidev_info *pcidev_info;
|
||||
struct tioce_common *ce_common;
|
||||
struct tioce *ce_mmr;
|
||||
uint64_t force_int_val;
|
||||
u64 force_int_val;
|
||||
|
||||
if (!sn_irq_info->irq_bridge)
|
||||
return;
|
||||
|
@ -687,7 +687,7 @@ tioce_target_interrupt(struct sn_irq_info *sn_irq_info)
|
|||
struct tioce_common *ce_common;
|
||||
struct tioce *ce_mmr;
|
||||
int bit;
|
||||
uint64_t vector;
|
||||
u64 vector;
|
||||
|
||||
pcidev_info = (struct pcidev_info *)sn_irq_info->irq_pciioinfo;
|
||||
if (!pcidev_info)
|
||||
|
@ -699,7 +699,7 @@ tioce_target_interrupt(struct sn_irq_info *sn_irq_info)
|
|||
bit = sn_irq_info->irq_int_bit;
|
||||
|
||||
__sn_setq_relaxed(&ce_mmr->ce_adm_int_mask, (1UL << bit));
|
||||
vector = (uint64_t)sn_irq_info->irq_irq << INTR_VECTOR_SHFT;
|
||||
vector = (u64)sn_irq_info->irq_irq << INTR_VECTOR_SHFT;
|
||||
vector |= sn_irq_info->irq_xtalkaddr;
|
||||
writeq(vector, &ce_mmr->ce_adm_int_dest[bit]);
|
||||
__sn_clrq_relaxed(&ce_mmr->ce_adm_int_mask, (1UL << bit));
|
||||
|
|
|
@ -12,6 +12,9 @@
|
|||
#include <linux/reboot.h>
|
||||
#include <asm/reboot.h>
|
||||
|
||||
void (*pm_power_off)(void);
|
||||
EXPORT_SYMBOL(pm_power_off);
|
||||
|
||||
/*
|
||||
* Urgs ... Too many MIPS machines to handle this in a generic way.
|
||||
* So handle all using function pointers to machine specific
|
||||
|
@ -33,6 +36,9 @@ void machine_halt(void)
|
|||
|
||||
void machine_power_off(void)
|
||||
{
|
||||
if (pm_power_off)
|
||||
pm_power_off();
|
||||
|
||||
_machine_power_off();
|
||||
}
|
||||
|
||||
|
|
581
arch/sh/Kconfig
581
arch/sh/Kconfig
|
@ -33,9 +33,11 @@ config GENERIC_CALIBRATE_DELAY
|
|||
bool
|
||||
default y
|
||||
|
||||
config GENERIC_IOMAP
|
||||
bool
|
||||
|
||||
config ARCH_MAY_HAVE_PC_FDC
|
||||
bool
|
||||
default y
|
||||
|
||||
source "init/Kconfig"
|
||||
|
||||
|
@ -53,24 +55,28 @@ config SH_SOLUTION_ENGINE
|
|||
|
||||
config SH_7751_SOLUTION_ENGINE
|
||||
bool "SolutionEngine7751"
|
||||
select CPU_SUBTYPE_SH7751
|
||||
help
|
||||
Select 7751 SolutionEngine if configuring for a Hitachi SH7751
|
||||
evaluation board.
|
||||
|
||||
config SH_7300_SOLUTION_ENGINE
|
||||
bool "SolutionEngine7300"
|
||||
select CPU_SUBTYPE_SH7300
|
||||
help
|
||||
Select 7300 SolutionEngine if configuring for a Hitachi SH7300(SH-Mobile V)
|
||||
evaluation board.
|
||||
|
||||
config SH_73180_SOLUTION_ENGINE
|
||||
bool "SolutionEngine73180"
|
||||
select CPU_SUBTYPE_SH73180
|
||||
help
|
||||
Select 73180 SolutionEngine if configuring for a Hitachi SH73180(SH-Mobile 3)
|
||||
evaluation board.
|
||||
|
||||
config SH_7751_SYSTEMH
|
||||
bool "SystemH7751R"
|
||||
select CPU_SUBTYPE_SH7751R
|
||||
help
|
||||
Select SystemH if you are configuring for a Renesas SystemH
|
||||
7751R evaluation board.
|
||||
|
@ -81,27 +87,13 @@ config SH_STB1_HARP
|
|||
config SH_STB1_OVERDRIVE
|
||||
bool "STB1_Overdrive"
|
||||
|
||||
config SH_HP620
|
||||
bool "HP620"
|
||||
config SH_HP6XX
|
||||
bool "HP6XX"
|
||||
help
|
||||
Select HP620 if configuring for a HP jornada HP620.
|
||||
Select HP6XX if configuring for a HP jornada HP6xx.
|
||||
More information (hardware only) at
|
||||
<http://www.hp.com/jornada/>.
|
||||
|
||||
config SH_HP680
|
||||
bool "HP680"
|
||||
help
|
||||
Select HP680 if configuring for a HP Jornada HP680.
|
||||
More information (hardware only) at
|
||||
<http://www.hp.com/jornada/products/680/>.
|
||||
|
||||
config SH_HP690
|
||||
bool "HP690"
|
||||
help
|
||||
Select HP690 if configuring for a HP Jornada HP690.
|
||||
More information (hardware only)
|
||||
at <http://www.hp.com/jornada/products/680/>.
|
||||
|
||||
config SH_CQREEK
|
||||
bool "CqREEK"
|
||||
help
|
||||
|
@ -123,11 +115,13 @@ config SH_EC3104
|
|||
|
||||
config SH_SATURN
|
||||
bool "Saturn"
|
||||
select CPU_SUBTYPE_SH7604
|
||||
help
|
||||
Select Saturn if configuring for a SEGA Saturn.
|
||||
|
||||
config SH_DREAMCAST
|
||||
bool "Dreamcast"
|
||||
select CPU_SUBTYPE_SH7091
|
||||
help
|
||||
Select Dreamcast if configuring for a SEGA Dreamcast.
|
||||
More information at
|
||||
|
@ -142,6 +136,7 @@ config SH_BIGSUR
|
|||
|
||||
config SH_SH2000
|
||||
bool "SH2000"
|
||||
select CPU_SUBTYPE_SH7709
|
||||
help
|
||||
SH-2000 is a single-board computer based around SH7709A chip
|
||||
intended for embedded applications.
|
||||
|
@ -153,20 +148,22 @@ config SH_ADX
|
|||
bool "ADX"
|
||||
|
||||
config SH_MPC1211
|
||||
bool "MPC1211"
|
||||
bool "Interface MPC1211"
|
||||
help
|
||||
CTP/PCI-SH02 is a CPU module computer that is produced
|
||||
by Interface Corporation.
|
||||
More information at <http://www.interface.co.jp>
|
||||
|
||||
config SH_SH03
|
||||
bool "SH03"
|
||||
bool "Interface CTP/PCI-SH03"
|
||||
help
|
||||
CTP/PCI-SH03 is a CPU module computer that produced
|
||||
CTP/PCI-SH03 is a CPU module computer that is produced
|
||||
by Interface Corporation.
|
||||
It is compact and excellent in durability.
|
||||
It will play an active part in your factory or laboratory
|
||||
as a FA computer.
|
||||
More information at <http://www.interface.co.jp>
|
||||
|
||||
config SH_SECUREEDGE5410
|
||||
bool "SecureEdge5410"
|
||||
select CPU_SUBTYPE_SH7751R
|
||||
help
|
||||
Select SecureEdge5410 if configuring for a SnapGear SH board.
|
||||
This includes both the OEM SecureEdge products as well as the
|
||||
|
@ -174,25 +171,49 @@ config SH_SECUREEDGE5410
|
|||
|
||||
config SH_HS7751RVOIP
|
||||
bool "HS7751RVOIP"
|
||||
select CPU_SUBTYPE_SH7751R
|
||||
help
|
||||
Select HS7751RVOIP if configuring for a Renesas Technology
|
||||
Sales VoIP board.
|
||||
|
||||
config SH_RTS7751R2D
|
||||
bool "RTS7751R2D"
|
||||
select CPU_SUBTYPE_SH7751R
|
||||
help
|
||||
Select RTS7751R2D if configuring for a Renesas Technology
|
||||
Sales SH-Graphics board.
|
||||
|
||||
config SH_R7780RP
|
||||
bool "R7780RP-1"
|
||||
select CPU_SUBTYPE_SH7780
|
||||
help
|
||||
Select R7780RP-1 if configuring for a Renesas Solutions
|
||||
HIGHLANDER board.
|
||||
|
||||
config SH_EDOSK7705
|
||||
bool "EDOSK7705"
|
||||
select CPU_SUBTYPE_SH7705
|
||||
|
||||
config SH_SH4202_MICRODEV
|
||||
bool "SH4-202 MicroDev"
|
||||
select CPU_SUBTYPE_SH4_202
|
||||
help
|
||||
Select SH4-202 MicroDev if configuring for a SuperH MicroDev board
|
||||
with an SH4-202 CPU.
|
||||
|
||||
config SH_LANDISK
|
||||
bool "LANDISK"
|
||||
select CPU_SUBTYPE_SH7751R
|
||||
help
|
||||
I-O DATA DEVICE, INC. "LANDISK Series" support.
|
||||
|
||||
config SH_TITAN
|
||||
bool "TITAN"
|
||||
select CPU_SUBTYPE_SH7751R
|
||||
help
|
||||
Select Titan if you are configuring for a Nimble Microsystems
|
||||
NetEngine NP51R.
|
||||
|
||||
config SH_UNKNOWN
|
||||
bool "BareCPU"
|
||||
help
|
||||
|
@ -207,168 +228,27 @@ config SH_UNKNOWN
|
|||
|
||||
endchoice
|
||||
|
||||
choice
|
||||
prompt "Processor family"
|
||||
default CPU_SH4
|
||||
help
|
||||
This option determines the CPU family to compile for. Supported
|
||||
targets are SH-2, SH-3, and SH-4. These options are independent of
|
||||
CPU functionality. As such, SH-DSP users will still want to select
|
||||
their respective processor family in addition to the DSP support
|
||||
option.
|
||||
source "arch/sh/mm/Kconfig"
|
||||
|
||||
config CPU_SH2
|
||||
bool "SH-2"
|
||||
select SH_WRITETHROUGH
|
||||
|
||||
config CPU_SH3
|
||||
bool "SH-3"
|
||||
|
||||
config CPU_SH4
|
||||
bool "SH-4"
|
||||
|
||||
endchoice
|
||||
|
||||
choice
|
||||
prompt "Processor subtype"
|
||||
|
||||
config CPU_SUBTYPE_SH7604
|
||||
bool "SH7604"
|
||||
depends on CPU_SH2
|
||||
help
|
||||
Select SH7604 if you have SH7604
|
||||
|
||||
config CPU_SUBTYPE_SH7300
|
||||
bool "SH7300"
|
||||
depends on CPU_SH3
|
||||
|
||||
config CPU_SUBTYPE_SH7705
|
||||
bool "SH7705"
|
||||
depends on CPU_SH3
|
||||
|
||||
config CPU_SUBTYPE_SH7707
|
||||
bool "SH7707"
|
||||
depends on CPU_SH3
|
||||
help
|
||||
Select SH7707 if you have a 60 Mhz SH-3 HD6417707 CPU.
|
||||
|
||||
config CPU_SUBTYPE_SH7708
|
||||
bool "SH7708"
|
||||
depends on CPU_SH3
|
||||
help
|
||||
Select SH7708 if you have a 60 Mhz SH-3 HD6417708S or
|
||||
if you have a 100 Mhz SH-3 HD6417708R CPU.
|
||||
|
||||
config CPU_SUBTYPE_SH7709
|
||||
bool "SH7709"
|
||||
depends on CPU_SH3
|
||||
help
|
||||
Select SH7709 if you have a 80 Mhz SH-3 HD6417709 CPU.
|
||||
|
||||
config CPU_SUBTYPE_SH7750
|
||||
bool "SH7750"
|
||||
depends on CPU_SH4
|
||||
help
|
||||
Select SH7750 if you have a 200 Mhz SH-4 HD6417750 CPU.
|
||||
|
||||
config CPU_SUBTYPE_SH7751
|
||||
bool "SH7751/SH7751R"
|
||||
depends on CPU_SH4
|
||||
help
|
||||
Select SH7751 if you have a 166 Mhz SH-4 HD6417751 CPU,
|
||||
or if you have a HD6417751R CPU.
|
||||
|
||||
config CPU_SUBTYPE_SH7760
|
||||
bool "SH7760"
|
||||
depends on CPU_SH4
|
||||
|
||||
config CPU_SUBTYPE_SH73180
|
||||
bool "SH73180"
|
||||
depends on CPU_SH4
|
||||
|
||||
config CPU_SUBTYPE_ST40STB1
|
||||
bool "ST40STB1 / ST40RA"
|
||||
depends on CPU_SH4
|
||||
help
|
||||
Select ST40STB1 if you have a ST40RA CPU.
|
||||
This was previously called the ST40STB1, hence the option name.
|
||||
|
||||
config CPU_SUBTYPE_ST40GX1
|
||||
bool "ST40GX1"
|
||||
depends on CPU_SH4
|
||||
help
|
||||
Select ST40GX1 if you have a ST40GX1 CPU.
|
||||
|
||||
config CPU_SUBTYPE_SH4_202
|
||||
bool "SH4-202"
|
||||
depends on CPU_SH4
|
||||
|
||||
endchoice
|
||||
|
||||
config SH7705_CACHE_32KB
|
||||
bool "Enable 32KB cache size for SH7705"
|
||||
depends on CPU_SUBTYPE_SH7705
|
||||
default y
|
||||
|
||||
config MMU
|
||||
bool "Support for memory management hardware"
|
||||
depends on !CPU_SH2
|
||||
default y
|
||||
help
|
||||
Early SH processors (such as the SH7604) lack an MMU. In order to
|
||||
boot on these systems, this option must not be set.
|
||||
|
||||
On other systems (such as the SH-3 and 4) where an MMU exists,
|
||||
turning this off will boot the kernel on these machines with the
|
||||
MMU implicitly switched off.
|
||||
|
||||
choice
|
||||
prompt "HugeTLB page size"
|
||||
depends on HUGETLB_PAGE && CPU_SH4 && MMU
|
||||
default HUGETLB_PAGE_SIZE_64K
|
||||
|
||||
config HUGETLB_PAGE_SIZE_64K
|
||||
bool "64K"
|
||||
|
||||
config HUGETLB_PAGE_SIZE_1MB
|
||||
bool "1MB"
|
||||
|
||||
endchoice
|
||||
|
||||
config CMDLINE_BOOL
|
||||
bool "Default bootloader kernel arguments"
|
||||
|
||||
config CMDLINE
|
||||
string "Initial kernel command string"
|
||||
depends on CMDLINE_BOOL
|
||||
default "console=ttySC1,115200"
|
||||
|
||||
# Platform-specific memory start and size definitions
|
||||
config MEMORY_START
|
||||
hex "Physical memory start address" if !MEMORY_SET || MEMORY_OVERRIDE
|
||||
default "0x08000000" if !MEMORY_SET || MEMORY_OVERRIDE || !MEMORY_OVERRIDE && SH_ADX || SH_MPC1211 || SH_SH03 || SH_SECUREEDGE5410 || SH_SH4202_MICRODEV
|
||||
default "0x0c000000" if !MEMORY_OVERRIDE && (SH_DREAMCAST || SH_HP600 || SH_BIGSUR || SH_SH2000 || SH_73180_SOLUTION_ENGINE || SH_7300_SOLUTION_ENGINE || SH_7751_SOLUTION_ENGINE || SH_SOLUTION_ENGINE || SH_HS7751RVOIP || SH_RTS7751R2D || SH_EDOSK7705)
|
||||
hex "Physical memory start address"
|
||||
default "0x08000000"
|
||||
---help---
|
||||
Computers built with Hitachi SuperH processors always
|
||||
map the ROM starting at address zero. But the processor
|
||||
does not specify the range that RAM takes.
|
||||
|
||||
The physical memory (RAM) start address will be automatically
|
||||
set to 08000000, unless you selected one of the following
|
||||
processor types: SolutionEngine, Overdrive, HP620, HP680, HP690,
|
||||
in which case the start address will be set to 0c000000.
|
||||
set to 08000000. Other platforms, such as the Solution Engine
|
||||
boards typically map RAM at 0C000000.
|
||||
|
||||
Tweak this only when porting to a new machine which is not already
|
||||
known by the config system. Changing it from the known correct
|
||||
Tweak this only when porting to a new machine which does not
|
||||
already have a defconfig. Changing it from the known correct
|
||||
value on any of the known systems will only lead to disaster.
|
||||
|
||||
config MEMORY_SIZE
|
||||
hex "Physical memory size" if !MEMORY_SET || MEMORY_OVERRIDE
|
||||
default "0x00400000" if !MEMORY_SET || MEMORY_OVERRIDE || !MEMORY_OVERRIDE && SH_ADX || !MEMORY_OVERRIDE && (SH_HP600 || SH_BIGSUR || SH_SH2000)
|
||||
default "0x01000000" if !MEMORY_OVERRIDE && SH_DREAMCAST || SH_SECUREEDGE5410 || SH_EDOSK7705
|
||||
default "0x02000000" if !MEMORY_OVERRIDE && (SH_73180_SOLUTION_ENGINE || SH_SOLUTION_ENGINE)
|
||||
default "0x04000000" if !MEMORY_OVERRIDE && (SH_7300_SOLUTION_ENGINE || SH_7751_SOLUTION_ENGINE || SH_HS7751RVOIP || SH_RTS7751R2D || SH_SH4202_MICRODEV)
|
||||
default "0x08000000" if SH_MPC1211 || SH_SH03
|
||||
hex "Physical memory size"
|
||||
default "0x00400000"
|
||||
help
|
||||
This sets the default memory size assumed by your SH kernel. It can
|
||||
be overridden as normal by the 'mem=' argument on the kernel command
|
||||
|
@ -376,21 +256,6 @@ config MEMORY_SIZE
|
|||
as 0x00400000 which was the default value before this became
|
||||
configurable.
|
||||
|
||||
config MEMORY_SET
|
||||
bool
|
||||
depends on !MEMORY_OVERRIDE && (SH_MPC1211 || SH_SH03 || SH_ADX || SH_DREAMCAST || SH_HP600 || SH_BIGSUR || SH_SH2000 || SH_7751_SOLUTION_ENGINE || SH_SOLUTION_ENGINE || SH_SECUREEDGE5410 || SH_HS7751RVOIP || SH_RTS7751R2D || SH_SH4202_MICRODEV || SH_EDOSK7705)
|
||||
default y
|
||||
help
|
||||
This is an option about which you will never be asked a question.
|
||||
Therefore, I conclude that you do not exist - go away.
|
||||
|
||||
There is a grue here.
|
||||
|
||||
# If none of the above have set memory start/size, ask the user.
|
||||
config MEMORY_OVERRIDE
|
||||
bool "Override default load address and memory size"
|
||||
|
||||
# XXX: break these out into the board-specific configs below
|
||||
config CF_ENABLER
|
||||
bool "Compact Flash Enabler support"
|
||||
depends on SH_ADX || SH_SOLUTION_ENGINE || SH_UNKNOWN || SH_CAT68701 || SH_SH03
|
||||
|
@ -434,10 +299,21 @@ config CF_BASE_ADDR
|
|||
default "0xb8000000" if CF_AREA6
|
||||
default "0xb4000000" if CF_AREA5
|
||||
|
||||
menu "Processor features"
|
||||
|
||||
config CPU_LITTLE_ENDIAN
|
||||
bool "Little Endian"
|
||||
help
|
||||
Some SuperH machines can be configured for either little or big
|
||||
endian byte order. These modes require different kernels. Say Y if
|
||||
your machine is little endian, N if it's a big endian machine.
|
||||
|
||||
# The SH7750 RTC module is disabled in the Dreamcast
|
||||
config SH_RTC
|
||||
bool
|
||||
depends on !SH_DREAMCAST && !SH_SATURN && !SH_7300_SOLUTION_ENGINE && !SH_73180_SOLUTION_ENGINE
|
||||
depends on !SH_DREAMCAST && !SH_SATURN && !SH_7300_SOLUTION_ENGINE && \
|
||||
!SH_73180_SOLUTION_ENGINE && !SH_LANDISK && \
|
||||
!SH_R7780RP
|
||||
default y
|
||||
help
|
||||
Selecting this option will allow the Linux kernel to emulate
|
||||
|
@ -476,98 +352,6 @@ config SH_ADC
|
|||
|
||||
If unsure, say N.
|
||||
|
||||
config SH_HP600
|
||||
bool
|
||||
depends on SH_HP620 || SH_HP680 || SH_HP690
|
||||
default y
|
||||
|
||||
config CPU_SUBTYPE_ST40
|
||||
bool
|
||||
depends on CPU_SUBTYPE_ST40STB1 || CPU_SUBTYPE_ST40GX1
|
||||
default y
|
||||
|
||||
source "mm/Kconfig"
|
||||
|
||||
config ZERO_PAGE_OFFSET
|
||||
hex "Zero page offset"
|
||||
default "0x00001000" if !(SH_MPC1211 || SH_SH03)
|
||||
default "0x00004000" if SH_MPC1211 || SH_SH03
|
||||
help
|
||||
This sets the default offset of zero page.
|
||||
|
||||
# XXX: needs to lose subtype for system type
|
||||
config ST40_LMI_MEMORY
|
||||
bool "Memory on LMI"
|
||||
depends on CPU_SUBTYPE_ST40STB1
|
||||
|
||||
config MEMORY_START
|
||||
hex
|
||||
depends on CPU_SUBTYPE_ST40STB1 && ST40_LMI_MEMORY
|
||||
default "0x08000000"
|
||||
|
||||
config MEMORY_SIZE
|
||||
hex
|
||||
depends on CPU_SUBTYPE_ST40STB1 && ST40_LMI_MEMORY
|
||||
default "0x00400000"
|
||||
|
||||
config MEMORY_SET
|
||||
bool
|
||||
depends on CPU_SUBTYPE_ST40STB1 && ST40_LMI_MEMORY
|
||||
default y
|
||||
|
||||
config BOOT_LINK_OFFSET
|
||||
hex "Link address offset for booting"
|
||||
default "0x00800000"
|
||||
help
|
||||
This option allows you to set the link address offset of the zImage.
|
||||
This can be useful if you are on a board which has a small amount of
|
||||
memory.
|
||||
|
||||
config CPU_LITTLE_ENDIAN
|
||||
bool "Little Endian"
|
||||
help
|
||||
Some SuperH machines can be configured for either little or big
|
||||
endian byte order. These modes require different kernels. Say Y if
|
||||
your machine is little endian, N if it's a big endian machine.
|
||||
|
||||
config PREEMPT
|
||||
bool "Preemptible Kernel (EXPERIMENTAL)"
|
||||
depends on EXPERIMENTAL
|
||||
|
||||
config UBC_WAKEUP
|
||||
bool "Wakeup UBC on startup"
|
||||
help
|
||||
Selecting this option will wakeup the User Break Controller (UBC) on
|
||||
startup. Although the UBC is left in an awake state when the processor
|
||||
comes up, some boot loaders misbehave by putting the UBC to sleep in a
|
||||
power saving state, which causes issues with things like ptrace().
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config SH_WRITETHROUGH
|
||||
bool "Use write-through caching"
|
||||
default y if CPU_SH2
|
||||
help
|
||||
Selecting this option will configure the caches in write-through
|
||||
mode, as opposed to the default write-back configuration.
|
||||
|
||||
Since there's sill some aliasing issues on SH-4, this option will
|
||||
unfortunately still require the majority of flushing functions to
|
||||
be implemented to deal with aliasing.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config SH_OCRAM
|
||||
bool "Operand Cache RAM (OCRAM) support"
|
||||
help
|
||||
Selecting this option will automatically tear down the number of
|
||||
sets in the dcache by half, which in turn exposes a memory range.
|
||||
|
||||
The addresses for the OC RAM base will vary according to the
|
||||
processor version. Consult vendor documentation for specifics.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config SH_STORE_QUEUES
|
||||
bool "Support for Store Queues"
|
||||
depends on CPU_SH4
|
||||
|
@ -575,6 +359,125 @@ config SH_STORE_QUEUES
|
|||
Selecting this option will enable an in-kernel API for manipulating
|
||||
the store queues integrated in the SH-4 processors.
|
||||
|
||||
config CPU_HAS_INTEVT
|
||||
bool
|
||||
|
||||
config CPU_HAS_PINT_IRQ
|
||||
bool
|
||||
|
||||
config CPU_HAS_INTC2_IRQ
|
||||
bool
|
||||
|
||||
config CPU_HAS_SR_RB
|
||||
bool "CPU has SR.RB"
|
||||
depends on CPU_SH3 || CPU_SH4
|
||||
default y
|
||||
help
|
||||
This will enable the use of SR.RB register bank usage. Processors
|
||||
that are lacking this bit must have another method in place for
|
||||
accomplishing what is taken care of by the banked registers.
|
||||
|
||||
See <file:Documentation/sh/register-banks.txt> for further
|
||||
information on SR.RB and register banking in the kernel in general.
|
||||
|
||||
endmenu
|
||||
|
||||
menu "Timer support"
|
||||
|
||||
config SH_TMU
|
||||
bool "TMU timer support"
|
||||
default y
|
||||
help
|
||||
This enables the use of the TMU as the system timer.
|
||||
|
||||
endmenu
|
||||
|
||||
source "arch/sh/boards/renesas/hs7751rvoip/Kconfig"
|
||||
|
||||
source "arch/sh/boards/renesas/rts7751r2d/Kconfig"
|
||||
|
||||
config SH_PCLK_FREQ_BOOL
|
||||
bool "Set default pclk frequency"
|
||||
default y if !SH_RTC
|
||||
default n
|
||||
|
||||
config SH_PCLK_FREQ
|
||||
int "Peripheral clock frequency (in Hz)"
|
||||
depends on SH_PCLK_FREQ_BOOL
|
||||
default "50000000" if CPU_SUBTYPE_SH7750 || CPU_SUBTYPE_SH7780
|
||||
default "60000000" if CPU_SUBTYPE_SH7751
|
||||
default "33333333" if CPU_SUBTYPE_SH7300 || CPU_SUBTYPE_SH7770 || CPU_SUBTYPE_SH7760
|
||||
default "27000000" if CPU_SUBTYPE_SH73180
|
||||
default "66000000" if CPU_SUBTYPE_SH4_202
|
||||
help
|
||||
This option is used to specify the peripheral clock frequency.
|
||||
This is necessary for determining the reference clock value on
|
||||
platforms lacking an RTC.
|
||||
|
||||
menu "CPU Frequency scaling"
|
||||
|
||||
source "drivers/cpufreq/Kconfig"
|
||||
|
||||
config SH_CPU_FREQ
|
||||
tristate "SuperH CPU Frequency driver"
|
||||
depends on CPU_FREQ
|
||||
select CPU_FREQ_TABLE
|
||||
help
|
||||
This adds the cpufreq driver for SuperH. At present, only
|
||||
the SH-4 is supported.
|
||||
|
||||
For details, take a look at <file:Documentation/cpu-freq>.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
endmenu
|
||||
|
||||
source "arch/sh/drivers/dma/Kconfig"
|
||||
|
||||
source "arch/sh/cchips/Kconfig"
|
||||
|
||||
config HEARTBEAT
|
||||
bool "Heartbeat LED"
|
||||
depends on SH_MPC1211 || SH_SH03 || SH_CAT68701 || \
|
||||
SH_STB1_HARP || SH_STB1_OVERDRIVE || SH_BIGSUR || \
|
||||
SH_7751_SOLUTION_ENGINE || SH_7300_SOLUTION_ENGINE || \
|
||||
SH_73180_SOLUTION_ENGINE || SH_SOLUTION_ENGINE || \
|
||||
SH_RTS7751R2D || SH_SH4202_MICRODEV || SH_LANDISK
|
||||
help
|
||||
Use the power-on LED on your machine as a load meter. The exact
|
||||
behavior is platform-dependent, but normally the flash frequency is
|
||||
a hyperbolic function of the 5-minute load average.
|
||||
|
||||
endmenu
|
||||
|
||||
config ISA_DMA_API
|
||||
bool
|
||||
depends on MPC1211
|
||||
default y
|
||||
|
||||
menu "Kernel features"
|
||||
|
||||
config KEXEC
|
||||
bool "kexec system call (EXPERIMENTAL)"
|
||||
depends on EXPERIMENTAL
|
||||
help
|
||||
kexec is a system call that implements the ability to shutdown your
|
||||
current kernel, and to start another kernel. It is like a reboot
|
||||
but it is indepedent of the system firmware. And like a reboot
|
||||
you can start any kernel with it, not just Linux.
|
||||
|
||||
The name comes from the similiarity to the exec system call.
|
||||
|
||||
It is an ongoing process to be certain the hardware in a machine
|
||||
is properly shutdown, so do not be surprised if this code does not
|
||||
initially work for you. It may help to enable device hotplugging
|
||||
support. As of this writing the exact hardware interface is
|
||||
strongly in flux, so no good recommendation can be made.
|
||||
|
||||
config PREEMPT
|
||||
bool "Preemptible Kernel (EXPERIMENTAL)"
|
||||
depends on EXPERIMENTAL
|
||||
|
||||
config SMP
|
||||
bool "Symmetric multi-processing support"
|
||||
---help---
|
||||
|
@ -610,87 +513,58 @@ config NR_CPUS
|
|||
This is purely to save memory - each supported CPU adds
|
||||
approximately eight kilobytes to the kernel image.
|
||||
|
||||
config HS7751RVOIP_CODEC
|
||||
bool "Support VoIP Codec section"
|
||||
depends on SH_HS7751RVOIP
|
||||
help
|
||||
Selecting this option will support CODEC section.
|
||||
|
||||
config RTS7751R2D_REV11
|
||||
bool "RTS7751R2D Rev. 1.1 board support"
|
||||
depends on SH_RTS7751R2D
|
||||
help
|
||||
Selecting this option will support version rev. 1.1.
|
||||
|
||||
config SH_PCLK_CALC
|
||||
bool
|
||||
default n if CPU_SUBTYPE_SH7300 || CPU_SUBTYPE_SH73180
|
||||
config CPU_HAS_SR_RB
|
||||
bool "CPU has SR.RB"
|
||||
depends on CPU_SH3 || CPU_SH4
|
||||
default y
|
||||
help
|
||||
This option will cause the PCLK value to be probed at run-time. It
|
||||
will display a notification if the probed value has greater than a
|
||||
1% variance of the hardcoded CONFIG_SH_PCLK_FREQ.
|
||||
This will enable the use of SR.RB register bank usage. Processors
|
||||
that are lacking this bit must have another method in place for
|
||||
accomplishing what is taken care of by the banked registers.
|
||||
|
||||
config SH_PCLK_FREQ
|
||||
int "Peripheral clock frequency (in Hz)"
|
||||
default "50000000" if CPU_SUBTYPE_SH7750
|
||||
default "60000000" if CPU_SUBTYPE_SH7751
|
||||
default "33333333" if CPU_SUBTYPE_SH7300
|
||||
default "27000000" if CPU_SUBTYPE_SH73180
|
||||
default "66000000" if CPU_SUBTYPE_SH4_202
|
||||
default "1193182"
|
||||
See <file:Documentation/sh/register-banks.txt> for further
|
||||
information on SR.RB and register banking in the kernel in general.
|
||||
|
||||
endmenu
|
||||
|
||||
menu "Boot options"
|
||||
|
||||
config ZERO_PAGE_OFFSET
|
||||
hex "Zero page offset"
|
||||
default "0x00004000" if SH_MPC1211 || SH_SH03
|
||||
default "0x00001000"
|
||||
help
|
||||
This option is used to specify the peripheral clock frequency. This
|
||||
option must be set for each processor in order for the kernel to
|
||||
function reliably. If no sane default exists, we use a default from
|
||||
the legacy i8254. Any discrepancies will be reported on boot time
|
||||
with an auto-probed frequency which should be considered the proper
|
||||
value for your hardware.
|
||||
This sets the default offset of zero page.
|
||||
|
||||
menu "CPU Frequency scaling"
|
||||
|
||||
source "drivers/cpufreq/Kconfig"
|
||||
|
||||
config SH_CPU_FREQ
|
||||
tristate "SuperH CPU Frequency driver"
|
||||
depends on CPU_FREQ
|
||||
select CPU_FREQ_TABLE
|
||||
config BOOT_LINK_OFFSET
|
||||
hex "Link address offset for booting"
|
||||
default "0x00800000"
|
||||
help
|
||||
This adds the cpufreq driver for SuperH. At present, only
|
||||
the SH-4 is supported.
|
||||
This option allows you to set the link address offset of the zImage.
|
||||
This can be useful if you are on a board which has a small amount of
|
||||
memory.
|
||||
|
||||
For details, take a look at <file:Documentation/cpu-freq>.
|
||||
config UBC_WAKEUP
|
||||
bool "Wakeup UBC on startup"
|
||||
help
|
||||
Selecting this option will wakeup the User Break Controller (UBC) on
|
||||
startup. Although the UBC is left in an awake state when the processor
|
||||
comes up, some boot loaders misbehave by putting the UBC to sleep in a
|
||||
power saving state, which causes issues with things like ptrace().
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
endmenu
|
||||
config CMDLINE_BOOL
|
||||
bool "Default bootloader kernel arguments"
|
||||
|
||||
source "arch/sh/drivers/dma/Kconfig"
|
||||
|
||||
source "arch/sh/cchips/Kconfig"
|
||||
|
||||
config HEARTBEAT
|
||||
bool "Heartbeat LED"
|
||||
depends on SH_MPC1211 || SH_SH03 || SH_CAT68701 || SH_STB1_HARP || SH_STB1_OVERDRIVE || SH_BIGSUR || SH_7751_SOLUTION_ENGINE || SH_7300_SOLUTION_ENGINE || SH_73180_SOLUTION_ENGINE || SH_SOLUTION_ENGINE || SH_RTS7751R2D || SH_SH4202_MICRODEV
|
||||
help
|
||||
Use the power-on LED on your machine as a load meter. The exact
|
||||
behavior is platform-dependent, but normally the flash frequency is
|
||||
a hyperbolic function of the 5-minute load average.
|
||||
|
||||
config RTC_9701JE
|
||||
tristate "EPSON RTC-9701JE support"
|
||||
depends on SH_RTS7751R2D
|
||||
help
|
||||
Selecting this option will support EPSON RTC-9701JE.
|
||||
config CMDLINE
|
||||
string "Initial kernel command string"
|
||||
depends on CMDLINE_BOOL
|
||||
default "console=ttySC1,115200"
|
||||
|
||||
endmenu
|
||||
|
||||
config ISA_DMA_API
|
||||
bool
|
||||
depends on MPC1211
|
||||
default y
|
||||
|
||||
menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)"
|
||||
menu "Bus options"
|
||||
|
||||
# Even on SuperH devices which don't have an ISA bus,
|
||||
# this variable helps the PCMCIA modules handle
|
||||
|
@ -701,7 +575,7 @@ menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)"
|
|||
# PCMCIA outright. -- PFM.
|
||||
config ISA
|
||||
bool
|
||||
default y if PCMCIA || SMC91X
|
||||
default y if PCMCIA
|
||||
help
|
||||
Find out whether you have ISA slots on your motherboard. ISA is the
|
||||
name of a bus system, i.e. the way the CPU talks to the other stuff
|
||||
|
@ -735,10 +609,9 @@ config MCA
|
|||
config SBUS
|
||||
bool
|
||||
|
||||
config MAPLE
|
||||
tristate "Maple Bus support"
|
||||
depends on SH_DREAMCAST
|
||||
default y
|
||||
config SUPERHYWAY
|
||||
tristate "SuperHyway Bus support"
|
||||
depends on CPU_SUBTYPE_SH4_202
|
||||
|
||||
source "arch/sh/drivers/pci/Kconfig"
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ config SH_STANDARD_BIOS
|
|||
|
||||
config EARLY_SCIF_CONSOLE
|
||||
bool "Use early SCIF console"
|
||||
depends on CPU_SH4
|
||||
depends on CPU_SH4 || CPU_SH2A && !SH_STANDARD_BIOS
|
||||
|
||||
config EARLY_PRINTK
|
||||
bool "Early printk support"
|
||||
|
|
|
@ -17,10 +17,30 @@
|
|||
cflags-y := -mb
|
||||
cflags-$(CONFIG_CPU_LITTLE_ENDIAN) := -ml
|
||||
|
||||
isa-y := any
|
||||
isa-$(CONFIG_CPU_SH2) := sh2
|
||||
isa-$(CONFIG_CPU_SH3) := sh3
|
||||
isa-$(CONFIG_CPU_SH4) := sh4
|
||||
isa-$(CONFIG_CPU_SH4A) := sh4a
|
||||
isa-$(CONFIG_CPU_SH2A) := sh2a
|
||||
|
||||
isa-$(CONFIG_SH_DSP) := $(isa-y)-dsp
|
||||
|
||||
ifndef CONFIG_MMU
|
||||
isa-y := $(isa-y)-nommu
|
||||
endif
|
||||
|
||||
ifndef CONFIG_SH_FPU
|
||||
isa-y := $(isa-y)-nofpu
|
||||
endif
|
||||
|
||||
cflags-y += $(call as-option,-Wa$(comma)-isa=$(isa-y),)
|
||||
|
||||
cflags-$(CONFIG_CPU_SH2) += -m2
|
||||
cflags-$(CONFIG_CPU_SH3) += -m3
|
||||
cflags-$(CONFIG_CPU_SH4) += -m4 \
|
||||
$(call cc-option,-mno-implicit-fp,-m4-nofpu)
|
||||
cflags-$(CONFIG_CPU_SH4A) += $(call cc-option,-m4a-nofpu,)
|
||||
|
||||
cflags-$(CONFIG_SH_DSP) += -Wa,-dsp
|
||||
cflags-$(CONFIG_SH_KGDB) += -g
|
||||
|
@ -67,9 +87,7 @@ machdir-$(CONFIG_SH_7300_SOLUTION_ENGINE) := se/7300
|
|||
machdir-$(CONFIG_SH_73180_SOLUTION_ENGINE) := se/73180
|
||||
machdir-$(CONFIG_SH_STB1_HARP) := harp
|
||||
machdir-$(CONFIG_SH_STB1_OVERDRIVE) := overdrive
|
||||
machdir-$(CONFIG_SH_HP620) := hp6xx/hp620
|
||||
machdir-$(CONFIG_SH_HP680) := hp6xx/hp680
|
||||
machdir-$(CONFIG_SH_HP690) := hp6xx/hp690
|
||||
machdir-$(CONFIG_SH_HP6XX) := hp6xx
|
||||
machdir-$(CONFIG_SH_CQREEK) := cqreek
|
||||
machdir-$(CONFIG_SH_DMIDA) := dmida
|
||||
machdir-$(CONFIG_SH_EC3104) := ec3104
|
||||
|
@ -119,31 +137,39 @@ boot := arch/sh/boot
|
|||
|
||||
CPPFLAGS_vmlinux.lds := -traditional
|
||||
|
||||
ifneq ($(KBUILD_SRC),)
|
||||
incdir-prefix := $(srctree)/include/asm-sh/
|
||||
else
|
||||
incdir-prefix :=
|
||||
endif
|
||||
|
||||
# Update machine arch and proc symlinks if something which affects
|
||||
# them changed. We use .arch and .mach to indicate when they were
|
||||
# updated last, otherwise make uses the target directory mtime.
|
||||
|
||||
include/asm-sh/.cpu: $(wildcard include/config/cpu/*.h) include/config/MARKER
|
||||
@echo ' SYMLINK include/asm-sh/cpu -> include/asm-sh/$(cpuincdir-y)'
|
||||
ifneq ($(KBUILD_SRC),)
|
||||
$(Q)mkdir -p include/asm-sh
|
||||
$(Q)ln -fsn $(srctree)/include/asm-sh/$(cpuincdir-y) include/asm-sh/cpu
|
||||
else
|
||||
$(Q)ln -fsn $(cpuincdir-y) include/asm-sh/cpu
|
||||
endif
|
||||
$(Q)if [ ! -d include/asm-sh ]; then mkdir -p include/asm-sh; fi
|
||||
$(Q)ln -fsn $(incdir-prefix)$(cpuincdir-y) include/asm-sh/cpu
|
||||
@touch $@
|
||||
|
||||
# Most boards have their own mach directories. For the ones that
|
||||
# don't, just reference the parent directory so the semantics are
|
||||
# kept roughly the same.
|
||||
|
||||
include/asm-sh/.mach: $(wildcard include/config/sh/*.h) include/config/MARKER
|
||||
@echo ' SYMLINK include/asm-sh/mach -> include/asm-sh/$(incdir-y)'
|
||||
ifneq ($(KBUILD_SRC),)
|
||||
$(Q)mkdir -p include/asm-sh
|
||||
$(Q)ln -fsn $(srctree)/include/asm-sh/$(incdir-y) include/asm-sh/mach
|
||||
else
|
||||
$(Q)ln -fsn $(incdir-y) include/asm-sh/mach
|
||||
endif
|
||||
@echo -n ' SYMLINK include/asm-sh/mach -> '
|
||||
$(Q)if [ ! -d include/asm-sh ]; then mkdir -p include/asm-sh; fi
|
||||
$(Q)if [ -d $(incdir-prefix)$(incdir-y) ]; then \
|
||||
echo -e 'include/asm-sh/$(incdir-y)'; \
|
||||
ln -fsn $(incdir-prefix)$(incdir-y) \
|
||||
include/asm-sh/mach; \
|
||||
else \
|
||||
echo -e 'include/asm-sh'; \
|
||||
ln -fsn $(incdir-prefix) include/asm-sh/mach; \
|
||||
fi
|
||||
@touch $@
|
||||
|
||||
|
||||
archprepare: maketools include/asm-sh/.cpu include/asm-sh/.mach
|
||||
|
||||
.PHONY: maketools FORCE
|
||||
|
|
6
arch/sh/boards/hp6xx/Makefile
Normal file
6
arch/sh/boards/hp6xx/Makefile
Normal file
|
@ -0,0 +1,6 @@
|
|||
#
|
||||
# Makefile for the HP6xx specific parts of the kernel
|
||||
#
|
||||
|
||||
obj-y := mach.o setup.o
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
#
|
||||
# Makefile for the HP620 specific parts of the kernel
|
||||
#
|
||||
|
||||
obj-y := mach.o setup.o
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
/*
|
||||
* linux/arch/sh/boards/hp6xx/hp620/mach.c
|
||||
*
|
||||
* Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
|
||||
*
|
||||
* May be copied or modified under the terms of the GNU General Public
|
||||
* License. See linux/COPYING for more information.
|
||||
*
|
||||
* Machine vector for the HP620
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <asm/machvec.h>
|
||||
#include <asm/rtc.h>
|
||||
#include <asm/machvec_init.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/hd64461/hd64461.h>
|
||||
#include <asm/irq.h>
|
||||
|
||||
/*
|
||||
* The Machine Vector
|
||||
*/
|
||||
|
||||
struct sh_machine_vector mv_hp620 __initmv = {
|
||||
.mv_nr_irqs = HD64461_IRQBASE+HD64461_IRQ_NUM,
|
||||
|
||||
.mv_inb = hd64461_inb,
|
||||
.mv_inw = hd64461_inw,
|
||||
.mv_inl = hd64461_inl,
|
||||
.mv_outb = hd64461_outb,
|
||||
.mv_outw = hd64461_outw,
|
||||
.mv_outl = hd64461_outl,
|
||||
|
||||
.mv_inb_p = hd64461_inb_p,
|
||||
.mv_inw_p = hd64461_inw,
|
||||
.mv_inl_p = hd64461_inl,
|
||||
.mv_outb_p = hd64461_outb_p,
|
||||
.mv_outw_p = hd64461_outw,
|
||||
.mv_outl_p = hd64461_outl,
|
||||
|
||||
.mv_insb = hd64461_insb,
|
||||
.mv_insw = hd64461_insw,
|
||||
.mv_insl = hd64461_insl,
|
||||
.mv_outsb = hd64461_outsb,
|
||||
.mv_outsw = hd64461_outsw,
|
||||
.mv_outsl = hd64461_outsl,
|
||||
|
||||
.mv_irq_demux = hd64461_irq_demux,
|
||||
};
|
||||
ALIAS_MV(hp620)
|
|
@ -1,45 +0,0 @@
|
|||
/*
|
||||
* linux/arch/sh/boards/hp6xx/hp620/setup.c
|
||||
*
|
||||
* Copyright (C) 2002 Andriy Skulysh, 2005 Kristoffer Ericson
|
||||
*
|
||||
* May be copied or modified under the terms of the GNU General Public
|
||||
* License. See Linux/COPYING for more information.
|
||||
*
|
||||
* Setup code for an HP620.
|
||||
* Due to similiarity with hp680/hp690 same inits are done (for now)
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/init.h>
|
||||
#include <asm/hd64461/hd64461.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/hp6xx/hp6xx.h>
|
||||
#include <asm/cpu/dac.h>
|
||||
|
||||
const char *get_system_type(void)
|
||||
{
|
||||
return "HP620";
|
||||
}
|
||||
|
||||
int __init platform_setup(void)
|
||||
{
|
||||
u16 v;
|
||||
|
||||
v = inw(HD64461_STBCR);
|
||||
v |= HD64461_STBCR_SURTST | HD64461_STBCR_SIRST |
|
||||
HD64461_STBCR_STM1ST | HD64461_STBCR_STM0ST |
|
||||
HD64461_STBCR_SAFEST | HD64461_STBCR_SPC0ST |
|
||||
HD64461_STBCR_SMIAST | HD64461_STBCR_SAFECKE_OST |
|
||||
HD64461_STBCR_SAFECKE_IST;
|
||||
outw(v, HD64461_STBCR);
|
||||
|
||||
v = inw(HD64461_GPADR);
|
||||
v |= HD64461_GPADR_SPEAKER | HD64461_GPADR_PCMCIA0;
|
||||
outw(v, HD64461_GPADR);
|
||||
|
||||
sh_dac_disable(DAC_SPEAKER_VOLUME);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
#
|
||||
# Makefile for the HP680 specific parts of the kernel
|
||||
#
|
||||
|
||||
obj-y := mach.o setup.o
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
#
|
||||
# Makefile for the HP690 specific parts of the kernel
|
||||
#
|
||||
|
||||
obj-y := mach.o
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
/*
|
||||
* linux/arch/sh/boards/hp6xx/hp690/mach.c
|
||||
*
|
||||
* Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
|
||||
*
|
||||
* May be copied or modified under the terms of the GNU General Public
|
||||
* License. See linux/COPYING for more information.
|
||||
*
|
||||
* Machine vector for the HP690
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <asm/machvec.h>
|
||||
#include <asm/rtc.h>
|
||||
#include <asm/machvec_init.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/hd64461/hd64461.h>
|
||||
#include <asm/irq.h>
|
||||
|
||||
struct sh_machine_vector mv_hp690 __initmv = {
|
||||
.mv_nr_irqs = HD64461_IRQBASE+HD64461_IRQ_NUM,
|
||||
|
||||
.mv_inb = hd64461_inb,
|
||||
.mv_inw = hd64461_inw,
|
||||
.mv_inl = hd64461_inl,
|
||||
.mv_outb = hd64461_outb,
|
||||
.mv_outw = hd64461_outw,
|
||||
.mv_outl = hd64461_outl,
|
||||
|
||||
.mv_inb_p = hd64461_inb_p,
|
||||
.mv_inw_p = hd64461_inw,
|
||||
.mv_inl_p = hd64461_inl,
|
||||
.mv_outb_p = hd64461_outb_p,
|
||||
.mv_outw_p = hd64461_outw,
|
||||
.mv_outl_p = hd64461_outl,
|
||||
|
||||
.mv_insb = hd64461_insb,
|
||||
.mv_insw = hd64461_insw,
|
||||
.mv_insl = hd64461_insl,
|
||||
.mv_outsb = hd64461_outsb,
|
||||
.mv_outsw = hd64461_outsw,
|
||||
.mv_outsl = hd64461_outsl,
|
||||
|
||||
.mv_irq_demux = hd64461_irq_demux,
|
||||
};
|
||||
ALIAS_MV(hp690)
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* linux/arch/sh/boards/hp6xx/hp680/mach.c
|
||||
* linux/arch/sh/boards/hp6xx/mach.c
|
||||
*
|
||||
* Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
|
||||
*
|
||||
|
@ -8,19 +8,12 @@
|
|||
*
|
||||
* Machine vector for the HP680
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <asm/machvec.h>
|
||||
#include <asm/rtc.h>
|
||||
#include <asm/machvec_init.h>
|
||||
|
||||
#include <asm/hd64461.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/hd64461/hd64461.h>
|
||||
#include <asm/hp6xx/io.h>
|
||||
#include <asm/irq.h>
|
||||
|
||||
struct sh_machine_vector mv_hp680 __initmv = {
|
||||
struct sh_machine_vector mv_hp6xx __initmv = {
|
||||
.mv_nr_irqs = HD64461_IRQBASE + HD64461_IRQ_NUM,
|
||||
|
||||
.mv_inb = hd64461_inb,
|
||||
|
@ -50,4 +43,4 @@ struct sh_machine_vector mv_hp680 __initmv = {
|
|||
.mv_irq_demux = hd64461_irq_demux,
|
||||
};
|
||||
|
||||
ALIAS_MV(hp680)
|
||||
ALIAS_MV(hp6xx)
|
|
@ -11,18 +11,19 @@
|
|||
|
||||
#include <linux/config.h>
|
||||
#include <linux/init.h>
|
||||
#include <asm/hd64461/hd64461.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/hd64461.h>
|
||||
#include <asm/hp6xx/hp6xx.h>
|
||||
#include <asm/cpu/dac.h>
|
||||
|
||||
const char *get_system_type(void)
|
||||
{
|
||||
return "HP680";
|
||||
return "HP6xx";
|
||||
}
|
||||
|
||||
int __init platform_setup(void)
|
||||
{
|
||||
u8 v8;
|
||||
u16 v;
|
||||
v = inw(HD64461_STBCR);
|
||||
v |= HD64461_STBCR_SURTST | HD64461_STBCR_SIRST |
|
||||
|
@ -30,12 +31,25 @@ int __init platform_setup(void)
|
|||
HD64461_STBCR_SAFEST | HD64461_STBCR_SPC0ST |
|
||||
HD64461_STBCR_SMIAST | HD64461_STBCR_SAFECKE_OST |
|
||||
HD64461_STBCR_SAFECKE_IST;
|
||||
#ifndef CONFIG_HD64461_ENABLER
|
||||
v |= HD64461_STBCR_SPC1ST;
|
||||
#endif
|
||||
outw(v, HD64461_STBCR);
|
||||
v = inw(HD64461_GPADR);
|
||||
v |= HD64461_GPADR_SPEAKER | HD64461_GPADR_PCMCIA0;
|
||||
outw(v, HD64461_GPADR);
|
||||
|
||||
outw(HD64461_PCCGCR_VCC0 | HD64461_PCCSCR_VCC1, HD64461_PCC0GCR);
|
||||
|
||||
#ifndef CONFIG_HD64461_ENABLER
|
||||
outw(HD64461_PCCGCR_VCC0 | HD64461_PCCSCR_VCC1, HD64461_PCC1GCR);
|
||||
#endif
|
||||
|
||||
sh_dac_output(0, DAC_SPEAKER_VOLUME);
|
||||
sh_dac_disable(DAC_SPEAKER_VOLUME);
|
||||
v8 = ctrl_inb(DACR);
|
||||
v8 &= ~DACR_DAE;
|
||||
ctrl_outb(v8,DACR);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
# Makefile for the STMicroelectronics Overdrive specific parts of the kernel
|
||||
#
|
||||
|
||||
obj-y := mach.o setup.o io.o irq.o led.o time.o
|
||||
obj-y := mach.o setup.o io.o irq.o led.o
|
||||
|
||||
obj-$(CONFIG_PCI) += fpga.o galileo.o pcidma.o
|
||||
|
||||
|
|
|
@ -17,8 +17,6 @@
|
|||
#include <asm/overdrive/overdrive.h>
|
||||
#include <asm/overdrive/fpga.h>
|
||||
|
||||
extern void od_time_init(void);
|
||||
|
||||
const char *get_system_type(void)
|
||||
{
|
||||
return "SH7750 Overdrive";
|
||||
|
@ -31,11 +29,9 @@ int __init platform_setup(void)
|
|||
{
|
||||
#ifdef CONFIG_PCI
|
||||
init_overdrive_fpga();
|
||||
galileo_init();
|
||||
galileo_init();
|
||||
#endif
|
||||
|
||||
board_time_init = od_time_init;
|
||||
|
||||
/* Enable RS232 receive buffers */
|
||||
writel(0x1e, OVERDRIVE_CTRL);
|
||||
}
|
||||
|
|
|
@ -1,119 +0,0 @@
|
|||
/*
|
||||
* arch/sh/boards/overdrive/time.c
|
||||
*
|
||||
* Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
|
||||
* Copyright (C) 2002 Paul Mundt (lethal@chaoticdreams.org)
|
||||
*
|
||||
* May be copied or modified under the terms of the GNU General Public
|
||||
* License. See linux/COPYING for more information.
|
||||
*
|
||||
* STMicroelectronics Overdrive Support.
|
||||
*/
|
||||
|
||||
void od_time_init(void)
|
||||
{
|
||||
struct frqcr_data {
|
||||
unsigned short frqcr;
|
||||
struct {
|
||||
unsigned char multiplier;
|
||||
unsigned char divisor;
|
||||
} factor[3];
|
||||
};
|
||||
|
||||
static struct frqcr_data st40_frqcr_table[] = {
|
||||
{ 0x000, {{1,1}, {1,1}, {1,2}}},
|
||||
{ 0x002, {{1,1}, {1,1}, {1,4}}},
|
||||
{ 0x004, {{1,1}, {1,1}, {1,8}}},
|
||||
{ 0x008, {{1,1}, {1,2}, {1,2}}},
|
||||
{ 0x00A, {{1,1}, {1,2}, {1,4}}},
|
||||
{ 0x00C, {{1,1}, {1,2}, {1,8}}},
|
||||
{ 0x011, {{1,1}, {2,3}, {1,6}}},
|
||||
{ 0x013, {{1,1}, {2,3}, {1,3}}},
|
||||
{ 0x01A, {{1,1}, {1,2}, {1,4}}},
|
||||
{ 0x01C, {{1,1}, {1,2}, {1,8}}},
|
||||
{ 0x023, {{1,1}, {2,3}, {1,3}}},
|
||||
{ 0x02C, {{1,1}, {1,2}, {1,8}}},
|
||||
{ 0x048, {{1,2}, {1,2}, {1,4}}},
|
||||
{ 0x04A, {{1,2}, {1,2}, {1,6}}},
|
||||
{ 0x04C, {{1,2}, {1,2}, {1,8}}},
|
||||
{ 0x05A, {{1,2}, {1,3}, {1,6}}},
|
||||
{ 0x05C, {{1,2}, {1,3}, {1,6}}},
|
||||
{ 0x063, {{1,2}, {1,4}, {1,4}}},
|
||||
{ 0x06C, {{1,2}, {1,4}, {1,8}}},
|
||||
{ 0x091, {{1,3}, {1,3}, {1,6}}},
|
||||
{ 0x093, {{1,3}, {1,3}, {1,6}}},
|
||||
{ 0x0A3, {{1,3}, {1,6}, {1,6}}},
|
||||
{ 0x0DA, {{1,4}, {1,4}, {1,8}}},
|
||||
{ 0x0DC, {{1,4}, {1,4}, {1,8}}},
|
||||
{ 0x0EC, {{1,4}, {1,8}, {1,8}}},
|
||||
{ 0x123, {{1,4}, {1,4}, {1,8}}},
|
||||
{ 0x16C, {{1,4}, {1,8}, {1,8}}},
|
||||
};
|
||||
|
||||
struct memclk_data {
|
||||
unsigned char multiplier;
|
||||
unsigned char divisor;
|
||||
};
|
||||
static struct memclk_data st40_memclk_table[8] = {
|
||||
{1,1}, // 000
|
||||
{1,2}, // 001
|
||||
{1,3}, // 010
|
||||
{2,3}, // 011
|
||||
{1,4}, // 100
|
||||
{1,6}, // 101
|
||||
{1,8}, // 110
|
||||
{1,8} // 111
|
||||
};
|
||||
|
||||
unsigned long pvr;
|
||||
|
||||
/*
|
||||
* This should probably be moved into the SH3 probing code, and then
|
||||
* use the processor structure to determine which CPU we are running
|
||||
* on.
|
||||
*/
|
||||
pvr = ctrl_inl(CCN_PVR);
|
||||
printk("PVR %08x\n", pvr);
|
||||
|
||||
if (((pvr >> CCN_PVR_CHIP_SHIFT) & CCN_PVR_CHIP_MASK) == CCN_PVR_CHIP_ST40STB1) {
|
||||
/*
|
||||
* Unfortunatly the STB1 FRQCR values are different from the
|
||||
* 7750 ones.
|
||||
*/
|
||||
struct frqcr_data *d;
|
||||
int a;
|
||||
unsigned long memclkcr;
|
||||
struct memclk_data *e;
|
||||
|
||||
for (a=0; a<ARRAY_SIZE(st40_frqcr_table); a++) {
|
||||
d = &st40_frqcr_table[a];
|
||||
if (d->frqcr == (frqcr & 0x1ff))
|
||||
break;
|
||||
}
|
||||
if (a == ARRAY_SIZE(st40_frqcr_table)) {
|
||||
d = st40_frqcr_table;
|
||||
printk("ERROR: Unrecognised FRQCR value, using default multipliers\n");
|
||||
}
|
||||
|
||||
memclkcr = ctrl_inl(CLOCKGEN_MEMCLKCR);
|
||||
e = &st40_memclk_table[memclkcr & MEMCLKCR_RATIO_MASK];
|
||||
|
||||
printk("Clock multipliers: CPU: %d/%d Bus: %d/%d Mem: %d/%d Periph: %d/%d\n",
|
||||
d->factor[0].multiplier, d->factor[0].divisor,
|
||||
d->factor[1].multiplier, d->factor[1].divisor,
|
||||
e->multiplier, e->divisor,
|
||||
d->factor[2].multiplier, d->factor[2].divisor);
|
||||
|
||||
current_cpu_data.master_clock = current_cpu_data.module_clock *
|
||||
d->factor[2].divisor /
|
||||
d->factor[2].multiplier;
|
||||
current_cpu_data.bus_clock = current_cpu_data.master_clock *
|
||||
d->factor[1].multiplier /
|
||||
d->factor[1].divisor;
|
||||
current_cpu_data.memory_clock = current_cpu_data.master_clock *
|
||||
e->multiplier / e->divisor;
|
||||
current_cpu_data.cpu_clock = current_cpu_data.master_clock *
|
||||
d->factor[0].multiplier /
|
||||
d->factor[0].divisor;
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
#
|
||||
# Automatically generated make config: don't edit
|
||||
# Linux kernel version: 2.6.11-sh
|
||||
# Wed Mar 2 15:09:41 2005
|
||||
# Linux kernel version: 2.6.15-sh
|
||||
# Wed Jan 4 15:32:56 2006
|
||||
#
|
||||
CONFIG_SUPERH=y
|
||||
CONFIG_UID16=y
|
||||
|
@ -17,37 +17,60 @@ CONFIG_EXPERIMENTAL=y
|
|||
# CONFIG_CLEAN_COMPILE is not set
|
||||
CONFIG_BROKEN=y
|
||||
CONFIG_BROKEN_ON_SMP=y
|
||||
CONFIG_INIT_ENV_ARG_LIMIT=32
|
||||
|
||||
#
|
||||
# General setup
|
||||
#
|
||||
CONFIG_LOCALVERSION=""
|
||||
CONFIG_LOCALVERSION_AUTO=y
|
||||
CONFIG_SWAP=y
|
||||
# CONFIG_SYSVIPC is not set
|
||||
# CONFIG_BSD_PROCESS_ACCT is not set
|
||||
# CONFIG_SYSCTL is not set
|
||||
# CONFIG_AUDIT is not set
|
||||
CONFIG_LOG_BUF_SHIFT=14
|
||||
# CONFIG_HOTPLUG is not set
|
||||
CONFIG_HOTPLUG=y
|
||||
# CONFIG_IKCONFIG is not set
|
||||
CONFIG_INITRAMFS_SOURCE=""
|
||||
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
|
||||
# CONFIG_EMBEDDED is not set
|
||||
CONFIG_KALLSYMS=y
|
||||
# CONFIG_KALLSYMS_EXTRA_PASS is not set
|
||||
CONFIG_PRINTK=y
|
||||
CONFIG_BUG=y
|
||||
CONFIG_BASE_FULL=y
|
||||
CONFIG_FUTEX=y
|
||||
CONFIG_EPOLL=y
|
||||
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
|
||||
CONFIG_SHMEM=y
|
||||
CONFIG_CC_ALIGN_FUNCTIONS=0
|
||||
CONFIG_CC_ALIGN_LABELS=0
|
||||
CONFIG_CC_ALIGN_LOOPS=0
|
||||
CONFIG_CC_ALIGN_JUMPS=0
|
||||
# CONFIG_TINY_SHMEM is not set
|
||||
CONFIG_BASE_SMALL=0
|
||||
|
||||
#
|
||||
# Loadable module support
|
||||
#
|
||||
# CONFIG_MODULES is not set
|
||||
|
||||
#
|
||||
# Block layer
|
||||
#
|
||||
# CONFIG_LBD is not set
|
||||
|
||||
#
|
||||
# IO Schedulers
|
||||
#
|
||||
CONFIG_IOSCHED_NOOP=y
|
||||
CONFIG_IOSCHED_AS=y
|
||||
CONFIG_IOSCHED_DEADLINE=y
|
||||
CONFIG_IOSCHED_CFQ=y
|
||||
CONFIG_DEFAULT_AS=y
|
||||
# CONFIG_DEFAULT_DEADLINE is not set
|
||||
# CONFIG_DEFAULT_CFQ is not set
|
||||
# CONFIG_DEFAULT_NOOP is not set
|
||||
CONFIG_DEFAULT_IOSCHED="anticipatory"
|
||||
|
||||
#
|
||||
# System type
|
||||
#
|
||||
|
@ -58,9 +81,7 @@ CONFIG_CC_ALIGN_JUMPS=0
|
|||
# CONFIG_SH_7751_SYSTEMH is not set
|
||||
# CONFIG_SH_STB1_HARP is not set
|
||||
# CONFIG_SH_STB1_OVERDRIVE is not set
|
||||
# CONFIG_SH_HP620 is not set
|
||||
CONFIG_SH_HP680=y
|
||||
# CONFIG_SH_HP690 is not set
|
||||
CONFIG_SH_HP6XX=y
|
||||
# CONFIG_SH_CQREEK is not set
|
||||
# CONFIG_SH_DMIDA is not set
|
||||
# CONFIG_SH_EC3104 is not set
|
||||
|
@ -77,43 +98,90 @@ CONFIG_SH_HP680=y
|
|||
# CONFIG_SH_RTS7751R2D is not set
|
||||
# CONFIG_SH_EDOSK7705 is not set
|
||||
# CONFIG_SH_SH4202_MICRODEV is not set
|
||||
# CONFIG_SH_LANDISK is not set
|
||||
# CONFIG_SH_TITAN is not set
|
||||
# CONFIG_SH_UNKNOWN is not set
|
||||
# CONFIG_CPU_SH2 is not set
|
||||
|
||||
#
|
||||
# Processor selection
|
||||
#
|
||||
CONFIG_CPU_SH3=y
|
||||
# CONFIG_CPU_SH4 is not set
|
||||
|
||||
#
|
||||
# SH-2 Processor Support
|
||||
#
|
||||
# CONFIG_CPU_SUBTYPE_SH7604 is not set
|
||||
|
||||
#
|
||||
# SH-3 Processor Support
|
||||
#
|
||||
# CONFIG_CPU_SUBTYPE_SH7300 is not set
|
||||
# CONFIG_CPU_SUBTYPE_SH7705 is not set
|
||||
# CONFIG_CPU_SUBTYPE_SH7707 is not set
|
||||
# CONFIG_CPU_SUBTYPE_SH7708 is not set
|
||||
CONFIG_CPU_SUBTYPE_SH7709=y
|
||||
|
||||
#
|
||||
# SH-4 Processor Support
|
||||
#
|
||||
# CONFIG_CPU_SUBTYPE_SH7750 is not set
|
||||
# CONFIG_CPU_SUBTYPE_SH7091 is not set
|
||||
# CONFIG_CPU_SUBTYPE_SH7750R is not set
|
||||
# CONFIG_CPU_SUBTYPE_SH7750S is not set
|
||||
# CONFIG_CPU_SUBTYPE_SH7751 is not set
|
||||
# CONFIG_CPU_SUBTYPE_SH7751R is not set
|
||||
# CONFIG_CPU_SUBTYPE_SH7760 is not set
|
||||
# CONFIG_CPU_SUBTYPE_SH73180 is not set
|
||||
# CONFIG_CPU_SUBTYPE_SH4_202 is not set
|
||||
|
||||
#
|
||||
# ST40 Processor Support
|
||||
#
|
||||
# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
|
||||
# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
|
||||
# CONFIG_CPU_SUBTYPE_SH4_202 is not set
|
||||
|
||||
#
|
||||
# SH-4A Processor Support
|
||||
#
|
||||
# CONFIG_CPU_SUBTYPE_SH73180 is not set
|
||||
# CONFIG_CPU_SUBTYPE_SH7770 is not set
|
||||
# CONFIG_CPU_SUBTYPE_SH7780 is not set
|
||||
|
||||
#
|
||||
# Memory management options
|
||||
#
|
||||
CONFIG_MMU=y
|
||||
# CONFIG_CMDLINE_BOOL is not set
|
||||
CONFIG_SELECT_MEMORY_MODEL=y
|
||||
CONFIG_FLATMEM_MANUAL=y
|
||||
# CONFIG_DISCONTIGMEM_MANUAL is not set
|
||||
# CONFIG_SPARSEMEM_MANUAL is not set
|
||||
CONFIG_FLATMEM=y
|
||||
CONFIG_FLAT_NODE_MEM_MAP=y
|
||||
# CONFIG_SPARSEMEM_STATIC is not set
|
||||
CONFIG_SPLIT_PTLOCK_CPUS=4
|
||||
|
||||
#
|
||||
# Cache configuration
|
||||
#
|
||||
# CONFIG_SH_DIRECT_MAPPED is not set
|
||||
# CONFIG_SH_WRITETHROUGH is not set
|
||||
# CONFIG_SH_OCRAM is not set
|
||||
CONFIG_MEMORY_START=0x0c000000
|
||||
CONFIG_MEMORY_SIZE=0x00400000
|
||||
CONFIG_MEMORY_SET=y
|
||||
# CONFIG_MEMORY_OVERRIDE is not set
|
||||
|
||||
#
|
||||
# Processor features
|
||||
#
|
||||
CONFIG_CPU_LITTLE_ENDIAN=y
|
||||
CONFIG_SH_RTC=y
|
||||
# CONFIG_SH_DSP is not set
|
||||
CONFIG_SH_ADC=y
|
||||
CONFIG_SH_HP600=y
|
||||
CONFIG_ZERO_PAGE_OFFSET=0x00001000
|
||||
CONFIG_BOOT_LINK_OFFSET=0x00800000
|
||||
CONFIG_CPU_LITTLE_ENDIAN=y
|
||||
# CONFIG_PREEMPT is not set
|
||||
# CONFIG_UBC_WAKEUP is not set
|
||||
# CONFIG_SH_WRITETHROUGH is not set
|
||||
# CONFIG_SH_OCRAM is not set
|
||||
# CONFIG_SMP is not set
|
||||
CONFIG_SH_PCLK_CALC=y
|
||||
CONFIG_SH_PCLK_FREQ=1193182
|
||||
|
||||
#
|
||||
# Timer support
|
||||
#
|
||||
CONFIG_SH_TMU=y
|
||||
CONFIG_SH_PCLK_FREQ_BOOL=y
|
||||
CONFIG_SH_PCLK_FREQ=22110000
|
||||
|
||||
#
|
||||
# CPU Frequency scaling
|
||||
|
@ -123,7 +191,10 @@ CONFIG_SH_PCLK_FREQ=1193182
|
|||
#
|
||||
# DMA support
|
||||
#
|
||||
# CONFIG_SH_DMA is not set
|
||||
CONFIG_SH_DMA=y
|
||||
CONFIG_NR_ONCHIP_DMA_CHANNELS=4
|
||||
# CONFIG_NR_DMA_CHANNELS_BOOL is not set
|
||||
# CONFIG_DMA_PAGE_OPS is not set
|
||||
|
||||
#
|
||||
# Companion Chips
|
||||
|
@ -132,21 +203,47 @@ CONFIG_HD6446X_SERIES=y
|
|||
CONFIG_HD64461=y
|
||||
# CONFIG_HD64465 is not set
|
||||
CONFIG_HD64461_IRQ=36
|
||||
# CONFIG_HD64461_ENABLER is not set
|
||||
CONFIG_HD64461_IOBASE=0xb0000000
|
||||
CONFIG_HD64461_ENABLER=y
|
||||
|
||||
#
|
||||
# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
|
||||
# Kernel features
|
||||
#
|
||||
# CONFIG_KEXEC is not set
|
||||
# CONFIG_PREEMPT is not set
|
||||
# CONFIG_SMP is not set
|
||||
|
||||
#
|
||||
# Boot options
|
||||
#
|
||||
CONFIG_ZERO_PAGE_OFFSET=0x00001000
|
||||
CONFIG_BOOT_LINK_OFFSET=0x00800000
|
||||
# CONFIG_UBC_WAKEUP is not set
|
||||
# CONFIG_CMDLINE_BOOL is not set
|
||||
|
||||
#
|
||||
# Bus options
|
||||
#
|
||||
CONFIG_ISA=y
|
||||
# CONFIG_PCI is not set
|
||||
|
||||
#
|
||||
# PCCARD (PCMCIA/CardBus) support
|
||||
#
|
||||
# CONFIG_PCCARD is not set
|
||||
CONFIG_PCCARD=y
|
||||
# CONFIG_PCMCIA_DEBUG is not set
|
||||
CONFIG_PCMCIA=y
|
||||
CONFIG_PCMCIA_LOAD_CIS=y
|
||||
CONFIG_PCMCIA_IOCTL=y
|
||||
|
||||
#
|
||||
# PC-card bridges
|
||||
#
|
||||
# CONFIG_I82365 is not set
|
||||
# CONFIG_TCIC is not set
|
||||
CONFIG_HD64461_PCMCIA=y
|
||||
CONFIG_HD64461_PCMCIA_SOCKETS=1
|
||||
CONFIG_PCMCIA_PROBE=y
|
||||
|
||||
#
|
||||
# PCI Hotplug Support
|
||||
|
@ -160,9 +257,9 @@ CONFIG_BINFMT_ELF=y
|
|||
# CONFIG_BINFMT_MISC is not set
|
||||
|
||||
#
|
||||
# SH initrd options
|
||||
# Networking
|
||||
#
|
||||
# CONFIG_EMBEDDED_RAMDISK is not set
|
||||
# CONFIG_NET is not set
|
||||
|
||||
#
|
||||
# Device Drivers
|
||||
|
@ -173,7 +270,11 @@ CONFIG_BINFMT_ELF=y
|
|||
#
|
||||
# CONFIG_STANDALONE is not set
|
||||
CONFIG_PREVENT_FIRMWARE_BUILD=y
|
||||
# CONFIG_FW_LOADER is not set
|
||||
CONFIG_FW_LOADER=y
|
||||
|
||||
#
|
||||
# Connector - unified userspace <-> kernelspace linker
|
||||
#
|
||||
|
||||
#
|
||||
# Memory Technology Devices (MTD)
|
||||
|
@ -188,29 +289,19 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
|
|||
#
|
||||
# Plug and Play support
|
||||
#
|
||||
# CONFIG_PNP is not set
|
||||
|
||||
#
|
||||
# Block devices
|
||||
#
|
||||
# CONFIG_BLK_DEV_FD is not set
|
||||
# CONFIG_BLK_DEV_COW_COMMON is not set
|
||||
# CONFIG_BLK_DEV_LOOP is not set
|
||||
CONFIG_BLK_DEV_RAM=y
|
||||
CONFIG_BLK_DEV_RAM_COUNT=16
|
||||
CONFIG_BLK_DEV_RAM_SIZE=4096
|
||||
CONFIG_BLK_DEV_INITRD=y
|
||||
CONFIG_INITRAMFS_SOURCE=""
|
||||
# CONFIG_LBD is not set
|
||||
# CONFIG_CDROM_PKTCDVD is not set
|
||||
|
||||
#
|
||||
# IO Schedulers
|
||||
#
|
||||
CONFIG_IOSCHED_NOOP=y
|
||||
CONFIG_IOSCHED_AS=y
|
||||
CONFIG_IOSCHED_DEADLINE=y
|
||||
CONFIG_IOSCHED_CFQ=y
|
||||
|
||||
#
|
||||
# ATA/ATAPI/MFM/RLL support
|
||||
#
|
||||
|
@ -224,6 +315,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_IDECS is not set
|
||||
# CONFIG_BLK_DEV_IDECD is not set
|
||||
# CONFIG_BLK_DEV_IDETAPE is not set
|
||||
# CONFIG_BLK_DEV_IDEFLOPPY is not set
|
||||
|
@ -235,6 +327,7 @@ CONFIG_BLK_DEV_IDEDISK=y
|
|||
CONFIG_IDE_GENERIC=y
|
||||
CONFIG_IDE_SH=y
|
||||
# CONFIG_IDE_ARM is not set
|
||||
# CONFIG_IDE_CHIPSETS is not set
|
||||
# CONFIG_BLK_DEV_IDEDMA is not set
|
||||
# CONFIG_IDEDMA_AUTO is not set
|
||||
# CONFIG_BLK_DEV_HD is not set
|
||||
|
@ -242,8 +335,14 @@ CONFIG_IDE_SH=y
|
|||
#
|
||||
# SCSI device support
|
||||
#
|
||||
# CONFIG_RAID_ATTRS is not set
|
||||
# CONFIG_SCSI is not set
|
||||
|
||||
#
|
||||
# Old CD-ROM drivers (not SCSI, not IDE)
|
||||
#
|
||||
# CONFIG_CD_NO_IDESCSI is not set
|
||||
|
||||
#
|
||||
# Multi-device support (RAID and LVM)
|
||||
#
|
||||
|
@ -252,6 +351,7 @@ CONFIG_IDE_SH=y
|
|||
#
|
||||
# Fusion MPT device support
|
||||
#
|
||||
# CONFIG_FUSION is not set
|
||||
|
||||
#
|
||||
# IEEE 1394 (FireWire) support
|
||||
|
@ -263,9 +363,8 @@ CONFIG_IDE_SH=y
|
|||
#
|
||||
|
||||
#
|
||||
# Networking support
|
||||
# Network device support
|
||||
#
|
||||
# CONFIG_NET is not set
|
||||
# CONFIG_NETPOLL is not set
|
||||
# CONFIG_NET_POLL_CONTROLLER is not set
|
||||
|
||||
|
@ -295,17 +394,6 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
|
|||
# CONFIG_INPUT_EVDEV is not set
|
||||
# CONFIG_INPUT_EVBUG is not set
|
||||
|
||||
#
|
||||
# Input I/O drivers
|
||||
#
|
||||
# CONFIG_GAMEPORT is not set
|
||||
CONFIG_SOUND_GAMEPORT=y
|
||||
CONFIG_SERIO=y
|
||||
# CONFIG_SERIO_I8042 is not set
|
||||
# CONFIG_SERIO_SERPORT is not set
|
||||
# CONFIG_SERIO_CT82C710 is not set
|
||||
# CONFIG_SERIO_RAW is not set
|
||||
|
||||
#
|
||||
# Input Device Drivers
|
||||
#
|
||||
|
@ -315,6 +403,15 @@ CONFIG_SERIO=y
|
|||
# CONFIG_INPUT_TOUCHSCREEN is not set
|
||||
# CONFIG_INPUT_MISC is not set
|
||||
|
||||
#
|
||||
# Hardware I/O ports
|
||||
#
|
||||
CONFIG_SERIO=y
|
||||
# CONFIG_SERIO_I8042 is not set
|
||||
# CONFIG_SERIO_SERPORT is not set
|
||||
# CONFIG_SERIO_RAW is not set
|
||||
# CONFIG_GAMEPORT is not set
|
||||
|
||||
#
|
||||
# Character devices
|
||||
#
|
||||
|
@ -353,9 +450,21 @@ CONFIG_LEGACY_PTY_COUNT=256
|
|||
#
|
||||
# Ftape, the floppy tape device driver
|
||||
#
|
||||
# CONFIG_DRM is not set
|
||||
|
||||
#
|
||||
# PCMCIA character devices
|
||||
#
|
||||
# CONFIG_SYNCLINK_CS is not set
|
||||
# CONFIG_CARDMAN_4000 is not set
|
||||
# CONFIG_CARDMAN_4040 is not set
|
||||
# CONFIG_RAW_DRIVER is not set
|
||||
|
||||
#
|
||||
# TPM devices
|
||||
#
|
||||
# CONFIG_TCG_TPM is not set
|
||||
# CONFIG_TELCLOCK is not set
|
||||
|
||||
#
|
||||
# I2C support
|
||||
#
|
||||
|
@ -366,10 +475,21 @@ CONFIG_LEGACY_PTY_COUNT=256
|
|||
#
|
||||
# CONFIG_W1 is not set
|
||||
|
||||
#
|
||||
# Hardware Monitoring support
|
||||
#
|
||||
CONFIG_HWMON=y
|
||||
# CONFIG_HWMON_VID is not set
|
||||
# CONFIG_HWMON_DEBUG_CHIP is not set
|
||||
|
||||
#
|
||||
# Misc devices
|
||||
#
|
||||
|
||||
#
|
||||
# Multimedia Capabilities Port drivers
|
||||
#
|
||||
|
||||
#
|
||||
# Multimedia devices
|
||||
#
|
||||
|
@ -383,27 +503,35 @@ CONFIG_LEGACY_PTY_COUNT=256
|
|||
# Graphics support
|
||||
#
|
||||
CONFIG_FB=y
|
||||
CONFIG_FB_CFB_FILLRECT=y
|
||||
CONFIG_FB_CFB_COPYAREA=y
|
||||
CONFIG_FB_CFB_IMAGEBLIT=y
|
||||
# CONFIG_FB_MACMODES is not set
|
||||
# CONFIG_FB_MODE_HELPERS is not set
|
||||
# CONFIG_FB_TILEBLITTING is not set
|
||||
# CONFIG_FB_EPSON1355 is not set
|
||||
# CONFIG_FB_S1D13XXX is not set
|
||||
CONFIG_FB_HIT=y
|
||||
# CONFIG_FB_VIRTUAL is not set
|
||||
|
||||
#
|
||||
# Console display driver support
|
||||
#
|
||||
# CONFIG_VGA_CONSOLE is not set
|
||||
# CONFIG_MDA_CONSOLE is not set
|
||||
CONFIG_DUMMY_CONSOLE=y
|
||||
CONFIG_FRAMEBUFFER_CONSOLE=y
|
||||
# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
|
||||
CONFIG_FONTS=y
|
||||
# CONFIG_FONT_8x8 is not set
|
||||
# CONFIG_FONT_8x16 is not set
|
||||
# CONFIG_FONT_6x11 is not set
|
||||
# CONFIG_FONT_7x14 is not set
|
||||
CONFIG_FONT_PEARL_8x8=y
|
||||
# CONFIG_FONT_ACORN_8x8 is not set
|
||||
# CONFIG_FONT_MINI_4x6 is not set
|
||||
# CONFIG_FONT_SUN8x16 is not set
|
||||
# CONFIG_FONT_SUN12x22 is not set
|
||||
# CONFIG_FONT_10x18 is not set
|
||||
|
||||
#
|
||||
# Logo configuration
|
||||
|
@ -414,7 +542,22 @@ CONFIG_FONT_PEARL_8x8=y
|
|||
#
|
||||
# Sound
|
||||
#
|
||||
# CONFIG_SOUND is not set
|
||||
CONFIG_SOUND=y
|
||||
|
||||
#
|
||||
# Advanced Linux Sound Architecture
|
||||
#
|
||||
# CONFIG_SND is not set
|
||||
|
||||
#
|
||||
# Open Sound System
|
||||
#
|
||||
CONFIG_SOUND_PRIME=y
|
||||
# CONFIG_OBSOLETE_OSS_DRIVER is not set
|
||||
# CONFIG_SOUND_MSNDCLAS is not set
|
||||
# CONFIG_SOUND_MSNDPIN is not set
|
||||
CONFIG_SOUND_SH_DAC_AUDIO=y
|
||||
CONFIG_SOUND_SH_DAC_AUDIO_CHANNEL=1
|
||||
|
||||
#
|
||||
# USB support
|
||||
|
@ -423,7 +566,7 @@ CONFIG_FONT_PEARL_8x8=y
|
|||
# CONFIG_USB_ARCH_HAS_OHCI is not set
|
||||
|
||||
#
|
||||
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
|
||||
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
|
||||
#
|
||||
|
||||
#
|
||||
|
@ -441,26 +584,30 @@ CONFIG_FONT_PEARL_8x8=y
|
|||
#
|
||||
# CONFIG_INFINIBAND is not set
|
||||
|
||||
#
|
||||
# SN Devices
|
||||
#
|
||||
|
||||
#
|
||||
# File systems
|
||||
#
|
||||
CONFIG_EXT2_FS=y
|
||||
# CONFIG_EXT2_FS_XATTR is not set
|
||||
# CONFIG_EXT2_FS_XIP is not set
|
||||
# CONFIG_EXT3_FS is not set
|
||||
# CONFIG_JBD is not set
|
||||
# CONFIG_REISERFS_FS is not set
|
||||
# CONFIG_JFS_FS is not set
|
||||
|
||||
#
|
||||
# XFS support
|
||||
#
|
||||
# CONFIG_FS_POSIX_ACL is not set
|
||||
# CONFIG_XFS_FS is not set
|
||||
# CONFIG_MINIX_FS is not set
|
||||
# CONFIG_ROMFS_FS is not set
|
||||
CONFIG_INOTIFY=y
|
||||
# CONFIG_QUOTA is not set
|
||||
CONFIG_DNOTIFY=y
|
||||
# CONFIG_AUTOFS_FS is not set
|
||||
# CONFIG_AUTOFS4_FS is not set
|
||||
# CONFIG_FUSE_FS is not set
|
||||
|
||||
#
|
||||
# CD-ROM/DVD Filesystems
|
||||
|
@ -471,8 +618,11 @@ CONFIG_DNOTIFY=y
|
|||
#
|
||||
# DOS/FAT/NT Filesystems
|
||||
#
|
||||
CONFIG_FAT_FS=y
|
||||
# CONFIG_MSDOS_FS is not set
|
||||
# CONFIG_VFAT_FS is not set
|
||||
CONFIG_VFAT_FS=y
|
||||
CONFIG_FAT_DEFAULT_CODEPAGE=437
|
||||
CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
|
||||
# CONFIG_NTFS_FS is not set
|
||||
|
||||
#
|
||||
|
@ -481,14 +631,11 @@ CONFIG_DNOTIFY=y
|
|||
CONFIG_PROC_FS=y
|
||||
CONFIG_PROC_KCORE=y
|
||||
CONFIG_SYSFS=y
|
||||
CONFIG_DEVFS_FS=y
|
||||
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
|
||||
# CONFIG_RELAYFS_FS is not set
|
||||
|
||||
#
|
||||
# Miscellaneous filesystems
|
||||
|
@ -516,7 +663,46 @@ CONFIG_MSDOS_PARTITION=y
|
|||
#
|
||||
# Native Language Support
|
||||
#
|
||||
# CONFIG_NLS is not set
|
||||
CONFIG_NLS=y
|
||||
CONFIG_NLS_DEFAULT="iso8859-1"
|
||||
# CONFIG_NLS_CODEPAGE_437 is not set
|
||||
# CONFIG_NLS_CODEPAGE_737 is not set
|
||||
# CONFIG_NLS_CODEPAGE_775 is not set
|
||||
# CONFIG_NLS_CODEPAGE_850 is not set
|
||||
# CONFIG_NLS_CODEPAGE_852 is not set
|
||||
# CONFIG_NLS_CODEPAGE_855 is not set
|
||||
# CONFIG_NLS_CODEPAGE_857 is not set
|
||||
# CONFIG_NLS_CODEPAGE_860 is not set
|
||||
# CONFIG_NLS_CODEPAGE_861 is not set
|
||||
# CONFIG_NLS_CODEPAGE_862 is not set
|
||||
# CONFIG_NLS_CODEPAGE_863 is not set
|
||||
# CONFIG_NLS_CODEPAGE_864 is not set
|
||||
# CONFIG_NLS_CODEPAGE_865 is not set
|
||||
# CONFIG_NLS_CODEPAGE_866 is not set
|
||||
# CONFIG_NLS_CODEPAGE_869 is not set
|
||||
# CONFIG_NLS_CODEPAGE_936 is not set
|
||||
# CONFIG_NLS_CODEPAGE_950 is not set
|
||||
# CONFIG_NLS_CODEPAGE_932 is not set
|
||||
# CONFIG_NLS_CODEPAGE_949 is not set
|
||||
# CONFIG_NLS_CODEPAGE_874 is not set
|
||||
# CONFIG_NLS_ISO8859_8 is not set
|
||||
# CONFIG_NLS_CODEPAGE_1250 is not set
|
||||
# CONFIG_NLS_CODEPAGE_1251 is not set
|
||||
# CONFIG_NLS_ASCII is not set
|
||||
# CONFIG_NLS_ISO8859_1 is not set
|
||||
# CONFIG_NLS_ISO8859_2 is not set
|
||||
# CONFIG_NLS_ISO8859_3 is not set
|
||||
# CONFIG_NLS_ISO8859_4 is not set
|
||||
# CONFIG_NLS_ISO8859_5 is not set
|
||||
# CONFIG_NLS_ISO8859_6 is not set
|
||||
# CONFIG_NLS_ISO8859_7 is not set
|
||||
# CONFIG_NLS_ISO8859_9 is not set
|
||||
# CONFIG_NLS_ISO8859_13 is not set
|
||||
# CONFIG_NLS_ISO8859_14 is not set
|
||||
# CONFIG_NLS_ISO8859_15 is not set
|
||||
# CONFIG_NLS_KOI8_R is not set
|
||||
# CONFIG_NLS_KOI8_U is not set
|
||||
# CONFIG_NLS_UTF8 is not set
|
||||
|
||||
#
|
||||
# Profiling support
|
||||
|
@ -526,7 +712,9 @@ CONFIG_MSDOS_PARTITION=y
|
|||
#
|
||||
# Kernel hacking
|
||||
#
|
||||
# CONFIG_PRINTK_TIME is not set
|
||||
# CONFIG_DEBUG_KERNEL is not set
|
||||
CONFIG_LOG_BUF_SHIFT=14
|
||||
# CONFIG_FRAME_POINTER is not set
|
||||
# CONFIG_SH_STANDARD_BIOS is not set
|
||||
# CONFIG_KGDB is not set
|
||||
|
@ -550,5 +738,6 @@ CONFIG_MSDOS_PARTITION=y
|
|||
# Library routines
|
||||
#
|
||||
# CONFIG_CRC_CCITT is not set
|
||||
# CONFIG_CRC16 is not set
|
||||
CONFIG_CRC32=y
|
||||
# CONFIG_LIBCRC32C is not set
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* SuperH-specific DMA management API
|
||||
*
|
||||
* Copyright (C) 2003, 2004 Paul Mundt
|
||||
* Copyright (C) 2003, 2004, 2005 Paul Mundt
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
|
@ -15,6 +15,7 @@
|
|||
#include <linux/spinlock.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <asm/dma.h>
|
||||
|
||||
DEFINE_SPINLOCK(dma_spin_lock);
|
||||
|
@ -55,16 +56,14 @@ static LIST_HEAD(registered_dmac_list);
|
|||
|
||||
struct dma_info *get_dma_info(unsigned int chan)
|
||||
{
|
||||
struct list_head *pos, *tmp;
|
||||
struct dma_info *info;
|
||||
unsigned int total = 0;
|
||||
|
||||
/*
|
||||
* Look for each DMAC's range to determine who the owner of
|
||||
* the channel is.
|
||||
*/
|
||||
list_for_each_safe(pos, tmp, ®istered_dmac_list) {
|
||||
struct dma_info *info = list_entry(pos, struct dma_info, list);
|
||||
|
||||
list_for_each_entry(info, ®istered_dmac_list, list) {
|
||||
total += info->nr_channels;
|
||||
if (chan > total)
|
||||
continue;
|
||||
|
@ -75,6 +74,20 @@ struct dma_info *get_dma_info(unsigned int chan)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static unsigned int get_nr_channels(void)
|
||||
{
|
||||
struct dma_info *info;
|
||||
unsigned int nr = 0;
|
||||
|
||||
if (unlikely(list_empty(®istered_dmac_list)))
|
||||
return nr;
|
||||
|
||||
list_for_each_entry(info, ®istered_dmac_list, list)
|
||||
nr += info->nr_channels;
|
||||
|
||||
return nr;
|
||||
}
|
||||
|
||||
struct dma_channel *get_dma_channel(unsigned int chan)
|
||||
{
|
||||
struct dma_info *info = get_dma_info(chan);
|
||||
|
@ -173,7 +186,7 @@ int dma_xfer(unsigned int chan, unsigned long from,
|
|||
static int dma_read_proc(char *buf, char **start, off_t off,
|
||||
int len, int *eof, void *data)
|
||||
{
|
||||
struct list_head *pos, *tmp;
|
||||
struct dma_info *info;
|
||||
char *p = buf;
|
||||
|
||||
if (list_empty(®istered_dmac_list))
|
||||
|
@ -182,8 +195,7 @@ static int dma_read_proc(char *buf, char **start, off_t off,
|
|||
/*
|
||||
* Iterate over each registered DMAC
|
||||
*/
|
||||
list_for_each_safe(pos, tmp, ®istered_dmac_list) {
|
||||
struct dma_info *info = list_entry(pos, struct dma_info, list);
|
||||
list_for_each_entry(info, ®istered_dmac_list, list) {
|
||||
int i;
|
||||
|
||||
/*
|
||||
|
@ -205,9 +217,9 @@ static int dma_read_proc(char *buf, char **start, off_t off,
|
|||
#endif
|
||||
|
||||
|
||||
int __init register_dmac(struct dma_info *info)
|
||||
int register_dmac(struct dma_info *info)
|
||||
{
|
||||
int i;
|
||||
unsigned int total_channels, i;
|
||||
|
||||
INIT_LIST_HEAD(&info->list);
|
||||
|
||||
|
@ -217,6 +229,11 @@ int __init register_dmac(struct dma_info *info)
|
|||
|
||||
BUG_ON((info->flags & DMAC_CHANNELS_CONFIGURED) && !info->channels);
|
||||
|
||||
info->pdev = platform_device_register_simple((char *)info->name, -1,
|
||||
NULL, 0);
|
||||
if (IS_ERR(info->pdev))
|
||||
return PTR_ERR(info->pdev);
|
||||
|
||||
/*
|
||||
* Don't touch pre-configured channels
|
||||
*/
|
||||
|
@ -232,10 +249,12 @@ int __init register_dmac(struct dma_info *info)
|
|||
memset(info->channels, 0, size);
|
||||
}
|
||||
|
||||
total_channels = get_nr_channels();
|
||||
for (i = 0; i < info->nr_channels; i++) {
|
||||
struct dma_channel *chan = info->channels + i;
|
||||
|
||||
chan->chan = i;
|
||||
chan->vchan = i + total_channels;
|
||||
|
||||
memcpy(chan->dev_id, "Unused", 7);
|
||||
|
||||
|
@ -245,9 +264,7 @@ int __init register_dmac(struct dma_info *info)
|
|||
init_MUTEX(&chan->sem);
|
||||
init_waitqueue_head(&chan->wait_queue);
|
||||
|
||||
#ifdef CONFIG_SYSFS
|
||||
dma_create_sysfs_files(chan);
|
||||
#endif
|
||||
dma_create_sysfs_files(chan, info);
|
||||
}
|
||||
|
||||
list_add(&info->list, ®istered_dmac_list);
|
||||
|
@ -255,12 +272,18 @@ int __init register_dmac(struct dma_info *info)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void __exit unregister_dmac(struct dma_info *info)
|
||||
void unregister_dmac(struct dma_info *info)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < info->nr_channels; i++)
|
||||
dma_remove_sysfs_files(info->channels + i, info);
|
||||
|
||||
if (!(info->flags & DMAC_CHANNELS_CONFIGURED))
|
||||
kfree(info->channels);
|
||||
|
||||
list_del(&info->list);
|
||||
platform_device_unregister(info->pdev);
|
||||
}
|
||||
|
||||
static int __init dma_api_init(void)
|
||||
|
|
|
@ -140,7 +140,7 @@ static struct dma_ops g2_dma_ops = {
|
|||
};
|
||||
|
||||
static struct dma_info g2_dma_info = {
|
||||
.name = "G2 DMA",
|
||||
.name = "g2_dmac",
|
||||
.nr_channels = 4,
|
||||
.ops = &g2_dma_ops,
|
||||
.flags = DMAC_CHANNELS_TEI_CAPABLE,
|
||||
|
@ -160,6 +160,7 @@ static int __init g2_dma_init(void)
|
|||
static void __exit g2_dma_exit(void)
|
||||
{
|
||||
free_irq(HW_EVENT_G2_DMA, 0);
|
||||
unregister_dmac(&g2_dma_info);
|
||||
}
|
||||
|
||||
subsys_initcall(g2_dma_init);
|
||||
|
|
|
@ -25,14 +25,14 @@
|
|||
* such, this code is meant for only the simplest of tasks (and shouldn't be
|
||||
* used in any new drivers at all).
|
||||
*
|
||||
* It should also be noted that various functions here are labelled as
|
||||
* being deprecated. This is due to the fact that the ops->xfer() method is
|
||||
* the preferred way of doing things (as well as just grabbing the spinlock
|
||||
* directly). As such, any users of this interface will be warned rather
|
||||
* loudly.
|
||||
* NOTE: ops->xfer() is the preferred way of doing things. However, there
|
||||
* are some users of the ISA DMA API that exist in common code that we
|
||||
* don't necessarily want to go out of our way to break, so we still
|
||||
* allow for some compatability at that level. Any new code is strongly
|
||||
* advised to run far away from the ISA DMA API and use the SH DMA API
|
||||
* directly.
|
||||
*/
|
||||
|
||||
unsigned long __deprecated claim_dma_lock(void)
|
||||
unsigned long claim_dma_lock(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
|
@ -42,19 +42,19 @@ unsigned long __deprecated claim_dma_lock(void)
|
|||
}
|
||||
EXPORT_SYMBOL(claim_dma_lock);
|
||||
|
||||
void __deprecated release_dma_lock(unsigned long flags)
|
||||
void release_dma_lock(unsigned long flags)
|
||||
{
|
||||
spin_unlock_irqrestore(&dma_spin_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL(release_dma_lock);
|
||||
|
||||
void __deprecated disable_dma(unsigned int chan)
|
||||
void disable_dma(unsigned int chan)
|
||||
{
|
||||
/* Nothing */
|
||||
}
|
||||
EXPORT_SYMBOL(disable_dma);
|
||||
|
||||
void __deprecated enable_dma(unsigned int chan)
|
||||
void enable_dma(unsigned int chan)
|
||||
{
|
||||
struct dma_info *info = get_dma_info(chan);
|
||||
struct dma_channel *channel = &info->channels[chan];
|
||||
|
|
|
@ -80,7 +80,7 @@ static struct dma_ops pvr2_dma_ops = {
|
|||
};
|
||||
|
||||
static struct dma_info pvr2_dma_info = {
|
||||
.name = "PowerVR 2 DMA",
|
||||
.name = "pvr2_dmac",
|
||||
.nr_channels = 1,
|
||||
.ops = &pvr2_dma_ops,
|
||||
.flags = DMAC_CHANNELS_TEI_CAPABLE,
|
||||
|
@ -98,6 +98,7 @@ static void __exit pvr2_dma_exit(void)
|
|||
{
|
||||
free_dma(PVR2_CASCADE_CHAN);
|
||||
free_irq(HW_EVENT_PVR2_DMA, 0);
|
||||
unregister_dmac(&pvr2_dma_info);
|
||||
}
|
||||
|
||||
subsys_initcall(pvr2_dma_init);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*
|
||||
* Copyright (C) 2000 Takashi YOSHII
|
||||
* Copyright (C) 2003, 2004 Paul Mundt
|
||||
* Copyright (C) 2005 Andriy Skulysh
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
|
@ -16,51 +17,28 @@
|
|||
#include <linux/irq.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/module.h>
|
||||
#include <asm/dreamcast/dma.h>
|
||||
#include <asm/signal.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/dma.h>
|
||||
#include <asm/io.h>
|
||||
#include "dma-sh.h"
|
||||
|
||||
/*
|
||||
* The SuperH DMAC supports a number of transmit sizes, we list them here,
|
||||
* with their respective values as they appear in the CHCR registers.
|
||||
*
|
||||
* Defaults to a 64-bit transfer size.
|
||||
*/
|
||||
enum {
|
||||
XMIT_SZ_64BIT,
|
||||
XMIT_SZ_8BIT,
|
||||
XMIT_SZ_16BIT,
|
||||
XMIT_SZ_32BIT,
|
||||
XMIT_SZ_256BIT,
|
||||
};
|
||||
|
||||
/*
|
||||
* The DMA count is defined as the number of bytes to transfer.
|
||||
*/
|
||||
static unsigned int ts_shift[] = {
|
||||
[XMIT_SZ_64BIT] = 3,
|
||||
[XMIT_SZ_8BIT] = 0,
|
||||
[XMIT_SZ_16BIT] = 1,
|
||||
[XMIT_SZ_32BIT] = 2,
|
||||
[XMIT_SZ_256BIT] = 5,
|
||||
};
|
||||
|
||||
static inline unsigned int get_dmte_irq(unsigned int chan)
|
||||
{
|
||||
unsigned int irq;
|
||||
unsigned int irq = 0;
|
||||
|
||||
/*
|
||||
* Normally we could just do DMTE0_IRQ + chan outright, though in the
|
||||
* case of the 7751R, the DMTE IRQs for channels > 4 start right above
|
||||
* the SCIF
|
||||
*/
|
||||
|
||||
if (chan < 4) {
|
||||
irq = DMTE0_IRQ + chan;
|
||||
} else {
|
||||
#ifdef DMTE4_IRQ
|
||||
irq = DMTE4_IRQ + chan - 4;
|
||||
#endif
|
||||
}
|
||||
|
||||
return irq;
|
||||
|
@ -78,9 +56,7 @@ static inline unsigned int calc_xmit_shift(struct dma_channel *chan)
|
|||
{
|
||||
u32 chcr = ctrl_inl(CHCR[chan->chan]);
|
||||
|
||||
chcr >>= 4;
|
||||
|
||||
return ts_shift[chcr & 0x0007];
|
||||
return ts_shift[(chcr & CHCR_TS_MASK)>>CHCR_TS_SHIFT];
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -109,8 +85,13 @@ static irqreturn_t dma_tei(int irq, void *dev_id, struct pt_regs *regs)
|
|||
|
||||
static int sh_dmac_request_dma(struct dma_channel *chan)
|
||||
{
|
||||
char name[32];
|
||||
|
||||
snprintf(name, sizeof(name), "DMAC Transfer End (Channel %d)",
|
||||
chan->chan);
|
||||
|
||||
return request_irq(get_dmte_irq(chan->chan), dma_tei,
|
||||
SA_INTERRUPT, "DMAC Transfer End", chan);
|
||||
SA_INTERRUPT, name, chan);
|
||||
}
|
||||
|
||||
static void sh_dmac_free_dma(struct dma_channel *chan)
|
||||
|
@ -118,10 +99,18 @@ static void sh_dmac_free_dma(struct dma_channel *chan)
|
|||
free_irq(get_dmte_irq(chan->chan), chan);
|
||||
}
|
||||
|
||||
static void sh_dmac_configure_channel(struct dma_channel *chan, unsigned long chcr)
|
||||
static void
|
||||
sh_dmac_configure_channel(struct dma_channel *chan, unsigned long chcr)
|
||||
{
|
||||
if (!chcr)
|
||||
chcr = RS_DUAL;
|
||||
chcr = RS_DUAL | CHCR_IE;
|
||||
|
||||
if (chcr & CHCR_IE) {
|
||||
chcr &= ~CHCR_IE;
|
||||
chan->flags |= DMA_TEI_CAPABLE;
|
||||
} else {
|
||||
chan->flags &= ~DMA_TEI_CAPABLE;
|
||||
}
|
||||
|
||||
ctrl_outl(chcr, CHCR[chan->chan]);
|
||||
|
||||
|
@ -130,22 +119,32 @@ static void sh_dmac_configure_channel(struct dma_channel *chan, unsigned long ch
|
|||
|
||||
static void sh_dmac_enable_dma(struct dma_channel *chan)
|
||||
{
|
||||
int irq = get_dmte_irq(chan->chan);
|
||||
int irq;
|
||||
u32 chcr;
|
||||
|
||||
chcr = ctrl_inl(CHCR[chan->chan]);
|
||||
chcr |= CHCR_DE | CHCR_IE;
|
||||
chcr |= CHCR_DE;
|
||||
|
||||
if (chan->flags & DMA_TEI_CAPABLE)
|
||||
chcr |= CHCR_IE;
|
||||
|
||||
ctrl_outl(chcr, CHCR[chan->chan]);
|
||||
|
||||
enable_irq(irq);
|
||||
if (chan->flags & DMA_TEI_CAPABLE) {
|
||||
irq = get_dmte_irq(chan->chan);
|
||||
enable_irq(irq);
|
||||
}
|
||||
}
|
||||
|
||||
static void sh_dmac_disable_dma(struct dma_channel *chan)
|
||||
{
|
||||
int irq = get_dmte_irq(chan->chan);
|
||||
int irq;
|
||||
u32 chcr;
|
||||
|
||||
disable_irq(irq);
|
||||
if (chan->flags & DMA_TEI_CAPABLE) {
|
||||
irq = get_dmte_irq(chan->chan);
|
||||
disable_irq(irq);
|
||||
}
|
||||
|
||||
chcr = ctrl_inl(CHCR[chan->chan]);
|
||||
chcr &= ~(CHCR_DE | CHCR_TE | CHCR_IE);
|
||||
|
@ -158,7 +157,7 @@ static int sh_dmac_xfer_dma(struct dma_channel *chan)
|
|||
* If we haven't pre-configured the channel with special flags, use
|
||||
* the defaults.
|
||||
*/
|
||||
if (!(chan->flags & DMA_CONFIGURED))
|
||||
if (unlikely(!(chan->flags & DMA_CONFIGURED)))
|
||||
sh_dmac_configure_channel(chan, 0);
|
||||
|
||||
sh_dmac_disable_dma(chan);
|
||||
|
@ -178,9 +177,11 @@ static int sh_dmac_xfer_dma(struct dma_channel *chan)
|
|||
* cascading to the PVR2 DMAC. In this case, we still need to write
|
||||
* SAR and DAR, regardless of value, in order for cascading to work.
|
||||
*/
|
||||
if (chan->sar || (mach_is_dreamcast() && chan->chan == 2))
|
||||
if (chan->sar || (mach_is_dreamcast() &&
|
||||
chan->chan == PVR2_CASCADE_CHAN))
|
||||
ctrl_outl(chan->sar, SAR[chan->chan]);
|
||||
if (chan->dar || (mach_is_dreamcast() && chan->chan == 2))
|
||||
if (chan->dar || (mach_is_dreamcast() &&
|
||||
chan->chan == PVR2_CASCADE_CHAN))
|
||||
ctrl_outl(chan->dar, DAR[chan->chan]);
|
||||
|
||||
ctrl_outl(chan->count >> calc_xmit_shift(chan), DMATCR[chan->chan]);
|
||||
|
@ -198,17 +199,38 @@ static int sh_dmac_get_dma_residue(struct dma_channel *chan)
|
|||
return ctrl_inl(DMATCR[chan->chan]) << calc_xmit_shift(chan);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CPU_SUBTYPE_SH7780
|
||||
#define dmaor_read_reg() ctrl_inw(DMAOR)
|
||||
#define dmaor_write_reg(data) ctrl_outw(data, DMAOR)
|
||||
#else
|
||||
#define dmaor_read_reg() ctrl_inl(DMAOR)
|
||||
#define dmaor_write_reg(data) ctrl_outl(data, DMAOR)
|
||||
#endif
|
||||
|
||||
static inline int dmaor_reset(void)
|
||||
{
|
||||
unsigned long dmaor = dmaor_read_reg();
|
||||
|
||||
/* Try to clear the error flags first, incase they are set */
|
||||
dmaor &= ~(DMAOR_NMIF | DMAOR_AE);
|
||||
dmaor_write_reg(dmaor);
|
||||
|
||||
dmaor |= DMAOR_INIT;
|
||||
dmaor_write_reg(dmaor);
|
||||
|
||||
/* See if we got an error again */
|
||||
if ((dmaor_read_reg() & (DMAOR_AE | DMAOR_NMIF))) {
|
||||
printk(KERN_ERR "dma-sh: Can't initialize DMAOR.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_CPU_SH4)
|
||||
static irqreturn_t dma_err(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
unsigned long dmaor = ctrl_inl(DMAOR);
|
||||
|
||||
printk("DMAE: DMAOR=%lx\n", dmaor);
|
||||
|
||||
ctrl_outl(ctrl_inl(DMAOR)&~DMAOR_NMIF, DMAOR);
|
||||
ctrl_outl(ctrl_inl(DMAOR)&~DMAOR_AE, DMAOR);
|
||||
ctrl_outl(ctrl_inl(DMAOR)|DMAOR_DME, DMAOR);
|
||||
|
||||
dmaor_reset();
|
||||
disable_irq(irq);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
|
@ -224,8 +246,8 @@ static struct dma_ops sh_dmac_ops = {
|
|||
};
|
||||
|
||||
static struct dma_info sh_dmac_info = {
|
||||
.name = "SuperH DMAC",
|
||||
.nr_channels = 4,
|
||||
.name = "sh_dmac",
|
||||
.nr_channels = CONFIG_NR_ONCHIP_DMA_CHANNELS,
|
||||
.ops = &sh_dmac_ops,
|
||||
.flags = DMAC_CHANNELS_TEI_CAPABLE,
|
||||
};
|
||||
|
@ -248,7 +270,13 @@ static int __init sh_dmac_init(void)
|
|||
make_ipr_irq(irq, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY);
|
||||
}
|
||||
|
||||
ctrl_outl(0x8000 | DMAOR_DME, DMAOR);
|
||||
/*
|
||||
* Initialize DMAOR, and clean up any error flags that may have
|
||||
* been set.
|
||||
*/
|
||||
i = dmaor_reset();
|
||||
if (i < 0)
|
||||
return i;
|
||||
|
||||
return register_dmac(info);
|
||||
}
|
||||
|
@ -258,10 +286,12 @@ static void __exit sh_dmac_exit(void)
|
|||
#ifdef CONFIG_CPU_SH4
|
||||
free_irq(DMAE_IRQ, 0);
|
||||
#endif
|
||||
unregister_dmac(&sh_dmac_info);
|
||||
}
|
||||
|
||||
subsys_initcall(sh_dmac_init);
|
||||
module_exit(sh_dmac_exit);
|
||||
|
||||
MODULE_AUTHOR("Takashi YOSHII, Paul Mundt, Andriy Skulysh");
|
||||
MODULE_DESCRIPTION("SuperH On-Chip DMAC Support");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
#ifndef __DMA_SH_H
|
||||
#define __DMA_SH_H
|
||||
|
||||
#include <asm/cpu/dma.h>
|
||||
|
||||
/* Definitions for the SuperH DMAC */
|
||||
#define REQ_L 0x00000000
|
||||
#define REQ_E 0x00080000
|
||||
|
@ -26,27 +28,47 @@
|
|||
#define SM_DEC 0x00002000
|
||||
#define RS_IN 0x00000200
|
||||
#define RS_OUT 0x00000300
|
||||
#define TM_BURST 0x0000080
|
||||
#define TS_8 0x00000010
|
||||
#define TS_16 0x00000020
|
||||
#define TS_32 0x00000030
|
||||
#define TS_64 0x00000000
|
||||
#define TS_BLK 0x00000040
|
||||
#define CHCR_DE 0x00000001
|
||||
#define CHCR_TE 0x00000002
|
||||
#define CHCR_IE 0x00000004
|
||||
|
||||
/* Define the default configuration for dual address memory-memory transfer.
|
||||
* The 0x400 value represents auto-request, external->external.
|
||||
*/
|
||||
#define RS_DUAL (DM_INC | SM_INC | 0x400 | TS_32)
|
||||
|
||||
#define DMAOR_COD 0x00000008
|
||||
/* DMAOR definitions */
|
||||
#define DMAOR_AE 0x00000004
|
||||
#define DMAOR_NMIF 0x00000002
|
||||
#define DMAOR_DME 0x00000001
|
||||
|
||||
/*
|
||||
* Define the default configuration for dual address memory-memory transfer.
|
||||
* The 0x400 value represents auto-request, external->external.
|
||||
*/
|
||||
#define RS_DUAL (DM_INC | SM_INC | 0x400 | TS_32)
|
||||
|
||||
#define MAX_DMAC_CHANNELS (CONFIG_NR_ONCHIP_DMA_CHANNELS)
|
||||
|
||||
/*
|
||||
* Subtypes that have fewer channels than this simply need to change
|
||||
* CONFIG_NR_ONCHIP_DMA_CHANNELS. Likewise, subtypes with a larger number
|
||||
* of channels should expand on this.
|
||||
*
|
||||
* For most subtypes we can easily figure these values out with some
|
||||
* basic calculation, unfortunately on other subtypes these are more
|
||||
* scattered, so we just leave it unrolled for simplicity.
|
||||
*/
|
||||
#define SAR ((unsigned long[]){SH_DMAC_BASE + 0x00, SH_DMAC_BASE + 0x10, \
|
||||
SH_DMAC_BASE + 0x20, SH_DMAC_BASE + 0x30, \
|
||||
SH_DMAC_BASE + 0x50, SH_DMAC_BASE + 0x60})
|
||||
#define DAR ((unsigned long[]){SH_DMAC_BASE + 0x04, SH_DMAC_BASE + 0x14, \
|
||||
SH_DMAC_BASE + 0x24, SH_DMAC_BASE + 0x34, \
|
||||
SH_DMAC_BASE + 0x54, SH_DMAC_BASE + 0x64})
|
||||
#define DMATCR ((unsigned long[]){SH_DMAC_BASE + 0x08, SH_DMAC_BASE + 0x18, \
|
||||
SH_DMAC_BASE + 0x28, SH_DMAC_BASE + 0x38, \
|
||||
SH_DMAC_BASE + 0x58, SH_DMAC_BASE + 0x68})
|
||||
#define CHCR ((unsigned long[]){SH_DMAC_BASE + 0x0c, SH_DMAC_BASE + 0x1c, \
|
||||
SH_DMAC_BASE + 0x2c, SH_DMAC_BASE + 0x3c, \
|
||||
SH_DMAC_BASE + 0x5c, SH_DMAC_BASE + 0x6c})
|
||||
|
||||
#define DMAOR (SH_DMAC_BASE + 0x40)
|
||||
|
||||
#endif /* __DMA_SH_H */
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* sysfs interface for SH DMA API
|
||||
*
|
||||
* Copyright (C) 2004 Paul Mundt
|
||||
* Copyright (C) 2004, 2005 Paul Mundt
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
|
@ -12,7 +12,9 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/sysdev.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/string.h>
|
||||
#include <asm/dma.h>
|
||||
|
||||
|
@ -77,7 +79,7 @@ static ssize_t dma_store_config(struct sys_device *dev,
|
|||
unsigned long config;
|
||||
|
||||
config = simple_strtoul(buf, NULL, 0);
|
||||
dma_configure_channel(channel->chan, config);
|
||||
dma_configure_channel(channel->vchan, config);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
@ -111,12 +113,13 @@ static SYSDEV_ATTR(field, S_IRUGO, dma_show_##field, NULL);
|
|||
dma_ro_attr(count, "0x%08x\n");
|
||||
dma_ro_attr(flags, "0x%08lx\n");
|
||||
|
||||
int __init dma_create_sysfs_files(struct dma_channel *chan)
|
||||
int dma_create_sysfs_files(struct dma_channel *chan, struct dma_info *info)
|
||||
{
|
||||
struct sys_device *dev = &chan->dev;
|
||||
char name[16];
|
||||
int ret;
|
||||
|
||||
dev->id = chan->chan;
|
||||
dev->id = chan->vchan;
|
||||
dev->cls = &dma_sysclass;
|
||||
|
||||
ret = sysdev_register(dev);
|
||||
|
@ -129,6 +132,24 @@ int __init dma_create_sysfs_files(struct dma_channel *chan)
|
|||
sysdev_create_file(dev, &attr_flags);
|
||||
sysdev_create_file(dev, &attr_config);
|
||||
|
||||
return 0;
|
||||
snprintf(name, sizeof(name), "dma%d", chan->chan);
|
||||
return sysfs_create_link(&info->pdev->dev.kobj, &dev->kobj, name);
|
||||
}
|
||||
|
||||
void dma_remove_sysfs_files(struct dma_channel *chan, struct dma_info *info)
|
||||
{
|
||||
struct sys_device *dev = &chan->dev;
|
||||
char name[16];
|
||||
|
||||
sysdev_remove_file(dev, &attr_dev_id);
|
||||
sysdev_remove_file(dev, &attr_count);
|
||||
sysdev_remove_file(dev, &attr_mode);
|
||||
sysdev_remove_file(dev, &attr_flags);
|
||||
sysdev_remove_file(dev, &attr_config);
|
||||
|
||||
snprintf(name, sizeof(name), "dma%d", chan->chan);
|
||||
sysfs_remove_link(&info->pdev->dev.kobj, name);
|
||||
|
||||
sysdev_unregister(dev);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,4 @@ obj-$(CONFIG_SH_KGDB) += kgdb_stub.o kgdb_jmp.o
|
|||
obj-$(CONFIG_SH_CPU_FREQ) += cpufreq.o
|
||||
obj-$(CONFIG_MODULES) += module.o
|
||||
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
|
||||
|
||||
USE_STANDARD_AS_RULE := true
|
||||
|
||||
obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
|
||||
|
|
|
@ -2,15 +2,12 @@
|
|||
# Makefile for the Linux/SuperH CPU-specifc backends.
|
||||
#
|
||||
|
||||
obj-y := irq_ipr.o irq_imask.o init.o bus.o
|
||||
obj-y += irq/ init.o bus.o clock.o
|
||||
|
||||
obj-$(CONFIG_CPU_SH2) += sh2/
|
||||
obj-$(CONFIG_CPU_SH3) += sh3/
|
||||
obj-$(CONFIG_CPU_SH4) += sh4/
|
||||
|
||||
obj-$(CONFIG_SH_RTC) += rtc.o
|
||||
obj-$(CONFIG_SH_RTC) += rtc.o
|
||||
obj-$(CONFIG_UBC_WAKEUP) += ubc.o
|
||||
obj-$(CONFIG_SH_ADC) += adc.o
|
||||
|
||||
USE_STANDARD_AS_RULE := true
|
||||
|
||||
obj-$(CONFIG_SH_ADC) += adc.o
|
||||
|
|
|
@ -109,6 +109,8 @@ int sh_device_register(struct sh_dev *dev)
|
|||
/* This is needed for USB OHCI to work */
|
||||
if (dev->dma_mask)
|
||||
dev->dev.dma_mask = dev->dma_mask;
|
||||
if (dev->coherent_dma_mask)
|
||||
dev->dev.coherent_dma_mask = dev->coherent_dma_mask;
|
||||
|
||||
snprintf(dev->dev.bus_id, BUS_ID_SIZE, "%s%u",
|
||||
dev->name, dev->dev_id);
|
||||
|
|
287
arch/sh/kernel/cpu/clock.c
Normal file
287
arch/sh/kernel/cpu/clock.c
Normal file
|
@ -0,0 +1,287 @@
|
|||
/*
|
||||
* arch/sh/kernel/cpu/clock.c - SuperH clock framework
|
||||
*
|
||||
* Copyright (C) 2005 Paul Mundt
|
||||
*
|
||||
* This clock framework is derived from the OMAP version by:
|
||||
*
|
||||
* Copyright (C) 2004 Nokia Corporation
|
||||
* Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/kref.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/err.h>
|
||||
#include <asm/clock.h>
|
||||
#include <asm/timer.h>
|
||||
|
||||
static LIST_HEAD(clock_list);
|
||||
static DEFINE_SPINLOCK(clock_lock);
|
||||
static DECLARE_MUTEX(clock_list_sem);
|
||||
|
||||
/*
|
||||
* Each subtype is expected to define the init routines for these clocks,
|
||||
* as each subtype (or processor family) will have these clocks at the
|
||||
* very least. These are all provided through the CPG, which even some of
|
||||
* the more quirky parts (such as ST40, SH4-202, etc.) still have.
|
||||
*
|
||||
* The processor-specific code is expected to register any additional
|
||||
* clock sources that are of interest.
|
||||
*/
|
||||
static struct clk master_clk = {
|
||||
.name = "master_clk",
|
||||
.flags = CLK_ALWAYS_ENABLED | CLK_RATE_PROPAGATES,
|
||||
#ifdef CONFIG_SH_PCLK_FREQ_BOOL
|
||||
.rate = CONFIG_SH_PCLK_FREQ,
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct clk module_clk = {
|
||||
.name = "module_clk",
|
||||
.parent = &master_clk,
|
||||
.flags = CLK_ALWAYS_ENABLED | CLK_RATE_PROPAGATES,
|
||||
};
|
||||
|
||||
static struct clk bus_clk = {
|
||||
.name = "bus_clk",
|
||||
.parent = &master_clk,
|
||||
.flags = CLK_ALWAYS_ENABLED | CLK_RATE_PROPAGATES,
|
||||
};
|
||||
|
||||
static struct clk cpu_clk = {
|
||||
.name = "cpu_clk",
|
||||
.parent = &master_clk,
|
||||
.flags = CLK_ALWAYS_ENABLED,
|
||||
};
|
||||
|
||||
/*
|
||||
* The ordering of these clocks matters, do not change it.
|
||||
*/
|
||||
static struct clk *onchip_clocks[] = {
|
||||
&master_clk,
|
||||
&module_clk,
|
||||
&bus_clk,
|
||||
&cpu_clk,
|
||||
};
|
||||
|
||||
static void propagate_rate(struct clk *clk)
|
||||
{
|
||||
struct clk *clkp;
|
||||
|
||||
list_for_each_entry(clkp, &clock_list, node) {
|
||||
if (likely(clkp->parent != clk))
|
||||
continue;
|
||||
if (likely(clkp->ops && clkp->ops->recalc))
|
||||
clkp->ops->recalc(clkp);
|
||||
}
|
||||
}
|
||||
|
||||
int __clk_enable(struct clk *clk)
|
||||
{
|
||||
/*
|
||||
* See if this is the first time we're enabling the clock, some
|
||||
* clocks that are always enabled still require "special"
|
||||
* initialization. This is especially true if the clock mode
|
||||
* changes and the clock needs to hunt for the proper set of
|
||||
* divisors to use before it can effectively recalc.
|
||||
*/
|
||||
if (unlikely(atomic_read(&clk->kref.refcount) == 1))
|
||||
if (clk->ops && clk->ops->init)
|
||||
clk->ops->init(clk);
|
||||
|
||||
if (clk->flags & CLK_ALWAYS_ENABLED)
|
||||
return 0;
|
||||
|
||||
if (likely(clk->ops && clk->ops->enable))
|
||||
clk->ops->enable(clk);
|
||||
|
||||
kref_get(&clk->kref);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int clk_enable(struct clk *clk)
|
||||
{
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
spin_lock_irqsave(&clock_lock, flags);
|
||||
ret = __clk_enable(clk);
|
||||
spin_unlock_irqrestore(&clock_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void clk_kref_release(struct kref *kref)
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
|
||||
void __clk_disable(struct clk *clk)
|
||||
{
|
||||
if (clk->flags & CLK_ALWAYS_ENABLED)
|
||||
return;
|
||||
|
||||
kref_put(&clk->kref, clk_kref_release);
|
||||
}
|
||||
|
||||
void clk_disable(struct clk *clk)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&clock_lock, flags);
|
||||
__clk_disable(clk);
|
||||
spin_unlock_irqrestore(&clock_lock, flags);
|
||||
}
|
||||
|
||||
int clk_register(struct clk *clk)
|
||||
{
|
||||
down(&clock_list_sem);
|
||||
|
||||
list_add(&clk->node, &clock_list);
|
||||
kref_init(&clk->kref);
|
||||
|
||||
up(&clock_list_sem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void clk_unregister(struct clk *clk)
|
||||
{
|
||||
down(&clock_list_sem);
|
||||
list_del(&clk->node);
|
||||
up(&clock_list_sem);
|
||||
}
|
||||
|
||||
inline unsigned long clk_get_rate(struct clk *clk)
|
||||
{
|
||||
return clk->rate;
|
||||
}
|
||||
|
||||
int clk_set_rate(struct clk *clk, unsigned long rate)
|
||||
{
|
||||
int ret = -EOPNOTSUPP;
|
||||
|
||||
if (likely(clk->ops && clk->ops->set_rate)) {
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&clock_lock, flags);
|
||||
ret = clk->ops->set_rate(clk, rate);
|
||||
spin_unlock_irqrestore(&clock_lock, flags);
|
||||
}
|
||||
|
||||
if (unlikely(clk->flags & CLK_RATE_PROPAGATES))
|
||||
propagate_rate(clk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void clk_recalc_rate(struct clk *clk)
|
||||
{
|
||||
if (likely(clk->ops && clk->ops->recalc)) {
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&clock_lock, flags);
|
||||
clk->ops->recalc(clk);
|
||||
spin_unlock_irqrestore(&clock_lock, flags);
|
||||
}
|
||||
|
||||
if (unlikely(clk->flags & CLK_RATE_PROPAGATES))
|
||||
propagate_rate(clk);
|
||||
}
|
||||
|
||||
struct clk *clk_get(const char *id)
|
||||
{
|
||||
struct clk *p, *clk = ERR_PTR(-ENOENT);
|
||||
|
||||
down(&clock_list_sem);
|
||||
list_for_each_entry(p, &clock_list, node) {
|
||||
if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
|
||||
clk = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
up(&clock_list_sem);
|
||||
|
||||
return clk;
|
||||
}
|
||||
|
||||
void clk_put(struct clk *clk)
|
||||
{
|
||||
if (clk && !IS_ERR(clk))
|
||||
module_put(clk->owner);
|
||||
}
|
||||
|
||||
void __init __attribute__ ((weak))
|
||||
arch_init_clk_ops(struct clk_ops **ops, int type)
|
||||
{
|
||||
}
|
||||
|
||||
int __init clk_init(void)
|
||||
{
|
||||
int i, ret = 0;
|
||||
|
||||
if (unlikely(!master_clk.rate))
|
||||
/*
|
||||
* NOTE: This will break if the default divisor has been
|
||||
* changed.
|
||||
*
|
||||
* No one should be changing the default on us however,
|
||||
* expect that a sane value for CONFIG_SH_PCLK_FREQ will
|
||||
* be defined in the event of a different divisor.
|
||||
*/
|
||||
master_clk.rate = get_timer_frequency() * 4;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(onchip_clocks); i++) {
|
||||
struct clk *clk = onchip_clocks[i];
|
||||
|
||||
arch_init_clk_ops(&clk->ops, i);
|
||||
ret |= clk_register(clk);
|
||||
clk_enable(clk);
|
||||
}
|
||||
|
||||
/* Kick the child clocks.. */
|
||||
propagate_rate(&master_clk);
|
||||
propagate_rate(&bus_clk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int show_clocks(struct seq_file *m)
|
||||
{
|
||||
struct clk *clk;
|
||||
|
||||
list_for_each_entry_reverse(clk, &clock_list, node) {
|
||||
unsigned long rate = clk_get_rate(clk);
|
||||
|
||||
/*
|
||||
* Don't bother listing dummy clocks with no ancestry
|
||||
* that only support enable and disable ops.
|
||||
*/
|
||||
if (unlikely(!rate && !clk->parent))
|
||||
continue;
|
||||
|
||||
seq_printf(m, "%-12s\t: %ld.%02ldMHz\n", clk->name,
|
||||
rate / 1000000, (rate % 1000000) / 10000);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(clk_register);
|
||||
EXPORT_SYMBOL_GPL(clk_unregister);
|
||||
EXPORT_SYMBOL_GPL(clk_get);
|
||||
EXPORT_SYMBOL_GPL(clk_put);
|
||||
EXPORT_SYMBOL_GPL(clk_enable);
|
||||
EXPORT_SYMBOL_GPL(clk_disable);
|
||||
EXPORT_SYMBOL_GPL(__clk_enable);
|
||||
EXPORT_SYMBOL_GPL(__clk_disable);
|
||||
EXPORT_SYMBOL_GPL(clk_get_rate);
|
||||
EXPORT_SYMBOL_GPL(clk_set_rate);
|
||||
EXPORT_SYMBOL_GPL(clk_recalc_rate);
|
7
arch/sh/kernel/cpu/irq/Makefile
Normal file
7
arch/sh/kernel/cpu/irq/Makefile
Normal file
|
@ -0,0 +1,7 @@
|
|||
#
|
||||
# Makefile for the Linux/SuperH CPU-specifc IRQ handlers.
|
||||
#
|
||||
obj-y += ipr.o imask.o
|
||||
|
||||
obj-$(CONFIG_CPU_HAS_PINT_IRQ) += pint.o
|
||||
obj-$(CONFIG_CPU_HAS_INTC2_IRQ) += intc2.o
|
|
@ -1,16 +1,12 @@
|
|||
/* $Id: irq_imask.c,v 1.1.2.1 2002/11/17 10:53:43 mrbrown Exp $
|
||||
*
|
||||
* linux/arch/sh/kernel/irq_imask.c
|
||||
/*
|
||||
* arch/sh/kernel/cpu/irq/imask.c
|
||||
*
|
||||
* Copyright (C) 1999, 2000 Niibe Yutaka
|
||||
*
|
||||
* Simple interrupt handling using IMASK of SR register.
|
||||
*
|
||||
*/
|
||||
|
||||
/* NOTE: Will not work on level 15 */
|
||||
|
||||
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/kernel_stat.h>
|
||||
|
@ -19,13 +15,11 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/bitops.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <asm/irq.h>
|
||||
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/cache.h>
|
||||
#include <linux/irq.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/irq.h>
|
||||
|
||||
/* Bitmap of IRQ masked */
|
||||
static unsigned long imask_mask = 0x7fff;
|
||||
|
@ -40,7 +34,7 @@ static void end_imask_irq(unsigned int irq);
|
|||
#define IMASK_PRIORITY 15
|
||||
|
||||
static unsigned int startup_imask_irq(unsigned int irq)
|
||||
{
|
||||
{
|
||||
/* Nothing to do */
|
||||
return 0; /* never anything pending */
|
||||
}
|
284
arch/sh/kernel/cpu/irq/intc2.c
Normal file
284
arch/sh/kernel/cpu/irq/intc2.c
Normal file
|
@ -0,0 +1,284 @@
|
|||
/*
|
||||
* Interrupt handling for INTC2-based IRQ.
|
||||
*
|
||||
* Copyright (C) 2001 David J. Mckay (david.mckay@st.com)
|
||||
* Copyright (C) 2005, 2006 Paul Mundt (lethal@linux-sh.org)
|
||||
*
|
||||
* May be copied or modified under the terms of the GNU General Public
|
||||
* License. See linux/COPYING for more information.
|
||||
*
|
||||
* These are the "new Hitachi style" interrupts, as present on the
|
||||
* Hitachi 7751, the STM ST40 STB1, SH7760, and SH7780.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/irq.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/machvec.h>
|
||||
|
||||
struct intc2_data {
|
||||
unsigned char msk_offset;
|
||||
unsigned char msk_shift;
|
||||
|
||||
int (*clear_irq) (int);
|
||||
};
|
||||
|
||||
static struct intc2_data intc2_data[NR_INTC2_IRQS];
|
||||
|
||||
static void enable_intc2_irq(unsigned int irq);
|
||||
static void disable_intc2_irq(unsigned int irq);
|
||||
|
||||
/* shutdown is same as "disable" */
|
||||
#define shutdown_intc2_irq disable_intc2_irq
|
||||
|
||||
static void mask_and_ack_intc2(unsigned int);
|
||||
static void end_intc2_irq(unsigned int irq);
|
||||
|
||||
static unsigned int startup_intc2_irq(unsigned int irq)
|
||||
{
|
||||
enable_intc2_irq(irq);
|
||||
return 0; /* never anything pending */
|
||||
}
|
||||
|
||||
static struct hw_interrupt_type intc2_irq_type = {
|
||||
.typename = "INTC2-IRQ",
|
||||
.startup = startup_intc2_irq,
|
||||
.shutdown = shutdown_intc2_irq,
|
||||
.enable = enable_intc2_irq,
|
||||
.disable = disable_intc2_irq,
|
||||
.ack = mask_and_ack_intc2,
|
||||
.end = end_intc2_irq
|
||||
};
|
||||
|
||||
static void disable_intc2_irq(unsigned int irq)
|
||||
{
|
||||
int irq_offset = irq - INTC2_FIRST_IRQ;
|
||||
int msk_shift, msk_offset;
|
||||
|
||||
/* Sanity check */
|
||||
if (unlikely(irq_offset < 0 || irq_offset >= NR_INTC2_IRQS))
|
||||
return;
|
||||
|
||||
msk_shift = intc2_data[irq_offset].msk_shift;
|
||||
msk_offset = intc2_data[irq_offset].msk_offset;
|
||||
|
||||
ctrl_outl(1 << msk_shift,
|
||||
INTC2_BASE + INTC2_INTMSK_OFFSET + msk_offset);
|
||||
}
|
||||
|
||||
static void enable_intc2_irq(unsigned int irq)
|
||||
{
|
||||
int irq_offset = irq - INTC2_FIRST_IRQ;
|
||||
int msk_shift, msk_offset;
|
||||
|
||||
/* Sanity check */
|
||||
if (unlikely(irq_offset < 0 || irq_offset >= NR_INTC2_IRQS))
|
||||
return;
|
||||
|
||||
msk_shift = intc2_data[irq_offset].msk_shift;
|
||||
msk_offset = intc2_data[irq_offset].msk_offset;
|
||||
|
||||
ctrl_outl(1 << msk_shift,
|
||||
INTC2_BASE + INTC2_INTMSKCLR_OFFSET + msk_offset);
|
||||
}
|
||||
|
||||
static void mask_and_ack_intc2(unsigned int irq)
|
||||
{
|
||||
disable_intc2_irq(irq);
|
||||
}
|
||||
|
||||
static void end_intc2_irq(unsigned int irq)
|
||||
{
|
||||
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
|
||||
enable_intc2_irq(irq);
|
||||
|
||||
if (unlikely(intc2_data[irq - INTC2_FIRST_IRQ].clear_irq))
|
||||
intc2_data[irq - INTC2_FIRST_IRQ].clear_irq(irq);
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup an INTC2 style interrupt.
|
||||
* NOTE: Unlike IPR interrupts, parameters are not shifted by this code,
|
||||
* allowing the use of the numbers straight out of the datasheet.
|
||||
* For example:
|
||||
* PIO1 which is INTPRI00[19,16] and INTMSK00[13]
|
||||
* would be: ^ ^ ^ ^
|
||||
* | | | |
|
||||
* make_intc2_irq(84, 0, 16, 0, 13);
|
||||
*/
|
||||
void make_intc2_irq(unsigned int irq,
|
||||
unsigned int ipr_offset, unsigned int ipr_shift,
|
||||
unsigned int msk_offset, unsigned int msk_shift,
|
||||
unsigned int priority)
|
||||
{
|
||||
int irq_offset = irq - INTC2_FIRST_IRQ;
|
||||
unsigned int flags;
|
||||
unsigned long ipr;
|
||||
|
||||
if (unlikely(irq_offset < 0 || irq_offset >= NR_INTC2_IRQS))
|
||||
return;
|
||||
|
||||
disable_irq_nosync(irq);
|
||||
|
||||
/* Fill the data we need */
|
||||
intc2_data[irq_offset].msk_offset = msk_offset;
|
||||
intc2_data[irq_offset].msk_shift = msk_shift;
|
||||
intc2_data[irq_offset].clear_irq = NULL;
|
||||
|
||||
/* Set the priority level */
|
||||
local_irq_save(flags);
|
||||
|
||||
ipr = ctrl_inl(INTC2_BASE + INTC2_INTPRI_OFFSET + ipr_offset);
|
||||
ipr &= ~(0xf << ipr_shift);
|
||||
ipr |= priority << ipr_shift;
|
||||
ctrl_outl(ipr, INTC2_BASE + INTC2_INTPRI_OFFSET + ipr_offset);
|
||||
|
||||
local_irq_restore(flags);
|
||||
|
||||
irq_desc[irq].handler = &intc2_irq_type;
|
||||
|
||||
disable_intc2_irq(irq);
|
||||
}
|
||||
|
||||
static struct intc2_init {
|
||||
unsigned short irq;
|
||||
unsigned char ipr_offset, ipr_shift;
|
||||
unsigned char msk_offset, msk_shift;
|
||||
unsigned char priority;
|
||||
} intc2_init_data[] __initdata = {
|
||||
#if defined(CONFIG_CPU_SUBTYPE_ST40)
|
||||
{64, 0, 0, 0, 0, 13}, /* PCI serr */
|
||||
{65, 0, 4, 0, 1, 13}, /* PCI err */
|
||||
{66, 0, 4, 0, 2, 13}, /* PCI ad */
|
||||
{67, 0, 4, 0, 3, 13}, /* PCI pwd down */
|
||||
{72, 0, 8, 0, 5, 13}, /* DMAC INT0 */
|
||||
{73, 0, 8, 0, 6, 13}, /* DMAC INT1 */
|
||||
{74, 0, 8, 0, 7, 13}, /* DMAC INT2 */
|
||||
{75, 0, 8, 0, 8, 13}, /* DMAC INT3 */
|
||||
{76, 0, 8, 0, 9, 13}, /* DMAC INT4 */
|
||||
{78, 0, 8, 0, 11, 13}, /* DMAC ERR */
|
||||
{80, 0, 12, 0, 12, 13}, /* PIO0 */
|
||||
{84, 0, 16, 0, 13, 13}, /* PIO1 */
|
||||
{88, 0, 20, 0, 14, 13}, /* PIO2 */
|
||||
{112, 4, 0, 4, 0, 13}, /* Mailbox */
|
||||
#ifdef CONFIG_CPU_SUBTYPE_ST40GX1
|
||||
{116, 4, 4, 4, 4, 13}, /* SSC0 */
|
||||
{120, 4, 8, 4, 8, 13}, /* IR Blaster */
|
||||
{124, 4, 12, 4, 12, 13}, /* USB host */
|
||||
{128, 4, 16, 4, 16, 13}, /* Video processor BLITTER */
|
||||
{132, 4, 20, 4, 20, 13}, /* UART0 */
|
||||
{134, 4, 20, 4, 22, 13}, /* UART2 */
|
||||
{136, 4, 24, 4, 24, 13}, /* IO_PIO0 */
|
||||
{140, 4, 28, 4, 28, 13}, /* EMPI */
|
||||
{144, 8, 0, 8, 0, 13}, /* MAFE */
|
||||
{148, 8, 4, 8, 4, 13}, /* PWM */
|
||||
{152, 8, 8, 8, 8, 13}, /* SSC1 */
|
||||
{156, 8, 12, 8, 12, 13}, /* IO_PIO1 */
|
||||
{160, 8, 16, 8, 16, 13}, /* USB target */
|
||||
{164, 8, 20, 8, 20, 13}, /* UART1 */
|
||||
{168, 8, 24, 8, 24, 13}, /* Teletext */
|
||||
{172, 8, 28, 8, 28, 13}, /* VideoSync VTG */
|
||||
{173, 8, 28, 8, 29, 13}, /* VideoSync DVP0 */
|
||||
{174, 8, 28, 8, 30, 13}, /* VideoSync DVP1 */
|
||||
#endif
|
||||
#elif defined(CONFIG_CPU_SUBTYPE_SH7760)
|
||||
/*
|
||||
* SH7760 INTC2-Style interrupts, vectors IRQ48-111 INTEVT 0x800-0xFE0
|
||||
*/
|
||||
/* INTPRIO0 | INTMSK0 */
|
||||
{48, 0, 28, 0, 31, 3}, /* IRQ 4 */
|
||||
{49, 0, 24, 0, 30, 3}, /* IRQ 3 */
|
||||
{50, 0, 20, 0, 29, 3}, /* IRQ 2 */
|
||||
{51, 0, 16, 0, 28, 3}, /* IRQ 1 */
|
||||
/* 52-55 (INTEVT 0x880-0x8E0) unused/reserved */
|
||||
/* INTPRIO4 | INTMSK0 */
|
||||
{56, 4, 28, 0, 25, 3}, /* HCAN2_CHAN0 */
|
||||
{57, 4, 24, 0, 24, 3}, /* HCAN2_CHAN1 */
|
||||
{58, 4, 20, 0, 23, 3}, /* I2S_CHAN0 */
|
||||
{59, 4, 16, 0, 22, 3}, /* I2S_CHAN1 */
|
||||
{60, 4, 12, 0, 21, 3}, /* AC97_CHAN0 */
|
||||
{61, 4, 8, 0, 20, 3}, /* AC97_CHAN1 */
|
||||
{62, 4, 4, 0, 19, 3}, /* I2C_CHAN0 */
|
||||
{63, 4, 0, 0, 18, 3}, /* I2C_CHAN1 */
|
||||
/* INTPRIO8 | INTMSK0 */
|
||||
{52, 8, 16, 0, 11, 3}, /* SCIF0_ERI_IRQ */
|
||||
{53, 8, 16, 0, 10, 3}, /* SCIF0_RXI_IRQ */
|
||||
{54, 8, 16, 0, 9, 3}, /* SCIF0_BRI_IRQ */
|
||||
{55, 8, 16, 0, 8, 3}, /* SCIF0_TXI_IRQ */
|
||||
{64, 8, 28, 0, 17, 3}, /* USBHI_IRQ */
|
||||
{65, 8, 24, 0, 16, 3}, /* LCDC */
|
||||
/* 66, 67 unused */
|
||||
{68, 8, 20, 0, 14, 13}, /* DMABRGI0_IRQ */
|
||||
{69, 8, 20, 0, 13, 13}, /* DMABRGI1_IRQ */
|
||||
{70, 8, 20, 0, 12, 13}, /* DMABRGI2_IRQ */
|
||||
/* 71 unused */
|
||||
{72, 8, 12, 0, 7, 3}, /* SCIF1_ERI_IRQ */
|
||||
{73, 8, 12, 0, 6, 3}, /* SCIF1_RXI_IRQ */
|
||||
{74, 8, 12, 0, 5, 3}, /* SCIF1_BRI_IRQ */
|
||||
{75, 8, 12, 0, 4, 3}, /* SCIF1_TXI_IRQ */
|
||||
{76, 8, 8, 0, 3, 3}, /* SCIF2_ERI_IRQ */
|
||||
{77, 8, 8, 0, 2, 3}, /* SCIF2_RXI_IRQ */
|
||||
{78, 8, 8, 0, 1, 3}, /* SCIF2_BRI_IRQ */
|
||||
{79, 8, 8, 0, 0, 3}, /* SCIF2_TXI_IRQ */
|
||||
/* | INTMSK4 */
|
||||
{80, 8, 4, 4, 23, 3}, /* SIM_ERI */
|
||||
{81, 8, 4, 4, 22, 3}, /* SIM_RXI */
|
||||
{82, 8, 4, 4, 21, 3}, /* SIM_TXI */
|
||||
{83, 8, 4, 4, 20, 3}, /* SIM_TEI */
|
||||
{84, 8, 0, 4, 19, 3}, /* HSPII */
|
||||
/* INTPRIOC | INTMSK4 */
|
||||
/* 85-87 unused/reserved */
|
||||
{88, 12, 20, 4, 18, 3}, /* MMCI0 */
|
||||
{89, 12, 20, 4, 17, 3}, /* MMCI1 */
|
||||
{90, 12, 20, 4, 16, 3}, /* MMCI2 */
|
||||
{91, 12, 20, 4, 15, 3}, /* MMCI3 */
|
||||
{92, 12, 12, 4, 6, 3}, /* MFI (unsure, bug? in my 7760 manual*/
|
||||
/* 93-107 reserved/undocumented */
|
||||
{108,12, 4, 4, 1, 3}, /* ADC */
|
||||
{109,12, 0, 4, 0, 3}, /* CMTI */
|
||||
/* 110-111 reserved/unused */
|
||||
#elif defined(CONFIG_CPU_SUBTYPE_SH7780)
|
||||
{ TIMER_IRQ, 0, 24, 0, INTC_TMU0_MSK, 2},
|
||||
#ifdef CONFIG_SH_RTC
|
||||
{ RTC_IRQ, 4, 0, 0, INTC_RTC_MSK, TIMER_PRIORITY },
|
||||
#endif
|
||||
{ SCIF0_ERI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY },
|
||||
{ SCIF0_RXI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY },
|
||||
{ SCIF0_BRI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY },
|
||||
{ SCIF0_TXI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY },
|
||||
|
||||
{ SCIF1_ERI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY },
|
||||
{ SCIF1_RXI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY },
|
||||
{ SCIF1_BRI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY },
|
||||
{ SCIF1_TXI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY },
|
||||
|
||||
{ PCIC0_IRQ, 0x10, 8, 0, INTC_PCIC0_MSK, PCIC0_PRIORITY },
|
||||
{ PCIC1_IRQ, 0x10, 0, 0, INTC_PCIC1_MSK, PCIC1_PRIORITY },
|
||||
{ PCIC2_IRQ, 0x14, 24, 0, INTC_PCIC2_MSK, PCIC2_PRIORITY },
|
||||
{ PCIC3_IRQ, 0x14, 16, 0, INTC_PCIC3_MSK, PCIC3_PRIORITY },
|
||||
{ PCIC4_IRQ, 0x14, 8, 0, INTC_PCIC4_MSK, PCIC4_PRIORITY },
|
||||
#endif
|
||||
};
|
||||
|
||||
void __init init_IRQ_intc2(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(intc2_init_data); i++) {
|
||||
struct intc2_init *p = intc2_init_data + i;
|
||||
make_intc2_irq(p->irq, p->ipr_offset, p->ipr_shift,
|
||||
p-> msk_offset, p->msk_shift, p->priority);
|
||||
}
|
||||
}
|
||||
|
||||
/* Adds a termination callback to the interrupt */
|
||||
void intc2_add_clear_irq(int irq, int (*fn)(int))
|
||||
{
|
||||
if (unlikely(irq < INTC2_FIRST_IRQ))
|
||||
return;
|
||||
|
||||
intc2_data[irq - INTC2_FIRST_IRQ].clear_irq = fn;
|
||||
}
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
/* $Id: irq_ipr.c,v 1.1.2.1 2002/11/17 10:53:43 mrbrown Exp $
|
||||
*
|
||||
* linux/arch/sh/kernel/irq_ipr.c
|
||||
/*
|
||||
* arch/sh/kernel/cpu/irq/ipr.c
|
||||
*
|
||||
* Copyright (C) 1999 Niibe Yutaka & Takeshi Yaegashi
|
||||
* Copyright (C) 2000 Kazumoto Kojima
|
||||
|
@ -109,7 +108,8 @@ static void end_ipr_irq(unsigned int irq)
|
|||
enable_ipr_irq(irq);
|
||||
}
|
||||
|
||||
void make_ipr_irq(unsigned int irq, unsigned int addr, int pos, int priority)
|
||||
void make_ipr_irq(unsigned int irq, unsigned int addr, int pos,
|
||||
int priority, int maskpos)
|
||||
{
|
||||
disable_irq_nosync(irq);
|
||||
ipr_data[irq].addr = addr;
|
||||
|
@ -120,126 +120,47 @@ void make_ipr_irq(unsigned int irq, unsigned int addr, int pos, int priority)
|
|||
disable_ipr_irq(irq);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_CPU_SUBTYPE_SH7705) || \
|
||||
defined(CONFIG_CPU_SUBTYPE_SH7707) || \
|
||||
defined(CONFIG_CPU_SUBTYPE_SH7709)
|
||||
static unsigned char pint_map[256];
|
||||
static unsigned long portcr_mask = 0;
|
||||
|
||||
static void enable_pint_irq(unsigned int irq);
|
||||
static void disable_pint_irq(unsigned int irq);
|
||||
|
||||
/* shutdown is same as "disable" */
|
||||
#define shutdown_pint_irq disable_pint_irq
|
||||
|
||||
static void mask_and_ack_pint(unsigned int);
|
||||
static void end_pint_irq(unsigned int irq);
|
||||
|
||||
static unsigned int startup_pint_irq(unsigned int irq)
|
||||
{
|
||||
enable_pint_irq(irq);
|
||||
return 0; /* never anything pending */
|
||||
}
|
||||
|
||||
static struct hw_interrupt_type pint_irq_type = {
|
||||
.typename = "PINT-IRQ",
|
||||
.startup = startup_pint_irq,
|
||||
.shutdown = shutdown_pint_irq,
|
||||
.enable = enable_pint_irq,
|
||||
.disable = disable_pint_irq,
|
||||
.ack = mask_and_ack_pint,
|
||||
.end = end_pint_irq
|
||||
};
|
||||
|
||||
static void disable_pint_irq(unsigned int irq)
|
||||
{
|
||||
unsigned long val, flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
val = ctrl_inw(INTC_INTER);
|
||||
val &= ~(1 << (irq - PINT_IRQ_BASE));
|
||||
ctrl_outw(val, INTC_INTER); /* disable PINTn */
|
||||
portcr_mask &= ~(3 << (irq - PINT_IRQ_BASE)*2);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static void enable_pint_irq(unsigned int irq)
|
||||
{
|
||||
unsigned long val, flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
val = ctrl_inw(INTC_INTER);
|
||||
val |= 1 << (irq - PINT_IRQ_BASE);
|
||||
ctrl_outw(val, INTC_INTER); /* enable PINTn */
|
||||
portcr_mask |= 3 << (irq - PINT_IRQ_BASE)*2;
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static void mask_and_ack_pint(unsigned int irq)
|
||||
{
|
||||
disable_pint_irq(irq);
|
||||
}
|
||||
|
||||
static void end_pint_irq(unsigned int irq)
|
||||
{
|
||||
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
|
||||
enable_pint_irq(irq);
|
||||
}
|
||||
|
||||
void make_pint_irq(unsigned int irq)
|
||||
{
|
||||
disable_irq_nosync(irq);
|
||||
irq_desc[irq].handler = &pint_irq_type;
|
||||
disable_pint_irq(irq);
|
||||
}
|
||||
#endif
|
||||
|
||||
void __init init_IRQ(void)
|
||||
{
|
||||
#if defined(CONFIG_CPU_SUBTYPE_SH7705) || \
|
||||
defined(CONFIG_CPU_SUBTYPE_SH7707) || \
|
||||
defined(CONFIG_CPU_SUBTYPE_SH7709)
|
||||
int i;
|
||||
#endif
|
||||
|
||||
make_ipr_irq(TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY);
|
||||
make_ipr_irq(TIMER1_IRQ, TIMER1_IPR_ADDR, TIMER1_IPR_POS, TIMER1_PRIORITY);
|
||||
#ifndef CONFIG_CPU_SUBTYPE_SH7780
|
||||
make_ipr_irq(TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY, 0);
|
||||
make_ipr_irq(TIMER1_IRQ, TIMER1_IPR_ADDR, TIMER1_IPR_POS, TIMER1_PRIORITY, 0);
|
||||
#if defined(CONFIG_SH_RTC)
|
||||
make_ipr_irq(RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY);
|
||||
make_ipr_irq(RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY, 0);
|
||||
#endif
|
||||
|
||||
#ifdef SCI_ERI_IRQ
|
||||
make_ipr_irq(SCI_ERI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY);
|
||||
make_ipr_irq(SCI_RXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY);
|
||||
make_ipr_irq(SCI_TXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY);
|
||||
make_ipr_irq(SCI_ERI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY, 0);
|
||||
make_ipr_irq(SCI_RXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY, 0);
|
||||
make_ipr_irq(SCI_TXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY, 0);
|
||||
#endif
|
||||
|
||||
#ifdef SCIF1_ERI_IRQ
|
||||
make_ipr_irq(SCIF1_ERI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY);
|
||||
make_ipr_irq(SCIF1_RXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY);
|
||||
make_ipr_irq(SCIF1_BRI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY);
|
||||
make_ipr_irq(SCIF1_TXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY);
|
||||
make_ipr_irq(SCIF1_ERI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY, 0);
|
||||
make_ipr_irq(SCIF1_RXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY, 0);
|
||||
make_ipr_irq(SCIF1_BRI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY, 0);
|
||||
make_ipr_irq(SCIF1_TXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY, 0);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_CPU_SUBTYPE_SH7300)
|
||||
make_ipr_irq(SCIF0_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS, SCIF0_PRIORITY);
|
||||
make_ipr_irq(DMTE2_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY);
|
||||
make_ipr_irq(DMTE3_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY);
|
||||
make_ipr_irq(VIO_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY);
|
||||
make_ipr_irq(SCIF0_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS, SCIF0_PRIORITY, 0);
|
||||
make_ipr_irq(DMTE2_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY, 0);
|
||||
make_ipr_irq(DMTE3_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY, 0);
|
||||
make_ipr_irq(VIO_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY, 0);
|
||||
#endif
|
||||
|
||||
#ifdef SCIF_ERI_IRQ
|
||||
make_ipr_irq(SCIF_ERI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY);
|
||||
make_ipr_irq(SCIF_RXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY);
|
||||
make_ipr_irq(SCIF_BRI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY);
|
||||
make_ipr_irq(SCIF_TXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY);
|
||||
make_ipr_irq(SCIF_ERI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY, 0);
|
||||
make_ipr_irq(SCIF_RXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY, 0);
|
||||
make_ipr_irq(SCIF_BRI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY, 0);
|
||||
make_ipr_irq(SCIF_TXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY, 0);
|
||||
#endif
|
||||
|
||||
#ifdef IRDA_ERI_IRQ
|
||||
make_ipr_irq(IRDA_ERI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY);
|
||||
make_ipr_irq(IRDA_RXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY);
|
||||
make_ipr_irq(IRDA_BRI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY);
|
||||
make_ipr_irq(IRDA_TXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY);
|
||||
make_ipr_irq(IRDA_ERI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY, 0);
|
||||
make_ipr_irq(IRDA_RXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY, 0);
|
||||
make_ipr_irq(IRDA_BRI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY, 0);
|
||||
make_ipr_irq(IRDA_TXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY, 0);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \
|
||||
|
@ -254,86 +175,32 @@ void __init init_IRQ(void)
|
|||
* You should set corresponding bits of PFC to "00"
|
||||
* to enable these interrupts.
|
||||
*/
|
||||
make_ipr_irq(IRQ0_IRQ, IRQ0_IPR_ADDR, IRQ0_IPR_POS, IRQ0_PRIORITY);
|
||||
make_ipr_irq(IRQ1_IRQ, IRQ1_IPR_ADDR, IRQ1_IPR_POS, IRQ1_PRIORITY);
|
||||
make_ipr_irq(IRQ2_IRQ, IRQ2_IPR_ADDR, IRQ2_IPR_POS, IRQ2_PRIORITY);
|
||||
make_ipr_irq(IRQ3_IRQ, IRQ3_IPR_ADDR, IRQ3_IPR_POS, IRQ3_PRIORITY);
|
||||
make_ipr_irq(IRQ4_IRQ, IRQ4_IPR_ADDR, IRQ4_IPR_POS, IRQ4_PRIORITY);
|
||||
make_ipr_irq(IRQ5_IRQ, IRQ5_IPR_ADDR, IRQ5_IPR_POS, IRQ5_PRIORITY);
|
||||
#if !defined(CONFIG_CPU_SUBTYPE_SH7300)
|
||||
make_ipr_irq(PINT0_IRQ, PINT0_IPR_ADDR, PINT0_IPR_POS, PINT0_PRIORITY);
|
||||
make_ipr_irq(PINT8_IRQ, PINT8_IPR_ADDR, PINT8_IPR_POS, PINT8_PRIORITY);
|
||||
enable_ipr_irq(PINT0_IRQ);
|
||||
enable_ipr_irq(PINT8_IRQ);
|
||||
make_ipr_irq(IRQ0_IRQ, IRQ0_IPR_ADDR, IRQ0_IPR_POS, IRQ0_PRIORITY, 0);
|
||||
make_ipr_irq(IRQ1_IRQ, IRQ1_IPR_ADDR, IRQ1_IPR_POS, IRQ1_PRIORITY, 0);
|
||||
make_ipr_irq(IRQ2_IRQ, IRQ2_IPR_ADDR, IRQ2_IPR_POS, IRQ2_PRIORITY, 0);
|
||||
make_ipr_irq(IRQ3_IRQ, IRQ3_IPR_ADDR, IRQ3_IPR_POS, IRQ3_PRIORITY, 0);
|
||||
make_ipr_irq(IRQ4_IRQ, IRQ4_IPR_ADDR, IRQ4_IPR_POS, IRQ4_PRIORITY, 0);
|
||||
make_ipr_irq(IRQ5_IRQ, IRQ5_IPR_ADDR, IRQ5_IPR_POS, IRQ5_PRIORITY, 0);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
for(i = 0; i < 16; i++)
|
||||
make_pint_irq(PINT_IRQ_BASE + i);
|
||||
for(i = 0; i < 256; i++)
|
||||
{
|
||||
if(i & 1) pint_map[i] = 0;
|
||||
else if(i & 2) pint_map[i] = 1;
|
||||
else if(i & 4) pint_map[i] = 2;
|
||||
else if(i & 8) pint_map[i] = 3;
|
||||
else if(i & 0x10) pint_map[i] = 4;
|
||||
else if(i & 0x20) pint_map[i] = 5;
|
||||
else if(i & 0x40) pint_map[i] = 6;
|
||||
else if(i & 0x80) pint_map[i] = 7;
|
||||
}
|
||||
#endif /* !CONFIG_CPU_SUBTYPE_SH7300 */
|
||||
#endif /* CONFIG_CPU_SUBTYPE_SH7707 || CONFIG_CPU_SUBTYPE_SH7709 || CONFIG_CPU_SUBTYPE_SH7300*/
|
||||
#ifdef CONFIG_CPU_HAS_PINT_IRQ
|
||||
init_IRQ_pint();
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CPU_SUBTYPE_ST40
|
||||
#ifdef CONFIG_CPU_HAS_INTC2_IRQ
|
||||
init_IRQ_intc2();
|
||||
#endif
|
||||
|
||||
/* Perform the machine specific initialisation */
|
||||
if (sh_mv.mv_init_irq != NULL) {
|
||||
if (sh_mv.mv_init_irq != NULL)
|
||||
sh_mv.mv_init_irq();
|
||||
}
|
||||
}
|
||||
#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \
|
||||
defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705)
|
||||
|
||||
#if !defined(CONFIG_CPU_HAS_PINT_IRQ)
|
||||
int ipr_irq_demux(int irq)
|
||||
{
|
||||
#if !defined(CONFIG_CPU_SUBTYPE_SH7300)
|
||||
unsigned long creg, dreg, d, sav;
|
||||
|
||||
if(irq == PINT0_IRQ)
|
||||
{
|
||||
#if defined(CONFIG_CPU_SUBTYPE_SH7707)
|
||||
creg = PORT_PACR;
|
||||
dreg = PORT_PADR;
|
||||
#else
|
||||
creg = PORT_PCCR;
|
||||
dreg = PORT_PCDR;
|
||||
#endif
|
||||
sav = ctrl_inw(creg);
|
||||
ctrl_outw(sav | portcr_mask, creg);
|
||||
d = (~ctrl_inb(dreg) ^ ctrl_inw(INTC_ICR2)) & ctrl_inw(INTC_INTER) & 0xff;
|
||||
ctrl_outw(sav, creg);
|
||||
if(d == 0) return irq;
|
||||
return PINT_IRQ_BASE + pint_map[d];
|
||||
}
|
||||
else if(irq == PINT8_IRQ)
|
||||
{
|
||||
#if defined(CONFIG_CPU_SUBTYPE_SH7707)
|
||||
creg = PORT_PBCR;
|
||||
dreg = PORT_PBDR;
|
||||
#else
|
||||
creg = PORT_PFCR;
|
||||
dreg = PORT_PFDR;
|
||||
#endif
|
||||
sav = ctrl_inw(creg);
|
||||
ctrl_outw(sav | (portcr_mask >> 16), creg);
|
||||
d = (~ctrl_inb(dreg) ^ (ctrl_inw(INTC_ICR2) >> 8)) & (ctrl_inw(INTC_INTER) >> 8) & 0xff;
|
||||
ctrl_outw(sav, creg);
|
||||
if(d == 0) return irq;
|
||||
return PINT_IRQ_BASE + 8 + pint_map[d];
|
||||
}
|
||||
#endif
|
||||
return irq;
|
||||
}
|
||||
#endif
|
||||
|
||||
EXPORT_SYMBOL(make_ipr_irq);
|
||||
|
169
arch/sh/kernel/cpu/irq/pint.c
Normal file
169
arch/sh/kernel/cpu/irq/pint.c
Normal file
|
@ -0,0 +1,169 @@
|
|||
/*
|
||||
* arch/sh/kernel/cpu/irq/pint.c - Interrupt handling for PINT-based IRQs.
|
||||
*
|
||||
* Copyright (C) 1999 Niibe Yutaka & Takeshi Yaegashi
|
||||
* Copyright (C) 2000 Kazumoto Kojima
|
||||
* Copyright (C) 2003 Takashi Kusuda <kusuda-takashi@hitachi-ul.co.jp>
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/machvec.h>
|
||||
|
||||
static unsigned char pint_map[256];
|
||||
static unsigned long portcr_mask;
|
||||
|
||||
static void enable_pint_irq(unsigned int irq);
|
||||
static void disable_pint_irq(unsigned int irq);
|
||||
|
||||
/* shutdown is same as "disable" */
|
||||
#define shutdown_pint_irq disable_pint_irq
|
||||
|
||||
static void mask_and_ack_pint(unsigned int);
|
||||
static void end_pint_irq(unsigned int irq);
|
||||
|
||||
static unsigned int startup_pint_irq(unsigned int irq)
|
||||
{
|
||||
enable_pint_irq(irq);
|
||||
return 0; /* never anything pending */
|
||||
}
|
||||
|
||||
static struct hw_interrupt_type pint_irq_type = {
|
||||
.typename = "PINT-IRQ",
|
||||
.startup = startup_pint_irq,
|
||||
.shutdown = shutdown_pint_irq,
|
||||
.enable = enable_pint_irq,
|
||||
.disable = disable_pint_irq,
|
||||
.ack = mask_and_ack_pint,
|
||||
.end = end_pint_irq
|
||||
};
|
||||
|
||||
static void disable_pint_irq(unsigned int irq)
|
||||
{
|
||||
unsigned long val, flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
val = ctrl_inw(INTC_INTER);
|
||||
val &= ~(1 << (irq - PINT_IRQ_BASE));
|
||||
ctrl_outw(val, INTC_INTER); /* disable PINTn */
|
||||
portcr_mask &= ~(3 << (irq - PINT_IRQ_BASE)*2);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static void enable_pint_irq(unsigned int irq)
|
||||
{
|
||||
unsigned long val, flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
val = ctrl_inw(INTC_INTER);
|
||||
val |= 1 << (irq - PINT_IRQ_BASE);
|
||||
ctrl_outw(val, INTC_INTER); /* enable PINTn */
|
||||
portcr_mask |= 3 << (irq - PINT_IRQ_BASE)*2;
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static void mask_and_ack_pint(unsigned int irq)
|
||||
{
|
||||
disable_pint_irq(irq);
|
||||
}
|
||||
|
||||
static void end_pint_irq(unsigned int irq)
|
||||
{
|
||||
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
|
||||
enable_pint_irq(irq);
|
||||
}
|
||||
|
||||
void make_pint_irq(unsigned int irq)
|
||||
{
|
||||
disable_irq_nosync(irq);
|
||||
irq_desc[irq].handler = &pint_irq_type;
|
||||
disable_pint_irq(irq);
|
||||
}
|
||||
|
||||
void __init init_IRQ_pint(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
make_ipr_irq(PINT0_IRQ, PINT0_IPR_ADDR, PINT0_IPR_POS, PINT0_PRIORITY);
|
||||
make_ipr_irq(PINT8_IRQ, PINT8_IPR_ADDR, PINT8_IPR_POS, PINT8_PRIORITY);
|
||||
|
||||
enable_irq(PINT0_IRQ);
|
||||
enable_irq(PINT8_IRQ);
|
||||
|
||||
for(i = 0; i < 16; i++)
|
||||
make_pint_irq(PINT_IRQ_BASE + i);
|
||||
|
||||
for(i = 0; i < 256; i++) {
|
||||
if (i & 1)
|
||||
pint_map[i] = 0;
|
||||
else if (i & 2)
|
||||
pint_map[i] = 1;
|
||||
else if (i & 4)
|
||||
pint_map[i] = 2;
|
||||
else if (i & 8)
|
||||
pint_map[i] = 3;
|
||||
else if (i & 0x10)
|
||||
pint_map[i] = 4;
|
||||
else if (i & 0x20)
|
||||
pint_map[i] = 5;
|
||||
else if (i & 0x40)
|
||||
pint_map[i] = 6;
|
||||
else if (i & 0x80)
|
||||
pint_map[i] = 7;
|
||||
}
|
||||
}
|
||||
|
||||
int ipr_irq_demux(int irq)
|
||||
{
|
||||
unsigned long creg, dreg, d, sav;
|
||||
|
||||
if (irq == PINT0_IRQ) {
|
||||
#if defined(CONFIG_CPU_SUBTYPE_SH7707)
|
||||
creg = PORT_PACR;
|
||||
dreg = PORT_PADR;
|
||||
#else
|
||||
creg = PORT_PCCR;
|
||||
dreg = PORT_PCDR;
|
||||
#endif
|
||||
sav = ctrl_inw(creg);
|
||||
ctrl_outw(sav | portcr_mask, creg);
|
||||
d = (~ctrl_inb(dreg) ^ ctrl_inw(INTC_ICR2)) &
|
||||
ctrl_inw(INTC_INTER) & 0xff;
|
||||
ctrl_outw(sav, creg);
|
||||
|
||||
if (d == 0)
|
||||
return irq;
|
||||
|
||||
return PINT_IRQ_BASE + pint_map[d];
|
||||
} else if (irq == PINT8_IRQ) {
|
||||
#if defined(CONFIG_CPU_SUBTYPE_SH7707)
|
||||
creg = PORT_PBCR;
|
||||
dreg = PORT_PBDR;
|
||||
#else
|
||||
creg = PORT_PFCR;
|
||||
dreg = PORT_PFDR;
|
||||
#endif
|
||||
sav = ctrl_inw(creg);
|
||||
ctrl_outw(sav | (portcr_mask >> 16), creg);
|
||||
d = (~ctrl_inb(dreg) ^ (ctrl_inw(INTC_ICR2) >> 8)) &
|
||||
(ctrl_inw(INTC_INTER) >> 8) & 0xff;
|
||||
ctrl_outw(sav, creg);
|
||||
|
||||
if (d == 0)
|
||||
return irq;
|
||||
|
||||
return PINT_IRQ_BASE + 8 + pint_map[d];
|
||||
}
|
||||
|
||||
return irq;
|
||||
}
|
||||
|
|
@ -4,3 +4,10 @@
|
|||
|
||||
obj-y := ex.o probe.o
|
||||
|
||||
clock-$(CONFIG_CPU_SH3) := clock-sh3.o
|
||||
clock-$(CONFIG_CPU_SUBTYPE_SH7300) := clock-sh7300.o
|
||||
clock-$(CONFIG_CPU_SUBTYPE_SH7705) := clock-sh7705.o
|
||||
clock-$(CONFIG_CPU_SUBTYPE_SH7709) := clock-sh7709.o
|
||||
|
||||
obj-y += $(clock-y)
|
||||
|
||||
|
|
89
arch/sh/kernel/cpu/sh3/clock-sh3.c
Normal file
89
arch/sh/kernel/cpu/sh3/clock-sh3.c
Normal file
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* arch/sh/kernel/cpu/sh3/clock-sh3.c
|
||||
*
|
||||
* Generic SH-3 support for the clock framework
|
||||
*
|
||||
* Copyright (C) 2005 Paul Mundt
|
||||
*
|
||||
* FRQCR parsing hacked out of arch/sh/kernel/time.c
|
||||
*
|
||||
* Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka
|
||||
* Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
|
||||
* Copyright (C) 2002, 2003, 2004 Paul Mundt
|
||||
* Copyright (C) 2002 M. R. Brown <mrbrown@linux-sh.org>
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <asm/clock.h>
|
||||
#include <asm/freq.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
static int stc_multipliers[] = { 1, 2, 3, 4, 6, 1, 1, 1 };
|
||||
static int ifc_divisors[] = { 1, 2, 3, 4, 1, 1, 1, 1 };
|
||||
static int pfc_divisors[] = { 1, 2, 3, 4, 6, 1, 1, 1 };
|
||||
|
||||
static void master_clk_init(struct clk *clk)
|
||||
{
|
||||
int frqcr = ctrl_inw(FRQCR);
|
||||
int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003);
|
||||
|
||||
clk->rate *= pfc_divisors[idx];
|
||||
}
|
||||
|
||||
static struct clk_ops sh3_master_clk_ops = {
|
||||
.init = master_clk_init,
|
||||
};
|
||||
|
||||
static void module_clk_recalc(struct clk *clk)
|
||||
{
|
||||
int frqcr = ctrl_inw(FRQCR);
|
||||
int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003);
|
||||
|
||||
clk->rate = clk->parent->rate / pfc_divisors[idx];
|
||||
}
|
||||
|
||||
static struct clk_ops sh3_module_clk_ops = {
|
||||
.recalc = module_clk_recalc,
|
||||
};
|
||||
|
||||
static void bus_clk_recalc(struct clk *clk)
|
||||
{
|
||||
int frqcr = ctrl_inw(FRQCR);
|
||||
int idx = ((frqcr & 0x8000) >> 13) | ((frqcr & 0x0030) >> 4);
|
||||
|
||||
clk->rate = clk->parent->rate / stc_multipliers[idx];
|
||||
}
|
||||
|
||||
static struct clk_ops sh3_bus_clk_ops = {
|
||||
.recalc = bus_clk_recalc,
|
||||
};
|
||||
|
||||
static void cpu_clk_recalc(struct clk *clk)
|
||||
{
|
||||
int frqcr = ctrl_inw(FRQCR);
|
||||
int idx = ((frqcr & 0x4000) >> 12) | ((frqcr & 0x000c) >> 2);
|
||||
|
||||
clk->rate = clk->parent->rate / ifc_divisors[idx];
|
||||
}
|
||||
|
||||
static struct clk_ops sh3_cpu_clk_ops = {
|
||||
.recalc = cpu_clk_recalc,
|
||||
};
|
||||
|
||||
static struct clk_ops *sh3_clk_ops[] = {
|
||||
&sh3_master_clk_ops,
|
||||
&sh3_module_clk_ops,
|
||||
&sh3_bus_clk_ops,
|
||||
&sh3_cpu_clk_ops,
|
||||
};
|
||||
|
||||
void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
|
||||
{
|
||||
if (idx < ARRAY_SIZE(sh3_clk_ops))
|
||||
*ops = sh3_clk_ops[idx];
|
||||
}
|
||||
|
78
arch/sh/kernel/cpu/sh3/clock-sh7300.c
Normal file
78
arch/sh/kernel/cpu/sh3/clock-sh7300.c
Normal file
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* arch/sh/kernel/cpu/sh3/clock-sh7300.c
|
||||
*
|
||||
* SH7300 support for the clock framework
|
||||
*
|
||||
* Copyright (C) 2005 Paul Mundt
|
||||
*
|
||||
* FRQCR parsing hacked out of arch/sh/kernel/time.c
|
||||
*
|
||||
* Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka
|
||||
* Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
|
||||
* Copyright (C) 2002, 2003, 2004 Paul Mundt
|
||||
* Copyright (C) 2002 M. R. Brown <mrbrown@linux-sh.org>
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <asm/clock.h>
|
||||
#include <asm/freq.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
static int md_table[] = { 1, 2, 3, 4, 6, 8, 12 };
|
||||
|
||||
static void master_clk_init(struct clk *clk)
|
||||
{
|
||||
clk->rate *= md_table[ctrl_inw(FRQCR) & 0x0007];
|
||||
}
|
||||
|
||||
static struct clk_ops sh7300_master_clk_ops = {
|
||||
.init = master_clk_init,
|
||||
};
|
||||
|
||||
static void module_clk_recalc(struct clk *clk)
|
||||
{
|
||||
int idx = (ctrl_inw(FRQCR) & 0x0007);
|
||||
clk->rate = clk->parent->rate / md_table[idx];
|
||||
}
|
||||
|
||||
static struct clk_ops sh7300_module_clk_ops = {
|
||||
.recalc = module_clk_recalc,
|
||||
};
|
||||
|
||||
static void bus_clk_recalc(struct clk *clk)
|
||||
{
|
||||
int idx = (ctrl_inw(FRQCR) & 0x0700) >> 8;
|
||||
clk->rate = clk->parent->rate / md_table[idx];
|
||||
}
|
||||
|
||||
static struct clk_ops sh7300_bus_clk_ops = {
|
||||
.recalc = bus_clk_recalc,
|
||||
};
|
||||
|
||||
static void cpu_clk_recalc(struct clk *clk)
|
||||
{
|
||||
int idx = (ctrl_inw(FRQCR) & 0x0070) >> 4;
|
||||
clk->rate = clk->parent->rate / md_table[idx];
|
||||
}
|
||||
|
||||
static struct clk_ops sh7300_cpu_clk_ops = {
|
||||
.recalc = cpu_clk_recalc,
|
||||
};
|
||||
|
||||
static struct clk_ops *sh7300_clk_ops[] = {
|
||||
&sh7300_master_clk_ops,
|
||||
&sh7300_module_clk_ops,
|
||||
&sh7300_bus_clk_ops,
|
||||
&sh7300_cpu_clk_ops,
|
||||
};
|
||||
|
||||
void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
|
||||
{
|
||||
if (idx < ARRAY_SIZE(sh7300_clk_ops))
|
||||
*ops = sh7300_clk_ops[idx];
|
||||
}
|
||||
|
84
arch/sh/kernel/cpu/sh3/clock-sh7705.c
Normal file
84
arch/sh/kernel/cpu/sh3/clock-sh7705.c
Normal file
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* arch/sh/kernel/cpu/sh3/clock-sh7705.c
|
||||
*
|
||||
* SH7705 support for the clock framework
|
||||
*
|
||||
* Copyright (C) 2005 Paul Mundt
|
||||
*
|
||||
* FRQCR parsing hacked out of arch/sh/kernel/time.c
|
||||
*
|
||||
* Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka
|
||||
* Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
|
||||
* Copyright (C) 2002, 2003, 2004 Paul Mundt
|
||||
* Copyright (C) 2002 M. R. Brown <mrbrown@linux-sh.org>
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <asm/clock.h>
|
||||
#include <asm/freq.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
/*
|
||||
* SH7705 uses the same divisors as the generic SH-3 case, it's just the
|
||||
* FRQCR layout that is a bit different..
|
||||
*/
|
||||
static int stc_multipliers[] = { 1, 2, 3, 4, 6, 1, 1, 1 };
|
||||
static int ifc_divisors[] = { 1, 2, 3, 4, 1, 1, 1, 1 };
|
||||
static int pfc_divisors[] = { 1, 2, 3, 4, 6, 1, 1, 1 };
|
||||
|
||||
static void master_clk_init(struct clk *clk)
|
||||
{
|
||||
clk->rate *= pfc_divisors[ctrl_inw(FRQCR) & 0x0003];
|
||||
}
|
||||
|
||||
static struct clk_ops sh7705_master_clk_ops = {
|
||||
.init = master_clk_init,
|
||||
};
|
||||
|
||||
static void module_clk_recalc(struct clk *clk)
|
||||
{
|
||||
int idx = ctrl_inw(FRQCR) & 0x0003;
|
||||
clk->rate = clk->parent->rate / pfc_divisors[idx];
|
||||
}
|
||||
|
||||
static struct clk_ops sh7705_module_clk_ops = {
|
||||
.recalc = module_clk_recalc,
|
||||
};
|
||||
|
||||
static void bus_clk_recalc(struct clk *clk)
|
||||
{
|
||||
int idx = (ctrl_inw(FRQCR) & 0x0300) >> 8;
|
||||
clk->rate = clk->parent->rate / stc_multipliers[idx];
|
||||
}
|
||||
|
||||
static struct clk_ops sh7705_bus_clk_ops = {
|
||||
.recalc = bus_clk_recalc,
|
||||
};
|
||||
|
||||
static void cpu_clk_recalc(struct clk *clk)
|
||||
{
|
||||
int idx = (ctrl_inw(FRQCR) & 0x0030) >> 4;
|
||||
clk->rate = clk->parent->rate / ifc_divisors[idx];
|
||||
}
|
||||
|
||||
static struct clk_ops sh7705_cpu_clk_ops = {
|
||||
.recalc = cpu_clk_recalc,
|
||||
};
|
||||
|
||||
static struct clk_ops *sh7705_clk_ops[] = {
|
||||
&sh7705_master_clk_ops,
|
||||
&sh7705_module_clk_ops,
|
||||
&sh7705_bus_clk_ops,
|
||||
&sh7705_cpu_clk_ops,
|
||||
};
|
||||
|
||||
void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
|
||||
{
|
||||
if (idx < ARRAY_SIZE(sh7705_clk_ops))
|
||||
*ops = sh7705_clk_ops[idx];
|
||||
}
|
||||
|
96
arch/sh/kernel/cpu/sh3/clock-sh7709.c
Normal file
96
arch/sh/kernel/cpu/sh3/clock-sh7709.c
Normal file
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* arch/sh/kernel/cpu/sh3/clock-sh7709.c
|
||||
*
|
||||
* SH7709 support for the clock framework
|
||||
*
|
||||
* Copyright (C) 2005 Andriy Skulysh
|
||||
*
|
||||
* Based on arch/sh/kernel/cpu/sh3/clock-sh7705.c
|
||||
* Copyright (C) 2005 Paul Mundt
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <asm/clock.h>
|
||||
#include <asm/freq.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
static int stc_multipliers[] = { 1, 2, 4, 8, 3, 6, 1, 1 };
|
||||
static int ifc_divisors[] = { 1, 2, 4, 1, 3, 1, 1, 1 };
|
||||
static int pfc_divisors[] = { 1, 2, 4, 1, 3, 6, 1, 1 };
|
||||
|
||||
static void set_bus_parent(struct clk *clk)
|
||||
{
|
||||
struct clk *bus_clk = clk_get("bus_clk");
|
||||
clk->parent = bus_clk;
|
||||
clk_put(bus_clk);
|
||||
}
|
||||
|
||||
static void master_clk_init(struct clk *clk)
|
||||
{
|
||||
int frqcr = ctrl_inw(FRQCR);
|
||||
int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003);
|
||||
|
||||
clk->rate *= pfc_divisors[idx];
|
||||
}
|
||||
|
||||
static struct clk_ops sh7709_master_clk_ops = {
|
||||
.init = master_clk_init,
|
||||
};
|
||||
|
||||
static void module_clk_recalc(struct clk *clk)
|
||||
{
|
||||
int frqcr = ctrl_inw(FRQCR);
|
||||
int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003);
|
||||
|
||||
clk->rate = clk->parent->rate / pfc_divisors[idx];
|
||||
}
|
||||
|
||||
static struct clk_ops sh7709_module_clk_ops = {
|
||||
#ifdef CLOCK_MODE_0_1_2_7
|
||||
.init = set_bus_parent,
|
||||
#endif
|
||||
.recalc = module_clk_recalc,
|
||||
};
|
||||
|
||||
static void bus_clk_recalc(struct clk *clk)
|
||||
{
|
||||
int frqcr = ctrl_inw(FRQCR);
|
||||
int idx = (frqcr & 0x0080) ?
|
||||
((frqcr & 0x8000) >> 13) | ((frqcr & 0x0030) >> 4) : 1;
|
||||
|
||||
clk->rate = clk->parent->rate * stc_multipliers[idx];
|
||||
}
|
||||
|
||||
static struct clk_ops sh7709_bus_clk_ops = {
|
||||
.recalc = bus_clk_recalc,
|
||||
};
|
||||
|
||||
static void cpu_clk_recalc(struct clk *clk)
|
||||
{
|
||||
int frqcr = ctrl_inw(FRQCR);
|
||||
int idx = ((frqcr & 0x4000) >> 12) | ((frqcr & 0x000c) >> 2);
|
||||
|
||||
clk->rate = clk->parent->rate / ifc_divisors[idx];
|
||||
}
|
||||
|
||||
static struct clk_ops sh7709_cpu_clk_ops = {
|
||||
.init = set_bus_parent,
|
||||
.recalc = cpu_clk_recalc,
|
||||
};
|
||||
|
||||
static struct clk_ops *sh7709_clk_ops[] = {
|
||||
&sh7709_master_clk_ops,
|
||||
&sh7709_module_clk_ops,
|
||||
&sh7709_bus_clk_ops,
|
||||
&sh7709_cpu_clk_ops,
|
||||
};
|
||||
|
||||
void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
|
||||
{
|
||||
if (idx < ARRAY_SIZE(sh7709_clk_ops))
|
||||
*ops = sh7709_clk_ops[idx];
|
||||
}
|
|
@ -5,6 +5,15 @@
|
|||
obj-y := ex.o probe.o
|
||||
|
||||
obj-$(CONFIG_SH_FPU) += fpu.o
|
||||
obj-$(CONFIG_CPU_SUBTYPE_ST40STB1) += irq_intc2.o
|
||||
obj-$(CONFIG_SH_STORE_QUEUES) += sq.o
|
||||
|
||||
# Primary on-chip clocks (common)
|
||||
clock-$(CONFIG_CPU_SH4) := clock-sh4.o
|
||||
clock-$(CONFIG_CPU_SUBTYPE_SH73180) := clock-sh73180.o
|
||||
clock-$(CONFIG_CPU_SUBTYPE_SH7770) := clock-sh7770.o
|
||||
clock-$(CONFIG_CPU_SUBTYPE_SH7780) := clock-sh7780.o
|
||||
|
||||
# Additional clocks by subtype
|
||||
clock-$(CONFIG_CPU_SUBTYPE_SH4_202) += clock-sh4-202.o
|
||||
|
||||
obj-y += $(clock-y)
|
||||
|
|
179
arch/sh/kernel/cpu/sh4/clock-sh4-202.c
Normal file
179
arch/sh/kernel/cpu/sh4/clock-sh4-202.c
Normal file
|
@ -0,0 +1,179 @@
|
|||
/*
|
||||
* arch/sh/kernel/cpu/sh4/clock-sh4-202.c
|
||||
*
|
||||
* Additional SH4-202 support for the clock framework
|
||||
*
|
||||
* Copyright (C) 2005 Paul Mundt
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/err.h>
|
||||
#include <asm/clock.h>
|
||||
#include <asm/freq.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#define CPG2_FRQCR3 0xfe0a0018
|
||||
|
||||
static int frqcr3_divisors[] = { 1, 2, 3, 4, 6, 8, 16 };
|
||||
static int frqcr3_values[] = { 0, 1, 2, 3, 4, 5, 6 };
|
||||
|
||||
static void emi_clk_recalc(struct clk *clk)
|
||||
{
|
||||
int idx = ctrl_inl(CPG2_FRQCR3) & 0x0007;
|
||||
clk->rate = clk->parent->rate / frqcr3_divisors[idx];
|
||||
}
|
||||
|
||||
static inline int frqcr3_lookup(struct clk *clk, unsigned long rate)
|
||||
{
|
||||
int divisor = clk->parent->rate / rate;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(frqcr3_divisors); i++)
|
||||
if (frqcr3_divisors[i] == divisor)
|
||||
return frqcr3_values[i];
|
||||
|
||||
/* Safe fallback */
|
||||
return 5;
|
||||
}
|
||||
|
||||
static struct clk_ops sh4202_emi_clk_ops = {
|
||||
.recalc = emi_clk_recalc,
|
||||
};
|
||||
|
||||
static struct clk sh4202_emi_clk = {
|
||||
.name = "emi_clk",
|
||||
.flags = CLK_ALWAYS_ENABLED,
|
||||
.ops = &sh4202_emi_clk_ops,
|
||||
};
|
||||
|
||||
static void femi_clk_recalc(struct clk *clk)
|
||||
{
|
||||
int idx = (ctrl_inl(CPG2_FRQCR3) >> 3) & 0x0007;
|
||||
clk->rate = clk->parent->rate / frqcr3_divisors[idx];
|
||||
}
|
||||
|
||||
static struct clk_ops sh4202_femi_clk_ops = {
|
||||
.recalc = femi_clk_recalc,
|
||||
};
|
||||
|
||||
static struct clk sh4202_femi_clk = {
|
||||
.name = "femi_clk",
|
||||
.flags = CLK_ALWAYS_ENABLED,
|
||||
.ops = &sh4202_femi_clk_ops,
|
||||
};
|
||||
|
||||
static void shoc_clk_init(struct clk *clk)
|
||||
{
|
||||
int i;
|
||||
|
||||
/*
|
||||
* For some reason, the shoc_clk seems to be set to some really
|
||||
* insane value at boot (values outside of the allowable frequency
|
||||
* range for instance). We deal with this by scaling it back down
|
||||
* to something sensible just in case.
|
||||
*
|
||||
* Start scaling from the high end down until we find something
|
||||
* that passes rate verification..
|
||||
*/
|
||||
for (i = 0; i < ARRAY_SIZE(frqcr3_divisors); i++) {
|
||||
int divisor = frqcr3_divisors[i];
|
||||
|
||||
if (clk->ops->set_rate(clk, clk->parent->rate / divisor) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
WARN_ON(i == ARRAY_SIZE(frqcr3_divisors)); /* Undefined clock */
|
||||
}
|
||||
|
||||
static void shoc_clk_recalc(struct clk *clk)
|
||||
{
|
||||
int idx = (ctrl_inl(CPG2_FRQCR3) >> 6) & 0x0007;
|
||||
clk->rate = clk->parent->rate / frqcr3_divisors[idx];
|
||||
}
|
||||
|
||||
static int shoc_clk_verify_rate(struct clk *clk, unsigned long rate)
|
||||
{
|
||||
struct clk *bclk = clk_get("bus_clk");
|
||||
unsigned long bclk_rate = clk_get_rate(bclk);
|
||||
|
||||
clk_put(bclk);
|
||||
|
||||
if (rate > bclk_rate)
|
||||
return 1;
|
||||
if (rate > 66000000)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int shoc_clk_set_rate(struct clk *clk, unsigned long rate)
|
||||
{
|
||||
unsigned long frqcr3;
|
||||
unsigned int tmp;
|
||||
|
||||
/* Make sure we have something sensible to switch to */
|
||||
if (shoc_clk_verify_rate(clk, rate) != 0)
|
||||
return -EINVAL;
|
||||
|
||||
tmp = frqcr3_lookup(clk, rate);
|
||||
|
||||
frqcr3 = ctrl_inl(CPG2_FRQCR3);
|
||||
frqcr3 &= ~(0x0007 << 6);
|
||||
frqcr3 |= tmp << 6;
|
||||
ctrl_outl(frqcr3, CPG2_FRQCR3);
|
||||
|
||||
clk->rate = clk->parent->rate / frqcr3_divisors[tmp];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct clk_ops sh4202_shoc_clk_ops = {
|
||||
.init = shoc_clk_init,
|
||||
.recalc = shoc_clk_recalc,
|
||||
.set_rate = shoc_clk_set_rate,
|
||||
};
|
||||
|
||||
static struct clk sh4202_shoc_clk = {
|
||||
.name = "shoc_clk",
|
||||
.flags = CLK_ALWAYS_ENABLED,
|
||||
.ops = &sh4202_shoc_clk_ops,
|
||||
};
|
||||
|
||||
static struct clk *sh4202_onchip_clocks[] = {
|
||||
&sh4202_emi_clk,
|
||||
&sh4202_femi_clk,
|
||||
&sh4202_shoc_clk,
|
||||
};
|
||||
|
||||
static int __init sh4202_clk_init(void)
|
||||
{
|
||||
struct clk *clk = clk_get("master_clk");
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sh4202_onchip_clocks); i++) {
|
||||
struct clk *clkp = sh4202_onchip_clocks[i];
|
||||
|
||||
clkp->parent = clk;
|
||||
clk_register(clkp);
|
||||
clk_enable(clkp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Now that we have the rest of the clocks registered, we need to
|
||||
* force the parent clock to propagate so that these clocks will
|
||||
* automatically figure out their rate. We cheat by handing the
|
||||
* parent clock its current rate and forcing child propagation.
|
||||
*/
|
||||
clk_set_rate(clk, clk_get_rate(clk));
|
||||
|
||||
clk_put(clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
arch_initcall(sh4202_clk_init);
|
||||
|
80
arch/sh/kernel/cpu/sh4/clock-sh4.c
Normal file
80
arch/sh/kernel/cpu/sh4/clock-sh4.c
Normal file
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* arch/sh/kernel/cpu/sh4/clock-sh4.c
|
||||
*
|
||||
* Generic SH-4 support for the clock framework
|
||||
*
|
||||
* Copyright (C) 2005 Paul Mundt
|
||||
*
|
||||
* FRQCR parsing hacked out of arch/sh/kernel/time.c
|
||||
*
|
||||
* Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka
|
||||
* Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
|
||||
* Copyright (C) 2002, 2003, 2004 Paul Mundt
|
||||
* Copyright (C) 2002 M. R. Brown <mrbrown@linux-sh.org>
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <asm/clock.h>
|
||||
#include <asm/freq.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
static int ifc_divisors[] = { 1, 2, 3, 4, 6, 8, 1, 1 };
|
||||
#define bfc_divisors ifc_divisors /* Same */
|
||||
static int pfc_divisors[] = { 2, 3, 4, 6, 8, 2, 2, 2 };
|
||||
|
||||
static void master_clk_init(struct clk *clk)
|
||||
{
|
||||
clk->rate *= pfc_divisors[ctrl_inw(FRQCR) & 0x0007];
|
||||
}
|
||||
|
||||
static struct clk_ops sh4_master_clk_ops = {
|
||||
.init = master_clk_init,
|
||||
};
|
||||
|
||||
static void module_clk_recalc(struct clk *clk)
|
||||
{
|
||||
int idx = (ctrl_inw(FRQCR) & 0x0007);
|
||||
clk->rate = clk->parent->rate / pfc_divisors[idx];
|
||||
}
|
||||
|
||||
static struct clk_ops sh4_module_clk_ops = {
|
||||
.recalc = module_clk_recalc,
|
||||
};
|
||||
|
||||
static void bus_clk_recalc(struct clk *clk)
|
||||
{
|
||||
int idx = (ctrl_inw(FRQCR) >> 3) & 0x0007;
|
||||
clk->rate = clk->parent->rate / bfc_divisors[idx];
|
||||
}
|
||||
|
||||
static struct clk_ops sh4_bus_clk_ops = {
|
||||
.recalc = bus_clk_recalc,
|
||||
};
|
||||
|
||||
static void cpu_clk_recalc(struct clk *clk)
|
||||
{
|
||||
int idx = (ctrl_inw(FRQCR) >> 6) & 0x0007;
|
||||
clk->rate = clk->parent->rate / ifc_divisors[idx];
|
||||
}
|
||||
|
||||
static struct clk_ops sh4_cpu_clk_ops = {
|
||||
.recalc = cpu_clk_recalc,
|
||||
};
|
||||
|
||||
static struct clk_ops *sh4_clk_ops[] = {
|
||||
&sh4_master_clk_ops,
|
||||
&sh4_module_clk_ops,
|
||||
&sh4_bus_clk_ops,
|
||||
&sh4_cpu_clk_ops,
|
||||
};
|
||||
|
||||
void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
|
||||
{
|
||||
if (idx < ARRAY_SIZE(sh4_clk_ops))
|
||||
*ops = sh4_clk_ops[idx];
|
||||
}
|
||||
|
81
arch/sh/kernel/cpu/sh4/clock-sh73180.c
Normal file
81
arch/sh/kernel/cpu/sh4/clock-sh73180.c
Normal file
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* arch/sh/kernel/cpu/sh4/clock-sh73180.c
|
||||
*
|
||||
* SH73180 support for the clock framework
|
||||
*
|
||||
* Copyright (C) 2005 Paul Mundt
|
||||
*
|
||||
* FRQCR parsing hacked out of arch/sh/kernel/time.c
|
||||
*
|
||||
* Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka
|
||||
* Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
|
||||
* Copyright (C) 2002, 2003, 2004 Paul Mundt
|
||||
* Copyright (C) 2002 M. R. Brown <mrbrown@linux-sh.org>
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <asm/clock.h>
|
||||
#include <asm/freq.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
/*
|
||||
* SH73180 uses a common set of divisors, so this is quite simple..
|
||||
*/
|
||||
static int divisors[] = { 1, 2, 3, 4, 6, 8, 12, 16 };
|
||||
|
||||
static void master_clk_init(struct clk *clk)
|
||||
{
|
||||
clk->rate *= divisors[ctrl_inl(FRQCR) & 0x0007];
|
||||
}
|
||||
|
||||
static struct clk_ops sh73180_master_clk_ops = {
|
||||
.init = master_clk_init,
|
||||
};
|
||||
|
||||
static void module_clk_recalc(struct clk *clk)
|
||||
{
|
||||
int idx = (ctrl_inl(FRQCR) & 0x0007);
|
||||
clk->rate = clk->parent->rate / divisors[idx];
|
||||
}
|
||||
|
||||
static struct clk_ops sh73180_module_clk_ops = {
|
||||
.recalc = module_clk_recalc,
|
||||
};
|
||||
|
||||
static void bus_clk_recalc(struct clk *clk)
|
||||
{
|
||||
int idx = (ctrl_inl(FRQCR) >> 12) & 0x0007;
|
||||
clk->rate = clk->parent->rate / divisors[idx];
|
||||
}
|
||||
|
||||
static struct clk_ops sh73180_bus_clk_ops = {
|
||||
.recalc = bus_clk_recalc,
|
||||
};
|
||||
|
||||
static void cpu_clk_recalc(struct clk *clk)
|
||||
{
|
||||
int idx = (ctrl_inl(FRQCR) >> 20) & 0x0007;
|
||||
clk->rate = clk->parent->rate / divisors[idx];
|
||||
}
|
||||
|
||||
static struct clk_ops sh73180_cpu_clk_ops = {
|
||||
.recalc = cpu_clk_recalc,
|
||||
};
|
||||
|
||||
static struct clk_ops *sh73180_clk_ops[] = {
|
||||
&sh73180_master_clk_ops,
|
||||
&sh73180_module_clk_ops,
|
||||
&sh73180_bus_clk_ops,
|
||||
&sh73180_cpu_clk_ops,
|
||||
};
|
||||
|
||||
void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
|
||||
{
|
||||
if (idx < ARRAY_SIZE(sh73180_clk_ops))
|
||||
*ops = sh73180_clk_ops[idx];
|
||||
}
|
||||
|
73
arch/sh/kernel/cpu/sh4/clock-sh7770.c
Normal file
73
arch/sh/kernel/cpu/sh4/clock-sh7770.c
Normal file
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* arch/sh/kernel/cpu/sh4/clock-sh7770.c
|
||||
*
|
||||
* SH7770 support for the clock framework
|
||||
*
|
||||
* Copyright (C) 2005 Paul Mundt
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <asm/clock.h>
|
||||
#include <asm/freq.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
static int ifc_divisors[] = { 1, 1, 1, 1, 1, 1, 1, 1 };
|
||||
static int bfc_divisors[] = { 1, 1, 1, 1, 1, 8,12, 1 };
|
||||
static int pfc_divisors[] = { 1, 8, 1,10,12,16, 1, 1 };
|
||||
|
||||
static void master_clk_init(struct clk *clk)
|
||||
{
|
||||
clk->rate *= pfc_divisors[(ctrl_inl(FRQCR) >> 28) & 0x000f];
|
||||
}
|
||||
|
||||
static struct clk_ops sh7770_master_clk_ops = {
|
||||
.init = master_clk_init,
|
||||
};
|
||||
|
||||
static void module_clk_recalc(struct clk *clk)
|
||||
{
|
||||
int idx = ((ctrl_inl(FRQCR) >> 28) & 0x000f);
|
||||
clk->rate = clk->parent->rate / pfc_divisors[idx];
|
||||
}
|
||||
|
||||
static struct clk_ops sh7770_module_clk_ops = {
|
||||
.recalc = module_clk_recalc,
|
||||
};
|
||||
|
||||
static void bus_clk_recalc(struct clk *clk)
|
||||
{
|
||||
int idx = (ctrl_inl(FRQCR) & 0x000f);
|
||||
clk->rate = clk->parent->rate / bfc_divisors[idx];
|
||||
}
|
||||
|
||||
static struct clk_ops sh7770_bus_clk_ops = {
|
||||
.recalc = bus_clk_recalc,
|
||||
};
|
||||
|
||||
static void cpu_clk_recalc(struct clk *clk)
|
||||
{
|
||||
int idx = ((ctrl_inl(FRQCR) >> 24) & 0x000f);
|
||||
clk->rate = clk->parent->rate / ifc_divisors[idx];
|
||||
}
|
||||
|
||||
static struct clk_ops sh7770_cpu_clk_ops = {
|
||||
.recalc = cpu_clk_recalc,
|
||||
};
|
||||
|
||||
static struct clk_ops *sh7770_clk_ops[] = {
|
||||
&sh7770_master_clk_ops,
|
||||
&sh7770_module_clk_ops,
|
||||
&sh7770_bus_clk_ops,
|
||||
&sh7770_cpu_clk_ops,
|
||||
};
|
||||
|
||||
void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
|
||||
{
|
||||
if (idx < ARRAY_SIZE(sh7770_clk_ops))
|
||||
*ops = sh7770_clk_ops[idx];
|
||||
}
|
||||
|
126
arch/sh/kernel/cpu/sh4/clock-sh7780.c
Normal file
126
arch/sh/kernel/cpu/sh4/clock-sh7780.c
Normal file
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* arch/sh/kernel/cpu/sh4/clock-sh7780.c
|
||||
*
|
||||
* SH7780 support for the clock framework
|
||||
*
|
||||
* Copyright (C) 2005 Paul Mundt
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <asm/clock.h>
|
||||
#include <asm/freq.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
static int ifc_divisors[] = { 2, 4 };
|
||||
static int bfc_divisors[] = { 1, 1, 1, 8, 12, 16, 24, 1 };
|
||||
static int pfc_divisors[] = { 1, 24, 24, 1 };
|
||||
static int cfc_divisors[] = { 1, 1, 4, 1, 6, 1, 1, 1 };
|
||||
|
||||
static void master_clk_init(struct clk *clk)
|
||||
{
|
||||
clk->rate *= pfc_divisors[ctrl_inl(FRQCR) & 0x0003];
|
||||
}
|
||||
|
||||
static struct clk_ops sh7780_master_clk_ops = {
|
||||
.init = master_clk_init,
|
||||
};
|
||||
|
||||
static void module_clk_recalc(struct clk *clk)
|
||||
{
|
||||
int idx = (ctrl_inl(FRQCR) & 0x0003);
|
||||
clk->rate = clk->parent->rate / pfc_divisors[idx];
|
||||
}
|
||||
|
||||
static struct clk_ops sh7780_module_clk_ops = {
|
||||
.recalc = module_clk_recalc,
|
||||
};
|
||||
|
||||
static void bus_clk_recalc(struct clk *clk)
|
||||
{
|
||||
int idx = ((ctrl_inl(FRQCR) >> 16) & 0x0007);
|
||||
clk->rate = clk->parent->rate / bfc_divisors[idx];
|
||||
}
|
||||
|
||||
static struct clk_ops sh7780_bus_clk_ops = {
|
||||
.recalc = bus_clk_recalc,
|
||||
};
|
||||
|
||||
static void cpu_clk_recalc(struct clk *clk)
|
||||
{
|
||||
int idx = ((ctrl_inl(FRQCR) >> 24) & 0x0001);
|
||||
clk->rate = clk->parent->rate / ifc_divisors[idx];
|
||||
}
|
||||
|
||||
static struct clk_ops sh7780_cpu_clk_ops = {
|
||||
.recalc = cpu_clk_recalc,
|
||||
};
|
||||
|
||||
static struct clk_ops *sh7780_clk_ops[] = {
|
||||
&sh7780_master_clk_ops,
|
||||
&sh7780_module_clk_ops,
|
||||
&sh7780_bus_clk_ops,
|
||||
&sh7780_cpu_clk_ops,
|
||||
};
|
||||
|
||||
void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
|
||||
{
|
||||
if (idx < ARRAY_SIZE(sh7780_clk_ops))
|
||||
*ops = sh7780_clk_ops[idx];
|
||||
}
|
||||
|
||||
static void shyway_clk_recalc(struct clk *clk)
|
||||
{
|
||||
int idx = ((ctrl_inl(FRQCR) >> 20) & 0x0007);
|
||||
clk->rate = clk->parent->rate / cfc_divisors[idx];
|
||||
}
|
||||
|
||||
static struct clk_ops sh7780_shyway_clk_ops = {
|
||||
.recalc = shyway_clk_recalc,
|
||||
};
|
||||
|
||||
static struct clk sh7780_shyway_clk = {
|
||||
.name = "shyway_clk",
|
||||
.flags = CLK_ALWAYS_ENABLED,
|
||||
.ops = &sh7780_shyway_clk_ops,
|
||||
};
|
||||
|
||||
/*
|
||||
* Additional SH7780-specific on-chip clocks that aren't already part of the
|
||||
* clock framework
|
||||
*/
|
||||
static struct clk *sh7780_onchip_clocks[] = {
|
||||
&sh7780_shyway_clk,
|
||||
};
|
||||
|
||||
static int __init sh7780_clk_init(void)
|
||||
{
|
||||
struct clk *clk = clk_get("master_clk");
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sh7780_onchip_clocks); i++) {
|
||||
struct clk *clkp = sh7780_onchip_clocks[i];
|
||||
|
||||
clkp->parent = clk;
|
||||
clk_register(clkp);
|
||||
clk_enable(clkp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Now that we have the rest of the clocks registered, we need to
|
||||
* force the parent clock to propagate so that these clocks will
|
||||
* automatically figure out their rate. We cheat by handing the
|
||||
* parent clock its current rate and forcing child propagation.
|
||||
*/
|
||||
clk_set_rate(clk, clk_get_rate(clk));
|
||||
|
||||
clk_put(clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
arch_initcall(sh7780_clk_init);
|
||||
|
|
@ -1,222 +0,0 @@
|
|||
/*
|
||||
* linux/arch/sh/kernel/irq_intc2.c
|
||||
*
|
||||
* Copyright (C) 2001 David J. Mckay (david.mckay@st.com)
|
||||
*
|
||||
* May be copied or modified under the terms of the GNU General Public
|
||||
* License. See linux/COPYING for more information.
|
||||
*
|
||||
* Interrupt handling for INTC2-based IRQ.
|
||||
*
|
||||
* These are the "new Hitachi style" interrupts, as present on the
|
||||
* Hitachi 7751 and the STM ST40 STB1.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/irq.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/machvec.h>
|
||||
|
||||
|
||||
struct intc2_data {
|
||||
unsigned char msk_offset;
|
||||
unsigned char msk_shift;
|
||||
#ifdef CONFIG_CPU_SUBTYPE_ST40
|
||||
int (*clear_irq) (int);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
static struct intc2_data intc2_data[NR_INTC2_IRQS];
|
||||
|
||||
static void enable_intc2_irq(unsigned int irq);
|
||||
static void disable_intc2_irq(unsigned int irq);
|
||||
|
||||
/* shutdown is same as "disable" */
|
||||
#define shutdown_intc2_irq disable_intc2_irq
|
||||
|
||||
static void mask_and_ack_intc2(unsigned int);
|
||||
static void end_intc2_irq(unsigned int irq);
|
||||
|
||||
static unsigned int startup_intc2_irq(unsigned int irq)
|
||||
{
|
||||
enable_intc2_irq(irq);
|
||||
return 0; /* never anything pending */
|
||||
}
|
||||
|
||||
static struct hw_interrupt_type intc2_irq_type = {
|
||||
.typename = "INTC2-IRQ",
|
||||
.startup = startup_intc2_irq,
|
||||
.shutdown = shutdown_intc2_irq,
|
||||
.enable = enable_intc2_irq,
|
||||
.disable = disable_intc2_irq,
|
||||
.ack = mask_and_ack_intc2,
|
||||
.end = end_intc2_irq
|
||||
};
|
||||
|
||||
static void disable_intc2_irq(unsigned int irq)
|
||||
{
|
||||
int irq_offset = irq - INTC2_FIRST_IRQ;
|
||||
int msk_shift, msk_offset;
|
||||
|
||||
// Sanity check
|
||||
if((irq_offset<0) || (irq_offset>=NR_INTC2_IRQS))
|
||||
return;
|
||||
|
||||
msk_shift = intc2_data[irq_offset].msk_shift;
|
||||
msk_offset = intc2_data[irq_offset].msk_offset;
|
||||
|
||||
ctrl_outl(1<<msk_shift,
|
||||
INTC2_BASE+INTC2_INTMSK_OFFSET+msk_offset);
|
||||
}
|
||||
|
||||
static void enable_intc2_irq(unsigned int irq)
|
||||
{
|
||||
int irq_offset = irq - INTC2_FIRST_IRQ;
|
||||
int msk_shift, msk_offset;
|
||||
|
||||
/* Sanity check */
|
||||
if((irq_offset<0) || (irq_offset>=NR_INTC2_IRQS))
|
||||
return;
|
||||
|
||||
msk_shift = intc2_data[irq_offset].msk_shift;
|
||||
msk_offset = intc2_data[irq_offset].msk_offset;
|
||||
|
||||
ctrl_outl(1<<msk_shift,
|
||||
INTC2_BASE+INTC2_INTMSKCLR_OFFSET+msk_offset);
|
||||
}
|
||||
|
||||
static void mask_and_ack_intc2(unsigned int irq)
|
||||
{
|
||||
disable_intc2_irq(irq);
|
||||
}
|
||||
|
||||
static void end_intc2_irq(unsigned int irq)
|
||||
{
|
||||
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
|
||||
enable_intc2_irq(irq);
|
||||
|
||||
#ifdef CONFIG_CPU_SUBTYPE_ST40
|
||||
if (intc2_data[irq - INTC2_FIRST_IRQ].clear_irq)
|
||||
intc2_data[irq - INTC2_FIRST_IRQ].clear_irq (irq);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup an INTC2 style interrupt.
|
||||
* NOTE: Unlike IPR interrupts, parameters are not shifted by this code,
|
||||
* allowing the use of the numbers straight out of the datasheet.
|
||||
* For example:
|
||||
* PIO1 which is INTPRI00[19,16] and INTMSK00[13]
|
||||
* would be: ^ ^ ^ ^
|
||||
* | | | |
|
||||
* make_intc2_irq(84, 0, 16, 0, 13);
|
||||
*/
|
||||
void make_intc2_irq(unsigned int irq,
|
||||
unsigned int ipr_offset, unsigned int ipr_shift,
|
||||
unsigned int msk_offset, unsigned int msk_shift,
|
||||
unsigned int priority)
|
||||
{
|
||||
int irq_offset = irq - INTC2_FIRST_IRQ;
|
||||
unsigned int flags;
|
||||
unsigned long ipr;
|
||||
|
||||
if((irq_offset<0) || (irq_offset>=NR_INTC2_IRQS))
|
||||
return;
|
||||
|
||||
disable_irq_nosync(irq);
|
||||
|
||||
/* Fill the data we need */
|
||||
intc2_data[irq_offset].msk_offset = msk_offset;
|
||||
intc2_data[irq_offset].msk_shift = msk_shift;
|
||||
#ifdef CONFIG_CPU_SUBTYPE_ST40
|
||||
intc2_data[irq_offset].clear_irq = NULL;
|
||||
#endif
|
||||
|
||||
/* Set the priority level */
|
||||
local_irq_save(flags);
|
||||
|
||||
ipr=ctrl_inl(INTC2_BASE+INTC2_INTPRI_OFFSET+ipr_offset);
|
||||
ipr&=~(0xf<<ipr_shift);
|
||||
ipr|=(priority)<<ipr_shift;
|
||||
ctrl_outl(ipr, INTC2_BASE+INTC2_INTPRI_OFFSET+ipr_offset);
|
||||
|
||||
local_irq_restore(flags);
|
||||
|
||||
irq_desc[irq].handler=&intc2_irq_type;
|
||||
|
||||
disable_intc2_irq(irq);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CPU_SUBTYPE_ST40
|
||||
|
||||
struct intc2_init {
|
||||
unsigned short irq;
|
||||
unsigned char ipr_offset, ipr_shift;
|
||||
unsigned char msk_offset, msk_shift;
|
||||
};
|
||||
|
||||
static struct intc2_init intc2_init_data[] __initdata = {
|
||||
{64, 0, 0, 0, 0}, /* PCI serr */
|
||||
{65, 0, 4, 0, 1}, /* PCI err */
|
||||
{66, 0, 4, 0, 2}, /* PCI ad */
|
||||
{67, 0, 4, 0, 3}, /* PCI pwd down */
|
||||
{72, 0, 8, 0, 5}, /* DMAC INT0 */
|
||||
{73, 0, 8, 0, 6}, /* DMAC INT1 */
|
||||
{74, 0, 8, 0, 7}, /* DMAC INT2 */
|
||||
{75, 0, 8, 0, 8}, /* DMAC INT3 */
|
||||
{76, 0, 8, 0, 9}, /* DMAC INT4 */
|
||||
{78, 0, 8, 0, 11}, /* DMAC ERR */
|
||||
{80, 0, 12, 0, 12}, /* PIO0 */
|
||||
{84, 0, 16, 0, 13}, /* PIO1 */
|
||||
{88, 0, 20, 0, 14}, /* PIO2 */
|
||||
{112, 4, 0, 4, 0}, /* Mailbox */
|
||||
#ifdef CONFIG_CPU_SUBTYPE_ST40GX1
|
||||
{116, 4, 4, 4, 4}, /* SSC0 */
|
||||
{120, 4, 8, 4, 8}, /* IR Blaster */
|
||||
{124, 4, 12, 4, 12}, /* USB host */
|
||||
{128, 4, 16, 4, 16}, /* Video processor BLITTER */
|
||||
{132, 4, 20, 4, 20}, /* UART0 */
|
||||
{134, 4, 20, 4, 22}, /* UART2 */
|
||||
{136, 4, 24, 4, 24}, /* IO_PIO0 */
|
||||
{140, 4, 28, 4, 28}, /* EMPI */
|
||||
{144, 8, 0, 8, 0}, /* MAFE */
|
||||
{148, 8, 4, 8, 4}, /* PWM */
|
||||
{152, 8, 8, 8, 8}, /* SSC1 */
|
||||
{156, 8, 12, 8, 12}, /* IO_PIO1 */
|
||||
{160, 8, 16, 8, 16}, /* USB target */
|
||||
{164, 8, 20, 8, 20}, /* UART1 */
|
||||
{168, 8, 24, 8, 24}, /* Teletext */
|
||||
{172, 8, 28, 8, 28}, /* VideoSync VTG */
|
||||
{173, 8, 28, 8, 29}, /* VideoSync DVP0 */
|
||||
{174, 8, 28, 8, 30}, /* VideoSync DVP1 */
|
||||
#endif
|
||||
};
|
||||
|
||||
void __init init_IRQ_intc2(void)
|
||||
{
|
||||
struct intc2_init *p;
|
||||
|
||||
printk(KERN_ALERT "init_IRQ_intc2\n");
|
||||
|
||||
for (p = intc2_init_data;
|
||||
p<intc2_init_data+ARRAY_SIZE(intc2_init_data);
|
||||
p++) {
|
||||
make_intc2_irq(p->irq, p->ipr_offset, p->ipr_shift,
|
||||
p-> msk_offset, p->msk_shift, 13);
|
||||
}
|
||||
}
|
||||
|
||||
/* Adds a termination callback to the interrupt */
|
||||
void intc2_add_clear_irq(int irq, int (*fn)(int))
|
||||
{
|
||||
if (irq < INTC2_FIRST_IRQ)
|
||||
return;
|
||||
|
||||
intc2_data[irq - INTC2_FIRST_IRQ].clear_irq = fn;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_CPU_SUBTYPE_ST40 */
|
|
@ -2,58 +2,73 @@
|
|||
* linux/arch/sh/kernel/io.c
|
||||
*
|
||||
* Copyright (C) 2000 Stuart Menefy
|
||||
* Copyright (C) 2005 Paul Mundt
|
||||
*
|
||||
* Provide real functions which expand to whatever the header file defined.
|
||||
* Also definitions of machine independent IO functions.
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <asm/machvec.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
/*
|
||||
* Copy data from IO memory space to "real" memory space.
|
||||
* This needs to be optimized.
|
||||
*/
|
||||
void memcpy_fromio(void * to, unsigned long from, unsigned long count)
|
||||
void memcpy_fromio(void *to, volatile void __iomem *from, unsigned long count)
|
||||
{
|
||||
char *p = to;
|
||||
while (count) {
|
||||
count--;
|
||||
*p = readb(from);
|
||||
*p = readb((void __iomem *)from);
|
||||
p++;
|
||||
from++;
|
||||
}
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(memcpy_fromio);
|
||||
|
||||
/*
|
||||
* Copy data from "real" memory space to IO memory space.
|
||||
* This needs to be optimized.
|
||||
*/
|
||||
void memcpy_toio(unsigned long to, const void * from, unsigned long count)
|
||||
void memcpy_toio(volatile void __iomem *to, const void *from, unsigned long count)
|
||||
{
|
||||
const char *p = from;
|
||||
while (count) {
|
||||
count--;
|
||||
writeb(*p, to);
|
||||
writeb(*p, (void __iomem *)to);
|
||||
p++;
|
||||
to++;
|
||||
}
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(memcpy_toio);
|
||||
|
||||
/*
|
||||
* "memset" on IO memory space.
|
||||
* This needs to be optimized.
|
||||
*/
|
||||
void memset_io(unsigned long dst, int c, unsigned long count)
|
||||
void memset_io(volatile void __iomem *dst, int c, unsigned long count)
|
||||
{
|
||||
while (count) {
|
||||
count--;
|
||||
writeb(c, dst);
|
||||
writeb(c, (void __iomem *)dst);
|
||||
dst++;
|
||||
}
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(memcpy_fromio);
|
||||
EXPORT_SYMBOL(memcpy_toio);
|
||||
EXPORT_SYMBOL(memset_io);
|
||||
|
||||
void __iomem *ioport_map(unsigned long port, unsigned int nr)
|
||||
{
|
||||
return sh_mv.mv_ioport_map(port, nr);
|
||||
}
|
||||
EXPORT_SYMBOL(ioport_map);
|
||||
|
||||
void ioport_unmap(void __iomem *addr)
|
||||
{
|
||||
sh_mv.mv_ioport_unmap(addr);
|
||||
}
|
||||
EXPORT_SYMBOL(ioport_unmap);
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
* linux/arch/sh/kernel/io_generic.c
|
||||
*
|
||||
* Copyright (C) 2000 Niibe Yutaka
|
||||
* Copyright (C) 2005 Paul Mundt
|
||||
*
|
||||
* Generic I/O routine. These can be used where a machine specific version
|
||||
* is not required.
|
||||
|
@ -10,21 +11,20 @@
|
|||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/machvec.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#if defined(CONFIG_CPU_SH3)
|
||||
#ifdef CONFIG_CPU_SH3
|
||||
/* SH3 has a PCMCIA bug that needs a dummy read from area 6 for a
|
||||
* workaround. */
|
||||
/* I'm not sure SH7709 has this kind of bug */
|
||||
#define SH3_PCMCIA_BUG_WORKAROUND 1
|
||||
#define DUMMY_READ_AREA6 0xba000000
|
||||
#define dummy_read() ctrl_inb(0xba000000)
|
||||
#else
|
||||
#define dummy_read()
|
||||
#endif
|
||||
|
||||
#define PORT2ADDR(x) (sh_mv.mv_isa_port2addr(x))
|
||||
|
||||
unsigned long generic_io_base;
|
||||
|
||||
static inline void delay(void)
|
||||
|
@ -32,40 +32,40 @@ static inline void delay(void)
|
|||
ctrl_inw(0xa0000000);
|
||||
}
|
||||
|
||||
unsigned char generic_inb(unsigned long port)
|
||||
u8 generic_inb(unsigned long port)
|
||||
{
|
||||
return *(volatile unsigned char*)PORT2ADDR(port);
|
||||
return ctrl_inb((unsigned long __force)ioport_map(port, 1));
|
||||
}
|
||||
|
||||
unsigned short generic_inw(unsigned long port)
|
||||
u16 generic_inw(unsigned long port)
|
||||
{
|
||||
return *(volatile unsigned short*)PORT2ADDR(port);
|
||||
return ctrl_inw((unsigned long __force)ioport_map(port, 2));
|
||||
}
|
||||
|
||||
unsigned int generic_inl(unsigned long port)
|
||||
u32 generic_inl(unsigned long port)
|
||||
{
|
||||
return *(volatile unsigned long*)PORT2ADDR(port);
|
||||
return ctrl_inl((unsigned long __force)ioport_map(port, 4));
|
||||
}
|
||||
|
||||
unsigned char generic_inb_p(unsigned long port)
|
||||
u8 generic_inb_p(unsigned long port)
|
||||
{
|
||||
unsigned long v = *(volatile unsigned char*)PORT2ADDR(port);
|
||||
unsigned long v = generic_inb(port);
|
||||
|
||||
delay();
|
||||
return v;
|
||||
}
|
||||
|
||||
unsigned short generic_inw_p(unsigned long port)
|
||||
u16 generic_inw_p(unsigned long port)
|
||||
{
|
||||
unsigned long v = *(volatile unsigned short*)PORT2ADDR(port);
|
||||
unsigned long v = generic_inw(port);
|
||||
|
||||
delay();
|
||||
return v;
|
||||
}
|
||||
|
||||
unsigned int generic_inl_p(unsigned long port)
|
||||
u32 generic_inl_p(unsigned long port)
|
||||
{
|
||||
unsigned long v = *(volatile unsigned long*)PORT2ADDR(port);
|
||||
unsigned long v = generic_inl(port);
|
||||
|
||||
delay();
|
||||
return v;
|
||||
|
@ -77,75 +77,70 @@ unsigned int generic_inl_p(unsigned long port)
|
|||
* convert the port address to real address once.
|
||||
*/
|
||||
|
||||
void generic_insb(unsigned long port, void *buffer, unsigned long count)
|
||||
void generic_insb(unsigned long port, void *dst, unsigned long count)
|
||||
{
|
||||
volatile unsigned char *port_addr;
|
||||
unsigned char *buf=buffer;
|
||||
volatile u8 *port_addr;
|
||||
u8 *buf = dst;
|
||||
|
||||
port_addr = (volatile unsigned char *)PORT2ADDR(port);
|
||||
|
||||
while(count--)
|
||||
*buf++ = *port_addr;
|
||||
port_addr = (volatile u8 *)ioport_map(port, 1);
|
||||
while (count--)
|
||||
*buf++ = *port_addr;
|
||||
}
|
||||
|
||||
void generic_insw(unsigned long port, void *buffer, unsigned long count)
|
||||
void generic_insw(unsigned long port, void *dst, unsigned long count)
|
||||
{
|
||||
volatile unsigned short *port_addr;
|
||||
unsigned short *buf=buffer;
|
||||
volatile u16 *port_addr;
|
||||
u16 *buf = dst;
|
||||
|
||||
port_addr = (volatile unsigned short *)PORT2ADDR(port);
|
||||
port_addr = (volatile u16 *)ioport_map(port, 2);
|
||||
while (count--)
|
||||
*buf++ = *port_addr;
|
||||
|
||||
while(count--)
|
||||
*buf++ = *port_addr;
|
||||
#ifdef SH3_PCMCIA_BUG_WORKAROUND
|
||||
ctrl_inb (DUMMY_READ_AREA6);
|
||||
#endif
|
||||
dummy_read();
|
||||
}
|
||||
|
||||
void generic_insl(unsigned long port, void *buffer, unsigned long count)
|
||||
void generic_insl(unsigned long port, void *dst, unsigned long count)
|
||||
{
|
||||
volatile unsigned long *port_addr;
|
||||
unsigned long *buf=buffer;
|
||||
volatile u32 *port_addr;
|
||||
u32 *buf = dst;
|
||||
|
||||
port_addr = (volatile unsigned long *)PORT2ADDR(port);
|
||||
port_addr = (volatile u32 *)ioport_map(port, 4);
|
||||
while (count--)
|
||||
*buf++ = *port_addr;
|
||||
|
||||
while(count--)
|
||||
*buf++ = *port_addr;
|
||||
#ifdef SH3_PCMCIA_BUG_WORKAROUND
|
||||
ctrl_inb (DUMMY_READ_AREA6);
|
||||
#endif
|
||||
dummy_read();
|
||||
}
|
||||
|
||||
void generic_outb(unsigned char b, unsigned long port)
|
||||
void generic_outb(u8 b, unsigned long port)
|
||||
{
|
||||
*(volatile unsigned char*)PORT2ADDR(port) = b;
|
||||
ctrl_outb(b, (unsigned long __force)ioport_map(port, 1));
|
||||
}
|
||||
|
||||
void generic_outw(unsigned short b, unsigned long port)
|
||||
void generic_outw(u16 b, unsigned long port)
|
||||
{
|
||||
*(volatile unsigned short*)PORT2ADDR(port) = b;
|
||||
ctrl_outw(b, (unsigned long __force)ioport_map(port, 2));
|
||||
}
|
||||
|
||||
void generic_outl(unsigned int b, unsigned long port)
|
||||
void generic_outl(u32 b, unsigned long port)
|
||||
{
|
||||
*(volatile unsigned long*)PORT2ADDR(port) = b;
|
||||
ctrl_outl(b, (unsigned long __force)ioport_map(port, 4));
|
||||
}
|
||||
|
||||
void generic_outb_p(unsigned char b, unsigned long port)
|
||||
void generic_outb_p(u8 b, unsigned long port)
|
||||
{
|
||||
*(volatile unsigned char*)PORT2ADDR(port) = b;
|
||||
generic_outb(b, port);
|
||||
delay();
|
||||
}
|
||||
|
||||
void generic_outw_p(unsigned short b, unsigned long port)
|
||||
void generic_outw_p(u16 b, unsigned long port)
|
||||
{
|
||||
*(volatile unsigned short*)PORT2ADDR(port) = b;
|
||||
generic_outw(b, port);
|
||||
delay();
|
||||
}
|
||||
|
||||
void generic_outl_p(unsigned int b, unsigned long port)
|
||||
void generic_outl_p(u32 b, unsigned long port)
|
||||
{
|
||||
*(volatile unsigned long*)PORT2ADDR(port) = b;
|
||||
generic_outl(b, port);
|
||||
delay();
|
||||
}
|
||||
|
||||
|
@ -154,90 +149,77 @@ void generic_outl_p(unsigned int b, unsigned long port)
|
|||
* address. However as the port address doesn't change we only need to
|
||||
* convert the port address to real address once.
|
||||
*/
|
||||
|
||||
void generic_outsb(unsigned long port, const void *buffer, unsigned long count)
|
||||
void generic_outsb(unsigned long port, const void *src, unsigned long count)
|
||||
{
|
||||
volatile unsigned char *port_addr;
|
||||
const unsigned char *buf=buffer;
|
||||
volatile u8 *port_addr;
|
||||
const u8 *buf = src;
|
||||
|
||||
port_addr = (volatile unsigned char *)PORT2ADDR(port);
|
||||
port_addr = (volatile u8 __force *)ioport_map(port, 1);
|
||||
|
||||
while(count--)
|
||||
*port_addr = *buf++;
|
||||
while (count--)
|
||||
*port_addr = *buf++;
|
||||
}
|
||||
|
||||
void generic_outsw(unsigned long port, const void *buffer, unsigned long count)
|
||||
void generic_outsw(unsigned long port, const void *src, unsigned long count)
|
||||
{
|
||||
volatile unsigned short *port_addr;
|
||||
const unsigned short *buf=buffer;
|
||||
volatile u16 *port_addr;
|
||||
const u16 *buf = src;
|
||||
|
||||
port_addr = (volatile unsigned short *)PORT2ADDR(port);
|
||||
port_addr = (volatile u16 __force *)ioport_map(port, 2);
|
||||
|
||||
while(count--)
|
||||
*port_addr = *buf++;
|
||||
while (count--)
|
||||
*port_addr = *buf++;
|
||||
|
||||
#ifdef SH3_PCMCIA_BUG_WORKAROUND
|
||||
ctrl_inb (DUMMY_READ_AREA6);
|
||||
#endif
|
||||
dummy_read();
|
||||
}
|
||||
|
||||
void generic_outsl(unsigned long port, const void *buffer, unsigned long count)
|
||||
void generic_outsl(unsigned long port, const void *src, unsigned long count)
|
||||
{
|
||||
volatile unsigned long *port_addr;
|
||||
const unsigned long *buf=buffer;
|
||||
volatile u32 *port_addr;
|
||||
const u32 *buf = src;
|
||||
|
||||
port_addr = (volatile unsigned long *)PORT2ADDR(port);
|
||||
port_addr = (volatile u32 __force *)ioport_map(port, 4);
|
||||
while (count--)
|
||||
*port_addr = *buf++;
|
||||
|
||||
while(count--)
|
||||
*port_addr = *buf++;
|
||||
|
||||
#ifdef SH3_PCMCIA_BUG_WORKAROUND
|
||||
ctrl_inb (DUMMY_READ_AREA6);
|
||||
#endif
|
||||
dummy_read();
|
||||
}
|
||||
|
||||
unsigned char generic_readb(unsigned long addr)
|
||||
u8 generic_readb(void __iomem *addr)
|
||||
{
|
||||
return *(volatile unsigned char*)addr;
|
||||
return ctrl_inb((unsigned long __force)addr);
|
||||
}
|
||||
|
||||
unsigned short generic_readw(unsigned long addr)
|
||||
u16 generic_readw(void __iomem *addr)
|
||||
{
|
||||
return *(volatile unsigned short*)addr;
|
||||
return ctrl_inw((unsigned long __force)addr);
|
||||
}
|
||||
|
||||
unsigned int generic_readl(unsigned long addr)
|
||||
u32 generic_readl(void __iomem *addr)
|
||||
{
|
||||
return *(volatile unsigned long*)addr;
|
||||
return ctrl_inl((unsigned long __force)addr);
|
||||
}
|
||||
|
||||
void generic_writeb(unsigned char b, unsigned long addr)
|
||||
void generic_writeb(u8 b, void __iomem *addr)
|
||||
{
|
||||
*(volatile unsigned char*)addr = b;
|
||||
ctrl_outb(b, (unsigned long __force)addr);
|
||||
}
|
||||
|
||||
void generic_writew(unsigned short b, unsigned long addr)
|
||||
void generic_writew(u16 b, void __iomem *addr)
|
||||
{
|
||||
*(volatile unsigned short*)addr = b;
|
||||
ctrl_outw(b, (unsigned long __force)addr);
|
||||
}
|
||||
|
||||
void generic_writel(unsigned int b, unsigned long addr)
|
||||
void generic_writel(u32 b, void __iomem *addr)
|
||||
{
|
||||
*(volatile unsigned long*)addr = b;
|
||||
ctrl_outl(b, (unsigned long __force)addr);
|
||||
}
|
||||
|
||||
void * generic_ioremap(unsigned long offset, unsigned long size)
|
||||
void __iomem *generic_ioport_map(unsigned long addr, unsigned int size)
|
||||
{
|
||||
return (void *) P2SEGADDR(offset);
|
||||
return (void __iomem *)(addr + generic_io_base);
|
||||
}
|
||||
EXPORT_SYMBOL(generic_ioremap);
|
||||
|
||||
void generic_iounmap(void *addr)
|
||||
void generic_ioport_unmap(void __iomem *addr)
|
||||
{
|
||||
}
|
||||
EXPORT_SYMBOL(generic_iounmap);
|
||||
|
||||
unsigned long generic_isa_port2addr(unsigned long offset)
|
||||
{
|
||||
return offset + generic_io_base;
|
||||
}
|
||||
|
|
|
@ -8,38 +8,13 @@
|
|||
* SuperH version: Copyright (C) 1999 Niibe Yutaka
|
||||
*/
|
||||
|
||||
/*
|
||||
* IRQs are in fact implemented a bit like signal handlers for the kernel.
|
||||
* Naturally it's not a 1:1 relation, but there are similarities.
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/kernel_stat.h>
|
||||
#include <linux/signal.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/timex.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/kallsyms.h>
|
||||
#include <linux/bitops.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/pgalloc.h>
|
||||
#include <asm/delay.h>
|
||||
#include <asm/irq.h>
|
||||
#include <linux/irq.h>
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/kernel_stat.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/cpu/mmu_context.h>
|
||||
|
||||
/*
|
||||
* 'what should we do if we get a hw irq event on an illegal vector'.
|
||||
|
@ -66,7 +41,7 @@ int show_interrupts(struct seq_file *p, void *v)
|
|||
seq_putc(p, '\n');
|
||||
}
|
||||
|
||||
if (i < ACTUAL_NR_IRQS) {
|
||||
if (i < NR_IRQS) {
|
||||
spin_lock_irqsave(&irq_desc[i].lock, flags);
|
||||
action = irq_desc[i].action;
|
||||
if (!action)
|
||||
|
@ -86,19 +61,32 @@ int show_interrupts(struct seq_file *p, void *v)
|
|||
}
|
||||
#endif
|
||||
|
||||
|
||||
asmlinkage int do_IRQ(unsigned long r4, unsigned long r5,
|
||||
unsigned long r6, unsigned long r7,
|
||||
struct pt_regs regs)
|
||||
{
|
||||
int irq;
|
||||
{
|
||||
int irq = r4;
|
||||
|
||||
irq_enter();
|
||||
asm volatile("stc r2_bank, %0\n\t"
|
||||
"shlr2 %0\n\t"
|
||||
"shlr2 %0\n\t"
|
||||
"shlr %0\n\t"
|
||||
"add #-16, %0\n\t"
|
||||
:"=z" (irq));
|
||||
|
||||
#ifdef CONFIG_CPU_HAS_INTEVT
|
||||
__asm__ __volatile__ (
|
||||
#ifdef CONFIG_CPU_HAS_SR_RB
|
||||
"stc r2_bank, %0\n\t"
|
||||
#else
|
||||
"mov.l @%1, %0\n\t"
|
||||
#endif
|
||||
"shlr2 %0\n\t"
|
||||
"shlr2 %0\n\t"
|
||||
"shlr %0\n\t"
|
||||
"add #-16, %0\n\t"
|
||||
: "=z" (irq), "=r" (r4)
|
||||
: "1" (INTEVT)
|
||||
: "memory"
|
||||
);
|
||||
#endif
|
||||
|
||||
irq = irq_demux(irq);
|
||||
__do_IRQ(irq, ®s);
|
||||
irq_exit();
|
||||
|
|
112
arch/sh/kernel/machine_kexec.c
Normal file
112
arch/sh/kernel/machine_kexec.c
Normal file
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* machine_kexec.c - handle transition of Linux booting another kernel
|
||||
* Copyright (C) 2002-2003 Eric Biederman <ebiederm@xmission.com>
|
||||
*
|
||||
* GameCube/ppc32 port Copyright (C) 2004 Albert Herranz
|
||||
* LANDISK/sh4 supported by kogiidena
|
||||
*
|
||||
* This source code is licensed under the GNU General Public License,
|
||||
* Version 2. See the file COPYING for more details.
|
||||
*/
|
||||
|
||||
#include <linux/mm.h>
|
||||
#include <linux/kexec.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/pgalloc.h>
|
||||
#include <asm/mmu_context.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/cacheflush.h>
|
||||
|
||||
typedef NORET_TYPE void (*relocate_new_kernel_t)(
|
||||
unsigned long indirection_page,
|
||||
unsigned long reboot_code_buffer,
|
||||
unsigned long start_address,
|
||||
unsigned long vbr_reg) ATTRIB_NORET;
|
||||
|
||||
const extern unsigned char relocate_new_kernel[];
|
||||
const extern unsigned int relocate_new_kernel_size;
|
||||
extern void *gdb_vbr_vector;
|
||||
|
||||
/*
|
||||
* Provide a dummy crash_notes definition while crash dump arrives to ppc.
|
||||
* This prevents breakage of crash_notes attribute in kernel/ksysfs.c.
|
||||
*/
|
||||
void *crash_notes = NULL;
|
||||
|
||||
void machine_shutdown(void)
|
||||
{
|
||||
}
|
||||
|
||||
void machine_crash_shutdown(struct pt_regs *regs)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Do what every setup is needed on image and the
|
||||
* reboot code buffer to allow us to avoid allocations
|
||||
* later.
|
||||
*/
|
||||
int machine_kexec_prepare(struct kimage *image)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void machine_kexec_cleanup(struct kimage *image)
|
||||
{
|
||||
}
|
||||
|
||||
static void kexec_info(struct kimage *image)
|
||||
{
|
||||
int i;
|
||||
printk("kexec information\n");
|
||||
for (i = 0; i < image->nr_segments; i++) {
|
||||
printk(" segment[%d]: 0x%08x - 0x%08x (0x%08x)\n",
|
||||
i,
|
||||
(unsigned int)image->segment[i].mem,
|
||||
(unsigned int)image->segment[i].mem + image->segment[i].memsz,
|
||||
(unsigned int)image->segment[i].memsz);
|
||||
}
|
||||
printk(" start : 0x%08x\n\n", (unsigned int)image->start);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Do not allocate memory (or fail in any way) in machine_kexec().
|
||||
* We are past the point of no return, committed to rebooting now.
|
||||
*/
|
||||
NORET_TYPE void machine_kexec(struct kimage *image)
|
||||
{
|
||||
|
||||
unsigned long page_list;
|
||||
unsigned long reboot_code_buffer;
|
||||
unsigned long vbr_reg;
|
||||
relocate_new_kernel_t rnk;
|
||||
|
||||
#if defined(CONFIG_SH_STANDARD_BIOS)
|
||||
vbr_reg = ((unsigned long )gdb_vbr_vector) - 0x100;
|
||||
#else
|
||||
vbr_reg = 0x80000000; // dummy
|
||||
#endif
|
||||
/* Interrupts aren't acceptable while we reboot */
|
||||
local_irq_disable();
|
||||
|
||||
page_list = image->head;
|
||||
|
||||
/* we need both effective and real address here */
|
||||
reboot_code_buffer =
|
||||
(unsigned long)page_address(image->control_code_page);
|
||||
|
||||
/* copy our kernel relocation code to the control code page */
|
||||
memcpy((void *)reboot_code_buffer, relocate_new_kernel,
|
||||
relocate_new_kernel_size);
|
||||
|
||||
kexec_info(image);
|
||||
flush_cache_all();
|
||||
|
||||
/* now call it */
|
||||
rnk = (relocate_new_kernel_t) reboot_code_buffer;
|
||||
(*rnk)(page_list, reboot_code_buffer, image->start, vbr_reg);
|
||||
}
|
||||
|
|
@ -71,6 +71,16 @@ void cpu_idle(void)
|
|||
|
||||
void machine_restart(char * __unused)
|
||||
{
|
||||
|
||||
#ifdef CONFIG_KEXEC
|
||||
struct kimage *image;
|
||||
image = xchg(&kexec_image, 0);
|
||||
if (image) {
|
||||
machine_shutdown();
|
||||
machine_kexec(image);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* SR.BL=1 and invoke address error to let CPU reset (manual reset) */
|
||||
asm volatile("ldc %0, sr\n\t"
|
||||
"mov.l @%1, %0" : : "r" (0x10000000), "r" (0x80000001));
|
||||
|
|
102
arch/sh/kernel/relocate_kernel.S
Normal file
102
arch/sh/kernel/relocate_kernel.S
Normal file
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* relocate_kernel.S - put the kernel image in place to boot
|
||||
* 2005.9.17 kogiidena@eggplant.ddo.jp
|
||||
*
|
||||
* LANDISK/sh4 is supported. Maybe, SH archtecture works well.
|
||||
*
|
||||
* This source code is licensed under the GNU General Public License,
|
||||
* Version 2. See the file COPYING for more details.
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/linkage.h>
|
||||
|
||||
#define PAGE_SIZE 4096 /* must be same value as in <asm/page.h> */
|
||||
|
||||
|
||||
.globl relocate_new_kernel
|
||||
relocate_new_kernel:
|
||||
/* r4 = indirection_page */
|
||||
/* r5 = reboot_code_buffer */
|
||||
/* r6 = start_address */
|
||||
/* r7 = vbr_reg */
|
||||
|
||||
mov.l 10f,r8 /* 4096 */
|
||||
mov.l 11f,r9 /* 0xa0000000 */
|
||||
|
||||
/* stack setting */
|
||||
add r8,r5
|
||||
mov r5,r15
|
||||
|
||||
bra 1f
|
||||
mov r4,r0 /* cmd = indirection_page */
|
||||
0:
|
||||
mov.l @r4+,r0 /* cmd = *ind++ */
|
||||
|
||||
1: /* addr = (cmd | 0xa0000000) & 0xfffffff0 */
|
||||
mov r0,r2
|
||||
or r9,r2
|
||||
mov #-16,r1
|
||||
and r1,r2
|
||||
|
||||
/* if(cmd & IND_DESTINATION) dst = addr */
|
||||
tst #1,r0
|
||||
bt 2f
|
||||
bra 0b
|
||||
mov r2,r5
|
||||
|
||||
2: /* else if(cmd & IND_INDIRECTION) ind = addr */
|
||||
tst #2,r0
|
||||
bt 3f
|
||||
bra 0b
|
||||
mov r2,r4
|
||||
|
||||
3: /* else if(cmd & IND_DONE) goto 6 */
|
||||
tst #4,r0
|
||||
bt 4f
|
||||
bra 6f
|
||||
nop
|
||||
|
||||
4: /* else if(cmd & IND_SOURCE) memcpy(dst,addr,PAGE_SIZE) */
|
||||
tst #8,r0
|
||||
bt 0b
|
||||
|
||||
mov r8,r3
|
||||
shlr2 r3
|
||||
shlr2 r3
|
||||
5:
|
||||
dt r3
|
||||
mov.l @r2+,r1 /* 16n+0 */
|
||||
mov.l r1,@r5
|
||||
add #4,r5
|
||||
mov.l @r2+,r1 /* 16n+4 */
|
||||
mov.l r1,@r5
|
||||
add #4,r5
|
||||
mov.l @r2+,r1 /* 16n+8 */
|
||||
mov.l r1,@r5
|
||||
add #4,r5
|
||||
mov.l @r2+,r1 /* 16n+12 */
|
||||
mov.l r1,@r5
|
||||
add #4,r5
|
||||
bf 5b
|
||||
|
||||
bra 0b
|
||||
nop
|
||||
6:
|
||||
#ifdef CONFIG_SH_STANDARD_BIOS
|
||||
ldc r7, vbr
|
||||
#endif
|
||||
jmp @r6
|
||||
nop
|
||||
|
||||
.align 2
|
||||
10:
|
||||
.long PAGE_SIZE
|
||||
11:
|
||||
.long 0xa0000000
|
||||
|
||||
relocate_new_kernel_end:
|
||||
|
||||
.globl relocate_new_kernel_size
|
||||
relocate_new_kernel_size:
|
||||
.long relocate_new_kernel_end - relocate_new_kernel
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka
|
||||
* Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
|
||||
* Copyright (C) 2002, 2003, 2004 Paul Mundt
|
||||
* Copyright (C) 2002, 2003, 2004, 2005 Paul Mundt
|
||||
* Copyright (C) 2002 M. R. Brown <mrbrown@linux-sh.org>
|
||||
*
|
||||
* Some code taken from i386 version.
|
||||
|
@ -11,50 +11,21 @@
|
|||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/param.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/profile.h>
|
||||
|
||||
#include <asm/processor.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/delay.h>
|
||||
#include <asm/machvec.h>
|
||||
#include <asm/clock.h>
|
||||
#include <asm/rtc.h>
|
||||
#include <asm/freq.h>
|
||||
#include <asm/cpu/timer.h>
|
||||
#ifdef CONFIG_SH_KGDB
|
||||
#include <asm/timer.h>
|
||||
#include <asm/kgdb.h>
|
||||
#endif
|
||||
|
||||
#include <linux/timex.h>
|
||||
#include <linux/irq.h>
|
||||
|
||||
#define TMU_TOCR_INIT 0x00
|
||||
#define TMU0_TCR_INIT 0x0020
|
||||
#define TMU_TSTR_INIT 1
|
||||
|
||||
#define TMU0_TCR_CALIB 0x0000
|
||||
|
||||
#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
|
||||
#define CLOCKGEN_MEMCLKCR 0xbb040038
|
||||
#define MEMCLKCR_RATIO_MASK 0x7
|
||||
#endif /* CONFIG_CPU_SUBTYPE_ST40STB1 */
|
||||
|
||||
extern unsigned long wall_jiffies;
|
||||
#define TICK_SIZE (tick_nsec / 1000)
|
||||
DEFINE_SPINLOCK(tmu0_lock);
|
||||
struct sys_timer *sys_timer;
|
||||
|
||||
/* Move this somewhere more sensible.. */
|
||||
DEFINE_SPINLOCK(rtc_lock);
|
||||
EXPORT_SYMBOL(rtc_lock);
|
||||
|
||||
/* XXX: Can we initialize this in a routine somewhere? Dreamcast doesn't want
|
||||
* these routines anywhere... */
|
||||
|
@ -66,98 +37,14 @@ void (*rtc_get_time)(struct timespec *);
|
|||
int (*rtc_set_time)(const time_t);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_CPU_SUBTYPE_SH7300)
|
||||
static int md_table[] = { 1, 2, 3, 4, 6, 8, 12 };
|
||||
#endif
|
||||
#if defined(CONFIG_CPU_SH3)
|
||||
static int stc_multipliers[] = { 1, 2, 3, 4, 6, 1, 1, 1 };
|
||||
static int stc_values[] = { 0, 1, 4, 2, 5, 0, 0, 0 };
|
||||
#define bfc_divisors stc_multipliers
|
||||
#define bfc_values stc_values
|
||||
static int ifc_divisors[] = { 1, 2, 3, 4, 1, 1, 1, 1 };
|
||||
static int ifc_values[] = { 0, 1, 4, 2, 0, 0, 0, 0 };
|
||||
static int pfc_divisors[] = { 1, 2, 3, 4, 6, 1, 1, 1 };
|
||||
static int pfc_values[] = { 0, 1, 4, 2, 5, 0, 0, 0 };
|
||||
#elif defined(CONFIG_CPU_SH4)
|
||||
#if defined(CONFIG_CPU_SUBTYPE_SH73180)
|
||||
static int ifc_divisors[] = { 1, 2, 3, 4, 6, 8, 12, 16 };
|
||||
static int ifc_values[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
|
||||
#define bfc_divisors ifc_divisors /* Same */
|
||||
#define bfc_values ifc_values
|
||||
#define pfc_divisors ifc_divisors /* Same */
|
||||
#define pfc_values ifc_values
|
||||
#else
|
||||
static int ifc_divisors[] = { 1, 2, 3, 4, 6, 8, 1, 1 };
|
||||
static int ifc_values[] = { 0, 1, 2, 3, 0, 4, 0, 5 };
|
||||
#define bfc_divisors ifc_divisors /* Same */
|
||||
#define bfc_values ifc_values
|
||||
static int pfc_divisors[] = { 2, 3, 4, 6, 8, 2, 2, 2 };
|
||||
static int pfc_values[] = { 0, 0, 1, 2, 0, 3, 0, 4 };
|
||||
#endif
|
||||
#else
|
||||
#error "Unknown ifc/bfc/pfc/stc values for this processor"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Scheduler clock - returns current time in nanosec units.
|
||||
*/
|
||||
unsigned long long sched_clock(void)
|
||||
unsigned long long __attribute__ ((weak)) sched_clock(void)
|
||||
{
|
||||
return (unsigned long long)jiffies * (1000000000 / HZ);
|
||||
}
|
||||
|
||||
static unsigned long do_gettimeoffset(void)
|
||||
{
|
||||
int count;
|
||||
unsigned long flags;
|
||||
|
||||
static int count_p = 0x7fffffff; /* for the first call after boot */
|
||||
static unsigned long jiffies_p = 0;
|
||||
|
||||
/*
|
||||
* cache volatile jiffies temporarily; we have IRQs turned off.
|
||||
*/
|
||||
unsigned long jiffies_t;
|
||||
|
||||
spin_lock_irqsave(&tmu0_lock, flags);
|
||||
/* timer count may underflow right here */
|
||||
count = ctrl_inl(TMU0_TCNT); /* read the latched count */
|
||||
|
||||
jiffies_t = jiffies;
|
||||
|
||||
/*
|
||||
* avoiding timer inconsistencies (they are rare, but they happen)...
|
||||
* there is one kind of problem that must be avoided here:
|
||||
* 1. the timer counter underflows
|
||||
*/
|
||||
|
||||
if( jiffies_t == jiffies_p ) {
|
||||
if( count > count_p ) {
|
||||
/* the nutcase */
|
||||
|
||||
if(ctrl_inw(TMU0_TCR) & 0x100) { /* Check UNF bit */
|
||||
/*
|
||||
* We cannot detect lost timer interrupts ...
|
||||
* well, that's why we call them lost, don't we? :)
|
||||
* [hmm, on the Pentium and Alpha we can ... sort of]
|
||||
*/
|
||||
count -= LATCH;
|
||||
} else {
|
||||
printk("do_slow_gettimeoffset(): hardware timer problem?\n");
|
||||
}
|
||||
}
|
||||
} else
|
||||
jiffies_p = jiffies_t;
|
||||
|
||||
count_p = count;
|
||||
spin_unlock_irqrestore(&tmu0_lock, flags);
|
||||
|
||||
count = ((LATCH-1) - count) * TICK_SIZE;
|
||||
count = (count + LATCH/2) / LATCH;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void do_gettimeofday(struct timeval *tv)
|
||||
{
|
||||
unsigned long seq;
|
||||
|
@ -166,7 +53,7 @@ void do_gettimeofday(struct timeval *tv)
|
|||
|
||||
do {
|
||||
seq = read_seqbegin(&xtime_lock);
|
||||
usec = do_gettimeoffset();
|
||||
usec = get_timer_offset();
|
||||
|
||||
lost = jiffies - wall_jiffies;
|
||||
if (lost)
|
||||
|
@ -202,7 +89,7 @@ int do_settimeofday(struct timespec *tv)
|
|||
* wall time. Discover what correction gettimeofday() would have
|
||||
* made, and then undo it!
|
||||
*/
|
||||
nsec -= 1000 * (do_gettimeoffset() +
|
||||
nsec -= 1000 * (get_timer_offset() +
|
||||
(jiffies - wall_jiffies) * (1000000 / HZ));
|
||||
|
||||
wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
|
||||
|
@ -224,10 +111,10 @@ EXPORT_SYMBOL(do_settimeofday);
|
|||
static long last_rtc_update;
|
||||
|
||||
/*
|
||||
* timer_interrupt() needs to keep up the real-time clock,
|
||||
* handle_timer_tick() needs to keep up the real-time clock,
|
||||
* as well as call the "do_timer()" routine every clocktick
|
||||
*/
|
||||
static inline void do_timer_interrupt(int irq, struct pt_regs *regs)
|
||||
void handle_timer_tick(struct pt_regs *regs)
|
||||
{
|
||||
do_timer(regs);
|
||||
#ifndef CONFIG_SMP
|
||||
|
@ -252,337 +139,35 @@ static inline void do_timer_interrupt(int irq, struct pt_regs *regs)
|
|||
if (rtc_set_time(xtime.tv_sec) == 0)
|
||||
last_rtc_update = xtime.tv_sec;
|
||||
else
|
||||
last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
|
||||
/* do it again in 60s */
|
||||
last_rtc_update = xtime.tv_sec - 600;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the same as the above, except we _also_ save the current
|
||||
* Time Stamp Counter value at the time of the timer interrupt, so that
|
||||
* we later on can estimate the time of day more exactly.
|
||||
*/
|
||||
static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
||||
static struct sysdev_class timer_sysclass = {
|
||||
set_kset_name("timer"),
|
||||
};
|
||||
|
||||
static int __init timer_init_sysfs(void)
|
||||
{
|
||||
unsigned long timer_status;
|
||||
int ret = sysdev_class_register(&timer_sysclass);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
/* Clear UNF bit */
|
||||
timer_status = ctrl_inw(TMU0_TCR);
|
||||
timer_status &= ~0x100;
|
||||
ctrl_outw(timer_status, TMU0_TCR);
|
||||
|
||||
/*
|
||||
* Here we are in the timer irq handler. We just have irqs locally
|
||||
* disabled but we don't know if the timer_bh is running on the other
|
||||
* CPU. We need to avoid to SMP race with it. NOTE: we don' t need
|
||||
* the irq version of write_lock because as just said we have irq
|
||||
* locally disabled. -arca
|
||||
*/
|
||||
write_seqlock(&xtime_lock);
|
||||
do_timer_interrupt(irq, regs);
|
||||
write_sequnlock(&xtime_lock);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
sys_timer->dev.cls = &timer_sysclass;
|
||||
return sysdev_register(&sys_timer->dev);
|
||||
}
|
||||
|
||||
/*
|
||||
* Hah! We'll see if this works (switching from usecs to nsecs).
|
||||
*/
|
||||
static unsigned int __init get_timer_frequency(void)
|
||||
{
|
||||
u32 freq;
|
||||
struct timespec ts1, ts2;
|
||||
unsigned long diff_nsec;
|
||||
unsigned long factor;
|
||||
|
||||
/* Setup the timer: We don't want to generate interrupts, just
|
||||
* have it count down at its natural rate.
|
||||
*/
|
||||
ctrl_outb(0, TMU_TSTR);
|
||||
#if !defined(CONFIG_CPU_SUBTYPE_SH7300)
|
||||
ctrl_outb(TMU_TOCR_INIT, TMU_TOCR);
|
||||
#endif
|
||||
ctrl_outw(TMU0_TCR_CALIB, TMU0_TCR);
|
||||
ctrl_outl(0xffffffff, TMU0_TCOR);
|
||||
ctrl_outl(0xffffffff, TMU0_TCNT);
|
||||
|
||||
rtc_get_time(&ts2);
|
||||
|
||||
do {
|
||||
rtc_get_time(&ts1);
|
||||
} while (ts1.tv_nsec == ts2.tv_nsec && ts1.tv_sec == ts2.tv_sec);
|
||||
|
||||
/* actually start the timer */
|
||||
ctrl_outb(TMU_TSTR_INIT, TMU_TSTR);
|
||||
|
||||
do {
|
||||
rtc_get_time(&ts2);
|
||||
} while (ts1.tv_nsec == ts2.tv_nsec && ts1.tv_sec == ts2.tv_sec);
|
||||
|
||||
freq = 0xffffffff - ctrl_inl(TMU0_TCNT);
|
||||
if (ts2.tv_nsec < ts1.tv_nsec) {
|
||||
ts2.tv_nsec += 1000000000;
|
||||
ts2.tv_sec--;
|
||||
}
|
||||
|
||||
diff_nsec = (ts2.tv_sec - ts1.tv_sec) * 1000000000 + (ts2.tv_nsec - ts1.tv_nsec);
|
||||
|
||||
/* this should work well if the RTC has a precision of n Hz, where
|
||||
* n is an integer. I don't think we have to worry about the other
|
||||
* cases. */
|
||||
factor = (1000000000 + diff_nsec/2) / diff_nsec;
|
||||
|
||||
if (factor * diff_nsec > 1100000000 ||
|
||||
factor * diff_nsec < 900000000)
|
||||
panic("weird RTC (diff_nsec %ld)", diff_nsec);
|
||||
|
||||
return freq * factor;
|
||||
}
|
||||
device_initcall(timer_init_sysfs);
|
||||
|
||||
void (*board_time_init)(void);
|
||||
void (*board_timer_setup)(struct irqaction *irq);
|
||||
|
||||
static unsigned int sh_pclk_freq __initdata = CONFIG_SH_PCLK_FREQ;
|
||||
|
||||
static int __init sh_pclk_setup(char *str)
|
||||
{
|
||||
unsigned int freq;
|
||||
|
||||
if (get_option(&str, &freq))
|
||||
sh_pclk_freq = freq;
|
||||
|
||||
return 1;
|
||||
}
|
||||
__setup("sh_pclk=", sh_pclk_setup);
|
||||
|
||||
static struct irqaction irq0 = { timer_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "timer", NULL, NULL};
|
||||
|
||||
void get_current_frequency_divisors(unsigned int *ifc, unsigned int *bfc, unsigned int *pfc)
|
||||
{
|
||||
unsigned int frqcr = ctrl_inw(FRQCR);
|
||||
|
||||
#if defined(CONFIG_CPU_SH3)
|
||||
#if defined(CONFIG_CPU_SUBTYPE_SH7300)
|
||||
*ifc = md_table[((frqcr & 0x0070) >> 4)];
|
||||
*bfc = md_table[((frqcr & 0x0700) >> 8)];
|
||||
*pfc = md_table[frqcr & 0x0007];
|
||||
#elif defined(CONFIG_CPU_SUBTYPE_SH7705)
|
||||
*bfc = stc_multipliers[(frqcr & 0x0300) >> 8];
|
||||
*ifc = ifc_divisors[(frqcr & 0x0030) >> 4];
|
||||
*pfc = pfc_divisors[frqcr & 0x0003];
|
||||
#else
|
||||
unsigned int tmp;
|
||||
|
||||
tmp = (frqcr & 0x8000) >> 13;
|
||||
tmp |= (frqcr & 0x0030) >> 4;
|
||||
*bfc = stc_multipliers[tmp];
|
||||
tmp = (frqcr & 0x4000) >> 12;
|
||||
tmp |= (frqcr & 0x000c) >> 2;
|
||||
*ifc = ifc_divisors[tmp];
|
||||
tmp = (frqcr & 0x2000) >> 11;
|
||||
tmp |= frqcr & 0x0003;
|
||||
*pfc = pfc_divisors[tmp];
|
||||
#endif
|
||||
#elif defined(CONFIG_CPU_SH4)
|
||||
#if defined(CONFIG_CPU_SUBTYPE_SH73180)
|
||||
*ifc = ifc_divisors[(frqcr>> 20) & 0x0007];
|
||||
*bfc = bfc_divisors[(frqcr>> 12) & 0x0007];
|
||||
*pfc = pfc_divisors[frqcr & 0x0007];
|
||||
#else
|
||||
*ifc = ifc_divisors[(frqcr >> 6) & 0x0007];
|
||||
*bfc = bfc_divisors[(frqcr >> 3) & 0x0007];
|
||||
*pfc = pfc_divisors[frqcr & 0x0007];
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* This bit of ugliness builds up accessor routines to get at both
|
||||
* the divisors and the physical values.
|
||||
*/
|
||||
#define _FREQ_TABLE(x) \
|
||||
unsigned int get_##x##_divisor(unsigned int value) \
|
||||
{ return x##_divisors[value]; } \
|
||||
\
|
||||
unsigned int get_##x##_value(unsigned int divisor) \
|
||||
{ return x##_values[(divisor - 1)]; }
|
||||
|
||||
_FREQ_TABLE(ifc);
|
||||
_FREQ_TABLE(bfc);
|
||||
_FREQ_TABLE(pfc);
|
||||
|
||||
#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
|
||||
|
||||
/*
|
||||
* The ST40 divisors are totally different so we set the cpu data
|
||||
* clocks using a different algorithm
|
||||
*
|
||||
* I've just plugged this from the 2.4 code
|
||||
* - Alex Bennee <kernel-hacker@bennee.com>
|
||||
*/
|
||||
#define CCN_PVR_CHIP_SHIFT 24
|
||||
#define CCN_PVR_CHIP_MASK 0xff
|
||||
#define CCN_PVR_CHIP_ST40STB1 0x4
|
||||
|
||||
|
||||
struct frqcr_data {
|
||||
unsigned short frqcr;
|
||||
|
||||
struct {
|
||||
unsigned char multiplier;
|
||||
unsigned char divisor;
|
||||
} factor[3];
|
||||
};
|
||||
|
||||
static struct frqcr_data st40_frqcr_table[] = {
|
||||
{ 0x000, {{1,1}, {1,1}, {1,2}}},
|
||||
{ 0x002, {{1,1}, {1,1}, {1,4}}},
|
||||
{ 0x004, {{1,1}, {1,1}, {1,8}}},
|
||||
{ 0x008, {{1,1}, {1,2}, {1,2}}},
|
||||
{ 0x00A, {{1,1}, {1,2}, {1,4}}},
|
||||
{ 0x00C, {{1,1}, {1,2}, {1,8}}},
|
||||
{ 0x011, {{1,1}, {2,3}, {1,6}}},
|
||||
{ 0x013, {{1,1}, {2,3}, {1,3}}},
|
||||
{ 0x01A, {{1,1}, {1,2}, {1,4}}},
|
||||
{ 0x01C, {{1,1}, {1,2}, {1,8}}},
|
||||
{ 0x023, {{1,1}, {2,3}, {1,3}}},
|
||||
{ 0x02C, {{1,1}, {1,2}, {1,8}}},
|
||||
{ 0x048, {{1,2}, {1,2}, {1,4}}},
|
||||
{ 0x04A, {{1,2}, {1,2}, {1,6}}},
|
||||
{ 0x04C, {{1,2}, {1,2}, {1,8}}},
|
||||
{ 0x05A, {{1,2}, {1,3}, {1,6}}},
|
||||
{ 0x05C, {{1,2}, {1,3}, {1,6}}},
|
||||
{ 0x063, {{1,2}, {1,4}, {1,4}}},
|
||||
{ 0x06C, {{1,2}, {1,4}, {1,8}}},
|
||||
{ 0x091, {{1,3}, {1,3}, {1,6}}},
|
||||
{ 0x093, {{1,3}, {1,3}, {1,6}}},
|
||||
{ 0x0A3, {{1,3}, {1,6}, {1,6}}},
|
||||
{ 0x0DA, {{1,4}, {1,4}, {1,8}}},
|
||||
{ 0x0DC, {{1,4}, {1,4}, {1,8}}},
|
||||
{ 0x0EC, {{1,4}, {1,8}, {1,8}}},
|
||||
{ 0x123, {{1,4}, {1,4}, {1,8}}},
|
||||
{ 0x16C, {{1,4}, {1,8}, {1,8}}},
|
||||
};
|
||||
|
||||
struct memclk_data {
|
||||
unsigned char multiplier;
|
||||
unsigned char divisor;
|
||||
};
|
||||
|
||||
static struct memclk_data st40_memclk_table[8] = {
|
||||
{1,1}, // 000
|
||||
{1,2}, // 001
|
||||
{1,3}, // 010
|
||||
{2,3}, // 011
|
||||
{1,4}, // 100
|
||||
{1,6}, // 101
|
||||
{1,8}, // 110
|
||||
{1,8} // 111
|
||||
};
|
||||
|
||||
static void st40_specific_time_init(unsigned int module_clock, unsigned short frqcr)
|
||||
{
|
||||
unsigned int cpu_clock, master_clock, bus_clock, memory_clock;
|
||||
struct frqcr_data *d;
|
||||
int a;
|
||||
unsigned long memclkcr;
|
||||
struct memclk_data *e;
|
||||
|
||||
for (a = 0; a < ARRAY_SIZE(st40_frqcr_table); a++) {
|
||||
d = &st40_frqcr_table[a];
|
||||
|
||||
if (d->frqcr == (frqcr & 0x1ff))
|
||||
break;
|
||||
}
|
||||
|
||||
if (a == ARRAY_SIZE(st40_frqcr_table)) {
|
||||
d = st40_frqcr_table;
|
||||
|
||||
printk("ERROR: Unrecognised FRQCR value (0x%x), "
|
||||
"using default multipliers\n", frqcr);
|
||||
}
|
||||
|
||||
memclkcr = ctrl_inl(CLOCKGEN_MEMCLKCR);
|
||||
e = &st40_memclk_table[memclkcr & MEMCLKCR_RATIO_MASK];
|
||||
|
||||
printk(KERN_INFO "Clock multipliers: CPU: %d/%d Bus: %d/%d "
|
||||
"Mem: %d/%d Periph: %d/%d\n",
|
||||
d->factor[0].multiplier, d->factor[0].divisor,
|
||||
d->factor[1].multiplier, d->factor[1].divisor,
|
||||
e->multiplier, e->divisor,
|
||||
d->factor[2].multiplier, d->factor[2].divisor);
|
||||
|
||||
master_clock = module_clock * d->factor[2].divisor
|
||||
/ d->factor[2].multiplier;
|
||||
bus_clock = master_clock * d->factor[1].multiplier
|
||||
/ d->factor[1].divisor;
|
||||
memory_clock = master_clock * e->multiplier
|
||||
/ e->divisor;
|
||||
cpu_clock = master_clock * d->factor[0].multiplier
|
||||
/ d->factor[0].divisor;
|
||||
|
||||
current_cpu_data.cpu_clock = cpu_clock;
|
||||
current_cpu_data.master_clock = master_clock;
|
||||
current_cpu_data.bus_clock = bus_clock;
|
||||
current_cpu_data.memory_clock = memory_clock;
|
||||
current_cpu_data.module_clock = module_clock;
|
||||
}
|
||||
#endif
|
||||
|
||||
void __init time_init(void)
|
||||
{
|
||||
unsigned int timer_freq = 0;
|
||||
unsigned int ifc, pfc, bfc;
|
||||
unsigned long interval;
|
||||
#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
|
||||
unsigned long pvr;
|
||||
unsigned short frqcr;
|
||||
#endif
|
||||
|
||||
if (board_time_init)
|
||||
board_time_init();
|
||||
|
||||
/*
|
||||
* If we don't have an RTC (such as with the SH7300), don't attempt to
|
||||
* probe the timer frequency. Rely on an either hardcoded peripheral
|
||||
* clock value, or on the sh_pclk command line option. Note that we
|
||||
* still need to have CONFIG_SH_PCLK_FREQ set in order for things like
|
||||
* CLOCK_TICK_RATE to be sane.
|
||||
*/
|
||||
current_cpu_data.module_clock = sh_pclk_freq;
|
||||
|
||||
#ifdef CONFIG_SH_PCLK_CALC
|
||||
/* XXX: Switch this over to a more generic test. */
|
||||
{
|
||||
unsigned int freq;
|
||||
|
||||
/*
|
||||
* If we've specified a peripheral clock frequency, and we have
|
||||
* an RTC, compare it against the autodetected value. Complain
|
||||
* if there's a mismatch.
|
||||
*/
|
||||
timer_freq = get_timer_frequency();
|
||||
freq = timer_freq * 4;
|
||||
|
||||
if (sh_pclk_freq && (sh_pclk_freq/100*99 > freq || sh_pclk_freq/100*101 < freq)) {
|
||||
printk(KERN_NOTICE "Calculated peripheral clock value "
|
||||
"%d differs from sh_pclk value %d, fixing..\n",
|
||||
freq, sh_pclk_freq);
|
||||
current_cpu_data.module_clock = freq;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
|
||||
/* XXX: Update ST40 code to use board_time_init() */
|
||||
pvr = ctrl_inl(CCN_PVR);
|
||||
frqcr = ctrl_inw(FRQCR);
|
||||
printk("time.c ST40 Probe: PVR %08lx, FRQCR %04hx\n", pvr, frqcr);
|
||||
|
||||
if (((pvr >> CCN_PVR_CHIP_SHIFT) & CCN_PVR_CHIP_MASK) == CCN_PVR_CHIP_ST40STB1)
|
||||
st40_specific_time_init(current_cpu_data.module_clock, frqcr);
|
||||
else
|
||||
#endif
|
||||
get_current_frequency_divisors(&ifc, &bfc, &pfc);
|
||||
clk_init();
|
||||
|
||||
if (rtc_get_time) {
|
||||
rtc_get_time(&xtime);
|
||||
|
@ -594,51 +179,12 @@ void __init time_init(void)
|
|||
set_normalized_timespec(&wall_to_monotonic,
|
||||
-xtime.tv_sec, -xtime.tv_nsec);
|
||||
|
||||
if (board_timer_setup) {
|
||||
board_timer_setup(&irq0);
|
||||
} else {
|
||||
setup_irq(TIMER_IRQ, &irq0);
|
||||
}
|
||||
|
||||
/*
|
||||
* for ST40 chips the current_cpu_data should already be set
|
||||
* so not having valid pfc/bfc/ifc shouldn't be a problem
|
||||
* Find the timer to use as the system timer, it will be
|
||||
* initialized for us.
|
||||
*/
|
||||
if (!current_cpu_data.master_clock)
|
||||
current_cpu_data.master_clock = current_cpu_data.module_clock * pfc;
|
||||
if (!current_cpu_data.bus_clock)
|
||||
current_cpu_data.bus_clock = current_cpu_data.master_clock / bfc;
|
||||
if (!current_cpu_data.cpu_clock)
|
||||
current_cpu_data.cpu_clock = current_cpu_data.master_clock / ifc;
|
||||
|
||||
printk("CPU clock: %d.%02dMHz\n",
|
||||
(current_cpu_data.cpu_clock / 1000000),
|
||||
(current_cpu_data.cpu_clock % 1000000)/10000);
|
||||
printk("Bus clock: %d.%02dMHz\n",
|
||||
(current_cpu_data.bus_clock / 1000000),
|
||||
(current_cpu_data.bus_clock % 1000000)/10000);
|
||||
#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
|
||||
printk("Memory clock: %d.%02dMHz\n",
|
||||
(current_cpu_data.memory_clock / 1000000),
|
||||
(current_cpu_data.memory_clock % 1000000)/10000);
|
||||
#endif
|
||||
printk("Module clock: %d.%02dMHz\n",
|
||||
(current_cpu_data.module_clock / 1000000),
|
||||
(current_cpu_data.module_clock % 1000000)/10000);
|
||||
|
||||
interval = (current_cpu_data.module_clock/4 + HZ/2) / HZ;
|
||||
|
||||
printk("Interval = %ld\n", interval);
|
||||
|
||||
/* Start TMU0 */
|
||||
ctrl_outb(0, TMU_TSTR);
|
||||
#if !defined(CONFIG_CPU_SUBTYPE_SH7300)
|
||||
ctrl_outb(TMU_TOCR_INIT, TMU_TOCR);
|
||||
#endif
|
||||
ctrl_outw(TMU0_TCR_INIT, TMU0_TCR);
|
||||
ctrl_outl(interval, TMU0_TCOR);
|
||||
ctrl_outl(interval, TMU0_TCNT);
|
||||
ctrl_outb(TMU_TSTR_INIT, TMU_TSTR);
|
||||
sys_timer = get_sys_timer();
|
||||
printk(KERN_INFO "Using %s for system timer\n", sys_timer->name);
|
||||
|
||||
#if defined(CONFIG_SH_KGDB)
|
||||
/*
|
||||
|
|
8
arch/sh/kernel/timers/Makefile
Normal file
8
arch/sh/kernel/timers/Makefile
Normal file
|
@ -0,0 +1,8 @@
|
|||
#
|
||||
# Makefile for the various Linux/SuperH timers
|
||||
#
|
||||
|
||||
obj-y := timer.o
|
||||
|
||||
obj-$(CONFIG_SH_TMU) += timer-tmu.o
|
||||
|
229
arch/sh/kernel/timers/timer-tmu.c
Normal file
229
arch/sh/kernel/timers/timer-tmu.c
Normal file
|
@ -0,0 +1,229 @@
|
|||
/*
|
||||
* arch/sh/kernel/timers/timer-tmu.c - TMU Timer Support
|
||||
*
|
||||
* Copyright (C) 2005 Paul Mundt
|
||||
*
|
||||
* TMU handling code hacked out of arch/sh/kernel/time.c
|
||||
*
|
||||
* Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka
|
||||
* Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
|
||||
* Copyright (C) 2002, 2003, 2004 Paul Mundt
|
||||
* Copyright (C) 2002 M. R. Brown <mrbrown@linux-sh.org>
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/seqlock.h>
|
||||
#include <asm/timer.h>
|
||||
#include <asm/rtc.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/clock.h>
|
||||
|
||||
#define TMU_TOCR_INIT 0x00
|
||||
#define TMU0_TCR_INIT 0x0020
|
||||
#define TMU_TSTR_INIT 1
|
||||
|
||||
#define TMU0_TCR_CALIB 0x0000
|
||||
|
||||
static DEFINE_SPINLOCK(tmu0_lock);
|
||||
|
||||
static unsigned long tmu_timer_get_offset(void)
|
||||
{
|
||||
int count;
|
||||
unsigned long flags;
|
||||
|
||||
static int count_p = 0x7fffffff; /* for the first call after boot */
|
||||
static unsigned long jiffies_p = 0;
|
||||
|
||||
/*
|
||||
* cache volatile jiffies temporarily; we have IRQs turned off.
|
||||
*/
|
||||
unsigned long jiffies_t;
|
||||
|
||||
spin_lock_irqsave(&tmu0_lock, flags);
|
||||
/* timer count may underflow right here */
|
||||
count = ctrl_inl(TMU0_TCNT); /* read the latched count */
|
||||
|
||||
jiffies_t = jiffies;
|
||||
|
||||
/*
|
||||
* avoiding timer inconsistencies (they are rare, but they happen)...
|
||||
* there is one kind of problem that must be avoided here:
|
||||
* 1. the timer counter underflows
|
||||
*/
|
||||
|
||||
if (jiffies_t == jiffies_p) {
|
||||
if (count > count_p) {
|
||||
/* the nutcase */
|
||||
if (ctrl_inw(TMU0_TCR) & 0x100) { /* Check UNF bit */
|
||||
count -= LATCH;
|
||||
} else {
|
||||
printk("%s (): hardware timer problem?\n",
|
||||
__FUNCTION__);
|
||||
}
|
||||
}
|
||||
} else
|
||||
jiffies_p = jiffies_t;
|
||||
|
||||
count_p = count;
|
||||
spin_unlock_irqrestore(&tmu0_lock, flags);
|
||||
|
||||
count = ((LATCH-1) - count) * TICK_SIZE;
|
||||
count = (count + LATCH/2) / LATCH;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static irqreturn_t tmu_timer_interrupt(int irq, void *dev_id,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
unsigned long timer_status;
|
||||
|
||||
/* Clear UNF bit */
|
||||
timer_status = ctrl_inw(TMU0_TCR);
|
||||
timer_status &= ~0x100;
|
||||
ctrl_outw(timer_status, TMU0_TCR);
|
||||
|
||||
/*
|
||||
* Here we are in the timer irq handler. We just have irqs locally
|
||||
* disabled but we don't know if the timer_bh is running on the other
|
||||
* CPU. We need to avoid to SMP race with it. NOTE: we don' t need
|
||||
* the irq version of write_lock because as just said we have irq
|
||||
* locally disabled. -arca
|
||||
*/
|
||||
write_seqlock(&xtime_lock);
|
||||
handle_timer_tick(regs);
|
||||
write_sequnlock(&xtime_lock);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static struct irqaction tmu_irq = {
|
||||
.name = "timer",
|
||||
.handler = tmu_timer_interrupt,
|
||||
.flags = SA_INTERRUPT,
|
||||
.mask = CPU_MASK_NONE,
|
||||
};
|
||||
|
||||
/*
|
||||
* Hah! We'll see if this works (switching from usecs to nsecs).
|
||||
*/
|
||||
static unsigned long tmu_timer_get_frequency(void)
|
||||
{
|
||||
u32 freq;
|
||||
struct timespec ts1, ts2;
|
||||
unsigned long diff_nsec;
|
||||
unsigned long factor;
|
||||
|
||||
/* Setup the timer: We don't want to generate interrupts, just
|
||||
* have it count down at its natural rate.
|
||||
*/
|
||||
ctrl_outb(0, TMU_TSTR);
|
||||
#if !defined(CONFIG_CPU_SUBTYPE_SH7300) && !defined(CONFIG_CPU_SUBTYPE_SH7760)
|
||||
ctrl_outb(TMU_TOCR_INIT, TMU_TOCR);
|
||||
#endif
|
||||
ctrl_outw(TMU0_TCR_CALIB, TMU0_TCR);
|
||||
ctrl_outl(0xffffffff, TMU0_TCOR);
|
||||
ctrl_outl(0xffffffff, TMU0_TCNT);
|
||||
|
||||
rtc_get_time(&ts2);
|
||||
|
||||
do {
|
||||
rtc_get_time(&ts1);
|
||||
} while (ts1.tv_nsec == ts2.tv_nsec && ts1.tv_sec == ts2.tv_sec);
|
||||
|
||||
/* actually start the timer */
|
||||
ctrl_outb(TMU_TSTR_INIT, TMU_TSTR);
|
||||
|
||||
do {
|
||||
rtc_get_time(&ts2);
|
||||
} while (ts1.tv_nsec == ts2.tv_nsec && ts1.tv_sec == ts2.tv_sec);
|
||||
|
||||
freq = 0xffffffff - ctrl_inl(TMU0_TCNT);
|
||||
if (ts2.tv_nsec < ts1.tv_nsec) {
|
||||
ts2.tv_nsec += 1000000000;
|
||||
ts2.tv_sec--;
|
||||
}
|
||||
|
||||
diff_nsec = (ts2.tv_sec - ts1.tv_sec) * 1000000000 + (ts2.tv_nsec - ts1.tv_nsec);
|
||||
|
||||
/* this should work well if the RTC has a precision of n Hz, where
|
||||
* n is an integer. I don't think we have to worry about the other
|
||||
* cases. */
|
||||
factor = (1000000000 + diff_nsec/2) / diff_nsec;
|
||||
|
||||
if (factor * diff_nsec > 1100000000 ||
|
||||
factor * diff_nsec < 900000000)
|
||||
panic("weird RTC (diff_nsec %ld)", diff_nsec);
|
||||
|
||||
return freq * factor;
|
||||
}
|
||||
|
||||
static void tmu_clk_init(struct clk *clk)
|
||||
{
|
||||
u8 divisor = TMU0_TCR_INIT & 0x7;
|
||||
ctrl_outw(TMU0_TCR_INIT, TMU0_TCR);
|
||||
clk->rate = clk->parent->rate / (4 << (divisor << 1));
|
||||
}
|
||||
|
||||
static void tmu_clk_recalc(struct clk *clk)
|
||||
{
|
||||
u8 divisor = ctrl_inw(TMU0_TCR) & 0x7;
|
||||
clk->rate = clk->parent->rate / (4 << (divisor << 1));
|
||||
}
|
||||
|
||||
static struct clk_ops tmu_clk_ops = {
|
||||
.init = tmu_clk_init,
|
||||
.recalc = tmu_clk_recalc,
|
||||
};
|
||||
|
||||
static struct clk tmu0_clk = {
|
||||
.name = "tmu0_clk",
|
||||
.ops = &tmu_clk_ops,
|
||||
};
|
||||
|
||||
static int tmu_timer_init(void)
|
||||
{
|
||||
unsigned long interval;
|
||||
|
||||
setup_irq(TIMER_IRQ, &tmu_irq);
|
||||
|
||||
tmu0_clk.parent = clk_get("module_clk");
|
||||
|
||||
/* Start TMU0 */
|
||||
ctrl_outb(0, TMU_TSTR);
|
||||
#if !defined(CONFIG_CPU_SUBTYPE_SH7300) && !defined(CONFIG_CPU_SUBTYPE_SH7760)
|
||||
ctrl_outb(TMU_TOCR_INIT, TMU_TOCR);
|
||||
#endif
|
||||
|
||||
clk_register(&tmu0_clk);
|
||||
clk_enable(&tmu0_clk);
|
||||
|
||||
interval = (clk_get_rate(&tmu0_clk) + HZ / 2) / HZ;
|
||||
printk(KERN_INFO "Interval = %ld\n", interval);
|
||||
|
||||
ctrl_outl(interval, TMU0_TCOR);
|
||||
ctrl_outl(interval, TMU0_TCNT);
|
||||
|
||||
ctrl_outb(TMU_TSTR_INIT, TMU_TSTR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct sys_timer_ops tmu_timer_ops = {
|
||||
.init = tmu_timer_init,
|
||||
.get_frequency = tmu_timer_get_frequency,
|
||||
.get_offset = tmu_timer_get_offset,
|
||||
};
|
||||
|
||||
struct sys_timer tmu_timer = {
|
||||
.name = "tmu",
|
||||
.ops = &tmu_timer_ops,
|
||||
};
|
||||
|
50
arch/sh/kernel/timers/timer.c
Normal file
50
arch/sh/kernel/timers/timer.c
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* arch/sh/kernel/timers/timer.c - Common timer code
|
||||
*
|
||||
* Copyright (C) 2005 Paul Mundt
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/string.h>
|
||||
#include <asm/timer.h>
|
||||
|
||||
static struct sys_timer *sys_timers[] __initdata = {
|
||||
#ifdef CONFIG_SH_TMU
|
||||
&tmu_timer,
|
||||
#endif
|
||||
NULL,
|
||||
};
|
||||
|
||||
static char timer_override[10] __initdata;
|
||||
static int __init timer_setup(char *str)
|
||||
{
|
||||
if (str)
|
||||
strlcpy(timer_override, str, sizeof(timer_override));
|
||||
return 1;
|
||||
}
|
||||
__setup("timer=", timer_setup);
|
||||
|
||||
struct sys_timer *get_sys_timer(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sys_timers); i++) {
|
||||
struct sys_timer *t = sys_timers[i];
|
||||
|
||||
if (unlikely(!t))
|
||||
break;
|
||||
if (unlikely(timer_override[0]))
|
||||
if ((strcmp(timer_override, t->name) != 0))
|
||||
continue;
|
||||
if (likely(t->ops->init() == 0))
|
||||
return t;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
233
arch/sh/mm/Kconfig
Normal file
233
arch/sh/mm/Kconfig
Normal file
|
@ -0,0 +1,233 @@
|
|||
menu "Processor selection"
|
||||
|
||||
#
|
||||
# Processor families
|
||||
#
|
||||
config CPU_SH2
|
||||
bool
|
||||
select SH_WRITETHROUGH
|
||||
|
||||
config CPU_SH3
|
||||
bool
|
||||
select CPU_HAS_INTEVT
|
||||
select CPU_HAS_SR_RB
|
||||
|
||||
config CPU_SH4
|
||||
bool
|
||||
select CPU_HAS_INTEVT
|
||||
select CPU_HAS_SR_RB
|
||||
|
||||
config CPU_SH4A
|
||||
bool
|
||||
select CPU_SH4
|
||||
select CPU_HAS_INTC2_IRQ
|
||||
|
||||
config CPU_SUBTYPE_ST40
|
||||
bool
|
||||
select CPU_SH4
|
||||
select CPU_HAS_INTC2_IRQ
|
||||
|
||||
#
|
||||
# Processor subtypes
|
||||
#
|
||||
|
||||
comment "SH-2 Processor Support"
|
||||
|
||||
config CPU_SUBTYPE_SH7604
|
||||
bool "Support SH7604 processor"
|
||||
select CPU_SH2
|
||||
|
||||
comment "SH-3 Processor Support"
|
||||
|
||||
config CPU_SUBTYPE_SH7300
|
||||
bool "Support SH7300 processor"
|
||||
select CPU_SH3
|
||||
|
||||
config CPU_SUBTYPE_SH7705
|
||||
bool "Support SH7705 processor"
|
||||
select CPU_SH3
|
||||
select CPU_HAS_PINT_IRQ
|
||||
|
||||
config CPU_SUBTYPE_SH7707
|
||||
bool "Support SH7707 processor"
|
||||
select CPU_SH3
|
||||
select CPU_HAS_PINT_IRQ
|
||||
help
|
||||
Select SH7707 if you have a 60 Mhz SH-3 HD6417707 CPU.
|
||||
|
||||
config CPU_SUBTYPE_SH7708
|
||||
bool "Support SH7708 processor"
|
||||
select CPU_SH3
|
||||
help
|
||||
Select SH7708 if you have a 60 Mhz SH-3 HD6417708S or
|
||||
if you have a 100 Mhz SH-3 HD6417708R CPU.
|
||||
|
||||
config CPU_SUBTYPE_SH7709
|
||||
bool "Support SH7709 processor"
|
||||
select CPU_SH3
|
||||
select CPU_HAS_PINT_IRQ
|
||||
help
|
||||
Select SH7709 if you have a 80 Mhz SH-3 HD6417709 CPU.
|
||||
|
||||
comment "SH-4 Processor Support"
|
||||
|
||||
config CPU_SUBTYPE_SH7750
|
||||
bool "Support SH7750 processor"
|
||||
select CPU_SH4
|
||||
help
|
||||
Select SH7750 if you have a 200 Mhz SH-4 HD6417750 CPU.
|
||||
|
||||
config CPU_SUBTYPE_SH7091
|
||||
bool "Support SH7091 processor"
|
||||
select CPU_SH4
|
||||
select CPU_SUBTYPE_SH7750
|
||||
help
|
||||
Select SH7091 if you have an SH-4 based Sega device (such as
|
||||
the Dreamcast, Naomi, and Naomi 2).
|
||||
|
||||
config CPU_SUBTYPE_SH7750R
|
||||
bool "Support SH7750R processor"
|
||||
select CPU_SH4
|
||||
select CPU_SUBTYPE_SH7750
|
||||
|
||||
config CPU_SUBTYPE_SH7750S
|
||||
bool "Support SH7750S processor"
|
||||
select CPU_SH4
|
||||
select CPU_SUBTYPE_SH7750
|
||||
|
||||
config CPU_SUBTYPE_SH7751
|
||||
bool "Support SH7751 processor"
|
||||
select CPU_SH4
|
||||
help
|
||||
Select SH7751 if you have a 166 Mhz SH-4 HD6417751 CPU,
|
||||
or if you have a HD6417751R CPU.
|
||||
|
||||
config CPU_SUBTYPE_SH7751R
|
||||
bool "Support SH7751R processor"
|
||||
select CPU_SH4
|
||||
select CPU_SUBTYPE_SH7751
|
||||
|
||||
config CPU_SUBTYPE_SH7760
|
||||
bool "Support SH7760 processor"
|
||||
select CPU_SH4
|
||||
select CPU_HAS_INTC2_IRQ
|
||||
|
||||
config CPU_SUBTYPE_SH4_202
|
||||
bool "Support SH4-202 processor"
|
||||
select CPU_SH4
|
||||
|
||||
comment "ST40 Processor Support"
|
||||
|
||||
config CPU_SUBTYPE_ST40STB1
|
||||
bool "Support ST40STB1/ST40RA processors"
|
||||
select CPU_SUBTYPE_ST40
|
||||
help
|
||||
Select ST40STB1 if you have a ST40RA CPU.
|
||||
This was previously called the ST40STB1, hence the option name.
|
||||
|
||||
config CPU_SUBTYPE_ST40GX1
|
||||
bool "Support ST40GX1 processor"
|
||||
select CPU_SUBTYPE_ST40
|
||||
help
|
||||
Select ST40GX1 if you have a ST40GX1 CPU.
|
||||
|
||||
comment "SH-4A Processor Support"
|
||||
|
||||
config CPU_SUBTYPE_SH73180
|
||||
bool "Support SH73180 processor"
|
||||
select CPU_SH4A
|
||||
|
||||
config CPU_SUBTYPE_SH7770
|
||||
bool "Support SH7770 processor"
|
||||
select CPU_SH4A
|
||||
|
||||
config CPU_SUBTYPE_SH7780
|
||||
bool "Support SH7780 processor"
|
||||
select CPU_SH4A
|
||||
|
||||
endmenu
|
||||
|
||||
menu "Memory management options"
|
||||
|
||||
config MMU
|
||||
bool "Support for memory management hardware"
|
||||
depends on !CPU_SH2
|
||||
default y
|
||||
help
|
||||
Some SH processors (such as SH-2/SH-2A) lack an MMU. In order to
|
||||
boot on these systems, this option must not be set.
|
||||
|
||||
On other systems (such as the SH-3 and 4) where an MMU exists,
|
||||
turning this off will boot the kernel on these machines with the
|
||||
MMU implicitly switched off.
|
||||
|
||||
config 32BIT
|
||||
bool "Support 32-bit physical addressing through PMB"
|
||||
depends on CPU_SH4A
|
||||
default y
|
||||
help
|
||||
If you say Y here, physical addressing will be extended to
|
||||
32-bits through the SH-4A PMB. If this is not set, legacy
|
||||
29-bit physical addressing will be used.
|
||||
|
||||
choice
|
||||
prompt "HugeTLB page size"
|
||||
depends on HUGETLB_PAGE && CPU_SH4 && MMU
|
||||
default HUGETLB_PAGE_SIZE_64K
|
||||
|
||||
config HUGETLB_PAGE_SIZE_64K
|
||||
bool "64K"
|
||||
|
||||
config HUGETLB_PAGE_SIZE_1MB
|
||||
bool "1MB"
|
||||
|
||||
endchoice
|
||||
|
||||
source "mm/Kconfig"
|
||||
|
||||
endmenu
|
||||
|
||||
menu "Cache configuration"
|
||||
|
||||
config SH7705_CACHE_32KB
|
||||
bool "Enable 32KB cache size for SH7705"
|
||||
depends on CPU_SUBTYPE_SH7705
|
||||
default y
|
||||
|
||||
config SH_DIRECT_MAPPED
|
||||
bool "Use direct-mapped caching"
|
||||
default n
|
||||
help
|
||||
Selecting this option will configure the caches to be direct-mapped,
|
||||
even if the cache supports a 2 or 4-way mode. This is useful primarily
|
||||
for debugging on platforms with 2 and 4-way caches (SH7750R/SH7751R,
|
||||
SH4-202, SH4-501, etc.)
|
||||
|
||||
Turn this option off for platforms that do not have a direct-mapped
|
||||
cache, and you have no need to run the caches in such a configuration.
|
||||
|
||||
config SH_WRITETHROUGH
|
||||
bool "Use write-through caching"
|
||||
default y if CPU_SH2
|
||||
help
|
||||
Selecting this option will configure the caches in write-through
|
||||
mode, as opposed to the default write-back configuration.
|
||||
|
||||
Since there's sill some aliasing issues on SH-4, this option will
|
||||
unfortunately still require the majority of flushing functions to
|
||||
be implemented to deal with aliasing.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config SH_OCRAM
|
||||
bool "Operand Cache RAM (OCRAM) support"
|
||||
help
|
||||
Selecting this option will automatically tear down the number of
|
||||
sets in the dcache by half, which in turn exposes a memory range.
|
||||
|
||||
The addresses for the OC RAM base will vary according to the
|
||||
processor version. Consult vendor documentation for specifics.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
endmenu
|
|
@ -6,13 +6,19 @@
|
|||
* 640k-1MB IO memory area on PC's
|
||||
*
|
||||
* (C) Copyright 1995 1996 Linus Torvalds
|
||||
* (C) Copyright 2005, 2006 Paul Mundt
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General
|
||||
* Public License. See the file "COPYING" in the main directory of this
|
||||
* archive for more details.
|
||||
*/
|
||||
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mm.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/pgalloc.h>
|
||||
#include <asm/addrspace.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/tlbflush.h>
|
||||
|
||||
|
@ -80,9 +86,15 @@ int remap_area_pages(unsigned long address, unsigned long phys_addr,
|
|||
if (address >= end)
|
||||
BUG();
|
||||
do {
|
||||
pud_t *pud;
|
||||
pmd_t *pmd;
|
||||
pmd = pmd_alloc(&init_mm, dir, address);
|
||||
|
||||
error = -ENOMEM;
|
||||
|
||||
pud = pud_alloc(&init_mm, dir, address);
|
||||
if (!pud)
|
||||
break;
|
||||
pmd = pmd_alloc(&init_mm, pud, address);
|
||||
if (!pmd)
|
||||
break;
|
||||
if (remap_area_pmd(pmd, address, end - address,
|
||||
|
@ -96,10 +108,6 @@ int remap_area_pages(unsigned long address, unsigned long phys_addr,
|
|||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generic mapping function (not visible outside):
|
||||
*/
|
||||
|
||||
/*
|
||||
* Remap an arbitrary physical address space into the kernel virtual
|
||||
* address space. Needed when the kernel wants to access high addresses
|
||||
|
@ -109,11 +117,11 @@ int remap_area_pages(unsigned long address, unsigned long phys_addr,
|
|||
* have to convert them into an offset in a page-aligned mapping, but the
|
||||
* caller shouldn't need to know that small detail.
|
||||
*/
|
||||
void * p3_ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
|
||||
void __iomem *__ioremap(unsigned long phys_addr, unsigned long size,
|
||||
unsigned long flags)
|
||||
{
|
||||
void * addr;
|
||||
struct vm_struct * area;
|
||||
unsigned long offset, last_addr;
|
||||
unsigned long offset, last_addr, addr, orig_addr;
|
||||
|
||||
/* Don't allow wraparound or zero size */
|
||||
last_addr = phys_addr + size - 1;
|
||||
|
@ -124,7 +132,7 @@ void * p3_ioremap(unsigned long phys_addr, unsigned long size, unsigned long fla
|
|||
* Don't remap the low PCI/ISA area, it's always mapped..
|
||||
*/
|
||||
if (phys_addr >= 0xA0000 && last_addr < 0x100000)
|
||||
return phys_to_virt(phys_addr);
|
||||
return (void __iomem *)phys_to_virt(phys_addr);
|
||||
|
||||
/*
|
||||
* Don't allow anybody to remap normal RAM that we're using..
|
||||
|
@ -146,16 +154,71 @@ void * p3_ioremap(unsigned long phys_addr, unsigned long size, unsigned long fla
|
|||
if (!area)
|
||||
return NULL;
|
||||
area->phys_addr = phys_addr;
|
||||
addr = area->addr;
|
||||
if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) {
|
||||
vunmap(addr);
|
||||
return NULL;
|
||||
}
|
||||
return (void *) (offset + (char *)addr);
|
||||
}
|
||||
orig_addr = addr = (unsigned long)area->addr;
|
||||
|
||||
void p3_iounmap(void *addr)
|
||||
{
|
||||
if (addr > high_memory)
|
||||
vfree((void *)(PAGE_MASK & (unsigned long)addr));
|
||||
#ifdef CONFIG_32BIT
|
||||
/*
|
||||
* First try to remap through the PMB once a valid VMA has been
|
||||
* established. Smaller allocations (or the rest of the size
|
||||
* remaining after a PMB mapping due to the size not being
|
||||
* perfectly aligned on a PMB size boundary) are then mapped
|
||||
* through the UTLB using conventional page tables.
|
||||
*
|
||||
* PMB entries are all pre-faulted.
|
||||
*/
|
||||
if (unlikely(size >= 0x1000000)) {
|
||||
unsigned long mapped = pmb_remap(addr, phys_addr, size, flags);
|
||||
|
||||
if (likely(mapped)) {
|
||||
addr += mapped;
|
||||
phys_addr += mapped;
|
||||
size -= mapped;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (likely(size))
|
||||
if (remap_area_pages(addr, phys_addr, size, flags)) {
|
||||
vunmap((void *)orig_addr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (void __iomem *)(offset + (char *)orig_addr);
|
||||
}
|
||||
EXPORT_SYMBOL(__ioremap);
|
||||
|
||||
void __iounmap(void __iomem *addr)
|
||||
{
|
||||
unsigned long vaddr = (unsigned long __force)addr;
|
||||
struct vm_struct *p;
|
||||
|
||||
if (PXSEG(vaddr) < P3SEG)
|
||||
return;
|
||||
|
||||
#ifdef CONFIG_32BIT
|
||||
/*
|
||||
* Purge any PMB entries that may have been established for this
|
||||
* mapping, then proceed with conventional VMA teardown.
|
||||
*
|
||||
* XXX: Note that due to the way that remove_vm_area() does
|
||||
* matching of the resultant VMA, we aren't able to fast-forward
|
||||
* the address past the PMB space until the end of the VMA where
|
||||
* the page tables reside. As such, unmap_vm_area() will be
|
||||
* forced to linearly scan over the area until it finds the page
|
||||
* tables where PTEs that need to be unmapped actually reside,
|
||||
* which is far from optimal. Perhaps we need to use a separate
|
||||
* VMA for the PMB mappings?
|
||||
* -- PFM.
|
||||
*/
|
||||
pmb_unmap(vaddr);
|
||||
#endif
|
||||
|
||||
p = remove_vm_area((void *)(vaddr & PAGE_MASK));
|
||||
if (!p) {
|
||||
printk(KERN_ERR "%s: bad address %p\n", __FUNCTION__, addr);
|
||||
return;
|
||||
}
|
||||
|
||||
kfree(p);
|
||||
}
|
||||
EXPORT_SYMBOL(__iounmap);
|
||||
|
|
|
@ -10,10 +10,7 @@ SE SH_SOLUTION_ENGINE
|
|||
7300SE SH_7300_SOLUTION_ENGINE
|
||||
73180SE SH_73180_SOLUTION_ENGINE
|
||||
7751SYSTEMH SH_7751_SYSTEMH
|
||||
HP600 SH_HP600
|
||||
HP620 SH_HP620
|
||||
HP680 SH_HP680
|
||||
HP690 SH_HP690
|
||||
HP6XX SH_HP6XX
|
||||
HD64461 HD64461
|
||||
HD64465 HD64465
|
||||
SH2000 SH_SH2000
|
||||
|
|
|
@ -295,8 +295,7 @@ static void iommu_release_one(u32 busa, int npages, struct sbus_bus *sbus)
|
|||
int ioptex;
|
||||
int i;
|
||||
|
||||
if (busa < iommu->start)
|
||||
BUG();
|
||||
BUG_ON(busa < iommu->start);
|
||||
ioptex = (busa - iommu->start) >> PAGE_SHIFT;
|
||||
for (i = 0; i < npages; i++) {
|
||||
iopte_val(iommu->page_table[ioptex + i]) = 0;
|
||||
|
@ -340,9 +339,9 @@ static int iommu_map_dma_area(dma_addr_t *pba, unsigned long va,
|
|||
iopte_t *first;
|
||||
int ioptex;
|
||||
|
||||
if ((va & ~PAGE_MASK) != 0) BUG();
|
||||
if ((addr & ~PAGE_MASK) != 0) BUG();
|
||||
if ((len & ~PAGE_MASK) != 0) BUG();
|
||||
BUG_ON((va & ~PAGE_MASK) != 0);
|
||||
BUG_ON((addr & ~PAGE_MASK) != 0);
|
||||
BUG_ON((len & ~PAGE_MASK) != 0);
|
||||
|
||||
/* page color = physical address */
|
||||
ioptex = bit_map_string_get(&iommu->usemap, len >> PAGE_SHIFT,
|
||||
|
@ -405,8 +404,8 @@ static void iommu_unmap_dma_area(unsigned long busa, int len)
|
|||
unsigned long end;
|
||||
int ioptex = (busa - iommu->start) >> PAGE_SHIFT;
|
||||
|
||||
if ((busa & ~PAGE_MASK) != 0) BUG();
|
||||
if ((len & ~PAGE_MASK) != 0) BUG();
|
||||
BUG_ON((busa & ~PAGE_MASK) != 0);
|
||||
BUG_ON((len & ~PAGE_MASK) != 0);
|
||||
|
||||
iopte += ioptex;
|
||||
end = busa + len;
|
||||
|
|
|
@ -280,9 +280,9 @@ static struct sparc64_tick_ops stick_operations __read_mostly = {
|
|||
* Since STICK is constantly updating, we have to access it carefully.
|
||||
*
|
||||
* The sequence we use to read is:
|
||||
* 1) read low
|
||||
* 2) read high
|
||||
* 3) read low again, if it rolled over increment high by 1
|
||||
* 1) read high
|
||||
* 2) read low
|
||||
* 3) read high again, if it rolled re-read both low and high again.
|
||||
*
|
||||
* Writing STICK safely is also tricky:
|
||||
* 1) write low to zero
|
||||
|
@ -295,18 +295,18 @@ static struct sparc64_tick_ops stick_operations __read_mostly = {
|
|||
static unsigned long __hbird_read_stick(void)
|
||||
{
|
||||
unsigned long ret, tmp1, tmp2, tmp3;
|
||||
unsigned long addr = HBIRD_STICK_ADDR;
|
||||
unsigned long addr = HBIRD_STICK_ADDR+8;
|
||||
|
||||
__asm__ __volatile__("ldxa [%1] %5, %2\n\t"
|
||||
"add %1, 0x8, %1\n\t"
|
||||
"ldxa [%1] %5, %3\n\t"
|
||||
__asm__ __volatile__("ldxa [%1] %5, %2\n"
|
||||
"1:\n\t"
|
||||
"sub %1, 0x8, %1\n\t"
|
||||
"ldxa [%1] %5, %3\n\t"
|
||||
"add %1, 0x8, %1\n\t"
|
||||
"ldxa [%1] %5, %4\n\t"
|
||||
"cmp %4, %2\n\t"
|
||||
"blu,a,pn %%xcc, 1f\n\t"
|
||||
" add %3, 1, %3\n"
|
||||
"1:\n\t"
|
||||
"sllx %3, 32, %3\n\t"
|
||||
"bne,a,pn %%xcc, 1b\n\t"
|
||||
" mov %4, %2\n\t"
|
||||
"sllx %4, 32, %4\n\t"
|
||||
"or %3, %4, %0\n\t"
|
||||
: "=&r" (ret), "=&r" (addr),
|
||||
"=&r" (tmp1), "=&r" (tmp2), "=&r" (tmp3)
|
||||
|
|
|
@ -305,7 +305,11 @@ config ARCH_DISCONTIGMEM_DEFAULT
|
|||
|
||||
config ARCH_SPARSEMEM_ENABLE
|
||||
def_bool y
|
||||
depends on NUMA
|
||||
depends on (NUMA || EXPERIMENTAL)
|
||||
|
||||
config ARCH_MEMORY_PROBE
|
||||
def_bool y
|
||||
depends on MEMORY_HOTPLUG
|
||||
|
||||
config ARCH_FLATMEM_ENABLE
|
||||
def_bool y
|
||||
|
@ -315,6 +319,7 @@ source "mm/Kconfig"
|
|||
|
||||
config HAVE_ARCH_EARLY_PFN_TO_NID
|
||||
def_bool y
|
||||
depends on NUMA
|
||||
|
||||
config NR_CPUS
|
||||
int "Maximum number of CPUs (2-256)"
|
||||
|
@ -350,7 +355,7 @@ config HPET_TIMER
|
|||
<http://www.intel.com/hardwaredesign/hpetspec.htm>.
|
||||
|
||||
config X86_PM_TIMER
|
||||
bool "PM timer"
|
||||
bool "PM timer" if EMBEDDED
|
||||
depends on ACPI
|
||||
default y
|
||||
help
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#
|
||||
# Automatically generated make config: don't edit
|
||||
# Linux kernel version: 2.6.15-git7
|
||||
# Wed Jan 11 11:57:36 2006
|
||||
# Linux kernel version: 2.6.15-git12
|
||||
# Mon Jan 16 13:09:08 2006
|
||||
#
|
||||
CONFIG_X86_64=y
|
||||
CONFIG_64BIT=y
|
||||
|
@ -319,6 +319,11 @@ CONFIG_IPV6=y
|
|||
# CONFIG_ATALK is not set
|
||||
# CONFIG_X25 is not set
|
||||
# CONFIG_LAPB is not set
|
||||
|
||||
#
|
||||
# TIPC Configuration (EXPERIMENTAL)
|
||||
#
|
||||
# CONFIG_TIPC is not set
|
||||
# CONFIG_NET_DIVERT is not set
|
||||
# CONFIG_ECONET is not set
|
||||
# CONFIG_WAN_ROUTER is not set
|
||||
|
@ -537,8 +542,7 @@ CONFIG_SCSI_SATA_INTEL_COMBINED=y
|
|||
# CONFIG_SCSI_IPR is not set
|
||||
# CONFIG_SCSI_QLOGIC_FC is not set
|
||||
# CONFIG_SCSI_QLOGIC_1280 is not set
|
||||
CONFIG_SCSI_QLA2XXX=y
|
||||
# CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE is not set
|
||||
# CONFIG_SCSI_QLA_FC is not set
|
||||
# CONFIG_SCSI_LPFC is not set
|
||||
# CONFIG_SCSI_DC395x is not set
|
||||
# CONFIG_SCSI_DC390T is not set
|
||||
|
@ -805,6 +809,7 @@ CONFIG_SOFT_WATCHDOG=y
|
|||
# CONFIG_W83877F_WDT is not set
|
||||
# CONFIG_W83977F_WDT is not set
|
||||
# CONFIG_MACHZ_WDT is not set
|
||||
# CONFIG_SBC_EPX_C3_WATCHDOG is not set
|
||||
|
||||
#
|
||||
# PCI-based Watchdog Cards
|
||||
|
@ -849,6 +854,12 @@ CONFIG_HPET_MMAP=y
|
|||
#
|
||||
# CONFIG_I2C is not set
|
||||
|
||||
#
|
||||
# SPI support
|
||||
#
|
||||
# CONFIG_SPI is not set
|
||||
# CONFIG_SPI_MASTER is not set
|
||||
|
||||
#
|
||||
# Dallas's 1-wire bus
|
||||
#
|
||||
|
@ -992,6 +1003,7 @@ CONFIG_USB_STORAGE=y
|
|||
#
|
||||
CONFIG_USB_HID=y
|
||||
CONFIG_USB_HIDINPUT=y
|
||||
# CONFIG_USB_HIDINPUT_POWERBOOK is not set
|
||||
# CONFIG_HID_FF is not set
|
||||
# CONFIG_USB_HIDDEV is not set
|
||||
# CONFIG_USB_AIPTEK is not set
|
||||
|
@ -1276,6 +1288,7 @@ CONFIG_DETECT_SOFTLOCKUP=y
|
|||
CONFIG_DEBUG_FS=y
|
||||
# CONFIG_DEBUG_VM is not set
|
||||
# CONFIG_FRAME_POINTER is not set
|
||||
# CONFIG_FORCED_INLINING is not set
|
||||
# CONFIG_RCU_TORTURE_TEST is not set
|
||||
CONFIG_INIT_DEBUG=y
|
||||
# CONFIG_DEBUG_RODATA is not set
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
#
|
||||
|
||||
obj-$(CONFIG_IA32_EMULATION) := ia32entry.o sys_ia32.o ia32_signal.o tls32.o \
|
||||
ia32_binfmt.o fpu32.o ptrace32.o syscall32.o syscall32_syscall.o
|
||||
ia32_binfmt.o fpu32.o ptrace32.o syscall32.o syscall32_syscall.o \
|
||||
mmap32.o
|
||||
|
||||
sysv-$(CONFIG_SYSVIPC) := ipc32.o
|
||||
obj-$(CONFIG_IA32_EMULATION) += $(sysv-y)
|
||||
|
|
|
@ -293,8 +293,6 @@ int ia32_setup_arg_pages(struct linux_binprm *bprm, unsigned long stack_top, int
|
|||
} while(0)
|
||||
|
||||
|
||||
#define elf_map elf32_map
|
||||
|
||||
#include <linux/module.h>
|
||||
|
||||
MODULE_DESCRIPTION("Binary format loader for compatibility with IA32 ELF binaries.");
|
||||
|
@ -390,21 +388,6 @@ int ia32_setup_arg_pages(struct linux_binprm *bprm, unsigned long stack_top,
|
|||
}
|
||||
EXPORT_SYMBOL(ia32_setup_arg_pages);
|
||||
|
||||
static unsigned long
|
||||
elf32_map (struct file *filep, unsigned long addr, struct elf_phdr *eppnt, int prot, int type)
|
||||
{
|
||||
unsigned long map_addr;
|
||||
struct task_struct *me = current;
|
||||
|
||||
down_write(&me->mm->mmap_sem);
|
||||
map_addr = do_mmap(filep, ELF_PAGESTART(addr),
|
||||
eppnt->p_filesz + ELF_PAGEOFFSET(eppnt->p_vaddr), prot,
|
||||
type,
|
||||
eppnt->p_offset - ELF_PAGEOFFSET(eppnt->p_vaddr));
|
||||
up_write(&me->mm->mmap_sem);
|
||||
return(map_addr);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SYSCTL
|
||||
/* Register vsyscall32 into the ABI table */
|
||||
#include <linux/sysctl.h>
|
||||
|
|
78
arch/x86_64/ia32/mmap32.c
Normal file
78
arch/x86_64/ia32/mmap32.c
Normal file
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* linux/arch/x86_64/ia32/mm/mmap.c
|
||||
*
|
||||
* flexible mmap layout support
|
||||
*
|
||||
* Based on the i386 version which was
|
||||
*
|
||||
* Copyright 2003-2004 Red Hat Inc., Durham, North Carolina.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*
|
||||
* Started by Ingo Molnar <mingo@elte.hu>
|
||||
*/
|
||||
|
||||
#include <linux/personality.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/random.h>
|
||||
|
||||
/*
|
||||
* Top of mmap area (just below the process stack).
|
||||
*
|
||||
* Leave an at least ~128 MB hole.
|
||||
*/
|
||||
#define MIN_GAP (128*1024*1024)
|
||||
#define MAX_GAP (TASK_SIZE/6*5)
|
||||
|
||||
static inline unsigned long mmap_base(struct mm_struct *mm)
|
||||
{
|
||||
unsigned long gap = current->signal->rlim[RLIMIT_STACK].rlim_cur;
|
||||
unsigned long random_factor = 0;
|
||||
|
||||
if (current->flags & PF_RANDOMIZE)
|
||||
random_factor = get_random_int() % (1024*1024);
|
||||
|
||||
if (gap < MIN_GAP)
|
||||
gap = MIN_GAP;
|
||||
else if (gap > MAX_GAP)
|
||||
gap = MAX_GAP;
|
||||
|
||||
return PAGE_ALIGN(TASK_SIZE - gap - random_factor);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function, called very early during the creation of a new
|
||||
* process VM image, sets up which VM layout function to use:
|
||||
*/
|
||||
void ia32_pick_mmap_layout(struct mm_struct *mm)
|
||||
{
|
||||
/*
|
||||
* Fall back to the standard layout if the personality
|
||||
* bit is set, or if the expected stack growth is unlimited:
|
||||
*/
|
||||
if (sysctl_legacy_va_layout ||
|
||||
(current->personality & ADDR_COMPAT_LAYOUT) ||
|
||||
current->signal->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY) {
|
||||
mm->mmap_base = TASK_UNMAPPED_BASE;
|
||||
mm->get_unmapped_area = arch_get_unmapped_area;
|
||||
mm->unmap_area = arch_unmap_area;
|
||||
} else {
|
||||
mm->mmap_base = mmap_base(mm);
|
||||
mm->get_unmapped_area = arch_get_unmapped_area_topdown;
|
||||
mm->unmap_area = arch_unmap_area_topdown;
|
||||
}
|
||||
}
|
|
@ -499,13 +499,10 @@ static int lapic_resume(struct sys_device *dev)
|
|||
if (!apic_pm_state.active)
|
||||
return 0;
|
||||
|
||||
/* XXX: Pavel needs this for S3 resume, but can't explain why */
|
||||
set_fixmap_nocache(FIX_APIC_BASE, APIC_DEFAULT_PHYS_BASE);
|
||||
|
||||
local_irq_save(flags);
|
||||
rdmsr(MSR_IA32_APICBASE, l, h);
|
||||
l &= ~MSR_IA32_APICBASE_BASE;
|
||||
l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE;
|
||||
l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr;
|
||||
wrmsr(MSR_IA32_APICBASE, l, h);
|
||||
apic_write(APIC_LVTERR, ERROR_APIC_VECTOR | APIC_LVT_MASKED);
|
||||
apic_write(APIC_ID, apic_pm_state.apic_id);
|
||||
|
|
|
@ -43,6 +43,7 @@ int main(void)
|
|||
ENTRY(irqcount);
|
||||
ENTRY(cpunumber);
|
||||
ENTRY(irqstackptr);
|
||||
ENTRY(data_offset);
|
||||
BLANK();
|
||||
#undef ENTRY
|
||||
#ifdef CONFIG_IA32_EMULATION
|
||||
|
@ -66,8 +67,6 @@ int main(void)
|
|||
DEFINE(pbe_orig_address, offsetof(struct pbe, orig_address));
|
||||
DEFINE(pbe_next, offsetof(struct pbe, next));
|
||||
BLANK();
|
||||
#if DEBUG_STKSZ > EXCEPTION_STKSZ
|
||||
DEFINE(DEBUG_IST, DEBUG_STACK);
|
||||
#endif
|
||||
DEFINE(TSS_ist, offsetof(struct tss_struct, ist));
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include <asm/unistd.h>
|
||||
#include <asm/thread_info.h>
|
||||
#include <asm/hw_irq.h>
|
||||
#include <asm/page.h>
|
||||
|
||||
.code64
|
||||
|
||||
|
@ -674,9 +675,6 @@ ENTRY(spurious_interrupt)
|
|||
|
||||
/* error code is on the stack already */
|
||||
/* handle NMI like exceptions that can happen everywhere */
|
||||
#ifndef DEBUG_IST
|
||||
# define DEBUG_IST 0
|
||||
#endif
|
||||
.macro paranoidentry sym, ist=0
|
||||
SAVE_ALL
|
||||
cld
|
||||
|
@ -695,11 +693,11 @@ ENTRY(spurious_interrupt)
|
|||
movq ORIG_RAX(%rsp),%rsi
|
||||
movq $-1,ORIG_RAX(%rsp)
|
||||
.if \ist
|
||||
subq $EXCEPTION_STACK_SIZE, per_cpu__init_tss + TSS_ist + (\ist - 1) * 8(%rbp)
|
||||
subq $EXCEPTION_STKSZ, per_cpu__init_tss + TSS_ist + (\ist - 1) * 8(%rbp)
|
||||
.endif
|
||||
call \sym
|
||||
.if \ist
|
||||
addq $EXCEPTION_STACK_SIZE, per_cpu__init_tss + TSS_ist + (\ist - 1) * 8(%rbp)
|
||||
addq $EXCEPTION_STKSZ, per_cpu__init_tss + TSS_ist + (\ist - 1) * 8(%rbp)
|
||||
.endif
|
||||
cli
|
||||
.endm
|
||||
|
@ -918,7 +916,7 @@ KPROBE_ENTRY(debug)
|
|||
INTR_FRAME
|
||||
pushq $0
|
||||
CFI_ADJUST_CFA_OFFSET 8
|
||||
paranoidentry do_debug, DEBUG_IST
|
||||
paranoidentry do_debug, DEBUG_STACK
|
||||
jmp paranoid_exit
|
||||
CFI_ENDPROC
|
||||
.previous .text
|
||||
|
@ -976,7 +974,7 @@ KPROBE_ENTRY(int3)
|
|||
INTR_FRAME
|
||||
pushq $0
|
||||
CFI_ADJUST_CFA_OFFSET 8
|
||||
paranoidentry do_int3, DEBUG_IST
|
||||
paranoidentry do_int3, DEBUG_STACK
|
||||
jmp paranoid_exit
|
||||
CFI_ENDPROC
|
||||
.previous .text
|
||||
|
|
|
@ -241,104 +241,70 @@ ljumpvector:
|
|||
ENTRY(stext)
|
||||
ENTRY(_stext)
|
||||
|
||||
.org 0x1000
|
||||
ENTRY(init_level4_pgt)
|
||||
$page = 0
|
||||
#define NEXT_PAGE(name) \
|
||||
$page = $page + 1; \
|
||||
.org $page * 0x1000; \
|
||||
phys_/**/name = $page * 0x1000 + __PHYSICAL_START; \
|
||||
ENTRY(name)
|
||||
|
||||
NEXT_PAGE(init_level4_pgt)
|
||||
/* This gets initialized in x86_64_start_kernel */
|
||||
.fill 512,8,0
|
||||
|
||||
.org 0x2000
|
||||
ENTRY(level3_ident_pgt)
|
||||
.quad 0x0000000000004007 + __PHYSICAL_START
|
||||
NEXT_PAGE(level3_ident_pgt)
|
||||
.quad phys_level2_ident_pgt | 0x007
|
||||
.fill 511,8,0
|
||||
|
||||
.org 0x3000
|
||||
ENTRY(level3_kernel_pgt)
|
||||
NEXT_PAGE(level3_kernel_pgt)
|
||||
.fill 510,8,0
|
||||
/* (2^48-(2*1024*1024*1024)-((2^39)*511))/(2^30) = 510 */
|
||||
.quad 0x0000000000005007 + __PHYSICAL_START /* -> level2_kernel_pgt */
|
||||
.quad phys_level2_kernel_pgt | 0x007
|
||||
.fill 1,8,0
|
||||
|
||||
.org 0x4000
|
||||
ENTRY(level2_ident_pgt)
|
||||
NEXT_PAGE(level2_ident_pgt)
|
||||
/* 40MB for bootup. */
|
||||
.quad 0x0000000000000083
|
||||
.quad 0x0000000000200083
|
||||
.quad 0x0000000000400083
|
||||
.quad 0x0000000000600083
|
||||
.quad 0x0000000000800083
|
||||
.quad 0x0000000000A00083
|
||||
.quad 0x0000000000C00083
|
||||
.quad 0x0000000000E00083
|
||||
.quad 0x0000000001000083
|
||||
.quad 0x0000000001200083
|
||||
.quad 0x0000000001400083
|
||||
.quad 0x0000000001600083
|
||||
.quad 0x0000000001800083
|
||||
.quad 0x0000000001A00083
|
||||
.quad 0x0000000001C00083
|
||||
.quad 0x0000000001E00083
|
||||
.quad 0x0000000002000083
|
||||
.quad 0x0000000002200083
|
||||
.quad 0x0000000002400083
|
||||
.quad 0x0000000002600083
|
||||
i = 0
|
||||
.rept 20
|
||||
.quad i << 21 | 0x083
|
||||
i = i + 1
|
||||
.endr
|
||||
/* Temporary mappings for the super early allocator in arch/x86_64/mm/init.c */
|
||||
.globl temp_boot_pmds
|
||||
temp_boot_pmds:
|
||||
.fill 492,8,0
|
||||
|
||||
.org 0x5000
|
||||
ENTRY(level2_kernel_pgt)
|
||||
NEXT_PAGE(level2_kernel_pgt)
|
||||
/* 40MB kernel mapping. The kernel code cannot be bigger than that.
|
||||
When you change this change KERNEL_TEXT_SIZE in page.h too. */
|
||||
/* (2^48-(2*1024*1024*1024)-((2^39)*511)-((2^30)*510)) = 0 */
|
||||
.quad 0x0000000000000183
|
||||
.quad 0x0000000000200183
|
||||
.quad 0x0000000000400183
|
||||
.quad 0x0000000000600183
|
||||
.quad 0x0000000000800183
|
||||
.quad 0x0000000000A00183
|
||||
.quad 0x0000000000C00183
|
||||
.quad 0x0000000000E00183
|
||||
.quad 0x0000000001000183
|
||||
.quad 0x0000000001200183
|
||||
.quad 0x0000000001400183
|
||||
.quad 0x0000000001600183
|
||||
.quad 0x0000000001800183
|
||||
.quad 0x0000000001A00183
|
||||
.quad 0x0000000001C00183
|
||||
.quad 0x0000000001E00183
|
||||
.quad 0x0000000002000183
|
||||
.quad 0x0000000002200183
|
||||
.quad 0x0000000002400183
|
||||
.quad 0x0000000002600183
|
||||
i = 0
|
||||
.rept 20
|
||||
.quad i << 21 | 0x183
|
||||
i = i + 1
|
||||
.endr
|
||||
/* Module mapping starts here */
|
||||
.fill 492,8,0
|
||||
|
||||
.org 0x6000
|
||||
ENTRY(empty_zero_page)
|
||||
NEXT_PAGE(empty_zero_page)
|
||||
|
||||
.org 0x7000
|
||||
ENTRY(empty_bad_page)
|
||||
NEXT_PAGE(level3_physmem_pgt)
|
||||
.quad phys_level2_kernel_pgt | 0x007 /* so that __va works even before pagetable_init */
|
||||
.fill 511,8,0
|
||||
|
||||
.org 0x8000
|
||||
ENTRY(empty_bad_pte_table)
|
||||
#undef NEXT_PAGE
|
||||
|
||||
.org 0x9000
|
||||
ENTRY(empty_bad_pmd_table)
|
||||
.data
|
||||
|
||||
.org 0xa000
|
||||
ENTRY(level3_physmem_pgt)
|
||||
.quad 0x0000000000005007 + __PHYSICAL_START /* -> level2_kernel_pgt (so that __va works even before pagetable_init) */
|
||||
|
||||
.org 0xb000
|
||||
#ifdef CONFIG_ACPI_SLEEP
|
||||
.align PAGE_SIZE
|
||||
ENTRY(wakeup_level4_pgt)
|
||||
.quad 0x0000000000002007 + __PHYSICAL_START /* -> level3_ident_pgt */
|
||||
.quad phys_level3_ident_pgt | 0x007
|
||||
.fill 255,8,0
|
||||
.quad 0x000000000000a007 + __PHYSICAL_START
|
||||
.quad phys_level3_physmem_pgt | 0x007
|
||||
.fill 254,8,0
|
||||
/* (2^48-(2*1024*1024*1024))/(2^39) = 511 */
|
||||
.quad 0x0000000000003007 + __PHYSICAL_START /* -> level3_kernel_pgt */
|
||||
.quad phys_level3_kernel_pgt | 0x007
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_HOTPLUG_CPU
|
||||
|
@ -352,12 +318,12 @@ ENTRY(wakeup_level4_pgt)
|
|||
*/
|
||||
.align PAGE_SIZE
|
||||
ENTRY(boot_level4_pgt)
|
||||
.quad 0x0000000000002007 + __PHYSICAL_START /* -> level3_ident_pgt */
|
||||
.quad phys_level3_ident_pgt | 0x007
|
||||
.fill 255,8,0
|
||||
.quad 0x000000000000a007 + __PHYSICAL_START
|
||||
.quad phys_level3_physmem_pgt | 0x007
|
||||
.fill 254,8,0
|
||||
/* (2^48-(2*1024*1024*1024))/(2^39) = 511 */
|
||||
.quad 0x0000000000003007 + __PHYSICAL_START /* -> level3_kernel_pgt */
|
||||
.quad phys_level3_kernel_pgt | 0x007
|
||||
|
||||
.data
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ struct desc_ptr idt_descr = { 256 * 16, (unsigned long) idt_table };
|
|||
char boot_cpu_stack[IRQSTACKSIZE] __attribute__((section(".bss.page_aligned")));
|
||||
|
||||
unsigned long __supported_pte_mask __read_mostly = ~0UL;
|
||||
static int do_not_nx __initdata = 0;
|
||||
static int do_not_nx __cpuinitdata = 0;
|
||||
|
||||
/* noexec=on|off
|
||||
Control non executable mappings for 64bit processes.
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
# Makefile for the linux x86_64-specific parts of the memory manager.
|
||||
#
|
||||
|
||||
obj-y := init.o fault.o ioremap.o extable.o pageattr.o
|
||||
obj-y := init.o fault.o ioremap.o extable.o pageattr.o mmap.o
|
||||
obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
|
||||
obj-$(CONFIG_NUMA) += numa.o
|
||||
obj-$(CONFIG_K8_NUMA) += k8topology.o
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
#include <linux/proc_fs.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/memory_hotplug.h>
|
||||
|
||||
#include <asm/processor.h>
|
||||
#include <asm/system.h>
|
||||
|
@ -180,13 +182,19 @@ static struct temp_map {
|
|||
{}
|
||||
};
|
||||
|
||||
static __init void *alloc_low_page(int *index, unsigned long *phys)
|
||||
static __meminit void *alloc_low_page(int *index, unsigned long *phys)
|
||||
{
|
||||
struct temp_map *ti;
|
||||
int i;
|
||||
unsigned long pfn = table_end++, paddr;
|
||||
void *adr;
|
||||
|
||||
if (after_bootmem) {
|
||||
adr = (void *)get_zeroed_page(GFP_ATOMIC);
|
||||
*phys = __pa(adr);
|
||||
return adr;
|
||||
}
|
||||
|
||||
if (pfn >= end_pfn)
|
||||
panic("alloc_low_page: ran out of memory");
|
||||
for (i = 0; temp_mappings[i].allocated; i++) {
|
||||
|
@ -199,55 +207,86 @@ static __init void *alloc_low_page(int *index, unsigned long *phys)
|
|||
ti->allocated = 1;
|
||||
__flush_tlb();
|
||||
adr = ti->address + ((pfn << PAGE_SHIFT) & ~PMD_MASK);
|
||||
memset(adr, 0, PAGE_SIZE);
|
||||
*index = i;
|
||||
*phys = pfn * PAGE_SIZE;
|
||||
return adr;
|
||||
}
|
||||
|
||||
static __init void unmap_low_page(int i)
|
||||
static __meminit void unmap_low_page(int i)
|
||||
{
|
||||
struct temp_map *ti = &temp_mappings[i];
|
||||
struct temp_map *ti;
|
||||
|
||||
if (after_bootmem)
|
||||
return;
|
||||
|
||||
ti = &temp_mappings[i];
|
||||
set_pmd(ti->pmd, __pmd(0));
|
||||
ti->allocated = 0;
|
||||
}
|
||||
|
||||
static void __init phys_pud_init(pud_t *pud, unsigned long address, unsigned long end)
|
||||
{
|
||||
long i, j;
|
||||
static void __meminit
|
||||
phys_pmd_init(pmd_t *pmd, unsigned long address, unsigned long end)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < PTRS_PER_PMD; pmd++, i++, address += PMD_SIZE) {
|
||||
unsigned long entry;
|
||||
|
||||
if (address > end) {
|
||||
for (; i < PTRS_PER_PMD; i++, pmd++)
|
||||
set_pmd(pmd, __pmd(0));
|
||||
break;
|
||||
}
|
||||
entry = _PAGE_NX|_PAGE_PSE|_KERNPG_TABLE|_PAGE_GLOBAL|address;
|
||||
entry &= __supported_pte_mask;
|
||||
set_pmd(pmd, __pmd(entry));
|
||||
}
|
||||
}
|
||||
|
||||
static void __meminit
|
||||
phys_pmd_update(pud_t *pud, unsigned long address, unsigned long end)
|
||||
{
|
||||
pmd_t *pmd = pmd_offset(pud, (unsigned long)__va(address));
|
||||
|
||||
if (pmd_none(*pmd)) {
|
||||
spin_lock(&init_mm.page_table_lock);
|
||||
phys_pmd_init(pmd, address, end);
|
||||
spin_unlock(&init_mm.page_table_lock);
|
||||
__flush_tlb_all();
|
||||
}
|
||||
}
|
||||
|
||||
static void __meminit phys_pud_init(pud_t *pud, unsigned long address, unsigned long end)
|
||||
{
|
||||
long i = pud_index(address);
|
||||
|
||||
i = pud_index(address);
|
||||
pud = pud + i;
|
||||
|
||||
if (after_bootmem && pud_val(*pud)) {
|
||||
phys_pmd_update(pud, address, end);
|
||||
return;
|
||||
}
|
||||
|
||||
for (; i < PTRS_PER_PUD; pud++, i++) {
|
||||
int map;
|
||||
unsigned long paddr, pmd_phys;
|
||||
pmd_t *pmd;
|
||||
|
||||
paddr = address + i*PUD_SIZE;
|
||||
if (paddr >= end) {
|
||||
for (; i < PTRS_PER_PUD; i++, pud++)
|
||||
set_pud(pud, __pud(0));
|
||||
paddr = (address & PGDIR_MASK) + i*PUD_SIZE;
|
||||
if (paddr >= end)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!e820_mapped(paddr, paddr+PUD_SIZE, 0)) {
|
||||
if (!after_bootmem && !e820_mapped(paddr, paddr+PUD_SIZE, 0)) {
|
||||
set_pud(pud, __pud(0));
|
||||
continue;
|
||||
}
|
||||
|
||||
pmd = alloc_low_page(&map, &pmd_phys);
|
||||
spin_lock(&init_mm.page_table_lock);
|
||||
set_pud(pud, __pud(pmd_phys | _KERNPG_TABLE));
|
||||
for (j = 0; j < PTRS_PER_PMD; pmd++, j++, paddr += PMD_SIZE) {
|
||||
unsigned long pe;
|
||||
|
||||
if (paddr >= end) {
|
||||
for (; j < PTRS_PER_PMD; j++, pmd++)
|
||||
set_pmd(pmd, __pmd(0));
|
||||
break;
|
||||
}
|
||||
pe = _PAGE_NX|_PAGE_PSE | _KERNPG_TABLE | _PAGE_GLOBAL | paddr;
|
||||
pe &= __supported_pte_mask;
|
||||
set_pmd(pmd, __pmd(pe));
|
||||
}
|
||||
phys_pmd_init(pmd, paddr, end);
|
||||
spin_unlock(&init_mm.page_table_lock);
|
||||
unmap_low_page(map);
|
||||
}
|
||||
__flush_tlb();
|
||||
|
@ -262,30 +301,25 @@ static void __init find_early_table_space(unsigned long end)
|
|||
tables = round_up(puds * sizeof(pud_t), PAGE_SIZE) +
|
||||
round_up(pmds * sizeof(pmd_t), PAGE_SIZE);
|
||||
|
||||
/* Put page tables beyond the DMA zones if possible.
|
||||
RED-PEN might be better to spread them out more over
|
||||
memory to avoid hotspots */
|
||||
if (end > MAX_DMA32_PFN<<PAGE_SHIFT)
|
||||
start = MAX_DMA32_PFN << PAGE_SHIFT;
|
||||
else if (end > MAX_DMA_PFN << PAGE_SHIFT)
|
||||
start = MAX_DMA_PFN << PAGE_SHIFT;
|
||||
else
|
||||
start = 0x8000;
|
||||
|
||||
table_start = find_e820_area(start, end, tables);
|
||||
if (table_start == -1)
|
||||
table_start = find_e820_area(0x8000, end, tables);
|
||||
/* RED-PEN putting page tables only on node 0 could
|
||||
cause a hotspot and fill up ZONE_DMA. The page tables
|
||||
need roughly 0.5KB per GB. */
|
||||
start = 0x8000;
|
||||
table_start = find_e820_area(start, end, tables);
|
||||
if (table_start == -1UL)
|
||||
panic("Cannot find space for the kernel page tables");
|
||||
|
||||
table_start >>= PAGE_SHIFT;
|
||||
table_end = table_start;
|
||||
|
||||
early_printk("kernel direct mapping tables up to %lx @ %lx-%lx\n",
|
||||
end, table_start << PAGE_SHIFT, table_end << PAGE_SHIFT);
|
||||
}
|
||||
|
||||
/* Setup the direct mapping of the physical memory at PAGE_OFFSET.
|
||||
This runs before bootmem is initialized and gets pages directly from the
|
||||
physical memory. To access them they are temporarily mapped. */
|
||||
void __init init_memory_mapping(unsigned long start, unsigned long end)
|
||||
void __meminit init_memory_mapping(unsigned long start, unsigned long end)
|
||||
{
|
||||
unsigned long next;
|
||||
|
||||
|
@ -297,7 +331,8 @@ void __init init_memory_mapping(unsigned long start, unsigned long end)
|
|||
* mapped. Unfortunately this is done currently before the nodes are
|
||||
* discovered.
|
||||
*/
|
||||
find_early_table_space(end);
|
||||
if (!after_bootmem)
|
||||
find_early_table_space(end);
|
||||
|
||||
start = (unsigned long)__va(start);
|
||||
end = (unsigned long)__va(end);
|
||||
|
@ -305,20 +340,26 @@ void __init init_memory_mapping(unsigned long start, unsigned long end)
|
|||
for (; start < end; start = next) {
|
||||
int map;
|
||||
unsigned long pud_phys;
|
||||
pud_t *pud = alloc_low_page(&map, &pud_phys);
|
||||
pgd_t *pgd = pgd_offset_k(start);
|
||||
pud_t *pud;
|
||||
|
||||
if (after_bootmem)
|
||||
pud = pud_offset_k(pgd, __PAGE_OFFSET);
|
||||
else
|
||||
pud = alloc_low_page(&map, &pud_phys);
|
||||
|
||||
next = start + PGDIR_SIZE;
|
||||
if (next > end)
|
||||
next = end;
|
||||
phys_pud_init(pud, __pa(start), __pa(next));
|
||||
set_pgd(pgd_offset_k(start), mk_kernel_pgd(pud_phys));
|
||||
if (!after_bootmem)
|
||||
set_pgd(pgd_offset_k(start), mk_kernel_pgd(pud_phys));
|
||||
unmap_low_page(map);
|
||||
}
|
||||
|
||||
asm volatile("movq %%cr4,%0" : "=r" (mmu_cr4_features));
|
||||
if (!after_bootmem)
|
||||
asm volatile("movq %%cr4,%0" : "=r" (mmu_cr4_features));
|
||||
__flush_tlb_all();
|
||||
early_printk("kernel direct mapping tables upto %lx @ %lx-%lx\n", end,
|
||||
table_start<<PAGE_SHIFT,
|
||||
table_end<<PAGE_SHIFT);
|
||||
}
|
||||
|
||||
void __cpuinit zap_low_mappings(int cpu)
|
||||
|
@ -393,6 +434,9 @@ size_zones(unsigned long *z, unsigned long *h,
|
|||
void __init paging_init(void)
|
||||
{
|
||||
unsigned long zones[MAX_NR_ZONES], holes[MAX_NR_ZONES];
|
||||
|
||||
memory_present(0, 0, end_pfn);
|
||||
sparse_init();
|
||||
size_zones(zones, holes, 0, end_pfn);
|
||||
free_area_init_node(0, NODE_DATA(0), zones,
|
||||
__pa(PAGE_OFFSET) >> PAGE_SHIFT, holes);
|
||||
|
@ -433,6 +477,50 @@ void __init clear_kernel_mapping(unsigned long address, unsigned long size)
|
|||
__flush_tlb_all();
|
||||
}
|
||||
|
||||
/*
|
||||
* Memory hotplug specific functions
|
||||
* These are only for non-NUMA machines right now.
|
||||
*/
|
||||
#ifdef CONFIG_MEMORY_HOTPLUG
|
||||
|
||||
void online_page(struct page *page)
|
||||
{
|
||||
ClearPageReserved(page);
|
||||
set_page_count(page, 1);
|
||||
__free_page(page);
|
||||
totalram_pages++;
|
||||
num_physpages++;
|
||||
}
|
||||
|
||||
int add_memory(u64 start, u64 size)
|
||||
{
|
||||
struct pglist_data *pgdat = NODE_DATA(0);
|
||||
struct zone *zone = pgdat->node_zones + MAX_NR_ZONES-2;
|
||||
unsigned long start_pfn = start >> PAGE_SHIFT;
|
||||
unsigned long nr_pages = size >> PAGE_SHIFT;
|
||||
int ret;
|
||||
|
||||
ret = __add_pages(zone, start_pfn, nr_pages);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
init_memory_mapping(start, (start + size -1));
|
||||
|
||||
return ret;
|
||||
error:
|
||||
printk("%s: Problem encountered in __add_pages!\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(add_memory);
|
||||
|
||||
int remove_memory(u64 start, u64 size)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(remove_memory);
|
||||
|
||||
#endif
|
||||
|
||||
static struct kcore_list kcore_mem, kcore_vmalloc, kcore_kernel, kcore_modules,
|
||||
kcore_vsyscall;
|
||||
|
||||
|
@ -539,7 +627,7 @@ void mark_rodata_ro(void)
|
|||
#ifdef CONFIG_BLK_DEV_INITRD
|
||||
void free_initrd_mem(unsigned long start, unsigned long end)
|
||||
{
|
||||
if (start < (unsigned long)&_end)
|
||||
if (start >= end)
|
||||
return;
|
||||
printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
|
||||
for (; start < end; start += PAGE_SIZE) {
|
||||
|
|
30
arch/x86_64/mm/mmap.c
Normal file
30
arch/x86_64/mm/mmap.c
Normal file
|
@ -0,0 +1,30 @@
|
|||
/* Copyright 2005 Andi Kleen, SuSE Labs.
|
||||
* Licensed under GPL, v.2
|
||||
*/
|
||||
#include <linux/config.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/random.h>
|
||||
#include <asm/ia32.h>
|
||||
|
||||
/* Notebook: move the mmap code from sys_x86_64.c over here. */
|
||||
|
||||
void arch_pick_mmap_layout(struct mm_struct *mm)
|
||||
{
|
||||
#ifdef CONFIG_IA32_EMULATION
|
||||
if (current_thread_info()->flags & _TIF_IA32)
|
||||
return ia32_pick_mmap_layout(mm);
|
||||
#endif
|
||||
mm->mmap_base = TASK_UNMAPPED_BASE;
|
||||
if (current->flags & PF_RANDOMIZE) {
|
||||
/* Add 28bit randomness which is about 40bits of address space
|
||||
because mmap base has to be page aligned.
|
||||
or ~1/128 of the total user VM
|
||||
(total user address space is 47bits) */
|
||||
unsigned rnd = get_random_int() & 0xfffffff;
|
||||
mm->mmap_base += ((unsigned long)rnd) << PAGE_SHIFT;
|
||||
}
|
||||
mm->get_unmapped_area = arch_get_unmapped_area;
|
||||
mm->unmap_area = arch_unmap_area;
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue