static void exyo_attach(device_t parent, device_t self, void *aux) { const struct exyo_locators *l = NULL; struct exyo_softc * const sc = &exyo_sc; prop_dictionary_t dict = device_properties(self); size_t nl = 0; sc->sc_dev = self; sc->sc_bst = &exynos_bs_tag; sc->sc_a4x_bst = &exynos_a4x_bs_tag; sc->sc_bsh = exynos_core_bsh; sc->sc_dmat = &exynos_bus_dma_tag; sc->sc_coherent_dmat = &exynos_coherent_bus_dma_tag; const uint16_t product_id = EXYNOS_PRODUCT_ID(exynos_soc_id); aprint_naive(": Exynos %x\n", product_id); aprint_normal(": Exynos %x\n", product_id); /* add sysctl nodes */ exynos_sysctl_cpufreq_init(); /* add all children */ #if defined(EXYNOS4) if (IS_EXYNOS4_P()) { l = exynos4_locinfo.locators; nl = exynos4_locinfo.nlocators; } #endif #if defined(EXYNOS5) if (IS_EXYNOS5_P()) { l = exynos5_locinfo.locators; nl = exynos5_locinfo.nlocators; } #endif KASSERT(l != NULL); KASSERT(nl > 0); for (const struct exyo_locators *loc = l; loc < l + nl; loc++) { char prop_name[31]; bool skip; if (loc->loc_port == EXYOCF_PORT_DEFAULT) { snprintf(prop_name, sizeof(prop_name), "no-%s", loc->loc_name); } else { snprintf(prop_name, sizeof(prop_name), "no-%s-%d", loc->loc_name, loc->loc_port); } if (prop_dictionary_get_bool(dict, prop_name, &skip) && skip) continue; struct exyo_attach_args exyo = { .exyo_loc = *loc, .exyo_core_bst = sc->sc_bst, .exyo_core_a4x_bst = sc->sc_a4x_bst, .exyo_core_bsh = sc->sc_bsh, .exyo_dmat = sc->sc_dmat, .exyo_coherent_dmat = sc->sc_coherent_dmat, }; cfdata_t cf = config_search_ia(exyo_find, sc->sc_dev, "exyo", &exyo); if (cf == NULL) { #ifdef EXYO_REQUIRED if (loc->loc_flags & EXYO_REQUIRED) panic("%s: failed to find %s!", __func__, loc->loc_name); #endif if (loc->loc_port == EXYOCF_PORT_DEFAULT) { aprint_verbose_dev(self, "%s not found\n", loc->loc_name); } else { aprint_verbose_dev(self, "%s%d not found\n", loc->loc_name, loc->loc_port); } continue; } config_attach(sc->sc_dev, cf, &exyo, exyo_print); } }
void exynos_device_register(device_t self, void *aux) { if (device_is_a(self, "armperiph") && device_is_a(device_parent(self), "mainbus")) { /* * XXX KLUDGE ALERT XXX * The iot mainbus supplies is completely wrong since it scales * addresses by 2. The simplest remedy is to replace with our * bus space used for the armcore registers (which armperiph uses). */ struct mainbus_attach_args * const mb = aux; mb->mb_iot = &armv7_generic_bs_tag; return; } if (device_is_a(self, "armgic") && device_is_a(device_parent(self), "armperiph")) { /* * The Exynos4420 armgic is located at a different location! */ extern uint32_t exynos_soc_id; switch (EXYNOS_PRODUCT_ID(exynos_soc_id)) { #ifdef EXYNOS5 case 0xe5410: /* offsets not changed on matt's request */ #if 0 mpcaa->mpcaa_memh = EXYNOS_CORE_VBASE; mpcaa->mpcaa_off1 = EXYNOS5_GIC_IOP_DISTRIBUTOR_OFFSET; mpcaa->mpcaa_off2 = EXYNOS5_GIC_IOP_CONTROLLER_OFFSET; #endif break; case 0xe5422: { struct mpcore_attach_args * const mpcaa = aux; mpcaa->mpcaa_memh = EXYNOS_CORE_VBASE; mpcaa->mpcaa_off1 = EXYNOS5_GIC_IOP_DISTRIBUTOR_OFFSET; mpcaa->mpcaa_off2 = EXYNOS5_GIC_IOP_CONTROLLER_OFFSET; break; } #endif #ifdef EXYNOS4 case 0xe4410: case 0xe4412: { struct mpcore_attach_args * const mpcaa = aux; mpcaa->mpcaa_memh = EXYNOS_CORE_VBASE; mpcaa->mpcaa_off1 = EXYNOS4_GIC_DISTRIBUTOR_OFFSET; mpcaa->mpcaa_off2 = EXYNOS4_GIC_CNTR_OFFSET; break; } #endif default: panic("%s: unknown SoC product id %#x", __func__, (u_int)EXYNOS_PRODUCT_ID(exynos_soc_id)); } return; } if (device_is_a(self, "armgtmr") || device_is_a(self, "mct")) { #ifdef EXYNOS5 /* * The global timer is dependent on the MCT running. */ bus_size_t o = EXYNOS5_MCT_OFFSET + MCT_G_TCON; uint32_t v = bus_space_read_4(&armv7_generic_bs_tag, exynos_core_bsh, o); v |= G_TCON_START; bus_space_write_4(&armv7_generic_bs_tag, exynos_core_bsh, o, v); #endif /* * The frequencies of the timers are the reference * frequency. */ prop_dictionary_set_uint32(device_properties(self), "frequency", EXYNOS_F_IN_FREQ); return; } }