int stm32mp1_ddr_clk_enable(struct ddr_info *priv, uint16_t mem_speed) { unsigned long ddrphy_clk; unsigned long ddr_clk; struct clk clk; int ret; int idx; for (idx = 0; idx < ARRAY_SIZE(clkname); idx++) { ret = clk_get_by_name(priv->dev, clkname[idx], &clk); if (!ret) ret = clk_enable(&clk); if (ret) { printf("error for %s : %d\n", clkname[idx], ret); return ret; } } priv->clk = clk; ddrphy_clk = clk_get_rate(&priv->clk); debug("DDR: mem_speed (%d MHz), RCC %d MHz\n", mem_speed, (u32)(ddrphy_clk / 1000 / 1000)); /* max 10% frequency delta */ ddr_clk = abs(ddrphy_clk - mem_speed * 1000 * 1000); if (ddr_clk > (mem_speed * 1000 * 100)) { pr_err("DDR expected freq %d MHz, current is %d MHz\n", mem_speed, (u32)(ddrphy_clk / 1000 / 1000)); return -EINVAL; } return 0; }
int soc_clk_ctl(const char *name, ulong *rate, enum clk_ctl_ops ctl) { int ret; ulong mhz_rate, priv_rate; struct clk clk; /* Dummy fmeas device, just to be able to use standard clk_* api */ struct udevice fmeas = { .name = "clk-fmeas", .node = ofnode_path("/clk-fmeas"), }; ret = clk_get_by_name(&fmeas, name, &clk); if (ret) { pr_err("clock '%s' not found, err=%d\n", name, ret); return ret; } if (ctl & CLK_ON) { ret = clk_enable(&clk); if (ret && ret != -ENOSYS && ret != -ENOTSUPP) return ret; } if ((ctl & CLK_SET) && rate) { priv_rate = ctl & CLK_MHZ ? (*rate) * HZ_IN_MHZ : *rate; ret = clk_set_rate(&clk, priv_rate); if (ret) return ret; } if (ctl & CLK_OFF) { ret = clk_disable(&clk); if (ret) { pr_err("clock '%s' can't be disabled, err=%d\n", name, ret); return ret; } } priv_rate = clk_get_rate(&clk); clk_free(&clk); mhz_rate = ceil(priv_rate, HZ_IN_MHZ); if (ctl & CLK_MHZ) priv_rate = mhz_rate; if ((ctl & CLK_GET) && rate) *rate = priv_rate; if ((ctl & CLK_PRINT) && (ctl & CLK_MHZ)) printf("HSDK: clock '%s' rate %lu MHz\n", name, priv_rate); else if (ctl & CLK_PRINT) printf("HSDK: clock '%s' rate %lu Hz\n", name, priv_rate); else debug("HSDK: clock '%s' rate %lu MHz\n", name, mhz_rate); return 0; }
static int a20_if_dwc_init(device_t dev) { const char *tx_parent_name; char *phy_type; clk_t clk_tx, clk_tx_parent; regulator_t reg; phandle_t node; int error; node = ofw_bus_get_node(dev); /* Configure PHY for MII or RGMII mode */ if (OF_getprop_alloc(node, "phy-mode", 1, (void **)&phy_type)) { error = clk_get_by_ofw_name(dev, 0, "allwinner_gmac_tx", &clk_tx); if (error != 0) { device_printf(dev, "could not get tx clk\n"); return (error); } if (strcmp(phy_type, "rgmii") == 0) tx_parent_name = "gmac_int_tx"; else tx_parent_name = "mii_phy_tx"; error = clk_get_by_name(dev, tx_parent_name, &clk_tx_parent); if (error != 0) { device_printf(dev, "could not get clock '%s'\n", tx_parent_name); return (error); } error = clk_set_parent_by_clk(clk_tx, clk_tx_parent); if (error != 0) { device_printf(dev, "could not set tx clk parent\n"); return (error); } } /* Enable PHY regulator if applicable */ if (regulator_get_by_ofw_property(dev, 0, "phy-supply", ®) == 0) { error = regulator_enable(reg); if (error != 0) { device_printf(dev, "could not enable PHY regulator\n"); return (error); } } return (0); }
static int zynq_gem_probe(struct udevice *dev) { void *bd_space; struct zynq_gem_priv *priv = dev_get_priv(dev); int ret; /* Align rxbuffers to ARCH_DMA_MINALIGN */ priv->rxbuffers = memalign(ARCH_DMA_MINALIGN, RX_BUF * PKTSIZE_ALIGN); if (!priv->rxbuffers) return -ENOMEM; memset(priv->rxbuffers, 0, RX_BUF * PKTSIZE_ALIGN); /* Align bd_space to MMU_SECTION_SHIFT */ bd_space = memalign(1 << MMU_SECTION_SHIFT, BD_SPACE); if (!bd_space) return -ENOMEM; mmu_set_region_dcache_behaviour((phys_addr_t)bd_space, BD_SPACE, DCACHE_OFF); /* Initialize the bd spaces for tx and rx bd's */ priv->tx_bd = (struct emac_bd *)bd_space; priv->rx_bd = (struct emac_bd *)((ulong)bd_space + BD_SEPRN_SPACE); ret = clk_get_by_name(dev, "tx_clk", &priv->clk); if (ret < 0) { dev_err(dev, "failed to get clock\n"); return -EINVAL; } priv->bus = mdio_alloc(); priv->bus->read = zynq_gem_miiphy_read; priv->bus->write = zynq_gem_miiphy_write; priv->bus->priv = priv; ret = mdio_register_seq(priv->bus, dev->seq); if (ret) return ret; return zynq_phy_init(dev); }
static __maybe_unused int stm32mp1_ddr_setup(struct udevice *dev) { struct ddr_info *priv = dev_get_priv(dev); int ret, idx; struct clk axidcg; struct stm32mp1_ddr_config config; #define PARAM(x, y) \ { x,\ offsetof(struct stm32mp1_ddr_config, y),\ sizeof(config.y) / sizeof(u32)} #define CTL_PARAM(x) PARAM("st,ctl-"#x, c_##x) #define PHY_PARAM(x) PARAM("st,phy-"#x, p_##x) const struct { const char *name; /* name in DT */ const u32 offset; /* offset in config struct */ const u32 size; /* size of parameters */ } param[] = { CTL_PARAM(reg), CTL_PARAM(timing), CTL_PARAM(map), CTL_PARAM(perf), PHY_PARAM(reg), PHY_PARAM(timing), PHY_PARAM(cal) }; config.info.speed = dev_read_u32_default(dev, "st,mem-speed", 0); config.info.size = dev_read_u32_default(dev, "st,mem-size", 0); config.info.name = dev_read_string(dev, "st,mem-name"); if (!config.info.name) { debug("%s: no st,mem-name\n", __func__); return -EINVAL; } printf("RAM: %s\n", config.info.name); for (idx = 0; idx < ARRAY_SIZE(param); idx++) { ret = dev_read_u32_array(dev, param[idx].name, (void *)((u32)&config + param[idx].offset), param[idx].size); debug("%s: %s[0x%x] = %d\n", __func__, param[idx].name, param[idx].size, ret); if (ret) { pr_err("%s: Cannot read %s\n", __func__, param[idx].name); return -EINVAL; } } ret = clk_get_by_name(dev, "axidcg", &axidcg); if (ret) { debug("%s: Cannot found axidcg\n", __func__); return -EINVAL; } clk_disable(&axidcg); /* disable clock gating during init */ stm32mp1_ddr_init(priv, &config); clk_enable(&axidcg); /* enable clock gating */ /* check size */ debug("%s : get_ram_size(%x, %x)\n", __func__, (u32)priv->info.base, (u32)STM32_DDR_SIZE); priv->info.size = get_ram_size((long *)priv->info.base, STM32_DDR_SIZE); debug("%s : %x\n", __func__, (u32)priv->info.size); /* check memory access for all memory */ if (config.info.size != priv->info.size) { printf("DDR invalid size : 0x%x, expected 0x%x\n", priv->info.size, config.info.size); return -EINVAL; } return 0; }
static int denali_dt_probe(struct udevice *dev) { struct denali_nand_info *denali = dev_get_priv(dev); const struct denali_dt_data *data; struct clk clk, clk_x, clk_ecc; struct resource res; int ret; data = (void *)dev_get_driver_data(dev); if (data) { denali->revision = data->revision; denali->caps = data->caps; denali->ecc_caps = data->ecc_caps; } denali->dev = dev; ret = dev_read_resource_byname(dev, "denali_reg", &res); if (ret) return ret; denali->reg = devm_ioremap(dev, res.start, resource_size(&res)); ret = dev_read_resource_byname(dev, "nand_data", &res); if (ret) return ret; denali->host = devm_ioremap(dev, res.start, resource_size(&res)); ret = clk_get_by_name(dev, "nand", &clk); if (ret) ret = clk_get_by_index(dev, 0, &clk); if (ret) return ret; ret = clk_get_by_name(dev, "nand_x", &clk_x); if (ret) clk_x.dev = NULL; ret = clk_get_by_name(dev, "ecc", &clk_ecc); if (ret) clk_ecc.dev = NULL; ret = clk_enable(&clk); if (ret) return ret; if (clk_x.dev) { ret = clk_enable(&clk_x); if (ret) return ret; } if (clk_ecc.dev) { ret = clk_enable(&clk_ecc); if (ret) return ret; } if (clk_x.dev) { denali->clk_rate = clk_get_rate(&clk); denali->clk_x_rate = clk_get_rate(&clk_x); } else { /* * Hardcode the clock rates for the backward compatibility. * This works for both SOCFPGA and UniPhier. */ dev_notice(dev, "necessary clock is missing. default clock rates are used.\n"); denali->clk_rate = 50000000; denali->clk_x_rate = 200000000; } ret = reset_get_bulk(dev, &denali->resets); if (ret) dev_warn(dev, "Can't get reset: %d\n", ret); else reset_deassert_bulk(&denali->resets); return denali_init(denali); }
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); }