1 /*- 2 * Copyright (c) 2013 Ian Lepore <ian@freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include <sys/cdefs.h> 28 __FBSDID("$FreeBSD$"); 29 30 /* 31 * Analog PLL and power regulator driver for Freescale i.MX6 family of SoCs. 32 * 33 * We don't really do anything with analog PLLs, but the registers for 34 * controlling them belong to the same block as the power regulator registers. 35 * Since the newbus hierarchy makes it hard for anyone other than us to get at 36 * them, we just export a couple public functions to allow the imx6 CCM clock 37 * driver to read and write those registers. 38 * 39 * We also don't do anything about power regulation yet, but when the need 40 * arises, this would be the place for that code to live. 41 * 42 * I have no idea where the "anatop" name comes from. It's in the standard DTS 43 * source describing i.MX6 SoCs, and in the linux and u-boot code which comes 44 * from Freescale, but it's not in the SoC manual. 45 */ 46 47 #include <sys/param.h> 48 #include <sys/systm.h> 49 #include <sys/kernel.h> 50 #include <sys/module.h> 51 #include <sys/bus.h> 52 #include <sys/rman.h> 53 54 #include <dev/ofw/ofw_bus.h> 55 #include <dev/ofw/ofw_bus_subr.h> 56 57 #include <machine/bus.h> 58 59 #include <arm/freescale/imx/imx6_anatopreg.h> 60 #include <arm/freescale/imx/imx6_anatopvar.h> 61 62 struct imx6_anatop_softc { 63 device_t dev; 64 struct resource *mem_res; 65 }; 66 67 static struct imx6_anatop_softc *imx6_anatop_sc; 68 69 uint32_t 70 imx6_anatop_read_4(bus_size_t offset) 71 { 72 73 return (bus_read_4(imx6_anatop_sc->mem_res, offset)); 74 } 75 76 void 77 imx6_anatop_write_4(bus_size_t offset, uint32_t value) 78 { 79 80 bus_write_4(imx6_anatop_sc->mem_res, offset, value); 81 } 82 83 static int 84 imx6_anatop_detach(device_t dev) 85 { 86 struct imx6_anatop_softc *sc; 87 88 sc = device_get_softc(dev); 89 90 if (sc->mem_res != NULL) 91 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res); 92 93 return (0); 94 } 95 96 static int 97 imx6_anatop_attach(device_t dev) 98 { 99 struct imx6_anatop_softc *sc; 100 int err, rid; 101 102 sc = device_get_softc(dev); 103 104 /* Allocate bus_space resources. */ 105 rid = 0; 106 sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 107 RF_ACTIVE); 108 if (sc->mem_res == NULL) { 109 device_printf(dev, "Cannot allocate memory resources\n"); 110 err = ENXIO; 111 goto out; 112 } 113 114 imx6_anatop_sc = sc; 115 err = 0; 116 117 out: 118 119 if (err != 0) 120 imx6_anatop_detach(dev); 121 122 return (err); 123 } 124 125 static int 126 imx6_anatop_probe(device_t dev) 127 { 128 129 if (ofw_bus_is_compatible(dev, "fsl,imx6q-anatop") == 0) 130 return (ENXIO); 131 132 device_set_desc(dev, "Freescale i.MX6 Analog PLLs and Power"); 133 134 return (BUS_PROBE_DEFAULT); 135 } 136 137 static device_method_t imx6_anatop_methods[] = { 138 /* Device interface */ 139 DEVMETHOD(device_probe, imx6_anatop_probe), 140 DEVMETHOD(device_attach, imx6_anatop_attach), 141 DEVMETHOD(device_detach, imx6_anatop_detach), 142 143 DEVMETHOD_END 144 }; 145 146 static driver_t imx6_anatop_driver = { 147 "imx6_anatop", 148 imx6_anatop_methods, 149 sizeof(struct imx6_anatop_softc) 150 }; 151 152 static devclass_t imx6_anatop_devclass; 153 154 DRIVER_MODULE(imx6_anatop, simplebus, imx6_anatop_driver, imx6_anatop_devclass, 0, 0); 155 156