This revision adds the following parts:
- machine dependent low level init code - SoC clocks detection and some utility functions - Common interface to read/write/modify SoC system control registers, used by some of the other drivers and utility functions - simple FDT resets support, based on the fdt_clock implementation already in the tree. For the moment resets and clocks are managed using these implementations. I am planning to port those to the new extres framework in the future, but currently I simply don't have time to do this part too. Approved by: adrian (mentor) Sponsored by: Smartcom - Bulgaria AD Differential Revision: https://reviews.freebsd.org/D5826
This commit is contained in:
parent
55275a5bbe
commit
10998af48d
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=297666
125
sys/mips/mediatek/fdt_reset.c
Normal file
125
sys/mips/mediatek/fdt_reset.c
Normal file
@ -0,0 +1,125 @@
|
||||
/*-
|
||||
* Copyright (c) 2016 Stanislav Galabov
|
||||
* Copyright (c) 2014 Ian Lepore <ian@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$
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <dev/ofw/ofw_bus.h>
|
||||
#include <dev/ofw/ofw_bus_subr.h>
|
||||
|
||||
#include "fdt_reset_if.h"
|
||||
#include <mips/mediatek/fdt_reset.h>
|
||||
|
||||
/*
|
||||
* Loop through all the tuples in the resets= property for a device, asserting
|
||||
* or deasserting each reset.
|
||||
*
|
||||
* Be liberal about errors for now: warn about a failure to (de)assert but keep
|
||||
* trying with any other resets in the list. Return ENXIO if any errors were
|
||||
* found, and let the caller decide whether the problem is fatal.
|
||||
*/
|
||||
static int
|
||||
assert_deassert_all(device_t consumer, boolean_t assert)
|
||||
{
|
||||
phandle_t rnode;
|
||||
device_t resetdev;
|
||||
int resetnum, err, i, ncells;
|
||||
uint32_t *resets;
|
||||
boolean_t anyerrors;
|
||||
|
||||
rnode = ofw_bus_get_node(consumer);
|
||||
ncells = OF_getencprop_alloc(rnode, "resets", sizeof(*resets),
|
||||
(void **)&resets);
|
||||
if (!assert && ncells < 2) {
|
||||
device_printf(consumer, "Warning: No resets specified in fdt "
|
||||
"data; device may not function.");
|
||||
return (ENXIO);
|
||||
}
|
||||
anyerrors = false;
|
||||
for (i = 0; i < ncells; i += 2) {
|
||||
resetdev = OF_device_from_xref(resets[i]);
|
||||
resetnum = resets[i + 1];
|
||||
if (resetdev == NULL) {
|
||||
if (!assert)
|
||||
device_printf(consumer, "Warning: can not find "
|
||||
"driver for reset number %u; device may "
|
||||
"not function\n", resetnum);
|
||||
anyerrors = true;
|
||||
continue;
|
||||
}
|
||||
if (assert)
|
||||
err = FDT_RESET_ASSERT(resetdev, resetnum);
|
||||
else
|
||||
err = FDT_RESET_DEASSERT(resetdev, resetnum);
|
||||
if (err != 0) {
|
||||
if (!assert)
|
||||
device_printf(consumer, "Warning: failed to "
|
||||
"deassert reset number %u; device may not "
|
||||
"function\n", resetnum);
|
||||
anyerrors = true;
|
||||
}
|
||||
}
|
||||
free(resets, M_OFWPROP);
|
||||
return (anyerrors ? ENXIO : 0);
|
||||
}
|
||||
|
||||
int
|
||||
fdt_reset_assert_all(device_t consumer)
|
||||
{
|
||||
|
||||
return (assert_deassert_all(consumer, true));
|
||||
}
|
||||
|
||||
int
|
||||
fdt_reset_deassert_all(device_t consumer)
|
||||
{
|
||||
|
||||
return (assert_deassert_all(consumer, false));
|
||||
}
|
||||
|
||||
void
|
||||
fdt_reset_register_provider(device_t provider)
|
||||
{
|
||||
|
||||
OF_device_register_xref(
|
||||
OF_xref_from_node(ofw_bus_get_node(provider)), provider);
|
||||
}
|
||||
|
||||
void
|
||||
fdt_reset_unregister_provider(device_t provider)
|
||||
{
|
||||
|
||||
OF_device_register_xref(OF_xref_from_device(provider), NULL);
|
||||
}
|
||||
|
49
sys/mips/mediatek/fdt_reset.h
Normal file
49
sys/mips/mediatek/fdt_reset.h
Normal file
@ -0,0 +1,49 @@
|
||||
/*-
|
||||
* Copyright (c) 2016 Stanislav Galabov
|
||||
* Copyright (c) 2014 Ian Lepore <ian@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 DEV_FDT_RESET_H
|
||||
#define DEV_FDT_RESET_H
|
||||
|
||||
#include "fdt_reset_if.h"
|
||||
|
||||
/*
|
||||
* Look up "resets" property in consumer's fdt data and assert or deassert all
|
||||
* configured resets.
|
||||
*/
|
||||
int fdt_reset_assert_all(device_t consumer);
|
||||
int fdt_reset_deassert_all(device_t consumer);
|
||||
|
||||
/*
|
||||
* [Un]register the given device instance as a driver that implements the
|
||||
* fdt_clock interface.
|
||||
*/
|
||||
void fdt_reset_register_provider(device_t provider);
|
||||
void fdt_reset_unregister_provider(device_t provider);
|
||||
|
||||
#endif /* DEV_FDT_RESET_H */
|
||||
|
58
sys/mips/mediatek/fdt_reset_if.m
Normal file
58
sys/mips/mediatek/fdt_reset_if.m
Normal file
@ -0,0 +1,58 @@
|
||||
#-
|
||||
# Copyright (c) 2016 Stanislav Galabov
|
||||
# Copyright (c) 2014 Ian Lepore
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#
|
||||
# This is the interface that fdt_reset drivers provide to other drivers.
|
||||
# In this context, reset refers to a reset signal provided to some other
|
||||
# hardware component within the system. They are most often found within
|
||||
# embedded processors that have on-chip IO controllers.
|
||||
#
|
||||
|
||||
INTERFACE fdt_reset;
|
||||
|
||||
#
|
||||
# Enable/assert/apply the specified reset.
|
||||
# Returns 0 on success or a standard errno value.
|
||||
#
|
||||
METHOD int assert {
|
||||
device_t provider;
|
||||
int index;
|
||||
};
|
||||
|
||||
#
|
||||
# Disable/de-assert/remove the specified reset.
|
||||
# Returns 0 on success or a standard errno value.
|
||||
#
|
||||
METHOD int deassert {
|
||||
device_t provider;
|
||||
int index;
|
||||
};
|
||||
|
286
sys/mips/mediatek/mtk_machdep.c
Normal file
286
sys/mips/mediatek/mtk_machdep.c
Normal file
@ -0,0 +1,286 @@
|
||||
/*-
|
||||
* Copyright (C) 2015-2016 by Stanislav Galabov. All rights reserved.
|
||||
* Copyright (C) 2010-2011 by Aleksandr Rybalko. All rights reserved.
|
||||
* Copyright (C) 2007 by 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 ``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.
|
||||
*
|
||||
*/
|
||||
|
||||
#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/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/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>
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_object.h>
|
||||
#include <vm/vm_page.h>
|
||||
|
||||
#include <machine/cache.h>
|
||||
#include <machine/clock.h>
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/cpuinfo.h>
|
||||
#include <machine/cpufunc.h>
|
||||
#include <machine/cpuregs.h>
|
||||
#include <machine/hwfunc.h>
|
||||
#include <machine/intr_machdep.h>
|
||||
#include <machine/locore.h>
|
||||
#include <machine/md_var.h>
|
||||
#include <machine/pte.h>
|
||||
#include <machine/sigframe.h>
|
||||
#include <machine/trap.h>
|
||||
#include <machine/vmparam.h>
|
||||
|
||||
#include <mips/mediatek/mtk_sysctl.h>
|
||||
#include <mips/mediatek/mtk_soc.h>
|
||||
|
||||
#include "opt_platform.h"
|
||||
#include "opt_rt305x.h"
|
||||
|
||||
#include <dev/fdt/fdt_common.h>
|
||||
#include <dev/ofw/openfirm.h>
|
||||
|
||||
extern int *edata;
|
||||
extern int *end;
|
||||
static char boot1_env[0x1000];
|
||||
|
||||
void
|
||||
platform_cpu_init()
|
||||
{
|
||||
/* Nothing special */
|
||||
}
|
||||
|
||||
static void
|
||||
mips_init(void)
|
||||
{
|
||||
struct mem_region mr[FDT_MEM_REGIONS];
|
||||
uint64_t val;
|
||||
int i, j, mr_cnt;
|
||||
char *memsize;
|
||||
|
||||
printf("entry: mips_init()\n");
|
||||
|
||||
bootverbose = 1;
|
||||
|
||||
for (i = 0; i < 10; i++)
|
||||
phys_avail[i] = 0;
|
||||
|
||||
dump_avail[0] = phys_avail[0] = MIPS_KSEG0_TO_PHYS(kernel_kseg0_end);
|
||||
|
||||
/*
|
||||
* The most low memory MT7621 can have. Currently MT7621 is the chip
|
||||
* that supports the most memory, so that seems reasonable.
|
||||
*/
|
||||
realmem = btoc(448 * 1024 * 1024);
|
||||
|
||||
if (fdt_get_mem_regions(mr, &mr_cnt, &val) == 0) {
|
||||
physmem = btoc(val);
|
||||
|
||||
printf("RAM size: %ldMB (from FDT)\n",
|
||||
ctob(physmem) / (1024 * 1024));
|
||||
|
||||
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 the 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];
|
||||
}
|
||||
} else {
|
||||
if ((memsize = kern_getenv("memsize")) != NULL) {
|
||||
physmem = btoc(strtol(memsize, NULL, 0) << 20);
|
||||
printf("RAM size: %ldMB (from memsize)\n",
|
||||
ctob(physmem) / (1024 * 1024));
|
||||
} else { /* All else failed, assume 32MB */
|
||||
physmem = btoc(32 * 1024 * 1024);
|
||||
printf("RAM size: %ldMB (assumed)\n",
|
||||
ctob(physmem) / (1024 * 1024));
|
||||
}
|
||||
|
||||
if (ctob(physmem) < (448 * 1024 * 1024)) {
|
||||
/*
|
||||
* Anything up to 448MB is assumed to be directly
|
||||
* mappable as low memory...
|
||||
*/
|
||||
dump_avail[1] = phys_avail[1] = ctob(physmem);
|
||||
} else if (mtk_soc_get_socid() == MTK_SOC_MT7621) {
|
||||
/*
|
||||
* On MT7621 the low memory is limited to 448MB, the
|
||||
* rest is high memory, mapped at 0x20000000
|
||||
*/
|
||||
phys_avail[1] = 448 * 1024 * 1024;
|
||||
phys_avail[2] = 0x20000000;
|
||||
phys_avail[3] = phys_avail[2] + ctob(physmem) -
|
||||
phys_avail[1];
|
||||
dump_avail[1] = phys_avail[1] - phys_avail[0];
|
||||
dump_avail[2] = phys_avail[2];
|
||||
dump_avail[3] = phys_avail[3] - phys_avail[2];
|
||||
} else {
|
||||
/*
|
||||
* We have > 448MB RAM and we're not MT7621? Currently
|
||||
* there is no such chip, so we'll just limit the RAM to
|
||||
* 32MB and let the user know...
|
||||
*/
|
||||
printf("Unknown chip, assuming 32MB RAM\n");
|
||||
physmem = btoc(32 * 1024 * 1024);
|
||||
dump_avail[1] = phys_avail[1] = ctob(physmem);
|
||||
}
|
||||
}
|
||||
|
||||
if (physmem < realmem)
|
||||
realmem = physmem;
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
void
|
||||
platform_reset(void)
|
||||
{
|
||||
|
||||
mtk_soc_reset();
|
||||
}
|
||||
|
||||
void
|
||||
platform_start(__register_t a0 __unused, __register_t a1 __unused,
|
||||
__register_t a2 __unused, __register_t a3 __unused)
|
||||
{
|
||||
vm_offset_t kernend;
|
||||
int argc = a0, i;//, res;
|
||||
uint32_t timer_clk;
|
||||
char **argv = (char **)MIPS_PHYS_TO_KSEG0(a1);
|
||||
char **envp = (char **)MIPS_PHYS_TO_KSEG0(a2);
|
||||
void *dtbp;
|
||||
|
||||
/* clear the BSS and SBSS segments */
|
||||
kernend = (vm_offset_t)&end;
|
||||
memset(&edata, 0, kernend - (vm_offset_t)(&edata));
|
||||
|
||||
mips_postboot_fixup();
|
||||
|
||||
/* Initialize pcpu stuff */
|
||||
mips_pcpu0_init();
|
||||
|
||||
dtbp = &fdt_static_dtb;
|
||||
if (OF_install(OFW_FDT, 0) == FALSE)
|
||||
while (1);
|
||||
if (OF_init((void *)dtbp) != 0)
|
||||
while (1);
|
||||
|
||||
mtk_soc_try_early_detect();
|
||||
if ((timer_clk = mtk_soc_get_timerclk()) == 0)
|
||||
timer_clk = 1000000000; /* no such speed yet */
|
||||
|
||||
mips_timer_early_init(timer_clk);
|
||||
|
||||
/* initialize console so that we have printf */
|
||||
boothowto |= (RB_SERIAL | RB_MULTIPLE); /* Use multiple consoles */
|
||||
boothowto |= (RB_VERBOSE);
|
||||
cninit();
|
||||
|
||||
init_static_kenv(boot1_env, sizeof(boot1_env));
|
||||
|
||||
printf("FDT DTB at: 0x%08x\n", (uint32_t)dtbp);
|
||||
|
||||
printf("CPU clock: %4dMHz\n", mtk_soc_get_cpuclk()/(1000*1000));
|
||||
printf("Timer clock: %4dMHz\n", timer_clk/(1000*1000));
|
||||
printf("UART clock: %4dMHz\n\n", mtk_soc_get_uartclk()/(1000*1000));
|
||||
|
||||
printf("U-Boot args (from %d args):\n", argc - 1);
|
||||
|
||||
if (argc == 1)
|
||||
printf("\tNone\n");
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
char *n = "argv ", *arg;
|
||||
|
||||
if (i > 99)
|
||||
break;
|
||||
|
||||
if (argv[i])
|
||||
{
|
||||
arg = (char *)(intptr_t)MIPS_PHYS_TO_KSEG0(argv[i]);
|
||||
printf("\targv[%d] = %s\n", i, arg);
|
||||
sprintf(n, "argv%d", i);
|
||||
kern_setenv(n, arg);
|
||||
}
|
||||
}
|
||||
|
||||
printf("Environment:\n");
|
||||
|
||||
for (i = 0; envp[i] && MIPS_IS_VALID_PTR(envp[i]); i++) {
|
||||
char *n, *arg;
|
||||
|
||||
arg = (char *)(intptr_t)MIPS_PHYS_TO_KSEG0(envp[i]);
|
||||
if (! MIPS_IS_VALID_PTR(arg))
|
||||
continue;
|
||||
printf("\t%s\n", arg);
|
||||
n = strsep(&arg, "=");
|
||||
if (arg == NULL)
|
||||
kern_setenv(n, "1");
|
||||
else
|
||||
kern_setenv(n, arg);
|
||||
}
|
||||
|
||||
|
||||
mips_init();
|
||||
mips_timer_init_params(timer_clk, 0);
|
||||
}
|
438
sys/mips/mediatek/mtk_soc.c
Normal file
438
sys/mips/mediatek/mtk_soc.c
Normal file
@ -0,0 +1,438 @@
|
||||
/*-
|
||||
* Copyright (c) 2016 Stanislav Galabov.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/rman.h>
|
||||
|
||||
#include <machine/fdt.h>
|
||||
|
||||
#include <dev/ofw/openfirm.h>
|
||||
#include <dev/ofw/ofw_bus.h>
|
||||
#include <dev/ofw/ofw_bus_subr.h>
|
||||
|
||||
#include <dev/fdt/fdt_common.h>
|
||||
#include <dev/fdt/fdt_clock.h>
|
||||
|
||||
#include <mips/mediatek/fdt_reset.h>
|
||||
#include <mips/mediatek/mtk_sysctl.h>
|
||||
#include <mips/mediatek/mtk_soc.h>
|
||||
|
||||
static uint32_t mtk_soc_socid = MTK_SOC_UNKNOWN;
|
||||
static uint32_t mtk_soc_uartclk = 0;
|
||||
static uint32_t mtk_soc_cpuclk = MTK_CPU_CLK_880MHZ;
|
||||
static uint32_t mtk_soc_timerclk = MTK_CPU_CLK_880MHZ / 2;
|
||||
|
||||
static const struct ofw_compat_data compat_data[] = {
|
||||
{ "ralink,rt3050-soc", MTK_SOC_RT3050 },
|
||||
{ "ralink,rt3052-soc", MTK_SOC_RT3052 },
|
||||
{ "ralink,rt3350-soc", MTK_SOC_RT3350 },
|
||||
{ "ralink,rt3352-soc", MTK_SOC_RT3352 },
|
||||
{ "ralink,rt3662-soc", MTK_SOC_RT3662 },
|
||||
{ "ralink,rt3883-soc", MTK_SOC_RT3883 },
|
||||
{ "ralink,rt5350-soc", MTK_SOC_RT5350 },
|
||||
{ "ralink,mtk7620a-soc", MTK_SOC_MT7620A },
|
||||
{ "ralink,mtk7620n-soc", MTK_SOC_MT7620N },
|
||||
{ "mediatek,mtk7621-soc", MTK_SOC_MT7621 },
|
||||
{ "ralink,mtk7621-soc", MTK_SOC_MT7621 },
|
||||
{ "ralink,mtk7628an-soc", MTK_SOC_MT7628 },
|
||||
{ "mediatek,mt7628an-soc", MTK_SOC_MT7628 },
|
||||
{ "ralink,mtk7688-soc", MTK_SOC_MT7688 },
|
||||
|
||||
/* Sentinel */
|
||||
{ NULL, MTK_SOC_UNKNOWN },
|
||||
};
|
||||
|
||||
static uint32_t
|
||||
mtk_detect_cpuclk_rt305x(bus_space_tag_t bst, bus_space_handle_t bsh)
|
||||
{
|
||||
uint32_t clk;
|
||||
|
||||
clk = bus_space_read_4(bst, bsh, SYSCTL_SYSCFG);
|
||||
clk >>= RT305X_CPU_CLKSEL_OFF;
|
||||
clk &= RT305X_CPU_CLKSEL_MSK;
|
||||
|
||||
return ((clk == 0) ? MTK_CPU_CLK_320MHZ : MTK_CPU_CLK_384MHZ);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
mtk_detect_cpuclk_rt3352(bus_space_tag_t bst, bus_space_handle_t bsh)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
val = bus_space_read_4(bst, bsh, SYSCTL_SYSCFG);
|
||||
val >>= RT3352_CPU_CLKSEL_OFF;
|
||||
val &= RT3352_CPU_CLKSEL_MSK;
|
||||
|
||||
if (val)
|
||||
return (MTK_CPU_CLK_400MHZ);
|
||||
|
||||
return (MTK_CPU_CLK_384MHZ);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
mtk_detect_cpuclk_rt3883(bus_space_tag_t bst, bus_space_handle_t bsh)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
val = bus_space_read_4(bst, bsh, SYSCTL_SYSCFG);
|
||||
val >>= RT3883_CPU_CLKSEL_OFF;
|
||||
val &= RT3883_CPU_CLKSEL_MSK;
|
||||
|
||||
switch (val) {
|
||||
case 0:
|
||||
return (MTK_CPU_CLK_250MHZ);
|
||||
case 1:
|
||||
return (MTK_CPU_CLK_384MHZ);
|
||||
case 2:
|
||||
return (MTK_CPU_CLK_480MHZ);
|
||||
case 3:
|
||||
return (MTK_CPU_CLK_500MHZ);
|
||||
}
|
||||
|
||||
/* Never reached */
|
||||
return (0);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
mtk_detect_cpuclk_rt5350(bus_space_tag_t bst, bus_space_handle_t bsh)
|
||||
{
|
||||
uint32_t val1, val2;
|
||||
|
||||
val1 = val2 = bus_space_read_4(bst, bsh, SYSCTL_SYSCFG);
|
||||
|
||||
val1 >>= RT5350_CPU_CLKSEL_OFF1;
|
||||
val2 >>= RT5350_CPU_CLKSEL_OFF2;
|
||||
val1 &= RT5350_CPU_CLKSEL_MSK;
|
||||
val2 &= RT5350_CPU_CLKSEL_MSK;
|
||||
val1 |= (val2 << 1);
|
||||
|
||||
switch (val1) {
|
||||
case 0:
|
||||
return (MTK_CPU_CLK_360MHZ);
|
||||
case 1:
|
||||
/* Reserved value, but we return UNKNOWN */
|
||||
return (MTK_CPU_CLK_UNKNOWN);
|
||||
case 2:
|
||||
return (MTK_CPU_CLK_320MHZ);
|
||||
case 3:
|
||||
return (MTK_CPU_CLK_300MHZ);
|
||||
}
|
||||
|
||||
/* Never reached */
|
||||
return (0);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
mtk_detect_cpuclk_mt7620(bus_space_tag_t bst, bus_space_handle_t bsh)
|
||||
{
|
||||
uint32_t val, mul, div, res;
|
||||
|
||||
val = bus_space_read_4(bst, bsh, SYSCTL_MT7620_CPLL_CFG1);
|
||||
if (val & MT7620_CPU_CLK_AUX0)
|
||||
return (MTK_CPU_CLK_480MHZ);
|
||||
|
||||
val = bus_space_read_4(bst, bsh, SYSCTL_MT7620_CPLL_CFG0);
|
||||
if (!(val & MT7620_CPLL_SW_CFG))
|
||||
return (MTK_CPU_CLK_600MHZ);
|
||||
|
||||
mul = MT7620_PLL_MULT_RATIO_BASE + ((val >> MT7620_PLL_MULT_RATIO_OFF) &
|
||||
MT7620_PLL_MULT_RATIO_MSK);
|
||||
div = (val >> MT7620_PLL_DIV_RATIO_OFF) & MT7620_PLL_DIV_RATIO_MSK;
|
||||
|
||||
if (div != MT7620_PLL_DIV_RATIO_MSK)
|
||||
div += MT7620_PLL_DIV_RATIO_BASE;
|
||||
else
|
||||
div = MT7620_PLL_DIV_RATIO_MAX;
|
||||
|
||||
res = (MT7620_XTAL_40 * mul) / div;
|
||||
|
||||
return (MTK_MHZ(res));
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
mtk_detect_cpuclk_mt7621(bus_space_tag_t bst, bus_space_handle_t bsh)
|
||||
{
|
||||
uint32_t val, div, res;
|
||||
|
||||
val = bus_space_read_4(bst, bsh, SYSCTL_CLKCFG0);
|
||||
if (val & MT7621_USES_MEMDIV) {
|
||||
div = bus_space_read_4(bst, bsh, MTK_MT7621_CLKDIV_REG);
|
||||
div >>= MT7621_MEMDIV_OFF;
|
||||
div &= MT7621_MEMDIV_MSK;
|
||||
div += MT7621_MEMDIV_BASE;
|
||||
|
||||
val = bus_space_read_4(bst, bsh, SYSCTL_SYSCFG);
|
||||
val >>= MT7621_CLKSEL_OFF;
|
||||
val &= MT7621_CLKSEL_MSK;
|
||||
|
||||
if (val >= MT7621_CLKSEL_25MHZ_VAL)
|
||||
res = div * MT7621_CLKSEL_25MHZ;
|
||||
else if (val >= MT7621_CLKSEL_20MHZ_VAL)
|
||||
res = div * MT7621_CLKSEL_20MHZ;
|
||||
else
|
||||
res = div * 0; /* XXX: not sure about this */
|
||||
} else {
|
||||
val = bus_space_read_4(bst, bsh, SYSCTL_CUR_CLK_STS);
|
||||
div = (val >> MT7621_CLK_STS_DIV_OFF) & MT7621_CLK_STS_MSK;
|
||||
val &= MT7621_CLK_STS_MSK;
|
||||
|
||||
res = (MT7621_CLK_STS_BASE * val) / div;
|
||||
}
|
||||
|
||||
return (MTK_MHZ(res));
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
mtk_detect_cpuclk_mt7628(bus_space_tag_t bst, bus_space_handle_t bsh)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
val = bus_space_read_4(bst, bsh, SYSCTL_SYSCFG);
|
||||
val >>= MT7628_CPU_CLKSEL_OFF;
|
||||
val &= MT7628_CPU_CLKSEL_MSK;
|
||||
|
||||
if (val)
|
||||
return (MTK_CPU_CLK_580MHZ);
|
||||
|
||||
return (MTK_CPU_CLK_575MHZ);
|
||||
}
|
||||
|
||||
void
|
||||
mtk_soc_try_early_detect(void)
|
||||
{
|
||||
bus_space_tag_t bst;
|
||||
bus_space_handle_t bsh;
|
||||
uint32_t base;
|
||||
phandle_t node;
|
||||
int i;
|
||||
|
||||
if ((node = OF_finddevice("/")) == -1)
|
||||
return;
|
||||
|
||||
for (i = 0; compat_data[i].ocd_str != NULL; i++) {
|
||||
if (fdt_is_compatible(node, compat_data[i].ocd_str)) {
|
||||
mtk_soc_socid = compat_data[i].ocd_data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (mtk_soc_socid == MTK_SOC_UNKNOWN) {
|
||||
/* We don't know the SoC, so we don't know how to get clocks */
|
||||
return;
|
||||
}
|
||||
|
||||
bst = fdtbus_bs_tag;
|
||||
if (mtk_soc_socid == MTK_SOC_MT7621)
|
||||
base = MTK_MT7621_BASE;
|
||||
else
|
||||
base = MTK_DEFAULT_BASE;
|
||||
|
||||
if (bus_space_map(bst, MTK_DEFAULT_BASE, MTK_DEFAULT_SIZE, 0, &bsh))
|
||||
return;
|
||||
|
||||
/* First, figure out the CPU clock */
|
||||
switch (mtk_soc_socid) {
|
||||
case MTK_SOC_RT3050: /* fallthrough */
|
||||
case MTK_SOC_RT3052:
|
||||
mtk_soc_cpuclk = mtk_detect_cpuclk_rt305x(bst, bsh);
|
||||
break;
|
||||
case MTK_SOC_RT3350:
|
||||
mtk_soc_cpuclk = MTK_CPU_CLK_320MHZ;
|
||||
break;
|
||||
case MTK_SOC_RT3352:
|
||||
mtk_soc_cpuclk = mtk_detect_cpuclk_rt3352(bst, bsh);
|
||||
break;
|
||||
case MTK_SOC_RT3662: /* fallthrough */
|
||||
case MTK_SOC_RT3883:
|
||||
mtk_soc_cpuclk = mtk_detect_cpuclk_rt3883(bst, bsh);
|
||||
break;
|
||||
case MTK_SOC_RT5350:
|
||||
mtk_soc_cpuclk = mtk_detect_cpuclk_rt5350(bst, bsh);
|
||||
break;
|
||||
case MTK_SOC_MT7620A: /* fallthrough */
|
||||
case MTK_SOC_MT7620N:
|
||||
mtk_soc_cpuclk = mtk_detect_cpuclk_mt7620(bst, bsh);
|
||||
break;
|
||||
case MTK_SOC_MT7621:
|
||||
mtk_soc_cpuclk = mtk_detect_cpuclk_mt7621(bst, bsh);
|
||||
break;
|
||||
case MTK_SOC_MT7628: /* fallthrough */
|
||||
case MTK_SOC_MT7688:
|
||||
mtk_soc_cpuclk = mtk_detect_cpuclk_mt7628(bst, bsh);
|
||||
break;
|
||||
default:
|
||||
/* We don't know the SoC, so we can't find the CPU clock */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Now figure out the timer clock */
|
||||
if (mtk_soc_socid == MTK_SOC_MT7621) {
|
||||
#ifdef notyet
|
||||
/*
|
||||
* We use the GIC timer for timing source and its clock freq is
|
||||
* the same as the CPU's clock freq
|
||||
*/
|
||||
mtk_soc_timerclk = mtk_soc_cpuclk;
|
||||
#else
|
||||
/*
|
||||
* When GIC timer and MIPS timer are ready to co-exist and
|
||||
* GIC timer is actually implemented, we need to switch to it.
|
||||
* Until then we use a fake GIC timer, which is actually a
|
||||
* normal MIPS ticker, so the timer clock is half the CPU clock
|
||||
*/
|
||||
mtk_soc_timerclk = mtk_soc_cpuclk / 2;
|
||||
#endif
|
||||
} else {
|
||||
/*
|
||||
* We use the MIPS ticker for the rest for now, so
|
||||
* the CPU clock is divided by 2
|
||||
*/
|
||||
mtk_soc_timerclk = mtk_soc_cpuclk / 2;
|
||||
}
|
||||
|
||||
switch (mtk_soc_socid) {
|
||||
case MTK_SOC_RT3350: /* fallthrough */
|
||||
case MTK_SOC_RT3050: /* fallthrough */
|
||||
case MTK_SOC_RT3052:
|
||||
/* UART clock is CPU clock / 3 */
|
||||
mtk_soc_uartclk = mtk_soc_cpuclk / MTK_UARTDIV_3;
|
||||
break;
|
||||
case MTK_SOC_RT3352: /* fallthrough */
|
||||
case MTK_SOC_RT3662: /* fallthrough */
|
||||
case MTK_SOC_RT3883: /* fallthrough */
|
||||
case MTK_SOC_RT5350: /* fallthrough */
|
||||
case MTK_SOC_MT7620A: /* fallthrough */
|
||||
case MTK_SOC_MT7620N: /* fallthrough */
|
||||
case MTK_SOC_MT7628: /* fallthrough */
|
||||
case MTK_SOC_MT7688:
|
||||
/* UART clock is always 40MHz */
|
||||
mtk_soc_uartclk = MTK_UART_CLK_40MHZ;
|
||||
break;
|
||||
case MTK_SOC_MT7621:
|
||||
/* UART clock is always 50MHz */
|
||||
mtk_soc_uartclk = MTK_UART_CLK_50MHZ;
|
||||
break;
|
||||
default:
|
||||
/* We don't know the SoC, so we don't know the UART clock */
|
||||
break;
|
||||
}
|
||||
|
||||
bus_space_unmap(bst, bsh, MTK_DEFAULT_SIZE);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
mtk_soc_get_uartclk(void)
|
||||
{
|
||||
|
||||
return mtk_soc_uartclk;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
mtk_soc_get_cpuclk(void)
|
||||
{
|
||||
|
||||
return mtk_soc_cpuclk;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
mtk_soc_get_timerclk(void)
|
||||
{
|
||||
|
||||
return mtk_soc_timerclk;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
mtk_soc_get_socid(void)
|
||||
{
|
||||
|
||||
return mtk_soc_socid;
|
||||
}
|
||||
|
||||
/*
|
||||
* The following are generic reset and clock functions
|
||||
*/
|
||||
|
||||
/* Default reset time is 100ms */
|
||||
#define DEFAULT_RESET_TIME 100000
|
||||
|
||||
int
|
||||
mtk_soc_reset_device(device_t dev)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = fdt_reset_assert_all(dev);
|
||||
if (res == 0) {
|
||||
DELAY(DEFAULT_RESET_TIME);
|
||||
res = fdt_reset_deassert_all(dev);
|
||||
if (res == 0)
|
||||
DELAY(DEFAULT_RESET_TIME);
|
||||
}
|
||||
|
||||
return (res);
|
||||
}
|
||||
|
||||
int
|
||||
mtk_soc_stop_clock(device_t dev)
|
||||
{
|
||||
|
||||
return (fdt_clock_disable_all(dev));
|
||||
}
|
||||
|
||||
int
|
||||
mtk_soc_start_clock(device_t dev)
|
||||
{
|
||||
|
||||
return (fdt_clock_enable_all(dev));
|
||||
}
|
||||
|
||||
int
|
||||
mtk_soc_assert_reset(device_t dev)
|
||||
{
|
||||
|
||||
return (fdt_reset_assert_all(dev));
|
||||
}
|
||||
|
||||
int
|
||||
mtk_soc_deassert_reset(device_t dev)
|
||||
{
|
||||
|
||||
return (fdt_reset_deassert_all(dev));
|
||||
}
|
||||
|
||||
void
|
||||
mtk_soc_reset(void)
|
||||
{
|
||||
|
||||
mtk_sysctl_clr_set(SYSCTL_RSTCTRL, 0, 1);
|
||||
mtk_sysctl_clr_set(SYSCTL_RSTCTRL, 1, 0);
|
||||
}
|
130
sys/mips/mediatek/mtk_soc.h
Normal file
130
sys/mips/mediatek/mtk_soc.h
Normal file
@ -0,0 +1,130 @@
|
||||
/*-
|
||||
* Copyright (c) 2016 Stanislav Galabov.
|
||||
* 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 _MTK_SOC_H_
|
||||
#define _MTK_SOC_H_
|
||||
|
||||
enum mtk_soc_id {
|
||||
MTK_SOC_UNKNOWN,
|
||||
MTK_SOC_RT3050,
|
||||
MTK_SOC_RT3052,
|
||||
MTK_SOC_RT3350,
|
||||
MTK_SOC_RT3352,
|
||||
MTK_SOC_RT3662,
|
||||
MTK_SOC_RT3883,
|
||||
MTK_SOC_RT5350,
|
||||
MTK_SOC_MT7620A,
|
||||
MTK_SOC_MT7620N,
|
||||
MTK_SOC_MT7621,
|
||||
MTK_SOC_MT7628,
|
||||
MTK_SOC_MT7688,
|
||||
MTK_SOC_MAX
|
||||
};
|
||||
|
||||
#define RT305X_CPU_CLKSEL_OFF 18
|
||||
#define RT305X_CPU_CLKSEL_MSK 0x1
|
||||
#define RT3352_CPU_CLKSEL_OFF 8
|
||||
#define RT3352_CPU_CLKSEL_MSK 0x1
|
||||
#define RT3883_CPU_CLKSEL_OFF 8
|
||||
#define RT3883_CPU_CLKSEL_MSK 0x3
|
||||
#define RT5350_CPU_CLKSEL_OFF1 8
|
||||
#define RT5350_CPU_CLKSEL_OFF2 10
|
||||
#define RT5350_CPU_CLKSEL_MSK 0x1
|
||||
#define MT7628_CPU_CLKSEL_OFF 6
|
||||
#define MT7628_CPU_CLKSEL_MSK 0x1
|
||||
|
||||
#define MT7620_CPU_CLK_AUX0 (1u<<24)
|
||||
#define MT7620_CPLL_SW_CFG (1u<<31)
|
||||
#define MT7620_PLL_MULT_RATIO_OFF 16
|
||||
#define MT7620_PLL_MULT_RATIO_MSK 0x7
|
||||
#define MT7620_PLL_MULT_RATIO_BASE 24
|
||||
#define MT7620_PLL_DIV_RATIO_OFF 10
|
||||
#define MT7620_PLL_DIV_RATIO_MSK 0x3
|
||||
#define MT7620_PLL_DIV_RATIO_BASE 2
|
||||
#define MT7620_PLL_DIV_RATIO_MAX 8
|
||||
#define MT7620_XTAL_40 40
|
||||
|
||||
#define MT7621_USES_MEMDIV (1u<<30)
|
||||
#define MT7621_MEMDIV_OFF 4
|
||||
#define MT7621_MEMDIV_MSK 0x7f
|
||||
#define MT7621_MEMDIV_BASE 1
|
||||
#define MT7621_CLKSEL_OFF 6
|
||||
#define MT7621_CLKSEL_MSK 0x7
|
||||
#define MT7621_CLKSEL_25MHZ_VAL 6
|
||||
#define MT7621_CLKSEL_20MHZ_VAL 3
|
||||
#define MT7621_CLKSEL_20MHZ 20
|
||||
#define MT7621_CLKSEL_25MHZ 25
|
||||
#define MT7621_CLK_STS_DIV_OFF 8
|
||||
#define MT7621_CLK_STS_MSK 0x1f
|
||||
#define MT7621_CLK_STS_BASE 500
|
||||
|
||||
#define MTK_MT7621_CLKDIV_REG 0x5648
|
||||
#define MTK_MT7621_CLKDIV_OFF 4
|
||||
#define MTK_MT7621_CLKDIV_MSK 0x7f
|
||||
|
||||
#define MTK_MHZ(x) ((x) * 1000 * 1000)
|
||||
|
||||
#define MTK_CPU_CLK_UNKNOWN 0
|
||||
#define MTK_CPU_CLK_250MHZ 250000000
|
||||
#define MTK_CPU_CLK_300MHZ 300000000
|
||||
#define MTK_CPU_CLK_320MHZ 320000000
|
||||
#define MTK_CPU_CLK_360MHZ 360000000
|
||||
#define MTK_CPU_CLK_384MHZ 384000000
|
||||
#define MTK_CPU_CLK_400MHZ 400000000
|
||||
#define MTK_CPU_CLK_480MHZ 480000000
|
||||
#define MTK_CPU_CLK_500MHZ 500000000
|
||||
#define MTK_CPU_CLK_575MHZ 575000000
|
||||
#define MTK_CPU_CLK_580MHZ 580000000
|
||||
#define MTK_CPU_CLK_600MHZ 600000000
|
||||
#define MTK_CPU_CLK_880MHZ 880000000
|
||||
|
||||
#define MTK_UART_CLK_40MHZ 40000000
|
||||
#define MTK_UART_CLK_50MHZ 50000000
|
||||
|
||||
#define MTK_UARTDIV_2 2
|
||||
#define MTK_UARTDIV_3 3
|
||||
|
||||
#define MTK_DEFAULT_BASE 0x10000000
|
||||
#define MTK_MT7621_BASE 0x1e000000
|
||||
#define MTK_DEFAULT_SIZE 0x6000
|
||||
|
||||
extern void mtk_soc_try_early_detect(void);
|
||||
extern uint32_t mtk_soc_get_uartclk(void);
|
||||
extern uint32_t mtk_soc_get_cpuclk(void);
|
||||
extern uint32_t mtk_soc_get_timerclk(void);
|
||||
extern uint32_t mtk_soc_get_socid(void);
|
||||
|
||||
extern int mtk_soc_reset_device(device_t);
|
||||
extern int mtk_soc_stop_clock(device_t);
|
||||
extern int mtk_soc_start_clock(device_t);
|
||||
extern int mtk_soc_assert_reset(device_t);
|
||||
extern int mtk_soc_deassert_reset(device_t);
|
||||
extern void mtk_soc_reset(void);
|
||||
|
||||
#endif /* _MTK_SOC_H_ */
|
191
sys/mips/mediatek/mtk_sysctl.c
Normal file
191
sys/mips/mediatek/mtk_sysctl.c
Normal file
@ -0,0 +1,191 @@
|
||||
/*-
|
||||
* Copyright (c) 2016 Stanislav Galabov.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/interrupt.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/rman.h>
|
||||
#include <sys/malloc.h>
|
||||
|
||||
#include <machine/fdt.h>
|
||||
|
||||
#include <dev/ofw/openfirm.h>
|
||||
#include <dev/ofw/ofw_bus.h>
|
||||
#include <dev/ofw/ofw_bus_subr.h>
|
||||
|
||||
#include <mips/mediatek/mtk_sysctl.h>
|
||||
|
||||
#include <dev/fdt/fdt_common.h>
|
||||
|
||||
struct mtk_sysctl_softc {
|
||||
device_t dev;
|
||||
struct resource *mem_res;
|
||||
int mem_rid;
|
||||
struct mtx mtx;
|
||||
};
|
||||
|
||||
static struct mtk_sysctl_softc *mtk_sysctl_sc = NULL;
|
||||
|
||||
static struct ofw_compat_data compat_data[] = {
|
||||
{ "ralink,rt2880-sysc", 1 },
|
||||
{ "ralink,rt3050-sysc", 1 },
|
||||
{ "ralink,rt3352-sysc", 1 },
|
||||
{ "ralink,rt3883-sysc", 1 },
|
||||
{ "ralink,rt5350-sysc", 1 },
|
||||
{ "ralink,mt7620a-sysc", 1 },
|
||||
{ "mtk,mt7621-sysc", 1 },
|
||||
|
||||
/* Sentinel */
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
#define MTK_SYSCTL_LOCK(sc) mtx_lock_spin(&(sc)->mtx)
|
||||
#define MTK_SYSCTL_UNLOCK(sc) mtx_unlock_spin(&(sc)->mtx)
|
||||
#define MTK_SYSCTL_LOCK_INIT(sc) \
|
||||
mtx_init(&(sc)->mtx, device_get_nameunit((sc)->dev), \
|
||||
"mtk_sysctl", MTX_SPIN)
|
||||
#define MTK_SYSCTL_LOCK_DESTROY(sc) mtx_destroy(&(sc)->mtx)
|
||||
|
||||
static int
|
||||
mtk_sysctl_probe(device_t dev)
|
||||
{
|
||||
|
||||
if (!ofw_bus_status_okay(dev))
|
||||
return (ENXIO);
|
||||
|
||||
if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
|
||||
return (ENXIO);
|
||||
|
||||
device_set_desc(dev, "MTK System Controller");
|
||||
|
||||
return (BUS_PROBE_DEFAULT);
|
||||
}
|
||||
|
||||
static int mtk_sysctl_detach(device_t);
|
||||
|
||||
static int
|
||||
mtk_sysctl_attach(device_t dev)
|
||||
{
|
||||
struct mtk_sysctl_softc *sc = device_get_softc(dev);
|
||||
|
||||
if (device_get_unit(dev) != 0 || mtk_sysctl_sc != NULL) {
|
||||
device_printf(dev, "Only one sysctl module supported\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
mtk_sysctl_sc = sc;
|
||||
|
||||
/* Map control/status registers. */
|
||||
sc->mem_rid = 0;
|
||||
sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
|
||||
&sc->mem_rid, RF_ACTIVE);
|
||||
|
||||
if (sc->mem_res == NULL) {
|
||||
device_printf(dev, "couldn't map memory\n");
|
||||
mtk_sysctl_detach(dev);
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
sc->dev = dev;
|
||||
|
||||
MTK_SYSCTL_LOCK_INIT(sc);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
mtk_sysctl_detach(device_t dev)
|
||||
{
|
||||
struct mtk_sysctl_softc *sc = device_get_softc(dev);
|
||||
|
||||
if (sc->mem_res)
|
||||
bus_release_resource(dev, SYS_RES_MEMORY, sc->mem_rid,
|
||||
sc->mem_res);
|
||||
|
||||
MTK_SYSCTL_LOCK_DESTROY(sc);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
mtk_sysctl_get(uint32_t reg)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
MTK_SYSCTL_LOCK(mtk_sysctl_sc);
|
||||
val = bus_read_4(mtk_sysctl_sc->mem_res, reg);
|
||||
MTK_SYSCTL_UNLOCK(mtk_sysctl_sc);
|
||||
|
||||
return (val);
|
||||
}
|
||||
|
||||
void
|
||||
mtk_sysctl_set(uint32_t reg, uint32_t val)
|
||||
{
|
||||
|
||||
MTK_SYSCTL_LOCK(mtk_sysctl_sc);
|
||||
bus_write_4(mtk_sysctl_sc->mem_res, reg, val);
|
||||
MTK_SYSCTL_UNLOCK(mtk_sysctl_sc);
|
||||
}
|
||||
|
||||
void
|
||||
mtk_sysctl_clr_set(uint32_t reg, uint32_t clr, uint32_t set)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
MTK_SYSCTL_LOCK(mtk_sysctl_sc);
|
||||
val = bus_read_4(mtk_sysctl_sc->mem_res, reg);
|
||||
val &= ~(clr);
|
||||
val |= set;
|
||||
bus_write_4(mtk_sysctl_sc->mem_res, reg, val);
|
||||
MTK_SYSCTL_UNLOCK(mtk_sysctl_sc);
|
||||
}
|
||||
|
||||
static device_method_t mtk_sysctl_methods[] = {
|
||||
DEVMETHOD(device_probe, mtk_sysctl_probe),
|
||||
DEVMETHOD(device_attach, mtk_sysctl_attach),
|
||||
DEVMETHOD(device_detach, mtk_sysctl_detach),
|
||||
|
||||
DEVMETHOD_END
|
||||
};
|
||||
|
||||
static driver_t mtk_sysctl_driver = {
|
||||
"sysc",
|
||||
mtk_sysctl_methods,
|
||||
sizeof(struct mtk_sysctl_softc),
|
||||
};
|
||||
static devclass_t mtk_sysctl_devclass;
|
||||
|
||||
EARLY_DRIVER_MODULE(mtk_sysctl, simplebus, mtk_sysctl_driver,
|
||||
mtk_sysctl_devclass, 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_EARLY);
|
59
sys/mips/mediatek/mtk_sysctl.h
Normal file
59
sys/mips/mediatek/mtk_sysctl.h
Normal file
@ -0,0 +1,59 @@
|
||||
/*-
|
||||
* Copyright (c) 2016 Stanislav Galabov.
|
||||
* 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 _MTK_SYSCTL_H_
|
||||
#define _MTK_SYSCTL_H_
|
||||
|
||||
/* System Control */
|
||||
#define SYSCTL_CHIPID0_3 0x00
|
||||
#define SYSCTL_CHIPID4_7 0x04
|
||||
|
||||
#define SYSCTL_REVID 0x0C
|
||||
#define SYSCTL_REVID_MASK 0xFFFF
|
||||
#define SYSCTL_MT7621_REV_E 0x0101
|
||||
|
||||
#define SYSCTL_SYSCFG 0x10
|
||||
#define SYSCTL_SYSCFG1 0x14
|
||||
#define SYSCTL_CLKCFG0 0x2C
|
||||
#define SYSCTL_CLKCFG1 0x30
|
||||
#define SYSCTL_RSTCTRL 0x34
|
||||
#define SYSCTL_GPIOMODE 0x60
|
||||
|
||||
#define SYSCTL_CUR_CLK_STS 0x44
|
||||
|
||||
#define SYSCTL_MT7620_CPLL_CFG0 0x54
|
||||
#define SYSCTL_MT7620_CPLL_CFG1 0x58
|
||||
|
||||
#define SYSCFG1_USB_HOST_MODE (1<<10)
|
||||
|
||||
extern uint32_t mtk_sysctl_get(uint32_t);
|
||||
extern void mtk_sysctl_set(uint32_t, uint32_t);
|
||||
extern void mtk_sysctl_clr_set(uint32_t, uint32_t, uint32_t);
|
||||
|
||||
#endif /* _MTK_SYSCTL_H_ */
|
Loading…
Reference in New Issue
Block a user