Yidi Lin has submitted this change. ( https://review.coreboot.org/c/coreboot/+/85128?usp=email )
Change subject: soc/mediatek/mt8196: Add PMIC MT6363 ADC driver ......................................................................
soc/mediatek/mt8196: Add PMIC MT6363 ADC driver
Add MT6363 AUXADC driver support, which is essential for handling the Analog-to-Digital Conversion (ADC) functionalities in the MT8196 SoC.
TEST=build pass BUG=b:317009620
Change-Id: Ice3c286cd207e445392d5f0126a07ce4f40dcf8a Signed-off-by: Hope Wang hope.wang@mediatek.corp-partner.google.com Reviewed-on: https://review.coreboot.org/c/coreboot/+/85128 Reviewed-by: Yidi Lin yidilin@google.com Tested-by: build bot (Jenkins) no-reply@coreboot.org Reviewed-by: Yu-Ping Wu yupingso@google.com --- A src/soc/mediatek/common/include/soc/mt6363_sdmadc.h A src/soc/mediatek/common/mt6363_sdmadc.c M src/soc/mediatek/mt8196/Makefile.mk 3 files changed, 203 insertions(+), 0 deletions(-)
Approvals: Yidi Lin: Looks good to me, approved build bot (Jenkins): Verified Yu-Ping Wu: Looks good to me, approved
diff --git a/src/soc/mediatek/common/include/soc/mt6363_sdmadc.h b/src/soc/mediatek/common/include/soc/mt6363_sdmadc.h new file mode 100644 index 0000000..ae990c9 --- /dev/null +++ b/src/soc/mediatek/common/include/soc/mt6363_sdmadc.h @@ -0,0 +1,90 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef __MT6363_SDMADC_H__ +#define __MT6363_SDMADC_H__ + +#include <soc/spmi.h> +#include <types.h> + +enum { + PMIC_AUXADC_ADC_OUT_CH12_L_ADDR = 0x10d2, + MT6363_AUXADC_RQST1 = 0x1109, + PMIC_SDMADC_EXT_THR_SRC_SEL_ADDR = 0x11c4, +}; + +/* + * enum auxadc_channels - enumeration of auxadc channels + */ +enum auxadc_channel { + AUXADC_CHAN_VIN1, + AUXADC_CHAN_VIN2, + AUXADC_CHAN_VIN3, + AUXADC_CHAN_VIN4, + AUXADC_CHAN_VIN5, + AUXADC_CHAN_VIN6, + AUXADC_CHAN_VIN7, + AUXADC_CHAN_MAX, +}; + +/* + * enum sdmadc_pures - enumeration of sdmadc pull up resistor + */ +enum sdmadc_pures { + SDMADC_100K, + SDMADC_30K, + SDMADC_400K, + SDMADC_OPEN, +}; + +/** + * enum auxadc_val_type - enumeration of auxadc value's type + */ +enum auxadc_val_type { + AUXADC_VAL_PROCESSED, + AUXADC_VAL_RAW, +}; + +/** + * struct auxadc_chan_spec - specification of an auxadc channel + * @channel: What auxadc_channel is it. + * @hw_info: Hardware design level information + * @hw_info.ref_volt Reference voltage + * @hw_info.ratio: Resistor Ratio. + * If read operation is not provided, the processed + * value will be calculated as following: + * (raw value * ratio[0] * ref_volt) / ratio[1] + * @hw_info.max_time: Maximum wait time(us). + * @hw_info.min_time: Minimum wait time(us). + * @hw_info.poll_time: Wait time(us) between every polling during retry. + * @hw_info.enable_reg Register address of enable control. + * @hw_info.enable_mask Mask of enable control. + * @hw_info.ready_reg Register address of channel's ready status. + * @hw_info.ready_mask Mask of ready status. + * @hw_info.value_reg Register address of raw value. + * @hw_info.res Resolution of this channel (number of valid bits). + */ +struct auxadc_chan_spec { + int channel; + struct { + u32 ref_volt; + u32 ratio[2]; + u32 max_time; + u32 min_time; + u32 poll_time; + u32 enable_reg; + u32 enable_mask; + u32 ready_reg; + u32 ready_mask; + u32 value_reg; + u8 res; + } hw_info; + struct { + u32 set_reg; + u32 cmd; + } sdmadc_hw_info; +}; + +int mt6363_sdmadc_read(enum auxadc_channel channel, int *val, enum sdmadc_pures pures, + enum auxadc_val_type type); + +#endif /* __MT6363_SDMADC_H__ */ diff --git a/src/soc/mediatek/common/mt6363_sdmadc.c b/src/soc/mediatek/common/mt6363_sdmadc.c new file mode 100644 index 0000000..eb4b978 --- /dev/null +++ b/src/soc/mediatek/common/mt6363_sdmadc.c @@ -0,0 +1,112 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR MIT */ + +/* + * These values are used by MediaTek internally. + * We can find these registers in "MT6363TP_PMIC_Design_Notice_for_MT8196G_V0.2" + * Chapter number: 2.15. + * The setting values are provided by MeidaTek designers. + */ + +#include <assert.h> +#include <console/console.h> +#include <delay.h> +#include <soc/mt6363.h> +#include <soc/mt6363_sdmadc.h> +#include <soc/pmif.h> +#include <timer.h> + +#define ERR_INVALID_ARGS (-8) +#define ERR_TIMED_OUT (-13) + +#define AUXADC_RDY_BIT BIT(15) +/* 0.385us(2.89MHz) x 42T (SPL(100K=29T)+ADC_compare(12T)+sync(1T)) ~= 16us */ +#define AUXADC_AVG_TIME_US 16 +#define AUXADC_POLL_TIME_US 100 +#define AUXADC_TIMEOUT_US 32000 +#define VOLT_FULL 1840 + +#define EXT_THR_SEL_DEF_VALUE 0x80 +#define EXT_THR_PURES_SHIFT 3 + +#define SDMADC_CHAN_SPEC(src_sel) \ +{ \ + .hw_info = { \ + .ref_volt = VOLT_FULL, \ + .min_time = 128 * AUXADC_AVG_TIME_US, \ + .max_time = AUXADC_TIMEOUT_US, \ + .poll_time = AUXADC_POLL_TIME_US, \ + .ratio = { 1, 1 }, \ + .enable_reg = MT6363_AUXADC_RQST1, \ + .enable_mask = BIT(4), \ + .ready_reg = PMIC_AUXADC_ADC_OUT_CH12_L_ADDR, \ + .ready_mask = AUXADC_RDY_BIT, \ + .res = 15, \ + }, \ + .sdmadc_hw_info = { \ + .set_reg = PMIC_SDMADC_EXT_THR_SRC_SEL_ADDR, \ + .cmd = EXT_THR_SEL_DEF_VALUE | src_sel, \ + }, \ +} + +static const struct auxadc_chan_spec mt6363_sdmadc_chan_specs[] = { + [AUXADC_CHAN_VIN1] = SDMADC_CHAN_SPEC(1), + [AUXADC_CHAN_VIN2] = SDMADC_CHAN_SPEC(2), + [AUXADC_CHAN_VIN3] = SDMADC_CHAN_SPEC(3), + [AUXADC_CHAN_VIN4] = SDMADC_CHAN_SPEC(4), + [AUXADC_CHAN_VIN5] = SDMADC_CHAN_SPEC(5), + [AUXADC_CHAN_VIN6] = SDMADC_CHAN_SPEC(6), + [AUXADC_CHAN_VIN7] = SDMADC_CHAN_SPEC(7), +}; + +_Static_assert(ARRAY_SIZE(mt6363_sdmadc_chan_specs) == AUXADC_CHAN_MAX, + "Wrong array size for mt6363_sdmadc_chan_specs"); + +int mt6363_sdmadc_read(enum auxadc_channel channel, int *val, + enum sdmadc_pures pures, enum auxadc_val_type type) +{ + u8 wdata; + u32 regval; + u32 elapsed = 0; + const struct auxadc_chan_spec *chan; + + if (channel < AUXADC_CHAN_VIN1 || channel >= AUXADC_CHAN_MAX) { + printk(BIOS_ERR, "[%s] Invalid channel %d\n", __func__, channel); + return ERR_INVALID_ARGS; + } + + mt6363_init_pmif_arb(); + chan = &mt6363_sdmadc_chan_specs[channel]; + + wdata = chan->sdmadc_hw_info.cmd | (pures << EXT_THR_PURES_SHIFT); + mt6363_write8(chan->sdmadc_hw_info.set_reg, wdata); + + wdata = chan->hw_info.enable_mask; + mt6363_write8(chan->hw_info.enable_reg, wdata); + + udelay(chan->hw_info.min_time); + elapsed += chan->hw_info.min_time; + + while (1) { + regval = mt6363_read16(chan->hw_info.ready_reg); + if (regval & chan->hw_info.ready_mask) + break; + if (elapsed > chan->hw_info.max_time) { + printk(BIOS_ERR, "[%s] Auxadc read time out", __func__); + return ERR_TIMED_OUT; + } + udelay(chan->hw_info.poll_time); + elapsed += chan->hw_info.poll_time; + } + + regval &= (BIT(chan->hw_info.res) - 1); + switch (type) { + case AUXADC_VAL_RAW: + *val = regval; + break; + case AUXADC_VAL_PROCESSED: + *val = ((regval * chan->hw_info.ratio[0] * chan->hw_info.ref_volt) / + chan->hw_info.ratio[1]) >> chan->hw_info.res; + break; + } + return 0; +} diff --git a/src/soc/mediatek/mt8196/Makefile.mk b/src/soc/mediatek/mt8196/Makefile.mk index 7a950d2..2a01ee5 100644 --- a/src/soc/mediatek/mt8196/Makefile.mk +++ b/src/soc/mediatek/mt8196/Makefile.mk @@ -45,6 +45,7 @@ ramstage-y += ../common/mmu_operations.c ../common/mmu_cmops.c ramstage-$(CONFIG_PCI) += ../common/pcie.c pcie.c ramstage-y += ../common/mt6363.c mt6363.c +ramstage-y += ../common/mt6363_sdmadc.c ramstage-y += soc.c ramstage-y += ../common/pmif_clk.c pmif_clk.c ramstage-y += ../common/pmif.c pmif_init.c