coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
pmic_wrap.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <device/mmio.h>
4 #include <soc/pmic_wrap.h>
5 #include <timer.h>
6 
7 u32 wait_for_state_idle(u32 timeout_us, void *wacs_register,
8  void *wacs_vldclr_register, u32 *read_reg)
9 {
10  u32 reg_rdata;
11 
12  struct stopwatch sw;
13 
14  stopwatch_init_usecs_expire(&sw, timeout_us);
15  do {
16  reg_rdata = read32((wacs_register));
17  /* if last read command timeout,clear vldclr bit
18  read command state machine:FSM_REQ-->wfdle-->WFVLDCLR;
19  write:FSM_REQ-->idle */
20  switch (((reg_rdata >> RDATA_WACS_FSM_SHIFT) &
22  case WACS_FSM_WFVLDCLR:
23  write32(wacs_vldclr_register, 1);
24  pwrap_err("WACS_FSM = PMIC_WRAP_WACS_VLDCLR\n");
25  break;
26  case WACS_FSM_WFDLE:
27  pwrap_err("WACS_FSM = WACS_FSM_WFDLE\n");
28  break;
29  case WACS_FSM_REQ:
30  pwrap_err("WACS_FSM = WACS_FSM_REQ\n");
31  break;
32  default:
33  break;
34  }
35 
36  if (stopwatch_expired(&sw))
38 
39  } while (((reg_rdata >> RDATA_WACS_FSM_SHIFT) & RDATA_WACS_FSM_MASK) !=
40  WACS_FSM_IDLE); /* IDLE State */
41  if (read_reg)
42  *read_reg = reg_rdata;
43  return 0;
44 }
45 
47  void *wacs_register, u32 *read_reg)
48 {
49  u32 reg_rdata;
50  struct stopwatch sw;
51 
52  stopwatch_init_usecs_expire(&sw, timeout_us);
53  do {
54  reg_rdata = read32((wacs_register));
55 
56  if (stopwatch_expired(&sw)) {
57  pwrap_err("timeout when waiting for idle\n");
59  }
60  } while (fp(reg_rdata)); /* IDLE State */
61  if (read_reg)
62  *read_reg = reg_rdata;
63  return 0;
64 }
65 
67 {
68  u32 ret = 0;
69 
73  write32(&mtk_pwrap->man_en, 1);
74  write32(&mtk_pwrap->dio_en, 0);
75 
76  write32(&mtk_pwrap->man_cmd, (OP_WR << 13) | (OP_CSL << 8));
77  /* Reset counter */
78  write32(&mtk_pwrap->man_cmd, (OP_WR << 13) | (OP_OUTS << 8));
79  write32(&mtk_pwrap->man_cmd, (OP_WR << 13) | (OP_CSH << 8));
80  /*
81  * In order to pull CSN signal to PMIC,
82  * PMIC will count it then reset spi slave
83  */
84  write32(&mtk_pwrap->man_cmd, (OP_WR << 13) | (OP_OUTS << 8));
85  write32(&mtk_pwrap->man_cmd, (OP_WR << 13) | (OP_OUTS << 8));
86  write32(&mtk_pwrap->man_cmd, (OP_WR << 13) | (OP_OUTS << 8));
87  write32(&mtk_pwrap->man_cmd, (OP_WR << 13) | (OP_OUTS << 8));
88 
90  &mtk_pwrap->wacs2_rdata, 0))
91  ret = E_PWR_TIMEOUT;
92 
93  write32(&mtk_pwrap->man_en, 0);
95 
96  return ret;
97 }
98 
99 s32 pwrap_wacs2(u32 write, u16 addr, u16 wdata, u16 *rdata, u32 init_check)
100 {
101  u32 reg_rdata = 0;
102  u32 wacs_write = 0;
103  u32 wacs_addr = 0;
104  u32 wacs_cmd = 0;
105  u32 wait_result = 0;
106  u32 shift;
107 
108  if (init_check) {
109  reg_rdata = read32(&mtk_pwrap->wacs2_rdata);
110  /* Prevent someone to use pwrap before pwrap init */
111  if (CONFIG(SOC_MEDIATEK_MT8186))
112  shift = RDATA_INIT_DONE_V2_SHIFT;
113  else
114  shift = RDATA_INIT_DONE_V1_SHIFT;
115 
116  if (((reg_rdata >> shift) & RDATA_INIT_DONE_MASK) != WACS_INIT_DONE) {
117  pwrap_err("Pwrap initialization isn't finished\n");
118  return E_PWR_NOT_INIT_DONE;
119  }
120  }
121  reg_rdata = 0;
122  /* Check IDLE in advance */
126  0);
127  if (wait_result != 0) {
128  pwrap_err("wait_for_fsm_idle fail,wait_result=%d\n",
129  wait_result);
131  }
132  wacs_write = write << 31;
133  wacs_addr = (addr >> 1) << 16;
134  wacs_cmd = wacs_write | wacs_addr | wdata;
135 
136  write32(&mtk_pwrap->wacs2_cmd, wacs_cmd);
137  if (write == 0) {
138  if (rdata == NULL) {
139  pwrap_err("rdata is a NULL pointer\n");
140  return E_PWR_INVALID_ARG;
141  }
145  &reg_rdata);
146  if (wait_result != 0) {
147  pwrap_err("wait_for_fsm_vldclr fail,wait_result=%d\n",
148  wait_result);
150  }
151  *rdata = ((reg_rdata >> RDATA_WACS_RDATA_SHIFT)
154  }
155 
156  return 0;
157 }
static void write32(void *addr, uint32_t val)
Definition: mmio.h:40
static uint32_t read32(const void *addr)
Definition: mmio.h:22
static u32 addr
Definition: cirrus.c:14
s32 pwrap_reset_spislv(void)
Definition: pmic_wrap.c:66
u32 wait_for_state_ready(loop_condition_fp fp, u32 timeout_us, void *wacs_register, u32 *read_reg)
Definition: pmic_wrap.c:46
u32 wait_for_state_idle(u32 timeout_us, void *wacs_register, void *wacs_vldclr_register, u32 *read_reg)
Definition: pmic_wrap.c:7
s32 pwrap_wacs2(u32 write, u16 addr, u16 wdata, u16 *rdata, u32 init_check)
Definition: pmic_wrap.c:99
@ CONFIG
Definition: dsi_common.h:201
static int stopwatch_expired(struct stopwatch *sw)
Definition: timer.h:152
static void stopwatch_init_usecs_expire(struct stopwatch *sw, long us)
Definition: timer.h:127
static struct mt8173_pwrap_regs *const mtk_pwrap
Definition: pmic_wrap.h:10
static u32 wait_for_sync(u32 x)
#define pwrap_err(fmt, arg ...)
u32(* loop_condition_fp)(u32)
@ WACS_FSM_REQ
@ WACS_FSM_WFDLE
@ WACS_FSM_WFVLDCLR
@ WACS_INIT_DONE
@ WACS_FSM_IDLE
@ RDATA_INIT_DONE_V2_SHIFT
@ RDATA_WACS_FSM_MASK
@ RDATA_WACS_RDATA_MASK
@ RDATA_INIT_DONE_MASK
@ RDATA_WACS_FSM_SHIFT
@ RDATA_INIT_DONE_V1_SHIFT
@ RDATA_WACS_RDATA_SHIFT
@ OP_OUTS
@ OP_WR
@ OP_CSH
@ OP_CSL
static u32 wait_for_fsm_vldclr(u32 x)
@ E_PWR_WAIT_IDLE_TIMEOUT_READ
@ E_PWR_WAIT_IDLE_TIMEOUT
@ E_PWR_INVALID_ARG
@ E_PWR_NOT_INIT_DONE
@ E_PWR_TIMEOUT
@ TIMEOUT_READ_US
@ TIMEOUT_WAIT_IDLE_US
static void read_reg(const void *src, void *value, uint32_t size)
Definition: spi.c:230
#define NULL
Definition: stddef.h:19
uint32_t u32
Definition: stdint.h:51
uint16_t u16
Definition: stdint.h:48
int32_t s32
Definition: stdint.h:50