Ejemplo n.º 1
0
/**
 * zynq_clk_register_aper_clk() - Set up a APER clock with the framework
 * @clk:	Pointer to struct clk for the clock
 * @ctrl:	Clock control register
 * @name:	PLL name
 */
static void zynq_clk_register_aper_clk(struct clk *clk, u32 *ctrl, char *name)
{
	clk->name = name;
	clk->reg = ctrl;
	clk->parent = cpu_1x_clk;
	clk->frequency = zynq_clk_get_rate(clk->parent);
}
Ejemplo n.º 2
0
/**
 * zynq_clk_periph_set_rate() - Set clock rate
 * @clk:	Handle of the peripheral clock
 * @rate:	New clock rate
 * Sets the clock frequency of @clk to @rate. Returns zero on success.
 */
static int zynq_clk_periph_set_rate(struct clk *clk,
		unsigned long rate)
{
	u32 ctrl, div0 = 0, div1 = 0;
	unsigned long prate, new_rate, cur_rate = clk->frequency;

	ctrl = readl(clk->reg);
	prate = zynq_clk_get_rate(clk->parent);
	ctrl &= ~CLK_CTRL_DIV0_MASK;

	if (clk->flags & ZYNQ_CLK_FLAGS_HAS_2_DIVS) {
		ctrl &= ~CLK_CTRL_DIV1_MASK;
		new_rate = periph_calc_two_divs(cur_rate, rate, prate, &div0,
				&div1);
		ctrl |= div1 << CLK_CTRL_DIV1_SHIFT;
	} else {
		div0 = DIV_ROUND_CLOSEST(prate, rate);
		div0 &= ZYNQ_CLK_MAXDIV;
		new_rate = DIV_ROUND_CLOSEST(rate, div0);
	}

	/* write new divs to hardware */
	ctrl |= div0 << CLK_CTRL_DIV0_SHIFT;
	writel(ctrl, clk->reg);

	/* update frequency in clk framework */
	clk->frequency = new_rate;

	return 0;
}
Ejemplo n.º 3
0
static void init_ddr_clocks(void)
{
	u32 div0, div1;
	unsigned long prate = zynq_clk_get_rate(ddrpll_clk);
	u32 clk_ctrl = readl(&slcr_base->ddr_clk_ctrl);

	/* DDR2x */
	clks[ddr2x_clk].reg = &slcr_base->ddr_clk_ctrl;
	clks[ddr2x_clk].parent = ddrpll_clk;
	clks[ddr2x_clk].name = "ddr_2x";
	clks[ddr2x_clk].frequency = ddr2x_get_rate(&clks[ddr2x_clk]);
	clks[ddr2x_clk].ops.get_rate = ddr2x_get_rate;

	/* DDR3x */
	clks[ddr3x_clk].reg = &slcr_base->ddr_clk_ctrl;
	clks[ddr3x_clk].parent = ddrpll_clk;
	clks[ddr3x_clk].name = "ddr_3x";
	clks[ddr3x_clk].frequency = ddr3x_get_rate(&clks[ddr3x_clk]);
	clks[ddr3x_clk].ops.get_rate = ddr3x_get_rate;

	/* DCI */
	clk_ctrl = readl(&slcr_base->dci_clk_ctrl);
	div0 = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
	div1 = (clk_ctrl & CLK_CTRL_DIV1_MASK) >> CLK_CTRL_DIV1_SHIFT;
	clks[dci_clk].reg = &slcr_base->dci_clk_ctrl;
	clks[dci_clk].parent = ddrpll_clk;
	clks[dci_clk].frequency = DIV_ROUND_CLOSEST(
			DIV_ROUND_CLOSEST(prate, div0), div1);
	clks[dci_clk].name = "dci";

	gd->bd->bi_ddr_freq = clks[ddr3x_clk].frequency / 1000000;
}
Ejemplo n.º 4
0
/**
 * ddr3x_get_rate() - Get clock rate of DDR3x clock
 * @clk:	Clock handle
 * Returns the current clock rate of @clk.
 */
static unsigned long ddr3x_get_rate(struct clk *clk)
{
	u32 clk_ctrl = readl(clk->reg);
	u32 div = (clk_ctrl & CLK_CTRL_DIV3X_MASK) >> CLK_CTRL_DIV3X_SHIFT;

	return DIV_ROUND_CLOSEST(zynq_clk_get_rate(clk->parent), div);
}
Ejemplo n.º 5
0
/**
 * soc_clk_dump() - Print clock frequencies
 * Returns zero on success
 *
 * Implementation for the clk dump command.
 */
int soc_clk_dump(void)
{
	int i;

	printf("clk\t\tfrequency\n");
	for (i = 0; i < clk_max; i++) {
		const char *name = zynq_clk_get_name(i);
		if (name)
			printf("%10s%20lu\n", name, zynq_clk_get_rate(i));
	}

	return 0;
}
Ejemplo n.º 6
0
struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
		unsigned int max_hz, unsigned int mode)
{
	int is_dual;
	unsigned long lqspi_frequency;
	struct zynq_qspi_slave *qspi;

	debug("%s: bus: %d cs: %d max_hz: %d mode: %d\n",
	      __func__, bus, cs, max_hz, mode);

	if (!spi_cs_is_valid(bus, cs))
		return NULL;

	is_dual = zynq_qspi_check_is_dual_flash();

	if (is_dual == MODE_UNKNOWN) {
		printf("%s: No QSPI device detected based on MIO settings\n",
		       __func__);
		return NULL;
	}

	zynq_qspi_init_hw(is_dual, cs);

	qspi = spi_alloc_slave(struct zynq_qspi_slave, bus, cs);
	if (!qspi) {
		printf("%s: Fail to allocate zynq_qspi_slave\n", __func__);
		return NULL;
	}

	lqspi_frequency = zynq_clk_get_rate(lqspi_clk);
	if (!lqspi_frequency) {
		debug("Defaulting to 200000000 Hz qspi clk");
		qspi->qspi.master.input_clk_hz = 200000000;
	} else {
		qspi->qspi.master.input_clk_hz = lqspi_frequency;
		debug("Qspi clk frequency set to %ld Hz\n", lqspi_frequency);
	}

	qspi->slave.is_dual = is_dual;
	qspi->slave.rd_cmd = READ_CMD_FULL;
	qspi->slave.wr_cmd = PAGE_PROGRAM | QUAD_PAGE_PROGRAM;
	qspi->qspi.master.speed_hz = qspi->qspi.master.input_clk_hz / 2;
	qspi->qspi.max_speed_hz = qspi->qspi.master.speed_hz;
	qspi->qspi.master.is_dual = is_dual;
	qspi->qspi.mode = mode;
	qspi->qspi.chip_select = 0;
	qspi->qspi.bits_per_word = 32;
	zynq_qspi_setup_transfer(&qspi->qspi, NULL);

	return &qspi->slave;
}
Ejemplo n.º 7
0
static void init_cpu_clocks(void)
{
	int clk_621;
	u32 reg, div, srcsel;
	enum zynq_clk parent;

	reg = readl(&slcr_base->arm_clk_ctrl);
	clk_621 = readl(&slcr_base->clk_621_true) & 1;
	div = (reg & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
	srcsel = (reg & CLK_CTRL_SRCSEL_MASK) >> CLK_CTRL_SRCSEL_SHIFT;
	parent = __zynq_clk_cpu_get_parent(srcsel);

	/* cpu clocks */
	clks[cpu_6or4x_clk].reg = &slcr_base->arm_clk_ctrl;
	clks[cpu_6or4x_clk].parent = parent;
	clks[cpu_6or4x_clk].frequency = DIV_ROUND_CLOSEST(
			zynq_clk_get_rate(parent), div);
	clks[cpu_6or4x_clk].name = "cpu_6or4x";

	clks[cpu_3or2x_clk].reg = &slcr_base->arm_clk_ctrl;
	clks[cpu_3or2x_clk].parent = cpu_6or4x_clk;
	clks[cpu_3or2x_clk].frequency = zynq_clk_get_rate(cpu_6or4x_clk) / 2;
	clks[cpu_3or2x_clk].name = "cpu_3or2x";

	clks[cpu_2x_clk].reg = &slcr_base->arm_clk_ctrl;
	clks[cpu_2x_clk].parent = cpu_6or4x_clk;
	clks[cpu_2x_clk].frequency = zynq_clk_get_rate(cpu_6or4x_clk) /
			(2 + clk_621);
	clks[cpu_2x_clk].name = "cpu_2x";

	clks[cpu_1x_clk].reg = &slcr_base->arm_clk_ctrl;
	clks[cpu_1x_clk].parent = cpu_6or4x_clk;
	clks[cpu_1x_clk].frequency = zynq_clk_get_rate(cpu_6or4x_clk) /
			(4 + 2 * clk_621);
	clks[cpu_1x_clk].name = "cpu_1x";
}
Ejemplo n.º 8
0
/**
 * zynq_clk_periph_get_rate() - Get clock rate
 * @clk:	Handle of the peripheral clock
 * Returns the current clock rate of @clk.
 */
static unsigned long zynq_clk_periph_get_rate(struct clk *clk)
{
	u32 clk_ctrl = readl(clk->reg);
	u32 div0 = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
	u32 div1 = 1;

	if (clk->flags & ZYNQ_CLK_FLAGS_HAS_2_DIVS)
		div1 = (clk_ctrl & CLK_CTRL_DIV1_MASK) >> CLK_CTRL_DIV1_SHIFT;

	/* a register value of zero == division by 1 */
	if (!div0)
		div0 = 1;
	if (!div1)
		div1 = 1;

	return
		DIV_ROUND_CLOSEST(
			DIV_ROUND_CLOSEST(zynq_clk_get_rate(clk->parent), div0),
			div1);
}