rk2928:sdk: add clock support

This commit is contained in:
chenxing
2012-08-06 14:51:32 +08:00
parent 5633de6473
commit 0f93e2344c
8 changed files with 3974 additions and 72 deletions

View File

@@ -4,6 +4,8 @@ obj-y += reset.o
obj-y += timer.o
obj-y += devices.o
obj-y += iomux.o
obj-y += clock.o
obj-y += clock_data.o
obj-$(CONFIG_PM) += pm.o
obj-$(CONFIG_MACH_RK2928_FPGA) += board-rk2928-fpga.o board-rk2928-fpga-key.o

View File

@@ -1189,81 +1189,10 @@ static void __init rk2928_reserve(void)
board_mem_reserved();
}
#if 1
#include <linux/clkdev.h>
struct clk {
const char *name;
unsigned long rate;
};
static struct clk xin24m = {
.name = "xin24m",
.rate = 24000000,
};
#define CLK(dev, con, ck) \
{ \
.dev_id = dev, \
.con_id = con, \
.clk = ck, \
}
static struct clk_lookup clks[] = {
CLK("rk30_i2c.0", "i2c", &xin24m),
CLK("rk30_i2c.1", "i2c", &xin24m),
CLK("rk30_i2c.2", "i2c", &xin24m),
CLK("rk30_i2c.3", "i2c", &xin24m),
CLK("rk29xx_spim.0", "spi", &xin24m),
CLK("rk29xx_spim.1", "spi", &xin24m),
CLK("rk_serial.0", "uart_div", &xin24m),
CLK("rk_serial.0", "uart_frac_div", &xin24m),
CLK("rk_serial.0", "uart", &xin24m),
CLK("rk_serial.0", "pclk_uart", &xin24m),
CLK("rk_serial.1", "uart_div", &xin24m),
CLK("rk_serial.1", "uart_frac_div", &xin24m),
CLK("rk_serial.1", "uart", &xin24m),
CLK("rk_serial.1", "pclk_uart", &xin24m),
CLK("rk_serial.2", "uart_div", &xin24m),
CLK("rk_serial.2", "uart_frac_div", &xin24m),
CLK("rk_serial.2", "uart", &xin24m),
CLK("rk_serial.2", "pclk_uart", &xin24m),
CLK("rk29_i2s.0", "i2s_div", &xin24m),
CLK("rk29_i2s.0", "i2s_frac_div", &xin24m),
CLK("rk29_i2s.0", "i2s", &xin24m),
CLK("rk29_i2s.0", "hclk_i2s", &xin24m),
CLK(NULL, "pd_lcdc0", &xin24m),
CLK(NULL, "hclk_lcdc0", &xin24m),
CLK(NULL, "aclk_lcdc0", &xin24m),
CLK(NULL, "dclk_lcdc0", &xin24m),
CLK(NULL, "pd_cif0", &xin24m),
CLK(NULL, "aclk_cif0", &xin24m),
CLK(NULL, "hclk_cif0", &xin24m),
CLK(NULL, "cif0_in", &xin24m),
CLK(NULL, "cif0_out", &xin24m),
};
void __init rk30_clock_init(void)
{
struct clk_lookup *lk;
for (lk = clks; lk < clks + ARRAY_SIZE(clks); lk++) {
clkdev_add(lk);
}
}
void __init board_clock_init(void)
{
rk30_clock_init();
rk2928_clock_data_init(periph_pll_default, codec_pll_default, RK30_CLOCKS_DEFAULT_FLAGS);
}
#else
void __init board_clock_init(void)
{
}
#endif
MACHINE_START(RK2928, "RK2928board")

754
arch/arm/mach-rk2928/clock.c Executable file
View File

@@ -0,0 +1,754 @@
/* linux/arch/arm/mach-rk30/clock.c
*
* Copyright (C) 2012 ROCKCHIP, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/hardirq.h>
#include <linux/delay.h>
#include <mach/clock.h>
#include "clock.h"
//#include <mach/dvfs.h>
#include <linux/delay.h>
#define CLOCK_PRINTK_DBG(fmt, args...) pr_debug(fmt, ## args);
#define CLOCK_PRINTK_ERR(fmt, args...) pr_err(fmt, ## args);
#define CLOCK_PRINTK_LOG(fmt, args...) pr_debug(fmt, ## args);
/* Clock flags */
/* bit 0 is free */
#define RATE_FIXED (1 << 1) /* Fixed clock rate */
#define CONFIG_PARTICIPANT (1 << 10) /* Fundamental clock */
#define MHZ (1000*1000)
#define KHZ (1000)
static void __clk_recalc(struct clk *clk);
static void __propagate_rate(struct clk *tclk);
static void __clk_reparent(struct clk *child, struct clk *parent);
static LIST_HEAD(clocks);
static DEFINE_MUTEX(clocks_mutex);
static DEFINE_SPINLOCK(clockfw_lock);
static LIST_HEAD(root_clks);
static void clk_notify(struct clk *clk, unsigned long msg,
unsigned long old_rate, unsigned long new_rate);
#define LOCK() do { WARN_ON(in_irq()); if (!irqs_disabled()) spin_lock_bh(&clockfw_lock); } while (0)
#define UNLOCK() do { if (!irqs_disabled()) spin_unlock_bh(&clockfw_lock); } while (0)
/**********************************************for clock data****************************************************/
static struct clk *def_ops_clk=NULL;
void clk_register_default_ops_clk(struct clk *clk)
{
def_ops_clk=clk;
}
static struct clk *clk_default_get_parent(struct clk *clk)
{
if(def_ops_clk&&def_ops_clk->get_parent)
return def_ops_clk->get_parent(clk);
else return NULL;
}
static int clk_default_set_parent(struct clk *clk, struct clk *parent)
{
if(def_ops_clk&&def_ops_clk->set_parent)
return def_ops_clk->set_parent(clk,parent);
else
return -EINVAL;
}
int __init clk_disable_unused(void)
{
struct clk *ck;
list_for_each_entry(ck, &clocks, node) {
if (ck->usecount > 0 || ck->mode == NULL || (ck->flags & IS_PD))
continue;
LOCK();
clk_enable_nolock(ck);
clk_disable_nolock(ck);
UNLOCK();
}
return 0;
}
/**
* recalculate_root_clocks - recalculate and propagate all root clocks
*
* Recalculates all root clocks (clocks with no parent), which if the
* clock's .recalc is set correctly, should also propagate their rates.
* Called at init.
*/
void clk_recalculate_root_clocks_nolock(void)
{
struct clk *clkp;
list_for_each_entry(clkp, &root_clks, sibling) {
__clk_recalc(clkp);
__propagate_rate(clkp);
}
}
/*
void clk_recalculate_root_clocks(void)
{
LOCK();
clk_recalculate_root_clocks_nolock();
UNLOCK();
}*/
/**
* clk_preinit - initialize any fields in the struct clk before clk init
* @clk: struct clk * to initialize
*
* Initialize any struct clk fields needed before normal clk initialization
* can run. No return value.
*/
int clk_register(struct clk *clk)
{
if (clk == NULL || IS_ERR(clk))
return -EINVAL;
//INIT_LIST_HEAD(&clk->sibling);
INIT_LIST_HEAD(&clk->children);
/*
* trap out already registered clocks
*/
if (clk->node.next || clk->node.prev)
return 0;
mutex_lock(&clocks_mutex);
if (clk->get_parent)
clk->parent = clk->get_parent(clk);
else if (clk->parents)
clk->parent =clk_default_get_parent(clk);
if (clk->parent){
printk("clk has parent\n");
list_add(&clk->sibling, &clk->parent->children);
}
else{
printk("clk has no parent\n");
list_add(&clk->sibling, &root_clks);
}
list_add(&clk->node, &clocks);
mutex_unlock(&clocks_mutex);
return 0;
}
/************************************************************/
static void __clk_recalc(struct clk *clk)
{
if (unlikely(clk->flags & RATE_FIXED))
return;
if (clk->recalc)
clk->rate = clk->recalc(clk);
else if (clk->parent)
clk->rate = clk->parent->rate;
}
static void __clk_reparent(struct clk *child, struct clk *parent)
{
if (child->parent == parent)
return;
//CLOCK_PRINTK_DBG("%s reparent to %s (was %s)\n", child->name, parent->name, ((child->parent) ? child->parent->name : "NULL"));
list_del_init(&child->sibling);
if (parent)
list_add(&child->sibling, &parent->children);
child->parent = parent;
}
/* Propagate rate to children */
static void __propagate_rate(struct clk *tclk)
{
struct clk *clkp;
//CLOCK_PRINTK_DBG("propagate_rate clk %s\n",clkp->name);
list_for_each_entry(clkp, &tclk->children, sibling) {
__clk_recalc(clkp);
__propagate_rate(clkp);
}
//CLOCK_PRINTK_DBG("propagate_rate clk %s end\n",clkp->name);
}
int clk_enable_nolock(struct clk *clk)
{
int ret = 0;
if (clk->usecount == 0) {
if (clk->parent) {
ret = clk_enable_nolock(clk->parent);
if (ret)
return ret;
}
if (clk->notifier_count)
clk_notify(clk, CLK_PRE_ENABLE, clk->rate, clk->rate);
if (clk->mode)
ret = clk->mode(clk, 1);
if (clk->notifier_count)
clk_notify(clk, ret ? CLK_ABORT_ENABLE : CLK_POST_ENABLE, clk->rate, clk->rate);
if (ret) {
if (clk->parent)
clk_disable_nolock(clk->parent);
return ret;
}
//pr_debug("%s enabled\n", clk->name);
printk("%s enabled\n", clk->name);
}
clk->usecount++;
return ret;
}
void clk_disable_nolock(struct clk *clk)
{
if (clk->usecount == 0) {
CLOCK_PRINTK_ERR(KERN_ERR "Trying disable clock %s with 0 usecount\n", clk->name);
WARN_ON(1);
return;
}
if (--clk->usecount == 0) {
int ret = 0;
if (clk->notifier_count)
clk_notify(clk, CLK_PRE_DISABLE, clk->rate, clk->rate);
if (clk->mode)
ret = clk->mode(clk, 0);
if (clk->notifier_count)
clk_notify(clk, ret ? CLK_ABORT_DISABLE : CLK_POST_DISABLE, clk->rate, clk->rate);
pr_debug("%s disabled\n", clk->name);
if (ret == 0 && clk->parent)
clk_disable_nolock(clk->parent);
}
}
/* Given a clock and a rate apply a clock specific rounding function */
long clk_round_rate_nolock(struct clk *clk, unsigned long rate)
{
if (clk->round_rate)
return clk->round_rate(clk, rate);
if (clk->flags & RATE_FIXED)
CLOCK_PRINTK_ERR("clock: clk_round_rate called on fixed-rate clock %s\n", clk->name);
return clk->rate;
}
int is_suport_round_rate(struct clk *clk)
{
return (clk->round_rate) ? 0:(-1);
}
int clk_set_rate_nolock(struct clk *clk, unsigned long rate)
{
int ret;
unsigned long old_rate;
if (rate == clk->rate)
return 0;
if (clk->flags & CONFIG_PARTICIPANT)
return -EINVAL;
if (!clk->set_rate)
return -EINVAL;
printk("**will set %s rate %lu\n", clk->name, rate);
old_rate = clk->rate;
if (clk->notifier_count)
clk_notify(clk, CLK_PRE_RATE_CHANGE, old_rate, rate);
ret = clk->set_rate(clk, rate);
if (ret == 0) {
__clk_recalc(clk);
printk("**set %s rate recalc=%lu\n",clk->name,clk->rate);
__propagate_rate(clk);
}
if (clk->notifier_count)
clk_notify(clk, ret ? CLK_ABORT_RATE_CHANGE : CLK_POST_RATE_CHANGE, old_rate, clk->rate);
return ret;
}
int clk_set_parent_nolock(struct clk *clk, struct clk *parent)
{
int ret;
int enabled = clk->usecount > 0;
struct clk *old_parent = clk->parent;
if (clk->parent == parent)
return 0;
/* if clk is already enabled, enable new parent first and disable old parent later. */
if (enabled)
clk_enable_nolock(parent);
if (clk->set_parent)
ret = clk->set_parent(clk, parent);
else
ret = clk_default_set_parent(clk,parent);
if (ret == 0) {
/* OK */
//CLOCK_PRINTK_DBG("set_parent %s reparent\n",clk->name,parent->name);
__clk_reparent(clk, parent);
__clk_recalc(clk);
__propagate_rate(clk);
if (enabled)
clk_disable_nolock(old_parent);
} else {
//CLOCK_PRINTK_DBG("set_parent err\n",clk->name,parent->name);
if (enabled)
clk_disable_nolock(parent);
}
return ret;
}
/**********************************dvfs****************************************************/
#if 0
struct clk_node *clk_get_dvfs_info(struct clk *clk)
{
return clk->dvfs_info;
}
int clk_set_rate_locked(struct clk * clk,unsigned long rate)
{
int ret;
//CLOCK_PRINTK_DBG("%s dvfs clk_set_locked\n",clk->name);
LOCK();
ret=clk_set_rate_nolock(clk, rate);;
UNLOCK();
return ret;
}
void clk_register_dvfs(struct clk_node *dvfs_clk, struct clk *clk)
{
clk->dvfs_info = dvfs_clk;
}
#endif
/*-------------------------------------------------------------------------
* Optional clock functions defined in include/linux/clk.h
*-------------------------------------------------------------------------*/
#ifdef RK30_CLK_OFFBOARD_TEST
long rk30_clk_round_rate(struct clk *clk, unsigned long rate)
#else
long clk_round_rate(struct clk *clk, unsigned long rate)
#endif
{
long ret = 0;
if (clk == NULL || IS_ERR(clk))
return ret;
LOCK();
ret = clk_round_rate_nolock(clk, rate);
UNLOCK();
return ret;
}
#ifdef RK30_CLK_OFFBOARD_TEST
EXPORT_SYMBOL(rk30_clk_round_rate);
#else
EXPORT_SYMBOL(clk_round_rate);
#endif
#ifdef RK30_CLK_OFFBOARD_TEST
unsigned long rk30_clk_get_rate(struct clk *clk)
#else
unsigned long clk_get_rate(struct clk *clk)
#endif
{
if (clk == NULL || IS_ERR(clk))
return 0;
return clk->rate;
}
#ifdef RK30_CLK_OFFBOARD_TEST
EXPORT_SYMBOL(rk30_clk_get_rate);
#else
EXPORT_SYMBOL(clk_get_rate);
#endif
/* Set the clock rate for a clock source */
#ifdef RK30_CLK_OFFBOARD_TEST
int rk30_clk_set_rate(struct clk *clk, unsigned long rate)
#else
int clk_set_rate(struct clk *clk, unsigned long rate)
#endif
{
int ret = -EINVAL;
if (clk == NULL || IS_ERR(clk)){
return ret;
}
if (rate == clk->rate)
return 0;
#if 0
if (clk->dvfs_info!=NULL&&is_support_dvfs(clk->dvfs_info))
return dvfs_set_rate(clk, rate);
#endif
LOCK();
ret = clk_set_rate_nolock(clk, rate);
UNLOCK();
return ret;
}
#ifdef RK30_CLK_OFFBOARD_TEST
EXPORT_SYMBOL(rk30_clk_set_rate);
#else
EXPORT_SYMBOL(clk_set_rate);
#endif
#ifdef RK30_CLK_OFFBOARD_TEST
int rk30_clk_set_parent(struct clk *clk, struct clk *parent)
#else
int clk_set_parent(struct clk *clk, struct clk *parent)
#endif
{
int ret = -EINVAL;
if (clk == NULL || IS_ERR(clk) || parent == NULL || IS_ERR(parent))
return ret;
if (clk->set_parent==NULL||clk->parents == NULL)
return ret;
LOCK();
if (clk->usecount == 0)
ret = clk_set_parent_nolock(clk, parent);
else
ret = -EBUSY;
UNLOCK();
return ret;
}
int clk_set_parent_force(struct clk *clk, struct clk *parent)
{
int ret = -EINVAL;
if (clk == NULL || IS_ERR(clk) || parent == NULL || IS_ERR(parent))
return ret;
if (clk->set_parent==NULL||clk->parents == NULL)
return ret;
LOCK();
ret = clk_set_parent_nolock(clk, parent);
UNLOCK();
return ret;
}
#ifdef RK30_CLK_OFFBOARD_TEST
EXPORT_SYMBOL(rk30_clk_set_parent);
#else
EXPORT_SYMBOL(clk_set_parent);
#endif
#ifdef RK30_CLK_OFFBOARD_TEST
struct clk *rk30_clk_get_parent(struct clk *clk)
#else
struct clk *clk_get_parent(struct clk *clk)
#endif
{
if (clk == NULL || IS_ERR(clk)) {
return ERR_PTR(-EINVAL);
}
return clk->parent;
}
#ifdef RK30_CLK_OFFBOARD_TEST
EXPORT_SYMBOL(rk30_clk_get_parent);
#else
EXPORT_SYMBOL(clk_get_parent);
#endif
#ifdef RK30_CLK_OFFBOARD_TEST
void rk30_clk_disable(struct clk *clk)
#else
void clk_disable(struct clk *clk)
#endif
{
if (clk == NULL || IS_ERR(clk))
return;
LOCK();
clk_disable_nolock(clk);
UNLOCK();
}
#ifdef RK30_CLK_OFFBOARD_TEST
EXPORT_SYMBOL(rk30_clk_disable);
#else
EXPORT_SYMBOL(clk_disable);
#endif
#ifdef RK30_CLK_OFFBOARD_TEST
int rk30_clk_enable(struct clk *clk)
#else
int clk_enable(struct clk *clk)
#endif
{
int ret = 0;
if (clk == NULL || IS_ERR(clk))
return -EINVAL;
LOCK();
ret = clk_enable_nolock(clk);
UNLOCK();
return ret;
}
#ifdef RK30_CLK_OFFBOARD_TEST
EXPORT_SYMBOL(rk30_clk_enable);
#else
EXPORT_SYMBOL(clk_enable);
#endif
/* Clk notifier implementation */
/**
* struct clk_notifier - associate a clk with a notifier
* @clk: struct clk * to associate the notifier with
* @notifier_head: a raw_notifier_head for this clk
* @node: linked list pointers
*
* A list of struct clk_notifier is maintained by the notifier code.
* An entry is created whenever code registers the first notifier on a
* particular @clk. Future notifiers on that @clk are added to the
* @notifier_head.
*/
struct clk_notifier {
struct clk *clk;
struct raw_notifier_head notifier_head;
struct list_head node;
};
static LIST_HEAD(clk_notifier_list);
/**
* _clk_free_notifier_chain - safely remove struct clk_notifier
* @cn: struct clk_notifier *
*
* Removes the struct clk_notifier @cn from the clk_notifier_list and
* frees it.
*/
static void _clk_free_notifier_chain(struct clk_notifier *cn)
{
list_del(&cn->node);
kfree(cn);
}
/**
* clk_notify - call clk notifier chain
* @clk: struct clk * that is changing rate
* @msg: clk notifier type (i.e., CLK_POST_RATE_CHANGE; see mach/clock.h)
* @old_rate: old rate
* @new_rate: new rate
*
* Triggers a notifier call chain on the post-clk-rate-change notifier
* for clock 'clk'. Passes a pointer to the struct clk and the
* previous and current rates to the notifier callback. Intended to be
* called by internal clock code only. No return value.
*/
static void clk_notify(struct clk *clk, unsigned long msg,
unsigned long old_rate, unsigned long new_rate)
{
struct clk_notifier *cn;
struct clk_notifier_data cnd;
cnd.clk = clk;
cnd.old_rate = old_rate;
cnd.new_rate = new_rate;
UNLOCK();
list_for_each_entry(cn, &clk_notifier_list, node) {
if (cn->clk == clk) {
pr_debug("%s msg %lu rate %lu -> %lu\n", clk->name, msg, old_rate, new_rate);
raw_notifier_call_chain(&cn->notifier_head, msg, &cnd);
break;
}
}
LOCK();
}
/**
* clk_notifier_register - add a clock parameter change notifier
* @clk: struct clk * to watch
* @nb: struct notifier_block * with callback info
*
* Request notification for changes to the clock 'clk'. This uses a
* blocking notifier. Callback code must not call into the clock
* framework, as clocks_mutex is held. Pre-notifier callbacks will be
* passed the previous and new rate of the clock.
*
* clk_notifier_register() must be called from process
* context. Returns -EINVAL if called with null arguments, -ENOMEM
* upon allocation failure; otherwise, passes along the return value
* of blocking_notifier_chain_register().
*/
int rk30_clk_notifier_register(struct clk *clk, struct notifier_block *nb)
{
struct clk_notifier *cn = NULL, *cn_new = NULL;
int r;
struct clk *clkp;
if (!clk || IS_ERR(clk) || !nb)
return -EINVAL;
mutex_lock(&clocks_mutex);
list_for_each_entry(cn, &clk_notifier_list, node)
if (cn->clk == clk)
break;
if (cn->clk != clk) {
cn_new = kzalloc(sizeof(struct clk_notifier), GFP_KERNEL);
if (!cn_new) {
r = -ENOMEM;
goto cnr_out;
};
cn_new->clk = clk;
RAW_INIT_NOTIFIER_HEAD(&cn_new->notifier_head);
list_add(&cn_new->node, &clk_notifier_list);
cn = cn_new;
}
r = raw_notifier_chain_register(&cn->notifier_head, nb);
if (!IS_ERR_VALUE(r)) {
clkp = clk;
do {
clkp->notifier_count++;
} while ((clkp = clkp->parent));
} else {
if (cn_new)
_clk_free_notifier_chain(cn);
}
cnr_out:
mutex_unlock(&clocks_mutex);
return r;
}
EXPORT_SYMBOL(rk30_clk_notifier_register);
/**
* clk_notifier_unregister - remove a clock change notifier
* @clk: struct clk *
* @nb: struct notifier_block * with callback info
*
* Request no further notification for changes to clock 'clk'.
* Returns -EINVAL if called with null arguments; otherwise, passes
* along the return value of blocking_notifier_chain_unregister().
*/
int rk30_clk_notifier_unregister(struct clk *clk, struct notifier_block *nb)
{
struct clk_notifier *cn = NULL;
struct clk *clkp;
int r = -EINVAL;
if (!clk || IS_ERR(clk) || !nb)
return -EINVAL;
mutex_lock(&clocks_mutex);
list_for_each_entry(cn, &clk_notifier_list, node)
if (cn->clk == clk)
break;
if (cn->clk != clk) {
r = -ENOENT;
goto cnu_out;
};
r = raw_notifier_chain_unregister(&cn->notifier_head, nb);
if (!IS_ERR_VALUE(r)) {
clkp = clk;
do {
clkp->notifier_count--;
} while ((clkp = clkp->parent));
}
/*
* XXX ugh, layering violation. There should be some
* support in the notifier code for this.
*/
if (!cn->notifier_head.head)
_clk_free_notifier_chain(cn);
cnu_out:
mutex_unlock(&clocks_mutex);
return r;
}
EXPORT_SYMBOL(rk30_clk_notifier_unregister);
static struct clk_dump_ops *dump_def_ops;
void clk_register_dump_ops(struct clk_dump_ops *ops)
{
dump_def_ops=ops;
}
static int proc_clk_show(struct seq_file *s, void *v)
{
struct clk* clk;
if(!dump_def_ops)
return 0;
if(dump_def_ops->dump_clk)
{
mutex_lock(&clocks_mutex);
list_for_each_entry(clk, &clocks, node) {
if (!clk->parent)
{
dump_def_ops->dump_clk(s, clk, 0,&clocks);
}
}
mutex_unlock(&clocks_mutex);
}
if(dump_def_ops->dump_regs)
dump_def_ops->dump_regs(s);
return 0;
}
static int proc_clk_open(struct inode *inode, struct file *file)
{
return single_open(file, proc_clk_show, NULL);
}
static const struct file_operations proc_clk_fops = {
.open = proc_clk_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int __init clk_proc_init(void)
{
proc_create("clocks", 0, NULL, &proc_clk_fops);
return 0;
}
late_initcall(clk_proc_init);

View File

@@ -0,0 +1,99 @@
#ifndef __MACH_CLOCK_H__
#define __MACH_CLOCK_H__
#ifndef CONFIG_ARCH_RK2928
#define RK30_CLK_OFFBOARD_TEST
#endif
/* Clock flags */
/* bit 0 is free */
#define RATE_FIXED (1 << 1) /* Fixed clock rate */
#define CONFIG_PARTICIPANT (1 << 10) /* Fundamental clock */
#define IS_PD (1 << 2) /* Power Domain */
enum _clk_i2s_rate_support {
i2s_8192khz = 8192000,
i2s_11289_6khz = 11289600,
i2s_12288khz = 12288000,
i2s_22579_2khz = 22579200,
i2s_24576khz = 24576000,//HDMI
i2s_49152khz = 24576000,//HDMI
};
struct _pll_data{
u8 id;
void *table;
};
//struct clk_node;
struct clk {
struct list_head node;
const char *name;
struct clk *parent;
struct list_head children;
struct list_head sibling; /* node for children */
int (*mode)(struct clk *clk, int on);
unsigned long (*recalc)(struct clk *); /* if null, follow parent */
int (*set_rate)(struct clk *, unsigned long);
long (*round_rate)(struct clk *, unsigned long);
struct clk* (*get_parent)(struct clk *); /* get clk's parent from the hardware. default is clksel_get_parent if parents present */
int (*set_parent)(struct clk *, struct clk *); /* default is clksel_set_parent if parents present */
unsigned long rate;
u32 flags;
s16 usecount;
u16 notifier_count;
u8 gate_idx;
struct _pll_data *pll;
u32 clksel_con;
u32 div_mask;
u32 div_shift;
u32 div_max;
u32 src_mask;
u32 src_shift;
struct clk **parents;
u8 parents_num;
struct clk_node *dvfs_info;
};
int __init clk_disable_unused(void);
void clk_recalculate_root_clocks_nolock(void);
void clk_recalculate_root_clocks(void);
int clk_register(struct clk *clk);
void clk_register_default_ops_clk(struct clk *clk);
int clk_enable_nolock(struct clk *clk);
void clk_disable_nolock(struct clk *clk);
long clk_round_rate_nolock(struct clk *clk, unsigned long rate);
int clk_set_rate_nolock(struct clk *clk, unsigned long rate);
int clk_set_parent_nolock(struct clk *clk, struct clk *parent);
int clk_set_rate_locked(struct clk * clk,unsigned long rate);
void clk_register_dvfs(struct clk_node *dvfs_clk, struct clk *clk);
struct clk_node *clk_get_dvfs_info(struct clk *clk);
int is_suport_round_rate(struct clk *clk);
#ifdef RK30_CLK_OFFBOARD_TEST
#include <linux/device.h>
struct clk *rk30_clk_get(struct device *dev, const char *con_id);
#endif
#ifdef CONFIG_PROC_FS
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
struct clk_dump_ops {
void (*dump_clk)(struct seq_file *s, struct clk *clk, int deep,const struct list_head *root_clocks);
void (*dump_regs)(struct seq_file *s);
};
void clk_register_dump_ops(struct clk_dump_ops *ops);
#else
static void clk_register_dump_ops(struct clk_dump_ops *ops){
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -57,5 +57,35 @@ struct eeti_egalax_platform_data{
};
#endif
enum _periph_pll {
periph_pll_1485mhz = 148500000,
periph_pll_297mhz = 297000000,
periph_pll_300mhz = 300000000,
periph_pll_1188mhz = 1188000000, /* for box*/
};
enum _codec_pll {
codec_pll_360mhz = 360000000, /* for HDMI */
codec_pll_408mhz = 408000000,
codec_pll_456mhz = 456000000,
codec_pll_504mhz = 504000000,
codec_pll_552mhz = 552000000, /* for HDMI */
codec_pll_600mhz = 600000000,
codec_pll_742_5khz = 742500000,
codec_pll_798mhz = 798000000,
codec_pll_1064mhz = 1064000000,
codec_pll_1188mhz = 1188000000,
};
//max i2s rate
#define CLK_FLG_MAX_I2S_12288KHZ (1<<1)
#define CLK_FLG_MAX_I2S_22579_2KHZ (1<<2)
#define CLK_FLG_MAX_I2S_24576KHZ (1<<3)
#define CLK_FLG_MAX_I2S_49152KHZ (1<<4)
#define RK30_CLOCKS_DEFAULT_FLAGS (CLK_FLG_MAX_I2S_12288KHZ/*|CLK_FLG_EXT_27MHZ*/)
#define periph_pll_default periph_pll_297mhz
#define codec_pll_default codec_pll_798mhz
//#define codec_pll_default codec_pll_1064mhz
#endif

View File

@@ -0,0 +1,81 @@
/* arch/arm/mach-rk29/include/mach/clock.h
*
* Copyright (C) 2011 ROCKCHIP, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef __ASM_ARCH_RK30_CLOCK_H
#define __ASM_ARCH_RK30_CLOCK_H
/**
* struct clk_notifier_data - rate data to pass to the notifier callback
* @clk: struct clk * being changed
* @old_rate: previous rate of this clock
* @new_rate: new rate of this clock
*
* For a pre-notifier, old_rate is the clock's rate before this rate
* change, and new_rate is what the rate will be in the future. For a
* post-notifier, old_rate and new_rate are both set to the clock's
* current rate (this was done to optimize the implementation).
*/
struct clk_notifier_data {
struct clk *clk;
unsigned long old_rate;
unsigned long new_rate;
};
/*
* Clk notifier callback types
*
* Since the notifier is called with interrupts disabled, any actions
* taken by callbacks must be extremely fast and lightweight.
*
* CLK_PRE_RATE_CHANGE - called after all callbacks have approved the
* rate change, immediately before the clock rate is changed, to
* indicate that the rate change will proceed. Drivers must
* immediately terminate any operations that will be affected by
* the rate change. Callbacks must always return NOTIFY_DONE.
*
* CLK_ABORT_RATE_CHANGE: called if the rate change failed for some
* reason after CLK_PRE_RATE_CHANGE. In this case, all registered
* notifiers on the clock will be called with
* CLK_ABORT_RATE_CHANGE. Callbacks must always return
* NOTIFY_DONE.
*
* CLK_POST_RATE_CHANGE - called after the clock rate change has
* successfully completed. Callbacks must always return
* NOTIFY_DONE.
*
*/
#define CLK_PRE_RATE_CHANGE 1
#define CLK_POST_RATE_CHANGE 2
#define CLK_ABORT_RATE_CHANGE 3
#define CLK_PRE_ENABLE 4
#define CLK_POST_ENABLE 5
#define CLK_ABORT_ENABLE 6
#define CLK_PRE_DISABLE 7
#define CLK_POST_DISABLE 8
#define CLK_ABORT_DISABLE 9
struct notifier_block;
extern int clk_notifier_register(struct clk *clk, struct notifier_block *nb);
extern int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb);
#endif

View File

@@ -0,0 +1,563 @@
#ifndef __MACH_CRU_H
#define __MACH_CRU_H
enum rk_plls_id {
APLL_ID = 0,
DPLL_ID,
CPLL_ID,
GPLL_ID,
END_PLL_ID,
};
/*****cru reg offset*****/
#define CRU_MODE_CON 0x40
#define CRU_CLKSEL_CON 0x44
#define CRU_CLKGATE_CON 0xd0
#define CRU_GLB_SRST_FST 0x100
#define CRU_GLB_SRST_SND 0x104
#define CRU_SOFTRST_CON 0x110
#define PLL_CONS(id, i) ((id) * 0x10 + ((i) * 4))
#define CRU_CLKSELS_CON_CNT (35)
#define CRU_CLKSELS_CON(i) (CRU_CLKSEL_CON + ((i) * 4))
#define CRU_CLKGATES_CON_CNT (10)
#define CRU_CLKGATES_CON(i) (CRU_CLKGATE_CON + ((i) * 4))
#define CRU_SOFTRSTS_CON_CNT (9)
#define CRU_SOFTRSTS_CON(i) (CRU_SOFTRST_CON + ((i) * 4))
#define CRU_MISC_CON (0x134)
#define CRU_GLB_CNT_TH (0x140)
/*PLL_CON 0,1,2*/
#define PLL_PWR_ON (1)
#define PLL_PWR_DN (0)
#define PLL_BYPASS (1 << 15)
#define PLL_NO_BYPASS (0 << 15)
//con0
#define PLL_BYPASS_SHIFT (15)
#define PLL_POSTDIV1_MASK (0x7)
#define PLL_POSTDIV1_SHIFT (12)
#define PLL_FBDIV_MASK (0xfff)
#define PLL_FBDIV_SHIFT (0)
//con1
#define PLL_RSTMODE_SHIFT (15)
#define PLL_RST_SHIFT (14)
#define PLL_PWR_DN_SHIFT (13)
#define PLL_DSMPD_SHIFT (12)
#define PLL_LOCK_SHIFT (10)
#define PLL_POSTDIV2_MASK (0x7)
#define PLL_POSTDIV2_SHIFT (6)
#define PLL_REFDIV_MASK (0x3f)
#define PLL_REFDIV_SHIFT (0)
//con2
#define PLL_FOUT4PHASE_PWR_DN_SHIFT (27)
#define PLL_FOUTVCO_PWR_DN_SHIFT (26)
#define PLL_FOUTPOSTDIV_PWR_DN_SHIFT (25)
#define PLL_DAC_PWR_DN_SHIFT (24)
#define PLL_FRAC_MASK (0xffffff)
#define PLL_FRAC_SHIFT (0)
/********************************************************************/
#define CRU_GET_REG_BIT_VAL(reg, bits_shift) (((reg) >> (bits_shift)) & (0x1))
#define CRU_GET_REG_BITS_VAL(reg, bits_shift, msk) (((reg) >> (bits_shift)) & (msk))
#define CRU_SET_BIT(val, bits_shift) (((val) & (0x1)) << (bits_shift))
#define CRU_SET_BITS(val, bits_shift, msk) (((val) & (msk)) << (bits_shift))
#define CRU_W_MSK(bits_shift, msk) ((msk) << ((bits_shift) + 16))
#define CRU_W_MSK_SETBITS(val, bits_shift, msk) (CRU_W_MSK(bits_shift, msk) \
| CRU_SET_BITS(val, bits_shift, msk))
#define CRU_W_MSK_SETBIT(val, bits_shift) (CRU_W_MSK(bits_shift, 0x1) \
| CRU_SET_BIT(val, bits_shift))
#define PLL_SET_REFDIV(val) CRU_W_MSK_SETBITS(val, PLL_REFDIV_SHIFT, PLL_REFDIV_MASK)
#define PLL_SET_FBDIV(val) CRU_W_MSK_SETBITS(val, PLL_FBDIV_SHIFT, PLL_FBDIV_MASK)
#define PLL_SET_POSTDIV1(val) CRU_W_MSK_SETBITS(val, PLL_POSTDIV1_SHIFT, PLL_POSTDIV1_MASK)
#define PLL_SET_POSTDIV2(val) CRU_W_MSK_SETBITS(val, PLL_POSTDIV2_SHIFT, PLL_POSTDIV2_MASK)
#define PLL_SET_FRAC(val) CRU_SET_BITS(val, PLL_FRAC_SHIFT, PLL_FRAC_MASK)
#define PLL_GET_REFDIV(reg) CRU_GET_REG_BITS_VAL(reg, PLL_REFDIV_SHIFT, PLL_REFDIV_MASK)
#define PLL_GET_FBDIV(reg) CRU_GET_REG_BITS_VAL(reg, PLL_FBDIV_SHIFT, PLL_FBDIV_MASK)
#define PLL_GET_POSTDIV1(reg) CRU_GET_REG_BITS_VAL(reg, PLL_POSTDIV1_SHIFT, PLL_POSTDIV1_MASK)
#define PLL_GET_POSTDIV2(reg) CRU_GET_REG_BITS_VAL(reg, PLL_POSTDIV2_SHIFT, PLL_POSTDIV2_MASK)
#define PLL_GET_FRAC(reg) CRU_GET_REG_BITS_VAL(reg, PLL_FRAC_SHIFT, PLL_FRAC_MASK)
//#define APLL_SET_BYPASS(val) CRU_SET_BIT(val, PLL_BYPASS_SHIFT)
#define PLL_SET_DSMPD(val) CRU_SET_BIT(val, PLL_DSMPD_SHIFT)
#define PLL_GET_DSMPD(reg) CRU_GET_REG_BIT_VAL(reg, PLL_DSMPD_SHIFT)
/*******************MODE BITS***************************/
#define PLL_MODE_MSK(id) (0x1 << ((id) * 4))
#define PLL_MODE_SHIFT(id) ((id) * 4)
#define PLL_MODE_SLOW(id) (CRU_W_MSK_SETBIT(0x0, PLL_MODE_SHIFT(id)))
#define PLL_MODE_NORM(id) (CRU_W_MSK_SETBIT(0x1, PLL_MODE_SHIFT(id)))
/*******************CLKSEL0 BITS***************************/
#define CLK_SET_DIV_CON_SUB1(val, bits_shift, msk) CRU_W_MSK_SETBITS((val - 1), bits_shift, msk)
#define CPU_CLK_PLL_SEL_SHIFT (13)
#define CORE_CLK_PLL_SEL_SHIFT (7)
#define SEL_APLL (0)
#define SEL_GPLL (1)
#define CPU_SEL_PLL(plls) CRU_W_MSK_SETBIT(plls, CPU_CLK_PLL_SEL_SHIFT)
#define CORE_SEL_PLL(plls) CRU_W_MSK_SETBIT(plls, CORE_CLK_PLL_SEL_SHIFT)
#define ACLK_CPU_DIV_MASK (0x1f)
#define ACLK_CPU_DIV_SHIFT (8)
#define A9_CORE_DIV_MASK (0x1f)
#define A9_CORE_DIV_SHIFT (0)
#define ACLK_CPU_DIV(val) CLK_SET_DIV_CON_SUB1(val, ACLK_CPU_DIV_SHIFT, ACLK_CPU_DIV_MASK)
#define CLK_CORE_DIV(val) CLK_SET_DIV_CON_SUB1(val, A9_CORE_DIV_SHIFT, A9_CORE_DIV_MASK)
/*******************CLKSEL1 BITS***************************/
#define PCLK_CPU_DIV_MASK (0x7)
#define PCLK_CPU_DIV_SHIFT (12)
#define HCLK_CPU_DIV_MASK (0x3)
#define HCLK_CPU_DIV_SHIFT (8)
#define ACLK_CORE_DIV_MASK (0x1)
#define ACLK_CORE_DIV_SHIFT (4)
#define CORE_PERIPH_DIV_MASK (0xf)
#define CORE_PERIPH_DIV_SHIFT (0)
#define PCLK_CPU_DIV(val) CLK_SET_DIV_CON_SUB1(val, PCLK_CPU_DIV_SHIFT, PCLK_CPU_DIV_MASK)
#define HCLK_CPU_DIV(val) CLK_SET_DIV_CON_SUB1(val, HCLK_CPU_DIV_SHIFT, HCLK_CPU_DIV_MASK)
#define ACLK_CORE_DIV(val) CLK_SET_DIV_CON_SUB1(val, ACLK_CORE_DIV_SHIFT, ACLK_CORE_DIV_MASK)
#define CLK_CORE_PERI_DIV(val) CLK_SET_DIV_CON_SUB1(val, CORE_PERIPH_DIV_SHIFT, CORE_PERIPH_DIV_MASK)
/*******************clksel10***************************/
#define PERI_PLL_SEL_SHIFT 15
#define PERI_PCLK_DIV_MASK (0x3)
#define PERI_PCLK_DIV_SHIFT (12)
#define PERI_HCLK_DIV_MASK (0x3)
#define PERI_HCLK_DIV_SHIFT (8)
#define PERI_ACLK_DIV_MASK (0x1f)
#define PERI_ACLK_DIV_SHIFT (0)
#define SEL_2PLL_GPLL (0)
#define SEL_2PLL_CPLL (1)
#define RATIO_11 (0)
#define RATIO_21 (1)
#define RATIO_41 (2)
#define RATIO_81 (3)
#define PERI_CLK_SEL_PLL(plls) CRU_W_MSK_SETBIT(plls, PERI_PLL_SEL_SHIFT)
#define PERI_SET_A2P_RATIO(ratio) CRU_W_MSK_SETBITS(ratio, PERI_PCLK_DIV_SHIFT, PERI_PCLK_DIV_MASK)
#define PERI_SET_A2H_RATIO(ratio) CRU_W_MSK_SETBITS(ratio, PERI_HCLK_DIV_SHIFT, PERI_PCLK_DIV_MASK)
#define PERI_SET_ACLK_DIV(val) CRU_W_MSK_SETBITS(val, PERI_ACLK_DIV_SHIFT, PERI_ACLK_DIV_MASK)
/*******************gate BITS***************************/
#define CLK_GATE_CLKID_CONS(i) CRU_CLKGATES_CON((i) / 16)
#define CLK_GATE(i) (1 << ((i)%16))
#define CLK_UN_GATE(i) (0)
#define CLK_GATE_W_MSK(i) (1 << (((i) % 16) + 16))
#define CLK_GATE_CLKID(i) (16 * (i))
enum cru_clk_gate {
/* SCU CLK GATE 0 CON */
CLK_GATE_CORE_PERIPH = CLK_GATE_CLKID(0),
CLK_GATE_CPU_GPLL,
CLK_GATE_DDRPHY_SRC,
CLK_GATE_ACLK_CPU,
CLK_GATE_HCLK_CPU,
CLK_GATE_PCLK_CPU,
CLK_GATE_0RES6,
CLK_GATE_ACLK_CORE,
CLK_GATE_0RES8,
CLK_GATE_I2S_SRC,
CLK_GATE_I2S_FRAC_SRC,
CLK_GATE_HCLK_VIO_PRE,
CLK_GATE_0RES12,
CLK_GATE_0RES13,
CLK_GATE_0RES14,
CLK_GATE_TESTCLK,
CLK_GATE_TIMER0 = CLK_GATE_CLKID(1),
CLK_GATE_TIMER1,
CLK_GATE_1RES2,
CLK_GATE_JTAG,
CLK_GATE_1RES4,
CLK_GATE_OTGPHY0,
CLK_GATE_OTGPHY1,
CLK_GATE_1RES7,
CLK_GATE_UART0_SRC,
CLK_GATE_UART0_FRAC_SRC,
CLK_GATE_UART1_SRC,
CLK_GATE_UART1_FRAC_SRC,
CLK_GATE_UART2_SRC,
CLK_GATE_UART2_FRAC_SRC,
CLK_GATE_1RES14,
CLK_GATE_1RES15,
CLK_GATE_PERIPH_SRC = CLK_GATE_CLKID(2),
CLK_GATE_ACLK_PERIPH,
CLK_GATE_HCLK_PERIPH,
CLK_GATE_PCLK_PERIPH,
CLK_GATE_2RES4,
CLK_GATE_2RES5,
CLK_GATE_2RES6,
CLK_GATE_2RES7,
CLK_GATE_SARADC_SRC,
CLK_GATE_SPI0_SRC,
CLK_GATE_2RES10,
CLK_GATE_MMC0_SRC,
CLK_GATE_2RES12,
CLK_GATE_SDIO_SRC,
CLK_GATE_EMMC_SRC,
CLK_GATE_2RES15,
CLK_GATE_ACLK_VIO_SRC = CLK_GATE_CLKID(3),
CLK_GATE_DCLK_LCDC0_SRC,
CLK_GATE_SCLK_LCDC_SRC,
CLK_GATE_PCLKIN_CIF,
CLK_GATE_ACLK_GPS,
CLK_GATE_3RES5,
CLK_GATE_3RES6,
CLK_GATE_CIF_OUT_SRC,
CLK_GATE_PCLK_HDMI,
CLK_GATE_ACLK_VEPU_SRC,
CLK_GATE_HCLK_VEPU,
CLK_GATE_ACLK_VDPU_SRC,
CLK_GATE_HCLK_VDPU,
CLK_GATE_GPU_PRE,
CLK_GATE_3RES14,
CLK_GATE_3RES15,
CLK_GATE_HCLK_PERI_AXI_MATRIX = CLK_GATE_CLKID(4),
CLK_GATE_PCLK_PERI_AXI_MATRIX,
CLK_GATE_ACLK_CPU_PERI,
CLK_GATE_ACLK_PERI_AXI_MATRIX,
CLK_GATE_4RES4,
CLK_GATE_4RES5,
CLK_GATE_4RES6,
CLK_GATE_4RES7,
CLK_GATE_4RES8,
CLK_GATE_4RES9,
CLK_GATE_ACLK_STRC_SYS,
CLK_GATE_4RES11,
CLK_GATE_ACLK_INTMEM,
CLK_GATE_4RES13,
CLK_GATE_4RES14,
CLK_GATE_4RES15,
CLK_GATE_5RES0 = CLK_GATE_CLKID(5),
CLK_GATE_ACLK_DMAC2,
CLK_GATE_PCLK_EFUSE,
CLK_GATE_5RES3,
CLK_GATE_PCLK_GRF,
CLK_GATE_5RES5,
CLK_GATE_HCLK_ROM,
CLK_GATE_PCLK_DDRUPCTL,
CLK_GATE_5RES8,
CLK_GATE_HCLK_NANDC,
CLK_GATE_HCLK_SDMMC0,
CLK_GATE_HCLK_SDIO,
CLK_GATE_5RES12,
CLK_GATE_HCLK_OTG0,
CLK_GATE_PCLK_ACODEC,
CLK_GATE_5RES15,
CLK_GATE_ACLK_LCDC0 = CLK_GATE_CLKID(6),
CLK_GATE_HCLK_LCDC0,
CLK_GATE_6RES2,
CLK_GATE_6RES3,
CLK_GATE_HCLK_CIF,
CLK_GATE_ACLK_CIF,
CLK_GATE_6RES6,
CLK_GATE_6RES7,
CLK_GATE_6RES8,
CLK_GATE_6RES9,
CLK_GATE_HCLK_RGA,
CLK_GATE_ACLK_RGA,
CLK_GATE_HCLK_VIO_BUS,
CLK_GATE_ACLK_VIO0,
CLK_GATE_6RES14,
CLK_GATE_6RES15,
CLK_GATE_HCLK_EMMC = CLK_GATE_CLKID(7),
CLK_GATE_7RES1,
CLK_GATE_HCLK_I2S,
CLK_GATE_HCLK_OTG1,
CLK_GATE_7RES4,
CLK_GATE_7RES5,
CLK_GATE_7RES6,
CLK_GATE_PCLK_TIMER0,
CLK_GATE_PCLK_TIMER1,
CLK_GATE_7RES9,
CLK_GATE_PCLK_PWM01,
CLK_GATE_7RES11,
CLK_GATE_PCLK_SPI0,
CLK_GATE_7RES13,
CLK_GATE_PCLK_SARADC,
CLK_GATE_PCLK_WDT,
CLK_GATE_PCLK_UART0 = CLK_GATE_CLKID(8),
CLK_GATE_PCLK_UART1,
CLK_GATE_PCLK_UART2,
CLK_GATE_8RES3,
CLK_GATE_PCLK_I2C0,
CLK_GATE_PCLK_I2C1,
CLK_GATE_PCLK_I2C2,
CLK_GATE_PCLK_I2C3,
CLK_GATE_8RES8,
CLK_GATE_PCLK_GPIO0,
CLK_GATE_PCLK_GPIO1,
CLK_GATE_PCLK_GPIO2,
CLK_GATE_PCLK_GPIO3,
CLK_GATE_8RES13,
CLK_GATE_8RES14,
CLK_GATE_8RES15,
CLK_GATE_CLK_CORE_DBG = CLK_GATE_CLKID(9),
CLK_GATE_PCLK_DBG,
CLK_GATE_9RES2,
CLK_GATE_9RES3,
CLK_GATE_CLK_L2C,
CLK_GATE_9RES5,
CLK_GATE_9RES6,
CLK_GATE_9RES7,
CLK_GATE_9RES8,
CLK_GATE_9RES9,
CLK_GATE_HCLK_USB_PERI,
CLK_GATE_HCLK_PERI_ARBI,
CLK_GATE_ACLK_PERI_NIU,
CLK_GATE_9RES13,
CLK_GATE_9RES14,
CLK_GATE_9RES15,
CLK_GATE_MAX,
};
#define SOFT_RST_ID(i) (16 * (i))
enum cru_soft_reset {
SOFT_RST_CORE_SRST_WDT_SEL = SOFT_RST_ID(0),
SOFT_RST_ACLK_CORE,
SOFT_RST_MCORE,
SOFT_RST_0RES3,
SOFT_RST_0RES4,
SOFT_RST_0RES5,
SOFT_RST_0RES6,
SOFT_RST_MCORE_DBG,
SOFT_RST_0RES8,
SOFT_RST_0RES9,
SOFT_RST_0RES10,
SOFT_RST_0RES11,
SOFT_RST_CORE0_WDT,
SOFT_RST_0RES13,
SOFT_RST_STRC_SYS_AXI,
SOFT_RST_0RES15,
SOFT_RST_CPU_STRC_SYS_AXI = SOFT_RST_ID(1),
SOFT_RST_CPUSYS_AHB,
SOFT_RST_L2MEM_CON_AXI,
SOFT_RST_AHB2APB,
SOFT_RST_1RES4,
SOFT_RST_INTMEM,
SOFT_RST_ROM,
SOFT_RST_PERI_NIU,
SOFT_RST_I2S,
SOFT_RST_1RES9,
SOFT_RST_1RES10,
SOFT_RST_TIMER0,
SOFT_RST_TIMER1,
SOFT_RST_1RES13,
SOFT_RST_EFUSE_APB,
SOFT_RST_ACODEC,
SOFT_RST_GPIO0 = SOFT_RST_ID(2),
SOFT_RST_GPIO1,
SOFT_RST_GPIO2,
SOFT_RST_GPIO3,
SOFT_RST_2RES4,
SOFT_RST_2RES5,
SOFT_RST_2RES6,
SOFT_RST_UART0,
SOFT_RST_UART1,
SOFT_RST_UART2,
SOFT_RST_2RES10,
SOFT_RST_I2C0,
SOFT_RST_I2C1,
SOFT_RST_I2C2,
SOFT_RST_I2C3,
SOFT_RST_2RES15,
SOFT_RST_PWM0 = SOFT_RST_ID(3),
SOFT_RST_PWM1,
SOFT_RST_DAP_PO,
SOFT_RST_DAP,
SOFT_RST_DAP_SYS,
SOFT_RST_3RES5,
SOFT_RST_3RES6,
SOFT_RST_GRF,
SOFT_RST_I2C,
SOFT_RST_PERIPHSYS_AXI,
SOFT_RST_PERIPHSYS_AHB,
SOFT_RST_PERIPHSYS_APB,
SOFT_RST_PWM2,
SOFT_RST_CPU_PERI,
SOFT_RST_EMEM_PERI,
SOFT_RST_USB_PERI,
SOFT_RST_DMA2 = SOFT_RST_ID(4),
SOFT_RST_4RES1,
SOFT_RST_4RES2,
SOFT_RST_GPS,
SOFT_RST_NANDC,
SOFT_RST_USBOTG0,
SOFT_RST_USBPHY0,
SOFT_RST_OTGC0,
SOFT_RST_USBOTG1,
SOFT_RST_USBPHY1,
SOFT_RST_OTGC1,
SOFT_RST_4RES11,
SOFT_RST_4RES12,
SOFT_RST_4RES13,
SOFT_RST_4RES14,
SOFT_RST_DDRMSCH,
SOFT_RST_5RES0 = SOFT_RST_ID(5),
SOFT_RST_MMC0,
SOFT_RST_SDIO,
SOFT_RST_EMMC,
SOFT_RST_SPI0,
SOFT_RST_5RES5,
SOFT_RST_WDT,
SOFT_RST_SARADC,
SOFT_RST_DDRPHY,
SOFT_RST_DDRPHY_APB,
SOFT_RST_DDRCTRL,
SOFT_RST_DDRCTRL_APB,
SOFT_RST_5RES12,
SOFT_RST_5RES13,
SOFT_RST_5RES14,
SOFT_RST_5RES15,
SOFT_RST_HDMI_PCLK = SOFT_RST_ID(6),
SOFT_RST_HDMI_DCLK,
SOFT_RST_VIO0_AXI,
SOFT_RST_VIO_BUS_AHB,
SOFT_RST_LCDC0_AXI,
SOFT_RST_LCDC0_AHB,
SOFT_RST_LCDC0_DCLK,
SOFT_RST_UTMI0,
SOFT_RST_UTMI1,
SOFT_RST_USBPOR,
SOFT_RST_6RES10,
SOFT_RST_6RES11,
SOFT_RST_RGA_AXI,
SOFT_RST_RGA_AHB,
SOFT_RST_CIF0,
SOFT_RST_LCDC_SCL,
SOFT_RST_VCODEC_AXI = SOFT_RST_ID(7),
SOFT_RST_VCODEC_AHB,
SOFT_RST_VIO1_AXI,
SOFT_RST_CPU_VCODEC,
SOFT_RST_VCODEC_NIU_AXI,
SOFT_RST_7RES5,
SOFT_RST_7RES6,
SOFT_RST_7RES7,
SOFT_RST_GPU,
SOFT_RST_7RES9,
SOFT_RST_GPU_NIU_AXI,
SOFT_RST_7RES11,
SOFT_RST_7RES12,
SOFT_RST_7RES13,
SOFT_RST_7RES14,
SOFT_RST_7RES15,
SOFT_RST_8RES0 = SOFT_RST_ID(8),
SOFT_RST_8RES1,
SOFT_RST_CORE_DBG,
SOFT_RST_DBG_APB,
SOFT_RST_8RES4,
SOFT_RST_8RES5,
SOFT_RST_8RES6,
SOFT_RST_8RES7,
SOFT_RST_8RES8,
SOFT_RST_8RES9,
SOFT_RST_8RES10,
SOFT_RST_8RES11,
SOFT_RST_8RES12,
SOFT_RST_8RES13,
SOFT_RST_8RES14,
SOFT_RST_8RES15,
SOFT_RST_MAX,
};
/*****cru reg end*****/
static inline void cru_set_soft_reset(enum cru_soft_reset idx, bool on)
{
const void __iomem *reg = RK2928_CRU_BASE + CRU_SOFTRSTS_CON(idx >> 4);
u32 val = on ? 0x10001U << (idx & 0xf) : 0x10000U << (idx & 0xf);
writel_relaxed(val, reg);
dsb();
}
#endif