1 /*- 2 * Copyright (c) 2015 Michal Meloun 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 #include <sys/param.h> 31 #include <sys/systm.h> 32 #include <sys/bus.h> 33 #include <sys/clock.h> 34 #include <sys/kernel.h> 35 #include <sys/limits.h> 36 #include <sys/lock.h> 37 #include <sys/mutex.h> 38 #include <sys/module.h> 39 #include <sys/resource.h> 40 #include <sys/rman.h> 41 42 #include <machine/bus.h> 43 #include <machine/resource.h> 44 45 #include <dev/extres/clk/clk.h> 46 #include <dev/extres/hwreset/hwreset.h> 47 #include <dev/ofw/ofw_bus.h> 48 #include <dev/ofw/ofw_bus_subr.h> 49 50 #include <arm/nvidia/tegra_efuse.h> 51 52 53 #define RD4(_sc, _r) bus_read_4((_sc)->mem_res, (_sc)->fuse_begin + (_r)) 54 55 static struct ofw_compat_data compat_data[] = { 56 {"nvidia,tegra124-efuse", 1}, 57 {NULL, 0} 58 }; 59 60 struct tegra_efuse_softc { 61 device_t dev; 62 struct resource *mem_res; 63 64 int fuse_begin; 65 clk_t clk; 66 hwreset_t reset; 67 }; 68 struct tegra_efuse_softc *dev_sc; 69 70 struct tegra_sku_info tegra_sku_info; 71 static char *tegra_rev_name[] = { 72 [TEGRA_REVISION_UNKNOWN] = "unknown", 73 [TEGRA_REVISION_A01] = "A01", 74 [TEGRA_REVISION_A02] = "A02", 75 [TEGRA_REVISION_A03] = "A03", 76 [TEGRA_REVISION_A03p] = "A03 prime", 77 [TEGRA_REVISION_A04] = "A04", 78 }; 79 80 /* Tegra30 and later */ 81 #define FUSE_VENDOR_CODE 0x100 82 #define FUSE_FAB_CODE 0x104 83 #define FUSE_LOT_CODE_0 0x108 84 #define FUSE_LOT_CODE_1 0x10c 85 #define FUSE_WAFER_ID 0x110 86 #define FUSE_X_COORDINATE 0x114 87 #define FUSE_Y_COORDINATE 0x118 88 89 /* ---------------------- Tegra 124 specific code & data --------------- */ 90 #define TEGRA124_FUSE_BEGIN 0x100 91 92 #define TEGRA124_CPU_PROCESS_CORNERS 2 93 #define TEGRA124_GPU_PROCESS_CORNERS 2 94 #define TEGRA124_SOC_PROCESS_CORNERS 2 95 96 #define TEGRA124_FUSE_SKU_INFO 0x10 97 #define TEGRA124_FUSE_CPU_SPEEDO_0 0x14 98 #define TEGRA124_FUSE_CPU_IDDQ 0x18 99 #define TEGRA124_FUSE_FT_REV 0x28 100 #define TEGRA124_FUSE_CPU_SPEEDO_1 0x2c 101 #define TEGRA124_FUSE_CPU_SPEEDO_2 0x30 102 #define TEGRA124_FUSE_SOC_SPEEDO_0 0x34 103 #define TEGRA124_FUSE_SOC_SPEEDO_1 0x38 104 #define TEGRA124_FUSE_SOC_SPEEDO_2 0x3c 105 #define TEGRA124_FUSE_SOC_IDDQ 0x40 106 #define TEGRA124_FUSE_GPU_IDDQ 0x128 107 108 enum { 109 TEGRA124_THRESHOLD_INDEX_0, 110 TEGRA124_THRESHOLD_INDEX_1, 111 TEGRA124_THRESHOLD_INDEX_COUNT, 112 }; 113 114 static uint32_t tegra124_cpu_process_speedos[][TEGRA124_CPU_PROCESS_CORNERS] = 115 { 116 {2190, UINT_MAX}, 117 {0, UINT_MAX}, 118 }; 119 120 static uint32_t tegra124_gpu_process_speedos[][TEGRA124_GPU_PROCESS_CORNERS] = 121 { 122 {1965, UINT_MAX}, 123 {0, UINT_MAX}, 124 }; 125 126 static uint32_t tegra124_soc_process_speedos[][TEGRA124_SOC_PROCESS_CORNERS] = 127 { 128 {2101, UINT_MAX}, 129 {0, UINT_MAX}, 130 }; 131 132 static void 133 tegra124_rev_sku_to_speedo_ids(struct tegra_efuse_softc *sc, 134 struct tegra_sku_info *sku, int *threshold) 135 { 136 137 /* Assign to default */ 138 sku->cpu_speedo_id = 0; 139 sku->soc_speedo_id = 0; 140 sku->gpu_speedo_id = 0; 141 *threshold = TEGRA124_THRESHOLD_INDEX_0; 142 143 switch (sku->sku_id) { 144 case 0x00: /* Eng sku */ 145 case 0x0F: 146 case 0x23: 147 /* Using the default */ 148 break; 149 case 0x83: 150 sku->cpu_speedo_id = 2; 151 break; 152 153 case 0x1F: 154 case 0x87: 155 case 0x27: 156 sku->cpu_speedo_id = 2; 157 sku->soc_speedo_id = 0; 158 sku->gpu_speedo_id = 1; 159 *threshold = TEGRA124_THRESHOLD_INDEX_0; 160 break; 161 case 0x81: 162 case 0x21: 163 case 0x07: 164 sku->cpu_speedo_id = 1; 165 sku->soc_speedo_id = 1; 166 sku->gpu_speedo_id = 1; 167 *threshold = TEGRA124_THRESHOLD_INDEX_1; 168 break; 169 case 0x49: 170 case 0x4A: 171 case 0x48: 172 sku->cpu_speedo_id = 4; 173 sku->soc_speedo_id = 2; 174 sku->gpu_speedo_id = 3; 175 *threshold = TEGRA124_THRESHOLD_INDEX_1; 176 break; 177 default: 178 device_printf(sc->dev, " Unknown SKU ID %d\n", sku->sku_id); 179 break; 180 } 181 } 182 183 184 static void 185 tegra124_init_speedo(struct tegra_efuse_softc *sc, struct tegra_sku_info *sku) 186 { 187 int i, threshold; 188 189 sku->sku_id = RD4(sc, TEGRA124_FUSE_SKU_INFO); 190 sku->soc_iddq_value = RD4(sc, TEGRA124_FUSE_SOC_IDDQ); 191 sku->cpu_iddq_value = RD4(sc, TEGRA124_FUSE_CPU_IDDQ); 192 sku->gpu_iddq_value = RD4(sc, TEGRA124_FUSE_GPU_IDDQ); 193 sku->soc_speedo_value = RD4(sc, TEGRA124_FUSE_SOC_SPEEDO_0); 194 sku->cpu_speedo_value = RD4(sc, TEGRA124_FUSE_CPU_SPEEDO_0); 195 sku->gpu_speedo_value = RD4(sc, TEGRA124_FUSE_CPU_SPEEDO_2); 196 197 if (sku->cpu_speedo_value == 0) { 198 device_printf(sc->dev, "CPU Speedo value is not fused.\n"); 199 return; 200 } 201 202 tegra124_rev_sku_to_speedo_ids(sc, sku, &threshold); 203 204 for (i = 0; i < TEGRA124_SOC_PROCESS_CORNERS; i++) { 205 if (sku->soc_speedo_value < 206 tegra124_soc_process_speedos[threshold][i]) 207 break; 208 } 209 sku->soc_process_id = i; 210 211 for (i = 0; i < TEGRA124_CPU_PROCESS_CORNERS; i++) { 212 if (sku->cpu_speedo_value < 213 tegra124_cpu_process_speedos[threshold][i]) 214 break; 215 } 216 sku->cpu_process_id = i; 217 218 for (i = 0; i < TEGRA124_GPU_PROCESS_CORNERS; i++) { 219 if (sku->gpu_speedo_value < 220 tegra124_gpu_process_speedos[threshold][i]) 221 break; 222 } 223 sku->gpu_process_id = i; 224 225 } 226 227 /* ----------------- End of Tegra 124 specific code & data --------------- */ 228 229 uint32_t 230 tegra_fuse_read_4(int addr) { 231 232 if (dev_sc == NULL) 233 panic("tegra_fuse_read_4 called too early"); 234 return (RD4(dev_sc, addr)); 235 } 236 237 238 static void 239 tegra_efuse_dump_sku(void) 240 { 241 printf(" TEGRA SKU Info:\n"); 242 printf(" chip_id: %u\n", tegra_sku_info.chip_id); 243 printf(" sku_id: %u\n", tegra_sku_info.sku_id); 244 printf(" cpu_process_id: %u\n", tegra_sku_info.cpu_process_id); 245 printf(" cpu_speedo_id: %u\n", tegra_sku_info.cpu_speedo_id); 246 printf(" cpu_speedo_value: %u\n", tegra_sku_info.cpu_speedo_value); 247 printf(" cpu_iddq_value: %u\n", tegra_sku_info.cpu_iddq_value); 248 printf(" soc_process_id: %u\n", tegra_sku_info.soc_process_id); 249 printf(" soc_speedo_id: %u\n", tegra_sku_info.soc_speedo_id); 250 printf(" soc_speedo_value: %u\n", tegra_sku_info.soc_speedo_value); 251 printf(" soc_iddq_value: %u\n", tegra_sku_info.soc_iddq_value); 252 printf(" gpu_process_id: %u\n", tegra_sku_info.gpu_process_id); 253 printf(" gpu_speedo_id: %u\n", tegra_sku_info.gpu_speedo_id); 254 printf(" gpu_speedo_value: %u\n", tegra_sku_info.gpu_speedo_value); 255 printf(" gpu_iddq_value: %u\n", tegra_sku_info.gpu_iddq_value); 256 printf(" revision: %s\n", tegra_rev_name[tegra_sku_info.revision]); 257 } 258 259 static int 260 tegra_efuse_probe(device_t dev) 261 { 262 if (!ofw_bus_status_okay(dev)) 263 return (ENXIO); 264 265 if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) 266 return (ENXIO); 267 268 return (BUS_PROBE_DEFAULT); 269 } 270 271 static int 272 tegra_efuse_attach(device_t dev) 273 { 274 int rv, rid; 275 phandle_t node; 276 struct tegra_efuse_softc *sc; 277 278 sc = device_get_softc(dev); 279 sc->dev = dev; 280 node = ofw_bus_get_node(dev); 281 282 /* Get the memory resource for the register mapping. */ 283 rid = 0; 284 sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 285 RF_ACTIVE); 286 if (sc->mem_res == NULL) { 287 device_printf(dev, "Cannot map registers.\n"); 288 rv = ENXIO; 289 goto fail; 290 } 291 292 /* OFW resources. */ 293 rv = clk_get_by_ofw_name(dev, 0, "fuse", &sc->clk); 294 if (rv != 0) { 295 device_printf(dev, "Cannot get fuse clock: %d\n", rv); 296 goto fail; 297 } 298 rv = clk_enable(sc->clk); 299 if (rv != 0) { 300 device_printf(dev, "Cannot enable clock: %d\n", rv); 301 goto fail; 302 } 303 rv = hwreset_get_by_ofw_name(sc->dev, 0, "fuse", &sc->reset); 304 if (rv != 0) { 305 device_printf(dev, "Cannot get fuse reset\n"); 306 goto fail; 307 } 308 rv = hwreset_deassert(sc->reset); 309 if (rv != 0) { 310 device_printf(sc->dev, "Cannot clear reset\n"); 311 goto fail; 312 } 313 314 /* Tegra124 specific init. */ 315 sc->fuse_begin = TEGRA124_FUSE_BEGIN; 316 tegra124_init_speedo(sc, &tegra_sku_info); 317 318 dev_sc = sc; 319 320 if (bootverbose) 321 tegra_efuse_dump_sku(); 322 return (bus_generic_attach(dev)); 323 324 fail: 325 dev_sc = NULL; 326 if (sc->clk != NULL) 327 clk_release(sc->clk); 328 if (sc->reset != NULL) 329 hwreset_release(sc->reset); 330 if (sc->mem_res != NULL) 331 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res); 332 333 return (rv); 334 } 335 336 static int 337 tegra_efuse_detach(device_t dev) 338 { 339 struct tegra_efuse_softc *sc; 340 341 sc = device_get_softc(dev); 342 dev_sc = NULL; 343 if (sc->clk != NULL) 344 clk_release(sc->clk); 345 if (sc->reset != NULL) 346 hwreset_release(sc->reset); 347 if (sc->mem_res != NULL) 348 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res); 349 350 return (bus_generic_detach(dev)); 351 } 352 353 static device_method_t tegra_efuse_methods[] = { 354 /* Device interface */ 355 DEVMETHOD(device_probe, tegra_efuse_probe), 356 DEVMETHOD(device_attach, tegra_efuse_attach), 357 DEVMETHOD(device_detach, tegra_efuse_detach), 358 359 DEVMETHOD_END 360 }; 361 362 static devclass_t tegra_efuse_devclass; 363 static DEFINE_CLASS_0(efuse, tegra_efuse_driver, tegra_efuse_methods, 364 sizeof(struct tegra_efuse_softc)); 365 EARLY_DRIVER_MODULE(tegra_efuse, simplebus, tegra_efuse_driver, 366 tegra_efuse_devclass, NULL, NULL, BUS_PASS_TIMER); 367