mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	msm_serial: Add support for poll_{get,put}_char()
Implement the polling functionality for the MSM serial driver. This allows us to use KGDB on this hardware. Cc: David Brown <davidb@codeaurora.org> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
		
							parent
							
								
									b28a960c42
								
							
						
					
					
						commit
						f7e54d7ad7
					
				
					 2 changed files with 146 additions and 3 deletions
				
			
		| 
						 | 
					@ -39,6 +39,13 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "msm_serial.h"
 | 
					#include "msm_serial.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum {
 | 
				
			||||||
 | 
						UARTDM_1P1 = 1,
 | 
				
			||||||
 | 
						UARTDM_1P2,
 | 
				
			||||||
 | 
						UARTDM_1P3,
 | 
				
			||||||
 | 
						UARTDM_1P4,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct msm_port {
 | 
					struct msm_port {
 | 
				
			||||||
	struct uart_port	uart;
 | 
						struct uart_port	uart;
 | 
				
			||||||
	char			name[16];
 | 
						char			name[16];
 | 
				
			||||||
| 
						 | 
					@ -309,6 +316,8 @@ static unsigned int msm_get_mctrl(struct uart_port *port)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void msm_reset(struct uart_port *port)
 | 
					static void msm_reset(struct uart_port *port)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct msm_port *msm_port = UART_TO_MSM(port);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* reset everything */
 | 
						/* reset everything */
 | 
				
			||||||
	msm_write(port, UART_CR_CMD_RESET_RX, UART_CR);
 | 
						msm_write(port, UART_CR_CMD_RESET_RX, UART_CR);
 | 
				
			||||||
	msm_write(port, UART_CR_CMD_RESET_TX, UART_CR);
 | 
						msm_write(port, UART_CR_CMD_RESET_TX, UART_CR);
 | 
				
			||||||
| 
						 | 
					@ -316,6 +325,10 @@ static void msm_reset(struct uart_port *port)
 | 
				
			||||||
	msm_write(port, UART_CR_CMD_RESET_BREAK_INT, UART_CR);
 | 
						msm_write(port, UART_CR_CMD_RESET_BREAK_INT, UART_CR);
 | 
				
			||||||
	msm_write(port, UART_CR_CMD_RESET_CTS, UART_CR);
 | 
						msm_write(port, UART_CR_CMD_RESET_CTS, UART_CR);
 | 
				
			||||||
	msm_write(port, UART_CR_CMD_SET_RFR, UART_CR);
 | 
						msm_write(port, UART_CR_CMD_SET_RFR, UART_CR);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Disable DM modes */
 | 
				
			||||||
 | 
						if (msm_port->is_uartdm)
 | 
				
			||||||
 | 
							msm_write(port, 0, UARTDM_DMEN);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void msm_set_mctrl(struct uart_port *port, unsigned int mctrl)
 | 
					static void msm_set_mctrl(struct uart_port *port, unsigned int mctrl)
 | 
				
			||||||
| 
						 | 
					@ -711,6 +724,117 @@ static void msm_power(struct uart_port *port, unsigned int state,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef CONFIG_CONSOLE_POLL
 | 
				
			||||||
 | 
					static int msm_poll_init(struct uart_port *port)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct msm_port *msm_port = UART_TO_MSM(port);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Enable single character mode on RX FIFO */
 | 
				
			||||||
 | 
						if (msm_port->is_uartdm >= UARTDM_1P4)
 | 
				
			||||||
 | 
							msm_write(port, UARTDM_DMEN_RX_SC_ENABLE, UARTDM_DMEN);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int msm_poll_get_char_single(struct uart_port *port)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct msm_port *msm_port = UART_TO_MSM(port);
 | 
				
			||||||
 | 
						unsigned int rf_reg = msm_port->is_uartdm ? UARTDM_RF : UART_RF;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!(msm_read(port, UART_SR) & UART_SR_RX_READY))
 | 
				
			||||||
 | 
							return NO_POLL_CHAR;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							return msm_read(port, rf_reg) & 0xff;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int msm_poll_get_char_dm_1p3(struct uart_port *port)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int c;
 | 
				
			||||||
 | 
						static u32 slop;
 | 
				
			||||||
 | 
						static int count;
 | 
				
			||||||
 | 
						unsigned char *sp = (unsigned char *)&slop;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Check if a previous read had more than one char */
 | 
				
			||||||
 | 
						if (count) {
 | 
				
			||||||
 | 
							c = sp[sizeof(slop) - count];
 | 
				
			||||||
 | 
							count--;
 | 
				
			||||||
 | 
						/* Or if FIFO is empty */
 | 
				
			||||||
 | 
						} else if (!(msm_read(port, UART_SR) & UART_SR_RX_READY)) {
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * If RX packing buffer has less than a word, force stale to
 | 
				
			||||||
 | 
							 * push contents into RX FIFO
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							count = msm_read(port, UARTDM_RXFS);
 | 
				
			||||||
 | 
							count = (count >> UARTDM_RXFS_BUF_SHIFT) & UARTDM_RXFS_BUF_MASK;
 | 
				
			||||||
 | 
							if (count) {
 | 
				
			||||||
 | 
								msm_write(port, UART_CR_CMD_FORCE_STALE, UART_CR);
 | 
				
			||||||
 | 
								slop = msm_read(port, UARTDM_RF);
 | 
				
			||||||
 | 
								c = sp[0];
 | 
				
			||||||
 | 
								count--;
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								c = NO_POLL_CHAR;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						/* FIFO has a word */
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							slop = msm_read(port, UARTDM_RF);
 | 
				
			||||||
 | 
							c = sp[0];
 | 
				
			||||||
 | 
							count = sizeof(slop) - 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return c;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int msm_poll_get_char(struct uart_port *port)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						u32 imr;
 | 
				
			||||||
 | 
						int c;
 | 
				
			||||||
 | 
						struct msm_port *msm_port = UART_TO_MSM(port);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Disable all interrupts */
 | 
				
			||||||
 | 
						imr = msm_read(port, UART_IMR);
 | 
				
			||||||
 | 
						msm_write(port, 0, UART_IMR);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (msm_port->is_uartdm == UARTDM_1P3)
 | 
				
			||||||
 | 
							c = msm_poll_get_char_dm_1p3(port);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							c = msm_poll_get_char_single(port);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Enable interrupts */
 | 
				
			||||||
 | 
						msm_write(port, imr, UART_IMR);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return c;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void msm_poll_put_char(struct uart_port *port, unsigned char c)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						u32 imr;
 | 
				
			||||||
 | 
						struct msm_port *msm_port = UART_TO_MSM(port);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Disable all interrupts */
 | 
				
			||||||
 | 
						imr = msm_read(port, UART_IMR);
 | 
				
			||||||
 | 
						msm_write(port, 0, UART_IMR);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (msm_port->is_uartdm)
 | 
				
			||||||
 | 
							reset_dm_count(port, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Wait until FIFO is empty */
 | 
				
			||||||
 | 
						while (!(msm_read(port, UART_SR) & UART_SR_TX_READY))
 | 
				
			||||||
 | 
							cpu_relax();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Write a character */
 | 
				
			||||||
 | 
						msm_write(port, c, msm_port->is_uartdm ? UARTDM_TF : UART_TF);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Wait until FIFO is empty */
 | 
				
			||||||
 | 
						while (!(msm_read(port, UART_SR) & UART_SR_TX_READY))
 | 
				
			||||||
 | 
							cpu_relax();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Enable interrupts */
 | 
				
			||||||
 | 
						msm_write(port, imr, UART_IMR);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct uart_ops msm_uart_pops = {
 | 
					static struct uart_ops msm_uart_pops = {
 | 
				
			||||||
	.tx_empty = msm_tx_empty,
 | 
						.tx_empty = msm_tx_empty,
 | 
				
			||||||
	.set_mctrl = msm_set_mctrl,
 | 
						.set_mctrl = msm_set_mctrl,
 | 
				
			||||||
| 
						 | 
					@ -729,6 +853,11 @@ static struct uart_ops msm_uart_pops = {
 | 
				
			||||||
	.config_port = msm_config_port,
 | 
						.config_port = msm_config_port,
 | 
				
			||||||
	.verify_port = msm_verify_port,
 | 
						.verify_port = msm_verify_port,
 | 
				
			||||||
	.pm = msm_power,
 | 
						.pm = msm_power,
 | 
				
			||||||
 | 
					#ifdef CONFIG_CONSOLE_POLL
 | 
				
			||||||
 | 
						.poll_init = msm_poll_init,
 | 
				
			||||||
 | 
						.poll_get_char	= msm_poll_get_char,
 | 
				
			||||||
 | 
						.poll_put_char	= msm_poll_put_char,
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct msm_port msm_uart_ports[] = {
 | 
					static struct msm_port msm_uart_ports[] = {
 | 
				
			||||||
| 
						 | 
					@ -900,7 +1029,10 @@ static struct uart_driver msm_uart_driver = {
 | 
				
			||||||
static atomic_t msm_uart_next_id = ATOMIC_INIT(0);
 | 
					static atomic_t msm_uart_next_id = ATOMIC_INIT(0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const struct of_device_id msm_uartdm_table[] = {
 | 
					static const struct of_device_id msm_uartdm_table[] = {
 | 
				
			||||||
	{ .compatible = "qcom,msm-uartdm" },
 | 
						{ .compatible = "qcom,msm-uartdm-v1.1", .data = (void *)UARTDM_1P1 },
 | 
				
			||||||
 | 
						{ .compatible = "qcom,msm-uartdm-v1.2", .data = (void *)UARTDM_1P2 },
 | 
				
			||||||
 | 
						{ .compatible = "qcom,msm-uartdm-v1.3", .data = (void *)UARTDM_1P3 },
 | 
				
			||||||
 | 
						{ .compatible = "qcom,msm-uartdm-v1.4", .data = (void *)UARTDM_1P4 },
 | 
				
			||||||
	{ }
 | 
						{ }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -909,6 +1041,7 @@ static int __init msm_serial_probe(struct platform_device *pdev)
 | 
				
			||||||
	struct msm_port *msm_port;
 | 
						struct msm_port *msm_port;
 | 
				
			||||||
	struct resource *resource;
 | 
						struct resource *resource;
 | 
				
			||||||
	struct uart_port *port;
 | 
						struct uart_port *port;
 | 
				
			||||||
 | 
						const struct of_device_id *id;
 | 
				
			||||||
	int irq;
 | 
						int irq;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (pdev->id == -1)
 | 
						if (pdev->id == -1)
 | 
				
			||||||
| 
						 | 
					@ -923,8 +1056,9 @@ static int __init msm_serial_probe(struct platform_device *pdev)
 | 
				
			||||||
	port->dev = &pdev->dev;
 | 
						port->dev = &pdev->dev;
 | 
				
			||||||
	msm_port = UART_TO_MSM(port);
 | 
						msm_port = UART_TO_MSM(port);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (of_match_device(msm_uartdm_table, &pdev->dev))
 | 
						id = of_match_device(msm_uartdm_table, &pdev->dev);
 | 
				
			||||||
		msm_port->is_uartdm = 1;
 | 
						if (id)
 | 
				
			||||||
 | 
							msm_port->is_uartdm = (unsigned long)id->data;
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		msm_port->is_uartdm = 0;
 | 
							msm_port->is_uartdm = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -59,6 +59,7 @@
 | 
				
			||||||
#define UART_CR_CMD_RESET_RFR		(14 << 4)
 | 
					#define UART_CR_CMD_RESET_RFR		(14 << 4)
 | 
				
			||||||
#define UART_CR_CMD_PROTECTION_EN	(16 << 4)
 | 
					#define UART_CR_CMD_PROTECTION_EN	(16 << 4)
 | 
				
			||||||
#define UART_CR_CMD_STALE_EVENT_ENABLE	(80 << 4)
 | 
					#define UART_CR_CMD_STALE_EVENT_ENABLE	(80 << 4)
 | 
				
			||||||
 | 
					#define UART_CR_CMD_FORCE_STALE		(4 << 8)
 | 
				
			||||||
#define UART_CR_CMD_RESET_TX_READY	(3 << 8)
 | 
					#define UART_CR_CMD_RESET_TX_READY	(3 << 8)
 | 
				
			||||||
#define UART_CR_TX_DISABLE		(1 << 3)
 | 
					#define UART_CR_TX_DISABLE		(1 << 3)
 | 
				
			||||||
#define UART_CR_TX_ENABLE		(1 << 2)
 | 
					#define UART_CR_TX_ENABLE		(1 << 2)
 | 
				
			||||||
| 
						 | 
					@ -113,6 +114,14 @@
 | 
				
			||||||
#define GSBI_PROTOCOL_UART	0x40
 | 
					#define GSBI_PROTOCOL_UART	0x40
 | 
				
			||||||
#define GSBI_PROTOCOL_IDLE	0x0
 | 
					#define GSBI_PROTOCOL_IDLE	0x0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define UARTDM_RXFS		0x50
 | 
				
			||||||
 | 
					#define UARTDM_RXFS_BUF_SHIFT	0x7
 | 
				
			||||||
 | 
					#define UARTDM_RXFS_BUF_MASK	0x7
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define UARTDM_DMEN		0x3C
 | 
				
			||||||
 | 
					#define UARTDM_DMEN_RX_SC_ENABLE BIT(5)
 | 
				
			||||||
 | 
					#define UARTDM_DMEN_TX_SC_ENABLE BIT(4)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define UARTDM_DMRX		0x34
 | 
					#define UARTDM_DMRX		0x34
 | 
				
			||||||
#define UARTDM_NCF_TX		0x40
 | 
					#define UARTDM_NCF_TX		0x40
 | 
				
			||||||
#define UARTDM_RX_TOTAL_SNAP	0x38
 | 
					#define UARTDM_RX_TOTAL_SNAP	0x38
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue