ti.h 11.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/*
 * TI clock drivers support
 *
 * Copyright (C) 2013 Texas Instruments, Inc.
 *
 * 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.
 *
 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
 * kind, whether express or implied; without even the implied warranty
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */
#ifndef __LINUX_CLK_TI_H__
#define __LINUX_CLK_TI_H__

18
#include <linux/clk-provider.h>
19 20
#include <linux/clkdev.h>

T
Tero Kristo 已提交
21 22 23 24 25
/**
 * struct dpll_data - DPLL registers and integration data
 * @mult_div1_reg: register containing the DPLL M and N bitfields
 * @mult_mask: mask of the DPLL M bitfield in @mult_div1_reg
 * @div1_mask: mask of the DPLL N bitfield in @mult_div1_reg
26 27
 * @clk_bypass: struct clk_hw pointer to the clock's bypass clock input
 * @clk_ref: struct clk_hw pointer to the clock's reference clock input
T
Tero Kristo 已提交
28 29 30 31 32 33 34 35 36 37 38 39
 * @control_reg: register containing the DPLL mode bitfield
 * @enable_mask: mask of the DPLL mode bitfield in @control_reg
 * @last_rounded_rate: cache of the last rate result of omap2_dpll_round_rate()
 * @last_rounded_m: cache of the last M result of omap2_dpll_round_rate()
 * @last_rounded_m4xen: cache of the last M4X result of
 *			omap4_dpll_regm4xen_round_rate()
 * @last_rounded_lpmode: cache of the last lpmode result of
 *			 omap4_dpll_lpmode_recalc()
 * @max_multiplier: maximum valid non-bypass multiplier value (actual)
 * @last_rounded_n: cache of the last N result of omap2_dpll_round_rate()
 * @min_divider: minimum valid non-bypass divider value (actual)
 * @max_divider: maximum valid non-bypass divider value (actual)
40
 * @max_rate: maximum clock rate for the DPLL
T
Tero Kristo 已提交
41 42 43 44 45
 * @modes: possible values of @enable_mask
 * @autoidle_reg: register containing the DPLL autoidle mode bitfield
 * @idlest_reg: register containing the DPLL idle status bitfield
 * @autoidle_mask: mask of the DPLL autoidle mode bitfield in @autoidle_reg
 * @freqsel_mask: mask of the DPLL jitter correction bitfield in @control_reg
46 47
 * @dcc_mask: mask of the DPLL DCC correction bitfield @mult_div1_reg
 * @dcc_rate: rate atleast which DCC @dcc_mask must be set
T
Tero Kristo 已提交
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
 * @idlest_mask: mask of the DPLL idle status bitfield in @idlest_reg
 * @lpmode_mask: mask of the DPLL low-power mode bitfield in @control_reg
 * @m4xen_mask: mask of the DPLL M4X multiplier bitfield in @control_reg
 * @auto_recal_bit: bitshift of the driftguard enable bit in @control_reg
 * @recal_en_bit: bitshift of the PRM_IRQENABLE_* bit for recalibration IRQs
 * @recal_st_bit: bitshift of the PRM_IRQSTATUS_* bit for recalibration IRQs
 * @flags: DPLL type/features (see below)
 *
 * Possible values for @flags:
 * DPLL_J_TYPE: "J-type DPLL" (only some 36xx, 4xxx DPLLs)
 *
 * @freqsel_mask is only used on the OMAP34xx family and AM35xx.
 *
 * XXX Some DPLLs have multiple bypass inputs, so it's not technically
 * correct to only have one @clk_bypass pointer.
 *
 * XXX The runtime-variable fields (@last_rounded_rate, @last_rounded_m,
 * @last_rounded_n) should be separated from the runtime-fixed fields
 * and placed into a different structure, so that the runtime-fixed data
 * can be placed into read-only space.
 */
struct dpll_data {
	void __iomem		*mult_div1_reg;
	u32			mult_mask;
	u32			div1_mask;
73 74
	struct clk_hw		*clk_bypass;
	struct clk_hw		*clk_ref;
T
Tero Kristo 已提交
75 76 77 78 79 80 81 82 83 84
	void __iomem		*control_reg;
	u32			enable_mask;
	unsigned long		last_rounded_rate;
	u16			last_rounded_m;
	u8			last_rounded_m4xen;
	u8			last_rounded_lpmode;
	u16			max_multiplier;
	u8			last_rounded_n;
	u8			min_divider;
	u16			max_divider;
85
	unsigned long		max_rate;
T
Tero Kristo 已提交
86 87 88 89 90 91 92 93
	u8			modes;
	void __iomem		*autoidle_reg;
	void __iomem		*idlest_reg;
	u32			autoidle_mask;
	u32			freqsel_mask;
	u32			idlest_mask;
	u32			dco_mask;
	u32			sddiv_mask;
94 95
	u32			dcc_mask;
	unsigned long		dcc_rate;
T
Tero Kristo 已提交
96 97 98 99 100 101 102 103
	u32			lpmode_mask;
	u32			m4xen_mask;
	u8			auto_recal_bit;
	u8			recal_en_bit;
	u8			recal_st_bit;
	u8			flags;
};

104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
struct clk_hw_omap;

/**
 * struct clk_hw_omap_ops - OMAP clk ops
 * @find_idlest: find idlest register information for a clock
 * @find_companion: find companion clock register information for a clock,
 *		    basically converts CM_ICLKEN* <-> CM_FCLKEN*
 * @allow_idle: enables autoidle hardware functionality for a clock
 * @deny_idle: prevent autoidle hardware functionality for a clock
 */
struct clk_hw_omap_ops {
	void	(*find_idlest)(struct clk_hw_omap *oclk,
			       void __iomem **idlest_reg,
			       u8 *idlest_bit, u8 *idlest_val);
	void	(*find_companion)(struct clk_hw_omap *oclk,
				  void __iomem **other_reg,
				  u8 *other_bit);
	void	(*allow_idle)(struct clk_hw_omap *oclk);
	void	(*deny_idle)(struct clk_hw_omap *oclk);
};
T
Tero Kristo 已提交
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188

/**
 * struct clk_hw_omap - OMAP struct clk
 * @node: list_head connecting this clock into the full clock list
 * @enable_reg: register to write to enable the clock (see @enable_bit)
 * @enable_bit: bitshift to write to enable/disable the clock (see @enable_reg)
 * @flags: see "struct clk.flags possibilities" above
 * @clksel_reg: for clksel clks, register va containing src/divisor select
 * @dpll_data: for DPLLs, pointer to struct dpll_data for this clock
 * @clkdm_name: clockdomain name that this clock is contained in
 * @clkdm: pointer to struct clockdomain, resolved from @clkdm_name at runtime
 * @ops: clock ops for this clock
 */
struct clk_hw_omap {
	struct clk_hw		hw;
	struct list_head	node;
	unsigned long		fixed_rate;
	u8			fixed_div;
	void __iomem		*enable_reg;
	u8			enable_bit;
	u8			flags;
	void __iomem		*clksel_reg;
	struct dpll_data	*dpll_data;
	const char		*clkdm_name;
	struct clockdomain	*clkdm;
	const struct clk_hw_omap_ops	*ops;
};

/*
 * struct clk_hw_omap.flags possibilities
 *
 * XXX document the rest of the clock flags here
 *
 * ENABLE_REG_32BIT: (OMAP1 only) clock control register must be accessed
 *     with 32bit ops, by default OMAP1 uses 16bit ops.
 * CLOCK_IDLE_CONTROL: (OMAP1 only) clock has autoidle support.
 * CLOCK_NO_IDLE_PARENT: (OMAP1 only) when clock is enabled, its parent
 *     clock is put to no-idle mode.
 * ENABLE_ON_INIT: Clock is enabled on init.
 * INVERT_ENABLE: By default, clock enable bit behavior is '1' enable, '0'
 *     disable. This inverts the behavior making '0' enable and '1' disable.
 * CLOCK_CLKOUTX2: (OMAP4 only) DPLL CLKOUT and CLKOUTX2 GATE_CTRL
 *     bits share the same register.  This flag allows the
 *     omap4_dpllmx*() code to determine which GATE_CTRL bit field
 *     should be used.  This is a temporary solution - a better approach
 *     would be to associate clock type-specific data with the clock,
 *     similar to the struct dpll_data approach.
 * MEMMAP_ADDRESSING: Use memmap addressing to access clock registers.
 */
#define ENABLE_REG_32BIT	(1 << 0)	/* Use 32-bit access */
#define CLOCK_IDLE_CONTROL	(1 << 1)
#define CLOCK_NO_IDLE_PARENT	(1 << 2)
#define ENABLE_ON_INIT		(1 << 3)	/* Enable upon framework init */
#define INVERT_ENABLE		(1 << 4)	/* 0 enables, 1 disables */
#define CLOCK_CLKOUTX2		(1 << 5)
#define MEMMAP_ADDRESSING	(1 << 6)

/* CM_CLKEN_PLL*.EN* bit values - not all are available for every DPLL */
#define DPLL_LOW_POWER_STOP	0x1
#define DPLL_LOW_POWER_BYPASS	0x5
#define DPLL_LOCKED		0x7

/* DPLL Type and DCO Selection Flags */
#define DPLL_J_TYPE		0x1

189 190 191
/* Static memmap indices */
enum {
	TI_CLKM_CM = 0,
192
	TI_CLKM_CM2,
193 194
	TI_CLKM_PRM,
	TI_CLKM_SCRM,
195
	TI_CLKM_CTRL,
196
	TI_CLKM_PLLSS,
197
	CLK_MAX_MEMMAPS
198 199
};

200 201 202 203 204 205 206 207 208 209 210
/**
 * struct clk_omap_reg - OMAP register declaration
 * @offset: offset from the master IP module base address
 * @index: index of the master IP module
 */
struct clk_omap_reg {
	u16 offset;
	u16 index;
};

/**
211
 * struct ti_clk_ll_ops - low-level ops for clocks
212 213
 * @clk_readl: pointer to register read function
 * @clk_writel: pointer to register write function
214 215
 * @clkdm_clk_enable: pointer to clockdomain enable function
 * @clkdm_clk_disable: pointer to clockdomain disable function
216
 * @clkdm_lookup: pointer to clockdomain lookup function
217 218
 * @cm_wait_module_ready: pointer to CM module wait ready function
 * @cm_split_idlest_reg: pointer to CM module function to split idlest reg
219
 *
220 221 222 223 224
 * Low-level ops are generally used by the basic clock types (clk-gate,
 * clk-mux, clk-divider etc.) to provide support for various low-level
 * hadrware interfaces (direct MMIO, regmap etc.), and is initialized
 * by board code. Low-level ops also contain some other platform specific
 * operations not provided directly by clock drivers.
225 226 227 228
 */
struct ti_clk_ll_ops {
	u32	(*clk_readl)(void __iomem *reg);
	void	(*clk_writel)(u32 val, void __iomem *reg);
229 230 231
	int	(*clkdm_clk_enable)(struct clockdomain *clkdm, struct clk *clk);
	int	(*clkdm_clk_disable)(struct clockdomain *clkdm,
				     struct clk *clk);
232
	struct clockdomain * (*clkdm_lookup)(const char *name);
233 234 235 236
	int	(*cm_wait_module_ready)(u8 part, s16 prcm_mod, u16 idlest_reg,
					u8 idlest_shift);
	int	(*cm_split_idlest_reg)(void __iomem *idlest_reg, s16 *prcm_inst,
				       u8 *idlest_reg_id);
237 238
};

T
Tero Kristo 已提交
239 240 241
#define to_clk_hw_omap(_hw) container_of(_hw, struct clk_hw_omap, hw)

void omap2_init_clk_clkdm(struct clk_hw *clk);
T
Tero Kristo 已提交
242
int omap2_clk_disable_autoidle_all(void);
243 244 245
int omap2_clk_enable_autoidle_all(void);
int omap2_clk_allow_idle(struct clk *clk);
int omap2_clk_deny_idle(struct clk *clk);
246 247 248 249 250
unsigned long omap2_dpllcore_recalc(struct clk_hw *hw,
				    unsigned long parent_rate);
int omap2_reprogram_dpllcore(struct clk_hw *clk, unsigned long rate,
			     unsigned long parent_rate);
void omap2xxx_clkt_dpllcore_init(struct clk_hw *hw);
251
void omap2xxx_clkt_vps_init(void);
252
unsigned long omap2_get_dpll_rate(struct clk_hw_omap *clk);
T
Tero Kristo 已提交
253

254
void ti_dt_clk_init_retry_clks(void);
255
void ti_dt_clockdomains_setup(void);
256
int ti_clk_setup_ll_ops(struct ti_clk_ll_ops *ops);
T
Tero Kristo 已提交
257

258 259 260 261 262 263
struct regmap;

int omap2_clk_provider_init(struct device_node *parent, int index,
			    struct regmap *syscon, void __iomem *mem);
void omap2_clk_legacy_provider_init(int index, void __iomem *mem);

T
Tero Kristo 已提交
264 265 266
int omap3430_dt_clk_init(void);
int omap3630_dt_clk_init(void);
int am35xx_dt_clk_init(void);
267 268
int dm814x_dt_clk_init(void);
int dm816x_dt_clk_init(void);
T
Tero Kristo 已提交
269
int omap4xxx_dt_clk_init(void);
T
Tero Kristo 已提交
270
int omap5xxx_dt_clk_init(void);
T
Tero Kristo 已提交
271
int dra7xx_dt_clk_init(void);
272
int am33xx_dt_clk_init(void);
273
int am43xx_dt_clk_init(void);
274 275
int omap2420_dt_clk_init(void);
int omap2430_dt_clk_init(void);
T
Tero Kristo 已提交
276

277 278 279 280 281 282 283 284 285 286 287 288
struct ti_clk_features {
	u32 flags;
	long fint_min;
	long fint_max;
	long fint_band1_max;
	long fint_band2_min;
	u8 dpll_bypass_vals;
	u8 cm_idlest_val;
};

#define TI_CLK_DPLL_HAS_FREQSEL			BIT(0)
#define TI_CLK_DPLL4_DENY_REPROGRAM		BIT(1)
289
#define TI_CLK_DISABLE_CLKDM_CONTROL		BIT(2)
290
#define TI_CLK_ERRATA_I810			BIT(3)
291 292 293 294

void ti_clk_setup_features(struct ti_clk_features *features);
const struct ti_clk_features *ti_clk_get_features(void);

295
extern const struct clk_hw_omap_ops clkhwops_omap2xxx_dpll;
T
Tero Kristo 已提交
296

297
#ifdef CONFIG_ATAGS
298 299 300 301
int omap3430_clk_legacy_init(void);
int omap3430es1_clk_legacy_init(void);
int omap36xx_clk_legacy_init(void);
int am35xx_clk_legacy_init(void);
302 303 304 305 306 307 308
#else
static inline int omap3430_clk_legacy_init(void) { return -ENXIO; }
static inline int omap3430es1_clk_legacy_init(void) { return -ENXIO; }
static inline int omap36xx_clk_legacy_init(void) { return -ENXIO; }
static inline int am35xx_clk_legacy_init(void) { return -ENXIO; }
#endif

309

310
#endif