clock.c 2.5 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*
 *  linux/arch/arm/mach-versatile/clock.c
 *
 *  Copyright (C) 2004 ARM Limited.
 *  Written by Deep Blue Solutions Limited.
 *
 * 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/module.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/errno.h>
#include <linux/err.h>
T
Tim Schmielau 已提交
16
#include <linux/string.h>
17
#include <linux/clk.h>
18
#include <linux/mutex.h>
L
Linus Torvalds 已提交
19 20 21 22 23 24

#include <asm/hardware/icst307.h>

#include "clock.h"

static LIST_HEAD(clocks);
25
static DEFINE_MUTEX(clocks_mutex);
L
Linus Torvalds 已提交
26 27 28 29 30

struct clk *clk_get(struct device *dev, const char *id)
{
	struct clk *p, *clk = ERR_PTR(-ENOENT);

31
	mutex_lock(&clocks_mutex);
L
Linus Torvalds 已提交
32 33 34 35 36 37
	list_for_each_entry(p, &clocks, node) {
		if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
			clk = p;
			break;
		}
	}
38
	mutex_unlock(&clocks_mutex);
L
Linus Torvalds 已提交
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107

	return clk;
}
EXPORT_SYMBOL(clk_get);

void clk_put(struct clk *clk)
{
	module_put(clk->owner);
}
EXPORT_SYMBOL(clk_put);

int clk_enable(struct clk *clk)
{
	return 0;
}
EXPORT_SYMBOL(clk_enable);

void clk_disable(struct clk *clk)
{
}
EXPORT_SYMBOL(clk_disable);

unsigned long clk_get_rate(struct clk *clk)
{
	return clk->rate;
}
EXPORT_SYMBOL(clk_get_rate);

long clk_round_rate(struct clk *clk, unsigned long rate)
{
	return rate;
}
EXPORT_SYMBOL(clk_round_rate);

int clk_set_rate(struct clk *clk, unsigned long rate)
{
	int ret = -EIO;

	if (clk->setvco) {
		struct icst307_vco vco;

		vco = icst307_khz_to_vco(clk->params, rate / 1000);
		clk->rate = icst307_khz(clk->params, vco) * 1000;

		printk("Clock %s: setting VCO reg params: S=%d R=%d V=%d\n",
			clk->name, vco.s, vco.r, vco.v);

		clk->setvco(clk, vco);
		ret = 0;
	}
	return ret;
}
EXPORT_SYMBOL(clk_set_rate);

/*
 * These are fixed clocks.
 */
static struct clk kmi_clk = {
	.name	= "KMIREFCLK",
	.rate	= 24000000,
};

static struct clk uart_clk = {
	.name	= "UARTCLK",
	.rate	= 24000000,
};

static struct clk mmci_clk = {
	.name	= "MCLK",
108
	.rate	= 24000000,
L
Linus Torvalds 已提交
109 110 111 112
};

int clk_register(struct clk *clk)
{
113
	mutex_lock(&clocks_mutex);
L
Linus Torvalds 已提交
114
	list_add(&clk->node, &clocks);
115
	mutex_unlock(&clocks_mutex);
L
Linus Torvalds 已提交
116 117 118 119 120 121
	return 0;
}
EXPORT_SYMBOL(clk_register);

void clk_unregister(struct clk *clk)
{
122
	mutex_lock(&clocks_mutex);
L
Linus Torvalds 已提交
123
	list_del(&clk->node);
124
	mutex_unlock(&clocks_mutex);
L
Linus Torvalds 已提交
125 126 127 128 129 130 131 132 133 134 135
}
EXPORT_SYMBOL(clk_unregister);

static int __init clk_init(void)
{
	clk_register(&kmi_clk);
	clk_register(&uart_clk);
	clk_register(&mmci_clk);
	return 0;
}
arch_initcall(clk_init);