static int qfprom_probe()

in qfprom.c [357:451]


static int qfprom_probe(struct platform_device *pdev)
{
	struct nvmem_config econfig = {
		.name = "qfprom",
		.stride = 1,
		.word_size = 1,
		.id = NVMEM_DEVID_AUTO,
		.reg_read = qfprom_reg_read,
	};
	struct device *dev = &pdev->dev;
	struct resource *res;
	struct nvmem_device *nvmem;
	const struct qfprom_soc_compatible_data *soc_data;
	struct qfprom_priv *priv;
	int ret;

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

	/* The corrected section is always provided */
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	priv->qfpcorrected = devm_ioremap_resource(dev, res);
	if (IS_ERR(priv->qfpcorrected))
		return PTR_ERR(priv->qfpcorrected);

	econfig.size = resource_size(res);
	econfig.dev = dev;
	econfig.priv = priv;

	priv->dev = dev;
	soc_data = device_get_match_data(dev);
	if (soc_data) {
		econfig.keepout = soc_data->keepout;
		econfig.nkeepout = soc_data->nkeepout;
	}

	/*
	 * If more than one region is provided then the OS has the ability
	 * to write.
	 */
	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
	if (res) {
		u32 version;
		int major_version, minor_version;

		priv->qfpraw = devm_ioremap_resource(dev, res);
		if (IS_ERR(priv->qfpraw))
			return PTR_ERR(priv->qfpraw);
		res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
		priv->qfpconf = devm_ioremap_resource(dev, res);
		if (IS_ERR(priv->qfpconf))
			return PTR_ERR(priv->qfpconf);
		res = platform_get_resource(pdev, IORESOURCE_MEM, 3);
		priv->qfpsecurity = devm_ioremap_resource(dev, res);
		if (IS_ERR(priv->qfpsecurity))
			return PTR_ERR(priv->qfpsecurity);

		version = readl(priv->qfpsecurity + QFPROM_VERSION_OFFSET);
		major_version = (version & QFPROM_MAJOR_VERSION_MASK) >>
				QFPROM_MAJOR_VERSION_SHIFT;
		minor_version = (version & QFPROM_MINOR_VERSION_MASK) >>
				QFPROM_MINOR_VERSION_SHIFT;

		if (major_version == 7 && minor_version == 8)
			priv->soc_data = &qfprom_7_8_data;
		else if (major_version == 7 && minor_version == 15)
			priv->soc_data = &qfprom_7_15_data;

		priv->vcc = devm_regulator_get(&pdev->dev, "vcc");
		if (IS_ERR(priv->vcc))
			return PTR_ERR(priv->vcc);

		priv->secclk = devm_clk_get(dev, "core");
		if (IS_ERR(priv->secclk)) {
			ret = PTR_ERR(priv->secclk);
			if (ret != -EPROBE_DEFER)
				dev_err(dev, "Error getting clock: %d\n", ret);
			return ret;
		}

		/* Only enable writing if we have SoC data. */
		if (priv->soc_data)
			econfig.reg_write = qfprom_reg_write;
	}

	pm_runtime_enable(dev);
	ret = devm_add_action_or_reset(dev, qfprom_runtime_disable, dev);
	if (ret)
		return ret;

	nvmem = devm_nvmem_register(dev, &econfig);

	return PTR_ERR_OR_ZERO(nvmem);
}