1 /* Driver for Calypso clock management */
3 /* (C) 2010 by Harald Welte <laforge@gnumonks.org>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
30 #include <calypso/clock.h>
32 #define REG_DPLL 0xffff9800
33 #define DPLL_LOCK (1 << 0)
34 #define DPLL_BREAKLN (1 << 1)
35 #define DPLL_BYPASS_DIV_SHIFT 2 /* 2 bits */
36 #define DPLL_PLL_ENABLE (1 << 4)
37 #define DPLL_PLL_DIV_SHIFT 5 /* 2 bits */
38 #define DPLL_PLL_MULT_SHIFT 7 /* 5 bits */
39 #define DPLL_TEST (1 << 12)
40 #define DPLL_IOB (1 << 13) /* Initialize on break */
41 #define DPLL_IAI (1 << 14) /* Initialize after Idle */
43 #define BASE_ADDR_CLKM 0xfffffd00
44 #define CLKM_REG(m) (BASE_ADDR_CLKM+(m))
54 #define ARM_CLK_BIG_SLEEP (1 << 0) /* MCU Master Clock enabled? */
55 #define ARM_CLK_CLKIN_SEL0 (1 << 1) /* MCU source clock (0 = DPLL output, 1 = VTCXO or CLKIN */
56 #define ARM_CLK_CLKIN_SEL (1 << 2) /* 0 = VTCXO or 1 = CLKIN */
57 #define ARM_CLK_MCLK_DIV5 (1 << 3) /* enable 1.5 or 2.5 division factor */
58 #define ARM_CLK_MCLK_DIV_SHIFT 4 /* 3 bits */
59 #define ARM_CLK_DEEP_POWER_SHIFT 8
60 #define ARM_CLK_DEEP_SLEEP 12
63 #define CLK_IRQ_CLK_DIS (1 << 0) /* IRQ clock control (0 always, 1 according ARM_MCLK_EN) */
64 #define CLK_BRIDGE_CLK_DIS (1 << 1)
65 #define CLK_TIMER_CLK_DIS (1 << 2)
66 #define CLK_DPLL_DIS (1 << 3) /* 0: DPLL is not stopped during SLEEP */
67 #define CLK_CLKOUT_EN (1 << 4) /* Enable CLKOUT output pins */
68 #define CLK_EN_IDLE3_FLG (1 << 5) /* DSP idle flag control (1 =
69 * SAM/HOM register forced to HOM when DSP IDLE3) */
70 #define CLK_VCLKOUT_DIV2 (1 << 6) /* 1: VCLKOUT-FR is divided by 2 */
71 #define CLK_VTCXO_DIV2 (1 << 7) /* 1: VTCXO is dividied by 2 */
73 #define BASE_ADDR_MEMIF 0xfffffb00
74 #define MEMIF_REG(x) (BASE_ADDR_MEMIF+(x))
81 static void dump_reg16(uint32_t addr
, char *name
)
83 printf("%s=0x%04x\n", name
, readw(addr
));
86 void calypso_clk_dump(void)
88 dump_reg16(REG_DPLL
, "REG_DPLL");
89 dump_reg16(CLKM_REG(CNTL_ARM_CLK
), "CNTL_ARM_CLK");
90 dump_reg16(CLKM_REG(CNTL_CLK
), "CNTL_CLK");
91 dump_reg16(CLKM_REG(CNTL_RST
), "CNTL_RST");
92 dump_reg16(CLKM_REG(CNTL_ARM_DIV
), "CNTL_ARM_DIV");
95 void calypso_pll_set(uint16_t inp
)
97 uint8_t mult
= inp
>> 8;
98 uint8_t div
= inp
& 0xff;
99 uint16_t reg
= readw(REG_DPLL
);
102 reg
|= (div
& 0x3) << DPLL_PLL_DIV_SHIFT
;
103 reg
|= (mult
& 0x1f) << DPLL_PLL_MULT_SHIFT
;
104 reg
|= DPLL_PLL_ENABLE
;
106 writew(reg
, REG_DPLL
);
109 void calypso_reset_set(enum calypso_rst calypso_rst
, int active
)
111 uint8_t reg
= readb(CLKM_REG(CNTL_RST
));
118 writeb(reg
, CLKM_REG(CNTL_RST
));
121 int calypso_reset_get(enum calypso_rst calypso_rst
)
123 uint8_t reg
= readb(CLKM_REG(CNTL_RST
));
125 if (reg
& calypso_rst
)
131 void calypso_clock_set(uint8_t vtcxo_div2
, uint16_t inp
, enum mclk_div mclk_div
)
133 uint16_t cntl_clock
= readw(CLKM_REG(CNTL_CLK
));
134 uint16_t cntl_arm_clk
= readw(CLKM_REG(CNTL_ARM_CLK
));
136 /* First set the vtcxo_div2 */
137 cntl_clock
&= ~CLK_VCLKOUT_DIV2
;
139 cntl_clock
|= CLK_VTCXO_DIV2
;
141 cntl_clock
&= ~CLK_VTCXO_DIV2
;
142 writew(cntl_clock
, CLKM_REG(CNTL_CLK
));
144 /* Then configure the MCLK divider */
145 cntl_arm_clk
&= ~ARM_CLK_CLKIN_SEL0
;
146 if (mclk_div
& 0x80) {
148 cntl_arm_clk
|= ARM_CLK_MCLK_DIV5
;
150 cntl_arm_clk
&= ~ARM_CLK_MCLK_DIV5
;
151 cntl_arm_clk
&= ~(0x7 << ARM_CLK_MCLK_DIV_SHIFT
);
152 cntl_arm_clk
|= (mclk_div
<< ARM_CLK_MCLK_DIV_SHIFT
);
153 writew(cntl_arm_clk
, CLKM_REG(CNTL_ARM_CLK
));
155 /* Then finally set the PLL */
156 calypso_pll_set(inp
);
159 void calypso_mem_cfg(enum calypso_bank bank
, uint8_t ws
,
160 enum calypso_mem_width width
, int we
)
162 writew((ws
& 0x1f) | ((width
& 3) << 5) | ((we
& 1) << 7),
163 BASE_ADDR_MEMIF
+ bank
);
166 void calypso_bootrom(int enable
)
168 uint16_t conf
= readw(MEMIF_REG(EXTRA_CONF
));
175 writew(conf
, MEMIF_REG(EXTRA_CONF
));
178 void calypso_debugunit(int enable
)
180 uint16_t conf
= readw(MEMIF_REG(EXTRA_CONF
));
187 writew(conf
, MEMIF_REG(EXTRA_CONF
));
190 #define REG_RHEA_CNTL 0xfffff900
191 #define REG_API_CNTL 0xfffff902
192 #define REG_ARM_RHEA 0xfffff904
194 void calypso_rhea_cfg(uint8_t fac0
, uint8_t fac1
, uint8_t timeout
,
195 uint8_t ws_h
, uint8_t ws_l
, uint8_t w_en0
, uint8_t w_en1
)
197 writew(fac0
| (fac1
<< 4) | (timeout
<< 8), REG_RHEA_CNTL
);
198 writew(ws_h
| (ws_l
<< 5), REG_API_CNTL
);
199 writew(w_en0
| (w_en1
<< 1), REG_ARM_RHEA
);