int tegra_set_emc(const void *blob, unsigned rate) { struct emc_ctlr *emc; const u32 *table; int err, i; err = decode_emc(blob, rate, &emc, &table); if (err) { debug("Warning: no valid EMC (%d), memory timings unset\n", err); return err; } debug("%s: Table found, setting EMC values as follows:\n", __func__); for (i = 0; i < TEGRA_EMC_NUM_REGS; i++) { u32 value = fdt32_to_cpu(table[i]); u32 addr = (uintptr_t)emc + emc_reg_addr[i]; debug(" %#x: %#x\n", addr, value); writel(value, addr); } /* trigger emc with new settings */ clock_adjust_periph_pll_div(PERIPH_ID_EMC, CLOCK_ID_MEMORY, clock_get_rate(CLOCK_ID_MEMORY), NULL); debug("EMC clock set to %lu\n", clock_get_periph_rate(PERIPH_ID_EMC, CLOCK_ID_MEMORY)); return 0; }
static void mmc_change_clock(struct mmc_host *host, uint clock) { int div; unsigned short clk; unsigned long timeout; debug(" mmc_change_clock called\n"); /* * Change Tegra SDMMCx clock divisor here. Source is PLLP_OUT0 */ if (clock == 0) goto out; #ifdef CONFIG_TEGRA186 { ulong rate = clk_set_rate(&host->clk, clock); div = (rate + clock - 1) / clock; } #else clock_adjust_periph_pll_div(host->mmc_id, CLOCK_ID_PERIPH, clock, &div); #endif debug("div = %d\n", div); writew(0, &host->reg->clkcon); /* * CLKCON * SELFREQ[15:8] : base clock divided by value * ENSDCLK[2] : SD Clock Enable * STBLINTCLK[1] : Internal Clock Stable * ENINTCLK[0] : Internal Clock Enable */ div >>= 1; clk = ((div << TEGRA_MMC_CLKCON_SDCLK_FREQ_SEL_SHIFT) | TEGRA_MMC_CLKCON_INTERNAL_CLOCK_ENABLE); writew(clk, &host->reg->clkcon); /* Wait max 10 ms */ timeout = 10; while (!(readw(&host->reg->clkcon) & TEGRA_MMC_CLKCON_INTERNAL_CLOCK_STABLE)) { if (timeout == 0) { printf("%s: timeout error\n", __func__); return; } timeout--; udelay(1000); } clk |= TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE; writew(clk, &host->reg->clkcon); debug("mmc_change_clock: clkcon = %08X\n", clk); out: host->clock = clock; }
static ulong tegra_car_clk_set_rate(struct clk *clk, ulong rate) { enum clock_id parent; debug("%s(clk=%p, rate=%lu) (dev=%p, id=%lu)\n", __func__, clk, rate, clk->dev, clk->id); parent = clock_get_periph_parent(clk->id); return clock_adjust_periph_pll_div(clk->id, parent, rate, NULL); }