diff options
Diffstat (limited to 'drivers/tty')
39 files changed, 574 insertions, 386 deletions
| diff --git a/drivers/tty/Kconfig b/drivers/tty/Kconfig index cc2b4d9433ed..b811442c5ce6 100644 --- a/drivers/tty/Kconfig +++ b/drivers/tty/Kconfig @@ -394,10 +394,14 @@ config GOLDFISH_TTY  	depends on GOLDFISH  	select SERIAL_CORE  	select SERIAL_CORE_CONSOLE -	select SERIAL_EARLYCON  	help  	  Console and system TTY driver for the Goldfish virtual platform. +config GOLDFISH_TTY_EARLY_CONSOLE +	bool +	default y if GOLDFISH_TTY=y +	select SERIAL_EARLYCON +  config DA_TTY  	bool "DA TTY"  	depends on METAG_DA diff --git a/drivers/tty/goldfish.c b/drivers/tty/goldfish.c index 7f657bb5113c..1c1bd0afcd48 100644 --- a/drivers/tty/goldfish.c +++ b/drivers/tty/goldfish.c @@ -433,6 +433,7 @@ static int goldfish_tty_remove(struct platform_device *pdev)  	return 0;  } +#ifdef CONFIG_GOLDFISH_TTY_EARLY_CONSOLE  static void gf_early_console_putchar(struct uart_port *port, int ch)  {  	__raw_writel(ch, port->membase); @@ -456,6 +457,7 @@ static int __init gf_earlycon_setup(struct earlycon_device *device,  }  OF_EARLYCON_DECLARE(early_gf_tty, "google,goldfish-tty", gf_earlycon_setup); +#endif  static const struct of_device_id goldfish_tty_of_match[] = {  	{ .compatible = "google,goldfish-tty", }, diff --git a/drivers/tty/isicom.c b/drivers/tty/isicom.c index 015686ff4825..bdd3027ef01b 100644 --- a/drivers/tty/isicom.c +++ b/drivers/tty/isicom.c @@ -219,13 +219,9 @@ static struct isi_port  isi_ports[PORT_COUNT];  static int WaitTillCardIsFree(unsigned long base)  {  	unsigned int count = 0; -	unsigned int a = in_atomic(); /* do we run under spinlock? */  	while (!(inw(base + 0xe) & 0x1) && count++ < 100) -		if (a) -			mdelay(1); -		else -			msleep(1); +		mdelay(1);  	return !(inw(base + 0xe) & 0x1);  } diff --git a/drivers/tty/moxa.c b/drivers/tty/moxa.c index 68cbc03aab4b..250a19f042d7 100644 --- a/drivers/tty/moxa.c +++ b/drivers/tty/moxa.c @@ -1487,8 +1487,6 @@ static void moxa_set_tty_param(struct tty_struct *tty, struct ktermios *old_term  	if (ts->c_iflag & IXANY)  		xany = 1; -	/* Clear the features we don't support */ -	ts->c_cflag &= ~CMSPAR;  	MoxaPortFlowCtrl(ch, rts, cts, txflow, rxflow, xany);  	baud = MoxaPortSetTermio(ch, ts, tty_get_baud_rate(tty));  	if (baud == -1) @@ -1781,10 +1779,17 @@ static int MoxaPortSetTermio(struct moxa_port *port, struct ktermios *termio,  		mode |= MX_STOP1;  	if (termio->c_cflag & PARENB) { -		if (termio->c_cflag & PARODD) -			mode |= MX_PARODD; -		else -			mode |= MX_PAREVEN; +		if (termio->c_cflag & PARODD) { +			if (termio->c_cflag & CMSPAR) +				mode |= MX_PARMARK; +			else +				mode |= MX_PARODD; +		} else { +			if (termio->c_cflag & CMSPAR) +				mode |= MX_PARSPACE; +			else +				mode |= MX_PAREVEN; +		}  	} else  		mode |= MX_PARNONE; diff --git a/drivers/tty/moxa.h b/drivers/tty/moxa.h index 8ce89fd36c7b..563d2dce80b3 100644 --- a/drivers/tty/moxa.h +++ b/drivers/tty/moxa.h @@ -301,5 +301,7 @@  #define	MX_PARNONE	0x00  #define	MX_PAREVEN	0x40  #define	MX_PARODD	0xC0 +#define	MX_PARMARK	0xA0 +#define	MX_PARSPACE	0x20  #endif diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index 5131bdc9e765..3b3e1f6632d7 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -1451,6 +1451,10 @@ static void gsm_dlci_open(struct gsm_dlci *dlci)   *	in which case an opening port goes back to closed and a closing port   *	is simply put into closed state (any further frames from the other   *	end will get a DM response) + * + *	Some control dlci can stay in ADM mode with other dlci working just + *	fine. In that case we can just keep the control dlci open after the + *	DLCI_OPENING retries time out.   */  static void gsm_dlci_t1(struct timer_list *t) @@ -1464,8 +1468,15 @@ static void gsm_dlci_t1(struct timer_list *t)  		if (dlci->retries) {  			gsm_command(dlci->gsm, dlci->addr, SABM|PF);  			mod_timer(&dlci->t1, jiffies + gsm->t1 * HZ / 100); -		} else +		} else if (!dlci->addr && gsm->control == (DM | PF)) { +			if (debug & 8) +				pr_info("DLCI %d opening in ADM mode.\n", +					dlci->addr); +			gsm_dlci_open(dlci); +		} else {  			gsm_dlci_close(dlci); +		} +  		break;  	case DLCI_CLOSING:  		dlci->retries--; @@ -1483,8 +1494,8 @@ static void gsm_dlci_t1(struct timer_list *t)   *	@dlci: DLCI to open   *   *	Commence opening a DLCI from the Linux side. We issue SABM messages - *	to the modem which should then reply with a UA, at which point we - *	will move into open state. Opening is done asynchronously with retry + *	to the modem which should then reply with a UA or ADM, at which point + *	we will move into open state. Opening is done asynchronously with retry   *	running off timers and the responses.   */ @@ -2457,20 +2468,20 @@ static ssize_t gsmld_write(struct tty_struct *tty, struct file *file,   *	Called without the kernel lock held - fine   */ -static unsigned int gsmld_poll(struct tty_struct *tty, struct file *file, +static __poll_t gsmld_poll(struct tty_struct *tty, struct file *file,  							poll_table *wait)  { -	unsigned int mask = 0; +	__poll_t mask = 0;  	struct gsm_mux *gsm = tty->disc_data;  	poll_wait(file, &tty->read_wait, wait);  	poll_wait(file, &tty->write_wait, wait);  	if (tty_hung_up_p(file)) -		mask |= POLLHUP; +		mask |= EPOLLHUP;  	if (!tty_is_writelocked(tty) && tty_write_room(tty) > 0) -		mask |= POLLOUT | POLLWRNORM; +		mask |= EPOLLOUT | EPOLLWRNORM;  	if (gsm->dead) -		mask |= POLLHUP; +		mask |= EPOLLHUP;  	return mask;  } @@ -2955,7 +2966,6 @@ static int gsmtty_open(struct tty_struct *tty, struct file *filp)  static void gsmtty_close(struct tty_struct *tty, struct file *filp)  {  	struct gsm_dlci *dlci = tty->driver_data; -	struct gsm_mux *gsm;  	if (dlci == NULL)  		return; @@ -2964,7 +2974,6 @@ static void gsmtty_close(struct tty_struct *tty, struct file *filp)  	mutex_lock(&dlci->mutex);  	gsm_destroy_network(dlci);  	mutex_unlock(&dlci->mutex); -	gsm = dlci->gsm;  	if (tty_port_close_start(&dlci->port, tty, filp) == 0)  		return;  	gsm_dlci_begin_close(dlci); diff --git a/drivers/tty/n_hdlc.c b/drivers/tty/n_hdlc.c index eea7b6cb3cc4..dabb391909aa 100644 --- a/drivers/tty/n_hdlc.c +++ b/drivers/tty/n_hdlc.c @@ -180,7 +180,7 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file,  			    const unsigned char *buf, size_t nr);  static int n_hdlc_tty_ioctl(struct tty_struct *tty, struct file *file,  			    unsigned int cmd, unsigned long arg); -static unsigned int n_hdlc_tty_poll(struct tty_struct *tty, struct file *filp, +static __poll_t n_hdlc_tty_poll(struct tty_struct *tty, struct file *filp,  				    poll_table *wait);  static int n_hdlc_tty_open(struct tty_struct *tty);  static void n_hdlc_tty_close(struct tty_struct *tty); @@ -796,11 +796,11 @@ static int n_hdlc_tty_ioctl(struct tty_struct *tty, struct file *file,   * to caller.   * Returns a bit mask containing info on which ops will not block.   */ -static unsigned int n_hdlc_tty_poll(struct tty_struct *tty, struct file *filp, +static __poll_t n_hdlc_tty_poll(struct tty_struct *tty, struct file *filp,  				    poll_table *wait)  {  	struct n_hdlc *n_hdlc = tty2n_hdlc (tty); -	unsigned int mask = 0; +	__poll_t mask = 0;  	if (debuglevel >= DEBUG_LEVEL_INFO)	  		printk("%s(%d)n_hdlc_tty_poll() called\n",__FILE__,__LINE__); @@ -814,14 +814,14 @@ static unsigned int n_hdlc_tty_poll(struct tty_struct *tty, struct file *filp,  		/* set bits for operations that won't block */  		if (!list_empty(&n_hdlc->rx_buf_list.list)) -			mask |= POLLIN | POLLRDNORM;	/* readable */ +			mask |= EPOLLIN | EPOLLRDNORM;	/* readable */  		if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) -			mask |= POLLHUP; +			mask |= EPOLLHUP;  		if (tty_hung_up_p(filp)) -			mask |= POLLHUP; +			mask |= EPOLLHUP;  		if (!tty_is_writelocked(tty) &&  				!list_empty(&n_hdlc->tx_free_buf_list.list)) -			mask |= POLLOUT | POLLWRNORM;	/* writable */ +			mask |= EPOLLOUT | EPOLLWRNORM;	/* writable */  	}  	return mask;  }	/* end of n_hdlc_tty_poll() */ diff --git a/drivers/tty/n_r3964.c b/drivers/tty/n_r3964.c index 30bb0900cd2f..dbf1ab36758e 100644 --- a/drivers/tty/n_r3964.c +++ b/drivers/tty/n_r3964.c @@ -135,7 +135,7 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file,  static int r3964_ioctl(struct tty_struct *tty, struct file *file,  		unsigned int cmd, unsigned long arg);  static void r3964_set_termios(struct tty_struct *tty, struct ktermios *old); -static unsigned int r3964_poll(struct tty_struct *tty, struct file *file, +static __poll_t r3964_poll(struct tty_struct *tty, struct file *file,  		struct poll_table_struct *wait);  static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp,  		char *fp, int count); @@ -1216,14 +1216,14 @@ static void r3964_set_termios(struct tty_struct *tty, struct ktermios *old)  }  /* Called without the kernel lock held - fine */ -static unsigned int r3964_poll(struct tty_struct *tty, struct file *file, +static __poll_t r3964_poll(struct tty_struct *tty, struct file *file,  			struct poll_table_struct *wait)  {  	struct r3964_info *pInfo = tty->disc_data;  	struct r3964_client_info *pClient;  	struct r3964_message *pMsg = NULL;  	unsigned long flags; -	int result = POLLOUT; +	__poll_t result = EPOLLOUT;  	TRACE_L("POLL"); @@ -1234,7 +1234,7 @@ static unsigned int r3964_poll(struct tty_struct *tty, struct file *file,  		pMsg = pClient->first_msg;  		spin_unlock_irqrestore(&pInfo->lock, flags);  		if (pMsg) -			result |= POLLIN | POLLRDNORM; +			result |= EPOLLIN | EPOLLRDNORM;  	} else {  		result = -EINVAL;  	} diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 539b49adb6af..5c0e59e8fe46 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1344,7 +1344,7 @@ handle_newline:  			put_tty_queue(c, ldata);  			smp_store_release(&ldata->canon_head, ldata->read_head);  			kill_fasync(&tty->fasync, SIGIO, POLL_IN); -			wake_up_interruptible_poll(&tty->read_wait, POLLIN); +			wake_up_interruptible_poll(&tty->read_wait, EPOLLIN);  			return 0;  		}  	} @@ -1625,7 +1625,7 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp,  	if (read_cnt(ldata)) {  		kill_fasync(&tty->fasync, SIGIO, POLL_IN); -		wake_up_interruptible_poll(&tty->read_wait, POLLIN); +		wake_up_interruptible_poll(&tty->read_wait, EPOLLIN);  	}  } @@ -2368,30 +2368,30 @@ break_out:   *	Called without the kernel lock held - fine   */ -static unsigned int n_tty_poll(struct tty_struct *tty, struct file *file, +static __poll_t n_tty_poll(struct tty_struct *tty, struct file *file,  							poll_table *wait)  { -	unsigned int mask = 0; +	__poll_t mask = 0;  	poll_wait(file, &tty->read_wait, wait);  	poll_wait(file, &tty->write_wait, wait);  	if (input_available_p(tty, 1)) -		mask |= POLLIN | POLLRDNORM; +		mask |= EPOLLIN | EPOLLRDNORM;  	else {  		tty_buffer_flush_work(tty->port);  		if (input_available_p(tty, 1)) -			mask |= POLLIN | POLLRDNORM; +			mask |= EPOLLIN | EPOLLRDNORM;  	}  	if (tty->packet && tty->link->ctrl_status) -		mask |= POLLPRI | POLLIN | POLLRDNORM; +		mask |= EPOLLPRI | EPOLLIN | EPOLLRDNORM;  	if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) -		mask |= POLLHUP; +		mask |= EPOLLHUP;  	if (tty_hung_up_p(file)) -		mask |= POLLHUP; +		mask |= EPOLLHUP;  	if (tty->ops->write && !tty_is_writelocked(tty) &&  			tty_chars_in_buffer(tty) < WAKEUP_CHARS &&  			tty_write_room(tty) > 0) -		mask |= POLLOUT | POLLWRNORM; +		mask |= EPOLLOUT | EPOLLWRNORM;  	return mask;  } diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index 64338442050e..6c7151edd715 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c @@ -344,7 +344,7 @@ static void pty_start(struct tty_struct *tty)  		tty->ctrl_status &= ~TIOCPKT_STOP;  		tty->ctrl_status |= TIOCPKT_START;  		spin_unlock_irqrestore(&tty->ctrl_lock, flags); -		wake_up_interruptible_poll(&tty->link->read_wait, POLLIN); +		wake_up_interruptible_poll(&tty->link->read_wait, EPOLLIN);  	}  } @@ -357,7 +357,7 @@ static void pty_stop(struct tty_struct *tty)  		tty->ctrl_status &= ~TIOCPKT_START;  		tty->ctrl_status |= TIOCPKT_STOP;  		spin_unlock_irqrestore(&tty->ctrl_lock, flags); -		wake_up_interruptible_poll(&tty->link->read_wait, POLLIN); +		wake_up_interruptible_poll(&tty->link->read_wait, EPOLLIN);  	}  } diff --git a/drivers/tty/serdev/core.c b/drivers/tty/serdev/core.c index 1bef39828ca7..f439c72b9e3c 100644 --- a/drivers/tty/serdev/core.c +++ b/drivers/tty/serdev/core.c @@ -19,6 +19,38 @@  static bool is_registered;  static DEFINE_IDA(ctrl_ida); +static ssize_t modalias_show(struct device *dev, +			     struct device_attribute *attr, char *buf) +{ +	int len; + +	len = acpi_device_modalias(dev, buf, PAGE_SIZE - 1); +	if (len != -ENODEV) +		return len; + +	return of_device_modalias(dev, buf, PAGE_SIZE); +} +static DEVICE_ATTR_RO(modalias); + +static struct attribute *serdev_device_attrs[] = { +	&dev_attr_modalias.attr, +	NULL, +}; +ATTRIBUTE_GROUPS(serdev_device); + +static int serdev_device_uevent(struct device *dev, struct kobj_uevent_env *env) +{ +	int rc; + +	/* TODO: platform modalias */ + +	rc = acpi_device_uevent_modalias(dev, env); +	if (rc != -ENODEV) +		return rc; + +	return of_device_uevent_modalias(dev, env); +} +  static void serdev_device_release(struct device *dev)  {  	struct serdev_device *serdev = to_serdev_device(dev); @@ -26,9 +58,16 @@ static void serdev_device_release(struct device *dev)  }  static const struct device_type serdev_device_type = { +	.groups		= serdev_device_groups, +	.uevent		= serdev_device_uevent,  	.release	= serdev_device_release,  }; +static bool is_serdev_device(const struct device *dev) +{ +	return dev->type == &serdev_device_type; +} +  static void serdev_ctrl_release(struct device *dev)  {  	struct serdev_controller *ctrl = to_serdev_controller(dev); @@ -42,6 +81,9 @@ static const struct device_type serdev_ctrl_type = {  static int serdev_device_match(struct device *dev, struct device_driver *drv)  { +	if (!is_serdev_device(dev)) +		return 0; +  	/* TODO: platform matching */  	if (acpi_driver_match_device(dev, drv))  		return 1; @@ -49,18 +91,6 @@ static int serdev_device_match(struct device *dev, struct device_driver *drv)  	return of_driver_match_device(dev, drv);  } -static int serdev_uevent(struct device *dev, struct kobj_uevent_env *env) -{ -	int rc; - -	/* TODO: platform modalias */ -	rc = acpi_device_uevent_modalias(dev, env); -	if (rc != -ENODEV) -		return rc; - -	return of_device_uevent_modalias(dev, env); -} -  /**   * serdev_device_add() - add a device previously constructed via serdev_device_alloc()   * @serdev:	serdev_device to be added @@ -132,6 +162,33 @@ void serdev_device_close(struct serdev_device *serdev)  }  EXPORT_SYMBOL_GPL(serdev_device_close); +static void devm_serdev_device_release(struct device *dev, void *dr) +{ +	serdev_device_close(*(struct serdev_device **)dr); +} + +int devm_serdev_device_open(struct device *dev, struct serdev_device *serdev) +{ +	struct serdev_device **dr; +	int ret; + +	dr = devres_alloc(devm_serdev_device_release, sizeof(*dr), GFP_KERNEL); +	if (!dr) +		return -ENOMEM; + +	ret = serdev_device_open(serdev); +	if (ret) { +		devres_free(dr); +		return ret; +	} + +	*dr = serdev; +	devres_add(dev, dr); + +	return 0; +} +EXPORT_SYMBOL_GPL(devm_serdev_device_open); +  void serdev_device_write_wakeup(struct serdev_device *serdev)  {  	complete(&serdev->write_comp); @@ -225,6 +282,18 @@ void serdev_device_set_flow_control(struct serdev_device *serdev, bool enable)  }  EXPORT_SYMBOL_GPL(serdev_device_set_flow_control); +int serdev_device_set_parity(struct serdev_device *serdev, +			     enum serdev_parity parity) +{ +	struct serdev_controller *ctrl = serdev->ctrl; + +	if (!ctrl || !ctrl->ops->set_parity) +		return -ENOTSUPP; + +	return ctrl->ops->set_parity(ctrl, parity); +} +EXPORT_SYMBOL_GPL(serdev_device_set_parity); +  void serdev_device_wait_until_sent(struct serdev_device *serdev, long timeout)  {  	struct serdev_controller *ctrl = serdev->ctrl; @@ -268,37 +337,16 @@ static int serdev_drv_probe(struct device *dev)  static int serdev_drv_remove(struct device *dev)  {  	const struct serdev_device_driver *sdrv = to_serdev_device_driver(dev->driver); - -	sdrv->remove(to_serdev_device(dev)); +	if (sdrv->remove) +		sdrv->remove(to_serdev_device(dev));  	return 0;  } -static ssize_t modalias_show(struct device *dev, -			     struct device_attribute *attr, char *buf) -{ -	int len; - -	len = acpi_device_modalias(dev, buf, PAGE_SIZE - 1); -	if (len != -ENODEV) -		return len; - -	return of_device_modalias(dev, buf, PAGE_SIZE); -} -DEVICE_ATTR_RO(modalias); - -static struct attribute *serdev_device_attrs[] = { -	&dev_attr_modalias.attr, -	NULL, -}; -ATTRIBUTE_GROUPS(serdev_device); -  static struct bus_type serdev_bus_type = {  	.name		= "serial",  	.match		= serdev_device_match,  	.probe		= serdev_drv_probe,  	.remove		= serdev_drv_remove, -	.uevent		= serdev_uevent, -	.dev_groups	= serdev_device_groups,  };  /** diff --git a/drivers/tty/serdev/serdev-ttyport.c b/drivers/tty/serdev/serdev-ttyport.c index 247788a16f0b..fa1672993b4c 100644 --- a/drivers/tty/serdev/serdev-ttyport.c +++ b/drivers/tty/serdev/serdev-ttyport.c @@ -59,7 +59,8 @@ static void ttyport_write_wakeup(struct tty_port *port)  	    test_bit(SERPORT_ACTIVE, &serport->flags))  		serdev_controller_write_wakeup(ctrl); -	wake_up_interruptible_poll(&tty->write_wait, POLLOUT); +	/* Wake up any tty_wait_until_sent() */ +	wake_up_interruptible(&tty->write_wait);  	tty_kref_put(tty);  } @@ -122,6 +123,8 @@ static int ttyport_open(struct serdev_controller *ctrl)  	if (ret)  		goto err_close; +	tty_unlock(serport->tty); +  	/* Bring the UART into a known 8 bits no parity hw fc state */  	ktermios = tty->termios;  	ktermios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | @@ -131,11 +134,12 @@ static int ttyport_open(struct serdev_controller *ctrl)  	ktermios.c_cflag &= ~(CSIZE | PARENB);  	ktermios.c_cflag |= CS8;  	ktermios.c_cflag |= CRTSCTS; +	/* Hangups are not supported so make sure to ignore carrier detect. */ +	ktermios.c_cflag |= CLOCAL;  	tty_set_termios(tty, &ktermios);  	set_bit(SERPORT_ACTIVE, &serport->flags); -	tty_unlock(serport->tty);  	return 0;  err_close: @@ -190,6 +194,29 @@ static void ttyport_set_flow_control(struct serdev_controller *ctrl, bool enable  	tty_set_termios(tty, &ktermios);  } +static int ttyport_set_parity(struct serdev_controller *ctrl, +			      enum serdev_parity parity) +{ +	struct serport *serport = serdev_controller_get_drvdata(ctrl); +	struct tty_struct *tty = serport->tty; +	struct ktermios ktermios = tty->termios; + +	ktermios.c_cflag &= ~(PARENB | PARODD | CMSPAR); +	if (parity != SERDEV_PARITY_NONE) { +		ktermios.c_cflag |= PARENB; +		if (parity == SERDEV_PARITY_ODD) +			ktermios.c_cflag |= PARODD; +	} + +	tty_set_termios(tty, &ktermios); + +	if ((tty->termios.c_cflag & (PARENB | PARODD | CMSPAR)) != +	    (ktermios.c_cflag & (PARENB | PARODD | CMSPAR))) +		return -EINVAL; + +	return 0; +} +  static void ttyport_wait_until_sent(struct serdev_controller *ctrl, long timeout)  {  	struct serport *serport = serdev_controller_get_drvdata(ctrl); @@ -227,6 +254,7 @@ static const struct serdev_controller_ops ctrl_ops = {  	.open = ttyport_open,  	.close = ttyport_close,  	.set_flow_control = ttyport_set_flow_control, +	.set_parity = ttyport_set_parity,  	.set_baudrate = ttyport_set_baudrate,  	.wait_until_sent = ttyport_wait_until_sent,  	.get_tiocm = ttyport_get_tiocm, diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index 5bb0c42c88dd..cd1b94a0f451 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -252,31 +252,25 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios,  			       struct ktermios *old)  {  	unsigned int baud = tty_termios_baud_rate(termios); -	unsigned int target_rate, min_rate, max_rate;  	struct dw8250_data *d = p->private_data;  	long rate; -	int i, ret; +	int ret;  	if (IS_ERR(d->clk) || !old)  		goto out; -	/* Find a clk rate within +/-1.6% of an integer multiple of baudx16 */ -	target_rate = baud * 16; -	min_rate = target_rate - (target_rate >> 6); -	max_rate = target_rate + (target_rate >> 6); - -	for (i = 1; i <= UART_DIV_MAX; i++) { -		rate = clk_round_rate(d->clk, i * target_rate); -		if (rate >= i * min_rate && rate <= i * max_rate) -			break; -	} -	if (i <= UART_DIV_MAX) { -		clk_disable_unprepare(d->clk); +	clk_disable_unprepare(d->clk); +	rate = clk_round_rate(d->clk, baud * 16); +	if (rate < 0) +		ret = rate; +	else if (rate == 0) +		ret = -ENOENT; +	else  		ret = clk_set_rate(d->clk, rate); -		clk_prepare_enable(d->clk); -		if (!ret) -			p->uartclk = rate; -	} +	clk_prepare_enable(d->clk); + +	if (!ret) +		p->uartclk = rate;  out:  	p->status &= ~UPSTAT_AUTOCTS; @@ -515,7 +509,8 @@ static int dw8250_probe(struct platform_device *pdev)  	/* If no clock rate is defined, fail. */  	if (!p->uartclk) {  		dev_err(dev, "clock rate not defined\n"); -		return -EINVAL; +		err = -EINVAL; +		goto err_clk;  	}  	data->pclk = devm_clk_get(dev, "apb_pclk"); diff --git a/drivers/tty/serial/8250/8250_exar.c b/drivers/tty/serial/8250/8250_exar.c index a402878c9f30..38af306ca0e8 100644 --- a/drivers/tty/serial/8250/8250_exar.c +++ b/drivers/tty/serial/8250/8250_exar.c @@ -34,6 +34,7 @@  #define PCI_DEVICE_ID_EXAR_XR17V4358		0x4358  #define PCI_DEVICE_ID_EXAR_XR17V8358		0x8358 +#define UART_EXAR_INT0		0x80  #define UART_EXAR_8XMODE	0x88	/* 8X sampling rate select */  #define UART_EXAR_FCTR		0x08	/* Feature Control Register */ @@ -121,6 +122,7 @@ struct exar8250_board {  struct exar8250 {  	unsigned int		nr;  	struct exar8250_board	*board; +	void __iomem		*virt;  	int			line[0];  }; @@ -131,12 +133,9 @@ static int default_setup(struct exar8250 *priv, struct pci_dev *pcidev,  	const struct exar8250_board *board = priv->board;  	unsigned int bar = 0; -	if (!pcim_iomap_table(pcidev)[bar] && !pcim_iomap(pcidev, bar, 0)) -		return -ENOMEM; -  	port->port.iotype = UPIO_MEM;  	port->port.mapbase = pci_resource_start(pcidev, bar) + offset; -	port->port.membase = pcim_iomap_table(pcidev)[bar] + offset; +	port->port.membase = priv->virt + offset;  	port->port.regshift = board->reg_shift;  	return 0; @@ -420,6 +419,25 @@ static void pci_xr17v35x_exit(struct pci_dev *pcidev)  	port->port.private_data = NULL;  } +/* + * These Exar UARTs have an extra interrupt indicator that could fire for a + * few interrupts that are not presented/cleared through IIR.  One of which is + * a wakeup interrupt when coming out of sleep.  These interrupts are only + * cleared by reading global INT0 or INT1 registers as interrupts are + * associated with channel 0. The INT[3:0] registers _are_ accessible from each + * channel's address space, but for the sake of bus efficiency we register a + * dedicated handler at the PCI device level to handle them. + */ +static irqreturn_t exar_misc_handler(int irq, void *data) +{ +	struct exar8250 *priv = data; + +	/* Clear all PCI interrupts by reading INT0. No effect on IIR */ +	ioread8(priv->virt + UART_EXAR_INT0); + +	return IRQ_HANDLED; +} +  static int  exar_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)  { @@ -448,6 +466,9 @@ exar_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)  		return -ENOMEM;  	priv->board = board; +	priv->virt = pcim_iomap(pcidev, bar, 0); +	if (!priv->virt) +		return -ENOMEM;  	pci_set_master(pcidev); @@ -461,6 +482,11 @@ exar_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)  	uart.port.irq = pci_irq_vector(pcidev, 0);  	uart.port.dev = &pcidev->dev; +	rc = devm_request_irq(&pcidev->dev, uart.port.irq, exar_misc_handler, +			 IRQF_SHARED, "exar_uart", priv); +	if (rc) +		return rc; +  	for (i = 0; i < nr_ports && i < maxnr; i++) {  		rc = board->setup(priv, pcidev, &uart, i);  		if (rc) { diff --git a/drivers/tty/serial/8250/8250_ingenic.c b/drivers/tty/serial/8250/8250_ingenic.c index 6af84900870e..15a8c8dfa92b 100644 --- a/drivers/tty/serial/8250/8250_ingenic.c +++ b/drivers/tty/serial/8250/8250_ingenic.c @@ -91,14 +91,22 @@ static int __init ingenic_early_console_setup(struct earlycon_device *dev,  					      const char *opt)  {  	struct uart_port *port = &dev->port; -	unsigned int baud, divisor; +	unsigned int divisor; +	int baud = 115200;  	if (!dev->port.membase)  		return -ENODEV; +	if (opt) { +		unsigned int parity, bits, flow; /* unused for now */ + +		uart_parse_options(opt, &baud, &parity, &bits, &flow); +	} +  	ingenic_early_console_setup_clock(dev); -	baud = dev->baud ?: 115200; +	if (dev->baud) +		baud = dev->baud;  	divisor = DIV_ROUND_CLOSEST(port->uartclk, 16 * baud);  	early_out(port, UART_IER, 0); @@ -125,6 +133,10 @@ EARLYCON_DECLARE(jz4740_uart, ingenic_early_console_setup);  OF_EARLYCON_DECLARE(jz4740_uart, "ingenic,jz4740-uart",  		    ingenic_early_console_setup); +EARLYCON_DECLARE(jz4770_uart, ingenic_early_console_setup); +OF_EARLYCON_DECLARE(jz4770_uart, "ingenic,jz4770-uart", +		    ingenic_early_console_setup); +  EARLYCON_DECLARE(jz4775_uart, ingenic_early_console_setup);  OF_EARLYCON_DECLARE(jz4775_uart, "ingenic,jz4775-uart",  		    ingenic_early_console_setup); @@ -319,6 +331,7 @@ static const struct ingenic_uart_config jz4780_uart_config = {  static const struct of_device_id of_match[] = {  	{ .compatible = "ingenic,jz4740-uart", .data = &jz4740_uart_config },  	{ .compatible = "ingenic,jz4760-uart", .data = &jz4760_uart_config }, +	{ .compatible = "ingenic,jz4770-uart", .data = &jz4760_uart_config },  	{ .compatible = "ingenic,jz4775-uart", .data = &jz4760_uart_config },  	{ .compatible = "ingenic,jz4780-uart", .data = &jz4780_uart_config },  	{ /* sentinel */ } diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c index 1e67a7e4a5fd..160b8906d9b9 100644 --- a/drivers/tty/serial/8250/8250_of.c +++ b/drivers/tty/serial/8250/8250_of.c @@ -136,8 +136,11 @@ static int of_platform_serial_setup(struct platform_device *ofdev,  	}  	info->rst = devm_reset_control_get_optional_shared(&ofdev->dev, NULL); -	if (IS_ERR(info->rst)) +	if (IS_ERR(info->rst)) { +		ret = PTR_ERR(info->rst);  		goto err_dispose; +	} +  	ret = reset_control_deassert(info->rst);  	if (ret)  		goto err_dispose; diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c index bd40ba402410..57f6eba47f44 100644 --- a/drivers/tty/serial/8250/8250_omap.c +++ b/drivers/tty/serial/8250/8250_omap.c @@ -414,7 +414,7 @@ static void omap_8250_set_termios(struct uart_port *port,  	/* Up to here it was mostly serial8250_do_set_termios() */  	/* -	 * We enable TRIG_GRANU for RX and TX and additionaly we set +	 * We enable TRIG_GRANU for RX and TX and additionally we set  	 * SCR_TX_EMPTY bit. The result is the following:  	 * - RX_TRIGGER amount of bytes in the FIFO will cause an interrupt.  	 * - less than RX_TRIGGER number of bytes will also cause an interrupt diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 11434551ac0a..1328c7e70108 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -441,7 +441,6 @@ static void io_serial_out(struct uart_port *p, int offset, int value)  }  static int serial8250_default_handle_irq(struct uart_port *port); -static int exar_handle_irq(struct uart_port *port);  static void set_io_from_upio(struct uart_port *p)  { @@ -1884,26 +1883,6 @@ static int serial8250_default_handle_irq(struct uart_port *port)  }  /* - * These Exar UARTs have an extra interrupt indicator that could - * fire for a few unimplemented interrupts.  One of which is a - * wakeup event when coming out of sleep.  Put this here just - * to be on the safe side that these interrupts don't go unhandled. - */ -static int exar_handle_irq(struct uart_port *port) -{ -	unsigned int iir = serial_port_in(port, UART_IIR); -	int ret = 0; - -	if (((port->type == PORT_XR17V35X) || (port->type == PORT_XR17D15X)) && -	    serial_port_in(port, UART_EXAR_INT0) != 0) -		ret = 1; - -	ret |= serial8250_handle_irq(port, iir); - -	return ret; -} - -/*   * Newer 16550 compatible parts such as the SC16C650 & Altera 16550 Soft IP   * have a programmable TX threshold that triggers the THRE interrupt in   * the IIR register. In this case, the THRE interrupt indicates the FIFO @@ -3067,11 +3046,6 @@ static void serial8250_config_port(struct uart_port *port, int flags)  	if (port->type == PORT_UNKNOWN)  		serial8250_release_std_resource(up); -	/* Fixme: probably not the best place for this */ -	if ((port->type == PORT_XR17V35X) || -	   (port->type == PORT_XR17D15X)) -		port->handle_irq = exar_handle_irq; -  	register_dev_spec_attr_grp(up);  	up->fcr = uart_config[up->port.type].fcr;  } diff --git a/drivers/tty/serial/8250/8250_uniphier.c b/drivers/tty/serial/8250/8250_uniphier.c index 45ef506293ae..28d88ccf5a0c 100644 --- a/drivers/tty/serial/8250/8250_uniphier.c +++ b/drivers/tty/serial/8250/8250_uniphier.c @@ -250,12 +250,13 @@ static int uniphier_uart_probe(struct platform_device *pdev)  	up.dl_read = uniphier_serial_dl_read;  	up.dl_write = uniphier_serial_dl_write; -	priv->line = serial8250_register_8250_port(&up); -	if (priv->line < 0) { +	ret = serial8250_register_8250_port(&up); +	if (ret < 0) {  		dev_err(dev, "failed to register 8250 port\n");  		clk_disable_unprepare(priv->clk);  		return ret;  	} +	priv->line = ret;  	platform_set_drvdata(pdev, priv); diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index a5c0ef1e7695..16b1496e6105 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -5,6 +5,7 @@  config SERIAL_8250  	tristate "8250/16550 and compatible serial support" +	depends on !S390  	select SERIAL_CORE  	---help---  	  This selects whether you want to include the driver for the standard diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index b788fee54249..3682fd3e960c 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -761,24 +761,30 @@ config SERIAL_SH_SCI  	select SERIAL_MCTRL_GPIO if GPIOLIB  config SERIAL_SH_SCI_NR_UARTS -	int "Maximum number of SCI(F) serial ports" +	int "Maximum number of SCI(F) serial ports" if EXPERT  	depends on SERIAL_SH_SCI +	default "3" if H8300 +	default "10" if SUPERH +	default "18" if ARCH_RENESAS  	default "2"  config SERIAL_SH_SCI_CONSOLE -	bool "Support for console on SuperH SCI(F)" +	bool "Support for console on SuperH SCI(F)" if EXPERT  	depends on SERIAL_SH_SCI=y  	select SERIAL_CORE_CONSOLE +	default y  config SERIAL_SH_SCI_EARLYCON -	bool "Support for early console on SuperH SCI(F)" +	bool "Support for early console on SuperH SCI(F)" if EXPERT  	depends on SERIAL_SH_SCI=y  	select SERIAL_CORE_CONSOLE  	select SERIAL_EARLYCON +	default ARCH_RENESAS || H8300  config SERIAL_SH_SCI_DMA -	bool "DMA support" +	bool "DMA support" if EXPERT  	depends on SERIAL_SH_SCI && DMA_ENGINE +	default ARCH_RENESAS  config SERIAL_PNX8XXX  	bool "Enable PNX8XXX SoCs' UART Support" diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 04af8de8617e..4b40a5b449ee 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -314,10 +314,9 @@ static void pl011_write(unsigned int val, const struct uart_amba_port *uap,  static int pl011_fifo_to_tty(struct uart_amba_port *uap)  {  	u16 status; -	unsigned int ch, flag, max_count = 256; -	int fifotaken = 0; +	unsigned int ch, flag, fifotaken; -	while (max_count--) { +	for (fifotaken = 0; fifotaken != 256; fifotaken++) {  		status = pl011_read(uap, REG_FR);  		if (status & UART01x_FR_RXFE)  			break; @@ -326,7 +325,6 @@ static int pl011_fifo_to_tty(struct uart_amba_port *uap)  		ch = pl011_read(uap, REG_DR) | UART_DUMMY_DR_RX;  		flag = TTY_NORMAL;  		uap->port.icount.rx++; -		fifotaken++;  		if (unlikely(ch & UART_DR_ERROR)) {  			if (ch & UART011_DR_BE) { @@ -1482,12 +1480,10 @@ static irqreturn_t pl011_int(int irq, void *dev_id)  	struct uart_amba_port *uap = dev_id;  	unsigned long flags;  	unsigned int status, pass_counter = AMBA_ISR_PASS_LIMIT; -	u16 imsc;  	int handled = 0;  	spin_lock_irqsave(&uap->port.lock, flags); -	imsc = pl011_read(uap, REG_IMSC); -	status = pl011_read(uap, REG_RIS) & imsc; +	status = pl011_read(uap, REG_RIS) & uap->im;  	if (status) {  		do {  			check_apply_cts_event_workaround(uap); @@ -1511,7 +1507,7 @@ static irqreturn_t pl011_int(int irq, void *dev_id)  			if (pass_counter-- == 0)  				break; -			status = pl011_read(uap, REG_RIS) & imsc; +			status = pl011_read(uap, REG_RIS) & uap->im;  		} while (status != 0);  		handled = 1;  	} diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index efa25611ca0c..df46a9e88c34 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -2345,7 +2345,7 @@ static int atmel_init_port(struct atmel_uart_port *atmel_port,  	atmel_init_property(atmel_port, pdev);  	atmel_set_ops(port); -	of_get_rs485_mode(pdev->dev.of_node, &port->rs485); +	uart_get_rs485_mode(&pdev->dev, &port->rs485);  	port->iotype		= UPIO_MEM;  	port->flags		= UPF_BOOT_AUTOCONF | UPF_IOREMAP; diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c index 4c8b80f1c688..870e84fb6e39 100644 --- a/drivers/tty/serial/earlycon.c +++ b/drivers/tty/serial/earlycon.c @@ -197,25 +197,20 @@ int __init setup_earlycon(char *buf)  }  /* - * When CONFIG_ACPI_SPCR_TABLE is defined, "earlycon" without parameters in - * command line does not start DT earlycon immediately, instead it defers - * starting it until DT/ACPI decision is made.  At that time if ACPI is enabled - * call parse_spcr(), else call early_init_dt_scan_chosen_stdout() + * This defers the initialization of the early console until after ACPI has + * been initialized.   */ -bool earlycon_init_is_deferred __initdata; +bool earlycon_acpi_spcr_enable __initdata;  /* early_param wrapper for setup_earlycon() */  static int __init param_setup_earlycon(char *buf)  {  	int err; -	/* -	 * Just 'earlycon' is a valid param for devicetree earlycons; -	 * don't generate a warning from parse_early_params() in that case -	 */ +	/* Just 'earlycon' is a valid param for devicetree and ACPI SPCR. */  	if (!buf || !buf[0]) {  		if (IS_ENABLED(CONFIG_ACPI_SPCR_TABLE)) { -			earlycon_init_is_deferred = true; +			earlycon_acpi_spcr_enable = true;  			return 0;  		} else if (!buf) {  			return early_init_dt_scan_chosen_stdout(); diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index 1c4d3f387138..8cf112f2efc3 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -2206,23 +2206,16 @@ static int lpuart_probe(struct platform_device *pdev)  	if (ret)  		goto failed_attach_port; -	of_get_rs485_mode(np, &sport->port.rs485); +	uart_get_rs485_mode(&pdev->dev, &sport->port.rs485); -	if (sport->port.rs485.flags & SER_RS485_RX_DURING_TX) { +	if (sport->port.rs485.flags & SER_RS485_RX_DURING_TX)  		dev_err(&pdev->dev, "driver doesn't support RX during TX\n"); -		return -ENOSYS; -	}  	if (sport->port.rs485.delay_rts_before_send || -	    sport->port.rs485.delay_rts_after_send) { +	    sport->port.rs485.delay_rts_after_send)  		dev_err(&pdev->dev, "driver doesn't support RTS delays\n"); -		return -ENOSYS; -	} -	if (sport->port.rs485.flags & SER_RS485_ENABLED) { -		sport->port.rs485.flags |= SER_RS485_RTS_ON_SEND; -		writeb(UARTMODEM_TXRTSE, sport->port.membase + UARTMODEM); -	} +	lpuart_config_rs485(&sport->port, &sport->port.rs485);  	sport->dma_tx_chan = dma_request_slave_channel(sport->port.dev, "tx");  	if (!sport->dma_tx_chan) diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index e4b3d9123a03..1d7ca382bc12 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -703,25 +703,6 @@ out:  	return IRQ_HANDLED;  } -static void imx_disable_rx_int(struct imx_port *sport) -{ -	unsigned long temp; - -	/* disable the receiver ready and aging timer interrupts */ -	temp = readl(sport->port.membase + UCR1); -	temp &= ~(UCR1_RRDYEN); -	writel(temp, sport->port.membase + UCR1); - -	temp = readl(sport->port.membase + UCR2); -	temp &= ~(UCR2_ATEN); -	writel(temp, sport->port.membase + UCR2); - -	/* disable the rx errors interrupts */ -	temp = readl(sport->port.membase + UCR4); -	temp &= ~UCR4_OREN; -	writel(temp, sport->port.membase + UCR4); -} -  static void clear_rx_errors(struct imx_port *sport);  /* @@ -1252,18 +1233,21 @@ static int imx_startup(struct uart_port *port)  	if (sport->dma_is_inited && !sport->dma_is_enabled)  		imx_enable_dma(sport); -	temp = readl(sport->port.membase + UCR1); -	temp |= UCR1_RRDYEN | UCR1_UARTEN; +	temp = readl(sport->port.membase + UCR1) & ~UCR1_RRDYEN; +	if (!sport->dma_is_enabled) +		temp |= UCR1_RRDYEN; +	temp |= UCR1_UARTEN;  	if (sport->have_rtscts)  			temp |= UCR1_RTSDEN;  	writel(temp, sport->port.membase + UCR1); -	temp = readl(sport->port.membase + UCR4); -	temp |= UCR4_OREN; +	temp = readl(sport->port.membase + UCR4) & ~UCR4_OREN; +	if (!sport->dma_is_enabled) +		temp |= UCR4_OREN;  	writel(temp, sport->port.membase + UCR4); -	temp = readl(sport->port.membase + UCR2); +	temp = readl(sport->port.membase + UCR2) & ~UCR2_ATEN;  	temp |= (UCR2_RXEN | UCR2_TXEN);  	if (!sport->have_rtscts)  		temp |= UCR2_IRTS; @@ -1297,10 +1281,8 @@ static int imx_startup(struct uart_port *port)  	 * In our iMX53 the average delay for the first reception dropped from  	 * approximately 35000 microseconds to 1000 microseconds.  	 */ -	if (sport->dma_is_enabled) { -		imx_disable_rx_int(sport); +	if (sport->dma_is_enabled)  		start_rx_dma(sport); -	}  	spin_unlock_irqrestore(&sport->port.lock, flags); @@ -2017,8 +1999,6 @@ static int serial_imx_probe_dt(struct imx_port *sport,  	if (of_get_property(np, "rts-gpios", NULL))  		sport->have_rtsgpio = 1; -	of_get_rs485_mode(np, &sport->port.rs485); -  	return 0;  }  #else @@ -2080,7 +2060,6 @@ static int serial_imx_probe(struct platform_device *pdev)  	sport->port.fifosize = 32;  	sport->port.ops = &imx_pops;  	sport->port.rs485_config = imx_rs485_config; -	sport->port.rs485.flags |= SER_RS485_RTS_ON_SEND;  	sport->port.flags = UPF_BOOT_AUTOCONF;  	timer_setup(&sport->timer, imx_timeout, 0); @@ -2111,6 +2090,14 @@ static int serial_imx_probe(struct platform_device *pdev)  		return ret;  	} +	uart_get_rs485_mode(&pdev->dev, &sport->port.rs485); + +	if (sport->port.rs485.flags & SER_RS485_ENABLED && +	    (!sport->have_rtscts || !sport->have_rtsgpio)) +		dev_err(&pdev->dev, "no RTS control, disabling rs485\n"); + +	imx_rs485_config(&sport->port, &sport->port.rs485); +  	/* Disable interrupts before requesting them */  	reg = readl_relaxed(sport->port.membase + UCR1);  	reg &= ~(UCR1_ADEN | UCR1_TRDYEN | UCR1_IDEN | UCR1_RRDYEN | @@ -2232,29 +2219,28 @@ static void serial_imx_enable_wakeup(struct imx_port *sport, bool on)  	unsigned int val;  	val = readl(sport->port.membase + UCR3); -	if (on) +	if (on) { +		writel(USR1_AWAKE, sport->port.membase + USR1);  		val |= UCR3_AWAKEN; +	}  	else  		val &= ~UCR3_AWAKEN;  	writel(val, sport->port.membase + UCR3); -	val = readl(sport->port.membase + UCR1); -	if (on) -		val |= UCR1_RTSDEN; -	else -		val &= ~UCR1_RTSDEN; -	writel(val, sport->port.membase + UCR1); +	if (sport->have_rtscts) { +		val = readl(sport->port.membase + UCR1); +		if (on) +			val |= UCR1_RTSDEN; +		else +			val &= ~UCR1_RTSDEN; +		writel(val, sport->port.membase + UCR1); +	}  }  static int imx_serial_port_suspend_noirq(struct device *dev)  {  	struct platform_device *pdev = to_platform_device(dev);  	struct imx_port *sport = platform_get_drvdata(pdev); -	int ret; - -	ret = clk_enable(sport->clk_ipg); -	if (ret) -		return ret;  	serial_imx_save_context(sport); @@ -2275,8 +2261,6 @@ static int imx_serial_port_resume_noirq(struct device *dev)  	serial_imx_restore_context(sport); -	clk_disable(sport->clk_ipg); -  	return 0;  } @@ -2284,15 +2268,19 @@ static int imx_serial_port_suspend(struct device *dev)  {  	struct platform_device *pdev = to_platform_device(dev);  	struct imx_port *sport = platform_get_drvdata(pdev); - -	/* enable wakeup from i.MX UART */ -	serial_imx_enable_wakeup(sport, true); +	int ret;  	uart_suspend_port(&imx_reg, &sport->port);  	disable_irq(sport->port.irq); -	/* Needed to enable clock in suspend_noirq */ -	return clk_prepare(sport->clk_ipg); +	ret = clk_prepare_enable(sport->clk_ipg); +	if (ret) +		return ret; + +	/* enable wakeup from i.MX UART */ +	serial_imx_enable_wakeup(sport, true); + +	return 0;  }  static int imx_serial_port_resume(struct device *dev) @@ -2306,7 +2294,7 @@ static int imx_serial_port_resume(struct device *dev)  	uart_resume_port(&imx_reg, &sport->port);  	enable_irq(sport->port.irq); -	clk_unprepare(sport->clk_ipg); +	clk_disable_unprepare(sport->clk_ipg);  	return 0;  } @@ -2318,8 +2306,7 @@ static int imx_serial_port_freeze(struct device *dev)  	uart_suspend_port(&imx_reg, &sport->port); -	/* Needed to enable clock in suspend_noirq */ -	return clk_prepare(sport->clk_ipg); +	return clk_prepare_enable(sport->clk_ipg);  }  static int imx_serial_port_thaw(struct device *dev) @@ -2329,7 +2316,7 @@ static int imx_serial_port_thaw(struct device *dev)  	uart_resume_port(&imx_reg, &sport->port); -	clk_unprepare(sport->clk_ipg); +	clk_disable_unprepare(sport->clk_ipg);  	return 0;  } diff --git a/drivers/tty/serial/jsm/jsm_neo.c b/drivers/tty/serial/jsm/jsm_neo.c index 4718560b8fdc..bf0e2a4cb0ce 100644 --- a/drivers/tty/serial/jsm/jsm_neo.c +++ b/drivers/tty/serial/jsm/jsm_neo.c @@ -282,9 +282,6 @@ static void neo_copy_data_from_uart_to_queue(struct jsm_channel *ch)  	u16 head;  	u16 tail; -	if (!ch) -		return; -  	/* cache head and tail of queue */  	head = ch->ch_r_head & RQUEUEMASK;  	tail = ch->ch_r_tail & RQUEUEMASK; @@ -1175,6 +1172,9 @@ static irqreturn_t neo_intr(int irq, void *voidbrd)  				continue;  			ch = brd->channels[port]; +			if (!ch) +				continue; +  			neo_copy_data_from_uart_to_queue(ch);  			/* Call our tty layer to enforce queue flow control if needed. */ diff --git a/drivers/tty/serial/jsm/jsm_tty.c b/drivers/tty/serial/jsm/jsm_tty.c index 469927d37b41..b6bd6e15e07b 100644 --- a/drivers/tty/serial/jsm/jsm_tty.c +++ b/drivers/tty/serial/jsm/jsm_tty.c @@ -523,9 +523,6 @@ void jsm_input(struct jsm_channel *ch)  	jsm_dbg(READ, &ch->ch_bd->pci_dev, "start\n"); -	if (!ch) -		return; -  	port = &ch->uart_port.state->port;  	tp = port->tty; @@ -648,11 +645,8 @@ static void jsm_carrier(struct jsm_channel *ch)  	int phys_carrier = 0;  	jsm_dbg(CARR, &ch->ch_bd->pci_dev, "start\n"); -	if (!ch) -		return;  	bd = ch->ch_bd; -  	if (!bd)  		return; diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c index ecb6513a6505..39f635812077 100644 --- a/drivers/tty/serial/max310x.c +++ b/drivers/tty/serial/max310x.c @@ -233,6 +233,7 @@  /* Misc definitions */  #define MAX310X_FIFO_SIZE		(128)  #define MAX310x_REV_MASK		(0xf8) +#define MAX310X_WRITE_BIT		0x80  /* MAX3107 specific */  #define MAX3107_REV_ID			(0xa0) @@ -593,57 +594,118 @@ static int max310x_set_ref_clk(struct max310x_port *s, unsigned long freq,  	return (int)bestfreq;  } -static void max310x_handle_rx(struct uart_port *port, unsigned int rxlen) +static void max310x_batch_write(struct uart_port *port, u8 *txbuf, unsigned int len)  { -	unsigned int sts, ch, flag; +	u8 header[] = { (port->iobase + MAX310X_THR_REG) | MAX310X_WRITE_BIT }; +	struct spi_transfer xfer[] = { +		{ +			.tx_buf = &header, +			.len = sizeof(header), +		}, { +			.tx_buf = txbuf, +			.len = len, +		} +	}; +	spi_sync_transfer(to_spi_device(port->dev), xfer, ARRAY_SIZE(xfer)); +} -	if (unlikely(rxlen >= port->fifosize)) { -		dev_warn_ratelimited(port->dev, "Possible RX FIFO overrun\n"); -		port->icount.buf_overrun++; -		/* Ensure sanity of RX level */ -		rxlen = port->fifosize; -	} +static void max310x_batch_read(struct uart_port *port, u8 *rxbuf, unsigned int len) +{ +	u8 header[] = { port->iobase + MAX310X_RHR_REG }; +	struct spi_transfer xfer[] = { +		{ +			.tx_buf = &header, +			.len = sizeof(header), +		}, { +			.rx_buf = rxbuf, +			.len = len, +		} +	}; +	spi_sync_transfer(to_spi_device(port->dev), xfer, ARRAY_SIZE(xfer)); +} -	while (rxlen--) { -		ch = max310x_port_read(port, MAX310X_RHR_REG); -		sts = max310x_port_read(port, MAX310X_LSR_IRQSTS_REG); +static void max310x_handle_rx(struct uart_port *port, unsigned int rxlen) +{ +	unsigned int sts, ch, flag, i; +	u8 buf[MAX310X_FIFO_SIZE]; + +	if (port->read_status_mask == MAX310X_LSR_RXOVR_BIT) { +		/* We are just reading, happily ignoring any error conditions. +		 * Break condition, parity checking, framing errors -- they +		 * are all ignored. That means that we can do a batch-read. +		 * +		 * There is a small opportunity for race if the RX FIFO +		 * overruns while we're reading the buffer; the datasheets says +		 * that the LSR register applies to the "current" character. +		 * That's also the reason why we cannot do batched reads when +		 * asked to check the individual statuses. +		 * */ -		sts &= MAX310X_LSR_RXPAR_BIT | MAX310X_LSR_FRERR_BIT | -		       MAX310X_LSR_RXOVR_BIT | MAX310X_LSR_RXBRK_BIT; +		sts = max310x_port_read(port, MAX310X_LSR_IRQSTS_REG); +		max310x_batch_read(port, buf, rxlen); -		port->icount.rx++; +		port->icount.rx += rxlen;  		flag = TTY_NORMAL; +		sts &= port->read_status_mask; -		if (unlikely(sts)) { -			if (sts & MAX310X_LSR_RXBRK_BIT) { -				port->icount.brk++; -				if (uart_handle_break(port)) -					continue; -			} else if (sts & MAX310X_LSR_RXPAR_BIT) -				port->icount.parity++; -			else if (sts & MAX310X_LSR_FRERR_BIT) -				port->icount.frame++; -			else if (sts & MAX310X_LSR_RXOVR_BIT) -				port->icount.overrun++; - -			sts &= port->read_status_mask; -			if (sts & MAX310X_LSR_RXBRK_BIT) -				flag = TTY_BREAK; -			else if (sts & MAX310X_LSR_RXPAR_BIT) -				flag = TTY_PARITY; -			else if (sts & MAX310X_LSR_FRERR_BIT) -				flag = TTY_FRAME; -			else if (sts & MAX310X_LSR_RXOVR_BIT) -				flag = TTY_OVERRUN; +		if (sts & MAX310X_LSR_RXOVR_BIT) { +			dev_warn_ratelimited(port->dev, "Hardware RX FIFO overrun\n"); +			port->icount.overrun++;  		} -		if (uart_handle_sysrq_char(port, ch)) -			continue; +		for (i = 0; i < rxlen; ++i) { +			uart_insert_char(port, sts, MAX310X_LSR_RXOVR_BIT, buf[i], flag); +		} + +	} else { +		if (unlikely(rxlen >= port->fifosize)) { +			dev_warn_ratelimited(port->dev, "Possible RX FIFO overrun\n"); +			port->icount.buf_overrun++; +			/* Ensure sanity of RX level */ +			rxlen = port->fifosize; +		} + +		while (rxlen--) { +			ch = max310x_port_read(port, MAX310X_RHR_REG); +			sts = max310x_port_read(port, MAX310X_LSR_IRQSTS_REG); + +			sts &= MAX310X_LSR_RXPAR_BIT | MAX310X_LSR_FRERR_BIT | +			       MAX310X_LSR_RXOVR_BIT | MAX310X_LSR_RXBRK_BIT; + +			port->icount.rx++; +			flag = TTY_NORMAL; + +			if (unlikely(sts)) { +				if (sts & MAX310X_LSR_RXBRK_BIT) { +					port->icount.brk++; +					if (uart_handle_break(port)) +						continue; +				} else if (sts & MAX310X_LSR_RXPAR_BIT) +					port->icount.parity++; +				else if (sts & MAX310X_LSR_FRERR_BIT) +					port->icount.frame++; +				else if (sts & MAX310X_LSR_RXOVR_BIT) +					port->icount.overrun++; + +				sts &= port->read_status_mask; +				if (sts & MAX310X_LSR_RXBRK_BIT) +					flag = TTY_BREAK; +				else if (sts & MAX310X_LSR_RXPAR_BIT) +					flag = TTY_PARITY; +				else if (sts & MAX310X_LSR_FRERR_BIT) +					flag = TTY_FRAME; +				else if (sts & MAX310X_LSR_RXOVR_BIT) +					flag = TTY_OVERRUN; +			} -		if (sts & port->ignore_status_mask) -			continue; +			if (uart_handle_sysrq_char(port, ch)) +				continue; -		uart_insert_char(port, sts, MAX310X_LSR_RXOVR_BIT, ch, flag); +			if (sts & port->ignore_status_mask) +				continue; + +			uart_insert_char(port, sts, MAX310X_LSR_RXOVR_BIT, ch, flag); +		}  	}  	tty_flip_buffer_push(&port->state->port); @@ -652,7 +714,7 @@ static void max310x_handle_rx(struct uart_port *port, unsigned int rxlen)  static void max310x_handle_tx(struct uart_port *port)  {  	struct circ_buf *xmit = &port->state->xmit; -	unsigned int txlen, to_send; +	unsigned int txlen, to_send, until_end;  	if (unlikely(port->x_char)) {  		max310x_port_write(port, MAX310X_THR_REG, port->x_char); @@ -666,28 +728,43 @@ static void max310x_handle_tx(struct uart_port *port)  	/* Get length of data pending in circular buffer */  	to_send = uart_circ_chars_pending(xmit); +	until_end = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);  	if (likely(to_send)) {  		/* Limit to size of TX FIFO */  		txlen = max310x_port_read(port, MAX310X_TXFIFOLVL_REG);  		txlen = port->fifosize - txlen;  		to_send = (to_send > txlen) ? txlen : to_send; +		if (until_end < to_send) { +			/* It's a circ buffer -- wrap around. +			 * We could do that in one SPI transaction, but meh. */ +			max310x_batch_write(port, xmit->buf + xmit->tail, until_end); +			max310x_batch_write(port, xmit->buf, to_send - until_end); +		} else { +			max310x_batch_write(port, xmit->buf + xmit->tail, to_send); +		} +  		/* Add data to send */  		port->icount.tx += to_send; -		while (to_send--) { -			max310x_port_write(port, MAX310X_THR_REG, -					   xmit->buf[xmit->tail]); -			xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); -		} +		xmit->tail = (xmit->tail + to_send) & (UART_XMIT_SIZE - 1);  	}  	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)  		uart_write_wakeup(port);  } -static void max310x_port_irq(struct max310x_port *s, int portno) +static void max310x_start_tx(struct uart_port *port) +{ +	struct max310x_one *one = container_of(port, struct max310x_one, port); + +	if (!work_pending(&one->tx_work)) +		schedule_work(&one->tx_work); +} + +static irqreturn_t max310x_port_irq(struct max310x_port *s, int portno)  {  	struct uart_port *port = &s->p[portno].port; +	irqreturn_t res = IRQ_NONE;  	do {  		unsigned int ists, lsr, rxlen; @@ -698,6 +775,8 @@ static void max310x_port_irq(struct max310x_port *s, int portno)  		if (!ists && !rxlen)  			break; +		res = IRQ_HANDLED; +  		if (ists & MAX310X_IRQ_CTS_BIT) {  			lsr = max310x_port_read(port, MAX310X_LSR_IRQSTS_REG);  			uart_handle_cts_change(port, @@ -705,17 +784,16 @@ static void max310x_port_irq(struct max310x_port *s, int portno)  		}  		if (rxlen)  			max310x_handle_rx(port, rxlen); -		if (ists & MAX310X_IRQ_TXEMPTY_BIT) { -			mutex_lock(&s->mutex); -			max310x_handle_tx(port); -			mutex_unlock(&s->mutex); -		} +		if (ists & MAX310X_IRQ_TXEMPTY_BIT) +			max310x_start_tx(port);  	} while (1); +	return res;  }  static irqreturn_t max310x_ist(int irq, void *dev_id)  {  	struct max310x_port *s = (struct max310x_port *)dev_id; +	bool handled = false;  	if (s->devtype->nr > 1) {  		do { @@ -726,12 +804,15 @@ static irqreturn_t max310x_ist(int irq, void *dev_id)  			val = ((1 << s->devtype->nr) - 1) & ~val;  			if (!val)  				break; -			max310x_port_irq(s, fls(val) - 1); +			if (max310x_port_irq(s, fls(val) - 1) == IRQ_HANDLED) +				handled = true;  		} while (1); -	} else -		max310x_port_irq(s, 0); +	} else { +		if (max310x_port_irq(s, 0) == IRQ_HANDLED) +			handled = true; +	} -	return IRQ_HANDLED; +	return IRQ_RETVAL(handled);  }  static void max310x_wq_proc(struct work_struct *ws) @@ -744,14 +825,6 @@ static void max310x_wq_proc(struct work_struct *ws)  	mutex_unlock(&s->mutex);  } -static void max310x_start_tx(struct uart_port *port) -{ -	struct max310x_one *one = container_of(port, struct max310x_one, port); - -	if (!work_pending(&one->tx_work)) -		schedule_work(&one->tx_work); -} -  static unsigned int max310x_tx_empty(struct uart_port *port)  {  	unsigned int lvl, sts; @@ -1086,10 +1159,31 @@ static int max310x_gpio_direction_output(struct gpio_chip *chip,  	return 0;  } + +static int max310x_gpio_set_config(struct gpio_chip *chip, unsigned int offset, +				   unsigned long config) +{ +	struct max310x_port *s = gpiochip_get_data(chip); +	struct uart_port *port = &s->p[offset / 4].port; + +	switch (pinconf_to_config_param(config)) { +	case PIN_CONFIG_DRIVE_OPEN_DRAIN: +		max310x_port_update(port, MAX310X_GPIOCFG_REG, +				1 << ((offset % 4) + 4), +				1 << ((offset % 4) + 4)); +		return 0; +	case PIN_CONFIG_DRIVE_PUSH_PULL: +		max310x_port_update(port, MAX310X_GPIOCFG_REG, +				1 << ((offset % 4) + 4), 0); +		return 0; +	default: +		return -ENOTSUPP; +	} +}  #endif  static int max310x_probe(struct device *dev, struct max310x_devtype *devtype, -			 struct regmap *regmap, int irq, unsigned long flags) +			 struct regmap *regmap, int irq)  {  	int i, ret, fmin, fmax, freq, uartclk;  	struct clk *clk_osc, *clk_xtal; @@ -1169,23 +1263,6 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype,  	uartclk = max310x_set_ref_clk(s, freq, xtal);  	dev_dbg(dev, "Reference clock set to %i Hz\n", uartclk); -#ifdef CONFIG_GPIOLIB -	/* Setup GPIO cotroller */ -	s->gpio.owner		= THIS_MODULE; -	s->gpio.parent		= dev; -	s->gpio.label		= dev_name(dev); -	s->gpio.direction_input	= max310x_gpio_direction_input; -	s->gpio.get		= max310x_gpio_get; -	s->gpio.direction_output= max310x_gpio_direction_output; -	s->gpio.set		= max310x_gpio_set; -	s->gpio.base		= -1; -	s->gpio.ngpio		= devtype->nr * 4; -	s->gpio.can_sleep	= 1; -	ret = devm_gpiochip_add_data(dev, &s->gpio, s); -	if (ret) -		goto out_clk; -#endif -  	mutex_init(&s->mutex);  	for (i = 0; i < devtype->nr; i++) { @@ -1237,9 +1314,27 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype,  		devtype->power(&s->p[i].port, 0);  	} +#ifdef CONFIG_GPIOLIB +	/* Setup GPIO cotroller */ +	s->gpio.owner		= THIS_MODULE; +	s->gpio.parent		= dev; +	s->gpio.label		= dev_name(dev); +	s->gpio.direction_input	= max310x_gpio_direction_input; +	s->gpio.get		= max310x_gpio_get; +	s->gpio.direction_output= max310x_gpio_direction_output; +	s->gpio.set		= max310x_gpio_set; +	s->gpio.set_config	= max310x_gpio_set_config; +	s->gpio.base		= -1; +	s->gpio.ngpio		= devtype->nr * 4; +	s->gpio.can_sleep	= 1; +	ret = devm_gpiochip_add_data(dev, &s->gpio, s); +	if (ret) +		goto out_uart; +#endif +  	/* Setup interrupt */  	ret = devm_request_threaded_irq(dev, irq, NULL, max310x_ist, -					IRQF_ONESHOT | flags, dev_name(dev), s); +					IRQF_ONESHOT | IRQF_SHARED, dev_name(dev), s);  	if (!ret)  		return 0; @@ -1293,7 +1388,7 @@ MODULE_DEVICE_TABLE(of, max310x_dt_ids);  static struct regmap_config regcfg = {  	.reg_bits = 8,  	.val_bits = 8, -	.write_flag_mask = 0x80, +	.write_flag_mask = MAX310X_WRITE_BIT,  	.cache_type = REGCACHE_RBTREE,  	.writeable_reg = max310x_reg_writeable,  	.volatile_reg = max310x_reg_volatile, @@ -1304,7 +1399,6 @@ static struct regmap_config regcfg = {  static int max310x_spi_probe(struct spi_device *spi)  {  	struct max310x_devtype *devtype; -	unsigned long flags = 0;  	struct regmap *regmap;  	int ret; @@ -1327,11 +1421,10 @@ static int max310x_spi_probe(struct spi_device *spi)  		devtype = (struct max310x_devtype *)id_entry->driver_data;  	} -	flags = IRQF_TRIGGER_FALLING;  	regcfg.max_register = devtype->nr * 0x20 - 1;  	regmap = devm_regmap_init_spi(spi, ®cfg); -	return max310x_probe(&spi->dev, devtype, regmap, spi->irq, flags); +	return max310x_probe(&spi->dev, devtype, regmap, spi->irq);  }  static int max310x_spi_remove(struct spi_device *spi) diff --git a/drivers/tty/serial/meson_uart.c b/drivers/tty/serial/meson_uart.c index daafe60175da..8a842591b37c 100644 --- a/drivers/tty/serial/meson_uart.c +++ b/drivers/tty/serial/meson_uart.c @@ -34,9 +34,15 @@  /* AML_UART_CONTROL bits */  #define AML_UART_TX_EN			BIT(12)  #define AML_UART_RX_EN			BIT(13) +#define AML_UART_TWO_WIRE_EN		BIT(15) +#define AML_UART_STOP_BIT_LEN_MASK	(0x03 << 16) +#define AML_UART_STOP_BIT_1SB		(0x00 << 16) +#define AML_UART_STOP_BIT_2SB		(0x01 << 16) +#define AML_UART_PARITY_TYPE		BIT(18) +#define AML_UART_PARITY_EN		BIT(19)  #define AML_UART_TX_RST			BIT(22)  #define AML_UART_RX_RST			BIT(23) -#define AML_UART_CLR_ERR		BIT(24) +#define AML_UART_CLEAR_ERR		BIT(24)  #define AML_UART_RX_INT_EN		BIT(27)  #define AML_UART_TX_INT_EN		BIT(28)  #define AML_UART_DATA_LEN_MASK		(0x03 << 20) @@ -57,15 +63,6 @@  					 AML_UART_FRAME_ERR  | \  					 AML_UART_TX_FIFO_WERR) -/* AML_UART_CONTROL bits */ -#define AML_UART_TWO_WIRE_EN		BIT(15) -#define AML_UART_PARITY_TYPE		BIT(18) -#define AML_UART_PARITY_EN		BIT(19) -#define AML_UART_CLEAR_ERR		BIT(24) -#define AML_UART_STOP_BIN_LEN_MASK	(0x03 << 16) -#define AML_UART_STOP_BIN_1SB		(0x00 << 16) -#define AML_UART_STOP_BIN_2SB		(0x01 << 16) -  /* AML_UART_MISC bits */  #define AML_UART_XMIT_IRQ(c)		(((c) & 0xff) << 8)  #define AML_UART_RECV_IRQ(c)		((c) & 0xff) @@ -263,10 +260,10 @@ static void meson_uart_reset(struct uart_port *port)  	u32 val;  	val = readl(port->membase + AML_UART_CONTROL); -	val |= (AML_UART_RX_RST | AML_UART_TX_RST | AML_UART_CLR_ERR); +	val |= (AML_UART_RX_RST | AML_UART_TX_RST | AML_UART_CLEAR_ERR);  	writel(val, port->membase + AML_UART_CONTROL); -	val &= ~(AML_UART_RX_RST | AML_UART_TX_RST | AML_UART_CLR_ERR); +	val &= ~(AML_UART_RX_RST | AML_UART_TX_RST | AML_UART_CLEAR_ERR);  	writel(val, port->membase + AML_UART_CONTROL);  } @@ -276,9 +273,9 @@ static int meson_uart_startup(struct uart_port *port)  	int ret = 0;  	val = readl(port->membase + AML_UART_CONTROL); -	val |= AML_UART_CLR_ERR; +	val |= AML_UART_CLEAR_ERR;  	writel(val, port->membase + AML_UART_CONTROL); -	val &= ~AML_UART_CLR_ERR; +	val &= ~AML_UART_CLEAR_ERR;  	writel(val, port->membase + AML_UART_CONTROL);  	val |= (AML_UART_RX_EN | AML_UART_TX_EN); @@ -354,11 +351,11 @@ static void meson_uart_set_termios(struct uart_port *port,  	else  		val &= ~AML_UART_PARITY_TYPE; -	val &= ~AML_UART_STOP_BIN_LEN_MASK; +	val &= ~AML_UART_STOP_BIT_LEN_MASK;  	if (cflags & CSTOPB) -		val |= AML_UART_STOP_BIN_2SB; +		val |= AML_UART_STOP_BIT_2SB;  	else -		val |= AML_UART_STOP_BIN_1SB; +		val |= AML_UART_STOP_BIT_1SB;  	if (cflags & CRTSCTS)  		val &= ~AML_UART_TWO_WIRE_EN; diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c index efb4fd3784ed..079dc47aa142 100644 --- a/drivers/tty/serial/mxs-auart.c +++ b/drivers/tty/serial/mxs-auart.c @@ -40,7 +40,6 @@  #include <asm/cacheflush.h> -#include <linux/gpio.h>  #include <linux/gpio/consumer.h>  #include <linux/err.h>  #include <linux/irq.h> @@ -1597,7 +1596,7 @@ static int mxs_auart_init_gpios(struct mxs_auart_port *s, struct device *dev)  	for (i = 0; i < UART_GPIO_MAX; i++) {  		gpiod = mctrl_gpio_to_gpiod(s->gpios, i); -		if (gpiod && (gpiod_get_direction(gpiod) == GPIOF_DIR_IN)) +		if (gpiod && (gpiod_get_direction(gpiod) == 1))  			s->gpio_irq[i] = gpiod_to_irq(gpiod);  		else  			s->gpio_irq[i] = -EINVAL; @@ -1721,7 +1720,7 @@ static int mxs_auart_probe(struct platform_device *pdev)  	ret = uart_add_one_port(&auart_driver, &s->port);  	if (ret) -		goto out_free_gpio_irq; +		goto out_disable_clks_free_qpio_irq;  	/* ASM9260 don't have version reg */  	if (is_asm9260_auart(s)) { @@ -1735,7 +1734,11 @@ static int mxs_auart_probe(struct platform_device *pdev)  	return 0; -out_free_gpio_irq: +out_disable_clks_free_qpio_irq: +	if (s->clk) +		clk_disable_unprepare(s->clk_ahb); +	if (s->clk_ahb) +		clk_disable_unprepare(s->clk_ahb);  	mxs_auart_free_gpio_irq(s);  	auart_port[pdev->id] = NULL;  	return ret; diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 53d59e9b944a..6420ae581a80 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -1602,7 +1602,6 @@ static int serial_omap_probe_rs485(struct uart_omap_port *up,  				   struct device_node *np)  {  	struct serial_rs485 *rs485conf = &up->port.rs485; -	enum of_gpio_flags flags;  	int ret;  	rs485conf->flags = 0; @@ -1611,19 +1610,24 @@ static int serial_omap_probe_rs485(struct uart_omap_port *up,  	if (!np)  		return 0; -	if (of_property_read_bool(np, "rs485-rts-active-high")) +	uart_get_rs485_mode(up->dev, rs485conf); + +	if (of_property_read_bool(np, "rs485-rts-active-high")) {  		rs485conf->flags |= SER_RS485_RTS_ON_SEND; -	else +		rs485conf->flags &= ~SER_RS485_RTS_AFTER_SEND; +	} else { +		rs485conf->flags &= ~SER_RS485_RTS_ON_SEND;  		rs485conf->flags |= SER_RS485_RTS_AFTER_SEND; +	}  	/* check for tx enable gpio */ -	up->rts_gpio = of_get_named_gpio_flags(np, "rts-gpio", 0, &flags); +	up->rts_gpio = of_get_named_gpio(np, "rts-gpio", 0);  	if (gpio_is_valid(up->rts_gpio)) {  		ret = devm_gpio_request(up->dev, up->rts_gpio, "omap-serial");  		if (ret < 0)  			return ret; -		ret = gpio_direction_output(up->rts_gpio, -					    flags & SER_RS485_RTS_AFTER_SEND); +		ret = rs485conf->flags & SER_RS485_RTS_AFTER_SEND ? 1 : 0; +		ret = gpio_direction_output(up->rts_gpio, ret);  		if (ret < 0)  			return ret;  	} else if (up->rts_gpio == -EPROBE_DEFER) { @@ -1632,8 +1636,6 @@ static int serial_omap_probe_rs485(struct uart_omap_port *up,  		up->rts_gpio = -EINVAL;  	} -	of_get_rs485_mode(np, rs485conf); -  	return 0;  } diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 854995e1cae7..c8dde56b532b 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -974,6 +974,8 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port,  		}  	} else {  		retval = uart_startup(tty, state, 1); +		if (retval == 0) +			tty_port_set_initialized(port, true);  		if (retval > 0)  			retval = 0;  	} @@ -1955,9 +1957,10 @@ EXPORT_SYMBOL_GPL(uart_parse_earlycon);   *	eg: 115200n8r   */  void -uart_parse_options(char *options, int *baud, int *parity, int *bits, int *flow) +uart_parse_options(const char *options, int *baud, int *parity, +		   int *bits, int *flow)  { -	char *s = options; +	const char *s = options;  	*baud = simple_strtoul(s, NULL, 10);  	while (*s >= '0' && *s <= '9') @@ -3013,19 +3016,20 @@ EXPORT_SYMBOL(uart_add_one_port);  EXPORT_SYMBOL(uart_remove_one_port);  /** - * of_get_rs485_mode() - Implement parsing rs485 properties - * @np: uart node + * uart_get_rs485_mode() - retrieve rs485 properties for given uart + * @dev: uart device   * @rs485conf: output parameter   *   * This function implements the device tree binding described in   * Documentation/devicetree/bindings/serial/rs485.txt.   */ -void of_get_rs485_mode(struct device_node *np, struct serial_rs485 *rs485conf) +void uart_get_rs485_mode(struct device *dev, struct serial_rs485 *rs485conf)  {  	u32 rs485_delay[2];  	int ret; -	ret = of_property_read_u32_array(np, "rs485-rts-delay", rs485_delay, 2); +	ret = device_property_read_u32_array(dev, "rs485-rts-delay", +					     rs485_delay, 2);  	if (!ret) {  		rs485conf->delay_rts_before_send = rs485_delay[0];  		rs485conf->delay_rts_after_send = rs485_delay[1]; @@ -3035,18 +3039,25 @@ void of_get_rs485_mode(struct device_node *np, struct serial_rs485 *rs485conf)  	}  	/* -	 * clear full-duplex and enabled flags to get to a defined state with -	 * the two following properties. +	 * Clear full-duplex and enabled flags, set RTS polarity to active high +	 * to get to a defined state with the following properties:  	 */ -	rs485conf->flags &= ~(SER_RS485_RX_DURING_TX | SER_RS485_ENABLED); +	rs485conf->flags &= ~(SER_RS485_RX_DURING_TX | SER_RS485_ENABLED | +			      SER_RS485_RTS_AFTER_SEND); +	rs485conf->flags |= SER_RS485_RTS_ON_SEND; -	if (of_property_read_bool(np, "rs485-rx-during-tx")) +	if (device_property_read_bool(dev, "rs485-rx-during-tx"))  		rs485conf->flags |= SER_RS485_RX_DURING_TX; -	if (of_property_read_bool(np, "linux,rs485-enabled-at-boot-time")) +	if (device_property_read_bool(dev, "linux,rs485-enabled-at-boot-time"))  		rs485conf->flags |= SER_RS485_ENABLED; + +	if (device_property_read_bool(dev, "rs485-rts-active-low")) { +		rs485conf->flags &= ~SER_RS485_RTS_ON_SEND; +		rs485conf->flags |= SER_RS485_RTS_AFTER_SEND; +	}  } -EXPORT_SYMBOL_GPL(of_get_rs485_mode); +EXPORT_SYMBOL_GPL(uart_get_rs485_mode);  MODULE_DESCRIPTION("Serial driver core");  MODULE_LICENSE("GPL"); diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index d9f399c4e90c..7257c078e155 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -1144,7 +1144,7 @@ static ssize_t rx_fifo_timeout_store(struct device *dev,  	return count;  } -static DEVICE_ATTR(rx_fifo_timeout, 0644, rx_fifo_timeout_show, rx_fifo_timeout_store); +static DEVICE_ATTR_RW(rx_fifo_timeout);  #ifdef CONFIG_SERIAL_SH_SCI_DMA diff --git a/drivers/tty/serial/stm32-usart.h b/drivers/tty/serial/stm32-usart.h index 8a5ff54d0f42..2294d0f05872 100644 --- a/drivers/tty/serial/stm32-usart.h +++ b/drivers/tty/serial/stm32-usart.h @@ -236,7 +236,7 @@ struct stm32_usart_info stm32h7_info = {  #define USART_ICR_CMCF		BIT(17)		/* F7 */  #define USART_ICR_WUCF		BIT(20)		/* H7 */ -#define STM32_SERIAL_NAME "ttyS" +#define STM32_SERIAL_NAME "ttySTM"  #define STM32_MAX_PORTS 8  #define RX_BUF_L 200		 /* dma rx buffer length     */ diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index dc60aeea87d8..eb9133b472f4 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -144,7 +144,7 @@ static ssize_t tty_read(struct file *, char __user *, size_t, loff_t *);  static ssize_t tty_write(struct file *, const char __user *, size_t, loff_t *);  ssize_t redirected_tty_write(struct file *, const char __user *,  							size_t, loff_t *); -static unsigned int tty_poll(struct file *, poll_table *); +static __poll_t tty_poll(struct file *, poll_table *);  static int tty_open(struct inode *, struct file *);  long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg);  #ifdef CONFIG_COMPAT @@ -443,9 +443,9 @@ static ssize_t hung_up_tty_write(struct file *file, const char __user *buf,  }  /* No kernel lock held - none needed ;) */ -static unsigned int hung_up_tty_poll(struct file *filp, poll_table *wait) +static __poll_t hung_up_tty_poll(struct file *filp, poll_table *wait)  { -	return POLLIN | POLLOUT | POLLERR | POLLHUP | POLLRDNORM | POLLWRNORM; +	return EPOLLIN | EPOLLOUT | EPOLLERR | EPOLLHUP | EPOLLRDNORM | EPOLLWRNORM;  }  static long hung_up_tty_ioctl(struct file *file, unsigned int cmd, @@ -533,7 +533,7 @@ void tty_wakeup(struct tty_struct *tty)  			tty_ldisc_deref(ld);  		}  	} -	wake_up_interruptible_poll(&tty->write_wait, POLLOUT); +	wake_up_interruptible_poll(&tty->write_wait, EPOLLOUT);  }  EXPORT_SYMBOL_GPL(tty_wakeup); @@ -867,7 +867,7 @@ static ssize_t tty_read(struct file *file, char __user *buf, size_t count,  static void tty_write_unlock(struct tty_struct *tty)  {  	mutex_unlock(&tty->atomic_write_lock); -	wake_up_interruptible_poll(&tty->write_wait, POLLOUT); +	wake_up_interruptible_poll(&tty->write_wait, EPOLLOUT);  }  static int tty_write_lock(struct tty_struct *tty, int ndelay) @@ -1323,6 +1323,9 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx)  			"%s: %s driver does not set tty->port. This will crash the kernel later. Fix the driver!\n",  			__func__, tty->driver->name); +	retval = tty_ldisc_lock(tty, 5 * HZ); +	if (retval) +		goto err_release_lock;  	tty->port->itty = tty;  	/* @@ -1333,6 +1336,7 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx)  	retval = tty_ldisc_setup(tty, tty->link);  	if (retval)  		goto err_release_tty; +	tty_ldisc_unlock(tty);  	/* Return the tty locked so that it cannot vanish under the caller */  	return tty; @@ -1345,9 +1349,11 @@ err_module_put:  	/* call the tty release_tty routine to clean out this slot */  err_release_tty: -	tty_unlock(tty); +	tty_ldisc_unlock(tty);  	tty_info_ratelimited(tty, "ldisc open failed (%d), clearing slot %d\n",  			     retval, idx); +err_release_lock: +	tty_unlock(tty);  	release_tty(tty, idx);  	return ERR_PTR(retval);  } @@ -1476,6 +1482,8 @@ static void release_tty(struct tty_struct *tty, int idx)  	if (tty->link)  		tty->link->port->itty = NULL;  	tty_buffer_cancel_work(tty->port); +	if (tty->link) +		tty_buffer_cancel_work(tty->link->port);  	tty_kref_put(tty->link);  	tty_kref_put(tty); @@ -1659,21 +1667,21 @@ int tty_release(struct inode *inode, struct file *filp)  		if (tty->count <= 1) {  			if (waitqueue_active(&tty->read_wait)) { -				wake_up_poll(&tty->read_wait, POLLIN); +				wake_up_poll(&tty->read_wait, EPOLLIN);  				do_sleep++;  			}  			if (waitqueue_active(&tty->write_wait)) { -				wake_up_poll(&tty->write_wait, POLLOUT); +				wake_up_poll(&tty->write_wait, EPOLLOUT);  				do_sleep++;  			}  		}  		if (o_tty && o_tty->count <= 1) {  			if (waitqueue_active(&o_tty->read_wait)) { -				wake_up_poll(&o_tty->read_wait, POLLIN); +				wake_up_poll(&o_tty->read_wait, EPOLLIN);  				do_sleep++;  			}  			if (waitqueue_active(&o_tty->write_wait)) { -				wake_up_poll(&o_tty->write_wait, POLLOUT); +				wake_up_poll(&o_tty->write_wait, EPOLLOUT);  				do_sleep++;  			}  		} @@ -2055,11 +2063,11 @@ retry_open:   *	may be re-entered freely by other callers.   */ -static unsigned int tty_poll(struct file *filp, poll_table *wait) +static __poll_t tty_poll(struct file *filp, poll_table *wait)  {  	struct tty_struct *tty = file_tty(filp);  	struct tty_ldisc *ld; -	int ret = 0; +	__poll_t ret = 0;  	if (tty_paranoia_check(tty, file_inode(filp), "tty_poll"))  		return 0; diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 24ec5c7e6b20..050f4d650891 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -337,7 +337,7 @@ static inline void __tty_ldisc_unlock(struct tty_struct *tty)  	ldsem_up_write(&tty->ldisc_sem);  } -static int tty_ldisc_lock(struct tty_struct *tty, unsigned long timeout) +int tty_ldisc_lock(struct tty_struct *tty, unsigned long timeout)  {  	int ret; @@ -348,7 +348,7 @@ static int tty_ldisc_lock(struct tty_struct *tty, unsigned long timeout)  	return 0;  } -static void tty_ldisc_unlock(struct tty_struct *tty) +void tty_ldisc_unlock(struct tty_struct *tty)  {  	clear_bit(TTY_LDISC_HALTED, &tty->flags);  	__tty_ldisc_unlock(tty); @@ -735,8 +735,8 @@ void tty_ldisc_hangup(struct tty_struct *tty, bool reinit)  		tty_ldisc_deref(ld);  	} -	wake_up_interruptible_poll(&tty->write_wait, POLLOUT); -	wake_up_interruptible_poll(&tty->read_wait, POLLIN); +	wake_up_interruptible_poll(&tty->write_wait, EPOLLOUT); +	wake_up_interruptible_poll(&tty->read_wait, EPOLLIN);  	/*  	 * Shutdown the current line discipline, and reset it to diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c index af4da9507180..7851383fbd6c 100644 --- a/drivers/tty/vt/selection.c +++ b/drivers/tty/vt/selection.c @@ -186,11 +186,7 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t  	}  	if (ps > pe)	/* make sel_start <= sel_end */ -	{ -		int tmp = ps; -		ps = pe; -		pe = tmp; -	} +		swap(ps, pe);  	if (sel_cons != vc_cons[fg_console].d) {  		clear_selection(); diff --git a/drivers/tty/vt/vc_screen.c b/drivers/tty/vt/vc_screen.c index 85b6634f518a..e4a66e1fd05f 100644 --- a/drivers/tty/vt/vc_screen.c +++ b/drivers/tty/vt/vc_screen.c @@ -559,11 +559,11 @@ unlock_out:  	return ret;  } -static unsigned int +static __poll_t  vcs_poll(struct file *file, poll_table *wait)  {  	struct vcs_poll_data *poll = vcs_poll_data_get(file); -	int ret = DEFAULT_POLLMASK|POLLERR|POLLPRI; +	__poll_t ret = DEFAULT_POLLMASK|EPOLLERR|EPOLLPRI;  	if (poll) {  		poll_wait(file, &poll->waitq, wait); |