diff --git a/src/soc/mediatek/mt8195/Makefile.inc b/src/soc/mediatek/mt8195/Makefile.inc index 181e99c91d..e584620868 100644 --- a/src/soc/mediatek/mt8195/Makefile.inc +++ b/src/soc/mediatek/mt8195/Makefile.inc @@ -45,6 +45,7 @@ romstage-y += ../common/pmif_spi.c pmif_spi.c romstage-y += ../common/pmif_spmi.c pmif_spmi.c romstage-y += ../common/mt6315.c mt6315.c romstage-y += ../common/mt6359p.c mt6359p.c +romstage-y += mt6691.c romstage-y += ../common/rtc.c ../common/rtc_osc_init.c ../common/rtc_mt6359p.c ramstage-y += ../common/auxadc.c diff --git a/src/soc/mediatek/mt8195/include/soc/mt6691.h b/src/soc/mediatek/mt8195/include/soc/mt6691.h new file mode 100644 index 0000000000..c347c41d93 --- /dev/null +++ b/src/soc/mediatek/mt8195/include/soc/mt6691.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef __SOC_MEDIATEK_MT8195_MT6691_H__ +#define __SOC_MEDIATEK_MT8195_MT6691_H__ + +#include + +void mt6691_probe(uint8_t i2c_num); +int mt6691_set_voltage(uint8_t i2c_num, unsigned int volt_uv); +int mt6691_get_voltage(uint8_t i2c_num); + +#define MT6691_CID_CODE 0x01 + +#define MT6691_VDD2_ID 0x0000 +#define MT6691_VDDQ_ID 0x0000 +#define MT6691_PGOOD_SHIFT 7 +#define MT6691_DN_SR_MASK 0x7 +#define MT6691_DN_SR_SHIFT 5 + +enum { + /* Voltage setting */ + MT6691_VSEL0 = 0x00, + MT6691_VSEL1 = 0x01, + /* Control register */ + MT6691_CONTROL = 0x02, + /* IC Type */ + MT6691_ID1 = 0x03, + /* IC mask version */ + MT6691_ID2 = 0x04, + /* Monitor register */ + MT6691_MONITOR = 0x05, + MT6691_CTRL2 = 0x06, + MT6691_CTRL3 = 0x07, + MT6691_CTRL4 = 0x08, +}; + +#endif diff --git a/src/soc/mediatek/mt8195/mt6691.c b/src/soc/mediatek/mt8195/mt6691.c new file mode 100644 index 0000000000..3f224215ef --- /dev/null +++ b/src/soc/mediatek/mt8195/mt6691.c @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include + +#define MT6691_MIN_VOLTAGE 300000 +#define MT6691_MAX_VOLTAGE 1300000 +#define MT6691_STEP_UV 5000 + +enum { + MT6691_SLAVE_ADDR = 0x51, +}; + +int mt6691_set_voltage(uint8_t i2c_num, unsigned int volt_uv) +{ + uint8_t selector; + + if (volt_uv > MT6691_MAX_VOLTAGE || volt_uv < MT6691_MIN_VOLTAGE) { + printk(BIOS_ERR, "%s: voltage out of range\n", __func__); + return -1; + } + + selector = DIV_ROUND_UP(volt_uv - MT6691_MIN_VOLTAGE, MT6691_STEP_UV); + + return i2c_write_field(i2c_num, MT6691_SLAVE_ADDR, + MT6691_VSEL0, selector, 0xFF, 0); +} + +int mt6691_get_voltage(uint8_t i2c_num) +{ + uint8_t selector = 0; + unsigned int volt; + + if (i2c_read_field(i2c_num, MT6691_SLAVE_ADDR, MT6691_VSEL0, + &selector, 0xFF, 0) < 0) { + printk(BIOS_ERR, "%s: failed to get voltage from i2c\n", __func__); + return -1; + } + + volt = (selector * MT6691_STEP_UV) + MT6691_MIN_VOLTAGE; + + if (volt > MT6691_MAX_VOLTAGE) { + printk(BIOS_ERR, "%s: voltage out of range\n", __func__); + return -1; + } + + return volt; +} + +static uint8_t get_mt6691_chip_id(uint8_t i2c_num) +{ + uint8_t id; + + if (i2c_read_field(i2c_num, MT6691_SLAVE_ADDR, MT6691_MONITOR, + &id, 0x1, MT6691_PGOOD_SHIFT) < 0) { + printk(BIOS_ERR, "%s: failed to read from i2c", __func__); + return 0; + } + + return id; +} + +void mt6691_probe(uint8_t i2c_num) +{ + /* Check device ID is MT6691 */ + if (!get_mt6691_chip_id(i2c_num)) { + printk(BIOS_ERR, "ERROR: unknown MT6691 chip_id\n"); + return; + } + /* Slew rate 12mV */ + i2c_write_field(i2c_num, MT6691_SLAVE_ADDR, MT6691_CTRL2, 0x1, + MT6691_DN_SR_MASK, MT6691_DN_SR_SHIFT); +}