drivers/net/wireless/st/cw1200/cw1200_spi.c

Source file repositories/reference/linux-study-clean/drivers/net/wireless/st/cw1200/cw1200_spi.c

File Facts

System
Linux kernel
Corpus path
drivers/net/wireless/st/cw1200/cw1200_spi.c
Extension
.c
Size
11243 bytes
Lines
472
Domain
Driver Families
Bucket
drivers/net
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 hwbus_priv {
	struct spi_device	*func;
	struct cw1200_common	*core;
	const struct cw1200_platform_data_spi *pdata;
	spinlock_t		lock; /* Serialize all bus operations */
	wait_queue_head_t       wq;
	struct gpio_desc	*reset;
	struct gpio_desc	*powerup;
	int claimed;
};

#define SDIO_TO_SPI_ADDR(addr) ((addr & 0x1f)>>2)
#define SET_WRITE 0x7FFF /* usage: and operation */
#define SET_READ 0x8000  /* usage: or operation */

/* Notes on byte ordering:
   LE:  B0 B1 B2 B3
   BE:  B3 B2 B1 B0

   Hardware expects 32-bit data to be written as 16-bit BE words:

   B1 B0 B3 B2
*/

static int cw1200_spi_memcpy_fromio(struct hwbus_priv *self,
				     unsigned int addr,
				     void *dst, int count)
{
	int ret, i;
	u16 regaddr;
	struct spi_message      m;

	struct spi_transfer     t_addr = {
		.tx_buf         = &regaddr,
		.len            = sizeof(regaddr),
	};
	struct spi_transfer     t_msg = {
		.rx_buf         = dst,
		.len            = count,
	};

	regaddr = (SDIO_TO_SPI_ADDR(addr))<<12;
	regaddr |= SET_READ;
	regaddr |= (count>>1);

#ifdef SPI_DEBUG
	pr_info("READ : %04d from 0x%02x (%04x)\n", count, addr, regaddr);
#endif

	/* Header is LE16 */
	regaddr = (__force u16)cpu_to_le16(regaddr);

	/* We have to byteswap if the SPI bus is limited to 8b operation
	   or we are running on a Big Endian system
	*/
#if defined(__LITTLE_ENDIAN)
	if (self->func->bits_per_word == 8)
#endif
		regaddr = swab16(regaddr);

	spi_message_init(&m);
	spi_message_add_tail(&t_addr, &m);
	spi_message_add_tail(&t_msg, &m);
	ret = spi_sync(self->func, &m);

#ifdef SPI_DEBUG
	pr_info("READ : ");
	for (i = 0; i < t_addr.len; i++)
		printk("%02x ", ((u8 *)t_addr.tx_buf)[i]);
	printk(" : ");
	for (i = 0; i < t_msg.len; i++)
		printk("%02x ", ((u8 *)t_msg.rx_buf)[i]);
	printk("\n");
#endif

	/* We have to byteswap if the SPI bus is limited to 8b operation
	   or we are running on a Big Endian system
	*/
#if defined(__LITTLE_ENDIAN)
	if (self->func->bits_per_word == 8)
#endif
	{
		uint16_t *buf = (uint16_t *)dst;
		for (i = 0; i < ((count + 1) >> 1); i++)
			buf[i] = swab16(buf[i]);
	}

	return ret;
}

Annotation

Implementation Notes