Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 56f4249d authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "spi: core: Add support for registering SPI slave controllers"

parents b9d7765e 7e351fc4
Loading
Loading
Loading
Loading
+13 −1
Original line number Original line Diff line number Diff line
@@ -704,6 +704,18 @@ config SPI_TLE62X0


endif # SPI_MASTER
endif # SPI_MASTER


# (slave support would go here)
#
# SLAVE side ... listening to other SPI masters
#

config SPI_SLAVE
	bool "SPI slave protocol handlers"
	help
	  If your system has a slave-capable SPI controller, you can enable
	  slave protocol handlers.

if SPI_SLAVE

endif # SPI_SLAVE


endif # SPI
endif # SPI
+2 −0
Original line number Original line Diff line number Diff line
@@ -95,3 +95,5 @@ obj-$(CONFIG_SPI_XTENSA_XTFPGA) += spi-xtensa-xtfpga.o
obj-$(CONFIG_SPI_ZYNQMP_GQSPI)		+= spi-zynqmp-gqspi.o
obj-$(CONFIG_SPI_ZYNQMP_GQSPI)		+= spi-zynqmp-gqspi.o
obj-$(CONFIG_SPI_QSD)			+= spi_qsd.o
obj-$(CONFIG_SPI_QSD)			+= spi_qsd.o
obj-$(CONFIG_SPI_QUP)			+= spi_qsd.o
obj-$(CONFIG_SPI_QUP)			+= spi_qsd.o

# SPI slave protocol handlers
+152 −24
Original line number Original line Diff line number Diff line
@@ -1427,15 +1427,6 @@ static int of_spi_parse_dt(struct spi_master *master, struct spi_device *spi,
	u32 value;
	u32 value;
	int rc;
	int rc;


	/* Device address */
	rc = of_property_read_u32(nc, "reg", &value);
	if (rc) {
		dev_err(&master->dev, "%s has no valid 'reg' property (%d)\n",
			nc->full_name, rc);
		return rc;
	}
	spi->chip_select = value;

	/* Mode (clock phase/polarity/etc.) */
	/* Mode (clock phase/polarity/etc.) */
	if (of_find_property(nc, "spi-cpha", NULL))
	if (of_find_property(nc, "spi-cpha", NULL))
		spi->mode |= SPI_CPHA;
		spi->mode |= SPI_CPHA;
@@ -1485,6 +1476,24 @@ static int of_spi_parse_dt(struct spi_master *master, struct spi_device *spi,
		}
		}
	}
	}


	if (spi_controller_is_slave(master)) {
		if (strcmp(nc->name, "slave")) {
			dev_err(&master->dev, "%s is not called 'slave'\n",
				nc->full_name);
			return -EINVAL;
		}
		return 0;
	}

	/* Device address */
	rc = of_property_read_u32(nc, "reg", &value);
	if (rc) {
		dev_err(&master->dev, "%s has no valid 'reg' property (%d)\n",
			nc->full_name, rc);
		return rc;
	}
	spi->chip_select = value;

	/* Device speed */
	/* Device speed */
	rc = of_property_read_u32(nc, "spi-max-frequency", &value);
	rc = of_property_read_u32(nc, "spi-max-frequency", &value);
	if (rc) {
	if (rc) {
@@ -1548,8 +1557,8 @@ err_out:
 * of_register_spi_devices() - Register child devices onto the SPI bus
 * of_register_spi_devices() - Register child devices onto the SPI bus
 * @master:	Pointer to spi_master device
 * @master:	Pointer to spi_master device
 *
 *
 * Registers an spi_device for each child node of master node which has a 'reg'
 * Registers an spi_device for each child node of controller node which
 * property.
 * represents a valid SPI slave.
 */
 */
static void of_register_spi_devices(struct spi_master *master)
static void of_register_spi_devices(struct spi_master *master)
{
{
@@ -1681,28 +1690,129 @@ static struct class spi_master_class = {
	.dev_groups	= spi_master_groups,
	.dev_groups	= spi_master_groups,
};
};


#ifdef CONFIG_SPI_SLAVE
/**
 * spi_slave_abort - abort the ongoing transfer request on an SPI slave
 *		     controller
 * @spi: device used for the current transfer
 */
int spi_slave_abort(struct spi_device *spi)
{
	struct spi_master *master = spi->master;

	if (spi_controller_is_slave(master) && master->slave_abort)
		return master->slave_abort(master);

	return -ENOTSUPP;
}
EXPORT_SYMBOL_GPL(spi_slave_abort);

static int match_true(struct device *dev, void *data)
{
	return 1;
}

static ssize_t spi_slave_show(struct device *dev,
			      struct device_attribute *attr, char *buf)
{
	struct spi_master *ctlr = container_of(dev, struct spi_master, dev);
	struct device *child;

	child = device_find_child(&ctlr->dev, NULL, match_true);
	return sprintf(buf, "%s\n",
		       child ? to_spi_device(child)->modalias : NULL);
}

static ssize_t spi_slave_store(struct device *dev,
			       struct device_attribute *attr, const char *buf,
			       size_t count)
{
	struct spi_master *ctlr = container_of(dev, struct spi_master, dev);
	struct spi_device *spi;
	struct device *child;
	char name[32];
	int rc;

	rc = sscanf(buf, "%31s", name);
	if (rc != 1 || !name[0])
		return -EINVAL;

	child = device_find_child(&ctlr->dev, NULL, match_true);
	if (child) {
		/* Remove registered slave */
		device_unregister(child);
		put_device(child);
	}

	if (strcmp(name, "(null)")) {
		/* Register new slave */
		spi = spi_alloc_device(ctlr);
		if (!spi)
			return -ENOMEM;

		strlcpy(spi->modalias, name, sizeof(spi->modalias));

		rc = spi_add_device(spi);
		if (rc) {
			spi_dev_put(spi);
			return rc;
		}
	}

	return count;
}

static DEVICE_ATTR(slave, 0644, spi_slave_show, spi_slave_store);

static struct attribute *spi_slave_attrs[] = {
	&dev_attr_slave.attr,
	NULL,
};

static const struct attribute_group spi_slave_group = {
	.attrs = spi_slave_attrs,
};

static const struct attribute_group *spi_slave_groups[] = {
	&spi_master_statistics_group,
	&spi_slave_group,
	NULL,
};

static struct class spi_slave_class = {
	.name		= "spi_slave",
	.owner		= THIS_MODULE,
	.dev_release	= spi_master_release,
	.dev_groups	= spi_slave_groups,
};
#else
extern struct class spi_slave_class;	/* dummy */
#endif


/**
/**
 * spi_alloc_master - allocate SPI master controller
 * __spi_alloc_controller - allocate an SPI master or slave controller
 * @dev: the controller, possibly using the platform_bus
 * @dev: the controller, possibly using the platform_bus
 * @size: how much zeroed driver-private data to allocate; the pointer to this
 * @size: how much zeroed driver-private data to allocate; the pointer to this
 *	memory is in the driver_data field of the returned device,
 *	memory is in the driver_data field of the returned device,
 *	accessible with spi_master_get_devdata().
 *	accessible with spi_master_get_devdata().
 * @slave: flag indicating whether to allocate an SPI master (false) or SPI
 *	slave (true) controller
 * Context: can sleep
 * Context: can sleep
 *
 *
 * This call is used only by SPI master controller drivers, which are the
 * This call is used only by SPI controller drivers, which are the
 * only ones directly touching chip registers.  It's how they allocate
 * only ones directly touching chip registers.  It's how they allocate
 * an spi_master structure, prior to calling spi_register_master().
 * an spi_master structure, prior to calling spi_register_master().
 *
 *
 * This must be called from context that can sleep.
 * This must be called from context that can sleep.
 *
 *
 * The caller is responsible for assigning the bus number and initializing
 * The caller is responsible for assigning the bus number and initializing the
 * the master's methods before calling spi_register_master(); and (after errors
 * controller's methods before calling spi_register_master(); and (after errors
 * adding the device) calling spi_master_put() to prevent a memory leak.
 * adding the device) calling spi_master_put() to prevent a memory leak.
 *
 *
 * Return: the SPI master structure on success, else NULL.
 * Return: the SPI controller structure on success, else NULL.
 */
 */
struct spi_master *spi_alloc_master(struct device *dev, unsigned size)
struct spi_master *__spi_alloc_controller(struct device *dev,
					  unsigned int size, bool slave)
{
{
	struct spi_master	*master;
	struct spi_master	*master;


@@ -1716,13 +1826,17 @@ struct spi_master *spi_alloc_master(struct device *dev, unsigned size)
	device_initialize(&master->dev);
	device_initialize(&master->dev);
	master->bus_num = -1;
	master->bus_num = -1;
	master->num_chipselect = 1;
	master->num_chipselect = 1;
	master->slave = slave;
	if (IS_ENABLED(CONFIG_SPI_SLAVE) && slave)
		master->dev.class = &spi_slave_class;
	else
		master->dev.class = &spi_master_class;
		master->dev.class = &spi_master_class;
	master->dev.parent = dev;
	master->dev.parent = dev;
	spi_master_set_devdata(master, &master[1]);
	spi_master_set_devdata(master, &master[1]);


	return master;
	return master;
}
}
EXPORT_SYMBOL_GPL(spi_alloc_master);
EXPORT_SYMBOL_GPL(__spi_alloc_controller);


#ifdef CONFIG_OF
#ifdef CONFIG_OF
static int of_spi_register_master(struct spi_master *master)
static int of_spi_register_master(struct spi_master *master)
@@ -1798,9 +1912,11 @@ int spi_register_master(struct spi_master *master)
	if (!dev)
	if (!dev)
		return -ENODEV;
		return -ENODEV;


	if (!spi_controller_is_slave(master)) {
		status = of_spi_register_master(master);
		status = of_spi_register_master(master);
		if (status)
		if (status)
			return status;
			return status;
	}


	/* even if it's just one always-selected device, there must
	/* even if it's just one always-selected device, there must
	 * be at least one chipselect
	 * be at least one chipselect
@@ -1836,8 +1952,9 @@ int spi_register_master(struct spi_master *master)
	status = device_add(&master->dev);
	status = device_add(&master->dev);
	if (status < 0)
	if (status < 0)
		goto done;
		goto done;
	dev_dbg(dev, "registered master %s%s\n", dev_name(&master->dev),
	dev_dbg(dev, "registered %s %s%s\n",
			dynamic ? " (dynamic)" : "");
			spi_controller_is_slave(master) ? "slave" : "master",
			dev_name(&master->dev), dynamic ? " (dynamic)" : "");


	/* If we're using a queued driver, start the queue */
	/* If we're using a queued driver, start the queue */
	if (master->transfer)
	if (master->transfer)
@@ -2625,6 +2742,9 @@ static struct spi_master *of_find_spi_master_by_node(struct device_node *node)


	dev = class_find_device(&spi_master_class, NULL, node,
	dev = class_find_device(&spi_master_class, NULL, node,
				__spi_of_master_match);
				__spi_of_master_match);
	if (!dev && IS_ENABLED(CONFIG_SPI_SLAVE))
		dev = class_find_device(&spi_slave_class, NULL, node,
					__spi_of_master_match);
	if (!dev)
	if (!dev)
		return NULL;
		return NULL;


@@ -2697,11 +2817,19 @@ static int __init spi_init(void)
	if (status < 0)
	if (status < 0)
		goto err2;
		goto err2;


	if (IS_ENABLED(CONFIG_SPI_SLAVE)) {
		status = class_register(&spi_slave_class);
		if (status < 0)
			goto err3;
	}

	if (IS_ENABLED(CONFIG_OF_DYNAMIC))
	if (IS_ENABLED(CONFIG_OF_DYNAMIC))
		WARN_ON(of_reconfig_notifier_register(&spi_of_notifier));
		WARN_ON(of_reconfig_notifier_register(&spi_of_notifier));


	return 0;
	return 0;


err3:
	class_unregister(&spi_master_class);
err2:
err2:
	bus_unregister(&spi_bus_type);
	bus_unregister(&spi_bus_type);
err1:
err1:
+31 −4
Original line number Original line Diff line number Diff line
@@ -27,8 +27,8 @@ struct spi_master;
struct spi_transfer;
struct spi_transfer;


/*
/*
 * INTERFACES between SPI master-side drivers and SPI infrastructure.
 * INTERFACES between SPI master-side drivers and SPI slave protocol handlers,
 * (There's no SPI slave support for Linux yet...)
 * and SPI infrastructure.
 */
 */
extern struct bus_type spi_bus_type;
extern struct bus_type spi_bus_type;


@@ -303,6 +303,7 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
 * @min_speed_hz: Lowest supported transfer speed
 * @min_speed_hz: Lowest supported transfer speed
 * @max_speed_hz: Highest supported transfer speed
 * @max_speed_hz: Highest supported transfer speed
 * @flags: other constraints relevant to this driver
 * @flags: other constraints relevant to this driver
 * @slave: indicates that this is an SPI slave controller
 * @bus_lock_spinlock: spinlock for SPI bus locking
 * @bus_lock_spinlock: spinlock for SPI bus locking
 * @bus_lock_mutex: mutex for SPI bus locking
 * @bus_lock_mutex: mutex for SPI bus locking
 * @bus_lock_flag: indicates that the SPI bus is locked for exclusive use
 * @bus_lock_flag: indicates that the SPI bus is locked for exclusive use
@@ -361,6 +362,7 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
 * @handle_err: the subsystem calls the driver to handle an error that occurs
 * @handle_err: the subsystem calls the driver to handle an error that occurs
 *		in the generic implementation of transfer_one_message().
 *		in the generic implementation of transfer_one_message().
 * @unprepare_message: undo any work done by prepare_message().
 * @unprepare_message: undo any work done by prepare_message().
 * @slave_abort: abort the ongoing transfer request on an SPI slave controller
 * @cs_gpios: Array of GPIOs to use as chip select lines; one per CS
 * @cs_gpios: Array of GPIOs to use as chip select lines; one per CS
 *	number. Any individual value may be -ENOENT for CS lines that
 *	number. Any individual value may be -ENOENT for CS lines that
 *	are not GPIOs (driven by the SPI controller itself).
 *	are not GPIOs (driven by the SPI controller itself).
@@ -425,6 +427,9 @@ struct spi_master {
#define SPI_MASTER_MUST_RX      BIT(3)		/* requires rx */
#define SPI_MASTER_MUST_RX      BIT(3)		/* requires rx */
#define SPI_MASTER_MUST_TX      BIT(4)		/* requires tx */
#define SPI_MASTER_MUST_TX      BIT(4)		/* requires tx */


	/* flag indicating this is an SPI slave controller */
	bool			slave;

	/* lock and mutex for SPI bus locking */
	/* lock and mutex for SPI bus locking */
	spinlock_t		bus_lock_spinlock;
	spinlock_t		bus_lock_spinlock;
	struct mutex		bus_lock_mutex;
	struct mutex		bus_lock_mutex;
@@ -507,6 +512,7 @@ struct spi_master {
			       struct spi_message *message);
			       struct spi_message *message);
	int (*unprepare_message)(struct spi_master *master,
	int (*unprepare_message)(struct spi_master *master,
				 struct spi_message *message);
				 struct spi_message *message);
	int (*slave_abort)(struct spi_master *spi);


	/*
	/*
	 * These hooks are for drivers that use a generic implementation
	 * These hooks are for drivers that use a generic implementation
@@ -556,6 +562,11 @@ static inline void spi_master_put(struct spi_master *master)
		put_device(&master->dev);
		put_device(&master->dev);
}
}


static inline bool spi_controller_is_slave(struct spi_master *ctlr)
{
	return IS_ENABLED(CONFIG_SPI_SLAVE) && ctlr->slave;
}

/* PM calls that need to be issued by the driver */
/* PM calls that need to be issued by the driver */
extern int spi_master_suspend(struct spi_master *master);
extern int spi_master_suspend(struct spi_master *master);
extern int spi_master_resume(struct spi_master *master);
extern int spi_master_resume(struct spi_master *master);
@@ -566,8 +577,23 @@ extern void spi_finalize_current_message(struct spi_master *master);
extern void spi_finalize_current_transfer(struct spi_master *master);
extern void spi_finalize_current_transfer(struct spi_master *master);


/* the spi driver core manages memory for the spi_master classdev */
/* the spi driver core manages memory for the spi_master classdev */
extern struct spi_master *
extern struct spi_master *__spi_alloc_controller(struct device *host,
spi_alloc_master(struct device *host, unsigned size);
						 unsigned int size, bool slave);

static inline struct spi_master *spi_alloc_master(struct device *host,
						  unsigned int size)
{
	return __spi_alloc_controller(host, size, false);
}

static inline struct spi_master *spi_alloc_slave(struct device *host,
						 unsigned int size)
{
	if (!IS_ENABLED(CONFIG_SPI_SLAVE))
		return NULL;

	return __spi_alloc_controller(host, size, true);
}


extern int spi_register_master(struct spi_master *master);
extern int spi_register_master(struct spi_master *master);
extern int devm_spi_register_master(struct device *dev,
extern int devm_spi_register_master(struct device *dev,
@@ -831,6 +857,7 @@ extern int spi_setup(struct spi_device *spi);
extern int spi_async(struct spi_device *spi, struct spi_message *message);
extern int spi_async(struct spi_device *spi, struct spi_message *message);
extern int spi_async_locked(struct spi_device *spi,
extern int spi_async_locked(struct spi_device *spi,
			    struct spi_message *message);
			    struct spi_message *message);
extern int spi_slave_abort(struct spi_device *spi);


/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/