Skip to contentSkip to conversation

OMAP2+: hwmod: Add API to enable IO ring wakeup.

PATCH Superseded Govindraj.R 5 participants 41 messages Sep 30, 2011 – Oct 14, 2011

Subsystems (6)

v6 of 8 Superseded Latest is v8 →

lore
Share & tools
lore
#0 lore raw

PATCH v6 1/16 OMAP2+: hwmod: Add API to enable IO ring wakeup.

Add API to enable IO pad wakeup capability based on mux dynamic pad and wake_up enable flag available from hwmod_mux initialization.

Use the wakeup_enable flag and enable wakeup capability for the given pads. Wakeup capability will be enabled/disabled during hwmod idle transition based on whether wakeup_flag is set or cleared.

Call the omap_hwmod_set_ioring_wakeup from hwmod_wakeup_enable/disable.

---
 arch/arm/mach-omap2/omap_hwmod.c |   59 ++++++++++++++++++++++++++++++++++++++
 1 files changed, 59 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/omap_hwmod.c +59 -0
index 84cc0bd..e751dd9 100644
@@ -2062,6 +2062,34 @@ static int __init omap_hwmod_setup_all(void)
 core_initcall(omap_hwmod_setup_all);
 
 /**
+ * omap_hwmod_set_ioring_wakeup - enable io pad wakeup flag.
+ * @oh: struct omap_hwmod *
+ * @set: bool value indicating to set or clear wakeup status.
+ *
+ * Set or Clear wakeup flag for the io_pad.
+ */
+static int omap_hwmod_set_ioring_wakeup(struct omap_hwmod *oh, bool set_wake)
+{
+	struct omap_device_pad *pad;
+	int ret = -EINVAL, j;
+
+	if (oh->mux && oh->mux->enabled) {
+		for (j = 0; j < oh->mux->nr_pads_dynamic; j++) {
+			pad = oh->mux->pads_dynamic[j];
+			if (pad->flags & OMAP_DEVICE_PAD_WAKEUP) {
+				if (set_wake)
+					pad->idle |= OMAP_WAKEUP_EN;
+				else
+					pad->idle &= ~OMAP_WAKEUP_EN;
+				ret = 0;
+			}
+		}
+	}
+
+	return ret;
+}
+
+/**
  * omap_hwmod_enable - enable an omap_hwmod
  * @oh: struct omap_hwmod *
  *
@@ -2393,6 +2421,35 @@ int omap_hwmod_del_initiator_dep(struct omap_hwmod *oh,
 {
 	return _del_initiator_dep(oh, init_oh);
 }
+/**
+ * omap_hwmod_enable_ioring_wakeup - Set wakeup flag for iopad.
+ * @oh: struct omap_hwmod *
+ *
+ * Traverse through dynamic pads, if pad is enabled then
+ * set wakeup enable bit flag for the mux pin. Wakeup pad bit
+ * will be set during hwmod idle transistion.
+ * Return error if pads are not enabled or not available.
+ */
+int omap_hwmod_enable_ioring_wakeup(struct omap_hwmod *oh)
+{
+	/* Enable pad wake-up capability */
+	return omap_hwmod_set_ioring_wakeup(oh, true);
+}
+
+/**
+ * omap_hwmod_disable_ioring_wakeup - Clear wakeup flag for iopad.
+ * @oh: struct omap_hwmod *
+ *
+ * Traverse through dynamic pads, if pad is enabled then
+ * clear wakeup enable bit flag for the mux pin. Wakeup pad bit
+ * will be set during hwmod idle transistion.
+ * Return error if pads are not enabled or not available.
+ */
+int omap_hwmod_disable_ioring_wakeup(struct omap_hwmod *oh)
+{
+	/* Disable pad wakeup capability */
+	return omap_hwmod_set_ioring_wakeup(oh, false);
+}
 
 /**
  * omap_hwmod_enable_wakeup - allow device to wake up the system
@@ -2419,6 +2476,7 @@ int omap_hwmod_enable_wakeup(struct omap_hwmod *oh)
 	v = oh->_sysc_cache;
 	_enable_wakeup(oh, &v);
 	_write_sysconfig(v, oh);
+	omap_hwmod_enable_ioring_wakeup(oh);
 	spin_unlock_irqrestore(&oh->_lock, flags);
 
 	return 0;
@@ -2449,6 +2507,7 @@ int omap_hwmod_disable_wakeup(struct omap_hwmod *oh)
 	v = oh->_sysc_cache;
 	_disable_wakeup(oh, &v);
 	_write_sysconfig(v, oh);
+	omap_hwmod_disable_ioring_wakeup(oh);
 	spin_unlock_irqrestore(&oh->_lock, flags);
 
 	return 0;
Signature · 1 line
1.7.4.1
#1 lore raw

PATCH v6 2/16 OMAP2+: hwmod: Add API to check IO PAD wakeup status

Add API to determine IO-PAD wakeup event status for a given hwmod dynamic_mux pad.

Wake up event set will be cleared on pad mux_read.

---
 arch/arm/mach-omap2/mux.c                    |   30 ++++++++++++++++++++++++++
 arch/arm/mach-omap2/mux.h                    |   13 +++++++++++
 arch/arm/mach-omap2/omap_hwmod.c             |    7 ++++++
 arch/arm/plat-omap/include/plat/omap_hwmod.h |    1 +
 4 files changed, 51 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/mux.c +30 -0
index 655e948..fb75aae 100644
@@ -351,6 +351,36 @@ err1:
 	return NULL;
 }
 
+/**
+ * omap_hwmod_mux_get_wake_status - omap hwmod check pad wakeup
+ * @hmux:		Pads for a hwmod
+ *
+ * Gets the wakeup status of given pad from omap-hwmod.
+ * Returns true if wakeup capability is set and wakeup event occurred.
+ * Returns false if wakeup event has not occurred or pads are not available.
+ */
+bool omap_hwmod_mux_get_wake_status(struct omap_hwmod_mux_info *hmux)
+{
+	int i;
+	unsigned int val;
+	u8 ret = false;
+
+	for (i = 0; i < hmux->nr_pads; i++) {
+		struct omap_device_pad *pad = &hmux->pads[i];
+
+		if (pad->flags & OMAP_DEVICE_PAD_WAKEUP) {
+			val = omap_mux_read(pad->partition,
+					pad->mux->reg_offset);
+			if (val & OMAP_WAKEUP_EVENT) {
+				ret = true;
+				break;
+			}
+		}
+	}
+
+	return ret;
+}
+
 /* Assumes the calling function takes care of locking */
 void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state)
 {
arch/arm/mach-omap2/mux.h +13 -0
index 2132308..8b2150a 100644
@@ -225,8 +225,21 @@ omap_hwmod_mux_init(struct omap_device_pad *bpads, int nr_pads);
  */
 void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state);
 
+/**
+ * omap_hwmod_mux_get_wake_status - omap hwmod check pad wakeup
+ * @hmux:		Pads for a hwmod
+ *
+ * Called only from omap_hwmod.c, do not use.
+ */
+bool omap_hwmod_mux_get_wake_status(struct omap_hwmod_mux_info *hmux);
 #else
 
+static inline bool
+omap_hwmod_mux_get_wake_status(struct omap_hwmod_mux_info *hmux)
+{
+	return 0;
+}
+
 static inline int omap_mux_init_gpio(int gpio, int val)
 {
 	return 0;
arch/arm/mach-omap2/omap_hwmod.c +7 -0
index e751dd9..a8b24d7 100644
@@ -2724,3 +2724,10 @@ int omap_hwmod_no_setup_reset(struct omap_hwmod *oh)
 
 	return 0;
 }
+
+int omap_hwmod_pad_get_wakeup_status(struct omap_hwmod *oh)
+{
+	if (oh && oh->mux)
+		return omap_hwmod_mux_get_wake_status(oh->mux);
+	return -EINVAL;
+}
arch/arm/plat-omap/include/plat/omap_hwmod.h +1 -0
index 0e329ca..9a6195c 100644
@@ -607,6 +607,7 @@ u32 omap_hwmod_get_context_loss_count(struct omap_hwmod *oh);
 
 int omap_hwmod_no_setup_reset(struct omap_hwmod *oh);
 
+int omap_hwmod_pad_get_wakeup_status(struct omap_hwmod *oh);
 /*
  * Chip variant-specific hwmod init routines - XXX should be converted
  * to use initcalls once the initial boot ordering is straightened out
Signature · 1 line
1.7.4.1
#2 lore raw

PATCH v6 2/16 OMAP2+: hwmod: Add API to check IO PAD wakeup status

Quoted 4 lines · Govindraj.R

Add API to determine IO-PAD wakeup event status for a given hwmod dynamic_mux pad.

Wake up event set will be cleared on pad mux_read.

Are these api's even getting used in this series?

Quoted 103 lines
---
  arch/arm/mach-omap2/mux.c                    |   30 ++++++++++++++++++++++++++
  arch/arm/mach-omap2/mux.h                    |   13 +++++++++++
  arch/arm/mach-omap2/omap_hwmod.c             |    7 ++++++
  arch/arm/plat-omap/include/plat/omap_hwmod.h |    1 +
  4 files changed, 51 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/mux.c +30 -0
index 655e948..fb75aae 100644
@@ -351,6 +351,36 @@ err1:
  	return NULL;
  }
 
+/**
+ * omap_hwmod_mux_get_wake_status - omap hwmod check pad wakeup
+ * @hmux:		Pads for a hwmod
+ *
+ * Gets the wakeup status of given pad from omap-hwmod.
+ * Returns true if wakeup capability is set and wakeup event occurred.
+ * Returns false if wakeup event has not occurred or pads are not available.
+ */
+bool omap_hwmod_mux_get_wake_status(struct omap_hwmod_mux_info *hmux)
+{
+	int i;
+	unsigned int val;
+	u8 ret = false;
+
+	for (i = 0; i<  hmux->nr_pads; i++) {
+		struct omap_device_pad *pad =&hmux->pads[i];
+
+		if (pad->flags&  OMAP_DEVICE_PAD_WAKEUP) {
+			val = omap_mux_read(pad->partition,
+					pad->mux->reg_offset);
+			if (val&  OMAP_WAKEUP_EVENT) {
+				ret = true;
+				break;
+			}
+		}
+	}
+
+	return ret;
+}
+
  /* Assumes the calling function takes care of locking */
  void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state)
  {
arch/arm/mach-omap2/mux.h +13 -0
index 2132308..8b2150a 100644
@@ -225,8 +225,21 @@ omap_hwmod_mux_init(struct omap_device_pad *bpads, int nr_pads);
   */
  void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state);
 
+/**
+ * omap_hwmod_mux_get_wake_status - omap hwmod check pad wakeup
+ * @hmux:		Pads for a hwmod
+ *
+ * Called only from omap_hwmod.c, do not use.
+ */
+bool omap_hwmod_mux_get_wake_status(struct omap_hwmod_mux_info *hmux);
  #else
 
+static inline bool
+omap_hwmod_mux_get_wake_status(struct omap_hwmod_mux_info *hmux)
+{
+	return 0;
+}
+
  static inline int omap_mux_init_gpio(int gpio, int val)
  {
  	return 0;
arch/arm/mach-omap2/omap_hwmod.c +7 -0
index e751dd9..a8b24d7 100644
@@ -2724,3 +2724,10 @@ int omap_hwmod_no_setup_reset(struct omap_hwmod *oh)
 
  	return 0;
  }
+
+int omap_hwmod_pad_get_wakeup_status(struct omap_hwmod *oh)
+{
+	if (oh&&  oh->mux)
+		return omap_hwmod_mux_get_wake_status(oh->mux);
+	return -EINVAL;
+}
arch/arm/plat-omap/include/plat/omap_hwmod.h +1 -0
index 0e329ca..9a6195c 100644
@@ -607,6 +607,7 @@ u32 omap_hwmod_get_context_loss_count(struct omap_hwmod *oh);
 
  int omap_hwmod_no_setup_reset(struct omap_hwmod *oh);
 
+int omap_hwmod_pad_get_wakeup_status(struct omap_hwmod *oh);
  /*
   * Chip variant-specific hwmod init routines - XXX should be converted
   * to use initcalls once the initial boot ordering is straightened out
#3 lore raw

PATCH v6 2/16 OMAP2+: hwmod: Add API to check IO PAD wakeup status

Thanks for the review,

Quoted 8 lines · Rajendra Nayak
Quoted 5 lines · Govindraj.R

Add API to determine IO-PAD wakeup event status for a given hwmod dynamic_mux pad.

Wake up event set will be cleared on pad mux_read.

Are these api's even getting used in this series?

Used in Tero's irq_chaining patches.

http://lkml.org/lkml/2011/9/23/121

--
Thanks,
Govindraj.R

Quoted 117 lines
Quoted 108 lines

---
?arch/arm/mach-omap2/mux.c ? ? ? ? ? ? ? ? ? ?| ? 30
++++++++++++++++++++++++++

?arch/arm/mach-omap2/mux.h ? ? ? ? ? ? ? ? ? ?| ? 13 +++++++++++
?arch/arm/mach-omap2/omap_hwmod.c ? ? ? ? ? ? | ? ?7 ++++++
?arch/arm/plat-omap/include/plat/omap_hwmod.h | ? ?1 +

?4 files changed, 51 insertions(+), 0 deletions(-)

arch/arm/mach-omap2/mux.c +7 -0
index 655e948..fb75aae 100644
@@ -351,6 +351,36 @@ err1:
 ? ? ? ?return NULL;
 ?}
 
+/**
+ * omap_hwmod_mux_get_wake_status - omap hwmod check pad wakeup
+ * @hmux: ? ? ? ? ? ? ?Pads for a hwmod
+ *
+ * Gets the wakeup status of given pad from omap-hwmod.
+ * Returns true if wakeup capability is set and wakeup event occurred.
+ * Returns false if wakeup event has not occurred or pads are not

available.
+ */

arch/arm/mach-omap2/mux.c +22 -0
+bool omap_hwmod_mux_get_wake_status(struct omap_hwmod_mux_info *hmux)
+{
+ ? ? ? int i;
+ ? ? ? unsigned int val;
+ ? ? ? u8 ret = false;
+
+ ? ? ? for (i = 0; i< ?hmux->nr_pads; i++) {
+ ? ? ? ? ? ? ? struct omap_device_pad *pad =&hmux->pads[i];
+
+ ? ? ? ? ? ? ? if (pad->flags& ?OMAP_DEVICE_PAD_WAKEUP) {
+ ? ? ? ? ? ? ? ? ? ? ? val = omap_mux_read(pad->partition,
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? pad->mux->reg_offset);
+ ? ? ? ? ? ? ? ? ? ? ? if (val& ?OMAP_WAKEUP_EVENT) {
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ret = true;
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? break;
+ ? ? ? ? ? ? ? ? ? ? ? }
+ ? ? ? ? ? ? ? }
+ ? ? ? }
+
+ ? ? ? return ret;
+}
+

?/* Assumes the calling function takes care of locking */ ?void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state) ?{

arch/arm/mach-omap2/mux.h +0 -0
index 2132308..8b2150a 100644
@@ -225,8 +225,21 @@ omap_hwmod_mux_init(struct omap_device_pad *bpads,
 int nr_pads);

? */
?void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state);

arch/arm/mach-omap2/mux.h +7 -0
+/**
+ * omap_hwmod_mux_get_wake_status - omap hwmod check pad wakeup
+ * @hmux: ? ? ? ? ? ? ?Pads for a hwmod
+ *
+ * Called only from omap_hwmod.c, do not use.
+ */
+bool omap_hwmod_mux_get_wake_status(struct omap_hwmod_mux_info *hmux);

?#else

arch/arm/mach-omap2/mux.h +6 -0
+static inline bool
+omap_hwmod_mux_get_wake_status(struct omap_hwmod_mux_info *hmux)
+{
+ ? ? ? return 0;
+}
+

?static inline int omap_mux_init_gpio(int gpio, int val) ?{
? ? ? ?return 0;

arch/arm/mach-omap2/omap_hwmod.c +0 -0
index e751dd9..a8b24d7 100644
@@ -2724,3 +2724,10 @@ int omap_hwmod_no_setup_reset(struct omap_hwmod
 *oh)
 
 ? ? ? ?return 0;

?}

arch/arm/mach-omap2/omap_hwmod.c +7 -0
+
+int omap_hwmod_pad_get_wakeup_status(struct omap_hwmod *oh)
+{
+ ? ? ? if (oh&& ?oh->mux)
+ ? ? ? ? ? ? ? return omap_hwmod_mux_get_wake_status(oh->mux);
+ ? ? ? return -EINVAL;
+}
arch/arm/plat-omap/include/plat/omap_hwmod.h +1 -0
index 0e329ca..9a6195c 100644
@@ -607,6 +607,7 @@ u32 omap_hwmod_get_context_loss_count(struct
 omap_hwmod *oh);
 
 ?int omap_hwmod_no_setup_reset(struct omap_hwmod *oh);
 
+int omap_hwmod_pad_get_wakeup_status(struct omap_hwmod *oh);
Quoted 3 lines

?/*
? * Chip variant-specific hwmod init routines - XXX should be converted ? * to use initcalls once the initial boot ordering is straightened out

--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in the body of a message to majordomo at vger.kernel.org
More majordomo info at ?http://vger.kernel.org/majordomo-info.html

#4 lore raw

PATCH v6 2/16 OMAP2+: hwmod: Add API to check IO PAD wakeup status

Quoted 6 lines · Govindraj

Thanks for the review,

Quoted 2 lines · Rajendra Nayak
Quoted 1 line · Govindraj.R
Quoted 8 lines
Quoted 6 lines
Quoted 4 lines

Add API to determine IO-PAD wakeup event status for a given hwmod dynamic_mux pad.

Wake up event set will be cleared on pad mux_read.

Are these api's even getting used in this series?

Used in Tero's irq_chaining patches.

So shouldn't this patch be part of his series instead?

Quoted 125 lines

http://lkml.org/lkml/2011/9/23/121

--
Thanks,
Govindraj.R

Quoted 117 lines
Quoted 110 lines
---
  arch/arm/mach-omap2/mux.c                    |   30
++++++++++++++++++++++++++
  arch/arm/mach-omap2/mux.h                    |   13 +++++++++++
  arch/arm/mach-omap2/omap_hwmod.c             |    7 ++++++
  arch/arm/plat-omap/include/plat/omap_hwmod.h |    1 +
  4 files changed, 51 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/mux.c +7 -0
index 655e948..fb75aae 100644
@@ -351,6 +351,36 @@ err1:
        return NULL;
  }
 
+/**
+ * omap_hwmod_mux_get_wake_status - omap hwmod check pad wakeup
+ * @hmux:              Pads for a hwmod
+ *
+ * Gets the wakeup status of given pad from omap-hwmod.
+ * Returns true if wakeup capability is set and wakeup event occurred.
+ * Returns false if wakeup event has not occurred or pads are not

available.
+ */

arch/arm/mach-omap2/mux.c +22 -0
+bool omap_hwmod_mux_get_wake_status(struct omap_hwmod_mux_info *hmux)
+{
+       int i;
+       unsigned int val;
+       u8 ret = false;
+
+       for (i = 0; i<    hmux->nr_pads; i++) {
+               struct omap_device_pad *pad =&hmux->pads[i];
+
+               if (pad->flags&    OMAP_DEVICE_PAD_WAKEUP) {
+                       val = omap_mux_read(pad->partition,
+                                       pad->mux->reg_offset);
+                       if (val&    OMAP_WAKEUP_EVENT) {
+                               ret = true;
+                               break;
+                       }
+               }
+       }
+
+       return ret;
+}
+
  /* Assumes the calling function takes care of locking */
  void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state)
  {
arch/arm/mach-omap2/mux.h +13 -0
index 2132308..8b2150a 100644
@@ -225,8 +225,21 @@ omap_hwmod_mux_init(struct omap_device_pad *bpads,
 int nr_pads);
   */
  void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state);
 
+/**
+ * omap_hwmod_mux_get_wake_status - omap hwmod check pad wakeup
+ * @hmux:              Pads for a hwmod
+ *
+ * Called only from omap_hwmod.c, do not use.
+ */
+bool omap_hwmod_mux_get_wake_status(struct omap_hwmod_mux_info *hmux);
  #else
 
+static inline bool
+omap_hwmod_mux_get_wake_status(struct omap_hwmod_mux_info *hmux)
+{
+       return 0;
+}
+
  static inline int omap_mux_init_gpio(int gpio, int val)
  {
        return 0;
arch/arm/mach-omap2/omap_hwmod.c +7 -0
index e751dd9..a8b24d7 100644
@@ -2724,3 +2724,10 @@ int omap_hwmod_no_setup_reset(struct omap_hwmod
 *oh)
 
        return 0;
  }
+
+int omap_hwmod_pad_get_wakeup_status(struct omap_hwmod *oh)
+{
+       if (oh&&    oh->mux)
+               return omap_hwmod_mux_get_wake_status(oh->mux);
+       return -EINVAL;
+}
arch/arm/plat-omap/include/plat/omap_hwmod.h +1 -0
index 0e329ca..9a6195c 100644
@@ -607,6 +607,7 @@ u32 omap_hwmod_get_context_loss_count(struct
 omap_hwmod *oh);
 
  int omap_hwmod_no_setup_reset(struct omap_hwmod *oh);
 
+int omap_hwmod_pad_get_wakeup_status(struct omap_hwmod *oh);
  /*
   * Chip variant-specific hwmod init routines - XXX should be converted
Quoted 1 line

* to use initcalls once the initial boot ordering is straightened out

--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

#5 lore raw

PATCH v6 2/16 OMAP2+: hwmod: Add API to check IO PAD wakeup status

Quoted 12 lines · Rajendra Nayak
Quoted 11 lines · Govindraj

Thanks for the review,

Quoted 6 lines · On Sat, Oct 1, 2011 at 8:03 PM, Rajendra Nayak<[email protected]> ?wrote:
Quoted 4 lines · Govindraj.R

Add API to determine IO-PAD wakeup event status for a given hwmod dynamic_mux pad.

Quoted 7 lines
Quoted 5 lines
Quoted 3 lines
Quoted 1 line

Wake up event set will be cleared on pad mux_read.

Are these api's even getting used in this series?

Used in Tero's irq_chaining patches.

So shouldn't this patch be part of his series instead?

Yes it is. Part of his v9-series.

--
Thanks,
Govindraj.R

Quoted 129 lines
Quoted 127 lines

http://lkml.org/lkml/2011/9/23/121

--
Thanks,
Govindraj.R

Quoted 118 lines
Quoted 108 lines

---
?arch/arm/mach-omap2/mux.c ? ? ? ? ? ? ? ? ? ?| ? 30
++++++++++++++++++++++++++

?arch/arm/mach-omap2/mux.h ? ? ? ? ? ? ? ? ? ?| ? 13 +++++++++++
?arch/arm/mach-omap2/omap_hwmod.c ? ? ? ? ? ? | ? ?7 ++++++
?arch/arm/plat-omap/include/plat/omap_hwmod.h | ? ?1 +

?4 files changed, 51 insertions(+), 0 deletions(-)

arch/arm/mach-omap2/mux.c +7 -0
index 655e948..fb75aae 100644
@@ -351,6 +351,36 @@ err1:
 ? ? ? ?return NULL;
 ?}
 
+/**
+ * omap_hwmod_mux_get_wake_status - omap hwmod check pad wakeup
+ * @hmux: ? ? ? ? ? ? ?Pads for a hwmod
+ *
+ * Gets the wakeup status of given pad from omap-hwmod.
+ * Returns true if wakeup capability is set and wakeup event occurred.
+ * Returns false if wakeup event has not occurred or pads are not

available.
+ */

arch/arm/mach-omap2/mux.c +22 -0
+bool omap_hwmod_mux_get_wake_status(struct omap_hwmod_mux_info *hmux)
+{
+ ? ? ? int i;
+ ? ? ? unsigned int val;
+ ? ? ? u8 ret = false;
+
+ ? ? ? for (i = 0; i< ? ?hmux->nr_pads; i++) {
+ ? ? ? ? ? ? ? struct omap_device_pad *pad =&hmux->pads[i];
+
+ ? ? ? ? ? ? ? if (pad->flags& ? ?OMAP_DEVICE_PAD_WAKEUP) {
+ ? ? ? ? ? ? ? ? ? ? ? val = omap_mux_read(pad->partition,
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? pad->mux->reg_offset);
+ ? ? ? ? ? ? ? ? ? ? ? if (val& ? ?OMAP_WAKEUP_EVENT) {
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ret = true;
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? break;
+ ? ? ? ? ? ? ? ? ? ? ? }
+ ? ? ? ? ? ? ? }
+ ? ? ? }
+
+ ? ? ? return ret;
+}
+

?/* Assumes the calling function takes care of locking */ ?void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state) ?{

arch/arm/mach-omap2/mux.h +0 -0
index 2132308..8b2150a 100644
@@ -225,8 +225,21 @@ omap_hwmod_mux_init(struct omap_device_pad *bpads,
 int nr_pads);

? */
?void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state);

arch/arm/mach-omap2/mux.h +7 -0
+/**
+ * omap_hwmod_mux_get_wake_status - omap hwmod check pad wakeup
+ * @hmux: ? ? ? ? ? ? ?Pads for a hwmod
+ *
+ * Called only from omap_hwmod.c, do not use.
+ */
+bool omap_hwmod_mux_get_wake_status(struct omap_hwmod_mux_info *hmux);

?#else

arch/arm/mach-omap2/mux.h +6 -0
+static inline bool
+omap_hwmod_mux_get_wake_status(struct omap_hwmod_mux_info *hmux)
+{
+ ? ? ? return 0;
+}
+

?static inline int omap_mux_init_gpio(int gpio, int val) ?{
? ? ? ?return 0;

arch/arm/mach-omap2/omap_hwmod.c +0 -0
index e751dd9..a8b24d7 100644
@@ -2724,3 +2724,10 @@ int omap_hwmod_no_setup_reset(struct omap_hwmod
 *oh)
 
 ? ? ? ?return 0;

?}

arch/arm/mach-omap2/omap_hwmod.c +7 -0
+
+int omap_hwmod_pad_get_wakeup_status(struct omap_hwmod *oh)
+{
+ ? ? ? if (oh&& ? ?oh->mux)
+ ? ? ? ? ? ? ? return omap_hwmod_mux_get_wake_status(oh->mux);
+ ? ? ? return -EINVAL;
+}
arch/arm/plat-omap/include/plat/omap_hwmod.h +1 -0
index 0e329ca..9a6195c 100644
@@ -607,6 +607,7 @@ u32 omap_hwmod_get_context_loss_count(struct
 omap_hwmod *oh);
 
 ?int omap_hwmod_no_setup_reset(struct omap_hwmod *oh);
 
+int omap_hwmod_pad_get_wakeup_status(struct omap_hwmod *oh);
Quoted 3 lines

?/*
? * Chip variant-specific hwmod init routines - XXX should be converted ? * to use initcalls once the initial boot ordering is straightened out

--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at ?http://vger.kernel.org/majordomo-info.html

#6 lore raw

PATCH v6 2/16 OMAP2+: hwmod: Add API to check IO PAD wakeup status

Quoted 12 lines · Govindraj
Quoted 11 lines · Rajendra Nayak
Quoted 9 lines · Govindraj
Quoted 8 lines · On Sat, Oct 1, 2011 at 8:03 PM, Rajendra Nayak<[email protected]> ?wrote:
Quoted 5 lines · Govindraj.R

Add API to determine IO-PAD wakeup event status for a given hwmod dynamic_mux pad.

Wake up event set will be cleared on pad mux_read.

Quoted 8 lines
Quoted 5 lines
Quoted 3 lines
Quoted 1 line

Are these api's even getting used in this series?

Used in Tero's irq_chaining patches.

So shouldn't this patch be part of his series instead?

Yes it is. Part of his v9-series.

Then please drop from this series and state the introductory patch (PATCH 0/n) that this series has a dependency on Tero's series.

Kevin

#7 lore raw

PATCH v6 2/16 OMAP2+: hwmod: Add API to check IO PAD wakeup status

Quoted 18 lines · Kevin Hilman
Quoted 16 lines · Govindraj
Quoted 15 lines · Rajendra Nayak
Quoted 12 lines · Govindraj
Quoted 9 lines · On Sat, Oct 1, 2011 at 8:03 PM, Rajendra Nayak<[email protected]> ?wrote:
Quoted 5 lines · Govindraj.R

Add API to determine IO-PAD wakeup event status for a given hwmod dynamic_mux pad.

Wake up event set will be cleared on pad mux_read.

Are these api's even getting used in this series?

Used in Tero's irq_chaining patches.

Quoted 8 lines
Quoted 4 lines
Quoted 1 line

So shouldn't this patch be part of his series instead?

Yes it is. Part of his v9-series.

Then please drop from this series and state the introductory patch (PATCH 0/n) that this series has a dependency on Tero's series.

Okay.

--
Thanks,
Govindraj.R

#8 lore raw

PATCH v6 3/16 OMAP2+: UART: cleanup + remove uart pm specific API

In reply to Govindraj.R

In preparation to UART runtime conversion remove uart specific calls from pm24xx/34xx files and their definition from serial.c These func calls will no more be used with upcoming uart runtime design.

1.) omap_uart_prepare_suspend :- can be taken care with driver suspend hooks. 2.) omap_uart_enable_irqs :- Used to enable/disable uart irq's in suspend
path from PM code, this is removed as same is handled by uart_suspend_port/uart_resume_port in omap-serial driver which will do an port_shutdown on suspend freeing irq and port_startup on resume enabling back irq.
3.) Remove prepare_idle/resume_idle calls used to gate uart clocks.
UART clocks can be gated within driver using runtime funcs and be woken up using irq_chaining from omap_prm driver.
4.) Remove console_locking from idle path as clock gating is done withing
driver itself with runtime API.

---
 arch/arm/mach-omap2/pm24xx.c             |   18 --------
 arch/arm/mach-omap2/pm34xx.c             |   23 ----------
 arch/arm/mach-omap2/serial.c             |   65 ------------------------------
 arch/arm/plat-omap/include/plat/serial.h |    4 --
 4 files changed, 0 insertions(+), 110 deletions(-)
arch/arm/mach-omap2/pm24xx.c +0 -18
index bf089e7..a75f764 100644
@@ -30,7 +30,6 @@
 #include <linux/irq.h>
 #include <linux/time.h>
 #include <linux/gpio.h>
-#include <linux/console.h>
 
 #include <asm/mach/time.h>
 #include <asm/mach/irq.h>
@@ -133,27 +132,11 @@ static void omap2_enter_full_retention(void)
 	if (omap_irq_pending())
 		goto no_sleep;
 
-	/* Block console output in case it is on one of the OMAP UARTs */
-	if (!is_suspending())
-		if (!console_trylock())
-			goto no_sleep;
-
-	omap_uart_prepare_idle(0);
-	omap_uart_prepare_idle(1);
-	omap_uart_prepare_idle(2);
-
 	/* Jump to SRAM suspend code */
 	omap2_sram_suspend(sdrc_read_reg(SDRC_DLLA_CTRL),
 			   OMAP_SDRC_REGADDR(SDRC_DLLA_CTRL),
 			   OMAP_SDRC_REGADDR(SDRC_POWER));
 
-	omap_uart_resume_idle(2);
-	omap_uart_resume_idle(1);
-	omap_uart_resume_idle(0);
-
-	if (!is_suspending())
-		console_unlock();
-
 no_sleep:
 	if (omap2_pm_debug) {
 		unsigned long long tmp;
@@ -317,7 +300,6 @@ static int omap2_pm_suspend(void)
 	mir1 = omap_readl(0x480fe0a4);
 	omap_writel(1 << 5, 0x480fe0ac);
 
-	omap_uart_prepare_suspend();
 	omap2_enter_full_retention();
 
 	omap_writel(mir1, 0x480fe0a4);
arch/arm/mach-omap2/pm34xx.c +0 -23
index 7255d9b..344d412 100644
@@ -28,7 +28,6 @@
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
-#include <linux/console.h>
 #include <trace/events/power.h>
 
 #include <asm/suspend.h>
@@ -379,18 +378,9 @@ void omap_sram_idle(void)
 		omap3_enable_io_chain();
 	}
 
-	/* Block console output in case it is on one of the OMAP UARTs */
-	if (!is_suspending())
-		if (per_next_state < PWRDM_POWER_ON ||
-		    core_next_state < PWRDM_POWER_ON)
-			if (!console_trylock())
-				goto console_still_active;
-
 	/* PER */
 	if (per_next_state < PWRDM_POWER_ON) {
 		per_going_off = (per_next_state == PWRDM_POWER_OFF) ? 1 : 0;
-		omap_uart_prepare_idle(2);
-		omap_uart_prepare_idle(3);
 		omap2_gpio_prepare_for_idle(per_going_off);
 		if (per_next_state == PWRDM_POWER_OFF)
 				omap3_per_save_context();
@@ -398,8 +388,6 @@ void omap_sram_idle(void)
 
 	/* CORE */
 	if (core_next_state < PWRDM_POWER_ON) {
-		omap_uart_prepare_idle(0);
-		omap_uart_prepare_idle(1);
 		if (core_next_state == PWRDM_POWER_OFF) {
 			omap3_core_save_context();
 			omap3_cm_save_context();
@@ -446,8 +434,6 @@ void omap_sram_idle(void)
 			omap3_sram_restore_context();
 			omap2_sms_restore_context();
 		}
-		omap_uart_resume_idle(0);
-		omap_uart_resume_idle(1);
 		if (core_next_state == PWRDM_POWER_OFF)
 			omap2_prm_clear_mod_reg_bits(OMAP3430_AUTO_OFF_MASK,
 					       OMAP3430_GR_MOD,
@@ -461,14 +447,8 @@ void omap_sram_idle(void)
 		omap2_gpio_resume_after_idle();
 		if (per_prev_state == PWRDM_POWER_OFF)
 			omap3_per_restore_context();
-		omap_uart_resume_idle(2);
-		omap_uart_resume_idle(3);
 	}
 
-	if (!is_suspending())
-		console_unlock();
-
-console_still_active:
 	/* Disable IO-PAD and IO-CHAIN wakeup */
 	if (omap3_has_io_wakeup() &&
 	    (per_next_state < PWRDM_POWER_ON ||
@@ -531,7 +511,6 @@ static int omap3_pm_suspend(void)
 			goto restore;
 	}
 
-	omap_uart_prepare_suspend();
 	omap3_intc_suspend();
 
 	omap_sram_idle();
@@ -578,14 +557,12 @@ static int omap3_pm_begin(suspend_state_t state)
 {
 	disable_hlt();
 	suspend_state = state;
-	omap_uart_enable_irqs(0);
 	return 0;
 }
 
 static void omap3_pm_end(void)
 {
 	suspend_state = PM_SUSPEND_ON;
-	omap_uart_enable_irqs(1);
 	enable_hlt();
 	return;
 }
arch/arm/mach-omap2/serial.c +0 -65

77 lines not on this page · raw message

arch/arm/plat-omap/include/plat/serial.h +0 -4
index de3b10c..fc8b60c 100644
@@ -111,10 +111,6 @@ extern void omap_serial_init(void);
 extern void omap_serial_init_port(struct omap_board_data *bdata);
 extern int omap_uart_can_sleep(void);
 extern void omap_uart_check_wakeup(void);
-extern void omap_uart_prepare_suspend(void);
-extern void omap_uart_prepare_idle(int num);
-extern void omap_uart_resume_idle(int num);
-extern void omap_uart_enable_irqs(int enable);
 #endif
 
 #endif
Signature · 1 line
1.7.4.1
#9 lore raw

PATCH v6 4/16 OMAP2+: UART: cleanup 8250 console driver support

In reply to Govindraj.R

We had been using traditional 8250 driver as uart console driver prior to omap-serial driver. Since we have omap-serial driver in mainline kernel for some time now it has been used as default uart console driver on omap2+ platforms. Remove 8250 support for omap-uarts.

Serial_in and serial_out override for 8250 serial driver is also removed. Empty fifo read fix is already taken care with omap-serial driver with data ready bit check from LSR reg before reading RX fifo. Also waiting for THRE(transmit hold reg empty) is done with wait_for_xmitr in omap-serial driver.

Remove headers that were necessary to support 8250 support and remove all config bindings done to keep 8250 backward compatibility while adding omap-serial driver. Remove omap_uart_reset needed for 8250 autoconf.

---
 arch/arm/mach-omap2/serial.c |  111 ------------------------------------------
 1 files changed, 0 insertions(+), 111 deletions(-)
arch/arm/mach-omap2/serial.c +0 -111
index 62d15ad..4ab90bf 100644
@@ -19,23 +19,17 @@
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/serial_reg.h>
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
-#include <linux/serial_8250.h>
 #include <linux/pm_runtime.h>
 #include <linux/console.h>
 
-#ifdef CONFIG_SERIAL_OMAP
 #include <plat/omap-serial.h>
-#endif
-
 #include <plat/common.h>
 #include <plat/board.h>
-#include <plat/clock.h>
 #include <plat/dma.h>
 #include <plat/omap_hwmod.h>
 #include <plat/omap_device.h>
@@ -47,10 +41,8 @@
 #include "control.h"
 #include "mux.h"
 
-#define UART_OMAP_NO_EMPTY_FIFO_READ_IP_REV	0x52
 #define UART_OMAP_WER		0x17	/* Wake-up enable register */
 
-#define UART_ERRATA_FIFO_FULL_ABORT	(0x1 << 0)
 #define UART_ERRATA_i202_MDR1_ACCESS	(0x1 << 1)
 
 /*
@@ -157,19 +149,6 @@ static inline void serial_write_reg(struct omap_uart_state *uart, int offset,
 	__raw_writeb(value, uart->membase + offset);
 }
 
-/*
- * Internal UARTs need to be initialized for the 8250 autoconfig to work
- * properly. Note that the TX watermark initialization may not be needed
- * once the 8250.c watermark handling code is merged.
- */
-
-static inline void __init omap_uart_reset(struct omap_uart_state *uart)
-{
-	serial_write_reg(uart, UART_OMAP_MDR1, UART_OMAP_MDR1_DISABLE);
-	serial_write_reg(uart, UART_OMAP_SCR, 0x08);
-	serial_write_reg(uart, UART_OMAP_MDR1, UART_OMAP_MDR1_16X_MODE);
-}
-
 #if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3)
 
 /*
@@ -555,41 +534,6 @@ static void omap_uart_block_sleep(struct omap_uart_state *uart)
 #define DEV_CREATE_FILE(dev, attr)
 #endif /* CONFIG_PM */
 
-#ifndef CONFIG_SERIAL_OMAP
-/*
- * Override the default 8250 read handler: mem_serial_in()
- * Empty RX fifo read causes an abort on omap3630 and omap4
- * This function makes sure that an empty rx fifo is not read on these silicons
- * (OMAP1/2/3430 are not affected)
- */
-static unsigned int serial_in_override(struct uart_port *up, int offset)
-{
-	if (UART_RX == offset) {
-		unsigned int lsr;
-		lsr = __serial_read_reg(up, UART_LSR);
-		if (!(lsr & UART_LSR_DR))
-			return -EPERM;
-	}
-
-	return __serial_read_reg(up, offset);
-}
-
-static void serial_out_override(struct uart_port *up, int offset, int value)
-{
-	unsigned int status, tmout = 10000;
-
-	status = __serial_read_reg(up, UART_LSR);
-	while (!(status & UART_LSR_THRE)) {
-		/* Wait up to 10ms for the character(s) to be sent. */
-		if (--tmout == 0)
-			break;
-		udelay(1);
-		status = __serial_read_reg(up, UART_LSR);
-	}
-	__serial_write_reg(up, offset, value);
-}
-#endif
-
 static int __init omap_serial_early_init(void)
 {
 	int i = 0;
@@ -650,15 +594,7 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
 	void *pdata = NULL;
 	u32 pdata_size = 0;
 	char *name;
-#ifndef CONFIG_SERIAL_OMAP
-	struct plat_serial8250_port ports[2] = {
-		{},
-		{.flags = 0},
-	};
-	struct plat_serial8250_port *p = &ports[0];
-#else
 	struct omap_uart_port_info omap_up;
-#endif
 
 	if (WARN_ON(!bdata))
 		return;
@@ -673,51 +609,6 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
 
 	oh = uart->oh;
 	uart->dma_enabled = 0;
-#ifndef CONFIG_SERIAL_OMAP
-	name = "serial8250";
-
-	/*
-	 * !! 8250 driver does not use standard IORESOURCE* It
-	 * has it's own custom pdata that can be taken from
-	 * the hwmod resource data.  But, this needs to be
-	 * done after the build.
-	 *
-	 * ?? does it have to be done before the register ??
-	 * YES, because platform_device_data_add() copies
-	 * pdata, it does not use a pointer.
-	 */
-	p->flags = UPF_BOOT_AUTOCONF;
-	p->iotype = UPIO_MEM;
-	p->regshift = 2;
-	p->uartclk = OMAP24XX_BASE_BAUD * 16;
-	p->irq = oh->mpu_irqs[0].irq;
-	p->mapbase = oh->slaves[0]->addr->pa_start;
-	p->membase = omap_hwmod_get_mpu_rt_va(oh);
-	p->irqflags = IRQF_SHARED;
-	p->private_data = uart;
-
-	/*
-	 * omap44xx, ti816x: Never read empty UART fifo
-	 * omap3xxx: Never read empty UART fifo on UARTs
-	 * with IP rev >=0x52
-	 */
-	uart->regshift = p->regshift;
-	uart->membase = p->membase;
-	if (cpu_is_omap44xx() || cpu_is_ti816x())
-		uart->errata |= UART_ERRATA_FIFO_FULL_ABORT;
-	else if ((serial_read_reg(uart, UART_OMAP_MVER) & 0xFF)
-			>= UART_OMAP_NO_EMPTY_FIFO_READ_IP_REV)
-		uart->errata |= UART_ERRATA_FIFO_FULL_ABORT;
-
-	if (uart->errata & UART_ERRATA_FIFO_FULL_ABORT) {
-		p->serial_in = serial_in_override;
-		p->serial_out = serial_out_override;
-	}
-
-	pdata = &ports[0];
-	pdata_size = 2 * sizeof(struct plat_serial8250_port);
-#else
-
 	name = DRIVER_NAME;
 
 	omap_up.dma_enabled = uart->dma_enabled;
@@ -729,7 +620,6 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
 
 	pdata = &omap_up;
 	pdata_size = sizeof(struct omap_uart_port_info);
-#endif
 
 	if (WARN_ON(!oh))
 		return;
@@ -762,7 +652,6 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
 
 	omap_device_enable(uart->pdev);
 	omap_uart_idle_init(uart);
-	omap_uart_reset(uart);
 	omap_hwmod_enable_wakeup(uart->oh);
 	omap_device_idle(uart->pdev);
 
Signature · 1 line
1.7.4.1
#10 lore raw

PATCH v6 4/16 OMAP2+: UART: cleanup 8250 console driver support

Quoted 5 lines · Govindraj.R

We had been using traditional 8250 driver as uart console driver prior to omap-serial driver. Since we have omap-serial driver in mainline kernel for some time now it has been used as default uart console driver on omap2+ platforms. Remove 8250 support for omap-uarts.

Nice to see the this disappearing.

Quoted 3 lines

Serial_in and serial_out override for 8250 serial driver is also removed. Empty fifo read fix is already taken care with omap-serial driver with data ready bit check from LSR reg before reading RX fifo.

As stated in the previous review. Patches that move code/features should have the removal and the add-back in the same patch. Doing so makes it easy for reviewers to see whether it was simply moved, or if it was modified when it was moved, etc.

Quoted 2 lines

Also waiting for THRE(transmit hold reg empty) is done with wait_for_xmitr in omap-serial driver.

Again, remove it here in the patch that adds that support (the errata patch I guess.)

Quoted 6 lines

Remove headers that were necessary to support 8250 support and remove all config bindings done to keep 8250 backward compatibility while adding omap-serial driver. Remove omap_uart_reset needed for 8250 autoconf.

So basically, this patch should only remove the legacy 8250 support (as the subject says) and everything else should be done in the other relevant patches.

Kevin

#11 lore raw

PATCH v6 4/16 OMAP2+: UART: cleanup 8250 console driver support

Hi Kevin,

Thanks for the review,

Quoted 13 lines · Kevin Hilman
Quoted 5 lines · Govindraj.R

We had been using traditional 8250 driver as uart console driver prior to omap-serial driver. Since we have omap-serial driver in mainline kernel for some time now it has been used as default uart console driver on omap2+ platforms. Remove 8250 support for omap-uarts.

Nice to see the this disappearing.

Quoted 2 lines

Serial_in and serial_out override for 8250 serial driver is also removed.

Quoted 8 lines
Quoted 2 lines

Empty fifo read fix is already taken care with omap-serial driver with data ready bit check from LSR reg before reading RX fifo.

As stated in the previous review. ?Patches that move code/features should have the removal and the add-back in the same patch. ?Doing so makes it easy for reviewers to see whether it was simply moved, or if it was modified when it was moved, etc.

Empty fifo read is already taken care in omap-serial.c and is part of mainline code.
Nothing to add to omap-serial.c

Quoted 6 lines
Quoted 2 lines

Also waiting for THRE(transmit hold reg empty) is done with wait_for_xmitr in omap-serial driver.

Again, remove it here in the patch that adds that support (the errata patch I guess.)

The errata patch ( [PATCH v6 11/16] ) moves only mdr_errata and force_idle from serial.c to omap-serial.c.

Already handled stuffs and things that already exists with omap-serial.c are removed here.

Quoted 11 lines
Quoted 6 lines

Remove headers that were necessary to support 8250 support and remove all config bindings done to keep 8250 backward compatibility while adding omap-serial driver. Remove omap_uart_reset needed for 8250 autoconf.

So basically, this patch should only remove the legacy 8250 support (as the subject says) and everything else should be done in the other relevant patches.

Yes removes only the 8250 code. serial_in/serial_out were read/write overrides part of 8250 code.

serial_in/serial_out had these checks for empty fifo read and wait for tx which is already handled with omap-serial.c.

--
Thanks,
Govindraj.R

Quoted 6 lines

Kevin
--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in the body of a message to majordomo at vger.kernel.org
More majordomo info at ?http://vger.kernel.org/majordomo-info.html

#12 lore raw

PATCH v6 4/16 OMAP2+: UART: cleanup 8250 console driver support

Quoted 22 lines · Govindraj

Hi Kevin,

Thanks for the review,

Quoted 16 lines · Kevin Hilman
Quoted 5 lines · Govindraj.R

We had been using traditional 8250 driver as uart console driver prior to omap-serial driver. Since we have omap-serial driver in mainline kernel for some time now it has been used as default uart console driver on omap2+ platforms. Remove 8250 support for omap-uarts.

Nice to see the this disappearing.

Quoted 5 lines

Serial_in and serial_out override for 8250 serial driver is also removed.

Empty fifo read fix is already taken care with omap-serial driver with data ready bit check from LSR reg before reading RX fifo.

Quoted 8 lines
Quoted 5 lines

As stated in the previous review. ?Patches that move code/features should have the removal and the add-back in the same patch. ?Doing so makes it easy for reviewers to see whether it was simply moved, or if it was modified when it was moved, etc.

Empty fifo read is already taken care in omap-serial.c and is part of mainline code. Nothing to add to omap-serial.c

OK, good. I guess I missed the 'already' part in your changelog.

Quoted 7 lines
Quoted 6 lines
Quoted 2 lines

Also waiting for THRE(transmit hold reg empty) is done with wait_for_xmitr in omap-serial driver.

Again, remove it here in the patch that adds that support (the errata patch I guess.)

Quoted 5 lines

The errata patch ( [PATCH v6 11/16] ) moves only mdr_errata and force_idle from serial.c to omap-serial.c.

Already handled stuffs and things that already exists with omap-serial.c are removed here.

OK.

Quoted 12 lines
Quoted 11 lines
Quoted 6 lines

Remove headers that were necessary to support 8250 support and remove all config bindings done to keep 8250 backward compatibility while adding omap-serial driver. Remove omap_uart_reset needed for 8250 autoconf.

So basically, this patch should only remove the legacy 8250 support (as the subject says) and everything else should be done in the other relevant patches.

Quoted 5 lines

Yes removes only the 8250 code. serial_in/serial_out were read/write overrides part of 8250 code.

serial_in/serial_out had these checks for empty fifo read and wait for tx which is already handled with omap-serial.c.

OK, thanks for the clarification.

The changelog could've been a bit more specific for readers not intimately familiar with the driver.

Kevin

#13 lore raw

PATCH v6 4/16 OMAP2+: UART: cleanup 8250 console driver support

Quoted 65 lines · Kevin Hilman
Quoted 22 lines · Govindraj

Hi Kevin,

Thanks for the review,

Quoted 16 lines · Kevin Hilman
Quoted 5 lines · Govindraj.R

We had been using traditional 8250 driver as uart console driver prior to omap-serial driver. Since we have omap-serial driver in mainline kernel for some time now it has been used as default uart console driver on omap2+ platforms. Remove 8250 support for omap-uarts.

Nice to see the this disappearing.

Quoted 5 lines

Serial_in and serial_out override for 8250 serial driver is also removed.

Empty fifo read fix is already taken care with omap-serial driver with data ready bit check from LSR reg before reading RX fifo.

Quoted 8 lines
Quoted 5 lines

As stated in the previous review. ?Patches that move code/features should have the removal and the add-back in the same patch. ?Doing so makes it easy for reviewers to see whether it was simply moved, or if it was modified when it was moved, etc.

Empty fifo read is already taken care in omap-serial.c and is part of mainline code. ?Nothing to add to omap-serial.c

OK, good. ?I guess I missed the 'already' part in your changelog.

Quoted 7 lines
Quoted 6 lines
Quoted 2 lines

Also waiting for THRE(transmit hold reg empty) is done with wait_for_xmitr in omap-serial driver.

Again, remove it here in the patch that adds that support (the errata patch I guess.)

Quoted 5 lines

The errata patch ( [PATCH v6 11/16] ) moves only mdr_errata and force_idle from serial.c to omap-serial.c.

Already handled stuffs and things that already exists with omap-serial.c are removed here.

OK.

Quoted 15 lines
Quoted 11 lines
Quoted 6 lines

Remove headers that were necessary to support 8250 support and remove all config bindings done to keep 8250 backward compatibility while adding omap-serial driver. Remove omap_uart_reset needed for 8250 autoconf.

So basically, this patch should only remove the legacy 8250 support (as the subject says) and everything else should be done in the other relevant patches.

Yes removes only the 8250 code. serial_in/serial_out were read/write overrides part of 8250 code.

Quoted 8 lines
Quoted 2 lines

serial_in/serial_out had these checks for empty fifo read and wait for tx which is already handled with omap-serial.c.

OK, thanks for the clarification.

The changelog could've been a bit more specific for readers not intimately familiar with the driver.

Okay fine, I will re-visit this.

--
Thanks,
Govindraj.R

#14 lore raw

PATCH v6 5/16 OMAP2+: UART: Cleanup part of clock gating mechanism for uart

In reply to Govindraj.R

Currently we use a shared irq handler to identify uart activity and then trigger a timer. Based the timeout value set from sysfs the timer used to expire. If no uart-activity was detected timer-expiry func sets can_sleep flag. Based on this we will disable the uart clocks in idle path.

Since the clock gating mechanism is outside the uart driver, we currently use this mechanism. In preparation to runtime implementation for omap-serial driver we can cleanup this mechanism and use runtime API's to gate uart clocks.

Also remove timer related info from local uart_state struct and remove the code used to set timeout value from sysfs. Remove un-used function omap_uart_check_wakeup.

---
 arch/arm/mach-omap2/serial.c                  |  116 +------------------------
 arch/arm/plat-omap/include/plat/omap-serial.h |    1 -
 arch/arm/plat-omap/include/plat/serial.h      |    1 -
 3 files changed, 1 insertions(+), 117 deletions(-)
arch/arm/mach-omap2/serial.c +1 -115
index 4ab90bf..c98b9b4 100644
@@ -58,8 +58,6 @@
 struct omap_uart_state {
 	int num;
 	int can_sleep;
-	struct timer_list timer;
-	u32 timeout;
 
 	void __iomem *wk_st;
 	void __iomem *wk_en;
@@ -67,13 +65,9 @@ struct omap_uart_state {
 	u32 padconf;
 	u32 dma_enabled;
 
-	struct clk *ick;
-	struct clk *fck;
 	int clocked;
 
-	int irq;
 	int regshift;
-	int irqflags;
 	void __iomem *membase;
 	resource_size_t mapbase;
 
@@ -340,32 +334,6 @@ static void omap_uart_block_sleep(struct omap_uart_state *uart)
 
 	omap_uart_smart_idle_enable(uart, 0);
 	uart->can_sleep = 0;
-	if (uart->timeout)
-		mod_timer(&uart->timer, jiffies + uart->timeout);
-	else
-		del_timer(&uart->timer);
-}
-
-static void omap_uart_allow_sleep(struct omap_uart_state *uart)
-{
-	if (device_may_wakeup(&uart->pdev->dev))
-		omap_uart_enable_wakeup(uart);
-	else
-		omap_uart_disable_wakeup(uart);
-
-	if (!uart->clocked)
-		return;
-
-	omap_uart_smart_idle_enable(uart, 1);
-	uart->can_sleep = 1;
-	del_timer(&uart->timer);
-}
-
-static void omap_uart_idle_timer(unsigned long data)
-{
-	struct omap_uart_state *uart = (struct omap_uart_state *)data;
-
-	omap_uart_allow_sleep(uart);
 }
 
 int omap_uart_can_sleep(void)
@@ -389,35 +357,11 @@ int omap_uart_can_sleep(void)
 	return can_sleep;
 }
 
-/**
- * omap_uart_interrupt()
- *
- * This handler is used only to detect that *any* UART interrupt has
- * occurred.  It does _nothing_ to handle the interrupt.  Rather,
- * any UART interrupt will trigger the inactivity timer so the
- * UART will not idle or sleep for its timeout period.
- *
- **/
-/* static int first_interrupt; */
-static irqreturn_t omap_uart_interrupt(int irq, void *dev_id)
-{
-	struct omap_uart_state *uart = dev_id;
-
-	omap_uart_block_sleep(uart);
-
-	return IRQ_NONE;
-}
-
 static void omap_uart_idle_init(struct omap_uart_state *uart)
 {
 	int ret;
 
 	uart->can_sleep = 0;
-	uart->timeout = DEFAULT_TIMEOUT;
-	setup_timer(&uart->timer, omap_uart_idle_timer,
-		    (unsigned long) uart);
-	if (uart->timeout)
-		mod_timer(&uart->timer, jiffies + uart->timeout);
 	omap_uart_smart_idle_enable(uart, 0);
 
 	if (cpu_is_omap34xx() && !cpu_is_ti816x()) {
@@ -479,51 +423,8 @@ static void omap_uart_idle_init(struct omap_uart_state *uart)
 		uart->wk_mask = 0;
 		uart->padconf = 0;
 	}
-
-	uart->irqflags |= IRQF_SHARED;
-	ret = request_threaded_irq(uart->irq, NULL, omap_uart_interrupt,
-				   IRQF_SHARED, "serial idle", (void *)uart);
-	WARN_ON(ret);
-}
-
-static ssize_t sleep_timeout_show(struct device *dev,
-				  struct device_attribute *attr,
-				  char *buf)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	struct omap_device *odev = to_omap_device(pdev);
-	struct omap_uart_state *uart = odev->hwmods[0]->dev_attr;
-
-	return sprintf(buf, "%u\n", uart->timeout / HZ);
 }
 
-static ssize_t sleep_timeout_store(struct device *dev,
-				   struct device_attribute *attr,
-				   const char *buf, size_t n)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	struct omap_device *odev = to_omap_device(pdev);
-	struct omap_uart_state *uart = odev->hwmods[0]->dev_attr;
-	unsigned int value;
-
-	if (sscanf(buf, "%u", &value) != 1) {
-		dev_err(dev, "sleep_timeout_store: Invalid value\n");
-		return -EINVAL;
-	}
-
-	uart->timeout = value * HZ;
-	if (uart->timeout)
-		mod_timer(&uart->timer, jiffies + uart->timeout);
-	else
-		/* A zero value means disable timeout feature */
-		omap_uart_block_sleep(uart);
-
-	return n;
-}
-
-static DEVICE_ATTR(sleep_timeout, 0644, sleep_timeout_show,
-		sleep_timeout_store);
-#define DEV_CREATE_FILE(dev, attr) WARN_ON(device_create_file(dev, attr))
 #else
 static inline void omap_uart_idle_init(struct omap_uart_state *uart) {}
 static void omap_uart_block_sleep(struct omap_uart_state *uart)
@@ -531,7 +432,6 @@ static void omap_uart_block_sleep(struct omap_uart_state *uart)
 	/* Needed to enable UART clocks when built without CONFIG_PM */
 	omap_uart_enable_clocks(uart);
 }
-#define DEV_CREATE_FILE(dev, attr)
 #endif /* CONFIG_PM */
 
 static int __init omap_serial_early_init(void)
@@ -615,7 +515,6 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
 	omap_up.uartclk = OMAP24XX_BASE_BAUD * 16;
 	omap_up.mapbase = oh->slaves[0]->addr->pa_start;
 	omap_up.membase = omap_hwmod_get_mpu_rt_va(oh);
-	omap_up.irqflags = IRQF_SHARED;
 	omap_up.flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
 
 	pdata = &omap_up;
@@ -633,7 +532,6 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
 	omap_device_disable_idle_on_suspend(pdev);
 	oh->mux = omap_hwmod_mux_init(bdata->pads, bdata->pads_cnt);
 
-	uart->irq = oh->mpu_irqs[0].irq;
 	uart->regshift = 2;
 	uart->mapbase = oh->slaves[0]->addr->pa_start;
 	uart->membase = omap_hwmod_get_mpu_rt_va(oh);
@@ -655,24 +553,12 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
 	omap_hwmod_enable_wakeup(uart->oh);
 	omap_device_idle(uart->pdev);
 
-	/*
-	 * Need to block sleep long enough for interrupt driven
-	 * driver to start.  Console driver is in polling mode
-	 * so device needs to be kept enabled while polling driver
-	 * is in use.
-	 */
-	if (uart->timeout)
-		uart->timeout = (30 * HZ);
 	omap_uart_block_sleep(uart);
-	uart->timeout = DEFAULT_TIMEOUT;
-
 	console_unlock();
 
 	if ((cpu_is_omap34xx() && uart->padconf) ||
-	    (uart->wk_en && uart->wk_mask)) {
+	    (uart->wk_en && uart->wk_mask))
 		device_init_wakeup(&pdev->dev, true);
-		DEV_CREATE_FILE(&pdev->dev, &dev_attr_sleep_timeout);
-	}
 
 	/* Enable the MDR1 errata for OMAP3 */
 	if (cpu_is_omap34xx() && !cpu_is_ti816x())
arch/arm/plat-omap/include/plat/omap-serial.h +0 -1
index 2682043..307cd6f 100644
@@ -61,7 +61,6 @@ struct omap_uart_port_info {
 	unsigned int		uartclk;	/* UART clock rate */
 	void __iomem		*membase;	/* ioremap cookie or NULL */
 	resource_size_t		mapbase;	/* resource base */
-	unsigned long		irqflags;	/* request_irq flags */
 	upf_t			flags;		/* UPF_* flags */
 };
 
arch/arm/plat-omap/include/plat/serial.h +0 -1
index fc8b60c..a8bc1f1 100644
@@ -110,7 +110,6 @@ struct omap_board_data;
 extern void omap_serial_init(void);
 extern void omap_serial_init_port(struct omap_board_data *bdata);
 extern int omap_uart_can_sleep(void);
-extern void omap_uart_check_wakeup(void);
 #endif
 
 #endif
Signature · 1 line
1.7.4.1
#15 lore raw

PATCH v6 5/16 OMAP2+: UART: Cleanup part of clock gating mechanism for uart

Quoted 2 lines · Govindraj.R

Currently we use a shared irq handler to identify uart activity and then trigger a timer.

OK.

Quoted 1 line

Based the timeout value set from sysfs the timer used to expire.

Please re-phrase as I'm not sure what is being said here.

Quoted 7 lines

If no uart-activity was detected timer-expiry func sets can_sleep flag. Based on this we will disable the uart clocks in idle path.

Since the clock gating mechanism is outside the uart driver, we currently use this mechanism. In preparation to runtime implementation for omap-serial driver we can cleanup this mechanism and use runtime API's to gate uart clocks.

Quoted 5 lines

Also remove timer related info from local uart_state struct and remove the code used to set timeout value from sysfs. Remove un-used function omap_uart_check_wakeup.

The patch itself fine, and is a well-neede cleanup, but changelog (especially the first part) does not read well.

Kevin

#16 lore raw

PATCH v6 5/16 OMAP2+: UART: Cleanup part of clock gating mechanism for uart

Quoted 18 lines · Kevin Hilman
Quoted 2 lines · Govindraj.R

Currently we use a shared irq handler to identify uart activity and then trigger a timer.

OK.

Quoted 1 line

Based the timeout value set from sysfs the timer used to expire.

Please re-phrase as I'm not sure what is being said here.

Quoted 7 lines

If no uart-activity was detected timer-expiry func sets can_sleep flag. Based on this we will disable the uart clocks in idle path.

Since the clock gating mechanism is outside the uart driver, we currently use this mechanism. In preparation to runtime implementation for omap-serial driver we can cleanup this mechanism and use runtime API's to gate uart clocks.

Quoted 9 lines
Quoted 5 lines

Also remove timer related info from local uart_state struct and remove the code used to set timeout value from sysfs. Remove un-used function omap_uart_check_wakeup.

The patch itself fine, and is a well-neede cleanup, but changelog (especially the first part) does not read well.

Okay, Will Correct.

--
Thanks.
Govindraj.R

#17 lore raw

PATCH v6 6/16 OMAP2+: UART: Remove certain feilds from omap_uart_state struct

In reply to Govindraj.R

Removing some of the uart info that is maintained in omap_uart_state struct used for UART PM in serial.c.

Remove omap_uart_state struct dependency from omap_serial_init, omap_serial_init_port, omap_serial_early_init and omap_uart_idle_init functions. And populate the same info in omap_uart_port_info struct used as pdata struct.

Added omap_uart_hwmod_lookup function to look up oh by name used in serial_port_init and omap_serial_early_init functions.

A list of omap_uart_state was maintained one for each uart, the same is removed. Number of uarts available is maintained in num_uarts field, re-use the same in omap_serial_init func to register each uart.

Remove omap_info which used details from omap_uart_state and use a pdata pointer to pass platform specific info to driver.

The mapbase (start_address), membase(io_remap cookie) maintained as part of uart_state struct and pdata struct are removed as this is handled within driver. Errata field is also moved to pdata. These changes are done to cleanup serial.c file and prepare for runtime changes.

---
 arch/arm/mach-omap2/serial.c                  |  132 +++++++++---------------
 arch/arm/plat-omap/include/plat/omap-serial.h |    4 +-
 drivers/tty/serial/omap-serial.c              |   12 ++-
 3 files changed, 61 insertions(+), 87 deletions(-)
arch/arm/mach-omap2/serial.c +50 -82
index c98b9b4..8c43d1c 100644
@@ -68,14 +68,6 @@ struct omap_uart_state {
 	int clocked;
 
 	int regshift;
-	void __iomem *membase;
-	resource_size_t mapbase;
-
-	struct list_head node;
-	struct omap_hwmod *oh;
-	struct platform_device *pdev;
-
-	u32 errata;
 #if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM)
 	int context_valid;
 
@@ -90,7 +82,6 @@ struct omap_uart_state {
 #endif
 };
 
-static LIST_HEAD(uart_list);
 static u8 num_uarts;
 
 static int uart_idle_hwmod(struct omap_device *od)
@@ -143,7 +134,19 @@ static inline void serial_write_reg(struct omap_uart_state *uart, int offset,
 	__raw_writeb(value, uart->membase + offset);
 }
 
-#if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3)
+struct omap_hwmod *omap_uart_hwmod_lookup(int num)
+{
+	struct omap_hwmod *oh;
+	char oh_name[MAX_UART_HWMOD_NAME_LEN];
+
+	snprintf(oh_name, MAX_UART_HWMOD_NAME_LEN, "uart%d", num + 1);
+	oh = omap_hwmod_lookup(oh_name);
+	WARN(IS_ERR(oh), "Could not lookup hmwod info for %s\n",
+			oh_name);
+	return oh;
+}
+
+#if defined(CONFIG_PM)
 
 /*
  * Work Around for Errata i202 (3430 - 1.12, 3630 - 1.6)
@@ -357,22 +360,17 @@ int omap_uart_can_sleep(void)
 	return can_sleep;
 }
 
-static void omap_uart_idle_init(struct omap_uart_state *uart)
+static void omap_uart_idle_init(struct omap_uart_port_info *uart,
+				unsigned short num)
 {
-	int ret;
-
-	uart->can_sleep = 0;
-	omap_uart_smart_idle_enable(uart, 0);
-
 	if (cpu_is_omap34xx() && !cpu_is_ti816x()) {
-		u32 mod = (uart->num > 1) ? OMAP3430_PER_MOD : CORE_MOD;
+		u32 mod = (num > 1) ? OMAP3430_PER_MOD : CORE_MOD;
 		u32 wk_mask = 0;
 		u32 padconf = 0;
 
-		/* XXX These PRM accesses do not belong here */
 		uart->wk_en = OMAP34XX_PRM_REGADDR(mod, PM_WKEN1);
 		uart->wk_st = OMAP34XX_PRM_REGADDR(mod, PM_WKST1);
-		switch (uart->num) {
+		switch (num) {
 		case 0:
 			wk_mask = OMAP3430_ST_UART1_MASK;
 			padconf = 0x182;
@@ -391,12 +389,11 @@ static void omap_uart_idle_init(struct omap_uart_state *uart)
 			break;
 		}
 		uart->wk_mask = wk_mask;
-		uart->padconf = padconf;
 	} else if (cpu_is_omap24xx()) {
 		u32 wk_mask = 0;
 		u32 wk_en = PM_WKEN1, wk_st = PM_WKST1;
 
-		switch (uart->num) {
+		switch (num) {
 		case 0:
 			wk_mask = OMAP24XX_ST_UART1_MASK;
 			break;
@@ -421,7 +418,6 @@ static void omap_uart_idle_init(struct omap_uart_state *uart)
 		uart->wk_en = NULL;
 		uart->wk_st = NULL;
 		uart->wk_mask = 0;
-		uart->padconf = 0;
 	}
 }
 
@@ -436,26 +432,13 @@ static void omap_uart_block_sleep(struct omap_uart_state *uart)
 
 static int __init omap_serial_early_init(void)
 {
-	int i = 0;
-
 	do {
-		char oh_name[MAX_UART_HWMOD_NAME_LEN];
 		struct omap_hwmod *oh;
-		struct omap_uart_state *uart;
 
-		snprintf(oh_name, MAX_UART_HWMOD_NAME_LEN,
-			 "uart%d", i + 1);
-		oh = omap_hwmod_lookup(oh_name);
+		oh = omap_uart_hwmod_lookup(num_uarts);
 		if (!oh)
 			break;
 
-		uart = kzalloc(sizeof(struct omap_uart_state), GFP_KERNEL);
-		if (WARN_ON(!uart))
-			return -ENODEV;
-
-		uart->oh = oh;
-		uart->num = i++;
-		list_add_tail(&uart->node, &uart_list);
 		num_uarts++;
 
 		/*
@@ -468,7 +451,7 @@ static int __init omap_serial_early_init(void)
 		 * to determine SoC specific init before omap_device
 		 * is ready.  Therefore, don't allow idle here
 		 */
-		uart->oh->flags |= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET;
+		oh->flags |= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET;
 	} while (1);
 
 	return 0;
@@ -488,57 +471,47 @@ core_initcall(omap_serial_early_init);
  */
 void __init omap_serial_init_port(struct omap_board_data *bdata)
 {
-	struct omap_uart_state *uart;
 	struct omap_hwmod *oh;
 	struct platform_device *pdev;
-	void *pdata = NULL;
+	char *name = DRIVER_NAME;
+	struct omap_uart_port_info *pdata;
 	u32 pdata_size = 0;
-	char *name;
-	struct omap_uart_port_info omap_up;
 
 	if (WARN_ON(!bdata))
 		return;
 	if (WARN_ON(bdata->id < 0))
 		return;
-	if (WARN_ON(bdata->id >= num_uarts))
+	if (WARN_ON(bdata->id >= OMAP_MAX_HSUART_PORTS))
 		return;
 
-	list_for_each_entry(uart, &uart_list, node)
-		if (bdata->id == uart->num)
-			break;
-
-	oh = uart->oh;
-	uart->dma_enabled = 0;
-	name = DRIVER_NAME;
+	oh = omap_uart_hwmod_lookup(bdata->id);
+	if (!oh)
+		return;
 
-	omap_up.dma_enabled = uart->dma_enabled;
-	omap_up.uartclk = OMAP24XX_BASE_BAUD * 16;
-	omap_up.mapbase = oh->slaves[0]->addr->pa_start;
-	omap_up.membase = omap_hwmod_get_mpu_rt_va(oh);
-	omap_up.flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
+	pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+	if (!pdata) {
+		pr_err("Memory allocation for UART pdata failed\n");
+		return;
+	}
 
-	pdata = &omap_up;
 	pdata_size = sizeof(struct omap_uart_port_info);
+	omap_uart_idle_init(pdata, bdata->id);
 
-	if (WARN_ON(!oh))
-		return;
+	pdata->uartclk = OMAP24XX_BASE_BAUD * 16;
+	pdata->flags = UPF_BOOT_AUTOCONF;
+
+	/* Enable the MDR1 errata for OMAP3 */
+	if (cpu_is_omap34xx() && !cpu_is_ti816x())
+		pdata->errata |= UART_ERRATA_i202_MDR1_ACCESS;
 
-	pdev = omap_device_build(name, uart->num, oh, pdata, pdata_size,
-			       omap_uart_latency,
-			       ARRAY_SIZE(omap_uart_latency), false);
+	pdev = omap_device_build(name, bdata->id, oh, pdata,
+				pdata_size, omap_uart_latency,
+				ARRAY_SIZE(omap_uart_latency), false);
 	WARN(IS_ERR(pdev), "Could not build omap_device for %s: %s.\n",
 	     name, oh->name);
 
-	omap_device_disable_idle_on_suspend(pdev);
 	oh->mux = omap_hwmod_mux_init(bdata->pads, bdata->pads_cnt);
 
-	uart->regshift = 2;
-	uart->mapbase = oh->slaves[0]->addr->pa_start;
-	uart->membase = omap_hwmod_get_mpu_rt_va(oh);
-	uart->pdev = pdev;
-
-	oh->dev_attr = uart;
-
 	console_lock(); /* in case the earlycon is on the UART */
 
 	/*
@@ -546,23 +519,18 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
 	 * on init.  Now that omap_device is ready, ensure full idle
 	 * before doing omap_device_enable().
 	 */
-	omap_hwmod_idle(uart->oh);
+	omap_hwmod_idle(oh);
 
-	omap_device_enable(uart->pdev);
-	omap_uart_idle_init(uart);
-	omap_hwmod_enable_wakeup(uart->oh);
-	omap_device_idle(uart->pdev);
+	omap_device_enable(pdev);
+	omap_hwmod_enable_wakeup(oh);
 
-	omap_uart_block_sleep(uart);
 	console_unlock();
 
-	if ((cpu_is_omap34xx() && uart->padconf) ||
-	    (uart->wk_en && uart->wk_mask))
+	if ((cpu_is_omap34xx() && bdata->pads) ||
+		(pdata->wk_en && pdata->wk_mask))
 		device_init_wakeup(&pdev->dev, true);
 
-	/* Enable the MDR1 errata for OMAP3 */
-	if (cpu_is_omap34xx() && !cpu_is_ti816x())
-		uart->errata |= UART_ERRATA_i202_MDR1_ACCESS;
+	kfree(pdata);
 }
 
 /**
@@ -574,11 +542,11 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
  */
 void __init omap_serial_init(void)
 {
-	struct omap_uart_state *uart;
 	struct omap_board_data bdata;
+	u8 i;
 
-	list_for_each_entry(uart, &uart_list, node) {
-		bdata.id = uart->num;
+	for (i = 0; i < num_uarts; i++) {
+		bdata.id = i;
 		bdata.flags = 0;
 		bdata.pads = NULL;
 		bdata.pads_cnt = 0;
arch/arm/plat-omap/include/plat/omap-serial.h +2 -2
index 307cd6f..0f061b4 100644
@@ -59,9 +59,9 @@
 struct omap_uart_port_info {
 	bool			dma_enabled;	/* To specify DMA Mode */
 	unsigned int		uartclk;	/* UART clock rate */
-	void __iomem		*membase;	/* ioremap cookie or NULL */
-	resource_size_t		mapbase;	/* resource base */
 	upf_t			flags;		/* UPF_* flags */
+
+	u32			errata;
 };
 
 struct uart_omap_dma {
drivers/tty/serial/omap-serial.c +9 -3
index 5e713d3..6c2ea54 100644
@@ -1275,10 +1275,16 @@ static int serial_omap_probe(struct platform_device *pdev)
 	up->port.ops = &serial_omap_pops;
 	up->port.line = pdev->id;
 
-	up->port.membase = omap_up_info->membase;
-	up->port.mapbase = omap_up_info->mapbase;
+	up->port.mapbase = mem->start;
+	up->port.membase = ioremap(mem->start, resource_size(mem));
+
+	if (!up->port.membase) {
+		dev_err(&pdev->dev, "can't ioremap UART\n");
+		ret = -ENOMEM;
+		goto err;
+	}
+
 	up->port.flags = omap_up_info->flags;
-	up->port.irqflags = omap_up_info->irqflags;
 	up->port.uartclk = omap_up_info->uartclk;
 	up->uart_dma.uart_base = mem->start;
 
Signature · 1 line
1.7.4.1
#18 lore raw

PATCH v6 6/16 OMAP2+: UART: Remove certain feilds from omap_uart_state struct

Quoted 7 lines · Govindraj.R

Removing some of the uart info that is maintained in omap_uart_state struct used for UART PM in serial.c.

Remove omap_uart_state struct dependency from omap_serial_init, omap_serial_init_port, omap_serial_early_init and omap_uart_idle_init functions. And populate the same info in omap_uart_port_info struct used as pdata struct.

IMO, this change doesn't belong in this patch and leads to clutter. The rest of the series slowly removes/replaces all the fields from this struct, so the right place to remove it's usage all together is at the end of the series when (if) all the fields are no longer needed (or have been moved.)

Stated differently, IMO, this patch should leave the uart->num and uart->oh and the list_head (uart->node) alone (probably uart->pdev too) and just cleanup the fields that are no longer used. Removing num, oh, node here causes churn because you're force to change things here that are then removed in later patches.

Quoted 2 lines

Added omap_uart_hwmod_lookup function to look up oh by name used in serial_port_init and omap_serial_early_init functions.

Because of the above change, you now are doing a hwmod lookup 2 times for every UART. Leaving the uart_list and uart->num in place will avoid the need for that change.

Quoted 6 lines

A list of omap_uart_state was maintained one for each uart, the same is removed. Number of uarts available is maintained in num_uarts field, re-use the same in omap_serial_init func to register each uart.

Remove omap_info which used details from omap_uart_state and use a pdata pointer to pass platform specific info to driver.

There is no omap_info. Did you mean omap_up_info?

Quoted 3 lines

The mapbase (start_address), membase(io_remap cookie) maintained as part of uart_state struct and pdata struct are removed as this is handled within driver.

This part makes sense.

Quoted 1 line

Errata field is also moved to pdata.

Why in this patch instead of the subsequent "Move errata handling from serial.c to omap-serial" patch?

Quoted 2 lines

These changes are done to cleanup serial.c file and prepare for runtime changes.

There are a lot of changes in this patch with very little description as to why, and many appear to be unrelated. They should probably be separate patches, or have a better description as to how all the changes are related so they belong in the same patch.

Quoted 42 lines
---
 arch/arm/mach-omap2/serial.c                  |  132 +++++++++---------------
 arch/arm/plat-omap/include/plat/omap-serial.h |    4 +-
 drivers/tty/serial/omap-serial.c              |   12 ++-
 3 files changed, 61 insertions(+), 87 deletions(-)
arch/arm/mach-omap2/serial.c +3 -10
index c98b9b4..8c43d1c 100644
@@ -68,14 +68,6 @@ struct omap_uart_state {
 	int clocked;
 
 	int regshift;
-	void __iomem *membase;
-	resource_size_t mapbase;
-
-	struct list_head node;
-	struct omap_hwmod *oh;
-	struct platform_device *pdev;
-
-	u32 errata;
 #if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM)
 	int context_valid;
 
@@ -90,7 +82,6 @@ struct omap_uart_state {
 #endif
 };
 
-static LIST_HEAD(uart_list);
 static u8 num_uarts;
 
 static int uart_idle_hwmod(struct omap_device *od)
@@ -143,7 +134,19 @@ static inline void serial_write_reg(struct omap_uart_state *uart, int offset,
 	__raw_writeb(value, uart->membase + offset);
 }
 
-#if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3)
+struct omap_hwmod *omap_uart_hwmod_lookup(int num)
+{
+	struct omap_hwmod *oh;

arch/arm/mach-omap2/serial.c static inline void serial_write_reg(struct omap_uart_state *uart, int offset, · line 149

Quoted 10 lines
arch/arm/mach-omap2/serial.c +10 -0
+	char oh_name[MAX_UART_HWMOD_NAME_LEN];
+
+	snprintf(oh_name, MAX_UART_HWMOD_NAME_LEN, "uart%d", num + 1);
+	oh = omap_hwmod_lookup(oh_name);
+	WARN(IS_ERR(oh), "Could not lookup hmwod info for %s\n",
+			oh_name);
+	return oh;
+}
+
+#if defined(CONFIG_PM)

The CONFIG_ARCH_OMAP3 part of this #if was dropped with this change with no mention as to why. (I understand why it was done, but it's not releveant to $SUBJECT patch so should be a separate patch.)

Quoted 12 lines
arch/arm/mach-omap2/serial.c +2 -3
 /*
  * Work Around for Errata i202 (3430 - 1.12, 3630 - 1.6)
@@ -357,22 +360,17 @@ int omap_uart_can_sleep(void)
 	return can_sleep;
 }
 
-static void omap_uart_idle_init(struct omap_uart_state *uart)
+static void omap_uart_idle_init(struct omap_uart_port_info *uart,
+				unsigned short num)
 {
-	int ret;
-

arch/arm/mach-omap2/serial.c int omap_uart_can_sleep(void) · line 372

Quoted 10 lines
arch/arm/mach-omap2/serial.c +1 -5
-	uart->can_sleep = 0;
-	omap_uart_smart_idle_enable(uart, 0);
-
 	if (cpu_is_omap34xx() && !cpu_is_ti816x()) {
-		u32 mod = (uart->num > 1) ? OMAP3430_PER_MOD : CORE_MOD;
+		u32 mod = (num > 1) ? OMAP3430_PER_MOD : CORE_MOD;
 		u32 wk_mask = 0;
 		u32 padconf = 0;
 
-		/* XXX These PRM accesses do not belong here */

why?

arch/arm/mach-omap2/serial.c static void omap_uart_idle_init(struct omap_uart_state *uart) · line 394

Quoted 12 lines
arch/arm/mach-omap2/serial.c +1 -2
 		uart->wk_en = OMAP34XX_PRM_REGADDR(mod, PM_WKEN1);
 		uart->wk_st = OMAP34XX_PRM_REGADDR(mod, PM_WKST1);
-		switch (uart->num) {
+		switch (num) {
 		case 0:
 			wk_mask = OMAP3430_ST_UART1_MASK;
 			padconf = 0x182;
@@ -391,12 +389,11 @@ static void omap_uart_idle_init(struct omap_uart_state *uart)
 			break;
 		}
 		uart->wk_mask = wk_mask;
-		uart->padconf = padconf;

The assignment is removed here, making all the rest of the padconf stuff that remains useless.

However, a subsequent patch removes the mux stuff entirely, so I suggest you just drop this change from here.

Quoted 64 lines
arch/arm/mach-omap2/serial.c +5 -19
 	} else if (cpu_is_omap24xx()) {
 		u32 wk_mask = 0;
 		u32 wk_en = PM_WKEN1, wk_st = PM_WKST1;
 
-		switch (uart->num) {
+		switch (num) {
 		case 0:
 			wk_mask = OMAP24XX_ST_UART1_MASK;
 			break;
@@ -421,7 +418,6 @@ static void omap_uart_idle_init(struct omap_uart_state *uart)
 		uart->wk_en = NULL;
 		uart->wk_st = NULL;
 		uart->wk_mask = 0;
-		uart->padconf = 0;
 	}
 }
 
@@ -436,26 +432,13 @@ static void omap_uart_block_sleep(struct omap_uart_state *uart)
 
 static int __init omap_serial_early_init(void)
 {
-	int i = 0;
-
 	do {
-		char oh_name[MAX_UART_HWMOD_NAME_LEN];
 		struct omap_hwmod *oh;
-		struct omap_uart_state *uart;
 
-		snprintf(oh_name, MAX_UART_HWMOD_NAME_LEN,
-			 "uart%d", i + 1);
-		oh = omap_hwmod_lookup(oh_name);
+		oh = omap_uart_hwmod_lookup(num_uarts);
 		if (!oh)
 			break;
 
-		uart = kzalloc(sizeof(struct omap_uart_state), GFP_KERNEL);
-		if (WARN_ON(!uart))
-			return -ENODEV;
-
-		uart->oh = oh;
-		uart->num = i++;
-		list_add_tail(&uart->node, &uart_list);
 		num_uarts++;
 
 		/*
@@ -468,7 +451,7 @@ static int __init omap_serial_early_init(void)
 		 * to determine SoC specific init before omap_device
 		 * is ready.  Therefore, don't allow idle here
 		 */
-		uart->oh->flags |= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET;
+		oh->flags |= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET;
 	} while (1);
 
 	return 0;
@@ -488,57 +471,47 @@ core_initcall(omap_serial_early_init);
  */
 void __init omap_serial_init_port(struct omap_board_data *bdata)
 {
-	struct omap_uart_state *uart;
 	struct omap_hwmod *oh;
 	struct platform_device *pdev;
-	void *pdata = NULL;
+	char *name = DRIVER_NAME;
+	struct omap_uart_port_info *pdata;

arch/arm/mach-omap2/serial.c core_initcall(omap_serial_early_init); · line 484

Quoted 10 lines
arch/arm/mach-omap2/serial.c +1 -3
 	u32 pdata_size = 0;
-	char *name;
-	struct omap_uart_port_info omap_up;
 
 	if (WARN_ON(!bdata))
 		return;
 	if (WARN_ON(bdata->id < 0))
 		return;
-	if (WARN_ON(bdata->id >= num_uarts))
+	if (WARN_ON(bdata->id >= OMAP_MAX_HSUART_PORTS))

why? because of early_init, num_uarts is already the max number of UARTs available (based on hwmod probe.)

Quoted 17 lines
arch/arm/mach-omap2/serial.c +3 -11
 		return;
 
-	list_for_each_entry(uart, &uart_list, node)
-		if (bdata->id == uart->num)
-			break;
-
-	oh = uart->oh;
-	uart->dma_enabled = 0;
-	name = DRIVER_NAME;
+	oh = omap_uart_hwmod_lookup(bdata->id);
+	if (!oh)
+		return;
 
-	omap_up.dma_enabled = uart->dma_enabled;
-	omap_up.uartclk = OMAP24XX_BASE_BAUD * 16;
-	omap_up.mapbase = oh->slaves[0]->addr->pa_start;
-	omap_up.membase = omap_hwmod_get_mpu_rt_va(oh);

arch/arm/mach-omap2/serial.c core_initcall(omap_serial_early_init); · line 498

Quoted 10 lines
arch/arm/mach-omap2/serial.c +6 -2
-	omap_up.flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
+	pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+	if (!pdata) {
+		pr_err("Memory allocation for UART pdata failed\n");
+		return;
+	}
 
-	pdata = &omap_up;
 	pdata_size = sizeof(struct omap_uart_port_info);
+	omap_uart_idle_init(pdata, bdata->id);

Why was this moved here?

ISTR that the order of this call relative to the hwmod/omap_device enable/disable calls below was important, especially in the DEBUG_LL case.

Quoted 5 lines
arch/arm/mach-omap2/serial.c +3 -2
-	if (WARN_ON(!oh))
-		return;
+	pdata->uartclk = OMAP24XX_BASE_BAUD * 16;
+	pdata->flags = UPF_BOOT_AUTOCONF;
+

arch/arm/mach-omap2/serial.c core_initcall(omap_serial_early_init); · line 509

Quoted 10 lines
arch/arm/mach-omap2/serial.c +6 -3
+	/* Enable the MDR1 errata for OMAP3 */
+	if (cpu_is_omap34xx() && !cpu_is_ti816x())
+		pdata->errata |= UART_ERRATA_i202_MDR1_ACCESS;
 
-	pdev = omap_device_build(name, uart->num, oh, pdata, pdata_size,
-			       omap_uart_latency,
-			       ARRAY_SIZE(omap_uart_latency), false);
+	pdev = omap_device_build(name, bdata->id, oh, pdata,
+				pdata_size, omap_uart_latency,
+				ARRAY_SIZE(omap_uart_latency), false);

Note the unecesary whitespace changes in this change.

arch/arm/mach-omap2/serial.c core_initcall(omap_serial_early_init); · line 532

Quoted 4 lines
arch/arm/mach-omap2/serial.c +0 -1
 	WARN(IS_ERR(pdev), "Could not build omap_device for %s: %s.\n",
 	     name, oh->name);
 
-	omap_device_disable_idle_on_suspend(pdev);

This should also be a separate patch at the end of the series, and is not related to the changes described in the changelog.

Quoted 23 lines
arch/arm/mach-omap2/serial.c +1 -12
 	oh->mux = omap_hwmod_mux_init(bdata->pads, bdata->pads_cnt);
 
-	uart->regshift = 2;
-	uart->mapbase = oh->slaves[0]->addr->pa_start;
-	uart->membase = omap_hwmod_get_mpu_rt_va(oh);
-	uart->pdev = pdev;
-
-	oh->dev_attr = uart;
-
 	console_lock(); /* in case the earlycon is on the UART */
 
 	/*
@@ -546,23 +519,18 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
 	 * on init.  Now that omap_device is ready, ensure full idle
 	 * before doing omap_device_enable().
 	 */
-	omap_hwmod_idle(uart->oh);
+	omap_hwmod_idle(oh);
 
-	omap_device_enable(uart->pdev);
-	omap_uart_idle_init(uart);
-	omap_hwmod_enable_wakeup(uart->oh);
-	omap_device_idle(uart->pdev);

arch/arm/mach-omap2/serial.c void __init omap_serial_init_port(struct omap_board_data *bdata) · line 530

Quoted 10 lines
arch/arm/mach-omap2/serial.c +4 -3
+	omap_device_enable(pdev);
+	omap_hwmod_enable_wakeup(oh);
 
-	omap_uart_block_sleep(uart);
 	console_unlock();
 
-	if ((cpu_is_omap34xx() && uart->padconf) ||
-	    (uart->wk_en && uart->wk_mask))
+	if ((cpu_is_omap34xx() && bdata->pads) ||
+		(pdata->wk_en && pdata->wk_mask))

This change seems to belong as part of the mux patch.

Quoted 53 lines
arch/arm/mach-omap2/serial.c +4 -6
 		device_init_wakeup(&pdev->dev, true);
 
-	/* Enable the MDR1 errata for OMAP3 */
-	if (cpu_is_omap34xx() && !cpu_is_ti816x())
-		uart->errata |= UART_ERRATA_i202_MDR1_ACCESS;
+	kfree(pdata);
 }
 
 /**
@@ -574,11 +542,11 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
  */
 void __init omap_serial_init(void)
 {
-	struct omap_uart_state *uart;
 	struct omap_board_data bdata;
+	u8 i;
 
-	list_for_each_entry(uart, &uart_list, node) {
-		bdata.id = uart->num;
+	for (i = 0; i < num_uarts; i++) {
+		bdata.id = i;
 		bdata.flags = 0;
 		bdata.pads = NULL;
 		bdata.pads_cnt = 0;
arch/arm/plat-omap/include/plat/omap-serial.h +2 -2
index 307cd6f..0f061b4 100644
@@ -59,9 +59,9 @@
 struct omap_uart_port_info {
 	bool			dma_enabled;	/* To specify DMA Mode */
 	unsigned int		uartclk;	/* UART clock rate */
-	void __iomem		*membase;	/* ioremap cookie or NULL */
-	resource_size_t		mapbase;	/* resource base */
 	upf_t			flags;		/* UPF_* flags */
+
+	u32			errata;
 };
 
 struct uart_omap_dma {
drivers/tty/serial/omap-serial.c +3 -2
index 5e713d3..6c2ea54 100644
@@ -1275,10 +1275,16 @@ static int serial_omap_probe(struct platform_device *pdev)
 	up->port.ops = &serial_omap_pops;
 	up->port.line = pdev->id;
 
-	up->port.membase = omap_up_info->membase;
-	up->port.mapbase = omap_up_info->mapbase;
+	up->port.mapbase = mem->start;
+	up->port.membase = ioremap(mem->start, resource_size(mem));
+

drivers/tty/serial/omap-serial.c static int serial_omap_probe(struct platform_device *pdev) · line 1289

Quoted 10 lines
drivers/tty/serial/omap-serial.c +6 -1
+	if (!up->port.membase) {
+		dev_err(&pdev->dev, "can't ioremap UART\n");
+		ret = -ENOMEM;
+		goto err;
+	}
+
 	up->port.flags = omap_up_info->flags;
-	up->port.irqflags = omap_up_info->irqflags;
 	up->port.uartclk = omap_up_info->uartclk;
 	up->uart_dma.uart_base = mem->start;

Kevin

#19 lore raw

PATCH v6 6/16 OMAP2+: UART: Remove certain feilds from omap_uart_state struct

Quoted 10 lines · Kevin Hilman
Quoted 7 lines · Govindraj.R

Removing some of the uart info that is maintained in omap_uart_state struct used for UART PM in serial.c.

Remove omap_uart_state struct dependency from omap_serial_init, omap_serial_init_port, omap_serial_early_init and omap_uart_idle_init functions. ?And populate the same info in omap_uart_port_info struct used as pdata struct.

Quoted 6 lines

IMO, this change doesn't belong in this patch and leads to clutter. ?The rest of the series slowly removes/replaces all the fields from this struct, so the right place to remove it's usage all together is at the end of the series when (if) all the fields are no longer needed (or have been moved.)

Okay will move it to end.

Quoted 6 lines

Stated differently, IMO, this patch should leave the uart->num and uart->oh and the list_head (uart->node) alone (probably uart->pdev too) and just cleanup the fields that are no longer used. ?Removing num, oh, node here causes churn because you're force to change things here that are then removed in later patches.

okay will retain the list part.

Quoted 7 lines
Quoted 2 lines

Added omap_uart_hwmod_lookup function to look up oh by name used in serial_port_init and omap_serial_early_init functions.

Because of the above change, you now are doing a hwmod lookup 2 times for every UART. ?Leaving the uart_list and uart->num in place will avoid the need for that change.

yes since uart_list was removed, will retain the uart_list to avoid the look up twice.

Quoted 8 lines
Quoted 6 lines

A list of omap_uart_state was maintained one for each uart, the same is removed. ?Number of uarts available is maintained in num_uarts field, re-use the same in omap_serial_init func to register each uart.

Remove omap_info which used details from omap_uart_state and use a pdata pointer to pass platform specific info to driver.

There is no omap_info. ?Did you mean omap_up_info?

yes sorry typo.

Quoted 7 lines
Quoted 4 lines

The mapbase (start_address), membase(io_remap cookie) maintained as part of uart_state struct and pdata struct are removed as this is handled within driver.

This part makes sense.

okay will retain this part only.

Quoted 5 lines
Quoted 1 line

Errata field is also moved to pdata.

Why in this patch instead of the subsequent "Move errata handling from serial.c to omap-serial" patch?

will move to the errata patch.

Quoted 8 lines
Quoted 2 lines

These changes are done to cleanup serial.c file and prepare for runtime changes.

There are a lot of changes in this patch with very little description as to why, and many appear to be unrelated. ?They should probably be separate patches, or have a better description as to how all the changes are related so they belong in the same patch.

okay fine will split them into smaller changes.

Quoted 98 lines
Quoted 42 lines

---

?arch/arm/mach-omap2/serial.c ? ? ? ? ? ? ? ? ?| ?132 +++++++++---------------
?arch/arm/plat-omap/include/plat/omap-serial.h | ? ?4 +-
?drivers/tty/serial/omap-serial.c ? ? ? ? ? ? ?| ? 12 ++-

?3 files changed, 61 insertions(+), 87 deletions(-)

arch/arm/mach-omap2/serial.c +0 -8
index c98b9b4..8c43d1c 100644
@@ -68,14 +68,6 @@ struct omap_uart_state {
 ? ? ? int clocked;
 
 ? ? ? int regshift;
- ? ? void __iomem *membase;
- ? ? resource_size_t mapbase;
-
- ? ? struct list_head node;
- ? ? struct omap_hwmod *oh;
- ? ? struct platform_device *pdev;
-
- ? ? u32 errata;
 ?#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM)
 ? ? ? int context_valid;
 
@@ -90,7 +82,6 @@ struct omap_uart_state {

?#endif
?};

-static LIST_HEAD(uart_list);
?static u8 num_uarts;

?static int uart_idle_hwmod(struct omap_device *od)

arch/arm/mach-omap2/serial.c +3 -1
@@ -143,7 +134,19 @@ static inline void serial_write_reg(struct omap_uart_state *uart, int offset,
 ? ? ? __raw_writeb(value, uart->membase + offset);
 ?}
 
-#if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3)
+struct omap_hwmod *omap_uart_hwmod_lookup(int num)
+{
+ ? ? struct omap_hwmod *oh;

arch/arm/mach-omap2/serial.c static inline void serial_write_reg(struct omap_uart_state *uart, int offset, · line 149

Quoted 10 lines
arch/arm/mach-omap2/serial.c +10 -0
+ ? ? char oh_name[MAX_UART_HWMOD_NAME_LEN];
+
+ ? ? snprintf(oh_name, MAX_UART_HWMOD_NAME_LEN, "uart%d", num + 1);
+ ? ? oh = omap_hwmod_lookup(oh_name);
+ ? ? WARN(IS_ERR(oh), "Could not lookup hmwod info for %s\n",
+ ? ? ? ? ? ? ? ? ? ? oh_name);
+ ? ? return oh;
+}
+
+#if defined(CONFIG_PM)

The CONFIG_ARCH_OMAP3 part of this #if was dropped with this change with no mention as to why. ?(I understand why it was done, but it's not releveant to $SUBJECT patch so should be a separate patch.)

Quoted 12 lines

?/*
? * Work Around for Errata i202 (3430 - 1.12, 3630 - 1.6)

arch/arm/mach-omap2/serial.c +2 -3
@@ -357,22 +360,17 @@ int omap_uart_can_sleep(void)
 ? ? ? return can_sleep;
 ?}
 
-static void omap_uart_idle_init(struct omap_uart_state *uart)
+static void omap_uart_idle_init(struct omap_uart_port_info *uart,
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? unsigned short num)
 ?{
- ? ? int ret;
-

arch/arm/mach-omap2/serial.c int omap_uart_can_sleep(void) · line 372

Quoted 10 lines
arch/arm/mach-omap2/serial.c +1 -5
- ? ? uart->can_sleep = 0;
- ? ? omap_uart_smart_idle_enable(uart, 0);
-
 ? ? ? if (cpu_is_omap34xx() && !cpu_is_ti816x()) {
- ? ? ? ? ? ? u32 mod = (uart->num > 1) ? OMAP3430_PER_MOD : CORE_MOD;
+ ? ? ? ? ? ? u32 mod = (num > 1) ? OMAP3430_PER_MOD : CORE_MOD;
 ? ? ? ? ? ? ? u32 wk_mask = 0;
 ? ? ? ? ? ? ? u32 padconf = 0;
 
- ? ? ? ? ? ? /* XXX These PRM accesses do not belong here */

why?

arch/arm/mach-omap2/serial.c static void omap_uart_idle_init(struct omap_uart_state *uart) · line 394

Quoted 12 lines
arch/arm/mach-omap2/serial.c +1 -1
 ? ? ? ? ? ? ? uart->wk_en = OMAP34XX_PRM_REGADDR(mod, PM_WKEN1);
 ? ? ? ? ? ? ? uart->wk_st = OMAP34XX_PRM_REGADDR(mod, PM_WKST1);
- ? ? ? ? ? ? switch (uart->num) {
+ ? ? ? ? ? ? switch (num) {

? ? ? ? ? ? ? case 0:
? ? ? ? ? ? ? ? ? ? ? wk_mask = OMAP3430_ST_UART1_MASK; ? ? ? ? ? ? ? ? ? ? ? padconf = 0x182;

arch/arm/mach-omap2/serial.c +0 -1
@@ -391,12 +389,11 @@ static void omap_uart_idle_init(struct omap_uart_state *uart)
 ? ? ? ? ? ? ? ? ? ? ? break;
 ? ? ? ? ? ? ? }
 ? ? ? ? ? ? ? uart->wk_mask = wk_mask;
- ? ? ? ? ? ? uart->padconf = padconf;

The assignment is removed here, making all the rest of the padconf stuff that remains useless.

Quoted 3 lines

However, a subsequent patch removes the mux stuff entirely, so I suggest you just drop this change from here.

okay will incorporate this as part of mux changes patch.

Quoted 68 lines
Quoted 68 lines
arch/arm/mach-omap2/serial.c +1 -1
 ? ? ? } else if (cpu_is_omap24xx()) {
 ? ? ? ? ? ? ? u32 wk_mask = 0;
 ? ? ? ? ? ? ? u32 wk_en = PM_WKEN1, wk_st = PM_WKST1;
 
- ? ? ? ? ? ? switch (uart->num) {
+ ? ? ? ? ? ? switch (num) {

? ? ? ? ? ? ? case 0:
? ? ? ? ? ? ? ? ? ? ? wk_mask = OMAP24XX_ST_UART1_MASK; ? ? ? ? ? ? ? ? ? ? ? break;

arch/arm/mach-omap2/serial.c +1 -15
@@ -421,7 +418,6 @@ static void omap_uart_idle_init(struct omap_uart_state *uart)
 ? ? ? ? ? ? ? uart->wk_en = NULL;
 ? ? ? ? ? ? ? uart->wk_st = NULL;
 ? ? ? ? ? ? ? uart->wk_mask = 0;
- ? ? ? ? ? ? uart->padconf = 0;
 ? ? ? }
 ?}
 
@@ -436,26 +432,13 @@ static void omap_uart_block_sleep(struct omap_uart_state *uart)
 
 ?static int __init omap_serial_early_init(void)
 ?{
- ? ? int i = 0;
-
 ? ? ? do {
- ? ? ? ? ? ? char oh_name[MAX_UART_HWMOD_NAME_LEN];
 ? ? ? ? ? ? ? struct omap_hwmod *oh;
- ? ? ? ? ? ? struct omap_uart_state *uart;
 
- ? ? ? ? ? ? snprintf(oh_name, MAX_UART_HWMOD_NAME_LEN,
- ? ? ? ? ? ? ? ? ? ? ?"uart%d", i + 1);
- ? ? ? ? ? ? oh = omap_hwmod_lookup(oh_name);
+ ? ? ? ? ? ? oh = omap_uart_hwmod_lookup(num_uarts);
 ? ? ? ? ? ? ? if (!oh)
 ? ? ? ? ? ? ? ? ? ? ? break;
 
- ? ? ? ? ? ? uart = kzalloc(sizeof(struct omap_uart_state), GFP_KERNEL);
- ? ? ? ? ? ? if (WARN_ON(!uart))
- ? ? ? ? ? ? ? ? ? ? return -ENODEV;
-
- ? ? ? ? ? ? uart->oh = oh;
- ? ? ? ? ? ? uart->num = i++;
- ? ? ? ? ? ? list_add_tail(&uart->node, &uart_list);
 ? ? ? ? ? ? ? num_uarts++;
 

? ? ? ? ? ? ? /*

arch/arm/mach-omap2/serial.c +0 -0
@@ -468,7 +451,7 @@ static int __init omap_serial_early_init(void)

? ? ? ? ? ? ? ?* to determine SoC specific init before omap_device ? ? ? ? ? ? ? ?* is ready. ?Therefore, don't allow idle here
? ? ? ? ? ? ? ?*/
- ? ? ? ? ? ? uart->oh->flags |= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET;
+ ? ? ? ? ? ? oh->flags |= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET; ? ? ? } while (1);

? ? ? return 0;

arch/arm/mach-omap2/serial.c +0 -0
@@ -488,57 +471,47 @@ core_initcall(omap_serial_early_init);

? */
?void __init omap_serial_init_port(struct omap_board_data *bdata) ?{
- ? ? struct omap_uart_state *uart;
? ? ? struct omap_hwmod *oh;
? ? ? struct platform_device *pdev;
- ? ? void *pdata = NULL;
+ ? ? char *name = DRIVER_NAME;
+ ? ? struct omap_uart_port_info *pdata;
? ? ? u32 pdata_size = 0;
- ? ? char *name;
- ? ? struct omap_uart_port_info omap_up;

Quoted 10 lines
Quoted 6 lines

? ? ? if (WARN_ON(!bdata))
? ? ? ? ? ? ? return;
? ? ? if (WARN_ON(bdata->id < 0))
? ? ? ? ? ? ? return;
- ? ? if (WARN_ON(bdata->id >= num_uarts))
+ ? ? if (WARN_ON(bdata->id >= OMAP_MAX_HSUART_PORTS))

why? ?because of early_init, num_uarts is already the max number of UARTs available (based on hwmod probe.)

yes will correct this and use num_uarts

Quoted 52 lines
Quoted 24 lines

? ? ? ? ? ? ? return;

- ? ? list_for_each_entry(uart, &uart_list, node)
- ? ? ? ? ? ? if (bdata->id == uart->num)
- ? ? ? ? ? ? ? ? ? ? break;
-
- ? ? oh = uart->oh;
- ? ? uart->dma_enabled = 0;
- ? ? name = DRIVER_NAME;
+ ? ? oh = omap_uart_hwmod_lookup(bdata->id);
+ ? ? if (!oh)
+ ? ? ? ? ? ? return;

- ? ? omap_up.dma_enabled = uart->dma_enabled;
- ? ? omap_up.uartclk = OMAP24XX_BASE_BAUD * 16;
- ? ? omap_up.mapbase = oh->slaves[0]->addr->pa_start;
- ? ? omap_up.membase = omap_hwmod_get_mpu_rt_va(oh);
- ? ? omap_up.flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
+ ? ? pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+ ? ? if (!pdata) {
+ ? ? ? ? ? ? pr_err("Memory allocation for UART pdata failed\n");
+ ? ? ? ? ? ? return;
+ ? ? }

Quoted 3 lines

- ? ? pdata = &omap_up;
? ? ? pdata_size = sizeof(struct omap_uart_port_info);
+ ? ? omap_uart_idle_init(pdata, bdata->id);

Why was this moved here?

ISTR that the order of this call relative to the hwmod/omap_device enable/disable calls below was important, especially in the DEBUG_LL case.

Quoted 9 lines

- ? ? if (WARN_ON(!oh))
- ? ? ? ? ? ? return;
+ ? ? pdata->uartclk = OMAP24XX_BASE_BAUD * 16;
+ ? ? pdata->flags = UPF_BOOT_AUTOCONF;
+
+ ? ? /* Enable the MDR1 errata for OMAP3 */
+ ? ? if (cpu_is_omap34xx() && !cpu_is_ti816x())
+ ? ? ? ? ? ? pdata->errata |= UART_ERRATA_i202_MDR1_ACCESS;

Quoted 6 lines

- ? ? pdev = omap_device_build(name, uart->num, oh, pdata, pdata_size,
- ? ? ? ? ? ? ? ? ? ? ? ? ? ?omap_uart_latency,
- ? ? ? ? ? ? ? ? ? ? ? ? ? ?ARRAY_SIZE(omap_uart_latency), false);
+ ? ? pdev = omap_device_build(name, bdata->id, oh, pdata,
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? pdata_size, omap_uart_latency,
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ARRAY_SIZE(omap_uart_latency), false);

Note the unecesary whitespace changes in this change.

Quoted 8 lines
Quoted 4 lines

? ? ? WARN(IS_ERR(pdev), "Could not build omap_device for %s: %s.\n", ? ? ? ? ? ?name, oh->name);

- ? ? omap_device_disable_idle_on_suspend(pdev);

This should also be a separate patch at the end of the series, and is not related to the changes described in the changelog.

okay.

Quoted 29 lines
Quoted 29 lines

? ? ? oh->mux = omap_hwmod_mux_init(bdata->pads, bdata->pads_cnt);

- ? ? uart->regshift = 2;
- ? ? uart->mapbase = oh->slaves[0]->addr->pa_start;
- ? ? uart->membase = omap_hwmod_get_mpu_rt_va(oh);
- ? ? uart->pdev = pdev;

arch/arm/mach-omap2/serial.c +0 -3
-
- ? ? oh->dev_attr = uart;
-

? ? ? console_lock(); /* in case the earlycon is on the UART */

? ? ? /*

arch/arm/mach-omap2/serial.c +0 -0
@@ -546,23 +519,18 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)

? ? ? ?* on init. ?Now that omap_device is ready, ensure full idle ? ? ? ?* before doing omap_device_enable().
? ? ? ?*/
- ? ? omap_hwmod_idle(uart->oh);
+ ? ? omap_hwmod_idle(oh);

- ? ? omap_device_enable(uart->pdev);
- ? ? omap_uart_idle_init(uart);
- ? ? omap_hwmod_enable_wakeup(uart->oh);
- ? ? omap_device_idle(uart->pdev);
+ ? ? omap_device_enable(pdev);
+ ? ? omap_hwmod_enable_wakeup(oh);

- ? ? omap_uart_block_sleep(uart);
? ? ? console_unlock();

Quoted 7 lines
Quoted 4 lines

- ? ? if ((cpu_is_omap34xx() && uart->padconf) ||
- ? ? ? ? (uart->wk_en && uart->wk_mask))
+ ? ? if ((cpu_is_omap34xx() && bdata->pads) ||
+ ? ? ? ? ? ? (pdata->wk_en && pdata->wk_mask))

This change seems to belong as part of the mux patch.

okay moving to mux change patch.

Quoted 70 lines
Quoted 53 lines

? ? ? ? ? ? ? device_init_wakeup(&pdev->dev, true);

- ? ? /* Enable the MDR1 errata for OMAP3 */
- ? ? if (cpu_is_omap34xx() && !cpu_is_ti816x())
- ? ? ? ? ? ? uart->errata |= UART_ERRATA_i202_MDR1_ACCESS;
+ ? ? kfree(pdata);
?}

?/**

arch/arm/mach-omap2/serial.c +0 -0
@@ -574,11 +542,11 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)

? */
?void __init omap_serial_init(void)
?{
- ? ? struct omap_uart_state *uart;
? ? ? struct omap_board_data bdata;
+ ? ? u8 i;

- ? ? list_for_each_entry(uart, &uart_list, node) {
- ? ? ? ? ? ? bdata.id = uart->num;
+ ? ? for (i = 0; i < num_uarts; i++) {
+ ? ? ? ? ? ? bdata.id = i;
? ? ? ? ? ? ? bdata.flags = 0;
? ? ? ? ? ? ? bdata.pads = NULL;
? ? ? ? ? ? ? bdata.pads_cnt = 0;

arch/arm/plat-omap/include/plat/omap-serial.h +0 -0
index 307cd6f..0f061b4 100644
@@ -59,9 +59,9 @@
 ?struct omap_uart_port_info {

? ? ? bool ? ? ? ? ? ? ? ? ? ?dma_enabled; ? ?/* To specify DMA Mode */ ? ? ? unsigned int ? ? ? ? ? ?uartclk; ? ? ? ?/* UART clock rate */
- ? ? void __iomem ? ? ? ? ? ?*membase; ? ? ? /* ioremap cookie or NULL */
- ? ? resource_size_t ? ? ? ? mapbase; ? ? ? ?/* resource base */ ? ? ? upf_t ? ? ? ? ? ? ? ? ? flags; ? ? ? ? ?/* UPF_* flags */ +
+ ? ? u32 ? ? ? ? ? ? ? ? ? ? errata;
?};

?struct uart_omap_dma {

drivers/tty/serial/omap-serial.c +3 -2
index 5e713d3..6c2ea54 100644
@@ -1275,10 +1275,16 @@ static int serial_omap_probe(struct platform_device *pdev)
 ? ? ? up->port.ops = &serial_omap_pops;
 ? ? ? up->port.line = pdev->id;
 
- ? ? up->port.membase = omap_up_info->membase;
- ? ? up->port.mapbase = omap_up_info->mapbase;
+ ? ? up->port.mapbase = mem->start;
+ ? ? up->port.membase = ioremap(mem->start, resource_size(mem));
+

drivers/tty/serial/omap-serial.c static int serial_omap_probe(struct platform_device *pdev) · line 1289

Quoted 10 lines
drivers/tty/serial/omap-serial.c +6 -1
+ ? ? if (!up->port.membase) {
+ ? ? ? ? ? ? dev_err(&pdev->dev, "can't ioremap UART\n");
+ ? ? ? ? ? ? ret = -ENOMEM;
+ ? ? ? ? ? ? goto err;
+ ? ? }
+
 ? ? ? up->port.flags = omap_up_info->flags;
- ? ? up->port.irqflags = omap_up_info->irqflags;
 ? ? ? up->port.uartclk = omap_up_info->uartclk;
 ? ? ? up->uart_dma.uart_base = mem->start;

Kevin
--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in the body of a message to majordomo at vger.kernel.org
More majordomo info at ?http://vger.kernel.org/majordomo-info.html

#20 lore raw

PATCH v6 7/16 OMAP2+: UART: Add default mux for all uarts.

In reply to Govindraj.R

Prior to this change rx-pad wakeup was done by writing to rx-pad offset value populated in serial.c idle_init. Now with mux framework support we can use mux_utilities along with hmwod framework to handle io-pad configuration and enable rx-pad wake-up mechanism.

Add default mux data for all uart's if mux info is not passed from board file to avoid breaking any board support.
With the default pads we have populated in serial.c wakeup capability for rx pads are enabled, this can be used to enable uart_rx io-pad wakeup from hwmod framework. The pad values in 3430sdp/4430sdp/omap4panda board file are same as the default pad values populated in serial.c. Remove pad values from 3430sdp/4430sdp/omap4panda board file and use the default pads from serial.c file.

---
 arch/arm/mach-omap2/board-3430sdp.c    |  100 +----------------
 arch/arm/mach-omap2/board-4430sdp.c    |   68 +-----------
 arch/arm/mach-omap2/board-omap4panda.c |   68 +-----------
 arch/arm/mach-omap2/serial.c           |  192 +++++++++++++++++++++-----------
 4 files changed, 131 insertions(+), 297 deletions(-)
arch/arm/mach-omap2/board-3430sdp.c +1 -99
index bd600cf..b12b38f 100644
@@ -482,106 +482,8 @@ static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
 static struct omap_board_mux board_mux[] __initdata = {
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
 };
-
-static struct omap_device_pad serial1_pads[] __initdata = {
-	/*
-	 * Note that off output enable is an active low
-	 * signal. So setting this means pin is a
-	 * input enabled in off mode
-	 */
-	OMAP_MUX_STATIC("uart1_cts.uart1_cts",
-			 OMAP_PIN_INPUT |
-			 OMAP_PIN_OFF_INPUT_PULLDOWN |
-			 OMAP_OFFOUT_EN |
-			 OMAP_MUX_MODE0),
-	OMAP_MUX_STATIC("uart1_rts.uart1_rts",
-			 OMAP_PIN_OUTPUT |
-			 OMAP_OFF_EN |
-			 OMAP_MUX_MODE0),
-	OMAP_MUX_STATIC("uart1_rx.uart1_rx",
-			 OMAP_PIN_INPUT |
-			 OMAP_PIN_OFF_INPUT_PULLDOWN |
-			 OMAP_OFFOUT_EN |
-			 OMAP_MUX_MODE0),
-	OMAP_MUX_STATIC("uart1_tx.uart1_tx",
-			 OMAP_PIN_OUTPUT |
-			 OMAP_OFF_EN |
-			 OMAP_MUX_MODE0),
-};
-
-static struct omap_device_pad serial2_pads[] __initdata = {
-	OMAP_MUX_STATIC("uart2_cts.uart2_cts",
-			 OMAP_PIN_INPUT_PULLUP |
-			 OMAP_PIN_OFF_INPUT_PULLDOWN |
-			 OMAP_OFFOUT_EN |
-			 OMAP_MUX_MODE0),
-	OMAP_MUX_STATIC("uart2_rts.uart2_rts",
-			 OMAP_PIN_OUTPUT |
-			 OMAP_OFF_EN |
-			 OMAP_MUX_MODE0),
-	OMAP_MUX_STATIC("uart2_rx.uart2_rx",
-			 OMAP_PIN_INPUT |
-			 OMAP_PIN_OFF_INPUT_PULLDOWN |
-			 OMAP_OFFOUT_EN |
-			 OMAP_MUX_MODE0),
-	OMAP_MUX_STATIC("uart2_tx.uart2_tx",
-			 OMAP_PIN_OUTPUT |
-			 OMAP_OFF_EN |
-			 OMAP_MUX_MODE0),
-};
-
-static struct omap_device_pad serial3_pads[] __initdata = {
-	OMAP_MUX_STATIC("uart3_cts_rctx.uart3_cts_rctx",
-			 OMAP_PIN_INPUT_PULLDOWN |
-			 OMAP_PIN_OFF_INPUT_PULLDOWN |
-			 OMAP_OFFOUT_EN |
-			 OMAP_MUX_MODE0),
-	OMAP_MUX_STATIC("uart3_rts_sd.uart3_rts_sd",
-			 OMAP_PIN_OUTPUT |
-			 OMAP_OFF_EN |
-			 OMAP_MUX_MODE0),
-	OMAP_MUX_STATIC("uart3_rx_irrx.uart3_rx_irrx",
-			 OMAP_PIN_INPUT |
-			 OMAP_PIN_OFF_INPUT_PULLDOWN |
-			 OMAP_OFFOUT_EN |
-			 OMAP_MUX_MODE0),
-	OMAP_MUX_STATIC("uart3_tx_irtx.uart3_tx_irtx",
-			 OMAP_PIN_OUTPUT |
-			 OMAP_OFF_EN |
-			 OMAP_MUX_MODE0),
-};
-
-static struct omap_board_data serial1_data __initdata = {
-	.id		= 0,
-	.pads		= serial1_pads,
-	.pads_cnt	= ARRAY_SIZE(serial1_pads),
-};
-
-static struct omap_board_data serial2_data __initdata = {
-	.id		= 1,
-	.pads		= serial2_pads,
-	.pads_cnt	= ARRAY_SIZE(serial2_pads),
-};
-
-static struct omap_board_data serial3_data __initdata = {
-	.id		= 2,
-	.pads		= serial3_pads,
-	.pads_cnt	= ARRAY_SIZE(serial3_pads),
-};
-
-static inline void board_serial_init(void)
-{
-	omap_serial_init_port(&serial1_data);
-	omap_serial_init_port(&serial2_data);
-	omap_serial_init_port(&serial3_data);
-}
 #else
 #define board_mux	NULL
-
-static inline void board_serial_init(void)
-{
-	omap_serial_init();
-}
 #endif
 
 /*
@@ -718,7 +620,7 @@ static void __init omap_3430sdp_init(void)
 	else
 		gpio_pendown = SDP3430_TS_GPIO_IRQ_SDPV1;
 	omap_ads7846_init(1, gpio_pendown, 310, NULL);
-	board_serial_init();
+	omap_serial_init();
 	usb_musb_init(NULL);
 	board_smc91x_init();
 	board_flash_init(sdp_flash_partitions, chip_sel_3430, 0);
arch/arm/mach-omap2/board-4430sdp.c +1 -67

82 lines not on this page · raw message

arch/arm/mach-omap2/board-omap4panda.c +1 -67

82 lines not on this page · raw message

arch/arm/mach-omap2/serial.c +128 -64

228 lines not on this page · raw message

Signature · 1 line
1.7.4.1
#21 lore raw

PATCH v6 7/16 OMAP2+: UART: Add default mux for all uarts.

Quoted 4 lines · Govindraj.R

Prior to this change rx-pad wakeup was done by writing to rx-pad offset value populated in serial.c idle_init. Now with mux framework support we can use mux_utilities along with hmwod framework to handle io-pad configuration and enable rx-pad wake-up mechanism.

This patch (along with a few others) have compile errors when CONFIG_PM is not set.

Kevin

#22 lore raw

PATCH v6 7/16 OMAP2+: UART: Add default mux for all uarts.

Thanks for the review.

Quoted 10 lines · Kevin Hilman
Quoted 4 lines · Govindraj.R

Prior to this change rx-pad wakeup was done by writing to rx-pad offset value populated in serial.c idle_init. Now with mux framework support we can use mux_utilities along with hmwod framework to handle io-pad configuration and enable rx-pad wake-up mechanism.

This patch (along with a few others) have compile errors when CONFIG_PM is not set.

Will check and fix this.

Please let me know on further comments on the series.

Will re-post fixing the same.

--
Thanks,
Govindraj.R

Quoted 6 lines

Kevin
--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in the body of a message to majordomo at vger.kernel.org
More majordomo info at ?http://vger.kernel.org/majordomo-info.html

#23 lore raw

PATCH v6 8/16 OMAP2+: UART: Store certain reg values to port structure

In reply to Govindraj.R

In preparation to runtime conversion add missing uart regs to port structure which can be used in context restore. Also ensuring all uart reg info's are part of port structure.

---
 arch/arm/plat-omap/include/plat/omap-serial.h |    3 ++
 drivers/tty/serial/omap-serial.c              |   33 ++++++++++++++----------
 2 files changed, 22 insertions(+), 14 deletions(-)
arch/arm/plat-omap/include/plat/omap-serial.h +3 -0
index 0f061b4..74822b3 100644
@@ -99,6 +99,9 @@ struct uart_omap_port {
 	unsigned char		mcr;
 	unsigned char		fcr;
 	unsigned char		efr;
+	unsigned char		dll;
+	unsigned char		dlh;
+	unsigned char		mdr1;
 
 	int			use_dma;
 	/*
drivers/tty/serial/omap-serial.c +19 -14
index 6c2ea54..9a0eac2 100644
@@ -433,8 +433,9 @@ static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl)
 	if (mctrl & TIOCM_LOOP)
 		mcr |= UART_MCR_LOOP;
 
-	mcr |= up->mcr;
-	serial_out(up, UART_MCR, mcr);
+	up->mcr = serial_in(up, UART_MCR);
+	up->mcr |= mcr;
+	serial_out(up, UART_MCR, up->mcr);
 }
 
 static void serial_omap_break_ctl(struct uart_port *port, int break_state)
@@ -573,8 +574,6 @@ static inline void
 serial_omap_configure_xonxoff
 		(struct uart_omap_port *up, struct ktermios *termios)
 {
-	unsigned char efr = 0;
-
 	up->lcr = serial_in(up, UART_LCR);
 	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
 	up->efr = serial_in(up, UART_EFR);
@@ -584,8 +583,7 @@ serial_omap_configure_xonxoff
 	serial_out(up, UART_XOFF1, termios->c_cc[VSTOP]);
 
 	/* clear SW control mode bits */
-	efr = up->efr;
-	efr &= OMAP_UART_SW_CLR;
+	up->efr &= OMAP_UART_SW_CLR;
 
 	/*
 	 * IXON Flag:
@@ -593,7 +591,7 @@ serial_omap_configure_xonxoff
 	 * Transmit XON1, XOFF1
 	 */
 	if (termios->c_iflag & IXON)
-		efr |= OMAP_UART_SW_TX;
+		up->efr |= OMAP_UART_SW_TX;
 
 	/*
 	 * IXOFF Flag:
@@ -601,7 +599,7 @@ serial_omap_configure_xonxoff
 	 * Receiver compares XON1, XOFF1.
 	 */
 	if (termios->c_iflag & IXOFF)
-		efr |= OMAP_UART_SW_RX;
+		up->efr |= OMAP_UART_SW_RX;
 
 	serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
 	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
@@ -624,7 +622,7 @@ serial_omap_configure_xonxoff
 	 * load the new software flow control mode IXON or IXOFF
 	 * and restore the UARTi.EFR_REG[4] ENHANCED_EN value.
 	 */
-	serial_out(up, UART_EFR, efr | UART_EFR_SCD);
+	serial_out(up, UART_EFR, up->efr | UART_EFR_SCD);
 	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
 
 	serial_out(up, UART_MCR, up->mcr & ~UART_MCR_TCRTLR);
@@ -671,6 +669,10 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
 	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/13);
 	quot = serial_omap_get_divisor(port, baud);
 
+	up->dll = quot & 0xff;
+	up->dlh = quot >> 8;
+	up->mdr1 = UART_OMAP_MDR1_DISABLE;
+
 	up->fcr = UART_FCR_R_TRIG_01 | UART_FCR_T_TRIG_01 |
 			UART_FCR_ENABLE_FIFO;
 	if (up->use_dma)
@@ -723,6 +725,7 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
 		up->ier |= UART_IER_MSI;
 	serial_out(up, UART_IER, up->ier);
 	serial_out(up, UART_LCR, cval);		/* reset DLAB */
+	up->lcr = cval;
 
 	/* FIFOs and DMA Settings */
 
@@ -759,7 +762,7 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
 
 	/* Protocol, Baud Rate, and Interrupt Settings */
 
-	serial_out(up, UART_OMAP_MDR1, UART_OMAP_MDR1_DISABLE);
+	serial_out(up, UART_OMAP_MDR1, up->mdr1);
 	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
 
 	up->efr = serial_in(up, UART_EFR);
@@ -769,8 +772,8 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
 	serial_out(up, UART_IER, 0);
 	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
 
-	serial_out(up, UART_DLL, quot & 0xff);          /* LS of divisor */
-	serial_out(up, UART_DLM, quot >> 8);            /* MS of divisor */
+	serial_out(up, UART_DLL, up->dll);	/* LS of divisor */
+	serial_out(up, UART_DLM, up->dlh);	/* MS of divisor */
 
 	serial_out(up, UART_LCR, 0);
 	serial_out(up, UART_IER, up->ier);
@@ -780,9 +783,11 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
 	serial_out(up, UART_LCR, cval);
 
 	if (baud > 230400 && baud != 3000000)
-		serial_out(up, UART_OMAP_MDR1, UART_OMAP_MDR1_13X_MODE);
+		up->mdr1 = UART_OMAP_MDR1_13X_MODE;
 	else
-		serial_out(up, UART_OMAP_MDR1, UART_OMAP_MDR1_16X_MODE);
+		up->mdr1 = UART_OMAP_MDR1_16X_MODE;
+
+	serial_out(up, UART_OMAP_MDR1, up->mdr1);
 
 	/* Hardware Flow Control Configuration */
 
Signature · 1 line
1.7.4.1
#24 lore raw

PATCH v6 8/16 OMAP2+: UART: Store certain reg values to port structure

Quoted 5 lines · Govindraj.R

In preparation to runtime conversion add missing uart regs to port structure which can be used in context restore. Also ensuring all uart reg info's are part of port structure.

IMO, this should come later in the series to avoid adding bunch of code that gets moved in a subsequent patch.

First, convert to runtime PM (current patch 9/16) Then, add a patch to move context save/restore into driver. Then, add this patch.

Kevin

#25 lore raw

PATCH v6 8/16 OMAP2+: UART: Store certain reg values to port structure

Quoted 6 lines · Kevin Hilman
Quoted 4 lines · Govindraj.R

In preparation to runtime conversion add missing uart regs to port structure which can be used in context restore. Also ensuring all uart reg info's are part of port structure.

Quoted 8 lines
Quoted 1 line

IMO, this should come later in the series to avoid adding bunch of code that gets moved in a subsequent patch.

First, convert to runtime PM (current patch 9/16) Then, add a patch to move context save/restore into driver. Then, add this patch.

Okay fine.

--
Thanks,
Govindraj.R

#26 lore raw

PATCH v6 9/16 OMAP2+: UART: Add runtime pm support for omap-serial driver

In reply to Govindraj.R

Adapts omap-serial driver to use pm_runtime API's.

Use runtime runtime API's to handle uart clocks and obtain device_usage statics. Set runtime API's usage to irq_safe so that we can use get_sync from irq context. Auto-suspend for port specific activities and put for reg access. Use device_may_wakeup to check whether uart has wakeup capabilities and then enable uart runtime usage for the uart.

Removing save_context/restore_context functions from serial.c Adding context restore to .runtime_suspend and using reg values from port structure to restore the uart port context based on context_loss_count. Maintain internal state machine using wakeups_enabled field for avoiding repeated enable/disable of uart port wakeup mechanism.

Remove omap_uart_disable_wakeup and modify omap_uart_enable_wakeup to accept pdev and bool value to enable/disable the uart wakeup mechanism after uart clock's are cut. omap_hwmod_enable_wakeup is used to set pad wakeup for the uarts. PM_WKEN reg values are left to default. Removed omap_uart_enable/disable_clocks in serial.c now clock handling done with runtime API's.

By default uart autosuspend delay is set to -1 to avoid character loss if uart's are autoidled and woken up on rx pin.

After boot up UART's can be autoidled by setting autosuspendi delay from sysfs.

echo 3000 > /sys/devices/platform/omap/omap_uart.X/power/autosuspend_delay_ms X=0,1,2,3 for UART1/2/3/4. Number of uarts available may vary across omap_soc.

---
 arch/arm/mach-omap2/serial.c                  |  206 ++----------------------
 arch/arm/plat-omap/include/plat/omap-serial.h |    5 +
 drivers/tty/serial/omap-serial.c              |  169 +++++++++++++++++++--
 3 files changed, 179 insertions(+), 201 deletions(-)
arch/arm/mach-omap2/serial.c +18 -188
index ca6807c..6725caf 100644
@@ -33,6 +33,7 @@
 #include <plat/dma.h>
 #include <plat/omap_hwmod.h>
 #include <plat/omap_device.h>
+#include <plat/omap-pm.h>
 
 #include "prm2xxx_3xxx.h"
 #include "pm.h"
@@ -41,8 +42,6 @@
 #include "control.h"
 #include "mux.h"
 
-#define UART_OMAP_WER		0x17	/* Wake-up enable register */
-
 #define UART_ERRATA_i202_MDR1_ACCESS	(0x1 << 1)
 
 /*
@@ -57,24 +56,7 @@
 
 struct omap_uart_state {
 	int num;
-	int can_sleep;
 	u32 dma_enabled;
-
-	int clocked;
-
-	int regshift;
-#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM)
-	int context_valid;
-
-	/* Registers to be saved/restored for OFF-mode */
-	u16 dll;
-	u16 dlh;
-	u16 ier;
-	u16 sysc;
-	u16 scr;
-	u16 wer;
-	u16 mcr;
-#endif
 };
 
 static u8 num_uarts;
@@ -101,34 +83,6 @@ static struct omap_device_pm_latency omap_uart_latency[] = {
 	},
 };
 
-static inline unsigned int __serial_read_reg(struct uart_port *up,
-					     int offset)
-{
-	offset <<= up->regshift;
-	return (unsigned int)__raw_readb(up->membase + offset);
-}
-
-static inline unsigned int serial_read_reg(struct omap_uart_state *uart,
-					   int offset)
-{
-	offset <<= uart->regshift;
-	return (unsigned int)__raw_readb(uart->membase + offset);
-}
-
-static inline void __serial_write_reg(struct uart_port *up, int offset,
-		int value)
-{
-	offset <<= up->regshift;
-	__raw_writeb(value, up->membase + offset);
-}
-
-static inline void serial_write_reg(struct omap_uart_state *uart, int offset,
-				    int value)
-{
-	offset <<= uart->regshift;
-	__raw_writeb(value, uart->membase + offset);
-}
-
 struct omap_hwmod *omap_uart_hwmod_lookup(int num)
 {
 	struct omap_hwmod *oh;
@@ -177,134 +131,8 @@ static void omap_uart_mdr1_errataset(struct omap_uart_state *uart, u8 mdr1_val,
 		udelay(1);
 	}
 }
-
-static void omap_uart_save_context(struct omap_uart_state *uart)
-{
-	u16 lcr = 0;
-
-	if (!enable_off_mode)
-		return;
-
-	lcr = serial_read_reg(uart, UART_LCR);
-	serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_B);
-	uart->dll = serial_read_reg(uart, UART_DLL);
-	uart->dlh = serial_read_reg(uart, UART_DLM);
-	serial_write_reg(uart, UART_LCR, lcr);
-	uart->ier = serial_read_reg(uart, UART_IER);
-	uart->sysc = serial_read_reg(uart, UART_OMAP_SYSC);
-	uart->scr = serial_read_reg(uart, UART_OMAP_SCR);
-	uart->wer = serial_read_reg(uart, UART_OMAP_WER);
-	serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_A);
-	uart->mcr = serial_read_reg(uart, UART_MCR);
-	serial_write_reg(uart, UART_LCR, lcr);
-
-	uart->context_valid = 1;
-}
-
-static void omap_uart_restore_context(struct omap_uart_state *uart)
-{
-	u16 efr = 0;
-
-	if (!enable_off_mode)
-		return;
-
-	if (!uart->context_valid)
-		return;
-
-	uart->context_valid = 0;
-
-	if (uart->errata & UART_ERRATA_i202_MDR1_ACCESS)
-		omap_uart_mdr1_errataset(uart, UART_OMAP_MDR1_DISABLE, 0xA0);
-	else
-		serial_write_reg(uart, UART_OMAP_MDR1, UART_OMAP_MDR1_DISABLE);
-
-	serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_B);
-	efr = serial_read_reg(uart, UART_EFR);
-	serial_write_reg(uart, UART_EFR, UART_EFR_ECB);
-	serial_write_reg(uart, UART_LCR, 0x0); /* Operational mode */
-	serial_write_reg(uart, UART_IER, 0x0);
-	serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_B);
-	serial_write_reg(uart, UART_DLL, uart->dll);
-	serial_write_reg(uart, UART_DLM, uart->dlh);
-	serial_write_reg(uart, UART_LCR, 0x0); /* Operational mode */
-	serial_write_reg(uart, UART_IER, uart->ier);
-	serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_A);
-	serial_write_reg(uart, UART_MCR, uart->mcr);
-	serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_B);
-	serial_write_reg(uart, UART_EFR, efr);
-	serial_write_reg(uart, UART_LCR, UART_LCR_WLEN8);
-	serial_write_reg(uart, UART_OMAP_SCR, uart->scr);
-	serial_write_reg(uart, UART_OMAP_WER, uart->wer);
-	serial_write_reg(uart, UART_OMAP_SYSC, uart->sysc);
-
-	if (uart->errata & UART_ERRATA_i202_MDR1_ACCESS)
-		omap_uart_mdr1_errataset(uart, UART_OMAP_MDR1_16X_MODE, 0xA1);
-	else
-		/* UART 16x mode */
-		serial_write_reg(uart, UART_OMAP_MDR1,
-				UART_OMAP_MDR1_16X_MODE);
-}
-#else
-static inline void omap_uart_save_context(struct omap_uart_state *uart) {}
-static inline void omap_uart_restore_context(struct omap_uart_state *uart) {}
 #endif /* CONFIG_PM && CONFIG_ARCH_OMAP3 */
 
-static inline void omap_uart_enable_clocks(struct omap_uart_state *uart)
-{
-	if (uart->clocked)
-		return;
-
-	omap_device_enable(uart->pdev);
-	uart->clocked = 1;
-	omap_uart_restore_context(uart);
-}
-
-#ifdef CONFIG_PM
-
-static inline void omap_uart_disable_clocks(struct omap_uart_state *uart)
-{
-	if (!uart->clocked)
-		return;
-
-	omap_uart_save_context(uart);
-	uart->clocked = 0;
-	omap_device_idle(uart->pdev);
-}
-
-static void omap_uart_enable_wakeup(struct omap_uart_state *uart)
-{
-	/* Set wake-enable bit */
-	if (uart->wk_en && uart->wk_mask) {
-		u32 v = __raw_readl(uart->wk_en);
-		v |= uart->wk_mask;
-		__raw_writel(v, uart->wk_en);
-	}
-
-	/* Ensure IOPAD wake-enables are set */
-	if (cpu_is_omap34xx() && uart->padconf) {
-		u16 v = omap_ctrl_readw(uart->padconf);
-		v |= OMAP3_PADCONF_WAKEUPENABLE0;
-		omap_ctrl_writew(v, uart->padconf);
-	}
-}
-
-static void omap_uart_disable_wakeup(struct omap_uart_state *uart)
-{
-	/* Clear wake-enable bit */
-	if (uart->wk_en && uart->wk_mask) {
-		u32 v = __raw_readl(uart->wk_en);
-		v &= ~uart->wk_mask;
-		__raw_writel(v, uart->wk_en);
-	}
-
-	/* Ensure IOPAD wake-enables are cleared */
-	if (cpu_is_omap34xx() && uart->padconf) {
-		u16 v = omap_ctrl_readw(uart->padconf);
-		v &= ~OMAP3_PADCONF_WAKEUPENABLE0;
-		omap_ctrl_writew(v, uart->padconf);
-	}
-}
-
 static void omap_uart_smart_idle_enable(struct omap_uart_state *uart,
 					       int enable)
 {
@@ -326,14 +154,6 @@ static void omap_uart_smart_idle_enable(struct omap_uart_state *uart,
 	omap_hwmod_set_slave_idlemode(uart->oh, idlemode);
 }
 
-static void omap_uart_block_sleep(struct omap_uart_state *uart)
-{
-	omap_uart_enable_clocks(uart);
-
-	omap_uart_smart_idle_enable(uart, 0);
-	uart->can_sleep = 0;
-}
-
 int omap_uart_can_sleep(void)
 {
 	struct omap_uart_state *uart;
@@ -483,12 +303,22 @@ static void omap_serial_fill_default_pads(struct omap_board_data *bdata)
 	}
 }
 
-#else
-static void omap_uart_block_sleep(struct omap_uart_state *uart)
+static void omap_uart_enable_wakeup(struct platform_device *pdev, bool enable)
 {
-	/* Needed to enable UART clocks when built without CONFIG_PM */
-	omap_uart_enable_clocks(uart);
+	struct omap_device *od = to_omap_device(pdev);
+
+	if (!od)
+		return;
+
+	if (enable)
+		omap_hwmod_enable_wakeup(od->hwmods[0]);
+	else
+		omap_hwmod_disable_wakeup(od->hwmods[0]);
 }
+
+#else
+static void omap_uart_enable_wakeup(struct platform_device *pdev, bool enable)
+{}
 #endif /* CONFIG_PM */
 
 static int __init omap_serial_early_init(void)
@@ -559,6 +389,8 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
 
 	pdata->uartclk = OMAP24XX_BASE_BAUD * 16;
 	pdata->flags = UPF_BOOT_AUTOCONF;
+	pdata->enable_wakeup = omap_uart_enable_wakeup;
+	pdata->get_context_loss_count = omap_pm_get_dev_context_loss_count;
 
 	/* Enable the MDR1 errata for OMAP3 */
 	if (cpu_is_omap34xx() && !cpu_is_ti816x())
@@ -582,12 +414,10 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
 	omap_hwmod_idle(oh);
 
 	omap_device_enable(pdev);
-	omap_hwmod_enable_wakeup(oh);
 
 	console_unlock();
 
-	if (((cpu_is_omap34xx() || cpu_is_omap44xx()) && bdata->pads) ||
-		(pdata->wk_en && pdata->wk_mask))
+	if ((cpu_is_omap34xx() || cpu_is_omap44xx()) && bdata->pads)
 		device_init_wakeup(&pdev->dev, true);
 
 	kfree(pdata);
arch/arm/plat-omap/include/plat/omap-serial.h +5 -0
index 74822b3..8ef81ce 100644
@@ -62,6 +62,9 @@ struct omap_uart_port_info {
 	upf_t			flags;		/* UPF_* flags */
 
 	u32			errata;
+
+	void (*enable_wakeup)(struct platform_device *, bool);
+	u32 (*get_context_loss_count)(struct device *);
 };
 
 struct uart_omap_dma {
@@ -113,6 +116,8 @@ struct uart_omap_port {
 	unsigned char		msr_saved_flags;
 	char			name[20];
 	unsigned long		port_activity;
+	u32			context_loss_cnt;
+	u8			wakeups_enabled;
 };
 
 #endif /* __OMAP_SERIAL_H__ */
drivers/tty/serial/omap-serial.c +156 -13

409 lines not on this page · raw message

Signature · 1 line
1.7.4.1
#27 lore raw

PATCH v6 9/16 OMAP2+: UART: Add runtime pm support for omap-serial driver

Quoted 1 line · Govindraj.R

Adapts omap-serial driver to use pm_runtime API's.

[...]

Quoted 14 lines
drivers/tty/serial/omap-serial.c +2 -3
@@ -1065,19 +1123,18 @@ static struct uart_driver serial_omap_reg = {
 	.cons		= OMAP_CONSOLE,
 };
 
-static int
-serial_omap_suspend(struct platform_device *pdev, pm_message_t state)
+static int serial_omap_suspend(struct device *dev)
 {
-	struct uart_omap_port *up = platform_get_drvdata(pdev);
+	struct uart_omap_port *up = dev_get_drvdata(dev);
 
 	if (up)
 		uart_suspend_port(&serial_omap_reg, &up->port);
 	return 0;

drivers/tty/serial/omap-serial.c static struct uart_driver serial_omap_reg = { · line 1140

Quoted 10 lines
drivers/tty/serial/omap-serial.c +2 -2
 }
 
-static int serial_omap_resume(struct platform_device *dev)
+static int serial_omap_resume(struct device *dev)
 {
-	struct uart_omap_port *up = platform_get_drvdata(dev);
+	struct uart_omap_port *up = dev_get_drvdata(dev);
 
 	if (up)
 		uart_resume_port(&serial_omap_reg, &up->port);

These functions need to be wrapped in #ifdef CONFIG_SUSPEND, otherwise, when building with !CONFIG_SUSPEND you'll get :

/work/kernel/omap/pm/drivers/tty/serial/omap-serial.c:1134:12: warning: 'serial_omap_suspend' defined but not used /work/kernel/omap/pm/drivers/tty/serial/omap-serial.c:1150:12: warning: 'serial_omap_resume' defined but not used

[...]

Quoted 35 lines
drivers/tty/serial/omap-serial.c +35 -0
+static int serial_omap_runtime_suspend(struct device *dev)
+{
+	struct uart_omap_port *up = dev_get_drvdata(dev);
+	struct omap_uart_port_info *pdata = dev->platform_data;
+
+	if (!up)
+		return -EINVAL;
+
+	if (!pdata->enable_wakeup || !pdata->get_context_loss_count)
+		return 0;
+
+	if (pdata->get_context_loss_count)
+		up->context_loss_cnt = pdata->get_context_loss_count(dev);
+
+	if (device_may_wakeup(dev)) {
+		if (!up->wakeups_enabled) {
+			pdata->enable_wakeup(up->pdev, true);
+			up->wakeups_enabled = true;
+		}
+	} else {
+		if (up->wakeups_enabled) {
+			pdata->enable_wakeup(up->pdev, false);
+			up->wakeups_enabled = false;
+		}
+	}
+
+	return 0;
+}
+
+static int serial_omap_runtime_resume(struct device *dev)
+{
+	struct uart_omap_port *up = dev_get_drvdata(dev);
+	struct omap_uart_port_info *pdata = dev->platform_data;
+
+	if (up) {

drivers/tty/serial/omap-serial.c static int serial_omap_remove(struct platform_device *dev) · line 1474

Quoted 10 lines
drivers/tty/serial/omap-serial.c +8 -0
+		if (pdata->get_context_loss_count) {
+			u32 loss_cnt = pdata->get_context_loss_count(dev);
+
+			if (up->context_loss_cnt != loss_cnt)
+				serial_omap_restore_context(up);
+		}
+	}
+
 	return 0;
 }

Similarily, thse need to be wrapped with #ifdef CONFIG_PM_RUNTIME, otherwise, when !CONFIG_PM_RUNTIME:

/work/kernel/omap/pm/drivers/tty/serial/omap-serial.c:1498:12: warning: 'serial_omap_runtime_suspend' defined but not used /work/kernel/omap/pm/drivers/tty/serial/omap-serial.c:1531:12: warning: 'serial_omap_runtime_resume' defined but not used

drivers/tty/serial/omap-serial.c static int serial_omap_remove(struct platform_device *dev) · line 1481

Quoted 6 lines
drivers/tty/serial/omap-serial.c +6 -0
+static const struct dev_pm_ops serial_omap_dev_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(serial_omap_suspend, serial_omap_resume)
+	SET_RUNTIME_PM_OPS(serial_omap_runtime_suspend,
+				serial_omap_runtime_resume, NULL)
+};
+

Note that you don't need #else parts to the above #ifdefs since the SET_*_OPS() macros used here take care of that.

Kevin

#28 lore raw

PATCH v6 9/16 OMAP2+: UART: Add runtime pm support for omap-serial driver

Quoted 92 lines · Kevin Hilman
Quoted 1 line · Govindraj.R

Adapts omap-serial driver to use pm_runtime API's.

[...]

Quoted 14 lines
(quoted diff) +2 -3
@@ -1065,19 +1123,18 @@ static struct uart_driver serial_omap_reg = {
 ? ? ? .cons ? ? ? ? ? = OMAP_CONSOLE,
 ?};
 
-static int
-serial_omap_suspend(struct platform_device *pdev, pm_message_t state)
+static int serial_omap_suspend(struct device *dev)
 ?{
- ? ? struct uart_omap_port *up = platform_get_drvdata(pdev);
+ ? ? struct uart_omap_port *up = dev_get_drvdata(dev);
 
 ? ? ? if (up)
 ? ? ? ? ? ? ? uart_suspend_port(&serial_omap_reg, &up->port);
 ? ? ? return 0;

Review static struct uart_driver serial_omap_reg = { · line 1140

Quoted 10 lines
(quoted diff) +2 -2
 ?}
 
-static int serial_omap_resume(struct platform_device *dev)
+static int serial_omap_resume(struct device *dev)
 ?{
- ? ? struct uart_omap_port *up = platform_get_drvdata(dev);
+ ? ? struct uart_omap_port *up = dev_get_drvdata(dev);
 
 ? ? ? if (up)
 ? ? ? ? ? ? ? uart_resume_port(&serial_omap_reg, &up->port);

These functions need to be wrapped in #ifdef CONFIG_SUSPEND, otherwise, when building with !CONFIG_SUSPEND you'll get :

/work/kernel/omap/pm/drivers/tty/serial/omap-serial.c:1134:12: warning: 'serial_omap_suspend' defined but not used /work/kernel/omap/pm/drivers/tty/serial/omap-serial.c:1150:12: warning: 'serial_omap_resume' defined but not used

[...]

Quoted 43 lines
(quoted diff) +43 -0
+static int serial_omap_runtime_suspend(struct device *dev)
+{
+ ? ? struct uart_omap_port *up = dev_get_drvdata(dev);
+ ? ? struct omap_uart_port_info *pdata = dev->platform_data;
+
+ ? ? if (!up)
+ ? ? ? ? ? ? return -EINVAL;
+
+ ? ? if (!pdata->enable_wakeup || !pdata->get_context_loss_count)
+ ? ? ? ? ? ? return 0;
+
+ ? ? if (pdata->get_context_loss_count)
+ ? ? ? ? ? ? up->context_loss_cnt = pdata->get_context_loss_count(dev);
+
+ ? ? if (device_may_wakeup(dev)) {
+ ? ? ? ? ? ? if (!up->wakeups_enabled) {
+ ? ? ? ? ? ? ? ? ? ? pdata->enable_wakeup(up->pdev, true);
+ ? ? ? ? ? ? ? ? ? ? up->wakeups_enabled = true;
+ ? ? ? ? ? ? }
+ ? ? } else {
+ ? ? ? ? ? ? if (up->wakeups_enabled) {
+ ? ? ? ? ? ? ? ? ? ? pdata->enable_wakeup(up->pdev, false);
+ ? ? ? ? ? ? ? ? ? ? up->wakeups_enabled = false;
+ ? ? ? ? ? ? }
+ ? ? }
+
+ ? ? return 0;
+}
+
+static int serial_omap_runtime_resume(struct device *dev)
+{
+ ? ? struct uart_omap_port *up = dev_get_drvdata(dev);
+ ? ? struct omap_uart_port_info *pdata = dev->platform_data;
+
+ ? ? if (up) {
+ ? ? ? ? ? ? if (pdata->get_context_loss_count) {
+ ? ? ? ? ? ? ? ? ? ? u32 loss_cnt = pdata->get_context_loss_count(dev);
+
+ ? ? ? ? ? ? ? ? ? ? if (up->context_loss_cnt != loss_cnt)
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? serial_omap_restore_context(up);
+ ? ? ? ? ? ? }
+ ? ? }
+
Quoted 2 lines

? ? ? return 0;
?}

Similarily, thse need to be wrapped with #ifdef CONFIG_PM_RUNTIME, otherwise, when !CONFIG_PM_RUNTIME:

/work/kernel/omap/pm/drivers/tty/serial/omap-serial.c:1498:12: warning: 'serial_omap_runtime_suspend' defined but not used /work/kernel/omap/pm/drivers/tty/serial/omap-serial.c:1531:12: warning: 'serial_omap_runtime_resume' defined but not used

Quoted 10 lines

drivers/tty/serial/omap-serial.c static int serial_omap_remove(struct platform_device *dev) · line 1481

Quoted 6 lines
drivers/tty/serial/omap-serial.c +6 -0
+static const struct dev_pm_ops serial_omap_dev_pm_ops = {
+ ? ? SET_SYSTEM_SLEEP_PM_OPS(serial_omap_suspend, serial_omap_resume)
+ ? ? SET_RUNTIME_PM_OPS(serial_omap_runtime_suspend,
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? serial_omap_runtime_resume, NULL)
+};
+

Note that you don't need #else parts to the above #ifdefs since the SET_*_OPS() macros used here take care of that.

Yes fine, Corrected

Thanks for catching this.

--
Govindraj.R

#29 lore raw

PATCH v6 9/16 OMAP2+: UART: Add runtime pm support for omap-serial driver

In reply to Govindraj.R
Quoted 8 lines · Govindraj.R

Adapts omap-serial driver to use pm_runtime API's.

Use runtime runtime API's to handle uart clocks and obtain device_usage statics. Set runtime API's usage to irq_safe so that we can use get_sync from irq context. Auto-suspend for port specific activities and put for reg access. Use device_may_wakeup to check whether uart has wakeup capabilities and then enable uart runtime usage for the uart.

OK. Current patch should do only this part. The rest should be separate patches with their own descriptive changelogs.

Quoted 5 lines

Removing save_context/restore_context functions from serial.c Adding context restore to .runtime_suspend and using reg values from port structure to restore the uart port context based on context_loss_count. Maintain internal state machine using wakeups_enabled field for avoiding repeated enable/disable of uart port wakeup mechanism.

This part should be a separate patch that follows.

Quoted 8 lines

Remove omap_uart_disable_wakeup and modify omap_uart_enable_wakeup to accept pdev and bool value to enable/disable the uart wakeup mechanism after uart clock's are cut.

omap_hwmod_enable_wakeup is used to set
pad wakeup for the uarts. PM_WKEN reg values are left to default. Removed omap_uart_enable/disable_clocks in serial.c now clock handling done with runtime API's.

As stated in previous reviews, this wakeup enable/disable needs more description as the functionality is changing compared to current code.

Current version modifies wakeup enable/disable at both power-domain level (PM_WKEN) and at the IO ring.

Updated version modifies wakeups at module-level (SYSCONFIG) and at IO ring using omap_hwmod_enable_wakeup()

IMO, the updated version makes more sense, but needs a description as to why that change in functionality will have equivalent results compared to the existing one.

Quoted 2 lines

By default uart autosuspend delay is set to -1 to avoid character loss if uart's are autoidled and woken up on rx pin.

OK, good.

Quoted 7 lines

After boot up UART's can be autoidled by setting autosuspendi delay from sysfs.

echo 3000 > /sys/devices/platform/omap/omap_uart.X/power/autosuspend_delay_ms X=0,1,2,3 for UART1/2/3/4. Number of uarts available may vary across omap_soc.

Kevin

#30 lore raw

PATCH v6 9/16 OMAP2+: UART: Add runtime pm support for omap-serial driver

Quoted 11 lines · Kevin Hilman
Quoted 8 lines · Govindraj.R

Adapts omap-serial driver to use pm_runtime API's.

Use runtime runtime API's to handle uart clocks and obtain device_usage statics. Set runtime API's usage to irq_safe so that we can use get_sync from irq context. Auto-suspend for port specific activities and put for reg access. Use device_may_wakeup to check whether uart has wakeup capabilities and then enable uart runtime usage for the uart.

Quoted 3 lines

OK. ?Current patch should do only this part. ?The rest should be separate patches with their own descriptive changelogs.

Yes, started splitting them.

Quoted 8 lines
Quoted 5 lines

Removing save_context/restore_context functions from serial.c Adding context restore to .runtime_suspend and using reg values from port structure to restore the uart port context based on context_loss_count. Maintain internal state machine using wakeups_enabled field for avoiding repeated enable/disable of uart port wakeup mechanism.

This part should be a separate patch that follows.

okay,

Quoted 15 lines
Quoted 8 lines

Remove omap_uart_disable_wakeup and modify omap_uart_enable_wakeup to accept pdev and bool value to enable/disable the uart wakeup mechanism after uart clock's are cut.

omap_hwmod_enable_wakeup is used to set
pad wakeup for the uarts. PM_WKEN reg values are left to default. Removed omap_uart_enable/disable_clocks in serial.c now clock handling done with runtime API's.

As stated in previous reviews, this wakeup enable/disable needs more description as the functionality is changing compared to current code.

Current version modifies wakeup enable/disable at both power-domain level (PM_WKEN) and at the IO ring.

Quoted 7 lines

Updated version modifies wakeups at module-level (SYSCONFIG) and at IO ring using omap_hwmod_enable_wakeup()

IMO, the updated version makes more sense, but needs a description as to why that change in functionality will have equivalent results compared to the existing one.

Okay,

Quoted 19 lines
Quoted 2 lines

By default uart autosuspend delay is set to -1 to avoid character loss if uart's are autoidled and woken up on rx pin.

OK, good.

Quoted 7 lines

After boot up UART's can be autoidled by setting autosuspendi delay from sysfs.

echo 3000 > /sys/devices/platform/omap/omap_uart.X/power/autosuspend_delay_ms X=0,1,2,3 for UART1/2/3/4. Number of uarts available may vary across omap_soc.

Kevin
--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in the body of a message to majordomo at vger.kernel.org
More majordomo info at ?http://vger.kernel.org/majordomo-info.html

#31 lore raw

PATCH v6 9/16 OMAP2+: UART: Add runtime pm support for omap-serial driver

In reply to Govindraj.R

"Govindraj.R" <[email protected]> writes:

[...]

Quoted 2 lines

Use device_may_wakeup to check whether uart has wakeup capabilities and then enable uart runtime usage for the uart.

Curious about what happens when device_may_wakeup() is not set during device init.

[...]

drivers/tty/serial/omap-serial.c static int serial_omap_probe(struct platform_device *pdev) · line 1372

Quoted 11 lines
drivers/tty/serial/omap-serial.c +7 -0
@@ -1305,6 +1363,16 @@ static int serial_omap_probe(struct platform_device *pdev)
 		up->uart_dma.rx_dma_channel = OMAP_UART_DMA_CH_FREE;
 	}
 
+	pm_runtime_use_autosuspend(&pdev->dev);
+	pm_runtime_set_autosuspend_delay(&pdev->dev,
+			OMAP_UART_AUTOSUSPEND_DELAY);
+
+	pm_runtime_irq_safe(&pdev->dev);
+	if (device_may_wakeup(&pdev->dev)) {
+		pm_runtime_enable(&pdev->dev);

So if device_may_wakeup() is false, runtime PM is not enabled, then...

drivers/tty/serial/omap-serial.c static int serial_omap_probe(struct platform_device *pdev) · line 1373

Quoted 1 line
drivers/tty/serial/omap-serial.c +1 -0
+		pm_runtime_get_sync(&pdev->dev);

...this get doesn't happen, and the first register access causes a crash.

So either this get isn't needed, because there is no device access in this path, or this path is broken and needs validation.

drivers/tty/serial/omap-serial.c static int serial_omap_probe(struct platform_device *pdev) · line 1383

Quoted 10 lines
drivers/tty/serial/omap-serial.c +3 -0
+	}
+
 	ui[pdev->id] = up;
 	serial_omap_add_console_port(up);
 
@@ -1312,6 +1380,7 @@ static int serial_omap_probe(struct platform_device *pdev)
 	if (ret != 0)
 		goto do_release_region;
 
+	pm_runtime_put(&pdev->dev);

...also, this put is not balanced with a corresponding get.

Kevin

#32 lore raw

PATCH v6 9/16 OMAP2+: UART: Add runtime pm support for omap-serial driver

Quoted 26 lines · Kevin Hilman

"Govindraj.R" <[email protected]> writes:

[...]

Quoted 2 lines

Use device_may_wakeup to check whether uart has wakeup capabilities and then enable uart runtime usage for the uart.

Curious about what happens when device_may_wakeup() is not set during device init.

[...]

Review static int serial_omap_probe(struct platform_device *pdev) · line 1372

Quoted 11 lines
(quoted diff) +7 -0
@@ -1305,6 +1363,16 @@ static int serial_omap_probe(struct platform_device *pdev)
 ? ? ? ? ? ? ? up->uart_dma.rx_dma_channel = OMAP_UART_DMA_CH_FREE;
 ? ? ? }
 
+ ? ? pm_runtime_use_autosuspend(&pdev->dev);
+ ? ? pm_runtime_set_autosuspend_delay(&pdev->dev,
+ ? ? ? ? ? ? ? ? ? ? OMAP_UART_AUTOSUSPEND_DELAY);
+
+ ? ? pm_runtime_irq_safe(&pdev->dev);
+ ? ? if (device_may_wakeup(&pdev->dev)) {
+ ? ? ? ? ? ? pm_runtime_enable(&pdev->dev);

So if device_may_wakeup() is false, runtime PM is not enabled, then...

Quoted 3 lines

Review static int serial_omap_probe(struct platform_device *pdev) · line 1373

Quoted 1 line
(quoted diff) +1 -0
+ ? ? ? ? ? ? pm_runtime_get_sync(&pdev->dev);

...this get doesn't happen, and the first register access causes a crash.

Actually no crash, clocks will left enabled from boot up (hwmod_no_reset/idle) that are idled and enabled back here.

Since hwmod_idle is binded here later ([PATCH v6 15/16]),

Quoted 9 lines

So either this get isn't needed, because there is no device access in this path, or this path is broken and needs validation.

Quoted 5 lines
(quoted diff) +2 -0
+ ? ? }
+
 ? ? ? ui[pdev->id] = up;
 ? ? ? serial_omap_add_console_port(up);
 
Quoted 7 lines

Review static int serial_omap_probe(struct platform_device *pdev) · line 1383

Quoted 5 lines
(quoted diff) +1 -0
@@ -1312,6 +1380,7 @@ static int serial_omap_probe(struct platform_device *pdev)
 ? ? ? if (ret != 0)
 ? ? ? ? ? ? ? goto do_release_region;
 
+ ? ? pm_runtime_put(&pdev->dev);

...also, this put is not balanced with a corresponding get.

this needs to happen only when runtime is enabled.

will correct this.

--
Thanks,
Govindraj.,R

#33 lore raw

PATCH v6 9/16 OMAP2+: UART: Add runtime pm support for omap-serial driver

Quoted 27 lines · Govindraj
Quoted 26 lines · Kevin Hilman

"Govindraj.R" <[email protected]> writes:

[...]

Quoted 2 lines

Use device_may_wakeup to check whether uart has wakeup capabilities and then enable uart runtime usage for the uart.

Curious about what happens when device_may_wakeup() is not set during device init.

[...]

Review static int serial_omap_probe(struct platform_device *pdev) · line 1372

Quoted 11 lines
(quoted diff) +7 -0
@@ -1305,6 +1363,16 @@ static int serial_omap_probe(struct platform_device *pdev)
 ? ? ? ? ? ? ? up->uart_dma.rx_dma_channel = OMAP_UART_DMA_CH_FREE;
 ? ? ? }
 
+ ? ? pm_runtime_use_autosuspend(&pdev->dev);
+ ? ? pm_runtime_set_autosuspend_delay(&pdev->dev,
+ ? ? ? ? ? ? ? ? ? ? OMAP_UART_AUTOSUSPEND_DELAY);
+
+ ? ? pm_runtime_irq_safe(&pdev->dev);
+ ? ? if (device_may_wakeup(&pdev->dev)) {
+ ? ? ? ? ? ? pm_runtime_enable(&pdev->dev);

So if device_may_wakeup() is false, runtime PM is not enabled, then...

Quoted 8 lines
Quoted 3 lines

Review static int serial_omap_probe(struct platform_device *pdev) · line 1373

Quoted 1 line
(quoted diff) +1 -0
+ ? ? ? ? ? ? pm_runtime_get_sync(&pdev->dev);

...this get doesn't happen, and the first register access causes a crash.

Actually no crash, clocks will left enabled from boot up (hwmod_no_reset/idle) that are idled and enabled back here.

Since hwmod_idle is binded here later ([PATCH v6 15/16]),

IMO, That's not a very maintainable solution.

What happens when when someone fixes serial.c to only set HWMOD_INIT_NO_IDLE on the console UART? or if we fix things so we don't need INIT_NO_IDLE anymore? Then this will crash.

Driver code should not make assumptions like this about what device init code is or isn't doing.

Kevin

#34 lore raw

PATCH v6 9/16 OMAP2+: UART: Add runtime pm support for omap-serial driver

Quoted 38 lines · Kevin Hilman
Quoted 27 lines · Govindraj
Quoted 26 lines · Kevin Hilman

"Govindraj.R" <[email protected]> writes:

[...]

Quoted 2 lines

Use device_may_wakeup to check whether uart has wakeup capabilities and then enable uart runtime usage for the uart.

Curious about what happens when device_may_wakeup() is not set during device init.

[...]

Review static int serial_omap_probe(struct platform_device *pdev) · line 1372

Quoted 11 lines
(quoted diff) +7 -0
@@ -1305,6 +1363,16 @@ static int serial_omap_probe(struct platform_device *pdev)
 ? ? ? ? ? ? ? up->uart_dma.rx_dma_channel = OMAP_UART_DMA_CH_FREE;
 ? ? ? }
 
+ ? ? pm_runtime_use_autosuspend(&pdev->dev);
+ ? ? pm_runtime_set_autosuspend_delay(&pdev->dev,
+ ? ? ? ? ? ? ? ? ? ? OMAP_UART_AUTOSUSPEND_DELAY);
+
+ ? ? pm_runtime_irq_safe(&pdev->dev);
+ ? ? if (device_may_wakeup(&pdev->dev)) {
+ ? ? ? ? ? ? pm_runtime_enable(&pdev->dev);

So if device_may_wakeup() is false, runtime PM is not enabled, then...

Quoted 8 lines
Quoted 3 lines

Review static int serial_omap_probe(struct platform_device *pdev) · line 1373

Quoted 1 line
(quoted diff) +1 -0
+ ? ? ? ? ? ? pm_runtime_get_sync(&pdev->dev);

...this get doesn't happen, and the first register access causes a crash.

Actually no crash, clocks will left enabled from boot up (hwmod_no_reset/idle) that are idled and enabled back here.

Since hwmod_idle is binded here later ([PATCH v6 15/16]),

Quoted 9 lines

IMO, That's not a very maintainable solution.

What happens when when someone fixes serial.c to only set HWMOD_INIT_NO_IDLE on the console UART? ?or if we fix things so we don't need INIT_NO_IDLE anymore? ?Then this will crash.

Driver code should not make assumptions like this about what device init code is or isn't doing.

Okay, How about doing as below ensuring get_sync always and forbid runtime to avoid clock_gating if wakeup is not set.

static int serial_omap_probe(struct platform_device *pdev) { [..]

        pm_runtime_enable(&pdev->dev);
        pm_runtime_get_sync(&pdev->dev);

        if (!device_may_wakeup(&pdev->dev))
                pm_runtime_forbid(&pdev->dev);

[..]

        pm_runtime_put(&pdev->dev);

[..]
}

--
Thanks,
Govindraj.R

#35 lore raw

PATCH v6 9/16 OMAP2+: UART: Add runtime pm support for omap-serial driver

Quoted 45 lines · Govindraj
Quoted 44 lines · Kevin Hilman
Quoted 27 lines · Govindraj
Quoted 26 lines · Kevin Hilman

"Govindraj.R" <[email protected]> writes:

[...]

Quoted 2 lines

Use device_may_wakeup to check whether uart has wakeup capabilities and then enable uart runtime usage for the uart.

Curious about what happens when device_may_wakeup() is not set during device init.

[...]

Review static int serial_omap_probe(struct platform_device *pdev) · line 1372

Quoted 11 lines
(quoted diff) +7 -0
@@ -1305,6 +1363,16 @@ static int serial_omap_probe(struct platform_device *pdev)
 ? ? ? ? ? ? ? up->uart_dma.rx_dma_channel = OMAP_UART_DMA_CH_FREE;
 ? ? ? }
 
+ ? ? pm_runtime_use_autosuspend(&pdev->dev);
+ ? ? pm_runtime_set_autosuspend_delay(&pdev->dev,
+ ? ? ? ? ? ? ? ? ? ? OMAP_UART_AUTOSUSPEND_DELAY);
+
+ ? ? pm_runtime_irq_safe(&pdev->dev);
+ ? ? if (device_may_wakeup(&pdev->dev)) {
+ ? ? ? ? ? ? pm_runtime_enable(&pdev->dev);

So if device_may_wakeup() is false, runtime PM is not enabled, then...

Quoted 8 lines
Quoted 3 lines

Review static int serial_omap_probe(struct platform_device *pdev) · line 1373

Quoted 1 line
(quoted diff) +1 -0
+ ? ? ? ? ? ? pm_runtime_get_sync(&pdev->dev);

...this get doesn't happen, and the first register access causes a crash.

Actually no crash, clocks will left enabled from boot up (hwmod_no_reset/idle) that are idled and enabled back here.

Since hwmod_idle is binded here later ([PATCH v6 15/16]),

IMO, That's not a very maintainable solution.

What happens when when someone fixes serial.c to only set HWMOD_INIT_NO_IDLE on the console UART? ?or if we fix things so we don't need INIT_NO_IDLE anymore? ?Then this will crash.

Quoted 7 lines
Quoted 3 lines

Driver code should not make assumptions like this about what device init code is or isn't doing.

Okay, How about doing as below ensuring get_sync always and forbid runtime to avoid clock_gating if wakeup is not set.

This is better, I'm not crazy about that either.

Consider a platform that doesn't have wakeups, but the UARTs are not
used (at least initially.) That means on power up, all the UARTs are
left enabled to consume power even when they're not used.

Kevin

#36 lore raw

PATCH v6 9/16 OMAP2+: UART: Add runtime pm support for omap-serial driver

Quoted 55 lines · Kevin Hilman
Quoted 45 lines · Govindraj
Quoted 44 lines · Kevin Hilman
Quoted 27 lines · Govindraj
Quoted 26 lines · Kevin Hilman

"Govindraj.R" <[email protected]> writes:

[...]

Quoted 2 lines

Use device_may_wakeup to check whether uart has wakeup capabilities and then enable uart runtime usage for the uart.

Curious about what happens when device_may_wakeup() is not set during device init.

[...]

Review static int serial_omap_probe(struct platform_device *pdev) · line 1372

Quoted 11 lines
(quoted diff) +7 -0
@@ -1305,6 +1363,16 @@ static int serial_omap_probe(struct platform_device *pdev)
 ? ? ? ? ? ? ? up->uart_dma.rx_dma_channel = OMAP_UART_DMA_CH_FREE;
 ? ? ? }
 
+ ? ? pm_runtime_use_autosuspend(&pdev->dev);
+ ? ? pm_runtime_set_autosuspend_delay(&pdev->dev,
+ ? ? ? ? ? ? ? ? ? ? OMAP_UART_AUTOSUSPEND_DELAY);
+
+ ? ? pm_runtime_irq_safe(&pdev->dev);
+ ? ? if (device_may_wakeup(&pdev->dev)) {
+ ? ? ? ? ? ? pm_runtime_enable(&pdev->dev);

So if device_may_wakeup() is false, runtime PM is not enabled, then...

Quoted 8 lines
Quoted 3 lines

Review static int serial_omap_probe(struct platform_device *pdev) · line 1373

Quoted 1 line
(quoted diff) +1 -0
+ ? ? ? ? ? ? pm_runtime_get_sync(&pdev->dev);

...this get doesn't happen, and the first register access causes a crash.

Actually no crash, clocks will left enabled from boot up (hwmod_no_reset/idle) that are idled and enabled back here.

Since hwmod_idle is binded here later ([PATCH v6 15/16]),

IMO, That's not a very maintainable solution.

What happens when when someone fixes serial.c to only set HWMOD_INIT_NO_IDLE on the console UART? ?or if we fix things so we don't need INIT_NO_IDLE anymore? ?Then this will crash.

Quoted 7 lines
Quoted 3 lines

Driver code should not make assumptions like this about what device init code is or isn't doing.

Okay, How about doing as below ensuring get_sync always and forbid runtime to avoid clock_gating if wakeup is not set.

Quoted 6 lines

This is better, I'm not crazy about that either.

Consider a platform that doesn't have wakeups, but the UARTs are not used (at least initially.) ? That means on power up, all the UARTs are left enabled to consume power even when they're not used.

okay, the right place would be serial_omap_pm
to do add runtime forbid.

whenever the uart port is used it will call serial_omap_pm with state param assigned value zero from serial_core layer for open system call from user space.

Also when uart port is closed it will shutdown where we can add runtime_allow. So for uart ports not wakeup capable keep uart clocks on until used and once port is shutdown cut uart clocks.

drivers/tty/serial/omap-serial.c +8 -0
index 8a955fc..2c43744 100644
@@ -608,6 +608,10 @@ static void serial_omap_shutdown(struct uart_port *port)
                        up->uart_dma.rx_buf_dma_phys);
                up->uart_dma.rx_buf = NULL;
        }
+
+       if (!device_may_wakeup(&up->pdev->dev))
+               pm_runtime_allow(&up->pdev->dev);
+
        pm_runtime_put(&up->pdev->dev);
        free_irq(up->port.irq, up);
 }
@@ -893,6 +897,10 @@ serial_omap_pm(struct uart_port *port, unsigned int state,
        serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
        serial_out(up, UART_EFR, efr);
        serial_out(up, UART_LCR, 0);
+
+       if (!state && !device_may_wakeup(&up->pdev->dev))
+               pm_runtime_forbid(&up->pdev->dev);
+
        pm_runtime_put(&up->pdev->dev);
 }
 

--
Thanks,
Govindraj.R

#37 lore raw

PATCH v6 1/16 OMAP2+: hwmod: Add API to enable IO ring wakeup.

In reply to Govindraj.R
Quoted 32 lines · Govindraj.R

Add API to enable IO pad wakeup capability based on mux dynamic pad and wake_up enable flag available from hwmod_mux initialization.

Use the wakeup_enable flag and enable wakeup capability for the given pads. Wakeup capability will be enabled/disabled during hwmod idle transition based on whether wakeup_flag is set or cleared.

Call the omap_hwmod_set_ioring_wakeup from hwmod_wakeup_enable/disable.

---
  arch/arm/mach-omap2/omap_hwmod.c |   59 ++++++++++++++++++++++++++++++++++++++
  1 files changed, 59 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/omap_hwmod.c +9 -0
index 84cc0bd..e751dd9 100644
@@ -2062,6 +2062,34 @@ static int __init omap_hwmod_setup_all(void)
  core_initcall(omap_hwmod_setup_all);
 
  /**
+ * omap_hwmod_set_ioring_wakeup - enable io pad wakeup flag.
+ * @oh: struct omap_hwmod *
+ * @set: bool value indicating to set or clear wakeup status.
+ *
+ * Set or Clear wakeup flag for the io_pad.
+ */
+static int omap_hwmod_set_ioring_wakeup(struct omap_hwmod *oh, bool set_wake)
+{
+	struct omap_device_pad *pad;

arch/arm/mach-omap2/omap_hwmod.c static int __init omap_hwmod_setup_all(void) · line 2083

Quoted 10 lines
arch/arm/mach-omap2/omap_hwmod.c +10 -0
+	int ret = -EINVAL, j;
+
+	if (oh->mux&&  oh->mux->enabled) {
+		for (j = 0; j<  oh->mux->nr_pads_dynamic; j++) {
+			pad = oh->mux->pads_dynamic[j];
+			if (pad->flags&  OMAP_DEVICE_PAD_WAKEUP) {
+				if (set_wake)
+					pad->idle |= OMAP_WAKEUP_EN;
+				else
+					pad->idle&= ~OMAP_WAKEUP_EN;

I think apart from enabling/disabling the IO wakeup's at the pad level, there is also a need to trigger the IO daisy chain control (Wu clock) by programming the PRCM.PM_WKEN_WKUP[16] EN_IO_CHAIN bit and waiting on the PRCM.PM_WKST_WKUP[16] ST_IO_CHAIN) bit, which is done by the omap3_enable/disable_io_chain function. This is still done in the cpuidle path, but it makes sense to move that over here, since it should be done every time a pad level wakeup is enabled or disabled.

See section 3.5.7.2.2 I/O Wake-Up Mechanism of 36xx TRM revA.

"The I/O wake-up scheme is enabled by triggering the I/O daisy chain control (Wu clock) by
programming a dedicated register (PRCM.PM_WKEN_WKUP[16] EN_IO_CHAIN) in the PRCM module.Software must wait for the I/O daisy chain to complete before it transitions the PER domain to a
nonfunctional state. This is done by polling a dedicated status bit in the PRCM module
(PRCM.PM_WKST_WKUP[16] ST_IO_CHAIN). This status bit must be cleared by software when the bit is
read to 1."

Quoted 64 lines
arch/arm/mach-omap2/omap_hwmod.c +40 -0
+				ret = 0;
+			}
+		}
+	}
+
+	return ret;
+}
+
+/**
   * omap_hwmod_enable - enable an omap_hwmod
   * @oh: struct omap_hwmod *
   *
@@ -2393,6 +2421,35 @@ int omap_hwmod_del_initiator_dep(struct omap_hwmod *oh,
  {
  	return _del_initiator_dep(oh, init_oh);
  }
+/**
+ * omap_hwmod_enable_ioring_wakeup - Set wakeup flag for iopad.
+ * @oh: struct omap_hwmod *
+ *
+ * Traverse through dynamic pads, if pad is enabled then
+ * set wakeup enable bit flag for the mux pin. Wakeup pad bit
+ * will be set during hwmod idle transistion.
+ * Return error if pads are not enabled or not available.
+ */
+int omap_hwmod_enable_ioring_wakeup(struct omap_hwmod *oh)
+{
+	/* Enable pad wake-up capability */
+	return omap_hwmod_set_ioring_wakeup(oh, true);
+}
+
+/**
+ * omap_hwmod_disable_ioring_wakeup - Clear wakeup flag for iopad.
+ * @oh: struct omap_hwmod *
+ *
+ * Traverse through dynamic pads, if pad is enabled then
+ * clear wakeup enable bit flag for the mux pin. Wakeup pad bit
+ * will be set during hwmod idle transistion.
+ * Return error if pads are not enabled or not available.
+ */
+int omap_hwmod_disable_ioring_wakeup(struct omap_hwmod *oh)
+{
+	/* Disable pad wakeup capability */
+	return omap_hwmod_set_ioring_wakeup(oh, false);
+}
 
  /**
   * omap_hwmod_enable_wakeup - allow device to wake up the system
@@ -2419,6 +2476,7 @@ int omap_hwmod_enable_wakeup(struct omap_hwmod *oh)
  	v = oh->_sysc_cache;
  	_enable_wakeup(oh,&v);
  	_write_sysconfig(v, oh);
+	omap_hwmod_enable_ioring_wakeup(oh);
  	spin_unlock_irqrestore(&oh->_lock, flags);
 
  	return 0;
@@ -2449,6 +2507,7 @@ int omap_hwmod_disable_wakeup(struct omap_hwmod *oh)
  	v = oh->_sysc_cache;
  	_disable_wakeup(oh,&v);
  	_write_sysconfig(v, oh);
+	omap_hwmod_disable_ioring_wakeup(oh);
  	spin_unlock_irqrestore(&oh->_lock, flags);
 
  	return 0;
#38 lore raw

PATCH v6 1/16 OMAP2+: hwmod: Add API to enable IO ring wakeup.

---snip--

Quoted 24 lines

arch/arm/mach-omap2/omap_hwmod.c static int __init omap_hwmod_setup_all(void)

Quoted 12 lines
arch/arm/mach-omap2/omap_hwmod.c +12 -0
+{
+	struct omap_device_pad *pad;
+	int ret = -EINVAL, j;
+
+	if (oh->mux&&  oh->mux->enabled) {
+		for (j = 0; j<  oh->mux->nr_pads_dynamic; j++) {
+			pad = oh->mux->pads_dynamic[j];
+			if (pad->flags&  OMAP_DEVICE_PAD_WAKEUP) {
+				if (set_wake)
+					pad->idle |= OMAP_WAKEUP_EN;
+				else
+					pad->idle&= ~OMAP_WAKEUP_EN;

I think apart from enabling/disabling the IO wakeup's at the pad level, there is also a need to trigger the IO daisy chain control (Wu clock) by programming the PRCM.PM_WKEN_WKUP[16] EN_IO_CHAIN bit and waiting on the PRCM.PM_WKST_WKUP[16] ST_IO_CHAIN) bit, which is done by the omap3_enable/disable_io_chain function. This is still done in the cpuidle path, but it makes sense to move that over here, since it should be done every time a pad level wakeup is enabled or disabled.

See section 3.5.7.2.2 I/O Wake-Up Mechanism of 36xx TRM revA.

Quoted 14 lines

"The I/O wake-up scheme is enabled by triggering the I/O daisy chain control (Wu clock) by
programming a dedicated register (PRCM.PM_WKEN_WKUP[16] EN_IO_CHAIN) in
the PRCM module.Software must wait for the I/O daisy chain to complete
before it transitions the PER domain to a
nonfunctional state. This is done by polling a dedicated status bit in
the PRCM module
(PRCM.PM_WKST_WKUP[16] ST_IO_CHAIN). This status bit must be cleared by
software when the bit is
read to 1."

I am working on adding Daisy chain support via hwmod mux framework. I will post the patches soon.

Regards
Vishwa

#39 lore raw

PATCH v6 1/16 OMAP2+: hwmod: Add API to enable IO ring wakeup.

In reply to Rajendra Nayak

Hi Rajendra,

Quoted 44 lines · Rajendra Nayak
Quoted 32 lines · Govindraj.R

Add API to enable IO pad wakeup capability based on mux dynamic pad and wake_up enable flag available from hwmod_mux initialization.

Use the wakeup_enable flag and enable wakeup capability for the given pads. Wakeup capability will be enabled/disabled during hwmod idle transition based on whether wakeup_flag is set or cleared.

Call the omap_hwmod_set_ioring_wakeup from hwmod_wakeup_enable/disable.

---
  arch/arm/mach-omap2/omap_hwmod.c |   59 ++++++++++++++++++++++++++++++++++++++
  1 files changed, 59 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/omap_hwmod.c +9 -0
index 84cc0bd..e751dd9 100644
@@ -2062,6 +2062,34 @@ static int __init omap_hwmod_setup_all(void)
  core_initcall(omap_hwmod_setup_all);
 
  /**
+ * omap_hwmod_set_ioring_wakeup - enable io pad wakeup flag.
+ * @oh: struct omap_hwmod *
+ * @set: bool value indicating to set or clear wakeup status.
+ *
+ * Set or Clear wakeup flag for the io_pad.
+ */
+static int omap_hwmod_set_ioring_wakeup(struct omap_hwmod *oh, bool set_wake)
+{
+	struct omap_device_pad *pad;

arch/arm/mach-omap2/omap_hwmod.c static int __init omap_hwmod_setup_all(void) · line 2083

Quoted 10 lines
arch/arm/mach-omap2/omap_hwmod.c +10 -0
+	int ret = -EINVAL, j;
+
+	if (oh->mux&&  oh->mux->enabled) {
+		for (j = 0; j<  oh->mux->nr_pads_dynamic; j++) {
+			pad = oh->mux->pads_dynamic[j];
+			if (pad->flags&  OMAP_DEVICE_PAD_WAKEUP) {
+				if (set_wake)
+					pad->idle |= OMAP_WAKEUP_EN;
+				else
+					pad->idle&= ~OMAP_WAKEUP_EN;
Quoted 8 lines

I think apart from enabling/disabling the IO wakeup's at the pad level, there is also a need to trigger the IO daisy chain control (Wu clock) by programming the PRCM.PM_WKEN_WKUP[16] EN_IO_CHAIN bit and waiting on the PRCM.PM_WKST_WKUP[16] ST_IO_CHAIN) bit, which is done by the omap3_enable/disable_io_chain function. This is still done in the cpuidle path, but it makes sense to move that over here, since it should be done every time a pad level wakeup is enabled or disabled.

So should it be done just here or also in the idle path? In general, I'm certainly for moving things out of the idle path into the places where they belong.

However, I don't get from the TRM description below that it should be done every time a pad-level wake is enabled or disabled. Can you clarify what part of the TRM description you mean?

All I understand is that it has to be done before PER domain transisions.

Also, if this were to happen, are there side-effects of having the IO daisy chain armed outside the idle path?

Kevin

Quoted 12 lines

See section 3.5.7.2.2 I/O Wake-Up Mechanism of 36xx TRM revA.

"The I/O wake-up scheme is enabled by triggering the I/O daisy chain control (Wu clock) by
programming a dedicated register (PRCM.PM_WKEN_WKUP[16] EN_IO_CHAIN) in the PRCM module.Software must wait for the I/O daisy chain to complete before it transitions the PER domain to a nonfunctional state. This is done by polling a dedicated status bit in the PRCM module
(PRCM.PM_WKST_WKUP[16] ST_IO_CHAIN). This status bit must be cleared by software when the bit is
read to 1."

#40 lore raw

PATCH v6 1/16 OMAP2+: hwmod: Add API to enable IO ring wakeup.

Hi Kevin,

Quoted 57 lines · Kevin Hilman

Hi Rajendra,

Quoted 44 lines · Rajendra Nayak
Quoted 32 lines · Govindraj.R

Add API to enable IO pad wakeup capability based on mux dynamic pad and wake_up enable flag available from hwmod_mux initialization.

Use the wakeup_enable flag and enable wakeup capability for the given pads. Wakeup capability will be enabled/disabled during hwmod idle transition based on whether wakeup_flag is set or cleared.

Call the omap_hwmod_set_ioring_wakeup from hwmod_wakeup_enable/disable.

---
   arch/arm/mach-omap2/omap_hwmod.c |   59 ++++++++++++++++++++++++++++++++++++++
   1 files changed, 59 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/omap_hwmod.c +9 -0
index 84cc0bd..e751dd9 100644
@@ -2062,6 +2062,34 @@ static int __init omap_hwmod_setup_all(void)
   core_initcall(omap_hwmod_setup_all);
 
   /**
+ * omap_hwmod_set_ioring_wakeup - enable io pad wakeup flag.
+ * @oh: struct omap_hwmod *
+ * @set: bool value indicating to set or clear wakeup status.
+ *
+ * Set or Clear wakeup flag for the io_pad.
+ */
+static int omap_hwmod_set_ioring_wakeup(struct omap_hwmod *oh, bool set_wake)
+{
+	struct omap_device_pad *pad;

arch/arm/mach-omap2/omap_hwmod.c static int __init omap_hwmod_setup_all(void) · line 2083

Quoted 10 lines
arch/arm/mach-omap2/omap_hwmod.c +10 -0
+	int ret = -EINVAL, j;
+
+	if (oh->mux&&   oh->mux->enabled) {
+		for (j = 0; j<   oh->mux->nr_pads_dynamic; j++) {
+			pad = oh->mux->pads_dynamic[j];
+			if (pad->flags&   OMAP_DEVICE_PAD_WAKEUP) {
+				if (set_wake)
+					pad->idle |= OMAP_WAKEUP_EN;
+				else
+					pad->idle&= ~OMAP_WAKEUP_EN;
Quoted 8 lines

I think apart from enabling/disabling the IO wakeup's at the pad level, there is also a need to trigger the IO daisy chain control (Wu clock) by programming the PRCM.PM_WKEN_WKUP[16] EN_IO_CHAIN bit and waiting on the PRCM.PM_WKST_WKUP[16] ST_IO_CHAIN) bit, which is done by the omap3_enable/disable_io_chain function. This is still done in the cpuidle path, but it makes sense to move that over here, since it should be done every time a pad level wakeup is enabled or disabled.

Quoted 7 lines

So should it be done just here or also in the idle path? In general, I'm certainly for moving things out of the idle path into the places where they belong.

However, I don't get from the TRM description below that it should be done every time a pad-level wake is enabled or disabled. Can you clarify what part of the TRM description you mean?

+ Nilesh from the PRCM design team, I and Vishwa had a short meeting with Nilesh just to double confirm our understanding on how IO daisy should be implemented.

I agree the OMAP3 TRM isn't very clear in mentioning this and overall there is very limited documentation on this.

The OMAP4 TRM however is a little better and there isn't any difference in the way IO Daisy is implemented in OMAP3 and OMAP4.

So, I'll try and explain what I meant based on whats in the OMAP4 TRM :)

I am referring to OMAP4430_ES2.x Public TRM vO.

refer to Figure 3-74. I/O Pads Daisy-Chain Configuration, The WUEN signal to each pad (which can be used to enable IO-daisy for the given pad) is a AND of a signal from PRCM and one from SCM.
The signal from PRCM can be enabled by writing into PRM_IO_PMCTRL[16] GLOBAL_WUEN bit (which in our case we keep enabled always, done early at boot).
The signal from SCM can be enabled by writing to the individual pad registers in SCM CONTROL.CONTROL_PADCONF_<IOpad>[14] WAKEUPENABLE0 CONTROL.CONTROL_PADCONF_<IOpad>[30] WAKEUPENABLE1.
This is done by hwmod every time the module is enabled/idled.

This is what is mentioned in the TRM here
"The I/O pad wake-up scheme must be enabled (WUEN signal) globally by setting the
PRM_IO_PMCTRL[16] GLOBAL_WUEN bit and by also setting I/O pad wake-up enabled/disabled
individually (WUEN signal) by writing to the following bit fields in the control module:
? CONTROL.CONTROL_PADCONF_<IOpad>[14] WAKEUPENABLE0
? CONTROL.CONTROL_PADCONF_<IOpad>[30] WAKEUPENABLE1"

And then the TRM mentions this about the need to trigger WUCLKIN for every pad enable/disable.
This is needed to reset any spurious wakeups events.

"Once configured, the wake-up scheme within each I/O pad is enabled and disabled by triggering a control
(WUCLKIN signal) of the I/O daisy chain. This is done thanks to a dedicated PRCM module register bit
PRM_IO_PMCTRL[8] WUCLK_CTRL. The software must enable the I/O wakeup prior entering a
low-power mode and disable it following a wake-up event. Writing the PRM_IO_PMCTRL[8] WUCLK_CTRL bit to 1 asserts signal WUCLKIN high to reset spurious
wake-up event and to latch the current pad input value. PRCM module register PRM_IO_PMCTRL[9]
WUCLK_STATUS logs the signal WUCLKOUT of the last pad of the I/O ring. Once this status is set to 1,
the software may clear the PRM_IO_PMCTRL[8] WUCLK_CTRL bit to effectively enable or disable the
wake-up feature within each pad."

The controls are exactly the same in case of OMAP3.
There is a global control at PRCM level (PRCM.PM_WKEN_WKUP[8] EN_IO) and at pad level in SCM.

To assert the WUCLKIN, there is PRCM.PM_WKEN_WKUP[16] EN_IO_CHAIN and to log the signal WUCLKOUT of the last pad there is PRCM.PM_WKST_WKUP[16] ST_IO_CHAIN.

Its just that the registers in OMAP3 are named weirdly, the digram isn't any clear and the explanation in the TRM does not help much, causing confusion.

Quoted 2 lines

All I understand is that it has to be done before PER domain transisions.

This is mostly coming from pre 3430 es3 days when there was no control for a WUCLKIN trigger in software. The hardware did this based on per/core entering sleep states.

With 3430es3.1 and the subsequent 3630/4430/4460 silicons, the software can decide when to enable/trigger iodaisy and it should ideally be done before the powerdomain corresponding to the given module transitions to RET or OFF. Until then the modules async wakeup is expected to generate a wakeup.

Quoted 2 lines

Also, if this were to happen, are there side-effects of having the IO daisy chain armed outside the idle path?

IO daisy is actually designed so that it can be armed outside of idle, by providing software control to generate the WUCLKIN pulse.

So as long as a module is clocked, it can generate interrupts, once its clocks are cut, it can generate an async wakeup, and once the powerdomain belonging to the module transitions to RET or OFF, it should be programmed to generate IO wakeup, independent of system idle state.

regards,
Rajendra

Quoted 17 lines

Kevin

Quoted 12 lines

See section 3.5.7.2.2 I/O Wake-Up Mechanism of 36xx TRM revA.

"The I/O wake-up scheme is enabled by triggering the I/O daisy chain control (Wu clock) by
programming a dedicated register (PRCM.PM_WKEN_WKUP[16] EN_IO_CHAIN) in the PRCM module.Software must wait for the I/O daisy chain to complete before it transitions the PER domain to a nonfunctional state. This is done by polling a dedicated status bit in the PRCM module
(PRCM.PM_WKST_WKUP[16] ST_IO_CHAIN). This status bit must be cleared by software when the bit is
read to 1."