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>
This commit is contained in:
parent
8910b6ba7d
commit
a1c50f233d
3 changed files with 203 additions and 0 deletions
90
src/soc/mediatek/common/include/soc/mt6363_sdmadc.h
Normal file
90
src/soc/mediatek/common/include/soc/mt6363_sdmadc.h
Normal file
|
|
@ -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__ */
|
||||
112
src/soc/mediatek/common/mt6363_sdmadc.c
Normal file
112
src/soc/mediatek/common/mt6363_sdmadc.c
Normal file
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -45,6 +45,7 @@ ramstage-y += ../common/mcu.c
|
|||
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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue