⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spi.c

📁 TI的达芬奇系列dm355使用的spi模块驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
/*-------------------------------------------------------------------------*/static void spi_master_release(struct class_device *cdev){	struct spi_master *master;	master = container_of(cdev, struct spi_master, cdev);	kfree(master);}static struct class spi_master_class = {	.name		= "spi_master",	.release	= spi_master_release,};/** * spi_alloc_master - allocate SPI master controller * @dev: the controller, possibly using the platform_bus * @size: how much driver-private data to preallocate; the pointer to this * 	memory is in the class_data field of the returned class_device, *	accessible with spi_master_get_devdata(). * * This call is used only by SPI master controller drivers, which are the * only ones directly touching chip registers.  It's how they allocate * an spi_master structure, prior to calling spi_add_master(). * * This must be called from context that can sleep.  It returns the SPI * master structure on success, else NULL. * * The caller is responsible for assigning the bus number and initializing * the master's methods before calling spi_add_master(); and (after errors * adding the device) calling spi_master_put() to prevent a memory leak. */struct spi_master * __init_or_modulespi_alloc_master(struct device *dev, unsigned size){	struct spi_master	*master;	if (!dev)		return NULL;	master = kzalloc(size + sizeof *master, SLAB_KERNEL);	if (!master)		return NULL;	class_device_initialize(&master->cdev);	master->cdev.class = &spi_master_class;	master->cdev.dev = get_device(dev);	spi_master_set_devdata(master, &master[1]);	return master;}EXPORT_SYMBOL_GPL(spi_alloc_master);/** * spi_register_master - register SPI master controller * @master: initialized master, originally from spi_alloc_master() * * SPI master controllers connect to their drivers using some non-SPI bus, * such as the platform bus.  The final stage of probe() in that code * includes calling spi_register_master() to hook up to this SPI bus glue. * * SPI controllers use board specific (often SOC specific) bus numbers, * and board-specific addressing for SPI devices combines those numbers * with chip select numbers.  Since SPI does not directly support dynamic * device identification, boards need configuration tables telling which * chip is at which address. * * This must be called from context that can sleep.  It returns zero on * success, else a negative error code (dropping the master's refcount). * After a successful return, the caller is responsible for calling * spi_unregister_master(). */int __init_or_modulespi_register_master(struct spi_master *master){	static atomic_t		dyn_bus_id = ATOMIC_INIT(0);	struct device		*dev = master->cdev.dev;	int			status = -ENODEV;	int			dynamic = 0;	if (!dev)		return -ENODEV;	/* convention:  dynamically assigned bus IDs count down from the max */	if (master->bus_num == 0) {		master->bus_num = atomic_dec_return(&dyn_bus_id);		dynamic = 1;	}	/* register the device, then userspace will see it.	 * registration fails if the bus ID is in use.	 */	snprintf(master->cdev.class_id, sizeof master->cdev.class_id,		"spi%u", master->bus_num);	status = class_device_add(&master->cdev);	if (status < 0)		goto done;	dev_dbg(dev, "registered master %s%s\n", master->cdev.class_id,			dynamic ? " (dynamic)" : "");	/* populate children from any spi device tables */	scan_boardinfo(master);	status = 0;done:	return status;}EXPORT_SYMBOL_GPL(spi_register_master);static int __unregister(struct device *dev, void *unused){	/* note: before about 2.6.14-rc1 this would corrupt memory: */	spi_unregister_device(to_spi_device(dev));	return 0;}/** * spi_unregister_master - unregister SPI master controller * @master: the master being unregistered * * This call is used only by SPI master controller drivers, which are the * only ones directly touching chip registers. * * This must be called from context that can sleep. */void spi_unregister_master(struct spi_master *master){	(void) device_for_each_child(master->cdev.dev, NULL, __unregister);	class_device_unregister(&master->cdev);	master->cdev.dev = NULL;}EXPORT_SYMBOL_GPL(spi_unregister_master);/** * spi_busnum_to_master - look up master associated with bus_num * @bus_num: the master's bus number * * This call may be used with devices that are registered after * arch init time.  It returns a refcounted pointer to the relevant * spi_master (which the caller must release), or NULL if there is * no such master registered. */struct spi_master *spi_busnum_to_master(u16 bus_num){	if (bus_num) {		char			name[8];		struct kobject		*bus;		snprintf(name, sizeof name, "spi%u", bus_num);		bus = kset_find_obj(&spi_master_class.subsys.kset, name);		if (bus)			return container_of(bus, struct spi_master, cdev.kobj);	}	return NULL;}EXPORT_SYMBOL_GPL(spi_busnum_to_master);/*-------------------------------------------------------------------------*/static void spi_complete(void *arg){	complete(arg);}/** * spi_sync - blocking/synchronous SPI data transfers * @spi: device with which data will be exchanged * @message: describes the data transfers * * This call may only be used from a context that may sleep.  The sleep * is non-interruptible, and has no timeout.  Low-overhead controller * drivers may DMA directly into and out of the message buffers. * * Note that the SPI device's chip select is active during the message, * and then is normally disabled between messages.  Drivers for some * frequently-used devices may want to minimize costs of selecting a chip, * by leaving it selected in anticipation that the next message will go * to the same chip.  (That may increase power usage.) * * Also, the caller is guaranteeing that the memory associated with the * message will not be freed before this call returns. * * The return value is a negative error code if the message could not be * submitted, else zero.  When the value is zero, then message->status is * also defined:  it's the completion code for the transfer, either zero * or a negative error code from the controller driver. */int spi_sync(struct spi_device *spi, struct spi_message *message){	DECLARE_COMPLETION(done);	int status;	message->complete = spi_complete;	message->context = &done;	status = spi_async(spi, message);	if (status == 0)		wait_for_completion(&done);	message->context = NULL;	return status;}EXPORT_SYMBOL_GPL(spi_sync);#define	SPI_BUFSIZ	(SMP_CACHE_BYTES)static u8	*buf;/** * spi_write_then_read - SPI synchronous write followed by read * @spi: device with which data will be exchanged * @txbuf: data to be written (need not be dma-safe) * @n_tx: size of txbuf, in bytes * @rxbuf: buffer into which data will be read * @n_rx: size of rxbuf, in bytes (need not be dma-safe) * * This performs a half duplex MicroWire style transaction with the * device, sending txbuf and then reading rxbuf.  The return value * is zero for success, else a negative errno status code. * This call may only be used from a context that may sleep. * * Parameters to this routine are always copied using a small buffer; * performance-sensitive or bulk transfer code should instead use * spi_{async,sync}() calls with dma-safe buffers. */int spi_write_then_read(struct spi_device *spi,		const u8 *txbuf, unsigned n_tx,		u8 *rxbuf, unsigned n_rx){	static DECLARE_MUTEX(lock);	int			status;	struct spi_message	message;	struct spi_transfer	x[2];	u8			*local_buf;	/* Use preallocated DMA-safe buffer.  We can't avoid copying here,	 * (as a pure convenience thing), but we can keep heap costs	 * out of the hot path ...	 */	if ((n_tx + n_rx) > SPI_BUFSIZ)		return -EINVAL;	spi_message_init(&message);	memset(x, 0, sizeof x);	if (n_tx) {		x[0].len = n_tx;		spi_message_add_tail(&x[0], &message);	}	if (n_rx) {		x[1].len = n_rx;		spi_message_add_tail(&x[1], &message);	}	/* ... unless someone else is using the pre-allocated buffer */	if (down_trylock(&lock)) {		local_buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL);		if (!local_buf)			return -ENOMEM;	} else		local_buf = buf;	memcpy(local_buf, txbuf, n_tx);	x[0].tx_buf = local_buf;	x[1].rx_buf = local_buf + n_tx;	/* do the i/o */	status = spi_sync(spi, &message);	if (status == 0) {		memcpy(rxbuf, x[1].rx_buf, n_rx);		status = message.status;	}	if (x[0].tx_buf == buf)		up(&lock);	else		kfree(local_buf);	return status;}EXPORT_SYMBOL_GPL(spi_write_then_read);/*-------------------------------------------------------------------------*/static int __init spi_init(void){	int	status;	buf = kmalloc(SPI_BUFSIZ, SLAB_KERNEL);	if (!buf) {		status = -ENOMEM;		goto err0;	}	status = bus_register(&spi_bus_type);	if (status < 0)		goto err1;	status = class_register(&spi_master_class);	if (status < 0)		goto err2;	return 0;err2:	bus_unregister(&spi_bus_type);err1:	kfree(buf);	buf = NULL;err0:	return status;}/* board_info is normally registered in arch_initcall(), * but even essential drivers wait till later * * REVISIT only boardinfo really needs static linking. the rest (device and * driver registration) _could_ be dynamically linked (modular) ... costs * include needing to have boardinfo data structures be much more public. */subsys_initcall(spi_init);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -