123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256 |
- /*
- * Copyright (C) 2005-2006 Atmel Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
- #include <linux/clk.h>
- #include <linux/delay.h>
- #include <linux/dw_dmac.h>
- #include <linux/fb.h>
- #include <linux/init.h>
- #include <linux/platform_device.h>
- #include <linux/dma-mapping.h>
- #include <linux/slab.h>
- #include <linux/gpio.h>
- #include <linux/spi/spi.h>
- #include <linux/usb/atmel_usba_udc.h>
- #include <mach/atmel-mci.h>
- #include <linux/atmel-mci.h>
- #include <asm/io.h>
- #include <asm/irq.h>
- #include <mach/at32ap700x.h>
- #include <mach/board.h>
- #include <mach/hmatrix.h>
- #include <mach/portmux.h>
- #include <mach/sram.h>
- #include <sound/atmel-abdac.h>
- #include <sound/atmel-ac97c.h>
- #include <video/atmel_lcdc.h>
- #include "clock.h"
- #include "pio.h"
- #include "pm.h"
- #define PBMEM(base) \
- { \
- .start = base, \
- .end = base + 0x3ff, \
- .flags = IORESOURCE_MEM, \
- }
- #define IRQ(num) \
- { \
- .start = num, \
- .end = num, \
- .flags = IORESOURCE_IRQ, \
- }
- #define NAMED_IRQ(num, _name) \
- { \
- .start = num, \
- .end = num, \
- .name = _name, \
- .flags = IORESOURCE_IRQ, \
- }
- /* REVISIT these assume *every* device supports DMA, but several
- * don't ... tc, smc, pio, rtc, watchdog, pwm, ps2, and more.
- */
- #define DEFINE_DEV(_name, _id) \
- static u64 _name##_id##_dma_mask = DMA_BIT_MASK(32); \
- static struct platform_device _name##_id##_device = { \
- .name = #_name, \
- .id = _id, \
- .dev = { \
- .dma_mask = &_name##_id##_dma_mask, \
- .coherent_dma_mask = DMA_BIT_MASK(32), \
- }, \
- .resource = _name##_id##_resource, \
- .num_resources = ARRAY_SIZE(_name##_id##_resource), \
- }
- #define DEFINE_DEV_DATA(_name, _id) \
- static u64 _name##_id##_dma_mask = DMA_BIT_MASK(32); \
- static struct platform_device _name##_id##_device = { \
- .name = #_name, \
- .id = _id, \
- .dev = { \
- .dma_mask = &_name##_id##_dma_mask, \
- .platform_data = &_name##_id##_data, \
- .coherent_dma_mask = DMA_BIT_MASK(32), \
- }, \
- .resource = _name##_id##_resource, \
- .num_resources = ARRAY_SIZE(_name##_id##_resource), \
- }
- #define select_peripheral(port, pin_mask, periph, flags) \
- at32_select_periph(GPIO_##port##_BASE, pin_mask, \
- GPIO_##periph, flags)
- #define DEV_CLK(_name, devname, bus, _index) \
- static struct clk devname##_##_name = { \
- .name = #_name, \
- .dev = &devname##_device.dev, \
- .parent = &bus##_clk, \
- .mode = bus##_clk_mode, \
- .get_rate = bus##_clk_get_rate, \
- .index = _index, \
- }
- static DEFINE_SPINLOCK(pm_lock);
- static struct clk osc0;
- static struct clk osc1;
- static unsigned long osc_get_rate(struct clk *clk)
- {
- return at32_board_osc_rates[clk->index];
- }
- static unsigned long pll_get_rate(struct clk *clk, unsigned long control)
- {
- unsigned long div, mul, rate;
- div = PM_BFEXT(PLLDIV, control) + 1;
- mul = PM_BFEXT(PLLMUL, control) + 1;
- rate = clk->parent->get_rate(clk->parent);
- rate = (rate + div / 2) / div;
- rate *= mul;
- return rate;
- }
- static long pll_set_rate(struct clk *clk, unsigned long rate,
- u32 *pll_ctrl)
- {
- unsigned long mul;
- unsigned long mul_best_fit = 0;
- unsigned long div;
- unsigned long div_min;
- unsigned long div_max;
- unsigned long div_best_fit = 0;
- unsigned long base;
- unsigned long pll_in;
- unsigned long actual = 0;
- unsigned long rate_error;
- unsigned long rate_error_prev = ~0UL;
- u32 ctrl;
- /* Rate must be between 80 MHz and 200 Mhz. */
- if (rate < 80000000UL || rate > 200000000UL)
- return -EINVAL;
- ctrl = PM_BF(PLLOPT, 4);
- base = clk->parent->get_rate(clk->parent);
- /* PLL input frequency must be between 6 MHz and 32 MHz. */
- div_min = DIV_ROUND_UP(base, 32000000UL);
- div_max = base / 6000000UL;
- if (div_max < div_min)
- return -EINVAL;
- for (div = div_min; div <= div_max; div++) {
- pll_in = (base + div / 2) / div;
- mul = (rate + pll_in / 2) / pll_in;
- if (mul == 0)
- continue;
- actual = pll_in * mul;
- rate_error = abs(actual - rate);
- if (rate_error < rate_error_prev) {
- mul_best_fit = mul;
- div_best_fit = div;
- rate_error_prev = rate_error;
- }
- if (rate_error == 0)
- break;
- }
- if (div_best_fit == 0)
- return -EINVAL;
- ctrl |= PM_BF(PLLMUL, mul_best_fit - 1);
- ctrl |= PM_BF(PLLDIV, div_best_fit - 1);
- ctrl |= PM_BF(PLLCOUNT, 16);
- if (clk->parent == &osc1)
- ctrl |= PM_BIT(PLLOSC);
- *pll_ctrl = ctrl;
- return actual;
- }
- static unsigned long pll0_get_rate(struct clk *clk)
- {
- u32 control;
- control = pm_readl(PLL0);
- return pll_get_rate(clk, control);
- }
- static void pll1_mode(struct clk *clk, int enabled)
- {
- unsigned long timeout;
- u32 status;
- u32 ctrl;
- ctrl = pm_readl(PLL1);
- if (enabled) {
- if (!PM_BFEXT(PLLMUL, ctrl) && !PM_BFEXT(PLLDIV, ctrl)) {
- pr_debug("clk %s: failed to enable, rate not set\n",
- clk->name);
- return;
- }
- ctrl |= PM_BIT(PLLEN);
- pm_writel(PLL1, ctrl);
- /* Wait for PLL lock. */
- for (timeout = 10000; timeout; timeout--) {
- status = pm_readl(ISR);
- if (status & PM_BIT(LOCK1))
- break;
- udelay(10);
- }
- if (!(status & PM_BIT(LOCK1)))
- printk(KERN_ERR "clk %s: timeout waiting for lock\n",
- clk->name);
- } else {
- ctrl &= ~PM_BIT(PLLEN);
- pm_writel(PLL1, ctrl);
- }
- }
- static unsigned long pll1_get_rate(struct clk *clk)
- {
- u32 control;
- control = pm_readl(PLL1);
- return pll_get_rate(clk, control);
- }
- static long pll1_set_rate(struct clk *clk, unsigned long rate, int apply)
- {
- u32 ctrl = 0;
- unsigned long actual_rate;
- actual_rate = pll_set_rate(clk, rate, &ctrl);
- if (apply) {
- if (actual_rate != rate)
- return -EINVAL;
|