blob: e4fcc820a86f2893740ad0de83082142ef99aa0e [file] [log] [blame]
/*
* arch/arm/plat-ambarella/include/plat/clk.c
*
* Author: Anthony Ginger <hfjiang@ambarella.com>
*
* Copyright (C) 2004-2010, Ambarella, Inc.
*
* 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, or
* (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef __PLAT_AMBARELLA_CLK_H__
#define __PLAT_AMBARELLA_CLK_H__
#include <plat/rct.h>
/* ==========================================================================*/
enum PLL_CLK_HZ {
PLL_CLK_10D1001MHZ = 9990010,
PLL_CLK_10MHZ = 10000000,
PLL_CLK_13D1001MHZ = 12987012,
PLL_CLK_13MHZ = 13000000,
PLL_CLK_13_5D1001MHZ = 13486513,
PLL_CLK_13_5MHZ = 13500000,
PLL_CLK_17_97515MHZ = 17975154,
PLL_CLK_17_97554MHZ = 17975544,
PLL_CLK_17_98201MHZ = 17982018,
PLL_CLK_18_44MHz = 18440000,
PLL_CLK_22_5MHZ = 22500000,
PLL_CLK_23_9772MHZ = 23977223,
PLL_CLK_23_9784MHZ = 23978422,
PLL_CLK_23_99MHZ = 23998277,
PLL_CLK_23_967MHZ = 23967392,
PLL_CLK_23_971MHZ = 23971444,
PLL_CLK_24D1001MHZ = 23976024,
PLL_CLK_23_996MHZ = 23996483,
PLL_CLK_24MHZ = 24000000,
PLL_CLK_24M1001MHZ = 24024000,
PLL_CLK_24_072MHZ = 24072001,
PLL_CLK_24_3MHZ = 24300000,
PLL_CLK_24_54MHZ = 24545430,
PLL_CLK_25MHZ = 25000000,
PLL_CLK_27D1001MHZ = 26973027,
PLL_CLK_26_9823MHZ = 26982318,
PLL_CLK_26_9485MHZ = 26948544,
PLL_CLK_26_9568MHZ = 26956800,
PLL_CLK_27MHZ = 27000000,
PLL_CLK_27_0432MHZ = 27043200,
PLL_CLK_27_0514MHZ = 27051402,
PLL_CLK_27M1001MHZ = 27027000,
PLL_CLK_30MHZ = 30000000,
PLL_CLK_27_1792MHZ = 27179210,
PLL_CLK_32_5D1001MHZ = 32467532,
PLL_CLK_36D1001MHZ = 35964036,
PLL_CLK_36MHZ = 36000000,
PLL_CLK_36_20MHZ = 36197802,
PLL_CLK_36_23MHZ = 36234000,
PLL_CLK_37_125D1001MHZ = 37087912,
PLL_CLK_37_125MHZ = 37125000,
PLL_CLK_42D1001MHZ = 41958042,
PLL_CLK_42MHZ = 42000000,
PLL_CLK_45MHZ = 45000000,
PLL_CLK_48D1001MHZ = 47952048,
PLL_CLK_48MHZ = 48000000,
PLL_CLK_48_6MHZ = 48600000,
PLL_CLK_49_5D1001MHZ = 49450549,
PLL_CLK_49_5MHZ = 49500000,
PLL_CLK_54MHZ = 54000000,
PLL_CLK_54M1001MHZ = 54054000,
PLL_CLK_59_4MHZ = 59400000,
PLL_CLK_60MHZ = 60000000,
PLL_CLK_60M1001MHZ = 60060000,
PLL_CLK_60_05MHz = 60054545,
PLL_CLK_60_16MHZ = 60164835,
PLL_CLK_60_18MHZ = 60183566,
PLL_CLK_60_29MHZ = 60285794,
PLL_CLK_60_33MHZ = 60329670,
PLL_CLK_60_35MHZ = 60346080,
PLL_CLK_60_39MHZ = 60390000,
PLL_CLK_60_48MHz = 60480000,
PLL_CLK_64D1001MHZ = 63936064,
PLL_CLK_64MHZ = 64000000,
PLL_CLK_65D1001MHZ = 64935064,
PLL_CLK_72D1001MHZ = 71928072,
PLL_CLK_72MHZ = 72000000,
PLL_CLK_74_25D1001MHZ = 74175824,
PLL_CLK_74_25MHZ = 74250000,
PLL_CLK_80MHZ = 80000000,
PLL_CLK_90D1001MHZ = 89910090,
PLL_CLK_90MHZ = 90000000,
PLL_CLK_90_62D1001MHZ = 90525314,
PLL_CLK_90_62MHZ = 90615840,
PLL_CLK_90_69D1001MHZ = 90596763,
PLL_CLK_90_69MHZ = 90687360,
PLL_CLK_95_993D1001MHZ = 95896903,
PLL_CLK_96D1001MHZ = 95904096,
PLL_CLK_96MHZ = 96000000,
PLL_CLK_99D1001MHZ = 98901099,
PLL_CLK_99MHZ = 99000000,
PLL_CLK_99_18D1001MHZ = 99081439,
PLL_CLK_99_18MHZ = 99180720,
PLL_CLK_108MHZ = 108000000,
PLL_CLK_148_5D1001MHZ = 148351648,
PLL_CLK_148_5MHZ = 148500000,
PLL_CLK_120MHZ = 120000000,
PLL_CLK_144MHZ = 144000000,
PLL_CLK_150MHZ = 150000000,
PLL_CLK_156MHZ = 156000000,
PLL_CLK_160MHZ = 160000000,
PLL_CLK_192MHZ = 192000000,
PLL_CLK_216MHZ = 216000000,
PLL_CLK_230_4MHZ = 230400000,
PLL_CLK_240MHZ = 240000000,
PLL_CLK_288MHZ = 288000000,
PLL_CLK_296_703MHZ = 296703000,
PLL_CLK_297MHZ = 297000000,
PLL_CLK_320MHZ = 320000000,
PLL_CLK_384MHZ = 384000000,
PLL_CLK_495MHZ = 495000000,
PLL_CLK_594MHZ = 594000000,
};
struct clk;
struct clk_ops {
int (*enable)(struct clk *c);
int (*disable)(struct clk *c);
unsigned long (*get_rate)(struct clk *c);
unsigned long (*round_rate)(struct clk *c, unsigned long rate);
int (*set_rate)(struct clk *c, unsigned long rate);
int (*set_parent)(struct clk *c, struct clk *parent);
};
struct clk {
struct list_head list;
struct clk *parent;
const char *name;
u64 rate;
u32 frac_mode;
u32 ctrl_reg;
u32 pres_reg;
u32 pres_val;
u32 post_reg;
u32 post_val;
u32 frac_reg;
u32 ctrl2_reg;
u32 ctrl2_val;
u32 ctrl3_reg;
u32 ctrl3_val;
u32 lock_reg;
u32 lock_bit;
u32 divider;
u32 max_divider;
u32 extra_scaler;
struct pll_table *table;
u32 table_size;
struct clk_ops *ops;
};
struct pll_table {
u64 multiplier; /* pll_out / (ref_clk / pre_scaler) */
u32 intp;
u32 sdiv;
u32 sout;
u32 post;
};
union ctrl_reg_u {
struct {
u32 write_enable : 1; /* [0] */
u32 reserved1 : 1; /* [1] */
u32 bypass : 1; /* [2] */
u32 frac_mode : 1; /* [3] */
u32 force_reset : 1; /* [4] */
u32 power_down : 1; /* [5] */
u32 halt_vco : 1; /* [6] */
u32 tristate : 1; /* [7] */
u32 tout_async : 4; /* [11:8] */
u32 sdiv : 4; /* [15:12] */
u32 sout : 4; /* [19:16] */
u32 force_lock : 1; /* [20] */
u32 force_bypass : 1; /* [21] */
u32 reserved2 : 2; /* [23:22] */
u32 intp : 7; /* [30:24] */
u32 reserved3 : 1; /* [31] */
} s;
u32 w;
};
union frac_reg_u {
struct {
u32 frac : 31; /* [30:0] */
u32 nega : 1; /* [31] */
} s;
u32 w;
};
/* ==========================================================================*/
#ifndef __ASSEMBLER__
#define AMBCLK_DO_DIV(divident, divider) do { \
do_div((divident), (divider)); \
} while (0)
#define AMBCLK_DO_DIV_ROUND(divident, divider) do { \
(divident) += ((divider) >> 1); \
do_div((divident), (divider)); \
} while (0)
extern struct clk_ops ambarella_rct_pll_ops;
extern struct clk_ops ambarella_rct_scaler_ops;
#ifdef CONFIG_AMBARELLA_CALC_PLL
#define AMBARELLA_PLL_FRAC_TABLE_SIZE (0)
extern struct pll_table ambarella_pll_frac_table[AMBARELLA_PLL_FRAC_TABLE_SIZE];
#define AMBARELLA_PLL_INT_TABLE_SIZE (0)
extern struct pll_table ambarella_pll_int_table[AMBARELLA_PLL_INT_TABLE_SIZE];
#else
#define AMBARELLA_PLL_FRAC_TABLE_SIZE (590)
extern struct pll_table ambarella_pll_frac_table[AMBARELLA_PLL_FRAC_TABLE_SIZE];
#define AMBARELLA_PLL_INT_TABLE_SIZE (93)
extern struct pll_table ambarella_pll_int_table[AMBARELLA_PLL_INT_TABLE_SIZE];
#define AMBARELLA_PLL_VOUT_TABLE_SIZE (797)
extern struct pll_table ambarella_pll_vout_table[AMBARELLA_PLL_VOUT_TABLE_SIZE];
#define AMBARELLA_PLL_VOUT2_TABLE_SIZE (793)
extern struct pll_table ambarella_pll_vout2_table[AMBARELLA_PLL_VOUT2_TABLE_SIZE];
#endif
extern u32 ambarella_rct_find_pll_table_index(unsigned long rate,
u32 pre_scaler, const struct pll_table *table, u32 table_size);
extern unsigned long ambarella_rct_clk_get_rate(struct clk *c);
extern int ambarella_rct_clk_set_rate(struct clk *c, unsigned long rate);
extern int ambarella_rct_clk_adj_rate(struct clk *c, unsigned long rate);
extern int ambarella_rct_clk_enable(struct clk *c);
extern int ambarella_rct_clk_disable(struct clk *c);
extern unsigned long ambarella_rct_scaler_get_rate(struct clk *c);
extern int ambarella_rct_scaler_set_rate(struct clk *c, unsigned long rate);
extern int ambarella_clk_init(void);
extern int ambarella_clk_add(struct clk *clk);
extern unsigned int ambarella_clk_get_ref_freq(void);
#endif /* __ASSEMBLER__ */
/* ==========================================================================*/
#endif