static int jzsmb_attach(device_t dev) { struct jzsmb_softc *sc; phandle_t node; int error; sc = device_get_softc(dev); node = ofw_bus_get_node(dev); mtx_init(&sc->mtx, device_get_nameunit(dev), "jzsmb", MTX_DEF); error = clk_get_by_ofw_index(dev, 0, 0, &sc->clk); if (error != 0) { device_printf(dev, "cannot get clock\n"); goto fail; } error = clk_enable(sc->clk); if (error != 0) { device_printf(dev, "cannot enable clock\n"); goto fail; } error = clk_get_freq(sc->clk, &sc->bus_freq); if (error != 0 || sc->bus_freq == 0) { device_printf(dev, "cannot get bus frequency\n"); return (error); } if (bus_alloc_resources(dev, jzsmb_spec, &sc->res) != 0) { device_printf(dev, "cannot allocate resources for device\n"); error = ENXIO; goto fail; } if (OF_getencprop(node, "clock-frequency", &sc->i2c_freq, sizeof(sc->i2c_freq)) != 0 || sc->i2c_freq == 0) sc->i2c_freq = 100000; /* Default to standard mode */ sc->iicbus = device_add_child(dev, "iicbus", -1); if (sc->iicbus == NULL) { device_printf(dev, "cannot add iicbus child device\n"); error = ENXIO; goto fail; } bus_generic_attach(dev); return (0); fail: bus_release_resources(dev, jzsmb_spec, &sc->res); if (sc->clk != NULL) clk_release(sc->clk); mtx_destroy(&sc->mtx); return (error); }
static int awusbphy_init(device_t dev) { struct awusbphy_softc *sc; phandle_t node; char pname[20]; int error, off; regulator_t reg; hwreset_t rst; clk_t clk; sc = device_get_softc(dev); node = ofw_bus_get_node(dev); /* Enable clocks */ for (off = 0; clk_get_by_ofw_index(dev, off, &clk) == 0; off++) { error = clk_enable(clk); if (error != 0) { device_printf(dev, "couldn't enable clock %s\n", clk_get_name(clk)); return (error); } } /* De-assert resets */ for (off = 0; hwreset_get_by_ofw_idx(dev, off, &rst) == 0; off++) { error = hwreset_deassert(rst); if (error != 0) { device_printf(dev, "couldn't de-assert reset %d\n", off); return (error); } } /* Get regulators */ for (off = 0; off < USBPHY_NPHYS; off++) { snprintf(pname, sizeof(pname), "usb%d_vbus-supply", off); if (regulator_get_by_ofw_property(dev, pname, ®) == 0) sc->reg[off] = reg; } /* Get GPIOs */ error = gpio_pin_get_by_ofw_property(dev, node, "usb0_id_det-gpios", &sc->id_det_pin); if (error == 0) sc->id_det_valid = 1; error = gpio_pin_get_by_ofw_property(dev, node, "usb0_vbus_det-gpios", &sc->vbus_det_pin); if (error == 0) sc->vbus_det_valid = 1; return (0); }
static int tegra_uart_probe(device_t dev) { struct tegra_softc *sc; phandle_t node; uint64_t freq; int shift; int rv; const struct ofw_compat_data *cd; sc = device_get_softc(dev); if (!ofw_bus_status_okay(dev)) return (ENXIO); cd = ofw_bus_search_compatible(dev, compat_data); if (cd->ocd_data == 0) return (ENXIO); sc->ns8250_base.base.sc_class = (struct uart_class *)cd->ocd_data; rv = hwreset_get_by_ofw_name(dev, "serial", &sc->reset); if (rv != 0) { device_printf(dev, "Cannot get 'serial' reset\n"); return (ENXIO); } rv = hwreset_deassert(sc->reset); if (rv != 0) { device_printf(dev, "Cannot unreset 'serial' reset\n"); return (ENXIO); } node = ofw_bus_get_node(dev); shift = uart_fdt_get_shift1(node); rv = clk_get_by_ofw_index(dev, 0, &sc->clk); if (rv != 0) { device_printf(dev, "Cannot get UART clock: %d\n", rv); return (ENXIO); } rv = clk_enable(sc->clk); if (rv != 0) { device_printf(dev, "Cannot enable UART clock: %d\n", rv); return (ENXIO); } rv = clk_get_freq(sc->clk, &freq); if (rv != 0) { device_printf(dev, "Cannot enable UART clock: %d\n", rv); return (ENXIO); } device_printf(dev, "got UART clock: %lld\n", freq); return (uart_bus_probe(dev, shift, (int)freq, 0, 0)); }
static int a10_twsi_attach(device_t dev) { struct twsi_softc *sc; clk_t clk; hwreset_t rst; int error; sc = device_get_softc(dev); /* De-assert reset */ if (hwreset_get_by_ofw_idx(dev, 0, &rst) == 0) { error = hwreset_deassert(rst); if (error != 0) { device_printf(dev, "could not de-assert reset\n"); return (error); } } /* Activate clock */ error = clk_get_by_ofw_index(dev, 0, &clk); if (error != 0) { device_printf(dev, "could not find clock\n"); return (error); } error = clk_enable(clk); if (error != 0) { device_printf(dev, "could not enable clock\n"); return (error); } sc->reg_data = TWI_DATA; sc->reg_slave_addr = TWI_ADDR; sc->reg_slave_ext_addr = TWI_XADDR; sc->reg_control = TWI_CNTR; sc->reg_status = TWI_STAT; sc->reg_baud_rate = TWI_CCR; sc->reg_soft_reset = TWI_SRST; /* Setup baud rate params */ sc->baud_rate[IIC_SLOW].param = TWSI_BAUD_RATE_PARAM(11, 2); sc->baud_rate[IIC_FAST].param = TWSI_BAUD_RATE_PARAM(11, 2); sc->baud_rate[IIC_FASTEST].param = TWSI_BAUD_RATE_PARAM(2, 2); return (twsi_attach(dev)); }
static int awusbphy_init(device_t dev) { char pname[20]; int error, off; regulator_t reg; hwreset_t rst; clk_t clk; /* Enable clocks */ for (off = 0; clk_get_by_ofw_index(dev, off, &clk) == 0; off++) { error = clk_enable(clk); if (error != 0) { device_printf(dev, "couldn't enable clock %s\n", clk_get_name(clk)); return (error); } } /* De-assert resets */ for (off = 0; hwreset_get_by_ofw_idx(dev, off, &rst) == 0; off++) { error = hwreset_deassert(rst); if (error != 0) { device_printf(dev, "couldn't de-assert reset %d\n", off); return (error); } } /* Enable regulator(s) */ for (off = 0; off < USBPHY_NUMOFF; off++) { snprintf(pname, sizeof(pname), "usb%d_vbus-supply", off); if (regulator_get_by_ofw_property(dev, pname, ®) != 0) continue; error = regulator_enable(reg); if (error != 0) { device_printf(dev, "couldn't enable regulator %s\n", pname); return (error); } } return (0); }
static int clk_fixed_init_fixed_factor(struct clk_fixed_softc *sc, phandle_t node, struct clk_fixed_def *def) { int rv; clk_t parent; def->clkdef.id = 1; rv = OF_getencprop(node, "clock-mult", &def->mult, sizeof(def->mult)); if (rv <= 0) return (ENXIO); rv = OF_getencprop(node, "clock-div", &def->div, sizeof(def->div)); if (rv <= 0) return (ENXIO); /* Get name of parent clock */ rv = clk_get_by_ofw_index(sc->dev, 0, &parent); if (rv != 0) return (ENXIO); def->clkdef.parent_names = malloc(sizeof(char *), M_OFWPROP, M_WAITOK); def->clkdef.parent_names[0] = clk_get_name(parent); def->clkdef.parent_cnt = 1; clk_release(parent); return (0); }
static int aw_usbclk_attach(device_t dev) { struct aw_usbclk_softc *sc; struct clkdom *clkdom; const char **names; const char *pname; int index, nout, error; enum aw_usbclk_type type; uint32_t *indices; clk_t clk_parent, clk_parent_pll; bus_size_t psize; phandle_t node; sc = device_get_softc(dev); node = ofw_bus_get_node(dev); indices = NULL; type = ofw_bus_search_compatible(dev, compat_data)->ocd_data; if (ofw_reg_to_paddr(node, 0, &sc->reg, &psize, NULL) != 0) { device_printf(dev, "cannot parse 'reg' property\n"); return (ENXIO); } clkdom = clkdom_create(dev); nout = clk_parse_ofw_out_names(dev, node, &names, &indices); if (nout == 0) { device_printf(dev, "no clock outputs found\n"); error = ENOENT; goto fail; } if (indices == NULL && type == AW_A10_USBCLK) indices = aw_usbclk_indices_a10; else if (indices == NULL && type == AW_H3_USBCLK) indices = aw_usbclk_indices_h3; error = clk_get_by_ofw_index(dev, 0, &clk_parent); if (error != 0) { device_printf(dev, "cannot parse clock parent\n"); return (ENXIO); } if (type == AW_A83T_USBCLK) { error = clk_get_by_ofw_index(dev, 1, &clk_parent_pll); if (error != 0) { device_printf(dev, "cannot parse pll clock parent\n"); return (ENXIO); } } for (index = 0; index < nout; index++) { if (strcmp(names[index], "usb_hsic_pll") == 0) pname = clk_get_name(clk_parent_pll); else pname = clk_get_name(clk_parent); error = aw_usbclk_create(dev, sc->reg, clkdom, pname, names[index], indices != NULL ? indices[index] : index); if (error) goto fail; } if (clkdom_finit(clkdom) != 0) { device_printf(dev, "cannot finalize clkdom initialization\n"); error = ENXIO; goto fail; } if (bootverbose) clkdom_dump(clkdom); hwreset_register_ofw_provider(dev); return (0); fail: return (error); }
static int a10dmac_attach(device_t dev) { struct a10dmac_softc *sc; unsigned int index; clk_t clk; int error; sc = device_get_softc(dev); if (bus_alloc_resources(dev, a10dmac_spec, sc->sc_res)) { device_printf(dev, "cannot allocate resources for device\n"); return (ENXIO); } mtx_init(&sc->sc_mtx, "a10 dmac", NULL, MTX_SPIN); /* Activate DMA controller clock */ error = clk_get_by_ofw_index(dev, 0, 0, &clk); if (error != 0) { device_printf(dev, "cannot get clock\n"); return (error); } error = clk_enable(clk); if (error != 0) { device_printf(dev, "cannot enable clock\n"); return (error); } /* Disable all interrupts and clear pending status */ DMA_WRITE(sc, AWIN_DMA_IRQ_EN_REG, 0); DMA_WRITE(sc, AWIN_DMA_IRQ_PEND_STA_REG, ~0); /* Initialize channels */ for (index = 0; index < NDMA_CHANNELS; index++) { sc->sc_ndma_channels[index].ch_sc = sc; sc->sc_ndma_channels[index].ch_index = index; sc->sc_ndma_channels[index].ch_type = CH_NDMA; sc->sc_ndma_channels[index].ch_callback = NULL; sc->sc_ndma_channels[index].ch_callbackarg = NULL; sc->sc_ndma_channels[index].ch_regoff = AWIN_NDMA_REG(index); DMACH_WRITE(&sc->sc_ndma_channels[index], AWIN_NDMA_CTL_REG, 0); } for (index = 0; index < DDMA_CHANNELS; index++) { sc->sc_ddma_channels[index].ch_sc = sc; sc->sc_ddma_channels[index].ch_index = index; sc->sc_ddma_channels[index].ch_type = CH_DDMA; sc->sc_ddma_channels[index].ch_callback = NULL; sc->sc_ddma_channels[index].ch_callbackarg = NULL; sc->sc_ddma_channels[index].ch_regoff = AWIN_DDMA_REG(index); DMACH_WRITE(&sc->sc_ddma_channels[index], AWIN_DDMA_CTL_REG, 0); } error = bus_setup_intr(dev, sc->sc_res[1], INTR_MPSAFE | INTR_TYPE_MISC, NULL, a10dmac_intr, sc, &sc->sc_ih); if (error != 0) { device_printf(dev, "could not setup interrupt handler\n"); bus_release_resources(dev, a10dmac_spec, sc->sc_res); mtx_destroy(&sc->sc_mtx); return (ENXIO); } OF_device_register_xref(OF_xref_from_node(ofw_bus_get_node(dev)), dev); return (0); }
static int tegra_rtc_attach(device_t dev) { int rv, rid; struct tegra_rtc_softc *sc; sc = device_get_softc(dev); sc->dev = dev; LOCK_INIT(sc); /* Get the memory resource for the register mapping. */ rid = 0; sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (sc->mem_res == NULL) { device_printf(dev, "Cannot map registers.\n"); rv = ENXIO; goto fail; } /* Allocate our IRQ resource. */ rid = 0; sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE); if (sc->irq_res == NULL) { device_printf(dev, "Cannot allocate interrupt.\n"); rv = ENXIO; goto fail; } /* OFW resources. */ rv = clk_get_by_ofw_index(dev, 0, 0, &sc->clk); if (rv != 0) { device_printf(dev, "Cannot get i2c clock: %d\n", rv); goto fail; } rv = clk_enable(sc->clk); if (rv != 0) { device_printf(dev, "Cannot enable clock: %d\n", rv); goto fail; } /* Init hardware. */ WR4(sc, RTC_SECONDS_ALARM0, 0); WR4(sc, RTC_SECONDS_ALARM1, 0); WR4(sc, RTC_INTR_STATUS, 0xFFFFFFFF); WR4(sc, RTC_INTR_MASK, 0); /* Setup interrupt */ rv = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE, NULL, tegra_rtc_intr, sc, &sc->irq_h); if (rv) { device_printf(dev, "Cannot setup interrupt.\n"); goto fail; } /* * Register as a time of day clock with 1-second resolution. * * XXXX Not yet, we don't have support for multiple RTCs */ /* clock_register(dev, 1000000); */ return (bus_generic_attach(dev)); fail: if (sc->clk != NULL) clk_release(sc->clk); if (sc->irq_h != NULL) bus_teardown_intr(dev, sc->irq_res, sc->irq_h); if (sc->irq_res != NULL) bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res); if (sc->mem_res != NULL) bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res); LOCK_DESTROY(sc); return (rv); }
static int aw_cpuclk_attach(device_t dev) { struct clk_mux_def def; struct clkdom *clkdom; bus_addr_t paddr; bus_size_t psize; phandle_t node; int error, ncells, i; clk_t clk; node = ofw_bus_get_node(dev); if (ofw_reg_to_paddr(node, 0, &paddr, &psize, NULL) != 0) { device_printf(dev, "cannot parse 'reg' property\n"); return (ENXIO); } error = ofw_bus_parse_xref_list_get_length(node, "clocks", "#clock-cells", &ncells); if (error != 0) { device_printf(dev, "cannot get clock count\n"); return (error); } clkdom = clkdom_create(dev); memset(&def, 0, sizeof(def)); def.clkdef.id = 1; def.clkdef.parent_names = malloc(sizeof(char *) * ncells, M_OFWPROP, M_WAITOK); for (i = 0; i < ncells; i++) { error = clk_get_by_ofw_index(dev, 0, i, &clk); if (error != 0) { device_printf(dev, "cannot get clock %d\n", i); goto fail; } def.clkdef.parent_names[i] = clk_get_name(clk); clk_release(clk); } def.clkdef.parent_cnt = ncells; def.offset = paddr; def.shift = CPU_CLK_SRC_SEL_SHIFT; def.width = CPU_CLK_SRC_SEL_WIDTH; error = clk_parse_ofw_clk_name(dev, node, &def.clkdef.name); if (error != 0) { device_printf(dev, "cannot parse clock name\n"); error = ENXIO; goto fail; } error = clknode_mux_register(clkdom, &def); if (error != 0) { device_printf(dev, "cannot register mux clock\n"); error = ENXIO; goto fail; } if (clkdom_finit(clkdom) != 0) { device_printf(dev, "cannot finalize clkdom initialization\n"); error = ENXIO; goto fail; } OF_prop_free(__DECONST(char *, def.clkdef.parent_names)); OF_prop_free(__DECONST(char *, def.clkdef.name)); if (bootverbose) clkdom_dump(clkdom); return (0); fail: OF_prop_free(__DECONST(char *, def.clkdef.name)); return (error); }
static int aw_gate_attach(device_t dev) { struct clkdom *clkdom; const char **names; int index, nout, error; uint32_t *indices; clk_t clk_parent; bus_addr_t paddr; bus_size_t psize; phandle_t node; node = ofw_bus_get_node(dev); indices = NULL; if (ofw_reg_to_paddr(node, 0, &paddr, &psize, NULL) != 0) { device_printf(dev, "cannot parse 'reg' property\n"); return (ENXIO); } clkdom = clkdom_create(dev); nout = clk_parse_ofw_out_names(dev, node, &names, &indices); if (nout == 0) { device_printf(dev, "no clock outputs found\n"); error = ENOENT; goto fail; } if (indices == NULL) { device_printf(dev, "no clock-indices property\n"); error = ENXIO; goto fail; } error = clk_get_by_ofw_index(dev, 0, &clk_parent); if (error != 0) { device_printf(dev, "cannot parse clock parent\n"); return (ENXIO); } for (index = 0; index < nout; index++) { error = aw_gate_create(dev, paddr, clkdom, clk_get_name(clk_parent), names[index], indices[index]); if (error) goto fail; } if (clkdom_finit(clkdom) != 0) { device_printf(dev, "cannot finalize clkdom initialization\n"); error = ENXIO; goto fail; } if (bootverbose) clkdom_dump(clkdom); return (0); fail: return (error); }