blob: f2eba5b6971249cc7b8906239d1981e72a3c69cd [file] [log] [blame]
Umang Agrawald13b5fe2017-12-19 12:09:31 +05301/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of The Linux Foundation, Inc. nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <stdio.h>
30#include <string.h>
31#include <stdlib.h>
32#include <err.h>
33#include <debug.h>
34#include <spmi.h>
35#include <qpnp_wled.h>
36#include <qpnp_lcdb.h>
37#include <qtimer.h>
38#include <target.h>
39
40struct qpnp_lcdb *lcdb;
41
42int qpnp_lcdb_enable(bool state)
43{
44 if (!lcdb) {
45 dprintf(CRITICAL, "%s: lcdb is not initialized yet\n", __func__);
46 return ERROR;
47 }
48
49 pmic_spmi_reg_mask_write(lcdb->lcdb_base + QPNP_LCDB_ENABLE_CTL_REG,
50 QPNP_LCDB_ENABLE_CTL_MASK, (state << LCDB_ENABLE_SHIFT));
51
52 return 0;
53}
54
55static int qpnp_lcdb_set_voltage(struct qpnp_lcdb *lcdb)
56{
57 int rc = -1;
58 uint32_t new_uV, boost_ref_volt;
59 uint8_t val;
60
61 /* Set LDO Voltage */
62 if (lcdb->ldo_min_volt < lcdb->ldo_init_volt) {
63 dprintf(CRITICAL, "qpnp_ldo_set_voltage failed, min_uV %d is "
64 "less than the minimum supported voltage %d\n",
65 lcdb->ldo_min_volt, lcdb->ldo_init_volt);
66 return rc;
67 }
68
69 val = ((lcdb->ldo_min_volt - lcdb->ldo_init_volt) +
70 LDO_VREG_STEP_SIZE_UV - 1) / LDO_VREG_STEP_SIZE_UV;
71 new_uV = val * LDO_VREG_STEP_SIZE_UV + lcdb->ldo_init_volt;
72 if (new_uV > lcdb->ldo_max_volt) {
73 dprintf(CRITICAL, "qpnp_ldo_set_voltage unable to set voltage "
74 "(%d %d)\n", lcdb->ldo_min_volt, lcdb->ldo_max_volt);
75 return rc;
76 }
77
78 /* Value adjustment as initial 1V has 100mV step and rest 50mV step */
79 if ( val > 18 )
80 val = val - 9;
81 else
82 val = val / 2;
83
84 pmic_spmi_reg_mask_write(lcdb->lcdb_base +
85 QPNP_LCDB_LDO_OUTPUT_VOLTAGE_REG,
86 QPNP_LCDB_LDO_OUTPUT_VOLTAGE_MASK, val);
87
88 udelay(2);
89
90 /* Set NCP voltage */
91 if (lcdb->ncp_min_volt < lcdb->ncp_init_volt) {
92 dprintf(CRITICAL, "qpnp_ncp_set_voltage failed, min_uV %d is "
93 "less than the minimum supported voltage %d\n",
94 lcdb->ncp_min_volt, lcdb->ncp_init_volt);
95 return rc;
96 }
97
98 val = ((lcdb->ncp_min_volt - lcdb->ncp_init_volt) +
99 NCP_VREG_STEP_SIZE_UV - 1) / NCP_VREG_STEP_SIZE_UV;
100 new_uV = val * NCP_VREG_STEP_SIZE_UV + lcdb->ncp_init_volt;
101 if (new_uV > lcdb->ncp_max_volt) {
102 dprintf(CRITICAL, "qpnp_ncp_set_voltage unable to set voltage "
103 "(%d %d)\n", lcdb->ncp_min_volt, lcdb->ncp_max_volt);
104 return rc;
105 }
106
107 /* Value adjustment as initial 1V has 100mV step and rest 50mV step */
108 if ( val > 18 )
109 val = val - 9;
110 else
111 val = val / 2;
112
113 pmic_spmi_reg_mask_write(lcdb->lcdb_base +
114 QPNP_LCDB_NCP_OUTPUT_VOLTAGE_REG,
115 QPNP_LCDB_NCP_OUTPUT_VOLTAGE_MASK, val);
116
117 udelay(2);
118
119 /* Set Boost voltage */
120 boost_ref_volt = ((lcdb->ldo_max_volt > lcdb->ncp_max_volt) ?
121 lcdb->ldo_max_volt : lcdb->ncp_max_volt) +
122 LCDB_BOOST_HEADROOM_VOLT_UV;
123 if (boost_ref_volt < lcdb->bst_init_volt)
124 boost_ref_volt = lcdb->bst_init_volt;
125
126 val = ((boost_ref_volt - lcdb->bst_init_volt) +
127 BST_VREG_STEP_SIZE_UV - 1) / BST_VREG_STEP_SIZE_UV;
128 new_uV = val * BST_VREG_STEP_SIZE_UV + lcdb->bst_init_volt;
129
130 pmic_spmi_reg_mask_write(lcdb->lcdb_base +
131 QPNP_LCDB_BST_OUTPUT_VOLTAGE_REG,
132 QPNP_LCDB_BST_OUTPUT_VOLTAGE_MASK, val);
133
134 return 0;
135}
136
137static int qpnp_lcdb_config(struct qpnp_lcdb *lcdb)
138{
139 int rc = 0;
140 uint8_t reg = 0;
141
142 /* TODO: Set power up & down delay register */
143 if (lcdb->lcdb_pwrup_dly_ms > QPNP_LCDB_PWRUP_DLY_MAX_MS)
144 lcdb->lcdb_pwrup_dly_ms = QPNP_LCDB_PWRUP_DLY_MAX_MS;
145
146 if (lcdb->lcdb_pwrdn_dly_ms > QPNP_LCDB_PWRDN_DLY_MAX_MS)
147 lcdb->lcdb_pwrdn_dly_ms = QPNP_LCDB_PWRDN_DLY_MAX_MS;
148
149 reg = pmic_spmi_reg_read(lcdb->lcdb_base +
150 QPNP_LCDB_PWRUP_PWRDN_CTL_REG);
151
152 /* Set power up delay */
153 reg &= QPNP_LCDB_PWRUP_DLY_MASK;
154 reg |= (lcdb->lcdb_pwrup_dly_ms << LCDB_PWRUP_DLY_SHIFT);
155
156 /* Set power down delay */
157 reg &= QPNP_LCDB_PWRDN_DLY_MASK;
158 reg |= (lcdb->lcdb_pwrdn_dly_ms);
159
160 pmic_spmi_reg_write(lcdb->lcdb_base + QPNP_LCDB_PWRUP_PWRDN_CTL_REG,
161 reg);
162
163 /* Make LCDB module ready */
164 pmic_spmi_reg_mask_write(lcdb->lcdb_base + QPNP_LCDB_MODULE_RDY_REG,
165 QPNP_LCDB_MODULE_RDY_MASK, LCDB_MODULE_RDY);
166
167 /* Set regulator voltage */
168 rc = qpnp_lcdb_set_voltage(lcdb);
169
170 return rc;
171}
172
173static int qpnp_lcdb_setup(struct qpnp_lcdb *lcdb,
174 struct qpnp_wled_config_data *config)
175{
176 lcdb->lcdb_base = QPNP_LCDB_BASE;
177 lcdb->lcdb_pwrup_dly_ms = config->pwr_up_delay;
178 lcdb->lcdb_pwrdn_dly_ms = config->pwr_down_delay;
179 lcdb->ldo_min_volt = config->lab_min_volt;
180 lcdb->ldo_max_volt = config->lab_max_volt;
181 lcdb->ldo_init_volt = LCDB_LDO_INIT_VOLTAGE_UV;
182 lcdb->ncp_min_volt = config->ibb_min_volt;
183 lcdb->ncp_max_volt = config->ibb_max_volt;
184 lcdb->ncp_init_volt = LCDB_NCP_INIT_VOLTAGE_UV;
185 lcdb->bst_init_volt = LCDB_BOOST_INIT_VOLTAGE_UV;
186
187 return 0;
188}
189
190int qpnp_lcdb_init(struct qpnp_wled_config_data *config)
191{
192 int rc;
193
194 if (!target_is_pmi_enabled())
195 return ERR_NOT_FOUND;
196
197 lcdb = malloc(sizeof(struct qpnp_lcdb));
198 if (!lcdb)
199 return ERR_NO_MEMORY;
200
201 memset(lcdb, 0, sizeof(struct qpnp_lcdb));
202
203 rc = qpnp_lcdb_setup(lcdb, config);
204 if(rc) {
205 dprintf(CRITICAL, "Setting LCDB parameters failed\n");
206 return rc;
207 }
208
209 rc = qpnp_lcdb_config(lcdb);
210 if (rc) {
211 dprintf(CRITICAL, "lcdb config failed\n");
212 return rc;
213 }
214
215 return rc;
216}