Merge ^/head r295601 through r295844.

This commit is contained in:
Dimitry Andric 2016-02-21 13:49:26 +00:00
commit 9893f787ec
395 changed files with 30019 additions and 3937 deletions

View File

@ -1090,7 +1090,7 @@ distrib-dirs distribution: .MAKE .PHONY
.if make(distribution)
${_+_}cd ${.CURDIR}; ${CROSSENV} PATH=${TMPPATH} \
${MAKE} -f Makefile.inc1 ${IMAKE_INSTALL} \
METALOG=${METALOG} installconfig
METALOG=${METALOG} MK_TESTS=no installconfig
.endif
#

View File

@ -24,7 +24,18 @@ test: ${PROG} gen
LC_ALL=en_US.US-ASCII hexdump -C | \
diff -I FreeBSD - ${.CURDIR}/ref.${conv}
.endfor
@rm -f gen
@${ECHO} "testing sparse file (obs zeroes)"
@./gen 189284 | ./dd ibs=16 obs=8 conv=sparse of=obs_zeroes 2> /dev/null
@hexdump -C obs_zeroes | diff -I FreeBSD - ${.CURDIR}/ref.obs_zeroes
@${ECHO} "testing spase file (all zeroes)"
@./dd if=/dev/zero of=1M_zeroes bs=1048576 count=1 2> /dev/null
@./dd if=1M_zeroes of=1M_zeroes.1 bs=1048576 conv=sparse 2> /dev/null
@./dd if=1M_zeroes of=1M_zeroes.2 bs=1048576 2> /dev/null
@diff 1M_zeroes 1M_zeroes.1
@diff 1M_zeroes 1M_zeroes.2
@rm -f gen 1M_zeroes* obs_zeroes
.if ${MK_TESTS} != "no"
SUBDIR+= tests

View File

@ -77,7 +77,6 @@ STAT st; /* statistics */
void (*cfunc)(void); /* conversion function */
uintmax_t cpy_cnt; /* # of blocks to copy */
static off_t pending = 0; /* pending seek if sparse */
static off_t last_sp = 0; /* size of last added sparse block */
u_int ddflags = 0; /* conversion options */
size_t cbsz; /* conversion block size */
uintmax_t files_cnt = 1; /* # of files to copy */
@ -409,6 +408,15 @@ dd_close(void)
}
if (out.dbcnt || pending)
dd_out(1);
/*
* If the file ends with a hole, ftruncate it to extend its size
* up to the end of the hole (without having to write any data).
*/
if (out.seek_offset > 0 && (out.flags & ISTRUNC)) {
if (ftruncate(out.fd, out.seek_offset) == -1)
err(1, "truncating %s", out.name);
}
}
void
@ -457,29 +465,27 @@ dd_out(int force)
}
if (sparse && !force) {
pending += cnt;
last_sp = cnt;
nw = cnt;
} else {
if (pending != 0) {
/* If forced to write, and we have no
* data left, we need to write the last
* sparse block explicitly.
/*
* Seek past hole. Note that we need to record the
* reached offset, because we might have no more data
* to write, in which case we'll need to call
* ftruncate to extend the file size.
*/
if (force && cnt == 0) {
pending -= last_sp;
assert(outp == out.db);
memset(outp, 0, cnt);
}
if (lseek(out.fd, pending, SEEK_CUR) ==
-1)
out.seek_offset = lseek(out.fd, pending, SEEK_CUR);
if (out.seek_offset == -1)
err(2, "%s: seek error creating sparse file",
out.name);
pending = last_sp = 0;
pending = 0;
}
if (cnt)
if (cnt) {
nw = write(out.fd, outp, cnt);
else
out.seek_offset = 0;
} else {
return;
}
}
if (nw <= 0) {

View File

@ -54,6 +54,7 @@ typedef struct {
const char *name; /* name */
int fd; /* file descriptor */
off_t offset; /* # of blocks to skip */
off_t seek_offset; /* offset of last seek past output hole */
} IO;
typedef struct {

View File

@ -5,13 +5,20 @@
*/
#include <stdio.h>
#include <string.h>
int
main(int argc __unused, char **argv __unused)
main(int argc, char **argv)
{
int i;
for (i = 0; i < 256; i++)
putchar(i);
if (argc > 1 && !strcmp(argv[1], "189284")) {
fputs("ABCDEFGH", stdout);
for (i = 0; i < 8; i++)
putchar(0);
} else {
for (i = 0; i < 256; i++)
putchar(i);
}
return (0);
}

3
bin/dd/ref.obs_zeroes Normal file
View File

@ -0,0 +1,3 @@
$FreeBSD$
00000000 41 42 43 44 45 46 47 48 00 00 00 00 00 00 00 00 |ABCDEFGH........|
00000010

View File

@ -195,8 +195,7 @@ preadfd(void)
int
preadbuffer(void)
{
char *p, *q;
int more;
char *p, *q, *r, *end;
char savec;
while (parsefile->strpush) {
@ -224,34 +223,31 @@ preadbuffer(void)
}
}
q = p = parsefile->buf + (parsenextc - parsefile->buf);
/* delete nul characters */
for (more = 1; more;) {
switch (*p) {
case '\0':
p++; /* Skip nul */
goto check;
case '\n':
parsenleft = q - parsenextc;
more = 0; /* Stop processing here */
break;
default:
break;
}
*q++ = *p++;
check:
if (--parselleft <= 0) {
parsenleft = q - parsenextc - 1;
if (parsenleft < 0)
goto again;
*q = '\0';
more = 0;
p = parsefile->buf + (parsenextc - parsefile->buf);
end = p + parselleft;
*end = '\0';
q = strchrnul(p, '\n');
if (q != end && *q == '\0') {
/* delete nul characters */
for (r = q; q != end; q++) {
if (*q != '\0')
*r++ = *q;
}
parselleft -= end - r;
if (parselleft == 0)
goto again;
end = p + parselleft;
*end = '\0';
q = strchrnul(p, '\n');
}
if (q == end) {
parsenleft = parselleft;
parselleft = 0;
} else /* *q == '\n' */ {
parsenleft = q - parsenextc + 1;
parselleft -= parsenleft;
}
parsenleft--;
savec = *q;
*q = '\0';

View File

@ -10,6 +10,4 @@ TESTS_SUBDIRS+= parameters
TESTS_SUBDIRS+= parser
TESTS_SUBDIRS+= set-e
SUBDIR_PARALLEL=
.include <bsd.test.mk>

View File

@ -25,6 +25,8 @@ FILES+= alias15.0 alias15.0.stdout
FILES+= and-pipe-not.0
FILES+= case1.0
FILES+= case2.0
FILES+= comment1.0
FILES+= comment2.42
FILES+= dollar-quote1.0
FILES+= dollar-quote2.0
FILES+= dollar-quote3.0
@ -71,6 +73,7 @@ FILES+= line-cont10.0
FILES+= line-cont11.0
FILES+= no-space1.0
FILES+= no-space2.0
FILES+= nul1.0
FILES+= only-redir1.0
FILES+= only-redir2.0
FILES+= only-redir3.0

View File

@ -0,0 +1,3 @@
# $FreeBSD$
${SH} -c '#'

View File

@ -0,0 +1,4 @@
# $FreeBSD$
${SH} -c '#
exit 42'

View File

@ -0,0 +1,12 @@
# $FreeBSD$
# Although POSIX does not specify the effect of NUL bytes in scripts,
# we ignore them.
{
printf 'v=%03000d\0%02000d' 7 2
dd if=/dev/zero bs=1000 count=1 status=none
printf '1 w=%03000d%02000d1\0\n' 7 2
printf '\0l\0v\0=\0$\0{\0#\0v\0}\n'
printf '\0l\0w\0=\0\0$\0{\0#\0w}\0\0\0\n'
printf '[ "$lv.$lw.$v" = "5001.5001.$w" ]\n'
} | ${SH}

View File

@ -1713,7 +1713,7 @@ zfs_do_get(int argc, char **argv)
default:
(void) fprintf(stderr,
gettext("invalid column name "
"'%s'\n"), value);
"'%s'\n"), suboptarg);
usage(B_FALSE);
}
}
@ -1750,7 +1750,7 @@ zfs_do_get(int argc, char **argv)
default:
(void) fprintf(stderr,
gettext("invalid source "
"'%s'\n"), value);
"'%s'\n"), suboptarg);
usage(B_FALSE);
}
}
@ -1786,7 +1786,7 @@ zfs_do_get(int argc, char **argv)
default:
(void) fprintf(stderr,
gettext("invalid type '%s'\n"),
value);
suboptarg);
usage(B_FALSE);
}
}
@ -3156,7 +3156,7 @@ zfs_do_list(int argc, char **argv)
default:
(void) fprintf(stderr,
gettext("invalid type '%s'\n"),
value);
suboptarg);
usage(B_FALSE);
}
}

View File

@ -5431,7 +5431,7 @@ zpool_do_get(int argc, char **argv)
default:
(void) fprintf(stderr,
gettext("invalid column name "
"'%s'\n"), value);
"'%s'\n"), suboptarg);
usage(B_FALSE);
}
}

View File

@ -86,6 +86,4 @@ TESTS_SUBDIRS+= aggs \
.PATH: ${.CURDIR:H:H:H:H:H}/tests
KYUAFILE= YES
SUBDIR_PARALLEL=
.include <bsd.test.mk>

View File

@ -641,6 +641,18 @@ create_file(struct elfcopy *ecp, const char *src, const char *dst)
* ELF object before processing.
*/
if (ecp->itf != ETF_ELF) {
/*
* If the output object is not an ELF file, choose an arbitrary
* ELF format for the intermediate file. srec, ihex and binary
* formats are independent of class, endianness and machine
* type so these choices do not affect the output.
*/
if (ecp->otf != ETF_ELF) {
if (ecp->oec == ELFCLASSNONE)
ecp->oec = ELFCLASS64;
if (ecp->oed == ELFDATANONE)
ecp->oed = ELFDATA2LSB;
}
create_tempfile(&elftemp, &efd);
if ((ecp->eout = elf_begin(efd, ELF_C_WRITE, NULL)) == NULL)
errx(EXIT_FAILURE, "elf_begin() failed: %s",

View File

@ -16,7 +16,7 @@
.R
..
.de Id
.ND \\$4
.ND 1 June 1995
..
.Id $FreeBSD$
.RP

View File

@ -36,8 +36,10 @@
#include <sys/cdefs.h>
#include <sys/_types.h>
#include <sys/signal.h>
#if __POSIX_VISIBLE >= 200112 || __XSI_VISIBLE
#include <machine/ucontext.h>
#include <sys/_ucontext.h>
#endif
#if __BSD_VISIBLE
/*

View File

@ -0,0 +1,15 @@
# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
include \
include/xlocale \
lib/libc++ \
lib/msun \
.include <dirdeps.mk>
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
# local dependencies - needed for -jN in clean tree
.endif

View File

@ -0,0 +1,15 @@
# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
include \
include/xlocale \
lib/libc++ \
lib/msun \
.include <dirdeps.mk>
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
# local dependencies - needed for -jN in clean tree
.endif

View File

@ -0,0 +1,18 @@
# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
include \
include/xlocale \
lib/libc++ \
lib/msun \
usr.bin/clang/tblgen.host \
.include <dirdeps.mk>
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
# local dependencies - needed for -jN in clean tree
LibDriver.o: Options.inc.h
LibDriver.po: Options.inc.h
.endif

View File

@ -0,0 +1,18 @@
# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
include \
include/xlocale \
lib/libc++ \
lib/msun \
usr.bin/clang/tblgen.host \
.include <dirdeps.mk>
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
# local dependencies - needed for -jN in clean tree
LTOCodeGenerator.o: Intrinsics.inc.h
LTOCodeGenerator.po: Intrinsics.inc.h
.endif

View File

@ -0,0 +1,15 @@
# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
include \
include/xlocale \
lib/libc++ \
lib/msun \
.include <dirdeps.mk>
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
# local dependencies - needed for -jN in clean tree
.endif

View File

@ -0,0 +1,15 @@
# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
include \
include/xlocale \
lib/libc++ \
lib/msun \
.include <dirdeps.mk>
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
# local dependencies - needed for -jN in clean tree
.endif

View File

@ -0,0 +1,18 @@
# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
include \
include/xlocale \
lib/libc++ \
lib/msun \
usr.bin/clang/tblgen.host \
.include <dirdeps.mk>
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
# local dependencies - needed for -jN in clean tree
PassBuilder.o: Intrinsics.inc.h
PassBuilder.po: Intrinsics.inc.h
.endif

View File

@ -28,7 +28,7 @@
.\" @(#)directory.3 8.1 (Berkeley) 6/4/93
.\" $FreeBSD$
.\"
.Dd May 6, 2015
.Dd February 19, 2016
.Dt DIRECTORY 3
.Os
.Sh NAME
@ -46,7 +46,6 @@
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
.In sys/types.h
.In dirent.h
.Ft DIR *
.Fn opendir "const char *filename"

View File

@ -28,7 +28,7 @@
.\" @(#)fgetln.3 8.3 (Berkeley) 4/19/94
.\" $FreeBSD$
.\"
.Dd April 19, 1994
.Dd February 15, 2016
.Dt FGETLN 3
.Os
.Sh NAME
@ -97,6 +97,9 @@ These changes are lost as soon as the pointer becomes invalid.
The argument
.Fa stream
is not a stream open for reading.
.It Bq Er ENOMEM
The internal line buffer could not be expanded due to lack of available memory,
or because it would need to expand beyond INT_MAX in size.
.El
.Pp
The

View File

@ -37,6 +37,8 @@ static char sccsid[] = "@(#)fgetln.c 8.2 (Berkeley) 1/2/94";
__FBSDID("$FreeBSD$");
#include "namespace.h"
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -61,6 +63,10 @@ __slbexpand(FILE *fp, size_t newsize)
#endif
if (fp->_lb._size >= newsize)
return (0);
if (newsize > INT_MAX) {
errno = ENOMEM;
return (-1);
}
if ((p = realloc(fp->_lb._base, newsize)) == NULL)
return (-1);
fp->_lb._base = p;
@ -152,13 +158,14 @@ fgetln(FILE *fp, size_t *lenp)
}
*lenp = len;
#ifdef notdef
fp->_lb._base[len] = 0;
fp->_lb._base[len] = '\0';
#endif
FUNLOCKFILE(fp);
return ((char *)fp->_lb._base);
error:
*lenp = 0; /* ??? */
fp->_flags |= __SERR;
FUNLOCKFILE(fp);
return (NULL); /* ??? */
}

View File

@ -37,6 +37,7 @@ static char sccsid[] = "@(#)fputs.c 8.1 (Berkeley) 6/4/93";
__FBSDID("$FreeBSD$");
#include "namespace.h"
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include "un-namespace.h"
@ -62,5 +63,7 @@ fputs(const char * __restrict s, FILE * __restrict fp)
ORIENT(fp, -1);
retval = __sfvwrite(fp, &uio);
FUNLOCKFILE(fp);
if (retval == 0)
return (iov.iov_len > INT_MAX ? INT_MAX : iov.iov_len);
return (retval);
}

View File

@ -28,7 +28,7 @@
.\" @(#)lseek.2 8.3 (Berkeley) 4/19/94
.\" $FreeBSD$
.\"
.Dd May 26, 2012
.Dd February 18, 2016
.Dt LSEEK 2
.Os
.Sh NAME
@ -131,8 +131,14 @@ Applications can use
.Dv SEEK_HOLE
to optimise their behavior for ranges of zeros, but must not depend on it to
find all such ranges in a file.
Each file is presented as having a zero-size virtual hole at the very
end of the file.
The existence of a hole at the end of every data region allows for easy
programming and implies that a virtual hole exists at the end of the file.
programming and also provides compatibility to the original implementation
in Solaris.
It also causes the current file size (i.e., end-of-file offset) to be returned
to indicate that there are no more holes past the supplied
.Fa offset .
Applications should use
.Fn fpathconf _PC_MIN_HOLE_SIZE
or
@ -176,9 +182,11 @@ be negative for a non-character special file.
For
.Dv SEEK_DATA ,
there are no more data regions past the supplied offset.
For
.Dv SEEK_HOLE ,
there are no more holes past the supplied offset.
Due to existence of the hole at the end of the file, for
.Dv SEEK_HOLE
this error is only returned when the
.Fa offset
already points to the end-of-file position.
.It Bq Er EOVERFLOW
The resulting file offset would be a value which cannot be represented
correctly in an object of type

View File

@ -22,6 +22,8 @@ TESTS_SUBDIRS+= termios
TESTS_SUBDIRS+= tls
TESTS_SUBDIRS+= ttyio
SUBDIR_DEPEND_tls= tls_dso
.if ${MK_LOCALES} != "no"
TESTS_SUBDIRS+= locale
.endif

View File

@ -20,7 +20,7 @@ CLEANFILES+= h_nonexec
.include "../../Makefile.netbsd-tests"
h_zero:
dd if=/dev/zero of=h_zero bs=1k count=2
dd if=/dev/zero of=h_zero bs=1k count=2 status=none
chmod a+x h_zero
CLEANFILES+= h_zero

View File

@ -78,6 +78,6 @@ truncate_test_FILESGRP= wheel
CLEANFILES= truncate_test.root_owned
truncate_test.root_owned:
dd if=/dev/null bs=1 count=1 of=${.TARGET}
dd if=/dev/null bs=1 count=1 of=${.TARGET} status=none
.include <bsd.test.mk>

View File

@ -183,7 +183,7 @@ _arm_initvtop(kvm_t *kd)
#define l1pte_section_p(pde) (((pde) & ARM_L1_TYPE_MASK) == ARM_L1_TYPE_S)
#define l1pte_valid(pde) ((pde) != 0)
#define l2pte_valid(pte) ((pte) != 0)
#define l2pte_index(v) (((v) & ARM_L2_ADDR_BITS) >> ARM_L2_S_SHIFT)
#define l2pte_index(v) (((v) & ARM_L1_S_OFFSET) >> ARM_L2_S_SHIFT)
static int

View File

@ -29,10 +29,6 @@
#ifndef __KVM_ARM_H__
#define __KVM_ARM_H__
#ifdef __arm__
#include <machine/pte.h>
#endif
typedef uint32_t arm_physaddr_t;
typedef uint32_t arm_pd_entry_t;
typedef uint32_t arm_pt_entry_t;
@ -72,11 +68,15 @@ typedef uint32_t arm_pt_entry_t;
#define ARM_L2_TYPE_T 0x03 /* Tiny Page - 1k - not used */
#define ARM_L2_TYPE_MASK 0x03
#define ARM_L2_ADDR_BITS 0x000ff000 /* L2 PTE address bits */
#ifdef __arm__
#include <machine/acle-compat.h>
#if __ARM_ARCH >= 6
#include <machine/pte-v6.h>
#else
#include <machine/pte-v4.h>
#endif
_Static_assert(PAGE_SHIFT == ARM_PAGE_SHIFT, "PAGE_SHIFT mismatch");
_Static_assert(PAGE_SIZE == ARM_PAGE_SIZE, "PAGE_SIZE mismatch");
_Static_assert(PAGE_MASK == ARM_PAGE_MASK, "PAGE_MASK mismatch");
@ -106,7 +106,6 @@ _Static_assert(L2_TYPE_S == ARM_L2_TYPE_S, "L2_TYPE_S mismatch");
_Static_assert(L2_TYPE_T == ARM_L2_TYPE_T, "L2_TYPE_T mismatch");
#endif
_Static_assert(L2_TYPE_MASK == ARM_L2_TYPE_MASK, "L2_TYPE_MASK mismatch");
_Static_assert(L2_ADDR_BITS == ARM_L2_ADDR_BITS, "L2_ADDR_BITS mismatch");
#endif
int _arm_native(kvm_t *);

13
lib/libpe/Makefile.depend Normal file
View File

@ -0,0 +1,13 @@
# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
include \
include/xlocale \
.include <dirdeps.mk>
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
# local dependencies - needed for -jN in clean tree
.endif

View File

@ -10,6 +10,7 @@ SUBDIR= ${_atf} \
${_dma} \
getty \
${_mail.local} \
${_makewhatis.local} \
${_mknetid} \
${_pppoed} \
revnetgroup \
@ -88,6 +89,10 @@ _mail.local= mail.local
_smrsh= smrsh
.endif
.if ${MK_MAN_UTILS} != "no"
_makewhatis.local= makewhatis.local
.endif
.if ${MK_TALK} != "no"
SUBDIR+= talkd
.endif

View File

@ -0,0 +1,9 @@
# $FreeBSD$
SCRIPTS= makewhatis.local.sh
MAN= makewhatis.local.8
SCRIPTSDIR= ${LIBEXECDIR}
LINKS= ${SCRIPTSDIR}/makewhatis.local ${SCRIPTSDIR}/catman.local
MLINKS= makewhatis.local.8 catman.local.8
.include <bsd.prog.mk>

View File

@ -0,0 +1,11 @@
# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
.include <dirdeps.mk>
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
# local dependencies - needed for -jN in clean tree
.endif

View File

@ -0,0 +1,83 @@
.\" Copyright (c) April 1996 Wolfram Schneider <wosch@FreeBSD.org>. Berlin.
.\" 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 April 26, 1996
.Dt MAKEWHATIS.LOCAL 8
.Os
.Sh NAME
.Nm makewhatis.local , catman.local
.Nd start makewhatis or catman for local file systems
.Sh SYNOPSIS
.Nm /usr/libexec/makewhatis.local
.Op options
.Ar directories ...
.Nm /usr/libexec/catman.local
.Op options
.Ar directories ...
.Sh DESCRIPTION
The
.Nm
utility starts
.Xr makewhatis 1
only for file systems physically mounted on the system
where the
.Nm
is being executed.
Running makewhatis
by
.Pa periodic weekly
for rw nfs-mounted /usr may kill
your NFS server -- all NFS clients start makewhatis at the same time!
So use this wrapper for
.Xr cron 8
instead of calling makewhatis directly.
The
.Nm catman.local
utility is using for same purposes as
.Nm
but for
.Xr catman 1 .
.Sh FILES
.Bl -tag -width /etc/periodic/weekly/320.whatis.XXX -compact
.It Pa /etc/periodic/weekly/320.whatis
run
.Nm
every week
.It Pa /etc/periodic/weekly/330.catman
run
.Nm catman.local
every week
.El
.Sh SEE ALSO
.Xr catman 1 ,
.Xr find 1 ,
.Xr makewhatis 1 ,
.Xr cron 8 ,
.Xr periodic 8
.Sh HISTORY
The
.Nm
utility appeared in
.Fx 2.2 .

View File

@ -0,0 +1,58 @@
#!/bin/sh
#
# Copyright (c) April 1996 Wolfram Schneider <wosch@FreeBSD.org>. Berlin.
# 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.
#
# makewhatis.local - start makewhatis(1) only for file systems
# physically mounted on the system
#
# Running makewhatis from /etc/periodic/weekly/320.whatis for rw nfs-mounted
# /usr may kill your NFS server -- all clients start makewhatis at the same
# time! So use this wrapper instead calling makewhatis directly.
#
# PS: this wrapper works also for catman(1)
#
# $FreeBSD$
PATH=/bin:/usr/bin:$PATH; export PATH
opt= dirs= localdirs=
for arg
do
case "$arg" in
-*) opt="$opt $arg";;
*) dirs="$dirs $arg";;
esac
done
dirs=`echo $dirs | sed 's/:/ /g'`
case X"$dirs" in X) echo "usage: $0 [options] directories ..."; exit 1;; esac
localdirs=`find -H $dirs -fstype local -type d -prune -print`
case X"$localdirs" in
X) echo "$0: no local-mounted manual directories found: $dirs"
exit 1;;
*) exec `basename $0 .local` $opt $localdirs;;
esac

View File

@ -4,6 +4,7 @@
SUBDIR+= libpythagoras target
SUBDIR_DEPEND_target= libpythagoras
ATF_TESTS_C= ld_library_pathfds
.include <bsd.test.mk>

View File

@ -144,11 +144,12 @@ ifclonecreate(int s, void *arg)
}
/*
* If we get a different name back than we put in, print it.
* If we get a different name back than we put in, update record and
* indicate it should be printed later.
*/
if (strncmp(name, ifr.ifr_name, sizeof(name)) != 0) {
strlcpy(name, ifr.ifr_name, sizeof(name));
printf("%s\n", name);
printifname = 1;
}
}

View File

@ -93,6 +93,7 @@ int clearaddr;
int newaddr = 1;
int verbose;
int noload;
int printifname = 0;
int supmedia = 0;
int printkeys = 0; /* Print keying material for interfaces. */
@ -108,6 +109,8 @@ static struct afswtch *af_getbyname(const char *name);
static struct afswtch *af_getbyfamily(int af);
static void af_other_status(int);
void printifnamemaybe(void);
static struct option *opts = NULL;
struct ifa_order_elt {
@ -297,6 +300,12 @@ sortifaddrs(struct ifaddrs *list,
return (result);
}
void printifnamemaybe()
{
if (printifname)
printf("%s\n", name);
}
int
main(int argc, char *argv[])
{
@ -314,6 +323,12 @@ main(int argc, char *argv[])
size_t iflen;
all = downonly = uponly = namesonly = noload = verbose = 0;
/*
* Ensure we print interface name when expected to,
* even if we terminate early due to error.
*/
atexit(printifnamemaybe);
/* Parse leading line options */
strlcpy(options, "adklmnuv", sizeof(options));
@ -1011,6 +1026,8 @@ setifname(const char *val, int dummy __unused, int s,
const struct afswtch *afp)
{
char *newname;
strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
newname = strdup(val);
if (newname == NULL)
@ -1020,6 +1037,7 @@ setifname(const char *val, int dummy __unused, int s,
free(newname);
err(1, "ioctl SIOCSIFNAME (set name)");
}
printifname = 1;
strlcpy(name, newname, sizeof(name));
free(newname);
}
@ -1031,6 +1049,8 @@ setifdescr(const char *val, int dummy __unused, int s,
{
char *newdescr;
strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
ifr.ifr_buffer.length = strlen(val) + 1;
if (ifr.ifr_buffer.length == 1) {
ifr.ifr_buffer.buffer = newdescr = NULL;

View File

@ -133,6 +133,7 @@ extern int supmedia;
extern int printkeys;
extern int newaddr;
extern int verbose;
extern int printifname;
void setifcap(const char *, int value, int s, const struct afswtch *);

View File

@ -8,6 +8,7 @@ DIRDEPS = \
lib/${CSU_DIR} \
lib/libc \
lib/libcompiler_rt \
lib/libutil \
.include <dirdeps.mk>

View File

@ -6,6 +6,7 @@ DIRDEPS = \
gnu/lib/libgcc \
include \
include/arpa \
include/gssapi \
include/xlocale \
lib/${CSU_DIR} \
lib/libc \

View File

@ -1,3 +1,4 @@
.\" Copyright (c) 2006, Ceri Davies <ceri@FreeBSD.org>
.\" Copyright (c) 2014, Luiz Otavio O Souza <loos@FreeBSD.org>
.\" All rights reserved.
.\"
@ -100,8 +101,18 @@ Consumers:
The
.Nm
driver was written by
.An Maxim Sobolev Aq Mt sobomax@FreeBSD.org
and
.An Aleksandr Rybalko Aq Mt ray@FreeBSD.org .
.An Max Khon Aq Mt fjoe@FreeBSD.org
as
.Xr geom_uzip 4 .
.An Aleksandr Rybalko Aq Mt ray@FreeBSD.org
copied it over as
.Nm
and added LZMA functionality .
This manual page was written by
.An Luiz Otavio O Souza Aq Mt loos@FreeBSD.org .
.An Ceri Davies Aq Mt ceri@FreeBSD.org
for the
.Xr geom_uzip 4 ,
and modified by
.An Luiz Otavio O Souza Aq Mt loos@FreeBSD.org
to match
.Nm .

View File

@ -31,7 +31,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd October 8, 2010
.Dd February 18, 2016
.Dt MAILER.CONF 5
.Os
.Sh NAME
@ -101,9 +101,10 @@ mailq /usr/libexec/sendmail/sendmail
newaliases /usr/libexec/sendmail/sendmail
.Ed
.Pp
This example shows how to invoke a sendmail-workalike like
Using
.Nm Postfix
in place of
(from ports)
to replace
.Xr sendmail 8 :
.Bd -literal -offset indent
# Emulate sendmail using postfix
@ -113,12 +114,10 @@ mailq /usr/local/sbin/sendmail
newaliases /usr/local/sbin/sendmail
.Ed
.Pp
This example shows
how to invoke
a sendmail-workalike with
Using
.Nm Exim
(from ports)
in place of
to replace
.Xr sendmail 8 :
.Bd -literal -offset indent
# Emulate sendmail using exim
@ -129,24 +128,40 @@ newaliases /usr/bin/true
rmail /usr/local/sbin/exim -i -oee
.Ed
.Pp
This example shows the use of the
Using
.Nm mini_sendmail
package from ports in place of
.Xr sendmail 8 .
Note the use of additional arguments.
(from ports)
to replace
.Xr sendmail 8 :
.Bd -literal -offset indent
# Send outgoing mail to a smart relay using mini_sendmail
sendmail /usr/local/bin/mini_sendmail -srelayhost
send-mail /usr/local/bin/mini_sendmail -srelayhost
.Ed
.Pp
Using
.Xr dma 8
to replace
.Xr sendmail 8 :
.Bd -literal -offset indent
# Execute dma instead of sendmail
sendmail /usr/libexec/dma
send-mail /usr/libexec/dma
mailq /usr/libexec/dma
newaliases /usr/libexec/dma
rmail /usr/libexec/dma
.Ed
.Sh SEE ALSO
.Xr mail 1 ,
.Xr mailq 1 ,
.Xr newaliases 1 ,
.Xr dma 8 ,
.Xr mailwrapper 8 ,
.Xr sendmail 8
.Pp
.Xr postfix 1 Pq Pa ports/mail/postfix ,
.Xr dma 8 Pq Pa ports/mail/dma ,
.Xr exim 8 Pq Pa ports/mail/exim ,
.Xr mini_sendmail 8 Pq Pa ports/mail/mini_sendmail
.Sh HISTORY
.Nm

View File

@ -175,6 +175,7 @@ nork [label="Norikatsu Shigemura\nnork@FreeBSD.org\n2002/04/01"]
novel [label="Roman Bogorodskiy\nnovel@FreeBSD.org\n2005/03/07"]
nox [label="Juergen Lock\nnox@FreeBSD.org\n2006/12/22"]
obrien [label="David E. O'Brien\nobrien@FreeBSD.org\n1996/10/29"]
olivier [label="Olivier Cochard-Labbe\nolivier@FreeBSD.org\n2016/02/02"]
olivierd [label="Olivier Duchateau\nolivierd@FreeBSD.org\n2012/05/29"]
osa [label="Sergey A. Osokin\nosa@FreeBSD.org\n2003/06/04"]
pat [label="Patrick Li\npat@FreeBSD.org\n2001/11/14"]
@ -400,6 +401,7 @@ itetcu -> sylvio
jadawin -> bapt
jadawin -> flo
jadawin -> olivier
jadawin -> riggs
jadawin -> sbz
jadawin -> wen

View File

@ -5,6 +5,11 @@
#
# +++ variables +++
#
# CLEANDEPENDDIRS Additional directories to remove for the cleandepend
# target.
#
# CLEANDEPENDFILES Additional files to remove for the cleandepend target.
#
# CTAGS A tags file generation program [gtags]
#
# CTAGSFLAGS Options for ctags(1) [not set]
@ -27,7 +32,8 @@
# +++ targets +++
#
# cleandepend:
# Remove depend and tags file
# remove ${CLEANDEPENDFILES}; remove ${CLEANDEPENDDIRS} and all
# contents.
#
# depend:
# Make the dependencies for the source files, and store
@ -59,7 +65,7 @@ DEPENDFILE?= .depend
.if ${MK_DIRDEPS_BUILD} == "no"
.MAKE.DEPENDFILE= ${DEPENDFILE}
.endif
DEPENDFILES= ${DEPENDFILE}
CLEANDEPENDFILES= ${DEPENDFILE} ${DEPENDFILE}.*
# Keep `tags' here, before SRCS are mangled below for `depend'.
.if !target(tags) && defined(SRCS) && !defined(NO_TAGS)
@ -75,6 +81,16 @@ tags: ${SRCS}
.endif
.endif
# Skip reading .depend when not needed to speed up tree-walks
# and simple lookups.
.if !empty(.MAKEFLAGS:M-V${_V_READ_DEPEND}) || make(obj) || make(clean*) || \
make(install*)
_SKIP_READ_DEPEND= 1
.if ${MK_DIRDEPS_BUILD} == "no"
.MAKE.DEPENDFILE= /dev/null
.endif
.endif
.if defined(SRCS)
CLEANFILES?=
@ -156,7 +172,6 @@ ${_D}.po: ${_DSRC} ${POBJS:S/^${_D}.po$//}
.if ${MK_FAST_DEPEND} == "yes" && \
(${.MAKE.MODE:Mmeta} == "" || ${.MAKE.MODE:Mnofilemon} != "")
DEPENDFILES+= ${DEPENDFILE}.*
DEPEND_MP?= -MP
# Handle OBJS=../somefile.o hacks. Just replace '/' rather than use :T to
# avoid collisions.
@ -176,7 +191,7 @@ DEPENDSRCS= ${SRCS:M*.[cSC]} ${SRCS:M*.cxx} ${SRCS:M*.cpp} ${SRCS:M*.cc}
DEPENDOBJS+= ${DEPENDSRCS:R:S,$,.o,}
.endif
DEPENDFILES_OBJS= ${DEPENDOBJS:O:u:${DEPEND_FILTER}:C/^/${DEPENDFILE}./}
.if ${.MAKEFLAGS:M-V} == ""
.if !defined(_SKIP_READ_DEPEND)
.for __depend_obj in ${DEPENDFILES_OBJS}
.sinclude "${__depend_obj}"
.endfor
@ -205,14 +220,6 @@ depend: beforedepend ${DEPENDFILE} afterdepend
# This could be simpler with bmake :tW but needs to support fmake for MFC.
_CFLAGS_INCLUDES= ${CFLAGS:Q:S/\\ /,/g:C/-include,/-include%/g:C/,/ /g:M-include*:C/%/ /g}
_CXXFLAGS_INCLUDES= ${CXXFLAGS:Q:S/\\ /,/g:C/-include,/-include%/g:C/,/ /g:M-include*:C/%/ /g}
# XXX: Temporary hack to workaround .depend files not tracking -include
_hdrincludes=${_CFLAGS_INCLUDES:M*.h} ${_CXXFLAGS_INCLUDES:M*.h}
.for _hdr in ${_hdrincludes:O:u}
.if exists(${_hdr})
${OBJS} ${POBJS} ${SOBJS}: ${_hdr}
.endif
.endfor
.undef _hdrincludes
# Different types of sources are compiled with slightly different flags.
# Split up the sources, and filter out headers and non-applicable flags.
@ -261,16 +268,20 @@ afterdepend:
.endif
.endif
.if ${CTAGS:T} == "gtags"
CLEANDEPENDFILES+= GPATH GRTAGS GSYMS GTAGS
.if defined(HTML)
CLEANDEPENDDIRS+= HTML
.endif
.else
CLEANDEPENDFILES+= tags
.endif
.if !target(cleandepend)
cleandepend:
.if defined(SRCS)
.if ${CTAGS:T} == "gtags"
rm -f ${DEPENDFILES} GPATH GRTAGS GSYMS GTAGS
.if defined(HTML)
rm -rf HTML
.endif
.else
rm -f ${DEPENDFILES} tags
rm -f ${CLEANDEPENDFILES}
.if !empty(CLEANDEPENDDIRS)
rm -rf ${CLEANDEPENDDIRS}
.endif
.endif
.endif

View File

@ -15,6 +15,10 @@ __<bsd.init.mk>__:
.endif
.include <bsd.own.mk>
.MAIN: all
beforebuild: .PHONY .NOTMAIN
.if !defined(_SKIP_BUILD)
all: beforebuild .WAIT
.endif
.if ${.MAKE.LEVEL:U1} == 0 && ${BUILD_AT_LEVEL0:Uyes:tl} == "no" && !make(clean*)
# this tells lib.mk and prog.mk to not actually build anything

View File

@ -128,11 +128,6 @@ PO_FLAG=-pg
-c ${.IMPSRC} -o ${.TARGET}
${CTFCONVERT_CMD}
.if !defined(_SKIP_BUILD)
all: beforebuild .WAIT
beforebuild: objwarn
.endif
_LIBDIR:=${LIBDIR}
_SHLIBDIR:=${SHLIBDIR}

View File

@ -89,6 +89,7 @@ objwarn:
canonical ${CANONICALOBJDIR}"
.endif
.endif
beforebuild: objwarn
.if !defined(NO_OBJ)
.if !target(obj)

View File

@ -148,8 +148,7 @@ MAN1= ${MAN}
.if defined(_SKIP_BUILD)
all:
.else
all: beforebuild .WAIT ${PROG} ${SCRIPTS}
beforebuild: objwarn
all: ${PROG} ${SCRIPTS}
.if ${MK_MAN} != "no"
all: _manpages
.endif

View File

@ -89,6 +89,7 @@ ${__stage}install:
install: beforeinstall realinstall afterinstall
.ORDER: beforeinstall realinstall afterinstall
.endif
.ORDER: all install
# SUBDIR recursing may be disabled for MK_DIRDEPS_BUILD
.if !target(_SUBDIR)

View File

@ -68,6 +68,7 @@ _TESTS=
SUBDIR+= ${ts}
.endif
.endfor
SUBDIR_PARALLEL= t
.endif
# it is rare for test cases to have man pages

View File

@ -204,6 +204,7 @@ CSU_DIR := ${CSU_DIR.${MACHINE_ARCH}}
.if !empty(TIME_STAMP)
TRACER= ${TIME_STAMP} ${:U}
.endif
WITH_META_STATS= t
# toolchains can be a pain - especially bootstrappping them
.if ${MACHINE} == "host"

View File

@ -41,7 +41,6 @@ __FBSDID("$FreeBSD$");
#include <sys/rman.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/gpio.h>
#include <machine/bus.h>
#include <dev/ofw/ofw_bus.h>
@ -49,7 +48,6 @@ __FBSDID("$FreeBSD$");
#include <dev/ahci/ahci.h>
#include <arm/allwinner/a10_clk.h>
#include "gpio_if.h"
/*
* Allwinner a1x/a2x/a8x SATA attachment. This is just the AHCI register
@ -119,9 +117,6 @@ __FBSDID("$FreeBSD$");
#define AHCI_P0PHYCR 0x0078
#define AHCI_P0PHYSR 0x007C
/* Kludge for CUBIEBOARD (and Banana PI too) */
#define GPIO_AHCI_PWR 40
static void inline
ahci_set(struct resource *m, bus_size_t off, uint32_t set)
{
@ -298,7 +293,6 @@ ahci_a10_probe(device_t dev)
static int
ahci_a10_attach(device_t dev)
{
device_t gpio;
int error;
struct ahci_controller *ctlr;
@ -316,19 +310,6 @@ ahci_a10_attach(device_t dev)
/* Turn on the PLL for SATA */
a10_clk_ahci_activate();
/* Apply power to the drive, if any */
gpio = devclass_get_device(devclass_find("gpio"), 0);
if (gpio == NULL) {
device_printf(dev,
"GPIO device not yet present (SATA won't work).\n");
bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid,
ctlr->r_mem);
return (ENXIO);
}
GPIO_PIN_SETFLAGS(gpio, GPIO_AHCI_PWR, GPIO_PIN_OUTPUT);
GPIO_PIN_SET(gpio, GPIO_AHCI_PWR, GPIO_PIN_HIGH);
DELAY(10000);
/* Reset controller */
if ((error = ahci_a10_ctlr_reset(dev)) != 0) {
bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid,

View File

@ -400,6 +400,29 @@ a10_clk_mmc_cfg(int devid, int freq)
return (0);
}
int
a10_clk_i2c_activate(int devid)
{
struct a10_ccm_softc *sc;
uint32_t reg_value;
sc = a10_ccm_sc;
if (sc == NULL)
return (ENXIO);
a10_clk_pll6_enable();
/* Gating APB clock for I2C/TWI */
reg_value = ccm_read_4(sc, CCM_APB1_GATING);
if (devid == 4)
reg_value |= CCM_APB1_GATING_TWI << 15;
else
reg_value |= CCM_APB1_GATING_TWI << devid;
ccm_write_4(sc, CCM_APB1_GATING, reg_value);
return (0);
}
int
a10_clk_dmac_activate(void)
{

View File

@ -121,6 +121,9 @@
/* AHB_GATING_REG1 */
#define CCM_AHB_GATING_GMAC (1 << 17)
/* APB1_GATING_REG */
#define CCM_APB1_GATING_TWI (1 << 0)
#define CCM_USB_PHY (1 << 8)
#define CCM_USB0_RESET (1 << 0)
#define CCM_USB1_RESET (1 << 1)
@ -166,6 +169,7 @@ int a10_clk_gmac_activate(phandle_t);
int a10_clk_ahci_activate(void);
int a10_clk_mmc_activate(int);
int a10_clk_mmc_cfg(int, int);
int a10_clk_i2c_activate(int);
int a10_clk_dmac_activate(void);
int a10_clk_codec_activate(unsigned int);

View File

@ -0,0 +1,850 @@
/*-
* Copyright (c) 2014-2016 Jared D. McNeill <jmcneill@invisible.ca>
* 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 A10/A20 Audio Codec
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/rman.h>
#include <sys/condvar.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/gpio.h>
#include <machine/bus.h>
#include <dev/sound/pcm/sound.h>
#include <dev/sound/chip.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#include <arm/allwinner/a10_clk.h>
#include "sunxi_dma_if.h"
#include "mixer_if.h"
#include "gpio_if.h"
#define TX_TRIG_LEVEL 0xf
#define RX_TRIG_LEVEL 0x7
#define DRQ_CLR_CNT 0x3
#define AC_DAC_DPC 0x00
#define DAC_DPC_EN_DA 0x80000000
#define AC_DAC_FIFOC 0x04
#define DAC_FIFOC_FS_SHIFT 29
#define DAC_FIFOC_FS_MASK (7U << DAC_FIFOC_FS_SHIFT)
#define DAC_FS_48KHZ 0
#define DAC_FS_32KHZ 1
#define DAC_FS_24KHZ 2
#define DAC_FS_16KHZ 3
#define DAC_FS_12KHZ 4
#define DAC_FS_8KHZ 5
#define DAC_FS_192KHZ 6
#define DAC_FS_96KHZ 7
#define DAC_FIFOC_FIFO_MODE_SHIFT 24
#define DAC_FIFOC_FIFO_MODE_MASK (3U << DAC_FIFOC_FIFO_MODE_SHIFT)
#define FIFO_MODE_24_31_8 0
#define FIFO_MODE_16_31_16 0
#define FIFO_MODE_16_15_0 1
#define DAC_FIFOC_DRQ_CLR_CNT_SHIFT 21
#define DAC_FIFOC_DRQ_CLR_CNT_MASK (3U << DAC_FIFOC_DRQ_CLR_CNT_SHIFT)
#define DAC_FIFOC_TX_TRIG_LEVEL_SHIFT 8
#define DAC_FIFOC_TX_TRIG_LEVEL_MASK (0x7f << DAC_FIFOC_TX_TRIG_LEVEL_SHIFT)
#define DAC_FIFOC_MONO_EN (1U << 6)
#define DAC_FIFOC_TX_BITS (1U << 5)
#define DAC_FIFOC_DRQ_EN (1U << 4)
#define DAC_FIFOC_FIFO_FLUSH (1U << 0)
#define AC_DAC_FIFOS 0x08
#define AC_DAC_TXDATA 0x0c
#define AC_DAC_ACTL 0x10
#define DAC_ACTL_DACAREN (1U << 31)
#define DAC_ACTL_DACALEN (1U << 30)
#define DAC_ACTL_MIXEN (1U << 29)
#define DAC_ACTL_DACPAS (1U << 8)
#define DAC_ACTL_PAMUTE (1U << 6)
#define DAC_ACTL_PAVOL_SHIFT 0
#define DAC_ACTL_PAVOL_MASK (0x3f << DAC_ACTL_PAVOL_SHIFT)
#define AC_ADC_FIFOC 0x1c
#define ADC_FIFOC_FS_SHIFT 29
#define ADC_FIFOC_FS_MASK (7U << ADC_FIFOC_FS_SHIFT)
#define ADC_FS_48KHZ 0
#define ADC_FIFOC_EN_AD (1U << 28)
#define ADC_FIFOC_RX_FIFO_MODE (1U << 24)
#define ADC_FIFOC_RX_TRIG_LEVEL_SHIFT 8
#define ADC_FIFOC_RX_TRIG_LEVEL_MASK (0x1f << ADC_FIFOC_RX_TRIG_LEVEL_SHIFT)
#define ADC_FIFOC_MONO_EN (1U << 7)
#define ADC_FIFOC_RX_BITS (1U << 6)
#define ADC_FIFOC_DRQ_EN (1U << 4)
#define ADC_FIFOC_FIFO_FLUSH (1U << 1)
#define AC_ADC_FIFOS 0x20
#define AC_ADC_RXDATA 0x24
#define AC_ADC_ACTL 0x28
#define ADC_ACTL_ADCREN (1U << 31)
#define ADC_ACTL_ADCLEN (1U << 30)
#define ADC_ACTL_PREG1EN (1U << 29)
#define ADC_ACTL_PREG2EN (1U << 28)
#define ADC_ACTL_VMICEN (1U << 27)
#define ADC_ACTL_ADCG_SHIFT 20
#define ADC_ACTL_ADCG_MASK (7U << ADC_ACTL_ADCG_SHIFT)
#define ADC_ACTL_ADCIS_SHIFT 17
#define ADC_ACTL_ADCIS_MASK (7U << ADC_ACTL_ADCIS_SHIFT)
#define ADC_IS_LINEIN 0
#define ADC_IS_FMIN 1
#define ADC_IS_MIC1 2
#define ADC_IS_MIC2 3
#define ADC_IS_MIC1_L_MIC2_R 4
#define ADC_IS_MIC1_LR_MIC2_LR 5
#define ADC_IS_OMIX 6
#define ADC_IS_LINEIN_L_MIC1_R 7
#define ADC_ACTL_LNRDF (1U << 16)
#define ADC_ACTL_LNPREG_SHIFT 13
#define ADC_ACTL_LNPREG_MASK (7U << ADC_ACTL_LNPREG_SHIFT)
#define ADC_ACTL_PA_EN (1U << 4)
#define ADC_ACTL_DDE (1U << 3)
#define AC_DAC_CNT 0x30
#define AC_ADC_CNT 0x34
static uint32_t a10codec_fmt[] = {
SND_FORMAT(AFMT_S16_LE, 1, 0),
SND_FORMAT(AFMT_S16_LE, 2, 0),
0
};
static struct pcmchan_caps a10codec_pcaps = { 8000, 192000, a10codec_fmt, 0 };
static struct pcmchan_caps a10codec_rcaps = { 8000, 48000, a10codec_fmt, 0 };
struct a10codec_info;
struct a10codec_chinfo {
struct snd_dbuf *buffer;
struct pcm_channel *channel;
struct a10codec_info *parent;
bus_dmamap_t dmamap;
void *dmaaddr;
bus_addr_t physaddr;
bus_size_t fifo;
device_t dmac;
void *dmachan;
int dir;
int run;
uint32_t pos;
uint32_t format;
uint32_t blocksize;
uint32_t speed;
};
struct a10codec_info {
device_t dev;
struct resource *res[2];
struct mtx *lock;
bus_dma_tag_t dmat;
unsigned dmasize;
void *ih;
unsigned drqtype_codec;
unsigned drqtype_sdram;
struct a10codec_chinfo play;
struct a10codec_chinfo rec;
};
static struct resource_spec a10codec_spec[] = {
{ SYS_RES_MEMORY, 0, RF_ACTIVE },
{ SYS_RES_IRQ, 0, RF_ACTIVE },
{ -1, 0 }
};
#define CODEC_READ(sc, reg) bus_read_4((sc)->res[0], (reg))
#define CODEC_WRITE(sc, reg, val) bus_write_4((sc)->res[0], (reg), (val))
/*
* Mixer interface
*/
static int
a10codec_mixer_init(struct snd_mixer *m)
{
struct a10codec_info *sc = mix_getdevinfo(m);
pcell_t prop[4];
phandle_t node;
device_t gpio;
uint32_t val;
ssize_t len;
int pin;
mix_setdevs(m, SOUND_MASK_VOLUME | SOUND_MASK_LINE | SOUND_MASK_RECLEV);
mix_setrecdevs(m, SOUND_MASK_LINE | SOUND_MASK_LINE1 | SOUND_MASK_MIC);
/* Unmute input source to PA */
val = CODEC_READ(sc, AC_DAC_ACTL);
val |= DAC_ACTL_PAMUTE;
CODEC_WRITE(sc, AC_DAC_ACTL, val);
/* Enable PA */
val = CODEC_READ(sc, AC_ADC_ACTL);
val |= ADC_ACTL_PA_EN;
CODEC_WRITE(sc, AC_ADC_ACTL, val);
/* Unmute PA */
node = ofw_bus_get_node(sc->dev);
len = OF_getencprop(node, "allwinner,pa-gpios", prop, sizeof(prop));
if (len > 0 && (len / sizeof(prop[0])) == 4) {
gpio = OF_device_from_xref(prop[0]);
if (gpio != NULL) {
pin = prop[1] * 32 + prop[2];
GPIO_PIN_SETFLAGS(gpio, pin, GPIO_PIN_OUTPUT);
GPIO_PIN_SET(gpio, pin, GPIO_PIN_LOW);
}
}
return (0);
}
static const struct a10codec_mixer {
unsigned reg;
unsigned mask;
unsigned shift;
} a10codec_mixers[SOUND_MIXER_NRDEVICES] = {
[SOUND_MIXER_VOLUME] = { AC_DAC_ACTL, DAC_ACTL_PAVOL_MASK,
DAC_ACTL_PAVOL_SHIFT },
[SOUND_MIXER_LINE] = { AC_ADC_ACTL, ADC_ACTL_LNPREG_MASK,
ADC_ACTL_LNPREG_SHIFT },
[SOUND_MIXER_RECLEV] = { AC_ADC_ACTL, ADC_ACTL_ADCG_MASK,
ADC_ACTL_ADCG_SHIFT },
};
static int
a10codec_mixer_set(struct snd_mixer *m, unsigned dev, unsigned left,
unsigned right)
{
struct a10codec_info *sc = mix_getdevinfo(m);
uint32_t val;
unsigned nvol, max;
max = a10codec_mixers[dev].mask >> a10codec_mixers[dev].shift;
nvol = (left * max) / 100;
val = CODEC_READ(sc, a10codec_mixers[dev].reg);
val &= ~a10codec_mixers[dev].mask;
val |= (nvol << a10codec_mixers[dev].shift);
CODEC_WRITE(sc, a10codec_mixers[dev].reg, val);
left = right = (left * 100) / max;
return (left | (right << 8));
}
static uint32_t
a10codec_mixer_setrecsrc(struct snd_mixer *m, uint32_t src)
{
struct a10codec_info *sc = mix_getdevinfo(m);
uint32_t val;
val = CODEC_READ(sc, AC_ADC_ACTL);
switch (src) {
case SOUND_MASK_LINE: /* line-in */
val &= ~ADC_ACTL_ADCIS_MASK;
val |= (ADC_IS_LINEIN << ADC_ACTL_ADCIS_SHIFT);
break;
case SOUND_MASK_MIC: /* MIC1 */
val &= ~ADC_ACTL_ADCIS_MASK;
val |= (ADC_IS_MIC1 << ADC_ACTL_ADCIS_SHIFT);
break;
case SOUND_MASK_LINE1: /* MIC2 */
val &= ~ADC_ACTL_ADCIS_MASK;
val |= (ADC_IS_MIC2 << ADC_ACTL_ADCIS_SHIFT);
break;
default:
break;
}
CODEC_WRITE(sc, AC_ADC_ACTL, val);
switch ((val & ADC_ACTL_ADCIS_MASK) >> ADC_ACTL_ADCIS_SHIFT) {
case ADC_IS_LINEIN:
return (SOUND_MASK_LINE);
case ADC_IS_MIC1:
return (SOUND_MASK_MIC);
case ADC_IS_MIC2:
return (SOUND_MASK_LINE1);
default:
return (0);
}
}
static kobj_method_t a10codec_mixer_methods[] = {
KOBJMETHOD(mixer_init, a10codec_mixer_init),
KOBJMETHOD(mixer_set, a10codec_mixer_set),
KOBJMETHOD(mixer_setrecsrc, a10codec_mixer_setrecsrc),
KOBJMETHOD_END
};
MIXER_DECLARE(a10codec_mixer);
/*
* Channel interface
*/
static void
a10codec_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
{
struct a10codec_chinfo *ch = arg;
if (error != 0)
return;
ch->physaddr = segs[0].ds_addr;
}
static void
a10codec_transfer(struct a10codec_chinfo *ch)
{
bus_addr_t src, dst;
int error;
if (ch->dir == PCMDIR_PLAY) {
src = ch->physaddr + ch->pos;
dst = ch->fifo;
} else {
src = ch->fifo;
dst = ch->physaddr + ch->pos;
}
error = SUNXI_DMA_TRANSFER(ch->dmac, ch->dmachan, src, dst,
ch->blocksize);
if (error) {
ch->run = 0;
device_printf(ch->parent->dev, "DMA transfer failed: %d\n",
error);
}
}
static void
a10codec_dmaconfig(struct a10codec_chinfo *ch)
{
struct a10codec_info *sc = ch->parent;
struct sunxi_dma_config conf;
memset(&conf, 0, sizeof(conf));
conf.src_width = conf.dst_width = 16;
conf.src_burst_len = conf.dst_burst_len = 4;
if (ch->dir == PCMDIR_PLAY) {
conf.dst_noincr = true;
conf.src_drqtype = sc->drqtype_sdram;
conf.dst_drqtype = sc->drqtype_codec;
} else {
conf.src_noincr = true;
conf.src_drqtype = sc->drqtype_codec;
conf.dst_drqtype = sc->drqtype_sdram;
}
SUNXI_DMA_SET_CONFIG(ch->dmac, ch->dmachan, &conf);
}
static void
a10codec_dmaintr(void *priv)
{
struct a10codec_chinfo *ch = priv;
unsigned bufsize;
bufsize = sndbuf_getsize(ch->buffer);
ch->pos += ch->blocksize;
if (ch->pos >= bufsize)
ch->pos -= bufsize;
if (ch->run) {
chn_intr(ch->channel);
a10codec_transfer(ch);
}
}
static unsigned
a10codec_fs(struct a10codec_chinfo *ch)
{
switch (ch->speed) {
case 48000:
return (DAC_FS_48KHZ);
case 24000:
return (DAC_FS_24KHZ);
case 12000:
return (DAC_FS_12KHZ);
case 192000:
return (DAC_FS_192KHZ);
case 32000:
return (DAC_FS_32KHZ);
case 16000:
return (DAC_FS_16KHZ);
case 8000:
return (DAC_FS_8KHZ);
case 96000:
return (DAC_FS_96KHZ);
default:
return (DAC_FS_48KHZ);
}
}
static void
a10codec_start(struct a10codec_chinfo *ch)
{
struct a10codec_info *sc = ch->parent;
uint32_t val;
ch->pos = 0;
if (ch->dir == PCMDIR_PLAY) {
/* Flush DAC FIFO */
CODEC_WRITE(sc, AC_DAC_FIFOC, DAC_FIFOC_FIFO_FLUSH);
/* Clear DAC FIFO status */
CODEC_WRITE(sc, AC_DAC_FIFOS, CODEC_READ(sc, AC_DAC_FIFOS));
/* Enable DAC analog left/right channels and output mixer */
val = CODEC_READ(sc, AC_DAC_ACTL);
val |= DAC_ACTL_DACAREN;
val |= DAC_ACTL_DACALEN;
val |= DAC_ACTL_DACPAS;
CODEC_WRITE(sc, AC_DAC_ACTL, val);
/* Configure DAC DMA channel */
a10codec_dmaconfig(ch);
/* Configure DAC FIFO */
CODEC_WRITE(sc, AC_DAC_FIFOC,
(AFMT_CHANNEL(ch->format) == 1 ? DAC_FIFOC_MONO_EN : 0) |
(a10codec_fs(ch) << DAC_FIFOC_FS_SHIFT) |
(FIFO_MODE_16_15_0 << DAC_FIFOC_FIFO_MODE_SHIFT) |
(DRQ_CLR_CNT << DAC_FIFOC_DRQ_CLR_CNT_SHIFT) |
(TX_TRIG_LEVEL << DAC_FIFOC_TX_TRIG_LEVEL_SHIFT));
/* Enable DAC DRQ */
val = CODEC_READ(sc, AC_DAC_FIFOC);
val |= DAC_FIFOC_DRQ_EN;
CODEC_WRITE(sc, AC_DAC_FIFOC, val);
} else {
/* Flush ADC FIFO */
CODEC_WRITE(sc, AC_ADC_FIFOC, ADC_FIFOC_FIFO_FLUSH);
/* Clear ADC FIFO status */
CODEC_WRITE(sc, AC_ADC_FIFOS, CODEC_READ(sc, AC_ADC_FIFOS));
/* Enable ADC analog left/right channels, MIC1 preamp,
* and VMIC pin voltage
*/
val = CODEC_READ(sc, AC_ADC_ACTL);
val |= ADC_ACTL_ADCREN;
val |= ADC_ACTL_ADCLEN;
val |= ADC_ACTL_PREG1EN;
val |= ADC_ACTL_VMICEN;
CODEC_WRITE(sc, AC_ADC_ACTL, val);
/* Configure ADC DMA channel */
a10codec_dmaconfig(ch);
/* Configure ADC FIFO */
CODEC_WRITE(sc, AC_ADC_FIFOC,
ADC_FIFOC_EN_AD |
ADC_FIFOC_RX_FIFO_MODE |
(AFMT_CHANNEL(ch->format) == 1 ? ADC_FIFOC_MONO_EN : 0) |
(a10codec_fs(ch) << ADC_FIFOC_FS_SHIFT) |
(RX_TRIG_LEVEL << ADC_FIFOC_RX_TRIG_LEVEL_SHIFT));
/* Enable ADC DRQ */
val = CODEC_READ(sc, AC_ADC_FIFOC);
val |= ADC_FIFOC_DRQ_EN;
CODEC_WRITE(sc, AC_ADC_FIFOC, val);
}
/* Start DMA transfer */
a10codec_transfer(ch);
}
static void
a10codec_stop(struct a10codec_chinfo *ch)
{
struct a10codec_info *sc = ch->parent;
uint32_t val;
/* Disable DMA channel */
SUNXI_DMA_HALT(ch->dmac, ch->dmachan);
if (ch->dir == PCMDIR_PLAY) {
/* Disable DAC analog left/right channels and output mixer */
val = CODEC_READ(sc, AC_DAC_ACTL);
val &= ~DAC_ACTL_DACAREN;
val &= ~DAC_ACTL_DACALEN;
val &= ~DAC_ACTL_DACPAS;
CODEC_WRITE(sc, AC_DAC_ACTL, val);
/* Disable DAC DRQ */
CODEC_WRITE(sc, AC_DAC_FIFOC, 0);
} else {
/* Disable ADC analog left/right channels, MIC1 preamp,
* and VMIC pin voltage
*/
val = CODEC_READ(sc, AC_ADC_ACTL);
val &= ~ADC_ACTL_ADCREN;
val &= ~ADC_ACTL_ADCLEN;
val &= ~ADC_ACTL_PREG1EN;
val &= ~ADC_ACTL_VMICEN;
CODEC_WRITE(sc, AC_ADC_ACTL, val);
/* Disable ADC DRQ */
CODEC_WRITE(sc, AC_ADC_FIFOC, 0);
}
}
static void *
a10codec_chan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b,
struct pcm_channel *c, int dir)
{
struct a10codec_info *sc = devinfo;
struct a10codec_chinfo *ch = dir == PCMDIR_PLAY ? &sc->play : &sc->rec;
int error;
ch->parent = sc;
ch->channel = c;
ch->buffer = b;
ch->dir = dir;
ch->fifo = rman_get_start(sc->res[0]) +
(dir == PCMDIR_REC ? AC_ADC_RXDATA : AC_DAC_TXDATA);
ch->dmac = devclass_get_device(devclass_find("a10dmac"), 0);
if (ch->dmac == NULL) {
device_printf(sc->dev, "cannot find DMA controller\n");
return (NULL);
}
ch->dmachan = SUNXI_DMA_ALLOC(ch->dmac, false, a10codec_dmaintr, ch);
if (ch->dmachan == NULL) {
device_printf(sc->dev, "cannot allocate DMA channel\n");
return (NULL);
}
error = bus_dmamem_alloc(sc->dmat, &ch->dmaaddr,
BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &ch->dmamap);
if (error != 0) {
device_printf(sc->dev, "cannot allocate channel buffer\n");
return (NULL);
}
error = bus_dmamap_load(sc->dmat, ch->dmamap, ch->dmaaddr,
sc->dmasize, a10codec_dmamap_cb, ch, BUS_DMA_NOWAIT);
if (error != 0) {
device_printf(sc->dev, "cannot load DMA map\n");
return (NULL);
}
memset(ch->dmaaddr, 0, sc->dmasize);
if (sndbuf_setup(ch->buffer, ch->dmaaddr, sc->dmasize) != 0) {
device_printf(sc->dev, "cannot setup sndbuf\n");
return (NULL);
}
return (ch);
}
static int
a10codec_chan_free(kobj_t obj, void *data)
{
struct a10codec_chinfo *ch = data;
struct a10codec_info *sc = ch->parent;
SUNXI_DMA_FREE(ch->dmac, ch->dmachan);
bus_dmamap_unload(sc->dmat, ch->dmamap);
bus_dmamem_free(sc->dmat, ch->dmaaddr, ch->dmamap);
return (0);
}
static int
a10codec_chan_setformat(kobj_t obj, void *data, uint32_t format)
{
struct a10codec_chinfo *ch = data;
ch->format = format;
return (0);
}
static uint32_t
a10codec_chan_setspeed(kobj_t obj, void *data, uint32_t speed)
{
struct a10codec_chinfo *ch = data;
/*
* The codec supports full duplex operation but both DAC and ADC
* use the same source clock (PLL2). Limit the available speeds to
* those supported by a 24576000 Hz input.
*/
switch (speed) {
case 8000:
case 12000:
case 16000:
case 24000:
case 32000:
case 48000:
ch->speed = speed;
break;
case 96000:
case 192000:
/* 96 KHz / 192 KHz mode only supported for playback */
if (ch->dir == PCMDIR_PLAY) {
ch->speed = speed;
} else {
ch->speed = 48000;
}
break;
case 44100:
ch->speed = 48000;
break;
case 22050:
ch->speed = 24000;
break;
case 11025:
ch->speed = 12000;
break;
default:
ch->speed = 48000;
break;
}
return (ch->speed);
}
static uint32_t
a10codec_chan_setblocksize(kobj_t obj, void *data, uint32_t blocksize)
{
struct a10codec_chinfo *ch = data;
ch->blocksize = blocksize & ~3;
return (ch->blocksize);
}
static int
a10codec_chan_trigger(kobj_t obj, void *data, int go)
{
struct a10codec_chinfo *ch = data;
struct a10codec_info *sc = ch->parent;
if (!PCMTRIG_COMMON(go))
return (0);
snd_mtxlock(sc->lock);
switch (go) {
case PCMTRIG_START:
ch->run = 1;
a10codec_start(ch);
break;
case PCMTRIG_STOP:
case PCMTRIG_ABORT:
ch->run = 0;
a10codec_stop(ch);
break;
default:
break;
}
snd_mtxunlock(sc->lock);
return (0);
}
static uint32_t
a10codec_chan_getptr(kobj_t obj, void *data)
{
struct a10codec_chinfo *ch = data;
return (ch->pos);
}
static struct pcmchan_caps *
a10codec_chan_getcaps(kobj_t obj, void *data)
{
struct a10codec_chinfo *ch = data;
if (ch->dir == PCMDIR_PLAY) {
return (&a10codec_pcaps);
} else {
return (&a10codec_rcaps);
}
}
static kobj_method_t a10codec_chan_methods[] = {
KOBJMETHOD(channel_init, a10codec_chan_init),
KOBJMETHOD(channel_free, a10codec_chan_free),
KOBJMETHOD(channel_setformat, a10codec_chan_setformat),
KOBJMETHOD(channel_setspeed, a10codec_chan_setspeed),
KOBJMETHOD(channel_setblocksize, a10codec_chan_setblocksize),
KOBJMETHOD(channel_trigger, a10codec_chan_trigger),
KOBJMETHOD(channel_getptr, a10codec_chan_getptr),
KOBJMETHOD(channel_getcaps, a10codec_chan_getcaps),
KOBJMETHOD_END
};
CHANNEL_DECLARE(a10codec_chan);
/*
* Device interface
*/
static int
a10codec_probe(device_t dev)
{
if (!ofw_bus_status_okay(dev))
return (ENXIO);
if (!ofw_bus_is_compatible(dev, "allwinner,sun7i-a20-codec"))
return (ENXIO);
device_set_desc(dev, "Allwinner Audio Codec");
return (BUS_PROBE_DEFAULT);
}
static int
a10codec_attach(device_t dev)
{
struct a10codec_info *sc;
char status[SND_STATUSLEN];
uint32_t val;
int error;
sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);
sc->dev = dev;
sc->lock = snd_mtxcreate(device_get_nameunit(dev), "a10codec softc");
if (bus_alloc_resources(dev, a10codec_spec, sc->res)) {
device_printf(dev, "cannot allocate resources for device\n");
error = ENXIO;
goto fail;
}
/* XXX DRQ types should come from FDT, but how? */
if (ofw_bus_is_compatible(dev, "allwinner,sun4i-a10-codec") ||
ofw_bus_is_compatible(dev, "allwinner,sun7i-a20-codec")) {
sc->drqtype_codec = 19;
sc->drqtype_sdram = 22;
} else {
device_printf(dev, "DRQ types not known for this SoC\n");
error = ENXIO;
goto fail;
}
sc->dmasize = 131072;
error = bus_dma_tag_create(
bus_get_dma_tag(dev),
4, sc->dmasize, /* alignment, boundary */
BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
BUS_SPACE_MAXADDR, /* highaddr */
NULL, NULL, /* filter, filterarg */
sc->dmasize, 1, /* maxsize, nsegs */
sc->dmasize, 0, /* maxsegsize, flags */
NULL, NULL, /* lockfunc, lockarg */
&sc->dmat);
if (error != 0) {
device_printf(dev, "cannot create DMA tag\n");
goto fail;
}
/* Activate audio codec clock. According to the A10 and A20 user
* manuals, Audio_pll can be either 24.576MHz or 22.5792MHz. Most
* audio sampling rates require an 24.576MHz input clock with the
* exception of 44.1kHz, 22.05kHz, and 11.025kHz. Unfortunately,
* both capture and playback use the same clock source so to
* safely support independent full duplex operation, we use a fixed
* 24.576MHz clock source and don't advertise native support for
* the three sampling rates that require a 22.5792MHz input.
*/
a10_clk_codec_activate(24576000);
/* Enable DAC */
val = CODEC_READ(sc, AC_DAC_DPC);
val |= DAC_DPC_EN_DA;
CODEC_WRITE(sc, AC_DAC_DPC, val);
#ifdef notdef
error = snd_setup_intr(dev, sc->irq, INTR_MPSAFE, a10codec_intr, sc,
&sc->ih);
if (error != 0) {
device_printf(dev, "could not setup interrupt handler\n");
goto fail;
}
#endif
if (mixer_init(dev, &a10codec_mixer_class, sc)) {
device_printf(dev, "mixer_init failed\n");
goto fail;
}
pcm_setflags(dev, pcm_getflags(dev) | SD_F_MPSAFE);
if (pcm_register(dev, sc, 1, 1)) {
device_printf(dev, "pcm_register failed\n");
goto fail;
}
pcm_addchan(dev, PCMDIR_PLAY, &a10codec_chan_class, sc);
pcm_addchan(dev, PCMDIR_REC, &a10codec_chan_class, sc);
snprintf(status, SND_STATUSLEN, "at %s", ofw_bus_get_name(dev));
pcm_setstatus(dev, status);
return (0);
fail:
bus_release_resources(dev, a10codec_spec, sc->res);
snd_mtxfree(sc->lock);
free(sc, M_DEVBUF);
return (error);
}
static device_method_t a10codec_pcm_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, a10codec_probe),
DEVMETHOD(device_attach, a10codec_attach),
DEVMETHOD_END
};
static driver_t a10codec_pcm_driver = {
"pcm",
a10codec_pcm_methods,
PCM_SOFTC_SIZE,
};
DRIVER_MODULE(a10codec, simplebus, a10codec_pcm_driver, pcm_devclass, 0, 0);
MODULE_DEPEND(a10codec, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
MODULE_VERSION(a10codec, 1);

View File

@ -0,0 +1,453 @@
/*-
* Copyright (c) 2014-2016 Jared D. McNeill <jmcneill@invisible.ca>
* 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.
*
*/
/*
* Allwinner A10/A20 DMA controller
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/rman.h>
#include <sys/condvar.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <machine/bus.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#include <arm/allwinner/a10_dmac.h>
#include <arm/allwinner/a10_clk.h>
#include "sunxi_dma_if.h"
#define NDMA_CHANNELS 8
#define DDMA_CHANNELS 8
enum a10dmac_type {
CH_NDMA,
CH_DDMA
};
struct a10dmac_softc;
struct a10dmac_channel {
struct a10dmac_softc * ch_sc;
uint8_t ch_index;
enum a10dmac_type ch_type;
void (*ch_callback)(void *);
void * ch_callbackarg;
uint32_t ch_regoff;
};
struct a10dmac_softc {
struct resource * sc_res[2];
struct mtx sc_mtx;
void * sc_ih;
struct a10dmac_channel sc_ndma_channels[NDMA_CHANNELS];
struct a10dmac_channel sc_ddma_channels[DDMA_CHANNELS];
};
static struct resource_spec a10dmac_spec[] = {
{ SYS_RES_MEMORY, 0, RF_ACTIVE },
{ SYS_RES_IRQ, 0, RF_ACTIVE },
{ -1, 0 }
};
#define DMA_READ(sc, reg) bus_read_4((sc)->sc_res[0], (reg))
#define DMA_WRITE(sc, reg, val) bus_write_4((sc)->sc_res[0], (reg), (val))
#define DMACH_READ(ch, reg) \
DMA_READ((ch)->ch_sc, (reg) + (ch)->ch_regoff)
#define DMACH_WRITE(ch, reg, val) \
DMA_WRITE((ch)->ch_sc, (reg) + (ch)->ch_regoff, (val))
static void a10dmac_intr(void *);
static int
a10dmac_probe(device_t dev)
{
if (!ofw_bus_status_okay(dev))
return (ENXIO);
if (!ofw_bus_is_compatible(dev, "allwinner,sun4i-a10-dma"))
return (ENXIO);
device_set_desc(dev, "Allwinner DMA controller");
return (BUS_PROBE_DEFAULT);
}
static int
a10dmac_attach(device_t dev)
{
struct a10dmac_softc *sc;
unsigned int index;
int error;
sc = device_get_softc(dev);
if (bus_alloc_resources(dev, a10dmac_spec, sc->sc_res)) {
device_printf(dev, "cannot allocate resources for device\n");
return (ENXIO);
}
mtx_init(&sc->sc_mtx, "a10 dmac", NULL, MTX_SPIN);
/* Activate DMA controller clock */
a10_clk_dmac_activate();
/* Disable all interrupts and clear pending status */
DMA_WRITE(sc, AWIN_DMA_IRQ_EN_REG, 0);
DMA_WRITE(sc, AWIN_DMA_IRQ_PEND_STA_REG, ~0);
/* Initialize channels */
for (index = 0; index < NDMA_CHANNELS; index++) {
sc->sc_ndma_channels[index].ch_sc = sc;
sc->sc_ndma_channels[index].ch_index = index;
sc->sc_ndma_channels[index].ch_type = CH_NDMA;
sc->sc_ndma_channels[index].ch_callback = NULL;
sc->sc_ndma_channels[index].ch_callbackarg = NULL;
sc->sc_ndma_channels[index].ch_regoff = AWIN_NDMA_REG(index);
DMACH_WRITE(&sc->sc_ndma_channels[index], AWIN_NDMA_CTL_REG, 0);
}
for (index = 0; index < DDMA_CHANNELS; index++) {
sc->sc_ddma_channels[index].ch_sc = sc;
sc->sc_ddma_channels[index].ch_index = index;
sc->sc_ddma_channels[index].ch_type = CH_DDMA;
sc->sc_ddma_channels[index].ch_callback = NULL;
sc->sc_ddma_channels[index].ch_callbackarg = NULL;
sc->sc_ddma_channels[index].ch_regoff = AWIN_DDMA_REG(index);
DMACH_WRITE(&sc->sc_ddma_channels[index], AWIN_DDMA_CTL_REG, 0);
}
error = bus_setup_intr(dev, sc->sc_res[1], INTR_MPSAFE | INTR_TYPE_MISC,
NULL, a10dmac_intr, sc, &sc->sc_ih);
if (error != 0) {
device_printf(dev, "could not setup interrupt handler\n");
bus_release_resources(dev, a10dmac_spec, sc->sc_res);
mtx_destroy(&sc->sc_mtx);
return (ENXIO);
}
return (0);
}
static void
a10dmac_intr(void *priv)
{
struct a10dmac_softc *sc = priv;
uint32_t sta, bit, mask;
uint8_t index;
sta = DMA_READ(sc, AWIN_DMA_IRQ_PEND_STA_REG);
DMA_WRITE(sc, AWIN_DMA_IRQ_PEND_STA_REG, sta);
while ((bit = ffs(sta & AWIN_DMA_IRQ_END_MASK)) != 0) {
mask = (1U << (bit - 1));
sta &= ~mask;
/*
* Map status bit to channel number. The status register is
* encoded with two bits of status per channel (lowest bit
* is half transfer pending, highest bit is end transfer
* pending). The 8 normal DMA channel status are in the lower
* 16 bits and the 8 dedicated DMA channel status are in
* the upper 16 bits. The output is a channel number from 0-7.
*/
index = ((bit - 1) / 2) & 7;
if (mask & AWIN_DMA_IRQ_NDMA) {
if (sc->sc_ndma_channels[index].ch_callback == NULL)
continue;
sc->sc_ndma_channels[index].ch_callback(
sc->sc_ndma_channels[index].ch_callbackarg);
} else {
if (sc->sc_ddma_channels[index].ch_callback == NULL)
continue;
sc->sc_ddma_channels[index].ch_callback(
sc->sc_ddma_channels[index].ch_callbackarg);
}
}
}
static uint32_t
a10dmac_read_ctl(struct a10dmac_channel *ch)
{
if (ch->ch_type == CH_NDMA) {
return (DMACH_READ(ch, AWIN_NDMA_CTL_REG));
} else {
return (DMACH_READ(ch, AWIN_DDMA_CTL_REG));
}
}
static void
a10dmac_write_ctl(struct a10dmac_channel *ch, uint32_t val)
{
if (ch->ch_type == CH_NDMA) {
DMACH_WRITE(ch, AWIN_NDMA_CTL_REG, val);
} else {
DMACH_WRITE(ch, AWIN_DDMA_CTL_REG, val);
}
}
static int
a10dmac_set_config(device_t dev, void *priv, const struct sunxi_dma_config *cfg)
{
struct a10dmac_channel *ch = priv;
uint32_t val;
unsigned int dst_dw, dst_bl, dst_bs, dst_wc;
unsigned int src_dw, src_bl, src_bs, src_wc;
switch (cfg->dst_width) {
case 8:
dst_dw = AWIN_DMA_CTL_DATA_WIDTH_8;
break;
case 16:
dst_dw = AWIN_DMA_CTL_DATA_WIDTH_16;
break;
case 32:
dst_dw = AWIN_DMA_CTL_DATA_WIDTH_32;
break;
default:
return (EINVAL);
}
switch (cfg->dst_burst_len) {
case 1:
dst_bl = AWIN_DMA_CTL_BURST_LEN_1;
break;
case 4:
dst_bl = AWIN_DMA_CTL_BURST_LEN_4;
break;
case 8:
dst_bl = AWIN_DMA_CTL_BURST_LEN_8;
break;
default:
return (EINVAL);
}
switch (cfg->src_width) {
case 8:
src_dw = AWIN_DMA_CTL_DATA_WIDTH_8;
break;
case 16:
src_dw = AWIN_DMA_CTL_DATA_WIDTH_16;
break;
case 32:
src_dw = AWIN_DMA_CTL_DATA_WIDTH_32;
break;
default:
return (EINVAL);
}
switch (cfg->src_burst_len) {
case 1:
src_bl = AWIN_DMA_CTL_BURST_LEN_1;
break;
case 4:
src_bl = AWIN_DMA_CTL_BURST_LEN_4;
break;
case 8:
src_bl = AWIN_DMA_CTL_BURST_LEN_8;
break;
default:
return (EINVAL);
}
val = (dst_dw << AWIN_DMA_CTL_DST_DATA_WIDTH_SHIFT) |
(dst_bl << AWIN_DMA_CTL_DST_BURST_LEN_SHIFT) |
(cfg->dst_drqtype << AWIN_DMA_CTL_DST_DRQ_TYPE_SHIFT) |
(src_dw << AWIN_DMA_CTL_SRC_DATA_WIDTH_SHIFT) |
(src_bl << AWIN_DMA_CTL_SRC_BURST_LEN_SHIFT) |
(cfg->src_drqtype << AWIN_DMA_CTL_SRC_DRQ_TYPE_SHIFT);
if (cfg->dst_noincr) {
val |= AWIN_NDMA_CTL_DST_ADDR_NOINCR;
}
if (cfg->src_noincr) {
val |= AWIN_NDMA_CTL_SRC_ADDR_NOINCR;
}
if (ch->ch_type == CH_NDMA) {
DMACH_WRITE(ch, AWIN_NDMA_CTL_REG, val);
} else {
DMACH_WRITE(ch, AWIN_DDMA_CTL_REG, val);
dst_bs = cfg->dst_blksize - 1;
dst_wc = cfg->dst_wait_cyc - 1;
src_bs = cfg->src_blksize - 1;
src_wc = cfg->src_wait_cyc - 1;
DMACH_WRITE(ch, AWIN_DDMA_PARA_REG,
(dst_bs << AWIN_DDMA_PARA_DST_DATA_BLK_SIZ_SHIFT) |
(dst_wc << AWIN_DDMA_PARA_DST_WAIT_CYC_SHIFT) |
(src_bs << AWIN_DDMA_PARA_SRC_DATA_BLK_SIZ_SHIFT) |
(src_wc << AWIN_DDMA_PARA_SRC_WAIT_CYC_SHIFT));
}
return (0);
}
static void *
a10dmac_alloc(device_t dev, bool dedicated, void (*cb)(void *), void *cbarg)
{
struct a10dmac_softc *sc = device_get_softc(dev);
struct a10dmac_channel *ch_list;
struct a10dmac_channel *ch = NULL;
uint32_t irqen;
uint8_t ch_count, index;
if (dedicated) {
ch_list = sc->sc_ddma_channels;
ch_count = DDMA_CHANNELS;
} else {
ch_list = sc->sc_ndma_channels;
ch_count = NDMA_CHANNELS;
}
mtx_lock_spin(&sc->sc_mtx);
for (index = 0; index < ch_count; index++) {
if (ch_list[index].ch_callback == NULL) {
ch = &ch_list[index];
ch->ch_callback = cb;
ch->ch_callbackarg = cbarg;
irqen = DMA_READ(sc, AWIN_DMA_IRQ_EN_REG);
if (ch->ch_type == CH_NDMA)
irqen |= AWIN_DMA_IRQ_NDMA_END(index);
else
irqen |= AWIN_DMA_IRQ_DDMA_END(index);
DMA_WRITE(sc, AWIN_DMA_IRQ_EN_REG, irqen);
break;
}
}
mtx_unlock_spin(&sc->sc_mtx);
return (ch);
}
static void
a10dmac_free(device_t dev, void *priv)
{
struct a10dmac_channel *ch = priv;
struct a10dmac_softc *sc = ch->ch_sc;
uint32_t irqen, sta, cfg;
mtx_lock_spin(&sc->sc_mtx);
irqen = DMA_READ(sc, AWIN_DMA_IRQ_EN_REG);
cfg = a10dmac_read_ctl(ch);
if (ch->ch_type == CH_NDMA) {
sta = AWIN_DMA_IRQ_NDMA_END(ch->ch_index);
cfg &= ~AWIN_NDMA_CTL_DMA_LOADING;
} else {
sta = AWIN_DMA_IRQ_DDMA_END(ch->ch_index);
cfg &= ~AWIN_DDMA_CTL_DMA_LOADING;
}
irqen &= ~sta;
a10dmac_write_ctl(ch, cfg);
DMA_WRITE(sc, AWIN_DMA_IRQ_EN_REG, irqen);
DMA_WRITE(sc, AWIN_DMA_IRQ_PEND_STA_REG, sta);
ch->ch_callback = NULL;
ch->ch_callbackarg = NULL;
mtx_unlock_spin(&sc->sc_mtx);
}
static int
a10dmac_transfer(device_t dev, void *priv, bus_addr_t src, bus_addr_t dst,
size_t nbytes)
{
struct a10dmac_channel *ch = priv;
uint32_t cfg;
cfg = a10dmac_read_ctl(ch);
if (ch->ch_type == CH_NDMA) {
if (cfg & AWIN_NDMA_CTL_DMA_LOADING)
return (EBUSY);
DMACH_WRITE(ch, AWIN_NDMA_SRC_ADDR_REG, src);
DMACH_WRITE(ch, AWIN_NDMA_DEST_ADDR_REG, dst);
DMACH_WRITE(ch, AWIN_NDMA_BC_REG, nbytes);
cfg |= AWIN_NDMA_CTL_DMA_LOADING;
a10dmac_write_ctl(ch, cfg);
} else {
if (cfg & AWIN_DDMA_CTL_DMA_LOADING)
return (EBUSY);
DMACH_WRITE(ch, AWIN_DDMA_SRC_START_ADDR_REG, src);
DMACH_WRITE(ch, AWIN_DDMA_DEST_START_ADDR_REG, dst);
DMACH_WRITE(ch, AWIN_DDMA_BC_REG, nbytes);
cfg |= AWIN_DDMA_CTL_DMA_LOADING;
a10dmac_write_ctl(ch, cfg);
}
return (0);
}
static void
a10dmac_halt(device_t dev, void *priv)
{
struct a10dmac_channel *ch = priv;
uint32_t cfg;
cfg = a10dmac_read_ctl(ch);
if (ch->ch_type == CH_NDMA) {
cfg &= ~AWIN_NDMA_CTL_DMA_LOADING;
} else {
cfg &= ~AWIN_DDMA_CTL_DMA_LOADING;
}
a10dmac_write_ctl(ch, cfg);
}
static device_method_t a10dmac_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, a10dmac_probe),
DEVMETHOD(device_attach, a10dmac_attach),
/* sunxi DMA interface */
DEVMETHOD(sunxi_dma_alloc, a10dmac_alloc),
DEVMETHOD(sunxi_dma_free, a10dmac_free),
DEVMETHOD(sunxi_dma_set_config, a10dmac_set_config),
DEVMETHOD(sunxi_dma_transfer, a10dmac_transfer),
DEVMETHOD(sunxi_dma_halt, a10dmac_halt),
DEVMETHOD_END
};
static driver_t a10dmac_driver = {
"a10dmac",
a10dmac_methods,
sizeof(struct a10dmac_softc)
};
static devclass_t a10dmac_devclass;
DRIVER_MODULE(a10dmac, simplebus, a10dmac_driver, a10dmac_devclass, 0, 0);

View File

@ -0,0 +1,158 @@
/*-
* Copyright (c) 2014-2016 Jared D. McNeill <jmcneill@invisible.ca>
* 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 _A10_DMAC_H_
#define _A10_DMAC_H_
#define AWIN_DMA_IRQ_EN_REG 0x0000
#define AWIN_DMA_IRQ_PEND_STA_REG 0x0004
#define AWIN_NDMA_AUTO_GATE_REG 0x0008
#define AWIN_NDMA_REG(n) (0x100+0x20*(n))
#define AWIN_NDMA_CTL_REG 0x0000
#define AWIN_NDMA_SRC_ADDR_REG 0x0004
#define AWIN_NDMA_DEST_ADDR_REG 0x0008
#define AWIN_NDMA_BC_REG 0x000c
#define AWIN_DDMA_REG(n) (0x300+0x20*(n))
#define AWIN_DDMA_CTL_REG 0x0000
#define AWIN_DDMA_SRC_START_ADDR_REG 0x0004
#define AWIN_DDMA_DEST_START_ADDR_REG 0x0008
#define AWIN_DDMA_BC_REG 0x000c
#define AWIN_DDMA_PARA_REG 0x0018
#define AWIN_DMA_IRQ_END_MASK 0xaaaaaaaa
#define AWIN_DMA_IRQ_HF_MASK 0x55555555
#define AWIN_DMA_IRQ_DDMA 0xffff0000
#define AWIN_DMA_IRQ_DDMA_END(n) (1U << (17+2*(n)))
#define AWIN_DMA_IRQ_DDMA_HF(n) (1U << (16+2*(n)))
#define AWIN_DMA_IRQ_NDMA 0x0000ffff
#define AWIN_DMA_IRQ_NDMA_END(n) (1U << (1+2*(n)))
#define AWIN_DMA_IRQ_NDMA_HF(n) (1U << (0+2*(n)))
#define AWIN_NDMA_AUTO_GATING_DIS (1U << 16)
#define AWIN_DMA_CTL_DST_DATA_WIDTH_SHIFT 25
#define AWIN_DMA_CTL_DST_DATA_WIDTH_MASK (3U << AWIN_DMA_CTL_DST_DATA_WIDTH_SHIFT)
#define AWIN_DMA_CTL_DATA_WIDTH_8 0
#define AWIN_DMA_CTL_DATA_WIDTH_16 1
#define AWIN_DMA_CTL_DATA_WIDTH_32 2
#define AWIN_DMA_CTL_DST_BURST_LEN_SHIFT 23
#define AWIN_DMA_CTL_DST_BURST_LEN_MASK (3 << AWIN_DMA_CTL_DST_BURST_LEN_SHIFT)
#define AWIN_DMA_CTL_BURST_LEN_1 0
#define AWIN_DMA_CTL_BURST_LEN_4 1
#define AWIN_DMA_CTL_BURST_LEN_8 2
#define AWIN_DMA_CTL_DST_DRQ_TYPE_SHIFT 16
#define AWIN_DMA_CTL_DST_DRQ_TYPE_MASK (0x1f << AWIN_DMA_CTL_DST_DRQ_TYPE_SHIFT)
#define AWIN_DMA_CTL_BC_REMAINING (1U << 15)
#define AWIN_DMA_CTL_SRC_DATA_WIDTH_SHIFT 9
#define AWIN_DMA_CTL_SRC_DATA_WIDTH_MASK (3U << AWIN_DMA_CTL_SRC_DATA_WIDTH_SHIFT)
#define AWIN_DMA_CTL_SRC_BURST_LEN_SHIFT 7
#define AWIN_DMA_CTL_SRC_BURST_LEN_MASK (3U << AWIN_DMA_CTL_SRC_BURST_LEN_SHIFT)
#define AWIN_DMA_CTL_SRC_DRQ_TYPE_SHIFT 0
#define AWIN_DMA_CTL_SRC_DRQ_TYPE_MASK (0x1f << AWIN_DMA_CTL_SRC_DRQ_TYPE_SHIFT)
#define AWIN_NDMA_CTL_DMA_LOADING (1U << 31)
#define AWIN_NDMA_CTL_DMA_CONTIN_MODE (1U << 30)
#define AWIN_NDMA_CTL_WAIT_STATE_LOG2_SHIFT 27
#define AWIN_NDMA_CTL_WAIT_STATE_LOG2_MASK (7U << AWIN_NDMA_CTL_WAIT_STATE_LOG2_SHIFT)
#define AWIN_NDMA_CTL_DST_NON_SECURE (1U << 22)
#define AWIN_NDMA_CTL_DST_ADDR_NOINCR (1U << 21)
#define AWIN_NDMA_CTL_DRQ_IRO 0
#define AWIN_NDMA_CTL_DRQ_IR1 1
#define AWIN_NDMA_CTL_DRQ_SPDIF 2
#define AWIN_NDMA_CTL_DRQ_IISO 3
#define AWIN_NDMA_CTL_DRQ_IIS1 4
#define AWIN_NDMA_CTL_DRQ_AC97 5
#define AWIN_NDMA_CTL_DRQ_IIS2 6
#define AWIN_NDMA_CTL_DRQ_UARTO 8
#define AWIN_NDMA_CTL_DRQ_UART1 9
#define AWIN_NDMA_CTL_DRQ_UART2 10
#define AWIN_NDMA_CTL_DRQ_UART3 11
#define AWIN_NDMA_CTL_DRQ_UART4 12
#define AWIN_NDMA_CTL_DRQ_UART5 13
#define AWIN_NDMA_CTL_DRQ_UART6 14
#define AWIN_NDMA_CTL_DRQ_UART7 15
#define AWIN_NDMA_CTL_DRQ_DDC 16
#define AWIN_NDMA_CTL_DRQ_USB_EP1 17
#define AWIN_NDMA_CTL_DRQ_CODEC 19
#define AWIN_NDMA_CTL_DRQ_SRAM 21
#define AWIN_NDMA_CTL_DRQ_SDRAM 22
#define AWIN_NDMA_CTL_DRQ_TP_AD 23
#define AWIN_NDMA_CTL_DRQ_SPI0 24
#define AWIN_NDMA_CTL_DRQ_SPI1 25
#define AWIN_NDMA_CTL_DRQ_SPI2 26
#define AWIN_NDMA_CTL_DRQ_SPI3 27
#define AWIN_NDMA_CTL_DRQ_USB_EP2 28
#define AWIN_NDMA_CTL_DRQ_USB_EP3 29
#define AWIN_NDMA_CTL_DRQ_USB_EP4 30
#define AWIN_NDMA_CTL_DRQ_USB_EP5 31
#define AWIN_NDMA_CTL_SRC_NON_SECURE (1U << 6)
#define AWIN_NDMA_CTL_SRC_ADDR_NOINCR (1U << 5)
#define AWIN_NDMA_BC_COUNT 0x0003ffff
#define AWIN_DDMA_CTL_DMA_LOADING (1U << 31)
#define AWIN_DDMA_CTL_BUSY (1U << 30)
#define AWIN_DDMA_CTL_DMA_CONTIN_MODE (1U << 29)
#define AWIN_DDMA_CTL_DST_NON_SECURE (1U << 28)
#define AWIN_DDMA_CTL_DST_ADDR_MODE_SHIFT 21
#define AWIN_DDMA_CTL_DST_ADDR_MODE_MASK (3U << AWIN_DDMA_CTL_DST_ADDR_MODE_SHIFT)
#define AWIN_DDMA_CTL_DMA_ADDR_LINEAR 0
#define AWIN_DDMA_CTL_DMA_ADDR_IO 1
#define AWIN_DDMA_CTL_DMA_ADDR_HPAGE 2
#define AWIN_DDMA_CTL_DMA_ADDR_VPAGE 3
#define AWIN_DDMA_CTL_DST_DRQ_TYPE_SHIFT 16
#define AWIN_DDMA_CTL_DST_DRQ_TYPE_MASK (0x1f << AWIN_DDMA_CTL_DST_DRQ_TYPE_SHIFT)
#define AWIN_DDMA_CTL_DRQ_SRAM 0
#define AWIN_DDMA_CTL_DRQ_SDRAM 1
#define AWIN_DDMA_CTL_DRQ_NFC 3
#define AWIN_DDMA_CTL_DRQ_USB0 4
#define AWIN_DDMA_CTL_DRQ_EMAC_TX 6
#define AWIN_DDMA_CTL_DRQ_EMAC_RX 7
#define AWIN_DDMA_CTL_DRQ_SPI1_TX 8
#define AWIN_DDMA_CTL_DRQ_SPI1_RX 9
#define AWIN_DDMA_CTL_DRQ_SS_TX 10
#define AWIN_DDMA_CTL_DRQ_SS_RX 11
#define AWIN_DDMA_CTL_DRQ_TCON0 14
#define AWIN_DDMA_CTL_DRQ_TCON1 15
#define AWIN_DDMA_CTL_DRQ_MS_TX 23
#define AWIN_DDMA_CTL_DRQ_MS_RX 23
#define AWIN_DDMA_CTL_DRQ_HDMI_AUDIO 24
#define AWIN_DDMA_CTL_DRQ_SPI0_TX 26
#define AWIN_DDMA_CTL_DRQ_SPI0_RX 27
#define AWIN_DDMA_CTL_DRQ_SPI2_TX 28
#define AWIN_DDMA_CTL_DRQ_SPI2_RX 29
#define AWIN_DDMA_CTL_DRQ_SPI3_TX 30
#define AWIN_DDMA_CTL_DRQ_SPI3_RX 31
#define AWIN_DDMA_CTL_SRC_NON_SECURE (1U << 12)
#define AWIN_DDMA_CTL_SRC_ADDR_MODE_SHIFT 5
#define AWIN_DDMA_CTL_SRC_ADDR_MODE_MASK (3U << AWIN_DDMA_CTL_SRC_ADDR_MODE_SHIFT)
#define AWIN_DDMA_BC_COUNT 0x00003fff
#define AWIN_DDMA_PARA_DST_DATA_BLK_SIZ_SHIFT 24
#define AWIN_DDMA_PARA_DST_DATA_BLK_SIZ_MASK (0xff << AWIN_DDMA_PARA_DST_DATA_BLK_SIZ_SHIFT)
#define AWIN_DDMA_PARA_DST_WAIT_CYC_SHIFT 16
#define AWIN_DDMA_PARA_DST_WAIT_CYC_MASK (0xff << AWIN_DDMA_PARA_DST_WAIT_CYC_SHIFT)
#define AWIN_DDMA_PARA_SRC_DATA_BLK_SIZ_SHIFT 8
#define AWIN_DDMA_PARA_SRC_DATA_BLK_SIZ_MASK (0xff << AWIN_DDMA_PARA_SRC_DATA_BLK_SIZ_SHIFT)
#define AWIN_DDMA_PARA_SRC_WAIT_CYC_SHIFT 0
#define AWIN_DDMA_PARA_SRC_WAIT_CYC_MASK (0xff << AWIN_DDMA_PARA_SRC_WAIT_CYC_SHIFT)
#endif /* !_A10_DMAC_H_ */

View File

@ -47,12 +47,15 @@ __FBSDID("$FreeBSD$");
#include <machine/intr.h>
#include <dev/fdt/fdt_common.h>
#include <dev/fdt/fdt_pinctrl.h>
#include <dev/gpio/gpiobusvar.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#include <arm/allwinner/allwinner_machdep.h>
#include <arm/allwinner/allwinner_pinctrl.h>
#include "gpio_if.h"
#include "a10_gpio.h"
/*
* A10 have 9 banks of gpio.
@ -62,7 +65,6 @@ __FBSDID("$FreeBSD$");
* PG0 - PG9 | PH0 - PH27 | PI0 - PI12
*/
#define A10_GPIO_PINS 288
#define A10_GPIO_DEFAULT_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | \
GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN)
@ -73,6 +75,9 @@ __FBSDID("$FreeBSD$");
#define A10_GPIO_INPUT 0
#define A10_GPIO_OUTPUT 1
#define AW_GPIO_DRV_MASK 0x3
#define AW_GPIO_PUD_MASK 0x3
static struct ofw_compat_data compat_data[] = {
{"allwinner,sun4i-a10-pinctrl", 1},
{"allwinner,sun7i-a20-pinctrl", 1},
@ -88,8 +93,19 @@ struct a10_gpio_softc {
bus_space_tag_t sc_bst;
bus_space_handle_t sc_bsh;
void * sc_intrhand;
const struct allwinner_padconf * padconf;
};
/* Defined in a10_padconf.c */
#ifdef SOC_ALLWINNER_A10
extern const struct allwinner_padconf a10_padconf;
#endif
/* Defined in a20_padconf.c */
#ifdef SOC_ALLWINNER_A20
extern const struct allwinner_padconf a20_padconf;
#endif
#define A10_GPIO_LOCK(_sc) mtx_lock_spin(&(_sc)->sc_mtx)
#define A10_GPIO_UNLOCK(_sc) mtx_unlock_spin(&(_sc)->sc_mtx)
#define A10_GPIO_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->sc_mtx, MA_OWNED)
@ -123,8 +139,10 @@ a10_gpio_get_function(struct a10_gpio_softc *sc, uint32_t pin)
/* Must be called with lock held. */
A10_GPIO_LOCK_ASSERT(sc);
bank = pin / 32;
pin = pin % 32;
if (pin > sc->padconf->npins)
return (0);
bank = sc->padconf->pins[pin].port;
pin = sc->padconf->pins[pin].pin;
offset = ((pin & 0x07) << 2);
func = A10_GPIO_READ(sc, A10_GPIO_GP_CFG(bank, pin >> 3));
@ -146,8 +164,8 @@ a10_gpio_set_function(struct a10_gpio_softc *sc, uint32_t pin, uint32_t f)
/* Must be called with lock held. */
A10_GPIO_LOCK_ASSERT(sc);
bank = pin / 32;
pin = pin % 32;
bank = sc->padconf->pins[pin].port;
pin = sc->padconf->pins[pin].pin;
offset = ((pin & 0x07) << 2);
data = A10_GPIO_READ(sc, A10_GPIO_GP_CFG(bank, pin >> 3));
@ -164,8 +182,8 @@ a10_gpio_get_pud(struct a10_gpio_softc *sc, uint32_t pin)
/* Must be called with lock held. */
A10_GPIO_LOCK_ASSERT(sc);
bank = pin / 32;
pin = pin % 32;
bank = sc->padconf->pins[pin].port;
pin = sc->padconf->pins[pin].pin;
offset = ((pin & 0x0f) << 1);
val = A10_GPIO_READ(sc, A10_GPIO_GP_PUL(bank, pin >> 4));
@ -187,16 +205,34 @@ a10_gpio_set_pud(struct a10_gpio_softc *sc, uint32_t pin, uint32_t state)
/* Must be called with lock held. */
A10_GPIO_LOCK_ASSERT(sc);
bank = pin / 32;
pin = pin % 32;
bank = sc->padconf->pins[pin].port;
pin = sc->padconf->pins[pin].pin;
offset = ((pin & 0x0f) << 1);
val = A10_GPIO_READ(sc, A10_GPIO_GP_PUL(bank, pin >> 4));
val &= ~(0x03 << offset);
val &= ~(AW_GPIO_PUD_MASK << offset);
val |= (state << offset);
A10_GPIO_WRITE(sc, A10_GPIO_GP_PUL(bank, pin >> 4), val);
}
static void
a10_gpio_set_drv(struct a10_gpio_softc *sc, uint32_t pin, uint32_t drive)
{
uint32_t bank, offset, val;
/* Must be called with lock held. */
A10_GPIO_LOCK_ASSERT(sc);
bank = sc->padconf->pins[pin].port;
pin = sc->padconf->pins[pin].pin;
offset = ((pin & 0x0f) << 1);
val = A10_GPIO_READ(sc, A10_GPIO_GP_DRV(bank, pin >> 4));
val &= ~(AW_GPIO_DRV_MASK << offset);
val |= (drive << offset);
A10_GPIO_WRITE(sc, A10_GPIO_GP_DRV(bank, pin >> 4), val);
}
static void
a10_gpio_pin_configure(struct a10_gpio_softc *sc, uint32_t pin, uint32_t flags)
{
@ -218,7 +254,7 @@ a10_gpio_pin_configure(struct a10_gpio_softc *sc, uint32_t pin, uint32_t flags)
a10_gpio_set_pud(sc, pin, A10_GPIO_PULLUP);
else
a10_gpio_set_pud(sc, pin, A10_GPIO_PULLDOWN);
} else
} else
a10_gpio_set_pud(sc, pin, A10_GPIO_NONE);
}
@ -235,16 +271,21 @@ a10_gpio_get_bus(device_t dev)
static int
a10_gpio_pin_max(device_t dev, int *maxpin)
{
struct a10_gpio_softc *sc;
*maxpin = A10_GPIO_PINS - 1;
sc = device_get_softc(dev);
*maxpin = sc->padconf->npins - 1;
return (0);
}
static int
a10_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
{
struct a10_gpio_softc *sc;
if (pin >= A10_GPIO_PINS)
sc = device_get_softc(dev);
if (pin >= sc->padconf->npins)
return (EINVAL);
*caps = A10_GPIO_DEFAULT_CAPS;
@ -257,10 +298,10 @@ a10_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
{
struct a10_gpio_softc *sc;
if (pin >= A10_GPIO_PINS)
sc = device_get_softc(dev);
if (pin >= sc->padconf->npins)
return (EINVAL);
sc = device_get_softc(dev);
A10_GPIO_LOCK(sc);
*flags = a10_gpio_get_function(sc, pin);
*flags |= a10_gpio_get_pud(sc, pin);
@ -272,14 +313,14 @@ a10_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
static int
a10_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
{
uint32_t bank;
struct a10_gpio_softc *sc;
if (pin >= A10_GPIO_PINS)
sc = device_get_softc(dev);
if (pin >= sc->padconf->npins)
return (EINVAL);
bank = pin / 32;
snprintf(name, GPIOMAXNAME - 1, "pin %d (P%c%d)",
pin, bank + 'A', pin % 32);
snprintf(name, GPIOMAXNAME - 1, "%s",
sc->padconf->pins[pin].name);
name[GPIOMAXNAME - 1] = '\0';
return (0);
@ -290,10 +331,10 @@ a10_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
{
struct a10_gpio_softc *sc;
if (pin >= A10_GPIO_PINS)
sc = device_get_softc(dev);
if (pin > sc->padconf->npins)
return (EINVAL);
sc = device_get_softc(dev);
A10_GPIO_LOCK(sc);
a10_gpio_pin_configure(sc, pin, flags);
A10_GPIO_UNLOCK(sc);
@ -307,13 +348,13 @@ a10_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
struct a10_gpio_softc *sc;
uint32_t bank, data;
if (pin >= A10_GPIO_PINS)
sc = device_get_softc(dev);
if (pin > sc->padconf->npins)
return (EINVAL);
bank = pin / 32;
pin = pin % 32;
bank = sc->padconf->pins[pin].port;
pin = sc->padconf->pins[pin].pin;
sc = device_get_softc(dev);
A10_GPIO_LOCK(sc);
data = A10_GPIO_READ(sc, A10_GPIO_GP_DAT(bank));
if (value)
@ -332,13 +373,13 @@ a10_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
struct a10_gpio_softc *sc;
uint32_t bank, reg_data;
if (pin >= A10_GPIO_PINS)
sc = device_get_softc(dev);
if (pin > sc->padconf->npins)
return (EINVAL);
bank = pin / 32;
pin = pin % 32;
bank = sc->padconf->pins[pin].port;
pin = sc->padconf->pins[pin].pin;
sc = device_get_softc(dev);
A10_GPIO_LOCK(sc);
reg_data = A10_GPIO_READ(sc, A10_GPIO_GP_DAT(bank));
A10_GPIO_UNLOCK(sc);
@ -353,13 +394,13 @@ a10_gpio_pin_toggle(device_t dev, uint32_t pin)
struct a10_gpio_softc *sc;
uint32_t bank, data;
if (pin >= A10_GPIO_PINS)
sc = device_get_softc(dev);
if (pin > sc->padconf->npins)
return (EINVAL);
bank = pin / 32;
pin = pin % 32;
bank = sc->padconf->pins[pin].port;
pin = sc->padconf->pins[pin].pin;
sc = device_get_softc(dev);
A10_GPIO_LOCK(sc);
data = A10_GPIO_READ(sc, A10_GPIO_GP_DAT(bank));
if (data & (1 << pin))
@ -372,6 +413,92 @@ a10_gpio_pin_toggle(device_t dev, uint32_t pin)
return (0);
}
static int
aw_find_pinnum_by_name(struct a10_gpio_softc *sc, const char *pinname)
{
int i;
for (i = 0; i < sc->padconf->npins; i++)
if (!strcmp(pinname, sc->padconf->pins[i].name))
return i;
return (-1);
}
static int
aw_find_pin_func(struct a10_gpio_softc *sc, int pin, const char *func)
{
int i;
for (i = 0; i < AW_MAX_FUNC_BY_PIN; i++)
if (sc->padconf->pins[pin].functions[i] &&
!strcmp(func, sc->padconf->pins[pin].functions[i]))
return (i);
return (-1);
}
static int
aw_fdt_configure_pins(device_t dev, phandle_t cfgxref)
{
struct a10_gpio_softc *sc;
phandle_t node;
const char **pinlist = NULL;
char *pin_function = NULL;
uint32_t pin_drive, pin_pull;
int pins_nb, pin_num, pin_func, i, ret;
sc = device_get_softc(dev);
node = OF_node_from_xref(cfgxref);
ret = 0;
/* Getting all prop for configuring pins */
pins_nb = ofw_bus_string_list_to_array(node, "allwinner,pins", &pinlist);
if (pins_nb <= 0)
return (ENOENT);
if (OF_getprop_alloc(node, "allwinner,function",
sizeof(*pin_function),
(void **)&pin_function) == -1) {
ret = ENOENT;
goto out;
}
if (OF_getencprop(node, "allwinner,drive",
&pin_drive, sizeof(pin_drive)) == -1) {
ret = ENOENT;
goto out;
}
if (OF_getencprop(node, "allwinner,pull",
&pin_pull, sizeof(pin_pull)) == -1) {
ret = ENOENT;
goto out;
}
/* Configure each pin to the correct function, drive and pull */
for (i = 0; i < pins_nb; i++) {
pin_num = aw_find_pinnum_by_name(sc, pinlist[i]);
if (pin_num == -1) {
ret = ENOENT;
goto out;
}
pin_func = aw_find_pin_func(sc, pin_num, pin_function);
if (pin_func == -1) {
ret = ENOENT;
goto out;
}
A10_GPIO_LOCK(sc);
a10_gpio_set_function(sc, pin_num, pin_func);
a10_gpio_set_drv(sc, pin_num, pin_drive);
a10_gpio_set_pud(sc, pin_num, pin_pull);
A10_GPIO_UNLOCK(sc);
}
out:
free(pinlist, M_OFWPROP);
free(pin_function, M_OFWPROP);
return (ret);
}
static int
a10_gpio_probe(device_t dev)
{
@ -382,7 +509,7 @@ a10_gpio_probe(device_t dev)
if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
return (ENXIO);
device_set_desc(dev, "Allwinner GPIO controller");
device_set_desc(dev, "Allwinner GPIO/Pinmux controller");
return (BUS_PROBE_DEFAULT);
}
@ -428,6 +555,29 @@ a10_gpio_attach(device_t dev)
if (sc->sc_busdev == NULL)
goto fail;
/* Use the right pin data for the current SoC */
switch (allwinner_soc_type()) {
#ifdef SOC_ALLWINNER_A10
case ALLWINNERSOC_A10:
sc->padconf = &a10_padconf;
break;
#endif
#ifdef SOC_ALLWINNER_A20
case ALLWINNERSOC_A20:
sc->padconf = &a20_padconf;
break;
#endif
default:
return (ENOENT);
}
/*
* Register as a pinctrl device
*/
fdt_pinctrl_register(dev, "allwinner,pins");
fdt_pinctrl_configure_tree(dev);
return (0);
fail:
@ -459,9 +609,18 @@ static int
a10_gpio_map_gpios(device_t bus, phandle_t dev, phandle_t gparent, int gcells,
pcell_t *gpios, uint32_t *pin, uint32_t *flags)
{
struct a10_gpio_softc *sc;
int i;
sc = device_get_softc(bus);
/* The GPIO pins are mapped as: <gpio-phandle bank pin flags>. */
*pin = gpios[0] * 32 + gpios[1];
for (i = 0; i < sc->padconf->npins; i++)
if (sc->padconf->pins[i].port == gpios[0] &&
sc->padconf->pins[i].pin == gpios[1]) {
*pin = i;
break;
}
*flags = gpios[gcells - 1];
return (0);
@ -488,6 +647,9 @@ static device_method_t a10_gpio_methods[] = {
/* ofw_bus interface */
DEVMETHOD(ofw_bus_get_node, a10_gpio_get_node),
/* fdt_pinctrl interface */
DEVMETHOD(fdt_pinctrl_configure,aw_fdt_configure_pins),
DEVMETHOD_END
};
@ -501,22 +663,3 @@ static driver_t a10_gpio_driver = {
EARLY_DRIVER_MODULE(a10_gpio, simplebus, a10_gpio_driver, a10_gpio_devclass, 0, 0,
BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);
int
a10_gpio_ethernet_activate(uint32_t func)
{
int i;
struct a10_gpio_softc *sc = a10_gpio_sc;
if (sc == NULL)
return (ENXIO);
/* Configure pin mux settings for MII. */
A10_GPIO_LOCK(sc);
for (i = 0; i <= 17; i++)
a10_gpio_set_function(sc, i, func);
A10_GPIO_UNLOCK(sc);
return (0);
}

View File

@ -0,0 +1,227 @@
/*-
* Copyright (c) 2016 Emmanuel Vadot <manu@bidouilliste.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/types.h>
#include <arm/allwinner/allwinner_pinctrl.h>
const static struct allwinner_pins a10_pins[] = {
{"PA0", 0, 0, {"gpio_in", "gpio_out", "emac", "spi1", "uart2", NULL, NULL, NULL}},
{"PA1", 0, 1, {"gpio_in", "gpio_out", "emac", "spi1", "uart2", NULL, NULL, NULL}},
{"PA2", 0, 2, {"gpio_in", "gpio_out", "emac", "spi1", "uart2", NULL, NULL, NULL}},
{"PA3", 0, 3, {"gpio_in", "gpio_out", "emac", "spi1", "uart2", NULL, NULL, NULL}},
{"PA4", 0, 4, {"gpio_in", "gpio_out", "emac", "spi1", NULL, NULL, NULL, NULL}},
{"PA5", 0, 5, {"gpio_in", "gpio_out", "emac", "spi3", NULL, NULL, NULL, NULL}},
{"PA6", 0, 6, {"gpio_in", "gpio_out", "emac", "spi3", NULL, NULL, NULL, NULL}},
{"PA7", 0, 7, {"gpio_in", "gpio_out", "emac", "spi3", NULL, NULL, NULL, NULL}},
{"PA8", 0, 8, {"gpio_in", "gpio_out", "emac", "spi3", NULL, NULL, NULL, NULL}},
{"PA9", 0, 9, {"gpio_in", "gpio_out", "emac", "spi3", NULL, NULL, NULL, NULL}},
{"PA10", 0, 10, {"gpio_in", "gpio_out", "emac", NULL, "uart1", NULL, NULL, NULL}},
{"PA11", 0, 11, {"gpio_in", "gpio_out", "emac", NULL, "uart1", NULL, NULL, NULL}},
{"PA12", 0, 12, {"gpio_in", "gpio_out", "emac", "uart6", "uart1", NULL, NULL, NULL}},
{"PA13", 0, 13, {"gpio_in", "gpio_out", "emac", "uart6", "uart1", NULL, NULL, NULL}},
{"PA14", 0, 14, {"gpio_in", "gpio_out", "emac", "uart7", "uart1", NULL, NULL, NULL}},
{"PA15", 0, 15, {"gpio_in", "gpio_out", "emac", "uart7", "uart1", NULL, NULL, NULL}},
{"PA16", 0, 16, {"gpio_in", "gpio_out", NULL, "can", "uart1", NULL, NULL, NULL}},
{"PA17", 0, 17, {"gpio_in", "gpio_out", NULL, "can", "uart1", NULL, NULL, NULL}},
{"PB0", 1, 0, {"gpio_in", "gpio_out", "i2c0", NULL, NULL, NULL, NULL, NULL}},
{"PB1", 1, 1, {"gpio_in", "gpio_out", "i2c0", NULL, NULL, NULL, NULL, NULL}},
{"PB2", 1, 2, {"gpio_in", "gpio_out", "pwm", NULL, NULL, NULL, NULL, NULL}},
{"PB3", 1, 3, {"gpio_in", "gpio_out", "ir0", NULL, NULL, NULL, NULL, NULL}},
{"PB4", 1, 4, {"gpio_in", "gpio_out", "ir0", NULL, NULL, NULL, NULL, NULL}},
{"PB5", 1, 5, {"gpio_in", "gpio_out", "i2s", "ac97", NULL, NULL, NULL, NULL}},
{"PB6", 1, 6, {"gpio_in", "gpio_out", "i2s", "ac97", NULL, NULL, NULL, NULL}},
{"PB7", 1, 7, {"gpio_in", "gpio_out", "i2s", "ac97", NULL, NULL, NULL, NULL}},
{"PB8", 1, 8, {"gpio_in", "gpio_out", "i2s", "ac97", NULL, NULL, NULL, NULL}},
{"PB9", 1, 9, {"gpio_in", "gpio_out", "i2s", NULL, NULL, NULL, NULL, NULL}},
{"PB10", 1, 10, {"gpio_in", "gpio_out", "i2s", NULL, NULL, NULL, NULL, NULL}},
{"PB11", 1, 11, {"gpio_in", "gpio_out", "i2s", NULL, NULL, NULL, NULL, NULL}},
{"PB12", 1, 12, {"gpio_in", "gpio_out", "i2s", "ac97", NULL, NULL, NULL, NULL}},
{"PB13", 1, 13, {"gpio_in", "gpio_out", "spi2", NULL, NULL, NULL, NULL, NULL}},
{"PB14", 1, 14, {"gpio_in", "gpio_out", "spi2", "jtag", NULL, NULL, NULL, NULL}},
{"PB15", 1, 15, {"gpio_in", "gpio_out", "spi2", "jtag", NULL, NULL, NULL, NULL}},
{"PB16", 1, 16, {"gpio_in", "gpio_out", "spi2", "jtag", NULL, NULL, NULL, NULL}},
{"PB17", 1, 17, {"gpio_in", "gpio_out", "spi2", "jtag", NULL, NULL, NULL, NULL}},
{"PB18", 1, 18, {"gpio_in", "gpio_out", "i2c1", NULL, NULL, NULL, NULL, NULL}},
{"PB19", 1, 19, {"gpio_in", "gpio_out", "i2c1", NULL, NULL, NULL, NULL, NULL}},
{"PB20", 1, 20, {"gpio_in", "gpio_out", "i2c1", NULL, NULL, NULL, NULL, NULL}},
{"PB21", 1, 21, {"gpio_in", "gpio_out", "i2c1", NULL, NULL, NULL, NULL, NULL}},
{"PB22", 1, 22, {"gpio_in", "gpio_out", "uart0", "ir1", NULL, NULL, NULL, NULL}},
{"PB23", 1, 23, {"gpio_in", "gpio_out", "uart0", "ir1", NULL, NULL, NULL, NULL}},
{"PC0", 2, 0, {"gpio_in", "gpio_out", "nand", "spi0", NULL, NULL, NULL, NULL}},
{"PC1", 2, 1, {"gpio_in", "gpio_out", "nand", "spi0", NULL, NULL, NULL, NULL}},
{"PC2", 2, 2, {"gpio_in", "gpio_out", "nand", "spi0", NULL, NULL, NULL, NULL}},
{"PC3", 2, 3, {"gpio_in", "gpio_out", "nand", NULL, NULL, NULL, NULL, NULL}},
{"PC4", 2, 4, {"gpio_in", "gpio_out", "nand", NULL, NULL, NULL, NULL, NULL}},
{"PC5", 2, 5, {"gpio_in", "gpio_out", "nand", NULL, NULL, NULL, NULL, NULL}},
{"PC6", 2, 6, {"gpio_in", "gpio_out", "nand", "mmc2", NULL, NULL, NULL, NULL}},
{"PC7", 2, 7, {"gpio_in", "gpio_out", "nand", "mmc2", NULL, NULL, NULL, NULL}},
{"PC8", 2, 8, {"gpio_in", "gpio_out", "nand", "mmc2", NULL, NULL, NULL, NULL}},
{"PC9", 2, 9, {"gpio_in", "gpio_out", "nand", "mmc2", NULL, NULL, NULL, NULL}},
{"PC10", 2, 10, {"gpio_in", "gpio_out", "nand", "mmc2", NULL, NULL, NULL, NULL}},
{"PC11", 2, 11, {"gpio_in", "gpio_out", "nand", "mmc2", NULL, NULL, NULL, NULL}},
{"PC12", 2, 12, {"gpio_in", "gpio_out", "nand", NULL, NULL, NULL, NULL, NULL}},
{"PC13", 2, 13, {"gpio_in", "gpio_out", "nand", NULL, NULL, NULL, NULL, NULL}},
{"PC14", 2, 14, {"gpio_in", "gpio_out", "nand", NULL, NULL, NULL, NULL, NULL}},
{"PC15", 2, 15, {"gpio_in", "gpio_out", "nand", NULL, NULL, NULL, NULL, NULL}},
{"PC16", 2, 16, {"gpio_in", "gpio_out", "nand", NULL, NULL, NULL, NULL, NULL}},
{"PC17", 2, 17, {"gpio_in", "gpio_out", "nand", NULL, NULL, NULL, NULL, NULL}},
{"PC18", 2, 18, {"gpio_in", "gpio_out", "nand", NULL, NULL, NULL, NULL, NULL}},
{"PC19", 2, 19, {"gpio_in", "gpio_out", "nand", "spi2", NULL, NULL, NULL, NULL}},
{"PC20", 2, 20, {"gpio_in", "gpio_out", "nand", "spi2", NULL, NULL, NULL, NULL}},
{"PC21", 2, 21, {"gpio_in", "gpio_out", "nand", "spi2", NULL, NULL, NULL, NULL}},
{"PC22", 2, 22, {"gpio_in", "gpio_out", "nand", "spi2", NULL, NULL, NULL, NULL}},
{"PC23", 2, 23, {"gpio_in", "gpio_out", "spi0", NULL, NULL, NULL, NULL, NULL}},
{"PC24", 2, 24, {"gpio_in", "gpio_out", "nand", NULL, NULL, NULL, NULL, NULL}},
{"PD0", 3, 0, {"gpio_in", "gpio_out", "lcd0", "lvds0", NULL, NULL, NULL, NULL}},
{"PD1", 3, 1, {"gpio_in", "gpio_out", "lcd0", "lvds0", NULL, NULL, NULL, NULL}},
{"PD2", 3, 2, {"gpio_in", "gpio_out", "lcd0", "lvds0", NULL, NULL, NULL, NULL}},
{"PD3", 3, 3, {"gpio_in", "gpio_out", "lcd0", "lvds0", NULL, NULL, NULL, NULL}},
{"PD4", 3, 4, {"gpio_in", "gpio_out", "lcd0", "lvds0", NULL, NULL, NULL, NULL}},
{"PD5", 3, 5, {"gpio_in", "gpio_out", "lcd0", "lvds0", NULL, NULL, NULL, NULL}},
{"PD6", 3, 6, {"gpio_in", "gpio_out", "lcd0", "lvds0", NULL, NULL, NULL, NULL}},
{"PD7", 3, 7, {"gpio_in", "gpio_out", "lcd0", "lvds0", NULL, NULL, NULL, NULL}},
{"PD8", 3, 8, {"gpio_in", "gpio_out", "lcd0", "lvds0", NULL, NULL, NULL, NULL}},
{"PD9", 3, 9, {"gpio_in", "gpio_out", "lcd0", "lvds0", NULL, NULL, NULL, NULL}},
{"PD10", 3, 10, {"gpio_in", "gpio_out", "lcd0", "lvds1", NULL, NULL, NULL, NULL}},
{"PD11", 3, 11, {"gpio_in", "gpio_out", "lcd0", "lvds1", NULL, NULL, NULL, NULL}},
{"PD12", 3, 12, {"gpio_in", "gpio_out", "lcd0", "lvds1", NULL, NULL, NULL, NULL}},
{"PD13", 3, 13, {"gpio_in", "gpio_out", "lcd0", "lvds1", NULL, NULL, NULL, NULL}},
{"PD14", 3, 14, {"gpio_in", "gpio_out", "lcd0", "lvds1", NULL, NULL, NULL, NULL}},
{"PD15", 3, 15, {"gpio_in", "gpio_out", "lcd0", "lvds1", NULL, NULL, NULL, NULL}},
{"PD16", 3, 16, {"gpio_in", "gpio_out", "lcd0", "lvds1", NULL, NULL, NULL, NULL}},
{"PD17", 3, 17, {"gpio_in", "gpio_out", "lcd0", "lvds1", NULL, NULL, NULL, NULL}},
{"PD18", 3, 18, {"gpio_in", "gpio_out", "lcd0", "lvds1", NULL, NULL, NULL, NULL}},
{"PD19", 3, 19, {"gpio_in", "gpio_out", "lcd0", "lvds1", NULL, NULL, NULL, NULL}},
{"PD20", 3, 20, {"gpio_in", "gpio_out", "lcd0", "csi1", NULL, NULL, NULL, NULL}},
{"PD21", 3, 21, {"gpio_in", "gpio_out", "lcd0", "sim", NULL, NULL, NULL, NULL}},
{"PD22", 3, 22, {"gpio_in", "gpio_out", "lcd0", "sim", NULL, NULL, NULL, NULL}},
{"PD23", 3, 23, {"gpio_in", "gpio_out", "lcd0", "sim", NULL, NULL, NULL, NULL}},
{"PD24", 3, 24, {"gpio_in", "gpio_out", "lcd0", "sim", NULL, NULL, NULL, NULL}},
{"PD25", 3, 25, {"gpio_in", "gpio_out", "lcd0", "sim", NULL, NULL, NULL, NULL}},
{"PD26", 3, 26, {"gpio_in", "gpio_out", "lcd0", "sim", NULL, NULL, NULL, NULL}},
{"PD27", 3, 27, {"gpio_in", "gpio_out", "lcd0", "sim", NULL, NULL, NULL, NULL}},
{"PE0", 4, 0, {"gpio_in", "gpio_out", "ts0", "csi0", NULL, NULL, NULL, NULL}},
{"PE1", 4, 1, {"gpio_in", "gpio_out", "ts0", "csi0", NULL, NULL, NULL, NULL}},
{"PE2", 4, 2, {"gpio_in", "gpio_out", "ts0", "csi0", NULL, NULL, NULL, NULL}},
{"PE3", 4, 3, {"gpio_in", "gpio_out", "ts0", "csi0", NULL, NULL, NULL, NULL}},
{"PE4", 4, 4, {"gpio_in", "gpio_out", "ts0", "csi0", NULL, NULL, NULL, NULL}},
{"PE5", 4, 5, {"gpio_in", "gpio_out", "ts0", "csi0", "sim", NULL, NULL, NULL}},
{"PE6", 4, 6, {"gpio_in", "gpio_out", "ts0", "csi0", NULL, NULL, NULL, NULL}},
{"PE7", 4, 7, {"gpio_in", "gpio_out", "ts0", "csi0", NULL, NULL, NULL, NULL}},
{"PE8", 4, 8, {"gpio_in", "gpio_out", "ts0", "csi0", NULL, NULL, NULL, NULL}},
{"PE9", 4, 9, {"gpio_in", "gpio_out", "ts0", "csi0", NULL, NULL, NULL, NULL}},
{"PE10", 4, 10, {"gpio_in", "gpio_out", "ts0", "csi0", NULL, NULL, NULL, NULL}},
{"PE11", 4, 11, {"gpio_in", "gpio_out", "ts0", "csi0", NULL, NULL, NULL, NULL}},
{"PF0", 5, 0, {"gpio_in", "gpio_out", "mmc0", NULL, "jtag", NULL, NULL, NULL}},
{"PF1", 5, 1, {"gpio_in", "gpio_out", "mmc0", NULL, "jtag", NULL, NULL, NULL}},
{"PF2", 5, 2, {"gpio_in", "gpio_out", "mmc0", NULL, "uart0", NULL, NULL, NULL}},
{"PF3", 5, 3, {"gpio_in", "gpio_out", "mmc0", NULL, "jtag", NULL, NULL, NULL}},
{"PF4", 5, 4, {"gpio_in", "gpio_out", "mmc0", NULL, "jtag", NULL, NULL, NULL}},
{"PF5", 5, 5, {"gpio_in", "gpio_out", "mmc0", NULL, "jtag", NULL, NULL, NULL}},
{"PG0", 6, 0, {"gpio_in", "gpio_out", "ts1", "csi1", "mmc1", NULL, NULL, NULL}},
{"PG1", 6, 1, {"gpio_in", "gpio_out", "ts1", "csi1", "mmc1", NULL, NULL, NULL}},
{"PG2", 6, 2, {"gpio_in", "gpio_out", "ts1", "csi1", "mmc1", NULL, NULL, NULL}},
{"PG3", 6, 3, {"gpio_in", "gpio_out", "ts1", "csi1", "mmc1", NULL, NULL, NULL}},
{"PG4", 6, 4, {"gpio_in", "gpio_out", "ts1", "csi1", "mmc1", "csi0", NULL, NULL}},
{"PG5", 6, 5, {"gpio_in", "gpio_out", "ts1", "csi1", "mmc1", "csi0", NULL, NULL}},
{"PG6", 6, 6, {"gpio_in", "gpio_out", "ts1", "csi1", "uart3", "csi0", NULL, NULL}},
{"PG7", 6, 7, {"gpio_in", "gpio_out", "ts1", "csi1", "uart3", "csi0", NULL, NULL}},
{"PG8", 6, 8, {"gpio_in", "gpio_out", "ts1", "csi1", "uart3", "csi0", NULL, NULL}},
{"PG9", 6, 9, {"gpio_in", "gpio_out", "ts1", "csi1", "uart3", "csi0", NULL, NULL}},
{"PG10", 6, 10, {"gpio_in", "gpio_out", "ts1", "csi1", "uart4", "csi0", NULL, NULL}},
{"PG11", 6, 11, {"gpio_in", "gpio_out", "ts1", "csi1", "uart4", "csi0", NULL, NULL}},
{"PH0", 7, 0, {"gpio_in", "gpio_out", "lcd1", "pata", "uart3", NULL, "eint", "csi1"}},
{"PH1", 7, 1, {"gpio_in", "gpio_out", "lcd1", "pata", "uart3", NULL, "eint", "csi1"}},
{"PH2", 7, 2, {"gpio_in", "gpio_out", "lcd1", "pata", "uart3", NULL, "eint", "csi1"}},
{"PH3", 7, 3, {"gpio_in", "gpio_out", "lcd1", "pata", "uart3", NULL, "eint", "csi1"}},
{"PH4", 7, 4, {"gpio_in", "gpio_out", "lcd1", "pata", "uart4", NULL, "eint", "csi1"}},
{"PH5", 7, 5, {"gpio_in", "gpio_out", "lcd1", "pata", "uart4", NULL, "eint", "csi1"}},
{"PH6", 7, 6, {"gpio_in", "gpio_out", "lcd1", "pata", "uart5", "ms", "eint", "csi1"}},
{"PH7", 7, 7, {"gpio_in", "gpio_out", "lcd1", "pata", "uart5", "ms", "eint", "csi1"}},
{"PH8", 7, 8, {"gpio_in", "gpio_out", "lcd1", "pata", "keypad", "ms", "eint", "csi1"}},
{"PH9", 7, 9, {"gpio_in", "gpio_out", "lcd1", "pata", "keypad", "ms", "eint", "csi1"}},
{"PH10", 7, 10, {"gpio_in", "gpio_out", "lcd1", "pata", "keypad", "ms", "eint", "csi1"}},
{"PH11", 7, 11, {"gpio_in", "gpio_out", "lcd1", "pata", "keypad", "ms", "eint", "csi1"}},
{"PH12", 7, 12, {"gpio_in", "gpio_out", "lcd1", "pata", "ps2", NULL, "eint", "csi1"}},
{"PH13", 7, 13, {"gpio_in", "gpio_out", "lcd1", "pata", "ps2", "sim", "eint", "csi1"}},
{"PH14", 7, 14, {"gpio_in", "gpio_out", "lcd1", "pata", "keypad", "sim", "eint", "csi1"}},
{"PH15", 7, 15, {"gpio_in", "gpio_out", "lcd1", "pata", "keypad", "sim", "eint", "csi1"}},
{"PH16", 7, 16, {"gpio_in", "gpio_out", "lcd1", "pata", "keypad", NULL, "eint", "csi1"}},
{"PH17", 7, 17, {"gpio_in", "gpio_out", "lcd1", "pata", "keypad", "sim", "eint", "csi1"}},
{"PH18", 7, 18, {"gpio_in", "gpio_out", "lcd1", "pata", "keypad", "sim", "eint", "csi1"}},
{"PH19", 7, 19, {"gpio_in", "gpio_out", "lcd1", "pata", "keypad", "sim", "eint", "csi1"}},
{"PH20", 7, 20, {"gpio_in", "gpio_out", "lcd1", "pata", "can", NULL, "eint", "csi1"}},
{"PH21", 7, 21, {"gpio_in", "gpio_out", "lcd1", "pata", "can", NULL, "eint", "csi1"}},
{"PH22", 7, 22, {"gpio_in", "gpio_out", "lcd1", "pata", "keypad", "mmc1", NULL, "csi1"}},
{"PH23", 7, 23, {"gpio_in", "gpio_out", "lcd1", "pata", "keypad", "mmc1", NULL, "csi1"}},
{"PH24", 7, 24, {"gpio_in", "gpio_out", "lcd1", "pata", "keypad", "mmc1", NULL, "csi1"}},
{"PH25", 7, 25, {"gpio_in", "gpio_out", "lcd1", "pata", "keypad", "mmc1", NULL, "csi1"}},
{"PH26", 7, 26, {"gpio_in", "gpio_out", "lcd1", "pata", "keypad", "mmc1", NULL, "csi1"}},
{"PH27", 7, 27, {"gpio_in", "gpio_out", "lcd1", "pata", "keypad", "mmc1", NULL, "csi1"}},
{"PI0", 8, 0, {"gpio_in", "gpio_out", NULL, NULL, NULL, NULL, NULL, NULL}},
{"PI1", 8, 1, {"gpio_in", "gpio_out", NULL, NULL, NULL, NULL, NULL, NULL}},
{"PI2", 8, 2, {"gpio_in", "gpio_out", NULL, NULL, NULL, NULL, NULL, NULL}},
{"PI3", 8, 3, {"gpio_in", "gpio_out", "pwm", NULL, NULL, NULL, NULL, NULL}},
{"PI4", 8, 4, {"gpio_in", "gpio_out", "mmc3", NULL, NULL, NULL, NULL, NULL}},
{"PI5", 8, 5, {"gpio_in", "gpio_out", "mmc3", NULL, NULL, NULL, NULL, NULL}},
{"PI6", 8, 6, {"gpio_in", "gpio_out", "mmc3", NULL, NULL, NULL, NULL, NULL}},
{"PI7", 8, 7, {"gpio_in", "gpio_out", "mmc3", NULL, NULL, NULL, NULL, NULL}},
{"PI8", 8, 8, {"gpio_in", "gpio_out", "mmc3", NULL, NULL, NULL, NULL, NULL}},
{"PI9", 8, 9, {"gpio_in", "gpio_out", "mmc3", NULL, NULL, NULL, NULL, NULL}},
{"PI10", 8, 10, {"gpio_in", "gpio_out", "spi0", "uart5", NULL, NULL, "eint", NULL}},
{"PI11", 8, 11, {"gpio_in", "gpio_out", "spi0", "uart5", NULL, NULL, "eint", NULL}},
{"PI12", 8, 12, {"gpio_in", "gpio_out", "spi0", "uart6", NULL, NULL, "eint", NULL}},
{"PI13", 8, 13, {"gpio_in", "gpio_out", "spi0", "uart6", NULL, NULL, "eint", NULL}},
{"PI14", 8, 14, {"gpio_in", "gpio_out", "spi0", "ps2", "timer4", NULL, "eint", NULL}},
{"PI15", 8, 15, {"gpio_in", "gpio_out", "spi1", "ps2", "timer5", NULL, "eint", NULL}},
{"PI16", 8, 16, {"gpio_in", "gpio_out", "spi1", "uart2", NULL, NULL, "eint", NULL}},
{"PI17", 8, 17, {"gpio_in", "gpio_out", "spi1", "uart2", NULL, NULL, "eint", NULL}},
{"PI18", 8, 18, {"gpio_in", "gpio_out", "spi1", "uart2", NULL, NULL, "eint", NULL}},
{"PI19", 8, 19, {"gpio_in", "gpio_out", "spi1", "uart2", NULL, NULL, "eint", NULL}},
{"PI20", 8, 20, {"gpio_in", "gpio_out", "ps2", "uart7", "hdmi", NULL, NULL, NULL}},
{"PI21", 8, 21, {"gpio_in", "gpio_out", "ps2", "uart7", "hdmi", NULL, NULL, NULL}},
};
const struct allwinner_padconf a10_padconf = {
.npins = sizeof(a10_pins) / sizeof(struct allwinner_pins),
.pins = a10_pins,
};

View File

@ -41,7 +41,6 @@ __FBSDID("$FreeBSD$");
#include <dev/ofw/ofw_bus_subr.h>
#include <arm/allwinner/a10_clk.h>
#include <arm/allwinner/a10_gpio.h>
#include "if_dwc_if.h"
@ -63,8 +62,7 @@ a20_if_dwc_init(device_t dev)
{
/* Activate GMAC clock and set the pin mux to rgmii. */
if (a10_clk_gmac_activate(ofw_bus_get_node(dev)) != 0 ||
a10_gpio_ethernet_activate(A10_GPIO_FUNC_RGMII)) {
if (a10_clk_gmac_activate(ofw_bus_get_node(dev)) != 0) {
device_printf(dev, "could not activate gmac module\n");
return (ENXIO);
}

View File

@ -0,0 +1,227 @@
/*-
* Copyright (c) 2016 Emmanuel Vadot <manu@bidouilliste.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/types.h>
#include <arm/allwinner/allwinner_pinctrl.h>
const static struct allwinner_pins a20_pins[] = {
{"PA0", 0, 0, {"gpio_in", "gpio_out", "emac", "spi1", "uart2", "gmac", NULL, NULL}},
{"PA1", 0, 1, {"gpio_in", "gpio_out", "emac", "spi1", "uart2", "gmac", NULL, NULL}},
{"PA2", 0, 2, {"gpio_in", "gpio_out", "emac", "spi1", "uart2", "gmac", NULL, NULL}},
{"PA3", 0, 3, {"gpio_in", "gpio_out", "emac", "spi1", "uart2", "gmac", NULL, NULL}},
{"PA4", 0, 4, {"gpio_in", "gpio_out", "emac", "spi1", NULL, "gmac", NULL, NULL}},
{"PA5", 0, 5, {"gpio_in", "gpio_out", "emac", "spi3", NULL, "gmac", NULL, NULL}},
{"PA6", 0, 6, {"gpio_in", "gpio_out", "emac", "spi3", NULL, "gmac", NULL, NULL}},
{"PA7", 0, 7, {"gpio_in", "gpio_out", "emac", "spi3", NULL, "gmac", NULL, NULL}},
{"PA8", 0, 8, {"gpio_in", "gpio_out", "emac", "spi3", NULL, "gmac", NULL, NULL}},
{"PA9", 0, 9, {"gpio_in", "gpio_out", "emac", "spi3", NULL, "gmac", "i2c1", NULL}},
{"PA10", 0, 10, {"gpio_in", "gpio_out", "emac", NULL, "uart1", "gmac", NULL, NULL}},
{"PA11", 0, 11, {"gpio_in", "gpio_out", "emac", NULL, "uart1", "gmac", NULL, NULL}},
{"PA12", 0, 12, {"gpio_in", "gpio_out", "emac", "uart6", "uart1", "gmac", NULL, NULL}},
{"PA13", 0, 13, {"gpio_in", "gpio_out", "emac", "uart6", "uart1", "gmac", NULL, NULL}},
{"PA14", 0, 14, {"gpio_in", "gpio_out", "emac", "uart7", "uart1", "gmac", "i2c1", NULL}},
{"PA15", 0, 15, {"gpio_in", "gpio_out", "emac", "uart7", "uart1", "gmac", "i2c1", NULL}},
{"PA16", 0, 16, {"gpio_in", "gpio_out", NULL, "can", "uart1", "gmac", "i2c1", NULL}},
{"PA17", 0, 17, {"gpio_in", "gpio_out", NULL, "can", "uart1", "gmac", "i2c1", NULL}},
{"PB0", 1, 0, {"gpio_in", "gpio_out", "i2c0", NULL, NULL, NULL, NULL, NULL}},
{"PB1", 1, 1, {"gpio_in", "gpio_out", "i2c0", NULL, NULL, NULL, NULL, NULL}},
{"PB2", 1, 2, {"gpio_in", "gpio_out", "pwm", NULL, NULL, NULL, NULL, NULL}},
{"PB3", 1, 3, {"gpio_in", "gpio_out", "ir0", NULL, "spdif", NULL, NULL, NULL}},
{"PB4", 1, 4, {"gpio_in", "gpio_out", "ir0", NULL, NULL, NULL, NULL, NULL}},
{"PB5", 1, 5, {"gpio_in", "gpio_out", "i2s0", "ac97", NULL, NULL, NULL, NULL}},
{"PB6", 1, 6, {"gpio_in", "gpio_out", "i2c0", "ac97", NULL, NULL, NULL, NULL}},
{"PB7", 1, 7, {"gpio_in", "gpio_out", "i2c0", "ac97", NULL, NULL, NULL, NULL}},
{"PB8", 1, 8, {"gpio_in", "gpio_out", "i2c0", "ac97", NULL, NULL, NULL, NULL}},
{"PB9", 1, 9, {"gpio_in", "gpio_out", "i2c0", NULL, NULL, NULL, NULL, NULL}},
{"PB10", 1, 10, {"gpio_in", "gpio_out", "i2c0", NULL, NULL, NULL, NULL, NULL}},
{"PB11", 1, 11, {"gpio_in", "gpio_out", "i2c0", NULL, NULL, NULL, NULL, NULL}},
{"PB12", 1, 12, {"gpio_in", "gpio_out", "i2c0", "ac97", "spdif", NULL, NULL, NULL}},
{"PB13", 1, 13, {"gpio_in", "gpio_out", "spi2", NULL, "spdif", NULL, NULL, NULL}},
{"PB14", 1, 14, {"gpio_in", "gpio_out", "spi2", "jtag", NULL, NULL, NULL, NULL}},
{"PB15", 1, 15, {"gpio_in", "gpio_out", "spi2", "jtag", NULL, NULL, NULL, NULL}},
{"PB16", 1, 16, {"gpio_in", "gpio_out", "spi2", "jtag", NULL, NULL, NULL, NULL}},
{"PB17", 1, 17, {"gpio_in", "gpio_out", "spi2", "jtag", NULL, NULL, NULL, NULL}},
{"PB18", 1, 18, {"gpio_in", "gpio_out", "i2c1", NULL, NULL, NULL, NULL, NULL}},
{"PB19", 1, 19, {"gpio_in", "gpio_out", "i2c1", NULL, NULL, NULL, NULL, NULL}},
{"PB20", 1, 20, {"gpio_in", "gpio_out", "i2c2", NULL, NULL, NULL, NULL, NULL}},
{"PB21", 1, 21, {"gpio_in", "gpio_out", "i2c2", NULL, NULL, NULL, NULL, NULL}},
{"PB22", 1, 22, {"gpio_in", "gpio_out", "uart0", "ir1", NULL, NULL, NULL, NULL}},
{"PB23", 1, 23, {"gpio_in", "gpio_out", "uart0", "ir1", NULL, NULL, NULL, NULL}},
{"PC0", 2, 0, {"gpio_in", "gpio_out", "nand0", "spi0", NULL, NULL, NULL, NULL}},
{"PC1", 2, 1, {"gpio_in", "gpio_out", "nand0", "spi0", NULL, NULL, NULL, NULL}},
{"PC2", 2, 2, {"gpio_in", "gpio_out", "nand0", "spi0", NULL, NULL, NULL, NULL}},
{"PC3", 2, 3, {"gpio_in", "gpio_out", "nand0", NULL, NULL, NULL, NULL, NULL}},
{"PC4", 2, 4, {"gpio_in", "gpio_out", "nand0", NULL, NULL, NULL, NULL, NULL}},
{"PC5", 2, 5, {"gpio_in", "gpio_out", "nand0", "mmc2", NULL, NULL, NULL, NULL}},
{"PC6", 2, 6, {"gpio_in", "gpio_out", "nand0", "mmc2", NULL, NULL, NULL, NULL}},
{"PC7", 2, 7, {"gpio_in", "gpio_out", "nand0", "mmc2", NULL, NULL, NULL, NULL}},
{"PC8", 2, 8, {"gpio_in", "gpio_out", "nand0", "mmc2", NULL, NULL, NULL, NULL}},
{"PC9", 2, 9, {"gpio_in", "gpio_out", "nand0", "mmc2", NULL, NULL, NULL, NULL}},
{"PC10", 2, 10, {"gpio_in", "gpio_out", "nand0", "mmc2", NULL, NULL, NULL, NULL}},
{"PC11", 2, 11, {"gpio_in", "gpio_out", "nand0", "mmc2", NULL, NULL, NULL, NULL}},
{"PC12", 2, 12, {"gpio_in", "gpio_out", "nand0", NULL, NULL, NULL, NULL, NULL}},
{"PC13", 2, 13, {"gpio_in", "gpio_out", "nand0", NULL, NULL, NULL, NULL, NULL}},
{"PC14", 2, 14, {"gpio_in", "gpio_out", "nand0", NULL, NULL, NULL, NULL, NULL}},
{"PC15", 2, 15, {"gpio_in", "gpio_out", "nand0", NULL, NULL, NULL, NULL, NULL}},
{"PC16", 2, 16, {"gpio_in", "gpio_out", "nand0", NULL, NULL, NULL, NULL, NULL}},
{"PC17", 2, 17, {"gpio_in", "gpio_out", "nand0", NULL, NULL, NULL, NULL, NULL}},
{"PC18", 2, 18, {"gpio_in", "gpio_out", "nand0", NULL, NULL, NULL, NULL, NULL}},
{"PC19", 2, 19, {"gpio_in", "gpio_out", "nand0", "spi2", NULL, NULL, "eint", NULL}},
{"PC20", 2, 20, {"gpio_in", "gpio_out", "nand0", "spi2", NULL, NULL, "eint", NULL}},
{"PC21", 2, 21, {"gpio_in", "gpio_out", "nand0", "spi2", NULL, NULL, "eint", NULL}},
{"PC22", 2, 22, {"gpio_in", "gpio_out", "nand0", "spi2", NULL, NULL, "eint", NULL}},
{"PC23", 2, 23, {"gpio_in", "gpio_out", NULL, "spi0", NULL, NULL, NULL, NULL}},
{"PC24", 2, 24, {"gpio_in", "gpio_out", "nand0", NULL, NULL, NULL, NULL, NULL}},
{"PD0", 3, 0, {"gpio_in", "gpio_out", "lcd0", "lvds0", NULL, NULL, NULL, NULL}},
{"PD1", 3, 1, {"gpio_in", "gpio_out", "lcd0", "lvds0", NULL, NULL, NULL, NULL}},
{"PD2", 3, 2, {"gpio_in", "gpio_out", "lcd0", "lvds0", NULL, NULL, NULL, NULL}},
{"PD3", 3, 3, {"gpio_in", "gpio_out", "lcd0", "lvds0", NULL, NULL, NULL, NULL}},
{"PD4", 3, 4, {"gpio_in", "gpio_out", "lcd0", "lvds0", NULL, NULL, NULL, NULL}},
{"PD5", 3, 5, {"gpio_in", "gpio_out", "lcd0", "lvds0", NULL, NULL, NULL, NULL}},
{"PD6", 3, 6, {"gpio_in", "gpio_out", "lcd0", "lvds0", NULL, NULL, NULL, NULL}},
{"PD7", 3, 7, {"gpio_in", "gpio_out", "lcd0", "lvds0", NULL, NULL, NULL, NULL}},
{"PD8", 3, 8, {"gpio_in", "gpio_out", "lcd0", "lvds0", NULL, NULL, NULL, NULL}},
{"PD9", 3, 9, {"gpio_in", "gpio_out", "lcd0", "lvds0", NULL, NULL, NULL, NULL}},
{"PD10", 3, 10, {"gpio_in", "gpio_out", "lcd0", "lvds0", NULL, NULL, NULL, NULL}},
{"PD11", 3, 11, {"gpio_in", "gpio_out", "lcd0", "lvds0", NULL, NULL, NULL, NULL}},
{"PD12", 3, 12, {"gpio_in", "gpio_out", "lcd0", "lvds0", NULL, NULL, NULL, NULL}},
{"PD13", 3, 13, {"gpio_in", "gpio_out", "lcd0", "lvds0", NULL, NULL, NULL, NULL}},
{"PD14", 3, 14, {"gpio_in", "gpio_out", "lcd0", "lvds0", NULL, NULL, NULL, NULL}},
{"PD15", 3, 15, {"gpio_in", "gpio_out", "lcd0", "lvds0", NULL, NULL, NULL, NULL}},
{"PD16", 3, 16, {"gpio_in", "gpio_out", "lcd0", "lvds0", NULL, NULL, NULL, NULL}},
{"PD17", 3, 17, {"gpio_in", "gpio_out", "lcd0", "lvds0", NULL, NULL, NULL, NULL}},
{"PD18", 3, 18, {"gpio_in", "gpio_out", "lcd0", "lvds0", NULL, NULL, NULL, NULL}},
{"PD19", 3, 19, {"gpio_in", "gpio_out", "lcd0", "lvds0", NULL, NULL, NULL, NULL}},
{"PD20", 3, 20, {"gpio_in", "gpio_out", "lcd0", "csi1", NULL, NULL, NULL, NULL}},
{"PD21", 3, 21, {"gpio_in", "gpio_out", "lcd0", "sim", NULL, NULL, NULL, NULL}},
{"PD22", 3, 22, {"gpio_in", "gpio_out", "lcd0", "sim", NULL, NULL, NULL, NULL}},
{"PD23", 3, 23, {"gpio_in", "gpio_out", "lcd0", "sim", NULL, NULL, NULL, NULL}},
{"PD24", 3, 24, {"gpio_in", "gpio_out", "lcd0", "sim", NULL, NULL, NULL, NULL}},
{"PD25", 3, 25, {"gpio_in", "gpio_out", "lcd0", "sim", NULL, NULL, NULL, NULL}},
{"PD26", 3, 26, {"gpio_in", "gpio_out", "lcd0", "sim", NULL, NULL, NULL, NULL}},
{"PD27", 3, 27, {"gpio_in", "gpio_out", "lcd0", "sim", NULL, NULL, NULL, NULL}},
{"PE0", 4, 0, {"gpio_in", "gpio_out", "ts0", "csi0", NULL, NULL, NULL, NULL}},
{"PE1", 4, 1, {"gpio_in", "gpio_out", "ts0", "csi0", NULL, NULL, NULL, NULL}},
{"PE2", 4, 2, {"gpio_in", "gpio_out", "ts0", "csi0", NULL, NULL, NULL, NULL}},
{"PE3", 4, 3, {"gpio_in", "gpio_out", "ts0", "csi0", NULL, NULL, NULL, NULL}},
{"PE4", 4, 4, {"gpio_in", "gpio_out", "ts0", "csi0", NULL, NULL, NULL, NULL}},
{"PE5", 4, 5, {"gpio_in", "gpio_out", "ts0", "csi0", NULL, NULL, NULL, NULL}},
{"PE6", 4, 6, {"gpio_in", "gpio_out", "ts0", "csi0", NULL, NULL, NULL, NULL}},
{"PE7", 4, 7, {"gpio_in", "gpio_out", "ts0", "csi0", NULL, NULL, NULL, NULL}},
{"PE8", 4, 8, {"gpio_in", "gpio_out", "ts0", "csi0", NULL, NULL, NULL, NULL}},
{"PE9", 4, 9, {"gpio_in", "gpio_out", "ts0", "csi0", NULL, NULL, NULL, NULL}},
{"PE10", 4, 10, {"gpio_in", "gpio_out", "ts0", "csi0", NULL, NULL, NULL, NULL}},
{"PE11", 4, 11, {"gpio_in", "gpio_out", "ts0", "csi0", NULL, NULL, NULL, NULL}},
{"PF0", 5, 0, {"gpio_in", "gpio_out", "mmc0", NULL, "jtag", NULL, NULL, NULL}},
{"PF1", 5, 1, {"gpio_in", "gpio_out", "mmc0", NULL, "jtag", NULL, NULL, NULL}},
{"PF2", 5, 2, {"gpio_in", "gpio_out", "mmc0", NULL, "uart0", NULL, NULL, NULL}},
{"PF3", 5, 3, {"gpio_in", "gpio_out", "mmc0", NULL, "jtag", NULL, NULL, NULL}},
{"PF4", 5, 4, {"gpio_in", "gpio_out", "mmc0", NULL, "uart0", NULL, NULL, NULL}},
{"PF5", 5, 5, {"gpio_in", "gpio_out", "mmc0", NULL, "jtag", NULL, NULL, NULL}},
{"PG0", 6, 0, {"gpio_in", "gpio_out", "ts1", "csi1", "mmc1", NULL, NULL, NULL}},
{"PG1", 6, 1, {"gpio_in", "gpio_out", "ts1", "csi1", "mmc1", NULL, NULL, NULL}},
{"PG2", 6, 2, {"gpio_in", "gpio_out", "ts1", "csi1", "mmc1", NULL, NULL, NULL}},
{"PG3", 6, 3, {"gpio_in", "gpio_out", "ts1", "csi1", "mmc1", NULL, NULL, NULL}},
{"PG4", 6, 4, {"gpio_in", "gpio_out", "ts1", "csi1", "mmc1", "csi0", NULL, NULL}},
{"PG5", 6, 5, {"gpio_in", "gpio_out", "ts1", "csi1", "mmc1", "csi0", NULL, NULL}},
{"PG6", 6, 6, {"gpio_in", "gpio_out", "ts1", "csi1", "uart3", "csi0", NULL, NULL}},
{"PG7", 6, 7, {"gpio_in", "gpio_out", "ts1", "csi1", "uart3", "csi0", NULL, NULL}},
{"PG8", 6, 8, {"gpio_in", "gpio_out", "ts1", "csi1", "uart3", "csi0", NULL, NULL}},
{"PG9", 6, 9, {"gpio_in", "gpio_out", "ts1", "csi1", "uart3", "csi0", NULL, NULL}},
{"PG10", 6, 10, {"gpio_in", "gpio_out", "ts1", "csi1", "uart4", "csi0", NULL, NULL}},
{"PG11", 6, 11, {"gpio_in", "gpio_out", "ts1", "csi1", "uart4", "csi0", NULL, NULL}},
{"PH0", 7, 0, {"gpio_in", "gpio_out", "lcd1", NULL, "uart3", NULL, "eint", "csi1"}},
{"PH1", 7, 1, {"gpio_in", "gpio_out", "lcd1", NULL, "uart3", NULL, "eint", "csi1"}},
{"PH2", 7, 2, {"gpio_in", "gpio_out", "lcd1", NULL, "uart3", NULL, "eint", "csi1"}},
{"PH3", 7, 3, {"gpio_in", "gpio_out", "lcd1", NULL, "uart3", NULL, "eint", "csi1"}},
{"PH4", 7, 4, {"gpio_in", "gpio_out", "lcd1", NULL, "uart4", NULL, "eint", "csi1"}},
{"PH5", 7, 5, {"gpio_in", "gpio_out", "lcd1", NULL, "uart4", NULL, "eint", "csi1"}},
{"PH6", 7, 6, {"gpio_in", "gpio_out", "lcd1", NULL, "uart5", "ms", "eint", "csi1"}},
{"PH7", 7, 7, {"gpio_in", "gpio_out", "lcd1", NULL, "uart5", "ms", "eint", "csi1"}},
{"PH8", 7, 8, {"gpio_in", "gpio_out", "lcd1", NULL, "keypad", "ms", "eint", "csi1"}},
{"PH9", 7, 9, {"gpio_in", "gpio_out", "lcd1", NULL, "keypad", "ms", "eint", "csi1"}},
{"PH10", 7, 10, {"gpio_in", "gpio_out", "lcd1", NULL, "keypad", "ms", "eint", "csi1"}},
{"PH11", 7, 11, {"gpio_in", "gpio_out", "lcd1", NULL, "keypad", "ms", "eint", "csi1"}},
{"PH12", 7, 12, {"gpio_in", "gpio_out", "lcd1", NULL, "ps2", NULL, "eint", "csi1"}},
{"PH13", 7, 13, {"gpio_in", "gpio_out", "lcd1", NULL, "ps2", "sim", "eint", "csi1"}},
{"PH14", 7, 14, {"gpio_in", "gpio_out", "lcd1", NULL, "keypad", "sim", "eint", "csi1"}},
{"PH15", 7, 15, {"gpio_in", "gpio_out", "lcd1", NULL, "keypad", "sim", "eint", "csi1"}},
{"PH16", 7, 16, {"gpio_in", "gpio_out", "lcd1", NULL, "keypad", "sim", "eint", "csi1"}},
{"PH17", 7, 17, {"gpio_in", "gpio_out", "lcd1", NULL, "keypad", "sim", "eint", "csi1"}},
{"PH18", 7, 18, {"gpio_in", "gpio_out", "lcd1", NULL, "keypad", "sim", "eint", "csi1"}},
{"PH19", 7, 19, {"gpio_in", "gpio_out", "lcd1", NULL, "keypad", "sim", "eint", "csi1"}},
{"PH20", 7, 20, {"gpio_in", "gpio_out", "lcd1", NULL, "can", NULL, "eint", "csi1"}},
{"PH21", 7, 21, {"gpio_in", "gpio_out", "lcd1", NULL, "can", NULL, "eint", "csi1"}},
{"PH22", 7, 22, {"gpio_in", "gpio_out", "lcd1", NULL, "keypad", "mmc1", NULL, "csi1"}},
{"PH23", 7, 23, {"gpio_in", "gpio_out", "lcd1", NULL, "keypad", "mmc1", NULL, "csi1"}},
{"PH24", 7, 24, {"gpio_in", "gpio_out", "lcd1", NULL, "keypad", "mmc1", NULL, "csi1"}},
{"PH25", 7, 25, {"gpio_in", "gpio_out", "lcd1", NULL, "keypad", "mmc1", NULL, "csi1"}},
{"PH26", 7, 26, {"gpio_in", "gpio_out", "lcd1", NULL, "keypad", "mmc1", NULL, "csi1"}},
{"PH27", 7, 27, {"gpio_in", "gpio_out", "lcd1", NULL, "keypad", "mmc1", NULL, "csi1"}},
{"PI0", 8, 0, {"gpio_in", "gpio_out", NULL, "i2c3", NULL, NULL, NULL, NULL}},
{"PI1", 8, 1, {"gpio_in", "gpio_out", NULL, "i2c3", NULL, NULL, NULL, NULL}},
{"PI2", 8, 2, {"gpio_in", "gpio_out", NULL, "i2c4", NULL, NULL, NULL, NULL}},
{"PI3", 8, 3, {"gpio_in", "gpio_out", "pwm", "i2c4", NULL, NULL, NULL, NULL}},
{"PI4", 8, 4, {"gpio_in", "gpio_out", "mmc3", NULL, NULL, NULL, NULL, NULL}},
{"PI5", 8, 5, {"gpio_in", "gpio_out", "mmc3", NULL, NULL, NULL, NULL, NULL}},
{"PI6", 8, 6, {"gpio_in", "gpio_out", "mmc3", NULL, NULL, NULL, NULL, NULL}},
{"PI7", 8, 7, {"gpio_in", "gpio_out", "mmc3", NULL, NULL, NULL, NULL, NULL}},
{"PI8", 8, 8, {"gpio_in", "gpio_out", "mmc3", NULL, NULL, NULL, NULL, NULL}},
{"PI9", 8, 9, {"gpio_in", "gpio_out", "mmc3", NULL, NULL, NULL, NULL, NULL}},
{"PI10", 8, 10, {"gpio_in", "gpio_out", "spi0", "uart5", NULL, NULL, "eint", NULL}},
{"PI11", 8, 11, {"gpio_in", "gpio_out", "spi0", "uart5", NULL, NULL, "eint", NULL}},
{"PI12", 8, 12, {"gpio_in", "gpio_out", "spi0", "uart6", "clk_out_a", NULL, "eint", NULL}},
{"PI13", 8, 13, {"gpio_in", "gpio_out", "spi0", "uart6", "clk_out_b", NULL, "eint", NULL}},
{"PI14", 8, 14, {"gpio_in", "gpio_out", "spi0", "ps2", "timer4", NULL, "eint", NULL}},
{"PI15", 8, 15, {"gpio_in", "gpio_out", "spi1", "ps2", "timer5", NULL, "eint", NULL}},
{"PI16", 8, 16, {"gpio_in", "gpio_out", "spi1", "uart2", NULL, NULL, "eint", NULL}},
{"PI17", 8, 17, {"gpio_in", "gpio_out", "spi1", "uart2", NULL, NULL, "eint", NULL}},
{"PI18", 8, 18, {"gpio_in", "gpio_out", "spi1", "uart2", NULL, NULL, "eint", NULL}},
{"PI19", 8, 19, {"gpio_in", "gpio_out", "spi1", "uart2", NULL, NULL, "eint", NULL}},
{"PI20", 8, 20, {"gpio_in", "gpio_out", "ps2", "uart7", "hdmi", NULL, NULL, NULL}},
{"PI21", 8, 21, {"gpio_in", "gpio_out", "ps2", "uart7", "hdmi", NULL, NULL, NULL}},
};
const struct allwinner_padconf a20_padconf = {
.npins = sizeof(a20_pins) / sizeof(struct allwinner_pins),
.pins = a20_pins,
};

View File

@ -1,4 +1,5 @@
# $FreeBSD$
arm/allwinner/a20/a20_padconf.c standard
arm/allwinner/a20/a20_mp.c optional smp
arm/allwinner/a20/a20_if_dwc.c optional dwc

View File

@ -75,6 +75,23 @@ a20_attach(platform_t plat)
return (0);
}
static int
a31_attach(platform_t plat)
{
soc_type = ALLWINNERSOC_A31;
soc_family = ALLWINNERSOC_SUN6I;
return (0);
}
static int
a31s_attach(platform_t plat)
{
soc_type = ALLWINNERSOC_A31S;
soc_family = ALLWINNERSOC_SUN6I;
return (0);
}
static vm_offset_t
allwinner_lastaddr(platform_t plat)
@ -138,6 +155,22 @@ static platform_method_t a20_methods[] = {
PLATFORMMETHOD_END,
};
static platform_method_t a31_methods[] = {
PLATFORMMETHOD(platform_attach, a31_attach),
PLATFORMMETHOD(platform_lastaddr, allwinner_lastaddr),
PLATFORMMETHOD(platform_devmap_init, allwinner_devmap_init),
PLATFORMMETHOD_END,
};
static platform_method_t a31s_methods[] = {
PLATFORMMETHOD(platform_attach, a31s_attach),
PLATFORMMETHOD(platform_lastaddr, allwinner_lastaddr),
PLATFORMMETHOD(platform_devmap_init, allwinner_devmap_init),
PLATFORMMETHOD_END,
};
u_int
allwinner_soc_type(void)
{
@ -152,3 +185,5 @@ allwinner_soc_family(void)
FDT_PLATFORM_DEF(a10, "a10", 0, "allwinner,sun4i-a10");
FDT_PLATFORM_DEF(a20, "a20", 0, "allwinner,sun7i-a20");
FDT_PLATFORM_DEF(a31, "a31", 0, "allwinner,sun6i-a31");
FDT_PLATFORM_DEF(a31s, "a31s", 0, "allwinner,sun6i-a31s");

View File

@ -34,9 +34,12 @@
#define ALLWINNERSOC_A13 0x13000000
#define ALLWINNERSOC_A10S 0x10000001
#define ALLWINNERSOC_A20 0x20000000
#define ALLWINNERSOC_A31 0x31000000
#define ALLWINNERSOC_A31S 0x31000001
#define ALLWINNERSOC_SUN4I 0x40000000
#define ALLWINNERSOC_SUN5I 0x50000000
#define ALLWINNERSOC_SUN6I 0x60000000
#define ALLWINNERSOC_SUN7I 0x70000000
u_int allwinner_soc_type(void);

View File

@ -0,0 +1,46 @@
/*-
* Copyright (c) 2016 Emmanuel Vadot <manu@bidouilliste.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef _ALLWINNER_PINCTRL_H_
#define _ALLWINNER_PINCTRL_H_
#define AW_MAX_FUNC_BY_PIN 8
struct allwinner_pins {
const char *name;
uint8_t port;
uint8_t pin;
const char *functions[8];
};
struct allwinner_padconf {
uint32_t npins;
const struct allwinner_pins * pins;
};
#endif /* _ALLWINNER_PINCTRL_H_ */

226
sys/arm/allwinner/axp209.c Normal file
View File

@ -0,0 +1,226 @@
/*-
* Copyright (c) 2015 Emmanuel Vadot <manu@bidouilliste.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* X-Power AXP209 PMU for Allwinner SoCs
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/eventhandler.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/clock.h>
#include <sys/time.h>
#include <sys/bus.h>
#include <sys/proc.h>
#include <sys/reboot.h>
#include <sys/resource.h>
#include <sys/rman.h>
#include <sys/sysctl.h>
#include <dev/iicbus/iicbus.h>
#include <dev/iicbus/iiconf.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#include "iicbus_if.h"
/* Power State Register */
#define AXP209_PSR 0x00
#define AXP209_PSR_ACIN 0x80
#define AXP209_PSR_ACIN_SHIFT 7
#define AXP209_PSR_VBUS 0x20
#define AXP209_PSR_VBUS_SHIFT 5
/* Shutdown and battery control */
#define AXP209_SHUTBAT 0x32
#define AXP209_SHUTBAT_SHUTDOWN 0x80
/* Temperature monitor */
#define AXP209_TEMPMON 0x5e
#define AXP209_TEMPMON_H(a) ((a) << 4)
#define AXP209_TEMPMON_L(a) ((a) & 0xf)
#define AXP209_TEMPMON_MIN 1447 /* -144.7C */
#define AXP209_0C_TO_K 2732
struct axp209_softc {
uint32_t addr;
struct intr_config_hook enum_hook;
};
enum axp209_sensor {
AXP209_TEMP
};
static int
axp209_read(device_t dev, uint8_t reg, uint8_t *data, uint8_t size)
{
struct axp209_softc *sc = device_get_softc(dev);
struct iic_msg msg[2];
msg[0].slave = sc->addr;
msg[0].flags = IIC_M_WR;
msg[0].len = 1;
msg[0].buf = &reg;
msg[1].slave = sc->addr;
msg[1].flags = IIC_M_RD;
msg[1].len = size;
msg[1].buf = data;
return (iicbus_transfer(dev, msg, 2));
}
static int
axp209_write(device_t dev, uint8_t reg, uint8_t data)
{
uint8_t buffer[2];
struct axp209_softc *sc = device_get_softc(dev);
struct iic_msg msg;
buffer[0] = reg;
buffer[1] = data;
msg.slave = sc->addr;
msg.flags = IIC_M_WR;
msg.len = 2;
msg.buf = buffer;
return (iicbus_transfer(dev, &msg, 1));
}
static int
axp209_sysctl(SYSCTL_HANDLER_ARGS)
{
device_t dev = arg1;
enum axp209_sensor sensor = arg2;
uint8_t data[2];
int val, error;
if (sensor != AXP209_TEMP)
return (ENOENT);
error = axp209_read(dev, AXP209_TEMPMON, data, 2);
if (error != 0)
return (error);
/* Temperature is between -144.7C and 264.8C, step +0.1C */
val = (AXP209_TEMPMON_H(data[0]) | AXP209_TEMPMON_L(data[1])) -
AXP209_TEMPMON_MIN + AXP209_0C_TO_K;
return sysctl_handle_opaque(oidp, &val, sizeof(val), req);
}
static void
axp209_shutdown(void *devp, int howto)
{
device_t dev;
if (!(howto & RB_POWEROFF))
return;
dev = (device_t)devp;
if (bootverbose)
device_printf(dev, "Shutdown AXP209\n");
axp209_write(dev, AXP209_SHUTBAT, AXP209_SHUTBAT_SHUTDOWN);
}
static int
axp209_probe(device_t dev)
{
if (!ofw_bus_status_okay(dev))
return (ENXIO);
if (!ofw_bus_is_compatible(dev, "x-powers,axp209"))
return (ENXIO);
device_set_desc(dev, "X-Power AXP209 Power Management Unit");
return (BUS_PROBE_DEFAULT);
}
static int
axp209_attach(device_t dev)
{
struct axp209_softc *sc;
const char *pwr_name[] = {"Battery", "AC", "USB", "AC and USB"};
uint8_t data;
uint8_t pwr_src;
sc = device_get_softc(dev);
sc->addr = iicbus_get_addr(dev);
if (bootverbose) {
/*
* Read the Power State register.
* Shift the AC presence into bit 0.
* Shift the Battery presence into bit 1.
*/
axp209_read(dev, AXP209_PSR, &data, 1);
pwr_src = ((data & AXP209_PSR_ACIN) >> AXP209_PSR_ACIN_SHIFT) |
((data & AXP209_PSR_VBUS) >> (AXP209_PSR_VBUS_SHIFT - 1));
device_printf(dev, "AXP209 Powered by %s\n",
pwr_name[pwr_src]);
}
EVENTHANDLER_REGISTER(shutdown_final, axp209_shutdown, dev,
SHUTDOWN_PRI_LAST);
SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
OID_AUTO, "temp",
CTLTYPE_INT | CTLFLAG_RD,
dev, AXP209_TEMP, axp209_sysctl, "IK", "Internal temperature");
return (0);
}
static device_method_t axp209_methods[] = {
DEVMETHOD(device_probe, axp209_probe),
DEVMETHOD(device_attach, axp209_attach),
{0, 0},
};
static driver_t axp209_driver = {
"axp209_pmu",
axp209_methods,
sizeof(struct axp209_softc),
};
static devclass_t axp209_devclass;
DRIVER_MODULE(axp209, iicbus, axp209_driver, axp209_devclass, 0, 0);
MODULE_VERSION(axp209, 1);
MODULE_DEPEND(axp209, iicbus, 1, 1, 1);

View File

@ -1,4 +1,5 @@
# $FreeBSD$
arm/allwinner/a10_padconf.c standard
arm/allwinner/aintc.c standard
arm/allwinner/timer.c standard

View File

@ -3,7 +3,9 @@ kern/kern_clocksource.c standard
arm/allwinner/a10_ahci.c optional ahci
arm/allwinner/a10_clk.c standard
arm/allwinner/a10_codec.c optional sound
arm/allwinner/a10_common.c standard
arm/allwinner/a10_dmac.c standard
arm/allwinner/a10_ehci.c optional ehci
arm/allwinner/a10_gpio.c optional gpio
arm/allwinner/a10_mmc.c optional mmc
@ -11,5 +13,8 @@ arm/allwinner/a10_sramc.c standard
arm/allwinner/a10_wdog.c standard
arm/allwinner/a20/a20_cpu_cfg.c standard
arm/allwinner/allwinner_machdep.c standard
arm/allwinner/axp209.c optional axp209
arm/allwinner/if_emac.c optional emac
arm/allwinner/sunxi_dma_if.m standard
dev/iicbus/twsi/a10_twsi.c optional twsi
#arm/allwinner/console.c standard

View File

@ -84,7 +84,6 @@ __FBSDID("$FreeBSD$");
#include "a10_clk.h"
#include "a10_sramc.h"
#include "a10_gpio.h"
struct emac_softc {
struct ifnet *emac_ifp;
@ -145,8 +144,6 @@ emac_sys_setup(void)
/* Activate EMAC clock. */
a10_clk_emac_activate();
/* Set the pin mux to EMAC (mii). */
a10_gpio_ethernet_activate(A10_GPIO_FUNC_MII);
/* Map sram. */
a10_map_to_emac();
}

View File

@ -0,0 +1,98 @@
#-
# Copyright (c) 2016 Jared D. McNeill <jmcneill@invisible.ca>
# 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$
#
#include <sys/bus.h>
INTERFACE sunxi_dma;
HEADER {
#include <machine/bus.h>
struct sunxi_dma_config {
unsigned int dst_width;
unsigned int dst_burst_len;
unsigned int dst_drqtype;
bool dst_noincr;
unsigned int dst_blksize; /* DDMA-only */
unsigned int dst_wait_cyc; /* DDMA-only */
unsigned int src_width;
unsigned int src_burst_len;
unsigned int src_drqtype;
bool src_noincr;
unsigned int src_blksize; /* DDMA-only */
unsigned int src_wait_cyc; /* DDMA-only */
};
typedef void (*sunxi_dma_callback)(void *);
}
#
# Allocate DMA channel
#
METHOD void * alloc {
device_t dev;
bool dedicated;
sunxi_dma_callback callback;
void *callback_arg;
};
#
# Free DMA channel
#
METHOD void free {
device_t dev;
void *dmachan;
};
#
# Set DMA channel configuration
#
METHOD int set_config {
device_t dev;
void *dmachan;
const struct sunxi_dma_config *cfg;
};
#
# Start DMA channel transfer
#
METHOD int transfer {
device_t dev;
void *dmachan;
bus_addr_t src;
bus_addr_t dst;
size_t nbytes;
};
#
# Halt DMA channel transfer
#
METHOD void halt {
device_t dev;
void *dmachan;
};

View File

@ -71,8 +71,8 @@ generic_bs_map(bus_space_tag_t t, bus_addr_t bpa, bus_size_t size, int flags,
/*
* We don't even examine the passed-in flags. For ARM, the CACHEABLE
* flag doesn't make sense (we create PTE_DEVICE mappings), and the
* LINEAR flag is just implied because we use kva_alloc(size).
* flag doesn't make sense (we create VM_MEMATTR_DEVICE mappings), and
* the LINEAR flag is just implied because we use kva_alloc(size).
*/
if ((va = pmap_mapdev(bpa, size)) == NULL)
return (ENOMEM);

View File

@ -52,7 +52,6 @@ static boolean_t devmap_bootstrap_done = false;
#if defined(__aarch64__)
#define MAX_VADDR VM_MAX_KERNEL_ADDRESS
#define PTE_DEVICE VM_MEMATTR_DEVICE
#elif defined(__arm__)
#define MAX_VADDR ARM_VECTORS_HIGH
#endif
@ -165,8 +164,6 @@ arm_devmap_add_entry(vm_paddr_t pa, vm_size_t sz)
m->pd_va = akva_devmap_vaddr;
m->pd_pa = pa;
m->pd_size = sz;
m->pd_prot = VM_PROT_READ | VM_PROT_WRITE;
m->pd_cache = PTE_DEVICE;
}
/*
@ -209,10 +206,10 @@ arm_devmap_bootstrap(vm_offset_t l1pt, const struct arm_devmap_entry *table)
#if defined(__arm__)
#if __ARM_ARCH >= 6
pmap_preboot_map_attr(pd->pd_pa, pd->pd_va, pd->pd_size,
pd->pd_prot, pd->pd_cache);
VM_PROT_READ | VM_PROT_WRITE, VM_MEMATTR_DEVICE);
#else
pmap_map_chunk(l1pt, pd->pd_va, pd->pd_pa, pd->pd_size,
pd->pd_prot, pd->pd_cache);
VM_PROT_READ | VM_PROT_WRITE, PTE_DEVICE);
#endif
#elif defined(__aarch64__)
pmap_kenter_device(pd->pd_va, pd->pd_size, pd->pd_pa);
@ -270,7 +267,8 @@ arm_devmap_vtop(void * vpva, vm_size_t size)
* range, otherwise it allocates kva space and maps the physical pages into it.
*
* This routine is intended to be used for mapping device memory, NOT real
* memory; the mapping type is inherently PTE_DEVICE in pmap_kenter_device().
* memory; the mapping type is inherently VM_MEMATTR_DEVICE in
* pmap_kenter_device().
*/
void *
pmap_mapdev(vm_offset_t pa, vm_size_t size)

View File

@ -36,7 +36,7 @@ __FBSDID("$FreeBSD$");
#include <sys/elf32.h>
#include <sys/inflate.h>
#include <machine/elf.h>
#include <machine/pte.h>
#include <machine/pte-v4.h>
#include <machine/cpufunc.h>
#include <machine/armreg.h>

View File

@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <machine/acle-compat.h>
#include <machine/armreg.h>
#include <machine/cpufunc.h>
#include <machine/fiq.h>
@ -73,13 +74,13 @@ fiq_installhandler(void *func, size_t size)
{
const uint32_t fiqvector = 7 * sizeof(uint32_t);
#if !defined(__ARM_FIQ_INDIRECT)
#if __ARM_ARCH < 6 && !defined(__ARM_FIQ_INDIRECT)
vector_page_setprot(VM_PROT_READ|VM_PROT_WRITE);
#endif
memcpy((void *)(vector_page + fiqvector), func, size);
#if !defined(__ARM_FIQ_INDIRECT)
#if __ARM_ARCH < 6 && !defined(__ARM_FIQ_INDIRECT)
vector_page_setprot(VM_PROT_READ);
#endif
icache_sync((vm_offset_t) fiqvector, size);

View File

@ -129,7 +129,9 @@ ASSYM(PC_CURPMAP, offsetof(struct pcpu, pc_curpmap));
#endif
ASSYM(PAGE_SIZE, PAGE_SIZE);
#if __ARM_ARCH < 6
ASSYM(PMAP_DOMAIN_KERNEL, PMAP_DOMAIN_KERNEL);
#endif
#ifdef PMAP_INCLUDE_PTE_SYNC
ASSYM(PMAP_INCLUDE_PTE_SYNC, 1);
#endif

View File

@ -363,6 +363,8 @@ arm_tmr_attach(device_t dev)
if (node > 0) {
error = OF_getencprop(node, "clock-frequency", &clock,
sizeof(clock));
if (error > 0)
sc->clkfreq = clock;
}
#endif

View File

@ -38,7 +38,7 @@
#include <machine/asm.h>
#include <machine/armreg.h>
#include <machine/cpuconf.h>
#include <machine/pte.h>
#include <machine/pte-v4.h>
__FBSDID("$FreeBSD$");

View File

@ -36,7 +36,7 @@
#include <machine/armreg.h>
#include <machine/sysreg.h>
#include <machine/cpuconf.h>
#include <machine/pte.h>
#include <machine/pte-v6.h>
__FBSDID("$FreeBSD$");
@ -280,7 +280,7 @@ ASENTRY_NP(init_mmu)
mcr CP15_CONTEXTIDR(r0) /* Set ASID to 0 */
/* Set the Domain Access register */
mov r0, #((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT)
mov r0, #DOMAIN_CLIENT /* Only domain #0 is used */
mcr CP15_DACR(r0)
/*

View File

@ -85,6 +85,7 @@ static struct resource *nexus_alloc_resource(device_t, device_t, int, int *,
rman_res_t, rman_res_t, rman_res_t, u_int);
static int nexus_activate_resource(device_t, device_t, int, int,
struct resource *);
static bus_space_tag_t nexus_get_bus_tag(device_t, device_t);
#ifdef ARM_INTRNG
#ifdef SMP
static int nexus_bind_intr(device_t, device_t, struct resource *, int);
@ -124,6 +125,7 @@ static device_method_t nexus_methods[] = {
DEVMETHOD(bus_release_resource, nexus_release_resource),
DEVMETHOD(bus_setup_intr, nexus_setup_intr),
DEVMETHOD(bus_teardown_intr, nexus_teardown_intr),
DEVMETHOD(bus_get_bus_tag, nexus_get_bus_tag),
#ifdef ARM_INTRNG
DEVMETHOD(bus_describe_intr, nexus_describe_intr),
#ifdef SMP
@ -260,6 +262,17 @@ nexus_release_resource(device_t bus, device_t child, int type, int rid,
return (rman_release_resource(res));
}
static bus_space_tag_t
nexus_get_bus_tag(device_t bus __unused, device_t child __unused)
{
#ifdef FDT
return(fdtbus_bs_tag);
#else
return((void *)1);
#endif
}
static int
nexus_config_intr(device_t dev, int irq, enum intr_trigger trig,
enum intr_polarity pol)

View File

@ -38,7 +38,7 @@ __FBSDID("$FreeBSD$");
int
OF_decode_addr(phandle_t dev, int regno, bus_space_tag_t *tag,
bus_space_handle_t *handle)
bus_space_handle_t *handle, bus_size_t *sz)
{
bus_addr_t addr;
bus_size_t size;
@ -66,6 +66,10 @@ OF_decode_addr(phandle_t dev, int regno, bus_space_tag_t *tag,
*tag = fdtbus_bs_tag;
flags = 0;
#endif
if (sz != NULL)
*sz = size;
return (bus_space_map(*tag, addr, size, flags, handle));
}

View File

@ -2549,7 +2549,7 @@ pmap_remove_pages(pmap_t pmap)
l2b = pmap_get_l2_bucket(pmap, pv->pv_va);
KASSERT(l2b != NULL, ("No L2 bucket in pmap_remove_pages"));
pt = &l2b->l2b_kva[l2pte_index(pv->pv_va)];
m = PHYS_TO_VM_PAGE(*pt & L2_ADDR_MASK);
m = PHYS_TO_VM_PAGE(*pt & L2_S_FRAME);
KASSERT((vm_offset_t)m >= KERNBASE, ("Trying to access non-existent page va %x pte %x", pv->pv_va, *pt));
*pt = 0;
PTE_SYNC(pt);

View File

@ -1022,6 +1022,7 @@ pmap_preboot_map_attr(vm_paddr_t pa, vm_offset_t va, vm_size_t size,
pt2_entry_t *pte2p;
l2_prot = prot & VM_PROT_WRITE ? PTE2_AP_KRW : PTE2_AP_KR;
l2_prot |= (prot & VM_PROT_EXECUTE) ? PTE2_X : PTE2_NX;
l2_attr = vm_memattr_to_pte2(attr);
l1_prot = ATTR_TO_L1(l2_prot);
l1_attr = ATTR_TO_L1(l2_attr);
@ -1266,13 +1267,6 @@ pmap_kenter_prot_attr(vm_offset_t va, vm_paddr_t pa, uint32_t prot,
pte2_store(pte2p, PTE2_KERN(pa, prot, attr));
}
static __inline void
pmap_kenter_attr(vm_offset_t va, vm_paddr_t pa, int attr)
{
pmap_kenter_prot_attr(va, pa, PTE2_AP_KRW, attr);
}
PMAP_INLINE void
pmap_kenter(vm_offset_t va, vm_paddr_t pa)
{
@ -6313,11 +6307,6 @@ pmap_fault(pmap_t pmap, vm_offset_t far, uint32_t fsr, int idx, bool usermode)
return (KERN_FAILURE);
}
/* !!!! REMOVE !!!! */
void vector_page_setprot(int p)
{
}
#if defined(PMAP_DEBUG)
/*
* Reusing of KVA used in pmap_zero_page function !!!

View File

@ -98,17 +98,6 @@ __FBSDID("$FreeBSD$");
void swi_handler(struct trapframe *);
static __inline void
call_trapsignal(struct thread *td, int sig, u_long code)
{
ksiginfo_t ksi;
ksiginfo_init_trap(&ksi);
ksi.ksi_signo = sig;
ksi.ksi_code = (int)code;
trapsignal(td, &ksi);
}
int
cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa)
{

View File

@ -164,7 +164,7 @@ at91_alloc_resource(device_t dev, device_t child, int type, int *rid,
return (NULL);
if (rle->res)
panic("Resource rid %d type %d already in use", *rid, type);
if (start == 0UL && end == ~0UL) {
if (RMAN_IS_DEFAULT_RANGE(start, end)) {
start = rle->start;
count = ulmax(count, rle->count);
end = ulmax(rle->end, start + count - 1);

View File

@ -128,8 +128,6 @@ const struct arm_devmap_entry at91_devmap[] = {
0xdff00000,
0xfff00000,
0x00100000,
VM_PROT_READ|VM_PROT_WRITE,
PTE_DEVICE,
},
/* There's a notion that we should do the rest of these lazily. */
/*
@ -152,16 +150,12 @@ const struct arm_devmap_entry at91_devmap[] = {
AT91RM92_OHCI_VA_BASE,
AT91RM92_OHCI_BASE,
0x00100000,
VM_PROT_READ|VM_PROT_WRITE,
PTE_DEVICE,
},
{
/* CompactFlash controller. Portion of EBI CS4 1MB */
AT91RM92_CF_VA_BASE,
AT91RM92_CF_BASE,
0x00100000,
VM_PROT_READ|VM_PROT_WRITE,
PTE_DEVICE,
},
/*
* The next two should be good for the 9260, 9261 and 9G20 since
@ -172,16 +166,12 @@ const struct arm_devmap_entry at91_devmap[] = {
AT91SAM9G20_OHCI_VA_BASE,
AT91SAM9G20_OHCI_BASE,
0x00100000,
VM_PROT_READ|VM_PROT_WRITE,
PTE_DEVICE,
},
{
/* EBI CS3 256MB */
AT91SAM9G20_NAND_VA_BASE,
AT91SAM9G20_NAND_BASE,
AT91SAM9G20_NAND_SIZE,
VM_PROT_READ|VM_PROT_WRITE,
PTE_DEVICE,
},
/*
* The next should be good for the 9G45.
@ -191,10 +181,8 @@ const struct arm_devmap_entry at91_devmap[] = {
AT91SAM9G45_OHCI_VA_BASE,
AT91SAM9G45_OHCI_BASE,
0x00100000,
VM_PROT_READ|VM_PROT_WRITE,
PTE_DEVICE,
},
{ 0, 0, 0, 0, 0, }
{ 0, 0, 0, }
};
#ifdef LINUX_BOOT_ABI

View File

@ -280,7 +280,7 @@ pinctrl_alloc_resource(device_t bus, device_t child, int type, int *rid,
* Request for the default allocation with a given rid: use resource
* list stored in the local device info.
*/
if ((start == 0UL) && (end == ~0UL)) {
if (RMAN_IS_DEFAULT_RANGE(start, end)) {
if ((di = device_get_ivars(child)) == NULL)
return (NULL);

View File

@ -104,6 +104,15 @@ __FBSDID("$FreeBSD$");
/* relative offset from BCM_VC_DMA0_BASE (p.39) */
#define BCM_DMA_CH(n) (0x100*(n))
/* channels used by GPU */
#define BCM_DMA_CH_BULK 0
#define BCM_DMA_CH_FAST1 2
#define BCM_DMA_CH_FAST2 3
#define BCM_DMA_CH_GPU_MASK ((1 << BCM_DMA_CH_BULK) | \
(1 << BCM_DMA_CH_FAST1) | \
(1 << BCM_DMA_CH_FAST2))
/* DMA Control Block - 256bit aligned (p.40) */
struct bcm_dma_cb {
uint32_t info; /* Transfer Information */
@ -143,6 +152,7 @@ struct bcm_dma_softc {
};
static struct bcm_dma_softc *bcm_dma_sc = NULL;
static uint32_t bcm_dma_channel_mask;
static void
bcm_dmamap_cb(void *arg, bus_dma_segment_t *segs,
@ -205,16 +215,32 @@ static int
bcm_dma_init(device_t dev)
{
struct bcm_dma_softc *sc = device_get_softc(dev);
uint32_t mask;
uint32_t reg;
struct bcm_dma_ch *ch;
void *cb_virt;
vm_paddr_t cb_phys;
int err;
int i;
/* disable and clear interrupt status */
bus_write_4(sc->sc_mem, BCM_DMA_ENABLE, 0);
bus_write_4(sc->sc_mem, BCM_DMA_INT_STATUS, 0);
/*
* Only channels set in bcm_dma_channel_mask can be controlled by us.
* The others are out of our control as well as the corresponding bits
* in both BCM_DMA_ENABLE and BCM_DMA_INT_STATUS global registers. As
* these registers are RW ones, there is no safe way how to write only
* the bits which can be controlled by us.
*
* Fortunately, after reset, all channels are enabled in BCM_DMA_ENABLE
* register and all statuses are cleared in BCM_DMA_INT_STATUS one.
* Not touching these registers is a trade off between correct
* initialization which does not count on anything and not messing up
* something we have no control over.
*/
reg = bus_read_4(sc->sc_mem, BCM_DMA_ENABLE);
if ((reg & bcm_dma_channel_mask) != bcm_dma_channel_mask)
device_printf(dev, "channels are not enabled\n");
reg = bus_read_4(sc->sc_mem, BCM_DMA_INT_STATUS);
if ((reg & bcm_dma_channel_mask) != 0)
device_printf(dev, "statuses are not cleared\n");
/* Allocate DMA chunks control blocks */
/* p.40 of spec - control block should be 32-bit aligned */
@ -227,7 +253,7 @@ bcm_dma_init(device_t dev)
&sc->sc_dma_tag);
if (err) {
device_printf(dev, "failed allocate DMA tag");
device_printf(dev, "failed allocate DMA tag\n");
return (err);
}
@ -235,6 +261,13 @@ bcm_dma_init(device_t dev)
for (i = 0; i < BCM_DMA_CH_MAX; i++) {
ch = &sc->sc_dma_ch[i];
bzero(ch, sizeof(struct bcm_dma_ch));
ch->ch = i;
ch->flags = BCM_DMA_CH_UNMAP;
if ((bcm_dma_channel_mask & (1 << i)) == 0)
continue;
err = bus_dmamem_alloc(sc->sc_dma_tag, &cb_virt,
BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO,
&ch->dma_map);
@ -263,33 +296,15 @@ bcm_dma_init(device_t dev)
break;
}
bzero(ch, sizeof(struct bcm_dma_ch));
ch->ch = i;
ch->cb = cb_virt;
ch->vc_cb = cb_phys;
ch->intr_func = NULL;
ch->intr_arg = NULL;
ch->flags = BCM_DMA_CH_UNMAP;
ch->flags = BCM_DMA_CH_FREE;
ch->cb->info = INFO_WAIT_RESP;
/* reset DMA engine */
bcm_dma_reset(dev, i);
bus_write_4(sc->sc_mem, BCM_DMA_CS(i), CS_RESET);
}
/* now use DMA2/DMA3 only */
sc->sc_dma_ch[2].flags = BCM_DMA_CH_FREE;
sc->sc_dma_ch[3].flags = BCM_DMA_CH_FREE;
/* enable DMAs */
mask = 0;
for (i = 0; i < BCM_DMA_CH_MAX; i++)
if (sc->sc_dma_ch[i].flags & BCM_DMA_CH_FREE)
mask |= (1 << i);
bus_write_4(sc->sc_mem, BCM_DMA_ENABLE, mask);
return (0);
}
@ -599,8 +614,11 @@ bcm_dma_intr(void *arg)
/* my interrupt? */
cs = bus_read_4(sc->sc_mem, BCM_DMA_CS(ch->ch));
if (!(cs & (CS_INT | CS_ERR)))
if (!(cs & (CS_INT | CS_ERR))) {
device_printf(sc->sc_dev,
"unexpected DMA intr CH=%d, CS=%x\n", ch->ch, cs);
return;
}
/* running? */
if (!(ch->flags & BCM_DMA_CH_USED)) {
@ -651,6 +669,7 @@ static int
bcm_dma_attach(device_t dev)
{
struct bcm_dma_softc *sc = device_get_softc(dev);
phandle_t node;
int rid, err = 0;
int i;
@ -664,6 +683,19 @@ bcm_dma_attach(device_t dev)
sc->sc_intrhand[i] = NULL;
}
/* Get DMA channel mask. */
node = ofw_bus_get_node(sc->sc_dev);
if (OF_getencprop(node, "brcm,dma-channel-mask", &bcm_dma_channel_mask,
sizeof(bcm_dma_channel_mask)) == -1 &&
OF_getencprop(node, "broadcom,channels", &bcm_dma_channel_mask,
sizeof(bcm_dma_channel_mask)) == -1) {
device_printf(dev, "could not get channel mask property\n");
return (ENXIO);
}
/* Mask out channels used by GPU. */
bcm_dma_channel_mask &= ~BCM_DMA_CH_GPU_MASK;
/* DMA0 - DMA14 */
rid = 0;
sc->sc_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
@ -674,6 +706,9 @@ bcm_dma_attach(device_t dev)
/* IRQ DMA0 - DMA11 XXX NOT USE DMA12(spurious?) */
for (rid = 0; rid < BCM_DMA_CH_MAX; rid++) {
if ((bcm_dma_channel_mask & (1 << rid)) == 0)
continue;
sc->sc_irq[rid] = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
RF_ACTIVE);
if (sc->sc_irq[rid] == NULL) {

View File

@ -37,8 +37,6 @@
/* request CH for any nubmer */
#define BCM_DMA_CH_INVALID (-1)
#define BCM_DMA_CH_ANY (-1)
#define BCM_DMA_CH_FAST1 (2)
#define BCM_DMA_CH_FAST2 (3)
/* Peripheral DREQ Signals (4.2.1.3) */
#define BCM_DMA_DREQ_NONE 0

View File

@ -214,11 +214,7 @@ bcm_sdhci_attach(device_t dev)
sdhci_init_slot(dev, &sc->sc_slot, 0);
sc->sc_dma_ch = bcm_dma_allocate(BCM_DMA_CH_FAST1);
if (sc->sc_dma_ch == BCM_DMA_CH_INVALID)
sc->sc_dma_ch = bcm_dma_allocate(BCM_DMA_CH_FAST2);
if (sc->sc_dma_ch == BCM_DMA_CH_INVALID)
sc->sc_dma_ch = bcm_dma_allocate(BCM_DMA_CH_ANY);
sc->sc_dma_ch = bcm_dma_allocate(BCM_DMA_CH_ANY);
if (sc->sc_dma_ch == BCM_DMA_CH_INVALID)
goto fail;

View File

@ -425,7 +425,7 @@ econa_alloc_resource(device_t dev, device_t child, int type, int *rid,
}
if (rle->res)
panic("Resource rid %d type %d already in use", *rid, type);
if (start == 0UL && end == ~0UL) {
if (RMAN_IS_DEFAULT_RANGE(start, end)) {
start = rle->start;
count = ulmax(count, rle->count);
end = ulmax(rle->end, start + count - 1);

View File

@ -113,8 +113,6 @@ static const struct arm_devmap_entry econa_devmap[] = {
ECONA_SDRAM_BASE, /*virtual*/
ECONA_SDRAM_BASE, /*physical*/
ECONA_SDRAM_SIZE, /*size*/
VM_PROT_READ|VM_PROT_WRITE,
PTE_DEVICE,
},
/*
* Map the on-board devices VA == PA so that we can access them
@ -128,8 +126,6 @@ static const struct arm_devmap_entry econa_devmap[] = {
ECONA_IO_BASE, /*virtual*/
ECONA_IO_BASE, /*physical*/
ECONA_IO_SIZE, /*size*/
VM_PROT_READ|VM_PROT_WRITE,
PTE_DEVICE,
},
{
/*
@ -138,8 +134,6 @@ static const struct arm_devmap_entry econa_devmap[] = {
ECONA_OHCI_VBASE, /*virtual*/
ECONA_OHCI_PBASE, /*physical*/
ECONA_USB_SIZE, /*size*/
VM_PROT_READ|VM_PROT_WRITE,
PTE_DEVICE,
},
{
/*
@ -148,15 +142,11 @@ static const struct arm_devmap_entry econa_devmap[] = {
ECONA_CFI_VBASE, /*virtual*/
ECONA_CFI_PBASE, /*physical*/
ECONA_CFI_SIZE,
VM_PROT_READ|VM_PROT_WRITE,
PTE_DEVICE,
},
{
0,
0,
0,
0,
0,
}
};

Some files were not shown because too many files have changed in this diff Show More