blob: 48908c72a113d2b9828b2bf6abba36c771f899e2 [file] [log] [blame]
developer65014b82015-04-13 14:47:57 +08001/*
2 * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice, this
8 * list of conditions and the following disclaimer.
9 *
10 * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * Neither the name of ARM nor the names of its contributors may be used
15 * to endorse or promote products derived from this software without specific
16 * prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30#include <debug.h>
31#include <delay_timer.h>
32#include <mmio.h>
33#include <mt8173_def.h>
34#include <pmic_wrap_init.h>
35
36/* pmic wrap module wait_idle and read polling interval (in microseconds) */
37enum {
38 WAIT_IDLE_POLLING_DELAY_US = 1,
39 READ_POLLING_DELAY_US = 2
40};
41
42static inline uint32_t wait_for_state_idle(uint32_t timeout_us,
43 void *wacs_register,
44 void *wacs_vldclr_register,
45 uint32_t *read_reg)
46{
47 uint32_t reg_rdata;
48 uint32_t retry;
49
50 retry = (timeout_us + WAIT_IDLE_POLLING_DELAY_US) /
51 WAIT_IDLE_POLLING_DELAY_US;
52
53 do {
54 udelay(WAIT_IDLE_POLLING_DELAY_US);
55 reg_rdata = mmio_read_32((uintptr_t)wacs_register);
56 /* if last read command timeout,clear vldclr bit
57 read command state machine:FSM_REQ-->wfdle-->WFVLDCLR;
58 write:FSM_REQ-->idle */
59 switch (((reg_rdata >> RDATA_WACS_FSM_SHIFT) &
60 RDATA_WACS_FSM_MASK)) {
61 case WACS_FSM_WFVLDCLR:
62 mmio_write_32((uintptr_t)wacs_vldclr_register, 1);
63 ERROR("WACS_FSM = PMIC_WRAP_WACS_VLDCLR\n");
64 break;
65 case WACS_FSM_WFDLE:
66 ERROR("WACS_FSM = WACS_FSM_WFDLE\n");
67 break;
68 case WACS_FSM_REQ:
69 ERROR("WACS_FSM = WACS_FSM_REQ\n");
70 break;
71 case WACS_FSM_IDLE:
72 goto done;
73 default:
74 break;
75 }
76
77 retry--;
78 } while (retry);
79
80done:
81 if (!retry) /* timeout */
82 return E_PWR_WAIT_IDLE_TIMEOUT;
83
84 if (read_reg)
85 *read_reg = reg_rdata;
86 return 0;
87}
88
89static inline uint32_t wait_for_state_ready(uint32_t timeout_us,
90 void *wacs_register,
91 uint32_t *read_reg)
92{
93 uint32_t reg_rdata;
94 uint32_t retry;
95
96 retry = (timeout_us + READ_POLLING_DELAY_US) / READ_POLLING_DELAY_US;
97
98 do {
99 udelay(READ_POLLING_DELAY_US);
100 reg_rdata = mmio_read_32((uintptr_t)wacs_register);
101
102 if (((reg_rdata >> RDATA_WACS_FSM_SHIFT) & RDATA_WACS_FSM_MASK)
103 == WACS_FSM_WFVLDCLR)
104 break;
105
106 retry--;
107 } while (retry);
108
109 if (!retry) { /* timeout */
110 ERROR("timeout when waiting for idle\n");
111 return E_PWR_WAIT_IDLE_TIMEOUT_READ;
112 }
113
114 if (read_reg)
115 *read_reg = reg_rdata;
116 return 0;
117}
118
119static int32_t pwrap_wacs2(uint32_t write,
120 uint32_t adr,
121 uint32_t wdata,
122 uint32_t *rdata,
123 uint32_t init_check)
124{
125 uint32_t reg_rdata = 0;
126 uint32_t wacs_write = 0;
127 uint32_t wacs_adr = 0;
128 uint32_t wacs_cmd = 0;
129 uint32_t return_value = 0;
130
131 if (init_check) {
132 reg_rdata = mmio_read_32((uintptr_t)&mt8173_pwrap->wacs2_rdata);
133 /* Prevent someone to used pwrap before pwrap init */
134 if (((reg_rdata >> RDATA_INIT_DONE_SHIFT) &
135 RDATA_INIT_DONE_MASK) != WACS_INIT_DONE) {
136 ERROR("initialization isn't finished\n");
137 return E_PWR_NOT_INIT_DONE;
138 }
139 }
140 reg_rdata = 0;
141 /* Check IDLE in advance */
142 return_value = wait_for_state_idle(TIMEOUT_WAIT_IDLE,
143 &mt8173_pwrap->wacs2_rdata,
144 &mt8173_pwrap->wacs2_vldclr,
145 0);
146 if (return_value != 0) {
147 ERROR("wait_for_fsm_idle fail,return_value=%d\n", return_value);
148 goto FAIL;
149 }
150 wacs_write = write << 31;
151 wacs_adr = (adr >> 1) << 16;
152 wacs_cmd = wacs_write | wacs_adr | wdata;
153
154 mmio_write_32((uintptr_t)&mt8173_pwrap->wacs2_cmd, wacs_cmd);
155 if (write == 0) {
156 if (NULL == rdata) {
157 ERROR("rdata is a NULL pointer\n");
158 return_value = E_PWR_INVALID_ARG;
159 goto FAIL;
160 }
161 return_value = wait_for_state_ready(TIMEOUT_READ,
162 &mt8173_pwrap->wacs2_rdata,
163 &reg_rdata);
164 if (return_value != 0) {
165 ERROR("wait_for_fsm_vldclr fail,return_value=%d\n",
166 return_value);
167 goto FAIL;
168 }
169 *rdata = ((reg_rdata >> RDATA_WACS_RDATA_SHIFT)
170 & RDATA_WACS_RDATA_MASK);
171 mmio_write_32((uintptr_t)&mt8173_pwrap->wacs2_vldclr, 1);
172 }
173FAIL:
174 return return_value;
175}
176
177/* external API for pmic_wrap user */
178
179int32_t pwrap_read(uint32_t adr, uint32_t *rdata)
180{
181 return pwrap_wacs2(0, adr, 0, rdata, 1);
182}
183
184int32_t pwrap_write(uint32_t adr, uint32_t wdata)
185{
186 return pwrap_wacs2(1, adr, wdata, 0, 1);
187}