OMAP2+: Serial: Runtime adaptation + cleanup
Subsystems (6)
v2 cover OMAP2+: Serial: Runtime adaptation + cleanup
Converting uart driver to adapt to pm runtime api's. Code re-org + cleanup.
Moving some functionality from serial.c to omap-serial.c
Changes involves:
================
1.) Cleaning up certain uart calls from sram_idle func.
2.) Removed all types of uart clock handling code from serial.c
3.) Using hwmod_mux api enable wakeup capability for uart pad during
hwmod_idle state i.e., when uart clocks are disabled we can enable io-pad wakeup capability for uart if mux_data is available for given uart. Also during during resume from idle call to uart we need to enable clocks back conditionally and this can be done only when io-pad wakeup event bit is set for uart_rx pad. So we need a hwmod api which can probe the uart pad and let us know whether a uart wakeup happened. So omap_hmwod_pad_wakeup_status api is added to meet this requirement.
3.) Adapted omap-serial driver to use runtime api's.
4.) Modify serial_init calls to accept certain uart parameters from board file. 5.) using resume_call to enable uart port back untill we have irq_chaining available.
Patch series is based on Kevin's PM Tree / pm-core branch [2.6.39-rc4] Patch series hosted at https://gitorious.org/uart_runtime/pm
Testing updates:
----------------
3430SDP:
retention, off_mode, system_wide suspend is tested. (earlyprintk & no_console_suspend checked)
OMAP3630 - Zoom3:
pm-retention checked, off mode for per domain checked. [uart3/uart4 in per domain on omap3630].
[ZOOM3 tested with uart3 as console uart and pm-ret checked]
OMAP4430-SDP: Boot tested.
OMAP2420/2430SDP: Boot tested.
-------------
Deepak K (1):
OMAP: Serial: Allow UART parameters to be configured from board file
Govindraj.R (10):
OMAP2+: UART: Remove certain uart calls from sram_idle OMAP2+: UART: Remove uart clock handling code from serial.c OMAP2+: Serial: Add default mux for all uarts.
Serial: OMAP: Add runtime pm support for omap-serial driver
OMAP: Serial: Hold console lock for console usage.
Serial: OMAP2+: Move erratum handling from serial.c
OMAP3: Serial: Remove uart pads from 3430 board file. OMAP2+: hwmod: Add api to enable io_ring wakeup.
OMAP: Serial: Use resume call from prcm to enable uart
OMAP2: Serial: Add no async wake flag.
Jon Hunter (1):
Serial: OMAP2+: Make the RX_TIMEOUT for DMA configurable for each
UART
arch/arm/mach-omap2/board-2430sdp.c | 3 +- arch/arm/mach-omap2/board-3430sdp.c | 101 +--- arch/arm/mach-omap2/board-4430sdp.c | 11 +- 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 | 11 +- 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/mux.c | 23 + arch/arm/mach-omap2/mux.h | 13 + arch/arm/mach-omap2/omap_hwmod.c | 47 ++ arch/arm/mach-omap2/pm24xx.c | 19 +- arch/arm/mach-omap2/pm34xx.c | 26 +- arch/arm/mach-omap2/serial.c | 917 +++++++------------------ arch/arm/plat-omap/include/plat/omap-serial.h | 38 +- arch/arm/plat-omap/include/plat/omap_device.h | 1 + arch/arm/plat-omap/include/plat/omap_hwmod.h | 2 + arch/arm/plat-omap/include/plat/serial.h | 13 +- arch/arm/plat-omap/omap_device.c | 34 +- drivers/tty/serial/omap-serial.c | 319 ++++++++- 38 files changed, 747 insertions(+), 902 deletions(-)
PATCH v2 1/12 OMAP2+: UART: Remove certain uart calls from sram_idle
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.
2.) omap_uart_can_sleep :- not needed driver can autosuspend based on usage_count
and autosuspend delay.
3.) omap_uart_prepare_suspend :- omap-serial can be taken care with driver
suspend/resume hooks.
4.) Also remove individual uart_prepare/resume calls.
--- arch/arm/mach-omap2/pm24xx.c | 19 ------------------- arch/arm/mach-omap2/pm34xx.c | 24 ------------------------ arch/arm/plat-omap/include/plat/serial.h | 6 ------ 3 files changed, 0 insertions(+), 49 deletions(-)
arch/arm/mach-omap2/pm24xx.c +0 -19
@@ -132,27 +132,11 @@ static void omap2_enter_full_retention(void)if (omap_irq_pending ()) goto no_sleep; -/* Block console output in case it is on one of the OMAP UARTs */ -if (!is_suspending ()) -if (!console_trylock ()) - goto no_sleep; - -omap_uart_prepare_idle (0 ); -omap_uart_prepare_idle (1 ); -omap_uart_prepare_idle (2 ); -/* Jump to SRAM suspend code */ omap2_sram_suspend (sdrc_read_reg (SDRC_DLLA_CTRL ),OMAP_SDRC_REGADDR (SDRC_DLLA_CTRL ),OMAP_SDRC_REGADDR (SDRC_POWER )); -omap_uart_resume_idle (2 ); -omap_uart_resume_idle (1 ); -omap_uart_resume_idle (0 ); - -if (!is_suspending ()) -console_unlock (); - no_sleep:if (omap2_pm_debug) {unsigned long long tmp;
@@ -267,8 +251,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 +301,6 @@ static int omap2_pm_suspend(void) mir1 =omap_readl (0x480fe0a4 );omap_writel (1 <<5 ,0x480fe0ac ); -omap_uart_prepare_suspend ();omap2_enter_full_retention ();omap_writel (mir1,0x480fe0a4 );
arch/arm/mach-omap2/pm34xx.c +0 -24
@@ -391,18 +391,9 @@ void omap_sram_idle(void)omap3_enable_io_chain (); } -/* Block console output in case it is on one of the OMAP UARTs */ -if (!is_suspending ()) -if (per_next_state <PWRDM_POWER_ON || - core_next_state <PWRDM_POWER_ON ) -if (!console_trylock ()) - goto console_still_active; -/* PER */ if (per_next_state <PWRDM_POWER_ON ) { per_going_off = (per_next_state ==PWRDM_POWER_OFF ) ?1 :0 ; -omap_uart_prepare_idle (2 ); -omap_uart_prepare_idle (3 );omap2_gpio_prepare_for_idle (per_going_off);if (per_next_state ==PWRDM_POWER_OFF )omap3_per_save_context ();
@@ -410,8 +401,6 @@ void omap_sram_idle(void)/* CORE */ if (core_next_state <PWRDM_POWER_ON ) { -omap_uart_prepare_idle (0 ); -omap_uart_prepare_idle (1 );if (core_next_state ==PWRDM_POWER_OFF ) {omap3_core_save_context ();omap3_cm_save_context ();
@@ -458,8 +447,6 @@ void omap_sram_idle(void)omap3_sram_restore_context ();omap2_sms_restore_context (); } -omap_uart_resume_idle (0 ); -omap_uart_resume_idle (1 );if (core_next_state ==PWRDM_POWER_OFF ) omap2_prm_clear_mod_reg_bits(OMAP3430_AUTO_OFF_MASK, OMAP3430_GR_MOD,
@@ -473,14 +460,8 @@ void omap_sram_idle(void)omap2_gpio_resume_after_idle ();if (per_prev_state ==PWRDM_POWER_OFF )omap3_per_restore_context (); -omap_uart_resume_idle (2 ); -omap_uart_resume_idle (3 ); } -if (!is_suspending ()) -console_unlock (); - -console_still_active:/* Disable IO-PAD and IO-CHAIN wakeup */ if (omap3_has_io_wakeup() && (per_next_state < PWRDM_POWER_ON ||
@@ -499,8 +480,6 @@ int omap3_can_sleep(void) {if (!sleep_while_idle)return 0 ; -if (!omap_uart_can_sleep ()) -return 0 ;return 1 ; }
@@ -549,7 +528,6 @@ static int omap3_pm_suspend(void) goto restore; } -omap_uart_prepare_suspend ();omap3_intc_suspend ();omap_sram_idle ();
@@ -596,14 +574,12 @@ static int omap3_pm_begin(suspend_state_t state) {disable_hlt (); suspend_state = state; -omap_uart_enable_irqs (0 );return 0 ; }static void omap3_pm_end (void ) { suspend_state =PM_SUSPEND_ON ; -omap_uart_enable_irqs (1 );enable_hlt ();return ; }
arch/arm/plat-omap/include/plat/serial.h +0 -6
@@ -106,12 +106,6 @@ struct omap_board_data;extern void omap_serial_init (void );extern void omap_serial_init_port (struct omap_board_data *bdata); -extern int omap_uart_can_sleep (void ); -extern void omap_uart_check_wakeup (void ); -extern void omap_uart_prepare_suspend (void ); -extern void omap_uart_prepare_idle (int num); -extern void omap_uart_resume_idle (int num); -extern void omap_uart_enable_irqs (int enable);#endif #endif
Signature · 1 line
1.7.1
PATCH v2 2/12 OMAP2+: UART: Remove uart clock handling code from serial.c
In reply to Govindraj.RCleanup serial.c file in preparation to addition of runtime api's in omap-serial file. Remove all clock handling mechanism as this will be taken care with pm runtime api's 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 func 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.
--- arch/arm/mach-omap2/serial.c | 754 ++----------------------- arch/arm/plat-omap/include/plat/omap-serial.h | 15 +- 2 files changed, 74 insertions(+), 695 deletions(-)
arch/arm/mach-omap2/serial.c +62 -692
@@ -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 +#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; - -/* 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) +static void omap_uart_idle_init (struct omap_uart_port_info *uart, +unsigned short num) { -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) -{ -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,49 @@ 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) -{ -struct platform_device *pdev =to_platform_device (dev); -struct omap_device *odev =to_omap_device (pdev); -struct omap_uart_state *uart = odev->hwmods[0 ]->dev_attr; - -return sprintf (buf,"%u\n" , uart->timeout /HZ ); -} - -static ssize_t sleep_timeout_store (struct device *dev, -struct device_attribute *attr, -const char *buf,size_t n) -{ -struct platform_device *pdev =to_platform_device (dev); -struct omap_device *odev =to_omap_device (pdev); -struct omap_uart_state *uart = odev->hwmods[0 ]->dev_attr; -unsigned int value; - -if (sscanf (buf,"%u" , &value) !=1 ) { -dev_err (dev,"sleep_timeout_store: Invalid value\n" ); -return -EINVAL ; } - - uart->timeout = value *HZ ; -if (uart->timeout) -mod_timer (&uart->timer, jiffies + uart->timeout); -else -/* A zero value means disable timeout feature */ -omap_uart_block_sleep (uart); - -return n; -} - -static DEVICE_ATTR(sleep_timeout, 0644, sleep_timeout_show, - sleep_timeout_store); -#define DEV_CREATE_FILE (dev, attr) WARN_ON(device_create_file(dev, attr)) -#else -static inline void omap_uart_idle_init (struct omap_uart_state *uart) {} -static void omap_uart_block_sleep (struct omap_uart_state *uart) -{ -/* 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) +char *cmdline_find_option (char *str) { -if (UART_RX == offset) { -unsigned int lsr; - lsr =__serial_read_reg (up,UART_LSR ); -if (!(lsr &UART_LSR_DR )) -return -EPERM ; - } +extern char *saved_command_line; -return __serial_read_reg (up, offset); +return strstr (saved_command_line, str); } -static void serial_out_override (struct uart_port *up,int offset,int value) +struct omap_hwmod *omap_uart_hwmod_lookup (int num) { -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 ) { +#ifdef CONFIG_EARLY_PRINTK 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_setup*() 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 ); - +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);
@@ -709,149 +179,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 ; - - 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 ; +/* Enable the MDR1 errata for OMAP3 */ +if (cpu_is_omap34xx ()) + pdata->errata |= UART_ERRATA_i202_MDR1_ACCESS; - pdata = &omap_up; - pdata_size =sizeof (struct omap_uart_port_info ); -#endif +omap_uart_idle_init (pdata, bdata->id); -if (WARN_ON (!oh)) -return ; + pdata->uartclk =OMAP24XX_BASE_BAUD *16 ; + pdata->flags =UPF_BOOT_AUTOCONF ; +if (bdata->id == omap_uart_con_id) + pdata->console_uart = true; - 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 +234,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); - } }
arch/arm/plat-omap/include/plat/omap-serial.h +12 -3
@@ -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,7 @@ struct uart_omap_port {unsigned char msr_saved_flags;char name[20 ];unsigned long port_activity; + unsigned int errata; };#endif /* __OMAP_SERIAL_H__ */
Signature · 1 line
1.7.1
OMAP2+: UART: Remove uart clock handling code from serial.c
Quoted 13 lines · On Fri, 29 Apr 2011 18:09:46 +0530 "Govindraj.R" <[email protected]> wrote:
Cleanup
serial.cfile in preparation to addition of runtime api's in omap-serial file. Remove all clock handling mechanism as this will be taken care with pm runtime api's inomap-serial.cfile 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_resumecallback for
get_synccall. No need to save context as all reg details available inuart_portstructure can be used for restore, so add missing regs in uart port struct.
3.) Add func 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.
Quoted 1 line
Signed-off-by Govindraj.R <[email protected]>
The tty parts of this look fine, the OMAP bits I have no idea.
So for the tty bits with my serial maintainer hat on
but its mostly up to the ARM/OMAP people
PATCH v2 3/12 OMAP2+: Serial: Add default mux for all uarts.
In reply to Govindraj.RAdd default mux data for all uarts if mux info is not passed from board file to avoid breaking any board support.
--- arch/arm/mach-omap2/serial.c | 127 +++++++++++++++++++++++++++++++++++++++++- 1 files changed, 126 insertions(+), 1 deletions(-)
arch/arm/mach-omap2/serial.c +126 -1
@@ -66,6 +66,129 @@ static struct omap_device_pm_latency omap_uart_latency[] = { }, }; +#ifdef CONFIG_OMAP_MUX +static struct omap_device_pad default_uart1_pads[]__initdata = { + { + .name ="uart1_cts.uart1_cts" , + .enable =OMAP_PIN_INPUT_PULLUP |OMAP_MUX_MODE0 , + }, + { + .name ="uart1_rts.uart1_rts" , + .enable =OMAP_PIN_OUTPUT |OMAP_MUX_MODE0 , + }, + { + .name ="uart1_tx.uart1_tx" , + .enable =OMAP_PIN_OUTPUT |OMAP_MUX_MODE0 , + }, + { + .name ="uart1_rx.uart1_rx" , + .flags =OMAP_DEVICE_PAD_REMUX |OMAP_DEVICE_PAD_WAKEUP , + .enable =OMAP_PIN_INPUT_PULLUP |OMAP_MUX_MODE0 , + }, +}; + +static struct omap_device_pad default_uart2_pads[]__initdata = { + { + .name ="uart2_cts.uart2_cts" , + .enable =OMAP_PIN_INPUT_PULLUP |OMAP_MUX_MODE0 , + }, + { + .name ="uart2_rts.uart2_rts" , + .enable =OMAP_PIN_OUTPUT |OMAP_MUX_MODE0 , + }, + { + .name ="uart2_tx.uart2_tx" , + .enable =OMAP_PIN_OUTPUT |OMAP_MUX_MODE0 , + }, + { + .name ="uart2_rx.uart2_rx" , + .flags =OMAP_DEVICE_PAD_REMUX |OMAP_DEVICE_PAD_WAKEUP , + .enable =OMAP_PIN_INPUT_PULLUP |OMAP_MUX_MODE0 , + }, +}; + +static struct omap_device_pad default_uart3_pads[]__initdata = { + { + .name ="uart3_cts_rctx.uart3_cts_rctx" , + .enable =OMAP_PIN_INPUT_PULLUP |OMAP_MUX_MODE0 , + }, + { + .name ="uart3_rts_sd.uart3_rts_sd" , + .enable =OMAP_PIN_OUTPUT |OMAP_MUX_MODE0 , + }, + { + .name ="uart3_tx_irtx.uart3_tx_irtx" , + .enable =OMAP_PIN_OUTPUT |OMAP_MUX_MODE0 , + }, + { + .name ="uart3_rx_irrx.uart3_rx_irrx" , + .flags =OMAP_DEVICE_PAD_REMUX |OMAP_DEVICE_PAD_WAKEUP , + .enable =OMAP_PIN_INPUT |OMAP_MUX_MODE0 , + }, +}; + +static struct omap_device_pad default_omap36xx_uart4_pads[]__initdata = { + { + .name ="gpmc_wait2.uart4_tx" , + .enable =OMAP_PIN_OUTPUT |OMAP_MUX_MODE0 , + }, + { + .name ="gpmc_wait3.uart4_rx" , + .flags =OMAP_DEVICE_PAD_REMUX |OMAP_DEVICE_PAD_WAKEUP , + .enable =OMAP_PIN_INPUT |OMAP_MUX_MODE2 , + }, +}; + +static struct omap_device_pad default_omap4_uart4_pads[]__initdata = { + { + .name ="uart4_tx.uart4_tx" , + .enable =OMAP_PIN_OUTPUT |OMAP_MUX_MODE0 , + }, + { + .name ="uart4_rx.uart4_rx" , + .flags =OMAP_DEVICE_PAD_REMUX |OMAP_DEVICE_PAD_WAKEUP , + .enable =OMAP_PIN_INPUT |OMAP_MUX_MODE0 , + }, +}; +#else +static struct omap_device_pad default_uart1_pads[]__initdata = {}; +static struct omap_device_pad default_uart2_pads[]__initdata = {}; +static struct omap_device_pad default_uart3_pads[]__initdata = {}; +static struct omap_device_pad default_omap36xx_uart4_pads[]__initdata = {}; +static struct omap_device_pad default_omap4_uart4_pads[]__initdata = {}; +#endif + +static void omap_serial_fill_default_pads (struct omap_board_data *bdata) +{ +switch (bdata->id) { +case 0 : + bdata->pads = default_uart1_pads; + bdata->pads_cnt =ARRAY_SIZE (default_uart1_pads); +break ; +case 1 : + bdata->pads = default_uart2_pads; + bdata->pads_cnt =ARRAY_SIZE (default_uart2_pads); +break ; +case 2 : + bdata->pads = default_uart3_pads; + bdata->pads_cnt =ARRAY_SIZE (default_uart3_pads); +break ; +case 3 : +if (cpu_is_omap44xx ()) { + bdata->pads = default_omap4_uart4_pads; + bdata->pads_cnt = +ARRAY_SIZE (default_omap4_uart4_pads); + }else { + bdata->pads = default_omap36xx_uart4_pads; + bdata->pads_cnt = +ARRAY_SIZE (default_omap36xx_uart4_pads); + } +break ; +default : +break ; + } +} +static void omap_uart_idle_init (struct omap_uart_port_info *uart,unsigned short num) {
@@ -242,6 +365,8 @@ void __init omap_serial_init(void) bdata.flags =0 ; bdata.pads =NULL ; bdata.pads_cnt =0 ; -omap_serial_init_port (&bdata); + +if (cpu_is_omap44xx () ||cpu_is_omap34xx ()) +omap_serial_fill_default_pads (&bdata); } }
Signature · 1 line
1.7.1
Tony Lindgren
maintainerPATCH v2 3/12 OMAP2+: Serial: Add default mux for all uarts.
Quoted 2 lines · Govindraj.R
Add default mux data for all uarts if mux info is not passed from board file to avoid breaking any board support.
This should only happen if omap_serial_init is called, then boards can still use platform data with omap_serial_init_port.
Quoted 79 lines
arch/arm/mach-omap2/serial.c +73
-0@@ -66,6 +66,129 @@ static struct omap_device_pm_latency omap_uart_latency[] = { }, }; +#ifdef CONFIG_OMAP_MUX +static struct omap_device_pad default_uart1_pads[]__initdata = { + { + .name ="uart1_cts.uart1_cts" , + .enable =OMAP_PIN_INPUT_PULLUP |OMAP_MUX_MODE0 , + }, + { + .name ="uart1_rts.uart1_rts" , + .enable =OMAP_PIN_OUTPUT |OMAP_MUX_MODE0 , + }, + { + .name ="uart1_tx.uart1_tx" , + .enable =OMAP_PIN_OUTPUT |OMAP_MUX_MODE0 , + }, + { + .name ="uart1_rx.uart1_rx" , + .flags =OMAP_DEVICE_PAD_REMUX |OMAP_DEVICE_PAD_WAKEUP , + .enable =OMAP_PIN_INPUT_PULLUP |OMAP_MUX_MODE0 , + }, +}; + +static struct omap_device_pad default_uart2_pads[]__initdata = { + { + .name ="uart2_cts.uart2_cts" , + .enable =OMAP_PIN_INPUT_PULLUP |OMAP_MUX_MODE0 , + }, + { + .name ="uart2_rts.uart2_rts" , + .enable =OMAP_PIN_OUTPUT |OMAP_MUX_MODE0 , + }, + { + .name ="uart2_tx.uart2_tx" , + .enable =OMAP_PIN_OUTPUT |OMAP_MUX_MODE0 , + }, + { + .name ="uart2_rx.uart2_rx" , + .flags =OMAP_DEVICE_PAD_REMUX |OMAP_DEVICE_PAD_WAKEUP , + .enable =OMAP_PIN_INPUT_PULLUP |OMAP_MUX_MODE0 , + }, +}; + +static struct omap_device_pad default_uart3_pads[]__initdata = { + { + .name ="uart3_cts_rctx.uart3_cts_rctx" , + .enable =OMAP_PIN_INPUT_PULLUP |OMAP_MUX_MODE0 , + }, + { + .name ="uart3_rts_sd.uart3_rts_sd" , + .enable =OMAP_PIN_OUTPUT |OMAP_MUX_MODE0 , + }, + { + .name ="uart3_tx_irtx.uart3_tx_irtx" , + .enable =OMAP_PIN_OUTPUT |OMAP_MUX_MODE0 , + }, + { + .name ="uart3_rx_irrx.uart3_rx_irrx" , + .flags =OMAP_DEVICE_PAD_REMUX |OMAP_DEVICE_PAD_WAKEUP , + .enable =OMAP_PIN_INPUT |OMAP_MUX_MODE0 , + }, +}; + +static struct omap_device_pad default_omap36xx_uart4_pads[]__initdata = { + { + .name ="gpmc_wait2.uart4_tx" , + .enable =OMAP_PIN_OUTPUT |OMAP_MUX_MODE0 , + }, + { + .name ="gpmc_wait3.uart4_rx" , + .flags =OMAP_DEVICE_PAD_REMUX |OMAP_DEVICE_PAD_WAKEUP , + .enable =OMAP_PIN_INPUT |OMAP_MUX_MODE2 , + }, +}; +
arch/arm/mach-omap2/serial.c static struct omap_device_pm_latency omap_uart_latency[] = { · line 151
Quoted 10 lines
arch/arm/mach-omap2/serial.c +10
-0+static struct omap_device_pad default_omap4_uart4_pads[]__initdata = { + { + .name ="uart4_tx.uart4_tx" , + .enable =OMAP_PIN_OUTPUT |OMAP_MUX_MODE0 , + }, + { + .name ="uart4_rx.uart4_rx" , + .flags =OMAP_DEVICE_PAD_REMUX |OMAP_DEVICE_PAD_WAKEUP , + .enable =OMAP_PIN_INPUT |OMAP_MUX_MODE0 , + },
Looks like you could easily allocate the struct and use sprintf to generate this as needed to avoid duplication.
Tony
PATCH v2 3/12 OMAP2+: Serial: Add default mux for all uarts.
Quoted 6 lines · Tony Lindgren
Quoted 2 lines · Govindraj.R
Add default mux data for all uarts if mux info is not passed from board file to avoid breaking any board support.
This should only happen if
omap_serial_initis called, then boards can still use platform data withomap_serial_init_port.
Yes correct thats how its designed with this patch series. One can use omap_serial_init to initialize all uarts or use omap_serial_init_port for individual uart.
Default pads are filled only if board uses omap_serial_init(NULL); to initialize all uarts.
Quoted 85 lines
Quoted 85 lines
arch/arm/mach-omap2/serial.c +78
-0@@ -66,6 +66,129 @@ static struct omap_device_pm_latency omap_uart_latency[] = { ? ? ? }, ?}; +#ifdef CONFIG_OMAP_MUX +static struct omap_device_pad default_uart1_pads[]__initdata = { + ? ? { + ? ? ? ? ? ? .name ? = "uart1_cts.uart1_cts", + ? ? ? ? ? ? .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0, + ? ? }, + ? ? { + ? ? ? ? ? ? .name ? = "uart1_rts.uart1_rts", + ? ? ? ? ? ? .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0, + ? ? }, + ? ? { + ? ? ? ? ? ? .name ? = "uart1_tx.uart1_tx", + ? ? ? ? ? ? .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0, + ? ? }, + ? ? { + ? ? ? ? ? ? .name ? = "uart1_rx.uart1_rx", + ? ? ? ? ? ? .flags ?= OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP, + ? ? ? ? ? ? .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0, + ? ? }, +}; + +static struct omap_device_pad default_uart2_pads[]__initdata = { + ? ? { + ? ? ? ? ? ? .name ? = "uart2_cts.uart2_cts", + ? ? ? ? ? ? .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0, + ? ? }, + ? ? { + ? ? ? ? ? ? .name ? = "uart2_rts.uart2_rts", + ? ? ? ? ? ? .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0, + ? ? }, + ? ? { + ? ? ? ? ? ? .name ? = "uart2_tx.uart2_tx", + ? ? ? ? ? ? .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0, + ? ? }, + ? ? { + ? ? ? ? ? ? .name ? = "uart2_rx.uart2_rx", + ? ? ? ? ? ? .flags ?= OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP, + ? ? ? ? ? ? .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0, + ? ? }, +}; + +static struct omap_device_pad default_uart3_pads[]__initdata = { + ? ? { + ? ? ? ? ? ? .name ? = "uart3_cts_rctx.uart3_cts_rctx", + ? ? ? ? ? ? .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0, + ? ? }, + ? ? { + ? ? ? ? ? ? .name ? = "uart3_rts_sd.uart3_rts_sd", + ? ? ? ? ? ? .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0, + ? ? }, + ? ? { + ? ? ? ? ? ? .name ? = "uart3_tx_irtx.uart3_tx_irtx", + ? ? ? ? ? ? .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0, + ? ? }, + ? ? { + ? ? ? ? ? ? .name ? = "uart3_rx_irrx.uart3_rx_irrx", + ? ? ? ? ? ? .flags ?= OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP, + ? ? ? ? ? ? .enable = OMAP_PIN_INPUT | OMAP_MUX_MODE0, + ? ? }, +}; + +static struct omap_device_pad default_omap36xx_uart4_pads[]__initdata = { + ? ? { + ? ? ? ? ? ? .name ? = "gpmc_wait2.uart4_tx", + ? ? ? ? ? ? .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0, + ? ? }, + ? ? { + ? ? ? ? ? ? .name ? = "gpmc_wait3.uart4_rx", + ? ? ? ? ? ? .flags ?= OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP, + ? ? ? ? ? ? .enable = OMAP_PIN_INPUT | OMAP_MUX_MODE2, + ? ? }, +}; + +static struct omap_device_pad default_omap4_uart4_pads[]__initdata = { + ? ? { + ? ? ? ? ? ? .name ? = "uart4_tx.uart4_tx", + ? ? ? ? ? ? .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0, + ? ? },
Quoted 8 lines
arch/arm/mach-omap2/serial.c static struct omap_device_pm_latency omap_uart_latency[] = { · line 151
Quoted 5 lines
arch/arm/mach-omap2/serial.c +5
-0+ ? ? { + ? ? ? ? ? ? .name ? = "uart4_rx.uart4_rx", + ? ? ? ? ? ? .flags ?= OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP, + ? ? ? ? ? ? .enable = OMAP_PIN_INPUT | OMAP_MUX_MODE0, + ? ? },Looks like you could easily allocate the struct and use sprintf to generate this as needed to avoid duplication.
Only uart1/2 have common name
* uart3 having different naming pins
* uart4 doesnt have cts/rts
* uart4 on 3630 uses gpmc.wait2
* rx requires wakeup enable flag
So would again give me a function with switch case for uart1/2/3/4 which is very similar to above structs.
Thats the reson I kept individual structs. Also becomes easy if we need to disable or avoid a individual uart pad.
--
Thanks,
Govindraj.R
Quoted 7 lines
Tony
--
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
PATCH v2 4/12 Serial: OMAP: Add runtime pm support for omap-serial driver
In reply to Govindraj.RAdapts omap-serial driver to use pm_runtime api's.
1.) Populate reg values to uart port which can be used for context restore. 2.) Moving context_restore func to driver from serial.c
3.) Adding port_enable/disable func to enable/disable given uart port.
enable port using get_sync and disable using autosuspend.
4.) using runtime irq safe api to make get_sync be called from irq context.
--- arch/arm/mach-omap2/serial.c | 16 ++ arch/arm/plat-omap/include/plat/omap-serial.h | 2 + drivers/tty/serial/omap-serial.c | 211 ++++++++++++++++++++++--- 3 files changed, 203 insertions(+), 26 deletions(-)
arch/arm/mach-omap2/serial.c +16 -0
@@ -189,6 +189,21 @@ static void omap_serial_fill_default_pads(struct omap_board_data *bdata) } } +static void omap_uart_wakeup_enable (struct platform_device *pdev,bool enable) +{ +struct omap_uart_port_info *up = pdev->dev.platform_data; + +/* Set or clear wake-enable bit */ +if (up->wk_en && up->wk_mask) { +u32 v =__raw_readl (up->wk_en); +if (enable) + v |= up->wk_mask; +else + v &= ~up->wk_mask; +__raw_writel (v, up->wk_en); + } +} +static void omap_uart_idle_init (struct omap_uart_port_info *uart,unsigned short num) {
@@ -332,6 +347,7 @@ void __init omap_serial_init_port(struct omap_board_data *bdata) pdata->uartclk =OMAP24XX_BASE_BAUD *16 ; pdata->flags =UPF_BOOT_AUTOCONF ; + pdata->enable_wakeup = omap_uart_wakeup_enable;if (bdata->id == omap_uart_con_id) pdata->console_uart = true;
arch/arm/plat-omap/include/plat/omap-serial.h +2 -0
@@ -65,6 +65,7 @@ struct omap_uart_port_info {unsigned int errata;unsigned int console_uart; +void (*enable_wakeup)(struct platform_device *,bool );void __iomem *wk_st;void __iomem *wk_en;u32 wk_mask;
@@ -120,6 +121,7 @@ struct uart_omap_port {char name[20 ];unsigned long port_activity;unsigned int errata; + void (*enable_wakeup)(struct platform_device *, bool); };#endif /* __OMAP_SERIAL_H__ */
drivers/tty/serial/omap-serial.c +185 -26
511 lines not on this page · raw message
Signature · 1 line
1.7.1
PATCH v2 4/12 Serial: OMAP: Add runtime pm support for omap-serial driver
Quoted 27 lines · Govindraj.R
Adapts omap-serial driver to use
pm_runtimeapi's.1.) Populate reg values to uart port which can be used for context restore. 2.) Moving
context_restorefunc to driver fromserial.c
3.) Adding port_enable/disable func to enable/disable given uart port.
enable port usingget_syncand disable using autosuspend.
4.) using runtime irq safe api to makeget_syncbe called from irq context.Signed-off-by Govindraj.R <[email protected]>--- arch/arm/mach-omap2/serial.c | 16 ++ arch/arm/plat-omap/include/plat/omap-serial.h | 2 + drivers/tty/serial/omap-serial.c | 211 ++++++++++++++++++++++--- 3 files changed, 203 insertions(+), 26 deletions(-)arch/arm/mach-omap2/serial.c +4
-0@@ -189,6 +189,21 @@ static void omap_serial_fill_default_pads(struct omap_board_data *bdata) } } +static void omap_uart_wakeup_enable (struct platform_device *pdev,bool enable) +{ +struct omap_uart_port_info *up = pdev->dev.platform_data; +
arch/arm/mach-omap2/serial.c static void omap_serial_fill_default_pads(struct omap_board_data *bdata) · line 205
Quoted 10 lines
arch/arm/mach-omap2/serial.c +10
-0+/* Set or clear wake-enable bit */ +if (up->wk_en && up->wk_mask) { +u32 v =__raw_readl (up->wk_en); +if (enable) + v |= up->wk_mask; +else + v &= ~up->wk_mask; +__raw_writel (v, up->wk_en); + } +}
Rather than having the driver do this via the PRCM, can you do an experiment? Can you try to leave the module-level wakeup enabled all the time in the PRCM, and the driver can then enable/disable module-level wakeups simply by toggling ENAWAKEUP in the module's SYSCONFIG? If that works, than you can just use omap_hwmod_enable_wakeup() for this and not need the above function.
Quoted 468 lines
arch/arm/mach-omap2/serial.c +1
-0static void omap_uart_idle_init (struct omap_uart_port_info *uart,unsigned short num) {@@ -332,6 +347,7 @@ void __init omap_serial_init_port(struct omap_board_data *bdata) pdata->uartclk =OMAP24XX_BASE_BAUD *16 ; pdata->flags =UPF_BOOT_AUTOCONF ; + pdata->enable_wakeup = omap_uart_wakeup_enable;if (bdata->id == omap_uart_con_id) pdata->console_uart = true;arch/arm/plat-omap/include/plat/omap-serial.h +2
-0@@ -65,6 +65,7 @@ struct omap_uart_port_info {unsigned int errata;unsigned int console_uart; +void (*enable_wakeup)(struct platform_device *,bool );void __iomem *wk_st;void __iomem *wk_en;u32 wk_mask;@@ -120,6 +121,7 @@ struct uart_omap_port {char name[20 ];unsigned long port_activity;unsigned int errata; + void (*enable_wakeup)(struct platform_device *, bool); };#endif /* __OMAP_SERIAL_H__ */ drivers/tty/serial/omap-serial.c +107
-22@@ -37,10 +37,14 @@#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/omap_device.h> + +#define OMAP_UART_AUTOSUSPEND_DELAY (30 * HZ)/* Value is msecs */ static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS ];@@ -94,6 +98,17 @@ serial_omap_get_divisor(struct uart_port *port, unsigned int baud)return port->uartclk/(baud * divisor); } +static inline void serial_omap_port_disable (struct uart_omap_port *up) +{ +pm_runtime_mark_last_busy (&up->pdev->dev); +pm_runtime_put_autosuspend (&up->pdev->dev); +} + +static inline void serial_omap_port_enable (struct uart_omap_port *up) +{ +pm_runtime_get_sync (&up->pdev->dev); +} +static void serial_omap_stop_rxdma (struct uart_omap_port *up) {if (up->uart_dma.rx_dma_used) {@@ -110,8 +125,11 @@ static void serial_omap_enable_ms(struct uart_port *port)struct uart_omap_port *up = (struct uart_omap_port *)port;dev_dbg (up->port.dev,"serial_omap_enable_ms+%d\n" , up->pdev->id); + +serial_omap_port_enable (up); up->ier |=UART_IER_MSI ;serial_out (up,UART_IER , up->ier); +serial_omap_port_disable (up); }static void serial_omap_stop_tx (struct uart_port *port)@@ -131,21 +149,26 @@ static void serial_omap_stop_tx(struct uart_port *port) up->uart_dma.tx_dma_channel =OMAP_UART_DMA_CH_FREE ; } +serial_omap_port_enable (up);if (up->ier &UART_IER_THRI ) { up->ier &= ~UART_IER_THRI ;serial_out (up,UART_IER , up->ier); } + +serial_omap_port_disable (up); }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 ; up->port.read_status_mask &= ~UART_LSR_DR ;serial_out (up,UART_IER , up->ier); +serial_omap_port_disable (up); }static inline void receive_chars (struct uart_omap_port *up,int *status)@@ -261,8 +284,10 @@ 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); +serial_omap_port_disable (up);return ; }@@ -354,9 +379,12 @@ 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 ) +if (iir &UART_IIR_NO_INT ) { +serial_omap_port_disable (up);return IRQ_NONE ; + }spin_lock_irqsave (&up->port.lock, flags); lsr =serial_in (up,UART_LSR );@@ -378,6 +406,8 @@ static inline irqreturn_t serial_omap_irq(int irq, void *dev_id)transmit_chars (up);spin_unlock_irqrestore (&up->port.lock, flags); +serial_omap_port_disable (up); + up->port_activity = jiffies;return IRQ_HANDLED ; }@@ -388,11 +418,12 @@ 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 ;spin_unlock_irqrestore (&up->port.lock, flags); - +serial_omap_port_disable (up);return ret; }@@ -402,7 +433,10 @@ 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); +serial_omap_port_disable (up); +dev_dbg (up->port.dev,"serial_omap_get_mctrl+%d\n" , up->pdev->id);if (status &UART_MSR_DCD )@@ -434,7 +468,9 @@ static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl) mcr |=UART_MCR_LOOP ; mcr |= up->mcr; +serial_omap_port_enable (up);serial_out (up,UART_MCR , mcr); +serial_omap_port_disable (up); }static void serial_omap_break_ctl (struct uart_port *port,int break_state)@@ -443,6 +479,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 ;@@ -450,6 +487,7 @@ static void serial_omap_break_ctl(struct uart_port *port, int break_state) up->lcr &= ~UART_LCR_SBC ;serial_out (up,UART_LCR , up->lcr);spin_unlock_irqrestore (&up->port.lock, flags); +serial_omap_port_disable (up); }static int serial_omap_startup (struct uart_port *port)@@ -468,6 +506,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()) @@ -523,6 +562,7 @@ static int serial_omap_startup(struct uart_port *port)/* Enable module level wake up */ serial_out (up,UART_OMAP_WER ,OMAP_UART_WER_MOD_WKUP ); +serial_omap_port_disable (up); up->port_activity = jiffies;return 0 ; }@@ -533,6 +573,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 */ @@ -566,6 +608,7 @@ static void serial_omap_shutdown(struct uart_port *port) up->uart_dma.rx_buf_dma_phys); up->uart_dma.rx_buf =NULL ; } +serial_omap_port_disable (up);free_irq (up->port.irq, up); }@@ -671,6 +714,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)@@ -680,6 +727,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);/* @@ -758,8 +806,7 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,serial_out (up,UART_MCR , up->mcr);/* Protocol, Baud Rate, and Interrupt Settings */ - -serial_out (up,UART_OMAP_MDR1 ,UART_OMAP_MDR1_DISABLE ); +serial_out (up,UART_OMAP_MDR1 , up->mdr1);serial_out (up,UART_LCR ,UART_LCR_CONF_MODE_B ); up->efr =serial_in (up,UART_EFR );@@ -769,8 +816,8 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,serial_out (up,UART_IER ,0 );serial_out (up,UART_LCR ,UART_LCR_CONF_MODE_B ); -serial_out (up,UART_DLL , quot &0xff );/* LS of divisor */ -serial_out (up,UART_DLM , quot >>8 );/* MS of divisor */ +serial_out (up,UART_DLL , up->dll);/* LS of divisor */ +serial_out (up,UART_DLM , up->dlh);/* MS of divisor */ serial_out (up,UART_LCR ,0 );serial_out (up,UART_IER , up->ier);@@ -780,9 +827,11 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,serial_out (up,UART_LCR , cval);if (baud >230400 && baud !=3000000 ) -serial_out (up,UART_OMAP_MDR1 ,UART_OMAP_MDR1_13X_MODE ); + up->mdr1 =UART_OMAP_MDR1_13X_MODE ;else -serial_out (up,UART_OMAP_MDR1 ,UART_OMAP_MDR1_16X_MODE ); + up->mdr1 =UART_OMAP_MDR1_16X_MODE ; + +serial_out (up,UART_OMAP_MDR1 , up->mdr1)/* Hardware Flow Control Configuration */ @@ -810,6 +859,7 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,serial_omap_configure_xonxoff (up, termios);spin_unlock_irqrestore (&up->port.lock, flags); +serial_omap_port_disable (up);dev_dbg (up->port.dev,"serial_omap_set_termios+%d\n" , up->pdev->id); }@@ -821,6 +871,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 );@@ -830,6 +882,10 @@ serial_omap_pm(struct uart_port *port, unsigned int state,serial_out (up,UART_LCR ,UART_LCR_CONF_MODE_B );serial_out (up,UART_EFR , efr);serial_out (up,UART_LCR ,0 ); +if (state) +pm_runtime_put_sync (&up->pdev->dev); +else +serial_omap_port_disable (up); }static void serial_omap_release_port (struct uart_port *port)@@ -907,25 +963,31 @@ 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); +serial_omap_port_disable (up); }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 ; -return serial_in (up,UART_RX ); + status =serial_in (up,UART_RX ); +serial_omap_port_disable (up); +return status; }#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;@@ -955,6 +1017,8 @@ serial_omap_console_write(struct console *co, const char *s,else spin_lock (&up->port.lock); +serial_omap_port_enable (up); +/* * First save the IER then disable the interrupts */ @@ -979,6 +1043,7 @@ serial_omap_console_write(struct console *co, const char *s,if (up->msr_saved_flags)check_modem_status (up); +serial_omap_port_disable (up);if (locked)spin_unlock (&up->port.lock);local_irq_restore (flags);@@ -1061,22 +1126,27 @@ 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); +console_trylock (); +serial_omap_pm (&up->port,3 ,0 ); + }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) +if (up) {uart_resume_port (&serial_omap_reg, &up->port); +console_unlock (); + } +return 0 ; }@@ -1097,6 +1167,7 @@ static void serial_omap_rx_timeout(unsigned long uart_no)serial_omap_stop_rxdma (up); up->ier |= (UART_IER_RDI |UART_IER_RLSI );serial_out (up,UART_IER , up->ier); +serial_omap_port_disable (up); }return ; }@@ -1128,6 +1199,9 @@ static void serial_omap_rx_timeout(unsigned long uart_no)static void uart_rx_dma_callback (int lch,u16 ch_status,void *data) { +struct uart_omap_port *up = (struct uart_omap_port *)data; + +serial_omap_port_disable (up);return ; }@@ -1135,6 +1209,7 @@ static int serial_omap_start_rxdma(struct uart_omap_port *up) {int ret =0 ; +serial_omap_port_enable (up);if (up->uart_dma.rx_dma_channel ==-1 ) { ret = omap_request_dma(up->uart_dma.uart_dma_rx, "UART Rx DMA",@@ -1214,6 +1289,7 @@ static void uart_tx_dma_callback(int lch, u16 ch_status, void *data)serial_omap_stop_tx (&up->port); up->uart_dma.tx_dma_used = false;spin_unlock (&(up->uart_dma.tx_lock)); +serial_omap_port_disable (up); }else {omap_stop_dma (up->uart_dma.tx_dma_channel);serial_omap_continue_tx (up);@@ -1224,9 +1300,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 );@@ -1276,12 +1353,20 @@ 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->enable_wakeup = omap_up_info->enable_wakeup;if (omap_up_info->dma_enabled) { up->uart_dma.uart_dma_tx = dma_tx->start;@@ -1295,18 +1380,36 @@ static int serial_omap_probe(struct platform_device *pdev) up->uart_dma.rx_dma_channel =OMAP_UART_DMA_CH_FREE ; }
drivers/tty/serial/omap-serial.c static int serial_omap_probe(struct platform_device *pdev) · line 1392
Quoted 10 lines
drivers/tty/serial/omap-serial.c +10
-0+pm_runtime_use_autosuspend (&pdev->dev); +pm_runtime_set_autosuspend_delay (&pdev->dev, +OMAP_UART_AUTOSUSPEND_DELAY ); + +pm_runtime_enable (&pdev->dev); +pm_runtime_irq_safe (&pdev->dev); + +if (omap_up_info->console_uart) { + od =to_omap_device (up->pdev); +omap_hwmod_idle (od->hwmods[0 ]);
Driver should have know knowlege of the underlying hwmod.
I assume this is here because of the usage of HWMOD_INIT_NO_IDLE and HWMOD_INIT_NO_RESET, right? With proper runtime PM, we should be able to remove the need for using those flags.
Kevin
Quoted 103 lines
drivers/tty/serial/omap-serial.c +68
-4+serial_omap_port_enable (up); +serial_omap_port_disable (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;@@ -1318,20 +1421,76 @@ 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 ; } +static void omap_uart_restore_context (struct uart_omap_port *up) +{ +u16 efr =0 ; + +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 ); +/* UART 16x mode */ +serial_out (up,UART_OMAP_MDR1 , up->mdr1); +} + +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 (dev)) + up->enable_wakeup (up->pdev, true); +else + up->enable_wakeup (up->pdev, false); +done: +return 0 ; +} + +static int omap_serial_runtime_resume (struct device *dev) +{ +struct uart_omap_port *up =dev_get_drvdata (dev); + +if (up) +omap_uart_restore_context (up); + +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, }, };
Paul Walmsley
maintainerPATCH v2 4/12 Serial: OMAP: Add runtime pm support for omap-serial driver
Hi Govindraj,
Quoted 7 lines · Kevin Hilman
Quoted 5 lines · Govindraj.R
+++
b/arch/arm/mach-omap2/serial.c(quoted diff) +0
-0@@ -189,6 +189,21 @@ static void omap_serial_fill_default_pads(struct omap_board_data *bdata) } }
Quoted 14 lines
Quoted 4 lines
arch/arm/mach-omap2/serial.c +4
-0+static void omap_uart_wakeup_enable (struct platform_device *pdev,bool enable) +{ +struct omap_uart_port_info *up = pdev->dev.platform_data; +arch/arm/mach-omap2/serial.c static void omap_serial_fill_default_pads(struct omap_board_data *bdata) · line 205
Quoted 10 lines
arch/arm/mach-omap2/serial.c +10
-0+/* Set or clear wake-enable bit */ +if (up->wk_en && up->wk_mask) { +u32 v =__raw_readl (up->wk_en); +if (enable) + v |= up->wk_mask; +else + v &= ~up->wk_mask; +__raw_writel (v, up->wk_en); + } +}
To be a little more direct: there should be no PRCM register interactions in the driver, absolutely none. This stuff needs to go through omap_device/omap_hwmod functions if it's really needed.
- Paul
PATCH v2 4/12 Serial: OMAP: Add runtime pm support for omap-serial driver
In reply to Kevin HilmanQuoted 43 lines · Kevin Hilman
Quoted 3 lines · Govindraj.R
Adapts omap-serial driver to use
pm_runtimeapi's.1.) Populate reg values to uart port which can be used for context
restore.
Quoted 4 lines
2.) Moving
context_restorefunc to driver fromserial.c
3.) Adding port_enable/disable func to enable/disable given uart port.
enable port usingget_syncand disable using autosuspend.
4.) using runtime irq safe api to makeget_syncbe called from irqcontext.
Quoted 6 lines
Signed-off-by Govindraj.R <[email protected]>--- arch/arm/mach-omap2/serial.c | 16 ++ arch/arm/plat-omap/include/plat/omap-serial.h | 2 + drivers/tty/serial/omap-serial.c | 211++++++++++++++++++++++---
arch/arm/mach-omap2/serial.c static void omap_serial_fill_default_pads(struct
Quoted 7 lines
3 files changed, 203 insertions(+), 26 deletions(-)arch/arm/mach-omap2/serial.c +0
-0@@ -189,6 +189,21 @@ static void omap_serial_fill_default_pads(struct
omap_board_data*bdata)arch/arm/mach-omap2/serial.c static void omap_serial_fill_default_pads(struct · line 192
Quoted 4 lines
arch/arm/mach-omap2/serial.c +1
-0} } +static void omap_uart_wakeup_enable(struct platform_device *pdev, boolenable)
Quoted 12 lines
arch/arm/mach-omap2/serial.c +12
-0+{ +struct omap_uart_port_info *up = pdev->dev.platform_data; + +/* Set or clear wake-enable bit */ +if (up->wk_en && up->wk_mask) { +u32 v =__raw_readl (up->wk_en); +if (enable) + v |= up->wk_mask; +else + v &= ~up->wk_mask; +__raw_writel (v, up->wk_en); + }
Quoted 9 lines
arch/arm/mach-omap2/serial.c static void omap_serial_fill_default_pads(struct · line 205
Quoted 1 line
arch/arm/mach-omap2/serial.c +1
-0+}Rather than having the driver do this via the PRCM, can you do an experiment? Can you try to leave the module-level wakeup enabled all the time in the PRCM, and the driver can then enable/disable module-level wakeups simply by toggling ENAWAKEUP in the module's SYSCONFIG? If that works, than you can just use
omap_hwmod_enable_wakeup()for this and not need the above function.
If we leave PRCM uart module level bit enabled all time and we disable wakeup using sysfs
echo disabled > /sys/devices/platform/omap/omap_uart.0/power/wakeup
it wakes up after clock disable, however unsetting the bit ensures it doesn't
wakeup after uart clocks are cut.
As Paul suggested, How about adding omap_device/omap_hwmod function to set and unset the bit?
Using
.module_bit = OMAP3430_EN_UART1_SHIFT,
from hwmod data?
Quoted 15 lines
arch/arm/mach-omap2/serial.c void __init omap_serial_init_port(struct
Quoted 5 lines
arch/arm/mach-omap2/serial.c +0
-0static void omap_uart_idle_init (struct omap_uart_port_info *uart,unsigned short num) {@@ -332,6 +347,7 @@ void __init omap_serial_init_port(struct
omap_board_data*bdata)Quoted 7 lines
arch/arm/mach-omap2/serial.c +1
-0pdata->uartclk =OMAP24XX_BASE_BAUD *16 ; pdata->flags =UPF_BOOT_AUTOCONF ; + pdata->enable_wakeup = omap_uart_wakeup_enable;if (bdata->id == omap_uart_con_id) pdata->console_uart = true;
<<SNIP>>
Quoted 13 lines
arch/arm/mach-omap2/serial.c void __init omap_serial_init_port(struct
Quoted 10 lines
arch/arm/mach-omap2/serial.c +10
-0+pm_runtime_use_autosuspend (&pdev->dev); +pm_runtime_set_autosuspend_delay (&pdev->dev, +OMAP_UART_AUTOSUSPEND_DELAY ); + +pm_runtime_enable (&pdev->dev); +pm_runtime_irq_safe (&pdev->dev); + +if (omap_up_info->console_uart) { + od =to_omap_device (up->pdev); +omap_hwmod_idle (od->hwmods[0 ]);Driver should have know knowlege of the underlying hwmod.
Quoted 2 lines
I assume this is here because of the usage of
HWMOD_INIT_NO_IDLEandHWMOD_INIT_NO_RESET, right?
Yes correct.
Quoted 3 lines
With proper runtime PM, we should be able to
remove the need for using those flags.
For omap-uart used for earlyprintk's the early_console driver will use printch from debug macro to print through uart.
During omap-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.
--
Thanks,
Govindraj.R
Quoted 99 lines
Kevin
arch/arm/mach-omap2/serial.c static int serial_omap_remove(struct
Quoted 25 lines
arch/arm/mach-omap2/serial.c +9
-1+serial_omap_port_enable (up); +serial_omap_port_disable (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;@@ -1318,20 +1421,76 @@ static int serial_omap_remove(struct
platform_device*dev)Quoted 70 lines
arch/arm/mach-omap2/serial.c +58
-0platform_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 ; } +static void omap_uart_restore_context (struct uart_omap_port *up) +{ +u16 efr =0 ; + +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 ); +/* UART 16x mode */ +serial_out (up,UART_OMAP_MDR1 , up->mdr1); +} + +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 (dev)) + up->enable_wakeup (up->pdev, true); +else + up->enable_wakeup (up->pdev, false); +done: +return 0 ; +} + +static int omap_serial_runtime_resume (struct device *dev) +{ +struct uart_omap_port *up =dev_get_drvdata (dev); + +if (up) +omap_uart_restore_context (up); + +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,
Quoted 9 lines
arch/arm/mach-omap2/serial.c static int serial_omap_remove(struct · line 1494
Quoted 8 lines
arch/arm/mach-omap2/serial.c +1
-3- - .suspend = serial_omap_suspend, - .resume = serial_omap_resume, .driver = { .name = DRIVER_NAME, + .pm = &omap_serial_dev_pm_ops, }, };
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20110505/874afec9/attachment-0001.html>
PATCH v2 4/12 Serial: OMAP: Add runtime pm support for omap-serial driver
In reply to Kevin HilmanQuoted 38 lines · Kevin Hilman
Quoted 36 lines · Govindraj.R
Adapts omap-serial driver to use
pm_runtimeapi's.1.) Populate reg values to uart port which can be used for context restore. 2.) Moving
context_restorefunc to driver fromserial.c
3.) Adding port_enable/disable func to enable/disable given uart port. ? ? enable port usingget_syncand disable using autosuspend. 4.) using runtime irq safe api to makeget_syncbe called from irq context.Signed-off-by Govindraj.R <[email protected]>---
?arch/arm/mach-omap2/serial.c ? ? ? ? ? ? ? ? ?| ? 16 ++ ?arch/arm/plat-omap/include/plat/omap-serial.h | ? ?2 + ?drivers/tty/serial/omap-serial.c ? ? ? ? ? ? ?| ?211 ++++++++++++++++++++++---?3 files changed, 203 insertions(+), 26 deletions(-)
arch/arm/mach-omap2/serial.c +13
-0@@ -189,6 +189,21 @@ static void omap_serial_fill_default_pads(struct omap_board_data *bdata) ? ? ? } ?} +static void omap_uart_wakeup_enable (struct platform_device *pdev,bool enable) +{ + ? ? struct omap_uart_port_info *up = pdev->dev.platform_data; + + ? ? /* Set or clear wake-enable bit */ + ? ? if (up->wk_en && up->wk_mask) { + ? ? ? ? ? ? u32 v = __raw_readl(up->wk_en); + ? ? ? ? ? ? if (enable) + ? ? ? ? ? ? ? ? ? ? v |= up->wk_mask; + ? ? ? ? ? ? else + ? ? ? ? ? ? ? ? ? ? v &= ~up->wk_mask; + ? ? ? ? ? ? __raw_writel(v, up->wk_en); + ? ? }
Quoted 9 lines
arch/arm/mach-omap2/serial.c static void omap_serial_fill_default_pads(struct omap_board_data *bdata) · line 205
Quoted 1 line
arch/arm/mach-omap2/serial.c +1
-0+}Rather than having the driver do this via the PRCM, can you do an experiment? ?Can you try to leave the module-level wakeup enabled all the time in the PRCM, and the driver can then enable/disable module-level wakeups simply by toggling ENAWAKEUP in the module's SYSCONFIG? ?If that works, than you can just use
omap_hwmod_enable_wakeup()for this and not need the above function.
If we leave PRCM uart module level bit enabled all time and we disable wakeup using sysfs
echo disabled > /sys/devices/platform/omap/omap_uart.0/power/wakeup
it wakes up after clock disable, however unsetting the bit ensures it doesn't wakeup after uart clocks are cut.
As Paul suggested, How about adding omap_device/omap_hwmod function to set and unset the bit?
Using
.module_bit = OMAP3430_EN_UART1_SHIFT,
from hwmod data?
Quoted 10 lines
arch/arm/mach-omap2/serial.c void __init omap_serial_init_port(struct omap_board_data *bdata) · line 352
Quoted 10 lines
arch/arm/mach-omap2/serial.c +1
-0?static void omap_uart_idle_init(struct omap_uart_port_info *uart, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? unsigned short num) ?{@@ -332,6 +347,7 @@ void __init omap_serial_init_port(struct omap_board_data *bdata) ? ? ? pdata->uartclk = OMAP24XX_BASE_BAUD * 16; ? ? ? pdata->flags = UPF_BOOT_AUTOCONF; + ? ? pdata->enable_wakeup = omap_uart_wakeup_enable; ? ? ? if (bdata->id == omap_uart_con_id) ? ? ? ? ? ? ? pdata->console_uart = true;
<<SNIP>>
Quoted 13 lines
arch/arm/mach-omap2/serial.c void __init omap_serial_init_port(struct omap_board_data *bdata)
Quoted 10 lines
arch/arm/mach-omap2/serial.c +10
-0+ ? ? pm_runtime_use_autosuspend(&pdev->dev); + ? ? pm_runtime_set_autosuspend_delay(&pdev->dev, + ? ? ? ? ? ? ? ? ? ? OMAP_UART_AUTOSUSPEND_DELAY); + + ? ? pm_runtime_enable(&pdev->dev); + ? ? pm_runtime_irq_safe(&pdev->dev); + + ? ? if (omap_up_info->console_uart) { + ? ? ? ? ? ? od = to_omap_device(up->pdev); + ? ? ? ? ? ? omap_hwmod_idle(od->hwmods[0]);Driver should have know knowlege of the underlying hwmod.
Quoted 2 lines
I assume this is here because of the usage of
HWMOD_INIT_NO_IDLEandHWMOD_INIT_NO_RESET, right?
Yes correct.
Quoted 1 line
?With proper runtime PM, we should be able to remove the need for using those flags.
For omap-uart used for earlyprintk's the early_console driver will use printch from debug macro to print through uart.
During omap-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.
--
Thanks,
Govindraj.R
Quoted 111 lines
Kevin
Quoted 93 lines
+ ? ? ? ? ? ?
serial_omap_port_enable(up);
+ ? ? ? ? ? ?serial_omap_port_disable(up);
+ ? ? }
+
? ? ? ui[pdev->id] = up;
? ? ?serial_omap_add_console_port(up);? ? ? ret =
uart_add_one_port(&serial_omap_reg, &up->port); ? ? ? if (ret != 0)
- ? ? ? ? ? ? gotodo_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;arch/arm/mach-omap2/serial.c +58
-0@@ -1318,20 +1421,76 @@ 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; ?} +static void omap_uart_restore_context (struct uart_omap_port *up) +{ + ? ? u16 efr = 0; + + ? ? 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); + ? ? /* UART 16x mode */ + ? ? serial_out(up, UART_OMAP_MDR1, up->mdr1); +} + +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(dev)) + ? ? ? ? ? ? up->enable_wakeup(up->pdev, true); + ? ? else + ? ? ? ? ? ? up->enable_wakeup(up->pdev, false); +done: + ? ? return 0; +} + +static int omap_serial_runtime_resume (struct device *dev) +{ + ? ? struct uart_omap_port *up = dev_get_drvdata(dev); + + ? ? if (up) + ? ? ? ? ? ? omap_uart_restore_context(up); + + ? ? 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 = {arch/arm/mach-omap2/serial.c static int serial_omap_remove(struct platform_device *dev) · line 1495
Quoted 10 lines
arch/arm/mach-omap2/serial.c +1
-3? ? ? .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, ? ? ? }, ?};--
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
PATCH v2 5/12 OMAP: Serial: Hold console lock for console usage.
In reply to Govindraj.RAcquire console lock before enabling and writing to console-uart to avoid any recursive prints from console write.
for ex:
--> printk --> uart_console_write --> get_sync --> printk from omap_device enable --> uart_console write
Also during bootup console_lock is not available.
--> uart_add_one_port --> console_register --> console_lock --> console_unlock --> call_console_drivers (here yet console_lock is not released) --> uart_console_write
Hence convert prints from omap_device_enable/disable to pr_debug.
--- arch/arm/plat-omap/omap_device.c | 8 ++++---- drivers/tty/serial/omap-serial.c | 8 +++++++- 2 files changed, 11 insertions(+), 5 deletions(-)
arch/arm/plat-omap/omap_device.c +4 -4
@@ -145,12 +145,12 @@ static int _omap_device_activate(struct omap_device *od, u8 ignore_lat) odpl->activate_lat_worst = act_lat;if (odpl->flags &OMAP_DEVICE_LATENCY_AUTO_ADJUST ) { odpl->activate_lat = act_lat; -pr_warning ("omap_device: %s.%d: new worst case " +pr_debug ("omap_device: %s.%d: new worst case " "activate latency %d: %llu\n" , od->pdev.name, od->pdev.id, od->pm_lat_level, act_lat); }else - pr_warning("omap_device: %s.%d: activate " + pr_debug("omap_device: %s.%d: activate " "latency %d higher than exptected. " "(%llu > %d)\n", od->pdev.name, od->pdev.id,
@@ -213,12 +213,12 @@ static int _omap_device_deactivate(struct omap_device *od, u8 ignore_lat) odpl->deactivate_lat_worst = deact_lat;if (odpl->flags &OMAP_DEVICE_LATENCY_AUTO_ADJUST ) { odpl->deactivate_lat = deact_lat; -pr_warning ("omap_device: %s.%d: new worst case " +pr_debug ("omap_device: %s.%d: new worst case " "deactivate latency %d: %llu\n" , od->pdev.name, od->pdev.id, od->pm_lat_level, deact_lat); }else - pr_warning("omap_device: %s.%d: deactivate " + pr_debug("omap_device: %s.%d: deactivate " "latency %d higher than exptected. " "(%llu > %d)\n", od->pdev.name, od->pdev.id,
drivers/tty/serial/omap-serial.c +7 -1
@@ -1007,7 +1007,10 @@ serial_omap_console_write(struct console *co, const char *s,struct uart_omap_port *up = serial_omap_console_ports[co->index];unsigned long flags;unsigned int ier; -int locked =1 ; +int console_lock =0 , locked =1 ; + +if (console_trylock ()) + console_lock =1 ;local_irq_save (flags);if (up->port.sysrq)
@@ -1043,6 +1046,9 @@ serial_omap_console_write(struct console *co, const char *s,if (up->msr_saved_flags)check_modem_status (up); +if (console_lock) +console_unlock (); +serial_omap_port_disable (up);if (locked)spin_unlock (&up->port.lock);
Signature · 1 line
1.7.1
Tony Lindgren
maintainerPATCH v2 5/12 OMAP: Serial: Hold console lock for console usage.
Quoted 10 lines · Govindraj.R
Also during bootup
console_lockis not available.--> uart_add_one_port --> console_register --> console_lock --> console_unlock --> call_console_drivers (here yet console_lock is not released) --> uart_console_writeHence convert prints from omap_device_enable/disable to
pr_debug.
This sounds like a hack considering we have things working with pr_debug currently.
Tony
PATCH v2 5/12 OMAP: Serial: Hold console lock for console usage.
Quoted 10 lines · Tony Lindgren
Quoted 9 lines · Govindraj.R
Also during bootup
console_lockis not available.--> uart_add_one_port --> console_register --> console_lock --> console_unlock --> call_console_drivers (here yet console_lock is not released) --> uart_console_write
Quoted 4 lines
Quoted 1 line
Hence convert prints from omap_device_enable/disable to
pr_debug.This sounds like a hack considering we have things working with
pr_debugcurrently.
It also highlights a different problem: stuffing subsystems full of debug, and keeping it way after the subsystem has been brought to a working state not only adds code bloat but also can cause additional bugs.
PATCH v2 5/12 OMAP: Serial: Hold console lock for console usage.
In reply to Tony LindgrenQuoted 10 lines · Tony Lindgren
Quoted 9 lines · Govindraj.R
Also during bootup
console_lockis not available.
? ? ? ?-->uart_add_one_port
? ? ? ? ?-->console_register
? ? ? ? ? ? ?-->console_lock
? ? ? ? ? ? ? -->console_unlock
? ? ? ? ? ? ? ? ? ?-->call_console_drivers(here yetconsole_lockis not released) ? ? ? ? ? ? ? ? ? ? ? ? -->uart_console_write
Quoted 4 lines
Quoted 1 line
Hence convert prints from omap_device_enable/disable to
pr_debug.This sounds like a hack considering we have things working with
pr_debugcurrently.
The reason it works currently is because we are aquiring console lock in omap_serial_init since with the patch series cleanup and things are moving to driver I see this issue.
The issue is due to recursive prints because of get_sync/put_sync printing active/deactivate latency from omap_device layer.
During printk -> uart_console_write -->
we do get_sync and if clock is cut and omap_device_enable gets called and omap_device_enable trying to pr_warn activate latency.
Here we end up in recursive lock up from printk.
--
Thanks,
Govindraj.R
Quoted 7 lines
Tony
--
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
PATCH v2 5/12 OMAP: Serial: Hold console lock for console usage.
In reply to Govindraj.RQuoted 8 lines · Govindraj.R
Acquire console lock before enabling and writing to console-uart to avoid any recursive prints from console write.
for ex:--> printk --> uart_console_write --> get_sync --> printk from omap_device enable --> uart_console write
By this time, since the device's runtime PM hooks have been called, the device's rutime PM state should be set to RPM_SUSPENDING (not yet RPM_SUSPENDED).
In addition to the console lock, you should be able to use that flag to avoid console writes while the console is in the process of suspending.
Quoted 9 lines
Also during bootup
console_lockis not available.--> uart_add_one_port --> console_register --> console_lock --> console_unlock --> call_console_drivers (here yet console_lock is not released) --> uart_console_writeHence convert prints from omap_device_enable/disable to
pr_debug.
And what if you add 'debug' to your kernel command line? IOW, you're only solving the problem if you debug printk's are not going to the console.
You're also not solving the problem that will happen down the road when someone else adds a printk to low-level code in order to debug something deep in the idle sequence.
The recursive locking needs to be solved, not avoided.
Kevin
Quoted 66 lines
Signed-off-by Govindraj.R <[email protected]>--- arch/arm/plat-omap/omap_device.c | 8 ++++---- drivers/tty/serial/omap-serial.c | 8 +++++++- 2 files changed, 11 insertions(+), 5 deletions(-)arch/arm/plat-omap/omap_device.c +4
-4@@ -145,12 +145,12 @@ static int _omap_device_activate(struct omap_device *od, u8 ignore_lat) odpl->activate_lat_worst = act_lat;if (odpl->flags &OMAP_DEVICE_LATENCY_AUTO_ADJUST ) { odpl->activate_lat = act_lat; -pr_warning ("omap_device: %s.%d: new worst case " +pr_debug ("omap_device: %s.%d: new worst case " "activate latency %d: %llu\n" , od->pdev.name, od->pdev.id, od->pm_lat_level, act_lat); }else - pr_warning("omap_device: %s.%d: activate " + pr_debug("omap_device: %s.%d: activate " "latency %d higher than exptected. " "(%llu > %d)\n", od->pdev.name, od->pdev.id,@@ -213,12 +213,12 @@ static int _omap_device_deactivate(struct omap_device *od, u8 ignore_lat) odpl->deactivate_lat_worst = deact_lat;if (odpl->flags &OMAP_DEVICE_LATENCY_AUTO_ADJUST ) { odpl->deactivate_lat = deact_lat; -pr_warning ("omap_device: %s.%d: new worst case " +pr_debug ("omap_device: %s.%d: new worst case " "deactivate latency %d: %llu\n" , od->pdev.name, od->pdev.id, od->pm_lat_level, deact_lat); }else - pr_warning("omap_device: %s.%d: deactivate " + pr_debug("omap_device: %s.%d: deactivate " "latency %d higher than exptected. " "(%llu > %d)\n", od->pdev.name, od->pdev.id,drivers/tty/serial/omap-serial.c +7
-1@@ -1007,7 +1007,10 @@ serial_omap_console_write(struct console *co, const char *s,struct uart_omap_port *up = serial_omap_console_ports[co->index];unsigned long flags;unsigned int ier; -int locked =1 ; +int console_lock =0 , locked =1 ; + +if (console_trylock ()) + console_lock =1 ;local_irq_save (flags);if (up->port.sysrq)@@ -1043,6 +1046,9 @@ serial_omap_console_write(struct console *co, const char *s,if (up->msr_saved_flags)check_modem_status (up); +if (console_lock) +console_unlock (); +serial_omap_port_disable (up);if (locked)spin_unlock (&up->port.lock);
PATCH v2 5/12 OMAP: Serial: Hold console lock for console usage.
Quoted 11 lines · Kevin Hilman
Quoted 8 lines · Govindraj.R
Acquire console lock before enabling and writing to console-uart to avoid any recursive prints from console write.
for ex:
? ? ? --> printk
? ? ? ? -->uart_console_write
? ? ? ? ? -->get_sync
? ? ? ? ? ? --> printk fromomap_deviceenable
? ? ? ? ? ? ? -->uart_consolewrite
Quoted 7 lines
By this time, since the device's runtime PM hooks have been called, the device's rutime PM state should be set to
RPM_SUSPENDING(not yetRPM_SUSPENDED).In addition to the console lock, you should be able to use that flag to avoid console writes while the console is in the process of suspending.
Yes RPM_SUSPENDING check helps along with console lock
<< Changes as below >>
---------------
drivers/tty/serial/omap-serial.c +0 -0
@@ -1040,6 +1040,18 @@ serial_omap_console_write(struct console *co,
const char *s,
if (console_trylock())
console_lock = 1;+ /*
+ * If console_lock is not available and we are in suspending + * state then we can avoid the console usage scenario + * as this may introduce recursive prints. + * Basically this scenario occurs during boot while + * printing debug bootlogs. + */
+
+ if (!console_lock &&
+ up->pdev->dev.power.runtime_status == RPM_SUSPENDING)
+ return;
+
local_irq_save(flags);
if (up->port.sysrq)
locked = 0;------------
Is it ok to check the RPM_SUSPENDING flag in driver ? I can't find any API currently available under runtime.h to use.
Quoted 8 lines
Quoted 8 lines
Also during bootup
console_lockis not available.
? ? ? ?-->uart_add_one_port
? ? ? ? ?-->console_register
? ? ? ? ? ? ?-->console_lock
? ? ? ? ? ? ? -->console_unlock
? ? ? ? ? ? ? ? ? ?-->call_console_drivers(here yetconsole_lockis not released) ? ? ? ? ? ? ? ? ? ? ? ? -->uart_console_write
Quoted 6 lines
Quoted 1 line
Hence convert prints from omap_device_enable/disable to
pr_debug.And what if you add 'debug' to your kernel command line? ?IOW, you're only solving the problem if you debug printk's are not going to the console.
yes correct issue will re-surface during boot-up once we have debug enabled and all pr_debugs with omap_device_enable trying to use console_write.
--
Thanks,
Govindraj.R
Quoted 79 lines
You're also not solving the problem that will happen down the road when someone else adds a printk to low-level code in order to debug something deep in the idle sequence.
The recursive locking needs to be solved, not avoided.
Kevin
Quoted 57 lines
Signed-off-by Govindraj.R <[email protected]>---
?arch/arm/plat-omap/omap_device.c | ? ?8 ++++---- ?drivers/tty/serial/omap-serial.c | ? ?8 +++++++- ?2 files changed, 11 insertions(+), 5 deletions(-)arch/arm/plat-omap/omap_device.c +1
-1@@ -145,12 +145,12 @@ static int _omap_device_activate(struct omap_device *od, u8 ignore_lat) ? ? ? ? ? ? ? ? ? ? ? odpl->activate_lat_worst = act_lat; ? ? ? ? ? ? ? ? ? ? ? if (odpl->flags & OMAP_DEVICE_LATENCY_AUTO_ADJUST) { ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? odpl->activate_lat = act_lat; - ? ? ? ? ? ? ? ? ? ? ? ? ? ? pr_warning("omap_device: %s.%d: new worst case " + ? ? ? ? ? ? ? ? ? ? ? ? ? ? pr_debug("omap_device: %s.%d: new worst case " ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?"activate latency %d: %llu\n", ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?od->pdev.name, od->pdev.id, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?od->pm_lat_level, act_lat);? ? ? ? ? ? ? ? ? ? ? } else
- ? ? ? ? ? ? ? ? ? ? ? ? ? ? pr_warning("omap_device: %s.%d: activate "
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? pr_debug("omap_device: %s.%d: activate " ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?"latency %d higher than exptected. " ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?"(%llu > %d)\n",
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?od->pdev.name,od->pdev.id,arch/arm/plat-omap/omap_device.c +1
-1@@ -213,12 +213,12 @@ static int _omap_device_deactivate(struct omap_device *od, u8 ignore_lat) ? ? ? ? ? ? ? ? ? ? ? odpl->deactivate_lat_worst = deact_lat; ? ? ? ? ? ? ? ? ? ? ? if (odpl->flags & OMAP_DEVICE_LATENCY_AUTO_ADJUST) { ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? odpl->deactivate_lat = deact_lat; - ? ? ? ? ? ? ? ? ? ? ? ? ? ? pr_warning("omap_device: %s.%d: new worst case " + ? ? ? ? ? ? ? ? ? ? ? ? ? ? pr_debug("omap_device: %s.%d: new worst case " ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?"deactivate latency %d: %llu\n", ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?od->pdev.name, od->pdev.id, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?od->pm_lat_level, deact_lat);? ? ? ? ? ? ? ? ? ? ? } else
- ? ? ? ? ? ? ? ? ? ? ? ? ? ? pr_warning("omap_device: %s.%d: deactivate "
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? pr_debug("omap_device: %s.%d: deactivate " ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?"latency %d higher than exptected. " ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?"(%llu > %d)\n",
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?od->pdev.name,od->pdev.id,drivers/tty/serial/omap-serial.c +4
-1@@ -1007,7 +1007,10 @@ serial_omap_console_write(struct console *co, const char *s, ? ? ? struct uart_omap_port *up = serial_omap_console_ports[co->index]; ? ? ? unsigned long flags; ? ? ? unsigned int ier; - ? ? int locked = 1; + ? ? int console_lock = 0, locked = 1; + + ? ? if (console_trylock()) + ? ? ? ? ? ? console_lock = 1; ? ? ? local_irq_save(flags); ? ? ? if (up->port.sysrq)drivers/tty/serial/omap-serial.c serial_omap_console_write(struct console *co, const char *s, · line 1054
Quoted 9 lines
drivers/tty/serial/omap-serial.c +3
-0@@ -1043,6 +1046,9 @@ serial_omap_console_write(struct console *co, const char *s, ? ? ? if (up->msr_saved_flags) ? ? ? ? ? ? ? check_modem_status(up); + ? ? if (console_lock) + ? ? ? ? ? ? console_unlock(); + ? ? ? serial_omap_port_disable(up); ? ? ? if (locked) ? ? ? ? ? ? ? spin_unlock(&up->port.lock);--
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
PATCH v2 5/12 OMAP: Serial: Hold console lock for console usage.
Quoted 16 lines · Govindraj
Quoted 15 lines · Kevin Hilman
Quoted 8 lines · Govindraj.R
Acquire console lock before enabling and writing to console-uart to avoid any recursive prints from console write.
for ex:
? ? ? --> printk
? ? ? ? -->uart_console_write
? ? ? ? ? -->get_sync
? ? ? ? ? ? --> printk fromomap_deviceenable
? ? ? ? ? ? ? -->uart_consolewriteBy this time, since the device's runtime PM hooks have been called, the device's rutime PM state should be set to
RPM_SUSPENDING(not yetRPM_SUSPENDED).
Quoted 5 lines
Quoted 3 lines
In addition to the console lock, you should be able to use that flag to avoid console writes while the console is in the process of suspending.
Yes
RPM_SUSPENDINGcheck helps along with console lock
Great!
Quoted 27 lines
<< Changes as below >>
---------------drivers/tty/serial/omap-serial.c +12
-0@@ -1040,6 +1040,18 @@ serial_omap_console_write(struct console *co,const char *s, if (console_trylock()) console_lock =1 ; +/* +* If console_lock is not available and we are in suspending +* state then we can avoid the console usage scenario +* as this may introduce recursive prints. +* Basically this scenario occurs during boot while +* printing debug bootlogs. +*/ + +if (!console_lock && + up->pdev->dev.power.runtime_status ==RPM_SUSPENDING ) +return ; +local_irq_save (flags);if (up->port.sysrq)locked = 0;
Quoted 4 lines
------------
Is it ok to check the
RPM_SUSPENDINGflag in driver ? I can't find any API currently available underruntime.hto use.
I would propose a new API in pm_runtime.h similar to pm_runtime_suspended() that checks for this.
Kevin
PATCH v2 6/12 Serial: OMAP2+: Move erratum handling from serial.c
In reply to Govindraj.RMove the erratum handling mechanism from serial.c to driver file and utilise the same func. in driver file.
--- drivers/tty/serial/omap-serial.c | 58 ++++++++++++++++++++++++++++++++++--- 1 files changed, 53 insertions(+), 5 deletions(-)
drivers/tty/serial/omap-serial.c +53 -5
@@ -52,6 +52,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) {
@@ -806,7 +807,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 */ -serial_out (up,UART_OMAP_MDR1 , up->mdr1); +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 ,UART_LCR_CONF_MODE_B ); up->efr =serial_in (up,UART_EFR );
@@ -831,7 +836,10 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,else up->mdr1 =UART_OMAP_MDR1_16X_MODE ; -serial_out (up,UART_OMAP_MDR1 , up->mdr1) +if (up->errata & UART_ERRATA_i202_MDR1_ACCESS) +omap_uart_mdr1_errataset (up); +else +serial_out (up,UART_OMAP_MDR1 , up->mdr1);/* Hardware Flow Control Configuration */
@@ -1434,11 +1442,48 @@ static int serial_omap_remove(struct platform_device *dev)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 ; -serial_out (up,UART_OMAP_MDR1 , up->mdr1); +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 );
@@ -1455,8 +1500,11 @@ static void omap_uart_restore_context(struct uart_omap_port *up)serial_out (up,UART_LCR ,0xBF );/* Config B mode */ serial_out (up,UART_EFR , efr);serial_out (up,UART_LCR ,UART_LCR_WLEN8 ); -/* UART 16x mode */ -serial_out (up,UART_OMAP_MDR1 , up->mdr1); +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 int omap_serial_runtime_suspend (struct device *dev)
Signature · 1 line
1.7.1
PATCH v2 7/12 OMAP: Serial: Allow UART parameters to be configured from board file
In reply to Govindraj.RFrom: Deepak K <[email protected]>
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 auto suspend delay that will be passed for pm_runtime_autosuspend
where uart will be disabled after timeout
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.
--- arch/arm/mach-omap2/board-2430sdp.c | 3 +- arch/arm/mach-omap2/board-3430sdp.c | 9 ++++--- arch/arm/mach-omap2/board-4430sdp.c | 11 +++++---- 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 | 11 +++++---- 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 | 28 +++++++++++++++++++++++- 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 | 8 ++---- 30 files changed, 109 insertions(+), 52 deletions(-)
arch/arm/mach-omap2/board-2430sdp.c +2 -1
@@ -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"
@@ -250,7 +251,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);
arch/arm/mach-omap2/board-3430sdp.c +5 -4
@@ -32,6 +32,7 @@#include <asm/mach/map.h> #include <plat/mcspi.h> +#include <plat/omap-serial.h> #include <plat/board.h> #include <plat/usb.h> #include <plat/common.h>
@@ -739,16 +740,16 @@ static struct omap_board_data serial3_data = {static inline void board_serial_init (void ) { -omap_serial_init_port (&serial1_data); -omap_serial_init_port (&serial2_data); -omap_serial_init_port (&serial3_data); +omap_serial_init_port (&serial1_data,NULL ); +omap_serial_init_port (&serial2_data,NULL ); +omap_serial_init_port (&serial3_data,NULL ); }#else #define board_mux NULLstatic inline void board_serial_init (void ) { -omap_serial_init (); +omap_serial_init (NULL ); }#endif
arch/arm/mach-omap2/board-4430sdp.c +6 -5
@@ -37,6 +37,7 @@#include <plat/mmc.h> #include <plat/omap4-keypad.h> #include <plat/display.h> +#include <plat/omap-serial.h> #include "mux.h" #include "hsmmc.h"
@@ -762,18 +763,18 @@ static inline void board_serial_init(void) bdata.pads_cnt =0 ; bdata.id =0 ;/* pass dummy data for UART1 */ -omap_serial_init_port (&bdata); +omap_serial_init_port (&bdata,NULL ); -omap_serial_init_port (&serial2_data); -omap_serial_init_port (&serial3_data); - omap_serial_init_port(&serial4_data); +omap_serial_init_port (&serial2_data,NULL ); +omap_serial_init_port (&serial3_data,NULL ); + omap_serial_init_port(&serial4_data, NULL); }#else #define board_mux NULLstatic inline void board_serial_init (void ) { -omap_serial_init (); +omap_serial_init (NULL ); }#endif
arch/arm/mach-omap2/board-am3517evm.c +2 -1
@@ -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"
@@ -490,7 +491,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 );
arch/arm/mach-omap2/board-apollon.c +2 -1
@@ -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 )
arch/arm/mach-omap2/board-cm-t35.c +2 -1
@@ -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>
@@ -729,7 +730,7 @@ static void __init cm_t35_init(void) omap_board_config = cm_t35_config; omap_board_config_size =ARRAY_SIZE (cm_t35_config);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 ();
arch/arm/mach-omap2/board-cm-t3517.c +2 -1
@@ -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>
@@ -291,7 +292,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 ); omap_board_config = cm_t3517_config; omap_board_config_size =ARRAY_SIZE (cm_t3517_config);cm_t3517_init_leds ();
arch/arm/mach-omap2/board-devkit8000.c +2 -1
@@ -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>
@@ -786,7 +787,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 ();
arch/arm/mach-omap2/board-generic.c +2 -1
@@ -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[] = { };
@@ -41,7 +42,7 @@ static void __init omap_generic_init_early(void)static void __init omap_generic_init (void ) { -omap_serial_init (); +omap_serial_init (NULL ); omap_board_config = generic_config; omap_board_config_size =ARRAY_SIZE (generic_config); }
arch/arm/mach-omap2/board-h4.c +2 -1
@@ -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 );h4_init_flash (); }
arch/arm/mach-omap2/board-igep0020.c +2 -1
@@ -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"
@@ -647,7 +648,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);usbhs_init (&usbhs_bdata);
arch/arm/mach-omap2/board-igep0030.c +2 -1
@@ -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);usbhs_init (&usbhs_bdata);
arch/arm/mach-omap2/board-ldp.c +2 -1
@@ -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>
@@ -404,7 +405,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 );
arch/arm/mach-omap2/board-n8x0.c +5 -4
@@ -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
arch/arm/mach-omap2/board-omap3beagle.c +2 -1
@@ -40,6 +40,7 @@#include <asm/mach/flash.h> #include <plat/board.h> +#include <plat/omap-serial.h> #include <plat/common.h> #include <plat/display.h> #include <plat/panel-generic-dpi.h>
@@ -662,7 +663,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" );
arch/arm/mach-omap2/board-omap3evm.c +2 -1
@@ -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"
@@ -795,7 +796,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 ();
arch/arm/mach-omap2/board-omap3logic.c +2 -1
@@ -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
@@ -211,7 +212,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 ();
arch/arm/mach-omap2/board-omap3pandora.c +2 -1
@@ -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"
@@ -702,7 +703,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 ();
arch/arm/mach-omap2/board-omap3stalker.c +2 -1
@@ -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>
@@ -605,7 +606,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);usbhs_init (&usbhs_bdata);ads7846_dev_init ();
arch/arm/mach-omap2/board-omap3touchbook.c +2 -1
@@ -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"
@@ -518,7 +519,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" );
arch/arm/mach-omap2/board-omap4panda.c +6 -5
@@ -40,6 +40,7 @@#include <plat/common.h> #include <plat/usb.h> #include <plat/mmc.h> +#include <plat/omap-serial.h> #include <plat/panel-generic-dpi.h> #include "timer-gp.h"
@@ -577,18 +578,18 @@ static inline void board_serial_init(void) bdata.pads_cnt =0 ; bdata.id =0 ;/* pass dummy data for UART1 */ -omap_serial_init_port (&bdata); +omap_serial_init_port (&bdata,NULL ); -omap_serial_init_port (&serial2_data); -omap_serial_init_port (&serial3_data); - omap_serial_init_port(&serial4_data); +omap_serial_init_port (&serial2_data,NULL ); +omap_serial_init_port (&serial3_data,NULL ); + omap_serial_init_port(&serial4_data, NULL); }#else #define board_mux NULLstatic inline void board_serial_init (void ) { -omap_serial_init (); +omap_serial_init (NULL ); }#endif
arch/arm/mach-omap2/board-overo.c +2 -1
@@ -52,6 +52,7 @@#include <plat/mcspi.h> #include <plat/mux.h> #include <plat/usb.h> +#include <plat/omap-serial.h> #include "mux.h" #include "sdram-micron-mt46h32m32lf-6.h"
@@ -653,7 +654,7 @@ static void __init overo_init(void)omap3_mux_init (board_mux,OMAP_PACKAGE_CBB );overo_i2c_init ();omap_display_init (&overo_dss_data); -omap_serial_init (); +omap_serial_init (NULL );overo_flash_init ();usb_musb_init (&musb_board_data);usbhs_init (&usbhs_bdata);
arch/arm/mach-omap2/board-rm680.c +2 -1
@@ -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 (); }
arch/arm/mach-omap2/board-rx51.c +2 -1
@@ -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 void __init rx51_init(void) omap_board_config = rx51_config; omap_board_config_size =ARRAY_SIZE (rx51_config);omap3_pm_init_cpuidle (rx51_cpuidle_params); -omap_serial_init (); +omap_serial_init (NULL );usb_musb_init (&musb_board_data);rx51_peripherals_init ();
arch/arm/mach-omap2/board-ti8168evm.c +1 -1
@@ -40,7 +40,7 @@ static void __init ti8168_evm_init_irq(void)static void __init ti8168_evm_init (void ) { -omap_serial_init (); +omap_serial_init (NULL ); omap_board_config = ti8168_evm_config; omap_board_config_size =ARRAY_SIZE (ti8168_evm_config); }
arch/arm/mach-omap2/board-zoom-peripherals.c +2 -1
@@ -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 ); }
arch/arm/mach-omap2/serial.c +26 -2
@@ -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 , + .auto_sus_timeout =DEFAULT_AUTOSUSPEND_DELAY , + }, +}; +static int uart_idle_hwmod (struct omap_device *od) {omap_hwmod_idle (od->hwmods[0 ]);
@@ -307,6 +316,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()
@@ -315,7 +325,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;
@@ -333,6 +344,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" );
@@ -348,6 +362,10 @@ void __init omap_serial_init_port(struct omap_board_data *bdata) pdata->uartclk =OMAP24XX_BASE_BAUD *16 ; pdata->flags =UPF_BOOT_AUTOCONF ; pdata->enable_wakeup = omap_uart_wakeup_enable; + 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->auto_sus_timeout = info->auto_sus_timeout;if (bdata->id == omap_uart_con_id) pdata->console_uart = true;
@@ -366,16 +384,20 @@ 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 ;
@@ -384,5 +406,7 @@ void __init omap_serial_init(void)if (cpu_is_omap44xx () ||cpu_is_omap34xx ())omap_serial_fill_default_pads (&bdata); + +omap_serial_init_port (&bdata, info); } }
arch/arm/plat-omap/include/plat/omap-serial.h +11 -3
@@ -51,7 +51,12 @@#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_AUTOSUSPEND_DELAY (30 * HZ)/* Runtime autosuspend (msecs) */ + +#define OMAP_MAX_HSUART_PORTS 4#define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA
@@ -64,6 +69,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 auto_sus_timeout;/* Auto_suspend timeout */ void (*enable_wakeup)(struct platform_device *,bool );void __iomem *wk_st;
@@ -92,8 +100,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 {
arch/arm/plat-omap/include/plat/serial.h +4 -2
@@ -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);#endif #endif
drivers/tty/serial/omap-serial.c +3 -5
@@ -44,8 +44,6 @@#include <plat/omap-serial.h> #include <plat/omap_device.h> -#define OMAP_UART_AUTOSUSPEND_DELAY (30 * HZ)/* Value is msecs */ -static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS ];/* Forward declaration of functions */
@@ -1386,8 +1384,8 @@ 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 ;
@@ -1396,7 +1394,7 @@ static int serial_omap_probe(struct platform_device *pdev)pm_runtime_use_autosuspend (&pdev->dev);pm_runtime_set_autosuspend_delay (&pdev->dev, -OMAP_UART_AUTOSUSPEND_DELAY ); + omap_up_info->auto_sus_timeout);pm_runtime_enable (&pdev->dev);pm_runtime_irq_safe (&pdev->dev);
Signature · 1 line
1.7.1
Tony Lindgren
maintainerPATCH v2 7/12 OMAP: Serial: Allow UART parameters to be configured from board file
Quoted 8 lines · Govindraj.R
arch/arm/mach-omap2/board-2430sdp.c +1
-1@@ -250,7 +251,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);
...
arch/arm/mach-omap2/board-3430sdp.c static struct omap_board_data serial3_data = { · line 753
Quoted 5 lines
static inline void
board_serial_init(void)
{arch/arm/mach-omap2/board-3430sdp.c +1
-1-omap_serial_init (); +omap_serial_init (NULL ); }
This change seems like "crazy churn" and probably not needed if it's always null. Boards using platform_data can use omap_serial_init_port instead, right?
Tony
PATCH v2 7/12 OMAP: Serial: Allow UART parameters to be configured from board file
Quoted 17 lines · Tony Lindgren
Quoted 8 lines · Govindraj.R
(quoted diff) +1
-1@@ -250,7 +251,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);...
Quoted 5 lines
?static inline void
board_serial_init(void)
?{
- ? ?omap_serial_init();
+ ? ?omap_serial_init(NULL);
?}
Quoted 3 lines
This change seems like "crazy churn" and probably not needed if it's always null. Boards using
platform_datacan useomap_serial_init_portinstead, right?
We can intiliaze only one uart port with omap_serial_init_port.
omap_serial_init initializes all uart port.
During any client device integration using dma mode (for example Bluetooth) we can pass the dma config params based on the board & client device.
--
Govindraj.R
Quoted 7 lines
Tony
--
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
Tony Lindgren
maintainerPATCH v2 7/12 OMAP: Serial: Allow UART parameters to be configured from board file
Quoted 22 lines · Govindraj
Quoted 17 lines · Tony Lindgren
Quoted 8 lines · Govindraj.R
(quoted diff) +1
-1@@ -250,7 +251,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);...
Quoted 5 lines
?static inline void
board_serial_init(void)
?{
- ? ?omap_serial_init();
+ ? ?omap_serial_init(NULL);
?}Quoted 3 lines
This change seems like "crazy churn" and probably not needed if it's always null. Boards using
platform_datacan useomap_serial_init_portinstead, right?
Quoted 7 lines
We can intiliaze only one uart port with
omap_serial_init_port.
omap_serial_initinitializes all uart port.During any client device integration using dma mode (for example Bluetooth) we can pass the dma config params based on the board & client device.
But you're changing all omap_serial_init() calls to omap_serial_init(NULL) so there are no users for that.
It should be a separate patch if it's needed.
Tony
PATCH v2 7/12 OMAP: Serial: Allow UART parameters to be configured from board file
Quoted 27 lines · Tony Lindgren
Quoted 26 lines · Govindraj
Quoted 17 lines · Tony Lindgren
Quoted 8 lines · Govindraj.R
(quoted diff) +1
-1@@ -250,7 +251,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);...
Quoted 5 lines
?static inline void
board_serial_init(void)
?{
- ? ?omap_serial_init();
+ ? ?omap_serial_init(NULL);
?}Quoted 3 lines
This change seems like "crazy churn" and probably not needed if it's always null. Boards using
platform_datacan useomap_serial_init_portinstead, right?We can intiliaze only one uart port with
omap_serial_init_port.
omap_serial_initinitializes all uart port.
Quoted 9 lines
Quoted 3 lines
During any client device integration using dma mode (for example Bluetooth) we can pass the dma config params based on the board & client device.
But you're changing all
omap_serial_init()calls toomap_serial_init(NULL)so there are no users for that.It should be a separate patch if it's needed.
Agree.
Will add seperate func. in serial.c file for board that need to pass these params and retain the old func. omap_serial_init() syntax to avoid all the additions in board-*.c files.
--
Thanks,
Govindraj.R
Quoted 2 lines
Tony
PATCH v2 8/12 Serial: OMAP2+: Make the RX_TIMEOUT for DMA configurable for each UART
In reply to Govindraj.RFrom: Jon Hunter <[email protected]>
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.
--- 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(-)
arch/arm/mach-omap2/serial.c +2 -0
@@ -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, .auto_sus_timeout = DEFAULT_AUTOSUSPEND_DELAY, },
@@ -364,6 +365,7 @@ void __init omap_serial_init_port(struct omap_board_data *bdata, pdata->enable_wakeup = omap_uart_wakeup_enable; 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->auto_sus_timeout = info->auto_sus_timeout;if (bdata->id == omap_uart_con_id)
arch/arm/plat-omap/include/plat/omap-serial.h +4 -2
@@ -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_AUTOSUSPEND_DELAY (30 * HZ)/* Runtime autosuspend (msecs) */
@@ -71,6 +71,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 auto_sus_timeout;/* Auto_suspend timeout */ void (*enable_wakeup)(struct platform_device *,bool );
@@ -101,6 +102,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; };
drivers/tty/serial/omap-serial.c +8 -7
@@ -48,7 +48,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);
@@ -543,7 +543,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,
@@ -1162,7 +1162,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;
@@ -1172,9 +1172,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 );
@@ -1204,7 +1204,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; }
@@ -1246,7 +1246,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; }
@@ -1386,6 +1386,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 ;
Signature · 1 line
1.7.1
PATCH v2 9/12 OMAP3: Serial: Remove uart pads from 3430 board file.
In reply to Govindraj.RThe pad values here are same as the default pad values updated in serial.c file. Avoid structure duplication and use default pads.
--- arch/arm/mach-omap2/board-3430sdp.c | 100 +---------------------------------- 1 files changed, 1 insertions(+), 99 deletions(-)
arch/arm/mach-omap2/board-3430sdp.c +1 -99
@@ -651,106 +651,8 @@ static const struct usbhs_omap_board_data usbhs_bdata __initconst = {static struct omap_board_mux board_mux[]__initdata = { { .reg_offset =OMAP_MUX_TERMINATOR }, }; - -static struct omap_device_pad serial1_pads[]__initdata = { -/* -* Note that off output enable is an active low -* signal. So setting this means pin is a -* input enabled in off mode -*/ -OMAP_MUX_STATIC ("uart1_cts.uart1_cts" , -OMAP_PIN_INPUT | -OMAP_PIN_OFF_INPUT_PULLDOWN | -OMAP_OFFOUT_EN | -OMAP_MUX_MODE0 ), -OMAP_MUX_STATIC ("uart1_rts.uart1_rts" , -OMAP_PIN_OUTPUT | -OMAP_OFF_EN | -OMAP_MUX_MODE0 ), -OMAP_MUX_STATIC ("uart1_rx.uart1_rx" , -OMAP_PIN_INPUT | -OMAP_PIN_OFF_INPUT_PULLDOWN | -OMAP_OFFOUT_EN | -OMAP_MUX_MODE0 ), -OMAP_MUX_STATIC ("uart1_tx.uart1_tx" , -OMAP_PIN_OUTPUT | -OMAP_OFF_EN | -OMAP_MUX_MODE0 ), -}; - -static struct omap_device_pad serial2_pads[]__initdata = { -OMAP_MUX_STATIC ("uart2_cts.uart2_cts" , -OMAP_PIN_INPUT_PULLUP | -OMAP_PIN_OFF_INPUT_PULLDOWN | -OMAP_OFFOUT_EN | -OMAP_MUX_MODE0 ), -OMAP_MUX_STATIC ("uart2_rts.uart2_rts" , -OMAP_PIN_OUTPUT | -OMAP_OFF_EN | -OMAP_MUX_MODE0 ), -OMAP_MUX_STATIC ("uart2_rx.uart2_rx" , -OMAP_PIN_INPUT | -OMAP_PIN_OFF_INPUT_PULLDOWN | -OMAP_OFFOUT_EN | -OMAP_MUX_MODE0 ), -OMAP_MUX_STATIC ("uart2_tx.uart2_tx" , -OMAP_PIN_OUTPUT | -OMAP_OFF_EN | -OMAP_MUX_MODE0 ), -}; - -static struct omap_device_pad serial3_pads[]__initdata = { -OMAP_MUX_STATIC ("uart3_cts_rctx.uart3_cts_rctx" , -OMAP_PIN_INPUT_PULLDOWN | -OMAP_PIN_OFF_INPUT_PULLDOWN | -OMAP_OFFOUT_EN | -OMAP_MUX_MODE0 ), -OMAP_MUX_STATIC ("uart3_rts_sd.uart3_rts_sd" , -OMAP_PIN_OUTPUT | -OMAP_OFF_EN | -OMAP_MUX_MODE0 ), -OMAP_MUX_STATIC ("uart3_rx_irrx.uart3_rx_irrx" , -OMAP_PIN_INPUT | -OMAP_PIN_OFF_INPUT_PULLDOWN | -OMAP_OFFOUT_EN | -OMAP_MUX_MODE0 ), -OMAP_MUX_STATIC ("uart3_tx_irtx.uart3_tx_irtx" , -OMAP_PIN_OUTPUT | -OMAP_OFF_EN | -OMAP_MUX_MODE0 ), -}; - -static struct omap_board_data serial1_data = { - .id =0 , - .pads = serial1_pads, - .pads_cnt =ARRAY_SIZE (serial1_pads), -}; - -static struct omap_board_data serial2_data = { - .id =1 , - .pads = serial2_pads, - .pads_cnt =ARRAY_SIZE (serial2_pads), -}; - -static struct omap_board_data serial3_data = { - .id =2 , - .pads = serial3_pads, - .pads_cnt =ARRAY_SIZE (serial3_pads), -}; - -static inline void board_serial_init (void ) -{ -omap_serial_init_port (&serial1_data,NULL ); -omap_serial_init_port (&serial2_data,NULL ); -omap_serial_init_port (&serial3_data,NULL ); -}#else #define board_mux NULL - -static inline void board_serial_init (void ) -{ -omap_serial_init (NULL ); -}#endif /*
@@ -895,7 +797,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 (); -board_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 );
Signature · 1 line
1.7.1
PATCH v2 10/12 OMAP2+: hwmod: Add api to enable io_ring wakeup.
In reply to Govindraj.RAdd api to enable io_pad wakeup based on mux dynamic pad and wake_up enable flag initialized during hwmod_mux.
Use the wakeup flag and pad_remux flag and enable wakeup capability for the pad having these flags enabled.
--- arch/arm/mach-omap2/omap_hwmod.c | 34 +++++++++++++++++++++++++ arch/arm/mach-omap2/serial.c | 6 ++++ arch/arm/plat-omap/include/plat/omap_device.h | 1 + arch/arm/plat-omap/include/plat/omap_hwmod.h | 1 + arch/arm/plat-omap/omap_device.c | 26 +++++++++++++++++++ 5 files changed, 68 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/omap_hwmod.c +34 -0
@@ -2369,3 +2369,37 @@ int omap_hwmod_no_setup_reset(struct omap_hwmod *oh)return 0 ; } + +/** +* omap_hwmod_enable_ioring_wakeup - Set wakeup bit for iopad ring. +* @oh: struct omap_hwmod * +* @enable: based on 0 or 1 set or unset wakeup bit. +* +* traverse through dynamic pads. If pad is enabled then +* set wakeup bit for the mux pin. Return error if pads are +* not enabled or not available. +*/ +int omap_hwmod_enable_ioring_wakeup (struct omap_hwmod *oh,bool enable) +{ +struct omap_device_pad *pad; +int ret = -EINVAL , j; +int val =0 ; + +/* Enable pin mux to make pad wake-up capable */ +if (enable) + val =OMAP_WAKEUP_EN ; +else + val = ~OMAP_WAKEUP_EN ; + +if (oh->mux->enabled) { +for (j =0 ; j < oh->mux->nr_pads_dynamic; j++) { + pad = oh->mux->pads_dynamic[j]; +if (pad->flags &OMAP_DEVICE_PAD_WAKEUP ) { + pad->idle = pad->enable | val; + ret =0 ; + } + } + } + +return ret; +}
arch/arm/mach-omap2/serial.c +6 -0
@@ -212,6 +212,12 @@ static void omap_uart_wakeup_enable(struct platform_device *pdev, bool enable) v &= ~up->wk_mask;__raw_writel (v, up->wk_en); } + +/* Enable or clear io-pad wakeup */ +if (enable) +omap_device_enable_ioring_wakeup (pdev, true); +else +omap_device_enable_ioring_wakeup (pdev, false); } static void omap_uart_idle_init(struct omap_uart_port_info *uart,
arch/arm/plat-omap/include/plat/omap_device.h +1 -0
@@ -117,6 +117,7 @@ int omap_device_enable_hwmods(struct omap_device *od);int omap_device_disable_clocks (struct omap_device *od);int omap_device_enable_clocks (struct omap_device *od); +int omap_device_enable_ioring_wakeup (struct platform_device *pdev,bool enable);/* * Entries should be kept in latency order ascending
arch/arm/plat-omap/include/plat/omap_hwmod.h +1 -0
@@ -601,6 +601,7 @@ 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_hwmod_no_setup_reset (struct omap_hwmod *oh); +int omap_hwmod_enable_ioring_wakeup (struct omap_hwmod *oh,bool enable);/* * Chip variant-specific hwmod init routines - XXX should be converted
arch/arm/plat-omap/omap_device.c +26 -0
@@ -742,6 +742,32 @@ void __iomem *omap_device_get_rt_va(struct omap_device *od)return omap_hwmod_get_mpu_rt_va (od->hwmods[0 ]); } +/** +* omap_device_enable_ioring_wakeup - Set wakeup bit for iopad ring. +* @pdev: platform_device for which wakeup needs to be set. +* @enable: based on 0 or 1 set or unset wakeup bit. +* +* Caller should ensure this is called if device_may_wakeup(dev) is true +* traverse through each hwmod and check each available pads +* if pad is enabled then set wakeup bit for the mux pin. +* Return error if pads are not enabled or not available. +* If pad is not enabled for the given device then return NULL. +*/ +int omap_device_enable_ioring_wakeup (struct platform_device *pdev,bool enable) +{ +int ret = -EINVAL , i; +struct omap_device *od; +struct omap_hwmod *oh; + + od =_find_by_pdev (pdev); +for (i =0 ; i < od->hwmods_cnt; i++) { + oh = od->hwmods[i]; + ret =omap_hwmod_enable_ioring_wakeup (oh, enable); + } + +return ret; +} +/* * Public functions intended for use in omap_device_pm_latency * .activate_func and .deactivate_func function pointers
Signature · 1 line
1.7.1
PATCH v2 10/12 OMAP2+: hwmod: Add api to enable io_ring wakeup.
Quoted 1 line · Govindraj.R
Add api to enable
io_padwakeup based on mux dynamic pad and
s/api/API/
s/io_pad/IO pad/
Quoted 6 lines
wake_upenable flag initialized duringhwmod_mux.Use the wakeup flag and
pad_remuxflag and enable wakeup capability for the pad having these flags enabled.Signed-off-by Govindraj.R <[email protected]>
This patch (except for the serial.c hange) isn't really dependent on the rest of this series, and should be a separate patch to be merged by Paul.
Some other comments below...
Quoted 13 lines
--- arch/arm/mach-omap2/omap_hwmod.c | 34 +++++++++++++++++++++++++ arch/arm/mach-omap2/serial.c | 6 ++++ arch/arm/plat-omap/include/plat/omap_device.h | 1 + arch/arm/plat-omap/include/plat/omap_hwmod.h | 1 + arch/arm/plat-omap/omap_device.c | 26 +++++++++++++++++++ 5 files changed, 68 insertions(+), 0 deletions(-)arch/arm/mach-omap2/omap_hwmod.c +0
-0
arch/arm/mach-omap2/omap_hwmod.c int omap_hwmod_no_setup_reset(struct omap_hwmod *oh) · line 2376
Quoted 8 lines
arch/arm/mach-omap2/omap_hwmod.c +5
-0@@ -2369,3 +2369,37 @@ int omap_hwmod_no_setup_reset(struct omap_hwmod *oh)return 0 ; } + +/** +* omap_hwmod_enable_ioring_wakeup - Set wakeup bit for iopad ring. +* @oh: struct omap_hwmod * +* @enable: based on 0 or 1 set or unset wakeup bit.
more specifically, when true, set wakeup bit, when false, clear wakeup bit
arch/arm/mach-omap2/omap_hwmod.c int omap_hwmod_no_setup_reset(struct omap_hwmod *oh) · line 2381
Quoted 4 lines
arch/arm/mach-omap2/omap_hwmod.c +4
-0+* traverse through dynamic pads. If pad is enabled then +* set wakeup bit for the mux pin. Return error if pads are +* not enabled or not available. +*/
The comment here should be clearer about when the bit actually gets set. Specifically, this function doesn't actually write the value out, but instead it configures the value which will be used during the hwmod idle transition.
Kevin
PATCH v2 10/12 OMAP2+: hwmod: Add api to enable io_ring wakeup.
Quoted 6 lines · Kevin Hilman
Quoted 1 line · Govindraj.R
Add api to enable
io_padwakeup based on mux dynamic pad ands/api/API/
s/io_pad/IO pad/
will update.
Quoted 12 lines
Quoted 7 lines
wake_upenable flag initialized duringhwmod_mux.Use the wakeup flag and
pad_remuxflag and enable wakeup capability for the pad having these flags enabled.Signed-off-by Govindraj.R <[email protected]>This patch (except for the
serial.change) isn't really dependent on the rest of this series, and should be a separate patch to be merged by Paul.
Yes. fine will post out hwmod API additions as separate patch.
Quoted 16 lines
Some other comments below...
Quoted 14 lines
---
?arch/arm/mach-omap2/omap_hwmod.c ? ? ? ? ? ? ?| ? 34 +++++++++++++++++++++++++ ?arch/arm/mach-omap2/serial.c ? ? ? ? ? ? ? ? ?| ? ?6 ++++ ?arch/arm/plat-omap/include/plat/omap_device.h | ? ?1 + ?arch/arm/plat-omap/include/plat/omap_hwmod.h ?| ? ?1 + ?arch/arm/plat-omap/omap_device.c ? ? ? ? ? ? ?| ? 26 +++++++++++++++++++?5 files changed, 68 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/omap_hwmod.c +0
-0@@ -2369,3 +2369,37 @@ int omap_hwmod_no_setup_reset(struct omap_hwmod *oh)
Quoted 9 lines
arch/arm/mach-omap2/omap_hwmod.c int omap_hwmod_no_setup_reset(struct omap_hwmod *oh) · line 2376
Quoted 7 lines
arch/arm/mach-omap2/omap_hwmod.c +5
-0? ? ? return 0; ?} + +/** +* omap_hwmod_enable_ioring_wakeup - Set wakeup bit for iopad ring. +* @oh: struct omap_hwmod * +* @enable: based on 0 or 1 set or unset wakeup bit. more specifically, when true, set wakeup bit, when false, clear wakeup bit
ok.
Quoted 11 lines
arch/arm/mach-omap2/omap_hwmod.c int omap_hwmod_no_setup_reset(struct omap_hwmod *oh) · line 2381
Quoted 5 lines
arch/arm/mach-omap2/omap_hwmod.c +4
-0+* traverse through dynamic pads. If pad is enabled then +* set wakeup bit for the mux pin. Return error if pads are +* not enabled or not available. +*/ The comment here should be clearer about when the bit actually gets set. ?Specifically, this function doesn't actually write the value out, but instead it configures the value which will be used during the hwmod idle transition.
Yes correct. Will update the comments.
Quoted 6 lines
Kevin
--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in the body of a message to majordomo at vger.kernel.org
More majordomo info at ?http://vger.kernel.org/majordomo-info.html
PATCH v2 11/12 OMAP: Serial: Use resume call from prcm to enable uart
In reply to Govindraj.RUse resume idle call from prcm_irq to enable uart_port from low power states. Add api to check pad wakeup status which will we used from uart_resume func. to enable back uart port if a wakeup event occurred.
UART_Resume func. can be removed once we have irq_chaining functionality available.
--- arch/arm/mach-omap2/mux.c | 23 +++++++++++++++++++++++ arch/arm/mach-omap2/mux.h | 13 +++++++++++++ arch/arm/mach-omap2/omap_hwmod.c | 13 +++++++++++++ arch/arm/mach-omap2/pm24xx.c | 2 ++ arch/arm/mach-omap2/pm34xx.c | 2 ++ arch/arm/mach-omap2/serial.c | 23 +++++++++++++++++++++++ arch/arm/plat-omap/include/plat/omap-serial.h | 2 ++ arch/arm/plat-omap/include/plat/omap_hwmod.h | 1 + arch/arm/plat-omap/include/plat/serial.h | 1 + drivers/tty/serial/omap-serial.c | 23 +++++++++++++++++++++++ 10 files changed, 103 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/mux.c +23 -0
@@ -348,6 +348,29 @@ err1:return NULL ; } +/* Gets the wakeup status of given pad from omap-hwmod. +* Returns the wake_up status bit of available pad mux pin +*/ +bool omap_hwmod_mux_wakeup (struct omap_hwmod_mux_info *hmux) +{ +int i; +unsigned int val; +u8 ret =0 ; + +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 &OMAP_WAKEUP_EVENT ) { + ret =1 ; +break ; + } + } + +return ret; +} +/* Assumes the calling function takes care of locking */ void omap_hwmod_mux (struct omap_hwmod_mux_info *hmux,u8 state) {
arch/arm/mach-omap2/mux.h +13 -0
@@ -225,8 +225,21 @@ omap_hwmod_mux_init(struct omap_device_pad *bpads, int nr_pads);*/ void omap_hwmod_mux (struct omap_hwmod_mux_info *hmux,u8 state); + +/** +* omap_hwmod_mux_wakeup - omap hwmod check given pad had wakeup event +* @hmux: Pads for a hwmod +* +* Called only from omap_hwmod.c, do not use. +*/ +bool omap_hwmod_mux_wakeup (struct omap_hwmod_mux_info *hmux);#else +static inline bool 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 ;
arch/arm/mach-omap2/omap_hwmod.c +13 -0
@@ -2403,3 +2403,16 @@ int omap_hwmod_enable_ioring_wakeup(struct omap_hwmod *oh, bool enable)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 ; +}
arch/arm/mach-omap2/pm24xx.c +2 -0
@@ -137,6 +137,8 @@ static void omap2_enter_full_retention(void)OMAP_SDRC_REGADDR (SDRC_DLLA_CTRL ), OMAP_SDRC_REGADDR(SDRC_POWER)); +omap_uart_resume_idle (); + no_sleep:if (omap2_pm_debug) {unsigned long long tmp;
arch/arm/mach-omap2/pm34xx.c +2 -0
@@ -216,6 +216,8 @@ static int prcm_clear_mod_irqs(s16 module, u8 regs) wkst =omap2_prm_read_mod_reg (module, wkst_off); wkst &=omap2_prm_read_mod_reg (module, grpsel_off); + + c +=omap_uart_resume_idle ();if (wkst) { iclk =omap2_cm_read_mod_reg (module, iclk_off); fclk =omap2_cm_read_mod_reg (module, fclk_off);
arch/arm/mach-omap2/serial.c +23 -0
@@ -199,6 +199,28 @@ static void omap_serial_fill_default_pads(struct omap_board_data *bdata) } } +/* TBD: Will be removed once we have irq-chaing mechanism */ +static bool omap_uart_chk_wakeup (struct platform_device *pdev) +{ +struct omap_uart_port_info *up = pdev->dev.platform_data; +struct omap_device *od; +u32 wkst =0 ; +bool ret = false; + + od =to_omap_device (pdev); +if (omap_hmwod_pad_wakeup_status (od->hwmods[0 ])) + ret = true; + +/* Check for normal UART wakeup (and clear it) */ + wkst =__raw_readl (up->wk_st) & up->wk_mask; +if (wkst) { +__raw_writel (wkst, up->wk_st); + ret = true; + } + +return ret; +} +static void omap_uart_wakeup_enable (struct platform_device *pdev,bool enable) {struct omap_uart_port_info *up = pdev->dev.platform_data;
@@ -369,6 +391,7 @@ void __init omap_serial_init_port(struct omap_board_data *bdata, pdata->uartclk =OMAP24XX_BASE_BAUD *16 ; pdata->flags =UPF_BOOT_AUTOCONF ; pdata->enable_wakeup = omap_uart_wakeup_enable; + pdata->chk_wakeup = omap_uart_chk_wakeup; 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;
arch/arm/plat-omap/include/plat/omap-serial.h +2 -0
@@ -75,6 +75,7 @@ struct omap_uart_port_info {unsigned int auto_sus_timeout;/* Auto_suspend timeout */ void (*enable_wakeup)(struct platform_device *,bool ); +bool (*chk_wakeup)(struct platform_device *);void __iomem *wk_st;void __iomem *wk_en;u32 wk_mask;
@@ -132,6 +133,7 @@ struct uart_omap_port {unsigned long port_activity;unsigned int errata;void (*enable_wakeup)(struct platform_device *,bool ); + bool (*chk_wakeup)(struct platform_device *); };#endif /* __OMAP_SERIAL_H__ */
arch/arm/plat-omap/include/plat/omap_hwmod.h +1 -0
@@ -603,6 +603,7 @@ u32 omap_hwmod_get_context_loss_count(struct omap_hwmod *oh);int omap_hwmod_no_setup_reset (struct omap_hwmod *oh);int omap_hwmod_enable_ioring_wakeup (struct omap_hwmod *oh,bool enable); +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
arch/arm/plat-omap/include/plat/serial.h +1 -0
@@ -108,6 +108,7 @@ struct omap_uart_port_info;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 u32 omap_uart_resume_idle (void );#endif #endif
drivers/tty/serial/omap-serial.c +23 -0
@@ -43,6 +43,7 @@#include <plat/dmtimer.h> #include <plat/omap-serial.h> #include <plat/omap_device.h> +#include <plat/serial.h> static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS ];
@@ -108,6 +109,27 @@ static inline void serial_omap_port_enable(struct uart_omap_port *up)pm_runtime_get_sync (&up->pdev->dev); } +/* TBD: Should be removed once we irq-chaining mechanism in place */ +u32 omap_uart_resume_idle () +{ +int i; +u32 ret =0 ; + +for (i =0 ; i <OMAP_MAX_HSUART_PORTS ; i++) { +struct uart_omap_port *up = ui[i]; + +if (!up) +continue ; + +if (up->chk_wakeup (up->pdev)) { +serial_omap_port_enable (up); +serial_omap_port_disable (up); + ret++; + } + } +return ret; +} +static void serial_omap_stop_rxdma (struct uart_omap_port *up) {if (up->uart_dma.rx_dma_used) {
@@ -1379,6 +1401,7 @@ static int serial_omap_probe(struct platform_device *pdev) up->uart_dma.uart_base = mem->start; up->errata = omap_up_info->errata; up->enable_wakeup = omap_up_info->enable_wakeup; + up->chk_wakeup = omap_up_info->chk_wakeup;if (omap_up_info->dma_enabled) { up->uart_dma.uart_dma_tx = dma_tx->start;
Signature · 1 line
1.7.1
PATCH v2 11/12 OMAP: Serial: Use resume call from prcm to enable uart
Quoted 8 lines · Govindraj.R
Use resume idle call from
prcm_irqto enableuart_portfrom low power states. Add api to check pad wakeup status which will we used fromuart_resumefunc. to enable back uart port if a wakeup event occurred.
UART_Resumefunc. can be removed once we haveirq_chainingfunctionality available.Signed-off-by Govindraj.R <[email protected]>
The part adding a new hwmod API needs to be separated out into a separate patch which is not dependent on the rest of this series.
Quoted 18 lines
--- arch/arm/mach-omap2/mux.c | 23 +++++++++++++++++++++++ arch/arm/mach-omap2/mux.h | 13 +++++++++++++ arch/arm/mach-omap2/omap_hwmod.c | 13 +++++++++++++ arch/arm/mach-omap2/pm24xx.c | 2 ++ arch/arm/mach-omap2/pm34xx.c | 2 ++ arch/arm/mach-omap2/serial.c | 23 +++++++++++++++++++++++ arch/arm/plat-omap/include/plat/omap-serial.h | 2 ++ arch/arm/plat-omap/include/plat/omap_hwmod.h | 1 + arch/arm/plat-omap/include/plat/serial.h | 1 + drivers/tty/serial/omap-serial.c | 23 +++++++++++++++++++++++ 10 files changed, 103 insertions(+), 0 deletions(-)arch/arm/mach-omap2/mux.c +0
-0
arch/arm/mach-omap2/mux.c err1: · line 353
Quoted 6 lines
arch/arm/mach-omap2/mux.c +3
-0@@ -348,6 +348,29 @@ err1:return NULL ; } +/* Gets the wakeup status of given pad from omap-hwmod. +* Returns the wake_up status bit of available pad mux pin +*/
fix multi-line comment style
arch/arm/mach-omap2/mux.c err1: · line 354
Quoted 1 line
arch/arm/mach-omap2/mux.c +1
-0+bool omap_hwmod_mux_wakeup (struct omap_hwmod_mux_info *hmux)
The name here should be more descriptive: like _get_wake_status or something.
Quoted 27 lines
arch/arm/mach-omap2/mux.c +19
-0+{ +int i; +unsigned int val; +u8 ret =0 ; + +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 &OMAP_WAKEUP_EVENT ) { + ret =1 ; +break ; + } + } + +return ret; +} +/* Assumes the calling function takes care of locking */ void omap_hwmod_mux (struct omap_hwmod_mux_info *hmux,u8 state) {arch/arm/mach-omap2/mux.h +0
-0
arch/arm/mach-omap2/mux.h omap_hwmod_mux_init(struct omap_device_pad *bpads, int nr_pads); · line 234
Quoted 10 lines
arch/arm/mach-omap2/mux.h +7
-0@@ -225,8 +225,21 @@ omap_hwmod_mux_init(struct omap_device_pad *bpads, int nr_pads);*/ void omap_hwmod_mux (struct omap_hwmod_mux_info *hmux,u8 state); + +/** +* omap_hwmod_mux_wakeup - omap hwmod check given pad had wakeup event +* @hmux: Pads for a hwmod +* +* Called only from omap_hwmod.c, do not use. +*/
Please put the kerneldoc comments in the C file instead of the header.
Quoted 16 lines
arch/arm/mach-omap2/mux.h +6
-0+bool omap_hwmod_mux_wakeup (struct omap_hwmod_mux_info *hmux);#else +static inline bool 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 ;arch/arm/mach-omap2/omap_hwmod.c +0
-0
arch/arm/mach-omap2/omap_hwmod.c int omap_hwmod_enable_ioring_wakeup(struct omap_hwmod *oh, bool enable) · line 2408
Quoted 6 lines
arch/arm/mach-omap2/omap_hwmod.c +3
-0@@ -2403,3 +2403,16 @@ int omap_hwmod_enable_ioring_wakeup(struct omap_hwmod *oh, bool enable)return ret; } + +/** +* omap_hwmod_pad_wakeup_status - get pad wakeup status if mux is available.
How about _get_pad_wakeup_status()
arch/arm/mach-omap2/omap_hwmod.c int omap_hwmod_enable_ioring_wakeup(struct omap_hwmod *oh, bool enable) · line 2411
Quoted 3 lines
arch/arm/mach-omap2/omap_hwmod.c +3
-0+* @oh: struct omap_hwmod * +* +* Returns the wake_up status bit of available pad mux pin.
or on error... ?
Quoted 25 lines
arch/arm/mach-omap2/omap_hwmod.c +7
-0+*/ +int omap_hmwod_pad_wakeup_status (struct omap_hwmod *oh) +{ +if (oh->mux) +return omap_hwmod_mux_wakeup (oh->mux); +return -EINVAL ; +}arch/arm/mach-omap2/pm24xx.c +2
-0@@ -137,6 +137,8 @@ static void omap2_enter_full_retention(void)OMAP_SDRC_REGADDR (SDRC_DLLA_CTRL ), OMAP_SDRC_REGADDR(SDRC_POWER)); +omap_uart_resume_idle (); + no_sleep:if (omap2_pm_debug) {unsigned long long tmp;arch/arm/mach-omap2/pm34xx.c +0
-0
arch/arm/mach-omap2/pm34xx.c static int prcm_clear_mod_irqs(s16 module, u8 regs) · line 220
Quoted 5 lines
arch/arm/mach-omap2/pm34xx.c +2
-0@@ -216,6 +216,8 @@ static int prcm_clear_mod_irqs(s16 module, u8 regs) wkst =omap2_prm_read_mod_reg (module, wkst_off); wkst &=omap2_prm_read_mod_reg (module, grpsel_off); + + c +=omap_uart_resume_idle ();
No...
[...]
Quoted 13 lines
drivers/tty/serial/omap-serial.c +1
-0@@ -43,6 +43,7 @@#include <plat/dmtimer.h> #include <plat/omap-serial.h> #include <plat/omap_device.h> +#include <plat/serial.h> static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS ];
drivers/tty/serial/omap-serial.c static inline void serial_omap_port_enable(struct uart_omap_port *up) · line 112
Quoted 4 lines
drivers/tty/serial/omap-serial.c +1
-0@@ -108,6 +109,27 @@ static inline void serial_omap_port_enable(struct uart_omap_port *up)pm_runtime_get_sync (&up->pdev->dev); } +/* TBD: Should be removed once we irq-chaining mechanism in place */
...indeed...
Quoted 9 lines
drivers/tty/serial/omap-serial.c +9
-0+u32 omap_uart_resume_idle () +{ +int i; +u32 ret =0 ; + +for (i =0 ; i <OMAP_MAX_HSUART_PORTS ; i++) { +struct uart_omap_port *up = ui[i]; + +if (!up)
drivers/tty/serial/omap-serial.c static inline void serial_omap_port_enable(struct uart_omap_port *up) · line 131
Quoted 10 lines
drivers/tty/serial/omap-serial.c +10
-0+continue ; + +if (up->chk_wakeup (up->pdev)) { +serial_omap_port_enable (up); +serial_omap_port_disable (up); + ret++; + } + } +return ret; +}
... this is just putting back basically the same thing that was removed in patch 1. IOW, this is now being checked for *every* PRCM wakeup, which is no different than having it in the idle path.
I thought I understood that you had the SW IRQ triggering working, so this part should not be necessary.
Kevin
PATCH v2 11/12 OMAP: Serial: Use resume call from prcm to enable uart
Quoted 6 lines · Kevin Hilman
Quoted 4 lines · Govindraj.R
Use resume idle call from
prcm_irqto enableuart_portfrom low power states. Add api to check pad wakeup status which will we used fromuart_resumefunc. to enable back uart port if a wakeup event occurred.
Quoted 8 lines
Quoted 4 lines
UART_Resumefunc. can be removed once we haveirq_chainingfunctionality available.Signed-off-by Govindraj.R <[email protected]>The part adding a new hwmod API needs to be separated out into a separate patch which is not dependent on the rest of this series.
ok. fine
Quoted 21 lines
Quoted 21 lines
---
?arch/arm/mach-omap2/mux.c ? ? ? ? ? ? ? ? ? ? | ? 23 +++++++++++++++++++++++ ?arch/arm/mach-omap2/mux.h ? ? ? ? ? ? ? ? ? ? | ? 13 +++++++++++++ ?arch/arm/mach-omap2/omap_hwmod.c ? ? ? ? ? ? ?| ? 13 +++++++++++++ ?arch/arm/mach-omap2/pm24xx.c ? ? ? ? ? ? ? ? ?| ? ?2 ++ ?arch/arm/mach-omap2/pm34xx.c ? ? ? ? ? ? ? ? ?| ? ?2 ++ ?arch/arm/mach-omap2/serial.c ? ? ? ? ? ? ? ? ?| ? 23 +++++++++++++++++++++++ ?arch/arm/plat-omap/include/plat/omap-serial.h | ? ?2 ++ ?arch/arm/plat-omap/include/plat/omap_hwmod.h ?| ? ?1 + ?arch/arm/plat-omap/include/plat/serial.h ? ? ?| ? ?1 + ?drivers/tty/serial/omap-serial.c ? ? ? ? ? ? ?| ? 23 +++++++++++++++++++++++?10 files changed, 103 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/mux.c +0
-0@@ -348,6 +348,29 @@ err1: ? ? ? return NULL; ?}
Quoted 6 lines
arch/arm/mach-omap2/mux.c err1: · line 353
Quoted 3 lines
arch/arm/mach-omap2/mux.c +3
-0+/* Gets the wakeup status of given pad from omap-hwmod. +* Returns the wake_up status bit of available pad mux pin +*/ fix multi-line comment style
ok.
Quoted 35 lines
arch/arm/mach-omap2/mux.c err1: · line 354
Quoted 1 line
arch/arm/mach-omap2/mux.c +1
-0+bool omap_hwmod_mux_wakeup (struct omap_hwmod_mux_info *hmux)The name here should be more descriptive: like
_get_wake_statusor something.Quoted 30 lines
arch/arm/mach-omap2/mux.c +19
-0+{ + ? ? int i; + ? ? unsigned int val; + ? ? u8 ret = 0; + + ? ? 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 & OMAP_WAKEUP_EVENT) { + ? ? ? ? ? ? ? ? ? ? ret = 1; + ? ? ? ? ? ? ? ? ? ? break; + ? ? ? ? ? ? } + ? ? } + + ? ? return ret; +} +?/* Assumes the calling function takes care of locking */ ?void
omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state)?{arch/arm/mach-omap2/mux.h +0
-0@@ -225,8 +225,21 @@ omap_hwmod_mux_init(struct omap_device_pad *bpads, int nr_pads);? */
?voidomap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state);
Quoted 10 lines
arch/arm/mach-omap2/mux.h
Quoted 7 lines
arch/arm/mach-omap2/mux.h +7
-0+ +/** +* 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. +*/ Please put the kerneldoc comments in the C file instead of the header.
ok.
Quoted 17 lines
Quoted 17 lines
+bool
omap_hwmod_mux_wakeup(struct omap_hwmod_mux_info *hmux); ?#elsearch/arm/mach-omap2/mux.h +5
-0+static inline bool 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;arch/arm/mach-omap2/omap_hwmod.c +0
-0@@ -2403,3 +2403,16 @@ int omap_hwmod_enable_ioring_wakeup(struct omap_hwmod *oh, bool enable)
Quoted 8 lines
arch/arm/mach-omap2/omap_hwmod.c int omap_hwmod_enable_ioring_wakeup(struct omap_hwmod *oh, bool enable) · line 2408
Quoted 5 lines
arch/arm/mach-omap2/omap_hwmod.c +3
-0? ? ? return ret; ?} + +/** +* omap_hwmod_pad_wakeup_status - get pad wakeup status if mux is available. How about
_get_pad_wakeup_status()
Yes fine will update.
Quoted 5 lines
arch/arm/mach-omap2/omap_hwmod.c int omap_hwmod_enable_ioring_wakeup(struct omap_hwmod *oh, bool enable) · line 2411
Quoted 3 lines
arch/arm/mach-omap2/omap_hwmod.c +3
-0+* @oh: struct omap_hwmod * +* +* Returns the wake_up status bit of available pad mux pin. or on error... ?
-EINVAL. Will update the comments.
Quoted 80 lines
Quoted 26 lines
arch/arm/mach-omap2/omap_hwmod.c +7
-0+*/ +int omap_hmwod_pad_wakeup_status (struct omap_hwmod *oh) +{ + ? ? if (oh->mux) + ? ? ? ? ? ? return omap_hwmod_mux_wakeup(oh->mux); + ? ? return -EINVAL; +}arch/arm/mach-omap2/pm24xx.c +2
-0@@ -137,6 +137,8 @@ static void omap2_enter_full_retention(void) ? ? ? ? ? ? ? ? ? ? ? ? ?OMAP_SDRC_REGADDR(SDRC_DLLA_CTRL), ? ? ? ? ? ? ? ? ? ? ? ? ?OMAP_SDRC_REGADDR(SDRC_POWER)); + ? ? omap_uart_resume_idle(); +?no_sleep:
? ? ? if (omap2_pm_debug) {
? ? ? ? ? ? ? unsigned long long tmp;arch/arm/mach-omap2/pm34xx.c +0
-0arch/arm/mach-omap2/pm34xx.c static int prcm_clear_mod_irqs(s16 module, u8 regs) · line 220
Quoted 5 lines
arch/arm/mach-omap2/pm34xx.c +2
-0@@ -216,6 +216,8 @@ static int prcm_clear_mod_irqs(s16 module, u8 regs) ? ? ? wkst = omap2_prm_read_mod_reg(module, wkst_off); ? ? ? wkst &= omap2_prm_read_mod_reg(module, grpsel_off); + + ? ? c += omap_uart_resume_idle();No...
[...]
Quoted 13 lines
drivers/tty/serial/omap-serial.c +0
-0@@ -43,6 +43,7 @@?#include <
plat/dmtimer.h>
?#include <plat/omap-serial.h>
?#include <plat/omap_device.h>
+#include <plat/serial.h>?static struct
uart_omap_port*ui[OMAP_MAX_HSUART_PORTS];drivers/tty/serial/omap-serial.c static inline void serial_omap_port_enable(struct uart_omap_port *up) · line 112
Quoted 4 lines
drivers/tty/serial/omap-serial.c +1
-0@@ -108,6 +109,27 @@ static inline void serial_omap_port_enable(struct uart_omap_port *up) ? ? ? pm_runtime_get_sync(&up->pdev->dev); ?} +/* TBD: Should be removed once we irq-chaining mechanism in place */ ...indeed...
Quoted 9 lines
drivers/tty/serial/omap-serial.c +9
-0+u32 omap_uart_resume_idle () +{ + ? ? int i; + ? ? u32 ret = 0; + + ? ? for (i = 0; i < OMAP_MAX_HSUART_PORTS; i++) { + ? ? ? ? ? ? struct uart_omap_port *up = ui[i]; + + ? ? ? ? ? ? if (!up)drivers/tty/serial/omap-serial.c static inline void serial_omap_port_enable(struct uart_omap_port *up) · line 131
Quoted 10 lines
drivers/tty/serial/omap-serial.c +10
-0+ ? ? ? ? ? ? ? ? ? ? continue; + + ? ? ? ? ? ? if (up->chk_wakeup(up->pdev)) { + ? ? ? ? ? ? ? ? ? ? serial_omap_port_enable(up); + ? ? ? ? ? ? ? ? ? ? serial_omap_port_disable(up); + ? ? ? ? ? ? ? ? ? ? ret++; + ? ? ? ? ? ? } + ? ? } + ? ? return ret; +}... this is just putting back basically the same thing that was removed in patch 1. ?IOW, this is now being checked for *every* PRCM wakeup, which is no different than having it in the idle path.
Quoted 2 lines
I thought I understood that you had the SW IRQ triggering working, so this part should not be necessary.
Actually I tried few experiments but couldn't get it working.
Tried below but didn't help.
------------------------------------
arch/arm/mach-omap2/pm34xx.c +0 -0
@@ -288,6 +288,16 @@ static irqreturn_t prcm_interrupt_handler (int
irq, void *dev_id)
do {
if (irqstatus_mpu & (OMAP3430_WKUP_ST_MASK |
OMAP3430_IO_ST_MASK)) {
+#if 1
+ /*
+ * EXP-1: SET UART1 SOFT IRQ BIT
+ * 3430 -SDP UART1 console.
+ * M_IRQ_72, INTCPS_ISR_SET
+ * 0x4820 0090 + (0x20 * n)
+ * bit-8 n = 2
+ */
+ __raw_writel(0x100 , 0x482000D0);
+#endif
c = _prcm_int_handle_wakeup();
/*-----------------------------------
Currently we are planning to integrate irq_chaining patches on top uart_runtime patches which is work-in-progress. Will remove resume_idle once we have irq_chaining patches available.
--
Thanks,
Govindraj.R
Quoted 7 lines
Kevin
--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in the body of a message to majordomo at vger.kernel.org
More majordomo info at ?http://vger.kernel.org/majordomo-info.html
PATCH v2 11/12 OMAP: Serial: Use resume call from prcm to enable uart
Govindraj <[email protected]> writes:
[...]
Quoted 9 lines
Quoted 7 lines
... this is just putting back basically the same thing that was removed in patch 1. ?IOW, this is now being checked for *every* PRCM wakeup, which is no different than having it in the idle path.
I thought I understood that you had the SW IRQ triggering working, so this part should not be necessary.
Actually I tried few experiments but couldn't get it working.
What exactly is not working? The interrupt is not firing at all? The
driver's ISR is not being called?
Quoted 26 lines
Tried below but didn't help.
------------------------------------
arch/arm/mach-omap2/pm34xx.c +10
-0@@ -288,6 +288,16 @@ static irqreturn_t prcm_interrupt_handler (int irq, void *dev_id) do { if (irqstatus_mpu & (OMAP3430_WKUP_ST_MASK | OMAP3430_IO_ST_MASK)) { +#if 1 + /* + * EXP-1: SET UART1 SOFT IRQ BIT + * 3430 -SDP UART1 console. + * M_IRQ_72, INTCPS_ISR_SET + * 0x4820 0090 + (0x20 * n) + * bit-8 n = 2 + */ + __raw_writel(0x100 , 0x482000D0); +#endif c = _prcm_int_handle_wakeup();/*
Quoted 5 lines
-----------------------------------
Currently we are planning to integrate
irq_chainingpatches on topuart_runtimepatches which is work-in-progress. Will removeresume_idleonce we haveirq_chainingpatches available.
Well, I'm not OK with $SUBJECT patch as it is since it's just moving an ugly hack from serial.c to the PRCM ISR. If the hack is going to stay, then it should stay where it is until it can be fixed for real.
Kevin
PATCH v2 11/12 OMAP: Serial: Use resume call from prcm to enable uart
Quoted 9 lines · Kevin Hilman
Govindraj <[email protected]> writes:
[...]
Quoted 5 lines
Quoted 5 lines
... this is just putting back basically the same thing that was removed in patch 1. ?IOW, this is now being checked for *every* PRCM wakeup, which is no different than having it in the idle path.
Quoted 8 lines
Quoted 4 lines
Quoted 2 lines
I thought I understood that you had the SW IRQ triggering working, so this part should not be necessary.
Actually I tried few experiments but couldn't get it working.
What exactly is not working? ? The interrupt is not firing at all? ?The driver's ISR is not being called?
It throws a oops as here
Reproduced with below [EXP-1] change + below kernel.
git://gitorious.org/uart_runtime/pm.git
[Has uart runtime patches based on pm-core branch]
Quoted 28 lines
Quoted 28 lines
Tried below but didn't help.
------------------------------------
arch/arm/mach-omap2/pm34xx.c +0
-0@@ -288,6 +288,16 @@ static irqreturn_t prcm_interrupt_handler (int irq, void *dev_id) ? ? ? ? do {? ? ? ? ? ? ? ? if (
irqstatus_mpu& (OMAP3430_WKUP_ST_MASK| ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?OMAP3430_IO_ST_MASK)) {arch/arm/mach-omap2/pm34xx.c +10
-0+#if 1 + ? ? ? ? ? ? ? ? ? ? ? /* + ? ? ? ? ? ? ? ? ? ? ? ?* EXP-1: SET UART1 SOFT IRQ BIT + ? ? ? ? ? ? ? ? ? ? ? ?* 3430 -SDP UART1 console. + ? ? ? ? ? ? ? ? ? ? ? ?* M_IRQ_72, INTCPS_ISR_SET + ? ? ? ? ? ? ? ? ? ? ? ?* 0x4820 0090 + (0x20 * n) + ? ? ? ? ? ? ? ? ? ? ? ?* bit-8 n = 2 + ? ? ? ? ? ? ? ? ? ? ? ?*/ + ? ? ? ? ? ? ? ? ? ? ? __raw_writel(0x100 , 0x482000D0); +#endif ? ? ? ? ? ? ? ? ? ? ? ? c =
_prcm_int_handle_wakeup();? ? ? ? ? ? ? ? ? ? ? ? /*
-----------------------------------
Quoted 7 lines
Quoted 3 lines
Currently we are planning to integrate
irq_chainingpatches on topuart_runtimepatches which is work-in-progress. Will removeresume_idleonce we haveirq_chainingpatches available.Well, I'm not OK with $SUBJECT patch as it is since it's just moving an ugly hack from
serial.cto the PRCM ISR. ?If the hack is going to stay, then it should stay where it is until it can be fixed for real.
Now with runtime changes we are cutting clocks independently whereas prior to this we where cutting clocks only in sram_idle path.
With runtime changes:
1.) Once we cut uart clocks and send a char to uart it directs wakeup_irq to prcm_irq_handler the one way to wakeup uart from there was to check uart mod wakeup status bits if wakeup event occurred then wakeup the particular uart.
2.) Moving this resume back to sram path will break module wakeup after uart clocks are disabled(using put_sync)
Thats the reason I have moved this to prcm_irq path to ensure once auto-suspend happens after inactivity period we have resume_call to wakeup uart port.
--
Thanks,
Govindraj.R
Quoted 3 lines
Kevin
PATCH v2 11/12 OMAP: Serial: Use resume call from prcm to enable uart
Quoted 15 lines · Govindraj
Quoted 14 lines · Kevin Hilman
Govindraj <[email protected]> writes:
[...]
Quoted 9 lines
Quoted 7 lines
... this is just putting back basically the same thing that was removed in patch 1. ?IOW, this is now being checked for *every* PRCM wakeup, which is no different than having it in the idle path.
I thought I understood that you had the SW IRQ triggering working, so this part should not be necessary.
Actually I tried few experiments but couldn't get it working.
Quoted 7 lines
Quoted 3 lines
What exactly is not working? ? The interrupt is not firing at all? ?The driver's ISR is not being called?
It throws a oops as here
This doesn't help understand what exactly is not working. This needs to be debugged further to understand the root cause.
A quick glance at the oops shows a fault when accessing a *physical* address within the INTC. The MMU is enabled here, and HW accesss should be using a virtual address.
Also, early in the boot there are a pile of other errors coming from the clock framework suggesting that this kernel has some other basic problems as well.
Quoted 52 lines
Reproduced with below [EXP-1] change + below kernel.
git://gitorious.org/uart_runtime/pm.git
[Has uart runtime patches based on pm-core branch]Quoted 28 lines
Quoted 28 lines
Tried below but didn't help.
------------------------------------
arch/arm/mach-omap2/pm34xx.c +0
-0@@ -288,6 +288,16 @@ static irqreturn_t prcm_interrupt_handler (int irq, void *dev_id) ? ? ? ? do {? ? ? ? ? ? ? ? if (
irqstatus_mpu& (OMAP3430_WKUP_ST_MASK| ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?OMAP3430_IO_ST_MASK)) {arch/arm/mach-omap2/pm34xx.c +10
-0+#if 1 + ? ? ? ? ? ? ? ? ? ? ? /* + ? ? ? ? ? ? ? ? ? ? ? ?* EXP-1: SET UART1 SOFT IRQ BIT + ? ? ? ? ? ? ? ? ? ? ? ?* 3430 -SDP UART1 console. + ? ? ? ? ? ? ? ? ? ? ? ?* M_IRQ_72, INTCPS_ISR_SET + ? ? ? ? ? ? ? ? ? ? ? ?* 0x4820 0090 + (0x20 * n) + ? ? ? ? ? ? ? ? ? ? ? ?* bit-8 n = 2 + ? ? ? ? ? ? ? ? ? ? ? ?*/ + ? ? ? ? ? ? ? ? ? ? ? __raw_writel(0x100 , 0x482000D0); +#endif ? ? ? ? ? ? ? ? ? ? ? ? c =
_prcm_int_handle_wakeup();? ? ? ? ? ? ? ? ? ? ? ? /*
-----------------------------------
Quoted 7 lines
Quoted 3 lines
Currently we are planning to integrate
irq_chainingpatches on topuart_runtimepatches which is work-in-progress. Will removeresume_idleonce we haveirq_chainingpatches available.Well, I'm not OK with $SUBJECT patch as it is since it's just moving an ugly hack from
serial.cto the PRCM ISR. ?If the hack is going to stay, then it should stay where it is until it can be fixed for real.Now with runtime changes we are cutting clocks independently whereas prior to this we where cutting clocks only in
sram_idlepath.With runtime changes:
1.) Once we cut uart clocks and send a char to uart it directswakeup_irqtoprcm_irq_handlerthe one way to wakeup uart from there was to check uart mod wakeup status bits if wakeup event occurred then wakeup the particular uart.
2.) Moving this resume back to sram path will break module wakeup after uart clocks aredisabled(using put_sync)
Quoted 3 lines
Thats the reason I have moved this to
prcm_irqpath to ensure once auto-suspend happens after inactivity period we haveresume_callto wakeup uart port.
I understand, but the point is that this approach is still the same as the previous hack (check for UART wakeup on *every* wakeup event.)
What is needed is to further investigate using SW triggered IRQs can be done for these wakeup events so we can get away from the above approach all together.
Kevin
PATCH v2 11/12 OMAP: Serial: Use resume call from prcm to enable uart
Quoted 23 lines · Kevin Hilman
Quoted 21 lines · Govindraj
Quoted 9 lines · Kevin Hilman
Govindraj <[email protected]> writes:
[...]
Quoted 5 lines
Quoted 5 lines
... this is just putting back basically the same thing that was removed in patch 1. ?IOW, this is now being checked for *every* PRCM wakeup, which is no different than having it in the idle path.
Quoted 8 lines
Quoted 4 lines
Quoted 2 lines
I thought I understood that you had the SW IRQ triggering working, so this part should not be necessary.
Actually I tried few experiments but couldn't get it working.
What exactly is not working? ? The interrupt is not firing at all? ?The driver's ISR is not being called?
It throws a oops as here
Quoted 8 lines
Quoted 1 line
This doesn't help understand what exactly is not working. ?This needs to be debugged further to understand the root cause.
A quick glance at the oops shows a fault when accessing a *physical* address within the INTC. ?The MMU is enabled here, and HW accesss should be using a virtual address.
Today we could get console_uart booted with irq_patches + uart_runtime shared by Avinash [Irq_chaining + some local hacks, still not clean patches]
But AFAIK looks like still soft irq method is not generic as we dont have any similar mechanism for omap4 so how to keep it consistent.
So Shall we retain resume method until we have a generic approach ?
--
Thanks,
Govindraj.R
Quoted 70 lines
Also, early in the boot there are a pile of other errors coming from the clock framework suggesting that this kernel has some other basic problems as well.
Quoted 52 lines
Reproduced with below [EXP-1] change + below kernel.
git://gitorious.org/uart_runtime/pm.git
[Has uart runtime patches based on pm-core branch]Quoted 28 lines
Quoted 28 lines
Tried below but didn't help.
------------------------------------
arch/arm/mach-omap2/pm34xx.c +0
-0@@ -288,6 +288,16 @@ static irqreturn_t prcm_interrupt_handler (int irq, void *dev_id) ? ? ? ? do {? ? ? ? ? ? ? ? if (
irqstatus_mpu& (OMAP3430_WKUP_ST_MASK| ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?OMAP3430_IO_ST_MASK)) {arch/arm/mach-omap2/pm34xx.c +10
-0+#if 1 + ? ? ? ? ? ? ? ? ? ? ? /* + ? ? ? ? ? ? ? ? ? ? ? ?* EXP-1: SET UART1 SOFT IRQ BIT + ? ? ? ? ? ? ? ? ? ? ? ?* 3430 -SDP UART1 console. + ? ? ? ? ? ? ? ? ? ? ? ?* M_IRQ_72, INTCPS_ISR_SET + ? ? ? ? ? ? ? ? ? ? ? ?* 0x4820 0090 + (0x20 * n) + ? ? ? ? ? ? ? ? ? ? ? ?* bit-8 n = 2 + ? ? ? ? ? ? ? ? ? ? ? ?*/ + ? ? ? ? ? ? ? ? ? ? ? __raw_writel(0x100 , 0x482000D0); +#endif ? ? ? ? ? ? ? ? ? ? ? ? c =
_prcm_int_handle_wakeup();? ? ? ? ? ? ? ? ? ? ? ? /*
-----------------------------------
Quoted 7 lines
Quoted 3 lines
Currently we are planning to integrate
irq_chainingpatches on topuart_runtimepatches which is work-in-progress. Will removeresume_idleonce we haveirq_chainingpatches available.Well, I'm not OK with $SUBJECT patch as it is since it's just moving an ugly hack from
serial.cto the PRCM ISR. ?If the hack is going to stay, then it should stay where it is until it can be fixed for real.Now with runtime changes we are cutting clocks independently whereas prior to this we where cutting clocks only in
sram_idlepath.With runtime changes:
1.) Once we cut uart clocks and send a char to uart it directswakeup_irqtoprcm_irq_handlerthe one way to wakeup uart from there was to check uart mod wakeup status bits if wakeup event occurred then wakeup the particular uart.
2.) Moving this resume back to sram path will break module wakeup after uart clocks aredisabled(using put_sync)Quoted 3 lines
Thats the reason I have moved this to
prcm_irqpath to ensure once auto-suspend happens after inactivity period we haveresume_callto wakeup uart port.I understand, but the point is that this approach is still the same as the previous hack (check for UART wakeup on *every* wakeup event.)
What is needed is to further investigate using SW triggered IRQs can be done for these wakeup events so we can get away from the above approach all together.
Kevin
PATCH v2 12/12 OMAP2: Serial: Add no async wake flag.
In reply to Govindraj.RFor omap2 cpu_idle thread will not be available and uart_clock cutting happens only in suspend path.
Prior to this patch the uart_clock was cut using prepare/resume calls since these funcs are no more available with runtime changes use no_async_wake flag to keep clock active during bootup otherwise uart port will disabled during boot-up and cannot be enabled back.
Also based on this flag we can disable uart port during suspend and enable back during resume.
--- arch/arm/mach-omap2/serial.c | 7 +++++++ arch/arm/plat-omap/include/plat/omap-serial.h | 3 +++ drivers/tty/serial/omap-serial.c | 14 ++++++++++++++ 3 files changed, 24 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/serial.c +7 -0
@@ -245,6 +245,12 @@ static void omap_uart_wakeup_enable(struct platform_device *pdev, bool enable)static void omap_uart_idle_init (struct omap_uart_port_info *uart,unsigned short num) { +/* On omap2 no cpu_idle and async wakeup from prcm_module. +* This flag can be used to cut clocks only in suspend path. +* to avoid boot break due to aggressive clock cutting from +* omap-serial driver. +*/ + uart->no_async_wake = true;if (cpu_is_omap34xx ()) {u32 mod = num >1 ?OMAP3430_PER_MOD :CORE_MOD ;u32 wk_mask =0 ;
@@ -266,6 +272,7 @@ static void omap_uart_idle_init(struct omap_uart_port_info *uart,break ; } uart->wk_mask = wk_mask; + uart->no_async_wake = false; }else if (cpu_is_omap24xx ()) {u32 wk_mask =0 ;u32 wk_en =PM_WKEN1 , wk_st =PM_WKST1 ;
arch/arm/plat-omap/include/plat/omap-serial.h +3 -0
@@ -79,6 +79,7 @@ struct omap_uart_port_info {void __iomem *wk_st;void __iomem *wk_en;u32 wk_mask; +bool no_async_wake; };struct uart_omap_dma {
@@ -134,6 +135,8 @@ struct uart_omap_port {unsigned int errata;void (*enable_wakeup)(struct platform_device *,bool );bool (*chk_wakeup)(struct platform_device *); + + bool no_async_wake; };#endif /* __OMAP_SERIAL_H__ */
drivers/tty/serial/omap-serial.c +14 -0
@@ -1168,6 +1168,13 @@ static int serial_omap_suspend(struct device *dev)uart_suspend_port (&serial_omap_reg, &up->port);console_trylock ();serial_omap_pm (&up->port,3 ,0 ); + +/* OMAP2 dont have cpu_idle thread and async wakeup from prcm. +* For such socs clocks will be kept active from probe and +* cut only in suspend path. +*/ +if (up->no_async_wake) +serial_omap_port_disable (up); }return 0 ; }
@@ -1179,6 +1186,9 @@ static int serial_omap_resume(struct device *dev)if (up) {uart_resume_port (&serial_omap_reg, &up->port);console_unlock (); + +if (up->no_async_wake) +serial_omap_port_enable (up); }return 0 ;
@@ -1402,6 +1412,7 @@ static int serial_omap_probe(struct platform_device *pdev) up->errata = omap_up_info->errata; up->enable_wakeup = omap_up_info->enable_wakeup; up->chk_wakeup = omap_up_info->chk_wakeup; + up->no_async_wake = omap_up_info->no_async_wake;if (omap_up_info->dma_enabled) { up->uart_dma.uart_dma_tx = dma_tx->start;
@@ -1430,6 +1441,9 @@ static int serial_omap_probe(struct platform_device *pdev)serial_omap_port_disable (up); } +if (up->no_async_wake) +serial_omap_port_enable (up); + ui[pdev->id] = up;serial_omap_add_console_port (up);
Signature · 1 line
1.7.1
PATCH v2 12/12 OMAP2: Serial: Add no async wake flag.
Quoted 1 line · Govindraj.R
For omap2
cpu_idlethread will not be available
Why not?
Quoted 1 line
and
uart_clockcutting happens only in suspend path.
Aren't clocks also cut after runtime PM autosuspend?
Quoted 5 lines
Prior to this patch the
uart_clockwas cut using prepare/resume calls since these funcs are no more available with runtime changes useno_async_wakeflag to keep clock active during bootup otherwise uart port will disabled during boot-up and cannot be enabled back.
This doesn't just keep clock active during bootup, but it keeps clock active always, except during suspend.
Quoted 2 lines
Also based on this flag we can disable uart port during suspend and enable back during resume.
I think disabling UART port during suspend should already be part of an earlier patch. This patch should then only make it conditional.
Quoted 12 lines
Signed-off-by Govindraj.R <[email protected]>--- arch/arm/mach-omap2/serial.c | 7 +++++++ arch/arm/plat-omap/include/plat/omap-serial.h | 3 +++ drivers/tty/serial/omap-serial.c | 14 ++++++++++++++ 3 files changed, 24 insertions(+), 0 deletions(-)arch/arm/mach-omap2/serial.c +0
-0
arch/arm/mach-omap2/serial.c static void omap_uart_wakeup_enable(struct platform_device *pdev, bool enable) · line 248
Quoted 4 lines
arch/arm/mach-omap2/serial.c +1
-0@@ -245,6 +245,12 @@ static void omap_uart_wakeup_enable(struct platform_device *pdev, bool enable)static void omap_uart_idle_init (struct omap_uart_port_info *uart,unsigned short num) { +/* On omap2 no cpu_idle and async wakeup from prcm_module.
Please remove comments about CPU idle, as the need for this has nothing to do with CPU idle.
arch/arm/mach-omap2/serial.c static void omap_uart_wakeup_enable(struct platform_device *pdev, bool enable) · line 252
Quoted 4 lines
arch/arm/mach-omap2/serial.c +4
-0+* This flag can be used to cut clocks only in suspend path. +* to avoid boot break due to aggressive clock cutting from +* omap-serial driver. +*/
fix multi-line comment style throughout
arch/arm/mach-omap2/serial.c static void omap_uart_wakeup_enable(struct platform_device *pdev, bool enable) · line 253
Quoted 1 line
arch/arm/mach-omap2/serial.c +1
-0+ uart->no_async_wake = true;
If needed (which I still don't think I understand), for readability sake this flag should be called 'has_async_wake', and default to false. It should then be set to true on available SoCs.
Kevin
Quoted 77 lines
arch/arm/mach-omap2/serial.c +1
-0if (cpu_is_omap34xx ()) {u32 mod = num >1 ?OMAP3430_PER_MOD :CORE_MOD ;u32 wk_mask =0 ;@@ -266,6 +272,7 @@ static void omap_uart_idle_init(struct omap_uart_port_info *uart,break ; } uart->wk_mask = wk_mask; + uart->no_async_wake = false; }else if (cpu_is_omap24xx ()) {u32 wk_mask =0 ;u32 wk_en =PM_WKEN1 , wk_st =PM_WKST1 ;arch/arm/plat-omap/include/plat/omap-serial.h +3
-0@@ -79,6 +79,7 @@ struct omap_uart_port_info {void __iomem *wk_st;void __iomem *wk_en;u32 wk_mask; +bool no_async_wake; };struct uart_omap_dma {@@ -134,6 +135,8 @@ struct uart_omap_port {unsigned int errata;void (*enable_wakeup)(struct platform_device *,bool );bool (*chk_wakeup)(struct platform_device *); + + bool no_async_wake; };#endif /* __OMAP_SERIAL_H__ */ drivers/tty/serial/omap-serial.c +14
-0@@ -1168,6 +1168,13 @@ static int serial_omap_suspend(struct device *dev)uart_suspend_port (&serial_omap_reg, &up->port);console_trylock ();serial_omap_pm (&up->port,3 ,0 ); + +/* OMAP2 dont have cpu_idle thread and async wakeup from prcm. +* For such socs clocks will be kept active from probe and +* cut only in suspend path. +*/ +if (up->no_async_wake) +serial_omap_port_disable (up); }return 0 ; }@@ -1179,6 +1186,9 @@ static int serial_omap_resume(struct device *dev)if (up) {uart_resume_port (&serial_omap_reg, &up->port);console_unlock (); + +if (up->no_async_wake) +serial_omap_port_enable (up); }return 0 ;@@ -1402,6 +1412,7 @@ static int serial_omap_probe(struct platform_device *pdev) up->errata = omap_up_info->errata; up->enable_wakeup = omap_up_info->enable_wakeup; up->chk_wakeup = omap_up_info->chk_wakeup; + up->no_async_wake = omap_up_info->no_async_wake;if (omap_up_info->dma_enabled) { up->uart_dma.uart_dma_tx = dma_tx->start;@@ -1430,6 +1441,9 @@ static int serial_omap_probe(struct platform_device *pdev)serial_omap_port_disable (up); } +if (up->no_async_wake) +serial_omap_port_enable (up); + ui[pdev->id] = up;serial_omap_add_console_port (up);
PATCH v2 12/12 OMAP2: Serial: Add no async wake flag.
Quoted 50 lines · Kevin Hilman
Quoted 1 line · Govindraj.R
For omap2
cpu_idlethread will not be availableWhy not?
Quoted 1 line
and
uart_clockcutting happens only in suspend path.Aren't clocks also cut after runtime PM autosuspend?
Quoted 5 lines
Prior to this patch the
uart_clockwas cut using prepare/resume calls since these funcs are no more available with runtime changes useno_async_wakeflag to keep clock active during bootup otherwise uart port will disabled during boot-up and cannot be enabled back.This doesn't just keep clock active during bootup, but it keeps clock active always, except during suspend.
Quoted 2 lines
Also based on this flag we can disable uart port during suspend and enable back during resume.
I think disabling UART port during suspend should already be part of an earlier patch. ?This patch should then only make it conditional.
Quoted 12 lines
Signed-off-by Govindraj.R <[email protected]>---
?arch/arm/mach-omap2/serial.c ? ? ? ? ? ? ? ? ?| ? ?7 +++++++ ?arch/arm/plat-omap/include/plat/omap-serial.h | ? ?3 +++ ?drivers/tty/serial/omap-serial.c ? ? ? ? ? ? ?| ? 14 ++++++++++++++?3 files changed, 24 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/serial.c +0
-0arch/arm/mach-omap2/serial.c static void omap_uart_wakeup_enable(struct platform_device *pdev, bool enable) · line 248
Quoted 4 lines
arch/arm/mach-omap2/serial.c +1
-0@@ -245,6 +245,12 @@ static void omap_uart_wakeup_enable(struct platform_device *pdev, bool enable) ?static void omap_uart_idle_init(struct omap_uart_port_info *uart, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? unsigned short num) ?{ + ? ? /* On omap2 no cpu_idle and async wakeup from prcm_module.Please remove comments about CPU idle, as the need for this has nothing to do with CPU idle.
arch/arm/mach-omap2/serial.c static void omap_uart_wakeup_enable(struct platform_device *pdev, bool enable) · line 252
Quoted 4 lines
arch/arm/mach-omap2/serial.c +4
-0+? ? ?* This flag can be used to cut clocks only in suspend path. +? ? ?* to avoid boot break due to aggressive clock cutting from +? ? ?* omap-serial driver. +? ? ?*/
Quoted 5 lines
fix multi-line comment style throughout
arch/arm/mach-omap2/serial.c static void omap_uart_wakeup_enable(struct platform_device *pdev, bool enable) · line 253
Quoted 1 line
arch/arm/mach-omap2/serial.c +1
-0+ ? ? uart->no_async_wake = true;If needed (which I still don't think I understand),
Looking into the pm24xx.c code what I understood is..
(1) omap2_enter_full_retention was cutting and enabling the uart clocks back whether in idle patch or in suspend path.
(2) since we cut clocks outside this retention path I don't know how to wake back uart as don't see any irq_handlers servicing wake-up events in pm24xx.c
[Correct me if I am missing something here.]
(3) Since there was no async wakeup mechanism I could see on pm24xx.c so one approach was to use of these flags. [If I cut clocks during boot using put_sync in uart code since no wakeup mechanism will break boot]
(4) For socs with no aync wakeup we are keeping clocks active from probe and disabling/enabling clocks in suspend/resume hooks.
Quoted 3 lines
for readability sake
this flag should be called 'has_async_wake', and default to false. ?It should then be set to true on available SoCs.
Yes sure I can rename the flag and use above approach.
--
Thanks,
Govindraj.R
Quoted 85 lines
Kevin
Quoted 69 lines
arch/arm/mach-omap2/serial.c +1
-0? ? ? if (cpu_is_omap34xx()) { ? ? ? ? ? ? ? u32 mod = num > 1 ? OMAP3430_PER_MOD : CORE_MOD; ? ? ? ? ? ? ? u32 wk_mask = 0;@@ -266,6 +272,7 @@ static void omap_uart_idle_init(struct omap_uart_port_info *uart, ? ? ? ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? ? } ? ? ? ? ? ? ? uart->wk_mask = wk_mask; + ? ? ? ? ? ? uart->no_async_wake = false; ? ? ? } else if (cpu_is_omap24xx()) { ? ? ? ? ? ? ? u32 wk_mask = 0; ? ? ? ? ? ? ? u32 wk_en = PM_WKEN1, wk_st = PM_WKST1;arch/arm/plat-omap/include/plat/omap-serial.h +3
-0@@ -79,6 +79,7 @@ struct omap_uart_port_info { ? ? ? void __iomem *wk_st; ? ? ? void __iomem *wk_en; ? ? ? u32 wk_mask; + ? ? bool ? ? ? ? ? ? ? ? ? ?no_async_wake; ?}; ?struct uart_omap_dma {@@ -134,6 +135,8 @@ struct uart_omap_port { ? ? ? unsigned int ? ? ? ? ? ?errata; ? ? ? void (*enable_wakeup)(struct platform_device *, bool); ? ? ? bool (*chk_wakeup)(struct platform_device *); + + ? ? bool ? ? ? ? ? ? ? ? ? ?no_async_wake; ?};?#endif /*
__OMAP_SERIAL_H__*/drivers/tty/serial/omap-serial.c +11
-0@@ -1168,6 +1168,13 @@ static int serial_omap_suspend(struct device *dev) ? ? ? ? ? ? ? uart_suspend_port(&serial_omap_reg, &up->port); ? ? ? ? ? ? ? console_trylock(); ? ? ? ? ? ? ? serial_omap_pm(&up->port, 3, 0); + + ? ? ? ? ? ? /* OMAP2 dont have cpu_idle thread and async wakeup from prcm. + ? ? ? ? ? ? ?* For such socs clocks will be kept active from probe and + ? ? ? ? ? ? ?* cut only in suspend path. + ? ? ? ? ? ? ?*/ + ? ? ? ? ? ? if (up->no_async_wake) + ? ? ? ? ? ? ? ? ? ? serial_omap_port_disable(up); ? ? ? } ? ? ? return 0; ?}@@ -1179,6 +1186,9 @@ static int serial_omap_resume(struct device *dev) ? ? ? if (up) { ? ? ? ? ? ? ? uart_resume_port(&serial_omap_reg, &up->port); ? ? ? ? ? ? ? console_unlock(); + + ? ? ? ? ? ? if (up->no_async_wake) + ? ? ? ? ? ? ? ? ? ? serial_omap_port_enable(up); ? ? ? } ? ? ? return 0;@@ -1402,6 +1412,7 @@ static int serial_omap_probe(struct platform_device *pdev) ? ? ? up->errata = omap_up_info->errata; ? ? ? up->enable_wakeup = omap_up_info->enable_wakeup; ? ? ? up->chk_wakeup = omap_up_info->chk_wakeup; + ? ? up->no_async_wake = omap_up_info->no_async_wake; ? ? ? if (omap_up_info->dma_enabled) { ? ? ? ? ? ? ? up->uart_dma.uart_dma_tx = dma_tx->start;drivers/tty/serial/omap-serial.c static int serial_omap_probe(struct platform_device *pdev) · line 1448
Quoted 8 lines
drivers/tty/serial/omap-serial.c +3
-0@@ -1430,6 +1441,9 @@ static int serial_omap_probe(struct platform_device *pdev) ? ? ? ? ? ? ? serial_omap_port_disable(up); ? ? ? } + ? ? if (up->no_async_wake) + ? ? ? ? ? ? serial_omap_port_enable(up); + ? ? ? ui[pdev->id] = up; ? ? ? serial_omap_add_console_port(up);--
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