drivers/regulator/mt6363-regulator.c

Source file repositories/reference/linux-study-clean/drivers/regulator/mt6363-regulator.c

File Facts

System
Linux kernel
Corpus path
drivers/regulator/mt6363-regulator.c
Extension
.c
Size
29670 bytes
Lines
944
Domain
Driver Families
Bucket
drivers/regulator
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

ret = device_add(&sdev->dev);
	if (ret) {
		put_device(&sdev->dev);
		return ERR_PTR(ret);
	};

	ret = devm_add_action_or_reset(dev, mt6363_spmi_remove, sdev);
	if (ret)
		return ERR_PTR(ret);

	mt6363_regmap_config.reg_base = base;

	return devm_regmap_init_spmi_ext(sdev, &mt6363_regmap_config);
}

static int mt6363_regulator_probe(struct platform_device *pdev)
{
	struct device_node *interrupt_parent;
	struct regulator_config config = {};
	struct mt6363_regulator_info *info;
	struct device *dev = &pdev->dev;
	struct regulator_dev *rdev;
	struct irq_domain *domain;
	struct irq_fwspec fwspec;
	struct spmi_device *sdev;
	int i, ret, val;

	config.regmap = mt6363_spmi_register_regmap(dev);
	if (IS_ERR(config.regmap))
		return dev_err_probe(dev, PTR_ERR(config.regmap),
				     "Cannot get regmap\n");
	config.dev = dev;
	sdev = to_spmi_device(dev->parent);

	/*
	 * The first read may fail if the bootloader sets sleep mode: wake up
	 * this PMIC with W/R on the SPMI bus and ignore the first result.
	 * This matches the MT6373 driver behavior.
	 */
	regmap_read(config.regmap, MT6363_TOP_TRAP, &val);

	interrupt_parent = of_irq_find_parent(dev->of_node);
	if (!interrupt_parent)
		return dev_err_probe(dev, -EINVAL, "Cannot find IRQ parent\n");

	domain = irq_find_host(interrupt_parent);
	of_node_put(interrupt_parent);
	fwspec.fwnode = domain->fwnode;

	fwspec.param_count = 3;
	fwspec.param[0] = sdev->usid;
	fwspec.param[2] = IRQ_TYPE_LEVEL_HIGH;

	for (i = 0; i < ARRAY_SIZE(mt6363_regulators); i++) {
		info = &mt6363_regulators[i];

		fwspec.param[1] = info->hwirq;
		info->virq = irq_create_fwspec_mapping(&fwspec);
		if (!info->virq)
			return dev_err_probe(dev, -EINVAL,
					     "Failed to map IRQ%d\n", info->hwirq);

		ret = devm_add_action_or_reset(dev, mt6363_irq_remove, &info->virq);
		if (ret)
			return ret;

		config.driver_data = info;
		INIT_DELAYED_WORK(&info->oc_work, mt6363_oc_irq_enable_work);

		rdev = devm_regulator_register(dev, &info->desc, &config);
		if (IS_ERR(rdev))
			return dev_err_probe(dev, PTR_ERR(rdev),
					     "failed to register %s\n", info->desc.name);

		if (info->lp_imax_uA) {
			ret = mt6363_backup_op_setting(config.regmap, info);
			if (ret) {
				dev_warn(dev, "Failed to backup op_setting for %s\n",
					 info->desc.name);
				info->lp_imax_uA = 0;
			}
		}
	}

	return 0;
}

static const struct of_device_id mt6363_regulator_match[] = {
	{ .compatible = "mediatek,mt6363-regulator" },
	{ /* sentinel */ }

Annotation

Implementation Notes