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.
- 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.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/acpi.hlinux/console.hlinux/delay.hlinux/io.hlinux/logic_pio.hlinux/module.hlinux/of.hlinux/of_platform.hlinux/pci.hlinux/platform_device.hlinux/serial_8250.hlinux/slab.h
Detected Declarations
struct lpc_cycle_parastruct hisi_lpc_devstruct hisi_lpc_acpi_cellfunction wait_lpc_idlefunction hisi_lpc_target_infunction hisi_lpc_target_outfunction hisi_lpc_pio_to_addrfunction hisi_lpc_comm_infunction outfunction hisi_lpc_comm_insfunction hisi_lpc_comm_outsfunction hisi_lpc_acpi_xlat_io_resfunction hisi_lpc_acpi_fixup_child_resourcefunction hisi_lpc_acpi_set_io_resfunction hisi_lpc_acpi_remove_subdevfunction hisi_lpc_acpi_clear_enumeratedfunction hisi_lpc_acpi_removefunction hisi_lpc_acpi_add_childfunction hisi_lpc_acpi_probefunction hisi_lpc_acpi_probefunction hisi_lpc_acpi_removefunction hisi_lpc_remove
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
- Immediate include surface: `linux/acpi.h`, `linux/console.h`, `linux/delay.h`, `linux/io.h`, `linux/logic_pio.h`, `linux/module.h`, `linux/of.h`, `linux/of_platform.h`.
- Detected declarations: `struct lpc_cycle_para`, `struct hisi_lpc_dev`, `struct hisi_lpc_acpi_cell`, `function wait_lpc_idle`, `function hisi_lpc_target_in`, `function hisi_lpc_target_out`, `function hisi_lpc_pio_to_addr`, `function hisi_lpc_comm_in`, `function out`, `function hisi_lpc_comm_ins`.
- Atlas domain: Driver Families / drivers/bus.
- Implementation status: source implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.