11.3Sskrll/* $Id: imx23_digctl.c,v 1.3 2025/10/02 06:51:15 skrll Exp $ */ 21.1Smatt 31.1Smatt/* 41.1Smatt* Copyright (c) 2013 The NetBSD Foundation, Inc. 51.1Smatt* All rights reserved. 61.1Smatt* 71.1Smatt* This code is derived from software contributed to The NetBSD Foundation 81.1Smatt* by Petri Laakso. 91.1Smatt* 101.1Smatt* Redistribution and use in source and binary forms, with or without 111.1Smatt* modification, are permitted provided that the following conditions 121.1Smatt* are met: 131.1Smatt* 1. Redistributions of source code must retain the above copyright 141.1Smatt* notice, this list of conditions and the following disclaimer. 151.1Smatt* 2. Redistributions in binary form must reproduce the above copyright 161.1Smatt* notice, this list of conditions and the following disclaimer in the 171.1Smatt* documentation and/or other materials provided with the distribution. 181.1Smatt* 191.1Smatt* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 201.1Smatt* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 211.1Smatt* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 221.1Smatt* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 231.1Smatt* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 241.1Smatt* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 251.1Smatt* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 261.1Smatt* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 271.1Smatt* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 281.1Smatt* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 291.1Smatt* POSSIBILITY OF SUCH DAMAGE. 301.1Smatt*/ 311.1Smatt 321.1Smatt#include <sys/param.h> 331.1Smatt#include <sys/types.h> 341.1Smatt#include <sys/bus.h> 351.1Smatt#include <sys/cdefs.h> 361.1Smatt#include <sys/device.h> 371.1Smatt#include <sys/errno.h> 381.1Smatt#include <sys/timetc.h> 391.1Smatt 401.1Smatt#include <arm/imx/imx23_digctlreg.h> 411.1Smatt#include <arm/imx/imx23_digctlvar.h> 421.1Smatt#include <arm/imx/imx23var.h> 431.1Smatt 441.1Smatttypedef struct digctl_softc { 451.1Smatt device_t sc_dev; 461.1Smatt bus_space_tag_t sc_iot; 471.1Smatt bus_space_handle_t sc_hdl; 481.1Smatt} *digctl_softc_t; 491.1Smatt 501.1Smattstatic int digctl_match(device_t, cfdata_t, void *); 511.1Smattstatic void digctl_attach(device_t, device_t, void *); 521.1Smattstatic int digctl_activate(device_t, enum devact); 531.1Smatt 541.1Smattstatic void digctl_reset(struct digctl_softc *); 551.1Smattstatic void digctl_init(struct digctl_softc *); 561.1Smatt 571.1Smatt/* timecounter. */ 581.1Smattstatic u_int digctl_tc_get_timecount(struct timecounter *); 591.1Smatt 601.1Smattstatic digctl_softc_t _sc = NULL; 611.1Smatt 621.1SmattCFATTACH_DECL3_NEW(digctl, 631.1Smatt sizeof(struct digctl_softc), 641.1Smatt digctl_match, 651.1Smatt digctl_attach, 661.1Smatt NULL, 671.1Smatt digctl_activate, 681.1Smatt NULL, 691.1Smatt NULL, 701.1Smatt 0 711.1Smatt); 721.1Smatt 731.1Smattstatic struct timecounter tc_useconds; 741.1Smatt 751.1Smatt#define DCTL_RD(sc, reg) \ 761.1Smatt bus_space_read_4(sc->sc_iot, sc->sc_hdl, (reg)) 771.1Smatt#define DCTL_WR(sc, reg, val) \ 781.1Smatt bus_space_write_4(sc->sc_iot, sc->sc_hdl, (reg), (val)) 791.1Smatt 801.1Smattstatic int 811.1Smattdigctl_match(device_t parent, cfdata_t match, void *aux) 821.1Smatt{ 831.1Smatt struct apb_attach_args *aa = aux; 841.1Smatt 851.1Smatt if ((aa->aa_addr == HW_DIGCTL_BASE) && (aa->aa_size == HW_DIGCTL_SIZE)) 861.1Smatt return 1; 871.1Smatt 881.1Smatt return 0; 891.1Smatt} 901.1Smatt 911.1Smattstatic void 921.1Smattdigctl_attach(device_t parent, device_t self, void *aux) 931.1Smatt{ 941.1Smatt struct digctl_softc *sc = device_private(self); 951.1Smatt struct apb_attach_args *aa = aux; 961.1Smatt static int digctl_attached = 0; 971.1Smatt 981.1Smatt sc->sc_dev = self; 991.1Smatt sc->sc_iot = aa->aa_iot; 1001.3Sskrll 1011.1Smatt if (digctl_attached) { 1021.1Smatt aprint_error_dev(sc->sc_dev, "already attached\n"); 1031.1Smatt return; 1041.1Smatt } 1051.1Smatt 1061.1Smatt if (bus_space_map(sc->sc_iot, aa->aa_addr, aa->aa_size, 0, 1071.1Smatt &sc->sc_hdl)) 1081.1Smatt { 1091.1Smatt aprint_error_dev(sc->sc_dev, "Unable to map bus space\n"); 1101.1Smatt return; 1111.1Smatt } 1121.1Smatt 1131.1Smatt digctl_reset(sc); 1141.1Smatt digctl_init(sc); 1151.1Smatt 1161.1Smatt aprint_normal("\n"); 1171.1Smatt 1181.1Smatt /* 1191.1Smatt * Setup timecounter to use digctl microseconds counter. 1201.1Smatt */ 1211.1Smatt tc_useconds.tc_get_timecount = digctl_tc_get_timecount; 1221.1Smatt tc_useconds.tc_poll_pps = NULL; 1231.1Smatt tc_useconds.tc_counter_mask = 0xffffffff; /* 32bit counter. */ 1241.1Smatt tc_useconds.tc_frequency = 1000000; /* @ 1MHz */ 1251.1Smatt tc_useconds.tc_name = "digctl"; 1261.1Smatt tc_useconds.tc_quality = 100; 1271.1Smatt 1281.1Smatt /* Enable counter. */ 1291.1Smatt DCTL_WR(sc, HW_DIGCTL_CTRL_CLR, HW_DIGCTL_CTRL_XTAL24M_GATE); 1301.1Smatt 1311.1Smatt tc_init(&tc_useconds); 1321.1Smatt 1331.1Smatt digctl_attached = 1; 1341.1Smatt 1351.1Smatt return; 1361.1Smatt} 1371.1Smatt 1381.1Smattstatic int 1391.1Smattdigctl_activate(device_t self, enum devact act) 1401.1Smatt{ 1411.1Smatt 1421.1Smatt return EOPNOTSUPP; 1431.1Smatt} 1441.1Smatt 1451.1Smatt/* 1461.1Smatt * Inspired by i.MX23 RM "39.3.10 Correct Way to Soft Reset a Block" 1471.1Smatt */ 1481.1Smattstatic void 1491.1Smattdigctl_reset(struct digctl_softc *sc) 1501.1Smatt{ 1511.1Smatt return; 1521.1Smatt} 1531.1Smatt 1541.3Sskrllstatic void 1551.1Smattdigctl_init(struct digctl_softc *sc) 1561.1Smatt{ 1571.1Smatt _sc = sc; 1581.1Smatt return; 1591.1Smatt} 1601.1Smatt 1611.1Smatt/* 1621.1Smatt * Control USB controller clocks. 1631.1Smatt */ 1641.1Smattvoid 1651.1Smattdigctl_usb_clkgate(int value) 1661.1Smatt{ 1671.1Smatt struct digctl_softc *sc = _sc; 1681.1Smatt 1691.1Smatt if (sc == NULL) { 1701.2Smsaitoh aprint_error("digctl is not initialized"); 1711.1Smatt return; 1721.1Smatt } 1731.1Smatt 1741.1Smatt if (value) { 1751.1Smatt /* Clocks OFF. */ 1761.1Smatt DCTL_WR(sc, HW_DIGCTL_CTRL_SET, HW_DIGCTL_CTRL_USB_CLKGATE); 1771.1Smatt } else { 1781.1Smatt /* Clocks ON. */ 1791.1Smatt DCTL_WR(sc, HW_DIGCTL_CTRL_CLR, HW_DIGCTL_CTRL_USB_CLKGATE); 1801.1Smatt } 1811.1Smatt 1821.1Smatt return; 1831.1Smatt} 1841.1Smatt 1851.1Smatt/* 1861.1Smatt * 1871.1Smatt */ 1881.1Smattstatic u_int 1891.1Smattdigctl_tc_get_timecount(struct timecounter *tc) 1901.1Smatt{ 1911.1Smatt struct digctl_softc *sc = _sc; 1921.1Smatt return DCTL_RD(sc, HW_DIGCTL_MICROSECONDS); 1931.1Smatt} 194