Commit fff45ce7e753cece9e205d2d32ec7deb1db743b8
Committed by
Lokesh Vutla
1 parent
6f3f23b509
Exists in
v2017.01-smarct4x
and in
2 other branches
power: pmic: tps65218: Fix tps65218_voltage_update function
commit 6183b29559107650cb38f905e069a93ff9da1d7d upstream Currently while setting the vsel value for dcdc1 and dcdc2 the driver is wrongly masking the entire 8 bits in the process clearing PFM (bit7) field as well. Hence describe an appropriate mask for vsel field and modify only those bits in the vsel mask. Source: http://www.ti.com/lit/ds/symlink/tps65218.pdf Signed-off-by: Keerthy <j-keerthy@ti.com> Fixes: 86db550b38 ("power: Add support for the TPS65218 PMIC") Reviewed-by: Jaehoon Chung <jh80.chung@samsung.com>
Showing 2 changed files with 3 additions and 1 deletions Inline Diff
drivers/power/pmic/pmic_tps65218.c
1 | /* | 1 | /* |
2 | * (C) Copyright 2011-2013 | 2 | * (C) Copyright 2011-2013 |
3 | * Texas Instruments, <www.ti.com> | 3 | * Texas Instruments, <www.ti.com> |
4 | * | 4 | * |
5 | * SPDX-License-Identifier: GPL-2.0+ | 5 | * SPDX-License-Identifier: GPL-2.0+ |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #include <common.h> | 8 | #include <common.h> |
9 | #include <i2c.h> | 9 | #include <i2c.h> |
10 | #include <linux/errno.h> | 10 | #include <linux/errno.h> |
11 | #include <power/pmic.h> | 11 | #include <power/pmic.h> |
12 | #include <power/tps65218.h> | 12 | #include <power/tps65218.h> |
13 | 13 | ||
14 | int tps65218_reg_read(uchar dest_reg, uchar *dest_val) | 14 | int tps65218_reg_read(uchar dest_reg, uchar *dest_val) |
15 | { | 15 | { |
16 | uchar read_val; | 16 | uchar read_val; |
17 | int ret; | 17 | int ret; |
18 | 18 | ||
19 | ret = i2c_read(TPS65218_CHIP_PM, dest_reg, 1, &read_val, 1); | 19 | ret = i2c_read(TPS65218_CHIP_PM, dest_reg, 1, &read_val, 1); |
20 | if (ret) | 20 | if (ret) |
21 | return ret; | 21 | return ret; |
22 | 22 | ||
23 | *dest_val = read_val; | 23 | *dest_val = read_val; |
24 | 24 | ||
25 | return 0; | 25 | return 0; |
26 | } | 26 | } |
27 | 27 | ||
28 | /** | 28 | /** |
29 | * tps65218_reg_write() - Generic function that can write a TPS65218 PMIC | 29 | * tps65218_reg_write() - Generic function that can write a TPS65218 PMIC |
30 | * register or bit field regardless of protection | 30 | * register or bit field regardless of protection |
31 | * level. | 31 | * level. |
32 | * | 32 | * |
33 | * @prot_level: Register password protection. Use | 33 | * @prot_level: Register password protection. Use |
34 | * TPS65218_PROT_LEVEL_NONE, | 34 | * TPS65218_PROT_LEVEL_NONE, |
35 | * TPS65218_PROT_LEVEL_1 or TPS65218_PROT_LEVEL_2 | 35 | * TPS65218_PROT_LEVEL_1 or TPS65218_PROT_LEVEL_2 |
36 | * @dest_reg: Register address to write. | 36 | * @dest_reg: Register address to write. |
37 | * @dest_val: Value to write. | 37 | * @dest_val: Value to write. |
38 | * @mask: Bit mask (8 bits) to be applied. Function will only | 38 | * @mask: Bit mask (8 bits) to be applied. Function will only |
39 | * change bits that are set in the bit mask. | 39 | * change bits that are set in the bit mask. |
40 | * | 40 | * |
41 | * @return: 0 for success, not 0 on failure, as per the i2c API | 41 | * @return: 0 for success, not 0 on failure, as per the i2c API |
42 | */ | 42 | */ |
43 | int tps65218_reg_write(uchar prot_level, uchar dest_reg, uchar dest_val, | 43 | int tps65218_reg_write(uchar prot_level, uchar dest_reg, uchar dest_val, |
44 | uchar mask) | 44 | uchar mask) |
45 | { | 45 | { |
46 | uchar read_val; | 46 | uchar read_val; |
47 | uchar xor_reg; | 47 | uchar xor_reg; |
48 | int ret; | 48 | int ret; |
49 | 49 | ||
50 | /* | 50 | /* |
51 | * If we are affecting only a bit field, read dest_reg and apply the | 51 | * If we are affecting only a bit field, read dest_reg and apply the |
52 | * mask | 52 | * mask |
53 | */ | 53 | */ |
54 | if (mask != TPS65218_MASK_ALL_BITS) { | 54 | if (mask != TPS65218_MASK_ALL_BITS) { |
55 | ret = i2c_read(TPS65218_CHIP_PM, dest_reg, 1, &read_val, 1); | 55 | ret = i2c_read(TPS65218_CHIP_PM, dest_reg, 1, &read_val, 1); |
56 | if (ret) | 56 | if (ret) |
57 | return ret; | 57 | return ret; |
58 | read_val &= (~mask); | 58 | read_val &= (~mask); |
59 | read_val |= (dest_val & mask); | 59 | read_val |= (dest_val & mask); |
60 | dest_val = read_val; | 60 | dest_val = read_val; |
61 | } | 61 | } |
62 | 62 | ||
63 | if (prot_level > 0) { | 63 | if (prot_level > 0) { |
64 | xor_reg = dest_reg ^ TPS65218_PASSWORD_UNLOCK; | 64 | xor_reg = dest_reg ^ TPS65218_PASSWORD_UNLOCK; |
65 | ret = i2c_write(TPS65218_CHIP_PM, TPS65218_PASSWORD, 1, | 65 | ret = i2c_write(TPS65218_CHIP_PM, TPS65218_PASSWORD, 1, |
66 | &xor_reg, 1); | 66 | &xor_reg, 1); |
67 | if (ret) | 67 | if (ret) |
68 | return ret; | 68 | return ret; |
69 | } | 69 | } |
70 | 70 | ||
71 | ret = i2c_write(TPS65218_CHIP_PM, dest_reg, 1, &dest_val, 1); | 71 | ret = i2c_write(TPS65218_CHIP_PM, dest_reg, 1, &dest_val, 1); |
72 | if (ret) | 72 | if (ret) |
73 | return ret; | 73 | return ret; |
74 | 74 | ||
75 | if (prot_level == TPS65218_PROT_LEVEL_2) { | 75 | if (prot_level == TPS65218_PROT_LEVEL_2) { |
76 | ret = i2c_write(TPS65218_CHIP_PM, TPS65218_PASSWORD, 1, | 76 | ret = i2c_write(TPS65218_CHIP_PM, TPS65218_PASSWORD, 1, |
77 | &xor_reg, 1); | 77 | &xor_reg, 1); |
78 | if (ret) | 78 | if (ret) |
79 | return ret; | 79 | return ret; |
80 | 80 | ||
81 | ret = i2c_write(TPS65218_CHIP_PM, dest_reg, 1, &dest_val, 1); | 81 | ret = i2c_write(TPS65218_CHIP_PM, dest_reg, 1, &dest_val, 1); |
82 | if (ret) | 82 | if (ret) |
83 | return ret; | 83 | return ret; |
84 | } | 84 | } |
85 | 85 | ||
86 | return 0; | 86 | return 0; |
87 | } | 87 | } |
88 | 88 | ||
89 | /** | 89 | /** |
90 | * tps65218_voltage_update() - Function to change a voltage level, as this | 90 | * tps65218_voltage_update() - Function to change a voltage level, as this |
91 | * is a multi-step process. | 91 | * is a multi-step process. |
92 | * @dc_cntrl_reg: DC voltage control register to change. | 92 | * @dc_cntrl_reg: DC voltage control register to change. |
93 | * @volt_sel: New value for the voltage register | 93 | * @volt_sel: New value for the voltage register |
94 | * @return: 0 for success, not 0 on failure. | 94 | * @return: 0 for success, not 0 on failure. |
95 | */ | 95 | */ |
96 | int tps65218_voltage_update(uchar dc_cntrl_reg, uchar volt_sel) | 96 | int tps65218_voltage_update(uchar dc_cntrl_reg, uchar volt_sel) |
97 | { | 97 | { |
98 | if ((dc_cntrl_reg != TPS65218_DCDC1) && | 98 | if ((dc_cntrl_reg != TPS65218_DCDC1) && |
99 | (dc_cntrl_reg != TPS65218_DCDC2) && | 99 | (dc_cntrl_reg != TPS65218_DCDC2) && |
100 | (dc_cntrl_reg != TPS65218_DCDC3)) | 100 | (dc_cntrl_reg != TPS65218_DCDC3)) |
101 | return 1; | 101 | return 1; |
102 | 102 | ||
103 | /* set voltage level */ | 103 | /* set voltage level */ |
104 | if (tps65218_reg_write(TPS65218_PROT_LEVEL_2, dc_cntrl_reg, volt_sel, | 104 | if (tps65218_reg_write(TPS65218_PROT_LEVEL_2, dc_cntrl_reg, volt_sel, |
105 | TPS65218_MASK_ALL_BITS)) | 105 | TPS65218_DCDC_VSEL_MASK)) |
106 | return 1; | 106 | return 1; |
107 | 107 | ||
108 | /* set GO bit to initiate voltage transition */ | 108 | /* set GO bit to initiate voltage transition */ |
109 | if (tps65218_reg_write(TPS65218_PROT_LEVEL_2, TPS65218_SLEW, | 109 | if (tps65218_reg_write(TPS65218_PROT_LEVEL_2, TPS65218_SLEW, |
110 | TPS65218_DCDC_GO, TPS65218_DCDC_GO)) | 110 | TPS65218_DCDC_GO, TPS65218_DCDC_GO)) |
111 | return 1; | 111 | return 1; |
112 | 112 | ||
113 | return 0; | 113 | return 0; |
114 | } | 114 | } |
115 | 115 | ||
116 | /** | 116 | /** |
117 | * tps65218_toggle_fseal() - Perform the sequence that toggles the FSEAL bit. | 117 | * tps65218_toggle_fseal() - Perform the sequence that toggles the FSEAL bit. |
118 | * | 118 | * |
119 | * @return: 0 on success, -EBADE if the sequence was broken | 119 | * @return: 0 on success, -EBADE if the sequence was broken |
120 | */ | 120 | */ |
121 | int tps65218_toggle_fseal(void) | 121 | int tps65218_toggle_fseal(void) |
122 | { | 122 | { |
123 | if (tps65218_reg_write(TPS65218_PROT_LEVEL_NONE, TPS65218_PASSWORD, | 123 | if (tps65218_reg_write(TPS65218_PROT_LEVEL_NONE, TPS65218_PASSWORD, |
124 | 0xb1, TPS65218_MASK_ALL_BITS)) | 124 | 0xb1, TPS65218_MASK_ALL_BITS)) |
125 | return -EBADE; | 125 | return -EBADE; |
126 | 126 | ||
127 | if (tps65218_reg_write(TPS65218_PROT_LEVEL_NONE, TPS65218_PASSWORD, | 127 | if (tps65218_reg_write(TPS65218_PROT_LEVEL_NONE, TPS65218_PASSWORD, |
128 | 0xfe, TPS65218_MASK_ALL_BITS)) | 128 | 0xfe, TPS65218_MASK_ALL_BITS)) |
129 | return -EBADE; | 129 | return -EBADE; |
130 | 130 | ||
131 | if (tps65218_reg_write(TPS65218_PROT_LEVEL_NONE, TPS65218_PASSWORD, | 131 | if (tps65218_reg_write(TPS65218_PROT_LEVEL_NONE, TPS65218_PASSWORD, |
132 | 0xa3, TPS65218_MASK_ALL_BITS)) | 132 | 0xa3, TPS65218_MASK_ALL_BITS)) |
133 | return -EBADE; | 133 | return -EBADE; |
134 | 134 | ||
135 | return 0; | 135 | return 0; |
136 | } | 136 | } |
137 | 137 | ||
138 | /** | 138 | /** |
139 | * tps65218_lock_fseal() - Perform the sequence that locks the FSEAL bit to 1. | 139 | * tps65218_lock_fseal() - Perform the sequence that locks the FSEAL bit to 1. |
140 | * | 140 | * |
141 | * The FSEAL bit prevents the PMIC from turning off DCDC5 and DCDC6. It can be | 141 | * The FSEAL bit prevents the PMIC from turning off DCDC5 and DCDC6. It can be |
142 | * toggled at most 3 times: 0->1, 1->0, and finally 0->1. After the third switch | 142 | * toggled at most 3 times: 0->1, 1->0, and finally 0->1. After the third switch |
143 | * its value is locked and can only be reset by powering off the PMIC entirely. | 143 | * its value is locked and can only be reset by powering off the PMIC entirely. |
144 | * | 144 | * |
145 | * @return: 0 on success, -EBADE if the sequence was broken | 145 | * @return: 0 on success, -EBADE if the sequence was broken |
146 | */ | 146 | */ |
147 | int tps65218_lock_fseal(void) | 147 | int tps65218_lock_fseal(void) |
148 | { | 148 | { |
149 | int i; | 149 | int i; |
150 | 150 | ||
151 | for (i = 0; i < 3; i++) | 151 | for (i = 0; i < 3; i++) |
152 | if (tps65218_toggle_fseal()) | 152 | if (tps65218_toggle_fseal()) |
153 | return -EBADE; | 153 | return -EBADE; |
154 | 154 | ||
155 | return 0; | 155 | return 0; |
156 | } | 156 | } |
157 | 157 | ||
158 | int power_tps65218_init(unsigned char bus) | 158 | int power_tps65218_init(unsigned char bus) |
159 | { | 159 | { |
160 | static const char name[] = "TPS65218_PMIC"; | 160 | static const char name[] = "TPS65218_PMIC"; |
161 | struct pmic *p = pmic_alloc(); | 161 | struct pmic *p = pmic_alloc(); |
162 | 162 | ||
163 | if (!p) { | 163 | if (!p) { |
164 | printf("%s: POWER allocation error!\n", __func__); | 164 | printf("%s: POWER allocation error!\n", __func__); |
165 | return -ENOMEM; | 165 | return -ENOMEM; |
166 | } | 166 | } |
167 | 167 | ||
168 | p->name = name; | 168 | p->name = name; |
169 | p->interface = PMIC_I2C; | 169 | p->interface = PMIC_I2C; |
170 | p->number_of_regs = TPS65218_PMIC_NUM_OF_REGS; | 170 | p->number_of_regs = TPS65218_PMIC_NUM_OF_REGS; |
171 | p->hw.i2c.addr = TPS65218_CHIP_PM; | 171 | p->hw.i2c.addr = TPS65218_CHIP_PM; |
172 | p->hw.i2c.tx_num = 1; | 172 | p->hw.i2c.tx_num = 1; |
173 | p->bus = bus; | 173 | p->bus = bus; |
174 | 174 | ||
175 | return 0; | 175 | return 0; |
176 | } | 176 | } |
177 | 177 |
include/power/tps65218.h
1 | /* | 1 | /* |
2 | * (C) Copyright 2014 | 2 | * (C) Copyright 2014 |
3 | * Texas Instruments, <www.ti.com> | 3 | * Texas Instruments, <www.ti.com> |
4 | * | 4 | * |
5 | * SPDX-License-Identifier: GPL-2.0+ | 5 | * SPDX-License-Identifier: GPL-2.0+ |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #ifndef __POWER_TPS65218_H__ | 8 | #ifndef __POWER_TPS65218_H__ |
9 | #define __POWER_TPS65218_H__ | 9 | #define __POWER_TPS65218_H__ |
10 | 10 | ||
11 | #include <linux/bitops.h> | 11 | #include <linux/bitops.h> |
12 | 12 | ||
13 | /* I2C chip address */ | 13 | /* I2C chip address */ |
14 | #define TPS65218_CHIP_PM 0x24 | 14 | #define TPS65218_CHIP_PM 0x24 |
15 | 15 | ||
16 | /* Registers */ | 16 | /* Registers */ |
17 | enum { | 17 | enum { |
18 | TPS65218_CHIPID = 0x00, | 18 | TPS65218_CHIPID = 0x00, |
19 | TPS65218_INT1, | 19 | TPS65218_INT1, |
20 | TPS65218_INT2, | 20 | TPS65218_INT2, |
21 | TPS65218_INT_MASK1, | 21 | TPS65218_INT_MASK1, |
22 | TPS65218_INT_MASK2, | 22 | TPS65218_INT_MASK2, |
23 | TPS65218_STATUS, | 23 | TPS65218_STATUS, |
24 | TPS65218_CONTROL, | 24 | TPS65218_CONTROL, |
25 | TPS65218_FLAG, | 25 | TPS65218_FLAG, |
26 | TPS65218_PASSWORD = 0x10, | 26 | TPS65218_PASSWORD = 0x10, |
27 | TPS65218_ENABLE1, | 27 | TPS65218_ENABLE1, |
28 | TPS65218_ENABLE2, | 28 | TPS65218_ENABLE2, |
29 | TPS65218_CONFIG1, | 29 | TPS65218_CONFIG1, |
30 | TPS65218_CONFIG2, | 30 | TPS65218_CONFIG2, |
31 | TPS65218_CONFIG3, | 31 | TPS65218_CONFIG3, |
32 | TPS65218_DCDC1, | 32 | TPS65218_DCDC1, |
33 | TPS65218_DCDC2, | 33 | TPS65218_DCDC2, |
34 | TPS65218_DCDC3, | 34 | TPS65218_DCDC3, |
35 | TPS65218_DCDC4, | 35 | TPS65218_DCDC4, |
36 | TPS65218_SLEW, | 36 | TPS65218_SLEW, |
37 | TPS65218_LDO1, | 37 | TPS65218_LDO1, |
38 | TPS65218_SEQ1 = 0x20, | 38 | TPS65218_SEQ1 = 0x20, |
39 | TPS65218_SEQ2, | 39 | TPS65218_SEQ2, |
40 | TPS65218_SEQ3, | 40 | TPS65218_SEQ3, |
41 | TPS65218_SEQ4, | 41 | TPS65218_SEQ4, |
42 | TPS65218_SEQ5, | 42 | TPS65218_SEQ5, |
43 | TPS65218_SEQ6, | 43 | TPS65218_SEQ6, |
44 | TPS65218_SEQ7, | 44 | TPS65218_SEQ7, |
45 | TPS65218_PMIC_NUM_OF_REGS, | 45 | TPS65218_PMIC_NUM_OF_REGS, |
46 | }; | 46 | }; |
47 | 47 | ||
48 | #define TPS65218_PROT_LEVEL_NONE 0x00 | 48 | #define TPS65218_PROT_LEVEL_NONE 0x00 |
49 | #define TPS65218_PROT_LEVEL_1 0x01 | 49 | #define TPS65218_PROT_LEVEL_1 0x01 |
50 | #define TPS65218_PROT_LEVEL_2 0x02 | 50 | #define TPS65218_PROT_LEVEL_2 0x02 |
51 | 51 | ||
52 | #define TPS65218_PASSWORD_LOCK_FOR_WRITE 0x00 | 52 | #define TPS65218_PASSWORD_LOCK_FOR_WRITE 0x00 |
53 | #define TPS65218_PASSWORD_UNLOCK 0x7D | 53 | #define TPS65218_PASSWORD_UNLOCK 0x7D |
54 | 54 | ||
55 | #define TPS65218_DCDC_GO 0x80 | 55 | #define TPS65218_DCDC_GO 0x80 |
56 | 56 | ||
57 | #define TPS65218_MASK_ALL_BITS 0xFF | 57 | #define TPS65218_MASK_ALL_BITS 0xFF |
58 | 58 | ||
59 | #define TPS65218_DCDC_VSEL_MASK 0x3F | ||
60 | |||
59 | #define TPS65218_DCDC_VOLT_SEL_0950MV 0x0a | 61 | #define TPS65218_DCDC_VOLT_SEL_0950MV 0x0a |
60 | #define TPS65218_DCDC_VOLT_SEL_1100MV 0x19 | 62 | #define TPS65218_DCDC_VOLT_SEL_1100MV 0x19 |
61 | #define TPS65218_DCDC_VOLT_SEL_1200MV 0x23 | 63 | #define TPS65218_DCDC_VOLT_SEL_1200MV 0x23 |
62 | #define TPS65218_DCDC_VOLT_SEL_1260MV 0x29 | 64 | #define TPS65218_DCDC_VOLT_SEL_1260MV 0x29 |
63 | #define TPS65218_DCDC_VOLT_SEL_1330MV 0x30 | 65 | #define TPS65218_DCDC_VOLT_SEL_1330MV 0x30 |
64 | #define TPS65218_DCDC3_VOLT_SEL_1350MV 0x12 | 66 | #define TPS65218_DCDC3_VOLT_SEL_1350MV 0x12 |
65 | 67 | ||
66 | #define TPS65218_CC_STAT (BIT(0) | BIT(1)) | 68 | #define TPS65218_CC_STAT (BIT(0) | BIT(1)) |
67 | #define TPS65218_STATE (BIT(2) | BIT(3)) | 69 | #define TPS65218_STATE (BIT(2) | BIT(3)) |
68 | #define TPS65218_PB_STATE BIT(4) | 70 | #define TPS65218_PB_STATE BIT(4) |
69 | #define TPS65218_AC_STATE BIT(5) | 71 | #define TPS65218_AC_STATE BIT(5) |
70 | #define TPS65218_EE BIT(6) | 72 | #define TPS65218_EE BIT(6) |
71 | #define TPS65218_FSEAL BIT(7) | 73 | #define TPS65218_FSEAL BIT(7) |
72 | 74 | ||
73 | int tps65218_reg_read(uchar dest_reg, uchar *dest_val); | 75 | int tps65218_reg_read(uchar dest_reg, uchar *dest_val); |
74 | int tps65218_reg_write(uchar prot_level, uchar dest_reg, uchar dest_val, | 76 | int tps65218_reg_write(uchar prot_level, uchar dest_reg, uchar dest_val, |
75 | uchar mask); | 77 | uchar mask); |
76 | int tps65218_voltage_update(uchar dc_cntrl_reg, uchar volt_sel); | 78 | int tps65218_voltage_update(uchar dc_cntrl_reg, uchar volt_sel); |
77 | int tps65218_toggle_fseal(void); | 79 | int tps65218_toggle_fseal(void); |
78 | int tps65218_lock_fseal(void); | 80 | int tps65218_lock_fseal(void); |
79 | int power_tps65218_init(unsigned char bus); | 81 | int power_tps65218_init(unsigned char bus); |
80 | #endif /* __POWER_TPS65218_H__ */ | 82 | #endif /* __POWER_TPS65218_H__ */ |
81 | 83 |