From 4672d506d0abfba7890b2719b7b53f3694b88d06 Mon Sep 17 00:00:00 2001 From: Rabeeh Khoury Date: Mon, 3 Feb 2020 14:26:55 +0200 Subject: [PATCH 13/17] lx2160a-cex7 : move from lsdk-19.06 to lsdk-19.09 Following is a list of changes - 1. I2C moved to DM model 2. removed emc2301 support 3. synchronized vid.c with NXP's driver. But it is still not functional in u-boot 4. Added eMMC to distroboot target list Upstream-Status: Inappropriate [Solid-Run BSP] Signed-off-by: Rabeeh Khoury --- arch/arm/dts/fsl-lx2160a-cex7.dts | 14 + board/solidrun/common/Makefile | 1 - board/solidrun/common/emc2301.c | 31 -- board/solidrun/common/vid.c | 638 +++++++++++++++++++++++++++++- board/solidrun/lx2160a/lx2160a.c | 8 + configs/lx2160acex7_tfa_defconfig | 8 +- 6 files changed, 665 insertions(+), 35 deletions(-) delete mode 100644 board/solidrun/common/emc2301.c diff --git a/arch/arm/dts/fsl-lx2160a-cex7.dts b/arch/arm/dts/fsl-lx2160a-cex7.dts index 4fbcaafb0e..4ca67df25a 100644 --- a/arch/arm/dts/fsl-lx2160a-cex7.dts +++ b/arch/arm/dts/fsl-lx2160a-cex7.dts @@ -46,6 +46,20 @@ status = "okay"; }; +&i2c0 { + status = "okay"; + u-boot,dm-pre-reloc; +}; + +&i2c4 { + status = "okay"; + + rtc@51 { + compatible = "pcf2127-rtc"; + reg = <0x51>; + }; +}; + &sata0 { status = "okay"; }; diff --git a/board/solidrun/common/Makefile b/board/solidrun/common/Makefile index 454a18e2f9..c335c658d4 100644 --- a/board/solidrun/common/Makefile +++ b/board/solidrun/common/Makefile @@ -16,7 +16,6 @@ ifdef MINIMAL obj- := __dummy__.o else obj-$(CONFIG_VID) += vid.o -obj-$(CONFIG_EMC2301) += emc2301.o ifdef CONFIG_SECURE_BOOT obj-$(CONFIG_CMD_ESBC_VALIDATE) += fsl_validate.o cmd_esbc_validate.o endif diff --git a/board/solidrun/common/emc2301.c b/board/solidrun/common/emc2301.c deleted file mode 100644 index a4780dbfcc..0000000000 --- a/board/solidrun/common/emc2301.c +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright 2019 SolidRun ltd. Based on code from NXP LX2160A RDB - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include - -#include "emc2301.h" - -DECLARE_GLOBAL_DATA_PTR; - -void set_fan_speed(u8 data) -{ - if (i2c_write(I2C_EMC2301_ADDR, I2C_EMC2301_FAN, 1, &data, 1) != 0) { - puts("Error: failed to change fan speed\n"); - } -} - -void emc2301_init(void) -{ - u8 data; - - data = I2C_EMC2301_CMD; - if (i2c_write(I2C_EMC2301_ADDR, I2C_EMC2301_CONF, 1, &data, 1) != 0) - puts("Error: failed to configure EMC2301\n"); -} diff --git a/board/solidrun/common/vid.c b/board/solidrun/common/vid.c index cc81e80c37..c7a626fd4f 100644 --- a/board/solidrun/common/vid.c +++ b/board/solidrun/common/vid.c @@ -1,8 +1,9 @@ // SPDX-License-Identifier: GPL-2.0+ /* * Copyright 2014 Freescale Semiconductor, Inc. - * Copyright 2018 NXP + * Copyright 2019 NXP */ + #include #include #include @@ -38,6 +39,52 @@ int __weak board_adjust_vdd(int vdd) return 0; } +#if defined(CONFIG_VOL_MONITOR_IR36021_SET) || \ + defined(CONFIG_VOL_MONITOR_IR36021_READ) +/* + * Get the i2c address configuration for the IR regulator chip + * + * There are some variance in the RDB HW regarding the I2C address configuration + * for the IR regulator chip, which is likely a problem of external resistor + * accuracy. So we just check each address in a hopefully non-intrusive mode + * and use the first one that seems to work + * + * The IR chip can show up under the following addresses: + * 0x08 (Verified on T1040RDB-PA,T4240RDB-PB,X-T4240RDB-16GPA) + * 0x09 (Verified on T1040RDB-PA) + * 0x38 (Verified on T2080QDS, T2081QDS, T4240RDB) + */ +static int find_ir_chip_on_i2c(void) +{ + int i2caddress; + int ret; + u8 byte; + int i; + const int ir_i2c_addr[] = {0x38, 0x08, 0x09}; +#ifdef CONFIG_DM_I2C + struct udevice *dev; +#endif + + /* Check all the address */ + for (i = 0; i < (sizeof(ir_i2c_addr)/sizeof(ir_i2c_addr[0])); i++) { + i2caddress = ir_i2c_addr[i]; +#ifndef CONFIG_DM_I2C + ret = i2c_read(i2caddress, + IR36021_MFR_ID_OFFSET, 1, (void *)&byte, + sizeof(byte)); +#else + ret = i2c_get_chip_for_busnum(0, i2caddress, 1, &dev); + if (!ret) + ret = dm_i2c_read(dev, IR36021_MFR_ID_OFFSET, + (void *)&byte, sizeof(byte)); +#endif + if ((ret >= 0) && (byte == IR36021_MFR_ID)) + return i2caddress; + } + return -1; +} +#endif + /* Maximum loop count waiting for new voltage to take effect */ #define MAX_LOOP_WAIT_NEW_VOL 100 /* Maximum loop count waiting for the voltage to be stable */ @@ -60,23 +107,135 @@ int __weak board_adjust_vdd(int vdd) #define ADC_MIN_ACCURACY 4 #endif +#ifdef CONFIG_VOL_MONITOR_INA220 +static int read_voltage_from_INA220(int i2caddress) +{ + int i, ret, voltage_read = 0; + u16 vol_mon; + u8 buf[2]; +#ifdef CONFIG_DM_I2C + struct udevice *dev; +#endif + + for (i = 0; i < NUM_READINGS; i++) { +#ifndef CONFIG_DM_I2C + ret = i2c_read(I2C_VOL_MONITOR_ADDR, + I2C_VOL_MONITOR_BUS_V_OFFSET, 1, + (void *)&buf, 2); +#else + ret = i2c_get_chip_for_busnum(0, I2C_VOL_MONITOR_ADDR, 1, &dev); + if (!ret) + ret = dm_i2c_read(dev, I2C_VOL_MONITOR_BUS_V_OFFSET, + (void *)&buf, 2); +#endif + if (ret) { + printf("VID: failed to read core voltage\n"); + return ret; + } + vol_mon = (buf[0] << 8) | buf[1]; + if (vol_mon & I2C_VOL_MONITOR_BUS_V_OVF) { + printf("VID: Core voltage sensor error\n"); + return -1; + } + debug("VID: bus voltage reads 0x%04x\n", vol_mon); + /* LSB = 4mv */ + voltage_read += (vol_mon >> I2C_VOL_MONITOR_BUS_V_SHIFT) * 4; + udelay(WAIT_FOR_ADC); + } + /* calculate the average */ + voltage_read /= NUM_READINGS; + + return voltage_read; +} +#endif + +/* read voltage from IR */ +#ifdef CONFIG_VOL_MONITOR_IR36021_READ +static int read_voltage_from_IR(int i2caddress) +{ + int i, ret, voltage_read = 0; + u16 vol_mon; + u8 buf; +#ifdef CONFIG_DM_I2C + struct udevice *dev; +#endif + + for (i = 0; i < NUM_READINGS; i++) { +#ifndef CONFIG_DM_I2C + ret = i2c_read(i2caddress, + IR36021_LOOP1_VOUT_OFFSET, + 1, (void *)&buf, 1); +#else + ret = i2c_get_chip_for_busnum(0, i2caddress, 1, &dev); + if (!ret) + ret = dm_i2c_read(dev, IR36021_LOOP1_VOUT_OFFSET, + (void *)&buf, 1); +#endif + if (ret) { + printf("VID: failed to read vcpu\n"); + return ret; + } + vol_mon = buf; + if (!vol_mon) { + printf("VID: Core voltage sensor error\n"); + return -1; + } + debug("VID: bus voltage reads 0x%02x\n", vol_mon); + /* Resolution is 1/128V. We scale up here to get 1/128mV + * and divide at the end + */ + voltage_read += vol_mon * 1000; + udelay(WAIT_FOR_ADC); + } + /* Scale down to the real mV as IR resolution is 1/128V, rounding up */ + voltage_read = DIV_ROUND_UP(voltage_read, 128); + + /* calculate the average */ + voltage_read /= NUM_READINGS; + + /* Compensate for a board specific voltage drop between regulator and + * SoC before converting into an IR VID value + */ + voltage_read -= board_vdd_drop_compensation(); + + return voltage_read; +} +#endif + +#ifdef CONFIG_VOL_MONITOR_LTC3882_READ /* read the current value of the LTC Regulator Voltage */ static int read_voltage_from_LTC(int i2caddress) { int ret, vcode = 0; u8 chan = PWM_CHANNEL0; +#ifndef CONFIG_DM_I2C /* select the PAGE 0 using PMBus commands PAGE for VDD*/ ret = i2c_write(I2C_VOL_MONITOR_ADDR, PMBUS_CMD_PAGE, 1, &chan, 1); +#else + struct udevice *dev; + + ret = i2c_get_chip_for_busnum(0, I2C_VOL_MONITOR_ADDR, 1, &dev); + if (!ret) + ret = dm_i2c_write(dev, PMBUS_CMD_PAGE, &chan, 1); +#endif if (ret) { printf("VID: failed to select VDD Page 0\n"); return ret; } +#ifndef CONFIG_DM_I2C /*read the output voltage using PMBus command READ_VOUT*/ ret = i2c_read(I2C_VOL_MONITOR_ADDR, PMBUS_CMD_READ_VOUT, 1, (void *)&vcode, 2); +#else + ret = dm_i2c_read(dev, PMBUS_CMD_READ_VOUT, (void *)&vcode, 2); + if (ret) { + printf("VID: failed to read the volatge\n"); + return ret; + } +#endif if (ret) { printf("VID: failed to read the volatge\n"); return ret; @@ -87,14 +246,131 @@ static int read_voltage_from_LTC(int i2caddress) return vcode; } +#endif static int read_voltage(int i2caddress) { int voltage_read; +#ifdef CONFIG_VOL_MONITOR_INA220 + voltage_read = read_voltage_from_INA220(i2caddress); +#elif defined CONFIG_VOL_MONITOR_IR36021_READ + voltage_read = read_voltage_from_IR(i2caddress); +#elif defined CONFIG_VOL_MONITOR_LTC3882_READ voltage_read = read_voltage_from_LTC(i2caddress); +#else + return -1; +#endif return voltage_read; } +#ifdef CONFIG_VOL_MONITOR_IR36021_SET +/* + * We need to calculate how long before the voltage stops to drop + * or increase. It returns with the loop count. Each loop takes + * several readings (WAIT_FOR_ADC) + */ +static int wait_for_new_voltage(int vdd, int i2caddress) +{ + int timeout, vdd_current; + + vdd_current = read_voltage(i2caddress); + /* wait until voltage starts to reach the target. Voltage slew + * rates by typical regulators will always lead to stable readings + * within each fairly long ADC interval in comparison to the + * intended voltage delta change until the target voltage is + * reached. The fairly small voltage delta change to any target + * VID voltage also means that this function will always complete + * within few iterations. If the timeout was ever reached, it would + * point to a serious failure in the regulator system. + */ + for (timeout = 0; + abs(vdd - vdd_current) > (IR_VDD_STEP_UP + IR_VDD_STEP_DOWN) && + timeout < MAX_LOOP_WAIT_NEW_VOL; timeout++) { + vdd_current = read_voltage(i2caddress); + } + if (timeout >= MAX_LOOP_WAIT_NEW_VOL) { + printf("VID: Voltage adjustment timeout\n"); + return -1; + } + return timeout; +} + +/* + * this function keeps reading the voltage until it is stable or until the + * timeout expires + */ +static int wait_for_voltage_stable(int i2caddress) +{ + int timeout, vdd_current, vdd; + + vdd = read_voltage(i2caddress); + udelay(NUM_READINGS * WAIT_FOR_ADC); + + /* wait until voltage is stable */ + vdd_current = read_voltage(i2caddress); + /* The maximum timeout is + * MAX_LOOP_WAIT_VOL_STABLE * NUM_READINGS * WAIT_FOR_ADC + */ + for (timeout = MAX_LOOP_WAIT_VOL_STABLE; + abs(vdd - vdd_current) > ADC_MIN_ACCURACY && + timeout > 0; timeout--) { + vdd = vdd_current; + udelay(NUM_READINGS * WAIT_FOR_ADC); + vdd_current = read_voltage(i2caddress); + } + if (timeout == 0) + return -1; + return vdd_current; +} + +/* Set the voltage to the IR chip */ +static int set_voltage_to_IR(int i2caddress, int vdd) +{ + int wait, vdd_last; + int ret; + u8 vid; + + /* Compensate for a board specific voltage drop between regulator and + * SoC before converting into an IR VID value + */ + vdd += board_vdd_drop_compensation(); +#ifdef CONFIG_FSL_LSCH2 + vid = DIV_ROUND_UP(vdd - 265, 5); +#else + vid = DIV_ROUND_UP(vdd - 245, 5); +#endif + +#ifndef CONFIG_DM_I2C + ret = i2c_write(i2caddress, IR36021_LOOP1_MANUAL_ID_OFFSET, + 1, (void *)&vid, sizeof(vid)); +#else + struct udevice *dev; + + ret = i2c_get_chip_for_busnum(0, i2caddress, 1, &dev); + if (!ret) + ret = dm_i2c_write(dev, IR36021_LOOP1_MANUAL_ID_OFFSET, + (void *)&vid, sizeof(vid)); + +#endif + if (ret) { + printf("VID: failed to write VID\n"); + return -1; + } + wait = wait_for_new_voltage(vdd, i2caddress); + if (wait < 0) + return -1; + debug("VID: Waited %d us\n", wait * NUM_READINGS * WAIT_FOR_ADC); + + vdd_last = wait_for_voltage_stable(i2caddress); + if (vdd_last < 0) + return -1; + debug("VID: Current voltage is %d mV\n", vdd_last); + return vdd_last; +} + +#endif + +#ifdef CONFIG_VOL_MONITOR_LTC3882_SET /* this function sets the VDD and returns the value set */ static int set_voltage_to_LTC(int i2caddress, int vdd) { @@ -111,8 +387,17 @@ static int set_voltage_to_LTC(int i2caddress, int vdd) vdd & 0xFF, (vdd & 0xFF00) >> 8}; /* Write the desired voltage code to the regulator */ +#ifndef CONFIG_DM_I2C ret = i2c_write(I2C_VOL_MONITOR_ADDR, PMBUS_CMD_PAGE_PLUS_WRITE, 1, (void *)&buff, 5); +#else + struct udevice *dev; + + ret = i2c_get_chip_for_busnum(0, I2C_VOL_MONITOR_ADDR, 1, &dev); + if (!ret) + ret = dm_i2c_write(dev, PMBUS_CMD_PAGE_PLUS_WRITE, + (void *)&buff, 5); +#endif if (ret) { printf("VID: I2C failed to write to the volatge regulator\n"); return -1; @@ -131,25 +416,39 @@ static int set_voltage_to_LTC(int i2caddress, int vdd) return vdd_last; } +#endif static int set_voltage(int i2caddress, int vdd) { int vdd_last = -1; +#ifdef CONFIG_VOL_MONITOR_IR36021_SET + vdd_last = set_voltage_to_IR(i2caddress, vdd); +#elif defined CONFIG_VOL_MONITOR_LTC3882_SET vdd_last = set_voltage_to_LTC(i2caddress, vdd); +#else + #error Specific voltage monitor must be defined +#endif return vdd_last; } +#ifdef CONFIG_FSL_LSCH3 int adjust_vdd(ulong vdd_override) { int re_enable = disable_interrupts(); struct ccsr_gur *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); u32 fusesr; +#if defined(CONFIG_VOL_MONITOR_IR36021_SET) || \ + defined(CONFIG_VOL_MONITOR_IR36021_READ) + u8 vid, buf; +#else u8 vid; +#endif int vdd_target, vdd_current, vdd_last; int ret, i2caddress; unsigned long vdd_string_override; char *vdd_string; +#ifdef CONFIG_ARCH_LX2160A static const u16 vdd[32] = { 8250, 7875, @@ -184,16 +483,129 @@ int adjust_vdd(ulong vdd_override) 0, /* reserved */ 0, /* reserved */ }; +#else +#ifdef CONFIG_ARCH_LS1088A + static const uint16_t vdd[32] = { + 10250, + 9875, + 9750, + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 9000, + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 10000, /* 1.0000V */ + 10125, + 10250, + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + }; + +#else + static const uint16_t vdd[32] = { + 10500, + 0, /* reserved */ + 9750, + 0, /* reserved */ + 9500, + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 9000, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 10000, /* 1.0000V */ + 0, /* reserved */ + 10250, + 0, /* reserved */ + 10500, + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + }; +#endif +#endif struct vdd_drive { u8 vid; unsigned voltage; }; + ret = i2c_multiplexer_select_vid_channel(I2C_MUX_CH_VOL_MONITOR); if (ret) { debug("VID: I2C failed to switch channel\n"); ret = -1; goto exit; } +#if defined(CONFIG_VOL_MONITOR_IR36021_SET) || \ + defined(CONFIG_VOL_MONITOR_IR36021_READ) + ret = find_ir_chip_on_i2c(); + if (ret < 0) { + printf("VID: Could not find voltage regulator on I2C.\n"); + ret = -1; + goto exit; + } else { + i2caddress = ret; + debug("VID: IR Chip found on I2C address 0x%02x\n", i2caddress); + } + + /* check IR chip work on Intel mode*/ +#ifndef CONFIG_DM_I2C + ret = i2c_read(i2caddress, + IR36021_INTEL_MODE_OOFSET, + 1, (void *)&buf, 1); +#else + struct udevice *dev; + + ret = i2c_get_chip_for_busnum(0, i2caddress, 1, &dev); + if (!ret) + ret = dm_i2c_read(dev, IR36021_INTEL_MODE_OOFSET, + (void *)&buf, 1); +#endif + if (ret) { + printf("VID: failed to read IR chip mode.\n"); + ret = -1; + goto exit; + } + + if ((buf & IR36021_MODE_MASK) != IR36021_INTEL_MODE) { + printf("VID: IR Chip is not used in Intel mode.\n"); + ret = -1; + goto exit; + } +#endif + /* get the voltage ID from fuse status register */ fusesr = in_le32(&gur->dcfg_fusesr); vid = (fusesr >> FSL_CHASSIS3_DCFG_FUSESR_ALTVID_SHIFT) & @@ -203,7 +615,6 @@ int adjust_vdd(ulong vdd_override) FSL_CHASSIS3_DCFG_FUSESR_VID_MASK; } vdd_target = vdd[vid]; - printf ("vid FUSE index %d (vdd_target = %d)\n",vid,vdd_target); /* check override variable for overriding VDD */ vdd_string = env_get(CONFIG_VID_FLS_ENV); @@ -246,8 +657,28 @@ int adjust_vdd(ulong vdd_override) vdd_current = vdd_last; debug("VID: Core voltage is currently at %d mV\n", vdd_last); +#ifdef CONFIG_VOL_MONITOR_LTC3882_SET /* Set the target voltage */ vdd_last = vdd_current = set_voltage(i2caddress, vdd_target); +#else + /* + * Adjust voltage to at or one step above target. + * As measurements are less precise than setting the values + * we may run through dummy steps that cancel each other + * when stepping up and then down. + */ + while (vdd_last > 0 && + vdd_last < vdd_target) { + vdd_current += IR_VDD_STEP_UP; + vdd_last = set_voltage(i2caddress, vdd_current); + } + while (vdd_last > 0 && + vdd_last > vdd_target + (IR_VDD_STEP_DOWN - 1)) { + vdd_current -= IR_VDD_STEP_DOWN; + vdd_last = set_voltage(i2caddress, vdd_current); + } + +#endif if (board_adjust_vdd(vdd_target) < 0) { ret = -1; goto exit; @@ -264,6 +695,197 @@ exit: i2c_multiplexer_select_vid_channel(I2C_MUX_CH_DEFAULT); return ret; } +#else /* !CONFIG_FSL_LSCH3 */ +int adjust_vdd(ulong vdd_override) +{ + int re_enable = disable_interrupts(); +#if defined(CONFIG_FSL_LSCH2) + struct ccsr_gur *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); +#else + ccsr_gur_t __iomem *gur = + (void __iomem *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); +#endif + u32 fusesr; + u8 vid, buf; + int vdd_target, vdd_current, vdd_last; + int ret, i2caddress; + unsigned long vdd_string_override; + char *vdd_string; + static const uint16_t vdd[32] = { + 0, /* unused */ + 9875, /* 0.9875V */ + 9750, + 9625, + 9500, + 9375, + 9250, + 9125, + 9000, + 8875, + 8750, + 8625, + 8500, + 8375, + 8250, + 8125, + 10000, /* 1.0000V */ + 10125, + 10250, + 10375, + 10500, + 10625, + 10750, + 10875, + 11000, + 0, /* reserved */ + }; + struct vdd_drive { + u8 vid; + unsigned voltage; + }; + + ret = i2c_multiplexer_select_vid_channel(I2C_MUX_CH_VOL_MONITOR); + if (ret) { + debug("VID: I2C failed to switch channel\n"); + ret = -1; + goto exit; + } +#if defined(CONFIG_VOL_MONITOR_IR36021_SET) || \ + defined(CONFIG_VOL_MONITOR_IR36021_READ) + ret = find_ir_chip_on_i2c(); + if (ret < 0) { + printf("VID: Could not find voltage regulator on I2C.\n"); + ret = -1; + goto exit; + } else { + i2caddress = ret; + debug("VID: IR Chip found on I2C address 0x%02x\n", i2caddress); + } + + /* check IR chip work on Intel mode*/ +#ifndef CONFIG_DM_I2C + ret = i2c_read(i2caddress, + IR36021_INTEL_MODE_OOFSET, + 1, (void *)&buf, 1); +#else + struct udevice *dev; + + ret = i2c_get_chip_for_busnum(0, i2caddress, 1, &dev); + if (!ret) + ret = dm_i2c_read(dev, IR36021_INTEL_MODE_OOFSET, + (void *)&buf, 1); +#endif + if (ret) { + printf("VID: failed to read IR chip mode.\n"); + ret = -1; + goto exit; + } + if ((buf & IR36021_MODE_MASK) != IR36021_INTEL_MODE) { + printf("VID: IR Chip is not used in Intel mode.\n"); + ret = -1; + goto exit; + } +#endif + + /* get the voltage ID from fuse status register */ + fusesr = in_be32(&gur->dcfg_fusesr); + /* + * VID is used according to the table below + * --------------------------------------- + * | DA_V | + * |-------------------------------------| + * | 5b00000 | 5b00001-5b11110 | 5b11111 | + * ---------------+---------+-----------------+---------| + * | D | 5b00000 | NO VID | VID = DA_V | NO VID | + * | A |----------+---------+-----------------+---------| + * | _ | 5b00001 |VID = | VID = |VID = | + * | V | ~ | DA_V_ALT| DA_V_ALT | DA_A_VLT| + * | _ | 5b11110 | | | | + * | A |----------+---------+-----------------+---------| + * | L | 5b11111 | No VID | VID = DA_V | NO VID | + * | T | | | | | + * ------------------------------------------------------ + */ +#ifdef CONFIG_FSL_LSCH2 + vid = (fusesr >> FSL_CHASSIS2_DCFG_FUSESR_ALTVID_SHIFT) & + FSL_CHASSIS2_DCFG_FUSESR_ALTVID_MASK; + if ((vid == 0) || (vid == FSL_CHASSIS2_DCFG_FUSESR_ALTVID_MASK)) { + vid = (fusesr >> FSL_CHASSIS2_DCFG_FUSESR_VID_SHIFT) & + FSL_CHASSIS2_DCFG_FUSESR_VID_MASK; + } +#else + vid = (fusesr >> FSL_CORENET_DCFG_FUSESR_ALTVID_SHIFT) & + FSL_CORENET_DCFG_FUSESR_ALTVID_MASK; + if ((vid == 0) || (vid == FSL_CORENET_DCFG_FUSESR_ALTVID_MASK)) { + vid = (fusesr >> FSL_CORENET_DCFG_FUSESR_VID_SHIFT) & + FSL_CORENET_DCFG_FUSESR_VID_MASK; + } +#endif + vdd_target = vdd[vid]; + + /* check override variable for overriding VDD */ + vdd_string = env_get(CONFIG_VID_FLS_ENV); + if (vdd_override == 0 && vdd_string && + !strict_strtoul(vdd_string, 10, &vdd_string_override)) + vdd_override = vdd_string_override; + if (vdd_override >= VDD_MV_MIN && vdd_override <= VDD_MV_MAX) { + vdd_target = vdd_override * 10; /* convert to 1/10 mV */ + debug("VDD override is %lu\n", vdd_override); + } else if (vdd_override != 0) { + printf("Invalid value.\n"); + } + if (vdd_target == 0) { + debug("VID: VID not used\n"); + ret = 0; + goto exit; + } else { + /* divide and round up by 10 to get a value in mV */ + vdd_target = DIV_ROUND_UP(vdd_target, 10); + debug("VID: vid = %d mV\n", vdd_target); + } + + /* + * Read voltage monitor to check real voltage. + */ + vdd_last = read_voltage(i2caddress); + if (vdd_last < 0) { + printf("VID: Couldn't read sensor abort VID adjustment\n"); + ret = -1; + goto exit; + } + vdd_current = vdd_last; + debug("VID: Core voltage is currently at %d mV\n", vdd_last); + /* + * Adjust voltage to at or one step above target. + * As measurements are less precise than setting the values + * we may run through dummy steps that cancel each other + * when stepping up and then down. + */ + while (vdd_last > 0 && + vdd_last < vdd_target) { + vdd_current += IR_VDD_STEP_UP; + vdd_last = set_voltage(i2caddress, vdd_current); + } + while (vdd_last > 0 && + vdd_last > vdd_target + (IR_VDD_STEP_DOWN - 1)) { + vdd_current -= IR_VDD_STEP_DOWN; + vdd_last = set_voltage(i2caddress, vdd_current); + } + + if (vdd_last > 0) + printf("VID: Core voltage after adjustment is at %d mV\n", + vdd_last); + else + ret = -1; +exit: + if (re_enable) + enable_interrupts(); + + i2c_multiplexer_select_vid_channel(I2C_MUX_CH_DEFAULT); + + return ret; +} +#endif static int print_vdd(void) { @@ -274,6 +896,18 @@ static int print_vdd(void) debug("VID : I2c failed to switch channel\n"); return -1; } +#if defined(CONFIG_VOL_MONITOR_IR36021_SET) || \ + defined(CONFIG_VOL_MONITOR_IR36021_READ) + ret = find_ir_chip_on_i2c(); + if (ret < 0) { + printf("VID: Could not find voltage regulator on I2C.\n"); + goto exit; + } else { + i2caddress = ret; + debug("VID: IR Chip found on I2C address 0x%02x\n", i2caddress); + } +#endif + /* * Read voltage monitor to check real voltage. */ diff --git a/board/solidrun/lx2160a/lx2160a.c b/board/solidrun/lx2160a/lx2160a.c index b0d9f1012e..3713e91351 100644 --- a/board/solidrun/lx2160a/lx2160a.c +++ b/board/solidrun/lx2160a/lx2160a.c @@ -62,7 +62,15 @@ int select_i2c_ch_pca9547(u8 ch) { int ret; +#ifndef CONFIG_DM_I2C ret = i2c_write(I2C_MUX_PCA_ADDR_PRI, 0, 1, &ch, 1); +#else + struct udevice *dev; + + ret = i2c_get_chip_for_busnum(0, I2C_MUX_PCA_ADDR_PRI, 1, &dev); + if (!ret) + ret = dm_i2c_write(dev, 0, &ch, 1); +#endif if (ret) { puts("PCA: failed to select proper channel\n"); return ret; diff --git a/configs/lx2160acex7_tfa_defconfig b/configs/lx2160acex7_tfa_defconfig index 3891d2a7c4..89a47adb23 100644 --- a/configs/lx2160acex7_tfa_defconfig +++ b/configs/lx2160acex7_tfa_defconfig @@ -2,7 +2,6 @@ CONFIG_ARM=y CONFIG_TARGET_LX2160ACEX7=y CONFIG_SYS_TEXT_BASE=0x82000000 CONFIG_SYS_MALLOC_F_LEN=0x6000 -CONFIG_EMC2301=y CONFIG_TFABOOT=y CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT=y CONFIG_SEC_FIRMWARE_ARMV8_PSCI=y @@ -73,3 +72,10 @@ CONFIG_DM_USB=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y CONFIG_EFI_LOADER_BOUNCE_BUFFER=y +CONFIG_DM_I2C=y +CONFIG_I2C_SET_DEFAULT_BUS_NUM=y +CONFIG_I2C_DEFAULT_BUS_NUMBER=0 +CONFIG_DM_RTC=y +CONFIG_DM_GPIO=y +CONFIG_CMD_DATE=y +CONFIG_RTC_PCF2127=y -- 2.17.1