Esempio n. 1
0
static int sc16is7xx_remove(struct device *dev)
{
	struct sc16is7xx_port *s = dev_get_drvdata(dev);
	int i, ret = 0;

#ifdef CONFIG_GPIOLIB
	if (s->devtype->nr_gpio) {
		ret = gpiochip_remove(&s->gpio);
		if (ret)
			return ret;
	}
#endif

	for (i = 0; i < s->uart.nr; i++) {
		cancel_work_sync(&s->p[i].tx_work);
		cancel_work_sync(&s->p[i].md_work);
		uart_remove_one_port(&s->uart, &s->p[i].port);
		sc16is7xx_power(&s->p[i].port, 0);
	}

	mutex_destroy(&s->mutex);
	uart_unregister_driver(&s->uart);
	if (!IS_ERR(s->clk))
		clk_disable_unprepare(s->clk);

	return ret;
}
Esempio n. 2
0
static void sc16is7xx_shutdown(struct uart_port *port)
{
	/* Disable all interrupts */
	sc16is7xx_port_write(port, SC16IS7XX_IER_REG, 0);
	/* Disable TX/RX */
	sc16is7xx_port_write(port, SC16IS7XX_EFCR_REG,
			     SC16IS7XX_EFCR_RXDISABLE_BIT |
			     SC16IS7XX_EFCR_TXDISABLE_BIT);

	sc16is7xx_power(port, 0);
}
Esempio n. 3
0
static int sc16is7xx_startup(struct uart_port *port)
{
	struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
	unsigned int val;

	sc16is7xx_power(port, 1);

	/* Reset FIFOs*/
	val = SC16IS7XX_FCR_RXRESET_BIT | SC16IS7XX_FCR_TXRESET_BIT;
	sc16is7xx_port_write(port, SC16IS7XX_FCR_REG, val);
	udelay(5);
	sc16is7xx_port_write(port, SC16IS7XX_FCR_REG,
			     SC16IS7XX_FCR_FIFO_BIT);

	/* Enable EFR */
	sc16is7xx_port_write(port, SC16IS7XX_LCR_REG,
			     SC16IS7XX_LCR_CONF_MODE_B);

	regcache_cache_bypass(s->regmap, true);

	/* Enable write access to enhanced features and internal clock div */
	sc16is7xx_port_write(port, SC16IS7XX_EFR_REG,
			     SC16IS7XX_EFR_ENABLE_BIT);

	/* Enable TCR/TLR */
	sc16is7xx_port_update(port, SC16IS7XX_MCR_REG,
			      SC16IS7XX_MCR_TCRTLR_BIT,
			      SC16IS7XX_MCR_TCRTLR_BIT);

	/* Configure flow control levels */
	/* Flow control halt level 48, resume level 24 */
	sc16is7xx_port_write(port, SC16IS7XX_TCR_REG,
			     SC16IS7XX_TCR_RX_RESUME(24) |
			     SC16IS7XX_TCR_RX_HALT(48));

	regcache_cache_bypass(s->regmap, false);

	/* Now, initialize the UART */
	sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, SC16IS7XX_LCR_WORD_LEN_8);

	/* Enable the Rx and Tx FIFO */
	sc16is7xx_port_update(port, SC16IS7XX_EFCR_REG,
			      SC16IS7XX_EFCR_RXDISABLE_BIT |
			      SC16IS7XX_EFCR_TXDISABLE_BIT,
			      0);

	/* Enable RX, TX, CTS change interrupts */
	val = SC16IS7XX_IER_RDI_BIT | SC16IS7XX_IER_THRI_BIT |
	      SC16IS7XX_IER_CTSI_BIT;
	sc16is7xx_port_write(port, SC16IS7XX_IER_REG, val);

	return 0;
}
Esempio n. 4
0
static void sc16is7xx_pm(struct uart_port *port, unsigned int state,
			 unsigned int oldstate)
{
	sc16is7xx_power(port, (state == UART_PM_STATE_ON) ? 1 : 0);
}
Esempio n. 5
0
static int sc16is7xx_probe(struct device *dev,
			   struct sc16is7xx_devtype *devtype,
			   struct regmap *regmap, int irq, unsigned long flags)
{
	unsigned long freq, *pfreq = dev_get_platdata(dev);
	int i, ret;
	struct sc16is7xx_port *s;

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

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

	s->clk = devm_clk_get(dev, NULL);
	if (IS_ERR(s->clk)) {
		if (pfreq)
			freq = *pfreq;
		else
			return PTR_ERR(s->clk);
	} else {
		freq = clk_get_rate(s->clk);
	}

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

	/* Register UART driver */
	s->uart.owner		= THIS_MODULE;
	s->uart.dev_name	= "ttySC";
	s->uart.nr		= devtype->nr_uart;
	ret = uart_register_driver(&s->uart);
	if (ret) {
		dev_err(dev, "Registering UART driver failed\n");
		goto out_clk;
	}

#ifdef CONFIG_GPIOLIB
	if (devtype->nr_gpio) {
		/* Setup GPIO cotroller */
		s->gpio.owner		 = THIS_MODULE;
		s->gpio.dev		 = 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(&s->gpio);
		if (ret)
			goto out_uart;
	}
#endif

	mutex_init(&s->mutex);

	for (i = 0; i < devtype->nr_uart; ++i) {
		/* Initialize port data */
		s->p[i].port.line	= i;
		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.iotype	= UPIO_PORT;
		s->p[i].port.uartclk	= freq;
		s->p[i].port.ops	= &sc16is7xx_ops;
		/* 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 queue for start TX */
		INIT_WORK(&s->p[i].tx_work, sc16is7xx_wq_proc);
		/* Initialize queue for changing mode */
		INIT_WORK(&s->p[i].md_work, sc16is7xx_md_proc);
		/* Register port */
		uart_add_one_port(&s->uart, &s->p[i].port);
		/* Go to suspend mode */
		sc16is7xx_power(&s->p[i].port, 0);
	}

	/* Setup interrupt */
	ret = devm_request_threaded_irq(dev, irq, NULL, sc16is7xx_ist,
					IRQF_ONESHOT | flags, dev_name(dev), s);
	if (!ret)
		return 0;

	mutex_destroy(&s->mutex);

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

out_uart:
#endif
	uart_unregister_driver(&s->uart);

out_clk:
	if (!IS_ERR(s->clk))
		clk_disable_unprepare(s->clk);

	return ret;
}