static int davinci_i2c_probe()

in busses/i2c-davinci.c [760:890]


static int davinci_i2c_probe(struct platform_device *pdev)
{
	struct davinci_i2c_dev *dev;
	struct i2c_adapter *adap;
	struct i2c_bus_recovery_info *rinfo;
	int r, irq;

	irq = platform_get_irq(pdev, 0);
	if (irq <= 0) {
		if (!irq)
			irq = -ENXIO;
		return dev_err_probe(&pdev->dev, irq, "can't get irq resource\n");
	}

	dev = devm_kzalloc(&pdev->dev, sizeof(struct davinci_i2c_dev),
			GFP_KERNEL);
	if (!dev) {
		dev_err(&pdev->dev, "Memory allocation failed\n");
		return -ENOMEM;
	}

	init_completion(&dev->cmd_complete);

	dev->dev = &pdev->dev;
	dev->irq = irq;
	dev->pdata = dev_get_platdata(&pdev->dev);
	platform_set_drvdata(pdev, dev);

	if (!dev->pdata && pdev->dev.of_node) {
		u32 prop;

		dev->pdata = devm_kzalloc(&pdev->dev,
			sizeof(struct davinci_i2c_platform_data), GFP_KERNEL);
		if (!dev->pdata)
			return -ENOMEM;

		memcpy(dev->pdata, &davinci_i2c_platform_data_default,
			sizeof(struct davinci_i2c_platform_data));
		if (!of_property_read_u32(pdev->dev.of_node, "clock-frequency",
			&prop))
			dev->pdata->bus_freq = prop / 1000;

		dev->pdata->has_pfunc =
			of_property_read_bool(pdev->dev.of_node,
					      "ti,has-pfunc");
	} else if (!dev->pdata) {
		dev->pdata = &davinci_i2c_platform_data_default;
	}

	dev->clk = devm_clk_get(&pdev->dev, NULL);
	if (IS_ERR(dev->clk))
		return PTR_ERR(dev->clk);

	dev->base = devm_platform_ioremap_resource(pdev, 0);
	if (IS_ERR(dev->base)) {
		return PTR_ERR(dev->base);
	}

	pm_runtime_set_autosuspend_delay(dev->dev,
					 DAVINCI_I2C_PM_TIMEOUT);
	pm_runtime_use_autosuspend(dev->dev);

	pm_runtime_enable(dev->dev);

	r = pm_runtime_get_sync(dev->dev);
	if (r < 0) {
		dev_err(dev->dev, "failed to runtime_get device: %d\n", r);
		pm_runtime_put_noidle(dev->dev);
		return r;
	}

	i2c_davinci_init(dev);

	r = devm_request_irq(&pdev->dev, dev->irq, i2c_davinci_isr, 0,
			pdev->name, dev);
	if (r) {
		dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq);
		goto err_unuse_clocks;
	}

	r = i2c_davinci_cpufreq_register(dev);
	if (r) {
		dev_err(&pdev->dev, "failed to register cpufreq\n");
		goto err_unuse_clocks;
	}

	adap = &dev->adapter;
	i2c_set_adapdata(adap, dev);
	adap->owner = THIS_MODULE;
	adap->class = I2C_CLASS_DEPRECATED;
	strlcpy(adap->name, "DaVinci I2C adapter", sizeof(adap->name));
	adap->algo = &i2c_davinci_algo;
	adap->dev.parent = &pdev->dev;
	adap->timeout = DAVINCI_I2C_TIMEOUT;
	adap->dev.of_node = pdev->dev.of_node;

	if (dev->pdata->has_pfunc)
		adap->bus_recovery_info = &davinci_i2c_scl_recovery_info;
	else if (dev->pdata->gpio_recovery) {
		rinfo =  &davinci_i2c_gpio_recovery_info;
		adap->bus_recovery_info = rinfo;
		rinfo->scl_gpiod = devm_gpiod_get(&pdev->dev, "scl",
						  GPIOD_OUT_HIGH_OPEN_DRAIN);
		if (IS_ERR(rinfo->scl_gpiod)) {
			r = PTR_ERR(rinfo->scl_gpiod);
			goto err_unuse_clocks;
		}
		rinfo->sda_gpiod = devm_gpiod_get(&pdev->dev, "sda", GPIOD_IN);
		if (IS_ERR(rinfo->sda_gpiod)) {
			r = PTR_ERR(rinfo->sda_gpiod);
			goto err_unuse_clocks;
		}
	}

	adap->nr = pdev->id;
	r = i2c_add_numbered_adapter(adap);
	if (r)
		goto err_unuse_clocks;

	pm_runtime_mark_last_busy(dev->dev);
	pm_runtime_put_autosuspend(dev->dev);

	return 0;

err_unuse_clocks:
	pm_runtime_dont_use_autosuspend(dev->dev);
	pm_runtime_put_sync(dev->dev);
	pm_runtime_disable(dev->dev);

	return r;
}