All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH] serial: ifx6x60: Add module parameters to manage the modem status through sysfs
  2012-11-16 12:59 [PATCH] serial: ifx6x60: Add module parameters to manage the modem status through sysfs Jun Chen
@ 2012-11-16 12:38 ` Greg KH
  2012-11-16 15:00   ` Alan Cox
  0 siblings, 1 reply; 17+ messages in thread
From: Greg KH @ 2012-11-16 12:38 UTC (permalink / raw)
  To: Jun Chen
  Cc: serial, russ.gorby, liu chuansheng, Linux Kernel, Bi Chao, Alan Cox

On Fri, Nov 16, 2012 at 07:59:49AM -0500, Jun Chen wrote:
> 
> The Medfield Platform implements a recovery procedure consisting in an escalation
> from simple and light recovery procedures to stronger ones with increased visibility
> and impact to end-user.After platform find some problem from Modem,such as no response,
> platform will try do modem warm reset.If several tries failed, platform will try to
> do modem cold boot procedure.For Modem Cold Boot, AP is responsible to generate
> blob (binary object containing PIN code and other necessary information).
> Blob is stored in AP volatile memory. AP decides to read PIN code from cache instead of
> prompting end-user, and sends it to modem as if end-user had entered it.
> 
> This patch add module parameters to manage the modem status through sysfs.
> Reset_modem can be read and write by user space.When read the reset_modem,user space will
> get the mdm_reset_state which used to avoid to run twice at once.When set the reset_modem to
> IFX_COLD_RESET_REQ,modem will do cold reset, other val value will trigger modem reset.
> 
> Hangup_reasons used to give one interface to user space to know and clear the modem reset reasons.
> Now there are four reasons:SPI timeout, modem initiative reset,modem coredump,spi tranfer error.

Why are these module parameters?  Why not just "real" sysfs files
instead?  That way, if you have multiple devices in a system, it will
work properly for them.  Right now you are limited to 1 device, right?

And where have you documented these options?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH] serial: ifx6x60: Add module parameters to manage the modem status through sysfs
@ 2012-11-16 12:59 Jun Chen
  2012-11-16 12:38 ` Greg KH
  0 siblings, 1 reply; 17+ messages in thread
From: Jun Chen @ 2012-11-16 12:59 UTC (permalink / raw)
  To: Greg KH
  Cc: serial, russ.gorby, liu chuansheng, Linux Kernel, Jun Chen,
	Bi Chao, Alan Cox


The Medfield Platform implements a recovery procedure consisting in an escalation
from simple and light recovery procedures to stronger ones with increased visibility
and impact to end-user.After platform find some problem from Modem,such as no response,
platform will try do modem warm reset.If several tries failed, platform will try to
do modem cold boot procedure.For Modem Cold Boot, AP is responsible to generate
blob (binary object containing PIN code and other necessary information).
Blob is stored in AP volatile memory. AP decides to read PIN code from cache instead of
prompting end-user, and sends it to modem as if end-user had entered it.

This patch add module parameters to manage the modem status through sysfs.
Reset_modem can be read and write by user space.When read the reset_modem,user space will
get the mdm_reset_state which used to avoid to run twice at once.When set the reset_modem to
IFX_COLD_RESET_REQ,modem will do cold reset, other val value will trigger modem reset.

Hangup_reasons used to give one interface to user space to know and clear the modem reset reasons.
Now there are four reasons:SPI timeout, modem initiative reset,modem coredump,spi tranfer error.

Cc: Bi Chao <chao.bi@intel.com>
Cc: Liu chuansheng <chuansheng.liu@intel.com>
Acked-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Chen Jun <jun.d.chen@intel.com>
---
 drivers/tty/serial/Kconfig   |    2 +-
 drivers/tty/serial/ifx6x60.c |  193 ++++++++++++++++++++++++++++++++++++++++++
 drivers/tty/serial/ifx6x60.h |    8 ++
 3 files changed, 202 insertions(+), 1 deletions(-)

diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 2a53be5..640b36a 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -1323,7 +1323,7 @@ config SERIAL_ALTERA_UART_CONSOLE
 
 config SERIAL_IFX6X60
         tristate "SPI protocol driver for Infineon 6x60 modem (EXPERIMENTAL)"
-	depends on GPIOLIB && SPI
+	depends on GPIOLIB && SPI && X86_INTEL_MID && INTEL_SCU_IPC
 	help
 	  Support for the IFX6x60 modem devices on Intel MID platforms.
 
diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c
index 5b9bc19..c17efc6 100644
--- a/drivers/tty/serial/ifx6x60.c
+++ b/drivers/tty/serial/ifx6x60.c
@@ -60,6 +60,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/spi/ifx_modem.h>
 #include <linux/delay.h>
+#include <asm/intel_scu_ipc.h>
 
 #include "ifx6x60.h"
 
@@ -72,6 +73,27 @@
 #define IFX_SPI_HEADER_0		(-1)
 #define IFX_SPI_HEADER_F		(-2)
 
+
+/* Delays for powering up/resetting the modem, ms */
+#define PO_INTERLINE_DELAY	1
+#define PO_POST_DELAY		200
+
+#define IFX_COLD_RESET_REQ	1
+
+#define IFX_MDM_PWR_ON	3
+#define IFX_MDM_RST_PMU	4
+
+/* For modem cold boot */
+#define V1P35CNT_W		0x0E0	/* PMIC register used to power off */
+/* the modem */
+#define V1P35_OFF	4
+#define V1P35_ON		6
+#define COLD_BOOT_DELAY_OFF_MIN	20000	/* 20 ms (use of usleep_range) */
+#define COLD_BOOT_DELAY_OFF_MAX	25000	/* 25 ms (use of usleep_range) */
+#define COLD_BOOT_DELAY_ON_MIN	10000	/* 10 ms (use of usleep_range) */
+#define COLD_BOOT_DELAY_ON_MAX	15000	/* 15 ms (use of usleep_range) */
+
+
 /* forward reference */
 static void ifx_spi_handle_srdy(struct ifx_spi_device *ifx_dev);
 
@@ -81,6 +103,35 @@ static struct tty_driver *tty_drv;
 static struct ifx_spi_device *saved_ifx_dev;
 static struct lock_class_key ifx_spi_key;
 
+
+/**
+ * do_modem_power - activity required to bring up modem
+ *
+ * Toggle gpios required to bring up modem power and start modem.
+ */
+static void do_modem_power(void)
+{
+	gpio_set_value(IFX_MDM_PWR_ON, 1);
+	mdelay(PO_INTERLINE_DELAY);
+	gpio_set_value(IFX_MDM_PWR_ON, 0);
+	msleep(PO_POST_DELAY);
+}
+
+/**
+ * do_modem_reset - activity required to reset modem
+ *
+ * Toggle gpios required to reset modem.
+ */
+static void do_modem_reset(void)
+{
+	gpio_set_value(IFX_MDM_RST_PMU, 0);
+	mdelay(PO_INTERLINE_DELAY);
+	gpio_set_value(IFX_MDM_RST_PMU, 1);
+	msleep(PO_POST_DELAY);
+}
+
+
+
 /* GPIO/GPE settings */
 
 /**
@@ -229,6 +280,7 @@ static void ifx_spi_timeout(unsigned long arg)
 	struct ifx_spi_device *ifx_dev = (struct ifx_spi_device *)arg;
 
 	dev_warn(&ifx_dev->spi_dev->dev, "*** SPI Timeout ***");
+	ifx_dev->hangup_reasons |= HU_TIMEOUT;
 	ifx_spi_ttyhangup(ifx_dev);
 	mrdy_set_low(ifx_dev);
 	clear_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags);
@@ -881,6 +933,7 @@ static irqreturn_t ifx_spi_reset_interrupt(int irq, void *dev)
 		/* exited reset */
 		clear_bit(MR_INPROGRESS, &ifx_dev->mdm_reset_state);
 		if (solreset) {
+			clear_bit(MR_START, &ifx_dev->mdm_reset_state);
 			set_bit(MR_COMPLETE, &ifx_dev->mdm_reset_state);
 			wake_up(&ifx_dev->mdm_reset_wait);
 		}
@@ -1405,6 +1458,146 @@ static int __init ifx_spi_init(void)
 module_init(ifx_spi_init);
 module_exit(ifx_spi_exit);
 
+/*
+ * Module parameters to manage the modem status through sysfs
+ */
+
+/**
+ * reset_modem - modem reset command function
+ * @val: a reference to the string where the modem reset query is given
+ * @kp: an unused reference to the kernel parameter
+ */
+
+static int reset_modem(const char *val, const struct kernel_param *kp)
+{
+	unsigned long reset_request;
+	int err = 0;
+
+	u16 addr = V1P35CNT_W;
+	u8 data, def_value;
+
+	if (kstrtoul(val, 10, &reset_request) < 0)
+		return -EINVAL;
+
+	if (!saved_ifx_dev) {
+		dev_dbg(&saved_ifx_dev->spi_dev->dev,
+				"%s is called before probe\n", __func__);
+		return -ENODEV;
+	}
+
+	dev_dbg(&saved_ifx_dev->spi_dev->dev,
+					"%s requested !\n", __func__);
+
+	if (test_and_set_bit(MR_START, &saved_ifx_dev->mdm_reset_state))
+		return -EBUSY;
+
+	if (reset_request == IFX_COLD_RESET_REQ) {
+		gpio_set_value(IFX_MDM_RST_PMU, 0);
+
+		/* Save the current register value */
+		err = intel_scu_ipc_readv(&addr, &def_value, 1);
+		if (err) {
+			dev_err(&saved_ifx_dev->spi_dev->dev,
+				" - %s -  read error: %d", __func__, err);
+			goto out;
+		}
+
+		/* Write the new register value (V1P35_OFF) */
+		data = (def_value & 0xf8) | V1P35_OFF;
+		err =  intel_scu_ipc_writev(&addr, &data, 1);
+		if (err) {
+			dev_err(&saved_ifx_dev->spi_dev->dev,
+				" - %s -  write error: %d", __func__, err);
+			goto out;
+		}
+		usleep_range(COLD_BOOT_DELAY_OFF_MIN, COLD_BOOT_DELAY_OFF_MAX);
+
+		/* Write the new register value (V1P35_ON) */
+		data = (def_value & 0xf8) | V1P35_ON;
+		err =  intel_scu_ipc_writev(&addr, &data, 1);
+		if (err) {
+			dev_err(&saved_ifx_dev->spi_dev->dev,
+				" - %s -  write error: %d", __func__, err);
+			goto out;
+		}
+		usleep_range(COLD_BOOT_DELAY_ON_MIN, COLD_BOOT_DELAY_ON_MAX);
+
+		/* Write back the initial register value */
+		err =  intel_scu_ipc_writev(&addr, &def_value, 1);
+		if (err) {
+			dev_err(&saved_ifx_dev->spi_dev->dev,
+				" - %s -  write error: %d", __func__, err);
+			goto out;
+		}
+
+	}
+
+	/* Perform a complete modem reset */
+	do_modem_reset();
+	do_modem_power();
+
+out:
+
+	return err;
+}
+
+
+/**
+* is_modem_reset - modem reset status module parameter callback function
+ * @val: a reference to the string where the modem reset status is returned
+ * @kp: an unused reference to the kernel parameter
+ */
+static int is_modem_reset(char *val, const struct kernel_param *kp)
+{
+	if (saved_ifx_dev)
+		return sprintf(val, "%lu", saved_ifx_dev->mdm_reset_state);
+	else
+		return -ENOTTY;
+}
+
+
+/**
+ * clear_hangup_reasons - clearing all hangup reasons
+ * @val: a reference to the string where the hangup reasons clear query is given
+ * @kp: an unused reference to the kernel parameter
+ */
+static int clear_hangup_reasons(const char *val, const struct kernel_param *kp)
+{
+	if (saved_ifx_dev) {
+		saved_ifx_dev->hangup_reasons = 0;
+		return 0;
+	} else
+		return -ENOTTY;
+}
+
+/**
+ * hangup_reasons - modem hangup reasons module parameter callback function
+ * @val: a reference to the string where the hangup reasons are returned
+ * @kp: an unused reference to the kernel parameter
+ */
+
+static int hangup_reasons(char *val, const struct kernel_param *kp)
+{
+	if (saved_ifx_dev)
+		return sprintf(val, "%lu", saved_ifx_dev->hangup_reasons);
+	else
+		return -ENOTTY;
+}
+
+
+static struct kernel_param_ops reset_modem_ops = {
+	.set = reset_modem,
+	.get = is_modem_reset,
+};
+module_param_cb(reset_modem, &reset_modem_ops, NULL, 0644);
+
+static struct kernel_param_ops hangup_reasons_ops = {
+	.set = clear_hangup_reasons,
+	.get = hangup_reasons,
+};
+module_param_cb(hangup_reasons, &hangup_reasons_ops, NULL, 0644);
+
+
 MODULE_AUTHOR("Intel");
 MODULE_DESCRIPTION("IFX6x60 spi driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/ifx6x60.h b/drivers/tty/serial/ifx6x60.h
index e8464ba..274b468 100644
--- a/drivers/tty/serial/ifx6x60.h
+++ b/drivers/tty/serial/ifx6x60.h
@@ -66,6 +66,13 @@
 #define IFX_SPI_POWER_DATA_PENDING	1
 #define IFX_SPI_POWER_SRDY		2
 
+
+/* reasons for hanging up */
+#define	HU_TIMEOUT		1	/* spi timer out */
+#define	HU_RESET			2	/* modem initiative reset */
+#define	HU_COREDUMP		4	/* modem crash coredump */
+#define	HU_RORTUR			8	/* transfer error:ROR or TUR */
+
 struct ifx_spi_device {
 	/* Our SPI device */
 	struct spi_device *spi_dev;
@@ -120,6 +127,7 @@ struct ifx_spi_device {
 
 	/* modem reset */
 	unsigned long mdm_reset_state;
+	unsigned long hangup_reasons;
 #define MR_START	0
 #define MR_INPROGRESS	1
 #define MR_COMPLETE	2
-- 
1.7.4.1




^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH] serial: ifx6x60: Add module parameters to manage the modem status through sysfs
  2012-11-16 12:38 ` Greg KH
@ 2012-11-16 15:00   ` Alan Cox
  2012-11-16 15:01     ` Greg KH
  0 siblings, 1 reply; 17+ messages in thread
From: Alan Cox @ 2012-11-16 15:00 UTC (permalink / raw)
  To: Greg KH
  Cc: Jun Chen, serial, russ.gorby, liu chuansheng, Linux Kernel,
	Bi Chao, Alan Cox

On Fri, 16 Nov 2012 04:38:06 -0800
Greg KH <gregkh@linuxfoundation.org> wrote:

> On Fri, Nov 16, 2012 at 07:59:49AM -0500, Jun Chen wrote:
> > 
> > The Medfield Platform implements a recovery procedure consisting in an escalation
> > from simple and light recovery procedures to stronger ones with increased visibility
> > and impact to end-user.After platform find some problem from Modem,such as no response,
> > platform will try do modem warm reset.If several tries failed, platform will try to
> > do modem cold boot procedure.For Modem Cold Boot, AP is responsible to generate
> > blob (binary object containing PIN code and other necessary information).
> > Blob is stored in AP volatile memory. AP decides to read PIN code from cache instead of
> > prompting end-user, and sends it to modem as if end-user had entered it.
> > 
> > This patch add module parameters to manage the modem status through sysfs.
> > Reset_modem can be read and write by user space.When read the reset_modem,user space will
> > get the mdm_reset_state which used to avoid to run twice at once.When set the reset_modem to
> > IFX_COLD_RESET_REQ,modem will do cold reset, other val value will trigger modem reset.
> > 
> > Hangup_reasons used to give one interface to user space to know and clear the modem reset reasons.
> > Now there are four reasons:SPI timeout, modem initiative reset,modem coredump,spi tranfer error.
> 
> Why are these module parameters?  Why not just "real" sysfs files
> instead?  That way, if you have multiple devices in a system, it will
> work properly for them.  Right now you are limited to 1 device, right?

Yes and its highly unlikely that there will ever be anyone who needs two.

Alan

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] serial: ifx6x60: Add module parameters to manage the modem status through sysfs
  2012-11-16 15:00   ` Alan Cox
@ 2012-11-16 15:01     ` Greg KH
  0 siblings, 0 replies; 17+ messages in thread
From: Greg KH @ 2012-11-16 15:01 UTC (permalink / raw)
  To: Alan Cox
  Cc: Jun Chen, serial, russ.gorby, liu chuansheng, Linux Kernel,
	Bi Chao, Alan Cox

On Fri, Nov 16, 2012 at 03:00:07PM +0000, Alan Cox wrote:
> On Fri, 16 Nov 2012 04:38:06 -0800
> Greg KH <gregkh@linuxfoundation.org> wrote:
> 
> > On Fri, Nov 16, 2012 at 07:59:49AM -0500, Jun Chen wrote:
> > > 
> > > The Medfield Platform implements a recovery procedure consisting in an escalation
> > > from simple and light recovery procedures to stronger ones with increased visibility
> > > and impact to end-user.After platform find some problem from Modem,such as no response,
> > > platform will try do modem warm reset.If several tries failed, platform will try to
> > > do modem cold boot procedure.For Modem Cold Boot, AP is responsible to generate
> > > blob (binary object containing PIN code and other necessary information).
> > > Blob is stored in AP volatile memory. AP decides to read PIN code from cache instead of
> > > prompting end-user, and sends it to modem as if end-user had entered it.
> > > 
> > > This patch add module parameters to manage the modem status through sysfs.
> > > Reset_modem can be read and write by user space.When read the reset_modem,user space will
> > > get the mdm_reset_state which used to avoid to run twice at once.When set the reset_modem to
> > > IFX_COLD_RESET_REQ,modem will do cold reset, other val value will trigger modem reset.
> > > 
> > > Hangup_reasons used to give one interface to user space to know and clear the modem reset reasons.
> > > Now there are four reasons:SPI timeout, modem initiative reset,modem coredump,spi tranfer error.
> > 
> > Why are these module parameters?  Why not just "real" sysfs files
> > instead?  That way, if you have multiple devices in a system, it will
> > work properly for them.  Right now you are limited to 1 device, right?
> 
> Yes and its highly unlikely that there will ever be anyone who needs two.

Ok, but why a module parameter?  That's a very "odd" way to do this type
of interaction, why not just a "normal" sysfs file instead?

Either way, there's no documentation here, which is needed for a new
kernel/user api that is being created.  Someone needs to add an entry
for Documentation/ABI/ here.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 17+ messages in thread

* RE: [PATCH] serial: ifx6x60: Add module parameters to manage the modem status through sysfs.
  2012-11-16  0:52 ` Greg KH
@ 2012-11-16  1:55   ` Chen, Jun D
  0 siblings, 0 replies; 17+ messages in thread
From: Chen, Jun D @ 2012-11-16  1:55 UTC (permalink / raw)
  To: Greg KH; +Cc: Alan Cox, serial, Gorby, Russ, Liu, Chuansheng, Bi, Chao

Hi,Greg,
Got it, I will resend the new patch based on the tty-next branch to Alan again.  
Thanks!


-----Original Message-----
From: Greg KH [mailto:gregkh@linuxfoundation.org] 
Sent: Friday, November 16, 2012 8:52 AM
To: Chen, Jun D
Cc: Alan Cox; serial; Gorby, Russ; Liu, Chuansheng; Bi, Chao
Subject: Re: [PATCH] serial: ifx6x60: Add module parameters to manage the modem status through sysfs.

On Wed, Nov 07, 2012 at 06:06:14AM -0500, Jun Chen wrote:
> 
> The Medfield Platform implements a recovery procedure consisting in an 
> escalation from simple and light recovery procedures to stronger ones 
> with increased visibility and impact to end-user.After platform find 
> some problem from Modem,such as no response, platform will try do 
> modem warm reset.If several tries failed, platform will try to do 
> modem cold boot procedure.For Modem Cold Boot, AP is responsible to generate blob (binary object containing PIN code and other necessary information).
> Blob is stored in AP volatile memory. AP decides to read PIN code from 
> cache instead of prompting end-user, and sends it to modem as if end-user had entered it.
> 
> This patch add module parameters to manage the modem status through sysfs.
> Reset_modem can be read and write by user space.When read the 
> reset_modem,user space will get the mdm_reset_state which used to 
> avoid to run twice at once.When set the reset_modem to IFX_COLD_RESET_REQ,modem will do cold reset, other val value will trigger modem reset.
> 
> Hangup_reasons used to give one interface to user space to know and clear the modem reset reasons.
> Now there are four reasons:SPI timeout, modem initiative reset,modem coredump,spi tranfer error.
> 
> Cc: Bi Chao <chao.bi@intel.com>
> Cc: Liu chuansheng <chuansheng.liu@intel.com>
> Signed-off-by: Chen Jun <jun.d.chen@intel.com>
> Acked-by: Alan Cox <alan@linux.intel.com>
> ---
>  drivers/tty/serial/Kconfig   |    2 +-
>  drivers/tty/serial/ifx6x60.c |  194 +++++++++++++++++++++++++++++++++++++++++-
>  drivers/tty/serial/ifx6x60.h |    8 ++
>  3 files changed, 202 insertions(+), 2 deletions(-)

This patch fails to apply, can you please refresh it against my tty-next branch and resend it, keeping Alan's ack on it, so I remember it's there?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] serial: ifx6x60: Add module parameters to manage the modem status through sysfs.
  2012-11-07 11:06 Jun Chen
  2012-11-07  8:47 ` Alan Cox
@ 2012-11-16  0:52 ` Greg KH
  2012-11-16  1:55   ` Chen, Jun D
  1 sibling, 1 reply; 17+ messages in thread
From: Greg KH @ 2012-11-16  0:52 UTC (permalink / raw)
  To: Jun Chen; +Cc: Alan Cox, serial, russ.gorby, liu chuansheng, Bi Chao

On Wed, Nov 07, 2012 at 06:06:14AM -0500, Jun Chen wrote:
> 
> The Medfield Platform implements a recovery procedure consisting in an escalation
> from simple and light recovery procedures to stronger ones with increased visibility
> and impact to end-user.After platform find some problem from Modem,such as no response,
> platform will try do modem warm reset.If several tries failed, platform will try to
> do modem cold boot procedure.For Modem Cold Boot, AP is responsible to generate
> blob (binary object containing PIN code and other necessary information).
> Blob is stored in AP volatile memory. AP decides to read PIN code from cache instead of
> prompting end-user, and sends it to modem as if end-user had entered it.
> 
> This patch add module parameters to manage the modem status through sysfs.
> Reset_modem can be read and write by user space.When read the reset_modem,user space will
> get the mdm_reset_state which used to avoid to run twice at once.When set the reset_modem to
> IFX_COLD_RESET_REQ,modem will do cold reset, other val value will trigger modem reset.
> 
> Hangup_reasons used to give one interface to user space to know and clear the modem reset reasons.
> Now there are four reasons:SPI timeout, modem initiative reset,modem coredump,spi tranfer error.
> 
> Cc: Bi Chao <chao.bi@intel.com>
> Cc: Liu chuansheng <chuansheng.liu@intel.com>
> Signed-off-by: Chen Jun <jun.d.chen@intel.com>
> Acked-by: Alan Cox <alan@linux.intel.com>
> ---
>  drivers/tty/serial/Kconfig   |    2 +-
>  drivers/tty/serial/ifx6x60.c |  194 +++++++++++++++++++++++++++++++++++++++++-
>  drivers/tty/serial/ifx6x60.h |    8 ++
>  3 files changed, 202 insertions(+), 2 deletions(-)

This patch fails to apply, can you please refresh it against my tty-next
branch and resend it, keeping Alan's ack on it, so I remember it's
there?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH] serial: ifx6x60: Add module parameters to manage the modem status through sysfs.
@ 2012-11-07 11:06 Jun Chen
  2012-11-07  8:47 ` Alan Cox
  2012-11-16  0:52 ` Greg KH
  0 siblings, 2 replies; 17+ messages in thread
From: Jun Chen @ 2012-11-07 11:06 UTC (permalink / raw)
  To: Alan Cox; +Cc: serial, russ.gorby, liu chuansheng, Bi Chao, jun.d.chen


The Medfield Platform implements a recovery procedure consisting in an escalation
from simple and light recovery procedures to stronger ones with increased visibility
and impact to end-user.After platform find some problem from Modem,such as no response,
platform will try do modem warm reset.If several tries failed, platform will try to
do modem cold boot procedure.For Modem Cold Boot, AP is responsible to generate
blob (binary object containing PIN code and other necessary information).
Blob is stored in AP volatile memory. AP decides to read PIN code from cache instead of
prompting end-user, and sends it to modem as if end-user had entered it.

This patch add module parameters to manage the modem status through sysfs.
Reset_modem can be read and write by user space.When read the reset_modem,user space will
get the mdm_reset_state which used to avoid to run twice at once.When set the reset_modem to
IFX_COLD_RESET_REQ,modem will do cold reset, other val value will trigger modem reset.

Hangup_reasons used to give one interface to user space to know and clear the modem reset reasons.
Now there are four reasons:SPI timeout, modem initiative reset,modem coredump,spi tranfer error.

Cc: Bi Chao <chao.bi@intel.com>
Cc: Liu chuansheng <chuansheng.liu@intel.com>
Signed-off-by: Chen Jun <jun.d.chen@intel.com>
---
 drivers/tty/serial/Kconfig   |    2 +-
 drivers/tty/serial/ifx6x60.c |  194 +++++++++++++++++++++++++++++++++++++++++-
 drivers/tty/serial/ifx6x60.h |    8 ++
 3 files changed, 202 insertions(+), 2 deletions(-)

diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 233fbaa..5ddff34 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -1323,7 +1323,7 @@ config SERIAL_ALTERA_UART_CONSOLE
 
 config SERIAL_IFX6X60
         tristate "SPI protocol driver for Infineon 6x60 modem (EXPERIMENTAL)"
-	depends on GPIOLIB && SPI
+	depends on GPIOLIB && SPI && X86_INTEL_MID && INTEL_SCU_IPC
 	help
 	  Support for the IFX6x60 modem devices on Intel MID platforms.
 
diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c
index 769396a..a688f8f 100644
--- a/drivers/tty/serial/ifx6x60.c
+++ b/drivers/tty/serial/ifx6x60.c
@@ -60,6 +60,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/spi/ifx_modem.h>
 #include <linux/delay.h>
+#include <asm/intel_scu_ipc.h>
 
 #include "ifx6x60.h"
 
@@ -72,6 +73,27 @@
 #define IFX_SPI_HEADER_0		(-1)
 #define IFX_SPI_HEADER_F		(-2)
 
+
+/* Delays for powering up/resetting the modem, ms */
+#define PO_INTERLINE_DELAY	1
+#define PO_POST_DELAY		200
+
+#define IFX_COLD_RESET_REQ	1
+
+#define IFX_MDM_PWR_ON	3
+#define IFX_MDM_RST_PMU	4
+
+/* For modem cold boot */
+#define V1P35CNT_W		0x0E0	/* PMIC register used to power off */
+/* the modem */
+#define V1P35_OFF	4
+#define V1P35_ON		6
+#define COLD_BOOT_DELAY_OFF_MIN	20000	/* 20 ms (use of usleep_range) */
+#define COLD_BOOT_DELAY_OFF_MAX	25000	/* 25 ms (use of usleep_range) */
+#define COLD_BOOT_DELAY_ON_MIN	10000	/* 10 ms (use of usleep_range) */
+#define COLD_BOOT_DELAY_ON_MAX	15000	/* 15 ms (use of usleep_range) */
+
+
 /* forward reference */
 static void ifx_spi_handle_srdy(struct ifx_spi_device *ifx_dev);
 
@@ -81,6 +103,35 @@ static struct tty_driver *tty_drv;
 static struct ifx_spi_device *saved_ifx_dev;
 static struct lock_class_key ifx_spi_key;
 
+
+/**
+ * do_modem_power - activity required to bring up modem
+ *
+ * Toggle gpios required to bring up modem power and start modem.
+ */
+static void do_modem_power(void)
+{
+	gpio_set_value(IFX_MDM_PWR_ON, 1);
+	mdelay(PO_INTERLINE_DELAY);
+	gpio_set_value(IFX_MDM_PWR_ON, 0);
+	msleep(PO_POST_DELAY);
+}
+
+/**
+ * do_modem_reset - activity required to reset modem
+ *
+ * Toggle gpios required to reset modem.
+ */
+static void do_modem_reset(void)
+{
+	gpio_set_value(IFX_MDM_RST_PMU, 0);
+	mdelay(PO_INTERLINE_DELAY);
+	gpio_set_value(IFX_MDM_RST_PMU, 1);
+	msleep(PO_POST_DELAY);
+}
+
+
+
 /* GPIO/GPE settings */
 
 /**
@@ -193,7 +244,6 @@ static void mrdy_assert(struct ifx_spi_device *ifx_dev)
 			ifx_dev->spi_timer.expires =
 				jiffies + IFX_SPI_TIMEOUT_SEC*HZ;
 			add_timer(&ifx_dev->spi_timer);
-
 		}
 	}
 	ifx_spi_power_state_set(ifx_dev, IFX_SPI_POWER_DATA_PENDING);
@@ -229,6 +279,7 @@ static void ifx_spi_timeout(unsigned long arg)
 	struct ifx_spi_device *ifx_dev = (struct ifx_spi_device *)arg;
 
 	dev_warn(&ifx_dev->spi_dev->dev, "*** SPI Timeout ***");
+	ifx_dev->hangup_reasons |= HU_TIMEOUT;
 	ifx_spi_ttyhangup(ifx_dev);
 	mrdy_set_low(ifx_dev);
 	clear_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags);
@@ -881,6 +932,7 @@ static irqreturn_t ifx_spi_reset_interrupt(int irq, void *dev)
 		/* exited reset */
 		clear_bit(MR_INPROGRESS, &ifx_dev->mdm_reset_state);
 		if (solreset) {
+			clear_bit(MR_START, &ifx_dev->mdm_reset_state);
 			set_bit(MR_COMPLETE, &ifx_dev->mdm_reset_state);
 			wake_up(&ifx_dev->mdm_reset_wait);
 		}
@@ -1405,6 +1457,146 @@ static int __init ifx_spi_init(void)
 module_init(ifx_spi_init);
 module_exit(ifx_spi_exit);
 
+/*
+ * Module parameters to manage the modem status through sysfs
+ */
+
+/**
+ * reset_modem - modem reset command function
+ * @val: a reference to the string where the modem reset query is given
+ * @kp: an unused reference to the kernel parameter
+ */
+
+static int reset_modem(const char *val, const struct kernel_param *kp)
+{
+	unsigned long reset_request;
+	int err = 0;
+
+	u16 addr = V1P35CNT_W;
+	u8 data, def_value;
+
+	if (kstrtoul(val, 10, &reset_request) < 0)
+		return -EINVAL;
+
+	if (!saved_ifx_dev) {
+		dev_dbg(&saved_ifx_dev->spi_dev->dev,
+				"%s is called before probe\n", __func__);
+		return -ENODEV;
+	}
+
+	dev_dbg(&saved_ifx_dev->spi_dev->dev,
+					"%s requested !\n", __func__);
+
+	if (test_and_set_bit(MR_START, &saved_ifx_dev->mdm_reset_state))
+		return -EBUSY;
+
+	if (reset_request == IFX_COLD_RESET_REQ) {
+		gpio_set_value(IFX_MDM_RST_PMU, 0);
+
+		/* Save the current register value */
+		err = intel_scu_ipc_readv(&addr, &def_value, 1);
+		if (err) {
+			dev_err(&saved_ifx_dev->spi_dev->dev,
+					" - %s -  read error: %d", __func__, err);
+			goto out;
+		}
+
+		/* Write the new register value (V1P35_OFF) */
+		data = (def_value & 0xf8) | V1P35_OFF;
+		err =  intel_scu_ipc_writev(&addr, &data, 1);
+		if (err) {
+			dev_err(&saved_ifx_dev->spi_dev->dev,
+				" - %s -  write error: %d", __func__, err);
+			goto out;
+		}
+		usleep_range(COLD_BOOT_DELAY_OFF_MIN, COLD_BOOT_DELAY_OFF_MAX);
+
+		/* Write the new register value (V1P35_ON) */
+		data = (def_value & 0xf8) | V1P35_ON;
+		err =  intel_scu_ipc_writev(&addr, &data, 1);
+		if (err) {
+			dev_err(&saved_ifx_dev->spi_dev->dev,
+				" - %s -  write error: %d", __func__, err);
+			goto out;
+		}
+		usleep_range(COLD_BOOT_DELAY_ON_MIN, COLD_BOOT_DELAY_ON_MAX);
+
+		/* Write back the initial register value */
+		err =  intel_scu_ipc_writev(&addr, &def_value, 1);
+		if (err) {
+			dev_err(&saved_ifx_dev->spi_dev->dev,
+				" - %s -  write error: %d", __func__, err);
+			goto out;
+		}
+
+	}
+
+	/* Perform a complete modem reset */
+	do_modem_reset();
+	do_modem_power();
+
+out:
+
+	return err;
+}
+
+
+/**
+* is_modem_reset - modem reset status module parameter callback function
+ * @val: a reference to the string where the modem reset status is returned
+ * @kp: an unused reference to the kernel parameter
+ */
+static int is_modem_reset(char *val, const struct kernel_param *kp)
+{
+	if (saved_ifx_dev)
+		return sprintf(val, "%lu", saved_ifx_dev->mdm_reset_state);
+	else
+		return -ENOTTY;
+}
+
+
+/**
+ * clear_hangup_reasons - clearing all hangup reasons
+ * @val: a reference to the string where the hangup reasons clear query is given
+ * @kp: an unused reference to the kernel parameter
+ */
+static int clear_hangup_reasons(const char *val, const struct kernel_param *kp)
+{
+	if (saved_ifx_dev) {
+		saved_ifx_dev->hangup_reasons = 0;
+		return 0;
+	} else
+		return -ENOTTY;
+}
+
+/**
+ * hangup_reasons - modem hangup reasons module parameter callback function
+ * @val: a reference to the string where the hangup reasons are returned
+ * @kp: an unused reference to the kernel parameter
+ */
+
+static int hangup_reasons(char *val, const struct kernel_param *kp)
+{
+	if (saved_ifx_dev)
+		return sprintf(val, "%lu", saved_ifx_dev->hangup_reasons);
+	else
+		return -ENOTTY;
+}
+
+
+static struct kernel_param_ops reset_modem_ops = {
+	.set = reset_modem,
+	.get = is_modem_reset,
+};
+module_param_cb(reset_modem, &reset_modem_ops, NULL, 0644);
+
+static struct kernel_param_ops hangup_reasons_ops = {
+	.set = clear_hangup_reasons,
+	.get = hangup_reasons,
+};
+module_param_cb(hangup_reasons, &hangup_reasons_ops, NULL, 0644);
+
+
 MODULE_AUTHOR("Intel");
 MODULE_DESCRIPTION("IFX6x60 spi driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/ifx6x60.h b/drivers/tty/serial/ifx6x60.h
index e8464ba..ae48d28 100644
--- a/drivers/tty/serial/ifx6x60.h
+++ b/drivers/tty/serial/ifx6x60.h
@@ -66,6 +66,13 @@
 #define IFX_SPI_POWER_DATA_PENDING	1
 #define IFX_SPI_POWER_SRDY		2
 
+
+/* reasons for hanging up */
+#define	HU_TIMEOUT		1	/* spi timer out */
+#define	HU_RESET			2	/* modem initiative reset */
+#define	HU_COREDUMP		4	/* modem crash coredump */
+#define	HU_RORTUR			8	/* spi transfer error:ROR or TUR */
+
 struct ifx_spi_device {
 	/* Our SPI device */
 	struct spi_device *spi_dev;
@@ -120,6 +127,7 @@ struct ifx_spi_device {
 
 	/* modem reset */
 	unsigned long mdm_reset_state;
+	unsigned long hangup_reasons;
 #define MR_START	0
 #define MR_INPROGRESS	1
 #define MR_COMPLETE	2
-- 
1.7.4.1




^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH] serial: ifx6x60: Add module parameters to manage the modem status through sysfs.
  2012-11-07 11:06 Jun Chen
@ 2012-11-07  8:47 ` Alan Cox
  2012-11-16  0:52 ` Greg KH
  1 sibling, 0 replies; 17+ messages in thread
From: Alan Cox @ 2012-11-07  8:47 UTC (permalink / raw)
  To: Jun Chen; +Cc: Alan Cox, serial, russ.gorby, liu chuansheng, Bi Chao


> Hangup_reasons used to give one interface to user space to know and clear the modem reset reasons.
> Now there are four reasons:SPI timeout, modem initiative reset,modem coredump,spi tranfer error.
> 
> Cc: Bi Chao <chao.bi@intel.com>
> Cc: Liu chuansheng <chuansheng.liu@intel.com>
> Signed-off-by: Chen Jun <jun.d.chen@intel.com>

Acked-by: Alan Cox <alan@linux.intel.com>

^ permalink raw reply	[flat|nested] 17+ messages in thread

* RE: [PATCH] serial: ifx6x60: Add module parameters to manage the modem status through sysfs.
  2012-11-06  9:45 ` Alan Cox
@ 2012-11-07  3:09   ` Chen, Jun D
  0 siblings, 0 replies; 17+ messages in thread
From: Chen, Jun D @ 2012-11-07  3:09 UTC (permalink / raw)
  To: Alan Cox; +Cc: Alan Cox, serial, Gorby, Russ, Bi, Chao, Liu, Chuansheng

Hi,Alan,
    Thank for your suggestion for two point, I have updated the patch in other email.

-----Original Message-----
From: Alan Cox [mailto:alan@lxorguk.ukuu.org.uk] 
Sent: Tuesday, November 06, 2012 5:46 PM
To: Chen, Jun D
Cc: Alan Cox; serial; Gorby, Russ; Bi, Chao; Liu, Chuansheng
Subject: Re: [PATCH] serial: ifx6x60: Add module parameters to manage the modem status through sysfs.

>  	dev_warn(&ifx_dev->spi_dev->dev, "*** SPI Timeout ***");
> +	saved_ifx_dev->hangup_reasons |= HU_TIMEOUT;
>  	ifx_spi_ttyhangup(ifx_dev);

This one should be using ifx_dev->hangup_reasons |=

this part of the code is clean for multiple devices so the ifx_dev pointer should be used (it will always be the same as saved_ifx_dev currently so it's just a tidy up)


> +/**
> + * reset_modem - modem reset command function
> + * @val: a reference to the string where the modem reset query is 
> +given
> + * @kp: an unused reference to the kernel parameter  */
> +
> +static int reset_modem(const char *val, const struct kernel_param 
> +*kp) {
> +	unsigned long reset_request;
> +	int err = 0;
> +
> +	u16 addr = V1P35CNT_W;
> +	u8 data, def_value;
> +
> +	if (kstrtoul(val, 10, &reset_request) < 0)
> +		return -EINVAL;
> +
> +	if (!saved_ifx_dev) {
> +		dev_dbg(&saved_ifx_dev->spi_dev->dev,
> +				"%s is called before probe\n", __func__);
> +		return -ENODEV;
> +	}
> +
> +	dev_dbg(&saved_ifx_dev->spi_dev->dev,
> +					"%s requested !\n", __func__);
> +
> +	if (test_and_set_bit(MR_START, &saved_ifx_dev->mdm_reset_state))
> +		goto out;

This case returns 0 - rather than an error like -EBUSY - is that intentional ?

Otherwise

Acked-by: Alan Cox <alan@linux.intel.com>

and the two points noted can be fixed up with a later patch IMHO.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] serial: ifx6x60: Add module parameters to manage the modem status through sysfs.
  2012-11-06  9:24 Jun Chen
@ 2012-11-06  9:45 ` Alan Cox
  2012-11-07  3:09   ` Chen, Jun D
  0 siblings, 1 reply; 17+ messages in thread
From: Alan Cox @ 2012-11-06  9:45 UTC (permalink / raw)
  To: Jun Chen; +Cc: Alan Cox, serial, russ.gorby, chao.bi, chuansheng.liu

>  	dev_warn(&ifx_dev->spi_dev->dev, "*** SPI Timeout ***");
> +	saved_ifx_dev->hangup_reasons |= HU_TIMEOUT;
>  	ifx_spi_ttyhangup(ifx_dev);

This one should be using ifx_dev->hangup_reasons |=

this part of the code is clean for multiple devices so the ifx_dev
pointer should be used (it will always be the same as saved_ifx_dev
currently so it's just a tidy up)


> +/**
> + * reset_modem - modem reset command function
> + * @val: a reference to the string where the modem reset query is given
> + * @kp: an unused reference to the kernel parameter
> + */
> +
> +static int reset_modem(const char *val, const struct kernel_param *kp)
> +{
> +	unsigned long reset_request;
> +	int err = 0;
> +
> +	u16 addr = V1P35CNT_W;
> +	u8 data, def_value;
> +
> +	if (kstrtoul(val, 10, &reset_request) < 0)
> +		return -EINVAL;
> +
> +	if (!saved_ifx_dev) {
> +		dev_dbg(&saved_ifx_dev->spi_dev->dev,
> +				"%s is called before probe\n", __func__);
> +		return -ENODEV;
> +	}
> +
> +	dev_dbg(&saved_ifx_dev->spi_dev->dev,
> +					"%s requested !\n", __func__);
> +
> +	if (test_and_set_bit(MR_START, &saved_ifx_dev->mdm_reset_state))
> +		goto out;

This case returns 0 - rather than an error like -EBUSY - is that
intentional ?

Otherwise

Acked-by: Alan Cox <alan@linux.intel.com>

and the two points noted can be fixed up with a later patch IMHO.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH] serial: ifx6x60: Add module parameters to manage the modem status through sysfs.
@ 2012-11-06  9:24 Jun Chen
  2012-11-06  9:45 ` Alan Cox
  0 siblings, 1 reply; 17+ messages in thread
From: Jun Chen @ 2012-11-06  9:24 UTC (permalink / raw)
  To: Alan Cox; +Cc: serial, russ.gorby, chao.bi, chuansheng.liu, jun.d.chen


The Medfield Platform implements a recovery procedure consisting in an escalation
from simple and light recovery procedures to stronger ones with increased visibility
and impact to end-user.After platform find some problem from Modem,such as no response,
platform will try do modem warm reset.If several tries failed, platform will try to
do modem cold boot procedure.For Modem Cold Boot, AP is responsible to generate
blob (binary object containing PIN code and other necessary information).
Blob is stored in AP volatile memory. AP decides to read PIN code from cache instead of
prompting end-user, and sends it to modem as if end-user had entered it.

This patch add module parameters to manage the modem status through sysfs.
Reset_modem can be read and write by user space.When read the reset_modem,user space will
get the mdm_reset_state which used to avoid to run twice at once.When set the reset_modem to
IFX_COLD_RESET_REQ,modem will do cold reset, other val value will trigger modem reset.

Hangup_reasons used to give one interface to user space to know and clear the modem reset reasons.
Now there are four reasons:SPI timeout, modem initiative reset,modem coredump,spi tranfer error.

Cc: Bi Chao <chao.bi@intel.com>
Cc: Liu chuansheng <chuansheng.liu@intel.com>
Signed-off-by: Chen Jun <jun.d.chen@intel.com>
---
 drivers/tty/serial/Kconfig   |    2 +-
 drivers/tty/serial/ifx6x60.c |  194 +++++++++++++++++++++++++++++++++++++++++-
 drivers/tty/serial/ifx6x60.h |    8 ++
 3 files changed, 202 insertions(+), 2 deletions(-)

diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 233fbaa..5ddff34 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -1323,7 +1323,7 @@ config SERIAL_ALTERA_UART_CONSOLE
 
 config SERIAL_IFX6X60
         tristate "SPI protocol driver for Infineon 6x60 modem (EXPERIMENTAL)"
-	depends on GPIOLIB && SPI
+	depends on GPIOLIB && SPI && X86_INTEL_MID && INTEL_SCU_IPC
 	help
 	  Support for the IFX6x60 modem devices on Intel MID platforms.
 
diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c
index 769396a..d0259c1 100644
--- a/drivers/tty/serial/ifx6x60.c
+++ b/drivers/tty/serial/ifx6x60.c
@@ -60,6 +60,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/spi/ifx_modem.h>
 #include <linux/delay.h>
+#include <asm/intel_scu_ipc.h>
 
 #include "ifx6x60.h"
 
@@ -72,6 +73,27 @@
 #define IFX_SPI_HEADER_0		(-1)
 #define IFX_SPI_HEADER_F		(-2)
 
+
+/* Delays for powering up/resetting the modem, ms */
+#define PO_INTERLINE_DELAY	1
+#define PO_POST_DELAY		200
+
+#define IFX_COLD_RESET_REQ	1
+
+#define IFX_MDM_PWR_ON	3
+#define IFX_MDM_RST_PMU	4
+
+/* For modem cold boot */
+#define V1P35CNT_W		0x0E0	/* PMIC register used to power off */
+/* the modem */
+#define V1P35_OFF	4
+#define V1P35_ON		6
+#define COLD_BOOT_DELAY_OFF_MIN	20000	/* 20 ms (use of usleep_range) */
+#define COLD_BOOT_DELAY_OFF_MAX	25000	/* 25 ms (use of usleep_range) */
+#define COLD_BOOT_DELAY_ON_MIN	10000	/* 10 ms (use of usleep_range) */
+#define COLD_BOOT_DELAY_ON_MAX	15000	/* 15 ms (use of usleep_range) */
+
+
 /* forward reference */
 static void ifx_spi_handle_srdy(struct ifx_spi_device *ifx_dev);
 
@@ -81,6 +103,35 @@ static struct tty_driver *tty_drv;
 static struct ifx_spi_device *saved_ifx_dev;
 static struct lock_class_key ifx_spi_key;
 
+
+/**
+ * do_modem_power - activity required to bring up modem
+ *
+ * Toggle gpios required to bring up modem power and start modem.
+ */
+static void do_modem_power(void)
+{
+	gpio_set_value(IFX_MDM_PWR_ON, 1);
+	mdelay(PO_INTERLINE_DELAY);
+	gpio_set_value(IFX_MDM_PWR_ON, 0);
+	msleep(PO_POST_DELAY);
+}
+
+/**
+ * do_modem_reset - activity required to reset modem
+ *
+ * Toggle gpios required to reset modem.
+ */
+static void do_modem_reset(void)
+{
+	gpio_set_value(IFX_MDM_RST_PMU, 0);
+	mdelay(PO_INTERLINE_DELAY);
+	gpio_set_value(IFX_MDM_RST_PMU, 1);
+	msleep(PO_POST_DELAY);
+}
+
+
+
 /* GPIO/GPE settings */
 
 /**
@@ -193,7 +244,6 @@ static void mrdy_assert(struct ifx_spi_device *ifx_dev)
 			ifx_dev->spi_timer.expires =
 				jiffies + IFX_SPI_TIMEOUT_SEC*HZ;
 			add_timer(&ifx_dev->spi_timer);
-
 		}
 	}
 	ifx_spi_power_state_set(ifx_dev, IFX_SPI_POWER_DATA_PENDING);
@@ -229,6 +279,7 @@ static void ifx_spi_timeout(unsigned long arg)
 	struct ifx_spi_device *ifx_dev = (struct ifx_spi_device *)arg;
 
 	dev_warn(&ifx_dev->spi_dev->dev, "*** SPI Timeout ***");
+	saved_ifx_dev->hangup_reasons |= HU_TIMEOUT;
 	ifx_spi_ttyhangup(ifx_dev);
 	mrdy_set_low(ifx_dev);
 	clear_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags);
@@ -881,6 +932,7 @@ static irqreturn_t ifx_spi_reset_interrupt(int irq, void *dev)
 		/* exited reset */
 		clear_bit(MR_INPROGRESS, &ifx_dev->mdm_reset_state);
 		if (solreset) {
+			clear_bit(MR_START, &ifx_dev->mdm_reset_state);
 			set_bit(MR_COMPLETE, &ifx_dev->mdm_reset_state);
 			wake_up(&ifx_dev->mdm_reset_wait);
 		}
@@ -1405,6 +1457,146 @@ static int __init ifx_spi_init(void)
 module_init(ifx_spi_init);
 module_exit(ifx_spi_exit);
 
+/*
+ * Module parameters to manage the modem status through sysfs
+ */
+
+/**
+ * reset_modem - modem reset command function
+ * @val: a reference to the string where the modem reset query is given
+ * @kp: an unused reference to the kernel parameter
+ */
+
+static int reset_modem(const char *val, const struct kernel_param *kp)
+{
+	unsigned long reset_request;
+	int err = 0;
+
+	u16 addr = V1P35CNT_W;
+	u8 data, def_value;
+
+	if (kstrtoul(val, 10, &reset_request) < 0)
+		return -EINVAL;
+
+	if (!saved_ifx_dev) {
+		dev_dbg(&saved_ifx_dev->spi_dev->dev,
+				"%s is called before probe\n", __func__);
+		return -ENODEV;
+	}
+
+	dev_dbg(&saved_ifx_dev->spi_dev->dev,
+					"%s requested !\n", __func__);
+
+	if (test_and_set_bit(MR_START, &saved_ifx_dev->mdm_reset_state))
+		goto out;
+
+	if (reset_request == IFX_COLD_RESET_REQ) {
+		gpio_set_value(IFX_MDM_RST_PMU, 0);
+
+		/* Save the current register value */
+		err = intel_scu_ipc_readv(&addr, &def_value, 1);
+		if (err) {
+			dev_err(&saved_ifx_dev->spi_dev->dev,
+					" - %s -  read error: %d", __func__, err);
+			goto out;
+		}
+
+		/* Write the new register value (V1P35_OFF) */
+		data = (def_value & 0xf8) | V1P35_OFF;
+		err =  intel_scu_ipc_writev(&addr, &data, 1);
+		if (err) {
+			dev_err(&saved_ifx_dev->spi_dev->dev,
+				" - %s -  write error: %d", __func__, err);
+			goto out;
+		}
+		usleep_range(COLD_BOOT_DELAY_OFF_MIN, COLD_BOOT_DELAY_OFF_MAX);
+
+		/* Write the new register value (V1P35_ON) */
+		data = (def_value & 0xf8) | V1P35_ON;
+		err =  intel_scu_ipc_writev(&addr, &data, 1);
+		if (err) {
+			dev_err(&saved_ifx_dev->spi_dev->dev,
+				" - %s -  write error: %d", __func__, err);
+			goto out;
+		}
+		usleep_range(COLD_BOOT_DELAY_ON_MIN, COLD_BOOT_DELAY_ON_MAX);
+
+		/* Write back the initial register value */
+		err =  intel_scu_ipc_writev(&addr, &def_value, 1);
+		if (err) {
+			dev_err(&saved_ifx_dev->spi_dev->dev,
+				" - %s -  write error: %d", __func__, err);
+			goto out;
+		}
+
+	}
+
+	/* Perform a complete modem reset */
+	do_modem_reset();
+	do_modem_power();
+
+out:
+
+	return err;
+}
+
+
+/**
+* is_modem_reset - modem reset status module parameter callback function
+ * @val: a reference to the string where the modem reset status is returned
+ * @kp: an unused reference to the kernel parameter
+ */
+static int is_modem_reset(char *val, const struct kernel_param *kp)
+{
+	if (saved_ifx_dev)
+		return sprintf(val, "%lu", saved_ifx_dev->mdm_reset_state);
+	else
+		return -ENOTTY;
+}
+
+
+/**
+ * clear_hangup_reasons - clearing all hangup reasons
+ * @val: a reference to the string where the hangup reasons clear query is given
+ * @kp: an unused reference to the kernel parameter
+ */
+static int clear_hangup_reasons(const char *val, const struct kernel_param *kp)
+{
+	if (saved_ifx_dev) {
+		saved_ifx_dev->hangup_reasons = 0;
+		return 0;
+	} else
+		return -ENOTTY;
+}
+
+/**
+ * hangup_reasons - modem hangup reasons module parameter callback function
+ * @val: a reference to the string where the hangup reasons are returned
+ * @kp: an unused reference to the kernel parameter
+ */
+
+static int hangup_reasons(char *val, const struct kernel_param *kp)
+{
+	if (saved_ifx_dev)
+		return sprintf(val, "%lu", saved_ifx_dev->hangup_reasons);
+	else
+		return -ENOTTY;
+}
+
+
+static struct kernel_param_ops reset_modem_ops = {
+	.set = reset_modem,
+	.get = is_modem_reset,
+};
+module_param_cb(reset_modem, &reset_modem_ops, NULL, 0644);
+
+static struct kernel_param_ops hangup_reasons_ops = {
+	.set = clear_hangup_reasons,
+	.get = hangup_reasons,
+};
+module_param_cb(hangup_reasons, &hangup_reasons_ops, NULL, 0644);
+
+
 MODULE_AUTHOR("Intel");
 MODULE_DESCRIPTION("IFX6x60 spi driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/ifx6x60.h b/drivers/tty/serial/ifx6x60.h
index e8464ba..ae48d28 100644
--- a/drivers/tty/serial/ifx6x60.h
+++ b/drivers/tty/serial/ifx6x60.h
@@ -66,6 +66,13 @@
 #define IFX_SPI_POWER_DATA_PENDING	1
 #define IFX_SPI_POWER_SRDY		2
 
+
+/* reasons for hanging up */
+#define	HU_TIMEOUT		1	/* spi timer out */
+#define	HU_RESET			2	/* modem initiative reset */
+#define	HU_COREDUMP		4	/* modem crash coredump */
+#define	HU_RORTUR			8	/* spi transfer error:ROR or TUR */
+
 struct ifx_spi_device {
 	/* Our SPI device */
 	struct spi_device *spi_dev;
@@ -120,6 +127,7 @@ struct ifx_spi_device {
 
 	/* modem reset */
 	unsigned long mdm_reset_state;
+	unsigned long hangup_reasons;
 #define MR_START	0
 #define MR_INPROGRESS	1
 #define MR_COMPLETE	2
-- 
1.7.4.1




^ permalink raw reply related	[flat|nested] 17+ messages in thread

* RE: [PATCH] serial: ifx6x60: Add module parameters to manage the modem status through sysfs.
  2012-11-05 11:43     ` Alan Cox
@ 2012-11-06  1:32       ` Chen, Jun D
  0 siblings, 0 replies; 17+ messages in thread
From: Chen, Jun D @ 2012-11-06  1:32 UTC (permalink / raw)
  To: Alan Cox; +Cc: alan, linux-serial, Gorby, Russ, Liu, Chuansheng, Bi, Chao

Hi, Alan,
    Thank you very much! 

Jun

-----Original Message-----
From: Alan Cox [mailto:alan@lxorguk.ukuu.org.uk] 
Sent: Monday, November 05, 2012 7:43 PM
To: Chen, Jun D
Cc: alan@linux.intel.com; linux-serial@vger.kernel.org; Gorby, Russ; Liu, Chuansheng; Bi, Chao
Subject: Re: [PATCH] serial: ifx6x60: Add module parameters to manage the modem status through sysfs.

On Mon, 5 Nov 2012 08:26:08 +0000
"Chen, Jun D" <jun.d.chen@intel.com> wrote:

> Hi,Alan
>     Thank your reply and advice. 
> > +	if (reset_request == IFX_COLD_RESET_REQ) {
> > +		/*  Need to add these action for modem cold reset:
> > +		* - Set the RESET_BB_N to low (better SIM protection)
> > +		* - Set the EXT1P35VREN field to low  during 20ms (V1P35CNT_W  register)
> > +		* - set the EXT1P35VREN field to high during 10ms (V1P35CNT_W  register)
> > +		*/
> I want to submit one finished version, but these code need to call the 
> intel_scu_ipc_readv and intel_scu_ipc_writev function defined in the file <asm/intel_scu_ipc.h> But this module seem not to be maked. Now I add one macro to disable these functions. I will send the new patch to you and would you like to give more suggestion about this issue.

You probably need your Kconfig entry to have

	depends on X86_INTEL_MID && INTEL_SCU_IPC

so that it can only be compiled when the feature is present.

Alan

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH] serial: ifx6x60: Add module parameters to manage the modem status through sysfs.
@ 2012-11-05 16:31 Jun Chen
  0 siblings, 0 replies; 17+ messages in thread
From: Jun Chen @ 2012-11-05 16:31 UTC (permalink / raw)
  To: alan; +Cc: linux-serial, russ.gorby, chuansheng.liu, chao.bi, jun.d.chen


The Medfield Platform implements a recovery procedure consisting in an escalation
from simple and light recovery procedures to stronger ones with increased visibility
and impact to end-user.After platform find some problem from Modem,such as no response,
platform will try do modem warm reset.If several tries failed, platform will try to
do modem cold boot procedure.For Modem Cold Boot, AP is responsible to generate
blob (binary object containing PIN code and other necessary information).
Blob is stored in AP volatile memory. AP decides to read PIN code from cache instead of
prompting end-user, and sends it to modem as if end-user had entered it.

This patch add module parameters to manage the modem status through sysfs.
Reset_modem can be read and write by user space.When read the reset_modem,user space will
get the mdm_reset_state which used to avoid to run twice at once.When set the reset_modem to
IFX_COLD_RESET_REQ,modem will do cold reset, other val value will trigger modem reset.

Hangup_reasons used to give one interface to user space to know and clear the modem reset reasons.
Now there are four reasons:SPI timeout, modem initiative reset,modem coredump,spi tranfer error.

Cc: Bi Chao <chao.bi@intel.com>
Cc: Liu chuansheng <chuansheng.liu@intel.com>
Signed-off-by: Chen Jun <jun.d.chen@intel.com>
---
 drivers/tty/serial/ifx6x60.c |  199 +++++++++++++++++++++++++++++++++++++++++-
 drivers/tty/serial/ifx6x60.h |    8 ++
 2 files changed, 206 insertions(+), 1 deletions(-)

diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c
index 769396a..ac718e1 100644
--- a/drivers/tty/serial/ifx6x60.c
+++ b/drivers/tty/serial/ifx6x60.c
@@ -60,6 +60,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/spi/ifx_modem.h>
 #include <linux/delay.h>
+#include <asm/intel_scu_ipc.h>
 
 #include "ifx6x60.h"
 
@@ -72,6 +73,27 @@
 #define IFX_SPI_HEADER_0		(-1)
 #define IFX_SPI_HEADER_F		(-2)
 
+
+/* Delays for powering up/resetting the modem, ms */
+#define PO_INTERLINE_DELAY	1
+#define PO_POST_DELAY		200
+
+#define IFX_COLD_RESET_REQ	1
+
+#define IFX_MDM_PWR_ON	3
+#define IFX_MDM_RST_PMU	4
+
+/* For modem cold boot */
+#define V1P35CNT_W		0x0E0	/* PMIC register used to power off */
+/* the modem */
+#define V1P35_OFF	4
+#define V1P35_ON		6
+#define COLD_BOOT_DELAY_OFF_MIN	20000	/* 20 ms (use of usleep_range) */
+#define COLD_BOOT_DELAY_OFF_MAX	25000	/* 25 ms (use of usleep_range) */
+#define COLD_BOOT_DELAY_ON_MIN	10000	/* 10 ms (use of usleep_range) */
+#define COLD_BOOT_DELAY_ON_MAX	15000	/* 15 ms (use of usleep_range) */
+
+
 /* forward reference */
 static void ifx_spi_handle_srdy(struct ifx_spi_device *ifx_dev);
 
@@ -81,6 +103,35 @@ static struct tty_driver *tty_drv;
 static struct ifx_spi_device *saved_ifx_dev;
 static struct lock_class_key ifx_spi_key;
 
+
+/**
+ * do_modem_power - activity required to bring up modem
+ *
+ * Toggle gpios required to bring up modem power and start modem.
+ */
+static void do_modem_power(void)
+{
+	gpio_set_value(IFX_MDM_PWR_ON, 1);
+	mdelay(PO_INTERLINE_DELAY);
+	gpio_set_value(IFX_MDM_PWR_ON, 0);
+	msleep(PO_POST_DELAY);
+}
+
+/**
+ * do_modem_reset - activity required to reset modem
+ *
+ * Toggle gpios required to reset modem.
+ */
+static void do_modem_reset(void)
+{
+	gpio_set_value(IFX_MDM_RST_PMU, 0);
+	mdelay(PO_INTERLINE_DELAY);
+	gpio_set_value(IFX_MDM_RST_PMU, 1);
+	msleep(PO_POST_DELAY);
+}
+
+
+
 /* GPIO/GPE settings */
 
 /**
@@ -193,7 +244,6 @@ static void mrdy_assert(struct ifx_spi_device *ifx_dev)
 			ifx_dev->spi_timer.expires =
 				jiffies + IFX_SPI_TIMEOUT_SEC*HZ;
 			add_timer(&ifx_dev->spi_timer);
-
 		}
 	}
 	ifx_spi_power_state_set(ifx_dev, IFX_SPI_POWER_DATA_PENDING);
@@ -229,6 +279,7 @@ static void ifx_spi_timeout(unsigned long arg)
 	struct ifx_spi_device *ifx_dev = (struct ifx_spi_device *)arg;
 
 	dev_warn(&ifx_dev->spi_dev->dev, "*** SPI Timeout ***");
+	saved_ifx_dev->hangup_reasons |= HU_TIMEOUT;
 	ifx_spi_ttyhangup(ifx_dev);
 	mrdy_set_low(ifx_dev);
 	clear_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags);
@@ -881,6 +932,7 @@ static irqreturn_t ifx_spi_reset_interrupt(int irq, void *dev)
 		/* exited reset */
 		clear_bit(MR_INPROGRESS, &ifx_dev->mdm_reset_state);
 		if (solreset) {
+			clear_bit(MR_START, &ifx_dev->mdm_reset_state);
 			set_bit(MR_COMPLETE, &ifx_dev->mdm_reset_state);
 			wake_up(&ifx_dev->mdm_reset_wait);
 		}
@@ -1405,6 +1457,151 @@ static int __init ifx_spi_init(void)
 module_init(ifx_spi_init);
 module_exit(ifx_spi_exit);
 
+/*
+ * Module parameters to manage the modem status through sysfs
+ */
+
+/**
+ * reset_modem - modem reset command function
+ * @val: a reference to the string where the modem reset query is given
+ * @kp: an unused reference to the kernel parameter
+ */
+
+static int reset_modem(const char *val, const struct kernel_param *kp)
+{
+	unsigned long reset_request;
+	int err = 0;
+
+#ifdef CONFIG_INTEL_SCU_IPC
+	u16 addr = V1P35CNT_W;
+	u8 data, def_value;
+#endif
+
+	if (kstrtoul(val, 10, &reset_request) < 0)
+		return -EINVAL;
+
+	if (!saved_ifx_dev) {
+		dev_dbg(&saved_ifx_dev->spi_dev->dev,
+				"%s is called before probe\n", __func__);
+		return -ENODEV;
+	}
+
+	dev_dbg(&saved_ifx_dev->spi_dev->dev,
+					"%s requested !\n", __func__);
+
+	if (test_and_set_bit(MR_START, &saved_ifx_dev->mdm_reset_state))
+		goto out;
+
+#ifdef CONFIG_INTEL_SCU_IPC
+
+	if (reset_request == IFX_COLD_RESET_REQ) {
+		gpio_set_value(IFX_MDM_RST_PMU, 0);
+
+		/* Save the current register value */
+		err = intel_scu_ipc_readv(&addr, &def_value, 1);
+		if (err) {
+			dev_err(&saved_ifx_dev->spi_dev->dev,
+					" - %s -  read error: %d", __func__, err);
+			goto out;
+		}
+
+		/* Write the new register value (V1P35_OFF) */
+		data = (def_value & 0xf8) | V1P35_OFF;
+		err =  intel_scu_ipc_writev(&addr, &data, 1);
+		if (err) {
+			dev_err(&saved_ifx_dev->spi_dev->dev,
+				" - %s -  write error: %d", __func__, err);
+			goto out;
+		}
+		usleep_range(COLD_BOOT_DELAY_OFF_MIN, COLD_BOOT_DELAY_OFF_MAX);
+
+		/* Write the new register value (V1P35_ON) */
+		data = (def_value & 0xf8) | V1P35_ON;
+		err =  intel_scu_ipc_writev(&addr, &data, 1);
+		if (err) {
+			dev_err(&saved_ifx_dev->spi_dev->dev,
+				" - %s -  write error: %d", __func__, err);
+			goto out;
+		}
+		usleep_range(COLD_BOOT_DELAY_ON_MIN, COLD_BOOT_DELAY_ON_MAX);
+
+		/* Write back the initial register value */
+		err =  intel_scu_ipc_writev(&addr, &def_value, 1);
+		if (err) {
+			dev_err(&saved_ifx_dev->spi_dev->dev,
+				" - %s -  write error: %d", __func__, err);
+			goto out;
+		}
+
+	}
+#endif
+
+	/* Perform a complete modem reset */
+	do_modem_reset();
+	do_modem_power();
+
+out:
+
+	return err;
+}
+
+
+/**
+* is_modem_reset - modem reset status module parameter callback function
+ * @val: a reference to the string where the modem reset status is returned
+ * @kp: an unused reference to the kernel parameter
+ */
+static int is_modem_reset(char *val, const struct kernel_param *kp)
+{
+	if (saved_ifx_dev)
+		return sprintf(val, "%lu", saved_ifx_dev->mdm_reset_state);
+	else
+		return -ENOTTY;
+}
+
+
+/**
+ * clear_hangup_reasons - clearing all hangup reasons
+ * @val: a reference to the string where the hangup reasons clear query is given
+ * @kp: an unused reference to the kernel parameter
+ */
+static int clear_hangup_reasons(const char *val, const struct kernel_param *kp)
+{
+	if (saved_ifx_dev) {
+		saved_ifx_dev->hangup_reasons = 0;
+		return 0;
+	} else
+		return -ENOTTY;
+}
+
+/**
+ * hangup_reasons - modem hangup reasons module parameter callback function
+ * @val: a reference to the string where the hangup reasons are returned
+ * @kp: an unused reference to the kernel parameter
+ */
+
+static int hangup_reasons(char *val, const struct kernel_param *kp)
+{
+	if (saved_ifx_dev)
+		return sprintf(val, "%lu", saved_ifx_dev->hangup_reasons);
+	else
+		return -ENOTTY;
+}
+
+
+static struct kernel_param_ops reset_modem_ops = {
+	.set = reset_modem,
+	.get = is_modem_reset,
+};
+module_param_cb(reset_modem, &reset_modem_ops, NULL, 0644);
+
+static struct kernel_param_ops hangup_reasons_ops = {
+	.set = clear_hangup_reasons,
+	.get = hangup_reasons,
+};
+module_param_cb(hangup_reasons, &hangup_reasons_ops, NULL, 0644);
+
+
 MODULE_AUTHOR("Intel");
 MODULE_DESCRIPTION("IFX6x60 spi driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/ifx6x60.h b/drivers/tty/serial/ifx6x60.h
index e8464ba..ae48d28 100644
--- a/drivers/tty/serial/ifx6x60.h
+++ b/drivers/tty/serial/ifx6x60.h
@@ -66,6 +66,13 @@
 #define IFX_SPI_POWER_DATA_PENDING	1
 #define IFX_SPI_POWER_SRDY		2
 
+
+/* reasons for hanging up */
+#define	HU_TIMEOUT		1	/* spi timer out */
+#define	HU_RESET			2	/* modem initiative reset */
+#define	HU_COREDUMP		4	/* modem crash coredump */
+#define	HU_RORTUR			8	/* spi transfer error:ROR or TUR */
+
 struct ifx_spi_device {
 	/* Our SPI device */
 	struct spi_device *spi_dev;
@@ -120,6 +127,7 @@ struct ifx_spi_device {
 
 	/* modem reset */
 	unsigned long mdm_reset_state;
+	unsigned long hangup_reasons;
 #define MR_START	0
 #define MR_INPROGRESS	1
 #define MR_COMPLETE	2
-- 
1.7.4.1




^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH] serial: ifx6x60: Add module parameters to manage the modem status through sysfs.
  2012-11-05  8:26   ` Chen, Jun D
@ 2012-11-05 11:43     ` Alan Cox
  2012-11-06  1:32       ` Chen, Jun D
  0 siblings, 1 reply; 17+ messages in thread
From: Alan Cox @ 2012-11-05 11:43 UTC (permalink / raw)
  To: Chen, Jun D; +Cc: alan, linux-serial, Gorby, Russ, Liu, Chuansheng, Bi, Chao

On Mon, 5 Nov 2012 08:26:08 +0000
"Chen, Jun D" <jun.d.chen@intel.com> wrote:

> Hi,Alan
>     Thank your reply and advice. 
> > +	if (reset_request == IFX_COLD_RESET_REQ) {
> > +		/*  Need to add these action for modem cold reset:
> > +		* - Set the RESET_BB_N to low (better SIM protection)
> > +		* - Set the EXT1P35VREN field to low  during 20ms (V1P35CNT_W  register)
> > +		* - set the EXT1P35VREN field to high during 10ms (V1P35CNT_W  register)
> > +		*/
> I want to submit one finished version, but these code need to call the intel_scu_ipc_readv and intel_scu_ipc_writev function defined in the file <asm/intel_scu_ipc.h>
> But this module seem not to be maked. Now I add one macro to disable these functions. I will send the new patch to you and would you like to give more suggestion about this issue.

You probably need your Kconfig entry to have

	depends on X86_INTEL_MID && INTEL_SCU_IPC

so that it can only be compiled when the feature is present.

Alan

^ permalink raw reply	[flat|nested] 17+ messages in thread

* RE: [PATCH] serial: ifx6x60: Add module parameters to manage the modem status through sysfs.
  2012-11-02 11:29 ` Alan Cox
@ 2012-11-05  8:26   ` Chen, Jun D
  2012-11-05 11:43     ` Alan Cox
  0 siblings, 1 reply; 17+ messages in thread
From: Chen, Jun D @ 2012-11-05  8:26 UTC (permalink / raw)
  To: Alan Cox; +Cc: alan, linux-serial, Gorby, Russ, Liu, Chuansheng, Bi, Chao

Hi,Alan
    Thank your reply and advice. 
> +	if (reset_request == IFX_COLD_RESET_REQ) {
> +		/*  Need to add these action for modem cold reset:
> +		* - Set the RESET_BB_N to low (better SIM protection)
> +		* - Set the EXT1P35VREN field to low  during 20ms (V1P35CNT_W  register)
> +		* - set the EXT1P35VREN field to high during 10ms (V1P35CNT_W  register)
> +		*/
I want to submit one finished version, but these code need to call the intel_scu_ipc_readv and intel_scu_ipc_writev function defined in the file <asm/intel_scu_ipc.h>
But this module seem not to be maked. Now I add one macro to disable these functions. I will send the new patch to you and would you like to give more suggestion about this issue.

About the reset_ongoing variable and hangup_reasons variable, I have modify these codes, use mdm_reset_state variable(old ) and hangup_reasons 
variable( add ) in the the device structure to realize the codes. 
The variable mdm_reset_state used to tell the user space the status about modem reset status and void to run even twice at once.
The variable hangup_reasons used to give one interface to user space to know and clear the reason of modem reset, which don't need to locked.
I've update the patch as your suggestion, please check another PATCH mail.

Jun

-----Original Message-----
From: Alan Cox [mailto:alan@lxorguk.ukuu.org.uk] 
Sent: Friday, November 02, 2012 7:30 PM
To: Chen, Jun D
Cc: alan@linux.intel.com; linux-serial@vger.kernel.org; Gorby, Russ; Liu, Chuansheng; Bi, Chao
Subject: Re: [PATCH] serial: ifx6x60: Add module parameters to manage the modem status through sysfs.

> +	if (reset_request == IFX_COLD_RESET_REQ) {
> +		/*  Need to add these action for modem cold reset:
> +		* - Set the RESET_BB_N to low (better SIM protection)
> +		* - Set the EXT1P35VREN field to low  during 20ms (V1P35CNT_W  register)
> +		* - set the EXT1P35VREN field to high during 10ms (V1P35CNT_W  register)
> +		*/

You seem to have submitted an unfinished version ?

Also can you explain the locking on your new reset_ongoing variable and hangup_reasons variable ? What stops the sysfs code being run in parallel with the other bits or even twice at once.

Looking at it I get the impression that

a) the variable should be in the device structure not a static global
b) it is write only which seems pointless
c) you probably want a mutex around the actual reset processes so that reset is single threaded in each case.
d) that mutex probably belongs in the device structure
 

The hangup reasons in this patch also appears to be write only ?

Alan

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH] serial: ifx6x60: Add module parameters to manage the modem status through sysfs.
@ 2012-11-02 16:15 Jun Chen
  2012-11-02 11:29 ` Alan Cox
  0 siblings, 1 reply; 17+ messages in thread
From: Jun Chen @ 2012-11-02 16:15 UTC (permalink / raw)
  To: alan; +Cc: linux-serial, russ.gorby, chuansheng.liu, chao.bi, jun.d.chen


The Medfield Platform implements a recovery procedure consisting in an escalation
from simple and light recovery procedures to stronger ones with increased visibility
and impact to end-user.After platform find some problem from Modem,such as no response,
platform will try do modem warm reset.If several tries failed, platform will try to
do modem cold boot procedure.For Modem Cold Boot, AP is responsible to generate
blob (binary object containing PIN code and other necessary information).
Blob is stored in AP volatile memory. AP decides to read PIN code from cache instead of
prompting end-user, and sends it to modem as if end-user had entered it.

This patch add module parameters to manage the modem status through sysfs.
These function are:reset_modem,reset_ongoing,hangup_reasons,

Cc: Bi Chao <chao.bi@intel.com>
Cc: Liu chuansheng <chuansheng.liu@intel.com>
Signed-off-by: Chen Jun <jun.d.chen@intel.com>
---
 drivers/tty/serial/ifx6x60.c |  108 ++++++++++++++++++++++++++++++++++++++++++
 drivers/tty/serial/ifx6x60.h |    7 +++
 2 files changed, 115 insertions(+), 0 deletions(-)

diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c
index e56ed33..50de856 100644
--- a/drivers/tty/serial/ifx6x60.c
+++ b/drivers/tty/serial/ifx6x60.c
@@ -72,6 +72,19 @@
 #define IFX_SPI_HEADER_0		(-1)
 #define IFX_SPI_HEADER_F		(-2)
 
+
+/* Delays for powering up/resetting the modem, ms */
+#define PO_INTERLINE_DELAY	1
+#define PO_POST_DELAY		200
+
+#define IFX_COLD_RESET_REQ	1
+
+#define IFX_MDM_PWR_ON	3
+#define IFX_MDM_RST_PMU	4
+
+static unsigned long  reset_ongoing;
+static unsigned long hangup_reasons;
+
 /* forward reference */
 static void ifx_spi_handle_srdy(struct ifx_spi_device *ifx_dev);
 
@@ -81,6 +94,42 @@ static struct tty_driver *tty_drv;
 static struct ifx_spi_device *saved_ifx_dev;
 static struct lock_class_key ifx_spi_key;
 
+
+/**
+ * do_modem_power - activity required to bring up modem
+ *
+ * Toggle gpios required to bring up modem power and start modem.
+ */
+static void do_modem_power(void)
+{
+
+	reset_ongoing = 1;
+
+
+	gpio_set_value(IFX_MDM_PWR_ON, 1);
+	mdelay(PO_INTERLINE_DELAY);
+	gpio_set_value(IFX_MDM_PWR_ON, 0);
+	msleep(PO_POST_DELAY);
+}
+
+/**
+ * do_modem_reset - activity required to reset modem
+ *
+ * Toggle gpios required to reset modem.
+ */
+static void do_modem_reset(void)
+{
+
+	reset_ongoing = 1;
+
+	gpio_set_value(IFX_MDM_RST_PMU, 0);
+	mdelay(PO_INTERLINE_DELAY);
+	gpio_set_value(IFX_MDM_RST_PMU, 1);
+	msleep(PO_POST_DELAY);
+}
+
+
+
 /* GPIO/GPE settings */
 
 /**
@@ -227,6 +276,7 @@ static void ifx_spi_timeout(unsigned long arg)
 	struct ifx_spi_device *ifx_dev = (struct ifx_spi_device *)arg;
 
 	dev_warn(&ifx_dev->spi_dev->dev, "*** SPI Timeout ***");
+	hangup_reasons |= HU_TIMEOUT;
 	ifx_spi_ttyhangup(ifx_dev);
 	mrdy_set_low(ifx_dev);
 	clear_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags);
@@ -877,6 +927,7 @@ static irqreturn_t ifx_spi_reset_interrupt(int irq, void *dev)
 		}
 	} else {
 		/* exited reset */
+		reset_ongoing = 0 ;
 		clear_bit(MR_INPROGRESS, &ifx_dev->mdm_reset_state);
 		if (solreset) {
 			set_bit(MR_COMPLETE, &ifx_dev->mdm_reset_state);
@@ -1403,6 +1454,63 @@ static int __init ifx_spi_init(void)
 module_init(ifx_spi_init);
 module_exit(ifx_spi_exit);
 
+/*
+ * Module parameters to manage the modem status through sysfs
+ */
+
+/**
+ * reset_modem - modem reset command function
+ * @val: a reference to the string where the modem reset query is given
+ * @kp: an unused reference to the kernel parameter
+ */
+
+static int reset_modem(const char *val, const struct kernel_param *kp)
+{
+	unsigned long reset_request;
+
+	if (kstrtoul(val, 10, &reset_request) < 0)
+		return -EINVAL;
+
+	if (!saved_ifx_dev) {
+		dev_dbg(&saved_ifx_dev->spi_dev->dev,
+				"%s is called before probe\n", __func__);
+		return -ENODEV;
+	}
+
+	dev_dbg(&saved_ifx_dev->spi_dev->dev,
+					"%s requested !\n", __func__);
+
+	reset_ongoing = 1;
+
+	if (reset_request == IFX_COLD_RESET_REQ) {
+		/*  Need to add these action for modem cold reset:
+		* - Set the RESET_BB_N to low (better SIM protection)
+		* - Set the EXT1P35VREN field to low  during 20ms (V1P35CNT_W  register)
+		* - set the EXT1P35VREN field to high during 10ms (V1P35CNT_W  register)
+		*/
+	}
+
+	/* Perform a complete modem reset */
+	do_modem_reset();
+	do_modem_power();
+
+	return 0;
+}
+
+static struct kernel_param_ops reset_modem_ops = {
+	.set = reset_modem,
+};
+module_param_cb(reset_modem, &reset_modem_ops, NULL, 0644);
+
+
+module_param(reset_ongoing, ulong, S_IRUGO);
+MODULE_PARM_DESC(reset_ongoing,  "modem reset status module parameter");
+
+module_param(hangup_reasons, ulong, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(hangup_reasons, "modem hangup reasons module parameter ");
+
+
+
 MODULE_AUTHOR("Intel");
 MODULE_DESCRIPTION("IFX6x60 spi driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/ifx6x60.h b/drivers/tty/serial/ifx6x60.h
index e8464ba..1ac36c4 100644
--- a/drivers/tty/serial/ifx6x60.h
+++ b/drivers/tty/serial/ifx6x60.h
@@ -66,6 +66,13 @@
 #define IFX_SPI_POWER_DATA_PENDING	1
 #define IFX_SPI_POWER_SRDY		2
 
+
+/* reasons for hanging up */
+#define	HU_TIMEOUT		1	/* spi timer out */
+#define	HU_RESET			2	/* modem initiative reset */
+#define	HU_COREDUMP		4	/* modem crash coredump */
+#define	HU_RORTUR			8	/* spi transfer error:ROR or TUR */
+
 struct ifx_spi_device {
 	/* Our SPI device */
 	struct spi_device *spi_dev;
-- 
1.7.4.1




^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH] serial: ifx6x60: Add module parameters to manage the modem status through sysfs.
  2012-11-02 16:15 Jun Chen
@ 2012-11-02 11:29 ` Alan Cox
  2012-11-05  8:26   ` Chen, Jun D
  0 siblings, 1 reply; 17+ messages in thread
From: Alan Cox @ 2012-11-02 11:29 UTC (permalink / raw)
  To: Jun Chen; +Cc: alan, linux-serial, russ.gorby, chuansheng.liu, chao.bi

> +	if (reset_request == IFX_COLD_RESET_REQ) {
> +		/*  Need to add these action for modem cold reset:
> +		* - Set the RESET_BB_N to low (better SIM protection)
> +		* - Set the EXT1P35VREN field to low  during 20ms (V1P35CNT_W  register)
> +		* - set the EXT1P35VREN field to high during 10ms (V1P35CNT_W  register)
> +		*/

You seem to have submitted an unfinished version ?

Also can you explain the locking on your new reset_ongoing variable and
hangup_reasons variable ? What stops the sysfs code being run in parallel
with the other bits or even twice at once.

Looking at it I get the impression that

a) the variable should be in the device structure not a static global
b) it is write only which seems pointless
c) you probably want a mutex around the actual reset processes so that
reset is single threaded in each case.
d) that mutex probably belongs in the device structure
 

The hangup reasons in this patch also appears to be write only ?

Alan

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2012-11-16 15:00 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-11-16 12:59 [PATCH] serial: ifx6x60: Add module parameters to manage the modem status through sysfs Jun Chen
2012-11-16 12:38 ` Greg KH
2012-11-16 15:00   ` Alan Cox
2012-11-16 15:01     ` Greg KH
  -- strict thread matches above, loose matches on Subject: below --
2012-11-07 11:06 Jun Chen
2012-11-07  8:47 ` Alan Cox
2012-11-16  0:52 ` Greg KH
2012-11-16  1:55   ` Chen, Jun D
2012-11-06  9:24 Jun Chen
2012-11-06  9:45 ` Alan Cox
2012-11-07  3:09   ` Chen, Jun D
2012-11-05 16:31 Jun Chen
2012-11-02 16:15 Jun Chen
2012-11-02 11:29 ` Alan Cox
2012-11-05  8:26   ` Chen, Jun D
2012-11-05 11:43     ` Alan Cox
2012-11-06  1:32       ` Chen, Jun D

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.