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