* [PATCH 1/7] OMAP2+ : hwmod_data: update uart hwmod data.
2011-02-28 14:39 [PATCH 0/7] OMAP2+: UART: runtime conversion + cleanup Govindraj.R
@ 2011-02-28 14:39 ` Govindraj.R
2011-02-28 14:39 ` [PATCH 2/7] OMAP2+: mux: Enable wakeup for wakeup enable requested pads Govindraj.R
` (5 subsequent siblings)
6 siblings, 0 replies; 25+ messages in thread
From: Govindraj.R @ 2011-02-28 14:39 UTC (permalink / raw)
To: linux-arm-kernel
Add HWMOD_SWSUP_SIDLE flag to uart*_hwmod data. With addition of this flag the
hwmod framework will take care of updating sysc reg with no_idle mode while
enabling clocks and to force_idle mode while disabling clocks.
Signed-off-by: Govindraj.R <govindraj.raja@ti.com>
---
arch/arm/mach-omap2/omap_hwmod_2420_data.c | 3 +++
arch/arm/mach-omap2/omap_hwmod_2430_data.c | 3 +++
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 4 ++++
arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 4 ++++
4 files changed, 14 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
index f323c6b..48392f3 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
@@ -434,6 +434,7 @@ static struct omap_hwmod_ocp_if *omap2420_uart1_slaves[] = {
static struct omap_hwmod omap2420_uart1_hwmod = {
.name = "uart1",
+ .flags = HWMOD_SWSUP_SIDLE,
.mpu_irqs = uart1_mpu_irqs,
.mpu_irqs_cnt = ARRAY_SIZE(uart1_mpu_irqs),
.sdma_reqs = uart1_sdma_reqs,
@@ -471,6 +472,7 @@ static struct omap_hwmod_ocp_if *omap2420_uart2_slaves[] = {
static struct omap_hwmod omap2420_uart2_hwmod = {
.name = "uart2",
+ .flags = HWMOD_SWSUP_SIDLE,
.mpu_irqs = uart2_mpu_irqs,
.mpu_irqs_cnt = ARRAY_SIZE(uart2_mpu_irqs),
.sdma_reqs = uart2_sdma_reqs,
@@ -508,6 +510,7 @@ static struct omap_hwmod_ocp_if *omap2420_uart3_slaves[] = {
static struct omap_hwmod omap2420_uart3_hwmod = {
.name = "uart3",
+ .flags = HWMOD_SWSUP_SIDLE,
.mpu_irqs = uart3_mpu_irqs,
.mpu_irqs_cnt = ARRAY_SIZE(uart3_mpu_irqs),
.sdma_reqs = uart3_sdma_reqs,
diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
index de0015d..ab58a20 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
@@ -490,6 +490,7 @@ static struct omap_hwmod_ocp_if *omap2430_uart1_slaves[] = {
static struct omap_hwmod omap2430_uart1_hwmod = {
.name = "uart1",
+ .flags = HWMOD_SWSUP_SIDLE,
.mpu_irqs = uart1_mpu_irqs,
.mpu_irqs_cnt = ARRAY_SIZE(uart1_mpu_irqs),
.sdma_reqs = uart1_sdma_reqs,
@@ -527,6 +528,7 @@ static struct omap_hwmod_ocp_if *omap2430_uart2_slaves[] = {
static struct omap_hwmod omap2430_uart2_hwmod = {
.name = "uart2",
+ .flags = HWMOD_SWSUP_SIDLE,
.mpu_irqs = uart2_mpu_irqs,
.mpu_irqs_cnt = ARRAY_SIZE(uart2_mpu_irqs),
.sdma_reqs = uart2_sdma_reqs,
@@ -564,6 +566,7 @@ static struct omap_hwmod_ocp_if *omap2430_uart3_slaves[] = {
static struct omap_hwmod omap2430_uart3_hwmod = {
.name = "uart3",
+ .flags = HWMOD_SWSUP_SIDLE,
.mpu_irqs = uart3_mpu_irqs,
.mpu_irqs_cnt = ARRAY_SIZE(uart3_mpu_irqs),
.sdma_reqs = uart3_sdma_reqs,
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index e9d0012..79c39d4 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -626,6 +626,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_uart1_slaves[] = {
static struct omap_hwmod omap3xxx_uart1_hwmod = {
.name = "uart1",
+ .flags = HWMOD_SWSUP_SIDLE,
.mpu_irqs = uart1_mpu_irqs,
.mpu_irqs_cnt = ARRAY_SIZE(uart1_mpu_irqs),
.sdma_reqs = uart1_sdma_reqs,
@@ -663,6 +664,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_uart2_slaves[] = {
static struct omap_hwmod omap3xxx_uart2_hwmod = {
.name = "uart2",
+ .flags = HWMOD_SWSUP_SIDLE,
.mpu_irqs = uart2_mpu_irqs,
.mpu_irqs_cnt = ARRAY_SIZE(uart2_mpu_irqs),
.sdma_reqs = uart2_sdma_reqs,
@@ -700,6 +702,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_uart3_slaves[] = {
static struct omap_hwmod omap3xxx_uart3_hwmod = {
.name = "uart3",
+ .flags = HWMOD_SWSUP_SIDLE,
.mpu_irqs = uart3_mpu_irqs,
.mpu_irqs_cnt = ARRAY_SIZE(uart3_mpu_irqs),
.sdma_reqs = uart3_sdma_reqs,
@@ -737,6 +740,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_uart4_slaves[] = {
static struct omap_hwmod omap3xxx_uart4_hwmod = {
.name = "uart4",
+ .flags = HWMOD_SWSUP_SIDLE,
.mpu_irqs = uart4_mpu_irqs,
.mpu_irqs_cnt = ARRAY_SIZE(uart4_mpu_irqs),
.sdma_reqs = uart4_sdma_reqs,
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index 79a8601..13c2df1 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -4587,6 +4587,7 @@ static struct omap_hwmod_ocp_if *omap44xx_uart1_slaves[] = {
static struct omap_hwmod omap44xx_uart1_hwmod = {
.name = "uart1",
+ .flags = HWMOD_SWSUP_SIDLE,
.class = &omap44xx_uart_hwmod_class,
.mpu_irqs = omap44xx_uart1_irqs,
.mpu_irqs_cnt = ARRAY_SIZE(omap44xx_uart1_irqs),
@@ -4639,6 +4640,7 @@ static struct omap_hwmod_ocp_if *omap44xx_uart2_slaves[] = {
static struct omap_hwmod omap44xx_uart2_hwmod = {
.name = "uart2",
+ .flags = HWMOD_SWSUP_SIDLE,
.class = &omap44xx_uart_hwmod_class,
.mpu_irqs = omap44xx_uart2_irqs,
.mpu_irqs_cnt = ARRAY_SIZE(omap44xx_uart2_irqs),
@@ -4691,6 +4693,7 @@ static struct omap_hwmod_ocp_if *omap44xx_uart3_slaves[] = {
static struct omap_hwmod omap44xx_uart3_hwmod = {
.name = "uart3",
+ .flags = HWMOD_SWSUP_SIDLE,
.class = &omap44xx_uart_hwmod_class,
.flags = (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET),
.mpu_irqs = omap44xx_uart3_irqs,
@@ -4744,6 +4747,7 @@ static struct omap_hwmod_ocp_if *omap44xx_uart4_slaves[] = {
static struct omap_hwmod omap44xx_uart4_hwmod = {
.name = "uart4",
+ .flags = HWMOD_SWSUP_SIDLE,
.class = &omap44xx_uart_hwmod_class,
.mpu_irqs = omap44xx_uart4_irqs,
.mpu_irqs_cnt = ARRAY_SIZE(omap44xx_uart4_irqs),
--
1.7.1
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 2/7] OMAP2+: mux: Enable wakeup for wakeup enable requested pads
2011-02-28 14:39 [PATCH 0/7] OMAP2+: UART: runtime conversion + cleanup Govindraj.R
2011-02-28 14:39 ` [PATCH 1/7] OMAP2+ : hwmod_data: update uart hwmod data Govindraj.R
@ 2011-02-28 14:39 ` Govindraj.R
2011-03-02 4:49 ` Varadarajan, Charulatha
2011-02-28 14:39 ` [PATCH 3/7] OMAP2+: UART: Remove certain uart calls from sram_idle Govindraj.R
` (4 subsequent siblings)
6 siblings, 1 reply; 25+ messages in thread
From: Govindraj.R @ 2011-02-28 14:39 UTC (permalink / raw)
To: linux-arm-kernel
For device pads which have OMAP_DEVICE_PAD_WAKEUP set (which means they
are wakeup capable) enable the IO-daisy wakeup capability.
During re-muxing avoid direct write with val as this can disturb if any
mux done at bootloader level so read the pad then write back.
Also add a api to fetch the wake-up status bit is set for given omap-hwmod
device using available mux info which is added during omap_hwmod_mux_init.
Wakeup status bit is needed for uart_resume_idle call from sram_idle path
based on wake-up event has occurred for given uart we can enable clocks back.
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
Signed-off-by: Govindraj.R <govindraj.raja@ti.com>
---
arch/arm/mach-omap2/mux.c | 23 +++++++++++++++++++++++
arch/arm/mach-omap2/mux.h | 13 +++++++++++++
arch/arm/mach-omap2/omap_hwmod.c | 13 +++++++++++++
arch/arm/plat-omap/include/plat/omap_hwmod.h | 1 +
4 files changed, 50 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
index 98148b6..5338b93 100644
--- a/arch/arm/mach-omap2/mux.c
+++ b/arch/arm/mach-omap2/mux.c
@@ -317,6 +317,24 @@ err1:
return NULL;
}
+/* Gets the wakeup status of given pad from omap-hwmod */
+int omap_hwmod_mux_wakeup(struct omap_hwmod_mux_info *hmux)
+{
+ int i;
+ unsigned int val = -EINVAL;
+
+ for (i = 0; i < hmux->nr_pads; i++) {
+ struct omap_device_pad *pad = &hmux->pads[i];
+
+ val = omap_mux_read(pad->partition, pad->mux->reg_offset);
+ }
+
+ if (val > 0 && val & OMAP_WAKEUP_EVENT)
+ return 1;
+ else
+ return 0;
+}
+
/* Assumes the calling function takes care of locking */
void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state)
{
@@ -342,6 +360,9 @@ void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state)
break;
flags &= ~OMAP_DEVICE_PAD_ENABLED;
val = pad->idle;
+ if (flags & OMAP_DEVICE_PAD_WAKEUP)
+ val |= OMAP_WAKEUP_EN;
+
pr_debug("%s: Idling %s %x\n", __func__,
pad->name, val);
break;
@@ -358,6 +379,8 @@ void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state)
};
if (val >= 0) {
+ val |= omap_mux_read(pad->partition,
+ pad->mux->reg_offset);
omap_mux_write(pad->partition, val,
pad->mux->reg_offset);
pad->flags = flags;
diff --git a/arch/arm/mach-omap2/mux.h b/arch/arm/mach-omap2/mux.h
index a4ab17a..84a8fc2 100644
--- a/arch/arm/mach-omap2/mux.h
+++ b/arch/arm/mach-omap2/mux.h
@@ -220,8 +220,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_wakeup - omap hwmod check given pad had wakeup event
+ * @hmux: Pads for a hwmod
+ *
+ * Called only from omap_hwmod.c, do not use.
+ */
+int omap_hwmod_mux_wakeup(struct omap_hwmod_mux_info *hmux);
#else
+static inline int omap_hwmod_mux_wakeup(struct omap_hwmod_mux_info *hmux)
+{
+ return 0;
+}
+
static inline int omap_mux_init_gpio(int gpio, int val)
{
return 0;
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 9e89a58..893dae1 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -2239,3 +2239,16 @@ u32 omap_hwmod_get_context_loss_count(struct omap_hwmod *oh)
return ret;
}
+
+/**
+ * omap_hwmod_pad_wakeup_status - get pad wakeup status if mux is available.
+ * @oh: struct omap_hwmod *
+ *
+ * Returns the wake_up status bit of available pad mux pin.
+ */
+int omap_hmwod_pad_wakeup_status(struct omap_hwmod *oh)
+{
+ if (oh->mux)
+ return omap_hwmod_mux_wakeup(oh->mux);
+ return -EINVAL;
+}
diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h
index fedd829..4100be0 100644
--- a/arch/arm/plat-omap/include/plat/omap_hwmod.h
+++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h
@@ -588,6 +588,7 @@ int omap_hwmod_for_each_by_class(const char *classname,
int omap_hwmod_set_postsetup_state(struct omap_hwmod *oh, u8 state);
u32 omap_hwmod_get_context_loss_count(struct omap_hwmod *oh);
+int omap_hmwod_pad_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
--
1.7.1
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 2/7] OMAP2+: mux: Enable wakeup for wakeup enable requested pads
2011-02-28 14:39 ` [PATCH 2/7] OMAP2+: mux: Enable wakeup for wakeup enable requested pads Govindraj.R
@ 2011-03-02 4:49 ` Varadarajan, Charulatha
2011-03-02 10:40 ` Govindraj
0 siblings, 1 reply; 25+ messages in thread
From: Varadarajan, Charulatha @ 2011-03-02 4:49 UTC (permalink / raw)
To: linux-arm-kernel
Govind,
Couple of minor comments.
On Mon, Feb 28, 2011 at 20:09, Govindraj.R <govindraj.raja@ti.com> wrote:
> For device pads which have OMAP_DEVICE_PAD_WAKEUP set (which means they
> are wakeup capable) enable the IO-daisy wakeup capability.
> During re-muxing avoid direct write with val as this can disturb if any
> mux done at bootloader level so read the pad then write back.
>
> Also add a api to fetch the wake-up status bit is set for given omap-hwmod
%s/a api/an API/
> device using available mux info which is added during omap_hwmod_mux_init.
> Wakeup status bit is needed for uart_resume_idle call from sram_idle path
> based on wake-up event has occurred for given uart we can enable clocks back.
>
> Signed-off-by: Rajendra Nayak <rnayak@ti.com>
> Signed-off-by: Govindraj.R <govindraj.raja@ti.com>
> ---
> ?arch/arm/mach-omap2/mux.c ? ? ? ? ? ? ? ? ? ?| ? 23 +++++++++++++++++++++++
> ?arch/arm/mach-omap2/mux.h ? ? ? ? ? ? ? ? ? ?| ? 13 +++++++++++++
> ?arch/arm/mach-omap2/omap_hwmod.c ? ? ? ? ? ? | ? 13 +++++++++++++
> ?arch/arm/plat-omap/include/plat/omap_hwmod.h | ? ?1 +
> ?4 files changed, 50 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
> index 98148b6..5338b93 100644
> --- a/arch/arm/mach-omap2/mux.c
> +++ b/arch/arm/mach-omap2/mux.c
> @@ -317,6 +317,24 @@ err1:
> ? ? ? ?return NULL;
> ?}
>
> +/* Gets the wakeup status of given pad from omap-hwmod */
> +int omap_hwmod_mux_wakeup(struct omap_hwmod_mux_info *hmux)
> +{
> + ? ? ? int i;
> + ? ? ? unsigned int val = -EINVAL;
> +
> + ? ? ? for (i = 0; i < hmux->nr_pads; i++) {
> + ? ? ? ? ? ? ? struct omap_device_pad *pad = &hmux->pads[i];
> +
> + ? ? ? ? ? ? ? val = omap_mux_read(pad->partition, pad->mux->reg_offset);
> + ? ? ? }
> +
> + ? ? ? if (val > 0 && val & OMAP_WAKEUP_EVENT)
> + ? ? ? ? ? ? ? return 1;
> + ? ? ? else
No need of else here.
> + ? ? ? ? ? ? ? return 0;
> +}
> +
- V Charulatha
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 2/7] OMAP2+: mux: Enable wakeup for wakeup enable requested pads
2011-03-02 4:49 ` Varadarajan, Charulatha
@ 2011-03-02 10:40 ` Govindraj
0 siblings, 0 replies; 25+ messages in thread
From: Govindraj @ 2011-03-02 10:40 UTC (permalink / raw)
To: linux-arm-kernel
On Wed, Mar 2, 2011 at 10:19 AM, Varadarajan, Charulatha <charu@ti.com> wrote:
> Govind,
>
> Couple of minor comments.
>
> On Mon, Feb 28, 2011 at 20:09, Govindraj.R <govindraj.raja@ti.com> wrote:
>> For device pads which have OMAP_DEVICE_PAD_WAKEUP set (which means they
>> are wakeup capable) enable the IO-daisy wakeup capability.
>> During re-muxing avoid direct write with val as this can disturb if any
>> mux done at bootloader level so read the pad then write back.
>>
>> Also add a api to fetch the wake-up status bit is set for given omap-hwmod
>
> %s/a api/an API/
>
>> device using available mux info which is added during omap_hwmod_mux_init.
>> Wakeup status bit is needed for uart_resume_idle call from sram_idle path
>> based on wake-up event has occurred for given uart we can enable clocks back.
>>
>> Signed-off-by: Rajendra Nayak <rnayak@ti.com>
>> Signed-off-by: Govindraj.R <govindraj.raja@ti.com>
>> ---
>> ?arch/arm/mach-omap2/mux.c ? ? ? ? ? ? ? ? ? ?| ? 23 +++++++++++++++++++++++
>> ?arch/arm/mach-omap2/mux.h ? ? ? ? ? ? ? ? ? ?| ? 13 +++++++++++++
>> ?arch/arm/mach-omap2/omap_hwmod.c ? ? ? ? ? ? | ? 13 +++++++++++++
>> ?arch/arm/plat-omap/include/plat/omap_hwmod.h | ? ?1 +
>> ?4 files changed, 50 insertions(+), 0 deletions(-)
>>
>> diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
>> index 98148b6..5338b93 100644
>> --- a/arch/arm/mach-omap2/mux.c
>> +++ b/arch/arm/mach-omap2/mux.c
>> @@ -317,6 +317,24 @@ err1:
>> ? ? ? ?return NULL;
>> ?}
>>
>> +/* Gets the wakeup status of given pad from omap-hwmod */
>> +int omap_hwmod_mux_wakeup(struct omap_hwmod_mux_info *hmux)
>> +{
>> + ? ? ? int i;
>> + ? ? ? unsigned int val = -EINVAL;
>> +
>> + ? ? ? for (i = 0; i < hmux->nr_pads; i++) {
>> + ? ? ? ? ? ? ? struct omap_device_pad *pad = &hmux->pads[i];
>> +
>> + ? ? ? ? ? ? ? val = omap_mux_read(pad->partition, pad->mux->reg_offset);
>> + ? ? ? }
>> +
>> + ? ? ? if (val > 0 && val & OMAP_WAKEUP_EVENT)
>> + ? ? ? ? ? ? ? return 1;
>> + ? ? ? else
>
> No need of else here.
Yes correct.
I am resending this patch with some more modifications
to fix one more issue in the above loop.
--
Thanks,
Govindraj.R
<<SNIP>>
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 3/7] OMAP2+: UART: Remove certain uart calls from sram_idle
2011-02-28 14:39 [PATCH 0/7] OMAP2+: UART: runtime conversion + cleanup Govindraj.R
2011-02-28 14:39 ` [PATCH 1/7] OMAP2+ : hwmod_data: update uart hwmod data Govindraj.R
2011-02-28 14:39 ` [PATCH 2/7] OMAP2+: mux: Enable wakeup for wakeup enable requested pads Govindraj.R
@ 2011-02-28 14:39 ` Govindraj.R
2011-02-28 14:39 ` [PATCH 4/7] OMAP2+: UART: Remove uart clock handling code serial.c Govindraj.R
` (3 subsequent siblings)
6 siblings, 0 replies; 25+ messages in thread
From: Govindraj.R @ 2011-02-28 14:39 UTC (permalink / raw)
To: linux-arm-kernel
In preparation to UART runtime conversion. Remove certain uart specific calls
from sram_idle path in pm24xx/34xx files.
These func calls will no more be used with upcoming uart runtime design.
1.) Removing console lock holding :- Now can be handled with omap-serial file
itself with appropraite console_enable/disable calls for clk_enable/disable
cases.
2.) omap_uart_can_sleep :- not needed driver can decide based on inactivity.
3.) omap_uart_prepare_suspend :- omap-serial can take care with driver
suspend/resume hooks.
Signed-off-by: Govindraj.R <govindraj.raja@ti.com>
---
arch/arm/mach-omap2/pm24xx.c | 11 -----------
arch/arm/mach-omap2/pm34xx.c | 16 ----------------
arch/arm/plat-omap/include/plat/serial.h | 4 ----
3 files changed, 0 insertions(+), 31 deletions(-)
diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c
index 97feb3a..5af9881 100644
--- a/arch/arm/mach-omap2/pm24xx.c
+++ b/arch/arm/mach-omap2/pm24xx.c
@@ -132,11 +132,6 @@ 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);
@@ -150,9 +145,6 @@ static void omap2_enter_full_retention(void)
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;
@@ -267,8 +259,6 @@ static int omap2_can_sleep(void)
{
if (omap2_fclks_active())
return 0;
- if (!omap_uart_can_sleep())
- return 0;
if (osc_ck->usecount > 1)
return 0;
if (omap_dma_running())
@@ -319,7 +309,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);
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 2f864e4..850bb0a 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -395,13 +395,6 @@ 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;
@@ -481,10 +474,6 @@ void omap_sram_idle(void)
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 ||
@@ -503,8 +492,6 @@ int omap3_can_sleep(void)
{
if (!sleep_while_idle)
return 0;
- if (!omap_uart_can_sleep())
- return 0;
return 1;
}
@@ -547,7 +534,6 @@ static int omap3_pm_suspend(void)
goto restore;
}
- omap_uart_prepare_suspend();
omap3_intc_suspend();
omap_sram_idle();
@@ -594,14 +580,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;
}
diff --git a/arch/arm/plat-omap/include/plat/serial.h b/arch/arm/plat-omap/include/plat/serial.h
index 8061695..6339848 100644
--- a/arch/arm/plat-omap/include/plat/serial.h
+++ b/arch/arm/plat-omap/include/plat/serial.h
@@ -106,12 +106,8 @@ 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);
-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
--
1.7.1
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 4/7] OMAP2+: UART: Remove uart clock handling code serial.c
2011-02-28 14:39 [PATCH 0/7] OMAP2+: UART: runtime conversion + cleanup Govindraj.R
` (2 preceding siblings ...)
2011-02-28 14:39 ` [PATCH 3/7] OMAP2+: UART: Remove certain uart calls from sram_idle Govindraj.R
@ 2011-02-28 14:39 ` Govindraj.R
2011-02-28 14:39 ` [PATCH 5/7] Serial: OMAP: add runtime pm support for omap-serial driver Govindraj.R
` (2 subsequent siblings)
6 siblings, 0 replies; 25+ messages in thread
From: Govindraj.R @ 2011-02-28 14:39 UTC (permalink / raw)
To: linux-arm-kernel
Cleanup serial.c file in preparation to addition of runtime api's in omap-serial
file. Cleanup serial.c file and remove all clock handling mechanism as
this will be taken care with pm runtime apis in omap-serial.c file itself.
1.) remove omap-device enable and disable. We can can use get_sync/put_sync api's
2.) remove context save/restore can be done with runtime_resume callback for
get_sync call. No need to save context as all reg details available in
uart_port structure can be used for restore, so add missing regs in
uart port struct.
3.) Add api to identify console uart.
4.) Erratum handling informed as flag to driver and func to handle erratum
can be moved to omap-serial driver itself.
Signed-off-by: Govindraj.R <govindraj.raja@ti.com>
---
arch/arm/mach-omap2/serial.c | 749 ++-----------------------
arch/arm/plat-omap/include/plat/omap-serial.h | 21 +-
2 files changed, 75 insertions(+), 695 deletions(-)
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 47eef48..755f4aa 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -19,25 +19,18 @@
*/
#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>
#include "prm2xxx_3xxx.h"
@@ -47,65 +40,9 @@
#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)
-
-/*
- * NOTE: By default the serial timeout is disabled as it causes lost characters
- * over the serial ports. This means that the UART clocks will stay on until
- * disabled via sysfs. This also causes that any deeper omap sleep states are
- * blocked.
- */
-#define DEFAULT_TIMEOUT 0
-
-#define MAX_UART_HWMOD_NAME_LEN 16
-
-struct omap_uart_state {
- int num;
- int can_sleep;
- struct timer_list timer;
- u32 timeout;
-
- void __iomem *wk_st;
- void __iomem *wk_en;
- u32 wk_mask;
- 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;
-
- 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;
+#define MAX_UART_HWMOD_NAME_LEN 16
- /* Registers to be saved/restored for OFF-mode */
- u16 dll;
- u16 dlh;
- u16 ier;
- u16 sysc;
- u16 scr;
- u16 wer;
- u16 mcr;
-#endif
-};
-
-static LIST_HEAD(uart_list);
-static u8 num_uarts;
+static int omap_uart_con_id __initdata = -1;
static int uart_idle_hwmod(struct omap_device *od)
{
@@ -129,396 +66,35 @@ 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);
-}
-
-/*
- * 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)
-
-/*
- * Work Around for Errata i202 (3430 - 1.12, 3630 - 1.6)
- * The access to uart register after MDR1 Access
- * causes UART to corrupt data.
- *
- * Need a delay =
- * 5 L4 clock cycles + 5 UART functional clock cycle (@48MHz = ~0.2uS)
- * give 10 times as much
- */
-static void omap_uart_mdr1_errataset(struct omap_uart_state *uart, u8 mdr1_val,
- u8 fcr_val)
-{
- u8 timeout = 255;
-
- serial_write_reg(uart, UART_OMAP_MDR1, mdr1_val);
- udelay(2);
- serial_write_reg(uart, UART_FCR, fcr_val | UART_FCR_CLEAR_XMIT |
- UART_FCR_CLEAR_RCVR);
- /*
- * Wait for FIFO to empty: when empty, RX_FIFO_E bit is 0 and
- * TX_FIFO_E bit is 1.
- */
- while (UART_LSR_THRE != (serial_read_reg(uart, UART_LSR) &
- (UART_LSR_THRE | UART_LSR_DR))) {
- timeout--;
- if (!timeout) {
- /* Should *never* happen. we warn and carry on */
- dev_crit(&uart->pdev->dev, "Errata i202: timedout %x\n",
- serial_read_reg(uart, UART_LSR));
- break;
- }
- 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)
-{
- u8 idlemode;
-
- if (enable) {
- /**
- * Errata 2.15: [UART]:Cannot Acknowledge Idle Requests
- * in Smartidle Mode When Configured for DMA Operations.
- */
- if (uart->dma_enabled)
- idlemode = HWMOD_IDLEMODE_FORCE;
- else
- idlemode = HWMOD_IDLEMODE_SMART;
- } else {
- idlemode = HWMOD_IDLEMODE_NO;
- }
-
- 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;
- 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)
+static void omap_uart_idle_init(struct omap_uart_port_info *uart,
+ unsigned short num)
{
- struct omap_uart_state *uart = (struct omap_uart_state *)data;
-
- omap_uart_allow_sleep(uart);
-}
-
-void omap_uart_prepare_idle(int num)
-{
- struct omap_uart_state *uart;
-
- list_for_each_entry(uart, &uart_list, node) {
- if (num == uart->num && uart->can_sleep) {
- omap_uart_disable_clocks(uart);
- return;
- }
- }
-}
-
-void omap_uart_resume_idle(int num)
-{
- struct omap_uart_state *uart;
-
- list_for_each_entry(uart, &uart_list, node) {
- if (num == uart->num && uart->can_sleep) {
- omap_uart_enable_clocks(uart);
-
- /* Check for IO pad wakeup */
- if (cpu_is_omap34xx() && uart->padconf) {
- u16 p = omap_ctrl_readw(uart->padconf);
-
- if (p & OMAP3_PADCONF_WAKEUPEVENT0)
- omap_uart_block_sleep(uart);
- }
-
- /* Check for normal UART wakeup */
- if (__raw_readl(uart->wk_st) & uart->wk_mask)
- omap_uart_block_sleep(uart);
- return;
- }
- }
-}
-
-void omap_uart_prepare_suspend(void)
-{
- struct omap_uart_state *uart;
-
- list_for_each_entry(uart, &uart_list, node) {
- omap_uart_allow_sleep(uart);
- }
-}
-
-int omap_uart_can_sleep(void)
-{
- struct omap_uart_state *uart;
- int can_sleep = 1;
-
- list_for_each_entry(uart, &uart_list, node) {
- if (!uart->clocked)
- continue;
-
- if (!uart->can_sleep) {
- can_sleep = 0;
- continue;
- }
-
- /* This UART can now safely sleep. */
- omap_uart_allow_sleep(uart);
- }
-
- 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()) {
- u32 mod = (uart->num > 1) ? OMAP3430_PER_MOD : CORE_MOD;
+ if (cpu_is_omap34xx()) {
+ 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;
break;
case 1:
wk_mask = OMAP3430_ST_UART2_MASK;
- padconf = 0x17a;
break;
case 2:
wk_mask = OMAP3430_ST_UART3_MASK;
- padconf = 0x19e;
break;
case 3:
wk_mask = OMAP3630_ST_UART4_MASK;
- padconf = 0x0d2;
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;
@@ -543,155 +119,44 @@ 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;
- }
-
- uart->irqflags |= IRQF_SHARED;
- ret = request_threaded_irq(uart->irq, NULL, omap_uart_interrupt,
- IRQF_SHARED, "serial idle", (void *)uart);
- WARN_ON(ret);
-}
-
-void omap_uart_enable_irqs(int enable)
-{
- int ret;
- struct omap_uart_state *uart;
-
- list_for_each_entry(uart, &uart_list, node) {
- if (enable) {
- pm_runtime_put_sync(&uart->pdev->dev);
- ret = request_threaded_irq(uart->irq, NULL,
- omap_uart_interrupt,
- IRQF_SHARED,
- "serial idle",
- (void *)uart);
- } else {
- pm_runtime_get_noresume(&uart->pdev->dev);
- free_irq(uart->irq, (void *)uart);
- }
}
}
-static ssize_t sleep_timeout_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+char *cmdline_find_option(char *str)
{
- 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;
+ extern char *saved_command_line;
- return sprintf(buf, "%u\n", uart->timeout / HZ);
+ return strstr(saved_command_line, str);
}
-static ssize_t sleep_timeout_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t n)
+struct omap_hwmod *omap_uart_hwmod_lookup(int num)
{
- 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)
-{
- /* Needed to enable UART clocks when built without CONFIG_PM */
- omap_uart_enable_clocks(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;
+ struct omap_hwmod *oh;
+ char oh_name[MAX_UART_HWMOD_NAME_LEN];
- 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);
+ 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;
}
-#endif
static int __init omap_serial_early_init(void)
{
int i = 0;
+ char omap_tty_name[MAX_UART_HWMOD_NAME_LEN];
+ struct omap_hwmod *oh;
- 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);
- 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++;
-
- /*
- * NOTE: omap_hwmod_init() has not yet been called,
- * so no hwmod functions will work yet.
- */
-
- /*
- * During UART early init, device need to be probed
- * 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;
- } while (1);
-
+ for (i = 0; i < OMAP_MAX_HSUART_PORTS; i++) {
+ snprintf(omap_tty_name, MAX_UART_HWMOD_NAME_LEN,
+ "%s%d", OMAP_SERIAL_NAME, i);
+ if (cmdline_find_option(omap_tty_name)) {
+ omap_uart_con_id = i;
+ oh = omap_uart_hwmod_lookup(i);
+ oh->flags |= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET;
+ return 0;
+ }
+ }
return 0;
}
core_initcall(omap_serial_early_init);
@@ -709,149 +174,50 @@ 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 omap_device *od;
- 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
+ struct omap_uart_port_info *pdata;
+ char *name = DRIVER_NAME;
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;
-#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;
+ oh = omap_uart_hwmod_lookup(bdata->id);
+ if (!oh)
+ return;
- if (uart->errata & UART_ERRATA_FIFO_FULL_ABORT) {
- p->serial_in = serial_in_override;
- p->serial_out = serial_out_override;
+ pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+ if (!pdata) {
+ pr_err("Memory allocation for UART pdata failed\n");
+ return;
}
- pdata = &ports[0];
- pdata_size = 2 * sizeof(struct plat_serial8250_port);
-#else
-
- name = DRIVER_NAME;
+ /* Enable the MDR1 errata for OMAP3 */
+ if (cpu_is_omap34xx())
+ pdata->errata |= UART_ERRATA_i202_MDR1_ACCESS;
- 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.irqflags = IRQF_SHARED;
- omap_up.flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
+ omap_uart_idle_init(pdata, bdata->id);
- pdata = &omap_up;
- pdata_size = sizeof(struct omap_uart_port_info);
-#endif
+ pdata->uartclk = OMAP24XX_BASE_BAUD * 16;
+ pdata->flags = UPF_BOOT_AUTOCONF;
+ if (bdata->id == omap_uart_con_id)
+ pdata->console_uart = true;
- if (WARN_ON(!oh))
- return;
-
- od = omap_device_build(name, uart->num, oh, pdata, pdata_size,
- omap_uart_latency,
- ARRAY_SIZE(omap_uart_latency), false);
+ od = omap_device_build(name, bdata->id, oh, pdata,
+ sizeof(*pdata), omap_uart_latency,
+ ARRAY_SIZE(omap_uart_latency), false);
WARN(IS_ERR(od), "Could not build omap_device for %s: %s.\n",
name, oh->name);
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);
- uart->pdev = &od->pdev;
-
- oh->dev_attr = uart;
-
- console_lock(); /* in case the earlycon is on the UART */
-
- /*
- * Because of early UART probing, UART did not get idled
- * on init. Now that omap_device is ready, ensure full idle
- * before doing omap_device_enable().
- */
- omap_hwmod_idle(uart->oh);
-
- 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);
-
- /*
- * 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)) {
+ if (((cpu_is_omap34xx() || cpu_is_omap44xx()) && bdata->pads) ||
+ (pdata->wk_en && pdata->wk_mask)) {
device_init_wakeup(&od->pdev.dev, true);
- DEV_CREATE_FILE(&od->pdev.dev, &dev_attr_sleep_timeout);
}
-
- /* Enable the MDR1 errata for OMAP3 */
- if (cpu_is_omap34xx() && !cpu_is_ti816x())
- uart->errata |= UART_ERRATA_i202_MDR1_ACCESS;
}
/**
@@ -863,15 +229,14 @@ 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 < OMAP_MAX_HSUART_PORTS; i++) {
+ bdata.id = i;
bdata.flags = 0;
bdata.pads = NULL;
bdata.pads_cnt = 0;
omap_serial_init_port(&bdata);
-
}
}
diff --git a/arch/arm/plat-omap/include/plat/omap-serial.h b/arch/arm/plat-omap/include/plat/omap-serial.h
index 2682043..f9bc7ef 100644
--- a/arch/arm/plat-omap/include/plat/omap-serial.h
+++ b/arch/arm/plat-omap/include/plat/omap-serial.h
@@ -56,13 +56,18 @@
#define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA
+#define UART_ERRATA_i202_MDR1_ACCESS BIT(0)
+
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 */
- unsigned long irqflags; /* request_irq flags */
upf_t flags; /* UPF_* flags */
+ unsigned int errata;
+ unsigned int console_uart;
+
+ void __iomem *wk_st;
+ void __iomem *wk_en;
+ u32 wk_mask;
};
struct uart_omap_dma {
@@ -100,6 +105,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;
/*
@@ -111,6 +119,13 @@ struct uart_omap_port {
unsigned char msr_saved_flags;
char name[20];
unsigned long port_activity;
+ struct timer_list inactivity_timer;
+ unsigned int errata;
+ int can_sleep;
+
+ void __iomem *wk_st;
+ void __iomem *wk_en;
+ u32 wk_mask;
};
#endif /* __OMAP_SERIAL_H__ */
--
1.7.1
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 5/7] Serial: OMAP: add runtime pm support for omap-serial driver
2011-02-28 14:39 [PATCH 0/7] OMAP2+: UART: runtime conversion + cleanup Govindraj.R
` (3 preceding siblings ...)
2011-02-28 14:39 ` [PATCH 4/7] OMAP2+: UART: Remove uart clock handling code serial.c Govindraj.R
@ 2011-02-28 14:39 ` Govindraj.R
2011-03-05 1:59 ` Kevin Hilman
2011-02-28 14:39 ` [PATCH 6/7] OMAP: Serial: Allow UART parameters to be configured from board file Govindraj.R
2011-02-28 14:39 ` [PATCH 7/7] Serial: OMAP2+: Make the RX_TIMEOUT for DMA configurable for each UART Govindraj.R
6 siblings, 1 reply; 25+ messages in thread
From: Govindraj.R @ 2011-02-28 14:39 UTC (permalink / raw)
To: linux-arm-kernel
Adapts omap-serial driver to use pm_runtime api's.
1.) Populate reg values to uart port which can be used for context restore.
2.) Moved Erratum handling func to driver from serial.c
3.) adding port_enable/disable func to enable/disable given uart port.
4.) using prepare/resume api's to cut and enable back uart func_clks.
5.) using timer to set flag to cut uart clocks based on this flag in
sram_idle path.
Signed-off-by: Govindraj.R <govindraj.raja@ti.com>
---
drivers/tty/serial/omap-serial.c | 304 +++++++++++++++++++++++++++++++++++---
1 files changed, 283 insertions(+), 21 deletions(-)
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index d40924a..bc877b9 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -33,10 +33,21 @@
#include <linux/clk.h>
#include <linux/serial_core.h>
#include <linux/irq.h>
+#include <linux/pm_runtime.h>
#include <plat/dma.h>
#include <plat/dmtimer.h>
#include <plat/omap-serial.h>
+#include <plat/serial.h>
+#include <plat/omap_device.h>
+
+#ifdef CONFIG_SERIAL_OMAP_CONSOLE
+#define omap_uart_console(port) ((port)->cons && (port)->cons->index == (port)->line)
+#else
+#define omap_uart_console(port) NULL
+#endif
+
+#define OMAP_UART_CLK_PUT_DELAY (5 * HZ)
static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS];
@@ -44,6 +55,7 @@ static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS];
static void uart_tx_dma_callback(int lch, u16 ch_status, void *data);
static void serial_omap_rx_timeout(unsigned long uart_no);
static int serial_omap_start_rxdma(struct uart_omap_port *up);
+static void omap_uart_mdr1_errataset(struct uart_omap_port *up);
static inline unsigned int serial_in(struct uart_omap_port *up, int offset)
{
@@ -90,6 +102,73 @@ serial_omap_get_divisor(struct uart_port *port, unsigned int baud)
return port->uartclk/(baud * divisor);
}
+static void omap_uart_smart_idle(struct uart_omap_port *up)
+{
+ struct platform_device *pdev = up->pdev;
+ struct omap_device *od = container_of(pdev, struct omap_device, pdev);
+
+ omap_hwmod_set_slave_idlemode(od->hwmods[0], HWMOD_IDLEMODE_SMART);
+}
+
+static void serial_omap_port_disable(struct uart_omap_port *up)
+{
+ if (!pm_runtime_suspended(&up->pdev->dev)) {
+ del_timer(&up->inactivity_timer);
+ if (omap_uart_console(&up->port))
+ console_stop(up->port.cons);
+
+ pm_runtime_put_sync(&up->pdev->dev);
+ }
+}
+
+static void serial_omap_inactivity_timer(unsigned long uart_no)
+{
+ struct uart_omap_port *up = ui[uart_no];
+
+ up->can_sleep = 1;
+ omap_uart_smart_idle(up);
+}
+
+static void serial_omap_port_enable(struct uart_omap_port *up)
+{
+ if (pm_runtime_suspended(&up->pdev->dev)) {
+ if (omap_uart_console(&up->port))
+ console_start(up->port.cons);
+
+ pm_runtime_get_sync(&up->pdev->dev);
+ }
+
+ up->can_sleep = 0;
+ mod_timer(&up->inactivity_timer, jiffies + OMAP_UART_CLK_PUT_DELAY);
+}
+
+void omap_uart_prepare_idle(int num)
+{
+ struct uart_omap_port *up = ui[num];
+
+ if (up && up->can_sleep)
+ serial_omap_port_disable(up);
+}
+
+void omap_uart_resume_idle(int num)
+{
+ struct uart_omap_port *up = ui[num];
+ struct omap_device *od;
+ struct platform_device *pdev;
+
+ if (!up)
+ return;
+
+ pdev = up->pdev;
+ od = container_of(pdev, struct omap_device, pdev);
+
+ if (omap_hmwod_pad_wakeup_status(od->hwmods[0]) == true)
+ serial_omap_port_enable(up);
+
+ if (up->wk_st && (__raw_readl(up->wk_st) & up->wk_mask))
+ serial_omap_port_enable(up);
+}
+
static void serial_omap_stop_rxdma(struct uart_omap_port *up)
{
if (up->uart_dma.rx_dma_used) {
@@ -105,6 +184,7 @@ static void serial_omap_enable_ms(struct uart_port *port)
{
struct uart_omap_port *up = (struct uart_omap_port *)port;
+ serial_omap_port_enable(up);
dev_dbg(up->port.dev, "serial_omap_enable_ms+%d\n", up->pdev->id);
up->ier |= UART_IER_MSI;
serial_out(up, UART_IER, up->ier);
@@ -114,6 +194,7 @@ static void serial_omap_stop_tx(struct uart_port *port)
{
struct uart_omap_port *up = (struct uart_omap_port *)port;
+ serial_omap_port_enable(up);
if (up->use_dma &&
up->uart_dma.tx_dma_channel != OMAP_UART_DMA_CH_FREE) {
/*
@@ -137,6 +218,7 @@ static void serial_omap_stop_rx(struct uart_port *port)
{
struct uart_omap_port *up = (struct uart_omap_port *)port;
+ serial_omap_port_enable(up);
if (up->use_dma)
serial_omap_stop_rxdma(up);
up->ier &= ~UART_IER_RLSI;
@@ -258,6 +340,7 @@ static void serial_omap_start_tx(struct uart_port *port)
unsigned int start;
int ret = 0;
+ serial_omap_port_enable(up);
if (!up->use_dma) {
serial_omap_enable_ier_thri(up);
return;
@@ -351,6 +434,7 @@ static inline irqreturn_t serial_omap_irq(int irq, void *dev_id)
unsigned int iir, lsr;
unsigned long flags;
+ serial_omap_port_enable(up);
iir = serial_in(up, UART_IIR);
if (iir & UART_IIR_NO_INT)
return IRQ_NONE;
@@ -385,6 +469,7 @@ static unsigned int serial_omap_tx_empty(struct uart_port *port)
unsigned long flags = 0;
unsigned int ret = 0;
+ serial_omap_port_enable(up);
dev_dbg(up->port.dev, "serial_omap_tx_empty+%d\n", up->pdev->id);
spin_lock_irqsave(&up->port.lock, flags);
ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
@@ -399,6 +484,7 @@ static unsigned int serial_omap_get_mctrl(struct uart_port *port)
unsigned char status;
unsigned int ret = 0;
+ serial_omap_port_enable(up);
status = check_modem_status(up);
dev_dbg(up->port.dev, "serial_omap_get_mctrl+%d\n", up->pdev->id);
@@ -419,6 +505,7 @@ static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl)
unsigned char mcr = 0;
dev_dbg(up->port.dev, "serial_omap_set_mctrl+%d\n", up->pdev->id);
+ serial_omap_port_enable(up);
if (mctrl & TIOCM_RTS)
mcr |= UART_MCR_RTS;
if (mctrl & TIOCM_DTR)
@@ -440,6 +527,7 @@ static void serial_omap_break_ctl(struct uart_port *port, int break_state)
unsigned long flags = 0;
dev_dbg(up->port.dev, "serial_omap_break_ctl+%d\n", up->pdev->id);
+ serial_omap_port_enable(up);
spin_lock_irqsave(&up->port.lock, flags);
if (break_state == -1)
up->lcr |= UART_LCR_SBC;
@@ -465,6 +553,7 @@ static int serial_omap_startup(struct uart_port *port)
dev_dbg(up->port.dev, "serial_omap_startup+%d\n", up->pdev->id);
+ serial_omap_port_enable(up);
/*
* Clear the FIFO buffers and disable them.
* (they will be reenabled in set_termios())
@@ -530,6 +619,8 @@ static void serial_omap_shutdown(struct uart_port *port)
unsigned long flags = 0;
dev_dbg(up->port.dev, "serial_omap_shutdown+%d\n", up->pdev->id);
+
+ serial_omap_port_enable(up);
/*
* Disable interrupts from this port
*/
@@ -668,6 +759,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)
@@ -677,6 +772,7 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
* Ok, we're now changing the port state. Do it with
* interrupts disabled.
*/
+ serial_omap_port_enable(up);
spin_lock_irqsave(&up->port.lock, flags);
/*
@@ -755,8 +851,11 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
serial_out(up, UART_MCR, up->mcr);
/* Protocol, Baud Rate, and Interrupt Settings */
+ if (up->errata & UART_ERRATA_i202_MDR1_ACCESS)
+ omap_uart_mdr1_errataset(up);
+ else
+ serial_out(up, UART_OMAP_MDR1, up->mdr1);
- serial_out(up, UART_OMAP_MDR1, UART_OMAP_MDR1_DISABLE);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
up->efr = serial_in(up, UART_EFR);
@@ -766,8 +865,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);
@@ -777,9 +876,14 @@ 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
+ up->mdr1 = UART_OMAP_MDR1_16X_MODE;
+
+ if (up->errata & UART_ERRATA_i202_MDR1_ACCESS)
+ omap_uart_mdr1_errataset(up);
else
- serial_out(up, UART_OMAP_MDR1, UART_OMAP_MDR1_16X_MODE);
+ serial_out(up, UART_OMAP_MDR1, up->mdr1);
/* Hardware Flow Control Configuration */
@@ -818,6 +922,8 @@ serial_omap_pm(struct uart_port *port, unsigned int state,
unsigned char efr;
dev_dbg(up->port.dev, "serial_omap_pm+%d\n", up->pdev->id);
+
+ serial_omap_port_enable(up);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
efr = serial_in(up, UART_EFR);
serial_out(up, UART_EFR, efr | UART_EFR_ECB);
@@ -827,6 +933,8 @@ 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)
+ serial_omap_port_disable(up);
}
static void serial_omap_release_port(struct uart_port *port)
@@ -904,6 +1012,8 @@ static inline void wait_for_xmitr(struct uart_omap_port *up)
static void serial_omap_poll_put_char(struct uart_port *port, unsigned char ch)
{
struct uart_omap_port *up = (struct uart_omap_port *)port;
+
+ serial_omap_port_enable(up);
wait_for_xmitr(up);
serial_out(up, UART_TX, ch);
}
@@ -911,8 +1021,10 @@ static void serial_omap_poll_put_char(struct uart_port *port, unsigned char ch)
static int serial_omap_poll_get_char(struct uart_port *port)
{
struct uart_omap_port *up = (struct uart_omap_port *)port;
- unsigned int status = serial_in(up, UART_LSR);
+ unsigned int status;
+ serial_omap_port_enable(up);
+ status = serial_in(up, UART_LSR);
if (!(status & UART_LSR_DR))
return NO_POLL_CHAR;
@@ -922,7 +1034,6 @@ static int serial_omap_poll_get_char(struct uart_port *port)
#endif /* CONFIG_CONSOLE_POLL */
#ifdef CONFIG_SERIAL_OMAP_CONSOLE
-
static struct uart_omap_port *serial_omap_console_ports[4];
static struct uart_driver serial_omap_reg;
@@ -931,6 +1042,7 @@ static void serial_omap_console_putchar(struct uart_port *port, int ch)
{
struct uart_omap_port *up = (struct uart_omap_port *)port;
+ serial_omap_port_enable(up);
wait_for_xmitr(up);
serial_out(up, UART_TX, ch);
}
@@ -944,6 +1056,7 @@ serial_omap_console_write(struct console *co, const char *s,
unsigned int ier;
int locked = 1;
+ serial_omap_port_enable(up);
local_irq_save(flags);
if (up->port.sysrq)
locked = 0;
@@ -1058,22 +1171,25 @@ 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)
+ if (up) {
uart_suspend_port(&serial_omap_reg, &up->port);
+ serial_omap_port_disable(up);
+ }
+
return 0;
}
-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);
+
return 0;
}
@@ -1221,9 +1337,10 @@ static void uart_tx_dma_callback(int lch, u16 ch_status, void *data)
static int serial_omap_probe(struct platform_device *pdev)
{
- struct uart_omap_port *up;
+ struct uart_omap_port *up = NULL;
struct resource *mem, *irq, *dma_tx, *dma_rx;
struct omap_uart_port_info *omap_up_info = pdev->dev.platform_data;
+ struct omap_device *od;
int ret = -ENOSPC;
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1273,12 +1390,23 @@ 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, mem->end - mem->start);
+
+ if (!up->port.membase) {
+ dev_err(&pdev->dev, "can't ioremap UART\n");
+ ret = -ENOMEM;
+ goto err1;
+ }
+
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;
+ up->errata = omap_up_info->errata;
+
+ up->wk_st = omap_up_info->wk_st;
+ up->wk_en = omap_up_info->wk_en;
+ up->wk_mask = omap_up_info->wk_mask;
if (omap_up_info->dma_enabled) {
up->uart_dma.uart_dma_tx = dma_tx->start;
@@ -1291,19 +1419,35 @@ static int serial_omap_probe(struct platform_device *pdev)
up->uart_dma.tx_dma_channel = OMAP_UART_DMA_CH_FREE;
up->uart_dma.rx_dma_channel = OMAP_UART_DMA_CH_FREE;
}
+ init_timer(&(up->inactivity_timer));
+ up->inactivity_timer.function = serial_omap_inactivity_timer;
+ up->inactivity_timer.data = up->pdev->id;
+
+ pm_runtime_enable(&pdev->dev);
+ pm_runtime_irq_safe(&pdev->dev);
+
+ if (omap_up_info->console_uart) {
+ od = container_of(pdev, struct omap_device, pdev);
+ omap_hwmod_idle(od->hwmods[0]);
+ serial_omap_port_enable(up);
+ }
ui[pdev->id] = up;
serial_omap_add_console_port(up);
ret = uart_add_one_port(&serial_omap_reg, &up->port);
if (ret != 0)
- goto do_release_region;
+ goto err1;
+ dev_set_drvdata(&pdev->dev, up);
platform_set_drvdata(pdev, up);
+
return 0;
err:
dev_err(&pdev->dev, "[UART%d]: failure [%s]: %d\n",
pdev->id, __func__, ret);
+err1:
+ kfree(up);
do_release_region:
release_mem_region(mem->start, (mem->end - mem->start) + 1);
return ret;
@@ -1315,20 +1459,138 @@ static int serial_omap_remove(struct platform_device *dev)
platform_set_drvdata(dev, NULL);
if (up) {
+ pm_runtime_disable(&up->pdev->dev);
uart_remove_one_port(&serial_omap_reg, &up->port);
kfree(up);
}
return 0;
}
+/*
+ * Work Around for Errata i202 (3430 - 1.12, 3630 - 1.6)
+ * The access to uart register after MDR1 Access
+ * causes UART to corrupt data.
+ *
+ * Need a delay =
+ * 5 L4 clock cycles + 5 UART functional clock cycle (@48MHz = ~0.2uS)
+ * give 10 times as much
+ */
+static void omap_uart_mdr1_errataset(struct uart_omap_port *up)
+{
+ u8 timeout = 255;
+
+ serial_out(up, UART_OMAP_MDR1, up->mdr1);
+ udelay(2);
+ serial_out(up, UART_FCR, up->fcr | UART_FCR_CLEAR_XMIT |
+ UART_FCR_CLEAR_RCVR);
+ /*
+ * Wait for FIFO to empty: when empty, RX_FIFO_E bit is 0 and
+ * TX_FIFO_E bit is 1.
+ */
+ while (UART_LSR_THRE != (serial_in(up, UART_LSR) &
+ (UART_LSR_THRE | UART_LSR_DR))) {
+ timeout--;
+ if (!timeout) {
+ /* Should *never* happen. we warn and carry on */
+ dev_crit(&up->pdev->dev, "Errata i202: timedout %x\n",
+ serial_in(up, UART_LSR));
+ break;
+ }
+ udelay(1);
+ }
+}
+
+static void omap_uart_restore_context(struct uart_omap_port *up)
+{
+ u16 efr = 0;
+
+ if (up->errata & UART_ERRATA_i202_MDR1_ACCESS)
+ omap_uart_mdr1_errataset(up);
+ else
+ serial_out(up, UART_OMAP_MDR1, up->mdr1);
+ serial_out(up, UART_LCR, 0xBF); /* Config B mode */
+ efr = serial_in(up, UART_EFR);
+ serial_out(up, UART_EFR, UART_EFR_ECB);
+ serial_out(up, UART_LCR, 0x0); /* Operational mode */
+ serial_out(up, UART_IER, 0x0);
+ serial_out(up, UART_LCR, 0xBF); /* Config B mode */
+ serial_out(up, UART_DLL, up->dll);
+ serial_out(up, UART_DLM, up->dlh);
+ serial_out(up, UART_LCR, 0x0); /* Operational mode */
+ serial_out(up, UART_IER, up->ier);
+ serial_out(up, UART_FCR, up->fcr);
+ serial_out(up, UART_LCR, 0x80);
+ serial_out(up, UART_MCR, up->mcr);
+ serial_out(up, UART_LCR, 0xBF); /* Config B mode */
+ serial_out(up, UART_EFR, efr);
+ serial_out(up, UART_LCR, UART_LCR_WLEN8);
+ if (up->errata & UART_ERRATA_i202_MDR1_ACCESS)
+ omap_uart_mdr1_errataset(up);
+ else
+ /* UART 16x mode */
+ serial_out(up, UART_OMAP_MDR1, up->mdr1);
+}
+
+static void omap_uart_enable_wakeup(struct uart_omap_port *up)
+{
+ /* Set wake-enable bit */
+ if (up->wk_en && up->wk_mask) {
+ u32 v = __raw_readl(up->wk_en);
+ v |= up->wk_mask;
+ __raw_writel(v, up->wk_en);
+ }
+}
+
+static void omap_uart_disable_wakeup(struct uart_omap_port *up)
+{
+ /* Clear wake-enable bit */
+ if (up->wk_en && up->wk_mask) {
+ u32 v = __raw_readl(up->wk_en);
+ v &= ~up->wk_mask;
+ __raw_writel(v, up->wk_en);
+ }
+}
+
+static int omap_serial_runtime_suspend(struct device *dev)
+{
+ struct uart_omap_port *up = dev_get_drvdata(dev);
+
+ if (!up)
+ goto done;
+
+ if (device_may_wakeup(&up->pdev->dev))
+ omap_uart_enable_wakeup(up);
+ else
+ omap_uart_disable_wakeup(up);
+done:
+ return 0;
+}
+
+static int omap_serial_runtime_resume(struct device *dev)
+{
+ struct uart_omap_port *up = dev_get_drvdata(dev);
+
+ if (!up)
+ goto done;
+
+ omap_uart_restore_context(up);
+done:
+ return 0;
+}
+
+static const struct dev_pm_ops omap_serial_dev_pm_ops = {
+ .suspend = serial_omap_suspend,
+ .resume = serial_omap_resume,
+ .runtime_suspend = omap_serial_runtime_suspend,
+ .runtime_resume = omap_serial_runtime_resume,
+};
+
static struct platform_driver serial_omap_driver = {
.probe = serial_omap_probe,
.remove = serial_omap_remove,
-
- .suspend = serial_omap_suspend,
- .resume = serial_omap_resume,
.driver = {
.name = DRIVER_NAME,
+ .pm = &omap_serial_dev_pm_ops,
},
};
--
1.7.1
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 5/7] Serial: OMAP: add runtime pm support for omap-serial driver
2011-02-28 14:39 ` [PATCH 5/7] Serial: OMAP: add runtime pm support for omap-serial driver Govindraj.R
@ 2011-03-05 1:59 ` Kevin Hilman
2011-03-08 14:04 ` Govindraj
0 siblings, 1 reply; 25+ messages in thread
From: Kevin Hilman @ 2011-03-05 1:59 UTC (permalink / raw)
To: linux-arm-kernel
"Govindraj.R" <govindraj.raja@ti.com> writes:
> Adapts omap-serial driver to use pm_runtime api's.
>
> 1.) Populate reg values to uart port which can be used for context restore.
> 2.) Moved Erratum handling func to driver from serial.c
> 3.) adding port_enable/disable func to enable/disable given uart port.
> 4.) using prepare/resume api's to cut and enable back uart func_clks.
> 5.) using timer to set flag to cut uart clocks based on this flag in
> sram_idle path.
At least the errata handling should be in a separate patch as it's not
related to runtime PM.
Also, please be sure to test building this driver as a module. Because
of direct access to hwmod in this patch, it will currently build as a module.
> Signed-off-by: Govindraj.R <govindraj.raja@ti.com>
> ---
> drivers/tty/serial/omap-serial.c | 304 +++++++++++++++++++++++++++++++++++---
> 1 files changed, 283 insertions(+), 21 deletions(-)
>
> diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
> index d40924a..bc877b9 100644
> --- a/drivers/tty/serial/omap-serial.c
> +++ b/drivers/tty/serial/omap-serial.c
> @@ -33,10 +33,21 @@
> #include <linux/clk.h>
> #include <linux/serial_core.h>
> #include <linux/irq.h>
> +#include <linux/pm_runtime.h>
>
> #include <plat/dma.h>
> #include <plat/dmtimer.h>
> #include <plat/omap-serial.h>
> +#include <plat/serial.h>
> +#include <plat/omap_device.h>
> +
> +#ifdef CONFIG_SERIAL_OMAP_CONSOLE
> +#define omap_uart_console(port) ((port)->cons && (port)->cons->index == (port)->line)
> +#else
> +#define omap_uart_console(port) NULL
> +#endif
> +
> +#define OMAP_UART_CLK_PUT_DELAY (5 * HZ)
>
> static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS];
>
> @@ -44,6 +55,7 @@ static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS];
> static void uart_tx_dma_callback(int lch, u16 ch_status, void *data);
> static void serial_omap_rx_timeout(unsigned long uart_no);
> static int serial_omap_start_rxdma(struct uart_omap_port *up);
> +static void omap_uart_mdr1_errataset(struct uart_omap_port *up);
>
> static inline unsigned int serial_in(struct uart_omap_port *up, int offset)
> {
> @@ -90,6 +102,73 @@ serial_omap_get_divisor(struct uart_port *port, unsigned int baud)
> return port->uartclk/(baud * divisor);
> }
>
> +static void omap_uart_smart_idle(struct uart_omap_port *up)
> +{
> + struct platform_device *pdev = up->pdev;
> + struct omap_device *od = container_of(pdev, struct omap_device, pdev);
> +
> + omap_hwmod_set_slave_idlemode(od->hwmods[0], HWMOD_IDLEMODE_SMART);
> +}
> +
> +static void serial_omap_port_disable(struct uart_omap_port *up)
> +{
> + if (!pm_runtime_suspended(&up->pdev->dev)) {
> + del_timer(&up->inactivity_timer);
> + if (omap_uart_console(&up->port))
> + console_stop(up->port.cons);
> +
> + pm_runtime_put_sync(&up->pdev->dev);
> + }
> +}
This function should not be needed.
The timer should be replaced by the auto-suspend feature of runtime PM.
Instead of calling omap_port_disable() callers should call
pm_runtime_put_autosuspend(), and the console_stop() should be part of
the ->runtime_suspend() callback.
Also, why do you check for pm_runtime_suspended()? Just call it for
every time and we get runtime PM use-counting and statistics for free
and the ->runtime_suspend() callback will be called when the usecount
goes to zero.
> +static void serial_omap_inactivity_timer(unsigned long uart_no)
> +{
> + struct uart_omap_port *up = ui[uart_no];
> +
> + up->can_sleep = 1;
> + omap_uart_smart_idle(up);
> +}
This will not be needed if using the autosuspend feature.
> +static void serial_omap_port_enable(struct uart_omap_port *up)
> +{
> + if (pm_runtime_suspended(&up->pdev->dev)) {
> + if (omap_uart_console(&up->port))
> + console_start(up->port.cons);
> +
> + pm_runtime_get_sync(&up->pdev->dev);
> + }
> +
> + up->can_sleep = 0;
> + mod_timer(&up->inactivity_timer, jiffies + OMAP_UART_CLK_PUT_DELAY);
> +}
Similarily to the disable side, callers of this function should call
pm_runtime_get_sync() and the console_start() should be in the
->runtime_resume method.
Again, no need to check pm_runtime_suspended() since the runtime PM core
does usecounting already.
> +void omap_uart_prepare_idle(int num)
> +{
> + struct uart_omap_port *up = ui[num];
> +
> + if (up && up->can_sleep)
> + serial_omap_port_disable(up);
pm_runtime_put_autosuspend()
> +}
> +
> +void omap_uart_resume_idle(int num)
> +{
> + struct uart_omap_port *up = ui[num];
> + struct omap_device *od;
> + struct platform_device *pdev;
> +
> + if (!up)
> + return;
> +
> + pdev = up->pdev;
> + od = container_of(pdev, struct omap_device, pdev);
od = to_omap_device(pdev);
> + if (omap_hmwod_pad_wakeup_status(od->hwmods[0]) == true)
> + serial_omap_port_enable(up);
> +
> + if (up->wk_st && (__raw_readl(up->wk_st) & up->wk_mask))
> + serial_omap_port_enable(up);
> +}
c.f. comments from PATCH 2/7
Also, direct hwmod access and PRCM accesses do not belong in drivers.
Until it is understood why wakeups are not working, these hacks should
stay in mach-omap2/serial.c
> static void serial_omap_stop_rxdma(struct uart_omap_port *up)
> {
> if (up->uart_dma.rx_dma_used) {
> @@ -105,6 +184,7 @@ static void serial_omap_enable_ms(struct uart_port *port)
> {
> struct uart_omap_port *up = (struct uart_omap_port *)port;
>
> + serial_omap_port_enable(up);
pm_runtime_put_autosuspend()
similarily for all calls to omap_port_enable()
> dev_dbg(up->port.dev, "serial_omap_enable_ms+%d\n", up->pdev->id);
> up->ier |= UART_IER_MSI;
> serial_out(up, UART_IER, up->ier);
> @@ -114,6 +194,7 @@ static void serial_omap_stop_tx(struct uart_port *port)
> {
> struct uart_omap_port *up = (struct uart_omap_port *)port;
>
> + serial_omap_port_enable(up);
> if (up->use_dma &&
> up->uart_dma.tx_dma_channel != OMAP_UART_DMA_CH_FREE) {
> /*
> @@ -137,6 +218,7 @@ static void serial_omap_stop_rx(struct uart_port *port)
> {
> struct uart_omap_port *up = (struct uart_omap_port *)port;
>
> + serial_omap_port_enable(up);
> if (up->use_dma)
> serial_omap_stop_rxdma(up);
> up->ier &= ~UART_IER_RLSI;
> @@ -258,6 +340,7 @@ static void serial_omap_start_tx(struct uart_port *port)
> unsigned int start;
> int ret = 0;
>
> + serial_omap_port_enable(up);
> if (!up->use_dma) {
> serial_omap_enable_ier_thri(up);
> return;
> @@ -351,6 +434,7 @@ static inline irqreturn_t serial_omap_irq(int irq, void *dev_id)
> unsigned int iir, lsr;
> unsigned long flags;
>
> + serial_omap_port_enable(up);
> iir = serial_in(up, UART_IIR);
> if (iir & UART_IIR_NO_INT)
> return IRQ_NONE;
> @@ -385,6 +469,7 @@ static unsigned int serial_omap_tx_empty(struct uart_port *port)
> unsigned long flags = 0;
> unsigned int ret = 0;
>
> + serial_omap_port_enable(up);
> dev_dbg(up->port.dev, "serial_omap_tx_empty+%d\n", up->pdev->id);
> spin_lock_irqsave(&up->port.lock, flags);
> ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
> @@ -399,6 +484,7 @@ static unsigned int serial_omap_get_mctrl(struct uart_port *port)
> unsigned char status;
> unsigned int ret = 0;
>
> + serial_omap_port_enable(up);
> status = check_modem_status(up);
> dev_dbg(up->port.dev, "serial_omap_get_mctrl+%d\n", up->pdev->id);
>
> @@ -419,6 +505,7 @@ static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl)
> unsigned char mcr = 0;
>
> dev_dbg(up->port.dev, "serial_omap_set_mctrl+%d\n", up->pdev->id);
> + serial_omap_port_enable(up);
> if (mctrl & TIOCM_RTS)
> mcr |= UART_MCR_RTS;
> if (mctrl & TIOCM_DTR)
> @@ -440,6 +527,7 @@ static void serial_omap_break_ctl(struct uart_port *port, int break_state)
> unsigned long flags = 0;
>
> dev_dbg(up->port.dev, "serial_omap_break_ctl+%d\n", up->pdev->id);
> + serial_omap_port_enable(up);
> spin_lock_irqsave(&up->port.lock, flags);
> if (break_state == -1)
> up->lcr |= UART_LCR_SBC;
> @@ -465,6 +553,7 @@ static int serial_omap_startup(struct uart_port *port)
>
> dev_dbg(up->port.dev, "serial_omap_startup+%d\n", up->pdev->id);
>
> + serial_omap_port_enable(up);
> /*
> * Clear the FIFO buffers and disable them.
> * (they will be reenabled in set_termios())
> @@ -530,6 +619,8 @@ static void serial_omap_shutdown(struct uart_port *port)
> unsigned long flags = 0;
>
> dev_dbg(up->port.dev, "serial_omap_shutdown+%d\n", up->pdev->id);
> +
> + serial_omap_port_enable(up);
> /*
> * Disable interrupts from this port
> */
> @@ -668,6 +759,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)
> @@ -677,6 +772,7 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
> * Ok, we're now changing the port state. Do it with
> * interrupts disabled.
> */
> + serial_omap_port_enable(up);
> spin_lock_irqsave(&up->port.lock, flags);
>
> /*
> @@ -755,8 +851,11 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
> serial_out(up, UART_MCR, up->mcr);
>
> /* Protocol, Baud Rate, and Interrupt Settings */
> + if (up->errata & UART_ERRATA_i202_MDR1_ACCESS)
> + omap_uart_mdr1_errataset(up);
> + else
> + serial_out(up, UART_OMAP_MDR1, up->mdr1);
>
> - serial_out(up, UART_OMAP_MDR1, UART_OMAP_MDR1_DISABLE);
> serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
>
> up->efr = serial_in(up, UART_EFR);
> @@ -766,8 +865,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);
> @@ -777,9 +876,14 @@ 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
> + up->mdr1 = UART_OMAP_MDR1_16X_MODE;
> +
> + if (up->errata & UART_ERRATA_i202_MDR1_ACCESS)
> + omap_uart_mdr1_errataset(up);
> else
> - serial_out(up, UART_OMAP_MDR1, UART_OMAP_MDR1_16X_MODE);
> + serial_out(up, UART_OMAP_MDR1, up->mdr1);
>
> /* Hardware Flow Control Configuration */
>
> @@ -818,6 +922,8 @@ serial_omap_pm(struct uart_port *port, unsigned int state,
> unsigned char efr;
>
> dev_dbg(up->port.dev, "serial_omap_pm+%d\n", up->pdev->id);
> +
> + serial_omap_port_enable(up);
> serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
> efr = serial_in(up, UART_EFR);
> serial_out(up, UART_EFR, efr | UART_EFR_ECB);
> @@ -827,6 +933,8 @@ 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)
> + serial_omap_port_disable(up);
FYI... this change doesn't apply when basing on the commit you mentioned
in PATCH 0/7.
> }
>
> static void serial_omap_release_port(struct uart_port *port)
> @@ -904,6 +1012,8 @@ static inline void wait_for_xmitr(struct uart_omap_port *up)
> static void serial_omap_poll_put_char(struct uart_port *port, unsigned char ch)
> {
> struct uart_omap_port *up = (struct uart_omap_port *)port;
> +
> + serial_omap_port_enable(up);
> wait_for_xmitr(up);
> serial_out(up, UART_TX, ch);
> }
> @@ -911,8 +1021,10 @@ static void serial_omap_poll_put_char(struct uart_port *port, unsigned char ch)
> static int serial_omap_poll_get_char(struct uart_port *port)
> {
> struct uart_omap_port *up = (struct uart_omap_port *)port;
> - unsigned int status = serial_in(up, UART_LSR);
> + unsigned int status;
>
> + serial_omap_port_enable(up);
> + status = serial_in(up, UART_LSR);
> if (!(status & UART_LSR_DR))
> return NO_POLL_CHAR;
>
> @@ -922,7 +1034,6 @@ static int serial_omap_poll_get_char(struct uart_port *port)
> #endif /* CONFIG_CONSOLE_POLL */
>
> #ifdef CONFIG_SERIAL_OMAP_CONSOLE
> -
> static struct uart_omap_port *serial_omap_console_ports[4];
>
> static struct uart_driver serial_omap_reg;
> @@ -931,6 +1042,7 @@ static void serial_omap_console_putchar(struct uart_port *port, int ch)
> {
> struct uart_omap_port *up = (struct uart_omap_port *)port;
>
> + serial_omap_port_enable(up);
> wait_for_xmitr(up);
> serial_out(up, UART_TX, ch);
> }
> @@ -944,6 +1056,7 @@ serial_omap_console_write(struct console *co, const char *s,
> unsigned int ier;
> int locked = 1;
>
> + serial_omap_port_enable(up);
> local_irq_save(flags);
> if (up->port.sysrq)
> locked = 0;
> @@ -1058,22 +1171,25 @@ 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)
> + if (up) {
> uart_suspend_port(&serial_omap_reg, &up->port);
> + serial_omap_port_disable(up);
> + }
> +
> return 0;
> }
>
> -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);
> +
> return 0;
> }
>
> @@ -1221,9 +1337,10 @@ static void uart_tx_dma_callback(int lch, u16 ch_status, void *data)
>
> static int serial_omap_probe(struct platform_device *pdev)
> {
> - struct uart_omap_port *up;
> + struct uart_omap_port *up = NULL;
> struct resource *mem, *irq, *dma_tx, *dma_rx;
> struct omap_uart_port_info *omap_up_info = pdev->dev.platform_data;
> + struct omap_device *od;
> int ret = -ENOSPC;
>
> mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> @@ -1273,12 +1390,23 @@ 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, mem->end - mem->start);
> +
> + if (!up->port.membase) {
> + dev_err(&pdev->dev, "can't ioremap UART\n");
> + ret = -ENOMEM;
> + goto err1;
> + }
> +
> 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;
> + up->errata = omap_up_info->errata;
> +
> + up->wk_st = omap_up_info->wk_st;
> + up->wk_en = omap_up_info->wk_en;
> + up->wk_mask = omap_up_info->wk_mask;
>
> if (omap_up_info->dma_enabled) {
> up->uart_dma.uart_dma_tx = dma_tx->start;
> @@ -1291,19 +1419,35 @@ static int serial_omap_probe(struct platform_device *pdev)
> up->uart_dma.tx_dma_channel = OMAP_UART_DMA_CH_FREE;
> up->uart_dma.rx_dma_channel = OMAP_UART_DMA_CH_FREE;
> }
> + init_timer(&(up->inactivity_timer));
> + up->inactivity_timer.function = serial_omap_inactivity_timer;
> + up->inactivity_timer.data = up->pdev->id;
> +
> + pm_runtime_enable(&pdev->dev);
> + pm_runtime_irq_safe(&pdev->dev);
The changelog should describe why the IRQ-safe mode is needed.
> + if (omap_up_info->console_uart) {
> + od = container_of(pdev, struct omap_device, pdev);
> + omap_hwmod_idle(od->hwmods[0]);
This was only in mach-omap2/serial.c because the early UART probing was
accessing registers. With this driver becoming runtime PM aware, this
hack should not be needed, and the
oh->flags |= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET;
should be removed from mach-omap2/serial.c
> + serial_omap_port_enable(up);
> + }
>
> ui[pdev->id] = up;
> serial_omap_add_console_port(up);
>
> ret = uart_add_one_port(&serial_omap_reg, &up->port);
> if (ret != 0)
> - goto do_release_region;
> + goto err1;
>
> + dev_set_drvdata(&pdev->dev, up);
> platform_set_drvdata(pdev, up);
> +
> return 0;
> err:
> dev_err(&pdev->dev, "[UART%d]: failure [%s]: %d\n",
> pdev->id, __func__, ret);
> +err1:
> + kfree(up);
> do_release_region:
> release_mem_region(mem->start, (mem->end - mem->start) + 1);
> return ret;
> @@ -1315,20 +1459,138 @@ static int serial_omap_remove(struct platform_device *dev)
>
> platform_set_drvdata(dev, NULL);
> if (up) {
> + pm_runtime_disable(&up->pdev->dev);
> uart_remove_one_port(&serial_omap_reg, &up->port);
> kfree(up);
> }
> return 0;
> }
>
> +/*
> + * Work Around for Errata i202 (3430 - 1.12, 3630 - 1.6)
> + * The access to uart register after MDR1 Access
> + * causes UART to corrupt data.
> + *
> + * Need a delay =
> + * 5 L4 clock cycles + 5 UART functional clock cycle (@48MHz = ~0.2uS)
> + * give 10 times as much
> + */
> +static void omap_uart_mdr1_errataset(struct uart_omap_port *up)
> +{
> + u8 timeout = 255;
> +
> + serial_out(up, UART_OMAP_MDR1, up->mdr1);
> + udelay(2);
> + serial_out(up, UART_FCR, up->fcr | UART_FCR_CLEAR_XMIT |
> + UART_FCR_CLEAR_RCVR);
> + /*
> + * Wait for FIFO to empty: when empty, RX_FIFO_E bit is 0 and
> + * TX_FIFO_E bit is 1.
> + */
> + while (UART_LSR_THRE != (serial_in(up, UART_LSR) &
> + (UART_LSR_THRE | UART_LSR_DR))) {
> + timeout--;
> + if (!timeout) {
> + /* Should *never* happen. we warn and carry on */
> + dev_crit(&up->pdev->dev, "Errata i202: timedout %x\n",
> + serial_in(up, UART_LSR));
> + break;
> + }
> + udelay(1);
> + }
> +}
> +
> +static void omap_uart_restore_context(struct uart_omap_port *up)
> +{
> + u16 efr = 0;
> +
> + if (up->errata & UART_ERRATA_i202_MDR1_ACCESS)
> + omap_uart_mdr1_errataset(up);
> + else
> + serial_out(up, UART_OMAP_MDR1, up->mdr1);
> + serial_out(up, UART_LCR, 0xBF); /* Config B mode */
> + efr = serial_in(up, UART_EFR);
> + serial_out(up, UART_EFR, UART_EFR_ECB);
> + serial_out(up, UART_LCR, 0x0); /* Operational mode */
> + serial_out(up, UART_IER, 0x0);
> + serial_out(up, UART_LCR, 0xBF); /* Config B mode */
> + serial_out(up, UART_DLL, up->dll);
> + serial_out(up, UART_DLM, up->dlh);
> + serial_out(up, UART_LCR, 0x0); /* Operational mode */
> + serial_out(up, UART_IER, up->ier);
> + serial_out(up, UART_FCR, up->fcr);
> + serial_out(up, UART_LCR, 0x80);
> + serial_out(up, UART_MCR, up->mcr);
> + serial_out(up, UART_LCR, 0xBF); /* Config B mode */
> + serial_out(up, UART_EFR, efr);
> + serial_out(up, UART_LCR, UART_LCR_WLEN8);
> + if (up->errata & UART_ERRATA_i202_MDR1_ACCESS)
> + omap_uart_mdr1_errataset(up);
> + else
> + /* UART 16x mode */
> + serial_out(up, UART_OMAP_MDR1, up->mdr1);
> +}
> +
> +static void omap_uart_enable_wakeup(struct uart_omap_port *up)
> +{
> + /* Set wake-enable bit */
> + if (up->wk_en && up->wk_mask) {
> + u32 v = __raw_readl(up->wk_en);
> + v |= up->wk_mask;
> + __raw_writel(v, up->wk_en);
> + }
> +}
> +
> +static void omap_uart_disable_wakeup(struct uart_omap_port *up)
> +{
> + /* Clear wake-enable bit */
> + if (up->wk_en && up->wk_mask) {
> + u32 v = __raw_readl(up->wk_en);
> + v &= ~up->wk_mask;
> + __raw_writel(v, up->wk_en);
> + }
> +}
Again, driver should not be doing direct PRCM accesses here.
For now, how about leaving these also in mach-omap2/serial.c and calling
them via pdata function pointers:
if (pdata->enable_wakeup)
pdata->enable_wakeup()
> +static int omap_serial_runtime_suspend(struct device *dev)
> +{
> + struct uart_omap_port *up = dev_get_drvdata(dev);
> +
> + if (!up)
> + goto done;
> +
> + if (device_may_wakeup(&up->pdev->dev))
> + omap_uart_enable_wakeup(up);
> + else
> + omap_uart_disable_wakeup(up);
> +done:
> + return 0;
> +}
> +
> +static int omap_serial_runtime_resume(struct device *dev)
> +{
> + struct uart_omap_port *up = dev_get_drvdata(dev);
> +
> + if (!up)
> + goto done;
> +
> + omap_uart_restore_context(up);
> +done:
> + return 0;
> +}
> +
> +static const struct dev_pm_ops omap_serial_dev_pm_ops = {
> + .suspend = serial_omap_suspend,
> + .resume = serial_omap_resume,
> + .runtime_suspend = omap_serial_runtime_suspend,
> + .runtime_resume = omap_serial_runtime_resume,
> +};
> +
> static struct platform_driver serial_omap_driver = {
> .probe = serial_omap_probe,
> .remove = serial_omap_remove,
> -
> - .suspend = serial_omap_suspend,
> - .resume = serial_omap_resume,
> .driver = {
> .name = DRIVER_NAME,
> + .pm = &omap_serial_dev_pm_ops,
> },
> };
Kevin
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 5/7] Serial: OMAP: add runtime pm support for omap-serial driver
2011-03-05 1:59 ` Kevin Hilman
@ 2011-03-08 14:04 ` Govindraj
2011-03-09 1:48 ` Kevin Hilman
0 siblings, 1 reply; 25+ messages in thread
From: Govindraj @ 2011-03-08 14:04 UTC (permalink / raw)
To: linux-arm-kernel
On Sat, Mar 5, 2011 at 7:29 AM, Kevin Hilman <khilman@ti.com> wrote:
> "Govindraj.R" <govindraj.raja@ti.com> writes:
>
>> Adapts omap-serial driver to use pm_runtime api's.
>>
>> 1.) Populate reg values to uart port which can be used for context restore.
>> 2.) Moved Erratum handling func to driver from serial.c
>> 3.) adding port_enable/disable func to enable/disable given uart port.
>> 4.) using prepare/resume api's to cut and enable back uart func_clks.
>> 5.) using timer to set flag to cut uart clocks based on this flag in
>> ? ? sram_idle path.
>
> At least the errata handling should be in a separate patch as it's not
> related to runtime PM.
>
ok. will move to separate patch
> Also, please be sure to test building this driver as a module. ?Because
> of direct access to hwmod in this patch, it will currently build as a module.
>
yes will check this out. I can check this only
on zoom board I think as most of other boards
seem to use omap-uart as console uart.
>> Signed-off-by: Govindraj.R <govindraj.raja@ti.com>
>> ---
>> ?drivers/tty/serial/omap-serial.c | ?304 +++++++++++++++++++++++++++++++++++---
>> ?1 files changed, 283 insertions(+), 21 deletions(-)
>>
>> diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
>> index d40924a..bc877b9 100644
>> --- a/drivers/tty/serial/omap-serial.c
>> +++ b/drivers/tty/serial/omap-serial.c
>> @@ -33,10 +33,21 @@
>> ?#include <linux/clk.h>
>> ?#include <linux/serial_core.h>
>> ?#include <linux/irq.h>
>> +#include <linux/pm_runtime.h>
>>
>> ?#include <plat/dma.h>
>> ?#include <plat/dmtimer.h>
>> ?#include <plat/omap-serial.h>
>> +#include <plat/serial.h>
>> +#include <plat/omap_device.h>
>> +
>> +#ifdef CONFIG_SERIAL_OMAP_CONSOLE
>> +#define omap_uart_console(port) ((port)->cons && (port)->cons->index == (port)->line)
>> +#else
>> +#define omap_uart_console(port) ? ? ?NULL
>> +#endif
>> +
>> +#define OMAP_UART_CLK_PUT_DELAY (5 * HZ)
>>
>> ?static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS];
>>
>> @@ -44,6 +55,7 @@ static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS];
>> ?static void uart_tx_dma_callback(int lch, u16 ch_status, void *data);
>> ?static void serial_omap_rx_timeout(unsigned long uart_no);
>> ?static int serial_omap_start_rxdma(struct uart_omap_port *up);
>> +static void omap_uart_mdr1_errataset(struct uart_omap_port *up);
>>
>> ?static inline unsigned int serial_in(struct uart_omap_port *up, int offset)
>> ?{
>> @@ -90,6 +102,73 @@ serial_omap_get_divisor(struct uart_port *port, unsigned int baud)
>> ? ? ? return port->uartclk/(baud * divisor);
>> ?}
>>
>> +static void omap_uart_smart_idle(struct uart_omap_port *up)
>> +{
>> + ? ? struct platform_device *pdev = up->pdev;
>> + ? ? struct omap_device *od = container_of(pdev, struct omap_device, pdev);
>> +
>> + ? ? omap_hwmod_set_slave_idlemode(od->hwmods[0], HWMOD_IDLEMODE_SMART);
>> +}
>> +
>> +static void serial_omap_port_disable(struct uart_omap_port *up)
>> +{
>> + ? ? if (!pm_runtime_suspended(&up->pdev->dev)) {
>> + ? ? ? ? ? ? del_timer(&up->inactivity_timer);
>> + ? ? ? ? ? ? if (omap_uart_console(&up->port))
>> + ? ? ? ? ? ? ? ? ? ? console_stop(up->port.cons);
>> +
>> + ? ? ? ? ? ? pm_runtime_put_sync(&up->pdev->dev);
>> + ? ? }
>> +}
>
> This function should not be needed.
>
> The timer should be replaced by the auto-suspend feature of runtime PM.
If I use autosuspend based on timer runtime framework
will disable clocks based on autosuspend timeout.
But if I cut clocks outside sram idle path module level wakeup
will not work. if I cut func clocks outside prepare for idle
wake_up is a problem. So I am going with existing model
where we are cutting clocks in prepare idle and enabling the
clock back in resume_idle based on wakeup event as any other
combination doesn't seem to work.
[As stated in other thread to reproduce the issue
with module level wakeup]
Even with existing framework if I try to experiment
by cutting clocks after uart timeout in allow_sleep
func, module level wakeup doesn't seem to happen.
>
> Instead of calling omap_port_disable() callers should call
> pm_runtime_put_autosuspend(), and the console_stop() should be part of
> the ->runtime_suspend() callback.
>
> Also, why do you check for pm_runtime_suspended()? ?Just call it for
> every time and we get runtime PM use-counting and statistics for free
> and the ->runtime_suspend() callback will be called when the usecount
> goes to zero.
>
Yes correct, but I can't balance the put_sync and get_sync
as said above. I can call put_sync only once in prepare_idle
to cut clocks. But having put_sync outside prepare_idle, if
clocks are cut module level wakeup doesn't seem to happen.
>> +static void serial_omap_inactivity_timer(unsigned long uart_no)
>> +{
>> + ? ? struct uart_omap_port *up = ui[uart_no];
>> +
>> + ? ? up->can_sleep = 1;
>> + ? ? omap_uart_smart_idle(up);
>> +}
>
> This will not be needed if using the autosuspend feature.
Using autosuspend, module level wakeup will not happen
since autosuspend cuts clocks outside prepare_idle
based on autosuspend timeout.
>
>> +static void serial_omap_port_enable(struct uart_omap_port *up)
>> +{
>> + ? ? if (pm_runtime_suspended(&up->pdev->dev)) {
>> + ? ? ? ? ? ? if (omap_uart_console(&up->port))
>> + ? ? ? ? ? ? ? ? ? ? console_start(up->port.cons);
>> +
>> + ? ? ? ? ? ? pm_runtime_get_sync(&up->pdev->dev);
>> + ? ? }
>> +
>> + ? ? up->can_sleep = 0;
>> + ? ? mod_timer(&up->inactivity_timer, jiffies + OMAP_UART_CLK_PUT_DELAY);
>> +}
>
> Similarily to the disable side, callers of this function should call
> pm_runtime_get_sync() and the console_start() should be in the
> ->runtime_resume method.
Agree, will move console_start/console_stop func
to runtime sync callbacks.
>
> Again, no need to check pm_runtime_suspended() since the runtime PM core
> does usecounting already.
>
Agree, but balancing put_sync is an issue currently
for uart with get_sync as we can use put_sync
just once in prepare_idle.
>> +void omap_uart_prepare_idle(int num)
>> +{
>> + ? ? struct uart_omap_port *up = ui[num];
>> +
>> + ? ? if (up && up->can_sleep)
>> + ? ? ? ? ? ? serial_omap_port_disable(up);
>
> ? ? ? ? ? ? ? ?pm_runtime_put_autosuspend()
>
>> +}
>> +
>> +void omap_uart_resume_idle(int num)
>> +{
>> + ? ? struct uart_omap_port *up = ui[num];
>> + ? ? struct omap_device *od;
>> + ? ? struct platform_device *pdev;
>> +
>> + ? ? if (!up)
>> + ? ? ? ? ? ? return;
>> +
>> + ? ? pdev = up->pdev;
>> + ? ? od = container_of(pdev, struct omap_device, pdev);
>
> ? ? ? ?od = to_omap_device(pdev);
>
>> + ? ? if (omap_hmwod_pad_wakeup_status(od->hwmods[0]) == true)
>> + ? ? ? ? ? ? serial_omap_port_enable(up);
>> +
>> + ? ? if (up->wk_st && (__raw_readl(up->wk_st) & up->wk_mask))
>> + ? ? ? ? ? ? serial_omap_port_enable(up);
>> +}
>
> c.f. comments from PATCH 2/7
>
> Also, direct hwmod access and PRCM accesses do not belong in drivers.
>
> Until it is understood why wakeups are not working, these hacks should
> stay in mach-omap2/serial.c
>
Ok. I will add callbacks to handle wk_mask and wk_st
will retain these funcs in serial.c but new format of this func can use
uart_port id based on which i can select wk_st and wk_mask
values and then read/write into these.
>> ?static void serial_omap_stop_rxdma(struct uart_omap_port *up)
>> ?{
>> ? ? ? if (up->uart_dma.rx_dma_used) {
>> @@ -105,6 +184,7 @@ static void serial_omap_enable_ms(struct uart_port *port)
>> ?{
>> ? ? ? struct uart_omap_port *up = (struct uart_omap_port *)port;
>>
>> + ? ? serial_omap_port_enable(up);
>
> ? ? ? ?pm_runtime_put_autosuspend()
>
> similarily for all calls to omap_port_enable()
>
>> ? ? ? dev_dbg(up->port.dev, "serial_omap_enable_ms+%d\n", up->pdev->id);
>> ? ? ? up->ier |= UART_IER_MSI;
>> ? ? ? serial_out(up, UART_IER, up->ier);
>> @@ -114,6 +194,7 @@ static void serial_omap_stop_tx(struct uart_port *port)
>> ?{
>> ? ? ? struct uart_omap_port *up = (struct uart_omap_port *)port;
>>
>> + ? ? serial_omap_port_enable(up);
>> ? ? ? if (up->use_dma &&
>> ? ? ? ? ? ? ? up->uart_dma.tx_dma_channel != OMAP_UART_DMA_CH_FREE) {
>> ? ? ? ? ? ? ? /*
>> @@ -137,6 +218,7 @@ static void serial_omap_stop_rx(struct uart_port *port)
>> ?{
>> ? ? ? struct uart_omap_port *up = (struct uart_omap_port *)port;
>>
>> + ? ? serial_omap_port_enable(up);
>> ? ? ? if (up->use_dma)
>> ? ? ? ? ? ? ? serial_omap_stop_rxdma(up);
>> ? ? ? up->ier &= ~UART_IER_RLSI;
>> @@ -258,6 +340,7 @@ static void serial_omap_start_tx(struct uart_port *port)
>> ? ? ? unsigned int start;
>> ? ? ? int ret = 0;
>>
>> + ? ? serial_omap_port_enable(up);
>> ? ? ? if (!up->use_dma) {
>> ? ? ? ? ? ? ? serial_omap_enable_ier_thri(up);
>> ? ? ? ? ? ? ? return;
>> @@ -351,6 +434,7 @@ static inline irqreturn_t serial_omap_irq(int irq, void *dev_id)
>> ? ? ? unsigned int iir, lsr;
>> ? ? ? unsigned long flags;
>>
>> + ? ? serial_omap_port_enable(up);
>> ? ? ? iir = serial_in(up, UART_IIR);
>> ? ? ? if (iir & UART_IIR_NO_INT)
>> ? ? ? ? ? ? ? return IRQ_NONE;
>> @@ -385,6 +469,7 @@ static unsigned int serial_omap_tx_empty(struct uart_port *port)
>> ? ? ? unsigned long flags = 0;
>> ? ? ? unsigned int ret = 0;
>>
>> + ? ? serial_omap_port_enable(up);
>> ? ? ? dev_dbg(up->port.dev, "serial_omap_tx_empty+%d\n", up->pdev->id);
>> ? ? ? spin_lock_irqsave(&up->port.lock, flags);
>> ? ? ? ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
>> @@ -399,6 +484,7 @@ static unsigned int serial_omap_get_mctrl(struct uart_port *port)
>> ? ? ? unsigned char status;
>> ? ? ? unsigned int ret = 0;
>>
>> + ? ? serial_omap_port_enable(up);
>> ? ? ? status = check_modem_status(up);
>> ? ? ? dev_dbg(up->port.dev, "serial_omap_get_mctrl+%d\n", up->pdev->id);
>>
>> @@ -419,6 +505,7 @@ static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl)
>> ? ? ? unsigned char mcr = 0;
>>
>> ? ? ? dev_dbg(up->port.dev, "serial_omap_set_mctrl+%d\n", up->pdev->id);
>> + ? ? serial_omap_port_enable(up);
>> ? ? ? if (mctrl & TIOCM_RTS)
>> ? ? ? ? ? ? ? mcr |= UART_MCR_RTS;
>> ? ? ? if (mctrl & TIOCM_DTR)
>> @@ -440,6 +527,7 @@ static void serial_omap_break_ctl(struct uart_port *port, int break_state)
>> ? ? ? unsigned long flags = 0;
>>
>> ? ? ? dev_dbg(up->port.dev, "serial_omap_break_ctl+%d\n", up->pdev->id);
>> + ? ? serial_omap_port_enable(up);
>> ? ? ? spin_lock_irqsave(&up->port.lock, flags);
>> ? ? ? if (break_state == -1)
>> ? ? ? ? ? ? ? up->lcr |= UART_LCR_SBC;
>> @@ -465,6 +553,7 @@ static int serial_omap_startup(struct uart_port *port)
>>
>> ? ? ? dev_dbg(up->port.dev, "serial_omap_startup+%d\n", up->pdev->id);
>>
>> + ? ? serial_omap_port_enable(up);
>> ? ? ? /*
>> ? ? ? ?* Clear the FIFO buffers and disable them.
>> ? ? ? ?* (they will be reenabled in set_termios())
>> @@ -530,6 +619,8 @@ static void serial_omap_shutdown(struct uart_port *port)
>> ? ? ? unsigned long flags = 0;
>>
>> ? ? ? dev_dbg(up->port.dev, "serial_omap_shutdown+%d\n", up->pdev->id);
>> +
>> + ? ? serial_omap_port_enable(up);
>> ? ? ? /*
>> ? ? ? ?* Disable interrupts from this port
>> ? ? ? ?*/
>> @@ -668,6 +759,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)
>> @@ -677,6 +772,7 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
>> ? ? ? ?* Ok, we're now changing the port state. Do it with
>> ? ? ? ?* interrupts disabled.
>> ? ? ? ?*/
>> + ? ? serial_omap_port_enable(up);
>> ? ? ? spin_lock_irqsave(&up->port.lock, flags);
>>
>> ? ? ? /*
>> @@ -755,8 +851,11 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
>> ? ? ? serial_out(up, UART_MCR, up->mcr);
>>
>> ? ? ? /* Protocol, Baud Rate, and Interrupt Settings */
>> + ? ? if (up->errata & UART_ERRATA_i202_MDR1_ACCESS)
>> + ? ? ? ? ? ? omap_uart_mdr1_errataset(up);
>> + ? ? else
>> + ? ? ? ? ? ? serial_out(up, UART_OMAP_MDR1, up->mdr1);
>>
>> - ? ? serial_out(up, UART_OMAP_MDR1, UART_OMAP_MDR1_DISABLE);
>> ? ? ? serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
>>
>> ? ? ? up->efr = serial_in(up, UART_EFR);
>> @@ -766,8 +865,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);
>> @@ -777,9 +876,14 @@ 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
>> + ? ? ? ? ? ? up->mdr1 = UART_OMAP_MDR1_16X_MODE;
>> +
>> + ? ? if (up->errata & UART_ERRATA_i202_MDR1_ACCESS)
>> + ? ? ? ? ? ? omap_uart_mdr1_errataset(up);
>> ? ? ? else
>> - ? ? ? ? ? ? serial_out(up, UART_OMAP_MDR1, UART_OMAP_MDR1_16X_MODE);
>> + ? ? ? ? ? ? serial_out(up, UART_OMAP_MDR1, up->mdr1);
>>
>> ? ? ? /* Hardware Flow Control Configuration */
>>
>> @@ -818,6 +922,8 @@ serial_omap_pm(struct uart_port *port, unsigned int state,
>> ? ? ? unsigned char efr;
>>
>> ? ? ? dev_dbg(up->port.dev, "serial_omap_pm+%d\n", up->pdev->id);
>> +
>> + ? ? serial_omap_port_enable(up);
>> ? ? ? serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
>> ? ? ? efr = serial_in(up, UART_EFR);
>> ? ? ? serial_out(up, UART_EFR, efr | UART_EFR_ECB);
>> @@ -827,6 +933,8 @@ 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)
>> + ? ? ? ? ? ? serial_omap_port_disable(up);
>
> FYI... this change doesn't apply when basing on the commit you mentioned
> in PATCH 0/7.
>
this patch series will apply on top the
dependency patches specified in cover letter.
Specially needs
https://patchwork.kernel.org/patch/501211/
without which it will fail here.
>> ?}
>>
>> ?static void serial_omap_release_port(struct uart_port *port)
>> @@ -904,6 +1012,8 @@ static inline void wait_for_xmitr(struct uart_omap_port *up)
>> ?static void serial_omap_poll_put_char(struct uart_port *port, unsigned char ch)
>> ?{
>> ? ? ? struct uart_omap_port *up = (struct uart_omap_port *)port;
>> +
>> + ? ? serial_omap_port_enable(up);
>> ? ? ? wait_for_xmitr(up);
>> ? ? ? serial_out(up, UART_TX, ch);
>> ?}
>> @@ -911,8 +1021,10 @@ static void serial_omap_poll_put_char(struct uart_port *port, unsigned char ch)
>> ?static int serial_omap_poll_get_char(struct uart_port *port)
>> ?{
>> ? ? ? struct uart_omap_port *up = (struct uart_omap_port *)port;
>> - ? ? unsigned int status = serial_in(up, UART_LSR);
>> + ? ? unsigned int status;
>>
>> + ? ? serial_omap_port_enable(up);
>> + ? ? status = serial_in(up, UART_LSR);
>> ? ? ? if (!(status & UART_LSR_DR))
>> ? ? ? ? ? ? ? return NO_POLL_CHAR;
>>
>> @@ -922,7 +1034,6 @@ static int serial_omap_poll_get_char(struct uart_port *port)
>> ?#endif /* CONFIG_CONSOLE_POLL */
>>
>> ?#ifdef CONFIG_SERIAL_OMAP_CONSOLE
>> -
>> ?static struct uart_omap_port *serial_omap_console_ports[4];
>>
>> ?static struct uart_driver serial_omap_reg;
>> @@ -931,6 +1042,7 @@ static void serial_omap_console_putchar(struct uart_port *port, int ch)
>> ?{
>> ? ? ? struct uart_omap_port *up = (struct uart_omap_port *)port;
>>
>> + ? ? serial_omap_port_enable(up);
>> ? ? ? wait_for_xmitr(up);
>> ? ? ? serial_out(up, UART_TX, ch);
>> ?}
>> @@ -944,6 +1056,7 @@ serial_omap_console_write(struct console *co, const char *s,
>> ? ? ? unsigned int ier;
>> ? ? ? int locked = 1;
>>
>> + ? ? serial_omap_port_enable(up);
>> ? ? ? local_irq_save(flags);
>> ? ? ? if (up->port.sysrq)
>> ? ? ? ? ? ? ? locked = 0;
>> @@ -1058,22 +1171,25 @@ 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)
>> + ? ? if (up) {
>> ? ? ? ? ? ? ? uart_suspend_port(&serial_omap_reg, &up->port);
>> + ? ? ? ? ? ? serial_omap_port_disable(up);
>> + ? ? }
>> +
>> ? ? ? return 0;
>> ?}
>>
>> -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);
>> +
>> ? ? ? return 0;
>> ?}
>>
>> @@ -1221,9 +1337,10 @@ static void uart_tx_dma_callback(int lch, u16 ch_status, void *data)
>>
>> ?static int serial_omap_probe(struct platform_device *pdev)
>> ?{
>> - ? ? struct uart_omap_port ? *up;
>> + ? ? struct uart_omap_port ? *up = NULL;
>> ? ? ? struct resource ? ? ? ? *mem, *irq, *dma_tx, *dma_rx;
>> ? ? ? struct omap_uart_port_info *omap_up_info = pdev->dev.platform_data;
>> + ? ? struct omap_device *od;
>> ? ? ? int ret = -ENOSPC;
>>
>> ? ? ? mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> @@ -1273,12 +1390,23 @@ 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, mem->end - mem->start);
>> +
>> + ? ? if (!up->port.membase) {
>> + ? ? ? ? ? ? dev_err(&pdev->dev, "can't ioremap UART\n");
>> + ? ? ? ? ? ? ret = -ENOMEM;
>> + ? ? ? ? ? ? goto err1;
>> + ? ? }
>> +
>> ? ? ? 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;
>> + ? ? up->errata = omap_up_info->errata;
>> +
>> + ? ? up->wk_st = omap_up_info->wk_st;
>> + ? ? up->wk_en = omap_up_info->wk_en;
>> + ? ? up->wk_mask = omap_up_info->wk_mask;
>>
>> ? ? ? if (omap_up_info->dma_enabled) {
>> ? ? ? ? ? ? ? up->uart_dma.uart_dma_tx = dma_tx->start;
>> @@ -1291,19 +1419,35 @@ static int serial_omap_probe(struct platform_device *pdev)
>> ? ? ? ? ? ? ? up->uart_dma.tx_dma_channel = OMAP_UART_DMA_CH_FREE;
>> ? ? ? ? ? ? ? up->uart_dma.rx_dma_channel = OMAP_UART_DMA_CH_FREE;
>> ? ? ? }
>> + ? ? init_timer(&(up->inactivity_timer));
>> + ? ? up->inactivity_timer.function = serial_omap_inactivity_timer;
>> + ? ? up->inactivity_timer.data = up->pdev->id;
>> +
>> + ? ? pm_runtime_enable(&pdev->dev);
>> + ? ? pm_runtime_irq_safe(&pdev->dev);
>
> The changelog should describe why the IRQ-safe mode is needed.
yes will add.
we need to use get_sync in irq_context hence needed.
>
>> + ? ? if (omap_up_info->console_uart) {
>> + ? ? ? ? ? ? od = container_of(pdev, struct omap_device, pdev);
>> + ? ? ? ? ? ? omap_hwmod_idle(od->hwmods[0]);
>
> This was only in mach-omap2/serial.c because the early UART probing was
> accessing registers. ?With this driver becoming runtime PM aware, this
> hack should not be needed, and the
>
> ? ? ? ?oh->flags |= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET;
>
> should be removed from mach-omap2/serial.c
Yes. Since any omap-uart can be used as
console uart and the console uart can be used
for earlyprintk's.
For earlyprintk's the early console driver will
use printch from debug macro to print through uart
during which hwmod is getting initialized
--> _setup
--> _idle
---> _disable_clocks
at this point of time while printch is happening and
hwmod disables uart clocks I dont have uart-console
driver available which can enable clocks back.
So I have to use those flags when earlyprintk
is enabled. I have added some more changes
into omap_serial_early_init which uses these flags
only when earlyprintk config is defined and
earlyprintk word is used in bootarg, snip below.
<<Function SNIP>>
==================================
static int __init omap_serial_early_init(void)
{
#ifdef CONFIG_EARLY_PRINTK
int i = 0;
char omap_tty_name[MAX_UART_HWMOD_NAME_LEN];
struct omap_hwmod *oh;
if (!cmdline_find_option("earlyprintk"))
return 0;
for (i = 0; i < OMAP_MAX_HSUART_PORTS; i++) {
snprintf(omap_tty_name, MAX_UART_HWMOD_NAME_LEN,
"%s%d", OMAP_SERIAL_NAME, i);
if (cmdline_find_option(omap_tty_name)) {
omap_uart_con_id = i;
oh = omap_uart_hwmod_lookup(i);
oh->flags |= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET;
return 0;
}
}
#endif
return 0;
}
core_initcall(omap_serial_early_init);
=========================================
>
>> + ? ? ? ? ? ? serial_omap_port_enable(up);
>> + ? ? }
>>
>> ? ? ? ui[pdev->id] = up;
>> ? ? ? serial_omap_add_console_port(up);
>>
>> ? ? ? ret = uart_add_one_port(&serial_omap_reg, &up->port);
>> ? ? ? if (ret != 0)
>> - ? ? ? ? ? ? goto do_release_region;
>> + ? ? ? ? ? ? goto err1;
>>
>> + ? ? dev_set_drvdata(&pdev->dev, up);
>> ? ? ? platform_set_drvdata(pdev, up);
>> +
>> ? ? ? return 0;
>> ?err:
>> ? ? ? dev_err(&pdev->dev, "[UART%d]: failure [%s]: %d\n",
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? pdev->id, __func__, ret);
>> +err1:
>> + ? ? kfree(up);
>> ?do_release_region:
>> ? ? ? release_mem_region(mem->start, (mem->end - mem->start) + 1);
>> ? ? ? return ret;
>> @@ -1315,20 +1459,138 @@ static int serial_omap_remove(struct platform_device *dev)
>>
>> ? ? ? platform_set_drvdata(dev, NULL);
>> ? ? ? if (up) {
>> + ? ? ? ? ? ? pm_runtime_disable(&up->pdev->dev);
>> ? ? ? ? ? ? ? uart_remove_one_port(&serial_omap_reg, &up->port);
>> ? ? ? ? ? ? ? kfree(up);
>> ? ? ? }
>> ? ? ? return 0;
>> ?}
>>
>> +/*
>> + * Work Around for Errata i202 (3430 - 1.12, 3630 - 1.6)
>> + * The access to uart register after MDR1 Access
>> + * causes UART to corrupt data.
>> + *
>> + * Need a delay =
>> + * 5 L4 clock cycles + 5 UART functional clock cycle (@48MHz = ~0.2uS)
>> + * give 10 times as much
>> + */
>> +static void omap_uart_mdr1_errataset(struct uart_omap_port *up)
>> +{
>> + ? ? u8 timeout = 255;
>> +
>> + ? ? serial_out(up, UART_OMAP_MDR1, up->mdr1);
>> + ? ? udelay(2);
>> + ? ? serial_out(up, UART_FCR, up->fcr | UART_FCR_CLEAR_XMIT |
>> + ? ? ? ? ? ? ? ? ? ? UART_FCR_CLEAR_RCVR);
>> + ? ? /*
>> + ? ? ?* Wait for FIFO to empty: when empty, RX_FIFO_E bit is 0 and
>> + ? ? ?* TX_FIFO_E bit is 1.
>> + ? ? ?*/
>> + ? ? while (UART_LSR_THRE != (serial_in(up, UART_LSR) &
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? (UART_LSR_THRE | UART_LSR_DR))) {
>> + ? ? ? ? ? ? timeout--;
>> + ? ? ? ? ? ? if (!timeout) {
>> + ? ? ? ? ? ? ? ? ? ? /* Should *never* happen. we warn and carry on */
>> + ? ? ? ? ? ? ? ? ? ? dev_crit(&up->pdev->dev, "Errata i202: timedout %x\n",
>> + ? ? ? ? ? ? ? ? ? ? serial_in(up, UART_LSR));
>> + ? ? ? ? ? ? ? ? ? ? break;
>> + ? ? ? ? ? ? }
>> + ? ? ? ? ? ? udelay(1);
>> + ? ? }
>> +}
>> +
>> +static void omap_uart_restore_context(struct uart_omap_port *up)
>> +{
>> + ? ? u16 efr = 0;
>> +
>> + ? ? if (up->errata & UART_ERRATA_i202_MDR1_ACCESS)
>> + ? ? ? ? ? ? omap_uart_mdr1_errataset(up);
>> + ? ? else
>> + ? ? ? ? ? ? serial_out(up, UART_OMAP_MDR1, up->mdr1);
>> + ? ? serial_out(up, UART_LCR, 0xBF); /* Config B mode */
>> + ? ? efr = serial_in(up, UART_EFR);
>> + ? ? serial_out(up, UART_EFR, UART_EFR_ECB);
>> + ? ? serial_out(up, UART_LCR, 0x0); /* Operational mode */
>> + ? ? serial_out(up, UART_IER, 0x0);
>> + ? ? serial_out(up, UART_LCR, 0xBF); /* Config B mode */
>> + ? ? serial_out(up, UART_DLL, up->dll);
>> + ? ? serial_out(up, UART_DLM, up->dlh);
>> + ? ? serial_out(up, UART_LCR, 0x0); /* Operational mode */
>> + ? ? serial_out(up, UART_IER, up->ier);
>> + ? ? serial_out(up, UART_FCR, up->fcr);
>> + ? ? serial_out(up, UART_LCR, 0x80);
>> + ? ? serial_out(up, UART_MCR, up->mcr);
>> + ? ? serial_out(up, UART_LCR, 0xBF); /* Config B mode */
>> + ? ? serial_out(up, UART_EFR, efr);
>> + ? ? serial_out(up, UART_LCR, UART_LCR_WLEN8);
>> + ? ? if (up->errata & UART_ERRATA_i202_MDR1_ACCESS)
>> + ? ? ? ? ? ? omap_uart_mdr1_errataset(up);
>> + ? ? else
>> + ? ? ? ? ? ? /* UART 16x mode */
>> + ? ? ? ? ? ? serial_out(up, UART_OMAP_MDR1, up->mdr1);
>> +}
>> +
>> +static void omap_uart_enable_wakeup(struct uart_omap_port *up)
>> +{
>> + ? ? /* Set wake-enable bit */
>> + ? ? if (up->wk_en && up->wk_mask) {
>> + ? ? ? ? ? ? u32 v = __raw_readl(up->wk_en);
>> + ? ? ? ? ? ? v |= up->wk_mask;
>> + ? ? ? ? ? ? __raw_writel(v, up->wk_en);
>> + ? ? }
>> +}
>> +
>> +static void omap_uart_disable_wakeup(struct uart_omap_port *up)
>> +{
>> + ? ? /* Clear wake-enable bit */
>> + ? ? if (up->wk_en && up->wk_mask) {
>> + ? ? ? ? ? ? u32 v = __raw_readl(up->wk_en);
>> + ? ? ? ? ? ? v &= ~up->wk_mask;
>> + ? ? ? ? ? ? __raw_writel(v, up->wk_en);
>> + ? ? }
>> +}
>
> Again, driver should not be doing direct PRCM accesses here.
>
> For now, how about leaving these also in mach-omap2/serial.c and calling
> them via pdata function pointers:
>
> ?if (pdata->enable_wakeup)
> ? ? ?pdata->enable_wakeup()
>
Agree will move these func's and use func. pointer.
--
Thanks,
Govindraj.R
>> +static int omap_serial_runtime_suspend(struct device *dev)
>> +{
>> + ? ? struct uart_omap_port *up = dev_get_drvdata(dev);
>> +
>> + ? ? if (!up)
>> + ? ? ? ? ? ? goto done;
>> +
>> + ? ? if (device_may_wakeup(&up->pdev->dev))
>> + ? ? ? ? ? ? omap_uart_enable_wakeup(up);
>> + ? ? else
>> + ? ? ? ? ? ? omap_uart_disable_wakeup(up);
>> +done:
>> + ? ? return 0;
>> +}
>> +
>> +static int omap_serial_runtime_resume(struct device *dev)
>> +{
>> + ? ? struct uart_omap_port *up = dev_get_drvdata(dev);
>> +
>> + ? ? if (!up)
>> + ? ? ? ? ? ? goto done;
>> +
>> + ? ? omap_uart_restore_context(up);
>> +done:
>> + ? ? return 0;
>> +}
>> +
>> +static const struct dev_pm_ops omap_serial_dev_pm_ops = {
>> + ? ? .suspend = serial_omap_suspend,
>> + ? ? .resume = serial_omap_resume,
>> + ? ? .runtime_suspend = omap_serial_runtime_suspend,
>> + ? ? .runtime_resume = omap_serial_runtime_resume,
>> +};
>> +
>> ?static struct platform_driver serial_omap_driver = {
>> ? ? ? .probe ? ? ? ? ?= serial_omap_probe,
>> ? ? ? .remove ? ? ? ? = serial_omap_remove,
>> -
>> - ? ? .suspend ? ? ? ?= serial_omap_suspend,
>> - ? ? .resume ? ? ? ? = serial_omap_resume,
>> ? ? ? .driver ? ? ? ? = {
>> ? ? ? ? ? ? ? .name ? = DRIVER_NAME,
>> + ? ? ? ? ? ? .pm = &omap_serial_dev_pm_ops,
>> ? ? ? },
>> ?};
>
> 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
>
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 5/7] Serial: OMAP: add runtime pm support for omap-serial driver
2011-03-08 14:04 ` Govindraj
@ 2011-03-09 1:48 ` Kevin Hilman
2011-03-09 2:02 ` Paul Walmsley
2011-03-09 15:07 ` Govindraj
0 siblings, 2 replies; 25+ messages in thread
From: Kevin Hilman @ 2011-03-09 1:48 UTC (permalink / raw)
To: linux-arm-kernel
Govindraj <govindraj.ti@gmail.com> writes:
[...]
>> This function should not be needed.
>>
>> The timer should be replaced by the auto-suspend feature of runtime PM.
>
> If I use autosuspend based on timer runtime framework
> will disable clocks based on autosuspend timeout.
>
> But if I cut clocks outside sram idle path module level wakeup
> will not work.
> if I cut func clocks outside prepare for idle
> wake_up is a problem.
As I mentioned in the other thread, module wakeups are not the problem,
rather the module generating the interrupt is the problem. So cutting
clocks outside prepare_for_idle path is not the problem. It's the
re-enabling of the clocks that is important.
> So I am going with existing model where we are cutting clocks in
> prepare idle and enabling the clock back in resume_idle based on
> wakeup event as any other combination doesn't seem to work.
>
> [As stated in other thread to reproduce the issue
> with module level wakeup]
>
> Even with existing framework if I try to experiment
> by cutting clocks after uart timeout in allow_sleep
> func, module level wakeup doesn't seem to happen.
>>
>> Instead of calling omap_port_disable() callers should call
>> pm_runtime_put_autosuspend(), and the console_stop() should be part of
>> the ->runtime_suspend() callback.
>>
>> Also, why do you check for pm_runtime_suspended()? ?Just call it for
>> every time and we get runtime PM use-counting and statistics for free
>> and the ->runtime_suspend() callback will be called when the usecount
>> goes to zero.
>>
>
> Yes correct, but I can't balance the put_sync and get_sync
> as said above. I can call put_sync only once in prepare_idle
> to cut clocks. But having put_sync outside prepare_idle, if
> clocks are cut module level wakeup doesn't seem to happen.
>
>
>>> +static void serial_omap_inactivity_timer(unsigned long uart_no)
>>> +{
>>> + ? ? struct uart_omap_port *up = ui[uart_no];
>>> +
>>> + ? ? up->can_sleep = 1;
>>> + ? ? omap_uart_smart_idle(up);
>>> +}
>>
>> This will not be needed if using the autosuspend feature.
>
> Using autosuspend, module level wakeup will not happen
> since autosuspend cuts clocks outside prepare_idle
> based on autosuspend timeout.
OK, I get the point. You mentioned module level wakeups about 10 times
in this message. ;)
However, rather than continue to hack around this problem we need to
understand the root cause. Thanks to Paul, I think I undersand the root
cause as explained in the other thread, and I think there's a relatively
easy way to make them work.
So here's an experiment to try with autosuspend. I suspect this will
work, just hack it up to prove the concept. If it works, we can make
something more generic. Here are a few alternatives to try. I may
experiment with some of them tomorrow as well, but please let me know
what you try:
Using autosuspend, clocks will get cut independently of the idle path.
Then, use the PRCM ISR detection of UART module wakeups to call the
UART's interrupt handler. The interrupt handler will pm_runtime_get(),
enable the clocks, and then take care of the interrupt. Done.
Alternatively, you could test it on current code by simply removing the
resume_from_idle call from the idle path and calling it instead from the
PRCM ISR when UART module wakeups are detected.
Another option to experiment with: use PRCM ISR to trigger a SW
interrupt of the UART IRQ (cf. MPU_INTC.INTCPS_ISR_SETn registers.)
This may be the cleanest approach, and not require calling into the
driver, but I'm not sure if the normal interrupt clearing process will
also clear the SW interrupt.
The best longer-term solution is will be to use the chained PRCM
interrupt handler[1] (not yet finished.) Using that, drivers could
directly register for their individual module wakeup interrupts.
Kevin
[1] http://marc.info/?l=linux-omap&m=129258489308837&w=2
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 5/7] Serial: OMAP: add runtime pm support for omap-serial driver
2011-03-09 1:48 ` Kevin Hilman
@ 2011-03-09 2:02 ` Paul Walmsley
2011-03-09 13:03 ` Govindraj
2011-03-09 15:07 ` Govindraj
1 sibling, 1 reply; 25+ messages in thread
From: Paul Walmsley @ 2011-03-09 2:02 UTC (permalink / raw)
To: linux-arm-kernel
Hi Govindraj,
what also would be good to find out is why the UART is apparently sending
asynchronous wakeups even when the driver doesn't set
SCR_REG.RX_CTS_WU_EN. This seems contrary to the expectation that 34xx
TRM vZH section 17.4.4.1.4.1 "Wake-up Interrupt" sets. Could you please
clarify under which circumstances the RX_CTS_WU_EN bit is used? I suppose
that, given that it's also mentioned under section 17.4.5.1.1 "Module
Power Savings", it might only be used when SLEEP_MODE is enabled.
- Paul
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 5/7] Serial: OMAP: add runtime pm support for omap-serial driver
2011-03-09 2:02 ` Paul Walmsley
@ 2011-03-09 13:03 ` Govindraj
0 siblings, 0 replies; 25+ messages in thread
From: Govindraj @ 2011-03-09 13:03 UTC (permalink / raw)
To: linux-arm-kernel
On Wed, Mar 9, 2011 at 7:32 AM, Paul Walmsley <paul@pwsan.com> wrote:
>
> Hi Govindraj,
>
> what also would be good to find out is why the UART is apparently sending
> asynchronous wakeups even when the driver doesn't set
> SCR_REG.RX_CTS_WU_EN. ?This seems contrary to the expectation that 34xx
> TRM vZH section 17.4.4.1.4.1 "Wake-up Interrupt" sets. ?Could you please
> clarify under which circumstances the RX_CTS_WU_EN bit is used? ?I suppose
> that, given that it's also mentioned under section 17.4.5.1.1 "Module
> Power Savings", it might only be used when SLEEP_MODE is enabled.
>
AFAIK, sleep_mode is used only for uart internal power saving
options if fifo's are empty which inturn can stop uart internal baud clock.
To enable back uart baud clock and start uart internal activity it
will depend on RX_CTS_WU_EN from scr to restart uart_baud_clock.
For system level powers saving like cutting uart_fclks
wakeup will depend on WER reg for wakeup event or io-pad
wakeup depending on power state.
Since I am cutting fclks directly I am depending on
WER reg wakeup events.
--
Thanks,
Govindraj.R
>
> - Paul
>
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 5/7] Serial: OMAP: add runtime pm support for omap-serial driver
2011-03-09 1:48 ` Kevin Hilman
2011-03-09 2:02 ` Paul Walmsley
@ 2011-03-09 15:07 ` Govindraj
2011-03-09 23:06 ` Kevin Hilman
1 sibling, 1 reply; 25+ messages in thread
From: Govindraj @ 2011-03-09 15:07 UTC (permalink / raw)
To: linux-arm-kernel
On Wed, Mar 9, 2011 at 7:18 AM, Kevin Hilman <khilman@ti.com> wrote:
> Govindraj <govindraj.ti@gmail.com> writes:
>
> [...]
>
>>> This function should not be needed.
>>>
>>> The timer should be replaced by the auto-suspend feature of runtime PM.
>>
>> If I use autosuspend based on timer runtime framework
>> will disable clocks based on autosuspend timeout.
>>
>> But if I cut clocks outside sram idle path module level wakeup
>> will not work.
>> if I cut func clocks outside prepare for idle
>> wake_up is a problem.
>
> As I mentioned in the other thread, module wakeups are not the problem,
> rather the module generating the interrupt is the problem. ?So cutting
> clocks outside prepare_for_idle path is not the problem. ?It's the
> re-enabling of the clocks that is important.
>
>> So I am going with existing model where we are cutting clocks in
>> prepare idle and enabling the clock back in resume_idle based on
>> wakeup event as any other combination doesn't seem to work.
>>
>> [As stated in other thread to reproduce the issue
>> with module level wakeup]
>>
>> Even with existing framework if I try to experiment
>> by cutting clocks after uart timeout in allow_sleep
>> func, module level wakeup doesn't seem to happen.
>>>
>>> Instead of calling omap_port_disable() callers should call
>>> pm_runtime_put_autosuspend(), and the console_stop() should be part of
>>> the ->runtime_suspend() callback.
>>>
>>> Also, why do you check for pm_runtime_suspended()? ?Just call it for
>>> every time and we get runtime PM use-counting and statistics for free
>>> and the ->runtime_suspend() callback will be called when the usecount
>>> goes to zero.
>>>
>>
>> Yes correct, but I can't balance the put_sync and get_sync
>> as said above. I can call put_sync only once in prepare_idle
>> to cut clocks. But having put_sync outside prepare_idle, if
>> clocks are cut module level wakeup doesn't seem to happen.
>>
>>
>>>> +static void serial_omap_inactivity_timer(unsigned long uart_no)
>>>> +{
>>>> + ? ? struct uart_omap_port *up = ui[uart_no];
>>>> +
>>>> + ? ? up->can_sleep = 1;
>>>> + ? ? omap_uart_smart_idle(up);
>>>> +}
>>>
>>> This will not be needed if using the autosuspend feature.
>>
>> Using autosuspend, module level wakeup will not happen
>> since autosuspend cuts clocks outside prepare_idle
>> based on autosuspend timeout.
>
> OK, I get the point. ?You mentioned module level wakeups about 10 times
> in this message. ?;)
>
> However, rather than continue to hack around this problem we need to
> understand the root cause. ?Thanks to Paul, I think I undersand the root
> cause as explained in the other thread, and I think there's a relatively
> easy way to make them work.
>
> So here's an experiment to try with autosuspend. ?I suspect this will
> work, just hack it up to prove the concept. ?If it works, we can make
> something more generic. ?Here are a few alternatives to try. ?I may
> experiment with some of them tomorrow as well, but please let me know
> what you try:
>
> Using autosuspend, clocks will get cut independently of the idle path.
> Then, use the PRCM ISR detection of UART module wakeups to call the
> UART's interrupt handler. ?The interrupt handler will pm_runtime_get(),
> enable the clocks, and then take care of the interrupt. ?Done.
>
> Alternatively, you could test it on current code by simply removing the
> resume_from_idle call from the idle path and calling it instead from the
> PRCM ISR when UART module wakeups are detected.
I remember doing similar experiment didn't seem to help,
>
> Another option to experiment with: use PRCM ISR to trigger a SW
> interrupt of the UART IRQ (cf. MPU_INTC.INTCPS_ISR_SETn registers.)
> This may be the cleanest approach, and not require calling into the
> driver, but I'm not sure if the normal interrupt clearing process will
> also clear the SW interrupt.
need to check this.
>
> The best longer-term solution is will be to use the chained PRCM
> interrupt handler[1] (not yet finished.) ?Using that, drivers could
> directly register for their individual module wakeup interrupts.
Agree.
>
> Kevin
>
> [1] http://marc.info/?l=linux-omap&m=129258489308837&w=2
>
>
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 5/7] Serial: OMAP: add runtime pm support for omap-serial driver
2011-03-09 15:07 ` Govindraj
@ 2011-03-09 23:06 ` Kevin Hilman
0 siblings, 0 replies; 25+ messages in thread
From: Kevin Hilman @ 2011-03-09 23:06 UTC (permalink / raw)
To: linux-arm-kernel
Govindraj <govindraj.ti@gmail.com> writes:
[...]
>>
>> So here's an experiment to try with autosuspend. ?I suspect this will
>> work, just hack it up to prove the concept. ?If it works, we can make
>> something more generic. ?Here are a few alternatives to try. ?I may
>> experiment with some of them tomorrow as well, but please let me know
>> what you try:
>>
>> Using autosuspend, clocks will get cut independently of the idle path.
>> Then, use the PRCM ISR detection of UART module wakeups to call the
>> UART's interrupt handler. ?The interrupt handler will pm_runtime_get(),
>> enable the clocks, and then take care of the interrupt. ?Done.
>>
>> Alternatively, you could test it on current code by simply removing the
>> resume_from_idle call from the idle path and calling it instead from the
>> PRCM ISR when UART module wakeups are detected.
>
> I remember doing similar experiment didn't seem to help,
>
To show it's possible, I did really hacky proof of concept, hard-coded
to UART3 console for n900/beagle, but at least it shows that this
approach can work, and the module-level wakeups are working and can be
used as the trigger for UART wakeup instead of resume_from_idle. Of
course, it still has problems with using serial after non-UART wakeups,
but once omap-serial is using runtime PM, that will no longer be an
issue.
My hacky branch is called pm-wip/uart-wkup and is in my pm git tree[1]
(based at the pm-core branch)
To test module-level wakeups (instead of IO-ring) I again forced CORE to
stay on during suspend, and tested wakeup from suspend on 3430/n900:
echo 3 > /debug/pm_debug/core_pwrdm/suspend
echo mem > /sys/power/state
Kevin
[1] git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-omap-pm.git
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 6/7] OMAP: Serial: Allow UART parameters to be configured from board file
2011-02-28 14:39 [PATCH 0/7] OMAP2+: UART: runtime conversion + cleanup Govindraj.R
` (4 preceding siblings ...)
2011-02-28 14:39 ` [PATCH 5/7] Serial: OMAP: add runtime pm support for omap-serial driver Govindraj.R
@ 2011-02-28 14:39 ` Govindraj.R
2011-03-01 19:16 ` Sricharan R
2011-02-28 14:39 ` [PATCH 7/7] Serial: OMAP2+: Make the RX_TIMEOUT for DMA configurable for each UART Govindraj.R
6 siblings, 1 reply; 25+ messages in thread
From: Govindraj.R @ 2011-02-28 14:39 UTC (permalink / raw)
To: linux-arm-kernel
From: Jon Hunter <jon-hunter@ti.com>
The following UART parameters are defined within the UART driver:
1). Whether the UART uses DMA (dma_enabled), by default set to 0
2). The size of dma buffer (set to 4096 bytes)
3). The time after which the dma should stop if no more data is received.
4). The idle timeout (DEFAULT_TIMEOUT) that sets the can_sleep flag after
uart inactivity.
5). Add default serial pads to board data if no pad info is available from
board file to avoid breaking uart wakeup capability from rx pad.
Different UARTs may be used for different purpose such as the console,
for interfacing bluetooth chip, for interfacing to a modem chip, etc.
Therefore, it is necessary to be able to customize the above settings
for a given board on a per UART basis.
This change allows these parameters to be configured from the board file
and allows the parameters to be configured for each UART independently.
If a board does not define its own custom parameters for the UARTs, then
use the default parameters in the structure "omap_serial_default_info".
The default parameters are defined to be the same as the current settings
in the UART driver to avoid breaking the UART for any board. By default,
make all boards use the default UART parameters.
Signed-off-by: Govindraj.R <govindraj.raja@ti.com>
Signed-off-by: Deepak K <deepak.k@ti.com>
Signed-off-by: Jon Hunter <jon-hunter@ti.com>
---
arch/arm/mach-omap2/board-2430sdp.c | 3 +-
arch/arm/mach-omap2/board-3430sdp.c | 4 +-
arch/arm/mach-omap2/board-4430sdp.c | 3 +-
arch/arm/mach-omap2/board-am3517evm.c | 3 +-
arch/arm/mach-omap2/board-apollon.c | 3 +-
arch/arm/mach-omap2/board-cm-t35.c | 3 +-
arch/arm/mach-omap2/board-cm-t3517.c | 3 +-
arch/arm/mach-omap2/board-devkit8000.c | 3 +-
arch/arm/mach-omap2/board-generic.c | 3 +-
arch/arm/mach-omap2/board-h4.c | 3 +-
arch/arm/mach-omap2/board-igep0020.c | 3 +-
arch/arm/mach-omap2/board-igep0030.c | 3 +-
arch/arm/mach-omap2/board-ldp.c | 3 +-
arch/arm/mach-omap2/board-n8x0.c | 9 +-
arch/arm/mach-omap2/board-omap3beagle.c | 3 +-
arch/arm/mach-omap2/board-omap3evm.c | 3 +-
arch/arm/mach-omap2/board-omap3logic.c | 3 +-
arch/arm/mach-omap2/board-omap3pandora.c | 3 +-
arch/arm/mach-omap2/board-omap3stalker.c | 3 +-
arch/arm/mach-omap2/board-omap3touchbook.c | 3 +-
arch/arm/mach-omap2/board-omap4panda.c | 3 +-
arch/arm/mach-omap2/board-overo.c | 3 +-
arch/arm/mach-omap2/board-rm680.c | 3 +-
arch/arm/mach-omap2/board-rx51.c | 3 +-
arch/arm/mach-omap2/board-ti8168evm.c | 2 +-
arch/arm/mach-omap2/board-zoom-peripherals.c | 3 +-
arch/arm/mach-omap2/serial.c | 108 +++++++++++++++++++++++-
arch/arm/plat-omap/include/plat/omap-serial.h | 14 +++-
arch/arm/plat-omap/include/plat/serial.h | 6 +-
drivers/tty/serial/omap-serial.c | 10 +-
30 files changed, 177 insertions(+), 45 deletions(-)
diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c
index cc42d47..0cfa3c7 100644
--- a/arch/arm/mach-omap2/board-2430sdp.c
+++ b/arch/arm/mach-omap2/board-2430sdp.c
@@ -38,6 +38,7 @@
#include <plat/gpmc.h>
#include <plat/usb.h>
#include <plat/gpmc-smc91x.h>
+#include <plat/omap-serial.h>
#include "mux.h"
#include "hsmmc.h"
@@ -249,7 +250,7 @@ static void __init omap_2430sdp_init(void)
omap2430_i2c_init();
platform_add_devices(sdp2430_devices, ARRAY_SIZE(sdp2430_devices));
- omap_serial_init();
+ omap_serial_init(NULL);
omap2_hsmmc_init(mmc);
omap2_usbfs_init(&sdp2430_usb_config);
diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index 8950ecc..7d7df08 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -39,8 +39,8 @@
#include <plat/gpmc.h>
#include <plat/display.h>
#include <plat/panel-generic-dpi.h>
-
#include <plat/gpmc-smc91x.h>
+#include <plat/omap-serial.h>
#include "board-flash.h"
#include "mux.h"
@@ -798,7 +798,7 @@ static void __init omap_3430sdp_init(void)
spi_register_board_info(sdp3430_spi_board_info,
ARRAY_SIZE(sdp3430_spi_board_info));
ads7846_dev_init();
- omap_serial_init();
+ omap_serial_init(NULL);
usb_musb_init(&musb_board_data);
board_smc91x_init();
board_flash_init(sdp_flash_partitions, chip_sel_3430, 0);
diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c
index 1a943be..9687aec 100644
--- a/arch/arm/mach-omap2/board-4430sdp.c
+++ b/arch/arm/mach-omap2/board-4430sdp.c
@@ -36,6 +36,7 @@
#include <plat/usb.h>
#include <plat/mmc.h>
#include <plat/omap4-keypad.h>
+#include <plat/omap-serial.h>
#include "mux.h"
#include "hsmmc.h"
@@ -643,7 +644,7 @@ static void __init omap_4430sdp_init(void)
omap4_i2c_init();
omap_sfh7741prox_init();
platform_add_devices(sdp4430_devices, ARRAY_SIZE(sdp4430_devices));
- omap_serial_init();
+ omap_serial_init(NULL);
omap4_twl6030_hsmmc_init(mmc);
usb_musb_init(&musb_board_data);
diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c
index 634fe65..bbc79a4 100644
--- a/arch/arm/mach-omap2/board-am3517evm.c
+++ b/arch/arm/mach-omap2/board-am3517evm.c
@@ -36,6 +36,7 @@
#include <plat/usb.h>
#include <plat/display.h>
#include <plat/panel-generic-dpi.h>
+#include <plat/omap-serial.h>
#include "mux.h"
#include "control.h"
@@ -487,7 +488,7 @@ static void __init am3517_evm_init(void)
am3517_evm_i2c_init();
omap_display_init(&am3517_evm_dss_data);
- omap_serial_init();
+ omap_serial_init(NULL);
/* Configure GPIO for EHCI port */
omap_mux_init_gpio(57, OMAP_PIN_OUTPUT);
diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c
index 4ef4aad..e021cdb 100644
--- a/arch/arm/mach-omap2/board-apollon.c
+++ b/arch/arm/mach-omap2/board-apollon.c
@@ -39,6 +39,7 @@
#include <plat/board.h>
#include <plat/common.h>
#include <plat/gpmc.h>
+#include <plat/omap-serial.h>
#include "mux.h"
#include "control.h"
@@ -342,7 +343,7 @@ static void __init omap_apollon_init(void)
* if not needed.
*/
platform_add_devices(apollon_devices, ARRAY_SIZE(apollon_devices));
- omap_serial_init();
+ omap_serial_init(NULL);
}
static void __init omap_apollon_map_io(void)
diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c
index 7311824..8ecde7e 100644
--- a/arch/arm/mach-omap2/board-cm-t35.c
+++ b/arch/arm/mach-omap2/board-cm-t35.c
@@ -48,6 +48,7 @@
#include <plat/display.h>
#include <plat/panel-generic-dpi.h>
#include <plat/mcspi.h>
+#include <plat/omap-serial.h>
#include <mach/hardware.h>
@@ -788,7 +789,7 @@ static struct omap_musb_board_data musb_board_data = {
static void __init cm_t35_init(void)
{
omap3_mux_init(board_mux, OMAP_PACKAGE_CUS);
- omap_serial_init();
+ omap_serial_init(NULL);
cm_t35_init_i2c();
cm_t35_init_nand();
cm_t35_init_ads7846();
diff --git a/arch/arm/mach-omap2/board-cm-t3517.c b/arch/arm/mach-omap2/board-cm-t3517.c
index 38bef6d..a1c0d87 100644
--- a/arch/arm/mach-omap2/board-cm-t3517.c
+++ b/arch/arm/mach-omap2/board-cm-t3517.c
@@ -43,6 +43,7 @@
#include <plat/usb.h>
#include <plat/nand.h>
#include <plat/gpmc.h>
+#include <plat/omap-serial.h>
#include <mach/am35xx.h>
@@ -292,7 +293,7 @@ static struct omap_board_mux board_mux[] __initdata = {
static void __init cm_t3517_init(void)
{
omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
- omap_serial_init();
+ omap_serial_init(NULL);
cm_t3517_init_leds();
cm_t3517_init_nand();
cm_t3517_init_rtc();
diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c
index 54abdd0..28fac56 100644
--- a/arch/arm/mach-omap2/board-devkit8000.c
+++ b/arch/arm/mach-omap2/board-devkit8000.c
@@ -47,6 +47,7 @@
#include <plat/usb.h>
#include <plat/display.h>
#include <plat/panel-generic-dpi.h>
+#include <plat/omap-serial.h>
#include <plat/mcspi.h>
#include <linux/input/matrix_keypad.h>
@@ -784,7 +785,7 @@ static struct omap_board_mux board_mux[] __initdata = {
static void __init devkit8000_init(void)
{
omap3_mux_init(board_mux, OMAP_PACKAGE_CUS);
- omap_serial_init();
+ omap_serial_init(NULL);
omap_dm9000_init();
diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c
index 682da92..450128b 100644
--- a/arch/arm/mach-omap2/board-generic.c
+++ b/arch/arm/mach-omap2/board-generic.c
@@ -29,6 +29,7 @@
#include <plat/usb.h>
#include <plat/board.h>
#include <plat/common.h>
+#include <plat/omap-serial.h>
static struct omap_board_config_kernel generic_config[] = {
};
@@ -43,7 +44,7 @@ static void __init omap_generic_init_early(void)
static void __init omap_generic_init(void)
{
- omap_serial_init();
+ omap_serial_init(NULL);
}
static void __init omap_generic_map_io(void)
diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c
index f6a3872..6481bab 100644
--- a/arch/arm/mach-omap2/board-h4.c
+++ b/arch/arm/mach-omap2/board-h4.c
@@ -39,6 +39,7 @@
#include <plat/menelaus.h>
#include <plat/dma.h>
#include <plat/gpmc.h>
+#include <plat/omap-serial.h>
#include "mux.h"
#include "control.h"
@@ -370,7 +371,7 @@ static void __init omap_h4_init(void)
platform_add_devices(h4_devices, ARRAY_SIZE(h4_devices));
omap2_usbfs_init(&h4_usb_config);
- omap_serial_init();
+ omap_serial_init(NULL);
}
static void __init omap_h4_map_io(void)
diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c
index 54e6318..9223b9b 100644
--- a/arch/arm/mach-omap2/board-igep0020.c
+++ b/arch/arm/mach-omap2/board-igep0020.c
@@ -34,6 +34,7 @@
#include <plat/display.h>
#include <plat/panel-generic-dpi.h>
#include <plat/onenand.h>
+#include <plat/omap-serial.h>
#include "mux.h"
#include "hsmmc.h"
@@ -686,7 +687,7 @@ static void __init igep2_init(void)
igep2_i2c_init();
platform_add_devices(igep2_devices, ARRAY_SIZE(igep2_devices));
omap_display_init(&igep2_dss_data);
- omap_serial_init();
+ omap_serial_init(NULL);
usb_musb_init(&musb_board_data);
usb_ehci_init(&ehci_pdata);
diff --git a/arch/arm/mach-omap2/board-igep0030.c b/arch/arm/mach-omap2/board-igep0030.c
index d75028e..c593a5c 100644
--- a/arch/arm/mach-omap2/board-igep0030.c
+++ b/arch/arm/mach-omap2/board-igep0030.c
@@ -31,6 +31,7 @@
#include <plat/gpmc.h>
#include <plat/usb.h>
#include <plat/onenand.h>
+#include <plat/omap-serial.h>
#include "mux.h"
#include "hsmmc.h"
@@ -432,7 +433,7 @@ static void __init igep3_init(void)
/* Register I2C busses and drivers */
igep3_i2c_init();
platform_add_devices(igep3_devices, ARRAY_SIZE(igep3_devices));
- omap_serial_init();
+ omap_serial_init(NULL);
usb_musb_init(&musb_board_data);
usb_ehci_init(&ehci_pdata);
diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c
index a3fae56..ff93da7 100644
--- a/arch/arm/mach-omap2/board-ldp.c
+++ b/arch/arm/mach-omap2/board-ldp.c
@@ -40,6 +40,7 @@
#include <plat/common.h>
#include <plat/gpmc.h>
#include <mach/board-zoom.h>
+#include <plat/omap-serial.h>
#include <asm/delay.h>
#include <plat/usb.h>
@@ -430,7 +431,7 @@ static void __init omap_ldp_init(void)
spi_register_board_info(ldp_spi_board_info,
ARRAY_SIZE(ldp_spi_board_info));
ads7846_dev_init();
- omap_serial_init();
+ omap_serial_init(NULL);
usb_musb_init(&musb_board_data);
board_nand_init(ldp_nand_partitions,
ARRAY_SIZE(ldp_nand_partitions), ZOOM_NAND_CS, 0);
diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c
index b36cbd2..7347256 100644
--- a/arch/arm/mach-omap2/board-n8x0.c
+++ b/arch/arm/mach-omap2/board-n8x0.c
@@ -33,6 +33,7 @@
#include <plat/onenand.h>
#include <plat/mmc.h>
#include <plat/serial.h>
+#include <plat/omap-serial.h>
#include "mux.h"
@@ -662,22 +663,22 @@ static inline void board_serial_init(void)
bdata.pads_cnt = 0;
bdata.id = 0;
- omap_serial_init_port(&bdata);
+ omap_serial_init_port(&bdata, NULL);
bdata.id = 1;
- omap_serial_init_port(&bdata);
+ omap_serial_init_port(&bdata, NULL);
bdata.id = 2;
bdata.pads = serial2_pads;
bdata.pads_cnt = ARRAY_SIZE(serial2_pads);
- omap_serial_init_port(&bdata);
+ omap_serial_init_port(&bdata, NULL);
}
#else
static inline void board_serial_init(void)
{
- omap_serial_init();
+ omap_serial_init(NULL);
}
#endif
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index a1faea3..e6c0299 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -45,6 +45,7 @@
#include <plat/gpmc.h>
#include <plat/nand.h>
#include <plat/usb.h>
+#include <plat/omap-serial.h>
#include "mux.h"
#include "hsmmc.h"
@@ -613,7 +614,7 @@ static void __init omap3_beagle_init(void)
platform_add_devices(omap3_beagle_devices,
ARRAY_SIZE(omap3_beagle_devices));
omap_display_init(&beagle_dss_data);
- omap_serial_init();
+ omap_serial_init(NULL);
omap_mux_init_gpio(170, OMAP_PIN_INPUT);
gpio_request(170, "DVI_nPD");
diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
index 5364147..0b793f1 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -46,6 +46,7 @@
#include <plat/mcspi.h>
#include <plat/display.h>
#include <plat/panel-generic-dpi.h>
+#include <plat/omap-serial.h>
#include "mux.h"
#include "sdram-micron-mt46h32m32lf-6.h"
@@ -831,7 +832,7 @@ static void __init omap3_evm_init(void)
spi_register_board_info(omap3evm_spi_board_info,
ARRAY_SIZE(omap3evm_spi_board_info));
- omap_serial_init();
+ omap_serial_init(NULL);
/* OMAP3EVM uses ISP1504 phy and so register nop transceiver */
usb_nop_xceiv_register();
diff --git a/arch/arm/mach-omap2/board-omap3logic.c b/arch/arm/mach-omap2/board-omap3logic.c
index b726943..0b5ba52 100644
--- a/arch/arm/mach-omap2/board-omap3logic.c
+++ b/arch/arm/mach-omap2/board-omap3logic.c
@@ -44,6 +44,7 @@
#include <plat/gpmc-smsc911x.h>
#include <plat/gpmc.h>
#include <plat/sdrc.h>
+#include <plat/omap-serial.h>
#define OMAP3LOGIC_SMSC911X_CS 1
@@ -212,7 +213,7 @@ static void __init omap3logic_init(void)
omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
omap3torpedo_fix_pbias_voltage();
omap3logic_i2c_init();
- omap_serial_init();
+ omap_serial_init(NULL);
board_mmc_init();
board_smsc911x_init();
diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c
index 17ef547..6f84247 100644
--- a/arch/arm/mach-omap2/board-omap3pandora.c
+++ b/arch/arm/mach-omap2/board-omap3pandora.c
@@ -48,6 +48,7 @@
#include <plat/usb.h>
#include <plat/display.h>
#include <plat/nand.h>
+#include <plat/omap-serial.h>
#include "mux.h"
#include "sdram-micron-mt46h32m32lf-6.h"
@@ -703,7 +704,7 @@ static void __init omap3pandora_init(void)
platform_add_devices(omap3pandora_devices,
ARRAY_SIZE(omap3pandora_devices));
omap_display_init(&pandora_dss_data);
- omap_serial_init();
+ omap_serial_init(NULL);
spi_register_board_info(omap3pandora_spi_board_info,
ARRAY_SIZE(omap3pandora_spi_board_info));
omap3pandora_ads7846_init();
diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c
index 07006c3..629bdce 100644
--- a/arch/arm/mach-omap2/board-omap3stalker.c
+++ b/arch/arm/mach-omap2/board-omap3stalker.c
@@ -41,6 +41,7 @@
#include <plat/usb.h>
#include <plat/display.h>
#include <plat/panel-generic-dpi.h>
+#include <plat/omap-serial.h>
#include <plat/mcspi.h>
#include <linux/input/matrix_keypad.h>
@@ -639,7 +640,7 @@ static void __init omap3_stalker_init(void)
spi_register_board_info(omap3stalker_spi_board_info,
ARRAY_SIZE(omap3stalker_spi_board_info));
- omap_serial_init();
+ omap_serial_init(NULL);
usb_musb_init(&musb_board_data);
usb_ehci_init(&ehci_pdata);
ads7846_dev_init();
diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c
index 6a60f79..c6bf289 100644
--- a/arch/arm/mach-omap2/board-omap3touchbook.c
+++ b/arch/arm/mach-omap2/board-omap3touchbook.c
@@ -48,6 +48,7 @@
#include <plat/gpmc.h>
#include <plat/nand.h>
#include <plat/usb.h>
+#include <plat/omap-serial.h>
#include "mux.h"
#include "hsmmc.h"
@@ -519,7 +520,7 @@ static void __init omap3_touchbook_init(void)
omap3_touchbook_i2c_init();
platform_add_devices(omap3_touchbook_devices,
ARRAY_SIZE(omap3_touchbook_devices));
- omap_serial_init();
+ omap_serial_init(NULL);
omap_mux_init_gpio(170, OMAP_PIN_INPUT);
gpio_request(176, "DVI_nPD");
diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
index 3dd241b..2245ed1 100644
--- a/arch/arm/mach-omap2/board-omap4panda.c
+++ b/arch/arm/mach-omap2/board-omap4panda.c
@@ -39,6 +39,7 @@
#include <plat/common.h>
#include <plat/usb.h>
#include <plat/mmc.h>
+#include <plat/omap-serial.h>
#include "timer-gp.h"
#include "hsmmc.h"
@@ -470,7 +471,7 @@ static void __init omap4_panda_init(void)
omap4_panda_i2c_init();
platform_add_devices(panda_devices, ARRAY_SIZE(panda_devices));
platform_device_register(&omap_vwlan_device);
- omap_serial_init();
+ omap_serial_init(NULL);
omap4_twl6030_hsmmc_init(mmc);
omap4_ehci_init();
usb_musb_init(&musb_board_data);
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index a33ec0e..960a3ea 100644
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -46,6 +46,7 @@
#include <mach/hardware.h>
#include <plat/nand.h>
#include <plat/usb.h>
+#include <plat/omap-serial.h>
#include "mux.h"
#include "sdram-micron-mt46h32m32lf-6.h"
@@ -450,7 +451,7 @@ static void __init overo_init(void)
omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
overo_i2c_init();
platform_add_devices(overo_devices, ARRAY_SIZE(overo_devices));
- omap_serial_init();
+ omap_serial_init(NULL);
overo_flash_init();
usb_musb_init(&musb_board_data);
usb_ehci_init(&ehci_pdata);
diff --git a/arch/arm/mach-omap2/board-rm680.c b/arch/arm/mach-omap2/board-rm680.c
index bdebcb7..bd4b7ad 100644
--- a/arch/arm/mach-omap2/board-rm680.c
+++ b/arch/arm/mach-omap2/board-rm680.c
@@ -27,6 +27,7 @@
#include <plat/gpmc.h>
#include <plat/common.h>
#include <plat/onenand.h>
+#include <plat/omap-serial.h>
#include "mux.h"
#include "hsmmc.h"
@@ -162,7 +163,7 @@ static struct omap_musb_board_data rm680_musb_data = {
static void __init rm680_init(void)
{
omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
- omap_serial_init();
+ omap_serial_init(NULL);
usb_musb_init(&rm680_musb_data);
rm680_peripherals_init();
}
diff --git a/arch/arm/mach-omap2/board-rx51.c b/arch/arm/mach-omap2/board-rx51.c
index 3cf72fe..08619e9 100644
--- a/arch/arm/mach-omap2/board-rx51.c
+++ b/arch/arm/mach-omap2/board-rx51.c
@@ -29,6 +29,7 @@
#include <plat/dma.h>
#include <plat/gpmc.h>
#include <plat/usb.h>
+#include <plat/omap-serial.h>
#include "mux.h"
#include "pm.h"
@@ -127,7 +128,7 @@ static struct omap_musb_board_data musb_board_data = {
static void __init rx51_init(void)
{
omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
- omap_serial_init();
+ omap_serial_init(NULL);
usb_musb_init(&musb_board_data);
rx51_peripherals_init();
diff --git a/arch/arm/mach-omap2/board-ti8168evm.c b/arch/arm/mach-omap2/board-ti8168evm.c
index f2b0971..c4f83ed 100644
--- a/arch/arm/mach-omap2/board-ti8168evm.c
+++ b/arch/arm/mach-omap2/board-ti8168evm.c
@@ -42,7 +42,7 @@ static void __init ti8168_evm_init_irq(void)
static void __init ti8168_evm_init(void)
{
- omap_serial_init();
+ omap_serial_init(NULL);
}
static void __init ti8168_evm_map_io(void)
diff --git a/arch/arm/mach-omap2/board-zoom-peripherals.c b/arch/arm/mach-omap2/board-zoom-peripherals.c
index e0e040f..82ca121 100644
--- a/arch/arm/mach-omap2/board-zoom-peripherals.c
+++ b/arch/arm/mach-omap2/board-zoom-peripherals.c
@@ -26,6 +26,7 @@
#include <plat/common.h>
#include <plat/usb.h>
+#include <plat/omap-serial.h>
#include <mach/board-zoom.h>
@@ -394,5 +395,5 @@ void __init zoom_peripherals_init(void)
platform_device_register(&omap_vwlan_device);
usb_musb_init(&musb_board_data);
enable_board_wakeup_source();
- omap_serial_init();
+ omap_serial_init(NULL);
}
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 755f4aa..530e9e3 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -44,6 +44,15 @@
static int omap_uart_con_id __initdata = -1;
+static struct omap_uart_port_info omap_serial_default_info[] = {
+ {
+ .dma_enabled = 0,
+ .dma_rx_buf_size = DEFAULT_RXDMA_BUFSIZE,
+ .dma_rx_timeout = DEFAULT_RXDMA_TIMEOUT,
+ .idle_timeout = DEFAULT_IDLE_TIMEOUT,
+ },
+};
+
static int uart_idle_hwmod(struct omap_device *od)
{
omap_hwmod_idle(od->hwmods[0]);
@@ -66,6 +75,54 @@ static struct omap_device_pm_latency omap_uart_latency[] = {
},
};
+#ifdef CONFIG_OMAP_MUX
+static struct omap_device_pad default_serial0_pads[] __initdata = {
+ {
+ .name = "uart1_rx.uart1_rx",
+ .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+ .enable = OMAP_MUX_MODE0,
+ },
+};
+
+static struct omap_device_pad default_serial1_pads[] __initdata = {
+ {
+ .name = "uart2_rx.uart2_rx",
+ .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+ .enable = OMAP_MUX_MODE0,
+ },
+};
+
+static struct omap_device_pad default_serial2_pads[] __initdata = {
+ {
+ .name = "uart3_rx_irrx.uart3_rx_irrx",
+ .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+ .enable = OMAP_MUX_MODE0,
+ },
+};
+
+static struct omap_device_pad default_omap36xx_serial3_pads[] __initdata = {
+ {
+ .name = "gpmc_wait3.uart4_rx",
+ .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+ .enable = OMAP_MUX_MODE2,
+ },
+};
+
+static struct omap_device_pad default_omap4_serial3_pads[] __initdata = {
+ {
+ .name = "uart4_rx.uart4_rx",
+ .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+ .enable = OMAP_MUX_MODE0,
+ },
+};
+#else
+static struct omap_device_pad default_serial0_pads[] __initdata = {};
+static struct omap_device_pad default_serial1_pads[] __initdata = {};
+static struct omap_device_pad default_serial2_pads[] __initdata = {};
+static struct omap_device_pad default_omap36xx_serial3_pads[] __initdata = {};
+static struct omap_device_pad default_omap4_serial3_pads[] __initdata = {};
+#endif
+
static void omap_uart_idle_init(struct omap_uart_port_info *uart,
unsigned short num)
{
@@ -164,6 +221,7 @@ core_initcall(omap_serial_early_init);
/**
* omap_serial_init_port() - initialize single serial port
* @bdata: port specific board data pointer
+ * @info: platform specific data pointer
*
* This function initialies serial driver for given port only.
* Platforms can call this function instead of omap_serial_init()
@@ -172,7 +230,8 @@ core_initcall(omap_serial_early_init);
* Don't mix calls to omap_serial_init_port() and omap_serial_init(),
* use only one of the two.
*/
-void __init omap_serial_init_port(struct omap_board_data *bdata)
+void __init omap_serial_init_port(struct omap_board_data *bdata,
+ struct omap_uart_port_info *info)
{
struct omap_hwmod *oh;
struct omap_device *od;
@@ -190,6 +249,9 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
if (!oh)
return;
+ if (info == NULL)
+ info = omap_serial_default_info;
+
pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
if (!pdata) {
pr_err("Memory allocation for UART pdata failed\n");
@@ -204,6 +266,10 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
pdata->uartclk = OMAP24XX_BASE_BAUD * 16;
pdata->flags = UPF_BOOT_AUTOCONF;
+ pdata->dma_enabled = info->dma_enabled;
+ pdata->dma_rx_buf_size = info->dma_rx_buf_size;
+ pdata->dma_rx_timeout = info->dma_rx_timeout;
+ pdata->idle_timeout = info->idle_timeout;
if (bdata->id == omap_uart_con_id)
pdata->console_uart = true;
@@ -222,21 +288,53 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
/**
* omap_serial_init() - initialize all supported serial ports
+ * @info: platform specific data pointer
*
* Initializes all available UARTs as serial ports. Platforms
* can call this function when they want to have default behaviour
* for serial ports (e.g initialize them all as serial ports).
*/
-void __init omap_serial_init(void)
+void __init omap_serial_init(struct omap_uart_port_info *info)
{
struct omap_board_data bdata;
u8 i;
+ if (info == NULL)
+ info = omap_serial_default_info;
+
for (i = 0; i < OMAP_MAX_HSUART_PORTS; i++) {
bdata.id = i;
bdata.flags = 0;
- bdata.pads = NULL;
- bdata.pads_cnt = 0;
- omap_serial_init_port(&bdata);
+ switch (i) {
+ case 0:
+ bdata.pads = default_serial0_pads;
+ bdata.pads_cnt = ARRAY_SIZE(default_serial0_pads);
+ break;
+ case 1:
+ bdata.pads = default_serial1_pads;
+ bdata.pads_cnt = ARRAY_SIZE(default_serial1_pads);
+ break;
+ case 2:
+ bdata.pads = default_serial2_pads;
+ bdata.pads_cnt = ARRAY_SIZE(default_serial2_pads);
+ break;
+ case 3:
+ if (cpu_is_omap44xx()) {
+ bdata.pads = default_omap4_serial3_pads;
+ bdata.pads_cnt =
+ ARRAY_SIZE(default_omap4_serial3_pads);
+ } else {
+ bdata.pads = default_omap36xx_serial3_pads;
+ bdata.pads_cnt =
+ ARRAY_SIZE(default_omap36xx_serial3_pads);
+ }
+ break;
+ default:
+ bdata.pads = NULL;
+ bdata.pads_cnt = 0;
+ break;
+ }
+
+ omap_serial_init_port(&bdata, info);
}
}
diff --git a/arch/arm/plat-omap/include/plat/omap-serial.h b/arch/arm/plat-omap/include/plat/omap-serial.h
index f9bc7ef..4f12d6c 100644
--- a/arch/arm/plat-omap/include/plat/omap-serial.h
+++ b/arch/arm/plat-omap/include/plat/omap-serial.h
@@ -51,7 +51,11 @@
#define OMAP_UART_DMA_CH_FREE -1
-#define RX_TIMEOUT (3 * HZ)
+#define RX_TIMEOUT (3 * HZ) /* RX DMA timeout (jiffies) */
+#define DEFAULT_RXDMA_TIMEOUT 1 /* RX DMA polling rate (us) */
+#define DEFAULT_RXDMA_BUFSIZE 4096 /* RX DMA buffer size */
+#define DEFAULT_IDLE_TIMEOUT (5 * HZ) /* UART idle timeout (secs) */
+
#define OMAP_MAX_HSUART_PORTS 4
#define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA
@@ -64,6 +68,9 @@ struct omap_uart_port_info {
upf_t flags; /* UPF_* flags */
unsigned int errata;
unsigned int console_uart;
+ unsigned int dma_rx_buf_size;/* DMA Rx Buffer Size */
+ unsigned int dma_rx_timeout; /* DMA RX timeout */
+ unsigned int idle_timeout; /* OMAP UART idle timeout */
void __iomem *wk_st;
void __iomem *wk_en;
@@ -91,8 +98,8 @@ struct uart_omap_dma {
spinlock_t rx_lock;
/* timer to poll activity on rx dma */
struct timer_list rx_timer;
- int rx_buf_size;
- int rx_timeout;
+ unsigned int rx_buf_size;
+ unsigned int rx_timeout;
};
struct uart_omap_port {
@@ -120,6 +127,7 @@ struct uart_omap_port {
char name[20];
unsigned long port_activity;
struct timer_list inactivity_timer;
+ unsigned int idle_timeout;
unsigned int errata;
int can_sleep;
diff --git a/arch/arm/plat-omap/include/plat/serial.h b/arch/arm/plat-omap/include/plat/serial.h
index 6339848..2ed24b3 100644
--- a/arch/arm/plat-omap/include/plat/serial.h
+++ b/arch/arm/plat-omap/include/plat/serial.h
@@ -103,9 +103,11 @@
#ifndef __ASSEMBLER__
struct omap_board_data;
+struct omap_uart_port_info;
-extern void omap_serial_init(void);
-extern void omap_serial_init_port(struct omap_board_data *bdata);
+extern void omap_serial_init(struct omap_uart_port_info *platform_data);
+extern void omap_serial_init_port(struct omap_board_data *bdata,
+ struct omap_uart_port_info *platform_data);
extern void omap_uart_prepare_idle(int num);
extern void omap_uart_resume_idle(int num);
#endif
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index bc877b9..008645c 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -47,8 +47,6 @@
#define omap_uart_console(port) NULL
#endif
-#define OMAP_UART_CLK_PUT_DELAY (5 * HZ)
-
static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS];
/* Forward declaration of functions */
@@ -139,7 +137,7 @@ static void serial_omap_port_enable(struct uart_omap_port *up)
}
up->can_sleep = 0;
- mod_timer(&up->inactivity_timer, jiffies + OMAP_UART_CLK_PUT_DELAY);
+ mod_timer(&up->inactivity_timer, jiffies + up->idle_timeout);
}
void omap_uart_prepare_idle(int num)
@@ -1412,16 +1410,18 @@ static int serial_omap_probe(struct platform_device *pdev)
up->uart_dma.uart_dma_tx = dma_tx->start;
up->uart_dma.uart_dma_rx = dma_rx->start;
up->use_dma = 1;
- up->uart_dma.rx_buf_size = 4096;
- up->uart_dma.rx_timeout = 2;
+ up->uart_dma.rx_buf_size = omap_up_info->dma_rx_buf_size;
+ up->uart_dma.rx_timeout = omap_up_info->dma_rx_timeout;
spin_lock_init(&(up->uart_dma.tx_lock));
spin_lock_init(&(up->uart_dma.rx_lock));
up->uart_dma.tx_dma_channel = OMAP_UART_DMA_CH_FREE;
up->uart_dma.rx_dma_channel = OMAP_UART_DMA_CH_FREE;
}
+
init_timer(&(up->inactivity_timer));
up->inactivity_timer.function = serial_omap_inactivity_timer;
up->inactivity_timer.data = up->pdev->id;
+ up->idle_timeout = omap_up_info->idle_timeout;
pm_runtime_enable(&pdev->dev);
pm_runtime_irq_safe(&pdev->dev);
--
1.7.1
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 6/7] OMAP: Serial: Allow UART parameters to be configured from board file
2011-02-28 14:39 ` [PATCH 6/7] OMAP: Serial: Allow UART parameters to be configured from board file Govindraj.R
@ 2011-03-01 19:16 ` Sricharan R
2011-03-02 7:40 ` Govindraj
0 siblings, 1 reply; 25+ messages in thread
From: Sricharan R @ 2011-03-01 19:16 UTC (permalink / raw)
To: linux-arm-kernel
Hi,
>diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
>index 755f4aa..530e9e3 100644
>--- a/arch/arm/mach-omap2/serial.c
>+++ b/arch/arm/mach-omap2/serial.c
>@@ -44,6 +44,15 @@
>
> static int omap_uart_con_id __initdata = -1;
>
>+static struct omap_uart_port_info omap_serial_default_info[] = {
>+ {
>+ .dma_enabled = 0,
>+ .dma_rx_buf_size = DEFAULT_RXDMA_BUFSIZE,
>+ .dma_rx_timeout = DEFAULT_RXDMA_TIMEOUT,
>+ .idle_timeout = DEFAULT_IDLE_TIMEOUT,
>+ },
>+};
>+
> static int uart_idle_hwmod(struct omap_device *od)
> {
> omap_hwmod_idle(od->hwmods[0]);
>@@ -66,6 +75,54 @@ static struct omap_device_pm_latency
omap_uart_latency[]
>= {
> },
> };
>
>+#ifdef CONFIG_OMAP_MUX
>+static struct omap_device_pad default_serial0_pads[] __initdata = {
>+ {
>+ .name = "uart1_rx.uart1_rx",
>+ .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
>+ .enable = OMAP_MUX_MODE0,
>+ },
>+};
>+
>+static struct omap_device_pad default_serial1_pads[] __initdata = {
>+ {
>+ .name = "uart2_rx.uart2_rx",
>+ .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
>+ .enable = OMAP_MUX_MODE0,
>+ },
>+};
>+
>+static struct omap_device_pad default_serial2_pads[] __initdata = {
>+ {
>+ .name = "uart3_rx_irrx.uart3_rx_irrx",
>+ .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
>+ .enable = OMAP_MUX_MODE0,
>+ },
>+};
>+
>+static struct omap_device_pad default_omap36xx_serial3_pads[] __initdata
=
>{
>+ {
>+ .name = "gpmc_wait3.uart4_rx",
>+ .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
>+ .enable = OMAP_MUX_MODE2,
>+ },
>+};
>+
>+static struct omap_device_pad default_omap4_serial3_pads[] __initdata =
{
>+ {
>+ .name = "uart4_rx.uart4_rx",
>+ .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
>+ .enable = OMAP_MUX_MODE0,
>+ },
>+};
Here only the UART RX pins are muxed, so what about the cts, rts, tx pins?
Is it consistent that across all socs that only UART3 would have UART/IRDA
functions capability so that serial2 pads can always be called "rx_irxx"
?.
Thanks,
sricharan
>
>--
>To unsubscribe from this list: send the line "unsubscribe linux-omap" in
>the body of a message to majordomo at vger.kernel.org
>More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 6/7] OMAP: Serial: Allow UART parameters to be configured from board file
2011-03-01 19:16 ` Sricharan R
@ 2011-03-02 7:40 ` Govindraj
2011-03-02 8:19 ` Sricharan R
0 siblings, 1 reply; 25+ messages in thread
From: Govindraj @ 2011-03-02 7:40 UTC (permalink / raw)
To: linux-arm-kernel
On Wed, Mar 2, 2011 at 12:46 AM, Sricharan R <r.sricharan@ti.com> wrote:
> Hi,
>>diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
>>index 755f4aa..530e9e3 100644
>>--- a/arch/arm/mach-omap2/serial.c
>>+++ b/arch/arm/mach-omap2/serial.c
>>@@ -44,6 +44,15 @@
>>
>> static int omap_uart_con_id __initdata = -1;
>>
>>+static struct omap_uart_port_info omap_serial_default_info[] = {
>>+ ? ? ?{
>>+ ? ? ? ? ? ? ?.dma_enabled ? ?= 0,
>>+ ? ? ? ? ? ? ?.dma_rx_buf_size = DEFAULT_RXDMA_BUFSIZE,
>>+ ? ? ? ? ? ? ?.dma_rx_timeout = DEFAULT_RXDMA_TIMEOUT,
>>+ ? ? ? ? ? ? ?.idle_timeout ? = DEFAULT_IDLE_TIMEOUT,
>>+ ? ? ?},
>>+};
>>+
>> static int uart_idle_hwmod(struct omap_device *od)
>> {
>> ? ? ? omap_hwmod_idle(od->hwmods[0]);
>>@@ -66,6 +75,54 @@ static struct omap_device_pm_latency
> omap_uart_latency[]
>>= {
>> ? ? ? },
>> };
>>
>>+#ifdef CONFIG_OMAP_MUX
>>+static struct omap_device_pad default_serial0_pads[] __initdata = {
>>+ ? ? ?{
>>+ ? ? ? ? ? ? ?.name ? = "uart1_rx.uart1_rx",
>>+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
>>+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
>>+ ? ? ?},
>>+};
>>+
>>+static struct omap_device_pad default_serial1_pads[] __initdata = {
>>+ ? ? ?{
>>+ ? ? ? ? ? ? ?.name ? = "uart2_rx.uart2_rx",
>>+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
>>+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
>>+ ? ? ?},
>>+};
>>+
>>+static struct omap_device_pad default_serial2_pads[] __initdata = {
>>+ ? ? ?{
>>+ ? ? ? ? ? ? ?.name ? = "uart3_rx_irrx.uart3_rx_irrx",
>>+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
>>+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
>>+ ? ? ?},
>>+};
>>+
>>+static struct omap_device_pad default_omap36xx_serial3_pads[] __initdata
> =
>>{
>>+ ? ? ?{
>>+ ? ? ? ? ? ? ?.name ? = "gpmc_wait3.uart4_rx",
>>+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
>>+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE2,
>>+ ? ? ?},
>>+};
>>+
>>+static struct omap_device_pad default_omap4_serial3_pads[] __initdata =
> {
>>+ ? ? ?{
>>+ ? ? ? ? ? ? ?.name ? = "uart4_rx.uart4_rx",
>>+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
>>+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
>>+ ? ? ?},
>>+};
> Here only the UART RX pins are muxed, so what about the cts, rts, tx pins?
The intention here is to enable wakeup capabilities for uart rx pad.
AFAIK most of the boards are currently dependent on bootloader for
uart-muxing if any board is not dependent on bootloader then we
can use omap_serial_init_port along with board_mux_info from board.
Prior to this change uart wakeup is based on rx_pad and we were populating
offset and using omap_ctrl api's to read/write which is cleaned up now.
Most of boards are dependent on uart-rx wakeup to avoid breaking any
board support we
are using omap_serial_init by filling default values, which provides
us with same
environment but with right approach towards handling mux data with a
handshake with
hwmod framework.
So if any board needs specific mux they can go ahead and add required
mux data in
board file and use map_serial_init_port instead of current omap_serial_init.
> Is it consistent that across all socs that only UART3 would have UART/IRDA
> functions capability so that serial2 pads can always be called "rx_irxx"
> ?.
Yes from OMAP2420 to OMAP4430 uart3 can used as irda.
--
Thanks,
Govindraj.R
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 6/7] OMAP: Serial: Allow UART parameters to be configured from board file
2011-03-02 7:40 ` Govindraj
@ 2011-03-02 8:19 ` Sricharan R
2011-03-02 10:07 ` Govindraj
0 siblings, 1 reply; 25+ messages in thread
From: Sricharan R @ 2011-03-02 8:19 UTC (permalink / raw)
To: linux-arm-kernel
Hi,
>-----Original Message-----
>From: Govindraj [mailto:govindraj.ti at gmail.com]
>Sent: Wednesday, March 02, 2011 1:11 PM
>To: Sricharan R
>Cc: Govindraj.R; linux-omap at vger.kernel.org;
linux-serial at vger.kernel.org;
>linux-arm-kernel at lists.infradead.org; Jon Hunter; Tony Lindgren; Benoit
>Cousson; Kevin Hilman; Paul Walmsley; Rajendra Nayak; Deepak Kattungal
>Subject: Re: [PATCH 6/7] OMAP: Serial: Allow UART parameters to be
>configured from board file
>
>On Wed, Mar 2, 2011 at 12:46 AM, Sricharan R <r.sricharan@ti.com> wrote:
>> Hi,
>>>diff --git a/arch/arm/mach-omap2/serial.c
b/arch/arm/mach-omap2/serial.c
>>>index 755f4aa..530e9e3 100644
>>>--- a/arch/arm/mach-omap2/serial.c
>>>+++ b/arch/arm/mach-omap2/serial.c
>>>@@ -44,6 +44,15 @@
>>>
>>> static int omap_uart_con_id __initdata = -1;
>>>
>>>+static struct omap_uart_port_info omap_serial_default_info[] = {
>>>+ ? ? ?{
>>>+ ? ? ? ? ? ? ?.dma_enabled ? ?= 0,
>>>+ ? ? ? ? ? ? ?.dma_rx_buf_size = DEFAULT_RXDMA_BUFSIZE,
>>>+ ? ? ? ? ? ? ?.dma_rx_timeout = DEFAULT_RXDMA_TIMEOUT,
>>>+ ? ? ? ? ? ? ?.idle_timeout ? = DEFAULT_IDLE_TIMEOUT,
>>>+ ? ? ?},
>>>+};
>>>+
>>> static int uart_idle_hwmod(struct omap_device *od)
>>> {
>>> ? ? ? omap_hwmod_idle(od->hwmods[0]);
>>>@@ -66,6 +75,54 @@ static struct omap_device_pm_latency
>> omap_uart_latency[]
>>>= {
>>> ? ? ? },
>>> };
>>>
>>>+#ifdef CONFIG_OMAP_MUX
>>>+static struct omap_device_pad default_serial0_pads[] __initdata = {
>>>+ ? ? ?{
>>>+ ? ? ? ? ? ? ?.name ? = "uart1_rx.uart1_rx",
>>>+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
OMAP_DEVICE_PAD_WAKEUP,
>>>+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
>>>+ ? ? ?},
>>>+};
>>>+
>>>+static struct omap_device_pad default_serial1_pads[] __initdata = {
>>>+ ? ? ?{
>>>+ ? ? ? ? ? ? ?.name ? = "uart2_rx.uart2_rx",
>>>+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
OMAP_DEVICE_PAD_WAKEUP,
>>>+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
>>>+ ? ? ?},
>>>+};
>>>+
>>>+static struct omap_device_pad default_serial2_pads[] __initdata = {
>>>+ ? ? ?{
>>>+ ? ? ? ? ? ? ?.name ? = "uart3_rx_irrx.uart3_rx_irrx",
>>>+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
OMAP_DEVICE_PAD_WAKEUP,
>>>+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
>>>+ ? ? ?},
>>>+};
>>>+
>>>+static struct omap_device_pad default_omap36xx_serial3_pads[]
__initdata
>> =
>>>{
>>>+ ? ? ?{
>>>+ ? ? ? ? ? ? ?.name ? = "gpmc_wait3.uart4_rx",
>>>+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
OMAP_DEVICE_PAD_WAKEUP,
>>>+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE2,
>>>+ ? ? ?},
>>>+};
>>>+
>>>+static struct omap_device_pad default_omap4_serial3_pads[] __initdata
=
>> {
>>>+ ? ? ?{
>>>+ ? ? ? ? ? ? ?.name ? = "uart4_rx.uart4_rx",
>>>+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
OMAP_DEVICE_PAD_WAKEUP,
>>>+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
>>>+ ? ? ?},
>>>+};
>> Here only the UART RX pins are muxed, so what about the cts, rts, tx
>pins?
>
>The intention here is to enable wakeup capabilities for uart rx pad.
>
>AFAIK most of the boards are currently dependent on bootloader for
>uart-muxing if any board is not dependent on bootloader then we
>can use omap_serial_init_port along with board_mux_info from board.
>
Yes. The idea is to be independent of the bootloaders for mux settings.
>Prior to this change uart wakeup is based on rx_pad and we were
populating
>offset and using omap_ctrl api's to read/write which is cleaned up now.
>Most of boards are dependent on uart-rx wakeup to avoid breaking any
>board support we
>are using omap_serial_init by filling default values, which provides
>us with same
>environment but with right approach towards handling mux data with a
>handshake with
>hwmod framework.
>
Now, in this change only the RX pin is configured. So if some board uses
omap_serial_init then only the RX is going to be configured.
How will they configure the rest of the pins?
They cannot call omap_serial_init_port after this just to configure the
rest of the mux pins( cts, rts, tx).
So data which is passed from omap_serial_init should have the
configuration
for all the pins, and this default data should be consistent across
atleast
some boards, so that they can use this. This will reduce the data
duplication across board files.
If this is not true, then all the pads can be configured from the board
files itself using omap_serial_init_port and you can set the required
RX wakeup capability there as well.
>So if any board needs specific mux they can go ahead and add required
>mux data in
>board file and use map_serial_init_port instead of current
>omap_serial_init.
>
>
>> Is it consistent that across all socs that only UART3 would have
>UART/IRDA
>> functions capability so that serial2 pads can always be called
"rx_irxx"
>> ?.
>
>Yes from OMAP2420 to OMAP4430 uart3 can used as irda.
>
Ok.
>--
>Thanks,
>Govindraj.R
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 6/7] OMAP: Serial: Allow UART parameters to be configured from board file
2011-03-02 8:19 ` Sricharan R
@ 2011-03-02 10:07 ` Govindraj
2011-03-02 18:24 ` Tony Lindgren
2011-03-03 5:08 ` Sricharan R
0 siblings, 2 replies; 25+ messages in thread
From: Govindraj @ 2011-03-02 10:07 UTC (permalink / raw)
To: linux-arm-kernel
On Wed, Mar 2, 2011 at 1:49 PM, Sricharan R <r.sricharan@ti.com> wrote:
> Hi,
>>-----Original Message-----
>>From: Govindraj [mailto:govindraj.ti at gmail.com]
>>Sent: Wednesday, March 02, 2011 1:11 PM
>>To: Sricharan R
>>Cc: Govindraj.R; linux-omap at vger.kernel.org;
> linux-serial at vger.kernel.org;
>>linux-arm-kernel at lists.infradead.org; Jon Hunter; Tony Lindgren; Benoit
>>Cousson; Kevin Hilman; Paul Walmsley; Rajendra Nayak; Deepak Kattungal
>>Subject: Re: [PATCH 6/7] OMAP: Serial: Allow UART parameters to be
>>configured from board file
>>
>>On Wed, Mar 2, 2011 at 12:46 AM, Sricharan R <r.sricharan@ti.com> wrote:
>>> Hi,
>>>>diff --git a/arch/arm/mach-omap2/serial.c
> b/arch/arm/mach-omap2/serial.c
>>>>index 755f4aa..530e9e3 100644
>>>>--- a/arch/arm/mach-omap2/serial.c
>>>>+++ b/arch/arm/mach-omap2/serial.c
>>>>@@ -44,6 +44,15 @@
>>>>
>>>> static int omap_uart_con_id __initdata = -1;
>>>>
>>>>+static struct omap_uart_port_info omap_serial_default_info[] = {
>>>>+ ? ? ?{
>>>>+ ? ? ? ? ? ? ?.dma_enabled ? ?= 0,
>>>>+ ? ? ? ? ? ? ?.dma_rx_buf_size = DEFAULT_RXDMA_BUFSIZE,
>>>>+ ? ? ? ? ? ? ?.dma_rx_timeout = DEFAULT_RXDMA_TIMEOUT,
>>>>+ ? ? ? ? ? ? ?.idle_timeout ? = DEFAULT_IDLE_TIMEOUT,
>>>>+ ? ? ?},
>>>>+};
>>>>+
>>>> static int uart_idle_hwmod(struct omap_device *od)
>>>> {
>>>> ? ? ? omap_hwmod_idle(od->hwmods[0]);
>>>>@@ -66,6 +75,54 @@ static struct omap_device_pm_latency
>>> omap_uart_latency[]
>>>>= {
>>>> ? ? ? },
>>>> };
>>>>
>>>>+#ifdef CONFIG_OMAP_MUX
>>>>+static struct omap_device_pad default_serial0_pads[] __initdata = {
>>>>+ ? ? ?{
>>>>+ ? ? ? ? ? ? ?.name ? = "uart1_rx.uart1_rx",
>>>>+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
> OMAP_DEVICE_PAD_WAKEUP,
>>>>+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
>>>>+ ? ? ?},
>>>>+};
>>>>+
>>>>+static struct omap_device_pad default_serial1_pads[] __initdata = {
>>>>+ ? ? ?{
>>>>+ ? ? ? ? ? ? ?.name ? = "uart2_rx.uart2_rx",
>>>>+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
> OMAP_DEVICE_PAD_WAKEUP,
>>>>+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
>>>>+ ? ? ?},
>>>>+};
>>>>+
>>>>+static struct omap_device_pad default_serial2_pads[] __initdata = {
>>>>+ ? ? ?{
>>>>+ ? ? ? ? ? ? ?.name ? = "uart3_rx_irrx.uart3_rx_irrx",
>>>>+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
> OMAP_DEVICE_PAD_WAKEUP,
>>>>+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
>>>>+ ? ? ?},
>>>>+};
>>>>+
>>>>+static struct omap_device_pad default_omap36xx_serial3_pads[]
> __initdata
>>> =
>>>>{
>>>>+ ? ? ?{
>>>>+ ? ? ? ? ? ? ?.name ? = "gpmc_wait3.uart4_rx",
>>>>+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
> OMAP_DEVICE_PAD_WAKEUP,
>>>>+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE2,
>>>>+ ? ? ?},
>>>>+};
>>>>+
>>>>+static struct omap_device_pad default_omap4_serial3_pads[] __initdata
> =
>>> {
>>>>+ ? ? ?{
>>>>+ ? ? ? ? ? ? ?.name ? = "uart4_rx.uart4_rx",
>>>>+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
> OMAP_DEVICE_PAD_WAKEUP,
>>>>+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
>>>>+ ? ? ?},
>>>>+};
>>> Here only the UART RX pins are muxed, so what about the cts, rts, tx
>>pins?
>>
>>The intention here is to enable wakeup capabilities for uart rx pad.
>>
>>AFAIK most of the boards are currently dependent on bootloader for
>>uart-muxing if any board is not dependent on bootloader then we
>>can use omap_serial_init_port along with board_mux_info from board.
>>
> Yes. The idea is to be independent of the bootloaders for mux settings.
>
>>Prior to this change uart wakeup is based on rx_pad and we were
> populating
>>offset and using omap_ctrl api's to read/write which is cleaned up now.
>>Most of boards are dependent on uart-rx wakeup to avoid breaking any
>>board support we
>>are using omap_serial_init by filling default values, which provides
>>us with same
>>environment but with right approach towards handling mux data with a
>>handshake with
>>hwmod framework.
>>
> Now, in this change only the RX pin is configured. So if some board uses
> omap_serial_init then only the RX is going to be configured.
> How will they configure the rest of the pins?
They should call omap_serial_init_port to configure each individual uart with
mux_info filled and not use omap_serial_init.
If any board is not dependent for mux from u-boot then they use above said
init_port func.
> They cannot call omap_serial_init_port after this just to configure the
> rest of the mux pins( cts, rts, tx).
No. You need to use either omap_serial_init_port or omap_serial_init
you cannot call both apis from board file please refer to both func
documentation.
Also please note i am not configuring all uart pins for pullups and pull downs
with this patch series and its not related to this patch series.
I am only enabling wakeup-enable pin for rx as it was done before.
> So data which is passed from omap_serial_init should have the
> configuration
> for all the pins, and this default data should be consistent across
> atleast
> some boards, so that they can use this. This will reduce the data
> duplication across board files.
>
> If this is not true, then all the pads can be configured from the board
> files itself using omap_serial_init_port and you can set the required
> RX wakeup capability there as well.
>
Yes that be done but currently but that is not in my intention here
with my patch
I just want to retain rx wakeup by default to avoid breaking support
for any board.
Adding pin mux for each individual pin is a separate activity where I also
need access to various boards So I am leaving that to developers who
want to configure
for the corresponding boards using init_port api.
Removing mux from u-boot level and adding it to board file is beyond
the scope of this
patch series and is a separate topic of discussion, as current patch series
assumes that uarts are muxed from u-boot level and needs to only enable wakeup
capability for rx-pin.
Hope this clarifies.
--
Thanks,
Govindraj.R
>>So if any board needs specific mux they can go ahead and add required
>>mux data in
>>board file and use map_serial_init_port instead of current
>>omap_serial_init.
>>
>>
>>> Is it consistent that across all socs that only UART3 would have
>>UART/IRDA
>>> functions capability so that serial2 pads can always be called
> "rx_irxx"
>>> ?.
>>
>>Yes from OMAP2420 to OMAP4430 uart3 can used as irda.
>>
> Ok.
>>--
>>Thanks,
>>Govindraj.R
>
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 6/7] OMAP: Serial: Allow UART parameters to be configured from board file
2011-03-02 10:07 ` Govindraj
@ 2011-03-02 18:24 ` Tony Lindgren
2011-03-03 12:14 ` Govindraj
2011-03-03 5:08 ` Sricharan R
1 sibling, 1 reply; 25+ messages in thread
From: Tony Lindgren @ 2011-03-02 18:24 UTC (permalink / raw)
To: linux-arm-kernel
* Govindraj <govindraj.ti@gmail.com> [110302 02:05]:
>
> >>>>+static struct omap_device_pad default_serial1_pads[] __initdata = {
> >>>>+ ? ? ?{
> >>>>+ ? ? ? ? ? ? ?.name ? = "uart2_rx.uart2_rx",
> >>>>+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
> > OMAP_DEVICE_PAD_WAKEUP,
> >>>>+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
> >>>>+ ? ? ?},
...
AFAIK you should only need the OMAP_DEVICE_PAD_REMUX option for
omap24xx. And if you use that option, you also need the .idle
value.
Tony
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 6/7] OMAP: Serial: Allow UART parameters to be configured from board file
2011-03-02 18:24 ` Tony Lindgren
@ 2011-03-03 12:14 ` Govindraj
0 siblings, 0 replies; 25+ messages in thread
From: Govindraj @ 2011-03-03 12:14 UTC (permalink / raw)
To: linux-arm-kernel
On Wed, Mar 2, 2011 at 11:54 PM, Tony Lindgren <tony@atomide.com> wrote:
> * Govindraj <govindraj.ti@gmail.com> [110302 02:05]:
>>
>> >>>>+static struct omap_device_pad default_serial1_pads[] __initdata = {
>> >>>>+ ? ? ?{
>> >>>>+ ? ? ? ? ? ? ?.name ? = "uart2_rx.uart2_rx",
>> >>>>+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
>> > OMAP_DEVICE_PAD_WAKEUP,
>> >>>>+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
>> >>>>+ ? ? ?},
> ...
>
> AFAIK you should only need the OMAP_DEVICE_PAD_REMUX option for
> omap24xx. And if you use that option, you also need the .idle
> value.
>
Yes correct. I should avoid enabling rx-pad wakeup for omap24xx and
populate rx pad wakeup only for 3xxx onwards as done prior to this patch.
Will correct this in next version.
--
Thanks,
Govindraj.R
> Tony
>
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 6/7] OMAP: Serial: Allow UART parameters to be configured from board file
2011-03-02 10:07 ` Govindraj
2011-03-02 18:24 ` Tony Lindgren
@ 2011-03-03 5:08 ` Sricharan R
2011-03-04 6:25 ` Govindraj
1 sibling, 1 reply; 25+ messages in thread
From: Sricharan R @ 2011-03-03 5:08 UTC (permalink / raw)
To: linux-arm-kernel
Hi,
>-----Original Message-----
>From: Govindraj [mailto:govindraj.ti at gmail.com]
>Sent: Wednesday, March 02, 2011 3:37 PM
>To: Sricharan R
>Cc: Govindraj.R; linux-omap at vger.kernel.org;
linux-serial at vger.kernel.org;
>linux-arm-kernel at lists.infradead.org; Jon Hunter; Tony Lindgren; Benoit
>Cousson; Kevin Hilman; Paul Walmsley; Rajendra Nayak; Deepak Kattungal
>Subject: Re: [PATCH 6/7] OMAP: Serial: Allow UART parameters to be
>configured from board file
>
>On Wed, Mar 2, 2011 at 1:49 PM, Sricharan R <r.sricharan@ti.com> wrote:
>> Hi,
>>>-----Original Message-----
>>>From: Govindraj [mailto:govindraj.ti at gmail.com]
>>>Sent: Wednesday, March 02, 2011 1:11 PM
>>>To: Sricharan R
>>>Cc: Govindraj.R; linux-omap at vger.kernel.org;
>> linux-serial at vger.kernel.org;
>>>linux-arm-kernel at lists.infradead.org; Jon Hunter; Tony Lindgren; Benoit
>>>Cousson; Kevin Hilman; Paul Walmsley; Rajendra Nayak; Deepak Kattungal
>>>Subject: Re: [PATCH 6/7] OMAP: Serial: Allow UART parameters to be
>>>configured from board file
>>>
>>>On Wed, Mar 2, 2011 at 12:46 AM, Sricharan R <r.sricharan@ti.com>
wrote:
>>>> Hi,
>>>>>diff --git a/arch/arm/mach-omap2/serial.c
>> b/arch/arm/mach-omap2/serial.c
>>>>>index 755f4aa..530e9e3 100644
>>>>>--- a/arch/arm/mach-omap2/serial.c
>>>>>+++ b/arch/arm/mach-omap2/serial.c
>>>>>@@ -44,6 +44,15 @@
>>>>>
>>>>> static int omap_uart_con_id __initdata = -1;
>>>>>
>>>>>+static struct omap_uart_port_info omap_serial_default_info[] = {
>>>>>+ ? ? ?{
>>>>>+ ? ? ? ? ? ? ?.dma_enabled ? ?= 0,
>>>>>+ ? ? ? ? ? ? ?.dma_rx_buf_size = DEFAULT_RXDMA_BUFSIZE,
>>>>>+ ? ? ? ? ? ? ?.dma_rx_timeout = DEFAULT_RXDMA_TIMEOUT,
>>>>>+ ? ? ? ? ? ? ?.idle_timeout ? = DEFAULT_IDLE_TIMEOUT,
>>>>>+ ? ? ?},
>>>>>+};
>>>>>+
>>>>> static int uart_idle_hwmod(struct omap_device *od)
>>>>> {
>>>>> ? ? ? omap_hwmod_idle(od->hwmods[0]);
>>>>>@@ -66,6 +75,54 @@ static struct omap_device_pm_latency
>>>> omap_uart_latency[]
>>>>>= {
>>>>> ? ? ? },
>>>>> };
>>>>>
>>>>>+#ifdef CONFIG_OMAP_MUX
>>>>>+static struct omap_device_pad default_serial0_pads[] __initdata = {
>>>>>+ ? ? ?{
>>>>>+ ? ? ? ? ? ? ?.name ? = "uart1_rx.uart1_rx",
>>>>>+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
>> OMAP_DEVICE_PAD_WAKEUP,
>>>>>+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
>>>>>+ ? ? ?},
>>>>>+};
>>>>>+
>>>>>+static struct omap_device_pad default_serial1_pads[] __initdata = {
>>>>>+ ? ? ?{
>>>>>+ ? ? ? ? ? ? ?.name ? = "uart2_rx.uart2_rx",
>>>>>+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
>> OMAP_DEVICE_PAD_WAKEUP,
>>>>>+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
>>>>>+ ? ? ?},
>>>>>+};
>>>>>+
>>>>>+static struct omap_device_pad default_serial2_pads[] __initdata = {
>>>>>+ ? ? ?{
>>>>>+ ? ? ? ? ? ? ?.name ? = "uart3_rx_irrx.uart3_rx_irrx",
>>>>>+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
>> OMAP_DEVICE_PAD_WAKEUP,
>>>>>+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
>>>>>+ ? ? ?},
>>>>>+};
>>>>>+
>>>>>+static struct omap_device_pad default_omap36xx_serial3_pads[]
>> __initdata
>>>> =
>>>>>{
>>>>>+ ? ? ?{
>>>>>+ ? ? ? ? ? ? ?.name ? = "gpmc_wait3.uart4_rx",
>>>>>+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
>> OMAP_DEVICE_PAD_WAKEUP,
>>>>>+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE2,
>>>>>+ ? ? ?},
>>>>>+};
>>>>>+
>>>>>+static struct omap_device_pad default_omap4_serial3_pads[]
__initdata
>> =
>>>> {
>>>>>+ ? ? ?{
>>>>>+ ? ? ? ? ? ? ?.name ? = "uart4_rx.uart4_rx",
>>>>>+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
>> OMAP_DEVICE_PAD_WAKEUP,
>>>>>+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
>>>>>+ ? ? ?},
>>>>>+};
>>>> Here only the UART RX pins are muxed, so what about the cts, rts, tx
>>>pins?
>>>
>>>The intention here is to enable wakeup capabilities for uart rx pad.
>>>
>>>AFAIK most of the boards are currently dependent on bootloader for
>>>uart-muxing if any board is not dependent on bootloader then we
>>>can use omap_serial_init_port along with board_mux_info from board.
>>>
>> Yes. The idea is to be independent of the bootloaders for mux settings.
>>
>>>Prior to this change uart wakeup is based on rx_pad and we were
>> populating
>>>offset and using omap_ctrl api's to read/write which is cleaned up now.
>>>Most of boards are dependent on uart-rx wakeup to avoid breaking any
>>>board support we
>>>are using omap_serial_init by filling default values, which provides
>>>us with same
>>>environment but with right approach towards handling mux data with a
>>>handshake with
>>>hwmod framework.
>>>
>> Now, in this change only the RX pin is configured. So if some board
uses
>> omap_serial_init then only the RX is going to be configured.
>> How will they configure the rest of the pins?
>
>
>They should call omap_serial_init_port to configure each individual uart
>with
>mux_info filled and not use omap_serial_init.
>
>If any board is not dependent for mux from u-boot then they use above
said
>init_port func.
>
>
>> They cannot call omap_serial_init_port after this just to configure the
>> rest of the mux pins( cts, rts, tx).
>
>No. You need to use either omap_serial_init_port or omap_serial_init
>you cannot call both apis from board file please refer to both func
>documentation.
>
>Also please note i am not configuring all uart pins for pullups and pull
>downs
>with this patch series and its not related to this patch series.
>I am only enabling wakeup-enable pin for rx as it was done before.
>
>> So data which is passed from omap_serial_init should have the
>> configuration
>> for all the pins, and this default data should be consistent across
>> atleast
>> some boards, so that they can use this. This will reduce the data
>> duplication across board files.
>>
>> If this is not true, then all the pads can be configured from the board
>> files itself using omap_serial_init_port and you can set the required
>> RX wakeup capability there as well.
>>
>
>Yes that be done but currently but that is not in my intention here
>with my patch
>I just want to retain rx wakeup by default to avoid breaking support
>for any board.
>
>Adding pin mux for each individual pin is a separate activity where I
also
>need access to various boards So I am leaving that to developers who
>want to configure
>for the corresponding boards using init_port api.
>
>Removing mux from u-boot level and adding it to board file is beyond
>the scope of this
>patch series and is a separate topic of discussion, as current patch
series
>assumes that uarts are muxed from u-boot level and needs to only enable
>wakeup
>capability for rx-pin.
>
>Hope this clarifies.
>
It is true that this patch is not intending to configure the pads.
But my question is, after this patch say
1) some board file calls omap_serial_port.
2) As a result , all the uarts devices are build and only the Rx pad is
configured for each device.
3) After this there will be no way of configuring the rest of the pads
??
That should not happen. Also relying that the bootloaders are going
to do the configuration is not correct.
So if some board calls omap_serial_port then there should be default
values for all pads which a board can use, otherwise the board calls
omap_serial_init_port for each of the device.
>--
>Thanks,
>Govindraj.R
>
>
>>>So if any board needs specific mux they can go ahead and add required
>>>mux data in
>>>board file and use map_serial_init_port instead of current
>>>omap_serial_init.
>>>
>>>
>>>> Is it consistent that across all socs that only UART3 would have
>>>UART/IRDA
>>>> functions capability so that serial2 pads can always be called
>> "rx_irxx"
>>>> ?.
>>>
>>>Yes from OMAP2420 to OMAP4430 uart3 can used as irda.
>>>
>> Ok.
>>>--
>>>Thanks,
>>>Govindraj.R
>>
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 6/7] OMAP: Serial: Allow UART parameters to be configured from board file
2011-03-03 5:08 ` Sricharan R
@ 2011-03-04 6:25 ` Govindraj
0 siblings, 0 replies; 25+ messages in thread
From: Govindraj @ 2011-03-04 6:25 UTC (permalink / raw)
To: linux-arm-kernel
On Thu, Mar 3, 2011 at 10:38 AM, Sricharan R <r.sricharan@ti.com> wrote:
> Hi,
>>-----Original Message-----
>>From: Govindraj [mailto:govindraj.ti at gmail.com]
>>Sent: Wednesday, March 02, 2011 3:37 PM
>>To: Sricharan R
>>Cc: Govindraj.R; linux-omap at vger.kernel.org;
> linux-serial at vger.kernel.org;
>>linux-arm-kernel at lists.infradead.org; Jon Hunter; Tony Lindgren; Benoit
>>Cousson; Kevin Hilman; Paul Walmsley; Rajendra Nayak; Deepak Kattungal
>>Subject: Re: [PATCH 6/7] OMAP: Serial: Allow UART parameters to be
>>configured from board file
>>
>>On Wed, Mar 2, 2011 at 1:49 PM, Sricharan R <r.sricharan@ti.com> wrote:
>>> Hi,
>>>>-----Original Message-----
>>>>From: Govindraj [mailto:govindraj.ti at gmail.com]
>>>>Sent: Wednesday, March 02, 2011 1:11 PM
>>>>To: Sricharan R
>>>>Cc: Govindraj.R; linux-omap at vger.kernel.org;
>>> linux-serial at vger.kernel.org;
>>>>linux-arm-kernel at lists.infradead.org; Jon Hunter; Tony Lindgren; Benoit
>>>>Cousson; Kevin Hilman; Paul Walmsley; Rajendra Nayak; Deepak Kattungal
>>>>Subject: Re: [PATCH 6/7] OMAP: Serial: Allow UART parameters to be
>>>>configured from board file
>>>>
>>>>On Wed, Mar 2, 2011 at 12:46 AM, Sricharan R <r.sricharan@ti.com>
> wrote:
>>>>> Hi,
>>>>>>diff --git a/arch/arm/mach-omap2/serial.c
>>> b/arch/arm/mach-omap2/serial.c
>>>>>>index 755f4aa..530e9e3 100644
>>>>>>--- a/arch/arm/mach-omap2/serial.c
>>>>>>+++ b/arch/arm/mach-omap2/serial.c
>>>>>>@@ -44,6 +44,15 @@
>>>>>>
>>>>>> static int omap_uart_con_id __initdata = -1;
>>>>>>
>>>>>>+static struct omap_uart_port_info omap_serial_default_info[] = {
>>>>>>+ ? ? ?{
>>>>>>+ ? ? ? ? ? ? ?.dma_enabled ? ?= 0,
>>>>>>+ ? ? ? ? ? ? ?.dma_rx_buf_size = DEFAULT_RXDMA_BUFSIZE,
>>>>>>+ ? ? ? ? ? ? ?.dma_rx_timeout = DEFAULT_RXDMA_TIMEOUT,
>>>>>>+ ? ? ? ? ? ? ?.idle_timeout ? = DEFAULT_IDLE_TIMEOUT,
>>>>>>+ ? ? ?},
>>>>>>+};
>>>>>>+
>>>>>> static int uart_idle_hwmod(struct omap_device *od)
>>>>>> {
>>>>>> ? ? ? omap_hwmod_idle(od->hwmods[0]);
>>>>>>@@ -66,6 +75,54 @@ static struct omap_device_pm_latency
>>>>> omap_uart_latency[]
>>>>>>= {
>>>>>> ? ? ? },
>>>>>> };
>>>>>>
>>>>>>+#ifdef CONFIG_OMAP_MUX
>>>>>>+static struct omap_device_pad default_serial0_pads[] __initdata = {
>>>>>>+ ? ? ?{
>>>>>>+ ? ? ? ? ? ? ?.name ? = "uart1_rx.uart1_rx",
>>>>>>+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
>>> OMAP_DEVICE_PAD_WAKEUP,
>>>>>>+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
>>>>>>+ ? ? ?},
>>>>>>+};
>>>>>>+
>>>>>>+static struct omap_device_pad default_serial1_pads[] __initdata = {
>>>>>>+ ? ? ?{
>>>>>>+ ? ? ? ? ? ? ?.name ? = "uart2_rx.uart2_rx",
>>>>>>+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
>>> OMAP_DEVICE_PAD_WAKEUP,
>>>>>>+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
>>>>>>+ ? ? ?},
>>>>>>+};
>>>>>>+
>>>>>>+static struct omap_device_pad default_serial2_pads[] __initdata = {
>>>>>>+ ? ? ?{
>>>>>>+ ? ? ? ? ? ? ?.name ? = "uart3_rx_irrx.uart3_rx_irrx",
>>>>>>+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
>>> OMAP_DEVICE_PAD_WAKEUP,
>>>>>>+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
>>>>>>+ ? ? ?},
>>>>>>+};
>>>>>>+
>>>>>>+static struct omap_device_pad default_omap36xx_serial3_pads[]
>>> __initdata
>>>>> =
>>>>>>{
>>>>>>+ ? ? ?{
>>>>>>+ ? ? ? ? ? ? ?.name ? = "gpmc_wait3.uart4_rx",
>>>>>>+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
>>> OMAP_DEVICE_PAD_WAKEUP,
>>>>>>+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE2,
>>>>>>+ ? ? ?},
>>>>>>+};
>>>>>>+
>>>>>>+static struct omap_device_pad default_omap4_serial3_pads[]
> __initdata
>>> =
>>>>> {
>>>>>>+ ? ? ?{
>>>>>>+ ? ? ? ? ? ? ?.name ? = "uart4_rx.uart4_rx",
>>>>>>+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
>>> OMAP_DEVICE_PAD_WAKEUP,
>>>>>>+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
>>>>>>+ ? ? ?},
>>>>>>+};
>>>>> Here only the UART RX pins are muxed, so what about the cts, rts, tx
>>>>pins?
>>>>
>>>>The intention here is to enable wakeup capabilities for uart rx pad.
>>>>
>>>>AFAIK most of the boards are currently dependent on bootloader for
>>>>uart-muxing if any board is not dependent on bootloader then we
>>>>can use omap_serial_init_port along with board_mux_info from board.
>>>>
>>> Yes. The idea is to be independent of the bootloaders for mux settings.
>>>
>>>>Prior to this change uart wakeup is based on rx_pad and we were
>>> populating
>>>>offset and using omap_ctrl api's to read/write which is cleaned up now.
>>>>Most of boards are dependent on uart-rx wakeup to avoid breaking any
>>>>board support we
>>>>are using omap_serial_init by filling default values, which provides
>>>>us with same
>>>>environment but with right approach towards handling mux data with a
>>>>handshake with
>>>>hwmod framework.
>>>>
>>> Now, in this change only the RX pin is configured. So if some board
> uses
>>> omap_serial_init then only the RX is going to be configured.
>>> How will they configure the rest of the pins?
>>
>>
>>They should call omap_serial_init_port to configure each individual uart
>>with
>>mux_info filled and not use omap_serial_init.
>>
>>If any board is not dependent for mux from u-boot then they use above
> said
>>init_port func.
>>
>>
>>> They cannot call omap_serial_init_port after this just to configure the
>>> rest of the mux pins( cts, rts, tx).
>>
>>No. You need to use either omap_serial_init_port or omap_serial_init
>>you cannot call both apis from board file please refer to both func
>>documentation.
>>
>>Also please note i am not configuring all uart pins for pullups and pull
>>downs
>>with this patch series and its not related to this patch series.
>>I am only enabling wakeup-enable pin for rx as it was done before.
>>
>>> So data which is passed from omap_serial_init should have the
>>> configuration
>>> for all the pins, and this default data should be consistent across
>>> atleast
>>> some boards, so that they can use this. This will reduce the data
>>> duplication across board files.
>>>
>>> If this is not true, then all the pads can be configured from the board
>>> files itself using omap_serial_init_port and you can set the required
>>> RX wakeup capability there as well.
>>>
>>
>>Yes that be done but currently but that is not in my intention here
>>with my patch
>>I just want to retain rx wakeup by default to avoid breaking support
>>for any board.
>>
>>Adding pin mux for each individual pin is a separate activity where I
> also
>>need access to various boards So I am leaving that to developers who
>>want to configure
>>for the corresponding boards using init_port api.
>>
>>Removing mux from u-boot level and adding it to board file is beyond
>>the scope of this
>>patch series and is a separate topic of discussion, as current patch
> series
>>assumes that uarts are muxed from u-boot level and needs to only enable
>>wakeup
>>capability for rx-pin.
>>
>>Hope this clarifies.
>>
> It is true that this patch is not intending to configure the pads.
>
> But my question is, after this patch say
> ? 1) some board file calls omap_serial_port.
> ? 2) As a result , all the uarts devices are build and only the Rx pad is
> configured for each device.
> ? 3) After this there will be no way of configuring the rest of the pads
> ??
> ? ? ?That should not happen. Also relying that the bootloaders are going
> ? ? ?to do the configuration is not correct.
>
> ? ? ?So if some board calls omap_serial_port then there should be default
> values for all pads which a board can use, otherwise the board calls
> omap_serial_init_port for each of the device.
ok I will add default values for all pads and enable rx wakeup for rx pad.
Will incorporate in next version.
--
Thanks,
Govindraj.R
>
>
>>--
>>Thanks,
>>Govindraj.R
>>
>>
>>>>So if any board needs specific mux they can go ahead and add required
>>>>mux data in
>>>>board file and use map_serial_init_port instead of current
>>>>omap_serial_init.
>>>>
>>>>
>>>>> Is it consistent that across all socs that only UART3 would have
>>>>UART/IRDA
>>>>> functions capability so that serial2 pads can always be called
>>> "rx_irxx"
>>>>> ?.
>>>>
>>>>Yes from OMAP2420 to OMAP4430 uart3 can used as irda.
>>>>
>>> Ok.
>>>>--
>>>>Thanks,
>>>>Govindraj.R
>>>
>
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 7/7] Serial: OMAP2+: Make the RX_TIMEOUT for DMA configurable for each UART
2011-02-28 14:39 [PATCH 0/7] OMAP2+: UART: runtime conversion + cleanup Govindraj.R
` (5 preceding siblings ...)
2011-02-28 14:39 ` [PATCH 6/7] OMAP: Serial: Allow UART parameters to be configured from board file Govindraj.R
@ 2011-02-28 14:39 ` Govindraj.R
6 siblings, 0 replies; 25+ messages in thread
From: Govindraj.R @ 2011-02-28 14:39 UTC (permalink / raw)
To: linux-arm-kernel
From: Jon Hunter <jon-hunter@ti.com>
When using DMA there are two timeouts defined. The first timeout,
rx_timeout, is really a polling rate in which software polls the
DMA status to see if the DMA has finished. This is necessary for
the RX side because we do not know how much data we will receive.
The secound timeout, RX_TIMEOUT, is a timeout after which the
DMA will be stopped if no more data is received. To make this
clearer, rename rx_timeout as rx_poll_rate and rename the
function serial_omap_rx_timeout() to serial_omap_rxdma_poll().
The OMAP-Serial driver defines an RX_TIMEOUT of 3 seconds that is
used to indicate when the DMA for UART can be stopped if no more
data is received. The value is a global definition that is applied
to all instances of the UART.
Each UART may be used for a different purpose and so the timeout
required may differ. Make this value configurable for each UART so
that this value can be optimised for power savings.
Signed-off-by: Govindraj.R <govindraj.raja@ti.com>
Signed-off-by: Jon Hunter <jon-hunter@ti.com>
---
arch/arm/mach-omap2/serial.c | 2 ++
arch/arm/plat-omap/include/plat/omap-serial.h | 6 ++++--
drivers/tty/serial/omap-serial.c | 15 ++++++++-------
3 files changed, 14 insertions(+), 9 deletions(-)
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 530e9e3..ff52442 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -48,6 +48,7 @@ static struct omap_uart_port_info omap_serial_default_info[] = {
{
.dma_enabled = 0,
.dma_rx_buf_size = DEFAULT_RXDMA_BUFSIZE,
+ .dma_rx_poll_rate = DEFAULT_RXDMA_POLLRATE,
.dma_rx_timeout = DEFAULT_RXDMA_TIMEOUT,
.idle_timeout = DEFAULT_IDLE_TIMEOUT,
},
@@ -268,6 +269,7 @@ void __init omap_serial_init_port(struct omap_board_data *bdata,
pdata->flags = UPF_BOOT_AUTOCONF;
pdata->dma_enabled = info->dma_enabled;
pdata->dma_rx_buf_size = info->dma_rx_buf_size;
+ pdata->dma_rx_poll_rate = info->dma_rx_poll_rate;
pdata->dma_rx_timeout = info->dma_rx_timeout;
pdata->idle_timeout = info->idle_timeout;
if (bdata->id == omap_uart_con_id)
diff --git a/arch/arm/plat-omap/include/plat/omap-serial.h b/arch/arm/plat-omap/include/plat/omap-serial.h
index 4f12d6c..e338f4e 100644
--- a/arch/arm/plat-omap/include/plat/omap-serial.h
+++ b/arch/arm/plat-omap/include/plat/omap-serial.h
@@ -51,8 +51,8 @@
#define OMAP_UART_DMA_CH_FREE -1
-#define RX_TIMEOUT (3 * HZ) /* RX DMA timeout (jiffies) */
-#define DEFAULT_RXDMA_TIMEOUT 1 /* RX DMA polling rate (us) */
+#define DEFAULT_RXDMA_TIMEOUT (3 * HZ) /* RX DMA timeout (jiffies) */
+#define DEFAULT_RXDMA_POLLRATE 1 /* RX DMA polling rate (us) */
#define DEFAULT_RXDMA_BUFSIZE 4096 /* RX DMA buffer size */
#define DEFAULT_IDLE_TIMEOUT (5 * HZ) /* UART idle timeout (secs) */
@@ -70,6 +70,7 @@ struct omap_uart_port_info {
unsigned int console_uart;
unsigned int dma_rx_buf_size;/* DMA Rx Buffer Size */
unsigned int dma_rx_timeout; /* DMA RX timeout */
+ unsigned int dma_rx_poll_rate; /* DMA RX timeout */
unsigned int idle_timeout; /* OMAP UART idle timeout */
void __iomem *wk_st;
@@ -99,6 +100,7 @@ struct uart_omap_dma {
/* timer to poll activity on rx dma */
struct timer_list rx_timer;
unsigned int rx_buf_size;
+ unsigned int rx_poll_rate;
unsigned int rx_timeout;
};
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 008645c..5c3d2fc 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -51,7 +51,7 @@ static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS];
/* Forward declaration of functions */
static void uart_tx_dma_callback(int lch, u16 ch_status, void *data);
-static void serial_omap_rx_timeout(unsigned long uart_no);
+static void serial_omap_rxdma_poll(unsigned long uart_no);
static int serial_omap_start_rxdma(struct uart_omap_port *up);
static void omap_uart_mdr1_errataset(struct uart_omap_port *up);
@@ -589,7 +589,7 @@ static int serial_omap_startup(struct uart_port *port)
(dma_addr_t *)&(up->uart_dma.tx_buf_dma_phys),
0);
init_timer(&(up->uart_dma.rx_timer));
- up->uart_dma.rx_timer.function = serial_omap_rx_timeout;
+ up->uart_dma.rx_timer.function = serial_omap_rxdma_poll;
up->uart_dma.rx_timer.data = up->pdev->id;
/* Currently the buffer size is 4KB. Can increase it */
up->uart_dma.rx_buf = dma_alloc_coherent(NULL,
@@ -1191,7 +1191,7 @@ static int serial_omap_resume(struct device *dev)
return 0;
}
-static void serial_omap_rx_timeout(unsigned long uart_no)
+static void serial_omap_rxdma_poll(unsigned long uart_no)
{
struct uart_omap_port *up = ui[uart_no];
unsigned int curr_dma_pos, curr_transmitted_size;
@@ -1201,9 +1201,9 @@ static void serial_omap_rx_timeout(unsigned long uart_no)
if ((curr_dma_pos == up->uart_dma.prev_rx_dma_pos) ||
(curr_dma_pos == 0)) {
if (jiffies_to_msecs(jiffies - up->port_activity) <
- RX_TIMEOUT) {
+ up->uart_dma.rx_timeout) {
mod_timer(&up->uart_dma.rx_timer, jiffies +
- usecs_to_jiffies(up->uart_dma.rx_timeout));
+ usecs_to_jiffies(up->uart_dma.rx_poll_rate));
} else {
serial_omap_stop_rxdma(up);
up->ier |= (UART_IER_RDI | UART_IER_RLSI);
@@ -1232,7 +1232,7 @@ static void serial_omap_rx_timeout(unsigned long uart_no)
}
} else {
mod_timer(&up->uart_dma.rx_timer, jiffies +
- usecs_to_jiffies(up->uart_dma.rx_timeout));
+ usecs_to_jiffies(up->uart_dma.rx_poll_rate));
}
up->port_activity = jiffies;
}
@@ -1270,7 +1270,7 @@ static int serial_omap_start_rxdma(struct uart_omap_port *up)
/* FIXME: Cache maintenance needed here? */
omap_start_dma(up->uart_dma.rx_dma_channel);
mod_timer(&up->uart_dma.rx_timer, jiffies +
- usecs_to_jiffies(up->uart_dma.rx_timeout));
+ usecs_to_jiffies(up->uart_dma.rx_poll_rate));
up->uart_dma.rx_dma_used = true;
return ret;
}
@@ -1412,6 +1412,7 @@ static int serial_omap_probe(struct platform_device *pdev)
up->use_dma = 1;
up->uart_dma.rx_buf_size = omap_up_info->dma_rx_buf_size;
up->uart_dma.rx_timeout = omap_up_info->dma_rx_timeout;
+ up->uart_dma.rx_poll_rate = omap_up_info->dma_rx_poll_rate;
spin_lock_init(&(up->uart_dma.tx_lock));
spin_lock_init(&(up->uart_dma.rx_lock));
up->uart_dma.tx_dma_channel = OMAP_UART_DMA_CH_FREE;
--
1.7.1
^ permalink raw reply related [flat|nested] 25+ messages in thread