blob: fca69130a4a9e7e5fd90e6da98dfef8356f3ad58 [file] [log] [blame]
developer74cf3ec2020-08-12 16:31:06 +08001/*
2 * Copyright (c) 2020, MediaTek Inc. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <common/debug.h>
8#include <drivers/delay_timer.h>
9#include <lib/mmio.h>
10
11#include "platform_def.h"
12#include "pmic_wrap_init.h"
13
14/* pmic wrap module wait_idle and read polling interval (in microseconds) */
15enum pwrap_polling_interval {
16 WAIT_IDLE_POLLING_DELAY_US = 1,
17 READ_POLLING_DELAY_US = 2
18};
19
20static uint32_t pwrap_check_idle(void *wacs_register, uint32_t timeout_us)
21{
22 uint32_t reg_rdata = 0U, retry;
23
24 retry = (timeout_us + WAIT_IDLE_POLLING_DELAY_US) /
25 WAIT_IDLE_POLLING_DELAY_US;
26 while (retry != 0) {
27 udelay(WAIT_IDLE_POLLING_DELAY_US);
28 reg_rdata = mmio_read_32((uintptr_t)wacs_register);
29 if (GET_WACS_FSM(reg_rdata) == SWINF_FSM_IDLE) {
30 break;
31 }
32 retry--;
33 };
34
35 if (retry == 0) {
36 /* timeout */
37 return E_PWR_WAIT_IDLE_TIMEOUT;
38 }
39
40 return 0U;
41}
42
43static uint32_t pwrap_check_vldclr(void *wacs_register, uint32_t timeout_us)
44{
45 uint32_t reg_rdata = 0U, retry;
46
47 retry = (timeout_us + READ_POLLING_DELAY_US) / READ_POLLING_DELAY_US;
48 while (retry != 0) {
49 udelay(READ_POLLING_DELAY_US);
50 reg_rdata = mmio_read_32((uintptr_t)wacs_register);
51 if (GET_WACS_FSM(reg_rdata) == SWINF_FSM_WFVLDCLR) {
52 break;
53 }
54 retry--;
55 };
56
57 if (retry == 0) {
58 /* timeout */
59 return E_PWR_WAIT_IDLE_TIMEOUT;
60 }
61
62 return 0U;
63}
64
65static int32_t pwrap_wacs2(uint32_t write, uint32_t adr, uint32_t wdata,
66 uint32_t *rdata, uint32_t init_check)
67{
68 uint32_t reg_rdata, return_value;
69
70 if (init_check != 0) {
71 if ((mmio_read_32((uintptr_t)&mtk_pwrap->init_done) & 0x1) == 0) {
72 ERROR("initialization isn't finished\n");
73 return E_PWR_NOT_INIT_DONE;
74 }
75 }
76
77 /* Wait for Software Interface FSM state to be IDLE. */
78 return_value = pwrap_check_idle(&mtk_pwrap->wacs2_sta,
79 PWRAP_WAIT_IDLE_US);
80 if (return_value != 0) {
81 return return_value;
82 }
83
84 /* Set the write data */
85 if (write == 1) {
86 /* Set the write data. */
87 mmio_write_32((uintptr_t)&mtk_pwrap->wacs2_wdata, wdata);
88 }
89
90 /* Send the command. */
91 mmio_write_32((uintptr_t)&mtk_pwrap->wacs2_cmd, (write << 29) | adr);
92
93 if (write == 0) {
94 /*
95 * Wait for Software Interface FSM state to be WFVLDCLR,
96 * read the data and clear the valid flag.
97 */
98 return_value = pwrap_check_vldclr(&mtk_pwrap->wacs2_sta,
99 PWRAP_READ_US);
100 if (return_value != 0) {
101 return return_value;
102 }
103
104 if (rdata == NULL) {
105 return E_PWR_INVALID_ARG;
106 }
107
108 reg_rdata = mmio_read_32((uintptr_t)&mtk_pwrap->wacs2_rdata);
109 *rdata = reg_rdata;
110 mmio_write_32((uintptr_t)&mtk_pwrap->wacs2_vldclr, 0x1);
111 }
112
113 return return_value;
114}
115
116/* external API for pmic_wrap user */
117int32_t pwrap_read(uint32_t adr, uint32_t *rdata)
118{
119 return pwrap_wacs2(0, adr, 0, rdata, 1);
120}
121
122int32_t pwrap_write(uint32_t adr, uint32_t wdata)
123{
124 return pwrap_wacs2(1, adr, wdata, 0, 1);
125}