Revert r336773: it removed too much.

r336773 removed all things xscale. However, some things xscale are
really armv5. Revert that entirely. A more modest removal will follow.

Noticed by: andrew@
This commit is contained in:
imp 2018-07-27 21:25:01 +00:00
parent 1323c481fa
commit de47afa9bf
77 changed files with 13066 additions and 14 deletions

View File

@ -2,4 +2,8 @@
#include <machine/asm.h>
__FBSDID("$FreeBSD$");
#if !defined(_ARM_ARCH_5E) || defined(_STANDALONE)
#include "memcpy_arm.S"
#else
#include "memcpy_xscale.S"
#endif

File diff suppressed because it is too large Load Diff

View File

@ -75,6 +75,7 @@ MAN+= pmc.tsc.3
MAN+= pmc.ucf.3
MAN+= pmc.westmere.3
MAN+= pmc.westmereuc.3
MAN+= pmc.xscale.3
MLINKS+= \
pmc_allocate.3 pmc_release.3 \

View File

@ -59,6 +59,10 @@ static int tsc_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
struct pmc_op_pmcallocate *_pmc_config);
#endif
#if defined(__arm__)
#if defined(__XSCALE__)
static int xscale_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
struct pmc_op_pmcallocate *_pmc_config);
#endif
static int armv7_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
struct pmc_op_pmcallocate *_pmc_config);
#endif
@ -136,6 +140,7 @@ struct pmc_class_descr {
PMC_CLASSDEP_TABLE(iaf, IAF);
PMC_CLASSDEP_TABLE(k8, K8);
PMC_CLASSDEP_TABLE(xscale, XSCALE);
PMC_CLASSDEP_TABLE(armv7, ARMV7);
PMC_CLASSDEP_TABLE(armv8, ARMV8);
PMC_CLASSDEP_TABLE(mips24k, MIPS24K);
@ -181,6 +186,7 @@ static const struct pmc_event_descr cortex_a57_event_table[] =
}
PMC_MDEP_TABLE(k8, K8, PMC_CLASS_SOFT, PMC_CLASS_TSC);
PMC_MDEP_TABLE(xscale, XSCALE, PMC_CLASS_SOFT, PMC_CLASS_XSCALE);
PMC_MDEP_TABLE(cortex_a8, ARMV7, PMC_CLASS_SOFT, PMC_CLASS_ARMV7);
PMC_MDEP_TABLE(cortex_a9, ARMV7, PMC_CLASS_SOFT, PMC_CLASS_ARMV7);
PMC_MDEP_TABLE(cortex_a53, ARMV8, PMC_CLASS_SOFT, PMC_CLASS_ARMV8);
@ -218,6 +224,9 @@ PMC_CLASS_TABLE_DESC(k8, K8, k8, k8);
PMC_CLASS_TABLE_DESC(tsc, TSC, tsc, tsc);
#endif
#if defined(__arm__)
#if defined(__XSCALE__)
PMC_CLASS_TABLE_DESC(xscale, XSCALE, xscale, xscale);
#endif
PMC_CLASS_TABLE_DESC(cortex_a8, ARMV7, cortex_a8, armv7);
PMC_CLASS_TABLE_DESC(cortex_a9, ARMV7, cortex_a9, armv7);
#endif
@ -748,6 +757,28 @@ soft_allocate_pmc(enum pmc_event pe, char *ctrspec,
}
#if defined(__arm__)
#if defined(__XSCALE__)
static struct pmc_event_alias xscale_aliases[] = {
EV_ALIAS("branches", "BRANCH_RETIRED"),
EV_ALIAS("branch-mispredicts", "BRANCH_MISPRED"),
EV_ALIAS("dc-misses", "DC_MISS"),
EV_ALIAS("ic-misses", "IC_MISS"),
EV_ALIAS("instructions", "INSTR_RETIRED"),
EV_ALIAS(NULL, NULL)
};
static int
xscale_allocate_pmc(enum pmc_event pe, char *ctrspec __unused,
struct pmc_op_pmcallocate *pmc_config __unused)
{
switch (pe) {
default:
break;
}
return (0);
}
#endif
static struct pmc_event_alias cortex_a8_aliases[] = {
EV_ALIAS("dc-misses", "L1_DCACHE_REFILL"),
@ -1206,6 +1237,10 @@ pmc_event_names_of_class(enum pmc_class cl, const char ***eventnames,
ev = k8_event_table;
count = PMC_EVENT_TABLE_SIZE(k8);
break;
case PMC_CLASS_XSCALE:
ev = xscale_event_table;
count = PMC_EVENT_TABLE_SIZE(xscale);
break;
case PMC_CLASS_ARMV7:
switch (cpu_info.pm_cputype) {
default:
@ -1447,6 +1482,12 @@ pmc_init(void)
PMC_MDEP_INIT(generic);
break;
#if defined(__arm__)
#if defined(__XSCALE__)
case PMC_CPU_INTEL_XSCALE:
PMC_MDEP_INIT(xscale);
pmc_class_table[n] = &xscale_class_table_descr;
break;
#endif
case PMC_CPU_ARMV7_CORTEX_A8:
PMC_MDEP_INIT(cortex_a8);
pmc_class_table[n] = &cortex_a8_class_table_descr;
@ -1575,6 +1616,9 @@ _pmc_name_of_event(enum pmc_event pe, enum pmc_cputype cpu)
if (pe >= PMC_EV_K8_FIRST && pe <= PMC_EV_K8_LAST) {
ev = k8_event_table;
evfence = k8_event_table + PMC_EVENT_TABLE_SIZE(k8);
} else if (pe >= PMC_EV_XSCALE_FIRST && pe <= PMC_EV_XSCALE_LAST) {
ev = xscale_event_table;
evfence = xscale_event_table + PMC_EVENT_TABLE_SIZE(xscale);
} else if (pe >= PMC_EV_ARMV7_FIRST && pe <= PMC_EV_ARMV7_LAST) {
switch (cpu) {
case PMC_CPU_ARMV7_CORTEX_A8:

View File

@ -545,6 +545,7 @@ API is
.Xr pmc.tsc 3 ,
.Xr pmc.westmere 3 ,
.Xr pmc.westmereuc 3 ,
.Xr pmc.xscale 3 ,
.Xr pmc_allocate 3 ,
.Xr pmc_attach 3 ,
.Xr pmc_capabilities 3 ,

156
lib/libpmc/pmc.xscale.3 Normal file
View File

@ -0,0 +1,156 @@
.\" Copyright (c) 2009, 2010 Rui Paulo. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD$
.\"
.Dd December 23, 2009
.Dt PMC.XSCALE 3
.Os
.Sh NAME
.Nm pmc.xscale
.Nd measurement events for
.Tn Intel
.Tn XScale
family CPUs
.Sh LIBRARY
.Lb libpmc
.Sh SYNOPSIS
.In pmc.h
.Sh DESCRIPTION
.Tn Intel XScale
CPUs are ARM CPUs based on the ARMv5e core.
.Pp
Second generation cores have 2 counters, while third generation cores
have 4 counters.
Third generation cores also have an increased number of PMC events.
.Pp
.Tn Intel XScale
PMCs are documented in
.Rs
.%B "3rd Generation Intel XScale Microarchitecture Developer's Manual"
.%D May 2007
.Re
.Ss Event Specifiers (Programmable PMCs)
.Tn Intel XScale
programmable PMCs support the following events:
.Bl -tag -width indent
.It Li IC_FETCH
External memory fetch due to L1 instruction cache miss.
.It Li IC_MISS
Instruction cache or TLB miss.
.It Li DATA_DEPENDENCY_STALLED
A data dependency stalled
.It Li ITLB_MISS
Instruction TLB miss.
.It Li DTLB_MISS
Data TLB miss.
.It Li BRANCH_RETIRED
Branch instruction retired (executed).
.It Li BRANCH_MISPRED
Branch mispredicted.
.It Li INSTR_RETIRED
Instructions retired (executed).
.It Li DC_FULL_CYCLE
L1 data cache buffer full stall.
Event occurs on every cycle the
condition is present.
.It Li DC_FULL_CONTIG
L1 data cache buffer full stall.
Event occurs once for each contiguous sequence of this type of stall.
.It Li DC_ACCESS
L1 data cache access, not including cache operations.
.It Li DC_MISS
L1 data cache miss, not including cache operations.
.It Li DC_WRITEBACK
L1 data cache write-back.
Occurs for each cache line that's written back from the cache.
.It Li PC_CHANGE
Software changed the program counter.
.It Li BRANCH_RETIRED_ALL
Branch instruction retired (executed).
This event counts all branch instructions, indirect or direct.
.It Li INSTR_CYCLE
Count the number of microarchitecture cycles each instruction requires
to issue.
.It Li CP_STALL
Coprocessor stalled the instruction pipeline.
.It Li PC_CHANGE_ALL
Software changed the program counter (includes exceptions).
.It Li PIPELINE_FLUSH
Pipeline flushes due to mispredictions or exceptions.
.It Li BACKEND_STALL
Backend stalled the instruction pipeline.
.It Li MULTIPLIER_USE
Multiplier used.
.It Li MULTIPLIER_STALLED
Multiplier stalled the instruction pipeline.
.It Li DATA_CACHE_STALLED
Data cache stalled the instruction pipeline.
.It Li L2_CACHE_REQ
L2 cache request, not including cache operations.
.It Li L2_CACHE_MISS
L2 cache miss, not including cache operations.
.It Li ADDRESS_BUS_TRANS
Address bus transaction.
.It Li SELF_ADDRESS_BUS_TRANS
Self initiated address bus transaction.
.It Li DATA_BUS_TRANS
Data bus transaction.
.El
.Ss Event Name Aliases
The following table shows the mapping between the PMC-independent
aliases supported by
.Lb libpmc
and the underlying hardware events used.
.Bl -column "branch-mispredicts" "BRANCH_MISPRED"
.It Em Alias Ta Em Event
.It Li branches Ta Li BRANCH_RETIRED
.It Li branch-mispredicts Ta Li BRANCH_MISPRED
.It Li dc-misses Ta Li DC_MISS
.It Li ic-misses Ta Li IC_MISS
.It Li instructions Ta Li INSTR_RETIRED
.El
.Sh SEE ALSO
.Xr pmc 3 ,
.Xr pmc.soft 3 ,
.Xr pmc_cpuinfo 3 ,
.Xr pmclog 3 ,
.Xr hwpmc 4
.Sh HISTORY
The
.Nm pmc
library first appeared in
.Fx 6.0 .
Intel XScale support first appeared in
.Fx 9.0 .
.Sh AUTHORS
.An -nosplit
The
.Lb libpmc
library was written by
.An Joseph Koshy Aq Mt jkoshy@FreeBSD.org .
.Pp
Intel XScale support was added by
.An Rui Paulo Aq Mt rpaulo@FreeBSD.org .
.Sh CAVEATS
The Intel XScale code does not yet support sampling.

View File

@ -16,6 +16,7 @@ MAN= \
imx6_snvs.4 \
imx_wdog.4 \
mge.4 \
npe.4 \
ti_adc.4
MLINKS= cgem.4 if_cgem.4

View File

@ -0,0 +1,163 @@
.\"
.\" Copyright (c) 2006 Sam Leffler, Errno Consulting
.\"
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR
.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
.\" IN NO EVENT SHALL THE DEVELOPERS BE LIABLE FOR ANY DIRECT, INDIRECT,
.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\" $FreeBSD$
.\"
.Dd December 4, 2006
.Dt NPE 4 arm
.Os
.Sh NAME
.Nm npe
.Nd "Intel XScale Network Processing Engine (NPE) Ethernet device driver"
.Sh SYNOPSIS
To compile this driver into the kernel,
place the following lines in your
kernel configuration file:
.Bd -ragged -offset indent
.Cd "device npe"
.Cd "device npe_fw"
.Cd "device firmware"
.Cd "device qmgr"
.Cd "device miibus"
.Ed
.Sh DESCRIPTION
The
.Nm
driver provides support for Ethernet adapters based on the Intel
XScale Network Processing Engine (NPE).
The NPE must be loaded with firmware that is typically distributed
with boards that have this part.
Otherwise the firmware may be obtained at no cost from the Intel web site.
.Pp
The
.Nm
driver supports the following media types:
.Bl -tag -width ".Cm full-duplex"
.It Cm autoselect
Enable autoselection of the media type and options.
.It Cm 10baseT/UTP
Set 10Mbps operation.
.It Cm 100baseTX
Set 100Mbps (Fast Ethernet) operation.
.El
.Pp
The
.Nm
driver supports the following media options:
.Bl -tag -width ".Cm full-duplex"
.It Cm full-duplex
Set full duplex operation.
.El
.Pp
The
.Nm
driver supports polled operation when the system is
configured with device polling support,
.Xr polling 4 .
Note that for multi-port configurations polling and interrupt-style
operation should not be combined as one of the hardware queues
is shared by all ports.
.Pp
For further information on configuring this device, see
.Xr ifconfig 8 .
.\".Pp
.\"The
.\".Nm
.\"driver supports reception and transmission of extended frames
.\"for
.\".Xr vlan 4 .
.\"This capability of
.\".Nm
.\"can be controlled by means of the
.\".Cm vlanmtu
.\"parameter
.\"to
.\".Xr ifconfig 8 .
.Sh HARDWARE
The adapters supported by the
.Nm
driver exist only on boards that have an XScale processor.
.Sh DIAGNOSTICS
.Bl -diag
.It "npe%d: unit %d not supported"
The unit is larger than the maximum number built into the driver.
This should not happen as
.Nm
devices are not really probed for; they are statically enumerated.
.It "npe%d: Cannot find my PHY."
The associated PHY did not appear while probing the MII bus.
The relationship between PHYs and NPEs is statically defined
in the driver and may require alterations to the driver for new boards.
.It "npe%d: unable to allocate memory for %s ... buffers"
There is not enough memory available for allocation.
The driver pre-allocated memory during attach so this should not happen.
.It "npe%d: remember to fix rx q setup"
See
.Sx BUGS
below.
.It "npe%d: free mbuf at entry %u"
An mbuf was unexpectedly found on the device queue; the index of
the queue entry is printed.
.It "npe%d: too many fragments %u"
A frame was dropped on transmit because it was too fragmented and
the logic to de-fragment failed.
This should not happen.
.It "npe%d: device timeout"
The device has stopped responding to the network, or there is a problem with
the network connection (cable).
.El
.Pp
Other diagnostics exist and are not listed here;
they should be self-explanatory.
.Sh SEE ALSO
.Xr altq 4 ,
.Xr arp 4 ,
.Xr miibus 4 ,
.Xr netintro 4 ,
.Xr polling 4 ,
.Xr qmgr 4 ,
.\".Xr vlan 4 ,
.Xr ifconfig 8
.Sh HISTORY
The
.Nm
device driver first appeared in
.Fx 6.3 .
.Sh CAVEATS
This driver has been tested only with dual-port boards using the IXP425
such as the Gateworks Avila 2348.
Some changes to the driver may be required for other configurations.
.Sh BUGS
The hardware queues are not properly flushed when the interface
is marked down.
.Pp
The assignment of receive traffic classes to hardware queues
is presently incomplete.
Only the first 4 classes are assigned while there are 8 total.
The driver will print
.Dq Li "remember to fix rx q setup"
on startup as a reminder.
For the moment it is not a problem as all traffic arrives classified
with class 0.

View File

@ -104,7 +104,11 @@ _CPUCFLAGS = -march=${CPUTYPE}
. elif ${MACHINE_CPUARCH} == "amd64"
_CPUCFLAGS = -march=${CPUTYPE}
. elif ${MACHINE_CPUARCH} == "arm"
. if ${CPUTYPE:M*soft*} != ""
. if ${CPUTYPE} == "xscale"
#XXX: gcc doesn't seem to like -mcpu=xscale, and dies while rebuilding itself
#_CPUCFLAGS = -mcpu=xscale
_CPUCFLAGS = -march=armv5te -D__XSCALE__
. elif ${CPUTYPE:M*soft*} != ""
_CPUCFLAGS = -mfloat-abi=softfp
. elif ${CPUTYPE} == "cortexa"
_CPUCFLAGS = -march=armv7 -mfpu=vfp

View File

@ -47,6 +47,9 @@
.word _C_LABEL(_min_memcpy_size)
__FBSDID("$FreeBSD$");
#ifdef _ARM_ARCH_5E
#include <arm/arm/bcopyinout_xscale.S>
#else
.text
.align 2
@ -556,6 +559,7 @@ ENTRY(copyout)
RET
END(copyout)
#endif
/*
* int badaddr_read_1(const uint8_t *src, uint8_t *dest)

View File

@ -0,0 +1,958 @@
/* $NetBSD: bcopyinout_xscale.S,v 1.3 2003/12/15 09:27:18 scw Exp $ */
/*-
* Copyright 2003 Wasabi Systems, Inc.
* All rights reserved.
*
* Written by Steve C. Woodford for Wasabi Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed for the NetBSD Project by
* Wasabi Systems, Inc.
* 4. The name of Wasabi Systems, Inc. may not be used to endorse
* or promote products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <machine/asm.h>
__FBSDID("$FreeBSD$");
.syntax unified
.text
.align 2
#if __ARM_ARCH >= 6
#define GET_PCB(tmp) \
mrc p15, 0, tmp, c13, c0, 4; \
add tmp, tmp, #(TD_PCB)
#else
.Lcurpcb:
.word _C_LABEL(__pcpu) + PC_CURPCB
#define GET_PCB(tmp) \
ldr tmp, .Lcurpcb
#endif
/*
* r0 = user space address
* r1 = kernel space address
* r2 = length
*
* Copies bytes from user space to kernel space
*/
ENTRY(copyin)
cmp r2, #0x00
movle r0, #0x00
movle pc, lr /* Bail early if length is <= 0 */
adds r3, r0, r2
movcs r0, #EFAULT
RETc(cs)
ldr r12, =(VM_MAXUSER_ADDRESS + 1)
cmp r3, r12
movcs r0, #EFAULT
RETc(cs)
ldr r3, .L_arm_memcpy
ldr r3, [r3]
cmp r3, #0
beq .Lnormal
ldr r3, .L_min_memcpy_size
ldr r3, [r3]
cmp r2, r3
blt .Lnormal
stmfd sp!, {r0-r2, r4, lr}
mov r3, r0
mov r0, r1
mov r1, r3
mov r3, #2 /* SRC_IS_USER */
ldr r4, .L_arm_memcpy
mov lr, pc
ldr pc, [r4]
cmp r0, #0
ldmfd sp!, {r0-r2, r4, lr}
moveq r0, #0
RETeq
.Lnormal:
stmfd sp!, {r10-r11, lr}
GET_PCB(r10)
ldr r10, [r10]
mov r3, #0x00
adr ip, .Lcopyin_fault
ldr r11, [r10, #PCB_ONFAULT]
str ip, [r10, #PCB_ONFAULT]
bl .Lcopyin_guts
str r11, [r10, #PCB_ONFAULT]
mov r0, #0x00
ldmfd sp!, {r10-r11, pc}
.Lcopyin_fault:
ldr r0, =EFAULT
str r11, [r10, #PCB_ONFAULT]
cmp r3, #0x00
ldmfdgt sp!, {r4-r7} /* r3 > 0 Restore r4-r7 */
ldmfdlt sp!, {r4-r9} /* r3 < 0 Restore r4-r9 */
ldmfd sp!, {r10-r11, pc}
.Lcopyin_guts:
pld [r0]
/* Word-align the destination buffer */
ands ip, r1, #0x03 /* Already word aligned? */
beq .Lcopyin_wordaligned /* Yup */
rsb ip, ip, #0x04
cmp r2, ip /* Enough bytes left to align it? */
blt .Lcopyin_l4_2 /* Nope. Just copy bytewise */
sub r2, r2, ip
rsbs ip, ip, #0x03
addne pc, pc, ip, lsl #3
nop
ldrbt ip, [r0], #0x01
strb ip, [r1], #0x01
ldrbt ip, [r0], #0x01
strb ip, [r1], #0x01
ldrbt ip, [r0], #0x01
strb ip, [r1], #0x01
cmp r2, #0x00 /* All done? */
RETeq
/* Destination buffer is now word aligned */
.Lcopyin_wordaligned:
ands ip, r0, #0x03 /* Is src also word-aligned? */
bne .Lcopyin_bad_align /* Nope. Things just got bad */
cmp r2, #0x08 /* Less than 8 bytes remaining? */
blt .Lcopyin_w_less_than8
/* Quad-align the destination buffer */
tst r1, #0x07 /* Already quad aligned? */
ldrtne ip, [r0], #0x04
strne ip, [r1], #0x04
subne r2, r2, #0x04
stmfd sp!, {r4-r9} /* Free up some registers */
mov r3, #-1 /* Signal restore r4-r9 */
/* Destination buffer quad aligned, source is word aligned */
subs r2, r2, #0x80
blt .Lcopyin_w_lessthan128
/* Copy 128 bytes at a time */
.Lcopyin_w_loop128:
ldrt r4, [r0], #0x04 /* LD:00-03 */
ldrt r5, [r0], #0x04 /* LD:04-07 */
pld [r0, #0x18] /* Prefetch 0x20 */
ldrt r6, [r0], #0x04 /* LD:08-0b */
ldrt r7, [r0], #0x04 /* LD:0c-0f */
ldrt r8, [r0], #0x04 /* LD:10-13 */
ldrt r9, [r0], #0x04 /* LD:14-17 */
strd r4, [r1], #0x08 /* ST:00-07 */
ldrt r4, [r0], #0x04 /* LD:18-1b */
ldrt r5, [r0], #0x04 /* LD:1c-1f */
strd r6, [r1], #0x08 /* ST:08-0f */
ldrt r6, [r0], #0x04 /* LD:20-23 */
ldrt r7, [r0], #0x04 /* LD:24-27 */
pld [r0, #0x18] /* Prefetch 0x40 */
strd r8, [r1], #0x08 /* ST:10-17 */
ldrt r8, [r0], #0x04 /* LD:28-2b */
ldrt r9, [r0], #0x04 /* LD:2c-2f */
strd r4, [r1], #0x08 /* ST:18-1f */
ldrt r4, [r0], #0x04 /* LD:30-33 */
ldrt r5, [r0], #0x04 /* LD:34-37 */
strd r6, [r1], #0x08 /* ST:20-27 */
ldrt r6, [r0], #0x04 /* LD:38-3b */
ldrt r7, [r0], #0x04 /* LD:3c-3f */
strd r8, [r1], #0x08 /* ST:28-2f */
ldrt r8, [r0], #0x04 /* LD:40-43 */
ldrt r9, [r0], #0x04 /* LD:44-47 */
pld [r0, #0x18] /* Prefetch 0x60 */
strd r4, [r1], #0x08 /* ST:30-37 */
ldrt r4, [r0], #0x04 /* LD:48-4b */
ldrt r5, [r0], #0x04 /* LD:4c-4f */
strd r6, [r1], #0x08 /* ST:38-3f */
ldrt r6, [r0], #0x04 /* LD:50-53 */
ldrt r7, [r0], #0x04 /* LD:54-57 */
strd r8, [r1], #0x08 /* ST:40-47 */
ldrt r8, [r0], #0x04 /* LD:58-5b */
ldrt r9, [r0], #0x04 /* LD:5c-5f */
strd r4, [r1], #0x08 /* ST:48-4f */
ldrt r4, [r0], #0x04 /* LD:60-63 */
ldrt r5, [r0], #0x04 /* LD:64-67 */
pld [r0, #0x18] /* Prefetch 0x80 */
strd r6, [r1], #0x08 /* ST:50-57 */
ldrt r6, [r0], #0x04 /* LD:68-6b */
ldrt r7, [r0], #0x04 /* LD:6c-6f */
strd r8, [r1], #0x08 /* ST:58-5f */
ldrt r8, [r0], #0x04 /* LD:70-73 */
ldrt r9, [r0], #0x04 /* LD:74-77 */
strd r4, [r1], #0x08 /* ST:60-67 */
ldrt r4, [r0], #0x04 /* LD:78-7b */
ldrt r5, [r0], #0x04 /* LD:7c-7f */
strd r6, [r1], #0x08 /* ST:68-6f */
strd r8, [r1], #0x08 /* ST:70-77 */
subs r2, r2, #0x80
strd r4, [r1], #0x08 /* ST:78-7f */
bge .Lcopyin_w_loop128
.Lcopyin_w_lessthan128:
adds r2, r2, #0x80 /* Adjust for extra sub */
ldmfdeq sp!, {r4-r9}
RETeq
subs r2, r2, #0x20
blt .Lcopyin_w_lessthan32
/* Copy 32 bytes at a time */
.Lcopyin_w_loop32:
ldrt r4, [r0], #0x04
ldrt r5, [r0], #0x04
pld [r0, #0x18]
ldrt r6, [r0], #0x04
ldrt r7, [r0], #0x04
ldrt r8, [r0], #0x04
ldrt r9, [r0], #0x04
strd r4, [r1], #0x08
ldrt r4, [r0], #0x04
ldrt r5, [r0], #0x04
strd r6, [r1], #0x08
strd r8, [r1], #0x08
subs r2, r2, #0x20
strd r4, [r1], #0x08
bge .Lcopyin_w_loop32
.Lcopyin_w_lessthan32:
adds r2, r2, #0x20 /* Adjust for extra sub */
ldmfdeq sp!, {r4-r9}
RETeq /* Return now if done */
and r4, r2, #0x18
rsb r5, r4, #0x18
subs r2, r2, r4
add pc, pc, r5, lsl #1
nop
/* At least 24 bytes remaining */
ldrt r4, [r0], #0x04
ldrt r5, [r0], #0x04
nop
strd r4, [r1], #0x08
/* At least 16 bytes remaining */
ldrt r4, [r0], #0x04
ldrt r5, [r0], #0x04
nop
strd r4, [r1], #0x08
/* At least 8 bytes remaining */
ldrt r4, [r0], #0x04
ldrt r5, [r0], #0x04
nop
strd r4, [r1], #0x08
/* Less than 8 bytes remaining */
ldmfd sp!, {r4-r9}
RETeq /* Return now if done */
mov r3, #0x00
.Lcopyin_w_less_than8:
subs r2, r2, #0x04
ldrtge ip, [r0], #0x04
strge ip, [r1], #0x04
RETeq /* Return now if done */
addlt r2, r2, #0x04
ldrbt ip, [r0], #0x01
cmp r2, #0x02
ldrbtge r2, [r0], #0x01
strb ip, [r1], #0x01
ldrbtgt ip, [r0]
strbge r2, [r1], #0x01
strbgt ip, [r1]
RET
/*
* At this point, it has not been possible to word align both buffers.
* The destination buffer (r1) is word aligned, but the source buffer
* (r0) is not.
*/
.Lcopyin_bad_align:
stmfd sp!, {r4-r7}
mov r3, #0x01
bic r0, r0, #0x03
cmp ip, #2
ldrt ip, [r0], #0x04
bgt .Lcopyin_bad3
beq .Lcopyin_bad2
b .Lcopyin_bad1
.Lcopyin_bad1_loop16:
#ifdef __ARMEB__
mov r4, ip, lsl #8
#else
mov r4, ip, lsr #8
#endif
ldrt r5, [r0], #0x04
pld [r0, #0x018]
ldrt r6, [r0], #0x04
ldrt r7, [r0], #0x04
ldrt ip, [r0], #0x04
#ifdef __ARMEB__
orr r4, r4, r5, lsr #24
mov r5, r5, lsl #8
orr r5, r5, r6, lsr #24
mov r6, r6, lsl #8
orr r6, r6, r7, lsr #24
mov r7, r7, lsl #8
orr r7, r7, ip, lsr #24
#else
orr r4, r4, r5, lsl #24
mov r5, r5, lsr #8
orr r5, r5, r6, lsl #24
mov r6, r6, lsr #8
orr r6, r6, r7, lsl #24
mov r7, r7, lsr #8
orr r7, r7, ip, lsl #24
#endif
str r4, [r1], #0x04
str r5, [r1], #0x04
str r6, [r1], #0x04
str r7, [r1], #0x04
.Lcopyin_bad1:
subs r2, r2, #0x10
bge .Lcopyin_bad1_loop16
adds r2, r2, #0x10
ldmfdeq sp!, {r4-r7}
RETeq /* Return now if done */
subs r2, r2, #0x04
sublt r0, r0, #0x03
blt .Lcopyin_l4
.Lcopyin_bad1_loop4:
#ifdef __ARMEB__
mov r4, ip, lsl #8
#else
mov r4, ip, lsr #8
#endif
ldrt ip, [r0], #0x04
subs r2, r2, #0x04
#ifdef __ARMEB__
orr r4, r4, ip, lsr #24
#else
orr r4, r4, ip, lsl #24
#endif
str r4, [r1], #0x04
bge .Lcopyin_bad1_loop4
sub r0, r0, #0x03
b .Lcopyin_l4
.Lcopyin_bad2_loop16:
#ifdef __ARMEB__
mov r4, ip, lsl #16
#else
mov r4, ip, lsr #16
#endif
ldrt r5, [r0], #0x04
pld [r0, #0x018]
ldrt r6, [r0], #0x04
ldrt r7, [r0], #0x04
ldrt ip, [r0], #0x04
#ifdef __ARMEB__
orr r4, r4, r5, lsr #16
mov r5, r5, lsl #16
orr r5, r5, r6, lsr #16
mov r6, r6, lsl #16
orr r6, r6, r7, lsr #16
mov r7, r7, lsl #16
orr r7, r7, ip, lsr #16
#else
orr r4, r4, r5, lsl #16
mov r5, r5, lsr #16
orr r5, r5, r6, lsl #16
mov r6, r6, lsr #16
orr r6, r6, r7, lsl #16
mov r7, r7, lsr #16
orr r7, r7, ip, lsl #16
#endif
str r4, [r1], #0x04
str r5, [r1], #0x04
str r6, [r1], #0x04
str r7, [r1], #0x04
.Lcopyin_bad2:
subs r2, r2, #0x10
bge .Lcopyin_bad2_loop16
adds r2, r2, #0x10
ldmfdeq sp!, {r4-r7}
RETeq /* Return now if done */
subs r2, r2, #0x04
sublt r0, r0, #0x02
blt .Lcopyin_l4
.Lcopyin_bad2_loop4:
#ifdef __ARMEB__
mov r4, ip, lsl #16
#else
mov r4, ip, lsr #16
#endif
ldrt ip, [r0], #0x04
subs r2, r2, #0x04
#ifdef __ARMEB__
orr r4, r4, ip, lsr #16
#else
orr r4, r4, ip, lsl #16
#endif
str r4, [r1], #0x04
bge .Lcopyin_bad2_loop4
sub r0, r0, #0x02
b .Lcopyin_l4
.Lcopyin_bad3_loop16:
#ifdef __ARMEB__
mov r4, ip, lsl #24
#else
mov r4, ip, lsr #24
#endif
ldrt r5, [r0], #0x04
pld [r0, #0x018]
ldrt r6, [r0], #0x04
ldrt r7, [r0], #0x04
ldrt ip, [r0], #0x04
#ifdef __ARMEB__
orr r4, r4, r5, lsr #8
mov r5, r5, lsl #24
orr r5, r5, r6, lsr #8
mov r6, r6, lsl #24
orr r6, r6, r7, lsr #8
mov r7, r7, lsl #24
orr r7, r7, ip, lsr #8
#else
orr r4, r4, r5, lsl #8
mov r5, r5, lsr #24
orr r5, r5, r6, lsl #8
mov r6, r6, lsr #24
orr r6, r6, r7, lsl #8
mov r7, r7, lsr #24
orr r7, r7, ip, lsl #8
#endif
str r4, [r1], #0x04
str r5, [r1], #0x04
str r6, [r1], #0x04
str r7, [r1], #0x04
.Lcopyin_bad3:
subs r2, r2, #0x10
bge .Lcopyin_bad3_loop16
adds r2, r2, #0x10
ldmfdeq sp!, {r4-r7}
RETeq /* Return now if done */
subs r2, r2, #0x04
sublt r0, r0, #0x01
blt .Lcopyin_l4
.Lcopyin_bad3_loop4:
#ifdef __ARMEB__
mov r4, ip, lsl #24
#else
mov r4, ip, lsr #24
#endif
ldrt ip, [r0], #0x04
subs r2, r2, #0x04
#ifdef __ARMEB__
orr r4, r4, ip, lsr #8
#else
orr r4, r4, ip, lsl #8
#endif
str r4, [r1], #0x04
bge .Lcopyin_bad3_loop4
sub r0, r0, #0x01
.Lcopyin_l4:
ldmfd sp!, {r4-r7}
mov r3, #0x00
adds r2, r2, #0x04
RETeq
.Lcopyin_l4_2:
rsbs r2, r2, #0x03
addne pc, pc, r2, lsl #3
nop
ldrbt ip, [r0], #0x01
strb ip, [r1], #0x01
ldrbt ip, [r0], #0x01
strb ip, [r1], #0x01
ldrbt ip, [r0]
strb ip, [r1]
RET
END(copyin)
/*
* r0 = kernel space address
* r1 = user space address
* r2 = length
*
* Copies bytes from kernel space to user space
*/
ENTRY(copyout)
cmp r2, #0x00
movle r0, #0x00
movle pc, lr /* Bail early if length is <= 0 */
adds r3, r1, r2
movcs r0, #EFAULT
RETc(cs)
ldr r12, =(VM_MAXUSER_ADDRESS + 1)
cmp r3, r12
movcs r0, #EFAULT
RETc(cs)
ldr r3, .L_arm_memcpy
ldr r3, [r3]
cmp r3, #0
beq .Lnormale
ldr r3, .L_min_memcpy_size
ldr r3, [r3]
cmp r2, r3
blt .Lnormale
stmfd sp!, {r0-r2, r4, lr}
mov r3, r0
mov r0, r1
mov r1, r3
mov r3, #1 /* DST_IS_USER */
ldr r4, .L_arm_memcpy
mov lr, pc
ldr pc, [r4]
cmp r0, #0
ldmfd sp!, {r0-r2, r4, lr}
moveq r0, #0
RETeq
.Lnormale:
stmfd sp!, {r10-r11, lr}
GET_PCB(r10)
ldr r10, [r10]
mov r3, #0x00
adr ip, .Lcopyout_fault
ldr r11, [r10, #PCB_ONFAULT]
str ip, [r10, #PCB_ONFAULT]
bl .Lcopyout_guts
str r11, [r10, #PCB_ONFAULT]
mov r0, #0x00
ldmfd sp!, {r10-r11, pc}
.Lcopyout_fault:
ldr r0, =EFAULT
str r11, [r10, #PCB_ONFAULT]
cmp r3, #0x00
ldmfdgt sp!, {r4-r7} /* r3 > 0 Restore r4-r7 */
ldmfdlt sp!, {r4-r9} /* r3 < 0 Restore r4-r9 */
ldmfd sp!, {r10-r11, pc}
.Lcopyout_guts:
pld [r0]
/* Word-align the destination buffer */
ands ip, r1, #0x03 /* Already word aligned? */
beq .Lcopyout_wordaligned /* Yup */
rsb ip, ip, #0x04
cmp r2, ip /* Enough bytes left to align it? */
blt .Lcopyout_l4_2 /* Nope. Just copy bytewise */
sub r2, r2, ip
rsbs ip, ip, #0x03
addne pc, pc, ip, lsl #3
nop
ldrb ip, [r0], #0x01
strbt ip, [r1], #0x01
ldrb ip, [r0], #0x01
strbt ip, [r1], #0x01
ldrb ip, [r0], #0x01
strbt ip, [r1], #0x01
cmp r2, #0x00 /* All done? */
RETeq
/* Destination buffer is now word aligned */
.Lcopyout_wordaligned:
ands ip, r0, #0x03 /* Is src also word-aligned? */
bne .Lcopyout_bad_align /* Nope. Things just got bad */
cmp r2, #0x08 /* Less than 8 bytes remaining? */
blt .Lcopyout_w_less_than8
/* Quad-align the destination buffer */
tst r0, #0x07 /* Already quad aligned? */
ldrne ip, [r0], #0x04
subne r2, r2, #0x04
strtne ip, [r1], #0x04
stmfd sp!, {r4-r9} /* Free up some registers */
mov r3, #-1 /* Signal restore r4-r9 */
/* Destination buffer word aligned, source is quad aligned */
subs r2, r2, #0x80
blt .Lcopyout_w_lessthan128
/* Copy 128 bytes at a time */
.Lcopyout_w_loop128:
ldrd r4, [r0], #0x08 /* LD:00-07 */
pld [r0, #0x18] /* Prefetch 0x20 */
ldrd r6, [r0], #0x08 /* LD:08-0f */
ldrd r8, [r0], #0x08 /* LD:10-17 */
strt r4, [r1], #0x04 /* ST:00-03 */
strt r5, [r1], #0x04 /* ST:04-07 */
ldrd r4, [r0], #0x08 /* LD:18-1f */
strt r6, [r1], #0x04 /* ST:08-0b */
strt r7, [r1], #0x04 /* ST:0c-0f */
ldrd r6, [r0], #0x08 /* LD:20-27 */
pld [r0, #0x18] /* Prefetch 0x40 */
strt r8, [r1], #0x04 /* ST:10-13 */
strt r9, [r1], #0x04 /* ST:14-17 */
ldrd r8, [r0], #0x08 /* LD:28-2f */
strt r4, [r1], #0x04 /* ST:18-1b */
strt r5, [r1], #0x04 /* ST:1c-1f */
ldrd r4, [r0], #0x08 /* LD:30-37 */
strt r6, [r1], #0x04 /* ST:20-23 */
strt r7, [r1], #0x04 /* ST:24-27 */
ldrd r6, [r0], #0x08 /* LD:38-3f */
strt r8, [r1], #0x04 /* ST:28-2b */
strt r9, [r1], #0x04 /* ST:2c-2f */
ldrd r8, [r0], #0x08 /* LD:40-47 */
pld [r0, #0x18] /* Prefetch 0x60 */
strt r4, [r1], #0x04 /* ST:30-33 */
strt r5, [r1], #0x04 /* ST:34-37 */
ldrd r4, [r0], #0x08 /* LD:48-4f */
strt r6, [r1], #0x04 /* ST:38-3b */
strt r7, [r1], #0x04 /* ST:3c-3f */
ldrd r6, [r0], #0x08 /* LD:50-57 */
strt r8, [r1], #0x04 /* ST:40-43 */
strt r9, [r1], #0x04 /* ST:44-47 */
ldrd r8, [r0], #0x08 /* LD:58-4f */
strt r4, [r1], #0x04 /* ST:48-4b */
strt r5, [r1], #0x04 /* ST:4c-4f */
ldrd r4, [r0], #0x08 /* LD:60-67 */
pld [r0, #0x18] /* Prefetch 0x80 */
strt r6, [r1], #0x04 /* ST:50-53 */
strt r7, [r1], #0x04 /* ST:54-57 */
ldrd r6, [r0], #0x08 /* LD:68-6f */
strt r8, [r1], #0x04 /* ST:58-5b */
strt r9, [r1], #0x04 /* ST:5c-5f */
ldrd r8, [r0], #0x08 /* LD:70-77 */
strt r4, [r1], #0x04 /* ST:60-63 */
strt r5, [r1], #0x04 /* ST:64-67 */
ldrd r4, [r0], #0x08 /* LD:78-7f */
strt r6, [r1], #0x04 /* ST:68-6b */
strt r7, [r1], #0x04 /* ST:6c-6f */
strt r8, [r1], #0x04 /* ST:70-73 */
strt r9, [r1], #0x04 /* ST:74-77 */
subs r2, r2, #0x80
strt r4, [r1], #0x04 /* ST:78-7b */
strt r5, [r1], #0x04 /* ST:7c-7f */
bge .Lcopyout_w_loop128
.Lcopyout_w_lessthan128:
adds r2, r2, #0x80 /* Adjust for extra sub */
ldmfdeq sp!, {r4-r9}
RETeq /* Return now if done */
subs r2, r2, #0x20
blt .Lcopyout_w_lessthan32
/* Copy 32 bytes at a time */
.Lcopyout_w_loop32:
ldrd r4, [r0], #0x08
pld [r0, #0x18]
ldrd r6, [r0], #0x08
ldrd r8, [r0], #0x08
strt r4, [r1], #0x04
strt r5, [r1], #0x04
ldrd r4, [r0], #0x08
strt r6, [r1], #0x04
strt r7, [r1], #0x04
strt r8, [r1], #0x04
strt r9, [r1], #0x04
subs r2, r2, #0x20
strt r4, [r1], #0x04
strt r5, [r1], #0x04
bge .Lcopyout_w_loop32
.Lcopyout_w_lessthan32:
adds r2, r2, #0x20 /* Adjust for extra sub */
ldmfdeq sp!, {r4-r9}
RETeq /* Return now if done */
and r4, r2, #0x18
rsb r5, r4, #0x18
subs r2, r2, r4
add pc, pc, r5, lsl #1
nop
/* At least 24 bytes remaining */
ldrd r4, [r0], #0x08
strt r4, [r1], #0x04
strt r5, [r1], #0x04
nop
/* At least 16 bytes remaining */
ldrd r4, [r0], #0x08
strt r4, [r1], #0x04
strt r5, [r1], #0x04
nop
/* At least 8 bytes remaining */
ldrd r4, [r0], #0x08
strt r4, [r1], #0x04
strt r5, [r1], #0x04
nop
/* Less than 8 bytes remaining */
ldmfd sp!, {r4-r9}
RETeq /* Return now if done */
mov r3, #0x00
.Lcopyout_w_less_than8:
subs r2, r2, #0x04
ldrge ip, [r0], #0x04
strtge ip, [r1], #0x04
RETeq /* Return now if done */
addlt r2, r2, #0x04
ldrb ip, [r0], #0x01
cmp r2, #0x02
ldrbge r2, [r0], #0x01
strbt ip, [r1], #0x01
ldrbgt ip, [r0]
strbtge r2, [r1], #0x01
strbtgt ip, [r1]
RET
/*
* At this point, it has not been possible to word align both buffers.
* The destination buffer (r1) is word aligned, but the source buffer
* (r0) is not.
*/
.Lcopyout_bad_align:
stmfd sp!, {r4-r7}
mov r3, #0x01
bic r0, r0, #0x03
cmp ip, #2
ldr ip, [r0], #0x04
bgt .Lcopyout_bad3
beq .Lcopyout_bad2
b .Lcopyout_bad1
.Lcopyout_bad1_loop16:
#ifdef __ARMEB__
mov r4, ip, lsl #8
#else
mov r4, ip, lsr #8
#endif
ldr r5, [r0], #0x04
pld [r0, #0x018]
ldr r6, [r0], #0x04
ldr r7, [r0], #0x04
ldr ip, [r0], #0x04
#ifdef __ARMEB__
orr r4, r4, r5, lsr #24
mov r5, r5, lsl #8
orr r5, r5, r6, lsr #24
mov r6, r6, lsl #8
orr r6, r6, r7, lsr #24
mov r7, r7, lsl #8
orr r7, r7, ip, lsr #24
#else
orr r4, r4, r5, lsl #24
mov r5, r5, lsr #8
orr r5, r5, r6, lsl #24
mov r6, r6, lsr #8
orr r6, r6, r7, lsl #24
mov r7, r7, lsr #8
orr r7, r7, ip, lsl #24
#endif
strt r4, [r1], #0x04
strt r5, [r1], #0x04
strt r6, [r1], #0x04
strt r7, [r1], #0x04
.Lcopyout_bad1:
subs r2, r2, #0x10
bge .Lcopyout_bad1_loop16
adds r2, r2, #0x10
ldmfdeq sp!, {r4-r7}
RETeq /* Return now if done */
subs r2, r2, #0x04
sublt r0, r0, #0x03
blt .Lcopyout_l4
.Lcopyout_bad1_loop4:
#ifdef __ARMEB__
mov r4, ip, lsl #8
#else
mov r4, ip, lsr #8
#endif
ldr ip, [r0], #0x04
subs r2, r2, #0x04
#ifdef __ARMEB__
orr r4, r4, ip, lsr #24
#else
orr r4, r4, ip, lsl #24
#endif
strt r4, [r1], #0x04
bge .Lcopyout_bad1_loop4
sub r0, r0, #0x03
b .Lcopyout_l4
.Lcopyout_bad2_loop16:
#ifdef __ARMEB__
mov r4, ip, lsl #16
#else
mov r4, ip, lsr #16
#endif
ldr r5, [r0], #0x04
pld [r0, #0x018]
ldr r6, [r0], #0x04
ldr r7, [r0], #0x04
ldr ip, [r0], #0x04
#ifdef __ARMEB__
orr r4, r4, r5, lsr #16
mov r5, r5, lsl #16
orr r5, r5, r6, lsr #16
mov r6, r6, lsl #16
orr r6, r6, r7, lsr #16
mov r7, r7, lsl #16
orr r7, r7, ip, lsr #16
#else
orr r4, r4, r5, lsl #16
mov r5, r5, lsr #16
orr r5, r5, r6, lsl #16
mov r6, r6, lsr #16
orr r6, r6, r7, lsl #16
mov r7, r7, lsr #16
orr r7, r7, ip, lsl #16
#endif
strt r4, [r1], #0x04
strt r5, [r1], #0x04
strt r6, [r1], #0x04
strt r7, [r1], #0x04
.Lcopyout_bad2:
subs r2, r2, #0x10
bge .Lcopyout_bad2_loop16
adds r2, r2, #0x10
ldmfdeq sp!, {r4-r7}
RETeq /* Return now if done */
subs r2, r2, #0x04
sublt r0, r0, #0x02
blt .Lcopyout_l4
.Lcopyout_bad2_loop4:
#ifdef __ARMEB__
mov r4, ip, lsl #16
#else
mov r4, ip, lsr #16
#endif
ldr ip, [r0], #0x04
subs r2, r2, #0x04
#ifdef __ARMEB__
orr r4, r4, ip, lsr #16
#else
orr r4, r4, ip, lsl #16
#endif
strt r4, [r1], #0x04
bge .Lcopyout_bad2_loop4
sub r0, r0, #0x02
b .Lcopyout_l4
.Lcopyout_bad3_loop16:
#ifdef __ARMEB__
mov r4, ip, lsl #24
#else
mov r4, ip, lsr #24
#endif
ldr r5, [r0], #0x04
pld [r0, #0x018]
ldr r6, [r0], #0x04
ldr r7, [r0], #0x04
ldr ip, [r0], #0x04
#ifdef __ARMEB__
orr r4, r4, r5, lsr #8
mov r5, r5, lsl #24
orr r5, r5, r6, lsr #8
mov r6, r6, lsl #24
orr r6, r6, r7, lsr #8
mov r7, r7, lsl #24
orr r7, r7, ip, lsr #8
#else
orr r4, r4, r5, lsl #8
mov r5, r5, lsr #24
orr r5, r5, r6, lsl #8
mov r6, r6, lsr #24
orr r6, r6, r7, lsl #8
mov r7, r7, lsr #24
orr r7, r7, ip, lsl #8
#endif
strt r4, [r1], #0x04
strt r5, [r1], #0x04
strt r6, [r1], #0x04
strt r7, [r1], #0x04
.Lcopyout_bad3:
subs r2, r2, #0x10
bge .Lcopyout_bad3_loop16
adds r2, r2, #0x10
ldmfdeq sp!, {r4-r7}
RETeq /* Return now if done */
subs r2, r2, #0x04
sublt r0, r0, #0x01
blt .Lcopyout_l4
.Lcopyout_bad3_loop4:
#ifdef __ARMEB__
mov r4, ip, lsl #24
#else
mov r4, ip, lsr #24
#endif
ldr ip, [r0], #0x04
subs r2, r2, #0x04
#ifdef __ARMEB__
orr r4, r4, ip, lsr #8
#else
orr r4, r4, ip, lsl #8
#endif
strt r4, [r1], #0x04
bge .Lcopyout_bad3_loop4
sub r0, r0, #0x01
.Lcopyout_l4:
ldmfd sp!, {r4-r7}
mov r3, #0x00
adds r2, r2, #0x04
RETeq
.Lcopyout_l4_2:
rsbs r2, r2, #0x03
addne pc, pc, r2, lsl #3
nop
ldrb ip, [r0], #0x01
strbt ip, [r1], #0x01
ldrb ip, [r0], #0x01
strbt ip, [r1], #0x01
ldrb ip, [r0]
strbt ip, [r1]
RET
END(copyout)

View File

@ -61,6 +61,10 @@ __FBSDID("$FreeBSD$");
#include <machine/cpufunc.h>
#if defined(CPU_XSCALE_81342)
#include <arm/xscale/i8134x/i81342reg.h>
#endif
/* PRIMARY CACHE VARIABLES */
int arm_picache_size;
int arm_picache_line_size;
@ -250,6 +254,109 @@ struct cpu_functions pj4bv7_cpufuncs = {
};
#endif /* CPU_MV_PJ4B */
#if defined(CPU_XSCALE_PXA2X0)
struct cpu_functions xscale_cpufuncs = {
/* CPU functions */
xscale_cpwait, /* cpwait */
/* MMU functions */
xscale_control, /* control */
xscale_setttb, /* setttb */
/* TLB functions */
armv4_tlb_flushID, /* tlb_flushID */
xscale_tlb_flushID_SE, /* tlb_flushID_SE */
armv4_tlb_flushD, /* tlb_flushD */
armv4_tlb_flushD_SE, /* tlb_flushD_SE */
/* Cache operations */
xscale_cache_syncI_rng, /* icache_sync_range */
xscale_cache_purgeD, /* dcache_wbinv_all */
xscale_cache_purgeD_rng, /* dcache_wbinv_range */
xscale_cache_flushD_rng, /* dcache_inv_range */
xscale_cache_cleanD_rng, /* dcache_wb_range */
xscale_cache_flushID, /* idcache_inv_all */
xscale_cache_purgeID, /* idcache_wbinv_all */
xscale_cache_purgeID_rng, /* idcache_wbinv_range */
cpufunc_nullop, /* l2cache_wbinv_all */
(void *)cpufunc_nullop, /* l2cache_wbinv_range */
(void *)cpufunc_nullop, /* l2cache_inv_range */
(void *)cpufunc_nullop, /* l2cache_wb_range */
(void *)cpufunc_nullop, /* l2cache_drain_writebuf */
/* Other functions */
armv4_drain_writebuf, /* drain_writebuf */
xscale_cpu_sleep, /* sleep */
/* Soft functions */
xscale_context_switch, /* context_switch */
xscale_setup /* cpu setup */
};
#endif
/* CPU_XSCALE_PXA2X0 */
#ifdef CPU_XSCALE_81342
struct cpu_functions xscalec3_cpufuncs = {
/* CPU functions */
xscale_cpwait, /* cpwait */
/* MMU functions */
xscale_control, /* control */
xscalec3_setttb, /* setttb */
/* TLB functions */
armv4_tlb_flushID, /* tlb_flushID */
xscale_tlb_flushID_SE, /* tlb_flushID_SE */
armv4_tlb_flushD, /* tlb_flushD */
armv4_tlb_flushD_SE, /* tlb_flushD_SE */
/* Cache operations */
xscalec3_cache_syncI_rng, /* icache_sync_range */
xscalec3_cache_purgeD, /* dcache_wbinv_all */
xscalec3_cache_purgeD_rng, /* dcache_wbinv_range */
xscale_cache_flushD_rng, /* dcache_inv_range */
xscalec3_cache_cleanD_rng, /* dcache_wb_range */
xscale_cache_flushID, /* idcache_inv_all */
xscalec3_cache_purgeID, /* idcache_wbinv_all */
xscalec3_cache_purgeID_rng, /* idcache_wbinv_range */
xscalec3_l2cache_purge, /* l2cache_wbinv_all */
xscalec3_l2cache_purge_rng, /* l2cache_wbinv_range */
xscalec3_l2cache_flush_rng, /* l2cache_inv_range */
xscalec3_l2cache_clean_rng, /* l2cache_wb_range */
(void *)cpufunc_nullop, /* l2cache_drain_writebuf */
/* Other functions */
armv4_drain_writebuf, /* drain_writebuf */
xscale_cpu_sleep, /* sleep */
/* Soft functions */
xscalec3_context_switch, /* context_switch */
xscale_setup /* cpu setup */
};
#endif /* CPU_XSCALE_81342 */
#if defined(CPU_FA526)
struct cpu_functions fa526_cpufuncs = {
/* CPU functions */
@ -355,7 +462,9 @@ u_int cpu_reset_needs_v4_MMU_disable; /* flag used in locore-v4.s */
#if defined(CPU_ARM9) || \
defined (CPU_ARM9E) || \
defined(CPU_ARM1176) || \
defined(CPU_XSCALE_PXA2X0) || \
defined(CPU_FA526) || defined(CPU_MV_PJ4B) || \
defined(CPU_XSCALE_81342) || \
defined(CPU_CORTEXA) || defined(CPU_KRAIT)
/* Global cache line sizes, use 32 as default */
@ -480,7 +589,7 @@ get_cachetype_cp15(void)
arm_dcache_align_mask = arm_dcache_align - 1;
}
}
#endif /* ARM9 */
#endif /* ARM9 || XSCALE */
/*
* Cannot panic here as we may not have a console yet ...
@ -588,6 +697,29 @@ set_cpufuncs(void)
}
#endif /* CPU_FA526 */
#if defined(CPU_XSCALE_81342)
if (cputype == CPU_ID_81342) {
cpufuncs = xscalec3_cpufuncs;
cpu_reset_needs_v4_MMU_disable = 1; /* XScale needs it */
get_cachetype_cp15();
pmap_pte_init_xscale();
goto out;
}
#endif /* CPU_XSCALE_81342 */
#ifdef CPU_XSCALE_PXA2X0
/* ignore core revision to test PXA2xx CPUs */
if ((cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA250 ||
(cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA27X ||
(cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA210) {
cpufuncs = xscale_cpufuncs;
cpu_reset_needs_v4_MMU_disable = 1; /* XScale needs it */
get_cachetype_cp15();
pmap_pte_init_xscale();
goto out;
}
#endif /* CPU_XSCALE_PXA2X0 */
/*
* Bzzzz. And the answer was ...
*/
@ -800,3 +932,71 @@ fa526_setup(void)
cpu_control(0xffffffff, cpuctrl);
}
#endif /* CPU_FA526 */
#if defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_81342)
void
xscale_setup(void)
{
uint32_t auxctl;
int cpuctrl, cpuctrlmask;
/*
* The XScale Write Buffer is always enabled. Our option
* is to enable/disable coalescing. Note that bits 6:3
* must always be enabled.
*/
cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
| CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
| CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
| CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE
| CPU_CONTROL_BPRD_ENABLE;
cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
| CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
| CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
| CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE
| CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE
| CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_BPRD_ENABLE
| CPU_CONTROL_CPCLK | CPU_CONTROL_VECRELOC | \
CPU_CONTROL_L2_ENABLE;
#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
#endif
#ifdef __ARMEB__
cpuctrl |= CPU_CONTROL_BEND_ENABLE;
#endif
if (vector_page == ARM_VECTORS_HIGH)
cpuctrl |= CPU_CONTROL_VECRELOC;
#ifdef CPU_XSCALE_CORE3
cpuctrl |= CPU_CONTROL_L2_ENABLE;
#endif
/* Clear out the cache */
cpu_idcache_wbinv_all();
/*
* Set the control register. Note that bits 6:3 must always
* be set to 1.
*/
/* cpu_control(cpuctrlmask, cpuctrl);*/
cpu_control(0xffffffff, cpuctrl);
/* Make sure write coalescing is turned on */
__asm __volatile("mrc p15, 0, %0, c1, c0, 1"
: "=r" (auxctl));
#ifdef XSCALE_NO_COALESCE_WRITES
auxctl |= XSCALE_AUXCTL_K;
#else
auxctl &= ~XSCALE_AUXCTL_K;
#endif
#ifdef CPU_XSCALE_CORE3
auxctl |= XSCALE_AUXCTL_LLR;
auxctl |= XSCALE_AUXCTL_MD_MASK;
#endif
__asm __volatile("mcr p15, 0, %0, c1, c0, 1"
: : "r" (auxctl));
}
#endif /* CPU_XSCALE_PXA2X0 */

View File

@ -0,0 +1,509 @@
/* $NetBSD: cpufunc_asm_xscale.S,v 1.16 2002/08/17 16:36:32 thorpej Exp $ */
/*-
* Copyright (c) 2001, 2002 Wasabi Systems, Inc.
* All rights reserved.
*
* Written by Allen Briggs and Jason R. Thorpe for Wasabi Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed for the NetBSD Project by
* Wasabi Systems, Inc.
* 4. The name of Wasabi Systems, Inc. may not be used to endorse
* or promote products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
/*-
* Copyright (c) 2001 Matt Thomas.
* Copyright (c) 1997,1998 Mark Brinicombe.
* Copyright (c) 1997 Causality Limited
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Causality Limited.
* 4. The name of Causality Limited may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY CAUSALITY LIMITED ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL CAUSALITY LIMITED BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* XScale assembly functions for CPU / MMU / TLB specific operations
*/
#include <machine/asm.h>
__FBSDID("$FreeBSD$");
#include <machine/armreg.h>
/*
* Size of the XScale core D-cache.
*/
#define DCACHE_SIZE 0x00008000
/*
* CPWAIT -- Canonical method to wait for CP15 update.
* From: Intel 80200 manual, section 2.3.3.
*
* NOTE: Clobbers the specified temp reg.
*/
#define CPWAIT_BRANCH \
sub pc, pc, #4
#define CPWAIT(tmp) \
mrc p15, 0, tmp, c2, c0, 0 /* arbitrary read of CP15 */ ;\
mov tmp, tmp /* wait for it to complete */ ;\
CPWAIT_BRANCH /* branch to next insn */
#define CPWAIT_AND_RETURN_SHIFTER lsr #32
#define CPWAIT_AND_RETURN(tmp) \
mrc p15, 0, tmp, c2, c0, 0 /* arbitrary read of CP15 */ ;\
/* Wait for it to complete and branch to the return address */ \
sub pc, lr, tmp, CPWAIT_AND_RETURN_SHIFTER
ENTRY(xscale_cpwait)
CPWAIT_AND_RETURN(r0)
END(xscale_cpwait)
/*
* We need a separate cpu_control() entry point, since we have to
* invalidate the Branch Target Buffer in the event the BPRD bit
* changes in the control register.
*/
ENTRY(xscale_control)
mrc CP15_SCTLR(r3) /* Read the control register */
bic r2, r3, r0 /* Clear bits */
eor r2, r2, r1 /* XOR bits */
teq r2, r3 /* Only write if there was a change */
mcrne p15, 0, r0, c7, c5, 6 /* Invalidate the BTB */
mcrne CP15_SCTLR(r2) /* Write new control register */
mov r0, r3 /* Return old value */
CPWAIT_AND_RETURN(r1)
END(xscale_control)
/*
* Functions to set the MMU Translation Table Base register
*
* We need to clean and flush the cache as it uses virtual
* addresses that are about to change.
*/
ENTRY(xscale_setttb)
#ifdef CACHE_CLEAN_BLOCK_INTR
mrs r3, cpsr
orr r1, r3, #(PSR_I | PSR_F)
msr cpsr_fsxc, r1
#endif
stmfd sp!, {r0-r3, lr}
bl _C_LABEL(xscale_cache_cleanID)
mcr p15, 0, r0, c7, c5, 0 /* invalidate I$ and BTB */
mcr p15, 0, r0, c7, c10, 4 /* drain write and fill buffer */
CPWAIT(r0)
ldmfd sp!, {r0-r3, lr}
/* Write the TTB */
mcr p15, 0, r0, c2, c0, 0
/* If we have updated the TTB we must flush the TLB */
mcr p15, 0, r0, c8, c7, 0 /* invalidate I+D TLB */
/* The cleanID above means we only need to flush the I cache here */
mcr p15, 0, r0, c7, c5, 0 /* invalidate I$ and BTB */
CPWAIT(r0)
#ifdef CACHE_CLEAN_BLOCK_INTR
msr cpsr_fsxc, r3
#endif
RET
END(xscale_setttb)
/*
* TLB functions
*
*/
ENTRY(xscale_tlb_flushID_SE)
mcr p15, 0, r0, c8, c6, 1 /* flush D tlb single entry */
mcr p15, 0, r0, c8, c5, 1 /* flush I tlb single entry */
CPWAIT_AND_RETURN(r0)
END(xscale_tlb_flushID_SE)
/*
* Cache functions
*/
ENTRY(xscale_cache_flushID)
mcr p15, 0, r0, c7, c7, 0 /* flush I+D cache */
CPWAIT_AND_RETURN(r0)
END(xscale_cache_flushID)
ENTRY(xscale_cache_flushI)
mcr p15, 0, r0, c7, c5, 0 /* flush I cache */
CPWAIT_AND_RETURN(r0)
END(xscale_cache_flushI)
ENTRY(xscale_cache_flushD)
mcr p15, 0, r0, c7, c6, 0 /* flush D cache */
CPWAIT_AND_RETURN(r0)
END(xscale_cache_flushD)
ENTRY(xscale_cache_flushI_SE)
mcr p15, 0, r0, c7, c5, 1 /* flush I cache single entry */
CPWAIT_AND_RETURN(r0)
END(xscale_cache_flushI_SE)
ENTRY(xscale_cache_flushD_SE)
/*
* Errata (rev < 2): Must clean-dcache-line to an address
* before invalidate-dcache-line to an address, or dirty
* bits will not be cleared in the dcache array.
*/
mcr p15, 0, r0, c7, c10, 1
mcr p15, 0, r0, c7, c6, 1 /* flush D cache single entry */
CPWAIT_AND_RETURN(r0)
END(xscale_cache_flushD_SE)
ENTRY(xscale_cache_cleanD_E)
mcr p15, 0, r0, c7, c10, 1 /* clean D cache entry */
CPWAIT_AND_RETURN(r0)
END(xscale_cache_cleanD_E)
/*
* Information for the XScale cache clean/purge functions:
*
* * Virtual address of the memory region to use
* * Size of memory region
*
* Note the virtual address for the Data cache clean operation
* does not need to be backed by physical memory, since no loads
* will actually be performed by the allocate-line operation.
*
* Note that the Mini-Data cache MUST be cleaned by executing
* loads from memory mapped into a region reserved exclusively
* for cleaning of the Mini-Data cache.
*/
.data
.global _C_LABEL(xscale_cache_clean_addr)
_C_LABEL(xscale_cache_clean_addr):
.word 0x00000000
.global _C_LABEL(xscale_cache_clean_size)
_C_LABEL(xscale_cache_clean_size):
.word DCACHE_SIZE
.global _C_LABEL(xscale_minidata_clean_addr)
_C_LABEL(xscale_minidata_clean_addr):
.word 0x00000000
.global _C_LABEL(xscale_minidata_clean_size)
_C_LABEL(xscale_minidata_clean_size):
.word 0x00000800
.text
.Lxscale_cache_clean_addr:
.word _C_LABEL(xscale_cache_clean_addr)
.Lxscale_cache_clean_size:
.word _C_LABEL(xscale_cache_clean_size)
.Lxscale_minidata_clean_addr:
.word _C_LABEL(xscale_minidata_clean_addr)
.Lxscale_minidata_clean_size:
.word _C_LABEL(xscale_minidata_clean_size)
#ifdef CACHE_CLEAN_BLOCK_INTR
#define XSCALE_CACHE_CLEAN_BLOCK \
mrs r3, cpsr ; \
orr r0, r3, #(PSR_I | PSR_F) ; \
msr cpsr_fsxc, r0
#define XSCALE_CACHE_CLEAN_UNBLOCK \
msr cpsr_fsxc, r3
#else
#define XSCALE_CACHE_CLEAN_BLOCK
#define XSCALE_CACHE_CLEAN_UNBLOCK
#endif /* CACHE_CLEAN_BLOCK_INTR */
#define XSCALE_CACHE_CLEAN_PROLOGUE \
XSCALE_CACHE_CLEAN_BLOCK ; \
ldr r2, .Lxscale_cache_clean_addr ; \
ldmia r2, {r0, r1} ; \
/* \
* BUG ALERT! \
* \
* The XScale core has a strange cache eviction bug, which \
* requires us to use 2x the cache size for the cache clean \
* and for that area to be aligned to 2 * cache size. \
* \
* The work-around is to use 2 areas for cache clean, and to \
* alternate between them whenever this is done. No one knows \
* why the work-around works (mmm!). \
*/ \
eor r0, r0, #(DCACHE_SIZE) ; \
str r0, [r2] ; \
add r0, r0, r1
#define XSCALE_CACHE_CLEAN_EPILOGUE \
XSCALE_CACHE_CLEAN_UNBLOCK
ENTRY_NP(xscale_cache_syncI)
EENTRY_NP(xscale_cache_purgeID)
mcr p15, 0, r0, c7, c5, 0 /* flush I cache (D cleaned below) */
EENTRY_NP(xscale_cache_cleanID)
EENTRY_NP(xscale_cache_purgeD)
EENTRY(xscale_cache_cleanD)
XSCALE_CACHE_CLEAN_PROLOGUE
1: subs r0, r0, #32
mcr p15, 0, r0, c7, c2, 5 /* allocate cache line */
subs r1, r1, #32
bne 1b
CPWAIT(r0)
mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
CPWAIT(r0)
XSCALE_CACHE_CLEAN_EPILOGUE
RET
EEND(xscale_cache_cleanD)
EEND(xscale_cache_purgeD)
EEND(xscale_cache_cleanID)
EEND(xscale_cache_purgeID)
END(xscale_cache_syncI)
/*
* Clean the mini-data cache.
*
* It's expected that we only use the mini-data cache for
* kernel addresses, so there is no need to purge it on
* context switch, and no need to prevent userspace access
* while we clean it.
*/
ENTRY(xscale_cache_clean_minidata)
ldr r2, .Lxscale_minidata_clean_addr
ldmia r2, {r0, r1}
1: ldr r3, [r0], #32
subs r1, r1, #32
bne 1b
mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
CPWAIT_AND_RETURN(r1)
END(xscale_cache_clean_minidata)
ENTRY(xscale_cache_purgeID_E)
mcr p15, 0, r0, c7, c10, 1 /* clean D cache entry */
CPWAIT(r1)
mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
mcr p15, 0, r0, c7, c5, 1 /* flush I cache single entry */
mcr p15, 0, r0, c7, c6, 1 /* flush D cache single entry */
CPWAIT_AND_RETURN(r1)
END(xscale_cache_purgeID_E)
ENTRY(xscale_cache_purgeD_E)
mcr p15, 0, r0, c7, c10, 1 /* clean D cache entry */
CPWAIT(r1)
mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
mcr p15, 0, r0, c7, c6, 1 /* flush D cache single entry */
CPWAIT_AND_RETURN(r1)
END(xscale_cache_purgeD_E)
/*
* Soft functions
*/
/* xscale_cache_syncI is identical to xscale_cache_purgeID */
EENTRY(xscale_cache_cleanID_rng)
ENTRY(xscale_cache_cleanD_rng)
cmp r1, #0x4000
bcs _C_LABEL(xscale_cache_cleanID)
and r2, r0, #0x1f
add r1, r1, r2
bic r0, r0, #0x1f
1: mcr p15, 0, r0, c7, c10, 1 /* clean D cache entry */
add r0, r0, #32
subs r1, r1, #32
bhi 1b
CPWAIT(r0)
mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
CPWAIT_AND_RETURN(r0)
/*END(xscale_cache_cleanID_rng)*/
END(xscale_cache_cleanD_rng)
ENTRY(xscale_cache_purgeID_rng)
cmp r1, #0x4000
bcs _C_LABEL(xscale_cache_purgeID)
and r2, r0, #0x1f
add r1, r1, r2
bic r0, r0, #0x1f
1: mcr p15, 0, r0, c7, c10, 1 /* clean D cache entry */
mcr p15, 0, r0, c7, c6, 1 /* flush D cache single entry */
mcr p15, 0, r0, c7, c5, 1 /* flush I cache single entry */
add r0, r0, #32
subs r1, r1, #32
bhi 1b
CPWAIT(r0)
mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
CPWAIT_AND_RETURN(r0)
END(xscale_cache_purgeID_rng)
ENTRY(xscale_cache_purgeD_rng)
cmp r1, #0x4000
bcs _C_LABEL(xscale_cache_purgeD)
and r2, r0, #0x1f
add r1, r1, r2
bic r0, r0, #0x1f
1: mcr p15, 0, r0, c7, c10, 1 /* clean D cache entry */
mcr p15, 0, r0, c7, c6, 1 /* flush D cache single entry */
add r0, r0, #32
subs r1, r1, #32
bhi 1b
CPWAIT(r0)
mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
CPWAIT_AND_RETURN(r0)
END(xscale_cache_purgeD_rng)
ENTRY(xscale_cache_syncI_rng)
cmp r1, #0x4000
bcs _C_LABEL(xscale_cache_syncI)
and r2, r0, #0x1f
add r1, r1, r2
bic r0, r0, #0x1f
1: mcr p15, 0, r0, c7, c10, 1 /* clean D cache entry */
mcr p15, 0, r0, c7, c5, 1 /* flush I cache single entry */
add r0, r0, #32
subs r1, r1, #32
bhi 1b
CPWAIT(r0)
mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
CPWAIT_AND_RETURN(r0)
END(xscale_cache_syncI_rng)
ENTRY(xscale_cache_flushD_rng)
and r2, r0, #0x1f
add r1, r1, r2
bic r0, r0, #0x1f
1: mcr p15, 0, r0, c7, c6, 1 /* flush D cache single entry */
add r0, r0, #32
subs r1, r1, #32
bhi 1b
mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
CPWAIT_AND_RETURN(r0)
END(xscale_cache_flushD_rng)
/*
* Context switch.
*
* These is the CPU-specific parts of the context switcher cpu_switch()
* These functions actually perform the TTB reload.
*
* NOTE: Special calling convention
* r1, r4-r13 must be preserved
*/
ENTRY(xscale_context_switch)
/*
* CF_CACHE_PURGE_ID will *ALWAYS* be called prior to this.
* Thus the data cache will contain only kernel data and the
* instruction cache will contain only kernel code, and all
* kernel mappings are shared by all processes.
*/
/* Write the TTB */
mcr p15, 0, r0, c2, c0, 0
/* If we have updated the TTB we must flush the TLB */
mcr p15, 0, r0, c8, c7, 0 /* flush the I+D tlb */
CPWAIT_AND_RETURN(r0)
END(xscale_context_switch)
/*
* xscale_cpu_sleep
*
* This is called when there is nothing on any of the run queues.
* We go into IDLE mode so that any IRQ or FIQ will awaken us.
*
* If this is called with anything other than ARM_SLEEP_MODE_IDLE,
* ignore it.
*/
ENTRY(xscale_cpu_sleep)
tst r0, #0x00000000
bne 1f
mov r0, #0x1
mcr p14, 0, r0, c7, c0, 0
1:
RET
END(xscale_cpu_sleep)

View File

@ -0,0 +1,399 @@
/* $NetBSD: cpufunc_asm_xscale.S,v 1.16 2002/08/17 16:36:32 thorpej Exp $ */
/*-
* Copyright (c) 2007 Olivier Houchard
* Copyright (c) 2001, 2002 Wasabi Systems, Inc.
* All rights reserved.
*
* Written by Allen Briggs and Jason R. Thorpe for Wasabi Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed for the NetBSD Project by
* Wasabi Systems, Inc.
* 4. The name of Wasabi Systems, Inc. may not be used to endorse
* or promote products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
/*-
* Copyright (c) 2001 Matt Thomas.
* Copyright (c) 1997,1998 Mark Brinicombe.
* Copyright (c) 1997 Causality Limited
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Causality Limited.
* 4. The name of Causality Limited may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY CAUSALITY LIMITED ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL CAUSALITY LIMITED BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* XScale core 3 assembly functions for CPU / MMU / TLB specific operations
*/
#include <machine/asm.h>
__FBSDID("$FreeBSD$");
#include <machine/armreg.h>
/*
* Size of the XScale core D-cache.
*/
#define DCACHE_SIZE 0x00008000
/*
* CPWAIT -- Canonical method to wait for CP15 update.
* From: Intel 80200 manual, section 2.3.3.
*
* NOTE: Clobbers the specified temp reg.
*/
#define CPWAIT_BRANCH \
sub pc, pc, #4
#define CPWAIT(tmp) \
mrc p15, 0, tmp, c2, c0, 0 /* arbitrary read of CP15 */ ;\
mov tmp, tmp /* wait for it to complete */ ;\
CPWAIT_BRANCH /* branch to next insn */
#define CPWAIT_AND_RETURN_SHIFTER lsr #32
#define CPWAIT_AND_RETURN(tmp) \
mrc p15, 0, tmp, c2, c0, 0 /* arbitrary read of CP15 */ ;\
/* Wait for it to complete and branch to the return address */ \
sub pc, lr, tmp, CPWAIT_AND_RETURN_SHIFTER
#define ARM_USE_L2_CACHE
#define L2_CACHE_SIZE 0x80000
#define L2_CACHE_WAYS 8
#define L2_CACHE_LINE_SIZE 32
#define L2_CACHE_SETS (L2_CACHE_SIZE / \
(L2_CACHE_WAYS * L2_CACHE_LINE_SIZE))
#define L1_DCACHE_SIZE 32 * 1024
#define L1_DCACHE_WAYS 4
#define L1_DCACHE_LINE_SIZE 32
#define L1_DCACHE_SETS (L1_DCACHE_SIZE / \
(L1_DCACHE_WAYS * L1_DCACHE_LINE_SIZE))
#ifdef CACHE_CLEAN_BLOCK_INTR
#define XSCALE_CACHE_CLEAN_BLOCK \
stmfd sp!, {r4} ; \
mrs r4, cpsr ; \
orr r0, r4, #(PSR_I | PSR_F) ; \
msr cpsr_fsxc, r0
#define XSCALE_CACHE_CLEAN_UNBLOCK \
msr cpsr_fsxc, r4 ; \
ldmfd sp!, {r4}
#else
#define XSCALE_CACHE_CLEAN_BLOCK
#define XSCALE_CACHE_CLEAN_UNBLOCK
#endif /* CACHE_CLEAN_BLOCK_INTR */
ENTRY_NP(xscalec3_cache_syncI)
EENTRY_NP(xscalec3_cache_purgeID)
mcr p15, 0, r0, c7, c5, 0 /* flush I cache (D cleaned below) */
EENTRY_NP(xscalec3_cache_cleanID)
EENTRY_NP(xscalec3_cache_purgeD)
EENTRY(xscalec3_cache_cleanD)
XSCALE_CACHE_CLEAN_BLOCK
mov r0, #0
1:
mov r1, r0, asl #30
mov r2, #0
2:
orr r3, r1, r2, asl #5
mcr p15, 0, r3, c7, c14, 2 /* clean and invalidate */
add r2, r2, #1
cmp r2, #L1_DCACHE_SETS
bne 2b
add r0, r0, #1
cmp r0, #4
bne 1b
CPWAIT(r0)
XSCALE_CACHE_CLEAN_UNBLOCK
mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
RET
EEND(xscalec3_cache_purgeID)
EEND(xscalec3_cache_cleanID)
EEND(xscalec3_cache_purgeD)
EEND(xscalec3_cache_cleanD)
END(xscalec3_cache_syncI)
ENTRY(xscalec3_cache_purgeID_rng)
cmp r1, #0x4000
bcs _C_LABEL(xscalec3_cache_cleanID)
and r2, r0, #0x1f
add r1, r1, r2
bic r0, r0, #0x1f
1: mcr p15, 0, r0, c7, c14, 1 /* clean/invalidate L1 D cache entry */
nop
mcr p15, 0, r0, c7, c5, 1 /* flush I cache single entry */
add r0, r0, #32
subs r1, r1, #32
bhi 1b
CPWAIT(r0)
mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
CPWAIT_AND_RETURN(r0)
END(xscalec3_cache_purgeID_rng)
ENTRY(xscalec3_cache_syncI_rng)
cmp r1, #0x4000
bcs _C_LABEL(xscalec3_cache_syncI)
and r2, r0, #0x1f
add r1, r1, r2
bic r0, r0, #0x1f
1: mcr p15, 0, r0, c7, c10, 1 /* clean D cache entry */
mcr p15, 0, r0, c7, c5, 1 /* flush I cache single entry */
add r0, r0, #32
subs r1, r1, #32
bhi 1b
CPWAIT(r0)
mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
CPWAIT_AND_RETURN(r0)
END(xscalec3_cache_syncI_rng)
ENTRY(xscalec3_cache_purgeD_rng)
cmp r1, #0x4000
bcs _C_LABEL(xscalec3_cache_cleanID)
and r2, r0, #0x1f
add r1, r1, r2
bic r0, r0, #0x1f
1: mcr p15, 0, r0, c7, c14, 1 /* Clean and invalidate D cache entry */
add r0, r0, #32
subs r1, r1, #32
bhi 1b
CPWAIT(r0)
mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
CPWAIT_AND_RETURN(r0)
END(xscalec3_cache_purgeD_rng)
ENTRY(xscalec3_cache_cleanID_rng)
EENTRY(xscalec3_cache_cleanD_rng)
cmp r1, #0x4000
bcs _C_LABEL(xscalec3_cache_cleanID)
and r2, r0, #0x1f
add r1, r1, r2
bic r0, r0, #0x1f
1: mcr p15, 0, r0, c7, c10, 1 /* clean L1 D cache entry */
nop
add r0, r0, #32
subs r1, r1, #32
bhi 1b
CPWAIT(r0)
mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
CPWAIT_AND_RETURN(r0)
EEND(xscalec3_cache_cleanD_rng)
END(xscalec3_cache_cleanID_rng)
ENTRY(xscalec3_l2cache_purge)
/* Clean-up the L2 cache */
mcr p15, 0, r0, c7, c10, 5 /* Data memory barrier */
mov r0, #0
1:
mov r1, r0, asl #29
mov r2, #0
2:
orr r3, r1, r2, asl #5
mcr p15, 1, r3, c7, c15, 2
add r2, r2, #1
cmp r2, #L2_CACHE_SETS
bne 2b
add r0, r0, #1
cmp r0, #8
bne 1b
mcr p15, 0, r0, c7, c10, 4 @ data write barrier
CPWAIT(r0)
mcr p15, 0, r0, c7, c10, 5 /* Data memory barrier */
RET
END(xscalec3_l2cache_purge)
ENTRY(xscalec3_l2cache_clean_rng)
mcr p15, 0, r0, c7, c10, 5 /* Data memory barrier */
and r2, r0, #0x1f
add r1, r1, r2
bic r0, r0, #0x1f
1: mcr p15, 1, r0, c7, c11, 1 /* Clean L2 D cache entry */
add r0, r0, #32
subs r1, r1, #32
bhi 1b
CPWAIT(r0)
mcr p15, 0, r0, c7, c10, 4 @ data write barrier
mcr p15, 0, r0, c7, c10, 5
CPWAIT_AND_RETURN(r0)
END(xscalec3_l2cache_clean_rng)
ENTRY(xscalec3_l2cache_purge_rng)
mcr p15, 0, r0, c7, c10, 5 /* Data memory barrier */
and r2, r0, #0x1f
add r1, r1, r2
bic r0, r0, #0x1f
1: mcr p15, 1, r0, c7, c11, 1 /* Clean L2 D cache entry */
mcr p15, 1, r0, c7, c7, 1 /* Invalidate L2 D cache entry */
add r0, r0, #32
subs r1, r1, #32
bhi 1b
mcr p15, 0, r0, c7, c10, 4 @ data write barrier
mcr p15, 0, r0, c7, c10, 5
CPWAIT_AND_RETURN(r0)
END(xscalec3_l2cache_purge_rng)
ENTRY(xscalec3_l2cache_flush_rng)
mcr p15, 0, r0, c7, c10, 5 /* Data memory barrier */
and r2, r0, #0x1f
add r1, r1, r2
bic r0, r0, #0x1f
1: mcr p15, 1, r0, c7, c7, 1 /* Invalidate L2 cache line */
add r0, r0, #32
subs r1, r1, #32
bhi 1b
mcr p15, 0, r0, c7, c10, 4 @ data write barrier
mcr p15, 0, r0, c7, c10, 5
CPWAIT_AND_RETURN(r0)
END(xscalec3_l2cache_flush_rng)
/*
* Functions to set the MMU Translation Table Base register
*
* We need to clean and flush the cache as it uses virtual
* addresses that are about to change.
*/
ENTRY(xscalec3_setttb)
#ifdef CACHE_CLEAN_BLOCK_INTR
mrs r3, cpsr
orr r1, r3, #(PSR_I | PSR_F)
msr cpsr_fsxc, r1
#endif
stmfd sp!, {r0-r3, lr}
bl _C_LABEL(xscalec3_cache_cleanID)
mcr p15, 0, r0, c7, c5, 0 /* invalidate I$ and BTB */
mcr p15, 0, r0, c7, c10, 4 /* drain write and fill buffer */
CPWAIT(r0)
ldmfd sp!, {r0-r3, lr}
#ifdef ARM_USE_L2_CACHE
orr r0, r0, #0x18 /* cache the page table in L2 */
#endif
/* Write the TTB */
mcr p15, 0, r0, c2, c0, 0
/* If we have updated the TTB we must flush the TLB */
mcr p15, 0, r0, c8, c7, 0 /* invalidate I+D TLB */
CPWAIT(r0)
#ifdef CACHE_CLEAN_BLOCK_INTR
msr cpsr_fsxc, r3
#endif
RET
END(xscalec3_setttb)
/*
* Context switch.
*
* These is the CPU-specific parts of the context switcher cpu_switch()
* These functions actually perform the TTB reload.
*
* NOTE: Special calling convention
* r1, r4-r13 must be preserved
*/
ENTRY(xscalec3_context_switch)
/*
* CF_CACHE_PURGE_ID will *ALWAYS* be called prior to this.
* Thus the data cache will contain only kernel data and the
* instruction cache will contain only kernel code, and all
* kernel mappings are shared by all processes.
*/
#ifdef ARM_USE_L2_CACHE
orr r0, r0, #0x18 /* Cache the page table in L2 */
#endif
/* Write the TTB */
mcr p15, 0, r0, c2, c0, 0
/* If we have updated the TTB we must flush the TLB */
mcr p15, 0, r0, c8, c7, 0 /* flush the I+D tlb */
CPWAIT_AND_RETURN(r0)
END(xscalec3_context_switch)

View File

@ -63,6 +63,9 @@ dumpsys_wbinv_all(void)
* part of stopping.
*/
dcache_wbinv_poc_all();
#ifdef __XSCALE__
xscale_cache_clean_minidata();
#endif
}
void

View File

@ -70,6 +70,16 @@ extern void fa526_idcache_wbinv_all(void);
#elif defined(CPU_ARM9E)
#define cpu_idcache_wbinv_all armv5_ec_idcache_wbinv_all
extern void armv5_ec_idcache_wbinv_all(void);
#elif defined(CPU_XSCALE_PXA2X0)
#define cpu_idcache_wbinv_all xscale_cache_purgeID
extern void xscale_cache_purgeID(void);
#elif defined(CPU_XSCALE_81342)
#define cpu_idcache_wbinv_all xscalec3_cache_purgeID
extern void xscalec3_cache_purgeID(void);
#endif
#ifdef CPU_XSCALE_81342
#define cpu_l2cache_wbinv_all xscalec3_l2cache_purge
extern void xscalec3_l2cache_purge(void);
#elif defined(SOC_MV_KIRKWOOD) || defined(SOC_MV_DISCOVERY)
#define cpu_l2cache_wbinv_all sheeva_l2cache_wbinv_all
extern void sheeva_l2cache_wbinv_all(void);

View File

@ -321,6 +321,10 @@ END(exception_exit)
* on exit (without transitioning back through the abort mode stack).
*/
ASENTRY_NP(prefetch_abort_entry)
#ifdef __XSCALE__
nop /* Make absolutely sure any pending */
nop /* imprecise aborts have occurred. */
#endif
sub lr, lr, #4 /* Adjust the lr. Transition to scv32 */
PUSHFRAMEINSVC /* mode stack, build trapframe there. */
adr lr, exception_exit /* Return from handler via standard */
@ -337,6 +341,10 @@ END(prefetch_abort_entry)
* on exit (without transitioning back through the abort mode stack).
*/
ASENTRY_NP(data_abort_entry)
#ifdef __XSCALE__
nop /* Make absolutely sure any pending */
nop /* imprecise aborts have occurred. */
#endif
sub lr, lr, #8 /* Adjust the lr. Transition to scv32 */
PUSHFRAMEINSVC /* mode stack, build trapframe there. */
adr lr, exception_exit /* Exception exit routine */

View File

@ -65,6 +65,60 @@ static const char * const generic_steppings[16] = {
"rev 12", "rev 13", "rev 14", "rev 15",
};
static const char * const xscale_steppings[16] = {
"step A-0", "step A-1", "step B-0", "step C-0",
"step D-0", "rev 5", "rev 6", "rev 7",
"rev 8", "rev 9", "rev 10", "rev 11",
"rev 12", "rev 13", "rev 14", "rev 15",
};
static const char * const i80219_steppings[16] = {
"step A-0", "rev 1", "rev 2", "rev 3",
"rev 4", "rev 5", "rev 6", "rev 7",
"rev 8", "rev 9", "rev 10", "rev 11",
"rev 12", "rev 13", "rev 14", "rev 15",
};
static const char * const i80321_steppings[16] = {
"step A-0", "step B-0", "rev 2", "rev 3",
"rev 4", "rev 5", "rev 6", "rev 7",
"rev 8", "rev 9", "rev 10", "rev 11",
"rev 12", "rev 13", "rev 14", "rev 15",
};
static const char * const i81342_steppings[16] = {
"step A-0", "rev 1", "rev 2", "rev 3",
"rev 4", "rev 5", "rev 6", "rev 7",
"rev 8", "rev 9", "rev 10", "rev 11",
"rev 12", "rev 13", "rev 14", "rev 15",
};
/* Steppings for PXA2[15]0 */
static const char * const pxa2x0_steppings[16] = {
"step A-0", "step A-1", "step B-0", "step B-1",
"step B-2", "step C-0", "rev 6", "rev 7",
"rev 8", "rev 9", "rev 10", "rev 11",
"rev 12", "rev 13", "rev 14", "rev 15",
};
/* Steppings for PXA255/26x.
* rev 5: PXA26x B0, rev 6: PXA255 A0
*/
static const char * const pxa255_steppings[16] = {
"rev 0", "rev 1", "rev 2", "step A-0",
"rev 4", "step B-0", "step A-0", "rev 7",
"rev 8", "rev 9", "rev 10", "rev 11",
"rev 12", "rev 13", "rev 14", "rev 15",
};
/* Stepping for PXA27x */
static const char * const pxa27x_steppings[16] = {
"step A-0", "step A-1", "step B-0", "step B-1",
"step C-0", "rev 5", "rev 6", "rev 7",
"rev 8", "rev 9", "rev 10", "rev 11",
"rev 12", "rev 13", "rev 14", "rev 15",
};
struct cpuidtab {
u_int32_t cpuid;
enum cpu_class cpu_class;
@ -104,6 +158,41 @@ const struct cpuidtab cpuids[] = {
{ CPU_ID_ARM1026EJS, CPU_CLASS_ARM10EJ, "ARM1026EJ-S",
generic_steppings },
{ CPU_ID_80200, CPU_CLASS_XSCALE, "i80200",
xscale_steppings },
{ CPU_ID_80321_400, CPU_CLASS_XSCALE, "i80321 400MHz",
i80321_steppings },
{ CPU_ID_80321_600, CPU_CLASS_XSCALE, "i80321 600MHz",
i80321_steppings },
{ CPU_ID_80321_400_B0, CPU_CLASS_XSCALE, "i80321 400MHz",
i80321_steppings },
{ CPU_ID_80321_600_B0, CPU_CLASS_XSCALE, "i80321 600MHz",
i80321_steppings },
{ CPU_ID_81342, CPU_CLASS_XSCALE, "i81342",
i81342_steppings },
{ CPU_ID_80219_400, CPU_CLASS_XSCALE, "i80219 400MHz",
i80219_steppings },
{ CPU_ID_80219_600, CPU_CLASS_XSCALE, "i80219 600MHz",
i80219_steppings },
{ CPU_ID_PXA27X, CPU_CLASS_XSCALE, "PXA27x",
pxa27x_steppings },
{ CPU_ID_PXA250A, CPU_CLASS_XSCALE, "PXA250",
pxa2x0_steppings },
{ CPU_ID_PXA210A, CPU_CLASS_XSCALE, "PXA210",
pxa2x0_steppings },
{ CPU_ID_PXA250B, CPU_CLASS_XSCALE, "PXA250",
pxa2x0_steppings },
{ CPU_ID_PXA210B, CPU_CLASS_XSCALE, "PXA210",
pxa2x0_steppings },
{ CPU_ID_PXA250C, CPU_CLASS_XSCALE, "PXA255",
pxa255_steppings },
{ CPU_ID_PXA210C, CPU_CLASS_XSCALE, "PXA210",
pxa2x0_steppings },
{ CPU_ID_MV88FR131, CPU_CLASS_MARVELL, "Feroceon 88FR131",
generic_steppings },
@ -125,6 +214,7 @@ const struct cpu_classtab cpu_classes[] = {
{ "ARM9EJ-S", "CPU_ARM9E" }, /* CPU_CLASS_ARM9EJS */
{ "ARM10E", "CPU_ARM10" }, /* CPU_CLASS_ARM10E */
{ "ARM10EJ", "CPU_ARM10" }, /* CPU_CLASS_ARM10EJ */
{ "XScale", "CPU_XSCALE_..." }, /* CPU_CLASS_XSCALE */
{ "Marvell", "CPU_MARVELL" }, /* CPU_CLASS_MARVELL */
};
@ -223,9 +313,13 @@ identify_arm_cpu(void)
case CPU_CLASS_ARM9EJS:
case CPU_CLASS_ARM10E:
case CPU_CLASS_ARM10EJ:
case CPU_CLASS_XSCALE:
case CPU_CLASS_MARVELL:
print_enadis(ctrl & CPU_CONTROL_DC_ENABLE, "DC");
print_enadis(ctrl & CPU_CONTROL_IC_ENABLE, "IC");
#ifdef CPU_XSCALE_81342
print_enadis(ctrl & CPU_CONTROL_L2_ENABLE, "L2");
#endif
#if defined(SOC_MV_KIRKWOOD) || defined(SOC_MV_DISCOVERY)
i = sheeva_control_ext(0, 0);
print_enadis(i & MV_WA_ENABLE, "WA");

View File

@ -406,6 +406,10 @@ static struct rwlock pvh_global_lock;
void pmap_copy_page_offs_generic(vm_paddr_t a_phys, vm_offset_t a_offs,
vm_paddr_t b_phys, vm_offset_t b_offs, int cnt);
#if ARM_MMU_XSCALE == 1
void pmap_copy_page_offs_xscale(vm_paddr_t a_phys, vm_offset_t a_offs,
vm_paddr_t b_phys, vm_offset_t b_offs, int cnt);
#endif
/*
* This list exists for the benefit of pmap_map_chunk(). It keeps track
@ -497,6 +501,176 @@ pmap_pte_init_generic(void)
#endif /* ARM_MMU_GENERIC != 0 */
#if ARM_MMU_XSCALE == 1
#if (ARM_NMMUS > 1) || defined (CPU_XSCALE_CORE3)
static u_int xscale_use_minidata;
#endif
void
pmap_pte_init_xscale(void)
{
uint32_t auxctl;
int write_through = 0;
pte_l1_s_cache_mode = L1_S_B|L1_S_C|L1_S_XSCALE_P;
pte_l1_s_cache_mask = L1_S_CACHE_MASK_xscale;
pte_l2_l_cache_mode = L2_B|L2_C;
pte_l2_l_cache_mask = L2_L_CACHE_MASK_xscale;
pte_l2_s_cache_mode = L2_B|L2_C;
pte_l2_s_cache_mask = L2_S_CACHE_MASK_xscale;
pte_l1_s_cache_mode_pt = L1_S_C;
pte_l2_l_cache_mode_pt = L2_C;
pte_l2_s_cache_mode_pt = L2_C;
#ifdef XSCALE_CACHE_READ_WRITE_ALLOCATE
/*
* The XScale core has an enhanced mode where writes that
* miss the cache cause a cache line to be allocated. This
* is significantly faster than the traditional, write-through
* behavior of this case.
*/
pte_l1_s_cache_mode |= L1_S_XSCALE_TEX(TEX_XSCALE_X);
pte_l2_l_cache_mode |= L2_XSCALE_L_TEX(TEX_XSCALE_X);
pte_l2_s_cache_mode |= L2_XSCALE_T_TEX(TEX_XSCALE_X);
#endif /* XSCALE_CACHE_READ_WRITE_ALLOCATE */
#ifdef XSCALE_CACHE_WRITE_THROUGH
/*
* Some versions of the XScale core have various bugs in
* their cache units, the work-around for which is to run
* the cache in write-through mode. Unfortunately, this
* has a major (negative) impact on performance. So, we
* go ahead and run fast-and-loose, in the hopes that we
* don't line up the planets in a way that will trip the
* bugs.
*
* However, we give you the option to be slow-but-correct.
*/
write_through = 1;
#elif defined(XSCALE_CACHE_WRITE_BACK)
/* force write back cache mode */
write_through = 0;
#elif defined(CPU_XSCALE_PXA2X0)
/*
* Intel PXA2[15]0 processors are known to have a bug in
* write-back cache on revision 4 and earlier (stepping
* A[01] and B[012]). Fixed for C0 and later.
*/
{
uint32_t id, type;
id = cpu_ident();
type = id & ~(CPU_ID_XSCALE_COREREV_MASK|CPU_ID_REVISION_MASK);
if (type == CPU_ID_PXA250 || type == CPU_ID_PXA210) {
if ((id & CPU_ID_REVISION_MASK) < 5) {
/* write through for stepping A0-1 and B0-2 */
write_through = 1;
}
}
}
#endif /* XSCALE_CACHE_WRITE_THROUGH */
if (write_through) {
pte_l1_s_cache_mode = L1_S_C;
pte_l2_l_cache_mode = L2_C;
pte_l2_s_cache_mode = L2_C;
}
#if (ARM_NMMUS > 1)
xscale_use_minidata = 1;
#endif
pte_l2_s_prot_u = L2_S_PROT_U_xscale;
pte_l2_s_prot_w = L2_S_PROT_W_xscale;
pte_l2_s_prot_mask = L2_S_PROT_MASK_xscale;
pte_l1_s_proto = L1_S_PROTO_xscale;
pte_l1_c_proto = L1_C_PROTO_xscale;
pte_l2_s_proto = L2_S_PROTO_xscale;
#ifdef CPU_XSCALE_CORE3
pmap_copy_page_func = pmap_copy_page_generic;
pmap_copy_page_offs_func = pmap_copy_page_offs_generic;
pmap_zero_page_func = pmap_zero_page_generic;
xscale_use_minidata = 0;
/* Make sure it is L2-cachable */
pte_l1_s_cache_mode |= L1_S_XSCALE_TEX(TEX_XSCALE_T);
pte_l1_s_cache_mode_pt = pte_l1_s_cache_mode &~ L1_S_XSCALE_P;
pte_l2_l_cache_mode |= L2_XSCALE_L_TEX(TEX_XSCALE_T) ;
pte_l2_l_cache_mode_pt = pte_l1_s_cache_mode;
pte_l2_s_cache_mode |= L2_XSCALE_T_TEX(TEX_XSCALE_T);
pte_l2_s_cache_mode_pt = pte_l2_s_cache_mode;
#else
pmap_copy_page_func = pmap_copy_page_xscale;
pmap_copy_page_offs_func = pmap_copy_page_offs_xscale;
pmap_zero_page_func = pmap_zero_page_xscale;
#endif
/*
* Disable ECC protection of page table access, for now.
*/
__asm __volatile("mrc p15, 0, %0, c1, c0, 1" : "=r" (auxctl));
auxctl &= ~XSCALE_AUXCTL_P;
__asm __volatile("mcr p15, 0, %0, c1, c0, 1" : : "r" (auxctl));
}
/*
* xscale_setup_minidata:
*
* Set up the mini-data cache clean area. We require the
* caller to allocate the right amount of physically and
* virtually contiguous space.
*/
extern vm_offset_t xscale_minidata_clean_addr;
extern vm_size_t xscale_minidata_clean_size; /* already initialized */
void
xscale_setup_minidata(vm_offset_t l1pt, vm_offset_t va, vm_paddr_t pa)
{
pd_entry_t *pde = (pd_entry_t *) l1pt;
pt_entry_t *pte;
vm_size_t size;
uint32_t auxctl;
xscale_minidata_clean_addr = va;
/* Round it to page size. */
size = (xscale_minidata_clean_size + L2_S_OFFSET) & L2_S_FRAME;
for (; size != 0;
va += L2_S_SIZE, pa += L2_S_SIZE, size -= L2_S_SIZE) {
pte = (pt_entry_t *) kernel_pt_lookup(
pde[L1_IDX(va)] & L1_C_ADDR_MASK);
if (pte == NULL)
panic("xscale_setup_minidata: can't find L2 table for "
"VA 0x%08x", (u_int32_t) va);
pte[l2pte_index(va)] =
L2_S_PROTO | pa | L2_S_PROT(PTE_KERNEL, VM_PROT_READ) |
L2_C | L2_XSCALE_T_TEX(TEX_XSCALE_X);
}
/*
* Configure the mini-data cache for write-back with
* read/write-allocate.
*
* NOTE: In order to reconfigure the mini-data cache, we must
* make sure it contains no valid data! In order to do that,
* we must issue a global data cache invalidate command!
*
* WE ASSUME WE ARE RUNNING UN-CACHED WHEN THIS ROUTINE IS CALLED!
* THIS IS VERY IMPORTANT!
*/
/* Invalidate data and mini-data. */
__asm __volatile("mcr p15, 0, %0, c7, c6, 0" : : "r" (0));
__asm __volatile("mrc p15, 0, %0, c1, c0, 1" : "=r" (auxctl));
auxctl = (auxctl & ~XSCALE_AUXCTL_MD_MASK) | XSCALE_AUXCTL_MD_WB_RWA;
__asm __volatile("mcr p15, 0, %0, c1, c0, 1" : : "r" (auxctl));
}
#endif
/*
* Allocate an L1 translation table for the specified pmap.
* This is called at pmap creation time.
@ -3781,7 +3955,7 @@ pmap_remove(pmap_t pm, vm_offset_t sva, vm_offset_t eva)
* StrongARM accesses to non-cached pages are non-burst making writing
* _any_ bulk data very slow.
*/
#if ARM_MMU_GENERIC != 0
#if ARM_MMU_GENERIC != 0 || defined(CPU_XSCALE_CORE3)
void
pmap_zero_page_generic(vm_paddr_t phys, int off, int size)
{
@ -3810,6 +3984,77 @@ pmap_zero_page_generic(vm_paddr_t phys, int off, int size)
}
#endif /* ARM_MMU_GENERIC != 0 */
#if ARM_MMU_XSCALE == 1
void
pmap_zero_page_xscale(vm_paddr_t phys, int off, int size)
{
if (_arm_bzero && size >= _min_bzero_size &&
_arm_bzero((void *)(phys + off), size, IS_PHYSICAL) == 0)
return;
mtx_lock(&cmtx);
/*
* Hook in the page, zero it, and purge the cache for that
* zeroed page. Invalidate the TLB as needed.
*/
*cdst_pte = L2_S_PROTO | phys |
L2_S_PROT(PTE_KERNEL, VM_PROT_WRITE) |
L2_C | L2_XSCALE_T_TEX(TEX_XSCALE_X); /* mini-data */
PTE_SYNC(cdst_pte);
cpu_tlb_flushD_SE(cdstp);
cpu_cpwait();
if (off || size != PAGE_SIZE)
bzero((void *)(cdstp + off), size);
else
bzero_page(cdstp);
mtx_unlock(&cmtx);
xscale_cache_clean_minidata();
}
/*
* Change the PTEs for the specified kernel mappings such that they
* will use the mini data cache instead of the main data cache.
*/
void
pmap_use_minicache(vm_offset_t va, vm_size_t size)
{
struct l2_bucket *l2b;
pt_entry_t *ptep, *sptep, pte;
vm_offset_t next_bucket, eva;
#if (ARM_NMMUS > 1) || defined(CPU_XSCALE_CORE3)
if (xscale_use_minidata == 0)
return;
#endif
eva = va + size;
while (va < eva) {
next_bucket = L2_NEXT_BUCKET(va);
if (next_bucket > eva)
next_bucket = eva;
l2b = pmap_get_l2_bucket(kernel_pmap, va);
sptep = ptep = &l2b->l2b_kva[l2pte_index(va)];
while (va < next_bucket) {
pte = *ptep;
if (!l2pte_minidata(pte)) {
cpu_dcache_wbinv_range(va, PAGE_SIZE);
cpu_tlb_flushD_SE(va);
*ptep = pte & ~L2_B;
}
ptep++;
va += PAGE_SIZE;
}
PTE_SYNC_RANGE(sptep, (u_int)(ptep - sptep));
}
cpu_cpwait();
}
#endif /* ARM_MMU_XSCALE == 1 */
/*
* pmap_zero_page zeros the specified hardware page by mapping
* the page into KVM and using bzero to clear its contents.
@ -3940,7 +4185,7 @@ pmap_clean_page(struct pv_entry *pv, boolean_t is_src)
* hook points. The same comment regarding cachability as in
* pmap_zero_page also applies here.
*/
#if ARM_MMU_GENERIC != 0
#if ARM_MMU_GENERIC != 0 || defined (CPU_XSCALE_CORE3)
void
pmap_copy_page_generic(vm_paddr_t src, vm_paddr_t dst)
{
@ -4007,6 +4252,72 @@ pmap_copy_page_offs_generic(vm_paddr_t a_phys, vm_offset_t a_offs,
}
#endif /* ARM_MMU_GENERIC != 0 */
#if ARM_MMU_XSCALE == 1
void
pmap_copy_page_xscale(vm_paddr_t src, vm_paddr_t dst)
{
#if 0
/* XXX: Only needed for pmap_clean_page(), which is commented out. */
struct vm_page *src_pg = PHYS_TO_VM_PAGE(src);
#endif
/*
* Clean the source page. Hold the source page's lock for
* the duration of the copy so that no other mappings can
* be created while we have a potentially aliased mapping.
*/
#if 0
/*
* XXX: Not needed while we call cpu_dcache_wbinv_all() in
* pmap_copy_page().
*/
(void) pmap_clean_page(TAILQ_FIRST(&src_pg->md.pv_list), TRUE);
#endif
/*
* Map the pages into the page hook points, copy them, and purge
* the cache for the appropriate page. Invalidate the TLB
* as required.
*/
mtx_lock(&cmtx);
*csrc_pte = L2_S_PROTO | src |
L2_S_PROT(PTE_KERNEL, VM_PROT_READ) |
L2_C | L2_XSCALE_T_TEX(TEX_XSCALE_X); /* mini-data */
PTE_SYNC(csrc_pte);
*cdst_pte = L2_S_PROTO | dst |
L2_S_PROT(PTE_KERNEL, VM_PROT_WRITE) |
L2_C | L2_XSCALE_T_TEX(TEX_XSCALE_X); /* mini-data */
PTE_SYNC(cdst_pte);
cpu_tlb_flushD_SE(csrcp);
cpu_tlb_flushD_SE(cdstp);
cpu_cpwait();
bcopy_page(csrcp, cdstp);
mtx_unlock(&cmtx);
xscale_cache_clean_minidata();
}
void
pmap_copy_page_offs_xscale(vm_paddr_t a_phys, vm_offset_t a_offs,
vm_paddr_t b_phys, vm_offset_t b_offs, int cnt)
{
mtx_lock(&cmtx);
*csrc_pte = L2_S_PROTO | a_phys |
L2_S_PROT(PTE_KERNEL, VM_PROT_READ) |
L2_C | L2_XSCALE_T_TEX(TEX_XSCALE_X);
PTE_SYNC(csrc_pte);
*cdst_pte = L2_S_PROTO | b_phys |
L2_S_PROT(PTE_KERNEL, VM_PROT_WRITE) |
L2_C | L2_XSCALE_T_TEX(TEX_XSCALE_X);
PTE_SYNC(cdst_pte);
cpu_tlb_flushD_SE(csrcp);
cpu_tlb_flushD_SE(cdstp);
cpu_cpwait();
bcopy((char *)csrcp + a_offs, (char *)cdstp + b_offs, cnt);
mtx_unlock(&cmtx);
xscale_cache_clean_minidata();
}
#endif /* ARM_MMU_XSCALE == 1 */
void
pmap_copy_page(vm_page_t src, vm_page_t dst)
{

View File

@ -514,6 +514,13 @@ dab_align(struct trapframe *tf, u_int fsr, u_int far, struct thread *td,
* If pcb_onfault is set, flag the fault and return to the handler.
* If the fault occurred in user mode, give the process a SIGBUS.
*
* Note: On XScale, FAULT_BUSERR_0, FAULT_BUSERR_1, and FAULT_BUSERR_2
* can be flagged as imprecise in the FSR. This causes a real headache
* since some of the machine state is lost. In this case, tf->tf_pc
* may not actually point to the offending instruction. In fact, if
* we've taken a double abort fault, it generally points somewhere near
* the top of "data_abort_entry" in exception.S.
*
* In all other cases, these data aborts are considered fatal.
*/
static int
@ -522,6 +529,52 @@ dab_buserr(struct trapframe *tf, u_int fsr, u_int far, struct thread *td,
{
struct pcb *pcb = td->td_pcb;
#ifdef __XSCALE__
if ((fsr & FAULT_IMPRECISE) != 0 &&
(tf->tf_spsr & PSR_MODE) == PSR_ABT32_MODE) {
/*
* Oops, an imprecise, double abort fault. We've lost the
* r14_abt/spsr_abt values corresponding to the original
* abort, and the spsr saved in the trapframe indicates
* ABT mode.
*/
tf->tf_spsr &= ~PSR_MODE;
/*
* We use a simple heuristic to determine if the double abort
* happened as a result of a kernel or user mode access.
* If the current trapframe is at the top of the kernel stack,
* the fault _must_ have come from user mode.
*/
if (tf != ((struct trapframe *)pcb->pcb_regs.sf_sp) - 1) {
/*
* Kernel mode. We're either about to die a
* spectacular death, or pcb_onfault will come
* to our rescue. Either way, the current value
* of tf->tf_pc is irrelevant.
*/
tf->tf_spsr |= PSR_SVC32_MODE;
if (pcb->pcb_onfault == NULL)
printf("\nKernel mode double abort!\n");
} else {
/*
* User mode. We've lost the program counter at the
* time of the fault (not that it was accurate anyway;
* it's not called an imprecise fault for nothing).
* About all we can do is copy r14_usr to tf_pc and
* hope for the best. The process is about to get a
* SIGBUS, so it's probably history anyway.
*/
tf->tf_spsr |= PSR_USR32_MODE;
tf->tf_pc = tf->tf_usr_lr;
}
}
/* FAR is invalid for imprecise exceptions */
if ((fsr & FAULT_IMPRECISE) != 0)
far = 0;
#endif /* __XSCALE__ */
if (pcb->pcb_onfault) {
tf->tf_r0 = EFAULT;
tf->tf_pc = (register_t)(intptr_t) pcb->pcb_onfault;

View File

@ -105,6 +105,11 @@ cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags)
/* Point the pcb to the top of the stack */
pcb2 = (struct pcb *)
(td2->td_kstack + td2->td_kstack_pages * PAGE_SIZE) - 1;
#ifdef __XSCALE__
#ifndef CPU_XSCALE_CORE3
pmap_use_minicache(td2->td_kstack, td2->td_kstack_pages * PAGE_SIZE);
#endif
#endif
#ifdef VFP
/* Store actual state of VFP */
if (curthread == td1) {
@ -306,6 +311,12 @@ cpu_thread_alloc(struct thread *td)
* the ARM EABI.
*/
td->td_frame = (struct trapframe *)((caddr_t)td->td_pcb) - 1;
#ifdef __XSCALE__
#ifndef CPU_XSCALE_CORE3
pmap_use_minicache(td->td_kstack, td->td_kstack_pages * PAGE_SIZE);
#endif
#endif
}
void

92
sys/arm/conf/CRB Normal file
View File

@ -0,0 +1,92 @@
# GENERIC -- Generic kernel configuration file for FreeBSD/arm
#
# For more information on this file, please read the handbook section on
# Kernel Configuration Files:
#
# https://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
#
# The handbook is also available locally in /usr/share/doc/handbook
# if you've installed the doc distribution, otherwise always see the
# FreeBSD World Wide Web server (https://www.FreeBSD.org/) for the
# latest information.
#
# An exhaustive list of options and more detailed explanations of the
# device lines is also present in the ../../conf/NOTES and NOTES files.
# If you are in doubt as to the purpose or necessity of a line, check first
# in NOTES.
#
# $FreeBSD$
ident CRB
include "std.arm"
options PHYSADDR=0x00000000
options KERNVIRTADDR=0xc0200000 # Used in ldscript.arm
options COUNTS_PER_SEC=400000000
include "../xscale/i8134x/std.crb"
makeoptions MODULES_OVERRIDE=""
makeoptions CONF_CFLAGS=-mcpu=xscale
options HZ=100
#options DEVICE_POLLING
options SCHED_4BSD # 4BSD scheduler
options INET # InterNETworking
options INET6 # IPv6 communications protocols
options TCP_HHOOK # hhook(9) framework for TCP
options FFS # Berkeley Fast Filesystem
options SOFTUPDATES # Enable FFS soft updates support
options UFS_ACL # Support for access control lists
options UFS_DIRHASH # Improve performance on big directories
options NFSCL # Network Filesystem Client
options NFSD # Network Filesystem Server
options NFSLOCKD # Network Lock Manager
options NFS_ROOT # NFS usable as /, requires NFSCL
#options MSDOSFS # MSDOS Filesystem
options GEOM_PART_BSD # BSD partition scheme
options GEOM_PART_MBR # MBR partition scheme
options TMPFS # Efficient memory filesystem
options CD9660 # ISO 9660 Filesystem
#options PROCFS # Process filesystem (requires PSEUDOFS)
options PSEUDOFS # Pseudo-filesystem framework
options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
options KTRACE # ktrace(1) support
options SYSVSHM # SYSV-style shared memory
options SYSVMSG # SYSV-style message queues
options SYSVSEM # SYSV-style semaphores
options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions
options KBD_INSTALL_CDEV # install a CDEV entry in /dev
options BOOTP
options BOOTP_NFSROOT
options BOOTP_NFSV3
options BOOTP_WIRED_TO=em0
options BOOTP_COMPAT
#options PREEMPTION
device loop
device ether
#device saarm
device miibus
device rl
device em
device uart
device pci
device ata
device scbus # SCSI bus (required for ATA/SCSI)
device cd # CD
device da # Direct Access (disks)
device pass # Passthrough device (direct ATA/SCSI access)
device "7seg"
# SCSI Controllers
options XSCALE_CACHE_READ_WRITE_ALLOCATE
device md
device random # Entropy device
device iopwdog
# Floppy drives

82
sys/arm/conf/GUMSTIX Normal file
View File

@ -0,0 +1,82 @@
# GUMSTIX -- Custom configuration for the Gumstix Basix and Connex boards from
# gumstix.com
#
# For more information on this file, please read the handbook section on
# Kernel Configuration Files:
#
# https://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
#
# The handbook is also available locally in /usr/share/doc/handbook
# if you've installed the doc distribution, otherwise always see the
# FreeBSD World Wide Web server (https://www.FreeBSD.org/) for the
# latest information.
#
# An exhaustive list of options and more detailed explanations of the
# device lines is also present in the ../../conf/NOTES and NOTES files.
# If you are in doubt as to the purpose or necessity of a line, check first
# in NOTES.
#
# $FreeBSD$
ident GUMSTIX
include "std.arm"
cpu CPU_XSCALE_PXA2X0
# This probably wants to move somewhere else. Maybe we can create a basic
# PXA2X0 config, then make a GUMSTIX config that includes the basic one,
# adds the smc and smcphy devices and pulls in this hints file.
hints "GUMSTIX.hints"
options PHYSADDR=0xa0000000
options KERNVIRTADDR=0xc0200000 # Used in ldscript.arm
include "../xscale/pxa/std.pxa"
makeoptions MODULES_OVERRIDE=""
options HZ=100
#options DEVICE_POLLING
options SCHED_4BSD # 4BSD scheduler
options INET # InterNETworking
#options INET6 # IPv6 communications protocols
options TCP_HHOOK # hhook(9) framework for TCP
options FFS # Berkeley Fast Filesystem
options SOFTUPDATES # Enable FFS soft updates support
options UFS_ACL # Support for access control lists
options UFS_DIRHASH # Improve performance on big directories
options NFSCL # Network Filesystem Client
#options NFSD # Network Filesystem Server
options NFS_ROOT # NFS usable as /, requires NFSCL
options GEOM_PART_BSD # BSD partition scheme
options GEOM_PART_MBR # MBR partition scheme
options TMPFS # Efficient memory filesystem
#options MSDOSFS # MSDOS Filesystem
#options CD9660 # ISO 9660 Filesystem
#options PROCFS # Process filesystem (requires PSEUDOFS)
options PSEUDOFS # Pseudo-filesystem framework
options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!]
options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
options KTRACE # ktrace(1) support
options SYSVSHM # SYSV-style shared memory
options SYSVMSG # SYSV-style message queues
options SYSVSEM # SYSV-style semaphores
options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions
options KBD_INSTALL_CDEV # install a CDEV entry in /dev
options BOOTP
options BOOTP_NFSROOT
options BOOTP_WIRED_TO=smc0
options BOOTP_COMPAT
options BOOTP_NFSV3
options BOOTP_BLOCKSIZE=4096
options PREEMPTION
device loop
device ether
device mii
device mii_bitbang
device smc
device smcphy
device uart
device uart_ns8250
device md
device random # Entropy device

25
sys/arm/conf/GUMSTIX-QEMU Normal file
View File

@ -0,0 +1,25 @@
# GUMSTIX-QEMU -- Custom configuration for the QEMU emulated Gumstix target
#
# For more information on this file, please read the handbook section on
# Kernel Configuration Files:
#
# https://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
#
# The handbook is also available locally in /usr/share/doc/handbook
# if you've installed the doc distribution, otherwise always see the
# FreeBSD World Wide Web server (https://www.FreeBSD.org/) for the
# latest information.
#
# An exhaustive list of options and more detailed explanations of the
# device lines is also present in the ../../conf/NOTES and NOTES files.
# If you are in doubt as to the purpose or necessity of a line, check first
# in NOTES.
#
# $FreeBSD$
include GUMSTIX
ident GUMSTIX-QEMU
options QEMU_WORKAROUNDS
nooptions ARM_CACHE_LOCK_ENABLE # QEMU does not implement this

View File

@ -0,0 +1,19 @@
# $FreeBSD$
# Make sure we don't trample important bits in the UART registers.
hint.uart.0.ier_mask="0xe0"
hint.uart.0.ier_rxbits="0x1d"
hint.uart.1.ier_mask="0xe0"
hint.uart.1.ier_rxbits="0x1d"
hint.uart.2.ier_mask="0xe0"
hint.uart.2.ier_rxbits="0x1d"
# SMSC LAN91C111s found on the netCF, netMMC and netDUO boards.
hint.smc.0.at="smi0"
hint.smc.0.mem="0x04000300"
hint.smc.0.size="0x10"
hint.smc.0.irq="100"
hint.smc.1.at="smi0"
hint.smc.1.mem="0x08000300"
hint.smc.1.size="0x10"
hint.smc.1.irq="91"

View File

@ -13,6 +13,9 @@ files "../mv/discovery/files.db78xxx"
files "../mv/kirkwood/files.kirkwood"
files "../mv/orion/files.db88f5xxx"
files "../mv/orion/files.ts7800"
files "../xscale/i8134x/files.crb"
files "../xscale/i8134x/files.i81342"
files "../xscale/pxa/files.pxa"
options PHYSADDR=0x00000000

View File

@ -108,6 +108,11 @@
/* Next three nybbles are part number */
#define CPU_ID_PARTNO_MASK 0x0000fff0
/* Intel XScale has sub fields in part number */
#define CPU_ID_XSCALE_COREGEN_MASK 0x0000e000 /* core generation */
#define CPU_ID_XSCALE_COREREV_MASK 0x00001c00 /* core revision */
#define CPU_ID_XSCALE_PRODUCT_MASK 0x000003f0 /* product number */
/* And finally, the revision number. */
#define CPU_ID_REVISION_MASK 0x0000000f
@ -313,6 +318,18 @@
#define ARM1176_AUXCTL_FSD 0x40000000 /* force speculative ops disable */
#define ARM1176_AUXCTL_FIO 0x80000000 /* low intr latency override */
/* XScale Auxillary Control Register (CP15 register 1, opcode2 1) */
#define XSCALE_AUXCTL_K 0x00000001 /* dis. write buffer coalescing */
#define XSCALE_AUXCTL_P 0x00000002 /* ECC protect page table access */
/* Note: XSCale core 3 uses those for LLR DCcahce attributes */
#define XSCALE_AUXCTL_MD_WB_RA 0x00000000 /* mini-D$ wb, read-allocate */
#define XSCALE_AUXCTL_MD_WB_RWA 0x00000010 /* mini-D$ wb, read/write-allocate */
#define XSCALE_AUXCTL_MD_WT 0x00000020 /* mini-D$ wt, read-allocate */
#define XSCALE_AUXCTL_MD_MASK 0x00000030
/* Xscale Core 3 only */
#define XSCALE_AUXCTL_LLR 0x00000400 /* Enable L2 for LLR Cache */
/* Marvell Extra Features Register (CP15 register 1, opcode2 0) */
#define MV_DC_REPLACE_LOCK 0x80000000 /* Replace DCache Lock */
#define MV_DC_STREAM_ENABLE 0x20000000 /* DCache Streaming Switch */
@ -393,6 +410,7 @@
#define FAULT_PERM_S 0x0d /* Permission -- Section */
#define FAULT_PERM_P 0x0f /* Permission -- Page */
#define FAULT_IMPRECISE 0x400 /* Imprecise exception (XSCALE) */
#define FAULT_EXTERNAL 0x400 /* External abort (armv6+) */
#define FAULT_WNR 0x800 /* Write-not-Read access (armv6+) */

View File

@ -95,6 +95,9 @@ _WF1(cp15_cpacr_set, CP15_CPACR(%0))
_RF0(cp15_dfsr_get, CP15_DFSR(%0))
_RF0(cp15_ttbr_get, CP15_TTBR0(%0))
_RF0(cp15_dfar_get, CP15_DFAR(%0))
/* XScale */
_RF0(cp15_actlr_get, CP15_ACTLR(%0))
_WF1(cp15_actlr_set, CP15_ACTLR(%0))
/*CPU id registers */
_RF0(cp15_midr_get, CP15_MIDR(%0))

View File

@ -306,7 +306,8 @@ void armv5_ec_idcache_wbinv_range(vm_offset_t, vm_size_t);
#endif
#if defined(CPU_ARM9) || defined(CPU_ARM9E) || \
defined(CPU_FA526)
defined(CPU_FA526) || \
defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_81342)
void armv4_tlb_flushID (void);
void armv4_tlb_flushD (void);
@ -316,6 +317,71 @@ void armv4_drain_writebuf (void);
void armv4_idcache_inv_all (void);
#endif
#if defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_81342)
void xscale_cpwait (void);
void xscale_cpu_sleep (int mode);
u_int xscale_control (u_int clear, u_int bic);
void xscale_setttb (u_int ttb);
void xscale_tlb_flushID_SE (u_int va);
void xscale_cache_flushID (void);
void xscale_cache_flushI (void);
void xscale_cache_flushD (void);
void xscale_cache_flushD_SE (u_int entry);
void xscale_cache_cleanID (void);
void xscale_cache_cleanD (void);
void xscale_cache_cleanD_E (u_int entry);
void xscale_cache_clean_minidata (void);
void xscale_cache_purgeID (void);
void xscale_cache_purgeID_E (u_int entry);
void xscale_cache_purgeD (void);
void xscale_cache_purgeD_E (u_int entry);
void xscale_cache_syncI (void);
void xscale_cache_cleanID_rng (vm_offset_t start, vm_size_t end);
void xscale_cache_cleanD_rng (vm_offset_t start, vm_size_t end);
void xscale_cache_purgeID_rng (vm_offset_t start, vm_size_t end);
void xscale_cache_purgeD_rng (vm_offset_t start, vm_size_t end);
void xscale_cache_syncI_rng (vm_offset_t start, vm_size_t end);
void xscale_cache_flushD_rng (vm_offset_t start, vm_size_t end);
void xscale_context_switch (void);
void xscale_setup (void);
#endif /* CPU_XSCALE_PXA2X0 */
#ifdef CPU_XSCALE_81342
void xscalec3_l2cache_purge (void);
void xscalec3_cache_purgeID (void);
void xscalec3_cache_purgeD (void);
void xscalec3_cache_cleanID (void);
void xscalec3_cache_cleanD (void);
void xscalec3_cache_syncI (void);
void xscalec3_cache_purgeID_rng (vm_offset_t start, vm_size_t end);
void xscalec3_cache_purgeD_rng (vm_offset_t start, vm_size_t end);
void xscalec3_cache_cleanID_rng (vm_offset_t start, vm_size_t end);
void xscalec3_cache_cleanD_rng (vm_offset_t start, vm_size_t end);
void xscalec3_cache_syncI_rng (vm_offset_t start, vm_size_t end);
void xscalec3_l2cache_flush_rng (vm_offset_t, vm_size_t);
void xscalec3_l2cache_clean_rng (vm_offset_t start, vm_size_t end);
void xscalec3_l2cache_purge_rng (vm_offset_t start, vm_size_t end);
void xscalec3_setttb (u_int ttb);
void xscalec3_context_switch (void);
#endif /* CPU_XSCALE_81342 */
/*
* Macros for manipulating CPU interrupts
*/

View File

@ -68,7 +68,12 @@ int intr_pic_ipi_setup(u_int, const char *, intr_ipi_handler_t *, void *);
#else /* INTRNG */
/* XXX move to std.* files? */
#if defined(SOC_MV_DISCOVERY)
#ifdef CPU_XSCALE_81342
#define NIRQ 128
#elif defined(CPU_XSCALE_PXA2X0)
#include <arm/xscale/pxa/pxareg.h>
#define NIRQ IRQ_GPIO_MAX
#elif defined(SOC_MV_DISCOVERY)
#define NIRQ 96
#elif defined(CPU_ARM9) || defined(SOC_MV_KIRKWOOD)
#define NIRQ 64

View File

@ -62,7 +62,7 @@ enum cpu_class {
CPU_CLASS_ARM10EJ,
CPU_CLASS_CORTEXA,
CPU_CLASS_KRAIT,
CPU_CLASS_reserved, /* XXX audit and remove ? */
CPU_CLASS_XSCALE,
CPU_CLASS_ARM11J,
CPU_CLASS_MARVELL
};

View File

@ -63,7 +63,13 @@
#define ARM_MMU_GENERIC 0
#endif
#define ARM_NMMUS ARM_MMU_GENERIC
#if (defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_81342))
#define ARM_MMU_XSCALE 1
#else
#define ARM_MMU_XSCALE 0
#endif
#define ARM_NMMUS (ARM_MMU_GENERIC + ARM_MMU_XSCALE)
#if ARM_NMMUS == 0 && !defined(KLD_MODULE) && defined(_KERNEL)
#error ARM_NMMUS is 0
#endif
@ -271,15 +277,35 @@ extern int pmap_needs_pte_sync;
*/
#define L1_S_CACHE_MASK_generic (L1_S_B|L1_S_C)
#define L1_S_CACHE_MASK_xscale (L1_S_B|L1_S_C|L1_S_XSCALE_TEX(TEX_XSCALE_X)|\
L1_S_XSCALE_TEX(TEX_XSCALE_T))
#define L2_L_CACHE_MASK_generic (L2_B|L2_C)
#define L2_L_CACHE_MASK_xscale (L2_B|L2_C|L2_XSCALE_L_TEX(TEX_XSCALE_X) | \
L2_XSCALE_L_TEX(TEX_XSCALE_T))
#define L2_S_PROT_U_generic (L2_AP(AP_U))
#define L2_S_PROT_W_generic (L2_AP(AP_W))
#define L2_S_PROT_MASK_generic (L2_S_PROT_U|L2_S_PROT_W)
#define L2_S_PROT_U_xscale (L2_AP0(AP_U))
#define L2_S_PROT_W_xscale (L2_AP0(AP_W))
#define L2_S_PROT_MASK_xscale (L2_S_PROT_U|L2_S_PROT_W)
#define L2_S_CACHE_MASK_generic (L2_B|L2_C)
#define L2_S_CACHE_MASK_xscale (L2_B|L2_C|L2_XSCALE_T_TEX(TEX_XSCALE_X)| \
L2_XSCALE_T_TEX(TEX_XSCALE_X))
#define L1_S_PROTO_generic (L1_TYPE_S | L1_S_IMP)
#define L1_S_PROTO_xscale (L1_TYPE_S)
#define L1_C_PROTO_generic (L1_TYPE_C | L1_C_IMP2)
#define L1_C_PROTO_xscale (L1_TYPE_C)
#define L2_L_PROTO (L2_TYPE_L)
#define L2_S_PROTO_generic (L2_TYPE_S)
#define L2_S_PROTO_xscale (L2_TYPE_XSCALE_XS)
/*
* User-visible names for the ones that vary with MMU class.
@ -312,9 +338,29 @@ extern int pmap_needs_pte_sync;
#define L1_S_PROTO L1_S_PROTO_generic
#define L1_C_PROTO L1_C_PROTO_generic
#define L2_S_PROTO L2_S_PROTO_generic
#endif
#elif ARM_MMU_XSCALE == 1
#define L2_S_PROT_U L2_S_PROT_U_xscale
#define L2_S_PROT_W L2_S_PROT_W_xscale
#define L2_S_PROT_MASK L2_S_PROT_MASK_xscale
#define L1_S_CACHE_MASK L1_S_CACHE_MASK_xscale
#define L2_L_CACHE_MASK L2_L_CACHE_MASK_xscale
#define L2_S_CACHE_MASK L2_S_CACHE_MASK_xscale
#define L1_S_PROTO L1_S_PROTO_xscale
#define L1_C_PROTO L1_C_PROTO_xscale
#define L2_S_PROTO L2_S_PROTO_xscale
#endif /* ARM_NMMUS > 1 */
#if defined(CPU_XSCALE_81342)
#define CPU_XSCALE_CORE3
#define PMAP_NEEDS_PTE_SYNC 1
#define PMAP_INCLUDE_PTE_SYNC
#else
#define PMAP_NEEDS_PTE_SYNC 0
#endif
/*
* These macros return various bits based on kernel/user and protection.
@ -411,13 +457,27 @@ extern void (*pmap_copy_page_offs_func)(vm_paddr_t a_phys,
vm_offset_t a_offs, vm_paddr_t b_phys, vm_offset_t b_offs, int cnt);
extern void (*pmap_zero_page_func)(vm_paddr_t, int, int);
#if ARM_MMU_GENERIC != 0
#if ARM_MMU_GENERIC != 0 || defined(CPU_XSCALE_81342)
void pmap_copy_page_generic(vm_paddr_t, vm_paddr_t);
void pmap_zero_page_generic(vm_paddr_t, int, int);
void pmap_pte_init_generic(void);
#endif /* ARM_MMU_GENERIC != 0 */
#if ARM_MMU_XSCALE == 1
void pmap_copy_page_xscale(vm_paddr_t, vm_paddr_t);
void pmap_zero_page_xscale(vm_paddr_t, int, int);
void pmap_pte_init_xscale(void);
void xscale_setup_minidata(vm_offset_t, vm_offset_t, vm_offset_t);
void pmap_use_minicache(vm_offset_t, vm_size_t);
#endif /* ARM_MMU_XSCALE == 1 */
#if defined(CPU_XSCALE_81342)
#define ARM_HAVE_SUPERSECTIONS
#endif
#define PTE_KERNEL 0
#define PTE_USER 1
#define l1pte_valid(pde) ((pde) != 0)
@ -428,6 +488,9 @@ void pmap_pte_init_generic(void);
#define l2pte_index(v) (((v) & L1_S_OFFSET) >> L2_S_SHIFT)
#define l2pte_valid(pte) ((pte) != 0)
#define l2pte_pa(pte) ((pte) & L2_S_FRAME)
#define l2pte_minidata(pte) (((pte) & \
(L2_B | L2_C | L2_XSCALE_T_TEX(TEX_XSCALE_X)))\
== (L2_C | L2_XSCALE_T_TEX(TEX_XSCALE_X)))
/* L1 and L2 page table macros */
#define pmap_pde_v(pde) l1pte_valid(*(pde))

View File

@ -31,13 +31,15 @@
#ifndef _MACHINE_PMC_MDEP_H_
#define _MACHINE_PMC_MDEP_H_
#define PMC_MDEP_CLASS_INDEX_XSCALE 1
#define PMC_MDEP_CLASS_INDEX_ARMV7 1
/*
* On the ARM platform we support the following PMCs.
*
* XSCALE Intel XScale processors
* ARMV7 ARM Cortex-A processors
*/
#include <dev/hwpmc/hwpmc_xscale.h>
#include <dev/hwpmc/hwpmc_armv7.h>
union pmc_md_op_pmcallocate {
@ -50,6 +52,7 @@ union pmc_md_op_pmcallocate {
#ifdef _KERNEL
union pmc_md_pmc {
struct pmc_md_xscale_pmc pm_xscale;
struct pmc_md_armv7_pmc pm_armv7;
};
@ -77,6 +80,8 @@ union pmc_md_pmc {
/*
* Prototypes
*/
struct pmc_mdep *pmc_xscale_initialize(void);
void pmc_xscale_finalize(struct pmc_mdep *_md);
struct pmc_mdep *pmc_armv7_initialize(void);
void pmc_armv7_finalize(struct pmc_mdep *_md);
#endif /* _KERNEL */

View File

@ -180,6 +180,9 @@ typedef pt_entry_t pt2_entry_t; /* compatibility with v6 */
#define L1_S_APX (1 << 15)
#define L1_SHARED (1 << 16)
#define L1_S_XSCALE_P 0x00000200 /* ECC enable for this section */
#define L1_S_XSCALE_TEX(x) ((x) << 12) /* Type Extension */
#define L1_S_SUPERSEC ((1) << 18) /* Section is a super-section. */
/* L1 Coarse Descriptor */
@ -190,6 +193,8 @@ typedef pt_entry_t pt2_entry_t; /* compatibility with v6 */
#define L1_C_DOM_MASK L1_C_DOM(0xf)
#define L1_C_ADDR_MASK 0xfffffc00 /* phys address of L2 Table */
#define L1_C_XSCALE_P 0x00000200 /* ECC enable for this section */
/* L1 Fine Descriptor */
#define L1_F_IMP0 0x00000004 /* implementation defined */
#define L1_F_IMP1 0x00000008 /* implementation defined */
@ -198,6 +203,8 @@ typedef pt_entry_t pt2_entry_t; /* compatibility with v6 */
#define L1_F_DOM_MASK L1_F_DOM(0xf)
#define L1_F_ADDR_MASK 0xfffff000 /* phys address of L2 Table */
#define L1_F_XSCALE_P 0x00000200 /* ECC enable for this section */
/*
* ARM L2 Descriptors
*/
@ -207,6 +214,15 @@ typedef pt_entry_t pt2_entry_t; /* compatibility with v6 */
#define L2_TYPE_S 0x02 /* Small Page */
#define L2_TYPE_T 0x03 /* Tiny Page */
#define L2_TYPE_MASK 0x03 /* mask of type bits */
/*
* This L2 Descriptor type is available on XScale processors
* when using a Coarse L1 Descriptor. The Extended Small
* Descriptor has the same format as the XScale Tiny Descriptor,
* but describes a 4K page, rather than a 1K page.
*/
#define L2_TYPE_XSCALE_XS 0x03 /* XScale Extended Small Page */
#define L2_B 0x00000004 /* Bufferable page */
#define L2_C 0x00000008 /* Cacheable page */
#define L2_AP0(x) ((x) << 4) /* access permissions (sp 0) */
@ -222,6 +238,10 @@ typedef pt_entry_t pt2_entry_t; /* compatibility with v6 */
#define L2_S_TEX_MASK (0x7 << 6) /* Type Extension */
#define L2_S_TEX(x) (((x) & 0x7) << 6)
#define L2_XSCALE_L_TEX(x) ((x) << 12) /* Type Extension */
#define L2_XSCALE_L_S(x) (1 << 15) /* Shared */
#define L2_XSCALE_T_TEX(x) ((x) << 6) /* Type Extension */
/*
* Access Permissions for L1 and L2 Descriptors.
*/
@ -248,6 +268,30 @@ typedef pt_entry_t pt2_entry_t; /* compatibility with v6 */
#define DOMAIN_RESERVED 0x02 /* reserved */
#define DOMAIN_MANAGER 0x03 /* manager */
/*
* Type Extension bits for XScale processors.
*
* Behavior of C and B when X == 0:
*
* C B Cacheable Bufferable Write Policy Line Allocate Policy
* 0 0 N N - -
* 0 1 N Y - -
* 1 0 Y Y Write-through Read Allocate
* 1 1 Y Y Write-back Read Allocate
*
* Behavior of C and B when X == 1:
* C B Cacheable Bufferable Write Policy Line Allocate Policy
* 0 0 - - - - DO NOT USE
* 0 1 N Y - -
* 1 0 Mini-Data - - -
* 1 1 Y Y Write-back R/W Allocate
*/
#define TEX_XSCALE_X 0x01 /* X modifies C and B */
#define TEX_XSCALE_E 0x02
#define TEX_XSCALE_T 0x04
/* Xscale core 3 */
/*
*
* Cache attributes with L2 present, S = 0

View File

@ -0,0 +1,333 @@
/* $NetBSD: hpc_machdep.c,v 1.70 2003/09/16 08:18:22 agc Exp $ */
/*-
* SPDX-License-Identifier: BSD-4-Clause
*
* Copyright (c) 1994-1998 Mark Brinicombe.
* Copyright (c) 1994 Brini.
* All rights reserved.
*
* This code is derived from software written for Brini by Mark Brinicombe
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Brini.
* 4. The name of the company nor the name of the author may be used to
* endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* RiscBSD kernel project
*
* machdep.c
*
* Machine dependent functions for kernel setup
*
* This file needs a lot of work.
*
* Created : 17/09/94
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_kstack_pages.h"
#define _ARM32_BUS_DMA_PRIVATE
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/sysproto.h>
#include <sys/signalvar.h>
#include <sys/imgact.h>
#include <sys/kernel.h>
#include <sys/ktr.h>
#include <sys/linker.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mutex.h>
#include <sys/pcpu.h>
#include <sys/proc.h>
#include <sys/ptrace.h>
#include <sys/cons.h>
#include <sys/bio.h>
#include <sys/bus.h>
#include <sys/buf.h>
#include <sys/exec.h>
#include <sys/kdb.h>
#include <sys/msgbuf.h>
#include <sys/devmap.h>
#include <machine/reg.h>
#include <machine/cpu.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <vm/vm_object.h>
#include <vm/vm_page.h>
#include <vm/vm_map.h>
#include <machine/vmparam.h>
#include <machine/pcb.h>
#include <machine/undefined.h>
#include <machine/machdep.h>
#include <machine/metadata.h>
#include <machine/armreg.h>
#include <machine/bus.h>
#include <machine/physmem.h>
#include <sys/reboot.h>
#include <arm/xscale/i8134x/i80321var.h> /* For i80321_calibrate_delay() */
#include <arm/xscale/i8134x/i81342reg.h>
#include <arm/xscale/i8134x/i81342var.h>
#include <arm/xscale/i8134x/obiovar.h>
#define KERNEL_PT_SYS 0 /* Page table for mapping proc0 zero page */
#define KERNEL_PT_IOPXS 1
#define KERNEL_PT_BEFOREKERN 2
#define KERNEL_PT_AFKERNEL 3 /* L2 table for mapping after kernel */
#define KERNEL_PT_AFKERNEL_NUM 9
/* this should be evenly divisable by PAGE_SIZE / L2_TABLE_SIZE_REAL (or 4) */
#define NUM_KERNEL_PTS (KERNEL_PT_AFKERNEL + KERNEL_PT_AFKERNEL_NUM)
struct pv_addr kernel_pt_table[NUM_KERNEL_PTS];
/* Physical and virtual addresses for some global pages */
struct pv_addr systempage;
struct pv_addr msgbufpv;
struct pv_addr irqstack;
struct pv_addr undstack;
struct pv_addr abtstack;
struct pv_addr kernelstack;
/* Static device mappings. */
static const struct devmap_entry iq81342_devmap[] = {
{
IOP34X_VADDR,
IOP34X_HWADDR,
IOP34X_SIZE,
},
{
/*
* Cheat and map a whole section, this will bring
* both PCI-X and PCI-E outbound I/O
*/
rounddown2(IOP34X_PCIX_OIOBAR_VADDR, 0x100000),
rounddown2(IOP34X_PCIX_OIOBAR, 0x100000),
0x100000,
},
{
IOP34X_PCE1_VADDR,
IOP34X_PCE1,
IOP34X_PCE1_SIZE,
},
{
0,
0,
0,
}
};
#define SDRAM_START 0x00000000
extern vm_offset_t xscale_cache_clean_addr;
void *
initarm(struct arm_boot_params *abp)
{
struct pv_addr kernel_l1pt;
struct pv_addr dpcpu;
int loop, i;
u_int l1pagetable;
vm_offset_t freemempos;
vm_offset_t freemem_pt;
vm_offset_t afterkern;
vm_offset_t freemem_after;
vm_offset_t lastaddr;
uint32_t memsize, memstart;
lastaddr = parse_boot_param(abp);
arm_physmem_kernaddr = abp->abp_physaddr;
set_cpufuncs();
pcpu_init(pcpup, 0, sizeof(struct pcpu));
PCPU_SET(curthread, &thread0);
/* Do basic tuning, hz etc */
init_param1();
freemempos = 0x00200000;
/* Define a macro to simplify memory allocation */
#define valloc_pages(var, np) \
alloc_pages((var).pv_pa, (np)); \
(var).pv_va = (var).pv_pa + 0xc0000000;
#define alloc_pages(var, np) \
freemempos -= (np * PAGE_SIZE); \
(var) = freemempos; \
memset((char *)(var), 0, ((np) * PAGE_SIZE));
while (((freemempos - L1_TABLE_SIZE) & (L1_TABLE_SIZE - 1)) != 0)
freemempos -= PAGE_SIZE;
valloc_pages(kernel_l1pt, L1_TABLE_SIZE / PAGE_SIZE);
for (loop = 0; loop < NUM_KERNEL_PTS; ++loop) {
if (!(loop % (PAGE_SIZE / L2_TABLE_SIZE_REAL))) {
valloc_pages(kernel_pt_table[loop],
L2_TABLE_SIZE / PAGE_SIZE);
} else {
kernel_pt_table[loop].pv_pa = freemempos +
(loop % (PAGE_SIZE / L2_TABLE_SIZE_REAL)) *
L2_TABLE_SIZE_REAL;
kernel_pt_table[loop].pv_va =
kernel_pt_table[loop].pv_pa + 0xc0000000;
}
}
freemem_pt = freemempos;
freemempos = 0x00100000;
/*
* Allocate a page for the system page mapped to V0x00000000
* This page will just contain the system vectors and can be
* shared by all processes.
*/
valloc_pages(systempage, 1);
/* Allocate dynamic per-cpu area. */
valloc_pages(dpcpu, DPCPU_SIZE / PAGE_SIZE);
dpcpu_init((void *)dpcpu.pv_va, 0);
/* Allocate stacks for all modes */
valloc_pages(irqstack, IRQ_STACK_SIZE);
valloc_pages(abtstack, ABT_STACK_SIZE);
valloc_pages(undstack, UND_STACK_SIZE);
valloc_pages(kernelstack, kstack_pages);
valloc_pages(msgbufpv, round_page(msgbufsize) / PAGE_SIZE);
/*
* Now we start construction of the L1 page table
* We start by mapping the L2 page tables into the L1.
* This means that we can replace L1 mappings later on if necessary
*/
l1pagetable = kernel_l1pt.pv_va;
/* Map the L2 pages tables in the L1 page table */
pmap_link_l2pt(l1pagetable, rounddown2(ARM_VECTORS_HIGH, 0x00100000),
&kernel_pt_table[KERNEL_PT_SYS]);
pmap_map_chunk(l1pagetable, KERNBASE, SDRAM_START, 0x100000,
VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
pmap_map_chunk(l1pagetable, KERNBASE + 0x100000, SDRAM_START + 0x100000,
0x100000, VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE);
pmap_map_chunk(l1pagetable, KERNBASE + 0x200000, SDRAM_START + 0x200000,
rounddown2(((uint32_t)(lastaddr) - KERNBASE - 0x200000) + L1_S_SIZE, L1_S_SIZE),
VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
freemem_after = rounddown2((int)lastaddr + PAGE_SIZE, PAGE_SIZE);
afterkern = round_page(rounddown2((vm_offset_t)lastaddr + L1_S_SIZE, L1_S_SIZE));
for (i = 0; i < KERNEL_PT_AFKERNEL_NUM; i++) {
pmap_link_l2pt(l1pagetable, afterkern + i * 0x00100000,
&kernel_pt_table[KERNEL_PT_AFKERNEL + i]);
}
/* Map the vector page. */
pmap_map_entry(l1pagetable, ARM_VECTORS_HIGH, systempage.pv_pa,
VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
devmap_bootstrap(l1pagetable, iq81342_devmap);
/*
* Give the XScale global cache clean code an appropriately
* sized chunk of unmapped VA space starting at 0xff000000
* (our device mappings end before this address).
*/
xscale_cache_clean_addr = 0xff000000U;
cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT);
cpu_setttb(kernel_l1pt.pv_pa);
cpu_tlb_flushID();
cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2));
/*
* Pages were allocated during the secondary bootstrap for the
* stacks for different CPU modes.
* We must now set the r13 registers in the different CPU modes to
* point to these stacks.
* Since the ARM stacks use STMFD etc. we must set r13 to the top end
* of the stack memory.
*/
set_stackptrs(0);
/*
* We must now clean the cache again....
* Cleaning may be done by reading new data to displace any
* dirty data in the cache. This will have happened in cpu_setttb()
* but since we are boot strapping the addresses used for the read
* may have just been remapped and thus the cache could be out
* of sync. A re-clean after the switch will cure this.
* After booting there are no gross relocations of the kernel thus
* this problem will not occur after initarm().
*/
cpu_idcache_wbinv_all();
cpu_setup();
i80321_calibrate_delay();
i81342_sdram_bounds(arm_base_bs_tag, IOP34X_VADDR, &memstart, &memsize);
physmem = memsize / PAGE_SIZE;
cninit();
/* Set stack for exception handlers */
undefined_init();
init_proc0(kernelstack.pv_va);
arm_vector_init(ARM_VECTORS_HIGH, ARM_VEC_ALL);
pmap_curmaxkvaddr = afterkern + PAGE_SIZE;
vm_max_kernel_address = 0xe0000000;
pmap_bootstrap(pmap_curmaxkvaddr, &kernel_l1pt);
msgbufp = (void*)msgbufpv.pv_va;
msgbufinit(msgbufp, msgbufsize);
mutex_init();
/*
* Add the physical ram we have available.
*
* Exclude the kernel (and all the things we allocated which immediately
* follow the kernel) from the VM allocation pool but not from crash
* dumps. virtual_avail is a global variable which tracks the kva we've
* "allocated" while setting up pmaps.
*
* Prepare the list of physical memory available to the vm subsystem.
*/
arm_physmem_hardware_region(SDRAM_START, memsize);
arm_physmem_exclude_region(freemem_pt, abp->abp_physaddr -
freemem_pt, EXFLAG_NOALLOC);
arm_physmem_exclude_region(freemempos, abp->abp_physaddr - 0x100000 -
freemempos, EXFLAG_NOALLOC);
arm_physmem_exclude_region(abp->abp_physaddr,
virtual_avail - KERNVIRTADDR, EXFLAG_NOALLOC);
arm_physmem_init_kernel_globals();
init_param2(physmem);
kdb_init();
return ((void *)(kernelstack.pv_va + USPACE_SVC_STACK_TOP -
sizeof(struct pcb)));
}

View File

@ -0,0 +1,3 @@
# $FreeBSD$
arm/xscale/i8134x/crb_machdep.c standard
arm/xscale/i8134x/iq81342_7seg.c optional 7seg

View File

@ -0,0 +1,12 @@
# $FreeBSD$
arm/arm/bus_space_base.c standard
arm/xscale/i8134x/i80321_timer.c standard
arm/xscale/i8134x/i80321_wdog.c optional iopwdog
arm/xscale/i8134x/i81342.c standard
arm/xscale/i8134x/i81342_mcu.c standard
arm/xscale/i8134x/i81342_pci.c optional pci
arm/xscale/i8134x/i81342_space.c standard
arm/xscale/i8134x/obio.c standard
arm/xscale/i8134x/uart_bus_i81342.c optional uart
arm/xscale/i8134x/uart_cpu_i81342.c optional uart
dev/uart/uart_dev_ns8250.c optional uart

View File

@ -0,0 +1,486 @@
/* $NetBSD: i80321_timer.c,v 1.7 2003/07/27 04:52:28 thorpej Exp $ */
/*-
* Copyright (c) 2001, 2002 Wasabi Systems, Inc.
* All rights reserved.
*
* Written by Jason R. Thorpe for Wasabi Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed for the NetBSD Project by
* Wasabi Systems, Inc.
* 4. The name of Wasabi Systems, Inc. may not be used to endorse
* or promote products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Timer/clock support for the Intel i80321 I/O processor.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/time.h>
#include <sys/bus.h>
#include <sys/resource.h>
#include <sys/rman.h>
#include <sys/timetc.h>
#include <machine/armreg.h>
#include <machine/bus.h>
#include <machine/cpu.h>
#include <machine/frame.h>
#include <machine/resource.h>
#include <machine/intr.h>
#include <arm/xscale/i8134x/i80321reg.h>
#include <arm/xscale/i8134x/i80321var.h>
#ifdef CPU_XSCALE_81342
#define ICU_INT_TIMER0 (8) /* XXX: Can't include i81342reg.h because
definitions overrides the ones from i80321reg.h
*/
#endif
#include "opt_timer.h"
void (*i80321_hardclock_hook)(void) = NULL;
struct i80321_timer_softc {
device_t dev;
} timer_softc;
static unsigned i80321_timer_get_timecount(struct timecounter *tc);
static uint32_t counts_per_hz;
#if defined(XSCALE_DISABLE_CCNT) || defined(CPU_XSCALE_81342)
static uint32_t offset;
static uint32_t last = -1;
#endif
static int ticked = 0;
#ifndef COUNTS_PER_SEC
#define COUNTS_PER_SEC 200000000 /* 200MHz */
#endif
#define COUNTS_PER_USEC (COUNTS_PER_SEC / 1000000)
static struct timecounter i80321_timer_timecounter = {
i80321_timer_get_timecount, /* get_timecount */
NULL, /* no poll_pps */
~0u, /* counter_mask */
#if defined(XSCALE_DISABLE_CCNT) || defined(CPU_XSCALE_81342)
COUNTS_PER_SEC,
#else
COUNTS_PER_SEC * 3, /* frequency */
#endif
"i80321 timer", /* name */
1000 /* quality */
};
static int
i80321_timer_probe(device_t dev)
{
device_set_desc(dev, "i80321 timer");
return (0);
}
static int
i80321_timer_attach(device_t dev)
{
timer_softc.dev = dev;
return (0);
}
static device_method_t i80321_timer_methods[] = {
DEVMETHOD(device_probe, i80321_timer_probe),
DEVMETHOD(device_attach, i80321_timer_attach),
{0, 0},
};
static driver_t i80321_timer_driver = {
"itimer",
i80321_timer_methods,
sizeof(struct i80321_timer_softc),
};
static devclass_t i80321_timer_devclass;
DRIVER_MODULE(itimer, iq, i80321_timer_driver, i80321_timer_devclass, 0, 0);
int clockhandler(void *);
static __inline uint32_t
tmr1_read(void)
{
uint32_t rv;
#ifdef CPU_XSCALE_81342
__asm __volatile("mrc p6, 0, %0, c1, c9, 0"
#else
__asm __volatile("mrc p6, 0, %0, c1, c1, 0"
#endif
: "=r" (rv));
return (rv);
}
static __inline void
tmr1_write(uint32_t val)
{
#ifdef CPU_XSCALE_81342
__asm __volatile("mcr p6, 0, %0, c1, c9, 0"
#else
__asm __volatile("mcr p6, 0, %0, c1, c1, 0"
#endif
:
: "r" (val));
}
static __inline uint32_t
tcr1_read(void)
{
uint32_t rv;
#ifdef CPU_XSCALE_81342
__asm __volatile("mrc p6, 0, %0, c3, c9, 0"
#else
__asm __volatile("mrc p6, 0, %0, c3, c1, 0"
#endif
: "=r" (rv));
return (rv);
}
static __inline void
tcr1_write(uint32_t val)
{
#ifdef CPU_XSCALE_81342
__asm __volatile("mcr p6, 0, %0, c3, c9, 0"
#else
__asm __volatile("mcr p6, 0, %0, c3, c1, 0"
#endif
:
: "r" (val));
}
static __inline void
trr1_write(uint32_t val)
{
#ifdef CPU_XSCALE_81342
__asm __volatile("mcr p6, 0, %0, c5, c9, 0"
#else
__asm __volatile("mcr p6, 0, %0, c5, c1, 0"
#endif
:
: "r" (val));
}
static __inline uint32_t
tmr0_read(void)
{
uint32_t rv;
#ifdef CPU_XSCALE_81342
__asm __volatile("mrc p6, 0, %0, c0, c9, 0"
#else
__asm __volatile("mrc p6, 0, %0, c0, c1, 0"
#endif
: "=r" (rv));
return (rv);
}
static __inline void
tmr0_write(uint32_t val)
{
#ifdef CPU_XSCALE_81342
__asm __volatile("mcr p6, 0, %0, c0, c9, 0"
#else
__asm __volatile("mcr p6, 0, %0, c0, c1, 0"
#endif
:
: "r" (val));
}
static __inline uint32_t
tcr0_read(void)
{
uint32_t rv;
#ifdef CPU_XSCALE_81342
__asm __volatile("mrc p6, 0, %0, c2, c9, 0"
#else
__asm __volatile("mrc p6, 0, %0, c2, c1, 0"
#endif
: "=r" (rv));
return (rv);
}
static __inline void
tcr0_write(uint32_t val)
{
#ifdef CPU_XSCALE_81342
__asm __volatile("mcr p6, 0, %0, c2, c9, 0"
#else
__asm __volatile("mcr p6, 0, %0, c2, c1, 0"
#endif
:
: "r" (val));
}
static __inline void
trr0_write(uint32_t val)
{
#ifdef CPU_XSCALE_81342
__asm __volatile("mcr p6, 0, %0, c4, c9, 0"
#else
__asm __volatile("mcr p6, 0, %0, c4, c1, 0"
#endif
:
: "r" (val));
}
static __inline void
tisr_write(uint32_t val)
{
#ifdef CPU_XSCALE_81342
__asm __volatile("mcr p6, 0, %0, c6, c9, 0"
#else
__asm __volatile("mcr p6, 0, %0, c6, c1, 0"
#endif
:
: "r" (val));
}
static __inline uint32_t
tisr_read(void)
{
int ret;
#ifdef CPU_XSCALE_81342
__asm __volatile("mrc p6, 0, %0, c6, c9, 0" : "=r" (ret));
#else
__asm __volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (ret));
#endif
return (ret);
}
static unsigned
i80321_timer_get_timecount(struct timecounter *tc)
{
#if defined(XSCALE_DISABLE_CCNT) || defined(CPU_XSCALE_81342)
uint32_t cur = tcr0_read();
if (cur > last && last != -1) {
offset += counts_per_hz;
if (ticked > 0)
ticked--;
}
if (ticked) {
offset += ticked * counts_per_hz;
ticked = 0;
}
return (counts_per_hz - cur + offset);
#else
uint32_t ret;
__asm __volatile("mrc p14, 0, %0, c1, c0, 0\n"
: "=r" (ret));
return (ret);
#endif
}
/*
* i80321_calibrate_delay:
*
* Calibrate the delay loop.
*/
void
i80321_calibrate_delay(void)
{
/*
* Just use hz=100 for now -- we'll adjust it, if necessary,
* in cpu_initclocks().
*/
counts_per_hz = COUNTS_PER_SEC / 100;
tmr0_write(0); /* stop timer */
tisr_write(TISR_TMR0); /* clear interrupt */
trr0_write(counts_per_hz); /* reload value */
tcr0_write(counts_per_hz); /* current value */
tmr0_write(TMRx_ENABLE|TMRx_RELOAD|TMRx_CSEL_CORE);
}
/*
* cpu_initclocks:
*
* Initialize the clock and get them going.
*/
void
cpu_initclocks(void)
{
u_int oldirqstate;
struct resource *irq;
int rid = 0;
void *ihl;
device_t dev = timer_softc.dev;
if (hz < 50 || COUNTS_PER_SEC % hz) {
printf("Cannot get %d Hz clock; using 100 Hz\n", hz);
hz = 100;
}
tick = 1000000 / hz; /* number of microseconds between interrupts */
/*
* We only have one timer available; stathz and profhz are
* always left as 0 (the upper-layer clock code deals with
* this situation).
*/
if (stathz != 0)
printf("Cannot get %d Hz statclock\n", stathz);
stathz = 0;
if (profhz != 0)
printf("Cannot get %d Hz profclock\n", profhz);
profhz = 0;
/* Report the clock frequency. */
oldirqstate = disable_interrupts(PSR_I);
irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
#ifdef CPU_XSCALE_81342
ICU_INT_TIMER0, ICU_INT_TIMER0,
#else
ICU_INT_TMR0, ICU_INT_TMR0,
#endif
1, RF_ACTIVE);
if (!irq)
panic("Unable to setup the clock irq handler.\n");
else
bus_setup_intr(dev, irq, INTR_TYPE_CLK, clockhandler, NULL,
NULL, &ihl);
tmr0_write(0); /* stop timer */
tisr_write(TISR_TMR0); /* clear interrupt */
counts_per_hz = COUNTS_PER_SEC / hz;
trr0_write(counts_per_hz); /* reload value */
tcr0_write(counts_per_hz); /* current value */
tmr0_write(TMRx_ENABLE|TMRx_RELOAD|TMRx_CSEL_CORE);
tc_init(&i80321_timer_timecounter);
restore_interrupts(oldirqstate);
rid = 0;
#if !defined(XSCALE_DISABLE_CCNT) && !defined(CPU_XSCALE_81342)
/* Enable the clock count register. */
__asm __volatile("mrc p14, 0, %0, c0, c0, 0\n" : "=r" (rid));
rid &= ~(1 << 3);
rid |= (1 << 2) | 1;
__asm __volatile("mcr p14, 0, %0, c0, c0, 0\n"
: : "r" (rid));
#endif
}
/*
* DELAY:
*
* Delay for at least N microseconds.
*/
void
DELAY(int n)
{
uint32_t cur, last, delta, usecs;
TSENTER();
/*
* This works by polling the timer and counting the
* number of microseconds that go by.
*/
last = tcr0_read();
delta = usecs = 0;
while (n > usecs) {
cur = tcr0_read();
/* Check to see if the timer has wrapped around. */
if (last < cur)
delta += (last + (counts_per_hz - cur));
else
delta += (last - cur);
last = cur;
if (delta >= COUNTS_PER_USEC) {
usecs += delta / COUNTS_PER_USEC;
delta %= COUNTS_PER_USEC;
}
}
TSEXIT();
}
/*
* clockhandler:
*
* Handle the hardclock interrupt.
*/
int
clockhandler(void *arg)
{
struct trapframe *frame = arg;
ticked++;
tisr_write(TISR_TMR0);
hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
if (i80321_hardclock_hook != NULL)
(*i80321_hardclock_hook)();
return (FILTER_HANDLED);
}
void
cpu_startprofclock(void)
{
}
void
cpu_stopprofclock(void)
{
}

View File

@ -0,0 +1,153 @@
/* $NetBSD: i80321_wdog.c,v 1.6 2003/07/15 00:24:54 lukem Exp $ */
/*-
* Copyright (c) 2005 Olivier Houchard
* Copyright (c) 2002 Wasabi Systems, Inc.
* All rights reserved.
*
* Written by Jason R. Thorpe for Wasabi Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed for the NetBSD Project by
* Wasabi Systems, Inc.
* 4. The name of Wasabi Systems, Inc. may not be used to endorse
* or promote products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Watchdog timer support for the Intel i80321 I/O processor.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/watchdog.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <machine/bus.h>
#include <machine/machdep.h>
#include <arm/xscale/i8134x/i80321reg.h>
#include <arm/xscale/i8134x/i80321var.h>
struct iopwdog_softc {
device_t dev;
int armed;
int wdog_period;
};
static __inline void
wdtcr_write(uint32_t val)
{
#ifdef CPU_XSCALE_81342
__asm __volatile("mcr p6, 0, %0, c7, c9, 0"
#else
__asm __volatile("mcr p6, 0, %0, c7, c1, 0"
#endif
:
: "r" (val));
}
static void
iopwdog_tickle(void *arg)
{
struct iopwdog_softc *sc = arg;
if (!sc->armed)
return;
wdtcr_write(WDTCR_ENABLE1);
wdtcr_write(WDTCR_ENABLE2);
}
static int
iopwdog_probe(device_t dev)
{
struct iopwdog_softc *sc = device_get_softc(dev);
char buf[128];
/*
* XXX Should compute the period based on processor speed.
* For a 600MHz XScale core, the wdog must be tickled approx.
* every 7 seconds.
*/
sc->wdog_period = 7;
sprintf(buf, "i80321 Watchdog, must be tickled every %d seconds",
sc->wdog_period);
device_set_desc_copy(dev, buf);
return (0);
}
static void
iopwdog_watchdog_fn(void *private, u_int cmd, int *error)
{
struct iopwdog_softc *sc = private;
cmd &= WD_INTERVAL;
if (cmd > 0 && cmd <= 63
&& (uint64_t)1<<cmd <= (uint64_t)sc->wdog_period * 1000000000) {
/* Valid value -> Enable watchdog */
iopwdog_tickle(sc);
sc->armed = 1;
*error = 0;
} else {
/* Can't disable this watchdog! */
if (sc->armed)
*error = EOPNOTSUPP;
}
}
static int
iopwdog_attach(device_t dev)
{
struct iopwdog_softc *sc = device_get_softc(dev);
sc->dev = dev;
sc->armed = 0;
EVENTHANDLER_REGISTER(watchdog_list, iopwdog_watchdog_fn, sc, 0);
return (0);
}
static device_method_t iopwdog_methods[] = {
DEVMETHOD(device_probe, iopwdog_probe),
DEVMETHOD(device_attach, iopwdog_attach),
{0, 0},
};
static driver_t iopwdog_driver = {
"iopwdog",
iopwdog_methods,
sizeof(struct iopwdog_softc),
};
static devclass_t iopwdog_devclass;
DRIVER_MODULE(iopwdog, iq, iopwdog_driver, iopwdog_devclass, 0, 0);

View File

@ -0,0 +1,455 @@
/* $NetBSD: i80321reg.h,v 1.14 2003/12/19 10:08:11 gavan Exp $ */
/*-
* Copyright (c) 2002 Wasabi Systems, Inc.
* All rights reserved.
*
* Written by Jason R. Thorpe for Wasabi Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed for the NetBSD Project by
* Wasabi Systems, Inc.
* 4. The name of Wasabi Systems, Inc. may not be used to endorse
* or promote products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*
*/
#ifndef _ARM_XSCALE_I80321REG_H_
#define _ARM_XSCALE_I80321REG_H_
/*
* Register definitions for the Intel 80321 (``Verde'') I/O processor,
* based on the XScale core.
*/
/*
* Base i80321 memory map:
*
* 0x0000.0000 - 0x7fff.ffff ATU Outbound Direct Addressing Window
* 0x8000.0000 - 0x9001.ffff ATU Outbound Translation Windows
* 0x9002.0000 - 0xffff.dfff External Memory
* 0xffff.e000 - 0xffff.e8ff Peripheral Memory Mapped Registers
* 0xffff.e900 - 0xffff.ffff Reserved
*/
#define VERDE_OUT_DIRECT_WIN_BASE 0x00000000UL
#define VERDE_OUT_DIRECT_WIN_SIZE 0x80000000UL
#define VERDE_OUT_XLATE_MEM_WIN_SIZE 0x04000000UL
#define VERDE_OUT_XLATE_IO_WIN_SIZE 0x00010000UL
#define VERDE_OUT_XLATE_MEM_WIN0_BASE 0x80000000UL
#define VERDE_OUT_XLATE_MEM_WIN1_BASE 0x84000000UL
#define VERDE_OUT_XLATE_IO_WIN0_BASE 0x90000000UL
#define VERDE_EXTMEM_BASE 0x90020000UL
#define VERDE_PMMR_BASE 0xffffe000UL
#define VERDE_PMMR_SIZE 0x00001700UL
/*
* Peripheral Memory Mapped Registers. Defined as offsets
* from the VERDE_PMMR_BASE.
*/
#define VERDE_ATU_BASE 0x0100
#define VERDE_ATU_SIZE 0x0100
#define VERDE_MU_BASE 0x0300
#define VERDE_MU_SIZE 0x0100
#define VERDE_DMA_BASE 0x0400
#define VERDE_DMA_BASE0 (VERDE_DMA_BASE + 0x00)
#define VERDE_DMA_BASE1 (VERDE_DMA_BASE + 0x40)
#define VERDE_DMA_SIZE 0x0100
#define VERDE_DMA_CHSIZE 0x0040
#define VERDE_MCU_BASE 0x0500
#define VERDE_MCU_SIZE 0x0100
#define VERDE_PBIU_BASE 0x0680
#define VERDE_PBIU_SIZE 0x0080
#define VERDE_I2C_BASE 0x1680
#define VERDE_I2C_BASE0 (VERDE_I2C_BASE + 0x00)
#define VERDE_I2C_BASE1 (VERDE_I2C_BASE + 0x20)
#define VERDE_I2C_SIZE 0x0080
#define VERDE_I2C_CHSIZE 0x0020
/*
* Address Translation Unit
*/
/* 0x00 - 0x38 -- PCI configuration space header */
#define ATU_IALR0 0x40 /* Inbound ATU Limit 0 */
#define ATU_IATVR0 0x44 /* Inbound ATU Xlate Value 0 */
#define ATU_ERLR 0x48 /* Expansion ROM Limit */
#define ATU_ERTVR 0x4c /* Expansion ROM Xlate Value */
#define ATU_IALR1 0x50 /* Inbound ATU Limit 1 */
#define ATU_IALR2 0x54 /* Inbound ATU Limit 2 */
#define ATU_IATVR2 0x58 /* Inbound ATU Xlate Value 2 */
#define ATU_OIOWTVR 0x5c /* Outbound I/O Window Xlate Value */
#define ATU_OMWTVR0 0x60 /* Outbound Mem Window Xlate Value 0 */
#define ATU_OUMWTVR0 0x64 /* Outbound Mem Window Xlate Value 0 Upper */
#define ATU_OMWTVR1 0x68 /* Outbound Mem Window Xlate Value 1 */
#define ATU_OUMWTVR1 0x6c /* Outbound Mem Window Xlate Value 1 Upper */
#define ATU_OUDWTVR 0x78 /* Outbound Mem Direct Xlate Value Upper */
#define ATU_ATUCR 0x80 /* ATU Configuration */
#define ATU_PCSR 0x84 /* PCI Configuration and Status */
#define ATU_ATUISR 0x88 /* ATU Interrupt Status */
#define ATU_ATUIMR 0x8c /* ATU Interrupt Mask */
#define ATU_IABAR3 0x90 /* Inbound ATU Base Address 3 */
#define ATU_IAUBAR3 0x94 /* Inbound ATU Base Address 3 Upper */
#define ATU_IALR3 0x98 /* Inbound ATU Limit 3 */
#define ATU_IATVR3 0x9c /* Inbound ATU Xlate Value 3 */
#define ATU_OCCAR 0xa4 /* Outbound Configuration Cycle Address */
#define ATU_OCCDR 0xac /* Outbound Configuration Cycle Data */
#define ATU_MSI_PORT 0xb4 /* MSI port */
#define ATU_PDSCR 0xbc /* PCI Bus Drive Strength Control */
#define ATU_PCI_X_CAP_ID 0xe0 /* (1) */
#define ATU_PCI_X_NEXT 0xe1 /* (1) */
#define ATU_PCIXCMD 0xe2 /* PCI-X Command Register (2) */
#define ATU_PCIXSR 0xe4 /* PCI-X Status Register */
#define ATUCR_DRC_ALIAS (1U << 19)
#define ATUCR_DAU2GXEN (1U << 18)
#define ATUCR_P_SERR_MA (1U << 16)
#define ATUCR_DTS (1U << 15)
#define ATUCR_P_SERR_DIE (1U << 9)
#define ATUCR_DAE (1U << 8)
#define ATUCR_BIST_IE (1U << 3)
#define ATUCR_OUT_EN (1U << 1)
#define PCSR_DAAAPE (1U << 18)
#define PCSR_PCI_X_CAP (3U << 16)
#define PCSR_PCI_X_CAP_BORING (0 << 16)
#define PCSR_PCI_X_CAP_66 (1U << 16)
#define PCSR_PCI_X_CAP_100 (2U << 16)
#define PCSR_PCI_X_CAP_133 (3U << 16)
#define PCSR_OTQB (1U << 15)
#define PCSR_IRTQB (1U << 14)
#define PCSR_DTV (1U << 12)
#define PCSR_BUS66 (1U << 10)
#define PCSR_BUS64 (1U << 8)
#define PCSR_RIB (1U << 5)
#define PCSR_RPB (1U << 4)
#define PCSR_CCR (1U << 2)
#define PCSR_CPR (1U << 1)
#define ATUISR_IMW1BU (1U << 14)
#define ATUISR_ISCEM (1U << 13)
#define ATUISR_RSCEM (1U << 12)
#define ATUISR_PST (1U << 11)
#define ATUISR_P_SERR_ASRT (1U << 10)
#define ATUISR_DPE (1U << 9)
#define ATUISR_BIST (1U << 8)
#define ATUISR_IBMA (1U << 7)
#define ATUISR_P_SERR_DET (1U << 4)
#define ATUISR_PMA (1U << 3)
#define ATUISR_PTAM (1U << 2)
#define ATUISR_PTAT (1U << 1)
#define ATUISR_PMPE (1U << 0)
#define ATUIMR_IMW1BU (1U << 11)
#define ATUIMR_ISCEM (1U << 10)
#define ATUIMR_RSCEM (1U << 9)
#define ATUIMR_PST (1U << 8)
#define ATUIMR_DPE (1U << 7)
#define ATUIMR_P_SERR_ASRT (1U << 6)
#define ATUIMR_PMA (1U << 5)
#define ATUIMR_PTAM (1U << 4)
#define ATUIMR_PTAT (1U << 3)
#define ATUIMR_PMPE (1U << 2)
#define ATUIMR_IE_SERR_EN (1U << 1)
#define ATUIMR_ECC_TAE (1U << 0)
#define PCIXCMD_MOST_1 (0 << 4)
#define PCIXCMD_MOST_2 (1 << 4)
#define PCIXCMD_MOST_3 (2 << 4)
#define PCIXCMD_MOST_4 (3 << 4)
#define PCIXCMD_MOST_8 (4 << 4)
#define PCIXCMD_MOST_12 (5 << 4)
#define PCIXCMD_MOST_16 (6 << 4)
#define PCIXCMD_MOST_32 (7 << 4)
#define PCIXCMD_MOST_MASK (7 << 4)
#define PCIXCMD_MMRBC_512 (0 << 2)
#define PCIXCMD_MMRBC_1024 (1 << 2)
#define PCIXCMD_MMRBC_2048 (2 << 2)
#define PCIXCMD_MMRBC_4096 (3 << 2)
#define PCIXCMD_MMRBC_MASK (3 << 2)
#define PCIXCMD_ERO (1U << 1)
#define PCIXCMD_DPERE (1U << 0)
#define PCIXSR_RSCEM (1U << 29)
#define PCIXSR_DMCRS_MASK (7 << 26)
#define PCIXSR_DMOST_MASK (7 << 23)
#define PCIXSR_COMPLEX (1U << 20)
#define PCIXSR_USC (1U << 19)
#define PCIXSR_SCD (1U << 18)
#define PCIXSR_133_CAP (1U << 17)
#define PCIXSR_32PCI (1U << 16) /* 0 = 32, 1 = 64 */
#define PCIXSR_BUSNO(x) (((x) & 0xff00) >> 8)
#define PCIXSR_DEVNO(x) (((x) & 0xf8) >> 3)
#define PCIXSR_FUNCNO(x) ((x) & 0x7)
/*
* Memory Controller Unit
*/
#define MCU_SDIR 0x00 /* DDR SDRAM Init. Register */
#define MCU_SDCR 0x04 /* DDR SDRAM Control Register */
#define MCU_SDBR 0x08 /* SDRAM Base Register */
#define MCU_SBR0 0x0c /* SDRAM Boundary 0 */
#define MCU_SBR1 0x10 /* SDRAM Boundary 1 */
#define MCU_ECCR 0x34 /* ECC Control Register */
#define MCU_ELOG0 0x38 /* ECC Log 0 */
#define MCU_ELOG1 0x3c /* ECC Log 1 */
#define MCU_ECAR0 0x40 /* ECC address 0 */
#define MCU_ECAR1 0x44 /* ECC address 1 */
#define MCU_ECTST 0x48 /* ECC test register */
#define MCU_MCISR 0x4c /* MCU Interrupt Status Register */
#define MCU_RFR 0x50 /* Refresh Frequency Register */
#define MCU_DBUDSR 0x54 /* Data Bus Pull-up Drive Strength */
#define MCU_DBDDSR 0x58 /* Data Bus Pull-down Drive Strength */
#define MCU_CUDSR 0x5c /* Clock Pull-up Drive Strength */
#define MCU_CDDSR 0x60 /* Clock Pull-down Drive Strength */
#define MCU_CEUDSR 0x64 /* Clock En Pull-up Drive Strength */
#define MCU_CEDDSR 0x68 /* Clock En Pull-down Drive Strength */
#define MCU_CSUDSR 0x6c /* Chip Sel Pull-up Drive Strength */
#define MCU_CSDDSR 0x70 /* Chip Sel Pull-down Drive Strength */
#define MCU_REUDSR 0x74 /* Rx En Pull-up Drive Strength */
#define MCU_REDDSR 0x78 /* Rx En Pull-down Drive Strength */
#define MCU_ABUDSR 0x7c /* Addr Bus Pull-up Drive Strength */
#define MCU_ABDDSR 0x80 /* Addr Bus Pull-down Drive Strength */
#define MCU_DSDR 0x84 /* Data Strobe Delay Register */
#define MCU_REDR 0x88 /* Rx Enable Delay Register */
#define SDCR_DIMMTYPE (1U << 1) /* 0 = unbuf, 1 = reg */
#define SDCR_BUSWIDTH (1U << 2) /* 0 = 64, 1 = 32 */
#define SBRx_TECH (1U << 31)
#define SBRx_BOUND 0x0000003f
#define ECCR_SBERE (1U << 0)
#define ECCR_MBERE (1U << 1)
#define ECCR_SBECE (1U << 2)
#define ECCR_ECCEN (1U << 3)
#define ELOGx_SYNDROME 0x000000ff
#define ELOGx_ERRTYPE (1U << 8) /* 1 = multi-bit */
#define ELOGx_RW (1U << 12) /* 1 = write error */
/*
* Dev ID Func Requester
* 2 0 XScale core
* 2 1 ATU
* 13 0 DMA channel 0
* 13 1 DMA channel 1
* 26 0 ATU
*/
#define ELOGx_REQ_DEV(x) (((x) >> 19) & 0x1f)
#define ELOGx_REQ_FUNC(x) (((x) >> 16) & 0x3)
#define MCISR_ECC_ERR0 (1U << 0)
#define MCISR_ECC_ERR1 (1U << 1)
#define MCISR_ECC_ERRN (1U << 2)
/*
* Timers
*
* The i80321 timer registers are available in both memory-mapped
* and coprocessor spaces. Most of the registers are read-only
* if memory-mapped, so we access them via coprocessor space.
*
* TMR0 cp6 c0,1 0xffffe7e0
* TMR1 cp6 c1,1 0xffffe7e4
* TCR0 cp6 c2,1 0xffffe7e8
* TCR1 cp6 c3,1 0xffffe7ec
* TRR0 cp6 c4,1 0xffffe7f0
* TRR1 cp6 c5,1 0xffffe7f4
* TISR cp6 c6,1 0xffffe7f8
* WDTCR cp6 c7,1 0xffffe7fc
*/
#define TMRx_TC (1U << 0)
#define TMRx_ENABLE (1U << 1)
#define TMRx_RELOAD (1U << 2)
#define TMRx_CSEL_CORE (0 << 4)
#define TMRx_CSEL_CORE_div4 (1 << 4)
#define TMRx_CSEL_CORE_div8 (2 << 4)
#define TMRx_CSEL_CORE_div16 (3 << 4)
#define TISR_TMR0 (1U << 0)
#define TISR_TMR1 (1U << 1)
#define WDTCR_ENABLE1 0x1e1e1e1e
#define WDTCR_ENABLE2 0xe1e1e1e1
/*
* Interrupt Controller Unit.
*
* INTCTL cp6 c0,0 0xffffe7d0
* INTSTR cp6 c4,0 0xffffe7d4
* IINTSRC cp6 c8,0 0xffffe7d8
* FINTSRC cp6 c9,0 0xffffe7dc
* PIRSR 0xffffe1ec
*/
#define ICU_PIRSR 0x01ec
#define ICU_GPOE 0x07c4
#define ICU_GPID 0x07c8
#define ICU_GPOD 0x07cc
/*
* NOTE: WE USE THE `bitXX' BITS TO INDICATE PENDING SOFTWARE
* INTERRUPTS. See i80321_icu.c
*/
#define ICU_INT_HPI 31 /* high priority interrupt */
#define ICU_INT_XINT0 27 /* external interrupts */
#define ICU_INT_XINT(x) ((x) + ICU_INT_XINT0)
#define ICU_INT_bit26 26
/* CPU_XSCALE_80321 */
#define ICU_INT_SSP 25 /* SSP serial port */
#define ICU_INT_MUE 24 /* msg unit error */
/* CPU_XSCALE_80321 */
#define ICU_INT_AAUE 23 /* AAU error */
#define ICU_INT_bit22 22
#define ICU_INT_DMA1E 21 /* DMA Ch 1 error */
#define ICU_INT_DMA0E 20 /* DMA Ch 0 error */
#define ICU_INT_MCUE 19 /* memory controller error */
#define ICU_INT_ATUE 18 /* ATU error */
#define ICU_INT_BIUE 17 /* bus interface unit error */
#define ICU_INT_PMU 16 /* XScale PMU */
#define ICU_INT_PPM 15 /* peripheral PMU */
#define ICU_INT_BIST 14 /* ATU Start BIST */
#define ICU_INT_MU 13 /* messaging unit */
#define ICU_INT_I2C1 12 /* i2c unit 1 */
#define ICU_INT_I2C0 11 /* i2c unit 0 */
#define ICU_INT_TMR1 10 /* timer 1 */
#define ICU_INT_TMR0 9 /* timer 0 */
#define ICU_INT_CPPM 8 /* core processor PMU */
/* CPU_XSCALE_80321 */
#define ICU_INT_AAU_EOC 7 /* AAU end-of-chain */
#define ICU_INT_AAU_EOT 6 /* AAU end-of-transfer */
#define ICU_INT_bit5 5
#define ICU_INT_bit4 4
#define ICU_INT_DMA1_EOC 3 /* DMA1 end-of-chain */
#define ICU_INT_DMA1_EOT 2 /* DMA1 end-of-transfer */
#define ICU_INT_DMA0_EOC 1 /* DMA0 end-of-chain */
#define ICU_INT_DMA0_EOT 0 /* DMA0 end-of-transfer */
/* CPU_XSCALE_80321 */
#define ICU_INT_HWMASK (0xffffffff & \
~((1 << ICU_INT_bit26) | \
(1 << ICU_INT_bit22) | \
(1 << ICU_INT_bit5) | \
(1 << ICU_INT_bit4)))
/*
* Peripheral Bus Interface Unit
*/
#define PBIU_PBCR 0x00 /* PBIU Control Register */
#define PBIU_PBBAR0 0x08 /* PBIU Base Address Register 0 */
#define PBIU_PBLR0 0x0c /* PBIU Limit Register 0 */
#define PBIU_PBBAR1 0x10 /* PBIU Base Address Register 1 */
#define PBIU_PBLR1 0x14 /* PBIU Limit Register 1 */
#define PBIU_PBBAR2 0x18 /* PBIU Base Address Register 2 */
#define PBIU_PBLR2 0x1c /* PBIU Limit Register 2 */
#define PBIU_PBBAR3 0x20 /* PBIU Base Address Register 3 */
#define PBIU_PBLR3 0x24 /* PBIU Limit Register 3 */
#define PBIU_PBBAR4 0x28 /* PBIU Base Address Register 4 */
#define PBIU_PBLR4 0x2c /* PBIU Limit Register 4 */
#define PBIU_PBBAR5 0x30 /* PBIU Base Address Register 5 */
#define PBIU_PBLR5 0x34 /* PBIU Limit Register 5 */
#define PBIU_DSCR 0x38 /* PBIU Drive Strength Control Reg. */
#define PBIU_MBR0 0x40 /* PBIU Memory-less Boot Reg. 0 */
#define PBIU_MBR1 0x60 /* PBIU Memory-less Boot Reg. 1 */
#define PBIU_MBR2 0x64 /* PBIU Memory-less Boot Reg. 2 */
#define PBIU_PBCR_PBIEN (1 << 0)
#define PBIU_PBCR_PBI100 (1 << 1)
#define PBIU_PBCR_PBI66 (2 << 1)
#define PBIU_PBCR_PBI33 (3 << 1)
#define PBIU_PBCR_PBBEN (1 << 3)
#define PBIU_PBARx_WIDTH8 (0 << 0)
#define PBIU_PBARx_WIDTH16 (1 << 0)
#define PBIU_PBARx_WIDTH32 (2 << 0)
#define PBIU_PBARx_ADWAIT4 (0 << 2)
#define PBIU_PBARx_ADWAIT8 (1 << 2)
#define PBIU_PBARx_ADWAIT12 (2 << 2)
#define PBIU_PBARx_ADWAIT16 (3 << 2)
#define PBIU_PBARx_ADWAIT20 (4 << 2)
#define PBIU_PBARx_RCWAIT1 (0 << 6)
#define PBIU_PBARx_RCWAIT4 (1 << 6)
#define PBIU_PBARx_RCWAIT8 (2 << 6)
#define PBIU_PBARx_RCWAIT12 (3 << 6)
#define PBIU_PBARx_RCWAIT16 (4 << 6)
#define PBIU_PBARx_RCWAIT20 (5 << 6)
#define PBIU_PBARx_FWE (1 << 9)
#define PBIU_BASE_MASK 0xfffff000U
#define PBIU_PBLRx_SIZE(x) (~((x) - 1))
/*
* Messaging Unit
*/
#define MU_IMR0 0x0010 /* MU Inbound Message Register 0 */
#define MU_IMR1 0x0014 /* MU Inbound Message Register 1 */
#define MU_OMR0 0x0018 /* MU Outbound Message Register 0 */
#define MU_OMR1 0x001c /* MU Outbound Message Register 1 */
#define MU_IDR 0x0020 /* MU Inbound Doorbell Register */
#define MU_IISR 0x0024 /* MU Inbound Interrupt Status Reg */
#define MU_IIMR 0x0028 /* MU Inbound Interrupt Mask Reg */
#define MU_ODR 0x002c /* MU Outbound Doorbell Register */
#define MU_OISR 0x0030 /* MU Outbound Interrupt Status Reg */
#define MU_OIMR 0x0034 /* MU Outbound Interrupt Mask Reg */
#define MU_MUCR 0x0050 /* MU Configuration Register */
#define MU_QBAR 0x0054 /* MU Queue Base Address Register */
#define MU_IFHPR 0x0060 /* MU Inbound Free Head Pointer Reg */
#define MU_IFTPR 0x0064 /* MU Inbound Free Tail Pointer Reg */
#define MU_IPHPR 0x0068 /* MU Inbound Post Head Pointer Reg */
#define MU_IPTPR 0x006c /* MU Inbound Post Tail Pointer Reg */
#define MU_OFHPR 0x0070 /* MU Outbound Free Head Pointer Reg */
#define MU_OFTPR 0x0074 /* MU Outbound Free Tail Pointer Reg */
#define MU_OPHPR 0x0078 /* MU Outbound Post Head Pointer Reg */
#define MU_OPTPR 0x007c /* MU Outbound Post Tail Pointer Reg */
#define MU_IAR 0x0080 /* MU Index Address Register */
#define MU_IIMR_IRI (1 << 6) /* Index Register Interrupt */
#define MU_IIMR_OFQFI (1 << 5) /* Outbound Free Queue Full Int. */
#define MU_IIMR_IPQI (1 << 4) /* Inbound Post Queue Interrupt */
#define MU_IIMR_EDI (1 << 3) /* Error Doorbell Interrupt */
#define MU_IIMR_IDI (1 << 2) /* Inbound Doorbell Interrupt */
#define MU_IIMR_IM1I (1 << 1) /* Inbound Message 1 Interrupt */
#define MU_IIMR_IM0I (1 << 0) /* Inbound Message 0 Interrupt */
#endif /* _ARM_XSCALE_I80321REG_H_ */

View File

@ -0,0 +1,137 @@
/* $NetBSD: i80321var.h,v 1.8 2003/10/06 16:06:06 thorpej Exp $ */
/*-
* Copyright (c) 2002, 2003 Wasabi Systems, Inc.
* All rights reserved.
*
* Written by Jason R. Thorpe for Wasabi Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed for the NetBSD Project by
* Wasabi Systems, Inc.
* 4. The name of Wasabi Systems, Inc. may not be used to endorse
* or promote products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*
*/
#ifndef _ARM_XSCALE_I80321VAR_H_
#define _ARM_XSCALE_I80321VAR_H_
#include <sys/queue.h>
#include <dev/pci/pcivar.h>
#include <sys/rman.h>
extern struct bus_space i80321_bs_tag;
struct i80321_softc {
device_t dev;
bus_space_tag_t sc_st;
bus_space_handle_t sc_sh;
/* Handles for the various subregions. */
bus_space_handle_t sc_atu_sh;
bus_space_handle_t sc_mcu_sh;
int sc_is_host;
/*
* We expect the board-specific front-end to have already mapped
* the PCI I/O space .. it is only 64K, and I/O mappings tend to
* be smaller than a page size, so it's generally more efficient
* to map them all into virtual space in one fell swoop.
*/
vm_offset_t sc_iow_vaddr; /* I/O window vaddr */
/*
* Variables that define the Inbound windows. The base address of
* 0-2 are configured by a host via BARs. The xlate variable
* defines the start of the local address space that it maps to.
* The size variable defines the byte size.
*
* The first 3 windows are for incoming PCI memory read/write
* cycles from a host. The 4th window, not configured by the
* host (as it outside the normal BAR range) is the inbound
* window for PCI devices controlled by the i80321.
*/
struct {
uint32_t iwin_base_hi;
uint32_t iwin_base_lo;
uint32_t iwin_xlate;
uint32_t iwin_size;
} sc_iwin[4];
/*
* Variables that define the Outbound windows.
*/
struct {
uint32_t owin_xlate_lo;
uint32_t owin_xlate_hi;
} sc_owin[2];
/*
* This is the PCI address that the Outbound I/O
* window maps to.
*/
uint32_t sc_ioout_xlate;
/* Bus space, DMA, and PCI tags for the PCI bus (private devices). */
struct bus_space sc_pci_iot;
struct bus_space sc_pci_memt;
/* GPIO state */
uint8_t sc_gpio_dir; /* GPIO pin direction (1 == output) */
uint8_t sc_gpio_val; /* GPIO output pin value */
struct rman sc_irq_rman;
};
struct i80321_pci_softc {
device_t sc_dev;
bus_space_tag_t sc_st;
bus_space_handle_t sc_atu_sh;
bus_space_tag_t sc_pciio;
bus_space_tag_t sc_pcimem;
int sc_busno;
struct rman sc_mem_rman;
struct rman sc_io_rman;
struct rman sc_irq_rman;
uint32_t sc_mem;
uint32_t sc_io;
};
void i80321_sdram_bounds(bus_space_tag_t, bus_space_handle_t,
vm_paddr_t *, vm_size_t *);
void i80321_attach(struct i80321_softc *);
void i80321_calibrate_delay(void);
void i80321_bs_init(bus_space_tag_t, void *);
void i80321_io_bs_init(bus_space_tag_t, void *);
void i80321_mem_bs_init(bus_space_tag_t, void *);
extern int machdep_pci_route_interrupt(device_t pcib, device_t dev, int pin);
#endif /* _ARM_XSCALE_I80321VAR_H_ */

View File

@ -0,0 +1,468 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2006 Olivier Houchard
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/module.h>
#define _ARM32_BUS_DMA_PRIVATE
#include <machine/armreg.h>
#include <machine/bus.h>
#include <machine/intr.h>
#include <arm/xscale/i8134x/i81342reg.h>
#include <arm/xscale/i8134x/i81342var.h>
#define WDTCR_ENABLE1 0x1e1e1e1e
#define WDTCR_ENABLE2 0xe1e1e1e1
static volatile int intr_enabled0;
static volatile int intr_enabled1;
static volatile int intr_enabled2;
static volatile int intr_enabled3;
struct bus_space i81342_bs_tag;
/* Read the interrupt pending register */
static __inline
uint32_t intpnd0_read(void)
{
uint32_t ret;
__asm __volatile("mrc p6, 0, %0, c0, c3, 0"
: "=r" (ret));
return (ret);
}
static __inline
uint32_t intpnd1_read(void)
{
uint32_t ret;
__asm __volatile("mrc p6, 0, %0, c1, c3, 0"
: "=r" (ret));
return (ret);
}
static __inline
uint32_t intpnd2_read(void)
{
uint32_t ret;
__asm __volatile("mrc p6, 0, %0, c2, c3, 0"
: "=r" (ret));
return (ret);
}
static __inline
uint32_t intpnd3_read(void)
{
uint32_t ret;
__asm __volatile("mrc p6, 0, %0, c3, c3, 0"
: "=r" (ret));
return (ret);
}
/* Read the interrupt control register */
/* 0 masked, 1 unmasked */
static __inline
uint32_t intctl0_read(void)
{
uint32_t ret;
__asm __volatile("mrc p6, 0, %0, c0, c4, 0"
: "=r" (ret));
return (ret);
}
static __inline
uint32_t intctl1_read(void)
{
uint32_t ret;
__asm __volatile("mrc p6, 0, %0, c1, c4, 0"
: "=r" (ret));
return (ret);
}
static __inline
uint32_t intctl2_read(void)
{
uint32_t ret;
__asm __volatile("mrc p6, 0, %0, c2, c4, 0"
: "=r" (ret));
return (ret);
}
static __inline
uint32_t intctl3_read(void)
{
uint32_t ret;
__asm __volatile("mrc p6, 0, %0, c3, c4, 0"
: "=r" (ret));
return (ret);
}
/* Write the interrupt control register */
static __inline
void intctl0_write(uint32_t val)
{
__asm __volatile("mcr p6, 0, %0, c0, c4, 0"
: : "r" (val));
}
static __inline
void intctl1_write(uint32_t val)
{
__asm __volatile("mcr p6, 0, %0, c1, c4, 0"
: : "r" (val));
}
static __inline
void intctl2_write(uint32_t val)
{
__asm __volatile("mcr p6, 0, %0, c2, c4, 0"
: : "r" (val));
}
static __inline
void intctl3_write(uint32_t val)
{
__asm __volatile("mcr p6, 0, %0, c3, c4, 0"
: : "r" (val));
}
/* Read the interrupt steering register */
/* 0 IRQ 1 FIQ */
static __inline
uint32_t intstr0_read(void)
{
uint32_t ret;
__asm __volatile("mrc p6, 0, %0, c0, c5, 0"
: "=r" (ret));
return (ret);
}
static __inline
uint32_t intstr1_read(void)
{
uint32_t ret;
__asm __volatile("mrc p6, 0, %0, c1, c5, 0"
: "=r" (ret));
return (ret);
}
static __inline
uint32_t intstr2_read(void)
{
uint32_t ret;
__asm __volatile("mrc p6, 0, %0, c2, c5, 0"
: "=r" (ret));
return (ret);
}
static __inline
uint32_t intstr3_read(void)
{
uint32_t ret;
__asm __volatile("mrc p6, 0, %0, c3, c5, 0"
: "=r" (ret));
return (ret);
}
/* Write the interrupt steering register */
static __inline
void intstr0_write(uint32_t val)
{
__asm __volatile("mcr p6, 0, %0, c0, c5, 0"
: : "r" (val));
}
static __inline
void intstr1_write(uint32_t val)
{
__asm __volatile("mcr p6, 0, %0, c1, c5, 0"
: : "r" (val));
}
static __inline
void intstr2_write(uint32_t val)
{
__asm __volatile("mcr p6, 0, %0, c2, c5, 0"
: : "r" (val));
}
static __inline
void intstr3_write(uint32_t val)
{
__asm __volatile("mcr p6, 0, %0, c3, c5, 0"
: : "r" (val));
}
void
cpu_reset(void)
{
disable_interrupts(PSR_I);
/* XXX: Use the watchdog to reset for now */
__asm __volatile("mcr p6, 0, %0, c8, c9, 0\n"
"mcr p6, 0, %1, c7, c9, 0\n"
"mcr p6, 0, %2, c7, c9, 0\n"
: : "r" (1), "r" (WDTCR_ENABLE1), "r" (WDTCR_ENABLE2));
while (1);
}
void
arm_mask_irq(uintptr_t nb)
{
if (nb < 32) {
intr_enabled0 &= ~(1 << nb);
intctl0_write(intr_enabled0);
} else if (nb < 64) {
intr_enabled1 &= ~(1 << (nb - 32));
intctl1_write(intr_enabled1);
} else if (nb < 96) {
intr_enabled2 &= ~(1 << (nb - 64));
intctl2_write(intr_enabled2);
} else {
intr_enabled3 &= ~(1 << (nb - 96));
intctl3_write(intr_enabled3);
}
}
void
arm_unmask_irq(uintptr_t nb)
{
if (nb < 32) {
intr_enabled0 |= (1 << nb);
intctl0_write(intr_enabled0);
} else if (nb < 64) {
intr_enabled1 |= (1 << (nb - 32));
intctl1_write(intr_enabled1);
} else if (nb < 96) {
intr_enabled2 |= (1 << (nb - 64));
intctl2_write(intr_enabled2);
} else {
intr_enabled3 |= (1 << (nb - 96));
intctl3_write(intr_enabled3);
}
}
int
arm_get_next_irq(int last __unused)
{
uint32_t val;
val = intpnd0_read() & intr_enabled0;
if (val)
return (ffs(val) - 1);
val = intpnd1_read() & intr_enabled1;
if (val)
return (32 + ffs(val) - 1);
val = intpnd2_read() & intr_enabled2;
if (val)
return (64 + ffs(val) - 1);
val = intpnd3_read() & intr_enabled3;
if (val)
return (96 + ffs(val) - 1);
return (-1);
}
int
bus_dma_get_range_nb(void)
{
return (0);
}
struct arm32_dma_range *
bus_dma_get_range(void)
{
return (NULL);
}
static int
i81342_probe(device_t dev)
{
unsigned int freq;
freq = *(volatile unsigned int *)(IOP34X_VADDR + IOP34X_PFR);
switch (freq & IOP34X_FREQ_MASK) {
case IOP34X_FREQ_600:
device_set_desc(dev, "Intel 81342 600MHz");
break;
case IOP34X_FREQ_667:
device_set_desc(dev, "Intel 81342 667MHz");
break;
case IOP34X_FREQ_800:
device_set_desc(dev, "Intel 81342 800MHz");
break;
case IOP34X_FREQ_833:
device_set_desc(dev, "Intel 81342 833MHz");
break;
case IOP34X_FREQ_1000:
device_set_desc(dev, "Intel 81342 1000MHz");
break;
case IOP34X_FREQ_1200:
device_set_desc(dev, "Intel 81342 1200MHz");
break;
default:
device_set_desc(dev, "Intel 81342 unknown frequency");
break;
}
return (0);
}
static void
i81342_identify(driver_t *driver, device_t parent)
{
BUS_ADD_CHILD(parent, 0, "iq", 0);
}
static int
i81342_attach(device_t dev)
{
struct i81342_softc *sc = device_get_softc(dev);
uint32_t esstrsr;
i81342_bs_init(&i81342_bs_tag, sc);
sc->sc_st = &i81342_bs_tag;
sc->sc_sh = IOP34X_VADDR;
esstrsr = bus_space_read_4(sc->sc_st, sc->sc_sh, IOP34X_ESSTSR0);
sc->sc_atux_sh = IOP34X_ATUX_ADDR(esstrsr) - IOP34X_HWADDR +
IOP34X_VADDR;
sc->sc_atue_sh = IOP34X_ATUE_ADDR(esstrsr) - IOP34X_HWADDR +
IOP34X_VADDR;
/* Disable all interrupts. */
intctl0_write(0);
intctl1_write(0);
intctl2_write(0);
intctl3_write(0);
/* Defaults to IRQ */
intstr0_write(0);
intstr1_write(0);
intstr2_write(0);
intstr3_write(0);
sc->sc_irq_rman.rm_type = RMAN_ARRAY;
sc->sc_irq_rman.rm_descr = "i81342 IRQs";
if (rman_init(&sc->sc_irq_rman) != 0 ||
rman_manage_region(&sc->sc_irq_rman, 0, 127) != 0)
panic("i81342_attach: failed to set up IRQ rman");
device_add_child(dev, "obio", 0);
device_add_child(dev, "itimer", 0);
device_add_child(dev, "iopwdog", 0);
device_add_child(dev, "pcib", 0);
device_add_child(dev, "pcib", 1);
device_add_child(dev, "iqseg", 0);
bus_generic_probe(dev);
bus_generic_attach(dev);
return (0);
}
static struct resource *
i81342_alloc_resource(device_t dev, device_t child, int type, int *rid,
rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
{
struct i81342_softc *sc = device_get_softc(dev);
struct resource *rv;
if (type == SYS_RES_IRQ) {
rv = rman_reserve_resource(&sc->sc_irq_rman,
start, end, count, flags, child);
if (rv != NULL)
rman_set_rid(rv, *rid);
return (rv);
}
return (NULL);
}
static int
i81342_setup_intr(device_t dev, device_t child, struct resource *ires,
int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg,
void **cookiep)
{
int error;
error = BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags,
filt, intr, arg, cookiep);
if (error)
return (error);
return (0);
}
static int
i81342_teardown_intr(device_t dev, device_t child, struct resource *res,
void *cookie)
{
return (BUS_TEARDOWN_INTR(device_get_parent(dev), child, res, cookie));
}
static device_method_t i81342_methods[] = {
DEVMETHOD(device_probe, i81342_probe),
DEVMETHOD(device_attach, i81342_attach),
DEVMETHOD(device_identify, i81342_identify),
DEVMETHOD(bus_alloc_resource, i81342_alloc_resource),
DEVMETHOD(bus_setup_intr, i81342_setup_intr),
DEVMETHOD(bus_teardown_intr, i81342_teardown_intr),
{0, 0},
};
static driver_t i81342_driver = {
"iq",
i81342_methods,
sizeof(struct i81342_softc),
};
static devclass_t i81342_devclass;
DRIVER_MODULE(iq, nexus, i81342_driver, i81342_devclass, 0, 0);

View File

@ -0,0 +1,58 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2006 Olivier Houchard
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <machine/bus.h>
#include <arm/xscale/i8134x/i81342reg.h>
#include <arm/xscale/i8134x/i81342var.h>
void
i81342_sdram_bounds(bus_space_tag_t bt, bus_space_handle_t bh,
vm_paddr_t *start, vm_size_t *size)
{
uint32_t reg;
int bank_nb;
reg = bus_space_read_4(bt, bh, SMC_SDBR);
*start = (reg & SMC_SDBR_BASEADDR_MASK);
reg = bus_space_read_4(bt, bh, SMC_SBSR);
if (reg & SMC_SBSR_BANK_NB)
bank_nb = 1;
else
bank_nb = 2;
*size = (reg & SMC_SBSR_BANK_SZ_MASK) * bank_nb;
}

View File

@ -0,0 +1,547 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2006 Olivier Houchard
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/types.h>
#include <sys/rman.h>
#include <machine/bus.h>
#include <machine/cpu.h>
#include <machine/pcb.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <vm/vm_extern.h>
#include <arm/xscale/i8134x/i81342reg.h>
#include <arm/xscale/i8134x/i81342var.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcib_private.h>
#include "pcib_if.h"
#include <dev/pci/pcireg.h>
static pcib_read_config_t i81342_pci_read_config;
static pcib_write_config_t i81342_pci_write_config;
static int
i81342_pci_probe(device_t dev)
{
struct i81342_pci_softc *sc;
sc = device_get_softc(dev);
if (device_get_unit(dev) == 0) {
device_set_desc(dev, "i81342 PCI-X bus");
sc->sc_is_atux = 1;
} else {
device_set_desc(dev, "i81342 PCIe bus");
sc->sc_is_atux = 0;
}
return (0);
}
#define PCI_MAPREG_MEM_PREFETCHABLE_MASK 0x00000008
#define PCI_MAPREG_MEM_TYPE_64BIT 0x00000004
static int
i81342_pci_attach(device_t dev)
{
struct i81342_softc *parent_sc;
struct i81342_pci_softc *sc;
uint32_t memsize, memstart;
uint32_t reg;
int func;
uint32_t busno;
sc = device_get_softc(dev);
parent_sc = device_get_softc(device_get_parent(dev));
sc->sc_atu_sh = sc->sc_is_atux ? parent_sc->sc_atux_sh :
parent_sc->sc_atue_sh;
sc->sc_st = parent_sc->sc_st;
if (bus_space_read_4(sc->sc_st, parent_sc->sc_sh, IOP34X_ESSTSR0)
& IOP34X_INT_SEL_PCIX) {
if (sc->sc_is_atux)
func = 5;
else
func = 0;
} else {
if (sc->sc_is_atux)
func = 0;
else
func = 5;
}
i81342_io_bs_init(&sc->sc_pciio, sc);
i81342_mem_bs_init(&sc->sc_pcimem, sc);
i81342_sdram_bounds(sc->sc_st, IOP34X_VADDR, &memstart, &memsize);
if (sc->sc_is_atux) {
reg = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCSR);
if (reg & ATUX_P_RSTOUT) {
bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_PCSR,
reg &~ ATUX_P_RSTOUT);
DELAY(200);
}
}
/* Setup the Inbound windows. */
bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IABAR0, 0);
bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IAUBAR0, 0);
bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR0, 0);
/* Set the mapping Physical address <=> PCI address */
bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IABAR1,
memstart | PCI_MAPREG_MEM_PREFETCHABLE_MASK |
PCI_MAPREG_MEM_TYPE_64BIT);
bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IAUBAR1, 0);
bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR1,
rounddown2(~(0xfff), memsize));
bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IATVR1, memstart);
bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IAUTVR1, 0);
bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IABAR2, 0);
bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IAUBAR2, 0);
bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR2, 0);
/* Setup the Outbound IO Bar */
if (sc->sc_is_atux)
bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OIOBAR,
(IOP34X_PCIX_OIOBAR >> 4) | func);
else
bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OIOBAR,
(IOP34X_PCIE_OIOBAR >> 4) | func);
/* Setup the Outbound windows */
bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OUMBAR0, 0);
if (sc->sc_is_atux)
bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OUMBAR1,
(IOP34X_PCIX_OMBAR >> 32) | (func << ATU_OUMBAR_FUNC) |
ATU_OUMBAR_EN);
else
bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OUMBAR1,
(IOP34X_PCIE_OMBAR >> 32) | (func << ATU_OUMBAR_FUNC) |
ATU_OUMBAR_EN);
bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OUMWTVR1, 0);
bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OUMBAR2, 0);
bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OUMBAR3, 0);
/* Enable the outbound windows. */
reg = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_CR);
bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_CR,
reg | ATU_CR_OUT_EN);
bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_ISR,
bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_ISR) & ATUX_ISR_ERRMSK);
/*
* Enable bus mastering, memory access, SERR, and parity
* checking on the ATU.
*/
if (sc->sc_is_atux) {
busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR);
busno = PCIXSR_BUSNO(busno);
} else {
busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCSR);
busno = PCIE_BUSNO(busno);
}
reg = bus_space_read_2(sc->sc_st, sc->sc_atu_sh, ATU_CMD);
reg |= PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN | PCIM_CMD_PERRESPEN |
PCIM_CMD_SERRESPEN;
bus_space_write_2(sc->sc_st, sc->sc_atu_sh, ATU_CMD, reg);
sc->sc_busno = busno;
/* Initialize memory and i/o rmans. */
sc->sc_io_rman.rm_type = RMAN_ARRAY;
sc->sc_io_rman.rm_descr = "I81342 PCI I/O Ports";
if (rman_init(&sc->sc_io_rman) != 0 ||
rman_manage_region(&sc->sc_io_rman,
sc->sc_is_atux ? IOP34X_PCIX_OIOBAR_VADDR :
IOP34X_PCIE_OIOBAR_VADDR,
(sc->sc_is_atux ? IOP34X_PCIX_OIOBAR_VADDR :
IOP34X_PCIE_OIOBAR_VADDR) + IOP34X_OIOBAR_SIZE) != 0) {
panic("i81342_pci_probe: failed to set up I/O rman");
}
sc->sc_mem_rman.rm_type = RMAN_ARRAY;
sc->sc_mem_rman.rm_descr = "I81342 PCI Memory";
if (rman_init(&sc->sc_mem_rman) != 0 ||
rman_manage_region(&sc->sc_mem_rman,
0, 0xffffffff) != 0) {
panic("i81342_pci_attach: failed to set up memory rman");
}
sc->sc_irq_rman.rm_type = RMAN_ARRAY;
sc->sc_irq_rman.rm_descr = "i81342 PCI IRQs";
if (sc->sc_is_atux) {
if (rman_init(&sc->sc_irq_rman) != 0 ||
rman_manage_region(&sc->sc_irq_rman, ICU_INT_XINT0,
ICU_INT_XINT3) != 0)
panic("i83142_pci_attach: failed to set up IRQ rman");
} else {
if (rman_init(&sc->sc_irq_rman) != 0 ||
rman_manage_region(&sc->sc_irq_rman, ICU_INT_ATUE_MA,
ICU_INT_ATUE_MD) != 0)
panic("i81342_pci_attach: failed to set up IRQ rman");
}
bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_ISR,
bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_ISR) & ATUX_ISR_ERRMSK);
device_add_child(dev, "pci", -1);
return (bus_generic_attach(dev));
}
static int
i81342_pci_maxslots(device_t dev)
{
return (PCI_SLOTMAX);
}
static void
i81342_pci_conf_setup(struct i81342_pci_softc *sc, int bus, int slot, int func,
int reg, uint32_t *addr)
{
uint32_t busno;
if (sc->sc_is_atux) {
busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR);
busno = PCIXSR_BUSNO(busno);
} else {
busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCSR);
busno = PCIE_BUSNO(busno);
}
bus &= 0xff;
slot &= 0x1f;
func &= 0x7;
if (sc->sc_is_atux) {
if (busno == bus)
*addr = (1 << (slot + 16)) | (slot << 11) |
(func << 8) | reg;
else
*addr = (bus << 16) | (slot << 11) | (func << 11) |
reg | 1;
} else {
*addr = (bus << 24) | (slot << 19) | (func << 16) | reg;
if (bus != busno)
*addr |= 1;
}
}
static u_int32_t
i81342_pci_read_config(device_t dev, u_int bus, u_int slot, u_int func,
u_int reg, int bytes)
{
struct i81342_pci_softc *sc = device_get_softc(dev);
uint32_t addr;
uint32_t ret = 0;
uint32_t isr;
int err = 0;
vm_offset_t va;
i81342_pci_conf_setup(sc, bus, slot, func, reg & ~3, &addr);
bus_space_write_4(sc->sc_st, sc->sc_atu_sh, sc->sc_is_atux ?
ATUX_OCCAR : ATUE_OCCAR, addr);
if (sc->sc_is_atux)
va = sc->sc_atu_sh + ATUX_OCCDR;
else
va = sc->sc_atu_sh + ATUE_OCCDR;
switch (bytes) {
case 1:
err = badaddr_read((void*)(va + (reg & 3)), 1, &ret);
break;
case 2:
err = badaddr_read((void*)(va + (reg & 3)), 2, &ret);
break;
case 4:
err = badaddr_read((void *)(va) , 4, &ret);
break;
default:
printf("i81342_read_config: invalid size %d\n", bytes);
ret = -1;
}
if (err) {
isr = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_ISR);
if (sc->sc_is_atux)
isr &= ATUX_ISR_ERRMSK;
else
isr &= ATUE_ISR_ERRMSK;
bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_ISR, isr);
ret = -1;
}
return (ret);
}
static void
i81342_pci_write_config(device_t dev, u_int bus, u_int slot, u_int func,
u_int reg, u_int32_t data, int bytes)
{
struct i81342_pci_softc *sc = device_get_softc(dev);
uint32_t addr;
vm_offset_t va;
i81342_pci_conf_setup(sc, bus, slot, func, reg & ~3, &addr);
bus_space_write_4(sc->sc_st, sc->sc_atu_sh, sc->sc_is_atux ?
ATUX_OCCAR : ATUE_OCCAR, addr);
va = sc->sc_is_atux ? ATUX_OCCDR : ATUE_OCCDR;
switch (bytes) {
case 1:
bus_space_write_1(sc->sc_st, sc->sc_atu_sh, va + (reg & 3)
, data);
break;
case 2:
bus_space_write_2(sc->sc_st, sc->sc_atu_sh, va + (reg & 3)
, data);
break;
case 4:
bus_space_write_4(sc->sc_st, sc->sc_atu_sh, va, data);
break;
default:
printf("i81342_pci_write_config: Invalid size : %d\n", bytes);
}
}
static struct resource *
i81342_pci_alloc_resource(device_t bus, device_t child, int type, int *rid,
rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
{
struct i81342_pci_softc *sc = device_get_softc(bus);
struct resource *rv;
struct rman *rm;
bus_space_tag_t bt = NULL;
bus_space_handle_t bh = 0;
switch (type) {
case SYS_RES_IRQ:
rm = &sc->sc_irq_rman;
break;
case SYS_RES_MEMORY:
rm = &sc->sc_mem_rman;
bt = &sc->sc_pcimem;
bh = 0;
break;
case SYS_RES_IOPORT:
rm = &sc->sc_io_rman;
bt = &sc->sc_pciio;
bh = sc->sc_is_atux ? IOP34X_PCIX_OIOBAR_VADDR :
IOP34X_PCIE_OIOBAR_VADDR;
start += bh;
end += bh;
break;
default:
return (NULL);
}
rv = rman_reserve_resource(rm, start, end, count, flags, child);
if (rv == NULL)
return (NULL);
rman_set_rid(rv, *rid);
if (type != SYS_RES_IRQ) {
if (type == SYS_RES_MEMORY)
bh += (rman_get_start(rv));
rman_set_bustag(rv, bt);
rman_set_bushandle(rv, bh);
if (flags & RF_ACTIVE) {
if (bus_activate_resource(child, type, *rid, rv)) {
rman_release_resource(rv);
return (NULL);
}
}
}
return (rv);
return (NULL);
}
static int
i81342_pci_activate_resource(device_t bus, device_t child, int type, int rid,
struct resource *r)
{
bus_space_handle_t p;
int error;
if (type == SYS_RES_MEMORY) {
error = bus_space_map(rman_get_bustag(r),
rman_get_bushandle(r), rman_get_size(r), 0, &p);
if (error)
return (error);
rman_set_bushandle(r, p);
}
return (rman_activate_resource(r));
}
static int
i81342_pci_setup_intr(device_t dev, device_t child, struct resource *ires,
int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg,
void **cookiep)
{
return (BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags,
filt, intr, arg, cookiep));
}
static int
i81342_pci_teardown_intr(device_t dev, device_t child, struct resource *res,
void *cookie)
{
return (BUS_TEARDOWN_INTR(device_get_parent(dev), child, res, cookie));
}
static int
i81342_pci_route_interrupt(device_t pcib, device_t dev, int pin)
{
struct i81342_pci_softc *sc;
int device;
device = pci_get_slot(dev);
sc = device_get_softc(pcib);
/* XXX: Is board specific */
if (sc->sc_is_atux) {
/* PCI-X */
switch(device) {
case 1:
switch (pin) {
case 1:
return (ICU_INT_XINT1);
case 2:
return (ICU_INT_XINT2);
case 3:
return (ICU_INT_XINT3);
case 4:
return (ICU_INT_XINT0);
default:
break;
}
case 2:
switch (pin) {
case 1:
return (ICU_INT_XINT2);
case 2:
return (ICU_INT_XINT3);
case 3:
return (ICU_INT_XINT2);
case 4:
return (ICU_INT_XINT3);
default:
break;
}
}
} else {
switch (pin) {
case 1:
return (ICU_INT_ATUE_MA);
case 2:
return (ICU_INT_ATUE_MB);
case 3:
return (ICU_INT_ATUE_MC);
case 4:
return (ICU_INT_ATUE_MD);
default:
break;
}
}
printf("Warning: couldn't map %s IRQ for device %d pin %d\n",
sc->sc_is_atux ? "PCI-X" : "PCIe", device, pin);
return (-1);
}
static int
i81342_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
{
struct i81342_pci_softc *sc = device_get_softc(dev);
switch (which) {
case PCIB_IVAR_DOMAIN:
*result = 0;
return (0);
case PCIB_IVAR_BUS:
*result = sc->sc_busno;
return (0);
}
return (ENOENT);
}
static int
i81342_write_ivar(device_t dev, device_t child, int which, uintptr_t result)
{
struct i81342_pci_softc * sc = device_get_softc(dev);
switch (which) {
case PCIB_IVAR_DOMAIN:
return (EINVAL);
case PCIB_IVAR_BUS:
sc->sc_busno = result;
return (0);
}
return (ENOENT);
}
static device_method_t i81342_pci_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, i81342_pci_probe),
DEVMETHOD(device_attach, i81342_pci_attach),
DEVMETHOD(device_shutdown, bus_generic_shutdown),
DEVMETHOD(device_suspend, bus_generic_suspend),
DEVMETHOD(device_resume, bus_generic_resume),
/* Bus interface */
DEVMETHOD(bus_read_ivar, i81342_read_ivar),
DEVMETHOD(bus_write_ivar, i81342_write_ivar),
DEVMETHOD(bus_alloc_resource, i81342_pci_alloc_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, i81342_pci_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
DEVMETHOD(bus_setup_intr, i81342_pci_setup_intr),
DEVMETHOD(bus_teardown_intr, i81342_pci_teardown_intr),
/* pcib interface */
DEVMETHOD(pcib_maxslots, i81342_pci_maxslots),
DEVMETHOD(pcib_read_config, i81342_pci_read_config),
DEVMETHOD(pcib_write_config, i81342_pci_write_config),
DEVMETHOD(pcib_route_interrupt, i81342_pci_route_interrupt),
DEVMETHOD(pcib_request_feature, pcib_request_feature_allow),
DEVMETHOD_END
};
static driver_t i81342_pci_driver = {
"pcib",
i81342_pci_methods,
sizeof(struct i81342_pci_softc),
};
static devclass_t i81342_pci_devclass;
DRIVER_MODULE(ipci, iq, i81342_pci_driver, i81342_pci_devclass, 0, 0);

View File

@ -0,0 +1,234 @@
/* $NetBSD: i80321_space.c,v 1.6 2003/10/06 15:43:35 thorpej Exp $ */
/*-
* SPDX-License-Identifier: BSD-4-Clause
*
* Copyright (c) 2001, 2002 Wasabi Systems, Inc.
* All rights reserved.
*
* Written by Jason R. Thorpe for Wasabi Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed for the NetBSD Project by
* Wasabi Systems, Inc.
* 4. The name of Wasabi Systems, Inc. may not be used to endorse
* or promote products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* bus_space functions for i81342 I/O Processor.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/malloc.h>
#include <machine/pcb.h>
#include <vm/vm.h>
#include <vm/vm_kern.h>
#include <vm/pmap.h>
#include <vm/vm_page.h>
#include <vm/vm_extern.h>
#include <machine/bus.h>
#include <arm/xscale/i8134x/i81342reg.h>
#include <arm/xscale/i8134x/i81342var.h>
/* Prototypes for all the bus_space structure functions */
bs_protos(i81342);
bs_protos(i81342_io);
bs_protos(i81342_mem);
void
i81342_bs_init(bus_space_tag_t bs, void *cookie)
{
*bs = *arm_base_bs_tag;
bs->bs_privdata = cookie;
}
void
i81342_io_bs_init(bus_space_tag_t bs, void *cookie)
{
*bs = *arm_base_bs_tag;
bs->bs_privdata = cookie;
bs->bs_map = i81342_io_bs_map;
bs->bs_unmap = i81342_io_bs_unmap;
bs->bs_alloc = i81342_io_bs_alloc;
bs->bs_free = i81342_io_bs_free;
}
void
i81342_mem_bs_init(bus_space_tag_t bs, void *cookie)
{
*bs = *arm_base_bs_tag;
bs->bs_privdata = cookie;
bs->bs_map = i81342_mem_bs_map;
bs->bs_unmap = i81342_mem_bs_unmap;
bs->bs_alloc = i81342_mem_bs_alloc;
bs->bs_free = i81342_mem_bs_free;
}
/* *** Routines shared by i81342, PCI IO, and PCI MEM. *** */
int
i81342_bs_subregion(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t offset,
bus_size_t size, bus_space_handle_t *nbshp)
{
*nbshp = bsh + offset;
return (0);
}
void
i81342_bs_barrier(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t offset,
bus_size_t len, int flags)
{
/* Nothing to do. */
}
/* *** Routines for PCI IO. *** */
int
i81342_io_bs_map(bus_space_tag_t tag, bus_addr_t bpa, bus_size_t size, int flags,
bus_space_handle_t *bshp)
{
*bshp = bpa;
return (0);
}
void
i81342_io_bs_unmap(bus_space_tag_t tag, bus_space_handle_t h, bus_size_t size)
{
/* Nothing to do. */
}
int
i81342_io_bs_alloc(bus_space_tag_t tag, bus_addr_t rstart, bus_addr_t rend,
bus_size_t size, bus_size_t alignment, bus_size_t boundary, int flags,
bus_addr_t *bpap, bus_space_handle_t *bshp)
{
panic("i81342_io_bs_alloc(): not implemented");
}
void
i81342_io_bs_free(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t size)
{
panic("i81342_io_bs_free(): not implemented");
}
/* *** Routines for PCI MEM. *** */
extern int badaddr_read(void *, int, void *);
static vm_offset_t allocable = 0xe1000000;
int
i81342_mem_bs_map(bus_space_tag_t tag, bus_addr_t bpa, bus_size_t size, int flags,
bus_space_handle_t *bshp)
{
struct i81342_pci_softc *sc = (struct i81342_pci_softc *)tag->bs_privdata;
struct i81342_pci_map *tmp;
vm_offset_t addr, endaddr;
vm_paddr_t paddr;
/* Lookup to see if we already have a mapping at this address. */
tmp = sc->sc_pci_mappings;
while (tmp) {
if (tmp->paddr <= bpa && tmp->paddr + tmp->size >
bpa + size) {
*bshp = bpa - tmp->paddr + tmp->vaddr;
return (0);
}
tmp = tmp->next;
}
addr = allocable;
endaddr = rounddown2(addr + size, 0x1000000) + 0x1000000;
if (endaddr >= IOP34X_VADDR)
panic("PCI virtual memory exhausted");
allocable = endaddr;
tmp = malloc(sizeof(*tmp), M_DEVBUF, M_WAITOK);
tmp->next = NULL;
paddr = rounddown2(bpa, 0x100000);
tmp->paddr = paddr;
tmp->vaddr = addr;
tmp->size = 0;
while (addr < endaddr) {
pmap_kenter_supersection(addr, paddr + (sc->sc_is_atux ?
IOP34X_PCIX_OMBAR : IOP34X_PCIE_OMBAR), 0);
addr += 0x1000000;
paddr += 0x1000000;
tmp->size += 0x1000000;
}
tmp->next = sc->sc_pci_mappings;
sc->sc_pci_mappings = tmp;
*bshp = bpa - tmp->paddr + tmp->vaddr;
return (0);
}
void
i81342_mem_bs_unmap(bus_space_tag_t tag, bus_space_handle_t h, bus_size_t size)
{
#if 0
vm_offset_t va, endva;
va = trunc_page((vm_offset_t)h);
endva = va + round_page(size);
/* Free the kernel virtual mapping. */
kva_free(va, endva - va);
#endif
}
int
i81342_mem_bs_alloc(bus_space_tag_t tag, bus_addr_t rstart, bus_addr_t rend,
bus_size_t size, bus_size_t alignment, bus_size_t boundary, int flags,
bus_addr_t *bpap, bus_space_handle_t *bshp)
{
panic("i81342_mem_bs_alloc(): not implemented");
}
void
i81342_mem_bs_free(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t size)
{
panic("i81342_mem_bs_free(): not implemented");
}

View File

@ -0,0 +1,350 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2006 Olivier Houchard
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/* $FreeBSD$ */
#ifndef I83142_REG_H_
#define I83142_REG_H_
/* Physical Memory Map */
/*
* 0x000000000 - 0x07FFFFFFF SDRAM
* 0x090100000 - 0x0901FFFFF ATUe Outbound IO Window
* 0x0F0000000 - 0x0F1FFFFFF Flash
* 0x0F2000000 - 0x0F20FFFFF PCE1
* 0x0F3000000 - 0x0FFCFFFFF Compact Flash
* 0x0FFD00000 - 0x0FFDFFFFF MMR
* 0x0FFFB0000 - 0x0FFFBFFFF ATU-X Outbound I/O Window
* 0x0FFFD0000 - 0x0FFFDFFFF ATUe Outbound I/O Window
* 0x100000000 - 0x1FFFFFFFF ATU-X outbound Memory Translation Window
* 0x2FF000000 - 0x2FFFFFFFF ATUe Outbound Memory Translation Window
*/
#define IOP34X_VADDR 0xf0000000
#define IOP34X_HWADDR 0xffd00000
#define IOP34X_SIZE 0x100000
#define IOP34X_ADMA0_OFFSET 0x00080000
#define IOP34X_ADMA1_OFFSET 0x00080200
#define IOP34X_ADMA2_OFFSET 0x00080400
#define IOP34X_ADMA_SIZE 0x200
/* ADMA Registers */
#define IOP34X_ADMA_CCR 0x0000 /* Channel Control Register */
#define IOP34X_ADMA_CSR 0x0004 /* Channel Status Register */
#define IOP34X_ADMA_DAR 0x0008 /* Descriptor Address Register */
#define IOP34X_ADMA_IPCR 0x0018 /* Internal Interface Parity Ctrl Reg */
#define IOP34X_ADMA_NDAR 0x0024 /* Next Descriptor Register */
#define IOP34X_ADMA_DCR 0x0028 /* Descriptor Control Register */
#define IOP34X_ADMA_IE (1 << 0) /* Interrupt enable */
#define IOP34X_ADMA_TR (1 << 1) /* Transfert Direction */
/*
* Source Destination
* 00 Host I/O Interface Local Memory
* 01 Local Memory Host I/O Interface
* 10 Internal Bus Local Memory
* 11 Local Memory Internal Bus
*/
#define IOP34X_ADMA_SS (1 << 3) /* Source selection */
/* 0000: Data Transfer / CRC / Memory Block Fill */
#define IOP34X_ADMA_ZRBCE (1 << 7) /* Zero Result Buffer Check Enable */
#define IOP34X_ADMA_MBFE (1 << 8) /* Memory Block Fill Enable */
#define IOP34X_ADMA_CGE (1 << 9) /* CRC Generation enable */
#define IOP34X_ADMA_CTD (1 << 10) /* CRC Transfer disable */
#define IOP34X_ADMA_CSFD (1 << 11) /* CRC Seed fetch disable */
#define IOP34X_ADMA_SWBE (1 << 12) /* Status write back enable */
#define IOP34X_ADMA_ESE (1 << 13) /* Endian swap enable */
#define IOP34X_ADMA_PQUTE (1 << 16) /* P+Q Update Transfer Enable */
#define IOP34X_ADMA_DXE (1 << 17) /* Dual XOR Enable */
#define IOP34X_ADMA_PQTE (1 << 18) /* P+Q Transfer Enable */
#define IOP34X_ADMA_PTD (1 << 19) /* P Transfer Disable */
#define IOP34X_ADMA_ROE (1 << 30) /* Relaxed Ordering Enable */
#define IOP34X_ADMA_NSE (1U << 31) /* No Snoop Enable */
#define IOP34X_PBBAR0 0x81588 /* PBI Base Address Register 0 */
#define IOP34X_PBBAR0_ADDRMASK 0xfffff000
#define IOP34X_PBBAR1 0x81590
#define IOP34X_PCE1 0xF2000000
#define IOP34X_PCE1_SIZE 0x00100000
#define IOP34X_PCE1_VADDR 0xF1000000
#define IOP34X_ESSTSR0 0x82188
#define IOP34X_CONTROLLER_ONLY (1 << 14)
#define IOP34X_INT_SEL_PCIX (1 << 15)
#define IOP34X_PFR 0x82180 /* Processor Frequency Register */
#define IOP34X_FREQ_MASK ((1 << 16) | (1 << 17) | (1 << 18))
#define IOP34X_FREQ_600 (0)
#define IOP34X_FREQ_667 (1 << 16)
#define IOP34X_FREQ_800 (1 << 17)
#define IOP34X_FREQ_833 ((1 << 17) | (1 << 16))
#define IOP34X_FREQ_1000 (1 << 18)
#define IOP34X_FREQ_1200 ((1 << 16) | (1 << 18))
#define IOP34X_UART0_VADDR IOP34X_VADDR + 0x82300
#define IOP34X_UART0_HWADDR IOP34X_HWADDR + 0x82300
#define IOP34X_UART1_VADDR IOP34X_VADDR + 0x82340
#define IOP34X_UART1_HWADDR IOP34X_HWADDR + 0x82340
#define IOP34X_PBI_HWADDR 0xffd81580
/* SDRAM Memory Controller */
#define SMC_SDBR 0x8180c /* Base Register */
#define SMC_SDBR_BASEADDR (1 << 27)
#define SMC_SDBR_BASEADDR_MASK ((1 << 27) | (1 << 28) | (1 << 29) | (1 << 30) \
| (1U << 31))
#define SMC_SDUBR 0x81810 /* Upper Base Register */
#define SMC_SBSR 0x81814 /* SDRAM Bank Size Register */
#define SMC_SBSR_BANK_NB (1 << 2) /* Number of DDR Banks
0 => 2 Banks
1 => 1 Bank
*/
#define SMC_SBSR_BANK_SZ (1 << 27) /* SDRAM Bank Size :
0x00000 Empty
0x00001 128MB
0x00010 256MB
0x00100 512MB
0x01000 1GB
*/
#define SMC_SBSR_BANK_SZ_MASK ((1 << 27) | (1 << 28) | (1 << 29) | (1 << 30) \
| (1U << 31))
/* Two possible addresses for ATUe depending on configuration. */
#define IOP34X_ATUE_ADDR(esstrsr) ((((esstrsr) & (IOP34X_CONTROLLER_ONLY | \
IOP34X_INT_SEL_PCIX)) == (IOP34X_CONTROLLER_ONLY | IOP34X_INT_SEL_PCIX)) ? \
0xffdc8000 : 0xffdcd000)
/* Three possible addresses for ATU-X depending on configuration. */
#define IOP34X_ATUX_ADDR(esstrsr) (!((esstrsr) & IOP34X_CONTROLLER_ONLY) ? \
0xffdcc000 : !((esstrsr) & IOP34X_INT_SEL_PCIX) ? 0xffdc8000 : 0xffdcd000)
#define IOP34X_OIOBAR_SIZE 0x10000
#define IOP34X_PCIX_OIOBAR 0xfffb0000
#define IOP34X_PCIX_OIOBAR_VADDR 0xf01b0000
#define IOP34X_PCIX_OMBAR 0x100000000
#define IOP34X_PCIE_OIOBAR 0xfffd0000
#define IOP34X_PCIE_OIOBAR_VADDR 0xf01d0000
#define IOP34X_PCIE_OMBAR 0x200000000
/* ATU Registers */
/* Common for ATU-X and ATUe */
#define ATU_VID 0x0000 /* ATU Vendor ID */
#define ATU_DID 0x0002 /* ATU Device ID */
#define ATU_CMD 0x0004 /* ATU Command Register */
#define ATU_SR 0x0006 /* ATU Status Register */
#define ATU_RID 0x0008 /* ATU Revision ID */
#define ATU_CCR 0x0009 /* ATU Class Code */
#define ATU_CLSR 0x000c /* ATU Cacheline Size */
#define ATU_LT 0x000d /* ATU Latency Timer */
#define ATU_HTR 0x000e /* ATU Header Type */
#define ATU_BISTR 0x000f /* ATU BIST Register */
#define ATU_IABAR0 0x0010 /* Inbound ATU Base Address register 0 */
#define ATU_IAUBAR0 0x0014 /* Inbound ATU Upper Base Address Register 0 */
#define ATU_IABAR1 0x0018 /* Inbound ATU Base Address Register 1 */
#define ATU_IAUBAR1 0x001c /* Inbound ATU Upper Base Address Register 1 */
#define ATU_IABAR2 0x0020 /* Inbound ATU Base Address Register 2 */
#define ATU_IAUBAR2 0x0024 /* Inbound ATU Upper Base Address Register 2 */
#define ATU_VSIR 0x002c /* ATU Subsystem Vendor ID Register */
#define ATU_SIR 0x002e /* ATU Subsystem ID Register */
#define ATU_ERBAR 0x0030 /* Expansion ROM Base Address Register */
#define ATU_CAPPTR 0x0034 /* ATU Capabilities Pointer Register */
#define ATU_ILR 0x003c /* ATU Interrupt Line Register */
#define ATU_IPR 0x003d /* ATU Interrupt Pin Register */
#define ATU_MGNT 0x003e /* ATU Minimum Grand Register */
#define ATU_MLAT 0x003f /* ATU Maximum Latency Register */
#define ATU_IALR0 0x0040 /* Inbound ATU Limit Register 0 */
#define ATU_IATVR0 0x0044 /* Inbound ATU Translate Value Register 0 */
#define ATU_IAUTVR0 0x0048 /* Inbound ATU Upper Translate Value Register 0*/
#define ATU_IALR1 0x004c /* Inbound ATU Limit Register 1 */
#define ATU_IATVR1 0x0050 /* Inbound ATU Translate Value Register 1 */
#define ATU_IAUTVR1 0x0054 /* Inbound ATU Upper Translate Value Register 1*/
#define ATU_IALR2 0x0058 /* Inbound ATU Limit Register 2 */
#define ATU_IATVR2 0x005c /* Inbound ATU Translate Value Register 2 */
#define ATU_IAUTVR2 0x0060 /* Inbound ATU Upper Translate Value Register 2*/
#define ATU_ERLR 0x0064 /* Expansion ROM Limit Register */
#define ATU_ERTVR 0x0068 /* Expansion ROM Translator Value Register */
#define ATU_ERUTVR 0x006c /* Expansion ROM Upper Translate Value Register*/
#define ATU_CR 0x0070 /* ATU Configuration Register */
#define ATU_CR_OUT_EN (1 << 1)
#define ATU_PCSR 0x0074 /* PCI Configuration and Status Register */
#define PCIE_BUSNO(x) ((x & 0xff000000) >> 24)
#define ATUX_CORE_RST ((1 << 30) | (1U << 31)) /* Core Processor Reset */
#define ATUX_P_RSTOUT (1 << 21) /* Central Resource PCI Bus Reset */
#define ATUE_CORE_RST ((1 << 9) | (1 << 8)) /* Core Processor Reset */
#define ATU_ISR 0x0078 /* ATU Interrupt Status Register */
#define ATUX_ISR_PIE (1 << 18) /* PCI Interface error */
#define ATUX_ISR_IBPR (1 << 16) /* Internal Bus Parity Error */
#define ATUX_ISR_DCE (1 << 14) /* Detected Correctable error */
#define ATUX_ISR_ISCE (1 << 13) /* Initiated Split Completion Error Msg */
#define ATUX_ISR_RSCE (1 << 12) /* Received Split Completion Error Msg */
#define ATUX_ISR_DPE (1 << 9) /* Detected Parity Error */
#define ATUX_ISR_IBMA (1 << 7) /* Internal Bus Master Abort */
#define ATUX_ISR_PMA (1 << 3) /* PCI Master Abort */
#define ATUX_ISR_PTAM (1 << 2) /* PCI Target Abort (Master) */
#define ATUX_ISR_PTAT (1 << 1) /* PCI Target Abort (Target) */
#define ATUX_ISR_PMPE (1 << 0) /* PCI Master Parity Error */
#define ATUX_ISR_ERRMSK (ATUX_ISR_PIE | ATUX_ISR_IBPR | ATUX_ISR_DCE | \
ATUX_ISR_ISCE | ATUX_ISR_RSCE | ATUX_ISR_DPE | ATUX_ISR_IBMA | ATUX_ISR_PMA\
| ATUX_ISR_PTAM | ATUX_ISR_PTAT | ATUX_ISR_PMPE)
#define ATUE_ISR_HON (1 << 13) /* Halt on Error Interrupt */
#define ATUE_ISR_RSE (1 << 12) /* Root System Error Message */
#define ATUE_ISR_REM (1 << 11) /* Root Error Message */
#define ATUE_ISR_PIE (1 << 10) /* PCI Interface error */
#define ATUE_ISR_CEM (1 << 9) /* Correctable Error Message */
#define ATUE_ISR_UEM (1 << 8) /* Uncorrectable error message */
#define ATUE_ISR_CRS (1 << 7) /* Received Configuration Retry Status */
#define ATUE_ISR_IBMA (1 << 5) /* Internal Bus Master Abort */
#define ATUE_ISR_DPE (1 << 4) /* Detected Parity Error Interrupt */
#define ATUE_ISR_MAI (1 << 3) /* Received Master Abort Interrupt */
#define ATUE_ISR_STAI (1 << 2) /* Signaled Target Abort Interrupt */
#define ATUE_ISR_TAI (1 << 1) /* Received Target Abort Interrupt */
#define ATUE_ISR_MDPE (1 << 0) /* Master Data Parity Error Interrupt */
#define ATUE_ISR_ERRMSK (ATUE_ISR_HON | ATUE_ISR_RSE | ATUE_ISR_REM | \
ATUE_ISR_PIE | ATUE_ISR_CEM | ATUE_ISR_UEM | ATUE_ISR_CRS | ATUE_ISR_IBMA |\
ATUE_ISR_DPE | ATUE_ISR_MAI | ATUE_ISR_STAI | ATUE_ISR_TAI | ATUE_ISR_MDPE)
#define ATU_IMR 0x007c /* ATU Interrupt Mask Register */
/* 0x0080 - 0x008f reserved */
#define ATU_VPDCID 0x0090 /* VPD Capability Identifier Register */
#define ATU_VPDNIP 0x0091 /* VPD Next Item Pointer Register */
#define ATU_VPDAR 0x0092 /* VPD Address Register */
#define ATU_VPDDR 0x0094 /* VPD Data Register */
#define ATU_PMCID 0x0098 /* PM Capability Identifier Register */
#define ATU_PMNIPR 0x0099 /* PM Next Item Pointer Register */
#define ATU_PMCR 0x009a /* ATU Power Management Capabilities Register */
#define ATU_PMCSR 0x009c /* ATU Power Management Control/Status Register*/
#define ATU_MSICIR 0x00a0 /* MSI Capability Identifier Register */
#define ATU_MSINIPR 0x00a1 /* MSI Next Item Pointer Register */
#define ATU_MCR 0x00a2 /* Message Control Register */
#define ATU_MAR 0x00a4 /* Message Address Register */
#define ATU_MUAR 0x00a8 /* Message Upper Address Register */
#define ATU_MDR 0x00ac /* Message Data Register */
#define ATU_PCIXSR 0x00d4 /* PCI-X Status Register */
#define PCIXSR_BUSNO(x) (((x) & 0xff00) >> 8)
#define ATU_IABAR3 0x0200 /* Inbound ATU Base Address Register 3 */
#define ATU_IAUBAR3 0x0204 /* Inbound ATU Upper Base Address Register 3 */
#define ATU_IALR3 0x0208 /* Inbound ATU Limit Register 3 */
#define ATU_ITVR3 0x020c /* Inbound ATU Upper Translate Value Reg 3 */
#define ATU_OIOBAR 0x0300 /* Outbound I/O Base Address Register */
#define ATU_OIOWTVR 0x0304 /* Outbound I/O Window Translate Value Reg */
#define ATU_OUMBAR0 0x0308 /* Outbound Upper Memory Window base addr reg 0*/
#define ATU_OUMBAR_FUNC (28)
#define ATU_OUMBAR_EN (1U << 31)
#define ATU_OUMWTVR0 0x030c /* Outbound Upper 32bit Memory Window Translate Value Register 0 */
#define ATU_OUMBAR1 0x0310 /* Outbound Upper Memory Window base addr reg1*/
#define ATU_OUMWTVR1 0x0314 /* Outbound Upper 32bit Memory Window Translate Value Register 1 */
#define ATU_OUMBAR2 0x0318 /* Outbound Upper Memory Window base addr reg2*/
#define ATU_OUMWTVR2 0x031c /* Outbount Upper 32bit Memory Window Translate Value Register 2 */
#define ATU_OUMBAR3 0x0320 /* Outbound Upper Memory Window base addr reg3*/
#define ATU_OUMWTVR3 0x0324 /* Outbound Upper 32bit Memory Window Translate Value Register 3 */
/* ATU-X specific */
#define ATUX_OCCAR 0x0330 /* Outbound Configuration Cycle Address Reg */
#define ATUX_OCCDR 0x0334 /* Outbound Configuration Cycle Data Reg */
#define ATUX_OCCFN 0x0338 /* Outbound Configuration Cycle Function Number*/
/* ATUe specific */
#define ATUE_OCCAR 0x032c /* Outbound Configuration Cycle Address Reg */
#define ATUE_OCCDR 0x0330 /* Outbound Configuration Cycle Data Reg */
#define ATUE_OCCFN 0x0334 /* Outbound Configuration Cycle Function Number*/
/* Interrupts */
/* IINTRSRC0 */
#define ICU_INT_ADMA0_EOT (0) /* ADMA 0 End of transfer */
#define ICU_INT_ADMA0_EOC (1) /* ADMA 0 End of Chain */
#define ICU_INT_ADMA1_EOT (2) /* ADMA 1 End of transfer */
#define ICU_INT_ADMA1_EOC (3) /* ADMA 1 End of chain */
#define ICU_INT_ADMA2_EOT (4) /* ADMA 2 End of transfer */
#define ICU_INT_ADMA2_EOC (5) /* ADMA 2 end of chain */
#define ICU_INT_WDOG (6) /* Watchdog timer */
/* 7 Reserved */
#define ICU_INT_TIMER0 (8) /* Timer 0 */
#define ICU_INT_TIMER1 (9) /* Timer 1 */
#define ICU_INT_I2C0 (10) /* I2C bus interface 0 */
#define ICU_INT_I2C1 (11) /* I2C bus interface 1 */
#define ICU_INT_MU (12) /* Message Unit */
#define ICU_INT_MU_IPQ (13) /* Message unit inbound post queue */
#define ICU_INT_ATUE_IM (14) /* ATU-E inbound message */
#define ICU_INT_ATU_BIST (15) /* ATU/Start BIST */
#define ICU_INT_PMC (16) /* PMC */
#define ICU_INT_PMU (17) /* PMU */
#define ICU_INT_PC (18) /* Processor cache */
/* 19-23 Reserved */
#define ICU_INT_XINT0 (24)
#define ICU_INT_XINT1 (25)
#define ICU_INT_XINT2 (26)
#define ICU_INT_XINT3 (27)
#define ICU_INT_XINT4 (28)
#define ICU_INT_XINT5 (29)
#define ICU_INT_XINT6 (30)
#define ICU_INT_XINT7 (31)
/* IINTSRC1 */
#define ICU_INT_XINT8 (32)
#define ICU_INT_XINT9 (33)
#define ICU_INT_XINT10 (34)
#define ICU_INT_XINT11 (35)
#define ICU_INT_XINT12 (36)
#define ICU_INT_XINT13 (37)
#define ICU_INT_XINT14 (38)
#define ICU_INT_XINT15 (39)
/* 40-50 reserved */
#define ICU_INT_UART0 (51) /* UART 0 */
#define ICU_INT_UART1 (52) /* UART 1 */
#define ICU_INT_PBIUE (53) /* Peripheral bus interface unit error */
#define ICU_INT_ATUCRW (54) /* ATU Configuration register write */
#define ICU_INT_ATUE (55) /* ATU error */
#define ICU_INT_MCUE (56) /* Memory controller unit error */
#define ICU_INT_ADMA0E (57) /* ADMA Channel 0 error */
#define ICU_INT_ADMA1E (58) /* ADMA Channel 1 error */
#define ICU_INT_ADMA2E (59) /* ADMA Channel 2 error */
/* 60-61 reserved */
#define ICU_INT_MUE (62) /* Messaging Unit Error */
/* 63 reserved */
/* IINTSRC2 */
#define ICU_INT_IP (64) /* Inter-processor */
/* 65-93 reserved */
#define ICU_INT_SIBBE (94) /* South internal bus bridge error */
/* 95 reserved */
/* IINTSRC3 */
#define ICU_INT_I2C2 (96) /* I2C bus interface 2 */
#define ICU_INT_ATUE_BIST (97) /* ATU-E/Start BIST */
#define ICU_INT_ATUE_CRW (98) /* ATU-E Configuration register write */
#define ICU_INT_ATUEE (99) /* ATU-E Error */
#define ICU_INT_IMU (100) /* IMU */
/* 101-106 reserved */
#define ICU_INT_ATUE_MA (107) /* ATUE Interrupt message A */
#define ICU_INT_ATUE_MB (108) /* ATUE Interrupt message B */
#define ICU_INT_ATUE_MC (109) /* ATUE Interrupt message C */
#define ICU_INT_ATUE_MD (110) /* ATUE Interrupt message D */
#define ICU_INT_MU_MSIX_TW (111) /* MU MSI-X Table write */
/* 112 reserved */
#define ICU_INT_IMSI (113) /* Inbound MSI */
/* 114-126 reserved */
#define ICU_INT_HPI (127) /* HPI */
#endif /* I81342_REG_H_ */

View File

@ -0,0 +1,72 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2006 Olivier Houchard
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/* $FreeBSD$ */
#ifndef I81342VAR_H_
#define I81342VAR_H_
#include <sys/rman.h>
struct i81342_softc {
device_t dev;
bus_space_tag_t sc_st;
bus_space_handle_t sc_sh;
bus_space_handle_t sc_atux_sh;
bus_space_handle_t sc_atue_sh;
bus_space_tag_t sc_pciio;
bus_space_tag_t sc_pcimem;
struct rman sc_irq_rman;
};
struct i81342_pci_map {
vm_offset_t vaddr;
vm_paddr_t paddr;
vm_size_t size;
struct i81342_pci_map *next;
};
struct i81342_pci_softc {
device_t sc_dev;
bus_space_tag_t sc_st;
bus_space_handle_t sc_atu_sh;
struct bus_space sc_pciio;
struct bus_space sc_pcimem;
struct rman sc_mem_rman;
struct rman sc_io_rman;
struct rman sc_irq_rman;
char sc_is_atux;
int sc_busno;
struct i81342_pci_map *sc_pci_mappings;
};
void i81342_bs_init(bus_space_tag_t, void *);
void i81342_io_bs_init(bus_space_tag_t, void *);
void i81342_mem_bs_init(bus_space_tag_t, void *);
void i81342_sdram_bounds(bus_space_tag_t, bus_space_handle_t, vm_paddr_t *,
vm_size_t *);
#endif /*I81342VAR_H_ */

View File

@ -0,0 +1,393 @@
/* $NetBSD: iq31244_7seg.c,v 1.2 2003/07/15 00:25:01 lukem Exp $ */
/*-
* SPDX-License-Identifier: BSD-4-Clause
*
* Copyright (c) 2001, 2002, 2003 Wasabi Systems, Inc.
* All rights reserved.
*
* Written by Jason R. Thorpe for Wasabi Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed for the NetBSD Project by
* Wasabi Systems, Inc.
* 4. The name of Wasabi Systems, Inc. may not be used to endorse
* or promote products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Support for the 7-segment display on the Intel IQ81342.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/bus.h>
#include <sys/sysctl.h>
#include <machine/bus.h>
#include <arm/xscale/i8134x/i81342reg.h>
#include <arm/xscale/i8134x/iq81342reg.h>
#include <arm/xscale/i8134x/iq81342var.h>
#define WRITE(x, v) *((__volatile uint8_t *) (x)) = (v)
static int snakestate;
/*
* The 7-segment display looks like so:
*
* A
* +-----+
* | |
* F | | B
* | G |
* +-----+
* | |
* E | | C
* | D |
* +-----+ o DP
*
* Setting a bit clears the corresponding segment on the
* display.
*/
#define SEG_A (1 << 1)
#define SEG_B (1 << 2)
#define SEG_C (1 << 3)
#define SEG_D (1 << 4)
#define SEG_E (1 << 5)
#define SEG_F (1 << 6)
#define SEG_G (1 << 7)
#define SEG_DP (1 << 0)
static const uint8_t digitmap[] = {
/* +#####+
* # #
* # #
* # #
* +-----+
* # #
* # #
* # #
* +#####+
*/
(unsigned char)~SEG_G,
/* +-----+
* | #
* | #
* | #
* +-----+
* | #
* | #
* | #
* +-----+
*/
SEG_B|SEG_C,
/* +#####+
* | #
* | #
* | #
* +#####+
* # |
* # |
* # |
* +#####+
*/
~(SEG_C|SEG_F),
/* +#####+
* | #
* | #
* | #
* +#####+
* | #
* | #
* | #
* +#####+
*/
~(SEG_E|SEG_F),
/* +-----+
* # #
* # #
* # #
* +#####+
* | #
* | #
* | #
* +-----+
*/
~(SEG_A|SEG_D|SEG_E),
/* +#####+
* # |
* # |
* # |
* +#####+
* | #
* | #
* | #
* +#####+
*/
~(SEG_B|SEG_E),
/* +#####+
* # |
* # |
* # |
* +#####+
* # #
* # #
* # #
* +#####+
*/
~(SEG_B),
/* +#####+
* | #
* | #
* | #
* +-----+
* | #
* | #
* | #
* +-----+
*/
~(SEG_D|SEG_E|SEG_F),
/* +#####+
* # #
* # #
* # #
* +#####+
* # #
* # #
* # #
* +#####+
*/
~0,
/* +#####+
* # #
* # #
* # #
* +#####+
* | #
* | #
* | #
* +-----+
*/
~(SEG_D|SEG_E),
};
static uint8_t
iq81342_7seg_xlate(char c)
{
uint8_t rv;
if (c >= '0' && c <= '9')
rv = digitmap[c - '0'];
else if (c == '.')
rv = (uint8_t) ~SEG_DP;
else
rv = 0xff;
return (rv);
}
void
iq81342_7seg(char a, char b)
{
uint8_t msb, lsb;
msb = iq81342_7seg_xlate(a);
lsb = iq81342_7seg_xlate(b);
snakestate = 0;
WRITE(IQ8134X_7SEG_MSB, msb);
WRITE(IQ8134X_7SEG_LSB, lsb);
}
static const uint8_t snakemap[][2] = {
/* +#####+ +#####+
* | | | |
* | | | |
* | | | |
* +-----+ +-----+
* | | | |
* | | | |
* | | | |
* +-----+ +-----+
*/
{ SEG_A, SEG_A },
/* +-----+ +-----+
* # | | #
* # | | #
* # | | #
* +-----+ +-----+
* | | | |
* | | | |
* | | | |
* +-----+ +-----+
*/
{ SEG_F, SEG_B },
/* +-----+ +-----+
* | | | |
* | | | |
* | | | |
* +#####+ +#####+
* | | | |
* | | | |
* | | | |
* +-----+ +-----+
*/
{ SEG_G, SEG_G },
/* +-----+ +-----+
* | | | |
* | | | |
* | | | |
* +-----+ +-----+
* | # # |
* | # # |
* | # # |
* +-----+ +-----+
*/
{ SEG_C, SEG_E },
/* +-----+ +-----+
* | | | |
* | | | |
* | | | |
* +-----+ +-----+
* | | | |
* | | | |
* | | | |
* +#####+ +#####+
*/
{ SEG_D, SEG_D },
/* +-----+ +-----+
* | | | |
* | | | |
* | | | |
* +-----+ +-----+
* # | | #
* # | | #
* # | | #
* +-----+ +-----+
*/
{ SEG_E, SEG_C },
/* +-----+ +-----+
* | | | |
* | | | |
* | | | |
* +#####+ +#####+
* | | | |
* | | | |
* | | | |
* +-----+ +-----+
*/
{ SEG_G, SEG_G },
/* +-----+ +-----+
* | # # |
* | # # |
* | # # |
* +-----+ +-----+
* | | | |
* | | | |
* | | | |
* +-----+ +-----+
*/
{ SEG_B, SEG_F },
};
static SYSCTL_NODE(_hw, OID_AUTO, sevenseg, CTLFLAG_RD, 0, "7 seg");
static int freq = 20;
SYSCTL_INT(_hw_sevenseg, OID_AUTO, freq, CTLFLAG_RW, &freq, 0,
"7 Seg update frequency");
static void
iq81342_7seg_snake(void)
{
static int snakefreq;
int cur = snakestate;
snakefreq++;
if ((snakefreq % freq))
return;
WRITE(IQ8134X_7SEG_MSB, snakemap[cur][0]);
WRITE(IQ8134X_7SEG_LSB, snakemap[cur][1]);
snakestate = (cur + 1) & 7;
}
struct iq81342_7seg_softc {
device_t dev;
};
static int
iq81342_7seg_probe(device_t dev)
{
device_set_desc(dev, "IQ81342 7seg");
return (0);
}
extern void (*i80321_hardclock_hook)(void);
static int
iq81342_7seg_attach(device_t dev)
{
i80321_hardclock_hook = iq81342_7seg_snake;
return (0);
}
static device_method_t iq81342_7seg_methods[] = {
DEVMETHOD(device_probe, iq81342_7seg_probe),
DEVMETHOD(device_attach, iq81342_7seg_attach),
{0, 0},
};
static driver_t iq81342_7seg_driver = {
"iqseg",
iq81342_7seg_methods,
sizeof(struct iq81342_7seg_softc),
};
static devclass_t iq81342_7seg_devclass;
DRIVER_MODULE(iqseg, iq, iq81342_7seg_driver, iq81342_7seg_devclass, 0, 0);

View File

@ -0,0 +1,35 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2006 Olivier Houchard
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/* $FreeBSD$ */
#ifndef _IQ81342REG_H_
#define _IQ81342REG_H_
#define IQ8134X_7SEG_MSB IOP34X_PCE1_VADDR + 0x40000
#define IQ8134X_7SEG_LSB IOP34X_PCE1_VADDR + 0x50000
#endif /* _IQ81342REG_H_ */

View File

@ -0,0 +1,34 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2006 Olivier Houchard
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/* $FreeBSD$ */
#ifndef _IQ81342VAR_H_
#define _IQ81342VAR_H_
void iq81342_7seg(char, char);
#endif /* _I8Q1342VAR_H_ */

View File

@ -0,0 +1,168 @@
/* $NetBSD: obio.c,v 1.11 2003/07/15 00:25:05 lukem Exp $ */
/*-
* SPDX-License-Identifier: BSD-4-Clause
*
* Copyright (c) 2001, 2002, 2003 Wasabi Systems, Inc.
* All rights reserved.
*
* Written by Jason R. Thorpe for Wasabi Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed for the NetBSD Project by
* Wasabi Systems, Inc.
* 4. The name of Wasabi Systems, Inc. may not be used to endorse
* or promote products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* On-board device autoconfiguration support for Intel IQ80321
* evaluation boards.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/rman.h>
#include <sys/malloc.h>
#include <machine/bus.h>
#include <arm/xscale/i8134x/i81342reg.h>
#include <arm/xscale/i8134x/obiovar.h>
static int
obio_probe(device_t dev)
{
return (0);
}
static int
obio_attach(device_t dev)
{
struct obio_softc *sc = device_get_softc(dev);
sc->oba_st = arm_base_bs_tag;
sc->oba_rman.rm_type = RMAN_ARRAY;
sc->oba_rman.rm_descr = "OBIO I/O";
if (rman_init(&sc->oba_rman) != 0 ||
rman_manage_region(&sc->oba_rman,
IOP34X_UART0_VADDR, IOP34X_UART1_VADDR + 0x40) != 0)
panic("obio_attach: failed to set up I/O rman");
sc->oba_irq_rman.rm_type = RMAN_ARRAY;
sc->oba_irq_rman.rm_descr = "OBIO IRQ";
if (rman_init(&sc->oba_irq_rman) != 0 ||
rman_manage_region(&sc->oba_irq_rman, ICU_INT_UART0, ICU_INT_UART1) != 0)
panic("obio_attach: failed to set up IRQ rman");
device_add_child(dev, "uart", 0);
device_add_child(dev, "uart", 1);
bus_generic_probe(dev);
bus_generic_attach(dev);
return (0);
}
static struct resource *
obio_alloc_resource(device_t bus, device_t child, int type, int *rid,
rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
{
struct resource *rv;
struct rman *rm;
bus_space_tag_t bt = NULL;
bus_space_handle_t bh = 0;
struct obio_softc *sc = device_get_softc(bus);
int unit = device_get_unit(child);
switch (type) {
case SYS_RES_IRQ:
rm = &sc->oba_irq_rman;
if (unit == 0)
start = end = ICU_INT_UART0;
else
start = end = ICU_INT_UART1;
break;
case SYS_RES_MEMORY:
return (NULL);
case SYS_RES_IOPORT:
rm = &sc->oba_rman;
bt = sc->oba_st;
if (unit == 0) {
bh = IOP34X_UART0_VADDR;
start = bh;
end = IOP34X_UART1_VADDR;
} else {
bh = IOP34X_UART1_VADDR;
start = bh;
end = start + 0x40;
}
break;
default:
return (NULL);
}
rv = rman_reserve_resource(rm, start, end, count, flags, child);
if (rv == NULL)
return (NULL);
if (type == SYS_RES_IRQ)
return (rv);
rman_set_rid(rv, *rid);
rman_set_bustag(rv, bt);
rman_set_bushandle(rv, bh);
return (rv);
}
static int
obio_activate_resource(device_t bus, device_t child, int type, int rid,
struct resource *r)
{
return (0);
}
static device_method_t obio_methods[] = {
DEVMETHOD(device_probe, obio_probe),
DEVMETHOD(device_attach, obio_attach),
DEVMETHOD(bus_alloc_resource, obio_alloc_resource),
DEVMETHOD(bus_activate_resource, obio_activate_resource),
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
{0, 0},
};
static driver_t obio_driver = {
"obio",
obio_methods,
sizeof(struct obio_softc),
};
static devclass_t obio_devclass;
DRIVER_MODULE(obio, iq, obio_driver, obio_devclass, 0, 0);

View File

@ -0,0 +1,56 @@
/* $NetBSD: obiovar.h,v 1.4 2003/06/16 17:40:53 thorpej Exp $ */
/*-
* SPDX-License-Identifier: BSD-4-Clause
*
* Copyright (c) 2002, 2003 Wasabi Systems, Inc.
* All rights reserved.
*
* Written by Jason R. Thorpe for Wasabi Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed for the NetBSD Project by
* Wasabi Systems, Inc.
* 4. The name of Wasabi Systems, Inc. may not be used to endorse
* or promote products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*
*/
#ifndef _IQ81342_OBIOVAR_H_
#define _IQ81342_OBIOVAR_H_
#include <sys/rman.h>
struct obio_softc {
bus_space_tag_t oba_st; /* bus space tag */
int oba_irq; /* XINT interrupt bit # */
struct rman oba_rman;
struct rman oba_irq_rman;
};
#endif /* _IQ80321_OBIOVAR_H_ */

View File

@ -0,0 +1,6 @@
#CRB board configuration
#$FreeBSD$
include "../xscale/i8134x/std.i81342"
files "../xscale/i8134x/files.crb"
makeoptions KERNPHYSADDR=0x00200000
makeoptions KERNVIRTADDR=0xc0200000

View File

@ -0,0 +1,6 @@
#XScale i81342 generic configuration
#$FreeBSD$
files "../xscale/i8134x/files.i81342"
include "../xscale/std.xscale"
cpu CPU_XSCALE_81342
machine arm

View File

@ -0,0 +1,94 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2004 Olivier Houchard. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <machine/bus.h>
#include <sys/rman.h>
#include <machine/resource.h>
#include <dev/pci/pcivar.h>
#include <dev/uart/uart.h>
#include <dev/uart/uart_bus.h>
#include <dev/uart/uart_cpu.h>
#include <dev/ic/ns16550.h>
#include "uart_if.h"
static int uart_i81342_probe(device_t dev);
static device_method_t uart_i81342_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, uart_i81342_probe),
DEVMETHOD(device_attach, uart_bus_attach),
DEVMETHOD(device_detach, uart_bus_detach),
{ 0, 0 }
};
static driver_t uart_i81342_driver = {
uart_driver_name,
uart_i81342_methods,
sizeof(struct uart_softc),
};
extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs;
static int
uart_i81342_probe(device_t dev)
{
struct uart_softc *sc;
int err;
sc = device_get_softc(dev);
sc->sc_class = &uart_ns8250_class;
if (device_get_unit(dev) == 0) {
sc->sc_sysdev = SLIST_FIRST(&uart_sysdevs);
bcopy(&sc->sc_sysdev->bas, &sc->sc_bas, sizeof(sc->sc_bas));
}
sc->sc_rres = bus_alloc_resource_anywhere(dev, SYS_RES_IOPORT,
&sc->sc_rrid, uart_getrange(sc->sc_class), RF_ACTIVE);
sc->sc_bas.bsh = rman_get_bushandle(sc->sc_rres);
sc->sc_bas.bst = rman_get_bustag(sc->sc_rres);
bus_space_write_4(sc->sc_bas.bst, sc->sc_bas.bsh, REG_IER << 2,
0x40 | 0x10);
bus_release_resource(dev, sc->sc_rtype, sc->sc_rrid, sc->sc_rres);
err = uart_bus_probe(dev, 2, 0, 33334000, 0, device_get_unit(dev));
sc->sc_rxfifosz = sc->sc_txfifosz = 1;
return (err);
}
DRIVER_MODULE(uart, obio, uart_i81342_driver, uart_devclass, 0, 0);

View File

@ -0,0 +1,70 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2003 Marcel Moolenaar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/cons.h>
#include <machine/bus.h>
#include <dev/uart/uart.h>
#include <dev/uart/uart_cpu.h>
#include <arm/xscale/i8134x/i81342reg.h>
#include <arm/xscale/i8134x/obiovar.h>
bus_space_tag_t uart_bus_space_io;
bus_space_tag_t uart_bus_space_mem;
int
uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2)
{
return ((b1->bsh == b2->bsh && b1->bst == b2->bst) ? 1 : 0);
}
int
uart_cpu_getdev(int devtype, struct uart_devinfo *di)
{
di->ops = uart_getops(&uart_ns8250_class);
di->bas.chan = 0;
di->bas.bst = arm_base_bs_tag;
di->bas.regshft = 2;
di->bas.rclk = 33334000;
di->baudrate = 115200;
di->databits = 8;
di->stopbits = 1;
di->parity = UART_PARITY_NONE;
uart_bus_space_io = arm_base_bs_tag;
uart_bus_space_mem = NULL;
di->bas.bsh = IOP34X_UART0_VADDR;
return (0);
}

View File

@ -0,0 +1,14 @@
# $FreeBSD$
arm/xscale/pxa/pxa_gpio.c standard
arm/xscale/pxa/pxa_icu.c standard
arm/xscale/pxa/pxa_machdep.c standard
arm/xscale/pxa/pxa_obio.c standard
arm/xscale/pxa/pxa_smi.c standard
arm/xscale/pxa/pxa_space.c standard
arm/xscale/pxa/pxa_timer.c standard
arm/xscale/pxa/uart_bus_pxa.c optional uart
arm/xscale/pxa/uart_cpu_pxa.c optional uart
arm/xscale/pxa/if_smc_smi.c optional smc

View File

@ -0,0 +1,127 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2008 Benno Rice
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/taskqueue.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <net/ethernet.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <net/if_media.h>
#include <dev/smc/if_smcvar.h>
#include <dev/mii/mii.h>
#include <dev/mii/miivar.h>
#include "miibus_if.h"
#include <arm/xscale/pxa/pxareg.h>
#include <arm/xscale/pxa/pxavar.h>
static int smc_smi_probe(device_t);
static int smc_smi_attach(device_t);
static int smc_smi_detach(device_t);
static int
smc_smi_probe(device_t dev)
{
struct smc_softc *sc;
sc = device_get_softc(dev);
sc->smc_usemem = 1;
if (smc_probe(dev) != 0) {
return (ENXIO);
}
return (0);
}
static int
smc_smi_attach(device_t dev)
{
int err;
struct smc_softc *sc;
sc = device_get_softc(dev);
err = smc_attach(dev);
if (err) {
return (err);
}
return (0);
}
static int
smc_smi_detach(device_t dev)
{
smc_detach(dev);
return (0);
}
static device_method_t smc_smi_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, smc_smi_probe),
DEVMETHOD(device_attach, smc_smi_attach),
DEVMETHOD(device_detach, smc_smi_detach),
/* MII interface */
DEVMETHOD(miibus_readreg, smc_miibus_readreg),
DEVMETHOD(miibus_writereg, smc_miibus_writereg),
DEVMETHOD(miibus_statchg, smc_miibus_statchg),
{ 0, 0 }
};
static driver_t smc_smi_driver = {
"smc",
smc_smi_methods,
sizeof(struct smc_softc),
};
extern devclass_t smc_devclass;
DRIVER_MODULE(smc, smi, smc_smi_driver, smc_devclass, 0, 0);
DRIVER_MODULE(miibus, smc, miibus_driver, miibus_devclass, 0, 0);
MODULE_DEPEND(smc, smi, 1, 1, 1);
MODULE_DEPEND(smc, ether, 1, 1, 1);
MODULE_DEPEND(smc, miibus, 1, 1, 1);

View File

@ -0,0 +1,360 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2006 Benno Rice. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/interrupt.h>
#include <sys/module.h>
#include <sys/malloc.h>
#include <sys/mutex.h>
#include <sys/rman.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/timetc.h>
#include <machine/bus.h>
#include <machine/intr.h>
#include <arm/xscale/pxa/pxavar.h>
#include <arm/xscale/pxa/pxareg.h>
struct pxa_gpio_softc {
struct resource * pg_res[4];
bus_space_tag_t pg_bst;
bus_space_handle_t pg_bsh;
struct mtx pg_mtx;
uint32_t pg_intr[3];
};
static struct resource_spec pxa_gpio_spec[] = {
{ SYS_RES_MEMORY, 0, RF_ACTIVE },
{ SYS_RES_IRQ, 0, RF_ACTIVE },
{ SYS_RES_IRQ, 1, RF_ACTIVE },
{ SYS_RES_IRQ, 2, RF_ACTIVE },
{ -1, 0 }
};
static struct pxa_gpio_softc *pxa_gpio_softc = NULL;
static int pxa_gpio_probe(device_t);
static int pxa_gpio_attach(device_t);
static driver_filter_t pxa_gpio_intr0;
static driver_filter_t pxa_gpio_intr1;
static driver_filter_t pxa_gpio_intrN;
static int
pxa_gpio_probe(device_t dev)
{
device_set_desc(dev, "GPIO Controller");
return (0);
}
static int
pxa_gpio_attach(device_t dev)
{
int error;
void *ihl;
struct pxa_gpio_softc *sc;
sc = (struct pxa_gpio_softc *)device_get_softc(dev);
if (pxa_gpio_softc != NULL)
return (ENXIO);
pxa_gpio_softc = sc;
error = bus_alloc_resources(dev, pxa_gpio_spec, sc->pg_res);
if (error) {
device_printf(dev, "could not allocate resources\n");
return (ENXIO);
}
sc->pg_bst = rman_get_bustag(sc->pg_res[0]);
sc->pg_bsh = rman_get_bushandle(sc->pg_res[0]);
/* Disable and clear all interrupts. */
bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GRER0, 0);
bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GRER1, 0);
bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GRER2, 0);
bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GFER0, 0);
bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GFER1, 0);
bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GFER2, 0);
bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR0, ~0);
bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR1, ~0);
bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR2, ~0);
mtx_init(&sc->pg_mtx, "GPIO mutex", NULL, MTX_SPIN);
if (bus_setup_intr(dev, sc->pg_res[1], INTR_TYPE_MISC|INTR_MPSAFE,
pxa_gpio_intr0, NULL, sc, &ihl) != 0) {
bus_release_resources(dev, pxa_gpio_spec, sc->pg_res);
device_printf(dev, "could not set up intr0\n");
return (ENXIO);
}
if (bus_setup_intr(dev, sc->pg_res[2], INTR_TYPE_MISC|INTR_MPSAFE,
pxa_gpio_intr1, NULL, sc, &ihl) != 0) {
bus_release_resources(dev, pxa_gpio_spec, sc->pg_res);
device_printf(dev, "could not set up intr1\n");
return (ENXIO);
}
if (bus_setup_intr(dev, sc->pg_res[3], INTR_TYPE_MISC|INTR_MPSAFE,
pxa_gpio_intrN, NULL, sc, &ihl) != 0) {
bus_release_resources(dev, pxa_gpio_spec, sc->pg_res);
device_printf(dev, "could not set up intrN\n");
return (ENXIO);
}
return (0);
}
static int
pxa_gpio_intr0(void *arg)
{
struct pxa_gpio_softc *sc;
sc = (struct pxa_gpio_softc *)arg;
bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR0, 0x1);
sc->pg_intr[0] |= 1;
return (FILTER_HANDLED);
}
static int
pxa_gpio_intr1(void *arg)
{
struct pxa_gpio_softc *sc;
sc = (struct pxa_gpio_softc *)arg;
bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR0, 0x2);
sc->pg_intr[1] |= 2;
return (FILTER_HANDLED);
}
static int
pxa_gpio_intrN(void *arg)
{
uint32_t gedr0, gedr1, gedr2;
struct pxa_gpio_softc *sc;
sc = (struct pxa_gpio_softc *)arg;
gedr0 = bus_space_read_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR0);
gedr0 &= 0xfffffffc;
bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR0, gedr0);
gedr1 = bus_space_read_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR1);
bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR1, gedr1);
gedr2 = bus_space_read_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR2);
gedr2 &= 0x001fffff;
bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR2, gedr2);
sc->pg_intr[0] |= gedr0;
sc->pg_intr[1] |= gedr1;
sc->pg_intr[2] |= gedr2;
return (FILTER_HANDLED);
}
static device_method_t pxa_gpio_methods[] = {
DEVMETHOD(device_probe, pxa_gpio_probe),
DEVMETHOD(device_attach, pxa_gpio_attach),
{0, 0}
};
static driver_t pxa_gpio_driver = {
"gpio",
pxa_gpio_methods,
sizeof(struct pxa_gpio_softc),
};
static devclass_t pxa_gpio_devclass;
DRIVER_MODULE(pxagpio, pxa, pxa_gpio_driver, pxa_gpio_devclass, 0, 0);
#define pxagpio_reg_read(softc, reg) \
bus_space_read_4(sc->pg_bst, sc->pg_bsh, reg)
#define pxagpio_reg_write(softc, reg, val) \
bus_space_write_4(sc->pg_bst, sc->pg_bsh, reg, val)
uint32_t
pxa_gpio_get_function(int gpio)
{
struct pxa_gpio_softc *sc;
uint32_t rv, io;
sc = pxa_gpio_softc;
rv = pxagpio_reg_read(sc, GPIO_FN_REG(gpio)) >> GPIO_FN_SHIFT(gpio);
rv = GPIO_FN(rv);
io = pxagpio_reg_read(sc, PXA250_GPIO_REG(GPIO_GPDR0, gpio));
if (io & GPIO_BIT(gpio))
rv |= GPIO_OUT;
io = pxagpio_reg_read(sc, PXA250_GPIO_REG(GPIO_GPLR0, gpio));
if (io & GPIO_BIT(gpio))
rv |= GPIO_SET;
return (rv);
}
uint32_t
pxa_gpio_set_function(int gpio, uint32_t fn)
{
struct pxa_gpio_softc *sc;
uint32_t rv, bit, oldfn;
sc = pxa_gpio_softc;
oldfn = pxa_gpio_get_function(gpio);
if (GPIO_FN(fn) == GPIO_FN(oldfn) &&
GPIO_FN_IS_OUT(fn) == GPIO_FN_IS_OUT(oldfn)) {
/*
* The pin's function is not changing.
* For Alternate Functions and GPIO input, we can just
* return now.
* For GPIO output pins, check the initial state is
* the same.
*
* Return 'fn' instead of 'oldfn' so the caller can
* reliably detect that we didn't change anything.
* (The initial state might be different for non-
* GPIO output pins).
*/
if (!GPIO_IS_GPIO_OUT(fn) ||
GPIO_FN_IS_SET(fn) == GPIO_FN_IS_SET(oldfn))
return (fn);
}
/*
* See section 4.1.3.7 of the PXA2x0 Developer's Manual for
* the correct procedure for changing GPIO pin functions.
*/
bit = GPIO_BIT(gpio);
/*
* 1. Configure the correct set/clear state of the pin
*/
if (GPIO_FN_IS_SET(fn))
pxagpio_reg_write(sc, PXA250_GPIO_REG(GPIO_GPSR0, gpio), bit);
else
pxagpio_reg_write(sc, PXA250_GPIO_REG(GPIO_GPCR0, gpio), bit);
/*
* 2. Configure the pin as an input or output as appropriate
*/
rv = pxagpio_reg_read(sc, PXA250_GPIO_REG(GPIO_GPDR0, gpio)) & ~bit;
if (GPIO_FN_IS_OUT(fn))
rv |= bit;
pxagpio_reg_write(sc, PXA250_GPIO_REG(GPIO_GPDR0, gpio), rv);
/*
* 3. Configure the pin's function
*/
bit = GPIO_FN_MASK << GPIO_FN_SHIFT(gpio);
fn = GPIO_FN(fn) << GPIO_FN_SHIFT(gpio);
rv = pxagpio_reg_read(sc, GPIO_FN_REG(gpio)) & ~bit;
pxagpio_reg_write(sc, GPIO_FN_REG(gpio), rv | fn);
return (oldfn);
}
/*
* GPIO "interrupt" handling.
*/
void
pxa_gpio_mask_irq(int irq)
{
uint32_t val;
struct pxa_gpio_softc *sc;
int gpio;
sc = pxa_gpio_softc;
gpio = IRQ_TO_GPIO(irq);
val = pxagpio_reg_read(sc, PXA250_GPIO_REG(GPIO_GRER0, gpio));
val &= ~GPIO_BIT(gpio);
pxagpio_reg_write(sc, PXA250_GPIO_REG(GPIO_GRER0, gpio), val);
}
void
pxa_gpio_unmask_irq(int irq)
{
uint32_t val;
struct pxa_gpio_softc *sc;
int gpio;
sc = pxa_gpio_softc;
gpio = IRQ_TO_GPIO(irq);
val = pxagpio_reg_read(sc, PXA250_GPIO_REG(GPIO_GRER0, gpio));
val |= GPIO_BIT(gpio);
pxagpio_reg_write(sc, PXA250_GPIO_REG(GPIO_GRER0, gpio), val);
}
int
pxa_gpio_get_next_irq(void)
{
struct pxa_gpio_softc *sc;
int gpio;
sc = pxa_gpio_softc;
if (sc->pg_intr[0] != 0) {
gpio = ffs(sc->pg_intr[0]) - 1;
sc->pg_intr[0] &= ~(1 << gpio);
return (GPIO_TO_IRQ(gpio));
}
if (sc->pg_intr[1] != 0) {
gpio = ffs(sc->pg_intr[1]) - 1;
sc->pg_intr[1] &= ~(1 << gpio);
return (GPIO_TO_IRQ(gpio + 32));
}
if (sc->pg_intr[2] != 0) {
gpio = ffs(sc->pg_intr[2]) - 1;
sc->pg_intr[2] &= ~(1 << gpio);
return (GPIO_TO_IRQ(gpio + 64));
}
return (-1);
}

View File

@ -0,0 +1,261 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2006 Benno Rice. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/malloc.h>
#include <sys/rman.h>
#include <sys/timetc.h>
#include <machine/armreg.h>
#include <machine/bus.h>
#include <machine/intr.h>
#include <arm/xscale/pxa/pxavar.h>
#include <arm/xscale/pxa/pxareg.h>
struct pxa_icu_softc {
struct resource * pi_res[1];
bus_space_tag_t pi_bst;
bus_space_handle_t pi_bsh;
};
static struct resource_spec pxa_icu_spec[] = {
{ SYS_RES_MEMORY, 0, RF_ACTIVE },
{ -1, 0 }
};
static struct pxa_icu_softc *pxa_icu_softc = NULL;
static int pxa_icu_probe(device_t);
static int pxa_icu_attach(device_t);
uint32_t pxa_icu_get_icip(void);
void pxa_icu_clear_icip(int);
uint32_t pxa_icu_get_icfp(void);
void pxa_icu_clear_icfp(int);
uint32_t pxa_icu_get_icmr(void);
void pxa_icu_set_icmr(uint32_t);
uint32_t pxa_icu_get_iclr(void);
void pxa_icu_set_iclr(uint32_t);
uint32_t pxa_icu_get_icpr(void);
void pxa_icu_idle_enable(void);
void pxa_icu_idle_disable(void);
extern uint32_t pxa_gpio_intr_flags[];
static int
pxa_icu_probe(device_t dev)
{
device_set_desc(dev, "Interrupt Controller");
return (0);
}
static int
pxa_icu_attach(device_t dev)
{
int error;
struct pxa_icu_softc *sc;
sc = (struct pxa_icu_softc *)device_get_softc(dev);
if (pxa_icu_softc != NULL)
return (ENXIO);
pxa_icu_softc = sc;
error = bus_alloc_resources(dev, pxa_icu_spec, sc->pi_res);
if (error) {
device_printf(dev, "could not allocate resources\n");
return (ENXIO);
}
sc->pi_bst = rman_get_bustag(sc->pi_res[0]);
sc->pi_bsh = rman_get_bushandle(sc->pi_res[0]);
/* Disable all interrupts. */
pxa_icu_set_icmr(0);
/* Route all interrupts to IRQ rather than FIQ. */
pxa_icu_set_iclr(0);
/* XXX: This should move to configure_final or something. */
enable_interrupts(PSR_I|PSR_F);
return (0);
}
static device_method_t pxa_icu_methods[] = {
DEVMETHOD(device_probe, pxa_icu_probe),
DEVMETHOD(device_attach, pxa_icu_attach),
{0, 0}
};
static driver_t pxa_icu_driver = {
"icu",
pxa_icu_methods,
sizeof(struct pxa_icu_softc),
};
static devclass_t pxa_icu_devclass;
DRIVER_MODULE(pxaicu, pxa, pxa_icu_driver, pxa_icu_devclass, 0, 0);
int
arm_get_next_irq(int last __unused)
{
int irq;
if ((irq = pxa_icu_get_icip()) != 0) {
return (ffs(irq) - 1);
}
return (pxa_gpio_get_next_irq());
}
void
arm_mask_irq(uintptr_t nb)
{
uint32_t mr;
if (nb >= IRQ_GPIO0) {
pxa_gpio_mask_irq(nb);
return;
}
mr = pxa_icu_get_icmr();
mr &= ~(1 << nb);
pxa_icu_set_icmr(mr);
}
void
arm_unmask_irq(uintptr_t nb)
{
uint32_t mr;
if (nb >= IRQ_GPIO0) {
pxa_gpio_unmask_irq(nb);
return;
}
mr = pxa_icu_get_icmr();
mr |= (1 << nb);
pxa_icu_set_icmr(mr);
}
uint32_t
pxa_icu_get_icip(void)
{
return (bus_space_read_4(pxa_icu_softc->pi_bst,
pxa_icu_softc->pi_bsh, ICU_IP));
}
void
pxa_icu_clear_icip(int irq)
{
bus_space_write_4(pxa_icu_softc->pi_bst,
pxa_icu_softc->pi_bsh, ICU_IP, (1 << irq));
}
uint32_t
pxa_icu_get_icfp(void)
{
return (bus_space_read_4(pxa_icu_softc->pi_bst,
pxa_icu_softc->pi_bsh, ICU_FP));
}
void
pxa_icu_clear_icfp(int irq)
{
bus_space_write_4(pxa_icu_softc->pi_bst,
pxa_icu_softc->pi_bsh, ICU_FP, (1 << irq));
}
uint32_t
pxa_icu_get_icmr(void)
{
return (bus_space_read_4(pxa_icu_softc->pi_bst,
pxa_icu_softc->pi_bsh, ICU_MR));
}
void
pxa_icu_set_icmr(uint32_t val)
{
bus_space_write_4(pxa_icu_softc->pi_bst,
pxa_icu_softc->pi_bsh, ICU_MR, val);
}
uint32_t
pxa_icu_get_iclr(void)
{
return (bus_space_read_4(pxa_icu_softc->pi_bst,
pxa_icu_softc->pi_bsh, ICU_LR));
}
void
pxa_icu_set_iclr(uint32_t val)
{
bus_space_write_4(pxa_icu_softc->pi_bst,
pxa_icu_softc->pi_bsh, ICU_LR, val);
}
uint32_t
pxa_icu_get_icpr(void)
{
return (bus_space_read_4(pxa_icu_softc->pi_bst,
pxa_icu_softc->pi_bsh, ICU_PR));
}
void
pxa_icu_idle_enable(void)
{
bus_space_write_4(pxa_icu_softc->pi_bst,
pxa_icu_softc->pi_bsh, ICU_CR, 0x0);
}
void
pxa_icu_idle_disable(void)
{
bus_space_write_4(pxa_icu_softc->pi_bst,
pxa_icu_softc->pi_bsh, ICU_CR, 0x1);
}

View File

@ -0,0 +1,439 @@
/* $NetBSD: hpc_machdep.c,v 1.70 2003/09/16 08:18:22 agc Exp $ */
/*-
* SPDX-License-Identifier: BSD-4-Clause
*
* Copyright (c) 1994-1998 Mark Brinicombe.
* Copyright (c) 1994 Brini.
* All rights reserved.
*
* This code is derived from software written for Brini by Mark Brinicombe
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Brini.
* 4. The name of the company nor the name of the author may be used to
* endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* RiscBSD kernel project
*
* machdep.c
*
* Machine dependent functions for kernel setup
*
* This file needs a lot of work.
*
* Created : 17/09/94
*/
#include "opt_ddb.h"
#include "opt_kstack_pages.h"
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#define _ARM32_BUS_DMA_PRIVATE
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/sysproto.h>
#include <sys/signalvar.h>
#include <sys/imgact.h>
#include <sys/kernel.h>
#include <sys/ktr.h>
#include <sys/linker.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mutex.h>
#include <sys/pcpu.h>
#include <sys/proc.h>
#include <sys/ptrace.h>
#include <sys/cons.h>
#include <sys/bio.h>
#include <sys/bus.h>
#include <sys/buf.h>
#include <sys/exec.h>
#include <sys/kdb.h>
#include <sys/msgbuf.h>
#include <sys/devmap.h>
#include <machine/reg.h>
#include <machine/cpu.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <vm/vm_object.h>
#include <vm/vm_page.h>
#include <vm/vm_map.h>
#include <machine/vmparam.h>
#include <machine/pcb.h>
#include <machine/undefined.h>
#include <machine/machdep.h>
#include <machine/metadata.h>
#include <machine/armreg.h>
#include <machine/bus.h>
#include <machine/physmem.h>
#include <sys/reboot.h>
#include <arm/xscale/pxa/pxareg.h>
#include <arm/xscale/pxa/pxavar.h>
#define KERNEL_PT_SYS 0 /* Page table for mapping proc0 zero page */
#define KERNEL_PT_IOPXS 1
#define KERNEL_PT_BEFOREKERN 2
#define KERNEL_PT_AFKERNEL 3 /* L2 table for mapping after kernel */
#define KERNEL_PT_AFKERNEL_NUM 9
/* this should be evenly divisable by PAGE_SIZE / L2_TABLE_SIZE_REAL (or 4) */
#define NUM_KERNEL_PTS (KERNEL_PT_AFKERNEL + KERNEL_PT_AFKERNEL_NUM)
struct pv_addr kernel_pt_table[NUM_KERNEL_PTS];
/* Physical and virtual addresses for some global pages */
struct pv_addr systempage;
struct pv_addr msgbufpv;
struct pv_addr irqstack;
struct pv_addr undstack;
struct pv_addr abtstack;
struct pv_addr kernelstack;
struct pv_addr minidataclean;
static void pxa_probe_sdram(bus_space_tag_t, bus_space_handle_t,
uint32_t *, uint32_t *);
/* Static device mappings. */
static const struct devmap_entry pxa_devmap[] = {
/*
* Map the on-board devices up into the KVA region so we don't muck
* up user-space.
*/
{
PXA2X0_PERIPH_START + PXA2X0_PERIPH_OFFSET,
PXA2X0_PERIPH_START,
PXA250_PERIPH_END - PXA2X0_PERIPH_START,
},
{ 0, 0, 0, }
};
#define SDRAM_START 0xa0000000
extern vm_offset_t xscale_cache_clean_addr;
void *
initarm(struct arm_boot_params *abp)
{
struct pv_addr kernel_l1pt;
struct pv_addr dpcpu;
int loop;
u_int l1pagetable;
vm_offset_t freemempos;
vm_offset_t freemem_pt;
vm_offset_t afterkern;
vm_offset_t freemem_after;
vm_offset_t lastaddr;
int i, j;
uint32_t memsize[PXA2X0_SDRAM_BANKS], memstart[PXA2X0_SDRAM_BANKS];
lastaddr = parse_boot_param(abp);
arm_physmem_kernaddr = abp->abp_physaddr;
set_cpufuncs();
pcpu_init(pcpup, 0, sizeof(struct pcpu));
PCPU_SET(curthread, &thread0);
/* Do basic tuning, hz etc */
init_param1();
freemempos = 0xa0200000;
/* Define a macro to simplify memory allocation */
#define valloc_pages(var, np) \
alloc_pages((var).pv_pa, (np)); \
(var).pv_va = (var).pv_pa + 0x20000000;
#define alloc_pages(var, np) \
freemempos -= (np * PAGE_SIZE); \
(var) = freemempos; \
memset((char *)(var), 0, ((np) * PAGE_SIZE));
while (((freemempos - L1_TABLE_SIZE) & (L1_TABLE_SIZE - 1)) != 0)
freemempos -= PAGE_SIZE;
valloc_pages(kernel_l1pt, L1_TABLE_SIZE / PAGE_SIZE);
for (loop = 0; loop < NUM_KERNEL_PTS; ++loop) {
if (!(loop % (PAGE_SIZE / L2_TABLE_SIZE_REAL))) {
valloc_pages(kernel_pt_table[loop],
L2_TABLE_SIZE / PAGE_SIZE);
} else {
kernel_pt_table[loop].pv_pa = freemempos +
(loop % (PAGE_SIZE / L2_TABLE_SIZE_REAL)) *
L2_TABLE_SIZE_REAL;
kernel_pt_table[loop].pv_va =
kernel_pt_table[loop].pv_pa + 0x20000000;
}
}
freemem_pt = freemempos;
freemempos = 0xa0100000;
/*
* Allocate a page for the system page mapped to V0x00000000
* This page will just contain the system vectors and can be
* shared by all processes.
*/
valloc_pages(systempage, 1);
/* Allocate dynamic per-cpu area. */
valloc_pages(dpcpu, DPCPU_SIZE / PAGE_SIZE);
dpcpu_init((void *)dpcpu.pv_va, 0);
/* Allocate stacks for all modes */
valloc_pages(irqstack, IRQ_STACK_SIZE);
valloc_pages(abtstack, ABT_STACK_SIZE);
valloc_pages(undstack, UND_STACK_SIZE);
valloc_pages(kernelstack, kstack_pages);
alloc_pages(minidataclean.pv_pa, 1);
valloc_pages(msgbufpv, round_page(msgbufsize) / PAGE_SIZE);
/*
* Allocate memory for the l1 and l2 page tables. The scheme to avoid
* wasting memory by allocating the l1pt on the first 16k memory was
* taken from NetBSD rpc_machdep.c. NKPT should be greater than 12 for
* this to work (which is supposed to be the case).
*/
/*
* Now we start construction of the L1 page table
* We start by mapping the L2 page tables into the L1.
* This means that we can replace L1 mappings later on if necessary
*/
l1pagetable = kernel_l1pt.pv_va;
/* Map the L2 pages tables in the L1 page table */
pmap_link_l2pt(l1pagetable, rounddown2(ARM_VECTORS_HIGH, 0x00100000),
&kernel_pt_table[KERNEL_PT_SYS]);
#if 0 /* XXXBJR: What is this? Don't know if there's an analogue. */
pmap_link_l2pt(l1pagetable, IQ80321_IOPXS_VBASE,
&kernel_pt_table[KERNEL_PT_IOPXS]);
#endif
pmap_link_l2pt(l1pagetable, KERNBASE,
&kernel_pt_table[KERNEL_PT_BEFOREKERN]);
pmap_map_chunk(l1pagetable, KERNBASE, SDRAM_START, 0x100000,
VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
pmap_map_chunk(l1pagetable, KERNBASE + 0x100000, SDRAM_START + 0x100000,
0x100000, VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE);
pmap_map_chunk(l1pagetable, KERNBASE + 0x200000, SDRAM_START + 0x200000,
rounddown2(((uint32_t)(lastaddr) - KERNBASE - 0x200000) + L1_S_SIZE, L1_S_SIZE),
VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
freemem_after = rounddown2((int)lastaddr + PAGE_SIZE, PAGE_SIZE);
afterkern = round_page(rounddown2((vm_offset_t)lastaddr + L1_S_SIZE, L1_S_SIZE));
for (i = 0; i < KERNEL_PT_AFKERNEL_NUM; i++) {
pmap_link_l2pt(l1pagetable, afterkern + i * 0x00100000,
&kernel_pt_table[KERNEL_PT_AFKERNEL + i]);
}
pmap_map_entry(l1pagetable, afterkern, minidataclean.pv_pa,
VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
/* Map the Mini-Data cache clean area. */
xscale_setup_minidata(l1pagetable, afterkern,
minidataclean.pv_pa);
/* Map the vector page. */
pmap_map_entry(l1pagetable, ARM_VECTORS_HIGH, systempage.pv_pa,
VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
devmap_bootstrap(l1pagetable, pxa_devmap);
/*
* Give the XScale global cache clean code an appropriately
* sized chunk of unmapped VA space starting at 0xff000000
* (our device mappings end before this address).
*/
xscale_cache_clean_addr = 0xff000000U;
cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT);
cpu_setttb(kernel_l1pt.pv_pa);
cpu_tlb_flushID();
cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2));
/*
* Pages were allocated during the secondary bootstrap for the
* stacks for different CPU modes.
* We must now set the r13 registers in the different CPU modes to
* point to these stacks.
* Since the ARM stacks use STMFD etc. we must set r13 to the top end
* of the stack memory.
*/
set_stackptrs(0);
/*
* We must now clean the cache again....
* Cleaning may be done by reading new data to displace any
* dirty data in the cache. This will have happened in cpu_setttb()
* but since we are boot strapping the addresses used for the read
* may have just been remapped and thus the cache could be out
* of sync. A re-clean after the switch will cure this.
* After booting there are no gross relocations of the kernel thus
* this problem will not occur after initarm().
*/
cpu_idcache_wbinv_all();
cpu_setup();
/*
* Sort out bus_space for on-board devices.
*/
pxa_obio_tag_init();
/*
* Fetch the SDRAM start/size from the PXA2X0 SDRAM configration
* registers.
*/
pxa_probe_sdram(obio_tag, PXA2X0_MEMCTL_BASE, memstart, memsize);
/* Fire up consoles. */
cninit();
undefined_init();
init_proc0(kernelstack.pv_va);
/* Enable MMU, I-cache, D-cache, write buffer. */
arm_vector_init(ARM_VECTORS_HIGH, ARM_VEC_ALL);
pmap_curmaxkvaddr = afterkern + PAGE_SIZE;
vm_max_kernel_address = 0xe0000000;
pmap_bootstrap(pmap_curmaxkvaddr, &kernel_l1pt);
msgbufp = (void*)msgbufpv.pv_va;
msgbufinit(msgbufp, msgbufsize);
mutex_init();
/*
* Add the physical ram we have available.
*
* Exclude the kernel (and all the things we allocated which immediately
* follow the kernel) from the VM allocation pool but not from crash
* dumps. virtual_avail is a global variable which tracks the kva we've
* "allocated" while setting up pmaps.
*
* Prepare the list of physical memory available to the vm subsystem.
*/
for (j = 0; j < PXA2X0_SDRAM_BANKS; j++) {
if (memsize[j] > 0)
arm_physmem_hardware_region(memstart[j], memsize[j]);
}
arm_physmem_exclude_region(freemem_pt, abp->abp_physaddr -
freemem_pt, EXFLAG_NOALLOC);
arm_physmem_exclude_region(freemempos, abp->abp_physaddr - 0x100000 -
freemempos, EXFLAG_NOALLOC);
arm_physmem_exclude_region(abp->abp_physaddr,
virtual_avail - KERNVIRTADDR, EXFLAG_NOALLOC);
arm_physmem_init_kernel_globals();
init_param2(physmem);
kdb_init();
return ((void *)(kernelstack.pv_va + USPACE_SVC_STACK_TOP -
sizeof(struct pcb)));
}
static void
pxa_probe_sdram(bus_space_tag_t bst, bus_space_handle_t bsh,
uint32_t *memstart, uint32_t *memsize)
{
uint32_t mdcnfg, dwid, dcac, drac, dnb;
int i;
mdcnfg = bus_space_read_4(bst, bsh, MEMCTL_MDCNFG);
/*
* Scan all 4 SDRAM banks
*/
for (i = 0; i < PXA2X0_SDRAM_BANKS; i++) {
memstart[i] = 0;
memsize[i] = 0;
switch (i) {
case 0:
case 1:
if ((i == 0 && (mdcnfg & MDCNFG_DE0) == 0) ||
(i == 1 && (mdcnfg & MDCNFG_DE1) == 0))
continue;
dwid = mdcnfg >> MDCNFD_DWID01_SHIFT;
dcac = mdcnfg >> MDCNFD_DCAC01_SHIFT;
drac = mdcnfg >> MDCNFD_DRAC01_SHIFT;
dnb = mdcnfg >> MDCNFD_DNB01_SHIFT;
break;
case 2:
case 3:
if ((i == 2 && (mdcnfg & MDCNFG_DE2) == 0) ||
(i == 3 && (mdcnfg & MDCNFG_DE3) == 0))
continue;
dwid = mdcnfg >> MDCNFD_DWID23_SHIFT;
dcac = mdcnfg >> MDCNFD_DCAC23_SHIFT;
drac = mdcnfg >> MDCNFD_DRAC23_SHIFT;
dnb = mdcnfg >> MDCNFD_DNB23_SHIFT;
break;
default:
panic("pxa_probe_sdram: impossible");
}
dwid = 2 << (1 - (dwid & MDCNFD_DWID_MASK)); /* 16/32 width */
dcac = 1 << ((dcac & MDCNFD_DCAC_MASK) + 8); /* 8-11 columns */
drac = 1 << ((drac & MDCNFD_DRAC_MASK) + 11); /* 11-13 rows */
dnb = 2 << (dnb & MDCNFD_DNB_MASK); /* # of banks */
memsize[i] = dwid * dcac * drac * dnb;
memstart[i] = PXA2X0_SDRAM0_START +
(i * PXA2X0_SDRAM_BANK_SIZE);
}
}
#define TIMER_FREQUENCY 3686400
#define UNIMPLEMENTED panic("%s: unimplemented", __func__)
/* XXXBJR: Belongs with DELAY in a timer.c of some sort. */
void
cpu_startprofclock(void)
{
UNIMPLEMENTED;
}
void
cpu_stopprofclock(void)
{
UNIMPLEMENTED;
}
static struct arm32_dma_range pxa_range = {
.dr_sysbase = 0,
.dr_busbase = 0,
.dr_len = ~0u,
};
struct arm32_dma_range *
bus_dma_get_range(void)
{
return (&pxa_range);
}
int
bus_dma_get_range_nb(void)
{
return (1);
}

View File

@ -0,0 +1,399 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2006 Benno Rice. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/malloc.h>
#include <sys/rman.h>
#include <machine/bus.h>
#include <machine/intr.h>
#include <arm/xscale/pxa/pxavar.h>
#include <arm/xscale/pxa/pxareg.h>
static void pxa_identify(driver_t *, device_t);
static int pxa_probe(device_t);
static int pxa_attach(device_t);
static int pxa_print_child(device_t, device_t);
static int pxa_setup_intr(device_t, device_t, struct resource *, int,
driver_filter_t *, driver_intr_t *, void *, void **);
static int pxa_read_ivar(device_t, device_t, int, uintptr_t *);
static struct resource_list * pxa_get_resource_list(device_t, device_t);
static struct resource * pxa_alloc_resource(device_t, device_t, int,
int *, rman_res_t, rman_res_t, rman_res_t, u_int);
static int pxa_release_resource(device_t, device_t, int,
int, struct resource *);
static int pxa_activate_resource(device_t, device_t,
int, int, struct resource *);
static struct resource * pxa_alloc_gpio_irq(device_t, device_t, int,
int *, rman_res_t, rman_res_t, rman_res_t, u_int);
struct obio_device {
const char *od_name;
u_long od_base;
u_long od_size;
u_int od_irqs[5];
struct resource_list od_resources;
};
static struct obio_device obio_devices[] = {
{ "icu", PXA2X0_INTCTL_BASE, PXA2X0_INTCTL_SIZE, { 0 } },
{ "timer", PXA2X0_OST_BASE, PXA2X0_OST_SIZE, { PXA2X0_INT_OST0, PXA2X0_INT_OST1, PXA2X0_INT_OST2, PXA2X0_INT_OST3, 0 } },
{ "dmac", PXA2X0_DMAC_BASE, PXA2X0_DMAC_SIZE, { PXA2X0_INT_DMA, 0 } },
{ "gpio", PXA2X0_GPIO_BASE, PXA250_GPIO_SIZE, { PXA2X0_INT_GPIO0, PXA2X0_INT_GPIO1, PXA2X0_INT_GPION, 0 } },
{ "uart", PXA2X0_FFUART_BASE, PXA2X0_FFUART_SIZE, { PXA2X0_INT_FFUART, 0 } },
{ "uart", PXA2X0_BTUART_BASE, PXA2X0_BTUART_SIZE, { PXA2X0_INT_BTUART, 0 } },
{ "uart", PXA2X0_STUART_BASE, PXA2X0_STUART_SIZE, { PXA2X0_INT_STUART, 0 } },
{ "uart", PXA2X0_HWUART_BASE, PXA2X0_HWUART_SIZE, { PXA2X0_INT_HWUART, 0 } },
{ "smi", PXA2X0_CS0_START, PXA2X0_CS_SIZE * 6, { 0 } },
{ NULL, 0, 0, { 0 } }
};
void
pxa_identify(driver_t *driver, device_t parent)
{
BUS_ADD_CHILD(parent, 0, "pxa", 0);
}
int
pxa_probe(device_t dev)
{
device_set_desc(dev, "XScale PXA On-board IO");
return (BUS_PROBE_NOWILDCARD);
}
int
pxa_attach(device_t dev)
{
struct obio_softc *sc;
struct obio_device *od;
int i;
device_t child;
sc = device_get_softc(dev);
sc->obio_bst = obio_tag;
sc->obio_mem.rm_type = RMAN_ARRAY;
sc->obio_mem.rm_descr = "PXA2X0 OBIO Memory";
if (rman_init(&sc->obio_mem) != 0)
panic("pxa_attach: failed to init obio mem rman");
if (rman_manage_region(&sc->obio_mem, 0, PXA250_PERIPH_END) != 0)
panic("pxa_attach: failed to set up obio mem rman");
sc->obio_irq.rm_type = RMAN_ARRAY;
sc->obio_irq.rm_descr = "PXA2X0 OBIO IRQ";
if (rman_init(&sc->obio_irq) != 0)
panic("pxa_attach: failed to init obio irq rman");
if (rman_manage_region(&sc->obio_irq, 0, 31) != 0)
panic("pxa_attach: failed to set up obio irq rman (main irqs)");
if (rman_manage_region(&sc->obio_irq, IRQ_GPIO0, IRQ_GPIO_MAX) != 0)
panic("pxa_attach: failed to set up obio irq rman (gpio irqs)");
for (od = obio_devices; od->od_name != NULL; od++) {
resource_list_init(&od->od_resources);
resource_list_add(&od->od_resources, SYS_RES_MEMORY, 0,
od->od_base, od->od_base + od->od_size, od->od_size);
for (i = 0; od->od_irqs[i] != 0; i++) {
resource_list_add(&od->od_resources, SYS_RES_IRQ, i,
od->od_irqs[i], od->od_irqs[i], 1);
}
child = device_add_child(dev, od->od_name, -1);
device_set_ivars(child, od);
}
bus_generic_probe(dev);
bus_generic_attach(dev);
return (0);
}
static int
pxa_print_child(device_t dev, device_t child)
{
struct obio_device *od;
int retval;
od = (struct obio_device *)device_get_ivars(child);
if (od == NULL)
panic("Unknown device on pxa0");
retval = 0;
retval += bus_print_child_header(dev, child);
retval += resource_list_print_type(&od->od_resources, "at mem",
SYS_RES_MEMORY, "0x%08jx");
retval += resource_list_print_type(&od->od_resources, "irq",
SYS_RES_IRQ, "%jd");
retval += bus_print_child_footer(dev, child);
return (retval);
}
static int
pxa_setup_intr(device_t dev, device_t child, struct resource *irq, int flags,
driver_filter_t *filter, driver_intr_t *ithread, void *arg, void **cookiep)
{
struct obio_softc *sc;
int error;
sc = (struct obio_softc *)device_get_softc(dev);
error = BUS_SETUP_INTR(device_get_parent(dev), child, irq, flags,
filter, ithread, arg, cookiep);
if (error)
return (error);
return (0);
}
static int
pxa_teardown_intr(device_t dev, device_t child, struct resource *ires,
void *cookie)
{
return (BUS_TEARDOWN_INTR(device_get_parent(dev), child, ires, cookie));}
static int
pxa_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
{
struct obio_device *od;
od = (struct obio_device *)device_get_ivars(child);
switch (which) {
case PXA_IVAR_BASE:
*((u_long *)result) = od->od_base;
break;
default:
return (ENOENT);
}
return (0);
}
static struct resource_list *
pxa_get_resource_list(device_t dev, device_t child)
{
struct obio_device *od;
od = (struct obio_device *)device_get_ivars(child);
if (od == NULL)
return (NULL);
return (&od->od_resources);
}
static struct resource *
pxa_alloc_resource(device_t dev, device_t child, int type, int *rid,
rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
{
struct obio_softc *sc;
struct obio_device *od;
struct resource *rv;
struct resource_list *rl;
struct resource_list_entry *rle;
struct rman *rm;
int needactivate;
sc = (struct obio_softc *)device_get_softc(dev);
od = (struct obio_device *)device_get_ivars(child);
rl = &od->od_resources;
rle = resource_list_find(rl, type, *rid);
if (rle == NULL) {
/* We can allocate GPIO-based IRQs lazily. */
if (type == SYS_RES_IRQ)
return (pxa_alloc_gpio_irq(dev, child, type, rid,
start, end, count, flags));
return (NULL);
}
if (rle->res != NULL)
panic("pxa_alloc_resource: resource is busy");
switch (type) {
case SYS_RES_IRQ:
rm = &sc->obio_irq;
break;
case SYS_RES_MEMORY:
rm = &sc->obio_mem;
break;
default:
return (NULL);
}
needactivate = flags & RF_ACTIVE;
flags &= ~RF_ACTIVE;
rv = rman_reserve_resource(rm, rle->start, rle->end, rle->count, flags,
child);
if (rv == NULL)
return (NULL);
rle->res = rv;
rman_set_rid(rv, *rid);
if (type == SYS_RES_MEMORY) {
rman_set_bustag(rv, sc->obio_bst);
rman_set_bushandle(rv, rle->start);
}
if (needactivate) {
if (bus_activate_resource(child, type, *rid, rv)) {
rman_release_resource(rv);
return (NULL);
}
}
return (rv);
}
static int
pxa_release_resource(device_t dev, device_t child, int type, int rid,
struct resource *r)
{
struct obio_device *od;
struct resource_list *rl;
struct resource_list_entry *rle;
od = (struct obio_device *)device_get_ivars(child);
rl = &od->od_resources;
if (type == SYS_RES_IOPORT)
type = SYS_RES_MEMORY;
rle = resource_list_find(rl, type, rid);
if (!rle)
panic("pxa_release_resource: can't find resource");
if (!rle->res)
panic("pxa_release_resource: resource entry is not busy");
rman_release_resource(rle->res);
rle->res = NULL;
return (0);
}
static int
pxa_activate_resource(device_t dev, device_t child, int type, int rid,
struct resource *r)
{
return (rman_activate_resource(r));
}
static device_method_t pxa_methods[] = {
DEVMETHOD(device_identify, pxa_identify),
DEVMETHOD(device_probe, pxa_probe),
DEVMETHOD(device_attach, pxa_attach),
DEVMETHOD(bus_print_child, pxa_print_child),
DEVMETHOD(bus_read_ivar, pxa_read_ivar),
DEVMETHOD(bus_setup_intr, pxa_setup_intr),
DEVMETHOD(bus_teardown_intr, pxa_teardown_intr),
DEVMETHOD(bus_get_resource_list, pxa_get_resource_list),
DEVMETHOD(bus_alloc_resource, pxa_alloc_resource),
DEVMETHOD(bus_release_resource, pxa_release_resource),
DEVMETHOD(bus_activate_resource, pxa_activate_resource),
{0, 0}
};
static driver_t pxa_driver = {
"pxa",
pxa_methods,
sizeof(struct obio_softc),
};
static devclass_t pxa_devclass;
DRIVER_MODULE(pxa, nexus, pxa_driver, pxa_devclass, 0, 0);
static struct resource *
pxa_alloc_gpio_irq(device_t dev, device_t child, int type, int *rid,
rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
{
struct obio_softc *sc;
struct obio_device *od;
struct resource_list *rl;
struct resource_list_entry *rle;
struct resource *rv;
struct rman *rm;
int needactivate;
sc = device_get_softc(dev);
od = device_get_ivars(child);
rl = &od->od_resources;
rm = &sc->obio_irq;
needactivate = flags & RF_ACTIVE;
flags &= ~RF_ACTIVE;
rv = rman_reserve_resource(rm, start, end, count, flags, child);
if (rv == NULL)
return (NULL);
resource_list_add(rl, type, *rid, start, end, count);
rle = resource_list_find(rl, type, *rid);
if (rle == NULL)
panic("pxa_alloc_gpio_irq: unexpectedly can't find resource");
rle->res = rv;
rle->start = rman_get_start(rv);
rle->end = rman_get_end(rv);
rle->count = count;
if (needactivate) {
if (bus_activate_resource(child, type, *rid, rv)) {
rman_release_resource(rv);
return (NULL);
}
}
if (bootverbose)
device_printf(dev, "lazy allocation of irq %jd for %s\n",
start, device_get_nameunit(child));
return (rv);
}

View File

@ -0,0 +1,356 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2006 Benno Rice. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/malloc.h>
#include <sys/rman.h>
#include <sys/timetc.h>
#include <machine/bus.h>
#include <machine/intr.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <arm/xscale/pxa/pxavar.h>
#include <arm/xscale/pxa/pxareg.h>
static MALLOC_DEFINE(M_PXASMI, "PXA SMI",
"Data for static memory interface devices.");
struct pxa_smi_softc {
struct resource *ps_res[1];
struct rman ps_mem;
bus_space_tag_t ps_bst;
bus_addr_t ps_base;
};
struct smi_ivars {
struct resource_list smid_resources;
bus_addr_t smid_mem;
};
static struct resource_spec pxa_smi_spec[] = {
{ SYS_RES_MEMORY, 0, RF_ACTIVE },
{ -1, 0 }
};
static int pxa_smi_probe(device_t);
static int pxa_smi_attach(device_t);
static int pxa_smi_print_child(device_t, device_t);
static int pxa_smi_read_ivar(device_t, device_t, int, uintptr_t *);
static struct resource * pxa_smi_alloc_resource(device_t, device_t,
int, int *, rman_res_t, rman_res_t, rman_res_t, u_int);
static int pxa_smi_release_resource(device_t, device_t,
int, int, struct resource *);
static int pxa_smi_activate_resource(device_t, device_t,
int, int, struct resource *);
static void pxa_smi_add_device(device_t, const char *, int);
static int
pxa_smi_probe(device_t dev)
{
if (resource_disabled("smi", device_get_unit(dev)))
return (ENXIO);
device_set_desc(dev, "Static Memory Interface");
return (0);
}
static int
pxa_smi_attach(device_t dev)
{
int error, i, dunit;
const char *dname;
struct pxa_smi_softc *sc;
sc = (struct pxa_smi_softc *)device_get_softc(dev);
error = bus_alloc_resources(dev, pxa_smi_spec, sc->ps_res);
if (error) {
device_printf(dev, "could not allocate resources\n");
return (ENXIO);
}
sc->ps_mem.rm_type = RMAN_ARRAY;
sc->ps_mem.rm_descr = device_get_nameunit(dev);
if (rman_init(&sc->ps_mem) != 0)
panic("pxa_smi_attach: failed to init mem rman");
if (rman_manage_region(&sc->ps_mem, 0, PXA2X0_CS_SIZE * 6) != 0)
panic("pxa_smi_attach: failed ot set up mem rman");
sc->ps_bst = base_tag;
sc->ps_base = rman_get_start(sc->ps_res[0]);
i = 0;
while (resource_find_match(&i, &dname, &dunit, "at",
device_get_nameunit(dev)) == 0) {
pxa_smi_add_device(dev, dname, dunit);
}
bus_generic_probe(dev);
bus_generic_attach(dev);
return (0);
}
static int
pxa_smi_print_child(device_t dev, device_t child)
{
struct smi_ivars *smid;
int retval;
smid = (struct smi_ivars *)device_get_ivars(child);
if (smid == NULL) {
device_printf(dev, "unknown device: %s\n",
device_get_nameunit(child));
return (0);
}
retval = 0;
retval += bus_print_child_header(dev, child);
retval += resource_list_print_type(&smid->smid_resources, "at mem",
SYS_RES_MEMORY, "%#jx");
retval += resource_list_print_type(&smid->smid_resources, "irq",
SYS_RES_IRQ, "%jd");
retval += bus_print_child_footer(dev, child);
return (retval);
}
static int
pxa_smi_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
{
struct pxa_smi_softc *sc;
struct smi_ivars *smid;
sc = device_get_softc(dev);
smid = device_get_ivars(child);
switch (which) {
case SMI_IVAR_PHYSBASE:
*((bus_addr_t *)result) = smid->smid_mem;
break;
default:
return (ENOENT);
}
return (0);
}
static struct resource *
pxa_smi_alloc_resource(device_t dev, device_t child, int type, int *rid,
rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
{
struct pxa_smi_softc *sc;
struct smi_ivars *smid;
struct resource *rv;
struct resource_list *rl;
struct resource_list_entry *rle;
int needactivate;
sc = (struct pxa_smi_softc *)device_get_softc(dev);
smid = (struct smi_ivars *)device_get_ivars(child);
rl = &smid->smid_resources;
if (type == SYS_RES_IOPORT)
type = SYS_RES_MEMORY;
rle = resource_list_find(rl, type, *rid);
if (rle == NULL)
return (NULL);
if (rle->res != NULL)
panic("pxa_smi_alloc_resource: resource is busy");
needactivate = flags & RF_ACTIVE;
flags &= ~RF_ACTIVE;
switch (type) {
case SYS_RES_MEMORY:
rv = rman_reserve_resource(&sc->ps_mem, rle->start, rle->end,
rle->count, flags, child);
if (rv == NULL)
return (NULL);
rle->res = rv;
rman_set_rid(rv, *rid);
rman_set_bustag(rv, sc->ps_bst);
rman_set_bushandle(rv, rle->start);
if (needactivate) {
if (bus_activate_resource(child, type, *rid, rv) != 0) {
rman_release_resource(rv);
return (NULL);
}
}
break;
case SYS_RES_IRQ:
rv = bus_alloc_resource(dev, type, rid, rle->start, rle->end,
rle->count, flags);
if (rv == NULL)
return (NULL);
if (needactivate) {
if (bus_activate_resource(child, type, *rid, rv) != 0) {
bus_release_resource(dev, type, *rid, rv);
return (NULL);
}
}
break;
default:
return (NULL);
}
return (rv);
}
static int
pxa_smi_release_resource(device_t dev, device_t child, int type, int rid,
struct resource *r)
{
struct smi_ivars *smid;
struct resource_list *rl;
struct resource_list_entry *rle;
if (type == SYS_RES_IRQ)
return (bus_release_resource(dev, SYS_RES_IRQ, rid, r));
smid = (struct smi_ivars *)device_get_ivars(child);
rl = &smid->smid_resources;
if (type == SYS_RES_IOPORT)
type = SYS_RES_MEMORY;
rle = resource_list_find(rl, type, rid);
if (rle == NULL)
panic("pxa_smi_release_resource: can't find resource");
if (rle->res == NULL)
panic("pxa_smi_release_resource: resource entry not busy");
rman_release_resource(rle->res);
rle->res = NULL;
return (0);
}
static int
pxa_smi_activate_resource(device_t dev, device_t child, int type, int rid,
struct resource *r)
{
struct pxa_smi_softc *sc;
sc = (struct pxa_smi_softc *)device_get_softc(dev);
if (type == SYS_RES_IRQ)
return (bus_activate_resource(dev, SYS_RES_IRQ, rid, r));
rman_set_bushandle(r, (bus_space_handle_t)pmap_mapdev(rman_get_start(r),
rman_get_size(r)));
return (rman_activate_resource(r));
}
static device_method_t pxa_smi_methods[] = {
DEVMETHOD(device_probe, pxa_smi_probe),
DEVMETHOD(device_attach, pxa_smi_attach),
DEVMETHOD(bus_print_child, pxa_smi_print_child),
DEVMETHOD(bus_read_ivar, pxa_smi_read_ivar),
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
DEVMETHOD(bus_alloc_resource, pxa_smi_alloc_resource),
DEVMETHOD(bus_release_resource, pxa_smi_release_resource),
DEVMETHOD(bus_activate_resource, pxa_smi_activate_resource),
{0, 0}
};
static driver_t pxa_smi_driver = {
"smi",
pxa_smi_methods,
sizeof(struct pxa_smi_softc),
};
static devclass_t pxa_smi_devclass;
DRIVER_MODULE(smi, pxa, pxa_smi_driver, pxa_smi_devclass, 0, 0);
static void
pxa_smi_add_device(device_t dev, const char *name, int unit)
{
device_t child;
int start, count;
struct smi_ivars *ivars;
ivars = (struct smi_ivars *)malloc(
sizeof(struct smi_ivars), M_PXASMI, M_WAITOK);
child = device_add_child(dev, name, unit);
if (child == NULL) {
free(ivars, M_PXASMI);
return;
}
device_set_ivars(child, ivars);
resource_list_init(&ivars->smid_resources);
start = 0;
count = 0;
resource_int_value(name, unit, "mem", &start);
resource_int_value(name, unit, "size", &count);
if (start > 0 || count > 0) {
resource_list_add(&ivars->smid_resources, SYS_RES_MEMORY, 0,
start, start + count, count);
ivars->smid_mem = (bus_addr_t)start;
}
start = -1;
count = 0;
resource_int_value(name, unit, "irq", &start);
if (start > -1)
resource_list_add(&ivars->smid_resources, SYS_RES_IRQ, 0, start,
start, 1);
if (resource_disabled(name, unit))
device_disable(child);
}

View File

@ -0,0 +1,267 @@
/* $NetBSD: obio_space.c,v 1.6 2003/07/15 00:25:05 lukem Exp $ */
/*-
* SPDX-License-Identifier: BSD-4-Clause
*
* Copyright (c) 2001, 2002, 2003 Wasabi Systems, Inc.
* All rights reserved.
*
* Written by Jason R. Thorpe for Wasabi Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed for the NetBSD Project by
* Wasabi Systems, Inc.
* 4. The name of Wasabi Systems, Inc. may not be used to endorse
* or promote products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* bus_space functions for PXA devices
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <machine/bus.h>
#include <arm/xscale/pxa/pxareg.h>
#include <arm/xscale/pxa/pxavar.h>
static MALLOC_DEFINE(M_PXATAG, "PXA bus_space tags", "Bus_space tags for PXA");
/* Prototypes for all the bus_space structure functions */
bs_protos(generic);
bs_protos(pxa);
/*
* The obio bus space tag. This is constant for all instances, so
* we never have to explicitly "create" it.
*/
struct bus_space _base_tag = {
/* cookie */
.bs_privdata = NULL,
/* mapping/unmapping */
.bs_map = generic_bs_map,
.bs_unmap = generic_bs_unmap,
.bs_subregion = generic_bs_subregion,
/* allocation/deallocation */
.bs_alloc = generic_bs_alloc,
.bs_free = generic_bs_free,
/* barrier */
.bs_barrier = generic_bs_barrier,
/* read (single) */
.bs_r_1 = pxa_bs_r_1,
.bs_r_2 = pxa_bs_r_2,
.bs_r_4 = pxa_bs_r_4,
.bs_r_8 = BS_UNIMPLEMENTED,
/* read multiple */
.bs_rm_1 = pxa_bs_rm_1,
.bs_rm_2 = pxa_bs_rm_2,
.bs_rm_4 = BS_UNIMPLEMENTED,
.bs_rm_8 = BS_UNIMPLEMENTED,
/* read region */
.bs_rr_1 = pxa_bs_rr_1,
.bs_rr_2 = BS_UNIMPLEMENTED,
.bs_rr_4 = BS_UNIMPLEMENTED,
.bs_rr_8 = BS_UNIMPLEMENTED,
/* write (single) */
.bs_w_1 = pxa_bs_w_1,
.bs_w_2 = pxa_bs_w_2,
.bs_w_4 = pxa_bs_w_4,
.bs_w_8 = BS_UNIMPLEMENTED,
/* write multiple */
.bs_wm_1 = pxa_bs_wm_1,
.bs_wm_2 = pxa_bs_wm_2,
.bs_wm_4 = BS_UNIMPLEMENTED,
.bs_wm_8 = BS_UNIMPLEMENTED,
/* write region */
.bs_wr_1 = BS_UNIMPLEMENTED,
.bs_wr_2 = BS_UNIMPLEMENTED,
.bs_wr_4 = BS_UNIMPLEMENTED,
.bs_wr_8 = BS_UNIMPLEMENTED,
/* set multiple */
.bs_sm_1 = BS_UNIMPLEMENTED,
.bs_sm_2 = BS_UNIMPLEMENTED,
.bs_sm_4 = BS_UNIMPLEMENTED,
.bs_sm_8 = BS_UNIMPLEMENTED,
/* set region */
.bs_sr_1 = BS_UNIMPLEMENTED,
.bs_sr_2 = BS_UNIMPLEMENTED,
.bs_sr_4 = BS_UNIMPLEMENTED,
.bs_sr_8 = BS_UNIMPLEMENTED,
/* copy */
.bs_c_1 = BS_UNIMPLEMENTED,
.bs_c_2 = BS_UNIMPLEMENTED,
.bs_c_4 = BS_UNIMPLEMENTED,
.bs_c_8 = BS_UNIMPLEMENTED,
/* read stream (single) */
.bs_r_1_s = BS_UNIMPLEMENTED,
.bs_r_2_s = BS_UNIMPLEMENTED,
.bs_r_4_s = BS_UNIMPLEMENTED,
.bs_r_8_s = BS_UNIMPLEMENTED,
/* read multiple stream */
.bs_rm_1_s = BS_UNIMPLEMENTED,
.bs_rm_2_s = BS_UNIMPLEMENTED,
.bs_rm_4_s = BS_UNIMPLEMENTED,
.bs_rm_8_s = BS_UNIMPLEMENTED,
/* read region stream */
.bs_rr_1_s = BS_UNIMPLEMENTED,
.bs_rr_2_s = BS_UNIMPLEMENTED,
.bs_rr_4_s = BS_UNIMPLEMENTED,
.bs_rr_8_s = BS_UNIMPLEMENTED,
/* write stream (single) */
.bs_w_1_s = BS_UNIMPLEMENTED,
.bs_w_2_s = BS_UNIMPLEMENTED,
.bs_w_4_s = BS_UNIMPLEMENTED,
.bs_w_8_s = BS_UNIMPLEMENTED,
/* write multiple stream */
.bs_wm_1_s = BS_UNIMPLEMENTED,
.bs_wm_2_s = BS_UNIMPLEMENTED,
.bs_wm_4_s = BS_UNIMPLEMENTED,
.bs_wm_8_s = BS_UNIMPLEMENTED,
/* write region stream */
.bs_wr_1_s = BS_UNIMPLEMENTED,
.bs_wr_2_s = BS_UNIMPLEMENTED,
.bs_wr_4_s = BS_UNIMPLEMENTED,
.bs_wr_8_s = BS_UNIMPLEMENTED,
};
static struct bus_space _obio_tag;
bus_space_tag_t base_tag = &_base_tag;
bus_space_tag_t obio_tag = NULL;
void
pxa_obio_tag_init(void)
{
bcopy(&_base_tag, &_obio_tag, sizeof(struct bus_space));
_obio_tag.bs_privdata = (void *)PXA2X0_PERIPH_OFFSET;
obio_tag = &_obio_tag;
}
bus_space_tag_t
pxa_bus_tag_alloc(bus_addr_t offset)
{
struct bus_space *tag;
tag = (struct bus_space *)malloc(sizeof(struct bus_space), M_PXATAG,
M_WAITOK);
bcopy(&_base_tag, tag, sizeof(struct bus_space));
tag->bs_privdata = (void *)offset;
return ((bus_space_tag_t)tag);
}
#define READ_SINGLE(type, proto, base) \
type \
proto(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t offset) \
{ \
bus_addr_t tag_offset; \
type value; \
tag_offset = (bus_addr_t)tag->bs_privdata; \
value = base(NULL, bsh + tag_offset, offset); \
return (value); \
}
READ_SINGLE(u_int8_t, pxa_bs_r_1, generic_bs_r_1)
READ_SINGLE(u_int16_t, pxa_bs_r_2, generic_bs_r_2)
READ_SINGLE(u_int32_t, pxa_bs_r_4, generic_bs_r_4)
#undef READ_SINGLE
#define WRITE_SINGLE(type, proto, base) \
void \
proto(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t offset, \
type value) \
{ \
bus_addr_t tag_offset; \
tag_offset = (bus_addr_t)tag->bs_privdata; \
base(NULL, bsh + tag_offset, offset, value); \
}
WRITE_SINGLE(u_int8_t, pxa_bs_w_1, generic_bs_w_1)
WRITE_SINGLE(u_int16_t, pxa_bs_w_2, generic_bs_w_2)
WRITE_SINGLE(u_int32_t, pxa_bs_w_4, generic_bs_w_4)
#undef WRITE_SINGLE
#define READ_MULTI(type, proto, base) \
void \
proto(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t offset, \
type *dest, bus_size_t count) \
{ \
bus_addr_t tag_offset; \
tag_offset = (bus_addr_t)tag->bs_privdata; \
base(NULL, bsh + tag_offset, offset, dest, count); \
}
READ_MULTI(u_int8_t, pxa_bs_rm_1, generic_bs_rm_1)
READ_MULTI(u_int16_t, pxa_bs_rm_2, generic_bs_rm_2)
READ_MULTI(u_int8_t, pxa_bs_rr_1, generic_bs_rr_1)
#undef READ_MULTI
#define WRITE_MULTI(type, proto, base) \
void \
proto(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t offset, \
const type *src, bus_size_t count) \
{ \
bus_addr_t tag_offset; \
tag_offset = (bus_addr_t)tag->bs_privdata; \
base(NULL, bsh + tag_offset, offset, src, count); \
}
WRITE_MULTI(u_int8_t, pxa_bs_wm_1, generic_bs_wm_1)
WRITE_MULTI(u_int16_t, pxa_bs_wm_2, generic_bs_wm_2)
#undef WRITE_MULTI

View File

@ -0,0 +1,322 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2006 Benno Rice. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/malloc.h>
#include <sys/rman.h>
#include <sys/timetc.h>
#include <machine/armreg.h>
#include <machine/bus.h>
#include <machine/cpu.h>
#include <machine/frame.h>
#include <machine/intr.h>
#include <arm/xscale/pxa/pxavar.h>
#include <arm/xscale/pxa/pxareg.h>
#define PXA_TIMER_FREQUENCY 3686400
#define PXA_TIMER_TICK (PXA_TIMER_FREQUENCY / hz)
struct pxa_timer_softc {
struct resource * pt_res[5];
bus_space_tag_t pt_bst;
bus_space_handle_t pt_bsh;
};
static struct resource_spec pxa_timer_spec[] = {
{ SYS_RES_MEMORY, 0, RF_ACTIVE },
{ SYS_RES_IRQ, 0, RF_ACTIVE },
{ SYS_RES_IRQ, 1, RF_ACTIVE },
{ SYS_RES_IRQ, 2, RF_ACTIVE },
{ SYS_RES_IRQ, 3, RF_ACTIVE },
{ -1, 0 }
};
static struct pxa_timer_softc *timer_softc = NULL;
static int pxa_timer_probe(device_t);
static int pxa_timer_attach(device_t);
static driver_filter_t pxa_hardclock;
static unsigned pxa_timer_get_timecount(struct timecounter *);
uint32_t pxa_timer_get_osmr(int);
void pxa_timer_set_osmr(int, uint32_t);
uint32_t pxa_timer_get_oscr(void);
void pxa_timer_set_oscr(uint32_t);
uint32_t pxa_timer_get_ossr(void);
void pxa_timer_clear_ossr(uint32_t);
void pxa_timer_watchdog_enable(void);
void pxa_timer_watchdog_disable(void);
void pxa_timer_interrupt_enable(int);
void pxa_timer_interrupt_disable(int);
static struct timecounter pxa_timer_timecounter = {
.tc_get_timecount = pxa_timer_get_timecount,
.tc_name = "OS Timer",
.tc_frequency = PXA_TIMER_FREQUENCY,
.tc_counter_mask = ~0u,
.tc_quality = 1000,
};
static int
pxa_timer_probe(device_t dev)
{
device_set_desc(dev, "OS Timer");
return (0);
}
static int
pxa_timer_attach(device_t dev)
{
int error;
void *ihl;
struct pxa_timer_softc *sc;
sc = (struct pxa_timer_softc *)device_get_softc(dev);
if (timer_softc != NULL)
return (ENXIO);
error = bus_alloc_resources(dev, pxa_timer_spec, sc->pt_res);
if (error) {
device_printf(dev, "could not allocate resources\n");
return (ENXIO);
}
sc->pt_bst = rman_get_bustag(sc->pt_res[0]);
sc->pt_bsh = rman_get_bushandle(sc->pt_res[0]);
timer_softc = sc;
pxa_timer_interrupt_disable(-1);
pxa_timer_watchdog_disable();
if (bus_setup_intr(dev, sc->pt_res[1], INTR_TYPE_CLK,
pxa_hardclock, NULL, NULL, &ihl) != 0) {
bus_release_resources(dev, pxa_timer_spec, sc->pt_res);
device_printf(dev, "could not setup hardclock interrupt\n");
return (ENXIO);
}
return (0);
}
static int
pxa_hardclock(void *arg)
{
struct trapframe *frame;
frame = (struct trapframe *)arg;
/* Clear the interrupt */
pxa_timer_clear_ossr(OST_SR_CH0);
/* Schedule next tick */
pxa_timer_set_osmr(0, pxa_timer_get_oscr() + PXA_TIMER_TICK);
/* Do what we came here for */
hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
return (FILTER_HANDLED);
}
static device_method_t pxa_timer_methods[] = {
DEVMETHOD(device_probe, pxa_timer_probe),
DEVMETHOD(device_attach, pxa_timer_attach),
{0, 0}
};
static driver_t pxa_timer_driver = {
"timer",
pxa_timer_methods,
sizeof(struct pxa_timer_softc),
};
static devclass_t pxa_timer_devclass;
DRIVER_MODULE(pxatimer, pxa, pxa_timer_driver, pxa_timer_devclass, 0, 0);
static unsigned
pxa_timer_get_timecount(struct timecounter *tc)
{
return (pxa_timer_get_oscr());
}
void
cpu_initclocks(void)
{
pxa_timer_set_oscr(0);
pxa_timer_set_osmr(0, PXA_TIMER_TICK);
pxa_timer_interrupt_enable(0);
tc_init(&pxa_timer_timecounter);
}
void
cpu_reset(void)
{
uint32_t val;
(void)disable_interrupts(PSR_I|PSR_F);
val = pxa_timer_get_oscr();
val += PXA_TIMER_FREQUENCY;
pxa_timer_set_osmr(3, val);
pxa_timer_watchdog_enable();
for(;;);
}
void
DELAY(int usec)
{
uint32_t val;
if (timer_softc == NULL) {
for (; usec > 0; usec--)
for (val = 100; val > 0; val--)
;
return;
}
TSENTER();
val = pxa_timer_get_oscr();
val += (PXA_TIMER_FREQUENCY * usec) / 1000000;
while (pxa_timer_get_oscr() <= val);
TSEXIT();
}
uint32_t
pxa_timer_get_osmr(int which)
{
return (bus_space_read_4(timer_softc->pt_bst,
timer_softc->pt_bsh, which * 0x4));
}
void
pxa_timer_set_osmr(int which, uint32_t val)
{
bus_space_write_4(timer_softc->pt_bst,
timer_softc->pt_bsh, which * 0x4, val);
}
uint32_t
pxa_timer_get_oscr(void)
{
return (bus_space_read_4(timer_softc->pt_bst,
timer_softc->pt_bsh, OST_CR));
}
void
pxa_timer_set_oscr(uint32_t val)
{
bus_space_write_4(timer_softc->pt_bst,
timer_softc->pt_bsh, OST_CR, val);
}
uint32_t
pxa_timer_get_ossr(void)
{
return (bus_space_read_4(timer_softc->pt_bst,
timer_softc->pt_bsh, OST_SR));
}
void
pxa_timer_clear_ossr(uint32_t val)
{
bus_space_write_4(timer_softc->pt_bst,
timer_softc->pt_bsh, OST_SR, val);
}
void
pxa_timer_watchdog_enable(void)
{
bus_space_write_4(timer_softc->pt_bst,
timer_softc->pt_bsh, OST_WR, 0x1);
}
void
pxa_timer_watchdog_disable(void)
{
bus_space_write_4(timer_softc->pt_bst,
timer_softc->pt_bsh, OST_WR, 0x0);
}
void
pxa_timer_interrupt_enable(int which)
{
uint32_t oier;
if (which == -1) {
bus_space_write_4(timer_softc->pt_bst,
timer_softc->pt_bsh, OST_IR, 0xf);
return;
}
oier = bus_space_read_4(timer_softc->pt_bst,
timer_softc->pt_bsh, OST_IR);
oier |= 1 << which;
bus_space_write_4(timer_softc->pt_bst,
timer_softc->pt_bsh, OST_IR, oier);
}
void
pxa_timer_interrupt_disable(int which)
{
uint32_t oier;
if (which == -1) {
bus_space_write_4(timer_softc->pt_bst,
timer_softc->pt_bsh, OST_IR, 0);
}
oier = bus_space_read_4(timer_softc->pt_bst,
timer_softc->pt_bsh, OST_IR);
oier &= ~(1 << which);
bus_space_write_4(timer_softc->pt_bst,
timer_softc->pt_bsh, OST_IR, oier);
}

758
sys/arm/xscale/pxa/pxareg.h Normal file
View File

@ -0,0 +1,758 @@
/* $NetBSD: pxa2x0reg.h,v 1.9 2006/04/10 04:13:58 simonb Exp $ */
/*-
* SPDX-License-Identifier: BSD-4-Clause
*
* Copyright (c) 2002 Genetec Corporation. All rights reserved.
* Written by Hiroyuki Bessho for Genetec Corporation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed for the NetBSD Project by
* Genetec Corporation.
* 4. The name of Genetec Corporation may not be used to endorse or
* promote products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORPORATION
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*/
/*
* Intel PXA2[15]0 processor is XScale based integrated CPU
*
* Reference:
* Intel(r) PXA250 and PXA210 Application Processors
* Developer's Manual
* (278522-001.pdf)
*/
#ifndef _ARM_XSCALE_PXAREG_H_
#define _ARM_XSCALE_PXAREG_H_
#ifndef _LOCORE
#include <sys/types.h> /* for uint32_t */
#endif
/*
* Chip select domains
*/
#define PXA2X0_CS0_START 0x00000000
#define PXA2X0_CS1_START 0x04000000
#define PXA2X0_CS2_START 0x08000000
#define PXA2X0_CS3_START 0x0c000000
#define PXA2X0_CS4_START 0x10000000
#define PXA2X0_CS5_START 0x14000000
#define PXA2X0_CS_SIZE 0x04000000
#define PXA2X0_PCMCIA_SLOT0 0x20000000
#define PXA2X0_PCMCIA_SLOT1 0x30000000
#define PXA2X0_PERIPH_START 0x40000000
/* #define PXA2X0_MEMCTL_START 0x48000000 */
#define PXA270_PERIPH_END 0x530fffff
#define PXA250_PERIPH_END 0x480fffff
#define PXA2X0_PERIPH_OFFSET 0xa8000000
#define PXA2X0_SDRAM0_START 0xa0000000
#define PXA2X0_SDRAM1_START 0xa4000000
#define PXA2X0_SDRAM2_START 0xa8000000
#define PXA2X0_SDRAM3_START 0xac000000
#define PXA2X0_SDRAM_BANKS 4
#define PXA2X0_SDRAM_BANK_SIZE 0x04000000
/*
* Physical address of integrated peripherals
*/
#define PXA2X0_DMAC_BASE 0x40000000
#define PXA2X0_DMAC_SIZE 0x300
#define PXA2X0_FFUART_BASE 0x40100000 /* Full Function UART */
#define PXA2X0_FFUART_SIZE 0x20
#define PXA2X0_BTUART_BASE 0x40200000 /* Bluetooth UART */
#define PXA2X0_BTUART_SIZE 0x24
#define PXA2X0_I2C_BASE 0x40300000
#define PXA2X0_I2C_SIZE 0x000016a4
#define PXA2X0_I2S_BASE 0x40400000
#define PXA2X0_AC97_BASE 0x40500000
#define PXA2X0_AC97_SIZE 0x600
#define PXA2X0_USBDC_BASE 0x40600000 /* USB Client */
#define PXA2X0_USBDC_SIZE 0x0e04
#define PXA2X0_STUART_BASE 0x40700000 /* Standard UART */
#define PXA2X0_STUART_SIZE 0x24
#define PXA2X0_ICP_BASE 0x40800000
#define PXA2X0_RTC_BASE 0x40900000
#define PXA2X0_RTC_SIZE 0x10
#define PXA2X0_OST_BASE 0x40a00000 /* OS Timer */
#define PXA2X0_OST_SIZE 0x20
#define PXA2X0_PWM0_BASE 0x40b00000
#define PXA2X0_PWM1_BASE 0x40c00000
#define PXA2X0_INTCTL_BASE 0x40d00000 /* Interrupt controller */
#define PXA2X0_INTCTL_SIZE 0x20
#define PXA2X0_GPIO_BASE 0x40e00000
#define PXA270_GPIO_SIZE 0x150
#define PXA250_GPIO_SIZE 0x70
#define PXA2X0_POWMAN_BASE 0x40f00000 /* Power management */
#define PXA2X0_SSP_BASE 0x41000000
#define PXA2X0_MMC_BASE 0x41100000 /* MultiMediaCard */
#define PXA2X0_MMC_SIZE 0x48
#define PXA2X0_CLKMAN_BASE 0x41300000 /* Clock Manager */
#define PXA2X0_CLKMAN_SIZE 12
#define PXA2X0_HWUART_BASE 0x41600000 /* Hardware UART */
#define PXA2X0_HWUART_SIZE 0x30
#define PXA2X0_LCDC_BASE 0x44000000 /* LCD Controller */
#define PXA2X0_LCDC_SIZE 0x220
#define PXA2X0_MEMCTL_BASE 0x48000000 /* Memory Controller */
#define PXA2X0_MEMCTL_SIZE 0x48
#define PXA2X0_USBH_BASE 0x4c000000 /* USB Host controller */
#define PXA2X0_USBH_SIZE 0x70
/* Internal SRAM storage. PXA27x only */
#define PXA270_SRAM0_START 0x5c000000
#define PXA270_SRAM1_START 0x5c010000
#define PXA270_SRAM2_START 0x5c020000
#define PXA270_SRAM3_START 0x5c030000
#define PXA270_SRAM_BANKS 4
#define PXA270_SRAM_BANK_SIZE 0x00010000
/* width of interrupt controller */
#define ICU_LEN 32 /* but [0..7,15,16] is not used */
#define ICU_INT_HWMASK 0xffffff00
#define PXA250_IRQ_MIN 8 /* 0..7 are not used by integrated
peripherals */
#define PXA270_IRQ_MIN 0
#define PXA2X0_INT_USBH1 3 /* USB host (OHCI) */
#define PXA2X0_INT_HWUART 7
#define PXA2X0_INT_GPIO0 8
#define PXA2X0_INT_GPIO1 9
#define PXA2X0_INT_GPION 10 /* irq from GPIO[2..80] */
#define PXA2X0_INT_USB 11
#define PXA2X0_INT_PMU 12
#define PXA2X0_INT_I2S 13
#define PXA2X0_INT_AC97 14
#define PXA2X0_INT_LCD 17
#define PXA2X0_INT_I2C 18
#define PXA2X0_INT_ICP 19
#define PXA2X0_INT_STUART 20
#define PXA2X0_INT_BTUART 21
#define PXA2X0_INT_FFUART 22
#define PXA2X0_INT_MMC 23
#define PXA2X0_INT_SSP 24
#define PXA2X0_INT_DMA 25
#define PXA2X0_INT_OST0 26
#define PXA2X0_INT_OST1 27
#define PXA2X0_INT_OST2 28
#define PXA2X0_INT_OST3 29
#define PXA2X0_INT_RTCHZ 30
#define PXA2X0_INT_ALARM 31 /* RTC Alarm interrupt */
/* DMAC */
#define DMAC_N_CHANNELS 16
#define DMAC_N_PRIORITIES 3
#define DMAC_DCSR(n) ((n)*4)
#define DCSR_BUSERRINTR (1<<0) /* bus error interrupt */
#define DCSR_STARTINTR (1<<1) /* start interrupt */
#define DCSR_ENDINTR (1<<2) /* end interrupt */
#define DCSR_STOPSTATE (1<<3) /* channel is not running */
#define DCSR_REQPEND (1<<8) /* request pending */
#define DCSR_STOPIRQEN (1<<29) /* stop interrupt enable */
#define DCSR_NODESCFETCH (1<<30) /* no-descriptor fetch mode */
#define DCSR_RUN (1<<31)
#define DMAC_DINT 0x00f0 /* DAM interrupt */
#define DMAC_DINT_MASK 0xffffu
#define DMAC_DRCMR(n) (0x100+(n)*4) /* Channel map register */
#define DRCMR_CHLNUM 0x0f /* channel number */
#define DRCMR_MAPVLD (1<<7) /* map valid */
#define DMAC_DDADR(n) (0x0200+(n)*16)
#define DDADR_STOP (1<<0)
#define DMAC_DSADR(n) (0x0204+(n)*16)
#define DMAC_DTADR(n) (0x0208+(n)*16)
#define DMAC_DCMD(n) (0x020c+(n)*16)
#define DCMD_LENGTH_MASK 0x1fff
#define DCMD_WIDTH_SHIFT 14
#define DCMD_WIDTH_0 (0<<DCMD_WIDTH_SHIFT) /* for mem-to-mem transfer*/
#define DCMD_WIDTH_1 (1<<DCMD_WIDTH_SHIFT)
#define DCMD_WIDTH_2 (2<<DCMD_WIDTH_SHIFT)
#define DCMD_WIDTH_4 (3<<DCMD_WIDTH_SHIFT)
#define DCMD_SIZE_SHIFT 16
#define DCMD_SIZE_8 (1<<DCMD_SIZE_SHIFT)
#define DCMD_SIZE_16 (2<<DCMD_SIZE_SHIFT)
#define DCMD_SIZE_32 (3<<DCMD_SIZE_SHIFT)
#define DCMD_LITTLE_ENDIEN (0<<18)
#define DCMD_ENDIRQEN (1<<21)
#define DCMD_STARTIRQEN (1<<22)
#define DCMD_FLOWTRG (1<<28) /* flow control by target */
#define DCMD_FLOWSRC (1<<29) /* flow control by source */
#define DCMD_INCTRGADDR (1<<30) /* increment target address */
#define DCMD_INCSRCADDR (1<<31) /* increment source address */
#ifndef __ASSEMBLER__
/* DMA descriptor */
struct pxa_dma_desc {
volatile uint32_t dd_ddadr;
#define DMAC_DESC_LAST 0x1
volatile uint32_t dd_dsadr;
volatile uint32_t dd_dtadr;
volatile uint32_t dd_dcmd; /* command and length */
};
#endif
/* UART */
#define PXA2X0_COM_FREQ 14745600L
/* I2C */
#define I2C_IBMR 0x1680 /* Bus monitor register */
#define I2C_IDBR 0x1688 /* Data buffer */
#define I2C_ICR 0x1690 /* Control register */
#define ICR_START (1<<0)
#define ICR_STOP (1<<1)
#define ICR_ACKNAK (1<<2)
#define ICR_TB (1<<3)
#define ICR_MA (1<<4)
#define I2C_ISR 0x1698 /* Status register */
#define I2C_ISAR 0x16a0 /* Slave address */
/* Clock Manager */
#define CLKMAN_CCCR 0x00 /* Core Clock Configuration */
#define CCCR_TURBO_X1 (2<<7)
#define CCCR_TURBO_X15 (3<<7) /* x 1.5 */
#define CCCR_TURBO_X2 (4<<7)
#define CCCR_TURBO_X25 (5<<7) /* x 2.5 */
#define CCCR_TURBO_X3 (6<<7) /* x 3.0 */
#define CCCR_RUN_X1 (1<<5)
#define CCCR_RUN_X2 (2<<5)
#define CCCR_RUN_X4 (3<<5)
#define CCCR_MEM_X27 (1<<0) /* x27, 99.53MHz */
#define CCCR_MEM_X32 (2<<0) /* x32, 117,96MHz */
#define CCCR_MEM_X36 (3<<0) /* x26, 132.71MHz */
#define CCCR_MEM_X40 (4<<0) /* x27, 99.53MHz */
#define CCCR_MEM_X45 (5<<0) /* x27, 99.53MHz */
#define CCCR_MEM_X9 (0x1f<<0) /* x9, 33.2MHz */
#define CLKMAN_CKEN 0x04 /* Clock Enable Register */
#define CLKMAN_OSCC 0x08 /* Osillcator Configuration Register */
#define CCCR_N_SHIFT 7
#define CCCR_N_MASK (0x07<<CCCR_N_SHIFT)
#define CCCR_M_SHIFT 5
#define CCCR_M_MASK (0x03<<CCCR_M_SHIFT)
#define CCCR_L_MASK 0x1f
#define CKEN_PWM0 (1<<0)
#define CKEN_PWM1 (1<<1)
#define CKEN_AC97 (1<<2)
#define CKEN_SSP (1<<3)
#define CKEN_STUART (1<<5)
#define CKEN_FFUART (1<<6)
#define CKEN_BTUART (1<<7)
#define CKEN_I2S (1<<8)
#define CKEN_USBH (1<<10)
#define CKEN_USB (1<<11)
#define CKEN_MMC (1<<12)
#define CKEN_FICP (1<<13)
#define CKEN_I2C (1<<14)
#define CKEN_LCD (1<<16)
#define OSCC_OOK (1<<0) /* 32.768 kHz oscillator status */
#define OSCC_OON (1<<1) /* 32.768 kHz oscillator */
/*
* RTC
*/
#define RTC_RCNR 0x0000 /* count register */
#define RTC_RTAR 0x0004 /* alarm register */
#define RTC_RTSR 0x0008 /* status register */
#define RTC_RTTR 0x000c /* trim register */
/*
* GPIO
*/
#define GPIO_GPLR0 0x00 /* Level reg [31:0] */
#define GPIO_GPLR1 0x04 /* Level reg [63:32] */
#define GPIO_GPLR2 0x08 /* Level reg [80:64] */
#define GPIO_GPDR0 0x0c /* dir reg [31:0] */
#define GPIO_GPDR1 0x10 /* dir reg [63:32] */
#define GPIO_GPDR2 0x14 /* dir reg [80:64] */
#define GPIO_GPSR0 0x18 /* set reg [31:0] */
#define GPIO_GPSR1 0x1c /* set reg [63:32] */
#define GPIO_GPSR2 0x20 /* set reg [80:64] */
#define GPIO_GPCR0 0x24 /* clear reg [31:0] */
#define GPIO_GPCR1 0x28 /* clear reg [63:32] */
#define GPIO_GPCR2 0x2c /* clear reg [80:64] */
#define GPIO_GPER0 0x30 /* rising edge [31:0] */
#define GPIO_GPER1 0x34 /* rising edge [63:32] */
#define GPIO_GPER2 0x38 /* rising edge [80:64] */
#define GPIO_GRER0 0x30 /* rising edge [31:0] */
#define GPIO_GRER1 0x34 /* rising edge [63:32] */
#define GPIO_GRER2 0x38 /* rising edge [80:64] */
#define GPIO_GFER0 0x3c /* falling edge [31:0] */
#define GPIO_GFER1 0x40 /* falling edge [63:32] */
#define GPIO_GFER2 0x44 /* falling edge [80:64] */
#define GPIO_GEDR0 0x48 /* edge detect [31:0] */
#define GPIO_GEDR1 0x4c /* edge detect [63:32] */
#define GPIO_GEDR2 0x50 /* edge detect [80:64] */
#define GPIO_GAFR0_L 0x54 /* alternate function [15:0] */
#define GPIO_GAFR0_U 0x58 /* alternate function [31:16] */
#define GPIO_GAFR1_L 0x5c /* alternate function [47:32] */
#define GPIO_GAFR1_U 0x60 /* alternate function [63:48] */
#define GPIO_GAFR2_L 0x64 /* alternate function [79:64] */
#define GPIO_GAFR2_U 0x68 /* alternate function [80] */
/* Only for PXA270 */
#define GPIO_GAFR3_L 0x6c /* alternate function [111:96] */
#define GPIO_GAFR3_U 0x70 /* alternate function [120:112] */
#define GPIO_GPLR3 0x100 /* Level reg [120:96] */
#define GPIO_GPDR3 0x10c /* dir reg [120:96] */
#define GPIO_GPSR3 0x118 /* set reg [120:96] */
#define GPIO_GPCR3 0x124 /* clear reg [120:96] */
#define GPIO_GRER3 0x130 /* rising edge [120:96] */
#define GPIO_GFER3 0x13c /* falling edge [120:96] */
#define GPIO_GEDR3 0x148 /* edge detect [120:96] */
/* a bit simpler if we don't support PXA270 */
#define PXA250_GPIO_REG(r, pin) ((r) + (((pin) / 32) * 4))
#define PXA250_GPIO_NPINS 85
#define PXA270_GPIO_REG(r, pin) \
(pin < 96 ? PXA250_GPIO_REG(r,pin) : ((r) + 0x100 + ((((pin)-96) / 32) * 4)))
#define PXA270_GPIO_NPINS 121
#define GPIO_BANK(pin) ((pin) / 32)
#define GPIO_BIT(pin) (1u << ((pin) & 0x1f))
#define GPIO_FN_REG(pin) (GPIO_GAFR0_L + (((pin) / 16) * 4))
#define GPIO_FN_SHIFT(pin) ((pin & 0xf) * 2)
#define GPIO_IN 0x00 /* Regular GPIO input pin */
#define GPIO_OUT 0x10 /* Regular GPIO output pin */
#define GPIO_ALT_FN_1_IN 0x01 /* Alternate function 1 input */
#define GPIO_ALT_FN_1_OUT 0x11 /* Alternate function 1 output */
#define GPIO_ALT_FN_2_IN 0x02 /* Alternate function 2 input */
#define GPIO_ALT_FN_2_OUT 0x12 /* Alternate function 2 output */
#define GPIO_ALT_FN_3_IN 0x03 /* Alternate function 3 input */
#define GPIO_ALT_FN_3_OUT 0x13 /* Alternate function 3 output */
#define GPIO_SET 0x20 /* Initial state is Set */
#define GPIO_CLR 0x00 /* Initial state is Clear */
#define GPIO_FN_MASK 0x03
#define GPIO_FN_IS_OUT(n) ((n) & GPIO_OUT)
#define GPIO_FN_IS_SET(n) ((n) & GPIO_SET)
#define GPIO_FN(n) ((n) & GPIO_FN_MASK)
#define GPIO_IS_GPIO(n) (GPIO_FN(n) == 0)
#define GPIO_IS_GPIO_IN(n) (((n) & (GPIO_FN_MASK|GPIO_OUT)) == GPIO_IN)
#define GPIO_IS_GPIO_OUT(n) (((n) & (GPIO_FN_MASK|GPIO_OUT)) == GPIO_OUT)
#define IRQ_GPIO0 64
#define IRQ_NGPIO 128
#define IRQ_GPIO_MAX IRQ_GPIO0 + IRQ_NGPIO
#define IRQ_TO_GPIO(x) (x - IRQ_GPIO0)
#define GPIO_TO_IRQ(x) (x + IRQ_GPIO0)
/*
* memory controller
*/
#define MEMCTL_MDCNFG 0x0000
#define MDCNFG_DE0 (1<<0)
#define MDCNFG_DE1 (1<<1)
#define MDCNFD_DWID01_SHIFT 2
#define MDCNFD_DCAC01_SHIFT 3
#define MDCNFD_DRAC01_SHIFT 5
#define MDCNFD_DNB01_SHIFT 7
#define MDCNFG_DE2 (1<<16)
#define MDCNFG_DE3 (1<<17)
#define MDCNFD_DWID23_SHIFT 18
#define MDCNFD_DCAC23_SHIFT 19
#define MDCNFD_DRAC23_SHIFT 21
#define MDCNFD_DNB23_SHIFT 23
#define MDCNFD_DWID_MASK 0x1
#define MDCNFD_DCAC_MASK 0x3
#define MDCNFD_DRAC_MASK 0x3
#define MDCNFD_DNB_MASK 0x1
#define MEMCTL_MDREFR 0x04 /* refresh control register */
#define MDREFR_DRI 0xfff
#define MDREFR_E0PIN (1<<12)
#define MDREFR_K0RUN (1<<13) /* SDCLK0 enable */
#define MDREFR_K0DB2 (1<<14) /* SDCLK0 1/2 freq */
#define MDREFR_E1PIN (1<<15)
#define MDREFR_K1RUN (1<<16) /* SDCLK1 enable */
#define MDREFR_K1DB2 (1<<17) /* SDCLK1 1/2 freq */
#define MDREFR_K2RUN (1<<18) /* SDCLK2 enable */
#define MDREFR_K2DB2 (1<<19) /* SDCLK2 1/2 freq */
#define MDREFR_APD (1<<20) /* Auto Power Down */
#define MDREFR_SLFRSH (1<<22) /* Self Refresh */
#define MDREFR_K0FREE (1<<23) /* SDCLK0 free run */
#define MDREFR_K1FREE (1<<24) /* SDCLK1 free run */
#define MDREFR_K2FREE (1<<25) /* SDCLK2 free run */
#define MEMCTL_MSC0 0x08 /* Asychronous Statis memory Control CS[01] */
#define MEMCTL_MSC1 0x0c /* Asychronous Statis memory Control CS[23] */
#define MEMCTL_MSC2 0x10 /* Asychronous Statis memory Control CS[45] */
#define MSC_RBUFF_SHIFT 15 /* return data buffer */
#define MSC_RBUFF (1<<MSC_RBUFF_SHIFT)
#define MSC_RRR_SHIFT 12 /* recovery time */
#define MSC_RRR (7<<MSC_RRR_SHIFT)
#define MSC_RDN_SHIFT 8 /* ROM delay next access */
#define MSC_RDN (0x0f<<MSC_RDN_SHIFT)
#define MSC_RDF_SHIFT 4 /* ROM delay first access*/
#define MSC_RDF (0x0f<<MSC_RDF_SHIFT)
#define MSC_RBW_SHIFT 3 /* 32/16 bit bus */
#define MSC_RBW (1<<MSC_RBW_SHIFT)
#define MSC_RT_SHIFT 0 /* type */
#define MSC_RT (7<<MSC_RT_SHIFT)
#define MSC_RT_NONBURST 0
#define MSC_RT_SRAM 1
#define MSC_RT_BURST4 2
#define MSC_RT_BURST8 3
#define MSC_RT_VLIO 4
/* expansion memory timing configuration */
#define MEMCTL_MCMEM(n) (0x28+4*(n))
#define MEMCTL_MCATT(n) (0x30+4*(n))
#define MEMCTL_MCIO(n) (0x38+4*(n))
#define MC_HOLD_SHIFT 14
#define MC_ASST_SHIFT 7
#define MC_SET_SHIFT 0
#define MC_TIMING_VAL(hold,asst,set) (((hold)<<MC_HOLD_SHIFT)| \
((asst)<<MC_ASST_SHIFT)|((set)<<MC_SET_SHIFT))
#define MEMCTL_MECR 0x14 /* Expansion memory configuration */
#define MECR_NOS (1<<0) /* Number of sockets */
#define MECR_CIT (1<<1) /* Card-is-there */
#define MEMCTL_MDMRS 0x0040
/*
* LCD Controller
*/
#define LCDC_LCCR0 0x000 /* Controller Control Register 0 */
#define LCCR0_ENB (1U<<0) /* LCD Controller Enable */
#define LCCR0_CMS (1U<<1) /* Color/Mono select */
#define LCCR0_SDS (1U<<2) /* Single/Dual -panel */
#define LCCR0_LDM (1U<<3) /* LCD Disable Done Mask */
#define LCCR0_SFM (1U<<4) /* Start of Frame Mask */
#define LCCR0_IUM (1U<<5) /* Input FIFO Underrun Mask */
#define LCCR0_EFM (1U<<6) /* End of Frame Mask */
#define LCCR0_PAS (1U<<7) /* Passive/Active Display select */
#define LCCR0_DPD (1U<<9) /* Double-Pixel Data pin mode */
#define LCCR0_DIS (1U<<10) /* LCD Disable */
#define LCCR0_QDM (1U<<11) /* LCD Quick Disable Mask */
#define LCCR0_BM (1U<<20) /* Branch Mask */
#define LCCR0_OUM (1U<<21) /* Output FIFO Underrun Mask */
#define LCCR0_IMASK (LCCR0_LDM|LCCR0_SFM|LCCR0_IUM|LCCR0_EFM|LCCR0_QDM|LCCR0_BM|LCCR0_OUM)
#define LCDC_LCCR1 0x004 /* Controller Control Register 1 */
#define LCDC_LCCR2 0x008 /* Controller Control Register 2 */
#define LCDC_LCCR3 0x00c /* Controller Control Register 2 */
#define LCCR3_BPP_SHIFT 24 /* Bits per pixel */
#define LCCR3_BPP (0x07<<LCCR3_BPP_SHIFT)
#define LCDC_LCCR4 0x010 /* Controller Control Register 4 */
#define LCDC_LCCR5 0x014 /* Controller Control Register 5 */
#define LCDC_FBR0 0x020 /* DMA ch0 frame branch register */
#define LCDC_FBR1 0x024 /* DMA ch1 frame branch register */
#define LCDC_FBR2 0x028 /* DMA ch2 frame branch register */
#define LCDC_FBR3 0x02c /* DMA ch3 frame branch register */
#define LCDC_FBR4 0x030 /* DMA ch4 frame branch register */
#define LCDC_LCSR1 0x034 /* controller status register 1 PXA27x only */
#define LCDC_LCSR 0x038 /* controller status register */
#define LCSR_LDD (1U<<0) /* LCD disable done */
#define LCSR_SOF (1U<<1) /* Start of frame */
#define LCDC_LIIDR 0x03c /* controller interrupt ID Register */
#define LCDC_TRGBR 0x040 /* TMED RGB Speed Register */
#define LCDC_TCR 0x044 /* TMED Control Register */
#define LCDC_OVL1C1 0x050 /* Overlay 1 control register 1 */
#define LCDC_OVL1C2 0x060 /* Overlay 1 control register 2 */
#define LCDC_OVL2C1 0x070 /* Overlay 1 control register 1 */
#define LCDC_OVL2C2 0x080 /* Overlay 1 control register 2 */
#define LCDC_CCR 0x090 /* Cursor control register */
#define LCDC_CMDCR 0x100 /* Command control register */
#define LCDC_PRSR 0x104 /* Panel read status register */
#define LCDC_FBR5 0x110 /* DMA ch5 frame branch register */
#define LCDC_FBR6 0x114 /* DMA ch6 frame branch register */
#define LCDC_FDADR0 0x200 /* DMA ch0 frame descriptor address */
#define LCDC_FSADR0 0x204 /* DMA ch0 frame source address */
#define LCDC_FIDR0 0x208 /* DMA ch0 frame ID register */
#define LCDC_LDCMD0 0x20c /* DMA ch0 command register */
#define LCDC_FDADR1 0x210 /* DMA ch1 frame descriptor address */
#define LCDC_FSADR1 0x214 /* DMA ch1 frame source address */
#define LCDC_FIDR1 0x218 /* DMA ch1 frame ID register */
#define LCDC_LDCMD1 0x21c /* DMA ch1 command register */
#define LCDC_FDADR2 0x220 /* DMA ch2 frame descriptor address */
#define LCDC_FSADR2 0x224 /* DMA ch2 frame source address */
#define LCDC_FIDR2 0x228 /* DMA ch2 frame ID register */
#define LCDC_LDCMD2 0x22c /* DMA ch2 command register */
#define LCDC_FDADR3 0x230 /* DMA ch3 frame descriptor address */
#define LCDC_FSADR3 0x234 /* DMA ch3 frame source address */
#define LCDC_FIDR3 0x238 /* DMA ch3 frame ID register */
#define LCDC_LDCMD3 0x23c /* DMA ch3 command register */
#define LCDC_FDADR4 0x240 /* DMA ch4 frame descriptor address */
#define LCDC_FSADR4 0x244 /* DMA ch4 frame source address */
#define LCDC_FIDR4 0x248 /* DMA ch4 frame ID register */
#define LCDC_LDCMD4 0x24c /* DMA ch4 command register */
#define LCDC_FDADR5 0x250 /* DMA ch5 frame descriptor address */
#define LCDC_FSADR5 0x254 /* DMA ch5 frame source address */
#define LCDC_FIDR5 0x258 /* DMA ch5 frame ID register */
#define LCDC_LDCMD5 0x25c /* DMA ch5 command register */
#define LCDC_FDADR6 0x260 /* DMA ch6 frame descriptor address */
#define LCDC_FSADR6 0x264 /* DMA ch6 frame source address */
#define LCDC_FIDR6 0x268 /* DMA ch6 frame ID register */
#define LCDC_LDCMD6 0x26c /* DMA ch6 command register */
#define LCDC_LCDBSCNTR 0x054 /* LCD buffer strength control register */
/*
* MMC/SD controller
*/
#define MMC_STRPCL 0x00 /* start/stop MMC clock */
#define STRPCL_NOOP 0
#define STRPCL_STOP 1 /* stop MMC clock */
#define STRPCL_START 2 /* start MMC clock */
#define MMC_STAT 0x04 /* status register */
#define STAT_READ_TIME_OUT (1<<0)
#define STAT_TIMEOUT_RESPONSE (1<<1)
#define STAT_CRC_WRITE_ERROR (1<<2)
#define STAT_CRC_READ_ERROR (1<<3)
#define STAT_SPI_READ_ERROR_TOKEN (1<<4)
#define STAT_RES_CRC_ERR (1<<5)
#define STAT_XMIT_FIFO_EMPTY (1<<6)
#define STAT_RECV_FIFO_FULL (1<<7)
#define STAT_CLK_EN (1<<8)
#define STAT_DATA_TRAN_DONE (1<<11)
#define STAT_PRG_DONE (1<<12)
#define STAT_END_CMD_RES (1<<13)
#define MMC_CLKRT 0x08 /* MMC clock rate */
#define CLKRT_20M 0
#define CLKRT_10M 1
#define CLKRT_5M 2
#define CLKRT_2_5M 3
#define CLKRT_1_25M 4
#define CLKRT_625K 5
#define CLKRT_312K 6
#define MMC_SPI 0x0c /* SPI mode control */
#define SPI_EN (1<<0) /* enable SPI mode */
#define SPI_CRC_ON (1<<1) /* enable CRC generation */
#define SPI_CS_EN (1<<2) /* Enable CS[01] */
#define SPI_CS_ADDRESS (1<<3) /* CS0/CS1 */
#define MMC_CMDAT 0x10 /* command/response/data */
#define CMDAT_RESPONSE_FORMAT 0x03
#define CMDAT_RESPONSE_FORMAT_NO 0 /* no response */
#define CMDAT_RESPONSE_FORMAT_R1 1 /* R1, R1b, R4, R5 */
#define CMDAT_RESPONSE_FORMAT_R2 2
#define CMDAT_RESPONSE_FORMAT_R3 3
#define CMDAT_DATA_EN (1<<2)
#define CMDAT_WRITE (1<<3) /* 1=write 0=read operation */
#define CMDAT_STREAM_BLOCK (1<<4) /* stream mode */
#define CMDAT_BUSY (1<<5) /* busy signal is expected */
#define CMDAT_INIT (1<<6) /* preceede command with 80 clocks */
#define CMDAT_MMC_DMA_EN (1<<7) /* DMA enable */
#define MMC_RESTO 0x14 /* expected response time out */
#define MMC_RDTO 0x18 /* expected data read time out */
#define MMC_BLKLEN 0x1c /* block length of data transaction */
#define MMC_NOB 0x20 /* number of blocks (block mode) */
#define MMC_PRTBUF 0x24 /* partial MMC_TXFIFO written */
#define PRTBUF_BUF_PART_FULL (1<<0) /* buffer partially full */
#define MMC_I_MASK 0x28 /* interrupt mask */
#define MMC_I_REG 0x2c /* interrupt register */
#define MMC_I_DATA_TRAN_DONE (1<<0)
#define MMC_I_PRG_DONE (1<<1)
#define MMC_I_END_CMD_RES (1<<2)
#define MMC_I_STOP_CMD (1<<3)
#define MMC_I_CLK_IS_OFF (1<<4)
#define MMC_I_RXFIFO_RD_REQ (1<<5)
#define MMC_I_TXFIFO_WR_REQ (1<<6)
#define MMC_CMD 0x30 /* index of current command */
#define MMC_ARGH 0x34 /* MSW part of the current command arg */
#define MMC_ARGL 0x38 /* LSW part of the current command arg */
#define MMC_RES 0x3c /* response FIFO */
#define MMC_RXFIFO 0x40 /* receive FIFO */
#define MMC_TXFIFO 0x44 /* transmit FIFO */
/*
* AC97
*/
#define AC97_N_CODECS 2
#define AC97_GCR 0x000c /* Global control register */
#define GCR_GIE (1<<0) /* interrupt enable */
#define GCR_COLD_RST (1<<1)
#define GCR_WARM_RST (1<<2)
#define GCR_ACLINK_OFF (1<<3)
#define GCR_PRIRES_IEN (1<<4) /* Primary resume interrupt enable */
#define GCR_SECRES_IEN (1<<5) /* Secondary resume interrupt enable */
#define GCR_PRIRDY_IEN (1<<8) /* Primary ready interrupt enable */
#define GCR_SECRDY_IEN (1<<9) /* Primary ready interrupt enable */
#define GCR_SDONE_IE (1<<18) /* Status done interrupt enable */
#define GCR_CDONE_IE (1<<19) /* Command done interrupt enable */
#define AC97_GSR 0x001c /* Global status register */
#define GSR_GSCI (1<<0) /* codec GPI status change interrupt */
#define GSR_MIINT (1<<1) /* modem in interrupt */
#define GSR_MOINT (1<<2) /* modem out interrupt */
#define GSR_PIINT (1<<5) /* PCM in interrupt */
#define GSR_POINT (1<<6) /* PCM out interrupt */
#define GSR_MINT (1<<7) /* Mic in interrupt */
#define GSR_PCR (1<<8) /* primary code ready */
#define GSR_SCR (1<<9) /* secondary code ready */
#define GSR_PRIRES (1<<10) /* primary resume interrupt */
#define GSR_SECRES (1<<11) /* secondary resume interrupt */
#define GSR_BIT1SLT12 (1<<12) /* Bit 1 of slot 12 */
#define GSR_BIT2SLT12 (1<<13) /* Bit 2 of slot 12 */
#define GSR_BIT3SLT12 (1<<14) /* Bit 3 of slot 12 */
#define GSR_RDCS (1<<15) /* Read completion status */
#define GSR_SDONE (1<<18) /* status done */
#define GSR_CDONE (1<<19) /* command done */
#define AC97_POCR 0x0000 /* PCM-out control */
#define AC97_PICR 0x0004 /* PCM-in control */
#define AC97_POSR 0x0010 /* PCM-out status */
#define AC97_PISR 0x0014 /* PCM-out status */
#define AC97_MCCR 0x0008 /* MIC-in control register */
#define AC97_MCSR 0x0018 /* MIC-in status register */
#define AC97_MICR 0x0100 /* Modem-in control register */
#define AC97_MISR 0x0108 /* Modem-in status register */
#define AC97_MOCR 0x0110 /* Modem-out control register */
#define AC97_MOSR 0x0118 /* Modem-out status register */
#define AC97_FEFIE (1<<3) /* fifo error interrupt enable */
#define AC97_FIFOE (1<<4) /* fifo error */
#define AC97_CAR 0x0020 /* Codec access register */
#define CAR_CAIP (1<<0) /* Codec access in progress */
#define AC97_PCDR 0x0040 /* PCM data register */
#define AC97_MCDR 0x0060 /* MIC-in data register */
#define AC97_MODR 0x0140 /* Modem data register */
/* address to access codec registers */
#define AC97_PRIAUDIO 0x0200 /* Primary audio codec */
#define AC97_SECAUDIO 0x0300 /* Secondary autio codec */
#define AC97_PRIMODEM 0x0400 /* Primary modem codec */
#define AC97_SECMODEM 0x0500 /* Secondary modem codec */
#define AC97_CODEC_BASE(c) (AC97_PRIAUDIO + ((c) * 0x100))
/*
* USB device controller
*/
#define USBDC_UDCCR 0x0000 /* UDC control register */
#define USBDC_UDCCS(n) (0x0010+4*(n)) /* Endpoint Control/Status Registers */
#define USBDC_UICR0 0x0050 /* UDC Interrupt Control Register 0 */
#define USBDC_UICR1 0x0054 /* UDC Interrupt Control Register 1 */
#define USBDC_USIR0 0x0058 /* UDC Status Interrupt Register 0 */
#define USBDC_USIR1 0x005C /* UDC Status Interrupt Register 1 */
#define USBDC_UFNHR 0x0060 /* UDC Frame Number Register High */
#define USBDC_UFNLR 0x0064 /* UDC Frame Number Register Low */
#define USBDC_UBCR2 0x0068 /* UDC Byte Count Register 2 */
#define USBDC_UBCR4 0x006C /* UDC Byte Count Register 4 */
#define USBDC_UBCR7 0x0070 /* UDC Byte Count Register 7 */
#define USBDC_UBCR9 0x0074 /* UDC Byte Count Register 9 */
#define USBDC_UBCR12 0x0078 /* UDC Byte Count Register 12 */
#define USBDC_UBCR14 0x007C /* UDC Byte Count Register 14 */
#define USBDC_UDDR0 0x0080 /* UDC Endpoint 0 Data Register */
#define USBDC_UDDR1 0x0100 /* UDC Endpoint 1 Data Register */
#define USBDC_UDDR2 0x0180 /* UDC Endpoint 2 Data Register */
#define USBDC_UDDR3 0x0200 /* UDC Endpoint 3 Data Register */
#define USBDC_UDDR4 0x0400 /* UDC Endpoint 4 Data Register */
#define USBDC_UDDR5 0x00A0 /* UDC Endpoint 5 Data Register */
#define USBDC_UDDR6 0x0600 /* UDC Endpoint 6 Data Register */
#define USBDC_UDDR7 0x0680 /* UDC Endpoint 7 Data Register */
#define USBDC_UDDR8 0x0700 /* UDC Endpoint 8 Data Register */
#define USBDC_UDDR9 0x0900 /* UDC Endpoint 9 Data Register */
#define USBDC_UDDR10 0x00C0 /* UDC Endpoint 10 Data Register */
#define USBDC_UDDR11 0x0B00 /* UDC Endpoint 11 Data Register */
#define USBDC_UDDR12 0x0B80 /* UDC Endpoint 12 Data Register */
#define USBDC_UDDR13 0x0C00 /* UDC Endpoint 13 Data Register */
#define USBDC_UDDR14 0x0E00 /* UDC Endpoint 14 Data Register */
#define USBDC_UDDR15 0x00E0 /* UDC Endpoint 15 Data Register */
#define USBHC_UHCRHDA 0x0048 /* UHC Root Hub Descriptor A */
#define UHCRHDA_POTPGT_SHIFT 24 /* Power on to power good time */
#define UHCRHDA_NOCP (1<<12) /* No over current protection */
#define UHCRHDA_OCPM (1<<11) /* Over current protection mode */
#define UHCRHDA_DT (1<<10) /* Device type */
#define UHCRHDA_NPS (1<<9) /* No power switching */
#define UHCRHDA_PSM (1<<8) /* Power switching mode */
#define UHCRHDA_NDP_MASK 0xff /* Number downstream ports */
#define USBHC_UHCRHDB 0x004c /* UHC Root Hub Descriptor B */
#define USBHC_UHCRHS 0x0050 /* UHC Root Hub Stauts */
#define USBHC_UHCHR 0x0064 /* UHC Reset Register */
#define UHCHR_SSEP3 (1<<11) /* Sleep standby enable for port3 */
#define UHCHR_SSEP2 (1<<10) /* Sleep standby enable for port2 */
#define UHCHR_SSEP1 (1<<9) /* Sleep standby enable for port1 */
#define UHCHR_PCPL (1<<7) /* Power control polarity low */
#define UHCHR_PSPL (1<<6) /* Power sense polarity low */
#define UHCHR_SSE (1<<5) /* Sleep standby enable */
#define UHCHR_UIT (1<<4) /* USB interrupt test */
#define UHCHR_SSDC (1<<3) /* Simulation scale down clock */
#define UHCHR_CGR (1<<2) /* Clock generation reset */
#define UHCHR_FHR (1<<1) /* Force host controller reset */
#define UHCHR_FSBIR (1<<0) /* Force system bus interface reset */
#define UHCHR_MASK 0xeff
/*
* PWM controller
*/
#define PWM_PWMCR 0x0000 /* Control register */
#define PWM_PWMDCR 0x0004 /* Duty cycle register */
#define PWM_FD (1<<10) /* Full duty */
#define PWM_PWMPCR 0x0008 /* Period register */
/*
* OS timer
*/
#define OST_MR0 0x00 /* Match register 0 */
#define OST_MR1 0x04 /* Match register 1 */
#define OST_MR2 0x08 /* Match register 2 */
#define OST_MR3 0x0c /* Match register 3 */
#define OST_CR 0x10 /* Count register */
#define OST_SR 0x14 /* Status register */
#define OST_SR_CH0 (1<<0)
#define OST_SR_CH1 (1<<1)
#define OST_SR_CH2 (1<<2)
#define OST_SR_CH3 (1<<3)
#define OST_WR 0x18 /* Watchdog enable register */
#define OST_IR 0x1c /* Interrupt enable register */
/*
* Interrupt controller
*/
#define ICU_IP 0x00 /* IRQ pending register */
#define ICU_MR 0x04 /* Mask register */
#define ICU_LR 0x08 /* Level register */
#define ICU_FP 0x0c /* FIQ pending register */
#define ICU_PR 0x10 /* Pending register */
#define ICU_CR 0x14 /* Control register */
#endif /* _ARM_XSCALE_PXAREG_H_ */

114
sys/arm/xscale/pxa/pxavar.h Normal file
View File

@ -0,0 +1,114 @@
/* $NetBSD: obiovar.h,v 1.4 2003/06/16 17:40:53 thorpej Exp $ */
/*-
* SPDX-License-Identifier: BSD-4-Clause
*
* Copyright (c) 2002, 2003 Wasabi Systems, Inc.
* All rights reserved.
*
* Written by Jason R. Thorpe for Wasabi Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed for the NetBSD Project by
* Wasabi Systems, Inc.
* 4. The name of Wasabi Systems, Inc. may not be used to endorse
* or promote products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*
*/
#ifndef _PXAVAR_H_
#define _PXAVAR_H_
#include <sys/rman.h>
struct obio_softc {
bus_space_tag_t obio_bst; /* bus space tag */
struct rman obio_mem;
struct rman obio_irq;
};
extern bus_space_tag_t base_tag;
extern bus_space_tag_t obio_tag;
void pxa_obio_tag_init(void);
bus_space_tag_t pxa_bus_tag_alloc(bus_addr_t);
uint32_t pxa_gpio_get_function(int);
uint32_t pxa_gpio_set_function(int, uint32_t);
int pxa_gpio_setup_intrhandler(const char *, driver_filter_t *,
driver_intr_t *, void *, int, int, void **);
void pxa_gpio_mask_irq(int);
void pxa_gpio_unmask_irq(int);
int pxa_gpio_get_next_irq(void);
struct dmac_channel;
struct dmac_descriptor {
uint32_t ddadr;
uint32_t dsadr;
uint32_t dtadr;
uint32_t dcmd;
};
#define DMACD_SET_DESCRIPTOR(d, dadr) do { d->ddadr = dadr; } while (0)
#define DMACD_SET_SOURCE(d, sadr) do { d->dsadr = sadr; } while (0)
#define DMACD_SET_TARGET(d, tadr) do { d->dtadr = tadr; } while (0)
#define DMACD_SET_COMMAND(d, cmd) do { d->dcmd = cmd; } while (0)
#define DMAC_PRIORITY_HIGHEST 1
#define DMAC_PRIORITY_HIGH 2
#define DMAC_PRIORITY_LOW 3
int pxa_dmac_alloc(int, struct dmac_channel **, int);
void pxa_dmac_release(struct dmac_channel *);
int pxa_dmac_transfer(struct dmac_channel *, bus_addr_t);
int pxa_dmac_transfer_single(struct dmac_channel *,
bus_addr_t, bus_addr_t, uint32_t);
int pxa_dmac_transfer_done(struct dmac_channel *);
int pxa_dmac_transfer_failed(struct dmac_channel *);
enum pxa_device_ivars {
PXA_IVAR_BASE,
};
enum smi_device_ivars {
SMI_IVAR_PHYSBASE,
};
#define PXA_ACCESSOR(var, ivar, type) \
__BUS_ACCESSOR(pxa, var, PXA, ivar, type)
PXA_ACCESSOR(base, BASE, u_long)
#undef PXA_ACCESSOR
#define SMI_ACCESSOR(var, ivar, type) \
__BUS_ACCESSOR(smi, var, SMI, ivar, type)
SMI_ACCESSOR(physbase, PHYSBASE, bus_addr_t)
#undef CSR_ACCESSOR
#endif /* _PXAVAR_H_ */

View File

@ -0,0 +1,9 @@
# XScale PXA generic configuration
# $FreeBSD$
files "../xscale/pxa/files.pxa"
include "../xscale/std.xscale"
makeoptions KERNPHYSADDR=0xa0200000
makeoptions KERNVIRTADDR=0xc0200000
makeoptions CONF_CFLAGS=-mcpu=xscale
options XSCALE_CACHE_READ_WRITE_ALLOCATE
machine arm

View File

@ -0,0 +1,105 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2006 Benno Rice. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <machine/bus.h>
#include <sys/rman.h>
#include <machine/resource.h>
#include <dev/pci/pcivar.h>
#include <dev/uart/uart.h>
#include <dev/uart/uart_bus.h>
#include <dev/uart/uart_cpu.h>
#include <dev/ic/ns16550.h>
#include <arm/xscale/pxa/pxavar.h>
#include <arm/xscale/pxa/pxareg.h>
#include "uart_if.h"
#define PXA_UART_UUE 0x40 /* UART Unit Enable */
static int uart_pxa_probe(device_t dev);
static device_method_t uart_pxa_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, uart_pxa_probe),
DEVMETHOD(device_attach, uart_bus_attach),
DEVMETHOD(device_detach, uart_bus_detach),
{ 0, 0 }
};
static driver_t uart_pxa_driver = {
uart_driver_name,
uart_pxa_methods,
sizeof(struct uart_softc),
};
static int
uart_pxa_probe(device_t dev)
{
bus_space_handle_t base;
struct uart_softc *sc;
base = (bus_space_handle_t)pxa_get_base(dev);
#ifdef QEMU_WORKAROUNDS
/*
* QEMU really exposes only the first uart unless
* you specify several of them in the configuration.
* Otherwise all the rest of UARTs stay unconnected,
* which causes problems in the ns16550 attach routine.
* Unfortunately, even if you provide qemu with 4 uarts
* on the command line, it has a bug where it segfaults
* trying to enable bluetooth on the HWUART. So we just
* allow the FFUART to be attached.
* Also, don't check the UUE (UART Unit Enable) bit, as
* the gumstix bootloader doesn't set it.
*/
if (base != PXA2X0_FFUART_BASE)
return (ENXIO);
#else
/* Check to see if the enable bit's on. */
if ((bus_space_read_4(obio_tag, base,
(REG_IER << 2)) & PXA_UART_UUE) == 0)
return (ENXIO);
#endif
sc = device_get_softc(dev);
sc->sc_class = &uart_ns8250_class;
return(uart_bus_probe(dev, 2, 0, PXA2X0_COM_FREQ, 0, 0));
}
DRIVER_MODULE(uart, pxa, uart_pxa_driver, uart_devclass, 0, 0);

View File

@ -0,0 +1,71 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2003 Marcel Moolenaar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/cons.h>
#include <machine/bus.h>
#include <dev/uart/uart.h>
#include <dev/uart/uart_cpu.h>
#include <arm/xscale/pxa/pxavar.h>
#include <arm/xscale/pxa/pxareg.h>
bus_space_tag_t uart_bus_space_io;
bus_space_tag_t uart_bus_space_mem;
int
uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2)
{
return (b1->bsh == b2->bsh ? 1 : 0);
}
int
uart_cpu_getdev(int devtype, struct uart_devinfo *di)
{
di->ops = uart_getops(&uart_ns8250_class);
di->bas.chan = 0;
di->bas.bst = obio_tag;
di->bas.regshft = 2;
di->bas.rclk = PXA2X0_COM_FREQ;
di->baudrate = 115200;
di->databits = 8;
di->stopbits = 1;
di->parity = UART_PARITY_NONE;
uart_bus_space_mem = obio_tag;
uart_bus_space_io = NULL;
di->bas.bsh = PXA2X0_FFUART_BASE;
return (0);
}

View File

@ -0,0 +1,3 @@
# $FreeBSD$
options ARM_CACHE_LOCK_ENABLE
options NO_EVENTTIMERS

View File

@ -73,8 +73,9 @@ SYSTEM_LD_TAIL +=;sed s/" + SIZEOF_HEADERS"// ldscript.$M\
rm ${FULLKERNEL}.noheader
FILES_CPU_FUNC = \
$S/$M/$M/cpufunc_asm_arm9.S $S/$M/$M/cpufunc_asm.S \
$S/$M/$M/cpufunc_asm_armv5_ec.S \
$S/$M/$M/cpufunc_asm_arm9.S \
$S/$M/$M/cpufunc_asm_xscale.S $S/$M/$M/cpufunc_asm.S \
$S/$M/$M/cpufunc_asm_xscale_c3.S $S/$M/$M/cpufunc_asm_armv5_ec.S \
$S/$M/$M/cpufunc_asm_fa526.S $S/$M/$M/cpufunc_asm_sheeva.S
.if ${MACHINE_ARCH:Marmv[67]*} == "" && defined(KERNPHYSADDR)

View File

@ -32,12 +32,14 @@ arm/arm/cpufunc.c standard
arm/arm/cpufunc_asm.S standard
arm/arm/cpufunc_asm_arm9.S optional cpu_arm9 | cpu_arm9e
arm/arm/cpufunc_asm_arm11x6.S optional cpu_arm1176
arm/arm/cpufunc_asm_armv4.S optional cpu_arm9 | cpu_arm9e | cpu_fa526
arm/arm/cpufunc_asm_armv4.S optional cpu_arm9 | cpu_arm9e | cpu_fa526 | cpu_xscale_pxa2x0 | cpu_xscale_81342
arm/arm/cpufunc_asm_armv5_ec.S optional cpu_arm9e
arm/arm/cpufunc_asm_armv7.S optional cpu_cortexa | cpu_krait | cpu_mv_pj4b
arm/arm/cpufunc_asm_fa526.S optional cpu_fa526
arm/arm/cpufunc_asm_pj4b.S optional cpu_mv_pj4b
arm/arm/cpufunc_asm_sheeva.S optional cpu_arm9e
arm/arm/cpufunc_asm_xscale.S optional cpu_xscale_pxa2x0 | cpu_xscale_81342
arm/arm/cpufunc_asm_xscale_c3.S optional cpu_xscale_81342
arm/arm/cpuinfo.c standard
arm/arm/cpu_asm-v6.S optional armv7 | armv6
arm/arm/db_disasm.c optional ddb

View File

@ -16,6 +16,8 @@ CPU_CORTEXA opt_global.h
CPU_KRAIT opt_global.h
CPU_FA526 opt_global.h
CPU_MV_PJ4B opt_global.h
CPU_XSCALE_81342 opt_global.h
CPU_XSCALE_PXA2X0 opt_global.h
SMP_ON_UP opt_global.h # Runtime detection of MP extensions
DEV_GIC opt_global.h
DEV_PMU opt_global.h
@ -64,6 +66,8 @@ SOC_OMAP4 opt_global.h
SOC_ROCKCHIP_RK3188 opt_global.h
SOC_TI_AM335X opt_global.h
SOC_TEGRA2 opt_global.h
XSCALE_CACHE_READ_WRITE_ALLOCATE opt_global.h
XSACLE_DISABLE_CCNT opt_timer.h
VERBOSE_INIT_ARM opt_global.h
VM_MAXUSER_ADDRESS opt_global.h
GFB_DEBUG opt_gfb.h

View File

@ -0,0 +1,72 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2009 Rui Paulo <rpaulo@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef _DEV_HWPMC_XSCALE_H_
#define _DEV_HWPMC_XSCALE_H_
#define XSCALE_PMC_CAPS (PMC_CAP_INTERRUPT | PMC_CAP_USER | \
PMC_CAP_SYSTEM | PMC_CAP_EDGE | \
PMC_CAP_THRESHOLD | PMC_CAP_READ | \
PMC_CAP_WRITE | PMC_CAP_INVERT | \
PMC_CAP_QUALIFIER)
#define XSCALE_PMNC_ENABLE 0x01 /* Enable all Counters */
#define XSCALE_PMNC_PMNRESET 0x02 /* Performance Counter Reset */
#define XSCALE_PMNC_CCNTRESET 0x04 /* Clock Counter Reset */
#define XSCALE_PMNC_CCNTDIV 0x08 /* Clock Counter Divider */
#define XSCALE_INTEN_CCNT 0x01 /* Enable Clock Counter Int. */
#define XSCALE_INTEN_PMN0 0x02 /* Enable PMN0 Interrupts */
#define XSCALE_INTEN_PMN1 0x04 /* Enable PMN1 Interrupts */
#define XSCALE_INTEN_PMN2 0x08 /* Enable PMN2 Interrupts */
#define XSCALE_INTEN_PMN3 0x10 /* Enable PMN3 Interrupts */
#define XSCALE_EVTSEL_EVT0_MASK 0x000000ff
#define XSCALE_EVTSEL_EVT1_MASK 0x0000ff00
#define XSCALE_EVTSEL_EVT2_MASK 0x00ff0000
#define XSCALE_EVTSEL_EVT3_MASK 0xff000000
#define XSCALE_FLAG_CCNT_OVERFLOW 0x01
#define XSCALE_FLAG_PMN0_OVERFLOW 0x02
#define XSCALE_FLAG_PMN1_OVERFLOW 0x04
#define XSCALE_FLAG_PMN2_OVERFLOW 0x08
#define XSCALE_FLAG_PMN3_OVERFLOW 0x10
#define XSCALE_RELOAD_COUNT_TO_PERFCTR_VALUE(R) (-(R))
#define XSCALE_PERFCTR_VALUE_TO_RELOAD_COUNT(P) (-(P))
#ifdef _KERNEL
/* MD extension for 'struct pmc' */
struct pmc_md_xscale_pmc {
uint32_t pm_xscale_evsel;
};
#endif /* _KERNEL */
#endif /* _DEV_HWPMC_XSCALE_H_ */

View File

@ -227,6 +227,52 @@ __PMC_EV_ALIAS("unhalted-core-cycles", IAP_ARCH_UNH_COR_CYC)
__PMC_EV(UCP, EVENT_0CH_08H_M) \
__PMC_EV(UCP, EVENT_0CH_08H_S) \
/*
* Intel XScale events from:
*
* Intel XScale Core Developer's Manual
* January, 2004, #27347302
*
* 3rd Generation Intel XScale Microarchitecture
* Developer's Manual
* May 2007, #31628302
*
* First 14 events are for 1st and 2nd Generation Intel XScale cores. The
* remaining are available only on 3rd Generation Intel XScale cores.
*/
#define __PMC_EV_XSCALE() \
__PMC_EV(XSCALE, IC_FETCH) \
__PMC_EV(XSCALE, IC_MISS) \
__PMC_EV(XSCALE, DATA_DEPENDENCY_STALLED) \
__PMC_EV(XSCALE, ITLB_MISS) \
__PMC_EV(XSCALE, DTLB_MISS) \
__PMC_EV(XSCALE, BRANCH_RETIRED) \
__PMC_EV(XSCALE, BRANCH_MISPRED) \
__PMC_EV(XSCALE, INSTR_RETIRED) \
__PMC_EV(XSCALE, DC_FULL_CYCLE) \
__PMC_EV(XSCALE, DC_FULL_CONTIG) \
__PMC_EV(XSCALE, DC_ACCESS) \
__PMC_EV(XSCALE, DC_MISS) \
__PMC_EV(XSCALE, DC_WRITEBACK) \
__PMC_EV(XSCALE, PC_CHANGE) \
__PMC_EV(XSCALE, BRANCH_RETIRED_ALL) \
__PMC_EV(XSCALE, INSTR_CYCLE) \
__PMC_EV(XSCALE, CP_STALL) \
__PMC_EV(XSCALE, PC_CHANGE_ALL) \
__PMC_EV(XSCALE, PIPELINE_FLUSH) \
__PMC_EV(XSCALE, BACKEND_STALL) \
__PMC_EV(XSCALE, MULTIPLIER_USE) \
__PMC_EV(XSCALE, MULTIPLIER_STALLED) \
__PMC_EV(XSCALE, DATA_CACHE_STALLED) \
__PMC_EV(XSCALE, L2_CACHE_REQ) \
__PMC_EV(XSCALE, L2_CACHE_MISS) \
__PMC_EV(XSCALE, ADDRESS_BUS_TRANS) \
__PMC_EV(XSCALE, SELF_ADDRESS_BUS_TRANS) \
__PMC_EV(XSCALE, DATA_BUS_TRANS)
#define PMC_EV_XSCALE_FIRST PMC_EV_XSCALE_IC_FETCH
#define PMC_EV_XSCALE_LAST PMC_EV_XSCALE_DATA_BUS_TRANS
/*
* ARMv7 Events
*/
@ -1724,6 +1770,7 @@ __PMC_EV_ALIAS("unhalted-core-cycles", IAP_ARCH_UNH_COR_CYC)
* 0x11000 0x0080 INTEL Pentium 4 events
* 0x11080 0x0080 INTEL Pentium MMX events
* 0x11100 0x0100 INTEL Pentium Pro/P-II/P-III/Pentium-M events
* 0x11200 0x00FF INTEL XScale events
* 0x11300 0x00FF MIPS 24K events
* 0x11400 0x00FF Octeon events
* 0x11500 0x00FF MIPS 74K events
@ -1743,6 +1790,8 @@ __PMC_EV_ALIAS("unhalted-core-cycles", IAP_ARCH_UNH_COR_CYC)
__PMC_EV_K7() \
__PMC_EV_BLOCK(K8, 0x2080) \
__PMC_EV_K8() \
__PMC_EV_BLOCK(XSCALE, 0x11200) \
__PMC_EV_XSCALE() \
__PMC_EV_BLOCK(MIPS24K, 0x11300) \
__PMC_EV_MIPS24K() \
__PMC_EV_BLOCK(OCTEON, 0x11400) \

View File

@ -110,6 +110,7 @@ extern char pmc_cpuid[PMC_CPUID_LEN];
__PMC_CPU(INTEL_BROADWELL_XEON, 0x97, "Intel Broadwell Xeon") \
__PMC_CPU(INTEL_SKYLAKE, 0x98, "Intel Skylake") \
__PMC_CPU(INTEL_SKYLAKE_XEON, 0x99, "Intel Skylake Xeon") \
__PMC_CPU(INTEL_XSCALE, 0x100, "Intel XScale") \
__PMC_CPU(MIPS_24K, 0x200, "MIPS 24K") \
__PMC_CPU(MIPS_OCTEON, 0x201, "Cavium Octeon") \
__PMC_CPU(MIPS_74K, 0x202, "MIPS 74K") \
@ -150,6 +151,7 @@ enum pmc_cputype {
__PMC_CLASS(IAP, 0x07, "Intel Core...Atom, programmable") \
__PMC_CLASS(UCF, 0x08, "Intel Uncore fixed function") \
__PMC_CLASS(UCP, 0x09, "Intel Uncore programmable") \
__PMC_CLASS(XSCALE, 0x0A, "Intel XScale counters") \
__PMC_CLASS(MIPS24K, 0x0B, "MIPS 24K") \
__PMC_CLASS(OCTEON, 0x0C, "Cavium Octeon") \
__PMC_CLASS(PPC7450, 0x0D, "Motorola MPC7450 class") \