Add a basic driver for the Clock and Reset controller, use it to determine

CPU frequency.
This commit is contained in:
jmcneill 2015-04-28 11:15:55 +00:00
parent 9521ae7bfd
commit 8bcb30da14
8 changed files with 196 additions and 9 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: files.tegra,v 1.2 2015/03/29 22:27:04 jmcneill Exp $
# $NetBSD: files.tegra,v 1.3 2015/04/28 11:15:55 jmcneill Exp $
#
# Configuration info for NVIDIA Tegra ARM Peripherals
#
@ -31,6 +31,11 @@ device tegrapmc
attach tegrapmc at tegraio with tegra_pmc
file arch/arm/nvidia/tegra_pmc.c tegra_pmc
# Clock and Reset controller
device tegracar
attach tegracar at tegraio with tegra_car
file arch/arm/nvidia/tegra_car.c tegra_car
# UART
attach com at tegraio with tegra_com
file arch/arm/nvidia/tegra_com.c tegra_com needs-flag

View File

@ -0,0 +1,123 @@
/* $NetBSD: tegra_car.c,v 1.1 2015/04/28 11:15:55 jmcneill Exp $ */
/*-
* Copyright (c) 2015 Jared D. McNeill <jmcneill@invisible.ca>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "locators.h"
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: tegra_car.c,v 1.1 2015/04/28 11:15:55 jmcneill Exp $");
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/device.h>
#include <sys/intr.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <arm/nvidia/tegra_reg.h>
#include <arm/nvidia/tegra_carreg.h>
#include <arm/nvidia/tegra_var.h>
static int tegra_car_match(device_t, cfdata_t, void *);
static void tegra_car_attach(device_t, device_t, void *);
struct tegra_car_softc {
device_t sc_dev;
bus_space_tag_t sc_bst;
bus_space_handle_t sc_bsh;
};
static struct tegra_car_softc *pmc_softc = NULL;
CFATTACH_DECL_NEW(tegra_car, sizeof(struct tegra_car_softc),
tegra_car_match, tegra_car_attach, NULL, NULL);
static int
tegra_car_match(device_t parent, cfdata_t cf, void *aux)
{
return 1;
}
static void
tegra_car_attach(device_t parent, device_t self, void *aux)
{
struct tegra_car_softc * const sc = device_private(self);
struct tegraio_attach_args * const tio = aux;
const struct tegra_locators * const loc = &tio->tio_loc;
sc->sc_dev = self;
sc->sc_bst = tio->tio_bst;
bus_space_subregion(tio->tio_bst, tio->tio_bsh,
loc->loc_offset, loc->loc_size, &sc->sc_bsh);
KASSERT(pmc_softc == NULL);
pmc_softc = sc;
aprint_naive("\n");
aprint_normal(": CAR\n");
aprint_verbose_dev(self, "PLLX = %u Hz\n", tegra_car_pllx_rate());
}
static void
tegra_car_get_bs(bus_space_tag_t *pbst, bus_space_handle_t *pbsh)
{
if (pmc_softc) {
*pbst = pmc_softc->sc_bst;
*pbsh = pmc_softc->sc_bsh;
} else {
*pbst = &armv7_generic_bs_tag;
bus_space_subregion(*pbst, tegra_ppsb_bsh,
TEGRA_CAR_OFFSET, TEGRA_CAR_SIZE, pbsh);
}
}
u_int
tegra_car_osc_rate(void)
{
return TEGRA_REF_FREQ;
}
u_int
tegra_car_pllx_rate(void)
{
bus_space_tag_t bst;
bus_space_handle_t bsh;
uint64_t rate;
tegra_car_get_bs(&bst, &bsh);
rate = tegra_car_osc_rate();
const uint32_t base = bus_space_read_4(bst, bsh, CAR_PLLX_BASE_REG);
const u_int divm = __SHIFTOUT(base, CAR_PLLX_BASE_DIVM);
const u_int divn = __SHIFTOUT(base, CAR_PLLX_BASE_DIVN);
const u_int divp = __SHIFTOUT(base, CAR_PLLX_BASE_DIVP);
rate = tegra_car_osc_rate() * divn;
return rate / (divm << divp);
}

View File

@ -0,0 +1,44 @@
/* $NetBSD: tegra_carreg.h,v 1.1 2015/04/28 11:15:55 jmcneill Exp $ */
/*-
* Copyright (c) 2015 Jared D. McNeill <jmcneill@invisible.ca>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef _ARM_TEGRA_CARREG_H
#define _ARM_TEGRA_CARREG_H
#define CAR_PLLX_BASE_REG 0xe0
#define CAR_PLLX_BASE_ENABLE __BIT(31)
#define CAR_PLLX_BASE_LOCK_OVERRIDE __BIT(30)
#define CAR_PLLX_BASE_REF __BIT(29)
#define CAR_PLLX_BASE_LOCK __BIT(27)
#define CAR_PLLX_BASE_DIVP __BITS(23,20)
#define CAR_PLLX_BASE_DIVN __BITS(15,8)
#define CAR_PLLX_BASE_DIVM __BITS(7,0)
#define CAR_PLLX_MISC_REG 0xe8
#endif /* _ARM_TEGRA_CARREG_H */

View File

@ -1,4 +1,4 @@
/* $NetBSD: tegra_io.c,v 1.2 2015/03/29 22:27:04 jmcneill Exp $ */
/* $NetBSD: tegra_io.c,v 1.3 2015/04/28 11:15:55 jmcneill Exp $ */
/*-
* Copyright (c) 2015 Jared D. McNeill <jmcneill@invisible.ca>
@ -29,7 +29,7 @@
#include "opt_tegra.h"
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: tegra_io.c,v 1.2 2015/03/29 22:27:04 jmcneill Exp $");
__KERNEL_RCSID(0, "$NetBSD: tegra_io.c,v 1.3 2015/04/28 11:15:55 jmcneill Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -61,6 +61,11 @@ static bool tegraio_found = false;
#define NOPORT TEGRAIOCF_PORT_DEFAULT
#define NOINTR TEGRAIO_INTR_DEFAULT
static const struct tegra_locators tegra_ppsb_locators[] = {
{ "tegracar",
TEGRA_CAR_OFFSET, TEGRA_CAR_SIZE, NOPORT, NOINTR },
};
static const struct tegra_locators tegra_apb_locators[] = {
{ "tegramc",
TEGRA_MC_OFFSET, TEGRA_MC_SIZE, NOPORT, NOINTR },
@ -113,6 +118,8 @@ tegraio_attach(device_t parent, device_t self, void *aux)
aprint_naive("\n");
aprint_normal(": %s\n", tegra_chip_name());
tegraio_scan(self, tegra_ppsb_bsh,
tegra_ppsb_locators, __arraycount(tegra_ppsb_locators));
tegraio_scan(self, tegra_apb_bsh,
tegra_apb_locators, __arraycount(tegra_apb_locators));
tegraio_scan(self, tegra_ahb_a2_bsh,

View File

@ -1,4 +1,4 @@
/* $NetBSD: tegra_reg.h,v 1.3 2015/04/26 22:04:28 jmcneill Exp $ */
/* $NetBSD: tegra_reg.h,v 1.4 2015/04/28 11:15:55 jmcneill Exp $ */
/*-
* Copyright (c) 2015 Jared D. McNeill <jmcneill@invisible.ca>
@ -87,6 +87,8 @@
#define TEGRA_XUSB_DEV_SIZE 0xa000
/* PPSB */
#define TEGRA_CAR_OFFSET 0x00006000
#define TEGRA_CAR_SIZE 0x1000
#define TEGRA_EVP_OFFSET 0x0000f000
#define TEGRA_EVP_SIZE 0x1000

View File

@ -1,4 +1,4 @@
/* $NetBSD: tegra_soc.c,v 1.3 2015/04/26 22:04:28 jmcneill Exp $ */
/* $NetBSD: tegra_soc.c,v 1.4 2015/04/28 11:15:55 jmcneill Exp $ */
/*-
* Copyright (c) 2015 Jared D. McNeill <jmcneill@invisible.ca>
@ -30,7 +30,7 @@
#include "opt_multiprocessor.h"
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: tegra_soc.c,v 1.3 2015/04/26 22:04:28 jmcneill Exp $");
__KERNEL_RCSID(0, "$NetBSD: tegra_soc.c,v 1.4 2015/04/28 11:15:55 jmcneill Exp $");
#define _ARM32_BUS_DMA_PRIVATE
#include <sys/param.h>
@ -81,7 +81,7 @@ tegra_bootstrap(void)
&tegra_ahb_a2_bsh) != 0)
panic("couldn't map AHB A2");
curcpu()->ci_data.cpu_cc_freq = 696000000; /* XXX */
curcpu()->ci_data.cpu_cc_freq = tegra_car_pllx_rate();
tegra_mpinit();
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: tegra_var.h,v 1.3 2015/04/26 22:04:28 jmcneill Exp $ */
/* $NetBSD: tegra_var.h,v 1.4 2015/04/28 11:15:55 jmcneill Exp $ */
/*-
* Copyright (c) 2015 Jared D. McNeill <jmcneill@invisible.ca>
@ -69,6 +69,9 @@ u_int tegra_chip_id(void);
const char *tegra_chip_name(void);
void tegra_bootstrap(void);
u_int tegra_car_osc_rate(void);
u_int tegra_car_pllx_rate(void);
void tegra_pmc_reset(void);
void tegra_pmc_power(u_int, bool);

View File

@ -1,5 +1,5 @@
#
# $NetBSD: JETSONTK1,v 1.5 2015/04/27 09:56:36 jmcneill Exp $
# $NetBSD: JETSONTK1,v 1.6 2015/04/28 11:15:55 jmcneill Exp $
#
# NVIDIA Jetson TK1 - Tegra K1 development kit
# https://developer.nvidia.com/jetson-tk1
@ -41,6 +41,9 @@ tegramc0 at tegraio? # MC
# Power management controller
tegrapmc0 at tegraio? # PMC
# Clock and Reset controller
tegracar0 at tegraio? # CAR
# UART
com3 at tegraio? port 3 # UART-D
options CONSADDR=0x70006300, CONSPEED=115200