soc/mediatek/mt8192: add pmif driver
MT8192 uses power management interface (PMIF) to access pmics by spmi and spi, so we add pmif driver to control pmics. BUG=b:155253454 BRANCH=none TEST=boot asurada correctly Signed-off-by: Hsin-Hsiung Wang <hsin-hsiung.wang@mediatek.com> Change-Id: I32fc28f72d9522133baa06f9d67c383f814d862c Reviewed-on: https://review.coreboot.org/c/coreboot/+/45398 Reviewed-by: Hung-Te Lin <hungte@chromium.org> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
committed by
Hung-Te Lin
parent
ec6cff2f20
commit
22f8370def
@@ -9,6 +9,7 @@ bootblock-$(CONFIG_SPI_FLASH) += ../common/spi.c spi.c
|
|||||||
bootblock-y += ../common/timer.c
|
bootblock-y += ../common/timer.c
|
||||||
bootblock-y += ../common/uart.c
|
bootblock-y += ../common/uart.c
|
||||||
bootblock-y += ../common/wdt.c
|
bootblock-y += ../common/wdt.c
|
||||||
|
bootblock-y += pmif.c pmif_clk.c pmif_spi.c pmif_spmi.c
|
||||||
|
|
||||||
verstage-y += flash_controller.c
|
verstage-y += flash_controller.c
|
||||||
verstage-y += ../common/gpio.c gpio.c
|
verstage-y += ../common/gpio.c gpio.c
|
||||||
|
@@ -3,6 +3,7 @@
|
|||||||
#include <bootblock_common.h>
|
#include <bootblock_common.h>
|
||||||
#include <soc/mmu_operations.h>
|
#include <soc/mmu_operations.h>
|
||||||
#include <soc/pll.h>
|
#include <soc/pll.h>
|
||||||
|
#include <soc/pmif.h>
|
||||||
#include <soc/wdt.h>
|
#include <soc/wdt.h>
|
||||||
|
|
||||||
void bootblock_soc_init(void)
|
void bootblock_soc_init(void)
|
||||||
@@ -10,4 +11,5 @@ void bootblock_soc_init(void)
|
|||||||
mtk_mmu_init();
|
mtk_mmu_init();
|
||||||
mtk_wdt_init();
|
mtk_wdt_init();
|
||||||
mt_pll_init();
|
mt_pll_init();
|
||||||
|
mtk_pmif_init();
|
||||||
}
|
}
|
||||||
|
@@ -21,7 +21,10 @@ enum {
|
|||||||
GPT_BASE = IO_PHYS + 0x00008000,
|
GPT_BASE = IO_PHYS + 0x00008000,
|
||||||
EINT_BASE = IO_PHYS + 0x0000B000,
|
EINT_BASE = IO_PHYS + 0x0000B000,
|
||||||
APMIXED_BASE = IO_PHYS + 0x0000C000,
|
APMIXED_BASE = IO_PHYS + 0x0000C000,
|
||||||
PWRAP_BASE = IO_PHYS + 0x0000D000,
|
PMIF_SPI_BASE = IO_PHYS + 0x00026000,
|
||||||
|
PMIF_SPMI_BASE = IO_PHYS + 0x00027000,
|
||||||
|
PMICSPI_MST_BASE = IO_PHYS + 0x00028000,
|
||||||
|
SPMI_MST_BASE = IO_PHYS + 0x00029000,
|
||||||
UART0_BASE = IO_PHYS + 0x01002000,
|
UART0_BASE = IO_PHYS + 0x01002000,
|
||||||
SPI0_BASE = IO_PHYS + 0x0100A000,
|
SPI0_BASE = IO_PHYS + 0x0100A000,
|
||||||
SPI1_BASE = IO_PHYS + 0x01010000,
|
SPI1_BASE = IO_PHYS + 0x01010000,
|
||||||
|
@@ -178,7 +178,11 @@ struct mtk_apmixed_regs {
|
|||||||
u32 mfgpll_con2;
|
u32 mfgpll_con2;
|
||||||
u32 mfgpll_con3;
|
u32 mfgpll_con3;
|
||||||
u32 ap_pllgp1_con2;
|
u32 ap_pllgp1_con2;
|
||||||
u32 reserved2[33];
|
u32 reserved2[13];
|
||||||
|
u32 ulposc1_con0;
|
||||||
|
u32 ulposc1_con1;
|
||||||
|
u32 ulposc1_con2;
|
||||||
|
u32 reserved3[17];
|
||||||
u32 ap_pllgp2_con0; /* 0x0300 */
|
u32 ap_pllgp2_con0; /* 0x0300 */
|
||||||
u32 ap_pllgp2_con1;
|
u32 ap_pllgp2_con1;
|
||||||
u32 univpll_con0;
|
u32 univpll_con0;
|
||||||
|
172
src/soc/mediatek/mt8192/include/soc/pmif.h
Normal file
172
src/soc/mediatek/mt8192/include/soc/pmif.h
Normal file
@@ -0,0 +1,172 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
|
||||||
|
#ifndef __MT8192_SOC_PMIF_H__
|
||||||
|
#define __MT8192_SOC_PMIF_H__
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PMIF_CMD_REG_0,
|
||||||
|
PMIF_CMD_REG,
|
||||||
|
PMIF_CMD_EXT_REG,
|
||||||
|
PMIF_CMD_EXT_REG_LONG,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mtk_pmif_regs {
|
||||||
|
u32 init_done;
|
||||||
|
u32 reserved1[5];
|
||||||
|
u32 inf_busy_sta;
|
||||||
|
u32 other_busy_sta_0;
|
||||||
|
u32 other_busy_sta_1;
|
||||||
|
u32 inf_en;
|
||||||
|
u32 other_inf_en;
|
||||||
|
u32 inf_cmd_per_0;
|
||||||
|
u32 inf_cmd_per_1;
|
||||||
|
u32 inf_cmd_per_2;
|
||||||
|
u32 inf_cmd_per_3;
|
||||||
|
u32 inf_max_bytecnt_per_0;
|
||||||
|
u32 inf_max_bytecnt_per_1;
|
||||||
|
u32 inf_max_bytecnt_per_2;
|
||||||
|
u32 inf_max_bytecnt_per_3;
|
||||||
|
u32 staupd_ctrl;
|
||||||
|
u32 reserved2[48];
|
||||||
|
u32 int_gps_auxadc_cmd_addr;
|
||||||
|
u32 int_gps_auxadc_cmd;
|
||||||
|
u32 int_gps_auxadc_rdata_addr;
|
||||||
|
u32 reserved3[13];
|
||||||
|
u32 arb_en;
|
||||||
|
u32 reserved4[34];
|
||||||
|
u32 lat_cnter_en;
|
||||||
|
u32 lat_limit_loading;
|
||||||
|
u32 lat_limit_0;
|
||||||
|
u32 lat_limit_1;
|
||||||
|
u32 lat_limit_2;
|
||||||
|
u32 lat_limit_3;
|
||||||
|
u32 lat_limit_4;
|
||||||
|
u32 lat_limit_5;
|
||||||
|
u32 lat_limit_6;
|
||||||
|
u32 lat_limit_7;
|
||||||
|
u32 lat_limit_8;
|
||||||
|
u32 lat_limit_9;
|
||||||
|
u32 reserved5[99];
|
||||||
|
u32 crc_ctrl;
|
||||||
|
u32 crc_sta;
|
||||||
|
u32 sig_mode;
|
||||||
|
u32 pmic_sig_addr;
|
||||||
|
u32 pmic_sig_val;
|
||||||
|
u32 reserved6[2];
|
||||||
|
u32 cmdissue_en;
|
||||||
|
u32 reserved7[10];
|
||||||
|
u32 timer_ctrl;
|
||||||
|
u32 timer_sta;
|
||||||
|
u32 sleep_protection_ctrl;
|
||||||
|
u32 reserved8[5];
|
||||||
|
u32 spi_mode_ctrl;
|
||||||
|
u32 reserved9[2];
|
||||||
|
u32 pmic_eint_sta_addr;
|
||||||
|
u32 reserved10[2];
|
||||||
|
u32 irq_event_en_0;
|
||||||
|
u32 irq_flag_raw_0;
|
||||||
|
u32 irq_flag_0;
|
||||||
|
u32 irq_clr_0;
|
||||||
|
u32 reserved11[502];
|
||||||
|
u32 swinf_0_acc;
|
||||||
|
u32 swinf_0_wdata_31_0;
|
||||||
|
u32 swinf_0_wdata_63_32;
|
||||||
|
u32 reserved12[2];
|
||||||
|
u32 swinf_0_rdata_31_0;
|
||||||
|
u32 swinf_0_rdata_63_32;
|
||||||
|
u32 reserved13[2];
|
||||||
|
u32 swinf_0_vld_clr;
|
||||||
|
u32 swinf_0_sta;
|
||||||
|
u32 reserved14[5];
|
||||||
|
u32 swinf_1_acc;
|
||||||
|
u32 swinf_1_wdata_31_0;
|
||||||
|
u32 swinf_1_wdata_63_32;
|
||||||
|
u32 reserved15[2];
|
||||||
|
u32 swinf_1_rdata_31_0;
|
||||||
|
u32 swinf_1_rdata_63_32;
|
||||||
|
u32 reserved16[2];
|
||||||
|
u32 swinf_1_vld_clr;
|
||||||
|
u32 swinf_1_sta;
|
||||||
|
u32 reserved17[5];
|
||||||
|
u32 swinf_2_acc;
|
||||||
|
u32 swinf_2_wdata_31_0;
|
||||||
|
u32 swinf_2_wdata_63_32;
|
||||||
|
u32 reserved18[2];
|
||||||
|
u32 swinf_2_rdata_31_0;
|
||||||
|
u32 swinf_2_rdata_63_32;
|
||||||
|
u32 reserved19[2];
|
||||||
|
u32 swinf_2_vld_clr;
|
||||||
|
u32 swinf_2_sta;
|
||||||
|
u32 reserved20[5];
|
||||||
|
u32 swinf_3_acc;
|
||||||
|
u32 swinf_3_wdata_31_0;
|
||||||
|
u32 swinf_3_wdata_63_32;
|
||||||
|
u32 reserved21[2];
|
||||||
|
u32 swinf_3_rdata_31_0;
|
||||||
|
u32 swinf_3_rdata_63_32;
|
||||||
|
u32 reserved22[2];
|
||||||
|
u32 swinf_3_vld_clr;
|
||||||
|
u32 swinf_3_sta;
|
||||||
|
u32 reserved23[133];
|
||||||
|
};
|
||||||
|
|
||||||
|
check_member(mtk_pmif_regs, inf_busy_sta, 0x18);
|
||||||
|
check_member(mtk_pmif_regs, int_gps_auxadc_cmd_addr, 0x110);
|
||||||
|
check_member(mtk_pmif_regs, arb_en, 0x0150);
|
||||||
|
check_member(mtk_pmif_regs, lat_cnter_en, 0x1DC);
|
||||||
|
check_member(mtk_pmif_regs, crc_ctrl, 0x398);
|
||||||
|
check_member(mtk_pmif_regs, cmdissue_en, 0x3B4);
|
||||||
|
check_member(mtk_pmif_regs, timer_ctrl, 0x3E0);
|
||||||
|
check_member(mtk_pmif_regs, spi_mode_ctrl, 0x400);
|
||||||
|
check_member(mtk_pmif_regs, pmic_eint_sta_addr, 0x40C);
|
||||||
|
check_member(mtk_pmif_regs, irq_event_en_0, 0x418);
|
||||||
|
check_member(mtk_pmif_regs, swinf_0_acc, 0xC00);
|
||||||
|
|
||||||
|
#define PMIF_SPMI_AP_CHAN (PMIF_SPMI_BASE + 0xC80)
|
||||||
|
#define PMIF_SPI_AP_CHAN (PMIF_SPI_BASE + 0xC80)
|
||||||
|
|
||||||
|
struct chan_regs {
|
||||||
|
u32 ch_send;
|
||||||
|
u32 wdata;
|
||||||
|
u32 reserved12[3];
|
||||||
|
u32 rdata;
|
||||||
|
u32 reserved13[3];
|
||||||
|
u32 ch_rdy;
|
||||||
|
u32 ch_sta;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pmif {
|
||||||
|
struct mtk_pmif_regs *mtk_pmif;
|
||||||
|
struct chan_regs *ch;
|
||||||
|
u32 swinf_no;
|
||||||
|
u32 mstid;
|
||||||
|
u32 pmifid;
|
||||||
|
void (*read)(struct pmif *arb, u32 slvid, u32 reg, u32 *data);
|
||||||
|
void (*write)(struct pmif *arb, u32 slvid, u32 reg, u32 data);
|
||||||
|
u32 (*read_field)(struct pmif *arb, u32 slvid, u32 reg, u32 mask, u32 shift);
|
||||||
|
void (*write_field)(struct pmif *arb, u32 slvid, u32 reg, u32 val, u32 mask, u32 shift);
|
||||||
|
int (*is_pmif_init_done)(struct pmif *arb);
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PMIF_SPI,
|
||||||
|
PMIF_SPMI,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
E_IO = 1, /* I/O error */
|
||||||
|
E_BUSY, /* Device or resource busy */
|
||||||
|
E_NODEV, /* No such device */
|
||||||
|
E_INVAL, /* Invalid argument */
|
||||||
|
E_OPNOTSUPP, /* Operation not supported on transport endpoint */
|
||||||
|
E_TIMEOUT, /* Wait for idle time out */
|
||||||
|
E_READ_TEST_FAIL, /* SPI read fail */
|
||||||
|
E_SPI_INIT_RESET_SPI, /* Reset SPI fail */
|
||||||
|
E_SPI_INIT_SIDLY, /* SPI edge calibration fail */
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct pmif *get_pmif_controller(int inf, int mstid);
|
||||||
|
extern int mtk_pmif_init(void);
|
||||||
|
#endif /*__MT8192_SOC_PMIF_H__*/
|
125
src/soc/mediatek/mt8192/include/soc/pmif_spi.h
Normal file
125
src/soc/mediatek/mt8192/include/soc/pmif_spi.h
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
|
||||||
|
#ifndef __SOC_MEDIATEK_MT8192_PMIC_WRAP_H__
|
||||||
|
#define __SOC_MEDIATEK_MT8192_PMIC_WRAP_H__
|
||||||
|
|
||||||
|
#include <soc/addressmap.h>
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
struct mt8192_pmicspi_mst_regs {
|
||||||
|
u32 reserved1[4];
|
||||||
|
u32 other_busy_sta_0;
|
||||||
|
u32 wrap_en;
|
||||||
|
u32 reserved2[2];
|
||||||
|
u32 man_en;
|
||||||
|
u32 man_acc;
|
||||||
|
u32 reserved3[3];
|
||||||
|
u32 mux_sel;
|
||||||
|
u32 reserved4[3];
|
||||||
|
u32 dio_en;
|
||||||
|
u32 rddmy;
|
||||||
|
u32 cslext_write;
|
||||||
|
u32 cslext_read;
|
||||||
|
u32 cshext_write;
|
||||||
|
u32 cshext_read;
|
||||||
|
u32 ext_ck_write;
|
||||||
|
u32 ext_ck_read;
|
||||||
|
u32 si_sampling_ctrl;
|
||||||
|
};
|
||||||
|
|
||||||
|
check_member(mt8192_pmicspi_mst_regs, other_busy_sta_0, 0x10);
|
||||||
|
check_member(mt8192_pmicspi_mst_regs, man_en, 0x20);
|
||||||
|
check_member(mt8192_pmicspi_mst_regs, mux_sel, 0x34);
|
||||||
|
check_member(mt8192_pmicspi_mst_regs, dio_en, 0x44);
|
||||||
|
|
||||||
|
static struct mt8192_pmicspi_mst_regs * const mtk_pmicspi_mst = (void *)PMICSPI_MST_BASE;
|
||||||
|
|
||||||
|
struct mt8192_iocfg_lm_regs {
|
||||||
|
u32 reserved[4];
|
||||||
|
u32 drv_cfg1;
|
||||||
|
};
|
||||||
|
check_member(mt8192_iocfg_lm_regs, drv_cfg1, 0x10);
|
||||||
|
|
||||||
|
static struct mt8192_iocfg_lm_regs * const mtk_iocfg_lm = (void *)IOCFG_LM_BASE;
|
||||||
|
|
||||||
|
/* PMIC registers */
|
||||||
|
enum {
|
||||||
|
PMIC_BASE = 0x0000,
|
||||||
|
PMIC_SMT_CON1 = PMIC_BASE + 0x0032,
|
||||||
|
PMIC_DRV_CON1 = PMIC_BASE + 0x003a,
|
||||||
|
PMIC_FILTER_CON0 = PMIC_BASE + 0x0042,
|
||||||
|
PMIC_GPIO_PULLEN0_CLR = PMIC_BASE + 0x0098,
|
||||||
|
PMIC_RG_SPI_CON0 = PMIC_BASE + 0x0408,
|
||||||
|
PMIC_DEW_DIO_EN = PMIC_BASE + 0x040c,
|
||||||
|
PMIC_DEW_READ_TEST = PMIC_BASE + 0x040e,
|
||||||
|
PMIC_DEW_WRITE_TEST = PMIC_BASE + 0x0410,
|
||||||
|
PMIC_DEW_CRC_EN = PMIC_BASE + 0x0414,
|
||||||
|
PMIC_DEW_CRC_VAL = PMIC_BASE + 0x0416,
|
||||||
|
PMIC_DEW_RDDMY_NO = PMIC_BASE + 0x0424,
|
||||||
|
PMIC_RG_SPI_CON2 = PMIC_BASE + 0x0426,
|
||||||
|
PMIC_SPISLV_KEY = PMIC_BASE + 0x044a,
|
||||||
|
PMIC_INT_STA = PMIC_BASE + 0x0452,
|
||||||
|
PMIC_AUXADC_ADC7 = PMIC_BASE + 0x1096,
|
||||||
|
PMIC_AUXADC_ADC10 = PMIC_BASE + 0x109c,
|
||||||
|
PMIC_AUXADC_RQST0 = PMIC_BASE + 0x1108,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define PMIF_SPI_HW_INF 0x307F
|
||||||
|
#define PMIF_SPI_MD BIT(8)
|
||||||
|
#define PMIF_SPI_AP_SECURE BIT(9)
|
||||||
|
#define PMIF_SPI_AP BIT(10)
|
||||||
|
#define PMIF_SPI_STAUPD BIT(14)
|
||||||
|
#define PMIF_SPI_TSX_HW BIT(19)
|
||||||
|
#define PMIF_SPI_DCXO_HW BIT(20)
|
||||||
|
|
||||||
|
#define DEFAULT_SLVID 0
|
||||||
|
|
||||||
|
#define PMIF_CMD_STA BIT(2)
|
||||||
|
#define SPIMST_STA BIT(9)
|
||||||
|
|
||||||
|
enum {
|
||||||
|
SPI_CLK = 0x1,
|
||||||
|
SPI_CSN = 0x1 << 1,
|
||||||
|
SPI_MOSI = 0x1 << 2,
|
||||||
|
SPI_MISO = 0x1 << 3,
|
||||||
|
SPI_FILTER = (SPI_CLK | SPI_CSN | SPI_MOSI | SPI_MISO) << 4,
|
||||||
|
SPI_SMT = SPI_CLK | SPI_CSN | SPI_MOSI | SPI_MISO,
|
||||||
|
SPI_PULL_DISABLE = (SPI_CLK | SPI_CSN | SPI_MOSI | SPI_MISO) << 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
IO_4_MA = 0x1,
|
||||||
|
SLV_IO_4_MA = 0x8,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
SPI_CLK_SHIFT = 0,
|
||||||
|
SPI_CSN_SHIFT = 4,
|
||||||
|
SPI_MOSI_SHIFT = 8,
|
||||||
|
SPI_MISO_SHIFT = 12,
|
||||||
|
SPI_DRIVING = SLV_IO_4_MA << SPI_CLK_SHIFT | SLV_IO_4_MA << SPI_CSN_SHIFT |
|
||||||
|
SLV_IO_4_MA << SPI_MOSI_SHIFT | SLV_IO_4_MA << SPI_MISO_SHIFT,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
OP_WR = 0x1,
|
||||||
|
OP_CSH = 0x0,
|
||||||
|
OP_CSL = 0x1,
|
||||||
|
OP_OUTS = 0x8,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
DEFAULT_VALUE_READ_TEST = 0x5aa5,
|
||||||
|
WRITE_TEST_VALUE = 0xa55a,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
DUMMY_READ_CYCLES = 0x8,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
E_CLK_EDGE = 1,
|
||||||
|
E_CLK_LAST_SETTING,
|
||||||
|
};
|
||||||
|
extern int pmif_spi_init(struct pmif *arb);
|
||||||
|
#endif /* __SOC_MEDIATEK_MT8192_PMIC_WRAP_H__ */
|
99
src/soc/mediatek/mt8192/include/soc/pmif_spmi.h
Normal file
99
src/soc/mediatek/mt8192/include/soc/pmif_spmi.h
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
|
||||||
|
#ifndef __PMIF_SPMI_H__
|
||||||
|
#define __PMIF_SPMI_H__
|
||||||
|
|
||||||
|
#include <soc/addressmap.h>
|
||||||
|
|
||||||
|
#define DEFAULT_VALUE_READ_TEST (0x5a)
|
||||||
|
#define DEFAULT_VALUE_WRITE_TEST (0xa5)
|
||||||
|
|
||||||
|
/* indicate which number SW channel start, by project */
|
||||||
|
#define PMIF_SPMI_SW_CHAN BIT(6)
|
||||||
|
#define PMIF_SPMI_INF 0x2F7
|
||||||
|
|
||||||
|
struct mtk_rgu_regs {
|
||||||
|
u32 reserved[36];
|
||||||
|
u32 wdt_swsysrst2;
|
||||||
|
};
|
||||||
|
check_member(mtk_rgu_regs, wdt_swsysrst2, 0x90);
|
||||||
|
|
||||||
|
struct mtk_iocfg_bm_regs {
|
||||||
|
u32 reserved[8];
|
||||||
|
u32 drv_cfg2;
|
||||||
|
};
|
||||||
|
check_member(mtk_iocfg_bm_regs, drv_cfg2, 0x20);
|
||||||
|
|
||||||
|
struct mtk_spm_regs {
|
||||||
|
u32 poweron_config_en;
|
||||||
|
u32 reserved[263];
|
||||||
|
u32 ulposc_con;
|
||||||
|
};
|
||||||
|
check_member(mtk_spm_regs, ulposc_con, 0x420);
|
||||||
|
|
||||||
|
struct mtk_spmi_mst_reg {
|
||||||
|
u32 op_st_ctrl;
|
||||||
|
u32 grp_id_en;
|
||||||
|
u32 op_st_sta;
|
||||||
|
u32 mst_sampl;
|
||||||
|
u32 mst_req_en;
|
||||||
|
u32 reserved1[11];
|
||||||
|
u32 rec_ctrl;
|
||||||
|
u32 rec0;
|
||||||
|
u32 rec1;
|
||||||
|
u32 rec2;
|
||||||
|
u32 rec3;
|
||||||
|
u32 rec4;
|
||||||
|
u32 reserved2[41];
|
||||||
|
u32 mst_dbg;
|
||||||
|
};
|
||||||
|
|
||||||
|
check_member(mtk_spmi_mst_reg, rec_ctrl, 0x40);
|
||||||
|
check_member(mtk_spmi_mst_reg, mst_dbg, 0xfc);
|
||||||
|
|
||||||
|
#define mtk_rug ((struct mtk_rgu_regs *)RGU_BASE)
|
||||||
|
#define mtk_iocfg_bm ((struct mtk_iocfg_bm_regs *)IOCFG_BM_BASE)
|
||||||
|
#define mtk_spm ((struct mtk_spm_regs *)SPM_BASE)
|
||||||
|
#define mtk_spmi_mst ((struct mtk_spmi_mst_reg *)SPMI_MST_BASE)
|
||||||
|
|
||||||
|
struct cali {
|
||||||
|
unsigned int dly;
|
||||||
|
unsigned int pol;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
SPMI_CK_NO_DLY = 0,
|
||||||
|
SPMI_CK_DLY_1T,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
SPMI_CK_POL_NEG = 0,
|
||||||
|
SPMI_CK_POL_POS,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum spmi_regs {
|
||||||
|
SPMI_OP_ST_CTRL,
|
||||||
|
SPMI_GRP_ID_EN,
|
||||||
|
SPMI_OP_ST_STA,
|
||||||
|
SPMI_MST_SAMPL,
|
||||||
|
SPMI_MST_REQ_EN,
|
||||||
|
SPMI_REC_CTRL,
|
||||||
|
SPMI_REC0,
|
||||||
|
SPMI_REC1,
|
||||||
|
SPMI_REC2,
|
||||||
|
SPMI_REC3,
|
||||||
|
SPMI_REC4,
|
||||||
|
SPMI_MST_DBG
|
||||||
|
};
|
||||||
|
|
||||||
|
/* MT6315 registers */
|
||||||
|
enum {
|
||||||
|
MT6315_BASE = 0x0,
|
||||||
|
MT6315_READ_TEST = MT6315_BASE + 0x9,
|
||||||
|
MT6315_READ_TEST_1 = MT6315_BASE + 0xb,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define MT6315_DEFAULT_VALUE_READ 0x15
|
||||||
|
|
||||||
|
extern int pmif_spmi_init(struct pmif *arb);
|
||||||
|
#endif /*__PMIF_SPMI_H__*/
|
45
src/soc/mediatek/mt8192/include/soc/pmif_sw.h
Normal file
45
src/soc/mediatek/mt8192/include/soc/pmif_sw.h
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
|
||||||
|
#ifndef __PMIF_SW_H__
|
||||||
|
#define __PMIF_SW_H__
|
||||||
|
|
||||||
|
/* Read/write byte limitation, by project */
|
||||||
|
/* hw bytecnt indicate when we set 0, it can send 1 byte;
|
||||||
|
* set 1, it can send 2 byte.
|
||||||
|
*/
|
||||||
|
#define PMIF_BYTECNT_MAX 1
|
||||||
|
|
||||||
|
/* macro for SWINF_FSM */
|
||||||
|
#define SWINF_FSM_IDLE 0x00
|
||||||
|
#define SWINF_FSM_REQ 0x02
|
||||||
|
#define SWINF_FSM_WFDLE 0x04
|
||||||
|
#define SWINF_FSM_WFVLDCLR 0x06
|
||||||
|
#define SWINF_INIT_DONE 0x01
|
||||||
|
|
||||||
|
#define FREQ_METER_ABIST_AD_OSC_CK 37
|
||||||
|
#define GET_SWINF_0_FSM(x) (((x) >> 1) & 0x7)
|
||||||
|
|
||||||
|
struct pmif_mpu {
|
||||||
|
unsigned int rgn_slvid;
|
||||||
|
unsigned short rgn_s_addr;
|
||||||
|
unsigned short rgn_e_addr;
|
||||||
|
unsigned int rgn_domain_per;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PMIF_READ_US = 1000,
|
||||||
|
PMIF_WAIT_IDLE_US = 1000,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
FREQ_260MHZ = 260,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* calibation tolerance rate, unit: 0.1% */
|
||||||
|
enum {
|
||||||
|
CAL_TOL_RATE = 40,
|
||||||
|
CAL_MAX_VAL = 0x7F,
|
||||||
|
};
|
||||||
|
|
||||||
|
extern int pmif_clk_init(void);
|
||||||
|
#endif /*__PMIF_SW_H__*/
|
50
src/soc/mediatek/mt8192/include/soc/spmi.h
Normal file
50
src/soc/mediatek/mt8192/include/soc/spmi.h
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
|
||||||
|
#ifndef __SPMI_H__
|
||||||
|
#define __SPMI_H__
|
||||||
|
|
||||||
|
enum spmi_master {
|
||||||
|
SPMI_MASTER_0,
|
||||||
|
SPMI_MASTER_1,
|
||||||
|
SPMI_MASTER_2,
|
||||||
|
SPMI_MASTER_3,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum spmi_slave {
|
||||||
|
SPMI_SLAVE_0,
|
||||||
|
SPMI_SLAVE_1,
|
||||||
|
SPMI_SLAVE_2,
|
||||||
|
SPMI_SLAVE_3,
|
||||||
|
SPMI_SLAVE_4,
|
||||||
|
SPMI_SLAVE_5,
|
||||||
|
SPMI_SLAVE_6,
|
||||||
|
SPMI_SLAVE_7,
|
||||||
|
SPMI_SLAVE_8,
|
||||||
|
SPMI_SLAVE_9,
|
||||||
|
SPMI_SLAVE_10,
|
||||||
|
SPMI_SLAVE_11,
|
||||||
|
SPMI_SLAVE_12,
|
||||||
|
SPMI_SLAVE_13,
|
||||||
|
SPMI_SLAVE_14,
|
||||||
|
SPMI_SLAVE_15,
|
||||||
|
SPMI_SLAVE_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum slv_type {
|
||||||
|
BUCK_CPU,
|
||||||
|
BUCK_GPU,
|
||||||
|
SLV_TYPE_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum slv_type_id {
|
||||||
|
BUCK_CPU_ID,
|
||||||
|
BUCK_GPU_ID,
|
||||||
|
SLV_TYPE_ID_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct spmi_device {
|
||||||
|
u32 slvid;
|
||||||
|
enum slv_type type;
|
||||||
|
enum slv_type_id type_id;
|
||||||
|
};
|
||||||
|
#endif /*__SPMI_H__*/
|
191
src/soc/mediatek/mt8192/pmif.c
Normal file
191
src/soc/mediatek/mt8192/pmif.c
Normal file
@@ -0,0 +1,191 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <console/console.h>
|
||||||
|
#include <device/mmio.h>
|
||||||
|
#include <soc/addressmap.h>
|
||||||
|
#include <soc/pmif.h>
|
||||||
|
#include <soc/pmif_spi.h>
|
||||||
|
#include <soc/pmif_spmi.h>
|
||||||
|
#include <soc/pmif_sw.h>
|
||||||
|
#include <soc/spmi.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <timer.h>
|
||||||
|
|
||||||
|
static int pmif_check_swinf(struct pmif *arb, long timeout_us, u32 expected_status)
|
||||||
|
{
|
||||||
|
u32 reg_rdata;
|
||||||
|
struct stopwatch sw;
|
||||||
|
|
||||||
|
stopwatch_init_usecs_expire(&sw, timeout_us);
|
||||||
|
do {
|
||||||
|
reg_rdata = read32(&arb->ch->ch_sta);
|
||||||
|
if (stopwatch_expired(&sw))
|
||||||
|
return E_TIMEOUT;
|
||||||
|
} while (GET_SWINF_0_FSM(reg_rdata) != expected_status);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pmif_send_cmd(struct pmif *arb, int write, u32 opc, u32 slvid,
|
||||||
|
u32 addr, u32 *rdata, u32 wdata, u32 len)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
u32 data, bc = len - 1;
|
||||||
|
|
||||||
|
/* Wait for Software Interface FSM state to be IDLE. */
|
||||||
|
ret = pmif_check_swinf(arb, PMIF_WAIT_IDLE_US, SWINF_FSM_IDLE);
|
||||||
|
if (ret) {
|
||||||
|
printk(BIOS_ERR, "[%s] idle timeout\n", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the write data */
|
||||||
|
if (write)
|
||||||
|
write32(&arb->ch->wdata, wdata);
|
||||||
|
|
||||||
|
/* Send the command. */
|
||||||
|
write32(&arb->ch->ch_send,
|
||||||
|
(opc << 30) | (write << 29) | (slvid << 24) | (bc << 16) | addr);
|
||||||
|
|
||||||
|
if (!write) {
|
||||||
|
/*
|
||||||
|
* Wait for Software Interface FSM state to be WFVLDCLR,
|
||||||
|
* read the data and clear the valid flag.
|
||||||
|
*/
|
||||||
|
ret = pmif_check_swinf(arb, PMIF_READ_US, SWINF_FSM_WFVLDCLR);
|
||||||
|
if (ret) {
|
||||||
|
printk(BIOS_ERR, "[%s] read timeout\n", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
data = read32(&arb->ch->rdata);
|
||||||
|
*rdata = data;
|
||||||
|
write32(&arb->ch->ch_rdy, 0x1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pmif_spmi_read(struct pmif *arb, u32 slvid, u32 reg, u32 *data)
|
||||||
|
{
|
||||||
|
*data = 0;
|
||||||
|
pmif_send_cmd(arb, 0, PMIF_CMD_EXT_REG_LONG, slvid, reg, data, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pmif_spmi_write(struct pmif *arb, u32 slvid, u32 reg, u32 data)
|
||||||
|
{
|
||||||
|
pmif_send_cmd(arb, 1, PMIF_CMD_EXT_REG_LONG, slvid, reg, NULL, data, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 pmif_spmi_read_field(struct pmif *arb, u32 slvid, u32 reg, u32 mask, u32 shift)
|
||||||
|
{
|
||||||
|
u32 data;
|
||||||
|
|
||||||
|
pmif_spmi_read(arb, slvid, reg, &data);
|
||||||
|
data &= (mask << shift);
|
||||||
|
data >>= shift;
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pmif_spmi_write_field(struct pmif *arb, u32 slvid, u32 reg,
|
||||||
|
u32 val, u32 mask, u32 shift)
|
||||||
|
{
|
||||||
|
u32 old, new;
|
||||||
|
|
||||||
|
pmif_spmi_read(arb, slvid, reg, &old);
|
||||||
|
new = old & ~(mask << shift);
|
||||||
|
new |= (val << shift);
|
||||||
|
pmif_spmi_write(arb, slvid, reg, new);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pmif_spi_read(struct pmif *arb, u32 slvid, u32 reg, u32 *data)
|
||||||
|
{
|
||||||
|
*data = 0;
|
||||||
|
pmif_send_cmd(arb, 0, PMIF_CMD_REG_0, slvid, reg, data, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pmif_spi_write(struct pmif *arb, u32 slvid, u32 reg, u32 data)
|
||||||
|
{
|
||||||
|
pmif_send_cmd(arb, 1, PMIF_CMD_REG_0, slvid, reg, NULL, data, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 pmif_spi_read_field(struct pmif *arb, u32 slvid, u32 reg, u32 mask, u32 shift)
|
||||||
|
{
|
||||||
|
u32 data;
|
||||||
|
|
||||||
|
pmif_spi_read(arb, slvid, reg, &data);
|
||||||
|
data &= (mask << shift);
|
||||||
|
data >>= shift;
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pmif_spi_write_field(struct pmif *arb, u32 slvid, u32 reg,
|
||||||
|
u32 val, u32 mask, u32 shift)
|
||||||
|
{
|
||||||
|
u32 old, new;
|
||||||
|
|
||||||
|
pmif_spi_read(arb, slvid, reg, &old);
|
||||||
|
new = old & ~(mask << shift);
|
||||||
|
new |= (val << shift);
|
||||||
|
pmif_spi_write(arb, slvid, reg, new);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int is_pmif_init_done(struct pmif *arb)
|
||||||
|
{
|
||||||
|
if (read32(&arb->mtk_pmif->init_done) & 0x1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return -E_NODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct pmif pmif_spmi_arb[] = {
|
||||||
|
{
|
||||||
|
.mtk_pmif = (struct mtk_pmif_regs *)PMIF_SPMI_BASE,
|
||||||
|
.ch = (struct chan_regs *)PMIF_SPMI_AP_CHAN,
|
||||||
|
.mstid = SPMI_MASTER_0,
|
||||||
|
.pmifid = PMIF_SPMI,
|
||||||
|
.write = pmif_spmi_write,
|
||||||
|
.read = pmif_spmi_read,
|
||||||
|
.write_field = pmif_spmi_write_field,
|
||||||
|
.read_field = pmif_spmi_read_field,
|
||||||
|
.is_pmif_init_done = is_pmif_init_done,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct pmif pmif_spi_arb[] = {
|
||||||
|
{
|
||||||
|
.mtk_pmif = (struct mtk_pmif_regs *)PMIF_SPI_BASE,
|
||||||
|
.ch = (struct chan_regs *)PMIF_SPI_AP_CHAN,
|
||||||
|
.pmifid = PMIF_SPI,
|
||||||
|
.write = pmif_spi_write,
|
||||||
|
.read = pmif_spi_read,
|
||||||
|
.write_field = pmif_spi_write_field,
|
||||||
|
.read_field = pmif_spi_read_field,
|
||||||
|
.is_pmif_init_done = is_pmif_init_done,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pmif *get_pmif_controller(int inf, int mstid)
|
||||||
|
{
|
||||||
|
if (inf == PMIF_SPMI && mstid < ARRAY_SIZE(pmif_spmi_arb))
|
||||||
|
return (struct pmif *)&pmif_spmi_arb[mstid];
|
||||||
|
else if (inf == PMIF_SPI)
|
||||||
|
return (struct pmif *)&pmif_spi_arb[0];
|
||||||
|
|
||||||
|
die("[%s] Failed to get pmif controller: inf = %d, mstid = %d\n", __func__, inf, mstid);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mtk_pmif_init(void)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = pmif_clk_init();
|
||||||
|
if (!ret)
|
||||||
|
ret = pmif_spmi_init(get_pmif_controller(PMIF_SPMI, SPMI_MASTER_0));
|
||||||
|
if (!ret)
|
||||||
|
ret = pmif_spi_init(get_pmif_controller(PMIF_SPI, 0));
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
172
src/soc/mediatek/mt8192/pmif_clk.c
Normal file
172
src/soc/mediatek/mt8192/pmif_clk.c
Normal file
@@ -0,0 +1,172 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
|
||||||
|
#include <commonlib/helpers.h>
|
||||||
|
#include <console/console.h>
|
||||||
|
#include <delay.h>
|
||||||
|
#include <device/mmio.h>
|
||||||
|
#include <soc/infracfg.h>
|
||||||
|
#include <soc/pll.h>
|
||||||
|
#include <soc/pll_common.h>
|
||||||
|
#include <soc/pmif.h>
|
||||||
|
#include <soc/pmif_sw.h>
|
||||||
|
#include <soc/pmif_spmi.h>
|
||||||
|
|
||||||
|
/* APMIXED, ULPOSC1_CON0 */
|
||||||
|
DEFINE_BITFIELD(OSC1_CALI, 6, 0)
|
||||||
|
DEFINE_BITFIELD(OSC1_IBAND, 13, 7)
|
||||||
|
DEFINE_BITFIELD(OSC1_FBAND, 17, 14)
|
||||||
|
DEFINE_BITFIELD(OSC1_DIV, 23, 18)
|
||||||
|
DEFINE_BIT(OSC1_CP_EN, 24)
|
||||||
|
|
||||||
|
/* APMIXED, ULPOSC1_CON1 */
|
||||||
|
DEFINE_BITFIELD(OSC1_32KCALI, 7, 0)
|
||||||
|
DEFINE_BITFIELD(OSC1_RSV1, 15, 8)
|
||||||
|
DEFINE_BITFIELD(OSC1_RSV2, 23, 16)
|
||||||
|
DEFINE_BITFIELD(OSC1_MOD, 25, 24)
|
||||||
|
DEFINE_BIT(OSC1_DIV2_EN, 26)
|
||||||
|
|
||||||
|
/* APMIXED, ULPOSC1_CON2 */
|
||||||
|
DEFINE_BITFIELD(OSC1_BIAS, 7, 0)
|
||||||
|
|
||||||
|
/* SPM, POWERON_CONFIG_EN */
|
||||||
|
DEFINE_BIT(BCLK_CG_EN, 0)
|
||||||
|
DEFINE_BITFIELD(PROJECT_CODE, 31, 16)
|
||||||
|
|
||||||
|
/* SPM, ULPOSC_CON */
|
||||||
|
DEFINE_BIT(ULPOSC_EN, 0)
|
||||||
|
DEFINE_BIT(ULPOSC_CG_EN, 2)
|
||||||
|
|
||||||
|
/* INFRA, MODULE_SW_CG */
|
||||||
|
DEFINE_BIT(PMIC_CG_TMR, 0)
|
||||||
|
DEFINE_BIT(PMIC_CG_AP, 1)
|
||||||
|
DEFINE_BIT(PMIC_CG_MD, 2)
|
||||||
|
DEFINE_BIT(PMIC_CG_CONN, 3)
|
||||||
|
|
||||||
|
/* INFRA, INFRA_GLOBALCON_RST2 */
|
||||||
|
DEFINE_BIT(PMIC_WRAP_SWRST, 0)
|
||||||
|
DEFINE_BIT(PMICSPMI_SWRST, 14)
|
||||||
|
|
||||||
|
/* INFRA, PMICW_CLOCK_CTRL */
|
||||||
|
DEFINE_BITFIELD(PMIC_SYSCK_26M_SEL, 3, 0)
|
||||||
|
|
||||||
|
/* TOPCKGEN, CLK_CFG_8 */
|
||||||
|
DEFINE_BITFIELD(CLK_PWRAP_ULPOSC_SET, 10, 8)
|
||||||
|
DEFINE_BIT(CLK_PWRAP_ULPOSC_INV, 12)
|
||||||
|
DEFINE_BIT(PDN_PWRAP_ULPOSC, 15)
|
||||||
|
|
||||||
|
/* TOPCKGEN, CLK_CFG_UPDATE1 */
|
||||||
|
DEFINE_BIT(CLK_CFG_UPDATE1, 2)
|
||||||
|
|
||||||
|
static void pmif_ulposc_config(void)
|
||||||
|
{
|
||||||
|
/* ULPOSC1_CON0 */
|
||||||
|
SET32_BITFIELDS(&mtk_apmixed->ulposc1_con0, OSC1_CP_EN, 0, OSC1_DIV, 0xe,
|
||||||
|
OSC1_FBAND, 0x2, OSC1_IBAND, 0x52, OSC1_CALI, 0x40);
|
||||||
|
|
||||||
|
/* ULPOSC1_CON1 */
|
||||||
|
SET32_BITFIELDS(&mtk_apmixed->ulposc1_con1, OSC1_DIV2_EN, 0, OSC1_MOD, 0,
|
||||||
|
OSC1_RSV2, 0, OSC1_RSV1, 0x29, OSC1_32KCALI, 0);
|
||||||
|
|
||||||
|
/* ULPOSC1_CON2 */
|
||||||
|
SET32_BITFIELDS(&mtk_apmixed->ulposc1_con2, OSC1_BIAS, 0x40);
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 pmif_get_ulposc_freq_mhz(u32 cali_val)
|
||||||
|
{
|
||||||
|
u32 result = 0;
|
||||||
|
|
||||||
|
/* set calibration value */
|
||||||
|
SET32_BITFIELDS(&mtk_apmixed->ulposc1_con0, OSC1_CALI, cali_val);
|
||||||
|
udelay(50);
|
||||||
|
result = mt_fmeter_get_freq_khz(FMETER_ABIST, FREQ_METER_ABIST_AD_OSC_CK);
|
||||||
|
|
||||||
|
return result / 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pmif_ulposc_cali(void)
|
||||||
|
{
|
||||||
|
u32 current_val = 0, min = 0, max = CAL_MAX_VAL, middle;
|
||||||
|
int ret = 0, diff_by_min, diff_by_max, cal_result;
|
||||||
|
|
||||||
|
do {
|
||||||
|
middle = (min + max) / 2;
|
||||||
|
if (middle == min)
|
||||||
|
break;
|
||||||
|
|
||||||
|
current_val = pmif_get_ulposc_freq_mhz(middle);
|
||||||
|
if (current_val > FREQ_260MHZ)
|
||||||
|
max = middle;
|
||||||
|
else
|
||||||
|
min = middle;
|
||||||
|
} while (min <= max);
|
||||||
|
|
||||||
|
diff_by_min = pmif_get_ulposc_freq_mhz(min) - FREQ_260MHZ;
|
||||||
|
diff_by_min = ABS(diff_by_min);
|
||||||
|
|
||||||
|
diff_by_max = pmif_get_ulposc_freq_mhz(max) - FREQ_260MHZ;
|
||||||
|
diff_by_max = ABS(diff_by_max);
|
||||||
|
|
||||||
|
if (diff_by_min < diff_by_max) {
|
||||||
|
cal_result = min;
|
||||||
|
current_val = pmif_get_ulposc_freq_mhz(min);
|
||||||
|
} else {
|
||||||
|
cal_result = max;
|
||||||
|
current_val = pmif_get_ulposc_freq_mhz(max);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check if calibrated value is in the range of target value +- 15% */
|
||||||
|
if (current_val < (FREQ_260MHZ * (1000 - CAL_TOL_RATE) / 1000) ||
|
||||||
|
current_val > (FREQ_260MHZ * (1000 + CAL_TOL_RATE) / 1000)) {
|
||||||
|
printk(BIOS_ERR, "[%s] calibration fail: %dM\n", __func__, current_val);
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pmif_init_ulposc(void)
|
||||||
|
{
|
||||||
|
/* calibrate ULPOSC1 */
|
||||||
|
pmif_ulposc_config();
|
||||||
|
|
||||||
|
/* enable spm swinf */
|
||||||
|
if (!READ32_BITFIELD(&mtk_spm->poweron_config_en, BCLK_CG_EN))
|
||||||
|
SET32_BITFIELDS(&mtk_spm->poweron_config_en, BCLK_CG_EN, 1,
|
||||||
|
PROJECT_CODE, 0xb16);
|
||||||
|
|
||||||
|
/* turn on ulposc */
|
||||||
|
SET32_BITFIELDS(&mtk_spm->ulposc_con, ULPOSC_EN, 1);
|
||||||
|
udelay(100);
|
||||||
|
SET32_BITFIELDS(&mtk_spm->ulposc_con, ULPOSC_CG_EN, 1);
|
||||||
|
|
||||||
|
return pmif_ulposc_cali();
|
||||||
|
}
|
||||||
|
|
||||||
|
int pmif_clk_init(void)
|
||||||
|
{
|
||||||
|
if (pmif_init_ulposc())
|
||||||
|
return E_NODEV;
|
||||||
|
|
||||||
|
/* turn off pmic_cg_tmr, cg_ap, cg_md, cg_conn clock */
|
||||||
|
SET32_BITFIELDS(&mt8192_infracfg->module_sw_cg_0_set, PMIC_CG_TMR, 1, PMIC_CG_AP, 1,
|
||||||
|
PMIC_CG_MD, 1, PMIC_CG_CONN, 1);
|
||||||
|
|
||||||
|
SET32_BITFIELDS(&mtk_topckgen->clk_cfg_8, PDN_PWRAP_ULPOSC, 0, CLK_PWRAP_ULPOSC_INV,
|
||||||
|
0, CLK_PWRAP_ULPOSC_SET, 0);
|
||||||
|
SET32_BITFIELDS(&mtk_topckgen->clk_cfg_update1, CLK_CFG_UPDATE1, 1);
|
||||||
|
|
||||||
|
/* use ULPOSC1 clock */
|
||||||
|
SET32_BITFIELDS(&mt8192_infracfg->pmicw_clock_ctrl_clr, PMIC_SYSCK_26M_SEL, 0xf);
|
||||||
|
|
||||||
|
/* toggle SPI/SPMI sw reset */
|
||||||
|
SET32_BITFIELDS(&mt8192_infracfg->infra_globalcon_rst2_set, PMICSPMI_SWRST, 1,
|
||||||
|
PMIC_WRAP_SWRST, 1);
|
||||||
|
SET32_BITFIELDS(&mt8192_infracfg->infra_globalcon_rst2_clr, PMICSPMI_SWRST, 1,
|
||||||
|
PMIC_WRAP_SWRST, 1);
|
||||||
|
|
||||||
|
/* turn on pmic_cg_tmr, cg_ap, cg_md, cg_conn clock */
|
||||||
|
SET32_BITFIELDS(&mt8192_infracfg->module_sw_cg_0_clr, PMIC_CG_TMR, 1, PMIC_CG_AP, 1,
|
||||||
|
PMIC_CG_MD, 1, PMIC_CG_CONN, 1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
332
src/soc/mediatek/mt8192/pmif_spi.c
Normal file
332
src/soc/mediatek/mt8192/pmif_spi.c
Normal file
@@ -0,0 +1,332 @@
|
|||||||
|
/* 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/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)
|
||||||
|
{
|
||||||
|
/* 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;
|
||||||
|
}
|
242
src/soc/mediatek/mt8192/pmif_spmi.c
Normal file
242
src/soc/mediatek/mt8192/pmif_spmi.c
Normal file
@@ -0,0 +1,242 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
|
||||||
|
#include <console/console.h>
|
||||||
|
#include <device/mmio.h>
|
||||||
|
#include <soc/addressmap.h>
|
||||||
|
#include <soc/pll.h>
|
||||||
|
#include <soc/pll_common.h>
|
||||||
|
#include <soc/pmif.h>
|
||||||
|
#include <soc/pmif_spmi.h>
|
||||||
|
#include <soc/pmif_sw.h>
|
||||||
|
#include <soc/spmi.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define PMIF_CMD_PER_3 (0x1 << PMIF_CMD_EXT_REG_LONG)
|
||||||
|
#define PMIF_CMD_PER_1_3 ((0x1 << PMIF_CMD_REG) | (0x1 << PMIF_CMD_EXT_REG_LONG))
|
||||||
|
|
||||||
|
/* IOCFG_BM, DRV_CFG2 */
|
||||||
|
DEFINE_BITFIELD(SPMI_SCL, 5, 3)
|
||||||
|
DEFINE_BITFIELD(SPMI_SDA, 8, 6)
|
||||||
|
|
||||||
|
/* TOPRGU, WDT_SWSYSRST2 */
|
||||||
|
DEFINE_BIT(SPMI_MST_RST, 4)
|
||||||
|
DEFINE_BITFIELD(UNLOCK_KEY, 31, 24)
|
||||||
|
|
||||||
|
/* TOPCKGEN, CLK_CFG_15 */
|
||||||
|
DEFINE_BITFIELD(CLK_SPMI_MST_SEL, 10, 8)
|
||||||
|
DEFINE_BIT(CLK_SPMI_MST_INT, 12)
|
||||||
|
DEFINE_BIT(PDN_SPMI_MST, 15)
|
||||||
|
|
||||||
|
/* TOPCKGEN, CLK_CFG_UPDATE2 */
|
||||||
|
DEFINE_BIT(SPMI_MST_CK_UPDATE, 30)
|
||||||
|
|
||||||
|
/* 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)
|
||||||
|
|
||||||
|
static const struct spmi_device spmi_dev[] = {
|
||||||
|
{
|
||||||
|
.slvid = SPMI_SLAVE_6,
|
||||||
|
.type = BUCK_CPU,
|
||||||
|
.type_id = BUCK_CPU_ID,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.slvid = SPMI_SLAVE_7,
|
||||||
|
.type = BUCK_GPU,
|
||||||
|
.type_id = BUCK_GPU_ID,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static int spmi_config_master(void)
|
||||||
|
{
|
||||||
|
/* Software reset */
|
||||||
|
SET32_BITFIELDS(&mtk_rug->wdt_swsysrst2, SPMI_MST_RST, 1, UNLOCK_KEY, 0x85);
|
||||||
|
|
||||||
|
SET32_BITFIELDS(&mtk_topckgen->clk_cfg_15,
|
||||||
|
CLK_SPMI_MST_SEL, 0x7,
|
||||||
|
CLK_SPMI_MST_INT, 1,
|
||||||
|
PDN_SPMI_MST, 1);
|
||||||
|
SET32_BITFIELDS(&mtk_topckgen->clk_cfg_update2, SPMI_MST_CK_UPDATE, 1);
|
||||||
|
|
||||||
|
/* Software reset */
|
||||||
|
SET32_BITFIELDS(&mtk_rug->wdt_swsysrst2, SPMI_MST_RST, 0, UNLOCK_KEY, 0x85);
|
||||||
|
|
||||||
|
/* Enable SPMI */
|
||||||
|
write32(&mtk_spmi_mst->mst_req_en, 1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
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_ERR, "%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_ERR, "%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},
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 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)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!pmif_arb) {
|
||||||
|
printk(BIOS_ERR, "%s: null pointer for pmif dev.\n", __func__);
|
||||||
|
return -E_INVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* config IOCFG */
|
||||||
|
SET32_BITFIELDS(&mtk_iocfg_bm->drv_cfg2, SPMI_SCL, 0x2, SPMI_SDA, 0x2);
|
||||||
|
spmi_config_master();
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(spmi_dev); 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);
|
||||||
|
u32 cmd_per;
|
||||||
|
|
||||||
|
/* clear all cmd permission for per channel */
|
||||||
|
write32(&arb->mtk_pmif->inf_cmd_per_0, 0);
|
||||||
|
write32(&arb->mtk_pmif->inf_cmd_per_1, 0);
|
||||||
|
write32(&arb->mtk_pmif->inf_cmd_per_2, 0);
|
||||||
|
write32(&arb->mtk_pmif->inf_cmd_per_3, 0);
|
||||||
|
|
||||||
|
/* enable if we need cmd 0~3 permission for per channel */
|
||||||
|
cmd_per = PMIF_CMD_PER_3 << 28 | PMIF_CMD_PER_3 << 24 |
|
||||||
|
PMIF_CMD_PER_3 << 20 | PMIF_CMD_PER_3 << 16 |
|
||||||
|
PMIF_CMD_PER_3 << 8 | PMIF_CMD_PER_3 << 4 |
|
||||||
|
PMIF_CMD_PER_1_3 << 0;
|
||||||
|
write32(&arb->mtk_pmif->inf_cmd_per_0, cmd_per);
|
||||||
|
|
||||||
|
cmd_per = PMIF_CMD_PER_3 << 4;
|
||||||
|
write32(&arb->mtk_pmif->inf_cmd_per_1, cmd_per);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
}
|
Reference in New Issue
Block a user