Exemple #1
0
int spi_cs_info(struct udevice *bus, uint cs, struct spi_cs_info *info)
{
	struct spi_cs_info local_info;
	struct dm_spi_ops *ops;
	int ret;

	if (!info)
		info = &local_info;

	/* If there is a device attached, return it */
	info->dev = NULL;
	ret = spi_find_chip_select(bus, cs, &info->dev);
	if (!ret)
		return 0;

	/*
	 * Otherwise ask the driver. For the moment we don't have CS info.
	 * When we do we could provide the driver with a helper function
	 * to figure out what chip selects are valid, or just handle the
	 * request.
	 */
	ops = spi_get_ops(bus);
	if (ops->cs_info)
		return ops->cs_info(bus, cs, info);

	/*
	 * We could assume there is at least one valid chip select, but best
	 * to be sure and return an error in this case. The driver didn't
	 * care enough to tell us.
	 */
	return -ENODEV;
}
Exemple #2
0
int dm_spi_claim_bus(struct udevice *dev)
{
	struct udevice *bus = dev->parent;
	struct dm_spi_ops *ops = spi_get_ops(bus);
	struct dm_spi_bus *spi = dev_get_uclass_priv(bus);
	struct spi_slave *slave = dev_get_parent_priv(dev);
	int speed;
	int ret;

	speed = slave->max_hz;
	if (spi->max_hz) {
		if (speed)
			speed = min(speed, (int)spi->max_hz);
		else
			speed = spi->max_hz;
	}
	if (!speed)
		speed = 100000;
	if (speed != slave->speed) {
		ret = spi_set_speed_mode(bus, speed, slave->mode);
		if (ret)
			return ret;
		slave->speed = speed;
	}

	return ops->claim_bus ? ops->claim_bus(dev) : 0;
}
Exemple #3
0
static int spi_post_probe(struct udevice *bus)
{
#if !CONFIG_IS_ENABLED(OF_PLATDATA)
	struct dm_spi_bus *spi = dev_get_uclass_priv(bus);

	spi->max_hz = fdtdec_get_int(gd->fdt_blob, bus->of_offset,
				     "spi-max-frequency", 0);
#endif
#if defined(CONFIG_NEEDS_MANUAL_RELOC)
	struct dm_spi_ops *ops = spi_get_ops(bus);


	if (ops->claim_bus)
		ops->claim_bus += gd->reloc_off;
	if (ops->release_bus)
		ops->release_bus += gd->reloc_off;
	if (ops->set_wordlen)
		ops->set_wordlen += gd->reloc_off;
	if (ops->xfer)
		ops->xfer += gd->reloc_off;
	if (ops->set_speed)
		ops->set_speed += gd->reloc_off;
	if (ops->set_mode)
		ops->set_mode += gd->reloc_off;
	if (ops->cs_info)
		ops->cs_info += gd->reloc_off;
#endif

	return 0;
}
Exemple #4
0
static int spi_set_speed_mode(struct udevice *bus, int speed, int mode)
{
	struct dm_spi_ops *ops;
	int ret;

	ops = spi_get_ops(bus);
	if (ops->set_speed)
		ret = ops->set_speed(bus, speed);
	else
		ret = -EINVAL;
	if (ret) {
		printf("Cannot set speed (err=%d)\n", ret);
		return ret;
	}

	if (ops->set_mode)
		ret = ops->set_mode(bus, mode);
	else
		ret = -EINVAL;
	if (ret) {
		printf("Cannot set mode (err=%d)\n", ret);
		return ret;
	}

	return 0;
}
Exemple #5
0
static int spi_post_probe(struct udevice *bus)
{
#if !CONFIG_IS_ENABLED(OF_PLATDATA)
	struct dm_spi_bus *spi = dev_get_uclass_priv(bus);

	spi->max_hz = dev_read_u32_default(bus, "spi-max-frequency", 0);
#endif
#if defined(CONFIG_NEEDS_MANUAL_RELOC)
	struct dm_spi_ops *ops = spi_get_ops(bus);

	if (ops->claim_bus)
		ops->claim_bus += gd->reloc_off;
	if (ops->release_bus)
		ops->release_bus += gd->reloc_off;
	if (ops->set_wordlen)
		ops->set_wordlen += gd->reloc_off;
	if (ops->xfer)
		ops->xfer += gd->reloc_off;
	if (ops->set_speed)
		ops->set_speed += gd->reloc_off;
	if (ops->set_mode)
		ops->set_mode += gd->reloc_off;
	if (ops->cs_info)
		ops->cs_info += gd->reloc_off;
	if (ops->is_flash_command_supported)
		ops->is_flash_command_supported += gd->reloc_off;
	if (ops->exec_flash_command)
		ops->exec_flash_command += gd->reloc_off;
#endif

	return 0;
}
Exemple #6
0
void dm_spi_release_bus(struct udevice *dev)
{
	struct udevice *bus = dev->parent;
	struct dm_spi_ops *ops = spi_get_ops(bus);

	if (ops->release_bus)
		ops->release_bus(dev);
}
Exemple #7
0
void spi_release_bus(struct spi_slave *slave)
{
	struct udevice *dev = slave->dev;
	struct udevice *bus = dev->parent;
	struct dm_spi_ops *ops = spi_get_ops(bus);

	if (ops->release_bus)
		ops->release_bus(bus);
}
Exemple #8
0
int dm_spi_xfer(struct udevice *dev, unsigned int bitlen,
		const void *dout, void *din, unsigned long flags)
{
	struct udevice *bus = dev->parent;

	if (bus->uclass->uc_drv->id != UCLASS_SPI)
		return -EOPNOTSUPP;

	return spi_get_ops(bus)->xfer(dev, bitlen, dout, din, flags);
}
Exemple #9
0
/**
 * spi_mem_supports_op() - Check if a memory device and the controller it is
 *			   connected to support a specific memory operation
 * @slave: the SPI device
 * @op: the memory operation to check
 *
 * Some controllers are only supporting Single or Dual IOs, others might only
 * support specific opcodes, or it can even be that the controller and device
 * both support Quad IOs but the hardware prevents you from using it because
 * only 2 IO lines are connected.
 *
 * This function checks whether a specific operation is supported.
 *
 * Return: true if @op is supported, false otherwise.
 */
bool spi_mem_supports_op(struct spi_slave *slave,
			 const struct spi_mem_op *op)
{
	struct udevice *bus = slave->dev->parent;
	struct dm_spi_ops *ops = spi_get_ops(bus);

	if (ops->mem_ops && ops->mem_ops->supports_op)
		return ops->mem_ops->supports_op(slave, op);

	return spi_mem_default_supports_op(slave, op);
}
Exemple #10
0
bool dm_spi_is_flash_command_supported(struct udevice *dev,
				       const struct spi_flash_command *cmd)
{
	struct udevice *bus = dev->parent;
	struct dm_spi_ops *ops = spi_get_ops(bus);

	if (ops->is_flash_command_supported)
		return ops->is_flash_command_supported(dev, cmd);

	return false;
}
Exemple #11
0
int dm_spi_exec_flash_command(struct udevice *dev,
			      const struct spi_flash_command *cmd)
{
	struct udevice *bus = dev->parent;
	struct dm_spi_ops *ops = spi_get_ops(bus);

	if (ops->exec_flash_command)
		return ops->exec_flash_command(dev, cmd);

	return -EINVAL;
}
Exemple #12
0
int spi_claim_bus(struct spi_slave *slave)
{
	struct udevice *dev = slave->dev;
	struct udevice *bus = dev->parent;
	struct dm_spi_ops *ops = spi_get_ops(bus);
	struct dm_spi_bus *spi = bus->uclass_priv;
	int speed;
	int ret;

	speed = slave->max_hz;
	if (spi->max_hz) {
		if (speed)
			speed = min(speed, (int)spi->max_hz);
		else
			speed = spi->max_hz;
	}
	if (!speed)
		speed = 100000;
	ret = spi_set_speed_mode(bus, speed, slave->mode);
	if (ret)
		return ret;

	return ops->claim_bus ? ops->claim_bus(bus) : 0;
}
Exemple #13
0
/**
 * spi_mem_exec_op() - Execute a memory operation
 * @slave: the SPI device
 * @op: the memory operation to execute
 *
 * Executes a memory operation.
 *
 * This function first checks that @op is supported and then tries to execute
 * it.
 *
 * Return: 0 in case of success, a negative error code otherwise.
 */
int spi_mem_exec_op(struct spi_slave *slave, const struct spi_mem_op *op)
{
	struct udevice *bus = slave->dev->parent;
	struct dm_spi_ops *ops = spi_get_ops(bus);
	unsigned int pos = 0;
	const u8 *tx_buf = NULL;
	u8 *rx_buf = NULL;
	u8 *op_buf;
	int op_len;
	u32 flag;
	int ret;
	int i;

	if (!spi_mem_supports_op(slave, op))
		return -ENOTSUPP;

	if (ops->mem_ops) {
#ifndef __UBOOT__
		/*
		 * Flush the message queue before executing our SPI memory
		 * operation to prevent preemption of regular SPI transfers.
		 */
		spi_flush_queue(ctlr);

		if (ctlr->auto_runtime_pm) {
			ret = pm_runtime_get_sync(ctlr->dev.parent);
			if (ret < 0) {
				dev_err(&ctlr->dev,
					"Failed to power device: %d\n",
					ret);
				return ret;
			}
		}

		mutex_lock(&ctlr->bus_lock_mutex);
		mutex_lock(&ctlr->io_mutex);
#endif
		ret = ops->mem_ops->exec_op(slave, op);
#ifndef __UBOOT__
		mutex_unlock(&ctlr->io_mutex);
		mutex_unlock(&ctlr->bus_lock_mutex);

		if (ctlr->auto_runtime_pm)
			pm_runtime_put(ctlr->dev.parent);
#endif

		/*
		 * Some controllers only optimize specific paths (typically the
		 * read path) and expect the core to use the regular SPI
		 * interface in other cases.
		 */
		if (!ret || ret != -ENOTSUPP)
			return ret;
	}

#ifndef __UBOOT__
	tmpbufsize = sizeof(op->cmd.opcode) + op->addr.nbytes +
		     op->dummy.nbytes;

	/*
	 * Allocate a buffer to transmit the CMD, ADDR cycles with kmalloc() so
	 * we're guaranteed that this buffer is DMA-able, as required by the
	 * SPI layer.
	 */
	tmpbuf = kzalloc(tmpbufsize, GFP_KERNEL | GFP_DMA);
	if (!tmpbuf)
		return -ENOMEM;

	spi_message_init(&msg);

	tmpbuf[0] = op->cmd.opcode;
	xfers[xferpos].tx_buf = tmpbuf;
	xfers[xferpos].len = sizeof(op->cmd.opcode);
	xfers[xferpos].tx_nbits = op->cmd.buswidth;
	spi_message_add_tail(&xfers[xferpos], &msg);
	xferpos++;
	totalxferlen++;

	if (op->addr.nbytes) {
		int i;

		for (i = 0; i < op->addr.nbytes; i++)
			tmpbuf[i + 1] = op->addr.val >>
					(8 * (op->addr.nbytes - i - 1));

		xfers[xferpos].tx_buf = tmpbuf + 1;
		xfers[xferpos].len = op->addr.nbytes;
		xfers[xferpos].tx_nbits = op->addr.buswidth;
		spi_message_add_tail(&xfers[xferpos], &msg);
		xferpos++;
		totalxferlen += op->addr.nbytes;
	}