summaryrefslogtreecommitdiff
path: root/bsp/at91sam9260/platform/system_clock.c
diff options
context:
space:
mode:
Diffstat (limited to 'bsp/at91sam9260/platform/system_clock.c')
-rw-r--r--bsp/at91sam9260/platform/system_clock.c362
1 files changed, 181 insertions, 181 deletions
diff --git a/bsp/at91sam9260/platform/system_clock.c b/bsp/at91sam9260/platform/system_clock.c
index f59aba016c..a8f866fdd6 100644
--- a/bsp/at91sam9260/platform/system_clock.c
+++ b/bsp/at91sam9260/platform/system_clock.c
@@ -14,270 +14,270 @@
static rt_list_t clocks;
struct clk {
- char name[32];
- rt_uint32_t rate_hz;
- struct clk *parent;
- rt_list_t node;
+ char name[32];
+ rt_uint32_t rate_hz;
+ struct clk *parent;
+ rt_list_t node;
};
static struct clk clk32k = {
- "clk32k",
- AT91_SLOW_CLOCK,
- RT_NULL,
- {RT_NULL, RT_NULL},
+ "clk32k",
+ AT91_SLOW_CLOCK,
+ RT_NULL,
+ {RT_NULL, RT_NULL},
};
static struct clk main_clk = {
- "main",
- 0,
- RT_NULL,
- {RT_NULL, RT_NULL},
+ "main",
+ 0,
+ RT_NULL,
+ {RT_NULL, RT_NULL},
};
static struct clk plla = {
- "plla",
- 0,
- RT_NULL,
- {RT_NULL, RT_NULL},
+ "plla",
+ 0,
+ RT_NULL,
+ {RT_NULL, RT_NULL},
};
static struct clk mck = {
- "mck",
- 0,
- RT_NULL,
- {RT_NULL, RT_NULL},
+ "mck",
+ 0,
+ RT_NULL,
+ {RT_NULL, RT_NULL},
};
static struct clk uhpck = {
- "uhpck",
- 0,
- RT_NULL,
- {RT_NULL, RT_NULL},
+ "uhpck",
+ 0,
+ RT_NULL,
+ {RT_NULL, RT_NULL},
};
static struct clk pllb = {
- "pllb",
- 0,
- &main_clk,
- {RT_NULL, RT_NULL},
+ "pllb",
+ 0,
+ &main_clk,
+ {RT_NULL, RT_NULL},
};
static struct clk udpck = {
- "udpck",
- 0,
- &pllb,
- {RT_NULL, RT_NULL},
+ "udpck",
+ 0,
+ &pllb,
+ {RT_NULL, RT_NULL},
};
static struct clk *const standard_pmc_clocks[] = {
- /* four primary clocks */
- &clk32k,
- &main_clk,
- &plla,
+ /* four primary clocks */
+ &clk32k,
+ &main_clk,
+ &plla,
- /* MCK */
- &mck
+ /* MCK */
+ &mck
};
/* clocks cannot be de-registered no refcounting necessary */
struct clk *clk_get(const char *id)
{
- struct clk *clk;
- rt_list_t *list;
-
- for (list = (&clocks)->next; list != &clocks; list = list->next)
- {
- clk = (struct clk *)rt_list_entry(list, struct clk, node);
- if (rt_strcmp(id, clk->name) == 0)
- return clk;
- }
+ struct clk *clk;
+ rt_list_t *list;
- return RT_NULL;
+ for (list = (&clocks)->next; list != &clocks; list = list->next)
+ {
+ clk = (struct clk *)rt_list_entry(list, struct clk, node);
+ if (rt_strcmp(id, clk->name) == 0)
+ return clk;
+ }
+
+ return RT_NULL;
}
rt_uint32_t clk_get_rate(struct clk *clk)
{
- rt_uint32_t flags;
- rt_uint32_t rate;
+ rt_uint32_t flags;
+ rt_uint32_t rate;
- for (;;) {
- rate = clk->rate_hz;
- if (rate || !clk->parent)
- break;
- clk = clk->parent;
- }
- return rate;
+ for (;;) {
+ rate = clk->rate_hz;
+ if (rate || !clk->parent)
+ break;
+ clk = clk->parent;
+ }
+ return rate;
}
static rt_uint32_t at91_pll_rate(struct clk *pll, rt_uint32_t freq, rt_uint32_t reg)
{
- unsigned mul, div;
+ unsigned mul, div;
- div = reg & 0xff;
- mul = (reg >> 16) & 0x7ff;
- if (div && mul) {
- freq /= div;
- freq *= mul + 1;
- } else
- freq = 0;
+ div = reg & 0xff;
+ mul = (reg >> 16) & 0x7ff;
+ if (div && mul) {
+ freq /= div;
+ freq *= mul + 1;
+ } else
+ freq = 0;
- return freq;
+ return freq;
}
static unsigned at91_pll_calc(unsigned main_freq, unsigned out_freq)
{
- unsigned i, div = 0, mul = 0, diff = 1 << 30;
- unsigned ret = (out_freq > 155000000) ? 0xbe00 : 0x3e00;
+ unsigned i, div = 0, mul = 0, diff = 1 << 30;
+ unsigned ret = (out_freq > 155000000) ? 0xbe00 : 0x3e00;
- /* PLL output max 240 MHz (or 180 MHz per errata) */
- if (out_freq > 240000000)
- goto fail;
+ /* PLL output max 240 MHz (or 180 MHz per errata) */
+ if (out_freq > 240000000)
+ goto fail;
- for (i = 1; i < 256; i++) {
- int diff1;
- unsigned input, mul1;
+ for (i = 1; i < 256; i++) {
+ int diff1;
+ unsigned input, mul1;
- /*
- * PLL input between 1MHz and 32MHz per spec, but lower
- * frequences seem necessary in some cases so allow 100K.
- * Warning: some newer products need 2MHz min.
- */
- input = main_freq / i;
- if (input < 100000)
- continue;
- if (input > 32000000)
- continue;
+ /*
+ * PLL input between 1MHz and 32MHz per spec, but lower
+ * frequences seem necessary in some cases so allow 100K.
+ * Warning: some newer products need 2MHz min.
+ */
+ input = main_freq / i;
+ if (input < 100000)
+ continue;
+ if (input > 32000000)
+ continue;
- mul1 = out_freq / input;
- if (mul1 > 2048)
- continue;
- if (mul1 < 2)
- goto fail;
+ mul1 = out_freq / input;
+ if (mul1 > 2048)
+ continue;
+ if (mul1 < 2)
+ goto fail;
- diff1 = out_freq - input * mul1;
- if (diff1 < 0)
- diff1 = -diff1;
- if (diff > diff1) {
- diff = diff1;
- div = i;
- mul = mul1;
- if (diff == 0)
- break;
- }
- }
- if (i == 256 && diff > (out_freq >> 5))
- goto fail;
- return ret | ((mul - 1) << 16) | div;
+ diff1 = out_freq - input * mul1;
+ if (diff1 < 0)
+ diff1 = -diff1;
+ if (diff > diff1) {
+ diff = diff1;
+ div = i;
+ mul = mul1;
+ if (diff == 0)
+ break;
+ }
+ }
+ if (i == 256 && diff > (out_freq >> 5))
+ goto fail;
+ return ret | ((mul - 1) << 16) | div;
fail:
- return 0;
+ return 0;
}
static rt_uint32_t at91_usb_rate(struct clk *pll, rt_uint32_t freq, rt_uint32_t reg)
{
- if (pll == &pllb && (reg & AT91_PMC_USB96M))
- return freq / 2;
- else
- return freq;
+ if (pll == &pllb && (reg & AT91_PMC_USB96M))
+ return freq / 2;
+ else
+ return freq;
}
/* PLLB generated USB full speed clock init */
static void at91_pllb_usbfs_clock_init(rt_uint32_t main_clock)
{
- rt_uint32_t at91_pllb_usb_init;
- /*
- * USB clock init: choose 48 MHz PLLB value,
- * disable 48MHz clock during usb peripheral suspend.
- *
- * REVISIT: assumes MCK doesn't derive from PLLB!
- */
- uhpck.parent = &pllb;
+ rt_uint32_t at91_pllb_usb_init;
+ /*
+ * USB clock init: choose 48 MHz PLLB value,
+ * disable 48MHz clock during usb peripheral suspend.
+ *
+ * REVISIT: assumes MCK doesn't derive from PLLB!
+ */
+ uhpck.parent = &pllb;
+
+ at91_pllb_usb_init = at91_pll_calc(main_clock, 48000000 * 2) | AT91_PMC_USB96M;
+ pllb.rate_hz = at91_pll_rate(&pllb, main_clock, at91_pllb_usb_init);
- at91_pllb_usb_init = at91_pll_calc(main_clock, 48000000 * 2) | AT91_PMC_USB96M;
- pllb.rate_hz = at91_pll_rate(&pllb, main_clock, at91_pllb_usb_init);
-
- at91_sys_write(AT91_CKGR_PLLBR, 0);
+ at91_sys_write(AT91_CKGR_PLLBR, 0);
- udpck.rate_hz = at91_usb_rate(&pllb, pllb.rate_hz, at91_pllb_usb_init);
- uhpck.rate_hz = at91_usb_rate(&pllb, pllb.rate_hz, at91_pllb_usb_init);
+ udpck.rate_hz = at91_usb_rate(&pllb, pllb.rate_hz, at91_pllb_usb_init);
+ uhpck.rate_hz = at91_usb_rate(&pllb, pllb.rate_hz, at91_pllb_usb_init);
}
static struct clk *at91_css_to_clk(unsigned long css)
{
- switch (css) {
- case AT91_PMC_CSS_SLOW:
- return &clk32k;
- case AT91_PMC_CSS_MAIN:
- return &main_clk;
- case AT91_PMC_CSS_PLLA:
- return &plla;
- case AT91_PMC_CSS_PLLB:
- return &pllb;
- }
+ switch (css) {
+ case AT91_PMC_CSS_SLOW:
+ return &clk32k;
+ case AT91_PMC_CSS_MAIN:
+ return &main_clk;
+ case AT91_PMC_CSS_PLLA:
+ return &plla;
+ case AT91_PMC_CSS_PLLB:
+ return &pllb;
+ }
- return RT_NULL;
+ return RT_NULL;
}
#define false 0
#define true 1
int at91_clock_init(rt_uint32_t main_clock)
{
- unsigned tmp, freq, mckr;
- int i;
- int pll_overclock = false;
+ unsigned tmp, freq, mckr;
+ int i;
+ int pll_overclock = false;
+
+ /*
+ * When the bootloader initialized the main oscillator correctly,
+ * there's no problem using the cycle counter. But if it didn't,
+ * or when using oscillator bypass mode, we must be told the speed
+ * of the main clock.
+ */
+ if (!main_clock) {
+ do {
+ tmp = at91_sys_read(AT91_CKGR_MCFR);
+ } while (!(tmp & AT91_PMC_MAINRDY));
+ main_clock = (tmp & AT91_PMC_MAINF) * (AT91_SLOW_CLOCK / 16);
+ }
+ main_clk.rate_hz = main_clock;
- /*
- * When the bootloader initialized the main oscillator correctly,
- * there's no problem using the cycle counter. But if it didn't,
- * or when using oscillator bypass mode, we must be told the speed
- * of the main clock.
- */
- if (!main_clock) {
- do {
- tmp = at91_sys_read(AT91_CKGR_MCFR);
- } while (!(tmp & AT91_PMC_MAINRDY));
- main_clock = (tmp & AT91_PMC_MAINF) * (AT91_SLOW_CLOCK / 16);
- }
- main_clk.rate_hz = main_clock;
+ /* report if PLLA is more than mildly overclocked */
+ plla.rate_hz = at91_pll_rate(&plla, main_clock, at91_sys_read(AT91_CKGR_PLLAR));
+ if (plla.rate_hz > 209000000)
+ pll_overclock = true;
+ if (pll_overclock)
+ ;//rt_kprintf("Clocks: PLLA overclocked, %ld MHz\n", plla.rate_hz / 1000000);
- /* report if PLLA is more than mildly overclocked */
- plla.rate_hz = at91_pll_rate(&plla, main_clock, at91_sys_read(AT91_CKGR_PLLAR));
- if (plla.rate_hz > 209000000)
- pll_overclock = true;
- if (pll_overclock)
- ;//rt_kprintf("Clocks: PLLA overclocked, %ld MHz\n", plla.rate_hz / 1000000);
+ at91_pllb_usbfs_clock_init(main_clock);
- at91_pllb_usbfs_clock_init(main_clock);
+ /*
+ * MCK and CPU derive from one of those primary clocks.
+ * For now, assume this parentage won't change.
+ */
+ mckr = at91_sys_read(AT91_PMC_MCKR);
+ mck.parent = at91_css_to_clk(mckr & AT91_PMC_CSS);
+ freq = mck.parent->rate_hz;
+ freq /= (1 << ((mckr & AT91_PMC_PRES) >> 2)); /* prescale */
- /*
- * MCK and CPU derive from one of those primary clocks.
- * For now, assume this parentage won't change.
- */
- mckr = at91_sys_read(AT91_PMC_MCKR);
- mck.parent = at91_css_to_clk(mckr & AT91_PMC_CSS);
- freq = mck.parent->rate_hz;
- freq /= (1 << ((mckr & AT91_PMC_PRES) >> 2)); /* prescale */
-
- mck.rate_hz = freq / (1 << ((mckr & AT91_PMC_MDIV) >> 8)); /* mdiv */
+ mck.rate_hz = freq / (1 << ((mckr & AT91_PMC_MDIV) >> 8)); /* mdiv */
- /* Register the PMC's standard clocks */
- rt_list_init(&clocks);
- for (i = 0; i < ARRAY_SIZE(standard_pmc_clocks); i++)
- rt_list_insert_after(&clocks, &standard_pmc_clocks[i]->node);
+ /* Register the PMC's standard clocks */
+ rt_list_init(&clocks);
+ for (i = 0; i < ARRAY_SIZE(standard_pmc_clocks); i++)
+ rt_list_insert_after(&clocks, &standard_pmc_clocks[i]->node);
- rt_list_insert_after(&clocks, &pllb.node);
- rt_list_insert_after(&clocks, &uhpck.node);
- rt_list_insert_after(&clocks, &udpck.node);
+ rt_list_insert_after(&clocks, &pllb.node);
+ rt_list_insert_after(&clocks, &uhpck.node);
+ rt_list_insert_after(&clocks, &udpck.node);
- /* MCK and CPU clock are "always on" */
- //clk_enable(&mck);
+ /* MCK and CPU clock are "always on" */
+ //clk_enable(&mck);
- /*rt_kprintf("Clocks: CPU %u MHz, master %u MHz, main %u.%03u MHz\n",
- freq / 1000000, (unsigned) mck.rate_hz / 1000000,
- (unsigned) main_clock / 1000000,
- ((unsigned) main_clock % 1000000) / 1000);*///cause blocked
+ /*rt_kprintf("Clocks: CPU %u MHz, master %u MHz, main %u.%03u MHz\n",
+ freq / 1000000, (unsigned) mck.rate_hz / 1000000,
+ (unsigned) main_clock / 1000000,
+ ((unsigned) main_clock % 1000000) / 1000);*///cause blocked
- return 0;
+ return 0;
}
/**
@@ -285,6 +285,6 @@ int at91_clock_init(rt_uint32_t main_clock)
*/
void rt_hw_clock_init(void)
{
- at91_clock_init(18432000);
+ at91_clock_init(18432000);
}