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

📄 spi-summary

📁 linux 内核源代码
💻
📖 第 1 页 / 共 2 页
字号:
		.irq		= GPIO_IRQ(31),		.max_speed_hz	= 120000 /* max sample rate at 3V */ * 16,		.bus_num	= 1,		.chip_select	= 0,	},	};Again, notice how board-specific information is provided; each chip may needseveral types.  This example shows generic constraints like the fastest SPIclock to allow (a function of board voltage in this case) or how an IRQ pinis wired, plus chip-specific constraints like an important delay that'schanged by the capacitance at one pin.(There's also "controller_data", information that may be useful to thecontroller driver.  An example would be peripheral-specific DMA tuningdata or chipselect callbacks.  This is stored in spi_device later.)The board_info should provide enough information to let the system workwithout the chip's driver being loaded.  The most troublesome aspect ofthat is likely the SPI_CS_HIGH bit in the spi_device.mode field, sincesharing a bus with a device that interprets chipselect "backwards" isnot possible until the infrastructure knows how to deselect it.Then your board initialization code would register that table with the SPIinfrastructure, so that it's available later when the SPI master controllerdriver is registered:	spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));Like with other static board-specific setup, you won't unregister those.The widely used "card" style computers bundle memory, cpu, and little elseonto a card that's maybe just thirty square centimeters.  On such systems,your arch/.../mach-.../board-*.c file would primarily provide informationabout the devices on the mainboard into which such a card is plugged.  Thatcertainly includes SPI devices hooked up through the card connectors!NON-STATIC CONFIGURATIONSDeveloper boards often play by different rules than product boards, and oneexample is the potential need to hotplug SPI devices and/or controllers.For those cases you might need to use spi_busnum_to_master() to lookup the spi bus master, and will likely need spi_new_device() to provide theboard info based on the board that was hotplugged.  Of course, you'd latercall at least spi_unregister_device() when that board is removed.When Linux includes support for MMC/SD/SDIO/DataFlash cards through SPI, thoseconfigurations will also be dynamic.  Fortunately, such devices all supportbasic device identification probes, so they should hotplug normally.How do I write an "SPI Protocol Driver"?----------------------------------------Most SPI drivers are currently kernel drivers, but there's also supportfor userspace drivers.  Here we talk only about kernel drivers.SPI protocol drivers somewhat resemble platform device drivers:	static struct spi_driver CHIP_driver = {		.driver = {			.name		= "CHIP",			.owner		= THIS_MODULE,		},		.probe		= CHIP_probe,		.remove		= __devexit_p(CHIP_remove),		.suspend	= CHIP_suspend,		.resume		= CHIP_resume,	};The driver core will autmatically attempt to bind this driver to any SPIdevice whose board_info gave a modalias of "CHIP".  Your probe() codemight look like this unless you're creating a device which is managinga bus (appearing under /sys/class/spi_master).	static int __devinit CHIP_probe(struct spi_device *spi)	{		struct CHIP			*chip;		struct CHIP_platform_data	*pdata;		/* assuming the driver requires board-specific data: */		pdata = &spi->dev.platform_data;		if (!pdata)			return -ENODEV;		/* get memory for driver's per-chip state */		chip = kzalloc(sizeof *chip, GFP_KERNEL);		if (!chip)			return -ENOMEM;		spi_set_drvdata(spi, chip);		... etc		return 0;	}As soon as it enters probe(), the driver may issue I/O requests tothe SPI device using "struct spi_message".  When remove() returns,or after probe() fails, the driver guarantees that it won't submitany more such messages.  - An spi_message is a sequence of protocol operations, executed    as one atomic sequence.  SPI driver controls include:      + when bidirectional reads and writes start ... by how its        sequence of spi_transfer requests is arranged;      + optionally defining short delays after transfers ... using        the spi_transfer.delay_usecs setting;      + whether the chipselect becomes inactive after a transfer and        any delay ... by using the spi_transfer.cs_change flag;      + hinting whether the next message is likely to go to this same        device ... using the spi_transfer.cs_change flag on the last	transfer in that atomic group, and potentially saving costs	for chip deselect and select operations.  - Follow standard kernel rules, and provide DMA-safe buffers in    your messages.  That way controller drivers using DMA aren't forced    to make extra copies unless the hardware requires it (e.g. working    around hardware errata that force the use of bounce buffering).    If standard dma_map_single() handling of these buffers is inappropriate,    you can use spi_message.is_dma_mapped to tell the controller driver    that you've already provided the relevant DMA addresses.  - The basic I/O primitive is spi_async().  Async requests may be    issued in any context (irq handler, task, etc) and completion    is reported using a callback provided with the message.    After any detected error, the chip is deselected and processing    of that spi_message is aborted.  - There are also synchronous wrappers like spi_sync(), and wrappers    like spi_read(), spi_write(), and spi_write_then_read().  These    may be issued only in contexts that may sleep, and they're all    clean (and small, and "optional") layers over spi_async().  - The spi_write_then_read() call, and convenience wrappers around    it, should only be used with small amounts of data where the    cost of an extra copy may be ignored.  It's designed to support    common RPC-style requests, such as writing an eight bit command    and reading a sixteen bit response -- spi_w8r16() being one its    wrappers, doing exactly that.Some drivers may need to modify spi_device characteristics like thetransfer mode, wordsize, or clock rate.  This is done with spi_setup(),which would normally be called from probe() before the first I/O isdone to the device.  However, that can also be called at any timethat no message is pending for that device.While "spi_device" would be the bottom boundary of the driver, theupper boundaries might include sysfs (especially for sensor readings),the input layer, ALSA, networking, MTD, the character device framework,or other Linux subsystems.Note that there are two types of memory your driver must manage as partof interacting with SPI devices.  - I/O buffers use the usual Linux rules, and must be DMA-safe.    You'd normally allocate them from the heap or free page pool.    Don't use the stack, or anything that's declared "static".  - The spi_message and spi_transfer metadata used to glue those    I/O buffers into a group of protocol transactions.  These can    be allocated anywhere it's convenient, including as part of    other allocate-once driver data structures.  Zero-init these.If you like, spi_message_alloc() and spi_message_free() convenienceroutines are available to allocate and zero-initialize an spi_messagewith several transfers.How do I write an "SPI Master Controller Driver"?-------------------------------------------------An SPI controller will probably be registered on the platform_bus; writea driver to bind to the device, whichever bus is involved.The main task of this type of driver is to provide an "spi_master".Use spi_alloc_master() to allocate the master, and spi_master_get_devdata()to get the driver-private data allocated for that device.	struct spi_master	*master;	struct CONTROLLER	*c;	master = spi_alloc_master(dev, sizeof *c);	if (!master)		return -ENODEV;	c = spi_master_get_devdata(master);The driver will initialize the fields of that spi_master, including thebus number (maybe the same as the platform device ID) and three methodsused to interact with the SPI core and SPI protocol drivers.  It willalso initialize its own internal state.  (See below about bus numberingand those methods.)After you initialize the spi_master, then use spi_register_master() topublish it to the rest of the system.  At that time, device nodes forthe controller and any predeclared spi devices will be made available,and the driver model core will take care of binding them to drivers.If you need to remove your SPI controller driver, spi_unregister_master()will reverse the effect of spi_register_master().BUS NUMBERINGBus numbering is important, since that's how Linux identifies a givenSPI bus (shared SCK, MOSI, MISO).  Valid bus numbers start at zero.  OnSOC systems, the bus numbers should match the numbers defined by the chipmanufacturer.  For example, hardware controller SPI2 would be bus number 2,and spi_board_info for devices connected to it would use that number.If you don't have such hardware-assigned bus number, and for some reasonyou can't just assign them, then provide a negative bus number.  That willthen be replaced by a dynamically assigned number. You'd then need to treatthis as a non-static configuration (see above).SPI MASTER METHODS    master->setup(struct spi_device *spi)	This sets up the device clock rate, SPI mode, and word sizes.	Drivers may change the defaults provided by board_info, and then	call spi_setup(spi) to invoke this routine.  It may sleep.	Unless each SPI slave has its own configuration registers, don't	change them right away ... otherwise drivers could corrupt I/O	that's in progress for other SPI devices.    master->transfer(struct spi_device *spi, struct spi_message *message)    	This must not sleep.  Its responsibility is arrange that the	transfer happens and its complete() callback is issued.  The two	will normally happen later, after other transfers complete, and	if the controller is idle it will need to be kickstarted.    master->cleanup(struct spi_device *spi)	Your controller driver may use spi_device.controller_state to hold	state it dynamically associates with that device.  If you do that,	be sure to provide the cleanup() method to free that state.SPI MESSAGE QUEUEThe bulk of the driver will be managing the I/O queue fed by transfer().That queue could be purely conceptual.  For example, a driver used onlyfor low-frequency sensor acess might be fine using synchronous PIO.But the queue will probably be very real, using message->queue, PIO,often DMA (especially if the root filesystem is in SPI flash), andexecution contexts like IRQ handlers, tasklets, or workqueues (suchas keventd).  Your driver can be as fancy, or as simple, as you need.Such a transfer() method would normally just add the message to aqueue, and then start some asynchronous transfer engine (unless it'salready running).THANKS TO---------Contributors to Linux-SPI discussions include (in alphabetical order,by last name):David BrownellRussell KingDmitry PervushinStephen StreetMark UnderwoodAndrew VictorVitaly Wool

⌨️ 快捷键说明

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