MFhead @ r305013
This commit is contained in:
commit
763f573683
@ -59,7 +59,7 @@ translator psinfo_t < struct proc *T > {
|
||||
pr_gid = T->p_ucred->cr_rgid;
|
||||
pr_egid = T->p_ucred->cr_groups[0];
|
||||
pr_addr = 0;
|
||||
pr_psargs = (T->p_args->ar_args == 0) ? "" :
|
||||
pr_psargs = (T->p_args == 0) ? "" :
|
||||
memstr(T->p_args->ar_args, ' ', T->p_args->ar_length);
|
||||
pr_arglen = T->p_args->ar_length;
|
||||
pr_jailid = T->p_ucred->cr_prison->pr_id;
|
||||
|
@ -108,6 +108,12 @@ public:
|
||||
* \brief No-op copy constructor for nonexistent vdevs.
|
||||
*/
|
||||
Vdev();
|
||||
|
||||
/**
|
||||
* \brief No-op virtual destructor, since this class has virtual
|
||||
* functions.
|
||||
*/
|
||||
virtual ~Vdev();
|
||||
bool DoesNotExist() const;
|
||||
|
||||
/**
|
||||
@ -145,6 +151,10 @@ private:
|
||||
extern Vdev NonexistentVdev;
|
||||
|
||||
//- Vdev Inline Public Methods ------------------------------------------------
|
||||
inline Vdev::~Vdev()
|
||||
{
|
||||
}
|
||||
|
||||
inline DevdCtl::Guid
|
||||
Vdev::PoolGUID() const
|
||||
{
|
||||
|
@ -12,7 +12,11 @@
|
||||
#define __OPTS_H__
|
||||
|
||||
#ifndef SOLARIS
|
||||
#define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
|
||||
# if defined(sun) && (defined(__svr4__) || defined(__SVR4))
|
||||
# define SOLARIS 1
|
||||
# else
|
||||
# define SOLARIS 0
|
||||
# endif
|
||||
#endif
|
||||
#define OPT_REMOVE 0x000001
|
||||
#define OPT_DEBUG 0x000002
|
||||
|
@ -1128,8 +1128,15 @@ header_common(struct archive_read *a, struct tar *tar,
|
||||
if (tar->entry_bytes_remaining < 0) {
|
||||
tar->entry_bytes_remaining = 0;
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Tar entry has negative size?");
|
||||
err = ARCHIVE_WARN;
|
||||
"Tar entry has negative size");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
if (tar->entry_bytes_remaining == INT64_MAX) {
|
||||
/* Note: tar_atol returns INT64_MAX on overflow */
|
||||
tar->entry_bytes_remaining = 0;
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Tar entry size overflow");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
tar->realsize = tar->entry_bytes_remaining;
|
||||
archive_entry_set_size(entry, tar->entry_bytes_remaining);
|
||||
|
@ -418,18 +418,30 @@ zip_time(const char *p)
|
||||
* id1+size1+data1 + id2+size2+data2 ...
|
||||
* triplets. id and size are 2 bytes each.
|
||||
*/
|
||||
static void
|
||||
process_extra(const char *p, size_t extra_length, struct zip_entry* zip_entry)
|
||||
static int
|
||||
process_extra(struct archive_read *a, const char *p, size_t extra_length, struct zip_entry* zip_entry)
|
||||
{
|
||||
unsigned offset = 0;
|
||||
|
||||
while (offset < extra_length - 4) {
|
||||
if (extra_length == 0) {
|
||||
return ARCHIVE_OK;
|
||||
}
|
||||
|
||||
if (extra_length < 4) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Too-small extra data: Need at least 4 bytes, but only found %d bytes", (int)extra_length);
|
||||
return ARCHIVE_FAILED;
|
||||
}
|
||||
while (offset <= extra_length - 4) {
|
||||
unsigned short headerid = archive_le16dec(p + offset);
|
||||
unsigned short datasize = archive_le16dec(p + offset + 2);
|
||||
|
||||
offset += 4;
|
||||
if (offset + datasize > extra_length) {
|
||||
break;
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Extra data overflow: Need %d bytes but only found %d bytes",
|
||||
(int)datasize, (int)(extra_length - offset));
|
||||
return ARCHIVE_FAILED;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "Header id 0x%04x, length %d\n",
|
||||
@ -715,13 +727,13 @@ process_extra(const char *p, size_t extra_length, struct zip_entry* zip_entry)
|
||||
}
|
||||
offset += datasize;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if (offset != extra_length)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Extra data field contents do not match reported size!\n");
|
||||
if (offset != extra_length) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Malformed extra data: Consumed %d bytes of %d bytes",
|
||||
(int)offset, (int)extra_length);
|
||||
return ARCHIVE_FAILED;
|
||||
}
|
||||
#endif
|
||||
return ARCHIVE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -840,7 +852,9 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
process_extra(h, extra_length, zip_entry);
|
||||
if (ARCHIVE_OK != process_extra(a, h, extra_length, zip_entry)) {
|
||||
return ARCHIVE_FATAL;
|
||||
}
|
||||
__archive_read_consume(a, extra_length);
|
||||
|
||||
/* Work around a bug in Info-Zip: When reading from a pipe, it
|
||||
@ -1293,7 +1307,7 @@ zip_read_data_deflate(struct archive_read *a, const void **buff,
|
||||
&& bytes_avail > zip->entry_bytes_remaining) {
|
||||
bytes_avail = (ssize_t)zip->entry_bytes_remaining;
|
||||
}
|
||||
if (bytes_avail <= 0) {
|
||||
if (bytes_avail < 0) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Truncated ZIP file body");
|
||||
return (ARCHIVE_FATAL);
|
||||
@ -2691,7 +2705,9 @@ slurp_central_directory(struct archive_read *a, struct zip *zip)
|
||||
"Truncated ZIP file header");
|
||||
return ARCHIVE_FATAL;
|
||||
}
|
||||
process_extra(p + filename_length, extra_length, zip_entry);
|
||||
if (ARCHIVE_OK != process_extra(a, p + filename_length, extra_length, zip_entry)) {
|
||||
return ARCHIVE_FATAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Mac resource fork files are stored under the
|
||||
|
@ -138,6 +138,7 @@ set_acl(struct archive *a, int fd, const char *name,
|
||||
acl_permset_t acl_permset;
|
||||
#ifdef ACL_TYPE_NFS4
|
||||
acl_flagset_t acl_flagset;
|
||||
int r;
|
||||
#endif
|
||||
int ret;
|
||||
int ae_type, ae_permset, ae_tag, ae_id;
|
||||
@ -145,7 +146,7 @@ set_acl(struct archive *a, int fd, const char *name,
|
||||
gid_t ae_gid;
|
||||
const char *ae_name;
|
||||
int entries;
|
||||
int i, r;
|
||||
int i;
|
||||
|
||||
ret = ARCHIVE_OK;
|
||||
entries = archive_acl_reset(abstract_acl, ae_requested_type);
|
||||
|
@ -2401,8 +2401,18 @@ check_symlinks(struct archive_write_disk *a)
|
||||
r = lstat(a->name, &st);
|
||||
if (r != 0) {
|
||||
/* We've hit a dir that doesn't exist; stop now. */
|
||||
if (errno == ENOENT)
|
||||
if (errno == ENOENT) {
|
||||
break;
|
||||
} else {
|
||||
/* Note: This effectively disables deep directory
|
||||
* support when security checks are enabled.
|
||||
* Otherwise, very long pathnames that trigger
|
||||
* an error here could evade the sandbox.
|
||||
* TODO: We could do better, but it would probably
|
||||
* require merging the symlink checks with the
|
||||
* deep-directory editing. */
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
} else if (S_ISLNK(st.st_mode)) {
|
||||
if (c == '\0') {
|
||||
/*
|
||||
|
@ -182,7 +182,7 @@ safe_fprintf(FILE *f, const char *fmt, ...)
|
||||
}
|
||||
|
||||
/* If our output buffer is full, dump it and keep going. */
|
||||
if (i > (sizeof(outbuff) - 20)) {
|
||||
if (i > (sizeof(outbuff) - 128)) {
|
||||
outbuff[i] = '\0';
|
||||
fprintf(f, "%s", outbuff);
|
||||
i = 0;
|
||||
|
@ -94,7 +94,7 @@ struct speed {
|
||||
int sp; /* the actual speed */
|
||||
};
|
||||
|
||||
#define DATA(number) { B##number, number }
|
||||
#define DATA(number) { (NCURSES_OSPEED)B##number, number }
|
||||
|
||||
static struct speed const speeds[] =
|
||||
{
|
||||
|
@ -32,6 +32,9 @@ basic_head()
|
||||
}
|
||||
basic_body()
|
||||
{
|
||||
# Begin FreeBSD
|
||||
atf_tc_expect_fail "dirname //usr//bin doesn't return //usr like it used to; bug # 212193"
|
||||
# End FreeBSD
|
||||
atf_check -o inline:"/\n" dirname /
|
||||
atf_check -o inline:"/\n" dirname //
|
||||
atf_check -o inline:"/usr\n" dirname /usr/bin/
|
||||
|
@ -392,11 +392,9 @@ int c4iw_post_send(struct ibv_qp *ibqp, struct ibv_send_wr *wr,
|
||||
t4_sq_produce(&qhp->wq, len16);
|
||||
idx += DIV_ROUND_UP(len16*16, T4_EQ_ENTRY_SIZE);
|
||||
}
|
||||
if (t4_wq_db_enabled(&qhp->wq)) {
|
||||
t4_ring_sq_db(&qhp->wq, idx, dev_is_t5(qhp->rhp),
|
||||
len16, wqe);
|
||||
} else
|
||||
ring_kernel_db(qhp, qhp->wq.sq.qid, idx);
|
||||
|
||||
t4_ring_sq_db(&qhp->wq, idx, dev_is_t5(qhp->rhp),
|
||||
len16, wqe);
|
||||
qhp->wq.sq.queue[qhp->wq.sq.size].status.host_wq_pidx = \
|
||||
(qhp->wq.sq.wq_pidx);
|
||||
pthread_spin_unlock(&qhp->lock);
|
||||
@ -458,11 +456,9 @@ int c4iw_post_receive(struct ibv_qp *ibqp, struct ibv_recv_wr *wr,
|
||||
wr = wr->next;
|
||||
num_wrs--;
|
||||
}
|
||||
if (t4_wq_db_enabled(&qhp->wq))
|
||||
t4_ring_rq_db(&qhp->wq, idx, dev_is_t5(qhp->rhp),
|
||||
len16, wqe);
|
||||
else
|
||||
ring_kernel_db(qhp, qhp->wq.rq.qid, idx);
|
||||
|
||||
t4_ring_rq_db(&qhp->wq, idx, dev_is_t5(qhp->rhp),
|
||||
len16, wqe);
|
||||
qhp->wq.rq.queue[qhp->wq.rq.size].status.host_wq_pidx = \
|
||||
(qhp->wq.rq.wq_pidx);
|
||||
pthread_spin_unlock(&qhp->lock);
|
||||
|
@ -39,4 +39,23 @@ char *basename_r(const char *, char *);
|
||||
char *dirname(char *);
|
||||
__END_DECLS
|
||||
|
||||
/*
|
||||
* In FreeBSD 12, the prototype of dirname() was modified to comply to
|
||||
* POSIX. This function may now modify its input. Unfortunately, our
|
||||
* copy of xinstall(8) shipped with previous versions of FreeBSD is
|
||||
* built using the host headers and libc during the bootstrapping phase
|
||||
* and depends on the old behavior.
|
||||
*
|
||||
* Apply a workaround where we explicitly link against dirname@FBSD_1.0
|
||||
* in case this function is called on constant strings, instead of
|
||||
* making the build fail.
|
||||
*/
|
||||
#if defined(__generic) && !defined(__cplusplus)
|
||||
__BEGIN_DECLS
|
||||
char *__old_dirname(const char *);
|
||||
__END_DECLS
|
||||
__sym_compat(dirname, __old_dirname, FBSD_1.0);
|
||||
#define dirname(x) __generic(x, const char *, __old_dirname, dirname)(x)
|
||||
#endif
|
||||
|
||||
#endif /* !_LIBGEN_H_ */
|
||||
|
@ -211,8 +211,6 @@ TESTS_SRCS= \
|
||||
test_write_disk_perms.c \
|
||||
test_write_disk_secure.c \
|
||||
test_write_disk_secure744.c \
|
||||
test_write_disk_secure745.c \
|
||||
test_write_disk_secure746.c \
|
||||
test_write_disk_sparse.c \
|
||||
test_write_disk_symlink.c \
|
||||
test_write_disk_times.c \
|
||||
|
@ -4,7 +4,7 @@
|
||||
SRCS+= amd64_get_fsbase.c amd64_get_gsbase.c amd64_set_fsbase.c \
|
||||
amd64_set_gsbase.c
|
||||
|
||||
MDASM= vfork.S brk.S cerror.S exect.S getcontext.S ptrace.S \
|
||||
MDASM= vfork.S brk.S cerror.S exect.S getcontext.S \
|
||||
sbrk.S setlogin.S sigreturn.S
|
||||
|
||||
# Don't generate default code for these syscalls:
|
||||
|
@ -1,55 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1990 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* William Jolitz.
|
||||
*
|
||||
* 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.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*/
|
||||
|
||||
#if defined(SYSLIBC_SCCS) && !defined(lint)
|
||||
.asciz "@(#)ptrace.s 5.1 (Berkeley) 4/23/90"
|
||||
#endif /* SYSLIBC_SCCS and not lint */
|
||||
#include <machine/asm.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "SYS.h"
|
||||
|
||||
ENTRY(ptrace)
|
||||
xorl %eax,%eax
|
||||
#ifdef PIC
|
||||
movq PIC_GOT(CNAME(errno)),%r8
|
||||
movl %eax,(%r8)
|
||||
#else
|
||||
movl %eax,CNAME(errno)(%rip)
|
||||
#endif
|
||||
mov $SYS_ptrace,%eax
|
||||
KERNCALL
|
||||
jb HIDENAME(cerror)
|
||||
ret
|
||||
END(ptrace)
|
||||
|
||||
.section .note.GNU-stack,"",%progbits
|
@ -2,7 +2,7 @@
|
||||
|
||||
SRCS+= __vdso_gettc.c
|
||||
|
||||
MDASM= Ovfork.S brk.S cerror.S ptrace.S sbrk.S shmat.S sigreturn.S syscall.S
|
||||
MDASM= Ovfork.S brk.S cerror.S sbrk.S shmat.S sigreturn.S syscall.S
|
||||
|
||||
# Don't generate default code for these syscalls:
|
||||
NOASM= break.o exit.o getlogin.o sstk.o vfork.o yield.o
|
||||
|
@ -1,51 +0,0 @@
|
||||
/* $NetBSD: ptrace.S,v 1.7 2003/08/07 16:42:04 agc Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1990 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*
|
||||
* from: @(#)ptrace.s 5.1 (Berkeley) 4/23/90
|
||||
*/
|
||||
|
||||
#include <machine/asm.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
#include "SYS.h"
|
||||
|
||||
ENTRY(ptrace)
|
||||
stmfd sp!, {r0-r3, lr}
|
||||
sub sp, sp, #4 /* align stack */
|
||||
bl PIC_SYM(_C_LABEL(__error), PLT)
|
||||
add sp, sp, #4 /* unalign stack */
|
||||
mov r1, #0x00000000
|
||||
str r1, [r0]
|
||||
ldmfd sp!, {r0-r3, lr}
|
||||
SYSTRAP(ptrace)
|
||||
bcs PIC_SYM(CERROR, PLT)
|
||||
RET
|
||||
END(ptrace)
|
||||
|
||||
.section .note.GNU-stack,"",%progbits
|
@ -31,7 +31,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <string.h>
|
||||
|
||||
char *
|
||||
dirname(char *path)
|
||||
(dirname)(char *path)
|
||||
{
|
||||
const char *in, *prev, *begin, *end;
|
||||
char *out;
|
||||
|
@ -7,7 +7,7 @@ SRCS+= i386_clr_watch.c i386_set_watch.c i386_vm86.c
|
||||
SRCS+= i386_get_fsbase.c i386_get_gsbase.c i386_get_ioperm.c i386_get_ldt.c \
|
||||
i386_set_fsbase.c i386_set_gsbase.c i386_set_ioperm.c i386_set_ldt.c
|
||||
|
||||
MDASM= Ovfork.S brk.S cerror.S exect.S getcontext.S ptrace.S \
|
||||
MDASM= Ovfork.S brk.S cerror.S exect.S getcontext.S \
|
||||
sbrk.S setlogin.S sigreturn.S syscall.S
|
||||
|
||||
# Don't generate default code for these syscalls:
|
||||
|
@ -1,57 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1990 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* William Jolitz.
|
||||
*
|
||||
* 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.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*/
|
||||
|
||||
#if defined(SYSLIBC_SCCS) && !defined(lint)
|
||||
.asciz "@(#)ptrace.s 5.1 (Berkeley) 4/23/90"
|
||||
#endif /* SYSLIBC_SCCS and not lint */
|
||||
#include <machine/asm.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "SYS.h"
|
||||
|
||||
ENTRY(ptrace)
|
||||
xorl %eax,%eax
|
||||
#ifdef PIC
|
||||
PIC_PROLOGUE
|
||||
movl PIC_GOT(CNAME(errno)),%edx
|
||||
movl %eax,(%edx)
|
||||
PIC_EPILOGUE
|
||||
#else
|
||||
movl %eax,CNAME(errno)
|
||||
#endif
|
||||
mov $SYS_ptrace,%eax
|
||||
KERNCALL
|
||||
jb HIDENAME(cerror)
|
||||
ret
|
||||
END(ptrace)
|
||||
|
||||
.section .note.GNU-stack,"",%progbits
|
@ -335,6 +335,7 @@ int __sys_openat(int, const char *, int, ...);
|
||||
int __sys_pselect(int, struct fd_set *, struct fd_set *,
|
||||
struct fd_set *, const struct timespec *,
|
||||
const __sigset_t *);
|
||||
int __sys_ptrace(int, __pid_t, char *, int);
|
||||
int __sys_poll(struct pollfd *, unsigned, int);
|
||||
int __sys_ppoll(struct pollfd *, unsigned, const struct timespec *,
|
||||
const __sigset_t *);
|
||||
|
@ -3,7 +3,7 @@
|
||||
SRCS+= trivial-vdso_tc.c
|
||||
|
||||
MDASM= Ovfork.S brk.S cerror.S exect.S \
|
||||
ptrace.S sbrk.S syscall.S
|
||||
sbrk.S syscall.S
|
||||
|
||||
# Don't generate default code for these syscalls:
|
||||
NOASM= break.o exit.o getlogin.o sstk.o vfork.o yield.o
|
||||
|
@ -1,71 +0,0 @@
|
||||
/* $NetBSD: ptrace.S,v 1.9 2003/08/07 16:42:17 agc Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Ralph Campbell.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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 <machine/asm.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
#include "SYS.h"
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
ASMSTR("from: @(#)ptrace.s 8.1 (Berkeley) 6/4/93")
|
||||
ASMSTR("$NetBSD: ptrace.S,v 1.9 2003/08/07 16:42:17 agc Exp $")
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
NESTED_NOPROFILE(ptrace, CALLFRAME_SIZ, ra)
|
||||
.mask 0x80000000, (CALLFRAME_RA - CALLFRAME_SIZ)
|
||||
SETUP_GP
|
||||
PTR_SUBU sp, sp, CALLFRAME_SIZ
|
||||
SETUP_GP64(CALLFRAME_GP, ptrace)
|
||||
SAVE_GP(CALLFRAME_GP)
|
||||
|
||||
PTR_S ra, CALLFRAME_RA(sp)
|
||||
|
||||
PTR_LA t9, _C_LABEL(__error) # locate address of errno
|
||||
jalr t9
|
||||
|
||||
PTR_L ra, CALLFRAME_RA(sp)
|
||||
INT_S zero, 0(v0) # update errno value
|
||||
|
||||
li v0, SYS_ptrace
|
||||
syscall
|
||||
|
||||
# Load __cerror's address using our gp, then restore it.
|
||||
PTR_LA t9, __cerror
|
||||
RESTORE_GP64
|
||||
PTR_ADDU sp, sp, CALLFRAME_SIZ
|
||||
|
||||
bne a3, zero, 1f
|
||||
|
||||
j ra
|
||||
1: j t9
|
||||
END(ptrace)
|
@ -224,6 +224,7 @@ struct ai_order {
|
||||
struct policyqueue *aio_dstpolicy;
|
||||
struct addrinfo *aio_ai;
|
||||
int aio_matchlen;
|
||||
int aio_initial_sequence;
|
||||
};
|
||||
|
||||
static const ns_src default_dns_files[] = {
|
||||
@ -708,6 +709,7 @@ reorder(struct addrinfo *sentinel)
|
||||
aio[i].aio_dstpolicy = match_addrselectpolicy(ai->ai_addr,
|
||||
&policyhead);
|
||||
set_source(&aio[i], &policyhead);
|
||||
aio[i].aio_initial_sequence = i;
|
||||
}
|
||||
|
||||
/* perform sorting. */
|
||||
@ -1066,6 +1068,23 @@ comp_dst(const void *arg1, const void *arg2)
|
||||
}
|
||||
|
||||
/* Rule 10: Otherwise, leave the order unchanged. */
|
||||
|
||||
/*
|
||||
* Note that qsort is unstable; so, we can't return zero and
|
||||
* expect the order to be unchanged.
|
||||
* That also means we can't depend on the current position of
|
||||
* dst2 being after dst1. We must enforce the initial order
|
||||
* with an explicit compare on the original position.
|
||||
* The qsort specification requires that "When the same objects
|
||||
* (consisting of width bytes, irrespective of their current
|
||||
* positions in the array) are passed more than once to the
|
||||
* comparison function, the results shall be consistent with one
|
||||
* another."
|
||||
* In other words, If A < B, then we must also return B > A.
|
||||
*/
|
||||
if (dst2->aio_initial_sequence < dst1->aio_initial_sequence)
|
||||
return(1);
|
||||
|
||||
return(-1);
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
# $FreeBSD$
|
||||
|
||||
MDASM+= brk.S cerror.S exect.S ptrace.S sbrk.S setlogin.S
|
||||
MDASM+= brk.S cerror.S exect.S sbrk.S setlogin.S
|
||||
|
||||
# Don't generate default code for these syscalls:
|
||||
NOASM= break.o exit.o getlogin.o sstk.o yield.o
|
||||
|
@ -1,61 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2002 Peter Grehan.
|
||||
* 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.
|
||||
*/
|
||||
/* $NetBSD: ptrace.S,v 1.3 2000/02/23 20:16:57 kleink Exp $ */
|
||||
|
||||
#include <machine/asm.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "SYS.h"
|
||||
|
||||
ENTRY(ptrace)
|
||||
mflr %r0
|
||||
stwu %r1,-32(%r1)
|
||||
stw %r0,36(%r1)
|
||||
stw %r3,8(%r1)
|
||||
stw %r4,12(%r1)
|
||||
stw %r5,16(%r1)
|
||||
stw %r6,20(%r1)
|
||||
|
||||
bl PIC_PLT(CNAME(__error))
|
||||
li %r7,0
|
||||
stw %r7,0(%r3)
|
||||
|
||||
lwz %r3,8(%r1)
|
||||
lwz %r4,12(%r1)
|
||||
lwz %r5,16(%r1)
|
||||
lwz %r0,36(%r1)
|
||||
lwz %r6,20(%r1)
|
||||
mtlr %r0
|
||||
la %r1,32(%r1)
|
||||
li %r0,SYS_ptrace
|
||||
sc
|
||||
bso 1f
|
||||
blr
|
||||
1:
|
||||
b PIC_PLT(HIDENAME(cerror))
|
||||
END(ptrace)
|
||||
|
||||
.section .note.GNU-stack,"",%progbits
|
@ -1,6 +1,6 @@
|
||||
# $FreeBSD$
|
||||
|
||||
MDASM+= brk.S cerror.S exect.S ptrace.S sbrk.S setlogin.S
|
||||
MDASM+= brk.S cerror.S exect.S sbrk.S setlogin.S
|
||||
|
||||
# Don't generate default code for these syscalls:
|
||||
NOASM= break.o exit.o getlogin.o sstk.o yield.o
|
||||
|
@ -12,7 +12,7 @@ SRCS+= __sparc_sigtramp_setup.c \
|
||||
|
||||
CFLAGS+= -I${LIBC_SRCTOP}/sparc64/fpu
|
||||
|
||||
MDASM+= brk.S cerror.S exect.S ptrace.S sbrk.S setlogin.S sigaction1.S
|
||||
MDASM+= brk.S cerror.S exect.S sbrk.S setlogin.S sigaction1.S
|
||||
|
||||
# Don't generate default code for these syscalls:
|
||||
NOASM= break.o exit.o getlogin.o sstk.o yield.o
|
||||
|
@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This software was developed by the Computer Systems Engineering group
|
||||
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
|
||||
* contributed to Berkeley.
|
||||
*
|
||||
* 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.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*
|
||||
* from: Header: ptrace.s,v 1.2 91/12/20 01:59:00 leres Exp
|
||||
* from: NetBSD: ptrace.S,v 1.4 2000/07/24 00:11:10 mycroft Exp
|
||||
*/
|
||||
|
||||
#if defined(SYSLIBC_SCCS) && !defined(lint)
|
||||
.asciz "@(#)ptrace.s 8.1 (Berkeley) 6/4/93"
|
||||
#if 0
|
||||
RCSID("$NetBSD: ptrace.S,v 1.4 2000/07/24 00:11:10 mycroft Exp $")
|
||||
#endif
|
||||
#endif /* SYSLIBC_SCCS and not lint */
|
||||
#include <machine/asm.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "SYS.h"
|
||||
|
||||
_SYSENTRY(ptrace)
|
||||
save %sp, -CCFSZ, %sp
|
||||
call CNAME(__error)
|
||||
nop
|
||||
stw %g0, [%o0]
|
||||
restore
|
||||
_SYSCALL(ptrace)
|
||||
retl
|
||||
nop
|
||||
_SYSEND(ptrace)
|
@ -139,8 +139,11 @@ fgetln(FILE *fp, size_t *lenp)
|
||||
(void)memcpy((void *)(fp->_lb._base + off), (void *)fp->_p,
|
||||
len - off);
|
||||
off = len;
|
||||
if (__srefill(fp))
|
||||
break; /* EOF or error: return partial line */
|
||||
if (__srefill(fp)) {
|
||||
if (__sfeof(fp))
|
||||
break;
|
||||
goto error;
|
||||
}
|
||||
if ((p = memchr((void *)fp->_p, '\n', (size_t)fp->_r)) == NULL)
|
||||
continue;
|
||||
|
||||
|
@ -53,7 +53,6 @@ fgetwln_l(FILE * __restrict fp, size_t *lenp, locale_t locale)
|
||||
ORIENT(fp, 1);
|
||||
|
||||
len = 0;
|
||||
/* WEOF or error: return partial line, see fgetln(3). */
|
||||
while ((wc = __fgetwc(fp, locale)) != WEOF) {
|
||||
#define GROW 512
|
||||
if (len * sizeof(wchar_t) >= fp->_lb._size &&
|
||||
@ -65,7 +64,7 @@ fgetwln_l(FILE * __restrict fp, size_t *lenp, locale_t locale)
|
||||
if (wc == L'\n')
|
||||
break;
|
||||
}
|
||||
if (len == 0)
|
||||
if (len == 0 || (wc == WEOF && !__sfeof(fp)))
|
||||
goto error;
|
||||
|
||||
FUNLOCKFILE(fp);
|
||||
|
@ -48,6 +48,7 @@ INTERPOSED = \
|
||||
poll \
|
||||
ppoll \
|
||||
pselect \
|
||||
ptrace \
|
||||
read \
|
||||
readv \
|
||||
recvfrom \
|
||||
|
@ -2,7 +2,7 @@
|
||||
.\" $NetBSD: ptrace.2,v 1.2 1995/02/27 12:35:37 cgd Exp $
|
||||
.\"
|
||||
.\" This file is in the public domain.
|
||||
.Dd July 28, 2016
|
||||
.Dd August 28, 2016
|
||||
.Dt PTRACE 2
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -906,7 +906,13 @@ to return
|
||||
\-1
|
||||
as a non-error value; to disambiguate,
|
||||
.Va errno
|
||||
can be set to 0 before the call and checked afterwards.
|
||||
is set to 0 in the libc wrapper for the
|
||||
.Fn ptrace
|
||||
system call and
|
||||
.Fn ptrace
|
||||
callers can reliably check
|
||||
.Va errno
|
||||
for non-zero value afterwards.
|
||||
.Sh ERRORS
|
||||
The
|
||||
.Fn ptrace
|
||||
|
49
lib/libc/sys/ptrace.c
Normal file
49
lib/libc/sys/ptrace.c
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2016 The FreeBSD Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Portions of this software were developed by Konstantin Belousov
|
||||
* under sponsorship from the FreeBSD Foundation.
|
||||
*
|
||||
* 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(s), this list of conditions and the following disclaimer as
|
||||
* the first lines of this file unmodified other than the possible
|
||||
* addition of one or more copyright notices.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice(s), 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 COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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/types.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <errno.h>
|
||||
#include "libc_private.h"
|
||||
|
||||
__weak_reference(_ptrace, ptrace);
|
||||
|
||||
int
|
||||
_ptrace(int request, pid_t pid, caddr_t addr, int data)
|
||||
{
|
||||
|
||||
errno = 0;
|
||||
return (__sys_ptrace(request, pid, addr, data));
|
||||
}
|
@ -11,7 +11,8 @@ SHLIB_MAJOR= 0
|
||||
.PATH: ${.CURDIR}/../../sys/contrib/libnv ${.CURDIR}/../../sys/sys
|
||||
CFLAGS+=-I${.CURDIR}/../../sys -I${.CURDIR}
|
||||
|
||||
SRCS= dnvlist.c
|
||||
SRCS= cnvlist.c
|
||||
SRCS+= dnvlist.c
|
||||
SRCS+= msgio.c
|
||||
SRCS+= nvlist.c
|
||||
SRCS+= nvpair.c
|
||||
|
@ -1,6 +1,7 @@
|
||||
# $FreeBSD$
|
||||
|
||||
ATF_TESTS_CXX= \
|
||||
cnv_tests \
|
||||
dnv_tests \
|
||||
nv_array_tests \
|
||||
nv_tests \
|
||||
|
1508
lib/libnv/tests/cnv_tests.cc
Normal file
1508
lib/libnv/tests/cnv_tests.cc
Normal file
File diff suppressed because it is too large
Load Diff
@ -439,7 +439,7 @@ dos_readdir(struct open_file *fd, struct dirent *d)
|
||||
u_char fn[261];
|
||||
DOS_DIR dd;
|
||||
size_t res;
|
||||
u_int chk, i, x, xdn;
|
||||
u_int chk, x, xdn;
|
||||
int err;
|
||||
|
||||
x = chk = 0;
|
||||
@ -598,7 +598,7 @@ lookup(DOS_FS *fs, u_int clus, const char *name, DOS_DE **dep)
|
||||
u_char lfn[261];
|
||||
u_char sfn[13];
|
||||
u_int nsec, lsec, xdn, chk, sec, ent, x;
|
||||
int err, ok, i;
|
||||
int err, ok;
|
||||
|
||||
if (!clus)
|
||||
for (ent = 0; ent < 2; ent++)
|
||||
@ -774,11 +774,11 @@ fatget(DOS_FS *fs, u_int *c)
|
||||
int err = 0;
|
||||
|
||||
if (fat.unit != dd->d_unit) {
|
||||
/* fat cache was changed to another device, dont use it */
|
||||
/* fat cache was changed to another device, don't use it */
|
||||
err = ioread(fs, secbyt(fs->lsnfat) + fatoff(fs->fatsz, *c), buf,
|
||||
fs->fatsz != 32 ? 2 : 4);
|
||||
if (err)
|
||||
return err;
|
||||
return (err);
|
||||
} else {
|
||||
offset = fatoff(fs->fatsz, *c);
|
||||
nbyte = fs->fatsz != 32 ? 2 : 4;
|
||||
|
@ -645,7 +645,7 @@ _mips_get_tls(void)
|
||||
".set\tmips64r2\n\t"
|
||||
"rdhwr\t%0, $29\n\t"
|
||||
".set\tpop"
|
||||
: "=v" (_rv));
|
||||
: "=r" (_rv));
|
||||
/*
|
||||
* XXXSS See 'git show c6be4f4d2d1b71c04de5d3bbb6933ce2dbcdb317'
|
||||
*
|
||||
@ -670,7 +670,7 @@ _mips_get_tls(void)
|
||||
".set\tmips32r2\n\t"
|
||||
"rdhwr\t%0, $29\n\t"
|
||||
".set\tpop"
|
||||
: "=v" (_rv));
|
||||
: "=r" (_rv));
|
||||
/*
|
||||
* XXXSS See 'git show c6be4f4d2d1b71c04de5d3bbb6933ce2dbcdb317'
|
||||
*
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -132,7 +132,11 @@ lzf_decompress (const void *const in_data, unsigned int in_len,
|
||||
* Unconditionally aligning does not cost very much, so do it if unsure
|
||||
*/
|
||||
#ifndef STRICT_ALIGN
|
||||
# define STRICT_ALIGN !(defined(__i386) || defined (__amd64))
|
||||
# if !(defined(__i386) || defined (__amd64))
|
||||
# define STRICT_ALIGN 1
|
||||
# else
|
||||
# define STRICT_ALIGN 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -57,6 +57,7 @@ MAN= accept_filter.9 \
|
||||
byteorder.9 \
|
||||
casuword.9 \
|
||||
cd.9 \
|
||||
cnv.9 \
|
||||
condvar.9 \
|
||||
config_intrhook.9 \
|
||||
contigmalloc.9 \
|
||||
@ -617,6 +618,41 @@ MLINKS+=byteorder.9 be16dec.9 \
|
||||
byteorder.9 le64dec.9 \
|
||||
byteorder.9 le64enc.9 \
|
||||
byteorder.9 le64toh.9
|
||||
MLINKS+=cnv.9 cnvlist.9 \
|
||||
cnv.9 cnvlist_free_binary.9 \
|
||||
cnv.9 cnvlist_free_bool.9 \
|
||||
cnv.9 cnvlist_free_bool_array.9 \
|
||||
cnv.9 cnvlist_free_descriptor.9 \
|
||||
cnv.9 cnvlist_free_descriptor_array.9 \
|
||||
cnv.9 cnvlist_free_null.9 \
|
||||
cnv.9 cnvlist_free_number.9 \
|
||||
cnv.9 cnvlist_free_number_array.9 \
|
||||
cnv.9 cnvlist_free_nvlist.9 \
|
||||
cnv.9 cnvlist_free_nvlist_array.9 \
|
||||
cnv.9 cnvlist_free_string.9 \
|
||||
cnv.9 cnvlist_free_string_array.9 \
|
||||
cnv.9 cnvlist_get_binary.9 \
|
||||
cnv.9 cnvlist_get_bool.9 \
|
||||
cnv.9 cnvlist_get_bool_array.9 \
|
||||
cnv.9 cnvlist_get_descriptor.9 \
|
||||
cnv.9 cnvlist_get_descriptor_array.9 \
|
||||
cnv.9 cnvlist_get_number.9 \
|
||||
cnv.9 cnvlist_get_number_array.9 \
|
||||
cnv.9 cnvlist_get_nvlist.9 \
|
||||
cnv.9 cnvlist_get_nvlist_array.9 \
|
||||
cnv.9 cnvlist_get_string.9 \
|
||||
cnv.9 cnvlist_get_string_array.9 \
|
||||
cnv.9 cnvlist_take_binary.9 \
|
||||
cnv.9 cnvlist_take_bool.9 \
|
||||
cnv.9 cnvlist_take_bool_array.9 \
|
||||
cnv.9 cnvlist_take_descriptor.9 \
|
||||
cnv.9 cnvlist_take_descriptor_array.9 \
|
||||
cnv.9 cnvlist_take_number.9 \
|
||||
cnv.9 cnvlist_take_number_array.9 \
|
||||
cnv.9 cnvlist_take_nvlist.9 \
|
||||
cnv.9 cnvlist_take_nvlist_array.9 \
|
||||
cnv.9 cnvlist_take_string.9 \
|
||||
cnv.9 cnvlist_take_string_array.9
|
||||
MLINKS+=condvar.9 cv_broadcast.9 \
|
||||
condvar.9 cv_broadcastpri.9 \
|
||||
condvar.9 cv_destroy.9 \
|
||||
|
199
share/man/man9/cnv.9
Normal file
199
share/man/man9/cnv.9
Normal file
@ -0,0 +1,199 @@
|
||||
.\"
|
||||
.\" Copyright (c) 2016 Adam Starak <starak.adam@gmail.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$
|
||||
.\"
|
||||
.Dd August 27, 2016
|
||||
.Dt CNV 9
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm cnvlist_get,
|
||||
.Nm cnvlist_take,
|
||||
.Nm cnvlist_free,
|
||||
.Nd "API for managing name/value pairs by cookie."
|
||||
.Sh LIBRARY
|
||||
.Lb libnv
|
||||
.Sh SYNOPSIS
|
||||
.In sys/cnv.h
|
||||
.Ft bool
|
||||
.Fn cnvlist_get_bool "void *cookiep"
|
||||
.Ft uint64_t
|
||||
.Fn cnvlist_get_number "void *cookiep"
|
||||
.Ft "const char *"
|
||||
.Fn cnvlist_get_string "void *cookiep"
|
||||
.Ft "const nvlist_t *"
|
||||
.Fn cnvlist_get_nvlist "void *cookiep"
|
||||
.Ft "const void *"
|
||||
.Fn cnvlist_get_binary "void *cookiep" "size_t *sizep"
|
||||
.Ft "const bool *"
|
||||
.Fn cnvlist_get_bool_array "void *cookiep" "size_t *nitemsp"
|
||||
.Ft "const uint64_t *"
|
||||
.Fn cnvlist_get_number_array "void *cookiep" "size_t *nitemsp"
|
||||
.Ft "const char * const *"
|
||||
.Fn cnvlist_get_string_array "void *cookiep" "size_t *nitemsp"
|
||||
.Ft "const nvlist_t * const *"
|
||||
.Fn cnvlist_get_nvlist_array "void *cookiep" "size_t *nitemsp"
|
||||
.Ft int
|
||||
.Fn cnvlist_get_descriptor "void *cookiep"
|
||||
.Ft "const int *"
|
||||
.Fn cnvlist_get_descriptor_array "void *cookiep" "size_t *nitemsp"
|
||||
.\"
|
||||
.Ft bool
|
||||
.Fn cnvlist_take_bool "void *cookiep"
|
||||
.Ft uint64_t
|
||||
.Fn cnvlist_take_number "void *cookiep"
|
||||
.Ft "const char *"
|
||||
.Fn cnvlist_take_string "void *cookiep"
|
||||
.Ft "const nvlist_t *"
|
||||
.Fn cnvlist_take_nvlist "void *cookiep"
|
||||
.Ft "const void *"
|
||||
.Fn cnvlist_take_binary "void *cookiep" "size_t *sizep"
|
||||
.Ft "const bool *"
|
||||
.Fn cnvlist_take_bool_array "void *cookiep" "size_t *nitemsp"
|
||||
.Ft "const uint64_t *"
|
||||
.Fn cnvlist_take_number_array "void *cookiep" "size_t *nitemsp"
|
||||
.Ft "const char * const *"
|
||||
.Fn cnvlist_take_string_array "void *cookiep" "size_t *nitemsp"
|
||||
.Ft "const nvlist_t * const *"
|
||||
.Fn cnvlist_take_nvlist_array "void *cookiep" "size_t *nitemsp"
|
||||
.Ft int
|
||||
.Fn cnvlist_take_descriptor "void *cookiep"
|
||||
.Ft "const int *'
|
||||
.Fn cnvlist_take_descriptor_array "void *cookiep" "size_t *nitemsp"
|
||||
.\"
|
||||
.Ft void
|
||||
.Fn cnvlist_free_null "nvlist_t *nvl" "void *cookiep"
|
||||
.Ft void
|
||||
.Fn cnvlist_free_bool "nvlist_t *nvl" "void *cookiep"
|
||||
.Ft void
|
||||
.Fn cnvlist_free_number "nvlist_t *nvl" "void *cookiep"
|
||||
.Ft void
|
||||
.Fn cnvlist_free_string "nvlist_t *nvl" "void *cookiep"
|
||||
.Ft void
|
||||
.Fn cnvlist_free_nvlist "nvlist_t *nvl" "void *cookiep"
|
||||
.Ft void
|
||||
.Fn cnvlist_free_descriptor "nvlist_t *nvl" "void *cookiep"
|
||||
.Ft void
|
||||
.Fn cnvlist_free_binary "nvlist_t *nvl" "void *cookiep"
|
||||
.Ft void
|
||||
.Fn cnvlist_free_bool_array "nvlist_t *nvl" "void *cookiep"
|
||||
.Ft void
|
||||
.Fn cnvlist_free_number_array "nvlist_t *nvl" "void *cookiep"
|
||||
.Ft void
|
||||
.Fn cnvlist_free_string_array "nvlist_t *nvl" "void *cookiep"
|
||||
.Ft void
|
||||
.Fn cnvlist_free_nvlist_array "nvlist_t *nvl" "void *cookiep"
|
||||
.Ft void
|
||||
.Fn cnvlist_free_descriptor_array "nvlist_t *nvl" "void *cookiep"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm libnv
|
||||
library permits easy management of name/value pairs and can send and receive
|
||||
them over sockets.
|
||||
For more information, also see
|
||||
.Xr nv 9 .
|
||||
.Pp
|
||||
The concept of cookies is explained in
|
||||
.Fn nvlist_next ,
|
||||
.Fn nvlist_get_parent ,
|
||||
and
|
||||
.Fn nvlist_get_pararr
|
||||
from
|
||||
.Xr nv 9 .
|
||||
.Pp
|
||||
The
|
||||
.Nm cnvlist_get
|
||||
family of functions obtains the value associated with the given cookie.
|
||||
Returned strings, nvlists, descriptors, binaries, or arrays must not be modified
|
||||
by the user, since they still belong to the nvlist.
|
||||
The nvlist must not be in an error state.
|
||||
.Pp
|
||||
The
|
||||
.Nm cnvlist_take
|
||||
family of functions returns the value associated with the given cookie and
|
||||
removes the element from the nvlist.
|
||||
When the value is a string, binary, or array value, the caller is responsible
|
||||
for freeing the returned memory with
|
||||
.Fn free 3 .
|
||||
When the value is an nvlist, the caller is responsible for destroying the
|
||||
returned nvlist with
|
||||
.Fn nvlist_destroy .
|
||||
When the value is a descriptor, the caller is responsible for closing the
|
||||
returned descriptor with the
|
||||
.Fn close 2 .
|
||||
.Pp
|
||||
The
|
||||
.Nm cnvlist_free
|
||||
family of functions removes an element of the supplied cookie and frees all
|
||||
resources.
|
||||
If an element of the given cookie has the wrong type or does not exist, the
|
||||
program
|
||||
is aborted.
|
||||
.Sh EXAMPLE
|
||||
The following example demonstrates how to deal with cnvlist API.
|
||||
.Bd -literal
|
||||
int type;
|
||||
void *cookie, *scookie, *bcookie;
|
||||
nvlist_t *nvl;
|
||||
char *name;
|
||||
|
||||
nvl = nvlist_create(0);
|
||||
nvlist_add_bool(nvl, "test", 1 == 2);
|
||||
nvlist_add_string(nvl, "test2", "cnvlist");
|
||||
cookie = NULL;
|
||||
|
||||
while (nvlist_next(nvl, &type, &cookie) != NULL) {
|
||||
switch (type) {
|
||||
case NV_TYPE_BOOL:
|
||||
printf("test: %d\\n", cnvlist_get_bool(cookie));
|
||||
bcookie = cookie;
|
||||
break;
|
||||
case NV_TYPE_STRING:
|
||||
printf("test2: %s\\n", cnvlist_get_string(cookie));
|
||||
scookie = cookie;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
name = cnvlist_take_string(nvl, scookie);
|
||||
cnvlist_free_bool(nvl, bcookie);
|
||||
|
||||
printf("test2: %s\\n", name);
|
||||
free(name);
|
||||
|
||||
printf("nvlist_empty = %d\\n", nvlist_empty(nvl));
|
||||
nvlist_destroy(nvl);
|
||||
|
||||
return (0);
|
||||
.Ed
|
||||
.Sh SEE ALSO
|
||||
.Xr nv 9 ,
|
||||
.Xr close 2 ,
|
||||
.Xr free 3
|
||||
.Sh AUTHORS
|
||||
.An -nosplit
|
||||
The
|
||||
.Nm cnv
|
||||
API was created during the Google Summer Of Code 2016 by
|
@ -297,6 +297,8 @@ cleandepend:
|
||||
rm -rf ${CLEANDEPENDDIRS}
|
||||
.endif
|
||||
.endif
|
||||
.ORDER: cleandepend all
|
||||
.ORDER: cleandepend depend
|
||||
|
||||
.if !target(checkdpadd) && (defined(DPADD) || defined(LDADD))
|
||||
_LDADD_FROM_DPADD= ${DPADD:R:T:C;^lib(.*)$;-l\1;g}
|
||||
|
@ -156,6 +156,7 @@ clean:
|
||||
-rm -rf ${CLEANDIRS}
|
||||
.endif
|
||||
.endif
|
||||
.ORDER: clean all
|
||||
|
||||
cleandir: cleanobj
|
||||
|
||||
|
@ -128,6 +128,11 @@ CWARNFLAGS+= -Wno-error=address \
|
||||
-Wno-error=unused-value
|
||||
.endif
|
||||
|
||||
# GCC 5.3.0
|
||||
.if ${COMPILER_TYPE} == "gcc" && ${COMPILER_VERSION} >= 50300
|
||||
CWARNFLAGS+= -Wno-error=strict-overflow
|
||||
.endif
|
||||
|
||||
# GCC 6.1.0
|
||||
.if ${COMPILER_TYPE} == "gcc" && ${COMPILER_VERSION} >= 60100
|
||||
CWARNFLAGS+= -Wno-error=misleading-indentation \
|
||||
|
@ -23,6 +23,7 @@ _src_env_conf_included_: .NOTMAIN
|
||||
.if make(*install*) && ${.MAKE.LEVEL} == 0
|
||||
META_MODE= normal
|
||||
MK_META_MODE= no
|
||||
.export MK_META_MODE
|
||||
.endif
|
||||
|
||||
# If we were found via .../share/mk we need to replace that
|
||||
|
@ -5153,8 +5153,7 @@ out:
|
||||
}
|
||||
|
||||
/*
|
||||
* pmap_zero_page zeros the specified hardware page by mapping
|
||||
* the page into KVM and using bzero to clear its contents.
|
||||
* Zero the specified hardware page.
|
||||
*/
|
||||
void
|
||||
pmap_zero_page(vm_page_t m)
|
||||
@ -5165,10 +5164,8 @@ pmap_zero_page(vm_page_t m)
|
||||
}
|
||||
|
||||
/*
|
||||
* pmap_zero_page_area zeros the specified hardware page by mapping
|
||||
* the page into KVM and using bzero to clear its contents.
|
||||
*
|
||||
* off and size may not cover an area beyond a single hardware page.
|
||||
* Zero an an area within a single hardware page. off and size must not
|
||||
* cover an area beyond a single hardware page.
|
||||
*/
|
||||
void
|
||||
pmap_zero_page_area(vm_page_t m, int off, int size)
|
||||
@ -5182,24 +5179,20 @@ pmap_zero_page_area(vm_page_t m, int off, int size)
|
||||
}
|
||||
|
||||
/*
|
||||
* pmap_zero_page_idle zeros the specified hardware page by mapping
|
||||
* the page into KVM and using bzero to clear its contents. This
|
||||
* is intended to be called from the vm_pagezero process only and
|
||||
* outside of Giant.
|
||||
* Zero the specified hardware page in a way that minimizes cache thrashing.
|
||||
* This is intended to be called from the vm_pagezero process only and
|
||||
* outside of Giant.
|
||||
*/
|
||||
void
|
||||
pmap_zero_page_idle(vm_page_t m)
|
||||
{
|
||||
vm_offset_t va = PHYS_TO_DMAP(VM_PAGE_TO_PHYS(m));
|
||||
|
||||
pagezero((void *)va);
|
||||
sse2_pagezero((void *)va);
|
||||
}
|
||||
|
||||
/*
|
||||
* pmap_copy_page copies the specified (machine independent)
|
||||
* page by mapping the page into virtual memory and using
|
||||
* bcopy to copy the page, one machine dependent page at a
|
||||
* time.
|
||||
* Copy 1 specified hardware page to another.
|
||||
*/
|
||||
void
|
||||
pmap_copy_page(vm_page_t msrc, vm_page_t mdst)
|
||||
|
@ -72,6 +72,30 @@ ENTRY(pagezero)
|
||||
ret
|
||||
END(pagezero)
|
||||
|
||||
/* Address: %rdi */
|
||||
ENTRY(sse2_pagezero)
|
||||
PUSH_FRAME_POINTER
|
||||
movq $-PAGE_SIZE,%rdx
|
||||
subq %rdx,%rdi
|
||||
xorl %eax,%eax
|
||||
jmp 1f
|
||||
/*
|
||||
* The loop takes 29 bytes. Ensure that it doesn't cross a 32-byte
|
||||
* cache line.
|
||||
*/
|
||||
.p2align 5,0x90
|
||||
1:
|
||||
movnti %rax,(%rdi,%rdx)
|
||||
movnti %rax,8(%rdi,%rdx)
|
||||
movnti %rax,16(%rdi,%rdx)
|
||||
movnti %rax,24(%rdi,%rdx)
|
||||
addq $32,%rdx
|
||||
jne 1b
|
||||
sfence
|
||||
POP_FRAME_POINTER
|
||||
ret
|
||||
END(sse2_pagezero)
|
||||
|
||||
ENTRY(bcmp)
|
||||
PUSH_FRAME_POINTER
|
||||
movq %rdx,%rcx
|
||||
|
@ -57,6 +57,7 @@ void gsbase_load_fault(void) __asm(__STRING(gsbase_load_fault));
|
||||
void fpstate_drop(struct thread *td);
|
||||
void pagezero(void *addr);
|
||||
void setidt(int idx, alias_for_inthand_t *func, int typ, int dpl, int ist);
|
||||
void sse2_pagezero(void *addr);
|
||||
struct savefpu *get_pcb_user_save_td(struct thread *td);
|
||||
struct savefpu *get_pcb_user_save_pcb(struct pcb *pcb);
|
||||
|
||||
|
@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/pci/pcivar.h>
|
||||
#include <dev/pci/pcireg.h>
|
||||
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/md_var.h>
|
||||
|
||||
#include "vmm_util.h"
|
||||
@ -51,6 +52,10 @@ static int iommu_avail;
|
||||
SYSCTL_INT(_hw_vmm_iommu, OID_AUTO, initialized, CTLFLAG_RD, &iommu_avail,
|
||||
0, "bhyve iommu initialized?");
|
||||
|
||||
static int iommu_enable = 1;
|
||||
SYSCTL_INT(_hw_vmm_iommu, OID_AUTO, enable, CTLFLAG_RDTUN, &iommu_enable, 0,
|
||||
"Enable use of I/O MMU (required for PCI passthrough).");
|
||||
|
||||
static struct iommu_ops *ops;
|
||||
static void *host_domain;
|
||||
|
||||
@ -148,7 +153,7 @@ IOMMU_DISABLE(void)
|
||||
(*ops->disable)();
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
iommu_init(void)
|
||||
{
|
||||
int error, bus, slot, func;
|
||||
@ -156,6 +161,9 @@ iommu_init(void)
|
||||
const char *name;
|
||||
device_t dev;
|
||||
|
||||
if (!iommu_enable)
|
||||
return;
|
||||
|
||||
if (vmm_is_intel())
|
||||
ops = &iommu_ops_intel;
|
||||
else if (vmm_is_amd())
|
||||
@ -174,8 +182,13 @@ iommu_init(void)
|
||||
*/
|
||||
maxaddr = vmm_mem_maxaddr();
|
||||
host_domain = IOMMU_CREATE_DOMAIN(maxaddr);
|
||||
if (host_domain == NULL)
|
||||
panic("iommu_init: unable to create a host domain");
|
||||
if (host_domain == NULL) {
|
||||
printf("iommu_init: unable to create a host domain");
|
||||
IOMMU_CLEANUP();
|
||||
ops = NULL;
|
||||
iommu_avail = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create 1:1 mappings from '0' to 'maxaddr' for devices assigned to
|
||||
@ -216,7 +229,16 @@ iommu_cleanup(void)
|
||||
void *
|
||||
iommu_create_domain(vm_paddr_t maxaddr)
|
||||
{
|
||||
static volatile int iommu_initted;
|
||||
|
||||
if (iommu_initted < 2) {
|
||||
if (atomic_cmpset_int(&iommu_initted, 0, 1)) {
|
||||
iommu_init();
|
||||
atomic_store_rel_int(&iommu_initted, 2);
|
||||
} else
|
||||
while (iommu_initted == 1)
|
||||
cpu_spinwait();
|
||||
}
|
||||
return (IOMMU_CREATE_DOMAIN(maxaddr));
|
||||
}
|
||||
|
||||
|
@ -61,7 +61,6 @@ struct iommu_ops {
|
||||
extern struct iommu_ops iommu_ops_intel;
|
||||
extern struct iommu_ops iommu_ops_amd;
|
||||
|
||||
void iommu_init(void);
|
||||
void iommu_cleanup(void);
|
||||
void *iommu_host_domain(void);
|
||||
void *iommu_create_domain(vm_paddr_t maxaddr);
|
||||
|
@ -224,11 +224,6 @@ SYSCTL_INT(_hw_vmm, OID_AUTO, trace_guest_exceptions, CTLFLAG_RDTUN,
|
||||
&trace_guest_exceptions, 0,
|
||||
"Trap into hypervisor on all guest exceptions and reflect them back");
|
||||
|
||||
static int vmm_force_iommu = 0;
|
||||
TUNABLE_INT("hw.vmm.force_iommu", &vmm_force_iommu);
|
||||
SYSCTL_INT(_hw_vmm, OID_AUTO, force_iommu, CTLFLAG_RDTUN, &vmm_force_iommu, 0,
|
||||
"Force use of I/O MMU even if no passthrough devices were found.");
|
||||
|
||||
static void vm_free_memmap(struct vm *vm, int ident);
|
||||
static bool sysmem_mapping(struct vm *vm, struct mem_map *mm);
|
||||
static void vcpu_notify_event_locked(struct vcpu *vcpu, bool lapic_intr);
|
||||
@ -358,8 +353,6 @@ vmm_handler(module_t mod, int what, void *arg)
|
||||
switch (what) {
|
||||
case MOD_LOAD:
|
||||
vmmdev_init();
|
||||
if (vmm_force_iommu || ppt_avail_devices() > 0)
|
||||
iommu_init();
|
||||
error = vmm_init();
|
||||
if (error == 0)
|
||||
vmm_initialized = 1;
|
||||
@ -396,9 +389,6 @@ static moduledata_t vmm_kmod = {
|
||||
/*
|
||||
* vmm initialization has the following dependencies:
|
||||
*
|
||||
* - iommu initialization must happen after the pci passthru driver has had
|
||||
* a chance to attach to any passthru devices (after SI_SUB_CONFIGURE).
|
||||
*
|
||||
* - VT-x initialization requires smp_rendezvous() and therefore must happen
|
||||
* after SMP is fully functional (after SI_SUB_SMP).
|
||||
*/
|
||||
@ -893,6 +883,8 @@ vm_assign_pptdev(struct vm *vm, int bus, int slot, int func)
|
||||
("vm_assign_pptdev: iommu must be NULL"));
|
||||
maxaddr = sysmem_maxaddr(vm);
|
||||
vm->iommu = iommu_create_domain(maxaddr);
|
||||
if (vm->iommu == NULL)
|
||||
return (ENXIO);
|
||||
vm_iommu_map(vm);
|
||||
}
|
||||
|
||||
|
@ -1089,7 +1089,9 @@ DB_SHOW_COMMAND(vtop, db_show_vtop)
|
||||
|
||||
if (have_addr) {
|
||||
phys = arm64_address_translate_s1e1r(addr);
|
||||
db_printf("Physical address reg: 0x%016lx\n", phys);
|
||||
db_printf("Physical address reg (read): 0x%016lx\n", phys);
|
||||
phys = arm64_address_translate_s1e1w(addr);
|
||||
db_printf("Physical address reg (write): 0x%016lx\n", phys);
|
||||
} else
|
||||
db_printf("show vtop <virt_addr>\n");
|
||||
}
|
||||
|
@ -497,7 +497,7 @@ bd_realstrategy(void *devdata, int rw, daddr_t dblk, size_t offset, size_t size,
|
||||
char *buf, size_t *rsize)
|
||||
{
|
||||
struct disk_devdesc *dev = (struct disk_devdesc *)devdata;
|
||||
int blks;
|
||||
int blks, remaining;
|
||||
#ifdef BD_SUPPORT_FRAGS /* XXX: sector size */
|
||||
char fragbuf[BIOSDISK_SECSIZE];
|
||||
size_t fragsize;
|
||||
@ -513,14 +513,15 @@ bd_realstrategy(void *devdata, int rw, daddr_t dblk, size_t offset, size_t size,
|
||||
if (rsize)
|
||||
*rsize = 0;
|
||||
|
||||
if (dblk >= BD(dev).bd_sectors) {
|
||||
DEBUG("IO past disk end %llu", (unsigned long long)dblk);
|
||||
return (EIO);
|
||||
}
|
||||
|
||||
if (dblk + blks > BD(dev).bd_sectors) {
|
||||
/* perform partial read */
|
||||
blks = BD(dev).bd_sectors - dblk;
|
||||
/*
|
||||
* Perform partial read to prevent read-ahead crossing
|
||||
* the end of disk - or any 32 bit aliases of the end.
|
||||
* Signed arithmetic is used to handle wrap-around cases
|
||||
* like we do for TCP sequence numbers.
|
||||
*/
|
||||
remaining = (int)(BD(dev).bd_sectors - dblk); /* truncate */
|
||||
if (remaining > 0 && remaining < blks) {
|
||||
blks = remaining;
|
||||
size = blks * BD(dev).bd_sectorsize;
|
||||
DEBUG("short read %d", blks);
|
||||
}
|
||||
|
@ -88,6 +88,7 @@ ata_op_string(struct ata_cmd *cmd)
|
||||
}
|
||||
return "DSM";
|
||||
case 0x08: return ("DEVICE_RESET");
|
||||
case 0x0b: return ("REQUEST_SENSE_DATA_EXT");
|
||||
case 0x20: return ("READ");
|
||||
case 0x24: return ("READ48");
|
||||
case 0x25: return ("READ_DMA48");
|
||||
@ -120,6 +121,12 @@ ata_op_string(struct ata_cmd *cmd)
|
||||
case 0x47: return ("READ_LOG_DMA_EXT");
|
||||
case 0x4a: return ("ZAC_MANAGEMENT_IN");
|
||||
case 0x51: return ("CONFIGURE_STREAM");
|
||||
case 0x57: return ("WRITE_LOG_DMA_EXT");
|
||||
case 0x5b: return ("TRUSTED_NON_DATA");
|
||||
case 0x5c: return ("TRUSTED_RECEIVE");
|
||||
case 0x5d: return ("TRUSTED_RECEIVE_DMA");
|
||||
case 0x5e: return ("TRUSTED_SEND");
|
||||
case 0x5f: return ("TRUSTED_SEND_DMA");
|
||||
case 0x60: return ("READ_FPDMA_QUEUED");
|
||||
case 0x61: return ("WRITE_FPDMA_QUEUED");
|
||||
case 0x63:
|
||||
@ -160,9 +167,12 @@ ata_op_string(struct ata_cmd *cmd)
|
||||
}
|
||||
return ("SEP_ATTN");
|
||||
case 0x70: return ("SEEK");
|
||||
case 0x77: return ("SET_DATE_TIME_EXT");
|
||||
case 0x78: return ("ACCESSIBLE_MAX_ADDRESS_CONFIGURATION");
|
||||
case 0x87: return ("CFA_TRANSLATE_SECTOR");
|
||||
case 0x90: return ("EXECUTE_DEVICE_DIAGNOSTIC");
|
||||
case 0x92: return ("DOWNLOAD_MICROCODE");
|
||||
case 0x93: return ("DOWNLOAD_MICROCODE_DMA");
|
||||
case 0x9a: return ("ZAC_MANAGEMENT_OUT");
|
||||
case 0xa0: return ("PACKET");
|
||||
case 0xa1: return ("ATAPI_IDENTIFY");
|
||||
@ -180,6 +190,7 @@ ata_op_string(struct ata_cmd *cmd)
|
||||
}
|
||||
return ("SMART");
|
||||
case 0xb1: return ("DEVICE CONFIGURATION");
|
||||
case 0xb4: return ("SANITIZE_DEVICE");
|
||||
case 0xc0: return ("CFA_ERASE");
|
||||
case 0xc4: return ("READ_MUL");
|
||||
case 0xc5: return ("WRITE_MUL");
|
||||
|
@ -526,6 +526,7 @@ contrib/libfdt/fdt_rw.c optional fdt
|
||||
contrib/libfdt/fdt_strerror.c optional fdt
|
||||
contrib/libfdt/fdt_sw.c optional fdt
|
||||
contrib/libfdt/fdt_wip.c optional fdt
|
||||
contrib/libnv/cnvlist.c standard
|
||||
contrib/libnv/dnvlist.c standard
|
||||
contrib/libnv/nvlist.c standard
|
||||
contrib/libnv/nvpair.c standard
|
||||
@ -1157,19 +1158,26 @@ dev/bhnd/bcma/bcma_bhndb.c optional bcma bhnd bhndb
|
||||
dev/bhnd/bcma/bcma_erom.c optional bcma bhnd
|
||||
dev/bhnd/bcma/bcma_nexus.c optional bcma_nexus bcma bhnd
|
||||
dev/bhnd/bcma/bcma_subr.c optional bcma bhnd
|
||||
dev/bhnd/cores/chipc/bhnd_chipc_if.m optional bhnd
|
||||
dev/bhnd/cores/chipc/bhnd_sprom_chipc.c optional bhnd
|
||||
dev/bhnd/cores/chipc/bhnd_pmu_chipc.c optional bhnd
|
||||
dev/bhnd/cores/chipc/chipc.c optional bhnd
|
||||
dev/bhnd/cores/chipc/chipc_cfi.c optional bhnd cfi
|
||||
dev/bhnd/cores/chipc/chipc_slicer.c optional bhnd cfi | bhnd spibus
|
||||
dev/bhnd/cores/chipc/chipc_spi.c optional bhnd spibus
|
||||
dev/bhnd/cores/chipc/chipc_subr.c optional bhnd
|
||||
dev/bhnd/cores/chipc/bhnd_chipc_if.m optional bhnd
|
||||
dev/bhnd/cores/chipc/bhnd_sprom_chipc.c optional bhnd
|
||||
dev/bhnd/cores/chipc/pwrctl/bhnd_pwrctl.c optional bhnd
|
||||
dev/bhnd/cores/chipc/pwrctl/bhnd_pwrctl_subr.c optional bhnd
|
||||
dev/bhnd/cores/pci/bhnd_pci.c optional bhnd pci
|
||||
dev/bhnd/cores/pci/bhnd_pci_hostb.c optional bhndb bhnd pci
|
||||
dev/bhnd/cores/pci/bhnd_pcib.c optional bhnd_pcib bhnd pci
|
||||
dev/bhnd/cores/pcie2/bhnd_pcie2.c optional bhnd pci
|
||||
dev/bhnd/cores/pcie2/bhnd_pcie2_hostb.c optional bhndb bhnd pci
|
||||
dev/bhnd/cores/pcie2/bhnd_pcie2b.c optional bhnd_pcie2b bhnd pci
|
||||
dev/bhnd/cores/pmu/bhnd_pmu.c optional bhnd
|
||||
dev/bhnd/cores/pmu/bhnd_pmu_core.c optional bhnd
|
||||
dev/bhnd/cores/pmu/bhnd_pmu_if.m optional bhnd
|
||||
dev/bhnd/cores/pmu/bhnd_pmu_subr.c optional bhnd
|
||||
dev/bhnd/nvram/bhnd_nvram.c optional bhnd
|
||||
dev/bhnd/nvram/bhnd_nvram_common.c optional bhnd
|
||||
dev/bhnd/nvram/bhnd_nvram_cfe.c optional bhnd siba_nexus cfe | \
|
||||
|
@ -1882,6 +1882,12 @@
|
||||
#define AR_PHY_PLL_BB_DPLL3 AR_PHY_65NM(overlay_0x16180.Osprey.ch0_bb_dpll3)
|
||||
#define AR_PHY_PLL_BB_DPLL4 AR_PHY_65NM(overlay_0x16180.Osprey.ch0_bb_dpll4)
|
||||
|
||||
/*
|
||||
* Wasp/Hornet PHY USB PLL control
|
||||
*/
|
||||
#define AR_PHY_USB_CTRL1 0x16c84
|
||||
#define AR_PHY_USB_CTRL2 0x16c88
|
||||
|
||||
/*
|
||||
* PMU Register Map
|
||||
*/
|
||||
|
@ -32,7 +32,13 @@
|
||||
# define __KERNEL__
|
||||
#endif
|
||||
|
||||
#define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
|
||||
#ifndef SOLARIS
|
||||
# if defined(sun) && (defined(__svr4__) || defined(__SVR4))
|
||||
# define SOLARIS 1
|
||||
# else
|
||||
# define SOLARIS 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__SVR4) || defined(__svr4__) || defined(__sgi)
|
||||
|
@ -29,7 +29,11 @@
|
||||
#endif
|
||||
|
||||
#ifndef SOLARIS
|
||||
# define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
|
||||
# if defined(sun) && (defined(__svr4__) || defined(__SVR4))
|
||||
# define SOLARIS 1
|
||||
# else
|
||||
# define SOLARIS 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef __P
|
||||
|
@ -19,7 +19,11 @@
|
||||
# include <osreldate.h>
|
||||
#endif
|
||||
#ifndef SOLARIS
|
||||
# define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
|
||||
# if defined(sun) && (defined(__svr4__) || defined(__SVR4))
|
||||
# define SOLARIS 1
|
||||
# else
|
||||
# define SOLARIS 0
|
||||
# endif
|
||||
#endif
|
||||
#include <sys/errno.h>
|
||||
#include <sys/types.h>
|
||||
|
@ -13,8 +13,12 @@
|
||||
#ifndef __IP_NAT_H__
|
||||
#define __IP_NAT_H__
|
||||
|
||||
#ifndef SOLARIS
|
||||
#define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
|
||||
#ifndef SOLARIS
|
||||
# if defined(sun) && (defined(__svr4__) || defined(__SVR4))
|
||||
# define SOLARIS 1
|
||||
# else
|
||||
# define SOLARIS 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(__STDC__) || defined(__GNUC__) || defined(_AIX51)
|
||||
|
@ -12,8 +12,12 @@
|
||||
#ifndef __IP_PROXY_H__
|
||||
#define __IP_PROXY_H__
|
||||
|
||||
#ifndef SOLARIS
|
||||
#define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
|
||||
#ifndef SOLARIS
|
||||
# if defined(sun) && (defined(__svr4__) || defined(__SVR4))
|
||||
# define SOLARIS 1
|
||||
# else
|
||||
# define SOLARIS 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(__STDC__) || defined(__GNUC__) || defined(_AIX51)
|
||||
|
197
sys/contrib/libnv/cnvlist.c
Normal file
197
sys/contrib/libnv/cnvlist.c
Normal file
@ -0,0 +1,197 @@
|
||||
/*-
|
||||
* Copyright (c) 2016 Adam Starak <starak.adam@gmail.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 AUTHORS 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 AUTHORS 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/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/malloc.h>
|
||||
|
||||
#include <machine/stdarg.h>
|
||||
|
||||
#else
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#include <sys/cnv.h>
|
||||
#include <sys/nv.h>
|
||||
|
||||
#include "nv_impl.h"
|
||||
#include "nvlist_impl.h"
|
||||
#include "nvpair_impl.h"
|
||||
|
||||
#define CNVLIST_GET(ftype, type, NVTYPE) \
|
||||
ftype \
|
||||
cnvlist_get_##type(void *cookiep) \
|
||||
{ \
|
||||
\
|
||||
if (nvpair_type(cookiep) != NV_TYPE_##NVTYPE) { \
|
||||
nvlist_report_missing(NV_TYPE_##NVTYPE, \
|
||||
nvpair_name(cookiep)); \
|
||||
} \
|
||||
return (nvpair_get_##type(cookiep)); \
|
||||
}
|
||||
|
||||
CNVLIST_GET(bool, bool, BOOL)
|
||||
CNVLIST_GET(uint64_t, number, NUMBER)
|
||||
CNVLIST_GET(const char *, string, STRING)
|
||||
CNVLIST_GET(const nvlist_t *, nvlist, NVLIST)
|
||||
#ifndef _KERNEL
|
||||
CNVLIST_GET(int, descriptor, DESCRIPTOR)
|
||||
#endif
|
||||
|
||||
#undef CNVLIST_GET
|
||||
|
||||
#define CNVLIST_GET_ARRAY(ftype, type, NVTYPE) \
|
||||
ftype \
|
||||
cnvlist_get_##type(void *cookiep, size_t *nitemsp) \
|
||||
{ \
|
||||
\
|
||||
if (nvpair_type(cookiep) != NV_TYPE_##NVTYPE) { \
|
||||
nvlist_report_missing(NV_TYPE_##NVTYPE, \
|
||||
nvpair_name(cookiep)); \
|
||||
} \
|
||||
return (nvpair_get_##type(cookiep, nitemsp)); \
|
||||
}
|
||||
|
||||
CNVLIST_GET_ARRAY(const bool *, bool_array, BOOL_ARRAY)
|
||||
CNVLIST_GET_ARRAY(const uint64_t *, number_array, NUMBER_ARRAY)
|
||||
CNVLIST_GET_ARRAY(const char * const *, string_array, STRING_ARRAY)
|
||||
CNVLIST_GET_ARRAY(const nvlist_t * const *, nvlist_array, NVLIST_ARRAY)
|
||||
#ifndef _KERNEL
|
||||
CNVLIST_GET_ARRAY(const int *, descriptor_array, DESCRIPTOR_ARRAY)
|
||||
#endif
|
||||
|
||||
#undef CNVLIST_GET_ARRAY
|
||||
|
||||
const void *
|
||||
cnvlist_get_binary(void *cookiep, size_t *sizep)
|
||||
{
|
||||
|
||||
if (nvpair_type(cookiep) != NV_TYPE_BINARY)
|
||||
nvlist_report_missing(NV_TYPE_BINARY, nvpair_name(cookiep));
|
||||
return (nvpair_get_binary(cookiep, sizep));
|
||||
}
|
||||
|
||||
#define CNVLIST_TAKE(ftype, type, NVTYPE) \
|
||||
ftype \
|
||||
cnvlist_take_##type(nvlist_t *nvl, void *cookiep) \
|
||||
{ \
|
||||
ftype value; \
|
||||
\
|
||||
if (nvpair_type(cookiep) != NV_TYPE_##NVTYPE) { \
|
||||
nvlist_report_missing(NV_TYPE_##NVTYPE, \
|
||||
nvpair_name(cookiep)); \
|
||||
} \
|
||||
value = (ftype)(intptr_t)nvpair_get_##type(cookiep); \
|
||||
nvlist_remove_nvpair(nvl, cookiep); \
|
||||
nvpair_free_structure(cookiep); \
|
||||
return (value); \
|
||||
}
|
||||
|
||||
CNVLIST_TAKE(bool, bool, BOOL)
|
||||
CNVLIST_TAKE(uint64_t, number, NUMBER)
|
||||
CNVLIST_TAKE(char *, string, STRING)
|
||||
CNVLIST_TAKE(nvlist_t *, nvlist, NVLIST)
|
||||
#ifndef _KERNEL
|
||||
CNVLIST_TAKE(int, descriptor, DESCRIPTOR)
|
||||
#endif
|
||||
|
||||
#undef CNVLIST_TAKE
|
||||
|
||||
#define CNVLIST_TAKE_ARRAY(ftype, type, NVTYPE) \
|
||||
ftype \
|
||||
cnvlist_take_##type(nvlist_t *nvl, void *cookiep, size_t *nitemsp) \
|
||||
{ \
|
||||
ftype value; \
|
||||
\
|
||||
if (nvpair_type(cookiep) != NV_TYPE_##NVTYPE) { \
|
||||
nvlist_report_missing(NV_TYPE_##NVTYPE, \
|
||||
nvpair_name(cookiep)); \
|
||||
} \
|
||||
value = (ftype)(intptr_t)nvpair_get_##type(cookiep, nitemsp); \
|
||||
nvlist_remove_nvpair(nvl, cookiep); \
|
||||
nvpair_free_structure(cookiep); \
|
||||
return (value); \
|
||||
}
|
||||
|
||||
CNVLIST_TAKE_ARRAY(bool *, bool_array, BOOL_ARRAY)
|
||||
CNVLIST_TAKE_ARRAY(uint64_t *, number_array, NUMBER_ARRAY)
|
||||
CNVLIST_TAKE_ARRAY(char **, string_array, STRING_ARRAY)
|
||||
CNVLIST_TAKE_ARRAY(nvlist_t **, nvlist_array, NVLIST_ARRAY)
|
||||
#ifndef _KERNEL
|
||||
CNVLIST_TAKE_ARRAY(int *, descriptor_array, DESCRIPTOR_ARRAY);
|
||||
#endif
|
||||
|
||||
#undef CNVLIST_TAKE_ARRAY
|
||||
|
||||
void *
|
||||
cnvlist_take_binary(nvlist_t *nvl, void *cookiep, size_t *sizep)
|
||||
{
|
||||
void *value;
|
||||
|
||||
if (nvpair_type(cookiep) != NV_TYPE_BINARY)
|
||||
nvlist_report_missing(NV_TYPE_BINARY, nvpair_name(cookiep));
|
||||
value = (void *)(intptr_t)nvpair_get_binary(cookiep, sizep);
|
||||
nvlist_remove_nvpair(nvl, cookiep);
|
||||
nvpair_free_structure(cookiep);
|
||||
return (value);
|
||||
}
|
||||
|
||||
|
||||
#define CNVLIST_FREE(type) \
|
||||
void \
|
||||
cnvlist_free_##type(nvlist_t *nvl, void *cookiep) \
|
||||
{ \
|
||||
\
|
||||
nvlist_free_nvpair(nvl, cookiep); \
|
||||
}
|
||||
|
||||
CNVLIST_FREE(bool)
|
||||
CNVLIST_FREE(number)
|
||||
CNVLIST_FREE(string)
|
||||
CNVLIST_FREE(nvlist)
|
||||
CNVLIST_FREE(binary);
|
||||
CNVLIST_FREE(bool_array)
|
||||
CNVLIST_FREE(number_array)
|
||||
CNVLIST_FREE(string_array)
|
||||
CNVLIST_FREE(nvlist_array)
|
||||
#ifndef _KERNEL
|
||||
CNVLIST_FREE(descriptor)
|
||||
CNVLIST_FREE(descriptor_array)
|
||||
#endif
|
||||
|
||||
#undef CNVLIST_FREE
|
@ -314,7 +314,7 @@ nvlist_set_flags(nvlist_t *nvl, int flags)
|
||||
nvl->nvl_flags = flags;
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
nvlist_report_missing(int type, const char *name)
|
||||
{
|
||||
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
void nvlist_report_missing(int type, const char *name);
|
||||
nvpair_t *nvlist_get_nvpair_parent(const nvlist_t *nvl);
|
||||
const unsigned char *nvlist_unpack_header(nvlist_t *nvl,
|
||||
const unsigned char *ptr, size_t nfds, bool *isbep, size_t *leftp);
|
||||
|
@ -72,6 +72,7 @@ static db_cmdfcn_t db_halt;
|
||||
static db_cmdfcn_t db_kill;
|
||||
static db_cmdfcn_t db_reset;
|
||||
static db_cmdfcn_t db_stack_trace;
|
||||
static db_cmdfcn_t db_stack_trace_active;
|
||||
static db_cmdfcn_t db_stack_trace_all;
|
||||
static db_cmdfcn_t db_watchdog;
|
||||
|
||||
@ -79,6 +80,12 @@ static db_cmdfcn_t db_watchdog;
|
||||
* 'show' commands
|
||||
*/
|
||||
|
||||
static struct command db_show_active_cmds[] = {
|
||||
{ "trace", db_stack_trace_active, 0, NULL },
|
||||
};
|
||||
struct command_table db_show_active_table =
|
||||
LIST_HEAD_INITIALIZER(db_show_active_table);
|
||||
|
||||
static struct command db_show_all_cmds[] = {
|
||||
{ "trace", db_stack_trace_all, 0, NULL },
|
||||
};
|
||||
@ -86,6 +93,7 @@ struct command_table db_show_all_table =
|
||||
LIST_HEAD_INITIALIZER(db_show_all_table);
|
||||
|
||||
static struct command db_show_cmds[] = {
|
||||
{ "active", 0, 0, &db_show_active_table },
|
||||
{ "all", 0, 0, &db_show_all_table },
|
||||
{ "registers", db_show_regs, 0, NULL },
|
||||
{ "breaks", db_listbreak_cmd, 0, NULL },
|
||||
@ -120,6 +128,8 @@ static struct command db_cmds[] = {
|
||||
{ "match", db_trace_until_matching_cmd,0, NULL },
|
||||
{ "trace", db_stack_trace, CS_OWN, NULL },
|
||||
{ "t", db_stack_trace, CS_OWN, NULL },
|
||||
/* XXX alias for active trace */
|
||||
{ "acttrace", db_stack_trace_active, 0, NULL },
|
||||
/* XXX alias for all trace */
|
||||
{ "alltrace", db_stack_trace_all, 0, NULL },
|
||||
{ "where", db_stack_trace, CS_OWN, NULL },
|
||||
@ -195,6 +205,9 @@ db_command_init(void)
|
||||
db_command_register(&db_cmd_table, &db_cmds[i]);
|
||||
for (i = 0; i < N(db_show_cmds); i++)
|
||||
db_command_register(&db_show_table, &db_show_cmds[i]);
|
||||
for (i = 0; i < N(db_show_active_cmds); i++)
|
||||
db_command_register(&db_show_active_table,
|
||||
&db_show_active_cmds[i]);
|
||||
for (i = 0; i < N(db_show_all_cmds); i++)
|
||||
db_command_register(&db_show_all_table, &db_show_all_cmds[i]);
|
||||
#undef N
|
||||
@ -799,8 +812,7 @@ db_stack_trace(db_expr_t tid, bool hastid, db_expr_t count, char *modif)
|
||||
}
|
||||
|
||||
static void
|
||||
db_stack_trace_all(db_expr_t dummy, bool dummy2, db_expr_t dummy3,
|
||||
char *dummy4)
|
||||
_db_stack_trace_all(bool active_only)
|
||||
{
|
||||
struct proc *p;
|
||||
struct thread *td;
|
||||
@ -811,8 +823,18 @@ db_stack_trace_all(db_expr_t dummy, bool dummy2, db_expr_t dummy3,
|
||||
prev_jb = kdb_jmpbuf(jb);
|
||||
if (setjmp(jb) == 0) {
|
||||
FOREACH_THREAD_IN_PROC(p, td) {
|
||||
db_printf("\nTracing command %s pid %d tid %ld td %p\n",
|
||||
p->p_comm, p->p_pid, (long)td->td_tid, td);
|
||||
if (td->td_state == TDS_RUNNING)
|
||||
db_printf("\nTracing command %s pid %d"
|
||||
" tid %ld td %p (CPU %d)\n",
|
||||
p->p_comm, p->p_pid,
|
||||
(long)td->td_tid, td,
|
||||
td->td_oncpu);
|
||||
else if (active_only)
|
||||
continue;
|
||||
else
|
||||
db_printf("\nTracing command %s pid %d"
|
||||
" tid %ld td %p\n", p->p_comm,
|
||||
p->p_pid, (long)td->td_tid, td);
|
||||
db_trace_thread(td, -1);
|
||||
if (db_pager_quit) {
|
||||
kdb_jmpbuf(prev_jb);
|
||||
@ -824,6 +846,22 @@ db_stack_trace_all(db_expr_t dummy, bool dummy2, db_expr_t dummy3,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
db_stack_trace_active(db_expr_t dummy, bool dummy2, db_expr_t dummy3,
|
||||
char *dummy4)
|
||||
{
|
||||
|
||||
_db_stack_trace_all(true);
|
||||
}
|
||||
|
||||
static void
|
||||
db_stack_trace_all(db_expr_t dummy, bool dummy2, db_expr_t dummy3,
|
||||
char *dummy4)
|
||||
{
|
||||
|
||||
_db_stack_trace_all(false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Take the parsed expression value from the command line that was parsed
|
||||
* as a hexadecimal value and convert it as if the expression was parsed
|
||||
|
@ -57,7 +57,8 @@ db_term(db_expr_t *valuep)
|
||||
if (!db_value_of_name(db_tok_string, valuep) &&
|
||||
!db_value_of_name_pcpu(db_tok_string, valuep) &&
|
||||
!db_value_of_name_vnet(db_tok_string, valuep)) {
|
||||
db_error("Symbol not found\n");
|
||||
db_printf("Symbol '%s' not found\n", db_tok_string);
|
||||
db_error(NULL);
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
return (true);
|
||||
@ -89,12 +90,14 @@ db_term(db_expr_t *valuep)
|
||||
}
|
||||
if (t == tLPAREN) {
|
||||
if (!db_expression(valuep)) {
|
||||
db_error("Syntax error\n");
|
||||
db_printf("Expression syntax error after '%c'\n", '(');
|
||||
db_error(NULL);
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
t = db_read_token();
|
||||
if (t != tRPAREN) {
|
||||
db_error("Syntax error\n");
|
||||
db_printf("Expression syntax error -- expected '%c'\n", ')');
|
||||
db_error(NULL);
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
return (true);
|
||||
@ -164,7 +167,9 @@ db_mult_expr(db_expr_t *valuep)
|
||||
while (t == tSTAR || t == tSLASH || t == tPCT || t == tHASH ||
|
||||
t == tBIT_AND ) {
|
||||
if (!db_term(&rhs)) {
|
||||
db_printf("Expression syntax error after '%c'\n", '!');
|
||||
db_printf("Expression syntax error after '%c'\n",
|
||||
t == tSTAR ? '*' : t == tSLASH ? '/' : t == tPCT ? '%' :
|
||||
t == tHASH ? '#' : '&');
|
||||
db_error(NULL);
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
@ -177,7 +182,7 @@ db_mult_expr(db_expr_t *valuep)
|
||||
break;
|
||||
default:
|
||||
if (rhs == 0) {
|
||||
db_error("Divide by 0\n");
|
||||
db_error("Division by 0\n");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
if (t == tSLASH)
|
||||
@ -199,7 +204,6 @@ db_add_expr(db_expr_t *valuep)
|
||||
{
|
||||
db_expr_t lhs, rhs;
|
||||
int t;
|
||||
char c;
|
||||
|
||||
if (!db_mult_expr(&lhs))
|
||||
return (false);
|
||||
@ -207,8 +211,8 @@ db_add_expr(db_expr_t *valuep)
|
||||
t = db_read_token();
|
||||
while (t == tPLUS || t == tMINUS || t == tBIT_OR) {
|
||||
if (!db_mult_expr(&rhs)) {
|
||||
c = db_tok_string[0];
|
||||
db_printf("Expression syntax error after '%c'\n", c);
|
||||
db_printf("Expression syntax error after '%c'\n",
|
||||
t == tPLUS ? '+' : t == tMINUS ? '-' : '|');
|
||||
db_error(NULL);
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
@ -243,11 +247,14 @@ db_shift_expr(db_expr_t *valuep)
|
||||
t = db_read_token();
|
||||
while (t == tSHIFT_L || t == tSHIFT_R) {
|
||||
if (!db_add_expr(&rhs)) {
|
||||
db_error("Syntax error\n");
|
||||
db_printf("Expression syntax error after '%s'\n",
|
||||
t == tSHIFT_L ? "<<" : ">>");
|
||||
db_error(NULL);
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
if (rhs < 0) {
|
||||
db_error("Negative shift amount\n");
|
||||
db_printf("Negative shift amount %jd\n", (intmax_t)rhs);
|
||||
db_error(NULL);
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
if (t == tSHIFT_L)
|
||||
@ -269,7 +276,6 @@ db_logical_relation_expr(
|
||||
{
|
||||
db_expr_t lhs, rhs;
|
||||
int t;
|
||||
char op[3];
|
||||
|
||||
if (!db_shift_expr(&lhs))
|
||||
return (false);
|
||||
@ -277,11 +283,11 @@ db_logical_relation_expr(
|
||||
t = db_read_token();
|
||||
while (t == tLOG_EQ || t == tLOG_NOT_EQ || t == tGREATER ||
|
||||
t == tGREATER_EQ || t == tLESS || t == tLESS_EQ) {
|
||||
op[0] = db_tok_string[0];
|
||||
op[1] = db_tok_string[1];
|
||||
op[2] = 0;
|
||||
if (!db_shift_expr(&rhs)) {
|
||||
db_printf("Expression syntax error after \"%s\"\n", op);
|
||||
db_printf("Expression syntax error after '%s'\n",
|
||||
t == tLOG_EQ ? "==" : t == tLOG_NOT_EQ ? "!=" :
|
||||
t == tGREATER ? ">" : t == tGREATER_EQ ? ">=" :
|
||||
t == tLESS ? "<" : "<=");
|
||||
db_error(NULL);
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
@ -259,6 +259,78 @@ bcma_suspend_core(device_t dev, device_t child)
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
bcma_read_config(device_t dev, device_t child, bus_size_t offset, u_int width)
|
||||
{
|
||||
struct bcma_devinfo *dinfo;
|
||||
struct bhnd_resource *r;
|
||||
|
||||
/* Must be a directly attached child core */
|
||||
if (device_get_parent(child) != dev)
|
||||
return (UINT32_MAX);
|
||||
|
||||
/* Fetch the agent registers */
|
||||
dinfo = device_get_ivars(child);
|
||||
if ((r = dinfo->res_agent) == NULL)
|
||||
return (UINT32_MAX);
|
||||
|
||||
/* Verify bounds */
|
||||
if (offset > rman_get_size(r->res))
|
||||
return (UINT32_MAX);
|
||||
|
||||
if (rman_get_size(r->res) - offset < width)
|
||||
return (UINT32_MAX);
|
||||
|
||||
switch (width) {
|
||||
case 1:
|
||||
return (bhnd_bus_read_1(r, offset));
|
||||
case 2:
|
||||
return (bhnd_bus_read_2(r, offset));
|
||||
case 4:
|
||||
return (bhnd_bus_read_4(r, offset));
|
||||
default:
|
||||
return (UINT32_MAX);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bcma_write_config(device_t dev, device_t child, bus_size_t offset, uint32_t val,
|
||||
u_int width)
|
||||
{
|
||||
struct bcma_devinfo *dinfo;
|
||||
struct bhnd_resource *r;
|
||||
|
||||
/* Must be a directly attached child core */
|
||||
if (device_get_parent(child) != dev)
|
||||
return;
|
||||
|
||||
/* Fetch the agent registers */
|
||||
dinfo = device_get_ivars(child);
|
||||
if ((r = dinfo->res_agent) == NULL)
|
||||
return;
|
||||
|
||||
/* Verify bounds */
|
||||
if (offset > rman_get_size(r->res))
|
||||
return;
|
||||
|
||||
if (rman_get_size(r->res) - offset < width)
|
||||
return;
|
||||
|
||||
switch (width) {
|
||||
case 1:
|
||||
bhnd_bus_write_1(r, offset, val);
|
||||
break;
|
||||
case 2:
|
||||
bhnd_bus_write_2(r, offset, val);
|
||||
break;
|
||||
case 4:
|
||||
bhnd_bus_write_4(r, offset, val);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static u_int
|
||||
bcma_get_port_count(device_t dev, device_t child, bhnd_port_type type)
|
||||
{
|
||||
@ -420,6 +492,42 @@ bcma_free_bhnd_dinfo(device_t dev, struct bhnd_devinfo *dinfo)
|
||||
bcma_free_dinfo(dev, (struct bcma_devinfo *)dinfo);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
bcma_get_core_table(device_t dev, device_t child, struct bhnd_core_info **cores,
|
||||
u_int *num_cores)
|
||||
{
|
||||
struct bcma_softc *sc;
|
||||
struct bcma_erom erom;
|
||||
const struct bhnd_chipid *cid;
|
||||
struct resource *r;
|
||||
int error;
|
||||
int rid;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
/* Map the EROM table. */
|
||||
cid = BHND_BUS_GET_CHIPID(dev, dev);
|
||||
rid = 0;
|
||||
r = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, cid->enum_addr,
|
||||
cid->enum_addr + BCMA_EROM_TABLE_SIZE, BCMA_EROM_TABLE_SIZE,
|
||||
RF_ACTIVE);
|
||||
if (r == NULL) {
|
||||
device_printf(dev, "failed to allocate EROM resource\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* Enumerate all declared cores */
|
||||
if ((error = bcma_erom_open(&erom, r, BCMA_EROM_TABLE_START)))
|
||||
goto cleanup;
|
||||
|
||||
error = bcma_erom_get_core_info(&erom, cores, num_cores);
|
||||
|
||||
cleanup:
|
||||
bus_release_resource(dev, SYS_RES_MEMORY, rid, r);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan a device enumeration ROM table, adding all valid discovered cores to
|
||||
* the bus.
|
||||
@ -473,6 +581,9 @@ bcma_add_children(device_t bus, struct resource *erom_res, bus_size_t erom_offse
|
||||
* unpopulated, the device shouldn't be used. */
|
||||
if (bhnd_is_hw_disabled(child))
|
||||
device_disable(child);
|
||||
|
||||
/* Issue bus callback for fully initialized child. */
|
||||
BHND_BUS_CHILD_ADDED(bus, child);
|
||||
}
|
||||
|
||||
/* Hit EOF parsing cores? */
|
||||
@ -502,8 +613,11 @@ static device_method_t bcma_methods[] = {
|
||||
DEVMETHOD(bhnd_bus_find_hostb_device, bcma_find_hostb_device),
|
||||
DEVMETHOD(bhnd_bus_alloc_devinfo, bcma_alloc_bhnd_dinfo),
|
||||
DEVMETHOD(bhnd_bus_free_devinfo, bcma_free_bhnd_dinfo),
|
||||
DEVMETHOD(bhnd_bus_get_core_table, bcma_get_core_table),
|
||||
DEVMETHOD(bhnd_bus_reset_core, bcma_reset_core),
|
||||
DEVMETHOD(bhnd_bus_suspend_core, bcma_suspend_core),
|
||||
DEVMETHOD(bhnd_bus_read_config, bcma_read_config),
|
||||
DEVMETHOD(bhnd_bus_write_config, bcma_write_config),
|
||||
DEVMETHOD(bhnd_bus_get_port_count, bcma_get_port_count),
|
||||
DEVMETHOD(bhnd_bus_get_region_count, bcma_get_region_count),
|
||||
DEVMETHOD(bhnd_bus_get_port_rid, bcma_get_port_rid),
|
||||
|
@ -51,15 +51,22 @@ __FBSDID("$FreeBSD$");
|
||||
static int
|
||||
bcma_bhndb_probe(device_t dev)
|
||||
{
|
||||
const struct bhnd_chipid *cid;
|
||||
const struct bhnd_chipid *cid;
|
||||
int error;
|
||||
|
||||
/* Defer to default probe implementation */
|
||||
if ((error = bcma_probe(dev)) > 0)
|
||||
return (error);
|
||||
|
||||
/* Check bus type */
|
||||
cid = BHNDB_GET_CHIPID(device_get_parent(dev), dev);
|
||||
if (cid->chip_type != BHND_CHIPTYPE_BCMA)
|
||||
return (ENXIO);
|
||||
|
||||
/* Delegate to default probe implementation */
|
||||
return (bcma_probe(dev));
|
||||
/* Set device description */
|
||||
bhnd_set_default_bus_desc(dev, cid);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -109,6 +109,19 @@
|
||||
#define BCMA_DMP_OOBDINWIDTH 0x364
|
||||
#define BCMA_DMP_OOBDOUTWIDTH 0x368
|
||||
|
||||
/* The exact interpretation of these bits is unverified; these
|
||||
* are our best guesses as to their use */
|
||||
#define BCMA_DMP_OOBSEL_MASK 0xFF /**< OOBSEL config mask */
|
||||
#define BCMA_DMP_OOBSEL_0_MASK BCMA_DMP_OOBSEL_MASK
|
||||
#define BCMA_DMP_OOBSEL_1_MASK BCMA_DMP_OOBSEL_MASK
|
||||
#define BCMA_DMP_OOBSEL_2_MASK BCMA_DMP_OOBSEL_MASK
|
||||
#define BCMA_DMP_OOBSEL_3_MASK BCMA_DMP_OOBSEL_MASK
|
||||
#define BCMA_DMP_OOBSEL_0_SHIFT 0 /**< first OOBSEL config */
|
||||
#define BCMA_DMP_OOBSEL_1_SHIFT 8 /**< second OOBSEL config */
|
||||
#define BCMA_DMP_OOBSEL_2_SHIFT 16 /**< third OOBSEL config */
|
||||
#define BCMA_DMP_OOBSEL_3_SHIFT 24 /**< fouth OOBSEL config */
|
||||
#define BCMA_DMP_OOBSEL_EN (1 << 7) /**< enable bit */
|
||||
|
||||
// This was inherited from Broadcom's aidmp.h header
|
||||
// Is it required for any of our use-cases?
|
||||
#if 0 /* defined(IL_BIGENDIAN) && defined(BCMHND74K) */
|
||||
|
@ -65,10 +65,18 @@ static int erom_skip_mport(struct bcma_erom *erom);
|
||||
static int erom_skip_sport_region(struct bcma_erom *erom);
|
||||
|
||||
static int erom_seek_next(struct bcma_erom *erom, uint8_t etype);
|
||||
static int erom_region_to_port_type(struct bcma_erom *erom,
|
||||
uint8_t region_type, bhnd_port_type *port_type);
|
||||
|
||||
#define EROM_LOG(erom, fmt, ...) \
|
||||
device_printf(erom->dev, "erom[0x%llx]: " fmt, \
|
||||
(unsigned long long) (erom->offset), ##__VA_ARGS__);
|
||||
#define EROM_LOG(erom, fmt, ...) do { \
|
||||
if (erom->dev != NULL) { \
|
||||
device_printf(erom->dev, "erom[0x%llx]: " fmt, \
|
||||
(unsigned long long) (erom->offset), ##__VA_ARGS__);\
|
||||
} else { \
|
||||
printf("erom[0x%llx]: " fmt, \
|
||||
(unsigned long long) (erom->offset), ##__VA_ARGS__);\
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
/**
|
||||
* Open an EROM table for reading.
|
||||
@ -82,11 +90,37 @@ static int erom_seek_next(struct bcma_erom *erom, uint8_t etype);
|
||||
* @retval non-zero if the erom table could not be opened.
|
||||
*/
|
||||
int
|
||||
bcma_erom_open(struct bcma_erom *erom, struct resource *r, bus_size_t offset)
|
||||
bcma_erom_open(struct bcma_erom *erom, struct resource *r,
|
||||
bus_size_t offset)
|
||||
{
|
||||
return (bhnd_erom_bus_space_open(erom, rman_get_device(r),
|
||||
rman_get_bustag(r), rman_get_bushandle(r), offset));
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open an EROM table for reading using the provided bus space tag and
|
||||
* handle.
|
||||
*
|
||||
* @param[out] erom On success, will be populated with a valid EROM
|
||||
* read state.
|
||||
* @param dev The owning device, or NULL if none.
|
||||
* @param bst EROM table bus space tag.
|
||||
* @param bsh EROM table bus space handle.
|
||||
* @param offset Offset of the EROM core from @p resource.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval non-zero if the erom table could not be opened.
|
||||
*/
|
||||
int
|
||||
bhnd_erom_bus_space_open(struct bcma_erom *erom, device_t dev,
|
||||
bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t offset)
|
||||
{
|
||||
/* Initialize the EROM reader */
|
||||
erom->dev = rman_get_device(r);
|
||||
erom->r = r;
|
||||
erom->dev = dev;
|
||||
erom->bst = bst;
|
||||
erom->bsh = bsh;
|
||||
erom->start = offset + BCMA_EROM_TABLE_START;
|
||||
erom->offset = 0;
|
||||
|
||||
@ -145,7 +179,8 @@ bcma_erom_peek32(struct bcma_erom *erom, uint32_t *entry)
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
*entry = bus_read_4(erom->r, erom->start + erom->offset);
|
||||
*entry = bus_space_read_4(erom->bst, erom->bsh,
|
||||
erom->start + erom->offset);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -299,6 +334,20 @@ bcma_erom_reset(struct bcma_erom *erom)
|
||||
erom->offset = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Seek to the next core entry.
|
||||
*
|
||||
* @param erom EROM read state.
|
||||
* @retval 0 success
|
||||
* @retval ENOENT The end of the EROM table was reached.
|
||||
* @retval non-zero Reading or parsing failed.
|
||||
*/
|
||||
int
|
||||
bcma_erom_seek_next_core(struct bcma_erom *erom)
|
||||
{
|
||||
return (erom_seek_next(erom, BCMA_EROM_ENTRY_TYPE_CORE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Seek to the requested core entry.
|
||||
*
|
||||
@ -386,6 +435,153 @@ bcma_erom_parse_core(struct bcma_erom *erom, struct bcma_erom_core *core)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Seek to a region record associated with @p core_index.
|
||||
*
|
||||
* @param erom EROM read state.
|
||||
* @param core_index The index of the core record to be searched.
|
||||
* @param port_type The port type to search for.
|
||||
* @param port_num The port number to search for.
|
||||
* @param region_num The region number to search for.
|
||||
* @retval 0 success
|
||||
* @retval ENOENT The requested region was not found.
|
||||
* @retval non-zero Reading or parsing failed.
|
||||
*/
|
||||
int
|
||||
bcma_erom_seek_core_sport_region(struct bcma_erom *erom, u_int core_index,
|
||||
bhnd_port_type port_type, u_int port_num, u_int region_num)
|
||||
{
|
||||
struct bcma_erom_core core;
|
||||
uint32_t entry;
|
||||
uint8_t region_port, region_type;
|
||||
bool found;
|
||||
int error;
|
||||
|
||||
if ((error = bcma_erom_seek_core_index(erom, core_index)))
|
||||
return (error);
|
||||
|
||||
if ((error = bcma_erom_parse_core(erom, &core)))
|
||||
return (error);
|
||||
|
||||
/* Skip master ports */
|
||||
for (u_long i = 0; i < core.num_mport; i++) {
|
||||
if ((error = erom_skip_mport(erom)))
|
||||
return (error);
|
||||
}
|
||||
|
||||
/* Seek to the region block for the given port type */
|
||||
found = false;
|
||||
while (1) {
|
||||
bhnd_port_type p_type;
|
||||
uint8_t r_type;
|
||||
|
||||
if ((error = bcma_erom_peek32(erom, &entry)))
|
||||
return (error);
|
||||
|
||||
if (!BCMA_EROM_ENTRY_IS(entry, REGION))
|
||||
return (ENOENT);
|
||||
|
||||
/* Expected region type? */
|
||||
r_type = BCMA_EROM_GET_ATTR(entry, REGION_TYPE);
|
||||
if ((error = erom_region_to_port_type(erom, r_type, &p_type)))
|
||||
return (error);
|
||||
|
||||
if (p_type == port_type) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Skip to next entry */
|
||||
if ((error = erom_skip_sport_region(erom)))
|
||||
return (error);
|
||||
}
|
||||
|
||||
if (!found)
|
||||
return (ENOENT);
|
||||
|
||||
/* Found the appropriate port type block; now find the region records
|
||||
* for the given port number */
|
||||
found = false;
|
||||
for (u_int i = 0; i <= port_num; i++) {
|
||||
bhnd_port_type p_type;
|
||||
|
||||
if ((error = bcma_erom_peek32(erom, &entry)))
|
||||
return (error);
|
||||
|
||||
if (!BCMA_EROM_ENTRY_IS(entry, REGION))
|
||||
return (ENOENT);
|
||||
|
||||
/* Fetch the type/port of the first region entry */
|
||||
region_type = BCMA_EROM_GET_ATTR(entry, REGION_TYPE);
|
||||
region_port = BCMA_EROM_GET_ATTR(entry, REGION_PORT);
|
||||
|
||||
/* Have we found the region entries for the desired port? */
|
||||
if (i == port_num) {
|
||||
error = erom_region_to_port_type(erom, region_type,
|
||||
&p_type);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
if (p_type == port_type)
|
||||
found = true;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* Otherwise, seek to next block of region records */
|
||||
while (1) {
|
||||
uint8_t next_type, next_port;
|
||||
|
||||
if ((error = erom_skip_sport_region(erom)))
|
||||
return (error);
|
||||
|
||||
if ((error = bcma_erom_peek32(erom, &entry)))
|
||||
return (error);
|
||||
|
||||
if (!BCMA_EROM_ENTRY_IS(entry, REGION))
|
||||
return (ENOENT);
|
||||
|
||||
next_type = BCMA_EROM_GET_ATTR(entry, REGION_TYPE);
|
||||
next_port = BCMA_EROM_GET_ATTR(entry, REGION_PORT);
|
||||
|
||||
if (next_type != region_type ||
|
||||
next_port != region_port)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
return (ENOENT);
|
||||
|
||||
/* Finally, search for the requested region number */
|
||||
for (u_int i = 0; i <= region_num; i++) {
|
||||
uint8_t next_port, next_type;
|
||||
|
||||
if ((error = bcma_erom_peek32(erom, &entry)))
|
||||
return (error);
|
||||
|
||||
if (!BCMA_EROM_ENTRY_IS(entry, REGION))
|
||||
return (ENOENT);
|
||||
|
||||
/* Check for the end of the region block */
|
||||
next_type = BCMA_EROM_GET_ATTR(entry, REGION_TYPE);
|
||||
next_port = BCMA_EROM_GET_ATTR(entry, REGION_PORT);
|
||||
|
||||
if (next_type != region_type ||
|
||||
next_port != region_port)
|
||||
break;
|
||||
|
||||
if (i == region_num)
|
||||
return (0);
|
||||
|
||||
if ((error = erom_skip_sport_region(erom)))
|
||||
return (error);
|
||||
}
|
||||
|
||||
/* Not found */
|
||||
return (ENOENT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the next master port descriptor from the EROM table.
|
||||
*
|
||||
@ -491,6 +687,25 @@ bcma_erom_parse_sport_region(struct bcma_erom *erom,
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a bcma_erom_core record to its bhnd_core_info representation.
|
||||
*
|
||||
* @param core EROM core record to convert.
|
||||
* @param core_idx The core index of @p core.
|
||||
* @param core_unit The core unit of @p core.
|
||||
* @param[out] info The populated bhnd_core_info representation.
|
||||
*/
|
||||
void
|
||||
bcma_erom_to_core_info(const struct bcma_erom_core *core, u_int core_idx,
|
||||
int core_unit, struct bhnd_core_info *info)
|
||||
{
|
||||
info->vendor = core->vendor;
|
||||
info->device = core->device;
|
||||
info->hwrev = core->rev;
|
||||
info->core_idx = core_idx;
|
||||
info->unit = core_unit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse all cores descriptors from @p erom and return the array
|
||||
* in @p cores and the count in @p num_cores. The current EROM read position
|
||||
@ -545,7 +760,8 @@ bcma_erom_get_core_info(struct bcma_erom *erom,
|
||||
/* Parse all core descriptors */
|
||||
bcma_erom_reset(erom);
|
||||
for (u_int i = 0; i < count; i++) {
|
||||
struct bcma_erom_core core;
|
||||
struct bcma_erom_core core;
|
||||
int unit;
|
||||
|
||||
/* Parse the core */
|
||||
error = erom_seek_next(erom, BCMA_EROM_ENTRY_TYPE_CORE);
|
||||
@ -555,20 +771,17 @@ bcma_erom_get_core_info(struct bcma_erom *erom,
|
||||
error = bcma_erom_parse_core(erom, &core);
|
||||
if (error)
|
||||
goto cleanup;
|
||||
|
||||
/* Convert to a bhnd info record */
|
||||
buffer[i].vendor = core.vendor;
|
||||
buffer[i].device = core.device;
|
||||
buffer[i].hwrev = core.rev;
|
||||
buffer[i].core_idx = i;
|
||||
buffer[i].unit = 0;
|
||||
|
||||
/* Determine the unit number */
|
||||
unit = 0;
|
||||
for (u_int j = 0; j < i; j++) {
|
||||
if (buffer[i].vendor == buffer[j].vendor &&
|
||||
buffer[i].device == buffer[j].device)
|
||||
buffer[i].unit++;
|
||||
unit++;
|
||||
}
|
||||
|
||||
/* Convert to a bhnd info record */
|
||||
bcma_erom_to_core_info(&core, i, unit, &buffer[i]);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
@ -585,6 +798,33 @@ cleanup:
|
||||
return (error);
|
||||
}
|
||||
|
||||
/**
|
||||
* Map an EROM region type to its corresponding port type.
|
||||
*
|
||||
* @param region_type Region type value.
|
||||
* @param[out] port_type On success, the corresponding port type.
|
||||
*/
|
||||
static int
|
||||
erom_region_to_port_type(struct bcma_erom *erom, uint8_t region_type,
|
||||
bhnd_port_type *port_type)
|
||||
{
|
||||
switch (region_type) {
|
||||
case BCMA_EROM_REGION_TYPE_DEVICE:
|
||||
*port_type = BHND_PORT_DEVICE;
|
||||
return (0);
|
||||
case BCMA_EROM_REGION_TYPE_BRIDGE:
|
||||
*port_type = BHND_PORT_BRIDGE;
|
||||
return (0);
|
||||
case BCMA_EROM_REGION_TYPE_MWRAP:
|
||||
case BCMA_EROM_REGION_TYPE_SWRAP:
|
||||
*port_type = BHND_PORT_AGENT;
|
||||
return (0);
|
||||
default:
|
||||
EROM_LOG(erom, "unsupported region type %hhx\n",
|
||||
region_type);
|
||||
return (EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register all MMIO region descriptors for the given slave port.
|
||||
@ -608,24 +848,10 @@ erom_corecfg_fill_port_regions(struct bcma_erom *erom,
|
||||
bhnd_port_type port_type;
|
||||
|
||||
error = 0;
|
||||
|
||||
|
||||
/* Determine the port type for this region type. */
|
||||
switch (region_type) {
|
||||
case BCMA_EROM_REGION_TYPE_DEVICE:
|
||||
port_type = BHND_PORT_DEVICE;
|
||||
break;
|
||||
case BCMA_EROM_REGION_TYPE_BRIDGE:
|
||||
port_type = BHND_PORT_BRIDGE;
|
||||
break;
|
||||
case BCMA_EROM_REGION_TYPE_MWRAP:
|
||||
case BCMA_EROM_REGION_TYPE_SWRAP:
|
||||
port_type = BHND_PORT_AGENT;
|
||||
break;
|
||||
default:
|
||||
EROM_LOG(erom, "unsupported region type %hhx\n",
|
||||
region_type);
|
||||
return (EINVAL);
|
||||
}
|
||||
if ((error = erom_region_to_port_type(erom, region_type, &port_type)))
|
||||
return (error);
|
||||
|
||||
/* Fetch the list to be populated */
|
||||
sports = bcma_corecfg_get_port_list(corecfg, port_type);
|
||||
|
@ -40,10 +40,11 @@
|
||||
* EROM read context.
|
||||
*/
|
||||
struct bcma_erom {
|
||||
device_t dev; /**< EROM parent device */
|
||||
struct resource *r; /**< EROM table resource. */
|
||||
bus_size_t start; /**< EROM table offset */
|
||||
bus_size_t offset; /**< current read offset */
|
||||
device_t dev; /**< EROM parent device */
|
||||
bus_space_tag_t bst; /**< EROM table bus space */
|
||||
bus_space_handle_t bsh; /**< EROM table bus handle */
|
||||
bus_size_t start; /**< EROM table offset */
|
||||
bus_size_t offset; /**< current read offset */
|
||||
};
|
||||
|
||||
/** EROM core descriptor. */
|
||||
@ -78,22 +79,34 @@ struct bcma_erom_sport_region {
|
||||
int bcma_erom_open(struct bcma_erom *erom, struct resource *r,
|
||||
bus_size_t offset);
|
||||
|
||||
int bhnd_erom_bus_space_open(struct bcma_erom *erom, device_t owner,
|
||||
bus_space_tag_t bst, bus_space_handle_t bsh,
|
||||
bus_size_t offset);
|
||||
|
||||
int bcma_erom_peek32(struct bcma_erom *erom, uint32_t *entry);
|
||||
bus_size_t bcma_erom_tell(struct bcma_erom *erom);
|
||||
void bcma_erom_seek(struct bcma_erom *erom, bus_size_t offset);
|
||||
void bcma_erom_reset(struct bcma_erom *erom);
|
||||
|
||||
int bcma_erom_seek_next_core(struct bcma_erom *erom);
|
||||
int bcma_erom_seek_core_index(struct bcma_erom *erom,
|
||||
u_int core_index);
|
||||
int bcma_erom_parse_core(struct bcma_erom *erom,
|
||||
struct bcma_erom_core *core);
|
||||
|
||||
int bcma_erom_seek_core_sport_region(struct bcma_erom *erom,
|
||||
u_int core_index, bhnd_port_type port_type, u_int port_num,
|
||||
u_int region_num);
|
||||
|
||||
int bcma_erom_parse_mport(struct bcma_erom *erom,
|
||||
struct bcma_erom_mport *mport);
|
||||
|
||||
int bcma_erom_parse_sport_region(struct bcma_erom *erom,
|
||||
struct bcma_erom_sport_region *region);
|
||||
|
||||
void bcma_erom_to_core_info(const struct bcma_erom_core *core,
|
||||
u_int core_idx, int core_unit, struct bhnd_core_info *info);
|
||||
|
||||
int bcma_erom_get_core_info(struct bcma_erom *erom,
|
||||
struct bhnd_core_info **cores,
|
||||
u_int *num_cores);
|
||||
|
@ -82,6 +82,9 @@ bcma_nexus_probe(device_t dev)
|
||||
return (error);
|
||||
}
|
||||
|
||||
/* Set device description */
|
||||
bhnd_set_default_bus_desc(dev, &sc->bcma_cid);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2015 Landon Fuller <landon@landonf.org>
|
||||
* Copyright (c) 2015-2016 Landon Fuller <landonf@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -60,6 +60,9 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include <dev/bhnd/cores/chipc/chipcvar.h>
|
||||
|
||||
#include <dev/bhnd/cores/pmu/bhnd_pmu.h>
|
||||
#include <dev/bhnd/cores/pmu/bhnd_pmureg.h>
|
||||
|
||||
#include "bhnd_chipc_if.h"
|
||||
#include "bhnd_nvram_if.h"
|
||||
|
||||
@ -342,7 +345,7 @@ bhnd_finish_attach(struct bhnd_softc *sc)
|
||||
{
|
||||
struct chipc_caps *ccaps;
|
||||
|
||||
GIANT_REQUIRED; /* newbus */
|
||||
GIANT_REQUIRED; /* for newbus */
|
||||
|
||||
KASSERT(bus_current_pass >= BHND_FINISH_ATTACH_PASS,
|
||||
("bhnd_finish_attach() called in pass %d", bus_current_pass));
|
||||
@ -367,10 +370,11 @@ bhnd_finish_attach(struct bhnd_softc *sc)
|
||||
}
|
||||
|
||||
/* Look for a PMU */
|
||||
if (ccaps->pmu) {
|
||||
if (ccaps->pmu || ccaps->pwr_ctrl) {
|
||||
if ((sc->pmu_dev = bhnd_find_pmu(sc)) == NULL) {
|
||||
device_printf(sc->dev,
|
||||
"warning: PMU device not found\n");
|
||||
"attach failed: supported PMU not found\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
}
|
||||
|
||||
@ -478,8 +482,6 @@ found:
|
||||
static device_t
|
||||
bhnd_find_pmu(struct bhnd_softc *sc)
|
||||
{
|
||||
struct chipc_caps *ccaps;
|
||||
|
||||
/* Make sure we're holding Giant for newbus */
|
||||
GIANT_REQUIRED;
|
||||
|
||||
@ -494,11 +496,6 @@ bhnd_find_pmu(struct bhnd_softc *sc)
|
||||
return (sc->pmu_dev);
|
||||
}
|
||||
|
||||
if ((ccaps = bhnd_find_chipc_caps(sc)) == NULL)
|
||||
return (NULL);
|
||||
|
||||
if (!ccaps->pmu)
|
||||
return (NULL);
|
||||
|
||||
return (bhnd_find_platform_dev(sc, "bhnd_pmu"));
|
||||
}
|
||||
@ -625,6 +622,244 @@ bhnd_generic_get_probe_order(device_t dev, device_t child)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Default bhnd(4) bus driver implementation of BHND_BUS_ALLOC_PMU().
|
||||
*/
|
||||
int
|
||||
bhnd_generic_alloc_pmu(device_t dev, device_t child)
|
||||
{
|
||||
struct bhnd_softc *sc;
|
||||
struct bhnd_resource *br;
|
||||
struct chipc_caps *ccaps;
|
||||
struct bhnd_devinfo *dinfo;
|
||||
struct bhnd_core_pmu_info *pm;
|
||||
struct resource_list *rl;
|
||||
struct resource_list_entry *rle;
|
||||
device_t pmu_dev;
|
||||
bhnd_addr_t r_addr;
|
||||
bhnd_size_t r_size;
|
||||
bus_size_t pmu_regs;
|
||||
int error;
|
||||
|
||||
GIANT_REQUIRED; /* for newbus */
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
dinfo = device_get_ivars(child);
|
||||
pmu_regs = BHND_CLK_CTL_ST;
|
||||
|
||||
if ((ccaps = bhnd_find_chipc_caps(sc)) == NULL) {
|
||||
device_printf(sc->dev, "alloc_pmu failed: chipc "
|
||||
"capabilities unavailable\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
if ((pmu_dev = bhnd_find_pmu(sc)) == NULL) {
|
||||
device_printf(sc->dev,
|
||||
"pmu unavailable; cannot allocate request state\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* already allocated? */
|
||||
if (dinfo->pmu_info != NULL) {
|
||||
panic("duplicate PMU allocation for %s",
|
||||
device_get_nameunit(child));
|
||||
}
|
||||
|
||||
/* Determine address+size of the core's PMU register block */
|
||||
error = bhnd_get_region_addr(child, BHND_PORT_DEVICE, 0, 0, &r_addr,
|
||||
&r_size);
|
||||
if (error) {
|
||||
device_printf(sc->dev, "error fetching register block info for "
|
||||
"%s: %d\n", device_get_nameunit(child), error);
|
||||
return (error);
|
||||
}
|
||||
|
||||
if (r_size < (pmu_regs + sizeof(uint32_t))) {
|
||||
device_printf(sc->dev, "pmu offset %#jx would overrun %s "
|
||||
"register block\n", (uintmax_t)pmu_regs,
|
||||
device_get_nameunit(child));
|
||||
return (ENODEV);
|
||||
}
|
||||
|
||||
/* Locate actual resource containing the core's register block */
|
||||
if ((rl = BUS_GET_RESOURCE_LIST(dev, child)) == NULL) {
|
||||
device_printf(dev, "NULL resource list returned for %s\n",
|
||||
device_get_nameunit(child));
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
if ((rle = resource_list_find(rl, SYS_RES_MEMORY, 0)) == NULL) {
|
||||
device_printf(dev, "cannot locate core register resource "
|
||||
"for %s\n", device_get_nameunit(child));
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
if (rle->res == NULL) {
|
||||
device_printf(dev, "core register resource unallocated for "
|
||||
"%s\n", device_get_nameunit(child));
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
if (r_addr+pmu_regs < rman_get_start(rle->res) ||
|
||||
r_addr+pmu_regs >= rman_get_end(rle->res))
|
||||
{
|
||||
device_printf(dev, "core register resource does not map PMU "
|
||||
"registers at %#jx\n for %s\n", r_addr+pmu_regs,
|
||||
device_get_nameunit(child));
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* Adjust PMU register offset relative to the actual start address
|
||||
* of the core's register block allocation.
|
||||
*
|
||||
* XXX: The saved offset will be invalid if bus_adjust_resource is
|
||||
* used to modify the resource's start address.
|
||||
*/
|
||||
if (rman_get_start(rle->res) > r_addr)
|
||||
pmu_regs -= rman_get_start(rle->res) - r_addr;
|
||||
else
|
||||
pmu_regs -= r_addr - rman_get_start(rle->res);
|
||||
|
||||
/* Allocate and initialize PMU info */
|
||||
br = malloc(sizeof(struct bhnd_resource), M_BHND, M_NOWAIT);
|
||||
if (br == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
br->res = rle->res;
|
||||
br->direct = ((rman_get_flags(rle->res) & RF_ACTIVE) != 0);
|
||||
|
||||
pm = malloc(sizeof(*dinfo->pmu_info), M_BHND, M_NOWAIT);
|
||||
if (pm == NULL) {
|
||||
free(br, M_BHND);
|
||||
return (ENOMEM);
|
||||
}
|
||||
pm->pm_dev = child;
|
||||
pm->pm_pmu = pmu_dev;
|
||||
pm->pm_res = br;
|
||||
pm->pm_regs = pmu_regs;
|
||||
|
||||
dinfo->pmu_info = pm;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default bhnd(4) bus driver implementation of BHND_BUS_RELEASE_PMU().
|
||||
*/
|
||||
int
|
||||
bhnd_generic_release_pmu(device_t dev, device_t child)
|
||||
{
|
||||
struct bhnd_softc *sc;
|
||||
struct bhnd_devinfo *dinfo;
|
||||
device_t pmu;
|
||||
int error;
|
||||
|
||||
GIANT_REQUIRED; /* for newbus */
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
dinfo = device_get_ivars(child);
|
||||
|
||||
if ((pmu = bhnd_find_pmu(sc)) == NULL) {
|
||||
device_printf(sc->dev,
|
||||
"pmu unavailable; cannot release request state\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* dispatch release request */
|
||||
if (dinfo->pmu_info == NULL)
|
||||
panic("pmu over-release for %s", device_get_nameunit(child));
|
||||
|
||||
if ((error = BHND_PMU_CORE_RELEASE(pmu, dinfo->pmu_info)))
|
||||
return (error);
|
||||
|
||||
/* free PMU info */
|
||||
free(dinfo->pmu_info->pm_res, M_BHND);
|
||||
free(dinfo->pmu_info, M_BHND);
|
||||
dinfo->pmu_info = NULL;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default bhnd(4) bus driver implementation of BHND_BUS_REQUEST_CLOCK().
|
||||
*/
|
||||
int
|
||||
bhnd_generic_request_clock(device_t dev, device_t child, bhnd_clock clock)
|
||||
{
|
||||
struct bhnd_softc *sc;
|
||||
struct bhnd_devinfo *dinfo;
|
||||
struct bhnd_core_pmu_info *pm;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
dinfo = device_get_ivars(child);
|
||||
|
||||
if ((pm = dinfo->pmu_info) == NULL)
|
||||
panic("no active PMU request state");
|
||||
|
||||
/* dispatch request to PMU */
|
||||
return (BHND_PMU_CORE_REQ_CLOCK(pm->pm_pmu, pm, clock));
|
||||
}
|
||||
|
||||
/**
|
||||
* Default bhnd(4) bus driver implementation of BHND_BUS_ENABLE_CLOCKS().
|
||||
*/
|
||||
int
|
||||
bhnd_generic_enable_clocks(device_t dev, device_t child, uint32_t clocks)
|
||||
{
|
||||
struct bhnd_softc *sc;
|
||||
struct bhnd_devinfo *dinfo;
|
||||
struct bhnd_core_pmu_info *pm;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
dinfo = device_get_ivars(child);
|
||||
|
||||
if ((pm = dinfo->pmu_info) == NULL)
|
||||
panic("no active PMU request state");
|
||||
|
||||
/* dispatch request to PMU */
|
||||
return (BHND_PMU_CORE_EN_CLOCKS(pm->pm_pmu, pm, clocks));
|
||||
}
|
||||
|
||||
/**
|
||||
* Default bhnd(4) bus driver implementation of BHND_BUS_REQUEST_EXT_RSRC().
|
||||
*/
|
||||
int
|
||||
bhnd_generic_request_ext_rsrc(device_t dev, device_t child, u_int rsrc)
|
||||
{
|
||||
struct bhnd_softc *sc;
|
||||
struct bhnd_devinfo *dinfo;
|
||||
struct bhnd_core_pmu_info *pm;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
dinfo = device_get_ivars(child);
|
||||
|
||||
if ((pm = dinfo->pmu_info) == NULL)
|
||||
panic("no active PMU request state");
|
||||
|
||||
/* dispatch request to PMU */
|
||||
return (BHND_PMU_CORE_REQ_EXT_RSRC(pm->pm_pmu, pm, rsrc));
|
||||
}
|
||||
|
||||
/**
|
||||
* Default bhnd(4) bus driver implementation of BHND_BUS_RELEASE_EXT_RSRC().
|
||||
*/
|
||||
int
|
||||
bhnd_generic_release_ext_rsrc(device_t dev, device_t child, u_int rsrc)
|
||||
{
|
||||
struct bhnd_softc *sc;
|
||||
struct bhnd_devinfo *dinfo;
|
||||
struct bhnd_core_pmu_info *pm;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
dinfo = device_get_ivars(child);
|
||||
|
||||
if ((pm = dinfo->pmu_info) == NULL)
|
||||
panic("no active PMU request state");
|
||||
|
||||
/* dispatch request to PMU */
|
||||
return (BHND_PMU_CORE_RELEASE_EXT_RSRC(pm->pm_pmu, pm, rsrc));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Default bhnd(4) bus driver implementation of BHND_BUS_IS_REGION_VALID().
|
||||
*
|
||||
@ -815,12 +1050,20 @@ bhnd_generic_add_child(device_t dev, u_int order, const char *name, int unit)
|
||||
|
||||
device_set_ivars(child, dinfo);
|
||||
|
||||
/* Inform concrete bus driver. */
|
||||
BHND_BUS_CHILD_ADDED(dev, child);
|
||||
|
||||
return (child);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default bhnd(4) bus driver implementation of BHND_BUS_CHILD_ADDED().
|
||||
*
|
||||
* This implementation manages internal bhnd(4) state, and must be called
|
||||
* by subclassing drivers.
|
||||
*/
|
||||
void
|
||||
bhnd_generic_child_added(device_t dev, device_t child)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Default bhnd(4) bus driver implementation of BUS_CHILD_DELETED().
|
||||
*
|
||||
@ -836,8 +1079,17 @@ bhnd_generic_child_deleted(device_t dev, device_t child)
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
/* Free device info */
|
||||
if ((dinfo = device_get_ivars(child)) != NULL)
|
||||
if ((dinfo = device_get_ivars(child)) != NULL) {
|
||||
if (dinfo->pmu_info != NULL) {
|
||||
/* Releasing PMU requests automatically would be nice,
|
||||
* but we can't reference per-core PMU register
|
||||
* resource after driver detach */
|
||||
panic("%s leaked device pmu state\n",
|
||||
device_get_nameunit(child));
|
||||
}
|
||||
|
||||
BHND_BUS_FREE_DEVINFO(dev, dinfo);
|
||||
}
|
||||
|
||||
/* Clean up platform device references */
|
||||
if (sc->chipc_dev == child) {
|
||||
@ -998,9 +1250,20 @@ static device_method_t bhnd_methods[] = {
|
||||
|
||||
/* BHND interface */
|
||||
DEVMETHOD(bhnd_bus_get_chipid, bhnd_bus_generic_get_chipid),
|
||||
DEVMETHOD(bhnd_bus_get_probe_order, bhnd_generic_get_probe_order),
|
||||
DEVMETHOD(bhnd_bus_is_region_valid, bhnd_generic_is_region_valid),
|
||||
DEVMETHOD(bhnd_bus_is_hw_disabled, bhnd_bus_generic_is_hw_disabled),
|
||||
DEVMETHOD(bhnd_bus_read_board_info, bhnd_bus_generic_read_board_info),
|
||||
|
||||
DEVMETHOD(bhnd_bus_get_probe_order, bhnd_generic_get_probe_order),
|
||||
|
||||
DEVMETHOD(bhnd_bus_alloc_pmu, bhnd_generic_alloc_pmu),
|
||||
DEVMETHOD(bhnd_bus_release_pmu, bhnd_generic_release_pmu),
|
||||
DEVMETHOD(bhnd_bus_request_clock, bhnd_generic_request_clock),
|
||||
DEVMETHOD(bhnd_bus_enable_clocks, bhnd_generic_enable_clocks),
|
||||
DEVMETHOD(bhnd_bus_request_ext_rsrc, bhnd_generic_request_ext_rsrc),
|
||||
DEVMETHOD(bhnd_bus_release_ext_rsrc, bhnd_generic_release_ext_rsrc),
|
||||
|
||||
DEVMETHOD(bhnd_bus_child_added, bhnd_generic_child_added),
|
||||
DEVMETHOD(bhnd_bus_is_region_valid, bhnd_generic_is_region_valid),
|
||||
DEVMETHOD(bhnd_bus_get_nvram_var, bhnd_generic_get_nvram_var),
|
||||
|
||||
/* BHND interface (bus I/O) */
|
||||
|
@ -49,6 +49,9 @@ extern devclass_t bhnd_devclass;
|
||||
extern devclass_t bhnd_hostb_devclass;
|
||||
extern devclass_t bhnd_nvram_devclass;
|
||||
|
||||
#define BHND_CHIPID_MAX_NAMELEN 32 /**< maximum buffer required for a
|
||||
bhnd_format_chip_id() */
|
||||
|
||||
/**
|
||||
* bhnd child instance variables
|
||||
*/
|
||||
@ -254,6 +257,8 @@ bhnd_devclass_t bhnd_find_core_class(uint16_t vendor,
|
||||
const char *bhnd_core_name(const struct bhnd_core_info *ci);
|
||||
bhnd_devclass_t bhnd_core_class(const struct bhnd_core_info *ci);
|
||||
|
||||
int bhnd_format_chip_id(char *buffer, size_t size,
|
||||
uint16_t chip_id);
|
||||
|
||||
device_t bhnd_match_child(device_t dev,
|
||||
const struct bhnd_core_match *desc);
|
||||
@ -312,6 +317,10 @@ void bhnd_release_resources(device_t dev,
|
||||
struct bhnd_chipid bhnd_parse_chipid(uint32_t idreg,
|
||||
bhnd_addr_t enum_addr);
|
||||
|
||||
int bhnd_chipid_fixed_ncores(
|
||||
const struct bhnd_chipid *cid,
|
||||
uint16_t chipc_hwrev, uint8_t *ncores);
|
||||
|
||||
int bhnd_read_chipid(device_t dev,
|
||||
struct resource_spec *rs,
|
||||
bus_size_t chipc_offset,
|
||||
@ -321,6 +330,9 @@ void bhnd_set_custom_core_desc(device_t dev,
|
||||
const char *name);
|
||||
void bhnd_set_default_core_desc(device_t dev);
|
||||
|
||||
void bhnd_set_default_bus_desc(device_t dev,
|
||||
const struct bhnd_chipid *chip_id);
|
||||
|
||||
int bhnd_nvram_getvar_str(device_t dev,
|
||||
const char *name, char *buf, size_t len,
|
||||
size_t *rlen);
|
||||
@ -416,6 +428,93 @@ bhnd_get_chipid(device_t dev) {
|
||||
return (BHND_BUS_GET_CHIPID(device_get_parent(dev), dev));
|
||||
};
|
||||
|
||||
/**
|
||||
* Get a list of all cores discoverable on the bhnd bus.
|
||||
*
|
||||
* Enumerates all cores discoverable on @p dev, returning the list in
|
||||
* @p cores and the count in @p num_cores.
|
||||
*
|
||||
* The memory allocated for the list should be freed using
|
||||
* `free(*cores, M_BHND)`. @p cores and @p num_cores are not changed
|
||||
* when an error is returned.
|
||||
*
|
||||
* @param dev A bhnd bus child device.
|
||||
* @param[out] cores The table of core descriptors.
|
||||
* @param[out] num_cores The number of core descriptors in @p cores.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval non-zero if an error occurs enumerating @p dev, a regular UNIX
|
||||
* error code should be returned.
|
||||
*/
|
||||
static inline int
|
||||
bhnd_get_core_table(device_t dev, struct bhnd_core_info **cores,
|
||||
u_int *num_cores)
|
||||
{
|
||||
return (BHND_BUS_GET_CORE_TABLE(device_get_parent(dev), dev, cores,
|
||||
num_cores));
|
||||
}
|
||||
|
||||
/**
|
||||
* If supported by the chipset, return the clock source for the given clock.
|
||||
*
|
||||
* This function is only supported on early PWRCTL-equipped chipsets
|
||||
* that expose clock management via their host bridge interface. Currently,
|
||||
* this includes PCI (not PCIe) devices, with ChipCommon core revisions 0-9.
|
||||
*
|
||||
* @param dev A bhnd bus child device.
|
||||
* @param clock The clock for which a clock source will be returned.
|
||||
*
|
||||
* @retval bhnd_clksrc The clock source for @p clock.
|
||||
* @retval BHND_CLKSRC_UNKNOWN If @p clock is unsupported, or its
|
||||
* clock source is not known to the bus.
|
||||
*/
|
||||
static inline bhnd_clksrc
|
||||
bhnd_pwrctl_get_clksrc(device_t dev, bhnd_clock clock)
|
||||
{
|
||||
return (BHND_BUS_PWRCTL_GET_CLKSRC(device_get_parent(dev), dev, clock));
|
||||
}
|
||||
|
||||
/**
|
||||
* If supported by the chipset, gate @p clock
|
||||
*
|
||||
* This function is only supported on early PWRCTL-equipped chipsets
|
||||
* that expose clock management via their host bridge interface. Currently,
|
||||
* this includes PCI (not PCIe) devices, with ChipCommon core revisions 0-9.
|
||||
*
|
||||
* @param dev A bhnd bus child device.
|
||||
* @param clock The clock to be disabled.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval ENODEV If bus-level clock source management is not supported.
|
||||
* @retval ENXIO If bus-level management of @p clock is not supported.
|
||||
*/
|
||||
static inline int
|
||||
bhnd_pwrctl_gate_clock(device_t dev, bhnd_clock clock)
|
||||
{
|
||||
return (BHND_BUS_PWRCTL_GATE_CLOCK(device_get_parent(dev), dev, clock));
|
||||
}
|
||||
|
||||
/**
|
||||
* If supported by the chipset, ungate @p clock
|
||||
*
|
||||
* This function is only supported on early PWRCTL-equipped chipsets
|
||||
* that expose clock management via their host bridge interface. Currently,
|
||||
* this includes PCI (not PCIe) devices, with ChipCommon core revisions 0-9.
|
||||
*
|
||||
* @param dev A bhnd bus child device.
|
||||
* @param clock The clock to be enabled.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval ENODEV If bus-level clock source management is not supported.
|
||||
* @retval ENXIO If bus-level management of @p clock is not supported.
|
||||
*/
|
||||
static inline int
|
||||
bhnd_pwrctl_ungate_clock(device_t dev, bhnd_clock clock)
|
||||
{
|
||||
return (BHND_BUS_PWRCTL_UNGATE_CLOCK(device_get_parent(dev), dev,
|
||||
clock));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the BHND attachment type of the parent bhnd bus.
|
||||
*
|
||||
@ -453,6 +552,171 @@ bhnd_read_board_info(device_t dev, struct bhnd_board_info *info)
|
||||
return (BHND_BUS_READ_BOARD_INFO(device_get_parent(dev), dev, info));
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate and enable per-core PMU request handling for @p child.
|
||||
*
|
||||
* The region containing the core's PMU register block (if any) must be
|
||||
* allocated via bus_alloc_resource(9) (or bhnd_alloc_resource) before
|
||||
* calling bhnd_alloc_pmu(), and must not be released until after
|
||||
* calling bhnd_release_pmu().
|
||||
*
|
||||
* @param dev The parent of @p child.
|
||||
* @param child The requesting bhnd device.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval non-zero If allocating PMU request state otherwise fails, a
|
||||
* regular unix error code will be returned.
|
||||
*/
|
||||
static inline int
|
||||
bhnd_alloc_pmu(device_t dev)
|
||||
{
|
||||
return (BHND_BUS_ALLOC_PMU(device_get_parent(dev), dev));
|
||||
}
|
||||
|
||||
/**
|
||||
* Release any per-core PMU resources allocated for @p child. Any outstanding
|
||||
* PMU requests are are discarded.
|
||||
*
|
||||
* @param dev The parent of @p child.
|
||||
* @param child The requesting bhnd device.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval non-zero If releasing PMU request state otherwise fails, a
|
||||
* regular unix error code will be returned, and
|
||||
* the core state will be left unmodified.
|
||||
*/
|
||||
static inline int
|
||||
bhnd_release_pmu(device_t dev)
|
||||
{
|
||||
return (BHND_BUS_RELEASE_PMU(device_get_parent(dev), dev));
|
||||
}
|
||||
|
||||
/**
|
||||
* Request that @p clock (or faster) be routed to @p dev.
|
||||
*
|
||||
* A driver must ask the bhnd bus to allocate clock request state
|
||||
* via bhnd_alloc_pmu() before it can request clock resources.
|
||||
*
|
||||
* Request multiplexing is managed by the bus.
|
||||
*
|
||||
* @param dev The bhnd(4) device to which @p clock should be routed.
|
||||
* @param clock The requested clock source.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval ENODEV If an unsupported clock was requested.
|
||||
* @retval ENXIO If the PMU has not been initialized or is otherwise unvailable.
|
||||
*/
|
||||
static inline int
|
||||
bhnd_request_clock(device_t dev, bhnd_clock clock)
|
||||
{
|
||||
return (BHND_BUS_REQUEST_CLOCK(device_get_parent(dev), dev, clock));
|
||||
}
|
||||
|
||||
/**
|
||||
* Request that @p clocks be powered on behalf of @p dev.
|
||||
*
|
||||
* This will power any clock sources (e.g. XTAL, PLL, etc) required for
|
||||
* @p clocks and wait until they are ready, discarding any previous
|
||||
* requests by @p dev.
|
||||
*
|
||||
* Request multiplexing is managed by the bus.
|
||||
*
|
||||
* A driver must ask the bhnd bus to allocate clock request state
|
||||
* via bhnd_alloc_pmu() before it can request clock resources.
|
||||
*
|
||||
* @param dev The requesting bhnd(4) device.
|
||||
* @param clocks The clock(s) to be enabled.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval ENODEV If an unsupported clock was requested.
|
||||
* @retval ENXIO If the PMU has not been initialized or is otherwise unvailable.
|
||||
*/
|
||||
static inline int
|
||||
bhnd_enable_clocks(device_t dev, uint32_t clocks)
|
||||
{
|
||||
return (BHND_BUS_ENABLE_CLOCKS(device_get_parent(dev), dev, clocks));
|
||||
}
|
||||
|
||||
/**
|
||||
* Power up an external PMU-managed resource assigned to @p dev.
|
||||
*
|
||||
* A driver must ask the bhnd bus to allocate PMU request state
|
||||
* via bhnd_alloc_pmu() before it can request PMU resources.
|
||||
*
|
||||
* @param dev The requesting bhnd(4) device.
|
||||
* @param rsrc The core-specific external resource identifier.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval ENODEV If the PMU does not support @p rsrc.
|
||||
* @retval ENXIO If the PMU has not been initialized or is otherwise unvailable.
|
||||
*/
|
||||
static inline int
|
||||
bhnd_request_ext_rsrc(device_t dev, u_int rsrc)
|
||||
{
|
||||
return (BHND_BUS_REQUEST_EXT_RSRC(device_get_parent(dev), dev, rsrc));
|
||||
}
|
||||
|
||||
/**
|
||||
* Power down an external PMU-managed resource assigned to @p dev.
|
||||
*
|
||||
* A driver must ask the bhnd bus to allocate PMU request state
|
||||
* via bhnd_alloc_pmu() before it can request PMU resources.
|
||||
*
|
||||
* @param dev The requesting bhnd(4) device.
|
||||
* @param rsrc The core-specific external resource identifier.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval ENODEV If the PMU does not support @p rsrc.
|
||||
* @retval ENXIO If the PMU has not been initialized or is otherwise unvailable.
|
||||
*/
|
||||
static inline int
|
||||
bhnd_release_ext_rsrc(device_t dev, u_int rsrc)
|
||||
{
|
||||
return (BHND_BUS_RELEASE_EXT_RSRC(device_get_parent(dev), dev, rsrc));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Read @p width bytes at @p offset from the bus-specific agent/config
|
||||
* space of @p dev.
|
||||
*
|
||||
* @param dev The bhnd device for which @p offset should be read.
|
||||
* @param offset The offset to be read.
|
||||
* @param width The size of the access. Must be 1, 2 or 4 bytes.
|
||||
*
|
||||
* The exact behavior of this method is bus-specific. In the case of
|
||||
* bcma(4), this method provides access to the first agent port of @p child.
|
||||
*
|
||||
* @note Device drivers should only use this API for functionality
|
||||
* that is not available via another bhnd(4) function.
|
||||
*/
|
||||
static inline uint32_t
|
||||
bhnd_read_config(device_t dev, bus_size_t offset, u_int width)
|
||||
{
|
||||
return (BHND_BUS_READ_CONFIG(device_get_parent(dev), dev, offset,
|
||||
width));
|
||||
}
|
||||
|
||||
/**
|
||||
* Read @p width bytes at @p offset from the bus-specific agent/config
|
||||
* space of @p dev.
|
||||
*
|
||||
* @param dev The bhnd device for which @p offset should be read.
|
||||
* @param offset The offset to be written.
|
||||
* @param width The size of the access. Must be 1, 2 or 4 bytes.
|
||||
*
|
||||
* The exact behavior of this method is bus-specific. In the case of
|
||||
* bcma(4), this method provides access to the first agent port of @p child.
|
||||
*
|
||||
* @note Device drivers should only use this API for functionality
|
||||
* that is not available via another bhnd(4) function.
|
||||
*/
|
||||
static inline void
|
||||
bhnd_write_config(device_t dev, bus_size_t offset, uint32_t val, u_int width)
|
||||
{
|
||||
BHND_BUS_WRITE_CONFIG(device_get_parent(dev), dev, offset, val, width);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read an NVRAM variable, coerced to the requested @p type.
|
||||
*
|
||||
|
@ -56,11 +56,39 @@ CODE {
|
||||
panic("bhnd_bus_get_chipid unimplemented");
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_bus_null_get_core_table(device_t dev, device_t child,
|
||||
struct bhnd_core_info **cores, u_int *num_cores)
|
||||
{
|
||||
panic("bhnd_bus_get_core_table unimplemented");
|
||||
}
|
||||
|
||||
static bhnd_attach_type
|
||||
bhnd_bus_null_get_attach_type(device_t dev, device_t child)
|
||||
{
|
||||
panic("bhnd_bus_get_attach_type unimplemented");
|
||||
}
|
||||
|
||||
static bhnd_clksrc
|
||||
bhnd_bus_null_pwrctl_get_clksrc(device_t dev, device_t child,
|
||||
bhnd_clock clock)
|
||||
{
|
||||
return (BHND_CLKSRC_UNKNOWN);
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_bus_null_pwrctl_gate_clock(device_t dev, device_t child,
|
||||
bhnd_clock clock)
|
||||
{
|
||||
return (ENODEV);
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_bus_null_pwrctl_ungate_clock(device_t dev, device_t child,
|
||||
bhnd_clock clock)
|
||||
{
|
||||
return (ENODEV);
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_bus_null_read_board_info(device_t dev, device_t child,
|
||||
@ -74,6 +102,60 @@ CODE {
|
||||
{
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_bus_null_alloc_pmu(device_t dev, device_t child)
|
||||
{
|
||||
panic("bhnd_bus_alloc_pmu unimplemented");
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_bus_null_release_pmu(device_t dev, device_t child)
|
||||
{
|
||||
panic("bhnd_bus_release_pmu unimplemented");
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_bus_null_request_clock(device_t dev, device_t child,
|
||||
bhnd_clock clock)
|
||||
{
|
||||
panic("bhnd_bus_request_clock unimplemented");
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_bus_null_enable_clocks(device_t dev, device_t child,
|
||||
uint32_t clocks)
|
||||
{
|
||||
panic("bhnd_bus_enable_clocks unimplemented");
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_bus_null_request_ext_rsrc(device_t dev, device_t child,
|
||||
u_int rsrc)
|
||||
{
|
||||
panic("bhnd_bus_request_ext_rsrc unimplemented");
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_bus_null_release_ext_rsrc(device_t dev, device_t child,
|
||||
u_int rsrc)
|
||||
{
|
||||
panic("bhnd_bus_release_ext_rsrc unimplemented");
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
bhnd_bus_null_read_config(device_t dev, device_t child,
|
||||
bus_size_t offset, u_int width)
|
||||
{
|
||||
panic("bhnd_bus_null_read_config unimplemented");
|
||||
}
|
||||
|
||||
static void
|
||||
bhnd_bus_null_write_config(device_t dev, device_t child,
|
||||
bus_size_t offset, uint32_t val, u_int width)
|
||||
{
|
||||
panic("bhnd_bus_null_write_config unimplemented");
|
||||
}
|
||||
|
||||
static device_t
|
||||
bhnd_bus_null_find_hostb_device(device_t dev)
|
||||
{
|
||||
@ -195,6 +277,32 @@ METHOD const struct bhnd_chipid * get_chipid {
|
||||
device_t child;
|
||||
} DEFAULT bhnd_bus_null_get_chipid;
|
||||
|
||||
/**
|
||||
* Get a list of all cores discoverable on @p dev.
|
||||
*
|
||||
* Enumerates all cores discoverable on @p dev, returning the list in
|
||||
* @p cores and the count in @p num_cores.
|
||||
*
|
||||
* The memory allocated for the list should be freed using
|
||||
* `free(*cores, M_BHND)`. @p cores and @p num_cores are not changed
|
||||
* when an error is returned.
|
||||
*
|
||||
* @param dev The bhnd bus device.
|
||||
* @param child The requesting bhnd bus child.
|
||||
* @param[out] cores The table of core descriptors.
|
||||
* @param[out] num_cores The number of core descriptors in @p cores.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval non-zero if an error occurs enumerating @p dev, a regular UNIX
|
||||
* error code should be returned.
|
||||
*/
|
||||
METHOD int get_core_table {
|
||||
device_t dev;
|
||||
device_t child;
|
||||
struct bhnd_core_info **cores;
|
||||
u_int *num_cores;
|
||||
} DEFAULT bhnd_bus_null_get_core_table;
|
||||
|
||||
/**
|
||||
* Return the BHND attachment type of the parent bus.
|
||||
*
|
||||
@ -261,9 +369,8 @@ METHOD void free_devinfo {
|
||||
/**
|
||||
* Notify a bhnd bus that a child was added.
|
||||
*
|
||||
* Called at the end of BUS_ADD_CHILD() to allow the concrete bhnd(4)
|
||||
* driver instance to initialize any additional driver-specific state for the
|
||||
* child.
|
||||
* This method must be called by concrete bhnd(4) driver impementations
|
||||
* after @p child's bus state is fully initialized.
|
||||
*
|
||||
* @param dev The bhnd bus whose child is being added.
|
||||
* @param child The child added to @p dev.
|
||||
@ -303,6 +410,231 @@ METHOD int suspend_core {
|
||||
device_t child;
|
||||
}
|
||||
|
||||
/**
|
||||
* If supported by the chipset, return the clock source for the given clock.
|
||||
*
|
||||
* This function is only supported on early PWRCTL-equipped chipsets
|
||||
* that expose clock management via their host bridge interface. Currently,
|
||||
* this includes PCI (not PCIe) devices, with ChipCommon core revisions 0-9.
|
||||
*
|
||||
* @param dev The parent of @p child.
|
||||
* @param child The bhnd device requesting a clock source.
|
||||
* @param clock The clock for which a clock source will be returned.
|
||||
*
|
||||
* @retval bhnd_clksrc The clock source for @p clock.
|
||||
* @retval BHND_CLKSRC_UNKNOWN If @p clock is unsupported, or its
|
||||
* clock source is not known to the bus.
|
||||
*/
|
||||
METHOD bhnd_clksrc pwrctl_get_clksrc {
|
||||
device_t dev;
|
||||
device_t child;
|
||||
bhnd_clock clock;
|
||||
} DEFAULT bhnd_bus_null_pwrctl_get_clksrc;
|
||||
|
||||
/**
|
||||
* If supported by the chipset, gate the clock source for @p clock
|
||||
*
|
||||
* This function is only supported on early PWRCTL-equipped chipsets
|
||||
* that expose clock management via their host bridge interface. Currently,
|
||||
* this includes PCI (not PCIe) devices, with ChipCommon core revisions 0-9.
|
||||
*
|
||||
* @param dev The parent of @p child.
|
||||
* @param child The bhnd device requesting clock gating.
|
||||
* @param clock The clock to be disabled.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval ENODEV If bus-level clock source management is not supported.
|
||||
* @retval ENXIO If bus-level management of @p clock is not supported.
|
||||
*/
|
||||
METHOD int pwrctl_gate_clock {
|
||||
device_t dev;
|
||||
device_t child;
|
||||
bhnd_clock clock;
|
||||
} DEFAULT bhnd_bus_null_pwrctl_gate_clock;
|
||||
|
||||
/**
|
||||
* If supported by the chipset, ungate the clock source for @p clock
|
||||
*
|
||||
* This function is only supported on early PWRCTL-equipped chipsets
|
||||
* that expose clock management via their host bridge interface. Currently,
|
||||
* this includes PCI (not PCIe) devices, with ChipCommon core revisions 0-9.
|
||||
*
|
||||
* @param dev The parent of @p child.
|
||||
* @param child The bhnd device requesting clock gating.
|
||||
* @param clock The clock to be enabled.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval ENODEV If bus-level clock source management is not supported.
|
||||
* @retval ENXIO If bus-level management of @p clock is not supported.
|
||||
*/
|
||||
METHOD int pwrctl_ungate_clock {
|
||||
device_t dev;
|
||||
device_t child;
|
||||
bhnd_clock clock;
|
||||
} DEFAULT bhnd_bus_null_pwrctl_ungate_clock;
|
||||
|
||||
/**
|
||||
* Allocate and enable per-core PMU request handling for @p child.
|
||||
*
|
||||
* The region containing the core's PMU register block (if any) must be
|
||||
* allocated via bus_alloc_resource(9) (or bhnd_alloc_resource) before
|
||||
* calling BHND_BUS_ALLOC_PMU(), and must not be released until after
|
||||
* calling BHND_BUS_RELEASE_PMU().
|
||||
*
|
||||
* @param dev The parent of @p child.
|
||||
* @param child The requesting bhnd device.
|
||||
*/
|
||||
METHOD int alloc_pmu {
|
||||
device_t dev;
|
||||
device_t child;
|
||||
} DEFAULT bhnd_bus_null_alloc_pmu;
|
||||
|
||||
/**
|
||||
* Release per-core PMU resources allocated for @p child. Any
|
||||
* outstanding PMU requests are discarded.
|
||||
*
|
||||
* @param dev The parent of @p child.
|
||||
* @param child The requesting bhnd device.
|
||||
*/
|
||||
METHOD int release_pmu {
|
||||
device_t dev;
|
||||
device_t child;
|
||||
} DEFAULT bhnd_bus_null_release_pmu;
|
||||
|
||||
/**
|
||||
* Request that @p clock (or faster) be routed to @p child.
|
||||
*
|
||||
* A driver must ask the bhnd bus to allocate PMU request state
|
||||
* via BHND_BUS_ALLOC_PMU() before it can request clock resources.
|
||||
*
|
||||
* Request multiplexing is managed by the bus.
|
||||
*
|
||||
* @param dev The parent of @p child.
|
||||
* @param child The bhnd device requesting @p clock.
|
||||
* @param clock The requested clock source.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval ENODEV If an unsupported clock was requested.
|
||||
* @retval ENXIO If the PMU has not been initialized or is otherwise unvailable.
|
||||
*/
|
||||
METHOD int request_clock {
|
||||
device_t dev;
|
||||
device_t child;
|
||||
bhnd_clock clock;
|
||||
} DEFAULT bhnd_bus_null_request_clock;
|
||||
|
||||
/**
|
||||
* Request that @p clocks be powered on behalf of @p child.
|
||||
*
|
||||
* This will power on clock sources (e.g. XTAL, PLL, etc) required for
|
||||
* @p clocks and wait until they are ready, discarding any previous
|
||||
* requests by @p child.
|
||||
*
|
||||
* Request multiplexing is managed by the bus.
|
||||
*
|
||||
* A driver must ask the bhnd bus to allocate PMU request state
|
||||
* via BHND_BUS_ALLOC_PMU() before it can request clock resources.
|
||||
*
|
||||
* @param dev The parent of @p child.
|
||||
* @param child The bhnd device requesting @p clock.
|
||||
* @param clock The requested clock source.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval ENODEV If an unsupported clock was requested.
|
||||
* @retval ENXIO If the PMU has not been initialized or is otherwise unvailable.
|
||||
*/
|
||||
METHOD int enable_clocks {
|
||||
device_t dev;
|
||||
device_t child;
|
||||
uint32_t clocks;
|
||||
} DEFAULT bhnd_bus_null_enable_clocks;
|
||||
|
||||
/**
|
||||
* Power up an external PMU-managed resource assigned to @p child.
|
||||
*
|
||||
* A driver must ask the bhnd bus to allocate PMU request state
|
||||
* via BHND_BUS_ALLOC_PMU() before it can request PMU resources.
|
||||
*
|
||||
* @param dev The parent of @p child.
|
||||
* @param child The bhnd device requesting @p rsrc.
|
||||
* @param rsrc The core-specific external resource identifier.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval ENODEV If the PMU does not support @p rsrc.
|
||||
* @retval ENXIO If the PMU has not been initialized or is otherwise unvailable.
|
||||
*/
|
||||
METHOD int request_ext_rsrc {
|
||||
device_t dev;
|
||||
device_t child;
|
||||
u_int rsrc;
|
||||
} DEFAULT bhnd_bus_null_request_ext_rsrc;
|
||||
|
||||
/**
|
||||
* Power down an external PMU-managed resource assigned to @p child.
|
||||
*
|
||||
* A driver must ask the bhnd bus to allocate PMU request state
|
||||
* via BHND_BUS_ALLOC_PMU() before it can request PMU resources.
|
||||
*
|
||||
* @param dev The parent of @p child.
|
||||
* @param child The bhnd device requesting @p rsrc.
|
||||
* @param rsrc The core-specific external resource number.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval ENODEV If the PMU does not support @p rsrc.
|
||||
* @retval ENXIO If the PMU has not been initialized or is otherwise unvailable.
|
||||
*/
|
||||
METHOD int release_ext_rsrc {
|
||||
device_t dev;
|
||||
device_t child;
|
||||
u_int rsrc;
|
||||
} DEFAULT bhnd_bus_null_release_ext_rsrc;
|
||||
|
||||
/**
|
||||
* Read @p width bytes at @p offset from the bus-specific agent/config
|
||||
* space of @p child.
|
||||
*
|
||||
* @param dev The parent of @p child.
|
||||
* @param child The bhnd device for which @p offset should be read.
|
||||
* @param offset The offset to be read.
|
||||
* @param width The size of the access. Must be 1, 2 or 4 bytes.
|
||||
*
|
||||
* The exact behavior of this method is bus-specific. On a bcma(4) bus, this
|
||||
* method provides access to the first agent port of @p child; on a siba(4) bus,
|
||||
* this method provides access to the core's CFG0 register block.
|
||||
*
|
||||
* @note Device drivers should only use this API for functionality
|
||||
* that is not available via another bhnd(4) function.
|
||||
*/
|
||||
METHOD uint32_t read_config {
|
||||
device_t dev;
|
||||
device_t child;
|
||||
bus_size_t offset;
|
||||
u_int width;
|
||||
} DEFAULT bhnd_bus_null_read_config;
|
||||
|
||||
/**
|
||||
* Read @p width bytes at @p offset from the bus-specific agent/config
|
||||
* space of @p child.
|
||||
*
|
||||
* @param dev The parent of @p child.
|
||||
* @param child The bhnd device for which @p offset should be read.
|
||||
* @param offset The offset to be written.
|
||||
* @param width The size of the access. Must be 1, 2 or 4 bytes.
|
||||
*
|
||||
* The exact behavior of this method is bus-specific. In the case of
|
||||
* bcma(4), this method provides access to the first agent port of @p child.
|
||||
*
|
||||
* @note Device drivers should only use this API for functionality
|
||||
* that is not available via another bhnd(4) function.
|
||||
*/
|
||||
METHOD void write_config {
|
||||
device_t dev;
|
||||
device_t child;
|
||||
bus_size_t offset;
|
||||
uint32_t val;
|
||||
u_int width;
|
||||
} DEFAULT bhnd_bus_null_write_config;
|
||||
|
||||
/**
|
||||
* Allocate a bhnd resource.
|
||||
*
|
||||
|
@ -46,40 +46,4 @@
|
||||
|
||||
#define BHND_RESET_SF 0x0804
|
||||
|
||||
/*
|
||||
* A register that is common to all cores to
|
||||
* communicate w/PMU regarding clock control.
|
||||
*
|
||||
* TODO: Determine when this register first appeared.
|
||||
*/
|
||||
#define BHND_CLK_CTL_ST 0x1e0 /**< clock control and status */
|
||||
|
||||
/*
|
||||
* BHND_CLK_CTL_ST register
|
||||
*
|
||||
* Clock Mode Name Description
|
||||
* High Throughput (HT) Full bandwidth, low latency. Generally supplied
|
||||
* from PLL.
|
||||
* Active Low Power (ALP) Register access, low speed DMA.
|
||||
* Idle Low Power (ILP) No interconnect activity, or if long latency
|
||||
* is permitted.
|
||||
*/
|
||||
#define BHND_CCS_FORCEALP 0x00000001 /**< force ALP request */
|
||||
#define BHND_CCS_FORCEHT 0x00000002 /**< force HT request */
|
||||
#define BHND_CCS_FORCEILP 0x00000004 /**< force ILP request */
|
||||
#define BHND_CCS_ALPAREQ 0x00000008 /**< ALP Avail Request */
|
||||
#define BHND_CCS_HTAREQ 0x00000010 /**< HT Avail Request */
|
||||
#define BHND_CCS_FORCEHWREQOFF 0x00000020 /**< Force HW Clock Request Off */
|
||||
#define BHND_CCS_ERSRC_REQ_MASK 0x00000700 /**< external resource requests */
|
||||
#define BHND_CCS_ERSRC_REQ_SHIFT 8
|
||||
#define BHND_CCS_ALPAVAIL 0x00010000 /**< ALP is available */
|
||||
#define BHND_CCS_HTAVAIL 0x00020000 /**< HT is available */
|
||||
#define BHND_CCS_BP_ON_APL 0x00040000 /**< RO: Backplane is running on ALP clock */
|
||||
#define BHND_CCS_BP_ON_HT 0x00080000 /**< RO: Backplane is running on HT clock */
|
||||
#define BHND_CCS_ERSRC_STS_MASK 0x07000000 /**< external resource status */
|
||||
#define BHND_CCS_ERSRC_STS_SHIFT 24
|
||||
|
||||
#define BHND_CCS0_HTAVAIL 0x00010000 /**< HT avail in chipc and pcmcia on 4328a0 */
|
||||
#define BHND_CCS0_ALPAVAIL 0x00020000 /**< ALP avail in chipc and pcmcia on 4328a0 */
|
||||
|
||||
#endif /* _BHND_BHND_CORE_H_ */
|
||||
|
@ -535,6 +535,12 @@
|
||||
#define BHND_CHIPTYPE_UBUS 2 /**< ubus interconnect found in bcm63xx devices */
|
||||
#define BHND_CHIPTYPE_BCMA_ALT 3 /**< bcma(4) interconnect */
|
||||
|
||||
/** Evaluates to true if @p _type uses a BCMA EROM table */
|
||||
#define BHND_CHIPTYPE_HAS_EROM(_type) \
|
||||
((_type) == BHND_CHIPTYPE_BCMA || \
|
||||
(_type) == BHND_CHIPTYPE_BCMA_ALT || \
|
||||
(_type) == BHND_CHIPTYPE_UBUS)
|
||||
|
||||
/* Boardflags */
|
||||
#define BHND_BFL_BTC2WIRE 0x00000001 /* old 2wire Bluetooth coexistence, OBSOLETE */
|
||||
#define BHND_BFL_BTCOEX 0x00000001 /* Board supports BTCOEX */
|
||||
@ -692,12 +698,6 @@
|
||||
#define BHND_GPIO_BTC4W_OUT_4313 0x060 /* bit 5 SW_BT, bit 6 SW_WL */
|
||||
#define BHND_GPIO_BTC4W_OUT_4331_SHARED 0x010 /* GPIO 4 */
|
||||
|
||||
/* Power Control Defines */
|
||||
#define BHND_CHIPC_PLL_DELAY 150 /* us pll on delay */
|
||||
#define BHND_CHIPC_FREF_DELAY 200 /* us fref change delay */
|
||||
#define BHND_CHIPC_MIN_SLOW_CLK 32 /* us Slow clock period */
|
||||
#define BHND_CHIPC_XTAL_ON_DELAY 1000 /* us crystal power-on delay */
|
||||
|
||||
/* Board Types */
|
||||
#define BHND_BOARD_BU4710 0x0400
|
||||
#define BHND_BOARD_VSIM4710 0x0401
|
||||
|
@ -38,6 +38,8 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/rman.h>
|
||||
#include <machine/resource.h>
|
||||
|
||||
#include <dev/bhnd/siba/sibareg.h>
|
||||
|
||||
#include <dev/bhnd/cores/chipc/chipcreg.h>
|
||||
|
||||
#include "nvram/bhnd_nvram.h"
|
||||
@ -287,6 +289,30 @@ bhnd_core_class(const struct bhnd_core_info *ci)
|
||||
return bhnd_find_core_class(ci->vendor, ci->device);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a human readable name representation of the given
|
||||
* BHND_CHIPID_* constant to @p buffer.
|
||||
*
|
||||
* @param buffer Output buffer, or NULL to compute the required size.
|
||||
* @param size Capacity of @p buffer, in bytes.
|
||||
* @param chip_id Chip ID to be formatted.
|
||||
*
|
||||
* @return Returns the required number of bytes on success, or a negative
|
||||
* integer on failure. No more than @p size-1 characters be written, with
|
||||
* the @p size'th set to '\0'.
|
||||
*
|
||||
* @sa BHND_CHIPID_MAX_NAMELEN
|
||||
*/
|
||||
int
|
||||
bhnd_format_chip_id(char *buffer, size_t size, uint16_t chip_id)
|
||||
{
|
||||
/* All hex formatted IDs are within the range of 0x4000-0x9C3F (40000-1) */
|
||||
if (chip_id >= 0x4000 && chip_id <= 0x9C3F)
|
||||
return (snprintf(buffer, size, "BCM%hX", chip_id));
|
||||
else
|
||||
return (snprintf(buffer, size, "BCM%hu", chip_id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a core info record with data from from a bhnd-attached @p dev.
|
||||
*
|
||||
@ -816,6 +842,63 @@ bhnd_parse_chipid(uint32_t idreg, bhnd_addr_t enum_addr)
|
||||
return (result);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine the correct core count for a chip identification value that
|
||||
* may contain an invalid core count.
|
||||
*
|
||||
* On some early siba(4) devices (see CHIPC_NCORES_MIN_HWREV()), the ChipCommon
|
||||
* core does not provide a valid CHIPC_ID_NUMCORE field.
|
||||
*
|
||||
* @param cid The chip identification to be queried.
|
||||
* @param chipc_hwrev The hardware revision of the ChipCommon core from which
|
||||
* @p cid was parsed.
|
||||
* @param[out] ncores On success, will be set to the correct core count.
|
||||
*
|
||||
* @retval 0 If the core count is already correct, or was mapped to a
|
||||
* a correct value.
|
||||
* @retval EINVAL If the core count is incorrect, but the chip was not
|
||||
* recognized.
|
||||
*/
|
||||
int
|
||||
bhnd_chipid_fixed_ncores(const struct bhnd_chipid *cid, uint16_t chipc_hwrev,
|
||||
uint8_t *ncores)
|
||||
{
|
||||
/* bcma(4), and most siba(4) devices */
|
||||
if (CHIPC_NCORES_MIN_HWREV(chipc_hwrev)) {
|
||||
*ncores = cid->ncores;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* broken siba(4) chipsets */
|
||||
switch (cid->chip_id) {
|
||||
case BHND_CHIPID_BCM4306:
|
||||
*ncores = 6;
|
||||
break;
|
||||
case BHND_CHIPID_BCM4704:
|
||||
*ncores = 9;
|
||||
break;
|
||||
case BHND_CHIPID_BCM5365:
|
||||
/*
|
||||
* BCM5365 does support ID_NUMCORE in at least
|
||||
* some of its revisions, but for unknown
|
||||
* reasons, Broadcom's drivers always exclude
|
||||
* the ChipCommon revision (0x5) used by BCM5365
|
||||
* from the set of revisions supporting
|
||||
* ID_NUMCORE, and instead supply a fixed value.
|
||||
*
|
||||
* Presumably, at least some of these devices
|
||||
* shipped with a broken ID_NUMCORE value.
|
||||
*/
|
||||
*ncores = 7;
|
||||
break;
|
||||
default:
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate the resource defined by @p rs via @p dev, use it
|
||||
* to read the ChipCommon ID register relative to @p chipc_offset,
|
||||
@ -834,12 +917,16 @@ bhnd_read_chipid(device_t dev, struct resource_spec *rs,
|
||||
bus_size_t chipc_offset, struct bhnd_chipid *result)
|
||||
{
|
||||
struct resource *res;
|
||||
bhnd_addr_t enum_addr;
|
||||
uint32_t reg;
|
||||
uint8_t chip_type;
|
||||
int error, rid, rtype;
|
||||
|
||||
/* Allocate the ChipCommon window resource and fetch the chipid data */
|
||||
rid = rs->rid;
|
||||
rtype = rs->type;
|
||||
error = 0;
|
||||
|
||||
/* Allocate the ChipCommon window resource and fetch the chipid data */
|
||||
res = bus_alloc_resource_any(dev, rtype, &rid, RF_ACTIVE);
|
||||
if (res == NULL) {
|
||||
device_printf(dev,
|
||||
@ -849,30 +936,44 @@ bhnd_read_chipid(device_t dev, struct resource_spec *rs,
|
||||
|
||||
/* Fetch the basic chip info */
|
||||
reg = bus_read_4(res, chipc_offset + CHIPC_ID);
|
||||
*result = bhnd_parse_chipid(reg, 0x0);
|
||||
chip_type = CHIPC_GET_BITS(reg, CHIPC_ID_BUS);
|
||||
|
||||
/* Fetch the enum base address */
|
||||
error = 0;
|
||||
switch (result->chip_type) {
|
||||
case BHND_CHIPTYPE_SIBA:
|
||||
result->enum_addr = BHND_DEFAULT_CHIPC_ADDR;
|
||||
break;
|
||||
case BHND_CHIPTYPE_BCMA:
|
||||
case BHND_CHIPTYPE_BCMA_ALT:
|
||||
result->enum_addr = bus_read_4(res, chipc_offset +
|
||||
CHIPC_EROMPTR);
|
||||
break;
|
||||
case BHND_CHIPTYPE_UBUS:
|
||||
device_printf(dev, "unsupported ubus/bcm63xx chip type");
|
||||
error = ENODEV;
|
||||
goto cleanup;
|
||||
default:
|
||||
device_printf(dev, "unknown chip type %hhu\n",
|
||||
result->chip_type);
|
||||
/* Fetch the EROMPTR */
|
||||
if (BHND_CHIPTYPE_HAS_EROM(chip_type)) {
|
||||
enum_addr = bus_read_4(res, chipc_offset + CHIPC_EROMPTR);
|
||||
} else if (chip_type == BHND_CHIPTYPE_SIBA) {
|
||||
/* siba(4) uses the ChipCommon base address as the enumeration
|
||||
* address */
|
||||
enum_addr = rman_get_start(res) + chipc_offset;
|
||||
} else {
|
||||
device_printf(dev, "unknown chip type %hhu\n", chip_type);
|
||||
error = ENODEV;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
*result = bhnd_parse_chipid(reg, enum_addr);
|
||||
|
||||
/* Fix the core count on early siba(4) devices */
|
||||
if (chip_type == BHND_CHIPTYPE_SIBA) {
|
||||
uint32_t idh;
|
||||
uint16_t chipc_hwrev;
|
||||
|
||||
/*
|
||||
* We need the ChipCommon revision to determine whether
|
||||
* the ncore field is valid.
|
||||
*
|
||||
* We can safely assume the siba IDHIGH register is mapped
|
||||
* within the chipc register block.
|
||||
*/
|
||||
idh = bus_read_4(res, SB0_REG_ABS(SIBA_CFG0_IDHIGH));
|
||||
chipc_hwrev = SIBA_IDH_CORE_REV(idh);
|
||||
|
||||
error = bhnd_chipid_fixed_ncores(result, chipc_hwrev,
|
||||
&result->ncores);
|
||||
if (error)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
/* Clean up */
|
||||
bus_release_resource(dev, rtype, rid, res);
|
||||
@ -1235,6 +1336,52 @@ bhnd_set_default_core_desc(device_t dev)
|
||||
bhnd_set_custom_core_desc(dev, bhnd_get_device_name(dev));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Using the bhnd @p chip_id, populate the bhnd(4) bus @p dev's device
|
||||
* description.
|
||||
*
|
||||
* @param dev A bhnd-bus attached device.
|
||||
*/
|
||||
void
|
||||
bhnd_set_default_bus_desc(device_t dev, const struct bhnd_chipid *chip_id)
|
||||
{
|
||||
const char *bus_name;
|
||||
char *desc;
|
||||
char chip_name[BHND_CHIPID_MAX_NAMELEN];
|
||||
|
||||
/* Determine chip type's bus name */
|
||||
switch (chip_id->chip_type) {
|
||||
case BHND_CHIPTYPE_SIBA:
|
||||
bus_name = "SIBA bus";
|
||||
break;
|
||||
case BHND_CHIPTYPE_BCMA:
|
||||
case BHND_CHIPTYPE_BCMA_ALT:
|
||||
bus_name = "BCMA bus";
|
||||
break;
|
||||
case BHND_CHIPTYPE_UBUS:
|
||||
bus_name = "UBUS bus";
|
||||
break;
|
||||
default:
|
||||
bus_name = "Unknown Type";
|
||||
break;
|
||||
}
|
||||
|
||||
/* Format chip name */
|
||||
bhnd_format_chip_id(chip_name, sizeof(chip_name),
|
||||
chip_id->chip_id);
|
||||
|
||||
/* Format and set device description */
|
||||
asprintf(&desc, M_BHND, "%s %s", chip_name, bus_name);
|
||||
if (desc != NULL) {
|
||||
device_set_desc_copy(dev, desc);
|
||||
free(desc, M_BHND);
|
||||
} else {
|
||||
device_set_desc(dev, bus_name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for implementing BHND_BUS_IS_HW_DISABLED().
|
||||
*
|
||||
@ -1314,7 +1461,9 @@ bhnd_bus_generic_read_board_info(device_t dev, device_t child,
|
||||
OPT_BHND_GV(info->board_vendor, BOARDVENDOR, 0);
|
||||
OPT_BHND_GV(info->board_type, BOARDTYPE, 0); /* srom >= 2 */
|
||||
REQ_BHND_GV(info->board_rev, BOARDREV);
|
||||
REQ_BHND_GV(info->board_srom_rev,SROMREV);
|
||||
OPT_BHND_GV(info->board_srom_rev,SROMREV, 0); /* missing in
|
||||
some SoC
|
||||
NVRAM */
|
||||
REQ_BHND_GV(info->board_flags, BOARDFLAGS);
|
||||
OPT_BHND_GV(info->board_flags2, BOARDFLAGS2, 0); /* srom >= 4 */
|
||||
OPT_BHND_GV(info->board_flags3, BOARDFLAGS3, 0); /* srom >= 11 */
|
||||
|
@ -85,6 +85,66 @@ typedef enum {
|
||||
* SoC */
|
||||
} bhnd_attach_type;
|
||||
|
||||
/**
|
||||
* bhnd(4) clock types.
|
||||
*/
|
||||
typedef enum {
|
||||
/**
|
||||
* Dynamically select an appropriate clock source based on all
|
||||
* outstanding clock requests.
|
||||
*/
|
||||
BHND_CLOCK_DYN = (1 << 0),
|
||||
|
||||
/**
|
||||
* Idle Low-Power (ILP).
|
||||
*
|
||||
* No register access is required, or long request latency is
|
||||
* acceptable.
|
||||
*/
|
||||
BHND_CLOCK_ILP = (1 << 1),
|
||||
|
||||
/**
|
||||
* Active Low-Power (ALP).
|
||||
*
|
||||
* Low-latency register access and low-rate DMA.
|
||||
*/
|
||||
BHND_CLOCK_ALP = (1 << 2),
|
||||
|
||||
/**
|
||||
* High Throughput (HT).
|
||||
*
|
||||
* High bus throughput and lowest-latency register access.
|
||||
*/
|
||||
BHND_CLOCK_HT = (1 << 3)
|
||||
} bhnd_clock;
|
||||
|
||||
/**
|
||||
* Given two clock types, return the type with the highest precedence.
|
||||
*/
|
||||
static inline bhnd_clock
|
||||
bhnd_clock_max(bhnd_clock a, bhnd_clock b) {
|
||||
return (a > b ? a : b);
|
||||
}
|
||||
|
||||
/**
|
||||
* bhnd(4) clock sources.
|
||||
*/
|
||||
typedef enum {
|
||||
/**
|
||||
* Clock is provided by the PCI bus clock
|
||||
*/
|
||||
BHND_CLKSRC_PCI = 0,
|
||||
|
||||
/** Clock is provided by a crystal. */
|
||||
BHND_CLKSRC_XTAL = 1,
|
||||
|
||||
/** Clock is provided by a low power oscillator. */
|
||||
BHND_CLKSRC_LPO = 2,
|
||||
|
||||
/** Clock source is unknown */
|
||||
BHND_CLKSRC_UNKNOWN = 3
|
||||
} bhnd_clksrc;
|
||||
|
||||
/** Evaluates to true if @p cls is a device class that can be configured
|
||||
* as a host bridge device. */
|
||||
#define BHND_DEVCLASS_SUPPORTS_HOSTB(cls) \
|
||||
|
@ -66,11 +66,42 @@ bhnd_bhndb_get_attach_type(device_t dev, device_t child)
|
||||
return (BHND_ATTACH_ADAPTER);
|
||||
}
|
||||
|
||||
static bhnd_clksrc
|
||||
bhnd_bhndb_pwrctl_get_clksrc(device_t dev, device_t child,
|
||||
bhnd_clock clock)
|
||||
{
|
||||
/* Delegate to parent bridge */
|
||||
return (BHND_BUS_PWRCTL_GET_CLKSRC(device_get_parent(dev), child,
|
||||
clock));
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_bhndb_pwrctl_gate_clock(device_t dev, device_t child,
|
||||
bhnd_clock clock)
|
||||
{
|
||||
/* Delegate to parent bridge */
|
||||
return (BHND_BUS_PWRCTL_GATE_CLOCK(device_get_parent(dev), child,
|
||||
clock));
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_bhndb_pwrctl_ungate_clock(device_t dev, device_t child,
|
||||
bhnd_clock clock)
|
||||
{
|
||||
/* Delegate to parent bridge */
|
||||
return (BHND_BUS_PWRCTL_UNGATE_CLOCK(device_get_parent(dev), child,
|
||||
clock));
|
||||
}
|
||||
|
||||
static device_method_t bhnd_bhndb_methods[] = {
|
||||
/* BHND interface */
|
||||
DEVMETHOD(bhnd_bus_get_attach_type, bhnd_bhndb_get_attach_type),
|
||||
DEVMETHOD(bhnd_bus_read_board_info, bhnd_bhndb_read_board_info),
|
||||
|
||||
DEVMETHOD(bhnd_bus_pwrctl_get_clksrc, bhnd_bhndb_pwrctl_get_clksrc),
|
||||
DEVMETHOD(bhnd_bus_pwrctl_gate_clock, bhnd_bhndb_pwrctl_gate_clock),
|
||||
DEVMETHOD(bhnd_bus_pwrctl_ungate_clock, bhnd_bhndb_pwrctl_ungate_clock),
|
||||
|
||||
DEVMETHOD_END
|
||||
};
|
||||
|
||||
|
@ -2028,4 +2028,3 @@ DEFINE_CLASS_0(bhndb, bhndb_driver, bhndb_methods, sizeof(struct bhndb_softc));
|
||||
|
||||
MODULE_VERSION(bhndb, 1);
|
||||
MODULE_DEPEND(bhndb, bhnd, 1, 1, 1);
|
||||
MODULE_DEPEND(bhndb, bhnd_chipc, 1, 1, 1);
|
||||
|
@ -606,6 +606,64 @@ bhndb_disable_pci_clocks(struct bhndb_pci_softc *sc)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static bhnd_clksrc
|
||||
bhndb_pci_pwrctl_get_clksrc(device_t dev, device_t child,
|
||||
bhnd_clock clock)
|
||||
{
|
||||
struct bhndb_pci_softc *sc;
|
||||
uint32_t gpio_out;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
/* Only supported on PCI devices */
|
||||
if (sc->pci_devclass != BHND_DEVCLASS_PCI)
|
||||
return (ENODEV);
|
||||
|
||||
/* Only ILP is supported */
|
||||
if (clock != BHND_CLOCK_ILP)
|
||||
return (ENXIO);
|
||||
|
||||
gpio_out = pci_read_config(sc->parent, BHNDB_PCI_GPIO_OUT, 4);
|
||||
if (gpio_out & BHNDB_PCI_GPIO_SCS)
|
||||
return (BHND_CLKSRC_PCI);
|
||||
else
|
||||
return (BHND_CLKSRC_XTAL);
|
||||
}
|
||||
|
||||
static int
|
||||
bhndb_pci_pwrctl_gate_clock(device_t dev, device_t child,
|
||||
bhnd_clock clock)
|
||||
{
|
||||
struct bhndb_pci_softc *sc = device_get_softc(dev);
|
||||
|
||||
/* Only supported on PCI devices */
|
||||
if (sc->pci_devclass != BHND_DEVCLASS_PCI)
|
||||
return (ENODEV);
|
||||
|
||||
/* Only HT is supported */
|
||||
if (clock != BHND_CLOCK_HT)
|
||||
return (ENXIO);
|
||||
|
||||
return (bhndb_disable_pci_clocks(sc));
|
||||
}
|
||||
|
||||
static int
|
||||
bhndb_pci_pwrctl_ungate_clock(device_t dev, device_t child,
|
||||
bhnd_clock clock)
|
||||
{
|
||||
struct bhndb_pci_softc *sc = device_get_softc(dev);
|
||||
|
||||
/* Only supported on PCI devices */
|
||||
if (sc->pci_devclass != BHND_DEVCLASS_PCI)
|
||||
return (ENODEV);
|
||||
|
||||
/* Only HT is supported */
|
||||
if (clock != BHND_CLOCK_HT)
|
||||
return (ENXIO);
|
||||
|
||||
return (bhndb_enable_pci_clocks(sc));
|
||||
}
|
||||
|
||||
static device_method_t bhndb_pci_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, bhndb_pci_probe),
|
||||
@ -614,6 +672,11 @@ static device_method_t bhndb_pci_methods[] = {
|
||||
DEVMETHOD(device_suspend, bhndb_pci_suspend),
|
||||
DEVMETHOD(device_detach, bhndb_pci_detach),
|
||||
|
||||
/* BHND interface */
|
||||
DEVMETHOD(bhnd_bus_pwrctl_get_clksrc, bhndb_pci_pwrctl_get_clksrc),
|
||||
DEVMETHOD(bhnd_bus_pwrctl_gate_clock, bhndb_pci_pwrctl_gate_clock),
|
||||
DEVMETHOD(bhnd_bus_pwrctl_ungate_clock, bhndb_pci_pwrctl_ungate_clock),
|
||||
|
||||
/* BHNDB interface */
|
||||
DEVMETHOD(bhndb_init_full_config, bhndb_pci_init_full_config),
|
||||
DEVMETHOD(bhndb_set_window_addr, bhndb_pci_set_window_addr),
|
||||
@ -627,7 +690,6 @@ DEFINE_CLASS_1(bhndb, bhndb_pci_driver, bhndb_pci_methods,
|
||||
|
||||
MODULE_VERSION(bhndb_pci, 1);
|
||||
MODULE_DEPEND(bhndb_pci, bhnd_pci_hostb, 1, 1, 1);
|
||||
MODULE_DEPEND(bhndb_pci, bhnd_pcie2_hostb, 1, 1, 1);
|
||||
MODULE_DEPEND(bhndb_pci, pci, 1, 1, 1);
|
||||
MODULE_DEPEND(bhndb_pci, bhndb, 1, 1, 1);
|
||||
MODULE_DEPEND(bhndb_pci, bhnd, 1, 1, 1);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2015 Landon Fuller <landon@landonf.org>
|
||||
* Copyright (c) 2015-2016 Landon Fuller <landonf@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -45,27 +45,7 @@
|
||||
MALLOC_DECLARE(M_BHND);
|
||||
DECLARE_CLASS(bhnd_driver);
|
||||
|
||||
/**
|
||||
* bhnd per-device info. Must be first member of all subclass
|
||||
* devinfo structures.
|
||||
*/
|
||||
struct bhnd_devinfo {
|
||||
};
|
||||
|
||||
/**
|
||||
* bhnd driver instance state. Must be first member of all subclass
|
||||
* softc structures.
|
||||
*/
|
||||
struct bhnd_softc {
|
||||
device_t dev; /**< bus device */
|
||||
|
||||
bool attach_done; /**< true if initialization of all
|
||||
* platform devices has been
|
||||
* completed */
|
||||
device_t chipc_dev; /**< bhnd_chipc device */
|
||||
device_t nvram_dev; /**< bhnd_nvram device, if any */
|
||||
device_t pmu_dev; /**< bhnd_pmu device, if any */
|
||||
};
|
||||
struct bhnd_core_pmu_info;
|
||||
|
||||
int bhnd_generic_attach(device_t dev);
|
||||
int bhnd_generic_detach(device_t dev);
|
||||
@ -76,6 +56,19 @@ int bhnd_generic_suspend(device_t dev);
|
||||
int bhnd_generic_get_probe_order(device_t dev,
|
||||
device_t child);
|
||||
|
||||
int bhnd_generic_alloc_pmu(device_t dev,
|
||||
device_t child);
|
||||
int bhnd_generic_release_pmu(device_t dev,
|
||||
device_t child);
|
||||
int bhnd_generic_request_clock(device_t dev,
|
||||
device_t child, bhnd_clock clock);
|
||||
int bhnd_generic_enable_clocks(device_t dev,
|
||||
device_t child, uint32_t clocks);
|
||||
int bhnd_generic_request_ext_rsrc(device_t dev,
|
||||
device_t child, u_int rsrc);
|
||||
int bhnd_generic_release_ext_rsrc(device_t dev,
|
||||
device_t child, u_int rsrc);
|
||||
|
||||
int bhnd_generic_print_child(device_t dev,
|
||||
device_t child);
|
||||
void bhnd_generic_probe_nomatch(device_t dev,
|
||||
@ -83,6 +76,7 @@ void bhnd_generic_probe_nomatch(device_t dev,
|
||||
|
||||
device_t bhnd_generic_add_child(device_t dev, u_int order,
|
||||
const char *name, int unit);
|
||||
void bhnd_generic_child_added(device_t dev, device_t child);
|
||||
void bhnd_generic_child_deleted(device_t dev,
|
||||
device_t child);
|
||||
int bhnd_generic_suspend_child(device_t dev,
|
||||
@ -94,4 +88,28 @@ int bhnd_generic_get_nvram_var(device_t dev,
|
||||
device_t child, const char *name, void *buf,
|
||||
size_t *size, bhnd_nvram_type type);
|
||||
|
||||
|
||||
/**
|
||||
* bhnd per-device info. Must be first member of all subclass
|
||||
* devinfo structures.
|
||||
*/
|
||||
struct bhnd_devinfo {
|
||||
struct bhnd_core_pmu_info *pmu_info; /**< PMU info, or NULL */
|
||||
};
|
||||
|
||||
/**
|
||||
* bhnd driver instance state. Must be first member of all subclass
|
||||
* softc structures.
|
||||
*/
|
||||
struct bhnd_softc {
|
||||
device_t dev; /**< bus device */
|
||||
|
||||
bool attach_done; /**< true if initialization of
|
||||
* all platform devices has
|
||||
* been completed */
|
||||
device_t chipc_dev; /**< bhnd_chipc device */
|
||||
device_t nvram_dev; /**< bhnd_nvram device, if any */
|
||||
device_t pmu_dev; /**< bhnd_pmu device, if any */
|
||||
};
|
||||
|
||||
#endif /* _BHND_BHNDVAR_H_ */
|
||||
|
@ -48,6 +48,22 @@ CODE {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the current value of the chipstatus register.
|
||||
*
|
||||
* @param dev A bhnd(4) ChipCommon device.
|
||||
*
|
||||
* Drivers should only use function for functionality that is not
|
||||
* available via another bhnd_chipc() function.
|
||||
*
|
||||
* @returns The chipstatus register value, or 0 if undefined by this
|
||||
* hardware (e.g. if @p dev is an EXTIF core).
|
||||
*/
|
||||
METHOD uint32_t read_chipst {
|
||||
device_t dev;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write @p value with @p mask directly to the chipctrl register.
|
||||
*
|
||||
|
126
sys/dev/bhnd/cores/chipc/bhnd_pmu_chipc.c
Normal file
126
sys/dev/bhnd/cores/chipc/bhnd_pmu_chipc.c
Normal file
@ -0,0 +1,126 @@
|
||||
/*-
|
||||
* Copyright (c) 2016 Landon Fuller <landon@landonf.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||
* similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
|
||||
* redistribution must be conditioned upon including a substantially
|
||||
* similar Disclaimer requirement for further binary redistribution.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
/*
|
||||
* ChipCommon attachment support for the bhnd(4) PMU driver.
|
||||
*
|
||||
* Supports non-AOB ("Always-on Bus") devices that map the PMU register blocks
|
||||
* via the ChipCommon core, rather than vending a distinct PMU core on the
|
||||
* bhnd bus.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/limits.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <dev/bhnd/bhnd.h>
|
||||
|
||||
#include <dev/bhnd/cores/pmu/bhnd_pmuvar.h>
|
||||
#include <dev/bhnd/cores/pmu/bhnd_pmureg.h>
|
||||
|
||||
#include "bhnd_chipc_if.h"
|
||||
#include "bhnd_pmu_if.h"
|
||||
|
||||
#include "chipcvar.h"
|
||||
|
||||
static int
|
||||
bhnd_pmu_chipc_probe(device_t dev)
|
||||
{
|
||||
struct bhnd_pmu_softc *sc;
|
||||
struct chipc_caps *ccaps;
|
||||
struct chipc_softc *chipc_sc;
|
||||
device_t chipc;
|
||||
char desc[34];
|
||||
int error;
|
||||
uint32_t pcaps;
|
||||
uint8_t rev;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
/* Look for chipc parent */
|
||||
chipc = device_get_parent(dev);
|
||||
if (device_get_devclass(chipc) != devclass_find("bhnd_chipc"))
|
||||
return (ENXIO);
|
||||
|
||||
/* Check the chipc PMU capability flag. */
|
||||
ccaps = BHND_CHIPC_GET_CAPS(chipc);
|
||||
if (!ccaps->pmu)
|
||||
return (ENXIO);
|
||||
|
||||
/* Delegate to common driver implementation */
|
||||
if ((error = bhnd_pmu_probe(dev)) > 0)
|
||||
return (error);
|
||||
|
||||
/* Fetch PMU capability flags */
|
||||
chipc_sc = device_get_softc(chipc);
|
||||
pcaps = bhnd_bus_read_4(chipc_sc->core, BHND_PMU_CAP);
|
||||
|
||||
/* Set description */
|
||||
rev = BHND_PMU_GET_BITS(pcaps, BHND_PMU_CAP_REV);
|
||||
snprintf(desc, sizeof(desc), "Broadcom ChipCommon PMU, rev %hhu", rev);
|
||||
device_set_desc_copy(dev, desc);
|
||||
|
||||
return (BUS_PROBE_NOWILDCARD);
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_pmu_chipc_attach(device_t dev)
|
||||
{
|
||||
struct chipc_softc *chipc_sc;
|
||||
struct bhnd_resource *r;
|
||||
|
||||
/* Fetch core registers from ChipCommon parent */
|
||||
chipc_sc = device_get_softc(device_get_parent(dev));
|
||||
r = chipc_sc->core;
|
||||
|
||||
return (bhnd_pmu_attach(dev, r));
|
||||
}
|
||||
|
||||
static device_method_t bhnd_pmu_chipc_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, bhnd_pmu_chipc_probe),
|
||||
DEVMETHOD(device_attach, bhnd_pmu_chipc_attach),
|
||||
|
||||
DEVMETHOD_END
|
||||
};
|
||||
|
||||
DEFINE_CLASS_1(bhnd_pmu, bhnd_pmu_chipc_driver, bhnd_pmu_chipc_methods,
|
||||
sizeof(struct bhnd_pmu_softc), bhnd_pmu_driver);
|
||||
EARLY_DRIVER_MODULE(bhnd_pmu_chipc, bhnd_chipc, bhnd_pmu_chipc_driver,
|
||||
bhnd_pmu_devclass, NULL, NULL, BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE);
|
||||
|
||||
MODULE_DEPEND(bhnd_pmu_chipc, bhnd, 1, 1, 1);
|
||||
MODULE_VERSION(bhnd_pmu_chipc, 1);
|
@ -46,10 +46,9 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/bhnd/nvram/bhnd_nvram.h>
|
||||
#include <dev/bhnd/nvram/bhnd_spromvar.h>
|
||||
|
||||
#include "bhnd_nvram_if.h"
|
||||
#include <dev/bhnd/cores/chipc/chipc.h>
|
||||
|
||||
#include "chipcvar.h"
|
||||
#include "chipc_private.h"
|
||||
#include "bhnd_nvram_if.h"
|
||||
|
||||
#define CHIPC_VALID_SPROM_SRC(_src) \
|
||||
((_src) == BHND_NVRAM_SRC_SPROM || (_src) == BHND_NVRAM_SRC_OTP)
|
||||
|
@ -110,25 +110,27 @@ static struct bhnd_device_quirk chipc_quirks[] = {
|
||||
// FIXME: IRQ shouldn't be hard-coded
|
||||
#define CHIPC_MIPS_IRQ 2
|
||||
|
||||
static int chipc_add_children(struct chipc_softc *sc);
|
||||
static int chipc_add_children(struct chipc_softc *sc);
|
||||
|
||||
static bhnd_nvram_src chipc_find_nvram_src(struct chipc_softc *sc,
|
||||
struct chipc_caps *caps);
|
||||
static int chipc_read_caps(struct chipc_softc *sc,
|
||||
struct chipc_caps *caps);
|
||||
static bhnd_nvram_src chipc_find_nvram_src(struct chipc_softc *sc,
|
||||
struct chipc_caps *caps);
|
||||
static int chipc_read_caps(struct chipc_softc *sc,
|
||||
struct chipc_caps *caps);
|
||||
|
||||
static bool chipc_should_enable_sprom(
|
||||
struct chipc_softc *sc);
|
||||
static bool chipc_should_enable_muxed_sprom(
|
||||
struct chipc_softc *sc);
|
||||
static int chipc_enable_otp_power(struct chipc_softc *sc);
|
||||
static void chipc_disable_otp_power(struct chipc_softc *sc);
|
||||
static int chipc_enable_sprom_pins(struct chipc_softc *sc);
|
||||
static void chipc_disable_sprom_pins(struct chipc_softc *sc);
|
||||
|
||||
static int chipc_try_activate_resource(
|
||||
struct chipc_softc *sc, device_t child,
|
||||
int type, int rid, struct resource *r,
|
||||
bool req_direct);
|
||||
static int chipc_try_activate_resource(struct chipc_softc *sc,
|
||||
device_t child, int type, int rid,
|
||||
struct resource *r, bool req_direct);
|
||||
|
||||
static int chipc_init_rman(struct chipc_softc *sc);
|
||||
static void chipc_free_rman(struct chipc_softc *sc);
|
||||
static struct rman *chipc_get_rman(struct chipc_softc *sc,
|
||||
int type);
|
||||
static int chipc_init_rman(struct chipc_softc *sc);
|
||||
static void chipc_free_rman(struct chipc_softc *sc);
|
||||
static struct rman *chipc_get_rman(struct chipc_softc *sc, int type);
|
||||
|
||||
/* quirk and capability flag convenience macros */
|
||||
#define CHIPC_QUIRK(_sc, _name) \
|
||||
@ -266,40 +268,19 @@ chipc_add_children(struct chipc_softc *sc)
|
||||
return (error);
|
||||
}
|
||||
|
||||
#ifdef notyet
|
||||
/*
|
||||
* PMU/SLOWCLK/INSTACLK
|
||||
* PMU/PWR_CTRL
|
||||
*
|
||||
* On AOB ("Always on Bus") devices, a PMU core (if it exists) is
|
||||
* enumerated directly by the bhnd(4) bus -- not chipc.
|
||||
*
|
||||
* Otherwise, we always add a PMU child device, and let the
|
||||
* chipc bhnd_pmu drivers probe for it. If the core supports an
|
||||
* earlier non-PMU clock/power register interface, one of the instaclk,
|
||||
* powerctl, or null bhnd_pmu drivers will claim the device.
|
||||
* On AOB ("Always on Bus") devices, the PMU core (if it exists) is
|
||||
* attached directly to the bhnd(4) bus -- not chipc.
|
||||
*/
|
||||
if (!sc->caps.aob || (sc->caps.aob && !sc->caps.pmu)) {
|
||||
if (sc->caps.pwr_ctrl || (sc->caps.pmu && !sc->caps.aob)) {
|
||||
child = BUS_ADD_CHILD(sc->dev, 0, "bhnd_pmu", -1);
|
||||
if (child == NULL) {
|
||||
device_printf(sc->dev, "failed to add pmu\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* Associate the applicable register block */
|
||||
error = 0;
|
||||
if (sc->caps.pmu) {
|
||||
error = chipc_set_resource(sc, child, SYS_RES_MEMORY, 0,
|
||||
CHIPC_PMU, CHIPC_PMU_SIZE, 0, 0);
|
||||
} else if (sc->caps.power_control) {
|
||||
error = chipc_set_resource(sc, child, SYS_RES_MEMORY, 0,
|
||||
CHIPC_PWRCTL, CHIPC_PWRCTL_SIZE, 0, 0);
|
||||
}
|
||||
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
}
|
||||
#endif /* notyet */
|
||||
|
||||
/* All remaining devices are SoC-only */
|
||||
if (bhnd_get_attach_type(sc->dev) != BHND_ATTACH_NATIVE)
|
||||
@ -422,7 +403,7 @@ chipc_read_caps(struct chipc_softc *sc, struct chipc_caps *caps)
|
||||
caps->uart_clock = CHIPC_GET_BITS(cap_reg, CHIPC_CAP_UCLKSEL);
|
||||
|
||||
caps->extbus_type = CHIPC_GET_BITS(cap_reg, CHIPC_CAP_EXTBUS);
|
||||
caps->power_control = CHIPC_GET_FLAG(cap_reg, CHIPC_CAP_PWR_CTL);
|
||||
caps->pwr_ctrl = CHIPC_GET_FLAG(cap_reg, CHIPC_CAP_PWR_CTL);
|
||||
caps->jtag_master = CHIPC_GET_FLAG(cap_reg, CHIPC_CAP_JTAGP);
|
||||
|
||||
caps->pll_type = CHIPC_GET_BITS(cap_reg, CHIPC_CAP_PLL);
|
||||
@ -1089,7 +1070,7 @@ chipc_deactivate_resource(device_t dev, device_t child, int type,
|
||||
* @param sc chipc driver state.
|
||||
*/
|
||||
static bool
|
||||
chipc_should_enable_sprom(struct chipc_softc *sc)
|
||||
chipc_should_enable_muxed_sprom(struct chipc_softc *sc)
|
||||
{
|
||||
device_t *devs;
|
||||
device_t hostb;
|
||||
@ -1098,17 +1079,19 @@ chipc_should_enable_sprom(struct chipc_softc *sc)
|
||||
int error;
|
||||
bool result;
|
||||
|
||||
mtx_assert(&Giant, MA_OWNED); /* for newbus */
|
||||
|
||||
/* Nothing to do? */
|
||||
if (!CHIPC_QUIRK(sc, MUX_SPROM))
|
||||
return (true);
|
||||
|
||||
mtx_lock(&Giant); /* for newbus */
|
||||
|
||||
parent = device_get_parent(sc->dev);
|
||||
hostb = bhnd_find_hostb_device(parent);
|
||||
|
||||
if ((error = device_get_children(parent, &devs, &devcount)))
|
||||
if ((error = device_get_children(parent, &devs, &devcount))) {
|
||||
mtx_unlock(&Giant);
|
||||
return (false);
|
||||
}
|
||||
|
||||
/* Reject any active devices other than ChipCommon, or the
|
||||
* host bridge (if any). */
|
||||
@ -1129,42 +1112,112 @@ chipc_should_enable_sprom(struct chipc_softc *sc)
|
||||
}
|
||||
|
||||
free(devs, M_TEMP);
|
||||
mtx_unlock(&Giant);
|
||||
return (result);
|
||||
}
|
||||
|
||||
static int
|
||||
chipc_enable_sprom(device_t dev)
|
||||
{
|
||||
struct chipc_softc *sc;
|
||||
int error;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
CHIPC_LOCK(sc);
|
||||
|
||||
/* Already enabled? */
|
||||
if (sc->sprom_refcnt >= 1) {
|
||||
sc->sprom_refcnt++;
|
||||
CHIPC_UNLOCK(sc);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
switch (sc->caps.nvram_src) {
|
||||
case BHND_NVRAM_SRC_SPROM:
|
||||
error = chipc_enable_sprom_pins(sc);
|
||||
break;
|
||||
case BHND_NVRAM_SRC_OTP:
|
||||
error = chipc_enable_otp_power(sc);
|
||||
break;
|
||||
default:
|
||||
error = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Bump the reference count */
|
||||
if (error == 0)
|
||||
sc->sprom_refcnt++;
|
||||
|
||||
CHIPC_UNLOCK(sc);
|
||||
return (error);
|
||||
}
|
||||
|
||||
static void
|
||||
chipc_disable_sprom(device_t dev)
|
||||
{
|
||||
struct chipc_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
CHIPC_LOCK(sc);
|
||||
|
||||
/* Check reference count, skip disable if in-use. */
|
||||
KASSERT(sc->sprom_refcnt > 0, ("sprom refcnt overrelease"));
|
||||
sc->sprom_refcnt--;
|
||||
if (sc->sprom_refcnt > 0) {
|
||||
CHIPC_UNLOCK(sc);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (sc->caps.nvram_src) {
|
||||
case BHND_NVRAM_SRC_SPROM:
|
||||
chipc_disable_sprom_pins(sc);
|
||||
break;
|
||||
case BHND_NVRAM_SRC_OTP:
|
||||
chipc_disable_otp_power(sc);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
CHIPC_UNLOCK(sc);
|
||||
}
|
||||
|
||||
static int
|
||||
chipc_enable_otp_power(struct chipc_softc *sc)
|
||||
{
|
||||
// TODO: Enable OTP resource via PMU, and wait up to 100 usec for
|
||||
// OTPS_READY to be set in `optstatus`.
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
chipc_disable_otp_power(struct chipc_softc *sc)
|
||||
{
|
||||
// TODO: Disable OTP resource via PMU
|
||||
}
|
||||
|
||||
/**
|
||||
* If required by this device, enable access to the SPROM.
|
||||
*
|
||||
* @param sc chipc driver state.
|
||||
*/
|
||||
static int
|
||||
chipc_enable_sprom_pins(device_t dev)
|
||||
chipc_enable_sprom_pins(struct chipc_softc *sc)
|
||||
{
|
||||
struct chipc_softc *sc;
|
||||
uint32_t cctrl;
|
||||
int error;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
CHIPC_LOCK_ASSERT(sc, MA_OWNED);
|
||||
KASSERT(sc->sprom_refcnt == 0, ("sprom pins already enabled"));
|
||||
|
||||
/* Nothing to do? */
|
||||
if (!CHIPC_QUIRK(sc, MUX_SPROM))
|
||||
return (0);
|
||||
|
||||
/* Make sure we're holding Giant for newbus */
|
||||
mtx_lock(&Giant);
|
||||
CHIPC_LOCK(sc);
|
||||
|
||||
/* Already enabled? */
|
||||
if (sc->sprom_refcnt >= 1) {
|
||||
error = 0;
|
||||
goto finished;
|
||||
}
|
||||
|
||||
/* Check whether bus is busy */
|
||||
if (!chipc_should_enable_sprom(sc)) {
|
||||
error = EBUSY;
|
||||
goto finished;
|
||||
}
|
||||
if (!chipc_should_enable_muxed_sprom(sc))
|
||||
return (EBUSY);
|
||||
|
||||
cctrl = bhnd_bus_read_4(sc->core, CHIPC_CHIPCTRL);
|
||||
|
||||
@ -1179,8 +1232,7 @@ chipc_enable_sprom_pins(device_t dev)
|
||||
cctrl &= ~CHIPC_CCTRL4331_EXTPA_EN2;
|
||||
|
||||
bhnd_bus_write_4(sc->core, CHIPC_CHIPCTRL, cctrl);
|
||||
error = 0;
|
||||
goto finished;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* 4360 devices */
|
||||
@ -1190,17 +1242,7 @@ chipc_enable_sprom_pins(device_t dev)
|
||||
|
||||
/* Refuse to proceed on unsupported devices with muxed SPROM pins */
|
||||
device_printf(sc->dev, "muxed sprom lines on unrecognized device\n");
|
||||
error = ENXIO;
|
||||
|
||||
finished:
|
||||
/* Bump the reference count */
|
||||
if (error == 0)
|
||||
sc->sprom_refcnt++;
|
||||
|
||||
CHIPC_UNLOCK(sc);
|
||||
mtx_unlock(&Giant);
|
||||
|
||||
return (error);
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1210,24 +1252,17 @@ finished:
|
||||
* @param sc chipc driver state.
|
||||
*/
|
||||
static void
|
||||
chipc_disable_sprom_pins(device_t dev)
|
||||
chipc_disable_sprom_pins(struct chipc_softc *sc)
|
||||
{
|
||||
struct chipc_softc *sc;
|
||||
uint32_t cctrl;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
/* Nothing to do? */
|
||||
if (!CHIPC_QUIRK(sc, MUX_SPROM))
|
||||
return;
|
||||
|
||||
CHIPC_LOCK(sc);
|
||||
|
||||
/* Check reference count, skip disable if in-use. */
|
||||
KASSERT(sc->sprom_refcnt > 0, ("sprom refcnt overrelease"));
|
||||
sc->sprom_refcnt--;
|
||||
if (sc->sprom_refcnt > 0)
|
||||
goto finished;
|
||||
CHIPC_LOCK_ASSERT(sc, MA_OWNED);
|
||||
KASSERT(sc->sprom_refcnt != 0, ("sprom pins already disabled"));
|
||||
KASSERT(sc->sprom_refcnt == 1, ("sprom pins in use"));
|
||||
|
||||
cctrl = bhnd_bus_read_4(sc->core, CHIPC_CHIPCTRL);
|
||||
|
||||
@ -1242,16 +1277,20 @@ chipc_disable_sprom_pins(device_t dev)
|
||||
cctrl |= CHIPC_CCTRL4331_EXTPA_EN2;
|
||||
|
||||
bhnd_bus_write_4(sc->core, CHIPC_CHIPCTRL, cctrl);
|
||||
goto finished;
|
||||
return;
|
||||
}
|
||||
|
||||
/* 4360 devices */
|
||||
if (CHIPC_QUIRK(sc, 4360_FEM_MUX_SPROM)) {
|
||||
/* Unimplemented */
|
||||
}
|
||||
}
|
||||
|
||||
finished:
|
||||
CHIPC_UNLOCK(sc);
|
||||
static uint32_t
|
||||
chipc_read_chipst(device_t dev)
|
||||
{
|
||||
struct chipc_softc *sc = device_get_softc(dev);
|
||||
return (bhnd_bus_read_4(sc->core, CHIPC_CHIPST));
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1317,16 +1356,17 @@ static device_method_t chipc_methods[] = {
|
||||
DEVMETHOD(bhnd_bus_activate_resource, chipc_activate_bhnd_resource),
|
||||
|
||||
/* ChipCommon interface */
|
||||
DEVMETHOD(bhnd_chipc_read_chipst, chipc_read_chipst),
|
||||
DEVMETHOD(bhnd_chipc_write_chipctrl, chipc_write_chipctrl),
|
||||
DEVMETHOD(bhnd_chipc_enable_sprom, chipc_enable_sprom_pins),
|
||||
DEVMETHOD(bhnd_chipc_disable_sprom, chipc_disable_sprom_pins),
|
||||
DEVMETHOD(bhnd_chipc_enable_sprom, chipc_enable_sprom),
|
||||
DEVMETHOD(bhnd_chipc_disable_sprom, chipc_disable_sprom),
|
||||
DEVMETHOD(bhnd_chipc_get_caps, chipc_get_caps),
|
||||
|
||||
DEVMETHOD_END
|
||||
};
|
||||
|
||||
DEFINE_CLASS_0(bhnd_chipc, chipc_driver, chipc_methods, sizeof(struct chipc_softc));
|
||||
EARLY_DRIVER_MODULE(bhnd_chipc, bhnd, chipc_driver, bhnd_chipc_devclass, 0, 0,
|
||||
DEFINE_CLASS_0(bhnd_chipc, bhnd_chipc_driver, chipc_methods, sizeof(struct chipc_softc));
|
||||
EARLY_DRIVER_MODULE(bhnd_chipc, bhnd, bhnd_chipc_driver, bhnd_chipc_devclass, 0, 0,
|
||||
BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
|
||||
MODULE_DEPEND(bhnd_chipc, bhnd, 1, 1, 1);
|
||||
MODULE_VERSION(bhnd_chipc, 1);
|
||||
|
@ -37,4 +37,60 @@
|
||||
|
||||
#include "bhnd_chipc_if.h"
|
||||
|
||||
/**
|
||||
* Supported ChipCommon flash types.
|
||||
*/
|
||||
typedef enum {
|
||||
CHIPC_FLASH_NONE = 0, /**< No flash, or a type unrecognized
|
||||
by the ChipCommon driver */
|
||||
CHIPC_PFLASH_CFI = 1, /**< CFI-compatible parallel flash */
|
||||
CHIPC_SFLASH_ST = 2, /**< ST serial flash */
|
||||
CHIPC_SFLASH_AT = 3, /**< Atmel serial flash */
|
||||
CHIPC_QSFLASH_ST = 4, /**< ST quad-SPI flash */
|
||||
CHIPC_QSFLASH_AT = 5, /**< Atmel quad-SPI flash */
|
||||
CHIPC_NFLASH = 6, /**< NAND flash */
|
||||
CHIPC_NFLASH_4706 = 7 /**< BCM4706 NAND flash */
|
||||
} chipc_flash;
|
||||
|
||||
/**
|
||||
* ChipCommon capability flags;
|
||||
*/
|
||||
struct chipc_caps {
|
||||
uint8_t num_uarts; /**< Number of attached UARTS (1-3) */
|
||||
bool mipseb; /**< MIPS is big-endian */
|
||||
uint8_t uart_clock; /**< UART clock source (see CHIPC_CAP_UCLKSEL_*) */
|
||||
uint8_t uart_gpio; /**< UARTs own GPIO pins 12-15 */
|
||||
|
||||
uint8_t extbus_type; /**< ExtBus type (CHIPC_CAP_EXTBUS_*) */
|
||||
|
||||
chipc_flash flash_type; /**< flash type */
|
||||
uint8_t cfi_width; /**< CFI bus width, 0 if unknown or CFI
|
||||
not present */
|
||||
|
||||
bhnd_nvram_src nvram_src; /**< identified NVRAM source */
|
||||
bus_size_t sprom_offset; /**< Offset to SPROM data within
|
||||
SPROM/OTP, 0 if unknown or not
|
||||
present */
|
||||
uint8_t otp_size; /**< OTP (row?) size, 0 if not present */
|
||||
|
||||
uint8_t pll_type; /**< PLL type */
|
||||
bool pwr_ctrl; /**< Power/clock control available */
|
||||
bool jtag_master; /**< JTAG Master present */
|
||||
bool boot_rom; /**< Internal boot ROM is active */
|
||||
uint8_t backplane_64; /**< Backplane supports 64-bit addressing.
|
||||
Note that this does not gaurantee
|
||||
the CPU itself supports 64-bit
|
||||
addressing. */
|
||||
bool pmu; /**< PMU is present. */
|
||||
bool eci; /**< ECI (enhanced coexistence inteface) is present. */
|
||||
bool seci; /**< SECI (serial ECI) is present */
|
||||
bool sprom; /**< SPROM is present */
|
||||
bool gsio; /**< GSIO (SPI/I2C) present */
|
||||
bool aob; /**< AOB (always on bus) present.
|
||||
If set, PMU and GCI registers are
|
||||
not accessible via ChipCommon,
|
||||
and are instead accessible via
|
||||
dedicated cores on the bhnd bus */
|
||||
};
|
||||
|
||||
#endif /* _BHND_CORES_CHIPC_CHIPC_H_ */
|
||||
|
@ -248,8 +248,8 @@ chipc_print_caps(device_t dev, struct chipc_caps *caps)
|
||||
CC_TFS(sprom), CC_TFS(otp_size));
|
||||
device_printf(dev, "CFIsz: 0x%02x | OTPsz: 0x%02x\n",
|
||||
caps->cfi_width, caps->otp_size);
|
||||
device_printf(dev, "ExtBus: 0x%02x | PwCtl: %s\n",
|
||||
caps->extbus_type, CC_TFS(power_control));
|
||||
device_printf(dev, "ExtBus: 0x%02x | PwrCtrl: %s\n",
|
||||
caps->extbus_type, CC_TFS(pwr_ctrl));
|
||||
device_printf(dev, "PLL: 0x%02x | JTAGM: %s\n",
|
||||
caps->pll_type, CC_TFS(jtag_master));
|
||||
device_printf(dev, "PMU: %-3s | ECI: %s\n",
|
||||
|
@ -31,10 +31,24 @@
|
||||
required during bus
|
||||
enumeration */
|
||||
|
||||
/** Evaluates to true if the given ChipCommon core revision supports
|
||||
* the CHIPC_CORECTRL register */
|
||||
#define CHIPC_HWREV_HAS_CORECTRL(hwrev) ((hwrev) >= 1)
|
||||
|
||||
/** Evaluates to true if the given ChipCommon core revision provides
|
||||
* the core count via the chip identification register. */
|
||||
#define CHIPC_NCORES_MIN_HWREV(hwrev) ((hwrev) == 4 || (hwrev) >= 6)
|
||||
|
||||
/** Evaluates to true if the given ChipCommon core revision supports
|
||||
* the CHIPC_CAPABILITIES_EXT register */
|
||||
#define CHIPC_HWREV_HAS_CAP_EXT(hwrev) ((hwrev) >= 35)
|
||||
|
||||
/** Evaluates to true if the chipcommon core (determined from the provided
|
||||
* @p _chipid (CHIPC_ID) register value) provides a pointer to the enumeration
|
||||
* table via CHIPC_EROMPTR */
|
||||
#define CHIPC_HAS_EROMPTR(_chipid) \
|
||||
(CHIPC_GET_BITS((_chipid), CHIPC_ID_BUS) != BHND_CHIPTYPE_SIBA)
|
||||
|
||||
#define CHIPC_GET_FLAG(_value, _flag) (((_value) & _flag) != 0)
|
||||
#define CHIPC_GET_BITS(_value, _field) \
|
||||
((_value & _field ## _MASK) >> _field ## _SHIFT)
|
||||
@ -90,24 +104,25 @@
|
||||
#define CHIPC_GPIOTIMERVAL 0x88 /**< gpio-based LED duty cycle (rev >= 16) */
|
||||
#define CHIPC_GPIOTIMEROUTMASK 0x8C
|
||||
|
||||
/* clock control block */
|
||||
/* clock control registers (non-PMU devices) */
|
||||
#define CHIPC_CLKC_N 0x90
|
||||
#define CHIPC_CLKC_SB 0x94 /* m0 (backplane) */
|
||||
#define CHIPC_CLKC_PCI 0x98 /* m1 */
|
||||
#define CHIPC_CLKC_M2 0x9C /* mii/uart/mipsref */
|
||||
#define CHIPC_CLKC_M3 0xA0 /* cpu */
|
||||
#define CHIPC_CLKDIV 0xA4 /* rev >= 3 */
|
||||
|
||||
#define CHIPC_GPIODEBUGSEL 0xA8 /* rev >= 28 */
|
||||
#define CHIPC_CAPABILITIES_EXT 0xAC
|
||||
|
||||
/* pll delay (registers rev >= 4) */
|
||||
#define CHIPC_PLL_ON_DELAY 0xB0
|
||||
#define CHIPC_PLL_FREFSEL_DELAY 0xB4
|
||||
#define CHIPC_PLL_SLOWCLK_CTL 0xB8 /* revs 6-9 */
|
||||
|
||||
/* "instaclock" registers */
|
||||
#define CHIPC_SYS_CLK_CTL 0xC0 /* rev >= 10 */
|
||||
#define CHIPC_SYS_CLKSTATESTRETCH 0xC4 /* rev >= 10 */
|
||||
/* pll/slowclk clock control registers (rev >= 4) */
|
||||
#define CHIPC_PLL_ON_DELAY 0xB0 /* rev >= 4 */
|
||||
#define CHIPC_PLL_FREFSEL_DELAY 0xB4 /* rev >= 4 */
|
||||
#define CHIPC_PLL_SLOWCLK_CTL 0xB8 /* "slowclock" (rev 6-9) */
|
||||
|
||||
/* "instaclock" clock control registers */
|
||||
#define CHIPC_SYS_CLK_CTL 0xC0 /* "instaclock" (rev >= 10) */
|
||||
#define CHIPC_SYS_CLK_ST_STRETCH 0xC4 /* state strech (?) rev >= 10 */
|
||||
|
||||
/* indirect backplane access (rev >= 10) */
|
||||
#define CHIPC_BP_ADDRLOW 0xD0
|
||||
@ -125,7 +140,7 @@
|
||||
|
||||
#define CHIPC_EROMPTR 0xFC /**< 32-bit EROM base address
|
||||
* on BCMA devices */
|
||||
|
||||
|
||||
/* ExtBus control registers (rev >= 3) */
|
||||
#define CHIPC_PCMCIA_CFG 0x100
|
||||
#define CHIPC_PCMCIA_MEMWAIT 0x104
|
||||
@ -178,38 +193,10 @@
|
||||
#define CHIPC_UART_MAX 3 /**< max UART blocks */
|
||||
#define CHIPC_UART(_n) (CHIPC_UART_BASE + (CHIPC_UART_SIZE*_n))
|
||||
|
||||
/* PMU registers (rev >= 20) */
|
||||
/* PMU register block (rev >= 20) */
|
||||
#define CHIPC_PMU_BASE 0x600
|
||||
#define CHIPC_PMU_SIZE 0x70
|
||||
|
||||
#define CHIPC_PMU_CTRL 0x600
|
||||
#define CHIPC_PMU_CAP 0x604
|
||||
#define CHIPC_PMU_ST 0x608
|
||||
#define CHIPC_PMU_RES_STATE 0x60c
|
||||
#define CHIPC_PMU_RES_PENDING 0x610
|
||||
#define CHIPC_PMU_TIMER 0x614
|
||||
#define CHIPC_PMU_MIN_RES_MASK 0x618
|
||||
#define CHIPC_PMU_MAX_RES_MASK 0x61c
|
||||
#define CHIPC_PMU_RES_TABLE_SEL 0x620
|
||||
#define CHIPC_PMU_RES_DEP_MASK 0x624
|
||||
#define CHIPC_PMU_RES_UPDN_TIMER 0x628
|
||||
#define CHIPC_PMU_RES_TIMER 0x62C
|
||||
#define CHIPC_PMU_CLKSTRETCH 0x630
|
||||
#define CHIPC_PMU_WATCHDOG 0x634
|
||||
#define CHIPC_PMU_GPIOSEL 0x638 /* pmu rev >= 1 ? */
|
||||
#define CHIPC_PMU_GPIOEN 0x63C /* pmu rev >= 1 ? */
|
||||
#define CHIPC_PMU_RES_REQ_TIMER_SEL 0x640
|
||||
#define CHIPC_PMU_RES_REQ_TIMER 0x644
|
||||
#define CHIPC_PMU_RES_REQ_MASK 0x648
|
||||
#define CHIPC_CHIPCTL_ADDR 0x650
|
||||
#define CHIPC_CHIPCTL_DATA 0x654
|
||||
#define CHIPC_PMU_REG_CONTROL_ADDR 0x658
|
||||
#define CHIPC_PMU_REG_CONTROL_DATA 0x65C
|
||||
#define CHIPC_PMU_PLL_CONTROL_ADDR 0x660
|
||||
#define CHIPC_PMU_PLL_CONTROL_DATA 0x664
|
||||
#define CHIPC_PMU_STRAPOPT 0x668 /* chipc rev >= 28 */
|
||||
#define CHIPC_PMU_XTALFREQ 0x66C /* pmu rev >= 10 */
|
||||
|
||||
#define CHIPC_SPROM_OTP 0x800 /* SPROM/OTP address space */
|
||||
#define CHIPC_SPROM_OTP_SIZE 0x400
|
||||
|
||||
@ -247,7 +234,7 @@
|
||||
#define CHIPC_CAP_PFLASH 0x7 /* Parallel flash */
|
||||
#define CHIPC_CAP_PLL_MASK 0x00038000 /* Type of PLL */
|
||||
#define CHIPC_CAP_PLL_SHIFT 15
|
||||
#define CHIPC_CAP_PWR_CTL 0x00040000 /* Power control */
|
||||
#define CHIPC_CAP_PWR_CTL 0x00040000 /* Power/clock control */
|
||||
#define CHIPC_CAP_OTP_SIZE_MASK 0x00380000 /* OTP Size (0 = none) */
|
||||
#define CHIPC_CAP_OTP_SIZE_SHIFT 19 /* OTP Size shift */
|
||||
#define CHIPC_CAP_OTP_SIZE_BASE 5 /* OTP Size base */
|
||||
@ -295,23 +282,31 @@ enum {
|
||||
#define CHIPC_CST_SPROM_OTP_SEL_R23_SHIFT 6
|
||||
|
||||
/* PLL type */
|
||||
#define CHIPC_PLL_NONE 0x00000000
|
||||
#define CHIPC_PLL_TYPE1 0x00010000 /* 48MHz base, 3 dividers */
|
||||
#define CHIPC_PLL_TYPE2 0x00020000 /* 48MHz, 4 dividers */
|
||||
#define CHIPC_PLL_TYPE3 0x00030000 /* 25MHz, 2 dividers */
|
||||
#define CHIPC_PLL_TYPE4 0x00008000 /* 48MHz, 4 dividers */
|
||||
#define CHIPC_PLL_TYPE5 0x00018000 /* 25MHz, 4 dividers */
|
||||
#define CHIPC_PLL_TYPE6 0x00028000 /* 100/200 or 120/240 only */
|
||||
#define CHIPC_PLL_TYPE7 0x00038000 /* 25MHz, 4 dividers */
|
||||
#define CHIPC_PLL_NONE 0x0
|
||||
#define CHIPC_PLL_TYPE1 0x2 /* 48MHz base, 3 dividers */
|
||||
#define CHIPC_PLL_TYPE2 0x4 /* 48MHz, 4 dividers */
|
||||
#define CHIPC_PLL_TYPE3 0x6 /* 25MHz, 2 dividers */
|
||||
#define CHIPC_PLL_TYPE4 0x8 /* 48MHz, 4 dividers */
|
||||
#define CHIPC_PLL_TYPE5 0x3 /* 25MHz, 4 dividers */
|
||||
#define CHIPC_PLL_TYPE6 0x5 /* 100/200 or 120/240 only */
|
||||
#define CHIPC_PLL_TYPE7 0x7 /* 25MHz, 4 dividers */
|
||||
|
||||
/* ILP clock */
|
||||
#define CHIPC_ILP_CLOCK 32000
|
||||
/* dynamic clock control defines */
|
||||
#define CHIPC_LPOMINFREQ 25000 /* low power oscillator min */
|
||||
#define CHIPC_LPOMAXFREQ 43000 /* low power oscillator max */
|
||||
#define CHIPC_XTALMINFREQ 19800000 /* 20 MHz - 1% */
|
||||
#define CHIPC_XTALMAXFREQ 20200000 /* 20 MHz + 1% */
|
||||
#define CHIPC_PCIMINFREQ 25000000 /* 25 MHz */
|
||||
#define CHIPC_PCIMAXFREQ 34000000 /* 33 MHz + fudge */
|
||||
|
||||
/* ALP clock on pre-PMU chips */
|
||||
#define CHIPC_ALP_CLOCK 20000000
|
||||
#define CHIPC_ILP_DIV_5MHZ 0 /* ILP = 5 MHz */
|
||||
#define CHIPC_ILP_DIV_1MHZ 4 /* ILP = 1 MHz */
|
||||
|
||||
/* HT clock */
|
||||
#define CHIPC_HT_CLOCK 80000000
|
||||
/* Power Control Defines */
|
||||
#define CHIPC_PLL_DELAY 150 /* us pll on delay */
|
||||
#define CHIPC_FREF_DELAY 200 /* us fref change delay */
|
||||
#define CHIPC_MIN_SLOW_CLK 32 /* us Slow clock period */
|
||||
#define CHIPC_XTAL_ON_DELAY 1000 /* us crystal power-on delay */
|
||||
|
||||
/* corecontrol */
|
||||
#define CHIPC_UARTCLKO 0x00000001 /* Drive UART with internal clock */
|
||||
@ -567,27 +562,12 @@ enum {
|
||||
#define CHIPC_SRC_SIZE_SHIFT 1
|
||||
#define CHIPC_SRC_PRESENT 0x00000001
|
||||
|
||||
/* Fields in pmucontrol */
|
||||
#define CHIPC_PCTL_ILP_DIV_MASK 0xffff0000
|
||||
#define CHIPC_PCTL_ILP_DIV_SHIFT 16
|
||||
#define CHIPC_PCTL_PLL_PLLCTL_UPD 0x00000400 /* rev 2 */
|
||||
#define CHIPC_PCTL_NOILP_ON_WAIT 0x00000200 /* rev 1 */
|
||||
#define CHIPC_PCTL_HT_REQ_EN 0x00000100
|
||||
#define CHIPC_PCTL_ALP_REQ_EN 0x00000080
|
||||
#define CHIPC_PCTL_XTALFREQ_MASK 0x0000007c
|
||||
#define CHIPC_PCTL_XTALFREQ_SHIFT 2
|
||||
#define CHIPC_PCTL_ILP_DIV_EN 0x00000002
|
||||
#define CHIPC_PCTL_LPO_SEL 0x00000001
|
||||
|
||||
/* Fields in clkstretch */
|
||||
#define CHIPC_CSTRETCH_HT 0xffff0000
|
||||
#define CHIPC_CSTRETCH_ALP 0x0000ffff
|
||||
|
||||
/* gpiotimerval */
|
||||
#define CHIPC_GPIO_ONTIME_SHIFT 16
|
||||
|
||||
/* clockcontrol_n */
|
||||
#define CHIPC_CN_N1_MASK 0x3f /* n1 control */
|
||||
#define CHIPC_CN_N1_SHIFT 0
|
||||
#define CHIPC_CN_N2_MASK 0x3f00 /* n2 control */
|
||||
#define CHIPC_CN_N2_SHIFT 8
|
||||
#define CHIPC_CN_PLLC_MASK 0xf0000 /* pll control */
|
||||
@ -595,6 +575,7 @@ enum {
|
||||
|
||||
/* clockcontrol_sb/pci/uart */
|
||||
#define CHIPC_M1_MASK 0x3f /* m1 control */
|
||||
#define CHIPC_M1_SHIFT 0
|
||||
#define CHIPC_M2_MASK 0x3f00 /* m2 control */
|
||||
#define CHIPC_M2_SHIFT 8
|
||||
#define CHIPC_M3_MASK 0x3f0000 /* m3 control */
|
||||
@ -778,345 +759,6 @@ enum {
|
||||
#define CHIPC_UART_IER_ETBEI 2 /* enable transmitter holding register empty interrupt */
|
||||
#define CHIPC_UART_IER_ERBFI 1 /* enable data available interrupt */
|
||||
|
||||
/* pmustatus */
|
||||
#define CHIPC_PST_EXTLPOAVAIL 0x0100
|
||||
#define CHIPC_PST_WDRESET 0x0080
|
||||
#define CHIPC_PST_INTPEND 0x0040
|
||||
#define CHIPC_PST_SBCLKST 0x0030
|
||||
#define CHIPC_PST_SBCLKST_ILP 0x0010
|
||||
#define CHIPC_PST_SBCLKST_ALP 0x0020
|
||||
#define CHIPC_PST_SBCLKST_HT 0x0030
|
||||
#define CHIPC_PST_ALPAVAIL 0x0008
|
||||
#define CHIPC_PST_HTAVAIL 0x0004
|
||||
#define CHIPC_PST_RESINIT 0x0003
|
||||
|
||||
/* pmucapabilities */
|
||||
#define CHIPC_PCAP_REV_MASK 0x000000ff
|
||||
#define CHIPC_PCAP_RC_MASK 0x00001f00
|
||||
#define CHIPC_PCAP_RC_SHIFT 8
|
||||
#define CHIPC_PCAP_TC_MASK 0x0001e000
|
||||
#define CHIPC_PCAP_TC_SHIFT 13
|
||||
#define CHIPC_PCAP_PC_MASK 0x001e0000
|
||||
#define CHIPC_PCAP_PC_SHIFT 17
|
||||
#define CHIPC_PCAP_VC_MASK 0x01e00000
|
||||
#define CHIPC_PCAP_VC_SHIFT 21
|
||||
#define CHIPC_PCAP_CC_MASK 0x1e000000
|
||||
#define CHIPC_PCAP_CC_SHIFT 25
|
||||
#define CHIPC_PCAP5_PC_MASK 0x003e0000 /* PMU corerev >= 5 */
|
||||
#define CHIPC_PCAP5_PC_SHIFT 17
|
||||
#define CHIPC_PCAP5_VC_MASK 0x07c00000
|
||||
#define CHIPC_PCAP5_VC_SHIFT 22
|
||||
#define CHIPC_PCAP5_CC_MASK 0xf8000000
|
||||
#define CHIPC_PCAP5_CC_SHIFT 27
|
||||
|
||||
/* PMU Resource Request Timer registers */
|
||||
/* This is based on PmuRev0 */
|
||||
#define CHIPC_PRRT_TIME_MASK 0x03ff
|
||||
#define CHIPC_PRRT_INTEN 0x0400
|
||||
#define CHIPC_PRRT_REQ_ACTIVE 0x0800
|
||||
#define CHIPC_PRRT_ALP_REQ 0x1000
|
||||
#define CHIPC_PRRT_HT_REQ 0x2000
|
||||
|
||||
/* PMU resource bit position */
|
||||
#define CHIPC_PMURES_BIT(bit) (1 << (bit))
|
||||
|
||||
/* PMU resource number limit */
|
||||
#define CHIPC_PMURES_MAX_RESNUM 30
|
||||
|
||||
/* PMU chip control0 register */
|
||||
#define CHIPC_PMU_CHIPCTL0 0
|
||||
|
||||
/* PMU chip control1 register */
|
||||
#define CHIPC_PMU_CHIPCTL1 1
|
||||
#define CHIPC_PMU_CC1_RXC_DLL_BYPASS 0x00010000
|
||||
|
||||
#define CHIPC_PMU_CC1_IF_TYPE_MASK 0x00000030
|
||||
#define CHIPC_PMU_CC1_IF_TYPE_RMII 0x00000000
|
||||
#define CHIPC_PMU_CC1_IF_TYPE_MII 0x00000010
|
||||
#define CHIPC_PMU_CC1_IF_TYPE_RGMII 0x00000020
|
||||
|
||||
#define CHIPC_PMU_CC1_SW_TYPE_MASK 0x000000c0
|
||||
#define CHIPC_PMU_CC1_SW_TYPE_EPHY 0x00000000
|
||||
#define CHIPC_PMU_CC1_SW_TYPE_EPHYMII 0x00000040
|
||||
#define CHIPC_PMU_CC1_SW_TYPE_EPHYRMII 0x00000080
|
||||
#define CHIPC_PMU_CC1_SW_TYPE_RGMII 0x000000c0
|
||||
|
||||
/* PMU corerev and chip specific PLL controls.
|
||||
* PMU<rev>_PLL<num>_XX where <rev> is PMU corerev and <num> is an arbitrary number
|
||||
* to differentiate different PLLs controlled by the same PMU rev.
|
||||
*/
|
||||
/* pllcontrol registers */
|
||||
/* PDIV, div_phy, div_arm, div_adc, dith_sel, ioff, kpd_scale, lsb_sel, mash_sel, lf_c & lf_r */
|
||||
#define CHIPC_PMU0_PLL0_PLLCTL0 0
|
||||
#define CHIPC_PMU0_PLL0_PC0_PDIV_MASK 1
|
||||
#define CHIPC_PMU0_PLL0_PC0_PDIV_FREQ 25000
|
||||
#define CHIPC_PMU0_PLL0_PC0_DIV_ARM_MASK 0x00000038
|
||||
#define CHIPC_PMU0_PLL0_PC0_DIV_ARM_SHIFT 3
|
||||
#define CHIPC_PMU0_PLL0_PC0_DIV_ARM_BASE 8
|
||||
|
||||
/* PC0_DIV_ARM for PLLOUT_ARM */
|
||||
#define CHIPC_PMU0_PLL0_PC0_DIV_ARM_110MHZ 0
|
||||
#define CHIPC_PMU0_PLL0_PC0_DIV_ARM_97_7MHZ 1
|
||||
#define CHIPC_PMU0_PLL0_PC0_DIV_ARM_88MHZ 2
|
||||
#define CHIPC_PMU0_PLL0_PC0_DIV_ARM_80MHZ 3 /* Default */
|
||||
#define CHIPC_PMU0_PLL0_PC0_DIV_ARM_73_3MHZ 4
|
||||
#define CHIPC_PMU0_PLL0_PC0_DIV_ARM_67_7MHZ 5
|
||||
#define CHIPC_PMU0_PLL0_PC0_DIV_ARM_62_9MHZ 6
|
||||
#define CHIPC_PMU0_PLL0_PC0_DIV_ARM_58_6MHZ 7
|
||||
|
||||
/* Wildcard base, stop_mod, en_lf_tp, en_cal & lf_r2 */
|
||||
#define CHIPC_PMU0_PLL0_PLLCTL1 1
|
||||
#define CHIPC_PMU0_PLL0_PC1_WILD_INT_MASK 0xf0000000
|
||||
#define CHIPC_PMU0_PLL0_PC1_WILD_INT_SHIFT 28
|
||||
#define CHIPC_PMU0_PLL0_PC1_WILD_FRAC_MASK 0x0fffff00
|
||||
#define CHIPC_PMU0_PLL0_PC1_WILD_FRAC_SHIFT 8
|
||||
#define CHIPC_PMU0_PLL0_PC1_STOP_MOD 0x00000040
|
||||
|
||||
/* Wildcard base, vco_calvar, vco_swc, vco_var_selref, vso_ical & vco_sel_avdd */
|
||||
#define CHIPC_PMU0_PLL0_PLLCTL2 2
|
||||
#define CHIPC_PMU0_PLL0_PC2_WILD_INT_MASK 0xf
|
||||
#define CHIPC_PMU0_PLL0_PC2_WILD_INT_SHIFT 4
|
||||
|
||||
/* pllcontrol registers */
|
||||
/* ndiv_pwrdn, pwrdn_ch<x>, refcomp_pwrdn, dly_ch<x>, p1div, p2div, _bypass_sdmod */
|
||||
#define CHIPC_PMU1_PLL0_PLLCTL0 0
|
||||
#define CHIPC_PMU1_PLL0_PC0_P1DIV_MASK 0x00f00000
|
||||
#define CHIPC_PMU1_PLL0_PC0_P1DIV_SHIFT 20
|
||||
#define CHIPC_PMU1_PLL0_PC0_P2DIV_MASK 0x0f000000
|
||||
#define CHIPC_PMU1_PLL0_PC0_P2DIV_SHIFT 24
|
||||
|
||||
/* m<x>div */
|
||||
#define CHIPC_PMU1_PLL0_PLLCTL1 1
|
||||
#define CHIPC_PMU1_PLL0_PC1_M1DIV_MASK 0x000000ff
|
||||
#define CHIPC_PMU1_PLL0_PC1_M1DIV_SHIFT 0
|
||||
#define CHIPC_PMU1_PLL0_PC1_M2DIV_MASK 0x0000ff00
|
||||
#define CHIPC_PMU1_PLL0_PC1_M2DIV_SHIFT 8
|
||||
#define CHIPC_PMU1_PLL0_PC1_M3DIV_MASK 0x00ff0000
|
||||
#define CHIPC_PMU1_PLL0_PC1_M3DIV_SHIFT 16
|
||||
#define CHIPC_PMU1_PLL0_PC1_M4DIV_MASK 0xff000000
|
||||
#define CHIPC_PMU1_PLL0_PC1_M4DIV_SHIFT 24
|
||||
|
||||
#define CHIPC_DOT11MAC_880MHZ_CLK_DIVISOR_SHIFT 8
|
||||
#define CHIPC_DOT11MAC_880MHZ_CLK_DIVISOR_MASK (0xFF << DOT11MAC_880MHZ_CLK_DIVISOR_SHIFT)
|
||||
#define CHIPC_DOT11MAC_880MHZ_CLK_DIVISOR_VAL (0xE << DOT11MAC_880MHZ_CLK_DIVISOR_SHIFT)
|
||||
|
||||
/* m<x>div, ndiv_dither_mfb, ndiv_mode, ndiv_int */
|
||||
#define CHIPC_PMU1_PLL0_PLLCTL2 2
|
||||
#define CHIPC_PMU1_PLL0_PC2_M5DIV_MASK 0x000000ff
|
||||
#define CHIPC_PMU1_PLL0_PC2_M5DIV_SHIFT 0
|
||||
#define CHIPC_PMU1_PLL0_PC2_M6DIV_MASK 0x0000ff00
|
||||
#define CHIPC_PMU1_PLL0_PC2_M6DIV_SHIFT 8
|
||||
#define CHIPC_PMU1_PLL0_PC2_NDIV_MODE_MASK 0x000e0000
|
||||
#define CHIPC_PMU1_PLL0_PC2_NDIV_MODE_SHIFT 17
|
||||
#define CHIPC_PMU1_PLL0_PC2_NDIV_MODE_MASH 1
|
||||
#define CHIPC_PMU1_PLL0_PC2_NDIV_MODE_MFB 2 /* recommended for 4319 */
|
||||
#define CHIPC_PMU1_PLL0_PC2_NDIV_INT_MASK 0x1ff00000
|
||||
#define CHIPC_PMU1_PLL0_PC2_NDIV_INT_SHIFT 20
|
||||
|
||||
/* ndiv_frac */
|
||||
#define CHIPC_PMU1_PLL0_PLLCTL3 3
|
||||
#define CHIPC_PMU1_PLL0_PC3_NDIV_FRAC_MASK 0x00ffffff
|
||||
#define CHIPC_PMU1_PLL0_PC3_NDIV_FRAC_SHIFT 0
|
||||
|
||||
/* pll_ctrl */
|
||||
#define CHIPC_PMU1_PLL0_PLLCTL4 4
|
||||
|
||||
/* pll_ctrl, vco_rng, clkdrive_ch<x> */
|
||||
#define CHIPC_PMU1_PLL0_PLLCTL5 5
|
||||
#define CHIPC_PMU1_PLL0_PC5_CLK_DRV_MASK 0xffffff00
|
||||
#define CHIPC_PMU1_PLL0_PC5_CLK_DRV_SHIFT 8
|
||||
|
||||
/* PMU rev 2 control words */
|
||||
#define CHIPC_PMU2_PHY_PLL_PLLCTL 4
|
||||
#define CHIPC_PMU2_SI_PLL_PLLCTL 10
|
||||
|
||||
/* PMU rev 2 */
|
||||
/* pllcontrol registers */
|
||||
/* ndiv_pwrdn, pwrdn_ch<x>, refcomp_pwrdn, dly_ch<x>, p1div, p2div, _bypass_sdmod */
|
||||
#define CHIPC_PMU2_PLL_PLLCTL0 0
|
||||
#define CHIPC_PMU2_PLL_PC0_P1DIV_MASK 0x00f00000
|
||||
#define CHIPC_PMU2_PLL_PC0_P1DIV_SHIFT 20
|
||||
#define CHIPC_PMU2_PLL_PC0_P2DIV_MASK 0x0f000000
|
||||
#define CHIPC_PMU2_PLL_PC0_P2DIV_SHIFT 24
|
||||
|
||||
/* m<x>div */
|
||||
#define CHIPC_PMU2_PLL_PLLCTL1 1
|
||||
#define CHIPC_PMU2_PLL_PC1_M1DIV_MASK 0x000000ff
|
||||
#define CHIPC_PMU2_PLL_PC1_M1DIV_SHIFT 0
|
||||
#define CHIPC_PMU2_PLL_PC1_M2DIV_MASK 0x0000ff00
|
||||
#define CHIPC_PMU2_PLL_PC1_M2DIV_SHIFT 8
|
||||
#define CHIPC_PMU2_PLL_PC1_M3DIV_MASK 0x00ff0000
|
||||
#define CHIPC_PMU2_PLL_PC1_M3DIV_SHIFT 16
|
||||
#define CHIPC_PMU2_PLL_PC1_M4DIV_MASK 0xff000000
|
||||
#define CHIPC_PMU2_PLL_PC1_M4DIV_SHIFT 24
|
||||
|
||||
/* m<x>div, ndiv_dither_mfb, ndiv_mode, ndiv_int */
|
||||
#define CHIPC_PMU2_PLL_PLLCTL2 2
|
||||
#define CHIPC_PMU2_PLL_PC2_M5DIV_MASK 0x000000ff
|
||||
#define CHIPC_PMU2_PLL_PC2_M5DIV_SHIFT 0
|
||||
#define CHIPC_PMU2_PLL_PC2_M6DIV_MASK 0x0000ff00
|
||||
#define CHIPC_PMU2_PLL_PC2_M6DIV_SHIFT 8
|
||||
#define CHIPC_PMU2_PLL_PC2_NDIV_MODE_MASK 0x000e0000
|
||||
#define CHIPC_PMU2_PLL_PC2_NDIV_MODE_SHIFT 17
|
||||
#define CHIPC_PMU2_PLL_PC2_NDIV_INT_MASK 0x1ff00000
|
||||
#define CHIPC_PMU2_PLL_PC2_NDIV_INT_SHIFT 20
|
||||
|
||||
/* ndiv_frac */
|
||||
#define CHIPC_PMU2_PLL_PLLCTL3 3
|
||||
#define CHIPC_PMU2_PLL_PC3_NDIV_FRAC_MASK 0x00ffffff
|
||||
#define CHIPC_PMU2_PLL_PC3_NDIV_FRAC_SHIFT 0
|
||||
|
||||
/* pll_ctrl */
|
||||
#define CHIPC_PMU2_PLL_PLLCTL4 4
|
||||
|
||||
/* pll_ctrl, vco_rng, clkdrive_ch<x> */
|
||||
#define CHIPC_PMU2_PLL_PLLCTL5 5
|
||||
#define CHIPC_PMU2_PLL_PC5_CLKDRIVE_CH1_MASK 0x00000f00
|
||||
#define CHIPC_PMU2_PLL_PC5_CLKDRIVE_CH1_SHIFT 8
|
||||
#define CHIPC_PMU2_PLL_PC5_CLKDRIVE_CH2_MASK 0x0000f000
|
||||
#define CHIPC_PMU2_PLL_PC5_CLKDRIVE_CH2_SHIFT 12
|
||||
#define CHIPC_PMU2_PLL_PC5_CLKDRIVE_CH3_MASK 0x000f0000
|
||||
#define CHIPC_PMU2_PLL_PC5_CLKDRIVE_CH3_SHIFT 16
|
||||
#define CHIPC_PMU2_PLL_PC5_CLKDRIVE_CH4_MASK 0x00f00000
|
||||
#define CHIPC_PMU2_PLL_PC5_CLKDRIVE_CH4_SHIFT 20
|
||||
#define CHIPC_PMU2_PLL_PC5_CLKDRIVE_CH5_MASK 0x0f000000
|
||||
#define CHIPC_PMU2_PLL_PC5_CLKDRIVE_CH5_SHIFT 24
|
||||
#define CHIPC_PMU2_PLL_PC5_CLKDRIVE_CH6_MASK 0xf0000000
|
||||
#define CHIPC_PMU2_PLL_PC5_CLKDRIVE_CH6_SHIFT 28
|
||||
|
||||
/* PMU rev 5 (& 6) */
|
||||
#define CHIPC_PMU5_PLL_P1P2_OFF 0
|
||||
#define CHIPC_PMU5_PLL_P1_MASK 0x0f000000
|
||||
#define CHIPC_PMU5_PLL_P1_SHIFT 24
|
||||
#define CHIPC_PMU5_PLL_P2_MASK 0x00f00000
|
||||
#define CHIPC_PMU5_PLL_P2_SHIFT 20
|
||||
#define CHIPC_PMU5_PLL_M14_OFF 1
|
||||
#define CHIPC_PMU5_PLL_MDIV_MASK 0x000000ff
|
||||
#define CHIPC_PMU5_PLL_MDIV_WIDTH 8
|
||||
#define CHIPC_PMU5_PLL_NM5_OFF 2
|
||||
#define CHIPC_PMU5_PLL_NDIV_MASK 0xfff00000
|
||||
#define CHIPC_PMU5_PLL_NDIV_SHIFT 20
|
||||
#define CHIPC_PMU5_PLL_NDIV_MODE_MASK 0x000e0000
|
||||
#define CHIPC_PMU5_PLL_NDIV_MODE_SHIFT 17
|
||||
#define CHIPC_PMU5_PLL_FMAB_OFF 3
|
||||
#define CHIPC_PMU5_PLL_MRAT_MASK 0xf0000000
|
||||
#define CHIPC_PMU5_PLL_MRAT_SHIFT 28
|
||||
#define CHIPC_PMU5_PLL_ABRAT_MASK 0x08000000
|
||||
#define CHIPC_PMU5_PLL_ABRAT_SHIFT 27
|
||||
#define CHIPC_PMU5_PLL_FDIV_MASK 0x07ffffff
|
||||
#define CHIPC_PMU5_PLL_PLLCTL_OFF 4
|
||||
#define CHIPC_PMU5_PLL_PCHI_OFF 5
|
||||
#define CHIPC_PMU5_PLL_PCHI_MASK 0x0000003f
|
||||
|
||||
/* pmu XtalFreqRatio */
|
||||
#define CHIPC_PMU_XTALFREQ_REG_ILPCTR_MASK 0x00001FFF
|
||||
#define CHIPC_PMU_XTALFREQ_REG_MEASURE_MASK 0x80000000
|
||||
#define CHIPC_PMU_XTALFREQ_REG_MEASURE_SHIFT 31
|
||||
|
||||
/* Divider allocation in 4716/47162/5356/5357 */
|
||||
#define CHIPC_PMU5_MAINPLL_CPU 1
|
||||
#define CHIPC_PMU5_MAINPLL_MEM 2
|
||||
#define CHIPC_PMU5_MAINPLL_SI 3
|
||||
|
||||
#define CHIPC_PMU7_PLL_PLLCTL7 7
|
||||
#define CHIPC_PMU7_PLL_PLLCTL8 8
|
||||
#define CHIPC_PMU7_PLL_PLLCTL11 11
|
||||
|
||||
/* PLL usage in 4716/47162 */
|
||||
#define CHIPC_PMU4716_MAINPLL_PLL0 12
|
||||
|
||||
/* PLL usage in 5356/5357 */
|
||||
#define CHIPC_PMU5356_MAINPLL_PLL0 0
|
||||
#define CHIPC_PMU5357_MAINPLL_PLL0 0
|
||||
|
||||
/* 4716/47162 resources */
|
||||
#define CHIPC_RES4716_PROC_PLL_ON 0x00000040
|
||||
#define CHIPC_RES4716_PROC_HT_AVAIL 0x00000080
|
||||
|
||||
/* 4716/4717/4718 Chip specific ChipControl register bits */
|
||||
#define CHIPC_CCTRL471X_I2S_PINS_ENABLE 0x0080 /* I2S pins off by default, shared with pflash */
|
||||
|
||||
/* 5354 resources */
|
||||
#define CHIPC_RES5354_EXT_SWITCHER_PWM 0 /* 0x00001 */
|
||||
#define CHIPC_RES5354_BB_SWITCHER_PWM 1 /* 0x00002 */
|
||||
#define CHIPC_RES5354_BB_SWITCHER_BURST 2 /* 0x00004 */
|
||||
#define CHIPC_RES5354_BB_EXT_SWITCHER_BURST 3 /* 0x00008 */
|
||||
#define CHIPC_RES5354_ILP_REQUEST 4 /* 0x00010 */
|
||||
#define CHIPC_RES5354_RADIO_SWITCHER_PWM 5 /* 0x00020 */
|
||||
#define CHIPC_RES5354_RADIO_SWITCHER_BURST 6 /* 0x00040 */
|
||||
#define CHIPC_RES5354_ROM_SWITCH 7 /* 0x00080 */
|
||||
#define CHIPC_RES5354_PA_REF_LDO 8 /* 0x00100 */
|
||||
#define CHIPC_RES5354_RADIO_LDO 9 /* 0x00200 */
|
||||
#define CHIPC_RES5354_AFE_LDO 10 /* 0x00400 */
|
||||
#define CHIPC_RES5354_PLL_LDO 11 /* 0x00800 */
|
||||
#define CHIPC_RES5354_BG_FILTBYP 12 /* 0x01000 */
|
||||
#define CHIPC_RES5354_TX_FILTBYP 13 /* 0x02000 */
|
||||
#define CHIPC_RES5354_RX_FILTBYP 14 /* 0x04000 */
|
||||
#define CHIPC_RES5354_XTAL_PU 15 /* 0x08000 */
|
||||
#define CHIPC_RES5354_XTAL_EN 16 /* 0x10000 */
|
||||
#define CHIPC_RES5354_BB_PLL_FILTBYP 17 /* 0x20000 */
|
||||
#define CHIPC_RES5354_RF_PLL_FILTBYP 18 /* 0x40000 */
|
||||
#define CHIPC_RES5354_BB_PLL_PU 19 /* 0x80000 */
|
||||
|
||||
/* 5357 Chip specific ChipControl register bits */
|
||||
#define CHIPC_CCTRL5357_EXTPA (1<<14) /* extPA in ChipControl 1, bit 14 */
|
||||
#define CHIPC_CCTRL5357_ANT_MUX_2o3 (1<<15) /* 2o3 in ChipControl 1, bit 15 */
|
||||
|
||||
/* 4328 resources */
|
||||
#define CHIPC_RES4328_EXT_SWITCHER_PWM 0 /* 0x00001 */
|
||||
#define CHIPC_RES4328_BB_SWITCHER_PWM 1 /* 0x00002 */
|
||||
#define CHIPC_RES4328_BB_SWITCHER_BURST 2 /* 0x00004 */
|
||||
#define CHIPC_RES4328_BB_EXT_SWITCHER_BURST 3 /* 0x00008 */
|
||||
#define CHIPC_RES4328_ILP_REQUEST 4 /* 0x00010 */
|
||||
#define CHIPC_RES4328_RADIO_SWITCHER_PWM 5 /* 0x00020 */
|
||||
#define CHIPC_RES4328_RADIO_SWITCHER_BURST 6 /* 0x00040 */
|
||||
#define CHIPC_RES4328_ROM_SWITCH 7 /* 0x00080 */
|
||||
#define CHIPC_RES4328_PA_REF_LDO 8 /* 0x00100 */
|
||||
#define CHIPC_RES4328_RADIO_LDO 9 /* 0x00200 */
|
||||
#define CHIPC_RES4328_AFE_LDO 10 /* 0x00400 */
|
||||
#define CHIPC_RES4328_PLL_LDO 11 /* 0x00800 */
|
||||
#define CHIPC_RES4328_BG_FILTBYP 12 /* 0x01000 */
|
||||
#define CHIPC_RES4328_TX_FILTBYP 13 /* 0x02000 */
|
||||
#define CHIPC_RES4328_RX_FILTBYP 14 /* 0x04000 */
|
||||
#define CHIPC_RES4328_XTAL_PU 15 /* 0x08000 */
|
||||
#define CHIPC_RES4328_XTAL_EN 16 /* 0x10000 */
|
||||
#define CHIPC_RES4328_BB_PLL_FILTBYP 17 /* 0x20000 */
|
||||
#define CHIPC_RES4328_RF_PLL_FILTBYP 18 /* 0x40000 */
|
||||
#define CHIPC_RES4328_BB_PLL_PU 19 /* 0x80000 */
|
||||
|
||||
/* 4325 A0/A1 resources */
|
||||
#define CHIPC_RES4325_BUCK_BOOST_BURST 0 /* 0x00000001 */
|
||||
#define CHIPC_RES4325_CBUCK_BURST 1 /* 0x00000002 */
|
||||
#define CHIPC_RES4325_CBUCK_PWM 2 /* 0x00000004 */
|
||||
#define CHIPC_RES4325_CLDO_CBUCK_BURST 3 /* 0x00000008 */
|
||||
#define CHIPC_RES4325_CLDO_CBUCK_PWM 4 /* 0x00000010 */
|
||||
#define CHIPC_RES4325_BUCK_BOOST_PWM 5 /* 0x00000020 */
|
||||
#define CHIPC_RES4325_ILP_REQUEST 6 /* 0x00000040 */
|
||||
#define CHIPC_RES4325_ABUCK_BURST 7 /* 0x00000080 */
|
||||
#define CHIPC_RES4325_ABUCK_PWM 8 /* 0x00000100 */
|
||||
#define CHIPC_RES4325_LNLDO1_PU 9 /* 0x00000200 */
|
||||
#define CHIPC_RES4325_OTP_PU 10 /* 0x00000400 */
|
||||
#define CHIPC_RES4325_LNLDO3_PU 11 /* 0x00000800 */
|
||||
#define CHIPC_RES4325_LNLDO4_PU 12 /* 0x00001000 */
|
||||
#define CHIPC_RES4325_XTAL_PU 13 /* 0x00002000 */
|
||||
#define CHIPC_RES4325_ALP_AVAIL 14 /* 0x00004000 */
|
||||
#define CHIPC_RES4325_RX_PWRSW_PU 15 /* 0x00008000 */
|
||||
#define CHIPC_RES4325_TX_PWRSW_PU 16 /* 0x00010000 */
|
||||
#define CHIPC_RES4325_RFPLL_PWRSW_PU 17 /* 0x00020000 */
|
||||
#define CHIPC_RES4325_LOGEN_PWRSW_PU 18 /* 0x00040000 */
|
||||
#define CHIPC_RES4325_AFE_PWRSW_PU 19 /* 0x00080000 */
|
||||
#define CHIPC_RES4325_BBPLL_PWRSW_PU 20 /* 0x00100000 */
|
||||
#define CHIPC_RES4325_HT_AVAIL 21 /* 0x00200000 */
|
||||
|
||||
/* 4325 B0/C0 resources */
|
||||
#define CHIPC_RES4325B0_CBUCK_LPOM 1 /* 0x00000002 */
|
||||
#define CHIPC_RES4325B0_CBUCK_BURST 2 /* 0x00000004 */
|
||||
#define CHIPC_RES4325B0_CBUCK_PWM 3 /* 0x00000008 */
|
||||
#define CHIPC_RES4325B0_CLDO_PU 4 /* 0x00000010 */
|
||||
|
||||
/* 4325 C1 resources */
|
||||
#define CHIPC_RES4325C1_LNLDO2_PU 12 /* 0x00001000 */
|
||||
|
||||
/* 4325 chip-specific ChipStatus register bits */
|
||||
#define CHIPC_CST4325_SPROM_OTP_SEL_MASK CHIPC_CST_SPROM_OTP_SEL_R22_MASK
|
||||
#define CHIPC_CST4325_SPROM_OTP_SEL_SHIFT CHIPC_CST_SPROM_OTP_SEL_R22_SHIFT
|
||||
@ -1129,29 +771,6 @@ enum {
|
||||
#define CHIPC_CST4325_PMUTOP_2B_MASK 0x00000200 /* 1 for 2b, 0 for to 2a */
|
||||
#define CHIPC_CST4325_PMUTOP_2B_SHIFT 9
|
||||
|
||||
#define CHIPC_RES4329_RESERVED0 0 /* 0x00000001 */
|
||||
#define CHIPC_RES4329_CBUCK_LPOM 1 /* 0x00000002 */
|
||||
#define CHIPC_RES4329_CBUCK_BURST 2 /* 0x00000004 */
|
||||
#define CHIPC_RES4329_CBUCK_PWM 3 /* 0x00000008 */
|
||||
#define CHIPC_RES4329_CLDO_PU 4 /* 0x00000010 */
|
||||
#define CHIPC_RES4329_PALDO_PU 5 /* 0x00000020 */
|
||||
#define CHIPC_RES4329_ILP_REQUEST 6 /* 0x00000040 */
|
||||
#define CHIPC_RES4329_RESERVED7 7 /* 0x00000080 */
|
||||
#define CHIPC_RES4329_RESERVED8 8 /* 0x00000100 */
|
||||
#define CHIPC_RES4329_LNLDO1_PU 9 /* 0x00000200 */
|
||||
#define CHIPC_RES4329_OTP_PU 10 /* 0x00000400 */
|
||||
#define CHIPC_RES4329_RESERVED11 11 /* 0x00000800 */
|
||||
#define CHIPC_RES4329_LNLDO2_PU 12 /* 0x00001000 */
|
||||
#define CHIPC_RES4329_XTAL_PU 13 /* 0x00002000 */
|
||||
#define CHIPC_RES4329_ALP_AVAIL 14 /* 0x00004000 */
|
||||
#define CHIPC_RES4329_RX_PWRSW_PU 15 /* 0x00008000 */
|
||||
#define CHIPC_RES4329_TX_PWRSW_PU 16 /* 0x00010000 */
|
||||
#define CHIPC_RES4329_RFPLL_PWRSW_PU 17 /* 0x00020000 */
|
||||
#define CHIPC_RES4329_LOGEN_PWRSW_PU 18 /* 0x00040000 */
|
||||
#define CHIPC_RES4329_AFE_PWRSW_PU 19 /* 0x00080000 */
|
||||
#define CHIPC_RES4329_BBPLL_PWRSW_PU 20 /* 0x00100000 */
|
||||
#define CHIPC_RES4329_HT_AVAIL 21 /* 0x00200000 */
|
||||
|
||||
/* 4329 chip-specific ChipStatus register bits */
|
||||
#define CHIPC_CST4329_SPROM_OTP_SEL_MASK CHIPC_CST_SPROM_OTP_SEL_R22_MASK
|
||||
#define CHIPC_CST4329_SPROM_OTP_SEL_SHIFT CHIPC_CST_SPROM_OTP_SEL_R22_SHIFT
|
||||
@ -1162,33 +781,6 @@ enum {
|
||||
#define CHIPC_CST4312_SPROM_OTP_SEL_MASK CHIPC_CST_SPROM_OTP_SEL_R22_MASK
|
||||
#define CHIPC_CST4312_SPROM_OTP_SEL_SHIFT CHIPC_CST_SPROM_OTP_SEL_R22_SHIFT
|
||||
|
||||
/* 4312 resources (all PMU chips with little memory constraint) */
|
||||
#define CHIPC_RES4312_SWITCHER_BURST 0 /* 0x00000001 */
|
||||
#define CHIPC_RES4312_SWITCHER_PWM 1 /* 0x00000002 */
|
||||
#define CHIPC_RES4312_PA_REF_LDO 2 /* 0x00000004 */
|
||||
#define CHIPC_RES4312_CORE_LDO_BURST 3 /* 0x00000008 */
|
||||
#define CHIPC_RES4312_CORE_LDO_PWM 4 /* 0x00000010 */
|
||||
#define CHIPC_RES4312_RADIO_LDO 5 /* 0x00000020 */
|
||||
#define CHIPC_RES4312_ILP_REQUEST 6 /* 0x00000040 */
|
||||
#define CHIPC_RES4312_BG_FILTBYP 7 /* 0x00000080 */
|
||||
#define CHIPC_RES4312_TX_FILTBYP 8 /* 0x00000100 */
|
||||
#define CHIPC_RES4312_RX_FILTBYP 9 /* 0x00000200 */
|
||||
#define CHIPC_RES4312_XTAL_PU 10 /* 0x00000400 */
|
||||
#define CHIPC_RES4312_ALP_AVAIL 11 /* 0x00000800 */
|
||||
#define CHIPC_RES4312_BB_PLL_FILTBYP 12 /* 0x00001000 */
|
||||
#define CHIPC_RES4312_RF_PLL_FILTBYP 13 /* 0x00002000 */
|
||||
#define CHIPC_RES4312_HT_AVAIL 14 /* 0x00004000 */
|
||||
|
||||
/* 4322 resources */
|
||||
#define CHIPC_RES4322_RF_LDO 0
|
||||
#define CHIPC_RES4322_ILP_REQUEST 1
|
||||
#define CHIPC_RES4322_XTAL_PU 2
|
||||
#define CHIPC_RES4322_ALP_AVAIL 3
|
||||
#define CHIPC_RES4322_SI_PLL_ON 4
|
||||
#define CHIPC_RES4322_HT_SI_AVAIL 5
|
||||
#define CHIPC_RES4322_PHY_PLL_ON 6
|
||||
#define CHIPC_RES4322_HT_PHY_AVAIL 7
|
||||
#define CHIPC_RES4322_OTP_PU 8
|
||||
|
||||
/* 4322 chip-specific ChipStatus register bits */
|
||||
#define CHIPC_CST4322_XTAL_FREQ_20_40MHZ 0x00000020
|
||||
@ -1217,26 +809,6 @@ enum {
|
||||
#define CHIPC_CST4322_CLK_SWITCH_PCI_TO_ALP 0x00020000
|
||||
#define CHIPC_CST4322_PCI_CARDBUS_MODE 0x00040000
|
||||
|
||||
/* 43224 chip-specific ChipControl register bits */
|
||||
#define CHIPC_CCTRL43224_GPIO_TOGGLE 0x8000
|
||||
#define CHIPC_CCTRL_43224A0_12MA_LED_DRIVE 0x00F000F0 /* 12 mA drive strength */
|
||||
#define CHIPC_CCTRL_43224B0_12MA_LED_DRIVE 0xF0 /* 12 mA drive strength for later 43224s */
|
||||
|
||||
/* 43236 resources */
|
||||
#define CHIPC_RES43236_REGULATOR 0
|
||||
#define CHIPC_RES43236_ILP_REQUEST 1
|
||||
#define CHIPC_RES43236_XTAL_PU 2
|
||||
#define CHIPC_RES43236_ALP_AVAIL 3
|
||||
#define CHIPC_RES43236_SI_PLL_ON 4
|
||||
#define CHIPC_RES43236_HT_SI_AVAIL 5
|
||||
|
||||
/* 43236 chip-specific ChipControl register bits */
|
||||
#define CHIPC_CCTRL43236_BT_COEXIST (1<<0) /* 0 disable */
|
||||
#define CHIPC_CCTRL43236_SECI (1<<1) /* 0 SECI is disabled (JATG functional) */
|
||||
#define CHIPC_CCTRL43236_EXT_LNA (1<<2) /* 0 disable */
|
||||
#define CHIPC_CCTRL43236_ANT_MUX_2o3 (1<<3) /* 2o3 mux, chipcontrol bit 3 */
|
||||
#define CHIPC_CCTRL43236_GSIO (1<<4) /* 0 disable */
|
||||
|
||||
/* 43236 Chip specific ChipStatus register bits */
|
||||
#define CHIPC_CST43236_SFLASH_MASK 0x00000040
|
||||
#define CHIPC_CST43236_OTP_SEL_MASK 0x00000080
|
||||
@ -1250,15 +822,17 @@ enum {
|
||||
#define CHIPC_CST43236_BOOT_FROM_FLASH 2 /* boot from FLASH */
|
||||
#define CHIPC_CST43236_BOOT_FROM_INVALID 3
|
||||
|
||||
/* 4331 resources */
|
||||
#define CHIPC_RES4331_REGULATOR 0
|
||||
#define CHIPC_RES4331_ILP_REQUEST 1
|
||||
#define CHIPC_RES4331_XTAL_PU 2
|
||||
#define CHIPC_RES4331_ALP_AVAIL 3
|
||||
#define CHIPC_RES4331_SI_PLL_ON 4
|
||||
#define CHIPC_RES4331_HT_SI_AVAIL 5
|
||||
/* 43237 Chip specific ChipStatus register bits */
|
||||
#define CHIPC_CST43237_BP_CLK 0x00000200 /* 96/80Mbps */
|
||||
|
||||
/* 4331 chip-specific ChipControl register bits */
|
||||
/* 4331 Chip specific ChipStatus register bits */
|
||||
#define CHIPC_CST4331_XTAL_FREQ 0x00000001 /* crystal frequency 20/40Mhz */
|
||||
#define CHIPC_CST4331_SPROM_PRESENT 0x00000002
|
||||
#define CHIPC_CST4331_OTP_PRESENT 0x00000004
|
||||
#define CHIPC_CST4331_LDO_RF 0x00000008
|
||||
#define CHIPC_CST4331_LDO_PAR 0x00000010
|
||||
|
||||
/* 4331 chip-specific CHIPCTRL register bits */
|
||||
#define CHIPC_CCTRL4331_BT_COEXIST (1<<0) /* 0 disable */
|
||||
#define CHIPC_CCTRL4331_SECI (1<<1) /* 0 SECI is disabled (JATG functional) */
|
||||
#define CHIPC_CCTRL4331_EXT_LNA (1<<2) /* 0 disable */
|
||||
@ -1275,33 +849,6 @@ enum {
|
||||
#define CHIPC_CCTRL4331_BT_SHD0_ON_GPIO4 (1<<16) /* enable bt_shd0 at gpio4 */
|
||||
#define CHIPC_CCTRL4331_BT_SHD1_ON_GPIO5 (1<<17) /* enable bt_shd1 at gpio5 */
|
||||
|
||||
/* 4331 Chip specific ChipStatus register bits */
|
||||
#define CHIPC_CST4331_XTAL_FREQ 0x00000001 /* crystal frequency 20/40Mhz */
|
||||
#define CHIPC_CST4331_SPROM_PRESENT 0x00000002
|
||||
#define CHIPC_CST4331_OTP_PRESENT 0x00000004
|
||||
#define CHIPC_CST4331_LDO_RF 0x00000008
|
||||
#define CHIPC_CST4331_LDO_PAR 0x00000010
|
||||
|
||||
/* 4315 resources */
|
||||
#define CHIPC_RES4315_CBUCK_LPOM 1 /* 0x00000002 */
|
||||
#define CHIPC_RES4315_CBUCK_BURST 2 /* 0x00000004 */
|
||||
#define CHIPC_RES4315_CBUCK_PWM 3 /* 0x00000008 */
|
||||
#define CHIPC_RES4315_CLDO_PU 4 /* 0x00000010 */
|
||||
#define CHIPC_RES4315_PALDO_PU 5 /* 0x00000020 */
|
||||
#define CHIPC_RES4315_ILP_REQUEST 6 /* 0x00000040 */
|
||||
#define CHIPC_RES4315_LNLDO1_PU 9 /* 0x00000200 */
|
||||
#define CHIPC_RES4315_OTP_PU 10 /* 0x00000400 */
|
||||
#define CHIPC_RES4315_LNLDO2_PU 12 /* 0x00001000 */
|
||||
#define CHIPC_RES4315_XTAL_PU 13 /* 0x00002000 */
|
||||
#define CHIPC_RES4315_ALP_AVAIL 14 /* 0x00004000 */
|
||||
#define CHIPC_RES4315_RX_PWRSW_PU 15 /* 0x00008000 */
|
||||
#define CHIPC_RES4315_TX_PWRSW_PU 16 /* 0x00010000 */
|
||||
#define CHIPC_RES4315_RFPLL_PWRSW_PU 17 /* 0x00020000 */
|
||||
#define CHIPC_RES4315_LOGEN_PWRSW_PU 18 /* 0x00040000 */
|
||||
#define CHIPC_RES4315_AFE_PWRSW_PU 19 /* 0x00080000 */
|
||||
#define CHIPC_RES4315_BBPLL_PWRSW_PU 20 /* 0x00100000 */
|
||||
#define CHIPC_RES4315_HT_AVAIL 21 /* 0x00200000 */
|
||||
|
||||
/* 4315 chip-specific ChipStatus register bits */
|
||||
#define CHIPC_CST4315_SPROM_OTP_SEL_MASK CHIPC_CST_SPROM_OTP_SEL_R22_MASK
|
||||
#define CHIPC_CST4315_SPROM_OTP_SEL_SHIFT CHIPC_CST_SPROM_OTP_SEL_R22_SHIFT
|
||||
@ -1314,26 +861,6 @@ enum {
|
||||
#define CHIPC_CST4315_CBUCK_MODE_BURST 0x00000400
|
||||
#define CHIPC_CST4315_CBUCK_MODE_LPBURST 0x00000c00
|
||||
|
||||
/* 4319 resources */
|
||||
#define CHIPC_RES4319_CBUCK_LPOM 1 /* 0x00000002 */
|
||||
#define CHIPC_RES4319_CBUCK_BURST 2 /* 0x00000004 */
|
||||
#define CHIPC_RES4319_CBUCK_PWM 3 /* 0x00000008 */
|
||||
#define CHIPC_RES4319_CLDO_PU 4 /* 0x00000010 */
|
||||
#define CHIPC_RES4319_PALDO_PU 5 /* 0x00000020 */
|
||||
#define CHIPC_RES4319_ILP_REQUEST 6 /* 0x00000040 */
|
||||
#define CHIPC_RES4319_LNLDO1_PU 9 /* 0x00000200 */
|
||||
#define CHIPC_RES4319_OTP_PU 10 /* 0x00000400 */
|
||||
#define CHIPC_RES4319_LNLDO2_PU 12 /* 0x00001000 */
|
||||
#define CHIPC_RES4319_XTAL_PU 13 /* 0x00002000 */
|
||||
#define CHIPC_RES4319_ALP_AVAIL 14 /* 0x00004000 */
|
||||
#define CHIPC_RES4319_RX_PWRSW_PU 15 /* 0x00008000 */
|
||||
#define CHIPC_RES4319_TX_PWRSW_PU 16 /* 0x00010000 */
|
||||
#define CHIPC_RES4319_RFPLL_PWRSW_PU 17 /* 0x00020000 */
|
||||
#define CHIPC_RES4319_LOGEN_PWRSW_PU 18 /* 0x00040000 */
|
||||
#define CHIPC_RES4319_AFE_PWRSW_PU 19 /* 0x00080000 */
|
||||
#define CHIPC_RES4319_BBPLL_PWRSW_PU 20 /* 0x00100000 */
|
||||
#define CHIPC_RES4319_HT_AVAIL 21 /* 0x00200000 */
|
||||
|
||||
/* 4319 chip-specific ChipStatus register bits */
|
||||
#define CHIPC_CST4319_SPI_CPULESSUSB 0x00000001
|
||||
#define CHIPC_CST4319_SPI_CLK_POL 0x00000002
|
||||
@ -1354,42 +881,6 @@ enum {
|
||||
#define CHIPC_CST4319_RCAL_VALUE_MASK 0x3e000000
|
||||
#define CHIPC_CST4319_RCAL_VALUE_SHIFT 25
|
||||
|
||||
#define CHIPC_PMU1_PLL0_CHIPCTL0 0
|
||||
#define CHIPC_PMU1_PLL0_CHIPCTL1 1
|
||||
#define CHIPC_PMU1_PLL0_CHIPCTL2 2
|
||||
#define CHIPC_CCTL_4319USB_XTAL_SEL_MASK 0x00180000
|
||||
#define CHIPC_CCTL_4319USB_XTAL_SEL_SHIFT 19
|
||||
#define CHIPC_CCTL_4319USB_48MHZ_PLL_SEL 1
|
||||
#define CHIPC_CCTL_4319USB_24MHZ_PLL_SEL 2
|
||||
|
||||
/* PMU resources for 4336 */
|
||||
#define CHIPC_RES4336_CBUCK_LPOM 0
|
||||
#define CHIPC_RES4336_CBUCK_BURST 1
|
||||
#define CHIPC_RES4336_CBUCK_LP_PWM 2
|
||||
#define CHIPC_RES4336_CBUCK_PWM 3
|
||||
#define CHIPC_RES4336_CLDO_PU 4
|
||||
#define CHIPC_RES4336_DIS_INT_RESET_PD 5
|
||||
#define CHIPC_RES4336_ILP_REQUEST 6
|
||||
#define CHIPC_RES4336_LNLDO_PU 7
|
||||
#define CHIPC_RES4336_LDO3P3_PU 8
|
||||
#define CHIPC_RES4336_OTP_PU 9
|
||||
#define CHIPC_RES4336_XTAL_PU 10
|
||||
#define CHIPC_RES4336_ALP_AVAIL 11
|
||||
#define CHIPC_RES4336_RADIO_PU 12
|
||||
#define CHIPC_RES4336_BG_PU 13
|
||||
#define CHIPC_RES4336_VREG1p4_PU_PU 14
|
||||
#define CHIPC_RES4336_AFE_PWRSW_PU 15
|
||||
#define CHIPC_RES4336_RX_PWRSW_PU 16
|
||||
#define CHIPC_RES4336_TX_PWRSW_PU 17
|
||||
#define CHIPC_RES4336_BB_PWRSW_PU 18
|
||||
#define CHIPC_RES4336_SYNTH_PWRSW_PU 19
|
||||
#define CHIPC_RES4336_MISC_PWRSW_PU 20
|
||||
#define CHIPC_RES4336_LOGEN_PWRSW_PU 21
|
||||
#define CHIPC_RES4336_BBPLL_PWRSW_PU 22
|
||||
#define CHIPC_RES4336_MACPHY_CLKAVAIL 23
|
||||
#define CHIPC_RES4336_HT_AVAIL 24
|
||||
#define CHIPC_RES4336_RSVD 25
|
||||
|
||||
/* 4336 chip-specific ChipStatus register bits */
|
||||
#define CHIPC_CST4336_SPI_MODE_MASK 0x00000001
|
||||
#define CHIPC_CST4336_SPROM_PRESENT 0x00000002
|
||||
@ -1406,36 +897,6 @@ enum {
|
||||
#define CHIPC_CST4336_CBUCK_MODE_MASK 0x00000600
|
||||
#define CHIPC_CST4336_CBUCK_MODE_SHIFT 9
|
||||
|
||||
/* 4330 resources */
|
||||
#define CHIPC_RES4330_CBUCK_LPOM 0
|
||||
#define CHIPC_RES4330_CBUCK_BURST 1
|
||||
#define CHIPC_RES4330_CBUCK_LP_PWM 2
|
||||
#define CHIPC_RES4330_CBUCK_PWM 3
|
||||
#define CHIPC_RES4330_CLDO_PU 4
|
||||
#define CHIPC_RES4330_DIS_INT_RESET_PD 5
|
||||
#define CHIPC_RES4330_ILP_REQUEST 6
|
||||
#define CHIPC_RES4330_LNLDO_PU 7
|
||||
#define CHIPC_RES4330_LDO3P3_PU 8
|
||||
#define CHIPC_RES4330_OTP_PU 9
|
||||
#define CHIPC_RES4330_XTAL_PU 10
|
||||
#define CHIPC_RES4330_ALP_AVAIL 11
|
||||
#define CHIPC_RES4330_RADIO_PU 12
|
||||
#define CHIPC_RES4330_BG_PU 13
|
||||
#define CHIPC_RES4330_VREG1p4_PU_PU 14
|
||||
#define CHIPC_RES4330_AFE_PWRSW_PU 15
|
||||
#define CHIPC_RES4330_RX_PWRSW_PU 16
|
||||
#define CHIPC_RES4330_TX_PWRSW_PU 17
|
||||
#define CHIPC_RES4330_BB_PWRSW_PU 18
|
||||
#define CHIPC_RES4330_SYNTH_PWRSW_PU 19
|
||||
#define CHIPC_RES4330_MISC_PWRSW_PU 20
|
||||
#define CHIPC_RES4330_LOGEN_PWRSW_PU 21
|
||||
#define CHIPC_RES4330_BBPLL_PWRSW_PU 22
|
||||
#define CHIPC_RES4330_MACPHY_CLKAVAIL 23
|
||||
#define CHIPC_RES4330_HT_AVAIL 24
|
||||
#define CHIPC_RES4330_5gRX_PWRSW_PU 25
|
||||
#define CHIPC_RES4330_5gTX_PWRSW_PU 26
|
||||
#define CHIPC_RES4330_5g_LOGEN_PWRSW_PU 27
|
||||
|
||||
/* 4330 chip-specific ChipStatus register bits */
|
||||
#define CHIPC_CST4330_CHIPMODE_SDIOD(cs) (((cs) & 0x7) < 6) /* SDIO || gSPI */
|
||||
#define CHIPC_CST4330_CHIPMODE_USB20D(cs) (((cs) & 0x7) >= 6) /* USB || USBDA */
|
||||
@ -1458,41 +919,12 @@ enum {
|
||||
#define CHIPC_SOCDEVRAM_4330_BP_ADDR 0x1E000000
|
||||
#define CHIPC_SOCDEVRAM_4330_ARM_ADDR 0x00800000
|
||||
|
||||
/* 4313 resources */
|
||||
#define CHIPC_RES4313_BB_PU_RSRC 0
|
||||
#define CHIPC_RES4313_ILP_REQ_RSRC 1
|
||||
#define CHIPC_RES4313_XTAL_PU_RSRC 2
|
||||
#define CHIPC_RES4313_ALP_AVAIL_RSRC 3
|
||||
#define CHIPC_RES4313_RADIO_PU_RSRC 4
|
||||
#define CHIPC_RES4313_BG_PU_RSRC 5
|
||||
#define CHIPC_RES4313_VREG1P4_PU_RSRC 6
|
||||
#define CHIPC_RES4313_AFE_PWRSW_RSRC 7
|
||||
#define CHIPC_RES4313_RX_PWRSW_RSRC 8
|
||||
#define CHIPC_RES4313_TX_PWRSW_RSRC 9
|
||||
#define CHIPC_RES4313_BB_PWRSW_RSRC 10
|
||||
#define CHIPC_RES4313_SYNTH_PWRSW_RSRC 11
|
||||
#define CHIPC_RES4313_MISC_PWRSW_RSRC 12
|
||||
#define CHIPC_RES4313_BB_PLL_PWRSW_RSRC 13
|
||||
#define CHIPC_RES4313_HT_AVAIL_RSRC 14
|
||||
#define CHIPC_RES4313_MACPHY_CLK_AVAIL_RSRC 15
|
||||
|
||||
/* 4313 chip-specific ChipStatus register bits */
|
||||
#define CHIPC_CST4313_SPROM_PRESENT 1
|
||||
#define CHIPC_CST4313_OTP_PRESENT 2
|
||||
#define CHIPC_CST4313_SPROM_OTP_SEL_MASK 0x00000002
|
||||
#define CHIPC_CST4313_SPROM_OTP_SEL_SHIFT 0
|
||||
|
||||
/* 4313 Chip specific ChipControl register bits */
|
||||
#define CHIPC_CCTRL_4313_12MA_LED_DRIVE 0x00000007 /* 12 mA drive strengh for later 4313 */
|
||||
|
||||
/* 43228 resources */
|
||||
#define CHIPC_RES43228_NOT_USED 0
|
||||
#define CHIPC_RES43228_ILP_REQUEST 1
|
||||
#define CHIPC_RES43228_XTAL_PU 2
|
||||
#define CHIPC_RES43228_ALP_AVAIL 3
|
||||
#define CHIPC_RES43228_PLL_EN 4
|
||||
#define CHIPC_RES43228_HT_PHY_AVAIL 5
|
||||
|
||||
/* 43228 chipstatus reg bits */
|
||||
#define CHIPC_CST43228_ILP_DIV_EN 0x1
|
||||
#define CHIPC_CST43228_OTP_PRESENT 0x2
|
||||
@ -1502,15 +934,6 @@ enum {
|
||||
#define CHIPC_CST43228_SDIO_OTP_PRESENT 0x10
|
||||
#define CHIPC_CST43228_SDIO_RESET 0x20
|
||||
|
||||
/*
|
||||
* Maximum delay for the PMU state transition in us.
|
||||
* This is an upper bound intended for spinwaits etc.
|
||||
*/
|
||||
#define CHIPC_PMU_MAX_TRANSITION_DLY 15000
|
||||
|
||||
/* PMU resource up transition time in ILP cycles */
|
||||
#define CHIPC_PMURES_UP_TRANSITION 2
|
||||
|
||||
/*
|
||||
* Register eci_inputlo bitfield values.
|
||||
* - BT packet type information bits [7:0]
|
||||
|
@ -39,71 +39,15 @@
|
||||
|
||||
#include "chipc.h"
|
||||
|
||||
DECLARE_CLASS(bhnd_chipc);
|
||||
DECLARE_CLASS(bhnd_chipc_driver);
|
||||
extern devclass_t bhnd_chipc_devclass;
|
||||
|
||||
struct chipc_region;
|
||||
|
||||
/**
|
||||
* Supported ChipCommon flash types.
|
||||
*/
|
||||
typedef enum {
|
||||
CHIPC_FLASH_NONE = 0, /**< No flash, or a type unrecognized
|
||||
by the ChipCommon driver */
|
||||
CHIPC_PFLASH_CFI = 1, /**< CFI-compatible parallel flash */
|
||||
CHIPC_SFLASH_ST = 2, /**< ST serial flash */
|
||||
CHIPC_SFLASH_AT = 3, /**< Atmel serial flash */
|
||||
CHIPC_QSFLASH_ST = 4, /**< ST quad-SPI flash */
|
||||
CHIPC_QSFLASH_AT = 5, /**< Atmel quad-SPI flash */
|
||||
CHIPC_NFLASH = 6, /**< NAND flash */
|
||||
CHIPC_NFLASH_4706 = 7 /**< BCM4706 NAND flash */
|
||||
} chipc_flash;
|
||||
|
||||
const char *chipc_flash_name(chipc_flash type);
|
||||
const char *chipc_flash_bus_name(chipc_flash type);
|
||||
const char *chipc_sflash_device_name(chipc_flash type);
|
||||
|
||||
/**
|
||||
* ChipCommon capability flags;
|
||||
*/
|
||||
struct chipc_caps {
|
||||
uint8_t num_uarts; /**< Number of attached UARTS (1-3) */
|
||||
bool mipseb; /**< MIPS is big-endian */
|
||||
uint8_t uart_clock; /**< UART clock source (see CHIPC_CAP_UCLKSEL_*) */
|
||||
uint8_t uart_gpio; /**< UARTs own GPIO pins 12-15 */
|
||||
|
||||
uint8_t extbus_type; /**< ExtBus type (CHIPC_CAP_EXTBUS_*) */
|
||||
|
||||
chipc_flash flash_type; /**< flash type */
|
||||
uint8_t cfi_width; /**< CFI bus width, 0 if unknown or CFI
|
||||
not present */
|
||||
|
||||
bhnd_nvram_src nvram_src; /**< identified NVRAM source */
|
||||
bus_size_t sprom_offset; /**< Offset to SPROM data within
|
||||
SPROM/OTP, 0 if unknown or not
|
||||
present */
|
||||
uint8_t otp_size; /**< OTP (row?) size, 0 if not present */
|
||||
|
||||
uint8_t pll_type; /**< PLL type */
|
||||
bool power_control; /**< Power control available */
|
||||
bool jtag_master; /**< JTAG Master present */
|
||||
bool boot_rom; /**< Internal boot ROM is active */
|
||||
uint8_t backplane_64; /**< Backplane supports 64-bit addressing.
|
||||
Note that this does not gaurantee
|
||||
the CPU itself supports 64-bit
|
||||
addressing. */
|
||||
bool pmu; /**< PMU is present. */
|
||||
bool eci; /**< ECI (enhanced coexistence inteface) is present. */
|
||||
bool seci; /**< SECI (serial ECI) is present */
|
||||
bool sprom; /**< SPROM is present */
|
||||
bool gsio; /**< GSIO (SPI/I2C) present */
|
||||
bool aob; /**< AOB (always on bus) present.
|
||||
If set, PMU and GCI registers are
|
||||
not accessible via ChipCommon,
|
||||
and are instead accessible via
|
||||
dedicated cores on the bhnd bus */
|
||||
};
|
||||
|
||||
/*
|
||||
* ChipCommon device quirks / features
|
||||
*/
|
||||
|
479
sys/dev/bhnd/cores/chipc/pwrctl/bhnd_pwrctl.c
Normal file
479
sys/dev/bhnd/cores/chipc/pwrctl/bhnd_pwrctl.c
Normal file
@ -0,0 +1,479 @@
|
||||
/*-
|
||||
* Copyright (c) 2016 Landon Fuller <landonf@FreeBSD.org>
|
||||
* Copyright (c) 2010, Broadcom Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This file is derived from the siutils.c source distributed with the
|
||||
* Asus RT-N16 firmware source code release.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* $Id: siutils.c,v 1.821.2.48 2011-02-11 20:59:28 Exp $
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/limits.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <dev/bhnd/bhnd.h>
|
||||
|
||||
#include <dev/bhnd/cores/chipc/chipcreg.h>
|
||||
#include <dev/bhnd/cores/chipc/chipcvar.h>
|
||||
|
||||
#include <dev/bhnd/cores/pmu/bhnd_pmuvar.h>
|
||||
#include <dev/bhnd/cores/pmu/bhnd_pmureg.h>
|
||||
|
||||
#include "bhnd_chipc_if.h"
|
||||
|
||||
#include "bhnd_pwrctl_private.h"
|
||||
|
||||
/*
|
||||
* ChipCommon Power Control.
|
||||
*
|
||||
* Provides a bhnd_pmu_if-compatible interface to device clocking and
|
||||
* power management on non-PMU chipsets.
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
BHND_PWRCTL_WAR_UP, /**< apply attach/resume workarounds */
|
||||
BHND_PWRCTL_WAR_RUN, /**< apply running workarounds */
|
||||
BHND_PWRCTL_WAR_DOWN, /**< apply detach/suspend workarounds */
|
||||
} bhnd_pwrctl_wars;
|
||||
|
||||
static int bhnd_pwrctl_updateclk(struct bhnd_pwrctl_softc *sc,
|
||||
bhnd_pwrctl_wars wars);
|
||||
|
||||
static struct bhnd_device_quirk pwrctl_quirks[];
|
||||
|
||||
|
||||
/* Supported parent core device identifiers */
|
||||
static const struct bhnd_device pwrctl_devices[] = {
|
||||
BHND_DEVICE(BCM, CC, "ChipCommon Power Control", pwrctl_quirks),
|
||||
BHND_DEVICE_END
|
||||
};
|
||||
|
||||
/* Device quirks table */
|
||||
static struct bhnd_device_quirk pwrctl_quirks[] = {
|
||||
BHND_CORE_QUIRK (HWREV_LTE(5), PWRCTL_QUIRK_PCICLK_CTL),
|
||||
BHND_CORE_QUIRK (HWREV_RANGE(6, 9), PWRCTL_QUIRK_SLOWCLK_CTL),
|
||||
BHND_CORE_QUIRK (HWREV_RANGE(10, 19), PWRCTL_QUIRK_INSTACLK_CTL),
|
||||
|
||||
BHND_DEVICE_QUIRK_END
|
||||
};
|
||||
|
||||
static int
|
||||
bhnd_pwrctl_probe(device_t dev)
|
||||
{
|
||||
const struct bhnd_device *id;
|
||||
struct chipc_caps *ccaps;
|
||||
device_t chipc;
|
||||
|
||||
/* Look for compatible chipc parent */
|
||||
chipc = device_get_parent(dev);
|
||||
if (device_get_devclass(chipc) != devclass_find("bhnd_chipc"))
|
||||
return (ENXIO);
|
||||
|
||||
if (device_get_driver(chipc) != &bhnd_chipc_driver)
|
||||
return (ENXIO);
|
||||
|
||||
/* Verify chipc capability flags */
|
||||
ccaps = BHND_CHIPC_GET_CAPS(chipc);
|
||||
if (ccaps->pmu || !ccaps->pwr_ctrl)
|
||||
return (ENXIO);
|
||||
|
||||
/* Check for chipc device match */
|
||||
id = bhnd_device_lookup(chipc, pwrctl_devices,
|
||||
sizeof(pwrctl_devices[0]));
|
||||
if (id == NULL)
|
||||
return (ENXIO);
|
||||
|
||||
device_set_desc(dev, id->desc);
|
||||
return (BUS_PROBE_NOWILDCARD);
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_pwrctl_attach(device_t dev)
|
||||
{
|
||||
struct bhnd_pwrctl_softc *sc;
|
||||
const struct bhnd_chipid *cid;
|
||||
struct chipc_softc *chipc_sc;
|
||||
bhnd_devclass_t hostb_class;
|
||||
device_t hostb_dev;
|
||||
int error;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
/* TODO: Need further testing on actual PWRCTL hardware */
|
||||
device_printf(dev, "WARNING: Using untested PWRCTL support\n");
|
||||
|
||||
sc->dev = dev;
|
||||
sc->chipc_dev = device_get_parent(dev);
|
||||
sc->quirks = bhnd_device_quirks(sc->chipc_dev, pwrctl_devices,
|
||||
sizeof(pwrctl_devices[0]));
|
||||
|
||||
/* On devices that lack a slow clock source, HT must always be
|
||||
* enabled. */
|
||||
hostb_class = BHND_DEVCLASS_INVALID;
|
||||
hostb_dev = bhnd_find_hostb_device(device_get_parent(sc->chipc_dev));
|
||||
if (hostb_dev != NULL)
|
||||
hostb_class = bhnd_get_class(hostb_dev);
|
||||
|
||||
cid = bhnd_get_chipid(sc->chipc_dev);
|
||||
switch (cid->chip_id) {
|
||||
case BHND_CHIPID_BCM4311:
|
||||
if (cid->chip_rev <= 1 && hostb_class == BHND_DEVCLASS_PCI)
|
||||
sc->quirks |= PWRCTL_QUIRK_FORCE_HT;
|
||||
break;
|
||||
|
||||
case BHND_CHIPID_BCM4321:
|
||||
if (hostb_class == BHND_DEVCLASS_PCIE ||
|
||||
hostb_class == BHND_DEVCLASS_PCI)
|
||||
sc->quirks |= PWRCTL_QUIRK_FORCE_HT;
|
||||
break;
|
||||
|
||||
case BHND_CHIPID_BCM4716:
|
||||
if (hostb_class == BHND_DEVCLASS_PCIE)
|
||||
sc->quirks |= PWRCTL_QUIRK_FORCE_HT;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Fetch core register block from ChipCommon parent */
|
||||
chipc_sc = device_get_softc(sc->chipc_dev);
|
||||
sc->res = chipc_sc->core;
|
||||
|
||||
PWRCTL_LOCK_INIT(sc);
|
||||
STAILQ_INIT(&sc->clkres_list);
|
||||
|
||||
/* Initialize power control */
|
||||
PWRCTL_LOCK(sc);
|
||||
|
||||
if ((error = bhnd_pwrctl_init(sc))) {
|
||||
PWRCTL_UNLOCK(sc);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Apply default clock transitions */
|
||||
if ((error = bhnd_pwrctl_updateclk(sc, BHND_PWRCTL_WAR_UP))) {
|
||||
PWRCTL_UNLOCK(sc);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
PWRCTL_UNLOCK(sc);
|
||||
|
||||
return (0);
|
||||
|
||||
cleanup:
|
||||
PWRCTL_LOCK_DESTROY(sc);
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_pwrctl_detach(device_t dev)
|
||||
{
|
||||
struct bhnd_pwrctl_softc *sc;
|
||||
struct bhnd_pwrctl_clkres *clkres, *crnext;
|
||||
int error;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
if ((error = bhnd_pwrctl_setclk(sc, BHND_CLOCK_DYN)))
|
||||
return (error);
|
||||
|
||||
STAILQ_FOREACH_SAFE(clkres, &sc->clkres_list, cr_link, crnext)
|
||||
free(clkres, M_DEVBUF);
|
||||
|
||||
PWRCTL_LOCK_DESTROY(sc);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_pwrctl_suspend(device_t dev)
|
||||
{
|
||||
struct bhnd_pwrctl_softc *sc;
|
||||
int error;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
/* Update clock state */
|
||||
PWRCTL_LOCK(sc);
|
||||
error = bhnd_pwrctl_updateclk(sc, BHND_PWRCTL_WAR_DOWN);
|
||||
PWRCTL_UNLOCK(sc);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_pwrctl_resume(device_t dev)
|
||||
{
|
||||
struct bhnd_pwrctl_softc *sc;
|
||||
int error;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
PWRCTL_LOCK(sc);
|
||||
|
||||
/* Re-initialize power control registers */
|
||||
if ((error = bhnd_pwrctl_init(sc))) {
|
||||
device_printf(sc->dev, "PWRCTL init failed: %d\n", error);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Restore clock state */
|
||||
if ((error = bhnd_pwrctl_updateclk(sc, BHND_PWRCTL_WAR_UP))) {
|
||||
device_printf(sc->dev, "clock state restore failed: %d\n",
|
||||
error);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
PWRCTL_UNLOCK(sc);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the clock reservation associated with @p pinfo, if any.
|
||||
*
|
||||
* @param sc Driver instance state.
|
||||
* @param pinfo PMU info for device.
|
||||
*/
|
||||
static struct bhnd_pwrctl_clkres *
|
||||
bhnd_pwrctl_find_res(struct bhnd_pwrctl_softc *sc,
|
||||
struct bhnd_core_pmu_info *pinfo)
|
||||
{
|
||||
struct bhnd_pwrctl_clkres *clkres;
|
||||
|
||||
PWRCTL_LOCK_ASSERT(sc, MA_OWNED);
|
||||
|
||||
STAILQ_FOREACH(clkres, &sc->clkres_list, cr_link) {
|
||||
if (clkres->owner == pinfo->pm_dev)
|
||||
return (clkres);
|
||||
}
|
||||
|
||||
/* not found */
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enumerate all active clock requests, compute the minimum required clock,
|
||||
* and issue any required clock transition.
|
||||
*
|
||||
* @param sc Driver instance state.
|
||||
* @param wars Work-around state.
|
||||
*/
|
||||
static int
|
||||
bhnd_pwrctl_updateclk(struct bhnd_pwrctl_softc *sc, bhnd_pwrctl_wars wars)
|
||||
{
|
||||
struct bhnd_pwrctl_clkres *clkres;
|
||||
bhnd_clock clock;
|
||||
|
||||
PWRCTL_LOCK_ASSERT(sc, MA_OWNED);
|
||||
|
||||
/* Default clock target */
|
||||
clock = BHND_CLOCK_DYN;
|
||||
|
||||
/* Apply quirk-specific overrides to the clock target */
|
||||
switch (wars) {
|
||||
case BHND_PWRCTL_WAR_UP:
|
||||
/* Force HT clock */
|
||||
if (PWRCTL_QUIRK(sc, FORCE_HT))
|
||||
clock = BHND_CLOCK_HT;
|
||||
break;
|
||||
|
||||
case BHND_PWRCTL_WAR_RUN:
|
||||
/* Cannot transition clock if FORCE_HT */
|
||||
if (PWRCTL_QUIRK(sc, FORCE_HT))
|
||||
return (0);
|
||||
break;
|
||||
|
||||
case BHND_PWRCTL_WAR_DOWN:
|
||||
/* Leave default clock unmodified to permit
|
||||
* transition back to BHND_CLOCK_DYN on FORCE_HT devices. */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Determine required clock */
|
||||
STAILQ_FOREACH(clkres, &sc->clkres_list, cr_link)
|
||||
clock = bhnd_clock_max(clock, clkres->clock);
|
||||
|
||||
/* Map to supported clock setting */
|
||||
switch (clock) {
|
||||
case BHND_CLOCK_DYN:
|
||||
case BHND_CLOCK_ILP:
|
||||
clock = BHND_CLOCK_DYN;
|
||||
break;
|
||||
case BHND_CLOCK_ALP:
|
||||
/* In theory FORCE_ALP is supported by the hardware, but
|
||||
* there are currently no known use-cases for it; mapping
|
||||
* to HT is still valid, and allows us to punt on determing
|
||||
* where FORCE_ALP is supported and functional */
|
||||
clock = BHND_CLOCK_HT;
|
||||
break;
|
||||
case BHND_CLOCK_HT:
|
||||
break;
|
||||
default:
|
||||
device_printf(sc->dev, "unknown clock: %#x\n", clock);
|
||||
return (ENODEV);
|
||||
}
|
||||
|
||||
/* Issue transition */
|
||||
return (bhnd_pwrctl_setclk(sc, clock));
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_pwrctl_core_req_clock(device_t dev, struct bhnd_core_pmu_info *pinfo,
|
||||
bhnd_clock clock)
|
||||
{
|
||||
struct bhnd_pwrctl_softc *sc;
|
||||
struct bhnd_pwrctl_clkres *clkres;
|
||||
int error;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
error = 0;
|
||||
|
||||
PWRCTL_LOCK(sc);
|
||||
|
||||
clkres = bhnd_pwrctl_find_res(sc, pinfo);
|
||||
|
||||
/* BHND_CLOCK_DYN discards the clock reservation entirely */
|
||||
if (clock == BHND_CLOCK_DYN) {
|
||||
/* nothing to clean up? */
|
||||
if (clkres == NULL) {
|
||||
PWRCTL_UNLOCK(sc);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* drop reservation and apply clock transition */
|
||||
STAILQ_REMOVE(&sc->clkres_list, clkres,
|
||||
bhnd_pwrctl_clkres, cr_link);
|
||||
|
||||
if ((error = bhnd_pwrctl_updateclk(sc, BHND_PWRCTL_WAR_RUN))) {
|
||||
device_printf(dev, "clock transition failed: %d\n",
|
||||
error);
|
||||
|
||||
/* restore reservation */
|
||||
STAILQ_INSERT_TAIL(&sc->clkres_list, clkres, cr_link);
|
||||
|
||||
PWRCTL_UNLOCK(sc);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/* deallocate orphaned reservation */
|
||||
free(clkres, M_DEVBUF);
|
||||
|
||||
PWRCTL_UNLOCK(sc);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* create (or update) reservation */
|
||||
if (clkres == NULL) {
|
||||
clkres = malloc(sizeof(struct bhnd_pwrctl_clkres), M_DEVBUF,
|
||||
M_NOWAIT);
|
||||
if (clkres == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
clkres->owner = pinfo->pm_dev;
|
||||
clkres->clock = clock;
|
||||
|
||||
STAILQ_INSERT_TAIL(&sc->clkres_list, clkres, cr_link);
|
||||
} else {
|
||||
KASSERT(clkres->owner == pinfo->pm_dev, ("invalid owner"));
|
||||
clkres->clock = clock;
|
||||
}
|
||||
|
||||
/* apply clock transition */
|
||||
error = bhnd_pwrctl_updateclk(sc, BHND_PWRCTL_WAR_RUN);
|
||||
if (error) {
|
||||
STAILQ_REMOVE(&sc->clkres_list, clkres, bhnd_pwrctl_clkres,
|
||||
cr_link);
|
||||
free(clkres, M_DEVBUF);
|
||||
}
|
||||
|
||||
PWRCTL_UNLOCK(sc);
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_pwrctl_core_req_ext_rsrc(device_t dev, struct bhnd_core_pmu_info *pinfo,
|
||||
u_int rsrc)
|
||||
{
|
||||
/* HW does not support per-core external resources */
|
||||
return (ENODEV);
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_pwrctl_core_release_ext_rsrc(device_t dev,
|
||||
struct bhnd_core_pmu_info *pinfo, u_int rsrc)
|
||||
{
|
||||
/* HW does not support per-core external resources */
|
||||
return (ENODEV);
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_pwrctl_core_en_clocks(device_t dev, struct bhnd_core_pmu_info *pinfo,
|
||||
uint32_t clocks)
|
||||
{
|
||||
/* All supported clocks are already enabled by default (?) */
|
||||
clocks &= ~(BHND_CLOCK_DYN |
|
||||
BHND_CLOCK_ILP |
|
||||
BHND_CLOCK_ALP |
|
||||
BHND_CLOCK_HT);
|
||||
|
||||
if (clocks != 0) {
|
||||
device_printf(dev, "%s requested unknown clocks: %#x\n",
|
||||
device_get_nameunit(pinfo->pm_dev), clocks);
|
||||
return (ENODEV);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_pwrctl_core_release(device_t dev, struct bhnd_core_pmu_info *pinfo)
|
||||
{
|
||||
/* Requesting BHND_CLOCK_DYN releases any outstanding clock
|
||||
* reservations */
|
||||
return (bhnd_pwrctl_core_req_clock(dev, pinfo, BHND_CLOCK_DYN));
|
||||
}
|
||||
|
||||
static device_method_t bhnd_pwrctl_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, bhnd_pwrctl_probe),
|
||||
DEVMETHOD(device_attach, bhnd_pwrctl_attach),
|
||||
DEVMETHOD(device_detach, bhnd_pwrctl_detach),
|
||||
DEVMETHOD(device_suspend, bhnd_pwrctl_suspend),
|
||||
DEVMETHOD(device_resume, bhnd_pwrctl_resume),
|
||||
|
||||
/* BHND PMU interface */
|
||||
DEVMETHOD(bhnd_pmu_core_req_clock, bhnd_pwrctl_core_req_clock),
|
||||
DEVMETHOD(bhnd_pmu_core_en_clocks, bhnd_pwrctl_core_en_clocks),
|
||||
DEVMETHOD(bhnd_pmu_core_req_ext_rsrc, bhnd_pwrctl_core_req_ext_rsrc),
|
||||
DEVMETHOD(bhnd_pmu_core_release_ext_rsrc, bhnd_pwrctl_core_release_ext_rsrc),
|
||||
DEVMETHOD(bhnd_pmu_core_release, bhnd_pwrctl_core_release),
|
||||
|
||||
DEVMETHOD_END
|
||||
};
|
||||
|
||||
DEFINE_CLASS_0(bhnd_pmu, bhnd_pwrctl_driver, bhnd_pwrctl_methods,
|
||||
sizeof(struct bhnd_pwrctl_softc));
|
||||
EARLY_DRIVER_MODULE(bhnd_pwrctl, bhnd_chipc, bhnd_pwrctl_driver,
|
||||
bhnd_pmu_devclass, NULL, NULL, BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE);
|
||||
|
||||
MODULE_DEPEND(bhnd_pwrctl, bhnd, 1, 1, 1);
|
||||
MODULE_VERSION(bhnd_pwrctl, 1);
|
43
sys/dev/bhnd/cores/chipc/pwrctl/bhnd_pwrctl_private.h
Normal file
43
sys/dev/bhnd/cores/chipc/pwrctl/bhnd_pwrctl_private.h
Normal file
@ -0,0 +1,43 @@
|
||||
/*-
|
||||
* Copyright (c) 2016 Landon Fuller <landonf@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||
* similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
|
||||
* redistribution must be conditioned upon including a substantially
|
||||
* similar Disclaimer requirement for further binary redistribution.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _BHND_PWRCTL_BHND_PWRCTL_PRIVATE_H_
|
||||
#define _BHND_PWRCTL_BHND_PWRCTL_PRIVATE_H_
|
||||
|
||||
#include "bhnd_pwrctlvar.h"
|
||||
|
||||
int bhnd_pwrctl_init(struct bhnd_pwrctl_softc *sc);
|
||||
int bhnd_pwrctl_setclk(struct bhnd_pwrctl_softc *sc,
|
||||
bhnd_clock clock);
|
||||
uint32_t bhnd_pwrctl_getclk_speed(struct bhnd_pwrctl_softc *sc);
|
||||
uint16_t bhnd_pwrctl_fast_pwrup_delay(struct bhnd_pwrctl_softc *sc);
|
||||
|
||||
#endif /* _BHND_PWRCTL_BHND_PWRCTL_PRIVATE_H_ */
|
558
sys/dev/bhnd/cores/chipc/pwrctl/bhnd_pwrctl_subr.c
Normal file
558
sys/dev/bhnd/cores/chipc/pwrctl/bhnd_pwrctl_subr.c
Normal file
@ -0,0 +1,558 @@
|
||||
/*-
|
||||
* Copyright (c) 2016 Landon Fuller <landonf@FreeBSD.org>
|
||||
* Copyright (c) 2010, Broadcom Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This file is derived from the siutils.c source distributed with the
|
||||
* Asus RT-N16 firmware source code release.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* $Id: siutils.c,v 1.821.2.48 2011-02-11 20:59:28 Exp $
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/limits.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <dev/bhnd/bhnd.h>
|
||||
#include <dev/bhnd/bhndb/bhndb_pcireg.h>
|
||||
|
||||
#include <dev/bhnd/cores/chipc/chipc.h>
|
||||
#include <dev/bhnd/cores/chipc/chipcreg.h>
|
||||
|
||||
#include <dev/bhnd/cores/pmu/bhnd_pmuvar.h>
|
||||
#include <dev/bhnd/cores/pmu/bhnd_pmureg.h>
|
||||
|
||||
#include "bhnd_chipc_if.h"
|
||||
|
||||
#include "bhnd_pwrctl_private.h"
|
||||
|
||||
static uint32_t bhnd_pwrctl_factor6(uint32_t x);
|
||||
|
||||
/**
|
||||
* Return the factor value corresponding to a given N3M clock control magic
|
||||
* field value (CHIPC_F6_*).
|
||||
*/
|
||||
static uint32_t
|
||||
bhnd_pwrctl_factor6(uint32_t x)
|
||||
{
|
||||
switch (x) {
|
||||
case CHIPC_F6_2:
|
||||
return (2);
|
||||
case CHIPC_F6_3:
|
||||
return (3);
|
||||
case CHIPC_F6_4:
|
||||
return (4);
|
||||
case CHIPC_F6_5:
|
||||
return (5);
|
||||
case CHIPC_F6_6:
|
||||
return (6);
|
||||
case CHIPC_F6_7:
|
||||
return (7);
|
||||
default:
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the backplane clock's chipc 'M' register offset for a given PLL type,
|
||||
* or 0 if a fixed clock speed should be used.
|
||||
*
|
||||
* @param cid Chip identification.
|
||||
* @param pll_type PLL type (CHIPC_PLL_TYPE*)
|
||||
* @param[out] fixed_hz If 0 is returned, will be set to the fixed clock
|
||||
* speed for this device.
|
||||
*/
|
||||
bus_size_t
|
||||
bhnd_pwrctl_si_clkreg_m(const struct bhnd_chipid *cid,
|
||||
uint8_t pll_type, uint32_t *fixed_hz)
|
||||
{
|
||||
switch (pll_type) {
|
||||
case CHIPC_PLL_TYPE6:
|
||||
return (CHIPC_CLKC_M3);
|
||||
case CHIPC_PLL_TYPE3:
|
||||
return (CHIPC_CLKC_M2);
|
||||
default:
|
||||
return (CHIPC_CLKC_SB);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the backplane clock speed (in Hz) for a given a set of clock
|
||||
* control values.
|
||||
*
|
||||
* @param cid Chip identification.
|
||||
* @param pll_type PLL type (CHIPC_PLL_TYPE*)
|
||||
* @param n clock control N register value.
|
||||
* @param m clock control M register value.
|
||||
*/
|
||||
uint32_t
|
||||
bhnd_pwrctl_si_clock_rate(const struct bhnd_chipid *cid,
|
||||
uint32_t pll_type, uint32_t n, uint32_t m)
|
||||
{
|
||||
uint32_t rate;
|
||||
|
||||
KASSERT(bhnd_pwrctl_si_clkreg_m(cid, pll_type, NULL) != 0,
|
||||
("can't compute clock rate on fixed clock"));
|
||||
|
||||
rate = bhnd_pwrctl_clock_rate(pll_type, n, m);
|
||||
if (pll_type == CHIPC_PLL_TYPE3)
|
||||
rate /= 2;
|
||||
|
||||
return (rate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the CPU clock's chipc 'M' register offset for a given PLL type,
|
||||
* or 0 if a fixed clock speed should be used.
|
||||
*
|
||||
* @param cid Chip identification.
|
||||
* @param pll_type PLL type (CHIPC_PLL_TYPE*)
|
||||
* @param[out] fixed_hz If 0 is returned, will be set to the fixed clock
|
||||
* speed for this device.
|
||||
*/
|
||||
bus_size_t
|
||||
bhnd_pwrctl_cpu_clkreg_m(const struct bhnd_chipid *cid,
|
||||
uint8_t pll_type, uint32_t *fixed_hz)
|
||||
{
|
||||
switch (pll_type) {
|
||||
case CHIPC_PLL_TYPE2:
|
||||
case CHIPC_PLL_TYPE4:
|
||||
case CHIPC_PLL_TYPE6:
|
||||
case CHIPC_PLL_TYPE7:
|
||||
return (CHIPC_CLKC_M3);
|
||||
|
||||
case CHIPC_PLL_TYPE5:
|
||||
/* fixed 200MHz */
|
||||
if (fixed_hz != NULL)
|
||||
*fixed_hz = 200 * 1000 * 1000;
|
||||
return (0);
|
||||
|
||||
case CHIPC_PLL_TYPE3:
|
||||
if (cid->chip_id == BHND_CHIPID_BCM5365) {
|
||||
/* fixed 200MHz */
|
||||
if (fixed_hz != NULL)
|
||||
*fixed_hz = 200 * 1000 * 1000;
|
||||
return (0);
|
||||
}
|
||||
|
||||
return (CHIPC_CLKC_M2);
|
||||
|
||||
default:
|
||||
return (CHIPC_CLKC_SB);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the CPU clock speed (in Hz) for a given a set of clock control
|
||||
* values.
|
||||
*
|
||||
* @param cid Chip identification.
|
||||
* @param pll_type PLL type (CHIPC_PLL_TYPE*)
|
||||
* @param n clock control N register value.
|
||||
* @param m clock control M register value.
|
||||
*/
|
||||
uint32_t
|
||||
bhnd_pwrctl_cpu_clock_rate(const struct bhnd_chipid *cid,
|
||||
uint32_t pll_type, uint32_t n, uint32_t m)
|
||||
{
|
||||
KASSERT(bhnd_pwrctl_cpu_clkreg_m(cid, pll_type, NULL) != 0,
|
||||
("can't compute clock rate on fixed clock"));
|
||||
|
||||
return (bhnd_pwrctl_clock_rate(pll_type, n, m));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the clock speed (in Hz) for a given a set of clockcontrol
|
||||
* values.
|
||||
*
|
||||
* @param pll_type PLL type (CHIPC_PLL_TYPE*)
|
||||
* @param n clock control N register value.
|
||||
* @param m clock control M register value.
|
||||
*/
|
||||
uint32_t
|
||||
bhnd_pwrctl_clock_rate(uint32_t pll_type, uint32_t n, uint32_t m)
|
||||
{
|
||||
uint32_t clk_base;
|
||||
uint32_t n1, n2, clock, m1, m2, m3, mc;
|
||||
|
||||
n1 = CHIPC_GET_BITS(n, CHIPC_CN_N1);
|
||||
n2 = CHIPC_GET_BITS(n, CHIPC_CN_N2);
|
||||
|
||||
switch (pll_type) {
|
||||
case CHIPC_PLL_TYPE1:
|
||||
case CHIPC_PLL_TYPE3:
|
||||
case CHIPC_PLL_TYPE4:
|
||||
case CHIPC_PLL_TYPE7:
|
||||
n1 = bhnd_pwrctl_factor6(n1);
|
||||
n2 += CHIPC_F5_BIAS;
|
||||
break;
|
||||
|
||||
case CHIPC_PLL_TYPE2:
|
||||
n1 += CHIPC_T2_BIAS;
|
||||
n2 += CHIPC_T2_BIAS;
|
||||
KASSERT(n1 >= 2 && n1 <= 7, ("invalid n1 value"));
|
||||
KASSERT(n2 >= 5 && n2 <= 23, ("invalid n2 value"));
|
||||
break;
|
||||
|
||||
case CHIPC_PLL_TYPE5:
|
||||
return (100000000);
|
||||
|
||||
case CHIPC_PLL_TYPE6:
|
||||
if (m & CHIPC_T6_MMASK)
|
||||
return (CHIPC_T6_M1);
|
||||
else
|
||||
return (CHIPC_T6_M0);
|
||||
|
||||
default:
|
||||
printf("unsupported PLL type %u\n", pll_type);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* PLL types 3 and 7 use BASE2 (25Mhz) */
|
||||
if (pll_type == CHIPC_PLL_TYPE3 || pll_type == CHIPC_PLL_TYPE7) {
|
||||
clk_base = CHIPC_CLOCK_BASE2;
|
||||
} else {
|
||||
clk_base = CHIPC_CLOCK_BASE1;
|
||||
}
|
||||
|
||||
clock = clk_base * n1 * n2;
|
||||
|
||||
if (clock == 0)
|
||||
return (0);
|
||||
|
||||
m1 = CHIPC_GET_BITS(m, CHIPC_M1);
|
||||
m2 = CHIPC_GET_BITS(m, CHIPC_M2);
|
||||
m3 = CHIPC_GET_BITS(m, CHIPC_M3);
|
||||
mc = CHIPC_GET_BITS(m, CHIPC_MC);
|
||||
|
||||
switch (pll_type) {
|
||||
case CHIPC_PLL_TYPE1:
|
||||
case CHIPC_PLL_TYPE3:
|
||||
case CHIPC_PLL_TYPE4:
|
||||
case CHIPC_PLL_TYPE7:
|
||||
m1 = bhnd_pwrctl_factor6(m1);
|
||||
if (pll_type == CHIPC_PLL_TYPE1 || pll_type == CHIPC_PLL_TYPE3)
|
||||
m2 += CHIPC_F5_BIAS;
|
||||
else
|
||||
m2 = bhnd_pwrctl_factor6(m2);
|
||||
|
||||
m3 = bhnd_pwrctl_factor6(m3);
|
||||
|
||||
switch (mc) {
|
||||
case CHIPC_MC_BYPASS:
|
||||
return (clock);
|
||||
case CHIPC_MC_M1:
|
||||
return (clock / m1);
|
||||
case CHIPC_MC_M1M2:
|
||||
return (clock / (m1 * m2));
|
||||
case CHIPC_MC_M1M2M3:
|
||||
return (clock / (m1 * m2 * m3));
|
||||
case CHIPC_MC_M1M3:
|
||||
return (clock / (m1 * m3));
|
||||
default:
|
||||
printf("unsupported pwrctl mc %#x\n", mc);
|
||||
return (0);
|
||||
}
|
||||
case CHIPC_PLL_TYPE2:
|
||||
m1 += CHIPC_T2_BIAS;
|
||||
m2 += CHIPC_T2M2_BIAS;
|
||||
m3 += CHIPC_T2_BIAS;
|
||||
KASSERT(m1 >= 2 && m1 <= 7, ("invalid m1 value"));
|
||||
KASSERT(m2 >= 3 && m2 <= 10, ("invalid m2 value"));
|
||||
KASSERT(m3 >= 2 && m3 <= 7, ("invalid m3 value"));
|
||||
|
||||
if ((mc & CHIPC_T2MC_M1BYP) == 0)
|
||||
clock /= m1;
|
||||
if ((mc & CHIPC_T2MC_M2BYP) == 0)
|
||||
clock /= m2;
|
||||
if ((mc & CHIPC_T2MC_M3BYP) == 0)
|
||||
clock /= m3;
|
||||
|
||||
return (clock);
|
||||
default:
|
||||
panic("unhandled PLL type %u\n", pll_type);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the backplane clock speed in Hz.
|
||||
*
|
||||
* @param sc driver instance state.
|
||||
*/
|
||||
uint32_t
|
||||
bhnd_pwrctl_getclk_speed(struct bhnd_pwrctl_softc *sc)
|
||||
{
|
||||
const struct bhnd_chipid *cid;
|
||||
struct chipc_caps *ccaps;
|
||||
bus_size_t creg;
|
||||
uint32_t n, m;
|
||||
uint32_t rate;
|
||||
|
||||
PWRCTL_LOCK_ASSERT(sc, MA_OWNED);
|
||||
|
||||
cid = bhnd_get_chipid(sc->chipc_dev);
|
||||
ccaps = BHND_CHIPC_GET_CAPS(sc->chipc_dev);
|
||||
|
||||
n = bhnd_bus_read_4(sc->res, CHIPC_CLKC_N);
|
||||
|
||||
/* Get M register offset */
|
||||
creg = bhnd_pwrctl_si_clkreg_m(cid, ccaps->pll_type, &rate);
|
||||
if (creg == 0) /* fixed rate */
|
||||
return (rate);
|
||||
|
||||
/* calculate rate */
|
||||
m = bhnd_bus_read_4(sc->res, creg);
|
||||
return (bhnd_pwrctl_si_clock_rate(cid, ccaps->pll_type, n, m));
|
||||
}
|
||||
|
||||
/* return the slow clock source */
|
||||
static bhnd_clksrc
|
||||
bhnd_pwrctl_slowclk_src(struct bhnd_pwrctl_softc *sc)
|
||||
{
|
||||
uint32_t clkreg;
|
||||
uint32_t clksrc;
|
||||
|
||||
/* Fetch clock source */
|
||||
if (PWRCTL_QUIRK(sc, PCICLK_CTL)) {
|
||||
return (bhnd_pwrctl_get_clksrc(sc->chipc_dev, BHND_CLOCK_ILP));
|
||||
} else if (PWRCTL_QUIRK(sc, SLOWCLK_CTL)) {
|
||||
clkreg = bhnd_bus_read_4(sc->res, CHIPC_PLL_SLOWCLK_CTL);
|
||||
clksrc = clkreg & CHIPC_SCC_SS_MASK;
|
||||
} else {
|
||||
/* Instaclock */
|
||||
clksrc = CHIPC_SCC_SS_XTAL;
|
||||
}
|
||||
|
||||
/* Map to bhnd_clksrc */
|
||||
switch (clksrc) {
|
||||
case CHIPC_SCC_SS_PCI:
|
||||
return (BHND_CLKSRC_PCI);
|
||||
case CHIPC_SCC_SS_LPO:
|
||||
return (BHND_CLKSRC_LPO);
|
||||
case CHIPC_SCC_SS_XTAL:
|
||||
return (BHND_CLKSRC_XTAL);
|
||||
default:
|
||||
return (BHND_CLKSRC_UNKNOWN);
|
||||
}
|
||||
}
|
||||
|
||||
/* return the ILP (slowclock) min or max frequency */
|
||||
static uint32_t
|
||||
bhnd_pwrctl_slowclk_freq(struct bhnd_pwrctl_softc *sc, bool max_freq)
|
||||
{
|
||||
bhnd_clksrc slowclk;
|
||||
uint32_t div;
|
||||
uint32_t hz;
|
||||
|
||||
slowclk = bhnd_pwrctl_slowclk_src(sc);
|
||||
|
||||
/* Determine clock divisor */
|
||||
if (PWRCTL_QUIRK(sc, PCICLK_CTL)) {
|
||||
if (slowclk == BHND_CLKSRC_PCI)
|
||||
div = 64;
|
||||
else
|
||||
div = 32;
|
||||
} else if (PWRCTL_QUIRK(sc, SLOWCLK_CTL)) {
|
||||
div = bhnd_bus_read_4(sc->res, CHIPC_PLL_SLOWCLK_CTL);
|
||||
div = CHIPC_GET_BITS(div, CHIPC_SCC_CD);
|
||||
div *= 4;
|
||||
} else if (PWRCTL_QUIRK(sc, INSTACLK_CTL)) {
|
||||
if (max_freq) {
|
||||
div = 1;
|
||||
} else {
|
||||
div = bhnd_bus_read_4(sc->res, CHIPC_SYS_CLK_CTL);
|
||||
div = CHIPC_GET_BITS(div, CHIPC_SYCC_CD);
|
||||
div = 4 * (div + 1);
|
||||
}
|
||||
} else {
|
||||
device_printf(sc->dev, "unknown device type\n");
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Determine clock frequency */
|
||||
switch (slowclk) {
|
||||
case BHND_CLKSRC_LPO:
|
||||
hz = max_freq ? CHIPC_LPOMAXFREQ : CHIPC_LPOMINFREQ;
|
||||
break;
|
||||
case BHND_CLKSRC_XTAL:
|
||||
hz = max_freq ? CHIPC_XTALMAXFREQ : CHIPC_XTALMINFREQ;
|
||||
break;
|
||||
case BHND_CLKSRC_PCI:
|
||||
hz = max_freq ? CHIPC_PCIMAXFREQ : CHIPC_PCIMINFREQ;
|
||||
break;
|
||||
default:
|
||||
device_printf(sc->dev, "unknown slowclk source %#x\n", slowclk);
|
||||
return (0);
|
||||
}
|
||||
|
||||
return (hz / div);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize power control registers.
|
||||
*/
|
||||
int
|
||||
bhnd_pwrctl_init(struct bhnd_pwrctl_softc *sc)
|
||||
{
|
||||
uint32_t clkctl;
|
||||
uint32_t pll_delay, slowclk, slowmaxfreq;
|
||||
uint32_t pll_on_delay, fref_sel_delay;
|
||||
int error;
|
||||
|
||||
pll_delay = CHIPC_PLL_DELAY;
|
||||
|
||||
/* set all Instaclk chip ILP to 1 MHz */
|
||||
if (PWRCTL_QUIRK(sc, INSTACLK_CTL)) {
|
||||
clkctl = (CHIPC_ILP_DIV_1MHZ << CHIPC_SYCC_CD_SHIFT);
|
||||
clkctl &= CHIPC_SYCC_CD_MASK;
|
||||
bhnd_bus_write_4(sc->res, CHIPC_SYS_CLK_CTL, clkctl);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize PLL/FREF delays.
|
||||
*
|
||||
* If the slow clock is not sourced by the xtal, include the
|
||||
* delay required to bring it up.
|
||||
*/
|
||||
slowclk = bhnd_pwrctl_slowclk_src(sc);
|
||||
if (slowclk != CHIPC_SCC_SS_XTAL)
|
||||
pll_delay += CHIPC_XTAL_ON_DELAY;
|
||||
|
||||
/* Starting with 4318 it is ILP that is used for the delays */
|
||||
if (PWRCTL_QUIRK(sc, INSTACLK_CTL))
|
||||
slowmaxfreq = bhnd_pwrctl_slowclk_freq(sc, false);
|
||||
else
|
||||
slowmaxfreq = bhnd_pwrctl_slowclk_freq(sc, true);
|
||||
|
||||
pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000;
|
||||
fref_sel_delay = ((slowmaxfreq * CHIPC_FREF_DELAY) + 999999) / 1000000;
|
||||
|
||||
bhnd_bus_write_4(sc->res, CHIPC_PLL_ON_DELAY, pll_on_delay);
|
||||
bhnd_bus_write_4(sc->res, CHIPC_PLL_FREFSEL_DELAY, fref_sel_delay);
|
||||
|
||||
/* If required, force HT */
|
||||
if (PWRCTL_QUIRK(sc, FORCE_HT)) {
|
||||
if ((error = bhnd_pwrctl_setclk(sc, BHND_CLOCK_HT)))
|
||||
return (error);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* return the value suitable for writing to the dot11 core
|
||||
* FAST_PWRUP_DELAY register */
|
||||
uint16_t
|
||||
bhnd_pwrctl_fast_pwrup_delay(struct bhnd_pwrctl_softc *sc)
|
||||
{
|
||||
uint32_t pll_on_delay, slowminfreq;
|
||||
uint16_t fpdelay;
|
||||
|
||||
fpdelay = 0;
|
||||
|
||||
slowminfreq = bhnd_pwrctl_slowclk_freq(sc, false);
|
||||
|
||||
pll_on_delay = bhnd_bus_read_4(sc->res, CHIPC_PLL_ON_DELAY) + 2;
|
||||
pll_on_delay *= 1000000;
|
||||
pll_on_delay += (slowminfreq - 1);
|
||||
fpdelay = pll_on_delay / slowminfreq;
|
||||
|
||||
return (fpdelay);
|
||||
}
|
||||
|
||||
/**
|
||||
* Distribute @p clock on backplane.
|
||||
*
|
||||
* @param sc Driver instance state.
|
||||
* @param clock Clock to enable.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval ENODEV If @p clock is unsupported, or if the device does not
|
||||
* support dynamic clock control.
|
||||
*/
|
||||
int
|
||||
bhnd_pwrctl_setclk(struct bhnd_pwrctl_softc *sc, bhnd_clock clock)
|
||||
{
|
||||
uint32_t scc;
|
||||
|
||||
PWRCTL_LOCK_ASSERT(sc, MA_OWNED);
|
||||
|
||||
/* Is dynamic clock control supported? */
|
||||
if (PWRCTL_QUIRK(sc, FIXED_CLK))
|
||||
return (ENODEV);
|
||||
|
||||
/* Chips with ccrev 10 are EOL and they don't have SYCC_HR used below */
|
||||
if (bhnd_get_hwrev(sc->chipc_dev) == 10)
|
||||
return (ENODEV);
|
||||
|
||||
scc = bhnd_bus_read_4(sc->res, CHIPC_PLL_SLOWCLK_CTL);
|
||||
|
||||
switch (clock) {
|
||||
case BHND_CLOCK_HT:
|
||||
/* fast (pll) clock */
|
||||
if (PWRCTL_QUIRK(sc, SLOWCLK_CTL)) {
|
||||
scc &= ~(CHIPC_SCC_XC | CHIPC_SCC_FS | CHIPC_SCC_IP);
|
||||
scc |= CHIPC_SCC_IP;
|
||||
|
||||
/* force xtal back on before clearing SCC_DYN_XTAL.. */
|
||||
bhnd_pwrctl_ungate_clock(sc->chipc_dev, BHND_CLOCK_HT);
|
||||
} else if (PWRCTL_QUIRK(sc, INSTACLK_CTL)) {
|
||||
scc |= CHIPC_SYCC_HR;
|
||||
} else {
|
||||
return (ENODEV);
|
||||
}
|
||||
|
||||
bhnd_bus_write_4(sc->res, CHIPC_PLL_SLOWCLK_CTL, scc);
|
||||
DELAY(CHIPC_PLL_DELAY);
|
||||
|
||||
break;
|
||||
|
||||
case BHND_CLOCK_DYN:
|
||||
/* enable dynamic clock control */
|
||||
if (PWRCTL_QUIRK(sc, SLOWCLK_CTL)) {
|
||||
scc &= ~(CHIPC_SCC_FS | CHIPC_SCC_IP | CHIPC_SCC_XC);
|
||||
if ((scc & CHIPC_SCC_SS_MASK) != CHIPC_SCC_SS_XTAL)
|
||||
scc |= CHIPC_SCC_XC;
|
||||
|
||||
bhnd_bus_write_4(sc->res, CHIPC_PLL_SLOWCLK_CTL, scc);
|
||||
|
||||
/* for dynamic control, we have to release our xtal_pu
|
||||
* "force on" */
|
||||
if (scc & CHIPC_SCC_XC) {
|
||||
bhnd_pwrctl_gate_clock(sc->chipc_dev,
|
||||
BHND_CLOCK_HT);
|
||||
}
|
||||
} else if (PWRCTL_QUIRK(sc, INSTACLK_CTL)) {
|
||||
/* Instaclock */
|
||||
scc &= ~CHIPC_SYCC_HR;
|
||||
bhnd_bus_write_4(sc->res, CHIPC_SYS_CLK_CTL, scc);
|
||||
} else {
|
||||
return (ENODEV);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return (ENODEV);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
135
sys/dev/bhnd/cores/chipc/pwrctl/bhnd_pwrctlvar.h
Normal file
135
sys/dev/bhnd/cores/chipc/pwrctl/bhnd_pwrctlvar.h
Normal file
@ -0,0 +1,135 @@
|
||||
/*-
|
||||
* Copyright (c) 2015-2016 Landon Fuller <landonf@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||
* similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
|
||||
* redistribution must be conditioned upon including a substantially
|
||||
* similar Disclaimer requirement for further binary redistribution.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _BHND_PWRCTL_BHND_PWRCTLVAR_H_
|
||||
#define _BHND_PWRCTL_BHND_PWRCTLVAR_H_
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/queue.h>
|
||||
|
||||
#include <dev/bhnd/bhnd.h>
|
||||
|
||||
uint32_t bhnd_pwrctl_clock_rate(uint32_t pll_type, uint32_t n,
|
||||
uint32_t m);
|
||||
|
||||
bus_size_t bhnd_pwrctl_si_clkreg_m(const struct bhnd_chipid *cid,
|
||||
uint8_t pll_type, uint32_t *fixed_hz);
|
||||
uint32_t bhnd_pwrctl_si_clock_rate(const struct bhnd_chipid *cid,
|
||||
uint32_t pll_type, uint32_t n, uint32_t m);
|
||||
|
||||
bus_size_t bhnd_pwrctl_cpu_clkreg_m(const struct bhnd_chipid *cid,
|
||||
uint8_t pll_type, uint32_t *fixed_hz);
|
||||
uint32_t bhnd_pwrctl_cpu_clock_rate(const struct bhnd_chipid *cid,
|
||||
uint32_t pll_type, uint32_t n, uint32_t m);
|
||||
|
||||
/**
|
||||
* bhnd pwrctl device quirks.
|
||||
*/
|
||||
enum {
|
||||
/** No quirks */
|
||||
PWRCTL_QUIRK_NONE = 0,
|
||||
|
||||
/**
|
||||
* Early ChipCommon revisions do not support dynamic clock control
|
||||
*/
|
||||
PWRCTL_QUIRK_FIXED_CLK = (1 << 0),
|
||||
|
||||
/**
|
||||
* On PCI (not PCIe) devices, early ChipCommon revisions
|
||||
* (rev <= 5) vend xtal/pll and clock config registers via the PCI
|
||||
* config space.
|
||||
*
|
||||
* Dynamic clock control is not supported on these devices.
|
||||
*/
|
||||
PWRCTL_QUIRK_PCICLK_CTL = (1 << 1) | PWRCTL_QUIRK_FIXED_CLK,
|
||||
|
||||
|
||||
/**
|
||||
* On earliy BCM4311, BCM4321, and BCM4716 PCI(e) devices, no ALP
|
||||
* clock is available, and the HT clock must be enabled.
|
||||
*/
|
||||
PWRCTL_QUIRK_FORCE_HT = (1 << 2),
|
||||
|
||||
/**
|
||||
* ChipCommon revisions 6-9 use the slowclk register layout.
|
||||
*/
|
||||
PWRCTL_QUIRK_SLOWCLK_CTL = (1 << 3),
|
||||
|
||||
/**
|
||||
* ChipCommon revisions 10-19 support the instaclk register layout.
|
||||
*/
|
||||
PWRCTL_QUIRK_INSTACLK_CTL = (1 << 4),
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* device clock reservation.
|
||||
*/
|
||||
struct bhnd_pwrctl_clkres {
|
||||
device_t owner; /**< bhnd(4) device holding this reservation */
|
||||
bhnd_clock clock; /**< requested clock */
|
||||
STAILQ_ENTRY(bhnd_pwrctl_clkres) cr_link;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* bhnd pwrctl driver instance state.
|
||||
*/
|
||||
struct bhnd_pwrctl_softc {
|
||||
device_t dev;
|
||||
uint32_t quirks;
|
||||
|
||||
device_t chipc_dev; /**< core device */
|
||||
struct bhnd_resource *res; /**< core register block. */
|
||||
|
||||
struct mtx mtx; /**< state mutex */
|
||||
|
||||
/** active clock reservations */
|
||||
STAILQ_HEAD(, bhnd_pwrctl_clkres) clkres_list;
|
||||
};
|
||||
|
||||
#define PWRCTL_LOCK_INIT(sc) \
|
||||
mtx_init(&(sc)->mtx, device_get_nameunit((sc)->dev), \
|
||||
"bhnd pwrctl driver lock", MTX_DEF)
|
||||
#define PWRCTL_LOCK(sc) mtx_lock(&(sc)->mtx)
|
||||
#define PWRCTL_UNLOCK(sc) mtx_unlock(&(sc)->mtx)
|
||||
#define PWRCTL_LOCK_ASSERT(sc, what) mtx_assert(&(sc)->mtx, what)
|
||||
#define PWRCTL_LOCK_DESTROY(sc) mtx_destroy(&(sc)->mtx)
|
||||
|
||||
/* quirk convenience macro */
|
||||
#define PWRCTL_QUIRK(_sc, _name) \
|
||||
((_sc)->quirks & PWRCTL_QUIRK_ ## _name)
|
||||
|
||||
#define PWRCTL_ASSERT_QUIRK(_sc, name) \
|
||||
KASSERT(PWRCTL_QUIRK((_sc), name), ("quirk " __STRING(_name) " not set"))
|
||||
|
||||
#endif /* _BHND_PWRCTL_BHND_PWRCTLVAR_H_ */
|
508
sys/dev/bhnd/cores/pmu/bhnd_pmu.c
Normal file
508
sys/dev/bhnd/cores/pmu/bhnd_pmu.c
Normal file
@ -0,0 +1,508 @@
|
||||
/*-
|
||||
* Copyright (c) 2015-2016 Landon Fuller <landon@landonf.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||
* similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
|
||||
* redistribution must be conditioned upon including a substantially
|
||||
* similar Disclaimer requirement for further binary redistribution.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/resource.h>
|
||||
|
||||
#include <dev/bhnd/bhnd.h>
|
||||
#include <dev/bhnd/cores/chipc/chipc.h>
|
||||
|
||||
#include "bhnd_nvram_map.h"
|
||||
|
||||
#include "bhnd_pmureg.h"
|
||||
#include "bhnd_pmuvar.h"
|
||||
|
||||
#include "bhnd_pmu_private.h"
|
||||
|
||||
/*
|
||||
* Broadcom PMU driver.
|
||||
*
|
||||
* On modern BHND chipsets, the PMU, GCI, and SRENG (Save/Restore Engine?)
|
||||
* register blocks are found within a dedicated PMU core (attached via
|
||||
* the AHB 'always on bus').
|
||||
*
|
||||
* On earlier chipsets, these register blocks are found at the same
|
||||
* offsets within the ChipCommon core.
|
||||
*/
|
||||
|
||||
devclass_t bhnd_pmu_devclass; /**< bhnd(4) PMU device class */
|
||||
|
||||
static int bhnd_pmu_sysctl_bus_freq(SYSCTL_HANDLER_ARGS);
|
||||
static int bhnd_pmu_sysctl_cpu_freq(SYSCTL_HANDLER_ARGS);
|
||||
static int bhnd_pmu_sysctl_mem_freq(SYSCTL_HANDLER_ARGS);
|
||||
|
||||
static uint32_t bhnd_pmu_read_4(bus_size_t reg, void *ctx);
|
||||
static void bhnd_pmu_write_4(bus_size_t reg, uint32_t val, void *ctx);
|
||||
static uint32_t bhnd_pmu_read_chipst(void *ctx);
|
||||
|
||||
static const struct bhnd_pmu_io bhnd_pmu_res_io = {
|
||||
.rd4 = bhnd_pmu_read_4,
|
||||
.wr4 = bhnd_pmu_write_4,
|
||||
.rd_chipst = bhnd_pmu_read_chipst
|
||||
};
|
||||
|
||||
#define BPMU_CLKCTL_READ_4(_pinfo) \
|
||||
bhnd_bus_read_4((_pinfo)->pm_res, (_pinfo)->pm_regs)
|
||||
|
||||
#define BPMU_CLKCTL_WRITE_4(_pinfo, _val) \
|
||||
bhnd_bus_write_4((_pinfo)->pm_res, (_pinfo)->pm_regs, (_val))
|
||||
|
||||
#define BPMU_CLKCTL_SET_4(_pinfo, _val, _mask) \
|
||||
BPMU_CLKCTL_WRITE_4((_pinfo), \
|
||||
((_val) & (_mask)) | (BPMU_CLKCTL_READ_4(_pinfo) & ~(_mask)))
|
||||
|
||||
/**
|
||||
* Default bhnd_pmu driver implementation of DEVICE_PROBE().
|
||||
*/
|
||||
int
|
||||
bhnd_pmu_probe(device_t dev)
|
||||
{
|
||||
return (BUS_PROBE_DEFAULT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default bhnd_pmu driver implementation of DEVICE_ATTACH().
|
||||
*
|
||||
* @param dev PMU device.
|
||||
* @param res The PMU device registers. The driver will maintain a borrowed
|
||||
* reference to this resource for the lifetime of the device.
|
||||
*/
|
||||
int
|
||||
bhnd_pmu_attach(device_t dev, struct bhnd_resource *res)
|
||||
{
|
||||
struct bhnd_pmu_softc *sc;
|
||||
struct sysctl_ctx_list *ctx;
|
||||
struct sysctl_oid *tree;
|
||||
devclass_t bhnd_class;
|
||||
device_t core, bus;
|
||||
int error;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
sc->dev = dev;
|
||||
sc->quirks = 0;
|
||||
sc->res = res;
|
||||
|
||||
/* Fetch capability flags */
|
||||
sc->caps = bhnd_bus_read_4(sc->res, BHND_PMU_CAP);
|
||||
|
||||
/* Find the bus-attached core */
|
||||
bhnd_class = devclass_find("bhnd");
|
||||
core = sc->dev;
|
||||
while ((bus = device_get_parent(core)) != NULL) {
|
||||
if (device_get_devclass(bus) == bhnd_class)
|
||||
break;
|
||||
|
||||
core = bus;
|
||||
}
|
||||
|
||||
if (core == NULL) {
|
||||
device_printf(sc->dev, "bhnd bus not found\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* Fetch chip and board info */
|
||||
sc->cid = *bhnd_get_chipid(core);
|
||||
|
||||
if ((error = bhnd_read_board_info(core, &sc->board))) {
|
||||
device_printf(sc->dev, "error fetching board info: %d\n",
|
||||
error);
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* Locate ChipCommon device */
|
||||
sc->chipc_dev = bhnd_find_child(bus, BHND_DEVCLASS_CC, 0);
|
||||
if (sc->chipc_dev == NULL) {
|
||||
device_printf(sc->dev, "chipcommon device not found\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* Initialize query state */
|
||||
error = bhnd_pmu_query_init(&sc->query, dev, sc->cid, &bhnd_pmu_res_io,
|
||||
sc);
|
||||
if (error)
|
||||
return (error);
|
||||
sc->io = sc->query.io;
|
||||
sc->io_ctx = sc->query.io_ctx;
|
||||
|
||||
BPMU_LOCK_INIT(sc);
|
||||
|
||||
/* Set quirk flags */
|
||||
switch (sc->cid.chip_id) {
|
||||
case BHND_CHIPID_BCM4328:
|
||||
case BHND_CHIPID_BCM5354:
|
||||
/* HTAVAIL/ALPAVAIL are bitswapped in CLKCTL */
|
||||
sc->quirks |= BPMU_QUIRK_CLKCTL_CCS0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Initialize PMU */
|
||||
if ((error = bhnd_pmu_init(sc))) {
|
||||
device_printf(sc->dev, "PMU init failed: %d\n", error);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/* Set up sysctl nodes */
|
||||
ctx = device_get_sysctl_ctx(dev);
|
||||
tree = device_get_sysctl_tree(dev);
|
||||
|
||||
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
||||
"bus_freq", CTLTYPE_UINT | CTLFLAG_RD, sc, 0,
|
||||
bhnd_pmu_sysctl_bus_freq, "IU", "Bus clock frequency");
|
||||
|
||||
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
||||
"cpu_freq", CTLTYPE_UINT | CTLFLAG_RD, sc, 0,
|
||||
bhnd_pmu_sysctl_cpu_freq, "IU", "CPU clock frequency");
|
||||
|
||||
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
||||
"mem_freq", CTLTYPE_UINT | CTLFLAG_RD, sc, 0,
|
||||
bhnd_pmu_sysctl_mem_freq, "IU", "Memory clock frequency");
|
||||
|
||||
return (0);
|
||||
|
||||
failed:
|
||||
BPMU_LOCK_DESTROY(sc);
|
||||
bhnd_pmu_query_fini(&sc->query);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default bhnd_pmu driver implementation of DEVICE_DETACH().
|
||||
*/
|
||||
int
|
||||
bhnd_pmu_detach(device_t dev)
|
||||
{
|
||||
struct bhnd_pmu_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
BPMU_LOCK_DESTROY(sc);
|
||||
bhnd_pmu_query_fini(&sc->query);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default bhnd_pmu driver implementation of DEVICE_SUSPEND().
|
||||
*/
|
||||
int
|
||||
bhnd_pmu_suspend(device_t dev)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default bhnd_pmu driver implementation of DEVICE_RESUME().
|
||||
*/
|
||||
int
|
||||
bhnd_pmu_resume(device_t dev)
|
||||
{
|
||||
struct bhnd_pmu_softc *sc;
|
||||
int error;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
/* Re-initialize PMU */
|
||||
if ((error = bhnd_pmu_init(sc))) {
|
||||
device_printf(sc->dev, "PMU init failed: %d\n", error);
|
||||
return (error);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_pmu_sysctl_bus_freq(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
struct bhnd_pmu_softc *sc;
|
||||
uint32_t freq;
|
||||
|
||||
sc = arg1;
|
||||
|
||||
BPMU_LOCK(sc);
|
||||
freq = bhnd_pmu_si_clock(&sc->query);
|
||||
BPMU_UNLOCK(sc);
|
||||
|
||||
return (sysctl_handle_32(oidp, NULL, freq, req));
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_pmu_sysctl_cpu_freq(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
struct bhnd_pmu_softc *sc;
|
||||
uint32_t freq;
|
||||
|
||||
sc = arg1;
|
||||
|
||||
BPMU_LOCK(sc);
|
||||
freq = bhnd_pmu_cpu_clock(&sc->query);
|
||||
BPMU_UNLOCK(sc);
|
||||
|
||||
return (sysctl_handle_32(oidp, NULL, freq, req));
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_pmu_sysctl_mem_freq(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
struct bhnd_pmu_softc *sc;
|
||||
uint32_t freq;
|
||||
|
||||
sc = arg1;
|
||||
|
||||
BPMU_LOCK(sc);
|
||||
freq = bhnd_pmu_mem_clock(&sc->query);
|
||||
BPMU_UNLOCK(sc);
|
||||
|
||||
return (sysctl_handle_32(oidp, NULL, freq, req));
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_pmu_core_req_clock(device_t dev, struct bhnd_core_pmu_info *pinfo,
|
||||
bhnd_clock clock)
|
||||
{
|
||||
struct bhnd_pmu_softc *sc;
|
||||
uint32_t avail;
|
||||
uint32_t req;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
avail = 0x0;
|
||||
req = 0x0;
|
||||
|
||||
switch (clock) {
|
||||
case BHND_CLOCK_DYN:
|
||||
break;
|
||||
case BHND_CLOCK_ILP:
|
||||
req |= BHND_CCS_FORCEILP;
|
||||
break;
|
||||
case BHND_CLOCK_ALP:
|
||||
req |= BHND_CCS_FORCEALP;
|
||||
avail |= BHND_CCS_ALPAVAIL;
|
||||
break;
|
||||
case BHND_CLOCK_HT:
|
||||
req |= BHND_CCS_FORCEHT;
|
||||
avail |= BHND_CCS_HTAVAIL;
|
||||
break;
|
||||
default:
|
||||
device_printf(dev, "%s requested unknown clock: %#x\n",
|
||||
device_get_nameunit(pinfo->pm_dev), clock);
|
||||
return (ENODEV);
|
||||
}
|
||||
|
||||
BPMU_LOCK(sc);
|
||||
|
||||
/* Issue request */
|
||||
BPMU_CLKCTL_SET_4(pinfo, req, BHND_CCS_FORCE_MASK);
|
||||
|
||||
/* Wait for clock availability */
|
||||
bhnd_pmu_wait_clkst(sc, pinfo->pm_dev, pinfo->pm_res, pinfo->pm_regs,
|
||||
avail, avail);
|
||||
|
||||
BPMU_UNLOCK(sc);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_pmu_core_en_clocks(device_t dev, struct bhnd_core_pmu_info *pinfo,
|
||||
uint32_t clocks)
|
||||
{
|
||||
struct bhnd_pmu_softc *sc;
|
||||
uint32_t avail;
|
||||
uint32_t req;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
avail = 0x0;
|
||||
req = 0x0;
|
||||
|
||||
/* Build clock request flags */
|
||||
if (clocks & BHND_CLOCK_DYN) /* nothing to enable */
|
||||
clocks &= ~BHND_CLOCK_DYN;
|
||||
|
||||
if (clocks & BHND_CLOCK_ILP) /* nothing to enable */
|
||||
clocks &= ~BHND_CLOCK_ILP;
|
||||
|
||||
if (clocks & BHND_CLOCK_ALP) {
|
||||
req |= BHND_CCS_ALPAREQ;
|
||||
avail |= BHND_CCS_ALPAVAIL;
|
||||
clocks &= ~BHND_CLOCK_ALP;
|
||||
}
|
||||
|
||||
if (clocks & BHND_CLOCK_HT) {
|
||||
req |= BHND_CCS_HTAREQ;
|
||||
avail |= BHND_CCS_HTAVAIL;
|
||||
clocks &= ~BHND_CLOCK_HT;
|
||||
}
|
||||
|
||||
/* Check for unknown clock values */
|
||||
if (clocks != 0x0) {
|
||||
device_printf(dev, "%s requested unknown clocks: %#x\n",
|
||||
device_get_nameunit(pinfo->pm_dev), clocks);
|
||||
return (ENODEV);
|
||||
}
|
||||
|
||||
BPMU_LOCK(sc);
|
||||
|
||||
/* Issue request */
|
||||
BPMU_CLKCTL_SET_4(pinfo, req, BHND_CCS_AREQ_MASK);
|
||||
|
||||
/* Wait for clock availability */
|
||||
bhnd_pmu_wait_clkst(sc, pinfo->pm_dev, pinfo->pm_res, pinfo->pm_regs,
|
||||
avail, avail);
|
||||
|
||||
BPMU_UNLOCK(sc);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_pmu_core_req_ext_rsrc(device_t dev, struct bhnd_core_pmu_info *pinfo,
|
||||
u_int rsrc)
|
||||
{
|
||||
struct bhnd_pmu_softc *sc;
|
||||
uint32_t req;
|
||||
uint32_t avail;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
if (rsrc > BHND_CCS_ERSRC_MAX)
|
||||
return (EINVAL);
|
||||
|
||||
req = BHND_PMU_SET_BITS((1<<rsrc), BHND_CCS_ERSRC_REQ);
|
||||
avail = BHND_PMU_SET_BITS((1<<rsrc), BHND_CCS_ERSRC_STS);
|
||||
|
||||
BPMU_LOCK(sc);
|
||||
|
||||
/* Write request */
|
||||
BPMU_CLKCTL_SET_4(pinfo, req, req);
|
||||
|
||||
/* Wait for resource availability */
|
||||
bhnd_pmu_wait_clkst(sc, pinfo->pm_dev, pinfo->pm_res, pinfo->pm_regs,
|
||||
avail, avail);
|
||||
|
||||
BPMU_UNLOCK(sc);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_pmu_core_release_ext_rsrc(device_t dev, struct bhnd_core_pmu_info *pinfo,
|
||||
u_int rsrc)
|
||||
{
|
||||
struct bhnd_pmu_softc *sc;
|
||||
uint32_t mask;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
if (rsrc > BHND_CCS_ERSRC_MAX)
|
||||
return (EINVAL);
|
||||
|
||||
mask = BHND_PMU_SET_BITS((1<<rsrc), BHND_CCS_ERSRC_REQ);
|
||||
|
||||
/* Clear request */
|
||||
BPMU_LOCK(sc);
|
||||
BPMU_CLKCTL_SET_4(pinfo, 0x0, mask);
|
||||
BPMU_UNLOCK(sc);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_pmu_core_release(device_t dev, struct bhnd_core_pmu_info *pinfo)
|
||||
{
|
||||
struct bhnd_pmu_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
BPMU_LOCK(sc);
|
||||
|
||||
/* Clear all FORCE, AREQ, and ERSRC flags */
|
||||
BPMU_CLKCTL_SET_4(pinfo, 0x0,
|
||||
BHND_CCS_FORCE_MASK | BHND_CCS_AREQ_MASK | BHND_CCS_ERSRC_REQ_MASK);
|
||||
|
||||
BPMU_UNLOCK(sc);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
bhnd_pmu_read_4(bus_size_t reg, void *ctx)
|
||||
{
|
||||
struct bhnd_pmu_softc *sc = ctx;
|
||||
return (bhnd_bus_read_4(sc->res, reg));
|
||||
}
|
||||
|
||||
static void
|
||||
bhnd_pmu_write_4(bus_size_t reg, uint32_t val, void *ctx)
|
||||
{
|
||||
struct bhnd_pmu_softc *sc = ctx;
|
||||
return (bhnd_bus_write_4(sc->res, reg, val));
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
bhnd_pmu_read_chipst(void *ctx)
|
||||
{
|
||||
struct bhnd_pmu_softc *sc = ctx;
|
||||
return (BHND_CHIPC_READ_CHIPST(sc->chipc_dev));
|
||||
}
|
||||
|
||||
static device_method_t bhnd_pmu_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, bhnd_pmu_probe),
|
||||
DEVMETHOD(device_detach, bhnd_pmu_detach),
|
||||
DEVMETHOD(device_suspend, bhnd_pmu_suspend),
|
||||
DEVMETHOD(device_resume, bhnd_pmu_resume),
|
||||
|
||||
/* BHND PMU interface */
|
||||
DEVMETHOD(bhnd_pmu_core_req_clock, bhnd_pmu_core_req_clock),
|
||||
DEVMETHOD(bhnd_pmu_core_en_clocks, bhnd_pmu_core_en_clocks),
|
||||
DEVMETHOD(bhnd_pmu_core_req_ext_rsrc, bhnd_pmu_core_req_ext_rsrc),
|
||||
DEVMETHOD(bhnd_pmu_core_release_ext_rsrc, bhnd_pmu_core_release_ext_rsrc),
|
||||
DEVMETHOD(bhnd_pmu_core_release, bhnd_pmu_core_release),
|
||||
|
||||
DEVMETHOD_END
|
||||
};
|
||||
|
||||
DEFINE_CLASS_0(bhnd_pmu, bhnd_pmu_driver, bhnd_pmu_methods, sizeof(struct bhnd_pmu_softc));
|
||||
MODULE_VERSION(bhnd_pmu, 1);
|
52
sys/dev/bhnd/cores/pmu/bhnd_pmu.h
Normal file
52
sys/dev/bhnd/cores/pmu/bhnd_pmu.h
Normal file
@ -0,0 +1,52 @@
|
||||
/*-
|
||||
* Copyright (c) 2016 Landon Fuller <landonf@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||
* similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
|
||||
* redistribution must be conditioned upon including a substantially
|
||||
* similar Disclaimer requirement for further binary redistribution.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _BHND_CORES_PMU_BHND_PMU_H_
|
||||
#define _BHND_CORES_PMU_BHND_PMU_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "bhnd_pmu_if.h"
|
||||
|
||||
/**
|
||||
* Per-core PMU register information.
|
||||
*/
|
||||
struct bhnd_core_pmu_info {
|
||||
device_t pm_dev; /**< core device */
|
||||
device_t pm_pmu; /**< PMU device */
|
||||
struct bhnd_resource *pm_res; /**< Resource containing PMU
|
||||
register block for this
|
||||
device (if any). */
|
||||
bus_size_t pm_regs; /**< Offset to PMU register
|
||||
* block in @p pm_res */
|
||||
};
|
||||
|
||||
#endif /* _BHND_CORES_PMU_BHND_PMU_H_ */
|
138
sys/dev/bhnd/cores/pmu/bhnd_pmu_core.c
Normal file
138
sys/dev/bhnd/cores/pmu/bhnd_pmu_core.c
Normal file
@ -0,0 +1,138 @@
|
||||
/*-
|
||||
* Copyright (c) 2015-2016 Landon Fuller <landon@landonf.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||
* similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
|
||||
* redistribution must be conditioned upon including a substantially
|
||||
* similar Disclaimer requirement for further binary redistribution.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/resource.h>
|
||||
|
||||
#include <dev/bhnd/bhnd.h>
|
||||
|
||||
#include "bhnd_pmureg.h"
|
||||
#include "bhnd_pmuvar.h"
|
||||
|
||||
/*
|
||||
* PMU core driver.
|
||||
*/
|
||||
|
||||
/* Supported device identifiers */
|
||||
static const struct bhnd_device bhnd_pmucore_devices[] = {
|
||||
BHND_DEVICE(BCM, PMU, NULL, NULL),
|
||||
|
||||
BHND_DEVICE_END
|
||||
};
|
||||
|
||||
static int
|
||||
bhnd_pmu_core_probe(device_t dev)
|
||||
{
|
||||
const struct bhnd_device *id;
|
||||
int error;
|
||||
|
||||
id = bhnd_device_lookup(dev, bhnd_pmucore_devices,
|
||||
sizeof(bhnd_pmucore_devices[0]));
|
||||
if (id == NULL)
|
||||
return (ENXIO);
|
||||
|
||||
/* Delegate to common driver implementation */
|
||||
if ((error = bhnd_pmu_probe(dev)) > 0)
|
||||
return (error);
|
||||
|
||||
bhnd_set_default_core_desc(dev);
|
||||
return (BUS_PROBE_DEFAULT);
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_pmu_core_attach(device_t dev)
|
||||
{
|
||||
struct bhnd_pmu_softc *sc;
|
||||
struct bhnd_resource *res;
|
||||
int error;
|
||||
int rid;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
/* Allocate register block */
|
||||
rid = 0;
|
||||
res = bhnd_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
|
||||
if (res == NULL) {
|
||||
device_printf(dev, "failed to allocate resources\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* Delegate to common driver implementation */
|
||||
if ((error = bhnd_pmu_attach(dev, res))) {
|
||||
bhnd_release_resource(dev, SYS_RES_MEMORY, rid, res);
|
||||
return (error);
|
||||
}
|
||||
|
||||
sc->rid = rid;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_pmu_core_detach(device_t dev)
|
||||
{
|
||||
struct bhnd_pmu_softc *sc;
|
||||
int error;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
/* Delegate to common driver implementation */
|
||||
if ((error = bhnd_pmu_detach(dev)))
|
||||
return (error);
|
||||
|
||||
bhnd_release_resource(dev, SYS_RES_MEMORY, sc->rid, sc->res);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static device_method_t bhnd_pmucore_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, bhnd_pmu_core_probe),
|
||||
DEVMETHOD(device_attach, bhnd_pmu_core_attach),
|
||||
DEVMETHOD(device_detach, bhnd_pmu_core_detach),
|
||||
|
||||
DEVMETHOD_END
|
||||
};
|
||||
|
||||
DEFINE_CLASS_1(bhnd_pmu, bhnd_pmucore_driver, bhnd_pmucore_methods,
|
||||
sizeof(struct bhnd_pmu_softc), bhnd_pmu_driver);
|
||||
EARLY_DRIVER_MODULE(bhnd_pmu, bhnd, bhnd_pmucore_driver, bhnd_pmu_devclass,
|
||||
NULL, NULL, BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE);
|
||||
|
||||
MODULE_DEPEND(bhnd_pmu_core, bhnd_pmu, 1, 1, 1);
|
||||
MODULE_VERSION(bhnd_pmu_core, 1);
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user