]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/arm/cpu/armv7/omap-common/abb.c
Merge branch 'master' of git://git.denx.de/u-boot-arm
[karo-tx-uboot.git] / arch / arm / cpu / armv7 / omap-common / abb.c
1 /*
2  *
3  * Adaptive Body Bias programming sequence for OMAP family
4  *
5  * (C) Copyright 2013
6  * Texas Instruments, <www.ti.com>
7  *
8  * Andrii Tseglytskyi <andrii.tseglytskyi@ti.com>
9  *
10  * See file CREDITS for list of people who contributed to this
11  * project.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License as
15  * published by the Free Software Foundation; either version 2 of
16  * the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
26  * MA 02111-1307 USA
27  */
28
29 #include <common.h>
30 #include <asm/omap_common.h>
31 #include <asm/io.h>
32 #include <asm/arch/sys_proto.h>
33
34 __weak s8 abb_setup_ldovbb(u32 fuse, u32 ldovbb)
35 {
36         return -1;
37 }
38
39 static void abb_setup_timings(u32 setup)
40 {
41         u32 sys_rate, sr2_cnt, clk_cycles;
42
43         /*
44          * SR2_WTCNT_VALUE is the settling time for the ABB ldo after a
45          * transition and must be programmed with the correct time at boot.
46          * The value programmed into the register is the number of SYS_CLK
47          * clock cycles that match a given wall time profiled for the ldo.
48          * This value depends on:
49          * settling time of ldo in micro-seconds (varies per OMAP family),
50          * of clock cycles per SYS_CLK period (varies per OMAP family),
51          * the SYS_CLK frequency in MHz (varies per board)
52          * The formula is:
53          *
54          *                     ldo settling time (in micro-seconds)
55          * SR2_WTCNT_VALUE = ------------------------------------------
56          *                  (# system clock cycles) * (sys_clk period)
57          *
58          * Put another way:
59          *
60          * SR2_WTCNT_VALUE = settling time / (# SYS_CLK cycles / SYS_CLK rate))
61          *
62          * To avoid dividing by zero multiply both "# clock cycles" and
63          * "settling time" by 10 such that the final result is the one we want.
64          */
65
66         /* calculate SR2_WTCNT_VALUE */
67         sys_rate = DIV_ROUND(V_OSCK, 1000000);
68         clk_cycles = DIV_ROUND(OMAP_ABB_CLOCK_CYCLES * 10, sys_rate);
69         sr2_cnt = DIV_ROUND(OMAP_ABB_SETTLING_TIME * 10, clk_cycles);
70
71         setbits_le32(setup,
72                      sr2_cnt << (ffs(OMAP_ABB_SETUP_SR2_WTCNT_VALUE_MASK) - 1));
73 }
74
75 void abb_setup(u32 fuse, u32 ldovbb, u32 setup, u32 control,
76                u32 txdone, u32 txdone_mask, u32 opp)
77 {
78         u32 abb_type_mask, opp_sel_mask;
79
80         /* sanity check */
81         if (!setup || !control || !txdone)
82                 return;
83
84         /* setup ABB only in case of Fast or Slow OPP */
85         switch (opp) {
86         case OMAP_ABB_FAST_OPP:
87                 abb_type_mask = OMAP_ABB_SETUP_ACTIVE_FBB_SEL_MASK;
88                 opp_sel_mask = OMAP_ABB_CONTROL_FAST_OPP_SEL_MASK;
89                 break;
90         case OMAP_ABB_SLOW_OPP:
91                 abb_type_mask = OMAP_ABB_SETUP_ACTIVE_RBB_SEL_MASK;
92                 opp_sel_mask = OMAP_ABB_CONTROL_SLOW_OPP_SEL_MASK;
93                 break;
94         default:
95                return;
96         }
97
98         /*
99          * For some OMAP silicons additional setup for LDOVBB register is
100          * required. This is determined by data retrieved from corresponding
101          * OPP EFUSE register. Data, which is retrieved from EFUSE - is
102          * ABB enable/disable flag and VSET value, which must be copied
103          * to LDOVBB register. If function call fails - return quietly,
104          * it means no ABB is required for such silicon.
105          *
106          * For silicons, which don't require LDOVBB setup "fuse" and
107          * "ldovbb" offsets are not defined. ABB will be initialized in
108          * the common way for them.
109          */
110         if (fuse && ldovbb) {
111                 if (abb_setup_ldovbb(fuse, ldovbb))
112                         return;
113         }
114
115         /* clear ABB registers */
116         writel(0, setup);
117         writel(0, control);
118
119         /* configure timings, based on oscillator value */
120         abb_setup_timings(setup);
121
122         /* clear pending interrupts before setup */
123         setbits_le32(txdone, txdone_mask);
124
125         /* select ABB type */
126         setbits_le32(setup, abb_type_mask | OMAP_ABB_SETUP_SR2EN_MASK);
127
128         /* initiate ABB ldo change */
129         setbits_le32(control, opp_sel_mask | OMAP_ABB_CONTROL_OPP_CHANGE_MASK);
130
131         /* wait until transition complete */
132         if (!wait_on_value(txdone_mask, txdone_mask, (void *)txdone, LDELAY))
133                 puts("Error: ABB txdone is not set\n");
134
135         /* clear ABB tranxdone */
136         setbits_le32(txdone, txdone_mask);
137 }