clk-iproc.h 5.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
/*
 * Copyright (C) 2014 Broadcom Corporation
 *
 * 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 version 2.
 *
 * 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 _CLK_IPROC_H
#define _CLK_IPROC_H

#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/of.h>
#include <linux/clk-provider.h>

#define IPROC_CLK_NAME_LEN 25
#define IPROC_CLK_INVALID_OFFSET 0xffffffff
#define bit_mask(width) ((1 << (width)) - 1)

/* clocks that should not be disabled at runtime */
#define IPROC_CLK_AON BIT(0)

/* PLL that requires gating through ASIU */
#define IPROC_CLK_PLL_ASIU BIT(1)

/* PLL that has fractional part of the NDIV */
#define IPROC_CLK_PLL_HAS_NDIV_FRAC BIT(2)

/*
 * Some of the iProc PLL/clocks may have an ASIC bug that requires read back
 * of the same register following the write to flush the write transaction into
 * the intended register
 */
#define IPROC_CLK_NEEDS_READ_BACK BIT(3)

/*
 * Some PLLs require the PLL SW override bit to be set before changes can be
 * applied to the PLL
 */
#define IPROC_CLK_PLL_NEEDS_SW_CFG BIT(4)

J
Jon Mason 已提交
51 52 53 54 55 56
/*
 * Some PLLs use a different way to control clock power, via the PWRDWN bit in
 * the PLL control register
 */
#define IPROC_CLK_EMBED_PWRCTRL BIT(5)

57 58 59 60 61 62
/*
 * Some PLLs have separate registers for Status and Control.  Identify this to
 * let the driver know if additional registers need to be used
 */
#define IPROC_CLK_PLL_SPLIT_STAT_CTRL BIT(6)

63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
/*
 * Some PLLs have an additional divide by 2 in master clock calculation;
 * MCLK = VCO_freq / (Mdiv * 2). Identify this to let the driver know
 * of modified calculations
 */
#define IPROC_CLK_MCLK_DIV_BY_2 BIT(7)

/*
 * Some PLLs provide a look up table for the leaf clock frequencies and
 * auto calculates VCO frequency parameters based on the provided leaf
 * clock frequencies. They have a user mode that allows the divider
 * controls to be determined by the user
 */
#define IPROC_CLK_PLL_USER_MODE_ON BIT(8)

/*
 * Some PLLs have an active low reset
 */
#define IPROC_CLK_PLL_RESET_ACTIVE_LOW BIT(9)

83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
/*
 * Parameters for VCO frequency configuration
 *
 * VCO frequency =
 * ((ndiv_int + ndiv_frac / 2^20) * (ref freqeuncy  / pdiv)
 */
struct iproc_pll_vco_param {
	unsigned long rate;
	unsigned int ndiv_int;
	unsigned int ndiv_frac;
	unsigned int pdiv;
};

struct iproc_clk_reg_op {
	unsigned int offset;
	unsigned int shift;
	unsigned int width;
};

/*
 * Clock gating control at the top ASIU level
 */
struct iproc_asiu_gate {
	unsigned int offset;
	unsigned int en_shift;
};

/*
 * Control of powering on/off of a PLL
 *
 * Before powering off a PLL, input isolation (ISO) needs to be enabled
 */
struct iproc_pll_aon_pwr_ctrl {
	unsigned int offset;
	unsigned int pwr_width;
	unsigned int pwr_shift;
	unsigned int iso_shift;
};

/*
J
Jon Mason 已提交
123
 * Control of the PLL reset
124 125 126 127 128
 */
struct iproc_pll_reset_ctrl {
	unsigned int offset;
	unsigned int reset_shift;
	unsigned int p_reset_shift;
J
Jon Mason 已提交
129 130 131 132 133 134 135
};

/*
 * Control of the Ki, Kp, and Ka parameters
 */
struct iproc_pll_dig_filter_ctrl {
	unsigned int offset;
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
	unsigned int ki_shift;
	unsigned int ki_width;
	unsigned int kp_shift;
	unsigned int kp_width;
	unsigned int ka_shift;
	unsigned int ka_width;
};

/*
 * To enable SW control of the PLL
 */
struct iproc_pll_sw_ctrl {
	unsigned int offset;
	unsigned int shift;
};

struct iproc_pll_vco_ctrl {
	unsigned int u_offset;
	unsigned int l_offset;
};

/*
 * Main PLL control parameters
 */
struct iproc_pll_ctrl {
	unsigned long flags;
	struct iproc_pll_aon_pwr_ctrl aon;
	struct iproc_asiu_gate asiu;
	struct iproc_pll_reset_ctrl reset;
J
Jon Mason 已提交
165
	struct iproc_pll_dig_filter_ctrl dig_filter;
166 167 168 169 170 171
	struct iproc_pll_sw_ctrl sw_ctrl;
	struct iproc_clk_reg_op ndiv_int;
	struct iproc_clk_reg_op ndiv_frac;
	struct iproc_clk_reg_op pdiv;
	struct iproc_pll_vco_ctrl vco_ctrl;
	struct iproc_clk_reg_op status;
172
	struct iproc_clk_reg_op macro_mode;
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
};

/*
 * Controls enabling/disabling a PLL derived clock
 */
struct iproc_clk_enable_ctrl {
	unsigned int offset;
	unsigned int enable_shift;
	unsigned int hold_shift;
	unsigned int bypass_shift;
};

/*
 * Main clock control parameters for clocks derived from the PLLs
 */
struct iproc_clk_ctrl {
	unsigned int channel;
	unsigned long flags;
	struct iproc_clk_enable_ctrl enable;
	struct iproc_clk_reg_op mdiv;
};

/*
 * Divisor of the ASIU clocks
 */
struct iproc_asiu_div {
	unsigned int offset;
	unsigned int en_shift;
	unsigned int high_shift;
	unsigned int high_width;
	unsigned int low_shift;
	unsigned int low_width;
};

R
Ray Jui 已提交
207 208 209 210 211 212 213 214 215 216 217
void iproc_armpll_setup(struct device_node *node);
void iproc_pll_clk_setup(struct device_node *node,
			 const struct iproc_pll_ctrl *pll_ctrl,
			 const struct iproc_pll_vco_param *vco,
			 unsigned int num_vco_entries,
			 const struct iproc_clk_ctrl *clk_ctrl,
			 unsigned int num_clks);
void iproc_asiu_setup(struct device_node *node,
		      const struct iproc_asiu_div *div,
		      const struct iproc_asiu_gate *gate,
		      unsigned int num_clks);
218 219

#endif /* _CLK_IPROC_H */