a20_cpu_cfg.c revision 266337
10SN/A/*- 29330SN/A * Copyright (c) 2013 Ganbold Tsagaankhuu <ganbold@freebsd.org> 30SN/A * All rights reserved. 40SN/A * 50SN/A * Redistribution and use in source and binary forms, with or without 60SN/A * modification, are permitted provided that the following conditions 70SN/A * are met: 80SN/A * 1. Redistributions of source code must retain the above copyright 90SN/A * notice, this list of conditions and the following disclaimer. 100SN/A * 2. Redistributions in binary form must reproduce the above copyright 110SN/A * notice, this list of conditions and the following disclaimer in the 120SN/A * documentation and/or other materials provided with the distribution. 130SN/A * 140SN/A * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 150SN/A * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 160SN/A * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 170SN/A * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 180SN/A * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 190SN/A * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 200SN/A * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 210SN/A * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 220SN/A * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 230SN/A * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 240SN/A * SUCH DAMAGE. 250SN/A */ 260SN/A 270SN/A/* CPU configuration module for Allwinner A20 */ 280SN/A 290SN/A#include <sys/cdefs.h> 300SN/A__FBSDID("$FreeBSD: stable/10/sys/arm/allwinner/a20/a20_cpu_cfg.c 266337 2014-05-17 18:53:36Z ian $"); 310SN/A 320SN/A#include <sys/param.h> 330SN/A#include <sys/systm.h> 340SN/A#include <sys/bus.h> 350SN/A#include <sys/kernel.h> 360SN/A#include <sys/module.h> 370SN/A#include <sys/malloc.h> 380SN/A#include <sys/rman.h> 390SN/A#include <sys/timeet.h> 400SN/A#include <sys/timetc.h> 410SN/A#include <sys/watchdog.h> 420SN/A#include <machine/bus.h> 430SN/A#include <machine/cpu.h> 440SN/A#include <machine/intr.h> 450SN/A 460SN/A#include <dev/fdt/fdt_common.h> 470SN/A#include <dev/ofw/openfirm.h> 480SN/A#include <dev/ofw/ofw_bus.h> 490SN/A#include <dev/ofw/ofw_bus_subr.h> 500SN/A 510SN/A#include <machine/bus.h> 520SN/A#include <machine/fdt.h> 530SN/A 540SN/A#include "a20_cpu_cfg.h" 550SN/A 560SN/Astruct a20_cpu_cfg_softc { 570SN/A struct resource *res; 580SN/A bus_space_tag_t bst; 590SN/A bus_space_handle_t bsh; 600SN/A}; 610SN/A 620SN/Astatic struct a20_cpu_cfg_softc *a20_cpu_cfg_sc = NULL; 630SN/A 640SN/A#define cpu_cfg_read_4(sc, reg) \ 650SN/A bus_space_read_4((sc)->bst, (sc)->bsh, (reg)) 660SN/A#define cpu_cfg_write_4(sc, reg, val) \ 670SN/A bus_space_write_4((sc)->bst, (sc)->bsh, (reg), (val)) 680SN/A 690SN/Astatic int 700SN/Aa20_cpu_cfg_probe(device_t dev) 710SN/A{ 720SN/A 730SN/A if (!ofw_bus_status_okay(dev)) 740SN/A return (ENXIO); 750SN/A 760SN/A if (ofw_bus_is_compatible(dev, "allwinner,sun7i-cpu-cfg")) { 770SN/A device_set_desc(dev, "A20 CPU Configuration Module"); 780SN/A return(BUS_PROBE_DEFAULT); 790SN/A } 800SN/A 810SN/A return (ENXIO); 820SN/A} 830SN/A 84936SN/Astatic int 850SN/Aa20_cpu_cfg_attach(device_t dev) 860SN/A{ 870SN/A struct a20_cpu_cfg_softc *sc = device_get_softc(dev); 880SN/A int rid = 0; 890SN/A 900SN/A if (a20_cpu_cfg_sc) 910SN/A return (ENXIO); 920SN/A 930SN/A sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); 940SN/A if (!sc->res) { 950SN/A device_printf(dev, "could not allocate resource\n"); 960SN/A return (ENXIO); 970SN/A } 980SN/A 990SN/A sc->bst = rman_get_bustag(sc->res); 1000SN/A sc->bsh = rman_get_bushandle(sc->res); 1010SN/A 1020SN/A a20_cpu_cfg_sc = sc; 1030SN/A 1040SN/A return (0); 1050SN/A} 1060SN/A 1070SN/Astatic device_method_t a20_cpu_cfg_methods[] = { 1080SN/A DEVMETHOD(device_probe, a20_cpu_cfg_probe), 1090SN/A DEVMETHOD(device_attach, a20_cpu_cfg_attach), 1100SN/A { 0, 0 } 1110SN/A}; 1120SN/A 1130SN/Astatic driver_t a20_cpu_cfg_driver = { 1140SN/A "a20_cpu_cfg", 1150SN/A a20_cpu_cfg_methods, 1160SN/A sizeof(struct a20_cpu_cfg_softc), 1172928SN/A}; 1180SN/A 1190SN/Astatic devclass_t a20_cpu_cfg_devclass; 1200SN/A 1210SN/ADRIVER_MODULE(a20_cpu_cfg, simplebus, a20_cpu_cfg_driver, a20_cpu_cfg_devclass, 0, 0); 1220SN/A 1230SN/Auint64_t 1240SN/Aa20_read_counter64(void) 1250SN/A{ 1260SN/A uint32_t lo, hi; 1272928SN/A 1282928SN/A /* Latch counter, wait for it to be ready to read. */ 1292928SN/A cpu_cfg_write_4(a20_cpu_cfg_sc, OSC24M_CNT64_CTRL_REG, CNT64_RL_EN); 1302928SN/A while (cpu_cfg_read_4(a20_cpu_cfg_sc, OSC24M_CNT64_CTRL_REG) & CNT64_RL_EN) 1312928SN/A continue; 1322928SN/A 1332928SN/A hi = cpu_cfg_read_4(a20_cpu_cfg_sc, OSC24M_CNT64_HIGH_REG); 134936SN/A lo = cpu_cfg_read_4(a20_cpu_cfg_sc, OSC24M_CNT64_LOW_REG); 135936SN/A 1360SN/A return (((uint64_t)hi << 32) | lo); 1370SN/A} 1380SN/A 1392928SN/A