clock.c 1.9 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
/*
 * linux/arch/arm/mach-w90x900/clock.c
 *
 * Copyright (c) 2008 Nuvoton technology corporation
 *
 * Wan ZongShun <mcuos.com@gmail.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.
 */

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/string.h>
#include <linux/clk.h>
#include <linux/spinlock.h>
#include <linux/platform_device.h>
#include <linux/io.h>

#include <mach/hardware.h>

#include "clock.h"

28 29
#define SUBCLK 0x24

30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
static DEFINE_SPINLOCK(clocks_lock);

int clk_enable(struct clk *clk)
{
	unsigned long flags;

	spin_lock_irqsave(&clocks_lock, flags);
	if (clk->enabled++ == 0)
		(clk->enable)(clk, 1);
	spin_unlock_irqrestore(&clocks_lock, flags);

	return 0;
}
EXPORT_SYMBOL(clk_enable);

void clk_disable(struct clk *clk)
{
	unsigned long flags;

	WARN_ON(clk->enabled == 0);

	spin_lock_irqsave(&clocks_lock, flags);
	if (--clk->enabled == 0)
		(clk->enable)(clk, 0);
	spin_unlock_irqrestore(&clocks_lock, flags);
}
EXPORT_SYMBOL(clk_disable);

58 59 60 61 62 63
unsigned long clk_get_rate(struct clk *clk)
{
	return 15000000;
}
EXPORT_SYMBOL(clk_get_rate);

64
void nuc900_clk_enable(struct clk *clk, int enable)
65 66 67 68 69 70 71 72 73 74 75 76 77 78
{
	unsigned int clocks = clk->cken;
	unsigned long clken;

	clken = __raw_readl(W90X900_VA_CLKPWR);

	if (enable)
		clken |= clocks;
	else
		clken &= ~clocks;

	__raw_writel(clken, W90X900_VA_CLKPWR);
}

79
void nuc900_subclk_enable(struct clk *clk, int enable)
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
{
	unsigned int clocks = clk->cken;
	unsigned long clken;

	clken = __raw_readl(W90X900_VA_CLKPWR + SUBCLK);

	if (enable)
		clken |= clocks;
	else
		clken &= ~clocks;

	__raw_writel(clken, W90X900_VA_CLKPWR + SUBCLK);
}


95 96 97 98 99 100 101
void clks_register(struct clk_lookup *clks, size_t num)
{
	int i;

	for (i = 0; i < num; i++)
		clkdev_add(&clks[i]);
}