bcm2835_cprman.c revision 1.2
11.2Saymeric/* $NetBSD: bcm2835_cprman.c,v 1.2 2018/09/09 07:21:17 aymeric Exp $ */ 21.1Sskrll 31.1Sskrll/*- 41.1Sskrll * Copyright (c) 2017 Jared D. McNeill <jmcneill@invisible.ca> 51.1Sskrll * All rights reserved. 61.1Sskrll * 71.1Sskrll * Redistribution and use in source and binary forms, with or without 81.1Sskrll * modification, are permitted provided that the following conditions 91.1Sskrll * are met: 101.1Sskrll * 1. Redistributions of source code must retain the above copyright 111.1Sskrll * notice, this list of conditions and the following disclaimer. 121.1Sskrll * 2. Redistributions in binary form must reproduce the above copyright 131.1Sskrll * notice, this list of conditions and the following disclaimer in the 141.1Sskrll * documentation and/or other materials provided with the distribution. 151.1Sskrll * 161.1Sskrll * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 171.1Sskrll * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 181.1Sskrll * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 191.1Sskrll * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 201.1Sskrll * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 211.1Sskrll * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 221.1Sskrll * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 231.1Sskrll * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 241.1Sskrll * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 251.1Sskrll * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 261.1Sskrll * SUCH DAMAGE. 271.1Sskrll */ 281.1Sskrll 291.1Sskrll#include <sys/cdefs.h> 301.2Saymeric__KERNEL_RCSID(0, "$NetBSD: bcm2835_cprman.c,v 1.2 2018/09/09 07:21:17 aymeric Exp $"); 311.1Sskrll 321.1Sskrll#include <sys/param.h> 331.1Sskrll#include <sys/systm.h> 341.1Sskrll#include <sys/device.h> 351.1Sskrll#include <sys/kmem.h> 361.1Sskrll#include <sys/bus.h> 371.1Sskrll 381.1Sskrll#include <dev/clk/clk_backend.h> 391.1Sskrll 401.1Sskrll#include <dev/fdt/fdtvar.h> 411.1Sskrll 421.1Sskrll#include <arm/broadcom/bcm2835var.h> 431.1Sskrll 441.1Sskrllenum { 451.1Sskrll CPRMAN_CLOCK_TIMER = 17, 461.1Sskrll CPRMAN_CLOCK_UART = 19, 471.1Sskrll CPRMAN_CLOCK_VPU = 20, 481.1Sskrll CPRMAN_CLOCK_V3D = 21, 491.1Sskrll CPRMAN_CLOCK_ISP = 22, 501.1Sskrll CPRMAN_CLOCK_H264 = 23, 511.1Sskrll CPRMAN_CLOCK_VEC = 24, 521.1Sskrll CPRMAN_CLOCK_HSM = 25, 531.1Sskrll CPRMAN_CLOCK_SDRAM = 26, 541.1Sskrll CPRMAN_CLOCK_TSENS = 27, 551.1Sskrll CPRMAN_CLOCK_EMMC = 28, 561.1Sskrll CPRMAN_CLOCK_PERIIMAGE = 29, 571.1Sskrll CPRMAN_CLOCK_PWM = 30, 581.1Sskrll CPRMAN_CLOCK_PCM = 31, 591.1Sskrll CPRMAN_NCLOCK 601.1Sskrll}; 611.1Sskrll 621.1Sskrllstruct cprman_clk { 631.1Sskrll struct clk base; 641.1Sskrll u_int id; 651.1Sskrll}; 661.1Sskrll 671.1Sskrllstruct cprman_softc { 681.1Sskrll device_t sc_dev; 691.1Sskrll int sc_phandle; 701.1Sskrll 711.1Sskrll struct clk_domain sc_clkdom; 721.1Sskrll struct cprman_clk sc_clk[CPRMAN_NCLOCK]; 731.1Sskrll}; 741.1Sskrll 751.1Sskrll 761.1Sskrllstatic struct clk * 771.2Saymericcprman_decode(device_t dev, int cc_phandle, const void *data, size_t len) 781.1Sskrll{ 791.1Sskrll struct cprman_softc * const sc = device_private(dev); 801.1Sskrll struct cprman_clk *clk; 811.1Sskrll const u_int *spec = data; 821.1Sskrll u_int id; 831.1Sskrll 841.1Sskrll if (len != 4) 851.1Sskrll return NULL; 861.1Sskrll 871.1Sskrll id = be32toh(spec[0]); 881.1Sskrll 891.1Sskrll if (id >= CPRMAN_NCLOCK) 901.1Sskrll return NULL; 911.1Sskrll clk = &sc->sc_clk[id]; 921.1Sskrll if (clk->base.name == NULL) 931.1Sskrll return NULL; 941.1Sskrll 951.1Sskrll return &clk->base; 961.1Sskrll} 971.1Sskrll 981.1Sskrllstatic const struct fdtbus_clock_controller_func cprman_fdt_funcs = { 991.1Sskrll .decode = cprman_decode 1001.1Sskrll}; 1011.1Sskrll 1021.1Sskrllstatic struct clk * 1031.1Sskrllcprman_get(void *priv, const char *name) 1041.1Sskrll{ 1051.1Sskrll struct cprman_softc * const sc = priv; 1061.1Sskrll u_int n; 1071.1Sskrll 1081.1Sskrll for (n = 0; n < __arraycount(sc->sc_clk); n++) { 1091.1Sskrll if (sc->sc_clk[n].base.name == NULL) 1101.1Sskrll continue; 1111.1Sskrll if (strcmp(sc->sc_clk[n].base.name, name) == 0) 1121.1Sskrll return &sc->sc_clk[n].base; 1131.1Sskrll } 1141.1Sskrll 1151.1Sskrll return NULL; 1161.1Sskrll} 1171.1Sskrll 1181.1Sskrllstatic void 1191.1Sskrllcprman_put(void *priv, struct clk *clk) 1201.1Sskrll{ 1211.1Sskrll} 1221.1Sskrll 1231.1Sskrllstatic u_int 1241.1Sskrllcprman_get_rate(void *priv, struct clk *baseclk) 1251.1Sskrll{ 1261.1Sskrll //struct cprman_softc * const sc = priv; 1271.1Sskrll struct cprman_clk *clk = container_of(baseclk, struct cprman_clk, base); 1281.1Sskrll 1291.1Sskrll switch (clk->id) { 1301.1Sskrll case CPRMAN_CLOCK_UART: 1311.1Sskrll return bcm283x_clk_get_rate_uart(); 1321.1Sskrll case CPRMAN_CLOCK_VPU: 1331.1Sskrll return bcm283x_clk_get_rate_vpu(); 1341.1Sskrll case CPRMAN_CLOCK_EMMC: 1351.1Sskrll return bcm283x_clk_get_rate_emmc(); 1361.1Sskrll default: 1371.1Sskrll panic("unsupported clock id %d\n", clk->id); 1381.1Sskrll } 1391.1Sskrll} 1401.1Sskrll 1411.1Sskrllstatic const struct clk_funcs cprman_clk_funcs = { 1421.1Sskrll .get = cprman_get, 1431.1Sskrll .put = cprman_put, 1441.1Sskrll .get_rate = cprman_get_rate, 1451.1Sskrll}; 1461.1Sskrll 1471.1Sskrllstatic void 1481.1Sskrllcprman_add_clock(struct cprman_softc *sc, u_int id, const char *name) 1491.1Sskrll{ 1501.1Sskrll sc->sc_clk[id].base.domain = &sc->sc_clkdom; 1511.1Sskrll sc->sc_clk[id].base.name = name; 1521.1Sskrll sc->sc_clk[id].id = id; 1531.1Sskrll} 1541.1Sskrll 1551.1Sskrllstatic int 1561.1Sskrllcprman_match(device_t parent, cfdata_t cf, void *aux) 1571.1Sskrll{ 1581.1Sskrll const char * const compatible[] = { "brcm,bcm2835-cprman", NULL }; 1591.1Sskrll const struct fdt_attach_args *faa = aux; 1601.1Sskrll 1611.1Sskrll return of_match_compatible(faa->faa_phandle, compatible); 1621.1Sskrll} 1631.1Sskrll 1641.1Sskrllstatic void 1651.1Sskrllcprman_attach(device_t parent, device_t self, void *aux) 1661.1Sskrll{ 1671.1Sskrll struct cprman_softc * const sc = device_private(self); 1681.1Sskrll const struct fdt_attach_args *faa = aux; 1691.1Sskrll const int phandle = faa->faa_phandle; 1701.1Sskrll 1711.1Sskrll sc->sc_dev = self; 1721.1Sskrll sc->sc_phandle = phandle; 1731.1Sskrll sc->sc_clkdom.funcs = &cprman_clk_funcs; 1741.1Sskrll sc->sc_clkdom.priv = sc; 1751.1Sskrll 1761.1Sskrll cprman_add_clock(sc, CPRMAN_CLOCK_UART, "uart"); 1771.1Sskrll cprman_add_clock(sc, CPRMAN_CLOCK_VPU, "vpu"); 1781.1Sskrll cprman_add_clock(sc, CPRMAN_CLOCK_EMMC, "emmc"); 1791.1Sskrll 1801.1Sskrll aprint_naive("\n"); 1811.1Sskrll aprint_normal(": BCM283x Clock Controller\n"); 1821.1Sskrll 1831.1Sskrll fdtbus_register_clock_controller(self, phandle, &cprman_fdt_funcs); 1841.1Sskrll} 1851.1Sskrll 1861.1SskrllCFATTACH_DECL_NEW(bcmcprman_fdt, sizeof(struct cprman_softc), 1871.1Sskrll cprman_match, cprman_attach, NULL, NULL); 188