QSPI Flash驱动代码分析(spi主设备驱动框架)

QSPI Flash驱动代码分析(spi主设备驱动框架)

        SPI主设备驱动的主要功能是:

  1. 向上提供 struct spi_master 主设备驱动接口和struct spi_controller_mem_ops相关访问操作方法。
  2. 向下管理SPI控制器。

1. struct spi_master结构体分配

/*linux/spi/spi.h*/
static inline struct spi_controller *spi_alloc_master(struct device *host,
						      unsigned int size)

参数介绍:

  1. 第一个参数是SPI控制器对应的device结构;
  2. 第二个参数是SPI控制器私有结构体的长度;

        可以通过宏spi_master_get_devdata(),根据struct spi_master结构体来获取私有结构体。

2.struct spi_controller结构体

        即struct spi_master结构

struct spi_controller {
	struct device	    dev;
	struct list_head    list;
	s16			        bus_num;
    /*SPI总线提供的有效片选信号数量,也可以指有效Flash芯片数量*/
	u16			        num_chipselect;
	u16			        dma_alignment;

    /*由SPI驱动提供的描述SPI控制器的收发模式*/
	u32			        mode_bits;

	u32			        buswidth_override_bits;
	u32			        bits_per_word_mask;

	u32			        min_speed_hz;
    /*设置为SPI设备的参考时钟频率*/
	u32			        max_speed_hz;

	u16			        flags;
	bool			    devm_allocated;
	bool			    slave;
	size_t (*max_transfer_size)(struct spi_device *spi);
	size_t (*max_message_size)(struct spi_device *spi);
	struct mutex		io_mutex;
	spinlock_t		    bus_lock_spinlock;
	struct mutex		bus_lock_mutex;
	bool			    bus_lock_flag;
	int	(*setup)(struct spi_device *spi);
	int (*set_cs_timing)(struct spi_device *spi, struct spi_delay *setup,
			     struct spi_delay *hold, struct spi_delay *inactive);
	int	(*transfer)(struct spi_device *spi,
						struct spi_message *mesg);
	void (*cleanup)(struct spi_device *spi);
	bool (*can_dma)(struct spi_controller *ctlr, struct spi_device *spi,
					   struct spi_transfer *xfer);
	bool				queued;
	struct kthread_worker		*kworker;
	struct kthread_work		    pump_messages;
	spinlock_t			    queue_lock;
	struct list_head		queue;
	struct spi_message		*cur_msg;
	bool				    idling;
	bool				    busy;
	bool				    running;
	bool				    rt;
	bool				    auto_runtime_pm;
	bool                    cur_msg_prepared;
	bool				    cur_msg_mapped;
	bool				    last_cs_enable;
	bool				    last_cs_mode_high;
	bool                    fallback;
	struct completion       xfer_completion;
	size_t				    max_dma_len;

	int (*prepare_transfer_hardware)(struct spi_controller *ctlr);
	int (*transfer_one_message)(struct spi_controller *ctlr,
				    struct spi_message *mesg);
	int (*unprepare_transfer_hardware)(struct spi_controller *ctlr);
	int (*prepare_message)(struct spi_controller *ctlr,
			       struct spi_message *message);
	int (*unprepare_message)(struct spi_controller *ctlr,
				 struct spi_message *message);
	int (*slave_abort)(struct spi_controller *ctlr);
	void (*set_cs)(struct spi_device *spi, bool enable);
	int (*transfer_one)(struct spi_controller *ctlr, struct spi_device *spi,
			    struct spi_transfer *transfer);
	void (*handle_err)(struct spi_controller *ctlr,
			   struct spi_message *message);

    /*由SPI驱动提供的访问SPI内存操作方法*/
	const struct spi_controller_mem_ops     *mem_ops; 

	struct spi_delay	cs_setup;
	struct spi_delay	cs_hold;
	struct spi_delay	cs_inactive;
	int			        *cs_gpios;
	struct gpio_desc	**cs_gpiods;
	bool			    use_gpio_descriptors;
	s8			        unused_native_cs;
	s8			        max_native_cs;
	struct spi_statistics	statistics;
	struct dma_chan		*dma_tx;
	struct dma_chan		*dma_rx;
	void			    *dummy_rx;
	void			    *dummy_tx;
	int (*fw_translate_cs)(struct spi_controller *ctlr, unsigned cs);
	bool			    ptp_sts_supported;
	unsigned long		irq_flags;
};

3. struct spi_controller_mem_ops访问SPI内存操作结构体

struct spi_controller_mem_ops {
	int (*adjust_op_size)(struct spi_mem *mem, struct spi_mem_op *op);
	bool (*supports_op)(struct spi_mem *mem,
			    const struct spi_mem_op *op);
	int (*exec_op)(struct spi_mem *mem,
		       const struct spi_mem_op *op);
	const char *(*get_name)(struct spi_mem *mem);
	int (*dirmap_create)(struct spi_mem_dirmap_desc *desc);
	void (*dirmap_destroy)(struct spi_mem_dirmap_desc *desc);
	ssize_t (*dirmap_read)(struct spi_mem_dirmap_desc *desc,
			       u64 offs, size_t len, void *buf);
	ssize_t (*dirmap_write)(struct spi_mem_dirmap_desc *desc,
				u64 offs, size_t len, const void *buf);
};

其中 supports_op判断访问是否被支持,exec_op是具体实现SPI内存访问操作的接口。

4. 向系统注册SPI master设备

devm_spi_register_master(_dev, _ctlr)

向系统注册SPI主设备,第一个参数是SPI设备的device结构体,第二参数是SPI设备的spi_master结构体。

猜你喜欢

转载自blog.csdn.net/lsshao/article/details/119929659