* Copyright (C) 2005 Ivan Kokshaysky
* Copyright (C) 2009 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
case AT91_PMC_MCKR_CSS_SLOW:
return CONFIG_SYS_AT91_SLOW_CLOCK;
case AT91_PMC_MCKR_CSS_MAIN:
- return gd->main_clk_rate_hz;
+ return gd->arch.main_clk_rate_hz;
case AT91_PMC_MCKR_CSS_PLLA:
- return gd->plla_rate_hz;
+ return gd->arch.plla_rate_hz;
case AT91_PMC_MCKR_CSS_PLLB:
- return gd->pllb_rate_hz;
+ return gd->arch.pllb_rate_hz;
}
return 0;
main_clock = tmp * (CONFIG_SYS_AT91_SLOW_CLOCK / 16);
}
#endif
- gd->main_clk_rate_hz = main_clock;
+ gd->arch.main_clk_rate_hz = main_clock;
/* report if PLLA is more than mildly overclocked */
- gd->plla_rate_hz = at91_pll_rate(main_clock, readl(&pmc->pllar));
+ gd->arch.plla_rate_hz = at91_pll_rate(main_clock, readl(&pmc->pllar));
#ifdef CONFIG_USB_ATMEL
/*
*
* REVISIT: assumes MCK doesn't derive from PLLB!
*/
- gd->at91_pllb_usb_init = at91_pll_calc(main_clock, 48000000 * 2) |
+ gd->arch.at91_pllb_usb_init = at91_pll_calc(main_clock, 48000000 * 2) |
AT91_PMC_PLLBR_USBDIV_2;
- gd->pllb_rate_hz = at91_pll_rate(main_clock, gd->at91_pllb_usb_init);
+ gd->arch.pllb_rate_hz = at91_pll_rate(main_clock,
+ gd->arch.at91_pllb_usb_init);
#endif
/*
* For now, assume this parentage won't change.
*/
mckr = readl(&pmc->mckr);
-#if defined(CONFIG_AT91SAM9G45) || defined(CONFIG_AT91SAM9M10G45)
+#if defined(CONFIG_AT91SAM9G45) || defined(CONFIG_AT91SAM9M10G45) \
+ || defined(CONFIG_AT91SAM9N12) || defined(CONFIG_AT91SAM9X5)
/* plla divisor by 2 */
- gd->plla_rate_hz /= (1 << ((mckr & 1 << 12) >> 12));
+ gd->arch.plla_rate_hz /= (1 << ((mckr & 1 << 12) >> 12));
#endif
- gd->mck_rate_hz = at91_css_to_rate(mckr & AT91_PMC_MCKR_CSS_MASK);
- freq = gd->mck_rate_hz;
+ gd->arch.mck_rate_hz = at91_css_to_rate(mckr & AT91_PMC_MCKR_CSS_MASK);
+ freq = gd->arch.mck_rate_hz;
freq /= (1 << ((mckr & AT91_PMC_MCKR_PRES_MASK) >> 2)); /* prescale */
#if defined(CONFIG_AT91SAM9G20)
/* mdiv ; (x >> 7) = ((x >> 8) * 2) */
- gd->mck_rate_hz = (mckr & AT91_PMC_MCKR_MDIV_MASK) ?
+ gd->arch.mck_rate_hz = (mckr & AT91_PMC_MCKR_MDIV_MASK) ?
freq / ((mckr & AT91_PMC_MCKR_MDIV_MASK) >> 7) : freq;
if (mckr & AT91_PMC_MCKR_MDIV_MASK)
freq /= 2; /* processor clock division */
-#elif defined(CONFIG_AT91SAM9G45) || defined(CONFIG_AT91SAM9M10G45)
- gd->mck_rate_hz = (mckr & AT91_PMC_MCKR_MDIV_MASK) ==
+#elif defined(CONFIG_AT91SAM9G45) || defined(CONFIG_AT91SAM9M10G45) \
+ || defined(CONFIG_AT91SAM9N12) || defined(CONFIG_AT91SAM9X5)
+ /* mdiv <==> divisor
+ * 0 <==> 1
+ * 1 <==> 2
+ * 2 <==> 4
+ * 3 <==> 3
+ */
+ gd->arch.mck_rate_hz = (mckr & AT91_PMC_MCKR_MDIV_MASK) ==
(AT91_PMC_MCKR_MDIV_2 | AT91_PMC_MCKR_MDIV_4)
? freq / 3
: freq / (1 << ((mckr & AT91_PMC_MCKR_MDIV_MASK) >> 8));
#else
- gd->mck_rate_hz = freq / (1 << ((mckr & AT91_PMC_MCKR_MDIV_MASK) >> 8));
+ gd->arch.mck_rate_hz = freq /
+ (1 << ((mckr & AT91_PMC_MCKR_MDIV_MASK) >> 8));
#endif
- gd->cpu_clk_rate_hz = freq;
+ gd->arch.cpu_clk_rate_hz = freq;
return 0;
}
+
+#if !defined(AT91_PLL_LOCK_TIMEOUT)
+#define AT91_PLL_LOCK_TIMEOUT 1000000
+#endif
+
+void at91_plla_init(u32 pllar)
+{
+ struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+ int timeout = AT91_PLL_LOCK_TIMEOUT;
+
+ writel(pllar, &pmc->pllar);
+ while (!(readl(&pmc->sr) & (AT91_PMC_LOCKA | AT91_PMC_MCKRDY))) {
+ timeout--;
+ if (timeout == 0)
+ break;
+ }
+}
+void at91_pllb_init(u32 pllbr)
+{
+ struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+ int timeout = AT91_PLL_LOCK_TIMEOUT;
+
+ writel(pllbr, &pmc->pllbr);
+ while (!(readl(&pmc->sr) & (AT91_PMC_LOCKB | AT91_PMC_MCKRDY))) {
+ timeout--;
+ if (timeout == 0)
+ break;
+ }
+}
+
+void at91_mck_init(u32 mckr)
+{
+ struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+ int timeout = AT91_PLL_LOCK_TIMEOUT;
+ u32 tmp;
+
+ tmp = readl(&pmc->mckr);
+ tmp &= ~(AT91_PMC_MCKR_PRES_MASK |
+ AT91_PMC_MCKR_MDIV_MASK |
+ AT91_PMC_MCKR_PLLADIV_MASK |
+ AT91_PMC_MCKR_CSS_MASK);
+ tmp |= mckr & (AT91_PMC_MCKR_PRES_MASK |
+ AT91_PMC_MCKR_MDIV_MASK |
+ AT91_PMC_MCKR_PLLADIV_MASK |
+ AT91_PMC_MCKR_CSS_MASK);
+ writel(tmp, &pmc->mckr);
+
+ while (!(readl(&pmc->sr) & AT91_PMC_MCKRDY)) {
+ timeout--;
+ if (timeout == 0)
+ break;
+ }
+}
+
+void at91_periph_clk_enable(int id)
+{
+ struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+
+ writel(1 << id, &pmc->pcer);
+}