coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
pmif_spi.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <console/console.h>
4 #include <device/mmio.h>
5 #include <soc/infracfg.h>
6 #include <soc/pll.h>
7 #include <soc/pmif_spi.h>
8 #include <soc/pmif_sw.h>
9 #include <timer.h>
10 
11 /* PMIF, SPI_MODE_CTRL */
12 DEFINE_BIT(SPI_MODE_CTRL_VLD_SRCLK_EN_CTRL, 5)
13 DEFINE_BIT(SPI_MODE_CTRL_PMIF_RDY, 9)
14 DEFINE_BIT(SPI_MODE_CTRL_SRCLK_EN, 10)
15 DEFINE_BIT(SPI_MODE_CTRL_SRVOL_EN, 11)
16 
17 /* PMIF, SLEEP_PROTECTION_CTRL */
18 DEFINE_BITFIELD(SPM_SLEEP_REQ_SEL, 1, 0)
19 DEFINE_BITFIELD(SCP_SLEEP_REQ_SEL, 10, 9)
20 
21 /* PMIF, OTHER_INF_EN */
22 DEFINE_BITFIELD(INTGPSADCINF_EN, 5, 4)
23 
24 /* PMIF, STAUPD_CTRL */
25 DEFINE_BITFIELD(STAUPD_CTRL_PRD, 3, 0)
26 DEFINE_BIT(STAUPD_CTRL_PMIC0_SIG_STA, 4)
27 DEFINE_BIT(STAUPD_CTRL_PMIC0_EINT_STA, 6)
28 
29 /* SPIMST, Manual_Mode_Access */
30 DEFINE_BITFIELD(MAN_ACC_SPI_OP, 12, 8)
31 DEFINE_BIT(MAN_ACC_SPI_RW, 13)
32 
33 static void pmif_spi_config(struct pmif *arb)
34 {
35  /* Set srclk_en always valid regardless of ulposc_sel_for_scp */
36  SET32_BITFIELDS(&arb->mtk_pmif->spi_mode_ctrl, SPI_MODE_CTRL_VLD_SRCLK_EN_CTRL, 0);
37 
38  /* Set SPI mode controlled by srclk_en and srvol_en instead of pmif_rdy */
39  SET32_BITFIELDS(&arb->mtk_pmif->spi_mode_ctrl,
40  SPI_MODE_CTRL_SRCLK_EN, 1,
41  SPI_MODE_CTRL_SRVOL_EN, 1,
42  SPI_MODE_CTRL_PMIF_RDY, 0);
43 
44  SET32_BITFIELDS(&arb->mtk_pmif->sleep_protection_ctrl, SPM_SLEEP_REQ_SEL, 0,
45  SCP_SLEEP_REQ_SEL, 0);
46 
47  /* Enable SWINF for AP */
48  write32(&arb->mtk_pmif->inf_en, PMIF_SPI_AP);
49 
50  /* Enable arbitration for SWINF for AP */
51  write32(&arb->mtk_pmif->arb_en, PMIF_SPI_AP);
52 
53  /* Enable PMIF_SPI Command Issue */
54  write32(&arb->mtk_pmif->cmdissue_en, 1);
55 }
56 
57 static int check_idle(void *addr, u32 expected)
58 {
59  u32 reg_rdata;
60  struct stopwatch sw;
61 
63  do {
64  reg_rdata = read32(addr);
65  if (stopwatch_expired(&sw))
66  return E_TIMEOUT;
67  } while ((reg_rdata & expected) != 0);
68 
69  return 0;
70 }
71 
72 static int reset_spislv(void)
73 {
74  u32 pmicspi_mst_dio_en_backup;
75 
79  pmicspi_mst_dio_en_backup = read32(&mtk_pmicspi_mst->dio_en);
81 
82  SET32_BITFIELDS(&mtk_pmicspi_mst->man_acc, MAN_ACC_SPI_RW, OP_WR,
83  MAN_ACC_SPI_OP, OP_CSL);
84  /* Reset counter */
85  SET32_BITFIELDS(&mtk_pmicspi_mst->man_acc, MAN_ACC_SPI_RW, OP_WR,
86  MAN_ACC_SPI_OP, OP_OUTS);
87  SET32_BITFIELDS(&mtk_pmicspi_mst->man_acc, MAN_ACC_SPI_RW, OP_WR,
88  MAN_ACC_SPI_OP, OP_CSH);
89  /*
90  * In order to pull CSN signal to PMIC,
91  * PMIC will count it then reset spi slave
92  */
93  SET32_BITFIELDS(&mtk_pmicspi_mst->man_acc, MAN_ACC_SPI_RW, OP_WR,
94  MAN_ACC_SPI_OP, OP_OUTS);
95  SET32_BITFIELDS(&mtk_pmicspi_mst->man_acc, MAN_ACC_SPI_RW, OP_WR,
96  MAN_ACC_SPI_OP, OP_OUTS);
97  SET32_BITFIELDS(&mtk_pmicspi_mst->man_acc, MAN_ACC_SPI_RW, OP_WR,
98  MAN_ACC_SPI_OP, OP_OUTS);
99  SET32_BITFIELDS(&mtk_pmicspi_mst->man_acc, MAN_ACC_SPI_RW, OP_WR,
100  MAN_ACC_SPI_OP, OP_OUTS);
101 
102  /* Wait for PMIC SPI Master to be idle */
104  printk(BIOS_ERR, "[%s] spi master busy, timeout\n", __func__);
105  return E_TIMEOUT;
106  }
107 
111  write32(&mtk_pmicspi_mst->dio_en, pmicspi_mst_dio_en_backup);
112 
113  return 0;
114 }
115 
116 static void init_reg_clock(struct pmif *arb)
117 {
118  pmif_spi_iocfg();
119 
120  /* Configure SPI protocol */
127 
128  /* Set Read Dummy Cycle Number (Slave Clock is 18MHz) */
131 
132  /* Enable DIO mode */
133  arb->write(arb, DEFAULT_SLVID, PMIC_DEW_DIO_EN, 0x1);
134 
135  /* Wait for completion of sending the commands */
137  printk(BIOS_ERR, "[%s] pmif channel busy, timeout\n", __func__);
138  return;
139  }
140 
142  printk(BIOS_ERR, "[%s] pmif cmd busy, timeout\n", __func__);
143  return;
144  }
145 
147  printk(BIOS_ERR, "[%s] spi master busy, timeout\n", __func__);
148  return;
149  }
150 
152 }
153 
154 static void init_spislv(struct pmif *arb)
155 {
156  /* Turn on SPI IO filter function */
158  /* Turn on SPI IO SMT function to improve noise immunity */
160  /* Turn off SPI IO pull function for power saving */
162  /* Enable SPI access in SODI-3.0 and Suspend modes */
163  arb->write(arb, DEFAULT_SLVID, PMIC_RG_SPI_CON0, 0x2);
164  /* Set SPI IO driving strength to 4 mA */
166 }
167 
168 static int init_sistrobe(struct pmif *arb)
169 {
170  u32 rdata = 0;
171  int si_sample_ctrl;
172  /* Random data for testing */
173  const u32 test_data[30] = {
174  0x6996, 0x9669, 0x6996, 0x9669, 0x6996, 0x9669, 0x6996,
175  0x9669, 0x6996, 0x9669, 0x5AA5, 0xA55A, 0x5AA5, 0xA55A,
176  0x5AA5, 0xA55A, 0x5AA5, 0xA55A, 0x5AA5, 0xA55A, 0x1B27,
177  0x1B27, 0x1B27, 0x1B27, 0x1B27, 0x1B27, 0x1B27, 0x1B27,
178  0x1B27, 0x1B27
179  };
180 
181  for (si_sample_ctrl = 0; si_sample_ctrl < 16; si_sample_ctrl++) {
182  write32(&mtk_pmicspi_mst->si_sampling_ctrl, si_sample_ctrl << 5);
183 
184  arb->read(arb, DEFAULT_SLVID, PMIC_DEW_READ_TEST, &rdata);
185  if (rdata == DEFAULT_VALUE_READ_TEST)
186  break;
187  }
188 
189  if (si_sample_ctrl == 16)
190  return E_CLK_EDGE;
191 
192  if (si_sample_ctrl == 15)
193  return E_CLK_LAST_SETTING;
194 
195  /*
196  * Add the delay time of SPI data from PMIC to align the start boundary
197  * to current sampling clock edge.
198  */
199  for (int si_dly = 0; si_dly < 10; si_dly++) {
200  arb->write(arb, DEFAULT_SLVID, PMIC_RG_SPI_CON2, si_dly);
201 
202  int start_boundary_found = 0;
203  for (int i = 0; i < ARRAY_SIZE(test_data); i++) {
204  arb->write(arb, DEFAULT_SLVID, PMIC_DEW_WRITE_TEST, test_data[i]);
205  arb->read(arb, DEFAULT_SLVID, PMIC_DEW_WRITE_TEST, &rdata);
206  if ((rdata & 0x7fff) != (test_data[i] & 0x7fff)) {
207  start_boundary_found = 1;
208  break;
209  }
210  }
211  if (start_boundary_found == 1)
212  break;
213  }
214 
215  /*
216  * Change the sampling clock edge to the next one which is the middle
217  * of SPI data window.
218  */
219  write32(&mtk_pmicspi_mst->si_sampling_ctrl, ++si_sample_ctrl << 5);
220 
221  /* Read Test */
222  arb->read(arb, DEFAULT_SLVID, PMIC_DEW_READ_TEST, &rdata);
223  if (rdata != DEFAULT_VALUE_READ_TEST) {
224  printk(BIOS_ERR, "[%s] Failed for read test, data = %#x.\n",
225  __func__, rdata);
226  return E_READ_TEST_FAIL;
227  }
228 
229  return 0;
230 }
231 
232 static void init_staupd(struct pmif *arb)
233 {
234  /* Unlock SPI Slave registers */
235  arb->write(arb, DEFAULT_SLVID, PMIC_SPISLV_KEY, 0xbade);
236 
237  /* Enable CRC of PMIC 0 */
238  arb->write(arb, DEFAULT_SLVID, PMIC_DEW_CRC_EN, 0x1);
239 
240  /* Wait for completion of sending the commands */
242  printk(BIOS_ERR, "[%s] pmif channel busy, timeout\n", __func__);
243  return;
244  }
245 
247  printk(BIOS_ERR, "[%s] pmif cmd busy, timeout\n", __func__);
248  return;
249  }
250 
252  printk(BIOS_ERR, "[%s] spi master busy, timeout\n", __func__);
253  return;
254  }
255 
256  /* Configure CRC of PMIC Interface */
257  write32(&arb->mtk_pmif->crc_ctrl, 0x1);
258  write32(&arb->mtk_pmif->sig_mode, 0x0);
259 
260  /* Lock SPI Slave registers */
261  arb->write(arb, DEFAULT_SLVID, PMIC_SPISLV_KEY, 0x0);
262 
263  /* Set up PMIC Siganature */
265 
266  /* Set up PMIC EINT */
268 
270  STAUPD_CTRL_PRD, 5,
271  STAUPD_CTRL_PMIC0_SIG_STA, 1,
272  STAUPD_CTRL_PMIC0_EINT_STA, 1);
273 }
274 
275 int pmif_spi_init(struct pmif *arb)
276 {
277  pmif_spi_config(arb);
278 
279  /* Reset spislv */
280  if (reset_spislv())
281  return E_SPI_INIT_RESET_SPI;
282 
283  /* Enable WRAP */
285 
286  /* SPI Waveform Configuration */
287  init_reg_clock(arb);
288 
289  /* SPI Slave Configuration */
290  init_spislv(arb);
291 
292  /* Input data calibration flow; */
293  if (init_sistrobe(arb)) {
294  printk(BIOS_ERR, "[%s] data calibration fail\n", __func__);
295  return E_SPI_INIT_SIDLY;
296  }
297 
298  /* Lock SPISLV Registers */
299  arb->write(arb, DEFAULT_SLVID, PMIC_SPISLV_KEY, 0x0);
300 
301  /*
302  * Status update function initialization
303  * 1. Check signature using CRC (CRC 0 only)
304  * 2. Update EINT
305  * 3. Read back AUXADC thermal data for GPS
306  */
307  init_staupd(arb);
308 
309  /* Configure PMIF Timer */
310  write32(&arb->mtk_pmif->timer_ctrl, 0x3);
311 
312  /* Enable interfaces and arbitration */
315 
318 
319  /* Enable GPS AUXADC HW 0 and 1 */
320  SET32_BITFIELDS(&arb->mtk_pmif->other_inf_en, INTGPSADCINF_EN, 0x3);
321 
322  /* Set INIT_DONE */
323  write32(&arb->mtk_pmif->init_done, 0x1);
324 
325  return 0;
326 }
static void write32(void *addr, uint32_t val)
Definition: mmio.h:40
static uint32_t read32(const void *addr)
Definition: mmio.h:22
#define ARRAY_SIZE(a)
Definition: helpers.h:12
static u32 addr
Definition: cirrus.c:14
int pmif_spi_init(struct pmif *arb)
Definition: pmif_spi.c:275
static void init_staupd(struct pmif *arb)
Definition: pmif_spi.c:232
static void init_reg_clock(struct pmif *arb)
Definition: pmif_spi.c:116
static int reset_spislv(void)
Definition: pmif_spi.c:72
static int init_sistrobe(struct pmif *arb)
Definition: pmif_spi.c:168
static void init_spislv(struct pmif *arb)
Definition: pmif_spi.c:154
static int check_idle(void *addr, u32 expected)
Definition: pmif_spi.c:57
static void pmif_spi_config(struct pmif *arb)
Definition: pmif_spi.c:33
#define printk(level,...)
Definition: stdlib.h:16
@ E_TIMEOUT
#define DEFINE_BITFIELD(name, high_bit, low_bit)
Definition: mmio.h:124
#define DEFINE_BIT(name, bit)
Definition: mmio.h:131
#define SET32_BITFIELDS(addr,...)
Definition: mmio.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
#define BIOS_ERR
BIOS_ERR - System in incomplete state.
Definition: loglevel.h:72
void pmif_spi_iocfg(void)
Definition: pmif_spi.c:10
@ OP_OUTS
@ OP_WR
@ OP_CSH
@ OP_CSL
@ E_SPI_INIT_SIDLY
Definition: pmif_common.h:52
@ E_READ_TEST_FAIL
Definition: pmif_common.h:50
@ E_SPI_INIT_RESET_SPI
Definition: pmif_common.h:51
@ PMIC_DEW_CRC_EN
Definition: pmif_spi.h:49
@ PMIC_DEW_READ_TEST
Definition: pmif_spi.h:47
@ PMIC_DEW_DIO_EN
Definition: pmif_spi.h:46
@ PMIC_DEW_WRITE_TEST
Definition: pmif_spi.h:48
@ PMIC_INT_STA
Definition: pmif_spi.h:54
@ PMIC_DEW_RDDMY_NO
Definition: pmif_spi.h:51
@ PMIC_FILTER_CON0
Definition: pmif_spi.h:43
@ PMIC_GPIO_PULLEN0_CLR
Definition: pmif_spi.h:44
@ PMIC_SMT_CON1
Definition: pmif_spi.h:41
@ PMIC_DEW_CRC_VAL
Definition: pmif_spi.h:50
@ PMIC_RG_SPI_CON2
Definition: pmif_spi.h:52
@ PMIC_DRV_CON1
Definition: pmif_spi.h:42
@ PMIC_SPISLV_KEY
Definition: pmif_spi.h:53
@ PMIC_RG_SPI_CON0
Definition: pmif_spi.h:45
#define PMIF_SPI_HW_INF
Definition: pmif_spi.h:60
#define PMIF_SPI_MD
Definition: pmif_spi.h:61
@ DUMMY_READ_CYCLES
Definition: pmif_spi.h:109
#define SPIMST_STA
Definition: pmif_spi.h:71
#define PMIF_SPI_AP
Definition: pmif_spi.h:63
#define PMIF_CMD_STA
Definition: pmif_spi.h:70
#define DEFAULT_SLVID
Definition: pmif_spi.h:68
@ SPI_DRIVING
Definition: pmif_spi.h:92
@ SPI_SMT
Definition: pmif_spi.h:79
@ SPI_FILTER
Definition: pmif_spi.h:78
@ SPI_PULL_DISABLE
Definition: pmif_spi.h:80
#define PMIF_SPI_AP_SECURE
Definition: pmif_spi.h:62
static struct mtk_pmicspi_mst_regs *const mtk_pmicspi_mst
Definition: pmif_spi.h:36
#define PMIF_SPI_DCXO_HW
Definition: pmif_spi.h:66
#define PMIF_SPI_STAUPD
Definition: pmif_spi.h:64
#define PMIF_SPI_TSX_HW
Definition: pmif_spi.h:65
@ E_CLK_EDGE
Definition: pmif_spi.h:113
@ E_CLK_LAST_SETTING
Definition: pmif_spi.h:114
#define DEFAULT_VALUE_READ_TEST
Definition: pmif_spmi.h:9
@ PMIF_WAIT_IDLE_US
Definition: pmif_sw.h:17
uint32_t u32
Definition: stdint.h:51
u32 crc_ctrl
Definition: pmif.h:47
u32 timer_ctrl
Definition: pmif.h:55
u32 other_busy_sta_0
Definition: pmif.h:14
u32 inf_en
Definition: pmif.h:16
u32 other_inf_en
Definition: pmif.h:17
u32 pmic_sig_addr
Definition: pmif.h:50
u32 staupd_ctrl
Definition: pmif.h:26
u32 pmic_eint_sta_addr
Definition: pmif.h:61
u32 init_done
Definition: pmif.h:11
u32 arb_en
Definition: pmif.h:32
u32 inf_busy_sta
Definition: pmif.h:13
u32 sig_mode
Definition: pmif.h:49
void(* write)(struct pmif *arb, u32 slvid, u32 reg, u32 data)
Definition: pmif_common.h:32
void(* read)(struct pmif *arb, u32 slvid, u32 reg, u32 *data)
Definition: pmif_common.h:31
struct mtk_pmif_regs * mtk_pmif
Definition: pmif_common.h:26