static int ds1wm_probe()

in masters/ds1wm.c [506:612]


static int ds1wm_probe(struct platform_device *pdev)
{
	struct ds1wm_data *ds1wm_data;
	struct ds1wm_driver_data *plat;
	struct resource *res;
	int ret;
	u8 inten;

	if (!pdev)
		return -ENODEV;

	ds1wm_data = devm_kzalloc(&pdev->dev, sizeof(*ds1wm_data), GFP_KERNEL);
	if (!ds1wm_data)
		return -ENOMEM;

	platform_set_drvdata(pdev, ds1wm_data);

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res)
		return -ENXIO;
	ds1wm_data->map = devm_ioremap(&pdev->dev, res->start,
				       resource_size(res));
	if (!ds1wm_data->map)
		return -ENOMEM;

	ds1wm_data->pdev = pdev;
	ds1wm_data->cell = mfd_get_cell(pdev);
	if (!ds1wm_data->cell)
		return -ENODEV;
	plat = dev_get_platdata(&pdev->dev);
	if (!plat)
		return -ENODEV;

	/* how many bits to shift register number to get register offset */
	if (plat->bus_shift > 2) {
		dev_err(&ds1wm_data->pdev->dev,
			"illegal bus shift %d, not written",
			ds1wm_data->bus_shift);
		return -EINVAL;
	}

	ds1wm_data->bus_shift = plat->bus_shift;
	/* make sure resource has space for 8 registers */
	if ((8 << ds1wm_data->bus_shift) > resource_size(res)) {
		dev_err(&ds1wm_data->pdev->dev,
			"memory resource size %d to small, should be %d\n",
			(int)resource_size(res),
			8 << ds1wm_data->bus_shift);
		return -EINVAL;
	}

	ds1wm_data->is_hw_big_endian = plat->is_hw_big_endian;

	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
	if (!res)
		return -ENXIO;
	ds1wm_data->irq = res->start;
	ds1wm_data->int_en_reg_none = (plat->active_high ? DS1WM_INTEN_IAS : 0);
	ds1wm_data->reset_recover_delay = plat->reset_recover_delay;

	/* Mask interrupts, set IAS before claiming interrupt */
	inten = ds1wm_read_register(ds1wm_data, DS1WM_INT_EN);
	ds1wm_write_register(ds1wm_data,
		DS1WM_INT_EN, ds1wm_data->int_en_reg_none);

	if (res->flags & IORESOURCE_IRQ_HIGHEDGE)
		irq_set_irq_type(ds1wm_data->irq, IRQ_TYPE_EDGE_RISING);
	if (res->flags & IORESOURCE_IRQ_LOWEDGE)
		irq_set_irq_type(ds1wm_data->irq, IRQ_TYPE_EDGE_FALLING);
	if (res->flags & IORESOURCE_IRQ_HIGHLEVEL)
		irq_set_irq_type(ds1wm_data->irq, IRQ_TYPE_LEVEL_HIGH);
	if (res->flags & IORESOURCE_IRQ_LOWLEVEL)
		irq_set_irq_type(ds1wm_data->irq, IRQ_TYPE_LEVEL_LOW);

	ret = devm_request_irq(&pdev->dev, ds1wm_data->irq, ds1wm_isr,
			IRQF_SHARED, "ds1wm", ds1wm_data);
	if (ret) {
		dev_err(&ds1wm_data->pdev->dev,
			"devm_request_irq %d failed with errno %d\n",
			ds1wm_data->irq,
			ret);

		return ret;
	}

	ds1wm_up(ds1wm_data);

	ds1wm_master.data = (void *)ds1wm_data;

	ret = w1_add_master_device(&ds1wm_master);
	if (ret)
		goto err;

	dev_dbg(&ds1wm_data->pdev->dev,
		"ds1wm: probe successful, IAS: %d, rec.delay: %d, clockrate: %d, bus-shift: %d, is Hw Big Endian: %d\n",
		plat->active_high,
		plat->reset_recover_delay,
		plat->clock_rate,
		ds1wm_data->bus_shift,
		ds1wm_data->is_hw_big_endian);
	return 0;

err:
	ds1wm_down(ds1wm_data);

	return ret;
}