Merge ^/head r314270 through r314419.
This commit is contained in:
commit
6b8cbe42da
@ -151,6 +151,11 @@ OLD_FILES+=usr/lib/clang/3.9.1/lib/freebsd/libclang_rt.ubsan_standalone_cxx-x86_
|
||||
OLD_DIRS+=usr/lib/clang/3.9.1/lib/freebsd
|
||||
OLD_DIRS+=usr/lib/clang/3.9.1/lib
|
||||
OLD_DIRS+=usr/lib/clang/3.9.1
|
||||
# 20170226: SVR4 compatibility removed
|
||||
.if ${TARGET_ARCH} == "amd64" || ${TARGET_ARCH} == "i386"
|
||||
OLD_FILES+=usr/share/man/man4/streams.4
|
||||
OLD_FILES+=usr/share/man/man4/svr4.4
|
||||
.endif
|
||||
# 20170219: OpenPAM RADULA upgrade removed the libpam tests
|
||||
OLD_FILES+=usr/tests/lib/libpam/Kyuafile
|
||||
OLD_FILES+=usr/tests/lib/libpam/t_openpam_ctype
|
||||
@ -8454,7 +8459,7 @@ OLD_FILES+=usr/share/man/man8/boot_i386.8.gz
|
||||
.endif
|
||||
.if ${TARGET_ARCH} != "aarch64" && ${TARGET} != "arm" && \
|
||||
${TARGET_ARCH} != "powerpc" && ${TARGET_ARCH} != "powerpc64" && \
|
||||
${TARGET_ARCH} != "sparc64"
|
||||
${TARGET_ARCH} != "sparc64" && ${TARGET} != "mips"
|
||||
OLD_FILES+=usr/share/man/man8/ofwdump.8.gz
|
||||
.endif
|
||||
OLD_FILES+=usr/share/man/man8/mount_reiserfs.8.gz
|
||||
|
@ -30,7 +30,7 @@ export PATH=/bin:/sbin:/usr/bin:/usr/sbin
|
||||
unset LD_LIBRARY_PATH
|
||||
|
||||
# generate config.h with krb5 and stash it
|
||||
sh configure $configure_args --with-kerberos5
|
||||
sh configure $configure_args --with-kerberos5=/usr
|
||||
mv config.log config.log.orig
|
||||
mv config.h config.h.orig
|
||||
|
||||
|
@ -319,7 +319,6 @@ add_local_forward(Options *options, const struct Forward *newfwd)
|
||||
#else
|
||||
ipport_reserved = IPPORT_RESERVED;
|
||||
#endif
|
||||
if (newfwd->listen_port < ipport_reserved && original_real_uid != 0)
|
||||
if (newfwd->listen_port < ipport_reserved && original_real_uid != 0 &&
|
||||
newfwd->listen_path == NULL)
|
||||
fatal("Privileged ports can only be forwarded by root.");
|
||||
|
@ -630,7 +630,6 @@ firstboot_sentinel="/firstboot" # Scripts with "firstboot" keyword are run if
|
||||
# Emulation/compatibility services provided by /etc/rc.d/abi
|
||||
sysvipc_enable="NO" # Load System V IPC primitives at startup (or NO).
|
||||
linux_enable="NO" # Linux binary compatibility loaded at startup (or NO).
|
||||
svr4_enable="NO" # SysVR4 emulation loaded at startup (or NO).
|
||||
clear_tmp_enable="NO" # Clear /tmp at startup.
|
||||
clear_tmp_X="YES" # Clear and recreate X11-related directories in /tmp
|
||||
ldconfig_insecure="NO" # Set to YES to disable ldconfig security checks
|
||||
|
@ -312,10 +312,10 @@ notify 10 {
|
||||
};
|
||||
|
||||
# This example works around a memory leak in PostgreSQL, restarting
|
||||
# it when the "user:pgsql:swap:devctl=1G" rctl(8) rule gets triggered.
|
||||
# it when the "user:postgres:swap:devctl=1G" rctl(8) rule gets triggered.
|
||||
notify 0 {
|
||||
match "system" "RCTL";
|
||||
match "rule" "user:70:swap:.*";
|
||||
match "rule" "user:770:swap:.*";
|
||||
action "/usr/local/etc/rc.d/postgresql restart";
|
||||
};
|
||||
|
||||
|
@ -43,25 +43,18 @@ linux_start()
|
||||
fi
|
||||
}
|
||||
|
||||
svr4_start()
|
||||
{
|
||||
echo -n ' svr4'
|
||||
load_kld -m svr4elf svr4
|
||||
}
|
||||
|
||||
abi_start()
|
||||
{
|
||||
local _echostop
|
||||
|
||||
_echostop=
|
||||
if checkyesno sysvipc_enable || checkyesno linux_enable || checkyesno svr4_enable; then
|
||||
if checkyesno sysvipc_enable || checkyesno linux_enable; then
|
||||
echo -n 'Additional ABI support:'
|
||||
_echostop=yes
|
||||
fi
|
||||
|
||||
checkyesno sysvipc_enable && sysv_start
|
||||
checkyesno linux_enable && linux_start
|
||||
checkyesno svr4_enable && svr4_start
|
||||
|
||||
[ -n "${_echostop}" ] && echo '.'
|
||||
}
|
||||
|
@ -175,6 +175,7 @@ typedef struct {
|
||||
#define T_ATMA ns_t_atma
|
||||
#define T_NAPTR ns_t_naptr
|
||||
#define T_A6 ns_t_a6
|
||||
#define T_DNAME ns_t_dname
|
||||
#define T_OPT ns_t_opt
|
||||
#define T_TSIG ns_t_tsig
|
||||
#define T_IXFR ns_t_ixfr
|
||||
|
@ -319,7 +319,7 @@ The additional word delimiters
|
||||
and
|
||||
.Ql \e>
|
||||
are provided to ease compatibility with traditional
|
||||
.Xr svr4 4
|
||||
SVR4
|
||||
systems but are not portable and should be avoided.
|
||||
.Pp
|
||||
In the event that an RE could match more than one substring of a given
|
||||
|
@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include "namespace.h"
|
||||
#include <sys/capsicum.h>
|
||||
#include <sys/elf.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
@ -124,6 +125,7 @@ __vdso_init_hpet(uint32_t u)
|
||||
static const char devprefix[] = "/dev/hpet";
|
||||
char devname[64], *c, *c1, t;
|
||||
volatile char *new_map, *old_map;
|
||||
unsigned int mode;
|
||||
uint32_t u1;
|
||||
int fd;
|
||||
|
||||
@ -144,18 +146,25 @@ __vdso_init_hpet(uint32_t u)
|
||||
if (old_map != NULL)
|
||||
return;
|
||||
|
||||
if (cap_getmode(&mode) == 0 && mode != 0)
|
||||
goto fail;
|
||||
|
||||
fd = _open(devname, O_RDONLY);
|
||||
if (fd == -1) {
|
||||
atomic_cmpset_rel_ptr((volatile uintptr_t *)&hpet_dev_map[u],
|
||||
(uintptr_t)old_map, (uintptr_t)MAP_FAILED);
|
||||
return;
|
||||
}
|
||||
if (fd == -1)
|
||||
goto fail;
|
||||
|
||||
new_map = mmap(NULL, PAGE_SIZE, PROT_READ, MAP_SHARED, fd, 0);
|
||||
_close(fd);
|
||||
if (atomic_cmpset_rel_ptr((volatile uintptr_t *)&hpet_dev_map[u],
|
||||
(uintptr_t)old_map, (uintptr_t)new_map) == 0 &&
|
||||
new_map != MAP_FAILED)
|
||||
munmap((void *)new_map, PAGE_SIZE);
|
||||
munmap((void *)new_map, PAGE_SIZE);
|
||||
|
||||
return;
|
||||
fail:
|
||||
/* Prevent the caller from re-entering. */
|
||||
atomic_cmpset_rel_ptr((volatile uintptr_t *)&hpet_dev_map[u],
|
||||
(uintptr_t)old_map, (uintptr_t)MAP_FAILED);
|
||||
}
|
||||
|
||||
#ifdef WANT_HYPERV
|
||||
@ -174,16 +183,22 @@ static void
|
||||
__vdso_init_hyperv_tsc(void)
|
||||
{
|
||||
int fd;
|
||||
unsigned int mode;
|
||||
|
||||
if (cap_getmode(&mode) == 0 && mode != 0)
|
||||
goto fail;
|
||||
|
||||
fd = _open(HYPERV_REFTSC_DEVPATH, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
/* Prevent the caller from re-entering. */
|
||||
hyperv_ref_tsc = MAP_FAILED;
|
||||
return;
|
||||
}
|
||||
if (fd < 0)
|
||||
goto fail;
|
||||
hyperv_ref_tsc = mmap(NULL, sizeof(*hyperv_ref_tsc), PROT_READ,
|
||||
MAP_SHARED, fd, 0);
|
||||
_close(fd);
|
||||
|
||||
return;
|
||||
fail:
|
||||
/* Prevent the caller from re-entering. */
|
||||
hyperv_ref_tsc = MAP_FAILED;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -153,7 +153,7 @@ fetch_syserr(void)
|
||||
case EHOSTDOWN:
|
||||
fetchLastErrCode = FETCH_DOWN;
|
||||
break;
|
||||
default:
|
||||
default:
|
||||
fetchLastErrCode = FETCH_UNKNOWN;
|
||||
}
|
||||
snprintf(fetchLastErrString, MAXERRSTRING, "%s", strerror(errno));
|
||||
@ -371,7 +371,7 @@ fetch_connect(const char *host, int port, int af, int verbose)
|
||||
}
|
||||
if (err != 0) {
|
||||
if (verbose)
|
||||
fetch_info("failed to connect to %s:%s", host, port);
|
||||
fetch_info("failed to connect to %s:%d", host, port);
|
||||
goto syserr;
|
||||
}
|
||||
|
||||
|
@ -244,10 +244,10 @@ rss_config_get(void)
|
||||
return (rc);
|
||||
|
||||
error:
|
||||
if ((rc != NULL) && rc->rss_bucket_map)
|
||||
if (rc != NULL) {
|
||||
free(rc->rss_bucket_map);
|
||||
if (rc != NULL)
|
||||
free(rc);
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
@ -1146,6 +1146,18 @@ variables can be used to control the behavior of the
|
||||
GEOM class.
|
||||
The default value is shown next to each variable.
|
||||
.Bl -tag -width indent
|
||||
.It Va kern.geom.part.auto_resize: No 1
|
||||
This variable controls automatic resize behavior of
|
||||
.Nm
|
||||
GEOM class.
|
||||
When this variable is enable and new size of provider is detected, the schema
|
||||
metadata is resized but all changes are not saved to disk, until
|
||||
.Cm gpart commit
|
||||
is run to confirm changes.
|
||||
This behavior is also reported with diagnostic message:
|
||||
.Sy "GEOM_PART: (provider) was automatically resized."
|
||||
.Sy "Use `gpart commit (provider)` to save changes or `gpart undo (provider)`"
|
||||
.Sy "to revert them."
|
||||
.It Va kern.geom.part.check_integrity : No 1
|
||||
This variable controls the behaviour of metadata integrity checks.
|
||||
When integrity checks are enabled, the
|
||||
|
@ -29,7 +29,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd February 6, 2017
|
||||
.Dd February 27, 2017
|
||||
.Dt SETKEY 8
|
||||
.Os
|
||||
.\"
|
||||
@ -593,12 +593,11 @@ keyed-md5 128 ah: 96bit ICV (no document)
|
||||
keyed-sha1 160 ah: 96bit ICV (no document)
|
||||
160 ah-old: 128bit ICV (no document)
|
||||
null 0 to 2048 for debugging
|
||||
hmac-sha2-256 256 ah: 96bit ICV
|
||||
(draft-ietf-ipsec-ciph-sha-256-00)
|
||||
hmac-sha2-256 256 ah: 128bit ICV (RFC4868)
|
||||
256 ah-old: 128bit ICV (no document)
|
||||
hmac-sha2-384 384 ah: 96bit ICV (no document)
|
||||
hmac-sha2-384 384 ah: 192bit ICV (RFC4868)
|
||||
384 ah-old: 128bit ICV (no document)
|
||||
hmac-sha2-512 512 ah: 96bit ICV (no document)
|
||||
hmac-sha2-512 512 ah: 256bit ICV (RFC4868)
|
||||
512 ah-old: 128bit ICV (no document)
|
||||
hmac-ripemd160 160 ah: 96bit ICV (RFC2857)
|
||||
ah-old: 128bit ICV (no document)
|
||||
|
@ -25,8 +25,6 @@ MAN= aic.4 \
|
||||
pnpbios.4 \
|
||||
sbni.4 \
|
||||
smapi.4 \
|
||||
streams.4 \
|
||||
svr4.4 \
|
||||
vpd.4 \
|
||||
vx.4
|
||||
|
||||
|
@ -1,85 +0,0 @@
|
||||
.\" Copyright (c) 2000 Mark Newton
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd March 17, 2008
|
||||
.Dt STREAMS 4 i386
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm streams
|
||||
.Nd System V STREAMS networking ABI support
|
||||
.Sh SYNOPSIS
|
||||
To compile support for this ABI into the kernel,
|
||||
place the following line in your
|
||||
kernel configuration file:
|
||||
.Bd -ragged -offset indent
|
||||
.Cd "device streams"
|
||||
.Ed
|
||||
.Pp
|
||||
Alternatively, to load the ABI as a
|
||||
module at boot time, place the following line in
|
||||
.Xr loader.conf 5 :
|
||||
.Bd -literal -offset indent
|
||||
streams_load="YES"
|
||||
.Ed
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
module provides limited
|
||||
System V Release 4 STREAMS interprocess communication ABI
|
||||
(application binary interface) compatibility
|
||||
for userland applications.
|
||||
.Pp
|
||||
Internally,
|
||||
.Nm
|
||||
provides STREAMS handles by using socket creation kernel routines, and
|
||||
adding state-tracking information to the socket to permit manipulation
|
||||
by STREAMS emulation code in
|
||||
.Xr svr4 4 .
|
||||
Hence, opening a stream device produces a result similar to what would be
|
||||
obtained by calling
|
||||
.Xr socket 2 .
|
||||
.Pp
|
||||
Applications should never use this interface directly: STREAMS
|
||||
emulation is only provided as a service to support ABI requirements in
|
||||
the SVR4 environment which
|
||||
.Xr svr4 4
|
||||
needs to present to client binaries.
|
||||
.Sh SEE ALSO
|
||||
.Xr svr4 4
|
||||
.Sh HISTORY
|
||||
System V Release 4 ABI support first appeared in
|
||||
.Fx 4.0 .
|
||||
The ABI was ported from an equivalent facility present in
|
||||
.Nx 1.3
|
||||
written by Christos Zoulas.
|
||||
.Sh BUGS
|
||||
This whole interface is a crude hack to produce STREAMS semantics
|
||||
through emulation over sockets.
|
||||
.Pp
|
||||
Programmers who hope to be able to use this interface to provide
|
||||
SVR4 STREAMS services to
|
||||
.Bx
|
||||
applications will be sorely disappointed.
|
@ -1,225 +0,0 @@
|
||||
.\" Copyright (c) 2000 Mark Newton
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd March 17, 2008
|
||||
.Dt SVR4 4 i386
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm svr4
|
||||
.Nd System V Release 4 ABI support
|
||||
.Sh SYNOPSIS
|
||||
To compile support for this ABI into the kernel,
|
||||
place the following line in your
|
||||
kernel configuration file:
|
||||
.Bd -ragged -offset indent
|
||||
.Cd "options COMPAT_SVR4"
|
||||
.Ed
|
||||
.Pp
|
||||
Alternatively, to load the ABI as a
|
||||
module at boot time, place the following line in
|
||||
.Xr loader.conf 5 :
|
||||
.Bd -literal -offset indent
|
||||
svr4_load="YES"
|
||||
.Ed
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
module provides limited
|
||||
System V Release 4 ABI (application binary interface) compatibility
|
||||
for userland applications.
|
||||
The module provides the following significant facilities:
|
||||
.Bl -bullet
|
||||
.It
|
||||
An image activator
|
||||
for correctly branded
|
||||
.Xr elf 5
|
||||
executable images
|
||||
.It
|
||||
Special signal handling for activated images
|
||||
.It
|
||||
SVR4 to native system call translation
|
||||
.It
|
||||
STREAMS network API emulation (via the
|
||||
.Xr streams 4
|
||||
loadable module, or by means of
|
||||
.Dl device streams
|
||||
in a kernel configuration file)
|
||||
.It
|
||||
Mappings between
|
||||
.Fx
|
||||
and SVR4
|
||||
.Xr ioctl 2
|
||||
calls, or, where no such mappings exist, reverse-engineered implementations
|
||||
of the SVR4 calls.
|
||||
.El
|
||||
.Pp
|
||||
It is important to note that the SVR4 ABI support
|
||||
it not provided through an emulator.
|
||||
Rather, a true (albeit limited) "clean room" reverse-engineered ABI
|
||||
implementation is provided.
|
||||
.Sh LIMITATIONS
|
||||
Because the provided ABI has been developed in ignorance of actual SVR4
|
||||
source code, there are bound to be unforeseen interactions between SVR4
|
||||
client applications and the emulated ABI which cause applications to
|
||||
malfunction.
|
||||
.Pp
|
||||
Additionally, some SVR4 operating systems do not adhere to the SVR4
|
||||
ELF standard.
|
||||
In particular, Solaris does not set the ELF interpreter field in the
|
||||
ELF header to a value which would allow the kernel to correctly
|
||||
identify a client executable as an SVR4 application.
|
||||
Thus, in certain instances it is necessary to use the
|
||||
.Xr brandelf 1
|
||||
utility to explicitly brand the executable, or to set the
|
||||
kern.fallback_elf_brand
|
||||
.Xr sysctl 8
|
||||
variable to define a "default" ABI for unbranded executables.
|
||||
Value ELFOSABI_SOLARIS represents Solaris; ELFOSABI_SYSV represents other
|
||||
SysVR4 operating systems.
|
||||
See
|
||||
.In sys/elf_common.h
|
||||
for ELFOSABI branding definitions, and
|
||||
.Xr brandelf 1
|
||||
for information on branding executables.
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
module can be linked into the kernel statically with the
|
||||
.Dv COMPAT_SVR4
|
||||
kernel configuration option
|
||||
or loaded as required.
|
||||
The following command will load the module
|
||||
if it is neither linked into the kernel
|
||||
nor already loaded as a module:
|
||||
.Bd -literal -offset indent
|
||||
if ! kldstat -v | grep -E 'svr4elf' > /dev/null; then
|
||||
kldload svr4 > /dev/null 2>&1
|
||||
fi
|
||||
.Ed
|
||||
.Pp
|
||||
The kernel
|
||||
will check for the presence of the
|
||||
.Xr streams 4
|
||||
module, and load it if necessary.
|
||||
.Pp
|
||||
Note that dynamically linked SVR4 executables
|
||||
will require a suitable environment in
|
||||
.Pa /compat/svr4 .
|
||||
.Pp
|
||||
For information on loading the
|
||||
.Nm
|
||||
kernel loadable module automatically on system startup,
|
||||
see
|
||||
.Xr rc.conf 5 .
|
||||
This information applies
|
||||
regardless of whether the
|
||||
.Nm
|
||||
module is statically linked into the kernel
|
||||
or loaded as a module.
|
||||
.Pp
|
||||
STREAMS emulation is limited but (largely) functional.
|
||||
Assuming the
|
||||
.Xr streams 4
|
||||
module is loaded, a STREAMS handle can be obtained by opening one of the
|
||||
relevant files in
|
||||
.Pa /dev
|
||||
or
|
||||
.Pa /compat/svr4/dev .
|
||||
Internally, the
|
||||
.Xr streams 4
|
||||
driver produces a socket descriptor and
|
||||
.Dq tags
|
||||
it with additional STREAMS
|
||||
state information before returning it to the client application.
|
||||
The
|
||||
.Nm
|
||||
environment uses the additional state information to recognize and
|
||||
manipulate emulated STREAMS handles when STREAMS-specific
|
||||
.Xr ioctl 2
|
||||
calls are executed.
|
||||
.Pp
|
||||
The subset of STREAMS functionality which is provided is small, probably
|
||||
little more than what is required to enable programs on the Solaris CD
|
||||
sets to run.
|
||||
.Sh FILES
|
||||
.Bl -tag -width /sys/compat/svr4/syscalls.master -compact
|
||||
.It Pa /compat/svr4
|
||||
minimal SVR4 run-time environment
|
||||
.It Pa /sys/compat/svr4/syscalls.master
|
||||
mappings between SVR4 syscalls and
|
||||
.Nm
|
||||
module entrypoints.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr brandelf 1 ,
|
||||
.Xr streams 4 ,
|
||||
.Xr elf 5
|
||||
.Sh HISTORY
|
||||
System V Release 4 ABI support first appeared in
|
||||
.Fx 4.0 .
|
||||
The ABI was ported from an equivalent facility present in
|
||||
.Nx 1.3
|
||||
written by Christos Zoulas.
|
||||
.Sh BUGS
|
||||
Emulation of signal handlers is buggy.
|
||||
.Pp
|
||||
Emulated connectionless STREAMS fail to receive data from the network in
|
||||
some circumstances (but succeed in others -- probably due to particular
|
||||
ways of initializing them which the
|
||||
.Xr streams 4
|
||||
module is mishandling, and interaction between STREAMS and
|
||||
.Xr poll 2 ) .
|
||||
Connection-oriented STREAMS appear to be functional.
|
||||
.Pp
|
||||
Ironically, this SVR4 emulator does not (yet) support SVR4 semaphores or
|
||||
shared memory.
|
||||
.Pp
|
||||
.Xr ports 7
|
||||
to automatically create the
|
||||
.Pa /compat/svr4
|
||||
environment do not exist.
|
||||
.Xr tar 1
|
||||
archives containing pre-populated trees can be obtained from
|
||||
.Pa http://people.FreeBSD.org/~newton/freebsd-svr4/ .
|
||||
.Pp
|
||||
Extensive testing has only really been carried out with Solaris 2.x binaries,
|
||||
with anecdotal reports of limited success coming from testers with
|
||||
early-revision SCO media.
|
||||
In theory, the basic SVR4 ABI should be constant
|
||||
across the set of vendors who produce SVR4 operating systems, but in
|
||||
practice that is probably not the case.
|
||||
If necessary, future work can
|
||||
either implement additional
|
||||
.Xr kld 4
|
||||
modules which produce functionality which contains OS-dependent
|
||||
departures from the behaviour which has been implemented in this
|
||||
ABI implementation.
|
||||
Alternatively,
|
||||
.Xr sysctl 8
|
||||
variables could set the
|
||||
.Dq personality
|
||||
the environment should present to
|
||||
client applications.
|
@ -24,7 +24,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd December 10, 2016
|
||||
.Dd February 26, 2017
|
||||
.Dt RC.CONF 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -3631,11 +3631,6 @@ Set to
|
||||
.Dq Li YES
|
||||
to enable Linux/ELF binary emulation at system initial
|
||||
boot time.
|
||||
.It Va svr4_enable
|
||||
.Pq Vt bool
|
||||
If set to
|
||||
.Dq Li YES ,
|
||||
enable SysVR4 emulation at boot time.
|
||||
.It Va sysvipc_enable
|
||||
.Pq Vt bool
|
||||
If set to
|
||||
|
@ -57,7 +57,8 @@
|
||||
.Nm sbuf_delete ,
|
||||
.Nm sbuf_start_section ,
|
||||
.Nm sbuf_end_section ,
|
||||
.Nm sbuf_hexdump
|
||||
.Nm sbuf_hexdump ,
|
||||
.Nm sbuf_putbuf
|
||||
.Nd safe string composition
|
||||
.Sh SYNOPSIS
|
||||
.In sys/types.h
|
||||
@ -124,6 +125,8 @@
|
||||
.Fa "const char *hdr"
|
||||
.Fa "int flags"
|
||||
.Fc
|
||||
.Ft void
|
||||
.Fn sbuf_putbuf "struct sbuf *s"
|
||||
.In sys/sysctl.h
|
||||
.Ft struct sbuf *
|
||||
.Fn sbuf_new_for_sysctl "struct sbuf *s" "char *buf" "int length" "struct sysctl_req *req"
|
||||
@ -472,6 +475,12 @@ representation of the bytes if possible.
|
||||
See the
|
||||
.Xr hexdump 3
|
||||
man page for more details on the interface.
|
||||
.Pp
|
||||
The
|
||||
.Fn sbuf_putbuf
|
||||
function printfs the sbuf to stdout if in userland, and to the console
|
||||
and log if in the kernel.
|
||||
It does not drain the buffer or update any pointers.
|
||||
.Sh NOTES
|
||||
If an operation caused an
|
||||
.Fa sbuf
|
||||
|
@ -613,6 +613,8 @@ static vm_page_t pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va,
|
||||
vm_page_t m, vm_prot_t prot, vm_page_t mpte, struct rwlock **lockp);
|
||||
static void pmap_fill_ptp(pt_entry_t *firstpte, pt_entry_t newpte);
|
||||
static int pmap_insert_pt_page(pmap_t pmap, vm_page_t mpte);
|
||||
static void pmap_invalidate_pde_page(pmap_t pmap, vm_offset_t va,
|
||||
pd_entry_t pde);
|
||||
static void pmap_kenter_attr(vm_offset_t va, vm_paddr_t pa, int mode);
|
||||
static void pmap_pde_attr(pd_entry_t *pde, int cache_bits, int mask);
|
||||
static void pmap_promote_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t va,
|
||||
@ -1838,6 +1840,27 @@ pmap_update_pde(pmap_t pmap, vm_offset_t va, pd_entry_t *pde, pd_entry_t newpde)
|
||||
}
|
||||
#endif /* !SMP */
|
||||
|
||||
static void
|
||||
pmap_invalidate_pde_page(pmap_t pmap, vm_offset_t va, pd_entry_t pde)
|
||||
{
|
||||
|
||||
/*
|
||||
* When the PDE has PG_PROMOTED set, the 2MB page mapping was created
|
||||
* by a promotion that did not invalidate the 512 4KB page mappings
|
||||
* that might exist in the TLB. Consequently, at this point, the TLB
|
||||
* may hold both 4KB and 2MB page mappings for the address range [va,
|
||||
* va + NBPDR). Therefore, the entire range must be invalidated here.
|
||||
* In contrast, when PG_PROMOTED is clear, the TLB will not hold any
|
||||
* 4KB page mappings for the address range [va, va + NBPDR), and so a
|
||||
* single INVLPG suffices to invalidate the 2MB page mapping from the
|
||||
* TLB.
|
||||
*/
|
||||
if ((pde & PG_PROMOTED) != 0)
|
||||
pmap_invalidate_range(pmap, va, va + NBPDR - 1);
|
||||
else
|
||||
pmap_invalidate_page(pmap, va);
|
||||
}
|
||||
|
||||
#define PMAP_CLFLUSH_THRESHOLD (2 * 1024 * 1024)
|
||||
|
||||
void
|
||||
@ -3472,7 +3495,8 @@ pmap_demote_pde_locked(pmap_t pmap, pd_entry_t *pde, vm_offset_t va,
|
||||
SLIST_INIT(&free);
|
||||
sva = trunc_2mpage(va);
|
||||
pmap_remove_pde(pmap, pde, sva, &free, lockp);
|
||||
pmap_invalidate_range(pmap, sva, sva + NBPDR - 1);
|
||||
if ((oldpde & PG_G) == 0)
|
||||
pmap_invalidate_pde_page(pmap, sva, oldpde);
|
||||
pmap_free_zero_pages(&free);
|
||||
CTR2(KTR_PMAP, "pmap_demote_pde: failure for va %#lx"
|
||||
" in pmap %p", va, pmap);
|
||||
@ -3612,25 +3636,8 @@ pmap_remove_pde(pmap_t pmap, pd_entry_t *pdq, vm_offset_t sva,
|
||||
oldpde = pte_load_clear(pdq);
|
||||
if (oldpde & PG_W)
|
||||
pmap->pm_stats.wired_count -= NBPDR / PAGE_SIZE;
|
||||
|
||||
/*
|
||||
* When workaround_erratum383 is false, a promotion to a 2M
|
||||
* page mapping does not invalidate the 512 4K page mappings
|
||||
* from the TLB. Consequently, at this point, the TLB may
|
||||
* hold both 4K and 2M page mappings. Therefore, the entire
|
||||
* range of addresses must be invalidated here. In contrast,
|
||||
* when workaround_erratum383 is true, a promotion does
|
||||
* invalidate the 512 4K page mappings, and so a single INVLPG
|
||||
* suffices to invalidate the 2M page mapping.
|
||||
*/
|
||||
if ((oldpde & PG_G) != 0) {
|
||||
if (workaround_erratum383)
|
||||
pmap_invalidate_page(kernel_pmap, sva);
|
||||
else
|
||||
pmap_invalidate_range(kernel_pmap, sva,
|
||||
sva + NBPDR - 1);
|
||||
}
|
||||
|
||||
if ((oldpde & PG_G) != 0)
|
||||
pmap_invalidate_pde_page(kernel_pmap, sva, oldpde);
|
||||
pmap_resident_count_dec(pmap, NBPDR / PAGE_SIZE);
|
||||
if (oldpde & PG_MANAGED) {
|
||||
CHANGE_PV_LIST_LOCK_TO_PHYS(lockp, oldpde & PG_PS_FRAME);
|
||||
@ -4010,16 +4017,16 @@ retry:
|
||||
if ((prot & VM_PROT_EXECUTE) == 0)
|
||||
newpde |= pg_nx;
|
||||
if (newpde != oldpde) {
|
||||
if (!atomic_cmpset_long(pde, oldpde, newpde))
|
||||
/*
|
||||
* As an optimization to future operations on this PDE, clear
|
||||
* PG_PROMOTED. The impending invalidation will remove any
|
||||
* lingering 4KB page mappings from the TLB.
|
||||
*/
|
||||
if (!atomic_cmpset_long(pde, oldpde, newpde & ~PG_PROMOTED))
|
||||
goto retry;
|
||||
if (oldpde & PG_G) {
|
||||
/* See pmap_remove_pde() for explanation. */
|
||||
if (workaround_erratum383)
|
||||
pmap_invalidate_page(kernel_pmap, sva);
|
||||
else
|
||||
pmap_invalidate_range(kernel_pmap, sva,
|
||||
sva + NBPDR - 1);
|
||||
} else
|
||||
if ((oldpde & PG_G) != 0)
|
||||
pmap_invalidate_pde_page(kernel_pmap, sva, oldpde);
|
||||
else
|
||||
anychanged = TRUE;
|
||||
}
|
||||
return (anychanged);
|
||||
@ -4272,7 +4279,7 @@ setpte:
|
||||
if (workaround_erratum383)
|
||||
pmap_update_pde(pmap, va, pde, PG_PS | newpde);
|
||||
else
|
||||
pde_store(pde, PG_PS | newpde);
|
||||
pde_store(pde, PG_PROMOTED | PG_PS | newpde);
|
||||
|
||||
atomic_add_long(&pmap_pde_promotions, 1);
|
||||
CTR2(KTR_PMAP, "pmap_promote_pde: success for va %#lx"
|
||||
@ -4585,7 +4592,8 @@ pmap_enter_pde(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
|
||||
pmap_resident_count_inc(pmap, NBPDR / PAGE_SIZE);
|
||||
|
||||
/*
|
||||
* Map the superpage.
|
||||
* Map the superpage. (This is not a promoted mapping; there will not
|
||||
* be any lingering 4KB page mappings in the TLB.)
|
||||
*/
|
||||
pde_store(pde, newpde);
|
||||
|
||||
|
@ -633,27 +633,6 @@ options LINPROCFS
|
||||
# and PSEUDOFS)
|
||||
options LINSYSFS
|
||||
|
||||
#
|
||||
# SysVR4 ABI emulation
|
||||
#
|
||||
# The svr4 ABI emulator can be statically compiled into the kernel or loaded as
|
||||
# a KLD module.
|
||||
# The STREAMS network emulation code can also be compiled statically or as a
|
||||
# module. If loaded as a module, it must be loaded before the svr4 module
|
||||
# (the /usr/sbin/svr4 script does this for you). If compiling statically,
|
||||
# the `streams' device must be configured into any kernel which also
|
||||
# specifies COMPAT_SVR4. It is possible to have a statically-configured
|
||||
# STREAMS device and a dynamically loadable svr4 emulator; the /usr/sbin/svr4
|
||||
# script understands that it doesn't need to load the `streams' module under
|
||||
# those circumstances.
|
||||
# Caveat: At this time, `options KTRACE' is required for the svr4 emulator
|
||||
# (whether static or dynamic).
|
||||
#
|
||||
#XXX#options COMPAT_SVR4 # build emulator statically
|
||||
#XXX#options DEBUG_SVR4 # enable verbose debugging
|
||||
#XXX#device streams # STREAMS network driver (required for svr4).
|
||||
|
||||
|
||||
#####################################################################
|
||||
# VM OPTIONS
|
||||
|
||||
|
@ -109,6 +109,7 @@
|
||||
#define PG_MANAGED X86_PG_AVAIL2
|
||||
#define EPT_PG_EMUL_V X86_PG_AVAIL(52)
|
||||
#define EPT_PG_EMUL_RW X86_PG_AVAIL(53)
|
||||
#define PG_PROMOTED X86_PG_AVAIL(54) /* PDE only */
|
||||
#define PG_FRAME (0x000ffffffffff000ul)
|
||||
#define PG_PS_FRAME (0x000fffffffe00000ul)
|
||||
|
||||
|
@ -103,10 +103,6 @@ DUMMY(vmsplice);
|
||||
DUMMY(move_pages);
|
||||
/* linux 2.6.22: */
|
||||
DUMMY(signalfd);
|
||||
DUMMY(timerfd_create);
|
||||
/* linux 2.6.25: */
|
||||
DUMMY(timerfd_settime);
|
||||
DUMMY(timerfd_gettime);
|
||||
/* linux 2.6.27: */
|
||||
DUMMY(signalfd4);
|
||||
DUMMY(inotify_init1);
|
||||
|
@ -995,12 +995,14 @@ struct linux_epoll_pwait_args {
|
||||
char maxevents_l_[PADL_(l_int)]; l_int maxevents; char maxevents_r_[PADR_(l_int)];
|
||||
char timeout_l_[PADL_(l_int)]; l_int timeout; char timeout_r_[PADR_(l_int)];
|
||||
char mask_l_[PADL_(l_sigset_t *)]; l_sigset_t * mask; char mask_r_[PADR_(l_sigset_t *)];
|
||||
char sigsetsize_l_[PADL_(l_size_t)]; l_size_t sigsetsize; char sigsetsize_r_[PADR_(l_size_t)];
|
||||
};
|
||||
struct linux_signalfd_args {
|
||||
register_t dummy;
|
||||
};
|
||||
struct linux_timerfd_create_args {
|
||||
register_t dummy;
|
||||
char clockid_l_[PADL_(l_int)]; l_int clockid; char clockid_r_[PADR_(l_int)];
|
||||
char flags_l_[PADL_(l_int)]; l_int flags; char flags_r_[PADR_(l_int)];
|
||||
};
|
||||
struct linux_eventfd_args {
|
||||
char initval_l_[PADL_(l_uint)]; l_uint initval; char initval_r_[PADR_(l_uint)];
|
||||
@ -1012,10 +1014,14 @@ struct linux_fallocate_args {
|
||||
char len_l_[PADL_(l_loff_t)]; l_loff_t len; char len_r_[PADR_(l_loff_t)];
|
||||
};
|
||||
struct linux_timerfd_settime_args {
|
||||
register_t dummy;
|
||||
char fd_l_[PADL_(l_int)]; l_int fd; char fd_r_[PADR_(l_int)];
|
||||
char flags_l_[PADL_(l_int)]; l_int flags; char flags_r_[PADR_(l_int)];
|
||||
char new_value_l_[PADL_(const struct l_itimerspec *)]; const struct l_itimerspec * new_value; char new_value_r_[PADR_(const struct l_itimerspec *)];
|
||||
char old_value_l_[PADL_(struct l_itimerspec *)]; struct l_itimerspec * old_value; char old_value_r_[PADR_(struct l_itimerspec *)];
|
||||
};
|
||||
struct linux_timerfd_gettime_args {
|
||||
register_t dummy;
|
||||
char fd_l_[PADL_(l_int)]; l_int fd; char fd_r_[PADR_(l_int)];
|
||||
char old_value_l_[PADL_(struct l_itimerspec *)]; struct l_itimerspec * old_value; char old_value_r_[PADR_(struct l_itimerspec *)];
|
||||
};
|
||||
struct linux_accept4_args {
|
||||
char s_l_[PADL_(l_int)]; l_int s; char s_r_[PADR_(l_int)];
|
||||
|
@ -300,11 +300,11 @@ struct sysent linux_sysent[] = {
|
||||
{ AS(linux_utimensat_args), (sy_call_t *)linux_utimensat, AUE_FUTIMESAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 280 = linux_utimensat */
|
||||
{ AS(linux_epoll_pwait_args), (sy_call_t *)linux_epoll_pwait, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 281 = linux_epoll_pwait */
|
||||
{ 0, (sy_call_t *)linux_signalfd, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 282 = linux_signalfd */
|
||||
{ 0, (sy_call_t *)linux_timerfd_create, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 283 = linux_timerfd_create */
|
||||
{ AS(linux_timerfd_create_args), (sy_call_t *)linux_timerfd_create, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 283 = linux_timerfd_create */
|
||||
{ AS(linux_eventfd_args), (sy_call_t *)linux_eventfd, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 284 = linux_eventfd */
|
||||
{ AS(linux_fallocate_args), (sy_call_t *)linux_fallocate, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 285 = linux_fallocate */
|
||||
{ 0, (sy_call_t *)linux_timerfd_settime, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 286 = linux_timerfd_settime */
|
||||
{ 0, (sy_call_t *)linux_timerfd_gettime, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 287 = linux_timerfd_gettime */
|
||||
{ AS(linux_timerfd_settime_args), (sy_call_t *)linux_timerfd_settime, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 286 = linux_timerfd_settime */
|
||||
{ AS(linux_timerfd_gettime_args), (sy_call_t *)linux_timerfd_gettime, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 287 = linux_timerfd_gettime */
|
||||
{ AS(linux_accept4_args), (sy_call_t *)linux_accept4, AUE_ACCEPT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 288 = linux_accept4 */
|
||||
{ 0, (sy_call_t *)linux_signalfd4, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 289 = linux_signalfd4 */
|
||||
{ AS(linux_eventfd2_args), (sy_call_t *)linux_eventfd2, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 290 = linux_eventfd2 */
|
||||
|
@ -2068,7 +2068,8 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
|
||||
iarg[2] = p->maxevents; /* l_int */
|
||||
iarg[3] = p->timeout; /* l_int */
|
||||
uarg[4] = (intptr_t) p->mask; /* l_sigset_t * */
|
||||
*n_args = 5;
|
||||
iarg[5] = p->sigsetsize; /* l_size_t */
|
||||
*n_args = 6;
|
||||
break;
|
||||
}
|
||||
/* linux_signalfd */
|
||||
@ -2078,7 +2079,10 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
|
||||
}
|
||||
/* linux_timerfd_create */
|
||||
case 283: {
|
||||
*n_args = 0;
|
||||
struct linux_timerfd_create_args *p = params;
|
||||
iarg[0] = p->clockid; /* l_int */
|
||||
iarg[1] = p->flags; /* l_int */
|
||||
*n_args = 2;
|
||||
break;
|
||||
}
|
||||
/* linux_eventfd */
|
||||
@ -2100,12 +2104,20 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
|
||||
}
|
||||
/* linux_timerfd_settime */
|
||||
case 286: {
|
||||
*n_args = 0;
|
||||
struct linux_timerfd_settime_args *p = params;
|
||||
iarg[0] = p->fd; /* l_int */
|
||||
iarg[1] = p->flags; /* l_int */
|
||||
uarg[2] = (intptr_t) p->new_value; /* const struct l_itimerspec * */
|
||||
uarg[3] = (intptr_t) p->old_value; /* struct l_itimerspec * */
|
||||
*n_args = 4;
|
||||
break;
|
||||
}
|
||||
/* linux_timerfd_gettime */
|
||||
case 287: {
|
||||
*n_args = 0;
|
||||
struct linux_timerfd_gettime_args *p = params;
|
||||
iarg[0] = p->fd; /* l_int */
|
||||
uarg[1] = (intptr_t) p->old_value; /* struct l_itimerspec * */
|
||||
*n_args = 2;
|
||||
break;
|
||||
}
|
||||
/* linux_accept4 */
|
||||
@ -5635,6 +5647,9 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
|
||||
case 4:
|
||||
p = "userland l_sigset_t *";
|
||||
break;
|
||||
case 5:
|
||||
p = "l_size_t";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
@ -5644,6 +5659,16 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
|
||||
break;
|
||||
/* linux_timerfd_create */
|
||||
case 283:
|
||||
switch(ndx) {
|
||||
case 0:
|
||||
p = "l_int";
|
||||
break;
|
||||
case 1:
|
||||
p = "l_int";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
break;
|
||||
/* linux_eventfd */
|
||||
case 284:
|
||||
@ -5676,9 +5701,35 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
|
||||
break;
|
||||
/* linux_timerfd_settime */
|
||||
case 286:
|
||||
switch(ndx) {
|
||||
case 0:
|
||||
p = "l_int";
|
||||
break;
|
||||
case 1:
|
||||
p = "l_int";
|
||||
break;
|
||||
case 2:
|
||||
p = "userland const struct l_itimerspec *";
|
||||
break;
|
||||
case 3:
|
||||
p = "userland struct l_itimerspec *";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
break;
|
||||
/* linux_timerfd_gettime */
|
||||
case 287:
|
||||
switch(ndx) {
|
||||
case 0:
|
||||
p = "l_int";
|
||||
break;
|
||||
case 1:
|
||||
p = "userland struct l_itimerspec *";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
break;
|
||||
/* linux_accept4 */
|
||||
case 288:
|
||||
@ -7494,6 +7545,9 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
|
||||
case 282:
|
||||
/* linux_timerfd_create */
|
||||
case 283:
|
||||
if (ndx == 0 || ndx == 1)
|
||||
p = "int";
|
||||
break;
|
||||
/* linux_eventfd */
|
||||
case 284:
|
||||
if (ndx == 0 || ndx == 1)
|
||||
@ -7506,8 +7560,14 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
|
||||
break;
|
||||
/* linux_timerfd_settime */
|
||||
case 286:
|
||||
if (ndx == 0 || ndx == 1)
|
||||
p = "int";
|
||||
break;
|
||||
/* linux_timerfd_gettime */
|
||||
case 287:
|
||||
if (ndx == 0 || ndx == 1)
|
||||
p = "int";
|
||||
break;
|
||||
/* linux_accept4 */
|
||||
case 288:
|
||||
if (ndx == 0 || ndx == 1)
|
||||
|
@ -473,14 +473,18 @@
|
||||
280 AUE_FUTIMESAT STD { int linux_utimensat(l_int dfd, const char *pathname, \
|
||||
const struct l_timespec *times, l_int flags); }
|
||||
281 AUE_NULL STD { int linux_epoll_pwait(l_int epfd, struct epoll_event *events, \
|
||||
l_int maxevents, l_int timeout, l_sigset_t *mask); }
|
||||
l_int maxevents, l_int timeout, l_sigset_t *mask, \
|
||||
l_size_t sigsetsize); }
|
||||
282 AUE_NULL STD { int linux_signalfd(void); }
|
||||
283 AUE_NULL STD { int linux_timerfd_create(void); }
|
||||
283 AUE_NULL STD { int linux_timerfd_create(l_int clockid, l_int flags); }
|
||||
284 AUE_NULL STD { int linux_eventfd(l_uint initval); }
|
||||
285 AUE_NULL STD { int linux_fallocate(l_int fd, l_int mode, \
|
||||
l_loff_t offset, l_loff_t len); }
|
||||
286 AUE_NULL STD { int linux_timerfd_settime(void); }
|
||||
287 AUE_NULL STD { int linux_timerfd_gettime(void); }
|
||||
286 AUE_NULL STD { int linux_timerfd_settime(l_int fd, l_int flags, \
|
||||
const struct l_itimerspec *new_value, \
|
||||
struct l_itimerspec *old_value); }
|
||||
287 AUE_NULL STD { int linux_timerfd_gettime(l_int fd, \
|
||||
struct l_itimerspec *old_value); }
|
||||
288 AUE_ACCEPT STD { int linux_accept4(l_int s, l_uintptr_t addr, \
|
||||
l_uintptr_t namelen, int flags); }
|
||||
; linux 2.6.27:
|
||||
|
@ -250,7 +250,9 @@ struct l_statfs64 {
|
||||
uint64_t f_ffree;
|
||||
l_fsid_t f_fsid;
|
||||
l_int f_namelen;
|
||||
l_int f_spare[6];
|
||||
l_int f_frsize;
|
||||
l_int f_flags;
|
||||
l_int f_spare[4];
|
||||
} __packed;
|
||||
|
||||
/* sigaction flags */
|
||||
|
@ -103,10 +103,6 @@ DUMMY(move_pages);
|
||||
DUMMY(getcpu);
|
||||
/* linux 2.6.22: */
|
||||
DUMMY(signalfd);
|
||||
DUMMY(timerfd_create);
|
||||
/* linux 2.6.25: */
|
||||
DUMMY(timerfd_settime);
|
||||
DUMMY(timerfd_gettime);
|
||||
/* linux 2.6.27: */
|
||||
DUMMY(signalfd4);
|
||||
DUMMY(inotify_init1);
|
||||
|
@ -1051,6 +1051,7 @@ struct linux_epoll_pwait_args {
|
||||
char maxevents_l_[PADL_(l_int)]; l_int maxevents; char maxevents_r_[PADR_(l_int)];
|
||||
char timeout_l_[PADL_(l_int)]; l_int timeout; char timeout_r_[PADR_(l_int)];
|
||||
char mask_l_[PADL_(l_sigset_t *)]; l_sigset_t * mask; char mask_r_[PADR_(l_sigset_t *)];
|
||||
char sigsetsize_l_[PADL_(l_size_t)]; l_size_t sigsetsize; char sigsetsize_r_[PADR_(l_size_t)];
|
||||
};
|
||||
struct linux_utimensat_args {
|
||||
char dfd_l_[PADL_(l_int)]; l_int dfd; char dfd_r_[PADR_(l_int)];
|
||||
@ -1062,7 +1063,8 @@ struct linux_signalfd_args {
|
||||
register_t dummy;
|
||||
};
|
||||
struct linux_timerfd_create_args {
|
||||
register_t dummy;
|
||||
char clockid_l_[PADL_(l_int)]; l_int clockid; char clockid_r_[PADR_(l_int)];
|
||||
char flags_l_[PADL_(l_int)]; l_int flags; char flags_r_[PADR_(l_int)];
|
||||
};
|
||||
struct linux_eventfd_args {
|
||||
char initval_l_[PADL_(l_uint)]; l_uint initval; char initval_r_[PADR_(l_uint)];
|
||||
@ -1074,10 +1076,14 @@ struct linux_fallocate_args {
|
||||
char len_l_[PADL_(l_loff_t)]; l_loff_t len; char len_r_[PADR_(l_loff_t)];
|
||||
};
|
||||
struct linux_timerfd_settime_args {
|
||||
register_t dummy;
|
||||
char fd_l_[PADL_(l_int)]; l_int fd; char fd_r_[PADR_(l_int)];
|
||||
char flags_l_[PADL_(l_int)]; l_int flags; char flags_r_[PADR_(l_int)];
|
||||
char new_value_l_[PADL_(const struct l_itimerspec *)]; const struct l_itimerspec * new_value; char new_value_r_[PADR_(const struct l_itimerspec *)];
|
||||
char old_value_l_[PADL_(struct l_itimerspec *)]; struct l_itimerspec * old_value; char old_value_r_[PADR_(struct l_itimerspec *)];
|
||||
};
|
||||
struct linux_timerfd_gettime_args {
|
||||
register_t dummy;
|
||||
char fd_l_[PADL_(l_int)]; l_int fd; char fd_r_[PADR_(l_int)];
|
||||
char old_value_l_[PADL_(struct l_itimerspec *)]; struct l_itimerspec * old_value; char old_value_r_[PADR_(struct l_itimerspec *)];
|
||||
};
|
||||
struct linux_signalfd4_args {
|
||||
register_t dummy;
|
||||
|
@ -340,11 +340,11 @@ struct sysent linux32_sysent[] = {
|
||||
{ AS(linux_epoll_pwait_args), (sy_call_t *)linux_epoll_pwait, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 319 = linux_epoll_pwait */
|
||||
{ AS(linux_utimensat_args), (sy_call_t *)linux_utimensat, AUE_FUTIMESAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 320 = linux_utimensat */
|
||||
{ 0, (sy_call_t *)linux_signalfd, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 321 = linux_signalfd */
|
||||
{ 0, (sy_call_t *)linux_timerfd_create, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 322 = linux_timerfd_create */
|
||||
{ AS(linux_timerfd_create_args), (sy_call_t *)linux_timerfd_create, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 322 = linux_timerfd_create */
|
||||
{ AS(linux_eventfd_args), (sy_call_t *)linux_eventfd, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 323 = linux_eventfd */
|
||||
{ AS(linux_fallocate_args), (sy_call_t *)linux_fallocate, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 324 = linux_fallocate */
|
||||
{ 0, (sy_call_t *)linux_timerfd_settime, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 325 = linux_timerfd_settime */
|
||||
{ 0, (sy_call_t *)linux_timerfd_gettime, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 326 = linux_timerfd_gettime */
|
||||
{ AS(linux_timerfd_settime_args), (sy_call_t *)linux_timerfd_settime, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 325 = linux_timerfd_settime */
|
||||
{ AS(linux_timerfd_gettime_args), (sy_call_t *)linux_timerfd_gettime, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 326 = linux_timerfd_gettime */
|
||||
{ 0, (sy_call_t *)linux_signalfd4, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 327 = linux_signalfd4 */
|
||||
{ AS(linux_eventfd2_args), (sy_call_t *)linux_eventfd2, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 328 = linux_eventfd2 */
|
||||
{ AS(linux_epoll_create1_args), (sy_call_t *)linux_epoll_create1, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 329 = linux_epoll_create1 */
|
||||
|
@ -2169,7 +2169,8 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
|
||||
iarg[2] = p->maxevents; /* l_int */
|
||||
iarg[3] = p->timeout; /* l_int */
|
||||
uarg[4] = (intptr_t) p->mask; /* l_sigset_t * */
|
||||
*n_args = 5;
|
||||
iarg[5] = p->sigsetsize; /* l_size_t */
|
||||
*n_args = 6;
|
||||
break;
|
||||
}
|
||||
/* linux_utimensat */
|
||||
@ -2189,7 +2190,10 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
|
||||
}
|
||||
/* linux_timerfd_create */
|
||||
case 322: {
|
||||
*n_args = 0;
|
||||
struct linux_timerfd_create_args *p = params;
|
||||
iarg[0] = p->clockid; /* l_int */
|
||||
iarg[1] = p->flags; /* l_int */
|
||||
*n_args = 2;
|
||||
break;
|
||||
}
|
||||
/* linux_eventfd */
|
||||
@ -2211,12 +2215,20 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
|
||||
}
|
||||
/* linux_timerfd_settime */
|
||||
case 325: {
|
||||
*n_args = 0;
|
||||
struct linux_timerfd_settime_args *p = params;
|
||||
iarg[0] = p->fd; /* l_int */
|
||||
iarg[1] = p->flags; /* l_int */
|
||||
uarg[2] = (intptr_t) p->new_value; /* const struct l_itimerspec * */
|
||||
uarg[3] = (intptr_t) p->old_value; /* struct l_itimerspec * */
|
||||
*n_args = 4;
|
||||
break;
|
||||
}
|
||||
/* linux_timerfd_gettime */
|
||||
case 326: {
|
||||
*n_args = 0;
|
||||
struct linux_timerfd_gettime_args *p = params;
|
||||
iarg[0] = p->fd; /* l_int */
|
||||
uarg[1] = (intptr_t) p->old_value; /* struct l_itimerspec * */
|
||||
*n_args = 2;
|
||||
break;
|
||||
}
|
||||
/* linux_signalfd4 */
|
||||
@ -5970,6 +5982,9 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
|
||||
case 4:
|
||||
p = "userland l_sigset_t *";
|
||||
break;
|
||||
case 5:
|
||||
p = "l_size_t";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
@ -5998,6 +6013,16 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
|
||||
break;
|
||||
/* linux_timerfd_create */
|
||||
case 322:
|
||||
switch(ndx) {
|
||||
case 0:
|
||||
p = "l_int";
|
||||
break;
|
||||
case 1:
|
||||
p = "l_int";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
break;
|
||||
/* linux_eventfd */
|
||||
case 323:
|
||||
@ -6030,9 +6055,35 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
|
||||
break;
|
||||
/* linux_timerfd_settime */
|
||||
case 325:
|
||||
switch(ndx) {
|
||||
case 0:
|
||||
p = "l_int";
|
||||
break;
|
||||
case 1:
|
||||
p = "l_int";
|
||||
break;
|
||||
case 2:
|
||||
p = "userland const struct l_itimerspec *";
|
||||
break;
|
||||
case 3:
|
||||
p = "userland struct l_itimerspec *";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
break;
|
||||
/* linux_timerfd_gettime */
|
||||
case 326:
|
||||
switch(ndx) {
|
||||
case 0:
|
||||
p = "l_int";
|
||||
break;
|
||||
case 1:
|
||||
p = "userland struct l_itimerspec *";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
break;
|
||||
/* linux_signalfd4 */
|
||||
case 327:
|
||||
@ -8128,6 +8179,9 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
|
||||
case 321:
|
||||
/* linux_timerfd_create */
|
||||
case 322:
|
||||
if (ndx == 0 || ndx == 1)
|
||||
p = "int";
|
||||
break;
|
||||
/* linux_eventfd */
|
||||
case 323:
|
||||
if (ndx == 0 || ndx == 1)
|
||||
@ -8140,8 +8194,14 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
|
||||
break;
|
||||
/* linux_timerfd_settime */
|
||||
case 325:
|
||||
if (ndx == 0 || ndx == 1)
|
||||
p = "int";
|
||||
break;
|
||||
/* linux_timerfd_gettime */
|
||||
case 326:
|
||||
if (ndx == 0 || ndx == 1)
|
||||
p = "int";
|
||||
break;
|
||||
/* linux_signalfd4 */
|
||||
case 327:
|
||||
/* linux_eventfd2 */
|
||||
|
@ -533,19 +533,23 @@
|
||||
; linux 2.6.19:
|
||||
318 AUE_NULL STD { int linux_getcpu(void); }
|
||||
319 AUE_NULL STD { int linux_epoll_pwait(l_int epfd, struct epoll_event *events, \
|
||||
l_int maxevents, l_int timeout, l_sigset_t *mask); }
|
||||
l_int maxevents, l_int timeout, l_sigset_t *mask, \
|
||||
l_size_t sigsetsize); }
|
||||
; linux 2.6.22:
|
||||
320 AUE_FUTIMESAT STD { int linux_utimensat(l_int dfd, const char *pathname, \
|
||||
const struct l_timespec *times, l_int flags); }
|
||||
321 AUE_NULL STD { int linux_signalfd(void); }
|
||||
322 AUE_NULL STD { int linux_timerfd_create(void); }
|
||||
322 AUE_NULL STD { int linux_timerfd_create(l_int clockid, l_int flags); }
|
||||
323 AUE_NULL STD { int linux_eventfd(l_uint initval); }
|
||||
; linux 2.6.23:
|
||||
324 AUE_NULL STD { int linux_fallocate(l_int fd, l_int mode, \
|
||||
l_loff_t offset, l_loff_t len); }
|
||||
; linux 2.6.25:
|
||||
325 AUE_NULL STD { int linux_timerfd_settime(void); }
|
||||
326 AUE_NULL STD { int linux_timerfd_gettime(void); }
|
||||
325 AUE_NULL STD { int linux_timerfd_settime(l_int fd, l_int flags, \
|
||||
const struct l_itimerspec *new_value, \
|
||||
struct l_itimerspec *old_value); }
|
||||
326 AUE_NULL STD { int linux_timerfd_gettime(l_int fd, \
|
||||
struct l_itimerspec *old_value); }
|
||||
; linux 2.6.27:
|
||||
327 AUE_NULL STD { int linux_signalfd4(void); }
|
||||
328 AUE_NULL STD { int linux_eventfd2(l_uint initval, l_int flags); }
|
||||
|
@ -1,5 +1,6 @@
|
||||
# $FreeBSD$
|
||||
|
||||
arm/allwinner/clkng/ccu_a31.c standard
|
||||
arm/allwinner/a31/a31_padconf.c standard
|
||||
arm/allwinner/a31/a31_r_padconf.c standard
|
||||
arm/allwinner/a31/a31s_padconf.c standard
|
||||
|
364
sys/arm/allwinner/clkng/aw_ccung.c
Normal file
364
sys/arm/allwinner/clkng/aw_ccung.c
Normal file
@ -0,0 +1,364 @@
|
||||
/*-
|
||||
* Copyright (c) 2017 Emmanuel Vadot <manu@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 ``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$
|
||||
*/
|
||||
|
||||
/*
|
||||
* Allwinner Clock Control Unit
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/rman.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
#include <machine/bus.h>
|
||||
|
||||
#include <dev/fdt/simplebus.h>
|
||||
|
||||
#include <dev/ofw/ofw_bus.h>
|
||||
#include <dev/ofw/ofw_bus_subr.h>
|
||||
|
||||
#include <dev/extres/clk/clk.h>
|
||||
#include <dev/extres/clk/clk_gate.h>
|
||||
|
||||
#include <dev/extres/hwreset/hwreset.h>
|
||||
|
||||
#include <arm/allwinner/clkng/aw_ccung.h>
|
||||
#include <arm/allwinner/clkng/aw_clk.h>
|
||||
|
||||
#if defined(SOC_ALLWINNER_A31)
|
||||
#include <arm/allwinner/clkng/ccu_a31.h>
|
||||
#endif
|
||||
|
||||
#if defined(SOC_ALLWINNER_H3)
|
||||
#include <arm/allwinner/clkng/ccu_h3.h>
|
||||
#endif
|
||||
|
||||
#include "clkdev_if.h"
|
||||
#include "hwreset_if.h"
|
||||
|
||||
static struct resource_spec aw_ccung_spec[] = {
|
||||
{ SYS_RES_MEMORY, 0, RF_ACTIVE },
|
||||
{ -1, 0 }
|
||||
};
|
||||
|
||||
#if defined(SOC_ALLWINNER_H3)
|
||||
#define H3_CCU 1
|
||||
#endif
|
||||
|
||||
#if defined(SOC_ALLWINNER_A31)
|
||||
#define A31_CCU 2
|
||||
#endif
|
||||
|
||||
static struct ofw_compat_data compat_data[] = {
|
||||
#if defined(SOC_ALLWINNER_H3)
|
||||
{ "allwinner,sun8i-h3-ccu", H3_CCU },
|
||||
#endif
|
||||
#if defined(SOC_ALLWINNER_A31)
|
||||
{ "allwinner,sun6i-a31-ccu", A31_CCU },
|
||||
#endif
|
||||
{NULL, 0 }
|
||||
};
|
||||
|
||||
#define CCU_READ4(sc, reg) bus_read_4((sc)->res, (reg))
|
||||
#define CCU_WRITE4(sc, reg, val) bus_write_4((sc)->res, (reg), (val))
|
||||
|
||||
static int
|
||||
aw_ccung_write_4(device_t dev, bus_addr_t addr, uint32_t val)
|
||||
{
|
||||
struct aw_ccung_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
CCU_WRITE4(sc, addr, val);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
aw_ccung_read_4(device_t dev, bus_addr_t addr, uint32_t *val)
|
||||
{
|
||||
struct aw_ccung_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
*val = CCU_READ4(sc, addr);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
aw_ccung_modify_4(device_t dev, bus_addr_t addr, uint32_t clr, uint32_t set)
|
||||
{
|
||||
struct aw_ccung_softc *sc;
|
||||
uint32_t reg;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
reg = CCU_READ4(sc, addr);
|
||||
reg &= ~clr;
|
||||
reg |= set;
|
||||
CCU_WRITE4(sc, addr, reg);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
aw_ccung_reset_assert(device_t dev, intptr_t id, bool reset)
|
||||
{
|
||||
struct aw_ccung_softc *sc;
|
||||
uint32_t val;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
if (id >= sc->nresets || sc->resets[id].offset == 0)
|
||||
return (0);
|
||||
|
||||
mtx_lock(&sc->mtx);
|
||||
val = CCU_READ4(sc, sc->resets[id].offset);
|
||||
if (reset)
|
||||
val &= ~(1 << sc->resets[id].shift);
|
||||
else
|
||||
val |= 1 << sc->resets[id].shift;
|
||||
CCU_WRITE4(sc, sc->resets[id].offset, val);
|
||||
mtx_unlock(&sc->mtx);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
aw_ccung_reset_is_asserted(device_t dev, intptr_t id, bool *reset)
|
||||
{
|
||||
struct aw_ccung_softc *sc;
|
||||
uint32_t val;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
if (id >= sc->nresets || sc->resets[id].offset == 0)
|
||||
return (0);
|
||||
|
||||
mtx_lock(&sc->mtx);
|
||||
val = CCU_READ4(sc, sc->resets[id].offset);
|
||||
*reset = (val & (1 << sc->resets[id].shift)) != 0 ? false : true;
|
||||
mtx_unlock(&sc->mtx);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
aw_ccung_device_lock(device_t dev)
|
||||
{
|
||||
struct aw_ccung_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
mtx_lock(&sc->mtx);
|
||||
}
|
||||
|
||||
static void
|
||||
aw_ccung_device_unlock(device_t dev)
|
||||
{
|
||||
struct aw_ccung_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
mtx_unlock(&sc->mtx);
|
||||
}
|
||||
|
||||
static int
|
||||
aw_ccung_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, "Allwinner Clock Control Unit NG");
|
||||
return (BUS_PROBE_DEFAULT);
|
||||
}
|
||||
|
||||
static int
|
||||
aw_ccung_register_gates(struct aw_ccung_softc *sc)
|
||||
{
|
||||
struct clk_gate_def def;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sc->ngates; i++) {
|
||||
if (sc->gates[i].name == NULL)
|
||||
continue;
|
||||
memset(&def, 0, sizeof(def));
|
||||
def.clkdef.id = i;
|
||||
def.clkdef.name = sc->gates[i].name;
|
||||
def.clkdef.parent_names = &sc->gates[i].parent_name;
|
||||
def.clkdef.parent_cnt = 1;
|
||||
def.offset = sc->gates[i].offset;
|
||||
def.shift = sc->gates[i].shift;
|
||||
def.mask = 1;
|
||||
def.on_value = 1;
|
||||
def.off_value = 0;
|
||||
clknode_gate_register(sc->clkdom, &def);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
aw_ccung_init_clocks(struct aw_ccung_softc *sc)
|
||||
{
|
||||
struct clknode *clknode;
|
||||
int i, error;
|
||||
|
||||
for (i = 0; i < sc->n_clk_init; i++) {
|
||||
clknode = clknode_find_by_name(sc->clk_init[i].name);
|
||||
if (clknode == NULL) {
|
||||
device_printf(sc->dev, "Cannot find clock %s\n",
|
||||
sc->clk_init[i].name);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sc->clk_init[i].parent_name != NULL) {
|
||||
if (bootverbose)
|
||||
device_printf(sc->dev, "Setting %s as parent for %s\n",
|
||||
sc->clk_init[i].parent_name,
|
||||
sc->clk_init[i].name);
|
||||
error = clknode_set_parent_by_name(clknode,
|
||||
sc->clk_init[i].parent_name);
|
||||
if (error != 0) {
|
||||
device_printf(sc->dev,
|
||||
"Cannot set parent to %s for %s\n",
|
||||
sc->clk_init[i].parent_name,
|
||||
sc->clk_init[i].name);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (sc->clk_init[i].default_freq != 0) {
|
||||
error = clknode_set_freq(clknode,
|
||||
sc->clk_init[i].default_freq, 0 , 0);
|
||||
if (error != 0) {
|
||||
device_printf(sc->dev,
|
||||
"Cannot set frequency for %s to %llu\n",
|
||||
sc->clk_init[i].name,
|
||||
sc->clk_init[i].default_freq);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (sc->clk_init[i].enable) {
|
||||
error = clknode_enable(clknode);
|
||||
if (error != 0) {
|
||||
device_printf(sc->dev,
|
||||
"Cannot enable %s\n",
|
||||
sc->clk_init[i].name);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
aw_ccung_attach(device_t dev)
|
||||
{
|
||||
struct aw_ccung_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
sc->dev = dev;
|
||||
|
||||
if (bus_alloc_resources(dev, aw_ccung_spec, &sc->res) != 0) {
|
||||
device_printf(dev, "cannot allocate resources for device\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF);
|
||||
|
||||
sc->type = ofw_bus_search_compatible(dev, compat_data)->ocd_data;
|
||||
|
||||
sc->clkdom = clkdom_create(dev);
|
||||
if (sc->clkdom == NULL)
|
||||
panic("Cannot create clkdom\n");
|
||||
|
||||
switch (sc->type) {
|
||||
#if defined(SOC_ALLWINNER_H3)
|
||||
case H3_CCU:
|
||||
ccu_h3_register_clocks(sc);
|
||||
break;
|
||||
#endif
|
||||
#if defined(SOC_ALLWINNER_A31)
|
||||
case A31_CCU:
|
||||
ccu_a31_register_clocks(sc);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (sc->gates)
|
||||
aw_ccung_register_gates(sc);
|
||||
if (clkdom_finit(sc->clkdom) != 0)
|
||||
panic("cannot finalize clkdom initialization\n");
|
||||
|
||||
clkdom_xlock(sc->clkdom);
|
||||
aw_ccung_init_clocks(sc);
|
||||
clkdom_unlock(sc->clkdom);
|
||||
|
||||
if (bootverbose)
|
||||
clkdom_dump(sc->clkdom);
|
||||
|
||||
/* If we have resets, register our self as a reset provider */
|
||||
if (sc->resets)
|
||||
hwreset_register_ofw_provider(dev);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static device_method_t aw_ccung_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, aw_ccung_probe),
|
||||
DEVMETHOD(device_attach, aw_ccung_attach),
|
||||
|
||||
/* clkdev interface */
|
||||
DEVMETHOD(clkdev_write_4, aw_ccung_write_4),
|
||||
DEVMETHOD(clkdev_read_4, aw_ccung_read_4),
|
||||
DEVMETHOD(clkdev_modify_4, aw_ccung_modify_4),
|
||||
DEVMETHOD(clkdev_device_lock, aw_ccung_device_lock),
|
||||
DEVMETHOD(clkdev_device_unlock, aw_ccung_device_unlock),
|
||||
|
||||
/* Reset interface */
|
||||
DEVMETHOD(hwreset_assert, aw_ccung_reset_assert),
|
||||
DEVMETHOD(hwreset_is_asserted, aw_ccung_reset_is_asserted),
|
||||
|
||||
DEVMETHOD_END
|
||||
};
|
||||
|
||||
static driver_t aw_ccung_driver = {
|
||||
"aw_ccung",
|
||||
aw_ccung_methods,
|
||||
sizeof(struct aw_ccung_softc),
|
||||
};
|
||||
|
||||
static devclass_t aw_ccung_devclass;
|
||||
|
||||
EARLY_DRIVER_MODULE(aw_ccung, simplebus, aw_ccung_driver, aw_ccung_devclass,
|
||||
0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
|
||||
MODULE_VERSION(aw_ccung, 1);
|
59
sys/arm/allwinner/clkng/aw_ccung.h
Normal file
59
sys/arm/allwinner/clkng/aw_ccung.h
Normal file
@ -0,0 +1,59 @@
|
||||
/*-
|
||||
* Copyright (c) 2017 Emmanuel Vadot <manu@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 ``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 __CCU_NG_H__
|
||||
#define __CCU_NG_H__
|
||||
|
||||
struct aw_ccung_softc {
|
||||
device_t dev;
|
||||
struct resource *res;
|
||||
struct clkdom *clkdom;
|
||||
struct mtx mtx;
|
||||
int type;
|
||||
struct aw_ccung_reset *resets;
|
||||
int nresets;
|
||||
struct aw_ccung_gate *gates;
|
||||
int ngates;
|
||||
struct aw_clk_init *clk_init;
|
||||
int n_clk_init;
|
||||
};
|
||||
|
||||
struct aw_ccung_reset {
|
||||
uint32_t offset;
|
||||
uint32_t shift;
|
||||
};
|
||||
|
||||
struct aw_ccung_gate {
|
||||
const char *name;
|
||||
const char *parent_name;
|
||||
uint32_t id;
|
||||
uint32_t offset;
|
||||
uint32_t shift;
|
||||
};
|
||||
|
||||
#endif /* __CCU_NG_H__ */
|
442
sys/arm/allwinner/clkng/aw_clk.h
Normal file
442
sys/arm/allwinner/clkng/aw_clk.h
Normal file
@ -0,0 +1,442 @@
|
||||
/*-
|
||||
* Copyright (c) 2017 Emmanuel Vadot <manu@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 ``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 __AW_CLK_H__
|
||||
#define __AW_CLK_H__
|
||||
|
||||
/*
|
||||
Allwinner clocks formula :
|
||||
|
||||
PLLs:
|
||||
|
||||
(24MHz*N*K)/(M*P)
|
||||
(24MHz*N)/(M*P)
|
||||
(24MHz*N*2)/M
|
||||
(24MHz*N)/M
|
||||
(24MHz*N*K)/M
|
||||
(24MHz*N*K/2)
|
||||
(24MHz*N)/M
|
||||
(24MHz*N*K/2)
|
||||
(24MHz*N)/M
|
||||
|
||||
Periph clocks:
|
||||
|
||||
Clock Source/Divider N/Divider M
|
||||
Clock Source/Divider N/Divider M/2
|
||||
|
||||
*/
|
||||
|
||||
struct aw_clk_init {
|
||||
const char *name;
|
||||
const char *parent_name;
|
||||
uint64_t default_freq;
|
||||
bool enable;
|
||||
};
|
||||
|
||||
#define AW_CLK_HAS_GATE 0x0001
|
||||
#define AW_CLK_HAS_LOCK 0x0002
|
||||
#define AW_CLK_HAS_MUX 0x0004
|
||||
#define AW_CLK_REPARENT 0x0008
|
||||
#define AW_CLK_SCALE_CHANGE 0x0010
|
||||
#define AW_CLK_HAS_FRAC 0x0020
|
||||
#define AW_CLK_HAS_UPDATE 0x0040
|
||||
|
||||
#define AW_CLK_FACTOR_POWER_OF_TWO 0x0001
|
||||
#define AW_CLK_FACTOR_ZERO_BASED 0x0002
|
||||
#define AW_CLK_FACTOR_HAS_COND 0x0004
|
||||
#define AW_CLK_FACTOR_FIXED 0x0008
|
||||
|
||||
struct aw_clk_factor {
|
||||
uint32_t shift; /* Shift bits for the factor */
|
||||
uint32_t mask; /* Mask to get the factor, will be override by the clk methods */
|
||||
uint32_t width; /* Number of bits for the factor */
|
||||
uint32_t value; /* Fixed value, depends on AW_CLK_FACTOR_FIXED */
|
||||
|
||||
uint32_t cond_shift;
|
||||
uint32_t cond_mask;
|
||||
uint32_t cond_width;
|
||||
uint32_t cond_value;
|
||||
|
||||
uint32_t flags; /* Flags */
|
||||
};
|
||||
|
||||
struct aw_clk_frac {
|
||||
uint64_t freq0;
|
||||
uint64_t freq1;
|
||||
uint32_t mode_sel;
|
||||
uint32_t freq_sel;
|
||||
};
|
||||
|
||||
static inline uint32_t
|
||||
aw_clk_get_factor(uint32_t val, struct aw_clk_factor *factor)
|
||||
{
|
||||
uint32_t factor_val;
|
||||
uint32_t cond;
|
||||
|
||||
if (factor->flags & AW_CLK_FACTOR_HAS_COND) {
|
||||
cond = (val & factor->cond_mask) >> factor->cond_shift;
|
||||
if (cond != factor->cond_value)
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (factor->flags & AW_CLK_FACTOR_FIXED)
|
||||
return (factor->value);
|
||||
|
||||
factor_val = (val & factor->mask) >> factor->shift;
|
||||
if (!(factor->flags & AW_CLK_FACTOR_ZERO_BASED))
|
||||
factor_val += 1;
|
||||
else if (factor->flags & AW_CLK_FACTOR_POWER_OF_TWO)
|
||||
factor_val = 1 << factor_val;
|
||||
|
||||
return (factor_val);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
aw_clk_factor_get_max(struct aw_clk_factor *factor)
|
||||
{
|
||||
uint32_t max;
|
||||
|
||||
if (factor->flags & AW_CLK_FACTOR_FIXED)
|
||||
max = factor->value;
|
||||
else if (factor->flags & AW_CLK_FACTOR_POWER_OF_TWO)
|
||||
max = 1 << ((1 << factor->width) - 1);
|
||||
else {
|
||||
max = (1 << factor->width);
|
||||
}
|
||||
|
||||
return (max);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
aw_clk_factor_get_min(struct aw_clk_factor *factor)
|
||||
{
|
||||
uint32_t min;
|
||||
|
||||
if (factor->flags & AW_CLK_FACTOR_FIXED)
|
||||
min = factor->value;
|
||||
else if (factor->flags & AW_CLK_FACTOR_ZERO_BASED)
|
||||
min = 0;
|
||||
else
|
||||
min = 1;
|
||||
|
||||
return (min);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
aw_clk_factor_get_value(struct aw_clk_factor *factor, uint32_t raw)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
if (factor->flags & AW_CLK_FACTOR_FIXED)
|
||||
return (factor->value);
|
||||
|
||||
if (factor->flags & AW_CLK_FACTOR_ZERO_BASED)
|
||||
val = raw;
|
||||
else if (factor->flags & AW_CLK_FACTOR_POWER_OF_TWO) {
|
||||
for (val = 0; raw != 1; val++)
|
||||
raw >>= 1;
|
||||
} else
|
||||
val = raw - 1;
|
||||
|
||||
return (val);
|
||||
}
|
||||
|
||||
#define CCU_RESET(idx, o, s) \
|
||||
[idx] = { \
|
||||
.offset = o, \
|
||||
.shift = s, \
|
||||
},
|
||||
|
||||
#define CCU_GATE(idx, clkname, pname, o, s) \
|
||||
[idx] = { \
|
||||
.name = clkname, \
|
||||
.parent_name = pname, \
|
||||
.offset = o, \
|
||||
.shift = s, \
|
||||
},
|
||||
|
||||
#define NKMP_CLK(_clkname, _id, _name, _pnames, \
|
||||
_offset, \
|
||||
_n_shift, _n_width, _n_value, _n_flags, \
|
||||
_k_shift, _k_width, _k_value, _k_flags, \
|
||||
_m_shift, _m_width, _m_value, _m_flags, \
|
||||
_p_shift, _p_width, _p_value, _p_flags, \
|
||||
_gate, \
|
||||
_lock, _lock_retries, \
|
||||
_flags) \
|
||||
static struct aw_clk_nkmp_def _clkname = { \
|
||||
.clkdef = { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_names = _pnames, \
|
||||
.parent_cnt = nitems(_pnames), \
|
||||
}, \
|
||||
.offset = _offset, \
|
||||
.n.shift = _n_shift, \
|
||||
.n.width = _n_width, \
|
||||
.n.value = _n_value, \
|
||||
.n.flags = _n_flags, \
|
||||
.k.shift = _k_shift, \
|
||||
.k.width = _k_width, \
|
||||
.k.value = _k_value, \
|
||||
.k.flags = _k_flags, \
|
||||
.m.shift = _m_shift, \
|
||||
.m.width = _m_width, \
|
||||
.m.value = _m_value, \
|
||||
.m.flags = _m_flags, \
|
||||
.p.shift = _p_shift, \
|
||||
.p.width = _p_width, \
|
||||
.p.value = _p_value, \
|
||||
.p.flags = _p_flags, \
|
||||
.gate_shift = _gate, \
|
||||
.lock_shift = _lock, \
|
||||
.lock_retries = _lock_retries, \
|
||||
.flags = _flags, \
|
||||
}
|
||||
|
||||
#define NKMP_CLK_WITH_MUX(_clkname, \
|
||||
_id, _name, _pnames, \
|
||||
_offset, \
|
||||
_n_shift, _n_width, _n_value, _n_flags, \
|
||||
_k_shift, _k_width, _k_value, _k_flags, \
|
||||
_m_shift, _m_width, _m_value, _m_flags, \
|
||||
_p_shift, _p_width, _p_value, _p_flags, \
|
||||
_mux_shift, _mux_width, _gate, \
|
||||
_lock, _lock_retries, \
|
||||
_flags) \
|
||||
static struct aw_clk_nkmp_def _clkname = { \
|
||||
.clkdef = { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_names = _pnames, \
|
||||
.parent_cnt = nitems(_pnames), \
|
||||
}, \
|
||||
.offset = _offset, \
|
||||
.n.shift = _n_shift, \
|
||||
.n.width = _n_width, \
|
||||
.n.value = _n_value, \
|
||||
.n.flags = _n_flags, \
|
||||
.k.shift = _k_shift, \
|
||||
.k.width = _k_width, \
|
||||
.k.value = _k_value, \
|
||||
.k.flags = _k_flags, \
|
||||
.m.shift = _m_shift, \
|
||||
.m.width = _m_width, \
|
||||
.m.value = _m_value, \
|
||||
.m.flags = _m_flags, \
|
||||
.p.shift = _p_shift, \
|
||||
.p.width = _p_width, \
|
||||
.p.value = _p_value, \
|
||||
.p.flags = _p_flags, \
|
||||
.mux_shift = _mux_shift, \
|
||||
.mux_width = _mux_width, \
|
||||
.gate_shift = _gate, \
|
||||
.lock_shift = _lock, \
|
||||
.lock_retries = _lock_retries, \
|
||||
.flags = _flags, \
|
||||
}
|
||||
|
||||
#define NKMP_CLK_WITH_UPDATE(_clkname, \
|
||||
_id, _name, _pnames, \
|
||||
_offset, \
|
||||
_n_shift, _n_width, _n_value, _n_flags, \
|
||||
_k_shift, _k_width, _k_value, _k_flags, \
|
||||
_m_shift, _m_width, _m_value, _m_flags, \
|
||||
_p_shift, _p_width, _p_value, _p_flags, \
|
||||
_gate, \
|
||||
_lock, _lock_retries, \
|
||||
_update, \
|
||||
_flags) \
|
||||
static struct aw_clk_nkmp_def _clkname = { \
|
||||
.clkdef = { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_names = _pnames, \
|
||||
.parent_cnt = nitems(_pnames), \
|
||||
}, \
|
||||
.offset = _offset, \
|
||||
.n.shift = _n_shift, \
|
||||
.n.width = _n_width, \
|
||||
.n.value = _n_value, \
|
||||
.n.flags = _n_flags, \
|
||||
.k.shift = _k_shift, \
|
||||
.k.width = _k_width, \
|
||||
.k.value = _k_value, \
|
||||
.k.flags = _k_flags, \
|
||||
.m.shift = _m_shift, \
|
||||
.m.width = _m_width, \
|
||||
.m.value = _m_value, \
|
||||
.m.flags = _m_flags, \
|
||||
.p.shift = _p_shift, \
|
||||
.p.width = _p_width, \
|
||||
.p.value = _p_value, \
|
||||
.p.flags = _p_flags, \
|
||||
.gate_shift = _gate, \
|
||||
.lock_shift = _lock, \
|
||||
.lock_retries = _lock_retries, \
|
||||
.update_shift = _update, \
|
||||
.flags = _flags | AW_CLK_HAS_UPDATE, \
|
||||
}
|
||||
|
||||
#define NM_CLK(_clkname, _id, _name, _pnames, \
|
||||
_offset, \
|
||||
_nshift, _nwidth, _nvalue, _nflags, \
|
||||
_mshift, _mwidth, _mvalue, _mflags, \
|
||||
_mux_shift, _mux_width, \
|
||||
_gate_shift, \
|
||||
_flags) \
|
||||
static struct aw_clk_nm_def _clkname = { \
|
||||
.clkdef = { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_names = _pnames, \
|
||||
.parent_cnt = nitems(_pnames), \
|
||||
}, \
|
||||
.offset = _offset, \
|
||||
.n.shift = _nshift, \
|
||||
.n.width = _nwidth, \
|
||||
.n.value = _nvalue, \
|
||||
.n.flags = _nflags, \
|
||||
.mux_shift = _mux_shift, \
|
||||
.m.shift = _mshift, \
|
||||
.m.width = _mwidth, \
|
||||
.m.value = _mvalue, \
|
||||
.m.flags = _mflags, \
|
||||
.mux_width = _mux_width, \
|
||||
.flags = _flags, \
|
||||
}
|
||||
|
||||
#define NM_CLK_WITH_FRAC(_clkname, _id, _name, _pnames, \
|
||||
_offset, \
|
||||
_nshift, _nwidth, _nvalue, _nflags, \
|
||||
_mshift, _mwidth, _mvalue, _mflags, \
|
||||
_gate_shift, _lock_shift,_lock_retries, \
|
||||
_flags, _freq0, _freq1, _mode_sel, _freq_sel) \
|
||||
static struct aw_clk_nm_def _clkname = { \
|
||||
.clkdef = { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_names = _pnames, \
|
||||
.parent_cnt = nitems(_pnames), \
|
||||
}, \
|
||||
.offset = _offset, \
|
||||
.n.shift = _nshift, \
|
||||
.n.width = _nwidth, \
|
||||
.n.value = _nvalue, \
|
||||
.n.flags = _nflags, \
|
||||
.m.shift = _mshift, \
|
||||
.m.width = _mwidth, \
|
||||
.m.value = _mvalue, \
|
||||
.m.flags = _mflags, \
|
||||
.gate_shift = _gate_shift, \
|
||||
.lock_shift = _lock_shift, \
|
||||
.lock_retries = _lock_retries, \
|
||||
.flags = _flags | AW_CLK_HAS_FRAC, \
|
||||
.frac.freq0 = _freq0, \
|
||||
.frac.freq1 = _freq1, \
|
||||
.frac.mode_sel = _mode_sel, \
|
||||
.frac.freq_sel = _freq_sel, \
|
||||
}
|
||||
|
||||
#define PREDIV_CLK(_clkname, _id, _name, _pnames, \
|
||||
_offset, \
|
||||
_mux_shift, _mux_width, \
|
||||
_div_shift, _div_width, _div_value, _div_flags, \
|
||||
_prediv_shift, _prediv_width, _prediv_value, _prediv_flags, \
|
||||
_prediv_cond_shift, _prediv_cond_width, _prediv_cond_value) \
|
||||
static struct aw_clk_prediv_mux_def _clkname = { \
|
||||
.clkdef = { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_names = _pnames, \
|
||||
.parent_cnt = nitems(_pnames), \
|
||||
}, \
|
||||
.offset = _offset, \
|
||||
.mux_shift = _mux_shift, \
|
||||
.mux_width = _mux_width, \
|
||||
.div.shift = _div_shift, \
|
||||
.div.width = _div_width, \
|
||||
.div.value = _div_value, \
|
||||
.div.flags = _div_flags, \
|
||||
.prediv.shift = _prediv_shift, \
|
||||
.prediv.width = _prediv_width, \
|
||||
.prediv.value = _prediv_value, \
|
||||
.prediv.flags = _prediv_flags, \
|
||||
.prediv.cond_shift = _prediv_cond_shift, \
|
||||
.prediv.cond_width = _prediv_cond_width, \
|
||||
.prediv.cond_value = _prediv_cond_value, \
|
||||
}
|
||||
|
||||
#define MUX_CLK(_clkname, _id, _name, _pnames, \
|
||||
_offset, _shift, _width) \
|
||||
static struct clk_mux_def _clkname = { \
|
||||
.clkdef = { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_names = _pnames, \
|
||||
.parent_cnt = nitems(_pnames) \
|
||||
}, \
|
||||
.offset = _offset, \
|
||||
.shift = _shift, \
|
||||
.width = _width, \
|
||||
}
|
||||
|
||||
#define DIV_CLK(_clkname, _id, _name, _pnames, \
|
||||
_offset, \
|
||||
_i_shift, _i_width, \
|
||||
_div_flags, _div_table) \
|
||||
static struct clk_div_def _clkname = { \
|
||||
.clkdef = { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_names = _pnames, \
|
||||
.parent_cnt = nitems(_pnames) \
|
||||
}, \
|
||||
.offset = _offset, \
|
||||
.i_shift = _i_shift, \
|
||||
.i_width = _i_width, \
|
||||
.div_flags = _div_flags, \
|
||||
.div_table = _div_table, \
|
||||
}
|
||||
|
||||
#define FIXED_CLK(_clkname, _id, _name, _pnames, \
|
||||
_freq, _mult, _div, _flags) \
|
||||
static struct clk_fixed_def _clkname = { \
|
||||
.clkdef = { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_names = _pnames, \
|
||||
.parent_cnt = 1, \
|
||||
}, \
|
||||
.freq = _freq, \
|
||||
.mult = _mult, \
|
||||
.div = _div, \
|
||||
.fixed_flags = _flags, \
|
||||
}
|
||||
|
||||
#endif /* __AW_CLK_H__ */
|
413
sys/arm/allwinner/clkng/aw_clk_nkmp.c
Normal file
413
sys/arm/allwinner/clkng/aw_clk_nkmp.c
Normal file
@ -0,0 +1,413 @@
|
||||
/*-
|
||||
* Copyright (c) 2017 Emmanuel Vadot <manu@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 ``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$
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
|
||||
#include <dev/extres/clk/clk.h>
|
||||
|
||||
#include <arm/allwinner/clkng/aw_clk.h>
|
||||
#include <arm/allwinner/clkng/aw_clk_nkmp.h>
|
||||
|
||||
#include "clkdev_if.h"
|
||||
|
||||
/*
|
||||
* clknode for clocks matching the formula :
|
||||
*
|
||||
* clk = (clkin * n * k) / (m * p)
|
||||
*
|
||||
*/
|
||||
|
||||
struct aw_clk_nkmp_sc {
|
||||
uint32_t offset;
|
||||
|
||||
struct aw_clk_factor n;
|
||||
struct aw_clk_factor k;
|
||||
struct aw_clk_factor m;
|
||||
struct aw_clk_factor p;
|
||||
|
||||
uint32_t mux_shift;
|
||||
uint32_t mux_mask;
|
||||
uint32_t gate_shift;
|
||||
uint32_t lock_shift;
|
||||
uint32_t lock_retries;
|
||||
uint32_t update_shift;
|
||||
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
#define WRITE4(_clk, off, val) \
|
||||
CLKDEV_WRITE_4(clknode_get_device(_clk), off, val)
|
||||
#define READ4(_clk, off, val) \
|
||||
CLKDEV_READ_4(clknode_get_device(_clk), off, val)
|
||||
#define MODIFY4(_clk, off, clr, set ) \
|
||||
CLKDEV_MODIFY_4(clknode_get_device(_clk), off, clr, set)
|
||||
#define DEVICE_LOCK(_clk) \
|
||||
CLKDEV_DEVICE_LOCK(clknode_get_device(_clk))
|
||||
#define DEVICE_UNLOCK(_clk) \
|
||||
CLKDEV_DEVICE_UNLOCK(clknode_get_device(_clk))
|
||||
|
||||
static int
|
||||
aw_clk_nkmp_init(struct clknode *clk, device_t dev)
|
||||
{
|
||||
struct aw_clk_nkmp_sc *sc;
|
||||
uint32_t val, idx;
|
||||
|
||||
sc = clknode_get_softc(clk);
|
||||
|
||||
idx = 0;
|
||||
if ((sc->flags & AW_CLK_HAS_MUX) != 0) {
|
||||
DEVICE_LOCK(clk);
|
||||
READ4(clk, sc->offset, &val);
|
||||
DEVICE_UNLOCK(clk);
|
||||
|
||||
idx = (val & sc->mux_mask) >> sc->mux_shift;
|
||||
}
|
||||
|
||||
clknode_init_parent_idx(clk, idx);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
aw_clk_nkmp_set_gate(struct clknode *clk, bool enable)
|
||||
{
|
||||
struct aw_clk_nkmp_sc *sc;
|
||||
uint32_t val;
|
||||
|
||||
sc = clknode_get_softc(clk);
|
||||
|
||||
if ((sc->flags & AW_CLK_HAS_GATE) == 0)
|
||||
return (0);
|
||||
|
||||
DEVICE_LOCK(clk);
|
||||
READ4(clk, sc->offset, &val);
|
||||
if (enable)
|
||||
val |= (1 << sc->gate_shift);
|
||||
else
|
||||
val &= ~(1 << sc->gate_shift);
|
||||
WRITE4(clk, sc->offset, val);
|
||||
DEVICE_UNLOCK(clk);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
aw_clk_nkmp_set_mux(struct clknode *clk, int index)
|
||||
{
|
||||
struct aw_clk_nkmp_sc *sc;
|
||||
uint32_t val;
|
||||
|
||||
sc = clknode_get_softc(clk);
|
||||
|
||||
if ((sc->flags & AW_CLK_HAS_MUX) != 0)
|
||||
return (0);
|
||||
|
||||
DEVICE_LOCK(clk);
|
||||
READ4(clk, sc->offset, &val);
|
||||
val &= ~(sc->mux_mask >> sc->mux_shift);
|
||||
val |= index << sc->mux_shift;
|
||||
WRITE4(clk, sc->offset, val);
|
||||
DEVICE_UNLOCK(clk);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
aw_clk_nkmp_find_best(struct aw_clk_nkmp_sc *sc, uint64_t fparent, uint64_t *fout,
|
||||
uint32_t *factor_n, uint32_t *factor_k, uint32_t *factor_m, uint32_t *factor_p)
|
||||
{
|
||||
uint64_t cur, best;
|
||||
uint32_t n, k, m, p;
|
||||
|
||||
best = 0;
|
||||
*factor_n = 0;
|
||||
*factor_k = 0;
|
||||
*factor_m = 0;
|
||||
*factor_p = 0;
|
||||
|
||||
for (n = aw_clk_factor_get_min(&sc->n); n <= aw_clk_factor_get_max(&sc->n); ) {
|
||||
for (k = aw_clk_factor_get_min(&sc->k); k <= aw_clk_factor_get_max(&sc->k); ) {
|
||||
for (m = aw_clk_factor_get_min(&sc->m); m <= aw_clk_factor_get_max(&sc->m); ) {
|
||||
for (p = aw_clk_factor_get_min(&sc->p); p <= aw_clk_factor_get_max(&sc->p); ) {
|
||||
cur = (fparent * n * k) / (m * p);
|
||||
if ((*fout - cur) < (*fout - best)) {
|
||||
best = cur;
|
||||
*factor_n = n;
|
||||
*factor_k = k;
|
||||
*factor_m = m;
|
||||
*factor_p = p;
|
||||
}
|
||||
if (best == *fout)
|
||||
return (best);
|
||||
if ((sc->p.flags & AW_CLK_FACTOR_POWER_OF_TWO) != 0)
|
||||
p <<= 1;
|
||||
else
|
||||
p++;
|
||||
}
|
||||
if ((sc->m.flags & AW_CLK_FACTOR_POWER_OF_TWO) != 0)
|
||||
m <<= 1;
|
||||
else
|
||||
m++;
|
||||
}
|
||||
if ((sc->k.flags & AW_CLK_FACTOR_POWER_OF_TWO) != 0)
|
||||
k <<= 1;
|
||||
else
|
||||
k++;
|
||||
}
|
||||
if ((sc->n.flags & AW_CLK_FACTOR_POWER_OF_TWO) != 0)
|
||||
n <<= 1;
|
||||
else
|
||||
n++;
|
||||
}
|
||||
|
||||
return best;
|
||||
}
|
||||
|
||||
static void
|
||||
aw_clk_nkmp_set_freq_scale(struct clknode *clk, struct aw_clk_nkmp_sc *sc,
|
||||
uint32_t factor_n, uint32_t factor_k, uint32_t factor_m, uint32_t factor_p)
|
||||
{
|
||||
uint32_t val, n, k, m, p;
|
||||
int retry;
|
||||
|
||||
DEVICE_LOCK(clk);
|
||||
READ4(clk, sc->offset, &val);
|
||||
|
||||
n = aw_clk_get_factor(val, &sc->n);
|
||||
k = aw_clk_get_factor(val, &sc->k);
|
||||
m = aw_clk_get_factor(val, &sc->m);
|
||||
p = aw_clk_get_factor(val, &sc->p);
|
||||
|
||||
if (p < factor_p) {
|
||||
val &= ~sc->p.mask;
|
||||
val |= aw_clk_factor_get_value(&sc->p, factor_p) << sc->p.shift;
|
||||
WRITE4(clk, sc->offset, val);
|
||||
DELAY(2000);
|
||||
}
|
||||
|
||||
if (m < factor_m) {
|
||||
val &= ~sc->m.mask;
|
||||
val |= aw_clk_factor_get_value(&sc->m, factor_m) << sc->m.shift;
|
||||
WRITE4(clk, sc->offset, val);
|
||||
DELAY(2000);
|
||||
}
|
||||
|
||||
val &= ~sc->n.mask;
|
||||
val &= ~sc->k.mask;
|
||||
val |= aw_clk_factor_get_value(&sc->n, factor_n) << sc->n.shift;
|
||||
val |= aw_clk_factor_get_value(&sc->k, factor_k) << sc->k.shift;
|
||||
WRITE4(clk, sc->offset, val);
|
||||
DELAY(2000);
|
||||
|
||||
if (m > factor_m) {
|
||||
val &= ~sc->m.mask;
|
||||
val |= aw_clk_factor_get_value(&sc->m, factor_m) << sc->m.shift;
|
||||
WRITE4(clk, sc->offset, val);
|
||||
DELAY(2000);
|
||||
}
|
||||
|
||||
if (p > factor_p) {
|
||||
val &= ~sc->p.mask;
|
||||
val |= aw_clk_factor_get_value(&sc->p, factor_p) << sc->p.shift;
|
||||
WRITE4(clk, sc->offset, val);
|
||||
DELAY(2000);
|
||||
}
|
||||
|
||||
if ((sc->flags & AW_CLK_HAS_LOCK) != 0) {
|
||||
for (retry = 0; retry < sc->lock_retries; retry++) {
|
||||
READ4(clk, sc->offset, &val);
|
||||
if ((val & (1 << sc->lock_shift)) != 0)
|
||||
break;
|
||||
DELAY(1000);
|
||||
}
|
||||
}
|
||||
|
||||
DEVICE_UNLOCK(clk);
|
||||
}
|
||||
|
||||
static int
|
||||
aw_clk_nkmp_set_freq(struct clknode *clk, uint64_t fparent, uint64_t *fout,
|
||||
int flags, int *stop)
|
||||
{
|
||||
struct aw_clk_nkmp_sc *sc;
|
||||
uint64_t best;
|
||||
uint32_t val, best_n, best_k, best_m, best_p;
|
||||
int retry;
|
||||
|
||||
sc = clknode_get_softc(clk);
|
||||
|
||||
best = aw_clk_nkmp_find_best(sc, fparent, fout,
|
||||
&best_n, &best_k, &best_m, &best_p);
|
||||
if ((flags & CLK_SET_DRYRUN) != 0) {
|
||||
*fout = best;
|
||||
*stop = 1;
|
||||
return (0);
|
||||
}
|
||||
|
||||
if ((best < *fout) &&
|
||||
((flags & CLK_SET_ROUND_DOWN) != 0)) {
|
||||
*stop = 1;
|
||||
return (ERANGE);
|
||||
}
|
||||
if ((best > *fout) &&
|
||||
((flags & CLK_SET_ROUND_UP) != 0)) {
|
||||
*stop = 1;
|
||||
return (ERANGE);
|
||||
}
|
||||
|
||||
if ((sc->flags & AW_CLK_SCALE_CHANGE) != 0)
|
||||
aw_clk_nkmp_set_freq_scale(clk, sc,
|
||||
best_n, best_k, best_m, best_p);
|
||||
else {
|
||||
DEVICE_LOCK(clk);
|
||||
READ4(clk, sc->offset, &val);
|
||||
val &= ~sc->n.mask;
|
||||
val &= ~sc->k.mask;
|
||||
val &= ~sc->m.mask;
|
||||
val &= ~sc->p.mask;
|
||||
val |= aw_clk_factor_get_value(&sc->n, best_n) << sc->n.shift;
|
||||
val |= aw_clk_factor_get_value(&sc->k, best_k) << sc->k.shift;
|
||||
val |= aw_clk_factor_get_value(&sc->m, best_m) << sc->m.shift;
|
||||
val |= aw_clk_factor_get_value(&sc->p, best_p) << sc->p.shift;
|
||||
WRITE4(clk, sc->offset, val);
|
||||
DELAY(2000);
|
||||
|
||||
if ((sc->flags & AW_CLK_HAS_UPDATE) != 0) {
|
||||
DEVICE_LOCK(clk);
|
||||
READ4(clk, sc->offset, &val);
|
||||
val |= 1 << sc->update_shift;
|
||||
WRITE4(clk, sc->offset, val);
|
||||
DELAY(2000);
|
||||
}
|
||||
|
||||
if ((sc->flags & AW_CLK_HAS_LOCK) != 0) {
|
||||
for (retry = 0; retry < sc->lock_retries; retry++) {
|
||||
READ4(clk, sc->offset, &val);
|
||||
if ((val & (1 << sc->lock_shift)) != 0)
|
||||
break;
|
||||
DELAY(1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*fout = best;
|
||||
*stop = 1;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
aw_clk_nkmp_recalc(struct clknode *clk, uint64_t *freq)
|
||||
{
|
||||
struct aw_clk_nkmp_sc *sc;
|
||||
uint32_t val, m, n, k, p;
|
||||
|
||||
sc = clknode_get_softc(clk);
|
||||
|
||||
DEVICE_LOCK(clk);
|
||||
READ4(clk, sc->offset, &val);
|
||||
DEVICE_UNLOCK(clk);
|
||||
|
||||
n = aw_clk_get_factor(val, &sc->n);
|
||||
k = aw_clk_get_factor(val, &sc->k);
|
||||
m = aw_clk_get_factor(val, &sc->m);
|
||||
p = aw_clk_get_factor(val, &sc->p);
|
||||
|
||||
*freq = (*freq * n * k) / (m * p);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static clknode_method_t aw_nkmp_clknode_methods[] = {
|
||||
/* Device interface */
|
||||
CLKNODEMETHOD(clknode_init, aw_clk_nkmp_init),
|
||||
CLKNODEMETHOD(clknode_set_gate, aw_clk_nkmp_set_gate),
|
||||
CLKNODEMETHOD(clknode_set_mux, aw_clk_nkmp_set_mux),
|
||||
CLKNODEMETHOD(clknode_recalc_freq, aw_clk_nkmp_recalc),
|
||||
CLKNODEMETHOD(clknode_set_freq, aw_clk_nkmp_set_freq),
|
||||
CLKNODEMETHOD_END
|
||||
};
|
||||
|
||||
DEFINE_CLASS_1(aw_nkmp_clknode, aw_nkmp_clknode_class, aw_nkmp_clknode_methods,
|
||||
sizeof(struct aw_clk_nkmp_sc), clknode_class);
|
||||
|
||||
int
|
||||
aw_clk_nkmp_register(struct clkdom *clkdom, struct aw_clk_nkmp_def *clkdef)
|
||||
{
|
||||
struct clknode *clk;
|
||||
struct aw_clk_nkmp_sc *sc;
|
||||
|
||||
clk = clknode_create(clkdom, &aw_nkmp_clknode_class, &clkdef->clkdef);
|
||||
if (clk == NULL)
|
||||
return (1);
|
||||
|
||||
sc = clknode_get_softc(clk);
|
||||
|
||||
sc->offset = clkdef->offset;
|
||||
|
||||
sc->n.shift = clkdef->n.shift;
|
||||
sc->n.width = clkdef->n.width;
|
||||
sc->n.mask = ((1 << clkdef->n.width) - 1) << sc->n.shift;
|
||||
sc->n.value = clkdef->n.value;
|
||||
sc->n.flags = clkdef->n.flags;
|
||||
|
||||
sc->k.shift = clkdef->k.shift;
|
||||
sc->k.width = clkdef->k.width;
|
||||
sc->k.mask = ((1 << clkdef->k.width) - 1) << sc->k.shift;
|
||||
sc->k.value = clkdef->k.value;
|
||||
sc->k.flags = clkdef->k.flags;
|
||||
|
||||
sc->m.shift = clkdef->m.shift;
|
||||
sc->m.width = clkdef->m.width;
|
||||
sc->m.mask = ((1 << clkdef->m.width) - 1) << sc->m.shift;
|
||||
sc->m.value = clkdef->m.value;
|
||||
sc->m.flags = clkdef->m.flags;
|
||||
|
||||
sc->p.shift = clkdef->p.shift;
|
||||
sc->p.width = clkdef->p.width;
|
||||
sc->p.mask = ((1 << clkdef->p.width) - 1) << sc->p.shift;
|
||||
sc->p.value = clkdef->p.value;
|
||||
sc->p.flags = clkdef->p.flags;
|
||||
|
||||
sc->mux_shift = clkdef->mux_shift;
|
||||
sc->mux_mask = ((1 << clkdef->mux_width) - 1) << sc->mux_shift;
|
||||
|
||||
sc->gate_shift = clkdef->gate_shift;
|
||||
sc->lock_shift = clkdef->lock_shift;
|
||||
sc->lock_retries = clkdef->lock_retries;
|
||||
sc->update_shift = clkdef->update_shift;
|
||||
sc->flags = clkdef->flags;
|
||||
|
||||
clknode_register(clkdom, clk);
|
||||
|
||||
return (0);
|
||||
}
|
56
sys/arm/allwinner/clkng/aw_clk_nkmp.h
Normal file
56
sys/arm/allwinner/clkng/aw_clk_nkmp.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*-
|
||||
* Copyright (c) 2017 Emmanuel Vadot <manu@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 ``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 __AW_CLK_NKMP_H__
|
||||
#define __AW_CLK_NKMP_H__
|
||||
|
||||
#include <arm/allwinner/clkng/aw_clk.h>
|
||||
|
||||
struct aw_clk_nkmp_def {
|
||||
struct clknode_init_def clkdef;
|
||||
|
||||
uint32_t offset;
|
||||
|
||||
struct aw_clk_factor m;
|
||||
struct aw_clk_factor k;
|
||||
struct aw_clk_factor n;
|
||||
struct aw_clk_factor p;
|
||||
|
||||
uint32_t mux_shift;
|
||||
uint32_t mux_width;
|
||||
uint32_t gate_shift;
|
||||
uint32_t lock_shift;
|
||||
uint32_t lock_retries;
|
||||
uint32_t update_shift;
|
||||
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
int aw_clk_nkmp_register(struct clkdom *clkdom, struct aw_clk_nkmp_def *clkdef);
|
||||
|
||||
#endif /* __AW_CLK_NKMP_H__ */
|
361
sys/arm/allwinner/clkng/aw_clk_nm.c
Normal file
361
sys/arm/allwinner/clkng/aw_clk_nm.c
Normal file
@ -0,0 +1,361 @@
|
||||
/*-
|
||||
* Copyright (c) 2017 Emmanuel Vadot <manu@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 ``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$
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
|
||||
#include <dev/extres/clk/clk.h>
|
||||
|
||||
#include <arm/allwinner/clkng/aw_clk.h>
|
||||
#include <arm/allwinner/clkng/aw_clk_nm.h>
|
||||
|
||||
#include "clkdev_if.h"
|
||||
|
||||
/*
|
||||
* clknode for clocks matching the formula :
|
||||
*
|
||||
* clk = clkin / n / m
|
||||
*
|
||||
*/
|
||||
|
||||
struct aw_clk_nm_sc {
|
||||
uint32_t offset;
|
||||
|
||||
struct aw_clk_factor m;
|
||||
struct aw_clk_factor n;
|
||||
struct aw_clk_frac frac;
|
||||
|
||||
uint32_t mux_shift;
|
||||
uint32_t mux_mask;
|
||||
uint32_t gate_shift;
|
||||
uint32_t lock_shift;
|
||||
uint32_t lock_retries;
|
||||
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
#define WRITE4(_clk, off, val) \
|
||||
CLKDEV_WRITE_4(clknode_get_device(_clk), off, val)
|
||||
#define READ4(_clk, off, val) \
|
||||
CLKDEV_READ_4(clknode_get_device(_clk), off, val)
|
||||
#define DEVICE_LOCK(_clk) \
|
||||
CLKDEV_DEVICE_LOCK(clknode_get_device(_clk))
|
||||
#define DEVICE_UNLOCK(_clk) \
|
||||
CLKDEV_DEVICE_UNLOCK(clknode_get_device(_clk))
|
||||
|
||||
static int
|
||||
aw_clk_nm_init(struct clknode *clk, device_t dev)
|
||||
{
|
||||
struct aw_clk_nm_sc *sc;
|
||||
uint32_t val, idx;
|
||||
|
||||
sc = clknode_get_softc(clk);
|
||||
|
||||
idx = 0;
|
||||
if ((sc->flags & AW_CLK_HAS_MUX) != 0) {
|
||||
DEVICE_LOCK(clk);
|
||||
READ4(clk, sc->offset, &val);
|
||||
DEVICE_UNLOCK(clk);
|
||||
|
||||
idx = (val & sc->mux_mask) >> sc->mux_shift;
|
||||
}
|
||||
|
||||
clknode_init_parent_idx(clk, idx);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
aw_clk_nm_set_gate(struct clknode *clk, bool enable)
|
||||
{
|
||||
struct aw_clk_nm_sc *sc;
|
||||
uint32_t val;
|
||||
|
||||
sc = clknode_get_softc(clk);
|
||||
|
||||
if ((sc->flags & AW_CLK_HAS_GATE) == 0)
|
||||
return (0);
|
||||
|
||||
DEVICE_LOCK(clk);
|
||||
READ4(clk, sc->offset, &val);
|
||||
if (enable)
|
||||
val |= (1 << sc->gate_shift);
|
||||
else
|
||||
val &= ~(1 << sc->gate_shift);
|
||||
WRITE4(clk, sc->offset, val);
|
||||
DEVICE_UNLOCK(clk);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
aw_clk_nm_set_mux(struct clknode *clk, int index)
|
||||
{
|
||||
struct aw_clk_nm_sc *sc;
|
||||
uint32_t val;
|
||||
|
||||
sc = clknode_get_softc(clk);
|
||||
|
||||
if ((sc->flags & AW_CLK_HAS_MUX) != 0)
|
||||
return (0);
|
||||
|
||||
DEVICE_LOCK(clk);
|
||||
READ4(clk, sc->offset, &val);
|
||||
val &= ~(sc->mux_mask >> sc->mux_shift);
|
||||
val |= index << sc->mux_shift;
|
||||
WRITE4(clk, sc->offset, val);
|
||||
DEVICE_UNLOCK(clk);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
aw_clk_nm_find_best(struct aw_clk_nm_sc *sc, uint64_t fparent, uint64_t *fout,
|
||||
uint32_t *factor_n, uint32_t *factor_m)
|
||||
{
|
||||
uint64_t cur, best;
|
||||
uint32_t m, n, max_m, max_n, min_m, min_n;
|
||||
|
||||
*factor_n = *factor_m = 0;
|
||||
|
||||
max_m = aw_clk_factor_get_max(&sc->m);
|
||||
max_n = aw_clk_factor_get_max(&sc->n);
|
||||
min_m = aw_clk_factor_get_min(&sc->m);
|
||||
min_n = aw_clk_factor_get_min(&sc->n);
|
||||
|
||||
for (m = min_m; m <= max_m; ) {
|
||||
for (n = min_m; n <= max_n; ) {
|
||||
cur = fparent / n / m;
|
||||
if ((*fout - cur) < (*fout - best)) {
|
||||
best = cur;
|
||||
*factor_n = n;
|
||||
*factor_m = m;
|
||||
}
|
||||
|
||||
if ((sc->n.flags & AW_CLK_FACTOR_POWER_OF_TWO) != 0)
|
||||
n <<= 1;
|
||||
else
|
||||
n++;
|
||||
}
|
||||
if ((sc->m.flags & AW_CLK_FACTOR_POWER_OF_TWO) != 0)
|
||||
m <<= 1;
|
||||
else
|
||||
m++;
|
||||
}
|
||||
|
||||
return (best);
|
||||
}
|
||||
|
||||
static int
|
||||
aw_clk_nm_set_freq(struct clknode *clk, uint64_t fparent, uint64_t *fout,
|
||||
int flags, int *stop)
|
||||
{
|
||||
struct aw_clk_nm_sc *sc;
|
||||
struct clknode *p_clk;
|
||||
const char **p_names;
|
||||
uint64_t cur, best, best_frac;
|
||||
uint32_t val, m, n, best_m, best_n;
|
||||
int p_idx, best_parent, retry;
|
||||
|
||||
sc = clknode_get_softc(clk);
|
||||
|
||||
best = best_frac = cur = 0;
|
||||
best_parent = 0;
|
||||
|
||||
if ((sc->flags & AW_CLK_REPARENT) != 0) {
|
||||
p_names = clknode_get_parent_names(clk);
|
||||
for (p_idx = 0; p_idx != clknode_get_parents_num(clk); p_idx++) {
|
||||
p_clk = clknode_find_by_name(p_names[p_idx]);
|
||||
clknode_get_freq(p_clk, &fparent);
|
||||
|
||||
cur = aw_clk_nm_find_best(sc, fparent, fout, &n, &m);
|
||||
if ((*fout - cur) < (*fout - best)) {
|
||||
best = cur;
|
||||
best_parent = p_idx;
|
||||
best_n = n;
|
||||
best_m = m;
|
||||
}
|
||||
}
|
||||
|
||||
p_idx = clknode_get_parent_idx(clk);
|
||||
p_clk = clknode_get_parent(clk);
|
||||
clknode_get_freq(p_clk, &fparent);
|
||||
} else {
|
||||
if (sc->flags & AW_CLK_HAS_FRAC &&
|
||||
(*fout == sc->frac.freq0 || *fout == sc->frac.freq1))
|
||||
best = best_frac = *fout;
|
||||
|
||||
if (best == 0)
|
||||
best = aw_clk_nm_find_best(sc, fparent, fout,
|
||||
&best_n, &best_m);
|
||||
}
|
||||
|
||||
if ((flags & CLK_SET_DRYRUN) != 0) {
|
||||
*fout = best;
|
||||
*stop = 1;
|
||||
return (0);
|
||||
}
|
||||
|
||||
if ((best < *fout) &&
|
||||
((flags & CLK_SET_ROUND_DOWN) == 0)) {
|
||||
*stop = 1;
|
||||
return (ERANGE);
|
||||
}
|
||||
if ((best > *fout) &&
|
||||
((flags & CLK_SET_ROUND_UP) == 0)) {
|
||||
*stop = 1;
|
||||
return (ERANGE);
|
||||
}
|
||||
|
||||
if (p_idx != best_parent)
|
||||
clknode_set_parent_by_idx(clk, best_parent);
|
||||
|
||||
DEVICE_LOCK(clk);
|
||||
READ4(clk, sc->offset, &val);
|
||||
|
||||
if (best_frac != 0) {
|
||||
val &= ~sc->frac.mode_sel;
|
||||
if (best_frac == sc->frac.freq0)
|
||||
val &= ~sc->frac.freq_sel;
|
||||
else
|
||||
val |= sc->frac.freq_sel;
|
||||
} else {
|
||||
n = aw_clk_factor_get_value(&sc->n, best_n);
|
||||
m = aw_clk_factor_get_value(&sc->m, best_m);
|
||||
val &= ~sc->n.mask;
|
||||
val &= ~sc->m.mask;
|
||||
val |= n << sc->n.shift;
|
||||
val |= m << sc->m.shift;
|
||||
}
|
||||
|
||||
WRITE4(clk, sc->offset, val);
|
||||
DEVICE_UNLOCK(clk);
|
||||
|
||||
if ((sc->flags & AW_CLK_HAS_LOCK) != 0) {
|
||||
for (retry = 0; retry < sc->lock_retries; retry++) {
|
||||
READ4(clk, sc->offset, &val);
|
||||
if ((val & (1 << sc->lock_shift)) != 0)
|
||||
break;
|
||||
DELAY(1000);
|
||||
}
|
||||
}
|
||||
|
||||
*fout = best;
|
||||
*stop = 1;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
aw_clk_nm_recalc(struct clknode *clk, uint64_t *freq)
|
||||
{
|
||||
struct aw_clk_nm_sc *sc;
|
||||
uint32_t val, m, n;
|
||||
|
||||
sc = clknode_get_softc(clk);
|
||||
|
||||
DEVICE_LOCK(clk);
|
||||
READ4(clk, sc->offset, &val);
|
||||
DEVICE_UNLOCK(clk);
|
||||
|
||||
if (sc->flags & AW_CLK_HAS_FRAC && ((val & sc->frac.mode_sel) == 0)) {
|
||||
if (val & sc->frac.freq_sel)
|
||||
*freq = sc->frac.freq1;
|
||||
else
|
||||
*freq = sc->frac.freq0;
|
||||
} else {
|
||||
m = aw_clk_get_factor(val, &sc->m);
|
||||
n = aw_clk_get_factor(val, &sc->n);
|
||||
|
||||
*freq = *freq / n / m;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static clknode_method_t aw_nm_clknode_methods[] = {
|
||||
/* Device interface */
|
||||
CLKNODEMETHOD(clknode_init, aw_clk_nm_init),
|
||||
CLKNODEMETHOD(clknode_set_gate, aw_clk_nm_set_gate),
|
||||
CLKNODEMETHOD(clknode_set_mux, aw_clk_nm_set_mux),
|
||||
CLKNODEMETHOD(clknode_recalc_freq, aw_clk_nm_recalc),
|
||||
CLKNODEMETHOD(clknode_set_freq, aw_clk_nm_set_freq),
|
||||
CLKNODEMETHOD_END
|
||||
};
|
||||
|
||||
DEFINE_CLASS_1(aw_nm_clknode, aw_nm_clknode_class, aw_nm_clknode_methods,
|
||||
sizeof(struct aw_clk_nm_sc), clknode_class);
|
||||
|
||||
int
|
||||
aw_clk_nm_register(struct clkdom *clkdom, struct aw_clk_nm_def *clkdef)
|
||||
{
|
||||
struct clknode *clk;
|
||||
struct aw_clk_nm_sc *sc;
|
||||
|
||||
clk = clknode_create(clkdom, &aw_nm_clknode_class, &clkdef->clkdef);
|
||||
if (clk == NULL)
|
||||
return (1);
|
||||
|
||||
sc = clknode_get_softc(clk);
|
||||
|
||||
sc->offset = clkdef->offset;
|
||||
|
||||
sc->m.shift = clkdef->m.shift;
|
||||
sc->m.width = clkdef->m.width;
|
||||
sc->m.mask = ((1 << sc->m.width) - 1) << sc->m.shift;
|
||||
sc->m.value = clkdef->m.value;
|
||||
sc->m.flags = clkdef->m.flags;
|
||||
|
||||
sc->n.shift = clkdef->n.shift;
|
||||
sc->n.width = clkdef->n.width;
|
||||
sc->n.mask = ((1 << sc->n.width) - 1) << sc->n.shift;
|
||||
sc->n.value = clkdef->n.value;
|
||||
sc->n.flags = clkdef->n.flags;
|
||||
|
||||
sc->frac.freq0 = clkdef->frac.freq0;
|
||||
sc->frac.freq1 = clkdef->frac.freq1;
|
||||
sc->frac.mode_sel = 1 << clkdef->frac.mode_sel;
|
||||
sc->frac.freq_sel = 1 << clkdef->frac.freq_sel;
|
||||
|
||||
sc->mux_shift = clkdef->mux_shift;
|
||||
sc->mux_mask = ((1 << clkdef->mux_width) - 1) << sc->mux_shift;
|
||||
|
||||
sc->gate_shift = clkdef->gate_shift;
|
||||
|
||||
sc->lock_shift = clkdef->lock_shift;
|
||||
sc->lock_retries = clkdef->lock_retries;
|
||||
|
||||
sc->flags = clkdef->flags;
|
||||
|
||||
clknode_register(clkdom, clk);
|
||||
|
||||
return (0);
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 1998 Mark Newton
|
||||
* Copyright (c) 1994 Christos Zoulas
|
||||
* Copyright (c) 2017 Emmanuel Vadot <manu@freebsd.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -11,31 +10,44 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission
|
||||
*
|
||||
* 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.
|
||||
* 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 _SVR4_ULIMIT_H_
|
||||
#define _SVR4_ULIMIT_H_
|
||||
#ifndef __AW_CLK_NM_H__
|
||||
#define __AW_CLK_NM_H__
|
||||
|
||||
#define SVR4_GFILLIM 1
|
||||
#define SVR4_SFILLIM 2
|
||||
#define SVR4_GMEMLIM 3
|
||||
#define SVR4_GDESLIM 4
|
||||
#define SVR4_GTXTOFF 64
|
||||
#include <dev/extres/clk/clk.h>
|
||||
|
||||
struct aw_clk_nm_def {
|
||||
struct clknode_init_def clkdef;
|
||||
uint32_t offset;
|
||||
|
||||
#endif /* !_SVR4_ULIMIT_H_ */
|
||||
struct aw_clk_factor m;
|
||||
struct aw_clk_factor n;
|
||||
struct aw_clk_frac frac;
|
||||
|
||||
uint32_t mux_shift;
|
||||
uint32_t mux_width;
|
||||
uint32_t gate_shift;
|
||||
uint32_t lock_shift;
|
||||
uint32_t lock_retries;
|
||||
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
int aw_clk_nm_register(struct clkdom *clkdom, struct aw_clk_nm_def *clkdef);
|
||||
|
||||
#endif /* __AW_CLK_NM_H__ */
|
169
sys/arm/allwinner/clkng/aw_clk_prediv_mux.c
Normal file
169
sys/arm/allwinner/clkng/aw_clk_prediv_mux.c
Normal file
@ -0,0 +1,169 @@
|
||||
/*-
|
||||
* Copyright (c) 2017 Emmanuel Vadot <manu@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 ``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$
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
|
||||
#include <dev/extres/clk/clk.h>
|
||||
|
||||
#include <arm/allwinner/clkng/aw_clk.h>
|
||||
#include <arm/allwinner/clkng/aw_clk_prediv_mux.h>
|
||||
|
||||
#include "clkdev_if.h"
|
||||
|
||||
/*
|
||||
* clknode for clocks matching the formula :
|
||||
*
|
||||
* clk = clkin / prediv / div
|
||||
*
|
||||
* and where prediv is conditional
|
||||
*
|
||||
*/
|
||||
|
||||
struct aw_clk_prediv_mux_sc {
|
||||
uint32_t offset;
|
||||
|
||||
uint32_t mux_shift;
|
||||
uint32_t mux_mask;
|
||||
|
||||
struct aw_clk_factor div;
|
||||
struct aw_clk_factor prediv;
|
||||
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
#define WRITE4(_clk, off, val) \
|
||||
CLKDEV_WRITE_4(clknode_get_device(_clk), off, val)
|
||||
#define READ4(_clk, off, val) \
|
||||
CLKDEV_READ_4(clknode_get_device(_clk), off, val)
|
||||
#define MODIFY4(_clk, off, clr, set ) \
|
||||
CLKDEV_MODIFY_4(clknode_get_device(_clk), off, clr, set)
|
||||
#define DEVICE_LOCK(_clk) \
|
||||
CLKDEV_DEVICE_LOCK(clknode_get_device(_clk))
|
||||
#define DEVICE_UNLOCK(_clk) \
|
||||
CLKDEV_DEVICE_UNLOCK(clknode_get_device(_clk))
|
||||
|
||||
static int
|
||||
aw_clk_prediv_mux_init(struct clknode *clk, device_t dev)
|
||||
{
|
||||
clknode_init_parent_idx(clk, 0);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
aw_clk_prediv_mux_set_mux(struct clknode *clk, int index)
|
||||
{
|
||||
struct aw_clk_prediv_mux_sc *sc;
|
||||
uint32_t val;
|
||||
|
||||
sc = clknode_get_softc(clk);
|
||||
|
||||
DEVICE_LOCK(clk);
|
||||
READ4(clk, sc->offset, &val);
|
||||
val &= ~sc->mux_mask;
|
||||
val |= index << sc->mux_shift;
|
||||
WRITE4(clk, sc->offset, val);
|
||||
DEVICE_UNLOCK(clk);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
aw_clk_prediv_mux_recalc(struct clknode *clk, uint64_t *freq)
|
||||
{
|
||||
struct aw_clk_prediv_mux_sc *sc;
|
||||
uint32_t val, div, prediv;
|
||||
|
||||
sc = clknode_get_softc(clk);
|
||||
|
||||
DEVICE_LOCK(clk);
|
||||
READ4(clk, sc->offset, &val);
|
||||
DEVICE_UNLOCK(clk);
|
||||
|
||||
div = aw_clk_get_factor(val, &sc->div);
|
||||
prediv = aw_clk_get_factor(val, &sc->prediv);
|
||||
|
||||
*freq = *freq / prediv / div;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static clknode_method_t aw_prediv_mux_clknode_methods[] = {
|
||||
/* Device interface */
|
||||
CLKNODEMETHOD(clknode_init, aw_clk_prediv_mux_init),
|
||||
CLKNODEMETHOD(clknode_set_mux, aw_clk_prediv_mux_set_mux),
|
||||
CLKNODEMETHOD(clknode_recalc_freq, aw_clk_prediv_mux_recalc),
|
||||
CLKNODEMETHOD_END
|
||||
};
|
||||
|
||||
DEFINE_CLASS_1(aw_prediv_mux_clknode, aw_prediv_mux_clknode_class,
|
||||
aw_prediv_mux_clknode_methods, sizeof(struct aw_clk_prediv_mux_sc),
|
||||
clknode_class);
|
||||
|
||||
int
|
||||
aw_clk_prediv_mux_register(struct clkdom *clkdom, struct aw_clk_prediv_mux_def *clkdef)
|
||||
{
|
||||
struct clknode *clk;
|
||||
struct aw_clk_prediv_mux_sc *sc;
|
||||
|
||||
clk = clknode_create(clkdom, &aw_prediv_mux_clknode_class, &clkdef->clkdef);
|
||||
if (clk == NULL)
|
||||
return (1);
|
||||
|
||||
sc = clknode_get_softc(clk);
|
||||
|
||||
sc->offset = clkdef->offset;
|
||||
|
||||
sc->mux_shift = clkdef->mux_shift;
|
||||
sc->mux_mask = ((1 << clkdef->mux_width) - 1) << sc->mux_shift;
|
||||
|
||||
sc->div.shift = clkdef->div.shift;
|
||||
sc->div.mask = ((1 << clkdef->div.width) - 1) << sc->div.shift;
|
||||
sc->div.value = clkdef->div.value;
|
||||
sc->div.cond_shift = clkdef->div.cond_shift;
|
||||
sc->div.cond_mask = ((1 << clkdef->div.cond_width) - 1) << sc->div.shift;
|
||||
sc->div.cond_value = clkdef->div.cond_value;
|
||||
sc->div.flags = clkdef->div.flags;
|
||||
|
||||
sc->prediv.shift = clkdef->prediv.shift;
|
||||
sc->prediv.mask = ((1 << clkdef->prediv.width) - 1) << sc->prediv.shift;
|
||||
sc->prediv.value = clkdef->prediv.value;
|
||||
sc->prediv.cond_shift = clkdef->prediv.cond_shift;
|
||||
sc->prediv.cond_mask = ((1 << clkdef->prediv.cond_width) - 1) << sc->prediv.shift;
|
||||
sc->prediv.cond_value = clkdef->prediv.cond_value;
|
||||
sc->prediv.flags = clkdef->prediv.flags;
|
||||
|
||||
sc->flags = clkdef->flags;
|
||||
|
||||
clknode_register(clkdom, clk);
|
||||
|
||||
return (0);
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 1998 Mark Newton
|
||||
* Copyright (c) 2017 Emmanuel Vadot <manu@freebsd.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -10,30 +10,40 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission
|
||||
*
|
||||
* 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.
|
||||
* 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$
|
||||
*/
|
||||
|
||||
#include "opt_svr4.h"
|
||||
#ifndef __AW_CLK_PREDIV_MUX_H__
|
||||
#define __AW_CLK_PREDIV_MUX_H__
|
||||
|
||||
#if !defined(_SVR4_H)
|
||||
#define _SVR4_H
|
||||
#include <arm/allwinner/clkng/aw_clk.h>
|
||||
|
||||
extern struct sysentvec svr4_sysvec;
|
||||
struct aw_clk_prediv_mux_def {
|
||||
struct clknode_init_def clkdef;
|
||||
uint32_t offset;
|
||||
|
||||
#define COMPAT_SVR4_SOLARIS2
|
||||
uint32_t mux_shift;
|
||||
uint32_t mux_width;
|
||||
|
||||
#endif
|
||||
struct aw_clk_factor div;
|
||||
struct aw_clk_factor prediv;
|
||||
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
int aw_clk_prediv_mux_register(struct clkdom *clkdom, struct aw_clk_prediv_mux_def *clkdef);
|
||||
|
||||
#endif /* __AW_CLK_PREDIV_MUX_H__ */
|
936
sys/arm/allwinner/clkng/ccu_a31.c
Normal file
936
sys/arm/allwinner/clkng/ccu_a31.c
Normal file
@ -0,0 +1,936 @@
|
||||
/*-
|
||||
* Copyright (c) 2017 Emmanuel Vadot <manu@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 ``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$
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
|
||||
#include <dev/extres/clk/clk_div.h>
|
||||
#include <dev/extres/clk/clk_fixed.h>
|
||||
#include <dev/extres/clk/clk_mux.h>
|
||||
|
||||
#include <arm/allwinner/clkng/aw_ccung.h>
|
||||
#include <arm/allwinner/clkng/aw_clk.h>
|
||||
#include <arm/allwinner/clkng/aw_clk_nm.h>
|
||||
#include <arm/allwinner/clkng/aw_clk_nkmp.h>
|
||||
#include <arm/allwinner/clkng/aw_clk_prediv_mux.h>
|
||||
|
||||
#include "ccu_a31.h"
|
||||
|
||||
static struct aw_ccung_reset a31_ccu_resets[] = {
|
||||
CCU_RESET(A31_RST_USB_PHY0, 0xcc, 0)
|
||||
CCU_RESET(A31_RST_USB_PHY1, 0xcc, 1)
|
||||
CCU_RESET(A31_RST_USB_PHY2, 0xcc, 2)
|
||||
|
||||
CCU_RESET(A31_RST_AHB1_MIPI_DSI, 0x2c0, 1)
|
||||
CCU_RESET(A31_RST_AHB1_SS, 0x2c0, 5)
|
||||
CCU_RESET(A31_RST_AHB1_DMA, 0x2c0, 6)
|
||||
CCU_RESET(A31_RST_AHB1_MMC0, 0x2c0, 8)
|
||||
CCU_RESET(A31_RST_AHB1_MMC1, 0x2c0, 9)
|
||||
CCU_RESET(A31_RST_AHB1_MMC2, 0x2c0, 10)
|
||||
CCU_RESET(A31_RST_AHB1_MMC3, 0x2c0, 11)
|
||||
CCU_RESET(A31_RST_AHB1_NAND1, 0x2c0, 12)
|
||||
CCU_RESET(A31_RST_AHB1_NAND0, 0x2c0, 13)
|
||||
CCU_RESET(A31_RST_AHB1_SDRAM, 0x2c0, 14)
|
||||
CCU_RESET(A31_RST_AHB1_EMAC, 0x2c0, 17)
|
||||
CCU_RESET(A31_RST_AHB1_TS, 0x2c0, 18)
|
||||
CCU_RESET(A31_RST_AHB1_HSTIMER, 0x2c0, 19)
|
||||
CCU_RESET(A31_RST_AHB1_SPI0, 0x2c0, 20)
|
||||
CCU_RESET(A31_RST_AHB1_SPI1, 0x2c0, 21)
|
||||
CCU_RESET(A31_RST_AHB1_SPI2, 0x2c0, 22)
|
||||
CCU_RESET(A31_RST_AHB1_SPI3, 0x2c0, 23)
|
||||
CCU_RESET(A31_RST_AHB1_OTG, 0x2c0, 24)
|
||||
CCU_RESET(A31_RST_AHB1_EHCI0, 0x2c0, 26)
|
||||
CCU_RESET(A31_RST_AHB1_EHCI1, 0x2c0, 27)
|
||||
CCU_RESET(A31_RST_AHB1_OHCI0, 0x2c0, 29)
|
||||
CCU_RESET(A31_RST_AHB1_OHCI1, 0x2c0, 30)
|
||||
CCU_RESET(A31_RST_AHB1_OHCI2, 0x2c0, 31)
|
||||
|
||||
CCU_RESET(A31_RST_AHB1_VE, 0x2c4, 0)
|
||||
CCU_RESET(A31_RST_AHB1_LCD0, 0x2c4, 4)
|
||||
CCU_RESET(A31_RST_AHB1_LCD1, 0x2c4, 5)
|
||||
CCU_RESET(A31_RST_AHB1_CSI, 0x2c4, 8)
|
||||
CCU_RESET(A31_RST_AHB1_HDMI, 0x2c4, 11)
|
||||
CCU_RESET(A31_RST_AHB1_BE0, 0x2c4, 12)
|
||||
CCU_RESET(A31_RST_AHB1_BE1, 0x2c4, 13)
|
||||
CCU_RESET(A31_RST_AHB1_FE0, 0x2c4, 14)
|
||||
CCU_RESET(A31_RST_AHB1_FE1, 0x2c4, 15)
|
||||
CCU_RESET(A31_RST_AHB1_MP, 0x2c4, 18)
|
||||
CCU_RESET(A31_RST_AHB1_GPU, 0x2c4, 20)
|
||||
CCU_RESET(A31_RST_AHB1_DEU0, 0x2c4, 23)
|
||||
CCU_RESET(A31_RST_AHB1_DEU1, 0x2c4, 24)
|
||||
CCU_RESET(A31_RST_AHB1_DRC0, 0x2c4, 25)
|
||||
CCU_RESET(A31_RST_AHB1_DRC1, 0x2c4, 26)
|
||||
|
||||
CCU_RESET(A31_RST_AHB1_LVDS, 0x2c8, 0)
|
||||
|
||||
CCU_RESET(A31_RST_APB1_CODEC, 0x2d0, 0)
|
||||
CCU_RESET(A31_RST_APB1_SPDIF, 0x2d0, 1)
|
||||
CCU_RESET(A31_RST_APB1_DIGITAL_MIC, 0x2d0, 4)
|
||||
CCU_RESET(A31_RST_APB1_DAUDIO0, 0x2d0, 12)
|
||||
CCU_RESET(A31_RST_APB1_DAUDIO1, 0x2d0, 13)
|
||||
|
||||
CCU_RESET(A31_RST_APB2_I2C0, 0x2d8, 0)
|
||||
CCU_RESET(A31_RST_APB2_I2C1, 0x2d8, 1)
|
||||
CCU_RESET(A31_RST_APB2_I2C2, 0x2d8, 2)
|
||||
CCU_RESET(A31_RST_APB2_I2C3, 0x2d8, 3)
|
||||
CCU_RESET(A31_RST_APB2_UART0, 0x2d8, 16)
|
||||
CCU_RESET(A31_RST_APB2_UART1, 0x2d8, 17)
|
||||
CCU_RESET(A31_RST_APB2_UART2, 0x2d8, 18)
|
||||
CCU_RESET(A31_RST_APB2_UART3, 0x2d8, 19)
|
||||
CCU_RESET(A31_RST_APB2_UART4, 0x2d8, 20)
|
||||
CCU_RESET(A31_RST_APB2_UART5, 0x2d8, 21)
|
||||
};
|
||||
|
||||
static struct aw_ccung_gate a31_ccu_gates[] = {
|
||||
CCU_GATE(A31_CLK_AHB1_MIPIDSI, "ahb1-mipidsi", "ahb1", 0x60, 1)
|
||||
CCU_GATE(A31_CLK_AHB1_SS, "ahb1-ss", "ahb1", 0x60, 5)
|
||||
CCU_GATE(A31_CLK_AHB1_DMA, "ahb1-dma", "ahb1", 0x60, 6)
|
||||
CCU_GATE(A31_CLK_AHB1_MMC0, "ahb1-mmc0", "ahb1", 0x60, 8)
|
||||
CCU_GATE(A31_CLK_AHB1_MMC1, "ahb1-mmc1", "ahb1", 0x60, 9)
|
||||
CCU_GATE(A31_CLK_AHB1_MMC2, "ahb1-mmc2", "ahb1", 0x60, 10)
|
||||
CCU_GATE(A31_CLK_AHB1_MMC3, "ahb1-mmc3", "ahb1", 0x60, 11)
|
||||
CCU_GATE(A31_CLK_AHB1_NAND1, "ahb1-nand1", "ahb1", 0x60, 12)
|
||||
CCU_GATE(A31_CLK_AHB1_NAND0, "ahb1-nand0", "ahb1", 0x60, 13)
|
||||
CCU_GATE(A31_CLK_AHB1_SDRAM, "ahb1-sdram", "ahb1", 0x60, 14)
|
||||
CCU_GATE(A31_CLK_AHB1_EMAC, "ahb1-emac", "ahb1", 0x60, 17)
|
||||
CCU_GATE(A31_CLK_AHB1_TS, "ahb1-ts", "ahb1", 0x60, 18)
|
||||
CCU_GATE(A31_CLK_AHB1_HSTIMER, "ahb1-hstimer", "ahb1", 0x60, 19)
|
||||
CCU_GATE(A31_CLK_AHB1_SPI0, "ahb1-spi0", "ahb1", 0x60, 20)
|
||||
CCU_GATE(A31_CLK_AHB1_SPI1, "ahb1-spi1", "ahb1", 0x60, 21)
|
||||
CCU_GATE(A31_CLK_AHB1_SPI2, "ahb1-spi2", "ahb1", 0x60, 22)
|
||||
CCU_GATE(A31_CLK_AHB1_SPI3, "ahb1-spi3", "ahb1", 0x60, 23)
|
||||
CCU_GATE(A31_CLK_AHB1_OTG, "ahb1-otg", "ahb1", 0x60, 24)
|
||||
CCU_GATE(A31_CLK_AHB1_EHCI0, "ahb1-ehci0", "ahb1", 0x60, 26)
|
||||
CCU_GATE(A31_CLK_AHB1_EHCI1, "ahb1-ehci1", "ahb1", 0x60, 27)
|
||||
CCU_GATE(A31_CLK_AHB1_OHCI0, "ahb1-ohci0", "ahb1", 0x60, 29)
|
||||
CCU_GATE(A31_CLK_AHB1_OHCI1, "ahb1-ohci1", "ahb1", 0x60, 30)
|
||||
CCU_GATE(A31_CLK_AHB1_OHCI2, "ahb1-ohci2", "ahb1", 0x60, 31)
|
||||
CCU_GATE(A31_CLK_AHB1_VE, "ahb1-ve", "ahb1", 0x64, 0)
|
||||
CCU_GATE(A31_CLK_AHB1_LCD0, "ahb1-lcd0", "ahb1", 0x64, 4)
|
||||
CCU_GATE(A31_CLK_AHB1_LCD1, "ahb1-lcd1", "ahb1", 0x64, 5)
|
||||
CCU_GATE(A31_CLK_AHB1_CSI, "ahb1-csi", "ahb1", 0x64, 8)
|
||||
CCU_GATE(A31_CLK_AHB1_HDMI, "ahb1-hdmi", "ahb1", 0x64, 11)
|
||||
CCU_GATE(A31_CLK_AHB1_BE0, "ahb1-be0", "ahb1", 0x64, 12)
|
||||
CCU_GATE(A31_CLK_AHB1_BE1, "ahb1-be1", "ahb1", 0x64, 13)
|
||||
CCU_GATE(A31_CLK_AHB1_FE0, "ahb1-fe0", "ahb1", 0x64, 14)
|
||||
CCU_GATE(A31_CLK_AHB1_FE1, "ahb1-fe1", "ahb1", 0x64, 15)
|
||||
CCU_GATE(A31_CLK_AHB1_MP, "ahb1-mp", "ahb1", 0x64, 18)
|
||||
CCU_GATE(A31_CLK_AHB1_GPU, "ahb1-gpu", "ahb1", 0x64, 20)
|
||||
CCU_GATE(A31_CLK_AHB1_DEU0, "ahb1-deu0", "ahb1", 0x64, 23)
|
||||
CCU_GATE(A31_CLK_AHB1_DEU1, "ahb1-deu1", "ahb1", 0x64, 24)
|
||||
CCU_GATE(A31_CLK_AHB1_DRC0, "ahb1-drc0", "ahb1", 0x64, 25)
|
||||
CCU_GATE(A31_CLK_AHB1_DRC1, "ahb1-drc1", "ahb1", 0x64, 26)
|
||||
|
||||
CCU_GATE(A31_CLK_APB1_CODEC, "apb1-codec", "apb1", 0x68, 0)
|
||||
CCU_GATE(A31_CLK_APB1_SPDIF, "apb1-spdif", "apb1", 0x68, 1)
|
||||
CCU_GATE(A31_CLK_APB1_DIGITAL_MIC, "apb1-digital-mic", "apb1", 0x68, 4)
|
||||
CCU_GATE(A31_CLK_APB1_PIO, "apb1-pio", "apb1", 0x68, 5)
|
||||
CCU_GATE(A31_CLK_APB1_DAUDIO0, "apb1-daudio0", "apb1", 0x68, 12)
|
||||
CCU_GATE(A31_CLK_APB1_DAUDIO1, "apb1-daudio1", "apb1", 0x68, 13)
|
||||
|
||||
CCU_GATE(A31_CLK_APB2_I2C0, "apb2-i2c0", "apb2", 0x6c, 0)
|
||||
CCU_GATE(A31_CLK_APB2_I2C1, "apb2-i2c1", "apb2", 0x6c, 1)
|
||||
CCU_GATE(A31_CLK_APB2_I2C2, "apb2-i2c2", "apb2", 0x6c, 2)
|
||||
CCU_GATE(A31_CLK_APB2_I2C3, "apb2-i2c3", "apb2", 0x6c, 3)
|
||||
CCU_GATE(A31_CLK_APB2_UART0, "apb2-uart0", "apb2", 0x6c, 16)
|
||||
CCU_GATE(A31_CLK_APB2_UART1, "apb2-uart1", "apb2", 0x6c, 17)
|
||||
CCU_GATE(A31_CLK_APB2_UART2, "apb2-uart2", "apb2", 0x6c, 18)
|
||||
CCU_GATE(A31_CLK_APB2_UART3, "apb2-uart3", "apb2", 0x6c, 19)
|
||||
CCU_GATE(A31_CLK_APB2_UART4, "apb2-uart4", "apb2", 0x6c, 20)
|
||||
CCU_GATE(A31_CLK_APB2_UART5, "apb2-uart5", "apb2", 0x6c, 21)
|
||||
|
||||
CCU_GATE(A31_CLK_DAUDIO0, "daudio0", "daudio0mux", 0xb0, 31)
|
||||
CCU_GATE(A31_CLK_DAUDIO1, "daudio1", "daudio1mux", 0xb4, 31)
|
||||
|
||||
CCU_GATE(A31_CLK_USB_PHY0, "usb-phy0", "osc24M", 0xcc, 8)
|
||||
CCU_GATE(A31_CLK_USB_PHY1, "usb-phy1", "osc24M", 0xcc, 9)
|
||||
CCU_GATE(A31_CLK_USB_PHY2, "usb-phy2", "osc24M", 0xcc, 10)
|
||||
CCU_GATE(A31_CLK_USB_OHCI0, "usb-ohci0", "osc24M", 0xcc, 16)
|
||||
CCU_GATE(A31_CLK_USB_OHCI1, "usb-ohci1", "osc24M", 0xcc, 17)
|
||||
CCU_GATE(A31_CLK_USB_OHCI2, "usb-ohci2", "osc24M", 0xcc, 18)
|
||||
|
||||
CCU_GATE(A31_CLK_DRAM_VE, "dram-ve", "mdfs", 0x100, 0)
|
||||
CCU_GATE(A31_CLK_DRAM_CSI_ISP, "dram-csi_isp", "mdfs", 0x100, 1)
|
||||
CCU_GATE(A31_CLK_DRAM_TS, "dram-ts", "mdfs", 0x100, 3)
|
||||
CCU_GATE(A31_CLK_DRAM_DRC0, "dram-drc0", "mdfs", 0x100, 16)
|
||||
CCU_GATE(A31_CLK_DRAM_DRC1, "dram-drc1", "mdfs", 0x100, 17)
|
||||
CCU_GATE(A31_CLK_DRAM_DEU0, "dram-deu0", "mdfs", 0x100, 18)
|
||||
CCU_GATE(A31_CLK_DRAM_DEU1, "dram-deu1", "mdfs", 0x100, 19)
|
||||
CCU_GATE(A31_CLK_DRAM_FE0, "dram-fe0", "mdfs", 0x100, 24)
|
||||
CCU_GATE(A31_CLK_DRAM_FE1, "dram-fe1", "mdfs", 0x100, 25)
|
||||
CCU_GATE(A31_CLK_DRAM_BE0, "dram-be0", "mdfs", 0x100, 26)
|
||||
CCU_GATE(A31_CLK_DRAM_BE1, "dram-be1", "mdfs", 0x100, 27)
|
||||
CCU_GATE(A31_CLK_DRAM_MP, "dram-mp", "mdfs", 0x100, 28)
|
||||
|
||||
CCU_GATE(A31_CLK_CODEC, "codec", "pll_audio", 0x140, 31)
|
||||
|
||||
CCU_GATE(A31_CLK_AVS, "avs", "pll_audio", 0x144, 31)
|
||||
|
||||
CCU_GATE(A31_CLK_DIGITAL_MIC, "digital-mic", "pll_audio", 0x148, 31)
|
||||
|
||||
CCU_GATE(A31_CLK_HDMI_DDC, "hdmi-ddc", "osc24M", 0x150, 30)
|
||||
|
||||
CCU_GATE(A31_CLK_PS, "ps", "lcd1_ch1", 0x154, 31)
|
||||
};
|
||||
|
||||
static const char *pll_parents[] = {"osc24M"};
|
||||
|
||||
NKMP_CLK(pll_cpu_clk,
|
||||
A31_CLK_PLL_CPU, /* id */
|
||||
"pll_cpu", pll_parents, /* name, parents */
|
||||
0x00, /* offset */
|
||||
8, 5, 0, 0, /* n factor */
|
||||
4, 2, 0, 0, /* k factor */
|
||||
0, 2, 0, 0, /* m factor */
|
||||
0, 0, 1, AW_CLK_FACTOR_FIXED, /* p factor (fake) */
|
||||
31, /* gate */
|
||||
28, 1000, /* lock */
|
||||
AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK | AW_CLK_SCALE_CHANGE); /* flags */
|
||||
|
||||
NKMP_CLK(pll_audio_clk,
|
||||
A31_CLK_PLL_AUDIO, /* id */
|
||||
"pll_audio", pll_parents, /* name, parents */
|
||||
0x08, /* offset */
|
||||
8, 7, 0, 0, /* n factor */
|
||||
0, 0, 1, AW_CLK_FACTOR_FIXED, /* k factor (fake) */
|
||||
0, 4, 1, 0, /* m factor */
|
||||
16, 3, 1, 0, /* p factor */
|
||||
31, /* gate */
|
||||
28, 1000, /* lock */
|
||||
AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK); /* flags */
|
||||
|
||||
static const char *pll_audio_mult_parents[] = {"pll_audio"};
|
||||
FIXED_CLK(pll_audio_2x_clk,
|
||||
A31_CLK_PLL_AUDIO_2X, /* id */
|
||||
"pll_audio-2x", /* name */
|
||||
pll_audio_mult_parents, /* parent */
|
||||
0, /* freq */
|
||||
2, /* mult */
|
||||
1, /* div */
|
||||
0); /* flags */
|
||||
FIXED_CLK(pll_audio_4x_clk,
|
||||
A31_CLK_PLL_AUDIO_4X, /* id */
|
||||
"pll_audio-4x", /* name */
|
||||
pll_audio_mult_parents, /* parent */
|
||||
0, /* freq */
|
||||
4, /* mult */
|
||||
1, /* div */
|
||||
0); /* flags */
|
||||
FIXED_CLK(pll_audio_8x_clk,
|
||||
A31_CLK_PLL_AUDIO_8X, /* id */
|
||||
"pll_audio-8x", /* name */
|
||||
pll_audio_mult_parents, /* parent */
|
||||
0, /* freq */
|
||||
8, /* mult */
|
||||
1, /* div */
|
||||
0); /* flags */
|
||||
|
||||
NM_CLK_WITH_FRAC(pll_video0_clk,
|
||||
A31_CLK_PLL_VIDEO0, /* id */
|
||||
"pll_video0", pll_parents, /* name, parents */
|
||||
0x10, /* offset */
|
||||
8, 7, 0, 0, /* n factor */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
31, 28, 1000, /* gate, lock, lock retries */
|
||||
AW_CLK_HAS_LOCK, /* flags */
|
||||
270000000, 297000000, /* freq0, freq1 */
|
||||
24, 25); /* mode sel, freq sel */
|
||||
|
||||
static const char *pll_video0_2x_parents[] = {"pll_video0"};
|
||||
FIXED_CLK(pll_video0_2x_clk,
|
||||
A31_CLK_PLL_VIDEO0_2X, /* id */
|
||||
"pll_video0-2x", /* name */
|
||||
pll_video0_2x_parents, /* parent */
|
||||
0, /* freq */
|
||||
2, /* mult */
|
||||
1, /* div */
|
||||
0); /* flags */
|
||||
|
||||
NM_CLK_WITH_FRAC(pll_ve_clk,
|
||||
A31_CLK_PLL_VE, /* id */
|
||||
"pll_ve", pll_parents, /* name, parents */
|
||||
0x18, /* offset */
|
||||
8, 7, 0, 0, /* n factor */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
31, 28, 1000, /* gate, lock, lock retries */
|
||||
AW_CLK_HAS_LOCK, /* flags */
|
||||
270000000, 297000000, /* freq0, freq1 */
|
||||
24, 25); /* mode sel, freq sel */
|
||||
|
||||
NKMP_CLK_WITH_UPDATE(pll_ddr_clk,
|
||||
A31_CLK_PLL_DDR, /* id */
|
||||
"pll_ddr", pll_parents, /* name, parents */
|
||||
0x20, /* offset */
|
||||
8, 5, 0, 0, /* n factor */
|
||||
4, 2, 0, 0, /* k factor */
|
||||
0, 2, 0, 0, /* m factor */
|
||||
0, 0, 1, AW_CLK_FACTOR_FIXED, /* p factor (fake) */
|
||||
31, /* gate */
|
||||
28, 1000, /* lock */
|
||||
20, /* update */
|
||||
AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK); /* flags */
|
||||
|
||||
NKMP_CLK(pll_periph_clk,
|
||||
A31_CLK_PLL_PERIPH, /* id */
|
||||
"pll_periph", pll_parents, /* name, parents */
|
||||
0x28, /* offset */
|
||||
8, 4, 0, 0, /* n factor */
|
||||
5, 2, 1, 0, /* k factor */
|
||||
0, 0, 1, AW_CLK_FACTOR_FIXED, /* m factor (fake) */
|
||||
0, 0, 1, AW_CLK_FACTOR_FIXED, /* p factor (fake) */
|
||||
31, /* gate */
|
||||
28, 1000, /* lock */
|
||||
AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK); /* flags */
|
||||
|
||||
static const char *pll_periph_2x_parents[] = {"pll_periph"};
|
||||
FIXED_CLK(pll_periph_2x_clk,
|
||||
A31_CLK_PLL_PERIPH_2X, /* id */
|
||||
"pll_periph-2x", /* name */
|
||||
pll_periph_2x_parents, /* parent */
|
||||
0, /* freq */
|
||||
2, /* mult */
|
||||
1, /* div */
|
||||
0); /* flags */
|
||||
|
||||
NM_CLK_WITH_FRAC(pll_video1_clk,
|
||||
A31_CLK_PLL_VIDEO1, /* id */
|
||||
"pll_video1", pll_parents, /* name, parents */
|
||||
0x30, /* offset */
|
||||
8, 7, 0, 0, /* n factor */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
31, 28, 1000, /* gate, lock, lock retries */
|
||||
AW_CLK_HAS_LOCK, /* flags */
|
||||
270000000, 297000000, /* freq0, freq1 */
|
||||
24, 25); /* mode sel, freq sel */
|
||||
|
||||
static const char *pll_video1_2x_parents[] = {"pll_video1"};
|
||||
FIXED_CLK(pll_video1_2x_clk,
|
||||
A31_CLK_PLL_VIDEO1_2X, /* id */
|
||||
"pll_video1-2x", /* name */
|
||||
pll_video1_2x_parents, /* parent */
|
||||
0, /* freq */
|
||||
2, /* mult */
|
||||
1, /* div */
|
||||
0); /* flags */
|
||||
|
||||
NM_CLK_WITH_FRAC(pll_gpu_clk,
|
||||
A31_CLK_PLL_GPU, /* id */
|
||||
"pll_gpu", pll_parents, /* name, parents */
|
||||
0x38, /* offset */
|
||||
8, 7, 0, 0, /* n factor */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
31, 28, 1000, /* gate, lock, lock retries */
|
||||
AW_CLK_HAS_LOCK, /* flags */
|
||||
270000000, 297000000, /* freq0, freq1 */
|
||||
24, 25); /* mode sel, freq sel */
|
||||
|
||||
static const char *pll_mipi_parents[] = {"pll_video0", "pll_video1"};
|
||||
NKMP_CLK(pll_mipi_clk,
|
||||
A31_CLK_PLL_MIPI, /* id */
|
||||
"pll_mipi", pll_mipi_parents, /* name, parents */
|
||||
0x40, /* offset */
|
||||
8, 4, 0, 0, /* n factor */
|
||||
4, 2, 1, 0, /* k factor */
|
||||
0, 2, 0, 0, /* m factor (fake) */
|
||||
0, 0, 1, AW_CLK_FACTOR_FIXED, /* p factor (fake) */
|
||||
31, /* gate */
|
||||
28, 1000, /* lock */
|
||||
AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK); /* flags */
|
||||
|
||||
NM_CLK_WITH_FRAC(pll9_clk,
|
||||
A31_CLK_PLL9, /* id */
|
||||
"pll9", pll_parents, /* name, parents */
|
||||
0x44, /* offset */
|
||||
8, 7, 0, 0, /* n factor */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
31, 28, 1000, /* gate, lock, lock retries */
|
||||
AW_CLK_HAS_LOCK, /* flags */
|
||||
270000000, 297000000, /* freq0, freq1 */
|
||||
24, 25); /* mode sel, freq sel */
|
||||
|
||||
NM_CLK_WITH_FRAC(pll10_clk,
|
||||
A31_CLK_PLL10, /* id */
|
||||
"pll10", pll_parents, /* name, parents */
|
||||
0x48, /* offset */
|
||||
8, 7, 0, 0, /* n factor */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
31, 28, 1000, /* gate, lock, lock retries */
|
||||
AW_CLK_HAS_LOCK, /* flags */
|
||||
270000000, 297000000, /* freq0, freq1 */
|
||||
24, 25); /* mode sel, freq sel */
|
||||
|
||||
static struct clk_div_table axi_div_table[] = {
|
||||
{ .value = 0, .divider = 1, },
|
||||
{ .value = 1, .divider = 2, },
|
||||
{ .value = 2, .divider = 3, },
|
||||
{ .value = 3, .divider = 4, },
|
||||
{ .value = 4, .divider = 4, },
|
||||
{ .value = 5, .divider = 4, },
|
||||
{ .value = 6, .divider = 4, },
|
||||
{ .value = 7, .divider = 4, },
|
||||
{ },
|
||||
};
|
||||
static const char *axi_parents[] = {"cpu"};
|
||||
DIV_CLK(axi_clk,
|
||||
A31_CLK_AXI, /* id */
|
||||
"axi", axi_parents, /* name, parents */
|
||||
0x50, /* offset */
|
||||
0, 2, /* shift, mask */
|
||||
0, axi_div_table); /* flags, div table */
|
||||
|
||||
static const char *cpu_parents[] = {"osc32k", "osc24M", "pll_cpu", "pll_cpu"};
|
||||
MUX_CLK(cpu_clk,
|
||||
A31_CLK_CPU, /* id */
|
||||
"cpu", cpu_parents, /* name, parents */
|
||||
0x50, 16, 2); /* offset, shift, width */
|
||||
|
||||
static const char *ahb1_parents[] = {"osc32k", "osc24M", "axi", "pll_periph"};
|
||||
PREDIV_CLK(ahb1_clk,
|
||||
A31_CLK_AHB1, /* id */
|
||||
"ahb1", ahb1_parents, /* name, parents */
|
||||
0x54, /* offset */
|
||||
12, 2, /* mux */
|
||||
4, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* div */
|
||||
6, 2, 0, AW_CLK_FACTOR_HAS_COND, /* prediv */
|
||||
12, 2, 3); /* prediv condition */
|
||||
|
||||
static const char *apb1_parents[] = {"ahb1"};
|
||||
static struct clk_div_table apb1_div_table[] = {
|
||||
{ .value = 0, .divider = 2, },
|
||||
{ .value = 1, .divider = 2, },
|
||||
{ .value = 2, .divider = 4, },
|
||||
{ .value = 3, .divider = 8, },
|
||||
{ },
|
||||
};
|
||||
DIV_CLK(apb1_clk,
|
||||
A31_CLK_APB1, /* id */
|
||||
"apb1", apb1_parents, /* name, parents */
|
||||
0x54, /* offset */
|
||||
8, 2, /* shift, mask */
|
||||
CLK_DIV_WITH_TABLE, /* flags */
|
||||
apb1_div_table); /* div table */
|
||||
|
||||
static const char *apb2_parents[] = {"osc32k", "osc24M", "pll_periph", "pll_periph"};
|
||||
NM_CLK(apb2_clk,
|
||||
A31_CLK_APB2, /* id */
|
||||
"apb2", apb2_parents, /* name, parents */
|
||||
0x58, /* offset */
|
||||
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
|
||||
0, 5, 0, 0, /* m factor */
|
||||
24, 2, /* mux */
|
||||
0, /* gate */
|
||||
AW_CLK_HAS_MUX);
|
||||
|
||||
static const char *mod_parents[] = {"osc24M", "pll_periph"};
|
||||
NM_CLK(nand0_clk,
|
||||
A31_CLK_NAND0, "nand0", mod_parents, /* id, name, parents */
|
||||
0x80, /* offset */
|
||||
16, 3, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
24, 2, /* mux */
|
||||
31, /* gate */
|
||||
AW_CLK_HAS_GATE | AW_CLK_HAS_MUX); /* flags */
|
||||
|
||||
NM_CLK(nand1_clk,
|
||||
A31_CLK_NAND1, "nand1", mod_parents, /* id, name, parents */
|
||||
0x80, /* offset */
|
||||
16, 3, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
24, 2, /* mux */
|
||||
31, /* gate */
|
||||
AW_CLK_HAS_GATE | AW_CLK_HAS_MUX); /* flags */
|
||||
|
||||
NM_CLK(mmc0_clk,
|
||||
A31_CLK_MMC0, "mmc0", mod_parents, /* id, name, parents */
|
||||
0x88, /* offset */
|
||||
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
24, 2, /* mux */
|
||||
31, /* gate */
|
||||
AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
|
||||
AW_CLK_REPARENT); /* flags */
|
||||
|
||||
NM_CLK(mmc1_clk,
|
||||
A31_CLK_MMC1, "mmc1", mod_parents, /* id, name, parents */
|
||||
0x8c, /* offset */
|
||||
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
24, 2, /* mux */
|
||||
31, /* gate */
|
||||
AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
|
||||
AW_CLK_REPARENT); /* flags */
|
||||
|
||||
NM_CLK(mmc2_clk,
|
||||
A31_CLK_MMC2, "mmc2", mod_parents, /* id, name, parents */
|
||||
0x90, /* offset */
|
||||
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
24, 2, /* mux */
|
||||
31, /* gate */
|
||||
AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
|
||||
AW_CLK_REPARENT); /* flags */
|
||||
|
||||
NM_CLK(mmc3_clk,
|
||||
A31_CLK_MMC2, "mmc3", mod_parents, /* id, name, parents */
|
||||
0x94, /* offset */
|
||||
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
24, 2, /* mux */
|
||||
31, /* gate */
|
||||
AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
|
||||
AW_CLK_REPARENT); /* flags */
|
||||
|
||||
static const char *ts_parents[] = {"osc24M", "pll_periph"};
|
||||
NM_CLK(ts_clk,
|
||||
A31_CLK_TS, "ts", ts_parents, /* id, name, parents */
|
||||
0x98, /* offset */
|
||||
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
24, 4, /* mux */
|
||||
31, /* gate */
|
||||
AW_CLK_HAS_GATE | AW_CLK_HAS_MUX); /* flags */
|
||||
|
||||
NM_CLK(ss_clk,
|
||||
A31_CLK_SS, "ss", mod_parents, /* id, name, parents */
|
||||
0x9C, /* offset */
|
||||
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
24, 4, /* mux */
|
||||
31, /* gate */
|
||||
AW_CLK_HAS_GATE | AW_CLK_HAS_MUX); /* flags */
|
||||
|
||||
NM_CLK(spi0_clk,
|
||||
A31_CLK_SPI0, "spi0", mod_parents, /* id, name, parents */
|
||||
0xA0, /* offset */
|
||||
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
24, 4, /* mux */
|
||||
31, /* gate */
|
||||
AW_CLK_HAS_GATE | AW_CLK_HAS_MUX); /* flags */
|
||||
|
||||
NM_CLK(spi1_clk,
|
||||
A31_CLK_SPI1, "spi1", mod_parents, /* id, name, parents */
|
||||
0xA4, /* offset */
|
||||
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
24, 4, /* mux */
|
||||
31, /* gate */
|
||||
AW_CLK_HAS_GATE | AW_CLK_HAS_MUX); /* flags */
|
||||
|
||||
NM_CLK(spi2_clk,
|
||||
A31_CLK_SPI2, "spi2", mod_parents, /* id, name, parents */
|
||||
0xA8, /* offset */
|
||||
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
24, 4, /* mux */
|
||||
31, /* gate */
|
||||
AW_CLK_HAS_GATE | AW_CLK_HAS_MUX); /* flags */
|
||||
|
||||
NM_CLK(spi3_clk,
|
||||
A31_CLK_SPI3, "spi3", mod_parents, /* id, name, parents */
|
||||
0xAC, /* offset */
|
||||
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
24, 4, /* mux */
|
||||
31, /* gate */
|
||||
AW_CLK_HAS_GATE | AW_CLK_HAS_MUX); /* flags */
|
||||
|
||||
|
||||
static const char *daudio_parents[] = {"pll_audio-8x", "pll_audio-4x", "pll_audio-2x", "pll_audio"};
|
||||
MUX_CLK(daudio0mux_clk,
|
||||
0,
|
||||
"daudio0mux", daudio_parents,
|
||||
0xb0, 16, 2);
|
||||
MUX_CLK(daudio1mux_clk,
|
||||
0,
|
||||
"daudio1mux", daudio_parents,
|
||||
0xb4, 16, 2);
|
||||
|
||||
static const char *mdfs_parents[] = {"pll_ddr", "pll_periph"};
|
||||
NM_CLK(mdfs_clk,
|
||||
A31_CLK_MDFS, "mdfs", mdfs_parents, /* id, name, parents */
|
||||
0xF0, /* offset */
|
||||
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
24, 4, /* mux */
|
||||
31, /* gate */
|
||||
AW_CLK_HAS_GATE | AW_CLK_HAS_MUX); /* flags */
|
||||
|
||||
static const char *dram_parents[] = {"pll_ddr", "pll_periph"};
|
||||
NM_CLK(sdram0_clk,
|
||||
A31_CLK_SDRAM0, "sdram0", dram_parents, /* id, name, parents */
|
||||
0xF4, /* offset */
|
||||
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
4, 1, /* mux */
|
||||
0, /* gate */
|
||||
AW_CLK_HAS_MUX); /* flags */
|
||||
NM_CLK(sdram1_clk,
|
||||
A31_CLK_SDRAM1, "sdram1", dram_parents, /* id, name, parents */
|
||||
0xF4, /* offset */
|
||||
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
|
||||
8, 4, 0, 0, /* m factor */
|
||||
12, 1, /* mux */
|
||||
0, /* gate */
|
||||
AW_CLK_HAS_MUX); /* flags */
|
||||
|
||||
static const char *befe_parents[] = {"pll_video0", "pll_video1", "pll_periph-2x", "pll_gpu", "pll9", "pll10"};
|
||||
NM_CLK(be0_clk,
|
||||
A31_CLK_BE0, "be0", befe_parents, /* id, name, parents */
|
||||
0x104, /* offset */
|
||||
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
24, 3, /* mux */
|
||||
31, /* gate */
|
||||
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
|
||||
|
||||
NM_CLK(be1_clk,
|
||||
A31_CLK_BE1, "be1", befe_parents, /* id, name, parents */
|
||||
0x108, /* offset */
|
||||
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
24, 3, /* mux */
|
||||
31, /* gate */
|
||||
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
|
||||
|
||||
NM_CLK(fe0_clk,
|
||||
A31_CLK_FE0, "fe0", befe_parents, /* id, name, parents */
|
||||
0x104, /* offset */
|
||||
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
24, 3, /* mux */
|
||||
31, /* gate */
|
||||
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
|
||||
NM_CLK(fe1_clk,
|
||||
A31_CLK_FE1, "fe1", befe_parents, /* id, name, parents */
|
||||
0x108, /* offset */
|
||||
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
24, 3, /* mux */
|
||||
31, /* gate */
|
||||
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
|
||||
|
||||
static const char *mp_parents[] = {"pll_video0", "pll_video1", "pll9", "pll10"};
|
||||
NM_CLK(mp_clk,
|
||||
A31_CLK_MP, "mp", mp_parents, /* id, name, parents */
|
||||
0x108, /* offset */
|
||||
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
24, 3, /* mux */
|
||||
31, /* gate */
|
||||
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
|
||||
|
||||
static const char *lcd_ch0_parents[] = {"pll_video0", "pll_video1", "pll_video0-2x", "pll_video1-2x", "pll_mipi"};
|
||||
NM_CLK(lcd0_ch0_clk,
|
||||
A31_CLK_LCD0_CH0, "lcd0_ch0", lcd_ch0_parents, /* id, name, parents */
|
||||
0x118, /* offset */
|
||||
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
|
||||
0, 0, 1, AW_CLK_FACTOR_FIXED, /* m factor (fake )*/
|
||||
24, 3, /* mux */
|
||||
31, /* gate */
|
||||
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
|
||||
|
||||
NM_CLK(lcd1_ch0_clk,
|
||||
A31_CLK_LCD1_CH0, "lcd1_ch0", lcd_ch0_parents, /* id, name, parents */
|
||||
0x11C, /* offset */
|
||||
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
|
||||
0, 0, 1, AW_CLK_FACTOR_FIXED, /* m factor (fake )*/
|
||||
24, 3, /* mux */
|
||||
31, /* gate */
|
||||
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
|
||||
|
||||
static const char *lcd_ch1_parents[] = {"pll_video0", "pll_video1", "pll_video0-2x", "pll_video1-2x"};
|
||||
NM_CLK(lcd0_ch1_clk,
|
||||
A31_CLK_LCD0_CH1, "lcd0_ch1", lcd_ch1_parents, /* id, name, parents */
|
||||
0x12C, /* offset */
|
||||
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
24, 3, /* mux */
|
||||
31, /* gate */
|
||||
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
|
||||
|
||||
NM_CLK(lcd1_ch1_clk,
|
||||
A31_CLK_LCD1_CH1, "lcd1_ch1", lcd_ch1_parents, /* id, name, parents */
|
||||
0x130, /* offset */
|
||||
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
24, 3, /* mux */
|
||||
31, /* gate */
|
||||
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
|
||||
|
||||
/* CSI0 0x134 Need Mux table */
|
||||
/* CSI1 0x138 Need Mux table */
|
||||
|
||||
static const char *ve_parents[] = {"pll_ve"};
|
||||
NM_CLK(ve_clk,
|
||||
A31_CLK_VE, "ve", ve_parents, /* id, name, parents */
|
||||
0x13C, /* offset */
|
||||
16, 3, 0, 0, /* n factor */
|
||||
0, 0, 1, AW_CLK_FACTOR_FIXED, /* m factor (fake) */
|
||||
0, 0, /* mux */
|
||||
31, /* gate */
|
||||
AW_CLK_HAS_GATE); /* flags */
|
||||
|
||||
NM_CLK(hdmi_clk,
|
||||
A31_CLK_HDMI, "hdmi", lcd_ch1_parents, /* id, name, parents */
|
||||
0x150, /* offset */
|
||||
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
0, 0, /* mux */
|
||||
31, /* gate */
|
||||
AW_CLK_HAS_GATE); /* flags */
|
||||
|
||||
static const char *mbus_parents[] = {"osc24M", "pll_periph", "pll_ddr"};
|
||||
NM_CLK(mbus0_clk,
|
||||
A31_CLK_MBUS0, "mbus0", mbus_parents, /* id, name, parents */
|
||||
0x15C, /* offset */
|
||||
16, 2, 0, 0, /* n factor */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
24, 2, /* mux */
|
||||
31, /* gate */
|
||||
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
|
||||
|
||||
NM_CLK(mbus1_clk,
|
||||
A31_CLK_MBUS1, "mbus1", mbus_parents, /* id, name, parents */
|
||||
0x160, /* offset */
|
||||
16, 2, 0, 0, /* n factor */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
24, 2, /* mux */
|
||||
31, /* gate */
|
||||
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
|
||||
|
||||
static const char *mipi_parents[] = {"pll_video0", "pll_video1", "pll_video0-2x", "pll_video1-2x"};
|
||||
NM_CLK(mipi_dsi_clk,
|
||||
A31_CLK_MIPI_DSI, "mipi_dsi", mipi_parents, /* id, name, parents */
|
||||
0x168, /* offset */
|
||||
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
|
||||
16, 4, 0, 0, /* m factor */
|
||||
24, 2, /* mux */
|
||||
31, /* gate */
|
||||
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
|
||||
|
||||
NM_CLK(mipi_dsi_dphy_clk,
|
||||
A31_CLK_MIPI_DSI_DPHY, "mipi_dsi_dphy", mipi_parents, /* id, name, parents */
|
||||
0x168, /* offset */
|
||||
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
8, 2, /* mux */
|
||||
15, /* gate */
|
||||
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
|
||||
|
||||
NM_CLK(mipi_csi_dphy_clk,
|
||||
A31_CLK_MIPI_CSI_DPHY, "mipi_csi_dphy", mipi_parents, /* id, name, parents */
|
||||
0x16C, /* offset */
|
||||
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
8, 2, /* mux */
|
||||
15, /* gate */
|
||||
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
|
||||
|
||||
static const char *iep_parents[] = {"pll_video0", "pll_video1", "pll_periph-2x", "pll_gpu", "pll9", "pll10"};
|
||||
|
||||
NM_CLK(iep_drc0_clk,
|
||||
A31_CLK_IEP_DRC0, "iep_drc0", iep_parents, /* id, name, parents */
|
||||
0x180, /* offset */
|
||||
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
24, 2, /* mux */
|
||||
31, /* gate */
|
||||
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
|
||||
|
||||
NM_CLK(iep_drc1_clk,
|
||||
A31_CLK_IEP_DRC1, "iep_drc1", iep_parents, /* id, name, parents */
|
||||
0x184, /* offset */
|
||||
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
24, 2, /* mux */
|
||||
31, /* gate */
|
||||
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
|
||||
|
||||
NM_CLK(iep_deu0_clk,
|
||||
A31_CLK_IEP_DEU0, "iep_deu0", iep_parents, /* id, name, parents */
|
||||
0x188, /* offset */
|
||||
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
24, 2, /* mux */
|
||||
31, /* gate */
|
||||
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
|
||||
|
||||
NM_CLK(iep_deu1_clk,
|
||||
A31_CLK_IEP_DEU1, "iep_deu1", iep_parents, /* id, name, parents */
|
||||
0x18C, /* offset */
|
||||
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
24, 2, /* mux */
|
||||
31, /* gate */
|
||||
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
|
||||
|
||||
static const char *gpu_parents[] = {"pll_gpu", "pll_periph-2x", "pll_video0", "pll_video1", "pll9", "pll10"};
|
||||
PREDIV_CLK(gpu_core_clk,
|
||||
A31_CLK_GPU_CORE, /* id */
|
||||
"gpu_core", gpu_parents, /* name, parents */
|
||||
0x1A0, /* offset */
|
||||
24, 3, /* mux */
|
||||
0, 3, 0, 0, /* div */
|
||||
0, 0, 3, AW_CLK_FACTOR_HAS_COND | AW_CLK_FACTOR_FIXED, /* prediv */
|
||||
24, 2, 1); /* prediv condition */
|
||||
|
||||
PREDIV_CLK(gpu_memory_clk,
|
||||
A31_CLK_GPU_MEMORY, /* id */
|
||||
"gpu_memory", gpu_parents, /* name, parents */
|
||||
0x1A4, /* offset */
|
||||
24, 3, /* mux */
|
||||
0, 3, 0, 0, /* div */
|
||||
0, 0, 3, AW_CLK_FACTOR_HAS_COND | AW_CLK_FACTOR_FIXED, /* prediv */
|
||||
24, 2, 1); /* prediv condition */
|
||||
|
||||
PREDIV_CLK(gpu_hyd_clk,
|
||||
A31_CLK_GPU_HYD, /* id */
|
||||
"gpu_hyd", gpu_parents, /* name, parents */
|
||||
0x1A8, /* offset */
|
||||
24, 3, /* mux */
|
||||
0, 3, 0, 0, /* div */
|
||||
0, 0, 3, AW_CLK_FACTOR_HAS_COND | AW_CLK_FACTOR_FIXED, /* prediv */
|
||||
24, 2, 1); /* prediv condition */
|
||||
|
||||
/* ATS 0x1B0 */
|
||||
/* Trace 0x1B4 */
|
||||
|
||||
static struct aw_clk_nkmp_def *nkmp_clks[] = {
|
||||
&pll_cpu_clk,
|
||||
&pll_audio_clk,
|
||||
&pll_periph_clk,
|
||||
&pll_ddr_clk,
|
||||
&pll_mipi_clk,
|
||||
};
|
||||
|
||||
static struct aw_clk_nm_def *nm_clks[] = {
|
||||
&pll_video0_clk,
|
||||
&pll_ve_clk,
|
||||
&pll_video1_clk,
|
||||
&pll_gpu_clk,
|
||||
&pll9_clk,
|
||||
&pll10_clk,
|
||||
&apb2_clk,
|
||||
&nand0_clk,
|
||||
&nand1_clk,
|
||||
&mmc0_clk,
|
||||
&mmc1_clk,
|
||||
&mmc2_clk,
|
||||
&mmc3_clk,
|
||||
&ts_clk,
|
||||
&ss_clk,
|
||||
&spi0_clk,
|
||||
&spi1_clk,
|
||||
&spi2_clk,
|
||||
&spi3_clk,
|
||||
&mdfs_clk,
|
||||
&sdram0_clk,
|
||||
&sdram1_clk,
|
||||
&be0_clk,
|
||||
&be1_clk,
|
||||
&fe0_clk,
|
||||
&fe1_clk,
|
||||
&mp_clk,
|
||||
&lcd0_ch0_clk,
|
||||
&lcd1_ch0_clk,
|
||||
&lcd0_ch1_clk,
|
||||
&lcd1_ch1_clk,
|
||||
&ve_clk,
|
||||
&hdmi_clk,
|
||||
&mbus0_clk,
|
||||
&mbus1_clk,
|
||||
&mipi_dsi_clk,
|
||||
&mipi_dsi_dphy_clk,
|
||||
&mipi_csi_dphy_clk,
|
||||
&iep_drc0_clk,
|
||||
&iep_drc1_clk,
|
||||
&iep_deu0_clk,
|
||||
&iep_deu1_clk,
|
||||
};
|
||||
|
||||
static struct aw_clk_prediv_mux_def *prediv_mux_clks[] = {
|
||||
&ahb1_clk,
|
||||
&gpu_core_clk,
|
||||
&gpu_memory_clk,
|
||||
&gpu_hyd_clk,
|
||||
};
|
||||
|
||||
static struct clk_div_def *div_clks[] = {
|
||||
&axi_clk,
|
||||
&apb1_clk,
|
||||
};
|
||||
|
||||
static struct clk_mux_def *mux_clks[] = {
|
||||
&cpu_clk,
|
||||
&daudio0mux_clk,
|
||||
&daudio1mux_clk,
|
||||
};
|
||||
|
||||
static struct clk_fixed_def *fixed_factor_clks[] = {
|
||||
&pll_audio_2x_clk,
|
||||
&pll_audio_4x_clk,
|
||||
&pll_audio_8x_clk,
|
||||
&pll_video0_2x_clk,
|
||||
&pll_periph_2x_clk,
|
||||
&pll_video1_2x_clk,
|
||||
};
|
||||
|
||||
static struct aw_clk_init init_clks[] = {
|
||||
};
|
||||
|
||||
void
|
||||
ccu_a31_register_clocks(struct aw_ccung_softc *sc)
|
||||
{
|
||||
int i;
|
||||
|
||||
sc->resets = a31_ccu_resets;
|
||||
sc->nresets = nitems(a31_ccu_resets);
|
||||
sc->gates = a31_ccu_gates;
|
||||
sc->ngates = nitems(a31_ccu_gates);
|
||||
sc->clk_init = init_clks;
|
||||
sc->n_clk_init = nitems(init_clks);
|
||||
|
||||
for (i = 0; i < nitems(nkmp_clks); i++)
|
||||
aw_clk_nkmp_register(sc->clkdom, nkmp_clks[i]);
|
||||
for (i = 0; i < nitems(nm_clks); i++)
|
||||
aw_clk_nm_register(sc->clkdom, nm_clks[i]);
|
||||
for (i = 0; i < nitems(prediv_mux_clks); i++)
|
||||
aw_clk_prediv_mux_register(sc->clkdom, prediv_mux_clks[i]);
|
||||
|
||||
for (i = 0; i < nitems(mux_clks); i++)
|
||||
clknode_mux_register(sc->clkdom, mux_clks[i]);
|
||||
for (i = 0; i < nitems(div_clks); i++)
|
||||
clknode_div_register(sc->clkdom, div_clks[i]);
|
||||
for (i = 0; i < nitems(fixed_factor_clks); i++)
|
||||
clknode_fixed_register(sc->clkdom, fixed_factor_clks[i]);
|
||||
}
|
250
sys/arm/allwinner/clkng/ccu_a31.h
Normal file
250
sys/arm/allwinner/clkng/ccu_a31.h
Normal file
@ -0,0 +1,250 @@
|
||||
/*-
|
||||
* Copyright (c) 2017 Emmanuel Vadot <manu@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 ``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 __CCU_A31_H__
|
||||
#define __CCU_A31_H__
|
||||
|
||||
#define A31_RST_USB_PHY0 0
|
||||
#define A31_RST_USB_PHY1 1
|
||||
#define A31_RST_USB_PHY2 2
|
||||
#define A31_RST_AHB1_MIPI_DSI 3
|
||||
#define A31_RST_AHB1_SS 4
|
||||
#define A31_RST_AHB1_DMA 5
|
||||
#define A31_RST_AHB1_MMC0 6
|
||||
#define A31_RST_AHB1_MMC1 7
|
||||
#define A31_RST_AHB1_MMC2 8
|
||||
#define A31_RST_AHB1_MMC3 9
|
||||
#define A31_RST_AHB1_NAND1 10
|
||||
#define A31_RST_AHB1_NAND0 11
|
||||
#define A31_RST_AHB1_SDRAM 12
|
||||
#define A31_RST_AHB1_EMAC 13
|
||||
#define A31_RST_AHB1_TS 14
|
||||
#define A31_RST_AHB1_HSTIMER 15
|
||||
#define A31_RST_AHB1_SPI0 16
|
||||
#define A31_RST_AHB1_SPI1 17
|
||||
#define A31_RST_AHB1_SPI2 18
|
||||
#define A31_RST_AHB1_SPI3 19
|
||||
#define A31_RST_AHB1_OTG 20
|
||||
#define A31_RST_AHB1_EHCI0 21
|
||||
#define A31_RST_AHB1_EHCI1 22
|
||||
#define A31_RST_AHB1_OHCI0 23
|
||||
#define A31_RST_AHB1_OHCI1 24
|
||||
#define A31_RST_AHB1_OHCI2 25
|
||||
#define A31_RST_AHB1_VE 26
|
||||
#define A31_RST_AHB1_LCD0 27
|
||||
#define A31_RST_AHB1_LCD1 28
|
||||
#define A31_RST_AHB1_CSI 29
|
||||
#define A31_RST_AHB1_HDMI 30
|
||||
#define A31_RST_AHB1_BE0 31
|
||||
#define A31_RST_AHB1_BE1 32
|
||||
#define A31_RST_AHB1_FE0 33
|
||||
#define A31_RST_AHB1_FE1 34
|
||||
#define A31_RST_AHB1_MP 35
|
||||
#define A31_RST_AHB1_GPU 36
|
||||
#define A31_RST_AHB1_DEU0 37
|
||||
#define A31_RST_AHB1_DEU1 38
|
||||
#define A31_RST_AHB1_DRC0 39
|
||||
#define A31_RST_AHB1_DRC1 40
|
||||
#define A31_RST_AHB1_LVDS 41
|
||||
#define A31_RST_APB1_CODEC 42
|
||||
#define A31_RST_APB1_SPDIF 43
|
||||
#define A31_RST_APB1_DIGITAL_MIC 44
|
||||
#define A31_RST_APB1_DAUDIO0 45
|
||||
#define A31_RST_APB1_DAUDIO1 46
|
||||
#define A31_RST_APB2_I2C0 47
|
||||
#define A31_RST_APB2_I2C1 48
|
||||
#define A31_RST_APB2_I2C2 49
|
||||
#define A31_RST_APB2_I2C3 50
|
||||
#define A31_RST_APB2_UART0 51
|
||||
#define A31_RST_APB2_UART1 52
|
||||
#define A31_RST_APB2_UART2 53
|
||||
#define A31_RST_APB2_UART3 54
|
||||
#define A31_RST_APB2_UART4 55
|
||||
#define A31_RST_APB2_UART5 56
|
||||
|
||||
#define A31_CLK_PLL_CPU 0
|
||||
#define A31_CLK_PLL_AUDIO_BASE 1
|
||||
#define A31_CLK_PLL_AUDIO 2
|
||||
#define A31_CLK_PLL_AUDIO_2X 3
|
||||
#define A31_CLK_PLL_AUDIO_4X 4
|
||||
#define A31_CLK_PLL_AUDIO_8X 5
|
||||
#define A31_CLK_PLL_VIDEO0 6
|
||||
#define A31_CLK_PLL_VIDEO0_2X 7
|
||||
#define A31_CLK_PLL_VE 8
|
||||
#define A31_CLK_PLL_DDR 9
|
||||
#define A31_CLK_PLL_PERIPH 10
|
||||
#define A31_CLK_PLL_PERIPH_2X 11
|
||||
#define A31_CLK_PLL_VIDEO1 12
|
||||
#define A31_CLK_PLL_VIDEO1_2X 13
|
||||
#define A31_CLK_PLL_GPU 14
|
||||
#define A31_CLK_PLL_MIPI 15
|
||||
#define A31_CLK_PLL9 16
|
||||
#define A31_CLK_PLL10 17
|
||||
#define A31_CLK_CPU 18
|
||||
#define A31_CLK_AXI 19
|
||||
#define A31_CLK_AHB1 20
|
||||
#define A31_CLK_APB1 21
|
||||
#define A31_CLK_APB2 22
|
||||
#define A31_CLK_AHB1_MIPIDSI 23
|
||||
#define A31_CLK_AHB1_SS 24
|
||||
#define A31_CLK_AHB1_DMA 25
|
||||
#define A31_CLK_AHB1_MMC0 26
|
||||
#define A31_CLK_AHB1_MMC1 27
|
||||
#define A31_CLK_AHB1_MMC2 28
|
||||
#define A31_CLK_AHB1_MMC3 29
|
||||
#define A31_CLK_AHB1_NAND1 30
|
||||
#define A31_CLK_AHB1_NAND0 31
|
||||
#define A31_CLK_AHB1_SDRAM 32
|
||||
#define A31_CLK_AHB1_EMAC 33
|
||||
#define A31_CLK_AHB1_TS 34
|
||||
#define A31_CLK_AHB1_HSTIMER 35
|
||||
#define A31_CLK_AHB1_SPI0 36
|
||||
#define A31_CLK_AHB1_SPI1 37
|
||||
#define A31_CLK_AHB1_SPI2 38
|
||||
#define A31_CLK_AHB1_SPI3 39
|
||||
#define A31_CLK_AHB1_OTG 40
|
||||
#define A31_CLK_AHB1_EHCI0 41
|
||||
#define A31_CLK_AHB1_EHCI1 42
|
||||
#define A31_CLK_AHB1_OHCI0 43
|
||||
#define A31_CLK_AHB1_OHCI1 44
|
||||
#define A31_CLK_AHB1_OHCI2 45
|
||||
#define A31_CLK_AHB1_VE 46
|
||||
#define A31_CLK_AHB1_LCD0 47
|
||||
#define A31_CLK_AHB1_LCD1 48
|
||||
#define A31_CLK_AHB1_CSI 49
|
||||
#define A31_CLK_AHB1_HDMI 50
|
||||
#define A31_CLK_AHB1_BE0 51
|
||||
#define A31_CLK_AHB1_BE1 52
|
||||
#define A31_CLK_AHB1_FE0 53
|
||||
#define A31_CLK_AHB1_FE1 54
|
||||
#define A31_CLK_AHB1_MP 55
|
||||
#define A31_CLK_AHB1_GPU 56
|
||||
#define A31_CLK_AHB1_DEU0 57
|
||||
#define A31_CLK_AHB1_DEU1 58
|
||||
#define A31_CLK_AHB1_DRC0 59
|
||||
#define A31_CLK_AHB1_DRC1 60
|
||||
#define A31_CLK_APB1_CODEC 61
|
||||
#define A31_CLK_APB1_SPDIF 62
|
||||
#define A31_CLK_APB1_DIGITAL_MIC 63
|
||||
#define A31_CLK_APB1_PIO 64
|
||||
#define A31_CLK_APB1_DAUDIO0 65
|
||||
#define A31_CLK_APB1_DAUDIO1 66
|
||||
#define A31_CLK_APB2_I2C0 67
|
||||
#define A31_CLK_APB2_I2C1 68
|
||||
#define A31_CLK_APB2_I2C2 69
|
||||
#define A31_CLK_APB2_I2C3 70
|
||||
#define A31_CLK_APB2_UART0 71
|
||||
#define A31_CLK_APB2_UART1 72
|
||||
#define A31_CLK_APB2_UART2 73
|
||||
#define A31_CLK_APB2_UART3 74
|
||||
#define A31_CLK_APB2_UART4 75
|
||||
#define A31_CLK_APB2_UART5 76
|
||||
#define A31_CLK_NAND0 77
|
||||
#define A31_CLK_NAND1 78
|
||||
#define A31_CLK_MMC0 79
|
||||
#define A31_CLK_MMC0_SAMPLE 80
|
||||
#define A31_CLK_MMC0_OUTPUT 81
|
||||
#define A31_CLK_MMC1 82
|
||||
#define A31_CLK_MMC1_SAMPLE 83
|
||||
#define A31_CLK_MMC1_OUTPUT 84
|
||||
#define A31_CLK_MMC2 85
|
||||
#define A31_CLK_MMC2_SAMPLE 86
|
||||
#define A31_CLK_MMC2_OUTPUT 87
|
||||
#define A31_CLK_MMC3 88
|
||||
#define A31_CLK_MMC3_SAMPLE 89
|
||||
#define A31_CLK_MMC3_OUTPUT 90
|
||||
#define A31_CLK_TS 91
|
||||
#define A31_CLK_SS 92
|
||||
#define A31_CLK_SPI0 93
|
||||
#define A31_CLK_SPI1 94
|
||||
#define A31_CLK_SPI2 95
|
||||
#define A31_CLK_SPI3 96
|
||||
#define A31_CLK_DAUDIO0 97
|
||||
#define A31_CLK_DAUDIO1 98
|
||||
#define A31_CLK_SPDIF 99
|
||||
#define A31_CLK_USB_PHY0 100
|
||||
#define A31_CLK_USB_PHY1 101
|
||||
#define A31_CLK_USB_PHY2 102
|
||||
#define A31_CLK_USB_OHCI0 103
|
||||
#define A31_CLK_USB_OHCI1 104
|
||||
#define A31_CLK_USB_OHCI2 105
|
||||
#define A31_CLK_MDFS 107
|
||||
#define A31_CLK_SDRAM0 108
|
||||
#define A31_CLK_SDRAM1 109
|
||||
#define A31_CLK_DRAM_VE 110
|
||||
#define A31_CLK_DRAM_CSI_ISP 111
|
||||
#define A31_CLK_DRAM_TS 112
|
||||
#define A31_CLK_DRAM_DRC0 113
|
||||
#define A31_CLK_DRAM_DRC1 114
|
||||
#define A31_CLK_DRAM_DEU0 115
|
||||
#define A31_CLK_DRAM_DEU1 116
|
||||
#define A31_CLK_DRAM_FE0 117
|
||||
#define A31_CLK_DRAM_FE1 118
|
||||
#define A31_CLK_DRAM_BE0 119
|
||||
#define A31_CLK_DRAM_BE1 120
|
||||
#define A31_CLK_DRAM_MP 121
|
||||
#define A31_CLK_BE0 122
|
||||
#define A31_CLK_BE1 123
|
||||
#define A31_CLK_FE0 124
|
||||
#define A31_CLK_FE1 125
|
||||
#define A31_CLK_MP 126
|
||||
#define A31_CLK_LCD0_CH0 127
|
||||
#define A31_CLK_LCD1_CH0 128
|
||||
#define A31_CLK_LCD0_CH1 129
|
||||
#define A31_CLK_LCD1_CH1 130
|
||||
#define A31_CLK_CSI0_SCLK 131
|
||||
#define A31_CLK_CSI0_MCLK 132
|
||||
#define A31_CLK_CSI1_MCLK 133
|
||||
#define A31_CLK_VE 134
|
||||
#define A31_CLK_CODEC 135
|
||||
#define A31_CLK_AVS 136
|
||||
#define A31_CLK_DIGITAL_MIC 137
|
||||
#define A31_CLK_HDMI 138
|
||||
#define A31_CLK_HDMI_DDC 139
|
||||
#define A31_CLK_PS 140
|
||||
#define A31_CLK_MBUS0 141
|
||||
#define A31_CLK_MBUS1 142
|
||||
#define A31_CLK_MIPI_DSI 143
|
||||
#define A31_CLK_MIPI_DSI_DPHY 144
|
||||
#define A31_CLK_MIPI_CSI_DPHY 145
|
||||
#define A31_CLK_IEP_DRC0 146
|
||||
#define A31_CLK_IEP_DRC1 147
|
||||
#define A31_CLK_IEP_DEU0 148
|
||||
#define A31_CLK_IEP_DEU1 149
|
||||
#define A31_CLK_GPU_CORE 150
|
||||
#define A31_CLK_GPU_MEMORY 151
|
||||
#define A31_CLK_GPU_HYD 152
|
||||
#define A31_CLK_ATS 153
|
||||
#define A31_CLK_TRACE 154
|
||||
#define A31_CLK_OUT_A 155
|
||||
#define A31_CLK_OUT_B 156
|
||||
#define A31_CLK_OUT_C 157
|
||||
|
||||
void ccu_a31_register_clocks(struct aw_ccung_softc *sc);
|
||||
|
||||
#endif /* __CCU_A31 H__ */
|
720
sys/arm/allwinner/clkng/ccu_h3.c
Normal file
720
sys/arm/allwinner/clkng/ccu_h3.c
Normal file
@ -0,0 +1,720 @@
|
||||
/*-
|
||||
* Copyright (c) 2017 Emmanuel Vadot <manu@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 ``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$
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
|
||||
#include <dev/extres/clk/clk_div.h>
|
||||
#include <dev/extres/clk/clk_fixed.h>
|
||||
#include <dev/extres/clk/clk_mux.h>
|
||||
|
||||
#include <arm/allwinner/clkng/aw_ccung.h>
|
||||
#include <arm/allwinner/clkng/aw_clk.h>
|
||||
#include <arm/allwinner/clkng/aw_clk_nm.h>
|
||||
#include <arm/allwinner/clkng/aw_clk_nkmp.h>
|
||||
#include <arm/allwinner/clkng/aw_clk_prediv_mux.h>
|
||||
|
||||
#include "ccu_h3.h"
|
||||
|
||||
static struct aw_ccung_reset h3_ccu_resets[] = {
|
||||
CCU_RESET(H3_RST_USB_PHY0, 0xcc, 0)
|
||||
CCU_RESET(H3_RST_USB_PHY1, 0xcc, 1)
|
||||
CCU_RESET(H3_RST_USB_PHY2, 0xcc, 2)
|
||||
CCU_RESET(H3_RST_USB_PHY3, 0xcc, 3)
|
||||
|
||||
CCU_RESET(H3_RST_MBUS, 0xfc, 31)
|
||||
|
||||
CCU_RESET(H3_RST_BUS_CE, 0x2c0, 5)
|
||||
CCU_RESET(H3_RST_BUS_DMA, 0x2c0, 6)
|
||||
CCU_RESET(H3_RST_BUS_MMC0, 0x2c0, 8)
|
||||
CCU_RESET(H3_RST_BUS_MMC1, 0x2c0, 9)
|
||||
CCU_RESET(H3_RST_BUS_MMC2, 0x2c0, 10)
|
||||
CCU_RESET(H3_RST_BUS_NAND, 0x2c0, 13)
|
||||
CCU_RESET(H3_RST_BUS_DRAM, 0x2c0, 14)
|
||||
CCU_RESET(H3_RST_BUS_EMAC, 0x2c0, 17)
|
||||
CCU_RESET(H3_RST_BUS_TS, 0x2c0, 18)
|
||||
CCU_RESET(H3_RST_BUS_HSTIMER, 0x2c0, 19)
|
||||
CCU_RESET(H3_RST_BUS_SPI0, 0x2c0, 20)
|
||||
CCU_RESET(H3_RST_BUS_SPI1, 0x2c0, 21)
|
||||
CCU_RESET(H3_RST_BUS_OTG, 0x2c0, 23)
|
||||
CCU_RESET(H3_RST_BUS_EHCI0, 0x2c0, 24)
|
||||
CCU_RESET(H3_RST_BUS_EHCI1, 0x2c0, 25)
|
||||
CCU_RESET(H3_RST_BUS_EHCI2, 0x2c0, 26)
|
||||
CCU_RESET(H3_RST_BUS_EHCI3, 0x2c0, 27)
|
||||
CCU_RESET(H3_RST_BUS_OHCI0, 0x2c0, 28)
|
||||
CCU_RESET(H3_RST_BUS_OHCI1, 0x2c0, 29)
|
||||
CCU_RESET(H3_RST_BUS_OHCI2, 0x2c0, 30)
|
||||
CCU_RESET(H3_RST_BUS_OHCI3, 0x2c0, 31)
|
||||
|
||||
CCU_RESET(H3_RST_BUS_VE, 0x2c4, 0)
|
||||
CCU_RESET(H3_RST_BUS_TCON0, 0x2c4, 3)
|
||||
CCU_RESET(H3_RST_BUS_TCON1, 0x2c4, 4)
|
||||
CCU_RESET(H3_RST_BUS_DEINTERLACE, 0x2c4, 5)
|
||||
CCU_RESET(H3_RST_BUS_CSI, 0x2c4, 8)
|
||||
CCU_RESET(H3_RST_BUS_TVE, 0x2c4, 9)
|
||||
CCU_RESET(H3_RST_BUS_HDMI0, 0x2c4, 10)
|
||||
CCU_RESET(H3_RST_BUS_HDMI1, 0x2c4, 11)
|
||||
CCU_RESET(H3_RST_BUS_DE, 0x2c4, 12)
|
||||
CCU_RESET(H3_RST_BUS_GPU, 0x2c4, 20)
|
||||
CCU_RESET(H3_RST_BUS_MSGBOX, 0x2c4, 21)
|
||||
CCU_RESET(H3_RST_BUS_SPINLOCK, 0x2c4, 22)
|
||||
CCU_RESET(H3_RST_BUS_DBG, 0x2c4, 31)
|
||||
|
||||
CCU_RESET(H3_RST_BUS_EPHY, 0x2c8, 2)
|
||||
|
||||
CCU_RESET(H3_RST_BUS_CODEC, 0x2d0, 0)
|
||||
CCU_RESET(H3_RST_BUS_SPDIF, 0x2d0, 1)
|
||||
CCU_RESET(H3_RST_BUS_THS, 0x2d0, 8)
|
||||
CCU_RESET(H3_RST_BUS_I2S0, 0x2d0, 12)
|
||||
CCU_RESET(H3_RST_BUS_I2S1, 0x2d0, 13)
|
||||
CCU_RESET(H3_RST_BUS_I2S2, 0x2d0, 14)
|
||||
|
||||
CCU_RESET(H3_RST_BUS_I2C0, 0x2d8, 0)
|
||||
CCU_RESET(H3_RST_BUS_I2C1, 0x2d8, 1)
|
||||
CCU_RESET(H3_RST_BUS_I2C2, 0x2d8, 2)
|
||||
CCU_RESET(H3_RST_BUS_UART0, 0x2d8, 16)
|
||||
CCU_RESET(H3_RST_BUS_UART1, 0x2d8, 17)
|
||||
CCU_RESET(H3_RST_BUS_UART2, 0x2d8, 18)
|
||||
CCU_RESET(H3_RST_BUS_UART3, 0x2d8, 19)
|
||||
CCU_RESET(H3_RST_BUS_SCR, 0x2d8, 20)
|
||||
};
|
||||
|
||||
static struct aw_ccung_gate h3_ccu_gates[] = {
|
||||
CCU_GATE(H3_CLK_BUS_CE, "bus-ce", "ahb1", 0x60, 5)
|
||||
CCU_GATE(H3_CLK_BUS_DMA, "bus-dma", "ahb1", 0x60, 6)
|
||||
CCU_GATE(H3_CLK_BUS_MMC0, "bus-mmc0", "ahb1", 0x60, 8)
|
||||
CCU_GATE(H3_CLK_BUS_MMC1, "bus-mmc1", "ahb1", 0x60, 9)
|
||||
CCU_GATE(H3_CLK_BUS_MMC2, "bus-mmc2", "ahb1", 0x60, 10)
|
||||
CCU_GATE(H3_CLK_BUS_NAND, "bus-nand", "ahb1", 0x60, 13)
|
||||
CCU_GATE(H3_CLK_BUS_DRAM, "bus-dram", "ahb1", 0x60, 14)
|
||||
CCU_GATE(H3_CLK_BUS_EMAC, "bus-emac", "ahb2", 0x60, 17)
|
||||
CCU_GATE(H3_CLK_BUS_TS, "bus-ts", "ahb1", 0x60, 18)
|
||||
CCU_GATE(H3_CLK_BUS_HSTIMER, "bus-hstimer", "ahb1", 0x60, 19)
|
||||
CCU_GATE(H3_CLK_BUS_SPI0, "bus-spi0", "ahb1", 0x60, 20)
|
||||
CCU_GATE(H3_CLK_BUS_SPI1, "bus-spi1", "ahb1", 0x60, 21)
|
||||
CCU_GATE(H3_CLK_BUS_OTG, "bus-otg", "ahb1", 0x60, 23)
|
||||
CCU_GATE(H3_CLK_BUS_EHCI0, "bus-ehci0", "ahb1", 0x60, 24)
|
||||
CCU_GATE(H3_CLK_BUS_EHCI1, "bus-ehci1", "ahb2", 0x60, 25)
|
||||
CCU_GATE(H3_CLK_BUS_EHCI2, "bus-ehci2", "ahb2", 0x60, 26)
|
||||
CCU_GATE(H3_CLK_BUS_EHCI3, "bus-ehci3", "ahb2", 0x60, 27)
|
||||
CCU_GATE(H3_CLK_BUS_OHCI0, "bus-ohci0", "ahb1", 0x60, 28)
|
||||
CCU_GATE(H3_CLK_BUS_OHCI1, "bus-ohci1", "ahb2", 0x60, 29)
|
||||
CCU_GATE(H3_CLK_BUS_OHCI2, "bus-ohci2", "ahb2", 0x60, 30)
|
||||
CCU_GATE(H3_CLK_BUS_OHCI3, "bus-ohci3", "ahb2", 0x60, 31)
|
||||
|
||||
CCU_GATE(H3_CLK_BUS_VE, "bus-ve", "ahb1", 0x64, 0)
|
||||
CCU_GATE(H3_CLK_BUS_TCON0, "bus-tcon0", "ahb1", 0x64, 3)
|
||||
CCU_GATE(H3_CLK_BUS_TCON1, "bus-tcon1", "ahb1", 0x64, 4)
|
||||
CCU_GATE(H3_CLK_BUS_DEINTERLACE, "bus-deinterlace", "ahb1", 0x64, 5)
|
||||
CCU_GATE(H3_CLK_BUS_CSI, "bus-csi", "ahb1", 0x64, 8)
|
||||
CCU_GATE(H3_CLK_BUS_TVE, "bus-tve", "ahb1", 0x64, 9)
|
||||
CCU_GATE(H3_CLK_BUS_HDMI, "bus-hdmi", "ahb1", 0x64, 11)
|
||||
CCU_GATE(H3_CLK_BUS_DE, "bus-de", "ahb1", 0x64, 12)
|
||||
CCU_GATE(H3_CLK_BUS_GPU, "bus-gpu", "ahb1", 0x64, 20)
|
||||
CCU_GATE(H3_CLK_BUS_MSGBOX, "bus-msgbox", "ahb1", 0x64, 21)
|
||||
CCU_GATE(H3_CLK_BUS_SPINLOCK, "bus-spinlock", "ahb1", 0x64, 22)
|
||||
|
||||
CCU_GATE(H3_CLK_BUS_CODEC, "bus-codec", "apb1", 0x68, 0)
|
||||
CCU_GATE(H3_CLK_BUS_SPDIF, "bus-spdif", "apb1", 0x68, 1)
|
||||
CCU_GATE(H3_CLK_BUS_PIO, "bus-pio", "apb1", 0x68, 5)
|
||||
CCU_GATE(H3_CLK_BUS_THS, "bus-ths", "apb1", 0x68, 8)
|
||||
CCU_GATE(H3_CLK_BUS_I2S0, "bus-i2s0", "apb1", 0x68, 12)
|
||||
CCU_GATE(H3_CLK_BUS_I2S1, "bus-i2s1", "apb1", 0x68, 13)
|
||||
CCU_GATE(H3_CLK_BUS_I2S2, "bus-i2s2", "apb1", 0x68, 14)
|
||||
|
||||
CCU_GATE(H3_CLK_BUS_I2C0, "bus-i2c0", "apb2", 0x6c, 0)
|
||||
CCU_GATE(H3_CLK_BUS_I2C1, "bus-i2c1", "apb2", 0x6c, 1)
|
||||
CCU_GATE(H3_CLK_BUS_I2C2, "bus-i2c2", "apb2", 0x6c, 2)
|
||||
CCU_GATE(H3_CLK_BUS_UART0, "bus-uart0", "apb2", 0x6c, 16)
|
||||
CCU_GATE(H3_CLK_BUS_UART1, "bus-uart1", "apb2", 0x6c, 17)
|
||||
CCU_GATE(H3_CLK_BUS_UART2, "bus-uart2", "apb2", 0x6c, 18)
|
||||
CCU_GATE(H3_CLK_BUS_UART3, "bus-uart3", "apb2", 0x6c, 19)
|
||||
CCU_GATE(H3_CLK_BUS_SCR, "bus-scr", "apb2", 0x6c, 20)
|
||||
|
||||
CCU_GATE(H3_CLK_BUS_EPHY, "bus-ephy", "ahb1", 0x70, 0)
|
||||
CCU_GATE(H3_CLK_BUS_DBG, "bus-dbg", "ahb1", 0x70, 7)
|
||||
|
||||
CCU_GATE(H3_CLK_USBPHY0, "usb-phy0", "osc24M", 0xcc, 8)
|
||||
CCU_GATE(H3_CLK_USBPHY1, "usb-phy1", "osc24M", 0xcc, 9)
|
||||
CCU_GATE(H3_CLK_USBPHY2, "usb-phy2", "osc24M", 0xcc, 10)
|
||||
CCU_GATE(H3_CLK_USBPHY3, "usb-phy3", "osc24M", 0xcc, 11)
|
||||
CCU_GATE(H3_CLK_USBOHCI0, "usb-ohci0", "osc24M", 0xcc, 16)
|
||||
CCU_GATE(H3_CLK_USBOHCI1, "usb-ohci1", "osc24M", 0xcc, 17)
|
||||
CCU_GATE(H3_CLK_USBOHCI2, "usb-ohci2", "osc24M", 0xcc, 18)
|
||||
CCU_GATE(H3_CLK_USBOHCI3, "usb-ohci3", "osc24M", 0xcc, 19)
|
||||
|
||||
CCU_GATE(H3_CLK_THS, "ths", "thsdiv", 0x74, 31)
|
||||
CCU_GATE(H3_CLK_I2S0, "i2s0", "i2s0mux", 0xB0, 31)
|
||||
CCU_GATE(H3_CLK_I2S1, "i2s1", "i2s1mux", 0xB4, 31)
|
||||
CCU_GATE(H3_CLK_I2S2, "i2s2", "i2s2mux", 0xB8, 31)
|
||||
|
||||
CCU_GATE(H3_CLK_DRAM_VE, "dram-ve", "dram", 0x100, 0)
|
||||
CCU_GATE(H3_CLK_DRAM_CSI, "dram-csi", "dram", 0x100, 1)
|
||||
CCU_GATE(H3_CLK_DRAM_DEINTERLACE, "dram-deinterlace", "dram", 0x100, 2)
|
||||
CCU_GATE(H3_CLK_DRAM_TS, "dram-ts", "dram", 0x100, 3)
|
||||
|
||||
CCU_GATE(H3_CLK_AC_DIG, "ac-dig", "pll_audio", 0x140, 31)
|
||||
|
||||
CCU_GATE(H3_CLK_AVS, "avs", "osc24M", 0x144, 31)
|
||||
|
||||
CCU_GATE(H3_CLK_CSI_MISC, "csi-misc", "osc24M", 0x130, 31)
|
||||
|
||||
CCU_GATE(H3_CLK_HDMI_DDC, "hdmi-ddc", "osc24M", 0x154, 31)
|
||||
};
|
||||
|
||||
static const char *pll_cpux_parents[] = {"osc24M"};
|
||||
NKMP_CLK(pll_cpux_clk,
|
||||
H3_CLK_PLL_CPUX, /* id */
|
||||
"pll_cpux", pll_cpux_parents, /* name, parents */
|
||||
0x00, /* offset */
|
||||
8, 5, 0, 0, /* n factor */
|
||||
4, 2, 0, 0, /* k factor */
|
||||
0, 2, 0, 0, /* m factor */
|
||||
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* p factor */
|
||||
31, /* gate */
|
||||
28, 1000, /* lock */
|
||||
AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK | AW_CLK_SCALE_CHANGE); /* flags */
|
||||
|
||||
static const char *pll_audio_parents[] = {"osc24M"};
|
||||
NKMP_CLK(pll_audio_clk,
|
||||
H3_CLK_PLL_AUDIO, /* id */
|
||||
"pll_audio", pll_audio_parents, /* name, parents */
|
||||
0x08, /* offset */
|
||||
8, 7, 0, 0, /* n factor */
|
||||
0, 0, 1, AW_CLK_FACTOR_FIXED, /* k factor (fake) */
|
||||
0, 5, 0, 0, /* m factor */
|
||||
16, 4, 0, 0, /* p factor */
|
||||
31, /* gate */
|
||||
28, 1000, /* lock */
|
||||
AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK); /* flags */
|
||||
|
||||
static const char *pll_audio_mult_parents[] = {"pll_audio"};
|
||||
FIXED_CLK(pll_audio_2x_clk,
|
||||
H3_CLK_PLL_AUDIO_2X, /* id */
|
||||
"pll_audio-2x", /* name */
|
||||
pll_audio_mult_parents, /* parent */
|
||||
0, /* freq */
|
||||
2, /* mult */
|
||||
1, /* div */
|
||||
0); /* flags */
|
||||
FIXED_CLK(pll_audio_4x_clk,
|
||||
H3_CLK_PLL_AUDIO_4X, /* id */
|
||||
"pll_audio-4x", /* name */
|
||||
pll_audio_mult_parents, /* parent */
|
||||
0, /* freq */
|
||||
4, /* mult */
|
||||
1, /* div */
|
||||
0); /* flags */
|
||||
FIXED_CLK(pll_audio_8x_clk,
|
||||
H3_CLK_PLL_AUDIO_8X, /* id */
|
||||
"pll_audio-8x", /* name */
|
||||
pll_audio_mult_parents, /* parent */
|
||||
0, /* freq */
|
||||
8, /* mult */
|
||||
1, /* div */
|
||||
0); /* flags */
|
||||
|
||||
static const char *pll_video_parents[] = {"osc24M"};
|
||||
NM_CLK_WITH_FRAC(pll_video_clk,
|
||||
H3_CLK_PLL_VIDEO, /* id */
|
||||
"pll_video", pll_video_parents, /* name, parents */
|
||||
0x10, /* offset */
|
||||
8, 7, 0, 0, /* n factor */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
31, 28, 1000, /* gate, lock, lock retries */
|
||||
AW_CLK_HAS_LOCK, /* flags */
|
||||
270000000, 297000000, /* freq0, freq1 */
|
||||
24, 25); /* mode sel, freq sel */
|
||||
|
||||
static const char *pll_ve_parents[] = {"osc24M"};
|
||||
NM_CLK_WITH_FRAC(pll_ve_clk,
|
||||
H3_CLK_PLL_VE, /* id */
|
||||
"pll_ve", pll_ve_parents, /* name, parents */
|
||||
0x18, /* offset */
|
||||
8, 7, 0, 0, /* n factor */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
31, 28, 1000, /* gate, lock, lock retries */
|
||||
AW_CLK_HAS_LOCK, /* flags */
|
||||
270000000, 297000000, /* freq0, freq1 */
|
||||
24, 25); /* mode sel, freq sel */
|
||||
|
||||
static const char *pll_ddr_parents[] = {"osc24M"};
|
||||
NKMP_CLK_WITH_UPDATE(pll_ddr_clk,
|
||||
H3_CLK_PLL_DDR, /* id */
|
||||
"pll_ddr", pll_ddr_parents, /* name, parents */
|
||||
0x20, /* offset */
|
||||
8, 5, 0, 0, /* n factor */
|
||||
4, 2, 0, 0, /* k factor */
|
||||
0, 2, 0, 0, /* m factor */
|
||||
0, 0, 1, AW_CLK_FACTOR_FIXED, /* p factor (fake) */
|
||||
31, /* gate */
|
||||
28, 1000, /* lock */
|
||||
20, /* update */
|
||||
AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK); /* flags */
|
||||
|
||||
static const char *pll_periph0_parents[] = {"osc24M"};
|
||||
static const char *pll_periph0_2x_parents[] = {"pll_periph0"};
|
||||
NKMP_CLK(pll_periph0_clk,
|
||||
H3_CLK_PLL_PERIPH0, /* id */
|
||||
"pll_periph0", pll_periph0_parents, /* name, parents */
|
||||
0x28, /* offset */
|
||||
8, 5, 0, 0, /* n factor */
|
||||
4, 2, 0, 0, /* k factor */
|
||||
0, 0, 2, AW_CLK_FACTOR_FIXED, /* m factor (fake) */
|
||||
0, 0, 1, AW_CLK_FACTOR_FIXED, /* p factor (fake) */
|
||||
31, /* gate */
|
||||
28, 1000, /* lock */
|
||||
AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK); /* flags */
|
||||
FIXED_CLK(pll_periph0_2x_clk,
|
||||
H3_CLK_PLL_PERIPH0_2X, /* id */
|
||||
"pll_periph0-2x", /* name */
|
||||
pll_periph0_2x_parents, /* parent */
|
||||
0, /* freq */
|
||||
2, /* mult */
|
||||
1, /* div */
|
||||
0); /* flags */
|
||||
|
||||
static const char *pll_gpu_parents[] = {"osc24M"};
|
||||
NM_CLK_WITH_FRAC(pll_gpu_clk,
|
||||
H3_CLK_PLL_GPU, /* id */
|
||||
"pll_gpu", pll_gpu_parents, /* name, parents */
|
||||
0x38, /* offset */
|
||||
8, 7, 0, 0, /* n factor */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
31, 28, 1000, /* gate, lock, lock retries */
|
||||
AW_CLK_HAS_LOCK, /* flags */
|
||||
270000000, 297000000, /* freq0, freq1 */
|
||||
24, 25); /* mode sel, freq sel */
|
||||
|
||||
static const char *pll_periph1_parents[] = {"osc24M"};
|
||||
NKMP_CLK(pll_periph1_clk,
|
||||
H3_CLK_PLL_PERIPH1, /* id */
|
||||
"pll_periph1", pll_periph1_parents, /* name, parents */
|
||||
0x44, /* offset */
|
||||
8, 5, 0, 0, /* n factor */
|
||||
4, 2, 0, 0, /* k factor */
|
||||
0, 0, 2, AW_CLK_FACTOR_FIXED, /* m factor (fake) */
|
||||
0, 0, 1, AW_CLK_FACTOR_FIXED, /* p factor (fake) */
|
||||
31, /* gate */
|
||||
28, 1000, /* lock */
|
||||
AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK); /* flags */
|
||||
|
||||
static const char *pll_de_parents[] = {"osc24M"};
|
||||
NM_CLK_WITH_FRAC(pll_de_clk,
|
||||
H3_CLK_PLL_DE, /* id */
|
||||
"pll_de", pll_de_parents, /* name, parents */
|
||||
0x48, /* offset */
|
||||
8, 7, 0, 0, /* n factor */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
31, 28, 1000, /* gate, lock, lock retries */
|
||||
AW_CLK_HAS_LOCK, /* flags */
|
||||
270000000, 297000000, /* freq0, freq1 */
|
||||
24, 25); /* mode sel, freq sel */
|
||||
|
||||
static const char *cpux_parents[] = {"osc32k", "osc24M", "pll_cpux", "pll_cpux"};
|
||||
MUX_CLK(cpux_clk,
|
||||
H3_CLK_CPUX, /* id */
|
||||
"cpux", cpux_parents, /* name, parents */
|
||||
0x50, 16, 2); /* offset, shift, width */
|
||||
|
||||
static const char *axi_parents[] = {"cpux"};
|
||||
DIV_CLK(axi_clk,
|
||||
H3_CLK_AXI, /* id */
|
||||
"axi", axi_parents, /* name, parents */
|
||||
0x50, /* offset */
|
||||
0, 2, /* shift, width */
|
||||
0, NULL); /* flags, div table */
|
||||
|
||||
static const char *ahb1_parents[] = {"osc32k", "osc24M", "axi", "pll_periph0"};
|
||||
PREDIV_CLK(ahb1_clk, H3_CLK_AHB1, /* id */
|
||||
"ahb1", ahb1_parents, /* name, parents */
|
||||
0x54, /* offset */
|
||||
12, 2, /* mux */
|
||||
4, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* div */
|
||||
6, 2, 0, AW_CLK_FACTOR_HAS_COND, /* prediv */
|
||||
12, 2, 3); /* prediv condition */
|
||||
|
||||
static const char *apb1_parents[] = {"ahb1"};
|
||||
static struct clk_div_table apb1_div_table[] = {
|
||||
{ .value = 0, .divider = 2, },
|
||||
{ .value = 1, .divider = 2, },
|
||||
{ .value = 2, .divider = 4, },
|
||||
{ .value = 3, .divider = 8, },
|
||||
{ },
|
||||
};
|
||||
DIV_CLK(apb1_clk,
|
||||
H3_CLK_APB1, /* id */
|
||||
"apb1", apb1_parents, /* name, parents */
|
||||
0x54, /* offset */
|
||||
8, 2, /* shift, width */
|
||||
CLK_DIV_WITH_TABLE, /* flags */
|
||||
apb1_div_table); /* div table */
|
||||
|
||||
static const char *apb2_parents[] = {"osc32k", "osc24M", "pll_periph0", "pll_periph0"};
|
||||
NM_CLK(apb2_clk,
|
||||
H3_CLK_APB2, /* id */
|
||||
"apb2", apb2_parents, /* name, parents */
|
||||
0x58, /* offset */
|
||||
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
|
||||
0, 5, 0, 0, /* m factor */
|
||||
24, 2, /* mux */
|
||||
0, /* gate */
|
||||
AW_CLK_HAS_MUX);
|
||||
|
||||
static const char *ahb2_parents[] = {"ahb1", "pll_periph0"};
|
||||
PREDIV_CLK(ahb2_clk, H3_CLK_AHB2, /* id */
|
||||
"ahb2", ahb2_parents, /* name, parents */
|
||||
0x5c, /* offset */
|
||||
0, 2, /* mux */
|
||||
0, 0, 1, AW_CLK_FACTOR_FIXED, /* div */
|
||||
0, 0, 2, AW_CLK_FACTOR_HAS_COND | AW_CLK_FACTOR_FIXED, /* prediv */
|
||||
0, 2, 1); /* prediv condition */
|
||||
|
||||
static const char *ths_parents[] = {"osc24M"};
|
||||
static struct clk_div_table ths_div_table[] = {
|
||||
{ .value = 0, .divider = 1, },
|
||||
{ .value = 1, .divider = 2, },
|
||||
{ .value = 2, .divider = 4, },
|
||||
{ .value = 3, .divider = 6, },
|
||||
{ },
|
||||
};
|
||||
DIV_CLK(thsdiv_clk,
|
||||
0, /* id */
|
||||
"thsdiv", ths_parents, /* name, parents */
|
||||
0x74, /* offset */
|
||||
0, 2, /* shift, width */
|
||||
CLK_DIV_WITH_TABLE, /* flags */
|
||||
ths_div_table); /* div table */
|
||||
|
||||
static const char *mod_parents[] = {"osc24M", "pll_periph0", "pll_periph1"};
|
||||
NM_CLK(nand_clk,
|
||||
H3_CLK_NAND, "nand", mod_parents, /* id, name, parents */
|
||||
0x80, /* offset */
|
||||
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
24, 2, /* mux */
|
||||
31, /* gate */
|
||||
AW_CLK_HAS_GATE | AW_CLK_HAS_MUX); /* flags */
|
||||
|
||||
NM_CLK(mmc0_clk,
|
||||
H3_CLK_MMC0, "mmc0", mod_parents, /* id, name, parents */
|
||||
0x88, /* offset */
|
||||
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
24, 2, /* mux */
|
||||
31, /* gate */
|
||||
AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
|
||||
AW_CLK_REPARENT); /* flags */
|
||||
|
||||
NM_CLK(mmc1_clk,
|
||||
H3_CLK_MMC1, "mmc1", mod_parents, /* id, name, parents */
|
||||
0x8c, /* offset */
|
||||
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
24, 2, /* mux */
|
||||
31, /* gate */
|
||||
AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
|
||||
AW_CLK_REPARENT); /* flags */
|
||||
|
||||
NM_CLK(mmc2_clk,
|
||||
H3_CLK_MMC2, "mmc2", mod_parents, /* id, name, parents */
|
||||
0x90, /* offset */
|
||||
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
24, 2, /* mux */
|
||||
31, /* gate */
|
||||
AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
|
||||
AW_CLK_REPARENT); /* flags */
|
||||
|
||||
static const char *ts_parents[] = {"osc24M", "pll_periph0"};
|
||||
NM_CLK(ts_clk,
|
||||
H3_CLK_TS, "ts", ts_parents, /* id, name, parents */
|
||||
0x98, /* offset */
|
||||
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
24, 2, /* mux */
|
||||
31, /* gate */
|
||||
AW_CLK_HAS_GATE | AW_CLK_HAS_MUX); /* flags */
|
||||
|
||||
NM_CLK(ce_clk,
|
||||
H3_CLK_CE, "ce", mod_parents, /* id, name, parents */
|
||||
0x9C, /* offset */
|
||||
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
24, 2, /* mux */
|
||||
31, /* gate */
|
||||
AW_CLK_HAS_GATE | AW_CLK_HAS_MUX); /* flags */
|
||||
|
||||
NM_CLK(spi0_clk,
|
||||
H3_CLK_SPI0, "spi0", mod_parents, /* id, name, parents */
|
||||
0xA0, /* offset */
|
||||
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
24, 2, /* mux */
|
||||
31, /* gate */
|
||||
AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
|
||||
AW_CLK_REPARENT); /* flags */
|
||||
|
||||
NM_CLK(spi1_clk,
|
||||
H3_CLK_SPI1, "spi1", mod_parents, /* id, name, parents */
|
||||
0xA4, /* offset */
|
||||
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
24, 2, /* mux */
|
||||
31, /* gate */
|
||||
AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
|
||||
AW_CLK_REPARENT); /* flags */
|
||||
|
||||
static const char *i2s_parents[] = {"pll_audio-8x", "pll_audio-4x", "pll_audio-2x", "pll_audio"};
|
||||
MUX_CLK(i2s0mux_clk,
|
||||
0, "i2s0mux", i2s_parents, /* id, name, parents */
|
||||
0xb0, 16, 2); /* offset, mux shift, mux width */
|
||||
MUX_CLK(i2s1mux_clk,
|
||||
0, "i2s1mux", i2s_parents, /* id, name, parents */
|
||||
0xb4, 16, 2); /* offset, mux shift, mux width */
|
||||
MUX_CLK(i2s2mux_clk,
|
||||
0, "i2s2mux", i2s_parents, /* id, name, parents */
|
||||
0xb8, 16, 2); /* offset, mux shift, mux width */
|
||||
|
||||
static const char *spdif_parents[] = {"pll_audio"};
|
||||
NM_CLK(spdif_clk,
|
||||
H3_CLK_SPDIF, "spdif", spdif_parents, /* id, name, parents */
|
||||
0xC0, /* offset */
|
||||
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake); */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
0, 0, /* mux */
|
||||
31, /* gate */
|
||||
AW_CLK_HAS_GATE); /* flags */
|
||||
|
||||
static const char *dram_parents[] = {"pll_ddr", "pll_periph0-2x"};
|
||||
NM_CLK(dram_clk,
|
||||
H3_CLK_DRAM, "dram", dram_parents, /* id, name, parents */
|
||||
0xF4, /* offset */
|
||||
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
20, 2, /* mux */
|
||||
0, /* gate */
|
||||
AW_CLK_HAS_MUX); /* flags */
|
||||
|
||||
static const char *de_parents[] = {"pll_periph0-2x", "pll_de"};
|
||||
NM_CLK(de_clk,
|
||||
H3_CLK_DE, "de", de_parents, /* id, name, parents */
|
||||
0x104, /* offset */
|
||||
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
24, 2, /* mux */
|
||||
31, /* gate */
|
||||
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
|
||||
|
||||
static const char *tcon0_parents[] = {"pll_video"};
|
||||
NM_CLK(tcon0_clk,
|
||||
H3_CLK_TCON0, "tcon0", tcon0_parents, /* id, name, parents */
|
||||
0x118, /* offset */
|
||||
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
24, 2, /* mux */
|
||||
31, /* gate */
|
||||
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
|
||||
|
||||
static const char *tve_parents[] = {"pll_de", "pll_periph1"};
|
||||
NM_CLK(tve_clk,
|
||||
H3_CLK_TVE, "tve", tve_parents, /* id, name, parents */
|
||||
0x120, /* offset */
|
||||
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
24, 2, /* mux */
|
||||
31, /* gate */
|
||||
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
|
||||
|
||||
static const char *deinterlace_parents[] = {"pll_periph0", "pll_periph1"};
|
||||
NM_CLK(deinterlace_clk,
|
||||
H3_CLK_DEINTERLACE, "deinterlace", deinterlace_parents, /* id, name, parents */
|
||||
0x124, /* offset */
|
||||
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
24, 2, /* mux */
|
||||
31, /* gate */
|
||||
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
|
||||
|
||||
static const char *csi_sclk_parents[] = {"pll_periph0", "pll_periph1"};
|
||||
NM_CLK(csi_sclk_clk,
|
||||
H3_CLK_CSI_SCLK, "csi-sclk", csi_sclk_parents, /* id, name, parents */
|
||||
0x134, /* offset */
|
||||
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
|
||||
16, 4, 0, 0, /* m factor */
|
||||
24, 2, /* mux */
|
||||
31, /* gate */
|
||||
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
|
||||
|
||||
static const char *csi_mclk_parents[] = {"osc24M", "pll_video", "pll_periph1"};
|
||||
NM_CLK(csi_mclk_clk,
|
||||
H3_CLK_CSI_MCLK, "csi-mclk", csi_mclk_parents, /* id, name, parents */
|
||||
0x134, /* offset */
|
||||
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
8, 2, /* mux */
|
||||
15, /* gate */
|
||||
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
|
||||
|
||||
static const char *ve_parents[] = {"pll_ve"};
|
||||
NM_CLK(ve_clk,
|
||||
H3_CLK_VE, "ve", ve_parents, /* id, name, parents */
|
||||
0x13C, /* offset */
|
||||
16, 3, 0, 0, /* n factor */
|
||||
0, 0, 1, AW_CLK_FACTOR_FIXED, /* m factor (fake) */
|
||||
0, 0, /* mux */
|
||||
31, /* gate */
|
||||
AW_CLK_HAS_GATE); /* flags */
|
||||
|
||||
static const char *hdmi_parents[] = {"pll_video"};
|
||||
NM_CLK(hdmi_clk,
|
||||
H3_CLK_HDMI, "hdmi", hdmi_parents, /* id, name, parents */
|
||||
0x150, /* offset */
|
||||
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
|
||||
0, 4, 0, 0, /* m factor */
|
||||
24, 2, /* mux */
|
||||
31, /* gate */
|
||||
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
|
||||
|
||||
static const char *mbus_parents[] = {"osc24M", "pll_periph0-2x", "pll_ddr"};
|
||||
NM_CLK(mbus_clk,
|
||||
H3_CLK_MBUS, "mbus", mbus_parents, /* id, name, parents */
|
||||
0x15C, /* offset */
|
||||
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
|
||||
0, 3, 0, 0, /* m factor */
|
||||
24, 2, /* mux */
|
||||
31, /* gate */
|
||||
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
|
||||
|
||||
static const char *gpu_parents[] = {"pll_gpu"};
|
||||
NM_CLK(gpu_clk,
|
||||
H3_CLK_GPU, "gpu", gpu_parents, /* id, name, parents */
|
||||
0x1A0, /* offset */
|
||||
0, 2, 0, 0, /* n factor */
|
||||
0, 0, 1, AW_CLK_FACTOR_FIXED, /* m factor (fake) */
|
||||
0, 0, /* mux */
|
||||
31, /* gate */
|
||||
AW_CLK_HAS_GATE); /* flags */
|
||||
|
||||
static struct aw_clk_nkmp_def *nkmp_clks[] = {
|
||||
&pll_cpux_clk,
|
||||
&pll_audio_clk,
|
||||
&pll_periph0_clk,
|
||||
&pll_periph1_clk,
|
||||
&pll_ddr_clk,
|
||||
};
|
||||
|
||||
static struct aw_clk_nm_def *nm_clks[] = {
|
||||
&pll_video_clk,
|
||||
&pll_ve_clk,
|
||||
&pll_gpu_clk,
|
||||
&pll_de_clk,
|
||||
&apb2_clk,
|
||||
&nand_clk,
|
||||
&mmc0_clk,
|
||||
&mmc1_clk,
|
||||
&mmc2_clk,
|
||||
&ts_clk,
|
||||
&ce_clk,
|
||||
&spi0_clk,
|
||||
&spi1_clk,
|
||||
&spdif_clk,
|
||||
&dram_clk,
|
||||
&de_clk,
|
||||
&tcon0_clk,
|
||||
&tve_clk,
|
||||
&deinterlace_clk,
|
||||
&csi_sclk_clk,
|
||||
&csi_mclk_clk,
|
||||
&ve_clk,
|
||||
&hdmi_clk,
|
||||
&mbus_clk,
|
||||
&gpu_clk,
|
||||
};
|
||||
|
||||
static struct aw_clk_prediv_mux_def *prediv_mux_clks[] = {
|
||||
&ahb1_clk,
|
||||
&ahb2_clk,
|
||||
};
|
||||
|
||||
static struct clk_mux_def *mux_clks[] = {
|
||||
&cpux_clk,
|
||||
&i2s0mux_clk,
|
||||
&i2s1mux_clk,
|
||||
&i2s2mux_clk,
|
||||
};
|
||||
|
||||
static struct clk_div_def *div_clks[] = {
|
||||
&axi_clk,
|
||||
&apb1_clk,
|
||||
&thsdiv_clk,
|
||||
};
|
||||
|
||||
static struct clk_fixed_def *fixed_factor_clks[] = {
|
||||
&pll_periph0_2x_clk,
|
||||
&pll_audio_2x_clk,
|
||||
&pll_audio_4x_clk,
|
||||
&pll_audio_8x_clk,
|
||||
};
|
||||
|
||||
static struct aw_clk_init init_clks[] = {
|
||||
{"ahb1", "pll_periph0", 0, false},
|
||||
{"ahb2", "pll_periph0", 0, false},
|
||||
{"dram", "pll_ddr", 0, false},
|
||||
};
|
||||
|
||||
void
|
||||
ccu_h3_register_clocks(struct aw_ccung_softc *sc)
|
||||
{
|
||||
int i;
|
||||
|
||||
sc->resets = h3_ccu_resets;
|
||||
sc->nresets = nitems(h3_ccu_resets);
|
||||
sc->gates = h3_ccu_gates;
|
||||
sc->ngates = nitems(h3_ccu_gates);
|
||||
sc->clk_init = init_clks;
|
||||
sc->n_clk_init = nitems(init_clks);
|
||||
|
||||
for (i = 0; i < nitems(nkmp_clks); i++)
|
||||
aw_clk_nkmp_register(sc->clkdom, nkmp_clks[i]);
|
||||
for (i = 0; i < nitems(nm_clks); i++)
|
||||
aw_clk_nm_register(sc->clkdom, nm_clks[i]);
|
||||
for (i = 0; i < nitems(prediv_mux_clks); i++)
|
||||
aw_clk_prediv_mux_register(sc->clkdom, prediv_mux_clks[i]);
|
||||
|
||||
for (i = 0; i < nitems(mux_clks); i++)
|
||||
clknode_mux_register(sc->clkdom, mux_clks[i]);
|
||||
for (i = 0; i < nitems(div_clks); i++)
|
||||
clknode_div_register(sc->clkdom, div_clks[i]);
|
||||
for (i = 0; i < nitems(fixed_factor_clks); i++)
|
||||
clknode_fixed_register(sc->clkdom, fixed_factor_clks[i]);
|
||||
}
|
205
sys/arm/allwinner/clkng/ccu_h3.h
Normal file
205
sys/arm/allwinner/clkng/ccu_h3.h
Normal file
@ -0,0 +1,205 @@
|
||||
/*-
|
||||
* Copyright (c) 2017 Emmanuel Vadot <manu@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 ``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 __CCU_H3_H__
|
||||
#define __CCU_H3_H__
|
||||
|
||||
#define H3_RST_USB_PHY0 0
|
||||
#define H3_RST_USB_PHY1 1
|
||||
#define H3_RST_USB_PHY2 2
|
||||
#define H3_RST_USB_PHY3 3
|
||||
#define H3_RST_MBUS 4
|
||||
#define H3_RST_BUS_CE 5
|
||||
#define H3_RST_BUS_DMA 6
|
||||
#define H3_RST_BUS_MMC0 7
|
||||
#define H3_RST_BUS_MMC1 8
|
||||
#define H3_RST_BUS_MMC2 9
|
||||
#define H3_RST_BUS_NAND 10
|
||||
#define H3_RST_BUS_DRAM 11
|
||||
#define H3_RST_BUS_EMAC 12
|
||||
#define H3_RST_BUS_TS 13
|
||||
#define H3_RST_BUS_HSTIMER 14
|
||||
#define H3_RST_BUS_SPI0 15
|
||||
#define H3_RST_BUS_SPI1 16
|
||||
#define H3_RST_BUS_OTG 17
|
||||
#define H3_RST_BUS_EHCI0 18
|
||||
#define H3_RST_BUS_EHCI1 19
|
||||
#define H3_RST_BUS_EHCI2 20
|
||||
#define H3_RST_BUS_EHCI3 21
|
||||
#define H3_RST_BUS_OHCI0 22
|
||||
#define H3_RST_BUS_OHCI1 23
|
||||
#define H3_RST_BUS_OHCI2 24
|
||||
#define H3_RST_BUS_OHCI3 25
|
||||
#define H3_RST_BUS_VE 26
|
||||
#define H3_RST_BUS_TCON0 27
|
||||
#define H3_RST_BUS_TCON1 28
|
||||
#define H3_RST_BUS_DEINTERLACE 29
|
||||
#define H3_RST_BUS_CSI 30
|
||||
#define H3_RST_BUS_TVE 31
|
||||
#define H3_RST_BUS_HDMI0 32
|
||||
#define H3_RST_BUS_HDMI1 33
|
||||
#define H3_RST_BUS_DE 34
|
||||
#define H3_RST_BUS_GPU 35
|
||||
#define H3_RST_BUS_MSGBOX 36
|
||||
#define H3_RST_BUS_SPINLOCK 37
|
||||
#define H3_RST_BUS_DBG 38
|
||||
#define H3_RST_BUS_EPHY 39
|
||||
#define H3_RST_BUS_CODEC 40
|
||||
#define H3_RST_BUS_SPDIF 41
|
||||
#define H3_RST_BUS_THS 42
|
||||
#define H3_RST_BUS_I2S0 43
|
||||
#define H3_RST_BUS_I2S1 44
|
||||
#define H3_RST_BUS_I2S2 45
|
||||
#define H3_RST_BUS_I2C0 46
|
||||
#define H3_RST_BUS_I2C1 47
|
||||
#define H3_RST_BUS_I2C2 48
|
||||
#define H3_RST_BUS_UART0 49
|
||||
#define H3_RST_BUS_UART1 50
|
||||
#define H3_RST_BUS_UART2 51
|
||||
#define H3_RST_BUS_UART3 52
|
||||
#define H3_RST_BUS_SCR 53
|
||||
|
||||
#define H3_CLK_PLL_CPUX 0
|
||||
#define H3_CLK_PLL_AUDIO_BASE 1
|
||||
#define H3_CLK_PLL_AUDIO 2
|
||||
#define H3_CLK_PLL_AUDIO_2X 3
|
||||
#define H3_CLK_PLL_AUDIO_4X 4
|
||||
#define H3_CLK_PLL_AUDIO_8X 5
|
||||
#define H3_CLK_PLL_VIDEO 6
|
||||
#define H3_CLK_PLL_VE 7
|
||||
#define H3_CLK_PLL_DDR 8
|
||||
#define H3_CLK_PLL_PERIPH0 9
|
||||
#define H3_CLK_PLL_PERIPH0_2X 10
|
||||
#define H3_CLK_PLL_GPU 11
|
||||
#define H3_CLK_PLL_PERIPH1 12
|
||||
#define H3_CLK_PLL_DE 13
|
||||
#define H3_CLK_CPUX 14
|
||||
#define H3_CLK_AXI 15
|
||||
#define H3_CLK_AHB1 16
|
||||
#define H3_CLK_APB1 17
|
||||
#define H3_CLK_APB2 18
|
||||
#define H3_CLK_AHB2 19
|
||||
#define H3_CLK_BUS_CE 20
|
||||
#define H3_CLK_BUS_DMA 21
|
||||
#define H3_CLK_BUS_MMC0 22
|
||||
#define H3_CLK_BUS_MMC1 23
|
||||
#define H3_CLK_BUS_MMC2 24
|
||||
#define H3_CLK_BUS_NAND 25
|
||||
#define H3_CLK_BUS_DRAM 26
|
||||
#define H3_CLK_BUS_EMAC 27
|
||||
#define H3_CLK_BUS_TS 28
|
||||
#define H3_CLK_BUS_HSTIMER 29
|
||||
#define H3_CLK_BUS_SPI0 30
|
||||
#define H3_CLK_BUS_SPI1 31
|
||||
#define H3_CLK_BUS_OTG 32
|
||||
#define H3_CLK_BUS_EHCI0 33
|
||||
#define H3_CLK_BUS_EHCI1 34
|
||||
#define H3_CLK_BUS_EHCI2 35
|
||||
#define H3_CLK_BUS_EHCI3 36
|
||||
#define H3_CLK_BUS_OHCI0 37
|
||||
#define H3_CLK_BUS_OHCI1 38
|
||||
#define H3_CLK_BUS_OHCI2 39
|
||||
#define H3_CLK_BUS_OHCI3 40
|
||||
#define H3_CLK_BUS_VE 41
|
||||
#define H3_CLK_BUS_TCON0 42
|
||||
#define H3_CLK_BUS_TCON1 43
|
||||
#define H3_CLK_BUS_DEINTERLACE 44
|
||||
#define H3_CLK_BUS_CSI 45
|
||||
#define H3_CLK_BUS_TVE 46
|
||||
#define H3_CLK_BUS_HDMI 47
|
||||
#define H3_CLK_BUS_DE 48
|
||||
#define H3_CLK_BUS_GPU 49
|
||||
#define H3_CLK_BUS_MSGBOX 50
|
||||
#define H3_CLK_BUS_SPINLOCK 51
|
||||
#define H3_CLK_BUS_CODEC 52
|
||||
#define H3_CLK_BUS_SPDIF 53
|
||||
#define H3_CLK_BUS_PIO 54
|
||||
#define H3_CLK_BUS_THS 55
|
||||
#define H3_CLK_BUS_I2S0 56
|
||||
#define H3_CLK_BUS_I2S1 57
|
||||
#define H3_CLK_BUS_I2S2 58
|
||||
#define H3_CLK_BUS_I2C0 59
|
||||
#define H3_CLK_BUS_I2C1 60
|
||||
#define H3_CLK_BUS_I2C2 61
|
||||
#define H3_CLK_BUS_UART0 62
|
||||
#define H3_CLK_BUS_UART1 63
|
||||
#define H3_CLK_BUS_UART2 64
|
||||
#define H3_CLK_BUS_UART3 65
|
||||
#define H3_CLK_BUS_SCR 66
|
||||
#define H3_CLK_BUS_EPHY 67
|
||||
#define H3_CLK_BUS_DBG 68
|
||||
#define H3_CLK_THS 69
|
||||
#define H3_CLK_NAND 70
|
||||
#define H3_CLK_MMC0 71
|
||||
#define H3_CLK_MMC0_SAMPLE 72
|
||||
#define H3_CLK_MMC0_OUTPUT 73
|
||||
#define H3_CLK_MMC1 74
|
||||
#define H3_CLK_MMC1_SAMPLE 75
|
||||
#define H3_CLK_MMC1_OUTPUT 76
|
||||
#define H3_CLK_MMC2 77
|
||||
#define H3_CLK_MMC2_SAMPLE 78
|
||||
#define H3_CLK_MMC2_OUTPUT 79
|
||||
#define H3_CLK_TS 80
|
||||
#define H3_CLK_CE 81
|
||||
#define H3_CLK_SPI0 82
|
||||
#define H3_CLK_SPI1 83
|
||||
#define H3_CLK_I2S0 84
|
||||
#define H3_CLK_I2S1 85
|
||||
#define H3_CLK_I2S2 86
|
||||
#define H3_CLK_SPDIF 87
|
||||
#define H3_CLK_USBPHY0 88
|
||||
#define H3_CLK_USBPHY1 89
|
||||
#define H3_CLK_USBPHY2 90
|
||||
#define H3_CLK_USBPHY3 91
|
||||
#define H3_CLK_USBOHCI0 92
|
||||
#define H3_CLK_USBOHCI1 93
|
||||
#define H3_CLK_USBOHCI2 94
|
||||
#define H3_CLK_USBOHCI3 95
|
||||
#define H3_CLK_DRAM 96
|
||||
#define H3_CLK_DRAM_VE 97
|
||||
#define H3_CLK_DRAM_CSI 98
|
||||
#define H3_CLK_DRAM_DEINTERLACE 99
|
||||
#define H3_CLK_DRAM_TS 100
|
||||
#define H3_CLK_DE 101
|
||||
#define H3_CLK_TCON0 102
|
||||
#define H3_CLK_TVE 103
|
||||
#define H3_CLK_DEINTERLACE 104
|
||||
#define H3_CLK_CSI_MISC 105
|
||||
#define H3_CLK_CSI_SCLK 106
|
||||
#define H3_CLK_CSI_MCLK 107
|
||||
#define H3_CLK_VE 108
|
||||
#define H3_CLK_AC_DIG 109
|
||||
#define H3_CLK_AVS 110
|
||||
#define H3_CLK_HDMI 111
|
||||
#define H3_CLK_HDMI_DDC 112
|
||||
#define H3_CLK_MBUS 113
|
||||
#define H3_CLK_GPU 114
|
||||
|
||||
void ccu_h3_register_clocks(struct aw_ccung_softc *sc);
|
||||
|
||||
#endif /* __CCU_H3_H__ */
|
@ -56,3 +56,8 @@ arm/allwinner/clk/aw_oscclk.c standard
|
||||
arm/allwinner/clk/aw_pll.c standard
|
||||
arm/allwinner/clk/aw_thsclk.c standard
|
||||
arm/allwinner/clk/aw_usbclk.c standard
|
||||
|
||||
arm/allwinner/clkng/aw_ccung.c standard
|
||||
arm/allwinner/clkng/aw_clk_nkmp.c standard
|
||||
arm/allwinner/clkng/aw_clk_nm.c standard
|
||||
arm/allwinner/clkng/aw_clk_prediv_mux.c standard
|
||||
|
@ -1,4 +1,5 @@
|
||||
# $FreeBSD$
|
||||
|
||||
arm/allwinner/clkng/ccu_h3.c standard
|
||||
arm/allwinner/h3/h3_padconf.c standard
|
||||
arm/allwinner/h3/h3_r_padconf.c standard
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
|
||||
* Copyright (c) 2014-2017 Ruslan Bukin <br@bsdpad.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include "platform_if.h"
|
||||
|
||||
#if defined(SOC_ALTERA_CYCLONE5)
|
||||
static int
|
||||
socfpga_devmap_init(platform_t plat)
|
||||
{
|
||||
@ -82,25 +83,47 @@ socfpga_devmap_init(platform_t plat)
|
||||
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(SOC_ALTERA_ARRIA10)
|
||||
static int
|
||||
socfpga_a10_devmap_init(platform_t plat)
|
||||
{
|
||||
|
||||
/* UART */
|
||||
devmap_add_entry(0xffc00000, 0x100000);
|
||||
|
||||
/* USB OTG */
|
||||
devmap_add_entry(0xffb00000, 0x100000);
|
||||
|
||||
/* dwmmc */
|
||||
devmap_add_entry(0xff800000, 0x100000);
|
||||
|
||||
/* scu */
|
||||
devmap_add_entry(0xfff00000, 0x100000);
|
||||
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
socfpga_cpu_reset(platform_t plat)
|
||||
_socfpga_cpu_reset(bus_size_t reg)
|
||||
{
|
||||
uint32_t paddr;
|
||||
bus_addr_t vaddr;
|
||||
phandle_t node;
|
||||
|
||||
if (rstmgr_warmreset() == 0)
|
||||
if (rstmgr_warmreset(reg) == 0)
|
||||
goto end;
|
||||
|
||||
node = OF_finddevice("rstmgr");
|
||||
node = OF_finddevice("/soc/rstmgr");
|
||||
if (node == -1)
|
||||
goto end;
|
||||
|
||||
if ((OF_getencprop(node, "reg", &paddr, sizeof(paddr))) > 0) {
|
||||
if (bus_space_map(fdtbus_bs_tag, paddr, 0x8, 0, &vaddr) == 0) {
|
||||
bus_space_write_4(fdtbus_bs_tag, vaddr,
|
||||
RSTMGR_CTRL, CTRL_SWWARMRSTREQ);
|
||||
reg, CTRL_SWWARMRSTREQ);
|
||||
}
|
||||
}
|
||||
|
||||
@ -108,16 +131,46 @@ end:
|
||||
while (1);
|
||||
}
|
||||
|
||||
#if defined(SOC_ALTERA_CYCLONE5)
|
||||
static void
|
||||
socfpga_cpu_reset(platform_t plat)
|
||||
{
|
||||
|
||||
_socfpga_cpu_reset(RSTMGR_CTRL);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(SOC_ALTERA_ARRIA10)
|
||||
static void
|
||||
socfpga_a10_cpu_reset(platform_t plat)
|
||||
{
|
||||
|
||||
_socfpga_cpu_reset(RSTMGR_A10_CTRL);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(SOC_ALTERA_CYCLONE5)
|
||||
static platform_method_t socfpga_methods[] = {
|
||||
PLATFORMMETHOD(platform_devmap_init, socfpga_devmap_init),
|
||||
PLATFORMMETHOD(platform_cpu_reset, socfpga_cpu_reset),
|
||||
|
||||
#ifdef SMP
|
||||
PLATFORMMETHOD(platform_mp_setmaxid, socfpga_mp_setmaxid),
|
||||
PLATFORMMETHOD(platform_mp_start_ap, socfpga_mp_start_ap),
|
||||
#endif
|
||||
|
||||
PLATFORMMETHOD_END,
|
||||
};
|
||||
FDT_PLATFORM_DEF(socfpga, "socfpga", 0, "altr,socfpga-cyclone5", 200);
|
||||
#endif
|
||||
|
||||
FDT_PLATFORM_DEF(socfpga, "socfpga", 0, "altr,socfpga", 0);
|
||||
#if defined(SOC_ALTERA_ARRIA10)
|
||||
static platform_method_t socfpga_a10_methods[] = {
|
||||
PLATFORMMETHOD(platform_devmap_init, socfpga_a10_devmap_init),
|
||||
PLATFORMMETHOD(platform_cpu_reset, socfpga_a10_cpu_reset),
|
||||
#ifdef SMP
|
||||
PLATFORMMETHOD(platform_mp_setmaxid, socfpga_mp_setmaxid),
|
||||
PLATFORMMETHOD(platform_mp_start_ap, socfpga_a10_mp_start_ap),
|
||||
#endif
|
||||
PLATFORMMETHOD_END,
|
||||
};
|
||||
FDT_PLATFORM_DEF(socfpga_a10, "socfpga", 0, "altr,socfpga-arria10", 200);
|
||||
#endif
|
||||
|
@ -377,7 +377,7 @@ fpgamgr_probe(device_t dev)
|
||||
if (!ofw_bus_status_okay(dev))
|
||||
return (ENXIO);
|
||||
|
||||
if (!ofw_bus_is_compatible(dev, "altr,fpga-mgr"))
|
||||
if (!ofw_bus_is_compatible(dev, "altr,socfpga-fpga-mgr"))
|
||||
return (ENXIO);
|
||||
|
||||
device_set_desc(dev, "FPGA Manager");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
|
||||
* Copyright (c) 2014-2017 Ruslan Bukin <br@bsdpad.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
@ -50,8 +50,10 @@ __FBSDID("$FreeBSD$");
|
||||
#include <machine/platformvar.h>
|
||||
|
||||
#include <arm/altera/socfpga/socfpga_mp.h>
|
||||
#include <arm/altera/socfpga/socfpga_rstmgr.h>
|
||||
|
||||
#define SCU_PHYSBASE 0xFFFEC000
|
||||
#define SCU_PHYSBASE_A10 0xFFFFC000
|
||||
#define SCU_SIZE 0x100
|
||||
|
||||
#define SCU_CONTROL_REG 0x00
|
||||
@ -69,11 +71,12 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#define RSTMGR_PHYSBASE 0xFFD05000
|
||||
#define RSTMGR_SIZE 0x100
|
||||
#define MPUMODRST 0x10
|
||||
#define MPUMODRST_CPU1 (1 << 1)
|
||||
|
||||
#define RAM_PHYSBASE 0x0
|
||||
#define RAM_SIZE 0x1000
|
||||
#define RAM_SIZE 0x1000
|
||||
|
||||
#define SOCFPGA_ARRIA10 1
|
||||
#define SOCFPGA_CYCLONE5 2
|
||||
|
||||
extern char *mpentry_addr;
|
||||
static void socfpga_trampoline(void);
|
||||
@ -109,15 +112,31 @@ socfpga_mp_setmaxid(platform_t plat)
|
||||
mp_maxid = ncpu - 1;
|
||||
}
|
||||
|
||||
void
|
||||
socfpga_mp_start_ap(platform_t plat)
|
||||
static void
|
||||
_socfpga_mp_start_ap(uint32_t platid)
|
||||
{
|
||||
bus_space_handle_t scu, rst, ram;
|
||||
int reg;
|
||||
|
||||
if (bus_space_map(fdtbus_bs_tag, SCU_PHYSBASE,
|
||||
SCU_SIZE, 0, &scu) != 0)
|
||||
panic("Couldn't map the SCU\n");
|
||||
switch (platid) {
|
||||
#if defined(SOC_ALTERA_ARRIA10)
|
||||
case SOCFPGA_ARRIA10:
|
||||
if (bus_space_map(fdtbus_bs_tag, SCU_PHYSBASE_A10,
|
||||
SCU_SIZE, 0, &scu) != 0)
|
||||
panic("Couldn't map the SCU\n");
|
||||
break;
|
||||
#endif
|
||||
#if defined(SOC_ALTERA_CYCLONE5)
|
||||
case SOCFPGA_CYCLONE5:
|
||||
if (bus_space_map(fdtbus_bs_tag, SCU_PHYSBASE,
|
||||
SCU_SIZE, 0, &scu) != 0)
|
||||
panic("Couldn't map the SCU\n");
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
panic("Unknown platform id %d\n", platid);
|
||||
}
|
||||
|
||||
if (bus_space_map(fdtbus_bs_tag, RSTMGR_PHYSBASE,
|
||||
RSTMGR_SIZE, 0, &rst) != 0)
|
||||
panic("Couldn't map the reset manager (RSTMGR)\n");
|
||||
@ -139,7 +158,22 @@ socfpga_mp_start_ap(platform_t plat)
|
||||
bus_space_write_4(fdtbus_bs_tag, scu, SCU_DIAG_CONTROL, reg);
|
||||
|
||||
/* Put CPU1 to reset state */
|
||||
bus_space_write_4(fdtbus_bs_tag, rst, MPUMODRST, MPUMODRST_CPU1);
|
||||
switch (platid) {
|
||||
#if defined(SOC_ALTERA_ARRIA10)
|
||||
case SOCFPGA_ARRIA10:
|
||||
bus_space_write_4(fdtbus_bs_tag, rst,
|
||||
RSTMGR_A10_MPUMODRST, MPUMODRST_CPU1);
|
||||
break;
|
||||
#endif
|
||||
#if defined(SOC_ALTERA_CYCLONE5)
|
||||
case SOCFPGA_CYCLONE5:
|
||||
bus_space_write_4(fdtbus_bs_tag, rst,
|
||||
RSTMGR_MPUMODRST, MPUMODRST_CPU1);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
panic("Unknown platform id %d\n", platid);
|
||||
}
|
||||
|
||||
/* Enable the SCU, then clean the cache on this core */
|
||||
reg = bus_space_read_4(fdtbus_bs_tag, scu, SCU_CONTROL_REG);
|
||||
@ -154,7 +188,22 @@ socfpga_mp_start_ap(platform_t plat)
|
||||
dcache_wbinv_poc_all();
|
||||
|
||||
/* Put CPU1 out from reset */
|
||||
bus_space_write_4(fdtbus_bs_tag, rst, MPUMODRST, 0);
|
||||
switch (platid) {
|
||||
#if defined(SOC_ALTERA_ARRIA10)
|
||||
case SOCFPGA_ARRIA10:
|
||||
bus_space_write_4(fdtbus_bs_tag, rst,
|
||||
RSTMGR_A10_MPUMODRST, 0);
|
||||
break;
|
||||
#endif
|
||||
#if defined(SOC_ALTERA_CYCLONE5)
|
||||
case SOCFPGA_CYCLONE5:
|
||||
bus_space_write_4(fdtbus_bs_tag, rst,
|
||||
RSTMGR_MPUMODRST, 0);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
panic("Unknown platform id %d\n", platid);
|
||||
}
|
||||
|
||||
dsb();
|
||||
sev();
|
||||
@ -163,3 +212,21 @@ socfpga_mp_start_ap(platform_t plat)
|
||||
bus_space_unmap(fdtbus_bs_tag, rst, RSTMGR_SIZE);
|
||||
bus_space_unmap(fdtbus_bs_tag, ram, RAM_SIZE);
|
||||
}
|
||||
|
||||
#if defined(SOC_ALTERA_ARRIA10)
|
||||
void
|
||||
socfpga_a10_mp_start_ap(platform_t plat)
|
||||
{
|
||||
|
||||
_socfpga_mp_start_ap(SOCFPGA_ARRIA10);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(SOC_ALTERA_CYCLONE5)
|
||||
void
|
||||
socfpga_mp_start_ap(platform_t plat)
|
||||
{
|
||||
|
||||
_socfpga_mp_start_ap(SOCFPGA_CYCLONE5);
|
||||
}
|
||||
#endif
|
||||
|
@ -30,5 +30,6 @@
|
||||
|
||||
void socfpga_mp_setmaxid(platform_t);
|
||||
void socfpga_mp_start_ap(platform_t);
|
||||
void socfpga_a10_mp_start_ap(platform_t);
|
||||
|
||||
#endif /* _SOCFPGA_MP_H_ */
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
|
||||
* Copyright (c) 2014-2017 Ruslan Bukin <br@bsdpad.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
@ -166,7 +166,7 @@ rstmgr_sysctl(SYSCTL_HANDLER_ARGS)
|
||||
}
|
||||
|
||||
int
|
||||
rstmgr_warmreset(void)
|
||||
rstmgr_warmreset(uint32_t reg)
|
||||
{
|
||||
struct rstmgr_softc *sc;
|
||||
|
||||
@ -175,8 +175,7 @@ rstmgr_warmreset(void)
|
||||
return (1);
|
||||
|
||||
/* Request warm reset */
|
||||
WRITE4(sc, RSTMGR_CTRL,
|
||||
CTRL_SWWARMRSTREQ);
|
||||
WRITE4(sc, reg, CTRL_SWWARMRSTREQ);
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -214,6 +213,7 @@ rstmgr_probe(device_t dev)
|
||||
return (ENXIO);
|
||||
|
||||
device_set_desc(dev, "Reset Manager");
|
||||
|
||||
return (BUS_PROBE_DEFAULT);
|
||||
}
|
||||
|
||||
|
@ -35,6 +35,7 @@
|
||||
#define CTRL_SWWARMRSTREQ (1 << 1) /* Trigger warm reset */
|
||||
#define RSTMGR_COUNTS 0x8 /* Reset Cycles Count */
|
||||
#define RSTMGR_MPUMODRST 0x10 /* MPU Module Reset */
|
||||
#define MPUMODRST_CPU1 (1 << 1)
|
||||
#define RSTMGR_PERMODRST 0x14 /* Peripheral Module Reset */
|
||||
#define RSTMGR_PER2MODRST 0x18 /* Peripheral 2 Module Reset */
|
||||
#define RSTMGR_BRGMODRST 0x1C /* Bridge Module Reset */
|
||||
@ -43,4 +44,7 @@
|
||||
#define BRGMODRST_HPS2FPGA (1 << 0)
|
||||
#define RSTMGR_MISCMODRST 0x20 /* Miscellaneous Module Reset */
|
||||
|
||||
int rstmgr_warmreset(void);
|
||||
#define RSTMGR_A10_CTRL 0xC /* Control */
|
||||
#define RSTMGR_A10_MPUMODRST 0x20 /* MPU Module Reset */
|
||||
|
||||
int rstmgr_warmreset(uint32_t reg);
|
||||
|
@ -104,7 +104,7 @@ usart_at91_probe(device_t dev)
|
||||
sc->sc_class = &at91_usart_class;
|
||||
if (sc->sc_class->uc_rclk == 0)
|
||||
sc->sc_class->uc_rclk = at91_master_clock;
|
||||
return (uart_bus_probe(dev, 0, 0, 0, device_get_unit(dev)));
|
||||
return (uart_bus_probe(dev, 0, 0, 0, 0, device_get_unit(dev)));
|
||||
}
|
||||
|
||||
|
||||
|
@ -69,7 +69,7 @@ uart_ec_probe(device_t dev)
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
sc->sc_class = &uart_ns8250_class;
|
||||
status = uart_bus_probe(dev, EC_UART_REGSHIFT, EC_UART_CLOCK, 0, 0);
|
||||
status = uart_bus_probe(dev, EC_UART_REGSHIFT, 0, EC_UART_CLOCK, 0, 0);
|
||||
return (status);
|
||||
}
|
||||
|
||||
|
30
sys/arm/conf/SOCDK
Normal file
30
sys/arm/conf/SOCDK
Normal file
@ -0,0 +1,30 @@
|
||||
#
|
||||
# Kernel configuration for Altera Arria10 SOC Development Kit.
|
||||
#
|
||||
# For more information on this file, please read the config(5) manual page,
|
||||
# and/or the handbook section on Kernel Configuration Files:
|
||||
#
|
||||
# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
|
||||
#
|
||||
# The handbook is also available locally in /usr/share/doc/handbook
|
||||
# if you've installed the doc distribution, otherwise always see the
|
||||
# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
|
||||
# latest information.
|
||||
#
|
||||
# An exhaustive list of options and more detailed explanations of the
|
||||
# device lines is also present in the ../../conf/NOTES and NOTES files.
|
||||
# If you are in doubt as to the purpose or necessity of a line, check first
|
||||
# in NOTES.
|
||||
#
|
||||
# $FreeBSD$
|
||||
|
||||
#NO_UNIVERSE
|
||||
|
||||
include "SOCFPGA"
|
||||
ident SOCDK
|
||||
|
||||
options ROOTDEVNAME=\"ufs:/dev/mmcsd0s4\"
|
||||
|
||||
# Flattened Device Tree
|
||||
options FDT_DTB_STATIC
|
||||
makeoptions FDT_DTS_FILE=socfpga_arria10_socdk_sdmmc.dts
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Kernel configuration for Terasic SoCKit (Altera Cyclone V SoC).
|
||||
# Kernel configuration for Altera SOCFPGA development kits.
|
||||
#
|
||||
# For more information on this file, please read the config(5) manual page,
|
||||
# and/or the handbook section on Kernel Configuration Files:
|
||||
@ -18,6 +18,7 @@
|
||||
#
|
||||
# $FreeBSD$
|
||||
|
||||
ident SOCFPGA
|
||||
include "std.armv6"
|
||||
include "../altera/socfpga/std.socfpga"
|
||||
|
||||
@ -29,6 +30,10 @@ options SCHED_ULE # ULE scheduler
|
||||
options PLATFORM # Platform based SoC
|
||||
options PLATFORM_SMP
|
||||
options SMP # Enable multiple cores
|
||||
options MULTIDELAY
|
||||
|
||||
options SOC_ALTERA_ARRIA10
|
||||
options SOC_ALTERA_CYCLONE5
|
||||
|
||||
# NFS root from boopt/dhcp
|
||||
#options BOOTP
|
||||
@ -60,7 +65,6 @@ device gpio
|
||||
# USB support
|
||||
options USB_HOST_ALIGN=64 # Align usb buffers to cache line size.
|
||||
device usb
|
||||
#device musb
|
||||
device dwcotg
|
||||
|
||||
device umass
|
||||
@ -70,7 +74,7 @@ device pass
|
||||
|
||||
# Serial ports
|
||||
device uart
|
||||
device uart_ns8250
|
||||
device uart_snps
|
||||
|
||||
# I2C (TWSI)
|
||||
device iic
|
@ -20,11 +20,11 @@
|
||||
|
||||
#NO_UNIVERSE
|
||||
|
||||
include "SOCFPGA"
|
||||
ident SOCKIT
|
||||
include "SOCKIT.common"
|
||||
|
||||
options ROOTDEVNAME=\"ufs:/dev/da0\"
|
||||
options ROOTDEVNAME=\"ufs:/dev/mmcsd0s4\"
|
||||
|
||||
# Flattened Device Tree
|
||||
options FDT_DTB_STATIC
|
||||
makeoptions FDT_DTS_FILE=socfpga-sockit.dts
|
||||
makeoptions FDT_DTS_FILE=socfpga_cyclone5_sockit_sdmmc.dts
|
||||
|
@ -18,8 +18,10 @@
|
||||
#
|
||||
# $FreeBSD$
|
||||
|
||||
#NO_UNIVERSE
|
||||
|
||||
include "SOCFPGA"
|
||||
ident SOCKIT-BERI
|
||||
include "SOCKIT.common"
|
||||
|
||||
options ROOTDEVNAME=\"ufs:/dev/mmcsd0s4\"
|
||||
|
||||
@ -32,4 +34,4 @@ device altera_pio
|
||||
|
||||
# Flattened Device Tree
|
||||
options FDT_DTB_STATIC
|
||||
makeoptions FDT_DTS_FILE=socfpga-sockit-beri.dts
|
||||
makeoptions FDT_DTS_FILE=socfpga_cyclone5_sockit_beri_sdmmc.dts
|
||||
|
@ -216,7 +216,7 @@ tegra_uart_probe(device_t dev)
|
||||
device_printf(dev, "Cannot enable UART clock: %d\n", rv);
|
||||
return (ENXIO);
|
||||
}
|
||||
return (uart_bus_probe(dev, shift, (int)freq, 0, 0));
|
||||
return (uart_bus_probe(dev, shift, 0, (int)freq, 0, 0));
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -83,7 +83,7 @@ uart_i81342_probe(device_t dev)
|
||||
0x40 | 0x10);
|
||||
bus_release_resource(dev, sc->sc_rtype, sc->sc_rrid, sc->sc_rres);
|
||||
|
||||
err = uart_bus_probe(dev, 2, 33334000, 0, device_get_unit(dev));
|
||||
err = uart_bus_probe(dev, 2, 0, 33334000, 0, device_get_unit(dev));
|
||||
sc->sc_rxfifosz = sc->sc_txfifosz = 1;
|
||||
return (err);
|
||||
}
|
||||
|
@ -78,5 +78,5 @@ uart_ixp425_probe(device_t dev)
|
||||
if (bootverbose)
|
||||
device_printf(dev, "rclk %u\n", rclk);
|
||||
|
||||
return uart_bus_probe(dev, 0, rclk, 0, 0);
|
||||
return uart_bus_probe(dev, 0, 0, rclk, 0, 0);
|
||||
}
|
||||
|
@ -97,7 +97,7 @@ uart_pxa_probe(device_t dev)
|
||||
sc = device_get_softc(dev);
|
||||
sc->sc_class = &uart_ns8250_class;
|
||||
|
||||
return(uart_bus_probe(dev, 2, PXA2X0_COM_FREQ, 0, 0));
|
||||
return(uart_bus_probe(dev, 2, 0, PXA2X0_COM_FREQ, 0, 0));
|
||||
}
|
||||
|
||||
DRIVER_MODULE(uart, pxa, uart_pxa_driver, uart_devclass, 0, 0);
|
||||
|
@ -1,200 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
|
||||
* ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/ {
|
||||
compatible = "altr,socfpga";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
interrupt-parent = <&GIC>;
|
||||
|
||||
aliases {
|
||||
soc = &SOC;
|
||||
rstmgr = &rstmgr;
|
||||
l3regs = &l3regs;
|
||||
serial0 = &serial0;
|
||||
serial1 = &serial1;
|
||||
};
|
||||
|
||||
SOC: socfpga {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "simple-bus";
|
||||
ranges;
|
||||
bus-frequency = <0>;
|
||||
|
||||
GIC: interrupt-controller@fffed000 {
|
||||
compatible = "arm,gic";
|
||||
reg = < 0xfffed000 0x1000 >, /* Distributor */
|
||||
< 0xfffec100 0x100 >; /* CPU Interface */
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <1>;
|
||||
};
|
||||
|
||||
mp_tmr@40002100 {
|
||||
compatible = "arm,mpcore-timers";
|
||||
clock-frequency = <200000000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = < 0xfffec200 0x100 >, /* Global Timer */
|
||||
< 0xfffec600 0x100 >; /* Private Timer */
|
||||
interrupts = < 27 29 >;
|
||||
interrupt-parent = < &GIC >;
|
||||
};
|
||||
|
||||
sysmgr: sysmgr@ffd08000 {
|
||||
compatible = "altr,sys-mgr";
|
||||
reg = <0xffd08000 0x1000>;
|
||||
};
|
||||
|
||||
clkmgr: clkmgr@ffd04000 {
|
||||
compatible = "altr,clk-mgr";
|
||||
reg = <0xffd04000 0x1000>;
|
||||
};
|
||||
|
||||
rstmgr: rstmgr@ffd05000 {
|
||||
compatible = "altr,rst-mgr";
|
||||
reg = <0xffd05000 0x1000>;
|
||||
};
|
||||
|
||||
l3regs: l3regs@ff800000 {
|
||||
compatible = "altr,l3regs";
|
||||
reg = <0xff800000 0x1000>;
|
||||
};
|
||||
|
||||
fpgamgr: fpgamgr@ff706000 {
|
||||
compatible = "altr,fpga-mgr";
|
||||
reg = <0xff706000 0x1000>, /* FPGAMGRREGS */
|
||||
<0xffb90000 0x1000>; /* FPGAMGRDATA */
|
||||
interrupts = < 207 >;
|
||||
interrupt-parent = <&GIC>;
|
||||
};
|
||||
|
||||
gpio0: gpio@ff708000 {
|
||||
compatible = "snps,dw-apb-gpio";
|
||||
reg = <0xff708000 0x1000>;
|
||||
porta: gpio-controller@0 {
|
||||
compatible = "snps,dw-apb-gpio-port";
|
||||
gpio-controller;
|
||||
snps,nr-gpios = <29>;
|
||||
};
|
||||
};
|
||||
|
||||
gpio1: gpio@ff709000 {
|
||||
compatible = "snps,dw-apb-gpio";
|
||||
reg = <0xff709000 0x1000>;
|
||||
portb: gpio-controller@0 {
|
||||
compatible = "snps,dw-apb-gpio-port";
|
||||
gpio-controller;
|
||||
snps,nr-gpios = <29>;
|
||||
};
|
||||
};
|
||||
|
||||
gpio2: gpio@ff70a000 {
|
||||
compatible = "snps,dw-apb-gpio";
|
||||
reg = <0xff70a000 0x1000>;
|
||||
portc: gpio-controller@0 {
|
||||
compatible = "snps,dw-apb-gpio-port";
|
||||
gpio-controller;
|
||||
snps,nr-gpios = <27>;
|
||||
};
|
||||
};
|
||||
|
||||
serial0: serial@ffc02000 {
|
||||
compatible = "ns16550";
|
||||
reg = <0xffc02000 0x1000>;
|
||||
reg-shift = <2>;
|
||||
interrupts = <194>;
|
||||
interrupt-parent = <&GIC>;
|
||||
current-speed = <115200>;
|
||||
clock-frequency = < 100000000 >;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
serial1: serial@ffc03000 {
|
||||
compatible = "ns16550";
|
||||
reg = <0xffc03000 0x1000>;
|
||||
reg-shift = <2>;
|
||||
interrupts = <195>;
|
||||
interrupt-parent = <&GIC>;
|
||||
current-speed = <115200>;
|
||||
clock-frequency = < 100000000 >;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
usb0: usb@ffb00000 {
|
||||
compatible = "synopsys,designware-hs-otg2";
|
||||
reg = <0xffb00000 0xffff>;
|
||||
interrupts = <157>;
|
||||
interrupt-parent = <&GIC>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
usb1: usb@ffb40000 {
|
||||
compatible = "synopsys,designware-hs-otg2";
|
||||
reg = <0xffb40000 0xffff>;
|
||||
interrupts = <160>;
|
||||
interrupt-parent = <&GIC>;
|
||||
dr_mode = "host";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
gmac0: ethernet@ff700000 {
|
||||
compatible = "altr,socfpga-stmmac",
|
||||
"snps,dwmac-3.70a", "snps,dwmac";
|
||||
reg = <0xff700000 0x2000>;
|
||||
interrupts = <147>;
|
||||
interrupt-parent = <&GIC>;
|
||||
phy-mode = "rgmii";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
gmac1: ethernet@ff702000 {
|
||||
compatible = "altr,socfpga-stmmac",
|
||||
"snps,dwmac-3.70a", "snps,dwmac";
|
||||
reg = <0xff702000 0x2000>;
|
||||
interrupts = <152>;
|
||||
interrupt-parent = <&GIC>;
|
||||
phy-mode = "rgmii";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
mmc: dwmmc@ff704000 {
|
||||
compatible = "altr,socfpga-dw-mshc";
|
||||
reg = <0xff704000 0x1000>;
|
||||
interrupts = <171>;
|
||||
interrupt-parent = <&GIC>;
|
||||
fifo-depth = <0x400>;
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
};
|
82
sys/boot/fdt/dts/arm/socfpga_arria10_socdk_sdmmc.dts
Normal file
82
sys/boot/fdt/dts/arm/socfpga_arria10_socdk_sdmmc.dts
Normal file
@ -0,0 +1,82 @@
|
||||
/*-
|
||||
* Copyright (c) 2017 Ruslan Bukin <br@bsdpad.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237
|
||||
* ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
#include "socfpga_arria10_socdk.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Altera SOCFPGA Arria 10";
|
||||
compatible = "altr,socfpga-arria10", "altr,socfpga";
|
||||
|
||||
/* Reserve first page for secondary CPU trampoline code */
|
||||
memreserve = < 0x00000000 0x1000 >;
|
||||
|
||||
soc {
|
||||
/* Local timer */
|
||||
timer@ffffc600 {
|
||||
clock-frequency = <200000000>;
|
||||
};
|
||||
|
||||
/* Global timer */
|
||||
global_timer: timer@ffffc200 {
|
||||
compatible = "arm,cortex-a9-global-timer";
|
||||
reg = <0xffffc200 0x20>;
|
||||
interrupts = <1 11 0x301>;
|
||||
clock-frequency = <200000000>;
|
||||
};
|
||||
};
|
||||
|
||||
chosen {
|
||||
stdin = "serial1";
|
||||
stdout = "serial1";
|
||||
};
|
||||
};
|
||||
|
||||
&uart1 {
|
||||
clock-frequency = < 50000000 >;
|
||||
};
|
||||
|
||||
&mmc {
|
||||
status = "okay";
|
||||
num-slots = <1>;
|
||||
cap-sd-highspeed;
|
||||
broken-cd;
|
||||
bus-width = <4>;
|
||||
bus-frequency = <200000000>;
|
||||
};
|
||||
|
||||
&i2c1 {
|
||||
lcd@28 {
|
||||
compatible = "newhaven,nhd-0216k3z-nsw-bbw";
|
||||
reg = <0x28>;
|
||||
};
|
||||
};
|
@ -1,9 +1,9 @@
|
||||
/*-
|
||||
* Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
|
||||
* Copyright (c) 2017 Ruslan Bukin <br@bsdpad.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237
|
||||
* ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -30,58 +30,29 @@
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
/include/ "socfpga.dtsi"
|
||||
/* /dts-v1/; */
|
||||
#include "socfpga_cyclone5_sockit.dts"
|
||||
|
||||
/ {
|
||||
model = "Terasic SoCKit";
|
||||
model = "Terasic SoCkit";
|
||||
compatible = "altr,socfpga-cyclone5", "altr,socfpga";
|
||||
|
||||
memreserve = < 0x00000000 0x1000 >, /* SMP trampoline */
|
||||
< 0x00001000 0x1000 >, /* virtio block */
|
||||
< 0x00002000 0x1000 >; /* virtio net */
|
||||
|
||||
memory {
|
||||
device_type = "memory";
|
||||
reg = < 0x00000000 0x40000000 >; /* 1G RAM */
|
||||
};
|
||||
|
||||
SOC: socfpga {
|
||||
serial0: serial@ffc02000 {
|
||||
status = "okay";
|
||||
soc {
|
||||
/* Local timer */
|
||||
timer@fffec600 {
|
||||
clock-frequency = <200000000>;
|
||||
};
|
||||
|
||||
usb1: usb@ffb40000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
gmac1: ethernet@ff702000 {
|
||||
status = "okay";
|
||||
|
||||
rxd0-skew-ps = <0>;
|
||||
rxd1-skew-ps = <0>;
|
||||
rxd2-skew-ps = <0>;
|
||||
rxd3-skew-ps = <0>;
|
||||
txen-skew-ps = <0>;
|
||||
txc-skew-ps = <2600>;
|
||||
rxdv-skew-ps = <0>;
|
||||
rxc-skew-ps = <2000>;
|
||||
};
|
||||
|
||||
mmc: dwmmc@ff704000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
status = "okay";
|
||||
num-slots = <1>;
|
||||
supports-highspeed;
|
||||
broken-cd;
|
||||
bus-frequency = <25000000>;
|
||||
|
||||
slot@0 {
|
||||
reg = <0>;
|
||||
bus-width = <4>;
|
||||
};
|
||||
/* Global timer */
|
||||
global_timer: timer@fffec200 {
|
||||
compatible = "arm,cortex-a9-global-timer";
|
||||
reg = <0xfffec200 0x20>;
|
||||
interrupts = <1 11 0xf04>;
|
||||
clock-frequency = <200000000>;
|
||||
};
|
||||
|
||||
beri_mem0: mem@d0000000 {
|
||||
@ -94,7 +65,6 @@
|
||||
compatible = "altr,pio";
|
||||
reg = <0xc0020000 0x1000>; /* recv */
|
||||
interrupts = < 76 >;
|
||||
interrupt-parent = <&GIC>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
@ -102,7 +72,6 @@
|
||||
compatible = "altr,pio";
|
||||
reg = <0xc0021000 0x1000>; /* send */
|
||||
interrupts = < 82 >; /* not in use on arm side */
|
||||
interrupt-parent = <&GIC>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
@ -110,7 +79,6 @@
|
||||
compatible = "altr,pio";
|
||||
reg = <0xc0022000 0x1000>; /* recv */
|
||||
interrupts = < 77 >;
|
||||
interrupt-parent = <&GIC>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
@ -118,7 +86,6 @@
|
||||
compatible = "altr,pio";
|
||||
reg = <0xc0023000 0x1000>; /* send */
|
||||
interrupts = < 83 >; /* not in use on arm side */
|
||||
interrupt-parent = <&GIC>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
@ -144,7 +111,6 @@
|
||||
compatible = "sri-cambridge,beri-ring";
|
||||
reg = <0xc0000000 0x3000>;
|
||||
interrupts = < 72 73 >;
|
||||
interrupt-parent = <&GIC>;
|
||||
device_name = "beri_debug";
|
||||
data_size = <0x1000>;
|
||||
data_read = <0x0>;
|
||||
@ -158,7 +124,6 @@
|
||||
compatible = "sri-cambridge,beri-ring";
|
||||
reg = <0xc0004000 0x3000>;
|
||||
interrupts = < 74 75 >;
|
||||
interrupt-parent = <&GIC>;
|
||||
device_name = "beri_console";
|
||||
data_size = <0x1000>;
|
||||
data_read = <0x0>;
|
||||
@ -170,8 +135,19 @@
|
||||
};
|
||||
|
||||
chosen {
|
||||
bootargs = "-v";
|
||||
stdin = "serial0";
|
||||
stdout = "serial0";
|
||||
};
|
||||
};
|
||||
|
||||
&mmc0 {
|
||||
bus-frequency = <25000000>;
|
||||
};
|
||||
|
||||
&uart0 {
|
||||
clock-frequency = <100000000>;
|
||||
};
|
||||
|
||||
&uart1 {
|
||||
status = "disabled";
|
||||
};
|
@ -1,9 +1,9 @@
|
||||
/*-
|
||||
* Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
|
||||
* Copyright (c) 2017 Ruslan Bukin <br@bsdpad.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237
|
||||
* ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -30,61 +30,45 @@
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
/include/ "socfpga.dtsi"
|
||||
/* /dts-v1/; */
|
||||
#include "socfpga_cyclone5_sockit.dts"
|
||||
|
||||
/ {
|
||||
model = "Terasic SoCKit";
|
||||
model = "Terasic SoCkit";
|
||||
compatible = "altr,socfpga-cyclone5", "altr,socfpga";
|
||||
|
||||
/* Reserve first page for secondary CPU trampoline code */
|
||||
memreserve = < 0x00000000 0x1000 >;
|
||||
|
||||
memory {
|
||||
device_type = "memory";
|
||||
reg = < 0x00000000 0x40000000 >; /* 1G RAM */
|
||||
};
|
||||
|
||||
SOC: socfpga {
|
||||
serial0: serial@ffc02000 {
|
||||
status = "okay";
|
||||
soc {
|
||||
/* Local timer */
|
||||
timer@fffec600 {
|
||||
clock-frequency = <200000000>;
|
||||
};
|
||||
|
||||
usb1: usb@ffb40000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
gmac1: ethernet@ff702000 {
|
||||
status = "okay";
|
||||
|
||||
rxd0-skew-ps = <0>;
|
||||
rxd1-skew-ps = <0>;
|
||||
rxd2-skew-ps = <0>;
|
||||
rxd3-skew-ps = <0>;
|
||||
txen-skew-ps = <0>;
|
||||
txc-skew-ps = <2600>;
|
||||
rxdv-skew-ps = <0>;
|
||||
rxc-skew-ps = <2000>;
|
||||
};
|
||||
|
||||
mmc: dwmmc@ff704000 {
|
||||
status = "okay";
|
||||
num-slots = <1>;
|
||||
supports-highspeed;
|
||||
broken-cd;
|
||||
bus-frequency = <25000000>;
|
||||
|
||||
slot@0 {
|
||||
reg = <0>;
|
||||
bus-width = <4>;
|
||||
};
|
||||
/* Global timer */
|
||||
global_timer: timer@fffec200 {
|
||||
compatible = "arm,cortex-a9-global-timer";
|
||||
reg = <0xfffec200 0x20>;
|
||||
interrupts = <1 11 0xf04>;
|
||||
clock-frequency = <200000000>;
|
||||
};
|
||||
};
|
||||
|
||||
chosen {
|
||||
bootargs = "-v";
|
||||
stdin = "serial0";
|
||||
stdout = "serial0";
|
||||
};
|
||||
};
|
||||
|
||||
&mmc0 {
|
||||
bus-frequency = <25000000>;
|
||||
};
|
||||
|
||||
&uart0 {
|
||||
clock-frequency = <100000000>;
|
||||
};
|
||||
|
||||
&uart1 {
|
||||
status = "disabled";
|
||||
};
|
@ -273,8 +273,6 @@ cloudabi64_load="NO" # 64-bit CloudABI executables support
|
||||
ibcs2_load="NO" # IBCS2 (SCO) emulation
|
||||
ibcs2_coff_load="NO"
|
||||
linux_load="NO" # Linux emulation
|
||||
svr4_load="NO" # SystemV R4 emulation
|
||||
streams_load="NO" # System V streams module
|
||||
|
||||
|
||||
##############################################################
|
||||
|
@ -25,7 +25,6 @@ BOOT2_UFS?= UFS1_AND_UFS2
|
||||
CFLAGS= -fomit-frame-pointer \
|
||||
-mrtd \
|
||||
-mregparm=3 \
|
||||
-DUSE_XREAD \
|
||||
-D${BOOT2_UFS} \
|
||||
-DFLAGS=${BOOT_BOOT1_FLAGS} \
|
||||
-DSIOPRT=${BOOT_COMCONSOLE_PORT} \
|
||||
|
@ -25,9 +25,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include "util.h"
|
||||
#include "drv.h"
|
||||
#include "edd.h"
|
||||
#ifdef USE_XREAD
|
||||
#include "xreadorg.h"
|
||||
#endif
|
||||
|
||||
static struct edd_params params;
|
||||
|
||||
@ -50,9 +47,7 @@ drvsize(struct dsk *dskp)
|
||||
return (params.sectors);
|
||||
}
|
||||
|
||||
#ifndef USE_XREAD
|
||||
static struct edd_packet packet;
|
||||
#endif
|
||||
|
||||
int
|
||||
drvread(struct dsk *dskp, void *buf, daddr_t lba, unsigned nblk)
|
||||
@ -61,7 +56,6 @@ drvread(struct dsk *dskp, void *buf, daddr_t lba, unsigned nblk)
|
||||
|
||||
if (!OPT_CHECK(RBX_QUIET))
|
||||
printf("%c\b", c = c << 8 | c >> 24);
|
||||
#ifndef USE_XREAD
|
||||
packet.len = sizeof(struct edd_packet);
|
||||
packet.count = nblk;
|
||||
packet.off = VTOPOFF(buf);
|
||||
@ -73,15 +67,6 @@ drvread(struct dsk *dskp, void *buf, daddr_t lba, unsigned nblk)
|
||||
v86.edx = dskp->drive;
|
||||
v86.ds = VTOPSEG(&packet);
|
||||
v86.esi = VTOPOFF(&packet);
|
||||
#else /* USE_XREAD */
|
||||
v86.ctl = V86_ADDR | V86_CALLF | V86_FLAGS;
|
||||
v86.addr = XREADORG; /* call to xread in boot1 */
|
||||
v86.es = VTOPSEG(buf);
|
||||
v86.eax = lba;
|
||||
v86.ebx = VTOPOFF(buf);
|
||||
v86.ecx = lba >> 32;
|
||||
v86.edx = nblk << 8 | dskp->drive;
|
||||
#endif /* USE_XREAD */
|
||||
v86int();
|
||||
if (V86_CY(v86.efl)) {
|
||||
printf("%s: error %u lba %u\n",
|
||||
|
@ -27,6 +27,8 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "opt_printf.h"
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
@ -72,6 +74,15 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include "opt_cam.h"
|
||||
|
||||
/* Wild guess based on not wanting to grow the stack too much */
|
||||
#define XPT_PRINT_MAXLEN 512
|
||||
#ifdef PRINTF_BUFR_SIZE
|
||||
#define XPT_PRINT_LEN PRINTF_BUFR_SIZE
|
||||
#else
|
||||
#define XPT_PRINT_LEN 128
|
||||
#endif
|
||||
_Static_assert(XPT_PRINT_LEN <= XPT_PRINT_MAXLEN, "XPT_PRINT_LEN is too large");
|
||||
|
||||
/*
|
||||
* This is the maximum number of high powered commands (e.g. start unit)
|
||||
* that can be outstanding at a particular time.
|
||||
|
@ -34,7 +34,6 @@
|
||||
|
||||
#ifdef _KERNEL
|
||||
#include <sys/cdefs.h>
|
||||
#include "opt_printf.h"
|
||||
#endif
|
||||
|
||||
/* Forward Declarations */
|
||||
@ -55,15 +54,6 @@ struct cam_path;
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
/* Wild guess based on not wanting to grow the stack too much */
|
||||
#define XPT_PRINT_MAXLEN 512
|
||||
#ifdef PRINTF_BUFR_SIZE
|
||||
#define XPT_PRINT_LEN PRINTF_BUFR_SIZE
|
||||
#else
|
||||
#define XPT_PRINT_LEN 128
|
||||
#endif
|
||||
_Static_assert(XPT_PRINT_LEN <= XPT_PRINT_MAXLEN, "XPT_PRINT_LEN is too large");
|
||||
|
||||
/*
|
||||
* Definition of an async handler callback block. These are used to add
|
||||
* SIMs and peripherals to the async callback lists.
|
||||
|
@ -478,15 +478,15 @@ static int ctl_scsiio_precheck(struct ctl_softc *ctl_softc,
|
||||
struct ctl_scsiio *ctsio);
|
||||
static int ctl_scsiio(struct ctl_scsiio *ctsio);
|
||||
|
||||
static int ctl_bus_reset(struct ctl_softc *ctl_softc, union ctl_io *io);
|
||||
static int ctl_target_reset(struct ctl_softc *ctl_softc, union ctl_io *io,
|
||||
ctl_ua_type ua_type);
|
||||
static int ctl_do_lun_reset(struct ctl_lun *lun, union ctl_io *io,
|
||||
static int ctl_target_reset(union ctl_io *io);
|
||||
static void ctl_do_lun_reset(struct ctl_lun *lun, uint32_t initidx,
|
||||
ctl_ua_type ua_type);
|
||||
static int ctl_lun_reset(struct ctl_softc *ctl_softc, union ctl_io *io);
|
||||
static int ctl_lun_reset(union ctl_io *io);
|
||||
static int ctl_abort_task(union ctl_io *io);
|
||||
static int ctl_abort_task_set(union ctl_io *io);
|
||||
static int ctl_query_task(union ctl_io *io, int task_set);
|
||||
static void ctl_i_t_nexus_loss(struct ctl_softc *softc, uint32_t initidx,
|
||||
ctl_ua_type ua_type);
|
||||
static int ctl_i_t_nexus_reset(union ctl_io *io);
|
||||
static int ctl_query_async_event(union ctl_io *io);
|
||||
static void ctl_run_task(union ctl_io *io);
|
||||
@ -1288,6 +1288,9 @@ ctl_isc_iid_sync(struct ctl_softc *softc, union ctl_ha_msg *msg, int len)
|
||||
return;
|
||||
}
|
||||
iid = msg->hdr.nexus.initid;
|
||||
if (port->wwpn_iid[iid].in_use != 0 &&
|
||||
msg->iid.in_use == 0)
|
||||
ctl_i_t_nexus_loss(softc, iid, CTL_UA_POWERON);
|
||||
port->wwpn_iid[iid].in_use = msg->iid.in_use;
|
||||
port->wwpn_iid[iid].wwpn = msg->iid.wwpn;
|
||||
free(port->wwpn_iid[iid].name, M_CTL);
|
||||
@ -2027,6 +2030,7 @@ int
|
||||
ctl_remove_initiator(struct ctl_port *port, int iid)
|
||||
{
|
||||
struct ctl_softc *softc = port->ctl_softc;
|
||||
int last;
|
||||
|
||||
mtx_assert(&softc->ctl_lock, MA_NOTOWNED);
|
||||
|
||||
@ -2037,9 +2041,11 @@ ctl_remove_initiator(struct ctl_port *port, int iid)
|
||||
}
|
||||
|
||||
mtx_lock(&softc->ctl_lock);
|
||||
port->wwpn_iid[iid].in_use--;
|
||||
last = (--port->wwpn_iid[iid].in_use == 0);
|
||||
port->wwpn_iid[iid].last_use = time_uptime;
|
||||
mtx_unlock(&softc->ctl_lock);
|
||||
if (last)
|
||||
ctl_i_t_nexus_loss(softc, iid, CTL_UA_POWERON);
|
||||
ctl_isc_announce_iid(port, iid);
|
||||
|
||||
return (0);
|
||||
@ -2144,11 +2150,6 @@ ctl_add_initiator(struct ctl_port *port, int iid, uint64_t wwpn, char *name)
|
||||
__func__, port->targ_port, iid, wwpn, name,
|
||||
(uintmax_t)port->wwpn_iid[iid].wwpn,
|
||||
port->wwpn_iid[iid].name);
|
||||
|
||||
/*
|
||||
* XXX KDM clear pending_sense and pending_ua on each LUN
|
||||
* for this initiator.
|
||||
*/
|
||||
}
|
||||
take:
|
||||
free(port->wwpn_iid[iid].name, M_CTL);
|
||||
@ -11603,50 +11604,42 @@ bailout:
|
||||
return (retval);
|
||||
}
|
||||
|
||||
/*
|
||||
* Since we only implement one target right now, a bus reset simply resets
|
||||
* our single target.
|
||||
*/
|
||||
static int
|
||||
ctl_bus_reset(struct ctl_softc *softc, union ctl_io *io)
|
||||
{
|
||||
return(ctl_target_reset(softc, io, CTL_UA_BUS_RESET));
|
||||
}
|
||||
|
||||
static int
|
||||
ctl_target_reset(struct ctl_softc *softc, union ctl_io *io,
|
||||
ctl_ua_type ua_type)
|
||||
ctl_target_reset(union ctl_io *io)
|
||||
{
|
||||
struct ctl_softc *softc = CTL_SOFTC(io);
|
||||
struct ctl_port *port = CTL_PORT(io);
|
||||
struct ctl_lun *lun;
|
||||
int retval;
|
||||
uint32_t initidx;
|
||||
ctl_ua_type ua_type;
|
||||
|
||||
if (!(io->io_hdr.flags & CTL_FLAG_FROM_OTHER_SC)) {
|
||||
union ctl_ha_msg msg_info;
|
||||
|
||||
msg_info.hdr.nexus = io->io_hdr.nexus;
|
||||
if (ua_type==CTL_UA_TARG_RESET)
|
||||
msg_info.task.task_action = CTL_TASK_TARGET_RESET;
|
||||
else
|
||||
msg_info.task.task_action = CTL_TASK_BUS_RESET;
|
||||
msg_info.task.task_action = io->taskio.task_action;
|
||||
msg_info.hdr.msg_type = CTL_MSG_MANAGE_TASKS;
|
||||
msg_info.hdr.original_sc = NULL;
|
||||
msg_info.hdr.serializing_sc = NULL;
|
||||
ctl_ha_msg_send(CTL_HA_CHAN_CTL, &msg_info,
|
||||
sizeof(msg_info.task), M_WAITOK);
|
||||
}
|
||||
retval = 0;
|
||||
|
||||
initidx = ctl_get_initindex(&io->io_hdr.nexus);
|
||||
if (io->taskio.task_action == CTL_TASK_TARGET_RESET)
|
||||
ua_type = CTL_UA_TARG_RESET;
|
||||
else
|
||||
ua_type = CTL_UA_BUS_RESET;
|
||||
mtx_lock(&softc->ctl_lock);
|
||||
STAILQ_FOREACH(lun, &softc->lun_list, links) {
|
||||
if (port != NULL &&
|
||||
ctl_lun_map_to_port(port, lun->lun) == UINT32_MAX)
|
||||
continue;
|
||||
retval += ctl_do_lun_reset(lun, io, ua_type);
|
||||
ctl_do_lun_reset(lun, initidx, ua_type);
|
||||
}
|
||||
mtx_unlock(&softc->ctl_lock);
|
||||
io->taskio.task_status = CTL_TASK_FUNCTION_COMPLETE;
|
||||
return (retval);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -11670,66 +11663,51 @@ ctl_target_reset(struct ctl_softc *softc, union ctl_io *io,
|
||||
*
|
||||
* XXX KDM for now, we're setting unit attention for all initiators.
|
||||
*/
|
||||
static int
|
||||
ctl_do_lun_reset(struct ctl_lun *lun, union ctl_io *io, ctl_ua_type ua_type)
|
||||
static void
|
||||
ctl_do_lun_reset(struct ctl_lun *lun, uint32_t initidx, ctl_ua_type ua_type)
|
||||
{
|
||||
union ctl_io *xio;
|
||||
#if 0
|
||||
uint32_t initidx;
|
||||
#endif
|
||||
int i;
|
||||
|
||||
mtx_lock(&lun->lun_lock);
|
||||
/*
|
||||
* Run through the OOA queue and abort each I/O.
|
||||
*/
|
||||
/* Abort tasks. */
|
||||
for (xio = (union ctl_io *)TAILQ_FIRST(&lun->ooa_queue); xio != NULL;
|
||||
xio = (union ctl_io *)TAILQ_NEXT(&xio->io_hdr, ooa_links)) {
|
||||
xio->io_hdr.flags |= CTL_FLAG_ABORT | CTL_FLAG_ABORT_STATUS;
|
||||
}
|
||||
|
||||
/*
|
||||
* This version sets unit attention for every
|
||||
*/
|
||||
#if 0
|
||||
initidx = ctl_get_initindex(&io->io_hdr.nexus);
|
||||
ctl_est_ua_all(lun, initidx, ua_type);
|
||||
#else
|
||||
ctl_est_ua_all(lun, -1, ua_type);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* A reset (any kind, really) clears reservations established with
|
||||
* RESERVE/RELEASE. It does not clear reservations established
|
||||
* with PERSISTENT RESERVE OUT, but we don't support that at the
|
||||
* moment anyway. See SPC-2, section 5.6. SPC-3 doesn't address
|
||||
* reservations made with the RESERVE/RELEASE commands, because
|
||||
* those commands are obsolete in SPC-3.
|
||||
*/
|
||||
lun->flags &= ~CTL_LUN_RESERVED;
|
||||
|
||||
/* Clear CA. */
|
||||
for (i = 0; i < CTL_MAX_PORTS; i++) {
|
||||
free(lun->pending_sense[i], M_CTL);
|
||||
lun->pending_sense[i] = NULL;
|
||||
}
|
||||
lun->prevent_count = 0;
|
||||
/* Clear reservation. */
|
||||
lun->flags &= ~CTL_LUN_RESERVED;
|
||||
/* Clear prevent media removal. */
|
||||
if (lun->prevent) {
|
||||
for (i = 0; i < CTL_MAX_INITIATORS; i++)
|
||||
ctl_clear_mask(lun->prevent, i);
|
||||
lun->prevent_count = 0;
|
||||
}
|
||||
/* Clear TPC status */
|
||||
ctl_tpc_lun_clear(lun, -1);
|
||||
/* Establish UA. */
|
||||
#if 0
|
||||
ctl_est_ua_all(lun, initidx, ua_type);
|
||||
#else
|
||||
ctl_est_ua_all(lun, -1, ua_type);
|
||||
#endif
|
||||
mtx_unlock(&lun->lun_lock);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
ctl_lun_reset(struct ctl_softc *softc, union ctl_io *io)
|
||||
ctl_lun_reset(union ctl_io *io)
|
||||
{
|
||||
struct ctl_softc *softc = CTL_SOFTC(io);
|
||||
struct ctl_lun *lun;
|
||||
uint32_t targ_lun;
|
||||
int retval;
|
||||
uint32_t targ_lun, initidx;
|
||||
|
||||
targ_lun = io->io_hdr.nexus.targ_mapped_lun;
|
||||
initidx = ctl_get_initindex(&io->io_hdr.nexus);
|
||||
mtx_lock(&softc->ctl_lock);
|
||||
if (targ_lun >= CTL_MAX_LUNS ||
|
||||
(lun = softc->ctl_luns[targ_lun]) == NULL) {
|
||||
@ -11737,7 +11715,7 @@ ctl_lun_reset(struct ctl_softc *softc, union ctl_io *io)
|
||||
io->taskio.task_status = CTL_TASK_LUN_DOES_NOT_EXIST;
|
||||
return (1);
|
||||
}
|
||||
retval = ctl_do_lun_reset(lun, io, CTL_UA_LUN_RESET);
|
||||
ctl_do_lun_reset(lun, initidx, CTL_UA_LUN_RESET);
|
||||
mtx_unlock(&softc->ctl_lock);
|
||||
io->taskio.task_status = CTL_TASK_FUNCTION_COMPLETE;
|
||||
|
||||
@ -11752,7 +11730,7 @@ ctl_lun_reset(struct ctl_softc *softc, union ctl_io *io)
|
||||
ctl_ha_msg_send(CTL_HA_CHAN_CTL, &msg_info,
|
||||
sizeof(msg_info.task), M_WAITOK);
|
||||
}
|
||||
return (retval);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -11832,12 +11810,46 @@ ctl_abort_task_set(union ctl_io *io)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
ctl_i_t_nexus_loss(struct ctl_softc *softc, uint32_t initidx,
|
||||
ctl_ua_type ua_type)
|
||||
{
|
||||
struct ctl_lun *lun;
|
||||
struct scsi_sense_data *ps;
|
||||
uint32_t p, i;
|
||||
|
||||
p = initidx / CTL_MAX_INIT_PER_PORT;
|
||||
i = initidx % CTL_MAX_INIT_PER_PORT;
|
||||
mtx_lock(&softc->ctl_lock);
|
||||
STAILQ_FOREACH(lun, &softc->lun_list, links) {
|
||||
mtx_lock(&lun->lun_lock);
|
||||
/* Abort tasks. */
|
||||
ctl_abort_tasks_lun(lun, p, i, 1);
|
||||
/* Clear CA. */
|
||||
ps = lun->pending_sense[p];
|
||||
if (ps != NULL)
|
||||
ps[i].error_code = 0;
|
||||
/* Clear reservation. */
|
||||
if ((lun->flags & CTL_LUN_RESERVED) && (lun->res_idx == initidx))
|
||||
lun->flags &= ~CTL_LUN_RESERVED;
|
||||
/* Clear prevent media removal. */
|
||||
if (lun->prevent && ctl_is_set(lun->prevent, initidx)) {
|
||||
ctl_clear_mask(lun->prevent, initidx);
|
||||
lun->prevent_count--;
|
||||
}
|
||||
/* Clear TPC status */
|
||||
ctl_tpc_lun_clear(lun, initidx);
|
||||
/* Establish UA. */
|
||||
ctl_est_ua(lun, initidx, ua_type);
|
||||
mtx_unlock(&lun->lun_lock);
|
||||
}
|
||||
mtx_unlock(&softc->ctl_lock);
|
||||
}
|
||||
|
||||
static int
|
||||
ctl_i_t_nexus_reset(union ctl_io *io)
|
||||
{
|
||||
struct ctl_softc *softc = CTL_SOFTC(io);
|
||||
struct ctl_lun *lun;
|
||||
struct scsi_sense_data *ps;
|
||||
uint32_t initidx;
|
||||
|
||||
if (!(io->io_hdr.flags & CTL_FLAG_FROM_OTHER_SC)) {
|
||||
@ -11853,24 +11865,7 @@ ctl_i_t_nexus_reset(union ctl_io *io)
|
||||
}
|
||||
|
||||
initidx = ctl_get_initindex(&io->io_hdr.nexus);
|
||||
mtx_lock(&softc->ctl_lock);
|
||||
STAILQ_FOREACH(lun, &softc->lun_list, links) {
|
||||
mtx_lock(&lun->lun_lock);
|
||||
ctl_abort_tasks_lun(lun, io->io_hdr.nexus.targ_port,
|
||||
io->io_hdr.nexus.initid, 1);
|
||||
ps = lun->pending_sense[initidx / CTL_MAX_INIT_PER_PORT];
|
||||
if (ps != NULL)
|
||||
ps[initidx % CTL_MAX_INIT_PER_PORT].error_code = 0;
|
||||
if ((lun->flags & CTL_LUN_RESERVED) && (lun->res_idx == initidx))
|
||||
lun->flags &= ~CTL_LUN_RESERVED;
|
||||
if (lun->prevent && ctl_is_set(lun->prevent, initidx)) {
|
||||
ctl_clear_mask(lun->prevent, initidx);
|
||||
lun->prevent_count--;
|
||||
}
|
||||
ctl_est_ua(lun, initidx, CTL_UA_I_T_NEXUS_LOSS);
|
||||
mtx_unlock(&lun->lun_lock);
|
||||
}
|
||||
mtx_unlock(&softc->ctl_lock);
|
||||
ctl_i_t_nexus_loss(softc, initidx, CTL_UA_I_T_NEXUS_LOSS);
|
||||
io->taskio.task_status = CTL_TASK_FUNCTION_COMPLETE;
|
||||
return (0);
|
||||
}
|
||||
@ -12079,7 +12074,6 @@ ctl_query_async_event(union ctl_io *io)
|
||||
static void
|
||||
ctl_run_task(union ctl_io *io)
|
||||
{
|
||||
struct ctl_softc *softc = CTL_SOFTC(io);
|
||||
int retval = 1;
|
||||
|
||||
CTL_DEBUG_PRINT(("ctl_run_task\n"));
|
||||
@ -12101,13 +12095,11 @@ ctl_run_task(union ctl_io *io)
|
||||
retval = ctl_i_t_nexus_reset(io);
|
||||
break;
|
||||
case CTL_TASK_LUN_RESET:
|
||||
retval = ctl_lun_reset(softc, io);
|
||||
retval = ctl_lun_reset(io);
|
||||
break;
|
||||
case CTL_TASK_TARGET_RESET:
|
||||
retval = ctl_target_reset(softc, io, CTL_UA_TARG_RESET);
|
||||
break;
|
||||
case CTL_TASK_BUS_RESET:
|
||||
retval = ctl_bus_reset(softc, io);
|
||||
retval = ctl_target_reset(io);
|
||||
break;
|
||||
case CTL_TASK_PORT_LOGIN:
|
||||
break;
|
||||
@ -13154,21 +13146,15 @@ ctl_queue_sense(union ctl_io *io)
|
||||
|
||||
initidx = ctl_get_initindex(&io->io_hdr.nexus);
|
||||
p = initidx / CTL_MAX_INIT_PER_PORT;
|
||||
if ((ps = lun->pending_sense[p]) == NULL) {
|
||||
mtx_unlock(&lun->lun_lock);
|
||||
ps = malloc(sizeof(*ps) * CTL_MAX_INIT_PER_PORT, M_CTL,
|
||||
M_WAITOK | M_ZERO);
|
||||
mtx_lock(&lun->lun_lock);
|
||||
if (lun->pending_sense[p] == NULL) {
|
||||
lun->pending_sense[p] = ps;
|
||||
} else {
|
||||
free(ps, M_CTL);
|
||||
ps = lun->pending_sense[p];
|
||||
}
|
||||
if (lun->pending_sense[p] == NULL) {
|
||||
lun->pending_sense[p] = malloc(sizeof(*ps) * CTL_MAX_INIT_PER_PORT,
|
||||
M_CTL, M_NOWAIT | M_ZERO);
|
||||
}
|
||||
if ((ps = lun->pending_sense[p]) != NULL) {
|
||||
ps += initidx % CTL_MAX_INIT_PER_PORT;
|
||||
memset(ps, 0, sizeof(*ps));
|
||||
memcpy(ps, &io->scsiio.sense_data, io->scsiio.sense_len);
|
||||
}
|
||||
ps += initidx % CTL_MAX_INIT_PER_PORT;
|
||||
memset(ps, 0, sizeof(*ps));
|
||||
memcpy(ps, &io->scsiio.sense_data, io->scsiio.sense_len);
|
||||
mtx_unlock(&lun->lun_lock);
|
||||
|
||||
bailout:
|
||||
|
@ -528,6 +528,7 @@ int ctl_get_lba_status(struct ctl_scsiio *ctsio);
|
||||
void ctl_tpc_init(struct ctl_softc *softc);
|
||||
void ctl_tpc_shutdown(struct ctl_softc *softc);
|
||||
void ctl_tpc_lun_init(struct ctl_lun *lun);
|
||||
void ctl_tpc_lun_clear(struct ctl_lun *lun, uint32_t initidx);
|
||||
void ctl_tpc_lun_shutdown(struct ctl_lun *lun);
|
||||
int ctl_inquiry_evpd_tpc(struct ctl_scsiio *ctsio, int alloc_len);
|
||||
int ctl_receive_copy_status_lid1(struct ctl_scsiio *ctsio);
|
||||
|
@ -221,6 +221,21 @@ ctl_tpc_lun_init(struct ctl_lun *lun)
|
||||
TAILQ_INIT(&lun->tpc_lists);
|
||||
}
|
||||
|
||||
void
|
||||
ctl_tpc_lun_clear(struct ctl_lun *lun, uint32_t initidx)
|
||||
{
|
||||
struct tpc_list *list, *tlist;
|
||||
|
||||
TAILQ_FOREACH_SAFE(list, &lun->tpc_lists, links, tlist) {
|
||||
if (initidx != -1 && list->init_idx != initidx)
|
||||
continue;
|
||||
if (!list->completed)
|
||||
continue;
|
||||
TAILQ_REMOVE(&lun->tpc_lists, list, links);
|
||||
free(list, M_CTL);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ctl_tpc_lun_shutdown(struct ctl_lun *lun)
|
||||
{
|
||||
|
@ -1223,6 +1223,20 @@ ctlfedone(struct cam_periph *periph, union ccb *done_ccb)
|
||||
* datamove done routine.
|
||||
*/
|
||||
if ((io->io_hdr.flags & CTL_FLAG_DMA_INPROG) == 0) {
|
||||
/*
|
||||
* If we asked to send sense data but it wasn't sent,
|
||||
* queue the I/O back to CTL for later REQUEST SENSE.
|
||||
*/
|
||||
if ((done_ccb->ccb_h.flags & CAM_SEND_SENSE) != 0 &&
|
||||
(done_ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP &&
|
||||
(done_ccb->ccb_h.status & CAM_SENT_SENSE) == 0 &&
|
||||
(io = ctl_alloc_io_nowait(bus_softc->port.ctl_pool_ref)) != NULL) {
|
||||
PRIV_INFO(io) = PRIV_INFO(
|
||||
(union ctl_io *)atio->ccb_h.io_ptr);
|
||||
ctl_queue_sense(atio->ccb_h.io_ptr);
|
||||
atio->ccb_h.io_ptr = io;
|
||||
}
|
||||
|
||||
/* Abort ATIO if CTIO sending status has failed. */
|
||||
if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) !=
|
||||
CAM_REQ_CMP) {
|
||||
@ -1253,7 +1267,8 @@ ctlfedone(struct cam_periph *periph, union ccb *done_ccb)
|
||||
*/
|
||||
switch (done_ccb->ccb_h.status & CAM_STATUS_MASK) {
|
||||
case CAM_REQ_CMP:
|
||||
io->scsiio.kern_data_resid -= csio->dxfer_len;
|
||||
io->scsiio.kern_data_resid -=
|
||||
csio->dxfer_len - csio->resid;
|
||||
io->io_hdr.port_status = 0;
|
||||
break;
|
||||
default:
|
||||
@ -1280,8 +1295,8 @@ ctlfedone(struct cam_periph *periph, union ccb *done_ccb)
|
||||
* pieces, figure out where we are in the list, and
|
||||
* continue sending pieces if necessary.
|
||||
*/
|
||||
if ((cmd_info->flags & CTLFE_CMD_PIECEWISE)
|
||||
&& (io->io_hdr.port_status == 0)) {
|
||||
if ((cmd_info->flags & CTLFE_CMD_PIECEWISE) &&
|
||||
io->io_hdr.port_status == 0 && csio->resid == 0) {
|
||||
ccb_flags flags;
|
||||
uint8_t *data_ptr;
|
||||
uint32_t dxfer_len;
|
||||
|
@ -6897,7 +6897,7 @@ top:
|
||||
}
|
||||
|
||||
if (!all && HDR_HAS_L2HDR(hdr) &&
|
||||
(hdr->b_l2hdr.b_daddr > taddr ||
|
||||
(hdr->b_l2hdr.b_daddr >= taddr ||
|
||||
hdr->b_l2hdr.b_daddr < dev->l2ad_hand)) {
|
||||
/*
|
||||
* We've evicted to the target address,
|
||||
@ -7031,7 +7031,22 @@ l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz)
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((write_asize + HDR_GET_LSIZE(hdr)) > target_sz) {
|
||||
/*
|
||||
* We rely on the L1 portion of the header below, so
|
||||
* it's invalid for this header to have been evicted out
|
||||
* of the ghost cache, prior to being written out. The
|
||||
* ARC_FLAG_L2_WRITING bit ensures this won't happen.
|
||||
*/
|
||||
ASSERT(HDR_HAS_L1HDR(hdr));
|
||||
|
||||
ASSERT3U(HDR_GET_PSIZE(hdr), >, 0);
|
||||
ASSERT3P(hdr->b_l1hdr.b_pdata, !=, NULL);
|
||||
ASSERT3U(arc_hdr_size(hdr), >, 0);
|
||||
uint64_t size = arc_hdr_size(hdr);
|
||||
uint64_t asize = vdev_psize_to_asize(dev->l2ad_vdev,
|
||||
size);
|
||||
|
||||
if ((write_psize + asize) > target_sz) {
|
||||
full = B_TRUE;
|
||||
mutex_exit(hash_lock);
|
||||
ARCSTAT_BUMP(arcstat_l2_write_full);
|
||||
@ -7066,21 +7081,6 @@ l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz)
|
||||
list_insert_head(&dev->l2ad_buflist, hdr);
|
||||
mutex_exit(&dev->l2ad_mtx);
|
||||
|
||||
/*
|
||||
* We rely on the L1 portion of the header below, so
|
||||
* it's invalid for this header to have been evicted out
|
||||
* of the ghost cache, prior to being written out. The
|
||||
* ARC_FLAG_L2_WRITING bit ensures this won't happen.
|
||||
*/
|
||||
ASSERT(HDR_HAS_L1HDR(hdr));
|
||||
|
||||
ASSERT3U(HDR_GET_PSIZE(hdr), >, 0);
|
||||
ASSERT3P(hdr->b_l1hdr.b_pdata, !=, NULL);
|
||||
ASSERT3U(arc_hdr_size(hdr), >, 0);
|
||||
uint64_t size = arc_hdr_size(hdr);
|
||||
uint64_t asize = vdev_psize_to_asize(dev->l2ad_vdev,
|
||||
size);
|
||||
|
||||
(void) refcount_add_many(&dev->l2ad_alloc, size, hdr);
|
||||
|
||||
/*
|
||||
@ -7142,7 +7142,7 @@ l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz)
|
||||
return (0);
|
||||
}
|
||||
|
||||
ASSERT3U(write_asize, <=, target_sz);
|
||||
ASSERT3U(write_psize, <=, target_sz);
|
||||
ARCSTAT_BUMP(arcstat_l2_writes_sent);
|
||||
ARCSTAT_INCR(arcstat_l2_write_bytes, write_asize);
|
||||
ARCSTAT_INCR(arcstat_l2_size, write_sz);
|
||||
|
@ -174,10 +174,6 @@ uint_t zio_taskq_basedc = 80; /* base duty cycle */
|
||||
boolean_t spa_create_process = B_TRUE; /* no process ==> no sysdc */
|
||||
extern int zfs_sync_pass_deferred_free;
|
||||
|
||||
#ifndef illumos
|
||||
extern void spa_deadman(void *arg);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This (illegal) pool name is used when temporarily importing a spa_t in order
|
||||
* to get the vdev stats associated with the imported devices.
|
||||
@ -6883,8 +6879,8 @@ spa_sync(spa_t *spa, uint64_t txg)
|
||||
spa->spa_sync_starttime + spa->spa_deadman_synctime));
|
||||
#else /* !illumos */
|
||||
#ifdef _KERNEL
|
||||
callout_reset(&spa->spa_deadman_cycid,
|
||||
hz * spa->spa_deadman_synctime / NANOSEC, spa_deadman, spa);
|
||||
callout_schedule(&spa->spa_deadman_cycid,
|
||||
hz * spa->spa_deadman_synctime / NANOSEC);
|
||||
#endif
|
||||
#endif /* illumos */
|
||||
|
||||
|
@ -597,8 +597,8 @@ spa_lookup(const char *name)
|
||||
* If the zfs_deadman_enabled flag is set then it inspects all vdev queues
|
||||
* looking for potentially hung I/Os.
|
||||
*/
|
||||
void
|
||||
spa_deadman(void *arg)
|
||||
static void
|
||||
spa_deadman(void *arg, int pending)
|
||||
{
|
||||
spa_t *spa = arg;
|
||||
|
||||
@ -627,6 +627,16 @@ spa_deadman(void *arg)
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(__FreeBSD__) && defined(_KERNEL)
|
||||
static void
|
||||
spa_deadman_timeout(void *arg)
|
||||
{
|
||||
spa_t *spa = arg;
|
||||
|
||||
taskqueue_enqueue(taskqueue_thread, &spa->spa_deadman_task);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Create an uninitialized spa_t with the given name. Requires
|
||||
* spa_namespace_lock. The caller must ensure that the spa_t doesn't already
|
||||
@ -698,7 +708,23 @@ spa_add(const char *name, nvlist_t *config, const char *altroot)
|
||||
mutex_exit(&cpu_lock);
|
||||
#else /* !illumos */
|
||||
#ifdef _KERNEL
|
||||
/*
|
||||
* callout(9) does not provide a way to initialize a callout with
|
||||
* a function and an argument, so we use callout_reset() to schedule
|
||||
* the callout in the very distant future. Even if that event ever
|
||||
* fires, it should be okayas we won't have any active zio-s.
|
||||
* But normally spa_sync() will reschedule the callout with a proper
|
||||
* timeout.
|
||||
* callout(9) does not allow the callback function to sleep but
|
||||
* vdev_deadman() needs to acquire vq_lock and illumos mutexes are
|
||||
* emulated using sx(9). For this reason spa_deadman_timeout()
|
||||
* will schedule spa_deadman() as task on a taskqueue that allows
|
||||
* sleeping.
|
||||
*/
|
||||
TASK_INIT(&spa->spa_deadman_task, 0, spa_deadman, spa);
|
||||
callout_init(&spa->spa_deadman_cycid, 1);
|
||||
callout_reset_sbt(&spa->spa_deadman_cycid, SBT_MAX, 0,
|
||||
spa_deadman_timeout, spa, 0);
|
||||
#endif
|
||||
#endif
|
||||
refcount_create(&spa->spa_refcount);
|
||||
@ -811,6 +837,7 @@ spa_remove(spa_t *spa)
|
||||
#else /* !illumos */
|
||||
#ifdef _KERNEL
|
||||
callout_drain(&spa->spa_deadman_cycid);
|
||||
taskqueue_drain(taskqueue_thread, &spa->spa_deadman_task);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@ -267,6 +267,7 @@ struct spa {
|
||||
#else /* !illumos */
|
||||
#ifdef _KERNEL
|
||||
struct callout spa_deadman_cycid; /* callout id */
|
||||
struct task spa_deadman_task;
|
||||
#endif
|
||||
#endif /* illumos */
|
||||
uint64_t spa_deadman_calls; /* number of deadman calls */
|
||||
|
@ -27,7 +27,7 @@
|
||||
* Portions Copyright 2010 Robert Milkowski
|
||||
*
|
||||
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
|
||||
* Copyright (c) 2012, 2014 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2012, 2016 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
|
||||
* Copyright (c) 2014 Integros [integros.com]
|
||||
*/
|
||||
@ -202,11 +202,22 @@ int zvol_maxphys = DMU_MAX_ACCESS/2;
|
||||
* Toggle unmap functionality.
|
||||
*/
|
||||
boolean_t zvol_unmap_enabled = B_TRUE;
|
||||
|
||||
/*
|
||||
* If true, unmaps requested as synchronous are executed synchronously,
|
||||
* otherwise all unmaps are asynchronous.
|
||||
*/
|
||||
boolean_t zvol_unmap_sync_enabled = B_FALSE;
|
||||
|
||||
#ifndef illumos
|
||||
SYSCTL_INT(_vfs_zfs_vol, OID_AUTO, unmap_enabled, CTLFLAG_RWTUN,
|
||||
&zvol_unmap_enabled, 0,
|
||||
"Enable UNMAP functionality");
|
||||
|
||||
SYSCTL_INT(_vfs_zfs_vol, OID_AUTO, unmap_sync_enabled, CTLFLAG_RWTUN,
|
||||
&zvol_unmap_sync_enabled, 0,
|
||||
"UNMAPs requested as sync are executed synchronously");
|
||||
|
||||
static d_open_t zvol_d_open;
|
||||
static d_close_t zvol_d_close;
|
||||
static d_read_t zvol_read;
|
||||
@ -2268,26 +2279,21 @@ zvol_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp)
|
||||
|
||||
zfs_range_unlock(rl);
|
||||
|
||||
if (error == 0) {
|
||||
/*
|
||||
* If the write-cache is disabled or 'sync' property
|
||||
* is set to 'always' then treat this as a synchronous
|
||||
* operation (i.e. commit to zil).
|
||||
*/
|
||||
if (!(zv->zv_flags & ZVOL_WCE) ||
|
||||
(zv->zv_objset->os_sync == ZFS_SYNC_ALWAYS))
|
||||
zil_commit(zv->zv_zilog, ZVOL_OBJ);
|
||||
|
||||
/*
|
||||
* If the caller really wants synchronous writes, and
|
||||
* can't wait for them, don't return until the write
|
||||
* is done.
|
||||
*/
|
||||
if (df.df_flags & DF_WAIT_SYNC) {
|
||||
txg_wait_synced(
|
||||
dmu_objset_pool(zv->zv_objset), 0);
|
||||
}
|
||||
/*
|
||||
* If the write-cache is disabled, 'sync' property
|
||||
* is set to 'always', or if the caller is asking for
|
||||
* a synchronous free, commit this operation to the zil.
|
||||
* This will sync any previous uncommitted writes to the
|
||||
* zvol object.
|
||||
* Can be overridden by the zvol_unmap_sync_enabled tunable.
|
||||
*/
|
||||
if ((error == 0) && zvol_unmap_sync_enabled &&
|
||||
(!(zv->zv_flags & ZVOL_WCE) ||
|
||||
(zv->zv_objset->os_sync == ZFS_SYNC_ALWAYS) ||
|
||||
(df.df_flags & DF_WAIT_SYNC))) {
|
||||
zil_commit(zv->zv_zilog, ZVOL_OBJ);
|
||||
}
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/limits.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/callout.h>
|
||||
#include <sys/capsicum.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/user.h>
|
||||
@ -63,6 +64,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <compat/linux/linux_emul.h>
|
||||
#include <compat/linux/linux_event.h>
|
||||
#include <compat/linux/linux_file.h>
|
||||
#include <compat/linux/linux_timer.h>
|
||||
#include <compat/linux/linux_util.h>
|
||||
|
||||
/*
|
||||
@ -123,7 +125,6 @@ typedef uint64_t eventfd_t;
|
||||
|
||||
static fo_rdwr_t eventfd_read;
|
||||
static fo_rdwr_t eventfd_write;
|
||||
static fo_truncate_t eventfd_truncate;
|
||||
static fo_ioctl_t eventfd_ioctl;
|
||||
static fo_poll_t eventfd_poll;
|
||||
static fo_kqfilter_t eventfd_kqfilter;
|
||||
@ -134,7 +135,7 @@ static fo_fill_kinfo_t eventfd_fill_kinfo;
|
||||
static struct fileops eventfdops = {
|
||||
.fo_read = eventfd_read,
|
||||
.fo_write = eventfd_write,
|
||||
.fo_truncate = eventfd_truncate,
|
||||
.fo_truncate = invfo_truncate,
|
||||
.fo_ioctl = eventfd_ioctl,
|
||||
.fo_poll = eventfd_poll,
|
||||
.fo_kqfilter = eventfd_kqfilter,
|
||||
@ -162,6 +163,41 @@ static struct filterops eventfd_wfiltops = {
|
||||
.f_event = filt_eventfdwrite
|
||||
};
|
||||
|
||||
/* timerfd */
|
||||
typedef uint64_t timerfd_t;
|
||||
|
||||
static fo_rdwr_t timerfd_read;
|
||||
static fo_poll_t timerfd_poll;
|
||||
static fo_kqfilter_t timerfd_kqfilter;
|
||||
static fo_stat_t timerfd_stat;
|
||||
static fo_close_t timerfd_close;
|
||||
static fo_fill_kinfo_t timerfd_fill_kinfo;
|
||||
|
||||
static struct fileops timerfdops = {
|
||||
.fo_read = timerfd_read,
|
||||
.fo_write = invfo_rdwr,
|
||||
.fo_truncate = invfo_truncate,
|
||||
.fo_ioctl = eventfd_ioctl,
|
||||
.fo_poll = timerfd_poll,
|
||||
.fo_kqfilter = timerfd_kqfilter,
|
||||
.fo_stat = timerfd_stat,
|
||||
.fo_close = timerfd_close,
|
||||
.fo_chmod = invfo_chmod,
|
||||
.fo_chown = invfo_chown,
|
||||
.fo_sendfile = invfo_sendfile,
|
||||
.fo_fill_kinfo = timerfd_fill_kinfo,
|
||||
.fo_flags = DFLAG_PASSABLE
|
||||
};
|
||||
|
||||
static void filt_timerfddetach(struct knote *kn);
|
||||
static int filt_timerfdread(struct knote *kn, long hint);
|
||||
|
||||
static struct filterops timerfd_rfiltops = {
|
||||
.f_isfd = 1,
|
||||
.f_detach = filt_timerfddetach,
|
||||
.f_event = filt_timerfdread
|
||||
};
|
||||
|
||||
struct eventfd {
|
||||
eventfd_t efd_count;
|
||||
uint32_t efd_flags;
|
||||
@ -169,7 +205,19 @@ struct eventfd {
|
||||
struct mtx efd_lock;
|
||||
};
|
||||
|
||||
struct timerfd {
|
||||
clockid_t tfd_clockid;
|
||||
struct itimerspec tfd_time;
|
||||
struct callout tfd_callout;
|
||||
timerfd_t tfd_count;
|
||||
bool tfd_canceled;
|
||||
struct selinfo tfd_sel;
|
||||
struct mtx tfd_lock;
|
||||
};
|
||||
|
||||
static int eventfd_create(struct thread *td, uint32_t initval, int flags);
|
||||
static void linux_timerfd_expire(void *);
|
||||
static void linux_timerfd_curval(struct timerfd *, struct itimerspec *);
|
||||
|
||||
|
||||
static void
|
||||
@ -207,7 +255,7 @@ epoll_create_common(struct thread *td, int flags)
|
||||
int error;
|
||||
|
||||
error = kern_kqueue(td, flags, NULL);
|
||||
if (error)
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
epoll_fd_install(td, EPOLL_DEF_SZ, 0);
|
||||
@ -309,14 +357,15 @@ kevent_to_epoll(struct kevent *kevent, struct epoll_event *l_event)
|
||||
return;
|
||||
}
|
||||
|
||||
/* XXX EPOLLPRI, EPOLLHUP */
|
||||
switch (kevent->filter) {
|
||||
case EVFILT_READ:
|
||||
l_event->events = LINUX_EPOLLIN|LINUX_EPOLLRDNORM|LINUX_EPOLLPRI;
|
||||
l_event->events = LINUX_EPOLLIN;
|
||||
if ((kevent->flags & EV_EOF) != 0)
|
||||
l_event->events |= LINUX_EPOLLRDHUP;
|
||||
break;
|
||||
case EVFILT_WRITE:
|
||||
l_event->events = LINUX_EPOLLOUT|LINUX_EPOLLWRNORM;
|
||||
l_event->events = LINUX_EPOLLOUT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -378,7 +427,7 @@ epoll_kev_copyin(void *arg, struct kevent *kevp, int count)
|
||||
struct epoll_copyin_args *args;
|
||||
|
||||
args = (struct epoll_copyin_args*) arg;
|
||||
|
||||
|
||||
memcpy(kevp, args->changelist, count * sizeof(*kevp));
|
||||
args->changelist += count;
|
||||
|
||||
@ -414,8 +463,10 @@ linux_epoll_ctl(struct thread *td, struct linux_epoll_ctl_args *args)
|
||||
cap_rights_init(&rights, CAP_KQUEUE_CHANGE), &epfp);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
if (epfp->f_type != DTYPE_KQUEUE)
|
||||
if (epfp->f_type != DTYPE_KQUEUE) {
|
||||
error = EINVAL;
|
||||
goto leave1;
|
||||
}
|
||||
|
||||
/* Protect user data vector from incorrectly supplied fd. */
|
||||
error = fget(td, args->fd, cap_rights_init(&rights, CAP_POLL_EVENT), &fp);
|
||||
@ -430,20 +481,34 @@ linux_epoll_ctl(struct thread *td, struct linux_epoll_ctl_args *args)
|
||||
|
||||
ciargs.changelist = kev;
|
||||
|
||||
if (args->op != LINUX_EPOLL_CTL_DEL) {
|
||||
kev_flags = EV_ADD | EV_ENABLE;
|
||||
error = epoll_to_kevent(td, epfp, args->fd, &le,
|
||||
&kev_flags, kev, &nchanges);
|
||||
if (error != 0)
|
||||
goto leave0;
|
||||
}
|
||||
|
||||
switch (args->op) {
|
||||
case LINUX_EPOLL_CTL_MOD:
|
||||
/*
|
||||
* We don't memorize which events were set for this FD
|
||||
* on this level, so just delete all we could have set:
|
||||
* EVFILT_READ and EVFILT_WRITE, ignoring any errors
|
||||
*/
|
||||
error = epoll_delete_all_events(td, epfp, args->fd);
|
||||
if (error)
|
||||
if (error != 0)
|
||||
goto leave0;
|
||||
/* FALLTHROUGH */
|
||||
break;
|
||||
|
||||
case LINUX_EPOLL_CTL_ADD:
|
||||
kev_flags = EV_ADD | EV_ENABLE;
|
||||
/*
|
||||
* kqueue_register() return ENOENT if event does not exists
|
||||
* and the EV_ADD flag is not set.
|
||||
*/
|
||||
kev[0].flags &= ~EV_ADD;
|
||||
error = kqfd_register(args->epfd, &kev[0], td, 1);
|
||||
if (error != ENOENT) {
|
||||
error = EEXIST;
|
||||
goto leave0;
|
||||
}
|
||||
error = 0;
|
||||
kev[0].flags |= EV_ADD;
|
||||
break;
|
||||
|
||||
case LINUX_EPOLL_CTL_DEL:
|
||||
@ -456,11 +521,6 @@ linux_epoll_ctl(struct thread *td, struct linux_epoll_ctl_args *args)
|
||||
goto leave0;
|
||||
}
|
||||
|
||||
error = epoll_to_kevent(td, epfp, args->fd, &le, &kev_flags,
|
||||
kev, &nchanges);
|
||||
if (error)
|
||||
goto leave0;
|
||||
|
||||
epoll_fd_install(td, args->fd, le.data);
|
||||
|
||||
error = kern_kevent_fp(td, epfp, nchanges, 0, &k_ops, NULL);
|
||||
@ -480,23 +540,32 @@ static int
|
||||
linux_epoll_wait_common(struct thread *td, int epfd, struct epoll_event *events,
|
||||
int maxevents, int timeout, sigset_t *uset)
|
||||
{
|
||||
struct file *epfp;
|
||||
struct timespec ts, *tsp;
|
||||
cap_rights_t rights;
|
||||
struct epoll_copyout_args coargs;
|
||||
struct kevent_copyops k_ops = { &coargs,
|
||||
epoll_kev_copyout,
|
||||
NULL};
|
||||
struct timespec ts, *tsp;
|
||||
cap_rights_t rights;
|
||||
struct file *epfp;
|
||||
sigset_t omask;
|
||||
int error;
|
||||
|
||||
if (maxevents <= 0 || maxevents > LINUX_MAX_EVENTS)
|
||||
return (EINVAL);
|
||||
|
||||
error = fget(td, epfd,
|
||||
cap_rights_init(&rights, CAP_KQUEUE_EVENT), &epfp);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
if (epfp->f_type != DTYPE_KQUEUE) {
|
||||
error = EINVAL;
|
||||
goto leave1;
|
||||
}
|
||||
if (uset != NULL) {
|
||||
error = kern_sigprocmask(td, SIG_SETMASK, uset,
|
||||
&td->td_oldsigmask, 0);
|
||||
&omask, 0);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
goto leave1;
|
||||
td->td_pflags |= TDP_OLDMASK;
|
||||
/*
|
||||
* Make sure that ast() is called on return to
|
||||
@ -508,10 +577,6 @@ linux_epoll_wait_common(struct thread *td, int epfd, struct epoll_event *events,
|
||||
thread_unlock(td);
|
||||
}
|
||||
|
||||
error = fget(td, epfd,
|
||||
cap_rights_init(&rights, CAP_KQUEUE_EVENT), &epfp);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
coargs.leventlist = events;
|
||||
coargs.p = td->td_proc;
|
||||
@ -521,7 +586,7 @@ linux_epoll_wait_common(struct thread *td, int epfd, struct epoll_event *events,
|
||||
if (timeout != -1) {
|
||||
if (timeout < 0) {
|
||||
error = EINVAL;
|
||||
goto leave;
|
||||
goto leave0;
|
||||
}
|
||||
/* Convert from milliseconds to timespec. */
|
||||
ts.tv_sec = timeout / 1000;
|
||||
@ -541,7 +606,12 @@ linux_epoll_wait_common(struct thread *td, int epfd, struct epoll_event *events,
|
||||
*/
|
||||
if (error == 0)
|
||||
td->td_retval[0] = coargs.count;
|
||||
leave:
|
||||
|
||||
leave0:
|
||||
if (uset != NULL)
|
||||
error = kern_sigprocmask(td, SIG_SETMASK, &omask,
|
||||
NULL, 0);
|
||||
leave1:
|
||||
fdrop(epfp, td);
|
||||
return (error);
|
||||
}
|
||||
@ -562,6 +632,8 @@ linux_epoll_pwait(struct thread *td, struct linux_epoll_pwait_args *args)
|
||||
int error;
|
||||
|
||||
if (args->mask != NULL) {
|
||||
if (args->sigsetsize != sizeof(l_sigset_t))
|
||||
return (EINVAL);
|
||||
error = copyin(args->mask, &lmask, sizeof(l_sigset_t));
|
||||
if (error != 0)
|
||||
return (error);
|
||||
@ -581,19 +653,11 @@ epoll_delete_event(struct thread *td, struct file *epfp, int fd, int filter)
|
||||
struct kevent_copyops k_ops = { &ciargs,
|
||||
NULL,
|
||||
epoll_kev_copyin};
|
||||
int error;
|
||||
|
||||
ciargs.changelist = &kev;
|
||||
EV_SET(&kev, fd, filter, EV_DELETE | EV_DISABLE, 0, 0, 0);
|
||||
|
||||
error = kern_kevent_fp(td, epfp, 1, 0, &k_ops, NULL);
|
||||
|
||||
/*
|
||||
* here we ignore ENONT, because we don't keep track of events here
|
||||
*/
|
||||
if (error == ENOENT)
|
||||
error = 0;
|
||||
return (error);
|
||||
return (kern_kevent_fp(td, epfp, 1, 0, &k_ops, NULL));
|
||||
}
|
||||
|
||||
static int
|
||||
@ -604,8 +668,8 @@ epoll_delete_all_events(struct thread *td, struct file *epfp, int fd)
|
||||
error1 = epoll_delete_event(td, epfp, fd, EVFILT_READ);
|
||||
error2 = epoll_delete_event(td, epfp, fd, EVFILT_WRITE);
|
||||
|
||||
/* report any errors we got */
|
||||
return (error1 == 0 ? error2 : error1);
|
||||
/* return 0 if at least one result positive */
|
||||
return (error1 == 0 ? 0 : error2);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -622,7 +686,7 @@ eventfd_create(struct thread *td, uint32_t initval, int flags)
|
||||
|
||||
fdp = td->td_proc->p_fd;
|
||||
error = falloc(td, &fp, &fd, fflags);
|
||||
if (error)
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
efd = malloc(sizeof(*efd), M_EPOLL, M_WAITOK | M_ZERO);
|
||||
@ -667,7 +731,7 @@ eventfd_close(struct file *fp, struct thread *td)
|
||||
|
||||
efd = fp->f_data;
|
||||
if (fp->f_type != DTYPE_LINUXEFD || efd == NULL)
|
||||
return (EBADF);
|
||||
return (EINVAL);
|
||||
|
||||
seldrain(&efd->efd_sel);
|
||||
knlist_destroy(&efd->efd_sel.si_note);
|
||||
@ -681,7 +745,7 @@ eventfd_close(struct file *fp, struct thread *td)
|
||||
|
||||
static int
|
||||
eventfd_read(struct file *fp, struct uio *uio, struct ucred *active_cred,
|
||||
int flags, struct thread *td)
|
||||
int flags, struct thread *td)
|
||||
{
|
||||
struct eventfd *efd;
|
||||
eventfd_t count;
|
||||
@ -689,7 +753,7 @@ eventfd_read(struct file *fp, struct uio *uio, struct ucred *active_cred,
|
||||
|
||||
efd = fp->f_data;
|
||||
if (fp->f_type != DTYPE_LINUXEFD || efd == NULL)
|
||||
return (EBADF);
|
||||
return (EINVAL);
|
||||
|
||||
if (uio->uio_resid < sizeof(eventfd_t))
|
||||
return (EINVAL);
|
||||
@ -698,7 +762,7 @@ eventfd_read(struct file *fp, struct uio *uio, struct ucred *active_cred,
|
||||
mtx_lock(&efd->efd_lock);
|
||||
retry:
|
||||
if (efd->efd_count == 0) {
|
||||
if ((efd->efd_flags & LINUX_O_NONBLOCK) != 0) {
|
||||
if ((fp->f_flag & FNONBLOCK) != 0) {
|
||||
mtx_unlock(&efd->efd_lock);
|
||||
return (EAGAIN);
|
||||
}
|
||||
@ -727,7 +791,7 @@ retry:
|
||||
|
||||
static int
|
||||
eventfd_write(struct file *fp, struct uio *uio, struct ucred *active_cred,
|
||||
int flags, struct thread *td)
|
||||
int flags, struct thread *td)
|
||||
{
|
||||
struct eventfd *efd;
|
||||
eventfd_t count;
|
||||
@ -735,13 +799,13 @@ eventfd_write(struct file *fp, struct uio *uio, struct ucred *active_cred,
|
||||
|
||||
efd = fp->f_data;
|
||||
if (fp->f_type != DTYPE_LINUXEFD || efd == NULL)
|
||||
return (EBADF);
|
||||
return (EINVAL);
|
||||
|
||||
if (uio->uio_resid < sizeof(eventfd_t))
|
||||
return (EINVAL);
|
||||
|
||||
error = uiomove(&count, sizeof(eventfd_t), uio);
|
||||
if (error)
|
||||
if (error != 0)
|
||||
return (error);
|
||||
if (count == UINT64_MAX)
|
||||
return (EINVAL);
|
||||
@ -749,7 +813,7 @@ eventfd_write(struct file *fp, struct uio *uio, struct ucred *active_cred,
|
||||
mtx_lock(&efd->efd_lock);
|
||||
retry:
|
||||
if (UINT64_MAX - efd->efd_count <= count) {
|
||||
if ((efd->efd_flags & LINUX_O_NONBLOCK) != 0) {
|
||||
if ((fp->f_flag & FNONBLOCK) != 0) {
|
||||
mtx_unlock(&efd->efd_lock);
|
||||
/* Do not not return the number of bytes written */
|
||||
uio->uio_resid += sizeof(eventfd_t);
|
||||
@ -773,7 +837,7 @@ retry:
|
||||
|
||||
static int
|
||||
eventfd_poll(struct file *fp, int events, struct ucred *active_cred,
|
||||
struct thread *td)
|
||||
struct thread *td)
|
||||
{
|
||||
struct eventfd *efd;
|
||||
int revents = 0;
|
||||
@ -860,33 +924,23 @@ filt_eventfdwrite(struct knote *kn, long hint)
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
static int
|
||||
eventfd_truncate(struct file *fp, off_t length, struct ucred *active_cred,
|
||||
struct thread *td)
|
||||
{
|
||||
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
static int
|
||||
eventfd_ioctl(struct file *fp, u_long cmd, void *data,
|
||||
struct ucred *active_cred, struct thread *td)
|
||||
struct ucred *active_cred, struct thread *td)
|
||||
{
|
||||
struct eventfd *efd;
|
||||
|
||||
efd = fp->f_data;
|
||||
if (fp->f_type != DTYPE_LINUXEFD || efd == NULL)
|
||||
if (fp->f_data == NULL || (fp->f_type != DTYPE_LINUXEFD &&
|
||||
fp->f_type != DTYPE_LINUXTFD))
|
||||
return (EINVAL);
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case FIONBIO:
|
||||
if (*(int *)data)
|
||||
efd->efd_flags |= LINUX_O_NONBLOCK;
|
||||
if ((*(int *)data))
|
||||
atomic_set_int(&fp->f_flag, FNONBLOCK);
|
||||
else
|
||||
efd->efd_flags &= ~LINUX_O_NONBLOCK;
|
||||
atomic_clear_int(&fp->f_flag, FNONBLOCK);
|
||||
case FIOASYNC:
|
||||
return (0);
|
||||
default:
|
||||
@ -897,7 +951,7 @@ eventfd_ioctl(struct file *fp, u_long cmd, void *data,
|
||||
/*ARGSUSED*/
|
||||
static int
|
||||
eventfd_stat(struct file *fp, struct stat *st, struct ucred *active_cred,
|
||||
struct thread *td)
|
||||
struct thread *td)
|
||||
{
|
||||
|
||||
return (ENXIO);
|
||||
@ -911,3 +965,360 @@ eventfd_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp
|
||||
kif->kf_type = KF_TYPE_UNKNOWN;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
linux_timerfd_create(struct thread *td, struct linux_timerfd_create_args *args)
|
||||
{
|
||||
struct filedesc *fdp;
|
||||
struct timerfd *tfd;
|
||||
struct file *fp;
|
||||
clockid_t clockid;
|
||||
int fflags, fd, error;
|
||||
|
||||
if ((args->flags & ~LINUX_TFD_CREATE_FLAGS) != 0)
|
||||
return (EINVAL);
|
||||
|
||||
error = linux_to_native_clockid(&clockid, args->clockid);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
if (clockid != CLOCK_REALTIME && clockid != CLOCK_MONOTONIC)
|
||||
return (EINVAL);
|
||||
|
||||
fflags = 0;
|
||||
if ((args->flags & LINUX_TFD_CLOEXEC) != 0)
|
||||
fflags |= O_CLOEXEC;
|
||||
|
||||
fdp = td->td_proc->p_fd;
|
||||
error = falloc(td, &fp, &fd, fflags);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
tfd = malloc(sizeof(*tfd), M_EPOLL, M_WAITOK | M_ZERO);
|
||||
tfd->tfd_clockid = clockid;
|
||||
mtx_init(&tfd->tfd_lock, "timerfd", NULL, MTX_DEF);
|
||||
|
||||
callout_init_mtx(&tfd->tfd_callout, &tfd->tfd_lock, 0);
|
||||
knlist_init_mtx(&tfd->tfd_sel.si_note, &tfd->tfd_lock);
|
||||
|
||||
fflags = FREAD;
|
||||
if ((args->flags & LINUX_O_NONBLOCK) != 0)
|
||||
fflags |= FNONBLOCK;
|
||||
|
||||
finit(fp, fflags, DTYPE_LINUXTFD, tfd, &timerfdops);
|
||||
fdrop(fp, td);
|
||||
|
||||
td->td_retval[0] = fd;
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
timerfd_close(struct file *fp, struct thread *td)
|
||||
{
|
||||
struct timerfd *tfd;
|
||||
|
||||
tfd = fp->f_data;
|
||||
if (fp->f_type != DTYPE_LINUXTFD || tfd == NULL)
|
||||
return (EINVAL);
|
||||
|
||||
timespecclear(&tfd->tfd_time.it_value);
|
||||
timespecclear(&tfd->tfd_time.it_interval);
|
||||
|
||||
mtx_lock(&tfd->tfd_lock);
|
||||
callout_drain(&tfd->tfd_callout);
|
||||
mtx_unlock(&tfd->tfd_lock);
|
||||
|
||||
seldrain(&tfd->tfd_sel);
|
||||
knlist_destroy(&tfd->tfd_sel.si_note);
|
||||
|
||||
fp->f_ops = &badfileops;
|
||||
mtx_destroy(&tfd->tfd_lock);
|
||||
free(tfd, M_EPOLL);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
timerfd_read(struct file *fp, struct uio *uio, struct ucred *active_cred,
|
||||
int flags, struct thread *td)
|
||||
{
|
||||
struct timerfd *tfd;
|
||||
timerfd_t count;
|
||||
int error;
|
||||
|
||||
tfd = fp->f_data;
|
||||
if (fp->f_type != DTYPE_LINUXTFD || tfd == NULL)
|
||||
return (EINVAL);
|
||||
|
||||
if (uio->uio_resid < sizeof(timerfd_t))
|
||||
return (EINVAL);
|
||||
|
||||
error = 0;
|
||||
mtx_lock(&tfd->tfd_lock);
|
||||
retry:
|
||||
if (tfd->tfd_canceled) {
|
||||
tfd->tfd_count = 0;
|
||||
mtx_unlock(&tfd->tfd_lock);
|
||||
return (ECANCELED);
|
||||
}
|
||||
if (tfd->tfd_count == 0) {
|
||||
if ((fp->f_flag & FNONBLOCK) != 0) {
|
||||
mtx_unlock(&tfd->tfd_lock);
|
||||
return (EAGAIN);
|
||||
}
|
||||
error = mtx_sleep(&tfd->tfd_count, &tfd->tfd_lock, PCATCH, "ltfdrd", 0);
|
||||
if (error == 0)
|
||||
goto retry;
|
||||
}
|
||||
if (error == 0) {
|
||||
count = tfd->tfd_count;
|
||||
tfd->tfd_count = 0;
|
||||
mtx_unlock(&tfd->tfd_lock);
|
||||
error = uiomove(&count, sizeof(timerfd_t), uio);
|
||||
} else
|
||||
mtx_unlock(&tfd->tfd_lock);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
timerfd_poll(struct file *fp, int events, struct ucred *active_cred,
|
||||
struct thread *td)
|
||||
{
|
||||
struct timerfd *tfd;
|
||||
int revents = 0;
|
||||
|
||||
tfd = fp->f_data;
|
||||
if (fp->f_type != DTYPE_LINUXTFD || tfd == NULL)
|
||||
return (POLLERR);
|
||||
|
||||
mtx_lock(&tfd->tfd_lock);
|
||||
if ((events & (POLLIN|POLLRDNORM)) && tfd->tfd_count > 0)
|
||||
revents |= events & (POLLIN|POLLRDNORM);
|
||||
if (revents == 0)
|
||||
selrecord(td, &tfd->tfd_sel);
|
||||
mtx_unlock(&tfd->tfd_lock);
|
||||
|
||||
return (revents);
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
static int
|
||||
timerfd_kqfilter(struct file *fp, struct knote *kn)
|
||||
{
|
||||
struct timerfd *tfd;
|
||||
|
||||
tfd = fp->f_data;
|
||||
if (fp->f_type != DTYPE_LINUXTFD || tfd == NULL)
|
||||
return (EINVAL);
|
||||
|
||||
if (kn->kn_filter == EVFILT_READ)
|
||||
kn->kn_fop = &timerfd_rfiltops;
|
||||
else
|
||||
return (EINVAL);
|
||||
|
||||
kn->kn_hook = tfd;
|
||||
knlist_add(&tfd->tfd_sel.si_note, kn, 0);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
filt_timerfddetach(struct knote *kn)
|
||||
{
|
||||
struct timerfd *tfd = kn->kn_hook;
|
||||
|
||||
mtx_lock(&tfd->tfd_lock);
|
||||
knlist_remove(&tfd->tfd_sel.si_note, kn, 1);
|
||||
mtx_unlock(&tfd->tfd_lock);
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
static int
|
||||
filt_timerfdread(struct knote *kn, long hint)
|
||||
{
|
||||
struct timerfd *tfd = kn->kn_hook;
|
||||
|
||||
return (tfd->tfd_count > 0);
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
static int
|
||||
timerfd_stat(struct file *fp, struct stat *st, struct ucred *active_cred,
|
||||
struct thread *td)
|
||||
{
|
||||
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
static int
|
||||
timerfd_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp)
|
||||
{
|
||||
|
||||
kif->kf_type = KF_TYPE_UNKNOWN;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
linux_timerfd_clocktime(struct timerfd *tfd, struct timespec *ts)
|
||||
{
|
||||
|
||||
if (tfd->tfd_clockid == CLOCK_REALTIME)
|
||||
getnanotime(ts);
|
||||
else /* CLOCK_MONOTONIC */
|
||||
getnanouptime(ts);
|
||||
}
|
||||
|
||||
static void
|
||||
linux_timerfd_curval(struct timerfd *tfd, struct itimerspec *ots)
|
||||
{
|
||||
struct timespec cts;
|
||||
|
||||
linux_timerfd_clocktime(tfd, &cts);
|
||||
*ots = tfd->tfd_time;
|
||||
if (ots->it_value.tv_sec != 0 || ots->it_value.tv_nsec != 0) {
|
||||
timespecsub(&ots->it_value, &cts);
|
||||
if (ots->it_value.tv_sec < 0 ||
|
||||
(ots->it_value.tv_sec == 0 &&
|
||||
ots->it_value.tv_nsec == 0)) {
|
||||
ots->it_value.tv_sec = 0;
|
||||
ots->it_value.tv_nsec = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
linux_timerfd_gettime(struct thread *td, struct linux_timerfd_gettime_args *args)
|
||||
{
|
||||
cap_rights_t rights;
|
||||
struct l_itimerspec lots;
|
||||
struct itimerspec ots;
|
||||
struct timerfd *tfd;
|
||||
struct file *fp;
|
||||
int error;
|
||||
|
||||
error = fget(td, args->fd, cap_rights_init(&rights, CAP_READ), &fp);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
tfd = fp->f_data;
|
||||
if (fp->f_type != DTYPE_LINUXTFD || tfd == NULL) {
|
||||
error = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
mtx_lock(&tfd->tfd_lock);
|
||||
linux_timerfd_curval(tfd, &ots);
|
||||
mtx_unlock(&tfd->tfd_lock);
|
||||
|
||||
error = native_to_linux_itimerspec(&lots, &ots);
|
||||
if (error == 0)
|
||||
error = copyout(&lots, args->old_value, sizeof(lots));
|
||||
|
||||
out:
|
||||
fdrop(fp, td);
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
linux_timerfd_settime(struct thread *td, struct linux_timerfd_settime_args *args)
|
||||
{
|
||||
struct l_itimerspec lots;
|
||||
struct itimerspec nts, ots;
|
||||
struct timespec cts, ts;
|
||||
cap_rights_t rights;
|
||||
struct timerfd *tfd;
|
||||
struct timeval tv;
|
||||
struct file *fp;
|
||||
int error;
|
||||
|
||||
if ((args->flags & ~LINUX_TFD_SETTIME_FLAGS) != 0)
|
||||
return (EINVAL);
|
||||
|
||||
error = copyin(args->new_value, &lots, sizeof(lots));
|
||||
if (error != 0)
|
||||
return (error);
|
||||
error = linux_to_native_itimerspec(&nts, &lots);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
error = fget(td, args->fd, cap_rights_init(&rights, CAP_WRITE), &fp);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
tfd = fp->f_data;
|
||||
if (fp->f_type != DTYPE_LINUXTFD || tfd == NULL) {
|
||||
error = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
mtx_lock(&tfd->tfd_lock);
|
||||
if (!timespecisset(&nts.it_value))
|
||||
timespecclear(&nts.it_interval);
|
||||
if (args->old_value != NULL)
|
||||
linux_timerfd_curval(tfd, &ots);
|
||||
|
||||
tfd->tfd_time = nts;
|
||||
if (timespecisset(&nts.it_value)) {
|
||||
linux_timerfd_clocktime(tfd, &cts);
|
||||
ts = nts.it_value;
|
||||
if ((args->flags & LINUX_TFD_TIMER_ABSTIME) == 0) {
|
||||
timespecadd(&tfd->tfd_time.it_value, &cts);
|
||||
} else {
|
||||
timespecsub(&ts, &cts);
|
||||
}
|
||||
TIMESPEC_TO_TIMEVAL(&tv, &ts);
|
||||
callout_reset(&tfd->tfd_callout, tvtohz(&tv),
|
||||
linux_timerfd_expire, tfd);
|
||||
tfd->tfd_canceled = false;
|
||||
} else {
|
||||
tfd->tfd_canceled = true;
|
||||
callout_stop(&tfd->tfd_callout);
|
||||
}
|
||||
mtx_unlock(&tfd->tfd_lock);
|
||||
|
||||
if (args->old_value != NULL) {
|
||||
error = native_to_linux_itimerspec(&lots, &ots);
|
||||
if (error == 0)
|
||||
error = copyout(&lots, args->old_value, sizeof(lots));
|
||||
}
|
||||
|
||||
out:
|
||||
fdrop(fp, td);
|
||||
return (error);
|
||||
}
|
||||
|
||||
static void
|
||||
linux_timerfd_expire(void *arg)
|
||||
{
|
||||
struct timespec cts, ts;
|
||||
struct timeval tv;
|
||||
struct timerfd *tfd;
|
||||
|
||||
tfd = (struct timerfd *)arg;
|
||||
|
||||
linux_timerfd_clocktime(tfd, &cts);
|
||||
if (timespeccmp(&cts, &tfd->tfd_time.it_value, >=)) {
|
||||
if (timespecisset(&tfd->tfd_time.it_interval))
|
||||
timespecadd(&tfd->tfd_time.it_value,
|
||||
&tfd->tfd_time.it_interval);
|
||||
else
|
||||
/* single shot timer */
|
||||
timespecclear(&tfd->tfd_time.it_value);
|
||||
if (timespecisset(&tfd->tfd_time.it_value)) {
|
||||
ts = tfd->tfd_time.it_value;
|
||||
timespecsub(&ts, &cts);
|
||||
TIMESPEC_TO_TIMEVAL(&tv, &ts);
|
||||
callout_reset(&tfd->tfd_callout, tvtohz(&tv),
|
||||
linux_timerfd_expire, tfd);
|
||||
}
|
||||
tfd->tfd_count++;
|
||||
KNOTE_LOCKED(&tfd->tfd_sel.si_note, 0);
|
||||
selwakeup(&tfd->tfd_sel);
|
||||
wakeup(&tfd->tfd_count);
|
||||
} else if (timespecisset(&tfd->tfd_time.it_value)) {
|
||||
ts = tfd->tfd_time.it_value;
|
||||
timespecsub(&ts, &cts);
|
||||
TIMESPEC_TO_TIMEVAL(&tv, &ts);
|
||||
callout_reset(&tfd->tfd_callout, tvtohz(&tv),
|
||||
linux_timerfd_expire, tfd);
|
||||
}
|
||||
}
|
||||
|
@ -57,4 +57,15 @@
|
||||
|
||||
#define LINUX_EFD_SEMAPHORE (1 << 0)
|
||||
|
||||
#define LINUX_TFD_TIMER_ABSTIME (1 << 0)
|
||||
#define LINUX_TFD_TIMER_CANCEL_ON_SET (1 << 1)
|
||||
#define LINUX_TFD_CLOEXEC LINUX_O_CLOEXEC
|
||||
#define LINUX_TFD_NONBLOCK LINUX_O_NONBLOCK
|
||||
|
||||
#define LINUX_TFD_SHARED_FCNTL_FLAGS (LINUX_TFD_CLOEXEC \
|
||||
|LINUX_TFD_NONBLOCK)
|
||||
#define LINUX_TFD_CREATE_FLAGS LINUX_TFD_SHARED_FCNTL_FLAGS
|
||||
#define LINUX_TFD_SETTIME_FLAGS (LINUX_TFD_TIMER_ABSTIME \
|
||||
|LINUX_TFD_TIMER_CANCEL_ON_SET)
|
||||
|
||||
#endif /* !_LINUX_EVENT_H_ */
|
||||
|
@ -2290,8 +2290,9 @@ linux_pselect6(struct thread *td, struct linux_pselect6_args *args)
|
||||
|
||||
TIMEVAL_TO_TIMESPEC(&utv, &uts);
|
||||
|
||||
native_to_linux_timespec(<s, &uts);
|
||||
error = copyout(<s, args->tsp, sizeof(lts));
|
||||
error = native_to_linux_timespec(<s, &uts);
|
||||
if (error == 0)
|
||||
error = copyout(<s, args->tsp, sizeof(lts));
|
||||
}
|
||||
|
||||
return (error);
|
||||
@ -2343,8 +2344,9 @@ linux_ppoll(struct thread *td, struct linux_ppoll_args *args)
|
||||
} else
|
||||
timespecclear(&uts);
|
||||
|
||||
native_to_linux_timespec(<s, &uts);
|
||||
error = copyout(<s, args->tsp, sizeof(lts));
|
||||
error = native_to_linux_timespec(<s, &uts);
|
||||
if (error == 0)
|
||||
error = copyout(<s, args->tsp, sizeof(lts));
|
||||
}
|
||||
|
||||
return (error);
|
||||
@ -2438,7 +2440,9 @@ linux_sched_rr_get_interval(struct thread *td,
|
||||
PROC_UNLOCK(tdt->td_proc);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
native_to_linux_timespec(<s, &ts);
|
||||
error = native_to_linux_timespec(<s, &ts);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
return (copyout(<s, uap->interval, sizeof(lts)));
|
||||
}
|
||||
|
||||
|
@ -303,7 +303,9 @@ struct l_statfs {
|
||||
l_long f_ffree;
|
||||
l_fsid_t f_fsid;
|
||||
l_long f_namelen;
|
||||
l_long f_spare[6];
|
||||
l_long f_frsize;
|
||||
l_long f_flags;
|
||||
l_long f_spare[4];
|
||||
};
|
||||
|
||||
#define LINUX_CODA_SUPER_MAGIC 0x73757245L
|
||||
@ -371,6 +373,9 @@ bsd_to_linux_statfs(struct statfs *bsd_statfs, struct l_statfs *linux_statfs)
|
||||
linux_statfs->f_fsid.val[0] = bsd_statfs->f_fsid.val[0];
|
||||
linux_statfs->f_fsid.val[1] = bsd_statfs->f_fsid.val[1];
|
||||
linux_statfs->f_namelen = MAXNAMLEN;
|
||||
linux_statfs->f_frsize = bsd_statfs->f_bsize;
|
||||
linux_statfs->f_flags = 0;
|
||||
memset(linux_statfs->f_spare, 0, sizeof(linux_statfs->f_spare));
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -415,6 +420,9 @@ bsd_to_linux_statfs64(struct statfs *bsd_statfs, struct l_statfs64 *linux_statfs
|
||||
linux_statfs->f_fsid.val[0] = bsd_statfs->f_fsid.val[0];
|
||||
linux_statfs->f_fsid.val[1] = bsd_statfs->f_fsid.val[1];
|
||||
linux_statfs->f_namelen = MAXNAMLEN;
|
||||
linux_statfs->f_frsize = bsd_statfs->f_bsize;
|
||||
linux_statfs->f_flags = 0;
|
||||
memset(linux_statfs->f_spare, 0, sizeof(linux_statfs->f_spare));
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -41,6 +41,7 @@ __KERNEL_RCSID(0, "$NetBSD: linux_time.c,v 1.14 2006/05/14 03:40:54 christos Exp
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/ucred.h>
|
||||
#include <sys/limits.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/resourcevar.h>
|
||||
@ -118,16 +119,21 @@ LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, unsupported_clockid, "int");
|
||||
LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, return, "int");
|
||||
|
||||
|
||||
void
|
||||
int
|
||||
native_to_linux_timespec(struct l_timespec *ltp, struct timespec *ntp)
|
||||
{
|
||||
|
||||
LIN_SDT_PROBE2(time, native_to_linux_timespec, entry, ltp, ntp);
|
||||
|
||||
#ifdef COMPAT_LINUX32
|
||||
if (ntp->tv_sec > INT_MAX &&
|
||||
sizeof(ltp->tv_sec) != sizeof(ntp->tv_sec))
|
||||
return (EOVERFLOW);
|
||||
#endif
|
||||
ltp->tv_sec = ntp->tv_sec;
|
||||
ltp->tv_nsec = ntp->tv_nsec;
|
||||
|
||||
LIN_SDT_PROBE0(time, native_to_linux_timespec, return);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
@ -147,6 +153,28 @@ linux_to_native_timespec(struct timespec *ntp, struct l_timespec *ltp)
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
native_to_linux_itimerspec(struct l_itimerspec *ltp, struct itimerspec *ntp)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = native_to_linux_timespec(<p->it_interval, &ntp->it_interval);
|
||||
if (error == 0)
|
||||
error = native_to_linux_timespec(<p->it_value, &ntp->it_interval);
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
linux_to_native_itimerspec(struct itimerspec *ntp, struct l_itimerspec *ltp)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = linux_to_native_timespec(&ntp->it_interval, <p->it_interval);
|
||||
if (error == 0)
|
||||
error = linux_to_native_timespec(&ntp->it_value, <p->it_value);
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
linux_to_native_clockid(clockid_t *n, clockid_t l)
|
||||
{
|
||||
@ -322,8 +350,9 @@ linux_clock_gettime(struct thread *td, struct linux_clock_gettime_args *args)
|
||||
LIN_SDT_PROBE1(time, linux_clock_gettime, return, error);
|
||||
return (error);
|
||||
}
|
||||
native_to_linux_timespec(<s, &tp);
|
||||
|
||||
error = native_to_linux_timespec(<s, &tp);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
error = copyout(<s, args->tp, sizeof lts);
|
||||
if (error != 0)
|
||||
LIN_SDT_PROBE1(time, linux_clock_gettime, copyout_error, error);
|
||||
@ -450,8 +479,9 @@ linux_clock_getres(struct thread *td, struct linux_clock_getres_args *args)
|
||||
LIN_SDT_PROBE1(time, linux_clock_getres, return, error);
|
||||
return (error);
|
||||
}
|
||||
native_to_linux_timespec(<s, &ts);
|
||||
|
||||
error = native_to_linux_timespec(<s, &ts);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
error = copyout(<s, args->tp, sizeof lts);
|
||||
if (error != 0)
|
||||
LIN_SDT_PROBE1(time, linux_clock_getres, copyout_error, error);
|
||||
@ -490,7 +520,9 @@ linux_nanosleep(struct thread *td, struct linux_nanosleep_args *args)
|
||||
}
|
||||
error = kern_nanosleep(td, &rqts, rmtp);
|
||||
if (args->rmtp != NULL) {
|
||||
native_to_linux_timespec(&lrmts, rmtp);
|
||||
error2 = native_to_linux_timespec(&lrmts, rmtp);
|
||||
if (error2 != 0)
|
||||
return (error2);
|
||||
error2 = copyout(&lrmts, args->rmtp, sizeof(lrmts));
|
||||
if (error2 != 0) {
|
||||
LIN_SDT_PROBE1(time, linux_nanosleep, copyout_error,
|
||||
@ -553,7 +585,9 @@ linux_clock_nanosleep(struct thread *td, struct linux_clock_nanosleep_args *args
|
||||
error = kern_nanosleep(td, &rqts, rmtp);
|
||||
if (args->rmtp != NULL) {
|
||||
/* XXX. Not for TIMER_ABSTIME */
|
||||
native_to_linux_timespec(&lrmts, rmtp);
|
||||
error2 = native_to_linux_timespec(&lrmts, rmtp);
|
||||
if (error2 != 0)
|
||||
return (error2);
|
||||
error2 = copyout(&lrmts, args->rmtp, sizeof(lrmts));
|
||||
if (error2 != 0) {
|
||||
LIN_SDT_PROBE1(time, linux_clock_nanosleep,
|
||||
|
@ -111,10 +111,14 @@ struct l_itimerspec {
|
||||
struct l_timespec it_value;
|
||||
};
|
||||
|
||||
void native_to_linux_timespec(struct l_timespec *,
|
||||
int native_to_linux_timespec(struct l_timespec *,
|
||||
struct timespec *);
|
||||
int linux_to_native_timespec(struct timespec *,
|
||||
struct l_timespec *);
|
||||
int linux_to_native_clockid(clockid_t *, clockid_t);
|
||||
int native_to_linux_itimerspec(struct l_itimerspec *,
|
||||
struct itimerspec *);
|
||||
int linux_to_native_itimerspec(struct itimerspec *,
|
||||
struct l_itimerspec *);
|
||||
|
||||
#endif /* _LINUX_TIMER_H */
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/libkern.h>
|
||||
|
||||
#define BIT(nr) (1UL << (nr))
|
||||
#define BIT_ULL(nr) (1ULL << (nr))
|
||||
@ -43,6 +44,7 @@
|
||||
#else
|
||||
#define BITS_PER_LONG 32
|
||||
#endif
|
||||
|
||||
#define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) % BITS_PER_LONG))
|
||||
#define BITMAP_LAST_WORD_MASK(n) (~0UL >> (BITS_PER_LONG - (n)))
|
||||
#define BITS_TO_LONGS(n) howmany((n), BITS_PER_LONG)
|
||||
@ -51,6 +53,12 @@
|
||||
#define GENMASK(h, l) (((~0UL) >> (BITS_PER_LONG - (h) - 1)) & ((~0UL) << (l)))
|
||||
#define BITS_PER_BYTE 8
|
||||
|
||||
#define hweight8(x) bitcount((uint8_t)(x))
|
||||
#define hweight16(x) bitcount16(x)
|
||||
#define hweight32(x) bitcount32(x)
|
||||
#define hweight64(x) bitcount64(x)
|
||||
#define hweight_long(x) bitcountl(x)
|
||||
|
||||
static inline int
|
||||
__ffs(int mask)
|
||||
{
|
||||
@ -75,10 +83,15 @@ __flsl(long mask)
|
||||
return (flsl(mask) - 1);
|
||||
}
|
||||
|
||||
static inline int
|
||||
fls64(uint64_t mask)
|
||||
{
|
||||
return (flsll(mask));
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
ror32(uint32_t word, unsigned int shift)
|
||||
{
|
||||
|
||||
return ((word >> shift) | (word << (32 - shift)));
|
||||
}
|
||||
|
||||
@ -542,4 +555,12 @@ bitmap_equal(const unsigned long *pa,
|
||||
return (1);
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
sign_extend64(uint64_t value, int index)
|
||||
{
|
||||
uint8_t shift = 63 - index;
|
||||
|
||||
return ((int64_t)(value << shift) >> shift);
|
||||
}
|
||||
|
||||
#endif /* _LINUX_BITOPS_H_ */
|
||||
|
@ -57,6 +57,7 @@ typedef unsigned int uint;
|
||||
typedef unsigned gfp_t;
|
||||
typedef uint64_t loff_t;
|
||||
typedef vm_paddr_t resource_size_t;
|
||||
typedef uint16_t __bitwise__ __sum16;
|
||||
|
||||
typedef u64 phys_addr_t;
|
||||
|
||||
|
@ -1,13 +0,0 @@
|
||||
# Makefile for syscall tables
|
||||
#
|
||||
# $FreeBSD$
|
||||
|
||||
all:
|
||||
@echo "make sysent only"
|
||||
|
||||
sysent: svr4_sysent.c svr4_syscall.h svr4_proto.h
|
||||
|
||||
svr4_syscallnames.c svr4_sysent.c svr4_syscall.h svr4_proto.h: \
|
||||
../../kern/makesyscalls.sh syscalls.master syscalls.conf
|
||||
sh ../../kern/makesyscalls.sh syscalls.master syscalls.conf
|
||||
|
@ -1,38 +0,0 @@
|
||||
This is a SysVR4 emulator derived from work done as part of the NetBSD
|
||||
Project by Christos Zoulas. It has been ported to FreeBSD by Mark Newton.
|
||||
|
||||
To use it:
|
||||
|
||||
1. Choose one of:
|
||||
a. Add "device streams" to your kernel config file and rebuild,
|
||||
reboot; or
|
||||
b. Build and install the streams module in /sys/modules/streams
|
||||
|
||||
2. Build and install the svr4 module in /sys/modules/svr4
|
||||
|
||||
3. Type "kldload svr4" to start it up.
|
||||
|
||||
4. Grab compat_sol26.tar.gz or compat_svr4.tar.gz from
|
||||
http://www.freebsd.org/~newton/freebsd-svr4 and install them in
|
||||
/compat/svr4
|
||||
|
||||
5. Run "sh SVR4_MAKEDEV all" in /compat/svr4/dev
|
||||
|
||||
6. Mount a Solaris/x86 v2.6 or v7 CD-ROM on /cdrom (also works with
|
||||
v2.4 and v2.5.1, but you need different symlinks in /compat/svr4)
|
||||
|
||||
7. Brand any executables you want to run, and/or set the
|
||||
kern.fallback_elf_brand sysctl to 'SVR4' to establish this as the
|
||||
default emulator for unbranded executables.
|
||||
|
||||
8. See if your SysVR4 programs work.
|
||||
|
||||
It's early days yet, folks -- You'll probably have trouble getting 100%
|
||||
functionality out of most things (specifically, poll() on a socket doesn't
|
||||
look like it works at the moment, so Netscape doesn't work (among other
|
||||
things)). Patches will be appreciated.
|
||||
|
||||
- Mark Newton
|
||||
newton@atdot.dotat.org
|
||||
|
||||
$FreeBSD$
|
@ -1,15 +0,0 @@
|
||||
TO-DO list
|
||||
----------
|
||||
|
||||
* svr4_getdents64() doesn't work properly in 'large' directories.
|
||||
|
||||
* signals are still suspect
|
||||
|
||||
* networking is notworking
|
||||
|
||||
* VM86 and USER_LDT are currently disabled (low-priority)
|
||||
|
||||
* Make SysV emulator use SysV shared memory support (duh)
|
||||
|
||||
|
||||
$FreeBSD$
|
@ -1,238 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1998 Mark Newton
|
||||
* Copyright (c) 1994-1996 Søren Schmidt
|
||||
* All rights reserved.
|
||||
*
|
||||
* Based heavily on /sys/kern/imgact_aout.c which is:
|
||||
* Copyright (c) 1993, David Greenman
|
||||
*
|
||||
* 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
|
||||
* in this position and unchanged.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission
|
||||
*
|
||||
* 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/exec.h>
|
||||
#include <sys/imgact.h>
|
||||
#include <sys/imgact_aout.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/racct.h>
|
||||
#include <sys/resourcevar.h>
|
||||
#include <sys/vnode.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_kern.h>
|
||||
#include <vm/vm_param.h>
|
||||
#include <vm/pmap.h>
|
||||
#include <vm/vm_map.h>
|
||||
#include <vm/vm_extern.h>
|
||||
|
||||
#include <compat/svr4/svr4.h>
|
||||
|
||||
static int exec_svr4_imgact(struct image_params *iparams);
|
||||
|
||||
static int
|
||||
exec_svr4_imgact(imgp)
|
||||
struct image_params *imgp;
|
||||
{
|
||||
const struct exec *a_out = (const struct exec *) imgp->image_header;
|
||||
struct vmspace *vmspace;
|
||||
vm_offset_t vmaddr;
|
||||
unsigned long virtual_offset, file_offset;
|
||||
unsigned long bss_size;
|
||||
ssize_t aresid;
|
||||
int error;
|
||||
|
||||
if (((a_out->a_magic >> 16) & 0xff) != 0x64)
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* Set file/virtual offset based on a.out variant.
|
||||
*/
|
||||
switch ((int)(a_out->a_magic & 0xffff)) {
|
||||
case 0413:
|
||||
virtual_offset = 0;
|
||||
file_offset = 1024;
|
||||
break;
|
||||
case 0314:
|
||||
virtual_offset = 4096;
|
||||
file_offset = 0;
|
||||
break;
|
||||
default:
|
||||
return (-1);
|
||||
}
|
||||
bss_size = round_page(a_out->a_bss);
|
||||
#ifdef DEBUG
|
||||
printf("imgact: text: %08lx, data: %08lx, bss: %08lx\n", (u_long)a_out->a_text, (u_long)a_out->a_data, bss_size);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Check various fields in header for validity/bounds.
|
||||
*/
|
||||
if (a_out->a_entry < virtual_offset ||
|
||||
a_out->a_entry >= virtual_offset + a_out->a_text ||
|
||||
a_out->a_text & PAGE_MASK || a_out->a_data & PAGE_MASK)
|
||||
return (-1);
|
||||
|
||||
/* text + data can't exceed file size */
|
||||
if (a_out->a_data + a_out->a_text > imgp->attr->va_size)
|
||||
return (EFAULT);
|
||||
/*
|
||||
* text/data/bss must not exceed limits
|
||||
*/
|
||||
PROC_LOCK(imgp->proc);
|
||||
if (a_out->a_text > maxtsiz ||
|
||||
a_out->a_data + bss_size > lim_cur_proc(imgp->proc, RLIMIT_DATA) ||
|
||||
racct_set(imgp->proc, RACCT_DATA, a_out->a_data + bss_size) != 0) {
|
||||
PROC_UNLOCK(imgp->proc);
|
||||
return (ENOMEM);
|
||||
}
|
||||
PROC_UNLOCK(imgp->proc);
|
||||
|
||||
VOP_UNLOCK(imgp->vp, 0);
|
||||
|
||||
/*
|
||||
* Destroy old process VM and create a new one (with a new stack)
|
||||
*/
|
||||
error = exec_new_vmspace(imgp, &svr4_sysvec);
|
||||
if (error)
|
||||
goto fail;
|
||||
vmspace = imgp->proc->p_vmspace;
|
||||
|
||||
/*
|
||||
* Check if file_offset page aligned,.
|
||||
* Currently we cannot handle misalinged file offsets,
|
||||
* and so we read in the entire image (what a waste).
|
||||
*/
|
||||
if (file_offset & PAGE_MASK) {
|
||||
#ifdef DEBUG
|
||||
printf("imgact: Non page aligned binary %lu\n", file_offset);
|
||||
#endif
|
||||
/*
|
||||
* Map text+data+bss read/write/execute
|
||||
*/
|
||||
vmaddr = virtual_offset;
|
||||
error = vm_map_find(&vmspace->vm_map, NULL, 0, &vmaddr,
|
||||
a_out->a_text + a_out->a_data + bss_size, 0, VMFS_NO_SPACE,
|
||||
VM_PROT_ALL, VM_PROT_ALL, 0);
|
||||
if (error)
|
||||
goto fail;
|
||||
|
||||
error = vn_rdwr(UIO_READ, imgp->vp, (void *)vmaddr, file_offset,
|
||||
a_out->a_text + a_out->a_data, UIO_USERSPACE, 0,
|
||||
curthread->td_ucred, NOCRED, &aresid, curthread);
|
||||
if (error != 0)
|
||||
goto fail;
|
||||
if (aresid != 0) {
|
||||
error = ENOEXEC;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*
|
||||
* remove write enable on the 'text' part
|
||||
*/
|
||||
error = vm_map_protect(&vmspace->vm_map,
|
||||
vmaddr,
|
||||
vmaddr + a_out->a_text,
|
||||
VM_PROT_EXECUTE|VM_PROT_READ,
|
||||
TRUE);
|
||||
if (error)
|
||||
goto fail;
|
||||
}
|
||||
else {
|
||||
#ifdef DEBUG
|
||||
printf("imgact: Page aligned binary %lu\n", file_offset);
|
||||
#endif
|
||||
/*
|
||||
* Map text+data read/execute
|
||||
*/
|
||||
vmaddr = virtual_offset;
|
||||
error = vm_mmap(&vmspace->vm_map, &vmaddr,
|
||||
a_out->a_text + a_out->a_data,
|
||||
VM_PROT_READ | VM_PROT_EXECUTE,
|
||||
VM_PROT_ALL,
|
||||
MAP_PRIVATE | MAP_FIXED,
|
||||
OBJT_VNODE, imgp->vp, file_offset);
|
||||
if (error)
|
||||
goto fail;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("imgact: startaddr=%08lx, length=%08lx\n", (u_long)vmaddr,
|
||||
(u_long)a_out->a_text + a_out->a_data);
|
||||
#endif
|
||||
/*
|
||||
* allow read/write of data
|
||||
*/
|
||||
error = vm_map_protect(&vmspace->vm_map,
|
||||
vmaddr + a_out->a_text,
|
||||
vmaddr + a_out->a_text + a_out->a_data,
|
||||
VM_PROT_ALL,
|
||||
FALSE);
|
||||
if (error)
|
||||
goto fail;
|
||||
|
||||
/*
|
||||
* Allocate anon demand-zeroed area for uninitialized data
|
||||
*/
|
||||
if (bss_size != 0) {
|
||||
vmaddr = virtual_offset + a_out->a_text + a_out->a_data;
|
||||
error = vm_map_find(&vmspace->vm_map, NULL, 0, &vmaddr,
|
||||
bss_size, 0, VMFS_NO_SPACE, VM_PROT_ALL, VM_PROT_ALL, 0);
|
||||
if (error)
|
||||
goto fail;
|
||||
#ifdef DEBUG
|
||||
printf("imgact: bssaddr=%08lx, length=%08lx\n",
|
||||
(u_long)vmaddr, bss_size);
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
/* Fill in process VM information */
|
||||
vmspace->vm_tsize = round_page(a_out->a_text) >> PAGE_SHIFT;
|
||||
vmspace->vm_dsize = round_page(a_out->a_data + bss_size) >> PAGE_SHIFT;
|
||||
vmspace->vm_taddr = (caddr_t)virtual_offset;
|
||||
vmspace->vm_daddr = (caddr_t)virtual_offset + a_out->a_text;
|
||||
|
||||
/* Fill in image_params */
|
||||
imgp->interpreted = 0;
|
||||
imgp->entry_addr = a_out->a_entry;
|
||||
|
||||
imgp->proc->p_sysent = &svr4_sysvec;
|
||||
fail:
|
||||
vn_lock(imgp->vp, LK_EXCLUSIVE | LK_RETRY);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Tell kern_execve.c about it, with a little help from the linker.
|
||||
*/
|
||||
struct execsw svr4_execsw = { exec_svr4_imgact, "svr4 ELF" };
|
||||
EXEC_SET(execsw_set, svr4_execsw);
|
||||
|
@ -1,46 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1998 Mark Newton
|
||||
* Copyright (c) 1996 Christos Zoulas.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Christos Zoulas.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* 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 _SVR4_ACL_H_
|
||||
#define _SVR4_ACL_H_
|
||||
|
||||
typedef struct svr4_aclent {
|
||||
int a_type;
|
||||
svr4_uid_t a_id;
|
||||
svr4_o_mode_t a_perm;
|
||||
} svr4_aclent_t;
|
||||
|
||||
#define SVR4_SYS_GETACL 1
|
||||
#define SVR4_SYS_SETACL 2
|
||||
#define SVR4_SYS_GETACLCNT 3
|
||||
|
||||
#endif /* !_SVR4_ACL_H_ */
|
@ -1,53 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1998 Mark Newton
|
||||
* Copyright (c) 1994 Christos Zoulas
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission
|
||||
*
|
||||
* 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 _SVR4_DIRENT_H_
|
||||
#define _SVR4_DIRENT_H_
|
||||
|
||||
#define SVR4_MAXNAMLEN 512
|
||||
|
||||
struct svr4_dirent {
|
||||
svr4_ino_t d_ino;
|
||||
svr4_off_t d_off;
|
||||
u_short d_reclen;
|
||||
char d_name[SVR4_MAXNAMLEN + 1];
|
||||
};
|
||||
|
||||
struct svr4_dirent64 {
|
||||
svr4_ino64_t d_ino;
|
||||
svr4_off64_t d_off;
|
||||
u_short d_reclen;
|
||||
char d_name[SVR4_MAXNAMLEN + 1];
|
||||
};
|
||||
|
||||
#define SVR4_NAMEOFF(dp) ((char *)&(dp)->d_name - (char *)dp)
|
||||
#define SVR4_RECLEN(de,namlen) ALIGN((SVR4_NAMEOFF(de) + (namlen) + 1))
|
||||
|
||||
#endif /* !_SVR4_DIRENT_H_ */
|
@ -1,172 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1998 Mark Newton
|
||||
* Copyright (c) 1994 Christos Zoulas
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission
|
||||
*
|
||||
* 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 _SVR4_ERRNO_H_
|
||||
#define _SVR4_ERRNO_H_
|
||||
|
||||
#define SVR4_EPERM 1
|
||||
#define SVR4_ENOENT 2
|
||||
#define SVR4_ESRCH 3
|
||||
#define SVR4_EINTR 4
|
||||
#define SVR4_EIO 5
|
||||
#define SVR4_ENXIO 6
|
||||
#define SVR4_E2BIG 7
|
||||
#define SVR4_ENOEXEC 8
|
||||
#define SVR4_EBADF 9
|
||||
#define SVR4_ECHILD 10
|
||||
#define SVR4_EAGAIN 11
|
||||
#define SVR4_ENOMEM 12
|
||||
#define SVR4_EACCES 13
|
||||
#define SVR4_EFAULT 14
|
||||
#define SVR4_ENOTBLK 15
|
||||
#define SVR4_EBUSY 16
|
||||
#define SVR4_EEXIST 17
|
||||
#define SVR4_EXDEV 18
|
||||
#define SVR4_ENODEV 19
|
||||
#define SVR4_ENOTDIR 20
|
||||
#define SVR4_EISDIR 21
|
||||
#define SVR4_EINVAL 22
|
||||
#define SVR4_ENFILE 23
|
||||
#define SVR4_EMFILE 24
|
||||
#define SVR4_ENOTTY 25
|
||||
#define SVR4_ETXTBSY 26
|
||||
#define SVR4_EFBIG 27
|
||||
#define SVR4_ENOSPC 28
|
||||
#define SVR4_ESPIPE 29
|
||||
#define SVR4_EROFS 30
|
||||
#define SVR4_EMLINK 31
|
||||
#define SVR4_EPIPE 32
|
||||
#define SVR4_EDOM 33
|
||||
#define SVR4_ERANGE 34
|
||||
#define SVR4_ENOMSG 35
|
||||
#define SVR4_EIDRM 36
|
||||
#define SVR4_ECHRNG 37
|
||||
#define SVR4_EL2NSYNC 38
|
||||
#define SVR4_EL3HLT 39
|
||||
#define SVR4_EL3RST 40
|
||||
#define SVR4_ELNRNG 41
|
||||
#define SVR4_EUNATCH 42
|
||||
#define SVR4_ENOCSI 43
|
||||
#define SVR4_EL2HLT 44
|
||||
#define SVR4_EDEADLK 45
|
||||
#define SVR4_ENOLCK 46
|
||||
#define SVR4_EBADE 50
|
||||
#define SVR4_EBADR 51
|
||||
#define SVR4_EXFULL 52
|
||||
#define SVR4_ENOANO 53
|
||||
#define SVR4_EBADRQC 54
|
||||
#define SVR4_EBADSLT 55
|
||||
#define SVR4_EDEADLOCK 56
|
||||
#define SVR4_EBFONT 57
|
||||
#define SVR4_ENOSTR 60
|
||||
#define SVR4_ENODATA 61
|
||||
#define SVR4_ETIME 62
|
||||
#define SVR4_ENOSR 63
|
||||
#define SVR4_ENONET 64
|
||||
#define SVR4_ENOPKG 65
|
||||
#define SVR4_EREMOTE 66
|
||||
#define SVR4_ENOLINK 67
|
||||
#define SVR4_EADV 68
|
||||
#define SVR4_ESRMNT 69
|
||||
#define SVR4_ECOMM 70
|
||||
#define SVR4_EPROTO 71
|
||||
#define SVR4_EMULTIHOP 74
|
||||
#define SVR4_EBADMSG 77
|
||||
#define SVR4_ENAMETOOLONG 78
|
||||
#define SVR4_EOVERFLOW 79
|
||||
#define SVR4_ENOTUNIQ 80
|
||||
#define SVR4_EBADFD 81
|
||||
#define SVR4_EREMCHG 82
|
||||
#define SVR4_ELIBACC 83
|
||||
#define SVR4_ELIBBAD 84
|
||||
#define SVR4_ELIBSCN 85
|
||||
#define SVR4_ELIBMAX 86
|
||||
#define SVR4_ELIBEXEC 87
|
||||
#define SVR4_EILSEQ 88
|
||||
#define SVR4_ENOSYS 89
|
||||
#define SVR4_ELOOP 90
|
||||
#define SVR4_ERESTART 91
|
||||
#define SVR4_ESTRPIPE 92
|
||||
#define SVR4_ENOTEMPTY 93
|
||||
#define SVR4_EUSERS 94
|
||||
#define SVR4_ENOTSOCK 95
|
||||
#define SVR4_EDESTADDRREQ 96
|
||||
#define SVR4_EMSGSIZE 97
|
||||
#define SVR4_EPROTOTYPE 98
|
||||
#define SVR4_ENOPROTOOPT 99
|
||||
#define SVR4_EPROTONOSUPPORT 120
|
||||
#define SVR4_ESOCKTNOSUPPORT 121
|
||||
#define SVR4_EOPNOTSUPP 122
|
||||
#define SVR4_EPFNOSUPPORT 123
|
||||
#define SVR4_EAFNOSUPPORT 124
|
||||
#define SVR4_EADDRINUSE 125
|
||||
#define SVR4_EADDRNOTAVAIL 126
|
||||
#define SVR4_ENETDOWN 127
|
||||
#define SVR4_ENETUNREACH 128
|
||||
#define SVR4_ENETRESET 129
|
||||
#define SVR4_ECONNABORTED 130
|
||||
#define SVR4_ECONNRESET 131
|
||||
#define SVR4_ENOBUFS 132
|
||||
#define SVR4_EISCONN 133
|
||||
#define SVR4_ENOTCONN 134
|
||||
#define SVR4_EUCLEAN 135
|
||||
#define SVR4_ENOTNAM 137
|
||||
#define SVR4_ENAVAIL 138
|
||||
#define SVR4_EISNAM 139
|
||||
#define SVR4_EREMOTEIO 140
|
||||
#define SVR4_EINIT 141
|
||||
#define SVR4_EREMDEV 142
|
||||
#define SVR4_ESHUTDOWN 143
|
||||
#define SVR4_ETOOMANYREFS 144
|
||||
#define SVR4_ETIMEDOUT 145
|
||||
#define SVR4_ECONNREFUSED 146
|
||||
#define SVR4_EHOSTDOWN 147
|
||||
#define SVR4_EHOSTUNREACH 148
|
||||
#define SVR4_EWOULDBLOCK SVR4_EAGAIN
|
||||
#define SVR4_EALREADY 149
|
||||
#define SVR4_EINPROGRESS 150
|
||||
#define SVR4_ESTALE 151
|
||||
#define SVR4_EIORESID 500
|
||||
|
||||
/*
|
||||
* These ones are not translated...
|
||||
*/
|
||||
#define SVR4_EPROCLIM SVR4_ENOSYS
|
||||
#define SVR4_EDQUOT SVR4_ENOSYS
|
||||
#define SVR4_EBADRPC SVR4_ENOSYS
|
||||
#define SVR4_ERPCMISMATCH SVR4_ENOSYS
|
||||
#define SVR4_EPROGUNAVAIL SVR4_ENOSYS
|
||||
#define SVR4_EPROGMISMATCH SVR4_ENOSYS
|
||||
#define SVR4_EPROCUNAVAIL SVR4_ENOSYS
|
||||
#define SVR4_EFTYPE SVR4_ENOSYS
|
||||
#define SVR4_EAUTH SVR4_ENOSYS
|
||||
#define SVR4_ENEEDAUTH SVR4_ENOSYS
|
||||
|
||||
#endif /* !_SVR4_ERRNO_H_ */
|
@ -1,70 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1998 Mark Newton
|
||||
* Copyright (c) 1994 Christos Zoulas
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission
|
||||
*
|
||||
* 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 _SVR4_EXEC_H_
|
||||
#define _SVR4_EXEC_H_
|
||||
|
||||
#ifdef SVR4_COMPAT_SOLARIS2
|
||||
# define SVR4_AUX_ARGSIZ (sizeof(AuxInfo) * 12 / sizeof(char *))
|
||||
#else
|
||||
# define SVR4_AUX_ARGSIZ (sizeof(AuxInfo) * 8 / sizeof(char *))
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/* Don't think we need all this NetBSD stuff */
|
||||
/*
|
||||
* The following is horrible; there must be a better way. I need to
|
||||
* play with brk(2) a bit more.
|
||||
*/
|
||||
#ifdef __i386__
|
||||
/*
|
||||
* I cannot load the interpreter after the data segment because brk(2)
|
||||
* breaks. I have to load it somewhere before. Programs start at
|
||||
* 0x08000000 so I load the interpreter far before.
|
||||
*/
|
||||
#define SVR4_INTERP_ADDR 0x01000000
|
||||
#endif
|
||||
|
||||
#ifdef sparc
|
||||
/*
|
||||
* Here programs load at 0x00010000, so I load the interpreter far after
|
||||
* the end of the data segment.
|
||||
*/
|
||||
#define SVR4_INTERP_ADDR 0x10000000
|
||||
#endif
|
||||
|
||||
#ifndef SVR4_INTERP_ADDR
|
||||
# define SVR4_INTERP_ADDR 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*void svr4_setregs(struct thread *, struct exec_package *, u_long);*/
|
||||
|
||||
#endif /* !_SVR4_EXEC_H_ */
|
@ -1,732 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1998 Mark Newton
|
||||
* Copyright (c) 1994, 1997 Christos Zoulas.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Christos Zoulas.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* 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/capsicum.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/filedesc.h>
|
||||
/*#include <sys/ioctl.h>*/
|
||||
#include <sys/lock.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/namei.h>
|
||||
#include <sys/priv.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/syscallsubr.h>
|
||||
#include <sys/unistd.h>
|
||||
#include <sys/vnode.h>
|
||||
|
||||
#include <sys/sysproto.h>
|
||||
|
||||
#include <compat/svr4/svr4.h>
|
||||
#include <compat/svr4/svr4_types.h>
|
||||
#include <compat/svr4/svr4_signal.h>
|
||||
#include <compat/svr4/svr4_proto.h>
|
||||
#include <compat/svr4/svr4_util.h>
|
||||
#include <compat/svr4/svr4_fcntl.h>
|
||||
|
||||
#include <security/mac/mac_framework.h>
|
||||
|
||||
static int svr4_to_bsd_flags(int);
|
||||
static u_long svr4_to_bsd_cmd(u_long);
|
||||
static int fd_revoke(struct thread *, int);
|
||||
static int fd_truncate(struct thread *, int, struct flock *);
|
||||
static int bsd_to_svr4_flags(int);
|
||||
static void bsd_to_svr4_flock(struct flock *, struct svr4_flock *);
|
||||
static void svr4_to_bsd_flock(struct svr4_flock *, struct flock *);
|
||||
static void bsd_to_svr4_flock64(struct flock *, struct svr4_flock64 *);
|
||||
static void svr4_to_bsd_flock64(struct svr4_flock64 *, struct flock *);
|
||||
|
||||
static u_long
|
||||
svr4_to_bsd_cmd(cmd)
|
||||
u_long cmd;
|
||||
{
|
||||
switch (cmd) {
|
||||
case SVR4_F_DUPFD:
|
||||
return F_DUPFD;
|
||||
case SVR4_F_DUP2FD:
|
||||
return F_DUP2FD;
|
||||
case SVR4_F_GETFD:
|
||||
return F_GETFD;
|
||||
case SVR4_F_SETFD:
|
||||
return F_SETFD;
|
||||
case SVR4_F_GETFL:
|
||||
return F_GETFL;
|
||||
case SVR4_F_SETFL:
|
||||
return F_SETFL;
|
||||
case SVR4_F_GETLK:
|
||||
return F_GETLK;
|
||||
case SVR4_F_SETLK:
|
||||
return F_SETLK;
|
||||
case SVR4_F_SETLKW:
|
||||
return F_SETLKW;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
svr4_to_bsd_flags(l)
|
||||
int l;
|
||||
{
|
||||
int r = 0;
|
||||
r |= (l & SVR4_O_RDONLY) ? O_RDONLY : 0;
|
||||
r |= (l & SVR4_O_WRONLY) ? O_WRONLY : 0;
|
||||
r |= (l & SVR4_O_RDWR) ? O_RDWR : 0;
|
||||
r |= (l & SVR4_O_NDELAY) ? O_NONBLOCK : 0;
|
||||
r |= (l & SVR4_O_APPEND) ? O_APPEND : 0;
|
||||
r |= (l & SVR4_O_SYNC) ? O_FSYNC : 0;
|
||||
r |= (l & SVR4_O_NONBLOCK) ? O_NONBLOCK : 0;
|
||||
r |= (l & SVR4_O_PRIV) ? O_EXLOCK : 0;
|
||||
r |= (l & SVR4_O_CREAT) ? O_CREAT : 0;
|
||||
r |= (l & SVR4_O_TRUNC) ? O_TRUNC : 0;
|
||||
r |= (l & SVR4_O_EXCL) ? O_EXCL : 0;
|
||||
r |= (l & SVR4_O_NOCTTY) ? O_NOCTTY : 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
static int
|
||||
bsd_to_svr4_flags(l)
|
||||
int l;
|
||||
{
|
||||
int r = 0;
|
||||
r |= (l & O_RDONLY) ? SVR4_O_RDONLY : 0;
|
||||
r |= (l & O_WRONLY) ? SVR4_O_WRONLY : 0;
|
||||
r |= (l & O_RDWR) ? SVR4_O_RDWR : 0;
|
||||
r |= (l & O_NDELAY) ? SVR4_O_NONBLOCK : 0;
|
||||
r |= (l & O_APPEND) ? SVR4_O_APPEND : 0;
|
||||
r |= (l & O_FSYNC) ? SVR4_O_SYNC : 0;
|
||||
r |= (l & O_NONBLOCK) ? SVR4_O_NONBLOCK : 0;
|
||||
r |= (l & O_EXLOCK) ? SVR4_O_PRIV : 0;
|
||||
r |= (l & O_CREAT) ? SVR4_O_CREAT : 0;
|
||||
r |= (l & O_TRUNC) ? SVR4_O_TRUNC : 0;
|
||||
r |= (l & O_EXCL) ? SVR4_O_EXCL : 0;
|
||||
r |= (l & O_NOCTTY) ? SVR4_O_NOCTTY : 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
bsd_to_svr4_flock(iflp, oflp)
|
||||
struct flock *iflp;
|
||||
struct svr4_flock *oflp;
|
||||
{
|
||||
switch (iflp->l_type) {
|
||||
case F_RDLCK:
|
||||
oflp->l_type = SVR4_F_RDLCK;
|
||||
break;
|
||||
case F_WRLCK:
|
||||
oflp->l_type = SVR4_F_WRLCK;
|
||||
break;
|
||||
case F_UNLCK:
|
||||
oflp->l_type = SVR4_F_UNLCK;
|
||||
break;
|
||||
default:
|
||||
oflp->l_type = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
oflp->l_whence = (short) iflp->l_whence;
|
||||
oflp->l_start = (svr4_off_t) iflp->l_start;
|
||||
oflp->l_len = (svr4_off_t) iflp->l_len;
|
||||
oflp->l_sysid = 0;
|
||||
oflp->l_pid = (svr4_pid_t) iflp->l_pid;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
svr4_to_bsd_flock(iflp, oflp)
|
||||
struct svr4_flock *iflp;
|
||||
struct flock *oflp;
|
||||
{
|
||||
switch (iflp->l_type) {
|
||||
case SVR4_F_RDLCK:
|
||||
oflp->l_type = F_RDLCK;
|
||||
break;
|
||||
case SVR4_F_WRLCK:
|
||||
oflp->l_type = F_WRLCK;
|
||||
break;
|
||||
case SVR4_F_UNLCK:
|
||||
oflp->l_type = F_UNLCK;
|
||||
break;
|
||||
default:
|
||||
oflp->l_type = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
oflp->l_whence = iflp->l_whence;
|
||||
oflp->l_start = (off_t) iflp->l_start;
|
||||
oflp->l_len = (off_t) iflp->l_len;
|
||||
oflp->l_pid = (pid_t) iflp->l_pid;
|
||||
oflp->l_sysid = iflp->l_sysid;
|
||||
}
|
||||
|
||||
static void
|
||||
bsd_to_svr4_flock64(iflp, oflp)
|
||||
struct flock *iflp;
|
||||
struct svr4_flock64 *oflp;
|
||||
{
|
||||
switch (iflp->l_type) {
|
||||
case F_RDLCK:
|
||||
oflp->l_type = SVR4_F_RDLCK;
|
||||
break;
|
||||
case F_WRLCK:
|
||||
oflp->l_type = SVR4_F_WRLCK;
|
||||
break;
|
||||
case F_UNLCK:
|
||||
oflp->l_type = SVR4_F_UNLCK;
|
||||
break;
|
||||
default:
|
||||
oflp->l_type = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
oflp->l_whence = (short) iflp->l_whence;
|
||||
oflp->l_start = (svr4_off64_t) iflp->l_start;
|
||||
oflp->l_len = (svr4_off64_t) iflp->l_len;
|
||||
oflp->l_sysid = iflp->l_sysid;
|
||||
oflp->l_pid = (svr4_pid_t) iflp->l_pid;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
svr4_to_bsd_flock64(iflp, oflp)
|
||||
struct svr4_flock64 *iflp;
|
||||
struct flock *oflp;
|
||||
{
|
||||
switch (iflp->l_type) {
|
||||
case SVR4_F_RDLCK:
|
||||
oflp->l_type = F_RDLCK;
|
||||
break;
|
||||
case SVR4_F_WRLCK:
|
||||
oflp->l_type = F_WRLCK;
|
||||
break;
|
||||
case SVR4_F_UNLCK:
|
||||
oflp->l_type = F_UNLCK;
|
||||
break;
|
||||
default:
|
||||
oflp->l_type = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
oflp->l_whence = iflp->l_whence;
|
||||
oflp->l_start = (off_t) iflp->l_start;
|
||||
oflp->l_len = (off_t) iflp->l_len;
|
||||
oflp->l_pid = (pid_t) iflp->l_pid;
|
||||
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
fd_revoke(td, fd)
|
||||
struct thread *td;
|
||||
int fd;
|
||||
{
|
||||
struct vnode *vp;
|
||||
struct mount *mp;
|
||||
struct vattr vattr;
|
||||
cap_rights_t rights;
|
||||
int error, *retval;
|
||||
|
||||
retval = td->td_retval;
|
||||
/*
|
||||
* If we ever want to support Capsicum on SVR4 processes (unlikely)
|
||||
* or FreeBSD grows a native frevoke() (more likely), we will need a
|
||||
* CAP_FREVOKE here.
|
||||
*
|
||||
* In the meantime, use CAP_ALL(): if a SVR4 process wants to
|
||||
* do an frevoke(), it needs to do it on either a regular file
|
||||
* descriptor or a fully-privileged capability (which is effectively
|
||||
* the same as a non-capability-restricted file descriptor).
|
||||
*/
|
||||
CAP_ALL(&rights);
|
||||
if ((error = fgetvp(td, fd, &rights, &vp)) != 0)
|
||||
return (error);
|
||||
|
||||
if (vp->v_type != VCHR && vp->v_type != VBLK) {
|
||||
error = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
#ifdef MAC
|
||||
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
|
||||
error = mac_vnode_check_revoke(td->td_ucred, vp);
|
||||
VOP_UNLOCK(vp, 0);
|
||||
if (error)
|
||||
goto out;
|
||||
#endif
|
||||
|
||||
if ((error = VOP_GETATTR(vp, &vattr, td->td_ucred)) != 0)
|
||||
goto out;
|
||||
|
||||
if (td->td_ucred->cr_uid != vattr.va_uid &&
|
||||
(error = priv_check(td, PRIV_VFS_ADMIN)) != 0)
|
||||
goto out;
|
||||
|
||||
if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
|
||||
goto out;
|
||||
if (vcount(vp) > 1)
|
||||
VOP_REVOKE(vp, REVOKEALL);
|
||||
vn_finished_write(mp);
|
||||
out:
|
||||
vrele(vp);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
fd_truncate(td, fd, flp)
|
||||
struct thread *td;
|
||||
int fd;
|
||||
struct flock *flp;
|
||||
{
|
||||
off_t start, length;
|
||||
struct file *fp;
|
||||
struct vnode *vp;
|
||||
struct vattr vattr;
|
||||
int error, *retval;
|
||||
struct ftruncate_args ft;
|
||||
cap_rights_t rights;
|
||||
|
||||
retval = td->td_retval;
|
||||
|
||||
/*
|
||||
* We only support truncating the file.
|
||||
*/
|
||||
error = fget(td, fd, cap_rights_init(&rights, CAP_FTRUNCATE), &fp);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
vp = fp->f_vnode;
|
||||
|
||||
if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
|
||||
fdrop(fp, td);
|
||||
return ESPIPE;
|
||||
}
|
||||
|
||||
if ((error = VOP_GETATTR(vp, &vattr, td->td_ucred)) != 0) {
|
||||
fdrop(fp, td);
|
||||
return error;
|
||||
}
|
||||
|
||||
length = vattr.va_size;
|
||||
|
||||
switch (flp->l_whence) {
|
||||
case SEEK_CUR:
|
||||
start = fp->f_offset + flp->l_start;
|
||||
break;
|
||||
|
||||
case SEEK_END:
|
||||
start = flp->l_start + length;
|
||||
break;
|
||||
|
||||
case SEEK_SET:
|
||||
start = flp->l_start;
|
||||
break;
|
||||
|
||||
default:
|
||||
fdrop(fp, td);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if (start + flp->l_len < length) {
|
||||
/* We don't support free'ing in the middle of the file */
|
||||
fdrop(fp, td);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
ft.fd = fd;
|
||||
ft.length = start;
|
||||
|
||||
error = sys_ftruncate(td, &ft);
|
||||
|
||||
fdrop(fp, td);
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
svr4_sys_open(td, uap)
|
||||
struct thread *td;
|
||||
struct svr4_sys_open_args *uap;
|
||||
{
|
||||
struct proc *p = td->td_proc;
|
||||
char *newpath;
|
||||
int bsd_flags, error, retval;
|
||||
|
||||
CHECKALTEXIST(td, uap->path, &newpath);
|
||||
|
||||
bsd_flags = svr4_to_bsd_flags(uap->flags);
|
||||
error = kern_openat(td, AT_FDCWD, newpath, UIO_SYSSPACE, bsd_flags,
|
||||
uap->mode);
|
||||
free(newpath, M_TEMP);
|
||||
|
||||
if (error) {
|
||||
/* uprintf("svr4_open(%s, 0x%0x, 0%o): %d\n", uap->path,
|
||||
uap->flags, uap->mode, error);*/
|
||||
return error;
|
||||
}
|
||||
|
||||
retval = td->td_retval[0];
|
||||
|
||||
PROC_LOCK(p);
|
||||
if (!(bsd_flags & O_NOCTTY) && SESS_LEADER(p) &&
|
||||
!(p->p_flag & P_CONTROLT)) {
|
||||
#if defined(NOTYET)
|
||||
cap_rights_t rights;
|
||||
struct file *fp;
|
||||
|
||||
error = fget(td, retval,
|
||||
cap_rights_init(&rights, CAP_IOCTL), &fp);
|
||||
PROC_UNLOCK(p);
|
||||
/*
|
||||
* we may have lost a race the above open() and
|
||||
* another thread issuing a close()
|
||||
*/
|
||||
if (error)
|
||||
return (EBADF); /* XXX: correct errno? */
|
||||
/* ignore any error, just give it a try */
|
||||
if (fp->f_type == DTYPE_VNODE)
|
||||
fo_ioctl(fp, TIOCSCTTY, (caddr_t) 0, td->td_ucred,
|
||||
td);
|
||||
fdrop(fp, td);
|
||||
} else {
|
||||
PROC_UNLOCK(p);
|
||||
}
|
||||
#else
|
||||
}
|
||||
PROC_UNLOCK(p);
|
||||
#endif
|
||||
return error;
|
||||
}
|
||||
|
||||
int
|
||||
svr4_sys_open64(td, uap)
|
||||
struct thread *td;
|
||||
struct svr4_sys_open64_args *uap;
|
||||
{
|
||||
return svr4_sys_open(td, (struct svr4_sys_open_args *)uap);
|
||||
}
|
||||
|
||||
int
|
||||
svr4_sys_creat(td, uap)
|
||||
struct thread *td;
|
||||
struct svr4_sys_creat_args *uap;
|
||||
{
|
||||
char *newpath;
|
||||
int error;
|
||||
|
||||
CHECKALTEXIST(td, uap->path, &newpath);
|
||||
|
||||
error = kern_openat(td, AT_FDCWD, newpath, UIO_SYSSPACE,
|
||||
O_WRONLY | O_CREAT | O_TRUNC, uap->mode);
|
||||
free(newpath, M_TEMP);
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
svr4_sys_creat64(td, uap)
|
||||
struct thread *td;
|
||||
struct svr4_sys_creat64_args *uap;
|
||||
{
|
||||
return svr4_sys_creat(td, (struct svr4_sys_creat_args *)uap);
|
||||
}
|
||||
|
||||
int
|
||||
svr4_sys_llseek(td, uap)
|
||||
struct thread *td;
|
||||
struct svr4_sys_llseek_args *uap;
|
||||
{
|
||||
struct lseek_args ap;
|
||||
|
||||
ap.fd = uap->fd;
|
||||
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
ap.offset = (((u_int64_t) uap->offset1) << 32) |
|
||||
uap->offset2;
|
||||
#else
|
||||
ap.offset = (((u_int64_t) uap->offset2) << 32) |
|
||||
uap->offset1;
|
||||
#endif
|
||||
ap.whence = uap->whence;
|
||||
|
||||
return sys_lseek(td, &ap);
|
||||
}
|
||||
|
||||
int
|
||||
svr4_sys_access(td, uap)
|
||||
struct thread *td;
|
||||
struct svr4_sys_access_args *uap;
|
||||
{
|
||||
char *newpath;
|
||||
int error;
|
||||
|
||||
CHECKALTEXIST(td, uap->path, &newpath);
|
||||
error = kern_accessat(td, AT_FDCWD, newpath, UIO_SYSSPACE,
|
||||
0, uap->amode);
|
||||
free(newpath, M_TEMP);
|
||||
return (error);
|
||||
}
|
||||
|
||||
#if defined(NOTYET)
|
||||
int
|
||||
svr4_sys_pread(td, uap)
|
||||
struct thread *td;
|
||||
struct svr4_sys_pread_args *uap;
|
||||
{
|
||||
struct pread_args pra;
|
||||
|
||||
/*
|
||||
* Just translate the args structure and call the NetBSD
|
||||
* pread(2) system call (offset type is 64-bit in NetBSD).
|
||||
*/
|
||||
pra.fd = uap->fd;
|
||||
pra.buf = uap->buf;
|
||||
pra.nbyte = uap->nbyte;
|
||||
pra.offset = uap->off;
|
||||
|
||||
return pread(td, &pra);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(NOTYET)
|
||||
int
|
||||
svr4_sys_pread64(td, v, retval)
|
||||
struct thread *td;
|
||||
void *v;
|
||||
register_t *retval;
|
||||
{
|
||||
|
||||
struct svr4_sys_pread64_args *uap = v;
|
||||
struct sys_pread_args pra;
|
||||
|
||||
/*
|
||||
* Just translate the args structure and call the NetBSD
|
||||
* pread(2) system call (offset type is 64-bit in NetBSD).
|
||||
*/
|
||||
pra.fd = uap->fd;
|
||||
pra.buf = uap->buf;
|
||||
pra.nbyte = uap->nbyte;
|
||||
pra.offset = uap->off;
|
||||
|
||||
return (sys_pread(td, &pra, retval));
|
||||
}
|
||||
#endif /* NOTYET */
|
||||
|
||||
#if defined(NOTYET)
|
||||
int
|
||||
svr4_sys_pwrite(td, uap)
|
||||
struct thread *td;
|
||||
struct svr4_sys_pwrite_args *uap;
|
||||
{
|
||||
struct pwrite_args pwa;
|
||||
|
||||
/*
|
||||
* Just translate the args structure and call the NetBSD
|
||||
* pwrite(2) system call (offset type is 64-bit in NetBSD).
|
||||
*/
|
||||
pwa.fd = uap->fd;
|
||||
pwa.buf = uap->buf;
|
||||
pwa.nbyte = uap->nbyte;
|
||||
pwa.offset = uap->off;
|
||||
|
||||
return pwrite(td, &pwa);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(NOTYET)
|
||||
int
|
||||
svr4_sys_pwrite64(td, v, retval)
|
||||
struct thread *td;
|
||||
void *v;
|
||||
register_t *retval;
|
||||
{
|
||||
struct svr4_sys_pwrite64_args *uap = v;
|
||||
struct sys_pwrite_args pwa;
|
||||
|
||||
/*
|
||||
* Just translate the args structure and call the NetBSD
|
||||
* pwrite(2) system call (offset type is 64-bit in NetBSD).
|
||||
*/
|
||||
pwa.fd = uap->fd;
|
||||
pwa.buf = uap->buf;
|
||||
pwa.nbyte = uap->nbyte;
|
||||
pwa.offset = uap->off;
|
||||
|
||||
return (sys_pwrite(td, &pwa, retval));
|
||||
}
|
||||
#endif /* NOTYET */
|
||||
|
||||
int
|
||||
svr4_sys_fcntl(td, uap)
|
||||
struct thread *td;
|
||||
struct svr4_sys_fcntl_args *uap;
|
||||
{
|
||||
int cmd, error, *retval;
|
||||
|
||||
retval = td->td_retval;
|
||||
|
||||
cmd = svr4_to_bsd_cmd(uap->cmd);
|
||||
|
||||
switch (cmd) {
|
||||
case F_DUPFD:
|
||||
case F_DUP2FD:
|
||||
case F_GETFD:
|
||||
case F_SETFD:
|
||||
return (kern_fcntl(td, uap->fd, cmd, (intptr_t)uap->arg));
|
||||
|
||||
case F_GETFL:
|
||||
error = kern_fcntl(td, uap->fd, cmd, (intptr_t)uap->arg);
|
||||
if (error)
|
||||
return (error);
|
||||
*retval = bsd_to_svr4_flags(*retval);
|
||||
return (error);
|
||||
|
||||
case F_SETFL:
|
||||
{
|
||||
/*
|
||||
* we must save the O_ASYNC flag, as that is
|
||||
* handled by ioctl(_, I_SETSIG, _) emulation.
|
||||
*/
|
||||
int flags;
|
||||
|
||||
DPRINTF(("Setting flags %p\n", uap->arg));
|
||||
|
||||
error = kern_fcntl(td, uap->fd, F_GETFL, 0);
|
||||
if (error)
|
||||
return (error);
|
||||
flags = *retval;
|
||||
flags &= O_ASYNC;
|
||||
flags |= svr4_to_bsd_flags((u_long) uap->arg);
|
||||
return (kern_fcntl(td, uap->fd, F_SETFL, flags));
|
||||
}
|
||||
|
||||
case F_GETLK:
|
||||
case F_SETLK:
|
||||
case F_SETLKW:
|
||||
{
|
||||
struct svr4_flock ifl;
|
||||
struct flock fl;
|
||||
|
||||
error = copyin(uap->arg, &ifl, sizeof (ifl));
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
svr4_to_bsd_flock(&ifl, &fl);
|
||||
|
||||
error = kern_fcntl(td, uap->fd, cmd, (intptr_t)&fl);
|
||||
if (error || cmd != F_GETLK)
|
||||
return (error);
|
||||
|
||||
bsd_to_svr4_flock(&fl, &ifl);
|
||||
|
||||
return (copyout(&ifl, uap->arg, sizeof (ifl)));
|
||||
}
|
||||
case -1:
|
||||
switch (uap->cmd) {
|
||||
case SVR4_F_FREESP:
|
||||
{
|
||||
struct svr4_flock ifl;
|
||||
struct flock fl;
|
||||
|
||||
error = copyin(uap->arg, &ifl,
|
||||
sizeof ifl);
|
||||
if (error)
|
||||
return error;
|
||||
svr4_to_bsd_flock(&ifl, &fl);
|
||||
return fd_truncate(td, uap->fd, &fl);
|
||||
}
|
||||
|
||||
case SVR4_F_GETLK64:
|
||||
case SVR4_F_SETLK64:
|
||||
case SVR4_F_SETLKW64:
|
||||
{
|
||||
struct svr4_flock64 ifl;
|
||||
struct flock fl;
|
||||
|
||||
switch (uap->cmd) {
|
||||
case SVR4_F_GETLK64:
|
||||
cmd = F_GETLK;
|
||||
break;
|
||||
case SVR4_F_SETLK64:
|
||||
cmd = F_SETLK;
|
||||
break;
|
||||
case SVR4_F_SETLKW64:
|
||||
cmd = F_SETLKW;
|
||||
break;
|
||||
}
|
||||
error = copyin(uap->arg, &ifl,
|
||||
sizeof (ifl));
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
svr4_to_bsd_flock64(&ifl, &fl);
|
||||
|
||||
error = kern_fcntl(td, uap->fd, cmd,
|
||||
(intptr_t)&fl);
|
||||
if (error || cmd != F_GETLK)
|
||||
return (error);
|
||||
|
||||
bsd_to_svr4_flock64(&fl, &ifl);
|
||||
|
||||
return (copyout(&ifl, uap->arg,
|
||||
sizeof (ifl)));
|
||||
}
|
||||
|
||||
case SVR4_F_FREESP64:
|
||||
{
|
||||
struct svr4_flock64 ifl;
|
||||
struct flock fl;
|
||||
|
||||
error = copyin(uap->arg, &ifl,
|
||||
sizeof ifl);
|
||||
if (error)
|
||||
return error;
|
||||
svr4_to_bsd_flock64(&ifl, &fl);
|
||||
return fd_truncate(td, uap->fd, &fl);
|
||||
}
|
||||
|
||||
case SVR4_F_REVOKE:
|
||||
return fd_revoke(td, uap->fd);
|
||||
|
||||
default:
|
||||
return ENOSYS;
|
||||
}
|
||||
|
||||
default:
|
||||
return ENOSYS;
|
||||
}
|
||||
}
|
@ -1,134 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1998 Mark Newton
|
||||
* Copyright (c) 1994 Christos Zoulas
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission
|
||||
*
|
||||
* 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 _SVR4_FCNTL_H_
|
||||
#define _SVR4_FCNTL_H_
|
||||
|
||||
#include <compat/svr4/svr4_types.h>
|
||||
#include <sys/fcntl.h>
|
||||
|
||||
#define SVR4_O_RDONLY 0x0000
|
||||
#define SVR4_O_WRONLY 0x0001
|
||||
#define SVR4_O_RDWR 0x0002
|
||||
#define SVR4_O_ACCMODE 0x0003
|
||||
#define SVR4_O_NDELAY 0x0004
|
||||
#define SVR4_O_APPEND 0x0008
|
||||
#define SVR4_O_SYNC 0x0010
|
||||
#define SVR4_O_NONBLOCK 0x0080
|
||||
#define SVR4_O_CREAT 0x0100
|
||||
#define SVR4_O_TRUNC 0x0200
|
||||
#define SVR4_O_EXCL 0x0400
|
||||
#define SVR4_O_NOCTTY 0x0800
|
||||
#define SVR4_O_PRIV 0x1000
|
||||
|
||||
|
||||
#define SVR4_FD_CLOEXEC 1
|
||||
|
||||
#define SVR4_F_DUPFD 0
|
||||
#define SVR4_F_GETFD 1
|
||||
#define SVR4_F_SETFD 2
|
||||
#define SVR4_F_GETFL 3
|
||||
#define SVR4_F_SETFL 4
|
||||
#define SVR4_F_GETLK_SVR3 5
|
||||
#define SVR4_F_SETLK 6
|
||||
#define SVR4_F_SETLKW 7
|
||||
#define SVR4_F_CHKFL 8
|
||||
#define SVR4_F_DUP2FD 9
|
||||
#define SVR4_F_ALLOCSP 10
|
||||
#define SVR4_F_FREESP 11
|
||||
|
||||
#define SVR4_F_ISSTREAM 13
|
||||
#define SVR4_F_GETLK 14
|
||||
#define SVR4_F_PRIV 15
|
||||
#define SVR4_F_NPRIV 16
|
||||
#define SVR4_F_QUOTACTL 17
|
||||
#define SVR4_F_BLOCKS 18
|
||||
#define SVR4_F_BLKSIZE 19
|
||||
#define SVR4_F_RSETLK 20
|
||||
#define SVR4_F_RGETLK 21
|
||||
#define SVR4_F_RSETLKW 22
|
||||
#define SVR4_F_GETOWN 23
|
||||
#define SVR4_F_SETOWN 24
|
||||
#define SVR4_F_REVOKE 25
|
||||
#define SVR4_F_HASREMOTELOCKS 26
|
||||
#define SVR4_F_FREESP64 27
|
||||
|
||||
#define SVR4_F_GETLK64 33
|
||||
#define SVR4_F_SETLK64 34
|
||||
#define SVR4_F_SETLKW64 35
|
||||
|
||||
#define SVR4_F_SHARE 40
|
||||
#define SVR4_F_UNSHARE 41
|
||||
|
||||
#define SVR4_F_CHSIZE_XENIX 0x6000
|
||||
#define SVR4_F_RDCHK_XENIX 0x6001
|
||||
#define SVR4_F_LK_UNLCK_XENIX 0x6300
|
||||
#define SVR4_F_LK_LOCK_XENIX 0x7200
|
||||
#define SVR4_F_LK_NBLCK_XENIX 0x6200
|
||||
#define SVR4_F_LK_RLCK_XENIX 0x7100
|
||||
#define SVR4_F_LK_NBRLCK_XENIX 0x6100
|
||||
|
||||
#define SVR4_LK_CMDTYPE(x) (((x) >> 12) & 0x7)
|
||||
#define SVR4_LK_LCKTYPE(x) (((x) >> 8) & 0x7)
|
||||
|
||||
#define SVR4_F_RDLCK 1
|
||||
#define SVR4_F_WRLCK 2
|
||||
#define SVR4_F_UNLCK 3
|
||||
|
||||
struct svr4_flock_svr3 {
|
||||
short l_type;
|
||||
short l_whence;
|
||||
svr4_off_t l_start;
|
||||
svr4_off_t l_len;
|
||||
short l_sysid;
|
||||
svr4_o_pid_t l_pid;
|
||||
};
|
||||
|
||||
|
||||
struct svr4_flock {
|
||||
short l_type;
|
||||
short l_whence;
|
||||
svr4_off_t l_start;
|
||||
svr4_off_t l_len;
|
||||
long l_sysid;
|
||||
svr4_pid_t l_pid;
|
||||
long pad[4];
|
||||
};
|
||||
|
||||
struct svr4_flock64 {
|
||||
short l_type;
|
||||
short l_whence;
|
||||
svr4_off64_t l_start;
|
||||
svr4_off64_t l_len;
|
||||
long l_sysid;
|
||||
svr4_pid_t l_pid;
|
||||
long pad[4];
|
||||
};
|
||||
#endif /* !_SVR4_FCNTL_H_ */
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user