diff --git a/_posts/2023-10-09-lwip-tcp.markdown b/_posts/2023-10-09-lwip-tcp.markdown new file mode 100644 index 0000000..30a239b --- /dev/null +++ b/_posts/2023-10-09-lwip-tcp.markdown @@ -0,0 +1,58 @@ +--- +layout: post +title: "LwIP TCP API" +date: 2023-10-09 00:00:00 -0400 +--- + +# Minimal LwIP TCP API (as used on a Raspberry PI pico-w) + +### tcp_new() +``` +struct tcp_pcb* tcp_new ( void ) +struct tcp_pcb* tcp_new_ip_type ( u8_t type ) +``` +Creates a new TCP protocol control block but doesn't place it on any of the TCP PCB lists until binding using tcp_bind(). + +Parameters +- IPADDR_TYPE_ANY| +Returns +- a new tcp_pcb that initially is in state CLOSED + +### tcp_bind() + +### tcp_connect() +``` +err_t tcp_connect ( struct tcp_pcb * pcb, const ip_addr_t * ipaddr, u16_t port, tcp_connected_fn connected) +``` +Parameters +- pcb the tcp_pcb used to establish the connection +- ipaddr the remote ip address to connect to +- port the remote tcp port to connect to +- connected callback function to call when connected (on error, the err calback will be called) +Returns +- ERR_VAL if invalid arguments are given ERR_OK if connect request has been sent other err_t values if connect request couldn't be sent + +### tcp_write() +``` +err_t tcp_write ( struct tcp_pcb * pcb, const void * arg, u16_t len, u8_t apiflags) +``` +Parameters +- pcb Protocol control block for the TCP connection to enqueue data for. +- arg Pointer to the data to be enqueued for sending. +- len Data length in bytes +- apiflags combination of following flags : + - TCP_WRITE_FLAG_COPY (0x01) data will be copied into memory belonging to the stack + - TCP_WRITE_FLAG_MORE (0x02) for TCP connection, PSH flag will not be set on last segment sent, +Returns +- ERR_OK if enqueued, another err_t on error + +### tcp_output() +``` +err_t tcp_output ( struct tcp_pcb * pcb ) +``` +Parameters +- pcb Protocol control block for the TCP connection to send data +Returns +- ERR_OK if data has been sent or nothing to send another err_t on error + + diff --git a/devicemodel.c b/devicemodel.c new file mode 100644 index 0000000..3441c54 --- /dev/null +++ b/devicemodel.c @@ -0,0 +1,485 @@ + + +device is usually embedded in more specific devices. + +struct device +- parent device +- kobj +- device_type +- bus +- device_driver +- platform_data /* Platform specific data, device core doesn't touch it */ +- driver_data /* Driver data, set and get with dev_set_drvdata/dev_get_drvdata */ +- dev_pin_info /* pinctrl *pins ? */ +- of_node +- knode_class /* The node used to add the device to the class list.*/ + + +So spi_device will include struct device and its members will be spi.dev.platform_data etc. +platform_device also includes struct device + +ssc_device points to platform_device: +ssc_device->pdev + +Therefore ssc_devices dev data is inheritied from platform_device.dev. + + +struct driver +- name +- bus_type +- ops + +A driver can be associated with a device, a bus or a class + + + + + + + +/** + * struct device - The basic device structure + * @parent: The device's "parent" device, the device to which it is attached. + * In most cases, a parent device is some sort of bus or host + * controller. If parent is NULL, the device, is a top-level device, + * which is not usually what you want. + * @p: Holds the private data of the driver core portions of the device. + * See the comment of the struct device_private for detail. + * @kobj: A top-level, abstract class from which other classes are derived. + * @init_name: Initial name of the device. + * @type: The type of device. + * This identifies the device type and carries type-specific + * information. + * @mutex: Mutex to synchronize calls to its driver. + * @bus: Type of bus device is on. + * @driver: Which driver has allocated this + * @platform_data: Platform data specific to the device. + * Example: For devices on custom boards, as typical of embedded + * and SOC based hardware, Linux often uses platform_data to point + * to board-specific structures describing devices and how they + * are wired. That can include what ports are available, chip + * variants, which GPIO pins act in what additional roles, and so + * on. This shrinks the "Board Support Packages" (BSPs) and + * minimizes board-specific #ifdefs in drivers. + * @driver_data: Private pointer for driver specific info. + * @links: Links to suppliers and consumers of this device. + * @power: For device power management. + * See Documentation/driver-api/pm/devices.rst for details. + * @pm_domain: Provide callbacks that are executed during system suspend, + * hibernation, system resume and during runtime PM transitions + * along with subsystem-level and driver-level callbacks. + * @em_pd: device's energy model performance domain + * @pins: For device pin management. + * See Documentation/driver-api/pin-control.rst for details. + * @msi: MSI related data + * @numa_node: NUMA node this device is close to. + * @dma_ops: DMA mapping operations for this device. + * @dma_mask: Dma mask (if dma'ble device). + * @coherent_dma_mask: Like dma_mask, but for alloc_coherent mapping as not all + * hardware supports 64-bit addresses for consistent allocations + * such descriptors. + * @bus_dma_limit: Limit of an upstream bridge or bus which imposes a smaller + * DMA limit than the device itself supports. + * @dma_range_map: map for DMA memory ranges relative to that of RAM + * @dma_parms: A low level driver may set these to teach IOMMU code about + * segment limitations. + * @dma_pools: Dma pools (if dma'ble device). + * @dma_mem: Internal for coherent mem override. + * @cma_area: Contiguous memory area for dma allocations + * @dma_io_tlb_mem: Pointer to the swiotlb pool used. Not for driver use. + * @archdata: For arch-specific additions. + * @of_node: Associated device tree node. + * @fwnode: Associated device node supplied by platform firmware. + * @devt: For creating the sysfs "dev". + * @id: device instance + * @devres_lock: Spinlock to protect the resource of the device. + * @devres_head: The resources list of the device. + * @knode_class: The node used to add the device to the class list. + * @class: The class of the device. + * @groups: Optional attribute groups. + * @release: Callback to free the device after all references have + * gone away. This should be set by the allocator of the + * device (i.e. the bus driver that discovered the device). + * @iommu_group: IOMMU group the device belongs to. + * @iommu: Per device generic IOMMU runtime data + * @physical_location: Describes physical location of the device connection + * point in the system housing. + * @removable: Whether the device can be removed from the system. This + * should be set by the subsystem / bus driver that discovered + * the device. + * + * @offline_disabled: If set, the device is permanently online. + * @offline: Set after successful invocation of bus type's .offline(). + * @of_node_reused: Set if the device-tree node is shared with an ancestor + * device. + * @state_synced: The hardware state of this device has been synced to match + * the software state of this device by calling the driver/bus + * sync_state() callback. + * @can_match: The device has matched with a driver at least once or it is in + * a bus (like AMBA) which can't check for matching drivers until + * other devices probe successfully. + * @dma_coherent: this particular device is dma coherent, even if the + * architecture supports non-coherent devices. + * @dma_ops_bypass: If set to %true then the dma_ops are bypassed for the + * streaming DMA operations (->map_* / ->unmap_* / ->sync_*), + * and optionall (if the coherent mask is large enough) also + * for dma allocations. This flag is managed by the dma ops + * instance from ->dma_supported. + * + * At the lowest level, every device in a Linux system is represented by an + * instance of struct device. The device structure contains the information + * that the device model core needs to model the system. Most subsystems, + * however, track additional information about the devices they host. As a + * result, it is rare for devices to be represented by bare device structures; + * instead, that structure, like kobject structures, is usually embedded within + * a higher-level representation of the device. + */ +struct device { + struct kobject kobj; + struct device *parent; + + struct device_private *p; + + const char *init_name; /* initial name of the device */ + const struct device_type *type; + + const struct bus_type *bus; /* type of bus device is on */ + struct device_driver *driver; /* which driver has allocated this + device */ + void *platform_data; /* Platform specific data, device + core doesn't touch it */ + void *driver_data; /* Driver data, set and get with + dev_set_drvdata/dev_get_drvdata */ + struct mutex mutex; /* mutex to synchronize calls to + * its driver. + */ + + struct dev_links_info links; + struct dev_pm_info power; + struct dev_pm_domain *pm_domain; + +#ifdef CONFIG_ENERGY_MODEL + struct em_perf_domain *em_pd; +#endif + +#ifdef CONFIG_PINCTRL + struct dev_pin_info *pins; +#endif + struct dev_msi_info msi; +#ifdef CONFIG_DMA_OPS + const struct dma_map_ops *dma_ops; +#endif + u64 *dma_mask; /* dma mask (if dma'able device) */ + u64 coherent_dma_mask;/* Like dma_mask, but for + alloc_coherent mappings as + not all hardware supports + 64 bit addresses for consistent + allocations such descriptors. */ + u64 bus_dma_limit; /* upstream dma constraint */ + const struct bus_dma_region *dma_range_map; + + struct device_dma_parameters *dma_parms; + + struct list_head dma_pools; /* dma pools (if dma'ble) */ + +#ifdef CONFIG_DMA_DECLARE_COHERENT + struct dma_coherent_mem *dma_mem; /* internal for coherent mem + override */ +#endif +#ifdef CONFIG_DMA_CMA + struct cma *cma_area; /* contiguous memory area for dma + allocations */ +#endif +#ifdef CONFIG_SWIOTLB + struct io_tlb_mem *dma_io_tlb_mem; +#endif + /* arch specific additions */ + struct dev_archdata archdata; + + struct device_node *of_node; /* associated device tree node */ + struct fwnode_handle *fwnode; /* firmware device node */ + +#ifdef CONFIG_NUMA + int numa_node; /* NUMA node this device is close to */ +#endif + dev_t devt; /* dev_t, creates the sysfs "dev" */ + u32 id; /* device instance */ + + spinlock_t devres_lock; + struct list_head devres_head; + + const struct class *class; + const struct attribute_group **groups; /* optional groups */ + + void (*release)(struct device *dev); + struct iommu_group *iommu_group; + struct dev_iommu *iommu; + + struct device_physical_location *physical_location; + + enum device_removable removable; + + bool offline_disabled:1; + bool offline:1; + bool of_node_reused:1; + bool state_synced:1; + bool can_match:1; +#if defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_DEVICE) || \ + defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU) || \ + defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU_ALL) + bool dma_coherent:1; +#endif +#ifdef CONFIG_DMA_OPS_BYPASS + bool dma_ops_bypass : 1; +#endif +}; +================================================== +/* + * The type of device, "struct device" is embedded in. A class + * or bus can contain devices of different types + * like "partitions" and "disks", "mouse" and "event". + * This identifies the device type and carries type-specific + * information, equivalent to the kobj_type of a kobject. + * If "name" is specified, the uevent will contain it in + * the DEVTYPE variable. + */ +struct device_type { + const char *name; + const struct attribute_group **groups; + int (*uevent)(const struct device *dev, struct kobj_uevent_env *env); + char *(*devnode)(const struct device *dev, umode_t *mode, + kuid_t *uid, kgid_t *gid); + void (*release)(struct device *dev); + + const struct dev_pm_ops *pm; +}; + +=================== + /* + * A class is a higher-level view of a device that abstracts out low-level + * implementation details. Drivers may see a SCSI disk or an ATA disk, but, + * at the class level, they are all simply disks. Classes allow user space + * to work with devices based on what they do, rather than how they are + * connected or how they work. + */ +struct class { + const char *name; + + const struct attribute_group **class_groups; + const struct attribute_group **dev_groups; + + int (*dev_uevent)(const struct device *dev, struct kobj_uevent_env *env); + char *(*devnode)(const struct device *dev, umode_t *mode); + + void (*class_release)(const struct class *class); + void (*dev_release)(struct device *dev); + + int (*shutdown_pre)(struct device *dev); + + const struct kobj_ns_type_operations *ns_type; + const void *(*namespace)(const struct device *dev); + + void (*get_ownership)(const struct device *dev, kuid_t *uid, kgid_t *gid); + + const struct dev_pm_ops *pm; +}; +=================== +/** + * struct device_driver - The basic device driver structure + * @name: Name of the device driver. + * @bus: The bus which the device of this driver belongs to. + * @owner: The module owner. + * @mod_name: Used for built-in modules. + * @suppress_bind_attrs: Disables bind/unbind via sysfs. + * @probe_type: Type of the probe (synchronous or asynchronous) to use. + * @of_match_table: The open firmware table. + * @acpi_match_table: The ACPI match table. + * @probe: Called to query the existence of a specific device, + * whether this driver can work with it, and bind the driver + * to a specific device. + * @sync_state: Called to sync device state to software state after all the + * state tracking consumers linked to this device (present at + * the time of late_initcall) have successfully bound to a + * driver. If the device has no consumers, this function will + * be called at late_initcall_sync level. If the device has + * consumers that are never bound to a driver, this function + * will never get called until they do. + * @remove: Called when the device is removed from the system to + * unbind a device from this driver. + * @shutdown: Called at shut-down time to quiesce the device. + * @suspend: Called to put the device to sleep mode. Usually to a + * low power state. + * @resume: Called to bring a device from sleep mode. + * @groups: Default attributes that get created by the driver core + * automatically. + * @dev_groups: Additional attributes attached to device instance once + * it is bound to the driver. + * @pm: Power management operations of the device which matched + * this driver. + * @coredump: Called when sysfs entry is written to. The device driver + * is expected to call the dev_coredump API resulting in a + * uevent. + * @p: Driver core's private data, no one other than the driver + * core can touch this. + * + * The device driver-model tracks all of the drivers known to the system. + * The main reason for this tracking is to enable the driver core to match + * up drivers with new devices. Once drivers are known objects within the + * system, however, a number of other things become possible. Device drivers + * can export information and configuration variables that are independent + * of any specific device. + */ +struct device_driver { + const char *name; + const struct bus_type *bus; + + struct module *owner; + const char *mod_name; /* used for built-in modules */ + + bool suppress_bind_attrs; /* disables bind/unbind via sysfs */ + enum probe_type probe_type; + + const struct of_device_id *of_match_table; + const struct acpi_device_id *acpi_match_table; + + int (*probe) (struct device *dev); + void (*sync_state)(struct device *dev); + int (*remove) (struct device *dev); + void (*shutdown) (struct device *dev); + int (*suspend) (struct device *dev, pm_message_t state); + int (*resume) (struct device *dev); + const struct attribute_group **groups; + const struct attribute_group **dev_groups; + + const struct dev_pm_ops *pm; + void (*coredump) (struct device *dev); + + struct driver_private *p; +}; +======================================================= + +/** + * struct spi_device - Controller side proxy for an SPI slave device + * @dev: Driver model representation of the device. + * @controller: SPI controller used with the device. + * @master: Copy of controller, for backwards compatibility. + * @max_speed_hz: Maximum clock rate to be used with this chip + * (on this board); may be changed by the device's driver. + * The spi_transfer.speed_hz can override this for each transfer. + * @chip_select: Chipselect, distinguishing chips handled by @controller. + * @mode: The spi mode defines how data is clocked out and in. + * This may be changed by the device's driver. + * The "active low" default for chipselect mode can be overridden + * (by specifying SPI_CS_HIGH) as can the "MSB first" default for + * each word in a transfer (by specifying SPI_LSB_FIRST). + * @bits_per_word: Data transfers involve one or more words; word sizes + * like eight or 12 bits are common. In-memory wordsizes are + * powers of two bytes (e.g. 20 bit samples use 32 bits). + * This may be changed by the device's driver, or left at the + * default (0) indicating protocol words are eight bit bytes. + * The spi_transfer.bits_per_word can override this for each transfer. + * @rt: Make the pump thread real time priority. + * @irq: Negative, or the number passed to request_irq() to receive + * interrupts from this device. + * @controller_state: Controller's runtime state + * @controller_data: Board-specific definitions for controller, such as + * FIFO initialization parameters; from board_info.controller_data + * @modalias: Name of the driver to use with this device, or an alias + * for that name. This appears in the sysfs "modalias" attribute + * for driver coldplugging, and in uevents used for hotplugging + * @driver_override: If the name of a driver is written to this attribute, then + * the device will bind to the named driver and only the named driver. + * Do not set directly, because core frees it; use driver_set_override() to + * set or clear it. + * @cs_gpiod: gpio descriptor of the chipselect line (optional, NULL when + * not using a GPIO line) + * @word_delay: delay to be inserted between consecutive + * words of a transfer + * @cs_setup: delay to be introduced by the controller after CS is asserted + * @cs_hold: delay to be introduced by the controller before CS is deasserted + * @cs_inactive: delay to be introduced by the controller after CS is + * deasserted. If @cs_change_delay is used from @spi_transfer, then the + * two delays will be added up. + * @pcpu_statistics: statistics for the spi_device + * + * A @spi_device is used to interchange data between an SPI slave + * (usually a discrete chip) and CPU memory. + * + * In @dev, the platform_data is used to hold information about this + * device that's meaningful to the device's protocol driver, but not + * to its controller. One example might be an identifier for a chip + * variant with slightly different functionality; another might be + * information about how this particular board wires the chip's pins. + */ +struct spi_device { + struct device dev; + struct spi_controller *controller; + struct spi_controller *master; /* Compatibility layer */ + u32 max_speed_hz; + u8 chip_select; + u8 bits_per_word; + bool rt; +#define SPI_NO_TX BIT(31) /* No transmit wire */ +#define SPI_NO_RX BIT(30) /* No receive wire */ + /* + * TPM specification defines flow control over SPI. Client device + * can insert a wait state on MISO when address is transmitted by + * controller on MOSI. Detecting the wait state in software is only + * possible for full duplex controllers. For controllers that support + * only half-duplex, the wait state detection needs to be implemented + * in hardware. TPM devices would set this flag when hardware flow + * control is expected from SPI controller. + */ +#define SPI_TPM_HW_FLOW BIT(29) /* TPM HW flow control */ + /* + * All bits defined above should be covered by SPI_MODE_KERNEL_MASK. + * The SPI_MODE_KERNEL_MASK has the SPI_MODE_USER_MASK counterpart, + * which is defined in 'include/uapi/linux/spi/spi.h'. + * The bits defined here are from bit 31 downwards, while in + * SPI_MODE_USER_MASK are from 0 upwards. + * These bits must not overlap. A static assert check should make sure of that. + * If adding extra bits, make sure to decrease the bit index below as well. + */ +#define SPI_MODE_KERNEL_MASK (~(BIT(29) - 1)) + u32 mode; + int irq; + void *controller_state; + void *controller_data; + char modalias[SPI_NAME_SIZE]; + const char *driver_override; + struct gpio_desc *cs_gpiod; /* Chip select gpio desc */ + struct spi_delay word_delay; /* Inter-word delay */ + /* CS delays */ + struct spi_delay cs_setup; + struct spi_delay cs_hold; + struct spi_delay cs_inactive; + + /* The statistics */ + struct spi_statistics __percpu *pcpu_statistics; + + /* + * likely need more hooks for more protocol options affecting how + * the controller talks to each chip, like: + * - memory packing (12 bit samples into low bits, others zeroed) + * - priority + * - chipselect delays + * - ... + */ +}; + +================================================================= + + + + + + + + + + + + + + + diff --git a/platform.c b/platform.c new file mode 100644 index 0000000..3d194b4 --- /dev/null +++ b/platform.c @@ -0,0 +1,54 @@ +====================================== +struct platform_device { + const char *name; + int id; + bool id_auto; + struct device dev; + u64 platform_dma_mask; + struct device_dma_parameters dma_parms; + u32 num_resources; + struct resource *resource; + + const struct platform_device_id *id_entry; + /* + * Driver name to force a match. Do not set directly, because core + * frees it. Use driver_set_override() to set or clear it. + */ + const char *driver_override; + + /* MFD cell pointer */ + struct mfd_cell *mfd_cell; + + /* arch specific additions */ + struct pdev_archdata archdata; +}; +========================================= +struct platform_driver { + int (*probe)(struct platform_device *); + + /* + * Traditionally the remove callback returned an int which however is + * ignored by the driver core. This led to wrong expectations by driver + * authors who thought returning an error code was a valid error + * handling strategy. To convert to a callback returning void, new + * drivers should implement .remove_new() until the conversion it done + * that eventually makes .remove() return void. + */ + int (*remove)(struct platform_device *); + void (*remove_new)(struct platform_device *); + + void (*shutdown)(struct platform_device *); + int (*suspend)(struct platform_device *, pm_message_t state); + int (*resume)(struct platform_device *); + struct device_driver driver; + const struct platform_device_id *id_table; + bool prevent_deferred_probe; + /* + * For most device drivers, no need to care about this flag as long as + * all DMAs are handled through the kernel DMA API. For some special + * ones, for example VFIO drivers, they know how to manage the DMA + * themselves and set this flag so that the IOMMU layer will allow them + * to setup and manage their own I/O address space. + */ + bool driver_managed_dma; +}; \ No newline at end of file diff --git a/spi.c b/spi.c new file mode 100644 index 0000000..55e3d07 --- /dev/null +++ b/spi.c @@ -0,0 +1,109 @@ +/** + * struct spi_device - Controller side proxy for an SPI slave device + * @dev: Driver model representation of the device. + * @controller: SPI controller used with the device. + * @master: Copy of controller, for backwards compatibility. + * @max_speed_hz: Maximum clock rate to be used with this chip + * (on this board); may be changed by the device's driver. + * The spi_transfer.speed_hz can override this for each transfer. + * @chip_select: Chipselect, distinguishing chips handled by @controller. + * @mode: The spi mode defines how data is clocked out and in. + * This may be changed by the device's driver. + * The "active low" default for chipselect mode can be overridden + * (by specifying SPI_CS_HIGH) as can the "MSB first" default for + * each word in a transfer (by specifying SPI_LSB_FIRST). + * @bits_per_word: Data transfers involve one or more words; word sizes + * like eight or 12 bits are common. In-memory wordsizes are + * powers of two bytes (e.g. 20 bit samples use 32 bits). + * This may be changed by the device's driver, or left at the + * default (0) indicating protocol words are eight bit bytes. + * The spi_transfer.bits_per_word can override this for each transfer. + * @rt: Make the pump thread real time priority. + * @irq: Negative, or the number passed to request_irq() to receive + * interrupts from this device. + * @controller_state: Controller's runtime state + * @controller_data: Board-specific definitions for controller, such as + * FIFO initialization parameters; from board_info.controller_data + * @modalias: Name of the driver to use with this device, or an alias + * for that name. This appears in the sysfs "modalias" attribute + * for driver coldplugging, and in uevents used for hotplugging + * @driver_override: If the name of a driver is written to this attribute, then + * the device will bind to the named driver and only the named driver. + * Do not set directly, because core frees it; use driver_set_override() to + * set or clear it. + * @cs_gpiod: gpio descriptor of the chipselect line (optional, NULL when + * not using a GPIO line) + * @word_delay: delay to be inserted between consecutive + * words of a transfer + * @cs_setup: delay to be introduced by the controller after CS is asserted + * @cs_hold: delay to be introduced by the controller before CS is deasserted + * @cs_inactive: delay to be introduced by the controller after CS is + * deasserted. If @cs_change_delay is used from @spi_transfer, then the + * two delays will be added up. + * @pcpu_statistics: statistics for the spi_device + * + * A @spi_device is used to interchange data between an SPI slave + * (usually a discrete chip) and CPU memory. + * + * In @dev, the platform_data is used to hold information about this + * device that's meaningful to the device's protocol driver, but not + * to its controller. One example might be an identifier for a chip + * variant with slightly different functionality; another might be + * information about how this particular board wires the chip's pins. + */ +struct spi_device { + struct device dev; + struct spi_controller *controller; + struct spi_controller *master; /* Compatibility layer */ + u32 max_speed_hz; + u8 chip_select; + u8 bits_per_word; + bool rt; +#define SPI_NO_TX BIT(31) /* No transmit wire */ +#define SPI_NO_RX BIT(30) /* No receive wire */ + /* + * TPM specification defines flow control over SPI. Client device + * can insert a wait state on MISO when address is transmitted by + * controller on MOSI. Detecting the wait state in software is only + * possible for full duplex controllers. For controllers that support + * only half-duplex, the wait state detection needs to be implemented + * in hardware. TPM devices would set this flag when hardware flow + * control is expected from SPI controller. + */ +#define SPI_TPM_HW_FLOW BIT(29) /* TPM HW flow control */ + /* + * All bits defined above should be covered by SPI_MODE_KERNEL_MASK. + * The SPI_MODE_KERNEL_MASK has the SPI_MODE_USER_MASK counterpart, + * which is defined in 'include/uapi/linux/spi/spi.h'. + * The bits defined here are from bit 31 downwards, while in + * SPI_MODE_USER_MASK are from 0 upwards. + * These bits must not overlap. A static assert check should make sure of that. + * If adding extra bits, make sure to decrease the bit index below as well. + */ +#define SPI_MODE_KERNEL_MASK (~(BIT(29) - 1)) + u32 mode; + int irq; + void *controller_state; + void *controller_data; + char modalias[SPI_NAME_SIZE]; + const char *driver_override; + struct gpio_desc *cs_gpiod; /* Chip select gpio desc */ + struct spi_delay word_delay; /* Inter-word delay */ + /* CS delays */ + struct spi_delay cs_setup; + struct spi_delay cs_hold; + struct spi_delay cs_inactive; + + /* The statistics */ + struct spi_statistics __percpu *pcpu_statistics; + + /* + * likely need more hooks for more protocol options affecting how + * the controller talks to each chip, like: + * - memory packing (12 bit samples into low bits, others zeroed) + * - priority + * - chipselect delays + * - ... + */ +}; +============================================================== \ No newline at end of file