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:
parent
15ddb363d4
commit
2368a310be
|
@ -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__ */
|
|
@ -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__ */
|
|
@ -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__ */
|
|
@ -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();
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue