static freq_t _spi_set_freq(clk_t* clk, freq_t hz) { freq_t fin; int clkid; int rpre, r; clkid = exynos_clk_get_priv_id(clk); switch (clk->id) { case CLK_SPI0_ISP: clkid += 32; break; case CLK_SPI1_ISP: clkid += 35; break; case CLK_SPI0: clkid += 12; break; case CLK_SPI1: clkid += 15; break; case CLK_SPI2: clkid += 18; break; default: return 0; } fin = clk_get_freq(clk->parent); rpre = fin / 0xf / hz; r = fin / (rpre + 1) / hz; exynos_cmu_set_div(_clk_regs, clkid, 1, r); exynos_cmu_set_div(_clk_regs, clkid + 2, 2, rpre); return clk_get_freq(clk); }
static freq_t _peric_clk_set_freq(clk_t* clk, freq_t hz) { freq_t fin; int clkid; int div; fin = clk_get_freq(clk->parent); div = fin / hz; clkid = exynos_clk_get_priv_id(clk); /* The DIV register has an additional 2 word offset */ clkid += 16; exynos_cmu_set_div(_clk_regs, clkid, 1, div); return clk_get_freq(clk); }
void clk_print_tree(clk_t* clk, char* prefix) { int depth = strlen(prefix); char new_prefix[depth + 2]; strcpy(new_prefix, prefix); strcpy(new_prefix + depth, "|"); while (clk != NULL) { const char* units[] = {"hz", "Khz", "Mhz", "Ghz"}; const char** u = units; float freq = clk_get_freq(clk); /* Find frequency with appropriate units */ while(freq > 10000){ freq/= 1000; u++; } /* Generate tree graphics */ if (clk->sibling == NULL) { strcpy(new_prefix + depth, " "); } printf("%s\\%s (%0.1f %s)\n", new_prefix, clk->name, freq, *u); clk_print_tree(clk->child, new_prefix); clk = clk->sibling; } }
/* The SPI div register is a special case as we have 2 dividers, one of which * is 2 nibbles wide */ static freq_t _spi_get_freq(clk_t* clk) { freq_t fin; int clkid; int rpre, r; clkid = exynos_clk_get_priv_id(clk); switch (clk->id) { case CLK_SPI0_ISP: clkid += 32; break; case CLK_SPI1_ISP: clkid += 35; break; case CLK_SPI0: clkid += 12; break; case CLK_SPI1: clkid += 15; break; case CLK_SPI2: clkid += 18; break; default: return 0; } r = exynos_cmu_get_div(_clk_regs, clkid, 1); rpre = exynos_cmu_get_div(_clk_regs, clkid + 2, 2); fin = clk_get_freq(clk->parent); return fin / (r + 1) / (rpre + 1); }
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 freq_t _peric_clk_get_freq(clk_t* clk) { freq_t fin; int clkid; int div; clkid = exynos_clk_get_priv_id(clk); /* The DIV register has an additional 2 word offset */ clkid += 16; div = exynos_cmu_get_div(_clk_regs, clkid, 1); fin = clk_get_freq(clk->parent); return fin / (div + 1); }
static freq_t _pll_set_freq(clk_t* clk, freq_t hz) { volatile uint32_t* ctrl_reg; volatile uint32_t* cfg_reg; uint32_t status_mask; uint32_t fin; uint8_t fdiv; fin = clk_get_freq(clk->parent); fdiv = fin / hz; fdiv = INRANGE(PLL_CTRL_FDIV_MIN, fdiv, PLL_CTRL_FDIV_MAX); status_mask = _decode_pll(clk, &ctrl_reg, &cfg_reg); if (status_mask == 0) { return 0; } /* Program the feedback divider value and the configuration register */ *ctrl_reg &= ~(PLL_CTRL_FDIV_MASK); *ctrl_reg |= PLL_CTRL_FDIV(fdiv); *cfg_reg = pll_cfg_tbl[fdiv - PLL_CTRL_FDIV_MIN].pll_cfg; /* Force the PLL into bypass mode */ *ctrl_reg |= PLL_CTRL_BYPASS_FORCE; /* Assert and de-assert the PLL reset */ *ctrl_reg |= PLL_CTRL_RESET; *ctrl_reg &= ~(PLL_CTRL_RESET); /* Verify that the PLL is locked */ while (!(clk_regs->pll_status & status_mask)); /* Disable the PLL bypass mode */ *ctrl_reg &= ~(PLL_CTRL_BYPASS_FORCE); return clk_get_freq(clk); }
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 jz4780_uart_probe(device_t dev) { struct jz4780_uart_softc *sc; 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); /* Figure out clock setup */ rv = clk_get_by_ofw_name(dev, 0, "module", &sc->clk_mod); if (rv != 0) { device_printf(dev, "Cannot get UART clock: %d\n", rv); return (ENXIO); } rv = clk_enable(sc->clk_mod); if (rv != 0) { device_printf(dev, "Cannot enable UART clock: %d\n", rv); return (ENXIO); } rv = clk_get_by_ofw_name(dev, 0, "baud", &sc->clk_baud); if (rv != 0) { device_printf(dev, "Cannot get UART clock: %d\n", rv); return (ENXIO); } rv = clk_enable(sc->clk_baud); if (rv != 0) { device_printf(dev, "Cannot enable UART clock: %d\n", rv); return (ENXIO); } rv = clk_get_freq(sc->clk_baud, &freq); if (rv != 0) { device_printf(dev, "Cannot determine UART clock frequency: %d\n", rv); return (ENXIO); } if (bootverbose) device_printf(dev, "got UART clock: %lld\n", freq); sc->ns8250_base.base.sc_class = (struct uart_class *)cd->ocd_data; shift = jz4780_uart_get_shift(dev); return (uart_bus_probe(dev, shift, (int)freq, 0, 0)); }
/* PLLs */ static freq_t _pll_get_freq(clk_t* clk) { volatile uint32_t* ctrl_reg; volatile uint32_t* cfg_reg; uint32_t status_mask; uint8_t fdiv; uint32_t fin, fout; status_mask = _decode_pll(clk, &ctrl_reg, &cfg_reg); if (status_mask == 0) { return 0; } fin = clk_get_freq(clk->parent); fdiv = (*ctrl_reg & PLL_CTRL_FDIV_MASK) >> PLL_CTRL_FDIV_SHIFT; fout = fin * fdiv; return fout; }
static void process_msg(struct tegra_xhci_softc *sc, uint32_t req_cmd, uint32_t req_data, uint32_t *resp_cmd, uint32_t *resp_data) { uint64_t freq; int rv; /* In most cases, data are echoed back. */ *resp_data = req_data; switch (req_cmd) { case MBOX_CMD_INC_FALC_CLOCK: case MBOX_CMD_DEC_FALC_CLOCK: rv = clk_set_freq(sc->clk_xusb_falcon_src, req_data * 1000ULL, 0); if (rv == 0) { rv = clk_get_freq(sc->clk_xusb_falcon_src, &freq); *resp_data = (uint32_t)(freq / 1000); } *resp_cmd = rv == 0 ? MBOX_CMD_ACK: MBOX_CMD_NAK; break; case MBOX_CMD_INC_SSPI_CLOCK: case MBOX_CMD_DEC_SSPI_CLOCK: rv = clk_set_freq(sc->clk_xusb_ss, req_data * 1000ULL, 0); if (rv == 0) { rv = clk_get_freq(sc->clk_xusb_ss, &freq); *resp_data = (uint32_t)(freq / 1000); } *resp_cmd = rv == 0 ? MBOX_CMD_ACK: MBOX_CMD_NAK; break; case MBOX_CMD_SET_BW: /* No respense is expected. */ *resp_cmd = 0; break; case MBOX_CMD_SET_SS_PWR_GATING: case MBOX_CMD_SET_SS_PWR_UNGATING: *resp_cmd = MBOX_CMD_NAK; break; case MBOX_CMD_SAVE_DFE_CTLE_CTX: /* Not implemented yet. */ *resp_cmd = MBOX_CMD_ACK; break; case MBOX_CMD_START_HSIC_IDLE: case MBOX_CMD_STOP_HSIC_IDLE: /* Not implemented yet. */ *resp_cmd = MBOX_CMD_NAK; break; case MBOX_CMD_DISABLE_SS_LFPS_DETECTION: case MBOX_CMD_ENABLE_SS_LFPS_DETECTION: /* Not implemented yet. */ *resp_cmd = MBOX_CMD_NAK; break; case MBOX_CMD_AIRPLANE_MODE_ENABLED: case MBOX_CMD_AIRPLANE_MODE_DISABLED: case MBOX_CMD_DBC_WAKE_STACK: case MBOX_CMD_HSIC_PRETEND_CONNECT: case MBOX_CMD_RESET_SSPI: device_printf(sc->dev, "Received unused/unexpected command: %u\n", req_cmd); *resp_cmd = 0; break; default: device_printf(sc->dev, "Received unknown command: %u\n", req_cmd); } }
struct eth_driver* ethif_plat_init(int dev_id, struct ethif_os_interface interface) { struct enet * enet; struct ocotp * ocotp; struct clock* arm_clk; struct imx6_eth_data *eth_data; struct ldesc* ldesc; (void)dev_id; os_iface_init(interface); eth_data = (struct imx6_eth_data*)os_malloc(sizeof(struct imx6_eth_data)); if (eth_data == NULL) { cprintf(COL_IMP, "Failed to allocate dma buffers\n"); return NULL; } ldesc = ldesc_init(RX_DESC_COUNT, RXBUF_SIZE, TX_DESC_COUNT, TXBUF_SIZE); assert(ldesc); /* * We scale up the CPU to improve benchmarking performance * It is not the right place so should be moved later */ arm_clk = clk_get_clock(CLK_ARM); clk_set_freq(arm_clk, CPU_FREQ); CLK_DEBUG(printf("ARM clock frequency: %9d HZ\n", clk_get_freq(arm_clk))); /* initialise the eFuse controller so we can get a MAC address */ ocotp = ocotp_init(); /* Initialise ethernet pins */ gpio_init(); setup_iomux_enet(); /* Initialise the phy library */ miiphy_init(); /* Initialise the phy */ phy_micrel_init(); /* Initialise the RGMII interface */ enet = enet_init(ldesc); assert(enet); /* Fetch and set the MAC address */ if(ocotp == NULL || ocotp_get_mac(ocotp, eth_data->ethaddr)){ memcpy(eth_data->ethaddr, DEFAULT_MAC, 6); } enet_set_mac(enet, eth_data->ethaddr); /* Connect the phy to the ethernet controller */ if(fec_init(CONFIG_FEC_MXC_PHYMASK, enet)){ return NULL; } /* Start the controller */ enet_enable(enet); /* Update book keeping */ eth_data->irq_enabled = 0; eth_data->enet = enet; eth_data->ldesc = ldesc; eth_driver_set_data(&imx6_eth_driver, eth_data); /* done */ return &imx6_eth_driver; }
static int tegra_i2c_attach(device_t dev) { int rv, rid; phandle_t node; struct tegra_i2c_softc *sc; uint64_t freq; sc = device_get_softc(dev); sc->dev = dev; node = ofw_bus_get_node(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; } /* FDT resources. */ rv = clk_get_by_ofw_name(dev, 0, "div-clk", &sc->clk); if (rv != 0) { device_printf(dev, "Cannot get i2c clock: %d\n", rv); goto fail; } rv = hwreset_get_by_ofw_name(sc->dev, 0, "i2c", &sc->reset); if (rv != 0) { device_printf(sc->dev, "Cannot get i2c reset\n"); return (ENXIO); } rv = OF_getencprop(node, "clock-frequency", &sc->bus_freq, sizeof(sc->bus_freq)); if (rv != sizeof(sc->bus_freq)) { sc->bus_freq = 100000; goto fail; } /* Request maximum frequency for I2C block 136MHz (408MHz / 3). */ rv = clk_set_freq(sc->clk, 136000000, CLK_SET_ROUND_DOWN); if (rv != 0) { device_printf(dev, "Cannot set clock frequency\n"); goto fail; } rv = clk_get_freq(sc->clk, &freq); if (rv != 0) { device_printf(dev, "Cannot get clock frequency\n"); goto fail; } sc->core_freq = (uint32_t)freq; rv = clk_enable(sc->clk); if (rv != 0) { device_printf(dev, "Cannot enable clock: %d\n", rv); goto fail; } /* Init hardware. */ rv = tegra_i2c_hw_init(sc); if (rv) { device_printf(dev, "tegra_i2c_activate failed\n"); goto fail; } /* Setup interrupt. */ rv = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE, NULL, tegra_i2c_intr, sc, &sc->irq_h); if (rv) { device_printf(dev, "Cannot setup interrupt.\n"); goto fail; } /* Attach the iicbus. */ sc->iicbus = device_add_child(dev, "iicbus", -1); if (sc->iicbus == NULL) { device_printf(dev, "Could not allocate iicbus instance.\n"); rv = ENXIO; goto fail; } /* Probe and attach the iicbus. */ return (bus_generic_attach(dev)); fail: 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 jz4780_timer_attach(device_t dev) { struct jz4780_timer_softc *sc = device_get_softc(dev); pcell_t counter_freq; clk_t clk; /* There should be exactly one instance. */ if (jz4780_timer_sc != NULL) return (ENXIO); sc->dev = dev; if (bus_alloc_resources(dev, jz4780_timer_spec, sc->res)) { device_printf(dev, "can not allocate resources for device\n"); return (ENXIO); } counter_freq = 0; if (clk_get_by_name(dev, "ext", &clk) == 0) { uint64_t clk_freq; if (clk_get_freq(clk, &clk_freq) == 0) counter_freq = (uint32_t)clk_freq / 16; clk_release(clk); } if (counter_freq == 0) { device_printf(dev, "unable to determine ext clock frequency\n"); /* Hardcode value we 'know' is correct */ counter_freq = 48000000 / 16; } /* * Disable the timers, select the input for each timer, * clear and then start OST. */ /* Stop OST, if it happens to be running */ CSR_WRITE_4(sc, JZ_TC_TECR, TESR_OST); /* Stop all other channels as well */ CSR_WRITE_4(sc, JZ_TC_TECR, TESR_TCST0 | TESR_TCST1 | TESR_TCST2 | TESR_TCST3 | TESR_TCST4 | TESR_TCST5 | TESR_TCST6 | TESR_TCST3); /* Clear detect mask flags */ CSR_WRITE_4(sc, JZ_TC_TFCR, 0xFFFFFFFF); /* Mask all interrupts */ CSR_WRITE_4(sc, JZ_TC_TMSR, 0xFFFFFFFF); /* Init counter with known data */ CSR_WRITE_4(sc, JZ_OST_CTRL, 0); CSR_WRITE_4(sc, JZ_OST_CNT_LO, 0); CSR_WRITE_4(sc, JZ_OST_CNT_HI, 0); CSR_WRITE_4(sc, JZ_OST_DATA, 0xffffffff); /* Configure counter for external clock */ CSR_WRITE_4(sc, JZ_OST_CTRL, OSTC_EXT_EN | OSTC_MODE | OSTC_DIV_16); /* Start the counter again */ CSR_WRITE_4(sc, JZ_TC_TESR, TESR_OST); /* Configure TCU channel 5 similarly to OST and leave it disabled */ CSR_WRITE_4(sc, JZ_TC_TCSR(5), TCSR_EXT_EN | TCSR_DIV_16); CSR_WRITE_4(sc, JZ_TC_TMCR, TMR_FMASK(5)); if (bus_setup_intr(dev, sc->res[2], INTR_TYPE_CLK, jz4780_hardclock, NULL, sc, &sc->ih_cookie)) { device_printf(dev, "could not setup interrupt handler\n"); bus_release_resources(dev, jz4780_timer_spec, sc->res); return (ENXIO); } sc->et.et_name = "JZ4780 TCU5"; sc->et.et_flags = ET_FLAGS_ONESHOT; sc->et.et_frequency = counter_freq; sc->et.et_quality = 1000; sc->et.et_min_period = (0x00000002LLU * SBT_1S) / sc->et.et_frequency; sc->et.et_max_period = (0x0000fffeLLU * SBT_1S) / sc->et.et_frequency; sc->et.et_start = jz4780_timer_start; sc->et.et_stop = jz4780_timer_stop; sc->et.et_priv = sc; et_register(&sc->et); sc->tc.tc_get_timecount = jz4780_get_timecount; sc->tc.tc_name = "JZ4780 OST"; sc->tc.tc_frequency = counter_freq; sc->tc.tc_counter_mask = ~0u; sc->tc.tc_quality = 1000; sc->tc.tc_priv = sc; tc_init(&sc->tc); /* Now when tc is initialized, allow DELAY to find it */ jz4780_timer_sc = sc; return (0); }