Alchemy: Add UART PM methods.
Custom UART PM hook for Alchemy chips: do standard UART pm and additionally en/disable uart block clocks as needed. This allows to get rid of a debug port PM hack in the Alchemy pm code. Tested on Db1200. Signed-off-by: Manuel Lauss <manuel.lauss@googlemail.com> Cc: Alan Cox <alan@lxorguk.ukuu.org.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
		
					parent
					
						
							
								c161afe975
							
						
					
				
			
			
				commit
				
					
						7d172bfefb
					
				
			
		
					 2 changed files with 28 additions and 35 deletions
				
			
		|  | @ -24,6 +24,33 @@ | ||||||
| 
 | 
 | ||||||
| #include <prom.h> | #include <prom.h> | ||||||
| 
 | 
 | ||||||
|  | static void alchemy_8250_pm(struct uart_port *port, unsigned int state, | ||||||
|  | 			    unsigned int old_state) | ||||||
|  | { | ||||||
|  | 	switch (state) { | ||||||
|  | 	case 0: | ||||||
|  | 		if ((__raw_readl(port->membase + UART_MOD_CNTRL) & 3) != 3) { | ||||||
|  | 			/* power-on sequence as suggested in the databooks */ | ||||||
|  | 			__raw_writel(0, port->membase + UART_MOD_CNTRL); | ||||||
|  | 			wmb(); | ||||||
|  | 			__raw_writel(1, port->membase + UART_MOD_CNTRL); | ||||||
|  | 			wmb(); | ||||||
|  | 		} | ||||||
|  | 		__raw_writel(3, port->membase + UART_MOD_CNTRL); /* full on */ | ||||||
|  | 		wmb(); | ||||||
|  | 		serial8250_do_pm(port, state, old_state); | ||||||
|  | 		break; | ||||||
|  | 	case 3:		/* power off */ | ||||||
|  | 		serial8250_do_pm(port, state, old_state); | ||||||
|  | 		__raw_writel(0, port->membase + UART_MOD_CNTRL); | ||||||
|  | 		wmb(); | ||||||
|  | 		break; | ||||||
|  | 	default: | ||||||
|  | 		serial8250_do_pm(port, state, old_state); | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| #define PORT(_base, _irq)					\ | #define PORT(_base, _irq)					\ | ||||||
| 	{							\ | 	{							\ | ||||||
| 		.mapbase	= _base,			\ | 		.mapbase	= _base,			\ | ||||||
|  | @ -33,6 +60,7 @@ | ||||||
| 		.flags		= UPF_SKIP_TEST | UPF_IOREMAP |	\ | 		.flags		= UPF_SKIP_TEST | UPF_IOREMAP |	\ | ||||||
| 				  UPF_FIXED_TYPE,		\ | 				  UPF_FIXED_TYPE,		\ | ||||||
| 		.type		= PORT_16550A,			\ | 		.type		= PORT_16550A,			\ | ||||||
|  | 		.pm		= alchemy_8250_pm,		\ | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| static struct plat_serial8250_port au1x00_uart_data[] = { | static struct plat_serial8250_port au1x00_uart_data[] = { | ||||||
|  |  | ||||||
|  | @ -49,11 +49,6 @@ | ||||||
|  * We only have to save/restore registers that aren't otherwise |  * We only have to save/restore registers that aren't otherwise | ||||||
|  * done as part of a driver pm_* function. |  * done as part of a driver pm_* function. | ||||||
|  */ |  */ | ||||||
| static unsigned int sleep_uart0_inten; |  | ||||||
| static unsigned int sleep_uart0_fifoctl; |  | ||||||
| static unsigned int sleep_uart0_linectl; |  | ||||||
| static unsigned int sleep_uart0_clkdiv; |  | ||||||
| static unsigned int sleep_uart0_enable; |  | ||||||
| static unsigned int sleep_usb[2]; | static unsigned int sleep_usb[2]; | ||||||
| static unsigned int sleep_sys_clocks[5]; | static unsigned int sleep_sys_clocks[5]; | ||||||
| static unsigned int sleep_sys_pinfunc; | static unsigned int sleep_sys_pinfunc; | ||||||
|  | @ -62,22 +57,6 @@ static unsigned int sleep_static_memctlr[4][3]; | ||||||
| 
 | 
 | ||||||
| static void save_core_regs(void) | static void save_core_regs(void) | ||||||
| { | { | ||||||
| 	extern void save_au1xxx_intctl(void); |  | ||||||
| 	extern void pm_eth0_shutdown(void); |  | ||||||
| 
 |  | ||||||
| 	/*
 |  | ||||||
| 	 * Do the serial ports.....these really should be a pm_* |  | ||||||
| 	 * registered function by the driver......but of course the |  | ||||||
| 	 * standard serial driver doesn't understand our Au1xxx |  | ||||||
| 	 * unique registers. |  | ||||||
| 	 */ |  | ||||||
| 	sleep_uart0_inten = au_readl(UART0_ADDR + UART_IER); |  | ||||||
| 	sleep_uart0_fifoctl = au_readl(UART0_ADDR + UART_FCR); |  | ||||||
| 	sleep_uart0_linectl = au_readl(UART0_ADDR + UART_LCR); |  | ||||||
| 	sleep_uart0_clkdiv = au_readl(UART0_ADDR + UART_CLK); |  | ||||||
| 	sleep_uart0_enable = au_readl(UART0_ADDR + UART_MOD_CNTRL); |  | ||||||
| 	au_sync(); |  | ||||||
| 
 |  | ||||||
| #ifndef CONFIG_SOC_AU1200 | #ifndef CONFIG_SOC_AU1200 | ||||||
| 	/* Shutdown USB host/device. */ | 	/* Shutdown USB host/device. */ | ||||||
| 	sleep_usb[0] = au_readl(USB_HOST_CONFIG); | 	sleep_usb[0] = au_readl(USB_HOST_CONFIG); | ||||||
|  | @ -175,20 +154,6 @@ static void restore_core_regs(void) | ||||||
| 	au_writel(sleep_static_memctlr[3][0], MEM_STCFG3); | 	au_writel(sleep_static_memctlr[3][0], MEM_STCFG3); | ||||||
| 	au_writel(sleep_static_memctlr[3][1], MEM_STTIME3); | 	au_writel(sleep_static_memctlr[3][1], MEM_STTIME3); | ||||||
| 	au_writel(sleep_static_memctlr[3][2], MEM_STADDR3); | 	au_writel(sleep_static_memctlr[3][2], MEM_STADDR3); | ||||||
| 
 |  | ||||||
| 	/*
 |  | ||||||
| 	 * Enable the UART if it was enabled before sleep. |  | ||||||
| 	 * I guess I should define module control bits........ |  | ||||||
| 	 */ |  | ||||||
| 	if (sleep_uart0_enable & 0x02) { |  | ||||||
| 		au_writel(0, UART0_ADDR + UART_MOD_CNTRL); au_sync(); |  | ||||||
| 		au_writel(1, UART0_ADDR + UART_MOD_CNTRL); au_sync(); |  | ||||||
| 		au_writel(3, UART0_ADDR + UART_MOD_CNTRL); au_sync(); |  | ||||||
| 		au_writel(sleep_uart0_inten, UART0_ADDR + UART_IER); au_sync(); |  | ||||||
| 		au_writel(sleep_uart0_fifoctl, UART0_ADDR + UART_FCR); au_sync(); |  | ||||||
| 		au_writel(sleep_uart0_linectl, UART0_ADDR + UART_LCR); au_sync(); |  | ||||||
| 		au_writel(sleep_uart0_clkdiv, UART0_ADDR + UART_CLK); au_sync(); |  | ||||||
| 	} |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void au_sleep(void) | void au_sleep(void) | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Manuel Lauss
				Manuel Lauss