summaryrefslogtreecommitdiff
path: root/src/soc/mediatek/mt8192/pmif_spi.c
diff options
context:
space:
mode:
authorYidi Lin <yidi.lin@mediatek.com>2021-02-02 21:00:36 +0800
committerHung-Te Lin <hungte@chromium.org>2021-04-28 02:41:43 +0000
commit2368a310be4bf60ea9c83fc89e89be9d6a040775 (patch)
tree9c346d5c793178b25d3bfeceb756cbe3ffcb5d75 /src/soc/mediatek/mt8192/pmif_spi.c
parent15ddb363d4d869fa1c3512e7fbf9682ec41375bf (diff)
soc/mediatek: Move the common part of PMIC drivers to common/
The PMIC drivers can be shared by MT8192 and MT8195. Signed-off-by: Yidi Lin <yidi.lin@mediatek.com> Change-Id: Ie17e01d25405b1e5119d9c70c5f7afb915daf80b Reviewed-on: https://review.coreboot.org/c/coreboot/+/52666 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Yu-Ping Wu <yupingso@google.com>
Diffstat (limited to 'src/soc/mediatek/mt8192/pmif_spi.c')
-rw-r--r--src/soc/mediatek/mt8192/pmif_spi.c322
1 files changed, 2 insertions, 320 deletions
diff --git a/src/soc/mediatek/mt8192/pmif_spi.c b/src/soc/mediatek/mt8192/pmif_spi.c
index 72620041bd..da8c2ad49c 100644
--- a/src/soc/mediatek/mt8192/pmif_spi.c
+++ b/src/soc/mediatek/mt8192/pmif_spi.c
@@ -1,332 +1,14 @@
/* SPDX-License-Identifier: GPL-2.0-only */
-#include <console/console.h>
-#include <delay.h>
#include <device/mmio.h>
-#include <soc/infracfg.h>
-#include <soc/pll.h>
-#include <soc/pmif.h>
+#include <soc/iocfg.h>
#include <soc/pmif_spi.h>
-#include <soc/pmif_sw.h>
-#include <timer.h>
-
-/* PMIF, SPI_MODE_CTRL */
-DEFINE_BIT(SPI_MODE_CTRL_VLD_SRCLK_EN_CTRL, 5)
-DEFINE_BIT(SPI_MODE_CTRL_PMIF_RDY, 9)
-DEFINE_BIT(SPI_MODE_CTRL_SRCLK_EN, 10)
-DEFINE_BIT(SPI_MODE_CTRL_SRVOL_EN, 11)
-
-/* PMIF, SLEEP_PROTECTION_CTRL */
-DEFINE_BITFIELD(SPM_SLEEP_REQ_SEL, 1, 0)
-DEFINE_BITFIELD(SCP_SLEEP_REQ_SEL, 10, 9)
-
-/* PMIF, OTHER_INF_EN */
-DEFINE_BITFIELD(INTGPSADCINF_EN, 5, 4)
-
-/* PMIF, STAUPD_CTRL */
-DEFINE_BITFIELD(STAUPD_CTRL_PRD, 3, 0)
-DEFINE_BIT(STAUPD_CTRL_PMIC0_SIG_STA, 4)
-DEFINE_BIT(STAUPD_CTRL_PMIC0_EINT_STA, 6)
-
-/* SPIMST, Manual_Mode_Access */
-DEFINE_BITFIELD(MAN_ACC_SPI_OP, 12, 8)
-DEFINE_BIT(MAN_ACC_SPI_RW, 13)
/* IOCFG_LM, PWRAP_SPI0_DRIVING */
DEFINE_BITFIELD(PWRAP_SPI0_DRIVING, 2, 0)
-static void pmif_spi_config(struct pmif *arb)
-{
- /* Set srclk_en always valid regardless of ulposc_sel_for_scp */
- SET32_BITFIELDS(&arb->mtk_pmif->spi_mode_ctrl, SPI_MODE_CTRL_VLD_SRCLK_EN_CTRL, 0);
-
- /* Set SPI mode controlled by srclk_en and srvol_en instead of pmif_rdy */
- SET32_BITFIELDS(&arb->mtk_pmif->spi_mode_ctrl,
- SPI_MODE_CTRL_SRCLK_EN, 1,
- SPI_MODE_CTRL_SRVOL_EN, 1,
- SPI_MODE_CTRL_PMIF_RDY, 0);
-
- SET32_BITFIELDS(&arb->mtk_pmif->sleep_protection_ctrl, SPM_SLEEP_REQ_SEL, 0,
- SCP_SLEEP_REQ_SEL, 0);
-
- /* Enable SWINF for AP */
- write32(&arb->mtk_pmif->inf_en, PMIF_SPI_AP);
-
- /* Enable arbitration for SWINF for AP */
- write32(&arb->mtk_pmif->arb_en, PMIF_SPI_AP);
-
- /* Enable PMIF_SPI Command Issue */
- write32(&arb->mtk_pmif->cmdissue_en, 1);
-}
-
-static int check_idle(void *addr, u32 expected)
-{
- u32 reg_rdata;
- struct stopwatch sw;
-
- stopwatch_init_usecs_expire(&sw, PMIF_WAIT_IDLE_US);
- do {
- reg_rdata = read32(addr);
- if (stopwatch_expired(&sw))
- return E_TIMEOUT;
- } while ((reg_rdata & expected) != 0);
-
- return 0;
-}
-
-static int reset_spislv(void)
-{
- u32 pmicspi_mst_dio_en_backup;
-
- write32(&mtk_pmicspi_mst->wrap_en, 0);
- write32(&mtk_pmicspi_mst->mux_sel, 1);
- write32(&mtk_pmicspi_mst->man_en, 1);
- pmicspi_mst_dio_en_backup = read32(&mtk_pmicspi_mst->dio_en);
- write32(&mtk_pmicspi_mst->dio_en, 0);
-
- SET32_BITFIELDS(&mtk_pmicspi_mst->man_acc, MAN_ACC_SPI_RW, OP_WR,
- MAN_ACC_SPI_OP, OP_CSL);
- /* Reset counter */
- SET32_BITFIELDS(&mtk_pmicspi_mst->man_acc, MAN_ACC_SPI_RW, OP_WR,
- MAN_ACC_SPI_OP, OP_OUTS);
- SET32_BITFIELDS(&mtk_pmicspi_mst->man_acc, MAN_ACC_SPI_RW, OP_WR,
- MAN_ACC_SPI_OP, OP_CSH);
- /*
- * In order to pull CSN signal to PMIC,
- * PMIC will count it then reset spi slave
- */
- SET32_BITFIELDS(&mtk_pmicspi_mst->man_acc, MAN_ACC_SPI_RW, OP_WR,
- MAN_ACC_SPI_OP, OP_OUTS);
- SET32_BITFIELDS(&mtk_pmicspi_mst->man_acc, MAN_ACC_SPI_RW, OP_WR,
- MAN_ACC_SPI_OP, OP_OUTS);
- SET32_BITFIELDS(&mtk_pmicspi_mst->man_acc, MAN_ACC_SPI_RW, OP_WR,
- MAN_ACC_SPI_OP, OP_OUTS);
- SET32_BITFIELDS(&mtk_pmicspi_mst->man_acc, MAN_ACC_SPI_RW, OP_WR,
- MAN_ACC_SPI_OP, OP_OUTS);
-
- /* Wait for PMIC SPI Master to be idle */
- if (check_idle(&mtk_pmicspi_mst->other_busy_sta_0, SPIMST_STA)) {
- printk(BIOS_ERR, "[%s] spi master busy, timeout\n", __func__);
- return E_TIMEOUT;
- }
-
- write32(&mtk_pmicspi_mst->man_en, 0);
- write32(&mtk_pmicspi_mst->mux_sel, 0);
- write32(&mtk_pmicspi_mst->wrap_en, 1);
- write32(&mtk_pmicspi_mst->dio_en, pmicspi_mst_dio_en_backup);
-
- return 0;
-}
-
-static void init_reg_clock(struct pmif *arb)
+void pmif_spi_iocfg(void)
{
/* Set SoC SPI IO driving strength to 4 mA */
SET32_BITFIELDS(&mtk_iocfg_lm->drv_cfg1, PWRAP_SPI0_DRIVING, IO_4_MA);
-
- /* Configure SPI protocol */
- write32(&mtk_pmicspi_mst->ext_ck_write, 1);
- write32(&mtk_pmicspi_mst->ext_ck_read, 0);
- write32(&mtk_pmicspi_mst->cshext_write, 0);
- write32(&mtk_pmicspi_mst->cshext_read, 0);
- write32(&mtk_pmicspi_mst->cslext_write, 0);
- write32(&mtk_pmicspi_mst->cslext_read, 0x100);
-
- /* Set Read Dummy Cycle Number (Slave Clock is 18MHz) */
- arb->write(arb, DEFAULT_SLVID, PMIC_DEW_RDDMY_NO, DUMMY_READ_CYCLES);
- write32(&mtk_pmicspi_mst->rddmy, DUMMY_READ_CYCLES);
-
- /* Enable DIO mode */
- arb->write(arb, DEFAULT_SLVID, PMIC_DEW_DIO_EN, 0x1);
-
- /* Wait for completion of sending the commands */
- if (check_idle(&arb->mtk_pmif->inf_busy_sta, PMIF_SPI_AP)) {
- printk(BIOS_ERR, "[%s] pmif channel busy, timeout\n", __func__);
- return;
- }
-
- if (check_idle(&arb->mtk_pmif->other_busy_sta_0, PMIF_CMD_STA)) {
- printk(BIOS_ERR, "[%s] pmif cmd busy, timeout\n", __func__);
- return;
- }
-
- if (check_idle(&mtk_pmicspi_mst->other_busy_sta_0, SPIMST_STA)) {
- printk(BIOS_ERR, "[%s] spi master busy, timeout\n", __func__);
- return;
- }
-
- write32(&mtk_pmicspi_mst->dio_en, 1);
-}
-
-static void init_spislv(struct pmif *arb)
-{
- /* Turn on SPI IO filter function */
- arb->write(arb, DEFAULT_SLVID, PMIC_FILTER_CON0, SPI_FILTER);
- /* Turn on SPI IO SMT function to improve noise immunity */
- arb->write(arb, DEFAULT_SLVID, PMIC_SMT_CON1, SPI_SMT);
- /* Turn off SPI IO pull function for power saving */
- arb->write(arb, DEFAULT_SLVID, PMIC_GPIO_PULLEN0_CLR, SPI_PULL_DISABLE);
- /* Enable SPI access in SODI-3.0 and Suspend modes */
- arb->write(arb, DEFAULT_SLVID, PMIC_RG_SPI_CON0, 0x2);
- /* Set SPI IO driving strength to 4 mA */
- arb->write(arb, DEFAULT_SLVID, PMIC_DRV_CON1, SPI_DRIVING);
-}
-
-static int init_sistrobe(struct pmif *arb)
-{
- u32 rdata = 0;
- int si_sample_ctrl;
- /* Random data for testing */
- const u32 test_data[30] = {
- 0x6996, 0x9669, 0x6996, 0x9669, 0x6996, 0x9669, 0x6996,
- 0x9669, 0x6996, 0x9669, 0x5AA5, 0xA55A, 0x5AA5, 0xA55A,
- 0x5AA5, 0xA55A, 0x5AA5, 0xA55A, 0x5AA5, 0xA55A, 0x1B27,
- 0x1B27, 0x1B27, 0x1B27, 0x1B27, 0x1B27, 0x1B27, 0x1B27,
- 0x1B27, 0x1B27
- };
-
- for (si_sample_ctrl = 0; si_sample_ctrl < 16; si_sample_ctrl++) {
- write32(&mtk_pmicspi_mst->si_sampling_ctrl, si_sample_ctrl << 5);
-
- arb->read(arb, DEFAULT_SLVID, PMIC_DEW_READ_TEST, &rdata);
- if (rdata == DEFAULT_VALUE_READ_TEST)
- break;
- }
-
- if (si_sample_ctrl == 16)
- return E_CLK_EDGE;
-
- if (si_sample_ctrl == 15)
- return E_CLK_LAST_SETTING;
-
- /*
- * Add the delay time of SPI data from PMIC to align the start boundary
- * to current sampling clock edge.
- */
- for (int si_dly = 0; si_dly < 10; si_dly++) {
- arb->write(arb, DEFAULT_SLVID, PMIC_RG_SPI_CON2, si_dly);
-
- int start_boundary_found = 0;
- for (int i = 0; i < ARRAY_SIZE(test_data); i++) {
- arb->write(arb, DEFAULT_SLVID, PMIC_DEW_WRITE_TEST, test_data[i]);
- arb->read(arb, DEFAULT_SLVID, PMIC_DEW_WRITE_TEST, &rdata);
- if ((rdata & 0x7fff) != (test_data[i] & 0x7fff)) {
- start_boundary_found = 1;
- break;
- }
- }
- if (start_boundary_found == 1)
- break;
- }
-
- /*
- * Change the sampling clock edge to the next one which is the middle
- * of SPI data window.
- */
- write32(&mtk_pmicspi_mst->si_sampling_ctrl, ++si_sample_ctrl << 5);
-
- /* Read Test */
- arb->read(arb, DEFAULT_SLVID, PMIC_DEW_READ_TEST, &rdata);
- if (rdata != DEFAULT_VALUE_READ_TEST) {
- printk(BIOS_ERR, "[%s] Failed for read test, data = %#x.\n",
- __func__, rdata);
- return E_READ_TEST_FAIL;
- }
-
- return 0;
-}
-
-static void init_staupd(struct pmif *arb)
-{
- /* Unlock SPI Slave registers */
- arb->write(arb, DEFAULT_SLVID, PMIC_SPISLV_KEY, 0xbade);
-
- /* Enable CRC of PMIC 0 */
- arb->write(arb, DEFAULT_SLVID, PMIC_DEW_CRC_EN, 0x1);
-
- /* Wait for completion of sending the commands */
- if (check_idle(&arb->mtk_pmif->inf_busy_sta, PMIF_SPI_AP)) {
- printk(BIOS_ERR, "[%s] pmif channel busy, timeout\n", __func__);
- return;
- }
-
- if (check_idle(&arb->mtk_pmif->other_busy_sta_0, PMIF_CMD_STA)) {
- printk(BIOS_ERR, "[%s] pmif cmd busy, timeout\n", __func__);
- return;
- }
-
- if (check_idle(&mtk_pmicspi_mst->other_busy_sta_0, SPIMST_STA)) {
- printk(BIOS_ERR, "[%s] spi master busy, timeout\n", __func__);
- return;
- }
-
- /* Configure CRC of PMIC Interface */
- write32(&arb->mtk_pmif->crc_ctrl, 0x1);
- write32(&arb->mtk_pmif->sig_mode, 0x0);
-
- /* Lock SPI Slave registers */
- arb->write(arb, DEFAULT_SLVID, PMIC_SPISLV_KEY, 0x0);
-
- /* Set up PMIC Siganature */
- write32(&arb->mtk_pmif->pmic_sig_addr, PMIC_DEW_CRC_VAL);
-
- /* Set up PMIC EINT */
- write32(&arb->mtk_pmif->pmic_eint_sta_addr, PMIC_INT_STA);
-
- SET32_BITFIELDS(&arb->mtk_pmif->staupd_ctrl,
- STAUPD_CTRL_PRD, 5,
- STAUPD_CTRL_PMIC0_SIG_STA, 1,
- STAUPD_CTRL_PMIC0_EINT_STA, 1);
-}
-
-int pmif_spi_init(struct pmif *arb)
-{
- pmif_spi_config(arb);
-
- /* Reset spislv */
- if (reset_spislv())
- return E_SPI_INIT_RESET_SPI;
-
- /* Enable WRAP */
- write32(&mtk_pmicspi_mst->wrap_en, 0x1);
-
- /* SPI Waveform Configuration */
- init_reg_clock(arb);
-
- /* SPI Slave Configuration */
- init_spislv(arb);
-
- /* Input data calibration flow; */
- if (init_sistrobe(arb)) {
- printk(BIOS_ERR, "[%s] data calibration fail\n", __func__);
- return E_SPI_INIT_SIDLY;
- }
-
- /* Lock SPISLV Registers */
- arb->write(arb, DEFAULT_SLVID, PMIC_SPISLV_KEY, 0x0);
-
- /*
- * Status update function initialization
- * 1. Check signature using CRC (CRC 0 only)
- * 2. Update EINT
- * 3. Read back AUXADC thermal data for GPS
- */
- init_staupd(arb);
-
- /* Configure PMIF Timer */
- write32(&arb->mtk_pmif->timer_ctrl, 0x3);
-
- /* Enable interfaces and arbitration */
- write32(&arb->mtk_pmif->inf_en, PMIF_SPI_HW_INF | PMIF_SPI_MD |
- PMIF_SPI_AP_SECURE | PMIF_SPI_AP);
-
- write32(&arb->mtk_pmif->arb_en, PMIF_SPI_HW_INF | PMIF_SPI_MD | PMIF_SPI_AP_SECURE |
- PMIF_SPI_AP | PMIF_SPI_STAUPD | PMIF_SPI_TSX_HW | PMIF_SPI_DCXO_HW);
-
- /* Enable GPS AUXADC HW 0 and 1 */
- SET32_BITFIELDS(&arb->mtk_pmif->other_inf_en, INTGPSADCINF_EN, 0x3);
-
- /* Set INIT_DONE */
- write32(&arb->mtk_pmif->init_done, 0x1);
-
- return 0;
}