126 lines
4.1 KiB
C
126 lines
4.1 KiB
C
|
/*
|
||
|
* Copyright (C) 2010 ST-Ericsson
|
||
|
* Copyright (C) 2009 STMicroelectronics
|
||
|
*
|
||
|
* 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.
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* struct clkops - ux500 clock operations
|
||
|
* @enable: function to enable the clock
|
||
|
* @disable: function to disable the clock
|
||
|
* @get_rate: function to get the current clock rate
|
||
|
*
|
||
|
* This structure contains function pointers to functions that will be used to
|
||
|
* control the clock. All of these functions are optional. If get_rate is
|
||
|
* NULL, the rate in the struct clk will be used.
|
||
|
*/
|
||
|
struct clkops {
|
||
|
void (*enable) (struct clk *);
|
||
|
void (*disable) (struct clk *);
|
||
|
unsigned long (*get_rate) (struct clk *);
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* struct clk - ux500 clock structure
|
||
|
* @ops: pointer to clkops struct used to control this clock
|
||
|
* @name: name, for debugging
|
||
|
* @enabled: refcount. positive if enabled, zero if disabled
|
||
|
* @rate: fixed rate for clocks which don't implement
|
||
|
* ops->getrate
|
||
|
* @prcmu_cg_off: address offset of the combined enable/disable register
|
||
|
* (used on u8500v1)
|
||
|
* @prcmu_cg_bit: bit in the combined enable/disable register (used on
|
||
|
* u8500v1)
|
||
|
* @prcmu_cg_mgt: address of the enable/disable register (used on
|
||
|
* u8500ed)
|
||
|
* @cluster: peripheral cluster number
|
||
|
* @prcc_bus: bit for the bus clock in the peripheral's CLKRST
|
||
|
* @prcc_kernel: bit for the kernel clock in the peripheral's CLKRST.
|
||
|
* -1 if no kernel clock exists.
|
||
|
* @parent_cluster: pointer to parent's cluster clk struct
|
||
|
* @parent_periph: pointer to parent's peripheral clk struct
|
||
|
*
|
||
|
* Peripherals are organised into clusters, and each cluster has an associated
|
||
|
* bus clock. Some peripherals also have a parent peripheral clock.
|
||
|
*
|
||
|
* In order to enable a clock for a peripheral, we need to enable:
|
||
|
* (1) the parent cluster (bus) clock at the PRCMU level
|
||
|
* (2) the parent peripheral clock (if any) at the PRCMU level
|
||
|
* (3) the peripheral's bus & kernel clock at the PRCC level
|
||
|
*
|
||
|
* (1) and (2) are handled by defining clk structs (DEFINE_PRCMU_CLK) for each
|
||
|
* of the cluster and peripheral clocks, and hooking these as the parents of
|
||
|
* the individual peripheral clocks.
|
||
|
*
|
||
|
* (3) is handled by specifying the bits in the PRCC control registers required
|
||
|
* to enable these clocks and modifying them in the ->enable and
|
||
|
* ->disable callbacks of the peripheral clocks (DEFINE_PRCC_CLK).
|
||
|
*
|
||
|
* This structure describes both the PRCMU-level clocks and PRCC-level clocks.
|
||
|
* The prcmu_* fields are only used for the PRCMU clocks, and the cluster,
|
||
|
* prcc, and parent pointers are only used for the PRCC-level clocks.
|
||
|
*/
|
||
|
struct clk {
|
||
|
const struct clkops *ops;
|
||
|
const char *name;
|
||
|
unsigned int enabled;
|
||
|
|
||
|
unsigned long rate;
|
||
|
struct list_head list;
|
||
|
|
||
|
/* These three are only for PRCMU clks */
|
||
|
|
||
|
unsigned int prcmu_cg_off;
|
||
|
unsigned int prcmu_cg_bit;
|
||
|
unsigned int prcmu_cg_mgt;
|
||
|
|
||
|
/* The rest are only for PRCC clks */
|
||
|
|
||
|
int cluster;
|
||
|
unsigned int prcc_bus;
|
||
|
unsigned int prcc_kernel;
|
||
|
|
||
|
struct clk *parent_cluster;
|
||
|
struct clk *parent_periph;
|
||
|
};
|
||
|
|
||
|
#define DEFINE_PRCMU_CLK(_name, _cg_off, _cg_bit, _reg) \
|
||
|
struct clk clk_##_name = { \
|
||
|
.name = #_name, \
|
||
|
.ops = &clk_prcmu_ops, \
|
||
|
.prcmu_cg_off = _cg_off, \
|
||
|
.prcmu_cg_bit = _cg_bit, \
|
||
|
.prcmu_cg_mgt = PRCM_##_reg##_MGT \
|
||
|
}
|
||
|
|
||
|
#define DEFINE_PRCMU_CLK_RATE(_name, _cg_off, _cg_bit, _reg, _rate) \
|
||
|
struct clk clk_##_name = { \
|
||
|
.name = #_name, \
|
||
|
.ops = &clk_prcmu_ops, \
|
||
|
.prcmu_cg_off = _cg_off, \
|
||
|
.prcmu_cg_bit = _cg_bit, \
|
||
|
.rate = _rate, \
|
||
|
.prcmu_cg_mgt = PRCM_##_reg##_MGT \
|
||
|
}
|
||
|
|
||
|
#define DEFINE_PRCC_CLK(_pclust, _name, _bus_en, _kernel_en, _kernclk) \
|
||
|
struct clk clk_##_name = { \
|
||
|
.name = #_name, \
|
||
|
.ops = &clk_prcc_ops, \
|
||
|
.cluster = _pclust, \
|
||
|
.prcc_bus = _bus_en, \
|
||
|
.prcc_kernel = _kernel_en, \
|
||
|
.parent_cluster = &clk_per##_pclust##clk, \
|
||
|
.parent_periph = _kernclk \
|
||
|
}
|
||
|
|
||
|
#define CLK(_clk, _devname, _conname) \
|
||
|
{ \
|
||
|
.clk = &clk_##_clk, \
|
||
|
.dev_id = _devname, \
|
||
|
.con_id = _conname, \
|
||
|
}
|