Yuchen Huang | ec39cb3 | 2020-09-23 20:41:19 +0800 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
| 2 | |
| 3 | #include <console/console.h> |
| 4 | #include <delay.h> |
| 5 | #include <device/mmio.h> |
| 6 | #include <soc/clkbuf.h> |
| 7 | #include <soc/pmif.h> |
Yuchen Huang | 6a6e58c | 2021-04-11 15:28:20 +0800 | [diff] [blame] | 8 | #if CONFIG(SRCLKEN_RC_SUPPORT) |
Yuchen Huang | ec39cb3 | 2020-09-23 20:41:19 +0800 | [diff] [blame] | 9 | #include <soc/srclken_rc.h> |
Yuchen Huang | 6a6e58c | 2021-04-11 15:28:20 +0800 | [diff] [blame] | 10 | #endif |
Yuchen Huang | ec39cb3 | 2020-09-23 20:41:19 +0800 | [diff] [blame] | 11 | |
| 12 | #define BUFTAG "[CLKBUF]" |
| 13 | #define buf_info(fmt, arg ...) printk(BIOS_INFO, BUFTAG "%s,%d: " fmt, \ |
| 14 | __func__, __LINE__, ## arg) |
| 15 | |
| 16 | #define _buf_clrset32_impl(addr, clear, set) \ |
| 17 | buf_write(addr, (buf_read(addr) & ~((uint32_t)(clear))) | (set)) |
| 18 | |
| 19 | #define BUF_SET_FIELDS(addr, ...) \ |
| 20 | _BF_IMPL(_buf_clrset32_impl, addr, __VA_ARGS__) |
| 21 | #define BUF_READ_FIELD(addr, name) \ |
| 22 | EXTRACT_BITFIELD(buf_read(addr), name) |
| 23 | |
| 24 | #define PMIC_CW00_INIT_VAL 0x4005 /* 0100 0000 0000 0101 */ |
| 25 | #define PMIC_CW09_INIT_VAL 0x01F0 /* 0000 0001 1111 0000 */ |
| 26 | |
| 27 | static struct pmif *pmif_arb; |
| 28 | |
| 29 | static u32 buf_read(u32 addr) |
| 30 | { |
| 31 | u32 rdata; |
| 32 | |
Elyes Haouas | 0f1fb8a | 2022-09-13 09:57:30 +0200 | [diff] [blame] | 33 | if (!pmif_arb) |
Yuchen Huang | ec39cb3 | 2020-09-23 20:41:19 +0800 | [diff] [blame] | 34 | pmif_arb = get_pmif_controller(PMIF_SPI, 0); |
| 35 | pmif_arb->read(pmif_arb, 0, addr, &rdata); |
| 36 | |
| 37 | return rdata; |
| 38 | } |
| 39 | |
| 40 | static void buf_write(u32 addr, u32 wdata) |
| 41 | { |
Elyes Haouas | 0f1fb8a | 2022-09-13 09:57:30 +0200 | [diff] [blame] | 42 | if (!pmif_arb) |
Yuchen Huang | ec39cb3 | 2020-09-23 20:41:19 +0800 | [diff] [blame] | 43 | pmif_arb = get_pmif_controller(PMIF_SPI, 0); |
| 44 | pmif_arb->write(pmif_arb, 0, addr, wdata); |
| 45 | } |
| 46 | |
| 47 | static void dump_clkbuf_log(void) |
| 48 | { |
| 49 | u32 pmic_cw00, pmic_cw09, pmic_cw12, pmic_cw13, pmic_cw15, pmic_cw19, |
| 50 | top_spi_con1, ldo_vrfck_op_en, ldo_vbbck_op_en, ldo_vrfck_en, |
| 51 | ldo_vbbck_en, vrfck_hv_en; |
| 52 | |
| 53 | pmic_cw00 = BUF_READ_FIELD(PMIC_RG_DCXO_CW00, PMIC_REG_COMMON); |
| 54 | pmic_cw09 = BUF_READ_FIELD(PMIC_RG_DCXO_CW09, PMIC_REG_COMMON); |
| 55 | pmic_cw12 = BUF_READ_FIELD(PMIC_RG_DCXO_CW12, PMIC_REG_COMMON); |
| 56 | pmic_cw13 = BUF_READ_FIELD(PMIC_RG_DCXO_CW13, PMIC_REG_COMMON); |
| 57 | pmic_cw15 = BUF_READ_FIELD(PMIC_RG_DCXO_CW15, PMIC_REG_COMMON); |
| 58 | pmic_cw19 = BUF_READ_FIELD(PMIC_RG_DCXO_CW19, PMIC_REG_COMMON); |
| 59 | buf_info("DCXO_CW00/09/12/13/15/19=%#x %#x %#x %#x %#x %#x\n", |
| 60 | pmic_cw00, pmic_cw09, pmic_cw12, |
| 61 | pmic_cw13, pmic_cw15, pmic_cw19); |
| 62 | |
| 63 | top_spi_con1 = BUF_READ_FIELD(PMIC_RG_TOP_SPI_CON1, PMIC_RG_SRCLKEN_IN3_EN); |
| 64 | ldo_vrfck_op_en = BUF_READ_FIELD(PMIC_RG_LDO_VRFCK_OP_EN, |
| 65 | PMIC_RG_LDO_VRFCK_HW14_OP_EN); |
| 66 | ldo_vbbck_op_en = BUF_READ_FIELD(PMIC_RG_LDO_VBBCK_OP_EN, |
| 67 | PMIC_RG_LDO_VBBCK_HW14_OP_EN); |
| 68 | ldo_vrfck_en = BUF_READ_FIELD(PMIC_RG_LDO_VRFCK_CON0, PMIC_RG_LDO_VRFCK_EN); |
| 69 | ldo_vbbck_en = BUF_READ_FIELD(PMIC_RG_LDO_VBBCK_CON0, PMIC_RG_LDO_VBBCK_EN); |
| 70 | buf_info("spi_con1/ldo_rf_op/ldo_bb_op/ldo_rf_en/ldo_bb_en=%#x %#x %#x %#x %#x\n", |
| 71 | top_spi_con1, ldo_vrfck_op_en, ldo_vbbck_op_en, |
| 72 | ldo_vrfck_en, ldo_vbbck_en); |
| 73 | |
| 74 | vrfck_hv_en = BUF_READ_FIELD(PMIC_RG_DCXO_ADLDO_BIAS_ELR_0, PMIC_RG_VRFCK_HV_EN); |
| 75 | buf_info("clk buf vrfck_hv_en=%#x\n", vrfck_hv_en); |
| 76 | } |
| 77 | |
| 78 | int clk_buf_init(void) |
| 79 | { |
| 80 | /* Dump registers before setting */ |
| 81 | dump_clkbuf_log(); |
| 82 | |
| 83 | /* Unlock pmic key */ |
| 84 | BUF_SET_FIELDS(PMIC_TOP_TMA_KEY, PMIC_REG_COMMON, PMIC_TOP_TMA_KEY_UNLOCK); |
| 85 | |
| 86 | /* 1.1 Set VRFCK input supply(11.ac mode) */ |
| 87 | BUF_SET_FIELDS(PMIC_RG_DCXO_ADLDO_BIAS_ELR_0, PMIC_RG_VRFCK_HV_EN, 0x0); |
| 88 | |
| 89 | /* 1.2.0 Set VRFCK En = 0 */ |
| 90 | BUF_SET_FIELDS(PMIC_RG_LDO_VRFCK_CON0, PMIC_RG_LDO_VRFCK_EN, 0x0); |
| 91 | /* 1.2.1 Set VRFCK1 as power src */ |
| 92 | BUF_SET_FIELDS(PMIC_RG_LDO_VRFCK_ELR, PMIC_RG_LDO_VRFCK_ANA_SEL, 0x1); |
| 93 | |
| 94 | /* 1.2.2 Switch LDO-RFCK to LDO-RFCK1 */ |
| 95 | BUF_SET_FIELDS(PMIC_RG_DCXO_ADLDO_BIAS_ELR_0, PMIC_RG_VRFCK_NDIS_EN, 0x0); |
| 96 | BUF_SET_FIELDS(PMIC_RG_DCXO_ADLDO_BIAS_ELR_1, PMIC_RG_VRFCK_1_NDIS_EN, 0x1); |
| 97 | |
| 98 | /* 1.2.0 Set VRFCK En = 1 */ |
| 99 | BUF_SET_FIELDS(PMIC_RG_LDO_VRFCK_CON0, PMIC_RG_LDO_VRFCK_EN, 0x1); |
| 100 | |
| 101 | /* 1.2.3 Lock pmic key */ |
| 102 | BUF_SET_FIELDS(PMIC_TOP_TMA_KEY, PMIC_REG_COMMON, 0x0); |
| 103 | |
| 104 | /* Enable XO LDO */ |
| 105 | BUF_SET_FIELDS(PMIC_RG_LDO_VRFCK_OP_EN_SET, PMIC_RG_LDO_VRFCK_HW14_OP_EN, 0x1); |
| 106 | BUF_SET_FIELDS(PMIC_RG_LDO_VBBCK_OP_EN_SET, PMIC_RG_LDO_VBBCK_HW14_OP_EN, 0x1); |
| 107 | BUF_SET_FIELDS(PMIC_RG_LDO_VRFCK_CON0, PMIC_RG_LDO_VRFCK_EN, 0x0); |
| 108 | BUF_SET_FIELDS(PMIC_RG_LDO_VBBCK_CON0, PMIC_RG_LDO_VBBCK_EN, 0x0); |
| 109 | |
| 110 | /* Enable 26M control */ |
| 111 | if (!CONFIG(SRCLKEN_RC_SUPPORT)) { |
| 112 | /* Legacy co-clock mode */ |
| 113 | BUF_SET_FIELDS(PMIC_RG_TOP_SPI_CON1, PMIC_RG_SRCLKEN_IN3_EN, 0x0); |
| 114 | |
| 115 | BUF_SET_FIELDS(PMIC_RG_DCXO_CW00, PMIC_REG_COMMON, PMIC_CW00_INIT_VAL); |
| 116 | BUF_SET_FIELDS(PMIC_RG_DCXO_CW09, PMIC_REG_COMMON, PMIC_CW09_INIT_VAL); |
| 117 | } else { |
| 118 | /* New co-clock mode */ |
| 119 | /* All XO mode should set to 2'b01 */ |
| 120 | BUF_SET_FIELDS(PMIC_RG_DCXO_CW00, PMIC_REG_COMMON, PMIC_CW00_INIT_VAL); |
| 121 | BUF_SET_FIELDS(PMIC_RG_DCXO_CW09, PMIC_REG_COMMON, PMIC_CW09_INIT_VAL); |
| 122 | |
| 123 | /* 1. Update control mapping table */ |
| 124 | BUF_SET_FIELDS(PMIC_RG_XO_BUF_CTL0, PMIC_RG_XO_VOTE, 0x005); |
| 125 | BUF_SET_FIELDS(PMIC_RG_XO_BUF_CTL1, PMIC_RG_XO_VOTE, 0x0); |
| 126 | BUF_SET_FIELDS(PMIC_RG_XO_BUF_CTL2, PMIC_RG_XO_VOTE, 0x0); |
| 127 | BUF_SET_FIELDS(PMIC_RG_XO_BUF_CTL3, PMIC_RG_XO_VOTE, 0x0); |
| 128 | BUF_SET_FIELDS(PMIC_RG_XO_BUF_CTL4, PMIC_RG_XO_VOTE, 0x0); |
| 129 | /* Wait 100us */ |
| 130 | udelay(100); |
| 131 | |
| 132 | /* 2. Switch to new control mode */ |
| 133 | BUF_SET_FIELDS(PMIC_RG_DCXO_CW08, PMIC_RG_XO_PMIC_TOP_DIG_SW, 0x0); |
| 134 | } |
| 135 | |
| 136 | /* Check if the setting is ok */ |
| 137 | dump_clkbuf_log(); |
| 138 | |
| 139 | return 0; |
| 140 | } |