karo: tx6: factor out PMIC initialization
[karo-tx-uboot.git] / board / karo / tx6 / ltc3676.c
1 /*
2  * Copyright (C) 2014 Lothar WaƟmann <LW@KARO-electronics.de>
3  *
4  * See file CREDITS for list of people who contributed to this
5  * project.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * version 2 as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  */
17
18 #include <common.h>
19 #include <i2c.h>
20 #include <asm/io.h>
21
22 #include "pmic.h"
23
24 #define LTC3676_BUCK1           0x01
25 #define LTC3676_BUCK2           0x02
26 #define LTC3676_BUCK3           0x03
27 #define LTC3676_BUCK4           0x04
28 #define LTC3676_DVB1A           0x0A
29 #define LTC3676_DVB1B           0x0B
30 #define LTC3676_DVB2A           0x0C
31 #define LTC3676_DVB2B           0x0D
32 #define LTC3676_DVB3A           0x0E
33 #define LTC3676_DVB3B           0x0F
34 #define LTC3676_DVB4A           0x10
35 #define LTC3676_DVB4B           0x11
36 #define LTC3676_MSKPG           0x13
37 #define LTC3676_CLIRQ           0x1f
38
39 #define LTC3676_BUCK_DVDT_FAST  (1 << 0)
40 #define LTC3676_BUCK_KEEP_ALIVE (1 << 1)
41 #define LTC3676_BUCK_CLK_RATE_LOW (1 << 2)
42 #define LTC3676_BUCK_PHASE_SEL  (1 << 3)
43 #define LTC3676_BUCK_ENABLE_300 (1 << 4)
44 #define LTC3676_BUCK_PULSE_SKIP (0 << 5)
45 #define LTC3676_BUCK_BURST_MODE (1 << 5)
46 #define LTC3676_BUCK_CONTINUOUS (2 << 5)
47 #define LTC3676_BUCK_ENABLE     (1 << 7)
48
49 #define LTC3676_PGOOD_MASK      (1 << 5)
50
51 #define LTC3676_MSKPG_BUCK1     (1 << 0)
52 #define LTC3676_MSKPG_BUCK2     (1 << 1)
53 #define LTC3676_MSKPG_BUCK3     (1 << 2)
54 #define LTC3676_MSKPG_BUCK4     (1 << 3)
55 #define LTC3676_MSKPG_LDO2      (1 << 5)
56 #define LTC3676_MSKPG_LDO3      (1 << 6)
57 #define LTC3676_MSKPG_LDO4      (1 << 7)
58
59 #define VDD_IO_VAL              mV_to_regval(vout_to_vref(3300 * 10, 5))
60 #define VDD_IO_VAL_LP           mV_to_regval(vout_to_vref(3100 * 10, 5))
61 #define VDD_IO_VAL_2            mV_to_regval(vout_to_vref(3300 * 10, 5_2))
62 #define VDD_IO_VAL_2_LP         mV_to_regval(vout_to_vref(3100 * 10, 5_2))
63 #define VDD_SOC_VAL             mV_to_regval(vout_to_vref(1425 * 10, 6))
64 #define VDD_SOC_VAL_LP          mV_to_regval(vout_to_vref(900 * 10, 6))
65 #define VDD_DDR_VAL             mV_to_regval(vout_to_vref(1500 * 10, 7))
66 #define VDD_DDR_VAL_LP          mV_to_regval(vout_to_vref(1500 * 10, 7))
67 #define VDD_CORE_VAL            mV_to_regval(vout_to_vref(1425 * 10, 8))
68 #define VDD_CORE_VAL_LP         mV_to_regval(vout_to_vref(900 * 10, 8))
69
70 /* LDO1 */
71 #define R1_1                    470
72 #define R2_1                    150
73 /* LDO4 */
74 #define R1_4                    470
75 #define R2_4                    150
76 /* Buck1 */
77 #define R1_5                    390
78 #define R2_5                    110
79 #define R1_5_2                  470
80 #define R2_5_2                  150
81 /* Buck2 (SOC) */
82 #define R1_6                    150
83 #define R2_6                    180
84 /* Buck3 (DDR) */
85 #define R1_7                    150
86 #define R2_7                    140
87 /* Buck4 (CORE) */
88 #define R1_8                    150
89 #define R2_8                    180
90
91 /* calculate voltages in 10mV */
92 #define R1(idx)                 R1_##idx
93 #define R2(idx)                 R2_##idx
94
95 #define vout_to_vref(vout, idx) ((vout) * R2(idx) / (R1(idx) + R2(idx)))
96 #define vref_to_vout(vref, idx) DIV_ROUND_UP((vref) * (R1(idx) + R2(idx)), R2(idx))
97
98 #define mV_to_regval(mV)        DIV_ROUND(((((mV) < 4125) ? 4125 : (mV)) - 4125), 125)
99 #define regval_to_mV(v)         (((v) * 125 + 4125))
100
101 static struct ltc3676_regs {
102         u8 addr;
103         u8 val;
104         u8 mask;
105 } ltc3676_regs[] = {
106         { LTC3676_MSKPG, ~LTC3676_MSKPG_BUCK1, },
107         { LTC3676_DVB2B, VDD_SOC_VAL_LP | LTC3676_PGOOD_MASK, ~0x3f, },
108         { LTC3676_DVB3B, VDD_DDR_VAL_LP, ~0x3f, },
109         { LTC3676_DVB4B, VDD_CORE_VAL_LP | LTC3676_PGOOD_MASK, ~0x3f, },
110         { LTC3676_DVB2A, VDD_SOC_VAL, ~0x3f, },
111         { LTC3676_DVB3A, VDD_DDR_VAL, ~0x3f, },
112         { LTC3676_DVB4A, VDD_CORE_VAL, ~0x3f, },
113         { LTC3676_BUCK1, LTC3676_BUCK_BURST_MODE | LTC3676_BUCK_CLK_RATE_LOW, },
114         { LTC3676_BUCK2, LTC3676_BUCK_BURST_MODE, },
115         { LTC3676_BUCK3, LTC3676_BUCK_BURST_MODE, },
116         { LTC3676_BUCK4, LTC3676_BUCK_BURST_MODE, },
117         { LTC3676_CLIRQ, 0, }, /* clear interrupt status */
118 };
119
120 static struct ltc3676_regs ltc3676_regs_1[] = {
121         { LTC3676_DVB1B, VDD_IO_VAL_LP | LTC3676_PGOOD_MASK, ~0x3f, },
122         { LTC3676_DVB1A, VDD_IO_VAL, ~0x3f, },
123 };
124
125 static struct ltc3676_regs ltc3676_regs_2[] = {
126         { LTC3676_DVB1B, VDD_IO_VAL_2_LP | LTC3676_PGOOD_MASK, ~0x3f, },
127         { LTC3676_DVB1A, VDD_IO_VAL_2, ~0x3f, },
128 };
129
130 static int tx6_rev_2(void)
131 {
132         struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
133         struct fuse_bank5_regs *fuse = (void *)ocotp->bank[5].fuse_regs;
134         u32 pad_settings = readl(&fuse->pad_settings);
135
136         debug("Fuse pad_settings @ %p = %02x\n",
137                 &fuse->pad_settings, pad_settings);
138         return pad_settings & 1;
139 }
140
141 static int ltc3676_setup_regs(struct ltc3676_regs *r, size_t count)
142 {
143         int ret;
144         int i;
145
146         for (i = 0; i < count; i++, r++) {
147 #ifdef DEBUG
148                 unsigned char value;
149
150                 ret = i2c_read(CONFIG_SYS_I2C_SLAVE, r->addr, 1, &value, 1);
151                 if ((value & ~r->mask) != r->val) {
152                         printf("Changing PMIC reg %02x from %02x to %02x\n",
153                                 r->addr, value, r->val);
154                 }
155                 if (ret) {
156                         printf("%s: failed to read PMIC register %02x: %d\n",
157                                 __func__, r->addr, ret);
158                         return ret;
159                 }
160 #endif
161                 ret = i2c_write(CONFIG_SYS_I2C_SLAVE,
162                                 r->addr, 1, &r->val, 1);
163                 if (ret) {
164                         printf("%s: failed to write PMIC register %02x: %d\n",
165                                 __func__, r->addr, ret);
166                         return ret;
167                 }
168         }
169         return 0;
170 }
171
172 int setup_pmic_voltages(void)
173 {
174         int ret;
175         unsigned char value;
176
177         ret = i2c_probe(CONFIG_SYS_I2C_SLAVE);
178         if (ret != 0) {
179                 printf("Failed to initialize I2C\n");
180                 return ret;
181         }
182
183         ret = i2c_read(CONFIG_SYS_I2C_SLAVE, 0x11, 1, &value, 1);
184         if (ret) {
185                 printf("%s: i2c_read error: %d\n", __func__, ret);
186                 return ret;
187         }
188
189         ret = ltc3676_setup_regs(ltc3676_regs, ARRAY_SIZE(ltc3676_regs));
190         if (ret)
191                 return ret;
192
193         printf("VDDCORE set to %umV\n",
194                 DIV_ROUND(vref_to_vout(regval_to_mV(VDD_CORE_VAL), 8), 10));
195         printf("VDDSOC  set to %umV\n",
196                 DIV_ROUND(vref_to_vout(regval_to_mV(VDD_SOC_VAL), 6), 10));
197
198         if (tx6_rev_2()) {
199                 ret = ltc3676_setup_regs(ltc3676_regs_2,
200                                 ARRAY_SIZE(ltc3676_regs_2));
201                 printf("VDDIO   set to %umV\n",
202                         DIV_ROUND(vref_to_vout(
203                                         regval_to_mV(VDD_IO_VAL_2), 5_2), 10));
204         } else {
205                 ret = ltc3676_setup_regs(ltc3676_regs_1,
206                                 ARRAY_SIZE(ltc3676_regs_1));
207         }
208         return ret;
209 }