drivers/fsi/fsi-occ.c

Source file repositories/reference/linux-study-clean/drivers/fsi/fsi-occ.c

File Facts

System
Linux kernel
Corpus path
drivers/fsi/fsi-occ.c
Extension
.c
Size
17544 bytes
Lines
760
Domain
Driver Families
Bucket
drivers/fsi
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern 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

static const struct file_operations occ_fops = {
	.owner = THIS_MODULE,
	.open = occ_open,
	.read = occ_read,
	.write = occ_write,
	.release = occ_release,
};

static void occ_save_ffdc(struct occ *occ, __be32 *resp, size_t parsed_len,
			  size_t resp_len)
{
	if (resp_len > parsed_len) {
		size_t dh = resp_len - parsed_len;
		size_t ffdc_len = (dh - 1) * 4; /* SBE words are four bytes */
		__be32 *ffdc = &resp[parsed_len];

		if (ffdc_len > occ->client_buffer_size)
			ffdc_len = occ->client_buffer_size;

		memcpy(occ->client_buffer, ffdc, ffdc_len);
		occ->client_response_size = ffdc_len;
	}
}

static int occ_verify_checksum(struct occ *occ, struct occ_response *resp,
			       u16 data_length)
{
	/* Fetch the two bytes after the data for the checksum. */
	u16 checksum_resp = get_unaligned_be16(&resp->data[data_length]);
	u16 checksum;
	u16 i;

	checksum = resp->seq_no;
	checksum += resp->cmd_type;
	checksum += resp->return_status;
	checksum += (data_length >> 8) + (data_length & 0xFF);

	for (i = 0; i < data_length; ++i)
		checksum += resp->data[i];

	if (checksum != checksum_resp) {
		dev_err(occ->dev, "Bad checksum: %04x!=%04x\n", checksum,
			checksum_resp);
		return -EBADE;
	}

	return 0;
}

static int occ_getsram(struct occ *occ, u32 offset, void *data, ssize_t len)
{
	u32 data_len = ((len + 7) / 8) * 8;	/* must be multiples of 8 B */
	size_t cmd_len, parsed_len, resp_data_len;
	size_t resp_len = OCC_MAX_RESP_WORDS;
	__be32 *resp = occ->buffer;
	__be32 cmd[6];
	int idx = 0, rc;

	/*
	 * Magic sequence to do SBE getsram command. SBE will fetch data from
	 * specified SRAM address.
	 */
	switch (occ->version) {
	default:
	case occ_p9:
		cmd_len = 5;
		cmd[2] = cpu_to_be32(1);	/* Normal mode */
		cmd[3] = cpu_to_be32(OCC_P9_SRAM_RSP_ADDR + offset);
		break;
	case occ_p10:
		idx = 1;
		cmd_len = 6;
		cmd[2] = cpu_to_be32(OCC_P10_SRAM_MODE);
		cmd[3] = 0;
		cmd[4] = cpu_to_be32(OCC_P10_SRAM_RSP_ADDR + offset);
		break;
	}

	cmd[0] = cpu_to_be32(cmd_len);
	cmd[1] = cpu_to_be32(SBEFIFO_CMD_GET_OCC_SRAM);
	cmd[4 + idx] = cpu_to_be32(data_len);

	rc = sbefifo_submit(occ->sbefifo, cmd, cmd_len, resp, &resp_len);
	if (rc)
		return rc;

	rc = sbefifo_parse_status(occ->sbefifo, SBEFIFO_CMD_GET_OCC_SRAM,
				  resp, resp_len, &parsed_len);
	if (rc > 0) {
		dev_err(occ->dev, "SRAM read returned failure status: %08x\n",

Annotation

Implementation Notes