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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
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
123
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
|
/*
* Copyright (C) 2014 Lothar Waßmann <LW@KARO-electronics.de>
*
* See file CREDITS for list of people who contributed to this
* project.
*
* 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 in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <common.h>
#include <i2c/i2c.h>
#include "pmic.h"
#define RN5T618_NOETIMSET 0x11
#define RN5T618_LDORTC1_SLOT 0x2a
#define RN5T618_DC1CTL 0x2c
#define RN5T618_DC1CTL2 0x2d
#define RN5T618_DC2CTL 0x2e
#define RN5T618_DC2CTL2 0x2f
#define RN5T618_DC3CTL 0x30
#define RN5T618_DC3CTL2 0x31
#define RN5T618_DC1DAC 0x36 /* CORE */
#define RN5T618_DC2DAC 0x37 /* SOC */
#define RN5T618_DC3DAC 0x38 /* DDR */
#define RN5T618_DC1DAC_SLP 0x3b
#define RN5T618_DC2DAC_SLP 0x3c
#define RN5T618_DC3DAC_SLP 0x3d
#define RN5T618_LDOEN1 0x44
#define RN5T618_LDODIS 0x46
#define RN5T618_LDOEN2 0x48
#define RN5T618_LDO3DAC 0x4e /* IO */
#define RN5T618_LDORTCDAC 0x56 /* VBACKUP */
#define VDD_RTC_VAL mV_to_regval_rtc(3000)
#define VDD_HIGH_VAL mV_to_regval3(3000)
#define VDD_HIGH_VAL_LP mV_to_regval3(3000)
#define VDD_CORE_VAL mV_to_regval(1425) /* DCDC1 */
#define VDD_CORE_VAL_LP mV_to_regval(900)
#define VDD_SOC_VAL mV_to_regval(1425) /* DCDC2 */
#define VDD_SOC_VAL_LP mV_to_regval(900)
#define VDD_DDR_VAL mV_to_regval(1500) /* DCDC3 */
#define VDD_DDR_VAL_LP mV_to_regval(1500)
/* calculate voltages in 10mV */
#define v2r(v,n,m) DIV_ROUND(((((v) < (n)) ? (n) : (v)) - (n)), (m))
#define r2v(r,n,m) (((r) * (m) + (n)) / 10)
/* DCDC1-3 */
#define mV_to_regval(mV) v2r((mV) * 10, 6000, 125)
#define regval_to_mV(r) r2v(r, 6000, 125)
/* LDO1-2 */
#define mV_to_regval2(mV) v2r((mV) * 10, 9000, 250)
#define regval2_to_mV(r) r2v(r, 9000, 250)
/* LDO3 */
#define mV_to_regval3(mV) v2r((mV) * 10, 6000, 250)
#define regval3_to_mV(r) r2v(r, 6000, 250)
/* LDORTC */
#define mV_to_regval_rtc(mV) v2r((mV) * 10, 17000, 250)
#define regval_rtc_to_mV(r) r2v(r, 17000, 250)
static struct rn5t618_regs {
u8 addr;
u8 val;
u8 mask;
} rn5t618_regs[] = {
{ RN5T618_NOETIMSET, 0, },
{ RN5T618_DC1DAC, VDD_CORE_VAL, },
{ RN5T618_DC2DAC, VDD_SOC_VAL, },
{ RN5T618_DC3DAC, VDD_DDR_VAL, },
{ RN5T618_DC1DAC_SLP, VDD_CORE_VAL_LP, },
{ RN5T618_DC2DAC_SLP, VDD_SOC_VAL_LP, },
{ RN5T618_DC3DAC_SLP, VDD_DDR_VAL_LP, },
{ RN5T618_LDOEN1, 0x01f, ~0x1f, },
{ RN5T618_LDOEN2, 0x10, ~0x30, },
{ RN5T618_LDODIS, 0x00, },
{ RN5T618_LDO3DAC, VDD_HIGH_VAL, },
{ RN5T618_LDORTCDAC, VDD_RTC_VAL, },
{ RN5T618_LDORTC1_SLOT, 0x0f, ~0x3f, },
};
static int rn5t618_setup_regs(struct i2c_client *client, struct rn5t618_regs *r,
size_t count)
{
int ret;
int i;
for (i = 0; i < count; i++, r++) {
#ifdef DEBUG
unsigned char value;
ret = i2c_read_reg(client, r->addr, &value, 1);
if ((value & ~r->mask) != r->val) {
pr_debug("Changing PMIC reg %02x from %02x to %02x\n",
r->addr, value, r->val);
}
if (ret != 1) {
pr_debug("%s: failed to read PMIC register %02x: %d\n",
__func__, r->addr, ret);
return ret;
}
#endif
ret = i2c_write_reg(client, r->addr, &r->val, 1);
if (ret != 1) {
pr_err("%s: failed to write PMIC register %02x: %d\n",
__func__, r->addr, ret);
return ret;
}
}
return 0;
}
int rn5t618_pmic_setup(struct i2c_client *client)
{
int ret;
unsigned char value;
ret = i2c_read_reg(client, 0x11, &value, 1);
if (ret) {
pr_err("i2c read error\n");
return ret;
}
ret = rn5t618_setup_regs(client, rn5t618_regs,
ARRAY_SIZE(rn5t618_regs));
if (ret)
return ret;
ret = i2c_read_reg(client, RN5T618_DC1DAC, &value, 1);
if (ret == 1) {
pr_debug("VDDCORE set to %umV\n", regval_to_mV(value));
} else {
pr_err("i2c read error\n");
return ret;
}
ret = i2c_read_reg(client, RN5T618_DC2DAC, &value, 1);
if (ret == 1) {
pr_debug("VDDSOC set to %umV\n", regval_to_mV(value));
} else {
pr_err("i2c read error\n");
return ret;
}
return 0;
}
|