forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add mmp specific clocks including apbc cloks, apmu clocks, and pll2, fraction clocks Signed-off-by: Chao Xie <[email protected]> Reviewed-by: Arnd Bergmann <[email protected]> Acked-by: Haojian Zhuang <[email protected]> Signed-off-by: Mike Turquette <[email protected]>
- Loading branch information
Chao Xie
authored and
Mike Turquette
committed
Aug 28, 2012
1 parent
f9a6aa4
commit 6b63f02
Showing
6 changed files
with
445 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# | ||
# Makefile for mmp specific clk | ||
# | ||
|
||
obj-y += clk-apbc.o clk-apmu.o clk-frac.o |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
/* | ||
* mmp APB clock operation source file | ||
* | ||
* Copyright (C) 2012 Marvell | ||
* Chao Xie <[email protected]> | ||
* | ||
* This file is licensed under the terms of the GNU General Public | ||
* License version 2. This program is licensed "as is" without any | ||
* warranty of any kind, whether express or implied. | ||
*/ | ||
|
||
#include <linux/kernel.h> | ||
#include <linux/clk.h> | ||
#include <linux/io.h> | ||
#include <linux/err.h> | ||
#include <linux/delay.h> | ||
#include <linux/slab.h> | ||
|
||
#include "clk.h" | ||
|
||
/* Common APB clock register bit definitions */ | ||
#define APBC_APBCLK (1 << 0) /* APB Bus Clock Enable */ | ||
#define APBC_FNCLK (1 << 1) /* Functional Clock Enable */ | ||
#define APBC_RST (1 << 2) /* Reset Generation */ | ||
#define APBC_POWER (1 << 7) /* Reset Generation */ | ||
|
||
#define to_clk_apbc(hw) container_of(hw, struct clk_apbc, hw) | ||
struct clk_apbc { | ||
struct clk_hw hw; | ||
void __iomem *base; | ||
unsigned int delay; | ||
unsigned int flags; | ||
spinlock_t *lock; | ||
}; | ||
|
||
static int clk_apbc_prepare(struct clk_hw *hw) | ||
{ | ||
struct clk_apbc *apbc = to_clk_apbc(hw); | ||
unsigned int data; | ||
unsigned long flags = 0; | ||
|
||
/* | ||
* It may share same register as MUX clock, | ||
* and it will impact FNCLK enable. Spinlock is needed | ||
*/ | ||
if (apbc->lock) | ||
spin_lock_irqsave(apbc->lock, flags); | ||
|
||
data = readl_relaxed(apbc->base); | ||
if (apbc->flags & APBC_POWER_CTRL) | ||
data |= APBC_POWER; | ||
data |= APBC_FNCLK; | ||
writel_relaxed(data, apbc->base); | ||
|
||
if (apbc->lock) | ||
spin_unlock_irqrestore(apbc->lock, flags); | ||
|
||
udelay(apbc->delay); | ||
|
||
if (apbc->lock) | ||
spin_lock_irqsave(apbc->lock, flags); | ||
|
||
data = readl_relaxed(apbc->base); | ||
data |= APBC_APBCLK; | ||
writel_relaxed(data, apbc->base); | ||
|
||
if (apbc->lock) | ||
spin_unlock_irqrestore(apbc->lock, flags); | ||
|
||
udelay(apbc->delay); | ||
|
||
if (!(apbc->flags & APBC_NO_BUS_CTRL)) { | ||
if (apbc->lock) | ||
spin_lock_irqsave(apbc->lock, flags); | ||
|
||
data = readl_relaxed(apbc->base); | ||
data &= ~APBC_RST; | ||
writel_relaxed(data, apbc->base); | ||
|
||
if (apbc->lock) | ||
spin_unlock_irqrestore(apbc->lock, flags); | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
static void clk_apbc_unprepare(struct clk_hw *hw) | ||
{ | ||
struct clk_apbc *apbc = to_clk_apbc(hw); | ||
unsigned long data; | ||
unsigned long flags = 0; | ||
|
||
if (apbc->lock) | ||
spin_lock_irqsave(apbc->lock, flags); | ||
|
||
data = readl_relaxed(apbc->base); | ||
if (apbc->flags & APBC_POWER_CTRL) | ||
data &= ~APBC_POWER; | ||
data &= ~APBC_FNCLK; | ||
writel_relaxed(data, apbc->base); | ||
|
||
if (apbc->lock) | ||
spin_unlock_irqrestore(apbc->lock, flags); | ||
|
||
udelay(10); | ||
|
||
if (apbc->lock) | ||
spin_lock_irqsave(apbc->lock, flags); | ||
|
||
data = readl_relaxed(apbc->base); | ||
data &= ~APBC_APBCLK; | ||
writel_relaxed(data, apbc->base); | ||
|
||
if (apbc->lock) | ||
spin_unlock_irqrestore(apbc->lock, flags); | ||
} | ||
|
||
struct clk_ops clk_apbc_ops = { | ||
.prepare = clk_apbc_prepare, | ||
.unprepare = clk_apbc_unprepare, | ||
}; | ||
|
||
struct clk *mmp_clk_register_apbc(const char *name, const char *parent_name, | ||
void __iomem *base, unsigned int delay, | ||
unsigned int apbc_flags, spinlock_t *lock) | ||
{ | ||
struct clk_apbc *apbc; | ||
struct clk *clk; | ||
struct clk_init_data init; | ||
|
||
apbc = kzalloc(sizeof(*apbc), GFP_KERNEL); | ||
if (!apbc) | ||
return NULL; | ||
|
||
init.name = name; | ||
init.ops = &clk_apbc_ops; | ||
init.flags = CLK_SET_RATE_PARENT; | ||
init.parent_names = (parent_name ? &parent_name : NULL); | ||
init.num_parents = (parent_name ? 1 : 0); | ||
|
||
apbc->base = base; | ||
apbc->delay = delay; | ||
apbc->flags = apbc_flags; | ||
apbc->lock = lock; | ||
apbc->hw.init = &init; | ||
|
||
clk = clk_register(NULL, &apbc->hw); | ||
if (IS_ERR(clk)) | ||
kfree(apbc); | ||
|
||
return clk; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
/* | ||
* mmp AXI peripharal clock operation source file | ||
* | ||
* Copyright (C) 2012 Marvell | ||
* Chao Xie <[email protected]> | ||
* | ||
* This file is licensed under the terms of the GNU General Public | ||
* License version 2. This program is licensed "as is" without any | ||
* warranty of any kind, whether express or implied. | ||
*/ | ||
|
||
#include <linux/kernel.h> | ||
#include <linux/clk.h> | ||
#include <linux/io.h> | ||
#include <linux/err.h> | ||
#include <linux/delay.h> | ||
#include <linux/slab.h> | ||
|
||
#include "clk.h" | ||
|
||
#define to_clk_apmu(clk) (container_of(clk, struct clk_apmu, clk)) | ||
struct clk_apmu { | ||
struct clk_hw hw; | ||
void __iomem *base; | ||
u32 rst_mask; | ||
u32 enable_mask; | ||
spinlock_t *lock; | ||
}; | ||
|
||
static int clk_apmu_enable(struct clk_hw *hw) | ||
{ | ||
struct clk_apmu *apmu = to_clk_apmu(hw); | ||
unsigned long data; | ||
unsigned long flags = 0; | ||
|
||
if (apmu->lock) | ||
spin_lock_irqsave(apmu->lock, flags); | ||
|
||
data = readl_relaxed(apmu->base) | apmu->enable_mask; | ||
writel_relaxed(data, apmu->base); | ||
|
||
if (apmu->lock) | ||
spin_unlock_irqrestore(apmu->lock, flags); | ||
|
||
return 0; | ||
} | ||
|
||
static void clk_apmu_disable(struct clk_hw *hw) | ||
{ | ||
struct clk_apmu *apmu = to_clk_apmu(hw); | ||
unsigned long data; | ||
unsigned long flags = 0; | ||
|
||
if (apmu->lock) | ||
spin_lock_irqsave(apmu->lock, flags); | ||
|
||
data = readl_relaxed(apmu->base) & ~apmu->enable_mask; | ||
writel_relaxed(data, apmu->base); | ||
|
||
if (apmu->lock) | ||
spin_unlock_irqrestore(apmu->lock, flags); | ||
} | ||
|
||
struct clk_ops clk_apmu_ops = { | ||
.enable = clk_apmu_enable, | ||
.disable = clk_apmu_disable, | ||
}; | ||
|
||
struct clk *mmp_clk_register_apmu(const char *name, const char *parent_name, | ||
void __iomem *base, u32 enable_mask, spinlock_t *lock) | ||
{ | ||
struct clk_apmu *apmu; | ||
struct clk *clk; | ||
struct clk_init_data init; | ||
|
||
apmu = kzalloc(sizeof(*apmu), GFP_KERNEL); | ||
if (!apmu) | ||
return NULL; | ||
|
||
init.name = name; | ||
init.ops = &clk_apmu_ops; | ||
init.flags = CLK_SET_RATE_PARENT; | ||
init.parent_names = (parent_name ? &parent_name : NULL); | ||
init.num_parents = (parent_name ? 1 : 0); | ||
|
||
apmu->base = base; | ||
apmu->enable_mask = enable_mask; | ||
apmu->lock = lock; | ||
apmu->hw.init = &init; | ||
|
||
clk = clk_register(NULL, &apmu->hw); | ||
|
||
if (IS_ERR(clk)) | ||
kfree(apmu); | ||
|
||
return clk; | ||
} |
Oops, something went wrong.