/* * tpm_tis_i2c_read() - read from TPM register * @addr: register address to read from * @buffer: provided by caller * @len: number of bytes to read * * Read len bytes from TPM register and put them into * buffer (little-endian format, i.e. first byte is put into buffer[0]). * * NOTE: TPM is big-endian for multi-byte values. Multi-byte * values have to be swapped. * * Return -EIO on error, 0 on success. */ static int tpm_tis_i2c_read(struct udevice *dev, u8 addr, u8 *buffer, size_t len) { struct tpm_chip *chip = dev_get_priv(dev); int rc; int count; uint32_t addrbuf = addr; if ((chip->chip_type == SLB9635) || (chip->chip_type == UNKNOWN)) { /* slb9635 protocol should work in both cases */ for (count = 0; count < MAX_COUNT; count++) { rc = dm_i2c_write(dev, 0, (uchar *)&addrbuf, 1); if (rc == 0) break; /* Success, break to skip sleep */ udelay(SLEEP_DURATION_US); } if (rc) return rc; /* After the TPM has successfully received the register address * it needs some time, thus we're sleeping here again, before * retrieving the data */ for (count = 0; count < MAX_COUNT; count++) { udelay(SLEEP_DURATION_US); rc = dm_i2c_read(dev, 0, buffer, len); if (rc == 0) break; /* success, break to skip sleep */ } } else { /* * Use a combined read for newer chips. * Unfortunately the smbus functions are not suitable due to * the 32 byte limit of the smbus. * Retries should usually not be needed, but are kept just to * be safe on the safe side. */ for (count = 0; count < MAX_COUNT; count++) { rc = dm_i2c_read(dev, addr, buffer, len); if (rc == 0) break; /* break here to skip sleep */ udelay(SLEEP_DURATION_US); } } /* Take care of 'guard time' */ udelay(SLEEP_DURATION_US); if (rc) return rc; return 0; }
/* * Set USB VBUS signals (via I2C IO expander/GPIO) as output and set * output value as disabled * * Set USB Current Limit signals (via I2C IO expander/GPIO) as output * and set output value as enabled */ int board_xhci_config(void) { struct udevice *dev; int ret; u8 buf[8]; if (of_machine_is_compatible("marvell,armada7040-db")) { /* Configure IO exander PCA9555: 7bit address 0x21 */ ret = i2c_get_chip_for_busnum(0, I2C_IO_EXP_ADDR, 1, &dev); if (ret) { printf("Cannot find PCA9555: %d\n", ret); return 0; } /* * Read configuration (direction) and set VBUS pin as output * (reset pin = output) */ ret = dm_i2c_read(dev, I2C_IO_CFG_REG_0, buf, 1); if (ret) { printf("Failed to read IO expander value via I2C\n"); return -EIO; } buf[0] &= ~I2C_IO_REG_VBUS; buf[0] &= ~I2C_IO_REG_CL; ret = dm_i2c_write(dev, I2C_IO_CFG_REG_0, buf, 1); if (ret) { printf("Failed to set IO expander via I2C\n"); return -EIO; } /* Read output value and configure it */ ret = dm_i2c_read(dev, I2C_IO_DATA_OUT_REG_0, buf, 1); if (ret) { printf("Failed to read IO expander value via I2C\n"); return -EIO; } buf[0] &= ~I2C_IO_REG_VBUS; buf[0] |= I2C_IO_REG_CL; ret = dm_i2c_write(dev, I2C_IO_DATA_OUT_REG_0, buf, 1); if (ret) { printf("Failed to set IO expander via I2C\n"); return -EIO; } mdelay(500); /* required delay to let output value settle */ } return 0; }
static int nand_sw_detect(void) { int rc; uchar data[2]; struct udevice *dev; rc = i2c_get_chip_for_busnum(NAND_PCF8575_I2C_BUS_NUM, NAND_PCF8575_ADDR, 0, &dev); if (rc) return -1; rc = dm_i2c_read(dev, 0, (uint8_t *)&data, sizeof(data)); if (rc) return -1; /* We are only interested in P10 and P11 on PCF8575 which is equal to * bits 8 and 9. */ data[1] = data[1] & 0x3; /* Ensure only P11 is set and P10 is cleared. This ensures only * NAND (P10) is configured and not NOR (P11) which are both low * true signals. NAND and NOR settings should not be enabled at * the same time. */ if (data[1] == 0x2) return 0; return -1; }
static int set_ethaddr_from_at24mac(void) { const int ETH_ADDR_LEN = 6; unsigned char ethaddr[ETH_ADDR_LEN]; const char *ETHADDR_NAME = "ethaddr"; struct udevice *bus, *dev; if (getenv(ETHADDR_NAME)) return 0; if (uclass_get_device_by_seq(UCLASS_I2C, AT24MAC_ON_I2C_BUS, &bus)) { printf("Cannot find I2C bus\n"); return -1; } if (dm_i2c_probe(bus, AT24MAC_ADDR, 0, &dev)) { printf("Failed to probe I2C device chip\n"); return -1; } if (dm_i2c_read(dev, AT24MAC_REG, ethaddr, ETH_ADDR_LEN)) { printf("Failed to read ethernet address from AT24MAC\n"); return -1; } if (!is_valid_ethaddr(ethaddr)) { printf("The ethernet address read from AT24MAC is not valid\n"); return -1; } return eth_setenv_enetaddr(ETHADDR_NAME, ethaddr); }
static int pcf2127_rtc_get(struct udevice *dev, struct rtc_time *tm) { int ret = 0; uchar buf[10] = { PCF2127_REG_CTRL1 }; ret = dm_i2c_write(dev, PCF2127_REG_CTRL1, buf, 1); if (ret < 0) return ret; ret = dm_i2c_read(dev, PCF2127_REG_CTRL1, buf, sizeof(buf)); if (ret < 0) return ret; if (buf[PCF2127_REG_CTRL3] & 0x04) puts("### Warning: RTC Low Voltage - date/time not reliable\n"); tm->tm_sec = bcd2bin(buf[PCF2127_REG_SC] & 0x7F); tm->tm_min = bcd2bin(buf[PCF2127_REG_MN] & 0x7F); tm->tm_hour = bcd2bin(buf[PCF2127_REG_HR] & 0x3F); tm->tm_mday = bcd2bin(buf[PCF2127_REG_DM] & 0x3F); tm->tm_mon = bcd2bin(buf[PCF2127_REG_MO] & 0x1F) - 1; tm->tm_year = bcd2bin(buf[PCF2127_REG_YR]) + 1900; if (tm->tm_year < 1970) tm->tm_year += 100; /* assume we are in 1970...2069 */ tm->tm_wday = buf[PCF2127_REG_DW] & 0x07; tm->tm_yday = 0; tm->tm_isdst = 0; debug("Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_wday, tm->tm_hour, tm->tm_min, tm->tm_sec); return ret; }
static int pca953x_read_regs(struct udevice *dev, int reg, u8 *val) { struct pca953x_info *info = dev_get_platdata(dev); int ret = 0; if (info->gpio_count <= 8) { ret = dm_i2c_read(dev, reg, val, 1); } else if (info->gpio_count <= 16) { ret = dm_i2c_read(dev, reg << 1, val, info->bank_count); } else { dev_err(dev, "Unsupported now\n"); return -EINVAL; } return ret; }
static int act8846_read(struct udevice *dev, uint reg, uint8_t *buff, int len) { if (dm_i2c_read(dev, reg, buff, len)) { debug("read error from device: %p register: %#x!\n", dev, reg); return -EIO; } return 0; }
static int lp873x_read(struct udevice *dev, uint reg, uint8_t *buff, int len) { if (dm_i2c_read(dev, reg, buff, len)) { error("read error from device: %p register: %#x!", dev, reg); return -EIO; } return 0; }
static int max8997_read(struct udevice *dev, uint reg, uint8_t *buff, int len) { int ret; ret = dm_i2c_read(dev, reg, buff, len); if (ret) pr_err("read error from device: %p register: %#x!", dev, reg); return ret; }
static int stpmu1_read(struct udevice *dev, uint reg, uint8_t *buff, int len) { int ret; ret = dm_i2c_read(dev, reg, buff, len); if (ret) dev_err(dev, "%s: failed to read register %#x : %d", __func__, reg, ret); return ret; }
static int pmic_tps65910_read(struct udevice *dev, uint reg, u8 *buffer, int len) { int ret; ret = dm_i2c_read(dev, reg, buffer, len); if (ret) pr_err("%s read error on register %02x\n", dev->name, reg); return ret; }
int dm_i2c_reg_read(struct udevice *dev, uint offset) { uint8_t val; int ret; ret = dm_i2c_read(dev, offset, &val, 1); if (ret < 0) return ret; return val; }
int i2c_read(uint8_t chip_addr, unsigned int addr, int alen, uint8_t *buffer, int len) { struct udevice *dev; int ret; ret = i2c_compat_get_device(chip_addr, alen, &dev); if (ret) return ret; return dm_i2c_read(dev, addr, buffer, len); }
/* * st33zp24_i2c_read8_reg * Recv byte from the TIS register according to the ST33ZP24 I2C protocol. * @param: tpm_register, the tpm tis register where the data should be read * @param: tpm_data, the TPM response * @param: tpm_size, tpm TPM response size to read. * @return: Number of byte read successfully else an error code. */ static int st33zp24_i2c_read8_reg(struct udevice *dev, u8 tpm_register, u8 *tpm_data, size_t tpm_size) { int status; u8 data; data = TPM_DUMMY_BYTE; status = st33zp24_i2c_write8_reg(dev, tpm_register, &data, 1); if (status < 0) return status; return dm_i2c_read(dev, 0, tpm_data, tpm_size); }
static int pca953x_read_single(struct udevice *dev, int reg, u8 *val, int offset) { struct pca953x_info *info = dev_get_platdata(dev); int bank_shift = fls((info->gpio_count - 1) / BANK_SZ); int off = offset / BANK_SZ; int ret; u8 byte; ret = dm_i2c_read(dev, (reg << bank_shift) + off, &byte, 1); if (ret) { dev_err(dev, "%s error\n", __func__); return ret; } *val = byte; return 0; }
static bool omnia_read_eeprom(struct omnia_eeprom *oep) { struct udevice *bus, *dev; int ret, crc, retry = 3; if (uclass_get_device_by_name(UCLASS_I2C, OMNIA_I2C_EEPROM_DM_NAME, &bus)) { puts("Cannot find EEPROM bus\n"); return false; } ret = i2c_get_chip(bus, OMNIA_I2C_EEPROM, OMNIA_I2C_EEPROM_ADDRLEN, &dev); if (ret) { puts("Cannot get EEPROM chip\n"); return false; } for (; retry > 0; --retry) { ret = dm_i2c_read(dev, OMNIA_I2C_EEPROM_CONFIG_ADDR, (uchar *) oep, sizeof(struct omnia_eeprom)); if (ret) continue; if (oep->magic != OMNIA_I2C_EEPROM_MAGIC) { puts("I2C EEPROM missing magic number!\n"); continue; } crc = crc32(0, (unsigned char *) oep, sizeof(struct omnia_eeprom) - 4); if (crc == oep->crc) { break; } else { printf("CRC of EEPROM memory config failed! " "calc=0x%04x saved=0x%04x\n", crc, oep->crc); } } if (!retry) { puts("I2C EEPROM read failed!\n"); return false; } return true; }
static bool omnia_detect_sata(void) { struct udevice *bus, *dev; int ret, retry = 3; u16 mode; puts("SERDES0 card detect: "); if (uclass_get_device_by_name(UCLASS_I2C, OMNIA_I2C_MCU_DM_NAME, &bus)) { puts("Cannot find MCU bus!\n"); return false; } ret = i2c_get_chip(bus, OMNIA_I2C_MCU, 1, &dev); if (ret) { puts("Cannot get MCU chip!\n"); return false; } for (; retry > 0; --retry) { ret = dm_i2c_read(dev, OMNIA_I2C_MCU_ADDR_STATUS, (uchar *) &mode, 2); if (!ret) break; } if (!retry) { puts("I2C read failed! Default PEX\n"); return false; } if (!(mode & OMNIA_I2C_MCU_CARDDET)) { puts("NONE\n"); return false; } if (mode & OMNIA_I2C_MCU_SATA) { puts("SATA\n"); return true; } else { puts("PEX\n"); return false; } }
int board_xhci_enable(void) { struct udevice *dev; int ret; u8 buf[8]; if (of_machine_is_compatible("marvell,armada7040-db")) { /* * This function enables all USB ports simultaniously, * it only needs to get called once */ if (usb_enabled) return 0; /* Configure IO exander PCA9555: 7bit address 0x21 */ ret = i2c_get_chip_for_busnum(0, I2C_IO_EXP_ADDR, 1, &dev); if (ret) { printf("Cannot find PCA9555: %d\n", ret); return 0; } /* Read VBUS output value */ ret = dm_i2c_read(dev, I2C_IO_DATA_OUT_REG_0, buf, 1); if (ret) { printf("Failed to read IO expander value via I2C\n"); return -EIO; } /* Enable VBUS power: Set output value of VBUS pin as enabled */ buf[0] |= I2C_IO_REG_VBUS; ret = dm_i2c_write(dev, I2C_IO_DATA_OUT_REG_0, buf, 1); if (ret) { printf("Failed to set IO expander via I2C\n"); return -EIO; } mdelay(500); /* required delay to let output value settle */ usb_enabled = 1; } return 0; }
int arch_misc_init(void) { /* Disable PMIC sleep mode on low supply voltage */ struct udevice *dev; u8 addr, data[1]; int err; err = i2c_get_chip_for_busnum(0, PMU_I2C_ADDRESS, 1, &dev); if (err) { debug("%s: Cannot find PMIC I2C chip\n", __func__); return err; } addr = PMU_SUPPLYENE; err = dm_i2c_read(dev, addr, data, 1); if (err) { debug("failed to get PMU_SUPPLYENE\n"); return err; } data[0] &= ~PMU_SUPPLYENE_SYSINEN; data[0] |= PMU_SUPPLYENE_EXITSLREQ; err = dm_i2c_write(dev, addr, data, 1); if (err) { debug("failed to set PMU_SUPPLYENE\n"); return err; } /* make sure SODIMM pin 87 nRESET_OUT is released properly */ pinmux_set_func(PMUX_PINGRP_ATA, PMUX_FUNC_GMI); if (readl(NV_PA_BASE_SRAM + NVBOOTINFOTABLE_BOOTTYPE) == NVBOOTTYPE_RECOVERY) printf("USB recovery mode\n"); return 0; }
void reset_cpu(ulong addr) { struct udevice *dev; const u8 pmic_bus = 6; const u8 pmic_addr = 0x5a; u8 data; int ret; ret = i2c_get_chip_for_busnum(pmic_bus, pmic_addr, 1, &dev); if (ret) hang(); ret = dm_i2c_read(dev, 0x13, &data, 1); if (ret) hang(); data |= BIT(1); ret = dm_i2c_write(dev, 0x13, &data, 1); if (ret) hang(); }
int board_late_init(void) { struct udevice *dev; u8 buf[8]; int ret; /* Configure SMSC USB2513 USB Hub: 7bit address 0x2c */ ret = i2c_get_chip_for_busnum(0, 0x2c, 1, &dev); if (ret) { printf("Cannot find USB2513: %d\n", ret); return 0; } /* * The first access to the USB Hub fails sometimes, so lets read * a dummy byte to be sure here */ dm_i2c_read(dev, 0x00, buf, 1); /* * The SMSC hub is not visible on the I2C bus after the first * configuration at power-up. The following code deliberately * does not report upon failure of these I2C write calls. */ buf[0] = 0x93; dm_i2c_write(dev, 0x06, buf, 1); buf[0] = 0xaa; dm_i2c_write(dev, 0xf8, buf, 1); buf[0] = 0x0f; dm_i2c_write(dev, 0xfa, buf, 1); buf[0] = 0x01; dm_i2c_write(dev, 0xff, buf, 1); return 0; }
static int cros_ec_i2c_command(struct udevice *udev, uint8_t cmd, int cmd_version, const uint8_t *dout, int dout_len, uint8_t **dinp, int din_len) { struct cros_ec_dev *dev = dev_get_uclass_priv(udev); /* version8, cmd8, arglen8, out8[dout_len], csum8 */ int out_bytes = dout_len + 4; /* response8, arglen8, in8[din_len], checksum8 */ int in_bytes = din_len + 3; uint8_t *ptr; /* Receive input data, so that args will be dword aligned */ uint8_t *in_ptr; int len, csum, ret; /* * Sanity-check I/O sizes given transaction overhead in internal * buffers. */ if (out_bytes > sizeof(dev->dout)) { debug("%s: Cannot send %d bytes\n", __func__, dout_len); return -1; } if (in_bytes > sizeof(dev->din)) { debug("%s: Cannot receive %d bytes\n", __func__, din_len); return -1; } assert(dout_len >= 0); assert(dinp); /* * Copy command and data into output buffer so we can do a single I2C * burst transaction. */ ptr = dev->dout; /* * in_ptr starts of pointing to a dword-aligned input data buffer. * We decrement it back by the number of header bytes we expect to * receive, so that the first parameter of the resulting input data * will be dword aligned. */ in_ptr = dev->din + sizeof(int64_t); if (dev->protocol_version != 2) { /* Something we don't support */ debug("%s: Protocol version %d unsupported\n", __func__, dev->protocol_version); return -1; } *ptr++ = EC_CMD_VERSION0 + cmd_version; *ptr++ = cmd; *ptr++ = dout_len; in_ptr -= 2; /* Expect status, length bytes */ memcpy(ptr, dout, dout_len); ptr += dout_len; *ptr++ = (uint8_t) cros_ec_calc_checksum(dev->dout, dout_len + 3); /* Send output data */ cros_ec_dump_data("out", -1, dev->dout, out_bytes); ret = dm_i2c_write(udev, 0, dev->dout, out_bytes); if (ret) { debug("%s: Cannot complete I2C write to %s\n", __func__, udev->name); ret = -1; } if (!ret) { ret = dm_i2c_read(udev, 0, in_ptr, in_bytes); if (ret) { debug("%s: Cannot complete I2C read from %s\n", __func__, udev->name); ret = -1; } } if (*in_ptr != EC_RES_SUCCESS) { debug("%s: Received bad result code %d\n", __func__, *in_ptr); return -(int)*in_ptr; } len = in_ptr[1]; if (len + 3 > sizeof(dev->din)) { debug("%s: Received length %#02x too large\n", __func__, len); return -1; } csum = cros_ec_calc_checksum(in_ptr, 2 + len); if (csum != in_ptr[2 + len]) { debug("%s: Invalid checksum rx %#02x, calced %#02x\n", __func__, in_ptr[2 + din_len], csum); return -1; } din_len = min(din_len, len); cros_ec_dump_data("in", -1, in_ptr, din_len + 3); /* Return pointer to dword-aligned input data, if any */ *dinp = dev->din + sizeof(int64_t); return din_len; }
static int i2c_eeprom_std_read(struct udevice *dev, int offset, uint8_t *buf, int size) { return dm_i2c_read(dev, offset, buf, size); }