1290807Sgonzo/*-
2290807Sgonzo * Copyright (c) 2015 Oleksandr Tymoshenko <gonzo@freebsd.org>
3290807Sgonzo * All rights reserved.
4290807Sgonzo *
5290807Sgonzo * Redistribution and use in source and binary forms, with or without
6290807Sgonzo * modification, are permitted provided that the following conditions
7290807Sgonzo * are met:
8290807Sgonzo * 1. Redistributions of source code must retain the above copyright
9290807Sgonzo *    notice, this list of conditions and the following disclaimer.
10290807Sgonzo * 2. Redistributions in binary form must reproduce the above copyright
11290807Sgonzo *    notice, this list of conditions and the following disclaimer in the
12290807Sgonzo *    documentation and/or other materials provided with the distribution.
13290807Sgonzo *
14290807Sgonzo * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15290807Sgonzo * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16290807Sgonzo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17290807Sgonzo * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18290807Sgonzo * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19290807Sgonzo * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20290807Sgonzo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21290807Sgonzo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22290807Sgonzo * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23290807Sgonzo * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24290807Sgonzo * SUCH DAMAGE.
25290807Sgonzo */
26290807Sgonzo
27290807Sgonzo#include <sys/cdefs.h>
28290807Sgonzo__FBSDID("$FreeBSD: stable/11/sys/arm/freescale/imx/imx6_src.c 314506 2017-03-01 19:55:04Z ian $");
29290807Sgonzo
30290807Sgonzo/*
31290807Sgonzo * System Reset Control for iMX6
32290807Sgonzo */
33290807Sgonzo
34290807Sgonzo#include <sys/param.h>
35290807Sgonzo#include <sys/systm.h>
36290807Sgonzo#include <sys/kernel.h>
37290807Sgonzo#include <sys/module.h>
38290807Sgonzo#include <sys/bus.h>
39290807Sgonzo#include <sys/rman.h>
40290807Sgonzo
41290807Sgonzo#include <dev/ofw/ofw_bus.h>
42290807Sgonzo#include <dev/ofw/ofw_bus_subr.h>
43290807Sgonzo
44290807Sgonzo#include <machine/bus.h>
45290807Sgonzo
46290807Sgonzo#include <arm/freescale/imx/imx6_src.h>
47290807Sgonzo
48290807Sgonzo#define	SRC_SCR		0
49290807Sgonzo#define		SW_IPU1_RST	(1 << 3)
50290807Sgonzo
51290807Sgonzostruct src_softc {
52290807Sgonzo	device_t	dev;
53290807Sgonzo	struct resource	*mem_res;
54290807Sgonzo};
55290807Sgonzo
56290807Sgonzostatic struct src_softc *src_sc;
57290807Sgonzo
58290807Sgonzostatic inline uint32_t
59290807SgonzoRD4(struct src_softc *sc, bus_size_t off)
60290807Sgonzo{
61290807Sgonzo
62290807Sgonzo	return (bus_read_4(sc->mem_res, off));
63290807Sgonzo}
64290807Sgonzo
65290807Sgonzostatic inline void
66290807SgonzoWR4(struct src_softc *sc, bus_size_t off, uint32_t val)
67290807Sgonzo{
68290807Sgonzo
69290807Sgonzo	bus_write_4(sc->mem_res, off, val);
70290807Sgonzo}
71290807Sgonzo
72290807Sgonzoint
73314506Siansrc_reset_ipu(void)
74290807Sgonzo{
75290807Sgonzo	uint32_t reg;
76290807Sgonzo	int timeout = 10000;
77290807Sgonzo
78290807Sgonzo	if (src_sc == NULL)
79290807Sgonzo		return (-1);
80290807Sgonzo
81290807Sgonzo	reg = RD4(src_sc, SRC_SCR);
82290807Sgonzo	reg |= SW_IPU1_RST;
83290807Sgonzo	WR4(src_sc, SRC_SCR, reg);
84290807Sgonzo
85290807Sgonzo	while (timeout-- > 0) {
86290807Sgonzo		reg = RD4(src_sc, SRC_SCR);
87290807Sgonzo		if (reg & SW_IPU1_RST)
88290807Sgonzo			DELAY(1);
89290807Sgonzo		else
90290807Sgonzo			break;
91290807Sgonzo	}
92290807Sgonzo
93290807Sgonzo	if (timeout < 0)
94290807Sgonzo		return (-1);
95290807Sgonzo	else
96290807Sgonzo		return (0);
97290807Sgonzo}
98290807Sgonzo
99290807Sgonzostatic int
100290807Sgonzosrc_detach(device_t dev)
101290807Sgonzo{
102290807Sgonzo	struct src_softc *sc;
103290807Sgonzo
104290807Sgonzo	sc = device_get_softc(dev);
105290807Sgonzo
106290807Sgonzo	if (sc->mem_res != NULL)
107290807Sgonzo		bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
108290807Sgonzo
109290807Sgonzo	return (0);
110290807Sgonzo}
111290807Sgonzo
112290807Sgonzostatic int
113290807Sgonzosrc_attach(device_t dev)
114290807Sgonzo{
115290807Sgonzo	struct src_softc *sc;
116290807Sgonzo	int err, rid;
117290807Sgonzo
118290807Sgonzo	sc = device_get_softc(dev);
119290807Sgonzo	err = 0;
120290807Sgonzo
121290807Sgonzo	/* Allocate bus_space resources. */
122290807Sgonzo	rid = 0;
123290807Sgonzo	sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
124290807Sgonzo	    RF_ACTIVE);
125290807Sgonzo	if (sc->mem_res == NULL) {
126290807Sgonzo		device_printf(dev, "Cannot allocate memory resources\n");
127290807Sgonzo		err = ENXIO;
128290807Sgonzo		goto out;
129290807Sgonzo	}
130290807Sgonzo
131290807Sgonzo	src_sc = sc;
132290807Sgonzo
133290807Sgonzo	err = 0;
134290807Sgonzo
135290807Sgonzoout:
136290807Sgonzo
137290807Sgonzo	if (err != 0)
138290807Sgonzo		src_detach(dev);
139290807Sgonzo
140290807Sgonzo	return (err);
141290807Sgonzo}
142290807Sgonzo
143290807Sgonzostatic int
144290807Sgonzosrc_probe(device_t dev)
145290807Sgonzo{
146290807Sgonzo
147290807Sgonzo        if ((ofw_bus_is_compatible(dev, "fsl,imx6q-src") == 0) &&
148290807Sgonzo            (ofw_bus_is_compatible(dev, "fsl,imx6-src") == 0))
149290807Sgonzo		return (ENXIO);
150290807Sgonzo
151290807Sgonzo	device_set_desc(dev, "Freescale i.MX6 System Reset Controller");
152290807Sgonzo
153290807Sgonzo	return (BUS_PROBE_DEFAULT);
154290807Sgonzo}
155290807Sgonzo
156290807Sgonzostatic device_method_t src_methods[] = {
157290807Sgonzo	/* Device interface */
158290807Sgonzo	DEVMETHOD(device_probe,  src_probe),
159290807Sgonzo	DEVMETHOD(device_attach, src_attach),
160290807Sgonzo	DEVMETHOD(device_detach, src_detach),
161290807Sgonzo
162290807Sgonzo	DEVMETHOD_END
163290807Sgonzo};
164290807Sgonzo
165290807Sgonzostatic driver_t src_driver = {
166290807Sgonzo	"src",
167290807Sgonzo	src_methods,
168290807Sgonzo	sizeof(struct src_softc)
169290807Sgonzo};
170290807Sgonzo
171290807Sgonzostatic devclass_t src_devclass;
172290807Sgonzo
173290807SgonzoDRIVER_MODULE(src, simplebus, src_driver, src_devclass, 0, 0);
174