drivers/platform/x86/serial-multi-instantiate.c

Source file repositories/reference/linux-study-clean/drivers/platform/x86/serial-multi-instantiate.c

File Facts

System
Linux kernel
Corpus path
drivers/platform/x86/serial-multi-instantiate.c
Extension
.c
Size
10906 bytes
Lines
436
Domain
Driver Families
Bucket
drivers/platform
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 smi_instance {
	const char *type;
	unsigned int flags;
	int irq_idx;
};

struct smi_node {
	enum smi_bus_type bus_type;
	struct smi_instance instances[];
};

struct smi {
	int i2c_num;
	int spi_num;
	struct i2c_client **i2c_devs;
	struct spi_device **spi_devs;
};

static int smi_get_irq(struct platform_device *pdev, struct acpi_device *adev,
		       const struct smi_instance *inst)
{
	int ret;

	switch (inst->flags & IRQ_RESOURCE_TYPE) {
	case IRQ_RESOURCE_AUTO:
		ret = acpi_dev_gpio_irq_get(adev, inst->irq_idx);
		if (ret > 0) {
			dev_dbg(&pdev->dev, "Using gpio irq\n");
			break;
		}
		ret = platform_get_irq(pdev, inst->irq_idx);
		if (ret > 0) {
			dev_dbg(&pdev->dev, "Using platform irq\n");
			break;
		}
		if (inst->flags & IRQ_RESOURCE_OPT) {
			dev_dbg(&pdev->dev, "No irq\n");
			return 0;
		}
		break;
	case IRQ_RESOURCE_GPIO:
		ret = acpi_dev_gpio_irq_get(adev, inst->irq_idx);
		break;
	case IRQ_RESOURCE_APIC:
		ret = platform_get_irq(pdev, inst->irq_idx);
		break;
	default:
		return 0;
	}
	if (ret < 0)
		return dev_err_probe(&pdev->dev, ret, "Error requesting irq at index %d\n",
				     inst->irq_idx);

	return ret;
}

static void smi_devs_unregister(struct smi *smi)
{
#if IS_REACHABLE(CONFIG_I2C)
	while (smi->i2c_num--)
		i2c_unregister_device(smi->i2c_devs[smi->i2c_num]);
#endif

	if (IS_REACHABLE(CONFIG_SPI)) {
		while (smi->spi_num--)
			spi_unregister_device(smi->spi_devs[smi->spi_num]);
	}
}

/**
 * smi_spi_probe - Instantiate multiple SPI devices from inst array
 * @pdev:	Platform device
 * @smi:	Internal struct for Serial multi instantiate driver
 * @inst_array:	Array of instances to probe
 *
 * Returns the number of SPI devices instantiate, Zero if none is found or a negative error code.
 */
static int smi_spi_probe(struct platform_device *pdev, struct smi *smi,
			 const struct smi_instance *inst_array)
{
	struct device *dev = &pdev->dev;
	struct acpi_device *adev = ACPI_COMPANION(dev);
	struct spi_controller *ctlr;
	struct spi_device *spi_dev;
	char name[50];
	int i, ret, count;

	ret = acpi_spi_count_resources(adev);
	if (ret < 0)
		return ret;

Annotation

Implementation Notes