blob: 5a359c7dddf04cc185496389e6c5778d74b03c7f [file] [log] [blame]
/* SPDX-License-Identifier: GPL-2.0-only */
#include <console/console.h>
#include <device/mmio.h>
#include <soc/addressmap.h>
#include <soc/pmif.h>
#include <soc/pmif_spmi.h>
#include <soc/pmif_sw.h>
#include <soc/spmi.h>
/* SPMI_MST, SPMI_SAMPL_CTRL */
DEFINE_BIT(SAMPL_CK_POL, 0)
DEFINE_BITFIELD(SAMPL_CK_DLY, 3, 1)
/* PMIF, SPI_MODE_CTRL */
DEFINE_BIT(SPI_MODE_CTRL, 7)
DEFINE_BIT(SRVOL_EN, 11)
DEFINE_BIT(SPI_MODE_EXT_CMD, 12)
DEFINE_BIT(SPI_EINT_MODE_GATING_EN, 13)
/* PMIF, SLEEP_PROTECTION_CTRL */
DEFINE_BITFIELD(SPM_SLEEP_REQ_SEL, 1, 0)
DEFINE_BITFIELD(SCP_SLEEP_REQ_SEL, 10, 9)
__weak void pmif_spmi_config(struct pmif *arb, int mstid)
{
/* Do nothing. */
}
static int spmi_read_check(struct pmif *pmif_arb, int slvid)
{
u32 rdata = 0;
pmif_arb->read(pmif_arb, slvid, MT6315_READ_TEST, &rdata);
if (rdata != MT6315_DEFAULT_VALUE_READ) {
printk(BIOS_INFO, "%s next, slvid:%d rdata = 0x%x.\n",
__func__, slvid, rdata);
return -E_NODEV;
}
pmif_arb->read(pmif_arb, slvid, MT6315_READ_TEST_1, &rdata);
if (rdata != MT6315_DEFAULT_VALUE_READ) {
printk(BIOS_INFO, "%s next, slvid:%d rdata = 0x%x.\n",
__func__, slvid, rdata);
return -E_NODEV;
}
return 0;
}
static int spmi_cali_rd_clock_polarity(struct pmif *pmif_arb, const struct spmi_device *dev)
{
int i;
bool success = false;
const struct cali cali_data[] = {
{SPMI_CK_DLY_1T, SPMI_CK_POL_POS},
{SPMI_CK_NO_DLY, SPMI_CK_POL_POS},
{SPMI_CK_NO_DLY, SPMI_CK_POL_NEG},
{SPMI_CK_DLY_1T, SPMI_CK_POL_NEG},
};
/* Indicate sampling clock polarity, 1: Positive 0: Negative */
for (i = 0; i < ARRAY_SIZE(cali_data); i++) {
SET32_BITFIELDS(&mtk_spmi_mst->mst_sampl, SAMPL_CK_DLY, cali_data[i].dly,
SAMPL_CK_POL, cali_data[i].pol);
if (spmi_read_check(pmif_arb, dev->slvid) == 0) {
success = true;
break;
}
}
if (!success)
die("ERROR - calibration fail for spmi clk");
return 0;
}
static int spmi_mst_init(struct pmif *pmif_arb)
{
size_t i;
if (!pmif_arb) {
printk(BIOS_ERR, "%s: null pointer for pmif dev.\n", __func__);
return -E_INVAL;
}
if (!CONFIG(PMIF_SPMI_IOCFG_DEFAULT_SETTING))
pmif_spmi_iocfg();
spmi_config_master();
for (i = 0; i < spmi_dev_cnt; i++)
spmi_cali_rd_clock_polarity(pmif_arb, &spmi_dev[i]);
return 0;
}
static void pmif_spmi_force_normal_mode(int mstid)
{
struct pmif *arb = get_pmif_controller(PMIF_SPMI, mstid);
/* listen srclken_0 only for entering normal or sleep mode */
SET32_BITFIELDS(&arb->mtk_pmif->spi_mode_ctrl,
SPI_MODE_CTRL, 0,
SRVOL_EN, 0,
SPI_MODE_EXT_CMD, 1,
SPI_EINT_MODE_GATING_EN, 1);
/* enable spm/scp sleep request */
SET32_BITFIELDS(&arb->mtk_pmif->sleep_protection_ctrl, SPM_SLEEP_REQ_SEL, 0,
SCP_SLEEP_REQ_SEL, 0);
}
static void pmif_spmi_enable_swinf(int mstid)
{
struct pmif *arb = get_pmif_controller(PMIF_SPMI, mstid);
write32(&arb->mtk_pmif->inf_en, PMIF_SPMI_SW_CHAN);
write32(&arb->mtk_pmif->arb_en, PMIF_SPMI_SW_CHAN);
}
static void pmif_spmi_enable_cmdIssue(int mstid, bool en)
{
struct pmif *arb = get_pmif_controller(PMIF_SPMI, mstid);
/* Enable cmdIssue */
write32(&arb->mtk_pmif->cmdissue_en, en);
}
static void pmif_spmi_enable(int mstid)
{
struct pmif *arb = get_pmif_controller(PMIF_SPMI, mstid);
pmif_spmi_config(arb, mstid);
/*
* set bytecnt max limitation.
* hw bytecnt indicate when we set 0, it can send 1 byte;
* set 1, it can send 2 byte.
*/
write32(&arb->mtk_pmif->inf_max_bytecnt_per_0, 0);
write32(&arb->mtk_pmif->inf_max_bytecnt_per_1, 0);
write32(&arb->mtk_pmif->inf_max_bytecnt_per_2, 0);
write32(&arb->mtk_pmif->inf_max_bytecnt_per_3, 0);
/* Add latency limitation */
write32(&arb->mtk_pmif->lat_cnter_en, PMIF_SPMI_INF);
write32(&arb->mtk_pmif->lat_limit_0, 0);
write32(&arb->mtk_pmif->lat_limit_1, 0x4);
write32(&arb->mtk_pmif->lat_limit_2, 0x8);
write32(&arb->mtk_pmif->lat_limit_4, 0x8);
write32(&arb->mtk_pmif->lat_limit_6, 0x3FF);
write32(&arb->mtk_pmif->lat_limit_9, 0x4);
write32(&arb->mtk_pmif->lat_limit_loading, PMIF_SPMI_INF);
write32(&arb->mtk_pmif->inf_en, PMIF_SPMI_INF);
write32(&arb->mtk_pmif->arb_en, PMIF_SPMI_INF);
write32(&arb->mtk_pmif->timer_ctrl, 0x3);
write32(&arb->mtk_pmif->init_done, 1);
}
int pmif_spmi_init(struct pmif *arb)
{
if (arb->is_pmif_init_done(arb) != 0) {
pmif_spmi_force_normal_mode(arb->mstid);
pmif_spmi_enable_swinf(arb->mstid);
pmif_spmi_enable_cmdIssue(arb->mstid, true);
pmif_spmi_enable(arb->mstid);
if (arb->is_pmif_init_done(arb))
return -E_NODEV;
}
if (spmi_mst_init(arb)) {
printk(BIOS_ERR, "[%s] failed to init spmi master\n", __func__);
return -E_NODEV;
}
return 0;
}