• Antonio Nino Diaz's avatar
    Sanitise includes across codebase · 09d40e0e
    Antonio Nino Diaz authored
    Enforce full include path for includes. Deprecate old paths.
    
    The following folders inside include/lib have been left unchanged:
    
    - include/lib/cpus/${ARCH}
    - include/lib/el3_runtime/${ARCH}
    
    The reason for this change is that having a global namespace for
    includes isn't a good idea. It defeats one of the advantages of having
    folders and it introduces problems that are sometimes subtle (because
    you may not know the header you are actually including if there are two
    of them).
    
    For example, this patch had to be created because two headers were
    called the same way: e0ea0928 ("Fix gpio includes of mt8173 platform
    to avoid collision."). More recently, this patch has had similar
    problems: 46f9b2c3 ("drivers: add tzc380 support").
    
    This problem was introduced in commit 4ecca339 ("Move include and
    source files to logical locations"). At that time, there weren't too
    many headers so it wasn't a real issue. However, time has shown that
    this creates problems.
    
    Platforms t...
    09d40e0e
pmic_wrap_init.c 3.84 KB
/*
 * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <common/debug.h>
#include <drivers/delay_timer.h>
#include <lib/mmio.h>

#include <mt8173_def.h>
#include <pmic_wrap_init.h>

/* pmic wrap module wait_idle and read polling interval (in microseconds) */
enum {
	WAIT_IDLE_POLLING_DELAY_US	= 1,
	READ_POLLING_DELAY_US		= 2
};

static inline uint32_t wait_for_state_idle(uint32_t timeout_us,
					   void *wacs_register,
					   void *wacs_vldclr_register,
					   uint32_t *read_reg)
{
	uint32_t reg_rdata;
	uint32_t retry;

	retry = (timeout_us + WAIT_IDLE_POLLING_DELAY_US) /
		WAIT_IDLE_POLLING_DELAY_US;

	do {
		udelay(WAIT_IDLE_POLLING_DELAY_US);
		reg_rdata = mmio_read_32((uintptr_t)wacs_register);
		/* if last read command timeout,clear vldclr bit
		   read command state machine:FSM_REQ-->wfdle-->WFVLDCLR;
		   write:FSM_REQ-->idle */
		switch (((reg_rdata >> RDATA_WACS_FSM_SHIFT) &
			RDATA_WACS_FSM_MASK)) {
		case WACS_FSM_WFVLDCLR:
			mmio_write_32((uintptr_t)wacs_vldclr_register, 1);
			ERROR("WACS_FSM = PMIC_WRAP_WACS_VLDCLR\n");
			break;
		case WACS_FSM_WFDLE:
			ERROR("WACS_FSM = WACS_FSM_WFDLE\n");
			break;
		case WACS_FSM_REQ:
			ERROR("WACS_FSM = WACS_FSM_REQ\n");
			break;
		case WACS_FSM_IDLE:
			goto done;
		default:
			break;
		}

		retry--;
	} while (retry);

done:
	if (!retry)	/* timeout */
		return E_PWR_WAIT_IDLE_TIMEOUT;

	if (read_reg)
		*read_reg = reg_rdata;
	return 0;
}

static inline uint32_t wait_for_state_ready(uint32_t timeout_us,
					    void *wacs_register,
					    uint32_t *read_reg)
{
	uint32_t reg_rdata;
	uint32_t retry;

	retry = (timeout_us + READ_POLLING_DELAY_US) / READ_POLLING_DELAY_US;

	do {
		udelay(READ_POLLING_DELAY_US);
		reg_rdata = mmio_read_32((uintptr_t)wacs_register);

		if (((reg_rdata >> RDATA_WACS_FSM_SHIFT) & RDATA_WACS_FSM_MASK)
		    == WACS_FSM_WFVLDCLR)
			break;

		retry--;
	} while (retry);

	if (!retry) {	/* timeout */
		ERROR("timeout when waiting for idle\n");
		return E_PWR_WAIT_IDLE_TIMEOUT_READ;
	}

	if (read_reg)
		*read_reg = reg_rdata;
	return 0;
}

static int32_t pwrap_wacs2(uint32_t write,
		    uint32_t adr,
		    uint32_t wdata,
		    uint32_t *rdata,
		    uint32_t init_check)
{
	uint32_t reg_rdata = 0;
	uint32_t wacs_write = 0;
	uint32_t wacs_adr = 0;
	uint32_t wacs_cmd = 0;
	uint32_t return_value = 0;

	if (init_check) {
		reg_rdata = mmio_read_32((uintptr_t)&mt8173_pwrap->wacs2_rdata);
		/* Prevent someone to used pwrap before pwrap init */
		if (((reg_rdata >> RDATA_INIT_DONE_SHIFT) &
		    RDATA_INIT_DONE_MASK) != WACS_INIT_DONE) {
			ERROR("initialization isn't finished\n");
			return E_PWR_NOT_INIT_DONE;
		}
	}
	reg_rdata = 0;
	/* Check IDLE in advance */
	return_value = wait_for_state_idle(TIMEOUT_WAIT_IDLE,
				&mt8173_pwrap->wacs2_rdata,
				&mt8173_pwrap->wacs2_vldclr,
				0);
	if (return_value != 0) {
		ERROR("wait_for_fsm_idle fail,return_value=%d\n", return_value);
		goto FAIL;
	}
	wacs_write = write << 31;
	wacs_adr = (adr >> 1) << 16;
	wacs_cmd = wacs_write | wacs_adr | wdata;

	mmio_write_32((uintptr_t)&mt8173_pwrap->wacs2_cmd, wacs_cmd);
	if (write == 0) {
		if (NULL == rdata) {
			ERROR("rdata is a NULL pointer\n");
			return_value = E_PWR_INVALID_ARG;
			goto FAIL;
		}
		return_value = wait_for_state_ready(TIMEOUT_READ,
					&mt8173_pwrap->wacs2_rdata,
					&reg_rdata);
		if (return_value != 0) {
			ERROR("wait_for_fsm_vldclr fail,return_value=%d\n",
				 return_value);
			goto FAIL;
		}
		*rdata = ((reg_rdata >> RDATA_WACS_RDATA_SHIFT)
			  & RDATA_WACS_RDATA_MASK);
		mmio_write_32((uintptr_t)&mt8173_pwrap->wacs2_vldclr, 1);
	}
FAIL:
	return return_value;
}

/* external API for pmic_wrap user */

int32_t pwrap_read(uint32_t adr, uint32_t *rdata)
{
	return pwrap_wacs2(0, adr, 0, rdata, 1);
}

int32_t pwrap_write(uint32_t adr, uint32_t wdata)
{
	return pwrap_wacs2(1, adr, wdata, 0, 1);
}