static int sc16is7xx_probe()

in serial/sc16is7xx.c [1178:1366]


static int sc16is7xx_probe(struct device *dev,
			   const struct sc16is7xx_devtype *devtype,
			   struct regmap *regmap, int irq)
{
	unsigned long freq = 0, *pfreq = dev_get_platdata(dev);
	unsigned int val;
	u32 uartclk = 0;
	int i, ret;
	struct sc16is7xx_port *s;

	if (IS_ERR(regmap))
		return PTR_ERR(regmap);

	/*
	 * This device does not have an identification register that would
	 * tell us if we are really connected to the correct device.
	 * The best we can do is to check if communication is at all possible.
	 */
	ret = regmap_read(regmap,
			  SC16IS7XX_LSR_REG << SC16IS7XX_REG_SHIFT, &val);
	if (ret < 0)
		return -EPROBE_DEFER;

	/* Alloc port structure */
	s = devm_kzalloc(dev, struct_size(s, p, devtype->nr_uart), GFP_KERNEL);
	if (!s) {
		dev_err(dev, "Error allocating port structure\n");
		return -ENOMEM;
	}

	/* Always ask for fixed clock rate from a property. */
	device_property_read_u32(dev, "clock-frequency", &uartclk);

	s->clk = devm_clk_get_optional(dev, NULL);
	if (IS_ERR(s->clk))
		return PTR_ERR(s->clk);

	ret = clk_prepare_enable(s->clk);
	if (ret)
		return ret;

	freq = clk_get_rate(s->clk);
	if (freq == 0) {
		if (uartclk)
			freq = uartclk;
		if (pfreq)
			freq = *pfreq;
		if (freq)
			dev_dbg(dev, "Clock frequency: %luHz\n", freq);
		else
			return -EINVAL;
	}

	s->regmap = regmap;
	s->devtype = devtype;
	dev_set_drvdata(dev, s);
	mutex_init(&s->efr_lock);

	kthread_init_worker(&s->kworker);
	s->kworker_task = kthread_run(kthread_worker_fn, &s->kworker,
				      "sc16is7xx");
	if (IS_ERR(s->kworker_task)) {
		ret = PTR_ERR(s->kworker_task);
		goto out_clk;
	}
	sched_set_fifo(s->kworker_task);

#ifdef CONFIG_GPIOLIB
	if (devtype->nr_gpio) {
		/* Setup GPIO cotroller */
		s->gpio.owner		 = THIS_MODULE;
		s->gpio.parent		 = dev;
		s->gpio.label		 = dev_name(dev);
		s->gpio.direction_input	 = sc16is7xx_gpio_direction_input;
		s->gpio.get		 = sc16is7xx_gpio_get;
		s->gpio.direction_output = sc16is7xx_gpio_direction_output;
		s->gpio.set		 = sc16is7xx_gpio_set;
		s->gpio.base		 = -1;
		s->gpio.ngpio		 = devtype->nr_gpio;
		s->gpio.can_sleep	 = 1;
		ret = gpiochip_add_data(&s->gpio, s);
		if (ret)
			goto out_thread;
	}
#endif

	/* reset device, purging any pending irq / data */
	regmap_write(s->regmap, SC16IS7XX_IOCONTROL_REG << SC16IS7XX_REG_SHIFT,
			SC16IS7XX_IOCONTROL_SRESET_BIT);

	for (i = 0; i < devtype->nr_uart; ++i) {
		s->p[i].line		= i;
		/* Initialize port data */
		s->p[i].port.dev	= dev;
		s->p[i].port.irq	= irq;
		s->p[i].port.type	= PORT_SC16IS7XX;
		s->p[i].port.fifosize	= SC16IS7XX_FIFO_SIZE;
		s->p[i].port.flags	= UPF_FIXED_TYPE | UPF_LOW_LATENCY;
		s->p[i].port.iobase	= i;
		s->p[i].port.iotype	= UPIO_PORT;
		s->p[i].port.uartclk	= freq;
		s->p[i].port.rs485_config = sc16is7xx_config_rs485;
		s->p[i].port.ops	= &sc16is7xx_ops;
		s->p[i].port.line	= sc16is7xx_alloc_line();
		if (s->p[i].port.line >= SC16IS7XX_MAX_DEVS) {
			ret = -ENOMEM;
			goto out_ports;
		}

		/* Disable all interrupts */
		sc16is7xx_port_write(&s->p[i].port, SC16IS7XX_IER_REG, 0);
		/* Disable TX/RX */
		sc16is7xx_port_write(&s->p[i].port, SC16IS7XX_EFCR_REG,
				     SC16IS7XX_EFCR_RXDISABLE_BIT |
				     SC16IS7XX_EFCR_TXDISABLE_BIT);
		/* Initialize kthread work structs */
		kthread_init_work(&s->p[i].tx_work, sc16is7xx_tx_proc);
		kthread_init_work(&s->p[i].reg_work, sc16is7xx_reg_proc);
		/* Register port */
		uart_add_one_port(&sc16is7xx_uart, &s->p[i].port);

		/* Enable EFR */
		sc16is7xx_port_write(&s->p[i].port, SC16IS7XX_LCR_REG,
				     SC16IS7XX_LCR_CONF_MODE_B);

		regcache_cache_bypass(s->regmap, true);

		/* Enable write access to enhanced features */
		sc16is7xx_port_write(&s->p[i].port, SC16IS7XX_EFR_REG,
				     SC16IS7XX_EFR_ENABLE_BIT);

		regcache_cache_bypass(s->regmap, false);

		/* Restore access to general registers */
		sc16is7xx_port_write(&s->p[i].port, SC16IS7XX_LCR_REG, 0x00);

		/* Go to suspend mode */
		sc16is7xx_power(&s->p[i].port, 0);
	}

	if (dev->of_node) {
		struct property *prop;
		const __be32 *p;
		u32 u;

		of_property_for_each_u32(dev->of_node, "irda-mode-ports",
					 prop, p, u)
			if (u < devtype->nr_uart)
				s->p[u].irda_mode = true;
	}

	/*
	 * Setup interrupt. We first try to acquire the IRQ line as level IRQ.
	 * If that succeeds, we can allow sharing the interrupt as well.
	 * In case the interrupt controller doesn't support that, we fall
	 * back to a non-shared falling-edge trigger.
	 */
	ret = devm_request_threaded_irq(dev, irq, NULL, sc16is7xx_irq,
					IRQF_TRIGGER_LOW | IRQF_SHARED |
					IRQF_ONESHOT,
					dev_name(dev), s);
	if (!ret)
		return 0;

	ret = devm_request_threaded_irq(dev, irq, NULL, sc16is7xx_irq,
					IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
					dev_name(dev), s);
	if (!ret)
		return 0;

out_ports:
	for (i--; i >= 0; i--) {
		uart_remove_one_port(&sc16is7xx_uart, &s->p[i].port);
		clear_bit(s->p[i].port.line, &sc16is7xx_lines);
	}

#ifdef CONFIG_GPIOLIB
	if (devtype->nr_gpio)
		gpiochip_remove(&s->gpio);

out_thread:
#endif
	kthread_stop(s->kworker_task);

out_clk:
	clk_disable_unprepare(s->clk);

	return ret;
}