Esempio n. 1
0
/*
 * 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;
}
Esempio n. 2
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;
}
Esempio n. 3
0
File: evm.c Progetto: Noltari/u-boot
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);
}
Esempio n. 5
0
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;
}
Esempio n. 6
0
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;
}
Esempio n. 7
0
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;
}
Esempio n. 8
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;
}
Esempio n. 9
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;
}
Esempio n. 10
0
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;
}
Esempio n. 11
0
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;
}
Esempio n. 12
0
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;
}
Esempio n. 13
0
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);
}
Esempio n. 14
0
/*
* 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);
}
Esempio n. 15
0
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;
}
Esempio n. 16
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;
}
Esempio n. 17
0
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;
	}
}
Esempio n. 18
0
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;
}
Esempio n. 19
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;
}
Esempio n. 20
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();
}
Esempio n. 21
0
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;
}
Esempio n. 22
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;
}
Esempio n. 23
0
static int i2c_eeprom_std_read(struct udevice *dev, int offset, uint8_t *buf,
			       int size)
{
	return dm_i2c_read(dev, offset, buf, size);
}