drivers/spi/spi-bcm63xx.c

Source file repositories/reference/linux-study-clean/drivers/spi/spi-bcm63xx.c

File Facts

System
Linux kernel
Corpus path
drivers/spi/spi-bcm63xx.c
Extension
.c
Size
17628 bytes
Lines
678
Domain
Driver Families
Bucket
drivers/spi
Inferred role
Driver Families: implementation source
Status
source 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 bcm63xx_spi {
	struct completion	done;

	void __iomem		*regs;
	int			irq;

	/* Platform data */
	const unsigned long	*reg_offsets;
	unsigned int		fifo_size;
	unsigned int		msg_type_shift;
	unsigned int		msg_ctl_width;

	/* data iomem */
	u8 __iomem		*tx_io;
	const u8 __iomem	*rx_io;

	struct clk		*clk;
	struct platform_device	*pdev;
};

static inline u8 bcm_spi_readb(struct bcm63xx_spi *bs,
			       unsigned int offset)
{
	return readb(bs->regs + bs->reg_offsets[offset]);
}

static inline void bcm_spi_writeb(struct bcm63xx_spi *bs,
				  u8 value, unsigned int offset)
{
	writeb(value, bs->regs + bs->reg_offsets[offset]);
}

static inline void bcm_spi_writew(struct bcm63xx_spi *bs,
				  u16 value, unsigned int offset)
{
#ifdef CONFIG_CPU_BIG_ENDIAN
	iowrite16be(value, bs->regs + bs->reg_offsets[offset]);
#else
	writew(value, bs->regs + bs->reg_offsets[offset]);
#endif
}

static const unsigned int bcm63xx_spi_freq_table[SPI_CLK_MASK][2] = {
	{ 20000000, SPI_CLK_20MHZ },
	{ 12500000, SPI_CLK_12_50MHZ },
	{  6250000, SPI_CLK_6_250MHZ },
	{  3125000, SPI_CLK_3_125MHZ },
	{  1563000, SPI_CLK_1_563MHZ },
	{   781000, SPI_CLK_0_781MHZ },
	{   391000, SPI_CLK_0_391MHZ }
};

static void bcm63xx_spi_setup_transfer(struct spi_device *spi,
				      struct spi_transfer *t)
{
	struct bcm63xx_spi *bs = spi_controller_get_devdata(spi->controller);
	u8 clk_cfg, reg;
	int i;

	/* Default to lowest clock configuration */
	clk_cfg = SPI_CLK_0_391MHZ;

	/* Find the closest clock configuration */
	for (i = 0; i < SPI_CLK_MASK; i++) {
		if (t->speed_hz >= bcm63xx_spi_freq_table[i][0]) {
			clk_cfg = bcm63xx_spi_freq_table[i][1];
			break;
		}
	}

	/* clear existing clock configuration bits of the register */
	reg = bcm_spi_readb(bs, SPI_CLK_CFG);
	reg &= ~SPI_CLK_MASK;
	reg |= clk_cfg;

	bcm_spi_writeb(bs, reg, SPI_CLK_CFG);
	dev_dbg(&spi->dev, "Setting clock register to %02x (hz %d)\n",
		clk_cfg, t->speed_hz);
}

/* the spi->mode bits understood by this driver: */
#define MODEBITS (SPI_CPOL | SPI_CPHA)

static int bcm63xx_txrx_bufs(struct spi_device *spi, struct spi_transfer *first,
				unsigned int num_transfers)
{
	struct bcm63xx_spi *bs = spi_controller_get_devdata(spi->controller);
	u16 msg_ctl;
	u16 cmd;
	unsigned int i, timeout = 0, prepend_len = 0, len = 0;

Annotation

Implementation Notes