Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
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", &reg) == 0) {
		error = regulator_enable(reg);
		if (error != 0) {
			device_printf(dev, "could not enable PHY regulator\n");
			return (error);
		}
	}

	return (0);
}
Ejemplo n.º 4
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);
}
Ejemplo n.º 5
0
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;
}
Ejemplo n.º 6
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);
}
Ejemplo n.º 7
0
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);
}