summaryrefslogtreecommitdiff
path: root/drivers/serial/max3107.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/serial/max3107.c')
-rw-r--r--drivers/serial/max3107.c413
1 files changed, 84 insertions, 329 deletions
diff --git a/drivers/serial/max3107.c b/drivers/serial/max3107.c
index a96ddd3..67283c1 100644
--- a/drivers/serial/max3107.c
+++ b/drivers/serial/max3107.c
@@ -31,98 +31,12 @@
#include <linux/device.h>
#include <linux/serial_core.h>
#include <linux/serial.h>
+#include <linux/gpio.h>
#include <linux/spi/spi.h>
#include <linux/freezer.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <linux/sfi.h>
-#include <asm/mrst.h>
#include "max3107.h"
-struct baud_table {
- int baud;
- u32 new_brg;
-};
-
-struct max3107_port {
- /* UART port structure */
- struct uart_port port;
-
- /* SPI device structure */
- struct spi_device *spi;
-
- /* GPIO chip stucture */
- struct gpio_chip chip;
-
- /* Workqueue that does all the magic */
- struct workqueue_struct *workqueue;
- struct work_struct work;
-
- /* Lock for shared data */
- spinlock_t data_lock;
-
- /* Device configuration */
- int ext_clk; /* 1 if external clock used */
- int loopback; /* Current loopback mode state */
- int baud; /* Current baud rate */
-
- /* State flags */
- int suspended; /* Indicates suspend mode */
- int tx_fifo_empty; /* Flag for TX FIFO state */
- int rx_enabled; /* Flag for receiver state */
- int tx_enabled; /* Flag for transmitter state */
-
- u16 irqen_reg; /* Current IRQ enable register value */
- /* Shared data */
- u16 mode1_reg; /* Current mode1 register value*/
- int mode1_commit; /* Flag for setting new mode1 register value */
- u16 lcr_reg; /* Current LCR register value */
- int lcr_commit; /* Flag for setting new LCR register value */
- u32 brg_cfg; /* Current Baud rate generator config */
- int brg_commit; /* Flag for setting new baud rate generator
- * config
- */
- struct baud_table *baud_tbl;
- int handle_irq; /* Indicates that IRQ should be handled */
-
- /* Rx buffer and str*/
- u16 *rxbuf;
- u8 *rxstr;
- /* Tx buffer*/
- u16 *txbuf;
-};
-
-/* Platform data structure */
-struct max3107_plat {
- /* Loopback mode enable */
- int loopback;
- /* External clock enable */
- int ext_clk;
- /* HW suspend function */
- void (*max3107_hw_suspend) (struct max3107_port *s, int suspend);
- /* Polling mode enable */
- int polled_mode;
- /* Polling period if polling mode enabled */
- int poll_time;
-};
-
-static struct baud_table brg13_ext[] = {
- { 300, MAX3107_BRG13_B300 },
- { 600, MAX3107_BRG13_B600 },
- { 1200, MAX3107_BRG13_B1200 },
- { 2400, MAX3107_BRG13_B2400 },
- { 4800, MAX3107_BRG13_B4800 },
- { 9600, MAX3107_BRG13_B9600 },
- { 19200, MAX3107_BRG13_B19200 },
- { 57600, MAX3107_BRG13_B57600 },
- { 115200, MAX3107_BRG13_B115200 },
- { 230400, MAX3107_BRG13_B230400 },
- { 460800, MAX3107_BRG13_B460800 },
- { 921600, MAX3107_BRG13_B921600 },
- { 0, 0 }
-};
-
-static struct baud_table brg26_ext[] = {
+static const struct baud_table brg26_ext[] = {
{ 300, MAX3107_BRG26_B300 },
{ 600, MAX3107_BRG26_B600 },
{ 1200, MAX3107_BRG26_B1200 },
@@ -138,7 +52,7 @@ static struct baud_table brg26_ext[] = {
{ 0, 0 }
};
-static struct baud_table brg13_int[] = {
+static const struct baud_table brg13_int[] = {
{ 300, MAX3107_BRG13_IB300 },
{ 600, MAX3107_BRG13_IB600 },
{ 1200, MAX3107_BRG13_IB1200 },
@@ -157,7 +71,7 @@ static struct baud_table brg13_int[] = {
static u32 get_new_brg(int baud, struct max3107_port *s)
{
int i;
- struct baud_table *baud_tbl = s->baud_tbl;
+ const struct baud_table *baud_tbl = s->baud_tbl;
for (i = 0; i < 13; i++) {
if (baud == baud_tbl[i].baud)
@@ -168,7 +82,7 @@ static u32 get_new_brg(int baud, struct max3107_port *s)
}
/* Perform SPI transfer for write/read of device register(s) */
-static int max3107_rw(struct max3107_port *s, u8 *tx, u8 *rx, int len)
+int max3107_rw(struct max3107_port *s, u8 *tx, u8 *rx, int len)
{
struct spi_message spi_msg;
struct spi_transfer spi_xfer;
@@ -213,6 +127,7 @@ static int max3107_rw(struct max3107_port *s, u8 *tx, u8 *rx, int len)
#endif
return 0;
}
+EXPORT_SYMBOL_GPL(max3107_rw);
/* Puts received data to circular buffer */
static void put_data_to_circ_buf(struct max3107_port *s, unsigned char *data,
@@ -611,16 +526,10 @@ static void max3107_register_init(struct max3107_port *s)
s->brg_cfg = MAX3107_BRG13_IB9600;
s->baud_tbl = (struct baud_table *)brg13_int;
}
-#if 0
- /*override for AAVA SC specific*/
- if (mrst_platform_id() == MRST_PLATFORM_AAVA_SC) {
- if (get_koski_build_id() <= KOSKI_EV2)
- if (s->ext_clk) {
- s->brg_cfg = MAX3107_BRG13_B9600;
- s->baud_tbl = (struct baud_table *)brg13_ext;
- }
- }
-#endif
+
+ if (s->pdata->init)
+ s->pdata->init(s);
+
buf[0] = (MAX3107_WRITE_BIT | MAX3107_BRGDIVMSB_REG)
| ((s->brg_cfg >> 16) & MAX3107_SPI_TX_DATA_MASK);
buf[1] = (MAX3107_WRITE_BIT | MAX3107_BRGDIVLSB_REG)
@@ -734,7 +643,7 @@ static irqreturn_t max3107_irq(int irqno, void *dev_id)
* used but that would mess the GPIOs
*
*/
-static void max3107_hw_susp(struct max3107_port *s, int suspend)
+void max3107_hw_susp(struct max3107_port *s, int suspend)
{
pr_debug("enter, suspend %d\n", suspend);
@@ -752,6 +661,7 @@ static void max3107_hw_susp(struct max3107_port *s, int suspend)
max3107_set_sleep(s, MAX3107_DISABLE_AUTOSLEEP);
}
}
+EXPORT_SYMBOL_GPL(max3107_hw_susp);
/* Modem status IRQ enabling */
static void max3107_enable_ms(struct uart_port *port)
@@ -899,10 +809,8 @@ static void max3107_shutdown(struct uart_port *port)
{
struct max3107_port *s = container_of(port, struct max3107_port, port);
- if (s->suspended) {
- /* Resume HW */
- max3107_hw_susp(s, 0);
- }
+ if (s->suspended && s->pdata->hw_suspend)
+ s->pdata->hw_suspend(s, 0);
/* Free the interrupt */
free_irq(s->spi->irq, s);
@@ -915,7 +823,8 @@ static void max3107_shutdown(struct uart_port *port)
}
/* Suspend HW */
- max3107_hw_susp(s, 1);
+ if (s->pdata->hw_suspend)
+ s->pdata->hw_suspend(s, 1);
}
/* Port startup function */
@@ -941,7 +850,8 @@ static int max3107_startup(struct uart_port *port)
}
/* Resume HW */
- max3107_hw_susp(s, 0);
+ if (s->pdata->hw_suspend)
+ s->pdata->hw_suspend(s, 0);
/* Init registers */
max3107_register_init(s);
@@ -973,16 +883,14 @@ static int max3107_request_port(struct uart_port *port)
static void max3107_config_port(struct uart_port *port, int flags)
{
struct max3107_port *s = container_of(port, struct max3107_port, port);
-
- /* Use PORT_MAX3100 since we are at least int the same series */
- s->port.type = PORT_MAX3100;
+ s->port.type = PORT_MAX3107;
}
/* Port verify function */
static int max3107_verify_port(struct uart_port *port,
struct serial_struct *ser)
{
- if (ser->type == PORT_UNKNOWN || ser->type == PORT_MAX3100)
+ if (ser->type == PORT_UNKNOWN || ser->type == PORT_MAX3107)
return 0;
return -EINVAL;
@@ -1000,157 +908,6 @@ static void max3107_break_ctl(struct uart_port *port, int break_state)
/* We don't support break control, do nothing */
}
-/* GPIO direction to input function */
-static int max3107_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
-{
- struct max3107_port *s = container_of(chip, struct max3107_port, chip);
- u16 buf[1]; /* Buffer for SPI transfer */
-
- if (offset >= MAX3107_GPIO_COUNT) {
- dev_err(&s->spi->dev, "Invalid GPIO\n");
- return -EINVAL;
- }
-
- /* Read current GPIO configuration register */
- buf[0] = MAX3107_GPIOCFG_REG;
- /* Perform SPI transfer */
- if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) {
- dev_err(&s->spi->dev, "SPI transfer GPIO read failed\n");
- return -EIO;
- }
- buf[0] &= MAX3107_SPI_RX_DATA_MASK;
-
- /* Set GPIO to input */
- buf[0] &= ~(0x0001 << offset);
-
- /* Write new GPIO configuration register value */
- buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIOCFG_REG);
- /* Perform SPI transfer */
- if (max3107_rw(s, (u8 *)buf, NULL, 2)) {
- dev_err(&s->spi->dev, "SPI transfer GPIO write failed\n");
- return -EIO;
- }
- return 0;
-}
-
-/* GPIO direction to output function */
-static int max3107_gpio_direction_out(struct gpio_chip *chip, unsigned offset,
- int value)
-{
- struct max3107_port *s = container_of(chip, struct max3107_port, chip);
- u16 buf[2]; /* Buffer for SPI transfers */
-
- if (offset >= MAX3107_GPIO_COUNT) {
- dev_err(&s->spi->dev, "Invalid GPIO\n");
- return -EINVAL;
- }
-
- /* Read current GPIO configuration and data registers */
- buf[0] = MAX3107_GPIOCFG_REG;
- buf[1] = MAX3107_GPIODATA_REG;
- /* Perform SPI transfer */
- if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 4)) {
- dev_err(&s->spi->dev, "SPI transfer gpio failed\n");
- return -EIO;
- }
- buf[0] &= MAX3107_SPI_RX_DATA_MASK;
- buf[1] &= MAX3107_SPI_RX_DATA_MASK;
-
- /* Set GPIO to output */
- buf[0] |= (0x0001 << offset);
- /* Set value */
- if (value)
- buf[1] |= (0x0001 << offset);
- else
- buf[1] &= ~(0x0001 << offset);
-
- /* Write new GPIO configuration and data register values */
- buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIOCFG_REG);
- buf[1] |= (MAX3107_WRITE_BIT | MAX3107_GPIODATA_REG);
- /* Perform SPI transfer */
- if (max3107_rw(s, (u8 *)buf, NULL, 4)) {
- dev_err(&s->spi->dev,
- "SPI transfer for GPIO conf data w failed\n");
- return -EIO;
- }
- return 0;
-}
-
-/* GPIO value query function */
-static int max3107_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
- struct max3107_port *s = container_of(chip, struct max3107_port, chip);
- u16 buf[1]; /* Buffer for SPI transfer */
-
- if (offset >= MAX3107_GPIO_COUNT) {
- dev_err(&s->spi->dev, "Invalid GPIO\n");
- return -EINVAL;
- }
-
- /* Read current GPIO data register */
- buf[0] = MAX3107_GPIODATA_REG;
- /* Perform SPI transfer */
- if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) {
- dev_err(&s->spi->dev, "SPI transfer GPIO data r failed\n");
- return -EIO;
- }
- buf[0] &= MAX3107_SPI_RX_DATA_MASK;
-
- /* Return value */
- return buf[0] & (0x0001 << offset);
-}
-
-/* GPIO value set function */
-static void max3107_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-{
- struct max3107_port *s = container_of(chip, struct max3107_port, chip);
- u16 buf[2]; /* Buffer for SPI transfers */
-
- if (offset >= MAX3107_GPIO_COUNT) {
- dev_err(&s->spi->dev, "Invalid GPIO\n");
- return;
- }
-
- /* Read current GPIO configuration registers*/
- buf[0] = MAX3107_GPIODATA_REG;
- buf[1] = MAX3107_GPIOCFG_REG;
- /* Perform SPI transfer */
- if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 4)) {
- dev_err(&s->spi->dev,
- "SPI transfer for GPIO data and config read failed\n");
- return;
- }
- buf[0] &= MAX3107_SPI_RX_DATA_MASK;
- buf[1] &= MAX3107_SPI_RX_DATA_MASK;
-
- if (!(buf[1] & (0x0001 << offset))) {
- /* Configured as input, can't set value */
- dev_warn(&s->spi->dev,
- "Trying to set value for input GPIO\n");
- return;
- }
-
- /* Set value */
- if (value)
- buf[0] |= (0x0001 << offset);
- else
- buf[0] &= ~(0x0001 << offset);
-
- /* Write new GPIO data register value */
- buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIODATA_REG);
- /* Perform SPI transfer */
- if (max3107_rw(s, (u8 *)buf, NULL, 2))
- dev_err(&s->spi->dev, "SPI transfer GPIO data w failed\n");
-}
-
-/* Platform data */
-static struct max3107_plat max3107_plat_data = {
- .loopback = 0,
- .ext_clk = 1,
- .max3107_hw_suspend = &max3107_hw_susp,
- .polled_mode = 0,
- .poll_time = 0,
-};
/* Port functions */
static struct uart_ops max3107_ops = {
@@ -1180,52 +937,48 @@ static struct uart_driver max3107_uart_driver = {
.nr = 1,
};
-/* GPIO chip data */
-static struct gpio_chip max3107_gpio_chip = {
- .owner = THIS_MODULE,
- .direction_input = max3107_gpio_direction_in,
- .direction_output = max3107_gpio_direction_out,
- .get = max3107_gpio_get,
- .set = max3107_gpio_set,
- .can_sleep = 1,
- .base = MAX3107_GPIO_BASE,
- .ngpio = MAX3107_GPIO_COUNT,
+static int driver_registered = 0;
+
+
+
+/* 'Generic' platform data */
+static struct max3107_plat generic_plat_data = {
+ .loopback = 0,
+ .ext_clk = 1,
+ .hw_suspend = max3107_hw_susp,
+ .polled_mode = 0,
+ .poll_time = 0,
};
-/* Device probe function */
-static int __devinit max3107_probe(struct spi_device *spi)
+
+
+/*******************************************************************/
+
+/**
+ * max3107_probe - SPI bus probe entry point
+ * @spi: the spi device
+ *
+ * SPI wants us to probe this device and if appropriate claim it.
+ * Perform any platform specific requirements and then initialise
+ * the device.
+ */
+
+int max3107_probe(struct spi_device *spi, struct max3107_plat *pdata)
{
struct max3107_port *s;
- struct max3107_plat *pdata = &max3107_plat_data;
u16 buf[2]; /* Buffer for SPI transfers */
int retval;
pr_info("enter max3107 probe\n");
- /* Reset the chip */
- if (gpio_request(MAX3107_RESET_GPIO, "max3107")) {
- pr_err("Requesting RESET GPIO failed\n");
- return -EIO;
- }
- if (gpio_direction_output(MAX3107_RESET_GPIO, 0)) {
- pr_err("Setting RESET GPIO to 0 failed\n");
- gpio_free(MAX3107_RESET_GPIO);
- return -EIO;
- }
- msleep(MAX3107_RESET_DELAY);
- if (gpio_direction_output(MAX3107_RESET_GPIO, 1)) {
- pr_err("Setting RESET GPIO to 1 failed\n");
- gpio_free(MAX3107_RESET_GPIO);
- return -EIO;
- }
- gpio_free(MAX3107_RESET_GPIO);
- msleep(MAX3107_WAKEUP_DELAY);
-
/* Allocate port structure */
s = kzalloc(sizeof(*s), GFP_KERNEL);
if (!s) {
pr_err("Allocating port structure failed\n");
return -ENOMEM;
}
+
+ s->pdata = pdata;
+
/* SPI Rx buffer
* +2 for RX FIFO interrupt
* disabling and RX level query
@@ -1298,10 +1051,13 @@ static int __devinit max3107_probe(struct spi_device *spi)
}
/* Register UART driver */
- retval = uart_register_driver(&max3107_uart_driver);
- if (retval) {
- dev_err(&s->spi->dev, "Registering UART driver failed\n");
- return retval;
+ if (!driver_registered) {
+ retval = uart_register_driver(&max3107_uart_driver);
+ if (retval) {
+ dev_err(&s->spi->dev, "Registering UART driver failed\n");
+ return retval;
+ }
+ driver_registered = 1;
}
/* Initialize UART port data */
@@ -1312,8 +1068,7 @@ static int __devinit max3107_probe(struct spi_device *spi)
s->port.uartclk = 9600;
s->port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
s->port.irq = s->spi->irq;
- /* Use PORT_MAX3100 since we are at least in the same series */
- s->port.type = PORT_MAX3100;
+ s->port.type = PORT_MAX3107;
/* Add UART port */
retval = uart_add_one_port(&max3107_uart_driver, &s->port);
@@ -1322,44 +1077,31 @@ static int __devinit max3107_probe(struct spi_device *spi)
return retval;
}
- /* Initialize GPIO chip data */
- s->chip = max3107_gpio_chip;
- s->chip.label = spi->modalias;
- s->chip.dev = &spi->dev;
-
- /* Add GPIO chip */
- retval = gpiochip_add(&s->chip);
- if (retval) {
- dev_err(&s->spi->dev, "Adding GPIO chip failed\n");
- return retval;
+ if (pdata->configure) {
+ retval = pdata->configure(s);
+ if (retval < 0)
+ return retval;
}
- /* Temporary fix for EV2 boot problems, set modem reset to 0 */
- max3107_gpio_direction_out(&s->chip, 3, 0);
-
/* Go to suspend mode */
- max3107_hw_susp(s, 1);
+ if (pdata->hw_suspend)
+ pdata->hw_suspend(s, 1);
return 0;
}
+EXPORT_SYMBOL_GPL(max3107_probe);
/* Driver remove function */
-static int __devexit max3107_remove(struct spi_device *spi)
+int max3107_remove(struct spi_device *spi)
{
struct max3107_port *s = dev_get_drvdata(&spi->dev);
pr_info("enter max3107 remove\n");
- /* Remove GPIO chip */
- if (gpiochip_remove(&s->chip))
- dev_warn(&s->spi->dev, "Removing GPIO chip failed\n");
-
/* Remove port */
if (uart_remove_one_port(&max3107_uart_driver, &s->port))
dev_warn(&s->spi->dev, "Removing UART port failed\n");
- /* Unregister UART driver */
- uart_unregister_driver(&max3107_uart_driver);
/* Free TxRx buffer */
kfree(s->rxbuf);
@@ -1371,9 +1113,10 @@ static int __devexit max3107_remove(struct spi_device *spi)
return 0;
}
+EXPORT_SYMBOL_GPL(max3107_remove);
/* Driver suspend function */
-static int max3107_suspend(struct spi_device *spi, pm_message_t state)
+int max3107_suspend(struct spi_device *spi, pm_message_t state)
{
#ifdef CONFIG_PM
struct max3107_port *s = dev_get_drvdata(&spi->dev);
@@ -1384,13 +1127,15 @@ static int max3107_suspend(struct spi_device *spi, pm_message_t state)
uart_suspend_port(&max3107_uart_driver, &s->port);
/* Go to suspend mode */
- max3107_hw_susp(s, 1);
+ if (s->pdata->hw_suspend)
+ s->pdata->hw_suspend(s, 1);
#endif /* CONFIG_PM */
return 0;
}
+EXPORT_SYMBOL_GPL(max3107_suspend);
/* Driver resume function */
-static int max3107_resume(struct spi_device *spi)
+int max3107_resume(struct spi_device *spi)
{
#ifdef CONFIG_PM
struct max3107_port *s = dev_get_drvdata(&spi->dev);
@@ -1398,13 +1143,20 @@ static int max3107_resume(struct spi_device *spi)
pr_debug("enter resume\n");
/* Resume from suspend */
- max3107_hw_susp(s, 0);
+ if (s->pdata->hw_suspend)
+ s->pdata->hw_suspend(s, 0);
/* Resume UART port */
uart_resume_port(&max3107_uart_driver, &s->port);
#endif /* CONFIG_PM */
return 0;
}
+EXPORT_SYMBOL_GPL(max3107_resume);
+
+static int max3107_probe_generic(struct spi_device *spi)
+{
+ return max3107_probe(spi, &generic_plat_data);
+}
/* Spi driver data */
static struct spi_driver max3107_driver = {
@@ -1413,7 +1165,7 @@ static struct spi_driver max3107_driver = {
.bus = &spi_bus_type,
.owner = THIS_MODULE,
},
- .probe = max3107_probe,
+ .probe = max3107_probe_generic,
.remove = __devexit_p(max3107_remove),
.suspend = max3107_suspend,
.resume = max3107_resume,
@@ -1430,6 +1182,9 @@ static int __init max3107_init(void)
static void __exit max3107_exit(void)
{
pr_info("enter max3107 exit\n");
+ /* Unregister UART driver */
+ if (driver_registered)
+ uart_unregister_driver(&max3107_uart_driver);
spi_unregister_driver(&max3107_driver);
}
@@ -1438,5 +1193,5 @@ module_exit(max3107_exit);
MODULE_DESCRIPTION("MAX3107 driver");
MODULE_AUTHOR("Aavamobile");
-MODULE_ALIAS("max3107-spi-uart");
-MODULE_LICENSE("GPLv2");
+MODULE_ALIAS("max3107-spi");
+MODULE_LICENSE("GPL v2");