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:
parent
fe532f1a50
commit
c09981f142
@ -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"
|
@ -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}
|
||||
|
@ -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}
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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}
|
||||
|
@ -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
|
||||
|
@ -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 . */
|
||||
}
|
@ -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 . */
|
||||
}
|
@ -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 . */
|
||||
}
|
@ -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 = .;
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
@ -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_ */
|
@ -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);
|
@ -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_ */
|
@ -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,
|
||||
};
|
@ -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
|
@ -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_ */
|
@ -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,
|
||||
};
|
@ -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
|
@ -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
|
@ -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);
|
@ -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__ */
|
@ -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
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
@ -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
|
@ -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);
|
@ -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);
|
@ -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_ */
|
@ -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 */
|
@ -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
@ -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__ */
|
@ -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);
|
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
@ -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__ */
|
@ -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);
|
@ -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,
|
||||
};
|
@ -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
|
@ -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
|
@ -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);
|
@ -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);
|
||||
}
|
@ -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__ */
|
@ -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);
|
@ -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__ */
|
@ -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);
|
||||
}
|
@ -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__ */
|
@ -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
|
||||
}
|
@ -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);
|
@ -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);
|
@ -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));
|
||||
}
|
@ -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__ */
|
@ -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;
|
||||
}
|
@ -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
|
@ -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);
|
@ -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);
|
@ -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_ */
|
@ -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
|
||||
};
|
@ -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
|
@ -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);
|
@ -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
|
@ -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,
|
||||
};
|
@ -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
|
@ -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
|
@ -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,
|
||||
};
|
@ -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
|
@ -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__ */
|
@ -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__ */
|
@ -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,
|
||||
};
|
@ -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
|
@ -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__ */
|
@ -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__ */
|
@ -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
@ -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__ */
|
@ -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);
|
@ -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__ */
|
@ -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,
|
||||
};
|
@ -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
|
@ -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__ */
|
@ -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,
|
||||
};
|
@ -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
|
@ -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);
|
@ -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__ */
|
@ -1,8 +0,0 @@
|
||||
# $FreeBSD$
|
||||
#
|
||||
# standard config for all ar71xx based kernels.
|
||||
|
||||
files "../atheros/files.ar71xx"
|
||||
|
||||
machine mips mips
|
||||
cpu CPU_MIPS4KC
|
@ -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);
|
@ -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);
|
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
@ -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
|
@ -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);
|
@ -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);
|
||||
}
|
@ -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", ®, 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);
|
||||
}
|
@ -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);
|
@ -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);
|
@ -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
|
@ -1,7 +0,0 @@
|
||||
# $FreeBSD$
|
||||
files "../beri/files.beri"
|
||||
|
||||
cpu CPU_MIPS4KC
|
||||
|
||||
options BERI_LARGE_TLB
|
||||
options PLATFORM_INIT_SECONDARY
|
@ -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
Loading…
Reference in New Issue
Block a user