Yidi Lin | 2368a31 | 2021-02-02 21:00:36 +0800 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
| 2 | |
| 3 | #include <console/console.h> |
| 4 | #include <device/mmio.h> |
| 5 | #include <soc/addressmap.h> |
| 6 | #include <soc/pmif.h> |
| 7 | #include <soc/pmif_spmi.h> |
| 8 | #include <soc/pmif_sw.h> |
| 9 | #include <soc/spmi.h> |
| 10 | |
Yidi Lin | 2368a31 | 2021-02-02 21:00:36 +0800 | [diff] [blame] | 11 | /* SPMI_MST, SPMI_SAMPL_CTRL */ |
| 12 | DEFINE_BIT(SAMPL_CK_POL, 0) |
| 13 | DEFINE_BITFIELD(SAMPL_CK_DLY, 3, 1) |
| 14 | |
| 15 | /* PMIF, SPI_MODE_CTRL */ |
| 16 | DEFINE_BIT(SPI_MODE_CTRL, 7) |
| 17 | DEFINE_BIT(SRVOL_EN, 11) |
| 18 | DEFINE_BIT(SPI_MODE_EXT_CMD, 12) |
| 19 | DEFINE_BIT(SPI_EINT_MODE_GATING_EN, 13) |
| 20 | |
| 21 | /* PMIF, SLEEP_PROTECTION_CTRL */ |
| 22 | DEFINE_BITFIELD(SPM_SLEEP_REQ_SEL, 1, 0) |
| 23 | DEFINE_BITFIELD(SCP_SLEEP_REQ_SEL, 10, 9) |
| 24 | |
Sen Chu | 28dceae | 2022-10-18 13:41:09 +0800 | [diff] [blame] | 25 | __weak void pmif_spmi_config(struct pmif *arb, int mstid) |
| 26 | { |
| 27 | /* Do nothing. */ |
| 28 | } |
| 29 | |
Yidi Lin | 2368a31 | 2021-02-02 21:00:36 +0800 | [diff] [blame] | 30 | static int spmi_read_check(struct pmif *pmif_arb, int slvid) |
| 31 | { |
| 32 | u32 rdata = 0; |
| 33 | |
| 34 | pmif_arb->read(pmif_arb, slvid, MT6315_READ_TEST, &rdata); |
| 35 | if (rdata != MT6315_DEFAULT_VALUE_READ) { |
Rex-BC Chen | d4cdf5d | 2022-05-06 14:52:01 +0800 | [diff] [blame] | 36 | printk(BIOS_INFO, "%s next, slvid:%d rdata = 0x%x.\n", |
Yidi Lin | 2368a31 | 2021-02-02 21:00:36 +0800 | [diff] [blame] | 37 | __func__, slvid, rdata); |
| 38 | return -E_NODEV; |
| 39 | } |
| 40 | |
| 41 | pmif_arb->read(pmif_arb, slvid, MT6315_READ_TEST_1, &rdata); |
| 42 | if (rdata != MT6315_DEFAULT_VALUE_READ) { |
Rex-BC Chen | d4cdf5d | 2022-05-06 14:52:01 +0800 | [diff] [blame] | 43 | printk(BIOS_INFO, "%s next, slvid:%d rdata = 0x%x.\n", |
Yidi Lin | 2368a31 | 2021-02-02 21:00:36 +0800 | [diff] [blame] | 44 | __func__, slvid, rdata); |
| 45 | return -E_NODEV; |
| 46 | } |
| 47 | |
| 48 | return 0; |
| 49 | } |
| 50 | |
| 51 | static int spmi_cali_rd_clock_polarity(struct pmif *pmif_arb, const struct spmi_device *dev) |
| 52 | { |
| 53 | int i; |
| 54 | bool success = false; |
| 55 | const struct cali cali_data[] = { |
| 56 | {SPMI_CK_DLY_1T, SPMI_CK_POL_POS}, |
| 57 | {SPMI_CK_NO_DLY, SPMI_CK_POL_POS}, |
| 58 | {SPMI_CK_NO_DLY, SPMI_CK_POL_NEG}, |
| 59 | {SPMI_CK_DLY_1T, SPMI_CK_POL_NEG}, |
| 60 | }; |
| 61 | |
| 62 | /* Indicate sampling clock polarity, 1: Positive 0: Negative */ |
| 63 | for (i = 0; i < ARRAY_SIZE(cali_data); i++) { |
| 64 | SET32_BITFIELDS(&mtk_spmi_mst->mst_sampl, SAMPL_CK_DLY, cali_data[i].dly, |
| 65 | SAMPL_CK_POL, cali_data[i].pol); |
| 66 | if (spmi_read_check(pmif_arb, dev->slvid) == 0) { |
| 67 | success = true; |
| 68 | break; |
| 69 | } |
| 70 | } |
| 71 | |
| 72 | if (!success) |
| 73 | die("ERROR - calibration fail for spmi clk"); |
| 74 | |
| 75 | return 0; |
| 76 | } |
| 77 | |
| 78 | static int spmi_mst_init(struct pmif *pmif_arb) |
| 79 | { |
Hui Liu | a5c9682 | 2022-07-05 14:53:22 +0800 | [diff] [blame] | 80 | size_t i; |
Yidi Lin | 2368a31 | 2021-02-02 21:00:36 +0800 | [diff] [blame] | 81 | |
| 82 | if (!pmif_arb) { |
| 83 | printk(BIOS_ERR, "%s: null pointer for pmif dev.\n", __func__); |
| 84 | return -E_INVAL; |
| 85 | } |
| 86 | |
Rex-BC Chen | 1543252 | 2022-10-19 19:00:22 +0800 | [diff] [blame] | 87 | if (!CONFIG(PMIF_SPMI_IOCFG_DEFAULT_SETTING)) |
| 88 | pmif_spmi_iocfg(); |
Yidi Lin | 2368a31 | 2021-02-02 21:00:36 +0800 | [diff] [blame] | 89 | spmi_config_master(); |
| 90 | |
Hui Liu | a5c9682 | 2022-07-05 14:53:22 +0800 | [diff] [blame] | 91 | for (i = 0; i < spmi_dev_cnt; i++) |
Yidi Lin | 2368a31 | 2021-02-02 21:00:36 +0800 | [diff] [blame] | 92 | spmi_cali_rd_clock_polarity(pmif_arb, &spmi_dev[i]); |
| 93 | |
| 94 | return 0; |
| 95 | } |
| 96 | |
| 97 | static void pmif_spmi_force_normal_mode(int mstid) |
| 98 | { |
| 99 | struct pmif *arb = get_pmif_controller(PMIF_SPMI, mstid); |
| 100 | |
| 101 | /* listen srclken_0 only for entering normal or sleep mode */ |
| 102 | SET32_BITFIELDS(&arb->mtk_pmif->spi_mode_ctrl, |
| 103 | SPI_MODE_CTRL, 0, |
| 104 | SRVOL_EN, 0, |
| 105 | SPI_MODE_EXT_CMD, 1, |
| 106 | SPI_EINT_MODE_GATING_EN, 1); |
| 107 | |
| 108 | /* enable spm/scp sleep request */ |
| 109 | SET32_BITFIELDS(&arb->mtk_pmif->sleep_protection_ctrl, SPM_SLEEP_REQ_SEL, 0, |
| 110 | SCP_SLEEP_REQ_SEL, 0); |
| 111 | } |
| 112 | |
| 113 | static void pmif_spmi_enable_swinf(int mstid) |
| 114 | { |
| 115 | struct pmif *arb = get_pmif_controller(PMIF_SPMI, mstid); |
| 116 | |
| 117 | write32(&arb->mtk_pmif->inf_en, PMIF_SPMI_SW_CHAN); |
| 118 | write32(&arb->mtk_pmif->arb_en, PMIF_SPMI_SW_CHAN); |
| 119 | } |
| 120 | |
| 121 | static void pmif_spmi_enable_cmdIssue(int mstid, bool en) |
| 122 | { |
| 123 | struct pmif *arb = get_pmif_controller(PMIF_SPMI, mstid); |
| 124 | |
| 125 | /* Enable cmdIssue */ |
| 126 | write32(&arb->mtk_pmif->cmdissue_en, en); |
| 127 | } |
| 128 | |
| 129 | static void pmif_spmi_enable(int mstid) |
| 130 | { |
| 131 | struct pmif *arb = get_pmif_controller(PMIF_SPMI, mstid); |
Yidi Lin | 2368a31 | 2021-02-02 21:00:36 +0800 | [diff] [blame] | 132 | |
Sen Chu | 28dceae | 2022-10-18 13:41:09 +0800 | [diff] [blame] | 133 | pmif_spmi_config(arb, mstid); |
Yidi Lin | 2368a31 | 2021-02-02 21:00:36 +0800 | [diff] [blame] | 134 | |
| 135 | /* |
| 136 | * set bytecnt max limitation. |
| 137 | * hw bytecnt indicate when we set 0, it can send 1 byte; |
| 138 | * set 1, it can send 2 byte. |
| 139 | */ |
| 140 | write32(&arb->mtk_pmif->inf_max_bytecnt_per_0, 0); |
| 141 | write32(&arb->mtk_pmif->inf_max_bytecnt_per_1, 0); |
| 142 | write32(&arb->mtk_pmif->inf_max_bytecnt_per_2, 0); |
| 143 | write32(&arb->mtk_pmif->inf_max_bytecnt_per_3, 0); |
| 144 | |
| 145 | /* Add latency limitation */ |
| 146 | write32(&arb->mtk_pmif->lat_cnter_en, PMIF_SPMI_INF); |
| 147 | write32(&arb->mtk_pmif->lat_limit_0, 0); |
| 148 | write32(&arb->mtk_pmif->lat_limit_1, 0x4); |
| 149 | write32(&arb->mtk_pmif->lat_limit_2, 0x8); |
| 150 | write32(&arb->mtk_pmif->lat_limit_4, 0x8); |
| 151 | write32(&arb->mtk_pmif->lat_limit_6, 0x3FF); |
| 152 | write32(&arb->mtk_pmif->lat_limit_9, 0x4); |
| 153 | write32(&arb->mtk_pmif->lat_limit_loading, PMIF_SPMI_INF); |
| 154 | |
| 155 | write32(&arb->mtk_pmif->inf_en, PMIF_SPMI_INF); |
| 156 | write32(&arb->mtk_pmif->arb_en, PMIF_SPMI_INF); |
| 157 | write32(&arb->mtk_pmif->timer_ctrl, 0x3); |
| 158 | write32(&arb->mtk_pmif->init_done, 1); |
| 159 | } |
| 160 | |
| 161 | int pmif_spmi_init(struct pmif *arb) |
| 162 | { |
| 163 | if (arb->is_pmif_init_done(arb) != 0) { |
| 164 | pmif_spmi_force_normal_mode(arb->mstid); |
| 165 | pmif_spmi_enable_swinf(arb->mstid); |
| 166 | pmif_spmi_enable_cmdIssue(arb->mstid, true); |
| 167 | pmif_spmi_enable(arb->mstid); |
| 168 | if (arb->is_pmif_init_done(arb)) |
| 169 | return -E_NODEV; |
| 170 | } |
| 171 | |
| 172 | if (spmi_mst_init(arb)) { |
| 173 | printk(BIOS_ERR, "[%s] failed to init spmi master\n", __func__); |
| 174 | return -E_NODEV; |
| 175 | } |
| 176 | |
| 177 | return 0; |
| 178 | } |