static int quad8_probe()

in 104-quad-8.c [1126:1201]


static int quad8_probe(struct device *dev, unsigned int id)
{
	struct counter_device *counter;
	struct quad8 *priv;
	int i, j;
	unsigned int base_offset;
	int err;

	if (!devm_request_region(dev, base[id], QUAD8_EXTENT, dev_name(dev))) {
		dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
			base[id], base[id] + QUAD8_EXTENT);
		return -EBUSY;
	}

	counter = devm_counter_alloc(dev, sizeof(*priv));
	if (!counter)
		return -ENOMEM;
	priv = counter_priv(counter);

	/* Initialize Counter device and driver data */
	counter->name = dev_name(dev);
	counter->parent = dev;
	counter->ops = &quad8_ops;
	counter->counts = quad8_counts;
	counter->num_counts = ARRAY_SIZE(quad8_counts);
	counter->signals = quad8_signals;
	counter->num_signals = ARRAY_SIZE(quad8_signals);
	priv->base = base[id];

	spin_lock_init(&priv->lock);

	/* Reset Index/Interrupt Register */
	outb(0x00, base[id] + QUAD8_REG_INDEX_INTERRUPT);
	/* Reset all counters and disable interrupt function */
	outb(QUAD8_CHAN_OP_RESET_COUNTERS, base[id] + QUAD8_REG_CHAN_OP);
	/* Set initial configuration for all counters */
	for (i = 0; i < QUAD8_NUM_COUNTERS; i++) {
		base_offset = base[id] + 2 * i;
		/* Reset Byte Pointer */
		outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
		/* Reset filter clock factor */
		outb(0, base_offset);
		outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_PRESET_PSC,
		     base_offset + 1);
		/* Reset Byte Pointer */
		outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
		/* Reset Preset Register */
		for (j = 0; j < 3; j++)
			outb(0x00, base_offset);
		/* Reset Borrow, Carry, Compare, and Sign flags */
		outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_FLAGS, base_offset + 1);
		/* Reset Error flag */
		outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, base_offset + 1);
		/* Binary encoding; Normal count; non-quadrature mode */
		outb(QUAD8_CTR_CMR, base_offset + 1);
		/* Disable A and B inputs; preset on index; FLG1 as Carry */
		outb(QUAD8_CTR_IOR, base_offset + 1);
		/* Disable index function; negative index polarity */
		outb(QUAD8_CTR_IDR, base_offset + 1);
	}
	/* Disable Differential Encoder Cable Status for all channels */
	outb(0xFF, base[id] + QUAD8_DIFF_ENCODER_CABLE_STATUS);
	/* Enable all counters and enable interrupt function */
	outb(QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC, base[id] + QUAD8_REG_CHAN_OP);

	err = devm_request_irq(&counter->dev, irq[id], quad8_irq_handler,
			       IRQF_SHARED, counter->name, counter);
	if (err)
		return err;

	err = devm_counter_add(dev, counter);
	if (err < 0)
		return dev_err_probe(dev, err, "Failed to add counter\n");

	return 0;
}