drivers/soc/aspeed/aspeed-p2a-ctrl.c

Source file repositories/reference/linux-study-clean/drivers/soc/aspeed/aspeed-p2a-ctrl.c

File Facts

System
Linux kernel
Corpus path
drivers/soc/aspeed/aspeed-p2a-ctrl.c
Extension
.c
Size
11380 bytes
Lines
435
Domain
Driver Families
Bucket
drivers/soc
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 aspeed_p2a_ctrl_fops = {
	.owner = THIS_MODULE,
	.mmap = aspeed_p2a_mmap,
	.unlocked_ioctl = aspeed_p2a_ioctl,
	.open = aspeed_p2a_open,
	.release = aspeed_p2a_release,
};

/* The regions are controlled by SCU2C */
static void aspeed_p2a_disable_all(struct aspeed_p2a_ctrl *p2a_ctrl)
{
	int i;
	u32 value = 0;

	for (i = 0; i < P2A_REGION_COUNT; i++)
		value |= p2a_ctrl->config->regions[i].bit;

	regmap_update_bits(p2a_ctrl->regmap, SCU2C, value, value);

	/* Disable the bridge. */
	aspeed_p2a_disable_bridge(p2a_ctrl);
}

static int aspeed_p2a_ctrl_probe(struct platform_device *pdev)
{
	struct aspeed_p2a_ctrl *misc_ctrl;
	struct device *dev;
	struct resource resm;
	int rc = 0;

	dev = &pdev->dev;

	misc_ctrl = devm_kzalloc(dev, sizeof(*misc_ctrl), GFP_KERNEL);
	if (!misc_ctrl)
		return -ENOMEM;

	mutex_init(&misc_ctrl->tracking);

	/* optional. */
	rc = of_reserved_mem_region_to_resource(dev->of_node, 0, &resm);
	if (!rc) {
		misc_ctrl->mem_size = resource_size(&resm);
		misc_ctrl->mem_base = resm.start;
	}

	misc_ctrl->regmap = syscon_node_to_regmap(pdev->dev.parent->of_node);
	if (IS_ERR(misc_ctrl->regmap)) {
		dev_err(dev, "Couldn't get regmap\n");
		return -ENODEV;
	}

	misc_ctrl->config = of_device_get_match_data(dev);

	dev_set_drvdata(&pdev->dev, misc_ctrl);

	aspeed_p2a_disable_all(misc_ctrl);

	misc_ctrl->miscdev.minor = MISC_DYNAMIC_MINOR;
	misc_ctrl->miscdev.name = DEVICE_NAME;
	misc_ctrl->miscdev.fops = &aspeed_p2a_ctrl_fops;
	misc_ctrl->miscdev.parent = dev;

	rc = misc_register(&misc_ctrl->miscdev);
	if (rc)
		dev_err(dev, "Unable to register device\n");

	return rc;
}

static void aspeed_p2a_ctrl_remove(struct platform_device *pdev)
{
	struct aspeed_p2a_ctrl *p2a_ctrl = dev_get_drvdata(&pdev->dev);

	misc_deregister(&p2a_ctrl->miscdev);
}

#define SCU2C_DRAM	BIT(25)
#define SCU2C_SPI	BIT(24)
#define SCU2C_SOC	BIT(23)
#define SCU2C_FLASH	BIT(22)

static const struct aspeed_p2a_model_data ast2400_model_data = {
	.regions = {
		{0x00000000, 0x17FFFFFF, SCU2C_FLASH},
		{0x18000000, 0x1FFFFFFF, SCU2C_SOC},
		{0x20000000, 0x2FFFFFFF, SCU2C_FLASH},
		{0x30000000, 0x3FFFFFFF, SCU2C_SPI},
		{0x40000000, 0x5FFFFFFF, SCU2C_DRAM},
		{0x60000000, 0xFFFFFFFF, SCU2C_SOC},
	}

Annotation

Implementation Notes