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>
This commit is contained in:
		| @@ -37,4 +37,6 @@ enum { | |||||||
| void mt6315_init(void); | void mt6315_init(void); | ||||||
| void mt6315_buck_set_voltage(u32 slvid, u32 buck_id, u32 buck_uv); | void mt6315_buck_set_voltage(u32 slvid, u32 buck_id, u32 buck_uv); | ||||||
| u32 mt6315_buck_get_voltage(u32 slvid, u32 buck_id); | u32 mt6315_buck_get_voltage(u32 slvid, u32 buck_id); | ||||||
|  | void mt6315_init_setting(void); | ||||||
|  | void mt6315_write_field(u32 slvid, u32 reg, u32 val, u32 mask, u32 shift); | ||||||
| #endif /* __SOC_MEDIATEK_MT6315_H__ */ | #endif /* __SOC_MEDIATEK_MT6315_H__ */ | ||||||
| @@ -66,4 +66,7 @@ void mt6359p_buck_set_voltage(u32 buck_id, u32 buck_uv); | |||||||
| u32 mt6359p_buck_get_voltage(u32 buck_id); | u32 mt6359p_buck_get_voltage(u32 buck_id); | ||||||
| void mt6359p_set_vm18_voltage(u32 vm18_uv); | void mt6359p_set_vm18_voltage(u32 vm18_uv); | ||||||
| u32 mt6359p_get_vm18_voltage(void); | u32 mt6359p_get_vm18_voltage(void); | ||||||
|  | void mt6359p_write_field(u32 reg, u32 val, u32 mask, u32 shift); | ||||||
|  | void pmic_init_setting(void); | ||||||
|  | void pmic_lp_setting(void); | ||||||
| #endif /* __SOC_MEDIATEK_MT6359P_H__ */ | #endif /* __SOC_MEDIATEK_MT6359P_H__ */ | ||||||
							
								
								
									
										87
									
								
								src/soc/mediatek/common/include/soc/pmif_common.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								src/soc/mediatek/common/include/soc/pmif_common.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,87 @@ | |||||||
|  | /* SPDX-License-Identifier: GPL-2.0-only */ | ||||||
|  |  | ||||||
|  | #ifndef __MEDIATEK_SOC_PMIF_COMMON__ | ||||||
|  | #define __MEDIATEK_SOC_PMIF_COMMON__ | ||||||
|  |  | ||||||
|  | #include <types.h> | ||||||
|  |  | ||||||
|  | enum { | ||||||
|  | 	PMIF_CMD_REG_0, | ||||||
|  | 	PMIF_CMD_REG, | ||||||
|  | 	PMIF_CMD_EXT_REG, | ||||||
|  | 	PMIF_CMD_EXT_REG_LONG, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | 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 */ | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | enum pmic_interface { | ||||||
|  | 	PMIF_VLD_RDY = 0, | ||||||
|  | 	PMIF_SLP_REQ, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | DEFINE_BIT(PMIFSPI_INF_EN_SRCLKEN_RC_HW, 4) | ||||||
|  |  | ||||||
|  | DEFINE_BIT(PMIFSPI_OTHER_INF_DXCO0_EN, 0) | ||||||
|  | DEFINE_BIT(PMIFSPI_OTHER_INF_DXCO1_EN, 1) | ||||||
|  |  | ||||||
|  | DEFINE_BIT(PMIFSPI_ARB_EN_SRCLKEN_RC_HW, 4) | ||||||
|  | DEFINE_BIT(PMIFSPI_ARB_EN_DCXO_CONN, 15) | ||||||
|  | DEFINE_BIT(PMIFSPI_ARB_EN_DCXO_NFC, 16) | ||||||
|  |  | ||||||
|  | DEFINE_BITFIELD(PMIFSPI_SPM_SLEEP_REQ_SEL, 1, 0) | ||||||
|  | DEFINE_BITFIELD(PMIFSPI_SCP_SLEEP_REQ_SEL, 10, 9) | ||||||
|  |  | ||||||
|  | DEFINE_BIT(PMIFSPI_MD_CTL_PMIF_RDY, 9) | ||||||
|  | DEFINE_BIT(PMIFSPI_MD_CTL_SRCLK_EN, 10) | ||||||
|  | DEFINE_BIT(PMIFSPI_MD_CTL_SRVOL_EN, 11) | ||||||
|  |  | ||||||
|  | DEFINE_BITFIELD(PMIFSPMI_SPM_SLEEP_REQ_SEL, 1, 0) | ||||||
|  | DEFINE_BITFIELD(PMIFSPMI_SCP_SLEEP_REQ_SEL, 10, 9) | ||||||
|  |  | ||||||
|  | DEFINE_BIT(PMIFSPMI_MD_CTL_PMIF_RDY, 9) | ||||||
|  | DEFINE_BIT(PMIFSPMI_MD_CTL_SRCLK_EN, 10) | ||||||
|  | DEFINE_BIT(PMIFSPMI_MD_CTL_SRVOL_EN, 11) | ||||||
|  |  | ||||||
|  | /* External API */ | ||||||
|  | struct pmif *get_pmif_controller(int inf, int mstid); | ||||||
|  | void pmwrap_interface_init(void); | ||||||
|  | int mtk_pmif_init(void); | ||||||
|  | #endif /*__MEDIATEK_SOC_PMIF_COMMON__*/ | ||||||
| @@ -1,12 +1,13 @@ | |||||||
| /* SPDX-License-Identifier: GPL-2.0-only */ | /* SPDX-License-Identifier: GPL-2.0-only */ | ||||||
| 
 | 
 | ||||||
| #ifndef __SOC_MEDIATEK_MT8192_PMIC_WRAP_H__ | #ifndef __SOC_MEDIATEK_PMIF_SPI_H__ | ||||||
| #define __SOC_MEDIATEK_MT8192_PMIC_WRAP_H__ | #define __SOC_MEDIATEK_PMIF_SPI_H__ | ||||||
| 
 | 
 | ||||||
| #include <soc/addressmap.h> | #include <soc/addressmap.h> | ||||||
|  | #include <soc/pmif.h> | ||||||
| #include <types.h> | #include <types.h> | ||||||
| 
 | 
 | ||||||
| struct mt8192_pmicspi_mst_regs { | struct mtk_pmicspi_mst_regs { | ||||||
| 	u32 reserved1[4]; | 	u32 reserved1[4]; | ||||||
| 	u32 other_busy_sta_0; | 	u32 other_busy_sta_0; | ||||||
| 	u32 wrap_en; | 	u32 wrap_en; | ||||||
| @@ -27,20 +28,12 @@ struct mt8192_pmicspi_mst_regs { | |||||||
| 	u32 si_sampling_ctrl; | 	u32 si_sampling_ctrl; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| check_member(mt8192_pmicspi_mst_regs, other_busy_sta_0, 0x10); | check_member(mtk_pmicspi_mst_regs, other_busy_sta_0, 0x10); | ||||||
| check_member(mt8192_pmicspi_mst_regs, man_en, 0x20); | check_member(mtk_pmicspi_mst_regs, man_en, 0x20); | ||||||
| check_member(mt8192_pmicspi_mst_regs, mux_sel, 0x34); | check_member(mtk_pmicspi_mst_regs, mux_sel, 0x34); | ||||||
| check_member(mt8192_pmicspi_mst_regs, dio_en, 0x44); | check_member(mtk_pmicspi_mst_regs, dio_en, 0x44); | ||||||
| 
 | 
 | ||||||
| static struct mt8192_pmicspi_mst_regs * const mtk_pmicspi_mst = (void *)PMICSPI_MST_BASE; | static struct mtk_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 */ | /* PMIC registers */ | ||||||
| enum { | enum { | ||||||
| @@ -88,7 +81,6 @@ enum { | |||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| enum { | enum { | ||||||
| 	IO_4_MA = 0x1, |  | ||||||
| 	SLV_IO_4_MA = 0x8, | 	SLV_IO_4_MA = 0x8, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @@ -121,5 +113,7 @@ enum { | |||||||
| 	E_CLK_EDGE = 1, | 	E_CLK_EDGE = 1, | ||||||
| 	E_CLK_LAST_SETTING, | 	E_CLK_LAST_SETTING, | ||||||
| }; | }; | ||||||
| extern int pmif_spi_init(struct pmif *arb); | 
 | ||||||
| #endif /* __SOC_MEDIATEK_MT8192_PMIC_WRAP_H__ */ | int pmif_spi_init(struct pmif *arb); | ||||||
|  | void pmif_spi_iocfg(void); | ||||||
|  | #endif /* __SOC_MEDIATEK_PMIF_SPI_H__ */ | ||||||
| @@ -1,9 +1,10 @@ | |||||||
| /* SPDX-License-Identifier: GPL-2.0-only */ | /* SPDX-License-Identifier: GPL-2.0-only */ | ||||||
| 
 | 
 | ||||||
| #ifndef __PMIF_SPMI_H__ | #ifndef __SOC_MEDIATEK_PMIF_SPMI_H__ | ||||||
| #define __PMIF_SPMI_H__ | #define __SOC_MEDIATEK_PMIF_SPMI_H__ | ||||||
| 
 | 
 | ||||||
| #include <soc/addressmap.h> | #include <soc/addressmap.h> | ||||||
|  | #include <soc/pmif.h> | ||||||
| 
 | 
 | ||||||
| #define DEFAULT_VALUE_READ_TEST		(0x5a) | #define DEFAULT_VALUE_READ_TEST		(0x5a) | ||||||
| #define DEFAULT_VALUE_WRITE_TEST	(0xa5) | #define DEFAULT_VALUE_WRITE_TEST	(0xa5) | ||||||
| @@ -18,12 +19,6 @@ struct mtk_rgu_regs { | |||||||
| }; | }; | ||||||
| check_member(mtk_rgu_regs, wdt_swsysrst2, 0x90); | 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_spmi_mst_reg { | struct mtk_spmi_mst_reg { | ||||||
| 	u32 op_st_ctrl; | 	u32 op_st_ctrl; | ||||||
| 	u32 grp_id_en; | 	u32 grp_id_en; | ||||||
| @@ -45,7 +40,6 @@ check_member(mtk_spmi_mst_reg, rec_ctrl, 0x40); | |||||||
| check_member(mtk_spmi_mst_reg, mst_dbg, 0xfc); | check_member(mtk_spmi_mst_reg, mst_dbg, 0xfc); | ||||||
| 
 | 
 | ||||||
| #define mtk_rug	((struct mtk_rgu_regs *)RGU_BASE) | #define mtk_rug	((struct mtk_rgu_regs *)RGU_BASE) | ||||||
| #define mtk_iocfg_bm	((struct mtk_iocfg_bm_regs *)IOCFG_BM_BASE) |  | ||||||
| #define mtk_spmi_mst	((struct mtk_spmi_mst_reg *)SPMI_MST_BASE) | #define mtk_spmi_mst	((struct mtk_spmi_mst_reg *)SPMI_MST_BASE) | ||||||
| 
 | 
 | ||||||
| struct cali { | struct cali { | ||||||
| @@ -87,5 +81,7 @@ enum { | |||||||
| 
 | 
 | ||||||
| #define MT6315_DEFAULT_VALUE_READ 0x15 | #define MT6315_DEFAULT_VALUE_READ 0x15 | ||||||
| 
 | 
 | ||||||
| extern int pmif_spmi_init(struct pmif *arb); | int pmif_spmi_init(struct pmif *arb); | ||||||
| #endif /*__PMIF_SPMI_H__*/ | int spmi_config_master(void); | ||||||
|  | void pmif_spmi_iocfg(void); | ||||||
|  | #endif /* __SOC_MEDIATEK_PMIF_SPMI_H__ */ | ||||||
							
								
								
									
										27
									
								
								src/soc/mediatek/common/include/soc/pmif_sw.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/soc/mediatek/common/include/soc/pmif_sw.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | |||||||
|  | /* SPDX-License-Identifier: GPL-2.0-only */ | ||||||
|  |  | ||||||
|  | #ifndef __SOC_MEDIATEK_PMIF_SW_H__ | ||||||
|  | #define __SOC_MEDIATEK_PMIF_SW_H__ | ||||||
|  |  | ||||||
|  | /* 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 GET_SWINF_0_FSM(x)	(((x) >> 1) & 0x7) | ||||||
|  |  | ||||||
|  | enum { | ||||||
|  | 	PMIF_READ_US        = 1000, | ||||||
|  | 	PMIF_WAIT_IDLE_US   = 1000, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* calibation tolerance rate, unit: 0.1% */ | ||||||
|  | enum { | ||||||
|  | 	CAL_TOL_RATE = 40, | ||||||
|  | 	CAL_MAX_VAL = 0x7F, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | int pmif_clk_init(void); | ||||||
|  | #endif /* __SOC_MEDIATEK_PMIF_SW_H__ */ | ||||||
| @@ -1,7 +1,9 @@ | |||||||
| /* SPDX-License-Identifier: GPL-2.0-only */ | /* SPDX-License-Identifier: GPL-2.0-only */ | ||||||
| 
 | 
 | ||||||
| #ifndef __SPMI_H__ | #ifndef __SOC_MEDIATEK_SPMI_H__ | ||||||
| #define __SPMI_H__ | #define __SOC_MEDIATEK_SPMI_H__ | ||||||
|  | 
 | ||||||
|  | #include <types.h> | ||||||
| 
 | 
 | ||||||
| enum spmi_master { | enum spmi_master { | ||||||
| 	SPMI_MASTER_0, | 	SPMI_MASTER_0, | ||||||
| @@ -47,4 +49,4 @@ struct spmi_device { | |||||||
| 	enum slv_type type; | 	enum slv_type type; | ||||||
| 	enum slv_type_id type_id; | 	enum slv_type_id type_id; | ||||||
| }; | }; | ||||||
| #endif /*__SPMI_H__*/ | #endif /* __SOC_MEDIATEK_SPMI_H__ */ | ||||||
							
								
								
									
										102
									
								
								src/soc/mediatek/common/mt6315.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								src/soc/mediatek/common/mt6315.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,102 @@ | |||||||
|  | /* SPDX-License-Identifier: GPL-2.0-only */ | ||||||
|  |  | ||||||
|  | #include <console/console.h> | ||||||
|  | #include <delay.h> | ||||||
|  | #include <soc/mt6315.h> | ||||||
|  | #include <soc/pmif.h> | ||||||
|  |  | ||||||
|  | static struct pmif *pmif_arb = NULL; | ||||||
|  |  | ||||||
|  | static void mt6315_read(u32 slvid, u32 reg, u32 *data) | ||||||
|  | { | ||||||
|  | 	pmif_arb->read(pmif_arb, slvid, reg, data); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void mt6315_write(u32 slvid, u32 reg, u32 data) | ||||||
|  | { | ||||||
|  | 	pmif_arb->write(pmif_arb, slvid, reg, data); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void mt6315_write_field(u32 slvid, u32 reg, u32 val, u32 mask, u32 shift) | ||||||
|  | { | ||||||
|  | 	pmif_arb->write_field(pmif_arb, slvid, reg, val, mask, shift); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void mt6315_wdt_enable(u32 slvid) | ||||||
|  | { | ||||||
|  | 	mt6315_write(slvid, 0x3A9, 0x63); | ||||||
|  | 	mt6315_write(slvid, 0x3A8, 0x15); | ||||||
|  | 	mt6315_write(slvid, 0x127, 0x2); | ||||||
|  | 	mt6315_write(slvid, 0x127, 0x1); | ||||||
|  | 	mt6315_write(slvid, 0x127, 0x8); | ||||||
|  | 	udelay(50); | ||||||
|  | 	mt6315_write(slvid, 0x128, 0x8); | ||||||
|  | 	mt6315_write(slvid, 0x3A8, 0); | ||||||
|  | 	mt6315_write(slvid, 0x3A9, 0); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void mt6315_buck_set_voltage(u32 slvid, u32 buck_id, u32 buck_uv) | ||||||
|  | { | ||||||
|  | 	unsigned int vol_reg, vol_val; | ||||||
|  |  | ||||||
|  | 	if (!pmif_arb) | ||||||
|  | 		die("ERROR: pmif_arb not initialized"); | ||||||
|  |  | ||||||
|  | 	switch (buck_id) { | ||||||
|  | 	case MT6315_BUCK_1: | ||||||
|  | 		vol_reg = MT6315_BUCK_TOP_ELR0; | ||||||
|  | 		break; | ||||||
|  | 	case MT6315_BUCK_3: | ||||||
|  | 		vol_reg = MT6315_BUCK_TOP_ELR3; | ||||||
|  | 		break; | ||||||
|  | 	default: | ||||||
|  | 		die("ERROR: Unknown buck_id %u", buck_id); | ||||||
|  | 		return; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	vol_val = buck_uv / 6250; | ||||||
|  | 	mt6315_write(slvid, vol_reg, vol_val); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | u32 mt6315_buck_get_voltage(u32 slvid, u32 buck_id) | ||||||
|  | { | ||||||
|  | 	u32 vol_reg, vol; | ||||||
|  |  | ||||||
|  | 	if (!pmif_arb) | ||||||
|  | 		die("ERROR: pmif_arb not initialized"); | ||||||
|  |  | ||||||
|  | 	switch (buck_id) { | ||||||
|  | 	case MT6315_BUCK_1: | ||||||
|  | 		vol_reg = MT6315_BUCK_VBUCK1_DBG0; | ||||||
|  | 		break; | ||||||
|  | 	case MT6315_BUCK_3: | ||||||
|  | 		vol_reg = MT6315_BUCK_VBUCK1_DBG3; | ||||||
|  | 		break; | ||||||
|  | 	default: | ||||||
|  | 		die("ERROR: Unknown buck_id %u", buck_id); | ||||||
|  | 		return 0; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	mt6315_read(slvid, vol_reg, &vol); | ||||||
|  | 	return vol * 6250; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void init_pmif_arb(void) | ||||||
|  | { | ||||||
|  | 	if (!pmif_arb) { | ||||||
|  | 		pmif_arb = get_pmif_controller(PMIF_SPMI, 0); | ||||||
|  | 		if (!pmif_arb) | ||||||
|  | 			die("ERROR: No spmi device"); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (pmif_arb->is_pmif_init_done(pmif_arb)) | ||||||
|  | 		die("ERROR - Failed to initialize pmif spmi"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void mt6315_init(void) | ||||||
|  | { | ||||||
|  | 	init_pmif_arb(); | ||||||
|  | 	mt6315_wdt_enable(MT6315_CPU); | ||||||
|  | 	mt6315_wdt_enable(MT6315_GPU); | ||||||
|  | 	mt6315_init_setting(); | ||||||
|  | } | ||||||
							
								
								
									
										271
									
								
								src/soc/mediatek/common/mt6359p.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										271
									
								
								src/soc/mediatek/common/mt6359p.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,271 @@ | |||||||
|  | /* SPDX-License-Identifier: GPL-2.0-only */ | ||||||
|  |  | ||||||
|  | #include <assert.h> | ||||||
|  | #include <console/console.h> | ||||||
|  | #include <delay.h> | ||||||
|  | #include <soc/mt6359p.h> | ||||||
|  | #include <soc/pmif.h> | ||||||
|  | #include <timer.h> | ||||||
|  |  | ||||||
|  | static const struct pmic_setting key_protect_setting[] = { | ||||||
|  | 	{0x3A8, 0x9CA6, 0xFFFF, 0}, | ||||||
|  | 	{0x44A, 0xBADE, 0xFFFF, 0}, | ||||||
|  | 	{0xA3A, 0x4729, 0xFFFF, 0}, | ||||||
|  | 	{0xC58, 0x1605, 0xFFFF, 0}, | ||||||
|  | 	{0xC5A, 0x1706, 0xFFFF, 0}, | ||||||
|  | 	{0xC5C, 0x1807, 0xFFFF, 0}, | ||||||
|  | 	{0xFB4, 0x6359, 0xFFFF, 0}, | ||||||
|  | 	{0x1432, 0x5543, 0xFFFF, 0}, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | static const struct pmic_efuse efuse_setting[] = { | ||||||
|  | 	{79, 0xa0e, 0x1, 0xf}, | ||||||
|  | 	{886, 0x198c, 0xf, 0x8}, | ||||||
|  | 	{890, 0x198e, 0xf, 0x0}, | ||||||
|  | 	{902, 0x1998, 0xf, 0x8}, | ||||||
|  | 	{906, 0x1998, 0xf, 0xc}, | ||||||
|  | 	{918, 0x19a2, 0xf, 0x8}, | ||||||
|  | 	{922, 0x19a2, 0xf, 0xc}, | ||||||
|  | 	{1014, 0x19ae, 0xf, 0x7}, | ||||||
|  | 	{1018, 0x19ae, 0xf, 0xb}, | ||||||
|  | 	{1158, 0x1a0a, 0xf, 0x7}, | ||||||
|  | 	{1162, 0x1a0a, 0xf, 0xb}, | ||||||
|  | 	{1206, 0x1a16, 0xf, 0x7}, | ||||||
|  | 	{1210, 0x1a16, 0xf, 0xb}, | ||||||
|  | 	{1254, 0x1a22, 0xf, 0x7}, | ||||||
|  | 	{1258, 0x1a22, 0xf, 0xb}, | ||||||
|  | 	{1304, 0x1a2c, 0x7, 0x4}, | ||||||
|  | 	{1307, 0x1a32, 0x7, 0x8}, | ||||||
|  | 	{1336, 0x1a34, 0x7, 0x4}, | ||||||
|  | 	{1339, 0x1a3a, 0x7, 0x8}, | ||||||
|  | 	{1683, 0x79c, 0xf, 0x4}, | ||||||
|  | 	{1688, 0xc8a, 0x1, 0x3}, | ||||||
|  | 	{1689, 0xc88, 0x1, 0x3}, | ||||||
|  | 	{1690, 0xc88, 0x7, 0x0}, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | static struct pmif *pmif_arb = NULL; | ||||||
|  | static void mt6359p_write(u32 reg, u32 data) | ||||||
|  | { | ||||||
|  | 	pmif_arb->write(pmif_arb, 0, reg, data); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static u32 mt6359p_read_field(u32 reg, u32 mask, u32 shift) | ||||||
|  | { | ||||||
|  | 	return pmif_arb->read_field(pmif_arb, 0, reg, mask, shift); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void mt6359p_write_field(u32 reg, u32 val, u32 mask, u32 shift) | ||||||
|  | { | ||||||
|  | 	pmif_arb->write_field(pmif_arb, 0, reg, val, mask, shift); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void pmic_set_power_hold(void) | ||||||
|  | { | ||||||
|  | 	mt6359p_write_field(PMIC_PWRHOLD, 0x1, 0x1, 0); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void pmic_wdt_set(void) | ||||||
|  | { | ||||||
|  | 	/* [5]=1, RG_WDTRSTB_DEB */ | ||||||
|  | 	mt6359p_write_field(PMIC_TOP_RST_MISC_SET, 0x20, 0xFFFF, 0); | ||||||
|  | 	/* [1]=0, RG_WDTRSTB_MODE */ | ||||||
|  | 	mt6359p_write_field(PMIC_TOP_RST_MISC_CLR, 0x02, 0xFFFF, 0); | ||||||
|  | 	/* [0]=1, RG_WDTRSTB_EN */ | ||||||
|  | 	mt6359p_write_field(PMIC_TOP_RST_MISC_SET, 0x01, 0xFFFF, 0); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void pmic_protect_key_setting(bool lock) | ||||||
|  | { | ||||||
|  | 	for (int i = 0; i < ARRAY_SIZE(key_protect_setting); i++) | ||||||
|  | 		mt6359p_write(key_protect_setting[i].addr, | ||||||
|  | 			      lock ? 0 : key_protect_setting[i].val); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int check_idle(u32 timeout, u32 addr, u32 mask) | ||||||
|  | { | ||||||
|  | 	if (!wait_us(timeout, !mt6359p_read_field(addr, mask, 0))) | ||||||
|  | 		return -1; | ||||||
|  |  | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static u32 pmic_read_efuse(u32 efuse_bit, u32 mask) | ||||||
|  | { | ||||||
|  | 	u32 efuse_data; | ||||||
|  | 	int index, shift; | ||||||
|  |  | ||||||
|  | 	index = efuse_bit / 16; | ||||||
|  | 	shift = efuse_bit % 16; | ||||||
|  | 	mt6359p_write_field(PMIC_TOP_CKHWEN_CON0, 0, 0x1, 2); | ||||||
|  | 	mt6359p_write_field(PMIC_TOP_CKPDN_CON0, 0, 0x1, 4); | ||||||
|  | 	mt6359p_write_field(PMIC_OTP_CON11, 1, 0x1, 0); | ||||||
|  | 	mt6359p_write_field(PMIC_OTP_CON0, index * 2, 0xFF, 0); | ||||||
|  | 	if (mt6359p_read_field(PMIC_OTP_CON8, 1, 0)) | ||||||
|  | 		mt6359p_write_field(PMIC_OTP_CON8, 0, 1, 0); | ||||||
|  | 	else | ||||||
|  | 		mt6359p_write_field(PMIC_OTP_CON8, 1, 1, 0); | ||||||
|  |  | ||||||
|  | 	udelay(300); | ||||||
|  | 	if (check_idle(EFUSE_WAIT_US, PMIC_OTP_CON13, EFUSE_BUSY)) | ||||||
|  | 		die("[%s] timeout after %d usecs\n", __func__, EFUSE_WAIT_US); | ||||||
|  |  | ||||||
|  | 	udelay(100); | ||||||
|  |  | ||||||
|  | 	efuse_data = mt6359p_read_field(PMIC_OTP_CON12, 0xFFFF, 0); | ||||||
|  | 	efuse_data = (efuse_data >> shift) & mask; | ||||||
|  |  | ||||||
|  | 	mt6359p_write_field(PMIC_TOP_CKHWEN_CON0, 1, 0x1, 2); | ||||||
|  | 	mt6359p_write_field(PMIC_TOP_CKPDN_CON0, 1, 0x1, 4); | ||||||
|  |  | ||||||
|  | 	return efuse_data; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void pmic_efuse_setting(void) | ||||||
|  | { | ||||||
|  | 	u32 efuse_data; | ||||||
|  | 	struct stopwatch sw; | ||||||
|  |  | ||||||
|  | 	stopwatch_init(&sw); | ||||||
|  |  | ||||||
|  | 	for (int i = 0; i < ARRAY_SIZE(efuse_setting); i++) { | ||||||
|  | 		efuse_data = pmic_read_efuse(efuse_setting[i].efuse_bit, efuse_setting[i].mask); | ||||||
|  | 		mt6359p_write_field(efuse_setting[i].addr, efuse_data, | ||||||
|  | 			efuse_setting[i].mask, efuse_setting[i].shift); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	efuse_data = pmic_read_efuse(EFUSE_RG_VPA_OC_FT, 0x1); | ||||||
|  | 	if (efuse_data) { | ||||||
|  | 		/* restore VPA_DLC initial setting */ | ||||||
|  | 		mt6359p_write(PMIC_BUCK_VPA_DLC_CON0, 0x2810); | ||||||
|  | 		mt6359p_write(PMIC_BUCK_VPA_DLC_CON1, 0x800); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	printk(BIOS_DEBUG, "%s: Set efuses in %ld msecs\n", | ||||||
|  | 	       __func__, stopwatch_duration_msecs(&sw)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void pmic_wk_vs2_voter_setting(void) | ||||||
|  | { | ||||||
|  | 	/* | ||||||
|  | 	 *  1. Set VS2_VOTER_VOSEL = 1.35V | ||||||
|  | 	 *  2. Clear VS2_VOTER | ||||||
|  | 	 *  3. Set VS2_VOSEL = 1.4V | ||||||
|  | 	 */ | ||||||
|  | 	mt6359p_write_field(PMIC_VS2_VOTER_CFG, 0x2C, 0x7F, 0); | ||||||
|  | 	mt6359p_write_field(PMIC_VS2_VOTER, 0, 0xFFF, 0); | ||||||
|  | 	mt6359p_write_field(PMIC_VS2_ELR0, 0x30, 0x7F, 0); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void mt6359p_buck_set_voltage(u32 buck_id, u32 buck_uv) | ||||||
|  | { | ||||||
|  | 	u32 vol_offset, vol_reg, vol; | ||||||
|  |  | ||||||
|  | 	if (!pmif_arb) | ||||||
|  | 		die("ERROR: pmif_arb not initialized"); | ||||||
|  |  | ||||||
|  | 	switch (buck_id) { | ||||||
|  | 	case MT6359P_GPU11: | ||||||
|  | 		vol_offset = 400000; | ||||||
|  | 		vol_reg = PMIC_VGPU11_ELR0; | ||||||
|  | 		break; | ||||||
|  | 	case MT6359P_SRAM_PROC1: | ||||||
|  | 		vol_offset = 500000; | ||||||
|  | 		vol_reg = PMIC_VSRAM_PROC1_ELR; | ||||||
|  | 		break; | ||||||
|  | 	case MT6359P_SRAM_PROC2: | ||||||
|  | 		vol_offset = 500000; | ||||||
|  | 		vol_reg = PMIC_VSRAM_PROC2_ELR; | ||||||
|  | 		break; | ||||||
|  | 	default: | ||||||
|  | 		die("ERROR: Unknown buck_id %u", buck_id); | ||||||
|  | 		return; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	vol = (buck_uv - vol_offset) / 6250; | ||||||
|  | 	mt6359p_write_field(vol_reg, vol, 0x7F, 0); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | u32 mt6359p_buck_get_voltage(u32 buck_id) | ||||||
|  | { | ||||||
|  | 	u32 vol_shift, vol_offset, vol_reg, vol; | ||||||
|  |  | ||||||
|  | 	if (!pmif_arb) | ||||||
|  | 		die("ERROR: pmif_arb not initialized"); | ||||||
|  |  | ||||||
|  | 	switch (buck_id) { | ||||||
|  | 	case MT6359P_GPU11: | ||||||
|  | 		vol_shift = 0; | ||||||
|  | 		vol_offset = 400000; | ||||||
|  | 		vol_reg = PMIC_VGPU11_DBG0; | ||||||
|  | 		break; | ||||||
|  | 	case MT6359P_SRAM_PROC1: | ||||||
|  | 		vol_shift = 8; | ||||||
|  | 		vol_offset = 500000; | ||||||
|  | 		vol_reg = PMIC_VSRAM_PROC1_VOSEL1; | ||||||
|  | 		break; | ||||||
|  | 	case MT6359P_SRAM_PROC2: | ||||||
|  | 		vol_shift = 8; | ||||||
|  | 		vol_offset = 500000; | ||||||
|  | 		vol_reg = PMIC_VSRAM_PROC2_VOSEL1; | ||||||
|  | 		break; | ||||||
|  | 	default: | ||||||
|  | 		die("ERROR: Unknown buck_id %u", buck_id); | ||||||
|  | 		return 0; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	vol = mt6359p_read_field(vol_reg, 0x7F, vol_shift); | ||||||
|  | 	return vol_offset + vol * 6250; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void mt6359p_set_vm18_voltage(u32 vm18_uv) | ||||||
|  | { | ||||||
|  | 	u32 reg_vol, reg_cali; | ||||||
|  |  | ||||||
|  | 	if (!pmif_arb) | ||||||
|  | 		die("ERROR: pmif_arb not initialized"); | ||||||
|  |  | ||||||
|  | 	assert(vm18_uv >= 1700000); | ||||||
|  | 	assert(vm18_uv < 2000000); | ||||||
|  |  | ||||||
|  | 	reg_vol = (vm18_uv / 1000 - VM18_VOL_OFFSET) / 100; | ||||||
|  | 	reg_cali = ((vm18_uv / 1000) % 100) / 10; | ||||||
|  | 	mt6359p_write(PMIC_VM18_ANA_CON0, (reg_vol << VM18_VOL_REG_SHIFT) | reg_cali); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | u32 mt6359p_get_vm18_voltage(void) | ||||||
|  | { | ||||||
|  | 	u32 reg_vol, reg_cali; | ||||||
|  |  | ||||||
|  | 	if (!pmif_arb) | ||||||
|  | 		die("ERROR: pmif_arb not initialized"); | ||||||
|  |  | ||||||
|  | 	reg_vol = 100 * mt6359p_read_field(PMIC_VM18_ANA_CON0, 0xF, VM18_VOL_REG_SHIFT); | ||||||
|  | 	reg_cali = 10 * mt6359p_read_field(PMIC_VM18_ANA_CON0, 0xF, 0); | ||||||
|  | 	return 1000 * (VM18_VOL_OFFSET + reg_vol + reg_cali); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void init_pmif_arb(void) | ||||||
|  | { | ||||||
|  | 	if (!pmif_arb) { | ||||||
|  | 		pmif_arb = get_pmif_controller(PMIF_SPI, 0); | ||||||
|  | 		if (!pmif_arb) | ||||||
|  | 			die("ERROR: No spi device"); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (pmif_arb->is_pmif_init_done(pmif_arb)) | ||||||
|  | 		die("ERROR - Failed to initialize pmif spi"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void mt6359p_init(void) | ||||||
|  | { | ||||||
|  | 	init_pmif_arb(); | ||||||
|  | 	pmic_set_power_hold(); | ||||||
|  | 	pmic_wdt_set(); | ||||||
|  | 	pmic_protect_key_setting(false); | ||||||
|  | 	pmic_init_setting(); | ||||||
|  | 	pmic_lp_setting(); | ||||||
|  | 	pmic_efuse_setting(); | ||||||
|  | 	pmic_protect_key_setting(true); | ||||||
|  | 	pmic_wk_vs2_voter_setting(); | ||||||
|  | } | ||||||
							
								
								
									
										327
									
								
								src/soc/mediatek/common/pmif_spi.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										327
									
								
								src/soc/mediatek/common/pmif_spi.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,327 @@ | |||||||
|  | /* 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_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) | ||||||
|  |  | ||||||
|  | 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) | ||||||
|  | { | ||||||
|  | 	pmif_spi_iocfg(); | ||||||
|  |  | ||||||
|  | 	/* 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; | ||||||
|  | } | ||||||
							
								
								
									
										203
									
								
								src/soc/mediatek/common/pmif_spmi.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										203
									
								
								src/soc/mediatek/common/pmif_spmi.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,203 @@ | |||||||
|  | /* 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> | ||||||
|  |  | ||||||
|  | #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)) | ||||||
|  |  | ||||||
|  | /* 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_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}, | ||||||
|  | 		{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) | ||||||
|  | { | ||||||
|  | 	int i; | ||||||
|  |  | ||||||
|  | 	if (!pmif_arb) { | ||||||
|  | 		printk(BIOS_ERR, "%s: null pointer for pmif dev.\n", __func__); | ||||||
|  | 		return -E_INVAL; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	pmif_spmi_iocfg(); | ||||||
|  | 	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; | ||||||
|  | } | ||||||
| @@ -35,10 +35,12 @@ romstage-y += ../common/pll.c pll.c | |||||||
| romstage-$(CONFIG_SPI_FLASH) += ../common/spi.c spi.c | romstage-$(CONFIG_SPI_FLASH) += ../common/spi.c spi.c | ||||||
| romstage-y += ../common/timer.c | romstage-y += ../common/timer.c | ||||||
| romstage-y += ../common/uart.c | romstage-y += ../common/uart.c | ||||||
| romstage-y += pmif.c pmif_clk.c pmif_spi.c pmif_spmi.c | romstage-y += ../common/pmif.c pmif_clk.c | ||||||
|  | romstage-y += ../common/pmif_spi.c pmif_spi.c | ||||||
|  | romstage-y += ../common/pmif_spmi.c pmif_spmi.c | ||||||
| romstage-y += ../common/rtc.c ../common/rtc_osc_init.c rtc.c | romstage-y += ../common/rtc.c ../common/rtc_osc_init.c rtc.c | ||||||
| romstage-y += mt6315.c | romstage-y += ../common/mt6315.c mt6315.c | ||||||
| romstage-y += mt6359p.c | romstage-y += ../common/mt6359p.c mt6359p.c | ||||||
|  |  | ||||||
| ramstage-y += ../common/auxadc.c | ramstage-y += ../common/auxadc.c | ||||||
| ramstage-y += ../common/ddp.c ddp.c | ramstage-y += ../common/ddp.c ddp.c | ||||||
| @@ -54,7 +56,7 @@ ramstage-y += mcupm.c | |||||||
| ramstage-y += ../common/mmu_operations.c mmu_operations.c | ramstage-y += ../common/mmu_operations.c mmu_operations.c | ||||||
| ramstage-$(CONFIG_COMMONLIB_STORAGE_MMC) += ../common/msdc.c | ramstage-$(CONFIG_COMMONLIB_STORAGE_MMC) += ../common/msdc.c | ||||||
| ramstage-y += ../common/mtcmos.c mtcmos.c | ramstage-y += ../common/mtcmos.c mtcmos.c | ||||||
| ramstage-y += pmif.c | ramstage-y += ../common/pmif.c | ||||||
| ramstage-y += ../common/rtc.c rtc.c | ramstage-y += ../common/rtc.c rtc.c | ||||||
| ramstage-y += soc.c | ramstage-y += soc.c | ||||||
| ramstage-y += spm.c | ramstage-y += spm.c | ||||||
|   | |||||||
							
								
								
									
										29
									
								
								src/soc/mediatek/mt8192/include/soc/iocfg.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/soc/mediatek/mt8192/include/soc/iocfg.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | |||||||
|  | /* SPDX-License-Identifier: GPL-2.0-only */ | ||||||
|  |  | ||||||
|  | #ifndef __SOC_MEDIATEK_MT8192_IOCFG_H__ | ||||||
|  | #define __SOC_MEDIATEK_MT8192_IOCFG_H__ | ||||||
|  |  | ||||||
|  | #include <soc/addressmap.h> | ||||||
|  | #include <types.h> | ||||||
|  |  | ||||||
|  | struct mt8192_iocfg_lm_regs { | ||||||
|  | 	u32 reserved[4]; | ||||||
|  | 	u32 drv_cfg1; | ||||||
|  | }; | ||||||
|  | check_member(mt8192_iocfg_lm_regs, drv_cfg1, 0x10); | ||||||
|  |  | ||||||
|  | enum { | ||||||
|  | 	IO_4_MA = 0x1, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | #define mtk_iocfg_lm    ((struct mt8192_iocfg_lm_regs *)IOCFG_LM_BASE) | ||||||
|  |  | ||||||
|  | struct mt8192_iocfg_bm_regs { | ||||||
|  | 	u32 reserved[8]; | ||||||
|  | 	u32 drv_cfg2; | ||||||
|  | }; | ||||||
|  | check_member(mt8192_iocfg_bm_regs, drv_cfg2, 0x20); | ||||||
|  |  | ||||||
|  | #define mtk_iocfg_bm	((struct mt8192_iocfg_bm_regs *)IOCFG_BM_BASE) | ||||||
|  |  | ||||||
|  | #endif /* __SOC_MEDIATEK_MT8192_IOCFG_H__ */ | ||||||
| @@ -4,15 +4,9 @@ | |||||||
| #define __MT8192_SOC_PMIF_H__ | #define __MT8192_SOC_PMIF_H__ | ||||||
|  |  | ||||||
| #include <device/mmio.h> | #include <device/mmio.h> | ||||||
|  | #include <soc/pmif_common.h> | ||||||
| #include <types.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 { | struct mtk_pmif_regs { | ||||||
| 	u32 init_done; | 	u32 init_done; | ||||||
| 	u32 reserved1[5]; | 	u32 reserved1[5]; | ||||||
| @@ -128,76 +122,9 @@ check_member(mtk_pmif_regs, swinf_0_acc, 0xC00); | |||||||
| #define PMIF_SPMI_AP_CHAN	(PMIF_SPMI_BASE + 0xC80) | #define PMIF_SPMI_AP_CHAN	(PMIF_SPMI_BASE + 0xC80) | ||||||
| #define PMIF_SPI_AP_CHAN	(PMIF_SPI_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 { | enum { | ||||||
| 	PMIF_SPI, | 	FREQ_260MHZ = 260, | ||||||
| 	PMIF_SPMI, |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| enum { | #define FREQ_METER_ABIST_AD_OSC_CK	37 | ||||||
| 	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 */ |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| enum pmic_interface { |  | ||||||
| 	PMIF_VLD_RDY = 0, |  | ||||||
| 	PMIF_SLP_REQ, |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| DEFINE_BIT(PMIFSPI_INF_EN_SRCLKEN_RC_HW, 4) |  | ||||||
|  |  | ||||||
| DEFINE_BIT(PMIFSPI_OTHER_INF_DXCO0_EN, 0) |  | ||||||
| DEFINE_BIT(PMIFSPI_OTHER_INF_DXCO1_EN, 1) |  | ||||||
|  |  | ||||||
| DEFINE_BIT(PMIFSPI_ARB_EN_SRCLKEN_RC_HW, 4) |  | ||||||
| DEFINE_BIT(PMIFSPI_ARB_EN_DCXO_CONN, 15) |  | ||||||
| DEFINE_BIT(PMIFSPI_ARB_EN_DCXO_NFC, 16) |  | ||||||
|  |  | ||||||
| DEFINE_BITFIELD(PMIFSPI_SPM_SLEEP_REQ_SEL, 1, 0) |  | ||||||
| DEFINE_BITFIELD(PMIFSPI_SCP_SLEEP_REQ_SEL, 10, 9) |  | ||||||
|  |  | ||||||
| DEFINE_BIT(PMIFSPI_MD_CTL_PMIF_RDY, 9) |  | ||||||
| DEFINE_BIT(PMIFSPI_MD_CTL_SRCLK_EN, 10) |  | ||||||
| DEFINE_BIT(PMIFSPI_MD_CTL_SRVOL_EN, 11) |  | ||||||
|  |  | ||||||
| DEFINE_BITFIELD(PMIFSPMI_SPM_SLEEP_REQ_SEL, 1, 0) |  | ||||||
| DEFINE_BITFIELD(PMIFSPMI_SCP_SLEEP_REQ_SEL, 10, 9) |  | ||||||
|  |  | ||||||
| DEFINE_BIT(PMIFSPMI_MD_CTL_PMIF_RDY, 9) |  | ||||||
| DEFINE_BIT(PMIFSPMI_MD_CTL_SRCLK_EN, 10) |  | ||||||
| DEFINE_BIT(PMIFSPMI_MD_CTL_SRVOL_EN, 11) |  | ||||||
|  |  | ||||||
| /* External API */ |  | ||||||
| extern struct pmif *get_pmif_controller(int inf, int mstid); |  | ||||||
| extern void pmwrap_interface_init(void); |  | ||||||
| extern int mtk_pmif_init(void); |  | ||||||
| #endif /*__MT8192_SOC_PMIF_H__*/ | #endif /*__MT8192_SOC_PMIF_H__*/ | ||||||
|   | |||||||
| @@ -1,45 +0,0 @@ | |||||||
| /* 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__*/ |  | ||||||
| @@ -1,13 +1,7 @@ | |||||||
| /* SPDX-License-Identifier: GPL-2.0-only */ | /* SPDX-License-Identifier: GPL-2.0-only */ | ||||||
|  |  | ||||||
| #include <assert.h> |  | ||||||
| #include <console/console.h> |  | ||||||
| #include <delay.h> |  | ||||||
| #include <soc/pmif.h> |  | ||||||
| #include <soc/mt6315.h> | #include <soc/mt6315.h> | ||||||
|  |  | ||||||
| static struct pmif *pmif_arb = NULL; |  | ||||||
|  |  | ||||||
| static const struct mt6315_setting init_setting_cpu[] = { | static const struct mt6315_setting init_setting_cpu[] = { | ||||||
| 	/* disable magic key protection */ | 	/* disable magic key protection */ | ||||||
| 	{0x3A9, 0x63, 0xFF, 0}, | 	{0x3A9, 0x63, 0xFF, 0}, | ||||||
| @@ -194,35 +188,7 @@ static const struct mt6315_setting init_setting_gpu[] = { | |||||||
| 	{0x3A9, 0, 0xFF, 0}, | 	{0x3A9, 0, 0xFF, 0}, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| static void mt6315_read(u32 slvid, u32 reg, u32 *data) | void mt6315_init_setting(void) | ||||||
| { |  | ||||||
| 	pmif_arb->read(pmif_arb, slvid, reg, data); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void mt6315_write(u32 slvid, u32 reg, u32 data) |  | ||||||
| { |  | ||||||
| 	pmif_arb->write(pmif_arb, slvid, reg, data); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void mt6315_write_field(u32 slvid, u32 reg, u32 val, u32 mask, u32 shift) |  | ||||||
| { |  | ||||||
| 	pmif_arb->write_field(pmif_arb, slvid, reg, val, mask, shift); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void mt6315_wdt_enable(u32 slvid) |  | ||||||
| { |  | ||||||
| 	mt6315_write(slvid, 0x3A9, 0x63); |  | ||||||
| 	mt6315_write(slvid, 0x3A8, 0x15); |  | ||||||
| 	mt6315_write(slvid, 0x127, 0x2); |  | ||||||
| 	mt6315_write(slvid, 0x127, 0x1); |  | ||||||
| 	mt6315_write(slvid, 0x127, 0x8); |  | ||||||
| 	udelay(50); |  | ||||||
| 	mt6315_write(slvid, 0x128, 0x8); |  | ||||||
| 	mt6315_write(slvid, 0x3A8, 0); |  | ||||||
| 	mt6315_write(slvid, 0x3A9, 0); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void mt6315_init_setting(void) |  | ||||||
| { | { | ||||||
| 	for (int i = 0; i < ARRAY_SIZE(init_setting_cpu); i++) | 	for (int i = 0; i < ARRAY_SIZE(init_setting_cpu); i++) | ||||||
| 		mt6315_write_field(MT6315_CPU, | 		mt6315_write_field(MT6315_CPU, | ||||||
| @@ -234,69 +200,3 @@ static void mt6315_init_setting(void) | |||||||
| 			init_setting_gpu[i].addr, init_setting_gpu[i].val, | 			init_setting_gpu[i].addr, init_setting_gpu[i].val, | ||||||
| 			init_setting_gpu[i].mask, init_setting_gpu[i].shift); | 			init_setting_gpu[i].mask, init_setting_gpu[i].shift); | ||||||
| } | } | ||||||
|  |  | ||||||
| void mt6315_buck_set_voltage(u32 slvid, u32 buck_id, u32 buck_uv) |  | ||||||
| { |  | ||||||
| 	unsigned int vol_reg, vol_val; |  | ||||||
|  |  | ||||||
| 	if (!pmif_arb) |  | ||||||
| 		die("ERROR: pmif_arb not initialized"); |  | ||||||
|  |  | ||||||
| 	switch (buck_id) { |  | ||||||
| 	case MT6315_BUCK_1: |  | ||||||
| 		vol_reg = MT6315_BUCK_TOP_ELR0; |  | ||||||
| 		break; |  | ||||||
| 	case MT6315_BUCK_3: |  | ||||||
| 		vol_reg = MT6315_BUCK_TOP_ELR3; |  | ||||||
| 		break; |  | ||||||
| 	default: |  | ||||||
| 		die("ERROR: Unknown buck_id %u", buck_id); |  | ||||||
| 		return; |  | ||||||
| 	}; |  | ||||||
|  |  | ||||||
| 	vol_val = buck_uv / 6250; |  | ||||||
| 	mt6315_write(slvid, vol_reg, vol_val); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| u32 mt6315_buck_get_voltage(u32 slvid, u32 buck_id) |  | ||||||
| { |  | ||||||
| 	u32 vol_reg, vol; |  | ||||||
|  |  | ||||||
| 	if (!pmif_arb) |  | ||||||
| 		die("ERROR: pmif_arb not initialized"); |  | ||||||
|  |  | ||||||
| 	switch (buck_id) { |  | ||||||
| 	case MT6315_BUCK_1: |  | ||||||
| 		vol_reg = MT6315_BUCK_VBUCK1_DBG0; |  | ||||||
| 		break; |  | ||||||
| 	case MT6315_BUCK_3: |  | ||||||
| 		vol_reg = MT6315_BUCK_VBUCK1_DBG3; |  | ||||||
| 		break; |  | ||||||
| 	default: |  | ||||||
| 		die("ERROR: Unknown buck_id %u", buck_id); |  | ||||||
| 		return 0; |  | ||||||
| 	}; |  | ||||||
|  |  | ||||||
| 	mt6315_read(slvid, vol_reg, &vol); |  | ||||||
| 	return vol * 6250; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void init_pmif_arb(void) |  | ||||||
| { |  | ||||||
| 	if (!pmif_arb) { |  | ||||||
| 		pmif_arb = get_pmif_controller(PMIF_SPMI, 0); |  | ||||||
| 		if (!pmif_arb) |  | ||||||
| 			die("ERROR: No spmi device"); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if (pmif_arb->is_pmif_init_done(pmif_arb)) |  | ||||||
| 		die("ERROR - Failed to initialize pmif spmi"); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void mt6315_init(void) |  | ||||||
| { |  | ||||||
| 	init_pmif_arb(); |  | ||||||
| 	mt6315_wdt_enable(MT6315_CPU); |  | ||||||
| 	mt6315_wdt_enable(MT6315_GPU); |  | ||||||
| 	mt6315_init_setting(); |  | ||||||
| } |  | ||||||
|   | |||||||
| @@ -1,22 +1,6 @@ | |||||||
| /* SPDX-License-Identifier: GPL-2.0-only */ | /* SPDX-License-Identifier: GPL-2.0-only */ | ||||||
|  |  | ||||||
| #include <assert.h> |  | ||||||
| #include <console/console.h> |  | ||||||
| #include <delay.h> |  | ||||||
| #include <soc/pmif.h> |  | ||||||
| #include <soc/mt6359p.h> | #include <soc/mt6359p.h> | ||||||
| #include <timer.h> |  | ||||||
|  |  | ||||||
| static const struct pmic_setting key_protect_setting[] = { |  | ||||||
| 	{0x3A8, 0x9CA6, 0xFFFF, 0}, |  | ||||||
| 	{0x44A, 0xBADE, 0xFFFF, 0}, |  | ||||||
| 	{0xA3A, 0x4729, 0xFFFF, 0}, |  | ||||||
| 	{0xC58, 0x1605, 0xFFFF, 0}, |  | ||||||
| 	{0xC5A, 0x1706, 0xFFFF, 0}, |  | ||||||
| 	{0xC5C, 0x1807, 0xFFFF, 0}, |  | ||||||
| 	{0xFB4, 0x6359, 0xFFFF, 0}, |  | ||||||
| 	{0x1432, 0x5543, 0xFFFF, 0}, |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| static const struct pmic_setting init_setting[] = { | static const struct pmic_setting init_setting[] = { | ||||||
| 	{0x20, 0xA, 0xA, 0}, | 	{0x20, 0xA, 0xA, 0}, | ||||||
| @@ -299,268 +283,16 @@ static const struct pmic_setting lp_setting[] = { | |||||||
| 	{0x1d14, 0x1, 0x1, 0x2}, | 	{0x1d14, 0x1, 0x1, 0x2}, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| static const struct pmic_efuse efuse_setting[] = { | void pmic_init_setting(void) | ||||||
| 	{79, 0xa0e, 0x1, 0xf}, |  | ||||||
| 	{886, 0x198c, 0xf, 0x8}, |  | ||||||
| 	{890, 0x198e, 0xf, 0x0}, |  | ||||||
| 	{902, 0x1998, 0xf, 0x8}, |  | ||||||
| 	{906, 0x1998, 0xf, 0xc}, |  | ||||||
| 	{918, 0x19a2, 0xf, 0x8}, |  | ||||||
| 	{922, 0x19a2, 0xf, 0xc}, |  | ||||||
| 	{1014, 0x19ae, 0xf, 0x7}, |  | ||||||
| 	{1018, 0x19ae, 0xf, 0xb}, |  | ||||||
| 	{1158, 0x1a0a, 0xf, 0x7}, |  | ||||||
| 	{1162, 0x1a0a, 0xf, 0xb}, |  | ||||||
| 	{1206, 0x1a16, 0xf, 0x7}, |  | ||||||
| 	{1210, 0x1a16, 0xf, 0xb}, |  | ||||||
| 	{1254, 0x1a22, 0xf, 0x7}, |  | ||||||
| 	{1258, 0x1a22, 0xf, 0xb}, |  | ||||||
| 	{1304, 0x1a2c, 0x7, 0x4}, |  | ||||||
| 	{1307, 0x1a32, 0x7, 0x8}, |  | ||||||
| 	{1336, 0x1a34, 0x7, 0x4}, |  | ||||||
| 	{1339, 0x1a3a, 0x7, 0x8}, |  | ||||||
| 	{1683, 0x79c, 0xf, 0x4}, |  | ||||||
| 	{1688, 0xc8a, 0x1, 0x3}, |  | ||||||
| 	{1689, 0xc88, 0x1, 0x3}, |  | ||||||
| 	{1690, 0xc88, 0x7, 0x0}, |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| static struct pmif *pmif_arb = NULL; |  | ||||||
| static void mt6359p_write(u32 reg, u32 data) |  | ||||||
| { |  | ||||||
| 	pmif_arb->write(pmif_arb, 0, reg, data); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static u32 mt6359p_read_field(u32 reg, u32 mask, u32 shift) |  | ||||||
| { |  | ||||||
| 	return pmif_arb->read_field(pmif_arb, 0, reg, mask, shift); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void mt6359p_write_field(u32 reg, u32 val, u32 mask, u32 shift) |  | ||||||
| { |  | ||||||
| 	pmif_arb->write_field(pmif_arb, 0, reg, val, mask, shift); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void pmic_set_power_hold(void) |  | ||||||
| { |  | ||||||
| 	mt6359p_write_field(PMIC_PWRHOLD, 0x1, 0x1, 0); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void pmic_wdt_set(void) |  | ||||||
| { |  | ||||||
| 	/* [5]=1, RG_WDTRSTB_DEB */ |  | ||||||
| 	mt6359p_write_field(PMIC_TOP_RST_MISC_SET, 0x20, 0xFFFF, 0); |  | ||||||
| 	/* [1]=0, RG_WDTRSTB_MODE */ |  | ||||||
| 	mt6359p_write_field(PMIC_TOP_RST_MISC_CLR, 0x02, 0xFFFF, 0); |  | ||||||
| 	/* [0]=1, RG_WDTRSTB_EN */ |  | ||||||
| 	mt6359p_write_field(PMIC_TOP_RST_MISC_SET, 0x01, 0xFFFF, 0); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void pmic_protect_key_setting(bool lock) |  | ||||||
| { |  | ||||||
| 	for (int i = 0; i < ARRAY_SIZE(key_protect_setting); i++) |  | ||||||
| 		mt6359p_write(key_protect_setting[i].addr, |  | ||||||
| 			      lock ? 0 : key_protect_setting[i].val); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static int check_idle(u32 timeout, u32 addr, u32 mask) |  | ||||||
| { |  | ||||||
| 	if (!wait_us(timeout, !mt6359p_read_field(addr, mask, 0))) |  | ||||||
| 		return -1; |  | ||||||
|  |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static u32 pmic_read_efuse(u32 efuse_bit, u32 mask) |  | ||||||
| { |  | ||||||
| 	u32 efuse_data; |  | ||||||
| 	int index, shift; |  | ||||||
|  |  | ||||||
| 	index = efuse_bit / 16; |  | ||||||
| 	shift = efuse_bit % 16; |  | ||||||
| 	mt6359p_write_field(PMIC_TOP_CKHWEN_CON0, 0, 0x1, 2); |  | ||||||
| 	mt6359p_write_field(PMIC_TOP_CKPDN_CON0, 0, 0x1, 4); |  | ||||||
| 	mt6359p_write_field(PMIC_OTP_CON11, 1, 0x1, 0); |  | ||||||
| 	mt6359p_write_field(PMIC_OTP_CON0, index * 2, 0xFF, 0); |  | ||||||
| 	if (mt6359p_read_field(PMIC_OTP_CON8, 1, 0)) |  | ||||||
| 		mt6359p_write_field(PMIC_OTP_CON8, 0, 1, 0); |  | ||||||
| 	else |  | ||||||
| 		mt6359p_write_field(PMIC_OTP_CON8, 1, 1, 0); |  | ||||||
|  |  | ||||||
| 	udelay(300); |  | ||||||
| 	if (check_idle(EFUSE_WAIT_US, PMIC_OTP_CON13, EFUSE_BUSY)) |  | ||||||
| 		die("[%s] timeout after %d usecs\n", __func__, EFUSE_WAIT_US); |  | ||||||
|  |  | ||||||
| 	udelay(100); |  | ||||||
|  |  | ||||||
| 	efuse_data = mt6359p_read_field(PMIC_OTP_CON12, 0xFFFF, 0); |  | ||||||
| 	efuse_data = (efuse_data >> shift) & mask; |  | ||||||
|  |  | ||||||
| 	mt6359p_write_field(PMIC_TOP_CKHWEN_CON0, 1, 0x1, 2); |  | ||||||
| 	mt6359p_write_field(PMIC_TOP_CKPDN_CON0, 1, 0x1, 4); |  | ||||||
|  |  | ||||||
| 	return efuse_data; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void pmic_init_setting(void) |  | ||||||
| { | { | ||||||
| 	for (int i = 0; i < ARRAY_SIZE(init_setting); i++) | 	for (int i = 0; i < ARRAY_SIZE(init_setting); i++) | ||||||
| 		mt6359p_write_field(init_setting[i].addr, init_setting[i].val, | 		mt6359p_write_field(init_setting[i].addr, init_setting[i].val, | ||||||
| 			init_setting[i].mask, init_setting[i].shift); | 			init_setting[i].mask, init_setting[i].shift); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void pmic_lp_setting(void) | void pmic_lp_setting(void) | ||||||
| { | { | ||||||
| 	for (int i = 0; i < ARRAY_SIZE(lp_setting); i++) | 	for (int i = 0; i < ARRAY_SIZE(lp_setting); i++) | ||||||
| 		mt6359p_write_field(lp_setting[i].addr, lp_setting[i].val, | 		mt6359p_write_field(lp_setting[i].addr, lp_setting[i].val, | ||||||
| 			lp_setting[i].mask, lp_setting[i].shift); | 			lp_setting[i].mask, lp_setting[i].shift); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void pmic_efuse_setting(void) |  | ||||||
| { |  | ||||||
| 	u32 efuse_data; |  | ||||||
| 	struct stopwatch sw; |  | ||||||
|  |  | ||||||
| 	stopwatch_init(&sw); |  | ||||||
|  |  | ||||||
| 	for (int i = 0; i < ARRAY_SIZE(efuse_setting); i++) { |  | ||||||
| 		efuse_data = pmic_read_efuse(efuse_setting[i].efuse_bit, efuse_setting[i].mask); |  | ||||||
| 		mt6359p_write_field(efuse_setting[i].addr, efuse_data, |  | ||||||
| 			efuse_setting[i].mask, efuse_setting[i].shift); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	efuse_data = pmic_read_efuse(EFUSE_RG_VPA_OC_FT, 0x1); |  | ||||||
| 	if (efuse_data) { |  | ||||||
| 		/* restore VPA_DLC initial setting */ |  | ||||||
| 		mt6359p_write(PMIC_BUCK_VPA_DLC_CON0, 0x2810); |  | ||||||
| 		mt6359p_write(PMIC_BUCK_VPA_DLC_CON1, 0x800); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	printk(BIOS_DEBUG, "%s: Set efuses in %ld msecs\n", |  | ||||||
| 	       __func__, stopwatch_duration_msecs(&sw)); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void pmic_wk_vs2_voter_setting(void) |  | ||||||
| { |  | ||||||
| 	/* |  | ||||||
| 	 *  1. Set VS2_VOTER_VOSEL = 1.35V |  | ||||||
| 	 *  2. Clear VS2_VOTER |  | ||||||
| 	 *  3. Set VS2_VOSEL = 1.4V |  | ||||||
| 	 */ |  | ||||||
| 	mt6359p_write_field(PMIC_VS2_VOTER_CFG, 0x2C, 0x7F, 0); |  | ||||||
| 	mt6359p_write_field(PMIC_VS2_VOTER, 0, 0xFFF, 0); |  | ||||||
| 	mt6359p_write_field(PMIC_VS2_ELR0, 0x30, 0x7F, 0); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void mt6359p_buck_set_voltage(u32 buck_id, u32 buck_uv) |  | ||||||
| { |  | ||||||
| 	u32 vol_offset, vol_reg, vol; |  | ||||||
|  |  | ||||||
| 	if (!pmif_arb) |  | ||||||
| 		die("ERROR: pmif_arb not initialized"); |  | ||||||
|  |  | ||||||
| 	switch (buck_id) { |  | ||||||
| 	case MT6359P_GPU11: |  | ||||||
| 		vol_offset = 400000; |  | ||||||
| 		vol_reg = PMIC_VGPU11_ELR0; |  | ||||||
| 		break; |  | ||||||
| 	case MT6359P_SRAM_PROC1: |  | ||||||
| 		vol_offset = 500000; |  | ||||||
| 		vol_reg = PMIC_VSRAM_PROC1_ELR; |  | ||||||
| 		break; |  | ||||||
| 	case MT6359P_SRAM_PROC2: |  | ||||||
| 		vol_offset = 500000; |  | ||||||
| 		vol_reg = PMIC_VSRAM_PROC2_ELR; |  | ||||||
| 		break; |  | ||||||
| 	default: |  | ||||||
| 		die("ERROR: Unknown buck_id %u", buck_id); |  | ||||||
| 		return; |  | ||||||
| 	}; |  | ||||||
|  |  | ||||||
| 	vol = (buck_uv - vol_offset) / 6250; |  | ||||||
| 	mt6359p_write_field(vol_reg, vol, 0x7F, 0); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| u32 mt6359p_buck_get_voltage(u32 buck_id) |  | ||||||
| { |  | ||||||
| 	u32 vol_shift, vol_offset, vol_reg, vol; |  | ||||||
|  |  | ||||||
| 	if (!pmif_arb) |  | ||||||
| 		die("ERROR: pmif_arb not initialized"); |  | ||||||
|  |  | ||||||
| 	switch (buck_id) { |  | ||||||
| 	case MT6359P_GPU11: |  | ||||||
| 		vol_shift = 0; |  | ||||||
| 		vol_offset = 400000; |  | ||||||
| 		vol_reg = PMIC_VGPU11_DBG0; |  | ||||||
| 		break; |  | ||||||
| 	case MT6359P_SRAM_PROC1: |  | ||||||
| 		vol_shift = 8; |  | ||||||
| 		vol_offset = 500000; |  | ||||||
| 		vol_reg = PMIC_VSRAM_PROC1_VOSEL1; |  | ||||||
| 		break; |  | ||||||
| 	case MT6359P_SRAM_PROC2: |  | ||||||
| 		vol_shift = 8; |  | ||||||
| 		vol_offset = 500000; |  | ||||||
| 		vol_reg = PMIC_VSRAM_PROC2_VOSEL1; |  | ||||||
| 		break; |  | ||||||
| 	default: |  | ||||||
| 		die("ERROR: Unknown buck_id %u", buck_id); |  | ||||||
| 		return 0; |  | ||||||
| 	}; |  | ||||||
|  |  | ||||||
| 	vol = mt6359p_read_field(vol_reg, 0x7F, vol_shift); |  | ||||||
| 	return vol_offset + vol * 6250; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void mt6359p_set_vm18_voltage(u32 vm18_uv) |  | ||||||
| { |  | ||||||
| 	u32 reg_vol, reg_cali; |  | ||||||
|  |  | ||||||
| 	if (!pmif_arb) |  | ||||||
| 		die("ERROR: pmif_arb not initialized"); |  | ||||||
|  |  | ||||||
| 	assert(vm18_uv >= 1700000); |  | ||||||
| 	assert(vm18_uv < 2000000); |  | ||||||
|  |  | ||||||
| 	reg_vol = (vm18_uv / 1000 - VM18_VOL_OFFSET) / 100; |  | ||||||
| 	reg_cali = ((vm18_uv / 1000) % 100) / 10; |  | ||||||
| 	mt6359p_write(PMIC_VM18_ANA_CON0, (reg_vol << VM18_VOL_REG_SHIFT) | reg_cali); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| u32 mt6359p_get_vm18_voltage(void) |  | ||||||
| { |  | ||||||
| 	u32 reg_vol, reg_cali; |  | ||||||
|  |  | ||||||
| 	if (!pmif_arb) |  | ||||||
| 		die("ERROR: pmif_arb not initialized"); |  | ||||||
|  |  | ||||||
| 	reg_vol = 100 * mt6359p_read_field(PMIC_VM18_ANA_CON0, 0xF, VM18_VOL_REG_SHIFT); |  | ||||||
| 	reg_cali = 10 * mt6359p_read_field(PMIC_VM18_ANA_CON0, 0xF, 0); |  | ||||||
| 	return 1000 * (VM18_VOL_OFFSET + reg_vol + reg_cali); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void init_pmif_arb(void) |  | ||||||
| { |  | ||||||
| 	if (!pmif_arb) { |  | ||||||
| 		pmif_arb = get_pmif_controller(PMIF_SPI, 0); |  | ||||||
| 		if (!pmif_arb) |  | ||||||
| 			die("ERROR: No spi device"); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if (pmif_arb->is_pmif_init_done(pmif_arb)) |  | ||||||
| 		die("ERROR - Failed to initialize pmif spi"); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void mt6359p_init(void) |  | ||||||
| { |  | ||||||
| 	init_pmif_arb(); |  | ||||||
| 	pmic_set_power_hold(); |  | ||||||
| 	pmic_wdt_set(); |  | ||||||
| 	pmic_protect_key_setting(false); |  | ||||||
| 	pmic_init_setting(); |  | ||||||
| 	pmic_lp_setting(); |  | ||||||
| 	pmic_efuse_setting(); |  | ||||||
| 	pmic_protect_key_setting(true); |  | ||||||
| 	pmic_wk_vs2_voter_setting(); |  | ||||||
| } |  | ||||||
|   | |||||||
| @@ -84,7 +84,7 @@ static u32 pmif_get_ulposc_freq_mhz(u32 cali_val) | |||||||
| 	return result / 1000; | 	return result / 1000; | ||||||
| } | } | ||||||
|  |  | ||||||
| static int pmif_ulposc_cali(void) | static int pmif_ulposc_cali(u32 target_val) | ||||||
| { | { | ||||||
| 	u32 current_val = 0, min = 0, max = CAL_MAX_VAL, middle; | 	u32 current_val = 0, min = 0, max = CAL_MAX_VAL, middle; | ||||||
| 	int ret = 0, diff_by_min, diff_by_max, cal_result; | 	int ret = 0, diff_by_min, diff_by_max, cal_result; | ||||||
| @@ -95,16 +95,16 @@ static int pmif_ulposc_cali(void) | |||||||
| 			break; | 			break; | ||||||
|  |  | ||||||
| 		current_val = pmif_get_ulposc_freq_mhz(middle); | 		current_val = pmif_get_ulposc_freq_mhz(middle); | ||||||
| 		if (current_val > FREQ_260MHZ) | 		if (current_val > target_val) | ||||||
| 			max = middle; | 			max = middle; | ||||||
| 		else | 		else | ||||||
| 			min = middle; | 			min = middle; | ||||||
| 	} while (min <= max); | 	} while (min <= max); | ||||||
|  |  | ||||||
| 	diff_by_min = pmif_get_ulposc_freq_mhz(min) - FREQ_260MHZ; | 	diff_by_min = pmif_get_ulposc_freq_mhz(min) - target_val; | ||||||
| 	diff_by_min = ABS(diff_by_min); | 	diff_by_min = ABS(diff_by_min); | ||||||
|  |  | ||||||
| 	diff_by_max = pmif_get_ulposc_freq_mhz(max) - FREQ_260MHZ; | 	diff_by_max = pmif_get_ulposc_freq_mhz(max) - target_val; | ||||||
| 	diff_by_max = ABS(diff_by_max); | 	diff_by_max = ABS(diff_by_max); | ||||||
|  |  | ||||||
| 	if (diff_by_min < diff_by_max) { | 	if (diff_by_min < diff_by_max) { | ||||||
| @@ -116,8 +116,8 @@ static int pmif_ulposc_cali(void) | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/* check if calibrated value is in the range of target value +- 15% */ | 	/* check if calibrated value is in the range of target value +- 15% */ | ||||||
| 	if (current_val < (FREQ_260MHZ * (1000 - CAL_TOL_RATE) / 1000) || | 	if (current_val < (target_val * (1000 - CAL_TOL_RATE) / 1000) || | ||||||
| 		current_val > (FREQ_260MHZ * (1000 + CAL_TOL_RATE) / 1000)) { | 		current_val > (target_val * (1000 + CAL_TOL_RATE) / 1000)) { | ||||||
| 		printk(BIOS_ERR, "[%s] calibration fail: %dM\n", __func__, current_val); | 		printk(BIOS_ERR, "[%s] calibration fail: %dM\n", __func__, current_val); | ||||||
| 		ret = 1; | 		ret = 1; | ||||||
| 	} | 	} | ||||||
| @@ -140,7 +140,7 @@ static int pmif_init_ulposc(void) | |||||||
| 	udelay(100); | 	udelay(100); | ||||||
| 	SET32_BITFIELDS(&mtk_spm->ulposc_con, ULPOSC_CG_EN, 1); | 	SET32_BITFIELDS(&mtk_spm->ulposc_con, ULPOSC_CG_EN, 1); | ||||||
|  |  | ||||||
| 	return pmif_ulposc_cali(); | 	return pmif_ulposc_cali(FREQ_260MHZ); | ||||||
| } | } | ||||||
|  |  | ||||||
| int pmif_clk_init(void) | int pmif_clk_init(void) | ||||||
|   | |||||||
| @@ -1,332 +1,14 @@ | |||||||
| /* SPDX-License-Identifier: GPL-2.0-only */ | /* SPDX-License-Identifier: GPL-2.0-only */ | ||||||
|  |  | ||||||
| #include <console/console.h> |  | ||||||
| #include <delay.h> |  | ||||||
| #include <device/mmio.h> | #include <device/mmio.h> | ||||||
| #include <soc/infracfg.h> | #include <soc/iocfg.h> | ||||||
| #include <soc/pll.h> |  | ||||||
| #include <soc/pmif.h> |  | ||||||
| #include <soc/pmif_spi.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 */ | /* IOCFG_LM, PWRAP_SPI0_DRIVING */ | ||||||
| DEFINE_BITFIELD(PWRAP_SPI0_DRIVING, 2, 0) | DEFINE_BITFIELD(PWRAP_SPI0_DRIVING, 2, 0) | ||||||
|  |  | ||||||
| static void pmif_spi_config(struct pmif *arb) | void pmif_spi_iocfg(void) | ||||||
| { |  | ||||||
| 	/* 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 */ | 	/* Set SoC SPI IO driving strength to 4 mA */ | ||||||
| 	SET32_BITFIELDS(&mtk_iocfg_lm->drv_cfg1, PWRAP_SPI0_DRIVING, IO_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; |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,17 +1,9 @@ | |||||||
| /* SPDX-License-Identifier: GPL-2.0-only */ | /* SPDX-License-Identifier: GPL-2.0-only */ | ||||||
|  |  | ||||||
| #include <console/console.h> |  | ||||||
| #include <device/mmio.h> | #include <device/mmio.h> | ||||||
| #include <soc/addressmap.h> | #include <soc/iocfg.h> | ||||||
| #include <soc/pll.h> | #include <soc/pll.h> | ||||||
| #include <soc/pll_common.h> |  | ||||||
| #include <soc/pmif.h> |  | ||||||
| #include <soc/pmif_spmi.h> | #include <soc/pmif_spmi.h> | ||||||
| #include <soc/pmif_sw.h> |  | ||||||
| #include <soc/spmi.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 */ | /* IOCFG_BM, DRV_CFG2 */ | ||||||
| DEFINE_BITFIELD(SPMI_SCL, 5, 3) | DEFINE_BITFIELD(SPMI_SCL, 5, 3) | ||||||
| @@ -29,34 +21,7 @@ DEFINE_BIT(PDN_SPMI_MST, 15) | |||||||
| /* TOPCKGEN, CLK_CFG_UPDATE2 */ | /* TOPCKGEN, CLK_CFG_UPDATE2 */ | ||||||
| DEFINE_BIT(SPMI_MST_CK_UPDATE, 30) | DEFINE_BIT(SPMI_MST_CK_UPDATE, 30) | ||||||
|  |  | ||||||
| /* SPMI_MST, SPMI_SAMPL_CTRL */ | int spmi_config_master(void) | ||||||
| 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 */ | 	/* Software reset */ | ||||||
| 	SET32_BITFIELDS(&mtk_rug->wdt_swsysrst2, SPMI_MST_RST, 1, UNLOCK_KEY, 0x85); | 	SET32_BITFIELDS(&mtk_rug->wdt_swsysrst2, SPMI_MST_RST, 1, UNLOCK_KEY, 0x85); | ||||||
| @@ -76,166 +41,7 @@ static int spmi_config_master(void) | |||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| static int spmi_read_check(struct pmif *pmif_arb, int slvid) | void pmif_spmi_iocfg(void) | ||||||
| { | { | ||||||
| 	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); | 	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