mips: Remove sys/mips

Remove sys/mips as the next step of decomissioning mips from the tree.
Remove mips special cases from the kernel make files. Remove the mips
specific linker scripts.

Sponsored by:		Netflix
This commit is contained in:
Warner Losh 2021-12-30 20:56:09 -07:00
parent fe532f1a50
commit c09981f142
594 changed files with 4 additions and 134562 deletions

View File

@ -1,110 +0,0 @@
# Makefile.mips
# $FreeBSD$
#
# Makefile for FreeBSD
#
# This makefile is constructed from a machine description:
# config machineid
# Most changes should be made in the machine description
# /sys/mips/conf/``machineid''
# after which you should do
# config machineid
# Generic makefile changes should be made in
# /sys/conf/Makefile.mips
# after which config should be rerun for all machines.
#
# Which version of config(8) is required.
%VERSREQ= 600012
STD8X16FONT?= iso
.if !defined(S)
.if exists(./@/.)
S= ./@
.else
S= ../../..
.endif
.endif
.include "$S/conf/kern.pre.mk"
INCLUDES+= -I$S/contrib/libfdt -I$S/contrib/device-tree/include
LDSCRIPT_NAME?=ldscript.$M
SYSTEM_LD:= ${SYSTEM_LD:$S/conf/${LDSCRIPT_NAME}=${LDSCRIPT_NAME}}
SYSTEM_DEP:= ${SYSTEM_DEP:$S/conf/${LDSCRIPT_NAME}=${LDSCRIPT_NAME}}
KERNLOADADDR?=0x80001000
# This obscure value is defined by CFE for WR160N
# To be changed later
TRAMPLOADADDR?=0x807963c0
# We default to the MIPS32 ISA for O32 and MIPS64 ISA for N64 and N32
# if none is specified in the kernel configuration file.
.if ${MACHINE_ARCH:Mmips64*} != "" || ${MACHINE_ARCH:Mmipsn32*} != ""
ARCH_FLAGS?=-march=mips64
.else
ARCH_FLAGS?=-march=mips32
.endif
ARCH_FLAGS+=-mabi=${MIPS_ABI}
EXTRA_FLAGS=-fno-pic -mno-abicalls -G0 -DKERNLOADADDR=${KERNLOADADDR}
EXTRA_FLAGS+=-${MIPS_ENDIAN}
# We add the -fno-pic flag to kernels because otherwise performance
# is extremely poor, as well as -mno-abicalls to force no ABI usage.
CFLAGS+=${EXTRA_FLAGS} $(ARCH_FLAGS)
TRAMP_ARCH_FLAGS?=$(ARCH_FLAGS)
TRAMP_EXTRA_FLAGS=${EXTRA_FLAGS} ${TRAMP_ARCH_FLAGS}
# Kernel code is always compiled with soft-float on MIPS
TRAMP_EXTRA_FLAGS+=-msoft-float
# No standard library available
TRAMP_EXTRA_FLAGS+=-ffreestanding
.if ${MACHINE_ARCH:Mmips64*} != ""
TRAMP_ELFSIZE=64
.else
TRAMP_ELFSIZE=32
.endif
ASM_CFLAGS+=${CFLAGS} -D_LOCORE -DLOCORE
.if !defined(WITHOUT_KERNEL_TRAMPOLINE)
KERNEL_EXTRA=trampoline
KERNEL_EXTRA_INSTALL=${KERNEL_KO}.tramp.bin
trampoline: ${KERNEL_KO}.tramp.bin
${KERNEL_KO}.tramp.bin: ${KERNEL_KO} $S/$M/$M/elf_trampoline.c \
$S/$M/$M/inckern.S
${OBJCOPY} --strip-symbol '$$d' --strip-symbol '$$a' \
-g --strip-symbol '$$t' ${FULLKERNEL} ${KERNEL_KO}.tmp
sed -e s/${KERNLOADADDR}/${TRAMPLOADADDR}/ -e s/" + SIZEOF_HEADERS"// \
${LDSCRIPT_NAME} > ${LDSCRIPT_NAME}.tramp.noheader
${CC} -O -nostdlib -I. -I$S ${TRAMP_EXTRA_FLAGS} ${TRAMP_LDFLAGS} -Xlinker \
-T -Xlinker ${LDSCRIPT_NAME}.tramp.noheader \
-DKERNNAME="\"${KERNEL_KO}.tmp\"" -DELFSIZE=${TRAMP_ELFSIZE} \
-fno-asynchronous-unwind-tables \
$S/$M/$M/inckern.S $S/$M/$M/elf_trampoline.c \
-o ${KERNEL_KO}.tramp.elf
${OBJCOPY} -S -O binary ${KERNEL_KO}.tramp.elf \
${KERNEL_KO}.tramp.bin
.endif
%BEFORE_DEPEND
%OBJS
%FILES.c
%FILES.s
%FILES.m
%CLEAN
CLEAN+= ${LDSCRIPT_NAME} ${LDSCRIPT_NAME}.tramp.noheader \
${KERNEL_KO}.tramp.elf ${KERNEL_KO}.tramp.bin
${LDSCRIPT_NAME}: $S/conf/${LDSCRIPT_NAME}
sed s/KERNLOADADDR/${KERNLOADADDR}/g $S/conf/${LDSCRIPT_NAME} \
> ${LDSCRIPT_NAME}
%RULES
.include "$S/conf/kern.post.mk"

View File

@ -10,11 +10,9 @@
.if !defined(KERNBUILDDIR)
opt_global.h:
touch ${.TARGET}
.if ${MACHINE} != "mips"
@echo "#define SMP 1" >> ${.TARGET}
@echo "#define MAC 1" >> ${.TARGET}
@echo "#define VIMAGE 1" >> ${.TARGET}
.endif
.if ${MK_BHYVE_SNAPSHOT} != "no"
opt_bhyve_snapshot.h:
@echo "#define BHYVE_SNAPSHOT 1" > ${.TARGET}

View File

@ -1,114 +0,0 @@
# This file tells config what files go into building a kernel,
# files marked standard are always included.
#
# $FreeBSD$
#
# Arch dependent files
mips/mips/autoconf.c standard
mips/mips/bus_space_generic.c standard
mips/mips/busdma_machdep.c standard
mips/mips/cache.c standard
mips/mips/cache_mipsNN.c standard
mips/mips/cpu.c standard
mips/mips/db_disasm.c optional ddb
mips/mips/db_interface.c optional ddb
mips/mips/db_trace.c optional ddb
mips/mips/dump_machdep.c standard
mips/mips/elf_machdep.c standard
mips/mips/exception.S standard
mips/mips/fp.S standard
mips/mips/freebsd32_machdep.c optional compat_freebsd32
mips/mips/gdb_machdep.c standard
mips/mips/libkern_machdep.c standard
mips/mips/locore.S standard no-obj
mips/mips/machdep.c standard
mips/mips/mem.c optional mem
mips/mips/minidump_machdep.c standard
mips/mips/mp_machdep.c optional smp
mips/mips/mpboot.S optional smp
mips/mips/nexus.c standard
mips/mips/ofw_machdep.c optional fdt
mips/mips/pm_machdep.c standard
mips/mips/pmap.c standard
mips/mips/ptrace_machdep.c standard
mips/mips/sc_machdep.c standard
mips/mips/stack_machdep.c optional ddb | stack
mips/mips/stdatomic.c standard \
compile-with "${NORMAL_C:N-Wmissing-prototypes}"
mips/mips/support.S standard
mips/mips/bcopy.S standard
mips/mips/swtch.S standard
mips/mips/sys_machdep.c standard
mips/mips/tlb.c standard
mips/mips/trap.c standard
mips/mips/uio_machdep.c standard
mips/mips/uma_machdep.c standard
mips/mips/vm_machdep.c standard
# misc opt-in bits
kern/link_elf_obj.c standard
kern/subr_atomic64.c optional mips | mipsel | mipshf | mipselhf
kern/subr_busdma_bufalloc.c standard
kern/subr_dummy_vdso_tc.c standard
kern/subr_sfbuf.c optional mips | mipsel | mipsn32
kern/subr_sfbuf.c optional mipshf | mipselhf
# gcc/clang runtime
libkern/ffsl.c standard
libkern/ffsll.c standard
libkern/fls.c standard
libkern/flsl.c standard
libkern/flsll.c standard
libkern/cmpdi2.c optional mips | mipshf | mipsel | mipselhf
libkern/ucmpdi2.c optional mips | mipshf | mipsel | mipselhf
libkern/ashldi3.c standard
libkern/ashrdi3.c standard
libkern/memcmp.c standard
libkern/strlen.c standard
# cfe support
dev/cfe/cfe_api.c optional cfe
dev/cfe/cfe_console.c optional cfe_console
dev/cfe/cfe_env.c optional cfe_env
# syscons support
dev/fb/fb.c optional sc
dev/syscons/scgfbrndr.c optional sc
mips/mips/sc_machdep.c optional sc
# FDT support
dev/uart/uart_cpu_fdt.c optional uart fdt
# crypto support -- use generic
crypto/des/des_enc.c optional netsmb
# AP common nvram interface MIPS specific, but maybe should be more generic
dev/nvram2env/nvram2env_mips.c optional nvram2env
dev/nvram2env/nvram2env.c optional nvram2env
# hwpmc support
dev/hwpmc/hwpmc_beri.c optional hwpmc_beri
dev/hwpmc/hwpmc_mips.c optional hwpmc_mips24k | \
hwpmc_mips74k
dev/hwpmc/hwpmc_mips24k.c optional hwpmc_mips24k
dev/hwpmc/hwpmc_mips74k.c optional hwpmc_mips74k
# ofw support
dev/ofw/ofw_pcib.c optional fdt pci
# INTRNG support code
kern/msi_if.m optional intrng
kern/pic_if.m optional intrng
kern/subr_intr.c optional intrng
# INTRNG compatible MIPS32 interrupt controller
mips/mips/mips_pic.c optional intrng
# DTrace
cddl/compat/opensolaris/kern/opensolaris_atomic.c optional zfs | dtrace compile-with "${CDDL_C}"
cddl/dev/dtrace/mips/dtrace_asm.S optional dtrace compile-with "${DTRACE_S}"
cddl/dev/dtrace/mips/dtrace_subr.c optional dtrace compile-with "${DTRACE_C}"
cddl/dev/fbt/mips/fbt_isa.c optional dtrace_fbt | dtraceall compile-with "${FBT_C}"
# Zstd
contrib/zstd/lib/freebsd/zstd_kfreebsd.c optional zstdio compile-with ${ZSTD_C}

View File

@ -192,14 +192,6 @@ CFLAGS.gcc+= -mno-spe
CFLAGS+= -mabi=elfv2
.endif
#
# For MIPS we also tell gcc to use floating point emulation
#
.if ${MACHINE_CPUARCH} == "mips"
CFLAGS+= -msoft-float
INLINE_LIMIT?= 8000
.endif
#
# GCC 3.0 and above like to do certain optimizations based on the
# assumption that the program is linked against libc. Stop this.
@ -307,16 +299,6 @@ LD_EMULATION_arm=armelf_fbsd
LD_EMULATION_armv6=armelf_fbsd
LD_EMULATION_armv7=armelf_fbsd
LD_EMULATION_i386=elf_i386_fbsd
LD_EMULATION_mips= elf32btsmip_fbsd
LD_EMULATION_mipshf= elf32btsmip_fbsd
LD_EMULATION_mips64= elf64btsmip_fbsd
LD_EMULATION_mips64hf= elf64btsmip_fbsd
LD_EMULATION_mipsel= elf32ltsmip_fbsd
LD_EMULATION_mipselhf= elf32ltsmip_fbsd
LD_EMULATION_mips64el= elf64ltsmip_fbsd
LD_EMULATION_mips64elhf= elf64ltsmip_fbsd
LD_EMULATION_mipsn32= elf32btsmipn32_fbsd
LD_EMULATION_mipsn32el= elf32btsmipn32_fbsd # I don't think this is a thing that works
LD_EMULATION_powerpc= elf32ppc_fbsd
LD_EMULATION_powerpcspe= elf32ppc_fbsd
LD_EMULATION_powerpc64= elf64ppc_fbsd

View File

@ -79,10 +79,6 @@ BROKEN_OPTIONS+= CDDL ZFS
. endif
.endif
.if ${MACHINE_CPUARCH} == "mips"
BROKEN_OPTIONS+= CDDL ZFS SSP
.endif
.if ${MACHINE_CPUARCH} == "powerpc" && ${MACHINE_ARCH} == "powerpc"
BROKEN_OPTIONS+= ZFS
.endif
@ -98,8 +94,8 @@ BROKEN_OPTIONS+= OFED
BROKEN_OPTIONS+= KERNEL_RETPOLINE
.endif
# EFI doesn't exist on mips, powerpc, or riscv.
.if ${MACHINE:Mmips} || ${MACHINE:Mpowerpc} || ${MACHINE:Mriscv}
# EFI doesn't exist on powerpc, or riscv
.if ${MACHINE:Mpowerpc} || ${MACHINE:Mriscv}
BROKEN_OPTIONS+=EFI
.endif

View File

@ -74,9 +74,6 @@ CFLAGS= ${COPTFLAGS} ${DEBUG}
CFLAGS+= ${INCLUDES} -D_KERNEL -DHAVE_KERNEL_OPTION_HEADERS -include opt_global.h
CFLAGS_PARAM_INLINE_UNIT_GROWTH?=100
CFLAGS_PARAM_LARGE_FUNCTION_GROWTH?=1000
.if ${MACHINE_CPUARCH} == "mips"
CFLAGS_ARCH_PARAMS?=--param max-inline-insns-single=1000 -DMACHINE_ARCH='"${MACHINE_ARCH}"'
.endif
CFLAGS.gcc+= -fms-extensions -finline-limit=${INLINE_LIMIT}
CFLAGS.gcc+= --param inline-unit-growth=${CFLAGS_PARAM_INLINE_UNIT_GROWTH}
CFLAGS.gcc+= --param large-function-growth=${CFLAGS_PARAM_LARGE_FUNCTION_GROWTH}

View File

@ -80,8 +80,8 @@ OBJCOPY?= objcopy
.SUFFIXES: .out .o .c .cc .cxx .C .y .l .s .S .m
# amd64 and mips use direct linking for kmod, all others use shared binaries
.if ${MACHINE_CPUARCH} != amd64 && ${MACHINE_CPUARCH} != mips
# amd64 uses direct linking for kmod, all others use shared binaries
.if ${MACHINE_CPUARCH} != amd64
__KLD_SHARED=yes
.else
__KLD_SHARED=no
@ -173,10 +173,6 @@ LDFLAGS+= --no-toc-optimize
.endif
.endif
.if ${MACHINE_CPUARCH} == mips
CFLAGS+= -G0 -fno-pic -mno-abicalls -mlong-calls
.endif
.if defined(DEBUG) || defined(DEBUG_FLAGS)
CTFFLAGS+= -g
.endif

View File

@ -1,300 +0,0 @@
/*-
* Copyright (c) 2001, 2004, 2008, Juniper Networks, Inc.
* 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 Juniper Networks, Inc. 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 JUNIPER NETWORKS 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 JUNIPER NETWORKS 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.
*
* JNPR: ldscript.mips,v 1.3 2006/10/11 06:12:04
* $FreeBSD$
*/
OUTPUT_ARCH(mips)
ENTRY(_start)
SEARCH_DIR(/usr/lib);
SECTIONS
{
/* Read-only sections, merged into text segment: */
. = KERNLOADADDR + SIZEOF_HEADERS;
.text :
{
*(.trap)
*(.text)
*(.text.*)
*(.stub)
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)
*(.gnu.linkonce.t.*)
} =0x1000000
.fini :
{
KEEP (*(.fini))
} =0x1000000
PROVIDE (__etext = .);
PROVIDE (_etext = .);
PROVIDE (etext = .);
.rodata : { *(.rodata) *(.rodata.*) *(.gnu.linkonce.r.*) }
.rodata1 : { *(.rodata1) }
.interp : { *(.interp) }
.hash : { *(.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.gnu.version : { *(.gnu.version) }
.gnu.version_d : { *(.gnu.version_d) }
.gnu.version_r : { *(.gnu.version_r) }
.note.gnu.build-id : {
PROVIDE (__build_id_start = .);
*(.note.gnu.build-id)
PROVIDE (__build_id_end = .);
}
.rel.init : { *(.rel.init) }
.rela.init : { *(.rela.init) }
.rel.text :
{
*(.rel.text)
*(.rel.text.*)
*(.rel.gnu.linkonce.t.*)
}
.rela.text :
{
*(.rela.text)
*(.rela.text.*)
*(.rela.gnu.linkonce.t.*)
}
.rel.fini : { *(.rel.fini) }
.rela.fini : { *(.rela.fini) }
.rel.rodata :
{
*(.rel.rodata)
*(.rel.rodata.*)
*(.rel.gnu.linkonce.r.*)
}
.rela.rodata :
{
*(.rela.rodata)
*(.rela.rodata.*)
*(.rela.gnu.linkonce.r.*)
}
.rel.data :
{
*(.rel.data)
*(.rel.data.*)
*(.rel.gnu.linkonce.d.*)
}
.rela.data :
{
*(.rela.data)
*(.rela.data.*)
*(.rela.gnu.linkonce.d.*)
}
.rel.ctors : { *(.rel.ctors) }
.rela.ctors : { *(.rela.ctors) }
.rel.dtors : { *(.rel.dtors) }
.rela.dtors : { *(.rela.dtors) }
.rel.got : { *(.rel.got) }
.rela.got : { *(.rela.got) }
.rel.sdata :
{
*(.rel.sdata)
*(.rel.sdata.*)
*(.rel.gnu.linkonce.s.*)
}
.rela.sdata :
{
*(.rela.sdata)
*(.rela.sdata.*)
*(.rela.gnu.linkonce.s.*)
}
.rel.sbss :
{
*(.rel.sbss)
*(.rel.sbss.*)
*(.rel.gnu.linkonce.sb.*)
}
.rela.sbss :
{
*(.rela.sbss)
*(.rela.sbss.*)
*(.rel.gnu.linkonce.sb.*)
}
.rel.sdata2 :
{
*(.rel.sdata2)
*(.rel.sdata2.*)
*(.rel.gnu.linkonce.s2.*)
}
.rela.sdata2 :
{
*(.rela.sdata2)
*(.rela.sdata2.*)
*(.rela.gnu.linkonce.s2.*)
}
.rel.sbss2 :
{
*(.rel.sbss2)
*(.rel.sbss2.*)
*(.rel.gnu.linkonce.sb2.*)
}
.rela.sbss2 :
{
*(.rela.sbss2)
*(.rela.sbss2.*)
*(.rela.gnu.linkonce.sb2.*)
}
.rel.bss :
{
*(.rel.bss)
*(.rel.bss.*)
*(.rel.gnu.linkonce.b.*)
}
.rela.bss :
{
*(.rela.bss)
*(.rela.bss.*)
*(.rela.gnu.linkonce.b.*)
}
.rel.plt : { *(.rel.plt) }
.rela.plt : { *(.rela.plt) }
.init :
{
KEEP (*(.init))
} =0x1000000
.reginfo : { *(.reginfo) }
.sdata2 : { *(.sdata2) *(.sdata2.*) *(.gnu.linkonce.s2.*) }
.sbss2 : { *(.sbss2) *(.sbss2.*) *(.gnu.linkonce.sb2.*) }
. = ALIGN(0x2000) + (. & (0x2000 - 1));
.data :
{
*(.data)
*(.data.*)
*(.gnu.linkonce.d.*)
}
.data1 : { *(.data1) }
.eh_frame : { KEEP (*(.eh_frame)) }
.gcc_except_table : { *(.gcc_except_table) }
.ctors :
{
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
/* We don't want to include the .ctor section from
from the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE (*crtend.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
}
.dtors :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
}
.plt : { *(.plt) }
_gp = ALIGN(16) + 0x7ff0;
.got : { *(.got.plt) *(.got) }
.dynamic : { *(.dynamic) }
/* We want the small data sections together, so single-instruction offsets
can access them all, and initialized data all before uninitialized, so
we can shorten the on-disk segment size. */
.sdata :
{
*(.sdata)
*(.sdata.*)
*(.gnu.linkonce.s.*)
}
_edata = .;
PROVIDE (edata = .);
__bss_start = .;
.sbss :
{
PROVIDE (__sbss_start = .);
PROVIDE (___sbss_start = .);
*(.dynsbss)
*(.sbss)
*(.sbss.*)
*(.gnu.linkonce.sb.*)
*(.scommon)
PROVIDE (__sbss_end = .);
PROVIDE (___sbss_end = .);
}
.bss :
{
*(.dynbss)
*(.bss)
*(.bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
/* Align here to ensure that the .bss section occupies space up to
_end. Align after .bss to ensure correct alignment even if the
.bss section disappears because there are no input sections. */
. = ALIGN(64 / 8);
}
. = ALIGN(64 / 8);
_end = .;
PROVIDE (end = .);
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info) *(.gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
/* These must appear regardless of . */
}

View File

@ -1,317 +0,0 @@
/*-
* Copyright (c) 2001, 2004, 2008, Juniper Networks, Inc.
* 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 Juniper Networks, Inc. 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 JUNIPER NETWORKS 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 JUNIPER NETWORKS 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.
*
* JNPR: ldscript.mips,v 1.3 2006/10/11 06:12:04
* $FreeBSD$
*/
/*
* This linker script is needed to build a kernel for use by Broadcom CFE
* when loaded over TFTP; its ELF loader does not support backwards seek
* on network I/O streams.
* Furthermore, CFE will only load PT_LOAD segments, therefore the dynamic
* sections must be placed in their own segment.
*/
ENTRY(_start)
SEARCH_DIR(/usr/lib);
PHDRS
{
headers PT_PHDR FILEHDR PHDRS ;
interp PT_INTERP ;
text PT_LOAD ;
dynamic PT_LOAD ;
data PT_LOAD ;
}
SECTIONS
{
/* Read-only sections, merged into text segment: */
. = KERNLOADADDR ;
.interp : { *(.interp) } :interp
.hash : { *(.hash) } :text
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.gnu.version : { *(.gnu.version) }
.gnu.version_d : { *(.gnu.version_d) }
.gnu.version_r : { *(.gnu.version_r) }
.rel.init : { *(.rel.init) }
.rela.init : { *(.rela.init) }
.rel.text :
{
*(.rel.text)
*(.rel.text.*)
*(.rel.gnu.linkonce.t.*)
}
.rela.text :
{
*(.rela.text)
*(.rela.text.*)
*(.rela.gnu.linkonce.t.*)
}
.rel.fini : { *(.rel.fini) }
.rela.fini : { *(.rela.fini) }
.rel.rodata :
{
*(.rel.rodata)
*(.rel.rodata.*)
*(.rel.gnu.linkonce.r.*)
}
.rela.rodata :
{
*(.rela.rodata)
*(.rela.rodata.*)
*(.rela.gnu.linkonce.r.*)
}
.rel.data :
{
*(.rel.data)
*(.rel.data.*)
*(.rel.gnu.linkonce.d.*)
}
.rela.data :
{
*(.rela.data)
*(.rela.data.*)
*(.rela.gnu.linkonce.d.*)
}
.rel.ctors : { *(.rel.ctors) }
.rela.ctors : { *(.rela.ctors) }
.rel.dtors : { *(.rel.dtors) }
.rela.dtors : { *(.rela.dtors) }
.rel.got : { *(.rel.got) }
.rela.got : { *(.rela.got) }
.rel.sdata :
{
*(.rel.sdata)
*(.rel.sdata.*)
*(.rel.gnu.linkonce.s.*)
}
.rela.sdata :
{
*(.rela.sdata)
*(.rela.sdata.*)
*(.rela.gnu.linkonce.s.*)
}
.rel.sbss :
{
*(.rel.sbss)
*(.rel.sbss.*)
*(.rel.gnu.linkonce.sb.*)
}
.rela.sbss :
{
*(.rela.sbss)
*(.rela.sbss.*)
*(.rel.gnu.linkonce.sb.*)
}
.rel.sdata2 :
{
*(.rel.sdata2)
*(.rel.sdata2.*)
*(.rel.gnu.linkonce.s2.*)
}
.rela.sdata2 :
{
*(.rela.sdata2)
*(.rela.sdata2.*)
*(.rela.gnu.linkonce.s2.*)
}
.rel.sbss2 :
{
*(.rel.sbss2)
*(.rel.sbss2.*)
*(.rel.gnu.linkonce.sb2.*)
}
.rela.sbss2 :
{
*(.rela.sbss2)
*(.rela.sbss2.*)
*(.rela.gnu.linkonce.sb2.*)
}
.rel.bss :
{
*(.rel.bss)
*(.rel.bss.*)
*(.rel.gnu.linkonce.b.*)
}
.rela.bss :
{
*(.rela.bss)
*(.rela.bss.*)
*(.rela.gnu.linkonce.b.*)
}
.rel.plt : { *(.rel.plt) }
.rela.plt : { *(.rela.plt) }
.init :
{
KEEP (*(.init))
} :text =0x1000000
.text :
{
*(.trap)
*(.text)
*(.text.*)
*(.stub)
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)
*(.gnu.linkonce.t.*)
} =0x1000000
.fini :
{
KEEP (*(.fini))
} =0x1000000
PROVIDE (__etext = .);
PROVIDE (_etext = .);
PROVIDE (etext = .);
.rodata : { *(.rodata) *(.rodata.*) *(.gnu.linkonce.r.*) }
.rodata1 : { *(.rodata1) }
.note.gnu.build-id : {
PROVIDE (__build_id_start = .);
*(.note.gnu.build-id)
PROVIDE (__build_id_end = .);
}
.reginfo : { *(.reginfo) }
.sdata2 : { *(.sdata2) *(.sdata2.*) *(.gnu.linkonce.s2.*) }
.sbss2 : { *(.sbss2) *(.sbss2.*) *(.gnu.linkonce.sb2.*) }
. = ALIGN(0x2000) + (. & (0x2000 - 1));
.data :
{
*(.data)
*(.data.*)
*(.gnu.linkonce.d.*)
} :data
.data1 : { *(.data1) }
.eh_frame : { KEEP (*(.eh_frame)) }
.gcc_except_table : { *(.gcc_except_table) }
.ctors :
{
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
/* We don't want to include the .ctor section from
from the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE (*crtend.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
}
.dtors :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
}
.plt : { *(.plt) }
_gp = ALIGN(16) + 0x7ff0;
.got : { *(.got.plt) *(.got) }
.dynamic : { *(.dynamic) } :dynamic
/* We want the small data sections together, so single-instruction offsets
can access them all, and initialized data all before uninitialized, so
we can shorten the on-disk segment size. */
.sdata :
{
*(.sdata)
*(.sdata.*)
*(.gnu.linkonce.s.*)
}
_edata = .;
PROVIDE (edata = .);
__bss_start = .;
.sbss :
{
PROVIDE (__sbss_start = .);
PROVIDE (___sbss_start = .);
*(.dynsbss)
*(.sbss)
*(.sbss.*)
*(.gnu.linkonce.sb.*)
*(.scommon)
PROVIDE (__sbss_end = .);
PROVIDE (___sbss_end = .);
}
.bss :
{
*(.dynbss)
*(.bss)
*(.bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
/* Align here to ensure that the .bss section occupies space up to
_end. Align after .bss to ensure correct alignment even if the
.bss section disappears because there are no input sections. */
. = ALIGN(64 / 8);
}
. = ALIGN(64 / 8);
_end = .;
PROVIDE (end = .);
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info) *(.gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
/* These must appear regardless of . */
}

View File

@ -1,301 +0,0 @@
/*-
* Copyright (c) 2001, 2004, 2008, Juniper Networks, Inc.
* 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 Juniper Networks, Inc. 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 JUNIPER NETWORKS 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 JUNIPER NETWORKS 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.
*
* JNPR: ldscript.mips,v 1.3 2006/10/11 06:12:04
* $FreeBSD$
*/
OUTPUT_ARCH(mips)
ENTRY(_start)
SEARCH_DIR(/usr/lib);
SECTIONS
{
/* Read-only sections, merged into text segment: */
. = KERNLOADADDR + SIZEOF_HEADERS;
.interp : { *(.interp) }
.hash : { *(.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.gnu.version : { *(.gnu.version) }
.gnu.version_d : { *(.gnu.version_d) }
.gnu.version_r : { *(.gnu.version_r) }
.rel.init : { *(.rel.init) }
.rela.init : { *(.rela.init) }
.rel.text :
{
*(.rel.text)
*(.rel.text.*)
*(.rel.gnu.linkonce.t.*)
}
.rela.text :
{
*(.rela.text)
*(.rela.text.*)
*(.rela.gnu.linkonce.t.*)
}
.rel.fini : { *(.rel.fini) }
.rela.fini : { *(.rela.fini) }
.rel.rodata :
{
*(.rel.rodata)
*(.rel.rodata.*)
*(.rel.gnu.linkonce.r.*)
}
.rela.rodata :
{
*(.rela.rodata)
*(.rela.rodata.*)
*(.rela.gnu.linkonce.r.*)
}
.rel.data :
{
*(.rel.data)
*(.rel.data.*)
*(.rel.gnu.linkonce.d.*)
}
.rela.data :
{
*(.rela.data)
*(.rela.data.*)
*(.rela.gnu.linkonce.d.*)
}
.rel.ctors : { *(.rel.ctors) }
.rela.ctors : { *(.rela.ctors) }
.rel.dtors : { *(.rel.dtors) }
.rela.dtors : { *(.rela.dtors) }
.rel.got : { *(.rel.got) }
.rela.got : { *(.rela.got) }
.rel.sdata :
{
*(.rel.sdata)
*(.rel.sdata.*)
*(.rel.gnu.linkonce.s.*)
}
.rela.sdata :
{
*(.rela.sdata)
*(.rela.sdata.*)
*(.rela.gnu.linkonce.s.*)
}
.rel.sbss :
{
*(.rel.sbss)
*(.rel.sbss.*)
*(.rel.gnu.linkonce.sb.*)
}
.rela.sbss :
{
*(.rela.sbss)
*(.rela.sbss.*)
*(.rel.gnu.linkonce.sb.*)
}
.rel.sdata2 :
{
*(.rel.sdata2)
*(.rel.sdata2.*)
*(.rel.gnu.linkonce.s2.*)
}
.rela.sdata2 :
{
*(.rela.sdata2)
*(.rela.sdata2.*)
*(.rela.gnu.linkonce.s2.*)
}
.rel.sbss2 :
{
*(.rel.sbss2)
*(.rel.sbss2.*)
*(.rel.gnu.linkonce.sb2.*)
}
.rela.sbss2 :
{
*(.rela.sbss2)
*(.rela.sbss2.*)
*(.rela.gnu.linkonce.sb2.*)
}
.rel.bss :
{
*(.rel.bss)
*(.rel.bss.*)
*(.rel.gnu.linkonce.b.*)
}
.rela.bss :
{
*(.rela.bss)
*(.rela.bss.*)
*(.rela.gnu.linkonce.b.*)
}
.rel.plt : { *(.rel.plt) }
.rela.plt : { *(.rela.plt) }
.init :
{
KEEP (*(.init))
} =0x1000000
.text :
{
*(.trap)
*(.text)
*(.text.*)
*(.stub)
/* .gnu.warning sections are handled specially by elf64.em. */
*(.gnu.warning)
*(.gnu.linkonce.t.*)
} =0x1000000
.fini :
{
KEEP (*(.fini))
} =0x1000000
PROVIDE (__etext = .);
PROVIDE (_etext = .);
PROVIDE (etext = .);
.rodata : { *(.rodata) *(.rodata.*) *(.gnu.linkonce.r.*) }
.rodata1 : { *(.rodata1) }
.note.gnu.build-id : {
PROVIDE (__build_id_start = .);
*(.note.gnu.build-id)
PROVIDE (__build_id_end = .);
}
.reginfo : { *(.reginfo) }
.sdata2 : { *(.sdata2) *(.sdata2.*) *(.gnu.linkonce.s2.*) }
.sbss2 : { *(.sbss2) *(.sbss2.*) *(.gnu.linkonce.sb2.*) }
. = ALIGN(0x2000) + (. & (0x2000 - 1));
.data :
{
*(.data)
*(.data.*)
*(.gnu.linkonce.d.*)
}
.data1 : { *(.data1) }
.eh_frame : { KEEP (*(.eh_frame)) }
.gcc_except_table : { *(.gcc_except_table) }
.ctors :
{
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
/* We don't want to include the .ctor section from
from the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE (*crtend.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
}
.dtors :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
}
.plt : { *(.plt) }
_gp = ALIGN(16) + 0x7ff0;
.got : { *(.got.plt) *(.got) }
.dynamic : { *(.dynamic) }
/* We want the small data sections together, so single-instruction offsets
can access them all, and initialized data all before uninitialized, so
we can shorten the on-disk segment size. */
.sdata :
{
*(.sdata)
*(.sdata.*)
*(.gnu.linkonce.s.*)
}
_edata = .;
PROVIDE (edata = .);
__bss_start = .;
.sbss :
{
PROVIDE (__sbss_start = .);
PROVIDE (___sbss_start = .);
*(.dynsbss)
*(.sbss)
*(.sbss.*)
*(.gnu.linkonce.sb.*)
*(.scommon)
PROVIDE (__sbss_end = .);
PROVIDE (___sbss_end = .);
}
.bss :
{
*(.dynbss)
*(.bss)
*(.bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
/* Align here to ensure that the .bss section occupies space up to
_end. Align after .bss to ensure correct alignment even if the
.bss section disappears because there are no input sections. */
. = ALIGN(64 / 8);
}
. = ALIGN(64 / 8);
_end = .;
PROVIDE (end = .);
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info) *(.gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
/* These must appear regardless of . */
}

View File

@ -1,66 +0,0 @@
/* $FreeBSD$ */
ENTRY(_start)
PHDRS {
text PT_LOAD FLAGS(0x7);
}
SECTIONS {
. = KERNLOADADDR + SIZEOF_HEADERS;
.text : {
*(.text)
etext = .;
_etext = .;
. = ALIGN(0x2000);
} : text
. = ALIGN(0x2000);
.rodata : {
_fdata = .;
*(.rodata)
. = ALIGN(32);
}
.note.gnu.build-id : {
PROVIDE (__build_id_start = .);
*(.note.gnu.build-id)
PROVIDE (__build_id_end = .);
}
.data : {
_rwdata = .;
*(.data)
. = ALIGN(32);
}
.plt : { *(.plt) }
_gp = ALIGN(16) + 0x7ff0;
.got : { *(.got.plt) *(.got) }
.dynamic : { *(.dynamic) }
.sdata : {
_small_start = .;
*(.sdata)
. = ALIGN(32);
edata = .;
_edata = .;
} : text
.sbss : {
__bss_start = .;
_fbss = .;
*(.sbss) *(.scommon)
_small_end = .;
. = ALIGN(32);
}
.bss : {
*(.bss)
*(COMMON)
. = ALIGN(32);
_end = .;
end = .;
}
}

View File

@ -1,537 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@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 unmodified, this list of conditions, and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/interrupt.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/rman.h>
#include <sys/malloc.h>
#include <sys/pcpu.h>
#include <sys/proc.h>
#include <sys/pmc.h>
#include <sys/pmckern.h>
#include <machine/bus.h>
#include <machine/intr_machdep.h>
#include <mips/atheros/apbvar.h>
#include <mips/atheros/ar71xxreg.h>
#include <mips/atheros/ar71xx_setup.h>
#define APB_INTR_PMC 5
#undef APB_DEBUG
#ifdef APB_DEBUG
#define dprintf printf
#else
#define dprintf(x, arg...)
#endif /* APB_DEBUG */
#define DEVTOAPB(dev) ((struct apb_ivar *) device_get_ivars(dev))
static int apb_activate_resource(device_t, device_t, int, int,
struct resource *);
static device_t apb_add_child(device_t, u_int, const char *, int);
static struct resource *
apb_alloc_resource(device_t, device_t, int, int *, rman_res_t,
rman_res_t, rman_res_t, u_int);
static int apb_attach(device_t);
static int apb_deactivate_resource(device_t, device_t, int, int,
struct resource *);
static struct resource_list *
apb_get_resource_list(device_t, device_t);
static void apb_hinted_child(device_t, const char *, int);
static int apb_filter(void *);
static int apb_probe(device_t);
static int apb_release_resource(device_t, device_t, int, int,
struct resource *);
static int apb_setup_intr(device_t, device_t, struct resource *, int,
driver_filter_t *, driver_intr_t *, void *, void **);
static int apb_teardown_intr(device_t, device_t, struct resource *,
void *);
static void
apb_mask_irq(void *source)
{
unsigned int irq = (unsigned int)source;
uint32_t reg;
reg = ATH_READ_REG(AR71XX_MISC_INTR_MASK);
ATH_WRITE_REG(AR71XX_MISC_INTR_MASK, reg & ~(1 << irq));
}
static void
apb_unmask_irq(void *source)
{
uint32_t reg;
unsigned int irq = (unsigned int)source;
reg = ATH_READ_REG(AR71XX_MISC_INTR_MASK);
ATH_WRITE_REG(AR71XX_MISC_INTR_MASK, reg | (1 << irq));
}
static int
apb_probe(device_t dev)
{
return (BUS_PROBE_NOWILDCARD);
}
static int
apb_attach(device_t dev)
{
struct apb_softc *sc = device_get_softc(dev);
int rid = 0;
device_set_desc(dev, "APB Bus bridge");
sc->apb_mem_rman.rm_type = RMAN_ARRAY;
sc->apb_mem_rman.rm_descr = "APB memory window";
if (rman_init(&sc->apb_mem_rman) != 0 ||
rman_manage_region(&sc->apb_mem_rman,
AR71XX_APB_BASE,
AR71XX_APB_BASE + AR71XX_APB_SIZE - 1) != 0)
panic("apb_attach: failed to set up memory rman");
sc->apb_irq_rman.rm_type = RMAN_ARRAY;
sc->apb_irq_rman.rm_descr = "APB IRQ";
if (rman_init(&sc->apb_irq_rman) != 0 ||
rman_manage_region(&sc->apb_irq_rman,
APB_IRQ_BASE, APB_IRQ_END) != 0)
panic("apb_attach: failed to set up IRQ rman");
if ((sc->sc_misc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
RF_SHAREABLE | RF_ACTIVE)) == NULL) {
device_printf(dev, "unable to allocate IRQ resource\n");
return (ENXIO);
}
if ((bus_setup_intr(dev, sc->sc_misc_irq, INTR_TYPE_MISC,
apb_filter, NULL, sc, &sc->sc_misc_ih))) {
device_printf(dev,
"WARNING: unable to register interrupt handler\n");
return (ENXIO);
}
bus_generic_probe(dev);
bus_enumerate_hinted_children(dev);
bus_generic_attach(dev);
/*
* Unmask performance counter IRQ
*/
apb_unmask_irq((void*)APB_INTR_PMC);
sc->sc_intr_counter[APB_INTR_PMC] = mips_intrcnt_create("apb irq5: pmc");
return (0);
}
static struct resource *
apb_alloc_resource(device_t bus, device_t child, int type, int *rid,
rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
{
struct apb_softc *sc = device_get_softc(bus);
struct apb_ivar *ivar = device_get_ivars(child);
struct resource *rv;
struct resource_list_entry *rle;
struct rman *rm;
int isdefault, needactivate, passthrough;
isdefault = (RMAN_IS_DEFAULT_RANGE(start, end));
needactivate = flags & RF_ACTIVE;
/*
* Pass memory requests to nexus device
*/
passthrough = (device_get_parent(child) != bus);
rle = NULL;
dprintf("%s: entry (%p, %p, %d, %d, %p, %p, %jd, %d)\n",
__func__, bus, child, type, *rid, (void *)(intptr_t)start,
(void *)(intptr_t)end, count, flags);
if (passthrough)
return (BUS_ALLOC_RESOURCE(device_get_parent(bus), child, type,
rid, start, end, count, flags));
/*
* If this is an allocation of the "default" range for a given RID,
* and we know what the resources for this device are (ie. they aren't
* maintained by a child bus), then work out the start/end values.
*/
if (isdefault) {
rle = resource_list_find(&ivar->resources, type, *rid);
if (rle == NULL) {
return (NULL);
}
if (rle->res != NULL) {
panic("%s: resource entry is busy", __func__);
}
start = rle->start;
end = rle->end;
count = rle->count;
dprintf("%s: default resource (%p, %p, %ld)\n",
__func__, (void *)(intptr_t)start,
(void *)(intptr_t)end, count);
}
switch (type) {
case SYS_RES_IRQ:
rm = &sc->apb_irq_rman;
break;
case SYS_RES_MEMORY:
rm = &sc->apb_mem_rman;
break;
default:
printf("%s: unknown resource type %d\n", __func__, type);
return (0);
}
rv = rman_reserve_resource(rm, start, end, count, flags, child);
if (rv == NULL) {
printf("%s: could not reserve resource\n", __func__);
return (0);
}
rman_set_rid(rv, *rid);
if (needactivate) {
if (bus_activate_resource(child, type, *rid, rv)) {
printf("%s: could not activate resource\n", __func__);
rman_release_resource(rv);
return (0);
}
}
return (rv);
}
static int
apb_activate_resource(device_t bus, device_t child, int type, int rid,
struct resource *r)
{
/* XXX: should we mask/unmask IRQ here? */
return (BUS_ACTIVATE_RESOURCE(device_get_parent(bus), child,
type, rid, r));
}
static int
apb_deactivate_resource(device_t bus, device_t child, int type, int rid,
struct resource *r)
{
/* XXX: should we mask/unmask IRQ here? */
return (BUS_DEACTIVATE_RESOURCE(device_get_parent(bus), child,
type, rid, r));
}
static int
apb_release_resource(device_t dev, device_t child, int type,
int rid, struct resource *r)
{
struct resource_list *rl;
struct resource_list_entry *rle;
rl = apb_get_resource_list(dev, child);
if (rl == NULL)
return (EINVAL);
rle = resource_list_find(rl, type, rid);
if (rle == NULL)
return (EINVAL);
rman_release_resource(r);
rle->res = NULL;
return (0);
}
static int
apb_setup_intr(device_t bus, device_t child, struct resource *ires,
int flags, driver_filter_t *filt, driver_intr_t *handler,
void *arg, void **cookiep)
{
struct apb_softc *sc = device_get_softc(bus);
struct intr_event *event;
int irq, error;
irq = rman_get_start(ires);
if (irq > APB_IRQ_END)
panic("%s: bad irq %d", __func__, irq);
event = sc->sc_eventstab[irq];
if (event == NULL) {
error = intr_event_create(&event, (void *)irq, 0, irq,
apb_mask_irq, apb_unmask_irq,
NULL, NULL,
"apb intr%d:", irq);
if (error == 0) {
sc->sc_eventstab[irq] = event;
sc->sc_intr_counter[irq] =
mips_intrcnt_create(event->ie_name);
}
else
return (error);
}
intr_event_add_handler(event, device_get_nameunit(child), filt,
handler, arg, intr_priority(flags), flags, cookiep);
mips_intrcnt_setname(sc->sc_intr_counter[irq], event->ie_fullname);
apb_unmask_irq((void*)irq);
return (0);
}
static int
apb_teardown_intr(device_t dev, device_t child, struct resource *ires,
void *cookie)
{
struct apb_softc *sc = device_get_softc(dev);
int irq, result;
irq = rman_get_start(ires);
if (irq > APB_IRQ_END)
panic("%s: bad irq %d", __func__, irq);
if (sc->sc_eventstab[irq] == NULL)
panic("Trying to teardown unoccupied IRQ");
apb_mask_irq((void*)irq);
result = intr_event_remove_handler(cookie);
if (!result)
sc->sc_eventstab[irq] = NULL;
return (result);
}
static int
apb_filter(void *arg)
{
struct apb_softc *sc = arg;
struct intr_event *event;
uint32_t reg, irq;
struct thread *td;
struct trapframe *tf;
reg = ATH_READ_REG(AR71XX_MISC_INTR_STATUS);
for (irq = 0; irq < APB_NIRQS; irq++) {
if (reg & (1 << irq)) {
switch (ar71xx_soc) {
case AR71XX_SOC_AR7240:
case AR71XX_SOC_AR7241:
case AR71XX_SOC_AR7242:
case AR71XX_SOC_AR9330:
case AR71XX_SOC_AR9331:
case AR71XX_SOC_AR9341:
case AR71XX_SOC_AR9342:
case AR71XX_SOC_AR9344:
case AR71XX_SOC_QCA9533:
case AR71XX_SOC_QCA9533_V2:
case AR71XX_SOC_QCA9556:
case AR71XX_SOC_QCA9558:
/* ACK/clear the given interrupt */
ATH_WRITE_REG(AR71XX_MISC_INTR_STATUS,
(1 << irq));
break;
default:
/* fallthrough */
break;
}
event = sc->sc_eventstab[irq];
/* always count interrupts; spurious or otherwise */
mips_intrcnt_inc(sc->sc_intr_counter[irq]);
if (!event || CK_SLIST_EMPTY(&event->ie_handlers)) {
if (irq == APB_INTR_PMC) {
td = PCPU_GET(curthread);
tf = td->td_intr_frame;
if (pmc_intr)
(*pmc_intr)(tf);
continue;
}
/* Ignore timer interrupts */
if (irq != 0 && irq != 8 && irq != 9 && irq != 10)
printf("Stray APB IRQ %d\n", irq);
continue;
}
intr_event_handle(event, PCPU_GET(curthread)->td_intr_frame);
}
}
return (FILTER_HANDLED);
}
static void
apb_hinted_child(device_t bus, const char *dname, int dunit)
{
device_t child;
long maddr;
int msize;
int irq;
int result;
int mem_hints_count;
child = BUS_ADD_CHILD(bus, 0, dname, dunit);
/*
* Set hard-wired resources for hinted child using
* specific RIDs.
*/
mem_hints_count = 0;
if (resource_long_value(dname, dunit, "maddr", &maddr) == 0)
mem_hints_count++;
if (resource_int_value(dname, dunit, "msize", &msize) == 0)
mem_hints_count++;
/* check if all info for mem resource has been provided */
if ((mem_hints_count > 0) && (mem_hints_count < 2)) {
printf("Either maddr or msize hint is missing for %s%d\n",
dname, dunit);
} else if (mem_hints_count) {
result = bus_set_resource(child, SYS_RES_MEMORY, 0,
maddr, msize);
if (result != 0)
device_printf(bus,
"warning: bus_set_resource() failed\n");
}
if (resource_int_value(dname, dunit, "irq", &irq) == 0) {
result = bus_set_resource(child, SYS_RES_IRQ, 0, irq, 1);
if (result != 0)
device_printf(bus,
"warning: bus_set_resource() failed\n");
}
}
static device_t
apb_add_child(device_t bus, u_int order, const char *name, int unit)
{
device_t child;
struct apb_ivar *ivar;
ivar = malloc(sizeof(struct apb_ivar), M_DEVBUF, M_WAITOK | M_ZERO);
resource_list_init(&ivar->resources);
child = device_add_child_ordered(bus, order, name, unit);
if (child == NULL) {
printf("Can't add child %s%d ordered\n", name, unit);
return (0);
}
device_set_ivars(child, ivar);
return (child);
}
/*
* Helper routine for bus_generic_rl_get_resource/bus_generic_rl_set_resource
* Provides pointer to resource_list for these routines
*/
static struct resource_list *
apb_get_resource_list(device_t dev, device_t child)
{
struct apb_ivar *ivar;
ivar = device_get_ivars(child);
return (&(ivar->resources));
}
static int
apb_print_all_resources(device_t dev)
{
struct apb_ivar *ndev = DEVTOAPB(dev);
struct resource_list *rl = &ndev->resources;
int retval = 0;
if (STAILQ_FIRST(rl))
retval += printf(" at");
retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#jx");
retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%jd");
return (retval);
}
static int
apb_print_child(device_t bus, device_t child)
{
int retval = 0;
retval += bus_print_child_header(bus, child);
retval += apb_print_all_resources(child);
if (device_get_flags(child))
retval += printf(" flags %#x", device_get_flags(child));
retval += printf(" on %s\n", device_get_nameunit(bus));
return (retval);
}
static device_method_t apb_methods[] = {
DEVMETHOD(bus_activate_resource, apb_activate_resource),
DEVMETHOD(bus_add_child, apb_add_child),
DEVMETHOD(bus_alloc_resource, apb_alloc_resource),
DEVMETHOD(bus_deactivate_resource, apb_deactivate_resource),
DEVMETHOD(bus_get_resource_list, apb_get_resource_list),
DEVMETHOD(bus_hinted_child, apb_hinted_child),
DEVMETHOD(bus_release_resource, apb_release_resource),
DEVMETHOD(bus_setup_intr, apb_setup_intr),
DEVMETHOD(bus_teardown_intr, apb_teardown_intr),
DEVMETHOD(device_attach, apb_attach),
DEVMETHOD(device_probe, apb_probe),
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
DEVMETHOD(bus_print_child, apb_print_child),
DEVMETHOD_END
};
static driver_t apb_driver = {
"apb",
apb_methods,
sizeof(struct apb_softc),
};
static devclass_t apb_devclass;
DRIVER_MODULE(apb, nexus, apb_driver, apb_devclass, 0, 0);

View File

@ -1,54 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@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 unmodified, this list of conditions, and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef _APBVAR_H_
#define _APBVAR_H_
#define APB_IRQ_BASE 0
#define APB_IRQ_END 31
#define APB_NIRQS 32
struct apb_softc {
struct rman apb_irq_rman;
struct rman apb_mem_rman;
/* IRQ events structs for child devices */
struct intr_event *sc_eventstab[APB_NIRQS];
mips_intrcnt_t sc_intr_counter[APB_NIRQS];
/* Resources and cookies for MIPS CPU INTs */
struct resource *sc_misc_irq;
void *sc_misc_ih;
};
struct apb_ivar {
struct resource_list resources;
};
#endif /* _APBVAR_H_ */

View File

@ -1,753 +0,0 @@
/*-
* Copyright (c) 2016, Hiroki Mori
* Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@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 unmodified, this list of conditions, and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "opt_platform.h"
#include "opt_ar531x.h"
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/interrupt.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/rman.h>
#include <sys/malloc.h>
#include <sys/pcpu.h>
#include <sys/proc.h>
#include <sys/pmc.h>
#include <sys/pmckern.h>
#include <machine/bus.h>
#ifdef INTRNG
#include <machine/intr.h>
#else
#include <machine/intr_machdep.h>
#endif
#ifdef INTRNG
#include "pic_if.h"
#define PIC_INTR_ISRC(sc, irq) (&(sc)->pic_irqs[(irq)].isrc)
#endif
#include <mips/atheros/ar531x/apbvar.h>
#include <mips/atheros/ar531x/ar5315reg.h>
#include <mips/atheros/ar531x/ar5312reg.h>
#include <mips/atheros/ar531x/ar5315_setup.h>
#ifdef AR531X_APB_DEBUG
#define dprintf printf
#else
#define dprintf(x, arg...)
#endif /* AR531X_APB_DEBUG */
static int apb_activate_resource(device_t, device_t, int, int,
struct resource *);
static device_t apb_add_child(device_t, u_int, const char *, int);
static struct resource *
apb_alloc_resource(device_t, device_t, int, int *, rman_res_t,
rman_res_t, rman_res_t, u_int);
static int apb_attach(device_t);
static int apb_deactivate_resource(device_t, device_t, int, int,
struct resource *);
static struct resource_list *
apb_get_resource_list(device_t, device_t);
static void apb_hinted_child(device_t, const char *, int);
static int apb_filter(void *);
static int apb_probe(device_t);
static int apb_release_resource(device_t, device_t, int, int,
struct resource *);
#ifndef INTRNG
static int apb_setup_intr(device_t, device_t, struct resource *, int,
driver_filter_t *, driver_intr_t *, void *, void **);
static int apb_teardown_intr(device_t, device_t, struct resource *,
void *);
#endif
static void
apb_mask_irq(void *source)
{
unsigned int irq = (unsigned int)source;
uint32_t reg;
if(ar531x_soc >= AR531X_SOC_AR5315) {
reg = ATH_READ_REG(AR5315_SYSREG_BASE +
AR5315_SYSREG_MISC_INTMASK);
ATH_WRITE_REG(AR5315_SYSREG_BASE
+ AR5315_SYSREG_MISC_INTMASK, reg & ~(1 << irq));
} else {
reg = ATH_READ_REG(AR5312_SYSREG_BASE +
AR5312_SYSREG_MISC_INTMASK);
ATH_WRITE_REG(AR5312_SYSREG_BASE
+ AR5312_SYSREG_MISC_INTMASK, reg & ~(1 << irq));
}
}
static void
apb_unmask_irq(void *source)
{
uint32_t reg;
unsigned int irq = (unsigned int)source;
if(ar531x_soc >= AR531X_SOC_AR5315) {
reg = ATH_READ_REG(AR5315_SYSREG_BASE +
AR5315_SYSREG_MISC_INTMASK);
ATH_WRITE_REG(AR5315_SYSREG_BASE +
AR5315_SYSREG_MISC_INTMASK, reg | (1 << irq));
} else {
reg = ATH_READ_REG(AR5312_SYSREG_BASE +
AR5312_SYSREG_MISC_INTMASK);
ATH_WRITE_REG(AR5312_SYSREG_BASE +
AR5312_SYSREG_MISC_INTMASK, reg | (1 << irq));
}
}
#ifdef INTRNG
static int
apb_pic_register_isrcs(struct apb_softc *sc)
{
int error;
uint32_t irq;
struct intr_irqsrc *isrc;
const char *name;
name = device_get_nameunit(sc->apb_dev);
for (irq = 0; irq < APB_NIRQS; irq++) {
sc->pic_irqs[irq].irq = irq;
isrc = PIC_INTR_ISRC(sc, irq);
error = intr_isrc_register(isrc, sc->apb_dev, 0, "%s", name);
if (error != 0) {
/* XXX call intr_isrc_deregister */
device_printf(sc->apb_dev, "%s failed", __func__);
return (error);
}
}
return (0);
}
static inline intptr_t
pic_xref(device_t dev)
{
return (0);
}
#endif
static int
apb_probe(device_t dev)
{
#ifdef INTRNG
device_set_desc(dev, "APB Bus bridge INTRNG");
#else
device_set_desc(dev, "APB Bus bridge");
#endif
return (0);
}
static int
apb_attach(device_t dev)
{
struct apb_softc *sc = device_get_softc(dev);
#ifdef INTRNG
intptr_t xref = pic_xref(dev);
int miscirq;
#else
int rid = 0;
#endif
sc->apb_dev = dev;
sc->apb_mem_rman.rm_type = RMAN_ARRAY;
sc->apb_mem_rman.rm_descr = "APB memory window";
if(ar531x_soc >= AR531X_SOC_AR5315) {
if (rman_init(&sc->apb_mem_rman) != 0 ||
rman_manage_region(&sc->apb_mem_rman,
AR5315_APB_BASE,
AR5315_APB_BASE + AR5315_APB_SIZE - 1) != 0)
panic("apb_attach: failed to set up memory rman");
} else {
if (rman_init(&sc->apb_mem_rman) != 0 ||
rman_manage_region(&sc->apb_mem_rman,
AR5312_APB_BASE,
AR5312_APB_BASE + AR5312_APB_SIZE - 1) != 0)
panic("apb_attach: failed to set up memory rman");
}
sc->apb_irq_rman.rm_type = RMAN_ARRAY;
sc->apb_irq_rman.rm_descr = "APB IRQ";
if (rman_init(&sc->apb_irq_rman) != 0 ||
rman_manage_region(&sc->apb_irq_rman,
APB_IRQ_BASE, APB_IRQ_END) != 0)
panic("apb_attach: failed to set up IRQ rman");
#ifndef INTRNG
if ((sc->sc_misc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
RF_SHAREABLE | RF_ACTIVE)) == NULL) {
device_printf(dev, "unable to allocate IRQ resource\n");
return (ENXIO);
}
if ((bus_setup_intr(dev, sc->sc_misc_irq, INTR_TYPE_MISC,
apb_filter, NULL, sc, &sc->sc_misc_ih))) {
device_printf(dev,
"WARNING: unable to register interrupt handler\n");
return (ENXIO);
}
#else
/* Register the interrupts */
if (apb_pic_register_isrcs(sc) != 0) {
device_printf(dev, "could not register PIC ISRCs\n");
return (ENXIO);
}
/*
* Now, when everything is initialized, it's right time to
* register interrupt controller to interrupt framefork.
*/
if (intr_pic_register(dev, xref) == NULL) {
device_printf(dev, "could not register PIC\n");
return (ENXIO);
}
if(ar531x_soc >= AR531X_SOC_AR5315) {
miscirq = AR5315_CPU_IRQ_MISC;
} else {
miscirq = AR5312_IRQ_MISC;
}
cpu_establish_hardintr("aric", apb_filter, NULL, sc, miscirq,
INTR_TYPE_MISC, NULL);
#endif
/* mask all misc interrupt */
if(ar531x_soc >= AR531X_SOC_AR5315) {
ATH_WRITE_REG(AR5315_SYSREG_BASE
+ AR5315_SYSREG_MISC_INTMASK, 0);
} else {
ATH_WRITE_REG(AR5312_SYSREG_BASE
+ AR5312_SYSREG_MISC_INTMASK, 0);
}
bus_generic_probe(dev);
bus_enumerate_hinted_children(dev);
bus_generic_attach(dev);
return (0);
}
static struct resource *
apb_alloc_resource(device_t bus, device_t child, int type, int *rid,
rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
{
struct apb_softc *sc = device_get_softc(bus);
struct apb_ivar *ivar = device_get_ivars(child);
struct resource *rv;
struct resource_list_entry *rle;
struct rman *rm;
int isdefault, needactivate, passthrough;
isdefault = (RMAN_IS_DEFAULT_RANGE(start, end));
needactivate = flags & RF_ACTIVE;
/*
* Pass memory requests to nexus device
*/
passthrough = (device_get_parent(child) != bus);
rle = NULL;
dprintf("%s: entry (%p, %p, %d, %d, %p, %p, %jd, %d)\n",
__func__, bus, child, type, *rid, (void *)(intptr_t)start,
(void *)(intptr_t)end, count, flags);
if (passthrough)
return (BUS_ALLOC_RESOURCE(device_get_parent(bus), child, type,
rid, start, end, count, flags));
/*
* If this is an allocation of the "default" range for a given RID,
* and we know what the resources for this device are (ie. they aren't
* maintained by a child bus), then work out the start/end values.
*/
if (isdefault) {
rle = resource_list_find(&ivar->resources, type, *rid);
if (rle == NULL) {
return (NULL);
}
if (rle->res != NULL) {
panic("%s: resource entry is busy", __func__);
}
start = rle->start;
end = rle->end;
count = rle->count;
dprintf("%s: default resource (%p, %p, %jd)\n",
__func__, (void *)(intptr_t)start,
(void *)(intptr_t)end, count);
}
switch (type) {
case SYS_RES_IRQ:
rm = &sc->apb_irq_rman;
break;
case SYS_RES_MEMORY:
rm = &sc->apb_mem_rman;
break;
default:
printf("%s: unknown resource type %d\n", __func__, type);
return (0);
}
rv = rman_reserve_resource(rm, start, end, count, flags, child);
if (rv == NULL) {
printf("%s: could not reserve resource %d\n", __func__, type);
return (0);
}
rman_set_rid(rv, *rid);
if (needactivate) {
if (bus_activate_resource(child, type, *rid, rv)) {
printf("%s: could not activate resource\n", __func__);
rman_release_resource(rv);
return (0);
}
}
return (rv);
}
static int
apb_activate_resource(device_t bus, device_t child, int type, int rid,
struct resource *r)
{
/* XXX: should we mask/unmask IRQ here? */
return (BUS_ACTIVATE_RESOURCE(device_get_parent(bus), child,
type, rid, r));
}
static int
apb_deactivate_resource(device_t bus, device_t child, int type, int rid,
struct resource *r)
{
/* XXX: should we mask/unmask IRQ here? */
return (BUS_DEACTIVATE_RESOURCE(device_get_parent(bus), child,
type, rid, r));
}
static int
apb_release_resource(device_t dev, device_t child, int type,
int rid, struct resource *r)
{
struct resource_list *rl;
struct resource_list_entry *rle;
rl = apb_get_resource_list(dev, child);
if (rl == NULL)
return (EINVAL);
rle = resource_list_find(rl, type, rid);
if (rle == NULL)
return (EINVAL);
rman_release_resource(r);
rle->res = NULL;
return (0);
}
static int
apb_setup_intr(device_t bus, device_t child, struct resource *ires,
int flags, driver_filter_t *filt, driver_intr_t *handler,
void *arg, void **cookiep)
{
struct apb_softc *sc = device_get_softc(bus);
int error;
int irq;
#ifndef INTRNG
struct intr_event *event;
#endif
#ifdef INTRNG
struct intr_irqsrc *isrc;
const char *name;
if ((rman_get_flags(ires) & RF_SHAREABLE) == 0)
flags |= INTR_EXCL;
irq = rman_get_start(ires);
isrc = PIC_INTR_ISRC(sc, irq);
if(isrc->isrc_event == 0) {
error = intr_event_create(&isrc->isrc_event, (void *)irq,
0, irq, apb_mask_irq, apb_unmask_irq,
NULL, NULL, "apb intr%d:", irq);
if(error != 0)
return(error);
}
name = device_get_nameunit(child);
error = intr_event_add_handler(isrc->isrc_event, name, filt, handler,
arg, intr_priority(flags), flags, cookiep);
return(error);
#else
irq = rman_get_start(ires);
if (irq > APB_IRQ_END)
panic("%s: bad irq %d", __func__, irq);
event = sc->sc_eventstab[irq];
if (event == NULL) {
error = intr_event_create(&event, (void *)irq, 0, irq,
apb_mask_irq, apb_unmask_irq,
NULL, NULL,
"apb intr%d:", irq);
if (error == 0) {
sc->sc_eventstab[irq] = event;
sc->sc_intr_counter[irq] =
mips_intrcnt_create(event->ie_name);
}
else
return (error);
}
intr_event_add_handler(event, device_get_nameunit(child), filt,
handler, arg, intr_priority(flags), flags, cookiep);
mips_intrcnt_setname(sc->sc_intr_counter[irq], event->ie_fullname);
apb_unmask_irq((void*)irq);
return (0);
#endif
}
#ifndef INTRNG
static int
apb_teardown_intr(device_t dev, device_t child, struct resource *ires,
void *cookie)
{
#ifdef INTRNG
return (intr_teardown_irq(child, ires, cookie));
#else
struct apb_softc *sc = device_get_softc(dev);
int irq, result;
irq = rman_get_start(ires);
if (irq > APB_IRQ_END)
panic("%s: bad irq %d", __func__, irq);
if (sc->sc_eventstab[irq] == NULL)
panic("Trying to teardown unoccupied IRQ");
apb_mask_irq((void*)irq);
result = intr_event_remove_handler(cookie);
if (!result)
sc->sc_eventstab[irq] = NULL;
return (result);
#endif
}
static int
apb_filter(void *arg)
{
struct apb_softc *sc = arg;
struct intr_event *event;
uint32_t reg, irq;
if(ar531x_soc >= AR531X_SOC_AR5315)
reg = ATH_READ_REG(AR5315_SYSREG_BASE +
AR5315_SYSREG_MISC_INTSTAT);
else
reg = ATH_READ_REG(AR5312_SYSREG_BASE +
AR5312_SYSREG_MISC_INTSTAT);
for (irq = 0; irq < APB_NIRQS; irq++) {
if (reg & (1 << irq)) {
if(ar531x_soc >= AR531X_SOC_AR5315) {
ATH_WRITE_REG(AR5315_SYSREG_BASE +
AR5315_SYSREG_MISC_INTSTAT,
reg & ~(1 << irq));
} else {
ATH_WRITE_REG(AR5312_SYSREG_BASE +
AR5312_SYSREG_MISC_INTSTAT,
reg & ~(1 << irq));
}
event = sc->sc_eventstab[irq];
if (!event || CK_SLIST_EMPTY(&event->ie_handlers)) {
if(irq == 1 && ar531x_soc < AR531X_SOC_AR5315) {
ATH_READ_REG(AR5312_SYSREG_BASE +
AR5312_SYSREG_AHBPERR);
ATH_READ_REG(AR5312_SYSREG_BASE +
AR5312_SYSREG_AHBDMAE);
}
/* Ignore non handle interrupts */
if (irq != 0 && irq != 6)
printf("Stray APB IRQ %d\n", irq);
continue;
}
intr_event_handle(event, PCPU_GET(curthread)->td_intr_frame);
mips_intrcnt_inc(sc->sc_intr_counter[irq]);
}
}
return (FILTER_HANDLED);
}
#else
static int
apb_filter(void *arg)
{
struct apb_softc *sc = arg;
struct thread *td;
uint32_t i, intr;
td = curthread;
/* Workaround: do not inflate intr nesting level */
td->td_intr_nesting_level--;
if(ar531x_soc >= AR531X_SOC_AR5315)
intr = ATH_READ_REG(AR5315_SYSREG_BASE +
AR5315_SYSREG_MISC_INTSTAT);
else
intr = ATH_READ_REG(AR5312_SYSREG_BASE +
AR5312_SYSREG_MISC_INTSTAT);
while ((i = fls(intr)) != 0) {
i--;
intr &= ~(1u << i);
if(i == 1 && ar531x_soc < AR531X_SOC_AR5315) {
ATH_READ_REG(AR5312_SYSREG_BASE +
AR5312_SYSREG_AHBPERR);
ATH_READ_REG(AR5312_SYSREG_BASE +
AR5312_SYSREG_AHBDMAE);
}
if (intr_isrc_dispatch(PIC_INTR_ISRC(sc, i),
curthread->td_intr_frame) != 0) {
device_printf(sc->apb_dev,
"Stray interrupt %u detected\n", i);
apb_mask_irq((void*)i);
continue;
}
}
KASSERT(i == 0, ("all interrupts handled"));
td->td_intr_nesting_level++;
return (FILTER_HANDLED);
}
#endif
static void
apb_hinted_child(device_t bus, const char *dname, int dunit)
{
device_t child;
long maddr;
int msize;
int irq;
int result;
int mem_hints_count;
child = BUS_ADD_CHILD(bus, 0, dname, dunit);
/*
* Set hard-wired resources for hinted child using
* specific RIDs.
*/
mem_hints_count = 0;
if (resource_long_value(dname, dunit, "maddr", &maddr) == 0)
mem_hints_count++;
if (resource_int_value(dname, dunit, "msize", &msize) == 0)
mem_hints_count++;
/* check if all info for mem resource has been provided */
if ((mem_hints_count > 0) && (mem_hints_count < 2)) {
printf("Either maddr or msize hint is missing for %s%d\n",
dname, dunit);
} else if (mem_hints_count) {
result = bus_set_resource(child, SYS_RES_MEMORY, 0,
maddr, msize);
if (result != 0)
device_printf(bus,
"warning: bus_set_resource() failed\n");
}
if (resource_int_value(dname, dunit, "irq", &irq) == 0) {
result = bus_set_resource(child, SYS_RES_IRQ, 0, irq, 1);
if (result != 0)
device_printf(bus,
"warning: bus_set_resource() failed\n");
}
}
static device_t
apb_add_child(device_t bus, u_int order, const char *name, int unit)
{
device_t child;
struct apb_ivar *ivar;
ivar = malloc(sizeof(struct apb_ivar), M_DEVBUF, M_WAITOK | M_ZERO);
if (ivar == NULL) {
printf("Failed to allocate ivar\n");
return (0);
}
resource_list_init(&ivar->resources);
child = device_add_child_ordered(bus, order, name, unit);
if (child == NULL) {
printf("Can't add child %s%d ordered\n", name, unit);
return (0);
}
device_set_ivars(child, ivar);
return (child);
}
/*
* Helper routine for bus_generic_rl_get_resource/bus_generic_rl_set_resource
* Provides pointer to resource_list for these routines
*/
static struct resource_list *
apb_get_resource_list(device_t dev, device_t child)
{
struct apb_ivar *ivar;
ivar = device_get_ivars(child);
return (&(ivar->resources));
}
#ifdef INTRNG
static void
apb_pic_enable_intr(device_t dev, struct intr_irqsrc *isrc)
{
u_int irq;
irq = ((struct apb_pic_irqsrc *)isrc)->irq;
apb_unmask_irq((void*)irq);
}
static void
apb_pic_disable_intr(device_t dev, struct intr_irqsrc *isrc)
{
u_int irq;
irq = ((struct apb_pic_irqsrc *)isrc)->irq;
apb_mask_irq((void*)irq);
}
static void
apb_pic_pre_ithread(device_t dev, struct intr_irqsrc *isrc)
{
apb_pic_disable_intr(dev, isrc);
}
static void
apb_pic_post_ithread(device_t dev, struct intr_irqsrc *isrc)
{
apb_pic_enable_intr(dev, isrc);
}
static void
apb_pic_post_filter(device_t dev, struct intr_irqsrc *isrc)
{
uint32_t reg, irq;
irq = ((struct apb_pic_irqsrc *)isrc)->irq;
if(ar531x_soc >= AR531X_SOC_AR5315) {
reg = ATH_READ_REG(AR5315_SYSREG_BASE +
AR5315_SYSREG_MISC_INTSTAT);
ATH_WRITE_REG(AR5315_SYSREG_BASE + AR5315_SYSREG_MISC_INTSTAT,
reg & ~(1 << irq));
} else {
reg = ATH_READ_REG(AR5312_SYSREG_BASE +
AR5312_SYSREG_MISC_INTSTAT);
ATH_WRITE_REG(AR5312_SYSREG_BASE + AR5312_SYSREG_MISC_INTSTAT,
reg & ~(1 << irq));
}
}
static int
apb_pic_map_intr(device_t dev, struct intr_map_data *data,
struct intr_irqsrc **isrcp)
{
return (ENOTSUP);
}
#endif
static device_method_t apb_methods[] = {
DEVMETHOD(bus_activate_resource, apb_activate_resource),
DEVMETHOD(bus_add_child, apb_add_child),
DEVMETHOD(bus_alloc_resource, apb_alloc_resource),
DEVMETHOD(bus_deactivate_resource, apb_deactivate_resource),
DEVMETHOD(bus_get_resource_list, apb_get_resource_list),
DEVMETHOD(bus_hinted_child, apb_hinted_child),
DEVMETHOD(bus_release_resource, apb_release_resource),
DEVMETHOD(device_attach, apb_attach),
DEVMETHOD(device_probe, apb_probe),
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
#ifdef INTRNG
DEVMETHOD(pic_disable_intr, apb_pic_disable_intr),
DEVMETHOD(pic_enable_intr, apb_pic_enable_intr),
DEVMETHOD(pic_map_intr, apb_pic_map_intr),
DEVMETHOD(pic_post_filter, apb_pic_post_filter),
DEVMETHOD(pic_post_ithread, apb_pic_post_ithread),
DEVMETHOD(pic_pre_ithread, apb_pic_pre_ithread),
// DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
#else
DEVMETHOD(bus_teardown_intr, apb_teardown_intr),
#endif
DEVMETHOD(bus_setup_intr, apb_setup_intr),
DEVMETHOD_END
};
static driver_t apb_driver = {
"apb",
apb_methods,
sizeof(struct apb_softc),
};
static devclass_t apb_devclass;
EARLY_DRIVER_MODULE(apb, nexus, apb_driver, apb_devclass, 0, 0,
BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);

View File

@ -1,63 +0,0 @@
/*-
* Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@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 unmodified, this list of conditions, and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef _APBVAR_H_
#define _APBVAR_H_
#define APB_IRQ_BASE 0
#define APB_IRQ_END 31
#define APB_NIRQS 32
struct apb_pic_irqsrc {
struct intr_irqsrc isrc;
u_int irq;
};
struct apb_softc {
device_t apb_dev;
struct rman apb_irq_rman;
struct rman apb_mem_rman;
/* IRQ events structs for child devices */
struct intr_event *sc_eventstab[APB_NIRQS];
#ifndef INTRNG
mips_intrcnt_t sc_intr_counter[APB_NIRQS];
#endif
/* Resources and cookies for MIPS CPU INTs */
struct resource *sc_misc_irq;
void *sc_misc_ih;
#ifdef INTRNG
struct apb_pic_irqsrc pic_irqs[APB_NIRQS];
#endif
};
struct apb_ivar {
struct resource_list resources;
};
#endif /* _APBVAR_H_ */

View File

@ -1,208 +0,0 @@
/*-
* Copyright (c) 2016 Hiroki Mori
* Copyright (c) 2010 Adrian Chadd
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_ddb.h"
#include <sys/param.h>
#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/cons.h>
#include <sys/kdb.h>
#include <sys/reboot.h>
#include <vm/vm.h>
#include <vm/vm_page.h>
#include <net/ethernet.h>
#include <machine/clock.h>
#include <machine/cpu.h>
#include <machine/cpuregs.h>
#include <machine/hwfunc.h>
#include <machine/md_var.h>
#include <machine/trap.h>
#include <machine/vmparam.h>
#include <mips/atheros/ar531x/ar5312reg.h>
#include <mips/atheros/ar531x/ar5315reg.h>
#include <mips/atheros/ar531x/ar5315_cpudef.h>
#include <mips/atheros/ar531x/ar5315_setup.h>
static void
ar5312_chip_detect_mem_size(void)
{
uint32_t memsize;
uint32_t memcfg, bank0, bank1;
/*
* Determine the memory size as established by system
* firmware.
*
* NB: we allow compile time override
*/
memcfg = ATH_READ_REG(AR5312_SDRAMCTL_BASE + AR5312_SDRAMCTL_MEM_CFG1);
bank0 = __SHIFTOUT(memcfg, AR5312_MEM_CFG1_BANK0);
bank1 = __SHIFTOUT(memcfg, AR5312_MEM_CFG1_BANK1);
memsize = (bank0 ? (1 << (bank0 + 1)) : 0) +
(bank1 ? (1 << (bank1 + 1)) : 0);
memsize <<= 20;
realmem = memsize;
}
static void
ar5312_chip_detect_sys_frequency(void)
{
uint32_t predivisor;
uint32_t multiplier;
const uint32_t clockctl = ATH_READ_REG(AR5312_SYSREG_BASE + AR5312_SYSREG_CLOCKCTL);
if(ar531x_soc == AR531X_SOC_AR5313) {
predivisor = __SHIFTOUT(clockctl, AR2313_CLOCKCTL_PREDIVIDE);
multiplier = __SHIFTOUT(clockctl, AR2313_CLOCKCTL_MULTIPLIER);
} else {
predivisor = __SHIFTOUT(clockctl, AR5312_CLOCKCTL_PREDIVIDE);
multiplier = __SHIFTOUT(clockctl, AR5312_CLOCKCTL_MULTIPLIER);
}
const uint32_t divisor = (0x5421 >> (predivisor * 4)) & 15;
const uint32_t cpufreq = (40000000 / divisor) * multiplier;
u_ar531x_cpu_freq = cpufreq;
u_ar531x_ahb_freq = cpufreq / 4;
u_ar531x_ddr_freq = 0;
}
/*
* This does not lock the CPU whilst doing the work!
*/
static void
ar5312_chip_device_reset(void)
{
ATH_WRITE_REG(AR5312_SYSREG_BASE + AR5312_SYSREG_RESETCTL,
AR5312_RESET_SYSTEM);
}
static void
ar5312_chip_device_start(void)
{
uint32_t cfg0, cfg1;
uint32_t bank0, bank1;
uint32_t size0, size1;
cfg0 = ATH_READ_REG(AR5312_SDRAMCTL_BASE + AR5312_SDRAMCTL_MEM_CFG0);
cfg1 = ATH_READ_REG(AR5312_SDRAMCTL_BASE + AR5312_SDRAMCTL_MEM_CFG1);
bank0 = __SHIFTOUT(cfg1, AR5312_MEM_CFG1_BANK0);
bank1 = __SHIFTOUT(cfg1, AR5312_MEM_CFG1_BANK1);
size0 = bank0 ? (1 << (bank0 + 1)) : 0;
size1 = bank1 ? (1 << (bank1 + 1)) : 0;
size0 <<= 20;
size1 <<= 20;
printf("SDRMCTL %x %x %x %x\n", cfg0, cfg1, size0, size1);
ATH_READ_REG(AR5312_SYSREG_BASE + AR5312_SYSREG_AHBPERR);
ATH_READ_REG(AR5312_SYSREG_BASE + AR5312_SYSREG_AHBDMAE);
// ATH_WRITE_REG(AR5312_SYSREG_BASE + AR5312_SYSREG_WDOG_CTL, 0);
ATH_WRITE_REG(AR5312_SYSREG_BASE + AR5312_SYSREG_ENABLE, 0);
ATH_WRITE_REG(AR5312_SYSREG_BASE+AR5312_SYSREG_ENABLE,
ATH_READ_REG(AR5312_SYSREG_BASE+AR5312_SYSREG_ENABLE) |
AR5312_ENABLE_ENET0 | AR5312_ENABLE_ENET1);
}
static int
ar5312_chip_device_stopped(uint32_t mask)
{
uint32_t reg;
reg = ATH_READ_REG(AR5312_SYSREG_BASE + AR5312_SYSREG_RESETCTL);
return ((reg & mask) == mask);
}
static void
ar5312_chip_set_mii_speed(uint32_t unit, uint32_t speed)
{
}
/* Speed is either 10, 100 or 1000 */
static void
ar5312_chip_set_pll_ge(int unit, int speed)
{
}
static void
ar5312_chip_ddr_flush_ge(int unit)
{
}
static void
ar5312_chip_soc_init(void)
{
u_ar531x_uart_addr = MIPS_PHYS_TO_KSEG1(AR5312_UART0_BASE);
u_ar531x_gpio_di = AR5312_GPIO_DI;
u_ar531x_gpio_do = AR5312_GPIO_DO;
u_ar531x_gpio_cr = AR5312_GPIO_CR;
u_ar531x_gpio_pins = AR5312_GPIO_PINS;
u_ar531x_wdog_ctl = AR5312_SYSREG_WDOG_CTL;
u_ar531x_wdog_timer = AR5312_SYSREG_WDOG_TIMER;
}
static uint32_t
ar5312_chip_get_eth_pll(unsigned int mac, int speed)
{
return 0;
}
struct ar5315_cpu_def ar5312_chip_def = {
&ar5312_chip_detect_mem_size,
&ar5312_chip_detect_sys_frequency,
&ar5312_chip_device_reset,
&ar5312_chip_device_start,
&ar5312_chip_device_stopped,
&ar5312_chip_set_pll_ge,
&ar5312_chip_set_mii_speed,
&ar5312_chip_ddr_flush_ge,
&ar5312_chip_get_eth_pll,
&ar5312_chip_soc_init,
};

View File

@ -1,34 +0,0 @@
/*-
* Copyright (c) 2010 Adrian Chadd
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* $FreeBSD$ */
#ifndef __AR5312_CHIP_H__
#define __AR5312_CHIP_H__
extern struct ar5315_cpu_def ar5312_chip_def;
#endif

View File

@ -1,239 +0,0 @@
/* $Id: ar5312reg.h,v 1.4 2011/07/07 05:06:44 matt Exp $ */
/*
* Copyright (c) 2006 Urbana-Champaign Independent Media Center.
* Copyright (c) 2006 Garrett D'Amore.
* All rights reserved.
*
* This code was written by Garrett D'Amore for the Champaign-Urbana
* Community Wireless Network Project.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgements:
* This product includes software developed by the Urbana-Champaign
* Independent Media Center.
* This product includes software developed by Garrett D'Amore.
* 4. Urbana-Champaign Independent Media Center's name and Garrett
* D'Amore's name may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE URBANA-CHAMPAIGN INDEPENDENT
* MEDIA CENTER AND GARRETT D'AMORE ``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 URBANA-CHAMPAIGN INDEPENDENT
* MEDIA CENTER OR GARRETT D'AMORE BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef _MIPS_ATHEROS_AR5312REG_H_
#define _MIPS_ATHEROS_AR5312REG_H_
#define AR5312_MEM0_BASE 0x00000000 /* sdram */
#define AR5312_MEM1_BASE 0x08000000 /* sdram/flash */
#define AR5312_MEM3_BASE 0x10000000 /* flash */
#define AR5312_WLAN0_BASE 0x18000000
#define AR5312_ENET0_BASE 0x18100000
#define AR5312_ENET1_BASE 0x18200000
#define AR5312_SDRAMCTL_BASE 0x18300000
#define AR5312_FLASHCTL_BASE 0x18400000
#define AR5312_WLAN1_BASE 0x18500000
#define AR5312_UART0_BASE 0x1C000000 /* high speed */
#define AR5312_UART1_BASE 0x1C001000
#define AR5312_GPIO_BASE 0x1C002000
#define AR5312_SYSREG_BASE 0x1C003000
#define AR5312_UARTDMA_BASE 0x1C004000
#define AR5312_FLASH_BASE 0x1E000000
#define AR5312_FLASH_END 0x20000000 /* possibly aliased */
/*
* FLASHCTL registers -- offset relative to AR531X_FLASHCTL_BASE
*/
#define AR5312_FLASHCTL_0 0x00
#define AR5312_FLASHCTL_1 0x04
#define AR5312_FLASHCTL_2 0x08
#define AR5312_FLASHCTL_IDCY __BITS(0,3) /* idle cycle turn */
#define AR5312_FLASHCTL_WST1 __BITS(5,9) /* wait state 1 */
#define AR5312_FLASHCTL_RBLE __BIT(10) /* rd byte enable */
#define AR5312_FLASHCTL_WST2 __BITS(11,15) /* wait state 1 */
#define AR5312_FLASHCTL_AC __BITS(16,18) /* addr chk */
#define AR5312_FLASHCTL_AC_128K 0
#define AR5312_FLASHCTL_AC_256K 1
#define AR5312_FLASHCTL_AC_512K 2
#define AR5312_FLASHCTL_AC_1M 3
#define AR5312_FLASHCTL_AC_2M 4
#define AR5312_FLASHCTL_AC_4M 5
#define AR5312_FLASHCTL_AC_8M 6
#define AR5312_FLASHCTL_AC_16M 7
#define AR5312_FLASHCTL_E __BIT(19) /* enable */
#define AR5312_FLASHCTL_BUSERR __BIT(24) /* buserr */
#define AR5312_FLASHCTL_WPERR __BIT(25) /* wperr */
#define AR5312_FLASHCTL_WP __BIT(26) /* wp */
#define AR5312_FLASHCTL_BM __BIT(27) /* bm */
#define AR5312_FLASHCTL_MW __BITS(28,29) /* mem width */
#define AR5312_FLASHCTL_AT __BITS(31,30) /* access type */
/*
* GPIO registers -- offset relative to AR531X_GPIO_BASE
*/
#define AR5312_GPIO_DO 0
#define AR5312_GPIO_DI 4
#define AR5312_GPIO_CR 8
#define AR5312_GPIO_PINS 8
/*
* SYSREG registers -- offset relative to AR531X_SYSREG_BASE
*/
#define AR5312_SYSREG_TIMER 0x0000
#define AR5312_SYSREG_TIMER_RELOAD 0x0004
#define AR5312_SYSREG_WDOG_CTL 0x0008
#define AR5312_SYSREG_WDOG_TIMER 0x000c
#define AR5312_SYSREG_MISC_INTSTAT 0x0010
#define AR5312_SYSREG_MISC_INTMASK 0x0014
#define AR5312_SYSREG_INTSTAT 0x0018
#define AR5312_SYSREG_RESETCTL 0x0020
#define AR5312_SYSREG_CLOCKCTL 0x0064
#define AR5312_SYSREG_SCRATCH 0x006c
#define AR5312_SYSREG_AHBPERR 0x0070
#define AR5312_SYSREG_PROC 0x0074
#define AR5312_SYSREG_AHBDMAE 0x0078
#define AR5312_SYSREG_ENABLE 0x0080
#define AR5312_SYSREG_REVISION 0x0090
/* WDOG_CTL watchdog control bits */
#define AR5312_WDOG_CTL_IGNORE 0x0000
#define AR5312_WDOG_CTL_NMI 0x0001
#define AR5312_WDOG_CTL_RESET 0x0002
/* Resets */
#define AR5312_RESET_SYSTEM __BIT(0)
#define AR5312_RESET_CPU __BIT(1)
#define AR5312_RESET_WLAN0 __BIT(2) /* mac & bb */
#define AR5312_RESET_PHY0 __BIT(3) /* enet phy */
#define AR5312_RESET_PHY1 __BIT(4) /* enet phy */
#define AR5312_RESET_ENET0 __BIT(5) /* mac */
#define AR5312_RESET_ENET1 __BIT(6) /* mac */
#define AR5312_RESET_UART0 __BIT(8) /* mac */
#define AR5312_RESET_WLAN1 __BIT(9) /* mac & bb */
#define AR5312_RESET_APB __BIT(10) /* bridge */
#define AR5312_RESET_WARM_CPU __BIT(16)
#define AR5312_RESET_WARM_WLAN0_MAC __BIT(17)
#define AR5312_RESET_WARM_WLAN0_BB __BIT(18)
#define AR5312_RESET_NMI __BIT(20)
#define AR5312_RESET_WARM_WLAN1_MAC __BIT(21)
#define AR5312_RESET_WARM_WLAN1_BB __BIT(22)
#define AR5312_RESET_LOCAL_BUS __BIT(23)
#define AR5312_RESET_WDOG __BIT(24)
/* AR5312/2312 clockctl bits */
#define AR5312_CLOCKCTL_PREDIVIDE __BITS(4,5)
#define AR5312_CLOCKCTL_MULTIPLIER __BITS(8,12)
#define AR5312_CLOCKCTL_DOUBLER __BIT(16)
/* AR2313 clockctl */
#define AR2313_CLOCKCTL_PREDIVIDE __BITS(12,13)
#define AR2313_CLOCKCTL_MULTIPLIER __BITS(16,20)
/* Enables */
#define AR5312_ENABLE_WLAN0 __BIT(0)
#define AR5312_ENABLE_ENET0 __BIT(1)
#define AR5312_ENABLE_ENET1 __BIT(2)
#define AR5312_ENABLE_WLAN1 __BITS(7,8) /* both DMA and PIO */
/* Revision ids */
#define AR5312_REVISION_WMAC_MAJOR(x) (((x) >> 12) & 0xf)
#define AR5312_REVISION_WMAC_MINOR(x) (((x) >> 8) & 0xf)
#define AR5312_REVISION_WMAC(x) (((x) >> 8) & 0xff)
#define AR5312_REVISION_MAJOR(x) (((x) >> 4) & 0xf)
#define AR5312_REVISION_MINOR(x) (((x) >> 0) & 0xf)
#define AR5312_REVISION_MAJ_AR5311 0x1
#define AR5312_REVISION_MAJ_AR5312 0x4
#define AR5312_REVISION_MAJ_AR2313 0x5
#define AR5312_REVISION_MAJ_AR5315 0xB
/*
* SDRAMCTL registers -- offset relative to SDRAMCTL
*/
#define AR5312_SDRAMCTL_MEM_CFG0 0x0000
#define AR5312_SDRAMCTL_MEM_CFG1 0x0004
/* memory config 1 bits */
#define AR5312_MEM_CFG1_BANK0 __BITS(8,10)
#define AR5312_MEM_CFG1_BANK1 __BITS(12,15)
/* helper macro for accessing system registers without bus space */
#define REGVAL(x) *((volatile uint32_t *)(MIPS_PHYS_TO_KSEG1((x))))
#define GETSYSREG(x) REGVAL((x) + AR5312_SYSREG_BASE)
#define PUTSYSREG(x,v) (REGVAL((x) + AR5312_SYSREG_BASE)) = (v)
#define GETSDRAMREG(x) REGVAL((x) + AR5312_SDRAMCTL_BASE)
#define PUTSDRAMREG(x,v) (REGVAL((x) + AR5312_SDRAMCTL_BASE)) = (v)
/*
* Interrupts.
*/
#define AR5312_IRQ_WLAN0 0
#define AR5312_IRQ_ENET0 1
#define AR5312_IRQ_ENET1 2
#define AR5312_IRQ_WLAN1 3
#define AR5312_IRQ_MISC 4
#define AR5312_MISC_IRQ_TIMER 1
#define AR5312_MISC_IRQ_AHBPERR 2
#define AR5312_MISC_IRQ_AHBDMAE 3
#define AR5312_MISC_IRQ_GPIO 4
#define AR5312_MISC_IRQ_UART0 5
#define AR5312_MISC_IRQ_UART0_DMA 6
#define AR5312_MISC_IRQ_WDOG 7
/*
* Board data. This is located in flash somewhere, ar531x_board_info
* locates it.
*/
#include <dev/ath/ath_hal/ah_soc.h> /* XXX really doesn't belong in hal */
/* XXX write-around for now */
#define AR5312_BOARD_MAGIC AR531X_BD_MAGIC
/* config bits */
#define AR5312_BOARD_CONFIG_ENET0 BD_ENET0
#define AR5312_BOARD_CONFIG_ENET1 BD_ENET1
#define AR5312_BOARD_CONFIG_UART1 BD_UART1
#define AR5312_BOARD_CONFIG_UART0 BD_UART0
#define AR5312_BOARD_CONFIG_RSTFACTORY BD_RSTFACTORY
#define AR5312_BOARD_CONFIG_SYSLED BD_SYSLED
#define AR5312_BOARD_CONFIG_EXTUARTCLK BD_EXTUARTCLK
#define AR5312_BOARD_CONFIG_CPUFREQ BD_CPUFREQ
#define AR5312_BOARD_CONFIG_SYSFREQ BD_SYSFREQ
#define AR5312_BOARD_CONFIG_WLAN0 BD_WLAN0
#define AR5312_BOARD_CONFIG_MEMCAP BD_MEMCAP
#define AR5312_BOARD_CONFIG_DISWDOG BD_DISWATCHDOG
#define AR5312_BOARD_CONFIG_WLAN1 BD_WLAN1
#define AR5312_BOARD_CONFIG_AR2312 BD_ISCASPER
#define AR5312_BOARD_CONFIG_WLAN0_2G BD_WLAN0_2G_EN
#define AR5312_BOARD_CONFIG_WLAN0_5G BD_WLAN0_5G_EN
#define AR5312_BOARD_CONFIG_WLAN1_2G BD_WLAN1_2G_EN
#define AR5312_BOARD_CONFIG_WLAN1_5G BD_WLAN1_5G_EN
#define AR5312_APB_BASE AR5312_UART0_BASE
#define AR5312_APB_SIZE 0x02000000
#endif /* _MIPS_ATHEROS_AR531XREG_H_ */

View File

@ -1,256 +0,0 @@
/*-
* Copyright (c) 2010 Adrian Chadd
* All rights reserved.
* Copyright (c) 2016, Hiroki Mori
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_ddb.h"
#include <sys/param.h>
#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/cons.h>
#include <sys/kdb.h>
#include <sys/reboot.h>
#include <vm/vm.h>
#include <vm/vm_page.h>
#include <net/ethernet.h>
#include <machine/clock.h>
#include <machine/cpu.h>
#include <machine/cpuregs.h>
#include <machine/hwfunc.h>
#include <machine/md_var.h>
#include <machine/trap.h>
#include <machine/vmparam.h>
#include <mips/atheros/ar531x/ar5315reg.h>
#include <mips/atheros/ar531x/ar5315_chip.h>
#include <mips/atheros/ar531x/ar5315_cpudef.h>
/* XXX these shouldn't be in here - this file is a per-chip file */
/* XXX these should be in the top-level ar5315 type, not ar5315 -chip */
uint32_t u_ar531x_cpu_freq;
uint32_t u_ar531x_ahb_freq;
uint32_t u_ar531x_ddr_freq;
uint32_t u_ar531x_uart_addr;
uint32_t u_ar531x_gpio_di;
uint32_t u_ar531x_gpio_do;
uint32_t u_ar531x_gpio_cr;
uint32_t u_ar531x_gpio_pins;
uint32_t u_ar531x_wdog_ctl;
uint32_t u_ar531x_wdog_timer;
static void
ar5315_chip_detect_mem_size(void)
{
uint32_t memsize = 0;
uint32_t memcfg, cw, rw, dw;
/*
* Determine the memory size. We query the board info.
*/
memcfg = ATH_READ_REG(AR5315_SDRAMCTL_BASE + AR5315_SDRAMCTL_MEM_CFG);
cw = __SHIFTOUT(memcfg, AR5315_MEM_CFG_COL_WIDTH);
cw += 1;
rw = __SHIFTOUT(memcfg, AR5315_MEM_CFG_ROW_WIDTH);
rw += 1;
/* XXX: according to redboot, this could be wrong if DDR SDRAM */
dw = __SHIFTOUT(memcfg, AR5315_MEM_CFG_DATA_WIDTH);
dw += 1;
dw *= 8; /* bits */
/* not too sure about this math, but it _seems_ to add up */
memsize = (1 << cw) * (1 << rw) * dw;
#if 0
printf("SDRAM_MEM_CFG =%x, cw=%d rw=%d dw=%d xmemsize=%d\n", memcfg,
cw, rw, dw, memsize);
#endif
realmem = memsize;
}
static void
ar5315_chip_detect_sys_frequency(void)
{
uint32_t freq_ref, freq_pll;
static const uint8_t pll_divide_table[] = {
2, 3, 4, 6, 3,
/*
* these entries are bogus, but it avoids a possible
* bad table dereference
*/
1, 1, 1
};
static const uint8_t pre_divide_table[] = {
1, 2, 4, 5
};
const uint32_t pllc = ATH_READ_REG(AR5315_SYSREG_BASE +
AR5315_SYSREG_PLLC_CTL);
const uint32_t refdiv = pre_divide_table[AR5315_PLLC_REF_DIV(pllc)];
const uint32_t fbdiv = AR5315_PLLC_FB_DIV(pllc);
const uint32_t div2 = (AR5315_PLLC_DIV_2(pllc) + 1) * 2; /* results in 2 or 4 */
freq_ref = 40000000;
/* 40MHz reference clk, reference and feedback dividers */
freq_pll = (freq_ref / refdiv) * div2 * fbdiv;
const uint32_t pllout[4] = {
/* CLKM select */
[0] = freq_pll / pll_divide_table[AR5315_PLLC_CLKM(pllc)],
[1] = freq_pll / pll_divide_table[AR5315_PLLC_CLKM(pllc)],
/* CLKC select */
[2] = freq_pll / pll_divide_table[AR5315_PLLC_CLKC(pllc)],
/* ref_clk select */
[3] = freq_ref, /* use original reference clock */
};
const uint32_t amba_clkctl = ATH_READ_REG(AR5315_SYSREG_BASE +
AR5315_SYSREG_AMBACLK);
uint32_t ambadiv = AR5315_CLOCKCTL_DIV(amba_clkctl);
ambadiv = ambadiv ? (ambadiv * 2) : 1;
u_ar531x_ahb_freq = pllout[AR5315_CLOCKCTL_SELECT(amba_clkctl)] / ambadiv;
const uint32_t cpu_clkctl = ATH_READ_REG(AR5315_SYSREG_BASE +
AR5315_SYSREG_CPUCLK);
uint32_t cpudiv = AR5315_CLOCKCTL_DIV(cpu_clkctl);
cpudiv = cpudiv ? (cpudiv * 2) : 1;
u_ar531x_cpu_freq = pllout[AR5315_CLOCKCTL_SELECT(cpu_clkctl)] / cpudiv;
u_ar531x_ddr_freq = 0;
}
/*
* This does not lock the CPU whilst doing the work!
*/
static void
ar5315_chip_device_reset(void)
{
ATH_WRITE_REG(AR5315_SYSREG_BASE + AR5315_SYSREG_COLDRESET,
AR5315_COLD_AHB | AR5315_COLD_APB | AR5315_COLD_CPU);
}
static void
ar5315_chip_device_start(void)
{
ATH_WRITE_REG(AR5315_SYSREG_BASE+AR5315_SYSREG_AHB_ERR0,
AR5315_AHB_ERROR_DET);
ATH_READ_REG(AR5315_SYSREG_BASE+AR5315_SYSREG_AHB_ERR1);
ATH_WRITE_REG(AR5315_SYSREG_BASE+AR5315_SYSREG_WDOG_CTL,
AR5315_WDOG_CTL_IGNORE);
// set Ethernet AHB master arbitration control
// Maybe RedBoot was enabled. But to make sure.
ATH_WRITE_REG(AR5315_SYSREG_BASE+AR5315_SYSREG_AHB_ARB_CTL,
ATH_READ_REG(AR5315_SYSREG_BASE+AR5315_SYSREG_AHB_ARB_CTL) |
AR5315_ARB_ENET);
// set Ethernet controller byteswap control
/*
ATH_WRITE_REG(AR5315_SYSREG_BASE+AR5315_SYSREG_ENDIAN,
ATH_READ_REG(AR5315_SYSREG_BASE+AR5315_SYSREG_ENDIAN) |
AR5315_ENDIAN_ENET);
*/
/* Disable interrupts for all gpio pins. */
ATH_WRITE_REG(AR5315_SYSREG_BASE+AR5315_SYSREG_GPIO_INT, 0);
printf("AHB Master Arbitration Control %08x\n",
ATH_READ_REG(AR5315_SYSREG_BASE+AR5315_SYSREG_AHB_ARB_CTL));
printf("Byteswap Control %08x\n",
ATH_READ_REG(AR5315_SYSREG_BASE+AR5315_SYSREG_ENDIAN));
}
static int
ar5315_chip_device_stopped(uint32_t mask)
{
uint32_t reg;
reg = ATH_READ_REG(AR5315_SYSREG_BASE + AR5315_SYSREG_COLDRESET);
return ((reg & mask) == mask);
}
static void
ar5315_chip_set_mii_speed(uint32_t unit, uint32_t speed)
{
}
/* Speed is either 10, 100 or 1000 */
static void
ar5315_chip_set_pll_ge(int unit, int speed)
{
}
static void
ar5315_chip_ddr_flush_ge(int unit)
{
}
static void
ar5315_chip_soc_init(void)
{
u_ar531x_uart_addr = MIPS_PHYS_TO_KSEG1(AR5315_UART_BASE);
u_ar531x_gpio_di = AR5315_SYSREG_GPIO_DI;
u_ar531x_gpio_do = AR5315_SYSREG_GPIO_DO;
u_ar531x_gpio_cr = AR5315_SYSREG_GPIO_CR;
u_ar531x_gpio_pins = AR5315_GPIO_PINS;
u_ar531x_wdog_ctl = AR5315_SYSREG_WDOG_CTL;
u_ar531x_wdog_timer = AR5315_SYSREG_WDOG_TIMER;
}
static uint32_t
ar5315_chip_get_eth_pll(unsigned int mac, int speed)
{
return 0;
}
struct ar5315_cpu_def ar5315_chip_def = {
&ar5315_chip_detect_mem_size,
&ar5315_chip_detect_sys_frequency,
&ar5315_chip_device_reset,
&ar5315_chip_device_start,
&ar5315_chip_device_stopped,
&ar5315_chip_set_pll_ge,
&ar5315_chip_set_mii_speed,
&ar5315_chip_ddr_flush_ge,
&ar5315_chip_get_eth_pll,
&ar5315_chip_soc_init,
};

View File

@ -1,34 +0,0 @@
/*-
* Copyright (c) 2010 Adrian Chadd
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* $FreeBSD$ */
#ifndef __AR5315_CHIP_H__
#define __AR5315_CHIP_H__
extern struct ar5315_cpu_def ar5315_chip_def;
#endif

View File

@ -1,135 +0,0 @@
/*-
* Copyright (c) 2010 Adrian Chadd
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* $FreeBSD$ */
#ifndef __AR5315_CPUDEF_H__
#define __AR5315_CPUDEF_H__
struct ar5315_cpu_def {
void (* detect_mem_size) (void);
void (* detect_sys_frequency) (void);
void (* ar5315_chip_device_reset) (void);
void (* ar5315_chip_device_start) (void);
int (* ar5315_chip_device_stopped) (uint32_t);
void (* ar5315_chip_set_pll_ge) (int, int);
void (* ar5315_chip_set_mii_speed) (uint32_t, uint32_t);
void (* ar5315_chip_ddr_flush_ge) (int);
uint32_t (* ar5315_chip_get_eth_pll) (unsigned int, int);
void (* ar5315_chip_soc_init) (void);
/*
* Allow to change MII bus mode:
* AR5315_ARGE_MII_MODE_MII
* AR5315_ARGE_MII_MODE_RMII
* AR5315_ARGE_MII_MODE_GMII
* AR5315_ARGE_MII_MODE_RGMII
* mii_mode(unit, mode);
*/
#define AR5315_ARGE_MII_MODE_MII 0x0100
#define AR5315_ARGE_MII_MODE_RMII 0x0101
#define AR5315_ARGE_MII_MODE_GMII 0x1000
#define AR5315_ARGE_MII_MODE_RGMII 0x1001
void (* ar5315_chip_set_mii_mode) (int, int, int);
};
extern struct ar5315_cpu_def * ar5315_cpu_ops;
static inline void ar531x_detect_mem_size(void)
{
ar5315_cpu_ops->detect_mem_size();
}
static inline void ar531x_detect_sys_frequency(void)
{
ar5315_cpu_ops->detect_sys_frequency();
}
static inline void ar531x_device_reset(void)
{
ar5315_cpu_ops->ar5315_chip_device_reset();
}
static inline void ar531x_device_start(void)
{
ar5315_cpu_ops->ar5315_chip_device_start();
}
static inline int ar531x_device_stopped(uint32_t mask)
{
return ar5315_cpu_ops->ar5315_chip_device_stopped(mask);
}
static inline void ar531x_device_set_pll_ge(int unit, int speed)
{
ar5315_cpu_ops->ar5315_chip_set_pll_ge(unit, speed);
}
static inline void ar531x_device_set_mii_speed(int unit, int speed)
{
ar5315_cpu_ops->ar5315_chip_set_mii_speed(unit, speed);
}
static inline void ar531x_device_flush_ddr_ge(int unit)
{
ar5315_cpu_ops->ar5315_chip_ddr_flush_ge(unit);
}
static inline void ar531x_device_soc_init(void)
{
ar5315_cpu_ops->ar5315_chip_soc_init();
}
static inline void ar531x_device_set_mii_mode(int unit, int mode, int speed)
{
ar5315_cpu_ops->ar5315_chip_set_mii_mode(unit, mode, speed);
}
/* XXX shouldn't be here! */
extern uint32_t u_ar531x_cpu_freq;
extern uint32_t u_ar531x_ahb_freq;
extern uint32_t u_ar531x_ddr_freq;
extern uint32_t u_ar531x_uart_addr;
extern uint32_t u_ar531x_gpio_di;
extern uint32_t u_ar531x_gpio_do;
extern uint32_t u_ar531x_gpio_cr;
extern uint32_t u_ar531x_gpio_pins;
extern uint32_t u_ar531x_wdog_ctl;
extern uint32_t u_ar531x_wdog_timer;
static inline uint32_t ar531x_cpu_freq(void) { return u_ar531x_cpu_freq; }
static inline uint32_t ar531x_ahb_freq(void) { return u_ar531x_ahb_freq; }
static inline uint32_t ar531x_ddr_freq(void) { return u_ar531x_ddr_freq; }
static inline uint32_t ar531x_uart_addr(void) { return u_ar531x_uart_addr; }
static inline uint32_t ar531x_gpio_di(void) { return u_ar531x_gpio_di; }
static inline uint32_t ar531x_gpio_cr(void) { return u_ar531x_gpio_cr; }
static inline uint32_t ar531x_gpio_do(void) { return u_ar531x_gpio_do; }
static inline uint32_t ar531x_gpio_pins(void) { return u_ar531x_gpio_pins; }
static inline uint32_t ar531x_wdog_ctl(void) { return u_ar531x_wdog_ctl; }
static inline uint32_t ar531x_wdog_timer(void) { return u_ar531x_wdog_timer; }
#endif

View File

@ -1,532 +0,0 @@
/*-
* Copyright (c) 2016, Hiroki Mori
* Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@FreeBSD.org>
* Copyright (c) 2009, Luiz Otavio O Souza.
* 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 unmodified, 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.
*/
/*
* GPIO driver for AR5315
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/rman.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mutex.h>
#include <sys/gpio.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <mips/atheros/ar531x/ar5315reg.h>
#include <mips/atheros/ar531x/ar5315_cpudef.h>
#include <mips/atheros/ar531x/ar5315_gpiovar.h>
#include <dev/gpio/gpiobusvar.h>
#include "gpio_if.h"
#define DEFAULT_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)
/*
* Helpers
*/
static void ar5315_gpio_function_enable(struct ar5315_gpio_softc *sc,
uint32_t mask);
static void ar5315_gpio_function_disable(struct ar5315_gpio_softc *sc,
uint32_t mask);
static void ar5315_gpio_pin_configure(struct ar5315_gpio_softc *sc,
struct gpio_pin *pin, uint32_t flags);
/*
* Driver stuff
*/
static int ar5315_gpio_probe(device_t dev);
static int ar5315_gpio_attach(device_t dev);
static int ar5315_gpio_detach(device_t dev);
static int ar5315_gpio_filter(void *arg);
static void ar5315_gpio_intr(void *arg);
/*
* GPIO interface
*/
static device_t ar5315_gpio_get_bus(device_t);
static int ar5315_gpio_pin_max(device_t dev, int *maxpin);
static int ar5315_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps);
static int ar5315_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t
*flags);
static int ar5315_gpio_pin_getname(device_t dev, uint32_t pin, char *name);
static int ar5315_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags);
static int ar5315_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value);
static int ar5315_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val);
static int ar5315_gpio_pin_toggle(device_t dev, uint32_t pin);
/*
* Enable/disable the GPIO function control space.
*
* This is primarily for the AR5315, which has SPI CS1/CS2, UART, SLIC, I2S
* as GPIO pin options.
*/
static void
ar5315_gpio_function_enable(struct ar5315_gpio_softc *sc, uint32_t mask)
{
// GPIO_SET_BITS(sc, AR5315_GPIO_FUNCTION, mask);
}
static void
ar5315_gpio_function_disable(struct ar5315_gpio_softc *sc, uint32_t mask)
{
// GPIO_CLEAR_BITS(sc, AR5315_GPIO_FUNCTION, mask);
}
static void
ar5315_gpio_pin_configure(struct ar5315_gpio_softc *sc, struct gpio_pin *pin,
unsigned int flags)
{
uint32_t mask;
mask = 1 << pin->gp_pin;
/*
* Manage input/output
*/
if (flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) {
pin->gp_flags &= ~(GPIO_PIN_INPUT|GPIO_PIN_OUTPUT);
if (flags & GPIO_PIN_OUTPUT) {
pin->gp_flags |= GPIO_PIN_OUTPUT;
GPIO_SET_BITS(sc, ar531x_gpio_cr(), mask);
}
else {
pin->gp_flags |= GPIO_PIN_INPUT;
GPIO_CLEAR_BITS(sc, ar531x_gpio_cr(), mask);
}
}
}
static device_t
ar5315_gpio_get_bus(device_t dev)
{
struct ar5315_gpio_softc *sc;
sc = device_get_softc(dev);
return (sc->busdev);
}
static int
ar5315_gpio_pin_max(device_t dev, int *maxpin)
{
*maxpin = ar531x_gpio_pins() - 1;
return (0);
}
static int
ar5315_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
{
struct ar5315_gpio_softc *sc = device_get_softc(dev);
int i;
for (i = 0; i < sc->gpio_npins; i++) {
if (sc->gpio_pins[i].gp_pin == pin)
break;
}
if (i >= sc->gpio_npins)
return (EINVAL);
GPIO_LOCK(sc);
*caps = sc->gpio_pins[i].gp_caps;
GPIO_UNLOCK(sc);
return (0);
}
static int
ar5315_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
{
struct ar5315_gpio_softc *sc = device_get_softc(dev);
int i;
int dir;
for (i = 0; i < sc->gpio_npins; i++) {
if (sc->gpio_pins[i].gp_pin == pin)
break;
}
if (i >= sc->gpio_npins)
return (EINVAL);
dir = GPIO_READ(sc, ar531x_gpio_cr()) & (1 << pin);
*flags = dir ? GPIO_PIN_OUTPUT : GPIO_PIN_INPUT;
/*
GPIO_LOCK(sc);
*flags = sc->gpio_pins[i].gp_flags;
GPIO_UNLOCK(sc);
*/
return (0);
}
static int
ar5315_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
{
struct ar5315_gpio_softc *sc = device_get_softc(dev);
int i;
for (i = 0; i < sc->gpio_npins; i++) {
if (sc->gpio_pins[i].gp_pin == pin)
break;
}
if (i >= sc->gpio_npins)
return (EINVAL);
GPIO_LOCK(sc);
memcpy(name, sc->gpio_pins[i].gp_name, GPIOMAXNAME);
GPIO_UNLOCK(sc);
return (0);
}
static int
ar5315_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
{
int i;
struct ar5315_gpio_softc *sc = device_get_softc(dev);
for (i = 0; i < sc->gpio_npins; i++) {
if (sc->gpio_pins[i].gp_pin == pin)
break;
}
if (i >= sc->gpio_npins)
return (EINVAL);
ar5315_gpio_pin_configure(sc, &sc->gpio_pins[i], flags);
return (0);
}
static int
ar5315_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
{
struct ar5315_gpio_softc *sc = device_get_softc(dev);
uint32_t state;
state = GPIO_READ(sc, ar531x_gpio_do());
if(value == 1) {
state |= (1 << pin);
} else {
state &= ~(1 << pin);
}
GPIO_WRITE(sc, ar531x_gpio_do(), state);
return (0);
}
static int
ar5315_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
{
struct ar5315_gpio_softc *sc = device_get_softc(dev);
int i;
for (i = 0; i < sc->gpio_npins; i++) {
if (sc->gpio_pins[i].gp_pin == pin)
break;
}
if (i >= sc->gpio_npins)
return (EINVAL);
*val = (GPIO_READ(sc, ar531x_gpio_di()) & (1 << pin)) ? 1 : 0;
return (0);
}
static int
ar5315_gpio_pin_toggle(device_t dev, uint32_t pin)
{
int res, i;
struct ar5315_gpio_softc *sc = device_get_softc(dev);
for (i = 0; i < sc->gpio_npins; i++) {
if (sc->gpio_pins[i].gp_pin == pin)
break;
}
if (i >= sc->gpio_npins)
return (EINVAL);
res = (GPIO_READ(sc, ar531x_gpio_do()) & (1 << pin)) ? 1 : 0;
if (res)
GPIO_CLEAR_BITS(sc, ar531x_gpio_do(), pin);
else
GPIO_SET_BITS(sc, ar531x_gpio_do(), pin);
return (0);
}
static int
ar5315_gpio_filter(void *arg)
{
/* TODO: something useful */
return (FILTER_STRAY);
}
static void
ar5315_gpio_intr(void *arg)
{
struct ar5315_gpio_softc *sc = arg;
GPIO_LOCK(sc);
/* TODO: something useful */
GPIO_UNLOCK(sc);
}
static int
ar5315_gpio_probe(device_t dev)
{
device_set_desc(dev, "Atheros AR531x GPIO driver");
return (0);
}
static int
ar5315_gpio_attach(device_t dev)
{
struct ar5315_gpio_softc *sc = device_get_softc(dev);
int i, j, maxpin;
int mask, pinon;
uint32_t oe;
KASSERT((device_get_unit(dev) == 0),
("ar5315_gpio: Only one gpio module supported"));
mtx_init(&sc->gpio_mtx, device_get_nameunit(dev), NULL, MTX_DEF);
/* Map control/status registers. */
sc->gpio_mem_rid = 0;
sc->gpio_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
&sc->gpio_mem_rid, RF_ACTIVE);
if (sc->gpio_mem_res == NULL) {
device_printf(dev, "couldn't map memory\n");
ar5315_gpio_detach(dev);
return (ENXIO);
}
if ((sc->gpio_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
&sc->gpio_irq_rid, RF_SHAREABLE | RF_ACTIVE)) == NULL) {
device_printf(dev, "unable to allocate IRQ resource\n");
ar5315_gpio_detach(dev);
return (ENXIO);
}
if ((bus_setup_intr(dev, sc->gpio_irq_res, INTR_TYPE_MISC,
ar5315_gpio_filter, ar5315_gpio_intr, sc, &sc->gpio_ih))) {
device_printf(dev,
"WARNING: unable to register interrupt handler\n");
ar5315_gpio_detach(dev);
return (ENXIO);
}
sc->dev = dev;
/* Enable function bits that are required */
if (resource_int_value(device_get_name(dev), device_get_unit(dev),
"function_set", &mask) == 0) {
device_printf(dev, "function_set: 0x%x\n", mask);
ar5315_gpio_function_enable(sc, mask);
}
/* Disable function bits that are required */
if (resource_int_value(device_get_name(dev), device_get_unit(dev),
"function_clear", &mask) == 0) {
device_printf(dev, "function_clear: 0x%x\n", mask);
ar5315_gpio_function_disable(sc, mask);
}
/* Initialise all pins specified in the mask, up to the pin count */
(void) ar5315_gpio_pin_max(dev, &maxpin);
if (resource_int_value(device_get_name(dev), device_get_unit(dev),
"pinmask", &mask) != 0)
mask = 0;
if (resource_int_value(device_get_name(dev), device_get_unit(dev),
"pinon", &pinon) != 0)
pinon = 0;
device_printf(dev, "gpio pinmask=0x%x\n", mask);
for (j = 0; j <= maxpin; j++) {
if ((mask & (1 << j)) == 0)
continue;
sc->gpio_npins++;
}
/* Iniatilize the GPIO pins, keep the loader settings. */
oe = GPIO_READ(sc, ar531x_gpio_cr());
sc->gpio_pins = malloc(sizeof(struct gpio_pin) * sc->gpio_npins,
M_DEVBUF, M_WAITOK | M_ZERO);
for (i = 0, j = 0; j <= maxpin; j++) {
if ((mask & (1 << j)) == 0)
continue;
snprintf(sc->gpio_pins[i].gp_name, GPIOMAXNAME,
"pin %d", j);
sc->gpio_pins[i].gp_pin = j;
sc->gpio_pins[i].gp_caps = DEFAULT_CAPS;
if (oe & (1 << j))
sc->gpio_pins[i].gp_flags = GPIO_PIN_OUTPUT;
else
sc->gpio_pins[i].gp_flags = GPIO_PIN_INPUT;
i++;
}
#if 0
/* Turn on the hinted pins. */
for (i = 0; i < sc->gpio_npins; i++) {
j = sc->gpio_pins[i].gp_pin;
if ((pinon & (1 << j)) != 0) {
ar5315_gpio_pin_setflags(dev, j, GPIO_PIN_OUTPUT);
ar5315_gpio_pin_set(dev, j, 1);
}
}
/*
* Search through the function hints, in case there's some
* overrides such as LNA control.
*
* hint.gpio.X.func.<pin>.gpiofunc=<func value>
* hint.gpio.X.func.<pin>.gpiomode=1 (for output, default low)
*/
for (i = 0; i <= maxpin; i++) {
char buf[32];
int gpiofunc, gpiomode;
snprintf(buf, 32, "func.%d.gpiofunc", i);
if (resource_int_value(device_get_name(dev),
device_get_unit(dev),
buf,
&gpiofunc) != 0)
continue;
/* Get the mode too */
snprintf(buf, 32, "func.%d.gpiomode", i);
if (resource_int_value(device_get_name(dev),
device_get_unit(dev),
buf,
&gpiomode) != 0)
continue;
/* We only handle mode=1 for now */
if (gpiomode != 1)
continue;
device_printf(dev, "%s: GPIO %d: func=%d, mode=%d\n",
__func__,
i,
gpiofunc,
gpiomode);
/* Set output (bit == 0) */
oe = GPIO_READ(sc, ar531x_gpio_cr());
oe &= ~ (1 << i);
GPIO_WRITE(sc, ar531x_gpio_cr(), oe);
/* Set pin value = 0, so it stays low by default */
oe = GPIO_READ(sc, ar531x_gpio_do());
oe &= ~ (1 << i);
GPIO_WRITE(sc, ar531x_gpio_do(), oe);
/* Finally: Set the output config */
// ar5315_gpio_ouput_configure(i, gpiofunc);
}
#endif
sc->busdev = gpiobus_attach_bus(dev);
if (sc->busdev == NULL) {
ar5315_gpio_detach(dev);
return (ENXIO);
}
return (0);
}
static int
ar5315_gpio_detach(device_t dev)
{
struct ar5315_gpio_softc *sc = device_get_softc(dev);
KASSERT(mtx_initialized(&sc->gpio_mtx), ("gpio mutex not initialized"));
gpiobus_detach_bus(dev);
if (sc->gpio_ih)
bus_teardown_intr(dev, sc->gpio_irq_res, sc->gpio_ih);
if (sc->gpio_irq_res)
bus_release_resource(dev, SYS_RES_IRQ, sc->gpio_irq_rid,
sc->gpio_irq_res);
if (sc->gpio_mem_res)
bus_release_resource(dev, SYS_RES_MEMORY, sc->gpio_mem_rid,
sc->gpio_mem_res);
if (sc->gpio_pins)
free(sc->gpio_pins, M_DEVBUF);
mtx_destroy(&sc->gpio_mtx);
return(0);
}
static device_method_t ar5315_gpio_methods[] = {
DEVMETHOD(device_probe, ar5315_gpio_probe),
DEVMETHOD(device_attach, ar5315_gpio_attach),
DEVMETHOD(device_detach, ar5315_gpio_detach),
/* GPIO protocol */
DEVMETHOD(gpio_get_bus, ar5315_gpio_get_bus),
DEVMETHOD(gpio_pin_max, ar5315_gpio_pin_max),
DEVMETHOD(gpio_pin_getname, ar5315_gpio_pin_getname),
DEVMETHOD(gpio_pin_getflags, ar5315_gpio_pin_getflags),
DEVMETHOD(gpio_pin_getcaps, ar5315_gpio_pin_getcaps),
DEVMETHOD(gpio_pin_setflags, ar5315_gpio_pin_setflags),
DEVMETHOD(gpio_pin_get, ar5315_gpio_pin_get),
DEVMETHOD(gpio_pin_set, ar5315_gpio_pin_set),
DEVMETHOD(gpio_pin_toggle, ar5315_gpio_pin_toggle),
{0, 0},
};
static driver_t ar5315_gpio_driver = {
"gpio",
ar5315_gpio_methods,
sizeof(struct ar5315_gpio_softc),
};
static devclass_t ar5315_gpio_devclass;
DRIVER_MODULE(ar5315_gpio, apb, ar5315_gpio_driver, ar5315_gpio_devclass, 0, 0);

View File

@ -1,75 +0,0 @@
/*-
* Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@FreeBSD.org>
* Copyright (c) 2009, Luiz Otavio O Souza.
* 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 unmodified, this list of conditions, and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*
*/
#ifndef __AR5315_GPIOVAR_H__
#define __AR5315_GPIOVAR_H__
#include <sys/timepps.h>
#define GPIO_LOCK(_sc) mtx_lock(&(_sc)->gpio_mtx)
#define GPIO_UNLOCK(_sc) mtx_unlock(&(_sc)->gpio_mtx)
#define GPIO_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->gpio_mtx, MA_OWNED)
/*
* register space access macros
*/
#define GPIO_WRITE(sc, reg, val) do { \
bus_write_4(sc->gpio_mem_res, (reg), (val)); \
} while (0)
#define GPIO_READ(sc, reg) bus_read_4(sc->gpio_mem_res, (reg))
#define GPIO_SET_BITS(sc, reg, bits) \
GPIO_WRITE(sc, reg, GPIO_READ(sc, (reg)) | (bits))
#define GPIO_CLEAR_BITS(sc, reg, bits) \
GPIO_WRITE(sc, reg, GPIO_READ(sc, (reg)) & ~(bits))
#define AR5315_GPIO_PINS 23
#define AR5312_GPIO_PINS 8
struct ar5315_gpio_softc {
device_t dev;
device_t busdev;
struct mtx gpio_mtx;
struct resource *gpio_mem_res;
int gpio_mem_rid;
struct resource *gpio_irq_res;
int gpio_irq_rid;
void *gpio_ih;
int gpio_npins;
struct gpio_pin *gpio_pins;
int gpio_ppspin;
struct pps_state gpio_pps;
uint32_t gpio_ppsenable;
};
#endif /* __AR5315_GPIOVAR_H__ */

View File

@ -1,323 +0,0 @@
/*-
* Copyright (c) 2016, Hiroki Mori
* Copyright (c) 2009 Oleksandr Tymoshenko
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_ddb.h"
#include "opt_ar531x.h"
#include <sys/param.h>
#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/cons.h>
#include <sys/kdb.h>
#include <sys/reboot.h>
#include <sys/boot.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_page.h>
#include <vm/vm_phys.h>
#include <vm/vm_dumpset.h>
#include <net/ethernet.h>
#include <machine/clock.h>
#include <machine/cpu.h>
#include <machine/cpuregs.h>
#include <machine/hwfunc.h>
#include <machine/md_var.h>
#include <machine/trap.h>
#include <mips/atheros/ar531x/ar5315reg.h>
#include <mips/atheros/ar531x/ar5315_setup.h>
#include <mips/atheros/ar531x/ar5315_cpudef.h>
extern char edata[], end[];
uint32_t ar711_base_mac[ETHER_ADDR_LEN];
/* 4KB static data aread to keep a copy of the bootload env until
the dynamic kenv is setup */
char boot1_env[4096];
void
platform_cpu_init()
{
/* Nothing special */
}
void
platform_reset(void)
{
ar531x_device_reset();
/* Wait for reset */
while(1)
;
}
/*
* Obtain the MAC address via the Redboot environment.
*/
static void
ar5315_redboot_get_macaddr(void)
{
char *var;
int count = 0;
/*
* "ethaddr" is passed via envp on RedBoot platforms
* "kmac" is passed via argv on RouterBOOT platforms
*/
if ((var = kern_getenv("ethaddr")) != NULL ||
(var = kern_getenv("kmac")) != NULL) {
count = sscanf(var, "%x%*c%x%*c%x%*c%x%*c%x%*c%x",
&ar711_base_mac[0], &ar711_base_mac[1],
&ar711_base_mac[2], &ar711_base_mac[3],
&ar711_base_mac[4], &ar711_base_mac[5]);
if (count < 6)
memset(ar711_base_mac, 0,
sizeof(ar711_base_mac));
freeenv(var);
}
}
#if defined(SOC_VENDOR) || defined(SOC_MODEL) || defined(SOC_REV)
static SYSCTL_NODE(_hw, OID_AUTO, soc, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
"System on Chip information");
#endif
#if defined(SOC_VENDOR)
static char hw_soc_vendor[] = SOC_VENDOR;
SYSCTL_STRING(_hw_soc, OID_AUTO, vendor, CTLFLAG_RD, hw_soc_vendor, 0,
"SoC vendor");
#endif
#if defined(SOC_MODEL)
static char hw_soc_model[] = SOC_MODEL;
SYSCTL_STRING(_hw_soc, OID_AUTO, model, CTLFLAG_RD, hw_soc_model, 0,
"SoC model");
#endif
#if defined(SOC_REV)
static char hw_soc_revision[] = SOC_REV;
SYSCTL_STRING(_hw_soc, OID_AUTO, revision, CTLFLAG_RD, hw_soc_revision, 0,
"SoC revision");
#endif
#if defined(DEVICE_VENDOR) || defined(DEVICE_MODEL) || defined(DEVICE_REV)
static SYSCTL_NODE(_hw, OID_AUTO, device, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
"Board information");
#endif
#if defined(DEVICE_VENDOR)
static char hw_device_vendor[] = DEVICE_VENDOR;
SYSCTL_STRING(_hw_device, OID_AUTO, vendor, CTLFLAG_RD, hw_device_vendor, 0,
"Board vendor");
#endif
#if defined(DEVICE_MODEL)
static char hw_device_model[] = DEVICE_MODEL;
SYSCTL_STRING(_hw_device, OID_AUTO, model, CTLFLAG_RD, hw_device_model, 0,
"Board model");
#endif
#if defined(DEVICE_REV)
static char hw_device_revision[] = DEVICE_REV;
SYSCTL_STRING(_hw_device, OID_AUTO, revision, CTLFLAG_RD, hw_device_revision, 0,
"Board revision");
#endif
void
platform_start(__register_t a0 __unused, __register_t a1 __unused,
__register_t a2 __unused, __register_t a3 __unused)
{
uint64_t platform_counter_freq;
int argc = 0, i;
char **argv = NULL;
#ifndef AR531X_ENV_UBOOT
char **envp = NULL;
#endif
vm_offset_t kernend;
/*
* clear the BSS and SBSS segments, this should be first call in
* the function
*/
kernend = (vm_offset_t)&end;
memset(&edata, 0, kernend - (vm_offset_t)(&edata));
mips_postboot_fixup();
/* Initialize pcpu stuff */
mips_pcpu0_init();
/*
* Until some more sensible abstractions for uboot/redboot
* environment handling, we have to make this a compile-time
* hack. The existing code handles the uboot environment
* very incorrectly so we should just ignore initialising
* the relevant pointers.
*/
#ifndef AR531X_ENV_UBOOT
argc = a0;
argv = (char**)a1;
envp = (char**)a2;
#endif
/*
* Protect ourselves from garbage in registers
*/
if (MIPS_IS_VALID_PTR(envp)) {
for (i = 0; envp[i]; i += 2) {
if (strcmp(envp[i], "memsize") == 0)
realmem = btoc(strtoul(envp[i+1], NULL, 16));
}
}
ar5315_detect_sys_type();
// RedBoot SDRAM Detect is missing
// ar531x_detect_mem_size();
/*
* Just wild guess. RedBoot let us down and didn't reported
* memory size
*/
if (realmem == 0)
realmem = btoc(16*1024*1024);
/*
* Allow build-time override in case Redboot lies
* or in other situations (eg where there's u-boot)
* where there isn't (yet) a convienent method of
* being told how much RAM is available.
*
* This happens on at least the Ubiquiti LS-SR71A
* board, where redboot says there's 16mb of RAM
* but in fact there's 32mb.
*/
#if defined(AR531X_REALMEM)
realmem = btoc(AR531X_REALMEM);
#endif
/* phys_avail regions are in bytes */
phys_avail[0] = MIPS_KSEG0_TO_PHYS(kernel_kseg0_end);
phys_avail[1] = ctob(realmem);
dump_avail[0] = phys_avail[0];
dump_avail[1] = phys_avail[1] - phys_avail[0];
physmem = realmem;
/*
* ns8250 uart code uses DELAY so ticker should be inititalized
* before cninit. And tick_init_params refers to hz, so * init_param1
* should be called first.
*/
init_param1();
boothowto |= (RB_SERIAL | RB_MULTIPLE); /* Use multiple consoles */
// boothowto |= RB_VERBOSE;
// boothowto |= (RB_SINGLE);
/* Detect the system type - this is needed for subsequent chipset-specific calls */
ar531x_device_soc_init();
ar531x_detect_sys_frequency();
platform_counter_freq = ar531x_cpu_freq();
mips_timer_init_params(platform_counter_freq, 1);
cninit();
init_static_kenv(boot1_env, sizeof(boot1_env));
printf("CPU platform: %s\n", ar5315_get_system_type());
printf("CPU Frequency=%d MHz\n", ar531x_cpu_freq() / 1000000);
printf("CPU DDR Frequency=%d MHz\n", ar531x_ddr_freq() / 1000000);
printf("CPU AHB Frequency=%d MHz\n", ar531x_ahb_freq() / 1000000);
printf("platform frequency: %lld\n", platform_counter_freq);
printf("arguments: \n");
printf(" a0 = %08x\n", a0);
printf(" a1 = %08x\n", a1);
printf(" a2 = %08x\n", a2);
printf(" a3 = %08x\n", a3);
strcpy(cpu_model, ar5315_get_system_type());
/*
* XXX this code is very redboot specific.
*/
printf("Cmd line:");
if (MIPS_IS_VALID_PTR(argv)) {
for (i = 0; i < argc; i++) {
printf(" %s", argv[i]);
boothowto |= boot_parse_arg(argv[i]);
}
}
else
printf ("argv is invalid");
printf("\n");
printf("Environment:\n");
#if 0
if (MIPS_IS_VALID_PTR(envp)) {
if (envp[0] && strchr(envp[0], '=') ) {
char *env_val; //
for (i = 0; envp[i]; i++) {
env_val = strchr(envp[i], '=');
/* Not sure if we correct to change data, but env in RAM */
*(env_val++) = '\0';
printf("= %s = %s\n", envp[i], env_val);
kern_setenv(envp[i], env_val);
}
} else {
for (i = 0; envp[i]; i+=2) {
printf(" %s = %s\n", envp[i], envp[i+1]);
kern_setenv(envp[i], envp[i+1]);
}
}
}
else
printf ("envp is invalid\n");
#else
printf ("envp skiped\n");
#endif
/* Redboot if_are MAC address is in the environment */
ar5315_redboot_get_macaddr();
init_param2(physmem);
mips_cpu_init();
pmap_bootstrap();
mips_proc0_init();
mutex_init();
ar531x_device_start();
kdb_init();
#ifdef KDB
if (boothowto & RB_KDB)
kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger");
#endif
}

View File

@ -1,160 +0,0 @@
/*-
* Copyright (c) 2016, Hiroki Mori
* Copyright (c) 2010 Adrian Chadd
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_ddb.h"
#include "opt_ar531x.h"
#include <sys/param.h>
#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/cons.h>
#include <sys/kdb.h>
#include <sys/reboot.h>
#include <vm/vm.h>
#include <vm/vm_page.h>
#include <net/ethernet.h>
#include <machine/clock.h>
#include <machine/cpu.h>
#include <machine/cpuregs.h>
#include <machine/hwfunc.h>
#include <machine/md_var.h>
#include <machine/trap.h>
#include <machine/vmparam.h>
#include <mips/atheros/ar531x/ar5315reg.h>
#include <mips/atheros/ar531x/ar5312reg.h>
#include <mips/atheros/ar531x/ar5315_setup.h>
#include <mips/atheros/ar531x/ar5315_cpudef.h>
#include <mips/atheros/ar531x/ar5315_chip.h>
#include <mips/atheros/ar531x/ar5312_chip.h>
#include <mips/atheros/ar724x_chip.h>
#include <mips/atheros/ar91xx_chip.h>
#include <dev/ath/ath_hal/ah_soc.h>
#define AR5315_SYS_TYPE_LEN 128
static char ar5315_sys_type[AR5315_SYS_TYPE_LEN];
enum ar531x_soc_type ar531x_soc;
struct ar5315_cpu_def * ar5315_cpu_ops = NULL;
void
ar5315_detect_sys_type(void)
{
char *chip = "????";
uint32_t ver = 0;
uint32_t rev = 0;
#if 0
const uint8_t *ptr, *end;
static const struct ar531x_boarddata *board = NULL;
ptr = (const uint8_t *) MIPS_PHYS_TO_KSEG1(AR5315_CONFIG_END
- 0x1000);
end = (const uint8_t *)AR5315_CONFIG_BASE;
for (; ptr > end; ptr -= 0x1000) {
if (*(const uint32_t *)ptr == AR531X_BD_MAGIC) {
board = (const struct ar531x_boarddata *) ptr;
rev = board->major;
break;
}
}
#endif
int soctype;
#ifdef AR531X_1ST_GENERATION
soctype = AR_FIRST_GEN;
#else
soctype = AR_SECOND_GEN;
#endif
if(soctype == AR_SECOND_GEN) {
ar5315_cpu_ops = &ar5315_chip_def;
ver = ATH_READ_REG(AR5315_SYSREG_BASE +
AR5315_SYSREG_SREV);
switch (ver) {
case 0x86:
ar531x_soc = AR531X_SOC_AR5315;
chip = "2315";
break;
case 0x87:
ar531x_soc = AR531X_SOC_AR5316;
chip = "2316";
break;
case 0x90:
ar531x_soc = AR531X_SOC_AR5317;
chip = "2317";
break;
case 0x91:
ar531x_soc = AR531X_SOC_AR5318;
chip = "2318";
break;
}
} else {
ar5315_cpu_ops = &ar5312_chip_def;
ver = ATH_READ_REG(AR5312_SYSREG_BASE +
AR5312_SYSREG_REVISION);
rev = AR5312_REVISION_MINOR(ver);
switch (AR5312_REVISION_MAJOR(ver)) {
case AR5312_REVISION_MAJ_AR5311:
ar531x_soc = AR531X_SOC_AR5311;
chip = "5311";
break;
case AR5312_REVISION_MAJ_AR5312:
ar531x_soc = AR531X_SOC_AR5312;
chip = "5312";
break;
case AR5312_REVISION_MAJ_AR2313:
ar531x_soc = AR531X_SOC_AR5313;
chip = "2313";
break;
}
}
sprintf(ar5315_sys_type, "Atheros AR%s rev %u", chip, rev);
}
const char *
ar5315_get_system_type(void)
{
return ar5315_sys_type;
}

View File

@ -1,51 +0,0 @@
/*-
* Copyright (c) 2010 Adrian Chadd
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* $FreeBSD$ */
#ifndef __AR5315_SETUP_H__
#define __AR5315_SETUP_H__
enum ar531x_soc_type {
AR531X_SOC_UNKNOWN,
AR531X_SOC_AR5311,
AR531X_SOC_AR5312,
AR531X_SOC_AR5313,
AR531X_SOC_AR5314,
AR531X_SOC_AR5315,
AR531X_SOC_AR5316,
AR531X_SOC_AR5317,
AR531X_SOC_AR5318,
};
extern enum ar531x_soc_type ar531x_soc;
extern void ar5315_detect_sys_type(void);
extern const char *ar5315_get_system_type(void);
#define AR_FIRST_GEN 1
#define AR_SECOND_GEN 2
#endif

View File

@ -1,290 +0,0 @@
/*-
* Copyright (c) 2016, Hiroki Mori
* Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@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 unmodified, this list of conditions, and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/interrupt.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/rman.h>
#include <sys/sysctl.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <vm/vm_extern.h>
#include <machine/bus.h>
#include <machine/cpu.h>
#include <machine/pmap.h>
#include <dev/spibus/spi.h>
#include <dev/spibus/spibusvar.h>
#include "spibus_if.h"
#include <mips/atheros/ar531x/arspireg.h>
#include <mips/atheros/ar531x/ar5315reg.h>
#undef AR531X_SPI_DEBUG
#ifdef AR531X_SPI_DEBUG
#define dprintf printf
#else
#define dprintf(x, arg...)
#endif
/*
* register space access macros
*/
#define SPI_WRITE(sc, reg, val) do { \
bus_write_4(sc->sc_mem_res, (reg), (val)); \
} while (0)
#define SPI_READ(sc, reg) bus_read_4(sc->sc_mem_res, (reg))
#define SPI_SET_BITS(sc, reg, bits) \
SPI_WRITE(sc, reg, SPI_READ(sc, (reg)) | (bits))
#define SPI_CLEAR_BITS(sc, reg, bits) \
SPI_WRITE(sc, reg, SPI_READ(sc, (reg)) & ~(bits))
struct ar5315_spi_softc {
device_t sc_dev;
struct resource *sc_mem_res;
uint32_t sc_reg_ctrl;
uint32_t sc_debug;
};
static void
ar5315_spi_attach_sysctl(device_t dev)
{
struct ar5315_spi_softc *sc;
struct sysctl_ctx_list *ctx;
struct sysctl_oid *tree;
sc = device_get_softc(dev);
ctx = device_get_sysctl_ctx(dev);
tree = device_get_sysctl_tree(dev);
SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
"debug", CTLFLAG_RW, &sc->sc_debug, 0,
"ar5315_spi debugging flags");
}
static int
ar5315_spi_probe(device_t dev)
{
device_set_desc(dev, "AR5315 SPI");
return (0);
}
static int
ar5315_spi_attach(device_t dev)
{
struct ar5315_spi_softc *sc = device_get_softc(dev);
int rid;
sc->sc_dev = dev;
rid = 0;
sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
RF_ACTIVE);
if (!sc->sc_mem_res) {
device_printf(dev, "Could not map memory\n");
return (ENXIO);
}
device_add_child(dev, "spibus", -1);
ar5315_spi_attach_sysctl(dev);
return (bus_generic_attach(dev));
}
static void
ar5315_spi_chip_activate(struct ar5315_spi_softc *sc, int cs)
{
}
static void
ar5315_spi_chip_deactivate(struct ar5315_spi_softc *sc, int cs)
{
}
static int
ar5315_spi_get_block(off_t offset, caddr_t data, off_t count)
{
int i;
for(i = 0; i < count / 4; ++i) {
*((uint32_t *)data + i) = ATH_READ_REG(AR5315_MEM1_BASE + offset + i * 4);
}
// printf("ar5315_spi_get_blockr: %x %x %x\n",
// (int)offset, (int)count, *(uint32_t *)data);
return (0);
}
static int
ar5315_spi_transfer(device_t dev, device_t child, struct spi_command *cmd)
{
struct ar5315_spi_softc *sc;
uint8_t *buf_in, *buf_out;
int lin, lout;
uint32_t ctl, cnt, op, rdat, cs;
int i, j;
sc = device_get_softc(dev);
if (sc->sc_debug & 0x8000)
printf("ar5315_spi_transfer: CMD ");
spibus_get_cs(child, &cs);
cs &= ~SPIBUS_CS_HIGH;
/* Open SPI controller interface */
ar5315_spi_chip_activate(sc, cs);
do {
ctl = SPI_READ(sc, ARSPI_REG_CTL);
} while (ctl & ARSPI_CTL_BUSY);
/*
* Transfer command
*/
buf_out = (uint8_t *)cmd->tx_cmd;
op = buf_out[0];
if(op == 0x0b) {
int offset = buf_out[1] << 16 | buf_out[2] << 8 | buf_out[3];
ar5315_spi_get_block(offset, cmd->rx_data, cmd->rx_data_sz);
return (0);
}
do {
ctl = SPI_READ(sc, ARSPI_REG_CTL);
} while (ctl & ARSPI_CTL_BUSY);
if (sc->sc_debug & 0x8000) {
printf("%08x ", op);
printf("tx_cmd_sz=%d rx_cmd_sz=%d ", cmd->tx_cmd_sz,
cmd->rx_cmd_sz);
if(cmd->tx_cmd_sz != 1) {
printf("%08x ", *((uint32_t *)cmd->tx_cmd));
printf("%08x ", *((uint32_t *)cmd->tx_cmd + 1));
}
}
SPI_WRITE(sc, ARSPI_REG_OPCODE, op);
/* clear all of the tx and rx bits */
ctl &= ~(ARSPI_CTL_TXCNT_MASK | ARSPI_CTL_RXCNT_MASK);
/* now set txcnt */
cnt = 1;
ctl |= (cnt << ARSPI_CTL_TXCNT_SHIFT);
cnt = 24;
/* now set txcnt */
if(cmd->rx_cmd_sz < 24)
cnt = cmd->rx_cmd_sz;
ctl |= (cnt << ARSPI_CTL_RXCNT_SHIFT);
ctl |= ARSPI_CTL_START;
SPI_WRITE(sc, ARSPI_REG_CTL, ctl);
if(op == 0x0b)
SPI_WRITE(sc, ARSPI_REG_DATA, 0);
if (sc->sc_debug & 0x8000)
printf("\nDATA ");
/*
* Receive/transmit data (depends on command)
*/
// buf_out = (uint8_t *)cmd->tx_data;
buf_in = (uint8_t *)cmd->rx_cmd;
// lout = cmd->tx_data_sz;
lin = cmd->rx_cmd_sz;
if (sc->sc_debug & 0x8000)
printf("t%d r%d ", lout, lin);
for(i = 0; i <= (cnt - 1) / 4; ++i) {
do {
ctl = SPI_READ(sc, ARSPI_REG_CTL);
} while (ctl & ARSPI_CTL_BUSY);
rdat = SPI_READ(sc, ARSPI_REG_DATA);
if (sc->sc_debug & 0x8000)
printf("I%08x ", rdat);
for(j = 0; j < 4; ++j) {
buf_in[i * 4 + j + 1] = 0xff & (rdat >> (8 * j));
if(i * 4 + j + 2 == cnt)
break;
}
}
ar5315_spi_chip_deactivate(sc, cs);
/*
* Close SPI controller interface, restore flash memory mapped access.
*/
if (sc->sc_debug & 0x8000)
printf("\n");
return (0);
}
static int
ar5315_spi_detach(device_t dev)
{
struct ar5315_spi_softc *sc = device_get_softc(dev);
if (sc->sc_mem_res)
bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
return (0);
}
static device_method_t ar5315_spi_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, ar5315_spi_probe),
DEVMETHOD(device_attach, ar5315_spi_attach),
DEVMETHOD(device_detach, ar5315_spi_detach),
DEVMETHOD(spibus_transfer, ar5315_spi_transfer),
// DEVMETHOD(spibus_get_block, ar5315_spi_get_block),
DEVMETHOD_END
};
static driver_t ar5315_spi_driver = {
"spi",
ar5315_spi_methods,
sizeof(struct ar5315_spi_softc),
};
static devclass_t ar5315_spi_devclass;
DRIVER_MODULE(ar5315_spi, nexus, ar5315_spi_driver, ar5315_spi_devclass, 0, 0);

View File

@ -1,150 +0,0 @@
/*-
* Copyright (c) 2016, Hiroki Mori
* Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@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 unmodified, 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.
*/
/*
* Watchdog driver for AR5315
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/watchdog.h>
#include <sys/bus.h>
#include <sys/eventhandler.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/sysctl.h>
#include <mips/atheros/ar531x/ar5315reg.h>
#include <mips/atheros/ar531x/ar5315_cpudef.h>
struct ar5315_wdog_softc {
device_t dev;
int armed;
int reboot_from_watchdog;
int debug;
};
static void
ar5315_wdog_watchdog_fn(void *private, u_int cmd, int *error)
{
struct ar5315_wdog_softc *sc = private;
uint64_t timer_val;
cmd &= WD_INTERVAL;
if (sc->debug)
device_printf(sc->dev, "ar5315_wdog_watchdog_fn: cmd: %x\n", cmd);
if (cmd > 0) {
timer_val = (uint64_t)(1ULL << cmd) * ar531x_ahb_freq() /
1000000000;
if (sc->debug)
device_printf(sc->dev, "ar5315_wdog_watchdog_fn: programming timer: %jx\n", (uintmax_t) timer_val);
/*
* Load timer with large enough value to prevent spurious
* reset
*/
ATH_WRITE_REG(ar531x_wdog_timer(),
ar531x_ahb_freq() * 10);
ATH_WRITE_REG(ar531x_wdog_ctl(),
AR5315_WDOG_CTL_RESET);
ATH_WRITE_REG(ar531x_wdog_timer(),
(timer_val & 0xffffffff));
sc->armed = 1;
*error = 0;
} else {
if (sc->debug)
device_printf(sc->dev, "ar5315_wdog_watchdog_fn: disarming\n");
if (sc->armed) {
ATH_WRITE_REG(ar531x_wdog_ctl(),
AR5315_WDOG_CTL_IGNORE);
sc->armed = 0;
}
}
}
static int
ar5315_wdog_probe(device_t dev)
{
device_set_desc(dev, "Atheros AR531x watchdog timer");
return (0);
}
static void
ar5315_wdog_sysctl(device_t dev)
{
struct ar5315_wdog_softc *sc = device_get_softc(dev);
struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->dev);
struct sysctl_oid *tree = device_get_sysctl_tree(sc->dev);
SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
"debug", CTLFLAG_RW, &sc->debug, 0,
"enable watchdog debugging");
SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
"armed", CTLFLAG_RD, &sc->armed, 0,
"whether the watchdog is armed");
SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
"reboot_from_watchdog", CTLFLAG_RD, &sc->reboot_from_watchdog, 0,
"whether the system rebooted from the watchdog");
}
static int
ar5315_wdog_attach(device_t dev)
{
struct ar5315_wdog_softc *sc = device_get_softc(dev);
/* Initialise */
sc->reboot_from_watchdog = 0;
sc->armed = 0;
sc->debug = 0;
ATH_WRITE_REG(ar531x_wdog_ctl(), AR5315_WDOG_CTL_IGNORE);
sc->dev = dev;
EVENTHANDLER_REGISTER(watchdog_list, ar5315_wdog_watchdog_fn, sc, 0);
ar5315_wdog_sysctl(dev);
return (0);
}
static device_method_t ar5315_wdog_methods[] = {
DEVMETHOD(device_probe, ar5315_wdog_probe),
DEVMETHOD(device_attach, ar5315_wdog_attach),
DEVMETHOD_END
};
static driver_t ar5315_wdog_driver = {
"ar5315_wdog",
ar5315_wdog_methods,
sizeof(struct ar5315_wdog_softc),
};
static devclass_t ar5315_wdog_devclass;
DRIVER_MODULE(ar5315_wdog, apb, ar5315_wdog_driver, ar5315_wdog_devclass, 0, 0);

View File

@ -1,244 +0,0 @@
/* $Id: ar5315reg.h,v 1.3 2011/07/07 05:06:44 matt Exp $ */
/*
* Copyright (c) 2006 Urbana-Champaign Independent Media Center.
* Copyright (c) 2006 Garrett D'Amore.
* All rights reserved.
*
* This code was written by Garrett D'Amore for the Champaign-Urbana
* Community Wireless Network Project.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgements:
* This product includes software developed by the Urbana-Champaign
* Independent Media Center.
* This product includes software developed by Garrett D'Amore.
* 4. Urbana-Champaign Independent Media Center's name and Garrett
* D'Amore's name may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE URBANA-CHAMPAIGN INDEPENDENT
* MEDIA CENTER AND GARRETT D'AMORE ``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 URBANA-CHAMPAIGN INDEPENDENT
* MEDIA CENTER OR GARRETT D'AMORE BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef _MIPS_ATHEROS_AR5315REG_H_
#define _MIPS_ATHEROS_AR5315REG_H_
#define AR5315_MEM0_BASE 0x00000000 /* sdram */
#define AR5315_MEM1_BASE 0x08000000 /* spi flash */
#define AR5315_WLAN_BASE 0x10000000
#define AR5315_PCI_BASE 0x10100000
#define AR5315_SDRAMCTL_BASE 0x10300000
#define AR5315_LOCAL_BASE 0x10400000 /* local bus */
#define AR5315_ENET_BASE 0x10500000
#define AR5315_SYSREG_BASE 0x11000000
#define AR5315_UART_BASE 0x11100000
#define AR5315_SPI_BASE 0x11300000 /* spi flash */
#define AR5315_BOOTROM_BASE 0x1FC00000 /* boot rom */
#define AR5315_CONFIG_BASE 0x087D0000 /* flash start */
#define AR5315_CONFIG_END 0x087FF000 /* flash end */
#define AR5315_RADIO_END 0x1FFFF000 /* radio end */
#if 0
#define AR5315_PCIEXT_BASE 0x80000000 /* pci external */
#define AR5315_RAM2_BASE 0xc0000000
#define AR5315_RAM3_BASE 0xe0000000
#endif
/*
* SYSREG registers -- offset relative to AR531X_SYSREG_BASE
*/
#define AR5315_SYSREG_COLDRESET 0x0000
#define AR5315_SYSREG_RESETCTL 0x0004
#define AR5315_SYSREG_AHB_ARB_CTL 0x0008
#define AR5315_SYSREG_ENDIAN 0x000c
#define AR5315_SYSREG_NMI_CTL 0x0010
#define AR5315_SYSREG_SREV 0x0014
#define AR5315_SYSREG_IF_CTL 0x0018
#define AR5315_SYSREG_MISC_INTSTAT 0x0020
#define AR5315_SYSREG_MISC_INTMASK 0x0024
#define AR5315_SYSREG_GISR 0x0028
#define AR5315_SYSREG_TIMER 0x0030
#define AR5315_SYSREG_RELOAD 0x0034
#define AR5315_SYSREG_WDOG_TIMER 0x0038
#define AR5315_SYSREG_WDOG_CTL 0x003c
#define AR5315_SYSREG_PERFCNT0 0x0048
#define AR5315_SYSREG_PERFCNT1 0x004c
#define AR5315_SYSREG_AHB_ERR0 0x0050
#define AR5315_SYSREG_AHB_ERR1 0x0054
#define AR5315_SYSREG_AHB_ERR2 0x0058
#define AR5315_SYSREG_AHB_ERR3 0x005c
#define AR5315_SYSREG_AHB_ERR4 0x0060
#define AR5315_SYSREG_PLLC_CTL 0x0064
#define AR5315_SYSREG_PLLV_CTL 0x0068
#define AR5315_SYSREG_CPUCLK 0x006c
#define AR5315_SYSREG_AMBACLK 0x0070
#define AR5315_SYSREG_SYNCCLK 0x0074
#define AR5315_SYSREG_DSL_SLEEP_CTL 0x0080
#define AR5315_SYSREG_DSL_SLEEP_DUR 0x0084
#define AR5315_SYSREG_GPIO_DI 0x0088
#define AR5315_SYSREG_GPIO_DO 0x0090
#define AR5315_SYSREG_GPIO_CR 0x0098
#define AR5315_SYSREG_GPIO_INT 0x00a0
#define AR5315_GPIO_PINS 23
/* Cold resets (AR5315_SYSREG_COLDRESET) */
#define AR5315_COLD_AHB 0x00000001
#define AR5315_COLD_APB 0x00000002
#define AR5315_COLD_CPU 0x00000004
#define AR5315_COLD_CPU_WARM 0x00000008
/* Resets (AR5315_SYSREG_RESETCTL) */
#define AR5315_RESET_WARM_WLAN0_MAC 0x00000001
#define AR5315_RESET_WARM_WLAN0_BB 0x00000002
#define AR5315_RESET_MPEGTS 0x00000004 /* MPEG-TS */
#define AR5315_RESET_PCIDMA 0x00000008 /* PCI dma */
#define AR5315_RESET_MEMCTL 0x00000010
#define AR5315_RESET_LOCAL 0x00000020 /* local bus */
#define AR5315_RESET_I2C 0x00000040 /* i2c */
#define AR5315_RESET_SPI 0x00000080 /* SPI */
#define AR5315_RESET_UART 0x00000100
#define AR5315_RESET_IR 0x00000200 /* infrared */
#define AR5315_RESET_PHY0 0x00000400 /* enet phy */
#define AR5315_RESET_ENET0 0x00000800
/* Watchdog control (AR5315_SYSREG_WDOG_CTL) */
#define AR5315_WDOG_CTL_IGNORE 0x0000
#define AR5315_WDOG_CTL_NMI 0x0001
#define AR5315_WDOG_CTL_RESET 0x0002
/* AR5315 AHB arbitration control (AR5315_SYSREG_AHB_ARB_CTL) */
#define AR5315_ARB_CPU 0x00001
#define AR5315_ARB_WLAN 0x00002
#define AR5315_ARB_MPEGTS 0x00004
#define AR5315_ARB_LOCAL 0x00008
#define AR5315_ARB_PCI 0x00010
#define AR5315_ARB_ENET 0x00020
#define AR5315_ARB_RETRY 0x00100
/* AR5315 endianness control (AR5315_SYSREG_ENDIAN) */
#define AR5315_ENDIAN_AHB 0x00001
#define AR5315_ENDIAN_WLAN 0x00002
#define AR5315_ENDIAN_MPEGTS 0x00004
#define AR5315_ENDIAN_PCI 0x00008
#define AR5315_ENDIAN_MEMCTL 0x00010
#define AR5315_ENDIAN_LOCAL 0x00020
#define AR5315_ENDIAN_ENET 0x00040
#define AR5315_ENDIAN_MERGE 0x00200
#define AR5315_ENDIAN_CPU 0x00400
#define AR5315_ENDIAN_PCIAHB 0x00800
#define AR5315_ENDIAN_PCIAHB_BRIDGE 0x01000
#define AR5315_ENDIAN_SPI 0x08000
#define AR5315_ENDIAN_CPU_DRAM 0x10000
#define AR5315_ENDIAN_CPU_PCI 0x20000
#define AR5315_ENDIAN_CPU_MMR 0x40000
/* AR5315 AHB error bits */
#define AR5315_AHB_ERROR_DET 1 /* error detected */
#define AR5315_AHB_ERROR_OVR 2 /* AHB overflow */
#define AR5315_AHB_ERROR_WDT 4 /* wdt (not hresp) */
/* AR5315 clocks */
#define AR5315_PLLC_REF_DIV(reg) ((reg) & 0x3)
#define AR5315_PLLC_FB_DIV(reg) (((reg) & 0x7c) >> 2)
#define AR5315_PLLC_DIV_2(reg) (((reg) & 0x80) >> 7)
#define AR5315_PLLC_CLKC(reg) (((reg) & 0x1c000) >> 14)
#define AR5315_PLLC_CLKM(reg) (((reg) & 0x700000) >> 20)
#define AR5315_CLOCKCTL_SELECT(reg) ((reg) & 0x3)
#define AR5315_CLOCKCTL_DIV(reg) (((reg) & 0xc) >> 2)
/*
* SDRAMCTL registers -- offset relative to SDRAMCTL
*/
#define AR5315_SDRAMCTL_MEM_CFG 0x0000
#define AR5315_MEM_CFG_DATA_WIDTH __BITS(13,14)
#define AR5315_MEM_CFG_COL_WIDTH __BITS(9,12)
#define AR5315_MEM_CFG_ROW_WIDTH __BITS(5,8)
/* memory config 1 bits */
#define AR531X_MEM_CFG1_BANK0 __BITS(8,10)
#define AR531X_MEM_CFG1_BANK1 __BITS(12,14)
/*
* PCI configuration stuff. I don't pretend to fully understand these
* registers, they seem to be magic numbers in the Linux code.
*/
#define AR5315_PCI_MAC_RC 0x4000
#define AR5315_PCI_MAC_SCR 0x4004
#define AR5315_PCI_MAC_INTPEND 0x4008
#define AR5315_PCI_MAC_SFR 0x400c
#define AR5315_PCI_MAC_PCICFG 0x4010
#define AR5315_PCI_MAC_SREV 0x4020
#define PCI_MAC_RC_MAC 0x1
#define PCI_MAC_RC_BB 0x2
#define PCI_MAC_SCR_SLM_MASK 0x00030000
#define PCI_MAC_SCR_SLM_FWAKE 0x00000000
#define PCI_MAC_SCR_SLM_FSLEEP 0x00010000
#define PCI_MAC_SCR_SLM_NORMAL 0x00020000
#define PCI_MAC_PCICFG_SPWR_DN 0x00010000
/* IRQS */
#define AR5315_CPU_IRQ_MISC 0
#define AR5315_CPU_IRQ_WLAN 1
#define AR5315_CPU_IRQ_ENET 2
#define AR5315_MISC_IRQ_UART 0
#define AR5315_MISC_IRQ_I2C 1
#define AR5315_MISC_IRQ_SPI 2
#define AR5315_MISC_IRQ_AHBE 3
#define AR5315_MISC_IRQ_AHPE 4
#define AR5315_MISC_IRQ_TIMER 5
#define AR5315_MISC_IRQ_GPIO 6
#define AR5315_MISC_IRQ_WDOG 7
#define AR5315_MISC_IRQ_IR 8
#define AR5315_APB_BASE AR5315_SYSREG_BASE
#define AR5315_APB_SIZE 0x06000000
#define ATH_READ_REG(reg) \
*((volatile uint32_t *)MIPS_PHYS_TO_KSEG1((reg)))
#define ATH_WRITE_REG(reg, val) \
*((volatile uint32_t *)MIPS_PHYS_TO_KSEG1((reg))) = (val)
/* Helpers from NetBSD cdefs.h */
/* __BIT(n): nth bit, where __BIT(0) == 0x1. */
#define __BIT(__n) \
(((__n) >= NBBY * sizeof(uintmax_t)) ? 0 : ((uintmax_t)1 << (__n)))
/* __BITS(m, n): bits m through n, m < n. */
#define __BITS(__m, __n) \
((__BIT(MAX((__m), (__n)) + 1) - 1) ^ (__BIT(MIN((__m), (__n))) - 1))
/* find least significant bit that is set */
#define __LOWEST_SET_BIT(__mask) ((((__mask) - 1) & (__mask)) ^ (__mask))
#define __SHIFTOUT(__x, __mask) (((__x) & (__mask)) / __LOWEST_SET_BIT(__mask))
#define __SHIFTOUT_MASK(__mask) __SHIFTOUT((__mask), (__mask))
#endif /* _MIPS_ATHEROS_AR531XREG_H_ */

View File

@ -1,62 +0,0 @@
/* $NetBSD: arspireg.h,v 1.1 2006/10/14 15:33:23 gdamore Exp $ */
/*-
* Copyright (c) 2006 Urbana-Champaign Independent Media Center.
* Copyright (c) 2006 Garrett D'Amore.
* All rights reserved.
*
* Portions of this code were written by Garrett D'Amore for the
* Champaign-Urbana Community Wireless Network Project.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgements:
* This product includes software developed by the Urbana-Champaign
* Independent Media Center.
* This product includes software developed by Garrett D'Amore.
* 4. Urbana-Champaign Independent Media Center's name and Garrett
* D'Amore's name may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE URBANA-CHAMPAIGN INDEPENDENT
* MEDIA CENTER AND GARRETT D'AMORE ``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 URBANA-CHAMPAIGN INDEPENDENT
* MEDIA CENTER OR GARRETT D'AMORE BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef _MIPS_ATHEROS_DEV_ARSPIREG_H
#define _MIPS_ATHEROS_DEV_ARSPIREG_H
#define ARSPI_REG_CTL 0x00
#define ARSPI_REG_OPCODE 0x04
#define ARSPI_REG_DATA 0x08
#define ARSPI_CTL_START 0x00000100
#define ARSPI_CTL_BUSY 0x00010000
#define ARSPI_CTL_TXCNT_MASK 0x0000000f
#define ARSPI_CTL_TXCNT_SHIFT 0
#define ARSPI_CTL_RXCNT_MASK 0x000000f0
#define ARSPI_CTL_RXCNT_SHIFT 4
#define ARSPI_CTL_SIZE_MASK 0x00060000
#define ARSPI_CTL_CLKSEL_MASK 0x03000000
#endif /* _MIPS_ATHEROS_DEV_ARSPIREG_H */

View File

@ -1,20 +0,0 @@
# $FreeBSD$
mips/atheros/ar531x/apb.c standard
mips/atheros/ar531x/if_are.c optional are
mips/atheros/ar531x/ar5315_spi.c optional ar5315_spi
mips/atheros/ar531x/ar5315_wdog.c optional ar5315_wdog
mips/atheros/ar531x/ar5315_gpio.c optional gpio
mips/atheros/ar531x/ar5315_machdep.c standard
mips/atheros/ar531x/ar5315_chip.c standard
mips/atheros/ar531x/ar5315_setup.c standard
mips/atheros/ar531x/uart_bus_ar5315.c optional uart_ar5315
mips/atheros/ar531x/uart_cpu_ar5315.c optional uart_ar5315
mips/atheros/ar531x/ar5312_chip.c standard
mips/atheros/ar71xx_bus_space_reversed.c standard
mips/mips/tick.c standard
# Non Intrng
mips/mips/intr_machdep.c optional !intrng

File diff suppressed because it is too large Load Diff

View File

@ -1,401 +0,0 @@
/*-
* Copyright (C) 2007
* Oleksandr Tymoshenko <gonzo@freebsd.org>. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES 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 MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*
*/
#ifndef __IF_AREREG_H__
#define __IF_AREREG_H__
struct are_desc {
uint32_t are_stat;
uint32_t are_devcs;
uint32_t are_addr;
uint32_t are_link;
};
#define ARE_DMASIZE(len) ((len) & ((1 << 11)-1))
#define ARE_PKTSIZE(len) ((len & 0xffff0000) >> 16)
#define ARE_RX_RING_CNT 128
#define ARE_TX_RING_CNT 128
#define ARE_TX_RING_SIZE sizeof(struct are_desc) * ARE_TX_RING_CNT
#define ARE_RX_RING_SIZE sizeof(struct are_desc) * ARE_RX_RING_CNT
#define ARE_MIN_FRAMELEN 60
#define ARE_RING_ALIGN sizeof(struct are_desc)
#define ARE_RX_ALIGN sizeof(uint32_t)
#define ARE_MAXFRAGS 8
#define ARE_TX_INTR_THRESH 8
#define ARE_TX_RING_ADDR(sc, i) \
((sc)->are_rdata.are_tx_ring_paddr + sizeof(struct are_desc) * (i))
#define ARE_RX_RING_ADDR(sc, i) \
((sc)->are_rdata.are_rx_ring_paddr + sizeof(struct are_desc) * (i))
#define ARE_INC(x,y) (x) = (((x) + 1) % y)
struct are_txdesc {
struct mbuf *tx_m;
bus_dmamap_t tx_dmamap;
};
struct are_rxdesc {
struct mbuf *rx_m;
bus_dmamap_t rx_dmamap;
struct are_desc *desc;
/* Use this values on error instead of allocating new mbuf */
uint32_t saved_ctl, saved_ca;
};
struct are_chain_data {
bus_dma_tag_t are_parent_tag;
bus_dma_tag_t are_tx_tag;
struct are_txdesc are_txdesc[ARE_TX_RING_CNT];
bus_dma_tag_t are_rx_tag;
struct are_rxdesc are_rxdesc[ARE_RX_RING_CNT];
bus_dma_tag_t are_tx_ring_tag;
bus_dma_tag_t are_rx_ring_tag;
bus_dmamap_t are_tx_ring_map;
bus_dmamap_t are_rx_ring_map;
bus_dmamap_t are_rx_sparemap;
int are_tx_pkts;
int are_tx_prod;
int are_tx_cons;
int are_tx_cnt;
int are_rx_cons;
};
struct are_ring_data {
struct are_desc *are_rx_ring;
struct are_desc *are_tx_ring;
bus_addr_t are_rx_ring_paddr;
bus_addr_t are_tx_ring_paddr;
};
struct are_softc {
struct ifnet *are_ifp; /* interface info */
bus_space_handle_t are_bhandle; /* bus space handle */
bus_space_tag_t are_btag; /* bus space tag */
device_t are_dev;
uint8_t are_eaddr[ETHER_ADDR_LEN];
struct resource *are_res;
int are_rid;
struct resource *are_irq;
void *are_intrhand;
u_int32_t sc_inten; /* copy of CSR_INTEN */
u_int32_t sc_rxint_mask; /* mask of Rx interrupts we want */
u_int32_t sc_txint_mask; /* mask of Tx interrupts we want */
#ifdef ARE_MII
device_t are_miibus;
#else
struct ifmedia are_ifmedia;
#endif
#ifdef ARE_MDIO
device_t are_miiproxy;
#endif
bus_dma_tag_t are_parent_tag;
bus_dma_tag_t are_tag;
struct mtx are_mtx;
struct callout are_stat_callout;
struct task are_link_task;
struct are_chain_data are_cdata;
struct are_ring_data are_rdata;
int are_link_status;
int are_detach;
int are_if_flags; /* last if flags */
};
#define ARE_LOCK(_sc) mtx_lock(&(_sc)->are_mtx)
#define ARE_UNLOCK(_sc) mtx_unlock(&(_sc)->are_mtx)
#define ARE_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->are_mtx, MA_OWNED)
/*
* register space access macros
*/
#define CSR_WRITE_4(sc, reg, val) \
bus_space_write_4(sc->are_btag, sc->are_bhandle, reg, val)
#define CSR_READ_4(sc, reg) \
bus_space_read_4(sc->are_btag, sc->are_bhandle, reg)
/* $NetBSD: aereg.h,v 1.2 2008/04/28 20:23:28 martin Exp $ */
/*-
* Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
* NASA Ames Research Center.
*
* 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
*/
/*
* Descriptor Status bits common to transmit and receive.
*/
#define ADSTAT_OWN 0x80000000 /* Tulip owns descriptor */
#define ADSTAT_ES 0x00008000 /* Error Summary */
/*
* Descriptor Status bits for Receive Descriptor.
*/
#define ADSTAT_Rx_FF 0x40000000 /* Filtering Fail */
#define ADSTAT_Rx_FL 0x3fff0000 /* Frame Length including CRC */
#define ADSTAT_Rx_DE 0x00004000 /* Descriptor Error */
#define ADSTAT_Rx_LE 0x00001000 /* Length Error */
#define ADSTAT_Rx_RF 0x00000800 /* Runt Frame */
#define ADSTAT_Rx_MF 0x00000400 /* Multicast Frame */
#define ADSTAT_Rx_FS 0x00000200 /* First Descriptor */
#define ADSTAT_Rx_LS 0x00000100 /* Last Descriptor */
#define ADSTAT_Rx_TL 0x00000080 /* Frame Too Long */
#define ADSTAT_Rx_CS 0x00000040 /* Collision Seen */
#define ADSTAT_Rx_RT 0x00000020 /* Frame Type */
#define ADSTAT_Rx_RW 0x00000010 /* Receive Watchdog */
#define ADSTAT_Rx_RE 0x00000008 /* Report on MII Error */
#define ADSTAT_Rx_DB 0x00000004 /* Dribbling Bit */
#define ADSTAT_Rx_CE 0x00000002 /* CRC Error */
#define ADSTAT_Rx_ZER 0x00000001 /* Zero (always 0) */
#define ADSTAT_Rx_LENGTH(x) (((x) & ADSTAT_Rx_FL) >> 16)
/*
* Descriptor Status bits for Transmit Descriptor.
*/
#define ADSTAT_Tx_ES 0x00008000 /* Error Summary */
#define ADSTAT_Tx_TO 0x00004000 /* Transmit Jabber Timeout */
#define ADSTAT_Tx_LO 0x00000800 /* Loss of Carrier */
#define ADSTAT_Tx_NC 0x00000400 /* No Carrier */
#define ADSTAT_Tx_LC 0x00000200 /* Late Collision */
#define ADSTAT_Tx_EC 0x00000100 /* Excessive Collisions */
#define ADSTAT_Tx_HF 0x00000080 /* Heartbeat Fail */
#define ADSTAT_Tx_CC 0x00000078 /* Collision Count */
#define ADSTAT_Tx_ED 0x00000004 /* Excessive Deferral */
#define ADSTAT_Tx_UF 0x00000002 /* Underflow Error */
#define ADSTAT_Tx_DE 0x00000001 /* Deferred */
#define ADSTAT_Tx_COLLISIONS(x) (((x) & ADSTAT_Tx_CC) >> 3)
/*
* Descriptor Control bits common to transmit and receive.
*/
#define ADCTL_SIZE1 0x000007ff /* Size of buffer 1 */
#define ADCTL_SIZE1_SHIFT 0
#define ADCTL_SIZE2 0x003ff800 /* Size of buffer 2 */
#define ADCTL_SIZE2_SHIFT 11
#define ADCTL_ER 0x02000000 /* End of Ring */
#define ADCTL_CH 0x01000000 /* Second Address Chained */
/*
* Descriptor Control bits for Transmit Descriptor.
*/
#define ADCTL_Tx_IC 0x80000000 /* Interrupt on Completion */
#define ADCTL_Tx_LS 0x40000000 /* Last Segment */
#define ADCTL_Tx_FS 0x20000000 /* First Segment */
#define ADCTL_Tx_AC 0x04000000 /* Add CRC Disable */
#define ADCTL_Tx_DPD 0x00800000 /* Disabled Padding */
/*
* Control registers.
*/
/* tese are registers only found on this part */
#define CSR_MACCTL 0x0000 /* mac control */
#define CSR_MACHI 0x0004
#define CSR_MACLO 0x0008
#define CSR_HTHI 0x000C /* multicast table high */
#define CSR_HTLO 0x0010 /* multicast table low */
#define CSR_MIIADDR 0x0014 /* mii address */
#define CSR_MIIDATA 0x0018 /* mii data */
#define CSR_FLOWC 0x001C /* flow control */
#define CSR_VL1 0x0020 /* vlan 1 tag */
/* these are more or less normal Tulip registers */
#define CSR_BUSMODE 0x1000 /* bus mode */
#define CSR_TXPOLL 0x1004 /* tx poll demand */
#define CSR_RXPOLL 0x1008 /* rx poll demand */
#define CSR_RXLIST 0x100C /* rx base descriptor address */
#define CSR_TXLIST 0x1010 /* tx base descriptor address */
#define CSR_STATUS 0x1014 /* (interrupt) status */
#define CSR_OPMODE 0x1018 /* operation mode */
#define CSR_INTEN 0x101C /* interrupt enable */
#define CSR_MISSED 0x1020 /* missed frame counter */
#define CSR_HTBA 0x1050 /* host tx buffer address (ro) */
#define CSR_HRBA 0x1054 /* host rx buffer address (ro) */
/* CSR_MACCTL - Mac Control */
#define MACCTL_RE 0x00000004 /* rx enable */
#define MACCTL_TE 0x00000008 /* tx enable */
#define MACCTL_DC 0x00000020 /* deferral check */
#define MACCTL_PSTR 0x00000100 /* automatic pad strip */
#define MACCTL_DTRY 0x00000400 /* disable retry */
#define MACCTL_DBF 0x00000800 /* disable broadcast frames */
#define MACCTL_LCC 0x00001000 /* late collision control */
#define MACCTL_HASH 0x00002000 /* hash filtering enable */
#define MACCTL_HO 0x00008000 /* disable perfect filtering */
#define MACCTL_PB 0x00010000 /* pass bad frames */
#define MACCTL_IF 0x00020000 /* inverse filtering */
#define MACCTL_PR 0x00040000 /* promiscuous mode */
#define MACCTL_PM 0x00080000 /* pass all multicast */
#define MACCTL_FDX 0x00100000 /* full duplex mode */
#define MACCTL_LOOP 0x00600000 /* loopback mask */
#define MACCTL_LOOP_INT 0x00200000 /* internal loopback */
#define MACCTL_LOOP_EXT 0x00400000 /* external loopback */
#define MACCTL_LOOP_NONE 0x00000000
#define MACCTL_DRO 0x00800000 /* disable receive own */
#define MACCTL_PS 0x08000000 /* port select, 0 = mii */
#define MACCTL_HBD 0x10000000 /* heartbeat disable */
#define MACCTL_BLE 0x40000000 /* mac big endian */
#define MACCTL_RA 0x80000000 /* receive all packets */
/* CSR_MIIADDR - MII Addess */
#define MIIADDR_BUSY 0x00000001 /* mii busy */
#define MIIADDR_WRITE 0x00000002 /* mii write */
#define MIIADDR_REG_MASK 0x000007C0 /* mii register */
#define MIIADDR_REG_SHIFT 6
#define MIIADDR_PHY_MASK 0x0000F800 /* mii phy */
#define MIIADDR_PHY_SHIFT 11
#define MIIADDR_GETREG(x) (((x) & MIIADDR_REG) >> 6)
#define MIIADDR_PUTREG(x) (((x) << 6) & MIIADR_REG)
#define MIIADDR_GETPHY(x) (((x) & MIIADDR_PHY) >> 11)
#define MIIADDR_PUTPHY(x) (((x) << 6) & MIIADR_PHY)
/* CSR_FLOWC - Flow Control */
#define FLOWC_FCB 0x00000001 /* flow control busy */
#define FLOWC_FCE 0x00000002 /* flow control enable */
#define FLOWC_PCF 0x00000004 /* pass control frames */
#define FLOWC_PT 0xffff0000 /* pause time */
/* CSR_BUSMODE - Bus Mode */
#define BUSMODE_SWR 0x00000001 /* software reset */
#define BUSMODE_BAR 0x00000002 /* bus arbitration */
#define BUSMODE_DSL 0x0000007c /* descriptor skip length */
#define BUSMODE_BLE 0x00000080 /* data buf endian */
/* programmable burst length */
#define BUSMODE_PBL_DEFAULT 0x00000000 /* default value */
#define BUSMODE_PBL_1LW 0x00000100 /* 1 longword */
#define BUSMODE_PBL_2LW 0x00000200 /* 2 longwords */
#define BUSMODE_PBL_4LW 0x00000400 /* 4 longwords */
#define BUSMODE_PBL_8LW 0x00000800 /* 8 longwords */
#define BUSMODE_PBL_16LW 0x00001000 /* 16 longwords */
#define BUSMODE_PBL_32LW 0x00002000 /* 32 longwords */
#define BUSMODE_DBO 0x00100000 /* descriptor endian */
#define BUSMODE_ALIGN_16B 0x01000000 /* force oddhw rx buf align */
/* CSR_TXPOLL - Transmit Poll Demand */
#define TXPOLL_TPD 0x00000001 /* transmit poll demand */
/* CSR_RXPOLL - Receive Poll Demand */
#define RXPOLL_RPD 0x00000001 /* receive poll demand */
/* CSR_STATUS - Status */
#define STATUS_TI 0x00000001 /* transmit interrupt */
#define STATUS_TPS 0x00000002 /* transmit process stopped */
#define STATUS_TU 0x00000004 /* transmit buffer unavail */
#define STATUS_TJT 0x00000008 /* transmit jabber timeout */
#define STATUS_UNF 0x00000020 /* transmit underflow */
#define STATUS_RI 0x00000040 /* receive interrupt */
#define STATUS_RU 0x00000080 /* receive buffer unavail */
#define STATUS_RPS 0x00000100 /* receive process stopped */
#define STATUS_ETI 0x00000400 /* early transmit interrupt */
#define STATUS_SE 0x00002000 /* system error */
#define STATUS_ER 0x00004000 /* early receive (21041) */
#define STATUS_AIS 0x00008000 /* abnormal intr summary */
#define STATUS_NIS 0x00010000 /* normal interrupt summary */
#define STATUS_RS 0x000e0000 /* receive process state */
#define STATUS_RS_STOPPED 0x00000000 /* Stopped */
#define STATUS_RS_FETCH 0x00020000 /* Running - fetch receive
descriptor */
#define STATUS_RS_CHECK 0x00040000 /* Running - check for end
of receive */
#define STATUS_RS_WAIT 0x00060000 /* Running - wait for packet */
#define STATUS_RS_SUSPENDED 0x00080000 /* Suspended */
#define STATUS_RS_CLOSE 0x000a0000 /* Running - close receive
descriptor */
#define STATUS_RS_FLUSH 0x000c0000 /* Running - flush current
frame from FIFO */
#define STATUS_RS_QUEUE 0x000e0000 /* Running - queue current
frame from FIFO into
buffer */
#define STATUS_TS 0x00700000 /* transmit process state */
#define STATUS_TS_STOPPED 0x00000000 /* Stopped */
#define STATUS_TS_FETCH 0x00100000 /* Running - fetch transmit
descriptor */
#define STATUS_TS_WAIT 0x00200000 /* Running - wait for end
of transmission */
#define STATUS_TS_READING 0x00300000 /* Running - read buffer from
memory and queue into
FIFO */
#define STATUS_TS_SUSPENDED 0x00600000 /* Suspended */
#define STATUS_TS_CLOSE 0x00700000 /* Running - close transmit
descriptor */
#define STATUS_TX_ABORT 0x00800000 /* Transmit bus abort */
#define STATUS_RX_ABORT 0x01000000 /* Transmit bus abort */
/* CSR_OPMODE - Operation Mode */
#define OPMODE_SR 0x00000002 /* start receive */
#define OPMODE_OSF 0x00000004 /* operate on second frame */
#define OPMODE_ST 0x00002000 /* start transmitter */
#define OPMODE_TR 0x0000c000 /* threshold control */
#define OPMODE_TR_32 0x00000000 /* 32 words */
#define OPMODE_TR_64 0x00004000 /* 64 words */
#define OPMODE_TR_128 0x00008000 /* 128 words */
#define OPMODE_TR_256 0x0000c000 /* 256 words */
#define OPMODE_SF 0x00200000 /* store and forward mode */
/* CSR_INTEN - Interrupt Enable */
/* See bits for CSR_STATUS -- Status */
/* CSR_MISSED - Missed Frames */
#define MISSED_MFC 0xffff0000 /* missed packet count */
#define MISSED_FOC 0x0000ffff /* fifo overflow counter */
#define MISSED_GETMFC(x) ((x) & MISSED_MFC)
#define MISSED_GETFOC(x) (((x) & MISSED_FOC) >> 16)
#endif /* __IF_AREREG_H__ */

View File

@ -1,89 +0,0 @@
/*-
* Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
*/
#include "opt_uart.h"
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <machine/bus.h>
#include <dev/uart/uart.h>
#include <dev/uart/uart_cpu.h>
#include <dev/uart/uart_bus.h>
#include <mips/atheros/ar531x/ar5315reg.h>
#include <mips/atheros/ar531x/ar5315_cpudef.h>
#include "uart_if.h"
static int uart_ar5315_probe(device_t dev);
extern struct uart_class uart_ar5315_uart_class;
static device_method_t uart_ar5315_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, uart_ar5315_probe),
DEVMETHOD(device_attach, uart_bus_attach),
DEVMETHOD(device_detach, uart_bus_detach),
DEVMETHOD_END
};
static driver_t uart_ar5315_driver = {
uart_driver_name,
uart_ar5315_methods,
sizeof(struct uart_softc),
};
extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs;
static int
uart_ar5315_probe(device_t dev)
{
struct uart_softc *sc;
uint64_t freq;
freq = ar531x_ahb_freq();
sc = device_get_softc(dev);
sc->sc_sysdev = SLIST_FIRST(&uart_sysdevs);
sc->sc_class = &uart_ns8250_class;
bcopy(&sc->sc_sysdev->bas, &sc->sc_bas, sizeof(sc->sc_bas));
sc->sc_sysdev->bas.regshft = 2;
sc->sc_sysdev->bas.bst = mips_bus_space_generic;
sc->sc_sysdev->bas.bsh = ar531x_uart_addr() + 3;
sc->sc_bas.regshft = 2;
sc->sc_bas.bst = mips_bus_space_generic;
sc->sc_bas.bsh = ar531x_uart_addr() + 3;
return (uart_bus_probe(dev, 2, 0, freq, 0, 0, 0));
}
DRIVER_MODULE(uart, apb, uart_ar5315_driver, uart_devclass, 0, 0);

View File

@ -1,76 +0,0 @@
/*-
* Copyright (c) 2009 Oleksandr Tymoshenko
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include "opt_uart.h"
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <machine/bus.h>
#include <dev/uart/uart.h>
#include <dev/uart/uart_cpu.h>
#include <mips/atheros/ar531x/ar5315reg.h>
#include <mips/atheros/ar531x/ar5315_cpudef.h>
#include <mips/atheros/ar71xx_bus_space_reversed.h>
bus_space_tag_t uart_bus_space_io;
bus_space_tag_t uart_bus_space_mem;
int
uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2)
{
return ((b1->bsh == b2->bsh && b1->bst == b2->bst) ? 1 : 0);
}
int
uart_cpu_getdev(int devtype, struct uart_devinfo *di)
{
uint64_t freq;
freq = ar531x_ahb_freq();
di->ops = uart_getops(&uart_ns8250_class);
di->bas.chan = 0;
di->bas.bst = ar71xx_bus_space_reversed;
di->bas.regshft = 2;
di->bas.rclk = freq;
di->baudrate = 9600; // RedBoot default is 9600
di->databits = 8;
di->stopbits = 1;
di->parity = UART_PARITY_NONE;
uart_bus_space_io = NULL;
uart_bus_space_mem = ar71xx_bus_space_reversed;
di->bas.bsh = ar531x_uart_addr();
return (0);
}

View File

@ -1,183 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@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 unmodified, this list of conditions, and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <machine/bus.h>
#include <mips/atheros/ar71xx_bus_space_reversed.h>
static bs_r_1_proto(reversed);
static bs_r_2_proto(reversed);
static bs_w_1_proto(reversed);
static bs_w_2_proto(reversed);
/*
* Bus space that handles offsets in word for 1/2 bytes read/write access.
* Byte order of values is handled by device drivers itself.
*/
static struct bus_space bus_space_reversed = {
/* cookie */
(void *) 0,
/* mapping/unmapping */
generic_bs_map,
generic_bs_unmap,
generic_bs_subregion,
/* allocation/deallocation */
NULL,
NULL,
/* barrier */
generic_bs_barrier,
/* read (single) */
reversed_bs_r_1,
reversed_bs_r_2,
generic_bs_r_4,
NULL,
/* read multiple */
generic_bs_rm_1,
generic_bs_rm_2,
generic_bs_rm_4,
NULL,
/* read region */
generic_bs_rr_1,
generic_bs_rr_2,
generic_bs_rr_4,
NULL,
/* write (single) */
reversed_bs_w_1,
reversed_bs_w_2,
generic_bs_w_4,
NULL,
/* write multiple */
generic_bs_wm_1,
generic_bs_wm_2,
generic_bs_wm_4,
NULL,
/* write region */
NULL,
generic_bs_wr_2,
generic_bs_wr_4,
NULL,
/* set multiple */
NULL,
NULL,
NULL,
NULL,
/* set region */
NULL,
generic_bs_sr_2,
generic_bs_sr_4,
NULL,
/* copy */
NULL,
generic_bs_c_2,
NULL,
NULL,
/* read (single) stream */
generic_bs_r_1,
generic_bs_r_2,
generic_bs_r_4,
NULL,
/* read multiple stream */
generic_bs_rm_1,
generic_bs_rm_2,
generic_bs_rm_4,
NULL,
/* read region stream */
generic_bs_rr_1,
generic_bs_rr_2,
generic_bs_rr_4,
NULL,
/* write (single) stream */
generic_bs_w_1,
generic_bs_w_2,
generic_bs_w_4,
NULL,
/* write multiple stream */
generic_bs_wm_1,
generic_bs_wm_2,
generic_bs_wm_4,
NULL,
/* write region stream */
NULL,
generic_bs_wr_2,
generic_bs_wr_4,
NULL,
};
bus_space_tag_t ar71xx_bus_space_reversed = &bus_space_reversed;
static uint8_t
reversed_bs_r_1(void *t, bus_space_handle_t h, bus_size_t o)
{
return readb(h + (o &~ 3) + (3 - (o & 3)));
}
static void
reversed_bs_w_1(void *t, bus_space_handle_t h, bus_size_t o, u_int8_t v)
{
writeb(h + (o &~ 3) + (3 - (o & 3)), v);
}
static uint16_t
reversed_bs_r_2(void *t, bus_space_handle_t h, bus_size_t o)
{
return readw(h + (o &~ 3) + (2 - (o & 3)));
}
static void
reversed_bs_w_2(void *t, bus_space_handle_t h, bus_size_t o, uint16_t v)
{
writew(h + (o &~ 3) + (2 - (o & 3)), v);
}

View File

@ -1,37 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@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 unmodified, this list of conditions, and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef __AR71XX_BUS_SPACE_REVERSEDH__
#define __AR71XX_BUS_SPACE_REVERSEDH__
extern bus_space_tag_t ar71xx_bus_space_reversed;
#endif /* __AR71XX_BUS_SPACE_REVERSEDH__ */

View File

@ -1,176 +0,0 @@
/*-
* Copyright (c) 2017, Adrian Chadd <adrian@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 unmodified, this list of conditions, and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_ar71xx.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/interrupt.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/rman.h>
#include <sys/lock.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <vm/vm_extern.h>
#include <machine/bus.h>
#include <machine/cpu.h>
#include <machine/intr_machdep.h>
#include <sys/linker.h>
#include <sys/firmware.h>
struct ar71xx_caldata_softc {
device_t sc_dev;
};
static int
ar71xx_caldata_probe(device_t dev)
{
return (BUS_PROBE_NOWILDCARD);
}
/* XXX TODO: unify with what's in ar71xx_fixup.c */
/*
* Create a calibration block from memory mapped SPI data for use by
* various drivers. Right now it's just ath(4) but later board support
* will include 802.11ac NICs with calibration data in NOR flash.
*
* (Yes, there are a handful of QCA MIPS boards with QCA9880v2 802.11ac chips
* with calibration data in flash..)
*/
static void
ar71xx_platform_create_cal_data(device_t dev, int id, long int flash_addr,
int size)
{
char buf[64];
uint16_t *cal_data = (uint16_t *) MIPS_PHYS_TO_KSEG1(flash_addr);
void *eeprom = NULL;
const struct firmware *fw = NULL;
device_printf(dev, "EEPROM firmware: 0x%lx @ %d bytes\n",
flash_addr, size);
eeprom = malloc(size, M_DEVBUF, M_WAITOK | M_ZERO);
if (! eeprom) {
device_printf(dev, "%s: malloc failed for '%s', aborting EEPROM\n",
__func__, buf);
return;
}
memcpy(eeprom, cal_data, size);
/*
* Generate a flash EEPROM 'firmware' from the given memory
* region. Since the SPI controller will eventually
* go into port-IO mode instead of memory-mapped IO
* mode, a copy of the EEPROM contents is required.
*/
snprintf(buf, sizeof(buf), "%s.%d.map.%d.eeprom_firmware",
device_get_name(dev),
device_get_unit(dev),
id);
fw = firmware_register(buf, eeprom, size, 1, NULL);
if (fw == NULL) {
device_printf(dev, "%s: firmware_register (%s) failed\n",
__func__, buf);
free(eeprom, M_DEVBUF);
return;
}
device_printf(dev, "device EEPROM '%s' registered\n", buf);
}
/*
* Iterate through a list of early-boot hints creating calibration
* data firmware chunks for AHB (ie, non-PCI) devices with calibration
* data.
*/
static int
ar71xx_platform_check_eeprom_hints(device_t dev)
{
char buf[64];
long int addr;
int size;
int i;
for (i = 0; i < 8; i++) {
snprintf(buf, sizeof(buf), "map.%d.ath_fixup_addr", i);
if (resource_long_value(device_get_name(dev),
device_get_unit(dev), buf, &addr) != 0)
break;
snprintf(buf, sizeof(buf), "map.%d.ath_fixup_size", i);
if (resource_int_value(device_get_name(dev),
device_get_unit(dev), buf, &size) != 0)
break;
device_printf(dev, "map.%d.ath_fixup_addr=0x%08x; size=%d\n",
i, (int) addr, size);
(void) ar71xx_platform_create_cal_data(dev, i, addr, size);
}
return (0);
}
static int
ar71xx_caldata_attach(device_t dev)
{
device_add_child(dev, "nexus", -1);
ar71xx_platform_check_eeprom_hints(dev);
return (bus_generic_attach(dev));
}
static device_method_t ar71xx_caldata_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, ar71xx_caldata_probe),
DEVMETHOD(device_attach, ar71xx_caldata_attach),
DEVMETHOD(device_shutdown, bus_generic_shutdown),
DEVMETHOD(device_suspend, bus_generic_suspend),
DEVMETHOD(device_resume, bus_generic_resume),
DEVMETHOD_END
};
static driver_t ar71xx_caldata_driver = {
"ar71xx_caldata",
ar71xx_caldata_methods,
sizeof(struct ar71xx_caldata_softc),
};
static devclass_t ar71xx_caldata_devclass;
DRIVER_MODULE(ar71xx_caldata, nexus, ar71xx_caldata_driver, ar71xx_caldata_devclass, 0, 0);

View File

@ -1,339 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2010 Adrian Chadd
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_ddb.h"
#include <sys/param.h>
#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/cons.h>
#include <sys/kdb.h>
#include <sys/reboot.h>
#include <vm/vm.h>
#include <vm/vm_page.h>
#include <net/ethernet.h>
#include <machine/clock.h>
#include <machine/cpu.h>
#include <machine/cpuregs.h>
#include <machine/hwfunc.h>
#include <machine/md_var.h>
#include <machine/trap.h>
#include <machine/vmparam.h>
#include <mips/atheros/ar71xxreg.h>
#include <mips/atheros/ar71xx_chip.h>
#include <mips/atheros/ar71xx_cpudef.h>
/* XXX these should replace the current definitions in ar71xxreg.h */
/* XXX perhaps an ar71xx_chip.h header file? */
#define AR71XX_PLL_REG_CPU_CONFIG AR71XX_PLL_CPU_BASE + 0x00
#define AR71XX_PLL_REG_SEC_CONFIG AR71XX_PLL_CPU_BASE + 0x04
#define AR71XX_PLL_REG_ETH0_INT_CLOCK AR71XX_PLL_CPU_BASE + 0x10
#define AR71XX_PLL_REG_ETH1_INT_CLOCK AR71XX_PLL_CPU_BASE + 0x14
#define AR71XX_PLL_DIV_SHIFT 3
#define AR71XX_PLL_DIV_MASK 0x1f
#define AR71XX_CPU_DIV_SHIFT 16
#define AR71XX_CPU_DIV_MASK 0x3
#define AR71XX_DDR_DIV_SHIFT 18
#define AR71XX_DDR_DIV_MASK 0x3
#define AR71XX_AHB_DIV_SHIFT 20
#define AR71XX_AHB_DIV_MASK 0x7
/* XXX these shouldn't be in here - this file is a per-chip file */
/* XXX these should be in the top-level ar71xx type, not ar71xx -chip */
uint32_t u_ar71xx_cpu_freq;
uint32_t u_ar71xx_ahb_freq;
uint32_t u_ar71xx_ddr_freq;
uint32_t u_ar71xx_uart_freq;
uint32_t u_ar71xx_wdt_freq;
uint32_t u_ar71xx_refclk;
uint32_t u_ar71xx_mdio_freq;
static void
ar71xx_chip_detect_mem_size(void)
{
}
static void
ar71xx_chip_detect_sys_frequency(void)
{
uint32_t pll;
uint32_t freq;
uint32_t div;
u_ar71xx_mdio_freq = u_ar71xx_refclk = AR71XX_BASE_FREQ;
pll = ATH_READ_REG(AR71XX_PLL_REG_CPU_CONFIG);
div = ((pll >> AR71XX_PLL_DIV_SHIFT) & AR71XX_PLL_DIV_MASK) + 1;
freq = div * AR71XX_BASE_FREQ;
div = ((pll >> AR71XX_CPU_DIV_SHIFT) & AR71XX_CPU_DIV_MASK) + 1;
u_ar71xx_cpu_freq = freq / div;
div = ((pll >> AR71XX_DDR_DIV_SHIFT) & AR71XX_DDR_DIV_MASK) + 1;
u_ar71xx_ddr_freq = freq / div;
div = (((pll >> AR71XX_AHB_DIV_SHIFT) & AR71XX_AHB_DIV_MASK) + 1) * 2;
u_ar71xx_ahb_freq = u_ar71xx_cpu_freq / div;
u_ar71xx_wdt_freq = u_ar71xx_cpu_freq / div;
u_ar71xx_uart_freq = u_ar71xx_cpu_freq / div;
}
/*
* This does not lock the CPU whilst doing the work!
*/
static void
ar71xx_chip_device_stop(uint32_t mask)
{
uint32_t reg;
reg = ATH_READ_REG(AR71XX_RST_RESET);
ATH_WRITE_REG(AR71XX_RST_RESET, reg | mask);
}
static void
ar71xx_chip_device_start(uint32_t mask)
{
uint32_t reg;
reg = ATH_READ_REG(AR71XX_RST_RESET);
ATH_WRITE_REG(AR71XX_RST_RESET, reg & ~mask);
}
static int
ar71xx_chip_device_stopped(uint32_t mask)
{
uint32_t reg;
reg = ATH_READ_REG(AR71XX_RST_RESET);
return ((reg & mask) == mask);
}
void
ar71xx_chip_set_mii_speed(uint32_t unit, uint32_t speed)
{
uint32_t val, reg, ctrl;
switch (unit) {
case 0:
reg = AR71XX_MII0_CTRL;
break;
case 1:
reg = AR71XX_MII1_CTRL;
break;
default:
printf("%s: invalid MII unit set for arge unit: %d\n",
__func__, unit);
return;
}
switch (speed) {
case 10:
ctrl = MII_CTRL_SPEED_10;
break;
case 100:
ctrl = MII_CTRL_SPEED_100;
break;
case 1000:
ctrl = MII_CTRL_SPEED_1000;
break;
default:
printf("%s: invalid MII speed (%d) set for arge unit: %d\n",
__func__, speed, unit);
return;
}
val = ATH_READ_REG(reg);
val &= ~(MII_CTRL_SPEED_MASK << MII_CTRL_SPEED_SHIFT);
val |= (ctrl & MII_CTRL_SPEED_MASK) << MII_CTRL_SPEED_SHIFT;
ATH_WRITE_REG(reg, val);
}
void
ar71xx_chip_set_mii_if(uint32_t unit, uint32_t mii_mode)
{
uint32_t val, reg, mii_if;
switch (unit) {
case 0:
reg = AR71XX_MII0_CTRL;
if (mii_mode == AR71XX_MII_MODE_GMII)
mii_if = MII0_CTRL_IF_GMII;
else if (mii_mode == AR71XX_MII_MODE_MII)
mii_if = MII0_CTRL_IF_MII;
else if (mii_mode == AR71XX_MII_MODE_RGMII)
mii_if = MII0_CTRL_IF_RGMII;
else if (mii_mode == AR71XX_MII_MODE_RMII)
mii_if = MII0_CTRL_IF_RMII;
else {
printf("%s: invalid MII mode (%d) for unit %d\n",
__func__, mii_mode, unit);
return;
}
break;
case 1:
reg = AR71XX_MII1_CTRL;
if (mii_mode == AR71XX_MII_MODE_RGMII)
mii_if = MII1_CTRL_IF_RGMII;
else if (mii_mode == AR71XX_MII_MODE_RMII)
mii_if = MII1_CTRL_IF_RMII;
else {
printf("%s: invalid MII mode (%d) for unit %d\n",
__func__, mii_mode, unit);
return;
}
break;
default:
printf("%s: invalid MII unit set for arge unit: %d\n",
__func__, unit);
return;
}
val = ATH_READ_REG(reg);
val &= ~(MII_CTRL_IF_MASK << MII_CTRL_IF_SHIFT);
val |= (mii_if & MII_CTRL_IF_MASK) << MII_CTRL_IF_SHIFT;
ATH_WRITE_REG(reg, val);
}
/* Speed is either 10, 100 or 1000 */
static void
ar71xx_chip_set_pll_ge(int unit, int speed, uint32_t pll)
{
switch (unit) {
case 0:
ar71xx_write_pll(AR71XX_PLL_SEC_CONFIG,
AR71XX_PLL_ETH_INT0_CLK, pll,
AR71XX_PLL_ETH0_SHIFT);
break;
case 1:
ar71xx_write_pll(AR71XX_PLL_SEC_CONFIG,
AR71XX_PLL_ETH_INT1_CLK, pll,
AR71XX_PLL_ETH1_SHIFT);
break;
default:
printf("%s: invalid PLL set for arge unit: %d\n",
__func__, unit);
return;
}
}
static void
ar71xx_chip_ddr_flush(ar71xx_flush_ddr_id_t id)
{
switch (id) {
case AR71XX_CPU_DDR_FLUSH_GE0:
ar71xx_ddr_flush(AR71XX_WB_FLUSH_GE0);
break;
case AR71XX_CPU_DDR_FLUSH_GE1:
ar71xx_ddr_flush(AR71XX_WB_FLUSH_GE1);
break;
case AR71XX_CPU_DDR_FLUSH_USB:
ar71xx_ddr_flush(AR71XX_WB_FLUSH_USB);
break;
case AR71XX_CPU_DDR_FLUSH_PCIE:
ar71xx_ddr_flush(AR71XX_WB_FLUSH_PCI);
break;
default:
printf("%s: invalid DDR flush id (%d)\n", __func__, id);
break;
}
}
static uint32_t
ar71xx_chip_get_eth_pll(unsigned int mac, int speed)
{
uint32_t pll;
switch (speed) {
case 10:
pll = PLL_ETH_INT_CLK_10;
break;
case 100:
pll = PLL_ETH_INT_CLK_100;
break;
case 1000:
pll = PLL_ETH_INT_CLK_1000;
break;
default:
printf("%s%d: invalid speed %d\n", __func__, mac, speed);
pll = 0;
}
return (pll);
}
static void
ar71xx_chip_init_usb_peripheral(void)
{
ar71xx_device_stop(RST_RESET_USB_OHCI_DLL |
RST_RESET_USB_HOST | RST_RESET_USB_PHY);
DELAY(1000);
ar71xx_device_start(RST_RESET_USB_OHCI_DLL |
RST_RESET_USB_HOST | RST_RESET_USB_PHY);
DELAY(1000);
ATH_WRITE_REG(AR71XX_USB_CTRL_CONFIG,
USB_CTRL_CONFIG_OHCI_DES_SWAP |
USB_CTRL_CONFIG_OHCI_BUF_SWAP |
USB_CTRL_CONFIG_EHCI_DES_SWAP |
USB_CTRL_CONFIG_EHCI_BUF_SWAP);
ATH_WRITE_REG(AR71XX_USB_CTRL_FLADJ,
(32 << USB_CTRL_FLADJ_HOST_SHIFT) |
(3 << USB_CTRL_FLADJ_A5_SHIFT));
DELAY(1000);
}
struct ar71xx_cpu_def ar71xx_chip_def = {
&ar71xx_chip_detect_mem_size,
&ar71xx_chip_detect_sys_frequency,
&ar71xx_chip_device_stop,
&ar71xx_chip_device_start,
&ar71xx_chip_device_stopped,
&ar71xx_chip_set_pll_ge,
&ar71xx_chip_set_mii_speed,
&ar71xx_chip_set_mii_if,
&ar71xx_chip_get_eth_pll,
&ar71xx_chip_ddr_flush,
&ar71xx_chip_init_usb_peripheral,
};

View File

@ -1,38 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2010 Adrian Chadd
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* $FreeBSD$ */
#ifndef __AR71XX_CHIP_H__
#define __AR71XX_CHIP_H__
extern struct ar71xx_cpu_def ar71xx_chip_def;
extern void ar71xx_chip_set_mii_speed(uint32_t unit, uint32_t speed);
extern void ar71xx_chip_set_mii_if(uint32_t unit, uint32_t mii_if);
#endif

View File

@ -1,182 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2010 Adrian Chadd
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* $FreeBSD$ */
#ifndef __AR71XX_CPUDEF_H__
#define __AR71XX_CPUDEF_H__
typedef enum {
AR71XX_CPU_DDR_FLUSH_GE0,
AR71XX_CPU_DDR_FLUSH_GE1,
AR71XX_CPU_DDR_FLUSH_USB,
AR71XX_CPU_DDR_FLUSH_PCIE,
AR71XX_CPU_DDR_FLUSH_WMAC,
AR71XX_CPU_DDR_FLUSH_PCIE_EP,
AR71XX_CPU_DDR_FLUSH_CHECKSUM,
} ar71xx_flush_ddr_id_t;
struct ar71xx_cpu_def {
void (* detect_mem_size) (void);
void (* detect_sys_frequency) (void);
void (* ar71xx_chip_device_stop) (uint32_t);
void (* ar71xx_chip_device_start) (uint32_t);
int (* ar71xx_chip_device_stopped) (uint32_t);
void (* ar71xx_chip_set_pll_ge) (int, int, uint32_t);
void (* ar71xx_chip_set_mii_speed) (uint32_t, uint32_t);
void (* ar71xx_chip_set_mii_if) (uint32_t, ar71xx_mii_mode);
uint32_t (* ar71xx_chip_get_eth_pll) (unsigned int, int);
/*
* From Linux - Handling this IRQ is a bit special.
* AR71xx - AR71XX_DDR_REG_FLUSH_PCI
* AR724x - AR724X_DDR_REG_FLUSH_PCIE
* AR91xx - AR91XX_DDR_REG_FLUSH_WMAC
*
* These are set when STATUSF_IP2 is set in regiser c0.
* This flush is done before the IRQ is handled to make
* sure the driver correctly sees any memory updates.
*/
void (* ar71xx_chip_ddr_flush) (ar71xx_flush_ddr_id_t id);
/*
* The USB peripheral init code is subtly different for
* each chip.
*/
void (* ar71xx_chip_init_usb_peripheral) (void);
void (* ar71xx_chip_reset_ethernet_switch) (void);
void (* ar71xx_chip_reset_wmac) (void);
void (* ar71xx_chip_init_gmac) (void);
void (* ar71xx_chip_reset_nfc) (int);
void (* ar71xx_chip_gpio_out_configure) (int, uint8_t);
};
extern struct ar71xx_cpu_def * ar71xx_cpu_ops;
static inline void ar71xx_detect_sys_frequency(void)
{
ar71xx_cpu_ops->detect_sys_frequency();
}
static inline void ar71xx_device_stop(uint32_t mask)
{
ar71xx_cpu_ops->ar71xx_chip_device_stop(mask);
}
static inline void ar71xx_device_start(uint32_t mask)
{
ar71xx_cpu_ops->ar71xx_chip_device_start(mask);
}
static inline int ar71xx_device_stopped(uint32_t mask)
{
return ar71xx_cpu_ops->ar71xx_chip_device_stopped(mask);
}
static inline void ar71xx_device_set_pll_ge(int unit, int speed, uint32_t pll)
{
ar71xx_cpu_ops->ar71xx_chip_set_pll_ge(unit, speed, pll);
}
static inline void ar71xx_device_set_mii_speed(int unit, int speed)
{
ar71xx_cpu_ops->ar71xx_chip_set_mii_speed(unit, speed);
}
static inline void ar71xx_device_set_mii_if(int unit, ar71xx_mii_mode mii_cfg)
{
ar71xx_cpu_ops->ar71xx_chip_set_mii_if(unit, mii_cfg);
}
static inline void ar71xx_device_flush_ddr(ar71xx_flush_ddr_id_t id)
{
ar71xx_cpu_ops->ar71xx_chip_ddr_flush(id);
}
static inline uint32_t ar71xx_device_get_eth_pll(unsigned int unit, int speed)
{
return (ar71xx_cpu_ops->ar71xx_chip_get_eth_pll(unit, speed));
}
static inline void ar71xx_init_usb_peripheral(void)
{
ar71xx_cpu_ops->ar71xx_chip_init_usb_peripheral();
}
static inline void ar71xx_reset_ethernet_switch(void)
{
if (ar71xx_cpu_ops->ar71xx_chip_reset_ethernet_switch)
ar71xx_cpu_ops->ar71xx_chip_reset_ethernet_switch();
}
static inline void ar71xx_reset_wmac(void)
{
if (ar71xx_cpu_ops->ar71xx_chip_reset_wmac)
ar71xx_cpu_ops->ar71xx_chip_reset_wmac();
}
static inline void ar71xx_init_gmac(void)
{
if (ar71xx_cpu_ops->ar71xx_chip_init_gmac)
ar71xx_cpu_ops->ar71xx_chip_init_gmac();
}
static inline void ar71xx_reset_nfc(int active)
{
if (ar71xx_cpu_ops->ar71xx_chip_reset_nfc)
ar71xx_cpu_ops->ar71xx_chip_reset_nfc(active);
}
static inline void ar71xx_gpio_ouput_configure(int gpio, uint8_t func)
{
if (ar71xx_cpu_ops->ar71xx_chip_gpio_out_configure)
ar71xx_cpu_ops->ar71xx_chip_gpio_out_configure(gpio, func);
}
/* XXX shouldn't be here! */
extern uint32_t u_ar71xx_refclk;
extern uint32_t u_ar71xx_cpu_freq;
extern uint32_t u_ar71xx_ahb_freq;
extern uint32_t u_ar71xx_ddr_freq;
extern uint32_t u_ar71xx_uart_freq;
extern uint32_t u_ar71xx_wdt_freq;
extern uint32_t u_ar71xx_mdio_freq;
static inline uint64_t ar71xx_refclk(void) { return u_ar71xx_refclk; }
static inline uint64_t ar71xx_cpu_freq(void) { return u_ar71xx_cpu_freq; }
static inline uint64_t ar71xx_ahb_freq(void) { return u_ar71xx_ahb_freq; }
static inline uint64_t ar71xx_ddr_freq(void) { return u_ar71xx_ddr_freq; }
static inline uint64_t ar71xx_uart_freq(void) { return u_ar71xx_uart_freq; }
static inline uint64_t ar71xx_wdt_freq(void) { return u_ar71xx_wdt_freq; }
static inline uint64_t ar71xx_mdio_freq(void) { return u_ar71xx_mdio_freq; }
#endif

View File

@ -1,293 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2008 Sam Leffler. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* AR71XX attachment driver for the USB Enhanced Host Controller.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_bus.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/rman.h>
#include <sys/condvar.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <machine/bus.h>
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
#include <dev/usb/usb_core.h>
#include <dev/usb/usb_busdma.h>
#include <dev/usb/usb_process.h>
#include <dev/usb/usb_util.h>
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
#include <dev/usb/controller/ehci.h>
#include <dev/usb/controller/ehcireg.h>
#include <mips/atheros/ar71xx_setup.h>
#include <mips/atheros/ar71xxreg.h> /* for stuff in ar71xx_cpudef.h */
#include <mips/atheros/ar71xx_cpudef.h>
#include <mips/atheros/ar71xx_bus_space_reversed.h>
#define EHCI_HC_DEVSTR "AR71XX Integrated USB 2.0 controller"
#define EHCI_USBMODE 0x68 /* USB Device mode register */
#define EHCI_UM_CM 0x00000003 /* R/WO Controller Mode */
#define EHCI_UM_CM_HOST 0x3 /* Host Controller */
struct ar71xx_ehci_softc {
ehci_softc_t base; /* storage for EHCI code */
};
static device_attach_t ar71xx_ehci_attach;
static device_detach_t ar71xx_ehci_detach;
bs_r_1_proto(reversed);
bs_w_1_proto(reversed);
static void
ar71xx_ehci_post_reset(struct ehci_softc *ehci_softc)
{
uint32_t usbmode;
/* Force HOST mode */
usbmode = EOREAD4(ehci_softc, EHCI_USBMODE_NOLPM);
usbmode &= ~EHCI_UM_CM;
usbmode |= EHCI_UM_CM_HOST;
EOWRITE4(ehci_softc, EHCI_USBMODE_NOLPM, usbmode);
}
static int
ar71xx_ehci_probe(device_t self)
{
device_set_desc(self, EHCI_HC_DEVSTR);
return (BUS_PROBE_NOWILDCARD);
}
static void
ar71xx_ehci_intr(void *arg)
{
/* XXX TODO: should really see if this was our interrupt.. */
ar71xx_device_flush_ddr(AR71XX_CPU_DDR_FLUSH_USB);
ehci_interrupt(arg);
}
static int
ar71xx_ehci_attach(device_t self)
{
struct ar71xx_ehci_softc *isc = device_get_softc(self);
ehci_softc_t *sc = &isc->base;
int err;
int rid;
/* initialise some bus fields */
sc->sc_bus.parent = self;
sc->sc_bus.devices = sc->sc_devices;
sc->sc_bus.devices_max = EHCI_MAX_DEVICES;
sc->sc_bus.dma_bits = 32;
/* get all DMA memory */
if (usb_bus_mem_alloc_all(&sc->sc_bus,
USB_GET_DMA_TAG(self), &ehci_iterate_hw_softc)) {
return (ENOMEM);
}
sc->sc_bus.usbrev = USB_REV_2_0;
/* NB: hints fix the memory location and irq */
rid = 0;
sc->sc_io_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, RF_ACTIVE);
if (!sc->sc_io_res) {
device_printf(self, "Could not map memory\n");
goto error;
}
/*
* Craft special resource for bus space ops that handle
* byte-alignment of non-word addresses.
*/
sc->sc_io_tag = ar71xx_bus_space_reversed;
sc->sc_io_hdl = rman_get_bushandle(sc->sc_io_res);
sc->sc_io_size = rman_get_size(sc->sc_io_res);
rid = 0;
sc->sc_irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid,
RF_ACTIVE | RF_SHAREABLE);
if (sc->sc_irq_res == NULL) {
device_printf(self, "Could not allocate irq\n");
goto error;
}
sc->sc_bus.bdev = device_add_child(self, "usbus", -1);
if (!sc->sc_bus.bdev) {
device_printf(self, "Could not add USB device\n");
goto error;
}
device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus);
device_set_desc(sc->sc_bus.bdev, EHCI_HC_DEVSTR);
sprintf(sc->sc_vendor, "Atheros");
err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
NULL, ar71xx_ehci_intr, sc, &sc->sc_intr_hdl);
if (err) {
device_printf(self, "Could not setup irq, %d\n", err);
sc->sc_intr_hdl = NULL;
goto error;
}
/*
* Arrange to force Host mode, select big-endian byte alignment,
* and arrange to not terminate reset operations (the adapter
* will ignore it if we do but might as well save a reg write).
* Also, the controller has an embedded Transaction Translator
* which means port speed must be read from the Port Status
* register following a port enable.
*/
sc->sc_flags = 0;
sc->sc_vendor_post_reset = ar71xx_ehci_post_reset;
switch (ar71xx_soc) {
case AR71XX_SOC_AR7241:
case AR71XX_SOC_AR7242:
case AR71XX_SOC_AR9130:
case AR71XX_SOC_AR9132:
case AR71XX_SOC_AR9330:
case AR71XX_SOC_AR9331:
case AR71XX_SOC_AR9341:
case AR71XX_SOC_AR9342:
case AR71XX_SOC_AR9344:
case AR71XX_SOC_QCA9533:
case AR71XX_SOC_QCA9533_V2:
case AR71XX_SOC_QCA9556:
case AR71XX_SOC_QCA9558:
sc->sc_flags |= EHCI_SCFLG_TT | EHCI_SCFLG_NORESTERM;
sc->sc_vendor_get_port_speed =
ehci_get_port_speed_portsc;
break;
default:
/* fallthrough */
break;
}
/*
* ehci_reset() needs the correct offset to access the host controller
* registers. The AR724x/AR913x offsets aren't 0.
*/
sc->sc_offs = EHCI_CAPLENGTH(EREAD4(sc, EHCI_CAPLEN_HCIVERSION));
(void) ehci_reset(sc);
err = ehci_init(sc);
if (!err) {
err = device_probe_and_attach(sc->sc_bus.bdev);
}
if (err) {
device_printf(self, "USB init failed err=%d\n", err);
goto error;
}
return (0);
error:
ar71xx_ehci_detach(self);
return (ENXIO);
}
static int
ar71xx_ehci_detach(device_t self)
{
struct ar71xx_ehci_softc *isc = device_get_softc(self);
ehci_softc_t *sc = &isc->base;
int err;
/* during module unload there are lots of children leftover */
device_delete_children(self);
if (sc->sc_irq_res && sc->sc_intr_hdl) {
/*
* only call ehci_detach() after ehci_init()
*/
ehci_detach(sc);
err = bus_teardown_intr(self, sc->sc_irq_res, sc->sc_intr_hdl);
if (err)
/* XXX or should we panic? */
device_printf(self, "Could not tear down irq, %d\n",
err);
sc->sc_intr_hdl = NULL;
}
if (sc->sc_irq_res) {
bus_release_resource(self, SYS_RES_IRQ, 0, sc->sc_irq_res);
sc->sc_irq_res = NULL;
}
if (sc->sc_io_res) {
bus_release_resource(self, SYS_RES_MEMORY, 0,
sc->sc_io_res);
sc->sc_io_res = NULL;
}
usb_bus_mem_free_all(&sc->sc_bus, &ehci_iterate_hw_softc);
return (0);
}
static device_method_t ehci_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, ar71xx_ehci_probe),
DEVMETHOD(device_attach, ar71xx_ehci_attach),
DEVMETHOD(device_detach, ar71xx_ehci_detach),
DEVMETHOD(device_suspend, bus_generic_suspend),
DEVMETHOD(device_resume, bus_generic_resume),
DEVMETHOD(device_shutdown, bus_generic_shutdown),
DEVMETHOD_END
};
static driver_t ehci_driver = {
.name = "ehci",
.methods = ehci_methods,
.size = sizeof(struct ar71xx_ehci_softc),
};
static devclass_t ehci_devclass;
DRIVER_MODULE(ehci, nexus, ehci_driver, ehci_devclass, 0, 0);
DRIVER_MODULE(ehci, apb, ehci_driver, ehci_devclass, 0, 0);
MODULE_DEPEND(ehci, usb, 1, 1, 1);

View File

@ -1,114 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@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 unmodified, this list of conditions, and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_ar71xx.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/interrupt.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/rman.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <vm/vm_extern.h>
#include <machine/bus.h>
#include <machine/cpu.h>
#include <machine/intr_machdep.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcib_private.h>
#include "pcib_if.h"
#include <mips/atheros/ar71xxreg.h>
#include <mips/atheros/ar71xx_pci_bus_space.h>
#include <mips/atheros/ar71xx_cpudef.h>
#include <sys/linker.h>
#include <sys/firmware.h>
#include <mips/atheros/ar71xx_fixup.h>
/*
* Take a copy of the EEPROM contents and squirrel it away in a firmware.
* The SPI flash will eventually cease to be memory-mapped, so we need
* to take a copy of this before the SPI driver initialises.
*/
void
ar71xx_pci_slot_create_eeprom_firmware(device_t dev, u_int bus, u_int slot,
u_int func, long int flash_addr, int size)
{
char buf[64];
uint16_t *cal_data = (uint16_t *) MIPS_PHYS_TO_KSEG1(flash_addr);
void *eeprom = NULL;
const struct firmware *fw = NULL;
device_printf(dev, "EEPROM firmware: 0x%lx @ %d bytes\n",
flash_addr, size);
eeprom = malloc(size, M_DEVBUF, M_WAITOK | M_ZERO);
if (! eeprom) {
device_printf(dev,
"%s: malloc failed for '%s', aborting EEPROM\n",
__func__, buf);
return;
}
memcpy(eeprom, cal_data, size);
/*
* Generate a flash EEPROM 'firmware' from the given memory
* region. Since the SPI controller will eventually
* go into port-IO mode instead of memory-mapped IO
* mode, a copy of the EEPROM contents is required.
*/
snprintf(buf, sizeof(buf), "%s.%d.bus.%d.%d.%d.eeprom_firmware",
device_get_name(dev), device_get_unit(dev), bus, slot, func);
fw = firmware_register(buf, eeprom, size, 1, NULL);
if (fw == NULL) {
device_printf(dev, "%s: firmware_register (%s) failed\n",
__func__, buf);
free(eeprom, M_DEVBUF);
return;
}
device_printf(dev, "device EEPROM '%s' registered\n", buf);
}

View File

@ -1,38 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2012, Adrian Chadd <adrian@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 unmodified, this list of conditions, and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef __ATHEROS_AR71XX_FIXUP_H__
#define __ATHEROS_AR71XX_FIXUP_H__
extern void ar71xx_pci_slot_create_eeprom_firmware(device_t dev,
u_int bus, u_int slot, u_int func, long int flash_addr, int size);
#endif /* __ATHEROS_AR71XX_FIXUP_H__ */

View File

@ -1,641 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@FreeBSD.org>
* Copyright (c) 2009, Luiz Otavio O Souza.
* 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 unmodified, 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.
*/
/*
* GPIO driver for AR71xx
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/rman.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mutex.h>
#include <sys/gpio.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <mips/atheros/ar71xxreg.h>
#include <mips/atheros/ar71xx_setup.h>
#include <mips/atheros/ar71xx_cpudef.h>
#include <mips/atheros/ar71xx_gpiovar.h>
#include <dev/gpio/gpiobusvar.h>
#include <mips/atheros/ar933xreg.h>
#include <mips/atheros/ar934xreg.h>
#include <mips/atheros/qca953xreg.h>
#include <mips/atheros/qca955xreg.h>
#include "gpio_if.h"
#define DEFAULT_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)
/*
* Helpers
*/
static void ar71xx_gpio_function_enable(struct ar71xx_gpio_softc *sc,
uint32_t mask);
static void ar71xx_gpio_function_disable(struct ar71xx_gpio_softc *sc,
uint32_t mask);
static void ar71xx_gpio_pin_configure(struct ar71xx_gpio_softc *sc,
struct gpio_pin *pin, uint32_t flags);
/*
* Driver stuff
*/
static int ar71xx_gpio_probe(device_t dev);
static int ar71xx_gpio_attach(device_t dev);
static int ar71xx_gpio_detach(device_t dev);
static int ar71xx_gpio_filter(void *arg);
static void ar71xx_gpio_intr(void *arg);
/*
* GPIO interface
*/
static device_t ar71xx_gpio_get_bus(device_t);
static int ar71xx_gpio_pin_max(device_t dev, int *maxpin);
static int ar71xx_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps);
static int ar71xx_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t
*flags);
static int ar71xx_gpio_pin_getname(device_t dev, uint32_t pin, char *name);
static int ar71xx_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags);
static int ar71xx_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value);
static int ar71xx_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val);
static int ar71xx_gpio_pin_toggle(device_t dev, uint32_t pin);
/*
* Enable/disable the GPIO function control space.
*
* This is primarily for the AR71xx, which has SPI CS1/CS2, UART, SLIC, I2S
* as GPIO pin options.
*/
static void
ar71xx_gpio_function_enable(struct ar71xx_gpio_softc *sc, uint32_t mask)
{
/*
* XXX TODO: refactor this out into a per-chipset method.
*/
if (ar71xx_soc == AR71XX_SOC_AR9341 ||
ar71xx_soc == AR71XX_SOC_AR9342 ||
ar71xx_soc == AR71XX_SOC_AR9344 ||
ar71xx_soc == AR71XX_SOC_QCA9533 ||
ar71xx_soc == AR71XX_SOC_QCA9533_V2 ||
ar71xx_soc == AR71XX_SOC_QCA9556 ||
ar71xx_soc == AR71XX_SOC_QCA9558)
GPIO_SET_BITS(sc, AR934X_GPIO_REG_FUNC, mask);
else
GPIO_SET_BITS(sc, AR71XX_GPIO_FUNCTION, mask);
}
static void
ar71xx_gpio_function_disable(struct ar71xx_gpio_softc *sc, uint32_t mask)
{
/*
* XXX TODO: refactor this out into a per-chipset method.
*/
if (ar71xx_soc == AR71XX_SOC_AR9341 ||
ar71xx_soc == AR71XX_SOC_AR9342 ||
ar71xx_soc == AR71XX_SOC_AR9344 ||
ar71xx_soc == AR71XX_SOC_QCA9533 ||
ar71xx_soc == AR71XX_SOC_QCA9533_V2 ||
ar71xx_soc == AR71XX_SOC_QCA9556 ||
ar71xx_soc == AR71XX_SOC_QCA9558)
GPIO_CLEAR_BITS(sc, AR934X_GPIO_REG_FUNC, mask);
else
GPIO_CLEAR_BITS(sc, AR71XX_GPIO_FUNCTION, mask);
}
/*
* On most platforms, GPIO_OE is a bitmap where the bit set
* means "enable output."
*
* On AR934x and QCA953x, it's the opposite - the bit set means
* "input enable".
*/
static int
ar71xx_gpio_oe_is_high(void)
{
switch (ar71xx_soc) {
case AR71XX_SOC_AR9341:
case AR71XX_SOC_AR9342:
case AR71XX_SOC_AR9344:
case AR71XX_SOC_QCA9533:
case AR71XX_SOC_QCA9533_V2:
return 0;
default:
return 1;
}
}
static void
ar71xx_gpio_oe_set_output(struct ar71xx_gpio_softc *sc, int b)
{
uint32_t mask;
mask = 1 << b;
if (ar71xx_gpio_oe_is_high())
GPIO_SET_BITS(sc, AR71XX_GPIO_OE, mask);
else
GPIO_CLEAR_BITS(sc, AR71XX_GPIO_OE, mask);
}
static void
ar71xx_gpio_oe_set_input(struct ar71xx_gpio_softc *sc, int b)
{
uint32_t mask;
mask = 1 << b;
if (ar71xx_gpio_oe_is_high())
GPIO_CLEAR_BITS(sc, AR71XX_GPIO_OE, mask);
else
GPIO_SET_BITS(sc, AR71XX_GPIO_OE, mask);
}
static void
ar71xx_gpio_pin_configure(struct ar71xx_gpio_softc *sc, struct gpio_pin *pin,
unsigned int flags)
{
/*
* Manage input/output
*/
if (flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) {
pin->gp_flags &= ~(GPIO_PIN_INPUT|GPIO_PIN_OUTPUT);
if (flags & GPIO_PIN_OUTPUT) {
pin->gp_flags |= GPIO_PIN_OUTPUT;
ar71xx_gpio_oe_set_output(sc, pin->gp_pin);
} else {
pin->gp_flags |= GPIO_PIN_INPUT;
ar71xx_gpio_oe_set_input(sc, pin->gp_pin);
}
}
}
static device_t
ar71xx_gpio_get_bus(device_t dev)
{
struct ar71xx_gpio_softc *sc;
sc = device_get_softc(dev);
return (sc->busdev);
}
static int
ar71xx_gpio_pin_max(device_t dev, int *maxpin)
{
switch (ar71xx_soc) {
case AR71XX_SOC_AR9130:
case AR71XX_SOC_AR9132:
*maxpin = AR91XX_GPIO_PINS - 1;
break;
case AR71XX_SOC_AR7240:
case AR71XX_SOC_AR7242:
*maxpin = AR724X_GPIO_PINS - 1;
break;
case AR71XX_SOC_AR7241:
*maxpin = AR7241_GPIO_PINS - 1;
break;
case AR71XX_SOC_AR9330:
case AR71XX_SOC_AR9331:
*maxpin = AR933X_GPIO_COUNT - 1;
break;
case AR71XX_SOC_AR9341:
case AR71XX_SOC_AR9342:
case AR71XX_SOC_AR9344:
*maxpin = AR934X_GPIO_COUNT - 1;
break;
case AR71XX_SOC_QCA9533:
case AR71XX_SOC_QCA9533_V2:
*maxpin = QCA953X_GPIO_COUNT - 1;
break;
case AR71XX_SOC_QCA9556:
case AR71XX_SOC_QCA9558:
*maxpin = QCA955X_GPIO_COUNT - 1;
break;
default:
*maxpin = AR71XX_GPIO_PINS - 1;
}
return (0);
}
static int
ar71xx_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
{
struct ar71xx_gpio_softc *sc = device_get_softc(dev);
int i;
for (i = 0; i < sc->gpio_npins; i++) {
if (sc->gpio_pins[i].gp_pin == pin)
break;
}
if (i >= sc->gpio_npins)
return (EINVAL);
GPIO_LOCK(sc);
*caps = sc->gpio_pins[i].gp_caps;
GPIO_UNLOCK(sc);
return (0);
}
static int
ar71xx_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
{
struct ar71xx_gpio_softc *sc = device_get_softc(dev);
int i;
for (i = 0; i < sc->gpio_npins; i++) {
if (sc->gpio_pins[i].gp_pin == pin)
break;
}
if (i >= sc->gpio_npins)
return (EINVAL);
GPIO_LOCK(sc);
*flags = sc->gpio_pins[i].gp_flags;
GPIO_UNLOCK(sc);
return (0);
}
static int
ar71xx_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
{
struct ar71xx_gpio_softc *sc = device_get_softc(dev);
int i;
for (i = 0; i < sc->gpio_npins; i++) {
if (sc->gpio_pins[i].gp_pin == pin)
break;
}
if (i >= sc->gpio_npins)
return (EINVAL);
GPIO_LOCK(sc);
memcpy(name, sc->gpio_pins[i].gp_name, GPIOMAXNAME);
GPIO_UNLOCK(sc);
return (0);
}
static int
ar71xx_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
{
int i;
struct ar71xx_gpio_softc *sc = device_get_softc(dev);
for (i = 0; i < sc->gpio_npins; i++) {
if (sc->gpio_pins[i].gp_pin == pin)
break;
}
if (i >= sc->gpio_npins)
return (EINVAL);
ar71xx_gpio_pin_configure(sc, &sc->gpio_pins[i], flags);
return (0);
}
static int
ar71xx_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
{
struct ar71xx_gpio_softc *sc = device_get_softc(dev);
int i;
for (i = 0; i < sc->gpio_npins; i++) {
if (sc->gpio_pins[i].gp_pin == pin)
break;
}
if (i >= sc->gpio_npins)
return (EINVAL);
if (value)
GPIO_WRITE(sc, AR71XX_GPIO_SET, (1 << pin));
else
GPIO_WRITE(sc, AR71XX_GPIO_CLEAR, (1 << pin));
return (0);
}
static int
ar71xx_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
{
struct ar71xx_gpio_softc *sc = device_get_softc(dev);
int i;
for (i = 0; i < sc->gpio_npins; i++) {
if (sc->gpio_pins[i].gp_pin == pin)
break;
}
if (i >= sc->gpio_npins)
return (EINVAL);
*val = (GPIO_READ(sc, AR71XX_GPIO_IN) & (1 << pin)) ? 1 : 0;
return (0);
}
static int
ar71xx_gpio_pin_toggle(device_t dev, uint32_t pin)
{
int res, i;
struct ar71xx_gpio_softc *sc = device_get_softc(dev);
for (i = 0; i < sc->gpio_npins; i++) {
if (sc->gpio_pins[i].gp_pin == pin)
break;
}
if (i >= sc->gpio_npins)
return (EINVAL);
res = (GPIO_READ(sc, AR71XX_GPIO_IN) & (1 << pin)) ? 1 : 0;
if (res)
GPIO_WRITE(sc, AR71XX_GPIO_CLEAR, (1 << pin));
else
GPIO_WRITE(sc, AR71XX_GPIO_SET, (1 << pin));
return (0);
}
static int
ar71xx_gpio_filter(void *arg)
{
/* TODO: something useful */
return (FILTER_STRAY);
}
static void
ar71xx_gpio_intr(void *arg)
{
struct ar71xx_gpio_softc *sc = arg;
GPIO_LOCK(sc);
/* TODO: something useful */
GPIO_UNLOCK(sc);
}
static int
ar71xx_gpio_probe(device_t dev)
{
device_set_desc(dev, "Atheros AR71XX GPIO driver");
return (0);
}
static int
ar71xx_gpio_attach(device_t dev)
{
struct ar71xx_gpio_softc *sc = device_get_softc(dev);
int i, j, maxpin;
int mask, pinon;
uint32_t oe;
KASSERT((device_get_unit(dev) == 0),
("ar71xx_gpio: Only one gpio module supported"));
mtx_init(&sc->gpio_mtx, device_get_nameunit(dev), NULL, MTX_DEF);
/* Map control/status registers. */
sc->gpio_mem_rid = 0;
sc->gpio_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
&sc->gpio_mem_rid, RF_ACTIVE);
if (sc->gpio_mem_res == NULL) {
device_printf(dev, "couldn't map memory\n");
ar71xx_gpio_detach(dev);
return (ENXIO);
}
if ((sc->gpio_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
&sc->gpio_irq_rid, RF_SHAREABLE | RF_ACTIVE)) == NULL) {
device_printf(dev, "unable to allocate IRQ resource\n");
ar71xx_gpio_detach(dev);
return (ENXIO);
}
if ((bus_setup_intr(dev, sc->gpio_irq_res, INTR_TYPE_MISC,
ar71xx_gpio_filter, ar71xx_gpio_intr, sc, &sc->gpio_ih))) {
device_printf(dev,
"WARNING: unable to register interrupt handler\n");
ar71xx_gpio_detach(dev);
return (ENXIO);
}
sc->dev = dev;
/* Enable function bits that are required */
if (resource_int_value(device_get_name(dev), device_get_unit(dev),
"function_set", &mask) == 0) {
device_printf(dev, "function_set: 0x%x\n", mask);
ar71xx_gpio_function_enable(sc, mask);
}
/* Disable function bits that are required */
if (resource_int_value(device_get_name(dev), device_get_unit(dev),
"function_clear", &mask) == 0) {
device_printf(dev, "function_clear: 0x%x\n", mask);
ar71xx_gpio_function_disable(sc, mask);
}
/* Disable interrupts for all pins. */
GPIO_WRITE(sc, AR71XX_GPIO_INT_MASK, 0);
/* Initialise all pins specified in the mask, up to the pin count */
(void) ar71xx_gpio_pin_max(dev, &maxpin);
if (resource_int_value(device_get_name(dev), device_get_unit(dev),
"pinmask", &mask) != 0)
mask = 0;
if (resource_int_value(device_get_name(dev), device_get_unit(dev),
"pinon", &pinon) != 0)
pinon = 0;
device_printf(dev, "gpio pinmask=0x%x\n", mask);
for (j = 0; j <= maxpin; j++) {
if ((mask & (1 << j)) == 0)
continue;
sc->gpio_npins++;
}
/* Iniatilize the GPIO pins, keep the loader settings. */
oe = GPIO_READ(sc, AR71XX_GPIO_OE);
/*
* For AR934x and QCA953x, the meaning of oe is inverted;
* so flip it the right way around so we can parse the GPIO
* state.
*/
if (!ar71xx_gpio_oe_is_high())
oe = ~oe;
sc->gpio_pins = malloc(sizeof(*sc->gpio_pins) * sc->gpio_npins,
M_DEVBUF, M_WAITOK | M_ZERO);
for (i = 0, j = 0; j <= maxpin; j++) {
if ((mask & (1 << j)) == 0)
continue;
snprintf(sc->gpio_pins[i].gp_name, GPIOMAXNAME,
"pin %d", j);
sc->gpio_pins[i].gp_pin = j;
sc->gpio_pins[i].gp_caps = DEFAULT_CAPS;
if (oe & (1 << j))
sc->gpio_pins[i].gp_flags = GPIO_PIN_OUTPUT;
else
sc->gpio_pins[i].gp_flags = GPIO_PIN_INPUT;
i++;
}
/* Turn on the hinted pins. */
for (i = 0; i < sc->gpio_npins; i++) {
j = sc->gpio_pins[i].gp_pin;
if ((pinon & (1 << j)) != 0) {
ar71xx_gpio_pin_setflags(dev, j, GPIO_PIN_OUTPUT);
ar71xx_gpio_pin_set(dev, j, 1);
}
}
/*
* Search through the function hints, in case there's some
* overrides such as LNA control.
*
* hint.gpio.X.func.<pin>.gpiofunc=<func value>
* hint.gpio.X.func.<pin>.gpiomode=1 (for output, default low)
*/
for (i = 0; i <= maxpin; i++) {
char buf[32];
int gpiofunc, gpiomode;
snprintf(buf, 32, "func.%d.gpiofunc", i);
if (resource_int_value(device_get_name(dev),
device_get_unit(dev),
buf,
&gpiofunc) != 0)
continue;
/* Get the mode too */
snprintf(buf, 32, "func.%d.gpiomode", i);
if (resource_int_value(device_get_name(dev),
device_get_unit(dev),
buf,
&gpiomode) != 0)
continue;
/* We only handle mode=1 (output) for now */
if (gpiomode != 1)
continue;
device_printf(dev, "%s: GPIO %d: func=%d, mode=%d\n",
__func__,
i,
gpiofunc,
gpiomode);
/* Set pin value = 0, so it stays low by default */
oe = GPIO_READ(sc, AR71XX_GPIO_OUT);
oe &= ~ (1 << i);
GPIO_WRITE(sc, AR71XX_GPIO_OUT, oe);
/* Set output */
ar71xx_gpio_oe_set_output(sc, i);
/* Finally: Set the output config */
ar71xx_gpio_ouput_configure(i, gpiofunc);
}
sc->busdev = gpiobus_attach_bus(dev);
if (sc->busdev == NULL) {
ar71xx_gpio_detach(dev);
return (ENXIO);
}
return (0);
}
static int
ar71xx_gpio_detach(device_t dev)
{
struct ar71xx_gpio_softc *sc = device_get_softc(dev);
KASSERT(mtx_initialized(&sc->gpio_mtx), ("gpio mutex not initialized"));
gpiobus_detach_bus(dev);
if (sc->gpio_ih)
bus_teardown_intr(dev, sc->gpio_irq_res, sc->gpio_ih);
if (sc->gpio_irq_res)
bus_release_resource(dev, SYS_RES_IRQ, sc->gpio_irq_rid,
sc->gpio_irq_res);
if (sc->gpio_mem_res)
bus_release_resource(dev, SYS_RES_MEMORY, sc->gpio_mem_rid,
sc->gpio_mem_res);
if (sc->gpio_pins)
free(sc->gpio_pins, M_DEVBUF);
mtx_destroy(&sc->gpio_mtx);
return(0);
}
static device_method_t ar71xx_gpio_methods[] = {
DEVMETHOD(device_probe, ar71xx_gpio_probe),
DEVMETHOD(device_attach, ar71xx_gpio_attach),
DEVMETHOD(device_detach, ar71xx_gpio_detach),
/* GPIO protocol */
DEVMETHOD(gpio_get_bus, ar71xx_gpio_get_bus),
DEVMETHOD(gpio_pin_max, ar71xx_gpio_pin_max),
DEVMETHOD(gpio_pin_getname, ar71xx_gpio_pin_getname),
DEVMETHOD(gpio_pin_getflags, ar71xx_gpio_pin_getflags),
DEVMETHOD(gpio_pin_getcaps, ar71xx_gpio_pin_getcaps),
DEVMETHOD(gpio_pin_setflags, ar71xx_gpio_pin_setflags),
DEVMETHOD(gpio_pin_get, ar71xx_gpio_pin_get),
DEVMETHOD(gpio_pin_set, ar71xx_gpio_pin_set),
DEVMETHOD(gpio_pin_toggle, ar71xx_gpio_pin_toggle),
{0, 0},
};
static driver_t ar71xx_gpio_driver = {
"gpio",
ar71xx_gpio_methods,
sizeof(struct ar71xx_gpio_softc),
};
static devclass_t ar71xx_gpio_devclass;
DRIVER_MODULE(ar71xx_gpio, apb, ar71xx_gpio_driver, ar71xx_gpio_devclass, 0, 0);

View File

@ -1,74 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@FreeBSD.org>
* Copyright (c) 2009, Luiz Otavio O Souza.
* 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 unmodified, this list of conditions, and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*
*/
#ifndef __AR71XX_GPIOVAR_H__
#define __AR71XX_GPIOVAR_H__
#define GPIO_LOCK(_sc) mtx_lock(&(_sc)->gpio_mtx)
#define GPIO_UNLOCK(_sc) mtx_unlock(&(_sc)->gpio_mtx)
#define GPIO_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->gpio_mtx, MA_OWNED)
/*
* register space access macros
*/
#define GPIO_WRITE(sc, reg, val) do { \
bus_write_4(sc->gpio_mem_res, (reg), (val)); \
} while (0)
#define GPIO_READ(sc, reg) bus_read_4(sc->gpio_mem_res, (reg))
#define GPIO_SET_BITS(sc, reg, bits) \
GPIO_WRITE(sc, reg, GPIO_READ(sc, (reg)) | (bits))
#define GPIO_CLEAR_BITS(sc, reg, bits) \
GPIO_WRITE(sc, reg, GPIO_READ(sc, (reg)) & ~(bits))
#define AR71XX_GPIO_PINS 12
#define AR724X_GPIO_PINS 18
#define AR7241_GPIO_PINS 20
#define AR91XX_GPIO_PINS 22
struct ar71xx_gpio_softc {
device_t dev;
device_t busdev;
struct mtx gpio_mtx;
struct resource *gpio_mem_res;
int gpio_mem_rid;
struct resource *gpio_irq_res;
int gpio_irq_rid;
void *gpio_ih;
int gpio_npins;
struct gpio_pin *gpio_pins;
};
#endif /* __AR71XX_GPIOVAR_H__ */

View File

@ -1,101 +0,0 @@
/*-
* Copyright (c) 2015, Adrian Chadd <adrian@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 unmodified, this list of conditions, and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/types.h>
#include <sys/libkern.h>
#include <net/ethernet.h>
#include <mips/atheros/ar71xx_macaddr.h>
/*
* Some boards don't have a separate MAC address for each individual
* device on-board, but instead need to derive them from a single MAC
* address stored somewhere.
*/
uint8_t ar71xx_board_mac_addr[ETHER_ADDR_LEN];
/*
* Initialise a MAC address 'dst' from a MAC address 'src'.
*
* 'offset' is added to the low three bytes to allow for sequential
* MAC addresses to be derived from a single one.
*
* 'is_local' is whether this 'dst' should be made a local MAC address.
*
* Returns 0 if it was successfully initialised, -1 on error.
*/
int
ar71xx_mac_addr_init(unsigned char *dst, const unsigned char *src,
int offset, int is_local)
{
int t;
if (dst == NULL || src == NULL)
return (-1);
/* XXX TODO: validate 'src' is a valid MAC address */
t = (((uint32_t) src[3]) << 16)
+ (((uint32_t) src[4]) << 8)
+ ((uint32_t) src[5]);
/* Note: this is handles both positive and negative offsets */
t += offset;
dst[0] = src[0];
dst[1] = src[1];
dst[2] = src[2];
dst[3] = (t >> 16) & 0xff;
dst[4] = (t >> 8) & 0xff;
dst[5] = t & 0xff;
if (is_local)
dst[0] |= 0x02;
/* Everything's okay */
return (0);
}
/*
* Initialise a random MAC address for use by if_arge.c and whatever
* else requires it.
*
* Returns 0 on success, -1 on error.
*/
int
ar71xx_mac_addr_random_init(struct ifnet *ifp, struct ether_addr *dst)
{
ether_gen_addr(ifp, dst);
return (0);
}

View File

@ -1,39 +0,0 @@
/*-
* Copyright (c) 2015, Adrian Chadd <adrian@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 unmodified, this list of conditions, and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef __ATHEROS_AR71XX_MACADDR_H__
#define __ATHEROS_AR71XX_MACADDR_H__
extern uint8_t ar71xx_board_mac_addr[ETHER_ADDR_LEN];
extern int ar71xx_mac_addr_init(unsigned char *dst, const unsigned char *src,
int offset, int is_local);
extern int ar71xx_mac_addr_random_init(struct ifnet *ifp, struct ether_addr *dst);
#endif /* __ATHEROS_AR71XX_MACADDR_H__ */

View File

@ -1,457 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2009 Oleksandr Tymoshenko
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_ddb.h"
#include "opt_ar71xx.h"
#include <sys/param.h>
#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/cons.h>
#include <sys/kdb.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/boot.h>
#include <sys/reboot.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_page.h>
#include <vm/vm_phys.h>
#include <vm/vm_dumpset.h>
#include <net/ethernet.h>
#include <machine/clock.h>
#include <machine/cpu.h>
#include <machine/cpuregs.h>
#include <machine/hwfunc.h>
#include <machine/md_var.h>
#include <machine/trap.h>
#include <mips/atheros/ar71xxreg.h>
#include <mips/atheros/ar71xx_setup.h>
#include <mips/atheros/ar71xx_cpudef.h>
#include <mips/atheros/ar71xx_macaddr.h>
extern char edata[], end[];
/* 4KB static data aread to keep a copy of the bootload env until
the dynamic kenv is setup */
char boot1_env[4096];
void
platform_cpu_init()
{
/* Nothing special */
}
void
platform_reset(void)
{
while(1) {
printf("%s: resetting via AHB FULL_CHIP register...\n", __func__);
ar71xx_device_start(RST_RESET_FULL_CHIP);
DELAY(100 * 1000);
ar71xx_device_stop(RST_RESET_FULL_CHIP);
DELAY(1000 * 1000);
}
}
/*
* Obtain the MAC address via the Redboot environment.
*/
static int
ar71xx_redboot_get_macaddr(void)
{
char *var;
int count = 0, i;
uint32_t macaddr[ETHER_ADDR_LEN];
uint8_t tmpmac[ETHER_ADDR_LEN];
/*
* "ethaddr" is passed via envp on RedBoot platforms
* "kmac" is passed via argv on RouterBOOT platforms
*/
if ((var = kern_getenv("ethaddr")) != NULL ||
(var = kern_getenv("kmac")) != NULL) {
count = sscanf(var, "%x%*c%x%*c%x%*c%x%*c%x%*c%x",
&macaddr[0], &macaddr[1],
&macaddr[2], &macaddr[3],
&macaddr[4], &macaddr[5]);
if (count < 6) {
memset(macaddr, 0,
sizeof(macaddr));
} else {
for (i = 0; i < ETHER_ADDR_LEN; i++)
tmpmac[i] = macaddr[i] & 0xff;
(void) ar71xx_mac_addr_init(ar71xx_board_mac_addr,
tmpmac,
0, /* offset */
0); /* is_local */
}
freeenv(var);
return (0);
}
return (-1);
}
#ifdef AR71XX_ENV_ROUTERBOOT
/*
* RouterBoot gives us the board memory in a command line argument.
*/
static int
ar71xx_routerboot_get_mem(int argc, char **argv)
{
int i, board_mem;
/*
* Protect ourselves from garbage in registers.
*/
if (!MIPS_IS_VALID_PTR(argv))
return (0);
for (i = 0; i < argc; i++) {
if (argv[i] == NULL)
continue;
if (strncmp(argv[i], "mem=", 4) == 0) {
if (sscanf(argv[i] + 4, "%dM", &board_mem) == 1)
return (btoc(board_mem * 1024 * 1024));
}
}
return (0);
}
#endif
/*
* Handle initialising the MAC address from a specific EEPROM
* offset.
*
* This is done during (very) early boot.
*
* hint.ar71xx.0.eeprom_mac_addr=<address to read from>
* hint.ar71xx.0.eeprom_mac_isascii=<0|1>
*/
static int
ar71xx_platform_read_eeprom_mac(void)
{
long eeprom_mac_addr = 0;
const char *mac;
int i, readascii = 0;
uint8_t macaddr[ETHER_ADDR_LEN];
if (resource_long_value("ar71xx", 0, "eeprom_mac_addr",
&eeprom_mac_addr) != 0)
return (-1);
/* get a pointer to the EEPROM MAC address */
mac = (const char *) MIPS_PHYS_TO_KSEG1(eeprom_mac_addr);
/* Check if it's ASCII or not */
if (resource_int_value("ar71xx", 0, "eeprom_mac_isascii",
&readascii) == 0 && readascii == 1) {
printf("ar71xx: Overriding MAC from EEPROM (ascii)\n");
for (i = 0; i < 6; i++) {
macaddr[i] = strtol(&(mac[i*3]), NULL, 16);
}
} else {
printf("ar71xx: Overriding MAC from EEPROM\n");
for (i = 0; i < 6; i++) {
macaddr[i] = mac[i];
}
}
/* Set the default board MAC */
(void) ar71xx_mac_addr_init(ar71xx_board_mac_addr,
macaddr,
0, /* offset */
0); /* is_local */
printf("ar71xx: Board MAC: %6D\n", ar71xx_board_mac_addr, ":");
return (0);
}
/*
* Populate a kenv hint for the given device based on the given
* MAC address and offset.
*
* Returns 0 if ok, < 0 on error.
*/
static int
ar71xx_platform_set_mac_hint(const char *dev, int unit,
const uint8_t *macaddr, int offset, int islocal)
{
char macstr[32];
uint8_t lclmac[ETHER_ADDR_LEN];
char devstr[32];
/* Initialise the MAC address, plus/minus the offset */
if (ar71xx_mac_addr_init(lclmac, macaddr, offset, islocal) != 0) {
return (-1);
}
/* Turn it into a string */
snprintf(macstr, 32, "%6D", lclmac, ":");
snprintf(devstr, 32, "hint.%s.%d.macaddr", dev, unit);
printf(" %s => %s\n", devstr, macstr);
/* Call setenv */
if (kern_setenv(devstr, macstr) != 0) {
printf("%s: failed to set hint (%s => %s)\n",
__func__,
devstr,
macstr);
return (-1);
}
return (0);
}
/*
* Iterate through the list of boot time hints that populate
* a device MAC address hint based on the "board" MAC address.
*
* ar71xx_mac_map.X.devid=<device id, eg ath>
* ar71xx_mac_map.X.unitid=<unit id, eg 0>
* ar71xx_mac_map.X.offset=<mac address value offset>
* ar71xx_mac_map.X.is_local=<1 or 0>
*/
static int
ar71xx_platform_check_mac_hints(void)
{
int i;
const char *devid;
int offset, is_local, unitid;
for (i = 0; i < 8; i++) {
if (resource_string_value("ar71xx_mac_map", i, "devid",
&devid) != 0)
break;
if (resource_int_value("ar71xx_mac_map", i, "unitid",
&unitid) != 0)
break;
if (resource_int_value("ar71xx_mac_map", i, "offset",
&offset) != 0)
break;
if (resource_int_value("ar71xx_mac_map", i, "is_local",
&is_local) != 0)
break;
printf("ar71xx: devid '%s.%d', MAC offset '%d'\n",
devid, unitid, offset);
(void) ar71xx_platform_set_mac_hint(devid, unitid,
ar71xx_board_mac_addr, offset, is_local);
}
return (0);
}
void
platform_start(__register_t a0 __unused, __register_t a1 __unused,
__register_t a2 __unused, __register_t a3 __unused)
{
uint64_t platform_counter_freq;
int argc = 0, i;
char **argv = NULL, **envp = NULL;
vm_offset_t kernend;
/*
* clear the BSS and SBSS segments, this should be first call in
* the function
*/
kernend = (vm_offset_t)&end;
memset(&edata, 0, kernend - (vm_offset_t)(&edata));
mips_postboot_fixup();
/* Initialize pcpu stuff */
mips_pcpu0_init();
/*
* Until some more sensible abstractions for uboot/redboot
* environment handling, we have to make this a compile-time
* hack. The existing code handles the uboot environment
* very incorrectly so we should just ignore initialising
* the relevant pointers.
*/
#ifndef AR71XX_ENV_UBOOT
argc = a0;
argv = (char**)a1;
envp = (char**)a2;
#endif
/*
* Protect ourselves from garbage in registers
*/
if (MIPS_IS_VALID_PTR(envp)) {
for (i = 0; envp[i]; i += 2) {
if (strcmp(envp[i], "memsize") == 0)
realmem = btoc(strtoul(envp[i+1], NULL, 16));
else if (strcmp(envp[i], "bootverbose") == 0)
bootverbose = btoc(strtoul(envp[i+1], NULL, 10));
}
}
bootverbose = 1;
#ifdef AR71XX_ENV_ROUTERBOOT
/*
* RouterBoot informs the board memory as a command line argument.
*/
if (realmem == 0)
realmem = ar71xx_routerboot_get_mem(argc, argv);
#endif
/*
* Just wild guess. RedBoot let us down and didn't reported
* memory size
*/
if (realmem == 0)
realmem = btoc(32*1024*1024);
/*
* Allow build-time override in case Redboot lies
* or in other situations (eg where there's u-boot)
* where there isn't (yet) a convienent method of
* being told how much RAM is available.
*
* This happens on at least the Ubiquiti LS-SR71A
* board, where redboot says there's 16mb of RAM
* but in fact there's 32mb.
*/
#if defined(AR71XX_REALMEM)
realmem = btoc(AR71XX_REALMEM);
#endif
/* phys_avail regions are in bytes */
phys_avail[0] = MIPS_KSEG0_TO_PHYS(kernel_kseg0_end);
phys_avail[1] = ctob(realmem);
dump_avail[0] = 0;
dump_avail[1] = phys_avail[1];
physmem = realmem;
/*
* ns8250 uart code uses DELAY so ticker should be inititalized
* before cninit. And tick_init_params refers to hz, so * init_param1
* should be called first.
*/
init_param1();
/* Detect the system type - this is needed for subsequent chipset-specific calls */
ar71xx_detect_sys_type();
ar71xx_detect_sys_frequency();
platform_counter_freq = ar71xx_cpu_freq();
mips_timer_init_params(platform_counter_freq, 1);
cninit();
init_static_kenv(boot1_env, sizeof(boot1_env));
printf("CPU platform: %s\n", ar71xx_get_system_type());
printf("CPU Frequency=%d MHz\n", u_ar71xx_cpu_freq / 1000000);
printf("CPU DDR Frequency=%d MHz\n", u_ar71xx_ddr_freq / 1000000);
printf("CPU AHB Frequency=%d MHz\n", u_ar71xx_ahb_freq / 1000000);
printf("platform frequency: %lld MHz\n", platform_counter_freq / 1000000);
printf("CPU reference clock: %d MHz\n", u_ar71xx_refclk / 1000000);
printf("CPU MDIO clock: %d MHz\n", u_ar71xx_mdio_freq / 1000000);
printf("arguments: \n");
printf(" a0 = %08x\n", a0);
printf(" a1 = %08x\n", a1);
printf(" a2 = %08x\n", a2);
printf(" a3 = %08x\n", a3);
strcpy(cpu_model, ar71xx_get_system_type());
/*
* XXX this code is very redboot specific.
*/
printf("Cmd line:");
if (MIPS_IS_VALID_PTR(argv)) {
for (i = 0; i < argc; i++) {
printf(" %s", argv[i]);
boothowto |= boot_parse_arg(argv[i]);
}
}
else
printf ("argv is invalid");
printf("\n");
printf("Environment:\n");
if (MIPS_IS_VALID_PTR(envp)) {
for (i = 0; envp[i]; i+=2) {
printf(" %s = %s\n", envp[i], envp[i+1]);
kern_setenv(envp[i], envp[i+1]);
}
}
else
printf ("envp is invalid\n");
/* Platform setup */
init_param2(physmem);
mips_cpu_init();
pmap_bootstrap();
mips_proc0_init();
mutex_init();
/*
* Reset USB devices
*/
ar71xx_init_usb_peripheral();
/*
* Reset internal ethernet switch, if one exists
*/
ar71xx_reset_ethernet_switch();
/*
* Initialise the gmac driver.
*/
ar71xx_init_gmac();
/* Redboot if_arge MAC address is in the environment */
(void) ar71xx_redboot_get_macaddr();
/* Various other boards need things to come out of EEPROM */
(void) ar71xx_platform_read_eeprom_mac();
/* Initialise the MAC address hint map */
ar71xx_platform_check_mac_hints();
kdb_init();
#ifdef KDB
if (boothowto & RB_KDB)
kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger");
#endif
}

View File

@ -1,221 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@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 unmodified, this list of conditions, and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/rman.h>
#include <sys/condvar.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
#include <dev/usb/usb_core.h>
#include <dev/usb/usb_busdma.h>
#include <dev/usb/usb_process.h>
#include <dev/usb/usb_util.h>
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
#include <dev/usb/controller/ohci.h>
#include <dev/usb/controller/ohcireg.h>
#include <mips/atheros/ar71xxreg.h> /* for stuff in ar71xx_cpudef.h */
#include <mips/atheros/ar71xx_cpudef.h>
static int ar71xx_ohci_attach(device_t dev);
static int ar71xx_ohci_detach(device_t dev);
static int ar71xx_ohci_probe(device_t dev);
struct ar71xx_ohci_softc
{
struct ohci_softc sc_ohci;
};
static int
ar71xx_ohci_probe(device_t dev)
{
device_set_desc(dev, "AR71XX integrated OHCI controller");
return (BUS_PROBE_DEFAULT);
}
static void
ar71xx_ohci_intr(void *arg)
{
/* XXX TODO: should really see if this was our interrupt.. */
ar71xx_device_flush_ddr(AR71XX_CPU_DDR_FLUSH_USB);
ohci_interrupt(arg);
}
static int
ar71xx_ohci_attach(device_t dev)
{
struct ar71xx_ohci_softc *sc = device_get_softc(dev);
int err;
int rid;
/* initialise some bus fields */
sc->sc_ohci.sc_bus.parent = dev;
sc->sc_ohci.sc_bus.devices = sc->sc_ohci.sc_devices;
sc->sc_ohci.sc_bus.devices_max = OHCI_MAX_DEVICES;
sc->sc_ohci.sc_bus.dma_bits = 32;
/* get all DMA memory */
if (usb_bus_mem_alloc_all(&sc->sc_ohci.sc_bus,
USB_GET_DMA_TAG(dev), &ohci_iterate_hw_softc)) {
return (ENOMEM);
}
sc->sc_ohci.sc_dev = dev;
rid = 0;
sc->sc_ohci.sc_io_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
RF_ACTIVE);
if (sc->sc_ohci.sc_io_res == NULL) {
err = ENOMEM;
goto error;
}
sc->sc_ohci.sc_io_tag = rman_get_bustag(sc->sc_ohci.sc_io_res);
sc->sc_ohci.sc_io_hdl = rman_get_bushandle(sc->sc_ohci.sc_io_res);
sc->sc_ohci.sc_io_size = rman_get_size(sc->sc_ohci.sc_io_res);
rid = 0;
sc->sc_ohci.sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
RF_ACTIVE);
if (sc->sc_ohci.sc_irq_res == NULL) {
err = ENOMEM;
goto error;
}
sc->sc_ohci.sc_bus.bdev = device_add_child(dev, "usbus", -1);
if (sc->sc_ohci.sc_bus.bdev == NULL) {
err = ENOMEM;
goto error;
}
device_set_ivars(sc->sc_ohci.sc_bus.bdev, &sc->sc_ohci.sc_bus);
err = bus_setup_intr(dev, sc->sc_ohci.sc_irq_res,
INTR_TYPE_BIO | INTR_MPSAFE, NULL,
ar71xx_ohci_intr, sc, &sc->sc_ohci.sc_intr_hdl);
if (err) {
err = ENXIO;
goto error;
}
strlcpy(sc->sc_ohci.sc_vendor, "Atheros", sizeof(sc->sc_ohci.sc_vendor));
bus_space_write_4(sc->sc_ohci.sc_io_tag, sc->sc_ohci.sc_io_hdl, OHCI_CONTROL, 0);
err = ohci_init(&sc->sc_ohci);
if (!err)
err = device_probe_and_attach(sc->sc_ohci.sc_bus.bdev);
if (err)
goto error;
return (0);
error:
if (err) {
ar71xx_ohci_detach(dev);
return (err);
}
return (err);
}
static int
ar71xx_ohci_detach(device_t dev)
{
struct ar71xx_ohci_softc *sc = device_get_softc(dev);
/* during module unload there are lots of children leftover */
device_delete_children(dev);
/*
* Put the controller into reset, then disable clocks and do
* the MI tear down. We have to disable the clocks/hardware
* after we do the rest of the teardown. We also disable the
* clocks in the opposite order we acquire them, but that
* doesn't seem to be absolutely necessary. We free up the
* clocks after we disable them, so the system could, in
* theory, reuse them.
*/
bus_space_write_4(sc->sc_ohci.sc_io_tag, sc->sc_ohci.sc_io_hdl,
OHCI_CONTROL, 0);
if (sc->sc_ohci.sc_intr_hdl) {
bus_teardown_intr(dev, sc->sc_ohci.sc_irq_res, sc->sc_ohci.sc_intr_hdl);
sc->sc_ohci.sc_intr_hdl = NULL;
}
if (sc->sc_ohci.sc_irq_res && sc->sc_ohci.sc_intr_hdl) {
/*
* only call ohci_detach() after ohci_init()
*/
ohci_detach(&sc->sc_ohci);
bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_ohci.sc_irq_res);
sc->sc_ohci.sc_irq_res = NULL;
}
if (sc->sc_ohci.sc_io_res) {
bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_ohci.sc_io_res);
sc->sc_ohci.sc_io_res = NULL;
sc->sc_ohci.sc_io_tag = 0;
sc->sc_ohci.sc_io_hdl = 0;
}
usb_bus_mem_free_all(&sc->sc_ohci.sc_bus, &ohci_iterate_hw_softc);
return (0);
}
static device_method_t ohci_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, ar71xx_ohci_probe),
DEVMETHOD(device_attach, ar71xx_ohci_attach),
DEVMETHOD(device_detach, ar71xx_ohci_detach),
DEVMETHOD(device_suspend, bus_generic_suspend),
DEVMETHOD(device_resume, bus_generic_resume),
DEVMETHOD(device_shutdown, bus_generic_shutdown),
DEVMETHOD_END
};
static driver_t ohci_driver = {
.name = "ohci",
.methods = ohci_methods,
.size = sizeof(struct ar71xx_ohci_softc),
};
static devclass_t ohci_devclass;
DRIVER_MODULE(ohci, apb, ohci_driver, ohci_devclass, 0, 0);

View File

@ -1,706 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@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 unmodified, this list of conditions, and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_ar71xx.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/interrupt.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/rman.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <vm/vm_extern.h>
#include <machine/bus.h>
#include <machine/cpu.h>
#include <machine/intr_machdep.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcib_private.h>
#include "pcib_if.h"
#include <mips/atheros/ar71xxreg.h>
#include <mips/atheros/ar71xx_pci_bus_space.h>
#include <mips/atheros/ar71xx_cpudef.h>
#ifdef AR71XX_ATH_EEPROM
#include <mips/atheros/ar71xx_fixup.h>
#endif /* AR71XX_ATH_EEPROM */
#undef AR71XX_PCI_DEBUG
#ifdef AR71XX_PCI_DEBUG
#define dprintf printf
#else
#define dprintf(x, arg...)
#endif
struct mtx ar71xx_pci_mtx;
MTX_SYSINIT(ar71xx_pci_mtx, &ar71xx_pci_mtx, "ar71xx PCI space mutex",
MTX_SPIN);
struct ar71xx_pci_softc {
device_t sc_dev;
int sc_busno;
int sc_baseslot;
struct rman sc_mem_rman;
struct rman sc_irq_rman;
struct intr_event *sc_eventstab[AR71XX_PCI_NIRQS];
mips_intrcnt_t sc_intr_counter[AR71XX_PCI_NIRQS];
struct resource *sc_irq;
void *sc_ih;
};
static int ar71xx_pci_setup_intr(device_t, device_t, struct resource *, int,
driver_filter_t *, driver_intr_t *, void *, void **);
static int ar71xx_pci_teardown_intr(device_t, device_t, struct resource *,
void *);
static int ar71xx_pci_intr(void *);
static void
ar71xx_pci_mask_irq(void *source)
{
uint32_t reg;
unsigned int irq = (unsigned int)source;
/* XXX is the PCI lock required here? */
reg = ATH_READ_REG(AR71XX_PCI_INTR_MASK);
/* flush */
reg = ATH_READ_REG(AR71XX_PCI_INTR_MASK);
ATH_WRITE_REG(AR71XX_PCI_INTR_MASK, reg & ~(1 << irq));
}
static void
ar71xx_pci_unmask_irq(void *source)
{
uint32_t reg;
unsigned int irq = (unsigned int)source;
/* XXX is the PCI lock required here? */
reg = ATH_READ_REG(AR71XX_PCI_INTR_MASK);
ATH_WRITE_REG(AR71XX_PCI_INTR_MASK, reg | (1 << irq));
/* flush */
reg = ATH_READ_REG(AR71XX_PCI_INTR_MASK);
}
/*
* get bitmask for bytes of interest:
* 0 - we want this byte, 1 - ignore it. e.g: we read 1 byte
* from register 7. Bitmask would be: 0111
*/
static uint32_t
ar71xx_get_bytes_to_read(int reg, int bytes)
{
uint32_t bytes_to_read = 0;
if ((bytes % 4) == 0)
bytes_to_read = 0;
else if ((bytes % 4) == 1)
bytes_to_read = (~(1 << (reg % 4))) & 0xf;
else if ((bytes % 4) == 2)
bytes_to_read = (~(3 << (reg % 4))) & 0xf;
else
panic("%s: wrong combination", __func__);
return (bytes_to_read);
}
static int
ar71xx_pci_check_bus_error(void)
{
uint32_t error, addr, has_errors = 0;
mtx_assert(&ar71xx_pci_mtx, MA_OWNED);
error = ATH_READ_REG(AR71XX_PCI_ERROR) & 0x3;
dprintf("%s: PCI error = %02x\n", __func__, error);
if (error) {
addr = ATH_READ_REG(AR71XX_PCI_ERROR_ADDR);
/* Do not report it yet */
#if 0
printf("PCI bus error %d at addr 0x%08x\n", error, addr);
#endif
ATH_WRITE_REG(AR71XX_PCI_ERROR, error);
has_errors = 1;
}
error = ATH_READ_REG(AR71XX_PCI_AHB_ERROR) & 0x1;
dprintf("%s: AHB error = %02x\n", __func__, error);
if (error) {
addr = ATH_READ_REG(AR71XX_PCI_AHB_ERROR_ADDR);
/* Do not report it yet */
#if 0
printf("AHB bus error %d at addr 0x%08x\n", error, addr);
#endif
ATH_WRITE_REG(AR71XX_PCI_AHB_ERROR, error);
has_errors = 1;
}
return (has_errors);
}
static uint32_t
ar71xx_pci_make_addr(int bus, int slot, int func, int reg)
{
if (bus == 0) {
return ((1 << slot) | (func << 8) | (reg & ~3));
} else {
return ((bus << 16) | (slot << 11) | (func << 8)
| (reg & ~3) | 1);
}
}
static int
ar71xx_pci_conf_setup(int bus, int slot, int func, int reg, int bytes,
uint32_t cmd)
{
uint32_t addr = ar71xx_pci_make_addr(bus, slot, func, (reg & ~3));
mtx_assert(&ar71xx_pci_mtx, MA_OWNED);
cmd |= (ar71xx_get_bytes_to_read(reg, bytes) << 4);
ATH_WRITE_REG(AR71XX_PCI_CONF_ADDR, addr);
ATH_WRITE_REG(AR71XX_PCI_CONF_CMD, cmd);
dprintf("%s: tag (%x, %x, %x) %d/%d addr=%08x, cmd=%08x\n", __func__,
bus, slot, func, reg, bytes, addr, cmd);
return ar71xx_pci_check_bus_error();
}
static uint32_t
ar71xx_pci_read_config(device_t dev, u_int bus, u_int slot, u_int func,
u_int reg, int bytes)
{
uint32_t data;
uint32_t shift, mask;
/* register access is 32-bit aligned */
shift = (reg & 3) * 8;
/* Create a mask based on the width, post-shift */
if (bytes == 2)
mask = 0xffff;
else if (bytes == 1)
mask = 0xff;
else
mask = 0xffffffff;
dprintf("%s: tag (%x, %x, %x) reg %d(%d)\n", __func__, bus, slot,
func, reg, bytes);
mtx_lock_spin(&ar71xx_pci_mtx);
if (ar71xx_pci_conf_setup(bus, slot, func, reg, bytes,
PCI_CONF_CMD_READ) == 0)
data = ATH_READ_REG(AR71XX_PCI_CONF_READ_DATA);
else
data = -1;
mtx_unlock_spin(&ar71xx_pci_mtx);
/* get request bytes from 32-bit word */
data = (data >> shift) & mask;
dprintf("%s: read 0x%x\n", __func__, data);
return (data);
}
static void
ar71xx_pci_local_write(device_t dev, uint32_t reg, uint32_t data, int bytes)
{
uint32_t cmd;
dprintf("%s: local write reg %d(%d)\n", __func__, reg, bytes);
data = data << (8*(reg % 4));
cmd = PCI_LCONF_CMD_WRITE | (reg & ~3);
cmd |= (ar71xx_get_bytes_to_read(reg, bytes) << 20);
mtx_lock_spin(&ar71xx_pci_mtx);
ATH_WRITE_REG(AR71XX_PCI_LCONF_CMD, cmd);
ATH_WRITE_REG(AR71XX_PCI_LCONF_WRITE_DATA, data);
mtx_unlock_spin(&ar71xx_pci_mtx);
}
static void
ar71xx_pci_write_config(device_t dev, u_int bus, u_int slot, u_int func,
u_int reg, uint32_t data, int bytes)
{
dprintf("%s: tag (%x, %x, %x) reg %d(%d)\n", __func__, bus, slot,
func, reg, bytes);
data = data << (8*(reg % 4));
mtx_lock_spin(&ar71xx_pci_mtx);
if (ar71xx_pci_conf_setup(bus, slot, func, reg, bytes,
PCI_CONF_CMD_WRITE) == 0)
ATH_WRITE_REG(AR71XX_PCI_CONF_WRITE_DATA, data);
mtx_unlock_spin(&ar71xx_pci_mtx);
}
#ifdef AR71XX_ATH_EEPROM
/*
* Some embedded boards (eg AP94) have the MAC attached via PCI but they
* don't have the MAC-attached EEPROM. The register initialisation
* values and calibration data are stored in the on-board flash.
* This routine initialises the NIC via the EEPROM register contents
* before the probe/attach routines get a go at things.
*/
static void
ar71xx_pci_fixup(device_t dev, u_int bus, u_int slot, u_int func,
long flash_addr, int len)
{
uint16_t *cal_data = (uint16_t *) MIPS_PHYS_TO_KSEG1(flash_addr);
uint32_t reg, val, bar0;
if (bootverbose)
device_printf(dev, "%s: flash_addr=%lx, cal_data=%p\n",
__func__, flash_addr, cal_data);
/* XXX check 0xa55a */
/* Save bar(0) address - just to flush bar(0) (SoC WAR) ? */
bar0 = ar71xx_pci_read_config(dev, bus, slot, func, PCIR_BAR(0), 4);
ar71xx_pci_write_config(dev, bus, slot, func, PCIR_BAR(0),
AR71XX_PCI_MEM_BASE, 4);
val = ar71xx_pci_read_config(dev, bus, slot, func, PCIR_COMMAND, 2);
val |= (PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN);
ar71xx_pci_write_config(dev, bus, slot, func, PCIR_COMMAND, val, 2);
cal_data += 3;
while (*cal_data != 0xffff) {
reg = *cal_data++;
val = *cal_data++;
val |= (*cal_data++) << 16;
if (bootverbose)
printf(" reg: %x, val=%x\n", reg, val);
/* Write eeprom fixup data to device memory */
ATH_WRITE_REG(AR71XX_PCI_MEM_BASE + reg, val);
DELAY(100);
}
val = ar71xx_pci_read_config(dev, bus, slot, func, PCIR_COMMAND, 2);
val &= ~(PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN);
ar71xx_pci_write_config(dev, bus, slot, func, PCIR_COMMAND, val, 2);
/* Write the saved bar(0) address */
ar71xx_pci_write_config(dev, bus, slot, func, PCIR_BAR(0), bar0, 4);
}
static void
ar71xx_pci_slot_fixup(device_t dev, u_int bus, u_int slot, u_int func)
{
long int flash_addr;
char buf[64];
int size;
/*
* Check whether the given slot has a hint to poke.
*/
if (bootverbose)
device_printf(dev, "%s: checking dev %s, %d/%d/%d\n",
__func__, device_get_nameunit(dev), bus, slot, func);
snprintf(buf, sizeof(buf), "bus.%d.%d.%d.ath_fixup_addr",
bus, slot, func);
if (resource_long_value(device_get_name(dev), device_get_unit(dev),
buf, &flash_addr) == 0) {
snprintf(buf, sizeof(buf), "bus.%d.%d.%d.ath_fixup_size",
bus, slot, func);
if (resource_int_value(device_get_name(dev),
device_get_unit(dev), buf, &size) != 0) {
device_printf(dev,
"%s: missing hint '%s', aborting EEPROM\n",
__func__, buf);
return;
}
device_printf(dev, "found EEPROM at 0x%lx on %d.%d.%d\n",
flash_addr, bus, slot, func);
ar71xx_pci_fixup(dev, bus, slot, func, flash_addr, size);
ar71xx_pci_slot_create_eeprom_firmware(dev, bus, slot, func,
flash_addr, size);
}
}
#endif /* AR71XX_ATH_EEPROM */
static int
ar71xx_pci_probe(device_t dev)
{
return (BUS_PROBE_NOWILDCARD);
}
static int
ar71xx_pci_attach(device_t dev)
{
int rid = 0;
struct ar71xx_pci_softc *sc = device_get_softc(dev);
sc->sc_mem_rman.rm_type = RMAN_ARRAY;
sc->sc_mem_rman.rm_descr = "ar71xx PCI memory window";
if (rman_init(&sc->sc_mem_rman) != 0 ||
rman_manage_region(&sc->sc_mem_rman, AR71XX_PCI_MEM_BASE,
AR71XX_PCI_MEM_BASE + AR71XX_PCI_MEM_SIZE - 1) != 0) {
panic("ar71xx_pci_attach: failed to set up I/O rman");
}
sc->sc_irq_rman.rm_type = RMAN_ARRAY;
sc->sc_irq_rman.rm_descr = "ar71xx PCI IRQs";
if (rman_init(&sc->sc_irq_rman) != 0 ||
rman_manage_region(&sc->sc_irq_rman, AR71XX_PCI_IRQ_START,
AR71XX_PCI_IRQ_END) != 0)
panic("ar71xx_pci_attach: failed to set up IRQ rman");
/*
* Check if there is a base slot hint. Otherwise use default value.
*/
if (resource_int_value(device_get_name(dev),
device_get_unit(dev), "baseslot", &sc->sc_baseslot) != 0) {
device_printf(dev,
"%s: missing hint '%s', default to AR71XX_PCI_BASE_SLOT\n",
__func__, "baseslot");
sc->sc_baseslot = AR71XX_PCI_BASE_SLOT;
}
ATH_WRITE_REG(AR71XX_PCI_INTR_STATUS, 0);
ATH_WRITE_REG(AR71XX_PCI_INTR_MASK, 0);
/* Hook up our interrupt handler. */
if ((sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
RF_SHAREABLE | RF_ACTIVE)) == NULL) {
device_printf(dev, "unable to allocate IRQ resource\n");
return ENXIO;
}
if ((bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_MISC,
ar71xx_pci_intr, NULL, sc, &sc->sc_ih))) {
device_printf(dev,
"WARNING: unable to register interrupt handler\n");
return ENXIO;
}
/* reset PCI core and PCI bus */
ar71xx_device_stop(RST_RESET_PCI_CORE | RST_RESET_PCI_BUS);
DELAY(100000);
ar71xx_device_start(RST_RESET_PCI_CORE | RST_RESET_PCI_BUS);
DELAY(100000);
/* Init PCI windows */
ATH_WRITE_REG(AR71XX_PCI_WINDOW0, PCI_WINDOW0_ADDR);
ATH_WRITE_REG(AR71XX_PCI_WINDOW1, PCI_WINDOW1_ADDR);
ATH_WRITE_REG(AR71XX_PCI_WINDOW2, PCI_WINDOW2_ADDR);
ATH_WRITE_REG(AR71XX_PCI_WINDOW3, PCI_WINDOW3_ADDR);
ATH_WRITE_REG(AR71XX_PCI_WINDOW4, PCI_WINDOW4_ADDR);
ATH_WRITE_REG(AR71XX_PCI_WINDOW5, PCI_WINDOW5_ADDR);
ATH_WRITE_REG(AR71XX_PCI_WINDOW6, PCI_WINDOW6_ADDR);
ATH_WRITE_REG(AR71XX_PCI_WINDOW7, PCI_WINDOW7_CONF_ADDR);
DELAY(100000);
mtx_lock_spin(&ar71xx_pci_mtx);
ar71xx_pci_check_bus_error();
mtx_unlock_spin(&ar71xx_pci_mtx);
/* Fixup internal PCI bridge */
ar71xx_pci_local_write(dev, PCIR_COMMAND,
PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN
| PCIM_CMD_SERRESPEN | PCIM_CMD_BACKTOBACK
| PCIM_CMD_PERRESPEN | PCIM_CMD_MWRICEN, 4);
#ifdef AR71XX_ATH_EEPROM
/*
* Hard-code a check for slot 17 and 18 - these are
* the two PCI slots which may have a PCI device that
* requires "fixing".
*/
ar71xx_pci_slot_fixup(dev, 0, 17, 0);
ar71xx_pci_slot_fixup(dev, 0, 18, 0);
#endif /* AR71XX_ATH_EEPROM */
device_add_child(dev, "pci", -1);
return (bus_generic_attach(dev));
}
static int
ar71xx_pci_read_ivar(device_t dev, device_t child, int which,
uintptr_t *result)
{
struct ar71xx_pci_softc *sc = device_get_softc(dev);
switch (which) {
case PCIB_IVAR_DOMAIN:
*result = 0;
return (0);
case PCIB_IVAR_BUS:
*result = sc->sc_busno;
return (0);
}
return (ENOENT);
}
static int
ar71xx_pci_write_ivar(device_t dev, device_t child, int which,
uintptr_t result)
{
struct ar71xx_pci_softc * sc = device_get_softc(dev);
switch (which) {
case PCIB_IVAR_BUS:
sc->sc_busno = result;
return (0);
}
return (ENOENT);
}
static struct resource *
ar71xx_pci_alloc_resource(device_t bus, device_t child, int type, int *rid,
rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
{
struct ar71xx_pci_softc *sc = device_get_softc(bus);
struct resource *rv;
struct rman *rm;
switch (type) {
case SYS_RES_IRQ:
rm = &sc->sc_irq_rman;
break;
case SYS_RES_MEMORY:
rm = &sc->sc_mem_rman;
break;
default:
return (NULL);
}
rv = rman_reserve_resource(rm, start, end, count, flags, child);
if (rv == NULL)
return (NULL);
rman_set_rid(rv, *rid);
if (flags & RF_ACTIVE) {
if (bus_activate_resource(child, type, *rid, rv)) {
rman_release_resource(rv);
return (NULL);
}
}
return (rv);
}
static int
ar71xx_pci_activate_resource(device_t bus, device_t child, int type, int rid,
struct resource *r)
{
int res = (BUS_ACTIVATE_RESOURCE(device_get_parent(bus),
child, type, rid, r));
if (!res) {
switch(type) {
case SYS_RES_MEMORY:
case SYS_RES_IOPORT:
rman_set_bustag(r, ar71xx_bus_space_pcimem);
break;
}
}
return (res);
}
static int
ar71xx_pci_setup_intr(device_t bus, device_t child, struct resource *ires,
int flags, driver_filter_t *filt, driver_intr_t *handler,
void *arg, void **cookiep)
{
struct ar71xx_pci_softc *sc = device_get_softc(bus);
struct intr_event *event;
int irq, error;
irq = rman_get_start(ires);
if (irq > AR71XX_PCI_IRQ_END)
panic("%s: bad irq %d", __func__, irq);
event = sc->sc_eventstab[irq];
if (event == NULL) {
error = intr_event_create(&event, (void *)irq, 0, irq,
ar71xx_pci_mask_irq, ar71xx_pci_unmask_irq, NULL, NULL,
"pci intr%d:", irq);
if (error == 0) {
sc->sc_eventstab[irq] = event;
sc->sc_intr_counter[irq] =
mips_intrcnt_create(event->ie_name);
}
else
return (error);
}
intr_event_add_handler(event, device_get_nameunit(child), filt,
handler, arg, intr_priority(flags), flags, cookiep);
mips_intrcnt_setname(sc->sc_intr_counter[irq], event->ie_fullname);
ar71xx_pci_unmask_irq((void*)irq);
return (0);
}
static int
ar71xx_pci_teardown_intr(device_t dev, device_t child, struct resource *ires,
void *cookie)
{
struct ar71xx_pci_softc *sc = device_get_softc(dev);
int irq, result;
irq = rman_get_start(ires);
if (irq > AR71XX_PCI_IRQ_END)
panic("%s: bad irq %d", __func__, irq);
if (sc->sc_eventstab[irq] == NULL)
panic("Trying to teardown unoccupied IRQ");
ar71xx_pci_mask_irq((void*)irq);
result = intr_event_remove_handler(cookie);
if (!result)
sc->sc_eventstab[irq] = NULL;
return (result);
}
static int
ar71xx_pci_intr(void *arg)
{
struct ar71xx_pci_softc *sc = arg;
struct intr_event *event;
uint32_t reg, irq, mask;
reg = ATH_READ_REG(AR71XX_PCI_INTR_STATUS);
mask = ATH_READ_REG(AR71XX_PCI_INTR_MASK);
/*
* Handle only unmasked interrupts
*/
reg &= mask;
for (irq = AR71XX_PCI_IRQ_START; irq <= AR71XX_PCI_IRQ_END; irq++) {
if (reg & (1 << irq)) {
event = sc->sc_eventstab[irq];
if (!event || CK_SLIST_EMPTY(&event->ie_handlers)) {
/* Ignore timer interrupts */
if (irq != 0)
printf("Stray IRQ %d\n", irq);
continue;
}
/* Flush DDR FIFO for PCI/PCIe */
ar71xx_device_flush_ddr(AR71XX_CPU_DDR_FLUSH_PCIE);
/* TODO: frame instead of NULL? */
intr_event_handle(event, NULL);
mips_intrcnt_inc(sc->sc_intr_counter[irq]);
}
}
return (FILTER_HANDLED);
}
static int
ar71xx_pci_maxslots(device_t dev)
{
return (PCI_SLOTMAX);
}
static int
ar71xx_pci_route_interrupt(device_t pcib, device_t device, int pin)
{
struct ar71xx_pci_softc *sc = device_get_softc(pcib);
if (pci_get_slot(device) < sc->sc_baseslot)
panic("%s: PCI slot %d is less then AR71XX_PCI_BASE_SLOT",
__func__, pci_get_slot(device));
return (pci_get_slot(device) - sc->sc_baseslot);
}
static device_method_t ar71xx_pci_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, ar71xx_pci_probe),
DEVMETHOD(device_attach, ar71xx_pci_attach),
DEVMETHOD(device_shutdown, bus_generic_shutdown),
DEVMETHOD(device_suspend, bus_generic_suspend),
DEVMETHOD(device_resume, bus_generic_resume),
/* Bus interface */
DEVMETHOD(bus_read_ivar, ar71xx_pci_read_ivar),
DEVMETHOD(bus_write_ivar, ar71xx_pci_write_ivar),
DEVMETHOD(bus_alloc_resource, ar71xx_pci_alloc_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, ar71xx_pci_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
DEVMETHOD(bus_setup_intr, ar71xx_pci_setup_intr),
DEVMETHOD(bus_teardown_intr, ar71xx_pci_teardown_intr),
/* pcib interface */
DEVMETHOD(pcib_maxslots, ar71xx_pci_maxslots),
DEVMETHOD(pcib_read_config, ar71xx_pci_read_config),
DEVMETHOD(pcib_write_config, ar71xx_pci_write_config),
DEVMETHOD(pcib_route_interrupt, ar71xx_pci_route_interrupt),
DEVMETHOD(pcib_request_feature, pcib_request_feature_allow),
DEVMETHOD_END
};
static driver_t ar71xx_pci_driver = {
"pcib",
ar71xx_pci_methods,
sizeof(struct ar71xx_pci_softc),
};
static devclass_t ar71xx_pci_devclass;
DRIVER_MODULE(ar71xx_pci, nexus, ar71xx_pci_driver, ar71xx_pci_devclass, 0, 0);

View File

@ -1,200 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@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 unmodified, this list of conditions, and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <machine/bus.h>
#include <mips/atheros/ar71xx_pci_bus_space.h>
static bs_r_1_s_proto(pcimem);
static bs_r_2_s_proto(pcimem);
static bs_r_4_s_proto(pcimem);
static bs_w_1_s_proto(pcimem);
static bs_w_2_s_proto(pcimem);
static bs_w_4_s_proto(pcimem);
/*
* Bus space that handles offsets in word for 1/2 bytes read/write access.
* Byte order of values is handled by device drivers itself.
*/
static struct bus_space bus_space_pcimem = {
/* cookie */
(void *) 0,
/* mapping/unmapping */
generic_bs_map,
generic_bs_unmap,
generic_bs_subregion,
/* allocation/deallocation */
NULL,
NULL,
/* barrier */
generic_bs_barrier,
/* read (single) */
generic_bs_r_1,
generic_bs_r_2,
generic_bs_r_4,
NULL,
/* read multiple */
generic_bs_rm_1,
generic_bs_rm_2,
generic_bs_rm_4,
NULL,
/* read region */
generic_bs_rr_1,
generic_bs_rr_2,
generic_bs_rr_4,
NULL,
/* write (single) */
generic_bs_w_1,
generic_bs_w_2,
generic_bs_w_4,
NULL,
/* write multiple */
generic_bs_wm_1,
generic_bs_wm_2,
generic_bs_wm_4,
NULL,
/* write region */
NULL,
generic_bs_wr_2,
generic_bs_wr_4,
NULL,
/* set multiple */
NULL,
NULL,
NULL,
NULL,
/* set region */
NULL,
generic_bs_sr_2,
generic_bs_sr_4,
NULL,
/* copy */
NULL,
generic_bs_c_2,
NULL,
NULL,
/* read (single) stream */
pcimem_bs_r_1_s,
pcimem_bs_r_2_s,
pcimem_bs_r_4_s,
NULL,
/* read multiple stream */
generic_bs_rm_1,
generic_bs_rm_2,
generic_bs_rm_4,
NULL,
/* read region stream */
generic_bs_rr_1,
generic_bs_rr_2,
generic_bs_rr_4,
NULL,
/* write (single) stream */
pcimem_bs_w_1_s,
pcimem_bs_w_2_s,
pcimem_bs_w_4_s,
NULL,
/* write multiple stream */
generic_bs_wm_1,
generic_bs_wm_2,
generic_bs_wm_4,
NULL,
/* write region stream */
NULL,
generic_bs_wr_2,
generic_bs_wr_4,
NULL,
};
bus_space_tag_t ar71xx_bus_space_pcimem = &bus_space_pcimem;
static uint8_t
pcimem_bs_r_1_s(void *t, bus_space_handle_t h, bus_size_t o)
{
return readb(h + (o &~ 3) + (3 - (o & 3)));
}
static void
pcimem_bs_w_1_s(void *t, bus_space_handle_t h, bus_size_t o, u_int8_t v)
{
writeb(h + (o &~ 3) + (3 - (o & 3)), v);
}
static uint16_t
pcimem_bs_r_2_s(void *t, bus_space_handle_t h, bus_size_t o)
{
return readw(h + (o &~ 3) + (2 - (o & 3)));
}
static void
pcimem_bs_w_2_s(void *t, bus_space_handle_t h, bus_size_t o, uint16_t v)
{
writew(h + (o &~ 3) + (2 - (o & 3)), v);
}
static uint32_t
pcimem_bs_r_4_s(void *t, bus_space_handle_t h, bus_size_t o)
{
return le32toh(readl(h + o));
}
static void
pcimem_bs_w_4_s(void *t, bus_space_handle_t h, bus_size_t o, uint32_t v)
{
writel(h + o, htole32(v));
}

View File

@ -1,37 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@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 unmodified, this list of conditions, and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef __AR71XX_PCI_BUS_SPACEH__
#define __AR71XX_PCI_BUS_SPACEH__
extern bus_space_tag_t ar71xx_bus_space_pcimem;
#endif /* __AR71XX_PCI_BUS_SPACEH__ */

View File

@ -1,236 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2010 Adrian Chadd
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_ddb.h"
#include <sys/param.h>
#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/cons.h>
#include <sys/kdb.h>
#include <sys/reboot.h>
#include <vm/vm.h>
#include <vm/vm_page.h>
#include <net/ethernet.h>
#include <machine/clock.h>
#include <machine/cpu.h>
#include <machine/cpuregs.h>
#include <machine/hwfunc.h>
#include <machine/md_var.h>
#include <machine/trap.h>
#include <machine/vmparam.h>
#include <mips/atheros/ar71xxreg.h>
#include <mips/atheros/ar933xreg.h>
#include <mips/atheros/ar934xreg.h>
#include <mips/atheros/qca955xreg.h>
#include <mips/atheros/qca953xreg.h>
#include <mips/atheros/ar71xx_setup.h>
#include <mips/atheros/ar71xx_cpudef.h>
#include <mips/atheros/ar71xx_chip.h>
#include <mips/atheros/ar724x_chip.h>
#include <mips/atheros/ar91xx_chip.h>
#include <mips/atheros/ar933x_chip.h>
#include <mips/atheros/ar934x_chip.h>
#include <mips/atheros/qca953x_chip.h>
#include <mips/atheros/qca955x_chip.h>
#define AR71XX_SYS_TYPE_LEN 128
static char ar71xx_sys_type[AR71XX_SYS_TYPE_LEN];
enum ar71xx_soc_type ar71xx_soc;
struct ar71xx_cpu_def * ar71xx_cpu_ops = NULL;
void
ar71xx_detect_sys_type(void)
{
char *chip = "????";
uint32_t id;
uint32_t major;
uint32_t minor;
uint32_t rev = 0;
id = ATH_READ_REG(AR71XX_RST_RESET_REG_REV_ID);
major = id & REV_ID_MAJOR_MASK;
switch (major) {
case REV_ID_MAJOR_AR71XX:
minor = id & AR71XX_REV_ID_MINOR_MASK;
rev = id >> AR71XX_REV_ID_REVISION_SHIFT;
rev &= AR71XX_REV_ID_REVISION_MASK;
ar71xx_cpu_ops = &ar71xx_chip_def;
switch (minor) {
case AR71XX_REV_ID_MINOR_AR7130:
ar71xx_soc = AR71XX_SOC_AR7130;
chip = "7130";
break;
case AR71XX_REV_ID_MINOR_AR7141:
ar71xx_soc = AR71XX_SOC_AR7141;
chip = "7141";
break;
case AR71XX_REV_ID_MINOR_AR7161:
ar71xx_soc = AR71XX_SOC_AR7161;
chip = "7161";
break;
}
break;
case REV_ID_MAJOR_AR7240:
ar71xx_soc = AR71XX_SOC_AR7240;
chip = "7240";
ar71xx_cpu_ops = &ar724x_chip_def;
rev = (id & AR724X_REV_ID_REVISION_MASK);
break;
case REV_ID_MAJOR_AR7241:
ar71xx_soc = AR71XX_SOC_AR7241;
chip = "7241";
ar71xx_cpu_ops = &ar724x_chip_def;
rev = (id & AR724X_REV_ID_REVISION_MASK);
break;
case REV_ID_MAJOR_AR7242:
ar71xx_soc = AR71XX_SOC_AR7242;
chip = "7242";
ar71xx_cpu_ops = &ar724x_chip_def;
rev = (id & AR724X_REV_ID_REVISION_MASK);
break;
case REV_ID_MAJOR_AR913X:
minor = id & AR91XX_REV_ID_MINOR_MASK;
rev = id >> AR91XX_REV_ID_REVISION_SHIFT;
rev &= AR91XX_REV_ID_REVISION_MASK;
ar71xx_cpu_ops = &ar91xx_chip_def;
switch (minor) {
case AR91XX_REV_ID_MINOR_AR9130:
ar71xx_soc = AR71XX_SOC_AR9130;
chip = "9130";
break;
case AR91XX_REV_ID_MINOR_AR9132:
ar71xx_soc = AR71XX_SOC_AR9132;
chip = "9132";
break;
}
break;
case REV_ID_MAJOR_AR9330:
minor = 0;
rev = (id & AR933X_REV_ID_REVISION_MASK);
chip = "9330";
ar71xx_cpu_ops = &ar933x_chip_def;
ar71xx_soc = AR71XX_SOC_AR9330;
break;
case REV_ID_MAJOR_AR9331:
minor = 1;
rev = (id & AR933X_REV_ID_REVISION_MASK);
chip = "9331";
ar71xx_soc = AR71XX_SOC_AR9331;
ar71xx_cpu_ops = &ar933x_chip_def;
break;
case REV_ID_MAJOR_AR9341:
minor = 0;
rev = (id & AR934X_REV_ID_REVISION_MASK);
chip = "9341";
ar71xx_soc = AR71XX_SOC_AR9341;
ar71xx_cpu_ops = &ar934x_chip_def;
break;
case REV_ID_MAJOR_AR9342:
minor = 0;
rev = (id & AR934X_REV_ID_REVISION_MASK);
chip = "9342";
ar71xx_soc = AR71XX_SOC_AR9342;
ar71xx_cpu_ops = &ar934x_chip_def;
break;
case REV_ID_MAJOR_AR9344:
minor = 0;
rev = (id & AR934X_REV_ID_REVISION_MASK);
chip = "9344";
ar71xx_soc = AR71XX_SOC_AR9344;
ar71xx_cpu_ops = &ar934x_chip_def;
break;
case REV_ID_MAJOR_QCA9533:
minor = 0;
rev = (id & QCA953X_REV_ID_REVISION_MASK);
chip = "9533";
ar71xx_soc = AR71XX_SOC_QCA9533;
ar71xx_cpu_ops = &qca953x_chip_def;
break;
case REV_ID_MAJOR_QCA9533_V2:
minor = 0;
rev = (id & QCA953X_REV_ID_REVISION_MASK);
chip = "9533v2";
ar71xx_soc = AR71XX_SOC_QCA9533_V2;
ar71xx_cpu_ops = &qca953x_chip_def;
break;
case REV_ID_MAJOR_QCA9556:
minor = 0;
rev = (id & QCA955X_REV_ID_REVISION_MASK);
chip = "9556";
ar71xx_soc = AR71XX_SOC_QCA9556;
ar71xx_cpu_ops = &qca955x_chip_def;
break;
case REV_ID_MAJOR_QCA9558:
minor = 0;
rev = (id & QCA955X_REV_ID_REVISION_MASK);
chip = "9558";
ar71xx_soc = AR71XX_SOC_QCA9558;
ar71xx_cpu_ops = &qca955x_chip_def;
break;
default:
panic("ar71xx: unknown chip id:0x%08x\n", id);
}
sprintf(ar71xx_sys_type, "Atheros AR%s rev %u", chip, rev);
}
const char *
ar71xx_get_system_type(void)
{
return ar71xx_sys_type;
}

View File

@ -1,59 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2010 Adrian Chadd
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* $FreeBSD$ */
#ifndef __AR71XX_SETUP_H__
#define __AR71XX_SETUP_H__
enum ar71xx_soc_type {
AR71XX_SOC_UNKNOWN,
AR71XX_SOC_AR7130,
AR71XX_SOC_AR7141,
AR71XX_SOC_AR7161,
AR71XX_SOC_AR7240,
AR71XX_SOC_AR7241,
AR71XX_SOC_AR7242,
AR71XX_SOC_AR9130,
AR71XX_SOC_AR9132,
AR71XX_SOC_AR9330,
AR71XX_SOC_AR9331,
AR71XX_SOC_AR9341,
AR71XX_SOC_AR9342,
AR71XX_SOC_AR9344,
AR71XX_SOC_QCA9556,
AR71XX_SOC_QCA9558,
AR71XX_SOC_QCA9533,
AR71XX_SOC_QCA9533_V2,
};
extern enum ar71xx_soc_type ar71xx_soc;
extern void ar71xx_detect_sys_type(void);
extern const char *ar71xx_get_system_type(void);
#endif

View File

@ -1,296 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@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 unmodified, this list of conditions, and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/interrupt.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/rman.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <vm/vm_extern.h>
#include <machine/bus.h>
#include <machine/cpu.h>
#include <dev/spibus/spi.h>
#include <dev/spibus/spibusvar.h>
#include "spibus_if.h"
#include <mips/atheros/ar71xxreg.h>
#undef AR71XX_SPI_DEBUG
#ifdef AR71XX_SPI_DEBUG
#define dprintf printf
#else
#define dprintf(x, arg...)
#endif
/*
* register space access macros
*/
#define SPI_BARRIER_WRITE(sc) bus_barrier((sc)->sc_mem_res, 0, 0, \
BUS_SPACE_BARRIER_WRITE)
#define SPI_BARRIER_READ(sc) bus_barrier((sc)->sc_mem_res, 0, 0, \
BUS_SPACE_BARRIER_READ)
#define SPI_BARRIER_RW(sc) bus_barrier((sc)->sc_mem_res, 0, 0, \
BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE)
#define SPI_WRITE(sc, reg, val) do { \
bus_write_4(sc->sc_mem_res, (reg), (val)); \
} while (0)
#define SPI_READ(sc, reg) bus_read_4(sc->sc_mem_res, (reg))
#define SPI_SET_BITS(sc, reg, bits) \
SPI_WRITE(sc, reg, SPI_READ(sc, (reg)) | (bits))
#define SPI_CLEAR_BITS(sc, reg, bits) \
SPI_WRITE(sc, reg, SPI_READ(sc, (reg)) & ~(bits))
struct ar71xx_spi_softc {
device_t sc_dev;
struct resource *sc_mem_res;
uint32_t sc_reg_ctrl;
};
static int
ar71xx_spi_probe(device_t dev)
{
device_set_desc(dev, "AR71XX SPI");
return (BUS_PROBE_NOWILDCARD);
}
static int
ar71xx_spi_attach(device_t dev)
{
struct ar71xx_spi_softc *sc = device_get_softc(dev);
int rid;
sc->sc_dev = dev;
rid = 0;
sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
RF_ACTIVE);
if (!sc->sc_mem_res) {
device_printf(dev, "Could not map memory\n");
return (ENXIO);
}
SPI_WRITE(sc, AR71XX_SPI_FS, 1);
/* Flush out read before reading the control register */
SPI_BARRIER_WRITE(sc);
sc->sc_reg_ctrl = SPI_READ(sc, AR71XX_SPI_CTRL);
/*
* XXX TODO: document what the SPI control register does.
*/
SPI_WRITE(sc, AR71XX_SPI_CTRL, 0x43);
/*
* Ensure the config register write has gone out before configuring
* the chip select mask.
*/
SPI_BARRIER_WRITE(sc);
SPI_WRITE(sc, AR71XX_SPI_IO_CTRL, SPI_IO_CTRL_CSMASK);
/*
* .. and ensure the write has gone out before continuing.
*/
SPI_BARRIER_WRITE(sc);
device_add_child(dev, "spibus", -1);
return (bus_generic_attach(dev));
}
static void
ar71xx_spi_chip_activate(struct ar71xx_spi_softc *sc, int cs)
{
uint32_t ioctrl = SPI_IO_CTRL_CSMASK;
/*
* Put respective CSx to low
*/
ioctrl &= ~(SPI_IO_CTRL_CS0 << cs);
/*
* Make sure any other writes have gone out to the
* device before changing the chip select line;
* then ensure that it has made it out to the device
* before continuing.
*/
SPI_BARRIER_WRITE(sc);
SPI_WRITE(sc, AR71XX_SPI_IO_CTRL, ioctrl);
SPI_BARRIER_WRITE(sc);
}
static void
ar71xx_spi_chip_deactivate(struct ar71xx_spi_softc *sc, int cs)
{
/*
* Put all CSx to high
*/
SPI_WRITE(sc, AR71XX_SPI_IO_CTRL, SPI_IO_CTRL_CSMASK);
}
static uint8_t
ar71xx_spi_txrx(struct ar71xx_spi_softc *sc, int cs, uint8_t data)
{
int bit;
/* CS0 */
uint32_t ioctrl = SPI_IO_CTRL_CSMASK;
/*
* low-level for selected CS
*/
ioctrl &= ~(SPI_IO_CTRL_CS0 << cs);
uint32_t iod, rds;
for (bit = 7; bit >=0; bit--) {
if (data & (1 << bit))
iod = ioctrl | SPI_IO_CTRL_DO;
else
iod = ioctrl & ~SPI_IO_CTRL_DO;
SPI_BARRIER_WRITE(sc);
SPI_WRITE(sc, AR71XX_SPI_IO_CTRL, iod);
SPI_BARRIER_WRITE(sc);
SPI_WRITE(sc, AR71XX_SPI_IO_CTRL, iod | SPI_IO_CTRL_CLK);
}
/*
* Provide falling edge for connected device by clear clock bit.
*/
SPI_BARRIER_WRITE(sc);
SPI_WRITE(sc, AR71XX_SPI_IO_CTRL, iod);
SPI_BARRIER_WRITE(sc);
rds = SPI_READ(sc, AR71XX_SPI_RDS);
return (rds & 0xff);
}
static int
ar71xx_spi_transfer(device_t dev, device_t child, struct spi_command *cmd)
{
struct ar71xx_spi_softc *sc;
uint32_t cs;
uint8_t *buf_in, *buf_out;
int i;
sc = device_get_softc(dev);
spibus_get_cs(child, &cs);
cs &= ~SPIBUS_CS_HIGH;
ar71xx_spi_chip_activate(sc, cs);
KASSERT(cmd->tx_cmd_sz == cmd->rx_cmd_sz,
("TX/RX command sizes should be equal"));
KASSERT(cmd->tx_data_sz == cmd->rx_data_sz,
("TX/RX data sizes should be equal"));
/*
* Transfer command
*/
buf_out = (uint8_t *)cmd->tx_cmd;
buf_in = (uint8_t *)cmd->rx_cmd;
for (i = 0; i < cmd->tx_cmd_sz; i++)
buf_in[i] = ar71xx_spi_txrx(sc, cs, buf_out[i]);
/*
* Receive/transmit data (depends on command)
*/
buf_out = (uint8_t *)cmd->tx_data;
buf_in = (uint8_t *)cmd->rx_data;
for (i = 0; i < cmd->tx_data_sz; i++)
buf_in[i] = ar71xx_spi_txrx(sc, cs, buf_out[i]);
ar71xx_spi_chip_deactivate(sc, cs);
return (0);
}
static int
ar71xx_spi_detach(device_t dev)
{
struct ar71xx_spi_softc *sc = device_get_softc(dev);
/*
* Ensure any other writes to the device are finished
* before we tear down the SPI device.
*/
SPI_BARRIER_WRITE(sc);
/*
* Restore the control register; ensure it has hit the
* hardware before continuing.
*/
SPI_WRITE(sc, AR71XX_SPI_CTRL, sc->sc_reg_ctrl);
SPI_BARRIER_WRITE(sc);
/*
* And now, put the flash back into mapped IO mode and
* ensure _that_ has completed before we finish up.
*/
SPI_WRITE(sc, AR71XX_SPI_FS, 0);
SPI_BARRIER_WRITE(sc);
if (sc->sc_mem_res)
bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
return (0);
}
static device_method_t ar71xx_spi_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, ar71xx_spi_probe),
DEVMETHOD(device_attach, ar71xx_spi_attach),
DEVMETHOD(device_detach, ar71xx_spi_detach),
DEVMETHOD(spibus_transfer, ar71xx_spi_transfer),
{0, 0}
};
static driver_t ar71xx_spi_driver = {
"spi",
ar71xx_spi_methods,
sizeof(struct ar71xx_spi_softc),
};
static devclass_t ar71xx_spi_devclass;
DRIVER_MODULE(ar71xx_spi, nexus, ar71xx_spi_driver, ar71xx_spi_devclass, 0, 0);

View File

@ -1,184 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@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 unmodified, 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.
*/
/*
* Watchdog driver for AR71xx
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/eventhandler.h>
#include <sys/systm.h>
#include <sys/watchdog.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/sysctl.h>
#include <mips/atheros/ar71xxreg.h>
#include <mips/atheros/ar71xx_cpudef.h>
struct ar71xx_wdog_softc {
device_t dev;
int armed;
int reboot_from_watchdog;
int watchdog_nmi;
int debug;
};
static void
ar71xx_wdog_watchdog_fn(void *private, u_int cmd, int *error)
{
struct ar71xx_wdog_softc *sc = private;
uint64_t timer_val;
int action;
action = RST_WDOG_ACTION_RESET;
if (sc->watchdog_nmi != 0)
action = RST_WDOG_ACTION_NMI;
cmd &= WD_INTERVAL;
if (sc->debug)
device_printf(sc->dev, "%s: : cmd: %x\n", __func__, cmd);
if (cmd > 0) {
timer_val = (uint64_t)(1ULL << cmd) * ar71xx_ahb_freq() /
1000000000;
/*
* Clamp the timer value in case we overflow.
*/
if (timer_val > 0xffffffff)
timer_val = 0xffffffff;
if (sc->debug)
device_printf(sc->dev, "%s: programming timer: %jx\n",
__func__, (uintmax_t) timer_val);
/*
* Make sure the watchdog is set to NOACTION and give it
* time to take.
*/
ATH_WRITE_REG(AR71XX_RST_WDOG_CONTROL, RST_WDOG_ACTION_NOACTION);
wmb();
DELAY(100);
/*
* Update the timer value. It's already clamped at this
* point so we don't have to wrap/clamp it here.
*/
ATH_WRITE_REG(AR71XX_RST_WDOG_TIMER, timer_val);
wmb();
DELAY(100);
/*
* And now, arm.
*/
ATH_WRITE_REG(AR71XX_RST_WDOG_CONTROL, action);
sc->armed = 1;
*error = 0;
} else {
if (sc->debug)
device_printf(sc->dev, "%s: disarming\n", __func__);
if (sc->armed) {
ATH_WRITE_REG(AR71XX_RST_WDOG_CONTROL,
RST_WDOG_ACTION_NOACTION);
sc->armed = 0;
}
}
}
static int
ar71xx_wdog_probe(device_t dev)
{
device_set_desc(dev, "Atheros AR71XX watchdog timer");
return (BUS_PROBE_NOWILDCARD);
}
static void
ar71xx_wdog_sysctl(device_t dev)
{
struct ar71xx_wdog_softc *sc = device_get_softc(dev);
struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->dev);
struct sysctl_oid *tree = device_get_sysctl_tree(sc->dev);
SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
"debug", CTLFLAG_RW, &sc->debug, 0,
"enable watchdog debugging");
SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
"nmi", CTLFLAG_RW, &sc->watchdog_nmi, 0,
"watchdog triggers NMI instead of reset");
SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
"armed", CTLFLAG_RD, &sc->armed, 0,
"whether the watchdog is armed");
SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
"reboot_from_watchdog", CTLFLAG_RD, &sc->reboot_from_watchdog, 0,
"whether the system rebooted from the watchdog");
}
static int
ar71xx_wdog_attach(device_t dev)
{
struct ar71xx_wdog_softc *sc = device_get_softc(dev);
/* Initialise */
sc->reboot_from_watchdog = 0;
sc->armed = 0;
sc->debug = 0;
if (ATH_READ_REG(AR71XX_RST_WDOG_CONTROL) & RST_WDOG_LAST) {
device_printf (dev,
"Previous reset was due to watchdog timeout\n");
sc->reboot_from_watchdog = 1;
}
ATH_WRITE_REG(AR71XX_RST_WDOG_CONTROL, RST_WDOG_ACTION_NOACTION);
sc->dev = dev;
EVENTHANDLER_REGISTER(watchdog_list, ar71xx_wdog_watchdog_fn, sc, 0);
ar71xx_wdog_sysctl(dev);
return (0);
}
static device_method_t ar71xx_wdog_methods[] = {
DEVMETHOD(device_probe, ar71xx_wdog_probe),
DEVMETHOD(device_attach, ar71xx_wdog_attach),
{0, 0},
};
static driver_t ar71xx_wdog_driver = {
"ar71xx_wdog",
ar71xx_wdog_methods,
sizeof(struct ar71xx_wdog_softc),
};
static devclass_t ar71xx_wdog_devclass;
DRIVER_MODULE(ar71xx_wdog, nexus, ar71xx_wdog_driver, ar71xx_wdog_devclass, 0, 0);

View File

@ -1,576 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2009 Oleksandr Tymoshenko
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* $FreeBSD$ */
#ifndef _AR71XX_REG_H_
#define _AR71XX_REG_H_
/* PCI region */
#define AR71XX_PCI_MEM_BASE 0x10000000
/*
* PCI mem windows is 0x08000000 bytes long but we exclude control
* region from the resource manager
*/
#define AR71XX_PCI_MEM_SIZE 0x07000000
#define AR71XX_PCI_IRQ_START 0
#define AR71XX_PCI_IRQ_END 2
#define AR71XX_PCI_NIRQS 3
/*
* PCI devices slots are starting from this number
*/
#define AR71XX_PCI_BASE_SLOT 17
/* PCI config registers */
#define AR71XX_PCI_LCONF_CMD 0x17010000
#define PCI_LCONF_CMD_READ 0x00000000
#define PCI_LCONF_CMD_WRITE 0x00010000
#define AR71XX_PCI_LCONF_WRITE_DATA 0x17010004
#define AR71XX_PCI_LCONF_READ_DATA 0x17010008
#define AR71XX_PCI_CONF_ADDR 0x1701000C
#define AR71XX_PCI_CONF_CMD 0x17010010
#define PCI_CONF_CMD_READ 0x0000000A
#define PCI_CONF_CMD_WRITE 0x0000000B
#define AR71XX_PCI_CONF_WRITE_DATA 0x17010014
#define AR71XX_PCI_CONF_READ_DATA 0x17010018
#define AR71XX_PCI_ERROR 0x1701001C
#define AR71XX_PCI_ERROR_ADDR 0x17010020
#define AR71XX_PCI_AHB_ERROR 0x17010024
#define AR71XX_PCI_AHB_ERROR_ADDR 0x17010028
/* APB region */
/*
* Size is not really true actual APB window size is
* 0x01000000 but it should handle OHCI memory as well
* because this controller's interrupt is routed through
* APB.
*/
#define AR71XX_APB_BASE 0x18000000
#define AR71XX_APB_SIZE 0x06000000
/* DDR registers */
#define AR71XX_DDR_CONFIG 0x18000000
#define AR71XX_DDR_CONFIG2 0x18000004
#define AR71XX_DDR_MODE_REGISTER 0x18000008
#define AR71XX_DDR_EXT_MODE_REGISTER 0x1800000C
#define AR71XX_DDR_CONTROL 0x18000010
#define AR71XX_DDR_REFRESH 0x18000014
#define AR71XX_DDR_RD_DATA_THIS_CYCLE 0x18000018
#define AR71XX_TAP_CONTROL0 0x1800001C
#define AR71XX_TAP_CONTROL1 0x18000020
#define AR71XX_TAP_CONTROL2 0x18000024
#define AR71XX_TAP_CONTROL3 0x18000028
#define AR71XX_PCI_WINDOW0 0x1800007C
#define AR71XX_PCI_WINDOW1 0x18000080
#define AR71XX_PCI_WINDOW2 0x18000084
#define AR71XX_PCI_WINDOW3 0x18000088
#define AR71XX_PCI_WINDOW4 0x1800008C
#define AR71XX_PCI_WINDOW5 0x18000090
#define AR71XX_PCI_WINDOW6 0x18000094
#define AR71XX_PCI_WINDOW7 0x18000098
#define AR71XX_WB_FLUSH_GE0 0x1800009C
#define AR71XX_WB_FLUSH_GE1 0x180000A0
#define AR71XX_WB_FLUSH_USB 0x180000A4
#define AR71XX_WB_FLUSH_PCI 0x180000A8
/*
* Values for PCI_WINDOW_X registers
*/
#define PCI_WINDOW0_ADDR 0x10000000
#define PCI_WINDOW1_ADDR 0x11000000
#define PCI_WINDOW2_ADDR 0x12000000
#define PCI_WINDOW3_ADDR 0x13000000
#define PCI_WINDOW4_ADDR 0x14000000
#define PCI_WINDOW5_ADDR 0x15000000
#define PCI_WINDOW6_ADDR 0x16000000
#define PCI_WINDOW7_ADDR 0x17000000
/* This value enables acces to PCI config registers */
#define PCI_WINDOW7_CONF_ADDR 0x07000000
#define AR71XX_UART_ADDR 0x18020000
#define AR71XX_UART_THR 0x0
#define AR71XX_UART_LSR 0x14
#define AR71XX_UART_LSR_THRE (1 << 5)
#define AR71XX_UART_LSR_TEMT (1 << 6)
#define AR71XX_USB_CTRL_FLADJ 0x18030000
#define USB_CTRL_FLADJ_HOST_SHIFT 12
#define USB_CTRL_FLADJ_A5_SHIFT 10
#define USB_CTRL_FLADJ_A4_SHIFT 8
#define USB_CTRL_FLADJ_A3_SHIFT 6
#define USB_CTRL_FLADJ_A2_SHIFT 4
#define USB_CTRL_FLADJ_A1_SHIFT 2
#define USB_CTRL_FLADJ_A0_SHIFT 0
#define AR71XX_USB_CTRL_CONFIG 0x18030004
#define USB_CTRL_CONFIG_OHCI_DES_SWAP (1 << 19)
#define USB_CTRL_CONFIG_OHCI_BUF_SWAP (1 << 18)
#define USB_CTRL_CONFIG_EHCI_DES_SWAP (1 << 17)
#define USB_CTRL_CONFIG_EHCI_BUF_SWAP (1 << 16)
#define USB_CTRL_CONFIG_DISABLE_XTL (1 << 13)
#define USB_CTRL_CONFIG_OVERRIDE_XTL (1 << 12)
#define USB_CTRL_CONFIG_CLK_SEL_SHIFT 4
#define USB_CTRL_CONFIG_CLK_SEL_MASK 3
#define USB_CTRL_CONFIG_CLK_SEL_12 0
#define USB_CTRL_CONFIG_CLK_SEL_24 1
#define USB_CTRL_CONFIG_CLK_SEL_48 2
#define USB_CTRL_CONFIG_OVER_CURRENT_AS_GPIO (1 << 8)
#define USB_CTRL_CONFIG_SS_SIMULATION_MODE (1 << 2)
#define USB_CTRL_CONFIG_RESUME_UTMI_PLS_DIS (1 << 1)
#define USB_CTRL_CONFIG_UTMI_BACKWARD_ENB (1 << 0)
#define AR71XX_GPIO_BASE 0x18040000
#define AR71XX_GPIO_OE 0x00
#define AR71XX_GPIO_IN 0x04
#define AR71XX_GPIO_OUT 0x08
#define AR71XX_GPIO_SET 0x0c
#define AR71XX_GPIO_CLEAR 0x10
#define AR71XX_GPIO_INT 0x14
#define AR71XX_GPIO_INT_TYPE 0x18
#define AR71XX_GPIO_INT_POLARITY 0x1c
#define AR71XX_GPIO_INT_PENDING 0x20
#define AR71XX_GPIO_INT_MASK 0x24
#define AR71XX_GPIO_FUNCTION 0x28
#define GPIO_FUNC_STEREO_EN (1 << 17)
#define GPIO_FUNC_SLIC_EN (1 << 16)
#define GPIO_FUNC_SPI_CS2_EN (1 << 13)
/* CS2 is shared with GPIO_1 */
#define GPIO_FUNC_SPI_CS1_EN (1 << 12)
/* CS1 is shared with GPIO_0 */
#define GPIO_FUNC_UART_EN (1 << 8)
#define GPIO_FUNC_USB_OC_EN (1 << 4)
#define GPIO_FUNC_USB_CLK_EN (0)
#define AR71XX_BASE_FREQ 40000000
#define AR71XX_PLL_CPU_BASE 0x18050000
#define AR71XX_PLL_CPU_CONFIG 0x18050000
#define PLL_SW_UPDATE (1U << 31)
#define PLL_LOCKED (1 << 30)
#define PLL_AHB_DIV_SHIFT 20
#define PLL_AHB_DIV_MASK 7
#define PLL_DDR_DIV_SEL_SHIFT 18
#define PLL_DDR_DIV_SEL_MASK 3
#define PLL_CPU_DIV_SEL_SHIFT 16
#define PLL_CPU_DIV_SEL_MASK 3
#define PLL_LOOP_BW_SHIFT 12
#define PLL_LOOP_BW_MASK 0xf
#define PLL_DIV_IN_SHIFT 10
#define PLL_DIV_IN_MASK 3
#define PLL_DIV_OUT_SHIFT 8
#define PLL_DIV_OUT_MASK 3
#define PLL_FB_SHIFT 3
#define PLL_FB_MASK 0x1f
#define PLL_BYPASS (1 << 1)
#define PLL_POWER_DOWN (1 << 0)
#define AR71XX_PLL_SEC_CONFIG 0x18050004
#define AR71XX_PLL_ETH0_SHIFT 17
#define AR71XX_PLL_ETH1_SHIFT 19
#define AR71XX_PLL_CPU_CLK_CTRL 0x18050008
#define AR71XX_PLL_ETH_INT0_CLK 0x18050010
#define AR71XX_PLL_ETH_INT1_CLK 0x18050014
#define XPLL_ETH_INT_CLK_10 0x00991099
#define XPLL_ETH_INT_CLK_100 0x00441011
#define XPLL_ETH_INT_CLK_1000 0x13110000
#define XPLL_ETH_INT_CLK_1000_GMII 0x14110000
#define PLL_ETH_INT_CLK_10 0x00991099
#define PLL_ETH_INT_CLK_100 0x00001099
#define PLL_ETH_INT_CLK_1000 0x00110000
#define AR71XX_PLL_ETH_EXT_CLK 0x18050018
#define AR71XX_PLL_PCI_CLK 0x1805001C
/* Reset block */
#define AR71XX_RST_BLOCK_BASE 0x18060000
#define AR71XX_RST_WDOG_CONTROL 0x18060008
#define RST_WDOG_LAST (1U << 31)
#define RST_WDOG_ACTION_MASK 3
#define RST_WDOG_ACTION_RESET 3
#define RST_WDOG_ACTION_NMI 2
#define RST_WDOG_ACTION_GP_INTR 1
#define RST_WDOG_ACTION_NOACTION 0
#define AR71XX_RST_WDOG_TIMER 0x1806000C
/*
* APB interrupt status and mask register and interrupt bit numbers for
*/
#define AR71XX_MISC_INTR_STATUS 0x18060010
#define AR71XX_MISC_INTR_MASK 0x18060014
#define MISC_INTR_TIMER 0
#define MISC_INTR_ERROR 1
#define MISC_INTR_GPIO 2
#define MISC_INTR_UART 3
#define MISC_INTR_WATCHDOG 4
#define MISC_INTR_PERF 5
#define MISC_INTR_OHCI 6
#define MISC_INTR_DMA 7
#define AR71XX_PCI_INTR_STATUS 0x18060018
#define AR71XX_PCI_INTR_MASK 0x1806001C
#define PCI_INTR_CORE (1 << 4)
#define AR71XX_RST_RESET 0x18060024
#define RST_RESET_FULL_CHIP (1 << 24) /* Same as pulling
the reset pin */
#define RST_RESET_CPU_COLD (1 << 20) /* Cold reset */
#define RST_RESET_GE1_MAC (1 << 13)
#define RST_RESET_GE1_PHY (1 << 12)
#define RST_RESET_GE0_MAC (1 << 9)
#define RST_RESET_GE0_PHY (1 << 8)
#define RST_RESET_USB_OHCI_DLL (1 << 6)
#define RST_RESET_USB_HOST (1 << 5)
#define RST_RESET_USB_PHY (1 << 4)
#define RST_RESET_PCI_BUS (1 << 1)
#define RST_RESET_PCI_CORE (1 << 0)
/* Chipset revision details */
#define AR71XX_RST_RESET_REG_REV_ID 0x18060090
#define REV_ID_MAJOR_MASK 0xfff0
#define REV_ID_MAJOR_AR71XX 0x00a0
#define REV_ID_MAJOR_AR913X 0x00b0
#define REV_ID_MAJOR_AR7240 0x00c0
#define REV_ID_MAJOR_AR7241 0x0100
#define REV_ID_MAJOR_AR7242 0x1100
/* AR71XX chipset revision details */
#define AR71XX_REV_ID_MINOR_MASK 0x3
#define AR71XX_REV_ID_MINOR_AR7130 0x0
#define AR71XX_REV_ID_MINOR_AR7141 0x1
#define AR71XX_REV_ID_MINOR_AR7161 0x2
#define AR71XX_REV_ID_REVISION_MASK 0x3
#define AR71XX_REV_ID_REVISION_SHIFT 2
/* AR724X chipset revision details */
#define AR724X_REV_ID_REVISION_MASK 0x3
/* AR91XX chipset revision details */
#define AR91XX_REV_ID_MINOR_MASK 0x3
#define AR91XX_REV_ID_MINOR_AR9130 0x0
#define AR91XX_REV_ID_MINOR_AR9132 0x1
#define AR91XX_REV_ID_REVISION_MASK 0x3
#define AR91XX_REV_ID_REVISION_SHIFT 2
typedef enum {
AR71XX_MII_MODE_NONE = 0,
AR71XX_MII_MODE_GMII,
AR71XX_MII_MODE_MII,
AR71XX_MII_MODE_RGMII,
AR71XX_MII_MODE_RMII,
AR71XX_MII_MODE_SGMII /* not hardware defined, though! */
} ar71xx_mii_mode;
/*
* AR71xx MII control region
*/
#define AR71XX_MII0_CTRL 0x18070000
#define MII_CTRL_SPEED_SHIFT 4
#define MII_CTRL_SPEED_MASK 3
#define MII_CTRL_SPEED_10 0
#define MII_CTRL_SPEED_100 1
#define MII_CTRL_SPEED_1000 2
#define MII_CTRL_IF_MASK 3
#define MII_CTRL_IF_SHIFT 0
#define MII0_CTRL_IF_GMII 0
#define MII0_CTRL_IF_MII 1
#define MII0_CTRL_IF_RGMII 2
#define MII0_CTRL_IF_RMII 3
#define AR71XX_MII1_CTRL 0x18070004
#define MII1_CTRL_IF_RGMII 0
#define MII1_CTRL_IF_RMII 1
/*
* GigE adapters region
*/
#define AR71XX_MAC0_BASE 0x19000000
#define AR71XX_MAC1_BASE 0x1A000000
#define AR71XX_MAC_CFG1 0x00
#define MAC_CFG1_SOFT_RESET (1U << 31)
#define MAC_CFG1_SIMUL_RESET (1 << 30)
#define MAC_CFG1_MAC_RX_BLOCK_RESET (1 << 19)
#define MAC_CFG1_MAC_TX_BLOCK_RESET (1 << 18)
#define MAC_CFG1_RX_FUNC_RESET (1 << 17)
#define MAC_CFG1_TX_FUNC_RESET (1 << 16)
#define MAC_CFG1_LOOPBACK (1 << 8)
#define MAC_CFG1_RXFLOW_CTRL (1 << 5)
#define MAC_CFG1_TXFLOW_CTRL (1 << 4)
#define MAC_CFG1_SYNC_RX (1 << 3)
#define MAC_CFG1_RX_ENABLE (1 << 2)
#define MAC_CFG1_SYNC_TX (1 << 1)
#define MAC_CFG1_TX_ENABLE (1 << 0)
#define AR71XX_MAC_CFG2 0x04
#define MAC_CFG2_PREAMBLE_LEN_MASK 0xf
#define MAC_CFG2_PREAMBLE_LEN_SHIFT 12
#define MAC_CFG2_IFACE_MODE_1000 (2 << 8)
#define MAC_CFG2_IFACE_MODE_10_100 (1 << 8)
#define MAC_CFG2_IFACE_MODE_SHIFT 8
#define MAC_CFG2_IFACE_MODE_MASK 3
#define MAC_CFG2_HUGE_FRAME (1 << 5)
#define MAC_CFG2_LENGTH_FIELD (1 << 4)
#define MAC_CFG2_ENABLE_PADCRC (1 << 2)
#define MAC_CFG2_ENABLE_CRC (1 << 1)
#define MAC_CFG2_FULL_DUPLEX (1 << 0)
#define AR71XX_MAC_IFG 0x08
#define AR71XX_MAC_HDUPLEX 0x0C
#define AR71XX_MAC_MAX_FRAME_LEN 0x10
#define AR71XX_MAC_MII_CFG 0x20
#define MAC_MII_CFG_RESET (1U << 31)
#define MAC_MII_CFG_SCAN_AUTO_INC (1 << 5)
#define MAC_MII_CFG_PREAMBLE_SUP (1 << 4)
#define MAC_MII_CFG_CLOCK_SELECT_MASK 0x7
#define MAC_MII_CFG_CLOCK_SELECT_MASK_AR933X 0xf
#define MAC_MII_CFG_CLOCK_DIV_4 0
#define MAC_MII_CFG_CLOCK_DIV_6 2
#define MAC_MII_CFG_CLOCK_DIV_8 3
#define MAC_MII_CFG_CLOCK_DIV_10 4
#define MAC_MII_CFG_CLOCK_DIV_14 5
#define MAC_MII_CFG_CLOCK_DIV_20 6
#define MAC_MII_CFG_CLOCK_DIV_28 7
/* .. and the AR933x/AR934x extensions */
#define MAC_MII_CFG_CLOCK_DIV_34 8
#define MAC_MII_CFG_CLOCK_DIV_42 9
#define MAC_MII_CFG_CLOCK_DIV_50 10
#define MAC_MII_CFG_CLOCK_DIV_58 11
#define MAC_MII_CFG_CLOCK_DIV_66 12
#define MAC_MII_CFG_CLOCK_DIV_74 13
#define MAC_MII_CFG_CLOCK_DIV_82 14
#define MAC_MII_CFG_CLOCK_DIV_98 15
#define AR71XX_MAC_MII_CMD 0x24
#define MAC_MII_CMD_SCAN_CYCLE (1 << 1)
#define MAC_MII_CMD_READ 1
#define MAC_MII_CMD_WRITE 0
#define AR71XX_MAC_MII_ADDR 0x28
#define MAC_MII_PHY_ADDR_SHIFT 8
#define MAC_MII_PHY_ADDR_MASK 0xff
#define MAC_MII_REG_MASK 0x1f
#define AR71XX_MAC_MII_CONTROL 0x2C
#define MAC_MII_CONTROL_MASK 0xffff
#define AR71XX_MAC_MII_STATUS 0x30
#define MAC_MII_STATUS_MASK 0xffff
#define AR71XX_MAC_MII_INDICATOR 0x34
#define MAC_MII_INDICATOR_NOT_VALID (1 << 2)
#define MAC_MII_INDICATOR_SCANNING (1 << 1)
#define MAC_MII_INDICATOR_BUSY (1 << 0)
#define AR71XX_MAC_IFCONTROL 0x38
#define MAC_IFCONTROL_SPEED (1 << 16)
#define AR71XX_MAC_STA_ADDR1 0x40
#define AR71XX_MAC_STA_ADDR2 0x44
#define AR71XX_MAC_FIFO_CFG0 0x48
#define FIFO_CFG0_TX_FABRIC (1 << 4)
#define FIFO_CFG0_TX_SYSTEM (1 << 3)
#define FIFO_CFG0_RX_FABRIC (1 << 2)
#define FIFO_CFG0_RX_SYSTEM (1 << 1)
#define FIFO_CFG0_WATERMARK (1 << 0)
#define FIFO_CFG0_ALL ((1 << 5) - 1)
#define FIFO_CFG0_ENABLE_SHIFT 8
#define AR71XX_MAC_FIFO_CFG1 0x4C
#define AR71XX_MAC_FIFO_CFG2 0x50
#define AR71XX_MAC_FIFO_TX_THRESHOLD 0x54
#define AR71XX_MAC_FIFO_RX_FILTMATCH 0x58
/*
* These flags applicable both to AR71XX_MAC_FIFO_RX_FILTMASK and
* to AR71XX_MAC_FIFO_RX_FILTMATCH
*/
#define FIFO_RX_MATCH_UNICAST (1 << 17)
#define FIFO_RX_MATCH_TRUNC_FRAME (1 << 16)
#define FIFO_RX_MATCH_VLAN_TAG (1 << 15)
#define FIFO_RX_MATCH_UNSUP_OPCODE (1 << 14)
#define FIFO_RX_MATCH_PAUSE_FRAME (1 << 13)
#define FIFO_RX_MATCH_CTRL_FRAME (1 << 12)
#define FIFO_RX_MATCH_LONG_EVENT (1 << 11)
#define FIFO_RX_MATCH_DRIBBLE_NIBBLE (1 << 10)
#define FIFO_RX_MATCH_BCAST (1 << 9)
#define FIFO_RX_MATCH_MCAST (1 << 8)
#define FIFO_RX_MATCH_OK (1 << 7)
#define FIFO_RX_MATCH_OORANGE (1 << 6)
#define FIFO_RX_MATCH_LEN_MSMTCH (1 << 5)
#define FIFO_RX_MATCH_CRC_ERROR (1 << 4)
#define FIFO_RX_MATCH_CODE_ERROR (1 << 3)
#define FIFO_RX_MATCH_FALSE_CARRIER (1 << 2)
#define FIFO_RX_MATCH_RX_DV_EVENT (1 << 1)
#define FIFO_RX_MATCH_DROP_EVENT (1 << 0)
/*
* Exclude unicast and truncated frames from matching
*/
#define FIFO_RX_FILTMATCH_DEFAULT \
(FIFO_RX_MATCH_VLAN_TAG | \
FIFO_RX_MATCH_UNSUP_OPCODE | \
FIFO_RX_MATCH_PAUSE_FRAME | \
FIFO_RX_MATCH_CTRL_FRAME | \
FIFO_RX_MATCH_LONG_EVENT | \
FIFO_RX_MATCH_DRIBBLE_NIBBLE | \
FIFO_RX_MATCH_BCAST | \
FIFO_RX_MATCH_MCAST | \
FIFO_RX_MATCH_OK | \
FIFO_RX_MATCH_OORANGE | \
FIFO_RX_MATCH_LEN_MSMTCH | \
FIFO_RX_MATCH_CRC_ERROR | \
FIFO_RX_MATCH_CODE_ERROR | \
FIFO_RX_MATCH_FALSE_CARRIER | \
FIFO_RX_MATCH_RX_DV_EVENT | \
FIFO_RX_MATCH_DROP_EVENT)
#define AR71XX_MAC_FIFO_RX_FILTMASK 0x5C
#define FIFO_RX_MASK_BYTE_MODE (1 << 19)
#define FIFO_RX_MASK_NO_SHORT_FRAME (1 << 18)
#define FIFO_RX_MASK_BIT17 (1 << 17)
#define FIFO_RX_MASK_BIT16 (1 << 16)
#define FIFO_RX_MASK_TRUNC_FRAME (1 << 15)
#define FIFO_RX_MASK_LONG_EVENT (1 << 14)
#define FIFO_RX_MASK_VLAN_TAG (1 << 13)
#define FIFO_RX_MASK_UNSUP_OPCODE (1 << 12)
#define FIFO_RX_MASK_PAUSE_FRAME (1 << 11)
#define FIFO_RX_MASK_CTRL_FRAME (1 << 10)
#define FIFO_RX_MASK_DRIBBLE_NIBBLE (1 << 9)
#define FIFO_RX_MASK_BCAST (1 << 8)
#define FIFO_RX_MASK_MCAST (1 << 7)
#define FIFO_RX_MASK_OK (1 << 6)
#define FIFO_RX_MASK_OORANGE (1 << 5)
#define FIFO_RX_MASK_LEN_MSMTCH (1 << 4)
#define FIFO_RX_MASK_CODE_ERROR (1 << 3)
#define FIFO_RX_MASK_FALSE_CARRIER (1 << 2)
#define FIFO_RX_MASK_RX_DV_EVENT (1 << 1)
#define FIFO_RX_MASK_DROP_EVENT (1 << 0)
/*
* Len. mismatch, unsup. opcode and short frmae bits excluded
*/
#define FIFO_RX_FILTMASK_DEFAULT \
(FIFO_RX_MASK_NO_SHORT_FRAME | \
FIFO_RX_MASK_BIT17 | \
FIFO_RX_MASK_BIT16 | \
FIFO_RX_MASK_TRUNC_FRAME | \
FIFO_RX_MASK_LONG_EVENT | \
FIFO_RX_MASK_VLAN_TAG | \
FIFO_RX_MASK_PAUSE_FRAME | \
FIFO_RX_MASK_CTRL_FRAME | \
FIFO_RX_MASK_DRIBBLE_NIBBLE | \
FIFO_RX_MASK_BCAST | \
FIFO_RX_MASK_MCAST | \
FIFO_RX_MASK_OK | \
FIFO_RX_MASK_OORANGE | \
FIFO_RX_MASK_CODE_ERROR | \
FIFO_RX_MASK_FALSE_CARRIER | \
FIFO_RX_MASK_RX_DV_EVENT | \
FIFO_RX_MASK_DROP_EVENT)
#define AR71XX_MAC_FIFO_RAM0 0x60
#define AR71XX_MAC_FIFO_RAM1 0x64
#define AR71XX_MAC_FIFO_RAM2 0x68
#define AR71XX_MAC_FIFO_RAM3 0x6C
#define AR71XX_MAC_FIFO_RAM4 0x70
#define AR71XX_MAC_FIFO_RAM5 0x74
#define AR71XX_MAC_FIFO_RAM6 0x78
#define AR71XX_DMA_TX_CONTROL 0x180
#define DMA_TX_CONTROL_EN (1 << 0)
#define AR71XX_DMA_TX_DESC 0x184
#define AR71XX_DMA_TX_STATUS 0x188
#define DMA_TX_STATUS_PCOUNT_MASK 0xff
#define DMA_TX_STATUS_PCOUNT_SHIFT 16
#define DMA_TX_STATUS_BUS_ERROR (1 << 3)
#define DMA_TX_STATUS_UNDERRUN (1 << 1)
#define DMA_TX_STATUS_PKT_SENT (1 << 0)
#define AR71XX_DMA_RX_CONTROL 0x18C
#define DMA_RX_CONTROL_EN (1 << 0)
#define AR71XX_DMA_RX_DESC 0x190
#define AR71XX_DMA_RX_STATUS 0x194
#define DMA_RX_STATUS_PCOUNT_MASK 0xff
#define DMA_RX_STATUS_PCOUNT_SHIFT 16
#define DMA_RX_STATUS_BUS_ERROR (1 << 3)
#define DMA_RX_STATUS_OVERFLOW (1 << 2)
#define DMA_RX_STATUS_PKT_RECVD (1 << 0)
#define AR71XX_DMA_INTR 0x198
#define AR71XX_DMA_INTR_STATUS 0x19C
#define DMA_INTR_ALL ((1 << 8) - 1)
#define DMA_INTR_RX_BUS_ERROR (1 << 7)
#define DMA_INTR_RX_OVERFLOW (1 << 6)
#define DMA_INTR_RX_PKT_RCVD (1 << 4)
#define DMA_INTR_TX_BUS_ERROR (1 << 3)
#define DMA_INTR_TX_UNDERRUN (1 << 1)
#define DMA_INTR_TX_PKT_SENT (1 << 0)
#define AR71XX_SPI_BASE 0x1f000000
#define AR71XX_SPI_FS 0x00
#define AR71XX_SPI_CTRL 0x04
#define SPI_CTRL_REMAP_DISABLE (1 << 6)
#define SPI_CTRL_CLOCK_DIVIDER_MASK ((1 << 6) - 1)
#define AR71XX_SPI_IO_CTRL 0x08
#define SPI_IO_CTRL_CS2 (1 << 18)
#define SPI_IO_CTRL_CS1 (1 << 17)
#define SPI_IO_CTRL_CS0 (1 << 16)
#define SPI_IO_CTRL_CSMASK (7 << 16)
#define SPI_IO_CTRL_CLK (1 << 8)
#define SPI_IO_CTRL_DO 1
#define AR71XX_SPI_RDS 0x0C
#define ATH_READ_REG(reg) \
*((volatile uint32_t *)MIPS_PHYS_TO_KSEG1((reg)))
/*
* Note: Don't put a flush read here; some users (eg the AR724x PCI fixup code)
* requires write-only space to certain registers. Doing the read afterwards
* causes things to break.
*/
#define ATH_WRITE_REG(reg, val) \
*((volatile uint32_t *)MIPS_PHYS_TO_KSEG1((reg))) = (val)
static inline void
ar71xx_ddr_flush(uint32_t reg)
{
ATH_WRITE_REG(reg, 1);
while ((ATH_READ_REG(reg) & 0x1))
;
ATH_WRITE_REG(reg, 1);
while ((ATH_READ_REG(reg) & 0x1))
;
}
static inline void
ar71xx_write_pll(uint32_t cfg_reg, uint32_t pll_reg, uint32_t pll, uint32_t pll_reg_shift)
{
uint32_t sec_cfg;
/* set PLL registers */
sec_cfg = ATH_READ_REG(cfg_reg);
sec_cfg &= ~(3 << pll_reg_shift);
sec_cfg |= (2 << pll_reg_shift);
ATH_WRITE_REG(cfg_reg, sec_cfg);
DELAY(100);
ATH_WRITE_REG(pll_reg, pll);
sec_cfg |= (3 << pll_reg_shift);
ATH_WRITE_REG(cfg_reg, sec_cfg);
DELAY(100);
sec_cfg &= ~(3 << pll_reg_shift);
ATH_WRITE_REG(cfg_reg, sec_cfg);
DELAY(100);
}
#endif /* _AR71XX_REG_H_ */

View File

@ -1,246 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2010 Adrian Chadd
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_ddb.h"
#include <sys/param.h>
#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/cons.h>
#include <sys/kdb.h>
#include <sys/reboot.h>
#include <vm/vm.h>
#include <vm/vm_page.h>
#include <net/ethernet.h>
#include <machine/clock.h>
#include <machine/cpu.h>
#include <machine/cpuregs.h>
#include <machine/hwfunc.h>
#include <machine/md_var.h>
#include <machine/trap.h>
#include <machine/vmparam.h>
#include <mips/atheros/ar71xxreg.h>
#include <mips/atheros/ar724xreg.h>
#include <mips/atheros/ar71xx_cpudef.h>
#include <mips/atheros/ar71xx_setup.h>
#include <mips/atheros/ar71xx_chip.h>
#include <mips/atheros/ar724x_chip.h>
static void
ar724x_chip_detect_mem_size(void)
{
}
static void
ar724x_chip_detect_sys_frequency(void)
{
uint32_t pll;
uint32_t freq;
uint32_t div;
u_ar71xx_mdio_freq = u_ar71xx_refclk = AR724X_BASE_FREQ;
pll = ATH_READ_REG(AR724X_PLL_REG_CPU_CONFIG);
div = ((pll >> AR724X_PLL_DIV_SHIFT) & AR724X_PLL_DIV_MASK);
freq = div * AR724X_BASE_FREQ;
div = ((pll >> AR724X_PLL_REF_DIV_SHIFT) & AR724X_PLL_REF_DIV_MASK);
freq *= div;
u_ar71xx_cpu_freq = freq;
div = ((pll >> AR724X_DDR_DIV_SHIFT) & AR724X_DDR_DIV_MASK) + 1;
u_ar71xx_ddr_freq = freq / div;
div = (((pll >> AR724X_AHB_DIV_SHIFT) & AR724X_AHB_DIV_MASK) + 1) * 2;
u_ar71xx_ahb_freq = u_ar71xx_cpu_freq / div;
u_ar71xx_wdt_freq = u_ar71xx_cpu_freq / div;
u_ar71xx_uart_freq = u_ar71xx_cpu_freq / div;
}
static void
ar724x_chip_device_stop(uint32_t mask)
{
uint32_t mask_inv, reg;
mask_inv = mask & AR724X_RESET_MODULE_USB_OHCI_DLL;
reg = ATH_READ_REG(AR724X_RESET_REG_RESET_MODULE);
reg |= mask;
reg &= ~mask_inv;
ATH_WRITE_REG(AR724X_RESET_REG_RESET_MODULE, reg);
}
static void
ar724x_chip_device_start(uint32_t mask)
{
uint32_t mask_inv, reg;
mask_inv = mask & AR724X_RESET_MODULE_USB_OHCI_DLL;
reg = ATH_READ_REG(AR724X_RESET_REG_RESET_MODULE);
reg &= ~mask;
reg |= mask_inv;
ATH_WRITE_REG(AR724X_RESET_REG_RESET_MODULE, reg);
}
static int
ar724x_chip_device_stopped(uint32_t mask)
{
uint32_t reg;
reg = ATH_READ_REG(AR724X_RESET_REG_RESET_MODULE);
return ((reg & mask) == mask);
}
static void
ar724x_chip_set_mii_speed(uint32_t unit, uint32_t speed)
{
/* XXX TODO */
return;
}
/*
* XXX TODO: set the PLL for arge0 only on AR7242.
* The PLL/clock requirements are different.
*
* Otherwise, it's a NULL function for AR7240, AR7241 and
* AR7242 arge1.
*/
static void
ar724x_chip_set_pll_ge(int unit, int speed, uint32_t pll)
{
switch (unit) {
case 0:
/* XXX TODO */
break;
case 1:
/* XXX TODO */
break;
default:
printf("%s: invalid PLL set for arge unit: %d\n",
__func__, unit);
return;
}
}
static void
ar724x_chip_ddr_flush(ar71xx_flush_ddr_id_t id)
{
switch (id) {
case AR71XX_CPU_DDR_FLUSH_GE0:
ar71xx_ddr_flush(AR724X_DDR_REG_FLUSH_GE0);
break;
case AR71XX_CPU_DDR_FLUSH_GE1:
ar71xx_ddr_flush(AR724X_DDR_REG_FLUSH_GE1);
break;
case AR71XX_CPU_DDR_FLUSH_USB:
ar71xx_ddr_flush(AR724X_DDR_REG_FLUSH_USB);
break;
case AR71XX_CPU_DDR_FLUSH_PCIE:
ar71xx_ddr_flush(AR724X_DDR_REG_FLUSH_PCIE);
break;
default:
printf("%s: invalid DDR flush id (%d)\n", __func__, id);
break;
}
}
static uint32_t
ar724x_chip_get_eth_pll(unsigned int mac, int speed)
{
return (0);
}
static void
ar724x_chip_init_usb_peripheral(void)
{
switch (ar71xx_soc) {
case AR71XX_SOC_AR7240:
ar71xx_device_stop(AR724X_RESET_MODULE_USB_OHCI_DLL |
AR724X_RESET_USB_HOST);
DELAY(1000);
ar71xx_device_start(AR724X_RESET_MODULE_USB_OHCI_DLL |
AR724X_RESET_USB_HOST);
DELAY(1000);
/*
* WAR for HW bug. Here it adjusts the duration
* between two SOFS.
*/
ATH_WRITE_REG(AR71XX_USB_CTRL_FLADJ,
(3 << USB_CTRL_FLADJ_A0_SHIFT));
break;
case AR71XX_SOC_AR7241:
case AR71XX_SOC_AR7242:
ar71xx_device_start(AR724X_RESET_MODULE_USB_OHCI_DLL);
DELAY(100);
ar71xx_device_start(AR724X_RESET_USB_HOST);
DELAY(100);
ar71xx_device_start(AR724X_RESET_USB_PHY);
DELAY(100);
break;
default:
break;
}
}
struct ar71xx_cpu_def ar724x_chip_def = {
&ar724x_chip_detect_mem_size,
&ar724x_chip_detect_sys_frequency,
&ar724x_chip_device_stop,
&ar724x_chip_device_start,
&ar724x_chip_device_stopped,
&ar724x_chip_set_pll_ge,
&ar724x_chip_set_mii_speed,
&ar71xx_chip_set_mii_if,
&ar724x_chip_get_eth_pll,
&ar724x_chip_ddr_flush,
&ar724x_chip_init_usb_peripheral
};

View File

@ -1,36 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2010 Adrian Chadd
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* $FreeBSD$ */
#ifndef __AR724X_CHIP_H__
#define __AR724X_CHIP_H__
extern struct ar71xx_cpu_def ar724x_chip_def;
#endif

View File

@ -1,672 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@FreeBSD.org>
* Copyright (c) 2011, Luiz Otavio O Souza.
* 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 unmodified, this list of conditions, and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_ar71xx.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/interrupt.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/rman.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <vm/vm_extern.h>
#include <machine/bus.h>
#include <machine/cpu.h>
#include <machine/intr_machdep.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcib_private.h>
#include "pcib_if.h"
#include <mips/atheros/ar71xxreg.h>
#include <mips/atheros/ar724xreg.h>
#include <mips/atheros/ar71xx_setup.h>
#include <mips/atheros/ar71xx_pci_bus_space.h>
#include <mips/atheros/ar71xx_cpudef.h>
#ifdef AR71XX_ATH_EEPROM
#include <mips/atheros/ar71xx_fixup.h>
#endif /* AR71XX_ATH_EEPROM */
#undef AR724X_PCI_DEBUG
#ifdef AR724X_PCI_DEBUG
#define dprintf printf
#else
#define dprintf(x, arg...)
#endif
struct ar71xx_pci_softc {
device_t sc_dev;
int sc_busno;
struct rman sc_mem_rman;
struct rman sc_irq_rman;
struct intr_event *sc_eventstab[AR71XX_PCI_NIRQS];
mips_intrcnt_t sc_intr_counter[AR71XX_PCI_NIRQS];
struct resource *sc_irq;
void *sc_ih;
};
static int ar724x_pci_setup_intr(device_t, device_t, struct resource *, int,
driver_filter_t *, driver_intr_t *, void *, void **);
static int ar724x_pci_teardown_intr(device_t, device_t, struct resource *,
void *);
static int ar724x_pci_intr(void *);
static void
ar724x_pci_write(uint32_t reg, uint32_t offset, uint32_t data, int bytes)
{
uint32_t val, mask, shift;
/* Register access is 32-bit aligned */
shift = (offset & 3) * 8;
if (bytes % 4)
mask = (1 << (bytes * 8)) - 1;
else
mask = 0xffffffff;
rmb();
val = ATH_READ_REG(reg + (offset & ~3));
val &= ~(mask << shift);
val |= ((data & mask) << shift);
ATH_WRITE_REG(reg + (offset & ~3), val);
wmb();
dprintf("%s: %#x/%#x addr=%#x, data=%#x(%#x), bytes=%d\n", __func__,
reg, reg + (offset & ~3), offset, data, val, bytes);
}
static uint32_t
ar724x_pci_read_config(device_t dev, u_int bus, u_int slot, u_int func,
u_int reg, int bytes)
{
uint32_t data, shift, mask;
/* Register access is 32-bit aligned */
shift = (reg & 3) * 8;
/* Create a mask based on the width, post-shift */
if (bytes == 2)
mask = 0xffff;
else if (bytes == 1)
mask = 0xff;
else
mask = 0xffffffff;
dprintf("%s: tag (%x, %x, %x) reg %d(%d)\n", __func__, bus, slot,
func, reg, bytes);
rmb();
if ((bus == 0) && (slot == 0) && (func == 0))
data = ATH_READ_REG(AR724X_PCI_CFG_BASE + (reg & ~3));
else
data = -1;
/* Get request bytes from 32-bit word */
data = (data >> shift) & mask;
dprintf("%s: read 0x%x\n", __func__, data);
return (data);
}
static void
ar724x_pci_write_config(device_t dev, u_int bus, u_int slot, u_int func,
u_int reg, uint32_t data, int bytes)
{
dprintf("%s: tag (%x, %x, %x) reg %d(%d): %x\n", __func__, bus, slot,
func, reg, bytes, data);
if ((bus != 0) || (slot != 0) || (func != 0))
return;
/*
* WAR for BAR issue on AR7240 - We are unable to access the PCI
* device space if we set the BAR with proper base address.
*
* However, we _do_ want to allow programming in the probe value
* (0xffffffff) so the PCI code can find out how big the memory
* map is for this device. Without it, it'll think the memory
* map is 32 bits wide, the PCI code will then end up thinking
* the register window is '0' and fail to allocate resources.
*
* Note: Test on AR7241/AR7242/AR9344! Those use a WAR value of
* 0x1000ffff.
*/
if (reg == PCIR_BAR(0) && bytes == 4
&& ar71xx_soc == AR71XX_SOC_AR7240
&& data != 0xffffffff)
ar724x_pci_write(AR724X_PCI_CFG_BASE, reg, 0xffff, bytes);
else
ar724x_pci_write(AR724X_PCI_CFG_BASE, reg, data, bytes);
}
static void
ar724x_pci_mask_irq(void *source)
{
uint32_t reg;
unsigned int irq = (unsigned int)source;
/* XXX - Only one interrupt ? Only one device ? */
if (irq != AR71XX_PCI_IRQ_START)
return;
/* Update the interrupt mask reg */
reg = ATH_READ_REG(AR724X_PCI_INTR_MASK);
ATH_WRITE_REG(AR724X_PCI_INTR_MASK,
reg & ~AR724X_PCI_INTR_DEV0);
/* Clear any pending interrupt */
reg = ATH_READ_REG(AR724X_PCI_INTR_STATUS);
ATH_WRITE_REG(AR724X_PCI_INTR_STATUS,
reg | AR724X_PCI_INTR_DEV0);
}
static void
ar724x_pci_unmask_irq(void *source)
{
uint32_t reg;
unsigned int irq = (unsigned int)source;
/* XXX */
if (irq != AR71XX_PCI_IRQ_START)
return;
/* Update the interrupt mask reg */
reg = ATH_READ_REG(AR724X_PCI_INTR_MASK);
ATH_WRITE_REG(AR724X_PCI_INTR_MASK,
reg | AR724X_PCI_INTR_DEV0);
}
static int
ar724x_pci_setup(device_t dev)
{
uint32_t reg;
/* setup COMMAND register */
reg = PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN | PCIM_CMD_SERRESPEN |
PCIM_CMD_BACKTOBACK | PCIM_CMD_PERRESPEN | PCIM_CMD_MWRICEN;
ar724x_pci_write(AR724X_PCI_CRP_BASE, PCIR_COMMAND, reg, 2);
ar724x_pci_write(AR724X_PCI_CRP_BASE, 0x20, 0x1ff01000, 4);
ar724x_pci_write(AR724X_PCI_CRP_BASE, 0x24, 0x1ff01000, 4);
reg = ATH_READ_REG(AR724X_PCI_RESET);
if (reg != 0x7) {
DELAY(100000);
ATH_WRITE_REG(AR724X_PCI_RESET, 0);
DELAY(100);
ATH_WRITE_REG(AR724X_PCI_RESET, 4);
DELAY(100000);
}
if (ar71xx_soc == AR71XX_SOC_AR7240)
reg = AR724X_PCI_APP_LTSSM_ENABLE;
else
reg = 0x1ffc1;
ATH_WRITE_REG(AR724X_PCI_APP, reg);
/* Flush write */
(void) ATH_READ_REG(AR724X_PCI_APP);
DELAY(1000);
reg = ATH_READ_REG(AR724X_PCI_RESET);
if ((reg & AR724X_PCI_RESET_LINK_UP) == 0) {
device_printf(dev, "no PCIe controller found\n");
return (ENXIO);
}
if (ar71xx_soc == AR71XX_SOC_AR7241 ||
ar71xx_soc == AR71XX_SOC_AR7242) {
reg = ATH_READ_REG(AR724X_PCI_APP);
reg |= (1 << 16);
ATH_WRITE_REG(AR724X_PCI_APP, reg);
}
return (0);
}
#ifdef AR71XX_ATH_EEPROM
#define AR5416_EEPROM_MAGIC 0xa55a
/*
* XXX - This should not be here ! And this looks like Atheros (if_ath) only.
*/
static void
ar724x_pci_fixup(device_t dev, long flash_addr, int len)
{
uint32_t bar0, reg, val;
uint16_t *cal_data = (uint16_t *) MIPS_PHYS_TO_KSEG1(flash_addr);
#if 0
if (cal_data[0] != AR5416_EEPROM_MAGIC) {
device_printf(dev, "%s: Invalid calibration data from 0x%x\n",
__func__, (uintptr_t) flash_addr);
return;
}
#endif
/* Save bar(0) address - just to flush bar(0) (SoC WAR) ? */
bar0 = ar724x_pci_read_config(dev, 0, 0, 0, PCIR_BAR(0), 4);
/* Write temporary BAR0 to map the NIC into a fixed location */
/* XXX AR7240: 0xffff; 7241/7242/9344: 0x1000ffff */
ar724x_pci_write_config(dev, 0, 0, 0, PCIR_BAR(0),
AR71XX_PCI_MEM_BASE, 4);
val = ar724x_pci_read_config(dev, 0, 0, 0, PCIR_COMMAND, 2);
val |= (PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN);
ar724x_pci_write_config(dev, 0, 0, 0, PCIR_COMMAND, val, 2);
/* set pointer to first reg address */
cal_data += 3;
while (*cal_data != 0xffff) {
reg = *cal_data++;
val = *cal_data++;
val |= (*cal_data++) << 16;
if (bootverbose)
printf(" 0x%08x=0x%08x\n", reg, val);
/* Write eeprom fixup data to device memory */
ATH_WRITE_REG(AR71XX_PCI_MEM_BASE + reg, val);
DELAY(100);
}
val = ar724x_pci_read_config(dev, 0, 0, 0, PCIR_COMMAND, 2);
val &= ~(PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN);
ar724x_pci_write_config(dev, 0, 0, 0, PCIR_COMMAND, val, 2);
/* Write the saved bar(0) address */
ar724x_pci_write_config(dev, 0, 0, 0, PCIR_BAR(0), bar0, 4);
}
#undef AR5416_EEPROM_MAGIC
/*
* XXX This is (mostly) duplicated with ar71xx_pci.c.
* It should at some point be fixed.
*/
static void
ar724x_pci_slot_fixup(device_t dev)
{
long int flash_addr;
char buf[64];
int size;
/*
* Check whether the given slot has a hint to poke.
*/
if (bootverbose)
device_printf(dev, "%s: checking dev %s, %d/%d/%d\n",
__func__, device_get_nameunit(dev), 0, 0, 0);
snprintf(buf, sizeof(buf), "bus.%d.%d.%d.ath_fixup_addr",
0, 0, 0);
if (resource_long_value(device_get_name(dev), device_get_unit(dev),
buf, &flash_addr) == 0) {
snprintf(buf, sizeof(buf), "bus.%d.%d.%d.ath_fixup_size",
0, 0, 0);
if (resource_int_value(device_get_name(dev),
device_get_unit(dev), buf, &size) != 0) {
device_printf(dev,
"%s: missing hint '%s', aborting EEPROM\n",
__func__, buf);
return;
}
device_printf(dev, "found EEPROM at 0x%lx on %d.%d.%d\n",
flash_addr, 0, 0, 0);
ar724x_pci_fixup(dev, flash_addr, size);
ar71xx_pci_slot_create_eeprom_firmware(dev, 0, 0, 0,
flash_addr, size);
}
}
#endif /* AR71XX_ATH_EEPROM */
static int
ar724x_pci_probe(device_t dev)
{
return (BUS_PROBE_NOWILDCARD);
}
static int
ar724x_pci_attach(device_t dev)
{
struct ar71xx_pci_softc *sc = device_get_softc(dev);
int rid = 0;
sc->sc_mem_rman.rm_type = RMAN_ARRAY;
sc->sc_mem_rman.rm_descr = "ar724x PCI memory window";
if (rman_init(&sc->sc_mem_rman) != 0 ||
rman_manage_region(&sc->sc_mem_rman, AR71XX_PCI_MEM_BASE,
AR71XX_PCI_MEM_BASE + AR71XX_PCI_MEM_SIZE - 1) != 0) {
panic("ar724x_pci_attach: failed to set up I/O rman");
}
sc->sc_irq_rman.rm_type = RMAN_ARRAY;
sc->sc_irq_rman.rm_descr = "ar724x PCI IRQs";
if (rman_init(&sc->sc_irq_rman) != 0 ||
rman_manage_region(&sc->sc_irq_rman, AR71XX_PCI_IRQ_START,
AR71XX_PCI_IRQ_END) != 0)
panic("ar724x_pci_attach: failed to set up IRQ rman");
/* Disable interrupts */
ATH_WRITE_REG(AR724X_PCI_INTR_STATUS, 0);
ATH_WRITE_REG(AR724X_PCI_INTR_MASK, 0);
/* Hook up our interrupt handler. */
if ((sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
RF_SHAREABLE | RF_ACTIVE)) == NULL) {
device_printf(dev, "unable to allocate IRQ resource\n");
return (ENXIO);
}
if ((bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_MISC,
ar724x_pci_intr, NULL, sc, &sc->sc_ih))) {
device_printf(dev,
"WARNING: unable to register interrupt handler\n");
return (ENXIO);
}
/* Reset PCIe core and PCIe PHY */
ar71xx_device_stop(AR724X_RESET_PCIE);
ar71xx_device_stop(AR724X_RESET_PCIE_PHY);
ar71xx_device_stop(AR724X_RESET_PCIE_PHY_SERIAL);
DELAY(100);
ar71xx_device_start(AR724X_RESET_PCIE_PHY_SERIAL);
DELAY(100);
ar71xx_device_start(AR724X_RESET_PCIE_PHY);
ar71xx_device_start(AR724X_RESET_PCIE);
if (ar724x_pci_setup(dev))
return (ENXIO);
#ifdef AR71XX_ATH_EEPROM
ar724x_pci_slot_fixup(dev);
#endif /* AR71XX_ATH_EEPROM */
/* Fixup internal PCI bridge */
ar724x_pci_write_config(dev, 0, 0, 0, PCIR_COMMAND,
PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN
| PCIM_CMD_SERRESPEN | PCIM_CMD_BACKTOBACK
| PCIM_CMD_PERRESPEN | PCIM_CMD_MWRICEN, 2);
device_add_child(dev, "pci", -1);
return (bus_generic_attach(dev));
}
static int
ar724x_pci_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
{
struct ar71xx_pci_softc *sc = device_get_softc(dev);
switch (which) {
case PCIB_IVAR_DOMAIN:
*result = 0;
return (0);
case PCIB_IVAR_BUS:
*result = sc->sc_busno;
return (0);
}
return (ENOENT);
}
static int
ar724x_pci_write_ivar(device_t dev, device_t child, int which, uintptr_t result)
{
struct ar71xx_pci_softc * sc = device_get_softc(dev);
switch (which) {
case PCIB_IVAR_BUS:
sc->sc_busno = result;
return (0);
}
return (ENOENT);
}
static struct resource *
ar724x_pci_alloc_resource(device_t bus, device_t child, int type, int *rid,
rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
{
struct ar71xx_pci_softc *sc = device_get_softc(bus);
struct resource *rv;
struct rman *rm;
switch (type) {
case SYS_RES_IRQ:
rm = &sc->sc_irq_rman;
break;
case SYS_RES_MEMORY:
rm = &sc->sc_mem_rman;
break;
default:
return (NULL);
}
rv = rman_reserve_resource(rm, start, end, count, flags, child);
if (rv == NULL)
return (NULL);
rman_set_rid(rv, *rid);
if (flags & RF_ACTIVE) {
if (bus_activate_resource(child, type, *rid, rv)) {
rman_release_resource(rv);
return (NULL);
}
}
return (rv);
}
static int
ar724x_pci_activate_resource(device_t bus, device_t child, int type, int rid,
struct resource *r)
{
int res = (BUS_ACTIVATE_RESOURCE(device_get_parent(bus),
child, type, rid, r));
if (!res) {
switch(type) {
case SYS_RES_MEMORY:
case SYS_RES_IOPORT:
rman_set_bustag(r, ar71xx_bus_space_pcimem);
break;
}
}
return (res);
}
static int
ar724x_pci_setup_intr(device_t bus, device_t child, struct resource *ires,
int flags, driver_filter_t *filt, driver_intr_t *handler,
void *arg, void **cookiep)
{
struct ar71xx_pci_softc *sc = device_get_softc(bus);
struct intr_event *event;
int irq, error;
irq = rman_get_start(ires);
if (irq > AR71XX_PCI_IRQ_END)
panic("%s: bad irq %d", __func__, irq);
event = sc->sc_eventstab[irq];
if (event == NULL) {
error = intr_event_create(&event, (void *)irq, 0, irq,
ar724x_pci_mask_irq, ar724x_pci_unmask_irq, NULL, NULL,
"pci intr%d:", irq);
if (error == 0) {
sc->sc_eventstab[irq] = event;
sc->sc_intr_counter[irq] =
mips_intrcnt_create(event->ie_name);
}
else
return error;
}
intr_event_add_handler(event, device_get_nameunit(child), filt,
handler, arg, intr_priority(flags), flags, cookiep);
mips_intrcnt_setname(sc->sc_intr_counter[irq], event->ie_fullname);
ar724x_pci_unmask_irq((void*)irq);
return (0);
}
static int
ar724x_pci_teardown_intr(device_t dev, device_t child, struct resource *ires,
void *cookie)
{
struct ar71xx_pci_softc *sc = device_get_softc(dev);
int irq, result;
irq = rman_get_start(ires);
if (irq > AR71XX_PCI_IRQ_END)
panic("%s: bad irq %d", __func__, irq);
if (sc->sc_eventstab[irq] == NULL)
panic("Trying to teardown unoccupied IRQ");
ar724x_pci_mask_irq((void*)irq);
result = intr_event_remove_handler(cookie);
if (!result)
sc->sc_eventstab[irq] = NULL;
return (result);
}
static int
ar724x_pci_intr(void *arg)
{
struct ar71xx_pci_softc *sc = arg;
struct intr_event *event;
uint32_t reg, irq, mask;
reg = ATH_READ_REG(AR724X_PCI_INTR_STATUS);
mask = ATH_READ_REG(AR724X_PCI_INTR_MASK);
/*
* Handle only unmasked interrupts
*/
reg &= mask;
if (reg & AR724X_PCI_INTR_DEV0) {
irq = AR71XX_PCI_IRQ_START;
event = sc->sc_eventstab[irq];
if (!event || CK_SLIST_EMPTY(&event->ie_handlers)) {
printf("Stray IRQ %d\n", irq);
return (FILTER_STRAY);
}
/* Flush pending memory transactions */
ar71xx_device_flush_ddr(AR71XX_CPU_DDR_FLUSH_PCIE);
/* TODO: frame instead of NULL? */
intr_event_handle(event, NULL);
mips_intrcnt_inc(sc->sc_intr_counter[irq]);
}
return (FILTER_HANDLED);
}
static int
ar724x_pci_maxslots(device_t dev)
{
return (PCI_SLOTMAX);
}
static int
ar724x_pci_route_interrupt(device_t pcib, device_t device, int pin)
{
return (pci_get_slot(device));
}
static device_method_t ar724x_pci_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, ar724x_pci_probe),
DEVMETHOD(device_attach, ar724x_pci_attach),
DEVMETHOD(device_shutdown, bus_generic_shutdown),
DEVMETHOD(device_suspend, bus_generic_suspend),
DEVMETHOD(device_resume, bus_generic_resume),
/* Bus interface */
DEVMETHOD(bus_read_ivar, ar724x_pci_read_ivar),
DEVMETHOD(bus_write_ivar, ar724x_pci_write_ivar),
DEVMETHOD(bus_alloc_resource, ar724x_pci_alloc_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, ar724x_pci_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
DEVMETHOD(bus_setup_intr, ar724x_pci_setup_intr),
DEVMETHOD(bus_teardown_intr, ar724x_pci_teardown_intr),
/* pcib interface */
DEVMETHOD(pcib_maxslots, ar724x_pci_maxslots),
DEVMETHOD(pcib_read_config, ar724x_pci_read_config),
DEVMETHOD(pcib_write_config, ar724x_pci_write_config),
DEVMETHOD(pcib_route_interrupt, ar724x_pci_route_interrupt),
DEVMETHOD(pcib_request_feature, pcib_request_feature_allow),
DEVMETHOD_END
};
static driver_t ar724x_pci_driver = {
"pcib",
ar724x_pci_methods,
sizeof(struct ar71xx_pci_softc),
};
static devclass_t ar724x_pci_devclass;
DRIVER_MODULE(ar724x_pci, nexus, ar724x_pci_driver, ar724x_pci_devclass, 0, 0);

View File

@ -1,110 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2010 Adrian Chadd
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* $FreeBSD$ */
#ifndef __AR72XX_REG_H__
#define __AR72XX_REG_H__
#define AR724X_PLL_REG_CPU_CONFIG AR71XX_PLL_CPU_BASE + 0x00
#define AR724X_PLL_REG_PCIE_CONFIG AR71XX_PLL_CPU_BASE + 0x18
#define AR724X_PLL_DIV_SHIFT 0
#define AR724X_PLL_DIV_MASK 0x3ff
#define AR724X_PLL_REF_DIV_SHIFT 10
#define AR724X_PLL_REF_DIV_MASK 0xf
#define AR724X_AHB_DIV_SHIFT 19
#define AR724X_AHB_DIV_MASK 0x1
#define AR724X_DDR_DIV_SHIFT 22
#define AR724X_DDR_DIV_MASK 0x3
#define AR724X_PLL_VAL_1000 0x00110000
#define AR724X_PLL_VAL_100 0x00001099
#define AR724X_PLL_VAL_10 0x00991099
#define AR724X_BASE_FREQ 5000000
#define AR724X_DDR_REG_FLUSH_GE0 (AR71XX_DDR_CONFIG + 0x7c)
#define AR724X_DDR_REG_FLUSH_GE1 (AR71XX_DDR_CONFIG + 0x80)
#define AR724X_DDR_REG_FLUSH_USB (AR71XX_DDR_CONFIG + 0x84)
#define AR724X_DDR_REG_FLUSH_PCIE (AR71XX_DDR_CONFIG + 0x88)
#define AR724X_RESET_REG_RESET_MODULE AR71XX_RST_BLOCK_BASE + 0x1c
#define AR724X_RESET_USB_HOST (1 << 5)
#define AR724X_RESET_USB_PHY (1 << 4)
#define AR724X_RESET_MODULE_USB_OHCI_DLL (1 << 3)
#define AR724X_RESET_GE1_MDIO (1 << 23)
#define AR724X_RESET_GE0_MDIO (1 << 22)
#define AR724X_RESET_PCIE_PHY_SERIAL (1 << 10)
#define AR724X_RESET_PCIE_PHY (1 << 7)
#define AR724X_RESET_PCIE (1 << 6)
#define AR724X_RESET_USB_HOST (1 << 5)
#define AR724X_RESET_USB_PHY (1 << 4)
#define AR724X_RESET_USBSUS_OVERRIDE (1 << 3)
/* XXX so USB requires different init code? -adrian */
#define AR7240_OHCI_BASE 0x1b000000
#define AR7240_OHCI_SIZE 0x01000000
#define AR724X_PCI_CRP_BASE (AR71XX_APB_BASE + 0x000C0000)
#define AR724X_PCI_CRP_SIZE 0x100
#define AR724X_PCI_CFG_BASE 0x14000000
#define AR724X_PCI_CFG_SIZE 0x1000
#define AR724X_PCI_CTRL_BASE (AR71XX_APB_BASE + 0x000F0000)
#define AR724X_PCI_CTRL_SIZE 0x100
/* PCI config registers - AR724X_PCI_CTRL_BASE */
#define AR724X_PCI_APP 0x180f0000
#define AR724X_PCI_APP_LTSSM_ENABLE (1 << 0)
#define AR724X_PCI_RESET 0x180f0018
#define AR724X_PCI_RESET_LINK_UP (1 << 0)
#define AR724X_PCI_INTR_STATUS 0x180f004c
#define AR724X_PCI_INTR_MASK 0x180f0050
#define AR724X_PCI_INTR_DEV0 (1 << 14)
#define AR724X_GPIO_FUNC_GE0_MII_CLK_EN (1 << 19)
#define AR724X_GPIO_FUNC_SPI_EN (1 << 18)
#define AR724X_GPIO_FUNC_SPI_CS_EN2 (1 << 14)
#define AR724X_GPIO_FUNC_SPI_CS_EN1 (1 << 13)
#define AR724X_GPIO_FUNC_CLK_OBS5_EN (1 << 12)
#define AR724X_GPIO_FUNC_CLK_OBS4_EN (1 << 11)
#define AR724X_GPIO_FUNC_CLK_OBS3_EN (1 << 10)
#define AR724X_GPIO_FUNC_CLK_OBS2_EN (1 << 9)
#define AR724X_GPIO_FUNC_CLK_OBS1_EN (1 << 8)
#define AR724X_GPIO_FUNC_ETH_SWITCH_LED4_EN (1 << 7)
#define AR724X_GPIO_FUNC_ETH_SWITCH_LED3_EN (1 << 6)
#define AR724X_GPIO_FUNC_ETH_SWITCH_LED2_EN (1 << 5)
#define AR724X_GPIO_FUNC_ETH_SWITCH_LED1_EN (1 << 4)
#define AR724X_GPIO_FUNC_ETH_SWITCH_LED0_EN (1 << 3)
#define AR724X_GPIO_FUNC_UART_RTS_CTS_EN (1 << 2)
#define AR724X_GPIO_FUNC_UART_EN (1 << 1)
#define AR724X_GPIO_FUNC_JTAG_DISABLE (1 << 0)
#endif

View File

@ -1,219 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2010 Adrian Chadd
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_ddb.h"
#include <sys/param.h>
#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/cons.h>
#include <sys/kdb.h>
#include <sys/reboot.h>
#include <vm/vm.h>
#include <vm/vm_page.h>
#include <net/ethernet.h>
#include <machine/clock.h>
#include <machine/cpu.h>
#include <machine/cpuregs.h>
#include <machine/hwfunc.h>
#include <machine/md_var.h>
#include <machine/trap.h>
#include <machine/vmparam.h>
#include <mips/atheros/ar71xxreg.h>
#include <mips/atheros/ar71xx_cpudef.h>
#include <mips/atheros/ar71xx_chip.h>
#include <mips/atheros/ar91xxreg.h>
#include <mips/atheros/ar91xx_chip.h>
static void
ar91xx_chip_detect_mem_size(void)
{
}
static void
ar91xx_chip_detect_sys_frequency(void)
{
uint32_t pll;
uint32_t freq;
uint32_t div;
u_ar71xx_mdio_freq = u_ar71xx_refclk = AR91XX_BASE_FREQ;
pll = ATH_READ_REG(AR91XX_PLL_REG_CPU_CONFIG);
div = ((pll >> AR91XX_PLL_DIV_SHIFT) & AR91XX_PLL_DIV_MASK);
freq = div * AR91XX_BASE_FREQ;
u_ar71xx_cpu_freq = freq;
div = ((pll >> AR91XX_DDR_DIV_SHIFT) & AR91XX_DDR_DIV_MASK) + 1;
u_ar71xx_ddr_freq = freq / div;
div = (((pll >> AR91XX_AHB_DIV_SHIFT) & AR91XX_AHB_DIV_MASK) + 1) * 2;
u_ar71xx_ahb_freq = u_ar71xx_cpu_freq / div;
u_ar71xx_uart_freq = u_ar71xx_cpu_freq / div;
u_ar71xx_wdt_freq = u_ar71xx_cpu_freq / div;
}
static void
ar91xx_chip_device_stop(uint32_t mask)
{
uint32_t reg;
reg = ATH_READ_REG(AR91XX_RESET_REG_RESET_MODULE);
ATH_WRITE_REG(AR91XX_RESET_REG_RESET_MODULE, reg | mask);
}
static void
ar91xx_chip_device_start(uint32_t mask)
{
uint32_t reg;
reg = ATH_READ_REG(AR91XX_RESET_REG_RESET_MODULE);
ATH_WRITE_REG(AR91XX_RESET_REG_RESET_MODULE, reg & ~mask);
}
static int
ar91xx_chip_device_stopped(uint32_t mask)
{
uint32_t reg;
reg = ATH_READ_REG(AR91XX_RESET_REG_RESET_MODULE);
return ((reg & mask) == mask);
}
static void
ar91xx_chip_set_pll_ge(int unit, int speed, uint32_t pll)
{
switch (unit) {
case 0:
ar71xx_write_pll(AR91XX_PLL_REG_ETH_CONFIG,
AR91XX_PLL_REG_ETH0_INT_CLOCK, pll,
AR91XX_ETH0_PLL_SHIFT);
break;
case 1:
ar71xx_write_pll(AR91XX_PLL_REG_ETH_CONFIG,
AR91XX_PLL_REG_ETH1_INT_CLOCK, pll,
AR91XX_ETH1_PLL_SHIFT);
break;
default:
printf("%s: invalid PLL set for arge unit: %d\n",
__func__, unit);
return;
}
}
static void
ar91xx_chip_ddr_flush(ar71xx_flush_ddr_id_t id)
{
switch (id) {
case AR71XX_CPU_DDR_FLUSH_GE0:
ar71xx_ddr_flush(AR91XX_DDR_REG_FLUSH_GE0);
break;
case AR71XX_CPU_DDR_FLUSH_GE1:
ar71xx_ddr_flush(AR91XX_DDR_REG_FLUSH_GE1);
break;
case AR71XX_CPU_DDR_FLUSH_USB:
ar71xx_ddr_flush(AR91XX_DDR_REG_FLUSH_USB);
break;
case AR71XX_CPU_DDR_FLUSH_WMAC:
ar71xx_ddr_flush(AR91XX_DDR_REG_FLUSH_WMAC);
break;
default:
printf("%s: invalid DDR flush id (%d)\n", __func__, id);
break;
}
}
static uint32_t
ar91xx_chip_get_eth_pll(unsigned int mac, int speed)
{
uint32_t pll;
switch(speed) {
case 10:
pll = AR91XX_PLL_VAL_10;
break;
case 100:
pll = AR91XX_PLL_VAL_100;
break;
case 1000:
pll = AR91XX_PLL_VAL_1000;
break;
default:
printf("%s%d: invalid speed %d\n", __func__, mac, speed);
pll = 0;
}
return (pll);
}
static void
ar91xx_chip_init_usb_peripheral(void)
{
ar71xx_device_stop(AR91XX_RST_RESET_MODULE_USBSUS_OVERRIDE);
DELAY(100);
ar71xx_device_start(RST_RESET_USB_HOST);
DELAY(100);
ar71xx_device_start(RST_RESET_USB_PHY);
DELAY(100);
/* Wireless */
ar71xx_device_stop(AR91XX_RST_RESET_MODULE_AMBA2WMAC);
DELAY(1000);
ar71xx_device_start(AR91XX_RST_RESET_MODULE_AMBA2WMAC);
DELAY(1000);
}
struct ar71xx_cpu_def ar91xx_chip_def = {
&ar91xx_chip_detect_mem_size,
&ar91xx_chip_detect_sys_frequency,
&ar91xx_chip_device_stop,
&ar91xx_chip_device_start,
&ar91xx_chip_device_stopped,
&ar91xx_chip_set_pll_ge,
&ar71xx_chip_set_mii_speed,
&ar71xx_chip_set_mii_if,
&ar91xx_chip_get_eth_pll,
&ar91xx_chip_ddr_flush,
&ar91xx_chip_init_usb_peripheral,
};

View File

@ -1,36 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2010 Adrian Chadd
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* $FreeBSD$ */
#ifndef __AR91XX_CHIP_H__
#define __AR91XX_CHIP_H__
extern struct ar71xx_cpu_def ar91xx_chip_def;
#endif

View File

@ -1,86 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2010 Adrian Chadd
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* $FreeBSD$ */
#ifndef __AR91XX_REG_H__
#define __AR91XX_REG_H__
#define AR91XX_BASE_FREQ 5000000
/* reset block */
#define AR91XX_RESET_REG_RESET_MODULE AR71XX_RST_BLOCK_BASE + 0x1c
#define AR91XX_RST_RESET_MODULE_USBSUS_OVERRIDE (1 << 10)
#define AR91XX_RST_RESET_MODULE_AMBA2WMAC (1 << 22)
/* PLL block */
#define AR91XX_PLL_REG_CPU_CONFIG AR71XX_PLL_CPU_BASE + 0x00
#define AR91XX_PLL_REG_ETH_CONFIG AR71XX_PLL_CPU_BASE + 0x04
#define AR91XX_PLL_REG_ETH0_INT_CLOCK AR71XX_PLL_CPU_BASE + 0x14
#define AR91XX_PLL_REG_ETH1_INT_CLOCK AR71XX_PLL_CPU_BASE + 0x18
#define AR91XX_PLL_DIV_SHIFT 0
#define AR91XX_PLL_DIV_MASK 0x3ff
#define AR91XX_DDR_DIV_SHIFT 22
#define AR91XX_DDR_DIV_MASK 0x3
#define AR91XX_AHB_DIV_SHIFT 19
#define AR91XX_AHB_DIV_MASK 0x1
#define AR91XX_ETH0_PLL_SHIFT 20
#define AR91XX_ETH1_PLL_SHIFT 22
#define AR91XX_PLL_VAL_1000 0x1a000000
#define AR91XX_PLL_VAL_100 0x13000a44
#define AR91XX_PLL_VAL_10 0x00441099
/* DDR block */
#define AR91XX_DDR_CTRLBASE (AR71XX_APB_BASE + 0)
#define AR91XX_DDR_CTRL_SIZE 0x10000
#define AR91XX_DDR_REG_FLUSH_GE0 AR91XX_DDR_CTRLBASE + 0x7c
#define AR91XX_DDR_REG_FLUSH_GE1 AR91XX_DDR_CTRLBASE + 0x80
#define AR91XX_DDR_REG_FLUSH_USB AR91XX_DDR_CTRLBASE + 0x84
#define AR91XX_DDR_REG_FLUSH_WMAC AR91XX_DDR_CTRLBASE + 0x88
/* WMAC stuff */
#define AR91XX_WMAC_BASE (AR71XX_APB_BASE + 0x000C0000)
#define AR91XX_WMAC_SIZE 0x30000
/* GPIO stuff */
#define AR91XX_GPIO_FUNC_WMAC_LED_EN (1 << 22)
#define AR91XX_GPIO_FUNC_EXP_PORT_CS_EN (1 << 21)
#define AR91XX_GPIO_FUNC_I2S_REFCLKEN (1 << 20)
#define AR91XX_GPIO_FUNC_I2S_MCKEN (1 << 19)
#define AR91XX_GPIO_FUNC_I2S1_EN (1 << 18)
#define AR91XX_GPIO_FUNC_I2S0_EN (1 << 17)
#define AR91XX_GPIO_FUNC_SLIC_EN (1 << 16)
#define AR91XX_GPIO_FUNC_UART_RTSCTS_EN (1 << 9)
#define AR91XX_GPIO_FUNC_UART_EN (1 << 8)
#define AR91XX_GPIO_FUNC_USB_CLK_EN (1 << 4)
#endif

View File

@ -1,357 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2012 Adrian Chadd <adrian@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_ddb.h"
#include <sys/param.h>
#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/cons.h>
#include <sys/kdb.h>
#include <sys/reboot.h>
#include <vm/vm.h>
#include <vm/vm_page.h>
#include <net/ethernet.h>
#include <machine/clock.h>
#include <machine/cpu.h>
#include <machine/cpuregs.h>
#include <machine/hwfunc.h>
#include <machine/md_var.h>
#include <machine/trap.h>
#include <machine/vmparam.h>
#include <mips/atheros/ar71xxreg.h>
#include <mips/atheros/ar933xreg.h>
#include <mips/atheros/ar71xx_cpudef.h>
#include <mips/atheros/ar71xx_setup.h>
#include <mips/atheros/ar71xx_chip.h>
#include <mips/atheros/ar933x_chip.h>
static void
ar933x_chip_detect_mem_size(void)
{
}
static void
ar933x_chip_detect_sys_frequency(void)
{
uint32_t clock_ctrl;
uint32_t cpu_config;
uint32_t freq;
uint32_t t;
t = ATH_READ_REG(AR933X_RESET_REG_BOOTSTRAP);
if (t & AR933X_BOOTSTRAP_REF_CLK_40)
u_ar71xx_refclk = (40 * 1000 * 1000);
else
u_ar71xx_refclk = (25 * 1000 * 1000);
clock_ctrl = ATH_READ_REG(AR933X_PLL_CLOCK_CTRL_REG);
if (clock_ctrl & AR933X_PLL_CLOCK_CTRL_BYPASS) {
u_ar71xx_cpu_freq = u_ar71xx_refclk;
u_ar71xx_ahb_freq = u_ar71xx_refclk;
u_ar71xx_ddr_freq = u_ar71xx_refclk;
} else {
cpu_config = ATH_READ_REG(AR933X_PLL_CPU_CONFIG_REG);
t = (cpu_config >> AR933X_PLL_CPU_CONFIG_REFDIV_SHIFT) &
AR933X_PLL_CPU_CONFIG_REFDIV_MASK;
freq = u_ar71xx_refclk / t;
t = (cpu_config >> AR933X_PLL_CPU_CONFIG_NINT_SHIFT) &
AR933X_PLL_CPU_CONFIG_NINT_MASK;
freq *= t;
t = (cpu_config >> AR933X_PLL_CPU_CONFIG_OUTDIV_SHIFT) &
AR933X_PLL_CPU_CONFIG_OUTDIV_MASK;
if (t == 0)
t = 1;
freq >>= t;
t = ((clock_ctrl >> AR933X_PLL_CLOCK_CTRL_CPU_DIV_SHIFT) &
AR933X_PLL_CLOCK_CTRL_CPU_DIV_MASK) + 1;
u_ar71xx_cpu_freq = freq / t;
t = ((clock_ctrl >> AR933X_PLL_CLOCK_CTRL_DDR_DIV_SHIFT) &
AR933X_PLL_CLOCK_CTRL_DDR_DIV_MASK) + 1;
u_ar71xx_ddr_freq = freq / t;
t = ((clock_ctrl >> AR933X_PLL_CLOCK_CTRL_AHB_DIV_SHIFT) &
AR933X_PLL_CLOCK_CTRL_AHB_DIV_MASK) + 1;
u_ar71xx_ahb_freq = freq / t;
}
/*
* On the AR933x, the UART frequency is the reference clock,
* not the AHB bus clock.
*/
u_ar71xx_uart_freq = u_ar71xx_refclk;
/*
* XXX TODO: check whether the mdio frequency is always the
* refclock frequency, or whether it's variable like on the
* AR934x.
*/
u_ar71xx_mdio_freq = u_ar71xx_refclk;
/*
* XXX check what the watchdog frequency should be?
*/
u_ar71xx_wdt_freq = u_ar71xx_ahb_freq;
}
static void
ar933x_chip_device_stop(uint32_t mask)
{
uint32_t reg;
reg = ATH_READ_REG(AR933X_RESET_REG_RESET_MODULE);
ATH_WRITE_REG(AR933X_RESET_REG_RESET_MODULE, reg | mask);
}
static void
ar933x_chip_device_start(uint32_t mask)
{
uint32_t reg;
reg = ATH_READ_REG(AR933X_RESET_REG_RESET_MODULE);
ATH_WRITE_REG(AR933X_RESET_REG_RESET_MODULE, reg & ~mask);
}
static int
ar933x_chip_device_stopped(uint32_t mask)
{
uint32_t reg;
reg = ATH_READ_REG(AR933X_RESET_REG_RESET_MODULE);
return ((reg & mask) == mask);
}
static void
ar933x_chip_set_mii_speed(uint32_t unit, uint32_t speed)
{
/* XXX TODO */
return;
}
/*
* XXX TODO !!
*/
static void
ar933x_chip_set_pll_ge(int unit, int speed, uint32_t pll)
{
switch (unit) {
case 0:
/* XXX TODO */
break;
case 1:
/* XXX TODO */
break;
default:
printf("%s: invalid PLL set for arge unit: %d\n",
__func__, unit);
return;
}
}
static void
ar933x_chip_ddr_flush(ar71xx_flush_ddr_id_t id)
{
switch (id) {
case AR71XX_CPU_DDR_FLUSH_GE0:
ar71xx_ddr_flush(AR933X_DDR_REG_FLUSH_GE0);
break;
case AR71XX_CPU_DDR_FLUSH_GE1:
ar71xx_ddr_flush(AR933X_DDR_REG_FLUSH_GE1);
break;
case AR71XX_CPU_DDR_FLUSH_USB:
ar71xx_ddr_flush(AR933X_DDR_REG_FLUSH_USB);
break;
case AR71XX_CPU_DDR_FLUSH_WMAC:
ar71xx_ddr_flush(AR933X_DDR_REG_FLUSH_WMAC);
break;
default:
printf("%s: invalid DDR flush id (%d)\n", __func__, id);
break;
}
}
static uint32_t
ar933x_chip_get_eth_pll(unsigned int mac, int speed)
{
uint32_t pll;
switch (speed) {
case 10:
pll = AR933X_PLL_VAL_10;
break;
case 100:
pll = AR933X_PLL_VAL_100;
break;
case 1000:
pll = AR933X_PLL_VAL_1000;
break;
default:
printf("%s%d: invalid speed %d\n", __func__, mac, speed);
pll = 0;
}
return (pll);
}
static void
ar933x_chip_init_usb_peripheral(void)
{
ar71xx_device_stop(AR933X_RESET_USBSUS_OVERRIDE);
DELAY(100);
ar71xx_device_start(AR933X_RESET_USB_HOST);
DELAY(100);
ar71xx_device_start(AR933X_RESET_USB_PHY);
DELAY(100);
}
static void
ar933x_configure_gmac(uint32_t gmac_cfg)
{
uint32_t reg;
reg = ATH_READ_REG(AR933X_GMAC_REG_ETH_CFG);
/*
* The relevant bits here include:
*
* + AR933X_ETH_CFG_SW_PHY_SWAP
* + AR933X_ETH_CFG_SW_PHY_ADDR_SWAP
*
* There are other things; look at what openwrt exposes so
* it can be correctly exposed.
*
* TODO: what about ethernet switch support? How's that work?
*/
if (bootverbose)
printf("%s: GMAC config was 0x%08x\n", __func__, reg);
reg &= ~(AR933X_ETH_CFG_SW_PHY_SWAP | AR933X_ETH_CFG_SW_PHY_ADDR_SWAP);
reg |= gmac_cfg;
if (bootverbose)
printf("%s: GMAC setting is 0x%08x; register is now 0x%08x\n",
__func__,
gmac_cfg,
reg);
ATH_WRITE_REG(AR933X_GMAC_REG_ETH_CFG, reg);
}
static void
ar933x_chip_init_gmac(void)
{
int val;
uint32_t gmac_cfg = 0;
/*
* These two bits need a bit better explanation.
*
* The default configuration in the hardware is to map both
* ports to the internal switch.
*
* Here, GE0 == arge0, GE1 == arge1.
*
* The internal switch has:
* + 5 MAC ports, MAC0->MAC4.
* + 5 PHY ports, PHY0->PHY4,
* + MAC0 connects to GE1;
* + GE0 connects to PHY4;
* + The other mappings are MAC1->PHY0, MAC2->PHY1 .. MAC4->PHY3.
*
* The GE1 port is linked in via 1000MBit/full, supplying what is
* normally the 'WAN' switch ports.
*
* The switch is connected the MDIO bus on GE1. It looks like
* a normal AR7240 on-board switch.
*
* The GE0 port is connected via MII to PHY4, and can operate in
* 10/100mbit, full/half duplex. Ie, you can speak to PHY4 on
* the MDIO bus and everything will simply 'work'.
*
* So far so good. This looks just like an AR7240 SoC.
*
* However, some configurations will just expose one or two
* physical ports. In this case, some configuration bits can
* be set to tweak this.
*
* + CFG_SW_PHY_ADDR_SWAP swaps PHY port 0 with PHY port 4.
* Ie, GE0's PHY shows up as PHY 0. So if there's only
* one physical port, there's no need to involve the
* switch framework - it can just show up as a default,
* normal single PHY.
*
* + CFG_SW_PHY_SWAP swaps the internal switch connection
* between PHY0 and PHY4. Ie, PHY4 connects to MAc1,
* PHY0 connects to GE0.
*/
if ((resource_int_value("ar933x_gmac", 0, "override_phy", &val) == 0)
&& (val == 0))
return;
if ((resource_int_value("ar933x_gmac", 0, "swap_phy", &val) == 0)
&& (val == 1))
gmac_cfg |= AR933X_ETH_CFG_SW_PHY_SWAP;
if ((resource_int_value("ar933x_gmac", 0, "swap_phy_addr", &val) == 0)
&& (val == 1))
gmac_cfg |= AR933X_ETH_CFG_SW_PHY_ADDR_SWAP;
ar933x_configure_gmac(gmac_cfg);
}
struct ar71xx_cpu_def ar933x_chip_def = {
&ar933x_chip_detect_mem_size,
&ar933x_chip_detect_sys_frequency,
&ar933x_chip_device_stop,
&ar933x_chip_device_start,
&ar933x_chip_device_stopped,
&ar933x_chip_set_pll_ge,
&ar933x_chip_set_mii_speed,
&ar71xx_chip_set_mii_if,
&ar933x_chip_get_eth_pll,
&ar933x_chip_ddr_flush,
&ar933x_chip_init_usb_peripheral,
NULL,
NULL,
&ar933x_chip_init_gmac,
};

View File

@ -1,36 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2012 Adrian Chadd <adrian@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* $FreeBSD$ */
#ifndef __AR933X_CHIP_H__
#define __AR933X_CHIP_H__
extern struct ar71xx_cpu_def ar933x_chip_def;
#endif

View File

@ -1,93 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2012 Adrian Chadd <adrian@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
/*
* Atheros AR933x SoC UART registers
*/
#ifndef __AR933X_UART_H__
#define __AR933X_UART_H__
#define AR933X_UART_REGS_SIZE 20
#define AR933X_UART_FIFO_SIZE 16
#define AR933X_UART_DATA_REG 0x00
#define AR933X_UART_CS_REG 0x04
#define AR933X_UART_CLOCK_REG 0x08
#define AR933X_UART_INT_REG 0x0c
#define AR933X_UART_INT_EN_REG 0x10
#define AR933X_UART_DATA_TX_RX_MASK 0xff
#define AR933X_UART_DATA_RX_CSR (1 << 8)
#define AR933X_UART_DATA_TX_CSR (1 << 9)
#define AR933X_UART_CS_PARITY_S 0
#define AR933X_UART_CS_PARITY_M 0x3
#define AR933X_UART_CS_PARITY_NONE 0
#define AR933X_UART_CS_PARITY_ODD 1
#define AR933X_UART_CS_PARITY_EVEN 2
#define AR933X_UART_CS_IF_MODE_S 2
#define AR933X_UART_CS_IF_MODE_M 0x3
#define AR933X_UART_CS_IF_MODE_NONE 0
#define AR933X_UART_CS_IF_MODE_DTE 1
#define AR933X_UART_CS_IF_MODE_DCE 2
#define AR933X_UART_CS_FLOW_CTRL_S 4
#define AR933X_UART_CS_FLOW_CTRL_M 0x3
#define AR933X_UART_CS_DMA_EN (1 << 6)
#define AR933X_UART_CS_TX_READY_ORIDE (1 << 7)
#define AR933X_UART_CS_RX_READY_ORIDE (1 << 8)
#define AR933X_UART_CS_TX_READY (1 << 9)
#define AR933X_UART_CS_RX_BREAK (1 << 10)
#define AR933X_UART_CS_TX_BREAK (1 << 11)
#define AR933X_UART_CS_HOST_INT (1 << 12)
#define AR933X_UART_CS_HOST_INT_EN (1 << 13)
#define AR933X_UART_CS_TX_BUSY (1 << 14)
#define AR933X_UART_CS_RX_BUSY (1 << 15)
#define AR933X_UART_CLOCK_SCALE_M 0xff
#define AR933X_UART_CLOCK_SCALE_S 16
#define AR933X_UART_CLOCK_STEP_M 0xffff
#define AR933X_UART_CLOCK_STEP_S 0
#define AR933X_UART_MAX_SCALE 0xff
#define AR933X_UART_MAX_STEP 0xffff
#define AR933X_UART_INT_RX_VALID (1 << 0)
#define AR933X_UART_INT_TX_READY (1 << 1)
#define AR933X_UART_INT_RX_FRAMING_ERR (1 << 2)
#define AR933X_UART_INT_RX_OFLOW_ERR (1 << 3)
#define AR933X_UART_INT_TX_OFLOW_ERR (1 << 4)
#define AR933X_UART_INT_RX_PARITY_ERR (1 << 5)
#define AR933X_UART_INT_RX_BREAK_ON (1 << 6)
#define AR933X_UART_INT_RX_BREAK_OFF (1 << 7)
#define AR933X_UART_INT_RX_FULL (1 << 8)
#define AR933X_UART_INT_TX_EMPTY (1 << 9)
#define AR933X_UART_INT_ALLINTS 0x3ff
#endif /* __AR933X_UART_H__ */

View File

@ -1,102 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2012 Adrian Chadd <adrian@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef __AR93XX_REG_H__
#define __AR93XX_REG_H__
#define REV_ID_MAJOR_AR9330 0x0110
#define REV_ID_MAJOR_AR9331 0x1110
#define AR933X_REV_ID_REVISION_MASK 0x3
#define AR933X_GPIO_COUNT 30
#define AR933X_UART_BASE (AR71XX_APB_BASE + 0x00020000)
#define AR933X_UART_SIZE 0x14
#define AR933X_GMAC_BASE (AR71XX_APB_BASE + 0x00070000)
#define AR933X_GMAC_SIZE 0x04
#define AR933X_GMAC_REG_ETH_CFG (AR933X_GMAC_BASE + 0x00)
#define AR933X_ETH_CFG_RGMII_GE0 (1 << 0)
#define AR933X_ETH_CFG_MII_GE0 (1 << 1)
#define AR933X_ETH_CFG_GMII_GE0 (1 << 2)
#define AR933X_ETH_CFG_MII_GE0_MASTER (1 << 3)
#define AR933X_ETH_CFG_MII_GE0_SLAVE (1 << 4)
#define AR933X_ETH_CFG_MII_GE0_ERR_EN (1 << 5)
#define AR933X_ETH_CFG_SW_PHY_SWAP (1 << 7)
#define AR933X_ETH_CFG_SW_PHY_ADDR_SWAP (1 << 8)
#define AR933X_ETH_CFG_RMII_GE0 (1 << 9)
#define AR933X_ETH_CFG_RMII_GE0_SPD_10 0
#define AR933X_ETH_CFG_RMII_GE0_SPD_100 (1 << 10)
#define AR933X_WMAC_BASE (AR71XX_APB_BASE + 0x00100000)
#define AR933X_WMAC_SIZE 0x20000
#define AR933X_EHCI_BASE 0x1b000000
#define AR933X_EHCI_SIZE 0x1000
#define AR933X_DDR_REG_FLUSH_GE0 (AR71XX_APB_BASE + 0x7c)
#define AR933X_DDR_REG_FLUSH_GE1 (AR71XX_APB_BASE + 0x80)
#define AR933X_DDR_REG_FLUSH_USB (AR71XX_APB_BASE + 0x84)
#define AR933X_DDR_REG_FLUSH_WMAC (AR71XX_APB_BASE + 0x88)
#define AR933X_PLL_CPU_CONFIG_REG (AR71XX_PLL_CPU_BASE + 0x00)
#define AR933X_PLL_CLOCK_CTRL_REG (AR71XX_PLL_CPU_BASE + 0x08)
#define AR933X_PLL_CPU_CONFIG_NINT_SHIFT 10
#define AR933X_PLL_CPU_CONFIG_NINT_MASK 0x3f
#define AR933X_PLL_CPU_CONFIG_REFDIV_SHIFT 16
#define AR933X_PLL_CPU_CONFIG_REFDIV_MASK 0x1f
#define AR933X_PLL_CPU_CONFIG_OUTDIV_SHIFT 23
#define AR933X_PLL_CPU_CONFIG_OUTDIV_MASK 0x7
#define AR933X_PLL_CLOCK_CTRL_BYPASS (1 << 2)
#define AR933X_PLL_CLOCK_CTRL_CPU_DIV_SHIFT 5
#define AR933X_PLL_CLOCK_CTRL_CPU_DIV_MASK 0x3
#define AR933X_PLL_CLOCK_CTRL_DDR_DIV_SHIFT 10
#define AR933X_PLL_CLOCK_CTRL_DDR_DIV_MASK 0x3
#define AR933X_PLL_CLOCK_CTRL_AHB_DIV_SHIFT 15
#define AR933X_PLL_CLOCK_CTRL_AHB_DIV_MASK 0x7
#define AR933X_RESET_REG_RESET_MODULE (AR71XX_RST_BLOCK_BASE + 0x1c)
#define AR933X_RESET_REG_BOOTSTRAP (AR71XX_RST_BLOCK_BASE + 0xac)
#define AR933X_RESET_WMAC (1 << 11)
#define AR933X_RESET_USB_HOST (1 << 5)
#define AR933X_RESET_USB_PHY (1 << 4)
#define AR933X_RESET_USBSUS_OVERRIDE (1 << 3)
#define AR933X_BOOTSTRAP_REF_CLK_40 (1 << 0)
#define AR933X_PLL_VAL_1000 0x00110000
#define AR933X_PLL_VAL_100 0x00001099
#define AR933X_PLL_VAL_10 0x00991099
#endif /* __AR93XX_REG_H__ */

View File

@ -1,475 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2013 Adrian Chadd <adrian@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_ddb.h"
#include <sys/param.h>
#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/cons.h>
#include <sys/kdb.h>
#include <sys/reboot.h>
#include <vm/vm.h>
#include <vm/vm_page.h>
#include <net/ethernet.h>
#include <machine/clock.h>
#include <machine/cpu.h>
#include <machine/cpuregs.h>
#include <machine/hwfunc.h>
#include <machine/md_var.h>
#include <machine/trap.h>
#include <machine/vmparam.h>
#include <mips/atheros/ar71xxreg.h>
#include <mips/atheros/ar934xreg.h>
#include <mips/atheros/ar71xx_cpudef.h>
#include <mips/atheros/ar71xx_setup.h>
#include <mips/atheros/ar71xx_chip.h>
#include <mips/atheros/ar934x_chip.h>
static void
ar934x_chip_detect_mem_size(void)
{
}
static uint32_t
ar934x_get_pll_freq(uint32_t ref, uint32_t ref_div, uint32_t nint,
uint32_t nfrac, uint32_t frac, uint32_t out_div)
{
uint64_t t;
uint32_t ret;
t = u_ar71xx_refclk;
t *= nint;
t = t / ref_div;
ret = t;
t = u_ar71xx_refclk;
t *= nfrac;
t = t / (ref_div * frac);
ret += t;
ret /= (1 << out_div);
return (ret);
}
static void
ar934x_chip_detect_sys_frequency(void)
{
uint32_t pll, out_div, ref_div, nint, nfrac, frac, clk_ctrl, postdiv;
uint32_t cpu_pll, ddr_pll;
uint32_t bootstrap;
uint32_t reg;
bootstrap = ATH_READ_REG(AR934X_RESET_REG_BOOTSTRAP);
if (bootstrap & AR934X_BOOTSTRAP_REF_CLK_40)
u_ar71xx_refclk = 40 * 1000 * 1000;
else
u_ar71xx_refclk = 25 * 1000 * 1000;
pll = ATH_READ_REG(AR934X_SRIF_CPU_DPLL2_REG);
if (pll & AR934X_SRIF_DPLL2_LOCAL_PLL) {
out_div = (pll >> AR934X_SRIF_DPLL2_OUTDIV_SHIFT) &
AR934X_SRIF_DPLL2_OUTDIV_MASK;
pll = ATH_READ_REG(AR934X_SRIF_CPU_DPLL1_REG);
nint = (pll >> AR934X_SRIF_DPLL1_NINT_SHIFT) &
AR934X_SRIF_DPLL1_NINT_MASK;
nfrac = pll & AR934X_SRIF_DPLL1_NFRAC_MASK;
ref_div = (pll >> AR934X_SRIF_DPLL1_REFDIV_SHIFT) &
AR934X_SRIF_DPLL1_REFDIV_MASK;
frac = 1 << 18;
} else {
pll = ATH_READ_REG(AR934X_PLL_CPU_CONFIG_REG);
out_div = (pll >> AR934X_PLL_CPU_CONFIG_OUTDIV_SHIFT) &
AR934X_PLL_CPU_CONFIG_OUTDIV_MASK;
ref_div = (pll >> AR934X_PLL_CPU_CONFIG_REFDIV_SHIFT) &
AR934X_PLL_CPU_CONFIG_REFDIV_MASK;
nint = (pll >> AR934X_PLL_CPU_CONFIG_NINT_SHIFT) &
AR934X_PLL_CPU_CONFIG_NINT_MASK;
nfrac = (pll >> AR934X_PLL_CPU_CONFIG_NFRAC_SHIFT) &
AR934X_PLL_CPU_CONFIG_NFRAC_MASK;
frac = 1 << 6;
}
cpu_pll = ar934x_get_pll_freq(u_ar71xx_refclk, ref_div, nint,
nfrac, frac, out_div);
pll = ATH_READ_REG(AR934X_SRIF_DDR_DPLL2_REG);
if (pll & AR934X_SRIF_DPLL2_LOCAL_PLL) {
out_div = (pll >> AR934X_SRIF_DPLL2_OUTDIV_SHIFT) &
AR934X_SRIF_DPLL2_OUTDIV_MASK;
pll = ATH_READ_REG(AR934X_SRIF_DDR_DPLL1_REG);
nint = (pll >> AR934X_SRIF_DPLL1_NINT_SHIFT) &
AR934X_SRIF_DPLL1_NINT_MASK;
nfrac = pll & AR934X_SRIF_DPLL1_NFRAC_MASK;
ref_div = (pll >> AR934X_SRIF_DPLL1_REFDIV_SHIFT) &
AR934X_SRIF_DPLL1_REFDIV_MASK;
frac = 1 << 18;
} else {
pll = ATH_READ_REG(AR934X_PLL_DDR_CONFIG_REG);
out_div = (pll >> AR934X_PLL_DDR_CONFIG_OUTDIV_SHIFT) &
AR934X_PLL_DDR_CONFIG_OUTDIV_MASK;
ref_div = (pll >> AR934X_PLL_DDR_CONFIG_REFDIV_SHIFT) &
AR934X_PLL_DDR_CONFIG_REFDIV_MASK;
nint = (pll >> AR934X_PLL_DDR_CONFIG_NINT_SHIFT) &
AR934X_PLL_DDR_CONFIG_NINT_MASK;
nfrac = (pll >> AR934X_PLL_DDR_CONFIG_NFRAC_SHIFT) &
AR934X_PLL_DDR_CONFIG_NFRAC_MASK;
frac = 1 << 10;
}
ddr_pll = ar934x_get_pll_freq(u_ar71xx_refclk, ref_div, nint,
nfrac, frac, out_div);
clk_ctrl = ATH_READ_REG(AR934X_PLL_CPU_DDR_CLK_CTRL_REG);
postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_SHIFT) &
AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_MASK;
if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_PLL_BYPASS)
u_ar71xx_cpu_freq = u_ar71xx_refclk;
else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_CPUCLK_FROM_CPUPLL)
u_ar71xx_cpu_freq = cpu_pll / (postdiv + 1);
else
u_ar71xx_cpu_freq = ddr_pll / (postdiv + 1);
postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_SHIFT) &
AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_MASK;
if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_PLL_BYPASS)
u_ar71xx_ddr_freq = u_ar71xx_refclk;
else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_DDRCLK_FROM_DDRPLL)
u_ar71xx_ddr_freq = ddr_pll / (postdiv + 1);
else
u_ar71xx_ddr_freq = cpu_pll / (postdiv + 1);
postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_SHIFT) &
AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_MASK;
if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_PLL_BYPASS)
u_ar71xx_ahb_freq = u_ar71xx_refclk;
else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_AHBCLK_FROM_DDRPLL)
u_ar71xx_ahb_freq = ddr_pll / (postdiv + 1);
else
u_ar71xx_ahb_freq = cpu_pll / (postdiv + 1);
u_ar71xx_wdt_freq = u_ar71xx_refclk;
u_ar71xx_uart_freq = u_ar71xx_refclk;
/*
* Next, fetch reference clock speed for MDIO bus.
*/
reg = ATH_READ_REG(AR934X_PLL_SWITCH_CLOCK_CONTROL_REG);
if (reg & AR934X_PLL_SWITCH_CLOCK_CONTROL_MDIO_CLK_SEL) {
printf("%s: mdio=100MHz\n", __func__);
u_ar71xx_mdio_freq = (100 * 1000 * 1000);
} else {
printf("%s: mdio=%d Hz\n", __func__, u_ar71xx_refclk);
u_ar71xx_mdio_freq = u_ar71xx_refclk;
}
}
static void
ar934x_chip_device_stop(uint32_t mask)
{
uint32_t reg;
reg = ATH_READ_REG(AR934X_RESET_REG_RESET_MODULE);
ATH_WRITE_REG(AR934X_RESET_REG_RESET_MODULE, reg | mask);
}
static void
ar934x_chip_device_start(uint32_t mask)
{
uint32_t reg;
reg = ATH_READ_REG(AR934X_RESET_REG_RESET_MODULE);
ATH_WRITE_REG(AR934X_RESET_REG_RESET_MODULE, reg & ~mask);
}
static int
ar934x_chip_device_stopped(uint32_t mask)
{
uint32_t reg;
reg = ATH_READ_REG(AR934X_RESET_REG_RESET_MODULE);
return ((reg & mask) == mask);
}
static void
ar934x_chip_set_mii_speed(uint32_t unit, uint32_t speed)
{
/* XXX TODO */
return;
}
/*
* XXX TODO !!
*/
static void
ar934x_chip_set_pll_ge(int unit, int speed, uint32_t pll)
{
switch (unit) {
case 0:
ATH_WRITE_REG(AR934X_PLL_ETH_XMII_CONTROL_REG, pll);
break;
case 1:
/* XXX nothing */
break;
default:
printf("%s: invalid PLL set for arge unit: %d\n",
__func__, unit);
return;
}
}
static void
ar934x_chip_ddr_flush(ar71xx_flush_ddr_id_t id)
{
switch (id) {
case AR71XX_CPU_DDR_FLUSH_GE0:
ar71xx_ddr_flush(AR934X_DDR_REG_FLUSH_GE0);
break;
case AR71XX_CPU_DDR_FLUSH_GE1:
ar71xx_ddr_flush(AR934X_DDR_REG_FLUSH_GE1);
break;
case AR71XX_CPU_DDR_FLUSH_USB:
ar71xx_ddr_flush(AR934X_DDR_REG_FLUSH_USB);
break;
case AR71XX_CPU_DDR_FLUSH_PCIE:
ar71xx_ddr_flush(AR934X_DDR_REG_FLUSH_PCIE);
break;
case AR71XX_CPU_DDR_FLUSH_WMAC:
ar71xx_ddr_flush(AR934X_DDR_REG_FLUSH_WMAC);
break;
default:
printf("%s: invalid DDR flush id (%d)\n", __func__, id);
break;
}
}
static uint32_t
ar934x_chip_get_eth_pll(unsigned int mac, int speed)
{
uint32_t pll;
switch (speed) {
case 10:
pll = AR934X_PLL_VAL_10;
break;
case 100:
pll = AR934X_PLL_VAL_100;
break;
case 1000:
pll = AR934X_PLL_VAL_1000;
break;
default:
printf("%s%d: invalid speed %d\n", __func__, mac, speed);
pll = 0;
}
return (pll);
}
static void
ar934x_chip_reset_ethernet_switch(void)
{
ar71xx_device_stop(AR934X_RESET_ETH_SWITCH);
DELAY(100);
ar71xx_device_start(AR934X_RESET_ETH_SWITCH);
DELAY(100);
ar71xx_device_stop(AR934X_RESET_ETH_SWITCH_ANALOG);
DELAY(100);
ar71xx_device_start(AR934X_RESET_ETH_SWITCH_ANALOG);
DELAY(100);
}
static void
ar934x_configure_gmac(uint32_t gmac_cfg)
{
uint32_t reg;
reg = ATH_READ_REG(AR934X_GMAC_REG_ETH_CFG);
printf("%s: ETH_CFG=0x%08x\n", __func__, reg);
reg &= ~(AR934X_ETH_CFG_RGMII_GMAC0 | AR934X_ETH_CFG_MII_GMAC0 |
AR934X_ETH_CFG_MII_GMAC0 | AR934X_ETH_CFG_SW_ONLY_MODE |
AR934X_ETH_CFG_SW_PHY_SWAP);
reg |= gmac_cfg;
ATH_WRITE_REG(AR934X_GMAC_REG_ETH_CFG, reg);
}
static void
ar934x_chip_init_usb_peripheral(void)
{
uint32_t reg;
reg = ATH_READ_REG(AR934X_RESET_REG_BOOTSTRAP);
if (reg & AR934X_BOOTSTRAP_USB_MODE_DEVICE)
return;
ar71xx_device_stop(AR934X_RESET_USBSUS_OVERRIDE);
DELAY(100);
ar71xx_device_start(AR934X_RESET_USB_PHY);
DELAY(100);
ar71xx_device_start(AR934X_RESET_USB_PHY_ANALOG);
DELAY(100);
ar71xx_device_start(AR934X_RESET_USB_HOST);
DELAY(100);
}
static void
ar934x_chip_set_mii_if(uint32_t unit, uint32_t mii_mode)
{
/*
* XXX !
*
* Nothing to see here; although gmac0 can have its
* MII configuration changed, the register values
* are slightly different.
*/
}
/*
* XXX TODO: fetch default MII divider configuration
*/
static void
ar934x_chip_reset_wmac(void)
{
/* XXX TODO */
}
static void
ar934x_chip_init_gmac(void)
{
long gmac_cfg;
if (resource_long_value("ar934x_gmac", 0, "gmac_cfg",
&gmac_cfg) == 0) {
printf("%s: gmac_cfg=0x%08lx\n",
__func__,
(long) gmac_cfg);
ar934x_configure_gmac((uint32_t) gmac_cfg);
}
}
/*
* Reset the NAND Flash Controller.
*
* + active=1 means "make it active".
* + active=0 means "make it inactive".
*/
static void
ar934x_chip_reset_nfc(int active)
{
if (active) {
ar71xx_device_start(AR934X_RESET_NANDF);
DELAY(100);
ar71xx_device_start(AR934X_RESET_ETH_SWITCH_ANALOG);
DELAY(250);
} else {
ar71xx_device_stop(AR934X_RESET_ETH_SWITCH_ANALOG);
DELAY(250);
ar71xx_device_stop(AR934X_RESET_NANDF);
DELAY(100);
}
}
/*
* Configure the GPIO output mux setup.
*
* The AR934x introduced an output mux which allowed
* certain functions to be configured on any pin.
* Specifically, the switch PHY link LEDs and
* WMAC external RX LNA switches are not limited to
* a specific GPIO pin.
*/
static void
ar934x_chip_gpio_output_configure(int gpio, uint8_t func)
{
uint32_t reg, s;
uint32_t t;
if (gpio > AR934X_GPIO_COUNT)
return;
reg = AR934X_GPIO_REG_OUT_FUNC0 + rounddown(gpio, 4);
s = 8 * (gpio % 4);
/* read-modify-write */
t = ATH_READ_REG(AR71XX_GPIO_BASE + reg);
t &= ~(0xff << s);
t |= func << s;
ATH_WRITE_REG(AR71XX_GPIO_BASE + reg, t);
/* flush write */
ATH_READ_REG(AR71XX_GPIO_BASE + reg);
}
struct ar71xx_cpu_def ar934x_chip_def = {
&ar934x_chip_detect_mem_size,
&ar934x_chip_detect_sys_frequency,
&ar934x_chip_device_stop,
&ar934x_chip_device_start,
&ar934x_chip_device_stopped,
&ar934x_chip_set_pll_ge,
&ar934x_chip_set_mii_speed,
&ar934x_chip_set_mii_if,
&ar934x_chip_get_eth_pll,
&ar934x_chip_ddr_flush,
&ar934x_chip_init_usb_peripheral,
&ar934x_chip_reset_ethernet_switch,
&ar934x_chip_reset_wmac,
&ar934x_chip_init_gmac,
&ar934x_chip_reset_nfc,
&ar934x_chip_gpio_output_configure,
};

View File

@ -1,36 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2013 Adrian Chadd <adrian@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* $FreeBSD$ */
#ifndef __AR934X_CHIP_H__
#define __AR934X_CHIP_H__
extern struct ar71xx_cpu_def ar934x_chip_def;
#endif

View File

@ -1,177 +0,0 @@
/*
* Copyright (c) 2014 Adrian Chadd <adrian@FreeBSD.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
/*
* Register definitions for the built-in NAND controller
* of the Atheros AR934x and QCA955x SoCs.
*
* This file is based on the AR934x SoC driver from OpenWRT.
*
* Copyright (C) 2011-2013 Gabor Juhos <juhosg@openwrt.org>
*
* Used with permission.
*/
#ifndef __AR934X_NFCREG_H__
#define __AR934X_NFCREG_H__
#define BIT(x) (1 << (x))
#define AR934X_NFC_REG_CMD 0x00
#define AR934X_NFC_REG_CTRL 0x04
#define AR934X_NFC_REG_STATUS 0x08
#define AR934X_NFC_REG_INT_MASK 0x0c
#define AR934X_NFC_REG_INT_STATUS 0x10
#define AR934X_NFC_REG_ECC_CTRL 0x14
#define AR934X_NFC_REG_ECC_OFFSET 0x18
#define AR934X_NFC_REG_ADDR0_0 0x1c
#define AR934X_NFC_REG_ADDR0_1 0x24
#define AR934X_NFC_REG_ADDR1_0 0x20
#define AR934X_NFC_REG_ADDR1_1 0x28
#define AR934X_NFC_REG_SPARE_SIZE 0x30
#define AR934X_NFC_REG_PROTECT 0x38
#define AR934X_NFC_REG_LOOKUP_EN 0x40
#define AR934X_NFC_REG_LOOKUP(_x) (0x44 + (_i) * 4)
#define AR934X_NFC_REG_DMA_ADDR 0x64
#define AR934X_NFC_REG_DMA_COUNT 0x68
#define AR934X_NFC_REG_DMA_CTRL 0x6c
#define AR934X_NFC_REG_MEM_CTRL 0x80
#define AR934X_NFC_REG_DATA_SIZE 0x84
#define AR934X_NFC_REG_READ_STATUS 0x88
#define AR934X_NFC_REG_TIME_SEQ 0x8c
#define AR934X_NFC_REG_TIMINGS_ASYN 0x90
#define AR934X_NFC_REG_TIMINGS_SYN 0x94
#define AR934X_NFC_REG_FIFO_DATA 0x98
#define AR934X_NFC_REG_TIME_MODE 0x9c
#define AR934X_NFC_REG_DMA_ADDR_OFFS 0xa0
#define AR934X_NFC_REG_FIFO_INIT 0xb0
#define AR934X_NFC_REG_GEN_SEQ_CTRL 0xb4
#define AR934X_NFC_CMD_CMD_SEQ_S 0
#define AR934X_NFC_CMD_CMD_SEQ_M 0x3f
#define AR934X_NFC_CMD_SEQ_1C 0x00
#define AR934X_NFC_CMD_SEQ_ERASE 0x0e
#define AR934X_NFC_CMD_SEQ_12 0x0c
#define AR934X_NFC_CMD_SEQ_1C1AXR 0x21
#define AR934X_NFC_CMD_SEQ_S 0x24
#define AR934X_NFC_CMD_SEQ_1C3AXR 0x27
#define AR934X_NFC_CMD_SEQ_1C5A1CXR 0x2a
#define AR934X_NFC_CMD_SEQ_18 0x32
#define AR934X_NFC_CMD_INPUT_SEL_SIU 0
#define AR934X_NFC_CMD_INPUT_SEL_DMA BIT(6)
#define AR934X_NFC_CMD_ADDR_SEL_0 0
#define AR934X_NFC_CMD_ADDR_SEL_1 BIT(7)
#define AR934X_NFC_CMD_CMD0_S 8
#define AR934X_NFC_CMD_CMD0_M 0xff
#define AR934X_NFC_CMD_CMD1_S 16
#define AR934X_NFC_CMD_CMD1_M 0xff
#define AR934X_NFC_CMD_CMD2_S 24
#define AR934X_NFC_CMD_CMD2_M 0xff
#define AR934X_NFC_CTRL_ADDR_CYCLE0_M 0x7
#define AR934X_NFC_CTRL_ADDR_CYCLE0_S 0
#define AR934X_NFC_CTRL_SPARE_EN BIT(3)
#define AR934X_NFC_CTRL_INT_EN BIT(4)
#define AR934X_NFC_CTRL_ECC_EN BIT(5)
#define AR934X_NFC_CTRL_BLOCK_SIZE_S 6
#define AR934X_NFC_CTRL_BLOCK_SIZE_M 0x3
#define AR934X_NFC_CTRL_BLOCK_SIZE_32 0
#define AR934X_NFC_CTRL_BLOCK_SIZE_64 1
#define AR934X_NFC_CTRL_BLOCK_SIZE_128 2
#define AR934X_NFC_CTRL_BLOCK_SIZE_256 3
#define AR934X_NFC_CTRL_PAGE_SIZE_S 8
#define AR934X_NFC_CTRL_PAGE_SIZE_M 0x7
#define AR934X_NFC_CTRL_PAGE_SIZE_256 0
#define AR934X_NFC_CTRL_PAGE_SIZE_512 1
#define AR934X_NFC_CTRL_PAGE_SIZE_1024 2
#define AR934X_NFC_CTRL_PAGE_SIZE_2048 3
#define AR934X_NFC_CTRL_PAGE_SIZE_4096 4
#define AR934X_NFC_CTRL_PAGE_SIZE_8192 5
#define AR934X_NFC_CTRL_PAGE_SIZE_16384 6
#define AR934X_NFC_CTRL_CUSTOM_SIZE_EN BIT(11)
#define AR934X_NFC_CTRL_IO_WIDTH_8BITS 0
#define AR934X_NFC_CTRL_IO_WIDTH_16BITS BIT(12)
#define AR934X_NFC_CTRL_LOOKUP_EN BIT(13)
#define AR934X_NFC_CTRL_PROT_EN BIT(14)
#define AR934X_NFC_CTRL_WORK_MODE_ASYNC 0
#define AR934X_NFC_CTRL_WORK_MODE_SYNC BIT(15)
#define AR934X_NFC_CTRL_ADDR0_AUTO_INC BIT(16)
#define AR934X_NFC_CTRL_ADDR1_AUTO_INC BIT(17)
#define AR934X_NFC_CTRL_ADDR_CYCLE1_M 0x7
#define AR934X_NFC_CTRL_ADDR_CYCLE1_S 18
#define AR934X_NFC_CTRL_SMALL_PAGE BIT(21)
#define AR934X_NFC_DMA_CTRL_DMA_START BIT(7)
#define AR934X_NFC_DMA_CTRL_DMA_DIR_WRITE 0
#define AR934X_NFC_DMA_CTRL_DMA_DIR_READ BIT(6)
#define AR934X_NFC_DMA_CTRL_DMA_MODE_SG BIT(5)
#define AR934X_NFC_DMA_CTRL_DMA_BURST_S 2
#define AR934X_NFC_DMA_CTRL_DMA_BURST_0 0
#define AR934X_NFC_DMA_CTRL_DMA_BURST_1 1
#define AR934X_NFC_DMA_CTRL_DMA_BURST_2 2
#define AR934X_NFC_DMA_CTRL_DMA_BURST_3 3
#define AR934X_NFC_DMA_CTRL_DMA_BURST_4 4
#define AR934X_NFC_DMA_CTRL_DMA_BURST_5 5
#define AR934X_NFC_DMA_CTRL_ERR_FLAG BIT(1)
#define AR934X_NFC_DMA_CTRL_DMA_READY BIT(0)
#define AR934X_NFC_INT_DEV_RDY(_x) BIT(4 + (_x))
#define AR934X_NFC_INT_CMD_END BIT(1)
#define AR934X_NFC_ECC_CTRL_ERR_THRES_S 8
#define AR934X_NFC_ECC_CTRL_ERR_THRES_M 0x1f
#define AR934X_NFC_ECC_CTRL_ECC_CAP_S 5
#define AR934X_NFC_ECC_CTRL_ECC_CAP_M 0x7
#define AR934X_NFC_ECC_CTRL_ECC_CAP_2 0
#define AR934X_NFC_ECC_CTRL_ECC_CAP_4 1
#define AR934X_NFC_ECC_CTRL_ECC_CAP_6 2
#define AR934X_NFC_ECC_CTRL_ECC_CAP_8 3
#define AR934X_NFC_ECC_CTRL_ECC_CAP_10 4
#define AR934X_NFC_ECC_CTRL_ECC_CAP_12 5
#define AR934X_NFC_ECC_CTRL_ECC_CAP_14 6
#define AR934X_NFC_ECC_CTRL_ECC_CAP_16 7
#define AR934X_NFC_ECC_CTRL_ERR_OVER BIT(2)
#define AR934X_NFC_ECC_CTRL_ERR_UNCORRECT BIT(1)
#define AR934X_NFC_ECC_CTRL_ERR_CORRECT BIT(0)
#define AR934X_NFC_ECC_OFFS_OFSET_M 0xffff
/* default timing values */
#define AR934X_NFC_TIME_SEQ_DEFAULT 0x7fff
#define AR934X_NFC_TIMINGS_ASYN_DEFAULT 0x22
#define AR934X_NFC_TIMINGS_SYN_DEFAULT 0xf
#define AR934X_NFC_ID_BUF_SIZE 8
#define AR934X_NFC_DEV_READY_TIMEOUT 25 /* msecs */
#define AR934X_NFC_DMA_READY_TIMEOUT 25 /* msecs */
#define AR934X_NFC_DONE_TIMEOUT 1000
#define AR934X_NFC_DMA_RETRIES 20
#define AR934X_NFC_IRQ_MASK AR934X_NFC_INT_DEV_RDY(0)
#define AR934X_NFC_GENSEQ_SMALL_PAGE_READ 0x30043
#endif /* __AR934X_NFCREG_H__ */

View File

@ -1,241 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2013 Adrian Chadd <adrian@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef __AR934X_REG_H__
#define __AR934X_REG_H__
#define AR934X_GMAC_BASE (AR71XX_APB_BASE + 0x00070000)
#define AR934X_GMAC_SIZE 0x14
#define AR934X_WMAC_BASE (AR71XX_APB_BASE + 0x00100000)
#define AR934X_WMAC_SIZE 0x20000
#define AR934X_EHCI_BASE 0x1b000000
#define AR934X_EHCI_SIZE 0x200
#define AR934X_SRIF_BASE (AR71XX_APB_BASE + 0x00116000)
#define AR934X_SRIF_SIZE 0x1000
/* AR934x GMAC configuration */
#define AR934X_GMAC_REG_ETH_CFG (AR934X_GMAC_BASE + 0x00)
#define AR934X_ETH_CFG_RGMII_GMAC0 (1 << 0)
#define AR934X_ETH_CFG_MII_GMAC0 (1 << 1)
#define AR934X_ETH_CFG_GMII_GMAC0 (1 << 2)
#define AR934X_ETH_CFG_MII_GMAC0_MASTER (1 << 3)
#define AR934X_ETH_CFG_MII_GMAC0_SLAVE (1 << 4)
#define AR934X_ETH_CFG_MII_GMAC0_ERR_EN (1 << 5)
#define AR934X_ETH_CFG_SW_ONLY_MODE (1 << 6)
#define AR934X_ETH_CFG_SW_PHY_SWAP (1 << 7)
#define AR934X_ETH_CFG_SW_APB_ACCESS (1 << 9)
#define AR934X_ETH_CFG_RMII_GMAC0 (1 << 10)
#define AR933X_ETH_CFG_MII_CNTL_SPEED (1 << 11)
#define AR934X_ETH_CFG_RMII_GMAC0_MASTER (1 << 12)
#define AR934X_ETH_CFG_SW_ACC_MSB_FIRST (1 << 13)
#define AR934X_DDR_REG_FLUSH_GE0 (AR71XX_APB_BASE + 0x9c)
#define AR934X_DDR_REG_FLUSH_GE1 (AR71XX_APB_BASE + 0xa0)
#define AR934X_DDR_REG_FLUSH_USB (AR71XX_APB_BASE + 0xa4)
#define AR934X_DDR_REG_FLUSH_PCIE (AR71XX_APB_BASE + 0xa8)
#define AR934X_DDR_REG_FLUSH_WMAC (AR71XX_APB_BASE + 0xac)
#define AR934X_PLL_CPU_CONFIG_REG (AR71XX_PLL_CPU_BASE + 0x00)
#define AR934X_PLL_DDR_CONFIG_REG (AR71XX_PLL_CPU_BASE + 0x04)
#define AR934X_PLL_CPU_DDR_CLK_CTRL_REG (AR71XX_PLL_CPU_BASE + 0x08)
#define AR934X_PLL_SWITCH_CLOCK_CONTROL_REG (AR71XX_PLL_CPU_BASE + 0x24)
#define AR934X_PLL_SWITCH_CLOCK_CONTROL_MDIO_CLK_SEL (1 << 6)
#define AR934X_PLL_ETH_XMII_CONTROL_REG (AR71XX_PLL_CPU_BASE + 0x2c)
#define AR934X_PLL_CPU_CONFIG_NFRAC_SHIFT 0
#define AR934X_PLL_CPU_CONFIG_NFRAC_MASK 0x3f
#define AR934X_PLL_CPU_CONFIG_NINT_SHIFT 6
#define AR934X_PLL_CPU_CONFIG_NINT_MASK 0x3f
#define AR934X_PLL_CPU_CONFIG_REFDIV_SHIFT 12
#define AR934X_PLL_CPU_CONFIG_REFDIV_MASK 0x1f
#define AR934X_PLL_CPU_CONFIG_OUTDIV_SHIFT 19
#define AR934X_PLL_CPU_CONFIG_OUTDIV_MASK 0x3
#define AR934X_PLL_DDR_CONFIG_NFRAC_SHIFT 0
#define AR934X_PLL_DDR_CONFIG_NFRAC_MASK 0x3ff
#define AR934X_PLL_DDR_CONFIG_NINT_SHIFT 10
#define AR934X_PLL_DDR_CONFIG_NINT_MASK 0x3f
#define AR934X_PLL_DDR_CONFIG_REFDIV_SHIFT 16
#define AR934X_PLL_DDR_CONFIG_REFDIV_MASK 0x1f
#define AR934X_PLL_DDR_CONFIG_OUTDIV_SHIFT 23
#define AR934X_PLL_DDR_CONFIG_OUTDIV_MASK 0x7
#define AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_PLL_BYPASS (1 << 2)
#define AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_PLL_BYPASS (1 << 3)
#define AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_PLL_BYPASS (1 << 4)
#define AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_SHIFT 5
#define AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_MASK 0x1f
#define AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_SHIFT 10
#define AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_MASK 0x1f
#define AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_SHIFT 15
#define AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_MASK 0x1f
#define AR934X_PLL_CPU_DDR_CLK_CTRL_CPUCLK_FROM_CPUPLL (1 << 20)
#define AR934X_PLL_CPU_DDR_CLK_CTRL_DDRCLK_FROM_DDRPLL (1 << 21)
#define AR934X_PLL_CPU_DDR_CLK_CTRL_AHBCLK_FROM_DDRPLL (1 << 24)
#define AR934X_RESET_REG_RESET_MODULE (AR71XX_RST_BLOCK_BASE + 0x1c)
#define AR934X_RESET_REG_BOOTSTRAP (AR71XX_RST_BLOCK_BASE + 0xb0)
#define AR934X_RESET_REG_PCIE_WMAC_INT_STATUS (AR71XX_RST_BLOCK_BASE + 0xac)
#define AR934X_RESET_HOST (1U << 31)
#define AR934X_RESET_SLIC (1 << 30)
#define AR934X_RESET_HDMA (1 << 29)
#define AR934X_RESET_EXTERNAL (1 << 28)
#define AR934X_RESET_RTC (1 << 27)
#define AR934X_RESET_PCIE_EP_INT (1 << 26)
#define AR934X_RESET_CHKSUM_ACC (1 << 25)
#define AR934X_RESET_FULL_CHIP (1 << 24)
#define AR934X_RESET_GE1_MDIO (1 << 23)
#define AR934X_RESET_GE0_MDIO (1 << 22)
#define AR934X_RESET_CPU_NMI (1 << 21)
#define AR934X_RESET_CPU_COLD (1 << 20)
#define AR934X_RESET_HOST_RESET_INT (1 << 19)
#define AR934X_RESET_PCIE_EP (1 << 18)
#define AR934X_RESET_UART1 (1 << 17)
#define AR934X_RESET_DDR (1 << 16)
#define AR934X_RESET_USB_PHY_PLL_PWD_EXT (1 << 15)
#define AR934X_RESET_NANDF (1 << 14)
#define AR934X_RESET_GE1_MAC (1 << 13)
#define AR934X_RESET_ETH_SWITCH_ANALOG (1 << 12)
#define AR934X_RESET_USB_PHY_ANALOG (1 << 11)
#define AR934X_RESET_HOST_DMA_INT (1 << 10)
#define AR934X_RESET_GE0_MAC (1 << 9)
#define AR934X_RESET_ETH_SWITCH (1 << 8)
#define AR934X_RESET_PCIE_PHY (1 << 7)
#define AR934X_RESET_PCIE (1 << 6)
#define AR934X_RESET_USB_HOST (1 << 5)
#define AR934X_RESET_USB_PHY (1 << 4)
#define AR934X_RESET_USBSUS_OVERRIDE (1 << 3)
#define AR934X_RESET_LUT (1 << 2)
#define AR934X_RESET_MBOX (1 << 1)
#define AR934X_RESET_I2S (1 << 0)
#define AR934X_BOOTSTRAP_SW_OPTION8 (1 << 23)
#define AR934X_BOOTSTRAP_SW_OPTION7 (1 << 22)
#define AR934X_BOOTSTRAP_SW_OPTION6 (1 << 21)
#define AR934X_BOOTSTRAP_SW_OPTION5 (1 << 20)
#define AR934X_BOOTSTRAP_SW_OPTION4 (1 << 19)
#define AR934X_BOOTSTRAP_SW_OPTION3 (1 << 18)
#define AR934X_BOOTSTRAP_SW_OPTION2 (1 << 17)
#define AR934X_BOOTSTRAP_SW_OPTION1 (1 << 16)
#define AR934X_BOOTSTRAP_USB_MODE_DEVICE (1 << 7)
#define AR934X_BOOTSTRAP_PCIE_RC (1 << 6)
#define AR934X_BOOTSTRAP_EJTAG_MODE (1 << 5)
#define AR934X_BOOTSTRAP_REF_CLK_40 (1 << 4)
#define AR934X_BOOTSTRAP_BOOT_FROM_SPI (1 << 2)
#define AR934X_BOOTSTRAP_SDRAM_DISABLED (1 << 1)
#define AR934X_BOOTSTRAP_DDR1 (1 << 0)
#define AR934X_PCIE_WMAC_INT_WMAC_MISC (1 << 0)
#define AR934X_PCIE_WMAC_INT_WMAC_TX (1 << 1)
#define AR934X_PCIE_WMAC_INT_WMAC_RXLP (1 << 2)
#define AR934X_PCIE_WMAC_INT_WMAC_RXHP (1 << 3)
#define AR934X_PCIE_WMAC_INT_PCIE_RC (1 << 4)
#define AR934X_PCIE_WMAC_INT_PCIE_RC0 (1 << 5)
#define AR934X_PCIE_WMAC_INT_PCIE_RC1 (1 << 6)
#define AR934X_PCIE_WMAC_INT_PCIE_RC2 (1 << 7)
#define AR934X_PCIE_WMAC_INT_PCIE_RC3 (1 << 8)
#define AR934X_PCIE_WMAC_INT_WMAC_ALL \
(AR934X_PCIE_WMAC_INT_WMAC_MISC | AR934X_PCIE_WMAC_INT_WMAC_TX | \
AR934X_PCIE_WMAC_INT_WMAC_RXLP | AR934X_PCIE_WMAC_INT_WMAC_RXHP)
#define AR934X_PCIE_WMAC_INT_PCIE_ALL \
(AR934X_PCIE_WMAC_INT_PCIE_RC | AR934X_PCIE_WMAC_INT_PCIE_RC0 | \
AR934X_PCIE_WMAC_INT_PCIE_RC1 | AR934X_PCIE_WMAC_INT_PCIE_RC2 | \
AR934X_PCIE_WMAC_INT_PCIE_RC3)
#define REV_ID_MAJOR_AR9341 0x0120
#define REV_ID_MAJOR_AR9342 0x1120
#define REV_ID_MAJOR_AR9344 0x2120
#define AR934X_REV_ID_REVISION_MASK 0xf
/*
* GPIO block
*/
#define AR934X_GPIO_REG_OUT_FUNC0 0x2c
#define AR934X_GPIO_REG_OUT_FUNC1 0x30
#define AR934X_GPIO_REG_OUT_FUNC2 0x34
#define AR934X_GPIO_REG_OUT_FUNC3 0x38
#define AR934X_GPIO_REG_OUT_FUNC4 0x3c
#define AR934X_GPIO_REG_OUT_FUNC5 0x40
#define AR934X_GPIO_REG_FUNC 0x6c
#define AR934X_GPIO_COUNT 23
/* GPIO functions */
#define AR934X_GPIO_FUNC_CLK_OBS7_EN (1 << 9)
#define AR934X_GPIO_FUNC_CLK_OBS6_EN (1 << 8)
#define AR934X_GPIO_FUNC_CLK_OBS5_EN (1 << 7)
#define AR934X_GPIO_FUNC_CLK_OBS4_EN (1 << 6)
#define AR934X_GPIO_FUNC_CLK_OBS3_EN (1 << 5)
#define AR934X_GPIO_FUNC_CLK_OBS2_EN (1 << 4)
#define AR934X_GPIO_FUNC_CLK_OBS1_EN (1 << 3)
#define AR934X_GPIO_FUNC_CLK_OBS0_EN (1 << 2)
#define AR934X_GPIO_FUNC_JTAG_DISABLE (1 << 1)
/* GPIO MUX output function: AR934X_GPIO_REG_OUT_FUNCx */
#define AR934X_GPIO_OUT_GPIO 0 /* I'm a GPIO */
#define AR934X_GPIO_OUT_SPI_CS1 7 /* I'm SPI CS1 */
#define AR934X_GPIO_OUT_LED_LINK0 41 /* I'm switch phy link0 */
#define AR934X_GPIO_OUT_LED_LINK1 42
#define AR934X_GPIO_OUT_LED_LINK2 43
#define AR934X_GPIO_OUT_LED_LINK3 44
#define AR934X_GPIO_OUT_LED_LINK4 45
#define AR934X_GPIO_OUT_EXT_LNA0 46 /* I'm WMAC EXT LNA chain 0 */
#define AR934X_GPIO_OUT_EXT_LNA1 47 /* I'm WMAC EXT LNA chain 1 */
/*
* SRIF block
*/
#define AR934X_SRIF_CPU_DPLL1_REG (AR934X_SRIF_BASE + 0x1c0)
#define AR934X_SRIF_CPU_DPLL2_REG (AR934X_SRIF_BASE + 0x1c4)
#define AR934X_SRIF_CPU_DPLL3_REG (AR934X_SRIF_BASE + 0x1c8)
#define AR934X_SRIF_DDR_DPLL1_REG (AR934X_SRIF_BASE + 0x240)
#define AR934X_SRIF_DDR_DPLL2_REG (AR934X_SRIF_BASE + 0x244)
#define AR934X_SRIF_DDR_DPLL3_REG (AR934X_SRIF_BASE + 0x248)
#define AR934X_SRIF_DPLL1_REFDIV_SHIFT 27
#define AR934X_SRIF_DPLL1_REFDIV_MASK 0x1f
#define AR934X_SRIF_DPLL1_NINT_SHIFT 18
#define AR934X_SRIF_DPLL1_NINT_MASK 0x1ff
#define AR934X_SRIF_DPLL1_NFRAC_MASK 0x0003ffff
#define AR934X_SRIF_DPLL2_LOCAL_PLL (1 << 30)
#define AR934X_SRIF_DPLL2_OUTDIV_SHIFT 13
#define AR934X_SRIF_DPLL2_OUTDIV_MASK 0x7
/* XXX verify! */
#define AR934X_PLL_VAL_1000 0x16000000
#define AR934X_PLL_VAL_100 0x00000101
#define AR934X_PLL_VAL_10 0x00001616
#endif /* __AR934X_REG_H__ */

View File

@ -1,35 +0,0 @@
# $FreeBSD$
mips/atheros/apb.c optional ar71xx_apb
mips/atheros/ar71xx_caldata.c optional ar71xx_caldata
mips/atheros/ar71xx_gpio.c optional gpio
mips/atheros/ar71xx_machdep.c standard
mips/atheros/ar71xx_ehci.c optional ehci
mips/atheros/ar71xx_ohci.c optional ohci
mips/atheros/ar71xx_pci.c optional ar71xx_pci pci
mips/atheros/ar724x_pci.c optional ar724x_pci pci
mips/atheros/ar71xx_pci_bus_space.c optional pci
mips/atheros/ar71xx_spi.c optional ar71xx_spi
mips/atheros/ar71xx_macaddr.c standard
mips/atheros/pcf2123_rtc.c optional pcf2123_rtc ar71xx_spi
mips/atheros/ar71xx_wdog.c optional ar71xx_wdog
mips/atheros/if_arge.c optional arge
mips/atheros/uart_bus_ar71xx.c optional uart_ar71xx
mips/atheros/uart_cpu_ar71xx.c optional uart_ar71xx
mips/atheros/uart_bus_ar933x.c optional uart_ar933x
mips/atheros/uart_cpu_ar933x.c optional uart_ar933x
mips/atheros/uart_dev_ar933x.c optional uart_ar933x
mips/atheros/ar71xx_bus_space_reversed.c standard
mips/mips/intr_machdep.c standard
mips/mips/tick.c standard
mips/atheros/ar71xx_setup.c standard
mips/atheros/ar71xx_chip.c standard
mips/atheros/ar724x_chip.c standard
mips/atheros/ar91xx_chip.c standard
mips/atheros/ar933x_chip.c standard
mips/atheros/ar934x_chip.c standard
mips/atheros/qca953x_chip.c standard
mips/atheros/qca955x_chip.c standard
mips/atheros/ar71xx_fixup.c optional ar71xx_ath_eeprom
mips/atheros/qca955x_apb.c optional qca955x_apb
mips/atheros/qca955x_pci.c optional qca955x_pci pci

File diff suppressed because it is too large Load Diff

View File

@ -1,222 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2009, Oleksandr Tymoshenko
* 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 unmodified, this list of conditions, and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef __IF_ARGEVAR_H__
#define __IF_ARGEVAR_H__
#define ARGE_NPHY 32
#define ARGE_TX_RING_COUNT 128
#define ARGE_RX_RING_COUNT 128
#define ARGE_RX_DMA_SIZE ARGE_RX_RING_COUNT * sizeof(struct arge_desc)
#define ARGE_TX_DMA_SIZE ARGE_TX_RING_COUNT * sizeof(struct arge_desc)
#define ARGE_MAXFRAGS 8
#define ARGE_RING_ALIGN sizeof(struct arge_desc)
#define ARGE_RX_ALIGN_4BYTE sizeof(uint32_t)
#define ARGE_RX_ALIGN_1BYTE sizeof(char)
#define ARGE_TX_ALIGN_4BYTE sizeof(uint32_t)
#define ARGE_TX_ALIGN_1BYTE sizeof(char)
#define ARGE_MAXFRAGS 8
#define ARGE_TX_RING_ADDR(sc, i) \
((sc)->arge_rdata.arge_tx_ring_paddr + sizeof(struct arge_desc) * (i))
#define ARGE_RX_RING_ADDR(sc, i) \
((sc)->arge_rdata.arge_rx_ring_paddr + sizeof(struct arge_desc) * (i))
#define ARGE_INC(x,y) (x) = (((x) + 1) % y)
#define ARGE_MII_TIMEOUT 1000
#define ARGE_LOCK(_sc) mtx_lock(&(_sc)->arge_mtx)
#define ARGE_UNLOCK(_sc) mtx_unlock(&(_sc)->arge_mtx)
#define ARGE_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->arge_mtx, MA_OWNED)
/*
* register space access macros
*/
#define ARGE_BARRIER_READ(sc) bus_barrier(sc->arge_res, 0, 0, \
BUS_SPACE_BARRIER_READ)
#define ARGE_BARRIER_WRITE(sc) bus_barrier(sc->arge_res, 0, 0, \
BUS_SPACE_BARRIER_WRITE)
#define ARGE_BARRIER_RW(sc) bus_barrier(sc->arge_res, 0, 0, \
BUS_SPACE_BARRIER_READ | \
BUS_SPACE_BARRIER_WRITE)
#define ARGE_WRITE(sc, reg, val) do { \
bus_write_4(sc->arge_res, (reg), (val)); \
ARGE_BARRIER_WRITE((sc)); \
ARGE_READ((sc), (reg)); \
} while (0)
#define ARGE_READ(sc, reg) bus_read_4(sc->arge_res, (reg))
#define ARGE_SET_BITS(sc, reg, bits) \
ARGE_WRITE(sc, reg, ARGE_READ(sc, (reg)) | (bits))
#define ARGE_CLEAR_BITS(sc, reg, bits) \
ARGE_WRITE(sc, reg, ARGE_READ(sc, (reg)) & ~(bits))
/*
* The linux driver code for the MDIO bus does a read-after-write
* which seems to be required on MIPS74k platforms for correct
* behaviour.
*
* So, ARGE_WRITE() does the write + barrier, and the following
* ARGE_READ() seems to flush the thing all the way through the device
* FIFO(s) before we continue issuing MDIO bus updates.
*/
#define ARGE_MDIO_WRITE(_sc, _reg, _val) \
ARGE_WRITE((_sc), (_reg), (_val))
#define ARGE_MDIO_READ(_sc, _reg) \
ARGE_READ((_sc), (_reg))
#define ARGE_MDIO_BARRIER_READ(_sc) ARGE_BARRIER_READ(_sc)
#define ARGE_MDIO_BARRIER_WRITE(_sc) ARGE_BARRIER_WRITE(_sc)
#define ARGE_MDIO_BARRIER_RW(_sc) ARGE_BARRIER_RW(_sc)
#define ARGE_DESC_EMPTY (1U << 31)
#define ARGE_DESC_MORE (1 << 24)
#define ARGE_DESC_SIZE_MASK ((1 << 12) - 1)
#define ARGE_DMASIZE(len) ((len) & ARGE_DESC_SIZE_MASK)
struct arge_desc {
uint32_t packet_addr;
uint32_t packet_ctrl;
uint32_t next_desc;
uint32_t padding;
};
struct arge_txdesc {
struct mbuf *tx_m;
bus_dmamap_t tx_dmamap;
};
struct arge_rxdesc {
struct mbuf *rx_m;
bus_dmamap_t rx_dmamap;
struct arge_desc *desc;
};
struct arge_chain_data {
bus_dma_tag_t arge_parent_tag;
bus_dma_tag_t arge_tx_tag;
struct arge_txdesc arge_txdesc[ARGE_TX_RING_COUNT];
bus_dma_tag_t arge_rx_tag;
struct arge_rxdesc arge_rxdesc[ARGE_RX_RING_COUNT];
bus_dma_tag_t arge_tx_ring_tag;
bus_dma_tag_t arge_rx_ring_tag;
bus_dmamap_t arge_tx_ring_map;
bus_dmamap_t arge_rx_ring_map;
bus_dmamap_t arge_rx_sparemap;
int arge_tx_prod;
int arge_tx_cons;
int arge_tx_cnt;
int arge_rx_cons;
};
struct arge_ring_data {
struct arge_desc *arge_rx_ring;
struct arge_desc *arge_tx_ring;
bus_addr_t arge_rx_ring_paddr;
bus_addr_t arge_tx_ring_paddr;
};
/*
* Allow PLL values to be overridden.
*/
struct arge_pll_data {
uint32_t pll_10;
uint32_t pll_100;
uint32_t pll_1000;
};
/*
* Hardware specific behaviours.
*/
/*
* Older chips support 4 byte only transmit and receive
* addresses.
*
* Later chips support arbitrary TX and later later,
* arbitrary RX addresses.
*/
#define ARGE_HW_FLG_TX_DESC_ALIGN_4BYTE 0x00000001
#define ARGE_HW_FLG_RX_DESC_ALIGN_4BYTE 0x00000002
#define ARGE_HW_FLG_TX_DESC_ALIGN_1BYTE 0x00000004
#define ARGE_HW_FLG_RX_DESC_ALIGN_1BYTE 0x00000008
struct arge_softc {
struct ifnet *arge_ifp; /* interface info */
device_t arge_dev;
struct ifmedia arge_ifmedia;
/*
* Media & duples settings for multiPHY MAC
*/
uint32_t arge_media_type;
uint32_t arge_duplex_mode;
uint32_t arge_phymask;
uint8_t arge_eaddr[ETHER_ADDR_LEN];
struct resource *arge_res;
int arge_rid;
struct resource *arge_irq;
void *arge_intrhand;
device_t arge_miibus;
device_t arge_miiproxy;
ar71xx_mii_mode arge_miicfg;
struct arge_pll_data arge_pllcfg;
bus_dma_tag_t arge_parent_tag;
bus_dma_tag_t arge_tag;
struct mtx arge_mtx;
struct callout arge_stat_callout;
struct task arge_link_task;
struct arge_chain_data arge_cdata;
struct arge_ring_data arge_rdata;
int arge_link_status;
int arge_detach;
uint32_t arge_intr_status;
int arge_mac_unit;
int arge_if_flags;
uint32_t arge_hw_flags;
uint32_t arge_debug;
uint32_t arge_mdiofreq;
struct {
uint32_t tx_pkts_unaligned;
uint32_t tx_pkts_unaligned_start;
uint32_t tx_pkts_unaligned_len;
uint32_t tx_pkts_unaligned_tooshort;
uint32_t tx_pkts_nosegs;
uint32_t tx_pkts_aligned;
uint32_t rx_overflow;
uint32_t tx_underflow;
uint32_t intr_stray;
uint32_t intr_stray2;
uint32_t intr_ok;
} stats;
struct {
uint32_t count[32];
} intr_stats;
};
#endif /* __IF_ARGEVAR_H__ */

View File

@ -1,206 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2010, Oleksandr Tymoshenko <gonzo@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 unmodified, this list of conditions, and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/lock.h>
#include <sys/time.h>
#include <sys/clock.h>
#include <sys/resource.h>
#include <sys/systm.h>
#include <sys/rman.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <mips/atheros/pcf2123reg.h>
#include <dev/spibus/spi.h>
#include "spibus_if.h"
#include "clock_if.h"
#define YEAR_BASE 1970
#define PCF2123_DELAY 50
struct pcf2123_rtc_softc {
device_t dev;
};
static int pcf2123_rtc_probe(device_t dev);
static int pcf2123_rtc_attach(device_t dev);
static int pcf2123_rtc_gettime(device_t dev, struct timespec *ts);
static int pcf2123_rtc_settime(device_t dev, struct timespec *ts);
static int
pcf2123_rtc_probe(device_t dev)
{
device_set_desc(dev, "PCF2123 SPI RTC");
return (0);
}
static int
pcf2123_rtc_attach(device_t dev)
{
struct pcf2123_rtc_softc *sc;
struct spi_command cmd;
unsigned char rxBuf[3];
unsigned char txBuf[3];
int err;
sc = device_get_softc(dev);
sc->dev = dev;
clock_register(dev, 1000000);
memset(&cmd, 0, sizeof(cmd));
memset(rxBuf, 0, sizeof(rxBuf));
memset(txBuf, 0, sizeof(txBuf));
/* Make sure Ctrl1 and Ctrl2 are zeroes */
txBuf[0] = PCF2123_WRITE(PCF2123_REG_CTRL1);
cmd.rx_cmd = rxBuf;
cmd.tx_cmd = txBuf;
cmd.rx_cmd_sz = sizeof(rxBuf);
cmd.tx_cmd_sz = sizeof(txBuf);
err = SPIBUS_TRANSFER(device_get_parent(dev), dev, &cmd);
DELAY(PCF2123_DELAY);
return (0);
}
static int
pcf2123_rtc_gettime(device_t dev, struct timespec *ts)
{
struct clocktime ct;
struct spi_command cmd;
unsigned char rxTimedate[8];
unsigned char txTimedate[8];
int err;
memset(&cmd, 0, sizeof(cmd));
memset(rxTimedate, 0, sizeof(rxTimedate));
memset(txTimedate, 0, sizeof(txTimedate));
/*
* Counter is stopped when access to time registers is in progress
* So there is no need to stop/start counter
*/
/* Start reading from seconds */
txTimedate[0] = PCF2123_READ(PCF2123_REG_SECONDS);
cmd.rx_cmd = rxTimedate;
cmd.tx_cmd = txTimedate;
cmd.rx_cmd_sz = sizeof(rxTimedate);
cmd.tx_cmd_sz = sizeof(txTimedate);
err = SPIBUS_TRANSFER(device_get_parent(dev), dev, &cmd);
DELAY(PCF2123_DELAY);
ct.nsec = 0;
ct.sec = FROMBCD(rxTimedate[1] & 0x7f);
ct.min = FROMBCD(rxTimedate[2] & 0x7f);
ct.hour = FROMBCD(rxTimedate[3] & 0x3f);
ct.dow = FROMBCD(rxTimedate[5] & 0x3f);
ct.day = FROMBCD(rxTimedate[4] & 0x3f);
ct.mon = FROMBCD(rxTimedate[6] & 0x1f);
ct.year = YEAR_BASE + FROMBCD(rxTimedate[7]);
return (clock_ct_to_ts(&ct, ts));
}
static int
pcf2123_rtc_settime(device_t dev, struct timespec *ts)
{
struct clocktime ct;
struct pcf2123_rtc_softc *sc;
struct spi_command cmd;
unsigned char rxTimedate[8];
unsigned char txTimedate[8];
int err;
sc = device_get_softc(dev);
/* Resolution: 1 sec */
if (ts->tv_nsec >= 500000000)
ts->tv_sec++;
ts->tv_nsec = 0;
clock_ts_to_ct(ts, &ct);
memset(&cmd, 0, sizeof(cmd));
memset(rxTimedate, 0, sizeof(rxTimedate));
memset(txTimedate, 0, sizeof(txTimedate));
/* Start reading from seconds */
cmd.rx_cmd = rxTimedate;
cmd.tx_cmd = txTimedate;
cmd.rx_cmd_sz = sizeof(rxTimedate);
cmd.tx_cmd_sz = sizeof(txTimedate);
/*
* Counter is stopped when access to time registers is in progress
* So there is no need to stop/start counter
*/
txTimedate[0] = PCF2123_WRITE(PCF2123_REG_SECONDS);
txTimedate[1] = TOBCD(ct.sec);
txTimedate[2] = TOBCD(ct.min);
txTimedate[3] = TOBCD(ct.hour);
txTimedate[4] = TOBCD(ct.day);
txTimedate[5] = TOBCD(ct.dow);
txTimedate[6] = TOBCD(ct.mon);
txTimedate[7] = TOBCD(ct.year - YEAR_BASE);
err = SPIBUS_TRANSFER(device_get_parent(dev), dev, &cmd);
DELAY(PCF2123_DELAY);
return (err);
}
static device_method_t pcf2123_rtc_methods[] = {
DEVMETHOD(device_probe, pcf2123_rtc_probe),
DEVMETHOD(device_attach, pcf2123_rtc_attach),
DEVMETHOD(clock_gettime, pcf2123_rtc_gettime),
DEVMETHOD(clock_settime, pcf2123_rtc_settime),
{ 0, 0 },
};
static driver_t pcf2123_rtc_driver = {
"rtc",
pcf2123_rtc_methods,
sizeof(struct pcf2123_rtc_softc),
};
static devclass_t pcf2123_rtc_devclass;
DRIVER_MODULE(pcf2123_rtc, spibus, pcf2123_rtc_driver, pcf2123_rtc_devclass, 0, 0);

View File

@ -1,68 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@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 unmodified, this list of conditions, and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* $FreeBSD$ */
#ifndef __PCF2123REG_H__
#define __PCF2123REG_H__
/* Control and status */
#define PCF2123_REG_CTRL1 0x0
#define PCF2123_REG_CTRL2 0x1
/* Time and date */
#define PCF2123_REG_SECONDS 0x2
#define PCF2123_REG_MINUTES 0x3
#define PCF2123_REG_HOURS 0x4
#define PCF2123_REG_DAYS 0x5
#define PCF2123_REG_WEEKDAYS 0x6
#define PCF2123_REG_MONTHS 0x7
#define PCF2123_REG_YEARS 0x8
/* Alarm registers */
#define PCF2123_REG_MINUTE_ALARM 0x9
#define PCF2123_REG_HOUR_ALARM 0xA
#define PCF2123_REG_DAY_ALARM 0xB
#define PCF2123_REG_WEEKDAY_ALARM 0xC
/* Offset */
#define PCF2123_REG_OFFSET 0xD
/* Timer */
#define PCF2123_REG_TIMER_CLKOUT 0xE
#define PCF2123_REG_COUNTDOWN_TIMER 0xF
/* Commands */
#define PCF2123_CMD_READ (1 << 7)
#define PCF2123_CMD_WRITE (0 << 7)
#define PCF2123_READ(reg) (PCF2123_CMD_READ | (1 << 4) | (reg))
#define PCF2123_WRITE(reg) (PCF2123_CMD_WRITE | (1 << 4) | (reg))
#endif /* __PCF2123REG_H__ */

View File

@ -1,393 +0,0 @@
/*-
* Copyright (c) 2015 Adrian Chadd <adrian@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_ddb.h"
#include <sys/param.h>
#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/cons.h>
#include <sys/kdb.h>
#include <sys/reboot.h>
#include <vm/vm.h>
#include <vm/vm_page.h>
#include <net/ethernet.h>
#include <machine/clock.h>
#include <machine/cpu.h>
#include <machine/cpuregs.h>
#include <machine/hwfunc.h>
#include <machine/md_var.h>
#include <machine/trap.h>
#include <machine/vmparam.h>
#include <mips/atheros/ar71xxreg.h>
#include <mips/atheros/qca953xreg.h>
#include <mips/atheros/ar71xx_cpudef.h>
#include <mips/atheros/ar71xx_setup.h>
#include <mips/atheros/ar71xx_chip.h>
#include <mips/atheros/qca953x_chip.h>
static void
qca953x_chip_detect_mem_size(void)
{
}
static void
qca953x_chip_detect_sys_frequency(void)
{
unsigned long ref_rate;
unsigned long cpu_rate;
unsigned long ddr_rate;
unsigned long ahb_rate;
uint32_t pll, out_div, ref_div, nint, frac, clk_ctrl, postdiv;
uint32_t cpu_pll, ddr_pll;
uint32_t bootstrap;
bootstrap = ATH_READ_REG(QCA953X_RESET_REG_BOOTSTRAP);
if (bootstrap & QCA953X_BOOTSTRAP_REF_CLK_40)
ref_rate = 40 * 1000 * 1000;
else
ref_rate = 25 * 1000 * 1000;
pll = ATH_READ_REG(QCA953X_PLL_CPU_CONFIG_REG);
out_div = (pll >> QCA953X_PLL_CPU_CONFIG_OUTDIV_SHIFT) &
QCA953X_PLL_CPU_CONFIG_OUTDIV_MASK;
ref_div = (pll >> QCA953X_PLL_CPU_CONFIG_REFDIV_SHIFT) &
QCA953X_PLL_CPU_CONFIG_REFDIV_MASK;
nint = (pll >> QCA953X_PLL_CPU_CONFIG_NINT_SHIFT) &
QCA953X_PLL_CPU_CONFIG_NINT_MASK;
frac = (pll >> QCA953X_PLL_CPU_CONFIG_NFRAC_SHIFT) &
QCA953X_PLL_CPU_CONFIG_NFRAC_MASK;
cpu_pll = nint * ref_rate / ref_div;
cpu_pll += frac * (ref_rate >> 6) / ref_div;
cpu_pll /= (1 << out_div);
pll = ATH_READ_REG(QCA953X_PLL_DDR_CONFIG_REG);
out_div = (pll >> QCA953X_PLL_DDR_CONFIG_OUTDIV_SHIFT) &
QCA953X_PLL_DDR_CONFIG_OUTDIV_MASK;
ref_div = (pll >> QCA953X_PLL_DDR_CONFIG_REFDIV_SHIFT) &
QCA953X_PLL_DDR_CONFIG_REFDIV_MASK;
nint = (pll >> QCA953X_PLL_DDR_CONFIG_NINT_SHIFT) &
QCA953X_PLL_DDR_CONFIG_NINT_MASK;
frac = (pll >> QCA953X_PLL_DDR_CONFIG_NFRAC_SHIFT) &
QCA953X_PLL_DDR_CONFIG_NFRAC_MASK;
ddr_pll = nint * ref_rate / ref_div;
ddr_pll += frac * (ref_rate >> 6) / (ref_div << 4);
ddr_pll /= (1 << out_div);
clk_ctrl = ATH_READ_REG(QCA953X_PLL_CLK_CTRL_REG);
postdiv = (clk_ctrl >> QCA953X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT) &
QCA953X_PLL_CLK_CTRL_CPU_POST_DIV_MASK;
if (clk_ctrl & QCA953X_PLL_CLK_CTRL_CPU_PLL_BYPASS)
cpu_rate = ref_rate;
else if (clk_ctrl & QCA953X_PLL_CLK_CTRL_CPUCLK_FROM_CPUPLL)
cpu_rate = cpu_pll / (postdiv + 1);
else
cpu_rate = ddr_pll / (postdiv + 1);
postdiv = (clk_ctrl >> QCA953X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT) &
QCA953X_PLL_CLK_CTRL_DDR_POST_DIV_MASK;
if (clk_ctrl & QCA953X_PLL_CLK_CTRL_DDR_PLL_BYPASS)
ddr_rate = ref_rate;
else if (clk_ctrl & QCA953X_PLL_CLK_CTRL_DDRCLK_FROM_DDRPLL)
ddr_rate = ddr_pll / (postdiv + 1);
else
ddr_rate = cpu_pll / (postdiv + 1);
postdiv = (clk_ctrl >> QCA953X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT) &
QCA953X_PLL_CLK_CTRL_AHB_POST_DIV_MASK;
if (clk_ctrl & QCA953X_PLL_CLK_CTRL_AHB_PLL_BYPASS)
ahb_rate = ref_rate;
else if (clk_ctrl & QCA953X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL)
ahb_rate = ddr_pll / (postdiv + 1);
else
ahb_rate = cpu_pll / (postdiv + 1);
u_ar71xx_ddr_freq = ddr_rate;
u_ar71xx_cpu_freq = cpu_rate;
u_ar71xx_ahb_freq = ahb_rate;
u_ar71xx_wdt_freq = ref_rate;
u_ar71xx_uart_freq = ref_rate;
u_ar71xx_mdio_freq = ref_rate;
u_ar71xx_refclk = ref_rate;
}
static void
qca953x_chip_device_stop(uint32_t mask)
{
uint32_t reg;
reg = ATH_READ_REG(QCA953X_RESET_REG_RESET_MODULE);
ATH_WRITE_REG(QCA953X_RESET_REG_RESET_MODULE, reg | mask);
}
static void
qca953x_chip_device_start(uint32_t mask)
{
uint32_t reg;
reg = ATH_READ_REG(QCA953X_RESET_REG_RESET_MODULE);
ATH_WRITE_REG(QCA953X_RESET_REG_RESET_MODULE, reg & ~mask);
}
static int
qca953x_chip_device_stopped(uint32_t mask)
{
uint32_t reg;
reg = ATH_READ_REG(QCA953X_RESET_REG_RESET_MODULE);
return ((reg & mask) == mask);
}
static void
qca953x_chip_set_mii_speed(uint32_t unit, uint32_t speed)
{
/* XXX TODO */
return;
}
static void
qca953x_chip_set_pll_ge(int unit, int speed, uint32_t pll)
{
switch (unit) {
case 0:
ATH_WRITE_REG(QCA953X_PLL_ETH_XMII_CONTROL_REG, pll);
break;
case 1:
/* nothing */
break;
default:
printf("%s: invalid PLL set for arge unit: %d\n",
__func__, unit);
return;
}
}
static void
qca953x_chip_ddr_flush(ar71xx_flush_ddr_id_t id)
{
switch (id) {
case AR71XX_CPU_DDR_FLUSH_GE0:
ar71xx_ddr_flush(QCA953X_DDR_REG_FLUSH_GE0);
break;
case AR71XX_CPU_DDR_FLUSH_GE1:
ar71xx_ddr_flush(QCA953X_DDR_REG_FLUSH_GE1);
break;
case AR71XX_CPU_DDR_FLUSH_USB:
ar71xx_ddr_flush(QCA953X_DDR_REG_FLUSH_USB);
break;
case AR71XX_CPU_DDR_FLUSH_PCIE:
ar71xx_ddr_flush(QCA953X_DDR_REG_FLUSH_PCIE);
break;
case AR71XX_CPU_DDR_FLUSH_WMAC:
ar71xx_ddr_flush(QCA953X_DDR_REG_FLUSH_WMAC);
break;
default:
printf("%s: invalid flush (%d)\n", __func__, id);
}
}
static uint32_t
qca953x_chip_get_eth_pll(unsigned int mac, int speed)
{
uint32_t pll;
switch (speed) {
case 10:
pll = QCA953X_PLL_VAL_10;
break;
case 100:
pll = QCA953X_PLL_VAL_100;
break;
case 1000:
pll = QCA953X_PLL_VAL_1000;
break;
default:
printf("%s%d: invalid speed %d\n", __func__, mac, speed);
pll = 0;
}
return (pll);
}
static void
qca953x_chip_reset_ethernet_switch(void)
{
}
static void
qca953x_configure_gmac(uint32_t gmac_cfg)
{
uint32_t reg;
reg = ATH_READ_REG(QCA953X_GMAC_REG_ETH_CFG);
printf("%s: ETH_CFG=0x%08x\n", __func__, reg);
reg &= ~(QCA953X_ETH_CFG_SW_ONLY_MODE |
QCA953X_ETH_CFG_SW_PHY_SWAP |
QCA953X_ETH_CFG_SW_APB_ACCESS |
QCA953X_ETH_CFG_SW_ACC_MSB_FIRST);
reg |= gmac_cfg;
ATH_WRITE_REG(QCA953X_GMAC_REG_ETH_CFG, reg);
}
static void
qca953x_chip_init_usb_peripheral(void)
{
uint32_t bootstrap;
bootstrap = ATH_READ_REG(QCA953X_RESET_REG_BOOTSTRAP);
ar71xx_device_stop(QCA953X_RESET_USBSUS_OVERRIDE);
DELAY(1000);
ar71xx_device_start(QCA953X_RESET_USB_PHY);
DELAY(1000);
ar71xx_device_start(QCA953X_RESET_USB_PHY_ANALOG);
DELAY(1000);
ar71xx_device_start(QCA953X_RESET_USB_HOST);
DELAY(1000);
}
static void
qca953x_chip_set_mii_if(uint32_t unit, uint32_t mii_mode)
{
/*
* XXX !
*
* Nothing to see here; although gmac0 can have its
* MII configuration changed, the register values
* are slightly different.
*/
}
/*
* XXX TODO: fetch default MII divider configuration
*/
static void
qca953x_chip_reset_wmac(void)
{
/* XXX TODO */
}
static void
qca953x_chip_init_gmac(void)
{
long gmac_cfg;
if (resource_long_value("qca953x_gmac", 0, "gmac_cfg",
&gmac_cfg) == 0) {
printf("%s: gmac_cfg=0x%08lx\n",
__func__,
(long) gmac_cfg);
qca953x_configure_gmac((uint32_t) gmac_cfg);
}
}
/*
* Reset the NAND Flash Controller.
*
* + active=1 means "make it active".
* + active=0 means "make it inactive".
*/
static void
qca953x_chip_reset_nfc(int active)
{
}
/*
* Configure the GPIO output mux setup.
*
* The QCA953x has an output mux which allowed
* certain functions to be configured on any pin.
* Specifically, the switch PHY link LEDs and
* WMAC external RX LNA switches are not limited to
* a specific GPIO pin.
*/
static void
qca953x_chip_gpio_output_configure(int gpio, uint8_t func)
{
uint32_t reg, s;
uint32_t t;
if (gpio > QCA953X_GPIO_COUNT)
return;
reg = QCA953X_GPIO_REG_OUT_FUNC0 + rounddown(gpio, 4);
s = 8 * (gpio % 4);
/* read-modify-write */
t = ATH_READ_REG(AR71XX_GPIO_BASE + reg);
t &= ~(0xff << s);
t |= func << s;
ATH_WRITE_REG(AR71XX_GPIO_BASE + reg, t);
/* flush write */
ATH_READ_REG(AR71XX_GPIO_BASE + reg);
}
struct ar71xx_cpu_def qca953x_chip_def = {
&qca953x_chip_detect_mem_size,
&qca953x_chip_detect_sys_frequency,
&qca953x_chip_device_stop,
&qca953x_chip_device_start,
&qca953x_chip_device_stopped,
&qca953x_chip_set_pll_ge,
&qca953x_chip_set_mii_speed,
&qca953x_chip_set_mii_if,
&qca953x_chip_get_eth_pll,
&qca953x_chip_ddr_flush,
&qca953x_chip_init_usb_peripheral,
&qca953x_chip_reset_ethernet_switch,
&qca953x_chip_reset_wmac,
&qca953x_chip_init_gmac,
&qca953x_chip_reset_nfc,
&qca953x_chip_gpio_output_configure,
};

View File

@ -1,34 +0,0 @@
/*-
* Copyright (c) 2015 Adrian Chadd <adrian@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* $FreeBSD$ */
#ifndef __QCA953X_CHIP_H__
#define __QCA953X_CHIP_H__
extern struct ar71xx_cpu_def qca953x_chip_def;
#endif

View File

@ -1,195 +0,0 @@
/*-
* Copyright (c) 2015 Adrian Chadd <adrian@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef __QCA953XREG_H__
#define __QCA953XREG_H__
#define BIT(x) (1 << (x))
/* Revision ID information */
#define REV_ID_MAJOR_QCA9533 0x0140
#define REV_ID_MAJOR_QCA9533_V2 0x0160
#define QCA953X_REV_ID_REVISION_MASK 0xf
/* Big enough to cover APB and SPI, and most peripherals */
/*
* it needs to cover SPI because right now the if_ath_ahb
* code uses rman to map in the SPI address into memory
* to read data instead of us squirreling it away at early
* boot-time and using the firmware interface.
*
* if_ath_ahb.c should use the same firmware interface
* that if_ath_pci.c uses.
*/
#define QCA953X_GMAC_BASE (AR71XX_APB_BASE + 0x00070000)
#define QCA953X_GMAC_SIZE 0x14
#define QCA953X_WMAC_BASE (AR71XX_APB_BASE + 0x00100000)
#define QCA953X_WMAC_SIZE 0x20000
#define QCA953X_EHCI_BASE 0x1b000000
#define QCA953X_EHCI_SIZE 0x200
#define QCA953X_SRIF_BASE (AR71XX_APB_BASE + 0x00116000)
#define QCA953X_SRIF_SIZE 0x1000
#define QCA953X_PCI_CFG_BASE0 0x14000000
#define QCA953X_PCI_CTRL_BASE0 (AR71XX_APB_BASE + 0x000f0000)
#define QCA953X_PCI_CRP_BASE0 (AR71XX_APB_BASE + 0x000c0000)
#define QCA953X_PCI_MEM_BASE0 0x10000000
#define QCA953X_PCI_MEM_SIZE 0x02000000
/* PLL Block */
#define QCA953X_PLL_CPU_CONFIG_REG (AR71XX_PLL_CPU_BASE + 0x00)
#define QCA953X_PLL_DDR_CONFIG_REG (AR71XX_PLL_CPU_BASE + 0x04)
#define QCA953X_PLL_CLK_CTRL_REG (AR71XX_PLL_CPU_BASE + 0x08)
#define QCA953X_PLL_ETH_XMII_CONTROL_REG (AR71XX_PLL_CPU_BASE + 0x2c)
#define QCA953X_PLL_ETH_SGMII_CONTROL_REG (AR71XX_PLL_CPU_BASE + 0x48)
#define QCA953X_PLL_CPU_CONFIG_NFRAC_SHIFT 0
#define QCA953X_PLL_CPU_CONFIG_NFRAC_MASK 0x3f
#define QCA953X_PLL_CPU_CONFIG_NINT_SHIFT 6
#define QCA953X_PLL_CPU_CONFIG_NINT_MASK 0x3f
#define QCA953X_PLL_CPU_CONFIG_REFDIV_SHIFT 12
#define QCA953X_PLL_CPU_CONFIG_REFDIV_MASK 0x1f
#define QCA953X_PLL_CPU_CONFIG_OUTDIV_SHIFT 19
#define QCA953X_PLL_CPU_CONFIG_OUTDIV_MASK 0x3
#define QCA953X_PLL_DDR_CONFIG_NFRAC_SHIFT 0
#define QCA953X_PLL_DDR_CONFIG_NFRAC_MASK 0x3ff
#define QCA953X_PLL_DDR_CONFIG_NINT_SHIFT 10
#define QCA953X_PLL_DDR_CONFIG_NINT_MASK 0x3f
#define QCA953X_PLL_DDR_CONFIG_REFDIV_SHIFT 16
#define QCA953X_PLL_DDR_CONFIG_REFDIV_MASK 0x1f
#define QCA953X_PLL_DDR_CONFIG_OUTDIV_SHIFT 23
#define QCA953X_PLL_DDR_CONFIG_OUTDIV_MASK 0x7
#define QCA953X_PLL_CLK_CTRL_CPU_PLL_BYPASS BIT(2)
#define QCA953X_PLL_CLK_CTRL_DDR_PLL_BYPASS BIT(3)
#define QCA953X_PLL_CLK_CTRL_AHB_PLL_BYPASS BIT(4)
#define QCA953X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT 5
#define QCA953X_PLL_CLK_CTRL_CPU_POST_DIV_MASK 0x1f
#define QCA953X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT 10
#define QCA953X_PLL_CLK_CTRL_DDR_POST_DIV_MASK 0x1f
#define QCA953X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT 15
#define QCA953X_PLL_CLK_CTRL_AHB_POST_DIV_MASK 0x1f
#define QCA953X_PLL_CLK_CTRL_CPUCLK_FROM_CPUPLL BIT(20)
#define QCA953X_PLL_CLK_CTRL_DDRCLK_FROM_DDRPLL BIT(21)
#define QCA953X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL BIT(24)
#define QCA953X_PLL_VAL_1000 0x16000000
#define QCA953X_PLL_VAL_100 0x00000101
#define QCA953X_PLL_VAL_10 0x00001616
/* Reset block */
#define QCA953X_RESET_REG_RESET_MODULE (AR71XX_RST_BLOCK_BASE + 0x1c)
#define QCA953X_RESET_USB_EXT_PWR BIT(29)
#define QCA953X_RESET_EXTERNAL BIT(28)
#define QCA953X_RESET_RTC BIT(27)
#define QCA953X_RESET_FULL_CHIP BIT(24)
#define QCA953X_RESET_GE1_MDIO BIT(23)
#define QCA953X_RESET_GE0_MDIO BIT(22)
#define QCA953X_RESET_CPU_NMI BIT(21)
#define QCA953X_RESET_CPU_COLD BIT(20)
#define QCA953X_RESET_DDR BIT(16)
#define QCA953X_RESET_USB_PHY_PLL_PWD_EXT BIT(15)
#define QCA953X_RESET_GE1_MAC BIT(13)
#define QCA953X_RESET_ETH_SWITCH_ANALOG BIT(12)
#define QCA953X_RESET_USB_PHY_ANALOG BIT(11)
#define QCA953X_RESET_GE0_MAC BIT(9)
#define QCA953X_RESET_ETH_SWITCH BIT(8)
#define QCA953X_RESET_PCIE_PHY BIT(7)
#define QCA953X_RESET_PCIE BIT(6)
#define QCA953X_RESET_USB_HOST BIT(5)
#define QCA953X_RESET_USB_PHY BIT(4)
#define QCA953X_RESET_USBSUS_OVERRIDE BIT(3)
#define QCA953X_RESET_REG_BOOTSTRAP (AR71XX_RST_BLOCK_BASE + 0xb0)
#define QCA953X_BOOTSTRAP_SW_OPTION2 BIT(12)
#define QCA953X_BOOTSTRAP_SW_OPTION1 BIT(11)
#define QCA953X_BOOTSTRAP_EJTAG_MODE BIT(5)
#define QCA953X_BOOTSTRAP_REF_CLK_40 BIT(4)
#define QCA953X_BOOTSTRAP_SDRAM_DISABLED BIT(1)
#define QCA953X_BOOTSTRAP_DDR1 BIT(0)
#define QCA953X_RESET_REG_EXT_INT_STATUS (AR71XX_RST_BLOCK_BASE + 0xac)
#define QCA953X_DDR_REG_FLUSH_GE0 (AR71XX_APB_BASE + 0x9c)
#define QCA953X_DDR_REG_FLUSH_GE1 (AR71XX_APB_BASE + 0xa0)
#define QCA953X_DDR_REG_FLUSH_USB (AR71XX_APB_BASE + 0xa4)
#define QCA953X_DDR_REG_FLUSH_PCIE (AR71XX_APB_BASE + 0xa8)
#define QCA953X_DDR_REG_FLUSH_WMAC (AR71XX_APB_BASE + 0xac)
/* GPIO block */
#define QCA953X_GPIO_REG_OUT_FUNC0 0x2c
#define QCA953X_GPIO_REG_OUT_FUNC1 0x30
#define QCA953X_GPIO_REG_OUT_FUNC2 0x34
#define QCA953X_GPIO_REG_OUT_FUNC3 0x38
#define QCA953X_GPIO_REG_OUT_FUNC4 0x3c
#define QCA953X_GPIO_REG_IN_ENABLE0 0x44
#define QCA953X_GPIO_REG_FUNC 0x6c
#define QCA953X_GPIO_OUT_MUX_SPI_CS1 10
#define QCA953X_GPIO_OUT_MUX_SPI_CS2 11
#define QCA953X_GPIO_OUT_MUX_SPI_CS0 9
#define QCA953X_GPIO_OUT_MUX_SPI_CLK 8
#define QCA953X_GPIO_OUT_MUX_SPI_MOSI 12
#define QCA953X_GPIO_OUT_MUX_LED_LINK1 41
#define QCA953X_GPIO_OUT_MUX_LED_LINK2 42
#define QCA953X_GPIO_OUT_MUX_LED_LINK3 43
#define QCA953X_GPIO_OUT_MUX_LED_LINK4 44
#define QCA953X_GPIO_OUT_MUX_LED_LINK5 45
#define QCA953X_GPIO_COUNT 18
/* GMAC block */
#define QCA953X_GMAC_REG_ETH_CFG (QCA953X_GMAC_BASE + 0x00)
#define QCA953X_ETH_CFG_SW_ONLY_MODE BIT(6)
#define QCA953X_ETH_CFG_SW_PHY_SWAP BIT(7)
#define QCA953X_ETH_CFG_SW_APB_ACCESS BIT(9)
#define QCA953X_ETH_CFG_SW_ACC_MSB_FIRST BIT(13)
/* SRIF block */
#define QCA953X_SRIF_CPU_DPLL1_REG 0x1c0
#define QCA953X_SRIF_CPU_DPLL2_REG 0x1c4
#define QCA953X_SRIF_CPU_DPLL3_REG 0x1c8
#define QCA953X_SRIF_DDR_DPLL1_REG 0x240
#define QCA953X_SRIF_DDR_DPLL2_REG 0x244
#define QCA953X_SRIF_DDR_DPLL3_REG 0x248
#define QCA953X_SRIF_DPLL1_REFDIV_SHIFT 27
#define QCA953X_SRIF_DPLL1_REFDIV_MASK 0x1f
#define QCA953X_SRIF_DPLL1_NINT_SHIFT 18
#define QCA953X_SRIF_DPLL1_NINT_MASK 0x1ff
#define QCA953X_SRIF_DPLL1_NFRAC_MASK 0x0003ffff
#define QCA953X_SRIF_DPLL2_LOCAL_PLL BIT(30)
#define QCA953X_SRIF_DPLL2_OUTDIV_SHIFT 13
#define QCA953X_SRIF_DPLL2_OUTDIV_MASK 0x7
#endif /* __QCA953XREG_H__ */

View File

@ -1,402 +0,0 @@
/*-
* Copyright (c) 2015 Adrian Chadd <adrian@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_ddb.h"
#include <sys/param.h>
#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/cons.h>
#include <sys/kdb.h>
#include <sys/reboot.h>
#include <vm/vm.h>
#include <vm/vm_page.h>
#include <net/ethernet.h>
#include <machine/clock.h>
#include <machine/cpu.h>
#include <machine/cpuregs.h>
#include <machine/hwfunc.h>
#include <machine/md_var.h>
#include <machine/trap.h>
#include <machine/vmparam.h>
#include <mips/atheros/ar71xxreg.h>
//#include <mips/atheros/ar934xreg.h>
#include <mips/atheros/qca955xreg.h>
#include <mips/atheros/ar71xx_cpudef.h>
#include <mips/atheros/ar71xx_setup.h>
#include <mips/atheros/ar71xx_chip.h>
#include <mips/atheros/qca955x_chip.h>
static void
qca955x_chip_detect_mem_size(void)
{
}
static void
qca955x_chip_detect_sys_frequency(void)
{
unsigned long ref_rate;
unsigned long cpu_rate;
unsigned long ddr_rate;
unsigned long ahb_rate;
uint32_t pll, out_div, ref_div, nint, frac, clk_ctrl, postdiv;
uint32_t cpu_pll, ddr_pll;
uint32_t bootstrap;
bootstrap = ATH_READ_REG(QCA955X_RESET_REG_BOOTSTRAP);
if (bootstrap & QCA955X_BOOTSTRAP_REF_CLK_40)
ref_rate = 40 * 1000 * 1000;
else
ref_rate = 25 * 1000 * 1000;
pll = ATH_READ_REG(QCA955X_PLL_CPU_CONFIG_REG);
out_div = (pll >> QCA955X_PLL_CPU_CONFIG_OUTDIV_SHIFT) &
QCA955X_PLL_CPU_CONFIG_OUTDIV_MASK;
ref_div = (pll >> QCA955X_PLL_CPU_CONFIG_REFDIV_SHIFT) &
QCA955X_PLL_CPU_CONFIG_REFDIV_MASK;
nint = (pll >> QCA955X_PLL_CPU_CONFIG_NINT_SHIFT) &
QCA955X_PLL_CPU_CONFIG_NINT_MASK;
frac = (pll >> QCA955X_PLL_CPU_CONFIG_NFRAC_SHIFT) &
QCA955X_PLL_CPU_CONFIG_NFRAC_MASK;
cpu_pll = nint * ref_rate / ref_div;
cpu_pll += frac * ref_rate / (ref_div * (1 << 6));
cpu_pll /= (1 << out_div);
pll = ATH_READ_REG(QCA955X_PLL_DDR_CONFIG_REG);
out_div = (pll >> QCA955X_PLL_DDR_CONFIG_OUTDIV_SHIFT) &
QCA955X_PLL_DDR_CONFIG_OUTDIV_MASK;
ref_div = (pll >> QCA955X_PLL_DDR_CONFIG_REFDIV_SHIFT) &
QCA955X_PLL_DDR_CONFIG_REFDIV_MASK;
nint = (pll >> QCA955X_PLL_DDR_CONFIG_NINT_SHIFT) &
QCA955X_PLL_DDR_CONFIG_NINT_MASK;
frac = (pll >> QCA955X_PLL_DDR_CONFIG_NFRAC_SHIFT) &
QCA955X_PLL_DDR_CONFIG_NFRAC_MASK;
ddr_pll = nint * ref_rate / ref_div;
ddr_pll += frac * ref_rate / (ref_div * (1 << 10));
ddr_pll /= (1 << out_div);
clk_ctrl = ATH_READ_REG(QCA955X_PLL_CLK_CTRL_REG);
postdiv = (clk_ctrl >> QCA955X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT) &
QCA955X_PLL_CLK_CTRL_CPU_POST_DIV_MASK;
if (clk_ctrl & QCA955X_PLL_CLK_CTRL_CPU_PLL_BYPASS)
cpu_rate = ref_rate;
else if (clk_ctrl & QCA955X_PLL_CLK_CTRL_CPUCLK_FROM_CPUPLL)
cpu_rate = ddr_pll / (postdiv + 1);
else
cpu_rate = cpu_pll / (postdiv + 1);
postdiv = (clk_ctrl >> QCA955X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT) &
QCA955X_PLL_CLK_CTRL_DDR_POST_DIV_MASK;
if (clk_ctrl & QCA955X_PLL_CLK_CTRL_DDR_PLL_BYPASS)
ddr_rate = ref_rate;
else if (clk_ctrl & QCA955X_PLL_CLK_CTRL_DDRCLK_FROM_DDRPLL)
ddr_rate = cpu_pll / (postdiv + 1);
else
ddr_rate = ddr_pll / (postdiv + 1);
postdiv = (clk_ctrl >> QCA955X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT) &
QCA955X_PLL_CLK_CTRL_AHB_POST_DIV_MASK;
if (clk_ctrl & QCA955X_PLL_CLK_CTRL_AHB_PLL_BYPASS)
ahb_rate = ref_rate;
else if (clk_ctrl & QCA955X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL)
ahb_rate = ddr_pll / (postdiv + 1);
else
ahb_rate = cpu_pll / (postdiv + 1);
u_ar71xx_ddr_freq = ddr_rate;
u_ar71xx_cpu_freq = cpu_rate;
u_ar71xx_ahb_freq = ahb_rate;
u_ar71xx_wdt_freq = ref_rate;
u_ar71xx_uart_freq = ref_rate;
u_ar71xx_mdio_freq = ref_rate;
u_ar71xx_refclk = ref_rate;
}
static void
qca955x_chip_device_stop(uint32_t mask)
{
uint32_t reg;
reg = ATH_READ_REG(QCA955X_RESET_REG_RESET_MODULE);
ATH_WRITE_REG(QCA955X_RESET_REG_RESET_MODULE, reg | mask);
}
static void
qca955x_chip_device_start(uint32_t mask)
{
uint32_t reg;
reg = ATH_READ_REG(QCA955X_RESET_REG_RESET_MODULE);
ATH_WRITE_REG(QCA955X_RESET_REG_RESET_MODULE, reg & ~mask);
}
static int
qca955x_chip_device_stopped(uint32_t mask)
{
uint32_t reg;
reg = ATH_READ_REG(QCA955X_RESET_REG_RESET_MODULE);
return ((reg & mask) == mask);
}
static void
qca955x_chip_set_mii_speed(uint32_t unit, uint32_t speed)
{
/* XXX TODO */
return;
}
static void
qca955x_chip_set_pll_ge(int unit, int speed, uint32_t pll)
{
switch (unit) {
case 0:
ATH_WRITE_REG(QCA955X_PLL_ETH_XMII_CONTROL_REG, pll);
break;
case 1:
ATH_WRITE_REG(QCA955X_PLL_ETH_SGMII_CONTROL_REG, pll);
break;
default:
printf("%s: invalid PLL set for arge unit: %d\n",
__func__, unit);
return;
}
}
static void
qca955x_chip_ddr_flush(ar71xx_flush_ddr_id_t id)
{
switch (id) {
case AR71XX_CPU_DDR_FLUSH_GE0:
ar71xx_ddr_flush(QCA955X_DDR_REG_FLUSH_GE0);
break;
case AR71XX_CPU_DDR_FLUSH_GE1:
ar71xx_ddr_flush(QCA955X_DDR_REG_FLUSH_GE1);
break;
case AR71XX_CPU_DDR_FLUSH_USB:
ar71xx_ddr_flush(QCA955X_DDR_REG_FLUSH_USB);
break;
case AR71XX_CPU_DDR_FLUSH_PCIE:
ar71xx_ddr_flush(QCA955X_DDR_REG_FLUSH_PCIE);
break;
case AR71XX_CPU_DDR_FLUSH_WMAC:
ar71xx_ddr_flush(QCA955X_DDR_REG_FLUSH_WMAC);
break;
case AR71XX_CPU_DDR_FLUSH_PCIE_EP:
ar71xx_ddr_flush(QCA955X_DDR_REG_FLUSH_SRC1);
break;
case AR71XX_CPU_DDR_FLUSH_CHECKSUM:
ar71xx_ddr_flush(QCA955X_DDR_REG_FLUSH_SRC2);
break;
default:
printf("%s: invalid flush (%d)\n", __func__, id);
}
}
static uint32_t
qca955x_chip_get_eth_pll(unsigned int mac, int speed)
{
uint32_t pll;
switch (speed) {
case 10:
pll = QCA955X_PLL_VAL_10;
break;
case 100:
pll = QCA955X_PLL_VAL_100;
break;
case 1000:
pll = QCA955X_PLL_VAL_1000;
break;
default:
printf("%s%d: invalid speed %d\n", __func__, mac, speed);
pll = 0;
}
return (pll);
}
static void
qca955x_chip_reset_ethernet_switch(void)
{
#if 0
ar71xx_device_stop(AR934X_RESET_ETH_SWITCH);
DELAY(100);
ar71xx_device_start(AR934X_RESET_ETH_SWITCH);
DELAY(100);
#endif
}
static void
qca955x_configure_gmac(uint32_t gmac_cfg)
{
uint32_t reg;
reg = ATH_READ_REG(QCA955X_GMAC_REG_ETH_CFG);
printf("%s: ETH_CFG=0x%08x\n", __func__, reg);
reg &= ~(QCA955X_ETH_CFG_RGMII_EN | QCA955X_ETH_CFG_GE0_SGMII);
reg |= gmac_cfg;
ATH_WRITE_REG(QCA955X_GMAC_REG_ETH_CFG, reg);
}
static void
qca955x_chip_init_usb_peripheral(void)
{
}
static void
qca955x_chip_set_mii_if(uint32_t unit, uint32_t mii_mode)
{
/*
* XXX !
*
* Nothing to see here; although gmac0 can have its
* MII configuration changed, the register values
* are slightly different.
*/
}
/*
* XXX TODO: fetch default MII divider configuration
*/
static void
qca955x_chip_reset_wmac(void)
{
/* XXX TODO */
}
static void
qca955x_chip_init_gmac(void)
{
long gmac_cfg;
if (resource_long_value("qca955x_gmac", 0, "gmac_cfg",
&gmac_cfg) == 0) {
printf("%s: gmac_cfg=0x%08lx\n",
__func__,
(long) gmac_cfg);
qca955x_configure_gmac((uint32_t) gmac_cfg);
}
}
/*
* Reset the NAND Flash Controller.
*
* + active=1 means "make it active".
* + active=0 means "make it inactive".
*/
static void
qca955x_chip_reset_nfc(int active)
{
#if 0
if (active) {
ar71xx_device_start(AR934X_RESET_NANDF);
DELAY(100);
ar71xx_device_start(AR934X_RESET_ETH_SWITCH_ANALOG);
DELAY(250);
} else {
ar71xx_device_stop(AR934X_RESET_ETH_SWITCH_ANALOG);
DELAY(250);
ar71xx_device_stop(AR934X_RESET_NANDF);
DELAY(100);
}
#endif
}
/*
* Configure the GPIO output mux setup.
*
* The QCA955x has an output mux which allowed
* certain functions to be configured on any pin.
* Specifically, the switch PHY link LEDs and
* WMAC external RX LNA switches are not limited to
* a specific GPIO pin.
*/
static void
qca955x_chip_gpio_output_configure(int gpio, uint8_t func)
{
uint32_t reg, s;
uint32_t t;
if (gpio > QCA955X_GPIO_COUNT)
return;
reg = QCA955X_GPIO_REG_OUT_FUNC0 + rounddown(gpio, 4);
s = 8 * (gpio % 4);
/* read-modify-write */
t = ATH_READ_REG(AR71XX_GPIO_BASE + reg);
t &= ~(0xff << s);
t |= func << s;
ATH_WRITE_REG(AR71XX_GPIO_BASE + reg, t);
/* flush write */
ATH_READ_REG(AR71XX_GPIO_BASE + reg);
}
struct ar71xx_cpu_def qca955x_chip_def = {
&qca955x_chip_detect_mem_size,
&qca955x_chip_detect_sys_frequency,
&qca955x_chip_device_stop,
&qca955x_chip_device_start,
&qca955x_chip_device_stopped,
&qca955x_chip_set_pll_ge,
&qca955x_chip_set_mii_speed,
&qca955x_chip_set_mii_if,
&qca955x_chip_get_eth_pll,
&qca955x_chip_ddr_flush,
&qca955x_chip_init_usb_peripheral,
&qca955x_chip_reset_ethernet_switch,
&qca955x_chip_reset_wmac,
&qca955x_chip_init_gmac,
&qca955x_chip_reset_nfc,
&qca955x_chip_gpio_output_configure,
};

View File

@ -1,34 +0,0 @@
/*-
* Copyright (c) 2015 Adrian Chadd <adrian@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* $FreeBSD$ */
#ifndef __QCA955X_CHIP_H__
#define __QCA955X_CHIP_H__
extern struct ar71xx_cpu_def qca955x_chip_def;
#endif

View File

@ -1,606 +0,0 @@
/*-
* Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@FreeBSD.org>
* Copyright (c) 2011, Luiz Otavio O Souza.
* Copyright (c) 2015, Adrian Chadd <adrian@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 unmodified, this list of conditions, and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_ar71xx.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/interrupt.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/rman.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <vm/vm_extern.h>
#include <machine/bus.h>
#include <machine/cpu.h>
#include <machine/intr_machdep.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcib_private.h>
#include "pcib_if.h"
#include <mips/atheros/ar71xxreg.h> /* XXX aim to eliminate this! */
#include <mips/atheros/qca955xreg.h>
#include <mips/atheros/ar71xx_setup.h>
#include <mips/atheros/ar71xx_pci_bus_space.h>
#include <mips/atheros/ar71xx_cpudef.h>
#undef AR724X_PCI_DEBUG
//#define AR724X_PCI_DEBUG
#ifdef AR724X_PCI_DEBUG
#define dprintf printf
#else
#define dprintf(x, arg...)
#endif
/*
* This is a PCI controller for the QCA955x and later SoCs.
* It needs to be aware of >1 PCIe host endpoints.
*
* XXX TODO; it may be nice to merge this with ar724x_pci.c;
* they're very similar.
*/
struct ar71xx_pci_irq {
struct ar71xx_pci_softc *sc;
int irq;
};
struct ar71xx_pci_softc {
device_t sc_dev;
int sc_busno;
struct rman sc_mem_rman;
struct rman sc_irq_rman;
uint32_t sc_pci_reg_base; /* XXX until bus stuff is done */
uint32_t sc_pci_crp_base; /* XXX until bus stuff is done */
uint32_t sc_pci_ctrl_base; /* XXX until bus stuff is done */
uint32_t sc_pci_mem_base; /* XXX until bus stuff is done */
uint32_t sc_pci_membase_limit;
struct intr_event *sc_eventstab[AR71XX_PCI_NIRQS];
mips_intrcnt_t sc_intr_counter[AR71XX_PCI_NIRQS];
struct ar71xx_pci_irq sc_pci_irq[AR71XX_PCI_NIRQS];
struct resource *sc_irq;
void *sc_ih;
};
static int qca955x_pci_setup_intr(device_t, device_t, struct resource *, int,
driver_filter_t *, driver_intr_t *, void *, void **);
static int qca955x_pci_teardown_intr(device_t, device_t, struct resource *,
void *);
static int qca955x_pci_intr(void *);
static void
qca955x_pci_write(uint32_t reg, uint32_t offset, uint32_t data, int bytes)
{
uint32_t val, mask, shift;
/* Register access is 32-bit aligned */
shift = (offset & 3) * 8;
if (bytes % 4)
mask = (1 << (bytes * 8)) - 1;
else
mask = 0xffffffff;
val = ATH_READ_REG(reg + (offset & ~3));
val &= ~(mask << shift);
val |= ((data & mask) << shift);
ATH_WRITE_REG(reg + (offset & ~3), val);
dprintf("%s: %#x/%#x addr=%#x, data=%#x(%#x), bytes=%d\n", __func__,
reg, reg + (offset & ~3), offset, data, val, bytes);
}
static uint32_t
qca955x_pci_read_config(device_t dev, u_int bus, u_int slot, u_int func,
u_int reg, int bytes)
{
struct ar71xx_pci_softc *sc = device_get_softc(dev);
uint32_t data, shift, mask;
/* Register access is 32-bit aligned */
shift = (reg & 3) * 8;
/* Create a mask based on the width, post-shift */
if (bytes == 2)
mask = 0xffff;
else if (bytes == 1)
mask = 0xff;
else
mask = 0xffffffff;
dprintf("%s: tag (%x, %x, %x) reg %d(%d)\n", __func__, bus, slot,
func, reg, bytes);
if ((bus == 0) && (slot == 0) && (func == 0))
data = ATH_READ_REG(sc->sc_pci_reg_base + (reg & ~3));
else
data = -1;
/* Get request bytes from 32-bit word */
data = (data >> shift) & mask;
dprintf("%s: read 0x%x\n", __func__, data);
return (data);
}
static void
qca955x_pci_write_config(device_t dev, u_int bus, u_int slot, u_int func,
u_int reg, uint32_t data, int bytes)
{
struct ar71xx_pci_softc *sc = device_get_softc(dev);
dprintf("%s: tag (%x, %x, %x) reg %d(%d): %x\n", __func__, bus, slot,
func, reg, bytes, data);
if ((bus != 0) || (slot != 0) || (func != 0))
return;
qca955x_pci_write(sc->sc_pci_reg_base, reg, data, bytes);
}
static void
qca955x_pci_mask_irq(void *source)
{
uint32_t reg;
struct ar71xx_pci_irq *pirq = source;
struct ar71xx_pci_softc *sc = pirq->sc;
/* XXX - Only one interrupt ? Only one device ? */
if (pirq->irq != AR71XX_PCI_IRQ_START)
return;
/* Update the interrupt mask reg */
reg = ATH_READ_REG(sc->sc_pci_ctrl_base + QCA955X_PCI_INTR_MASK);
ATH_WRITE_REG(sc->sc_pci_ctrl_base + QCA955X_PCI_INTR_MASK,
reg & ~QCA955X_PCI_INTR_DEV0);
/* Clear any pending interrupt */
reg = ATH_READ_REG(sc->sc_pci_ctrl_base + QCA955X_PCI_INTR_STATUS);
ATH_WRITE_REG(sc->sc_pci_ctrl_base + QCA955X_PCI_INTR_STATUS,
reg | QCA955X_PCI_INTR_DEV0);
}
static void
qca955x_pci_unmask_irq(void *source)
{
uint32_t reg;
struct ar71xx_pci_irq *pirq = source;
struct ar71xx_pci_softc *sc = pirq->sc;
if (pirq->irq != AR71XX_PCI_IRQ_START)
return;
/* Update the interrupt mask reg */
reg = ATH_READ_REG(sc->sc_pci_ctrl_base + QCA955X_PCI_INTR_MASK);
ATH_WRITE_REG(sc->sc_pci_ctrl_base + QCA955X_PCI_INTR_MASK,
reg | QCA955X_PCI_INTR_DEV0);
}
static int
qca955x_pci_setup(device_t dev)
{
struct ar71xx_pci_softc *sc = device_get_softc(dev);
uint32_t reg;
/* setup COMMAND register */
reg = PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN | PCIM_CMD_SERRESPEN |
PCIM_CMD_BACKTOBACK | PCIM_CMD_PERRESPEN | PCIM_CMD_MWRICEN;
qca955x_pci_write(sc->sc_pci_crp_base, PCIR_COMMAND, reg, 2);
/* These are the memory/prefetch base/limit parameters */
qca955x_pci_write(sc->sc_pci_crp_base, 0x20, sc->sc_pci_membase_limit, 4);
qca955x_pci_write(sc->sc_pci_crp_base, 0x24, sc->sc_pci_membase_limit, 4);
reg = ATH_READ_REG(sc->sc_pci_ctrl_base + QCA955X_PCI_RESET);
if (reg != 0x7) {
DELAY(100000);
ATH_WRITE_REG(sc->sc_pci_ctrl_base + QCA955X_PCI_RESET, 0);
ATH_READ_REG(sc->sc_pci_ctrl_base + QCA955X_PCI_RESET);
DELAY(100);
ATH_WRITE_REG(sc->sc_pci_ctrl_base + QCA955X_PCI_RESET, 4);
ATH_READ_REG(sc->sc_pci_ctrl_base + QCA955X_PCI_RESET);
DELAY(100000);
}
ATH_WRITE_REG(sc->sc_pci_ctrl_base + QCA955X_PCI_APP, 0x1ffc1);
/* Flush write */
(void) ATH_READ_REG(sc->sc_pci_ctrl_base + QCA955X_PCI_APP);
DELAY(1000);
reg = ATH_READ_REG(sc->sc_pci_ctrl_base + QCA955X_PCI_RESET);
if ((reg & QCA955X_PCI_RESET_LINK_UP) == 0) {
device_printf(dev, "no PCIe controller found\n");
return (ENXIO);
}
return (0);
}
static int
qca955x_pci_probe(device_t dev)
{
return (BUS_PROBE_NOWILDCARD);
}
static int
qca955x_pci_attach(device_t dev)
{
struct ar71xx_pci_softc *sc = device_get_softc(dev);
int unit = device_get_unit(dev);
int rid = 0;
/* Dirty; maybe these could all just be hints */
if (unit == 0) {
sc->sc_pci_reg_base = QCA955X_PCI_CFG_BASE0;
sc->sc_pci_crp_base = QCA955X_PCI_CRP_BASE0;
sc->sc_pci_ctrl_base = QCA955X_PCI_CTRL_BASE0;
sc->sc_pci_mem_base = QCA955X_PCI_MEM_BASE0;
/* XXX verify */
sc->sc_pci_membase_limit = 0x11f01000;
} else if (unit == 1) {
sc->sc_pci_reg_base = QCA955X_PCI_CFG_BASE1;
sc->sc_pci_crp_base = QCA955X_PCI_CRP_BASE1;
sc->sc_pci_ctrl_base = QCA955X_PCI_CTRL_BASE1;
sc->sc_pci_mem_base = QCA955X_PCI_MEM_BASE1;
/* XXX verify */
sc->sc_pci_membase_limit = 0x12f01200;
} else {
device_printf(dev, "%s: invalid unit (%d)\n", __func__, unit);
return (ENXIO);
}
sc->sc_mem_rman.rm_type = RMAN_ARRAY;
sc->sc_mem_rman.rm_descr = "qca955x PCI memory window";
if (rman_init(&sc->sc_mem_rman) != 0 ||
rman_manage_region(&sc->sc_mem_rman,
sc->sc_pci_mem_base,
sc->sc_pci_mem_base + QCA955X_PCI_MEM_SIZE - 1) != 0) {
panic("qca955x_pci_attach: failed to set up I/O rman");
}
sc->sc_irq_rman.rm_type = RMAN_ARRAY;
sc->sc_irq_rman.rm_descr = "qca955x PCI IRQs";
if (rman_init(&sc->sc_irq_rman) != 0 ||
rman_manage_region(&sc->sc_irq_rman, AR71XX_PCI_IRQ_START,
AR71XX_PCI_IRQ_END) != 0)
panic("qca955x_pci_attach: failed to set up IRQ rman");
/* Disable interrupts */
ATH_WRITE_REG(sc->sc_pci_ctrl_base + QCA955X_PCI_INTR_STATUS, 0);
ATH_WRITE_REG(sc->sc_pci_ctrl_base + QCA955X_PCI_INTR_MASK, 0);
/* Hook up our interrupt handler. */
if ((sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
RF_SHAREABLE | RF_ACTIVE)) == NULL) {
device_printf(dev, "unable to allocate IRQ resource\n");
return (ENXIO);
}
if ((bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_MISC,
qca955x_pci_intr, NULL, sc, &sc->sc_ih))) {
device_printf(dev,
"WARNING: unable to register interrupt handler\n");
return (ENXIO);
}
/* Reset PCIe core and PCIe PHY */
ar71xx_device_stop(QCA955X_RESET_PCIE);
ar71xx_device_stop(QCA955X_RESET_PCIE_PHY);
DELAY(100);
ar71xx_device_start(QCA955X_RESET_PCIE_PHY);
ar71xx_device_start(QCA955X_RESET_PCIE);
if (qca955x_pci_setup(dev))
return (ENXIO);
/*
* Write initial base address.
*
* I'm not yet sure why this is required and/or why it isn't
* initialised like this. The AR71xx PCI code initialises
* the PCI windows for each device, but neither it or the
* 724x PCI bridge modules explicitly initialise the BAR.
*
* So before this gets committed, have a chat with jhb@ or
* someone else who knows PCI well and figure out whether
* the initial BAR is supposed to be determined by /other/
* means.
*/
qca955x_pci_write_config(dev, 0, 0, 0, PCIR_BAR(0),
sc->sc_pci_mem_base,
4);
/* Fixup internal PCI bridge */
qca955x_pci_write_config(dev, 0, 0, 0, PCIR_COMMAND,
PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN
| PCIM_CMD_SERRESPEN | PCIM_CMD_BACKTOBACK
| PCIM_CMD_PERRESPEN | PCIM_CMD_MWRICEN, 2);
device_add_child(dev, "pci", -1);
return (bus_generic_attach(dev));
}
static int
qca955x_pci_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
{
struct ar71xx_pci_softc *sc = device_get_softc(dev);
switch (which) {
case PCIB_IVAR_DOMAIN:
*result = 0;
return (0);
case PCIB_IVAR_BUS:
*result = sc->sc_busno;
return (0);
}
return (ENOENT);
}
static int
qca955x_pci_write_ivar(device_t dev, device_t child, int which, uintptr_t result)
{
struct ar71xx_pci_softc * sc = device_get_softc(dev);
switch (which) {
case PCIB_IVAR_BUS:
sc->sc_busno = result;
return (0);
}
return (ENOENT);
}
static struct resource *
qca955x_pci_alloc_resource(device_t bus, device_t child, int type, int *rid,
rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
{
struct ar71xx_pci_softc *sc = device_get_softc(bus);
struct resource *rv;
struct rman *rm;
switch (type) {
case SYS_RES_IRQ:
rm = &sc->sc_irq_rman;
break;
case SYS_RES_MEMORY:
rm = &sc->sc_mem_rman;
break;
default:
return (NULL);
}
rv = rman_reserve_resource(rm, start, end, count, flags, child);
if (rv == NULL)
return (NULL);
rman_set_rid(rv, *rid);
if (flags & RF_ACTIVE) {
if (bus_activate_resource(child, type, *rid, rv)) {
rman_release_resource(rv);
return (NULL);
}
}
return (rv);
}
static int
qca955x_pci_activate_resource(device_t bus, device_t child, int type, int rid,
struct resource *r)
{
int res = (BUS_ACTIVATE_RESOURCE(device_get_parent(bus),
child, type, rid, r));
if (!res) {
switch(type) {
case SYS_RES_MEMORY:
case SYS_RES_IOPORT:
rman_set_bustag(r, ar71xx_bus_space_pcimem);
break;
}
}
return (res);
}
static int
qca955x_pci_setup_intr(device_t bus, device_t child, struct resource *ires,
int flags, driver_filter_t *filt, driver_intr_t *handler,
void *arg, void **cookiep)
{
struct ar71xx_pci_softc *sc = device_get_softc(bus);
struct intr_event *event;
int irq, error;
irq = rman_get_start(ires);
if (irq > AR71XX_PCI_IRQ_END)
panic("%s: bad irq %d", __func__, irq);
event = sc->sc_eventstab[irq];
if (event == NULL) {
sc->sc_pci_irq[irq].sc = sc;
sc->sc_pci_irq[irq].irq = irq;
error = intr_event_create(&event, (void *)&sc->sc_pci_irq[irq],
0, irq,
qca955x_pci_mask_irq,
qca955x_pci_unmask_irq,
NULL, NULL,
"pci intr%d:", irq);
if (error == 0) {
sc->sc_eventstab[irq] = event;
sc->sc_intr_counter[irq] =
mips_intrcnt_create(event->ie_name);
}
else
return error;
}
intr_event_add_handler(event, device_get_nameunit(child), filt,
handler, arg, intr_priority(flags), flags, cookiep);
mips_intrcnt_setname(sc->sc_intr_counter[irq], event->ie_fullname);
qca955x_pci_unmask_irq(&sc->sc_pci_irq[irq]);
return (0);
}
static int
qca955x_pci_teardown_intr(device_t dev, device_t child, struct resource *ires,
void *cookie)
{
struct ar71xx_pci_softc *sc = device_get_softc(dev);
int irq, result;
irq = rman_get_start(ires);
if (irq > AR71XX_PCI_IRQ_END)
panic("%s: bad irq %d", __func__, irq);
if (sc->sc_eventstab[irq] == NULL)
panic("Trying to teardown unoccupied IRQ");
qca955x_pci_mask_irq(&sc->sc_pci_irq[irq]);
result = intr_event_remove_handler(cookie);
if (!result)
sc->sc_eventstab[irq] = NULL;
return (result);
}
static int
qca955x_pci_intr(void *arg)
{
struct ar71xx_pci_softc *sc = arg;
struct intr_event *event;
uint32_t reg, irq, mask;
/* There's only one PCIe DDR flush for both PCIe EPs */
ar71xx_device_flush_ddr(AR71XX_CPU_DDR_FLUSH_PCIE);
reg = ATH_READ_REG(sc->sc_pci_ctrl_base + QCA955X_PCI_INTR_STATUS);
mask = ATH_READ_REG(sc->sc_pci_ctrl_base + QCA955X_PCI_INTR_MASK);
/*
* Handle only unmasked interrupts
*/
reg &= mask;
/*
* XXX TODO: handle >1 PCIe end point!
*/
if (reg & QCA955X_PCI_INTR_DEV0) {
irq = AR71XX_PCI_IRQ_START;
event = sc->sc_eventstab[irq];
if (!event || CK_SLIST_EMPTY(&event->ie_handlers)) {
printf("Stray IRQ %d\n", irq);
return (FILTER_STRAY);
}
/* TODO: frame instead of NULL? */
intr_event_handle(event, NULL);
mips_intrcnt_inc(sc->sc_intr_counter[irq]);
}
return (FILTER_HANDLED);
}
static int
qca955x_pci_maxslots(device_t dev)
{
return (PCI_SLOTMAX);
}
static int
qca955x_pci_route_interrupt(device_t pcib, device_t device, int pin)
{
return (pci_get_slot(device));
}
static device_method_t qca955x_pci_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, qca955x_pci_probe),
DEVMETHOD(device_attach, qca955x_pci_attach),
DEVMETHOD(device_shutdown, bus_generic_shutdown),
DEVMETHOD(device_suspend, bus_generic_suspend),
DEVMETHOD(device_resume, bus_generic_resume),
/* Bus interface */
DEVMETHOD(bus_read_ivar, qca955x_pci_read_ivar),
DEVMETHOD(bus_write_ivar, qca955x_pci_write_ivar),
DEVMETHOD(bus_alloc_resource, qca955x_pci_alloc_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, qca955x_pci_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
DEVMETHOD(bus_setup_intr, qca955x_pci_setup_intr),
DEVMETHOD(bus_teardown_intr, qca955x_pci_teardown_intr),
/* pcib interface */
DEVMETHOD(pcib_maxslots, qca955x_pci_maxslots),
DEVMETHOD(pcib_read_config, qca955x_pci_read_config),
DEVMETHOD(pcib_write_config, qca955x_pci_write_config),
DEVMETHOD(pcib_route_interrupt, qca955x_pci_route_interrupt),
DEVMETHOD(pcib_request_feature, pcib_request_feature_allow),
DEVMETHOD_END
};
static driver_t qca955x_pci_driver = {
"pcib",
qca955x_pci_methods,
sizeof(struct ar71xx_pci_softc),
};
static devclass_t qca955x_pci_devclass;
DRIVER_MODULE(qca955x_pci, nexus, qca955x_pci_driver, qca955x_pci_devclass, 0, 0);
DRIVER_MODULE(qca955x_pci, apb, qca955x_pci_driver, qca955x_pci_devclass, 0, 0);

View File

@ -1,228 +0,0 @@
/*-
* Copyright (c) 2013 Adrian Chadd <adrian@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef __QCA955XREG_H__
#define __QCA955XREG_H__
#define BIT(x) (1 << (x))
/* Revision ID information */
#define REV_ID_MAJOR_QCA9556 0x0130
#define REV_ID_MAJOR_QCA9558 0x1130
#define QCA955X_REV_ID_REVISION_MASK 0xf
/* Big enough to cover APB and SPI, and most peripherals */
/*
* it needs to cover SPI because right now the if_ath_ahb
* code uses rman to map in the SPI address into memory
* to read data instead of us squirreling it away at early
* boot-time and using the firmware interface.
*
* if_ath_ahb.c should use the same firmware interface
* that if_ath_pci.c uses.
*/
#define QCA955X_APB_BASE 0x18000000
#define QCA955X_APB_SIZE 0x08000000
#define QCA955X_PCI_MEM_BASE0 0x10000000
#define QCA955X_PCI_MEM_BASE1 0x12000000
#define QCA955X_PCI_MEM_SIZE 0x02000000
#define QCA955X_PCI_CFG_BASE0 0x14000000
#define QCA955X_PCI_CFG_BASE1 0x16000000
#define QCA955X_PCI_CFG_SIZE 0x1000
#define QCA955X_PCI_CRP_BASE0 (AR71XX_APB_BASE + 0x000c0000)
#define QCA955X_PCI_CRP_BASE1 (AR71XX_APB_BASE + 0x00250000)
#define QCA955X_PCI_CRP_SIZE 0x1000
#define QCA955X_PCI_CTRL_BASE0 (AR71XX_APB_BASE + 0x000f0000)
#define QCA955X_PCI_CTRL_BASE1 (AR71XX_APB_BASE + 0x00280000)
#define QCA955X_PCI_CTRL_SIZE 0x100
#define QCA955X_WMAC_BASE (AR71XX_APB_BASE + 0x00100000)
#define QCA955X_WMAC_SIZE 0x20000
#define QCA955X_EHCI0_BASE 0x1b000000
#define QCA955X_EHCI1_BASE 0x1b400000
#define QCA955X_EHCI_SIZE 0x1000
/* PLL block */
#define QCA955X_PLL_CPU_CONFIG_REG (AR71XX_PLL_CPU_BASE + 0x00)
#define QCA955X_PLL_DDR_CONFIG_REG (AR71XX_PLL_CPU_BASE + 0x04)
#define QCA955X_PLL_CLK_CTRL_REG (AR71XX_PLL_CPU_BASE + 0x08)
#define QCA955X_PLL_CPU_CONFIG_NFRAC_SHIFT 0
#define QCA955X_PLL_CPU_CONFIG_NFRAC_MASK 0x3f
#define QCA955X_PLL_CPU_CONFIG_NINT_SHIFT 6
#define QCA955X_PLL_CPU_CONFIG_NINT_MASK 0x3f
#define QCA955X_PLL_CPU_CONFIG_REFDIV_SHIFT 12
#define QCA955X_PLL_CPU_CONFIG_REFDIV_MASK 0x1f
#define QCA955X_PLL_CPU_CONFIG_OUTDIV_SHIFT 19
#define QCA955X_PLL_CPU_CONFIG_OUTDIV_MASK 0x3
#define QCA955X_PLL_DDR_CONFIG_NFRAC_SHIFT 0
#define QCA955X_PLL_DDR_CONFIG_NFRAC_MASK 0x3ff
#define QCA955X_PLL_DDR_CONFIG_NINT_SHIFT 10
#define QCA955X_PLL_DDR_CONFIG_NINT_MASK 0x3f
#define QCA955X_PLL_DDR_CONFIG_REFDIV_SHIFT 16
#define QCA955X_PLL_DDR_CONFIG_REFDIV_MASK 0x1f
#define QCA955X_PLL_DDR_CONFIG_OUTDIV_SHIFT 23
#define QCA955X_PLL_DDR_CONFIG_OUTDIV_MASK 0x7
#define QCA955X_PLL_CLK_CTRL_CPU_PLL_BYPASS BIT(2)
#define QCA955X_PLL_CLK_CTRL_DDR_PLL_BYPASS BIT(3)
#define QCA955X_PLL_CLK_CTRL_AHB_PLL_BYPASS BIT(4)
#define QCA955X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT 5
#define QCA955X_PLL_CLK_CTRL_CPU_POST_DIV_MASK 0x1f
#define QCA955X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT 10
#define QCA955X_PLL_CLK_CTRL_DDR_POST_DIV_MASK 0x1f
#define QCA955X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT 15
#define QCA955X_PLL_CLK_CTRL_AHB_POST_DIV_MASK 0x1f
#define QCA955X_PLL_CLK_CTRL_CPUCLK_FROM_CPUPLL BIT(20)
#define QCA955X_PLL_CLK_CTRL_DDRCLK_FROM_DDRPLL BIT(21)
#define QCA955X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL BIT(24)
#define QCA955X_PLL_ETH_XMII_CONTROL_REG (AR71XX_PLL_CPU_BASE + 0x28)
#define QCA955X_PLL_ETH_SGMII_CONTROL_REG (AR71XX_PLL_CPU_BASE + 0x48)
/* Reset block */
#define QCA955X_RESET_REG_RESET_MODULE (AR71XX_RST_BLOCK_BASE + 0x1c)
#define QCA955X_RESET_REG_BOOTSTRAP (AR71XX_RST_BLOCK_BASE + 0xb0)
#define QCA955X_RESET_REG_EXT_INT_STATUS (AR71XX_RST_BLOCK_BASE + 0xac)
#define QCA955X_BOOTSTRAP_REF_CLK_40 BIT(4)
#define QCA955X_EXT_INT_WMAC_MISC BIT(0)
#define QCA955X_EXT_INT_WMAC_TX BIT(1)
#define QCA955X_EXT_INT_WMAC_RXLP BIT(2)
#define QCA955X_EXT_INT_WMAC_RXHP BIT(3)
#define QCA955X_EXT_INT_PCIE_RC1 BIT(4)
#define QCA955X_EXT_INT_PCIE_RC1_INT0 BIT(5)
#define QCA955X_EXT_INT_PCIE_RC1_INT1 BIT(6)
#define QCA955X_EXT_INT_PCIE_RC1_INT2 BIT(7)
#define QCA955X_EXT_INT_PCIE_RC1_INT3 BIT(8)
#define QCA955X_EXT_INT_PCIE_RC2 BIT(12)
#define QCA955X_EXT_INT_PCIE_RC2_INT0 BIT(13)
#define QCA955X_EXT_INT_PCIE_RC2_INT1 BIT(14)
#define QCA955X_EXT_INT_PCIE_RC2_INT2 BIT(15)
#define QCA955X_EXT_INT_PCIE_RC2_INT3 BIT(16)
#define QCA955X_EXT_INT_USB1 BIT(24)
#define QCA955X_EXT_INT_USB2 BIT(28)
#define QCA955X_EXT_INT_WMAC_ALL \
(QCA955X_EXT_INT_WMAC_MISC | QCA955X_EXT_INT_WMAC_TX | \
QCA955X_EXT_INT_WMAC_RXLP | QCA955X_EXT_INT_WMAC_RXHP)
#define QCA955X_EXT_INT_PCIE_RC1_ALL \
(QCA955X_EXT_INT_PCIE_RC1 | QCA955X_EXT_INT_PCIE_RC1_INT0 | \
QCA955X_EXT_INT_PCIE_RC1_INT1 | QCA955X_EXT_INT_PCIE_RC1_INT2 | \
QCA955X_EXT_INT_PCIE_RC1_INT3)
#define QCA955X_EXT_INT_PCIE_RC2_ALL \
(QCA955X_EXT_INT_PCIE_RC2 | QCA955X_EXT_INT_PCIE_RC2_INT0 | \
QCA955X_EXT_INT_PCIE_RC2_INT1 | QCA955X_EXT_INT_PCIE_RC2_INT2 | \
QCA955X_EXT_INT_PCIE_RC2_INT3)
#define QCA955X_RESET_HOST BIT(31)
#define QCA955X_RESET_SLIC BIT(30)
#define QCA955X_RESET_HDMA BIT(29)
#define QCA955X_RESET_EXTERNAL BIT(28)
#define QCA955X_RESET_RTC BIT(27)
#define QCA955X_RESET_PCIE_EP_INT BIT(26)
#define QCA955X_RESET_CHKSUM_ACC BIT(25)
#define QCA955X_RESET_FULL_CHIP BIT(24)
#define QCA955X_RESET_GE1_MDIO BIT(23)
#define QCA955X_RESET_GE0_MDIO BIT(22)
#define QCA955X_RESET_CPU_NMI BIT(21)
#define QCA955X_RESET_CPU_COLD BIT(20)
#define QCA955X_RESET_HOST_RESET_INT BIT(19)
#define QCA955X_RESET_PCIE_EP BIT(18)
#define QCA955X_RESET_UART1 BIT(17)
#define QCA955X_RESET_DDR BIT(16)
#define QCA955X_RESET_USB_PHY_PLL_PWD_EXT BIT(15)
#define QCA955X_RESET_NANDF BIT(14)
#define QCA955X_RESET_GE1_MAC BIT(13)
#define QCA955X_RESET_SGMII_ANALOG BIT(12)
#define QCA955X_RESET_USB_PHY_ANALOG BIT(11)
#define QCA955X_RESET_HOST_DMA_INT BIT(10)
#define QCA955X_RESET_GE0_MAC BIT(9)
#define QCA955X_RESET_SGMII BIT(8)
#define QCA955X_RESET_PCIE_PHY BIT(7)
#define QCA955X_RESET_PCIE BIT(6)
#define QCA955X_RESET_USB_HOST BIT(5)
#define QCA955X_RESET_USB_PHY BIT(4)
#define QCA955X_RESET_USBSUS_OVERRIDE BIT(3)
#define QCA955X_RESET_LUT BIT(2)
#define QCA955X_RESET_MBOX BIT(1)
#define QCA955X_RESET_I2S BIT(0)
/* GPIO block */
#define QCA955X_GPIO_REG_OUT_FUNC0 0x2c
#define QCA955X_GPIO_REG_OUT_FUNC1 0x30
#define QCA955X_GPIO_REG_OUT_FUNC2 0x34
#define QCA955X_GPIO_REG_OUT_FUNC3 0x38
#define QCA955X_GPIO_REG_OUT_FUNC4 0x3c
#define QCA955X_GPIO_REG_OUT_FUNC5 0x40
#define QCA955X_GPIO_REG_FUNC 0x6c
#define QCA955X_GPIO_COUNT 24
#define QCA955X_GMAC_BASE (AR71XX_APB_BASE + 0x00070000)
#define QCA955X_GMAC_SIZE 0x40
#define QCA955X_NFC_BASE 0x1b800200
#define QCA955X_NFC_SIZE 0xb8
/* GMAC Interface */
#define QCA955X_GMAC_REG_ETH_CFG (QCA955X_GMAC_BASE + 0x00)
#define QCA955X_ETH_CFG_RGMII_EN BIT(0)
#define QCA955X_ETH_CFG_GE0_SGMII BIT(6)
/* XXX Same as AR934x values */
#define QCA955X_PLL_VAL_1000 0x16000000
#define QCA955X_PLL_VAL_100 0x00000101
#define QCA955X_PLL_VAL_10 0x00001616
/* DDR block */
#define QCA955X_DDR_REG_FLUSH_GE0 (AR71XX_APB_BASE + 0x9c)
#define QCA955X_DDR_REG_FLUSH_GE1 (AR71XX_APB_BASE + 0xa0)
#define QCA955X_DDR_REG_FLUSH_USB (AR71XX_APB_BASE + 0xa4)
#define QCA955X_DDR_REG_FLUSH_PCIE (AR71XX_APB_BASE + 0xa8)
#define QCA955X_DDR_REG_FLUSH_WMAC (AR71XX_APB_BASE + 0xac)
/* PCIe EP */
#define QCA955X_DDR_REG_FLUSH_SRC1 (AR71XX_APB_BASE + 0xb0)
/* checksum engine */
#define QCA955X_DDR_REG_FLUSH_SRC2 (AR71XX_APB_BASE + 0xb2)
/* PCIe control block - relative to PCI_CTRL_BASE0/PCI_CTRL_BASE1 */
#define QCA955X_PCI_APP 0x0
#define QCA955X_PCI_APP_LTSSM_ENABLE (1 << 0)
#define QCA955X_PCI_RESET 0x18
#define QCA955X_PCI_RESET_LINK_UP (1 << 0)
#define QCA955X_PCI_INTR_STATUS 0x4c
#define QCA955X_PCI_INTR_MASK 0x50
#define QCA955X_PCI_INTR_DEV0 (1 << 14)
#endif /* __QCA955XREG_H__ */

View File

@ -1,8 +0,0 @@
# $FreeBSD$
#
# standard config for all ar71xx based kernels.
files "../atheros/files.ar71xx"
machine mips mips
cpu CPU_MIPS4KC

View File

@ -1,108 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
*/
#include "opt_uart.h"
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <machine/bus.h>
#include <dev/uart/uart.h>
#include <dev/uart/uart_cpu.h>
#include <dev/uart/uart_bus.h>
#include <mips/atheros/ar71xxreg.h>
#include <mips/atheros/ar71xx_cpudef.h>
#include "uart_if.h"
static int uart_ar71xx_probe(device_t dev);
extern struct uart_class uart_ar71xx_uart_class;
static device_method_t uart_ar71xx_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, uart_ar71xx_probe),
DEVMETHOD(device_attach, uart_bus_attach),
DEVMETHOD(device_detach, uart_bus_detach),
{ 0, 0 }
};
static driver_t uart_ar71xx_driver = {
uart_driver_name,
uart_ar71xx_methods,
sizeof(struct uart_softc),
};
extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs;
static int
uart_ar71xx_probe(device_t dev)
{
struct uart_softc *sc;
uint64_t freq;
freq = ar71xx_uart_freq();
sc = device_get_softc(dev);
sc->sc_sysdev = SLIST_FIRST(&uart_sysdevs);
sc->sc_class = &uart_ns8250_class;
bcopy(&sc->sc_sysdev->bas, &sc->sc_bas, sizeof(sc->sc_bas));
sc->sc_sysdev->bas.regshft = 2;
sc->sc_sysdev->bas.bst = mips_bus_space_generic;
sc->sc_sysdev->bas.bsh = MIPS_PHYS_TO_KSEG1(AR71XX_UART_ADDR) + 3;
sc->sc_bas.regshft = 2;
sc->sc_bas.bst = mips_bus_space_generic;
sc->sc_bas.bsh = MIPS_PHYS_TO_KSEG1(AR71XX_UART_ADDR) + 3;
return (uart_bus_probe(dev, 2, 0, freq, 0, 0, 0));
}
#ifdef EARLY_PRINTF
static void
ar71xx_early_putc(int c)
{
int i;
for (i = 0; i < 1000; i++) {
if (ATH_READ_REG(AR71XX_UART_ADDR + AR71XX_UART_LSR)
& AR71XX_UART_LSR_THRE)
break;
}
ATH_WRITE_REG(AR71XX_UART_ADDR + AR71XX_UART_THR, (c & 0xff));
}
early_putc_t *early_putc = ar71xx_early_putc;
#endif
DRIVER_MODULE(uart, apb, uart_ar71xx_driver, uart_devclass, 0, 0);

View File

@ -1,117 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2012, Adrian Chadd <adrian@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
*/
#include "opt_uart.h"
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <machine/bus.h>
#include <dev/uart/uart.h>
#include <dev/uart/uart_cpu.h>
#include <dev/uart/uart_bus.h>
#include <mips/atheros/ar71xxreg.h>
#include <mips/atheros/ar71xx_cpudef.h>
#include <mips/atheros/uart_dev_ar933x.h>
#ifdef EARLY_PRINTF
#include <mips/atheros/ar933x_uart.h>
#endif
#include "uart_if.h"
static int uart_ar933x_probe(device_t dev);
extern struct uart_class uart_ar933x_uart_class;
static device_method_t uart_ar933x_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, uart_ar933x_probe),
DEVMETHOD(device_attach, uart_bus_attach),
DEVMETHOD(device_detach, uart_bus_detach),
{ 0, 0 }
};
static driver_t uart_ar933x_driver = {
uart_driver_name,
uart_ar933x_methods,
sizeof(struct uart_softc),
};
extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs;
static int
uart_ar933x_probe(device_t dev)
{
struct uart_softc *sc;
uint64_t freq;
freq = ar71xx_uart_freq();
sc = device_get_softc(dev);
sc->sc_sysdev = SLIST_FIRST(&uart_sysdevs);
sc->sc_class = &uart_ar933x_class;
bcopy(&sc->sc_sysdev->bas, &sc->sc_bas, sizeof(sc->sc_bas));
sc->sc_sysdev->bas.regshft = 0;
sc->sc_sysdev->bas.bst = mips_bus_space_generic;
sc->sc_sysdev->bas.bsh = MIPS_PHYS_TO_KSEG1(AR71XX_UART_ADDR);
sc->sc_bas.regshft = 0;
sc->sc_bas.bst = mips_bus_space_generic;
sc->sc_bas.bsh = MIPS_PHYS_TO_KSEG1(AR71XX_UART_ADDR);
return (uart_bus_probe(dev, 2, 0, freq, 0, 0, 0));
}
/*
* Assume the UART is setup by the bootloader and just echo that.
*/
#if defined(EARLY_PRINTF)
static void
ar933x_early_putc(int c)
{
int i = 1000;
/* Wait until FIFO is clear */
while ((i > 0) && (ATH_READ_REG(AR71XX_UART_ADDR + AR933X_UART_CS_REG) &
AR933X_UART_CS_TX_BUSY))
i--;
/* Write it out */
ATH_WRITE_REG(AR71XX_UART_ADDR + AR933X_UART_DATA_REG,
(c & 0xff)| AR933X_UART_DATA_TX_CSR);
}
early_putc_t *early_putc = ar933x_early_putc;
#endif /* EARLY_PRINTF */
DRIVER_MODULE(uart, apb, uart_ar933x_driver, uart_devclass, 0, 0);

View File

@ -1,78 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2009 Oleksandr Tymoshenko
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include "opt_uart.h"
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <machine/bus.h>
#include <dev/uart/uart.h>
#include <dev/uart/uart_cpu.h>
#include <mips/atheros/ar71xxreg.h>
#include <mips/atheros/ar71xx_cpudef.h>
#include <mips/atheros/ar71xx_bus_space_reversed.h>
bus_space_tag_t uart_bus_space_io;
bus_space_tag_t uart_bus_space_mem;
int
uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2)
{
return ((b1->bsh == b2->bsh && b1->bst == b2->bst) ? 1 : 0);
}
int
uart_cpu_getdev(int devtype, struct uart_devinfo *di)
{
uint64_t freq;
freq = ar71xx_uart_freq();
di->ops = uart_getops(&uart_ns8250_class);
di->bas.chan = 0;
di->bas.bst = ar71xx_bus_space_reversed;
di->bas.regshft = 2;
di->bas.rclk = freq;
di->baudrate = 115200;
di->databits = 8;
di->stopbits = 1;
di->parity = UART_PARITY_NONE;
uart_bus_space_io = NULL;
uart_bus_space_mem = ar71xx_bus_space_reversed;
di->bas.bsh = MIPS_PHYS_TO_KSEG1(AR71XX_UART_ADDR);
return (0);
}

View File

@ -1,80 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2012 Adrian Chadd <adrian@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include "opt_uart.h"
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <machine/bus.h>
#include <dev/uart/uart.h>
#include <dev/uart/uart_cpu.h>
#include <mips/atheros/ar71xxreg.h>
#include <mips/atheros/ar71xx_cpudef.h>
#include <mips/atheros/ar71xx_bus_space_reversed.h>
#include <mips/atheros/uart_dev_ar933x.h>
bus_space_tag_t uart_bus_space_io;
bus_space_tag_t uart_bus_space_mem;
int
uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2)
{
return ((b1->bsh == b2->bsh && b1->bst == b2->bst) ? 1 : 0);
}
int
uart_cpu_getdev(int devtype, struct uart_devinfo *di)
{
uint64_t freq;
freq = ar71xx_uart_freq();
di->ops = uart_getops(&uart_ar933x_class);
di->bas.chan = 0;
di->bas.bst = ar71xx_bus_space_reversed;
di->bas.regshft = 0; /* We'll do "correct" dword addressing here */
di->bas.rclk = freq;
di->baudrate = 115200;
di->databits = 8;
di->stopbits = 1;
di->parity = UART_PARITY_NONE;
uart_bus_space_io = NULL;
uart_bus_space_mem = ar71xx_bus_space_reversed;
di->bas.bsh = MIPS_PHYS_TO_KSEG1(AR71XX_UART_ADDR);
return (0);
}

View File

@ -1,736 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2013 Adrian Chadd <adrian@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <machine/bus.h>
#include <dev/uart/uart.h>
#include <dev/uart/uart_cpu.h>
#include <dev/uart/uart_bus.h>
#include <mips/atheros/ar933x_uart.h>
#include "uart_if.h"
/*
* Default system clock is 25MHz; see ar933x_chip.c for how
* the startup process determines whether it's 25MHz or 40MHz.
*/
#define DEFAULT_RCLK (25 * 1000 * 1000)
#define ar933x_getreg(bas, reg) \
bus_space_read_4((bas)->bst, (bas)->bsh, reg)
#define ar933x_setreg(bas, reg, value) \
bus_space_write_4((bas)->bst, (bas)->bsh, reg, value)
static int
ar933x_drain(struct uart_bas *bas, int what)
{
int limit;
if (what & UART_DRAIN_TRANSMITTER) {
limit = 10*1024;
/* Loop over until the TX FIFO shows entirely clear */
while (--limit) {
if ((ar933x_getreg(bas, AR933X_UART_CS_REG)
& AR933X_UART_CS_TX_BUSY) == 0)
break;
}
if (limit == 0) {
return (EIO);
}
}
if (what & UART_DRAIN_RECEIVER) {
limit=10*4096;
while (--limit) {
/* XXX duplicated from ar933x_getc() */
/* XXX TODO: refactor! */
/* If there's nothing to read, stop! */
if ((ar933x_getreg(bas, AR933X_UART_DATA_REG) &
AR933X_UART_DATA_RX_CSR) == 0) {
break;
}
/* Read the top of the RX FIFO */
(void) ar933x_getreg(bas, AR933X_UART_DATA_REG);
/* Remove that entry from said RX FIFO */
ar933x_setreg(bas, AR933X_UART_DATA_REG,
AR933X_UART_DATA_RX_CSR);
uart_barrier(bas);
DELAY(2);
}
if (limit == 0) {
return (EIO);
}
}
return (0);
}
/*
* Calculate the baud from the given chip configuration parameters.
*/
static unsigned long
ar933x_uart_get_baud(unsigned int clk, unsigned int scale,
unsigned int step)
{
uint64_t t;
uint32_t div;
div = (2 << 16) * (scale + 1);
t = clk;
t *= step;
t += (div / 2);
t = t / div;
return (t);
}
/*
* Calculate the scale/step with the lowest possible deviation from
* the target baudrate.
*/
static void
ar933x_uart_get_scale_step(struct uart_bas *bas, unsigned int baud,
unsigned int *scale, unsigned int *step)
{
unsigned int tscale;
uint32_t clk;
long min_diff;
clk = bas->rclk;
*scale = 0;
*step = 0;
min_diff = baud;
for (tscale = 0; tscale < AR933X_UART_MAX_SCALE; tscale++) {
uint64_t tstep;
int diff;
tstep = baud * (tscale + 1);
tstep *= (2 << 16);
tstep = tstep / clk;
if (tstep > AR933X_UART_MAX_STEP)
break;
diff = abs(ar933x_uart_get_baud(clk, tscale, tstep) - baud);
if (diff < min_diff) {
min_diff = diff;
*scale = tscale;
*step = tstep;
}
}
}
static int
ar933x_param(struct uart_bas *bas, int baudrate, int databits, int stopbits,
int parity)
{
/* UART always 8 bits */
/* UART always 1 stop bit */
/* UART parity is controllable by bits 0:1, ignore for now */
/* Set baudrate if required. */
if (baudrate > 0) {
uint32_t clock_scale, clock_step;
/* Find the best fit for the given baud rate */
ar933x_uart_get_scale_step(bas, baudrate, &clock_scale,
&clock_step);
/*
* Program the clock register in its entirety - no need
* for Read-Modify-Write.
*/
ar933x_setreg(bas, AR933X_UART_CLOCK_REG,
((clock_scale & AR933X_UART_CLOCK_SCALE_M)
<< AR933X_UART_CLOCK_SCALE_S) |
(clock_step & AR933X_UART_CLOCK_STEP_M));
}
uart_barrier(bas);
return (0);
}
/*
* Low-level UART interface.
*/
static int ar933x_probe(struct uart_bas *bas);
static void ar933x_init(struct uart_bas *bas, int, int, int, int);
static void ar933x_term(struct uart_bas *bas);
static void ar933x_putc(struct uart_bas *bas, int);
static int ar933x_rxready(struct uart_bas *bas);
static int ar933x_getc(struct uart_bas *bas, struct mtx *);
static struct uart_ops uart_ar933x_ops = {
.probe = ar933x_probe,
.init = ar933x_init,
.term = ar933x_term,
.putc = ar933x_putc,
.rxready = ar933x_rxready,
.getc = ar933x_getc,
};
static int
ar933x_probe(struct uart_bas *bas)
{
/* We always know this will be here */
return (0);
}
static void
ar933x_init(struct uart_bas *bas, int baudrate, int databits, int stopbits,
int parity)
{
uint32_t reg;
/* Setup default parameters */
ar933x_param(bas, baudrate, databits, stopbits, parity);
/* XXX Force enable UART in case it was disabled */
/* Disable all interrupts */
ar933x_setreg(bas, AR933X_UART_INT_EN_REG, 0x00000000);
/* Disable the host interrupt */
reg = ar933x_getreg(bas, AR933X_UART_CS_REG);
reg &= ~AR933X_UART_CS_HOST_INT_EN;
ar933x_setreg(bas, AR933X_UART_CS_REG, reg);
uart_barrier(bas);
/* XXX Set RTS/DTR? */
}
/*
* Detach from console.
*/
static void
ar933x_term(struct uart_bas *bas)
{
/* XXX TODO */
}
static void
ar933x_putc(struct uart_bas *bas, int c)
{
int limit;
limit = 250000;
/* Wait for space in the TX FIFO */
while ( ((ar933x_getreg(bas, AR933X_UART_DATA_REG) &
AR933X_UART_DATA_TX_CSR) == 0) && --limit)
DELAY(4);
/* Write the actual byte */
ar933x_setreg(bas, AR933X_UART_DATA_REG,
(c & 0xff) | AR933X_UART_DATA_TX_CSR);
}
static int
ar933x_rxready(struct uart_bas *bas)
{
/* Wait for a character to come ready */
return (!!(ar933x_getreg(bas, AR933X_UART_DATA_REG)
& AR933X_UART_DATA_RX_CSR));
}
static int
ar933x_getc(struct uart_bas *bas, struct mtx *hwmtx)
{
int c;
uart_lock(hwmtx);
/* Wait for a character to come ready */
while ((ar933x_getreg(bas, AR933X_UART_DATA_REG) &
AR933X_UART_DATA_RX_CSR) == 0) {
uart_unlock(hwmtx);
DELAY(4);
uart_lock(hwmtx);
}
/* Read the top of the RX FIFO */
c = ar933x_getreg(bas, AR933X_UART_DATA_REG) & 0xff;
/* Remove that entry from said RX FIFO */
ar933x_setreg(bas, AR933X_UART_DATA_REG, AR933X_UART_DATA_RX_CSR);
uart_unlock(hwmtx);
return (c);
}
/*
* High-level UART interface.
*/
struct ar933x_softc {
struct uart_softc base;
uint32_t u_ier;
};
static int ar933x_bus_attach(struct uart_softc *);
static int ar933x_bus_detach(struct uart_softc *);
static int ar933x_bus_flush(struct uart_softc *, int);
static int ar933x_bus_getsig(struct uart_softc *);
static int ar933x_bus_ioctl(struct uart_softc *, int, intptr_t);
static int ar933x_bus_ipend(struct uart_softc *);
static int ar933x_bus_param(struct uart_softc *, int, int, int, int);
static int ar933x_bus_probe(struct uart_softc *);
static int ar933x_bus_receive(struct uart_softc *);
static int ar933x_bus_setsig(struct uart_softc *, int);
static int ar933x_bus_transmit(struct uart_softc *);
static void ar933x_bus_grab(struct uart_softc *);
static void ar933x_bus_ungrab(struct uart_softc *);
static kobj_method_t ar933x_methods[] = {
KOBJMETHOD(uart_attach, ar933x_bus_attach),
KOBJMETHOD(uart_detach, ar933x_bus_detach),
KOBJMETHOD(uart_flush, ar933x_bus_flush),
KOBJMETHOD(uart_getsig, ar933x_bus_getsig),
KOBJMETHOD(uart_ioctl, ar933x_bus_ioctl),
KOBJMETHOD(uart_ipend, ar933x_bus_ipend),
KOBJMETHOD(uart_param, ar933x_bus_param),
KOBJMETHOD(uart_probe, ar933x_bus_probe),
KOBJMETHOD(uart_receive, ar933x_bus_receive),
KOBJMETHOD(uart_setsig, ar933x_bus_setsig),
KOBJMETHOD(uart_transmit, ar933x_bus_transmit),
KOBJMETHOD(uart_grab, ar933x_bus_grab),
KOBJMETHOD(uart_ungrab, ar933x_bus_ungrab),
{ 0, 0 }
};
struct uart_class uart_ar933x_class = {
"ar933x",
ar933x_methods,
sizeof(struct ar933x_softc),
.uc_ops = &uart_ar933x_ops,
.uc_range = 8,
.uc_rclk = DEFAULT_RCLK,
.uc_rshift = 0
};
#define SIGCHG(c, i, s, d) \
if (c) { \
i |= (i & s) ? s : s | d; \
} else { \
i = (i & s) ? (i & ~s) | d : i; \
}
static int
ar933x_bus_attach(struct uart_softc *sc)
{
struct ar933x_softc *u = (struct ar933x_softc *)sc;
struct uart_bas *bas = &sc->sc_bas;
uint32_t reg;
/* XXX TODO: flush transmitter */
/*
* Setup initial interrupt notifications.
*
* XXX for now, just RX FIFO valid.
* Later on (when they're handled), also handle
* RX errors/overflow.
*/
u->u_ier = AR933X_UART_INT_RX_VALID;
/* Enable RX interrupts to kick-start things */
ar933x_setreg(bas, AR933X_UART_INT_EN_REG, u->u_ier);
/* Enable the host interrupt now */
reg = ar933x_getreg(bas, AR933X_UART_CS_REG);
reg |= AR933X_UART_CS_HOST_INT_EN;
ar933x_setreg(bas, AR933X_UART_CS_REG, reg);
return (0);
}
static int
ar933x_bus_detach(struct uart_softc *sc)
{
struct uart_bas *bas = &sc->sc_bas;
uint32_t reg;
/* Disable all interrupts */
ar933x_setreg(bas, AR933X_UART_INT_EN_REG, 0x00000000);
/* Disable the host interrupt */
reg = ar933x_getreg(bas, AR933X_UART_CS_REG);
reg &= ~AR933X_UART_CS_HOST_INT_EN;
ar933x_setreg(bas, AR933X_UART_CS_REG, reg);
uart_barrier(bas);
return (0);
}
static int
ar933x_bus_flush(struct uart_softc *sc, int what)
{
struct uart_bas *bas;
bas = &sc->sc_bas;
uart_lock(sc->sc_hwmtx);
ar933x_drain(bas, what);
uart_unlock(sc->sc_hwmtx);
return (0);
}
static int
ar933x_bus_getsig(struct uart_softc *sc)
{
uint32_t sig = sc->sc_hwsig;
/*
* For now, let's just return that DSR/DCD/CTS is asserted.
*/
SIGCHG(1, sig, SER_DSR, SER_DDSR);
SIGCHG(1, sig, SER_CTS, SER_DCTS);
SIGCHG(1, sig, SER_DCD, SER_DDCD);
SIGCHG(1, sig, SER_RI, SER_DRI);
sc->sc_hwsig = sig & ~SER_MASK_DELTA;
return (sig);
}
/*
* XXX TODO: actually implement the rest of this!
*/
static int
ar933x_bus_ioctl(struct uart_softc *sc, int request, intptr_t data)
{
int error = 0;
/* XXX lock */
switch (request) {
case UART_IOCTL_BREAK:
case UART_IOCTL_IFLOW:
case UART_IOCTL_OFLOW:
break;
case UART_IOCTL_BAUD:
*(int*)data = 115200;
break;
default:
error = EINVAL;
break;
}
/* XXX unlock */
return (error);
}
/*
* Bus interrupt handler.
*
* For now, system interrupts are disabled.
* So this is just called from a callout in uart_core.c
* to poll various state.
*/
static int
ar933x_bus_ipend(struct uart_softc *sc)
{
struct ar933x_softc *u = (struct ar933x_softc *)sc;
struct uart_bas *bas = &sc->sc_bas;
int ipend = 0;
uint32_t isr;
uart_lock(sc->sc_hwmtx);
/*
* Fetch/ACK the ISR status.
*/
isr = ar933x_getreg(bas, AR933X_UART_INT_REG);
ar933x_setreg(bas, AR933X_UART_INT_REG, isr);
uart_barrier(bas);
/*
* RX ready - notify upper layer.
*/
if (isr & AR933X_UART_INT_RX_VALID) {
ipend |= SER_INT_RXREADY;
}
/*
* If we get this interrupt, we should disable
* it from the interrupt mask and inform the uart
* driver appropriately.
*
* We can't keep setting SER_INT_TXIDLE or SER_INT_SIGCHG
* all the time or IO stops working. So we will always
* clear this interrupt if we get it, then we only signal
* the upper layer if we were doing active TX in the
* first place.
*
* Also, the name is misleading. This actually means
* "the FIFO is almost empty." So if we just write some
* more data to the FIFO without checking whether it can
* take said data, we'll overflow the thing.
*
* Unfortunately the FreeBSD uart device has no concept of
* partial UART writes - it expects that the whole buffer
* is written to the hardware. Thus for now, ar933x_bus_transmit()
* will wait for the FIFO to finish draining before it pushes
* more frames into it.
*/
if (isr & AR933X_UART_INT_TX_EMPTY) {
/*
* Update u_ier to disable TX notifications; update hardware
*/
u->u_ier &= ~AR933X_UART_INT_TX_EMPTY;
ar933x_setreg(bas, AR933X_UART_INT_EN_REG, u->u_ier);
uart_barrier(bas);
}
/*
* Only signal TX idle if we're not busy transmitting.
*
* XXX I never get _out_ of txbusy? Debug that!
*/
if (sc->sc_txbusy) {
if (isr & AR933X_UART_INT_TX_EMPTY) {
ipend |= SER_INT_TXIDLE;
} else {
ipend |= SER_INT_SIGCHG;
}
}
uart_unlock(sc->sc_hwmtx);
return (ipend);
}
static int
ar933x_bus_param(struct uart_softc *sc, int baudrate, int databits,
int stopbits, int parity)
{
struct uart_bas *bas;
int error;
bas = &sc->sc_bas;
uart_lock(sc->sc_hwmtx);
error = ar933x_param(bas, baudrate, databits, stopbits, parity);
uart_unlock(sc->sc_hwmtx);
return (error);
}
static int
ar933x_bus_probe(struct uart_softc *sc)
{
struct uart_bas *bas;
int error;
bas = &sc->sc_bas;
error = ar933x_probe(bas);
if (error)
return (error);
/* Reset FIFOs. */
ar933x_drain(bas, UART_FLUSH_RECEIVER|UART_FLUSH_TRANSMITTER);
/* XXX TODO: actually find out what the FIFO depth is! */
sc->sc_rxfifosz = 16;
sc->sc_txfifosz = 16;
return (0);
}
static int
ar933x_bus_receive(struct uart_softc *sc)
{
struct uart_bas *bas = &sc->sc_bas;
int xc;
uart_lock(sc->sc_hwmtx);
/* Loop over until we are full, or no data is available */
while (ar933x_rxready(bas)) {
if (uart_rx_full(sc)) {
sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN;
break;
}
/* Read the top of the RX FIFO */
xc = ar933x_getreg(bas, AR933X_UART_DATA_REG) & 0xff;
/* Remove that entry from said RX FIFO */
ar933x_setreg(bas, AR933X_UART_DATA_REG,
AR933X_UART_DATA_RX_CSR);
uart_barrier(bas);
/* XXX frame, parity error */
uart_rx_put(sc, xc);
}
/*
* XXX TODO: Discard everything left in the Rx FIFO?
* XXX only if we've hit an overrun condition?
*/
uart_unlock(sc->sc_hwmtx);
return (0);
}
static int
ar933x_bus_setsig(struct uart_softc *sc, int sig)
{
#if 0
struct ar933x_softc *ns8250 = (struct ar933x_softc*)sc;
struct uart_bas *bas;
uint32_t new, old;
bas = &sc->sc_bas;
do {
old = sc->sc_hwsig;
new = old;
if (sig & SER_DDTR) {
SIGCHG(sig & SER_DTR, new, SER_DTR,
SER_DDTR);
}
if (sig & SER_DRTS) {
SIGCHG(sig & SER_RTS, new, SER_RTS,
SER_DRTS);
}
} while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
uart_lock(sc->sc_hwmtx);
ns8250->mcr &= ~(MCR_DTR|MCR_RTS);
if (new & SER_DTR)
ns8250->mcr |= MCR_DTR;
if (new & SER_RTS)
ns8250->mcr |= MCR_RTS;
uart_setreg(bas, REG_MCR, ns8250->mcr);
uart_barrier(bas);
uart_unlock(sc->sc_hwmtx);
#endif
return (0);
}
/*
* Write the current transmit buffer to the TX FIFO.
*
* Unfortunately the FreeBSD uart device has no concept of
* partial UART writes - it expects that the whole buffer
* is written to the hardware. Thus for now, this will wait for
* the FIFO to finish draining before it pushes more frames into it.
*
* If non-blocking operation is truely needed here, either
* the FreeBSD uart device will need to handle partial writes
* in xxx_bus_transmit(), or we'll need to do TX FIFO buffering
* of our own here.
*/
static int
ar933x_bus_transmit(struct uart_softc *sc)
{
struct uart_bas *bas = &sc->sc_bas;
struct ar933x_softc *u = (struct ar933x_softc *)sc;
int i;
uart_lock(sc->sc_hwmtx);
/* Wait for the FIFO to be clear - see above */
while (ar933x_getreg(bas, AR933X_UART_CS_REG) &
AR933X_UART_CS_TX_BUSY)
;
/*
* Write some data!
*/
for (i = 0; i < sc->sc_txdatasz; i++) {
/* Write the TX data */
ar933x_setreg(bas, AR933X_UART_DATA_REG,
(sc->sc_txbuf[i] & 0xff) | AR933X_UART_DATA_TX_CSR);
uart_barrier(bas);
}
/*
* Now that we're transmitting, get interrupt notification
* when the FIFO is (almost) empty - see above.
*/
u->u_ier |= AR933X_UART_INT_TX_EMPTY;
ar933x_setreg(bas, AR933X_UART_INT_EN_REG, u->u_ier);
uart_barrier(bas);
/*
* Inform the upper layer that we are presently transmitting
* data to the hardware; this will be cleared when the
* TXIDLE interrupt occurs.
*/
sc->sc_txbusy = 1;
uart_unlock(sc->sc_hwmtx);
return (0);
}
static void
ar933x_bus_grab(struct uart_softc *sc)
{
struct uart_bas *bas = &sc->sc_bas;
uint32_t reg;
/* Disable the host interrupt now */
uart_lock(sc->sc_hwmtx);
reg = ar933x_getreg(bas, AR933X_UART_CS_REG);
reg &= ~AR933X_UART_CS_HOST_INT_EN;
ar933x_setreg(bas, AR933X_UART_CS_REG, reg);
uart_unlock(sc->sc_hwmtx);
}
static void
ar933x_bus_ungrab(struct uart_softc *sc)
{
struct uart_bas *bas = &sc->sc_bas;
uint32_t reg;
/* Enable the host interrupt now */
uart_lock(sc->sc_hwmtx);
reg = ar933x_getreg(bas, AR933X_UART_CS_REG);
reg |= AR933X_UART_CS_HOST_INT_EN;
ar933x_setreg(bas, AR933X_UART_CS_REG, reg);
uart_unlock(sc->sc_hwmtx);
}

View File

@ -1,35 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2013 Adrian Chadd <adrian@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef __UART_DEV_AR933X__
#define __UART_DEV_AR933X__
extern struct uart_class uart_ar933x_class;
#endif

View File

@ -1,235 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2019 Ruslan Bukin <br@bsdpad.com>
*
* This software was developed by SRI International and the University of
* Cambridge Computer Laboratory (Department of Computer Science and
* Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the
* DARPA SSITH research programme.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/malloc.h>
#include <sys/rman.h>
#include <sys/timeet.h>
#include <sys/timetc.h>
#include <sys/conf.h>
#include <sys/uio.h>
#include <sys/endian.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#include <machine/cache.h>
#include <machine/bus.h>
#include <machine/cpu.h>
#include <machine/intr.h>
#include <dev/xdma/xdma.h>
#include "xdma_if.h"
#define IOMMU_INVALIDATE 0x00
#define IOMMU_SET_BASE 0x08
struct beri_iommu_softc {
struct resource *res[1];
device_t dev;
bus_space_tag_t bst_data;
bus_space_handle_t bsh_data;
uint32_t offs;
};
static struct resource_spec beri_iommu_spec[] = {
{ SYS_RES_MEMORY, 0, RF_ACTIVE },
{ -1, 0 }
};
static void
beri_iommu_invalidate(struct beri_iommu_softc *sc, vm_offset_t addr)
{
bus_write_8(sc->res[0], IOMMU_INVALIDATE, htole64(addr));
}
static void
beri_iommu_set_base(struct beri_iommu_softc *sc, vm_offset_t addr)
{
bus_write_8(sc->res[0], IOMMU_SET_BASE, htole64(addr));
}
static int
beri_iommu_release(device_t dev, struct xdma_iommu *xio)
{
struct beri_iommu_softc *sc;
sc = device_get_softc(dev);
beri_iommu_set_base(sc, 0);
return (0);
}
static int
beri_iommu_init(device_t dev, struct xdma_iommu *xio)
{
struct beri_iommu_softc *sc;
sc = device_get_softc(dev);
beri_iommu_set_base(sc, (uintptr_t)xio->p.pm_segtab);
return (0);
}
static int
beri_iommu_remove(device_t dev, struct xdma_iommu *xio, vm_offset_t va)
{
struct beri_iommu_softc *sc;
sc = device_get_softc(dev);
beri_iommu_invalidate(sc, va);
return (0);
}
static int
beri_iommu_enter(device_t dev, struct xdma_iommu *xio, vm_offset_t va,
vm_paddr_t pa)
{
struct beri_iommu_softc *sc;
pt_entry_t opte, npte;
pt_entry_t *pte;
pmap_t p;
sc = device_get_softc(dev);
p = &xio->p;
pte = pmap_pte(p, va);
if (pte == NULL)
panic("pte is NULL\n");
/* Make pte uncacheable. */
opte = *pte;
npte = opte & ~PTE_C_MASK;
npte |= PTE_C(VM_MEMATTR_UNCACHEABLE);
*pte = npte;
/* Write back, invalidate pte. */
mips_dcache_wbinv_range((vm_offset_t)pte, sizeof(vm_offset_t));
/* Invalidate the entry. */
if (pte_test(&opte, PTE_V) && opte != npte)
beri_iommu_invalidate(sc, va);
return (0);
}
static int
beri_iommu_probe(device_t dev)
{
if (!ofw_bus_status_okay(dev))
return (ENXIO);
if (!ofw_bus_is_compatible(dev, "beri,iommu"))
return (ENXIO);
device_set_desc(dev, "BERI IOMMU");
return (BUS_PROBE_DEFAULT);
}
static int
beri_iommu_attach(device_t dev)
{
struct beri_iommu_softc *sc;
phandle_t xref, node;
sc = device_get_softc(dev);
sc->dev = dev;
if (bus_alloc_resources(dev, beri_iommu_spec, sc->res)) {
device_printf(dev, "could not allocate resources\n");
return (ENXIO);
}
/* Memory interface */
sc->bst_data = rman_get_bustag(sc->res[0]);
sc->bsh_data = rman_get_bushandle(sc->res[0]);
node = ofw_bus_get_node(dev);
xref = OF_xref_from_node(node);
OF_device_register_xref(xref, dev);
return (0);
}
static int
beri_iommu_detach(device_t dev)
{
struct beri_iommu_softc *sc;
sc = device_get_softc(dev);
bus_release_resources(dev, beri_iommu_spec, sc->res);
return (0);
}
static device_method_t beri_iommu_methods[] = {
/* xDMA IOMMU interface */
DEVMETHOD(xdma_iommu_init, beri_iommu_init),
DEVMETHOD(xdma_iommu_release, beri_iommu_release),
DEVMETHOD(xdma_iommu_enter, beri_iommu_enter),
DEVMETHOD(xdma_iommu_remove, beri_iommu_remove),
/* Device interface */
DEVMETHOD(device_probe, beri_iommu_probe),
DEVMETHOD(device_attach, beri_iommu_attach),
DEVMETHOD(device_detach, beri_iommu_detach),
{ 0, 0 }
};
static driver_t beri_iommu_driver = {
"beri_iommu",
beri_iommu_methods,
sizeof(struct beri_iommu_softc),
};
static devclass_t beri_iommu_devclass;
DRIVER_MODULE(beri_iommu, simplebus, beri_iommu_driver,
beri_iommu_devclass, 0, 0);

View File

@ -1,279 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2006 Wojciech A. Koszek <wkoszek@FreeBSD.org>
* Copyright (c) 2012-2014 Robert N. M. Watson
* All rights reserved.
*
* This software was developed by SRI International and the University of
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
* ("CTSRD"), as part of the DARPA CRASH research programme.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_ddb.h"
#include "opt_platform.h"
#include <sys/param.h>
#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/imgact.h>
#include <sys/bio.h>
#include <sys/buf.h>
#include <sys/bus.h>
#include <sys/cpu.h>
#include <sys/cons.h>
#include <sys/exec.h>
#include <sys/linker.h>
#include <sys/ucontext.h>
#include <sys/proc.h>
#include <sys/kdb.h>
#include <sys/ptrace.h>
#include <sys/reboot.h>
#include <sys/signalvar.h>
#include <sys/sysent.h>
#include <sys/sysproto.h>
#include <sys/user.h>
#ifdef FDT
#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_subr.h>
#endif
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_object.h>
#include <vm/vm_page.h>
#include <vm/vm_phys.h>
#include <vm/vm_dumpset.h>
#include <machine/bootinfo.h>
#include <machine/clock.h>
#include <machine/cpu.h>
#include <machine/cpuregs.h>
#include <machine/hwfunc.h>
#include <machine/md_var.h>
#include <machine/metadata.h>
#include <machine/pmap.h>
#include <machine/trap.h>
extern int *edata;
extern int *end;
void
platform_cpu_init()
{
/* Nothing special */
}
static void
mips_init(void)
{
int i;
#ifdef FDT
struct mem_region mr[FDT_MEM_REGIONS];
uint64_t val;
int mr_cnt;
int j;
#endif
for (i = 0; i < 10; i++) {
phys_avail[i] = 0;
}
/* phys_avail regions are in bytes */
phys_avail[0] = MIPS_KSEG0_TO_PHYS(kernel_kseg0_end);
phys_avail[1] = ctob(realmem);
dump_avail[0] = phys_avail[0];
dump_avail[1] = phys_avail[1];
physmem = realmem;
#ifdef FDT
if (fdt_get_mem_regions(mr, &mr_cnt, &val) == 0) {
physmem = btoc(val);
KASSERT((phys_avail[0] >= mr[0].mr_start) && \
(phys_avail[0] < (mr[0].mr_start + mr[0].mr_size)),
("First region is not within FDT memory range"));
/* Limit size of the first region */
phys_avail[1] = (mr[0].mr_start + MIN(mr[0].mr_size, ctob(realmem)));
dump_avail[1] = phys_avail[1];
/* Add the rest of regions */
for (i = 1, j = 2; i < mr_cnt; i++, j+=2) {
phys_avail[j] = mr[i].mr_start;
phys_avail[j+1] = (mr[i].mr_start + mr[i].mr_size);
dump_avail[j] = phys_avail[j];
dump_avail[j+1] = phys_avail[j+1];
}
}
#endif
init_param1();
init_param2(physmem);
mips_cpu_init();
pmap_bootstrap();
mips_proc0_init();
mutex_init();
kdb_init();
#ifdef KDB
if (boothowto & RB_KDB)
kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger");
#endif
}
/*
* Perform a board-level soft-reset.
*/
void
platform_reset(void)
{
/* XXX SMP will likely require us to do more. */
__asm__ __volatile__(
"mfc0 $k0, $12\n\t"
"li $k1, 0x00100000\n\t"
"or $k0, $k0, $k1\n\t"
"mtc0 $k0, $12\n");
for( ; ; )
__asm__ __volatile("wait");
}
void
platform_start(__register_t a0, __register_t a1, __register_t a2,
__register_t a3)
{
struct bootinfo *bootinfop;
vm_offset_t kernend;
uint64_t platform_counter_freq;
int argc = a0;
char **argv = (char **)a1;
char **envp = (char **)a2;
long memsize;
#ifdef FDT
vm_offset_t dtbp;
void *kmdp;
#endif
int i;
/* clear the BSS and SBSS segments */
kernend = (vm_offset_t)&end;
memset(&edata, 0, kernend - (vm_offset_t)(&edata));
mips_postboot_fixup();
mips_pcpu0_init();
/*
* Over time, we've changed out boot-time binary interface for the
* kernel. Miniboot simply provides a 'memsize' in a3, whereas the
* FreeBSD boot loader provides a 'bootinfo *' in a3. While slightly
* grody, we support both here by detecting 'pointer-like' values in
* a3 and assuming physical memory can never be that back.
*
* XXXRW: Pull more values than memsize out of bootinfop -- e.g.,
* module information.
*/
if (a3 >= 0x9800000000000000ULL) {
bootinfop = (void *)a3;
memsize = bootinfop->bi_memsize;
preload_metadata = (caddr_t)bootinfop->bi_modulep;
} else {
bootinfop = NULL;
memsize = a3;
}
#ifdef FDT
/*
* Find the dtb passed in by the boot loader (currently fictional).
*/
kmdp = preload_search_by_type("elf kernel");
dtbp = MD_FETCH(kmdp, MODINFOMD_DTBP, vm_offset_t);
#if defined(FDT_DTB_STATIC)
/*
* In case the device tree blob was not retrieved (from metadata) try
* to use the statically embedded one.
*/
if (dtbp == (vm_offset_t)NULL)
dtbp = (vm_offset_t)&fdt_static_dtb;
#else
#error "Non-static FDT not yet supported on BERI"
#endif
if (OF_install(OFW_FDT, 0) == FALSE)
while (1);
if (OF_init((void *)dtbp) != 0)
while (1);
/*
* Configure more boot-time parameters passed in by loader.
*/
boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int);
init_static_kenv(MD_FETCH(kmdp, MODINFOMD_ENVP, char *), 0);
/*
* Get bootargs from FDT if specified.
*/
ofw_parse_bootargs();
#endif
/*
* XXXRW: We have no way to compare wallclock time to cycle rate on
* BERI, so for now assume we run at the MALTA default (100MHz).
*/
platform_counter_freq = MIPS_DEFAULT_HZ;
mips_timer_early_init(platform_counter_freq);
cninit();
printf("entry: platform_start()\n");
bootverbose = 1;
if (bootverbose) {
printf("cmd line: ");
for (i = 0; i < argc; i++)
printf("%s ", argv[i]);
printf("\n");
printf("envp:\n");
for (i = 0; envp[i]; i += 2)
printf("\t%s = %s\n", envp[i], envp[i+1]);
if (bootinfop != NULL)
printf("bootinfo found at %p\n", bootinfop);
printf("memsize = %p\n", (void *)memsize);
}
realmem = btoc(memsize);
mips_init();
mips_timer_init_params(platform_counter_freq, 0);
}

View File

@ -1,308 +0,0 @@
/*-
* Copyright (c) 2017 Ruslan Bukin <br@bsdpad.com>
* Copyright (c) 2012-2015 Robert N. M. Watson
* Copyright (c) 2013 SRI International
* All rights reserved.
*
* This software was developed by SRI International and the University of
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
* ("CTSRD"), as part of the DARPA CRASH research programme.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/smp.h>
#include <machine/hwfunc.h>
#include <machine/smp.h>
#include <mips/beri/beri_mp.h>
#include <dev/fdt/fdt_common.h>
struct spin_entry {
uint64_t entry_addr;
uint64_t a0;
uint32_t rsvd1;
uint32_t pir;
uint64_t rsvd2;
};
static phandle_t cpu_of_nodes[MAXCPU];
static device_t picmap[MAXCPU];
int
platform_processor_id(void)
{
int cpu;
cpu = beri_get_cpu();
return (cpu);
}
void
platform_cpu_mask(cpuset_t *mask)
{
int ncores, ncpus, nthreads;
phandle_t cpus, cpu;
pcell_t reg;
char prop[16];
struct spin_entry *se;
ncores = beri_get_ncores();
nthreads = beri_get_nthreads();
KASSERT(ncores <= 0x10000, ("%s: too many cores %d", __func__, ncores));
KASSERT(nthreads <= 0x10000, ("%s: too many threads %d", __func__,
nthreads));
KASSERT(ncores < 0xffff || nthreads < 0xffff,
("%s: cores x thread (%d x %d) would overflow", __func__, ncores,
nthreads));
ncpus = ncores * nthreads;
if (MAXCPU > 1 && ncpus > MAXCPU)
printf("%s: Hardware supports more CPUs (%d) than kernel (%d)\n",
__func__, ncpus, MAXCPU);
printf("%s: hardware has %d cores with %d threads each\n", __func__,
ncores, nthreads);
if ((cpus = OF_finddevice("/cpus")) <= 0) {
printf("%s: no \"/cpus\" device found in FDT\n", __func__);
goto error;
}
if ((cpu = OF_child(cpus)) <= 0) {
printf("%s: no children of \"/cpus\" found in FDT\n", __func__);
goto error;
}
CPU_ZERO(mask);
do {
if (OF_getprop(cpu, "reg", &reg, sizeof(reg)) <= 0) {
printf("%s: cpu device with no reg property\n",
__func__);
goto error;
}
if (reg > MAXCPU) {
printf("%s: cpu ID too large (%d > %d)\n", __func__,
reg, MAXCPU);
continue;
}
cpu_of_nodes[reg] = cpu;
if (reg != 0) {
if (OF_getprop(cpu, "enable-method", &prop,
sizeof(prop)) <= 0 && OF_getprop(OF_parent(cpu),
"enable-method", &prop, sizeof(prop)) <= 0) {
printf("%s: CPU %d has no enable-method "
"property\n", __func__, reg);
continue;
}
if (strcmp("spin-table", prop) != 0) {
printf("%s: CPU %d enable-method is '%s' not "
"'spin-table'\n", __func__, reg, prop);
continue;
}
if (OF_getprop(cpu, "cpu-release-addr", &se,
sizeof(se)) <= 0) {
printf("%s: CPU %d has missing or invalid "
"cpu-release-addr\n", __func__, reg);
continue;
}
if (se->entry_addr != 1) {
printf("%s: CPU %d has uninitialized spin "
"entry\n", __func__, reg);
continue;
}
}
CPU_SET(reg, mask);
} while ((cpu = OF_peer(cpu)) > 0);
return;
error:
/*
* If we run into any problems determining the CPU layout,
* fall back to UP.
*
* XXX: panic instead?
*/
CPU_ZERO(mask);
CPU_SET(0, mask);
}
void
platform_init_secondary(int cpuid)
{
device_t ic;
int ipi;
ipi = platform_ipi_hardintr_num();
ic = devclass_get_device(devclass_find("beripic"), cpuid);
picmap[cpuid] = ic;
beripic_setup_ipi(ic, cpuid, ipi);
/* Unmask the interrupt */
if (cpuid != 0) {
mips_wr_status(mips_rd_status() | (((1 << ipi) << 8) << 2));
}
}
void
platform_ipi_send(int cpuid)
{
mips_sync(); /* Ordering, liveness. */
beripic_send_ipi(picmap[cpuid], cpuid);
}
void
platform_ipi_clear(void)
{
int cpuid;
cpuid = platform_processor_id();
beripic_clear_ipi(picmap[cpuid], cpuid);
}
/*
* XXXBED: Set via FDT?
*/
int
platform_ipi_hardintr_num(void)
{
return (4);
}
int
platform_ipi_softintr_num(void)
{
return (-1);
}
/*
* XXXBED: Fine for MT, will need something better for multi-core.
*/
struct cpu_group *
platform_smp_topo(void)
{
return (smp_topo_none());
}
void
platform_init_ap(int cpuid)
{
uint32_t status;
u_int clock_int_mask;
KASSERT(cpuid < MAXCPU, ("%s: invalid CPU id %d", __func__, cpuid));
/* Make sure coprocessors are enabled. */
status = mips_rd_status();
status |= (MIPS_SR_COP_0_BIT | MIPS_SR_COP_1_BIT);
#if defined(CPU_CHERI)
status |= MIPS_SR_COP_2_BIT;
#endif
mips_wr_status(status);
#if 0
register_t hwrena;
/* Enable HDWRD instruction in userspace. Also enables statcounters. */
hwrena = mips_rd_hwrena();
hwrena |= (MIPS_HWRENA_CC | MIPS_HWRENA_CCRES | MIPS_HWRENA_CPUNUM |
MIPS_HWRENA_BERI_STATCOUNTERS_MASK);
mips_wr_hwrena(hwrena);
#endif
/*
* Enable per-thread timer.
*/
clock_int_mask = hard_int_mask(5);
set_intr_mask(clock_int_mask);
}
/*
* BERI startup conforms to the spin-table start method defined in the
* ePAPR 1.0 spec. The initial spin waiting for an address is started
* by the CPU firmware.
*/
int
platform_start_ap(int cpuid)
{
phandle_t cpu;
char prop[16];
struct spin_entry *se;
KASSERT(cpuid != 0, ("%s: can't start CPU 0!\n", __func__));
KASSERT((cpuid > 0 && cpuid < MAXCPU),
("%s: invalid CPU id %d", __func__, cpuid));
cpu = cpu_of_nodes[cpuid];
if (OF_getprop(cpu, "status", &prop, sizeof(prop)) <= 0) {
if (bootverbose)
printf("%s: CPU %d has no status property, "
"trying parent\n", __func__, cpuid);
if (OF_getprop(OF_parent(cpu), "status", &prop,
sizeof(prop)) <= 0)
panic("%s: CPU %d has no status property", __func__,
cpuid);
}
if (strcmp("disabled", prop) != 0)
panic("%s: CPU %d status is '%s' not 'disabled'",
__func__, cpuid, prop);
if (OF_getprop(cpu, "enable-method", &prop, sizeof(prop)) <= 0) {
if (bootverbose)
printf("%s: CPU %d has no enable-method, "
"trying parent\n", __func__, cpuid);
if (OF_getprop(OF_parent(cpu), "enable-method", &prop,
sizeof(prop)) <= 0)
panic("%s: CPU %d has no enable-method property",
__func__, cpuid);
}
if (strcmp("spin-table", prop) != 0)
panic("%s: CPU %d enable-method is '%s' not "
"'spin-table'", __func__, cpuid, prop);
if (OF_getprop(cpu, "cpu-release-addr", &se, sizeof(se)) <= 0)
panic("%s: CPU %d has missing or invalid cpu-release-addr",
__func__, cpuid);
se->pir = cpuid;
if (bootverbose)
printf("%s: writing %p to %p\n", __func__, mpentry,
&se->entry_addr);
mips_sync(); /* Ordering. */
se->entry_addr = (intptr_t)mpentry;
mips_sync(); /* Liveness. */
return (0);
}

View File

@ -1,85 +0,0 @@
/*-
* Copyright (c) 2014 SRI International
* All rights reserved.
*
* This software was developed by SRI International and the University of
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-11-C-0249)
* ("MRC2"), as part of the DARPA MRC research programme.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
static inline int
beri_get_core(void)
{
uint32_t cinfo;
cinfo = mips_rd_cinfo();
return (cinfo & 0xffff);
}
static inline int
beri_get_ncores(void)
{
uint32_t cinfo;
cinfo = mips_rd_cinfo();
return ((cinfo >> 16) + 1);
}
static inline int
beri_get_thread(void)
{
uint32_t tinfo;
tinfo = mips_rd_tinfo();
return (tinfo & 0xffff);
}
static inline int
beri_get_nthreads(void)
{
uint32_t tinfo;
tinfo = mips_rd_tinfo();
return ((tinfo >> 16) + 1);
}
static inline int
beri_get_cpu(void)
{
return ((beri_get_core() * beri_get_nthreads()) + beri_get_thread());
}
static inline int
beri_get_ncpus(void)
{
return(beri_get_ncores() * beri_get_nthreads());
}
void beripic_setup_ipi(device_t dev, u_int tid, u_int ipi_irq);
void beripic_send_ipi(device_t dev, u_int tid);
void beripic_clear_ipi(device_t dev, u_int tid);

View File

@ -1,370 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2017 Ruslan Bukin <br@bsdpad.com>
* Copyright (c) 2013 SRI International
* All rights reserved.
*
* This software was developed by SRI International and the University of
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
* ("CTSRD"), as part of the DARPA CRASH research programme.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "opt_platform.h"
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/mutex.h>
#include <sys/proc.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <machine/bus.h>
#include <machine/intr.h>
#ifdef SMP
#include <mips/beri/beri_mp.h>
#endif
#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#include "pic_if.h"
#define BP_NUM_HARD_IRQS 5
#define BP_NUM_IRQS 32
/* We use hard irqs 15-31 as soft */
#define BP_FIRST_SOFT 16
#define BP_CFG_IRQ_S 0
#define BP_CFG_IRQ_M (0xf << BP_CFG_IRQ_S)
#define BP_CFG_TID_S 8
#define BP_CFG_TID_M (0x7FFFFF << BP_CFG_TID_S)
#define BP_CFG_ENABLE (1 << 31)
enum {
BP_CFG,
BP_IP_READ,
BP_IP_SET,
BP_IP_CLEAR
};
struct beripic_softc;
struct beri_pic_isrc {
struct intr_irqsrc isrc;
u_int irq;
uint32_t mips_hard_irq;
};
struct hirq {
uint32_t irq;
struct beripic_softc *sc;
};
struct beripic_softc {
device_t dev;
uint32_t nirqs;
struct beri_pic_isrc irqs[BP_NUM_IRQS];
struct resource *res[4 + BP_NUM_HARD_IRQS];
void *ih[BP_NUM_HARD_IRQS];
struct hirq hirq[BP_NUM_HARD_IRQS];
uint8_t mips_hard_irq_idx;
};
static struct resource_spec beri_pic_spec[] = {
{ SYS_RES_MEMORY, 0, RF_ACTIVE },
{ SYS_RES_MEMORY, 1, RF_ACTIVE },
{ SYS_RES_MEMORY, 2, RF_ACTIVE },
{ SYS_RES_MEMORY, 3, RF_ACTIVE },
{ SYS_RES_IRQ, 0, RF_ACTIVE },
{ SYS_RES_IRQ, 1, RF_ACTIVE },
{ SYS_RES_IRQ, 2, RF_ACTIVE },
{ SYS_RES_IRQ, 3, RF_ACTIVE },
{ SYS_RES_IRQ, 4, RF_ACTIVE },
{ -1, 0 }
};
static int
beri_pic_intr(void *arg)
{
struct beripic_softc *sc;
struct intr_irqsrc *isrc;
struct hirq *h;
uint64_t intr;
uint64_t reg;
int i;
h = arg;
sc = h->sc;
intr = bus_read_8(sc->res[BP_IP_READ], 0);
while ((i = fls(intr)) != 0) {
i--;
intr &= ~(1u << i);
isrc = &sc->irqs[i].isrc;
reg = bus_read_8(sc->res[BP_CFG], i * 8);
if ((reg & BP_CFG_IRQ_M) != h->irq) {
continue;
}
if ((reg & (BP_CFG_ENABLE)) == 0) {
continue;
}
if (intr_isrc_dispatch(isrc, curthread->td_intr_frame) != 0) {
device_printf(sc->dev, "Stray interrupt %u detected\n", i);
}
bus_write_8(sc->res[BP_IP_CLEAR], 0, (1 << i));
}
return (FILTER_HANDLED);
}
static int
beripic_probe(device_t dev)
{
if (!ofw_bus_status_okay(dev))
return (ENXIO);
if (!ofw_bus_is_compatible(dev, "sri-cambridge,beri-pic"))
return (ENXIO);
device_set_desc(dev, "BERI Programmable Interrupt Controller");
return (BUS_PROBE_DEFAULT);
}
static int
beripic_attach(device_t dev)
{
struct beripic_softc *sc;
struct beri_pic_isrc *pic_isrc;
const char *name;
struct intr_irqsrc *isrc;
intptr_t xref;
uint32_t unit;
int err;
int i;
sc = device_get_softc(dev);
sc->dev = dev;
if (bus_alloc_resources(dev, beri_pic_spec, sc->res)) {
device_printf(dev, "could not allocate resources\n");
return (ENXIO);
}
xref = OF_xref_from_node(ofw_bus_get_node(dev));
name = device_get_nameunit(dev);
unit = device_get_unit(dev);
sc->nirqs = BP_NUM_IRQS;
for (i = 0; i < sc->nirqs; i++) {
sc->irqs[i].irq = i;
isrc = &sc->irqs[i].isrc;
/* Assign mips hard irq number. */
pic_isrc = (struct beri_pic_isrc *)isrc;
pic_isrc->mips_hard_irq = sc->mips_hard_irq_idx++;
/* Last IRQ is used for IPIs. */
if (sc->mips_hard_irq_idx >= (BP_NUM_HARD_IRQS - 1)) {
sc->mips_hard_irq_idx = 0;
}
err = intr_isrc_register(isrc, sc->dev,
0, "pic%d,%d", unit, i);
bus_write_8(sc->res[BP_CFG], i * 8, 0);
}
/*
* Now, when everything is initialized, it's right time to
* register interrupt controller to interrupt framefork.
*/
if (intr_pic_register(dev, xref) == NULL) {
device_printf(dev, "could not register PIC\n");
return (ENXIO);
}
/* Last IRQ is used for IPIs. */
for (i = 0; i < (BP_NUM_HARD_IRQS - 1); i++) {
sc->hirq[i].sc = sc;
sc->hirq[i].irq = i;
if (bus_setup_intr(dev, sc->res[4+i], INTR_TYPE_CLK,
beri_pic_intr, NULL, &sc->hirq[i], sc->ih[i])) {
device_printf(dev, "could not setup irq handler\n");
intr_pic_deregister(dev, xref);
return (ENXIO);
}
}
return (0);
}
static void
beri_pic_enable_intr(device_t dev, struct intr_irqsrc *isrc)
{
struct beri_pic_isrc *pic_isrc;
struct beripic_softc *sc;
uint64_t reg;
sc = device_get_softc(dev);
pic_isrc = (struct beri_pic_isrc *)isrc;
reg = BP_CFG_ENABLE;
reg |= (pic_isrc->mips_hard_irq << BP_CFG_IRQ_S);
bus_write_8(sc->res[BP_CFG], pic_isrc->irq * 8, reg);
}
static void
beri_pic_disable_intr(device_t dev, struct intr_irqsrc *isrc)
{
struct beri_pic_isrc *pic_isrc;
struct beripic_softc *sc;
uint64_t reg;
sc = device_get_softc(dev);
pic_isrc = (struct beri_pic_isrc *)isrc;
reg = bus_read_8(sc->res[BP_CFG], pic_isrc->irq * 8);
reg &= ~BP_CFG_ENABLE;
bus_write_8(sc->res[BP_CFG], pic_isrc->irq * 8, reg);
}
static int
beri_pic_map_intr(device_t dev, struct intr_map_data *data,
struct intr_irqsrc **isrcp)
{
struct beripic_softc *sc;
struct intr_map_data_fdt *daf;
uint32_t irq;
sc = device_get_softc(dev);
daf = (struct intr_map_data_fdt *)data;
if (data == NULL || data->type != INTR_MAP_DATA_FDT ||
daf->ncells != 1 || daf->cells[0] >= sc->nirqs)
return (EINVAL);
irq = daf->cells[0];
*isrcp = &sc->irqs[irq].isrc;
return (0);
}
static void
beri_pic_post_ithread(device_t dev, struct intr_irqsrc *isrc)
{
beri_pic_enable_intr(dev, isrc);
}
static void
beri_pic_pre_ithread(device_t dev, struct intr_irqsrc *isrc)
{
beri_pic_disable_intr(dev, isrc);
}
#ifdef SMP
void
beripic_setup_ipi(device_t dev, u_int tid, u_int ipi_irq)
{
struct beripic_softc *sc;
uint64_t reg;
sc = device_get_softc(dev);
reg = (BP_CFG_ENABLE);
reg |= (ipi_irq << BP_CFG_IRQ_S);
reg |= (tid << BP_CFG_TID_S);
bus_write_8(sc->res[BP_CFG], ((BP_FIRST_SOFT + tid) * 8), reg);
}
void
beripic_send_ipi(device_t dev, u_int tid)
{
struct beripic_softc *sc;
uint64_t bit;
sc = device_get_softc(dev);
bit = (BP_FIRST_SOFT + tid);
KASSERT(bit < BP_NUM_IRQS, ("tid (%d) to large\n", tid));
bus_write_8(sc->res[BP_IP_SET], 0x0, (1 << bit));
}
void
beripic_clear_ipi(device_t dev, u_int tid)
{
struct beripic_softc *sc;
uint64_t bit;
sc = device_get_softc(dev);
bit = (BP_FIRST_SOFT + tid);
KASSERT(bit < BP_NUM_IRQS, ("tid (%d) to large\n", tid));
bus_write_8(sc->res[BP_IP_CLEAR], 0x0, (1 << bit));
}
#endif
static device_method_t beripic_fdt_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, beripic_probe),
DEVMETHOD(device_attach, beripic_attach),
/* Interrupt controller interface */
DEVMETHOD(pic_enable_intr, beri_pic_enable_intr),
DEVMETHOD(pic_disable_intr, beri_pic_disable_intr),
DEVMETHOD(pic_map_intr, beri_pic_map_intr),
DEVMETHOD(pic_post_ithread, beri_pic_post_ithread),
DEVMETHOD(pic_pre_ithread, beri_pic_pre_ithread),
DEVMETHOD_END
};
devclass_t beripic_devclass;
static driver_t beripic_driver = {
"beripic",
beripic_fdt_methods,
sizeof(struct beripic_softc)
};
EARLY_DRIVER_MODULE(beripic, ofwbus, beripic_driver, beripic_devclass, 0, 0,
BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);

View File

@ -1,27 +0,0 @@
# $FreeBSD$
dev/altera/atse/if_atse.c optional altera_atse
dev/altera/atse/if_atse_fdt.c optional altera_atse fdt
dev/altera/atse/if_atse_nexus.c optional altera_atse
dev/altera/jtag_uart/altera_jtag_uart_cons.c optional altera_jtag_uart
dev/altera/jtag_uart/altera_jtag_uart_tty.c optional altera_jtag_uart
dev/altera/jtag_uart/altera_jtag_uart_fdt.c optional altera_jtag_uart fdt
dev/altera/jtag_uart/altera_jtag_uart_nexus.c optional altera_jtag_uart
dev/beri/virtio/virtio_mmio_platform.c optional virtio_mmio
dev/netfpga10g/nf10bmac/if_nf10bmac_fdt.c optional netfpga10g_nf10bmac fdt
dev/netfpga10g/nf10bmac/if_nf10bmac.c optional netfpga10g_nf10bmac
dev/terasic/de4led/terasic_de4led.c optional terasic_de4led
dev/terasic/de4led/terasic_de4led_fdt.c optional terasic_de4led fdt
dev/terasic/de4led/terasic_de4led_nexus.c optional terasic_de4led
dev/terasic/mtl/terasic_mtl.c optional terasic_mtl
dev/terasic/mtl/terasic_mtl_fdt.c optional terasic_mtl fdt
dev/terasic/mtl/terasic_mtl_nexus.c optional terasic_mtl
dev/terasic/mtl/terasic_mtl_pixel.c optional terasic_mtl
dev/terasic/mtl/terasic_mtl_reg.c optional terasic_mtl
dev/terasic/mtl/terasic_mtl_syscons.c optional terasic_mtl sc
dev/terasic/mtl/terasic_mtl_text.c optional terasic_mtl
dev/terasic/mtl/terasic_mtl_vt.c optional terasic_mtl vt
mips/beri/beri_iommu.c optional xdma
mips/beri/beri_machdep.c standard
mips/beri/beri_mp.c optional smp
mips/beri/beri_pic.c optional fdt
mips/mips/tick.c standard

View File

@ -1,7 +0,0 @@
# $FreeBSD$
files "../beri/files.beri"
cpu CPU_MIPS4KC
options BERI_LARGE_TLB
options PLATFORM_INIT_SECONDARY

View File

@ -1,419 +0,0 @@
/*-
* Copyright (c) 2016 Landon Fuller <landonf@FreeBSD.org>
* Copyright (c) 2017 The FreeBSD Foundation
* All rights reserved.
*
* Portions of this software were developed by Landon Fuller
* 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, 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/bus.h>
#include <sys/module.h>
#include <sys/proc.h>
#include <machine/bus.h>
#include <sys/rman.h>
#include <machine/intr.h>
#include <machine/resource.h>
#include <dev/bhnd/bhnd.h>
#include <dev/bhnd/siba/sibareg.h>
#include "pic_if.h"
#include "bcm_mipsvar.h"
#include "bcm_bmipsreg.h"
/*
* BMIPS32 and BMIPS3300 core driver.
*
* These cores are only found on siba(4) chipsets, allowing
* us to assume the availability of siba interrupt registers.
*/
struct bcm_bmips_softc;
static int bcm_bmips_pic_intr(void *arg);
static void bcm_bmips_mask_irq(struct bcm_bmips_softc *sc, u_int mips_irq,
u_int ivec);
static void bcm_bmips_unmask_irq(struct bcm_bmips_softc *sc, u_int mips_irq,
u_int ivec);
static const struct bhnd_device bcm_bmips_devs[] = {
BHND_DEVICE(BCM, MIPS33, NULL, NULL, BHND_DF_SOC),
BHND_DEVICE_END
};
struct bcm_bmips_softc {
struct bcm_mips_softc bcm_mips; /**< parent softc */
device_t dev;
struct resource *mem; /**< cpu core registers */
int mem_rid;
struct resource *cfg; /**< cpu core's cfg0 register block */
int cfg_rid;
};
#define BCM_BMIPS_NCPU_IRQS 5 /**< MIPS HW IRQs 0-4 are assignable */
#define BCM_BMIPS_TIMER_IRQ 5 /**< MIPS HW IRQ5 is always assigned to the timer */
static int
bcm_bmips_probe(device_t dev)
{
const struct bhnd_device *id;
id = bhnd_device_lookup(dev, bcm_bmips_devs, sizeof(bcm_bmips_devs[0]));
if (id == NULL)
return (ENXIO);
/* Check the chip type; should only be found on siba(4) chipsets */
if (bhnd_get_chipid(dev)->chip_type != BHND_CHIPTYPE_SIBA)
return (ENXIO);
bhnd_set_default_core_desc(dev);
return (BUS_PROBE_DEFAULT);
}
static int
bcm_bmips_attach(device_t dev)
{
struct bcm_bmips_softc *sc;
int error;
sc = device_get_softc(dev);
sc->dev = dev;
/* Allocate our core's register block */
sc->mem_rid = 0;
sc->mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->mem_rid,
RF_ACTIVE);
if (sc->mem == NULL) {
device_printf(dev, "failed to allocate cpu register block\n");
error = ENXIO;
goto failed;
}
/* Determine the resource ID for our siba CFG0 registers */
sc->cfg_rid = bhnd_get_port_rid(dev, BHND_PORT_AGENT, 0, 0);
if (sc->cfg_rid == -1) {
device_printf(dev, "missing required cfg0 register block\n");
error = ENXIO;
goto failed;
}
/* Allocate our CFG0 register block */
sc->cfg = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->cfg_rid,
RF_ACTIVE|RF_SHAREABLE);
if (sc->cfg == NULL) {
device_printf(dev, "failed to allocate cfg0 register block\n");
error = ENXIO;
goto failed;
}
/* Clear interrupt map */
bus_write_4(sc->cfg, SIBA_CFG0_INTVEC, 0x0); /* MIPS IRQ0 */
bus_write_4(sc->cfg, SIBA_CFG0_IPSFLAG, 0x0); /* MIPS IRQ1-4 */
/* Initialize the generic BHND MIPS driver state */
error = bcm_mips_attach(dev, BCM_BMIPS_NCPU_IRQS, BCM_BMIPS_TIMER_IRQ,
bcm_bmips_pic_intr);
if (error)
goto failed;
return (0);
failed:
if (sc->mem != NULL)
bus_release_resource(dev, SYS_RES_MEMORY, sc->mem_rid, sc->mem);
if (sc->cfg != NULL)
bus_release_resource(dev, SYS_RES_MEMORY, sc->cfg_rid, sc->cfg);
return (error);
}
static int
bcm_bmips_detach(device_t dev)
{
struct bcm_bmips_softc *sc;
int error;
sc = device_get_softc(dev);
if ((error = bcm_mips_detach(dev)))
return (error);
bus_release_resource(dev, SYS_RES_MEMORY, sc->mem_rid, sc->mem);
bus_release_resource(dev, SYS_RES_MEMORY, sc->cfg_rid, sc->cfg);
return (0);
}
/* PIC_DISABLE_INTR() */
static void
bcm_bmips_pic_disable_intr(device_t dev, struct intr_irqsrc *irqsrc)
{
struct bcm_bmips_softc *sc;
struct bcm_mips_irqsrc *isrc;
sc = device_get_softc(dev);
isrc = (struct bcm_mips_irqsrc *)irqsrc;
KASSERT(isrc->cpuirq != NULL, ("no assigned MIPS IRQ"));
bcm_bmips_mask_irq(sc, isrc->cpuirq->mips_irq, isrc->ivec);
}
/* PIC_ENABLE_INTR() */
static void
bcm_bmips_pic_enable_intr(device_t dev, struct intr_irqsrc *irqsrc)
{
struct bcm_bmips_softc *sc;
struct bcm_mips_irqsrc *isrc;
sc = device_get_softc(dev);
isrc = (struct bcm_mips_irqsrc *)irqsrc;
KASSERT(isrc->cpuirq != NULL, ("no assigned MIPS IRQ"));
bcm_bmips_unmask_irq(sc, isrc->cpuirq->mips_irq, isrc->ivec);
}
/* PIC_PRE_ITHREAD() */
static void
bcm_bmips_pic_pre_ithread(device_t dev, struct intr_irqsrc *isrc)
{
bcm_bmips_pic_disable_intr(dev, isrc);
}
/* PIC_POST_ITHREAD() */
static void
bcm_bmips_pic_post_ithread(device_t dev, struct intr_irqsrc *isrc)
{
bcm_bmips_pic_enable_intr(dev, isrc);
}
/* PIC_POST_FILTER() */
static void
bcm_bmips_pic_post_filter(device_t dev, struct intr_irqsrc *isrc)
{
}
/**
* Disable routing of backplane interrupt vector @p ivec to MIPS IRQ
* @p mips_irq.
*/
static void
bcm_bmips_mask_irq(struct bcm_bmips_softc *sc, u_int mips_irq, u_int ivec)
{
KASSERT(ivec < SIBA_MAX_INTR, ("invalid sbflag# ivec"));
KASSERT(mips_irq < sc->bcm_mips.num_cpuirqs, ("invalid MIPS IRQ %u",
mips_irq));
if (mips_irq == 0) {
uint32_t sbintvec;
sbintvec = bus_read_4(sc->cfg, SIBA_CFG0_INTVEC);
sbintvec &= ~(1 << ivec);
bus_write_4(sc->cfg, SIBA_CFG0_INTVEC, sbintvec);
} else {
uint32_t ipsflag;
/* Can we route this via ipsflag? */
KASSERT(((1 << ivec) & SIBA_IPS_INT1_MASK) != 0,
("cannot route high sbflag# ivec %u", ivec));
ipsflag = bus_read_4(sc->cfg, SIBA_CFG0_IPSFLAG);
ipsflag &= ~(
((1 << ivec) << SIBA_IPS_INT_SHIFT(mips_irq)) &
SIBA_IPS_INT_MASK(mips_irq));
bus_write_4(sc->cfg, SIBA_CFG0_IPSFLAG, ipsflag);
}
}
/**
* Enable routing of an interrupt.
*/
static void
bcm_bmips_unmask_irq(struct bcm_bmips_softc *sc, u_int mips_irq, u_int ivec)
{
KASSERT(ivec < SIBA_MAX_INTR, ("invalid sbflag# ivec"));
KASSERT(mips_irq < sc->bcm_mips.num_cpuirqs, ("invalid MIPS IRQ %u",
mips_irq));
if (mips_irq == 0) {
uint32_t sbintvec;
sbintvec = bus_read_4(sc->cfg, SIBA_CFG0_INTVEC);
sbintvec |= (1 << ivec);
bus_write_4(sc->cfg, SIBA_CFG0_INTVEC, sbintvec);
} else {
uint32_t ipsflag;
/* Can we route this via ipsflag? */
KASSERT(((1 << ivec) & SIBA_IPS_INT1_MASK) != 0,
("cannot route high sbflag# ivec %u", ivec));
ipsflag = bus_read_4(sc->cfg, SIBA_CFG0_IPSFLAG);
ipsflag |= (ivec << SIBA_IPS_INT_SHIFT(mips_irq)) &
SIBA_IPS_INT_MASK(mips_irq);
bus_write_4(sc->cfg, SIBA_CFG0_IPSFLAG, ipsflag);
}
}
/* our MIPS CPU interrupt filter */
static int
bcm_bmips_pic_intr(void *arg)
{
struct bcm_bmips_softc *sc;
struct bcm_mips_cpuirq *cpuirq;
struct bcm_mips_irqsrc *isrc_solo;
uint32_t sbintvec, sbstatus;
u_int mips_irq, i;
int error;
cpuirq = arg;
sc = (struct bcm_bmips_softc*)cpuirq->sc;
/* Fetch current interrupt state */
sbstatus = bus_read_4(sc->cfg, SIBA_CFG0_FLAGST);
/* Fetch mask of interrupt vectors routed to this MIPS IRQ */
mips_irq = cpuirq->mips_irq;
if (mips_irq == 0) {
sbintvec = bus_read_4(sc->cfg, SIBA_CFG0_INTVEC);
} else {
uint32_t ipsflag;
ipsflag = bus_read_4(sc->cfg, SIBA_CFG0_IPSFLAG);
/* Map to an intvec-compatible representation */
switch (mips_irq) {
case 1:
sbintvec = (ipsflag & SIBA_IPS_INT1_MASK) >>
SIBA_IPS_INT1_SHIFT;
break;
case 2:
sbintvec = (ipsflag & SIBA_IPS_INT2_MASK) >>
SIBA_IPS_INT2_SHIFT;
break;
case 3:
sbintvec = (ipsflag & SIBA_IPS_INT3_MASK) >>
SIBA_IPS_INT3_SHIFT;
break;
case 4:
sbintvec = (ipsflag & SIBA_IPS_INT4_MASK) >>
SIBA_IPS_INT4_SHIFT;
break;
default:
panic("invalid irq %u", mips_irq);
}
}
/* Ignore interrupts not routed to this MIPS IRQ */
sbstatus &= sbintvec;
/* Handle isrc_solo direct dispatch path */
isrc_solo = cpuirq->isrc_solo;
if (isrc_solo != NULL) {
if (sbstatus & BCM_MIPS_IVEC_MASK(isrc_solo)) {
error = intr_isrc_dispatch(&isrc_solo->isrc,
curthread->td_intr_frame);
if (error) {
device_printf(sc->dev, "Stray interrupt %u "
"detected\n", isrc_solo->ivec);
bcm_bmips_pic_disable_intr(sc->dev,
&isrc_solo->isrc);
}
}
sbstatus &= ~(BCM_MIPS_IVEC_MASK(isrc_solo));
if (sbstatus == 0)
return (FILTER_HANDLED);
/* Report and mask additional stray interrupts */
while ((i = fls(sbstatus)) != 0) {
i--; /* Get a 0-offset interrupt. */
sbstatus &= ~(1 << i);
device_printf(sc->dev, "Stray interrupt %u "
"detected\n", i);
bcm_bmips_mask_irq(sc, mips_irq, i);
}
return (FILTER_HANDLED);
}
/* Standard dispatch path */
while ((i = fls(sbstatus)) != 0) {
i--; /* Get a 0-offset interrupt. */
sbstatus &= ~(1 << i);
KASSERT(i < nitems(sc->bcm_mips.isrcs), ("invalid ivec %u", i));
error = intr_isrc_dispatch(&sc->bcm_mips.isrcs[i].isrc,
curthread->td_intr_frame);
if (error) {
device_printf(sc->dev, "Stray interrupt %u detected\n",
i);
bcm_bmips_mask_irq(sc, mips_irq, i);
continue;
}
}
return (FILTER_HANDLED);
}
static device_method_t bcm_bmips_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, bcm_bmips_probe),
DEVMETHOD(device_attach, bcm_bmips_attach),
DEVMETHOD(device_detach, bcm_bmips_detach),
/* Interrupt controller interface */
DEVMETHOD(pic_disable_intr, bcm_bmips_pic_disable_intr),
DEVMETHOD(pic_enable_intr, bcm_bmips_pic_enable_intr),
DEVMETHOD(pic_pre_ithread, bcm_bmips_pic_pre_ithread),
DEVMETHOD(pic_post_ithread, bcm_bmips_pic_post_ithread),
DEVMETHOD(pic_post_filter, bcm_bmips_pic_post_filter),
DEVMETHOD_END
};
static devclass_t bcm_mips_devclass;
DEFINE_CLASS_1(bcm_mips, bcm_bmips_driver, bcm_bmips_methods, sizeof(struct bcm_bmips_softc), bcm_mips_driver);
EARLY_DRIVER_MODULE(bcm_bmips, bhnd, bcm_bmips_driver, bcm_mips_devclass, 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);
MODULE_VERSION(bcm_bmips, 1);
MODULE_DEPEND(bcm_bmips, bhnd, 1, 1, 1);

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