Merge ^/head r356848 through r356919.
This commit is contained in:
commit
53d2936cd3
@ -1,7 +1,7 @@
|
||||
# $FreeBSD$
|
||||
|
||||
freebsd_instance:
|
||||
image: freebsd-12-0-release-amd64
|
||||
image: freebsd-12-1-release-amd64
|
||||
cpu: 8
|
||||
memory: 24G
|
||||
|
||||
@ -14,5 +14,7 @@ task:
|
||||
- pkg install -y qemu-devel uefi-edk2-qemu-x86_64
|
||||
script:
|
||||
- make -j$(sysctl -n hw.ncpu) WITHOUT_TOOLCHAIN=yes buildworld buildkernel
|
||||
package_script:
|
||||
- make WITHOUT_TOOLCHAIN=yes PKG_FORMAT=tar packages
|
||||
test_script:
|
||||
- sh tools/boot/ci-qemu-test.sh
|
||||
|
@ -1853,6 +1853,7 @@ PORTSDIR?= /usr/ports
|
||||
WSTAGEDIR?= ${OBJTOP}/worldstage
|
||||
KSTAGEDIR?= ${OBJTOP}/kernelstage
|
||||
REPODIR?= ${OBJROOT}repo
|
||||
PKG_FORMAT?= txz
|
||||
PKGSIGNKEY?= # empty
|
||||
|
||||
.ORDER: stage-packages create-packages
|
||||
@ -1925,6 +1926,10 @@ create-world-packages: _pkgbootstrap .PHONY
|
||||
.include "${WSTAGEDIR}/packages.mk"
|
||||
.endif
|
||||
|
||||
.if make(create-world-packages-jobs) || make(create-kernel-packages*)
|
||||
PKG_ABI!=${PKG_CMD} -o ABI_FILE=${WSTAGEDIR}/usr/bin/uname config ABI
|
||||
.endif
|
||||
|
||||
create-world-packages-jobs: .PHONY
|
||||
.for pkgname in ${_PKGS}
|
||||
create-world-packages-jobs: create-world-package-${pkgname}
|
||||
@ -1939,10 +1944,10 @@ create-world-package-${pkgname}: .PHONY
|
||||
sed -i '' -e "s/%VCS_REVISION%/${VCS_REVISION}/" ${WSTAGEDIR}/${pkgname}.ucl ; \
|
||||
fi
|
||||
${PKG_CMD} -o ABI_FILE=${WSTAGEDIR}/usr/bin/uname -o ALLOW_BASE_SHLIBS=yes \
|
||||
create -M ${WSTAGEDIR}/${pkgname}.ucl \
|
||||
create -f ${PKG_FORMAT} -M ${WSTAGEDIR}/${pkgname}.ucl \
|
||||
-p ${WSTAGEDIR}/${pkgname}.plist \
|
||||
-r ${WSTAGEDIR} \
|
||||
-o ${REPODIR}/$$(${PKG_CMD} -o ABI_FILE=${WSTAGEDIR}/usr/bin/uname config ABI)/${PKG_VERSION}
|
||||
-o ${REPODIR}/${PKG_ABI}/${PKG_VERSION}
|
||||
.endfor
|
||||
|
||||
_default_flavor= -default
|
||||
@ -1971,10 +1976,11 @@ create-kernel-packages-flavor${flavor:C,^""$,${_default_flavor},}: _pkgbootstrap
|
||||
/version/ {print $$2; next } ' \
|
||||
${KSTAGEDIR}/${DISTDIR}/kernel.${INSTALLKERNEL}${flavor}.ucl ; \
|
||||
${PKG_CMD} -o ABI_FILE=${WSTAGEDIR}/usr/bin/uname -o ALLOW_BASE_SHLIBS=yes \
|
||||
create -M ${KSTAGEDIR}/${DISTDIR}/kernel.${INSTALLKERNEL}${flavor}.ucl \
|
||||
create -f ${PKG_FORMAT} \
|
||||
-M ${KSTAGEDIR}/${DISTDIR}/kernel.${INSTALLKERNEL}${flavor}.ucl \
|
||||
-p ${KSTAGEDIR}/${DISTDIR}/kernel.${INSTALLKERNEL}${flavor}.plist \
|
||||
-r ${KSTAGEDIR}/${DISTDIR} \
|
||||
-o ${REPODIR}/$$(${PKG_CMD} -o ABI_FILE=${WSTAGEDIR}/usr/bin/uname config ABI)/${PKG_VERSION}
|
||||
-o ${REPODIR}/${PKG_ABI}/${PKG_VERSION}
|
||||
. endfor
|
||||
.endif
|
||||
.if ${BUILDKERNELS:[#]} > 1 && ${NO_INSTALLEXTRAKERNELS} != "yes"
|
||||
@ -2003,19 +2009,22 @@ create-kernel-packages-extra-flavor${flavor:C,^""$,${_default_flavor},}-${_kerne
|
||||
/version/ {print $$2; next } ' \
|
||||
${KSTAGEDIR}/kernel.${_kernel}/kernel.${_kernel}${flavor}.ucl ; \
|
||||
${PKG_CMD} -o ABI_FILE=${WSTAGEDIR}/usr/bin/uname -o ALLOW_BASE_SHLIBS=yes \
|
||||
create -M ${KSTAGEDIR}/kernel.${_kernel}/kernel.${_kernel}${flavor}.ucl \
|
||||
create -f ${PKG_FORMAT} \
|
||||
-M ${KSTAGEDIR}/kernel.${_kernel}/kernel.${_kernel}${flavor}.ucl \
|
||||
-p ${KSTAGEDIR}/kernel.${_kernel}/kernel.${_kernel}${flavor}.plist \
|
||||
-r ${KSTAGEDIR}/kernel.${_kernel} \
|
||||
-o ${REPODIR}/$$(${PKG_CMD} -o ABI_FILE=${WSTAGEDIR}/usr/bin/uname config ABI)/${PKG_VERSION}
|
||||
-o ${REPODIR}/${PKG_ABI}/${PKG_VERSION}
|
||||
. endfor
|
||||
. endif
|
||||
. endfor
|
||||
.endif
|
||||
|
||||
sign-packages: _pkgbootstrap .PHONY
|
||||
printf "version = 2;\npacking_format = \"${PKG_FORMAT}\";\n" > ${WSTAGEDIR}/meta
|
||||
@[ -L "${REPODIR}/$$(${PKG_CMD} -o ABI_FILE=${WSTAGEDIR}/usr/bin/uname config ABI)/latest" ] && \
|
||||
unlink ${REPODIR}/$$(${PKG_CMD} -o ABI_FILE=${WSTAGEDIR}/usr/bin/uname config ABI)/latest ; \
|
||||
${PKG_CMD} -o ABI_FILE=${WSTAGEDIR}/usr/bin/uname repo \
|
||||
-m ${WSTAGEDIR}/meta \
|
||||
-o ${REPODIR}/$$(${PKG_CMD} -o ABI_FILE=${WSTAGEDIR}/usr/bin/uname config ABI)/${PKG_VERSION} \
|
||||
${REPODIR}/$$(${PKG_CMD} -o ABI_FILE=${WSTAGEDIR}/usr/bin/uname config ABI)/${PKG_VERSION} \
|
||||
${PKGSIGNKEY} ; \
|
||||
|
@ -769,6 +769,7 @@ extern ulong_t get_system_hostid(void);
|
||||
extern boolean_t is_mounted(libzfs_handle_t *, const char *special, char **);
|
||||
extern boolean_t zfs_is_mounted(zfs_handle_t *, char **);
|
||||
extern int zfs_mount(zfs_handle_t *, const char *, int);
|
||||
extern int zfs_mount_at(zfs_handle_t *, const char *, int, const char *);
|
||||
extern int zfs_unmount(zfs_handle_t *, const char *, int);
|
||||
extern int zfs_unmountall(zfs_handle_t *, int);
|
||||
|
||||
|
@ -301,6 +301,17 @@ zfs_is_mounted(zfs_handle_t *zhp, char **where)
|
||||
return (is_mounted(zhp->zfs_hdl, zfs_get_name(zhp), where));
|
||||
}
|
||||
|
||||
static boolean_t
|
||||
zfs_is_mountable_internal(zfs_handle_t *zhp, const char *mountpoint)
|
||||
{
|
||||
|
||||
if (zfs_prop_get_int(zhp, ZFS_PROP_ZONED) &&
|
||||
getzoneid() == GLOBAL_ZONEID)
|
||||
return (B_FALSE);
|
||||
|
||||
return (B_TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns true if the given dataset is mountable, false otherwise. Returns the
|
||||
* mountpoint in 'buf'.
|
||||
@ -325,8 +336,7 @@ zfs_is_mountable(zfs_handle_t *zhp, char *buf, size_t buflen,
|
||||
if (zfs_prop_get_int(zhp, ZFS_PROP_CANMOUNT) == ZFS_CANMOUNT_OFF)
|
||||
return (B_FALSE);
|
||||
|
||||
if (zfs_prop_get_int(zhp, ZFS_PROP_ZONED) &&
|
||||
getzoneid() == GLOBAL_ZONEID)
|
||||
if (!zfs_is_mountable_internal(zhp, buf))
|
||||
return (B_FALSE);
|
||||
|
||||
if (source)
|
||||
@ -341,8 +351,19 @@ zfs_is_mountable(zfs_handle_t *zhp, char *buf, size_t buflen,
|
||||
int
|
||||
zfs_mount(zfs_handle_t *zhp, const char *options, int flags)
|
||||
{
|
||||
struct stat buf;
|
||||
char mountpoint[ZFS_MAXPROPLEN];
|
||||
|
||||
if (!zfs_is_mountable(zhp, mountpoint, sizeof (mountpoint), NULL))
|
||||
return (0);
|
||||
|
||||
return (zfs_mount_at(zhp, options, flags, mountpoint));
|
||||
}
|
||||
|
||||
int
|
||||
zfs_mount_at(zfs_handle_t *zhp, const char *options, int flags,
|
||||
const char *mountpoint)
|
||||
{
|
||||
struct stat buf;
|
||||
char mntopts[MNT_LINE_MAX];
|
||||
libzfs_handle_t *hdl = zhp->zfs_hdl;
|
||||
|
||||
@ -357,8 +378,8 @@ zfs_mount(zfs_handle_t *zhp, const char *options, int flags)
|
||||
if (zpool_get_prop_int(zhp->zpool_hdl, ZPOOL_PROP_READONLY, NULL))
|
||||
flags |= MS_RDONLY;
|
||||
|
||||
if (!zfs_is_mountable(zhp, mountpoint, sizeof (mountpoint), NULL))
|
||||
return (0);
|
||||
if (!zfs_is_mountable_internal(zhp, mountpoint))
|
||||
return (B_FALSE);
|
||||
|
||||
/* Create the directory if it doesn't already exist */
|
||||
if (lstat(mountpoint, &buf) != 0) {
|
||||
|
@ -8,9 +8,15 @@ SUBDIR= libiberty \
|
||||
|
||||
SUBDIR.${MK_BINUTILS}+= doc
|
||||
SUBDIR.${MK_BINUTILS}+= libbinutils
|
||||
SUBDIR.${MK_BINUTILS}+= as
|
||||
SUBDIR.${MK_BINUTILS}+= objdump
|
||||
|
||||
# GNU as is used on x86 only, for a few files that cannot be assembled by
|
||||
# Clang IAS. Other archs either use Clang IAS for every assembly file, or
|
||||
# use external toolchain.
|
||||
.if ${TARGET} == "amd64" || ${TARGET} == "i386"
|
||||
SUBDIR.${MK_BINUTILS}+= as
|
||||
.endif
|
||||
|
||||
# All archs except powerpc either use lld or require external toolchain.
|
||||
# powerpc still needs binutils ld to link 32-bit binaries.
|
||||
.if ${TARGET} == "powerpc"
|
||||
|
@ -324,6 +324,11 @@ extern char *suboptarg; /* getsubopt(3) external variable */
|
||||
|
||||
#if __EXT1_VISIBLE
|
||||
|
||||
#ifndef _RSIZE_T_DEFINED
|
||||
#define _RSIZE_T_DEFINED
|
||||
typedef size_t rsize_t;
|
||||
#endif
|
||||
|
||||
#ifndef _ERRNO_T_DEFINED
|
||||
#define _ERRNO_T_DEFINED
|
||||
typedef int errno_t;
|
||||
@ -339,6 +344,9 @@ _Noreturn void abort_handler_s(const char * __restrict, void * __restrict,
|
||||
errno_t);
|
||||
/* K3.6.1.3 */
|
||||
void ignore_handler_s(const char * __restrict, void * __restrict, errno_t);
|
||||
/* K.3.6.3.2 */
|
||||
errno_t qsort_s(void *, rsize_t, rsize_t,
|
||||
int (*)(const void *, const void *, void *), void *);
|
||||
#endif /* __EXT1_VISIBLE */
|
||||
|
||||
__END_DECLS
|
||||
|
@ -82,7 +82,6 @@ be_mount_iter(zfs_handle_t *zfs_hdl, void *data)
|
||||
char *mountpoint;
|
||||
char tmp[BE_MAXPATHLEN], zfs_mnt[BE_MAXPATHLEN];
|
||||
struct be_mount_info *info;
|
||||
char opt;
|
||||
|
||||
info = (struct be_mount_info *)data;
|
||||
|
||||
@ -121,9 +120,7 @@ be_mount_iter(zfs_handle_t *zfs_hdl, void *data)
|
||||
mountpoint);
|
||||
}
|
||||
|
||||
opt = '\0';
|
||||
if ((err = zmount(zfs_get_name(zfs_hdl), tmp, info->mntflags,
|
||||
__DECONST(char *, MNTTYPE_ZFS), NULL, 0, &opt, 1)) != 0) {
|
||||
if ((err = zfs_mount_at(zfs_hdl, NULL, info->mntflags, tmp)) != 0) {
|
||||
switch (errno) {
|
||||
case ENAMETOOLONG:
|
||||
return (set_error(info->lbh, BE_ERR_PATHLEN));
|
||||
|
@ -11,8 +11,8 @@ MISRCS+=C99_Exit.c a64l.c abort.c abs.c atexit.c atof.c atoi.c atol.c atoll.c \
|
||||
getsubopt.c hcreate.c hcreate_r.c hdestroy_r.c heapsort.c heapsort_b.c \
|
||||
hsearch_r.c imaxabs.c imaxdiv.c \
|
||||
insque.c l64a.c labs.c ldiv.c llabs.c lldiv.c lsearch.c \
|
||||
merge.c mergesort_b.c ptsname.c qsort.c qsort_r.c quick_exit.c \
|
||||
radixsort.c rand.c \
|
||||
merge.c mergesort_b.c ptsname.c qsort.c qsort_r.c qsort_s.c \
|
||||
quick_exit.c radixsort.c rand.c \
|
||||
random.c reallocarray.c reallocf.c realpath.c remque.c \
|
||||
set_constraint_handler_s.c strfmon.c strtoimax.c \
|
||||
strtol.c strtold.c strtoll.c strtoq.c strtoul.c strtonum.c strtoull.c \
|
||||
@ -51,7 +51,8 @@ MLINKS+=hcreate.3 hcreate_r.3 hcreate.3 hdestroy_r.3 hcreate.3 hsearch_r.3
|
||||
MLINKS+=insque.3 remque.3
|
||||
MLINKS+=lsearch.3 lfind.3
|
||||
MLINKS+=ptsname.3 grantpt.3 ptsname.3 unlockpt.3
|
||||
MLINKS+=qsort.3 heapsort.3 qsort.3 mergesort.3 qsort.3 qsort_r.3
|
||||
MLINKS+=qsort.3 heapsort.3 qsort.3 mergesort.3 qsort.3 qsort_r.3 \
|
||||
qsort.3 qsort_s.3
|
||||
MLINKS+=rand.3 rand_r.3 rand.3 srand.3
|
||||
MLINKS+=random.3 initstate.3 random.3 setstate.3 random.3 srandom.3 \
|
||||
random.3 srandomdev.3
|
||||
|
@ -123,6 +123,10 @@ FBSD_1.5 {
|
||||
set_constraint_handler_s;
|
||||
};
|
||||
|
||||
FBSD_1.6 {
|
||||
qsort_s;
|
||||
};
|
||||
|
||||
FBSDprivate_1.0 {
|
||||
__system;
|
||||
_system;
|
||||
|
@ -32,7 +32,7 @@
|
||||
.\" @(#)qsort.3 8.1 (Berkeley) 6/4/93
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd February 20, 2013
|
||||
.Dd January 14, 2020
|
||||
.Dt QSORT 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -98,6 +98,15 @@
|
||||
.Fa "size_t size"
|
||||
.Fa "int \*[lp]^compar\*[rp]\*[lp]const void *, const void *\*[rp]"
|
||||
.Fc
|
||||
.Fd #define __STDC_WANT_LIB_EXT1__ 1
|
||||
.Ft errno_t
|
||||
.Fo qsort_s
|
||||
.Fa "void *base"
|
||||
.Fa "rsize_t nmemb"
|
||||
.Fa "rsize_t size"
|
||||
.Fa "int \*[lp]*compar\*[rp]\*[lp]const void *, const void *, void *\*[rp]"
|
||||
.Fa "void *thunk"
|
||||
.Fc
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Fn qsort
|
||||
@ -238,6 +247,36 @@ is faster than
|
||||
.Fn heapsort .
|
||||
Memory availability and pre-existing order in the data can make this
|
||||
untrue.
|
||||
.Pp
|
||||
The
|
||||
.Fn qsort_s
|
||||
function behaves the same as
|
||||
.Fn qsort_r , except that:
|
||||
.Bl -dash
|
||||
.It
|
||||
The order of arguments is different
|
||||
.It
|
||||
The order of arguments to
|
||||
.Fa compar
|
||||
is different
|
||||
.It
|
||||
if
|
||||
.Fa nmemb
|
||||
or
|
||||
.Fa size
|
||||
are greater than
|
||||
.Dv RSIZE_MAX ,
|
||||
or
|
||||
.Fa nmemb
|
||||
is not zero and
|
||||
.Fa compar
|
||||
is NULL, then the runtime-constraint handler is called, and
|
||||
.Fn qsort_s
|
||||
returns an error.
|
||||
Note that the handler is called before
|
||||
.Fn qsort_s
|
||||
returns the error, and the handler function might not return.
|
||||
.El
|
||||
.Sh RETURN VALUES
|
||||
The
|
||||
.Fn qsort
|
||||
@ -245,6 +284,9 @@ and
|
||||
.Fn qsort_r
|
||||
functions
|
||||
return no value.
|
||||
The
|
||||
.Fn qsort_s
|
||||
function returns zero on success, non-zero on error.
|
||||
.Pp
|
||||
.Rv -std heapsort mergesort
|
||||
.Sh EXAMPLES
|
||||
@ -288,6 +330,19 @@ main(void)
|
||||
}
|
||||
.Ed
|
||||
.Sh COMPATIBILITY
|
||||
The order of arguments for the comparison function used with
|
||||
.Fn qsort_r
|
||||
is different from the one used by
|
||||
.Fn qsort_s ,
|
||||
and the GNU libc implementation of
|
||||
.Fn qsort_r .
|
||||
When porting software written for GNU libc, it is usually possible
|
||||
to replace
|
||||
.Fn qsort_r
|
||||
with
|
||||
.Fn qsort_s
|
||||
to work around this problem.
|
||||
.Pp
|
||||
Previous versions of
|
||||
.Fn qsort
|
||||
did not permit the comparison routine itself to call
|
||||
@ -366,6 +421,10 @@ The
|
||||
function
|
||||
conforms to
|
||||
.St -isoC .
|
||||
.Fn qsort_s
|
||||
conforms to
|
||||
.St -isoC-2011
|
||||
K.3.6.3.2.
|
||||
.Sh HISTORY
|
||||
The variants of these functions that take blocks as arguments first appeared in
|
||||
Mac OS X.
|
||||
|
@ -35,10 +35,16 @@ static char sccsid[] = "@(#)qsort.c 8.1 (Berkeley) 6/4/93";
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "libc_private.h"
|
||||
|
||||
#ifdef I_AM_QSORT_R
|
||||
#if defined(I_AM_QSORT_R)
|
||||
typedef int cmp_t(void *, const void *, const void *);
|
||||
#elif defined(I_AM_QSORT_S)
|
||||
typedef int cmp_t(const void *, const void *, void *);
|
||||
#else
|
||||
typedef int cmp_t(const void *, const void *);
|
||||
#endif
|
||||
@ -65,15 +71,17 @@ swapfunc(char *a, char *b, size_t es)
|
||||
#define vecswap(a, b, n) \
|
||||
if ((n) > 0) swapfunc(a, b, n)
|
||||
|
||||
#ifdef I_AM_QSORT_R
|
||||
#if defined(I_AM_QSORT_R)
|
||||
#define CMP(t, x, y) (cmp((t), (x), (y)))
|
||||
#elif defined(I_AM_QSORT_S)
|
||||
#define CMP(t, x, y) (cmp((x), (y), (t)))
|
||||
#else
|
||||
#define CMP(t, x, y) (cmp((x), (y)))
|
||||
#endif
|
||||
|
||||
static inline char *
|
||||
med3(char *a, char *b, char *c, cmp_t *cmp, void *thunk
|
||||
#ifndef I_AM_QSORT_R
|
||||
#if !defined(I_AM_QSORT_R) && !defined(I_AM_QSORT_S)
|
||||
__unused
|
||||
#endif
|
||||
)
|
||||
@ -83,9 +91,12 @@ __unused
|
||||
:(CMP(thunk, b, c) > 0 ? b : (CMP(thunk, a, c) < 0 ? a : c ));
|
||||
}
|
||||
|
||||
#ifdef I_AM_QSORT_R
|
||||
#if defined(I_AM_QSORT_R)
|
||||
void
|
||||
qsort_r(void *a, size_t n, size_t es, void *thunk, cmp_t *cmp)
|
||||
#elif defined(I_AM_QSORT_S)
|
||||
errno_t
|
||||
qsort_s(void *a, rsize_t n, rsize_t es, cmp_t *cmp, void *thunk)
|
||||
#else
|
||||
#define thunk NULL
|
||||
void
|
||||
@ -97,6 +108,24 @@ qsort(void *a, size_t n, size_t es, cmp_t *cmp)
|
||||
int cmp_result;
|
||||
int swap_cnt;
|
||||
|
||||
#ifdef I_AM_QSORT_S
|
||||
if (n > RSIZE_MAX) {
|
||||
__throw_constraint_handler_s("qsort_s : n > RSIZE_MAX", EINVAL);
|
||||
return (EINVAL);
|
||||
} else if (es > RSIZE_MAX) {
|
||||
__throw_constraint_handler_s("qsort_s : es > RSIZE_MAX", EINVAL);
|
||||
return (EINVAL);
|
||||
} else if (n != 0) {
|
||||
if (a == NULL) {
|
||||
__throw_constraint_handler_s("qsort_s : a == NULL", EINVAL);
|
||||
return (EINVAL);
|
||||
} else if (cmp == NULL) {
|
||||
__throw_constraint_handler_s("qsort_s : cmp == NULL", EINVAL);
|
||||
return (EINVAL);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
loop:
|
||||
swap_cnt = 0;
|
||||
if (n < 7) {
|
||||
@ -105,7 +134,11 @@ loop:
|
||||
pl > (char *)a && CMP(thunk, pl - es, pl) > 0;
|
||||
pl -= es)
|
||||
swapfunc(pl, pl - es, es);
|
||||
#ifdef I_AM_QSORT_S
|
||||
return (0);
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
pm = (char *)a + (n / 2) * es;
|
||||
if (n > 7) {
|
||||
@ -154,7 +187,11 @@ loop:
|
||||
pl > (char *)a && CMP(thunk, pl - es, pl) > 0;
|
||||
pl -= es)
|
||||
swapfunc(pl, pl - es, es);
|
||||
#ifdef I_AM_QSORT_S
|
||||
return (0);
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
pn = (char *)a + n * es;
|
||||
@ -168,8 +205,10 @@ loop:
|
||||
if (d1 <= d2) {
|
||||
/* Recurse on left partition, then iterate on right partition */
|
||||
if (d1 > es) {
|
||||
#ifdef I_AM_QSORT_R
|
||||
#if defined(I_AM_QSORT_R)
|
||||
qsort_r(a, d1 / es, es, thunk, cmp);
|
||||
#elif defined(I_AM_QSORT_S)
|
||||
qsort_s(a, d1 / es, es, cmp, thunk);
|
||||
#else
|
||||
qsort(a, d1 / es, es, cmp);
|
||||
#endif
|
||||
@ -184,8 +223,10 @@ loop:
|
||||
} else {
|
||||
/* Recurse on right partition, then iterate on left partition */
|
||||
if (d2 > es) {
|
||||
#ifdef I_AM_QSORT_R
|
||||
#if defined(I_AM_QSORT_R)
|
||||
qsort_r(pn - d2, d2 / es, es, thunk, cmp);
|
||||
#elif defined(I_AM_QSORT_S)
|
||||
qsort_s(pn - d2, d2 / es, es, cmp, thunk);
|
||||
#else
|
||||
qsort(pn - d2, d2 / es, es, cmp);
|
||||
#endif
|
||||
@ -197,4 +238,8 @@ loop:
|
||||
goto loop;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef I_AM_QSORT_S
|
||||
return (0);
|
||||
#endif
|
||||
}
|
||||
|
8
lib/libc/stdlib/qsort_s.c
Normal file
8
lib/libc/stdlib/qsort_s.c
Normal file
@ -0,0 +1,8 @@
|
||||
/*
|
||||
* This file is in the public domain. Originally written by Garrett
|
||||
* A. Wollman.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
#define I_AM_QSORT_S
|
||||
#include "qsort.c"
|
@ -6,6 +6,8 @@ ATF_TESTS_C+= dynthr_test
|
||||
ATF_TESTS_C+= heapsort_test
|
||||
ATF_TESTS_C+= mergesort_test
|
||||
ATF_TESTS_C+= qsort_test
|
||||
ATF_TESTS_C+= qsort_r_test
|
||||
ATF_TESTS_C+= qsort_s_test
|
||||
ATF_TESTS_C+= set_constraint_handler_s_test
|
||||
ATF_TESTS_C+= strfmon_test
|
||||
ATF_TESTS_C+= tsearch_test
|
||||
|
92
lib/libc/tests/stdlib/qsort_r_test.c
Normal file
92
lib/libc/tests/stdlib/qsort_r_test.c
Normal file
@ -0,0 +1,92 @@
|
||||
/*-
|
||||
* Copyright (C) 2020 Edward Tomasz Napierala <trasz@FreeBSD.org>
|
||||
* Copyright (C) 2004 Maxim Sobolev <sobomax@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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Test for qsort_r(3) routine.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "test-sort.h"
|
||||
|
||||
#define THUNK 42
|
||||
|
||||
static int
|
||||
sorthelp_r(void *thunk, const void *a, const void *b)
|
||||
{
|
||||
const int *oa, *ob;
|
||||
|
||||
ATF_REQUIRE_EQ(*(int *)thunk, THUNK);
|
||||
|
||||
oa = a;
|
||||
ob = b;
|
||||
/* Don't use "return *oa - *ob" since it's easy to cause overflow! */
|
||||
if (*oa > *ob)
|
||||
return (1);
|
||||
if (*oa < *ob)
|
||||
return (-1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
ATF_TC_WITHOUT_HEAD(qsort_r_test);
|
||||
ATF_TC_BODY(qsort_r_test, tc)
|
||||
{
|
||||
int testvector[IVEC_LEN];
|
||||
int sresvector[IVEC_LEN];
|
||||
int i, j;
|
||||
int thunk = THUNK;
|
||||
|
||||
for (j = 2; j < IVEC_LEN; j++) {
|
||||
/* Populate test vectors */
|
||||
for (i = 0; i < j; i++)
|
||||
testvector[i] = sresvector[i] = initvector[i];
|
||||
|
||||
/* Sort using qsort_r(3) */
|
||||
qsort_r(testvector, j, sizeof(testvector[0]), &thunk,
|
||||
sorthelp_r);
|
||||
/* Sort using reference slow sorting routine */
|
||||
ssort(sresvector, j);
|
||||
|
||||
/* Compare results */
|
||||
for (i = 0; i < j; i++)
|
||||
ATF_CHECK_MSG(testvector[i] == sresvector[i],
|
||||
"item at index %d didn't match: %d != %d",
|
||||
i, testvector[i], sresvector[i]);
|
||||
}
|
||||
}
|
||||
|
||||
ATF_TP_ADD_TCS(tp)
|
||||
{
|
||||
|
||||
ATF_TP_ADD_TC(tp, qsort_r_test);
|
||||
|
||||
return (atf_no_error());
|
||||
}
|
257
lib/libc/tests/stdlib/qsort_s_test.c
Normal file
257
lib/libc/tests/stdlib/qsort_s_test.c
Normal file
@ -0,0 +1,257 @@
|
||||
/*-
|
||||
* Copyright (C) 2020 Edward Tomasz Napierala <trasz@FreeBSD.org>
|
||||
* Copyright (c) 2017 Juniper Networks. All rights reserved.
|
||||
* Copyright (C) 2004 Maxim Sobolev <sobomax@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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Test for qsort_s(3) routine.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define THUNK 42
|
||||
|
||||
#include "test-sort.h"
|
||||
|
||||
static errno_t e;
|
||||
|
||||
static int
|
||||
sorthelp_s(const void *a, const void *b, void *thunk)
|
||||
{
|
||||
const int *oa, *ob;
|
||||
|
||||
ATF_REQUIRE_EQ(*(int *)thunk, THUNK);
|
||||
|
||||
oa = a;
|
||||
ob = b;
|
||||
/* Don't use "return *oa - *ob" since it's easy to cause overflow! */
|
||||
if (*oa > *ob)
|
||||
return (1);
|
||||
if (*oa < *ob)
|
||||
return (-1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
h(const char * restrict msg __unused, void * restrict ptr __unused, errno_t error)
|
||||
{
|
||||
e = error;
|
||||
}
|
||||
|
||||
/* nmemb < 0 */
|
||||
ATF_TC_WITHOUT_HEAD(qsort_s_nmemb_lt_zero);
|
||||
ATF_TC_BODY(qsort_s_nmemb_lt_zero, tc)
|
||||
{
|
||||
int thunk = THUNK;
|
||||
int b;
|
||||
|
||||
ATF_CHECK(qsort_s(&b, -1, sizeof(int), sorthelp_s, &thunk) != 0);
|
||||
}
|
||||
|
||||
/* nmemb > rmax */
|
||||
ATF_TC_WITHOUT_HEAD(qsort_s_nmemb_gt_rmax);
|
||||
ATF_TC_BODY(qsort_s_nmemb_gt_rmax, tc)
|
||||
{
|
||||
int thunk = THUNK;
|
||||
int b;
|
||||
|
||||
ATF_CHECK(qsort_s(&b, RSIZE_MAX + 1, sizeof(int), sorthelp_s, &thunk) != 0);
|
||||
}
|
||||
|
||||
/* size < 0 */
|
||||
ATF_TC_WITHOUT_HEAD(qsort_s_size_lt_zero);
|
||||
ATF_TC_BODY(qsort_s_size_lt_zero, tc)
|
||||
{
|
||||
int thunk = THUNK;
|
||||
int b;
|
||||
|
||||
ATF_CHECK(qsort_s(&b, 1, -1, sorthelp_s, &thunk) != 0);
|
||||
}
|
||||
|
||||
/* size > rmax */
|
||||
ATF_TC_WITHOUT_HEAD(qsort_s_size_gt_rmax);
|
||||
ATF_TC_BODY(qsort_s_size_gt_rmax, tc)
|
||||
{
|
||||
int thunk = THUNK;
|
||||
int b;
|
||||
|
||||
ATF_CHECK(qsort_s(&b, 1, RSIZE_MAX + 1, sorthelp_s, &thunk) != 0);
|
||||
}
|
||||
|
||||
/* NULL compar */
|
||||
ATF_TC_WITHOUT_HEAD(qsort_s_null_compar);
|
||||
ATF_TC_BODY(qsort_s_null_compar, tc)
|
||||
{
|
||||
int thunk = THUNK;
|
||||
int b;
|
||||
|
||||
ATF_CHECK(qsort_s(&b, 1, sizeof(int), NULL, &thunk) != 0);
|
||||
}
|
||||
|
||||
/* nmemb < 0, handler */
|
||||
ATF_TC_WITHOUT_HEAD(qsort_s_nmemb_lt_zero_h);
|
||||
ATF_TC_BODY(qsort_s_nmemb_lt_zero_h, tc)
|
||||
{
|
||||
int thunk = THUNK;
|
||||
int b[] = {81, 4, 7};
|
||||
|
||||
e = 0;
|
||||
set_constraint_handler_s(h);
|
||||
ATF_CHECK(qsort_s(&b, -1, sizeof(int), sorthelp_s, &thunk) != 0);
|
||||
ATF_CHECK(e > 0);
|
||||
ATF_CHECK_EQ(b[0], 81);
|
||||
ATF_CHECK_EQ(b[1], 4);
|
||||
ATF_CHECK_EQ(b[2], 7);
|
||||
}
|
||||
|
||||
/* nmemb > rmax, handler */
|
||||
ATF_TC_WITHOUT_HEAD(qsort_s_nmemb_gt_rmax_h);
|
||||
ATF_TC_BODY(qsort_s_nmemb_gt_rmax_h, tc)
|
||||
{
|
||||
int thunk = THUNK;
|
||||
int b[] = {81, 4, 7};
|
||||
|
||||
e = 0;
|
||||
set_constraint_handler_s(h);
|
||||
ATF_CHECK(qsort_s(&b, RSIZE_MAX + 1, sizeof(int), sorthelp_s, &thunk) != 0);
|
||||
ATF_CHECK(e > 0);
|
||||
ATF_CHECK_EQ(b[0], 81);
|
||||
ATF_CHECK_EQ(b[1], 4);
|
||||
ATF_CHECK_EQ(b[2], 7);
|
||||
}
|
||||
|
||||
/* size < 0, handler */
|
||||
ATF_TC_WITHOUT_HEAD(qsort_s_size_lt_zero_h);
|
||||
ATF_TC_BODY(qsort_s_size_lt_zero_h, tc)
|
||||
{
|
||||
int thunk = THUNK;
|
||||
int b[] = {81, 4, 7};
|
||||
|
||||
e = 0;
|
||||
set_constraint_handler_s(h);
|
||||
ATF_CHECK(qsort_s(&b, nitems(b), -1, sorthelp_s, &thunk) != 0);
|
||||
ATF_CHECK(e > 0);
|
||||
ATF_CHECK_EQ(b[0], 81);
|
||||
ATF_CHECK_EQ(b[1], 4);
|
||||
ATF_CHECK_EQ(b[2], 7);
|
||||
}
|
||||
|
||||
/* size > rmax, handler */
|
||||
ATF_TC_WITHOUT_HEAD(qsort_s_size_gt_rmax_h);
|
||||
ATF_TC_BODY(qsort_s_size_gt_rmax_h, tc)
|
||||
{
|
||||
int thunk = THUNK;
|
||||
int b[] = {81, 4, 7};
|
||||
|
||||
e = 0;
|
||||
set_constraint_handler_s(h);
|
||||
ATF_CHECK(qsort_s(&b, nitems(b), RSIZE_MAX + 1, sorthelp_s, &thunk) != 0);
|
||||
ATF_CHECK(e > 0);
|
||||
ATF_CHECK_EQ(b[0], 81);
|
||||
ATF_CHECK_EQ(b[1], 4);
|
||||
ATF_CHECK_EQ(b[2], 7);
|
||||
}
|
||||
|
||||
/* NULL compar, handler */
|
||||
ATF_TC_WITHOUT_HEAD(qsort_s_null_compar_h);
|
||||
ATF_TC_BODY(qsort_s_null_compar_h, tc)
|
||||
{
|
||||
int thunk = THUNK;
|
||||
int b[] = {81, 4, 7};
|
||||
|
||||
e = 0;
|
||||
set_constraint_handler_s(h);
|
||||
ATF_CHECK(qsort_s(&b, nitems(b), sizeof(int), NULL, &thunk) != 0);
|
||||
ATF_CHECK(e > 0);
|
||||
ATF_CHECK_EQ(b[0], 81);
|
||||
ATF_CHECK_EQ(b[1], 4);
|
||||
ATF_CHECK_EQ(b[2], 7);
|
||||
}
|
||||
|
||||
ATF_TC_WITHOUT_HEAD(qsort_s_h);
|
||||
ATF_TC_BODY(qsort_s_h, tc)
|
||||
{
|
||||
int thunk = THUNK;
|
||||
int b[] = {81, 4, 7};
|
||||
|
||||
e = 0;
|
||||
set_constraint_handler_s(h);
|
||||
ATF_CHECK(qsort_s(&b, nitems(b), sizeof(int), sorthelp_s, &thunk) == 0);
|
||||
ATF_CHECK(e == 0);
|
||||
ATF_CHECK_EQ(b[0], 4);
|
||||
ATF_CHECK_EQ(b[1], 7);
|
||||
ATF_CHECK_EQ(b[2], 81);
|
||||
}
|
||||
|
||||
ATF_TC_WITHOUT_HEAD(qsort_s_test);
|
||||
ATF_TC_BODY(qsort_s_test, tc)
|
||||
{
|
||||
int testvector[IVEC_LEN];
|
||||
int sresvector[IVEC_LEN];
|
||||
int i, j;
|
||||
int thunk = THUNK;
|
||||
|
||||
for (j = 2; j < IVEC_LEN; j++) {
|
||||
/* Populate test vectors */
|
||||
for (i = 0; i < j; i++)
|
||||
testvector[i] = sresvector[i] = initvector[i];
|
||||
|
||||
/* Sort using qsort_s(3) */
|
||||
qsort_s(testvector, j, sizeof(testvector[0]),
|
||||
sorthelp_s, &thunk);
|
||||
/* Sort using reference slow sorting routine */
|
||||
ssort(sresvector, j);
|
||||
|
||||
/* Compare results */
|
||||
for (i = 0; i < j; i++)
|
||||
ATF_CHECK_MSG(testvector[i] == sresvector[i],
|
||||
"item at index %d didn't match: %d != %d",
|
||||
i, testvector[i], sresvector[i]);
|
||||
}
|
||||
}
|
||||
|
||||
ATF_TP_ADD_TCS(tp)
|
||||
{
|
||||
ATF_TP_ADD_TC(tp, qsort_s_nmemb_lt_zero);
|
||||
ATF_TP_ADD_TC(tp, qsort_s_nmemb_gt_rmax);
|
||||
ATF_TP_ADD_TC(tp, qsort_s_size_lt_zero);
|
||||
ATF_TP_ADD_TC(tp, qsort_s_size_gt_rmax);
|
||||
ATF_TP_ADD_TC(tp, qsort_s_null_compar);
|
||||
ATF_TP_ADD_TC(tp, qsort_s_nmemb_lt_zero_h);
|
||||
ATF_TP_ADD_TC(tp, qsort_s_nmemb_gt_rmax_h);
|
||||
ATF_TP_ADD_TC(tp, qsort_s_size_lt_zero_h);
|
||||
ATF_TP_ADD_TC(tp, qsort_s_size_gt_rmax_h);
|
||||
ATF_TP_ADD_TC(tp, qsort_s_null_compar_h);
|
||||
ATF_TP_ADD_TC(tp, qsort_s_h);
|
||||
ATF_TP_ADD_TC(tp, qsort_s_test);
|
||||
|
||||
return (atf_no_error());
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
.\" DO NOT EDIT-- this file is @generated by tools/build/options/makeman.
|
||||
.\" $FreeBSD$
|
||||
.Dd January 17, 2020
|
||||
.Dd January 19, 2020
|
||||
.Dt SRC.CONF 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -185,37 +185,32 @@ Do not build or install GNU
|
||||
.Xr objdump 1
|
||||
as part
|
||||
of the normal system build.
|
||||
The resulting system cannot build programs from source.
|
||||
.Pp
|
||||
This is a default setting on
|
||||
arm64/aarch64, riscv/riscv64 and riscv/riscv64sf.
|
||||
.It Va WITH_BINUTILS
|
||||
Set to build and install GNU
|
||||
.Xr as 1 ,
|
||||
Build and install GNU
|
||||
.Xr as 1
|
||||
on i386 and amd64,
|
||||
.Xr objdump 1 ,
|
||||
and, on powerpc,
|
||||
and
|
||||
.Xr ld.bfd 1
|
||||
as part
|
||||
of the normal system build.
|
||||
on powerpc as part of the normal system build.
|
||||
.Pp
|
||||
This is a default setting on
|
||||
amd64/amd64, arm/armv6, arm/armv7, i386/i386, mips/mipsel, mips/mips, mips/mips64el, mips/mips64, mips/mipsn32, mips/mipselhf, mips/mipshf, mips/mips64elhf, mips/mips64hf, powerpc/powerpc, powerpc/powerpc64 and sparc64/sparc64.
|
||||
.It Va WITHOUT_BINUTILS_BOOTSTRAP
|
||||
Do not build binutils (as, ld.bfd, and objdump)
|
||||
as part of the bootstrap process.
|
||||
.Bf -symbolic
|
||||
The option does not work for build targets unless some alternative
|
||||
toolchain is provided.
|
||||
.Ef
|
||||
.Pp
|
||||
This is a default setting on
|
||||
arm64/aarch64, mips/mipsel, mips/mips, mips/mips64el, mips/mips64, mips/mipsn32, mips/mipselhf, mips/mipshf, mips/mips64elhf, mips/mips64hf, riscv/riscv64, riscv/riscv64sf and sparc64/sparc64.
|
||||
arm/armv6, arm/armv7, arm64/aarch64, mips/mipsel, mips/mips, mips/mips64el, mips/mips64, mips/mipsn32, mips/mipselhf, mips/mipshf, mips/mips64elhf, mips/mips64hf, riscv/riscv64, riscv/riscv64sf and sparc64/sparc64.
|
||||
.It Va WITH_BINUTILS_BOOTSTRAP
|
||||
Set build binutils (as, objdump, and on powerpc ld)
|
||||
Build binutils (as on i386 and amd64, objdump, and ld on powerpc)
|
||||
as part of the bootstrap process.
|
||||
.Pp
|
||||
This is a default setting on
|
||||
amd64/amd64, arm/armv6, arm/armv7, i386/i386, powerpc/powerpc and powerpc/powerpc64.
|
||||
amd64/amd64, i386/i386, powerpc/powerpc and powerpc/powerpc64.
|
||||
.It Va WITHOUT_BLACKLIST
|
||||
Set this if you do not want to build
|
||||
.Xr blacklistd 8
|
||||
|
@ -28,7 +28,7 @@
|
||||
.\" @(#)hier.7 8.1 (Berkeley) 6/5/93
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd September 10, 2019
|
||||
.Dd January 20, 2020
|
||||
.Dt HIER 7
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -420,12 +420,6 @@ for
|
||||
.Pa /usr
|
||||
should be used.
|
||||
Exceptions are the
|
||||
.Pa man
|
||||
directory
|
||||
.Po directly under
|
||||
.Pa local/
|
||||
rather than under
|
||||
.Pa local/share/ Ns Pc ,
|
||||
ports documentation
|
||||
.Po in
|
||||
.Pa share/doc/<port>/ Ns Pc ,
|
||||
|
@ -112,6 +112,7 @@ bcr -> bhd
|
||||
bcr -> sevan
|
||||
bcr -> dexter
|
||||
bcr -> sg
|
||||
bcr -> carlavilla
|
||||
|
||||
blackend -> ale
|
||||
|
||||
|
@ -63,7 +63,6 @@ __DEFAULT_YES_OPTIONS = \
|
||||
AUTOFS \
|
||||
BHYVE \
|
||||
BINUTILS \
|
||||
BINUTILS_BOOTSTRAP \
|
||||
BLACKLIST \
|
||||
BLUETOOTH \
|
||||
BOOT \
|
||||
@ -314,6 +313,11 @@ __DEFAULT_NO_OPTIONS+=CLANG CLANG_BOOTSTRAP CLANG_IS_CC LLD
|
||||
.if ${__T} == "aarch64" || ${__T:Mriscv*} != ""
|
||||
BROKEN_OPTIONS+=BINUTILS BINUTILS_BOOTSTRAP GCC GCC_BOOTSTRAP GDB
|
||||
.endif
|
||||
.if ${__T} == "amd64" || ${__T} == "i386" || ${__T:Mpowerpc*}
|
||||
__DEFAULT_YES_OPTIONS+=BINUTILS_BOOTSTRAP
|
||||
.else
|
||||
__DEFAULT_NO_OPTIONS+=BINUTILS_BOOTSTRAP
|
||||
.endif
|
||||
.if ${__T:Mriscv*} != ""
|
||||
BROKEN_OPTIONS+=OFED
|
||||
.endif
|
||||
|
@ -38,10 +38,11 @@ _start:
|
||||
lis %r11, uboot_address@ha
|
||||
addi %r11, %r11, uboot_address@l
|
||||
stw %r1, 0(%r11)
|
||||
/* Save U-Boot's r14 */
|
||||
/* Save U-Boot's r14 and r30 */
|
||||
lis %r11, saved_regs@ha
|
||||
addi %r11, %r11, saved_regs@l
|
||||
stw %r14, 0(%r11)
|
||||
stw %r30, 4(%r11)
|
||||
/* Disable interrupts */
|
||||
mfmsr %r11
|
||||
andi. %r11, %r11, ~0x8000@l
|
||||
@ -52,14 +53,16 @@ _start:
|
||||
* syscall()
|
||||
*/
|
||||
ENTRY(syscall)
|
||||
stwu %r1, -16(%r1)
|
||||
stwu %r1, -32(%r1)
|
||||
mflr %r0
|
||||
stw %r14, 8(%r1)
|
||||
stw %r0, 20(%r1)
|
||||
/* Restore U-Boot's r14 */
|
||||
stw %r30, 12(%r1)
|
||||
stw %r0, 36(%r1)
|
||||
/* Restore U-Boot's r14 and r30 */
|
||||
lis %r11, saved_regs@ha
|
||||
addi %r11, %r11, saved_regs@l
|
||||
lwz %r14, 0(%r11)
|
||||
lwz %r30, 4(%r11)
|
||||
/* Enable interrupts */
|
||||
mfmsr %r11
|
||||
ori %r11, %r11, 0x8000@l
|
||||
@ -79,6 +82,7 @@ ENTRY(syscall)
|
||||
lwz %r0, 4(%r11)
|
||||
mtlr %r0
|
||||
lwz %r14, 8(%r1)
|
||||
lwz %r30, 12(%r1)
|
||||
mr %r1, %r11
|
||||
blr
|
||||
|
||||
@ -90,5 +94,6 @@ GLOBAL(syscall_ptr)
|
||||
.long 0
|
||||
GLOBAL(saved_regs)
|
||||
.long 0 /* R14 */
|
||||
.long 0 /* R30 */
|
||||
GLOBAL(uboot_address)
|
||||
.long 0
|
||||
|
@ -2,27 +2,6 @@
|
||||
#
|
||||
# $FreeBSD$
|
||||
|
||||
# Don't use an OBJDIR
|
||||
.OBJDIR: ${.CURDIR}
|
||||
GENERATED_PREFIX= linux_
|
||||
|
||||
.include <src.lua.mk>
|
||||
|
||||
MAKESYSCALLS= ../../tools/makesyscalls.lua
|
||||
SRCS= syscalls.conf \
|
||||
syscalls.master
|
||||
GENERATED= linux_proto.h \
|
||||
linux_syscall.h \
|
||||
linux_syscalls.c \
|
||||
linux_sysent.c \
|
||||
linux_systrace_args.c
|
||||
|
||||
all:
|
||||
@echo "make sysent only"
|
||||
|
||||
# We .ORDER these explicitly so that we only run MAKESYSCALLS once, rather than
|
||||
# potentially once for each ${GENERATED} file.
|
||||
.ORDER: ${GENERATED}
|
||||
sysent: ${GENERATED}
|
||||
|
||||
${GENERATED}: ${MAKESYSCALLS} ${SRCS}
|
||||
${LUA} ${MAKESYSCALLS} syscalls.master syscalls.conf
|
||||
.include "../../conf/sysent.mk"
|
||||
|
@ -2,27 +2,6 @@
|
||||
#
|
||||
# $FreeBSD$
|
||||
|
||||
# Don't use an OBJDIR
|
||||
.OBJDIR: ${.CURDIR}
|
||||
GENERATED_PREFIX= linux32_
|
||||
|
||||
.include <src.lua.mk>
|
||||
|
||||
MAKESYSCALLS= ../../tools/makesyscalls.lua
|
||||
SRCS= syscalls.conf \
|
||||
syscalls.master
|
||||
GENERATED= linux32_proto.h \
|
||||
linux32_syscall.h \
|
||||
linux32_syscalls.c \
|
||||
linux32_sysent.c \
|
||||
linux32_systrace_args.c
|
||||
|
||||
all:
|
||||
@echo "make sysent only"
|
||||
|
||||
# We .ORDER these explicitly so that we only run MAKESYSCALLS once, rather than
|
||||
# potentially once for each ${GENERATED} file.
|
||||
.ORDER: ${GENERATED}
|
||||
sysent: ${GENERATED}
|
||||
|
||||
${GENERATED}: ${MAKESYSCALLS} ${SRCS}
|
||||
${LUA} ${MAKESYSCALLS} syscalls.master syscalls.conf
|
||||
.include "../../conf/sysent.mk"
|
||||
|
@ -169,28 +169,28 @@ const static struct allwinner_pins a10_pins[] = {
|
||||
{"PG10", 6, 10, {"gpio_in", "gpio_out", "ts1", "csi1", "uart4", "csi0", NULL, NULL}},
|
||||
{"PG11", 6, 11, {"gpio_in", "gpio_out", "ts1", "csi1", "uart4", "csi0", NULL, NULL}},
|
||||
|
||||
{"PH0", 7, 0, {"gpio_in", "gpio_out", "lcd1", "pata", "uart3", NULL, "eint0", "csi1"}, 6, 0},
|
||||
{"PH1", 7, 1, {"gpio_in", "gpio_out", "lcd1", "pata", "uart3", NULL, "eint1", "csi1"}, 6, 1},
|
||||
{"PH2", 7, 2, {"gpio_in", "gpio_out", "lcd1", "pata", "uart3", NULL, "eint2", "csi1"}, 6, 2},
|
||||
{"PH3", 7, 3, {"gpio_in", "gpio_out", "lcd1", "pata", "uart3", NULL, "eint3", "csi1"}, 6, 3},
|
||||
{"PH4", 7, 4, {"gpio_in", "gpio_out", "lcd1", "pata", "uart4", NULL, "eint4", "csi1"}, 6, 4},
|
||||
{"PH5", 7, 5, {"gpio_in", "gpio_out", "lcd1", "pata", "uart4", NULL, "eint5", "csi1"}, 6, 5},
|
||||
{"PH6", 7, 6, {"gpio_in", "gpio_out", "lcd1", "pata", "uart5", "ms", "eint6", "csi1"}, 6, 6},
|
||||
{"PH7", 7, 7, {"gpio_in", "gpio_out", "lcd1", "pata", "uart5", "ms", "eint7", "csi1"}, 6, 7},
|
||||
{"PH8", 7, 8, {"gpio_in", "gpio_out", "lcd1", "pata", "keypad", "ms", "eint8", "csi1"}, 6, 8},
|
||||
{"PH9", 7, 9, {"gpio_in", "gpio_out", "lcd1", "pata", "keypad", "ms", "eint9", "csi1"}, 6, 9},
|
||||
{"PH10", 7, 10, {"gpio_in", "gpio_out", "lcd1", "pata", "keypad", "ms", "eint10", "csi1"}, 6, 10},
|
||||
{"PH11", 7, 11, {"gpio_in", "gpio_out", "lcd1", "pata", "keypad", "ms", "eint11", "csi1"}, 6, 11},
|
||||
{"PH12", 7, 12, {"gpio_in", "gpio_out", "lcd1", "pata", "ps2", NULL, "eint12", "csi1"}, 6, 12},
|
||||
{"PH13", 7, 13, {"gpio_in", "gpio_out", "lcd1", "pata", "ps2", "sim", "eint13", "csi1"}, 6, 13},
|
||||
{"PH14", 7, 14, {"gpio_in", "gpio_out", "lcd1", "pata", "keypad", "sim", "eint14", "csi1"}, 6, 14},
|
||||
{"PH15", 7, 15, {"gpio_in", "gpio_out", "lcd1", "pata", "keypad", "sim", "eint15", "csi1"}, 6, 15},
|
||||
{"PH16", 7, 16, {"gpio_in", "gpio_out", "lcd1", "pata", "keypad", NULL, "eint16", "csi1"}, 6, 16},
|
||||
{"PH17", 7, 17, {"gpio_in", "gpio_out", "lcd1", "pata", "keypad", "sim", "eint17", "csi1"}, 6, 17},
|
||||
{"PH18", 7, 18, {"gpio_in", "gpio_out", "lcd1", "pata", "keypad", "sim", "eint18", "csi1"}, 6, 18},
|
||||
{"PH19", 7, 19, {"gpio_in", "gpio_out", "lcd1", "pata", "keypad", "sim", "eint19", "csi1"}, 6, 19},
|
||||
{"PH20", 7, 20, {"gpio_in", "gpio_out", "lcd1", "pata", "can", NULL, "eint20", "csi1"}, 6, 20},
|
||||
{"PH21", 7, 21, {"gpio_in", "gpio_out", "lcd1", "pata", "can", NULL, "eint21", "csi1"}, 6, 21},
|
||||
{"PH0", 7, 0, {"gpio_in", "gpio_out", "lcd1", "pata", "uart3", NULL, "ph_eint0", "csi1"}, 6, 0, 0},
|
||||
{"PH1", 7, 1, {"gpio_in", "gpio_out", "lcd1", "pata", "uart3", NULL, "ph_eint1", "csi1"}, 6, 1, 0},
|
||||
{"PH2", 7, 2, {"gpio_in", "gpio_out", "lcd1", "pata", "uart3", NULL, "ph_eint2", "csi1"}, 6, 2, 0},
|
||||
{"PH3", 7, 3, {"gpio_in", "gpio_out", "lcd1", "pata", "uart3", NULL, "ph_eint3", "csi1"}, 6, 3, 0},
|
||||
{"PH4", 7, 4, {"gpio_in", "gpio_out", "lcd1", "pata", "uart4", NULL, "ph_eint4", "csi1"}, 6, 4, 0},
|
||||
{"PH5", 7, 5, {"gpio_in", "gpio_out", "lcd1", "pata", "uart4", NULL, "ph_eint5", "csi1"}, 6, 5, 0},
|
||||
{"PH6", 7, 6, {"gpio_in", "gpio_out", "lcd1", "pata", "uart5", "ms", "ph_eint6", "csi1"}, 6, 6, 0},
|
||||
{"PH7", 7, 7, {"gpio_in", "gpio_out", "lcd1", "pata", "uart5", "ms", "ph_eint7", "csi1"}, 6, 7, 0},
|
||||
{"PH8", 7, 8, {"gpio_in", "gpio_out", "lcd1", "pata", "keypad", "ms", "ph_eint8", "csi1"}, 6, 8, 0},
|
||||
{"PH9", 7, 9, {"gpio_in", "gpio_out", "lcd1", "pata", "keypad", "ms", "ph_eint9", "csi1"}, 6, 9, 0},
|
||||
{"PH10", 7, 10, {"gpio_in", "gpio_out", "lcd1", "pata", "keypad", "ms", "ph_eint10", "csi1"}, 6, 10, 0},
|
||||
{"PH11", 7, 11, {"gpio_in", "gpio_out", "lcd1", "pata", "keypad", "ms", "ph_eint11", "csi1"}, 6, 11, 0},
|
||||
{"PH12", 7, 12, {"gpio_in", "gpio_out", "lcd1", "pata", "ps2", NULL, "ph_eint12", "csi1"}, 6, 12, 0},
|
||||
{"PH13", 7, 13, {"gpio_in", "gpio_out", "lcd1", "pata", "ps2", "sim", "ph_eint13", "csi1"}, 6, 13, 0},
|
||||
{"PH14", 7, 14, {"gpio_in", "gpio_out", "lcd1", "pata", "keypad", "sim", "ph_eint14", "csi1"}, 6, 14, 0},
|
||||
{"PH15", 7, 15, {"gpio_in", "gpio_out", "lcd1", "pata", "keypad", "sim", "ph_eint15", "csi1"}, 6, 15, 0},
|
||||
{"PH16", 7, 16, {"gpio_in", "gpio_out", "lcd1", "pata", "keypad", NULL, "ph_eint16", "csi1"}, 6, 16, 0},
|
||||
{"PH17", 7, 17, {"gpio_in", "gpio_out", "lcd1", "pata", "keypad", "sim", "ph_eint17", "csi1"}, 6, 17, 0},
|
||||
{"PH18", 7, 18, {"gpio_in", "gpio_out", "lcd1", "pata", "keypad", "sim", "ph_eint18", "csi1"}, 6, 18, 0},
|
||||
{"PH19", 7, 19, {"gpio_in", "gpio_out", "lcd1", "pata", "keypad", "sim", "ph_eint19", "csi1"}, 6, 19, 0},
|
||||
{"PH20", 7, 20, {"gpio_in", "gpio_out", "lcd1", "pata", "can", NULL, "ph_eint20", "csi1"}, 6, 20, 0},
|
||||
{"PH21", 7, 21, {"gpio_in", "gpio_out", "lcd1", "pata", "can", NULL, "ph_eint21", "csi1"}, 6, 21, 0},
|
||||
{"PH22", 7, 22, {"gpio_in", "gpio_out", "lcd1", "pata", "keypad", "mmc1", NULL, "csi1"}},
|
||||
{"PH23", 7, 23, {"gpio_in", "gpio_out", "lcd1", "pata", "keypad", "mmc1", NULL, "csi1"}},
|
||||
{"PH24", 7, 24, {"gpio_in", "gpio_out", "lcd1", "pata", "keypad", "mmc1", NULL, "csi1"}},
|
||||
@ -208,16 +208,16 @@ const static struct allwinner_pins a10_pins[] = {
|
||||
{"PI7", 8, 7, {"gpio_in", "gpio_out", "mmc3", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PI8", 8, 8, {"gpio_in", "gpio_out", "mmc3", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PI9", 8, 9, {"gpio_in", "gpio_out", "mmc3", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PI10", 8, 10, {"gpio_in", "gpio_out", "spi0", "uart5", NULL, NULL, "eint22", NULL}, 6, 22},
|
||||
{"PI11", 8, 11, {"gpio_in", "gpio_out", "spi0", "uart5", NULL, NULL, "eint23", NULL}, 6, 23},
|
||||
{"PI12", 8, 12, {"gpio_in", "gpio_out", "spi0", "uart6", NULL, NULL, "eint24", NULL}, 6, 24},
|
||||
{"PI13", 8, 13, {"gpio_in", "gpio_out", "spi0", "uart6", NULL, NULL, "eint25", NULL}, 6, 25},
|
||||
{"PI14", 8, 14, {"gpio_in", "gpio_out", "spi0", "ps2", "timer4", NULL, "eint26", NULL}, 6, 26},
|
||||
{"PI15", 8, 15, {"gpio_in", "gpio_out", "spi1", "ps2", "timer5", NULL, "eint27", NULL}, 6, 27},
|
||||
{"PI16", 8, 16, {"gpio_in", "gpio_out", "spi1", "uart2", NULL, NULL, "eint28", NULL}, 6, 28},
|
||||
{"PI17", 8, 17, {"gpio_in", "gpio_out", "spi1", "uart2", NULL, NULL, "eint29", NULL}, 6, 29},
|
||||
{"PI18", 8, 18, {"gpio_in", "gpio_out", "spi1", "uart2", NULL, NULL, "eint30", NULL}, 6, 30},
|
||||
{"PI19", 8, 19, {"gpio_in", "gpio_out", "spi1", "uart2", NULL, NULL, "eint31", NULL}, 6, 31},
|
||||
{"PI10", 8, 10, {"gpio_in", "gpio_out", "spi0", "uart5", NULL, NULL, "pi_eint22", NULL}, 6, 22, 0},
|
||||
{"PI11", 8, 11, {"gpio_in", "gpio_out", "spi0", "uart5", NULL, NULL, "pi_eint23", NULL}, 6, 23, 0},
|
||||
{"PI12", 8, 12, {"gpio_in", "gpio_out", "spi0", "uart6", NULL, NULL, "pi_eint24", NULL}, 6, 24, 0},
|
||||
{"PI13", 8, 13, {"gpio_in", "gpio_out", "spi0", "uart6", NULL, NULL, "pi_eint25", NULL}, 6, 25, 0},
|
||||
{"PI14", 8, 14, {"gpio_in", "gpio_out", "spi0", "ps2", "timer4", NULL, "pi_eint26", NULL}, 6, 26, 0},
|
||||
{"PI15", 8, 15, {"gpio_in", "gpio_out", "spi1", "ps2", "timer5", NULL, "pi_eint27", NULL}, 6, 27, 0},
|
||||
{"PI16", 8, 16, {"gpio_in", "gpio_out", "spi1", "uart2", NULL, NULL, "pi_eint28", NULL}, 6, 28, 0},
|
||||
{"PI17", 8, 17, {"gpio_in", "gpio_out", "spi1", "uart2", NULL, NULL, "pi_eint29", NULL}, 6, 29, 0},
|
||||
{"PI18", 8, 18, {"gpio_in", "gpio_out", "spi1", "uart2", NULL, NULL, "pi_eint30", NULL}, 6, 30, 0},
|
||||
{"PI19", 8, 19, {"gpio_in", "gpio_out", "spi1", "uart2", NULL, NULL, "pi_eint31", NULL}, 6, 31, 0},
|
||||
{"PI20", 8, 20, {"gpio_in", "gpio_out", "ps2", "uart7", "hdmi", NULL, NULL, NULL}},
|
||||
{"PI21", 8, 21, {"gpio_in", "gpio_out", "ps2", "uart7", "hdmi", NULL, NULL, NULL}},
|
||||
};
|
||||
|
@ -39,10 +39,10 @@ __FBSDID("$FreeBSD$");
|
||||
const static struct allwinner_pins a13_pins[] = {
|
||||
{"PB0", 1, 0, {"gpio_in", "gpio_out", "i2c0", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PB1", 1, 1, {"gpio_in", "gpio_out", "i2c0", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PB2", 1, 2, {"gpio_in", "gpio_out", "pwm", NULL, NULL, NULL, "eint16", NULL}, 6, 16},
|
||||
{"PB3", 1, 3, {"gpio_in", "gpio_out", "ir0", NULL, NULL, NULL, "eint17", NULL}, 6, 17},
|
||||
{"PB4", 1, 4, {"gpio_in", "gpio_out", "ir0", NULL, NULL, NULL, "eint18", NULL}, 6, 18},
|
||||
{"PB10", 1, 10, {"gpio_in", "gpio_out", "spi2", NULL, NULL, NULL, "eint24", NULL}, 6, 24},
|
||||
{"PB2", 1, 2, {"gpio_in", "gpio_out", "pwm", NULL, NULL, NULL, "pb_eint16", NULL}, 6, 16, 0},
|
||||
{"PB3", 1, 3, {"gpio_in", "gpio_out", "ir0", NULL, NULL, NULL, "pb_eint17", NULL}, 6, 17, 0},
|
||||
{"PB4", 1, 4, {"gpio_in", "gpio_out", "ir0", NULL, NULL, NULL, "pb_eint18", NULL}, 6, 18, 0},
|
||||
{"PB10", 1, 10, {"gpio_in", "gpio_out", "spi2", NULL, NULL, NULL, "pb_eint24", NULL}, 6, 24, 0},
|
||||
{"PB15", 1, 15, {"gpio_in", "gpio_out", "i2c1", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PB16", 1, 16, {"gpio_in", "gpio_out", "i2c1", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PB17", 1, 17, {"gpio_in", "gpio_out", "i2c2", NULL, NULL, NULL, NULL, NULL}},
|
||||
@ -89,8 +89,8 @@ const static struct allwinner_pins a13_pins[] = {
|
||||
{"PD26", 3, 26, {"gpio_in", "gpio_out", "lcd0", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PD27", 3, 27, {"gpio_in", "gpio_out", "lcd0", NULL, NULL, NULL, NULL, NULL}},
|
||||
|
||||
{"PE0", 4, 0, {"gpio_in", NULL, NULL, "csi0", "spi2", NULL, "eint14", NULL}, 6, 14},
|
||||
{"PE1", 4, 1, {"gpio_in", NULL, NULL, "csi0", "spi2", NULL, "eint15", NULL}, 6, 15},
|
||||
{"PE0", 4, 0, {"gpio_in", NULL, NULL, "csi0", "spi2", NULL, "pe_eint14", NULL}, 6, 14, 0},
|
||||
{"PE1", 4, 1, {"gpio_in", NULL, NULL, "csi0", "spi2", NULL, "pe_eint15", NULL}, 6, 15, 0},
|
||||
{"PE2", 4, 2, {"gpio_in", NULL, NULL, "csi0", "spi2", NULL, NULL, NULL}},
|
||||
{"PE3", 4, 3, {"gpio_in", "gpio_out", NULL, "csi0", "spi2", NULL, NULL, NULL}},
|
||||
{"PE4", 4, 4, {"gpio_in", "gpio_out", NULL, "csi0", "mmc2", NULL, NULL, NULL}},
|
||||
@ -109,15 +109,15 @@ const static struct allwinner_pins a13_pins[] = {
|
||||
{"PF4", 5, 4, {"gpio_in", "gpio_out", "mmc0", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PF5", 5, 5, {"gpio_in", "gpio_out", "mmc0", NULL, NULL, NULL, NULL, NULL}},
|
||||
|
||||
{"PG0", 6, 0, {"gpio_in", NULL, NULL, NULL, NULL, NULL, "eint0", NULL}, 6, 0},
|
||||
{"PG1", 6, 1, {"gpio_in", NULL, NULL, NULL, NULL, NULL, "eint1", NULL}, 6, 1},
|
||||
{"PG2", 6, 2, {"gpio_in", NULL, NULL, NULL, NULL, NULL, "eint2", NULL}, 6, 2},
|
||||
{"PG3", 6, 3, {"gpio_in", "gpio_out", "mmc1", NULL, "uart1", NULL, "eint3", NULL}, 6, 3},
|
||||
{"PG4", 6, 4, {"gpio_in", "gpio_out", "mmc1", NULL, "uart1", NULL, "eint4", NULL}, 6, 4},
|
||||
{"PG9", 6, 9, {"gpio_in", "gpio_out", "spi1", "uart3", NULL, NULL, "eint9", NULL}, 6, 9},
|
||||
{"PG10", 6, 10, {"gpio_in", "gpio_out", "spi1", "uart3", NULL, NULL, "eint10", NULL}, 6, 10},
|
||||
{"PG11", 6, 11, {"gpio_in", "gpio_out", "spi1", "uart3", NULL, NULL, "eint11", NULL}, 6, 11},
|
||||
{"PG12", 6, 12, {"gpio_in", "gpio_out", "spi1", "uart3", NULL, NULL, "eint12", NULL}, 6, 12},
|
||||
{"PG0", 6, 0, {"gpio_in", NULL, NULL, NULL, NULL, NULL, "pg_eint0", NULL}, 6, 0, 6},
|
||||
{"PG1", 6, 1, {"gpio_in", NULL, NULL, NULL, NULL, NULL, "pg_eint1", NULL}, 6, 1, 6},
|
||||
{"PG2", 6, 2, {"gpio_in", NULL, NULL, NULL, NULL, NULL, "pg_eint2", NULL}, 6, 2, 6},
|
||||
{"PG3", 6, 3, {"gpio_in", "gpio_out", "mmc1", NULL, "uart1", NULL, "pg_eint3", NULL}, 6, 3, 0},
|
||||
{"PG4", 6, 4, {"gpio_in", "gpio_out", "mmc1", NULL, "uart1", NULL, "pg_eint4", NULL}, 6, 4, 0},
|
||||
{"PG9", 6, 9, {"gpio_in", "gpio_out", "spi1", "uart3", NULL, NULL, "pg_eint9", NULL}, 6, 9, 0},
|
||||
{"PG10", 6, 10, {"gpio_in", "gpio_out", "spi1", "uart3", NULL, NULL, "pg_eint10", NULL}, 6, 10, 0},
|
||||
{"PG11", 6, 11, {"gpio_in", "gpio_out", "spi1", "uart3", NULL, NULL, "pg_eint11", NULL}, 6, 11, 0},
|
||||
{"PG12", 6, 12, {"gpio_in", "gpio_out", "spi1", "uart3", NULL, NULL, "pg_eint12", NULL}, 6, 12, 0},
|
||||
};
|
||||
|
||||
const struct allwinner_padconf a13_padconf = {
|
||||
|
@ -100,10 +100,10 @@ const static struct allwinner_pins a20_pins[] = {
|
||||
{"PC16", 2, 16, {"gpio_in", "gpio_out", "nand0", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PC17", 2, 17, {"gpio_in", "gpio_out", "nand0", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PC18", 2, 18, {"gpio_in", "gpio_out", "nand0", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PC19", 2, 19, {"gpio_in", "gpio_out", "nand0", "spi2", NULL, NULL, "eint12", NULL}, 6, 12},
|
||||
{"PC20", 2, 20, {"gpio_in", "gpio_out", "nand0", "spi2", NULL, NULL, "eint13", NULL}, 6, 13},
|
||||
{"PC21", 2, 21, {"gpio_in", "gpio_out", "nand0", "spi2", NULL, NULL, "eint14", NULL}, 6, 14},
|
||||
{"PC22", 2, 22, {"gpio_in", "gpio_out", "nand0", "spi2", NULL, NULL, "eint15", NULL}, 6, 15},
|
||||
{"PC19", 2, 19, {"gpio_in", "gpio_out", "nand0", "spi2", NULL, NULL, NULL, NULL}},
|
||||
{"PC20", 2, 20, {"gpio_in", "gpio_out", "nand0", "spi2", NULL, NULL, NULL, NULL}},
|
||||
{"PC21", 2, 21, {"gpio_in", "gpio_out", "nand0", "spi2", NULL, NULL, NULL, NULL}},
|
||||
{"PC22", 2, 22, {"gpio_in", "gpio_out", "nand0", "spi2", NULL, NULL, NULL, NULL}},
|
||||
{"PC23", 2, 23, {"gpio_in", "gpio_out", NULL, "spi0", NULL, NULL, NULL, NULL}},
|
||||
{"PC24", 2, 24, {"gpio_in", "gpio_out", "nand0", NULL, NULL, NULL, NULL, NULL}},
|
||||
|
||||
@ -169,28 +169,28 @@ const static struct allwinner_pins a20_pins[] = {
|
||||
{"PG10", 6, 10, {"gpio_in", "gpio_out", "ts1", "csi1", "uart4", "csi0", NULL, NULL}},
|
||||
{"PG11", 6, 11, {"gpio_in", "gpio_out", "ts1", "csi1", "uart4", "csi0", NULL, NULL}},
|
||||
|
||||
{"PH0", 7, 0, {"gpio_in", "gpio_out", "lcd1", NULL, "uart3", NULL, "eint0", "csi1"}, 6, 0},
|
||||
{"PH1", 7, 1, {"gpio_in", "gpio_out", "lcd1", NULL, "uart3", NULL, "eint1", "csi1"}, 6, 1},
|
||||
{"PH2", 7, 2, {"gpio_in", "gpio_out", "lcd1", NULL, "uart3", NULL, "eint2", "csi1"}, 6, 2},
|
||||
{"PH3", 7, 3, {"gpio_in", "gpio_out", "lcd1", NULL, "uart3", NULL, "eint3", "csi1"}, 6, 3},
|
||||
{"PH4", 7, 4, {"gpio_in", "gpio_out", "lcd1", NULL, "uart4", NULL, "eint4", "csi1"}, 6, 4},
|
||||
{"PH5", 7, 5, {"gpio_in", "gpio_out", "lcd1", NULL, "uart4", NULL, "eint5", "csi1"}, 6, 5},
|
||||
{"PH6", 7, 6, {"gpio_in", "gpio_out", "lcd1", NULL, "uart5", "ms", "eint6", "csi1"}, 6, 6},
|
||||
{"PH7", 7, 7, {"gpio_in", "gpio_out", "lcd1", NULL, "uart5", "ms", "eint7", "csi1"}, 6, 7},
|
||||
{"PH8", 7, 8, {"gpio_in", "gpio_out", "lcd1", NULL, "keypad", "ms", "eint8", "csi1"}, 6, 8},
|
||||
{"PH9", 7, 9, {"gpio_in", "gpio_out", "lcd1", NULL, "keypad", "ms", "eint9", "csi1"}, 6, 9},
|
||||
{"PH10", 7, 10, {"gpio_in", "gpio_out", "lcd1", NULL, "keypad", "ms", "eint10", "csi1"}, 6, 10},
|
||||
{"PH11", 7, 11, {"gpio_in", "gpio_out", "lcd1", NULL, "keypad", "ms", "eint11", "csi1"}, 6, 11},
|
||||
{"PH12", 7, 12, {"gpio_in", "gpio_out", "lcd1", NULL, "ps2", NULL, "eint12", "csi1"}, 6, 12},
|
||||
{"PH13", 7, 13, {"gpio_in", "gpio_out", "lcd1", NULL, "ps2", "sim", "eint13", "csi1"}, 6, 13},
|
||||
{"PH14", 7, 14, {"gpio_in", "gpio_out", "lcd1", NULL, "keypad", "sim", "eint14", "csi1"}, 6, 14},
|
||||
{"PH15", 7, 15, {"gpio_in", "gpio_out", "lcd1", NULL, "keypad", "sim", "eint15", "csi1"}, 6, 15},
|
||||
{"PH16", 7, 16, {"gpio_in", "gpio_out", "lcd1", NULL, "keypad", "sim", "eint16", "csi1"}, 6, 16},
|
||||
{"PH17", 7, 17, {"gpio_in", "gpio_out", "lcd1", NULL, "keypad", "sim", "eint17", "csi1"}, 6, 17},
|
||||
{"PH18", 7, 18, {"gpio_in", "gpio_out", "lcd1", NULL, "keypad", "sim", "eint18", "csi1"}, 6, 18},
|
||||
{"PH19", 7, 19, {"gpio_in", "gpio_out", "lcd1", NULL, "keypad", "sim", "eint19", "csi1"}, 6, 19},
|
||||
{"PH20", 7, 20, {"gpio_in", "gpio_out", "lcd1", NULL, "can", NULL, "eint20", "csi1"}, 6, 20},
|
||||
{"PH21", 7, 21, {"gpio_in", "gpio_out", "lcd1", NULL, "can", NULL, "eint21", "csi1"}, 6, 21},
|
||||
{"PH0", 7, 0, {"gpio_in", "gpio_out", "lcd1", NULL, "uart3", NULL, "ph_eint0", "csi1"}, 6, 0, 0},
|
||||
{"PH1", 7, 1, {"gpio_in", "gpio_out", "lcd1", NULL, "uart3", NULL, "ph_eint1", "csi1"}, 6, 1, 0},
|
||||
{"PH2", 7, 2, {"gpio_in", "gpio_out", "lcd1", NULL, "uart3", NULL, "ph_eint2", "csi1"}, 6, 2, 0},
|
||||
{"PH3", 7, 3, {"gpio_in", "gpio_out", "lcd1", NULL, "uart3", NULL, "ph_eint3", "csi1"}, 6, 3, 0},
|
||||
{"PH4", 7, 4, {"gpio_in", "gpio_out", "lcd1", NULL, "uart4", NULL, "ph_eint4", "csi1"}, 6, 4, 0},
|
||||
{"PH5", 7, 5, {"gpio_in", "gpio_out", "lcd1", NULL, "uart4", NULL, "ph_eint5", "csi1"}, 6, 5, 0},
|
||||
{"PH6", 7, 6, {"gpio_in", "gpio_out", "lcd1", NULL, "uart5", "ms", "ph_eint6", "csi1"}, 6, 6, 0},
|
||||
{"PH7", 7, 7, {"gpio_in", "gpio_out", "lcd1", NULL, "uart5", "ms", "ph_eint7", "csi1"}, 6, 7, 0},
|
||||
{"PH8", 7, 8, {"gpio_in", "gpio_out", "lcd1", NULL, "keypad", "ms", "ph_eint8", "csi1"}, 6, 8, 0},
|
||||
{"PH9", 7, 9, {"gpio_in", "gpio_out", "lcd1", NULL, "keypad", "ms", "ph_eint9", "csi1"}, 6, 9, 0},
|
||||
{"PH10", 7, 10, {"gpio_in", "gpio_out", "lcd1", NULL, "keypad", "ms", "ph_eint10", "csi1"}, 6, 10, 0},
|
||||
{"PH11", 7, 11, {"gpio_in", "gpio_out", "lcd1", NULL, "keypad", "ms", "ph_eint11", "csi1"}, 6, 11, 0},
|
||||
{"PH12", 7, 12, {"gpio_in", "gpio_out", "lcd1", NULL, "ps2", NULL, "ph_eint12", "csi1"}, 6, 12, 0},
|
||||
{"PH13", 7, 13, {"gpio_in", "gpio_out", "lcd1", NULL, "ps2", "sim", "ph_eint13", "csi1"}, 6, 13, 0},
|
||||
{"PH14", 7, 14, {"gpio_in", "gpio_out", "lcd1", NULL, "keypad", "sim", "ph_eint14", "csi1"}, 6, 14, 0},
|
||||
{"PH15", 7, 15, {"gpio_in", "gpio_out", "lcd1", NULL, "keypad", "sim", "ph_eint15", "csi1"}, 6, 15, 0},
|
||||
{"PH16", 7, 16, {"gpio_in", "gpio_out", "lcd1", NULL, "keypad", "sim", "ph_eint16", "csi1"}, 6, 16, 0},
|
||||
{"PH17", 7, 17, {"gpio_in", "gpio_out", "lcd1", NULL, "keypad", "sim", "ph_eint17", "csi1"}, 6, 17, 0},
|
||||
{"PH18", 7, 18, {"gpio_in", "gpio_out", "lcd1", NULL, "keypad", "sim", "ph_eint18", "csi1"}, 6, 18, 0},
|
||||
{"PH19", 7, 19, {"gpio_in", "gpio_out", "lcd1", NULL, "keypad", "sim", "ph_eint19", "csi1"}, 6, 19, 0},
|
||||
{"PH20", 7, 20, {"gpio_in", "gpio_out", "lcd1", NULL, "can", NULL, "ph_eint20", "csi1"}, 6, 20, 0},
|
||||
{"PH21", 7, 21, {"gpio_in", "gpio_out", "lcd1", NULL, "can", NULL, "ph_eint21", "csi1"}, 6, 21, 0},
|
||||
{"PH22", 7, 22, {"gpio_in", "gpio_out", "lcd1", NULL, "keypad", "mmc1", NULL, "csi1"}},
|
||||
{"PH23", 7, 23, {"gpio_in", "gpio_out", "lcd1", NULL, "keypad", "mmc1", NULL, "csi1"}},
|
||||
{"PH24", 7, 24, {"gpio_in", "gpio_out", "lcd1", NULL, "keypad", "mmc1", NULL, "csi1"}},
|
||||
@ -208,16 +208,16 @@ const static struct allwinner_pins a20_pins[] = {
|
||||
{"PI7", 8, 7, {"gpio_in", "gpio_out", "mmc3", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PI8", 8, 8, {"gpio_in", "gpio_out", "mmc3", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PI9", 8, 9, {"gpio_in", "gpio_out", "mmc3", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PI10", 8, 10, {"gpio_in", "gpio_out", "spi0", "uart5", NULL, NULL, "eint", NULL}},
|
||||
{"PI11", 8, 11, {"gpio_in", "gpio_out", "spi0", "uart5", NULL, NULL, "eint", NULL}},
|
||||
{"PI12", 8, 12, {"gpio_in", "gpio_out", "spi0", "uart6", "clk_out_a", NULL, "eint", NULL}},
|
||||
{"PI13", 8, 13, {"gpio_in", "gpio_out", "spi0", "uart6", "clk_out_b", NULL, "eint", NULL}},
|
||||
{"PI14", 8, 14, {"gpio_in", "gpio_out", "spi0", "ps2", "timer4", NULL, "eint", NULL}},
|
||||
{"PI15", 8, 15, {"gpio_in", "gpio_out", "spi1", "ps2", "timer5", NULL, "eint", NULL}},
|
||||
{"PI16", 8, 16, {"gpio_in", "gpio_out", "spi1", "uart2", NULL, NULL, "eint", NULL}},
|
||||
{"PI17", 8, 17, {"gpio_in", "gpio_out", "spi1", "uart2", NULL, NULL, "eint", NULL}},
|
||||
{"PI18", 8, 18, {"gpio_in", "gpio_out", "spi1", "uart2", NULL, NULL, "eint", NULL}},
|
||||
{"PI19", 8, 19, {"gpio_in", "gpio_out", "spi1", "uart2", NULL, NULL, "eint", NULL}},
|
||||
{"PI10", 8, 10, {"gpio_in", "gpio_out", "spi0", "uart5", NULL, NULL, "pi_eint22", NULL}, 6, 22, 0},
|
||||
{"PI11", 8, 11, {"gpio_in", "gpio_out", "spi0", "uart5", NULL, NULL, "pi_eint23", NULL}, 6, 23, 0},
|
||||
{"PI12", 8, 12, {"gpio_in", "gpio_out", "spi0", "uart6", "clk_out_a", NULL, "pi_eint24", NULL}, 6, 24, 0},
|
||||
{"PI13", 8, 13, {"gpio_in", "gpio_out", "spi0", "uart6", "clk_out_b", NULL, "pi_eint25", NULL}, 6, 25, 0},
|
||||
{"PI14", 8, 14, {"gpio_in", "gpio_out", "spi0", "ps2", "timer4", NULL, "pi_eint26", NULL}, 6, 26, 0},
|
||||
{"PI15", 8, 15, {"gpio_in", "gpio_out", "spi1", "ps2", "timer5", NULL, "pi_eint27", NULL}, 6, 27, 0},
|
||||
{"PI16", 8, 16, {"gpio_in", "gpio_out", "spi1", "uart2", NULL, NULL, "pi_eint28", NULL}, 6, 28, 0},
|
||||
{"PI17", 8, 17, {"gpio_in", "gpio_out", "spi1", "uart2", NULL, NULL, "pi_eint29", NULL}, 6, 29, 0},
|
||||
{"PI18", 8, 18, {"gpio_in", "gpio_out", "spi1", "uart2", NULL, NULL, "pi_eint30", NULL}, 6, 30, 0},
|
||||
{"PI19", 8, 19, {"gpio_in", "gpio_out", "spi1", "uart2", NULL, NULL, "pi_eint31", NULL}, 6, 31, 0},
|
||||
{"PI20", 8, 20, {"gpio_in", "gpio_out", "ps2", "uart7", "hdmi", NULL, NULL, NULL}},
|
||||
{"PI21", 8, 21, {"gpio_in", "gpio_out", "ps2", "uart7", "hdmi", NULL, NULL, NULL}},
|
||||
};
|
||||
|
@ -37,43 +37,43 @@ __FBSDID("$FreeBSD$");
|
||||
#ifdef SOC_ALLWINNER_A31
|
||||
|
||||
const static struct allwinner_pins a31_pins[] = {
|
||||
{"PA0", 0, 0, {"gpio_in", "gpio_out", "gmac", "lcd1", "uart1", NULL, "pa_eint0", NULL}, 6, 0},
|
||||
{"PA1", 0, 1, {"gpio_in", "gpio_out", "gmac", "lcd1", "uart1", NULL, "pa_eint1", NULL}, 6, 1},
|
||||
{"PA2", 0, 2, {"gpio_in", "gpio_out", "gmac", "lcd1", "uart1", NULL, "pa_eint2", NULL}, 6, 2},
|
||||
{"PA3", 0, 3, {"gpio_in", "gpio_out", "gmac", "lcd1", "uart1", NULL, "pa_eint3", NULL}, 6, 3},
|
||||
{"PA4", 0, 4, {"gpio_in", "gpio_out", "gmac", "lcd1", "uart1", NULL, "pa_eint4", NULL}, 6, 4},
|
||||
{"PA5", 0, 5, {"gpio_in", "gpio_out", "gmac", "lcd1", "uart1", NULL, "pa_eint5", NULL}, 6, 5},
|
||||
{"PA6", 0, 6, {"gpio_in", "gpio_out", "gmac", "lcd1", "uart1", NULL, "pa_eint6", NULL}, 6, 6},
|
||||
{"PA7", 0, 7, {"gpio_in", "gpio_out", "gmac", "lcd1", "uart1", NULL, "pa_eint7", NULL}, 6, 7},
|
||||
{"PA8", 0, 8, {"gpio_in", "gpio_out", "gmac", "lcd1", NULL, NULL, "pa_eint8", NULL}, 6, 8},
|
||||
{"PA9", 0, 9, {"gpio_in", "gpio_out", "gmac", "lcd1", NULL, "mmc2", "pa_eint9", NULL}, 6, 9},
|
||||
{"PA10", 0, 10, {"gpio_in", "gpio_out", "gmac", "lcd1", "mmc3", "mmc2", "pa_eint10", NULL}, 6, 10},
|
||||
{"PA11", 0, 11, {"gpio_in", "gpio_out", "gmac", "lcd1", "mmc3", "mmc2", "pa_eint11", NULL}, 6, 11},
|
||||
{"PA12", 0, 12, {"gpio_in", "gpio_out", "gmac", "lcd1", "mmc3", "mmc2", "pa_eint12", NULL}, 6, 12},
|
||||
{"PA13", 0, 13, {"gpio_in", "gpio_out", "gmac", "lcd1", "mmc3", "mmc2", "pa_eint13", NULL}, 6, 13},
|
||||
{"PA14", 0, 14, {"gpio_in", "gpio_out", "gmac", "lcd1", "mmc3", "mmc2", "pa_eint14", NULL}, 6, 14},
|
||||
{"PA15", 0, 15, {"gpio_in", "gpio_out", "gmac", "lcd1", "clk_out_a", NULL, "pa_eint15", NULL}, 6, 15},
|
||||
{"PA16", 0, 16, {"gpio_in", "gpio_out", "gmac", "lcd1", "dmic", NULL, "pa_eint16", NULL}, 6, 16},
|
||||
{"PA17", 0, 17, {"gpio_in", "gpio_out", "gmac", "lcd1", "dmic", NULL, "pa_eint17", NULL}, 6, 17},
|
||||
{"PA18", 0, 18, {"gpio_in", "gpio_out", "gmac", "lcd1", "clk_out_b", NULL, "pa_eint18", NULL}, 6, 18},
|
||||
{"PA19", 0, 19, {"gpio_in", "gpio_out", "gmac", "lcd1", "pwm3", NULL, "pa_eint19", NULL}, 6, 19},
|
||||
{"PA20", 0, 20, {"gpio_in", "gpio_out", "gmac", "lcd1", "pwm3", NULL, "pa_eint20", NULL}, 6, 20},
|
||||
{"PA21", 0, 21, {"gpio_in", "gpio_out", "gmac", "lcd1", "spi3", NULL, "pa_eint21", NULL}, 6, 21},
|
||||
{"PA22", 0, 22, {"gpio_in", "gpio_out", "gmac", "lcd1", "spi3", NULL, "pa_eint22", NULL}, 6, 22},
|
||||
{"PA23", 0, 23, {"gpio_in", "gpio_out", "gmac", "lcd1", "spi3", NULL, "pa_eint23", NULL}, 6, 23},
|
||||
{"PA24", 0, 24, {"gpio_in", "gpio_out", "gmac", "lcd1", "spi3", NULL, "pa_eint24", NULL}, 6, 24},
|
||||
{"PA25", 0, 25, {"gpio_in", "gpio_out", "gmac", "lcd1", "spi3", NULL, "pa_eint25", NULL}, 6, 25},
|
||||
{"PA26", 0, 26, {"gpio_in", "gpio_out", "gmac", "lcd1", "clk_out_c", NULL, "pa_eint26", NULL}, 6, 26},
|
||||
{"PA27", 0, 27, {"gpio_in", "gpio_out", "gmac", "lcd1", NULL, NULL, "pa_eint27", NULL}, 6, 27},
|
||||
{"PA0", 0, 0, {"gpio_in", "gpio_out", "gmac", "lcd1", "uart1", NULL, "pa_eint0", NULL}, 6, 0, 0},
|
||||
{"PA1", 0, 1, {"gpio_in", "gpio_out", "gmac", "lcd1", "uart1", NULL, "pa_eint1", NULL}, 6, 1, 0},
|
||||
{"PA2", 0, 2, {"gpio_in", "gpio_out", "gmac", "lcd1", "uart1", NULL, "pa_eint2", NULL}, 6, 2, 0},
|
||||
{"PA3", 0, 3, {"gpio_in", "gpio_out", "gmac", "lcd1", "uart1", NULL, "pa_eint3", NULL}, 6, 3, 0},
|
||||
{"PA4", 0, 4, {"gpio_in", "gpio_out", "gmac", "lcd1", "uart1", NULL, "pa_eint4", NULL}, 6, 4, 0},
|
||||
{"PA5", 0, 5, {"gpio_in", "gpio_out", "gmac", "lcd1", "uart1", NULL, "pa_eint5", NULL}, 6, 5, 0},
|
||||
{"PA6", 0, 6, {"gpio_in", "gpio_out", "gmac", "lcd1", "uart1", NULL, "pa_eint6", NULL}, 6, 6, 0},
|
||||
{"PA7", 0, 7, {"gpio_in", "gpio_out", "gmac", "lcd1", "uart1", NULL, "pa_eint7", NULL}, 6, 7, 0},
|
||||
{"PA8", 0, 8, {"gpio_in", "gpio_out", "gmac", "lcd1", NULL, NULL, "pa_eint8", NULL}, 6, 8, 0},
|
||||
{"PA9", 0, 9, {"gpio_in", "gpio_out", "gmac", "lcd1", NULL, "mmc2", "pa_eint9", NULL}, 6, 9, 0},
|
||||
{"PA10", 0, 10, {"gpio_in", "gpio_out", "gmac", "lcd1", "mmc3", "mmc2", "pa_eint10", NULL}, 6, 10, 0},
|
||||
{"PA11", 0, 11, {"gpio_in", "gpio_out", "gmac", "lcd1", "mmc3", "mmc2", "pa_eint11", NULL}, 6, 11, 0},
|
||||
{"PA12", 0, 12, {"gpio_in", "gpio_out", "gmac", "lcd1", "mmc3", "mmc2", "pa_eint12", NULL}, 6, 12, 0},
|
||||
{"PA13", 0, 13, {"gpio_in", "gpio_out", "gmac", "lcd1", "mmc3", "mmc2", "pa_eint13", NULL}, 6, 13, 0},
|
||||
{"PA14", 0, 14, {"gpio_in", "gpio_out", "gmac", "lcd1", "mmc3", "mmc2", "pa_eint14", NULL}, 6, 14, 0},
|
||||
{"PA15", 0, 15, {"gpio_in", "gpio_out", "gmac", "lcd1", "clk_out_a", NULL, "pa_eint15", NULL}, 6, 15, 0},
|
||||
{"PA16", 0, 16, {"gpio_in", "gpio_out", "gmac", "lcd1", "dmic", NULL, "pa_eint16", NULL}, 6, 16, 0},
|
||||
{"PA17", 0, 17, {"gpio_in", "gpio_out", "gmac", "lcd1", "dmic", NULL, "pa_eint17", NULL}, 6, 17, 0},
|
||||
{"PA18", 0, 18, {"gpio_in", "gpio_out", "gmac", "lcd1", "clk_out_b", NULL, "pa_eint18", NULL}, 6, 18, 0},
|
||||
{"PA19", 0, 19, {"gpio_in", "gpio_out", "gmac", "lcd1", "pwm3", NULL, "pa_eint19", NULL}, 6, 19, 0},
|
||||
{"PA20", 0, 20, {"gpio_in", "gpio_out", "gmac", "lcd1", "pwm3", NULL, "pa_eint20", NULL}, 6, 20, 0},
|
||||
{"PA21", 0, 21, {"gpio_in", "gpio_out", "gmac", "lcd1", "spi3", NULL, "pa_eint21", NULL}, 6, 21, 0},
|
||||
{"PA22", 0, 22, {"gpio_in", "gpio_out", "gmac", "lcd1", "spi3", NULL, "pa_eint22", NULL}, 6, 22, 0},
|
||||
{"PA23", 0, 23, {"gpio_in", "gpio_out", "gmac", "lcd1", "spi3", NULL, "pa_eint23", NULL}, 6, 23, 0},
|
||||
{"PA24", 0, 24, {"gpio_in", "gpio_out", "gmac", "lcd1", "spi3", NULL, "pa_eint24", NULL}, 6, 24, 0},
|
||||
{"PA25", 0, 25, {"gpio_in", "gpio_out", "gmac", "lcd1", "spi3", NULL, "pa_eint25", NULL}, 6, 25, 0},
|
||||
{"PA26", 0, 26, {"gpio_in", "gpio_out", "gmac", "lcd1", "clk_out_c", NULL, "pa_eint26", NULL}, 6, 26, 0},
|
||||
{"PA27", 0, 27, {"gpio_in", "gpio_out", "gmac", "lcd1", NULL, NULL, "pa_eint27", NULL}, 6, 27, 0},
|
||||
|
||||
{"PB0", 1, 0, {"gpio_in", "gpio_out", "i2s0", "uart3", "csi", NULL, "pb_eint0", NULL}, 6, 0},
|
||||
{"PB1", 1, 1, {"gpio_in", "gpio_out", "i2s0", NULL, NULL, NULL, "pb_eint1", NULL}, 6, 1},
|
||||
{"PB2", 1, 2, {"gpio_in", "gpio_out", "i2s0", NULL, NULL, NULL, "pb_eint2", NULL}, 6, 2},
|
||||
{"PB3", 1, 3, {"gpio_in", "gpio_out", "i2s0", NULL, NULL, NULL, "pb_eint3", NULL}, 6, 3},
|
||||
{"PB4", 1, 4, {"gpio_in", "gpio_out", "i2s0", "uart3", NULL, NULL, "pb_eint4", NULL}, 6, 4},
|
||||
{"PB5", 1, 5, {"gpio_in", "gpio_out", "i2s0", "uart3", "i2c3", NULL, "pb_eint5", NULL}, 6, 5},
|
||||
{"PB6", 1, 6, {"gpio_in", "gpio_out", "i2s0", "uart3", "i2c3", NULL, "pb_eint6", NULL}, 6, 6},
|
||||
{"PB7", 1, 7, {"gpio_in", "gpio_out", "i2s0", NULL, NULL, NULL, "pb_eint7", NULL}, 6, 7},
|
||||
{"PB0", 1, 0, {"gpio_in", "gpio_out", "i2s0", "uart3", "csi", NULL, "pb_eint0", NULL}, 6, 0, 1},
|
||||
{"PB1", 1, 1, {"gpio_in", "gpio_out", "i2s0", NULL, NULL, NULL, "pb_eint1", NULL}, 6, 1, 1},
|
||||
{"PB2", 1, 2, {"gpio_in", "gpio_out", "i2s0", NULL, NULL, NULL, "pb_eint2", NULL}, 6, 2, 1},
|
||||
{"PB3", 1, 3, {"gpio_in", "gpio_out", "i2s0", NULL, NULL, NULL, "pb_eint3", NULL}, 6, 3, 1},
|
||||
{"PB4", 1, 4, {"gpio_in", "gpio_out", "i2s0", "uart3", NULL, NULL, "pb_eint4", NULL}, 6, 4, 1},
|
||||
{"PB5", 1, 5, {"gpio_in", "gpio_out", "i2s0", "uart3", "i2c3", NULL, "pb_eint5", NULL}, 6, 5, 1},
|
||||
{"PB6", 1, 6, {"gpio_in", "gpio_out", "i2s0", "uart3", "i2c3", NULL, "pb_eint6", NULL}, 6, 6, 1},
|
||||
{"PB7", 1, 7, {"gpio_in", "gpio_out", "i2s0", NULL, NULL, NULL, "pb_eint7", NULL}, 6, 7, 1},
|
||||
|
||||
{"PC0", 2, 0, {"gpio_in", "gpio_out", "nand0", "spi0", NULL, NULL, NULL, NULL}},
|
||||
{"PC1", 2, 1, {"gpio_in", "gpio_out", "nand0", "spi0", NULL, NULL, NULL, NULL}},
|
||||
@ -133,23 +133,23 @@ const static struct allwinner_pins a31_pins[] = {
|
||||
{"PD26", 3, 26, {"gpio_in", "gpio_out", "lcd0", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PD27", 3, 27, {"gpio_in", "gpio_out", "lcd0", NULL, NULL, NULL, NULL, NULL}},
|
||||
|
||||
{"PE0", 4, 0, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint0", NULL}, 6, 0},
|
||||
{"PE1", 4, 1, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint1", NULL}, 6, 1},
|
||||
{"PE2", 4, 2, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint2", NULL}, 6, 2},
|
||||
{"PE3", 4, 3, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint3", NULL}, 6, 3},
|
||||
{"PE4", 4, 4, {"gpio_in", "gpio_out", "csi", "uart5", NULL, NULL, "pe_eint4", NULL}, 6, 4},
|
||||
{"PE5", 4, 5, {"gpio_in", "gpio_out", "csi", "uart5", NULL, NULL, "pe_eint5", NULL}, 6, 5},
|
||||
{"PE6", 4, 6, {"gpio_in", "gpio_out", "csi", "uart5", NULL, NULL, "pe_eint6", NULL}, 6, 6},
|
||||
{"PE7", 4, 7, {"gpio_in", "gpio_out", "csi", "uart5", NULL, NULL, "pe_eint7", NULL}, 6, 7},
|
||||
{"PE8", 4, 8, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint8", NULL}, 6, 8},
|
||||
{"PE9", 4, 9, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint9", NULL}, 6, 9},
|
||||
{"PE10", 4, 10, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint10", NULL}, 6, 10},
|
||||
{"PE11", 4, 11, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint11", NULL}, 6, 11},
|
||||
{"PE12", 4, 12, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint12", NULL}, 6, 12},
|
||||
{"PE13", 4, 13, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint13", NULL}, 6, 13},
|
||||
{"PE14", 4, 14, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint14", NULL}, 6, 14},
|
||||
{"PE15", 4, 15, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint15", NULL}, 6, 15},
|
||||
{"PE16", 4, 16, {"gpio_in", "gpio_out", "csi", NULL, NULL, NULL, "pe_eint16", NULL}, 6, 16},
|
||||
{"PE0", 4, 0, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint0", NULL}, 6, 0, 4},
|
||||
{"PE1", 4, 1, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint1", NULL}, 6, 1, 4},
|
||||
{"PE2", 4, 2, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint2", NULL}, 6, 2, 4},
|
||||
{"PE3", 4, 3, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint3", NULL}, 6, 3, 4},
|
||||
{"PE4", 4, 4, {"gpio_in", "gpio_out", "csi", "uart5", NULL, NULL, "pe_eint4", NULL}, 6, 4, 4},
|
||||
{"PE5", 4, 5, {"gpio_in", "gpio_out", "csi", "uart5", NULL, NULL, "pe_eint5", NULL}, 6, 5, 4},
|
||||
{"PE6", 4, 6, {"gpio_in", "gpio_out", "csi", "uart5", NULL, NULL, "pe_eint6", NULL}, 6, 6, 4},
|
||||
{"PE7", 4, 7, {"gpio_in", "gpio_out", "csi", "uart5", NULL, NULL, "pe_eint7", NULL}, 6, 7, 4},
|
||||
{"PE8", 4, 8, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint8", NULL}, 6, 8, 4},
|
||||
{"PE9", 4, 9, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint9", NULL}, 6, 9, 4},
|
||||
{"PE10", 4, 10, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint10", NULL}, 6, 10, 4},
|
||||
{"PE11", 4, 11, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint11", NULL}, 6, 11, 4},
|
||||
{"PE12", 4, 12, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint12", NULL}, 6, 12, 4},
|
||||
{"PE13", 4, 13, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint13", NULL}, 6, 13, 4},
|
||||
{"PE14", 4, 14, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint14", NULL}, 6, 14, 4},
|
||||
{"PE15", 4, 15, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint15", NULL}, 6, 15, 4},
|
||||
{"PE16", 4, 16, {"gpio_in", "gpio_out", "csi", NULL, NULL, NULL, "pe_eint16", NULL}, 6, 16, 4},
|
||||
|
||||
{"PF0", 5, 0, {"gpio_in", "gpio_out", "mmc0", NULL, "jtag", NULL, NULL, NULL}},
|
||||
{"PF1", 5, 1, {"gpio_in", "gpio_out", "mmc0", NULL, "jtag", NULL, NULL, NULL}},
|
||||
@ -158,25 +158,25 @@ const static struct allwinner_pins a31_pins[] = {
|
||||
{"PF4", 5, 4, {"gpio_in", "gpio_out", "mmc0", NULL, "uart0", NULL, NULL, NULL}},
|
||||
{"PF5", 5, 5, {"gpio_in", "gpio_out", "mmc0", NULL, "jtag", NULL, NULL, NULL}},
|
||||
|
||||
{"PG0", 6, 0, {"gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint0", NULL}, 6, 0},
|
||||
{"PG1", 6, 1, {"gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint1", NULL}, 6, 1},
|
||||
{"PG2", 6, 2, {"gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint2", NULL}, 6, 2},
|
||||
{"PG3", 6, 3, {"gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint3", NULL}, 6, 3},
|
||||
{"PG4", 6, 4, {"gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint4", NULL}, 6, 4},
|
||||
{"PG5", 6, 5, {"gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint5", NULL}, 6, 5},
|
||||
{"PG6", 6, 6, {"gpio_in", "gpio_out", "uart2", NULL, NULL, NULL, "pg_eint6", NULL}, 6, 6},
|
||||
{"PG7", 6, 7, {"gpio_in", "gpio_out", "uart2", NULL, NULL, NULL, "pg_eint7", NULL}, 6, 7},
|
||||
{"PG8", 6, 8, {"gpio_in", "gpio_out", "uart2", NULL, NULL, NULL, "pg_eint8", NULL}, 6, 8},
|
||||
{"PG9", 6, 9, {"gpio_in", "gpio_out", "uart2", NULL, NULL, NULL, "pg_eint9", NULL}, 6, 9},
|
||||
{"PG10", 6, 10, {"gpio_in", "gpio_out", "i2c3", "usb", NULL, NULL, "pg_eint10", NULL}, 6, 10},
|
||||
{"PG11", 6, 11, {"gpio_in", "gpio_out", "i2c3", "usb", NULL, NULL, "pg_eint11", NULL}, 6, 11},
|
||||
{"PG12", 6, 12, {"gpio_in", "gpio_out", "spi1", "i2s1", NULL, NULL, "pg_eint12", NULL}, 6, 12},
|
||||
{"PG13", 6, 13, {"gpio_in", "gpio_out", "spi1", "i2s1", NULL, NULL, "pg_eint13", NULL}, 6, 13},
|
||||
{"PG14", 6, 14, {"gpio_in", "gpio_out", "spi1", "i2s1", NULL, NULL, "pg_eint14", NULL}, 6, 14},
|
||||
{"PG15", 6, 15, {"gpio_in", "gpio_out", "spi1", "i2s1", NULL, NULL, "pg_eint15", NULL}, 6, 15},
|
||||
{"PG16", 6, 16, {"gpio_in", "gpio_out", "spi1", "i2s1", NULL, NULL, "pg_eint16", NULL}, 6, 16},
|
||||
{"PG17", 6, 17, {"gpio_in", "gpio_out", "uart4", NULL, NULL, NULL, "pg_eint17", NULL}, 6, 17},
|
||||
{"PG18", 6, 18, {"gpio_in", "gpio_out", "uart4", NULL, NULL, NULL, "pg_eint18", NULL}, 6, 18},
|
||||
{"PG0", 6, 0, {"gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint0", NULL}, 6, 0, 6},
|
||||
{"PG1", 6, 1, {"gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint1", NULL}, 6, 1, 6},
|
||||
{"PG2", 6, 2, {"gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint2", NULL}, 6, 2, 6},
|
||||
{"PG3", 6, 3, {"gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint3", NULL}, 6, 3, 6},
|
||||
{"PG4", 6, 4, {"gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint4", NULL}, 6, 4, 6},
|
||||
{"PG5", 6, 5, {"gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint5", NULL}, 6, 5, 6},
|
||||
{"PG6", 6, 6, {"gpio_in", "gpio_out", "uart2", NULL, NULL, NULL, "pg_eint6", NULL}, 6, 6, 6},
|
||||
{"PG7", 6, 7, {"gpio_in", "gpio_out", "uart2", NULL, NULL, NULL, "pg_eint7", NULL}, 6, 7, 6},
|
||||
{"PG8", 6, 8, {"gpio_in", "gpio_out", "uart2", NULL, NULL, NULL, "pg_eint8", NULL}, 6, 8, 6},
|
||||
{"PG9", 6, 9, {"gpio_in", "gpio_out", "uart2", NULL, NULL, NULL, "pg_eint9", NULL}, 6, 9, 6},
|
||||
{"PG10", 6, 10, {"gpio_in", "gpio_out", "i2c3", "usb", NULL, NULL, "pg_eint10", NULL}, 6, 10, 6},
|
||||
{"PG11", 6, 11, {"gpio_in", "gpio_out", "i2c3", "usb", NULL, NULL, "pg_eint11", NULL}, 6, 11, 6},
|
||||
{"PG12", 6, 12, {"gpio_in", "gpio_out", "spi1", "i2s1", NULL, NULL, "pg_eint12", NULL}, 6, 12, 6},
|
||||
{"PG13", 6, 13, {"gpio_in", "gpio_out", "spi1", "i2s1", NULL, NULL, "pg_eint13", NULL}, 6, 13, 6},
|
||||
{"PG14", 6, 14, {"gpio_in", "gpio_out", "spi1", "i2s1", NULL, NULL, "pg_eint14", NULL}, 6, 14, 6},
|
||||
{"PG15", 6, 15, {"gpio_in", "gpio_out", "spi1", "i2s1", NULL, NULL, "pg_eint15", NULL}, 6, 15, 6},
|
||||
{"PG16", 6, 16, {"gpio_in", "gpio_out", "spi1", "i2s1", NULL, NULL, "pg_eint16", NULL}, 6, 16, 6},
|
||||
{"PG17", 6, 17, {"gpio_in", "gpio_out", "uart4", NULL, NULL, NULL, "pg_eint17", NULL}, 6, 17, 6},
|
||||
{"PG18", 6, 18, {"gpio_in", "gpio_out", "uart4", NULL, NULL, NULL, "pg_eint18", NULL}, 6, 18, 6},
|
||||
|
||||
{"PH0", 7, 0, {"gpio_in", "gpio_out", "nand1", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PH1", 7, 1, {"gpio_in", "gpio_out", "nand1", NULL, NULL, NULL, NULL, NULL}},
|
||||
|
@ -37,43 +37,43 @@ __FBSDID("$FreeBSD$");
|
||||
#ifdef SOC_ALLWINNER_A31S
|
||||
|
||||
const static struct allwinner_pins a31s_pins[] = {
|
||||
{"PA0", 0, 0, {"gpio_in", "gpio_out", "gmac", NULL, "uart1", NULL, "pa_eint0", NULL}, 6, 0},
|
||||
{"PA1", 0, 1, {"gpio_in", "gpio_out", "gmac", NULL, "uart1", NULL, "pa_eint1", NULL}, 6, 1},
|
||||
{"PA2", 0, 2, {"gpio_in", "gpio_out", "gmac", NULL, "uart1", NULL, "pa_eint2", NULL}, 6, 2},
|
||||
{"PA3", 0, 3, {"gpio_in", "gpio_out", "gmac", NULL, "uart1", NULL, "pa_eint3", NULL}, 6, 3},
|
||||
{"PA4", 0, 4, {"gpio_in", "gpio_out", "gmac", NULL, "uart1", NULL, "pa_eint4", NULL}, 6, 4},
|
||||
{"PA5", 0, 5, {"gpio_in", "gpio_out", "gmac", NULL, "uart1", NULL, "pa_eint5", NULL}, 6, 5},
|
||||
{"PA6", 0, 6, {"gpio_in", "gpio_out", "gmac", NULL, "uart1", NULL, "pa_eint6", NULL}, 6, 6},
|
||||
{"PA7", 0, 7, {"gpio_in", "gpio_out", "gmac", NULL, "uart1", NULL, "pa_eint7", NULL}, 6, 7},
|
||||
{"PA8", 0, 8, {"gpio_in", "gpio_out", "gmac", NULL, NULL, NULL, "pa_eint8", NULL}, 6, 8},
|
||||
{"PA9", 0, 9, {"gpio_in", "gpio_out", "gmac", NULL, NULL, NULL, "pa_eint9", NULL}, 6, 9},
|
||||
{"PA10", 0, 10, {"gpio_in", "gpio_out", "gmac", NULL, "mmc3", "mmc2", "pa_eint10", NULL}, 6, 10},
|
||||
{"PA11", 0, 11, {"gpio_in", "gpio_out", "gmac", NULL, "mmc3", "mmc2", "pa_eint11", NULL}, 6, 11},
|
||||
{"PA12", 0, 12, {"gpio_in", "gpio_out", "gmac", NULL, "mmc3", "mmc2", "pa_eint12", NULL}, 6, 12},
|
||||
{"PA13", 0, 13, {"gpio_in", "gpio_out", "gmac", NULL, "mmc3", "mmc2", "pa_eint13", NULL}, 6, 13},
|
||||
{"PA14", 0, 14, {"gpio_in", "gpio_out", "gmac", NULL, "mmc3", "mmc2", "pa_eint14", NULL}, 6, 14},
|
||||
{"PA15", 0, 15, {"gpio_in", "gpio_out", "gmac", NULL, "dmic", NULL, "pa_eint15", NULL}, 6, 15},
|
||||
{"PA16", 0, 16, {"gpio_in", "gpio_out", "gmac", NULL, "dmic", NULL, "pa_eint16", NULL}, 6, 16},
|
||||
{"PA17", 0, 17, {"gpio_in", "gpio_out", "gmac", NULL, "clk_out_b", NULL, "pa_eint17", NULL}, 6, 17},
|
||||
{"PA18", 0, 18, {"gpio_in", "gpio_out", "gmac", NULL, "pwm3", NULL, "pa_eint18", NULL}, 6, 18},
|
||||
{"PA19", 0, 19, {"gpio_in", "gpio_out", "gmac", NULL, "pwm3", NULL, "pa_eint19", NULL}, 6, 19},
|
||||
{"PA20", 0, 20, {"gpio_in", "gpio_out", "gmac", NULL, "spi3", NULL, "pa_eint20", NULL}, 6, 20},
|
||||
{"PA21", 0, 21, {"gpio_in", "gpio_out", "gmac", NULL, "spi3", NULL, "pa_eint21", NULL}, 6, 21},
|
||||
{"PA22", 0, 22, {"gpio_in", "gpio_out", "gmac", NULL, "spi3", NULL, "pa_eint22", NULL}, 6, 22},
|
||||
{"PA23", 0, 23, {"gpio_in", "gpio_out", "gmac", NULL, "spi3", NULL, "pa_eint23", NULL}, 6, 23},
|
||||
{"PA24", 0, 24, {"gpio_in", "gpio_out", "gmac", NULL, "spi3", NULL, "pa_eint24", NULL}, 6, 24},
|
||||
{"PA25", 0, 25, {"gpio_in", "gpio_out", "gmac", NULL, "spi3", NULL, "pa_eint25", NULL}, 6, 25},
|
||||
{"PA26", 0, 26, {"gpio_in", "gpio_out", "gmac", NULL, "clk_out_c", NULL, "pa_eint26", NULL}, 6, 26},
|
||||
{"PA27", 0, 27, {"gpio_in", "gpio_out", "gmac", NULL, NULL, NULL, "pa_eint27", NULL}, 6, 27},
|
||||
{"PA0", 0, 0, {"gpio_in", "gpio_out", "gmac", NULL, "uart1", NULL, "pa_eint0", NULL}, 6, 0, 0},
|
||||
{"PA1", 0, 1, {"gpio_in", "gpio_out", "gmac", NULL, "uart1", NULL, "pa_eint1", NULL}, 6, 1, 0},
|
||||
{"PA2", 0, 2, {"gpio_in", "gpio_out", "gmac", NULL, "uart1", NULL, "pa_eint2", NULL}, 6, 2, 0},
|
||||
{"PA3", 0, 3, {"gpio_in", "gpio_out", "gmac", NULL, "uart1", NULL, "pa_eint3", NULL}, 6, 3, 0},
|
||||
{"PA4", 0, 4, {"gpio_in", "gpio_out", "gmac", NULL, "uart1", NULL, "pa_eint4", NULL}, 6, 4, 0},
|
||||
{"PA5", 0, 5, {"gpio_in", "gpio_out", "gmac", NULL, "uart1", NULL, "pa_eint5", NULL}, 6, 5, 0},
|
||||
{"PA6", 0, 6, {"gpio_in", "gpio_out", "gmac", NULL, "uart1", NULL, "pa_eint6", NULL}, 6, 6, 0},
|
||||
{"PA7", 0, 7, {"gpio_in", "gpio_out", "gmac", NULL, "uart1", NULL, "pa_eint7", NULL}, 6, 7, 0},
|
||||
{"PA8", 0, 8, {"gpio_in", "gpio_out", "gmac", NULL, NULL, NULL, "pa_eint8", NULL}, 6, 8, 0},
|
||||
{"PA9", 0, 9, {"gpio_in", "gpio_out", "gmac", NULL, NULL, NULL, "pa_eint9", NULL}, 6, 9, 0},
|
||||
{"PA10", 0, 10, {"gpio_in", "gpio_out", "gmac", NULL, "mmc3", "mmc2", "pa_eint10", NULL}, 6, 10, 0},
|
||||
{"PA11", 0, 11, {"gpio_in", "gpio_out", "gmac", NULL, "mmc3", "mmc2", "pa_eint11", NULL}, 6, 11, 0},
|
||||
{"PA12", 0, 12, {"gpio_in", "gpio_out", "gmac", NULL, "mmc3", "mmc2", "pa_eint12", NULL}, 6, 12, 0},
|
||||
{"PA13", 0, 13, {"gpio_in", "gpio_out", "gmac", NULL, "mmc3", "mmc2", "pa_eint13", NULL}, 6, 13, 0},
|
||||
{"PA14", 0, 14, {"gpio_in", "gpio_out", "gmac", NULL, "mmc3", "mmc2", "pa_eint14", NULL}, 6, 14, 0},
|
||||
{"PA15", 0, 15, {"gpio_in", "gpio_out", "gmac", NULL, "dmic", NULL, "pa_eint15", NULL}, 6, 15, 0},
|
||||
{"PA16", 0, 16, {"gpio_in", "gpio_out", "gmac", NULL, "dmic", NULL, "pa_eint16", NULL}, 6, 16, 0},
|
||||
{"PA17", 0, 17, {"gpio_in", "gpio_out", "gmac", NULL, "clk_out_b", NULL, "pa_eint17", NULL}, 6, 17, 0},
|
||||
{"PA18", 0, 18, {"gpio_in", "gpio_out", "gmac", NULL, "pwm3", NULL, "pa_eint18", NULL}, 6, 18, 0},
|
||||
{"PA19", 0, 19, {"gpio_in", "gpio_out", "gmac", NULL, "pwm3", NULL, "pa_eint19", NULL}, 6, 19, 0},
|
||||
{"PA20", 0, 20, {"gpio_in", "gpio_out", "gmac", NULL, "spi3", NULL, "pa_eint20", NULL}, 6, 20, 0},
|
||||
{"PA21", 0, 21, {"gpio_in", "gpio_out", "gmac", NULL, "spi3", NULL, "pa_eint21", NULL}, 6, 21, 0},
|
||||
{"PA22", 0, 22, {"gpio_in", "gpio_out", "gmac", NULL, "spi3", NULL, "pa_eint22", NULL}, 6, 22, 0},
|
||||
{"PA23", 0, 23, {"gpio_in", "gpio_out", "gmac", NULL, "spi3", NULL, "pa_eint23", NULL}, 6, 23, 0},
|
||||
{"PA24", 0, 24, {"gpio_in", "gpio_out", "gmac", NULL, "spi3", NULL, "pa_eint24", NULL}, 6, 24, 0},
|
||||
{"PA25", 0, 25, {"gpio_in", "gpio_out", "gmac", NULL, "spi3", NULL, "pa_eint25", NULL}, 6, 25, 0},
|
||||
{"PA26", 0, 26, {"gpio_in", "gpio_out", "gmac", NULL, "clk_out_c", NULL, "pa_eint26", NULL}, 6, 26, 0},
|
||||
{"PA27", 0, 27, {"gpio_in", "gpio_out", "gmac", NULL, NULL, NULL, "pa_eint27", NULL}, 6, 27, 0},
|
||||
|
||||
{"PB0", 1, 0, {"gpio_in", "gpio_out", "i2s0", "uart3", NULL , NULL, "pb_eint0", NULL}, 6, 0},
|
||||
{"PB1", 1, 1, {"gpio_in", "gpio_out", "i2s0", NULL, NULL, NULL, "pb_eint1", NULL}, 6, 1},
|
||||
{"PB2", 1, 2, {"gpio_in", "gpio_out", "i2s0", NULL, NULL, NULL, "pb_eint2", NULL}, 6, 2},
|
||||
{"PB3", 1, 3, {"gpio_in", "gpio_out", "i2s0", NULL, NULL, NULL, "pb_eint3", NULL}, 6, 3},
|
||||
{"PB4", 1, 4, {"gpio_in", "gpio_out", "i2s0", "uart3", NULL, NULL, "pb_eint4", NULL}, 6, 4},
|
||||
{"PB5", 1, 5, {"gpio_in", "gpio_out", "i2s0", "uart3", "i2c3", NULL, "pb_eint5", NULL}, 6, 5},
|
||||
{"PB6", 1, 6, {"gpio_in", "gpio_out", "i2s0", "uart3", "i2c3", NULL, "pb_eint6", NULL}, 6, 6},
|
||||
{"PB7", 1, 7, {"gpio_in", "gpio_out", "i2s0", NULL, NULL, NULL, "pb_eint7", NULL}, 6, 7},
|
||||
{"PB0", 1, 0, {"gpio_in", "gpio_out", "i2s0", "uart3", NULL , NULL, "pb_eint0", NULL}, 6, 0, 1},
|
||||
{"PB1", 1, 1, {"gpio_in", "gpio_out", "i2s0", NULL, NULL, NULL, "pb_eint1", NULL}, 6, 1, 1},
|
||||
{"PB2", 1, 2, {"gpio_in", "gpio_out", "i2s0", NULL, NULL, NULL, "pb_eint2", NULL}, 6, 2, 1},
|
||||
{"PB3", 1, 3, {"gpio_in", "gpio_out", "i2s0", NULL, NULL, NULL, "pb_eint3", NULL}, 6, 3, 1},
|
||||
{"PB4", 1, 4, {"gpio_in", "gpio_out", "i2s0", "uart3", NULL, NULL, "pb_eint4", NULL}, 6, 4, 1},
|
||||
{"PB5", 1, 5, {"gpio_in", "gpio_out", "i2s0", "uart3", "i2c3", NULL, "pb_eint5", NULL}, 6, 5, 1},
|
||||
{"PB6", 1, 6, {"gpio_in", "gpio_out", "i2s0", "uart3", "i2c3", NULL, "pb_eint6", NULL}, 6, 6, 1},
|
||||
{"PB7", 1, 7, {"gpio_in", "gpio_out", "i2s0", NULL, NULL, NULL, "pb_eint7", NULL}, 6, 7, 1},
|
||||
|
||||
{"PC0", 2, 0, {"gpio_in", "gpio_out", "nand0", "spi0", NULL, NULL, NULL, NULL}},
|
||||
{"PC1", 2, 1, {"gpio_in", "gpio_out", "nand0", "spi0", NULL, NULL, NULL, NULL}},
|
||||
@ -125,22 +125,22 @@ const static struct allwinner_pins a31s_pins[] = {
|
||||
{"PD26", 3, 26, {"gpio_in", "gpio_out", "lcd0", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PD27", 3, 27, {"gpio_in", "gpio_out", "lcd0", NULL, NULL, NULL, NULL, NULL}},
|
||||
|
||||
{"PE0", 4, 0, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint0", NULL}, 6, 0},
|
||||
{"PE1", 4, 1, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint1", NULL}, 6, 1},
|
||||
{"PE2", 4, 2, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint2", NULL}, 6, 2},
|
||||
{"PE3", 4, 3, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint3", NULL}, 6, 3},
|
||||
{"PE4", 4, 4, {"gpio_in", "gpio_out", "csi", "uart5", NULL, NULL, "pe_eint4", NULL}, 6, 4},
|
||||
{"PE5", 4, 5, {"gpio_in", "gpio_out", "csi", "uart5", NULL, NULL, "pe_eint5", NULL}, 6, 5},
|
||||
{"PE6", 4, 6, {"gpio_in", "gpio_out", "csi", "uart5", NULL, NULL, "pe_eint6", NULL}, 6, 6},
|
||||
{"PE7", 4, 7, {"gpio_in", "gpio_out", "csi", "uart5", NULL, NULL, "pe_eint7", NULL}, 6, 7},
|
||||
{"PE8", 4, 8, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint8", NULL}, 6, 8},
|
||||
{"PE9", 4, 9, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint9", NULL}, 6, 9},
|
||||
{"PE10", 4, 10, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint10", NULL}, 6, 10},
|
||||
{"PE11", 4, 11, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint11", NULL}, 6, 11},
|
||||
{"PE12", 4, 12, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint12", NULL}, 6, 12},
|
||||
{"PE13", 4, 13, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint13", NULL}, 6, 13},
|
||||
{"PE14", 4, 14, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint14", NULL}, 6, 14},
|
||||
{"PE15", 4, 15, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint15", NULL}, 6, 15},
|
||||
{"PE0", 4, 0, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint0", NULL}, 6, 0, 4},
|
||||
{"PE1", 4, 1, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint1", NULL}, 6, 1, 4},
|
||||
{"PE2", 4, 2, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint2", NULL}, 6, 2, 4},
|
||||
{"PE3", 4, 3, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint3", NULL}, 6, 3, 4},
|
||||
{"PE4", 4, 4, {"gpio_in", "gpio_out", "csi", "uart5", NULL, NULL, "pe_eint4", NULL}, 6, 4, 4},
|
||||
{"PE5", 4, 5, {"gpio_in", "gpio_out", "csi", "uart5", NULL, NULL, "pe_eint5", NULL}, 6, 5, 4},
|
||||
{"PE6", 4, 6, {"gpio_in", "gpio_out", "csi", "uart5", NULL, NULL, "pe_eint6", NULL}, 6, 6, 4},
|
||||
{"PE7", 4, 7, {"gpio_in", "gpio_out", "csi", "uart5", NULL, NULL, "pe_eint7", NULL}, 6, 7, 4},
|
||||
{"PE8", 4, 8, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint8", NULL}, 6, 8, 4},
|
||||
{"PE9", 4, 9, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint9", NULL}, 6, 9, 4},
|
||||
{"PE10", 4, 10, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint10", NULL}, 6, 10, 4},
|
||||
{"PE11", 4, 11, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint11", NULL}, 6, 11, 4},
|
||||
{"PE12", 4, 12, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint12", NULL}, 6, 12, 4},
|
||||
{"PE13", 4, 13, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint13", NULL}, 6, 13, 4},
|
||||
{"PE14", 4, 14, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint14", NULL}, 6, 14, 4},
|
||||
{"PE15", 4, 15, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint15", NULL}, 6, 15, 4},
|
||||
|
||||
{"PF0", 5, 0, {"gpio_in", "gpio_out", "mmc0", NULL, "jtag", NULL, NULL, NULL}},
|
||||
{"PF1", 5, 1, {"gpio_in", "gpio_out", "mmc0", NULL, "jtag", NULL, NULL, NULL}},
|
||||
@ -149,25 +149,25 @@ const static struct allwinner_pins a31s_pins[] = {
|
||||
{"PF4", 5, 4, {"gpio_in", "gpio_out", "mmc0", NULL, "uart0", NULL, NULL, NULL}},
|
||||
{"PF5", 5, 5, {"gpio_in", "gpio_out", "mmc0", NULL, "jtag", NULL, NULL, NULL}},
|
||||
|
||||
{"PG0", 6, 0, {"gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint0", NULL}, 6, 0},
|
||||
{"PG1", 6, 1, {"gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint1", NULL}, 6, 1},
|
||||
{"PG2", 6, 2, {"gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint2", NULL}, 6, 2},
|
||||
{"PG3", 6, 3, {"gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint3", NULL}, 6, 3},
|
||||
{"PG4", 6, 4, {"gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint4", NULL}, 6, 4},
|
||||
{"PG5", 6, 5, {"gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint5", NULL}, 6, 5},
|
||||
{"PG6", 6, 6, {"gpio_in", "gpio_out", "uart2", NULL, NULL, NULL, "pg_eint6", NULL}, 6, 6},
|
||||
{"PG7", 6, 7, {"gpio_in", "gpio_out", "uart2", NULL, NULL, NULL, "pg_eint7", NULL}, 6, 7},
|
||||
{"PG8", 6, 8, {"gpio_in", "gpio_out", "uart2", NULL, NULL, NULL, "pg_eint8", NULL}, 6, 8},
|
||||
{"PG9", 6, 9, {"gpio_in", "gpio_out", "uart2", NULL, NULL, NULL, "pg_eint9", NULL}, 6, 9},
|
||||
{"PG10", 6, 10, {"gpio_in", "gpio_out", "i2c3", NULL, NULL, NULL, "pg_eint10", NULL}, 6, 10},
|
||||
{"PG11", 6, 11, {"gpio_in", "gpio_out", "i2c3", NULL, NULL, NULL, "pg_eint11", NULL}, 6, 11},
|
||||
{"PG12", 6, 12, {"gpio_in", "gpio_out", "spi1", "i2s1", NULL, NULL, "pg_eint12", NULL}, 6, 12},
|
||||
{"PG13", 6, 13, {"gpio_in", "gpio_out", "spi1", "i2s1", NULL, NULL, "pg_eint13", NULL}, 6, 13},
|
||||
{"PG14", 6, 14, {"gpio_in", "gpio_out", "spi1", "i2s1", NULL, NULL, "pg_eint14", NULL}, 6, 14},
|
||||
{"PG15", 6, 15, {"gpio_in", "gpio_out", "spi1", "i2s1", NULL, NULL, "pg_eint15", NULL}, 6, 15},
|
||||
{"PG16", 6, 16, {"gpio_in", "gpio_out", "spi1", "i2s1", NULL, NULL, "pg_eint16", NULL}, 6, 16},
|
||||
{"PG17", 6, 17, {"gpio_in", "gpio_out", "uart4", NULL, NULL, NULL, "pg_eint17", NULL}, 6, 17},
|
||||
{"PG18", 6, 18, {"gpio_in", "gpio_out", "uart4", NULL, NULL, NULL, "pg_eint18", NULL}, 6, 18},
|
||||
{"PG0", 6, 0, {"gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint0", NULL}, 6, 0, 6},
|
||||
{"PG1", 6, 1, {"gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint1", NULL}, 6, 1, 6},
|
||||
{"PG2", 6, 2, {"gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint2", NULL}, 6, 2, 6},
|
||||
{"PG3", 6, 3, {"gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint3", NULL}, 6, 3, 6},
|
||||
{"PG4", 6, 4, {"gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint4", NULL}, 6, 4, 6},
|
||||
{"PG5", 6, 5, {"gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint5", NULL}, 6, 5, 6},
|
||||
{"PG6", 6, 6, {"gpio_in", "gpio_out", "uart2", NULL, NULL, NULL, "pg_eint6", NULL}, 6, 6, 6},
|
||||
{"PG7", 6, 7, {"gpio_in", "gpio_out", "uart2", NULL, NULL, NULL, "pg_eint7", NULL}, 6, 7, 6},
|
||||
{"PG8", 6, 8, {"gpio_in", "gpio_out", "uart2", NULL, NULL, NULL, "pg_eint8", NULL}, 6, 8, 6},
|
||||
{"PG9", 6, 9, {"gpio_in", "gpio_out", "uart2", NULL, NULL, NULL, "pg_eint9", NULL}, 6, 9, 6},
|
||||
{"PG10", 6, 10, {"gpio_in", "gpio_out", "i2c3", NULL, NULL, NULL, "pg_eint10", NULL}, 6, 10, 6},
|
||||
{"PG11", 6, 11, {"gpio_in", "gpio_out", "i2c3", NULL, NULL, NULL, "pg_eint11", NULL}, 6, 11, 6},
|
||||
{"PG12", 6, 12, {"gpio_in", "gpio_out", "spi1", "i2s1", NULL, NULL, "pg_eint12", NULL}, 6, 12, 6},
|
||||
{"PG13", 6, 13, {"gpio_in", "gpio_out", "spi1", "i2s1", NULL, NULL, "pg_eint13", NULL}, 6, 13, 6},
|
||||
{"PG14", 6, 14, {"gpio_in", "gpio_out", "spi1", "i2s1", NULL, NULL, "pg_eint14", NULL}, 6, 14, 6},
|
||||
{"PG15", 6, 15, {"gpio_in", "gpio_out", "spi1", "i2s1", NULL, NULL, "pg_eint15", NULL}, 6, 15, 6},
|
||||
{"PG16", 6, 16, {"gpio_in", "gpio_out", "spi1", "i2s1", NULL, NULL, "pg_eint16", NULL}, 6, 16, 6},
|
||||
{"PG17", 6, 17, {"gpio_in", "gpio_out", "uart4", NULL, NULL, NULL, "pg_eint17", NULL}, 6, 17, 6},
|
||||
{"PG18", 6, 18, {"gpio_in", "gpio_out", "uart4", NULL, NULL, NULL, "pg_eint18", NULL}, 6, 18, 6},
|
||||
|
||||
{"PH9", 7, 9, {"gpio_in", "gpio_out", "spi2", "jtag", "pwm1", NULL, NULL, NULL}},
|
||||
{"PH10", 7, 10, {"gpio_in", "gpio_out", "spi2", "jtag", "pwm1", NULL, NULL, NULL}},
|
||||
|
@ -37,14 +37,14 @@ __FBSDID("$FreeBSD$");
|
||||
#ifdef SOC_ALLWINNER_A33
|
||||
|
||||
const static struct allwinner_pins a33_pins[] = {
|
||||
{"PB0", 1, 0, {"gpio_in", "gpio_out", "uart2", "uart0", "pb_eint0", NULL}, 4, 0},
|
||||
{"PB1", 1, 1, {"gpio_in", "gpio_out", "uart2", "uart0", "pb_eint1", NULL}, 4, 1},
|
||||
{"PB2", 1, 2, {"gpio_in", "gpio_out", "uart2", NULL, "pb_eint2", NULL}, 4, 2},
|
||||
{"PB3", 1, 3, {"gpio_in", "gpio_out", "uart2", NULL, "pb_eint3", NULL}, 4, 3},
|
||||
{"PB4", 1, 4, {"gpio_in", "gpio_out", "i2s0", "aif2", "pb_eint4", NULL}, 4, 4},
|
||||
{"PB5", 1, 5, {"gpio_in", "gpio_out", "i2s0", "aif2", "pb_eint5", NULL}, 4, 5},
|
||||
{"PB6", 1, 6, {"gpio_in", "gpio_out", "i2s0", "aif2", "pb_eint6", NULL}, 4, 6},
|
||||
{"PB7", 1, 7, {"gpio_in", "gpio_out", "i2s0", "aif2", "pb_eint7", NULL}, 4, 7},
|
||||
{"PB0", 1, 0, {"gpio_in", "gpio_out", "uart2", "uart0", "pb_eint0", NULL}, 4, 0, 1},
|
||||
{"PB1", 1, 1, {"gpio_in", "gpio_out", "uart2", "uart0", "pb_eint1", NULL}, 4, 1, 1},
|
||||
{"PB2", 1, 2, {"gpio_in", "gpio_out", "uart2", NULL, "pb_eint2", NULL}, 4, 2, 1},
|
||||
{"PB3", 1, 3, {"gpio_in", "gpio_out", "uart2", NULL, "pb_eint3", NULL}, 4, 3, 1},
|
||||
{"PB4", 1, 4, {"gpio_in", "gpio_out", "i2s0", "aif2", "pb_eint4", NULL}, 4, 4, 1},
|
||||
{"PB5", 1, 5, {"gpio_in", "gpio_out", "i2s0", "aif2", "pb_eint5", NULL}, 4, 5, 1},
|
||||
{"PB6", 1, 6, {"gpio_in", "gpio_out", "i2s0", "aif2", "pb_eint6", NULL}, 4, 6, 1},
|
||||
{"PB7", 1, 7, {"gpio_in", "gpio_out", "i2s0", "aif2", "pb_eint7", NULL}, 4, 7, 1},
|
||||
|
||||
{"PC0", 2, 0, {"gpio_in", "gpio_out", "nand0", "spi0", NULL, NULL, NULL, NULL}},
|
||||
{"PC1", 2, 1, {"gpio_in", "gpio_out", "nand0", "spi0", NULL, NULL, NULL, NULL}},
|
||||
@ -113,20 +113,20 @@ const static struct allwinner_pins a33_pins[] = {
|
||||
{"PF4", 5, 4, {"gpio_in", "gpio_out", "mmc0", "uart0", NULL, NULL, NULL}},
|
||||
{"PF5", 5, 5, {"gpio_in", "gpio_out", "mmc0", "jtag", NULL, NULL, NULL}},
|
||||
|
||||
{"PG0", 6, 0, {"gpio_in", "gpio_out", "mmc1", NULL, "pg_eint0", NULL}, 4, 0},
|
||||
{"PG1", 6, 1, {"gpio_in", "gpio_out", "mmc1", NULL, "pg_eint1", NULL}, 4, 1},
|
||||
{"PG2", 6, 2, {"gpio_in", "gpio_out", "mmc1", NULL, "pg_eint2", NULL}, 4, 2},
|
||||
{"PG3", 6, 3, {"gpio_in", "gpio_out", "mmc1", NULL, "pg_eint3", NULL}, 4, 3},
|
||||
{"PG4", 6, 4, {"gpio_in", "gpio_out", "mmc1", NULL, "pg_eint4", NULL}, 4, 4},
|
||||
{"PG5", 6, 5, {"gpio_in", "gpio_out", "mmc1", NULL, "pg_eint5", NULL}, 4, 5},
|
||||
{"PG6", 6, 6, {"gpio_in", "gpio_out", "uart1", NULL, "pg_eint6", NULL}, 4, 6},
|
||||
{"PG7", 6, 7, {"gpio_in", "gpio_out", "uart1", NULL, "pg_eint7", NULL}, 4, 7},
|
||||
{"PG8", 6, 8, {"gpio_in", "gpio_out", "uart1", NULL, "pg_eint8", NULL}, 4, 8},
|
||||
{"PG9", 6, 9, {"gpio_in", "gpio_out", "uart1", NULL, "pg_eint9", NULL}, 4, 9},
|
||||
{"PG10", 6, 10, {"gpio_in", "gpio_out", "i2s1", "aif3", "pg_eint10", NULL}, 4, 10},
|
||||
{"PG11", 6, 11, {"gpio_in", "gpio_out", "i2s1", "aif3", "pg_eint11", NULL}, 4, 11},
|
||||
{"PG12", 6, 12, {"gpio_in", "gpio_out", "i2s1", "aif3", "pg_eint12", NULL}, 4, 12},
|
||||
{"PG13", 6, 13, {"gpio_in", "gpio_out", "i2s1", "aif3", "pg_eint13", NULL}, 4, 13},
|
||||
{"PG0", 6, 0, {"gpio_in", "gpio_out", "mmc1", NULL, "pg_eint0", NULL}, 4, 0, 6},
|
||||
{"PG1", 6, 1, {"gpio_in", "gpio_out", "mmc1", NULL, "pg_eint1", NULL}, 4, 1, 6},
|
||||
{"PG2", 6, 2, {"gpio_in", "gpio_out", "mmc1", NULL, "pg_eint2", NULL}, 4, 2, 6},
|
||||
{"PG3", 6, 3, {"gpio_in", "gpio_out", "mmc1", NULL, "pg_eint3", NULL}, 4, 3, 6},
|
||||
{"PG4", 6, 4, {"gpio_in", "gpio_out", "mmc1", NULL, "pg_eint4", NULL}, 4, 4, 6},
|
||||
{"PG5", 6, 5, {"gpio_in", "gpio_out", "mmc1", NULL, "pg_eint5", NULL}, 4, 5, 6},
|
||||
{"PG6", 6, 6, {"gpio_in", "gpio_out", "uart1", NULL, "pg_eint6", NULL}, 4, 6, 6},
|
||||
{"PG7", 6, 7, {"gpio_in", "gpio_out", "uart1", NULL, "pg_eint7", NULL}, 4, 7, 6},
|
||||
{"PG8", 6, 8, {"gpio_in", "gpio_out", "uart1", NULL, "pg_eint8", NULL}, 4, 8, 6},
|
||||
{"PG9", 6, 9, {"gpio_in", "gpio_out", "uart1", NULL, "pg_eint9", NULL}, 4, 9, 6},
|
||||
{"PG10", 6, 10, {"gpio_in", "gpio_out", "i2s1", "aif3", "pg_eint10", NULL}, 4, 10, 6},
|
||||
{"PG11", 6, 11, {"gpio_in", "gpio_out", "i2s1", "aif3", "pg_eint11", NULL}, 4, 11, 6},
|
||||
{"PG12", 6, 12, {"gpio_in", "gpio_out", "i2s1", "aif3", "pg_eint12", NULL}, 4, 12, 6},
|
||||
{"PG13", 6, 13, {"gpio_in", "gpio_out", "i2s1", "aif3", "pg_eint13", NULL}, 4, 13, 6},
|
||||
|
||||
{"PH0", 7, 0, {"gpio_in", "gpio_out", "pwm0", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PH1", 7, 1, {"gpio_in", "gpio_out", "pwm1", NULL, NULL, NULL, NULL, NULL}},
|
||||
|
@ -40,16 +40,16 @@ __FBSDID("$FreeBSD$");
|
||||
#ifdef SOC_ALLWINNER_A64
|
||||
|
||||
static const struct allwinner_pins a64_pins[] = {
|
||||
{ "PB0", 1, 0, { "gpio_in", "gpio_out", "uart2", NULL, "jtag", NULL, "pb_eint0" }, 6, 0},
|
||||
{ "PB1", 1, 1, { "gpio_in", "gpio_out", "uart2", NULL, "jtag", "sim", "pb_eint1" }, 6, 1},
|
||||
{ "PB2", 1, 2, { "gpio_in", "gpio_out", "uart2", NULL, "jtag", "sim", "pb_eint2" }, 6, 2},
|
||||
{ "PB3", 1, 3, { "gpio_in", "gpio_out", "uart2", "i2s0", "jtag", "sim", "pb_eint3" }, 6, 3},
|
||||
{ "PB4", 1, 4, { "gpio_in", "gpio_out", "aif2", "pcm0", NULL, "sim", "pb_eint4" }, 6, 4},
|
||||
{ "PB5", 1, 5, { "gpio_in", "gpio_out", "aif2", "pcm0", NULL, "sim", "pb_eint5" }, 6, 5},
|
||||
{ "PB6", 1, 6, { "gpio_in", "gpio_out", "aif2", "pcm0", NULL, "sim", "pb_eint6" }, 6, 6},
|
||||
{ "PB7", 1, 7, { "gpio_in", "gpio_out", "aif2", "pcm0", NULL, "sim", "pb_eint7" }, 6, 7},
|
||||
{ "PB8", 1, 8, { "gpio_in", "gpio_out", NULL, NULL, "uart0", NULL, "pb_eint8" }, 6, 8},
|
||||
{ "PB9", 1, 9, { "gpio_in", "gpio_out", NULL, NULL, "uart0", NULL, "pb_eint9" }, 6, 9},
|
||||
{ "PB0", 1, 0, { "gpio_in", "gpio_out", "uart2", NULL, "jtag", NULL, "pb_eint0" }, 6, 0, 0},
|
||||
{ "PB1", 1, 1, { "gpio_in", "gpio_out", "uart2", NULL, "jtag", "sim", "pb_eint1" }, 6, 1, 0},
|
||||
{ "PB2", 1, 2, { "gpio_in", "gpio_out", "uart2", NULL, "jtag", "sim", "pb_eint2" }, 6, 2, 0},
|
||||
{ "PB3", 1, 3, { "gpio_in", "gpio_out", "uart2", "i2s0", "jtag", "sim", "pb_eint3" }, 6, 3, 0},
|
||||
{ "PB4", 1, 4, { "gpio_in", "gpio_out", "aif2", "pcm0", NULL, "sim", "pb_eint4" }, 6, 4, 0},
|
||||
{ "PB5", 1, 5, { "gpio_in", "gpio_out", "aif2", "pcm0", NULL, "sim", "pb_eint5" }, 6, 5, 0},
|
||||
{ "PB6", 1, 6, { "gpio_in", "gpio_out", "aif2", "pcm0", NULL, "sim", "pb_eint6" }, 6, 6, 0},
|
||||
{ "PB7", 1, 7, { "gpio_in", "gpio_out", "aif2", "pcm0", NULL, "sim", "pb_eint7" }, 6, 7, 0},
|
||||
{ "PB8", 1, 8, { "gpio_in", "gpio_out", NULL, NULL, "uart0", NULL, "pb_eint8" }, 6, 8, 0},
|
||||
{ "PB9", 1, 9, { "gpio_in", "gpio_out", NULL, NULL, "uart0", NULL, "pb_eint9" }, 6, 9, 0},
|
||||
|
||||
{ "PC0", 2, 0, { "gpio_in", "gpio_out", "nand", NULL, "spi0" } },
|
||||
{ "PC1", 2, 1, { "gpio_in", "gpio_out", "nand", "mmc2", "spi0" } },
|
||||
@ -122,33 +122,33 @@ static const struct allwinner_pins a64_pins[] = {
|
||||
{ "PF5", 5, 5, { "gpio_in", "gpio_out", "mmc0", "jtag" } },
|
||||
{ "PF6", 5, 6, { "gpio_in", "gpio_out" } },
|
||||
|
||||
{ "PG0", 6, 0, { "gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint0" }, 6, 0},
|
||||
{ "PG1", 6, 1, { "gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint1" }, 6, 1},
|
||||
{ "PG2", 6, 2, { "gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint2" }, 6, 2},
|
||||
{ "PG3", 6, 3, { "gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint3" }, 6, 3},
|
||||
{ "PG4", 6, 4, { "gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint4" }, 6, 4},
|
||||
{ "PG5", 6, 5, { "gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint5" }, 6, 5},
|
||||
{ "PG6", 6, 6, { "gpio_in", "gpio_out", "uart1", NULL, NULL, NULL, "pg_eint6" }, 6, 6},
|
||||
{ "PG7", 6, 7, { "gpio_in", "gpio_out", "uart1", NULL, NULL, NULL, "pg_eint7" }, 6, 7},
|
||||
{ "PG8", 6, 8, { "gpio_in", "gpio_out", "uart1", NULL, NULL, NULL, "pg_eint8" }, 6, 8},
|
||||
{ "PG9", 6, 9, { "gpio_in", "gpio_out", "uart1", NULL, NULL, NULL, "pg_eint9" }, 6, 9},
|
||||
{ "PG10", 6, 10, { "gpio_in", "gpio_out", "aif3", "pcm1", NULL, NULL, "pg_eint10" }, 6, 10},
|
||||
{ "PG11", 6, 11, { "gpio_in", "gpio_out", "aif3", "pcm1", NULL, NULL, "pg_eint11" }, 6, 11},
|
||||
{ "PG12", 6, 12, { "gpio_in", "gpio_out", "aif3", "pcm1", NULL, NULL, "pg_eint12" }, 6, 12},
|
||||
{ "PG13", 6, 13, { "gpio_in", "gpio_out", "aif3", "pcm1", NULL, NULL, "pg_eint13" }, 6, 13},
|
||||
{ "PG0", 6, 0, { "gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint0" }, 6, 0, 1},
|
||||
{ "PG1", 6, 1, { "gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint1" }, 6, 1, 1},
|
||||
{ "PG2", 6, 2, { "gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint2" }, 6, 2, 1},
|
||||
{ "PG3", 6, 3, { "gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint3" }, 6, 3, 1},
|
||||
{ "PG4", 6, 4, { "gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint4" }, 6, 4, 1},
|
||||
{ "PG5", 6, 5, { "gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint5" }, 6, 5, 1},
|
||||
{ "PG6", 6, 6, { "gpio_in", "gpio_out", "uart1", NULL, NULL, NULL, "pg_eint6" }, 6, 6, 1},
|
||||
{ "PG7", 6, 7, { "gpio_in", "gpio_out", "uart1", NULL, NULL, NULL, "pg_eint7" }, 6, 7, 1},
|
||||
{ "PG8", 6, 8, { "gpio_in", "gpio_out", "uart1", NULL, NULL, NULL, "pg_eint8" }, 6, 8, 1},
|
||||
{ "PG9", 6, 9, { "gpio_in", "gpio_out", "uart1", NULL, NULL, NULL, "pg_eint9" }, 6, 9, 1},
|
||||
{ "PG10", 6, 10, { "gpio_in", "gpio_out", "aif3", "pcm1", NULL, NULL, "pg_eint10" }, 6, 10, 1},
|
||||
{ "PG11", 6, 11, { "gpio_in", "gpio_out", "aif3", "pcm1", NULL, NULL, "pg_eint11" }, 6, 11, 1},
|
||||
{ "PG12", 6, 12, { "gpio_in", "gpio_out", "aif3", "pcm1", NULL, NULL, "pg_eint12" }, 6, 12, 1},
|
||||
{ "PG13", 6, 13, { "gpio_in", "gpio_out", "aif3", "pcm1", NULL, NULL, "pg_eint13" }, 6, 13, 1},
|
||||
|
||||
{ "PH0", 7, 0, { "gpio_in", "gpio_out", "i2c0", NULL, NULL, NULL, "ph_eint0" }, 6, 0},
|
||||
{ "PH1", 7, 1, { "gpio_in", "gpio_out", "i2c0", NULL, NULL, NULL, "ph_eint1" }, 6, 1},
|
||||
{ "PH2", 7, 2, { "gpio_in", "gpio_out", "i2c1", NULL, NULL, NULL, "ph_eint2" }, 6, 2},
|
||||
{ "PH3", 7, 3, { "gpio_in", "gpio_out", "i2c1", NULL, NULL, NULL, "ph_eint3" }, 6, 3},
|
||||
{ "PH4", 7, 4, { "gpio_in", "gpio_out", "uart3", NULL, NULL, NULL, "ph_eint4" }, 6, 4},
|
||||
{ "PH5", 7, 5, { "gpio_in", "gpio_out", "uart3", NULL, NULL, NULL, "ph_eint5" }, 6, 5},
|
||||
{ "PH6", 7, 6, { "gpio_in", "gpio_out", "uart3", NULL, NULL, NULL, "ph_eint6" }, 6, 6},
|
||||
{ "PH7", 7, 7, { "gpio_in", "gpio_out", "uart3", NULL, NULL, NULL, "ph_eint7" }, 6, 7},
|
||||
{ "PH8", 7, 8, { "gpio_in", "gpio_out", "owa", NULL, NULL, NULL, "ph_eint8" }, 6, 8},
|
||||
{ "PH9", 7, 9, { "gpio_in", "gpio_out", NULL, NULL, NULL, NULL, "ph_eint9" }, 6, 9},
|
||||
{ "PH10", 7, 10, { "gpio_in", "gpio_out", "mic", NULL, NULL, NULL, "ph_eint10" }, 6, 10},
|
||||
{ "PH11", 7, 11, { "gpio_in", "gpio_out", "mic", NULL, NULL, NULL, "ph_eint11" }, 6, 11},
|
||||
{ "PH0", 7, 0, { "gpio_in", "gpio_out", "i2c0", NULL, NULL, NULL, "ph_eint0" }, 6, 0, 2},
|
||||
{ "PH1", 7, 1, { "gpio_in", "gpio_out", "i2c0", NULL, NULL, NULL, "ph_eint1" }, 6, 1, 2},
|
||||
{ "PH2", 7, 2, { "gpio_in", "gpio_out", "i2c1", NULL, NULL, NULL, "ph_eint2" }, 6, 2, 2},
|
||||
{ "PH3", 7, 3, { "gpio_in", "gpio_out", "i2c1", NULL, NULL, NULL, "ph_eint3" }, 6, 3, 2},
|
||||
{ "PH4", 7, 4, { "gpio_in", "gpio_out", "uart3", NULL, NULL, NULL, "ph_eint4" }, 6, 4, 2},
|
||||
{ "PH5", 7, 5, { "gpio_in", "gpio_out", "uart3", NULL, NULL, NULL, "ph_eint5" }, 6, 5, 2},
|
||||
{ "PH6", 7, 6, { "gpio_in", "gpio_out", "uart3", NULL, NULL, NULL, "ph_eint6" }, 6, 6, 2},
|
||||
{ "PH7", 7, 7, { "gpio_in", "gpio_out", "uart3", NULL, NULL, NULL, "ph_eint7" }, 6, 7, 2},
|
||||
{ "PH8", 7, 8, { "gpio_in", "gpio_out", "owa", NULL, NULL, NULL, "ph_eint8" }, 6, 8, 2},
|
||||
{ "PH9", 7, 9, { "gpio_in", "gpio_out", NULL, NULL, NULL, NULL, "ph_eint9" }, 6, 9, 2},
|
||||
{ "PH10", 7, 10, { "gpio_in", "gpio_out", "mic", NULL, NULL, NULL, "ph_eint10" }, 6, 10, 2},
|
||||
{ "PH11", 7, 11, { "gpio_in", "gpio_out", "mic", NULL, NULL, NULL, "ph_eint11" }, 6, 11, 2},
|
||||
};
|
||||
|
||||
const struct allwinner_padconf a64_padconf = {
|
||||
|
@ -40,19 +40,19 @@ __FBSDID("$FreeBSD$");
|
||||
#ifdef SOC_ALLWINNER_A64
|
||||
|
||||
static const struct allwinner_pins a64_r_pins[] = {
|
||||
{ "PL0", 0, 0, { "gpio_in", "gpio_out", "s_rsb", "s_i2c", NULL, NULL, "pl_eint0" }, 6, 0},
|
||||
{ "PL1", 0, 1, { "gpio_in", "gpio_out", "s_rsb", "s_i2c", NULL, NULL, "pl_eint1" }, 6, 1},
|
||||
{ "PL2", 0, 2, { "gpio_in", "gpio_out", "s_uart", NULL, NULL, NULL, "pl_eint2" }, 6, 2},
|
||||
{ "PL3", 0, 3, { "gpio_in", "gpio_out", "s_uart", NULL, NULL, NULL, "pl_eint3" }, 6, 3},
|
||||
{ "PL4", 0, 4, { "gpio_in", "gpio_out", "s_jtag", NULL, NULL, NULL, "pl_eint4" }, 6, 4},
|
||||
{ "PL5", 0, 5, { "gpio_in", "gpio_out", "s_jtag", NULL, NULL, NULL, "pl_eint5" }, 6, 5},
|
||||
{ "PL6", 0, 6, { "gpio_in", "gpio_out", "s_jtag", NULL, NULL, NULL, "pl_eint6" }, 6, 6},
|
||||
{ "PL7", 0, 7, { "gpio_in", "gpio_out", "s_jtag", NULL, NULL, NULL, "pl_eint7" }, 6, 7},
|
||||
{ "PL8", 0, 8, { "gpio_in", "gpio_out", "s_i2c", NULL, NULL, NULL, "pl_eint8" }, 6, 8},
|
||||
{ "PL9", 0, 9, { "gpio_in", "gpio_out", "s_i2c", NULL, NULL, NULL, "pl_eint9" }, 6, 9},
|
||||
{ "PL10", 0, 10, { "gpio_in", "gpio_out", "s_pwm", NULL, NULL, NULL, "pl_eint10" }, 6, 10},
|
||||
{ "PL11", 0, 11, { "gpio_in", "gpio_out", "s_cir", NULL, NULL, NULL, "pl_eint11" }, 6, 11},
|
||||
{ "PL12", 0, 12, { "gpio_in", "gpio_out", NULL, NULL, NULL, NULL, "pl_eint12" }, 6, 12},
|
||||
{ "PL0", 0, 0, { "gpio_in", "gpio_out", "s_rsb", "s_i2c", NULL, NULL, "pl_eint0" }, 6, 0, 0},
|
||||
{ "PL1", 0, 1, { "gpio_in", "gpio_out", "s_rsb", "s_i2c", NULL, NULL, "pl_eint1" }, 6, 1, 0},
|
||||
{ "PL2", 0, 2, { "gpio_in", "gpio_out", "s_uart", NULL, NULL, NULL, "pl_eint2" }, 6, 2, 0},
|
||||
{ "PL3", 0, 3, { "gpio_in", "gpio_out", "s_uart", NULL, NULL, NULL, "pl_eint3" }, 6, 3, 0},
|
||||
{ "PL4", 0, 4, { "gpio_in", "gpio_out", "s_jtag", NULL, NULL, NULL, "pl_eint4" }, 6, 4, 0},
|
||||
{ "PL5", 0, 5, { "gpio_in", "gpio_out", "s_jtag", NULL, NULL, NULL, "pl_eint5" }, 6, 5, 0},
|
||||
{ "PL6", 0, 6, { "gpio_in", "gpio_out", "s_jtag", NULL, NULL, NULL, "pl_eint6" }, 6, 6, 0},
|
||||
{ "PL7", 0, 7, { "gpio_in", "gpio_out", "s_jtag", NULL, NULL, NULL, "pl_eint7" }, 6, 7, 0},
|
||||
{ "PL8", 0, 8, { "gpio_in", "gpio_out", "s_i2c", NULL, NULL, NULL, "pl_eint8" }, 6, 8, 0},
|
||||
{ "PL9", 0, 9, { "gpio_in", "gpio_out", "s_i2c", NULL, NULL, NULL, "pl_eint9" }, 6, 9, 0},
|
||||
{ "PL10", 0, 10, { "gpio_in", "gpio_out", "s_pwm", NULL, NULL, NULL, "pl_eint10" }, 6, 10, 0},
|
||||
{ "PL11", 0, 11, { "gpio_in", "gpio_out", "s_cir", NULL, NULL, NULL, "pl_eint11" }, 6, 11, 0},
|
||||
{ "PL12", 0, 12, { "gpio_in", "gpio_out", NULL, NULL, NULL, NULL, "pl_eint12" }, 6, 12, 0},
|
||||
};
|
||||
|
||||
const struct allwinner_padconf a64_r_padconf = {
|
||||
|
@ -38,17 +38,17 @@ __FBSDID("$FreeBSD$");
|
||||
#ifdef SOC_ALLWINNER_A83T
|
||||
|
||||
static const struct allwinner_pins a83t_pins[] = {
|
||||
{ "PB0", 1, 0, { "gpio_in", "gpio_out", "uart2", "jtag", NULL, NULL, "eint" } },
|
||||
{ "PB1", 1, 1, { "gpio_in", "gpio_out", "uart2", "jtag", NULL, NULL, "eint" } },
|
||||
{ "PB2", 1, 2, { "gpio_in", "gpio_out", "uart2", "jtag", NULL, NULL, "eint" } },
|
||||
{ "PB3", 1, 3, { "gpio_in", "gpio_out", "uart2", "jtag", NULL, NULL, "eint" } },
|
||||
{ "PB4", 1, 4, { "gpio_in", "gpio_out", "i2s0", "tdm", NULL, NULL, "eint" } },
|
||||
{ "PB5", 1, 5, { "gpio_in", "gpio_out", "i2s0", "tdm", NULL, NULL, "eint" } },
|
||||
{ "PB6", 1, 6, { "gpio_in", "gpio_out", "i2s0", "tdm", NULL, NULL, "eint" } },
|
||||
{ "PB7", 1, 7, { "gpio_in", "gpio_out", "i2s0", "tdm", NULL, NULL, "eint" } },
|
||||
{ "PB8", 1, 8, { "gpio_in", "gpio_out", "i2s0", "tdm", NULL, NULL, "eint" } },
|
||||
{ "PB9", 1, 9, { "gpio_in", "gpio_out", "uart0", NULL, NULL, NULL, "eint" } },
|
||||
{ "PB10", 1, 10, { "gpio_in", "gpio_out", "uart0", NULL, NULL, NULL, "eint" } },
|
||||
{ "PB0", 1, 0, { "gpio_in", "gpio_out", "uart2", "jtag", NULL, NULL, "pb_eint0" }, 6, 0, 0},
|
||||
{ "PB1", 1, 1, { "gpio_in", "gpio_out", "uart2", "jtag", NULL, NULL, "pb_eint1" }, 6, 1, 0},
|
||||
{ "PB2", 1, 2, { "gpio_in", "gpio_out", "uart2", "jtag", NULL, NULL, "pb_eint2" }, 6, 2, 0},
|
||||
{ "PB3", 1, 3, { "gpio_in", "gpio_out", "uart2", "jtag", NULL, NULL, "pb_eint3" }, 6, 3, 0},
|
||||
{ "PB4", 1, 4, { "gpio_in", "gpio_out", "i2s0", "tdm", NULL, NULL, "pb_eint4" }, 6, 4, 0},
|
||||
{ "PB5", 1, 5, { "gpio_in", "gpio_out", "i2s0", "tdm", NULL, NULL, "pb_eint5" }, 6, 5, 0},
|
||||
{ "PB6", 1, 6, { "gpio_in", "gpio_out", "i2s0", "tdm", NULL, NULL, "pb_eint6" }, 6, 6, 0},
|
||||
{ "PB7", 1, 7, { "gpio_in", "gpio_out", "i2s0", "tdm", NULL, NULL, "pb_eint7" }, 6, 7, 0},
|
||||
{ "PB8", 1, 8, { "gpio_in", "gpio_out", "i2s0", "tdm", NULL, NULL, "pb_eint8" }, 6, 8, 0},
|
||||
{ "PB9", 1, 9, { "gpio_in", "gpio_out", "uart0", NULL, NULL, NULL, "pb_eint9" }, 6, 9, 0},
|
||||
{ "PB10", 1, 10, { "gpio_in", "gpio_out", "uart0", NULL, NULL, NULL, "pb_eint10" }, 6, 10, 0},
|
||||
|
||||
{ "PC0", 2, 0, { "gpio_in", "gpio_out", "nand", "spi0" } },
|
||||
{ "PC1", 2, 1, { "gpio_in", "gpio_out", "nand", "spi0" } },
|
||||
@ -124,33 +124,33 @@ static const struct allwinner_pins a83t_pins[] = {
|
||||
{ "PF5", 5, 5, { "gpio_in", "gpio_out", "mmc0", "jtag" } },
|
||||
{ "PF6", 5, 6, { "gpio_in", "gpio_out" } },
|
||||
|
||||
{ "PG0", 6, 0, { "gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "eint" } },
|
||||
{ "PG1", 6, 1, { "gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "eint" } },
|
||||
{ "PG2", 6, 2, { "gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "eint" } },
|
||||
{ "PG3", 6, 3, { "gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "eint" } },
|
||||
{ "PG4", 6, 4, { "gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "eint" } },
|
||||
{ "PG5", 6, 5, { "gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "eint" } },
|
||||
{ "PG6", 6, 6, { "gpio_in", "gpio_out", "uart1", "spi1", NULL, NULL, "eint" } },
|
||||
{ "PG7", 6, 7, { "gpio_in", "gpio_out", "uart1", "spi1", NULL, NULL, "eint" } },
|
||||
{ "PG8", 6, 8, { "gpio_in", "gpio_out", "uart1", "spi1", NULL, NULL, "eint" } },
|
||||
{ "PG9", 6, 9, { "gpio_in", "gpio_out", "uart1", "spi1", NULL, NULL, "eint" } },
|
||||
{ "PG10", 6, 10, { "gpio_in", "gpio_out", "i2s1", "uart3", NULL, NULL, "eint" } },
|
||||
{ "PG11", 6, 11, { "gpio_in", "gpio_out", "i2s1", "uart3", NULL, NULL, "eint" } },
|
||||
{ "PG12", 6, 12, { "gpio_in", "gpio_out", "i2s1", "uart3", NULL, NULL, "eint" } },
|
||||
{ "PG13", 6, 13, { "gpio_in", "gpio_out", "i2s1", "uart3", NULL, NULL, "eint" } },
|
||||
{ "PG0", 6, 0, { "gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint0" }, 6, 0, 1},
|
||||
{ "PG1", 6, 1, { "gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint1" }, 6, 1, 1},
|
||||
{ "PG2", 6, 2, { "gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint2" }, 6, 2, 1},
|
||||
{ "PG3", 6, 3, { "gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint3" }, 6, 3, 1},
|
||||
{ "PG4", 6, 4, { "gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint4" }, 6, 4, 1},
|
||||
{ "PG5", 6, 5, { "gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint5" }, 6, 5, 1},
|
||||
{ "PG6", 6, 6, { "gpio_in", "gpio_out", "uart1", "spi1", NULL, NULL, "pg_eint6" }, 6, 6, 1},
|
||||
{ "PG7", 6, 7, { "gpio_in", "gpio_out", "uart1", "spi1", NULL, NULL, "pg_eint7" }, 6, 7, 1},
|
||||
{ "PG8", 6, 8, { "gpio_in", "gpio_out", "uart1", "spi1", NULL, NULL, "pg_eint8" }, 6, 8, 1},
|
||||
{ "PG9", 6, 9, { "gpio_in", "gpio_out", "uart1", "spi1", NULL, NULL, "pg_eint9" }, 6, 9, 1},
|
||||
{ "PG10", 6, 10, { "gpio_in", "gpio_out", "i2s1", "uart3", NULL, NULL, "pg_eint10" }, 6, 10, 1},
|
||||
{ "PG11", 6, 11, { "gpio_in", "gpio_out", "i2s1", "uart3", NULL, NULL, "pg_eint11" }, 6, 11, 1},
|
||||
{ "PG12", 6, 12, { "gpio_in", "gpio_out", "i2s1", "uart3", NULL, NULL, "pg_eint12" }, 6, 12, 1},
|
||||
{ "PG13", 6, 13, { "gpio_in", "gpio_out", "i2s1", "uart3", NULL, NULL, "pg_eint13" }, 6, 13, 1},
|
||||
|
||||
{ "PH0", 7, 0, { "gpio_in", "gpio_out", "i2c0", NULL, NULL, NULL, "eint" } },
|
||||
{ "PH1", 7, 1, { "gpio_in", "gpio_out", "i2c0", NULL, NULL, NULL, "eint" } },
|
||||
{ "PH2", 7, 2, { "gpio_in", "gpio_out", "i2c1", NULL, NULL, NULL, "eint" } },
|
||||
{ "PH3", 7, 3, { "gpio_in", "gpio_out", "i2c1", NULL, NULL, NULL, "eint" } },
|
||||
{ "PH4", 7, 4, { "gpio_in", "gpio_out", "i2c2", NULL, NULL, NULL, "eint" } },
|
||||
{ "PH5", 7, 5, { "gpio_in", "gpio_out", "i2c2", NULL, NULL, NULL, "eint" } },
|
||||
{ "PH6", 7, 6, { "gpio_in", "gpio_out", "hdmiddc", NULL, NULL, NULL, "eint" } },
|
||||
{ "PH7", 7, 7, { "gpio_in", "gpio_out", "hdmiddc", NULL, NULL, NULL, "eint" } },
|
||||
{ "PH8", 7, 8, { "gpio_in", "gpio_out", "hdmiddc", NULL, NULL, NULL, "eint" } },
|
||||
{ "PH9", 7, 9, { "gpio_in", "gpio_out", NULL, NULL, NULL, NULL, "eint" } },
|
||||
{ "PH10", 7, 10, { "gpio_in", "gpio_out", NULL, NULL, NULL, NULL, "eint" } },
|
||||
{ "PH11", 7, 11, { "gpio_in", "gpio_out", NULL, NULL, NULL, NULL, "eint" } },
|
||||
{ "PH0", 7, 0, { "gpio_in", "gpio_out", "i2c0", NULL, NULL, NULL, "ph_eint0" }, 6, 0, 2},
|
||||
{ "PH1", 7, 1, { "gpio_in", "gpio_out", "i2c0", NULL, NULL, NULL, "ph_eint1" }, 6, 1, 2},
|
||||
{ "PH2", 7, 2, { "gpio_in", "gpio_out", "i2c1", NULL, NULL, NULL, "ph_eint2" }, 6, 2, 2},
|
||||
{ "PH3", 7, 3, { "gpio_in", "gpio_out", "i2c1", NULL, NULL, NULL, "ph_eint3" }, 6, 3, 2},
|
||||
{ "PH4", 7, 4, { "gpio_in", "gpio_out", "i2c2", NULL, NULL, NULL, "ph_eint4" }, 6, 4, 2},
|
||||
{ "PH5", 7, 5, { "gpio_in", "gpio_out", "i2c2", NULL, NULL, NULL, "ph_eint5" }, 6, 5, 2},
|
||||
{ "PH6", 7, 6, { "gpio_in", "gpio_out", "hdmiddc", NULL, NULL, NULL, "ph_eint6" }, 6, 6, 2},
|
||||
{ "PH7", 7, 7, { "gpio_in", "gpio_out", "hdmiddc", NULL, NULL, NULL, "ph_eint7" }, 6, 7, 2},
|
||||
{ "PH8", 7, 8, { "gpio_in", "gpio_out", "hdmiddc", NULL, NULL, NULL, "ph_eint8" }, 6, 8, 2},
|
||||
{ "PH9", 7, 9, { "gpio_in", "gpio_out", NULL, NULL, NULL, NULL, "ph_eint9" }, 6, 9, 2},
|
||||
{ "PH10", 7, 10, { "gpio_in", "gpio_out", NULL, NULL, NULL, NULL, "ph_eint10" }, 6, 10, 2},
|
||||
{ "PH11", 7, 11, { "gpio_in", "gpio_out", NULL, NULL, NULL, NULL, "ph_eint11" }, 6, 11, 2},
|
||||
};
|
||||
|
||||
const struct allwinner_padconf a83t_padconf = {
|
||||
|
@ -37,6 +37,7 @@ struct allwinner_pins {
|
||||
const char *functions[8];
|
||||
uint8_t eint_func;
|
||||
uint8_t eint_num;
|
||||
uint8_t eint_bank;
|
||||
};
|
||||
|
||||
struct allwinner_padconf {
|
||||
|
@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/gpio.h>
|
||||
#include <sys/proc.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/resource.h>
|
||||
@ -61,10 +62,17 @@ __FBSDID("$FreeBSD$");
|
||||
#include "opt_soc.h"
|
||||
#endif
|
||||
|
||||
#ifdef INTRNG
|
||||
#include "pic_if.h"
|
||||
#endif
|
||||
|
||||
#include "gpio_if.h"
|
||||
|
||||
#define AW_GPIO_DEFAULT_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | \
|
||||
GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN)
|
||||
GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN);
|
||||
|
||||
#define AW_GPIO_INTR_CAPS (GPIO_INTR_LEVEL_LOW | GPIO_INTR_LEVEL_HIGH | \
|
||||
GPIO_INTR_EDGE_RISING | GPIO_INTR_EDGE_FALLING | GPIO_INTR_EDGE_BOTH)
|
||||
|
||||
#define AW_GPIO_NONE 0
|
||||
#define AW_GPIO_PULLUP 1
|
||||
@ -249,17 +257,45 @@ struct clk_list {
|
||||
clk_t clk;
|
||||
};
|
||||
|
||||
#ifdef INTRNG
|
||||
struct gpio_irqsrc {
|
||||
struct intr_irqsrc isrc;
|
||||
u_int irq;
|
||||
uint32_t mode;
|
||||
uint32_t pin;
|
||||
uint32_t bank;
|
||||
uint32_t intnum;
|
||||
uint32_t intfunc;
|
||||
uint32_t oldfunc;
|
||||
bool enabled;
|
||||
};
|
||||
#endif
|
||||
|
||||
#define AW_GPIO_MEMRES 0
|
||||
#define AW_GPIO_IRQRES 1
|
||||
#define AW_GPIO_RESSZ 2
|
||||
|
||||
struct aw_gpio_softc {
|
||||
device_t sc_dev;
|
||||
device_t sc_busdev;
|
||||
struct resource * sc_res[AW_GPIO_RESSZ];
|
||||
struct mtx sc_mtx;
|
||||
struct resource * sc_mem_res;
|
||||
struct resource * sc_irq_res;
|
||||
bus_space_tag_t sc_bst;
|
||||
bus_space_handle_t sc_bsh;
|
||||
void * sc_intrhand;
|
||||
struct aw_gpio_conf *conf;
|
||||
TAILQ_HEAD(, clk_list) clk_list;
|
||||
|
||||
#ifdef INTRNG
|
||||
struct gpio_irqsrc *gpio_pic_irqsrc;
|
||||
int nirqs;
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct resource_spec aw_gpio_res_spec[] = {
|
||||
{ SYS_RES_MEMORY, 0, RF_ACTIVE },
|
||||
{ SYS_RES_IRQ, 0, RF_ACTIVE | RF_SHAREABLE },
|
||||
{ -1, 0, 0 }
|
||||
};
|
||||
|
||||
#define AW_GPIO_LOCK(_sc) mtx_lock_spin(&(_sc)->sc_mtx)
|
||||
@ -271,14 +307,18 @@ struct aw_gpio_softc {
|
||||
#define AW_GPIO_GP_DRV(_bank, _idx) 0x14 + ((_bank) * 0x24) + ((_idx) << 2)
|
||||
#define AW_GPIO_GP_PUL(_bank, _idx) 0x1c + ((_bank) * 0x24) + ((_idx) << 2)
|
||||
|
||||
#define AW_GPIO_GP_INT_CFG0 0x200
|
||||
#define AW_GPIO_GP_INT_CFG1 0x204
|
||||
#define AW_GPIO_GP_INT_CFG2 0x208
|
||||
#define AW_GPIO_GP_INT_CFG3 0x20c
|
||||
#define AW_GPIO_GP_INT_BASE(_bank) (0x200 + 0x20 * _bank)
|
||||
|
||||
#define AW_GPIO_GP_INT_CTL 0x210
|
||||
#define AW_GPIO_GP_INT_STA 0x214
|
||||
#define AW_GPIO_GP_INT_DEB 0x218
|
||||
#define AW_GPIO_GP_INT_CFG(_bank, _pin) (AW_GPIO_GP_INT_BASE(_bank) + (0x4 * ((_pin) / 8)))
|
||||
#define AW_GPIO_GP_INT_CTL(_bank) (AW_GPIO_GP_INT_BASE(_bank) + 0x10)
|
||||
#define AW_GPIO_GP_INT_STA(_bank) (AW_GPIO_GP_INT_BASE(_bank) + 0x14)
|
||||
#define AW_GPIO_GP_INT_DEB(_bank) (AW_GPIO_GP_INT_BASE(_bank) + 0x18)
|
||||
|
||||
#define AW_GPIO_INT_EDGE_POSITIVE 0x0
|
||||
#define AW_GPIO_INT_EDGE_NEGATIVE 0x1
|
||||
#define AW_GPIO_INT_LEVEL_HIGH 0x2
|
||||
#define AW_GPIO_INT_LEVEL_LOW 0x3
|
||||
#define AW_GPIO_INT_EDGE_BOTH 0x4
|
||||
|
||||
static char *aw_gpio_parse_function(phandle_t node);
|
||||
static const char **aw_gpio_parse_pins(phandle_t node, int *pins_nb);
|
||||
@ -290,10 +330,16 @@ static int aw_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value);
|
||||
static int aw_gpio_pin_get_locked(struct aw_gpio_softc *sc, uint32_t pin, unsigned int *value);
|
||||
static int aw_gpio_pin_set_locked(struct aw_gpio_softc *sc, uint32_t pin, unsigned int value);
|
||||
|
||||
static void aw_gpio_intr(void *arg);
|
||||
static void aw_gpio_pic_disable_intr(device_t dev, struct intr_irqsrc *isrc);
|
||||
static void aw_gpio_pic_disable_intr_locked(struct aw_gpio_softc *sc, struct intr_irqsrc *isrc);
|
||||
static void aw_gpio_pic_post_filter(device_t dev, struct intr_irqsrc *isrc);
|
||||
static int aw_gpio_register_isrcs(struct aw_gpio_softc *sc);
|
||||
|
||||
#define AW_GPIO_WRITE(_sc, _off, _val) \
|
||||
bus_space_write_4(_sc->sc_bst, _sc->sc_bsh, _off, _val)
|
||||
bus_write_4((_sc)->sc_res[AW_GPIO_MEMRES], _off, _val)
|
||||
#define AW_GPIO_READ(_sc, _off) \
|
||||
bus_space_read_4(_sc->sc_bst, _sc->sc_bsh, _off)
|
||||
bus_read_4((_sc)->sc_res[AW_GPIO_MEMRES], _off)
|
||||
|
||||
static uint32_t
|
||||
aw_gpio_get_function(struct aw_gpio_softc *sc, uint32_t pin)
|
||||
@ -492,6 +538,8 @@ aw_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
|
||||
return (EINVAL);
|
||||
|
||||
*caps = AW_GPIO_DEFAULT_CAPS;
|
||||
if (sc->conf->padconf->pins[pin].eint_func != 0)
|
||||
*caps |= AW_GPIO_INTR_CAPS;
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -806,6 +854,27 @@ aw_gpio_pin_config_32(device_t dev, uint32_t first_pin, uint32_t num_pins,
|
||||
return (err);
|
||||
}
|
||||
|
||||
static int
|
||||
aw_gpio_map_gpios(device_t bus, phandle_t dev, phandle_t gparent, int gcells,
|
||||
pcell_t *gpios, uint32_t *pin, uint32_t *flags)
|
||||
{
|
||||
struct aw_gpio_softc *sc;
|
||||
int i;
|
||||
|
||||
sc = device_get_softc(bus);
|
||||
|
||||
/* The GPIO pins are mapped as: <gpio-phandle bank pin flags>. */
|
||||
for (i = 0; i < sc->conf->padconf->npins; i++)
|
||||
if (sc->conf->padconf->pins[i].port == gpios[0] &&
|
||||
sc->conf->padconf->pins[i].pin == gpios[1]) {
|
||||
*pin = i;
|
||||
break;
|
||||
}
|
||||
*flags = gpios[gcells - 1];
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
aw_find_pinnum_by_name(struct aw_gpio_softc *sc, const char *pinname)
|
||||
{
|
||||
@ -938,7 +1007,7 @@ aw_gpio_probe(device_t dev)
|
||||
static int
|
||||
aw_gpio_attach(device_t dev)
|
||||
{
|
||||
int rid, error;
|
||||
int error;
|
||||
phandle_t gpio;
|
||||
struct aw_gpio_softc *sc;
|
||||
struct clk_list *clkp, *clkp_tmp;
|
||||
@ -951,22 +1020,15 @@ aw_gpio_attach(device_t dev)
|
||||
|
||||
mtx_init(&sc->sc_mtx, "aw gpio", "gpio", MTX_SPIN);
|
||||
|
||||
rid = 0;
|
||||
sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
|
||||
RF_ACTIVE);
|
||||
if (!sc->sc_mem_res) {
|
||||
device_printf(dev, "cannot allocate memory window\n");
|
||||
goto fail;
|
||||
if (bus_alloc_resources(dev, aw_gpio_res_spec, sc->sc_res) != 0) {
|
||||
device_printf(dev, "cannot allocate device resources\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
sc->sc_bst = rman_get_bustag(sc->sc_mem_res);
|
||||
sc->sc_bsh = rman_get_bushandle(sc->sc_mem_res);
|
||||
|
||||
rid = 0;
|
||||
sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
|
||||
RF_ACTIVE);
|
||||
if (!sc->sc_irq_res) {
|
||||
device_printf(dev, "cannot allocate interrupt\n");
|
||||
if (bus_setup_intr(dev, sc->sc_res[AW_GPIO_IRQRES],
|
||||
INTR_TYPE_CLK | INTR_MPSAFE, NULL, aw_gpio_intr, sc,
|
||||
&sc->sc_intrhand)) {
|
||||
device_printf(dev, "cannot setup interrupt handler\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@ -1009,6 +1071,11 @@ aw_gpio_attach(device_t dev)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#ifdef INTRNG
|
||||
aw_gpio_register_isrcs(sc);
|
||||
intr_pic_register(dev, OF_xref_from_node(ofw_bus_get_node(dev)));
|
||||
#endif
|
||||
|
||||
sc->sc_busdev = gpiobus_attach_bus(dev);
|
||||
if (sc->sc_busdev == NULL)
|
||||
goto fail;
|
||||
@ -1062,6 +1129,314 @@ aw_gpio_detach(device_t dev)
|
||||
return (EBUSY);
|
||||
}
|
||||
|
||||
static void
|
||||
aw_gpio_intr(void *arg)
|
||||
{
|
||||
struct aw_gpio_softc *sc;
|
||||
struct intr_irqsrc *isrc;
|
||||
uint32_t reg;
|
||||
int irq;
|
||||
|
||||
sc = (struct aw_gpio_softc *)arg;
|
||||
|
||||
AW_GPIO_LOCK(sc);
|
||||
for (irq = 0; irq < sc->nirqs; irq++) {
|
||||
if (!sc->gpio_pic_irqsrc[irq].enabled)
|
||||
continue;
|
||||
|
||||
reg = AW_GPIO_READ(sc, AW_GPIO_GP_INT_STA(sc->gpio_pic_irqsrc[irq].bank));
|
||||
if (!(reg & (1 << sc->gpio_pic_irqsrc[irq].intnum)))
|
||||
continue;
|
||||
|
||||
isrc = &sc->gpio_pic_irqsrc[irq].isrc;
|
||||
if (intr_isrc_dispatch(isrc, curthread->td_intr_frame) != 0) {
|
||||
aw_gpio_pic_disable_intr_locked(sc, isrc);
|
||||
aw_gpio_pic_post_filter(sc->sc_dev, isrc);
|
||||
device_printf(sc->sc_dev, "Stray irq %u disabled\n", irq);
|
||||
}
|
||||
}
|
||||
AW_GPIO_UNLOCK(sc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Interrupts support
|
||||
*/
|
||||
|
||||
static int
|
||||
aw_gpio_register_isrcs(struct aw_gpio_softc *sc)
|
||||
{
|
||||
const char *name;
|
||||
int nirqs;
|
||||
int pin;
|
||||
int err;
|
||||
|
||||
name = device_get_nameunit(sc->sc_dev);
|
||||
|
||||
for (nirqs = 0, pin = 0; pin < sc->conf->padconf->npins; pin++) {
|
||||
if (sc->conf->padconf->pins[pin].eint_func == 0)
|
||||
continue;
|
||||
|
||||
nirqs++;
|
||||
}
|
||||
|
||||
sc->gpio_pic_irqsrc = malloc(sizeof(*sc->gpio_pic_irqsrc) * nirqs,
|
||||
M_DEVBUF, M_WAITOK | M_ZERO);
|
||||
for (nirqs = 0, pin = 0; pin < sc->conf->padconf->npins; pin++) {
|
||||
if (sc->conf->padconf->pins[pin].eint_func == 0)
|
||||
continue;
|
||||
|
||||
sc->gpio_pic_irqsrc[nirqs].pin = pin;
|
||||
sc->gpio_pic_irqsrc[nirqs].bank = sc->conf->padconf->pins[pin].eint_bank;
|
||||
sc->gpio_pic_irqsrc[nirqs].intnum = sc->conf->padconf->pins[pin].eint_num;
|
||||
sc->gpio_pic_irqsrc[nirqs].intfunc = sc->conf->padconf->pins[pin].eint_func;
|
||||
sc->gpio_pic_irqsrc[nirqs].irq = nirqs;
|
||||
sc->gpio_pic_irqsrc[nirqs].mode = GPIO_INTR_CONFORM;
|
||||
|
||||
err = intr_isrc_register(&sc->gpio_pic_irqsrc[nirqs].isrc,
|
||||
sc->sc_dev, 0, "%s,%s", name,
|
||||
sc->conf->padconf->pins[pin].functions[sc->conf->padconf->pins[pin].eint_func]);
|
||||
if (err) {
|
||||
device_printf(sc->sc_dev, "intr_isrs_register failed for irq %d\n", nirqs);
|
||||
}
|
||||
|
||||
nirqs++;
|
||||
}
|
||||
|
||||
sc->nirqs = nirqs;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
aw_gpio_pic_disable_intr_locked(struct aw_gpio_softc *sc, struct intr_irqsrc *isrc)
|
||||
{
|
||||
u_int irq;
|
||||
uint32_t reg;
|
||||
|
||||
AW_GPIO_LOCK_ASSERT(sc);
|
||||
irq = ((struct gpio_irqsrc *)isrc)->irq;
|
||||
reg = AW_GPIO_READ(sc, AW_GPIO_GP_INT_CTL(sc->gpio_pic_irqsrc[irq].bank));
|
||||
reg &= ~(1 << sc->gpio_pic_irqsrc[irq].intnum);
|
||||
AW_GPIO_WRITE(sc, AW_GPIO_GP_INT_CTL(sc->gpio_pic_irqsrc[irq].bank), reg);
|
||||
|
||||
sc->gpio_pic_irqsrc[irq].enabled = false;
|
||||
}
|
||||
|
||||
static void
|
||||
aw_gpio_pic_disable_intr(device_t dev, struct intr_irqsrc *isrc)
|
||||
{
|
||||
struct aw_gpio_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
AW_GPIO_LOCK(sc);
|
||||
aw_gpio_pic_disable_intr_locked(sc, isrc);
|
||||
AW_GPIO_UNLOCK(sc);
|
||||
}
|
||||
|
||||
static void
|
||||
aw_gpio_pic_enable_intr(device_t dev, struct intr_irqsrc *isrc)
|
||||
{
|
||||
struct aw_gpio_softc *sc;
|
||||
u_int irq;
|
||||
uint32_t reg;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
irq = ((struct gpio_irqsrc *)isrc)->irq;
|
||||
AW_GPIO_LOCK(sc);
|
||||
reg = AW_GPIO_READ(sc, AW_GPIO_GP_INT_CTL(sc->gpio_pic_irqsrc[irq].bank));
|
||||
reg |= 1 << sc->gpio_pic_irqsrc[irq].intnum;
|
||||
AW_GPIO_WRITE(sc, AW_GPIO_GP_INT_CTL(sc->gpio_pic_irqsrc[irq].bank), reg);
|
||||
AW_GPIO_UNLOCK(sc);
|
||||
|
||||
sc->gpio_pic_irqsrc[irq].enabled = true;
|
||||
}
|
||||
|
||||
static int
|
||||
aw_gpio_pic_map_gpio(struct aw_gpio_softc *sc, struct intr_map_data_gpio *dag,
|
||||
u_int *irqp, u_int *mode)
|
||||
{
|
||||
u_int irq;
|
||||
int pin;
|
||||
|
||||
irq = dag->gpio_pin_num;
|
||||
|
||||
for (pin = 0; pin < sc->nirqs; pin++)
|
||||
if (sc->gpio_pic_irqsrc[pin].pin == irq)
|
||||
break;
|
||||
if (pin == sc->nirqs) {
|
||||
device_printf(sc->sc_dev, "Invalid interrupt number %u\n", irq);
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
switch (dag->gpio_intr_mode) {
|
||||
case GPIO_INTR_LEVEL_LOW:
|
||||
case GPIO_INTR_LEVEL_HIGH:
|
||||
case GPIO_INTR_EDGE_RISING:
|
||||
case GPIO_INTR_EDGE_FALLING:
|
||||
case GPIO_INTR_EDGE_BOTH:
|
||||
break;
|
||||
default:
|
||||
device_printf(sc->sc_dev, "Unsupported interrupt mode 0x%8x\n",
|
||||
dag->gpio_intr_mode);
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
*irqp = pin;
|
||||
if (mode != NULL)
|
||||
*mode = dag->gpio_intr_mode;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
aw_gpio_pic_map_intr(device_t dev, struct intr_map_data *data,
|
||||
struct intr_irqsrc **isrcp)
|
||||
{
|
||||
struct aw_gpio_softc *sc;
|
||||
u_int irq;
|
||||
int err;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
switch (data->type) {
|
||||
case INTR_MAP_DATA_GPIO:
|
||||
err = aw_gpio_pic_map_gpio(sc,
|
||||
(struct intr_map_data_gpio *)data,
|
||||
&irq, NULL);
|
||||
break;
|
||||
default:
|
||||
return (ENOTSUP);
|
||||
};
|
||||
|
||||
if (err == 0)
|
||||
*isrcp = &sc->gpio_pic_irqsrc[irq].isrc;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
aw_gpio_pic_setup_intr(device_t dev, struct intr_irqsrc *isrc,
|
||||
struct resource *res, struct intr_map_data *data)
|
||||
{
|
||||
struct aw_gpio_softc *sc;
|
||||
struct gpio_irqsrc *gi;
|
||||
uint32_t irqcfg;
|
||||
uint32_t pinidx, reg;
|
||||
u_int irq, mode;
|
||||
int err;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
gi = (struct gpio_irqsrc *)isrc;
|
||||
|
||||
switch (data->type) {
|
||||
case INTR_MAP_DATA_GPIO:
|
||||
err = aw_gpio_pic_map_gpio(sc,
|
||||
(struct intr_map_data_gpio *)data,
|
||||
&irq, &mode);
|
||||
break;
|
||||
default:
|
||||
return (ENOTSUP);
|
||||
};
|
||||
|
||||
pinidx = (sc->gpio_pic_irqsrc[irq].intnum % 8) * 4;
|
||||
|
||||
AW_GPIO_LOCK(sc);
|
||||
switch (mode) {
|
||||
case GPIO_INTR_LEVEL_LOW:
|
||||
irqcfg = AW_GPIO_INT_LEVEL_LOW << pinidx;
|
||||
break;
|
||||
case GPIO_INTR_LEVEL_HIGH:
|
||||
irqcfg = AW_GPIO_INT_LEVEL_HIGH << pinidx;
|
||||
break;
|
||||
case GPIO_INTR_EDGE_RISING:
|
||||
irqcfg = AW_GPIO_INT_EDGE_POSITIVE << pinidx;
|
||||
break;
|
||||
case GPIO_INTR_EDGE_FALLING:
|
||||
irqcfg = AW_GPIO_INT_EDGE_NEGATIVE << pinidx;
|
||||
break;
|
||||
case GPIO_INTR_EDGE_BOTH:
|
||||
irqcfg = AW_GPIO_INT_EDGE_BOTH << pinidx;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Switch the pin to interrupt mode */
|
||||
sc->gpio_pic_irqsrc[irq].oldfunc = aw_gpio_get_function(sc,
|
||||
sc->gpio_pic_irqsrc[irq].pin);
|
||||
aw_gpio_set_function(sc, sc->gpio_pic_irqsrc[irq].pin,
|
||||
sc->gpio_pic_irqsrc[irq].intfunc);
|
||||
|
||||
/* Write interrupt mode */
|
||||
reg = AW_GPIO_READ(sc,
|
||||
AW_GPIO_GP_INT_CFG(sc->gpio_pic_irqsrc[irq].bank,
|
||||
sc->gpio_pic_irqsrc[irq].intnum));
|
||||
reg &= ~(0xF << pinidx);
|
||||
reg |= irqcfg;
|
||||
AW_GPIO_WRITE(sc,
|
||||
AW_GPIO_GP_INT_CFG(sc->gpio_pic_irqsrc[irq].bank,
|
||||
sc->gpio_pic_irqsrc[irq].intnum),
|
||||
reg);
|
||||
|
||||
AW_GPIO_UNLOCK(sc);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
aw_gpio_pic_teardown_intr(device_t dev, struct intr_irqsrc *isrc,
|
||||
struct resource *res, struct intr_map_data *data)
|
||||
{
|
||||
struct aw_gpio_softc *sc;
|
||||
struct gpio_irqsrc *gi;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
gi = (struct gpio_irqsrc *)isrc;
|
||||
|
||||
/* Switch back the pin to it's original function */
|
||||
AW_GPIO_LOCK(sc);
|
||||
aw_gpio_set_function(sc, gi->pin, gi->oldfunc);
|
||||
AW_GPIO_UNLOCK(sc);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
aw_gpio_pic_post_filter(device_t dev, struct intr_irqsrc *isrc)
|
||||
{
|
||||
struct aw_gpio_softc *sc;
|
||||
struct gpio_irqsrc *gi;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
gi = (struct gpio_irqsrc *)isrc;
|
||||
|
||||
arm_irq_memory_barrier(0);
|
||||
AW_GPIO_WRITE(sc, AW_GPIO_GP_INT_STA(gi->bank), 1 << gi->intnum);
|
||||
}
|
||||
|
||||
static void
|
||||
aw_gpio_pic_post_ithread(device_t dev, struct intr_irqsrc *isrc)
|
||||
{
|
||||
struct aw_gpio_softc *sc;
|
||||
struct gpio_irqsrc *gi;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
gi = (struct gpio_irqsrc *)isrc;
|
||||
|
||||
arm_irq_memory_barrier(0);
|
||||
AW_GPIO_WRITE(sc, AW_GPIO_GP_INT_STA(gi->bank), 1 << gi->intnum);
|
||||
aw_gpio_pic_enable_intr(dev, isrc);
|
||||
}
|
||||
|
||||
static void
|
||||
aw_gpio_pic_pre_ithread(device_t dev, struct intr_irqsrc *isrc)
|
||||
{
|
||||
struct aw_gpio_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
aw_gpio_pic_disable_intr_locked(sc, isrc);
|
||||
}
|
||||
|
||||
/*
|
||||
* OFWBUS Interface
|
||||
*/
|
||||
static phandle_t
|
||||
aw_gpio_get_node(device_t dev, device_t bus)
|
||||
{
|
||||
@ -1070,33 +1445,24 @@ aw_gpio_get_node(device_t dev, device_t bus)
|
||||
return (ofw_bus_get_node(dev));
|
||||
}
|
||||
|
||||
static int
|
||||
aw_gpio_map_gpios(device_t bus, phandle_t dev, phandle_t gparent, int gcells,
|
||||
pcell_t *gpios, uint32_t *pin, uint32_t *flags)
|
||||
{
|
||||
struct aw_gpio_softc *sc;
|
||||
int i;
|
||||
|
||||
sc = device_get_softc(bus);
|
||||
|
||||
/* The GPIO pins are mapped as: <gpio-phandle bank pin flags>. */
|
||||
for (i = 0; i < sc->conf->padconf->npins; i++)
|
||||
if (sc->conf->padconf->pins[i].port == gpios[0] &&
|
||||
sc->conf->padconf->pins[i].pin == gpios[1]) {
|
||||
*pin = i;
|
||||
break;
|
||||
}
|
||||
*flags = gpios[gcells - 1];
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static device_method_t aw_gpio_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, aw_gpio_probe),
|
||||
DEVMETHOD(device_attach, aw_gpio_attach),
|
||||
DEVMETHOD(device_detach, aw_gpio_detach),
|
||||
|
||||
#ifdef INTRNG
|
||||
/* Interrupt controller interface */
|
||||
DEVMETHOD(pic_disable_intr, aw_gpio_pic_disable_intr),
|
||||
DEVMETHOD(pic_enable_intr, aw_gpio_pic_enable_intr),
|
||||
DEVMETHOD(pic_map_intr, aw_gpio_pic_map_intr),
|
||||
DEVMETHOD(pic_setup_intr, aw_gpio_pic_setup_intr),
|
||||
DEVMETHOD(pic_teardown_intr, aw_gpio_pic_teardown_intr),
|
||||
DEVMETHOD(pic_post_filter, aw_gpio_pic_post_filter),
|
||||
DEVMETHOD(pic_post_ithread, aw_gpio_pic_post_ithread),
|
||||
DEVMETHOD(pic_pre_ithread, aw_gpio_pic_pre_ithread),
|
||||
#endif
|
||||
|
||||
/* GPIO protocol */
|
||||
DEVMETHOD(gpio_get_bus, aw_gpio_get_bus),
|
||||
DEVMETHOD(gpio_pin_max, aw_gpio_pin_max),
|
||||
|
@ -126,20 +126,20 @@ const static struct allwinner_pins h3_pins[] = {
|
||||
{"PF5", 5, 5, {"gpio_in", "gpio_out", "mmc0", "jtag", NULL, NULL, NULL, NULL}},
|
||||
{"PF6", 5, 6, {"gpio_in", "gpio_out", NULL, NULL, NULL, NULL, NULL, NULL}},
|
||||
|
||||
{"PG0", 6, 0, {"gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint0", NULL}, 6, 0},
|
||||
{"PG1", 6, 1, {"gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint1", NULL}, 6, 1},
|
||||
{"PG2", 6, 2, {"gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint2", NULL}, 6, 2},
|
||||
{"PG3", 6, 3, {"gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint3", NULL}, 6, 3},
|
||||
{"PG4", 6, 4, {"gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint4", NULL}, 6, 4},
|
||||
{"PG5", 6, 5, {"gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint5", NULL}, 6, 5},
|
||||
{"PG6", 6, 6, {"gpio_in", "gpio_out", "uart1", NULL, NULL, NULL, "pg_eint6", NULL}, 6, 6},
|
||||
{"PG7", 6, 7, {"gpio_in", "gpio_out", "uart1", NULL, NULL, NULL, "pg_eint7", NULL}, 6, 7},
|
||||
{"PG8", 6, 8, {"gpio_in", "gpio_out", "uart1", NULL, NULL, NULL, "pg_eint8", NULL}, 6, 8},
|
||||
{"PG9", 6, 9, {"gpio_in", "gpio_out", "uart1", NULL, NULL, NULL, "pg_eint9", NULL}, 6, 9},
|
||||
{"PG10", 6, 10, {"gpio_in", "gpio_out", "i2s1", NULL, NULL, NULL, "pg_eint10", NULL}, 6, 10},
|
||||
{"PG11", 6, 11, {"gpio_in", "gpio_out", "i2s1", NULL, NULL, NULL, "pg_eint11", NULL}, 6, 11},
|
||||
{"PG12", 6, 12, {"gpio_in", "gpio_out", "i2s1", NULL, NULL, NULL, "pg_eint12", NULL}, 6, 12},
|
||||
{"PG13", 6, 13, {"gpio_in", "gpio_out", "i2s1", NULL, NULL, NULL, "pg_eint13", NULL}, 6, 13},
|
||||
{"PG0", 6, 0, {"gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint0", NULL}, 6, 0, 1},
|
||||
{"PG1", 6, 1, {"gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint1", NULL}, 6, 1, 1},
|
||||
{"PG2", 6, 2, {"gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint2", NULL}, 6, 2, 1},
|
||||
{"PG3", 6, 3, {"gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint3", NULL}, 6, 3, 1},
|
||||
{"PG4", 6, 4, {"gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint4", NULL}, 6, 4, 1},
|
||||
{"PG5", 6, 5, {"gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint5", NULL}, 6, 5, 1},
|
||||
{"PG6", 6, 6, {"gpio_in", "gpio_out", "uart1", NULL, NULL, NULL, "pg_eint6", NULL}, 6, 6, 1},
|
||||
{"PG7", 6, 7, {"gpio_in", "gpio_out", "uart1", NULL, NULL, NULL, "pg_eint7", NULL}, 6, 7, 1},
|
||||
{"PG8", 6, 8, {"gpio_in", "gpio_out", "uart1", NULL, NULL, NULL, "pg_eint8", NULL}, 6, 8, 1},
|
||||
{"PG9", 6, 9, {"gpio_in", "gpio_out", "uart1", NULL, NULL, NULL, "pg_eint9", NULL}, 6, 9, 1},
|
||||
{"PG10", 6, 10, {"gpio_in", "gpio_out", "i2s1", NULL, NULL, NULL, "pg_eint10", NULL}, 6, 10, 1},
|
||||
{"PG11", 6, 11, {"gpio_in", "gpio_out", "i2s1", NULL, NULL, NULL, "pg_eint11", NULL}, 6, 11, 1},
|
||||
{"PG12", 6, 12, {"gpio_in", "gpio_out", "i2s1", NULL, NULL, NULL, "pg_eint12", NULL}, 6, 12, 1},
|
||||
{"PG13", 6, 13, {"gpio_in", "gpio_out", "i2s1", NULL, NULL, NULL, "pg_eint13", NULL}, 6, 13, 1},
|
||||
};
|
||||
|
||||
const struct allwinner_padconf h3_padconf = {
|
||||
|
@ -41,18 +41,18 @@ __FBSDID("$FreeBSD$");
|
||||
#if defined(SOC_ALLWINNER_H3) || defined(SOC_ALLWINNER_H5)
|
||||
|
||||
const static struct allwinner_pins h3_r_pins[] = {
|
||||
{"PL0", 0, 0, {"gpio_in", "gpio_out", "s_twi", NULL, NULL, NULL, "pl_eint0", NULL}, 6, 0},
|
||||
{"PL1", 0, 1, {"gpio_in", "gpio_out", "s_twi", NULL, NULL, NULL, "pl_eint1", NULL}, 6, 1},
|
||||
{"PL2", 0, 2, {"gpio_in", "gpio_out", "s_uart", NULL, NULL, NULL, "pl_eint2", NULL}, 6, 2},
|
||||
{"PL3", 0, 3, {"gpio_in", "gpio_out", "s_uart", NULL, NULL, NULL, "pl_eint3", NULL}, 6, 3},
|
||||
{"PL4", 0, 4, {"gpio_in", "gpio_out", "s_jtag", NULL, NULL, NULL, "pl_eint4", NULL}, 6, 4},
|
||||
{"PL5", 0, 5, {"gpio_in", "gpio_out", "s_jtag", NULL, NULL, NULL, "pl_eint5", NULL}, 6, 5},
|
||||
{"PL6", 0, 6, {"gpio_in", "gpio_out", "s_jtag", NULL, NULL, NULL, "pl_eint6", NULL}, 6, 6},
|
||||
{"PL7", 0, 7, {"gpio_in", "gpio_out", "s_jtag", NULL, NULL, NULL, "pl_eint7", NULL}, 6, 7},
|
||||
{"PL8", 0, 8, {"gpio_in", "gpio_out", NULL, NULL, NULL, NULL, "pl_eint8", NULL}, 6, 8},
|
||||
{"PL9", 0, 9, {"gpio_in", "gpio_out", NULL, NULL, NULL, NULL, "pl_eint9", NULL}, 6, 9},
|
||||
{"PL10", 0, 10, {"gpio_in", "gpio_out", "s_pwm", NULL, NULL, NULL, "pl_eint10", NULL}, 6, 10},
|
||||
{"PL11", 0, 11, {"gpio_in", "gpio_out", "s_cir_rx", NULL, NULL, NULL, "pl_eint11", NULL}, 6, 11},
|
||||
{"PL0", 0, 0, {"gpio_in", "gpio_out", "s_twi", NULL, NULL, NULL, "pl_eint0", NULL}, 6, 0, 0},
|
||||
{"PL1", 0, 1, {"gpio_in", "gpio_out", "s_twi", NULL, NULL, NULL, "pl_eint1", NULL}, 6, 1, 0},
|
||||
{"PL2", 0, 2, {"gpio_in", "gpio_out", "s_uart", NULL, NULL, NULL, "pl_eint2", NULL}, 6, 2, 0},
|
||||
{"PL3", 0, 3, {"gpio_in", "gpio_out", "s_uart", NULL, NULL, NULL, "pl_eint3", NULL}, 6, 3, 0},
|
||||
{"PL4", 0, 4, {"gpio_in", "gpio_out", "s_jtag", NULL, NULL, NULL, "pl_eint4", NULL}, 6, 4, 0},
|
||||
{"PL5", 0, 5, {"gpio_in", "gpio_out", "s_jtag", NULL, NULL, NULL, "pl_eint5", NULL}, 6, 5, 0},
|
||||
{"PL6", 0, 6, {"gpio_in", "gpio_out", "s_jtag", NULL, NULL, NULL, "pl_eint6", NULL}, 6, 6, 0},
|
||||
{"PL7", 0, 7, {"gpio_in", "gpio_out", "s_jtag", NULL, NULL, NULL, "pl_eint7", NULL}, 6, 7, 0},
|
||||
{"PL8", 0, 8, {"gpio_in", "gpio_out", NULL, NULL, NULL, NULL, "pl_eint8", NULL}, 6, 8, 0},
|
||||
{"PL9", 0, 9, {"gpio_in", "gpio_out", NULL, NULL, NULL, NULL, "pl_eint9", NULL}, 6, 9, 0},
|
||||
{"PL10", 0, 10, {"gpio_in", "gpio_out", "s_pwm", NULL, NULL, NULL, "pl_eint10", NULL}, 6, 10, 0},
|
||||
{"PL11", 0, 11, {"gpio_in", "gpio_out", "s_cir_rx", NULL, NULL, NULL, "pl_eint11", NULL}, 6, 11, 0},
|
||||
};
|
||||
|
||||
const struct allwinner_padconf h3_r_padconf = {
|
||||
|
@ -83,41 +83,41 @@ static const struct allwinner_pins h6_pins[] = {
|
||||
{ "PD25", 3, 25, { "gpio_in", "gpio_out", "i2c0", "ts3", "uart3", "jtag" } },
|
||||
{ "PD26", 3, 26, { "gpio_in", "gpio_out", "i2c0", "ts3", "uart3", "jtag" } },
|
||||
|
||||
{ "PF0", 5, 0, { "gpio_in", "gpio_out", "mmc0", "jtag", NULL, NULL, "pf_eint0" } },
|
||||
{ "PF1", 5, 1, { "gpio_in", "gpio_out", "mmc0", "jtag", NULL, NULL, "pf_eint1" } },
|
||||
{ "PF2", 5, 2, { "gpio_in", "gpio_out", "mmc0", "uart0", NULL, NULL, "pf_eint2" } },
|
||||
{ "PF3", 5, 3, { "gpio_in", "gpio_out", "mmc0", "jtag", NULL, NULL, "pf_eint3" } },
|
||||
{ "PF4", 5, 4, { "gpio_in", "gpio_out", "mmc0", "uart0", NULL, NULL, "pf_eint4" } },
|
||||
{ "PF5", 5, 5, { "gpio_in", "gpio_out", "mmc0", "jtag", NULL, NULL, "pf_eint5" } },
|
||||
{ "PF6", 5, 6, { "gpio_in", "gpio_out", NULL, NULL, NULL, NULL, "pf_eint6" } },
|
||||
{ "PF0", 5, 0, { "gpio_in", "gpio_out", "mmc0", "jtag", NULL, NULL, "pf_eint0" }, 6, 0, 5 },
|
||||
{ "PF1", 5, 1, { "gpio_in", "gpio_out", "mmc0", "jtag", NULL, NULL, "pf_eint1" }, 6, 1, 5 },
|
||||
{ "PF2", 5, 2, { "gpio_in", "gpio_out", "mmc0", "uart0", NULL, NULL, "pf_eint2" }, 6, 2, 5 },
|
||||
{ "PF3", 5, 3, { "gpio_in", "gpio_out", "mmc0", "jtag", NULL, NULL, "pf_eint3" }, 6, 3, 5 },
|
||||
{ "PF4", 5, 4, { "gpio_in", "gpio_out", "mmc0", "uart0", NULL, NULL, "pf_eint4" }, 6, 4, 5 },
|
||||
{ "PF5", 5, 5, { "gpio_in", "gpio_out", "mmc0", "jtag", NULL, NULL, "pf_eint5" }, 6, 5, 5 },
|
||||
{ "PF6", 5, 6, { "gpio_in", "gpio_out", NULL, NULL, NULL, NULL, "pf_eint6" }, 6, 6, 5 },
|
||||
|
||||
{ "PG0", 6, 0, { "gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint0" }, 6, 0 },
|
||||
{ "PG1", 6, 1, { "gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint1" }, 6, 1 },
|
||||
{ "PG2", 6, 2, { "gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint2" }, 6, 2 },
|
||||
{ "PG3", 6, 3, { "gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint3" }, 6, 3 },
|
||||
{ "PG4", 6, 4, { "gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint4" }, 6, 4 },
|
||||
{ "PG5", 6, 5, { "gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint5" }, 6, 5 },
|
||||
{ "PG6", 6, 6, { "gpio_in", "gpio_out", "uart1", NULL, NULL, NULL, "pg_eint6" }, 6, 6 },
|
||||
{ "PG7", 6, 7, { "gpio_in", "gpio_out", "uart1", NULL, NULL, NULL, "pg_eint7" }, 6, 7 },
|
||||
{ "PG8", 6, 8, { "gpio_in", "gpio_out", "uart1", NULL, "sim0", NULL, "pg_eint8" }, 6, 8 },
|
||||
{ "PG9", 6, 9, { "gpio_in", "gpio_out", "uart1", NULL, "sim0", NULL, "pg_eint9" }, 6, 9 },
|
||||
{ "PG10", 6, 10, { "gpio_in", "gpio_out", "i2s2", "h_i2s2", "sim0", NULL, "pg_eint10" }, 6, 10 },
|
||||
{ "PG11", 6, 11, { "gpio_in", "gpio_out", "i2s2", "h_i2s2", "sim0", NULL, "pg_eint11" }, 6, 11 },
|
||||
{ "PG12", 6, 12, { "gpio_in", "gpio_out", "i2s2", "h_i2s2", "sim0", NULL, "pg_eint12" }, 6, 12 },
|
||||
{ "PG13", 6, 13, { "gpio_in", "gpio_out", "i2s2", "h_i2s2", "sim0", NULL, "pg_eint13" }, 6, 13 },
|
||||
{ "PG14", 6, 14, { "gpio_in", "gpio_out", "i2s2", "h_i2s2", "sim0", NULL, "pg_eint14" }, 6, 13 },
|
||||
{ "PG0", 6, 0, { "gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint0" }, 6, 0, 6},
|
||||
{ "PG1", 6, 1, { "gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint1" }, 6, 1, 6},
|
||||
{ "PG2", 6, 2, { "gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint2" }, 6, 2, 6},
|
||||
{ "PG3", 6, 3, { "gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint3" }, 6, 3, 6},
|
||||
{ "PG4", 6, 4, { "gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint4" }, 6, 4, 6},
|
||||
{ "PG5", 6, 5, { "gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint5" }, 6, 5, 6},
|
||||
{ "PG6", 6, 6, { "gpio_in", "gpio_out", "uart1", NULL, NULL, NULL, "pg_eint6" }, 6, 6, 6},
|
||||
{ "PG7", 6, 7, { "gpio_in", "gpio_out", "uart1", NULL, NULL, NULL, "pg_eint7" }, 6, 7, 6},
|
||||
{ "PG8", 6, 8, { "gpio_in", "gpio_out", "uart1", NULL, "sim0", NULL, "pg_eint8" }, 6, 8, 6},
|
||||
{ "PG9", 6, 9, { "gpio_in", "gpio_out", "uart1", NULL, "sim0", NULL, "pg_eint9" }, 6, 9, 6},
|
||||
{ "PG10", 6, 10, { "gpio_in", "gpio_out", "i2s2", "h_i2s2", "sim0", NULL, "pg_eint10" }, 6, 10, 6},
|
||||
{ "PG11", 6, 11, { "gpio_in", "gpio_out", "i2s2", "h_i2s2", "sim0", NULL, "pg_eint11" }, 6, 11, 6},
|
||||
{ "PG12", 6, 12, { "gpio_in", "gpio_out", "i2s2", "h_i2s2", "sim0", NULL, "pg_eint12" }, 6, 12, 6},
|
||||
{ "PG13", 6, 13, { "gpio_in", "gpio_out", "i2s2", "h_i2s2", "sim0", NULL, "pg_eint13" }, 6, 13, 6},
|
||||
{ "PG14", 6, 14, { "gpio_in", "gpio_out", "i2s2", "h_i2s2", "sim0", NULL, "pg_eint14" }, 6, 13, 6},
|
||||
|
||||
{ "PH0", 7, 0, { "gpio_in", "gpio_out", "uart0", "i2s0", "h_i2s0", "sim1", "ph_eint0" }, 6, 0 },
|
||||
{ "PH1", 7, 1, { "gpio_in", "gpio_out", "uart0", "i2s0", "h_i2s0", "sim1", "ph_eint1" }, 6, 1 },
|
||||
{ "PH2", 7, 2, { "gpio_in", "gpio_out", "cir", "i2s0", "h_i2s0", "sim1", "ph_eint2" }, 6, 2 },
|
||||
{ "PH3", 7, 3, { "gpio_in", "gpio_out", "spi1", "i2s0", "h_i2s0", "sim1", "ph_eint3" }, 6, 3 },
|
||||
{ "PH4", 7, 4, { "gpio_in", "gpio_out", "spi1", "i2s0", "h_i2s0", "sim1", "ph_eint4" }, 6, 4 },
|
||||
{ "PH5", 7, 5, { "gpio_in", "gpio_out", "spi1", "spdif", "i2c1", "sim1", "ph_eint5" }, 6, 5 },
|
||||
{ "PH6", 7, 6, { "gpio_in", "gpio_out", "spi1", "spdif", "i2c1", "sim1", "ph_eint6" }, 6, 6 },
|
||||
{ "PH7", 7, 7, { "gpio_in", "gpio_out", NULL, "spdif", NULL, NULL, "ph_eint7" }, 6, 7 },
|
||||
{ "PH8", 7, 8, { "gpio_in", "gpio_out", "hdmi", NULL, NULL, NULL, "ph_eint8" }, 6, 8 },
|
||||
{ "PH9", 7, 9, { "gpio_in", "gpio_out", "hdmi", NULL, NULL, NULL, "ph_eint9" }, 6, 9 },
|
||||
{ "PH10", 7, 10, { "gpio_in", "gpio_out", "hdmi", NULL, NULL, NULL, "ph_eint10" }, 6, 10 },
|
||||
{ "PH0", 7, 0, { "gpio_in", "gpio_out", "uart0", "i2s0", "h_i2s0", "sim1", "ph_eint0" }, 6, 0, 7},
|
||||
{ "PH1", 7, 1, { "gpio_in", "gpio_out", "uart0", "i2s0", "h_i2s0", "sim1", "ph_eint1" }, 6, 1, 7},
|
||||
{ "PH2", 7, 2, { "gpio_in", "gpio_out", "cir", "i2s0", "h_i2s0", "sim1", "ph_eint2" }, 6, 2, 7},
|
||||
{ "PH3", 7, 3, { "gpio_in", "gpio_out", "spi1", "i2s0", "h_i2s0", "sim1", "ph_eint3" }, 6, 3, 7},
|
||||
{ "PH4", 7, 4, { "gpio_in", "gpio_out", "spi1", "i2s0", "h_i2s0", "sim1", "ph_eint4" }, 6, 4, 7},
|
||||
{ "PH5", 7, 5, { "gpio_in", "gpio_out", "spi1", "spdif", "i2c1", "sim1", "ph_eint5" }, 6, 5, 7},
|
||||
{ "PH6", 7, 6, { "gpio_in", "gpio_out", "spi1", "spdif", "i2c1", "sim1", "ph_eint6" }, 6, 6, 7},
|
||||
{ "PH7", 7, 7, { "gpio_in", "gpio_out", NULL, "spdif", NULL, NULL, "ph_eint7" }, 6, 7, 7},
|
||||
{ "PH8", 7, 8, { "gpio_in", "gpio_out", "hdmi", NULL, NULL, NULL, "ph_eint8" }, 6, 8, 7},
|
||||
{ "PH9", 7, 9, { "gpio_in", "gpio_out", "hdmi", NULL, NULL, NULL, "ph_eint9" }, 6, 9, 7},
|
||||
{ "PH10", 7, 10, { "gpio_in", "gpio_out", "hdmi", NULL, NULL, NULL, "ph_eint10" }, 6, 10, 7},
|
||||
};
|
||||
|
||||
const struct allwinner_padconf h6_padconf = {
|
||||
|
@ -35,23 +35,23 @@ __FBSDID("$FreeBSD$");
|
||||
#include <arm/allwinner/allwinner_pinctrl.h>
|
||||
|
||||
const static struct allwinner_pins h6_r_pins[] = {
|
||||
{"PL0", 0, 0, {"gpio_in", "gpio_out", NULL, "s_i2c", NULL, NULL, "pl_eint0", NULL}, 6, 0},
|
||||
{"PL1", 0, 1, {"gpio_in", "gpio_out", NULL, "s_i2c", NULL, NULL, "pl_eint1", NULL}, 6, 1},
|
||||
{"PL2", 0, 2, {"gpio_in", "gpio_out", "s_uart", NULL, NULL, NULL, "pl_eint2", NULL}, 6, 2},
|
||||
{"PL3", 0, 3, {"gpio_in", "gpio_out", "s_uart", NULL, NULL, NULL, "pl_eint3", NULL}, 6, 3},
|
||||
{"PL4", 0, 4, {"gpio_in", "gpio_out", "s_jtag", NULL, NULL, NULL, "pl_eint4", NULL}, 6, 4},
|
||||
{"PL5", 0, 5, {"gpio_in", "gpio_out", "s_jtag", NULL, NULL, NULL, "pl_eint5", NULL}, 6, 5},
|
||||
{"PL6", 0, 6, {"gpio_in", "gpio_out", "s_jtag", NULL, NULL, NULL, "pl_eint6", NULL}, 6, 6},
|
||||
{"PL7", 0, 7, {"gpio_in", "gpio_out", "s_jtag", NULL, NULL, NULL, "pl_eint7", NULL}, 6, 7},
|
||||
{"PL8", 0, 8, {"gpio_in", "gpio_out", "s_i2c", NULL, NULL, NULL, "pl_eint8", NULL}, 6, 8},
|
||||
{"PL9", 0, 9, {"gpio_in", "gpio_out", "s_cir", NULL, NULL, NULL, "pl_eint9", NULL}, 6, 9},
|
||||
{"PL10", 0, 10, {"gpio_in", "gpio_out", "s_spdif", NULL, NULL, NULL, "pl_eint10", NULL}, 6, 10},
|
||||
{"PL0", 0, 0, {"gpio_in", "gpio_out", NULL, "s_i2c", NULL, NULL, "pl_eint0", NULL}, 6, 0, 0},
|
||||
{"PL1", 0, 1, {"gpio_in", "gpio_out", NULL, "s_i2c", NULL, NULL, "pl_eint1", NULL}, 6, 1, 0},
|
||||
{"PL2", 0, 2, {"gpio_in", "gpio_out", "s_uart", NULL, NULL, NULL, "pl_eint2", NULL}, 6, 2, 0},
|
||||
{"PL3", 0, 3, {"gpio_in", "gpio_out", "s_uart", NULL, NULL, NULL, "pl_eint3", NULL}, 6, 3, 0},
|
||||
{"PL4", 0, 4, {"gpio_in", "gpio_out", "s_jtag", NULL, NULL, NULL, "pl_eint4", NULL}, 6, 4, 0},
|
||||
{"PL5", 0, 5, {"gpio_in", "gpio_out", "s_jtag", NULL, NULL, NULL, "pl_eint5", NULL}, 6, 5, 0},
|
||||
{"PL6", 0, 6, {"gpio_in", "gpio_out", "s_jtag", NULL, NULL, NULL, "pl_eint6", NULL}, 6, 6, 0},
|
||||
{"PL7", 0, 7, {"gpio_in", "gpio_out", "s_jtag", NULL, NULL, NULL, "pl_eint7", NULL}, 6, 7, 0},
|
||||
{"PL8", 0, 8, {"gpio_in", "gpio_out", "s_i2c", NULL, NULL, NULL, "pl_eint8", NULL}, 6, 8, 0},
|
||||
{"PL9", 0, 9, {"gpio_in", "gpio_out", "s_cir", NULL, NULL, NULL, "pl_eint9", NULL}, 6, 9, 0},
|
||||
{"PL10", 0, 10, {"gpio_in", "gpio_out", "s_spdif", NULL, NULL, NULL, "pl_eint10", NULL}, 6, 10, 0},
|
||||
|
||||
{"PM0", 0, 0, {"gpio_in", "gpio_out", NULL, NULL, NULL, NULL, "pm_eint0", NULL}, 6, 0},
|
||||
{"PM1", 0, 0, {"gpio_in", "gpio_out", NULL, NULL, NULL, NULL, "pm_eint1", NULL}, 6, 1},
|
||||
{"PM2", 0, 0, {"gpio_in", "gpio_out", NULL, NULL, NULL, NULL, "pm_eint2", NULL}, 6, 2},
|
||||
{"PM3", 0, 0, {"gpio_in", "gpio_out", NULL, NULL, NULL, NULL, "pm_eint3", NULL}, 6, 3},
|
||||
{"PM4", 0, 0, {"gpio_in", "gpio_out", NULL, NULL, NULL, NULL, "pm_eint4", NULL}, 6, 4},
|
||||
{"PM0", 0, 0, {"gpio_in", "gpio_out", NULL, NULL, NULL, NULL, "pm_eint0", NULL}, 6, 0, 1},
|
||||
{"PM1", 0, 0, {"gpio_in", "gpio_out", NULL, NULL, NULL, NULL, "pm_eint1", NULL}, 6, 1, 1},
|
||||
{"PM2", 0, 0, {"gpio_in", "gpio_out", NULL, NULL, NULL, NULL, "pm_eint2", NULL}, 6, 2, 1},
|
||||
{"PM3", 0, 0, {"gpio_in", "gpio_out", NULL, NULL, NULL, NULL, "pm_eint3", NULL}, 6, 3, 1},
|
||||
{"PM4", 0, 0, {"gpio_in", "gpio_out", NULL, NULL, NULL, NULL, "pm_eint4", NULL}, 6, 4, 1},
|
||||
};
|
||||
|
||||
const struct allwinner_padconf h6_r_padconf = {
|
||||
|
@ -35,9 +35,6 @@ __FBSDID("$FreeBSD$");
|
||||
* mappings for use in DMA/mailbox interactions. This is only used for the
|
||||
* arm64 SoC because the 32-bit SoC used the same mappings.
|
||||
*/
|
||||
#if defined (__aarch64__)
|
||||
#include "opt_soc.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/systm.h>
|
||||
@ -67,7 +64,6 @@ struct bcm283x_memory_mapping {
|
||||
vm_paddr_t vcbus_start;
|
||||
};
|
||||
|
||||
#ifdef SOC_BCM2835
|
||||
static struct bcm283x_memory_mapping bcm2835_memmap[] = {
|
||||
{
|
||||
/* SDRAM */
|
||||
@ -83,9 +79,7 @@ static struct bcm283x_memory_mapping bcm2835_memmap[] = {
|
||||
},
|
||||
{ 0, 0, 0 },
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef SOC_BCM2836
|
||||
static struct bcm283x_memory_mapping bcm2836_memmap[] = {
|
||||
{
|
||||
/* SDRAM */
|
||||
@ -101,9 +95,7 @@ static struct bcm283x_memory_mapping bcm2836_memmap[] = {
|
||||
},
|
||||
{ 0, 0, 0 },
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef SOC_BRCM_BCM2837
|
||||
static struct bcm283x_memory_mapping bcm2837_memmap[] = {
|
||||
{
|
||||
/* SDRAM */
|
||||
@ -119,9 +111,6 @@ static struct bcm283x_memory_mapping bcm2837_memmap[] = {
|
||||
},
|
||||
{ 0, 0, 0 },
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef SOC_BRCM_BCM2838
|
||||
|
||||
/*
|
||||
* The BCM2838 supports up to 4GB of SDRAM, but unfortunately we can still only
|
||||
@ -144,14 +133,12 @@ static struct bcm283x_memory_mapping bcm2838_memmap[] = {
|
||||
},
|
||||
{ 0, 0, 0 },
|
||||
};
|
||||
#endif
|
||||
|
||||
static struct bcm283x_memory_soc_cfg {
|
||||
struct bcm283x_memory_mapping *memmap;
|
||||
const char *soc_compat;
|
||||
bus_addr_t busdma_lowaddr;
|
||||
} bcm283x_memory_configs[] = {
|
||||
#ifdef SOC_BCM2835
|
||||
/* Legacy */
|
||||
{
|
||||
.memmap = bcm2835_memmap,
|
||||
@ -164,8 +151,6 @@ static struct bcm283x_memory_soc_cfg {
|
||||
.soc_compat = "brcm,bcm2835",
|
||||
.busdma_lowaddr = BUS_SPACE_MAXADDR_32BIT,
|
||||
},
|
||||
#endif
|
||||
#ifdef SOC_BCM2836
|
||||
/* Legacy */
|
||||
{
|
||||
.memmap = bcm2836_memmap,
|
||||
@ -178,16 +163,11 @@ static struct bcm283x_memory_soc_cfg {
|
||||
.soc_compat = "brcm,bcm2836",
|
||||
.busdma_lowaddr = BUS_SPACE_MAXADDR_32BIT,
|
||||
},
|
||||
|
||||
#endif
|
||||
#ifdef SOC_BRCM_BCM2837
|
||||
{
|
||||
.memmap = bcm2837_memmap,
|
||||
.soc_compat = "brcm,bcm2837",
|
||||
.busdma_lowaddr = BUS_SPACE_MAXADDR_32BIT,
|
||||
},
|
||||
#endif
|
||||
#ifdef SOC_BRCM_BCM2838
|
||||
{
|
||||
.memmap = bcm2838_memmap,
|
||||
.soc_compat = "brcm,bcm2711",
|
||||
@ -198,7 +178,6 @@ static struct bcm283x_memory_soc_cfg {
|
||||
.soc_compat = "brcm,bcm2838",
|
||||
.busdma_lowaddr = BCM2838_PERIPH_MAXADDR,
|
||||
},
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct bcm283x_memory_soc_cfg *booted_soc_memcfg;
|
||||
|
@ -172,6 +172,7 @@ device spigen
|
||||
device bcm2835_spi
|
||||
device mv_spi
|
||||
device ti_spi
|
||||
device zy7_qspi # Xilinx Zynq QSPI controller
|
||||
|
||||
# ADC support
|
||||
device ti_adc
|
||||
|
@ -57,6 +57,10 @@ device pty
|
||||
device uart
|
||||
device gpio
|
||||
|
||||
device spibus
|
||||
device mx25l
|
||||
device zy7_qspi # Xilinx Zynq QSPI controller
|
||||
|
||||
device md
|
||||
device mmc # mmc/sd bus
|
||||
device mmcsd # mmc/sd flash cards
|
||||
|
@ -2,27 +2,6 @@
|
||||
#
|
||||
# $FreeBSD$
|
||||
|
||||
# Don't use an OBJDIR
|
||||
.OBJDIR: ${.CURDIR}
|
||||
GENERATED_PREFIX= linux_
|
||||
|
||||
.include <src.lua.mk>
|
||||
|
||||
MAKESYSCALLS= ../../tools/makesyscalls.lua
|
||||
SRCS= syscalls.conf \
|
||||
syscalls.master
|
||||
GENERATED= linux_proto.h \
|
||||
linux_syscall.h \
|
||||
linux_syscalls.c \
|
||||
linux_sysent.c \
|
||||
linux_systrace_args.c
|
||||
|
||||
all:
|
||||
@echo "make sysent only"
|
||||
|
||||
# We .ORDER these explicitly so that we only run MAKESYSCALLS once, rather than
|
||||
# potentially once for each ${GENERATED} file.
|
||||
.ORDER: ${GENERATED}
|
||||
sysent: ${GENERATED}
|
||||
|
||||
${GENERATED}: ${MAKESYSCALLS} ${SRCS}
|
||||
${LUA} ${MAKESYSCALLS} syscalls.master syscalls.conf
|
||||
.include "../../conf/sysent.mk"
|
||||
|
@ -13,4 +13,5 @@ dev/cadence/if_cgem.c optional cgem
|
||||
arm/xilinx/zy7_ehci.c optional ehci
|
||||
arm/xilinx/uart_dev_cdnc.c optional uart
|
||||
arm/xilinx/zy7_gpio.c optional gpio
|
||||
arm/xilinx/zy7_qspi.c optional zy7_qspi
|
||||
|
||||
|
763
sys/arm/xilinx/zy7_qspi.c
Normal file
763
sys/arm/xilinx/zy7_qspi.c
Normal file
@ -0,0 +1,763 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
|
||||
*
|
||||
* Copyright (c) 2018 Thomas Skibo <thomasskibo@yahoo.com>
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
/*
|
||||
* This is a driver for the Quad-SPI Flash Controller in the Xilinx
|
||||
* Zynq-7000 SoC.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/rman.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/resource.h>
|
||||
#include <machine/stdarg.h>
|
||||
|
||||
#include <dev/fdt/fdt_common.h>
|
||||
#include <dev/ofw/ofw_bus.h>
|
||||
#include <dev/ofw/ofw_bus_subr.h>
|
||||
|
||||
#include <dev/spibus/spi.h>
|
||||
#include <dev/spibus/spibusvar.h>
|
||||
|
||||
#include <dev/flash/mx25lreg.h>
|
||||
|
||||
#include "spibus_if.h"
|
||||
|
||||
static struct ofw_compat_data compat_data[] = {
|
||||
{"xlnx,zy7_qspi", 1},
|
||||
{"xlnx,zynq-qspi-1.0", 1},
|
||||
{NULL, 0}
|
||||
};
|
||||
|
||||
struct zy7_qspi_softc {
|
||||
device_t dev;
|
||||
device_t child;
|
||||
struct mtx sc_mtx;
|
||||
struct resource *mem_res;
|
||||
struct resource *irq_res;
|
||||
void *intrhandle;
|
||||
|
||||
uint32_t cfg_reg_shadow;
|
||||
uint32_t lqspi_cfg_shadow;
|
||||
uint32_t spi_clock;
|
||||
uint32_t ref_clock;
|
||||
unsigned int spi_clk_real_freq;
|
||||
unsigned int rx_overflows;
|
||||
unsigned int tx_underflows;
|
||||
unsigned int interrupts;
|
||||
unsigned int stray_ints;
|
||||
struct spi_command *cmd;
|
||||
int tx_bytes; /* tx_cmd_sz + tx_data_sz */
|
||||
int tx_bytes_sent;
|
||||
int rx_bytes; /* rx_cmd_sz + rx_data_sz */
|
||||
int rx_bytes_rcvd;
|
||||
int busy;
|
||||
int is_dual;
|
||||
int is_stacked;
|
||||
int is_dio;
|
||||
};
|
||||
|
||||
#define ZY7_QSPI_DEFAULT_SPI_CLOCK 50000000
|
||||
|
||||
#define QSPI_SC_LOCK(sc) mtx_lock(&(sc)->sc_mtx)
|
||||
#define QSPI_SC_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx)
|
||||
#define QSPI_SC_LOCK_INIT(sc) \
|
||||
mtx_init(&(sc)->sc_mtx, device_get_nameunit((sc)->dev), NULL, MTX_DEF)
|
||||
#define QSPI_SC_LOCK_DESTROY(sc) mtx_destroy(&(sc)->sc_mtx)
|
||||
#define QSPI_SC_ASSERT_LOCKED(sc) mtx_assert(&(sc)->sc_mtx, MA_OWNED)
|
||||
|
||||
#define RD4(sc, off) (bus_read_4((sc)->mem_res, (off)))
|
||||
#define WR4(sc, off, val) (bus_write_4((sc)->mem_res, (off), (val)))
|
||||
|
||||
/*
|
||||
* QSPI device registers.
|
||||
* Reference: Zynq-7000 All Programmable SoC Technical Reference Manual.
|
||||
* (v1.12.2) July 1, 2018. Xilinx doc UG585.
|
||||
*/
|
||||
#define ZY7_QSPI_CONFIG_REG 0x0000
|
||||
#define ZY7_QSPI_CONFIG_IFMODE (1U << 31)
|
||||
#define ZY7_QSPI_CONFIG_ENDIAN (1 << 26)
|
||||
#define ZY7_QSPI_CONFIG_HOLDB_DR (1 << 19)
|
||||
#define ZY7_QSPI_CONFIG_RSVD1 (1 << 17) /* must be 1 */
|
||||
#define ZY7_QSPI_CONFIG_MANSTRT (1 << 16)
|
||||
#define ZY7_QSPI_CONFIG_MANSTRTEN (1 << 15)
|
||||
#define ZY7_QSPI_CONFIG_SSFORCE (1 << 14)
|
||||
#define ZY7_QSPI_CONFIG_PCS (1 << 10)
|
||||
#define ZY7_QSPI_CONFIG_REF_CLK (1 << 8)
|
||||
#define ZY7_QSPI_CONFIG_FIFO_WIDTH_MASK (3 << 6)
|
||||
#define ZY7_QSPI_CONFIG_FIFO_WIDTH32 (3 << 6)
|
||||
#define ZY7_QSPI_CONFIG_BAUD_RATE_DIV_MASK (7 << 3)
|
||||
#define ZY7_QSPI_CONFIG_BAUD_RATE_DIV_SHIFT 3
|
||||
#define ZY7_QSPI_CONFIG_BAUD_RATE_DIV(x) ((x) << 3) /* divide by 2<<x */
|
||||
#define ZY7_QSPI_CONFIG_CLK_PH (1 << 2) /* clock phase */
|
||||
#define ZY7_QSPI_CONFIG_CLK_POL (1 << 1) /* clock polarity */
|
||||
#define ZY7_QSPI_CONFIG_MODE_SEL (1 << 0) /* master enable */
|
||||
|
||||
#define ZY7_QSPI_INTR_STAT_REG 0x0004
|
||||
#define ZY7_QSPI_INTR_EN_REG 0x0008
|
||||
#define ZY7_QSPI_INTR_DIS_REG 0x000c
|
||||
#define ZY7_QSPI_INTR_MASK_REG 0x0010
|
||||
#define ZY7_QSPI_INTR_TX_FIFO_UNDERFLOW (1 << 6)
|
||||
#define ZY7_QSPI_INTR_RX_FIFO_FULL (1 << 5)
|
||||
#define ZY7_QSPI_INTR_RX_FIFO_NOT_EMPTY (1 << 4)
|
||||
#define ZY7_QSPI_INTR_TX_FIFO_FULL (1 << 3)
|
||||
#define ZY7_QSPI_INTR_TX_FIFO_NOT_FULL (1 << 2)
|
||||
#define ZY7_QSPI_INTR_RX_OVERFLOW (1 << 0)
|
||||
|
||||
#define ZY7_QSPI_EN_REG 0x0014
|
||||
#define ZY7_SPI_ENABLE 1
|
||||
|
||||
#define ZY7_QSPI_DELAY_REG 0x0018
|
||||
#define ZY7_QSPI_DELAY_NSS_MASK (0xffU << 24)
|
||||
#define ZY7_QSPI_DELAY_NSS_SHIFT 24
|
||||
#define ZY7_QSPI_DELAY_NSS(x) ((x) << 24)
|
||||
#define ZY7_QSPI_DELAY_BTWN_MASK (0xff << 16)
|
||||
#define ZY7_QSPI_DELAY_BTWN_SHIFT 16
|
||||
#define ZY7_QSPI_DELAY_BTWN(x) ((x) << 16)
|
||||
#define ZY7_QSPI_DELAY_AFTER_MASK (0xff << 8)
|
||||
#define ZY7_QSPI_DELAY_AFTER_SHIFT 8
|
||||
#define ZY7_QSPI_DELAY_AFTER(x) ((x) << 8)
|
||||
#define ZY7_QSPI_DELAY_INIT_MASK 0xff
|
||||
#define ZY7_QSPI_DELAY_INIT_SHIFT 0
|
||||
#define ZY7_QSPI_DELAY_INIT(x) (x)
|
||||
|
||||
#define ZY7_QSPI_TXD0_REG 0x001c
|
||||
#define ZY7_QSPI_RX_DATA_REG 0x0020
|
||||
|
||||
#define ZY7_QSPI_SLV_IDLE_CT_REG 0x0024
|
||||
#define ZY7_QSPI_SLV_IDLE_CT_MASK 0xff
|
||||
|
||||
#define ZY7_QSPI_TX_THRESH_REG 0x0028
|
||||
#define ZY7_QSPI_RX_THRESH_REG 0x002c
|
||||
|
||||
#define ZY7_QSPI_GPIO_REG 0x0030
|
||||
#define ZY7_QSPI_GPIO_WP_N 1
|
||||
|
||||
#define ZY7_QSPI_LPBK_DLY_ADJ_REG 0x0038
|
||||
#define ZY7_QSPI_LPBK_DLY_ADJ_LPBK_SEL (1 << 8)
|
||||
#define ZY7_QSPI_LPBK_DLY_ADJ_LPBK_PH (1 << 7)
|
||||
#define ZY7_QSPI_LPBK_DLY_ADJ_USE_LPBK (1 << 5)
|
||||
#define ZY7_QSPI_LPBK_DLY_ADJ_DLY1_MASK (3 << 3)
|
||||
#define ZY7_QSPI_LPBK_DLY_ADJ_DLY1_SHIFT 3
|
||||
#define ZY7_QSPI_LPBK_DLY_ADJ_DLY1(x) ((x) << 3)
|
||||
#define ZY7_QSPI_LPBK_DLY_ADJ_DLY0_MASK 7
|
||||
#define ZY7_QSPI_LPBK_DLY_ADJ_DLY0_SHIFT 0
|
||||
#define ZY7_QSPI_LPBK_DLY_ADJ_DLY0(x) (x)
|
||||
|
||||
#define ZY7_QSPI_TXD1_REG 0x0080
|
||||
#define ZY7_QSPI_TXD2_REG 0x0084
|
||||
#define ZY7_QSPI_TXD3_REG 0x0088
|
||||
|
||||
#define ZY7_QSPI_LQSPI_CFG_REG 0x00a0
|
||||
#define ZY7_QSPI_LQSPI_CFG_LINEAR (1U << 31)
|
||||
#define ZY7_QSPI_LQSPI_CFG_TWO_MEM (1 << 30)
|
||||
#define ZY7_QSPI_LQSPI_CFG_SEP_BUS (1 << 29)
|
||||
#define ZY7_QSPI_LQSPI_CFG_U_PAGE (1 << 28)
|
||||
#define ZY7_QSPI_LQSPI_CFG_MODE_EN (1 << 25)
|
||||
#define ZY7_QSPI_LQSPI_CFG_MODE_ON (1 << 24)
|
||||
#define ZY7_QSPI_LQSPI_CFG_MODE_BITS_MASK (0xff << 16)
|
||||
#define ZY7_QSPI_LQSPI_CFG_MODE_BITS_SHIFT 16
|
||||
#define ZY7_QSPI_LQSPI_CFG_MODE_BITS(x) ((x) << 16)
|
||||
#define ZY7_QSPI_LQSPI_CFG_DUMMY_BYTES_MASK (7 << 8)
|
||||
#define ZY7_QSPI_LQSPI_CFG_DUMMY_BYTES_SHIFT 8
|
||||
#define ZY7_QSPI_LQSPI_CFG_DUMMY_BYTES(x) ((x) << 8)
|
||||
#define ZY7_QSPI_LQSPI_CFG_INST_CODE_MASK 0xff
|
||||
#define ZY7_QSPI_LQSPI_CFG_INST_CODE_SHIFT 0
|
||||
#define ZY7_QSPI_LQSPI_CFG_INST_CODE(x) (x)
|
||||
|
||||
#define ZY7_QSPI_LQSPI_STS_REG 0x00a4
|
||||
#define ZY7_QSPI_LQSPI_STS_D_FSM_ERR (1 << 2)
|
||||
#define ZY7_QSPI_LQSPI_STS_WR_RECVD (1 << 1)
|
||||
|
||||
#define ZY7_QSPI_MOD_ID_REG 0x00fc
|
||||
|
||||
static int zy7_qspi_detach(device_t);
|
||||
|
||||
/* Fill hardware fifo with command and data bytes. */
|
||||
static void
|
||||
zy7_qspi_write_fifo(struct zy7_qspi_softc *sc, int nbytes)
|
||||
{
|
||||
int n, nvalid;
|
||||
uint32_t data;
|
||||
|
||||
while (nbytes > 0) {
|
||||
nvalid = MIN(4, nbytes);
|
||||
data = 0xffffffff;
|
||||
|
||||
/*
|
||||
* A hardware bug forces us to wait until the tx fifo is
|
||||
* empty before writing partial words. We'll come back
|
||||
* next tx interrupt.
|
||||
*/
|
||||
if (nvalid < 4 && (RD4(sc, ZY7_QSPI_INTR_STAT_REG) &
|
||||
ZY7_QSPI_INTR_TX_FIFO_NOT_FULL) == 0)
|
||||
return;
|
||||
|
||||
if (sc->tx_bytes_sent < sc->cmd->tx_cmd_sz) {
|
||||
/* Writing command. */
|
||||
n = MIN(nvalid, sc->cmd->tx_cmd_sz -
|
||||
sc->tx_bytes_sent);
|
||||
memcpy(&data, (uint8_t *)sc->cmd->tx_cmd +
|
||||
sc->tx_bytes_sent, n);
|
||||
|
||||
if (nvalid > n) {
|
||||
/* Writing start of data. */
|
||||
memcpy((uint8_t *)&data + n,
|
||||
sc->cmd->tx_data, nvalid - n);
|
||||
}
|
||||
} else
|
||||
/* Writing data. */
|
||||
memcpy(&data, (uint8_t *)sc->cmd->tx_data +
|
||||
(sc->tx_bytes_sent - sc->cmd->tx_cmd_sz), nvalid);
|
||||
|
||||
switch (nvalid) {
|
||||
case 1:
|
||||
WR4(sc, ZY7_QSPI_TXD1_REG, data);
|
||||
break;
|
||||
case 2:
|
||||
WR4(sc, ZY7_QSPI_TXD2_REG, data);
|
||||
break;
|
||||
case 3:
|
||||
WR4(sc, ZY7_QSPI_TXD3_REG, data);
|
||||
break;
|
||||
case 4:
|
||||
WR4(sc, ZY7_QSPI_TXD0_REG, data);
|
||||
break;
|
||||
}
|
||||
|
||||
sc->tx_bytes_sent += nvalid;
|
||||
nbytes -= nvalid;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Read hardware fifo data into command response and data buffers. */
|
||||
static void
|
||||
zy7_qspi_read_fifo(struct zy7_qspi_softc *sc)
|
||||
{
|
||||
int n, nbytes;
|
||||
uint32_t data;
|
||||
|
||||
do {
|
||||
data = RD4(sc, ZY7_QSPI_RX_DATA_REG);
|
||||
nbytes = MIN(4, sc->rx_bytes - sc->rx_bytes_rcvd);
|
||||
|
||||
/*
|
||||
* Last word in non-word-multiple transfer is packed
|
||||
* non-intuitively.
|
||||
*/
|
||||
if (nbytes < 4)
|
||||
data >>= 8 * (4 - nbytes);
|
||||
|
||||
if (sc->rx_bytes_rcvd < sc->cmd->rx_cmd_sz) {
|
||||
/* Reading command. */
|
||||
n = MIN(nbytes, sc->cmd->rx_cmd_sz -
|
||||
sc->rx_bytes_rcvd);
|
||||
memcpy((uint8_t *)sc->cmd->rx_cmd + sc->rx_bytes_rcvd,
|
||||
&data, n);
|
||||
sc->rx_bytes_rcvd += n;
|
||||
nbytes -= n;
|
||||
data >>= 8 * n;
|
||||
}
|
||||
|
||||
if (nbytes > 0) {
|
||||
/* Reading data. */
|
||||
memcpy((uint8_t *)sc->cmd->rx_data +
|
||||
(sc->rx_bytes_rcvd - sc->cmd->rx_cmd_sz),
|
||||
&data, nbytes);
|
||||
sc->rx_bytes_rcvd += nbytes;
|
||||
}
|
||||
|
||||
} while (sc->rx_bytes_rcvd < sc->rx_bytes &&
|
||||
(RD4(sc, ZY7_QSPI_INTR_STAT_REG) &
|
||||
ZY7_QSPI_INTR_RX_FIFO_NOT_EMPTY) != 0);
|
||||
}
|
||||
|
||||
/* End a transfer early by draining rx fifo and disabling interrupts. */
|
||||
static void
|
||||
zy7_qspi_abort_transfer(struct zy7_qspi_softc *sc)
|
||||
{
|
||||
/* Drain receive fifo. */
|
||||
while ((RD4(sc, ZY7_QSPI_INTR_STAT_REG) &
|
||||
ZY7_QSPI_INTR_RX_FIFO_NOT_EMPTY) != 0)
|
||||
(void)RD4(sc, ZY7_QSPI_RX_DATA_REG);
|
||||
|
||||
/* Shut down interrupts. */
|
||||
WR4(sc, ZY7_QSPI_INTR_DIS_REG,
|
||||
ZY7_QSPI_INTR_RX_OVERFLOW |
|
||||
ZY7_QSPI_INTR_RX_FIFO_NOT_EMPTY |
|
||||
ZY7_QSPI_INTR_TX_FIFO_NOT_FULL);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
zy7_qspi_intr(void *arg)
|
||||
{
|
||||
struct zy7_qspi_softc *sc = (struct zy7_qspi_softc *)arg;
|
||||
uint32_t istatus;
|
||||
|
||||
QSPI_SC_LOCK(sc);
|
||||
|
||||
sc->interrupts++;
|
||||
|
||||
istatus = RD4(sc, ZY7_QSPI_INTR_STAT_REG);
|
||||
|
||||
/* Stray interrupts can happen if a transfer gets interrupted. */
|
||||
if (!sc->busy) {
|
||||
sc->stray_ints++;
|
||||
QSPI_SC_UNLOCK(sc);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((istatus & ZY7_QSPI_INTR_RX_OVERFLOW) != 0) {
|
||||
device_printf(sc->dev, "rx fifo overflow!\n");
|
||||
sc->rx_overflows++;
|
||||
|
||||
/* Clear status bit. */
|
||||
WR4(sc, ZY7_QSPI_INTR_STAT_REG,
|
||||
ZY7_QSPI_INTR_RX_OVERFLOW);
|
||||
}
|
||||
|
||||
/* Empty receive fifo before any more transmit data is sent. */
|
||||
if (sc->rx_bytes_rcvd < sc->rx_bytes &&
|
||||
(istatus & ZY7_QSPI_INTR_RX_FIFO_NOT_EMPTY) != 0) {
|
||||
zy7_qspi_read_fifo(sc);
|
||||
if (sc->rx_bytes_rcvd == sc->rx_bytes)
|
||||
/* Disable receive interrupts. */
|
||||
WR4(sc, ZY7_QSPI_INTR_DIS_REG,
|
||||
ZY7_QSPI_INTR_RX_FIFO_NOT_EMPTY |
|
||||
ZY7_QSPI_INTR_RX_OVERFLOW);
|
||||
}
|
||||
|
||||
/*
|
||||
* Transmit underflows aren't really a bug because a hardware
|
||||
* bug forces us to allow the tx fifo to go empty between full
|
||||
* and partial fifo writes. Why bother counting?
|
||||
*/
|
||||
if ((istatus & ZY7_QSPI_INTR_TX_FIFO_UNDERFLOW) != 0) {
|
||||
sc->tx_underflows++;
|
||||
|
||||
/* Clear status bit. */
|
||||
WR4(sc, ZY7_QSPI_INTR_STAT_REG,
|
||||
ZY7_QSPI_INTR_TX_FIFO_UNDERFLOW);
|
||||
}
|
||||
|
||||
/* Fill transmit fifo. */
|
||||
if (sc->tx_bytes_sent < sc->tx_bytes &&
|
||||
(istatus & ZY7_QSPI_INTR_TX_FIFO_NOT_FULL) != 0) {
|
||||
zy7_qspi_write_fifo(sc, MIN(240, sc->tx_bytes -
|
||||
sc->tx_bytes_sent));
|
||||
|
||||
if (sc->tx_bytes_sent == sc->tx_bytes) {
|
||||
/*
|
||||
* Disable transmit FIFO interrupt, enable receive
|
||||
* FIFO interrupt.
|
||||
*/
|
||||
WR4(sc, ZY7_QSPI_INTR_DIS_REG,
|
||||
ZY7_QSPI_INTR_TX_FIFO_NOT_FULL);
|
||||
WR4(sc, ZY7_QSPI_INTR_EN_REG,
|
||||
ZY7_QSPI_INTR_RX_FIFO_NOT_EMPTY);
|
||||
}
|
||||
}
|
||||
|
||||
/* Finished with transfer? */
|
||||
if (sc->tx_bytes_sent == sc->tx_bytes &&
|
||||
sc->rx_bytes_rcvd == sc->rx_bytes) {
|
||||
|
||||
/* De-assert CS. */
|
||||
sc->cfg_reg_shadow |= ZY7_QSPI_CONFIG_PCS;
|
||||
WR4(sc, ZY7_QSPI_CONFIG_REG, sc->cfg_reg_shadow);
|
||||
|
||||
wakeup(sc->dev);
|
||||
}
|
||||
|
||||
QSPI_SC_UNLOCK(sc);
|
||||
}
|
||||
|
||||
/* Initialize hardware. */
|
||||
static int
|
||||
zy7_qspi_init_hw(struct zy7_qspi_softc *sc)
|
||||
{
|
||||
uint32_t baud_div;
|
||||
|
||||
/* Configure LQSPI Config register. Disable linear mode. */
|
||||
sc->lqspi_cfg_shadow = RD4(sc, ZY7_QSPI_LQSPI_CFG_REG);
|
||||
sc->lqspi_cfg_shadow &= ~(ZY7_QSPI_LQSPI_CFG_LINEAR |
|
||||
ZY7_QSPI_LQSPI_CFG_TWO_MEM |
|
||||
ZY7_QSPI_LQSPI_CFG_SEP_BUS);
|
||||
if (sc->is_dual) {
|
||||
sc->lqspi_cfg_shadow |= ZY7_QSPI_LQSPI_CFG_TWO_MEM;
|
||||
if (sc->is_stacked) {
|
||||
sc->lqspi_cfg_shadow &=
|
||||
~ZY7_QSPI_LQSPI_CFG_INST_CODE_MASK;
|
||||
sc->lqspi_cfg_shadow |=
|
||||
ZY7_QSPI_LQSPI_CFG_INST_CODE(sc->is_dio ?
|
||||
CMD_READ_DUAL_IO : CMD_READ_QUAD_OUTPUT);
|
||||
} else
|
||||
sc->lqspi_cfg_shadow |= ZY7_QSPI_LQSPI_CFG_SEP_BUS;
|
||||
}
|
||||
WR4(sc, ZY7_QSPI_LQSPI_CFG_REG, sc->lqspi_cfg_shadow);
|
||||
|
||||
/* Find best clock divider. */
|
||||
baud_div = 0;
|
||||
while ((sc->ref_clock >> (baud_div + 1)) > sc->spi_clock &&
|
||||
baud_div < 8)
|
||||
baud_div++;
|
||||
if (baud_div >= 8) {
|
||||
device_printf(sc->dev, "cannot configure clock divider: ref=%d"
|
||||
" spi=%d.\n", sc->ref_clock, sc->spi_clock);
|
||||
return (EINVAL);
|
||||
}
|
||||
sc->spi_clk_real_freq = sc->ref_clock >> (baud_div + 1);
|
||||
|
||||
/*
|
||||
* If divider is 2 (the max speed), use internal loopback master
|
||||
* clock for read data. (See section 12.3.1 in ref man.)
|
||||
*/
|
||||
if (baud_div == 0)
|
||||
WR4(sc, ZY7_QSPI_LPBK_DLY_ADJ_REG,
|
||||
ZY7_QSPI_LPBK_DLY_ADJ_USE_LPBK |
|
||||
ZY7_QSPI_LPBK_DLY_ADJ_DLY1(0) |
|
||||
ZY7_QSPI_LPBK_DLY_ADJ_DLY0(0));
|
||||
else
|
||||
WR4(sc, ZY7_QSPI_LPBK_DLY_ADJ_REG, 0);
|
||||
|
||||
/* Set up configuration register. */
|
||||
sc->cfg_reg_shadow =
|
||||
ZY7_QSPI_CONFIG_IFMODE |
|
||||
ZY7_QSPI_CONFIG_HOLDB_DR |
|
||||
ZY7_QSPI_CONFIG_RSVD1 |
|
||||
ZY7_QSPI_CONFIG_SSFORCE |
|
||||
ZY7_QSPI_CONFIG_PCS |
|
||||
ZY7_QSPI_CONFIG_FIFO_WIDTH32 |
|
||||
ZY7_QSPI_CONFIG_BAUD_RATE_DIV(baud_div) |
|
||||
ZY7_QSPI_CONFIG_MODE_SEL;
|
||||
WR4(sc, ZY7_QSPI_CONFIG_REG, sc->cfg_reg_shadow);
|
||||
|
||||
/*
|
||||
* Set thresholds. We must use 1 for tx threshold because there
|
||||
* is no fifo empty flag and we need one to implement a bug
|
||||
* workaround.
|
||||
*/
|
||||
WR4(sc, ZY7_QSPI_TX_THRESH_REG, 1);
|
||||
WR4(sc, ZY7_QSPI_RX_THRESH_REG, 1);
|
||||
|
||||
/* Clear and disable all interrupts. */
|
||||
WR4(sc, ZY7_QSPI_INTR_STAT_REG, ~0);
|
||||
WR4(sc, ZY7_QSPI_INTR_DIS_REG, ~0);
|
||||
|
||||
/* Enable SPI. */
|
||||
WR4(sc, ZY7_QSPI_EN_REG, ZY7_SPI_ENABLE);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
zy7_qspi_add_sysctls(device_t dev)
|
||||
{
|
||||
struct zy7_qspi_softc *sc = device_get_softc(dev);
|
||||
struct sysctl_ctx_list *ctx;
|
||||
struct sysctl_oid_list *child;
|
||||
|
||||
ctx = device_get_sysctl_ctx(dev);
|
||||
child = SYSCTL_CHILDREN(device_get_sysctl_tree(dev));
|
||||
|
||||
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "spi_clk_real_freq", CTLFLAG_RD,
|
||||
&sc->spi_clk_real_freq, 0, "SPI clock real frequency");
|
||||
|
||||
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "rx_overflows", CTLFLAG_RD,
|
||||
&sc->rx_overflows, 0, "RX FIFO overflow events");
|
||||
|
||||
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "tx_underflows", CTLFLAG_RD,
|
||||
&sc->tx_underflows, 0, "TX FIFO underflow events");
|
||||
|
||||
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "interrupts", CTLFLAG_RD,
|
||||
&sc->interrupts, 0, "interrupt calls");
|
||||
|
||||
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "stray_ints", CTLFLAG_RD,
|
||||
&sc->stray_ints, 0, "stray interrupts");
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
zy7_qspi_probe(device_t dev)
|
||||
{
|
||||
|
||||
if (!ofw_bus_status_okay(dev))
|
||||
return (ENXIO);
|
||||
|
||||
if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
|
||||
return (ENXIO);
|
||||
|
||||
device_set_desc(dev, "Zynq Quad-SPI Flash Controller");
|
||||
|
||||
return (BUS_PROBE_DEFAULT);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
zy7_qspi_attach(device_t dev)
|
||||
{
|
||||
struct zy7_qspi_softc *sc;
|
||||
int rid, err;
|
||||
phandle_t node;
|
||||
pcell_t cell;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
sc->dev = dev;
|
||||
|
||||
QSPI_SC_LOCK_INIT(sc);
|
||||
|
||||
/* Get ref-clock, spi-clock, and other properties. */
|
||||
node = ofw_bus_get_node(dev);
|
||||
if (OF_getprop(node, "ref-clock", &cell, sizeof(cell)) > 0)
|
||||
sc->ref_clock = fdt32_to_cpu(cell);
|
||||
else {
|
||||
device_printf(dev, "must have ref-clock property\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
if (OF_getprop(node, "spi-clock", &cell, sizeof(cell)) > 0)
|
||||
sc->spi_clock = fdt32_to_cpu(cell);
|
||||
else
|
||||
sc->spi_clock = ZY7_QSPI_DEFAULT_SPI_CLOCK;
|
||||
if (OF_getprop(node, "is-stacked", &cell, sizeof(cell)) > 0 &&
|
||||
fdt32_to_cpu(cell) != 0) {
|
||||
sc->is_dual = 1;
|
||||
sc->is_stacked = 1;
|
||||
} else if (OF_getprop(node, "is-dual", &cell, sizeof(cell)) > 0 &&
|
||||
fdt32_to_cpu(cell) != 0)
|
||||
sc->is_dual = 1;
|
||||
if (OF_getprop(node, "is-dio", &cell, sizeof(cell)) > 0 &&
|
||||
fdt32_to_cpu(cell) != 0)
|
||||
sc->is_dio = 1;
|
||||
|
||||
/* Get memory resource. */
|
||||
rid = 0;
|
||||
sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
|
||||
RF_ACTIVE);
|
||||
if (sc->mem_res == NULL) {
|
||||
device_printf(dev, "could not allocate memory resources.\n");
|
||||
zy7_qspi_detach(dev);
|
||||
return (ENOMEM);
|
||||
}
|
||||
|
||||
/* Allocate IRQ. */
|
||||
rid = 0;
|
||||
sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
|
||||
RF_ACTIVE);
|
||||
if (sc->irq_res == NULL) {
|
||||
device_printf(dev, "could not allocate IRQ resource.\n");
|
||||
zy7_qspi_detach(dev);
|
||||
return (ENOMEM);
|
||||
}
|
||||
|
||||
/* Activate the interrupt. */
|
||||
err = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
|
||||
NULL, zy7_qspi_intr, sc, &sc->intrhandle);
|
||||
if (err) {
|
||||
device_printf(dev, "could not setup IRQ.\n");
|
||||
zy7_qspi_detach(dev);
|
||||
return (err);
|
||||
}
|
||||
|
||||
/* Configure the device. */
|
||||
err = zy7_qspi_init_hw(sc);
|
||||
if (err) {
|
||||
zy7_qspi_detach(dev);
|
||||
return (err);
|
||||
}
|
||||
|
||||
sc->child = device_add_child(dev, "spibus", -1);
|
||||
|
||||
zy7_qspi_add_sysctls(dev);
|
||||
|
||||
/* Attach spibus driver as a child later when interrupts work. */
|
||||
config_intrhook_oneshot((ich_func_t)bus_generic_attach, dev);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
zy7_qspi_detach(device_t dev)
|
||||
{
|
||||
struct zy7_qspi_softc *sc = device_get_softc(dev);
|
||||
|
||||
if (device_is_attached(dev))
|
||||
bus_generic_detach(dev);
|
||||
|
||||
/* Delete child bus. */
|
||||
if (sc->child)
|
||||
device_delete_child(dev, sc->child);
|
||||
|
||||
/* Disable hardware. */
|
||||
if (sc->mem_res != NULL) {
|
||||
/* Disable SPI. */
|
||||
WR4(sc, ZY7_QSPI_EN_REG, 0);
|
||||
|
||||
/* Clear and disable all interrupts. */
|
||||
WR4(sc, ZY7_QSPI_INTR_STAT_REG, ~0);
|
||||
WR4(sc, ZY7_QSPI_INTR_DIS_REG, ~0);
|
||||
}
|
||||
|
||||
/* Teardown and release interrupt. */
|
||||
if (sc->irq_res != NULL) {
|
||||
if (sc->intrhandle)
|
||||
bus_teardown_intr(dev, sc->irq_res, sc->intrhandle);
|
||||
bus_release_resource(dev, SYS_RES_IRQ,
|
||||
rman_get_rid(sc->irq_res), sc->irq_res);
|
||||
}
|
||||
|
||||
/* Release memory resource. */
|
||||
if (sc->mem_res != NULL)
|
||||
bus_release_resource(dev, SYS_RES_MEMORY,
|
||||
rman_get_rid(sc->mem_res), sc->mem_res);
|
||||
|
||||
QSPI_SC_LOCK_DESTROY(sc);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
static phandle_t
|
||||
zy7_qspi_get_node(device_t bus, device_t dev)
|
||||
{
|
||||
|
||||
return (ofw_bus_get_node(bus));
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
zy7_qspi_transfer(device_t dev, device_t child, struct spi_command *cmd)
|
||||
{
|
||||
struct zy7_qspi_softc *sc = device_get_softc(dev);
|
||||
int err = 0;
|
||||
|
||||
KASSERT(cmd->tx_cmd_sz == cmd->rx_cmd_sz,
|
||||
("TX/RX command sizes should be equal"));
|
||||
KASSERT(cmd->tx_data_sz == cmd->rx_data_sz,
|
||||
("TX/RX data sizes should be equal"));
|
||||
|
||||
if (sc->is_dual && cmd->tx_data_sz % 2 != 0) {
|
||||
device_printf(dev, "driver does not support odd byte data "
|
||||
"transfers in dual mode. (sz=%d)\n", cmd->tx_data_sz);
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
QSPI_SC_LOCK(sc);
|
||||
|
||||
/* Wait for controller available. */
|
||||
while (sc->busy != 0) {
|
||||
err = mtx_sleep(dev, &sc->sc_mtx, 0, "zqspi0", 0);
|
||||
if (err) {
|
||||
QSPI_SC_UNLOCK(sc);
|
||||
return (err);
|
||||
}
|
||||
}
|
||||
|
||||
/* Start transfer. */
|
||||
sc->busy = 1;
|
||||
sc->cmd = cmd;
|
||||
sc->tx_bytes = sc->cmd->tx_cmd_sz + sc->cmd->tx_data_sz;
|
||||
sc->tx_bytes_sent = 0;
|
||||
sc->rx_bytes = sc->cmd->rx_cmd_sz + sc->cmd->rx_data_sz;
|
||||
sc->rx_bytes_rcvd = 0;
|
||||
|
||||
/* Enable interrupts. zy7_qspi_intr() will handle transfer. */
|
||||
WR4(sc, ZY7_QSPI_INTR_EN_REG,
|
||||
ZY7_QSPI_INTR_TX_FIFO_NOT_FULL |
|
||||
ZY7_QSPI_INTR_RX_OVERFLOW);
|
||||
|
||||
#ifdef SPI_XFER_U_PAGE /* XXX: future support for stacked memories. */
|
||||
if (sc->is_stacked) {
|
||||
if ((cmd->flags & SPI_XFER_U_PAGE) != 0)
|
||||
sc->lqspi_cfg_shadow |= ZY7_QSPI_LQSPI_CFG_U_PAGE;
|
||||
else
|
||||
sc->lqspi_cfg_shadow &= ~ZY7_QSPI_LQSPI_CFG_U_PAGE;
|
||||
WR4(sc, ZY7_QSPI_LQSPI_CFG_REG, sc->lqspi_cfg_shadow);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Assert CS. */
|
||||
sc->cfg_reg_shadow &= ~ZY7_QSPI_CONFIG_PCS;
|
||||
WR4(sc, ZY7_QSPI_CONFIG_REG, sc->cfg_reg_shadow);
|
||||
|
||||
/* Wait for completion. */
|
||||
err = mtx_sleep(dev, &sc->sc_mtx, 0, "zqspi1", hz * 2);
|
||||
if (err)
|
||||
zy7_qspi_abort_transfer(sc);
|
||||
|
||||
/* Release controller. */
|
||||
sc->busy = 0;
|
||||
wakeup_one(dev);
|
||||
|
||||
QSPI_SC_UNLOCK(sc);
|
||||
|
||||
return (err);
|
||||
}
|
||||
|
||||
static device_method_t zy7_qspi_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, zy7_qspi_probe),
|
||||
DEVMETHOD(device_attach, zy7_qspi_attach),
|
||||
DEVMETHOD(device_detach, zy7_qspi_detach),
|
||||
|
||||
/* SPI interface */
|
||||
DEVMETHOD(spibus_transfer, zy7_qspi_transfer),
|
||||
|
||||
/* ofw_bus interface */
|
||||
DEVMETHOD(ofw_bus_get_node, zy7_qspi_get_node),
|
||||
|
||||
DEVMETHOD_END
|
||||
};
|
||||
|
||||
|
||||
static driver_t zy7_qspi_driver = {
|
||||
"zy7_qspi",
|
||||
zy7_qspi_methods,
|
||||
sizeof(struct zy7_qspi_softc),
|
||||
};
|
||||
static devclass_t zy7_qspi_devclass;
|
||||
|
||||
DRIVER_MODULE(zy7_qspi, simplebus, zy7_qspi_driver, zy7_qspi_devclass, 0, 0);
|
||||
DRIVER_MODULE(ofw_spibus, zy7_qspi, ofw_spibus_driver, ofw_spibus_devclass, 0, 0);
|
||||
SIMPLEBUS_PNP_INFO(compat_data);
|
||||
MODULE_DEPEND(zy7_qspi, ofw_spibus, 1, 1, 1);
|
@ -2,27 +2,6 @@
|
||||
#
|
||||
# $FreeBSD$
|
||||
|
||||
# Don't use an OBJDIR
|
||||
.OBJDIR: ${.CURDIR}
|
||||
GENERATED_PREFIX= linux_
|
||||
|
||||
.include <src.lua.mk>
|
||||
|
||||
MAKESYSCALLS= ../../tools/makesyscalls.lua
|
||||
SRCS= syscalls.conf \
|
||||
syscalls.master
|
||||
GENERATED= linux_proto.h \
|
||||
linux_syscall.h \
|
||||
linux_syscalls.c \
|
||||
linux_sysent.c \
|
||||
linux_systrace_args.c
|
||||
|
||||
all:
|
||||
@echo "make sysent only"
|
||||
|
||||
# We .ORDER these explicitly so that we only run MAKESYSCALLS once, rather than
|
||||
# potentially once for each ${GENERATED} file.
|
||||
.ORDER: ${GENERATED}
|
||||
sysent: ${GENERATED}
|
||||
|
||||
${GENERATED}: ${MAKESYSCALLS} ${SRCS}
|
||||
${LUA} ${MAKESYSCALLS} syscalls.master syscalls.conf
|
||||
.include "../../conf/sysent.mk"
|
||||
|
@ -97,6 +97,9 @@ struct rk805_softc {
|
||||
int nregs;
|
||||
};
|
||||
|
||||
static int rk805_regnode_set_voltage(struct regnode *regnode, int min_uvolt,
|
||||
int max_uvolt, int *udelay);
|
||||
|
||||
static struct rk805_regdef rk805_regdefs[] = {
|
||||
{
|
||||
.id = RK805_DCDC1,
|
||||
@ -354,7 +357,26 @@ rk805_write(device_t dev, uint8_t reg, uint8_t data)
|
||||
static int
|
||||
rk805_regnode_init(struct regnode *regnode)
|
||||
{
|
||||
return (0);
|
||||
struct rk805_reg_sc *sc;
|
||||
struct regnode_std_param *param;
|
||||
int rv, udelay;
|
||||
|
||||
sc = regnode_get_softc(regnode);
|
||||
param = regnode_get_stdparam(regnode);
|
||||
if (param->min_uvolt == 0)
|
||||
return (0);
|
||||
|
||||
/*
|
||||
* Set the regulator at the correct voltage
|
||||
* Do not enable it, this is will be done either by a
|
||||
* consumer or by regnode_set_constraint if boot_on is true
|
||||
*/
|
||||
rv = rk805_regnode_set_voltage(regnode, param->min_uvolt,
|
||||
param->max_uvolt, &udelay);
|
||||
if (rv != 0)
|
||||
DELAY(udelay);
|
||||
|
||||
return (rv);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -1,27 +1,6 @@
|
||||
# $FreeBSD$
|
||||
|
||||
# Don't use an OBJDIR
|
||||
.OBJDIR: ${.CURDIR}
|
||||
SYSENT_FILE= ${SYSDIR}/contrib/cloudabi/syscalls32.master
|
||||
GENERATED_PREFIX= cloudabi32_
|
||||
|
||||
.include <src.lua.mk>
|
||||
|
||||
MAKESYSCALLS= ../../tools/makesyscalls.lua
|
||||
SRCS= syscalls.conf \
|
||||
../../contrib/cloudabi/syscalls32.master
|
||||
GENERATED= cloudabi32_proto.h \
|
||||
cloudabi32_syscall.h \
|
||||
cloudabi32_syscalls.c \
|
||||
cloudabi32_sysent.c \
|
||||
cloudabi32_systrace_args.c
|
||||
|
||||
all:
|
||||
@echo "make sysent only"
|
||||
|
||||
# We .ORDER these explicitly so that we only run MAKESYSCALLS once, rather than
|
||||
# potentially once for each ${GENERATED} file.
|
||||
.ORDER: ${GENERATED}
|
||||
sysent: ${GENERATED}
|
||||
|
||||
${GENERATED}: ${MAKESYSCALLS} ${SRCS}
|
||||
${LUA} ${MAKESYSCALLS} \
|
||||
../../contrib/cloudabi/syscalls32.master syscalls.conf
|
||||
.include "../../conf/sysent.mk"
|
||||
|
@ -1,27 +1,6 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.include <src.lua.mk>
|
||||
SYSENT_FILE= ${SYSDIR}/contrib/cloudabi/syscalls64.master
|
||||
GENERATED_PREFIX= cloudabi64_
|
||||
|
||||
# Don't use an OBJDIR
|
||||
.OBJDIR: ${.CURDIR}
|
||||
|
||||
MAKESYSCALLS= ../../tools/makesyscalls.lua
|
||||
SRCS= syscalls.conf \
|
||||
../../contrib/cloudabi/syscalls64.master
|
||||
GENERATED= cloudabi64_proto.h \
|
||||
cloudabi64_syscall.h \
|
||||
cloudabi64_syscalls.c \
|
||||
cloudabi64_sysent.c \
|
||||
cloudabi64_systrace_args.c
|
||||
|
||||
all:
|
||||
@echo "make sysent only"
|
||||
|
||||
# We .ORDER these explicitly so that we only run MAKESYSCALLS once, rather than
|
||||
# potentially once for each ${GENERATED} file.
|
||||
.ORDER: ${GENERATED}
|
||||
sysent: ${GENERATED}
|
||||
|
||||
${GENERATED}: ${MAKESYSCALLS} ${SRCS}
|
||||
${LUA} ${MAKESYSCALLS} \
|
||||
../../contrib/cloudabi/syscalls64.master syscalls.conf
|
||||
.include "../../conf/sysent.mk"
|
||||
|
@ -2,28 +2,6 @@
|
||||
#
|
||||
# $FreeBSD$
|
||||
|
||||
# Don't use an OBJDIR
|
||||
.OBJDIR: ${.CURDIR}
|
||||
GENERATED_PREFIX= freebsd32_
|
||||
|
||||
.include <src.lua.mk>
|
||||
|
||||
MAKESYSCALLS= ../../tools/makesyscalls.lua
|
||||
SRCS= ../../kern/capabilities.conf \
|
||||
syscalls.conf \
|
||||
syscalls.master
|
||||
GENERATED= freebsd32_proto.h \
|
||||
freebsd32_syscall.h \
|
||||
freebsd32_syscalls.c \
|
||||
freebsd32_sysent.c \
|
||||
freebsd32_systrace_args.c
|
||||
|
||||
all:
|
||||
@echo "make sysent only"
|
||||
|
||||
# We .ORDER these explicitly so that we only run MAKESYSCALLS once, rather than
|
||||
# potentially once for each ${GENERATED} file.
|
||||
.ORDER: ${GENERATED}
|
||||
sysent: ${GENERATED}
|
||||
|
||||
${GENERATED}: ${MAKESYSCALLS} ${SRCS}
|
||||
${LUA} ${MAKESYSCALLS} syscalls.master syscalls.conf
|
||||
.include "../../conf/sysent.mk"
|
||||
|
@ -1078,9 +1078,14 @@ int
|
||||
linux_umount(struct thread *td, struct linux_umount_args *args)
|
||||
{
|
||||
struct unmount_args bsd;
|
||||
int flags;
|
||||
|
||||
flags = 0;
|
||||
if ((args->flags & LINUX_MNT_FORCE) != 0)
|
||||
flags |= MNT_FORCE;
|
||||
|
||||
bsd.path = args->path;
|
||||
bsd.flags = args->flags; /* XXX correct? */
|
||||
bsd.flags = flags;
|
||||
return (sys_unmount(td, &bsd));
|
||||
}
|
||||
#endif
|
||||
|
@ -56,6 +56,11 @@
|
||||
#define LINUX_MS_NOEXEC 0x0008
|
||||
#define LINUX_MS_REMOUNT 0x0020
|
||||
|
||||
/*
|
||||
* umount2 flags
|
||||
*/
|
||||
#define LINUX_MNT_FORCE 0x0001
|
||||
|
||||
/*
|
||||
* common open/fcntl flags
|
||||
*/
|
||||
|
@ -107,6 +107,7 @@ powerpc/aim/moea64_native.c optional aim
|
||||
powerpc/aim/mp_cpudep.c optional aim
|
||||
powerpc/aim/slb.c optional aim powerpc64
|
||||
powerpc/amigaone/platform_amigaone.c optional amigaone
|
||||
powerpc/amigaone/cpld_x5000.c optional powerpc amigaone | powerpc64 amigaone
|
||||
powerpc/booke/locore.S optional booke no-obj
|
||||
powerpc/booke/booke_machdep.c optional booke
|
||||
powerpc/booke/machdep_e500.c optional booke_e500
|
||||
|
35
sys/conf/sysent.mk
Normal file
35
sys/conf/sysent.mk
Normal file
@ -0,0 +1,35 @@
|
||||
# $FreeBSD$
|
||||
|
||||
# Don't use an OBJDIR
|
||||
.OBJDIR: ${.CURDIR}
|
||||
|
||||
.include <bsd.sysdir.mk>
|
||||
.include <src.lua.mk>
|
||||
|
||||
COMMON_GENERATED= proto.h \
|
||||
syscall.h \
|
||||
syscalls.c \
|
||||
sysent.c \
|
||||
systrace_args.c
|
||||
|
||||
GENERATED_PREFIX?=
|
||||
GENERATED?= ${COMMON_GENERATED:S/^/${GENERATED_PREFIX}/}
|
||||
SYSENT_FILE?= syscalls.master
|
||||
SYSENT_CONF?= syscalls.conf
|
||||
|
||||
# Including Makefile should override SYSENT_FILE and SYSENT_CONF as needed,
|
||||
# and set GENERATED.
|
||||
SRCS+= ${SYSENT_FILE}
|
||||
SRCS+= ${SYSENT_CONF}
|
||||
MAKESYSCALLS= ${SYSDIR}/tools/makesyscalls.lua
|
||||
|
||||
all:
|
||||
@echo "make sysent only"
|
||||
|
||||
# We .ORDER these explicitly so that we only run MAKESYSCALLS once, rather than
|
||||
# potentially once for each ${GENERATED} file.
|
||||
.ORDER: ${GENERATED}
|
||||
sysent: ${GENERATED}
|
||||
|
||||
${GENERATED}: ${MAKESYSCALLS} ${SRCS}
|
||||
${LUA} ${MAKESYSCALLS} ${SYSENT_FILE} ${SYSENT_CONF}
|
@ -319,6 +319,7 @@ s32 e1000_set_mac_type(struct e1000_hw *hw)
|
||||
case E1000_DEV_ID_PCH_ICP_I219_V8:
|
||||
case E1000_DEV_ID_PCH_ICP_I219_LM9:
|
||||
case E1000_DEV_ID_PCH_ICP_I219_V9:
|
||||
case E1000_DEV_ID_PCH_ICP_I219_V10:
|
||||
mac->type = e1000_pch_cnp;
|
||||
break;
|
||||
case E1000_DEV_ID_82575EB_COPPER:
|
||||
|
@ -155,6 +155,7 @@ struct e1000_hw;
|
||||
#define E1000_DEV_ID_PCH_ICP_I219_V8 0x15E0
|
||||
#define E1000_DEV_ID_PCH_ICP_I219_LM9 0x15E1
|
||||
#define E1000_DEV_ID_PCH_ICP_I219_V9 0x15E2
|
||||
#define E1000_DEV_ID_PCH_ICP_I219_V10 0x0D4F
|
||||
#define E1000_DEV_ID_82576 0x10C9
|
||||
#define E1000_DEV_ID_82576_FIBER 0x10E6
|
||||
#define E1000_DEV_ID_82576_SERDES 0x10E7
|
||||
|
@ -174,6 +174,7 @@ static pci_vendor_info_t em_vendor_info_array[] =
|
||||
PVID(0x8086, E1000_DEV_ID_PCH_ICP_I219_V8, "Intel(R) PRO/1000 Network Connection"),
|
||||
PVID(0x8086, E1000_DEV_ID_PCH_ICP_I219_LM9, "Intel(R) PRO/1000 Network Connection"),
|
||||
PVID(0x8086, E1000_DEV_ID_PCH_ICP_I219_V9, "Intel(R) PRO/1000 Network Connection"),
|
||||
PVID(0x8086, E1000_DEV_ID_PCH_ICP_I219_V10, "Intel(R) PRO/1000 Network Connection"),
|
||||
/* required last entry */
|
||||
PVID_END
|
||||
};
|
||||
|
@ -42,6 +42,8 @@
|
||||
#define CMD_WRITE_STATUS 0x01
|
||||
#define CMD_READ 0x03
|
||||
#define CMD_FAST_READ 0x0B
|
||||
#define CMD_READ_DUAL_IO 0xBB
|
||||
#define CMD_READ_QUAD_OUTPUT 0x6B
|
||||
#define CMD_PAGE_PROGRAM 0x02
|
||||
#define CMD_SECTOR_ERASE 0xD8
|
||||
#define CMD_BULK_ERASE 0xC7
|
||||
|
@ -1057,11 +1057,12 @@ mdstart_swap(struct md_s *sc, struct bio *bp)
|
||||
lastend = (bp->bio_offset + bp->bio_length - 1) % PAGE_SIZE + 1;
|
||||
|
||||
rv = VM_PAGER_OK;
|
||||
VM_OBJECT_WLOCK(sc->object);
|
||||
vm_object_pip_add(sc->object, 1);
|
||||
for (i = bp->bio_offset / PAGE_SIZE; i <= lastp; i++) {
|
||||
len = ((i == lastp) ? lastend : PAGE_SIZE) - offs;
|
||||
VM_OBJECT_WLOCK(sc->object);
|
||||
m = vm_page_grab(sc->object, i, VM_ALLOC_SYSTEM);
|
||||
VM_OBJECT_WUNLOCK(sc->object);
|
||||
if (bp->bio_cmd == BIO_READ) {
|
||||
if (vm_page_all_valid(m))
|
||||
rv = VM_PAGER_OK;
|
||||
@ -1069,7 +1070,9 @@ mdstart_swap(struct md_s *sc, struct bio *bp)
|
||||
rv = vm_pager_get_pages(sc->object, &m, 1,
|
||||
NULL, NULL);
|
||||
if (rv == VM_PAGER_ERROR) {
|
||||
VM_OBJECT_WLOCK(sc->object);
|
||||
vm_page_free(m);
|
||||
VM_OBJECT_WUNLOCK(sc->object);
|
||||
break;
|
||||
} else if (rv == VM_PAGER_FAIL) {
|
||||
/*
|
||||
@ -1099,7 +1102,9 @@ mdstart_swap(struct md_s *sc, struct bio *bp)
|
||||
rv = vm_pager_get_pages(sc->object, &m, 1,
|
||||
NULL, NULL);
|
||||
if (rv == VM_PAGER_ERROR) {
|
||||
VM_OBJECT_WLOCK(sc->object);
|
||||
vm_page_free(m);
|
||||
VM_OBJECT_WUNLOCK(sc->object);
|
||||
break;
|
||||
} else if (rv == VM_PAGER_FAIL)
|
||||
pmap_zero_page(m);
|
||||
@ -1122,8 +1127,10 @@ mdstart_swap(struct md_s *sc, struct bio *bp)
|
||||
else
|
||||
rv = vm_pager_get_pages(sc->object, &m, 1,
|
||||
NULL, NULL);
|
||||
VM_OBJECT_WLOCK(sc->object);
|
||||
if (rv == VM_PAGER_ERROR) {
|
||||
vm_page_free(m);
|
||||
VM_OBJECT_WUNLOCK(sc->object);
|
||||
break;
|
||||
} else if (rv == VM_PAGER_FAIL) {
|
||||
vm_page_free(m);
|
||||
@ -1139,6 +1146,7 @@ mdstart_swap(struct md_s *sc, struct bio *bp)
|
||||
m = NULL;
|
||||
}
|
||||
}
|
||||
VM_OBJECT_WUNLOCK(sc->object);
|
||||
}
|
||||
if (m != NULL) {
|
||||
vm_page_xunbusy(m);
|
||||
@ -1160,7 +1168,6 @@ mdstart_swap(struct md_s *sc, struct bio *bp)
|
||||
ma_offs += len;
|
||||
}
|
||||
vm_object_pip_wakeup(sc->object);
|
||||
VM_OBJECT_WUNLOCK(sc->object);
|
||||
return (rv != VM_PAGER_ERROR ? 0 : ENOSPC);
|
||||
}
|
||||
|
||||
|
@ -145,6 +145,7 @@ struct mps_ident {
|
||||
|
||||
static devclass_t mps_devclass;
|
||||
DRIVER_MODULE(mps, pci, mps_pci_driver, mps_devclass, 0, 0);
|
||||
MODULE_DEPEND(mps, cam, 1, 1, 1);
|
||||
MODULE_PNP_INFO("U16:vendor;U16:device;U16:subvendor;U16:subdevice", pci, mps,
|
||||
mps_identifiers, nitems(mps_identifiers) - 1);
|
||||
static struct mps_ident *
|
||||
|
@ -60,6 +60,15 @@
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&qspi0 {
|
||||
status = "okay";
|
||||
|
||||
flash0 {
|
||||
compatible = "st,m25p", "s25fl128";
|
||||
spi-chipselect = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
&sdhci0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
@ -60,6 +60,15 @@
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&qspi0 {
|
||||
status = "okay";
|
||||
|
||||
flash0 {
|
||||
compatible = "st,m25p", "s25fl128";
|
||||
spi-chipselect = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
&sdhci0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
@ -202,7 +202,8 @@
|
||||
reg = <0xd000 0x1000>;
|
||||
interrupts = <0 19 4>;
|
||||
interrupt-parent = <&GIC>;
|
||||
spi-clock = <50000000>;
|
||||
ref-clock = <200000000>; // 200 Mhz
|
||||
spi-clock = <50000000>; // 50 Mhz
|
||||
};
|
||||
|
||||
// SDIO controllers
|
||||
|
@ -1480,8 +1480,12 @@ retry:
|
||||
VM_ALLOC_WAITFAIL);
|
||||
if (m == NULL)
|
||||
goto retry;
|
||||
vm_object_pip_add(uobj, 1);
|
||||
VM_OBJECT_WUNLOCK(uobj);
|
||||
rv = vm_pager_get_pages(uobj, &m, 1, NULL,
|
||||
NULL);
|
||||
VM_OBJECT_WLOCK(uobj);
|
||||
vm_object_pip_wakeup(uobj);
|
||||
if (rv == VM_PAGER_OK) {
|
||||
/*
|
||||
* Since the page was not resident,
|
||||
|
@ -179,9 +179,25 @@ g_label_mangle_name(char *label, size_t size)
|
||||
{
|
||||
struct sbuf *sb;
|
||||
const u_char *c;
|
||||
size_t len, i;
|
||||
|
||||
/* Trim trailing whitespace. */
|
||||
len = strlen(label);
|
||||
for (i = len; i > 0; i--) {
|
||||
if (isspace(label[i - 1]))
|
||||
label[i - 1] = '\0';
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (*label == '\0')
|
||||
return;
|
||||
|
||||
|
||||
sb = sbuf_new(NULL, NULL, size, SBUF_FIXEDLEN);
|
||||
for (c = label; *c != '\0'; c++) {
|
||||
/* Trim leading whitespace. */
|
||||
if (isspace(*c) && sbuf_len(sb) == 0)
|
||||
continue;
|
||||
if (!isprint(*c) || isspace(*c) || *c =='"' || *c == '%')
|
||||
sbuf_printf(sb, "%%%02X", *c);
|
||||
else
|
||||
|
@ -2,27 +2,6 @@
|
||||
#
|
||||
# $FreeBSD$
|
||||
|
||||
# Don't use an OBJDIR
|
||||
.OBJDIR: ${.CURDIR}
|
||||
GENERATED_PREFIX= linux_
|
||||
|
||||
.include <src.lua.mk>
|
||||
|
||||
MAKESYSCALLS= ../../tools/makesyscalls.lua
|
||||
SRCS= syscalls.conf \
|
||||
syscalls.master
|
||||
GENERATED= linux_proto.h \
|
||||
linux_syscall.h \
|
||||
linux_syscalls.c \
|
||||
linux_sysent.c \
|
||||
linux_systrace_args.c
|
||||
|
||||
all:
|
||||
@echo "make sysent only"
|
||||
|
||||
# We .ORDER these explicitly so that we only run MAKESYSCALLS once, rather than
|
||||
# potentially once for each ${GENERATED} file.
|
||||
.ORDER: ${GENERATED}
|
||||
sysent: ${GENERATED}
|
||||
|
||||
${GENERATED}: ${MAKESYSCALLS} ${SRCS}
|
||||
${LUA} ${MAKESYSCALLS} syscalls.master syscalls.conf
|
||||
.include "../../conf/sysent.mk"
|
||||
|
@ -3,28 +3,12 @@
|
||||
#
|
||||
# Makefile for init_sysent
|
||||
|
||||
# Don't use an OBJDIR
|
||||
.OBJDIR: ${.CURDIR}
|
||||
SYSENT_CONF=
|
||||
GENERATED= init_sysent.c \
|
||||
syscalls.c \
|
||||
systrace_args.c \
|
||||
${SYSDIR}/sys/syscall.h \
|
||||
${SYSDIR}/sys/syscall.mk \
|
||||
${SYSDIR}/sys/sysproto.h
|
||||
|
||||
.include <src.lua.mk>
|
||||
|
||||
MAKESYSCALLS= ../tools/makesyscalls.lua
|
||||
SRCS= capabilities.conf \
|
||||
syscalls.master
|
||||
GENERATED= init_sysent.c \
|
||||
syscalls.c \
|
||||
systrace_args.c \
|
||||
../sys/syscall.h \
|
||||
../sys/syscall.mk \
|
||||
../sys/sysproto.h
|
||||
|
||||
all:
|
||||
@echo "make sysent only"
|
||||
|
||||
# We .ORDER these explicitly so that we only run MAKESYSCALLS once, rather than
|
||||
# potentially once for each ${GENERATED} file.
|
||||
.ORDER: ${GENERATED}
|
||||
sysent: ${GENERATED}
|
||||
|
||||
${GENERATED}: ${MAKESYSCALLS} ${SRCS}
|
||||
${LUA} ${MAKESYSCALLS} syscalls.master
|
||||
.include "../conf/sysent.mk"
|
||||
|
@ -89,6 +89,7 @@ struct sf_io {
|
||||
int npages;
|
||||
struct socket *so;
|
||||
struct mbuf *m;
|
||||
vm_object_t obj;
|
||||
#ifdef KERN_TLS
|
||||
struct ktls_session *tls;
|
||||
#endif
|
||||
@ -269,6 +270,8 @@ sendfile_iodone(void *arg, vm_page_t *pg, int count, int error)
|
||||
if (!refcount_release(&sfio->nios))
|
||||
return;
|
||||
|
||||
vm_object_pip_wakeup(sfio->obj);
|
||||
|
||||
if (__predict_false(sfio->error && sfio->m == NULL)) {
|
||||
/*
|
||||
* I/O operation failed, but pru_send hadn't been executed -
|
||||
@ -421,9 +424,11 @@ sendfile_swapin(vm_object_t obj, struct sf_io *sfio, int *nios, off_t off,
|
||||
}
|
||||
|
||||
refcount_acquire(&sfio->nios);
|
||||
VM_OBJECT_WUNLOCK(obj);
|
||||
rv = vm_pager_get_pages_async(obj, pa + i, count, NULL,
|
||||
i + count == npages ? &rhpages : NULL,
|
||||
&sendfile_iodone, sfio);
|
||||
VM_OBJECT_WLOCK(obj);
|
||||
if (__predict_false(rv != VM_PAGER_OK)) {
|
||||
/*
|
||||
* Perform full pages recovery before returning EIO.
|
||||
@ -815,7 +820,9 @@ retry_space:
|
||||
npages * sizeof(vm_page_t), M_TEMP, M_WAITOK);
|
||||
refcount_init(&sfio->nios, 1);
|
||||
sfio->so = so;
|
||||
sfio->obj = obj;
|
||||
sfio->error = 0;
|
||||
vm_object_pip_add(obj, 1);
|
||||
|
||||
#ifdef KERN_TLS
|
||||
/*
|
||||
@ -1053,6 +1060,7 @@ prepend_header:
|
||||
* we can send data right now without the
|
||||
* PRUS_NOTREADY flag.
|
||||
*/
|
||||
vm_object_pip_wakeup(sfio->obj);
|
||||
free(sfio, M_TEMP);
|
||||
#ifdef KERN_TLS
|
||||
if (tls != NULL && tls->mode == TCP_TLS_MODE_SW) {
|
||||
|
@ -381,15 +381,21 @@ refcount_release_last(volatile u_int *count, u_int n, u_int old)
|
||||
* a precise answer should use refcount_wait().
|
||||
*/
|
||||
void
|
||||
refcount_sleep(volatile u_int *count, const char *wmesg, int pri)
|
||||
_refcount_sleep(volatile u_int *count, struct lock_object *lock,
|
||||
const char *wmesg, int pri)
|
||||
{
|
||||
void *wchan;
|
||||
u_int old;
|
||||
|
||||
if (REFCOUNT_COUNT(*count) == 0)
|
||||
if (REFCOUNT_COUNT(*count) == 0) {
|
||||
if (lock != NULL)
|
||||
LOCK_CLASS(lock)->lc_unlock(lock);
|
||||
return;
|
||||
}
|
||||
wchan = __DEVOLATILE(void *, count);
|
||||
sleepq_lock(wchan);
|
||||
if (lock != NULL)
|
||||
LOCK_CLASS(lock)->lc_unlock(lock);
|
||||
old = *count;
|
||||
for (;;) {
|
||||
if (REFCOUNT_COUNT(old) == 0) {
|
||||
|
@ -504,8 +504,12 @@ retry:
|
||||
VM_ALLOC_NORMAL | VM_ALLOC_WAITFAIL);
|
||||
if (m == NULL)
|
||||
goto retry;
|
||||
vm_object_pip_add(object, 1);
|
||||
VM_OBJECT_WUNLOCK(object);
|
||||
rv = vm_pager_get_pages(object, &m, 1, NULL,
|
||||
NULL);
|
||||
VM_OBJECT_WLOCK(object);
|
||||
vm_object_pip_wakeup(object);
|
||||
if (rv == VM_PAGER_OK) {
|
||||
/*
|
||||
* Since the page was not resident,
|
||||
|
@ -205,7 +205,6 @@ SYSCTL_ULONG(_vfs, OID_AUTO, ncnegfactor, CTLFLAG_RW, &ncnegfactor, 0,
|
||||
"Ratio of negative namecache entries");
|
||||
static u_long __exclusive_cache_line numneg; /* number of negative entries allocated */
|
||||
static u_long __exclusive_cache_line numcache;/* number of cache entries allocated */
|
||||
static u_long __exclusive_cache_line numcachehv;/* number of cache entries with vnodes held */
|
||||
u_int ncsizefactor = 2;
|
||||
SYSCTL_UINT(_vfs, OID_AUTO, ncsizefactor, CTLFLAG_RW, &ncsizefactor, 0,
|
||||
"Size factor for namecache");
|
||||
@ -352,7 +351,7 @@ static SYSCTL_NODE(_vfs, OID_AUTO, cache, CTLFLAG_RW, 0,
|
||||
SYSCTL_COUNTER_U64(_vfs_cache, OID_AUTO, name, CTLFLAG_RD, &name, descr);
|
||||
STATNODE_ULONG(numneg, "Number of negative cache entries");
|
||||
STATNODE_ULONG(numcache, "Number of cache entries");
|
||||
STATNODE_ULONG(numcachehv, "Number of namecache entries with vnodes held");
|
||||
STATNODE_COUNTER(numcachehv, "Number of namecache entries with vnodes held");
|
||||
STATNODE_COUNTER(numcalls, "Number of cache lookups");
|
||||
STATNODE_COUNTER(dothits, "Number of '.' hits");
|
||||
STATNODE_COUNTER(dotdothits, "Number of '..' hits");
|
||||
@ -873,7 +872,7 @@ cache_zap_locked(struct namecache *ncp, bool neg_locked)
|
||||
LIST_REMOVE(ncp, nc_src);
|
||||
if (LIST_EMPTY(&ncp->nc_dvp->v_cache_src)) {
|
||||
ncp->nc_flag |= NCF_DVDROP;
|
||||
atomic_subtract_rel_long(&numcachehv, 1);
|
||||
counter_u64_add(numcachehv, -1);
|
||||
}
|
||||
}
|
||||
atomic_subtract_rel_long(&numcache, 1);
|
||||
@ -1742,7 +1741,7 @@ cache_enter_time(struct vnode *dvp, struct vnode *vp, struct componentname *cnp,
|
||||
held_dvp = false;
|
||||
if (LIST_EMPTY(&dvp->v_cache_src) && flag != NCF_ISDOTDOT) {
|
||||
vhold(dvp);
|
||||
atomic_add_long(&numcachehv, 1);
|
||||
counter_u64_add(numcachehv, 1);
|
||||
held_dvp = true;
|
||||
}
|
||||
|
||||
@ -1837,7 +1836,7 @@ cache_enter_time(struct vnode *dvp, struct vnode *vp, struct componentname *cnp,
|
||||
if (LIST_EMPTY(&dvp->v_cache_src)) {
|
||||
if (!held_dvp) {
|
||||
vhold(dvp);
|
||||
atomic_add_long(&numcachehv, 1);
|
||||
counter_u64_add(numcachehv, 1);
|
||||
}
|
||||
} else {
|
||||
if (held_dvp) {
|
||||
@ -1848,7 +1847,7 @@ cache_enter_time(struct vnode *dvp, struct vnode *vp, struct componentname *cnp,
|
||||
* this from changing.
|
||||
*/
|
||||
vdrop(dvp);
|
||||
atomic_subtract_long(&numcachehv, 1);
|
||||
counter_u64_add(numcachehv, -1);
|
||||
}
|
||||
}
|
||||
LIST_INSERT_HEAD(&dvp->v_cache_src, ncp, nc_src);
|
||||
@ -1886,7 +1885,7 @@ out_unlock_free:
|
||||
cache_free(ncp);
|
||||
if (held_dvp) {
|
||||
vdrop(dvp);
|
||||
atomic_subtract_long(&numcachehv, 1);
|
||||
counter_u64_add(numcachehv, -1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -1957,6 +1956,7 @@ nchinit(void *dummy __unused)
|
||||
|
||||
mtx_init(&ncneg_shrink_lock, "ncnegs", NULL, MTX_DEF);
|
||||
|
||||
numcachehv = counter_u64_alloc(M_WAITOK);
|
||||
numcalls = counter_u64_alloc(M_WAITOK);
|
||||
dothits = counter_u64_alloc(M_WAITOK);
|
||||
dotdothits = counter_u64_alloc(M_WAITOK);
|
||||
|
@ -526,7 +526,7 @@ vop_stdunlock(ap)
|
||||
{
|
||||
struct vnode *vp = ap->a_vp;
|
||||
|
||||
return (lockmgr_unlock_fast_path(vp->v_vnlock, 0, NULL));
|
||||
return (lockmgr_unlock(vp->v_vnlock));
|
||||
}
|
||||
|
||||
/* See above. */
|
||||
|
@ -191,10 +191,11 @@ static struct vnode *vnode_list_reclaim_marker;
|
||||
* E.g., 9% of 75% of MAXVNODES is more than 566000 vnodes to reclaim
|
||||
* whenever vnlru_proc() becomes active.
|
||||
*/
|
||||
static u_long wantfreevnodes;
|
||||
static u_long __exclusive_cache_line freevnodes;
|
||||
static long wantfreevnodes;
|
||||
static long __exclusive_cache_line freevnodes;
|
||||
SYSCTL_ULONG(_vfs, OID_AUTO, freevnodes, CTLFLAG_RD,
|
||||
&freevnodes, 0, "Number of \"free\" vnodes");
|
||||
static long freevnodes_old;
|
||||
|
||||
static counter_u64_t recycles_count;
|
||||
SYSCTL_COUNTER_U64(_vfs, OID_AUTO, recycles, CTLFLAG_RD, &recycles_count,
|
||||
@ -299,6 +300,7 @@ SYSCTL_INT(_debug, OID_AUTO, rush_requests, CTLFLAG_RW, &stat_rush_requests, 0,
|
||||
#define VDBATCH_SIZE 8
|
||||
struct vdbatch {
|
||||
u_int index;
|
||||
long freevnodes;
|
||||
struct mtx lock;
|
||||
struct vnode *tab[VDBATCH_SIZE];
|
||||
};
|
||||
@ -323,6 +325,8 @@ static u_long vlowat; /* minimal extras before expansion */
|
||||
static u_long vstir; /* nonzero to stir non-free vnodes */
|
||||
static volatile int vsmalltrigger = 8; /* pref to keep if > this many pages */
|
||||
|
||||
static u_long vnlru_read_freevnodes(void);
|
||||
|
||||
/*
|
||||
* Note that no attempt is made to sanitize these parameters.
|
||||
*/
|
||||
@ -1205,15 +1209,17 @@ SYSCTL_INT(_debug, OID_AUTO, max_vnlru_free, CTLFLAG_RW, &max_vnlru_free,
|
||||
/*
|
||||
* Attempt to reduce the free list by the requested amount.
|
||||
*/
|
||||
static void
|
||||
static int
|
||||
vnlru_free_locked(int count, struct vfsops *mnt_op)
|
||||
{
|
||||
struct vnode *vp, *mvp;
|
||||
struct mount *mp;
|
||||
int ocount;
|
||||
|
||||
mtx_assert(&vnode_list_mtx, MA_OWNED);
|
||||
if (count > max_vnlru_free)
|
||||
count = max_vnlru_free;
|
||||
ocount = count;
|
||||
mvp = vnode_list_free_marker;
|
||||
restart:
|
||||
vp = mvp;
|
||||
@ -1254,6 +1260,7 @@ restart:
|
||||
mtx_lock(&vnode_list_mtx);
|
||||
goto restart;
|
||||
}
|
||||
return (ocount - count);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1283,11 +1290,60 @@ vnlru_recalc(void)
|
||||
static struct proc *vnlruproc;
|
||||
static int vnlruproc_sig;
|
||||
|
||||
/*
|
||||
* The main freevnodes counter is only updated when threads requeue their vnode
|
||||
* batches. CPUs are conditionally walked to compute a more accurate total.
|
||||
*
|
||||
* Limit how much of a slop are we willing to tolerate. Note: the actual value
|
||||
* at any given moment can still exceed slop, but it should not be by significant
|
||||
* margin in practice.
|
||||
*/
|
||||
#define VNLRU_FREEVNODES_SLOP 128
|
||||
|
||||
static u_long
|
||||
vnlru_read_freevnodes(void)
|
||||
{
|
||||
struct vdbatch *vd;
|
||||
long slop;
|
||||
int cpu;
|
||||
|
||||
mtx_assert(&vnode_list_mtx, MA_OWNED);
|
||||
if (freevnodes > freevnodes_old)
|
||||
slop = freevnodes - freevnodes_old;
|
||||
else
|
||||
slop = freevnodes_old - freevnodes;
|
||||
if (slop < VNLRU_FREEVNODES_SLOP)
|
||||
return (freevnodes >= 0 ? freevnodes : 0);
|
||||
freevnodes_old = freevnodes;
|
||||
CPU_FOREACH(cpu) {
|
||||
vd = DPCPU_ID_PTR((cpu), vd);
|
||||
freevnodes_old += vd->freevnodes;
|
||||
}
|
||||
return (freevnodes_old >= 0 ? freevnodes_old : 0);
|
||||
}
|
||||
|
||||
static bool
|
||||
vnlru_under(u_long rnumvnodes, u_long limit)
|
||||
{
|
||||
u_long rfreevnodes, space;
|
||||
|
||||
if (__predict_false(rnumvnodes > desiredvnodes))
|
||||
return (true);
|
||||
|
||||
space = desiredvnodes - rnumvnodes;
|
||||
if (space < limit) {
|
||||
rfreevnodes = vnlru_read_freevnodes();
|
||||
if (rfreevnodes > wantfreevnodes)
|
||||
space += rfreevnodes - wantfreevnodes;
|
||||
}
|
||||
return (space < limit);
|
||||
}
|
||||
|
||||
static bool
|
||||
vnlru_under_unlocked(u_long rnumvnodes, u_long limit)
|
||||
{
|
||||
long rfreevnodes, space;
|
||||
|
||||
if (__predict_false(rnumvnodes > desiredvnodes))
|
||||
return (true);
|
||||
|
||||
@ -1317,16 +1373,23 @@ vnlru_proc(void)
|
||||
u_long rnumvnodes, rfreevnodes, target;
|
||||
unsigned long onumvnodes;
|
||||
int done, force, trigger, usevnodes;
|
||||
bool reclaim_nc_src;
|
||||
bool reclaim_nc_src, want_reread;
|
||||
|
||||
EVENTHANDLER_REGISTER(shutdown_pre_sync, kproc_shutdown, vnlruproc,
|
||||
SHUTDOWN_PRI_FIRST);
|
||||
|
||||
force = 0;
|
||||
want_reread = false;
|
||||
for (;;) {
|
||||
kproc_suspend_check(vnlruproc);
|
||||
mtx_lock(&vnode_list_mtx);
|
||||
rnumvnodes = atomic_load_long(&numvnodes);
|
||||
|
||||
if (want_reread) {
|
||||
force = vnlru_under(numvnodes, vhiwat) ? 1 : 0;
|
||||
want_reread = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* If numvnodes is too large (due to desiredvnodes being
|
||||
* adjusted using its sysctl, or emergency growth), first
|
||||
@ -1354,7 +1417,7 @@ vnlru_proc(void)
|
||||
PVFS|PDROP, "vlruwt", hz);
|
||||
continue;
|
||||
}
|
||||
rfreevnodes = atomic_load_long(&freevnodes);
|
||||
rfreevnodes = vnlru_read_freevnodes();
|
||||
|
||||
onumvnodes = rnumvnodes;
|
||||
/*
|
||||
@ -1397,16 +1460,14 @@ vnlru_proc(void)
|
||||
force = 3;
|
||||
continue;
|
||||
}
|
||||
want_reread = true;
|
||||
force = 0;
|
||||
vnlru_nowhere++;
|
||||
tsleep(vnlruproc, PPAUSE, "vlrup", hz * 3);
|
||||
} else
|
||||
} else {
|
||||
want_reread = true;
|
||||
kern_yield(PRI_USER);
|
||||
/*
|
||||
* After becoming active to expand above low water, keep
|
||||
* active until above high water.
|
||||
*/
|
||||
force = vnlru_under(numvnodes, vhiwat) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1510,7 +1571,7 @@ vn_alloc_hard(struct mount *mp)
|
||||
vn_alloc_cyclecount = 0;
|
||||
goto alloc;
|
||||
}
|
||||
rfreevnodes = atomic_load_long(&freevnodes);
|
||||
rfreevnodes = vnlru_read_freevnodes();
|
||||
if (vn_alloc_cyclecount++ >= rfreevnodes) {
|
||||
vn_alloc_cyclecount = 0;
|
||||
vstir = 1;
|
||||
@ -1525,10 +1586,8 @@ vn_alloc_hard(struct mount *mp)
|
||||
* should be chosen so that we never wait or even reclaim from
|
||||
* the free list to below its target minimum.
|
||||
*/
|
||||
if (rfreevnodes > 0) {
|
||||
vnlru_free_locked(1, NULL);
|
||||
if (vnlru_free_locked(1, NULL) > 0)
|
||||
goto alloc;
|
||||
}
|
||||
if (mp == NULL || (mp->mnt_kern_flag & MNTK_SUSPEND) == 0) {
|
||||
/*
|
||||
* Wait for space for a new vnode.
|
||||
@ -1536,7 +1595,7 @@ vn_alloc_hard(struct mount *mp)
|
||||
vnlru_kick();
|
||||
msleep(&vnlruproc_sig, &vnode_list_mtx, PVFS, "vlruwk", hz);
|
||||
if (atomic_load_long(&numvnodes) + 1 > desiredvnodes &&
|
||||
atomic_load_long(&freevnodes) > 1)
|
||||
vnlru_read_freevnodes() > 1)
|
||||
vnlru_free_locked(1, NULL);
|
||||
}
|
||||
alloc:
|
||||
@ -1555,7 +1614,7 @@ vn_alloc(struct mount *mp)
|
||||
if (__predict_false(vn_alloc_cyclecount != 0))
|
||||
return (vn_alloc_hard(mp));
|
||||
rnumvnodes = atomic_fetchadd_long(&numvnodes, 1) + 1;
|
||||
if (__predict_false(vnlru_under(rnumvnodes, vlowat))) {
|
||||
if (__predict_false(vnlru_under_unlocked(rnumvnodes, vlowat))) {
|
||||
atomic_subtract_long(&numvnodes, 1);
|
||||
return (vn_alloc_hard(mp));
|
||||
}
|
||||
@ -1610,11 +1669,15 @@ getnewvnode(const char *tag, struct mount *mp, struct vop_vector *vops,
|
||||
* that we can compare pointers rather than doing a strcmp().
|
||||
*/
|
||||
lo = &vp->v_vnlock->lock_object;
|
||||
#ifdef WITNESS
|
||||
if (lo->lo_name != tag) {
|
||||
#endif
|
||||
lo->lo_name = tag;
|
||||
#ifdef WITNESS
|
||||
WITNESS_DESTROY(lo);
|
||||
WITNESS_INIT(lo, tag);
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* By default, don't allow shared locks unless filesystems opt-in.
|
||||
*/
|
||||
@ -2763,38 +2826,26 @@ v_decr_devcount(struct vnode *vp)
|
||||
* see doomed vnodes. If inactive processing was delayed in
|
||||
* vput try to do it here.
|
||||
*
|
||||
* Both holdcnt and usecount can be manipulated using atomics without holding
|
||||
* any locks except in these cases which require the vnode interlock:
|
||||
* holdcnt: 1->0 and 0->1
|
||||
* usecount: 0->1
|
||||
*
|
||||
* usecount is permitted to transition 1->0 without the interlock because
|
||||
* vnode is kept live by holdcnt.
|
||||
* usecount is manipulated using atomics without holding any locks,
|
||||
* except when transitioning 0->1 in which case the interlock is held.
|
||||
|
||||
* holdcnt is manipulated using atomics without holding any locks,
|
||||
* except when transitioning 1->0 in which case the interlock is held.
|
||||
*/
|
||||
static enum vgetstate __always_inline
|
||||
_vget_prep(struct vnode *vp, bool interlock)
|
||||
enum vgetstate
|
||||
vget_prep(struct vnode *vp)
|
||||
{
|
||||
enum vgetstate vs;
|
||||
|
||||
if (refcount_acquire_if_not_zero(&vp->v_usecount)) {
|
||||
vs = VGET_USECOUNT;
|
||||
} else {
|
||||
if (interlock)
|
||||
vholdl(vp);
|
||||
else
|
||||
vhold(vp);
|
||||
vhold(vp);
|
||||
vs = VGET_HOLDCNT;
|
||||
}
|
||||
return (vs);
|
||||
}
|
||||
|
||||
enum vgetstate
|
||||
vget_prep(struct vnode *vp)
|
||||
{
|
||||
|
||||
return (_vget_prep(vp, false));
|
||||
}
|
||||
|
||||
int
|
||||
vget(struct vnode *vp, int flags, struct thread *td)
|
||||
{
|
||||
@ -2802,7 +2853,7 @@ vget(struct vnode *vp, int flags, struct thread *td)
|
||||
|
||||
MPASS(td == curthread);
|
||||
|
||||
vs = _vget_prep(vp, (flags & LK_INTERLOCK) != 0);
|
||||
vs = vget_prep(vp);
|
||||
return (vget_finish(vp, flags, vs));
|
||||
}
|
||||
|
||||
@ -3171,33 +3222,21 @@ vunref(struct vnode *vp)
|
||||
vputx(vp, VPUTX_VUNREF);
|
||||
}
|
||||
|
||||
/*
|
||||
* Increase the hold count and activate if this is the first reference.
|
||||
*/
|
||||
static void
|
||||
vhold_activate(struct vnode *vp)
|
||||
{
|
||||
|
||||
ASSERT_VI_LOCKED(vp, __func__);
|
||||
VNASSERT(vp->v_holdcnt == 0, vp,
|
||||
("%s: wrong hold count", __func__));
|
||||
VNASSERT(vp->v_op != NULL, vp,
|
||||
("%s: vnode already reclaimed.", __func__));
|
||||
atomic_subtract_long(&freevnodes, 1);
|
||||
refcount_acquire(&vp->v_holdcnt);
|
||||
}
|
||||
|
||||
void
|
||||
vhold(struct vnode *vp)
|
||||
{
|
||||
struct vdbatch *vd;
|
||||
int old;
|
||||
|
||||
ASSERT_VI_UNLOCKED(vp, __func__);
|
||||
CTR2(KTR_VFS, "%s: vp %p", __func__, vp);
|
||||
if (refcount_acquire_if_not_zero(&vp->v_holdcnt))
|
||||
old = atomic_fetchadd_int(&vp->v_holdcnt, 1);
|
||||
VNASSERT(old >= 0, vp, ("%s: wrong hold count %d", __func__, old));
|
||||
if (old != 0)
|
||||
return;
|
||||
VI_LOCK(vp);
|
||||
vholdl(vp);
|
||||
VI_UNLOCK(vp);
|
||||
critical_enter();
|
||||
vd = DPCPU_PTR(vd);
|
||||
vd->freevnodes--;
|
||||
critical_exit();
|
||||
}
|
||||
|
||||
void
|
||||
@ -3206,11 +3245,7 @@ vholdl(struct vnode *vp)
|
||||
|
||||
ASSERT_VI_LOCKED(vp, __func__);
|
||||
CTR2(KTR_VFS, "%s: vp %p", __func__, vp);
|
||||
if (vp->v_holdcnt > 0) {
|
||||
refcount_acquire(&vp->v_holdcnt);
|
||||
return;
|
||||
}
|
||||
vhold_activate(vp);
|
||||
vhold(vp);
|
||||
}
|
||||
|
||||
void
|
||||
@ -3233,9 +3268,12 @@ vdbatch_process(struct vdbatch *vd)
|
||||
int i;
|
||||
|
||||
mtx_assert(&vd->lock, MA_OWNED);
|
||||
MPASS(curthread->td_pinned > 0);
|
||||
MPASS(vd->index == VDBATCH_SIZE);
|
||||
|
||||
mtx_lock(&vnode_list_mtx);
|
||||
critical_enter();
|
||||
freevnodes += vd->freevnodes;
|
||||
for (i = 0; i < VDBATCH_SIZE; i++) {
|
||||
vp = vd->tab[i];
|
||||
TAILQ_REMOVE(&vnode_list, vp, v_vnodelist);
|
||||
@ -3244,6 +3282,8 @@ vdbatch_process(struct vdbatch *vd)
|
||||
vp->v_dbatchcpu = NOCPU;
|
||||
}
|
||||
mtx_unlock(&vnode_list_mtx);
|
||||
critical_exit();
|
||||
vd->freevnodes = 0;
|
||||
bzero(vd->tab, sizeof(vd->tab));
|
||||
vd->index = 0;
|
||||
}
|
||||
@ -3257,20 +3297,24 @@ vdbatch_enqueue(struct vnode *vp)
|
||||
VNASSERT(!VN_IS_DOOMED(vp), vp,
|
||||
("%s: deferring requeue of a doomed vnode", __func__));
|
||||
|
||||
critical_enter();
|
||||
vd = DPCPU_PTR(vd);
|
||||
vd->freevnodes++;
|
||||
if (vp->v_dbatchcpu != NOCPU) {
|
||||
VI_UNLOCK(vp);
|
||||
critical_exit();
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* A hack: pin us to the current CPU so that we know what to put in
|
||||
* ->v_dbatchcpu.
|
||||
*/
|
||||
sched_pin();
|
||||
vd = DPCPU_PTR(vd);
|
||||
critical_exit();
|
||||
mtx_lock(&vd->lock);
|
||||
MPASS(vd->index < VDBATCH_SIZE);
|
||||
MPASS(vd->tab[vd->index] == NULL);
|
||||
/*
|
||||
* A hack: we depend on being pinned so that we know what to put in
|
||||
* ->v_dbatchcpu.
|
||||
*/
|
||||
vp->v_dbatchcpu = curcpu;
|
||||
vd->tab[vd->index] = vp;
|
||||
vd->index++;
|
||||
@ -3341,8 +3385,6 @@ vdrop_deactivate(struct vnode *vp)
|
||||
("vdrop: returning doomed vnode"));
|
||||
VNASSERT(vp->v_op != NULL, vp,
|
||||
("vdrop: vnode already reclaimed."));
|
||||
VNASSERT(vp->v_holdcnt == 0, vp,
|
||||
("vdrop: freeing when we shouldn't"));
|
||||
VNASSERT((vp->v_iflag & VI_OWEINACT) == 0, vp,
|
||||
("vnode with VI_OWEINACT set"));
|
||||
VNASSERT((vp->v_iflag & VI_DEFINACT) == 0, vp,
|
||||
@ -3350,12 +3392,20 @@ vdrop_deactivate(struct vnode *vp)
|
||||
if (vp->v_mflag & VMP_LAZYLIST) {
|
||||
mp = vp->v_mount;
|
||||
mtx_lock(&mp->mnt_listmtx);
|
||||
vp->v_mflag &= ~VMP_LAZYLIST;
|
||||
TAILQ_REMOVE(&mp->mnt_lazyvnodelist, vp, v_lazylist);
|
||||
mp->mnt_lazyvnodelistsize--;
|
||||
VNASSERT(vp->v_mflag & VMP_LAZYLIST, vp, ("lost VMP_LAZYLIST"));
|
||||
/*
|
||||
* Don't remove the vnode from the lazy list if another thread
|
||||
* has increased the hold count. It may have re-enqueued the
|
||||
* vnode to the lazy list and is now responsible for its
|
||||
* removal.
|
||||
*/
|
||||
if (vp->v_holdcnt == 0) {
|
||||
vp->v_mflag &= ~VMP_LAZYLIST;
|
||||
TAILQ_REMOVE(&mp->mnt_lazyvnodelist, vp, v_lazylist);
|
||||
mp->mnt_lazyvnodelistsize--;
|
||||
}
|
||||
mtx_unlock(&mp->mnt_listmtx);
|
||||
}
|
||||
atomic_add_long(&freevnodes, 1);
|
||||
vdbatch_enqueue(vp);
|
||||
}
|
||||
|
||||
|
11
sys/net/if.c
11
sys/net/if.c
@ -1867,10 +1867,13 @@ ifa_maintain_loopback_route(int cmd, const char *otype, struct ifaddr *ifa,
|
||||
if (rti_ifa != NULL)
|
||||
ifa_free(rti_ifa);
|
||||
|
||||
if (error != 0 &&
|
||||
!(cmd == RTM_ADD && error == EEXIST) &&
|
||||
!(cmd == RTM_DELETE && error == ENOENT))
|
||||
if_printf(ifp, "%s failed: %d\n", otype, error);
|
||||
if (error == 0 ||
|
||||
(cmd == RTM_ADD && error == EEXIST) ||
|
||||
(cmd == RTM_DELETE && (error == ENOENT || error == ESRCH)))
|
||||
return (error);
|
||||
|
||||
log(LOG_DEBUG, "%s: %s failed for interface %s: %u\n",
|
||||
__func__, otype, if_name(ifp), error);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
@ -477,18 +477,12 @@ amrr_sysctlattach(struct ieee80211vap *vap,
|
||||
}
|
||||
|
||||
static void
|
||||
amrr_node_stats(struct ieee80211_node *ni, struct sbuf *s)
|
||||
amrr_print_node_rate(struct ieee80211_amrr_node *amn,
|
||||
struct ieee80211_node *ni, struct sbuf *s)
|
||||
{
|
||||
int rate;
|
||||
struct ieee80211_amrr_node *amn = ni->ni_rctls;
|
||||
struct ieee80211_rateset *rs;
|
||||
|
||||
/* XXX TODO: check locking? */
|
||||
|
||||
if (!amn)
|
||||
return;
|
||||
|
||||
/* XXX TODO: this should be a method */
|
||||
if (amrr_node_is_11n(ni)) {
|
||||
rs = (struct ieee80211_rateset *) &ni->ni_htrates;
|
||||
rate = rs->rs_rates[amn->amn_rix] & IEEE80211_RATE_VAL;
|
||||
@ -498,7 +492,19 @@ amrr_node_stats(struct ieee80211_node *ni, struct sbuf *s)
|
||||
rate = rs->rs_rates[amn->amn_rix] & IEEE80211_RATE_VAL;
|
||||
sbuf_printf(s, "rate: %d Mbit\n", rate / 2);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
amrr_node_stats(struct ieee80211_node *ni, struct sbuf *s)
|
||||
{
|
||||
struct ieee80211_amrr_node *amn = ni->ni_rctls;
|
||||
|
||||
/* XXX TODO: check locking? */
|
||||
|
||||
if (!amn)
|
||||
return;
|
||||
|
||||
amrr_print_node_rate(amn, ni, s);
|
||||
sbuf_printf(s, "ticks: %d\n", amn->amn_ticks);
|
||||
sbuf_printf(s, "txcnt: %u\n", amn->amn_txcnt);
|
||||
sbuf_printf(s, "success: %u\n", amn->amn_success);
|
||||
|
@ -388,16 +388,18 @@ aim_cpu_init(vm_offset_t toc)
|
||||
bcopy(&dsitrap, (void *)(EXC_DSI + trap_offset), (size_t)&dsiend -
|
||||
(size_t)&dsitrap);
|
||||
|
||||
/* Set address of generictrap for self-reloc calculations */
|
||||
*((void **)TRAP_GENTRAP) = &generictrap;
|
||||
#ifdef __powerpc64__
|
||||
/* Set TOC base so that the interrupt code can get at it */
|
||||
*((void **)TRAP_GENTRAP) = &generictrap;
|
||||
*((void **)TRAP_ENTRY) = &generictrap;
|
||||
*((register_t *)TRAP_TOCBASE) = toc;
|
||||
#else
|
||||
/* Set branch address for trap code */
|
||||
if (cpu_features & PPC_FEATURE_64)
|
||||
*((void **)TRAP_GENTRAP) = &generictrap64;
|
||||
*((void **)TRAP_ENTRY) = &generictrap64;
|
||||
else
|
||||
*((void **)TRAP_GENTRAP) = &generictrap;
|
||||
*((void **)TRAP_ENTRY) = &generictrap;
|
||||
*((void **)TRAP_TOCBASE) = _GLOBAL_OFFSET_TABLE_;
|
||||
|
||||
/* G2-specific TLB miss helper handlers */
|
||||
|
@ -185,7 +185,6 @@ uma_zone_t moea64_pvo_zone; /* zone for pvo entries */
|
||||
static struct pvo_entry *moea64_bpvo_pool;
|
||||
static int moea64_bpvo_pool_index = 0;
|
||||
static int moea64_bpvo_pool_size = 327680;
|
||||
TUNABLE_INT("machdep.moea64_bpvo_pool_size", &moea64_bpvo_pool_size);
|
||||
SYSCTL_INT(_machdep, OID_AUTO, moea64_allocated_bpvo_entries, CTLFLAG_RD,
|
||||
&moea64_bpvo_pool_index, 0, "");
|
||||
|
||||
@ -390,9 +389,11 @@ alloc_pvo_entry(int bootstrap)
|
||||
|
||||
if (!moea64_initialized || bootstrap) {
|
||||
if (moea64_bpvo_pool_index >= moea64_bpvo_pool_size) {
|
||||
panic("moea64_enter: bpvo pool exhausted, %d, %d, %zd",
|
||||
moea64_bpvo_pool_index, moea64_bpvo_pool_size,
|
||||
moea64_bpvo_pool_size * sizeof(struct pvo_entry));
|
||||
panic("%s: bpvo pool exhausted, index=%d, size=%d, bytes=%zd."
|
||||
"Try setting machdep.moea64_bpvo_pool_size tunable",
|
||||
__func__, moea64_bpvo_pool_index,
|
||||
moea64_bpvo_pool_size,
|
||||
moea64_bpvo_pool_size * sizeof(struct pvo_entry));
|
||||
}
|
||||
pvo = &moea64_bpvo_pool[
|
||||
atomic_fetchadd_int(&moea64_bpvo_pool_index, 1)];
|
||||
@ -914,6 +915,7 @@ moea64_mid_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernelend)
|
||||
/*
|
||||
* Initialise the bootstrap pvo pool.
|
||||
*/
|
||||
TUNABLE_INT_FETCH("machdep.moea64_bpvo_pool_size", &moea64_bpvo_pool_size);
|
||||
moea64_bpvo_pool = (struct pvo_entry *)moea64_bootstrap_alloc(
|
||||
moea64_bpvo_pool_size*sizeof(struct pvo_entry), PAGE_SIZE);
|
||||
moea64_bpvo_pool_index = 0;
|
||||
|
@ -43,6 +43,7 @@
|
||||
*/
|
||||
|
||||
INTERFACE moea64;
|
||||
SINGLETON;
|
||||
|
||||
CODE {
|
||||
static moea64_pte_replace_t moea64_pte_replace_default;
|
||||
|
@ -348,7 +348,7 @@ CNAME(trapcode):
|
||||
mtsprg1 %r1 /* save SP */
|
||||
mflr %r1 /* Save the old LR in r1 */
|
||||
mtsprg2 %r1 /* And then in SPRG2 */
|
||||
lwz %r1, TRAP_GENTRAP(0) /* Get branch address */
|
||||
lwz %r1, TRAP_ENTRY(0) /* Get branch address */
|
||||
mtlr %r1
|
||||
li %r1, 0xe0 /* How to get the vector from LR */
|
||||
blrl /* LR & (0xff00 | r1) is exception # */
|
||||
@ -908,7 +908,7 @@ CNAME(dblow):
|
||||
mflr %r1 /* save LR */
|
||||
mtsprg2 %r1 /* And then in SPRG2 */
|
||||
|
||||
lwz %r1, TRAP_GENTRAP(0) /* Get branch address */
|
||||
lwz %r1, TRAP_ENTRY(0) /* Get branch address */
|
||||
mtlr %r1
|
||||
li %r1, 0 /* How to get the vector from LR */
|
||||
blrl /* LR & (0xff00 | r1) is exception # */
|
||||
|
@ -318,7 +318,7 @@ CNAME(rstcode):
|
||||
* It is software reset when 46:47 = 0b00
|
||||
*/
|
||||
/* 0x00 */
|
||||
ld %r2,TRAP_GENTRAP(0) /* Real-mode &generictrap */
|
||||
ld %r2,TRAP_ENTRY(0) /* Real-mode &generictrap */
|
||||
mfsrr1 %r9 /* Load SRR1 into r9 */
|
||||
andis. %r9,%r9,0x3 /* Logic AND with 46:47 bits */
|
||||
|
||||
@ -446,7 +446,7 @@ CNAME(trapcode):
|
||||
mtsprg1 %r1 /* save SP */
|
||||
mflr %r1 /* Save the old LR in r1 */
|
||||
mtsprg2 %r1 /* And then in SPRG2 */
|
||||
ld %r1,TRAP_GENTRAP(0)
|
||||
ld %r1,TRAP_ENTRY(0)
|
||||
mtlr %r1
|
||||
li %r1, 0xe0 /* How to get the vector from LR */
|
||||
blrl /* Branch to generictrap */
|
||||
@ -493,7 +493,7 @@ CNAME(slbtrap):
|
||||
mflr %r1
|
||||
/* 0x30 */
|
||||
mtsprg2 %r1 /* save LR in SPRG2 */
|
||||
ld %r1,TRAP_GENTRAP(0) /* real-mode &generictrap */
|
||||
ld %r1,TRAP_ENTRY(0) /* real-mode &generictrap */
|
||||
mtlr %r1
|
||||
li %r1, 0x80 /* How to get the vector from LR */
|
||||
/* 0x40 */
|
||||
@ -955,7 +955,7 @@ CNAME(dblow):
|
||||
mflr %r1 /* save LR */
|
||||
mtsprg2 %r1 /* And then in SPRG2 */
|
||||
|
||||
ld %r1, TRAP_GENTRAP(0) /* Get branch address */
|
||||
ld %r1, TRAP_ENTRY(0) /* Get branch address */
|
||||
mtlr %r1
|
||||
li %r1, 0 /* How to get the vector from LR */
|
||||
blrl /* Branch to generictrap */
|
||||
|
45
sys/powerpc/amigaone/cpld.h
Normal file
45
sys/powerpc/amigaone/cpld.h
Normal file
@ -0,0 +1,45 @@
|
||||
/*-
|
||||
* Copyright (c) 2020 Justin Hibbits
|
||||
*
|
||||
* 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 AMIGAONE_CPLD_H
|
||||
#define AMIGAONE_CPLD_H
|
||||
|
||||
#include <sys/ioccom.h>
|
||||
|
||||
/*
|
||||
* Write 'words' to 'offset' offset in dual-port RAM, then write cmd to mailbox.
|
||||
*/
|
||||
struct cpld_cmd_data {
|
||||
unsigned int cmd;
|
||||
unsigned int len;
|
||||
unsigned int offset;
|
||||
void *words;
|
||||
};
|
||||
|
||||
#define IOCCPLDSEND _IOW('c', 2, struct cpld_cmd_data)
|
||||
#define IOCCPLDRECV _IOW('c', 3, struct cpld_cmd_data)
|
||||
|
||||
#endif /* AMIGAONE_CPLD_H */
|
337
sys/powerpc/amigaone/cpld_x5000.c
Normal file
337
sys/powerpc/amigaone/cpld_x5000.c
Normal file
@ -0,0 +1,337 @@
|
||||
/*-
|
||||
* Copyright (c) 2020 Justin Hibbits
|
||||
*
|
||||
* 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/conf.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/limits.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/rman.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
|
||||
#include <dev/ofw/ofw_bus.h>
|
||||
#include <dev/ofw/ofw_bus_subr.h>
|
||||
|
||||
#include "cpld.h"
|
||||
|
||||
/*
|
||||
* A driver for the AmigaOne X5000 "Cyrus+" CPLD.
|
||||
*
|
||||
* This is the interface between the CPU and the "Xena" (XMOS) chip. Since the
|
||||
* XMOS is programmable via a SPI-attached flash memory, there's no direct
|
||||
* driver written for the Xena attachment. Instead, a userspace process would
|
||||
* communicate with the Xena by issuing ioctl()s to this CPLD.
|
||||
*/
|
||||
|
||||
/* Resource access addresses. */
|
||||
#define CPLD_MEM_ADDR 0x0000
|
||||
#define CPLD_MEM_DATA 0x8000
|
||||
|
||||
#define CPLD_MAX_DRAM_WORDS 0x800
|
||||
|
||||
/* CPLD Registers. */
|
||||
#define CPLD_REG_SIG1 0x00
|
||||
#define CPLD_REG_SIG2 0x01
|
||||
#define CPLD_REG_HWREV 0x02
|
||||
#define CPLD_REG_MBC2X 0x05
|
||||
#define CPLD_REG_MBX2C 0x06
|
||||
#define CPLD_REG_XDEBUG 0x0c
|
||||
#define CPLD_REG_XJTAG 0x0d
|
||||
#define CPLD_REG_FAN_TACHO 0x10
|
||||
#define CPLD_REG_DATE_LW 0x21
|
||||
#define CPLD_REG_DATE_UW 0x22
|
||||
#define CPLD_REG_TIME_LW 0x23
|
||||
#define CPLD_REG_TIME_UW 0x24
|
||||
#define CPLD_REG_SCR1 0x30
|
||||
#define CPLD_REG_SCR2 0x31
|
||||
#define CPLD_REG_RAM 0x8000
|
||||
|
||||
struct cpld_softc {
|
||||
device_t sc_dev;
|
||||
struct resource *sc_mem;
|
||||
struct cdev *sc_cdev;
|
||||
struct mtx sc_mutex;
|
||||
bool sc_isopen;
|
||||
};
|
||||
|
||||
static d_open_t cpld_open;
|
||||
static d_close_t cpld_close;
|
||||
static d_ioctl_t cpld_ioctl;
|
||||
|
||||
static struct cdevsw cpld_cdevsw = {
|
||||
.d_version = D_VERSION,
|
||||
.d_open = cpld_open,
|
||||
.d_close = cpld_close,
|
||||
.d_ioctl = cpld_ioctl,
|
||||
.d_name = "nvram",
|
||||
};
|
||||
|
||||
static device_probe_t cpld_probe;
|
||||
static device_attach_t cpld_attach;
|
||||
static int cpld_fan_sysctl(SYSCTL_HANDLER_ARGS);
|
||||
|
||||
static device_method_t cpld_methods[] = {
|
||||
DEVMETHOD(device_probe, cpld_probe),
|
||||
DEVMETHOD(device_attach, cpld_attach),
|
||||
|
||||
DEVMETHOD_END
|
||||
};
|
||||
|
||||
static driver_t cpld_driver = {
|
||||
"cpld",
|
||||
cpld_methods,
|
||||
sizeof(struct cpld_softc)
|
||||
};
|
||||
|
||||
static devclass_t cpld_devclass;
|
||||
DRIVER_MODULE(cpld, lbc, cpld_driver, cpld_devclass, 0, 0);
|
||||
|
||||
static void
|
||||
cpld_write(struct cpld_softc *sc, int addr, int data)
|
||||
{
|
||||
bus_write_2(sc->sc_mem, CPLD_MEM_ADDR, addr);
|
||||
bus_write_2(sc->sc_mem, CPLD_MEM_DATA, data);
|
||||
}
|
||||
|
||||
static int
|
||||
cpld_read(struct cpld_softc *sc, int addr)
|
||||
{
|
||||
bus_write_2(sc->sc_mem, CPLD_MEM_ADDR, addr);
|
||||
|
||||
return (bus_read_2(sc->sc_mem, CPLD_MEM_DATA));
|
||||
}
|
||||
|
||||
static int
|
||||
cpld_probe(device_t dev)
|
||||
{
|
||||
if (!ofw_bus_is_compatible(dev, "aeon,cyrus-cpld"))
|
||||
return (ENXIO);
|
||||
|
||||
device_set_desc(dev, "AmigaOne Cyrus CPLD");
|
||||
|
||||
return (BUS_PROBE_GENERIC);
|
||||
}
|
||||
|
||||
static int
|
||||
cpld_attach(device_t dev)
|
||||
{
|
||||
struct make_dev_args mda;
|
||||
struct cpld_softc *sc;
|
||||
int rid;
|
||||
int date, time, tmp;
|
||||
int err;
|
||||
struct sysctl_ctx_list *ctx;
|
||||
struct sysctl_oid *tree;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
sc->sc_dev = dev;
|
||||
|
||||
rid = 0;
|
||||
sc->sc_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
|
||||
RF_ACTIVE|RF_SHAREABLE);
|
||||
if (sc->sc_mem == NULL) {
|
||||
device_printf(dev, "Unable to allocate memory resource.\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
mtx_init(&sc->sc_mutex, "cpld", NULL, MTX_DEF);
|
||||
if (bootverbose) {
|
||||
date = (cpld_read(sc, CPLD_REG_DATE_UW) << 16) |
|
||||
cpld_read(sc, CPLD_REG_DATE_LW);
|
||||
time = (cpld_read(sc, CPLD_REG_TIME_UW) << 16) |
|
||||
cpld_read(sc, CPLD_REG_TIME_LW);
|
||||
|
||||
device_printf(dev, "Build date: %04x-%02x-%02x\n",
|
||||
(date >> 16) & 0xffff, (date >> 8) & 0xff, date & 0xff);
|
||||
device_printf(dev, "Build time: %02x:%02x:%02x\n",
|
||||
(time >> 16) & 0xff, (time >> 8) & 0xff, time & 0xff);
|
||||
}
|
||||
|
||||
tmp = cpld_read(sc, CPLD_REG_HWREV);
|
||||
device_printf(dev, "Hardware revision: %d\n", tmp);
|
||||
|
||||
ctx = device_get_sysctl_ctx(dev);
|
||||
tree = device_get_sysctl_tree(dev);
|
||||
|
||||
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
||||
"cpu_fan", CTLTYPE_INT | CTLFLAG_RD, sc, 0,
|
||||
cpld_fan_sysctl, "I", "CPU Fan speed in RPM");
|
||||
|
||||
make_dev_args_init(&mda);
|
||||
mda.mda_flags = MAKEDEV_CHECKNAME;
|
||||
mda.mda_devsw = &cpld_cdevsw;
|
||||
mda.mda_uid = UID_ROOT;
|
||||
mda.mda_gid = GID_WHEEL;
|
||||
mda.mda_mode = 0660;
|
||||
mda.mda_si_drv1 = sc;
|
||||
err = make_dev_s(&mda, &sc->sc_cdev, "cpld");
|
||||
if (err != 0) {
|
||||
device_printf(dev, "Error creating character device: %d\n", err);
|
||||
device_printf(dev, "Only sysctl interfaces will be available.\n");
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
cpld_fan_sysctl(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
struct cpld_softc *sc;
|
||||
int error, old, rpm;
|
||||
|
||||
sc = arg1;
|
||||
mtx_lock(&sc->sc_mutex);
|
||||
/* Read until we get some level of read stability. */
|
||||
rpm = cpld_read(sc, CPLD_REG_FAN_TACHO);
|
||||
do {
|
||||
old = rpm;
|
||||
rpm = cpld_read(sc, CPLD_REG_FAN_TACHO);
|
||||
} while (abs(rpm - old) > 10);
|
||||
mtx_unlock(&sc->sc_mutex);
|
||||
|
||||
/* Convert RPS->RPM. */
|
||||
rpm *= 60;
|
||||
error = sysctl_handle_int(oidp, &rpm, 0, req);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
cpld_open(struct cdev *dev, int flags, int fmt, struct thread *td)
|
||||
{
|
||||
struct cpld_softc *sc = dev->si_drv1;
|
||||
|
||||
if (sc->sc_isopen)
|
||||
return (EBUSY);
|
||||
sc->sc_isopen = 1;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
cpld_close(struct cdev *dev, int fflag, int devtype, struct thread *td)
|
||||
{
|
||||
struct cpld_softc *sc = dev->si_drv1;
|
||||
|
||||
sc->sc_isopen = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
cpld_send(device_t dev, struct cpld_cmd_data *d)
|
||||
{
|
||||
struct cpld_softc *sc;
|
||||
uint16_t *word;
|
||||
int i;
|
||||
|
||||
if (d->cmd > USHRT_MAX)
|
||||
return (EINVAL);
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
mtx_lock(&sc->sc_mutex);
|
||||
for (i = 0, word = d->words; i < d->len; i++, word++) {
|
||||
if (i == 0)
|
||||
cpld_write(sc, CPLD_REG_RAM, *word);
|
||||
else
|
||||
bus_write_4(sc->sc_mem, CPLD_MEM_DATA, *word);
|
||||
}
|
||||
|
||||
cpld_write(sc, CPLD_REG_MBC2X, d->cmd);
|
||||
mtx_unlock(&sc->sc_mutex);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
cpld_recv(device_t dev, struct cpld_cmd_data *d)
|
||||
{
|
||||
struct cpld_softc *sc;
|
||||
uint16_t *word;
|
||||
int i;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
mtx_lock(&sc->sc_mutex);
|
||||
d->cmd = cpld_read(sc, CPLD_REG_MBX2C);
|
||||
|
||||
for (i = 0, word = d->words; i < d->len; i++, word++) {
|
||||
if (i == 0)
|
||||
*word = cpld_read(sc, CPLD_REG_RAM);
|
||||
else
|
||||
*word = bus_read_4(sc->sc_mem, CPLD_MEM_DATA);
|
||||
}
|
||||
mtx_unlock(&sc->sc_mutex);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
cpld_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, struct thread *td)
|
||||
{
|
||||
struct cpld_softc *sc;
|
||||
struct cpld_cmd_data *d;
|
||||
void *xfer_data, *tmp;
|
||||
int err;
|
||||
|
||||
sc = dev->si_drv1;
|
||||
|
||||
err = 0;
|
||||
d = (struct cpld_cmd_data *)data;
|
||||
if (d->len + d->offset > CPLD_MAX_DRAM_WORDS) {
|
||||
return (EINVAL);
|
||||
}
|
||||
xfer_data = malloc(d->len * sizeof(uint16_t), M_TEMP, M_WAITOK);
|
||||
|
||||
switch (cmd) {
|
||||
case IOCCPLDSEND:
|
||||
err = copyin(d->words, xfer_data, d->len * sizeof(uint16_t));
|
||||
d->words = xfer_data;
|
||||
if (err == 0)
|
||||
err = cpld_send(sc->sc_dev, d);
|
||||
break;
|
||||
case IOCCPLDRECV:
|
||||
tmp = d->words;
|
||||
d->words = xfer_data;
|
||||
err = cpld_recv(sc->sc_dev, d);
|
||||
d->words = tmp;
|
||||
if (err == 0)
|
||||
err = copyout(xfer_data, d->words,
|
||||
d->len * sizeof(uint16_t));
|
||||
break;
|
||||
default:
|
||||
err = ENOTTY;
|
||||
break;
|
||||
}
|
||||
free(xfer_data, M_TEMP);
|
||||
|
||||
return (err);
|
||||
}
|
@ -4028,7 +4028,22 @@ tlb1_mapin_region(vm_offset_t va, vm_paddr_t pa, vm_size_t size, int wimge)
|
||||
sz >>= 2;
|
||||
} while (va % sz != 0);
|
||||
}
|
||||
/* Now align from there to VA */
|
||||
#ifdef __powerpc64__
|
||||
/*
|
||||
* Clamp TLB1 entries to 4G.
|
||||
*
|
||||
* While the e6500 supports up to 1TB mappings, the e5500
|
||||
* only supports up to 4G mappings. (0b1011)
|
||||
*
|
||||
* If any e6500 machines capable of supporting a very
|
||||
* large amount of memory appear in the future, we can
|
||||
* revisit this.
|
||||
*
|
||||
* For now, though, since we have plenty of space in TLB1,
|
||||
* always avoid creating entries larger than 4GB.
|
||||
*/
|
||||
sz = MIN(sz, 1UL << 32);
|
||||
#endif
|
||||
if (bootverbose)
|
||||
printf("Wiring VA=%p to PA=%jx (size=%lx)\n",
|
||||
(void *)va, (uintmax_t)pa, (long)sz);
|
||||
|
@ -37,6 +37,9 @@
|
||||
#include <dev/ofw/openfirm.h>
|
||||
#include <machine/platform.h>
|
||||
|
||||
struct mem_region;
|
||||
struct numa_mem_region;
|
||||
|
||||
typedef uint32_t cell_t;
|
||||
|
||||
void OF_getetheraddr(device_t dev, u_char *addr);
|
||||
|
@ -37,6 +37,7 @@
|
||||
#ifndef _MACHINE_PLATFORM_H_
|
||||
#define _MACHINE_PLATFORM_H_
|
||||
|
||||
#include <machine/ofw_machdep.h>
|
||||
#include <machine/smp.h>
|
||||
#include <machine/pcpu.h>
|
||||
|
||||
@ -66,6 +67,7 @@ int platform_smp_start_cpu(struct pcpu *);
|
||||
void platform_smp_timebase_sync(u_long tb, int ap);
|
||||
void platform_smp_ap_init(void);
|
||||
void platform_smp_probe_threads(void);
|
||||
int platform_node_numa_domain(phandle_t);
|
||||
|
||||
const char *installed_platform(void);
|
||||
void platform_probe_and_attach(void);
|
||||
|
@ -147,8 +147,9 @@
|
||||
#define EXC_DTRACE 0x7ffff808
|
||||
|
||||
/* Magic pointer to store TOC base and other info for trap handlers on ppc64 */
|
||||
#define TRAP_GENTRAP 0x1f0
|
||||
#define TRAP_TOCBASE 0x1f8
|
||||
#define TRAP_ENTRY 0x1e8
|
||||
#define TRAP_GENTRAP 0x1f0
|
||||
#define TRAP_TOCBASE 0x1f8
|
||||
|
||||
#ifndef LOCORE
|
||||
struct trapframe;
|
||||
|
@ -466,9 +466,8 @@ void
|
||||
ofw_numa_mem_regions(struct numa_mem_region *memp, int *memsz)
|
||||
{
|
||||
phandle_t phandle;
|
||||
int res, count, msz;
|
||||
int count, msz;
|
||||
char name[31];
|
||||
cell_t associativity[5];
|
||||
struct numa_mem_region *curmemp;
|
||||
|
||||
msz = 0;
|
||||
@ -486,13 +485,8 @@ ofw_numa_mem_regions(struct numa_mem_region *memp, int *memsz)
|
||||
if (count == 0)
|
||||
continue;
|
||||
curmemp = &memp[msz];
|
||||
res = OF_getproplen(phandle, "ibm,associativity");
|
||||
if (res <= 0)
|
||||
continue;
|
||||
MPASS(count == 1);
|
||||
OF_getencprop(phandle, "ibm,associativity",
|
||||
associativity, res);
|
||||
curmemp->mr_domain = associativity[3];
|
||||
curmemp->mr_domain = platform_node_numa_domain(phandle);
|
||||
if (bootverbose)
|
||||
printf("%s %#jx-%#jx domain(%ju)\n",
|
||||
name, (uintmax_t)curmemp->mr_start,
|
||||
|
@ -385,39 +385,13 @@ ofw_pcibus_get_devinfo(device_t bus, device_t dev)
|
||||
return (&dinfo->opd_obdinfo);
|
||||
}
|
||||
|
||||
static int
|
||||
ofw_pcibus_parse_associativity(device_t dev, int *domain)
|
||||
{
|
||||
phandle_t node;
|
||||
cell_t associativity[5];
|
||||
int res;
|
||||
|
||||
if ((node = ofw_bus_get_node(dev)) == -1) {
|
||||
if (bootverbose)
|
||||
device_printf(dev, "no ofw node found\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
res = OF_getproplen(node, "ibm,associativity");
|
||||
if (res <= 0)
|
||||
return (ENXIO);
|
||||
OF_getencprop(node, "ibm,associativity",
|
||||
associativity, res);
|
||||
|
||||
*domain = associativity[3];
|
||||
if (bootverbose)
|
||||
device_printf(dev, "domain(%d)\n", *domain);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
ofw_pcibus_get_cpus(device_t dev, device_t child, enum cpu_sets op, size_t setsize,
|
||||
cpuset_t *cpuset)
|
||||
{
|
||||
int d, error;
|
||||
|
||||
error = ofw_pcibus_parse_associativity(child, &d);
|
||||
if (error)
|
||||
return (bus_generic_get_cpus(dev, child, op, setsize, cpuset));
|
||||
d = platform_node_numa_domain(ofw_bus_get_node(dev));
|
||||
|
||||
switch (op) {
|
||||
case LOCAL_CPUS:
|
||||
@ -450,12 +424,7 @@ ofw_pcibus_get_cpus(device_t dev, device_t child, enum cpu_sets op, size_t setsi
|
||||
int
|
||||
ofw_pcibus_get_domain(device_t dev, device_t child, int *domain)
|
||||
{
|
||||
int d, error;
|
||||
*domain = platform_node_numa_domain(ofw_bus_get_node(child));
|
||||
|
||||
error = ofw_pcibus_parse_associativity(child, &d);
|
||||
/* No ofw node; go up a level */
|
||||
if (error)
|
||||
return (bus_generic_get_domain(dev, child, domain));
|
||||
*domain = d;
|
||||
return (0);
|
||||
}
|
||||
|
@ -79,6 +79,7 @@ static struct cpu_group *powernv_smp_topo(platform_t plat);
|
||||
static void powernv_reset(platform_t);
|
||||
static void powernv_cpu_idle(sbintime_t sbt);
|
||||
static int powernv_cpuref_init(void);
|
||||
static int powernv_node_numa_domain(platform_t platform, phandle_t node);
|
||||
|
||||
static platform_method_t powernv_methods[] = {
|
||||
PLATFORMMETHOD(platform_probe, powernv_probe),
|
||||
@ -96,6 +97,7 @@ static platform_method_t powernv_methods[] = {
|
||||
PLATFORMMETHOD(platform_smp_probe_threads, powernv_smp_probe_threads),
|
||||
PLATFORMMETHOD(platform_smp_topo, powernv_smp_topo),
|
||||
#endif
|
||||
PLATFORMMETHOD(platform_node_numa_domain, powernv_node_numa_domain),
|
||||
|
||||
PLATFORMMETHOD(platform_reset, powernv_reset),
|
||||
|
||||
@ -111,6 +113,7 @@ static platform_def_t powernv_platform = {
|
||||
static struct cpuref platform_cpuref[MAXCPU];
|
||||
static int platform_cpuref_cnt;
|
||||
static int platform_cpuref_valid;
|
||||
static int platform_associativity;
|
||||
|
||||
PLATFORM_DEF(powernv_platform);
|
||||
|
||||
@ -131,8 +134,10 @@ powernv_attach(platform_t plat)
|
||||
uint32_t nptlp, shift = 0, slb_encoding = 0;
|
||||
int32_t lp_size, lp_encoding;
|
||||
char buf[255];
|
||||
pcell_t refpoints[3];
|
||||
pcell_t prop;
|
||||
phandle_t cpu;
|
||||
phandle_t opal;
|
||||
int res, len, idx;
|
||||
register_t msr;
|
||||
|
||||
@ -144,6 +149,13 @@ powernv_attach(platform_t plat)
|
||||
#else
|
||||
opal_call(OPAL_REINIT_CPUS, 1 /* Big endian */);
|
||||
#endif
|
||||
opal = OF_finddevice("/ibm,opal");
|
||||
|
||||
platform_associativity = 4; /* Skiboot default. */
|
||||
if (OF_getencprop(opal, "ibm,associativity-reference-points", refpoints,
|
||||
sizeof(refpoints)) > 0) {
|
||||
platform_associativity = refpoints[0];
|
||||
}
|
||||
|
||||
if (cpu_idle_hook == NULL)
|
||||
cpu_idle_hook = powernv_cpu_idle;
|
||||
@ -328,7 +340,8 @@ powernv_cpuref_init(void)
|
||||
for (a = 0; a < res/sizeof(cell_t); a++) {
|
||||
tmp_cpuref[tmp_cpuref_cnt].cr_hwref = interrupt_servers[a];
|
||||
tmp_cpuref[tmp_cpuref_cnt].cr_cpuid = tmp_cpuref_cnt;
|
||||
tmp_cpuref[tmp_cpuref_cnt].cr_domain = interrupt_servers[a] >> 11;
|
||||
tmp_cpuref[tmp_cpuref_cnt].cr_domain =
|
||||
powernv_node_numa_domain(NULL, cpu);
|
||||
if (interrupt_servers[a] == (uint32_t)powernv_boot_pir)
|
||||
bsp = tmp_cpuref_cnt;
|
||||
|
||||
@ -495,6 +508,40 @@ powernv_cpu_idle(sbintime_t sbt)
|
||||
{
|
||||
}
|
||||
|
||||
static int
|
||||
powernv_node_numa_domain(platform_t platform, phandle_t node)
|
||||
{
|
||||
/* XXX: Is locking necessary in here? */
|
||||
static int numa_domains[MAXMEMDOM];
|
||||
static int numa_max_domain;
|
||||
cell_t associativity[5];
|
||||
int i, res;
|
||||
|
||||
res = OF_getproplen(node, "ibm,associativity");
|
||||
|
||||
/* If already at the root, use default domain. */
|
||||
if (res == 0)
|
||||
return (0);
|
||||
else if (res < 0)
|
||||
/* If this node doesn't have associativity, check its parent. */
|
||||
return (powernv_node_numa_domain(platform, OF_parent(node)));
|
||||
|
||||
OF_getencprop(node, "ibm,associativity",
|
||||
associativity, res);
|
||||
|
||||
for (i = 0; i < numa_max_domain; i++) {
|
||||
if (numa_domains[i] == associativity[platform_associativity])
|
||||
return (i);
|
||||
}
|
||||
if (i < MAXMEMDOM)
|
||||
numa_domains[numa_max_domain++] =
|
||||
associativity[platform_associativity];
|
||||
else
|
||||
i = 0;
|
||||
|
||||
return (i);
|
||||
}
|
||||
|
||||
/* Set up the Nest MMU on POWER9 relatively early, but after pmap is setup. */
|
||||
static void
|
||||
powernv_setup_nmmu(void *unused)
|
||||
|
@ -46,6 +46,7 @@
|
||||
*/
|
||||
|
||||
INTERFACE mmu;
|
||||
SINGLETON;
|
||||
|
||||
#
|
||||
# Default implementations of some methods
|
||||
|
@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/md_var.h>
|
||||
#include <machine/ofw_machdep.h>
|
||||
#include <machine/platform.h>
|
||||
#include <machine/platformvar.h>
|
||||
#include <machine/smp.h>
|
||||
@ -310,6 +311,12 @@ cpu_topo(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
platform_node_numa_domain(phandle_t node)
|
||||
{
|
||||
return (PLATFORM_NODE_NUMA_DOMAIN(plat_obj, node));
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset back to firmware.
|
||||
*/
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <sys/systm.h>
|
||||
#include <sys/smp.h>
|
||||
|
||||
#include <machine/ofw_machdep.h>
|
||||
#include <machine/platform.h>
|
||||
#include <machine/platformvar.h>
|
||||
#include <machine/smp.h>
|
||||
@ -88,6 +89,11 @@ CODE {
|
||||
{
|
||||
return;
|
||||
}
|
||||
static int platform_null_node_numa_domain(platform_t plat,
|
||||
phandle_t node)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@ -255,3 +261,12 @@ METHOD void smp_timebase_sync {
|
||||
int _ap;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Return the NUMA domain for the given device tree node. Always returns
|
||||
* a valid domain.
|
||||
*
|
||||
*/
|
||||
METHOD int node_numa_domain {
|
||||
platform_t _plat;
|
||||
phandle_t _node;
|
||||
} DEFAULT platform_null_node_numa_domain;
|
||||
|
@ -63,9 +63,13 @@ CNAME(sigcode64_elfv2):
|
||||
addi 3,1,112+SF_UC /* restore sp, and get &frame->sf_uc */
|
||||
li 0,SYS_sigreturn
|
||||
sc /* sigreturn(scp) */
|
||||
/*
|
||||
* If we get back to here, it means sigreturn failed.
|
||||
* As such, we are now stuck in the wrong context.
|
||||
* Exit immediately without touching the stack.
|
||||
*/
|
||||
li 0,SYS_exit
|
||||
sc /* exit(errno) */
|
||||
nop /* align to doubleword */
|
||||
endsigcode64:
|
||||
|
||||
.data
|
||||
|
@ -46,7 +46,6 @@
|
||||
#define REFCOUNT_COUNT(x) ((x) & ~REFCOUNT_WAITER)
|
||||
|
||||
bool refcount_release_last(volatile u_int *count, u_int n, u_int old);
|
||||
void refcount_sleep(volatile u_int *count, const char *wmesg, int prio);
|
||||
|
||||
/*
|
||||
* Attempt to handle reference count overflow and underflow. Force the counter
|
||||
@ -135,6 +134,21 @@ refcount_release(volatile u_int *count)
|
||||
return (refcount_releasen(count, 1));
|
||||
}
|
||||
|
||||
#ifdef _KERNEL
|
||||
struct lock_object;
|
||||
void _refcount_sleep(volatile u_int *count, struct lock_object *,
|
||||
const char *wmesg, int prio);
|
||||
|
||||
static __inline void
|
||||
refcount_sleep(volatile u_int *count, const char *wmesg, int prio)
|
||||
{
|
||||
|
||||
_refcount_sleep(count, NULL, wmesg, prio);
|
||||
}
|
||||
|
||||
#define refcount_sleep_interlock(count, lock, wmesg, prio) \
|
||||
_refcount_sleep((count), (struct lock_object *)(lock), (wmesg), (prio))
|
||||
|
||||
static __inline void
|
||||
refcount_wait(volatile u_int *count, const char *wmesg, int prio)
|
||||
{
|
||||
@ -142,6 +156,7 @@ refcount_wait(volatile u_int *count, const char *wmesg, int prio)
|
||||
while (*count != 0)
|
||||
refcount_sleep(count, wmesg, prio);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This functions returns non-zero if the refcount was
|
||||
|
@ -325,13 +325,18 @@ function handle_method (static, doc)
|
||||
line_width, length(prototype)));
|
||||
}
|
||||
printh("{");
|
||||
printh("\tkobjop_t _m;");
|
||||
if (singleton)
|
||||
printh("\tstatic kobjop_t _m;");
|
||||
else
|
||||
printh("\tkobjop_t _m;");
|
||||
if (ret != "void")
|
||||
printh("\t" ret " rc;");
|
||||
if (!static)
|
||||
firstvar = "((kobj_t)" firstvar ")";
|
||||
if (prolog != "")
|
||||
printh(prolog);
|
||||
if (singleton)
|
||||
printh("\tif (_m == NULL)");
|
||||
printh("\tKOBJOPLOOKUP(" firstvar "->ops," mname ");");
|
||||
rceq = (ret != "void") ? "rc = " : "";
|
||||
printh("\t" rceq "((" mname "_t *) _m)(" varname_list ");");
|
||||
@ -453,6 +458,7 @@ for (file_i = 0; file_i < num_files; file_i++) {
|
||||
lastdoc = "";
|
||||
prolog = "";
|
||||
epilog = "";
|
||||
singleton = 0;
|
||||
|
||||
while (!error && (getline < src) > 0) {
|
||||
lineno++;
|
||||
@ -497,6 +503,8 @@ for (file_i = 0; file_i < num_files; file_i++) {
|
||||
prolog = handle_code();
|
||||
else if (/^EPILOG[ ]*{$/)
|
||||
epilog = handle_code();
|
||||
else if (/^SINGLETON/)
|
||||
singleton = 1;
|
||||
else {
|
||||
debug($0);
|
||||
warnsrc("Invalid line encountered");
|
||||
|
@ -289,9 +289,9 @@ dev_pager_getpages(vm_object_t object, vm_page_t *ma, int count, int *rbehind,
|
||||
|
||||
/* Since our haspage reports zero after/before, the count is 1. */
|
||||
KASSERT(count == 1, ("%s: count %d", __func__, count));
|
||||
VM_OBJECT_ASSERT_WLOCKED(object);
|
||||
if (object->un_pager.devp.ops->cdev_pg_fault == NULL)
|
||||
return (VM_PAGER_FAIL);
|
||||
VM_OBJECT_WLOCK(object);
|
||||
error = object->un_pager.devp.ops->cdev_pg_fault(object,
|
||||
IDX_TO_OFF(ma[0]->pindex), PROT_READ, &ma[0]);
|
||||
|
||||
@ -312,6 +312,7 @@ dev_pager_getpages(vm_object_t object, vm_page_t *ma, int count, int *rbehind,
|
||||
if (rahead)
|
||||
*rahead = 0;
|
||||
}
|
||||
VM_OBJECT_WUNLOCK(object);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
@ -143,7 +143,6 @@ phys_pager_getpages(vm_object_t object, vm_page_t *m, int count, int *rbehind,
|
||||
{
|
||||
int i;
|
||||
|
||||
VM_OBJECT_ASSERT_WLOCKED(object);
|
||||
for (i = 0; i < count; i++) {
|
||||
if (vm_page_none_valid(m[i])) {
|
||||
if ((m[i]->flags & PG_ZERO) == 0)
|
||||
|
@ -155,10 +155,9 @@ sg_pager_getpages(vm_object_t object, vm_page_t *m, int count, int *rbehind,
|
||||
|
||||
/* Since our haspage reports zero after/before, the count is 1. */
|
||||
KASSERT(count == 1, ("%s: count %d", __func__, count));
|
||||
VM_OBJECT_ASSERT_WLOCKED(object);
|
||||
/* Handle is stable while paging is in progress. */
|
||||
sg = object->handle;
|
||||
memattr = object->memattr;
|
||||
VM_OBJECT_WUNLOCK(object);
|
||||
offset = m[0]->pindex;
|
||||
|
||||
/*
|
||||
@ -196,6 +195,7 @@ sg_pager_getpages(vm_object_t object, vm_page_t *m, int count, int *rbehind,
|
||||
VM_OBJECT_WLOCK(object);
|
||||
TAILQ_INSERT_TAIL(&object->un_pager.sgp.sgp_pglist, page, plinks.q);
|
||||
vm_page_replace(page, object, offset, m[0]);
|
||||
VM_OBJECT_WUNLOCK(object);
|
||||
m[0] = page;
|
||||
vm_page_valid(page);
|
||||
|
||||
|
@ -974,15 +974,12 @@ swp_pager_xfer_source(vm_object_t srcobject, vm_object_t dstobject,
|
||||
* Destination has no swapblk and is not resident, transfer source.
|
||||
* swp_pager_meta_build() can sleep.
|
||||
*/
|
||||
vm_object_pip_add(srcobject, 1);
|
||||
VM_OBJECT_WUNLOCK(srcobject);
|
||||
vm_object_pip_add(dstobject, 1);
|
||||
dstaddr = swp_pager_meta_build(dstobject, pindex, addr);
|
||||
KASSERT(dstaddr == SWAPBLK_NONE,
|
||||
("Unexpected destination swapblk"));
|
||||
vm_object_pip_wakeup(dstobject);
|
||||
VM_OBJECT_WLOCK(srcobject);
|
||||
vm_object_pip_wakeup(srcobject);
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
@ -995,8 +992,7 @@ swp_pager_xfer_source(vm_object_t srcobject, vm_object_t dstobject,
|
||||
* we keep the destination's.
|
||||
*
|
||||
* This routine is allowed to sleep. It may sleep allocating metadata
|
||||
* indirectly through swp_pager_meta_build() or if paging is still in
|
||||
* progress on the source.
|
||||
* indirectly through swp_pager_meta_build().
|
||||
*
|
||||
* The source object contains no vm_page_t's (which is just as well)
|
||||
*
|
||||
@ -1019,18 +1015,14 @@ swap_pager_copy(vm_object_t srcobject, vm_object_t dstobject,
|
||||
*/
|
||||
if (destroysource && (srcobject->flags & OBJ_ANON) == 0 &&
|
||||
srcobject->handle != NULL) {
|
||||
vm_object_pip_add(srcobject, 1);
|
||||
VM_OBJECT_WUNLOCK(srcobject);
|
||||
vm_object_pip_add(dstobject, 1);
|
||||
VM_OBJECT_WUNLOCK(dstobject);
|
||||
sx_xlock(&sw_alloc_sx);
|
||||
TAILQ_REMOVE(NOBJLIST(srcobject->handle), srcobject,
|
||||
pager_object_list);
|
||||
sx_xunlock(&sw_alloc_sx);
|
||||
VM_OBJECT_WLOCK(dstobject);
|
||||
vm_object_pip_wakeup(dstobject);
|
||||
VM_OBJECT_WLOCK(srcobject);
|
||||
vm_object_pip_wakeup(srcobject);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1205,28 +1197,34 @@ swap_pager_getpages(vm_object_t object, vm_page_t *ma, int count, int *rbehind,
|
||||
daddr_t blk;
|
||||
int i, maxahead, maxbehind, reqcount;
|
||||
|
||||
VM_OBJECT_WLOCK(object);
|
||||
reqcount = count;
|
||||
|
||||
/*
|
||||
* Determine the final number of read-behind pages and
|
||||
* allocate them BEFORE releasing the object lock. Otherwise,
|
||||
* there can be a problematic race with vm_object_split().
|
||||
* Specifically, vm_object_split() might first transfer pages
|
||||
* that precede ma[0] in the current object to a new object,
|
||||
* and then this function incorrectly recreates those pages as
|
||||
* read-behind pages in the current object.
|
||||
*/
|
||||
KASSERT(object->type == OBJT_SWAP,
|
||||
("%s: object not swappable", __func__));
|
||||
if (!swap_pager_haspage(object, ma[0]->pindex, &maxbehind, &maxahead))
|
||||
if (!swap_pager_haspage(object, ma[0]->pindex, &maxbehind, &maxahead)) {
|
||||
VM_OBJECT_WUNLOCK(object);
|
||||
return (VM_PAGER_FAIL);
|
||||
}
|
||||
|
||||
KASSERT(reqcount - 1 <= maxahead,
|
||||
("page count %d extends beyond swap block", reqcount));
|
||||
|
||||
/*
|
||||
* Do not transfer any pages other than those that are xbusied
|
||||
* when running during a split or collapse operation. This
|
||||
* prevents clustering from re-creating pages which are being
|
||||
* moved into another object.
|
||||
*/
|
||||
if ((object->flags & (OBJ_SPLIT | OBJ_DEAD)) != 0) {
|
||||
maxahead = reqcount - 1;
|
||||
maxbehind = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clip the readahead and readbehind ranges to exclude resident pages.
|
||||
*/
|
||||
if (rahead != NULL) {
|
||||
KASSERT(reqcount - 1 <= maxahead,
|
||||
("page count %d extends beyond swap block", reqcount));
|
||||
*rahead = imin(*rahead, maxahead - (reqcount - 1));
|
||||
pindex = ma[reqcount - 1]->pindex;
|
||||
msucc = TAILQ_NEXT(ma[reqcount - 1], listq);
|
||||
@ -1324,6 +1322,7 @@ swap_pager_getpages(vm_object_t object, vm_page_t *ma, int count, int *rbehind,
|
||||
* is set in the metadata for each page in the request.
|
||||
*/
|
||||
VM_OBJECT_WLOCK(object);
|
||||
/* This could be implemented more efficiently with aflags */
|
||||
while ((ma[0]->oflags & VPO_SWAPINPROG) != 0) {
|
||||
ma[0]->oflags |= VPO_SWAPSLEEP;
|
||||
VM_CNT_INC(v_intrans);
|
||||
@ -1334,6 +1333,7 @@ swap_pager_getpages(vm_object_t object, vm_page_t *ma, int count, int *rbehind,
|
||||
bp->b_bufobj, (intmax_t)bp->b_blkno, bp->b_bcount);
|
||||
}
|
||||
}
|
||||
VM_OBJECT_WUNLOCK(object);
|
||||
|
||||
/*
|
||||
* If we had an unrecoverable read error pages will not be valid.
|
||||
@ -1365,7 +1365,6 @@ swap_pager_getpages_async(vm_object_t object, vm_page_t *ma, int count,
|
||||
int r, error;
|
||||
|
||||
r = swap_pager_getpages(object, ma, count, rbehind, rahead);
|
||||
VM_OBJECT_WUNLOCK(object);
|
||||
switch (r) {
|
||||
case VM_PAGER_OK:
|
||||
error = 0;
|
||||
@ -1380,7 +1379,6 @@ swap_pager_getpages_async(vm_object_t object, vm_page_t *ma, int count,
|
||||
panic("unhandled swap_pager_getpages() error %d", r);
|
||||
}
|
||||
(iodone)(arg, ma, count, error);
|
||||
VM_OBJECT_WLOCK(object);
|
||||
|
||||
return (r);
|
||||
}
|
||||
@ -1761,10 +1759,12 @@ swp_pager_force_pagein(vm_object_t object, vm_pindex_t pindex, int npages)
|
||||
if (i < npages && ma[i]->valid != VM_PAGE_BITS_ALL)
|
||||
continue;
|
||||
if (j < i) {
|
||||
VM_OBJECT_WUNLOCK(object);
|
||||
/* Page-in nonresident pages. Mark for laundering. */
|
||||
if (swap_pager_getpages(object, &ma[j], i - j, NULL,
|
||||
NULL) != VM_PAGER_OK)
|
||||
panic("%s: read from swap failed", __func__);
|
||||
VM_OBJECT_WLOCK(object);
|
||||
do {
|
||||
swp_pager_force_launder(ma[j]);
|
||||
} while (++j < i);
|
||||
|
@ -1521,7 +1521,11 @@ pcpu_page_alloc(uma_zone_t zone, vm_size_t bytes, int domain, uint8_t *pflag,
|
||||
p = vm_page_alloc(NULL, 0, flags);
|
||||
#else
|
||||
pc = pcpu_find(cpu);
|
||||
p = vm_page_alloc_domain(NULL, 0, pc->pc_domain, flags);
|
||||
if (__predict_false(VM_DOMAIN_EMPTY(pc->pc_domain)))
|
||||
p = NULL;
|
||||
else
|
||||
p = vm_page_alloc_domain(NULL, 0,
|
||||
pc->pc_domain, flags);
|
||||
if (__predict_false(p == NULL))
|
||||
p = vm_page_alloc(NULL, 0, flags);
|
||||
#endif
|
||||
|
@ -1080,8 +1080,10 @@ readrest:
|
||||
}
|
||||
ahead = ulmin(ahead, atop(e_end - vaddr) - 1);
|
||||
}
|
||||
VM_OBJECT_WUNLOCK(fs.object);
|
||||
rv = vm_pager_get_pages(fs.object, &fs.m, 1,
|
||||
&behind, &ahead);
|
||||
VM_OBJECT_WLOCK(fs.object);
|
||||
if (rv == VM_PAGER_OK) {
|
||||
faultcount = behind + 1 + ahead;
|
||||
hardfault = true;
|
||||
|
@ -116,8 +116,6 @@ static int vm_object_page_collect_flush(vm_object_t object, vm_page_t p,
|
||||
boolean_t *eio);
|
||||
static boolean_t vm_object_page_remove_write(vm_page_t p, int flags,
|
||||
boolean_t *allclean);
|
||||
static void vm_object_qcollapse(vm_object_t object);
|
||||
static void vm_object_vndeallocate(vm_object_t object);
|
||||
static void vm_object_backing_remove(vm_object_t object);
|
||||
|
||||
/*
|
||||
@ -164,12 +162,18 @@ SYSCTL_COUNTER_U64(_vm_stats_object, OID_AUTO, bypasses, CTLFLAG_RD,
|
||||
&object_bypasses,
|
||||
"VM object bypasses");
|
||||
|
||||
static counter_u64_t object_collapse_waits = EARLY_COUNTER;
|
||||
SYSCTL_COUNTER_U64(_vm_stats_object, OID_AUTO, collapse_waits, CTLFLAG_RD,
|
||||
&object_collapse_waits,
|
||||
"Number of sleeps for collapse");
|
||||
|
||||
static void
|
||||
counter_startup(void)
|
||||
{
|
||||
|
||||
object_collapses = counter_u64_alloc(M_WAITOK);
|
||||
object_bypasses = counter_u64_alloc(M_WAITOK);
|
||||
object_collapse_waits = counter_u64_alloc(M_WAITOK);
|
||||
}
|
||||
SYSINIT(object_counters, SI_SUB_CPU, SI_ORDER_ANY, counter_startup, NULL);
|
||||
|
||||
@ -376,6 +380,19 @@ vm_object_pip_wakeupn(vm_object_t object, short i)
|
||||
refcount_releasen(&object->paging_in_progress, i);
|
||||
}
|
||||
|
||||
/*
|
||||
* Atomically drop the interlock and wait for pip to drain. This protects
|
||||
* from sleep/wakeup races due to identity changes. The lock is not
|
||||
* re-acquired on return.
|
||||
*/
|
||||
static void
|
||||
vm_object_pip_sleep(vm_object_t object, char *waitid)
|
||||
{
|
||||
|
||||
refcount_sleep_interlock(&object->paging_in_progress,
|
||||
&object->lock, waitid, PVM);
|
||||
}
|
||||
|
||||
void
|
||||
vm_object_pip_wait(vm_object_t object, char *waitid)
|
||||
{
|
||||
@ -383,8 +400,7 @@ vm_object_pip_wait(vm_object_t object, char *waitid)
|
||||
VM_OBJECT_ASSERT_WLOCKED(object);
|
||||
|
||||
while (REFCOUNT_COUNT(object->paging_in_progress) > 0) {
|
||||
VM_OBJECT_WUNLOCK(object);
|
||||
refcount_wait(&object->paging_in_progress, waitid, PVM);
|
||||
vm_object_pip_sleep(object, waitid);
|
||||
VM_OBJECT_WLOCK(object);
|
||||
}
|
||||
}
|
||||
@ -466,30 +482,17 @@ vm_object_allocate_anon(vm_pindex_t size, vm_object_t backing_object,
|
||||
return (object);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* vm_object_reference:
|
||||
*
|
||||
* Gets another reference to the given object. Note: OBJ_DEAD
|
||||
* objects can be referenced during final cleaning.
|
||||
*/
|
||||
void
|
||||
vm_object_reference(vm_object_t object)
|
||||
static void
|
||||
vm_object_reference_vnode(vm_object_t object)
|
||||
{
|
||||
struct vnode *vp;
|
||||
u_int old;
|
||||
|
||||
if (object == NULL)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Many places assume exclusive access to objects with a single
|
||||
* ref. vm_object_collapse() in particular will directly mainpulate
|
||||
* references for objects in this state. vnode objects only need
|
||||
* the lock for the first ref to reference the vnode.
|
||||
* vnode objects need the lock for the first reference
|
||||
* to serialize with vnode_object_deallocate().
|
||||
*/
|
||||
if (!refcount_acquire_if_gt(&object->ref_count,
|
||||
object->type == OBJT_VNODE ? 0 : 1)) {
|
||||
if (!refcount_acquire_if_gt(&object->ref_count, 0)) {
|
||||
VM_OBJECT_RLOCK(object);
|
||||
old = refcount_acquire(&object->ref_count);
|
||||
if (object->type == OBJT_VNODE && old == 0) {
|
||||
@ -500,6 +503,26 @@ vm_object_reference(vm_object_t object)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* vm_object_reference:
|
||||
*
|
||||
* Acquires a reference to the given object.
|
||||
*/
|
||||
void
|
||||
vm_object_reference(vm_object_t object)
|
||||
{
|
||||
|
||||
if (object == NULL)
|
||||
return;
|
||||
|
||||
if (object->type == OBJT_VNODE)
|
||||
vm_object_reference_vnode(object);
|
||||
else
|
||||
refcount_acquire(&object->ref_count);
|
||||
KASSERT((object->flags & OBJ_DEAD) == 0,
|
||||
("vm_object_reference: Referenced dead object."));
|
||||
}
|
||||
|
||||
/*
|
||||
* vm_object_reference_locked:
|
||||
*
|
||||
@ -516,23 +539,23 @@ vm_object_reference_locked(vm_object_t object)
|
||||
VM_OBJECT_ASSERT_LOCKED(object);
|
||||
old = refcount_acquire(&object->ref_count);
|
||||
if (object->type == OBJT_VNODE && old == 0) {
|
||||
vp = object->handle;
|
||||
vref(vp);
|
||||
}
|
||||
vp = object->handle; vref(vp); }
|
||||
KASSERT((object->flags & OBJ_DEAD) == 0,
|
||||
("vm_object_reference: Referenced dead object."));
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle deallocating an object of type OBJT_VNODE.
|
||||
*/
|
||||
static void
|
||||
vm_object_vndeallocate(vm_object_t object)
|
||||
vm_object_deallocate_vnode(vm_object_t object)
|
||||
{
|
||||
struct vnode *vp = (struct vnode *) object->handle;
|
||||
bool last;
|
||||
|
||||
KASSERT(object->type == OBJT_VNODE,
|
||||
("vm_object_vndeallocate: not a vnode object"));
|
||||
KASSERT(vp != NULL, ("vm_object_vndeallocate: missing vp"));
|
||||
("vm_object_deallocate_vnode: not a vnode object"));
|
||||
KASSERT(vp != NULL, ("vm_object_deallocate_vnode: missing vp"));
|
||||
|
||||
/* Object lock to protect handle lookup. */
|
||||
last = refcount_release(&object->ref_count);
|
||||
@ -548,6 +571,53 @@ vm_object_vndeallocate(vm_object_t object)
|
||||
vrele(vp);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* We dropped a reference on an object and discovered that it had a
|
||||
* single remaining shadow. This is a sibling of the reference we
|
||||
* dropped. Attempt to collapse the sibling and backing object.
|
||||
*/
|
||||
static vm_object_t
|
||||
vm_object_deallocate_anon(vm_object_t backing_object)
|
||||
{
|
||||
vm_object_t object;
|
||||
|
||||
/* Fetch the final shadow. */
|
||||
object = LIST_FIRST(&backing_object->shadow_head);
|
||||
KASSERT(object != NULL && backing_object->shadow_count == 1,
|
||||
("vm_object_anon_deallocate: ref_count: %d, shadow_count: %d",
|
||||
backing_object->ref_count, backing_object->shadow_count));
|
||||
KASSERT((object->flags & (OBJ_TMPFS_NODE | OBJ_ANON)) == OBJ_ANON,
|
||||
("invalid shadow object %p", object));
|
||||
|
||||
if (!VM_OBJECT_TRYWLOCK(object)) {
|
||||
/*
|
||||
* Prevent object from disappearing since we do not have a
|
||||
* reference.
|
||||
*/
|
||||
vm_object_pip_add(object, 1);
|
||||
VM_OBJECT_WUNLOCK(backing_object);
|
||||
VM_OBJECT_WLOCK(object);
|
||||
vm_object_pip_wakeup(object);
|
||||
} else
|
||||
VM_OBJECT_WUNLOCK(backing_object);
|
||||
|
||||
/*
|
||||
* Check for a collapse/terminate race with the last reference holder.
|
||||
*/
|
||||
if ((object->flags & (OBJ_DEAD | OBJ_COLLAPSING)) != 0 ||
|
||||
!refcount_acquire_if_not_zero(&object->ref_count)) {
|
||||
VM_OBJECT_WUNLOCK(object);
|
||||
return (NULL);
|
||||
}
|
||||
backing_object = object->backing_object;
|
||||
if (backing_object != NULL && (backing_object->flags & OBJ_ANON) != 0)
|
||||
vm_object_collapse(object);
|
||||
VM_OBJECT_WUNLOCK(object);
|
||||
|
||||
return (object);
|
||||
}
|
||||
|
||||
/*
|
||||
* vm_object_deallocate:
|
||||
*
|
||||
@ -562,7 +632,7 @@ vm_object_vndeallocate(vm_object_t object)
|
||||
void
|
||||
vm_object_deallocate(vm_object_t object)
|
||||
{
|
||||
vm_object_t robject, temp;
|
||||
vm_object_t temp;
|
||||
bool released;
|
||||
|
||||
while (object != NULL) {
|
||||
@ -583,7 +653,7 @@ vm_object_deallocate(vm_object_t object)
|
||||
if (object->type == OBJT_VNODE) {
|
||||
VM_OBJECT_RLOCK(object);
|
||||
if (object->type == OBJT_VNODE) {
|
||||
vm_object_vndeallocate(object);
|
||||
vm_object_deallocate_vnode(object);
|
||||
return;
|
||||
}
|
||||
VM_OBJECT_RUNLOCK(object);
|
||||
@ -594,92 +664,30 @@ vm_object_deallocate(vm_object_t object)
|
||||
("vm_object_deallocate: object deallocated too many times: %d",
|
||||
object->type));
|
||||
|
||||
if (refcount_release(&object->ref_count))
|
||||
goto doterm;
|
||||
if (object->ref_count > 1) {
|
||||
VM_OBJECT_WUNLOCK(object);
|
||||
return;
|
||||
} else if (object->ref_count == 1) {
|
||||
if (object->shadow_count == 0 &&
|
||||
(object->flags & OBJ_ANON) != 0) {
|
||||
vm_object_set_flag(object, OBJ_ONEMAPPING);
|
||||
} else if (object->shadow_count == 1) {
|
||||
KASSERT((object->flags & OBJ_ANON) != 0,
|
||||
("obj %p with shadow_count > 0 is not anon",
|
||||
object));
|
||||
robject = LIST_FIRST(&object->shadow_head);
|
||||
KASSERT(robject != NULL,
|
||||
("vm_object_deallocate: ref_count: %d, "
|
||||
"shadow_count: %d", object->ref_count,
|
||||
object->shadow_count));
|
||||
KASSERT((robject->flags & OBJ_TMPFS_NODE) == 0,
|
||||
("shadowed tmpfs v_object %p", object));
|
||||
if (!VM_OBJECT_TRYWLOCK(robject)) {
|
||||
/*
|
||||
* Avoid a potential deadlock.
|
||||
*/
|
||||
refcount_acquire(&object->ref_count);
|
||||
VM_OBJECT_WUNLOCK(object);
|
||||
/*
|
||||
* More likely than not the thread
|
||||
* holding robject's lock has lower
|
||||
* priority than the current thread.
|
||||
* Let the lower priority thread run.
|
||||
*/
|
||||
pause("vmo_de", 1);
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* Collapse object into its shadow unless its
|
||||
* shadow is dead. In that case, object will
|
||||
* be deallocated by the thread that is
|
||||
* deallocating its shadow.
|
||||
*/
|
||||
if ((robject->flags &
|
||||
(OBJ_DEAD | OBJ_ANON)) == OBJ_ANON) {
|
||||
|
||||
refcount_acquire(&robject->ref_count);
|
||||
retry:
|
||||
if (REFCOUNT_COUNT(robject->paging_in_progress) > 0) {
|
||||
VM_OBJECT_WUNLOCK(object);
|
||||
vm_object_pip_wait(robject,
|
||||
"objde1");
|
||||
temp = robject->backing_object;
|
||||
if (object == temp) {
|
||||
VM_OBJECT_WLOCK(object);
|
||||
goto retry;
|
||||
}
|
||||
} else if (REFCOUNT_COUNT(object->paging_in_progress) > 0) {
|
||||
VM_OBJECT_WUNLOCK(robject);
|
||||
VM_OBJECT_WUNLOCK(object);
|
||||
refcount_wait(
|
||||
&object->paging_in_progress,
|
||||
"objde2", PVM);
|
||||
VM_OBJECT_WLOCK(robject);
|
||||
temp = robject->backing_object;
|
||||
if (object == temp) {
|
||||
VM_OBJECT_WLOCK(object);
|
||||
goto retry;
|
||||
}
|
||||
} else
|
||||
VM_OBJECT_WUNLOCK(object);
|
||||
|
||||
if (robject->ref_count == 1) {
|
||||
refcount_release(&robject->ref_count);
|
||||
object = robject;
|
||||
goto doterm;
|
||||
}
|
||||
object = robject;
|
||||
vm_object_collapse(object);
|
||||
VM_OBJECT_WUNLOCK(object);
|
||||
continue;
|
||||
}
|
||||
VM_OBJECT_WUNLOCK(robject);
|
||||
/*
|
||||
* If this is not the final reference to an anonymous
|
||||
* object we may need to collapse the shadow chain.
|
||||
*/
|
||||
if (!refcount_release(&object->ref_count)) {
|
||||
if (object->ref_count > 1 ||
|
||||
object->shadow_count == 0) {
|
||||
if ((object->flags & OBJ_ANON) != 0 &&
|
||||
object->ref_count == 1)
|
||||
vm_object_set_flag(object,
|
||||
OBJ_ONEMAPPING);
|
||||
VM_OBJECT_WUNLOCK(object);
|
||||
return;
|
||||
}
|
||||
VM_OBJECT_WUNLOCK(object);
|
||||
return;
|
||||
|
||||
/* Handle collapsing last ref on anonymous objects. */
|
||||
object = vm_object_deallocate_anon(object);
|
||||
continue;
|
||||
}
|
||||
doterm:
|
||||
|
||||
/*
|
||||
* Handle the final reference to an object. We restart
|
||||
* the loop with the backing object to avoid recursion.
|
||||
*/
|
||||
umtx_shm_object_terminated(object);
|
||||
temp = object->backing_object;
|
||||
if (temp != NULL) {
|
||||
@ -687,16 +695,11 @@ doterm:
|
||||
("shadowed tmpfs v_object 2 %p", object));
|
||||
vm_object_backing_remove(object);
|
||||
}
|
||||
/*
|
||||
* Don't double-terminate, we could be in a termination
|
||||
* recursion due to the terminate having to sync data
|
||||
* to disk.
|
||||
*/
|
||||
if ((object->flags & OBJ_DEAD) == 0) {
|
||||
vm_object_set_flag(object, OBJ_DEAD);
|
||||
vm_object_terminate(object);
|
||||
} else
|
||||
VM_OBJECT_WUNLOCK(object);
|
||||
|
||||
KASSERT((object->flags & OBJ_DEAD) == 0,
|
||||
("vm_object_deallocate: Terminating dead object."));
|
||||
vm_object_set_flag(object, OBJ_DEAD);
|
||||
vm_object_terminate(object);
|
||||
object = temp;
|
||||
}
|
||||
}
|
||||
@ -734,6 +737,9 @@ vm_object_backing_remove_locked(vm_object_t object)
|
||||
VM_OBJECT_ASSERT_WLOCKED(object);
|
||||
VM_OBJECT_ASSERT_WLOCKED(backing_object);
|
||||
|
||||
KASSERT((object->flags & OBJ_COLLAPSING) == 0,
|
||||
("vm_object_backing_remove: Removing collapsing object."));
|
||||
|
||||
if ((object->flags & OBJ_SHADOWLIST) != 0) {
|
||||
LIST_REMOVE(object, shadow_list);
|
||||
backing_object->shadow_count--;
|
||||
@ -788,6 +794,98 @@ vm_object_backing_insert(vm_object_t object, vm_object_t backing_object)
|
||||
object->backing_object = backing_object;
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert an object into a backing_object's shadow list with an additional
|
||||
* reference to the backing_object added.
|
||||
*/
|
||||
static void
|
||||
vm_object_backing_insert_ref(vm_object_t object, vm_object_t backing_object)
|
||||
{
|
||||
|
||||
VM_OBJECT_ASSERT_WLOCKED(object);
|
||||
|
||||
if ((backing_object->flags & OBJ_ANON) != 0) {
|
||||
VM_OBJECT_WLOCK(backing_object);
|
||||
KASSERT((backing_object->flags & OBJ_DEAD) == 0,
|
||||
("shadowing dead anonymous object"));
|
||||
vm_object_reference_locked(backing_object);
|
||||
vm_object_backing_insert_locked(object, backing_object);
|
||||
vm_object_clear_flag(backing_object, OBJ_ONEMAPPING);
|
||||
VM_OBJECT_WUNLOCK(backing_object);
|
||||
} else {
|
||||
vm_object_reference(backing_object);
|
||||
object->backing_object = backing_object;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Transfer a backing reference from backing_object to object.
|
||||
*/
|
||||
static void
|
||||
vm_object_backing_transfer(vm_object_t object, vm_object_t backing_object)
|
||||
{
|
||||
vm_object_t new_backing_object;
|
||||
|
||||
/*
|
||||
* Note that the reference to backing_object->backing_object
|
||||
* moves from within backing_object to within object.
|
||||
*/
|
||||
vm_object_backing_remove_locked(object);
|
||||
new_backing_object = backing_object->backing_object;
|
||||
if (new_backing_object == NULL)
|
||||
return;
|
||||
if ((new_backing_object->flags & OBJ_ANON) != 0) {
|
||||
VM_OBJECT_WLOCK(new_backing_object);
|
||||
vm_object_backing_remove_locked(backing_object);
|
||||
vm_object_backing_insert_locked(object, new_backing_object);
|
||||
VM_OBJECT_WUNLOCK(new_backing_object);
|
||||
} else {
|
||||
object->backing_object = new_backing_object;
|
||||
backing_object->backing_object = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait for a concurrent collapse to settle.
|
||||
*/
|
||||
static void
|
||||
vm_object_collapse_wait(vm_object_t object)
|
||||
{
|
||||
|
||||
VM_OBJECT_ASSERT_WLOCKED(object);
|
||||
|
||||
while ((object->flags & OBJ_COLLAPSING) != 0) {
|
||||
vm_object_pip_wait(object, "vmcolwait");
|
||||
counter_u64_add(object_collapse_waits, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Waits for a backing object to clear a pending collapse and returns
|
||||
* it locked if it is an ANON object.
|
||||
*/
|
||||
static vm_object_t
|
||||
vm_object_backing_collapse_wait(vm_object_t object)
|
||||
{
|
||||
vm_object_t backing_object;
|
||||
|
||||
VM_OBJECT_ASSERT_WLOCKED(object);
|
||||
|
||||
for (;;) {
|
||||
backing_object = object->backing_object;
|
||||
if (backing_object == NULL ||
|
||||
(backing_object->flags & OBJ_ANON) == 0)
|
||||
return (NULL);
|
||||
VM_OBJECT_WLOCK(backing_object);
|
||||
if ((backing_object->flags & (OBJ_DEAD | OBJ_COLLAPSING)) == 0)
|
||||
break;
|
||||
VM_OBJECT_WUNLOCK(object);
|
||||
vm_object_pip_sleep(backing_object, "vmbckwait");
|
||||
counter_u64_add(object_collapse_waits, 1);
|
||||
VM_OBJECT_WLOCK(object);
|
||||
}
|
||||
return (backing_object);
|
||||
}
|
||||
|
||||
/*
|
||||
* vm_object_terminate_pages removes any remaining pageable pages
|
||||
@ -843,9 +941,14 @@ vm_object_terminate_pages(vm_object_t object)
|
||||
void
|
||||
vm_object_terminate(vm_object_t object)
|
||||
{
|
||||
|
||||
VM_OBJECT_ASSERT_WLOCKED(object);
|
||||
KASSERT((object->flags & OBJ_DEAD) != 0,
|
||||
("terminating non-dead obj %p", object));
|
||||
KASSERT((object->flags & OBJ_COLLAPSING) == 0,
|
||||
("terminating collapsing obj %p", object));
|
||||
KASSERT(object->backing_object == NULL,
|
||||
("terminating shadow obj %p", object));
|
||||
|
||||
/*
|
||||
* wait for the pageout daemon to be done with the object
|
||||
@ -853,11 +956,11 @@ vm_object_terminate(vm_object_t object)
|
||||
vm_object_pip_wait(object, "objtrm");
|
||||
|
||||
KASSERT(!REFCOUNT_COUNT(object->paging_in_progress),
|
||||
("vm_object_terminate: pageout in progress"));
|
||||
("vm_object_terminate: pageout in progress"));
|
||||
|
||||
KASSERT(object->ref_count == 0,
|
||||
("vm_object_terminate: object with references, ref_count=%d",
|
||||
object->ref_count));
|
||||
KASSERT(object->ref_count == 0,
|
||||
("vm_object_terminate: object with references, ref_count=%d",
|
||||
object->ref_count));
|
||||
|
||||
if ((object->flags & OBJ_PG_DTOR) == 0)
|
||||
vm_object_terminate_pages(object);
|
||||
@ -1397,11 +1500,13 @@ void
|
||||
vm_object_split(vm_map_entry_t entry)
|
||||
{
|
||||
vm_page_t m, m_next;
|
||||
vm_object_t orig_object, new_object, source;
|
||||
vm_object_t orig_object, new_object, backing_object;
|
||||
vm_pindex_t idx, offidxstart;
|
||||
vm_size_t size;
|
||||
|
||||
orig_object = entry->object.vm_object;
|
||||
KASSERT((orig_object->flags & OBJ_ONEMAPPING) != 0,
|
||||
("vm_object_split: Splitting object with multiple mappings."));
|
||||
if ((orig_object->flags & OBJ_ANON) == 0)
|
||||
return;
|
||||
if (orig_object->ref_count <= 1)
|
||||
@ -1418,36 +1523,26 @@ vm_object_split(vm_map_entry_t entry)
|
||||
new_object = vm_object_allocate_anon(size, orig_object,
|
||||
orig_object->cred, ptoa(size));
|
||||
|
||||
/*
|
||||
* We must wait for the orig_object to complete any in-progress
|
||||
* collapse so that the swap blocks are stable below. The
|
||||
* additional reference on backing_object by new object will
|
||||
* prevent further collapse operations until split completes.
|
||||
*/
|
||||
VM_OBJECT_WLOCK(orig_object);
|
||||
vm_object_collapse_wait(orig_object);
|
||||
|
||||
/*
|
||||
* At this point, the new object is still private, so the order in
|
||||
* which the original and new objects are locked does not matter.
|
||||
*/
|
||||
VM_OBJECT_WLOCK(new_object);
|
||||
VM_OBJECT_WLOCK(orig_object);
|
||||
new_object->domain = orig_object->domain;
|
||||
source = orig_object->backing_object;
|
||||
if (source != NULL) {
|
||||
if ((source->flags & (OBJ_ANON | OBJ_DEAD)) != 0) {
|
||||
VM_OBJECT_WLOCK(source);
|
||||
if ((source->flags & OBJ_DEAD) != 0) {
|
||||
VM_OBJECT_WUNLOCK(source);
|
||||
VM_OBJECT_WUNLOCK(orig_object);
|
||||
VM_OBJECT_WUNLOCK(new_object);
|
||||
new_object->cred = NULL;
|
||||
vm_object_deallocate(new_object);
|
||||
VM_OBJECT_WLOCK(orig_object);
|
||||
return;
|
||||
}
|
||||
vm_object_backing_insert_locked(new_object, source);
|
||||
vm_object_reference_locked(source); /* for new_object */
|
||||
vm_object_clear_flag(source, OBJ_ONEMAPPING);
|
||||
VM_OBJECT_WUNLOCK(source);
|
||||
} else {
|
||||
vm_object_backing_insert(new_object, source);
|
||||
vm_object_reference(source);
|
||||
}
|
||||
backing_object = orig_object->backing_object;
|
||||
if (backing_object != NULL) {
|
||||
vm_object_backing_insert_ref(new_object, backing_object);
|
||||
new_object->backing_object_offset =
|
||||
orig_object->backing_object_offset + entry->offset;
|
||||
orig_object->backing_object_offset + entry->offset;
|
||||
}
|
||||
if (orig_object->cred != NULL) {
|
||||
crhold(orig_object->cred);
|
||||
@ -1455,6 +1550,12 @@ vm_object_split(vm_map_entry_t entry)
|
||||
("orig_object->charge < 0"));
|
||||
orig_object->charge -= ptoa(size);
|
||||
}
|
||||
|
||||
/*
|
||||
* Mark the split operation so that swap_pager_getpages() knows
|
||||
* that the object is in transition.
|
||||
*/
|
||||
vm_object_set_flag(orig_object, OBJ_SPLIT);
|
||||
retry:
|
||||
m = vm_page_find_least(orig_object, offidxstart);
|
||||
for (; m != NULL && (idx = m->pindex - offidxstart) < size;
|
||||
@ -1523,6 +1624,7 @@ retry:
|
||||
TAILQ_FOREACH(m, &new_object->memq, listq)
|
||||
vm_page_xunbusy(m);
|
||||
}
|
||||
vm_object_clear_flag(orig_object, OBJ_SPLIT);
|
||||
VM_OBJECT_WUNLOCK(orig_object);
|
||||
VM_OBJECT_WUNLOCK(new_object);
|
||||
entry->object.vm_object = new_object;
|
||||
@ -1531,12 +1633,8 @@ retry:
|
||||
VM_OBJECT_WLOCK(new_object);
|
||||
}
|
||||
|
||||
#define OBSC_COLLAPSE_NOWAIT 0x0002
|
||||
#define OBSC_COLLAPSE_WAIT 0x0004
|
||||
|
||||
static vm_page_t
|
||||
vm_object_collapse_scan_wait(vm_object_t object, vm_page_t p, vm_page_t next,
|
||||
int op)
|
||||
vm_object_collapse_scan_wait(vm_object_t object, vm_page_t p)
|
||||
{
|
||||
vm_object_t backing_object;
|
||||
|
||||
@ -1546,8 +1644,6 @@ vm_object_collapse_scan_wait(vm_object_t object, vm_page_t p, vm_page_t next,
|
||||
|
||||
KASSERT(p == NULL || p->object == object || p->object == backing_object,
|
||||
("invalid ownership %p %p %p", p, object, backing_object));
|
||||
if ((op & OBSC_COLLAPSE_NOWAIT) != 0)
|
||||
return (next);
|
||||
/* The page is only NULL when rename fails. */
|
||||
if (p == NULL) {
|
||||
VM_OBJECT_WUNLOCK(object);
|
||||
@ -1632,8 +1728,8 @@ vm_object_scan_all_shadowed(vm_object_t object)
|
||||
return (true);
|
||||
}
|
||||
|
||||
static bool
|
||||
vm_object_collapse_scan(vm_object_t object, int op)
|
||||
static void
|
||||
vm_object_collapse_scan(vm_object_t object)
|
||||
{
|
||||
vm_object_t backing_object;
|
||||
vm_page_t next, p, pp;
|
||||
@ -1645,12 +1741,6 @@ vm_object_collapse_scan(vm_object_t object, int op)
|
||||
backing_object = object->backing_object;
|
||||
backing_offset_index = OFF_TO_IDX(object->backing_object_offset);
|
||||
|
||||
/*
|
||||
* Initial conditions
|
||||
*/
|
||||
if ((op & OBSC_COLLAPSE_WAIT) != 0)
|
||||
vm_object_set_flag(backing_object, OBJ_DEAD);
|
||||
|
||||
/*
|
||||
* Our scan
|
||||
*/
|
||||
@ -1662,12 +1752,16 @@ vm_object_collapse_scan(vm_object_t object, int op)
|
||||
* Check for busy page
|
||||
*/
|
||||
if (vm_page_tryxbusy(p) == 0) {
|
||||
next = vm_object_collapse_scan_wait(object, p, next, op);
|
||||
next = vm_object_collapse_scan_wait(object, p);
|
||||
continue;
|
||||
}
|
||||
|
||||
KASSERT(object->backing_object == backing_object,
|
||||
("vm_object_collapse_scan: backing object mismatch %p != %p",
|
||||
object->backing_object, backing_object));
|
||||
KASSERT(p->object == backing_object,
|
||||
("vm_object_collapse_scan: object mismatch"));
|
||||
("vm_object_collapse_scan: object mismatch %p != %p",
|
||||
p->object, backing_object));
|
||||
|
||||
if (p->pindex < backing_offset_index ||
|
||||
new_pindex >= object->size) {
|
||||
@ -1689,16 +1783,9 @@ vm_object_collapse_scan(vm_object_t object, int op)
|
||||
* The page in the parent is busy and possibly not
|
||||
* (yet) valid. Until its state is finalized by the
|
||||
* busy bit owner, we can't tell whether it shadows the
|
||||
* original page. Therefore, we must either skip it
|
||||
* and the original (backing_object) page or wait for
|
||||
* its state to be finalized.
|
||||
*
|
||||
* This is due to a race with vm_fault() where we must
|
||||
* unbusy the original (backing_obj) page before we can
|
||||
* (re)lock the parent. Hence we can get here.
|
||||
* original page.
|
||||
*/
|
||||
next = vm_object_collapse_scan_wait(object, pp, next,
|
||||
op);
|
||||
next = vm_object_collapse_scan_wait(object, pp);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1742,10 +1829,7 @@ vm_object_collapse_scan(vm_object_t object, int op)
|
||||
*/
|
||||
if (vm_page_rename(p, object, new_pindex)) {
|
||||
vm_page_xunbusy(p);
|
||||
if (pp != NULL)
|
||||
vm_page_xunbusy(pp);
|
||||
next = vm_object_collapse_scan_wait(object, NULL, next,
|
||||
op);
|
||||
next = vm_object_collapse_scan_wait(object, NULL);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1763,27 +1847,7 @@ vm_object_collapse_scan(vm_object_t object, int op)
|
||||
#endif
|
||||
vm_page_xunbusy(p);
|
||||
}
|
||||
return (true);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* this version of collapse allows the operation to occur earlier and
|
||||
* when paging_in_progress is true for an object... This is not a complete
|
||||
* operation, but should plug 99.9% of the rest of the leaks.
|
||||
*/
|
||||
static void
|
||||
vm_object_qcollapse(vm_object_t object)
|
||||
{
|
||||
vm_object_t backing_object = object->backing_object;
|
||||
|
||||
VM_OBJECT_ASSERT_WLOCKED(object);
|
||||
VM_OBJECT_ASSERT_WLOCKED(backing_object);
|
||||
|
||||
if (backing_object->ref_count != 1)
|
||||
return;
|
||||
|
||||
vm_object_collapse_scan(object, OBSC_COLLAPSE_NOWAIT);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1801,53 +1865,48 @@ vm_object_collapse(vm_object_t object)
|
||||
VM_OBJECT_ASSERT_WLOCKED(object);
|
||||
|
||||
while (TRUE) {
|
||||
KASSERT((object->flags & (OBJ_DEAD | OBJ_ANON)) == OBJ_ANON,
|
||||
("collapsing invalid object"));
|
||||
|
||||
/*
|
||||
* Verify that the conditions are right for collapse:
|
||||
*
|
||||
* The object exists and the backing object exists.
|
||||
* Wait for the backing_object to finish any pending
|
||||
* collapse so that the caller sees the shortest possible
|
||||
* shadow chain.
|
||||
*/
|
||||
if ((backing_object = object->backing_object) == NULL)
|
||||
break;
|
||||
backing_object = vm_object_backing_collapse_wait(object);
|
||||
if (backing_object == NULL)
|
||||
return;
|
||||
|
||||
KASSERT(object->ref_count > 0 &&
|
||||
object->ref_count > object->shadow_count,
|
||||
("collapse with invalid ref %d or shadow %d count.",
|
||||
object->ref_count, object->shadow_count));
|
||||
KASSERT((backing_object->flags &
|
||||
(OBJ_COLLAPSING | OBJ_DEAD)) == 0,
|
||||
("vm_object_collapse: Backing object already collapsing."));
|
||||
KASSERT((object->flags & (OBJ_COLLAPSING | OBJ_DEAD)) == 0,
|
||||
("vm_object_collapse: object is already collapsing."));
|
||||
|
||||
/*
|
||||
* we check the backing object first, because it is most likely
|
||||
* not collapsable.
|
||||
*/
|
||||
if ((backing_object->flags & OBJ_ANON) == 0)
|
||||
break;
|
||||
VM_OBJECT_WLOCK(backing_object);
|
||||
if ((backing_object->flags & OBJ_DEAD) != 0 ||
|
||||
(object->flags & (OBJ_DEAD | OBJ_ANON)) != OBJ_ANON) {
|
||||
VM_OBJECT_WUNLOCK(backing_object);
|
||||
break;
|
||||
}
|
||||
|
||||
if (REFCOUNT_COUNT(object->paging_in_progress) > 0 ||
|
||||
REFCOUNT_COUNT(backing_object->paging_in_progress) > 0) {
|
||||
vm_object_qcollapse(object);
|
||||
VM_OBJECT_WUNLOCK(backing_object);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* We know that we can either collapse the backing object (if
|
||||
* the parent is the only reference to it) or (perhaps) have
|
||||
* We know that we can either collapse the backing object if
|
||||
* the parent is the only reference to it, or (perhaps) have
|
||||
* the parent bypass the object if the parent happens to shadow
|
||||
* all the resident pages in the entire backing object.
|
||||
*
|
||||
* This is ignoring pager-backed pages such as swap pages.
|
||||
* vm_object_collapse_scan fails the shadowing test in this
|
||||
* case.
|
||||
*/
|
||||
if (backing_object->ref_count == 1) {
|
||||
KASSERT(backing_object->shadow_count == 1,
|
||||
("vm_object_collapse: shadow_count: %d",
|
||||
backing_object->shadow_count));
|
||||
vm_object_pip_add(object, 1);
|
||||
vm_object_set_flag(object, OBJ_COLLAPSING);
|
||||
vm_object_pip_add(backing_object, 1);
|
||||
vm_object_set_flag(backing_object, OBJ_DEAD);
|
||||
|
||||
/*
|
||||
* If there is exactly one reference to the backing
|
||||
* object, we can collapse it into the parent.
|
||||
*/
|
||||
vm_object_collapse_scan(object, OBSC_COLLAPSE_WAIT);
|
||||
vm_object_collapse_scan(object);
|
||||
|
||||
#if VM_NRESERVLEVEL > 0
|
||||
/*
|
||||
@ -1866,31 +1925,24 @@ vm_object_collapse(vm_object_t object)
|
||||
* the backing_object's and object's locks are
|
||||
* released and reacquired.
|
||||
* Since swap_pager_copy() is being asked to
|
||||
* destroy the source, it will change the
|
||||
* backing_object's type to OBJT_DEFAULT.
|
||||
* destroy backing_object, it will change the
|
||||
* type to OBJT_DEFAULT.
|
||||
*/
|
||||
swap_pager_copy(
|
||||
backing_object,
|
||||
object,
|
||||
OFF_TO_IDX(object->backing_object_offset), TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Object now shadows whatever backing_object did.
|
||||
* Note that the reference to
|
||||
* backing_object->backing_object moves from within
|
||||
* backing_object to within object.
|
||||
*/
|
||||
vm_object_backing_remove_locked(object);
|
||||
new_backing_object = backing_object->backing_object;
|
||||
if (new_backing_object != NULL) {
|
||||
VM_OBJECT_WLOCK(new_backing_object);
|
||||
vm_object_backing_remove_locked(backing_object);
|
||||
vm_object_backing_insert_locked(object,
|
||||
new_backing_object);
|
||||
VM_OBJECT_WUNLOCK(new_backing_object);
|
||||
}
|
||||
vm_object_clear_flag(object, OBJ_COLLAPSING);
|
||||
vm_object_backing_transfer(object, backing_object);
|
||||
object->backing_object_offset +=
|
||||
backing_object->backing_object_offset;
|
||||
VM_OBJECT_WUNLOCK(object);
|
||||
vm_object_pip_wakeup(object);
|
||||
|
||||
/*
|
||||
* Discard backing_object.
|
||||
@ -1903,17 +1955,17 @@ vm_object_collapse(vm_object_t object)
|
||||
"backing_object %p was somehow re-referenced during collapse!",
|
||||
backing_object));
|
||||
vm_object_pip_wakeup(backing_object);
|
||||
backing_object->type = OBJT_DEAD;
|
||||
refcount_release(&backing_object->ref_count);
|
||||
VM_OBJECT_WUNLOCK(backing_object);
|
||||
vm_object_destroy(backing_object);
|
||||
|
||||
vm_object_pip_wakeup(object);
|
||||
(void)refcount_release(&backing_object->ref_count);
|
||||
vm_object_terminate(backing_object);
|
||||
counter_u64_add(object_collapses, 1);
|
||||
VM_OBJECT_WLOCK(object);
|
||||
} else {
|
||||
/*
|
||||
* If we do not entirely shadow the backing object,
|
||||
* there is nothing we can do so we give up.
|
||||
*
|
||||
* The object lock and backing_object lock must not
|
||||
* be dropped during this sequence.
|
||||
*/
|
||||
if (!vm_object_scan_all_shadowed(object)) {
|
||||
VM_OBJECT_WUNLOCK(backing_object);
|
||||
@ -1926,21 +1978,22 @@ vm_object_collapse(vm_object_t object)
|
||||
* it, since its reference count is at least 2.
|
||||
*/
|
||||
vm_object_backing_remove_locked(object);
|
||||
|
||||
new_backing_object = backing_object->backing_object;
|
||||
if (new_backing_object != NULL) {
|
||||
vm_object_backing_insert(object,
|
||||
vm_object_backing_insert_ref(object,
|
||||
new_backing_object);
|
||||
vm_object_reference(new_backing_object);
|
||||
object->backing_object_offset +=
|
||||
backing_object->backing_object_offset;
|
||||
backing_object->backing_object_offset;
|
||||
}
|
||||
|
||||
/*
|
||||
* Drop the reference count on backing_object. Since
|
||||
* its ref_count was at least 2, it will not vanish.
|
||||
*/
|
||||
refcount_release(&backing_object->ref_count);
|
||||
(void)refcount_release(&backing_object->ref_count);
|
||||
KASSERT(backing_object->ref_count >= 1, (
|
||||
"backing_object %p was somehow dereferenced during collapse!",
|
||||
backing_object));
|
||||
VM_OBJECT_WUNLOCK(backing_object);
|
||||
counter_u64_add(object_bypasses, 1);
|
||||
}
|
||||
@ -2155,7 +2208,7 @@ vm_object_coalesce(vm_object_t prev_object, vm_ooffset_t prev_offset,
|
||||
|
||||
VM_OBJECT_WLOCK(prev_object);
|
||||
/*
|
||||
* Try to collapse the object first
|
||||
* Try to collapse the object first.
|
||||
*/
|
||||
vm_object_collapse(prev_object);
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user