Merge ^/head r356848 through r356919.

This commit is contained in:
Dimitry Andric 2020-01-20 17:55:51 +00:00
commit 53d2936cd3
112 changed files with 3408 additions and 1247 deletions

View File

@ -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

View File

@ -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} ; \

View File

@ -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);

View File

@ -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) {

View File

@ -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"

View File

@ -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

View File

@ -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));

View File

@ -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

View File

@ -123,6 +123,10 @@ FBSD_1.5 {
set_constraint_handler_s;
};
FBSD_1.6 {
qsort_s;
};
FBSDprivate_1.0 {
__system;
_system;

View File

@ -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.

View File

@ -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
}

View 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"

View File

@ -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

View 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());
}

View 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());
}

View File

@ -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

View File

@ -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 ,

View File

@ -112,6 +112,7 @@ bcr -> bhd
bcr -> sevan
bcr -> dexter
bcr -> sg
bcr -> carlavilla
blackend -> ale

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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"

View File

@ -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}},
};

View File

@ -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 = {

View File

@ -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}},
};

View File

@ -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}},

View File

@ -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}},

View File

@ -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}},

View File

@ -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 = {

View File

@ -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 = {

View File

@ -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 = {

View File

@ -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 {

View File

@ -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),

View File

@ -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 = {

View File

@ -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 = {

View File

@ -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 = {

View File

@ -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 = {

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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
View 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);

View File

@ -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"

View File

@ -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

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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

View File

@ -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
*/

View File

@ -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
View 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}

View File

@ -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:

View File

@ -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

View File

@ -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
};

View File

@ -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

View File

@ -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);
}

View File

@ -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 *

View File

@ -60,6 +60,15 @@
status = "okay";
};
&qspi0 {
status = "okay";
flash0 {
compatible = "st,m25p", "s25fl128";
spi-chipselect = <0>;
};
};
&sdhci0 {
status = "okay";
};

View File

@ -60,6 +60,15 @@
status = "okay";
};
&qspi0 {
status = "okay";
flash0 {
compatible = "st,m25p", "s25fl128";
spi-chipselect = <0>;
};
};
&sdhci0 {
status = "okay";
};

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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"

View File

@ -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"

View File

@ -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) {

View File

@ -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) {

View File

@ -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,

View File

@ -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);

View File

@ -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. */

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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 */

View File

@ -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;

View File

@ -43,6 +43,7 @@
*/
INTERFACE moea64;
SINGLETON;
CODE {
static moea64_pte_replace_t moea64_pte_replace_default;

View File

@ -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 # */

View File

@ -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 */

View 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 */

View 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);
}

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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,

View File

@ -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);
}

View File

@ -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)

View File

@ -46,6 +46,7 @@
*/
INTERFACE mmu;
SINGLETON;
#
# Default implementations of some methods

View File

@ -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.
*/

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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");

View File

@ -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);
}

View File

@ -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)

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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