Beispiel #1
0
int at91_clk_probe(struct udevice *dev)
{
	struct udevice *dev_periph_container, *dev_pmc;
	struct pmc_platdata *plat = dev_get_platdata(dev);

	dev_periph_container = dev_get_parent(dev);
	dev_pmc = dev_get_parent(dev_periph_container);

	plat->reg_base = (struct at91_pmc *)dev_get_addr_ptr(dev_pmc);

	return 0;
}
Beispiel #2
0
static int palmas_ldo_probe(struct udevice *dev)
{
	struct dm_regulator_uclass_platdata *uc_pdata;
	struct udevice *parent;

	uc_pdata = dev_get_uclass_platdata(dev);

	parent = dev_get_parent(dev);
	int type = dev_get_driver_data(parent);

	uc_pdata->type = REGULATOR_TYPE_LDO;

	if (dev->driver_data) {
		u8 idx = dev->driver_data - 1;
		uc_pdata->ctrl_reg = palmas_ldo_ctrl[type][idx];
		uc_pdata->volt_reg = palmas_ldo_volt[type][idx];
	} else {
		/* check for ldoln and ldousb cases */
		if (!strcmp("ldoln", dev->name)) {
			uc_pdata->ctrl_reg = palmas_ldo_ctrl[type][9];
			uc_pdata->volt_reg = palmas_ldo_volt[type][9];
		} else if (!strcmp("ldousb", dev->name)) {
			uc_pdata->ctrl_reg = palmas_ldo_ctrl[type][10];
			uc_pdata->volt_reg = palmas_ldo_volt[type][10];
		}
	}

	return 0;
}
Beispiel #3
0
static int palmas_ldo_bypass_enable(struct udevice *dev, bool enabled)
{
	int type = dev_get_driver_data(dev_get_parent(dev));
	struct dm_regulator_uclass_platdata *p;
	unsigned int adr;
	int reg;

	if (type == TPS65917) {
		/* bypass available only on LDO1 and LDO2 */
		if (dev->driver_data > 2)
			return -ENOTSUPP;
	} else if (type == TPS659038) {
		/* bypass available only on LDO9 */
		if (dev->driver_data != 9)
			return -ENOTSUPP;
	}

	p = dev_get_uclass_platdata(dev);
	adr = p->ctrl_reg;

	reg = pmic_reg_read(dev->parent, adr);
	if (reg < 0)
		return reg;

	if (enabled)
		reg |= PALMAS_LDO_BYPASS_EN;
	else
		reg &= ~PALMAS_LDO_BYPASS_EN;

	return pmic_reg_write(dev->parent, adr, reg);
}
Beispiel #4
0
static int periph_clk_enable(struct clk *clk)
{
	struct pmc_platdata *plat = dev_get_platdata(clk->dev);
	struct at91_pmc *pmc = plat->reg_base;
	enum periph_clk_type clk_type;
	void *addr;

	if (clk->id < PERIPHERAL_ID_MIN)
		return -1;

	clk_type = dev_get_driver_data(dev_get_parent(clk->dev));
	if (clk_type == CLK_PERIPH_AT91RM9200) {
		addr = &pmc->pcer;
		if (clk->id > PERIPHERAL_ID_MAX)
			addr = &pmc->pcer1;

		setbits_le32(addr, PERIPHERAL_MASK(clk->id));
	} else {
		writel(clk->id & AT91_PMC_PCR_PID_MASK, &pmc->pcr);
		setbits_le32(&pmc->pcr,
			     AT91_PMC_PCR_CMD_WRITE | AT91_PMC_PCR_EN);
	}

	return 0;
}
Beispiel #5
0
/* Test that block devices work correctly with USB */
static int dm_test_blk_usb(struct unit_test_state *uts)
{
	struct udevice *usb_dev, *dev;
	struct blk_desc *dev_desc;

	/* Get a flash device */
	state_set_skip_delays(true);
	ut_assertok(usb_init());
	ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 0, &usb_dev));
	ut_assertok(blk_get_device_by_str("usb", "0", &dev_desc));

	/* The parent should be a block device */
	ut_assertok(blk_get_device(IF_TYPE_USB, 0, &dev));
	ut_asserteq_ptr(usb_dev, dev_get_parent(dev));

	/* Check we have one block device for each mass storage device */
	ut_asserteq(6, count_blk_devices());

	/* Now go around again, making sure the old devices were unbound */
	ut_assertok(usb_stop());
	ut_assertok(usb_init());
	ut_asserteq(6, count_blk_devices());
	ut_assertok(usb_stop());

	return 0;
}
Beispiel #6
0
static int i2c_read_bytewise(struct udevice *dev, uint offset,
			     uint8_t *buffer, int len)
{
	struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
	struct udevice *bus = dev_get_parent(dev);
	struct dm_i2c_ops *ops = i2c_get_ops(bus);
	struct i2c_msg msg[2], *ptr;
	uint8_t offset_buf[I2C_MAX_OFFSET_LEN];
	int ret;
	int i;

	for (i = 0; i < len; i++) {
		if (i2c_setup_offset(chip, offset + i, offset_buf, msg))
			return -EINVAL;
		ptr = msg + 1;
		ptr->addr = chip->chip_addr;
		ptr->flags = msg->flags | I2C_M_RD;
		ptr->len = 1;
		ptr->buf = &buffer[i];
		ptr++;

		ret = ops->xfer(bus, msg, ptr - msg);
		if (ret)
			return ret;
	}

	return 0;
}
Beispiel #7
0
/* Test that block device numbering works as expected */
static int dm_test_blk_devnum(struct unit_test_state *uts)
{
	struct udevice *dev, *mmc_dev, *parent;
	int i;

	/*
	 * Probe the devices, with the first one being probed last. This is the
	 * one with no alias / sequence numnber.
	 */
	ut_assertok(uclass_get_device(UCLASS_MMC, 1, &dev));
	ut_assertok(uclass_get_device(UCLASS_MMC, 2, &dev));
	ut_assertok(uclass_get_device(UCLASS_MMC, 0, &dev));
	for (i = 0; i < 3; i++) {
		struct blk_desc *desc;

		/* Check that the bblock device is attached */
		ut_assertok(uclass_get_device_by_seq(UCLASS_MMC, i, &mmc_dev));
		ut_assertok(blk_find_device(IF_TYPE_MMC, i, &dev));
		parent = dev_get_parent(dev);
		ut_asserteq_ptr(parent, mmc_dev);
		ut_asserteq(trailing_strtol(mmc_dev->name), i);

		/*
		 * Check that the block device devnum matches its parent's
		 * sequence number
		 */
		desc = dev_get_uclass_platdata(dev);
		ut_asserteq(desc->devnum, i);
	}

	return 0;
}
Beispiel #8
0
int dm_i2c_read(struct udevice *dev, uint offset, uint8_t *buffer, int len)
{
	struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
	struct udevice *bus = dev_get_parent(dev);
	struct dm_i2c_ops *ops = i2c_get_ops(bus);
	struct i2c_msg msg[2], *ptr;
	uint8_t offset_buf[I2C_MAX_OFFSET_LEN];
	int msg_count;

	if (!ops->xfer)
		return -ENOSYS;
	if (chip->flags & DM_I2C_CHIP_RD_ADDRESS)
		return i2c_read_bytewise(dev, offset, buffer, len);
	ptr = msg;
	if (!i2c_setup_offset(chip, offset, offset_buf, ptr))
		ptr++;

	if (len) {
		ptr->addr = chip->chip_addr;
		ptr->flags = chip->flags & DM_I2C_CHIP_10BIT ? I2C_M_TEN : 0;
		ptr->flags |= I2C_M_RD;
		ptr->len = len;
		ptr->buf = buffer;
		ptr++;
	}
	msg_count = ptr - msg;

	return ops->xfer(bus, msg, msg_count);
}
Beispiel #9
0
static void spi_cs_deactivate(struct udevice *dev)
{
	struct udevice *bus = dev_get_parent(dev);
	struct xilinx_spi_priv *priv = dev_get_priv(bus);
	struct xilinx_spi_regs *regs = priv->regs;

	writel(SPISSR_OFF, &regs->spissr);
}
Beispiel #10
0
static int mmc_blk_remove(struct udevice *dev)
{
	struct udevice *mmc_dev = dev_get_parent(dev);
	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(mmc_dev);
	struct mmc *mmc = upriv->mmc;

	return mmc_deinit(mmc);
}
Beispiel #11
0
static int atmel_spi_release_bus(struct udevice *dev)
{
	struct udevice *bus = dev_get_parent(dev);
	struct atmel_spi_platdata *bus_plat = dev_get_platdata(bus);

	writel(ATMEL_SPI_CR_SPIDIS, &bus_plat->regs->cr);

	return 0;
}
Beispiel #12
0
static void atmel_spi_cs_deactivate(struct udevice *dev)
{
	struct udevice *bus = dev_get_parent(dev);
	struct atmel_spi_priv *priv = dev_get_priv(bus);
	struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
	u32 cs = slave_plat->cs;

	dm_gpio_set_value(&priv->cs_gpios[cs], 1);
}
Beispiel #13
0
int dm_i2c_xfer(struct udevice *dev, struct i2c_msg *msg, int nmsgs)
{
	struct udevice *bus = dev_get_parent(dev);
	struct dm_i2c_ops *ops = i2c_get_ops(bus);

	if (!ops->xfer)
		return -ENOSYS;

	return ops->xfer(bus, msg, nmsgs);
}
Beispiel #14
0
int at91_pmc_core_probe(struct udevice *dev)
{
	struct pmc_platdata *plat = dev_get_platdata(dev);

	dev = dev_get_parent(dev);

	plat->reg_base = (struct at91_pmc *)dev_get_addr_ptr(dev);

	return 0;
}
Beispiel #15
0
int dm_i2c_write(struct udevice *dev, uint offset, const uint8_t *buffer,
		 int len)
{
	struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
	struct udevice *bus = dev_get_parent(dev);
	struct dm_i2c_ops *ops = i2c_get_ops(bus);
	struct i2c_msg msg[1];

	if (!ops->xfer)
		return -ENOSYS;

	if (chip->flags & DM_I2C_CHIP_WR_ADDRESS)
		return i2c_write_bytewise(dev, offset, buffer, len);
	/*
	 * The simple approach would be to send two messages here: one to
	 * set the offset and one to write the bytes. However some drivers
	 * will not be expecting this, and some chips won't like how the
	 * driver presents this on the I2C bus.
	 *
	 * The API does not support separate offset and data. We could extend
	 * it with a flag indicating that there is data in the next message
	 * that needs to be processed in the same transaction. We could
	 * instead add an additional buffer to each message. For now, handle
	 * this in the uclass since it isn't clear what the impact on drivers
	 * would be with this extra complication. Unfortunately this means
	 * copying the message.
	 *
	 * Use the stack for small messages, malloc() for larger ones. We
	 * need to allow space for the offset (up to 4 bytes) and the message
	 * itself.
	 */
	if (len < 64) {
		uint8_t buf[I2C_MAX_OFFSET_LEN + len];

		i2c_setup_offset(chip, offset, buf, msg);
		msg->len += len;
		memcpy(buf + chip->offset_len, buffer, len);

		return ops->xfer(bus, msg, 1);
	} else {
		uint8_t *buf;
		int ret;

		buf = malloc(I2C_MAX_OFFSET_LEN + len);
		if (!buf)
			return -ENOMEM;
		i2c_setup_offset(chip, offset, buf, msg);
		msg->len += len;
		memcpy(buf + chip->offset_len, buffer, len);

		ret = ops->xfer(bus, msg, 1);
		free(buf);
		return ret;
	}
}
Beispiel #16
0
static int xilinx_spi_release_bus(struct udevice *dev)
{
	struct udevice *bus = dev_get_parent(dev);
	struct xilinx_spi_priv *priv = dev_get_priv(bus);
	struct xilinx_spi_regs *regs = priv->regs;

	writel(SPISSR_OFF, &regs->spissr);
	writel(XILSPI_SPICR_DFLT_OFF, &regs->spicr);

	return 0;
}
Beispiel #17
0
static int pfuze100_regulator_probe(struct udevice *dev)
{
	struct dm_regulator_uclass_platdata *uc_pdata;
	struct pfuze100_regulator_platdata *plat = dev_get_platdata(dev);
	struct pfuze100_regulator_desc *desc;

	switch (dev_get_driver_data(dev_get_parent(dev))) {
	case PFUZE100:
		desc = se_desc(pfuze100_regulators,
			       ARRAY_SIZE(pfuze100_regulators),
			       dev->name);
		break;
	case PFUZE200:
		desc = se_desc(pfuze200_regulators,
			       ARRAY_SIZE(pfuze200_regulators),
			       dev->name);
		break;
	case PFUZE3000:
		desc = se_desc(pfuze3000_regulators,
			       ARRAY_SIZE(pfuze3000_regulators),
			       dev->name);
		break;
	default:
		debug("Unsupported PFUZE\n");
		return -EINVAL;
	}
	if (!desc) {
		debug("Do not support regulator %s\n", dev->name);
		return -EINVAL;
	}

	plat->desc = desc;
	uc_pdata = dev_get_uclass_platdata(dev);

	uc_pdata->type = desc->type;
	if (uc_pdata->type == REGULATOR_TYPE_BUCK) {
		if (!strcmp(dev->name, "swbst")) {
			uc_pdata->mode = pfuze_swbst_modes;
			uc_pdata->mode_count = ARRAY_SIZE(pfuze_swbst_modes);
		} else {
			uc_pdata->mode = pfuze_sw_modes;
			uc_pdata->mode_count = ARRAY_SIZE(pfuze_sw_modes);
		}
	} else if (uc_pdata->type == REGULATOR_TYPE_LDO) {
		uc_pdata->mode = pfuze_ldo_modes;
		uc_pdata->mode_count = ARRAY_SIZE(pfuze_ldo_modes);
	} else {
		uc_pdata->mode = NULL;
		uc_pdata->mode_count = 0;
	}

	return 0;
}
Beispiel #18
0
static int bcm6858_led_probe(struct udevice *dev)
{
	struct led_uc_plat *uc_plat = dev_get_uclass_platdata(dev);

	/* Top-level LED node */
	if (!uc_plat->label) {
		void __iomem *regs;
		u32 set_bits = 0;

		regs = dev_remap_addr(dev);
		if (!regs)
			return -EINVAL;

		if (dev_read_bool(dev, "brcm,serial-led-msb-first"))
			set_bits |= LED_CTRL_SERIAL_LED_MSB_FIRST;
		if (dev_read_bool(dev, "brcm,serial-led-en-pol"))
			set_bits |= LED_CTRL_SERIAL_LED_EN_POL;
		if (dev_read_bool(dev, "brcm,serial-led-clk-pol"))
			set_bits |= LED_CTRL_SERIAL_LED_CLK_POL;
		if (dev_read_bool(dev, "brcm,serial-led-data-ppol"))
			set_bits |= LED_CTRL_SERIAL_LED_DATA_PPOL;
		if (dev_read_bool(dev, "brcm,led-test-mode"))
			set_bits |= LED_CTRL_LED_TEST_MODE;

		clrsetbits_32(regs + LED_CTRL_REG, ~0, set_bits);
	} else {
		struct bcm6858_led_priv *priv = dev_get_priv(dev);
		void __iomem *regs;
		unsigned int pin;

		regs = dev_remap_addr(dev_get_parent(dev));
		if (!regs)
			return -EINVAL;

		pin = dev_read_u32_default(dev, "reg", LEDS_MAX);
		if (pin >= LEDS_MAX)
			return -EINVAL;

		priv->regs = regs;
		priv->pin = pin;

		/* this led is managed by software */
		clrbits_32(regs + LED_HW_LED_EN_REG, 1 << pin);

		/* configure the polarity */
		if (dev_read_bool(dev, "active-low"))
			clrbits_32(regs + LED_SW_LED_IP_PPOL_REG, 1 << pin);
		else
			setbits_32(regs + LED_SW_LED_IP_PPOL_REG, 1 << pin);
	}

	return 0;
}
static int atmel_pinctrl_probe(struct udevice *dev)
{
	struct atmel_pio4_platdata *plat = dev_get_platdata(dev);
	fdt_addr_t addr_base;

	dev = dev_get_parent(dev);
	addr_base = dev_get_addr(dev);
	if (addr_base == FDT_ADDR_T_NONE)
		return -EINVAL;

	plat->reg_base = (struct atmel_pio4_port *)addr_base;

	return 0;
}
Beispiel #20
0
static int mmc_select_hwpart(struct udevice *bdev, int hwpart)
{
	struct udevice *mmc_dev = dev_get_parent(bdev);
	struct mmc *mmc = mmc_get_mmc_dev(mmc_dev);
	struct blk_desc *desc = dev_get_uclass_platdata(bdev);

	if (desc->hwpart == hwpart)
		return 0;

	if (mmc->part_config == MMCPART_NOAVAILABLE)
		return -EMEDIUMTYPE;

	return mmc_switch_part(mmc, hwpart);
}
Beispiel #21
0
static void atmel_spi_cs_deactivate(struct udevice *dev)
{
#ifdef CONFIG_DM_GPIO
	struct udevice *bus = dev_get_parent(dev);
	struct atmel_spi_priv *priv = dev_get_priv(bus);
	struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
	u32 cs = slave_plat->cs;

	if (!dm_gpio_is_valid(&priv->cs_gpios[cs]))
		return;

	dm_gpio_set_value(&priv->cs_gpios[cs], 1);
#endif
}
Beispiel #22
0
static int mmc_blk_probe(struct udevice *dev)
{
	struct udevice *mmc_dev = dev_get_parent(dev);
	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(mmc_dev);
	struct mmc *mmc = upriv->mmc;
	int ret;

	ret = mmc_init(mmc);
	if (ret) {
		debug("%s: mmc_init() failed (err=%d)\n", __func__, ret);
		return ret;
	}

	return 0;
}
Beispiel #23
0
struct mmc *find_mmc_device(int dev_num)
{
	struct udevice *dev, *mmc_dev;
	int ret;

	ret = blk_get_device(IF_TYPE_MMC, dev_num, &dev);

	if (ret) {
#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
		printf("MMC Device %d not found\n", dev_num);
#endif
		return NULL;
	}

	mmc_dev = dev_get_parent(dev);

	return mmc_get_mmc_dev(mmc_dev);
}
Beispiel #24
0
static ulong periph_get_rate(struct clk *clk)
{
	struct udevice *dev;
	struct clk clk_dev;
	ulong clk_rate;
	int ret;

	dev = dev_get_parent(clk->dev);

	ret = clk_get_by_index(dev, 0, &clk_dev);
	if (ret)
		return ret;

	clk_rate = clk_get_rate(&clk_dev);

	clk_free(&clk_dev);

	return clk_rate;
}
Beispiel #25
0
/**
 * pinctrl_config_one() - apply pinctrl settings for a single node
 *
 * @config: pin configuration node
 * @return: 0 on success, or negative error code on failure
 */
static int pinctrl_config_one(struct udevice *config)
{
	struct udevice *pctldev;
	const struct pinctrl_ops *ops;

	pctldev = config;
	for (;;) {
		pctldev = dev_get_parent(pctldev);
		if (!pctldev) {
			dev_err(config, "could not find pctldev\n");
			return -EINVAL;
		}
		if (pctldev->uclass->uc_drv->id == UCLASS_PINCTRL)
			break;
	}

	ops = pinctrl_get_ops(pctldev);
	return ops->set_state(pctldev, config);
}
Beispiel #26
0
static int atmel_spi_claim_bus(struct udevice *dev)
{
	struct udevice *bus = dev_get_parent(dev);
	struct atmel_spi_platdata *bus_plat = dev_get_platdata(bus);
	struct atmel_spi_priv *priv = dev_get_priv(bus);
	struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
	struct at91_spi *reg_base = bus_plat->regs;
	u32 cs = slave_plat->cs;
	u32 freq = priv->freq;
	u32 scbr, csrx, mode;

	scbr = (priv->bus_clk_rate + freq - 1) / freq;
	if (scbr > ATMEL_SPI_CSRx_SCBR_MAX)
		return -EINVAL;

	if (scbr < 1)
		scbr = 1;

	csrx = ATMEL_SPI_CSRx_SCBR(scbr);
	csrx |= ATMEL_SPI_CSRx_BITS(ATMEL_SPI_BITS_8);

	if (!(priv->mode & SPI_CPHA))
		csrx |= ATMEL_SPI_CSRx_NCPHA;
	if (priv->mode & SPI_CPOL)
		csrx |= ATMEL_SPI_CSRx_CPOL;

	writel(csrx, &reg_base->csr[cs]);

	mode = ATMEL_SPI_MR_MSTR |
	       ATMEL_SPI_MR_MODFDIS |
	       ATMEL_SPI_MR_WDRBT |
	       ATMEL_SPI_MR_PCS(~(1 << cs));

	writel(mode, &reg_base->mr);

	writel(ATMEL_SPI_CR_SPIEN, &reg_base->cr);

	return 0;
}
Beispiel #27
0
static int i2c_write_bytewise(struct udevice *dev, uint offset,
			     const uint8_t *buffer, int len)
{
	struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
	struct udevice *bus = dev_get_parent(dev);
	struct dm_i2c_ops *ops = i2c_get_ops(bus);
	struct i2c_msg msg[1];
	uint8_t buf[I2C_MAX_OFFSET_LEN + 1];
	int ret;
	int i;

	for (i = 0; i < len; i++) {
		if (i2c_setup_offset(chip, offset + i, buf, msg))
			return -EINVAL;
		buf[msg->len++] = buffer[i];

		ret = ops->xfer(bus, msg, 1);
		if (ret)
			return ret;
	}

	return 0;
}
Beispiel #28
0
static int palmas_smps_probe(struct udevice *dev)
{
	struct dm_regulator_uclass_platdata *uc_pdata;
	struct udevice *parent;
	int idx;

	uc_pdata = dev_get_uclass_platdata(dev);

	parent = dev_get_parent(dev);
	int type = dev_get_driver_data(parent);

	uc_pdata->type = REGULATOR_TYPE_BUCK;

	switch (type) {
	case PALMAS:
	case TPS659038:
		switch (dev->driver_data) {
		case 123:
		case 12:
			uc_pdata->ctrl_reg = palmas_smps_ctrl[type][0];
			uc_pdata->volt_reg = palmas_smps_volt[type][0];
			break;
		case 3:
			uc_pdata->ctrl_reg = palmas_smps_ctrl[type][1];
			uc_pdata->volt_reg = palmas_smps_volt[type][1];
			break;
		case 45:
			uc_pdata->ctrl_reg = palmas_smps_ctrl[type][2];
			uc_pdata->volt_reg = palmas_smps_volt[type][2];
			break;
		case 6:
		case 7:
		case 8:
		case 9:
		case 10:
			idx = dev->driver_data - 3;
			uc_pdata->ctrl_reg = palmas_smps_ctrl[type][idx];
			uc_pdata->volt_reg = palmas_smps_volt[type][idx];
			break;

		default:
			printf("Wrong ID for regulator\n");
		}
		break;

	case TPS65917:
		switch (dev->driver_data) {
		case 1:
		case 2:
		case 3:
		case 4:
		case 5:
			idx = dev->driver_data - 1;
			uc_pdata->ctrl_reg = palmas_smps_ctrl[type][idx];
			uc_pdata->volt_reg = palmas_smps_volt[type][idx];
			break;
		case 12:
			idx = 0;
			uc_pdata->ctrl_reg = palmas_smps_ctrl[type][idx];
			uc_pdata->volt_reg = palmas_smps_volt[type][idx];
			break;
		default:
			printf("Wrong ID for regulator\n");
		}
		break;

	default:
			printf("Invalid PMIC ID\n");
	}

	return 0;
}
Beispiel #29
0
static int xilinx_spi_xfer(struct udevice *dev, unsigned int bitlen,
			    const void *dout, void *din, unsigned long flags)
{
	struct udevice *bus = dev_get_parent(dev);
	struct xilinx_spi_priv *priv = dev_get_priv(bus);
	struct xilinx_spi_regs *regs = priv->regs;
	struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
	/* assume spi core configured to do 8 bit transfers */
	unsigned int bytes = bitlen / XILSPI_MAX_XFER_BITS;
	const unsigned char *txp = dout;
	unsigned char *rxp = din;
	unsigned rxecount = 17;	/* max. 16 elements in FIFO, leftover 1 */
	unsigned global_timeout;

	debug("spi_xfer: bus:%i cs:%i bitlen:%i bytes:%i flags:%lx\n",
	      bus->seq, slave_plat->cs, bitlen, bytes, flags);

	if (bitlen == 0)
		goto done;

	if (bitlen % XILSPI_MAX_XFER_BITS) {
		printf("XILSPI warning: Not a multiple of %d bits\n",
		       XILSPI_MAX_XFER_BITS);
		flags |= SPI_XFER_END;
		goto done;
	}

	/* empty read buffer */
	while (rxecount && !(readl(&regs->spisr) & SPISR_RX_EMPTY)) {
		readl(&regs->spidrr);
		rxecount--;
	}

	if (!rxecount) {
		printf("XILSPI error: Rx buffer not empty\n");
		return -1;
	}

	if (flags & SPI_XFER_BEGIN)
		spi_cs_activate(dev, slave_plat->cs);

	/* at least 1usec or greater, leftover 1 */
	global_timeout = priv->freq > XILSPI_MAX_XFER_BITS * 1000000 ? 2 :
			(XILSPI_MAX_XFER_BITS * 1000000 / priv->freq) + 1;

	while (bytes--) {
		unsigned timeout = global_timeout;
		/* get Tx element from data out buffer and count up */
		unsigned char d = txp ? *txp++ : CONFIG_XILINX_SPI_IDLE_VAL;
		debug("spi_xfer: tx:%x ", d);

		/* write out and wait for processing (receive data) */
		writel(d & SPIDTR_8BIT_MASK, &regs->spidtr);
		while (timeout && readl(&regs->spisr)
						& SPISR_RX_EMPTY) {
			timeout--;
			udelay(1);
		}

		if (!timeout) {
			printf("XILSPI error: Xfer timeout\n");
			return -1;
		}

		/* read Rx element and push into data in buffer */
		d = readl(&regs->spidrr) & SPIDRR_8BIT_MASK;
		if (rxp)
			*rxp++ = d;
		debug("spi_xfer: rx:%x\n", d);
	}

 done:
	if (flags & SPI_XFER_END)
		spi_cs_deactivate(dev);

	return 0;
}
Beispiel #30
0
static int atmel_spi_xfer(struct udevice *dev, unsigned int bitlen,
			  const void *dout, void *din, unsigned long flags)
{
	struct udevice *bus = dev_get_parent(dev);
	struct atmel_spi_platdata *bus_plat = dev_get_platdata(bus);
	struct at91_spi *reg_base = bus_plat->regs;

	u32 len_tx, len_rx, len;
	u32 status;
	const u8 *txp = dout;
	u8 *rxp = din;
	u8 value;

	if (bitlen == 0)
		goto out;

	/*
	 * The controller can do non-multiple-of-8 bit
	 * transfers, but this driver currently doesn't support it.
	 *
	 * It's also not clear how such transfers are supposed to be
	 * represented as a stream of bytes...this is a limitation of
	 * the current SPI interface.
	 */
	if (bitlen % 8) {
		/* Errors always terminate an ongoing transfer */
		flags |= SPI_XFER_END;
		goto out;
	}

	len = bitlen / 8;

	/*
	 * The controller can do automatic CS control, but it is
	 * somewhat quirky, and it doesn't really buy us much anyway
	 * in the context of U-Boot.
	 */
	if (flags & SPI_XFER_BEGIN) {
		atmel_spi_cs_activate(dev);

		/*
		 * sometimes the RDR is not empty when we get here,
		 * in theory that should not happen, but it DOES happen.
		 * Read it here to be on the safe side.
		 * That also clears the OVRES flag. Required if the
		 * following loop exits due to OVRES!
		 */
		readl(&reg_base->rdr);
	}

	for (len_tx = 0, len_rx = 0; len_rx < len; ) {
		status = readl(&reg_base->sr);

		if (status & ATMEL_SPI_SR_OVRES)
			return -1;

		if ((len_tx < len) && (status & ATMEL_SPI_SR_TDRE)) {
			if (txp)
				value = *txp++;
			else
				value = 0;
			writel(value, &reg_base->tdr);
			len_tx++;
		}

		if (status & ATMEL_SPI_SR_RDRF) {
			value = readl(&reg_base->rdr);
			if (rxp)
				*rxp++ = value;
			len_rx++;
		}
	}

out:
	if (flags & SPI_XFER_END) {
		/*
		 * Wait until the transfer is completely done before
		 * we deactivate CS.
		 */
		wait_for_bit(__func__, &reg_base->sr,
			     ATMEL_SPI_SR_TXEMPTY, true, 1000, false);

		atmel_spi_cs_deactivate(dev);
	}

	return 0;
}