diff options
| -rw-r--r-- | arch/arm/boot/dts/omap3_h1.dts | 10 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/board-omap3h1-bluetooth.c | 83 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/board-omap3h1.c | 21 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/board-omap3h1.h | 2 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/serial.c | 3 | ||||
| -rw-r--r-- | drivers/base/power/runtime.c | 2 | ||||
| -rw-r--r-- | drivers/tty/serial/omap-serial.c | 91 | ||||
| -rw-r--r-- | include/linux/platform_data/serial-omap.h | 5 | ||||
| -rw-r--r-- | include/linux/serial_core.h | 2 | 
9 files changed, 166 insertions, 53 deletions
| diff --git a/arch/arm/boot/dts/omap3_h1.dts b/arch/arm/boot/dts/omap3_h1.dts index 090cd6f4362..b83d1bdb0bd 100644 --- a/arch/arm/boot/dts/omap3_h1.dts +++ b/arch/arm/boot/dts/omap3_h1.dts @@ -75,8 +75,8 @@  		/* listed below will be reported as the wakeup reason */  		/*                                                    */  		/*             off  IRQ handle                        */ -		ti,pad_irq = <0x150  88  1>, /* uart1 - BT input      */ -                     <0x9f6  143 1>, /* mpu6515 irq pin - is this offset correct?      */ +		ti,pad_irq = <0x150  88  1>, /* 72 + 16, uart1 - BT input */ +                     <0x9f6  143 1>, /* mpu6515 irq pin - is this offset correct? */                       <0x9f4  123 1>, /* BT host wake          */                       <0x1b0  23  1>; /* sys_nirq              */  	}; @@ -147,7 +147,7 @@  			0x19c 0x118	/* MCSPI1_SOMI, MODE0 | INPUT_PULLUP */  			0x1a0 0x000	/* MCSPI1_CS1, MODE0 | OUTPUT */ -                        /* CKE pin for memory */ +            /* CKE pin for memory */              0x232 0x000	/* SDRC_CKE0, MODE0 | OUTPUT */              0x234 0x000	/* SDRC_CKE1, MODE0 | OUTPUT */ @@ -193,14 +193,14 @@                                       OMAP_PIN_OFF_WAKEUPENABLE */              0x14c 0x000     /* UART1, BT, TX  */ -            0x14e 0x000     /* UART1, BT, RTS - E00 = output high off */ +            0x14e 0xA00     /* UART1, BT, RTS - A00 = output off high, this one is active low! */              0x150 0x4100    /* UART1, BT, CTS */              0x152 0x100     /* UART1, BT, RX  */              /* BT_WAKE_GPIO - for waking up BT */              /* OMAP_OFF_ENABLE, OMAP_OFF_PULL_EN, OMAP_OFF_OUTENABLE for sleep modes. */               /* Now set this to regular old output .. also off enable, output low. (0x600) */ -            0x0da 0x604 /* 0x1604 */ /* DSS_DATA23, (IDIS | PI | M4 ) */ +            0x0da 0x004 /* 0x1604 */ /* DSS_DATA23, (IDIS | PI | M4 ) */  	    >;  	}; diff --git a/arch/arm/mach-omap2/board-omap3h1-bluetooth.c b/arch/arm/mach-omap2/board-omap3h1-bluetooth.c index a56ae4e4bd5..2d502bab5a6 100644 --- a/arch/arm/mach-omap2/board-omap3h1-bluetooth.c +++ b/arch/arm/mach-omap2/board-omap3h1-bluetooth.c @@ -41,6 +41,10 @@  #include "board-omap3h1.h"  #include <linux/regulator/driver.h> +#include "asm/io.h" +#include "mux.h" +#include "iomap.h" +  static void set_host_wake_locked(int);  #define BT_RESET_GPIO 179 @@ -48,6 +52,7 @@ static void set_host_wake_locked(int);  #define BT_WAKE_GPIO 93  #define BT_HOST_WAKE_GPIO 11  #define UART_PORT 0  /* UART 1 = 0 */ +#define BT_RST_PIN 149  #define olio_debug(format, ...) printk ("OLIO %s: ", __FUNCTION__); printk (format, ##__VA_ARGS__) @@ -79,12 +84,49 @@ static struct bcm_bt_lpm {  	char bcm_wake_lock_name[100];  } bt_lpm; +static int wake_mode_calls = 0; + +/*************************************************************************** + * rts_enter_sleep_mode - set RTS pin to off mode + *  + * The RTS pin needs to be kept high while sleeping.  + */ + +void rts_enter_sleep_mode() +{ +  if (wake_mode_calls == 0) +    __raw_writew ((u16) ( 1 << 8 | 1 << 4 | 1 << 3 | 4 ),  +                  (volatile void *) OMAP2_L4_IO_ADDRESS(OMAP3_CONTROL_PADCONF_MUX_PBASE) +  +                  OMAP3_CONTROL_PADCONF_UART1_RTS_OFFSET);      + +  /* Now this is a GPIO pin. Send to sleep. */ +   +  return; +} + +/*************************************************************************** + * rts_exit_sleep_mode - set RTS pin to on mode + *  + * The RTS pin needs to be kept high while sleeping, otherwise let the  + * driver decide. + */ + +void rts_exit_sleep_mode() +{ +  if (wake_mode_calls == 0) +    __raw_writew ((u16) ( 0x0 ), +                  (volatile void *) OMAP2_L4_IO_ADDRESS(OMAP3_CONTROL_PADCONF_MUX_PBASE) +  +                  OMAP3_CONTROL_PADCONF_UART1_RTS_OFFSET); + +  return; +} +  static int bcm20702_bt_rfkill_set_power(void *data, bool blocked)  {      // rfkill_ops callback. Turn transmitter on when blocked is false  	if (!blocked) {  		if (clk32ksys_reg && !bt_enabled) -			regulator_enable(clk32ksys_reg); +          (void) regulator_enable(clk32ksys_reg);          gpio_set_value(BT_RESET_GPIO, 1);  		gpio_set_value(BT_REG_GPIO, 1); @@ -123,10 +165,6 @@ static void set_wake_locked(int wake)          olio_debug ("Now locking wake lock\n");          wake_lock (&bt_lpm.bcm_wake_lock); -        /* Does this even make sense here? We've already using the port,  -           doesn't that mean that we're */ -            -          if (!wake_uart_enabled)               omap_serial_ext_uart_enable(UART_PORT);      } @@ -190,11 +228,13 @@ static void set_host_wake_locked(int host_wake)  	if (host_wake) {          olio_debug ("host_wake is set, taking wake lock\n");          wake_lock(&bt_lpm.host_wake_lock); - +         		if (!host_wake_uart_enabled) {  			omap_serial_ext_uart_enable(UART_PORT); -		} +         } +  	} else  { +  		if (host_wake_uart_enabled) {  			omap_serial_ext_uart_disable(UART_PORT);  		} @@ -400,35 +440,6 @@ static int bcm20702_bluetooth_remove(struct platform_device *pdev)  	return 0;  } -int bcm4430_bluetooth_suspend(struct platform_device *pdev, pm_message_t state) -{ -	int irq = gpio_to_irq(BT_HOST_WAKE_GPIO); -	int host_wake; - -	disable_irq(irq); - -	host_wake = gpio_get_value(BT_HOST_WAKE_GPIO);  - -	if (host_wake) { -		enable_irq(irq); -		return -EBUSY; -	} - -	return 0; -} - -int bcm4430_bluetooth_resume(struct platform_device *pdev) -{ -	int irq = gpio_to_irq(BT_HOST_WAKE_GPIO); -	enable_irq(irq); -	return 0; -} - -/*  -	.suspend = bcm4430_bluetooth_suspend, -	.resume = bcm4430_bluetooth_resume, -*/ -  static struct platform_driver bcm20702_bluetooth_platform_driver = {  	.probe = bcm20702_bluetooth_probe,  	.remove = bcm20702_bluetooth_remove, diff --git a/arch/arm/mach-omap2/board-omap3h1.c b/arch/arm/mach-omap2/board-omap3h1.c index 063b3851b4e..071af9b51c3 100644 --- a/arch/arm/mach-omap2/board-omap3h1.c +++ b/arch/arm/mach-omap2/board-omap3h1.c @@ -315,8 +315,12 @@ static struct i2c_board_info __initdata omap3h1_i2c3_board_info[] = {  		.dma_rx_buf_size = DEFAULT_RXDMA_BUFSIZE,  		.dma_rx_poll_rate = DEFAULT_RXDMA_POLLRATE,  		.dma_rx_timeout = DEFAULT_RXDMA_TIMEOUT, +        This one sets runtime pm autosuspend timeout - -1 disables runtime +        pm (that is, pm that's done while running, not sleeping).  		.autosuspend_timeout = DEFAULT_AUTOSUSPEND_DELAY, ( -1 or X ms. ) +        Wakelock timeout: If there's an interrupt on the serial port, this is  +        how long we expect to wait before the system is functional.          .wakelock_timeout - for minnow, this is 150 (BT) or 50 (M4 debug).                Can be left out. @@ -329,6 +333,8 @@ static struct i2c_board_info __initdata omap3h1_i2c3_board_info[] = {          bool			open_close_pm; - Minnow uses this for c55 only          unsigned int	rx_trig;  Minnow, BT & debug only + +        The flags field is not used (it's hardcoded in omap_serial_init_port).  */  static struct omap_uart_port_info omap_uart_ports[] = { @@ -342,6 +348,12 @@ static struct omap_uart_port_info omap_uart_ports[] = {          .wake_peer = bcm_bt_lpm_exit_lpm_locked,          .wakeup_capable = true,          .rx_trig = 32, +         +        /* OLIO: make sure RTS isn't enabled before we're ready */ + +        .rts_wait    = true, +        .rts_enable_fn  = rts_exit_sleep_mode, +        .rts_disable_fn = rts_enter_sleep_mode,      },      {          .dma_enabled = false,	/* To specify DMA Mode */ @@ -350,6 +362,9 @@ static struct omap_uart_port_info omap_uart_ports[] = {          .dma_rx_poll_rate = DEFAULT_RXDMA_POLLRATE,          .autosuspend_timeout = 0,          .wakeup_capable = false, +        .rts_wait = false, +        .rts_enable_fn = NULL, +        .rts_disable_fn = NULL,      },      {          .dma_enabled = false,	/* To specify DMA Mode */ @@ -358,6 +373,9 @@ static struct omap_uart_port_info omap_uart_ports[] = {          .dma_rx_poll_rate = DEFAULT_RXDMA_POLLRATE,          .autosuspend_timeout = -1,          .wakeup_capable = true, +        .rts_wait = false, +        .rts_enable_fn = NULL, +        .rts_disable_fn = NULL,      },      {          .dma_enabled = false,	/* To specify DMA Mode */ @@ -366,6 +384,9 @@ static struct omap_uart_port_info omap_uart_ports[] = {          .dma_rx_poll_rate = DEFAULT_RXDMA_POLLRATE,          .autosuspend_timeout = 0,          .wakeup_capable = false, +        .rts_wait = false, +        .rts_enable_fn = NULL, +        .rts_disable_fn = NULL,      },  }; diff --git a/arch/arm/mach-omap2/board-omap3h1.h b/arch/arm/mach-omap2/board-omap3h1.h index 343eaeaaf86..ddf95f41fa4 100644 --- a/arch/arm/mach-omap2/board-omap3h1.h +++ b/arch/arm/mach-omap2/board-omap3h1.h @@ -26,5 +26,7 @@  #include <linux/serial_core.h>  extern void bcm_bt_lpm_exit_lpm_locked(struct uart_port *uport); +extern void rts_exit_sleep_mode (void); +extern void rts_enter_sleep_mode (void);  #endif /*  __BOARD_OMAP3H1_H__  */ diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c index b1f3fb1d396..a605fe9a9a2 100644 --- a/arch/arm/mach-omap2/serial.c +++ b/arch/arm/mach-omap2/serial.c @@ -305,6 +305,9 @@ void __init omap_serial_init_port(struct omap_board_data *bdata,  	omap_up.DTR_gpio = info->DTR_gpio;  	omap_up.DTR_inverted = info->DTR_inverted;  	omap_up.DTR_present = info->DTR_present; +    omap_up.rts_enable_fn = info->rts_enable_fn; +    omap_up.rts_disable_fn = info->rts_disable_fn; +    omap_up.rts_wait = info->rts_wait;  	pdata = &omap_up;  	pdata_size = sizeof(struct omap_uart_port_info); diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index f8bc937728b..ebbbdca1ee4 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -958,7 +958,7 @@ int __pm_runtime_resume(struct device *dev, int rpmflags)  	spin_lock_irqsave(&dev->power.lock, flags);  	retval = rpm_resume(dev, rpmflags); -    BUG_ON (dev == NULL); /* OLIO: I get weird crashes here */ +    BUG_ON (dev == NULL);  	spin_unlock_irqrestore(&dev->power.lock, flags);  	return retval; diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 9b19ae172c3..a9c37ae9b2a 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -180,6 +180,8 @@ struct uart_omap_port {  	unsigned int		rx_trig;  	int			wakelock_timeout;  	int (*get_context_loss_count)(struct device *); + +    bool rts_wait;  };  #define to_uart_omap_port(p)	((container_of((p), struct uart_omap_port, port))) @@ -1115,8 +1117,41 @@ static void serial_omap_wake_peer(struct uart_port *port)         struct omap_uart_port_info *pdata = up->dev->platform_data;         if (pdata->wake_peer) -               pdata->wake_peer(port); +           pdata->wake_peer(port); +} + +static void serial_omap_rts_enable(struct uart_port *port) +{ +    struct uart_omap_port *up; +    struct omap_uart_port_info *pdata; + +    up = to_uart_omap_port(port); + +    if ((up != NULL) && (up->dev != NULL) && (up->dev->platform_data != NULL)) { +        pdata = up->dev->platform_data; + +        if (pdata->rts_enable_fn) { +            pdata->rts_enable_fn(); +        } +    } +} + +static void serial_omap_rts_disable(struct uart_port *port) +{ +    struct uart_omap_port *up; + +    up = to_uart_omap_port(port); + +    if ((up != NULL) && (up->dev != NULL) && (up->dev->platform_data != NULL)) { +        struct omap_uart_port_info *pdata = up->dev->platform_data; + +        if (pdata->rts_disable_fn) { +            pdata->rts_disable_fn(); +        } +    }  } + +  static void serial_omap_release_port(struct uart_port *port)  {  	dev_dbg(port->dev, "serial_omap_release_port+\n"); @@ -1348,12 +1383,14 @@ static struct uart_ops serial_omap_pops = {  	.shutdown	= serial_omap_shutdown,  	.set_termios	= serial_omap_set_termios,  	.pm		= serial_omap_pm, -	.wake_peer 	= serial_omap_wake_peer,  	.type		= serial_omap_type,  	.release_port	= serial_omap_release_port,  	.request_port	= serial_omap_request_port,  	.config_port	= serial_omap_config_port,  	.verify_port	= serial_omap_verify_port, +	.wake_peer 	    = serial_omap_wake_peer, +    .rts_enable     = serial_omap_rts_enable, +    .rts_disable    = serial_omap_rts_disable,  #ifdef CONFIG_CONSOLE_POLL  	.poll_put_char  = serial_omap_poll_put_char,  	.poll_get_char  = serial_omap_poll_get_char, @@ -1364,7 +1401,7 @@ static struct uart_driver serial_omap_reg = {  	.owner		= THIS_MODULE,  	.driver_name	= "OMAP-SERIAL",  	.dev_name	= OMAP_SERIAL_NAME, -	.nr		= OMAP_MAX_HSUART_PORTS, +	.nr	    	= OMAP_MAX_HSUART_PORTS,  	.cons		= OMAP_CONSOLE,  }; @@ -1372,9 +1409,17 @@ static struct uart_driver serial_omap_reg = {  static int serial_omap_prepare(struct device *dev)  {  	struct uart_omap_port *up = dev_get_drvdata(dev); +	unsigned long flags;  	up->is_suspending = true; +    if (up->rts_wait) { +        spin_lock_irqsave(&up->delayed_rts_lock, flags); +        up->port.ops->rts_disable(&(up->port)); +        up->need_delayed_rts = 1; +        spin_unlock_irqrestore(&up->delayed_rts_lock, flags); +    } +  	return 0;  } @@ -1389,6 +1434,12 @@ static void serial_omap_complete(struct device *dev)  		up->need_delayed_rts = 0;  	} +    /* OLIO: We're not using pinctrl, but we still need rts delayed */ +    else if (up->need_delayed_rts) { +        up->port.ops->rts_enable(&(up->port)); +		up->need_delayed_rts = 0; +    } +  	up->is_suspending = false;  	spin_unlock_irqrestore(&up->delayed_rts_lock, flags);  } @@ -1412,7 +1463,7 @@ static int serial_omap_resume(struct device *dev)  }  #else  #define serial_omap_prepare NULL -#define serial_omap_prepare NULL +#define serial_omap_complete NULL  #endif /* CONFIG_PM_SLEEP */  static void omap_serial_fill_features_erratas(struct uart_omap_port *up) @@ -1618,6 +1669,10 @@ static int serial_omap_probe(struct platform_device *pdev)  		goto err_ioremap;  	} +    /* OLIO */ +    if (omap_up_info->rts_wait) +      up->rts_wait = omap_up_info->rts_wait; +  	up->rx_trig = omap_up_info->rx_trig;  	up->port.flags = omap_up_info->flags;  	up->port.uartclk = omap_up_info->uartclk; @@ -1781,6 +1836,15 @@ static int serial_omap_runtime_suspend(struct device *dev)  		up->need_delayed_rts = 0;  		spin_unlock_irqrestore(&up->delayed_rts_lock, flags);  	} + +    /* OLIO */ +    else if (up->rts_wait) { +      spin_lock_irqsave(&up->delayed_rts_lock, flags); +      up->port.ops->rts_disable(&(up->port)); +      up->need_delayed_rts = 0; +      spin_unlock_irqrestore(&up->delayed_rts_lock, flags); +    } +  	up->context_loss_cnt = serial_omap_get_context_loss_count(up);  	if (device_may_wakeup(dev)) { @@ -1810,13 +1874,20 @@ static int serial_omap_runtime_resume(struct device *dev)  	}  	up->latency = up->calc_latency;  	serial_omap_uart_qos(up); -	if (up->pin_default && up->pin_idle) { -		if (up->is_suspending) -			up->need_delayed_rts = 1; -		else -			pinctrl_select_state(up->pins, up->pin_default); -	} +    if (up->pin_default && up->pin_idle) { +        if (up->is_suspending) +            up->need_delayed_rts = 1; +        else +            pinctrl_select_state(up->pins, up->pin_default); +    } +    else if (up->rts_wait) { +        if (up->is_suspending) +            up->need_delayed_rts = 1; +        else { +            up->port.ops->rts_enable(&(up->port)); +        } +    }  	return 0;  }  #endif diff --git a/include/linux/platform_data/serial-omap.h b/include/linux/platform_data/serial-omap.h index 9990f7cd03c..b430bbc3093 100644 --- a/include/linux/platform_data/serial-omap.h +++ b/include/linux/platform_data/serial-omap.h @@ -45,10 +45,13 @@ struct omap_uart_port_info {  	bool			wakeup_capable;  	bool			open_close_pm;  	unsigned int		rx_trig; +    bool        rts_wait;  	int (*get_context_loss_count)(struct device *);  	void (*enable_wakeup)(struct device *, bool); -	void (*wake_peer)(struct uart_port *); +    void (*wake_peer)(struct uart_port *); +	void (*rts_enable_fn)(void); +	void (*rts_disable_fn)(void);  };  extern void omap_uart_remove_wakeup(struct device *dev); diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 8148bc7d0a8..20920ee1b19 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -68,6 +68,8 @@ struct uart_ops {  			      unsigned int oldstate);  	int		(*set_wake)(struct uart_port *, unsigned int state);  	void		(*wake_peer)(struct uart_port *); +    void        (*rts_enable)(struct uart_port *); +    void        (*rts_disable)(struct uart_port *);  	/*  	 * Return a string describing the type of the port |