Signed-off-by: Russ Gorby <[email protected]>
---
drivers/serial/ifx6x60.c | 83 ++++++++++++++++++++++++++-----------
drivers/serial/ifx6x60.h | 1 +
include/linux/spi/ifx6x60_ioctl.h | 5 ++
3 files changed, 65 insertions(+), 24 deletions(-)
diff --git a/drivers/serial/ifx6x60.c b/drivers/serial/ifx6x60.c
index f84fd11..8ddac7c 100644
--- a/drivers/serial/ifx6x60.c
+++ b/drivers/serial/ifx6x60.c
@@ -668,6 +668,53 @@ static int ifx_spi_chars_in_buffer(struct tty_struct *tty)
}
/**
+ * reset_modem
+ *
+ * allows the modem to be reset under application control
+ * does not generate tty hangup as with silent reset
+ */
+static int
+reset_modem(struct ifx_spi_device *ifx_dev)
+{
+ int ret;
+
+ set_bit(MR_START, &ifx_dev->mdm_reset_state);
+ gpio_set_value(ifx_dev->gpio.po, 0);
+ gpio_set_value(ifx_dev->gpio.reset, 0);
+ msleep(25);
+ gpio_set_value(ifx_dev->gpio.reset, 1);
+ msleep(1);
+ gpio_set_value(ifx_dev->gpio.po, 1);
+ msleep(1);
+ gpio_set_value(ifx_dev->gpio.po, 0);
+ ret = wait_event_timeout(ifx_dev->mdm_reset_wait,
+ test_bit(MR_COMPLETE,
+ &ifx_dev->mdm_reset_state),
+ IFX_RESET_TIMEOUT);
+ if (!ret) {
+ dev_warn(&ifx_dev->spi_dev->dev,
+ "Modem reset timeout: (state:%lx)",
+ ifx_dev->mdm_reset_state);
+ ret = -1;
+ /*
+ * FIXME - sometime we don't see both interrupts from
+ * RESET_OUT, but if we've seen the first one, then
+ * that's sufficient currently
+ */
+ if (test_bit(MR_INPROGRESS, &ifx_dev->mdm_reset_state))
+ ret = 0;
+ } else {
+ dev_dbg(&ifx_dev->spi_dev->dev,
+ "Modem reset success: (state:%lx)",
+ ifx_dev->mdm_reset_state);
+ ret = 0;
+ }
+ ifx_dev->mdm_reset_state = 0;
+
+ return ret;
+}
+
+/**
* ifx_spi_ioctl - special ioctl handler
* @tty: our tty device
* @file: the file handle used for the ioctl
@@ -684,6 +731,7 @@ static int ifx_spi_ioctl(struct tty_struct *tty, struct
file *file,
unsigned int cmd, unsigned long arg)
{
int nreset;
+ int ret;
struct ifx_spi_device *ifx_dev = saved_ifx_dev;
dev_dbg(&ifx_dev->spi_dev->dev,
@@ -700,6 +748,14 @@ static int ifx_spi_ioctl(struct tty_struct *tty, struct
file *file,
return -EFAULT;
break;
+ case IFX_MODEM_RESET:
+ if (!capable(CAP_SYS_RAWIO))
+ return -EPERM;
+ ret = reset_modem(ifx_dev);
+ if (ret)
+ return -ENXIO;
+ break;
+
default:
return -ENOIOCTLCMD;
}
@@ -1278,11 +1334,9 @@ static irqreturn_t ifx_spi_reset_interrupt(int irq, void
*dev)
/* entered reset */
++ifx_dev->mdm_reset_cnt;
set_bit(MR_INPROGRESS, &ifx_dev->mdm_reset_state);
- if (!solreset) {
- /* unsolicited reset */
+ if (!solreset)
++ifx_dev->mdm_reset_unsol;
- ifx_spi_ttyhangup(ifx_dev);
- }
+ ifx_spi_ttyhangup(ifx_dev);
} else {
/* exited reset */
clear_bit(MR_INPROGRESS, &ifx_dev->mdm_reset_state);
@@ -1524,26 +1578,7 @@ static int ifx_spi_spi_probe(struct spi_device *spi)
* delays are required on some platforms for the modem
* to reset properly
*/
- set_bit(MR_START, &ifx_dev->mdm_reset_state);
- gpio_set_value(ifx_dev->gpio.po, 0);
- gpio_set_value(ifx_dev->gpio.reset, 0);
- msleep(25);
- gpio_set_value(ifx_dev->gpio.reset, 1);
- msleep(1);
- gpio_set_value(ifx_dev->gpio.po, 1);
- msleep(1);
- gpio_set_value(ifx_dev->gpio.po, 0);
- ret = wait_event_timeout(ifx_dev->mdm_reset_wait,
- test_bit(MR_COMPLETE,
- &ifx_dev->mdm_reset_state),
- IFX_RESET_TIMEOUT);
- if (!ret)
- dev_warn(&spi->dev, "Modem reset timeout: (state:%lx)",
- ifx_dev->mdm_reset_state);
- else
- dev_dbg(&spi->dev, "Modem reset success: (state:%lx)",
- ifx_dev->mdm_reset_state);
- ifx_dev->mdm_reset_state = 0;
+ (void) reset_modem(ifx_dev);
dev_dbg(&spi->dev, "Trying to get irq %x (%x)",
gpio_to_irq(ifx_dev->gpio.srdy), ifx_dev->gpio.srdy);
diff --git a/drivers/serial/ifx6x60.h b/drivers/serial/ifx6x60.h
index fc8dd21..ed1c24d 100644
--- a/drivers/serial/ifx6x60.h
+++ b/drivers/serial/ifx6x60.h
@@ -75,6 +75,7 @@ struct ifx_spi_device {
struct ifx_spi_port_data *port_data;
struct tasklet_struct io_work_tasklet;
struct work_struct write_wakeup_work;
+ struct work_struct reset_work;
unsigned long flags;
int modem;
dma_addr_t rx_dma;
diff --git a/include/linux/spi/ifx6x60_ioctl.h
b/include/linux/spi/ifx6x60_ioctl.h
index 3d773ab..3fa86d1 100644
--- a/include/linux/spi/ifx6x60_ioctl.h
+++ b/include/linux/spi/ifx6x60_ioctl.h
@@ -36,4 +36,9 @@
*/
#define IFX_GET_SILENT_RESET _IOR(IFX_SPI_MAGIC, 1, int)
+/*
+ * IFX_MODEM_RESET - reset the modem (solicited reset)
+ */
+#define IFX_MODEM_RESET _IO(IFX_SPI_MAGIC, 4)
+
#endif /* _IFX6X60_IOCTL_H */
--
1.6.0.6
_______________________________________________
MeeGo-kernel mailing list
[email protected]
http://lists.meego.com/listinfo/meego-kernel