Home | History | Annotate | Download | only in pmic
      1 /*
      2  * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
      3  *
      4  * SPDX-License-Identifier: BSD-3-Clause
      5  */
      6 #include <debug.h>
      7 #include <delay_timer.h>
      8 #include <mmio.h>
      9 #include <mt8173_def.h>
     10 #include <pmic_wrap_init.h>
     11 
     12 /* pmic wrap module wait_idle and read polling interval (in microseconds) */
     13 enum {
     14 	WAIT_IDLE_POLLING_DELAY_US	= 1,
     15 	READ_POLLING_DELAY_US		= 2
     16 };
     17 
     18 static inline uint32_t wait_for_state_idle(uint32_t timeout_us,
     19 					   void *wacs_register,
     20 					   void *wacs_vldclr_register,
     21 					   uint32_t *read_reg)
     22 {
     23 	uint32_t reg_rdata;
     24 	uint32_t retry;
     25 
     26 	retry = (timeout_us + WAIT_IDLE_POLLING_DELAY_US) /
     27 		WAIT_IDLE_POLLING_DELAY_US;
     28 
     29 	do {
     30 		udelay(WAIT_IDLE_POLLING_DELAY_US);
     31 		reg_rdata = mmio_read_32((uintptr_t)wacs_register);
     32 		/* if last read command timeout,clear vldclr bit
     33 		   read command state machine:FSM_REQ-->wfdle-->WFVLDCLR;
     34 		   write:FSM_REQ-->idle */
     35 		switch (((reg_rdata >> RDATA_WACS_FSM_SHIFT) &
     36 			RDATA_WACS_FSM_MASK)) {
     37 		case WACS_FSM_WFVLDCLR:
     38 			mmio_write_32((uintptr_t)wacs_vldclr_register, 1);
     39 			ERROR("WACS_FSM = PMIC_WRAP_WACS_VLDCLR\n");
     40 			break;
     41 		case WACS_FSM_WFDLE:
     42 			ERROR("WACS_FSM = WACS_FSM_WFDLE\n");
     43 			break;
     44 		case WACS_FSM_REQ:
     45 			ERROR("WACS_FSM = WACS_FSM_REQ\n");
     46 			break;
     47 		case WACS_FSM_IDLE:
     48 			goto done;
     49 		default:
     50 			break;
     51 		}
     52 
     53 		retry--;
     54 	} while (retry);
     55 
     56 done:
     57 	if (!retry)	/* timeout */
     58 		return E_PWR_WAIT_IDLE_TIMEOUT;
     59 
     60 	if (read_reg)
     61 		*read_reg = reg_rdata;
     62 	return 0;
     63 }
     64 
     65 static inline uint32_t wait_for_state_ready(uint32_t timeout_us,
     66 					    void *wacs_register,
     67 					    uint32_t *read_reg)
     68 {
     69 	uint32_t reg_rdata;
     70 	uint32_t retry;
     71 
     72 	retry = (timeout_us + READ_POLLING_DELAY_US) / READ_POLLING_DELAY_US;
     73 
     74 	do {
     75 		udelay(READ_POLLING_DELAY_US);
     76 		reg_rdata = mmio_read_32((uintptr_t)wacs_register);
     77 
     78 		if (((reg_rdata >> RDATA_WACS_FSM_SHIFT) & RDATA_WACS_FSM_MASK)
     79 		    == WACS_FSM_WFVLDCLR)
     80 			break;
     81 
     82 		retry--;
     83 	} while (retry);
     84 
     85 	if (!retry) {	/* timeout */
     86 		ERROR("timeout when waiting for idle\n");
     87 		return E_PWR_WAIT_IDLE_TIMEOUT_READ;
     88 	}
     89 
     90 	if (read_reg)
     91 		*read_reg = reg_rdata;
     92 	return 0;
     93 }
     94 
     95 static int32_t pwrap_wacs2(uint32_t write,
     96 		    uint32_t adr,
     97 		    uint32_t wdata,
     98 		    uint32_t *rdata,
     99 		    uint32_t init_check)
    100 {
    101 	uint32_t reg_rdata = 0;
    102 	uint32_t wacs_write = 0;
    103 	uint32_t wacs_adr = 0;
    104 	uint32_t wacs_cmd = 0;
    105 	uint32_t return_value = 0;
    106 
    107 	if (init_check) {
    108 		reg_rdata = mmio_read_32((uintptr_t)&mt8173_pwrap->wacs2_rdata);
    109 		/* Prevent someone to used pwrap before pwrap init */
    110 		if (((reg_rdata >> RDATA_INIT_DONE_SHIFT) &
    111 		    RDATA_INIT_DONE_MASK) != WACS_INIT_DONE) {
    112 			ERROR("initialization isn't finished\n");
    113 			return E_PWR_NOT_INIT_DONE;
    114 		}
    115 	}
    116 	reg_rdata = 0;
    117 	/* Check IDLE in advance */
    118 	return_value = wait_for_state_idle(TIMEOUT_WAIT_IDLE,
    119 				&mt8173_pwrap->wacs2_rdata,
    120 				&mt8173_pwrap->wacs2_vldclr,
    121 				0);
    122 	if (return_value != 0) {
    123 		ERROR("wait_for_fsm_idle fail,return_value=%d\n", return_value);
    124 		goto FAIL;
    125 	}
    126 	wacs_write = write << 31;
    127 	wacs_adr = (adr >> 1) << 16;
    128 	wacs_cmd = wacs_write | wacs_adr | wdata;
    129 
    130 	mmio_write_32((uintptr_t)&mt8173_pwrap->wacs2_cmd, wacs_cmd);
    131 	if (write == 0) {
    132 		if (NULL == rdata) {
    133 			ERROR("rdata is a NULL pointer\n");
    134 			return_value = E_PWR_INVALID_ARG;
    135 			goto FAIL;
    136 		}
    137 		return_value = wait_for_state_ready(TIMEOUT_READ,
    138 					&mt8173_pwrap->wacs2_rdata,
    139 					&reg_rdata);
    140 		if (return_value != 0) {
    141 			ERROR("wait_for_fsm_vldclr fail,return_value=%d\n",
    142 				 return_value);
    143 			goto FAIL;
    144 		}
    145 		*rdata = ((reg_rdata >> RDATA_WACS_RDATA_SHIFT)
    146 			  & RDATA_WACS_RDATA_MASK);
    147 		mmio_write_32((uintptr_t)&mt8173_pwrap->wacs2_vldclr, 1);
    148 	}
    149 FAIL:
    150 	return return_value;
    151 }
    152 
    153 /* external API for pmic_wrap user */
    154 
    155 int32_t pwrap_read(uint32_t adr, uint32_t *rdata)
    156 {
    157 	return pwrap_wacs2(0, adr, 0, rdata, 1);
    158 }
    159 
    160 int32_t pwrap_write(uint32_t adr, uint32_t wdata)
    161 {
    162 	return pwrap_wacs2(1, adr, wdata, 0, 1);
    163 }
    164