drivers/mfd/dln2.c

Source file repositories/reference/linux-study-clean/drivers/mfd/dln2.c

File Facts

System
Linux kernel
Corpus path
drivers/mfd/dln2.c
Extension
.c
Size
19369 bytes
Lines
870
Domain
Driver Families
Bucket
drivers/mfd
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct dln2_header {
	__le16 size;
	__le16 id;
	__le16 echo;
	__le16 handle;
};

struct dln2_response {
	struct dln2_header hdr;
	__le16 result;
};

#define DLN2_GENERIC_MODULE_ID		0x00
#define DLN2_GENERIC_CMD(cmd)		DLN2_CMD(cmd, DLN2_GENERIC_MODULE_ID)
#define CMD_GET_DEVICE_VER		DLN2_GENERIC_CMD(0x30)
#define CMD_GET_DEVICE_SN		DLN2_GENERIC_CMD(0x31)

#define DLN2_HW_ID			0x200
#define DLN2_USB_TIMEOUT		200	/* in ms */
#define DLN2_MAX_RX_SLOTS		16
#define DLN2_MAX_URBS			16
#define DLN2_RX_BUF_SIZE		512

enum dln2_handle {
	DLN2_HANDLE_EVENT = 0,		/* don't change, hardware defined */
	DLN2_HANDLE_CTRL,
	DLN2_HANDLE_GPIO,
	DLN2_HANDLE_I2C,
	DLN2_HANDLE_SPI,
	DLN2_HANDLE_ADC,
	DLN2_HANDLES
};

/*
 * Receive context used between the receive demultiplexer and the transfer
 * routine. While sending a request the transfer routine will look for a free
 * receive context and use it to wait for a response and to receive the URB and
 * thus the response data.
 */
struct dln2_rx_context {
	/* completion used to wait for a response */
	struct completion done;

	/* if non-NULL the URB contains the response */
	struct urb *urb;

	/* if true then this context is used to wait for a response */
	bool in_use;
};

/*
 * Receive contexts for a particular DLN2 module (i2c, gpio, etc.). We use the
 * handle header field to identify the module in dln2_dev.mod_rx_slots and then
 * the echo header field to index the slots field and find the receive context
 * for a particular request.
 */
struct dln2_mod_rx_slots {
	/* RX slots bitmap */
	DECLARE_BITMAP(bmap, DLN2_MAX_RX_SLOTS);

	/* used to wait for a free RX slot */
	wait_queue_head_t wq;

	/* used to wait for an RX operation to complete */
	struct dln2_rx_context slots[DLN2_MAX_RX_SLOTS];

	/* avoid races between alloc/free_rx_slot and dln2_rx_transfer */
	spinlock_t lock;
};

struct dln2_dev {
	struct usb_device *usb_dev;
	struct usb_interface *interface;
	u8 ep_in;
	u8 ep_out;

	struct urb *rx_urb[DLN2_MAX_URBS];
	void *rx_buf[DLN2_MAX_URBS];

	struct dln2_mod_rx_slots mod_rx_slots[DLN2_HANDLES];

	struct list_head event_cb_list;
	spinlock_t event_cb_lock;

	bool disconnect;
	int active_transfers;
	wait_queue_head_t disconnect_wq;
	spinlock_t disconnect_lock;
};

Annotation

Implementation Notes