drivers/soc/hisilicon/kunpeng_hccs.c

Source file repositories/reference/linux-study-clean/drivers/soc/hisilicon/kunpeng_hccs.c

File Facts

System
Linux kernel
Corpus path
drivers/soc/hisilicon/kunpeng_hccs.c
Extension
.c
Size
45694 bytes
Lines
1833
Domain
Driver Families
Bucket
drivers/soc
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 hccs_register_ctx {
	struct device *dev;
	u8 chan_id;
	int err;
};

static acpi_status hccs_get_register_cb(struct acpi_resource *ares,
					void *context)
{
	struct acpi_resource_generic_register *reg;
	struct hccs_register_ctx *ctx = context;

	if (ares->type != ACPI_RESOURCE_TYPE_GENERIC_REGISTER)
		return AE_OK;

	reg = &ares->data.generic_reg;
	if (reg->space_id != ACPI_ADR_SPACE_PLATFORM_COMM) {
		dev_err(ctx->dev, "Bad register resource.\n");
		ctx->err = -EINVAL;
		return AE_ERROR;
	}
	ctx->chan_id = reg->access_size;

	return AE_OK;
}

static int hccs_get_pcc_chan_id(struct hccs_dev *hdev)
{
	acpi_handle handle = ACPI_HANDLE(hdev->dev);
	struct hccs_register_ctx ctx = {0};
	acpi_status status;

	if (!acpi_has_method(handle, METHOD_NAME__CRS)) {
		dev_err(hdev->dev, "No _CRS method.\n");
		return -ENODEV;
	}

	ctx.dev = hdev->dev;
	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
				     hccs_get_register_cb, &ctx);
	if (ACPI_FAILURE(status))
		return ctx.err;
	hdev->chan_id = ctx.chan_id;

	return 0;
}

static void hccs_chan_tx_done(struct mbox_client *cl, void *msg, int ret)
{
	if (ret < 0)
		pr_debug("TX did not complete: CMD sent:0x%x, ret:%d\n",
			 *(u8 *)msg, ret);
	else
		pr_debug("TX completed. CMD sent:0x%x, ret:%d\n",
			 *(u8 *)msg, ret);
}

static void hccs_pcc_rx_callback(struct mbox_client *cl, void *mssg)
{
	struct hccs_mbox_client_info *cl_info =
			container_of(cl, struct hccs_mbox_client_info, client);

	complete(&cl_info->done);
}

static void hccs_unregister_pcc_channel(struct hccs_dev *hdev)
{
	pcc_mbox_free_channel(hdev->cl_info.pcc_chan);
}

static int hccs_register_pcc_channel(struct hccs_dev *hdev)
{
	struct hccs_mbox_client_info *cl_info = &hdev->cl_info;
	struct mbox_client *cl = &cl_info->client;
	struct pcc_mbox_chan *pcc_chan;
	struct mbox_chan *mbox_chan;
	struct device *dev = hdev->dev;
	int rc;

	cl->dev = dev;
	cl->tx_block = false;
	cl->knows_txdone = true;
	cl->tx_done = hccs_chan_tx_done;
	cl->rx_callback = hdev->verspec_data->rx_callback;
	init_completion(&cl_info->done);

	pcc_chan = pcc_mbox_request_channel(cl, hdev->chan_id);
	if (IS_ERR(pcc_chan)) {
		dev_err(dev, "PCC channel request failed.\n");
		rc = -ENODEV;

Annotation

Implementation Notes