linux/arch/arm/mach-sa1100/clock.c
<<
>>
Prefs
   1/*
   2 *  linux/arch/arm/mach-sa1100/clock.c
   3 */
   4#include <linux/module.h>
   5#include <linux/kernel.h>
   6#include <linux/device.h>
   7#include <linux/list.h>
   8#include <linux/errno.h>
   9#include <linux/err.h>
  10#include <linux/string.h>
  11#include <linux/clk.h>
  12#include <linux/spinlock.h>
  13#include <linux/mutex.h>
  14#include <linux/io.h>
  15#include <linux/clkdev.h>
  16
  17#include <mach/hardware.h>
  18#include <mach/generic.h>
  19
  20struct clkops {
  21        void                    (*enable)(struct clk *);
  22        void                    (*disable)(struct clk *);
  23        unsigned long           (*get_rate)(struct clk *);
  24};
  25
  26struct clk {
  27        const struct clkops     *ops;
  28        unsigned int            enabled;
  29};
  30
  31#define DEFINE_CLK(_name, _ops)                         \
  32struct clk clk_##_name = {                              \
  33                .ops    = _ops,                         \
  34        }
  35
  36static DEFINE_SPINLOCK(clocks_lock);
  37
  38static void clk_gpio27_enable(struct clk *clk)
  39{
  40        /*
  41         * First, set up the 3.6864MHz clock on GPIO 27 for the SA-1111:
  42         * (SA-1110 Developer's Manual, section 9.1.2.1)
  43         */
  44        GAFR |= GPIO_32_768kHz;
  45        GPDR |= GPIO_32_768kHz;
  46        TUCR = TUCR_3_6864MHz;
  47}
  48
  49static void clk_gpio27_disable(struct clk *clk)
  50{
  51        TUCR = 0;
  52        GPDR &= ~GPIO_32_768kHz;
  53        GAFR &= ~GPIO_32_768kHz;
  54}
  55
  56static void clk_cpu_enable(struct clk *clk)
  57{
  58}
  59
  60static void clk_cpu_disable(struct clk *clk)
  61{
  62}
  63
  64static unsigned long clk_cpu_get_rate(struct clk *clk)
  65{
  66        return sa11x0_getspeed(0) * 1000;
  67}
  68
  69int clk_enable(struct clk *clk)
  70{
  71        unsigned long flags;
  72
  73        if (clk) {
  74                spin_lock_irqsave(&clocks_lock, flags);
  75                if (clk->enabled++ == 0)
  76                        clk->ops->enable(clk);
  77                spin_unlock_irqrestore(&clocks_lock, flags);
  78        }
  79
  80        return 0;
  81}
  82EXPORT_SYMBOL(clk_enable);
  83
  84void clk_disable(struct clk *clk)
  85{
  86        unsigned long flags;
  87
  88        if (clk) {
  89                WARN_ON(clk->enabled == 0);
  90                spin_lock_irqsave(&clocks_lock, flags);
  91                if (--clk->enabled == 0)
  92                        clk->ops->disable(clk);
  93                spin_unlock_irqrestore(&clocks_lock, flags);
  94        }
  95}
  96EXPORT_SYMBOL(clk_disable);
  97
  98unsigned long clk_get_rate(struct clk *clk)
  99{
 100        if (clk && clk->ops && clk->ops->get_rate)
 101                return clk->ops->get_rate(clk);
 102
 103        return 0;
 104}
 105EXPORT_SYMBOL(clk_get_rate);
 106
 107const struct clkops clk_gpio27_ops = {
 108        .enable         = clk_gpio27_enable,
 109        .disable        = clk_gpio27_disable,
 110};
 111
 112const struct clkops clk_cpu_ops = {
 113        .enable         = clk_cpu_enable,
 114        .disable        = clk_cpu_disable,
 115        .get_rate       = clk_cpu_get_rate,
 116};
 117
 118static DEFINE_CLK(gpio27, &clk_gpio27_ops);
 119
 120static DEFINE_CLK(cpu, &clk_cpu_ops);
 121
 122static unsigned long clk_36864_get_rate(struct clk *clk)
 123{
 124        return 3686400;
 125}
 126
 127static struct clkops clk_36864_ops = {
 128        .get_rate       = clk_36864_get_rate,
 129};
 130
 131static DEFINE_CLK(36864, &clk_36864_ops);
 132
 133static struct clk_lookup sa11xx_clkregs[] = {
 134        CLKDEV_INIT("sa1111.0", NULL, &clk_gpio27),
 135        CLKDEV_INIT("sa1100-rtc", NULL, NULL),
 136        CLKDEV_INIT("sa11x0-fb", NULL, &clk_cpu),
 137        CLKDEV_INIT("sa11x0-pcmcia", NULL, &clk_cpu),
 138        /* sa1111 names devices using internal offsets, PCMCIA is at 0x1800 */
 139        CLKDEV_INIT("1800", NULL, &clk_cpu),
 140        CLKDEV_INIT(NULL, "OSTIMER0", &clk_36864),
 141};
 142
 143static int __init sa11xx_clk_init(void)
 144{
 145        clkdev_add_table(sa11xx_clkregs, ARRAY_SIZE(sa11xx_clkregs));
 146        return 0;
 147}
 148core_initcall(sa11xx_clk_init);
 149