17831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox/*
27831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox *
37831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox *  Copyright (C) 2008 Christian Pellegrin <chripell@evolware.org>
47831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox *
57831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox * This program is free software; you can redistribute it and/or modify
67831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox * it under the terms of the GNU General Public License as published by
77831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox * the Free Software Foundation; either version 2 of the License, or
87831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox * (at your option) any later version.
97831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox *
107831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox *
117831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox * Notes: the MAX3100 doesn't provide an interrupt on CTS so we have
127831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox * to use polling for flow control. TX empty IRQ is unusable, since
137831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox * writing conf clears FIFO buffer and we cannot have this interrupt
147831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox * always asking us for attention.
157831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox *
167831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox * Example platform data:
177831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
187831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox static struct plat_max3100 max3100_plat_data = {
197831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox .loopback = 0,
207831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox .crystal = 0,
217831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox .poll_time = 100,
227831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox };
237831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
247831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox static struct spi_board_info spi_board_info[] = {
257831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox {
267831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox .modalias	= "max3100",
277831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox .platform_data	= &max3100_plat_data,
287831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox .irq		= IRQ_EINT12,
297831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox .max_speed_hz	= 5*1000*1000,
307831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox .chip_select	= 0,
317831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox },
327831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox };
337831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
347831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox * The initial minor number is 209 in the low-density serial port:
357831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox * mknod /dev/ttyMAX0 c 204 209
367831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox */
377831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
387831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#define MAX3100_MAJOR 204
397831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#define MAX3100_MINOR 209
407831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox/* 4 MAX3100s should be enough for everyone */
417831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#define MAX_MAX3100 4
427831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
437831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#include <linux/delay.h>
445a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
457831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#include <linux/device.h>
46578b9ce0095ff3dd2c3b94508407c3be8fcce68dPaul Gortmaker#include <linux/module.h>
477831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#include <linux/serial_core.h>
487831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#include <linux/serial.h>
497831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#include <linux/spi/spi.h>
507831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#include <linux/freezer.h>
51ee160a38eee357ed2572cf41437d5814ce53c839Jiri Slaby#include <linux/tty.h>
52ee160a38eee357ed2572cf41437d5814ce53c839Jiri Slaby#include <linux/tty_flip.h>
537831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
547831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#include <linux/serial_max3100.h>
557831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
567831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#define MAX3100_C    (1<<14)
577831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#define MAX3100_D    (0<<14)
587831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#define MAX3100_W    (1<<15)
597831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#define MAX3100_RX   (0<<15)
607831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
617831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#define MAX3100_WC   (MAX3100_W  | MAX3100_C)
627831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#define MAX3100_RC   (MAX3100_RX | MAX3100_C)
637831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#define MAX3100_WD   (MAX3100_W  | MAX3100_D)
647831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#define MAX3100_RD   (MAX3100_RX | MAX3100_D)
657831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#define MAX3100_CMD  (3 << 14)
667831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
677831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#define MAX3100_T    (1<<14)
687831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#define MAX3100_R    (1<<15)
697831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
707831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#define MAX3100_FEN  (1<<13)
717831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#define MAX3100_SHDN (1<<12)
727831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#define MAX3100_TM   (1<<11)
737831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#define MAX3100_RM   (1<<10)
747831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#define MAX3100_PM   (1<<9)
757831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#define MAX3100_RAM  (1<<8)
767831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#define MAX3100_IR   (1<<7)
777831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#define MAX3100_ST   (1<<6)
787831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#define MAX3100_PE   (1<<5)
797831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#define MAX3100_L    (1<<4)
807831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#define MAX3100_BAUD (0xf)
817831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
827831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#define MAX3100_TE   (1<<10)
837831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#define MAX3100_RAFE (1<<10)
847831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#define MAX3100_RTS  (1<<9)
857831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#define MAX3100_CTS  (1<<9)
867831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#define MAX3100_PT   (1<<8)
877831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#define MAX3100_DATA (0xff)
887831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
897831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#define MAX3100_RT   (MAX3100_R | MAX3100_T)
907831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#define MAX3100_RTC  (MAX3100_RT | MAX3100_CTS | MAX3100_RAFE)
917831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
927831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox/* the following simulate a status reg for ignore_status_mask */
937831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#define MAX3100_STATUS_PE 1
947831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#define MAX3100_STATUS_FE 2
957831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#define MAX3100_STATUS_OE 4
967831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
977831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Coxstruct max3100_port {
987831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	struct uart_port port;
997831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	struct spi_device *spi;
1007831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
1017831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	int cts;	        /* last CTS received for flow ctrl */
1027831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	int tx_empty;		/* last TX empty bit */
1037831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
1047831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	spinlock_t conf_lock;	/* shared data */
1057831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	int conf_commit;	/* need to make changes */
1067831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	int conf;		/* configuration for the MAX31000
1077831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox				 * (bits 0-7, bits 8-11 are irqs) */
1087831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	int rts_commit;	        /* need to change rts */
1097831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	int rts;		/* rts status */
1107831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	int baud;		/* current baud rate */
1117831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
1127831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	int parity;		/* keeps track if we should send parity */
1137831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#define MAX3100_PARITY_ON 1
1147831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#define MAX3100_PARITY_ODD 2
1157831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#define MAX3100_7BIT 4
1167831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	int rx_enabled;	        /* if we should rx chars */
1177831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
1187831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	int irq;		/* irq assigned to the max3100 */
1197831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
1207831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	int minor;		/* minor number */
1217831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	int crystal;		/* 1 if 3.6864Mhz crystal 0 for 1.8432 */
1227831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	int loopback;		/* 1 if we are in loopback mode */
1237831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
1247831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	/* for handling irqs: need workqueue since we do spi_sync */
1257831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	struct workqueue_struct *workqueue;
1267831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	struct work_struct work;
1277831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	/* set to 1 to make the workhandler exit as soon as possible */
1287831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	int  force_end_work;
1297831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	/* need to know we are suspending to avoid deadlock on workqueue */
1307831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	int suspending;
1317831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
1327831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	/* hook for suspending MAX3100 via dedicated pin */
1337831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	void (*max3100_hw_suspend) (int suspend);
1347831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
1357831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	/* poll time (in ms) for ctrl lines */
1367831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	int poll_time;
1377831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	/* and its timer */
1387831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	struct timer_list	timer;
1397831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox};
1407831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
1417831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Coxstatic struct max3100_port *max3100s[MAX_MAX3100]; /* the chips */
1427831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Coxstatic DEFINE_MUTEX(max3100s_lock);		   /* race on probe */
1437831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
1447831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Coxstatic int max3100_do_parity(struct max3100_port *s, u16 c)
1457831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox{
1467831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	int parity;
1477831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
1487831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	if (s->parity & MAX3100_PARITY_ODD)
1497831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		parity = 1;
1507831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	else
1517831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		parity = 0;
1527831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
1537831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	if (s->parity & MAX3100_7BIT)
1547831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		c &= 0x7f;
1557831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	else
1567831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		c &= 0xff;
1577831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
1587831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	parity = parity ^ (hweight8(c) & 1);
1597831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	return parity;
1607831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox}
1617831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
1627831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Coxstatic int max3100_check_parity(struct max3100_port *s, u16 c)
1637831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox{
1647831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	return max3100_do_parity(s, c) == ((c >> 8) & 1);
1657831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox}
1667831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
1677831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Coxstatic void max3100_calc_parity(struct max3100_port *s, u16 *c)
1687831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox{
1697831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	if (s->parity & MAX3100_7BIT)
1707831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		*c &= 0x7f;
1717831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	else
1727831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		*c &= 0xff;
1737831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
1747831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	if (s->parity & MAX3100_PARITY_ON)
1757831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		*c |= max3100_do_parity(s, *c) << 8;
1767831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox}
1777831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
1787831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Coxstatic void max3100_work(struct work_struct *w);
1797831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
1807831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Coxstatic void max3100_dowork(struct max3100_port *s)
1817831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox{
1827831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	if (!s->force_end_work && !work_pending(&s->work) &&
1837831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	    !freezing(current) && !s->suspending)
1847831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		queue_work(s->workqueue, &s->work);
1857831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox}
1867831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
1877831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Coxstatic void max3100_timeout(unsigned long data)
1887831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox{
1897831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	struct max3100_port *s = (struct max3100_port *)data;
1907831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
191ebd2c8f6d2ec4012c267ecb95e72a57b8355a705Alan Cox	if (s->port.state) {
1927831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		max3100_dowork(s);
1937831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		mod_timer(&s->timer, jiffies + s->poll_time);
1947831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	}
1957831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox}
1967831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
1977831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Coxstatic int max3100_sr(struct max3100_port *s, u16 tx, u16 *rx)
1987831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox{
1997831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	struct spi_message message;
2007831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	u16 etx, erx;
2017831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	int status;
2027831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	struct spi_transfer tran = {
2037831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		.tx_buf = &etx,
2047831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		.rx_buf = &erx,
2057831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		.len = 2,
2067831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	};
2077831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
2087831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	etx = cpu_to_be16(tx);
2097831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	spi_message_init(&message);
2107831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	spi_message_add_tail(&tran, &message);
2117831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	status = spi_sync(s->spi, &message);
2127831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	if (status) {
2137831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		dev_warn(&s->spi->dev, "error while calling spi_sync\n");
2147831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		return -EIO;
2157831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	}
2167831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	*rx = be16_to_cpu(erx);
2177831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	s->tx_empty = (*rx & MAX3100_T) > 0;
2187831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	dev_dbg(&s->spi->dev, "%04x - %04x\n", tx, *rx);
2197831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	return 0;
2207831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox}
2217831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
2227831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Coxstatic int max3100_handlerx(struct max3100_port *s, u16 rx)
2237831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox{
2247831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	unsigned int ch, flg, status = 0;
2257831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	int ret = 0, cts;
2267831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
2277831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	if (rx & MAX3100_R && s->rx_enabled) {
2287831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		dev_dbg(&s->spi->dev, "%s\n", __func__);
2297831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		ch = rx & (s->parity & MAX3100_7BIT ? 0x7f : 0xff);
2307831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		if (rx & MAX3100_RAFE) {
2317831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox			s->port.icount.frame++;
2327831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox			flg = TTY_FRAME;
2337831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox			status |= MAX3100_STATUS_FE;
2347831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		} else {
2357831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox			if (s->parity & MAX3100_PARITY_ON) {
2367831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox				if (max3100_check_parity(s, rx)) {
2377831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox					s->port.icount.rx++;
2387831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox					flg = TTY_NORMAL;
2397831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox				} else {
2407831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox					s->port.icount.parity++;
2417831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox					flg = TTY_PARITY;
2427831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox					status |= MAX3100_STATUS_PE;
2437831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox				}
2447831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox			} else {
2457831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox				s->port.icount.rx++;
2467831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox				flg = TTY_NORMAL;
2477831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox			}
2487831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		}
2497831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		uart_insert_char(&s->port, status, MAX3100_STATUS_OE, ch, flg);
2507831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		ret = 1;
2517831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	}
2527831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
2537831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	cts = (rx & MAX3100_CTS) > 0;
2547831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	if (s->cts != cts) {
2557831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		s->cts = cts;
2567831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		uart_handle_cts_change(&s->port, cts ? TIOCM_CTS : 0);
2577831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	}
2587831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
2597831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	return ret;
2607831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox}
2617831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
2627831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Coxstatic void max3100_work(struct work_struct *w)
2637831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox{
2647831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	struct max3100_port *s = container_of(w, struct max3100_port, work);
2657831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	int rxchars;
2667831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	u16 tx, rx;
2677831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	int conf, cconf, rts, crts;
268ebd2c8f6d2ec4012c267ecb95e72a57b8355a705Alan Cox	struct circ_buf *xmit = &s->port.state->xmit;
2697831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
2707831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	dev_dbg(&s->spi->dev, "%s\n", __func__);
2717831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
2727831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	rxchars = 0;
2737831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	do {
2747831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		spin_lock(&s->conf_lock);
2757831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		conf = s->conf;
2767831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		cconf = s->conf_commit;
2777831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		s->conf_commit = 0;
2787831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		rts = s->rts;
2797831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		crts = s->rts_commit;
2807831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		s->rts_commit = 0;
2817831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		spin_unlock(&s->conf_lock);
2827831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		if (cconf)
2837831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox			max3100_sr(s, MAX3100_WC | conf, &rx);
2847831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		if (crts) {
2857831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox			max3100_sr(s, MAX3100_WD | MAX3100_TE |
2867831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox				   (s->rts ? MAX3100_RTS : 0), &rx);
2877831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox			rxchars += max3100_handlerx(s, rx);
2887831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		}
2897831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
2907831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		max3100_sr(s, MAX3100_RD, &rx);
2917831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		rxchars += max3100_handlerx(s, rx);
2927831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
2937831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		if (rx & MAX3100_T) {
2947831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox			tx = 0xffff;
2957831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox			if (s->port.x_char) {
2967831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox				tx = s->port.x_char;
2977831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox				s->port.icount.tx++;
2987831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox				s->port.x_char = 0;
2997831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox			} else if (!uart_circ_empty(xmit) &&
3007831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox				   !uart_tx_stopped(&s->port)) {
3017831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox				tx = xmit->buf[xmit->tail];
3027831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox				xmit->tail = (xmit->tail + 1) &
3037831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox					(UART_XMIT_SIZE - 1);
3047831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox				s->port.icount.tx++;
3057831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox			}
3067831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox			if (tx != 0xffff) {
3077831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox				max3100_calc_parity(s, &tx);
3087831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox				tx |= MAX3100_WD | (s->rts ? MAX3100_RTS : 0);
3097831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox				max3100_sr(s, tx, &rx);
3107831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox				rxchars += max3100_handlerx(s, rx);
3117831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox			}
3127831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		}
3137831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
314ebd2c8f6d2ec4012c267ecb95e72a57b8355a705Alan Cox		if (rxchars > 16 && s->port.state->port.tty != NULL) {
315ebd2c8f6d2ec4012c267ecb95e72a57b8355a705Alan Cox			tty_flip_buffer_push(s->port.state->port.tty);
3167831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox			rxchars = 0;
3177831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		}
3187831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
3197831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox			uart_write_wakeup(&s->port);
3207831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
3217831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	} while (!s->force_end_work &&
3227831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		 !freezing(current) &&
3237831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		 ((rx & MAX3100_R) ||
3247831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		  (!uart_circ_empty(xmit) &&
3257831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		   !uart_tx_stopped(&s->port))));
3267831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
327ebd2c8f6d2ec4012c267ecb95e72a57b8355a705Alan Cox	if (rxchars > 0 && s->port.state->port.tty != NULL)
328ebd2c8f6d2ec4012c267ecb95e72a57b8355a705Alan Cox		tty_flip_buffer_push(s->port.state->port.tty);
3297831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox}
3307831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
3317831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Coxstatic irqreturn_t max3100_irq(int irqno, void *dev_id)
3327831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox{
3337831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	struct max3100_port *s = dev_id;
3347831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
3357831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	dev_dbg(&s->spi->dev, "%s\n", __func__);
3367831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
3377831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	max3100_dowork(s);
3387831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	return IRQ_HANDLED;
3397831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox}
3407831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
3417831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Coxstatic void max3100_enable_ms(struct uart_port *port)
3427831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox{
3437831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	struct max3100_port *s = container_of(port,
3447831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox					      struct max3100_port,
3457831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox					      port);
3467831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
3477831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	if (s->poll_time > 0)
3487831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		mod_timer(&s->timer, jiffies);
3497831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	dev_dbg(&s->spi->dev, "%s\n", __func__);
3507831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox}
3517831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
3527831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Coxstatic void max3100_start_tx(struct uart_port *port)
3537831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox{
3547831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	struct max3100_port *s = container_of(port,
3557831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox					      struct max3100_port,
3567831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox					      port);
3577831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
3587831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	dev_dbg(&s->spi->dev, "%s\n", __func__);
3597831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
3607831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	max3100_dowork(s);
3617831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox}
3627831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
3637831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Coxstatic void max3100_stop_rx(struct uart_port *port)
3647831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox{
3657831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	struct max3100_port *s = container_of(port,
3667831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox					      struct max3100_port,
3677831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox					      port);
3687831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
3697831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	dev_dbg(&s->spi->dev, "%s\n", __func__);
3707831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
3717831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	s->rx_enabled = 0;
3727831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	spin_lock(&s->conf_lock);
3737831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	s->conf &= ~MAX3100_RM;
3747831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	s->conf_commit = 1;
3757831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	spin_unlock(&s->conf_lock);
3767831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	max3100_dowork(s);
3777831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox}
3787831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
3797831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Coxstatic unsigned int max3100_tx_empty(struct uart_port *port)
3807831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox{
3817831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	struct max3100_port *s = container_of(port,
3827831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox					      struct max3100_port,
3837831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox					      port);
3847831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
3857831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	dev_dbg(&s->spi->dev, "%s\n", __func__);
3867831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
3877831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	/* may not be truly up-to-date */
3887831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	max3100_dowork(s);
3897831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	return s->tx_empty;
3907831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox}
3917831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
3927831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Coxstatic unsigned int max3100_get_mctrl(struct uart_port *port)
3937831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox{
3947831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	struct max3100_port *s = container_of(port,
3957831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox					      struct max3100_port,
3967831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox					      port);
3977831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
3987831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	dev_dbg(&s->spi->dev, "%s\n", __func__);
3997831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
4007831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	/* may not be truly up-to-date */
4017831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	max3100_dowork(s);
4027831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	/* always assert DCD and DSR since these lines are not wired */
4037831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	return (s->cts ? TIOCM_CTS : 0) | TIOCM_DSR | TIOCM_CAR;
4047831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox}
4057831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
4067831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Coxstatic void max3100_set_mctrl(struct uart_port *port, unsigned int mctrl)
4077831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox{
4087831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	struct max3100_port *s = container_of(port,
4097831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox					      struct max3100_port,
4107831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox					      port);
4117831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	int rts;
4127831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
4137831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	dev_dbg(&s->spi->dev, "%s\n", __func__);
4147831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
4157831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	rts = (mctrl & TIOCM_RTS) > 0;
4167831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
4177831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	spin_lock(&s->conf_lock);
4187831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	if (s->rts != rts) {
4197831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		s->rts = rts;
4207831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		s->rts_commit = 1;
4217831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		max3100_dowork(s);
4227831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	}
4237831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	spin_unlock(&s->conf_lock);
4247831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox}
4257831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
4267831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Coxstatic void
4277831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Coxmax3100_set_termios(struct uart_port *port, struct ktermios *termios,
4287831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		    struct ktermios *old)
4297831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox{
4307831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	struct max3100_port *s = container_of(port,
4317831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox					      struct max3100_port,
4327831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox					      port);
4337831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	int baud = 0;
4347831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	unsigned cflag;
4357831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	u32 param_new, param_mask, parity = 0;
4367831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
4377831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	dev_dbg(&s->spi->dev, "%s\n", __func__);
4387831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
4397831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	cflag = termios->c_cflag;
4407831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	param_new = 0;
4417831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	param_mask = 0;
4427831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
443eab4f5af6b07009d1fc48bac5f3215c0cbfb2fc3Alan Cox	baud = tty_termios_baud_rate(termios);
4447831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	param_new = s->conf & MAX3100_BAUD;
4457831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	switch (baud) {
4467831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	case 300:
4477831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		if (s->crystal)
4487831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox			baud = s->baud;
4497831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		else
4507831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox			param_new = 15;
4517831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		break;
4527831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	case 600:
4537831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		param_new = 14 + s->crystal;
4547831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		break;
4557831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	case 1200:
4567831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		param_new = 13 + s->crystal;
4577831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		break;
4587831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	case 2400:
4597831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		param_new = 12 + s->crystal;
4607831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		break;
4617831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	case 4800:
4627831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		param_new = 11 + s->crystal;
4637831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		break;
4647831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	case 9600:
4657831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		param_new = 10 + s->crystal;
4667831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		break;
4677831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	case 19200:
4687831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		param_new = 9 + s->crystal;
4697831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		break;
4707831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	case 38400:
4717831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		param_new = 8 + s->crystal;
4727831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		break;
4737831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	case 57600:
4747831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		param_new = 1 + s->crystal;
4757831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		break;
4767831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	case 115200:
4777831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		param_new = 0 + s->crystal;
4787831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		break;
4797831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	case 230400:
4807831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		if (s->crystal)
4817831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox			param_new = 0;
4827831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		else
4837831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox			baud = s->baud;
4847831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		break;
4857831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	default:
4867831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		baud = s->baud;
4877831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	}
488eab4f5af6b07009d1fc48bac5f3215c0cbfb2fc3Alan Cox	tty_termios_encode_baud_rate(termios, baud, baud);
4897831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	s->baud = baud;
4907831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	param_mask |= MAX3100_BAUD;
4917831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
4927831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	if ((cflag & CSIZE) == CS8) {
4937831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		param_new &= ~MAX3100_L;
4947831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		parity &= ~MAX3100_7BIT;
4957831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	} else {
4967831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		param_new |= MAX3100_L;
4977831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		parity |= MAX3100_7BIT;
4987831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		cflag = (cflag & ~CSIZE) | CS7;
4997831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	}
5007831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	param_mask |= MAX3100_L;
5017831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
5027831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	if (cflag & CSTOPB)
5037831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		param_new |= MAX3100_ST;
5047831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	else
5057831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		param_new &= ~MAX3100_ST;
5067831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	param_mask |= MAX3100_ST;
5077831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
5087831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	if (cflag & PARENB) {
5097831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		param_new |= MAX3100_PE;
5107831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		parity |= MAX3100_PARITY_ON;
5117831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	} else {
5127831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		param_new &= ~MAX3100_PE;
5137831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		parity &= ~MAX3100_PARITY_ON;
5147831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	}
5157831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	param_mask |= MAX3100_PE;
5167831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
5177831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	if (cflag & PARODD)
5187831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		parity |= MAX3100_PARITY_ODD;
5197831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	else
5207831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		parity &= ~MAX3100_PARITY_ODD;
5217831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
5227831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	/* mask termios capabilities we don't support */
5237831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	cflag &= ~CMSPAR;
5247831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	termios->c_cflag = cflag;
5257831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
5267831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	s->port.ignore_status_mask = 0;
5277831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	if (termios->c_iflag & IGNPAR)
5287831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		s->port.ignore_status_mask |=
5297831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox			MAX3100_STATUS_PE | MAX3100_STATUS_FE |
5307831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox			MAX3100_STATUS_OE;
5317831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
5327831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	/* we are sending char from a workqueue so enable */
533ebd2c8f6d2ec4012c267ecb95e72a57b8355a705Alan Cox	s->port.state->port.tty->low_latency = 1;
5347831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
5357831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	if (s->poll_time > 0)
5367831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		del_timer_sync(&s->timer);
5377831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
5387831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	uart_update_timeout(port, termios->c_cflag, baud);
5397831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
5407831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	spin_lock(&s->conf_lock);
5417831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	s->conf = (s->conf & ~param_mask) | (param_new & param_mask);
5427831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	s->conf_commit = 1;
5437831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	s->parity = parity;
5447831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	spin_unlock(&s->conf_lock);
5457831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	max3100_dowork(s);
5467831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
5477831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	if (UART_ENABLE_MS(&s->port, termios->c_cflag))
5487831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		max3100_enable_ms(&s->port);
5497831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox}
5507831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
5517831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Coxstatic void max3100_shutdown(struct uart_port *port)
5527831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox{
5537831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	struct max3100_port *s = container_of(port,
5547831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox					      struct max3100_port,
5557831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox					      port);
5567831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
5577831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	dev_dbg(&s->spi->dev, "%s\n", __func__);
5587831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
5597831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	if (s->suspending)
5607831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		return;
5617831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
5627831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	s->force_end_work = 1;
5637831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
5647831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	if (s->poll_time > 0)
5657831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		del_timer_sync(&s->timer);
5667831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
5677831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	if (s->workqueue) {
5687831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		flush_workqueue(s->workqueue);
5697831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		destroy_workqueue(s->workqueue);
5707831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		s->workqueue = NULL;
5717831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	}
5727831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	if (s->irq)
5737831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		free_irq(s->irq, s);
5747831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
5757831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	/* set shutdown mode to save power */
5767831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	if (s->max3100_hw_suspend)
5777831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		s->max3100_hw_suspend(1);
5787831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	else  {
5797831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		u16 tx, rx;
5807831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
5817831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		tx = MAX3100_WC | MAX3100_SHDN;
5827831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		max3100_sr(s, tx, &rx);
5837831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	}
5847831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox}
5857831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
5867831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Coxstatic int max3100_startup(struct uart_port *port)
5877831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox{
5887831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	struct max3100_port *s = container_of(port,
5897831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox					      struct max3100_port,
5907831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox					      port);
5917831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	char b[12];
5927831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
5937831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	dev_dbg(&s->spi->dev, "%s\n", __func__);
5947831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
5957831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	s->conf = MAX3100_RM;
5967831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	s->baud = s->crystal ? 230400 : 115200;
5977831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	s->rx_enabled = 1;
5987831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
5997831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	if (s->suspending)
6007831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		return 0;
6017831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
6027831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	s->force_end_work = 0;
6037831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	s->parity = 0;
6047831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	s->rts = 0;
6057831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
6067831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	sprintf(b, "max3100-%d", s->minor);
60758a69cb47ec6991bf006a3e5d202e8571b0327a4Tejun Heo	s->workqueue = create_freezable_workqueue(b);
6087831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	if (!s->workqueue) {
6097831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		dev_warn(&s->spi->dev, "cannot create workqueue\n");
6107831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		return -EBUSY;
6117831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	}
6127831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	INIT_WORK(&s->work, max3100_work);
6137831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
6147831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	if (request_irq(s->irq, max3100_irq,
6157831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox			IRQF_TRIGGER_FALLING, "max3100", s) < 0) {
6167831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		dev_warn(&s->spi->dev, "cannot allocate irq %d\n", s->irq);
6177831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		s->irq = 0;
6187831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		destroy_workqueue(s->workqueue);
6197831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		s->workqueue = NULL;
6207831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		return -EBUSY;
6217831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	}
6227831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
6237831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	if (s->loopback) {
6247831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		u16 tx, rx;
6257831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		tx = 0x4001;
6267831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		max3100_sr(s, tx, &rx);
6277831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	}
6287831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
6297831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	if (s->max3100_hw_suspend)
6307831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		s->max3100_hw_suspend(0);
6317831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	s->conf_commit = 1;
6327831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	max3100_dowork(s);
6337831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	/* wait for clock to settle */
6347831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	msleep(50);
6357831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
6367831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	max3100_enable_ms(&s->port);
6377831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
6387831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	return 0;
6397831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox}
6407831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
6417831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Coxstatic const char *max3100_type(struct uart_port *port)
6427831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox{
6437831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	struct max3100_port *s = container_of(port,
6447831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox					      struct max3100_port,
6457831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox					      port);
6467831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
6477831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	dev_dbg(&s->spi->dev, "%s\n", __func__);
6487831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
6497831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	return s->port.type == PORT_MAX3100 ? "MAX3100" : NULL;
6507831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox}
6517831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
6527831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Coxstatic void max3100_release_port(struct uart_port *port)
6537831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox{
6547831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	struct max3100_port *s = container_of(port,
6557831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox					      struct max3100_port,
6567831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox					      port);
6577831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
6587831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	dev_dbg(&s->spi->dev, "%s\n", __func__);
6597831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox}
6607831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
6617831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Coxstatic void max3100_config_port(struct uart_port *port, int flags)
6627831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox{
6637831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	struct max3100_port *s = container_of(port,
6647831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox					      struct max3100_port,
6657831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox					      port);
6667831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
6677831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	dev_dbg(&s->spi->dev, "%s\n", __func__);
6687831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
6697831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	if (flags & UART_CONFIG_TYPE)
6707831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		s->port.type = PORT_MAX3100;
6717831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox}
6727831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
6737831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Coxstatic int max3100_verify_port(struct uart_port *port,
6747831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox			       struct serial_struct *ser)
6757831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox{
6767831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	struct max3100_port *s = container_of(port,
6777831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox					      struct max3100_port,
6787831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox					      port);
6797831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	int ret = -EINVAL;
6807831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
6817831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	dev_dbg(&s->spi->dev, "%s\n", __func__);
6827831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
6837831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	if (ser->type == PORT_UNKNOWN || ser->type == PORT_MAX3100)
6847831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		ret = 0;
6857831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	return ret;
6867831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox}
6877831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
6887831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Coxstatic void max3100_stop_tx(struct uart_port *port)
6897831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox{
6907831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	struct max3100_port *s = container_of(port,
6917831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox					      struct max3100_port,
6927831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox					      port);
6937831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
6947831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	dev_dbg(&s->spi->dev, "%s\n", __func__);
6957831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox}
6967831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
6977831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Coxstatic int max3100_request_port(struct uart_port *port)
6987831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox{
6997831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	struct max3100_port *s = container_of(port,
7007831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox					      struct max3100_port,
7017831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox					      port);
7027831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
7037831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	dev_dbg(&s->spi->dev, "%s\n", __func__);
7047831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	return 0;
7057831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox}
7067831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
7077831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Coxstatic void max3100_break_ctl(struct uart_port *port, int break_state)
7087831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox{
7097831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	struct max3100_port *s = container_of(port,
7107831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox					      struct max3100_port,
7117831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox					      port);
7127831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
7137831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	dev_dbg(&s->spi->dev, "%s\n", __func__);
7147831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox}
7157831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
7167831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Coxstatic struct uart_ops max3100_ops = {
7177831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	.tx_empty	= max3100_tx_empty,
7187831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	.set_mctrl	= max3100_set_mctrl,
7197831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	.get_mctrl	= max3100_get_mctrl,
7207831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	.stop_tx        = max3100_stop_tx,
7217831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	.start_tx	= max3100_start_tx,
7227831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	.stop_rx	= max3100_stop_rx,
7237831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	.enable_ms      = max3100_enable_ms,
7247831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	.break_ctl      = max3100_break_ctl,
7257831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	.startup	= max3100_startup,
7267831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	.shutdown	= max3100_shutdown,
7277831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	.set_termios	= max3100_set_termios,
7287831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	.type		= max3100_type,
7297831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	.release_port   = max3100_release_port,
7307831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	.request_port   = max3100_request_port,
7317831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	.config_port	= max3100_config_port,
7327831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	.verify_port	= max3100_verify_port,
7337831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox};
7347831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
7357831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Coxstatic struct uart_driver max3100_uart_driver = {
7367831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	.owner          = THIS_MODULE,
7377831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	.driver_name    = "ttyMAX",
7387831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	.dev_name       = "ttyMAX",
7397831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	.major          = MAX3100_MAJOR,
7407831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	.minor          = MAX3100_MINOR,
7417831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	.nr             = MAX_MAX3100,
7427831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox};
7437831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Coxstatic int uart_driver_registered;
7447831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
7457831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Coxstatic int __devinit max3100_probe(struct spi_device *spi)
7467831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox{
7477831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	int i, retval;
7487831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	struct plat_max3100 *pdata;
7497831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	u16 tx, rx;
7507831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
7517831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	mutex_lock(&max3100s_lock);
7527831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
7537831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	if (!uart_driver_registered) {
7547831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		uart_driver_registered = 1;
7557831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		retval = uart_register_driver(&max3100_uart_driver);
7567831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		if (retval) {
7577831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox			printk(KERN_ERR "Couldn't register max3100 uart driver\n");
7587831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox			mutex_unlock(&max3100s_lock);
7597831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox			return retval;
7607831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		}
7617831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	}
7627831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
7637831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	for (i = 0; i < MAX_MAX3100; i++)
7647831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		if (!max3100s[i])
7657831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox			break;
7667831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	if (i == MAX_MAX3100) {
7677831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		dev_warn(&spi->dev, "too many MAX3100 chips\n");
7687831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		mutex_unlock(&max3100s_lock);
7697831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		return -ENOMEM;
7707831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	}
7717831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
7727831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	max3100s[i] = kzalloc(sizeof(struct max3100_port), GFP_KERNEL);
7737831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	if (!max3100s[i]) {
7747831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		dev_warn(&spi->dev,
7757831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox			 "kmalloc for max3100 structure %d failed!\n", i);
7767831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		mutex_unlock(&max3100s_lock);
7777831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		return -ENOMEM;
7787831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	}
7797831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	max3100s[i]->spi = spi;
7807831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	max3100s[i]->irq = spi->irq;
7817831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	spin_lock_init(&max3100s[i]->conf_lock);
7827831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	dev_set_drvdata(&spi->dev, max3100s[i]);
7837831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	pdata = spi->dev.platform_data;
7847831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	max3100s[i]->crystal = pdata->crystal;
7857831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	max3100s[i]->loopback = pdata->loopback;
7867831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	max3100s[i]->poll_time = pdata->poll_time * HZ / 1000;
7877831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	if (pdata->poll_time > 0 && max3100s[i]->poll_time == 0)
7887831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		max3100s[i]->poll_time = 1;
7897831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	max3100s[i]->max3100_hw_suspend = pdata->max3100_hw_suspend;
7907831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	max3100s[i]->minor = i;
7917831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	init_timer(&max3100s[i]->timer);
7927831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	max3100s[i]->timer.function = max3100_timeout;
7937831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	max3100s[i]->timer.data = (unsigned long) max3100s[i];
7947831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
7957831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	dev_dbg(&spi->dev, "%s: adding port %d\n", __func__, i);
7967831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	max3100s[i]->port.irq = max3100s[i]->irq;
7977831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	max3100s[i]->port.uartclk = max3100s[i]->crystal ? 3686400 : 1843200;
7987831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	max3100s[i]->port.fifosize = 16;
7997831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	max3100s[i]->port.ops = &max3100_ops;
8007831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	max3100s[i]->port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
8017831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	max3100s[i]->port.line = i;
8027831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	max3100s[i]->port.type = PORT_MAX3100;
8037831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	max3100s[i]->port.dev = &spi->dev;
8047831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	retval = uart_add_one_port(&max3100_uart_driver, &max3100s[i]->port);
8057831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	if (retval < 0)
8067831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		dev_warn(&spi->dev,
8077831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox			 "uart_add_one_port failed for line %d with error %d\n",
8087831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox			 i, retval);
8097831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
8107831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	/* set shutdown mode to save power. Will be woken-up on open */
8117831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	if (max3100s[i]->max3100_hw_suspend)
8127831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		max3100s[i]->max3100_hw_suspend(1);
8137831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	else {
8147831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		tx = MAX3100_WC | MAX3100_SHDN;
8157831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		max3100_sr(max3100s[i], tx, &rx);
8167831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	}
8177831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	mutex_unlock(&max3100s_lock);
8187831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	return 0;
8197831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox}
8207831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
8217831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Coxstatic int __devexit max3100_remove(struct spi_device *spi)
8227831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox{
8237831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	struct max3100_port *s = dev_get_drvdata(&spi->dev);
8247831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	int i;
8257831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
8267831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	mutex_lock(&max3100s_lock);
8277831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
8287831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	/* find out the index for the chip we are removing */
8297831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	for (i = 0; i < MAX_MAX3100; i++)
8307831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		if (max3100s[i] == s)
8317831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox			break;
8327831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
8337831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	dev_dbg(&spi->dev, "%s: removing port %d\n", __func__, i);
8347831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	uart_remove_one_port(&max3100_uart_driver, &max3100s[i]->port);
8357831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	kfree(max3100s[i]);
8367831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	max3100s[i] = NULL;
8377831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
8387831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	/* check if this is the last chip we have */
8397831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	for (i = 0; i < MAX_MAX3100; i++)
8407831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		if (max3100s[i]) {
8417831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox			mutex_unlock(&max3100s_lock);
8427831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox			return 0;
8437831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		}
8447831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	pr_debug("removing max3100 driver\n");
8457831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	uart_unregister_driver(&max3100_uart_driver);
8467831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
8477831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	mutex_unlock(&max3100s_lock);
8487831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	return 0;
8497831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox}
8507831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
8517831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#ifdef CONFIG_PM
8527831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
8537831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Coxstatic int max3100_suspend(struct spi_device *spi, pm_message_t state)
8547831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox{
8557831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	struct max3100_port *s = dev_get_drvdata(&spi->dev);
8567831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
8577831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	dev_dbg(&s->spi->dev, "%s\n", __func__);
8587831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
8597831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	disable_irq(s->irq);
8607831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
8617831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	s->suspending = 1;
8627831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	uart_suspend_port(&max3100_uart_driver, &s->port);
8637831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
8647831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	if (s->max3100_hw_suspend)
8657831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		s->max3100_hw_suspend(1);
8667831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	else {
8677831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		/* no HW suspend, so do SW one */
8687831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		u16 tx, rx;
8697831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
8707831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		tx = MAX3100_WC | MAX3100_SHDN;
8717831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		max3100_sr(s, tx, &rx);
8727831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	}
8737831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	return 0;
8747831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox}
8757831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
8767831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Coxstatic int max3100_resume(struct spi_device *spi)
8777831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox{
8787831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	struct max3100_port *s = dev_get_drvdata(&spi->dev);
8797831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
8807831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	dev_dbg(&s->spi->dev, "%s\n", __func__);
8817831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
8827831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	if (s->max3100_hw_suspend)
8837831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		s->max3100_hw_suspend(0);
8847831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	uart_resume_port(&max3100_uart_driver, &s->port);
8857831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	s->suspending = 0;
8867831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
8877831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	enable_irq(s->irq);
8887831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
8897831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	s->conf_commit = 1;
8907831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	if (s->workqueue)
8917831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		max3100_dowork(s);
8927831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
8937831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	return 0;
8947831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox}
8957831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
8967831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#else
8977831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#define max3100_suspend NULL
8987831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#define max3100_resume  NULL
8997831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox#endif
9007831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
9017831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Coxstatic struct spi_driver max3100_driver = {
9027831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	.driver = {
9037831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		.name		= "max3100",
9047831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox		.owner		= THIS_MODULE,
9057831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	},
9067831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
9077831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	.probe		= max3100_probe,
9087831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	.remove		= __devexit_p(max3100_remove),
9097831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	.suspend	= max3100_suspend,
9107831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	.resume		= max3100_resume,
9117831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox};
9127831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
9137831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Coxstatic int __init max3100_init(void)
9147831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox{
9157831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	return spi_register_driver(&max3100_driver);
9167831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox}
9177831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Coxmodule_init(max3100_init);
9187831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
9197831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Coxstatic void __exit max3100_exit(void)
9207831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox{
9217831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox	spi_unregister_driver(&max3100_driver);
9227831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox}
9237831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Coxmodule_exit(max3100_exit);
9247831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan Cox
9257831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan CoxMODULE_DESCRIPTION("MAX3100 driver");
9267831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan CoxMODULE_AUTHOR("Christian Pellegrin <chripell@evolware.org>");
9277831d56b0a3544cbb6f82f76c34ca95e24d5b676Alan CoxMODULE_LICENSE("GPL");
928e0626e3844e8f430fc1a4417f523a00797df7ca6Anton VorontsovMODULE_ALIAS("spi:max3100");
929