drivers/mfd/intel_soc_pmic_crc.c

Source file repositories/reference/linux-study-clean/drivers/mfd/intel_soc_pmic_crc.c

File Facts

System
Linux kernel
Corpus path
drivers/mfd/intel_soc_pmic_crc.c
Extension
.c
Size
7536 bytes
Lines
284
Domain
Driver Families
Bucket
drivers/mfd
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 crystal_cove_config {
	unsigned long irq_flags;
	struct mfd_cell *cell_dev;
	int n_cell_devs;
	const struct regmap_config *regmap_config;
	const struct regmap_irq_chip *irq_chip;
};

static const struct crystal_cove_config crystal_cove_config_byt_crc = {
	.irq_flags = IRQF_TRIGGER_RISING,
	.cell_dev = crystal_cove_byt_dev,
	.n_cell_devs = ARRAY_SIZE(crystal_cove_byt_dev),
	.regmap_config = &crystal_cove_regmap_config,
	.irq_chip = &crystal_cove_irq_chip,
};

static const struct crystal_cove_config crystal_cove_config_cht_crc = {
	.irq_flags = IRQF_TRIGGER_RISING,
	.cell_dev = crystal_cove_cht_dev,
	.n_cell_devs = ARRAY_SIZE(crystal_cove_cht_dev),
	.regmap_config = &crystal_cove_regmap_config,
	.irq_chip = &crystal_cove_irq_chip,
};

static int crystal_cove_i2c_probe(struct i2c_client *i2c)
{
	const struct crystal_cove_config *config;
	struct device *dev = &i2c->dev;
	struct intel_soc_pmic *pmic;
	int ret;

	if (soc_intel_is_byt())
		config = &crystal_cove_config_byt_crc;
	else
		config = &crystal_cove_config_cht_crc;

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

	i2c_set_clientdata(i2c, pmic);

	pmic->regmap = devm_regmap_init_i2c(i2c, config->regmap_config);
	if (IS_ERR(pmic->regmap))
		return PTR_ERR(pmic->regmap);

	pmic->irq = i2c->irq;

	ret = devm_regmap_add_irq_chip(dev, pmic->regmap, pmic->irq,
				       config->irq_flags | IRQF_ONESHOT,
				       0, config->irq_chip, &pmic->irq_chip_data);
	if (ret)
		return ret;

	ret = enable_irq_wake(pmic->irq);
	if (ret)
		dev_warn(dev, "Can't enable IRQ as wake source: %d\n", ret);

	/* Add lookup table for crc-pwm */
	pwm_add_table(crc_pwm_lookup, ARRAY_SIZE(crc_pwm_lookup));

	/* To distuingish this domain from the GPIO/charger's irqchip domains */
	irq_domain_update_bus_token(regmap_irq_get_domain(pmic->irq_chip_data),
				    DOMAIN_BUS_NEXUS);

	ret = mfd_add_devices(dev, PLATFORM_DEVID_NONE, config->cell_dev,
			      config->n_cell_devs, NULL, 0,
			      regmap_irq_get_domain(pmic->irq_chip_data));
	if (ret)
		pwm_remove_table(crc_pwm_lookup, ARRAY_SIZE(crc_pwm_lookup));

	return ret;
}

static void crystal_cove_i2c_remove(struct i2c_client *i2c)
{
	/* remove crc-pwm lookup table */
	pwm_remove_table(crc_pwm_lookup, ARRAY_SIZE(crc_pwm_lookup));

	mfd_remove_devices(&i2c->dev);
}

static void crystal_cove_shutdown(struct i2c_client *i2c)
{
	struct intel_soc_pmic *pmic = i2c_get_clientdata(i2c);

	disable_irq(pmic->irq);

	return;
}

Annotation

Implementation Notes