drivers/bus/hisi_lpc.c

Source file repositories/reference/linux-study-clean/drivers/bus/hisi_lpc.c

File Facts

System
Linux kernel
Corpus path
drivers/bus/hisi_lpc.c
Extension
.c
Size
18419 bytes
Lines
695
Domain
Driver Families
Bucket
drivers/bus
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 lpc_cycle_para {
	unsigned int opflags;
	unsigned int csize; /* data length of each operation */
};

struct hisi_lpc_dev {
	spinlock_t cycle_lock;
	void __iomem  *membase;
	struct logic_pio_hwaddr *io_host;
};

/* The max IO cycle counts supported is four per operation at maximum */
#define LPC_MAX_DWIDTH	4

#define LPC_REG_STARTUP_SIGNAL		0x00
#define LPC_REG_STARTUP_SIGNAL_START	BIT(0)
#define LPC_REG_OP_STATUS		0x04
#define LPC_REG_OP_STATUS_IDLE		BIT(0)
#define LPC_REG_OP_STATUS_FINISHED	BIT(1)
#define LPC_REG_OP_LEN			0x10 /* LPC cycles count per start */
#define LPC_REG_CMD			0x14
#define LPC_REG_CMD_OP			BIT(0) /* 0: read, 1: write */
#define LPC_REG_CMD_SAMEADDR		BIT(3)
#define LPC_REG_ADDR			0x20 /* target address */
#define LPC_REG_WDATA			0x24 /* write FIFO */
#define LPC_REG_RDATA			0x28 /* read FIFO */

/* The minimal nanosecond interval for each query on LPC cycle status */
#define LPC_NSEC_PERWAIT	100

/*
 * The maximum waiting time is about 128us.  It is specific for stream I/O,
 * such as ins.
 *
 * The fastest IO cycle time is about 390ns, but the worst case will wait
 * for extra 256 lpc clocks, so (256 + 13) * 30ns = 8 us. The maximum burst
 * cycles is 16. So, the maximum waiting time is about 128us under worst
 * case.
 *
 * Choose 1300 as the maximum.
 */
#define LPC_MAX_WAITCNT		1300

/* About 10us. This is specific for single IO operations, such as inb */
#define LPC_PEROP_WAITCNT	100

static int wait_lpc_idle(void __iomem *mbase, unsigned int waitcnt)
{
	u32 status;

	do {
		status = readl(mbase + LPC_REG_OP_STATUS);
		if (status & LPC_REG_OP_STATUS_IDLE)
			return (status & LPC_REG_OP_STATUS_FINISHED) ? 0 : -EIO;
		ndelay(LPC_NSEC_PERWAIT);
	} while (--waitcnt);

	return -ETIMEDOUT;
}

/*
 * hisi_lpc_target_in - trigger a series of LPC cycles for read operation
 * @lpcdev: pointer to hisi lpc device
 * @para: some parameters used to control the lpc I/O operations
 * @addr: the lpc I/O target port address
 * @buf: where the read back data is stored
 * @opcnt: how many I/O operations required, i.e. data width
 *
 * Returns 0 on success, non-zero on fail.
 */
static int hisi_lpc_target_in(struct hisi_lpc_dev *lpcdev,
			      struct lpc_cycle_para *para, unsigned long addr,
			      unsigned char *buf, unsigned long opcnt)
{
	unsigned int cmd_word;
	unsigned int waitcnt;
	unsigned long flags;
	int ret;

	if (!buf || !opcnt || !para || !para->csize || !lpcdev)
		return -EINVAL;

	cmd_word = 0; /* IO mode, Read */
	waitcnt = LPC_PEROP_WAITCNT;
	if (!(para->opflags & FG_INCRADDR_LPC)) {
		cmd_word |= LPC_REG_CMD_SAMEADDR;
		waitcnt = LPC_MAX_WAITCNT;
	}

	/* whole operation must be atomic */

Annotation

Implementation Notes