diff options
Diffstat (limited to 'meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-pch-uart.patch')
-rw-r--r-- | meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-pch-uart.patch | 1589 |
1 files changed, 1589 insertions, 0 deletions
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-pch-uart.patch b/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-pch-uart.patch new file mode 100644 index 0000000..b1e1f48 --- /dev/null +++ b/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-pch-uart.patch @@ -0,0 +1,1589 @@ + + +From: Masayuki Ohtake <masa-korg@dsn.okisemi.com> +Subject: OKI Semiconductor PCH UART driver + +This driver implements UART controls for PCH. + +Signed-off-by: Masayuki Ohtake <masa-korg@dsn.okisemi.com> +Acked-by: Wang Qi <qi.wang@intel.com> + +--- + drivers/serial/8250.c | 8 + drivers/serial/8250_pch.h | 57 + drivers/serial/8250_pci.c | + drivers/serial/Kconfig | 15 + drivers/serial/Makefile | 11 ++++++++++++++++++++++++++++++++ 5 files changed, zz insertions(+) +diff -urN linux-2.6.33.1/drivers/serial/8250.c topcliff-2.6.33.1/drivers/serial/8250.c +--- linux-2.6.33.1/drivers/serial/8250.c 2010-03-16 01:09:39.000000000 +0900 ++++ topcliff-2.6.33.1/drivers/serial/8250.c 2010-03-23 10:34:44.000000000 +0900 +@@ -39,11 +39,19 @@ + #include <linux/nmi.h> + #include <linux/mutex.h> + ++#if defined(ENABLE_SERIAL_8250_PCH) && defined(ENABLE_PCH_DMA_FEATURE) ++/* For using DMA features. */ ++#include <linux/pci.h> ++#include <linux/pci_ids.h> ++#include <linux/dma-mapping.h> ++#include "pch_dma_main.h" ++#endif ++ + #include <asm/io.h> + #include <asm/irq.h> + + #include "8250.h" +- ++#include "8250_pch.h" + #ifdef CONFIG_SPARC + #include "suncore.h" + #endif +@@ -129,6 +137,18 @@ + static unsigned int probe_rsa_count; + #endif /* CONFIG_SERIAL_8250_RSA */ + ++#if defined(ENABLE_SERIAL_8250_PCH) && defined(ENABLE_PCH_DMA_FEATURE) ++/* Structure for storing the DMA channel related information. */ ++struct ioh_dma_feature { ++ u32 buf; ++ u32 phy_addr; ++ s32 channel; ++ u32 size; ++}; ++#endif ++ ++ ++ + struct uart_8250_port { + struct uart_port port; + struct timer_list timer; /* "no irq" timer */ +@@ -159,6 +179,17 @@ + */ + void (*pm)(struct uart_port *port, + unsigned int state, unsigned int old); ++ ++#if defined(ENABLE_SERIAL_8250_PCH) && defined(ENABLE_PCH_DMA_FEATURE) ++ struct ioh_dma_feature rx_dma; /* DMA operation for Receive. */ ++ struct ioh_dma_feature tx_dma; /* DMA operation for Transmit. */ ++ unsigned int buffer; /* The buffer for DMA descriptors.*/ ++ unsigned int buffer_phy; /* The physical address of the buffer.*/ ++ unsigned int dma_flag;/* DMA flag variable for enabling DMA transfer. */ ++ unsigned int rx_fifo_size; /* The UART Rx fifo size.*/ ++ unsigned int dma_progress; /* The DMA in progress flag.*/ ++ unsigned int dma_enabled; /* The DMA enable flag. */ ++#endif + }; + + struct irq_info { +@@ -299,6 +330,25 @@ + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00, + .flags = UART_CAP_FIFO | UART_CAP_AFE, + }, ++#if defined(ENABLE_SERIAL_8250_PCH) ++ [PORT_IOH_256FIFO] = { ++ .name = "IOH_256FIFO", ++ .fifo_size = 256, ++ .tx_loadsz = 256, ++ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 | ++ UART_FCR7_256BYTE, ++ .flags = UART_CAP_FIFO | UART_CAP_AFE, ++ }, ++ ++ [PORT_IOH_64FIFO] = { ++ .name = "IOH_64FIFO", ++ .fifo_size = 64, ++ .tx_loadsz = 64, ++ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 | ++ UART_FCR7_64BYTE, ++ .flags = UART_CAP_FIFO | UART_BUG_NOMSR, ++ }, ++#endif + }; + + #if defined (CONFIG_SERIAL_8250_AU1X00) +@@ -383,6 +433,78 @@ + + #endif + ++ ++#if defined(ENABLE_SERIAL_8250_PCH) && defined(ENABLE_PCH_DMA_FEATURE) ++ ++/* Function for calculating the Rx FIFO size of the IOH UART. */ ++void get_rx_fifo_size(struct uart_8250_port *up, u8 fcr_value) ++{ ++ unsigned fifo_size; ++ ++#ifdef DEBUG ++ printk(KERN_DEBUG"get_rx_fifo -> The FCR register value: %x.\n", ++ fcr_value); ++#endif ++/* check if the UART is a 64 byte FIFO UART */ ++ if ((up->port.flags & UPF_IOH_UART_64_FIFO) != 0) { ++ switch ((fcr_value & 0xC0)) { ++ case 0: ++ fifo_size = 1; ++ break; ++ ++ case 0x40: ++ fifo_size = 16; ++ break; ++ ++ case 0x80: ++ fifo_size = 32; ++ break; ++ ++ case 0xC0: ++ fifo_size = 56; ++ break; ++ ++ default: ++ fifo_size = 1; ++ break; ++ } ++ } else { ++/* UART is 256 byte byte FIFO UART */ ++ switch ((fcr_value & 0xC0)) { ++ case 0: ++ fifo_size = 1; ++ break; ++ ++ case 0x40: ++ fifo_size = 64; ++ break; ++ ++ case 0x80: ++ fifo_size = 128; ++ break; ++ ++ case 0xC0: ++ fifo_size = 224; ++ break; ++ ++ default: ++ fifo_size = 1; ++ break; ++ } ++ } ++/* save the fifo size for reference */ ++ up->rx_fifo_size = fifo_size; ++#ifdef DEBUG ++ printk(KERN_DEBUG"Function get_rx_fifo_size stores fifo_size as: %u.\n", ++ fifo_size); ++#endif ++} ++ ++#endif ++ ++ ++ ++ + static unsigned int hub6_serial_in(struct uart_port *p, int offset) + { + offset = map_8250_in_reg(p, offset) << p->regshift; +@@ -550,15 +672,285 @@ + (up->port.serial_in(&(up)->port, (offset))) + #define serial_out(up, offset, value) \ + (up->port.serial_out(&(up)->port, (offset), (value))) ++ + /* + * We used to support using pause I/O for certain machines. We + * haven't supported this for a while, but just in case it's badly + * needed for certain old 386 machines, I've left these #define's + * in.... + */ ++ + #define serial_inp(up, offset) serial_in(up, offset) + #define serial_outp(up, offset, value) serial_out(up, offset, value) + ++ ++#if defined(ENABLE_SERIAL_8250_PCH) && defined(ENABLE_PCH_DMA_FEATURE) ++ ++/* DMA TX callback function */ ++void ioh_dma_tx_callback(int status, unsigned long data) ++{ ++ struct uart_8250_port *up = (struct uart_8250_port *)data; ++/* struct circ_buf *xmit = &up->port.info->xmit;*/ ++ struct circ_buf *xmit = &up->port.state->xmit;/*for 2.6.33-rc3*/ ++ u8 value; ++ ++#ifdef DEBUG ++ if (status == IOH_DMA_END) { ++ printk(KERN_DEBUG"ioh_dma_tx_callback -> DMA END interrupt\ ++ obtained " \ ++ "for transmission.\n"); ++ ++ } ++#endif ++ if (status == IOH_DMA_ABORT) { ++ printk(KERN_ERR"ioh_dma_tx_callback -> DMA ABORT interrupt\ ++ obtained " \ ++ "for transmission.\n"); ++ } ++ ++ /* Un-mapping the DMA buffer. */ ++ if (up->tx_dma.phy_addr > 0) ++ dma_unmap_single(up->port.dev, up->tx_dma.phy_addr, ++ up->tx_dma.size, DMA_TO_DEVICE); ++ ++ dma_unmap_single(up->port.dev, up->buffer_phy, ++ PAGE_SIZE, DMA_TO_DEVICE); ++ ++ /*Enable TX interrupt.*/ ++ if (uart_circ_chars_pending(xmit)) { ++ value = (u8)serial_in(up, UART_IER); ++ serial_out(up, UART_IER, (value | 0x02)); ++ up->ier = serial_in(up, UART_IER); ++ } ++#ifdef DEBUG ++ printk(KERN_DEBUG"Function ioh_dma_tx_callback invoked.\n"); ++#endif ++} ++ ++/* Function for DMA setting for Scatter Gather Mode. */ ++void set_scatter_gather_dma_mode(struct uart_8250_port *up, unsigned count) ++{ ++ u32 in_address; ++ u32 out_address; ++ u32 desc_address; ++ u32 total_desc; ++ u32 i, j; ++ u8 value; ++ struct ioh_dma_desc *desc; ++ int channel = up->tx_dma.channel; ++ struct ioh_dma_mode_param mode = { ++ .TransferDirection = IOH_DMA_DIR_OUT_TO_IN, ++ .DMASizeType = IOH_DMA_SIZE_TYPE_8BIT, ++ .DMATransferMode = DMA_SCATTER_GATHER_MODE ++ }; ++ ++ desc = (struct ioh_dma_desc *)up->tx_dma.buf; ++ ++ /* Mapping the DMA buffer for transfer. */ ++ out_address = dma_map_single(up->port.dev, (void *)up->buffer, ++ PAGE_SIZE, DMA_TO_DEVICE); ++ in_address = up->port.mapbase + (map_8250_in_reg(up, UART_TX)); ++ desc_address = dma_map_single(up->port.dev, (void *)up->tx_dma.buf, ++ up->tx_dma.size, DMA_TO_DEVICE); ++ up->buffer_phy = out_address; ++ up->tx_dma.phy_addr = desc_address; ++ ++ /* Disable Transmit hardware interrupt.*/ ++ value = (u8)serial_in(up, UART_IER); ++ serial_out(up, UART_IER, (value & 0xFD)); ++ up->ier = serial_in(up, UART_IER); ++ ++ total_desc = count/(up->tx_loadsz); ++ ++ if ((count % (up->tx_loadsz)) > 0) ++ total_desc++; ++ ++ dma_sync_single_for_cpu(up->port.dev, desc_address, up->tx_dma.size, ++ DMA_TO_DEVICE); ++ ++ /* Organising the DMA descriptors. */ ++ for (i = 0, j = 0; (i < total_desc && count > 0); i++) { ++ desc[i].insideAddress = in_address; ++ desc[i].outsideAddress = (out_address + j); ++ ++ if ((int)(count - (up->tx_loadsz)) > 0) { ++ desc[i].size = up->tx_loadsz | IOH_DMA_SIZE_TYPE_8BIT; ++ count = count - (up->tx_loadsz); ++ j += (up->tx_loadsz); ++ } else { ++ desc[i].size = count | IOH_DMA_SIZE_TYPE_8BIT; ++ j += count; ++ count = 0; ++ } ++ ++ desc[i].nextDesc = ((((u32)((desc_address + ++ ((i + 1)*(sizeof(struct ioh_dma_desc)))))) & 0xFFFFFFFC) | ++ DMA_DESC_FOLLOW_WITHOUT_INTERRUPT); ++ } ++ ++ desc[i - 1].nextDesc = (DMA_DESC_END_WITH_INTERRUPT); ++ ++ dma_sync_single_for_device(up->port.dev, desc_address, up->tx_dma.size, ++ DMA_TO_DEVICE); ++ ++ /* Initiating the DMA transfer. */ ++ ioh_set_dma_mode(channel, mode); ++ ioh_set_dma_desc(channel, (struct ioh_dma_desc *)((desc_address & ++ 0xFFFFFFFC) | DMA_DESC_FOLLOW_WITHOUT_INTERRUPT),\ ++ (((struct ioh_dma_desc *)desc_address) + (total_desc - 1))); ++ ioh_dma_set_callback(channel, ioh_dma_tx_callback, (u32)up); ++ ioh_enable_dma(channel); ++ ++#ifdef DEBUG ++ printk(KERN_DEBUG"Function set_scatter_gather_dma_mode invoked.\n"); ++#endif ++} ++ ++/* Function for DMA settings for ONE SHOT mode. */ ++void set_one_shot_dma_mode(struct uart_8250_port *up, unsigned count) ++{ ++ u32 in_address; ++ u32 out_address; ++ u8 value; ++ int channel = up->tx_dma.channel; ++ struct ioh_dma_mode_param mode = { ++ .TransferDirection = IOH_DMA_DIR_OUT_TO_IN, ++ .DMASizeType = IOH_DMA_SIZE_TYPE_8BIT, ++ .DMATransferMode = DMA_ONE_SHOT_MODE ++ }; ++ ++ /* Disable Receive hardware interrupt.*/ ++ value = (u8)serial_in(up, UART_IER); ++ serial_out(up, UART_IER, (value & 0xFD)); ++ up->ier = serial_in(up, UART_IER); ++ ++ /* Mapping the DMA buffer for transfer. */ ++ out_address = dma_map_single(up->port.dev, (void *)up->buffer, ++ PAGE_SIZE, DMA_TO_DEVICE); ++ in_address = up->port.mapbase + (map_8250_in_reg(up, UART_TX)); ++ up->buffer_phy = out_address; ++ up->tx_dma.phy_addr = 0; ++ ++ /* Initiating the DMA transfer. */ ++ ioh_set_dma_mode(channel, mode); ++ ioh_set_dma_addr(channel, in_address, out_address); ++ ioh_set_dma_count(channel, count); ++ ioh_dma_set_callback(channel, ioh_dma_tx_callback, (u32)up); ++ ioh_enable_dma(channel); ++ ++#ifdef DEBUG ++ printk(KERN_DEBUG"Function set_one_shot_dma_mode invoked.\n"); ++#endif ++} ++ ++/* Function for pushing the received characters to tty buffer. */ ++/* At high baud rates tty buffer does not get emptied sufficiently fast ++ and hence multiple retries are required to push the data into the buffer */ ++ ++static int push_rx(struct tty_struct *tty, const unsigned char *buf, int size) ++{ ++ u32 sz, i, j; ++ u32 loop; ++ u32 pushed; ++ ++ for (pushed = 0, i = 0, loop = 1; (pushed < size) && loop; ++ pushed += sz, i++) { ++ sz = tty_insert_flip_string(tty, &buf[pushed], size - pushed); ++ ++ for (j = 0; (j < 100000) && (sz == 0); j++) { ++ tty_flip_buffer_push(tty); ++ sz = tty_insert_flip_string(tty, &buf[pushed], ++ size - pushed); ++ } ++ ++ if (sz == 0) ++ loop = 0; ++ ++ } ++ ++ tty_flip_buffer_push(tty); ++ ++#ifdef DEBUG ++ printk(KERN_DEBUG"push_rx -> %d characters pushed. Remained " \ ++ "%d characters.\n", pushed, size - pushed); ++ printk(KERN_DEBUG"Function push_rx return %u.\n", pushed); ++#endif ++ ++ return pushed; ++} ++ ++/* The DMA reception callback function. */ ++void ioh_dma_rx_callback(int status, unsigned long data) ++{ ++ struct uart_8250_port *up = (struct uart_8250_port *)data; ++ unsigned fifo_size; ++ unsigned long flags; ++ u8 value; ++ ++ spin_lock_irqsave(&up->port.lock, flags); ++ ++ /* Normal end. */ ++ if (status == IOH_DMA_END) { ++ /* Preparing the DMA buffer to be accessed by the CPU*/ ++ dma_sync_single_for_cpu(up->port.dev, up->rx_dma.phy_addr, ++ up->rx_dma.size, DMA_FROM_DEVICE); ++ ++#ifdef DEBUG ++ printk(KERN_DEBUG"ioh_dma_rx_callback -> DMA END interrupt\ ++ obtained for reception.\n"); ++#endif ++ fifo_size = up->rx_fifo_size; ++/* push_rx(up->port.info->port.tty, (char *)up->rx_dma.buf, ++ fifo_size);*/ ++ push_rx(up->port.state->port.tty, (char *)up->rx_dma.buf, ++ fifo_size); /*for 2.6.33-rc3 */ ++ ++ } else if (status == IOH_DMA_ABORT) { /* DMA abort. */ ++ printk(KERN_ERR"ioh_dma_rx_callback -> DMA ABORT interrupt\ ++ obtained for reception.\n"); ++ } ++ ++ /* Unmapping the buffer from DMA accesible area. */ ++ dma_unmap_single(up->port.dev, up->rx_dma.phy_addr, up->rx_dma.size, ++ DMA_FROM_DEVICE); ++ ++ /*Enable hardware interrupt.*/ ++ value = (u8)serial_in(up, UART_IER); ++ serial_out(up, UART_IER, (value | 0x01)); ++ up->ier = serial_in(up, UART_IER); ++ up->dma_progress = 0; ++ ++ spin_unlock_irqrestore(&up->port.lock, flags); ++ ++#ifdef DEBUG ++ printk(KERN_DEBUG"ioh_dma_rx_callback -> Function ioh_dma_rx_callback\ ++ is invoked.\n"); ++#endif ++} ++ ++/* For initiating the DMA operation.*/ ++void handle_dma_operation(struct uart_8250_port *up) ++{ ++ u8 value; ++ int channel = up->rx_dma.channel; ++ ++ /* Disable Receive hardware interrupt.*/ ++ value = (u8)serial_in(up, UART_IER); ++ serial_out(up, UART_IER, (value & 0xFE)); ++ up->ier = serial_in(up, UART_IER); ++ ++ /* Enabling the DMA transfer. */ ++ ioh_enable_dma(channel); ++ up->dma_progress = 1; ++ ++#ifdef DEBUG ++ printk(KERN_DEBUG"handle_dma_operation -> DMA settings for reception\ ++ completed.\n"); ++ printk(KERN_DEBUG"Function handle_dma_operation invoked.\n"); ++#endif ++} ++#endif /*for 2.6.33-rc3 */ ++ + /* Uart divisor latch read */ + static inline int _serial_dl_read(struct uart_8250_port *up) + { +@@ -725,7 +1117,8 @@ + result = !(mode & UART_RSA_MSR_FIFO); + + if (!result) { +- serial_outp(up, UART_RSA_MSR, mode & ~UART_RSA_MSR_FIFO); ++ serial_outp(up, UART_RSA_MSR, ++ mode & ~UART_RSA_MSR_FIFO); + mode = serial_inp(up, UART_RSA_MSR); + result = !(mode & UART_RSA_MSR_FIFO); + } +@@ -1040,6 +1433,18 @@ + return; + } + ++#if defined(ENABLE_SERIAL_8250_PCH) ++ if ((up->port.flags & UPF_IOH_UART) != 0) { ++ if ((up->port.flags & UPF_IOH_UART_64_FIFO) != 0) ++ /* IOH 2 Line 64 FIFO UART */ ++ up->port.type = PORT_IOH_64FIFO; ++ else ++ /* IOH 8 Line 256 FIFO UART */ ++ up->port.type = PORT_IOH_256FIFO; ++ ++ } ++#endif ++ + /* + * Try writing and reading the UART_IER_UUE bit (b6). + * If it works, this is probably one of the Xscale platform's +@@ -1093,7 +1498,7 @@ + return; + + DEBUG_AUTOCONF("ttyS%d: autoconf (0x%04lx, 0x%p): ", +- serial_index(&up->port), up->port.iobase, up->port.membase); ++ serial_index(&up->port), up->port.iobase, up->port.membase); + + /* + * We really do need global IRQs disabled here - we're going to +@@ -1196,7 +1601,34 @@ + up->port.type = PORT_16550; + break; + case 3: +- autoconfig_16550a(up); ++#ifdef ENABLE_SERIAL_8250_PCH ++ if ((up->port.type != PORT_IOH_256FIFO) && ++ (up->port.type != PORT_IOH_64FIFO)) { ++#endif ++ ++#ifdef DEBUG ++ printk(KERN_DEBUG ++ "IOH UART LOG:function autoconfig->autoconfig_16550a\ ++ invoked " ++ "for port %d\n", up->port.type); ++#endif ++ autoconfig_16550a(up); ++ ++#ifdef ENABLE_SERIAL_8250_PCH ++ } ++#endif ++ ++#ifdef ENABLE_SERIAL_8250_PCH ++ else { ++ ++#ifdef DEBUG ++ printk(KERN_DEBUG ++ "IOH UART LOG:function autoconfig->autoconfig_16550a\ ++ not " ++ "invoked for IOH UART port %d\n", up->port.type); ++#endif ++ } ++#endif + break; + } + +@@ -1224,18 +1656,40 @@ + #endif + + serial_outp(up, UART_LCR, save_lcr); ++#ifdef ENABLE_SERIAL_8250_PCH ++ if ((up->port.type != PORT_IOH_256FIFO) && ++ (up->port.type != PORT_IOH_64FIFO)) { ++ /* autoconfig is not done for ioh uarts. ++ hence do not report any kernel warning */ ++#endif + +- if (up->capabilities != uart_config[up->port.type].flags) { +- printk(KERN_WARNING +- "ttyS%d: detected caps %08x should be %08x\n", +- serial_index(&up->port), up->capabilities, +- uart_config[up->port.type].flags); ++ if (up->capabilities != uart_config[up->port.type].flags) { ++ printk(KERN_WARNING "ttyS%d: detected\ ++ caps %08x should be %08x\n", ++ up->port.line, up->capabilities, ++ uart_config[up->port.type].flags); ++ } ++ ++#ifdef ENABLE_SERIAL_8250_PCH + } ++#endif + + up->port.fifosize = uart_config[up->port.type].fifo_size; + up->capabilities = uart_config[up->port.type].flags; + up->tx_loadsz = uart_config[up->port.type].tx_loadsz; + ++#ifdef DEBUG ++ printk(KERN_DEBUG ++ "IOH UART LOG:autoconfig: up->port.type = %d, up->port.fifosize =%d," ++ "up->capabilities = %x, up->tx_loadsz = %d\n", up->port.type, ++ up->port.fifosize, up->capabilities, up->tx_loadsz); ++ ++ printk(KERN_DEBUG ++ "IOH UART LOG:autoconfig: port.name = %s, port.fcr = %x\n", ++ uart_config[up->port.type].name, uart_config[up->port.type].fcr); ++ ++#endif ++ + if (up->port.type == PORT_UNKNOWN) + goto out; + +@@ -1461,7 +1915,11 @@ + static void transmit_chars(struct uart_8250_port *up) + { + struct circ_buf *xmit = &up->port.state->xmit; +- int count; ++ int count = 0; ++#if defined(ENABLE_SERIAL_8250_PCH) && defined(ENABLE_PCH_DMA_FEATURE) ++ unsigned limit = 0; ++ unsigned size = 0; ++#endif + + if (up->port.x_char) { + serial_outp(up, UART_TX, up->port.x_char); +@@ -1478,15 +1936,53 @@ + return; + } + ++#if defined(ENABLE_SERIAL_8250_PCH) && defined(ENABLE_PCH_DMA_FEATURE) ++ if (((up->port.flags & UPF_IOH_UART) != 0)) { ++ size = uart_circ_chars_pending(xmit); ++ ++ if (size > PAGE_SIZE) ++ size = PAGE_SIZE; ++ ++ count = size; ++ } ++ ++ else ++#endif + count = up->tx_loadsz; + do { ++#if defined(ENABLE_SERIAL_8250_PCH) && defined(ENABLE_PCH_DMA_FEATURE) ++ if ((((up->port.flags & UPF_IOH_UART) != 0)) && (size > 0)) { ++ ((char *)(up->buffer))[limit] = xmit->buf[xmit->tail]; ++ limit++; ++ ++ } else ++#endif + serial_out(up, UART_TX, xmit->buf[xmit->tail]); ++ + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); + up->port.icount.tx++; + if (uart_circ_empty(xmit)) + break; + } while (--count > 0); + ++#if defined(ENABLE_SERIAL_8250_PCH) && defined(ENABLE_PCH_DMA_FEATURE) ++ if (limit > 0) { ++ if (limit > up->tx_loadsz) { ++ set_scatter_gather_dma_mode(up, limit); ++#ifdef DEBUG ++ printk(KERN_DEBUG"transmit_chars -> Function\ ++ set_scatter_gather_dma_mode invoked.\n"); ++#endif ++ } else { ++ set_one_shot_dma_mode(up, limit); ++#ifdef DEBUG ++ printk(KERN_DEBUG"transmit_chars -> Function\ ++ set_one_shot_dma_mode invoked.\n"); ++#endif ++ } ++ } ++#endif ++ + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_write_wakeup(&up->port); + +@@ -1494,6 +1990,10 @@ + + if (uart_circ_empty(xmit)) + __stop_tx(up); ++ ++#ifdef DEBUG ++ printk(KERN_DEBUG"Function transmit_chars invoked.\n"); ++#endif + } + + static unsigned int check_modem_status(struct uart_8250_port *up) +@@ -1509,9 +2009,11 @@ + if (status & UART_MSR_DDSR) + up->port.icount.dsr++; + if (status & UART_MSR_DDCD) +- uart_handle_dcd_change(&up->port, status & UART_MSR_DCD); ++ uart_handle_dcd_change(&up->port, ++ status & UART_MSR_DCD); + if (status & UART_MSR_DCTS) +- uart_handle_cts_change(&up->port, status & UART_MSR_CTS); ++ uart_handle_cts_change(&up->port, ++ status & UART_MSR_CTS); + + wake_up_interruptible(&up->port.state->port.delta_msr_wait); + } +@@ -1533,13 +2035,36 @@ + + DEBUG_INTR("status = %x...", status); + +- if (status & (UART_LSR_DR | UART_LSR_BI)) +- receive_chars(up, &status); ++#if defined(ENABLE_SERIAL_8250_PCH) && defined(ENABLE_PCH_DMA_FEATURE) ++ if ((up->dma_flag) && (up->dma_enabled)) { ++ /* If reception has to be done through DMA. */ ++#ifdef DEBUG ++ printk(KERN_DEBUG"serial8250_handle_port ->\ ++ Proceeding to handle reception " \ ++ "interrupt through DMA operation.\n"); ++#endif ++ handle_dma_operation(up); ++ } else { ++#endif ++ ++ if ((status & (UART_LSR_DR | UART_LSR_BI)) ++#if defined(ENABLE_SERIAL_8250_PCH) && defined(ENABLE_PCH_DMA_FEATURE) ++ && (!up->dma_progress) ++#endif ++ ) ++ receive_chars(up, &status); ++#if defined(ENABLE_SERIAL_8250_PCH) && defined(ENABLE_PCH_DMA_FEATURE) ++ } ++#endif + check_modem_status(up); + if (status & UART_LSR_THRE) + transmit_chars(up); + + spin_unlock_irqrestore(&up->port.lock, flags); ++ ++#ifdef DEBUG ++ printk(KERN_DEBUG"serial8250_handle_port invoked.\n"); ++#endif + } + + /* +@@ -1575,6 +2100,26 @@ + + iir = serial_in(up, UART_IIR); + if (!(iir & UART_IIR_NO_INT)) { ++#if defined(ENABLE_SERIAL_8250_PCH) && defined(ENABLE_PCH_DMA_FEATURE) ++ /* Determing whether the receive FIFO is full. */ ++ if ((iir & UART_IIR_RDI) && !(iir & 0x8) && ++ ((up->port.flags & UPF_IOH_UART) != 0)) { ++ ++ up->dma_flag = 1; ++ ++#ifdef DEBUG ++ printk(KERN_DEBUG"serial8250_interrupt ->\ ++ DMA Mode enabled for reception.\n"); ++#endif ++ } else { ++ up->dma_flag = 0; ++#ifdef DEBUG ++ printk(KERN_DEBUG"serial8250_interrupt ->\ ++ DMA Mode disabled for reception.\n"); ++#endif ++ } ++#endif ++ + serial8250_handle_port(up); + + handled = 1; +@@ -1946,6 +2491,167 @@ + unsigned char lsr, iir; + int retval; + ++#if defined(ENABLE_SERIAL_8250_PCH) && defined(ENABLE_PCH_DMA_FEATURE) ++ /* Initialising the device for DMA support. */ ++ int dma_flag = 0; ++ up->dma_progress = 0; ++ up->dma_enabled = 0; ++ ++ if ((up->port.flags & UPF_IOH_UART) != 0) { ++ struct pci_dev pdev; ++ ++/* switch((up->port.flags & 0xE000000))*/ ++ switch ((up->port.flags & (UPF_IOH_UART | UPF_IOH_UART_BIT0 | ++ UPF_IOH_UART_BIT1))) { ++ case UPF_IOH_UART0: ++#ifdef DEBUG ++ printk(KERN_DEBUG"serial8250_startup ->\ ++ UART0 detected.\n"); ++#endif ++ pdev.device = PCI_DEVICE_ID_IOH_UART0; ++ up->port.mctrl |= TIOCM_RTS; ++ break; ++ ++ case UPF_IOH_UART1: ++#ifdef DEBUG ++ printk(KERN_DEBUG"serial8250_startup ->\ ++ UART1 detected.\n"); ++#endif ++ pdev.device = PCI_DEVICE_ID_IOH_UART1; ++ break; ++ ++ case UPF_IOH_UART2: ++#ifdef DEBUG ++ printk(KERN_DEBUG"serial8250_startup ->\ ++ UART2 detected.\n"); ++#endif ++ pdev.device = PCI_DEVICE_ID_IOH_UART2; ++ break; ++ ++ case UPF_IOH_UART3: ++#ifdef DEBUG ++ printk(KERN_DEBUG"serial8250_startup ->\ ++ UART3 detected.\n"); ++#endif ++ pdev.device = PCI_DEVICE_ID_IOH_UART3; ++ break; ++ ++ default: ++ break; ++ } ++ ++ /* Allocating space for DMA buffer. */ ++ up->rx_dma.buf = (u32)__get_free_page(GFP_KERNEL|GFP_DMA); ++ if (!(up->rx_dma.buf)) { ++ printk(KERN_ERR"serial8250_startup -> DMA buffer\ ++ allocation " \ ++ "failed for Rx DMA buffer.\n"); ++ return -ENOMEM; ++ } ++ ++ /* For transmission process. */ ++ up->tx_dma.buf = (u32)__get_free_page(GFP_KERNEL|GFP_DMA); ++ if (!(up->tx_dma.buf)) { ++ free_page(up->rx_dma.buf); ++ printk(KERN_ERR"serial8250_startup -> DMA buffer\ ++ allocation " \ ++ "failed for TX DMA buffer.\n"); ++ return -ENOMEM; ++ } ++ ++ /* For copying of transmit data. */ ++ up->buffer = (u32)__get_free_page(GFP_KERNEL|GFP_DMA); ++ if (!(up->buffer)) { ++ free_page(up->rx_dma.buf); ++ free_page(up->tx_dma.buf); ++ printk(KERN_ERR"serial8250_startup -> DMA buffer\ ++ allocation " \ ++ "failed for Buffer.\n"); ++ return -ENOMEM; ++ } ++ ++ up->rx_dma.size = PAGE_SIZE; ++ up->tx_dma.size = PAGE_SIZE; ++ ++ /* Requesting for DMA channel for reception. */ ++ up->rx_dma.channel = ioh_request_dma(&pdev, ++ IOH_DMA_RX_DATA_REQ0); ++ if (up->rx_dma.channel < 0) { ++ free_page(up->rx_dma.buf); ++ free_page(up->tx_dma.buf); ++ free_page(up->buffer); ++ up->rx_dma.buf = 0; ++ up->tx_dma.buf = 0; ++ up->buffer = 0; ++ ++ printk(KERN_ERR"serial8250_startup -> DMA channel\ ++ allocation for " \ ++ "reception failed.\n"); ++ return -EIO; ++ } ++ ++ /* Requesting DMA channel for transmission. */ ++ up->tx_dma.channel = ioh_request_dma(&pdev, ++ IOH_DMA_TX_DATA_REQ0); ++ if (up->tx_dma.channel < 0) { ++ free_page(up->rx_dma.buf); ++ free_page(up->tx_dma.buf); ++ free_page(up->buffer); ++ up->rx_dma.buf = 0; ++ up->tx_dma.buf = 0; ++ up->buffer = 0; ++ ioh_free_dma(up->rx_dma.channel); ++ ++ printk(KERN_ERR"serial8250_startup -> DMA channel\ ++ allocation for " \ ++ "transmission failed.\n"); ++ return -EIO; ++ } ++ ++ /* Performing DMA settings for reception. */ ++ { ++ u32 in_address; ++ u32 out_address; ++ u32 size; ++ int channel = up->rx_dma.channel; ++ struct ioh_dma_mode_param mode = { ++ .TransferDirection = IOH_DMA_DIR_IN_TO_OUT, ++ .DMASizeType = IOH_DMA_SIZE_TYPE_8BIT, ++ .DMATransferMode = DMA_ONE_SHOT_MODE ++ }; ++ ++ /* Mapping the DMA buffer to DMA accessible area and ++ obtaining its base address. */ ++ out_address = dma_map_single(up->port.dev, ++ (void *)up->rx_dma.buf, ++ up->rx_dma.size, ++ DMA_FROM_DEVICE); ++ in_address = up->port.mapbase + ++ (map_8250_in_reg(up, UART_RX)); ++ size = up->rx_fifo_size; ++ up->rx_dma.phy_addr = out_address; ++ ++ /* Setting the DMA settings. */ ++ (void)ioh_set_dma_mode(channel, mode); ++ (void)ioh_set_dma_addr(channel, in_address, ++ out_address); ++ (void)ioh_set_dma_count(channel, size); ++ (void)ioh_dma_set_callback(channel, ioh_dma_rx_callback, ++ (u32)up); ++ } ++ ++ dma_flag = 1; ++ ++#ifdef DEBUG ++ printk(KERN_DEBUG"serial8250_startup -> Buffer Allocation\ ++ successful and DMA " \ ++ "channels obtained are Reception: %d\ ++ Transmission: %d.\n", \ ++ up->rx_dma.channel, up->tx_dma.channel); ++#endif ++ } ++#endif ++ + up->capabilities = uart_config[up->port.type].flags; + up->mcr = 0; + +@@ -1996,6 +2702,21 @@ + (serial_inp(up, UART_LSR) == 0xff)) { + printk(KERN_INFO "ttyS%d: LSR safety check engaged!\n", + serial_index(&up->port)); ++ ++#if defined(ENABLE_SERIAL_8250_PCH) && defined(ENABLE_PCH_DMA_FEATURE) ++ /* Releasing the DMA resources on failure.*/ ++ if (dma_flag == 1) { ++ ioh_free_dma(up->rx_dma.channel); ++ ioh_free_dma(up->tx_dma.channel); ++ free_page(up->rx_dma.buf); ++ free_page(up->tx_dma.buf); ++ free_page(up->buffer); ++ up->rx_dma.buf = 0; ++ up->tx_dma.buf = 0; ++ up->buffer = 0; ++ } ++#endif ++ + return -ENODEV; + } + +@@ -2008,9 +2729,11 @@ + serial_outp(up, UART_LCR, 0xbf); + + fctr = serial_inp(up, UART_FCTR) & ~(UART_FCTR_RX|UART_FCTR_TX); +- serial_outp(up, UART_FCTR, fctr | UART_FCTR_TRGD | UART_FCTR_RX); ++ serial_outp(up, UART_FCTR, fctr | UART_FCTR_TRGD | ++ UART_FCTR_RX); + serial_outp(up, UART_TRG, UART_TRG_96); +- serial_outp(up, UART_FCTR, fctr | UART_FCTR_TRGD | UART_FCTR_TX); ++ serial_outp(up, UART_FCTR, fctr | UART_FCTR_TRGD | ++ UART_FCTR_TX); + serial_outp(up, UART_TRG, UART_TRG_96); + + serial_outp(up, UART_LCR, 0); +@@ -2076,8 +2799,22 @@ + mod_timer(&up->timer, jiffies + poll_timeout(up->port.timeout)); + } else { + retval = serial_link_irq_chain(up); +- if (retval) ++ if (retval) { ++#if defined(ENABLE_SERIAL_8250_PCH) && defined(ENABLE_PCH_DMA_FEATURE) ++ /* Releasing the DMA resources on failure.*/ ++ if (dma_flag == 1) { ++ ioh_free_dma(up->rx_dma.channel); ++ ioh_free_dma(up->tx_dma.channel); ++ free_page(up->rx_dma.buf); ++ free_page(up->tx_dma.buf); ++ free_page(up->buffer); ++ up->rx_dma.buf = 0; ++ up->tx_dma.buf = 0; ++ up->buffer = 0; ++ } ++ #endif + return retval; ++ } + } + + /* +@@ -2124,7 +2861,8 @@ + if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) { + if (!(up->bugs & UART_BUG_TXEN)) { + up->bugs |= UART_BUG_TXEN; +- pr_debug("ttyS%d - enabling bad tx status workarounds\n", ++ pr_debug("ttyS%d - enabling bad tx status\ ++ workarounds\n", + serial_index(port)); + } + } else { +@@ -2172,6 +2910,31 @@ + struct uart_8250_port *up = (struct uart_8250_port *)port; + unsigned long flags; + ++#if defined(ENABLE_SERIAL_8250_PCH) && defined(ENABLE_PCH_DMA_FEATURE) ++ /* Releasing the DMA resources on exit.*/ ++ if ((up->port.flags & UPF_IOH_UART) != 0) { ++ if (up->rx_dma.channel >= 0) ++ ioh_free_dma(up->rx_dma.channel); ++ if (up->tx_dma.channel >= 0) ++ ioh_free_dma(up->tx_dma.channel); ++ ++ if (up->rx_dma.buf) ++ free_page(up->rx_dma.buf); ++ if (up->tx_dma.buf) ++ free_page(up->tx_dma.buf); ++ if (up->buffer) ++ free_page(up->buffer); ++ ++ up->rx_dma.buf = 0; ++ up->tx_dma.buf = 0; ++ up->buffer = 0; ++ ++#ifdef DEBUG ++ printk(KERN_DEBUG"serial8250_shutdown -> DMA buffers and\ ++ channels released.\n"); ++#endif ++ } ++#endif + /* + * Disable interrupts from this port + */ +@@ -2214,7 +2977,8 @@ + serial_unlink_irq_chain(up); + } + +-static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int baud) ++static unsigned int serial8250_get_divisor(struct uart_port *port, ++ unsigned int baud) + { + unsigned int quot; + +@@ -2242,6 +3006,7 @@ + unsigned char cval, fcr = 0; + unsigned long flags; + unsigned int baud, quot; ++ unsigned int bdrate; + + switch (termios->c_cflag & CSIZE) { + case CS5: +@@ -2278,6 +3043,11 @@ + port->uartclk / 16); + quot = serial8250_get_divisor(port, baud); + ++#ifdef DEBUG ++ printk(KERN_DEBUG "IOH UART LOG:max_baud: %d\n,baud :%d\n quot:%d\n" ++ , max_baud, baud, quot); ++#endif ++ + /* + * Oxford Semi 952 rev B workaround + */ +@@ -2285,12 +3055,37 @@ + quot++; + + if (up->capabilities & UART_CAP_FIFO && up->port.fifosize > 1) { +- if (baud < 2400) ++ if (baud < 2400) { + fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1; +- else +- fcr = uart_config[up->port.type].fcr; ++ ++#ifdef ENABLE_SERIAL_8250_PCH ++ if ((up->port.flags & UPF_IOH_UART) != 0) ++ /*This enables 256 byte FIFO ++ for UART 0.*/ ++ fcr |= UART_FCR7_64BYTE; ++ ++#endif ++ } else ++ fcr = uart_config[up->port.type].fcr; + } + ++#if defined(ENABLE_SERIAL_8250_PCH) && defined(ENABLE_PCH_DMA_FEATURE) ++ /* Deciding whether to use DMA feature or not.*/ ++ if ((baud >= 38400) && ((up->port.flags & UPF_IOH_UART) != 0)) ++ up->dma_enabled = 1; ++ else ++ up->dma_enabled = 0; ++ ++ ++ get_rx_fifo_size(up, fcr); ++ ++#ifdef DEBUG ++ printk(KERN_DEBUG"serial8250_set_termios -> The Rx fifo size is: %u\n", ++ up->rx_fifo_size); ++#endif ++ ++#endif ++ + /* + * MCR-based auto flow control. When AFE is enabled, RTS will be + * deasserted when the receive FIFO contains more characters than +@@ -2409,8 +3204,22 @@ + serial8250_set_mctrl(&up->port, up->port.mctrl); + spin_unlock_irqrestore(&up->port.lock, flags); + /* Don't rewrite B0 */ +- if (tty_termios_baud_rate(termios)) ++ ++ bdrate = tty_termios_baud_rate(termios); ++ ++#ifdef DEBUG ++ printk(KERN_DEBUG "tty_termios_baud_rate value:%d\n", bdrate); ++#endif ++ ++ if (bdrate) { + tty_termios_encode_baud_rate(termios, baud, baud); ++ ++#ifdef DEBUG ++ printk(KERN_DEBUG "termios->c_ispeed:%d\n,\ ++ termios->c_ospeed:%d\n " ++ , termios->c_ispeed, termios->c_ospeed); ++#endif ++ } + } + + static void +@@ -2580,18 +3389,24 @@ + if (ret < 0) + probeflags &= ~PROBE_RSA; + ++ + if (up->port.iotype != up->cur_iotype) + set_io_from_upio(port); + ++ + if (flags & UART_CONFIG_TYPE) + autoconfig(up, probeflags); ++ + if (up->port.type != PORT_UNKNOWN && flags & UART_CONFIG_IRQ) + autoconfig_irq(up); + ++ + if (up->port.type != PORT_RSA && probeflags & PROBE_RSA) + serial8250_release_rsa_resource(up); ++ + if (up->port.type == PORT_UNKNOWN) + serial8250_release_std_resource(up); ++ + } + + static int +@@ -2686,6 +3501,7 @@ + up->port.regshift = old_serial_port[i].iomem_reg_shift; + set_io_from_upio(&up->port); + up->port.irqflags |= irqflag; ++ + } + } + +@@ -2967,7 +3783,8 @@ + port.irqflags |= irqflag; + ret = serial8250_register_port(&port); + if (ret < 0) { +- dev_err(&dev->dev, "unable to register port at index %d " ++ dev_err(&dev->dev, "unable to register port at\ ++ index %d " + "(IO%lx MEM%llx IRQ%d): %d\n", i, + p->iobase, (unsigned long long)p->mapbase, + p->irq, ret); +@@ -3044,7 +3861,8 @@ + */ + static DEFINE_MUTEX(serial_mutex); + +-static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port *port) ++static ++struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port *port) + { + int i; + +@@ -3251,7 +4069,8 @@ + " (unsafe)"); + + module_param(nr_uarts, uint, 0644); +-MODULE_PARM_DESC(nr_uarts, "Maximum number of UARTs supported. (1-" __MODULE_STRING(CONFIG_SERIAL_8250_NR_UARTS) ")"); ++MODULE_PARM_DESC(nr_uarts, "Maximum number of UARTs supported. \ ++ (1-" __MODULE_STRING(CONFIG_SERIAL_8250_NR_UARTS) ")"); + + module_param(skip_txen_test, uint, 0644); + MODULE_PARM_DESC(skip_txen_test, "Skip checking for the TXEN bug at init time"); +diff -urN linux-2.6.33.1/drivers/serial/8250_pch.h topcliff-2.6.33.1/drivers/serial/8250_pch.h +--- linux-2.6.33.1/drivers/serial/8250_pch.h 1970-01-01 09:00:00.000000000 +0900 ++++ topcliff-2.6.33.1/drivers/serial/8250_pch.h 2010-03-23 10:34:44.000000000 +0900 +@@ -0,0 +1,57 @@ ++/*! ++ * @file 8250_pch.h ++ * @brief Provides the macro definitions used by all files. ++ * @version 1.0.0.0 ++ * @section ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; version 2 of the License. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. ++ */ ++ ++/* ++ * History: ++ * Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD. ++ * All rights reserved. ++ * ++ * created: ++ * OKISEMI 03/16/2010 ++ * ++ */ ++ ++#ifndef __IOH_8250_PCH_H__ ++#define __IOH_8250_PCH_H__ ++ ++#define PORT_IOH_256FIFO 128 /* IOH UART with 256 byte FIFO */ ++#define PORT_IOH_64FIFO 129 /* IOH UART with 64 byte FIFO */ ++ ++/* flags for IOH port detection */ ++/* The below fields are used to identify the IOH UART port 0 to 3 */ ++#define UPF_IOH_UART_BIT0 ((__force upf_t) (1 << 17)) ++#define UPF_IOH_UART_BIT1 ((__force upf_t) (1 << 18)) ++ ++#define UPF_IOH_UART ((__force upf_t) (1 << 19)) ++#define UPF_IOH_UART0 ((UPF_IOH_UART) | (0)) ++#define UPF_IOH_UART1 ((UPF_IOH_UART) | ((__force upf_t) (UPF_IOH_UART_BIT0))) ++#define UPF_IOH_UART2 ((UPF_IOH_UART) | ((__force upf_t) (UPF_IOH_UART_BIT1))) ++#define UPF_IOH_UART3 ((UPF_IOH_UART) | ((__force upf_t) (UPF_IOH_UART_BIT0 |\ ++ UPF_IOH_UART_BIT1))) ++#define UPF_IOH_UART_64_FIFO ((__force upf_t) (UPF_IOH_UART3)) ++ ++#define UART_FCR7_256BYTE 0x20 /* Go into 256 byte FIFO mode (IOH UART) */ ++ ++/* Intel IOH GE UART PCI device IDs */ ++#define PCI_DEVICE_ID_IOH_UART0 (0x8811) ++#define PCI_DEVICE_ID_IOH_UART1 (0x8812) ++#define PCI_DEVICE_ID_IOH_UART2 (0x8813) ++#define PCI_DEVICE_ID_IOH_UART3 (0x8814) ++ ++#endif +diff -urN linux-2.6.33.1/drivers/serial/8250_pci.c topcliff-2.6.33.1/drivers/serial/8250_pci.c +--- linux-2.6.33.1/drivers/serial/8250_pci.c 2010-03-16 01:09:39.000000000 +0900 ++++ topcliff-2.6.33.1/drivers/serial/8250_pci.c 2010-03-23 10:34:44.000000000 +0900 +@@ -14,6 +14,7 @@ + #include <linux/module.h> + #include <linux/init.h> + #include <linux/pci.h> ++#include <linux/pci_ids.h> + #include <linux/string.h> + #include <linux/kernel.h> + #include <linux/slab.h> +@@ -27,7 +28,7 @@ + #include <asm/io.h> + + #include "8250.h" +- ++#include "8250_pch.h" + #undef SERIAL_DEBUG_PCI + + /* +@@ -726,6 +727,87 @@ + #define NI8430_PORTCON 0x0f + #define NI8430_PORTCON_TXVR_ENABLE (1 << 3) + ++#if defined(ENABLE_SERIAL_8250_PCH) ++ ++static int ++pci_ioh_init(struct pci_dev *dev) ++{ ++ int retval = 0; ++ ++#ifdef DEBUG ++ printk(KERN_DEBUG "IOH UART LOG:function pci_ioh_init invoked \n"); ++ ++ printk(KERN_DEBUG "IOH UART LOG:function pci_ioh_init->pci_enable_wake invoked \n"); ++#endif ++ ++ /* disable Wake on UART */ ++ pci_enable_wake(dev, PCI_D3hot, 0); ++ ++#ifdef DEBUG ++ printk(KERN_DEBUG "IOH UART LOG:function pci_ioh_init return = %d\n", ++ retval); ++#endif ++ ++ return retval; ++} ++ ++static int ++pci_ioh_setup(struct serial_private *priv, const struct pciserial_board *board, ++ struct uart_port *port, int idx) ++{ ++ int retval = 1 ; ++ unsigned int bar = 0; ++ unsigned int offset = 0; ++ ++ if (idx == 0) { ++ /* IOH UART has only 1 channel per device */ ++ switch (priv->dev->device) { ++ case PCI_DEVICE_ID_IOH_UART0: ++ port->flags |= UPF_IOH_UART0; ++ break; ++ ++ case PCI_DEVICE_ID_IOH_UART1: ++ port->flags |= UPF_IOH_UART1; ++ break; ++ ++ case PCI_DEVICE_ID_IOH_UART2: ++ port->flags |= UPF_IOH_UART2; ++ break; ++ ++ case PCI_DEVICE_ID_IOH_UART3: ++ port->flags |= UPF_IOH_UART3; ++ break; ++ ++ default: ++ break; ++ } ++ ++ retval = setup_port(priv, port, bar, offset, board->reg_shift); ++ ++ #ifdef ENABLE_PCH_DMA_FEATURE ++ /* Obtaing the Memory Map base for DMA operations. */ ++ port->mapbase = pci_resource_start(priv->dev, 1); ++ #ifdef DEBUG ++ printk(KERN_DEBUG"pci_ioh_setup -> The Map Base has been obtained.\n"); ++ #endif ++ #endif ++ } ++ ++ ++#ifdef DEBUG ++ printk(KERN_DEBUG "pci_ioh_setup -> Function pci_ioh_setup invoked \n"); ++ printk(KERN_DEBUG "pci_ioh_setup -> board.base_baud = %d, flags = %d,\ ++ num_ports = %d,reg_shift = %d\n", ++ board->base_baud, board->flags, ++ board->num_ports, board->reg_shift); ++ printk(KERN_DEBUG "pci_ioh_setup -> port->flags =%x\n", port->flags); ++ printk(KERN_DEBUG "Function pci_ioh_setup return = %d\n", retval); ++ ++#endif ++ return retval; ++} ++#endif ++ + static int + pci_ni8430_setup(struct serial_private *priv, + const struct pciserial_board *board, +@@ -918,7 +1000,8 @@ + (dev->device & 0xF000) != 0xC000) + return 0; + +- p = pci_iomap(dev, 0, 5); ++ /*p = pci_iomap(dev, 0, 5);*/ ++ p = pci_iomap(dev, 1, 5); + if (p == NULL) + return -ENOMEM; + +@@ -1393,6 +1476,43 @@ + .setup = pci_default_setup, + }, + /* ++ * IOH UART ++ */ ++#if defined(ENABLE_SERIAL_8250_PCH) ++ { ++ .vendor = PCI_VENDOR_ID_INTEL, ++ .device = PCI_DEVICE_ID_IOH_UART0, ++ .subvendor = PCI_ANY_ID, ++ .subdevice = PCI_ANY_ID, ++ .init = pci_ioh_init, ++ .setup = pci_ioh_setup, ++ }, ++ { ++ .vendor = PCI_VENDOR_ID_INTEL, ++ .device = PCI_DEVICE_ID_IOH_UART1, ++ .subvendor = PCI_ANY_ID, ++ .subdevice = PCI_ANY_ID, ++ .init = pci_ioh_init, ++ .setup = pci_ioh_setup, ++ }, ++ { ++ .vendor = PCI_VENDOR_ID_INTEL, ++ .device = PCI_DEVICE_ID_IOH_UART2, ++ .subvendor = PCI_ANY_ID, ++ .subdevice = PCI_ANY_ID, ++ .init = pci_ioh_init, ++ .setup = pci_ioh_setup, ++ }, ++ { ++ .vendor = PCI_VENDOR_ID_INTEL, ++ .device = PCI_DEVICE_ID_IOH_UART3, ++ .subvendor = PCI_ANY_ID, ++ .subdevice = PCI_ANY_ID, ++ .init = pci_ioh_init, ++ .setup = pci_ioh_setup, ++ }, ++#endif ++ /* + * Default "match everything" terminator entry + */ + { +@@ -1571,6 +1691,10 @@ + pbn_ADDIDATA_PCIe_2_3906250, + pbn_ADDIDATA_PCIe_4_3906250, + pbn_ADDIDATA_PCIe_8_3906250, ++#if defined(ENABLE_SERIAL_8250_PCH) ++ pbn_ioh_uart_8L_256FIFO, /* ioh 8 Line UART with 256 byte FIFO */ ++ pbn_ioh_uart_2L_64FIFO /* ioh 2 Line UART with 64 byte FIFO */ ++#endif + }; + + /* +@@ -2228,6 +2352,27 @@ + .uart_offset = 0x200, + .first_offset = 0x1000, + }, ++ ++#if defined(ENABLE_SERIAL_8250_PCH) ++ ++ /* ++ * IOH UART ++ */ ++ [pbn_ioh_uart_8L_256FIFO] = { ++ .flags = FL_BASE0, ++ .num_ports = 1, ++ .base_baud = 115200, /* OKISEMI For LSI */ ++ .reg_shift = 0, ++ }, ++ ++ [pbn_ioh_uart_2L_64FIFO] = { ++ .flags = FL_BASE0, ++ .num_ports = 1, ++ .base_baud = 115200, /* OKISEMI For LSI*/ ++ .reg_shift = 0, ++ }, ++#endif ++ + }; + + static const struct pci_device_id softmodem_blacklist[] = { +@@ -2473,8 +2618,20 @@ + return -EINVAL; + } + ++#ifdef DEBUG ++ printk(KERN_DEBUG "IOH UART LOG:function pciserial_init_one ent->vendor" ++ " = %x\n, ent->device = %x, ent->driver_data = %ld\n ", ++ ent->vendor, ent->device, ent->driver_data); ++#endif ++ + board = &pci_boards[ent->driver_data]; + ++#ifdef DEBUG ++ printk(KERN_DEBUG "IOH UART LOG:function pciserial_init_one board->" ++ "base_baud = %u\n, board->flags = %d, board->num_ports = %d\n " ++ , board->base_baud, board->flags, board->num_ports); ++#endif ++ + rc = pci_enable_device(dev); + if (rc) + return rc; +@@ -2540,6 +2697,17 @@ + if (priv) + pciserial_suspend_ports(priv); + ++#if defined(ENABLE_SERIAL_8250_PCH) ++ ++#ifdef DEBUG ++ printk(KERN_DEBUG "IOH UART LOG:pciserial_suspend_one->pci_enable_wake" ++ "invoked \n"); ++#endif ++ ++ ++ pci_enable_wake(dev, PCI_D3hot, 1); ++#endif ++ + pci_save_state(dev); + pci_set_power_state(dev, pci_choose_state(dev, state)); + return 0; +@@ -2561,6 +2729,17 @@ + /* FIXME: We cannot simply error out here */ + if (err) + printk(KERN_ERR "pciserial: Unable to re-enable ports, trying to continue.\n"); ++ ++#if defined(ENABLE_SERIAL_8250_PCH) ++ ++#ifdef DEBUG ++ printk(KERN_DEBUG "IOH UART LOG:pciserial_resume_one->pci_enable_wake" ++ "invoked \n"); ++#endif ++ ++ pci_enable_wake(dev, PCI_D3hot, 0); ++#endif ++ + pciserial_resume_ports(priv); + } + return 0; +@@ -3649,6 +3828,48 @@ + 0, 0, pbn_b0_1_115200 }, + + /* ++ * IOH UART ++ */ ++#if defined(ENABLE_SERIAL_8250_PCH) ++ ++ { PCI_VENDOR_ID_INTEL, ++ /*device id for ioh uart with 8 i/o lines and 256 byte fifo. */ ++ PCI_DEVICE_ID_IOH_UART0, ++ PCI_ANY_ID, ++ PCI_ANY_ID, ++ 0, ++ 0, ++ pbn_ioh_uart_8L_256FIFO }, ++ ++ { PCI_VENDOR_ID_INTEL, ++ /*device id for ioh uart with 2 i/o lines and 256 byte fifo. */ ++ PCI_DEVICE_ID_IOH_UART1, ++ PCI_ANY_ID, ++ PCI_ANY_ID, ++ 0, ++ 0, ++ pbn_ioh_uart_2L_64FIFO }, ++ ++ { PCI_VENDOR_ID_INTEL, ++ /*device id for ioh uart with 8 i/o lines and 64 byte fifo. */ ++ PCI_DEVICE_ID_IOH_UART2, ++ PCI_ANY_ID, ++ PCI_ANY_ID, ++ 0, ++ 0, ++ pbn_ioh_uart_2L_64FIFO }, ++ ++ { PCI_VENDOR_ID_INTEL, ++ /*device id for ioh uart with 2 i/o lines and 64 byte fifo. */ ++ PCI_DEVICE_ID_IOH_UART3, ++ PCI_ANY_ID, ++ PCI_ANY_ID, ++ 0, ++ 0, ++ pbn_ioh_uart_2L_64FIFO }, ++#endif ++ ++ /* + * These entries match devices with class COMMUNICATION_SERIAL, + * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL + */ +diff -urN linux-2.6.33.1/drivers/serial/Kconfig topcliff-2.6.33.1/drivers/serial/Kconfig +--- linux-2.6.33.1/drivers/serial/Kconfig 2010-03-16 01:09:39.000000000 +0900 ++++ topcliff-2.6.33.1/drivers/serial/Kconfig 2010-03-23 10:34:44.000000000 +0900 +@@ -89,6 +89,21 @@ + disable this feature if you only need legacy serial support. + Saves about 9K. + ++config SERIAL_8250_PCH ++ tristate "PCH PCI serial device support" ++ depends on SERIAL_8250 && PCI && SERIAL_8250_PCI ++ default SERIAL_8250_PCI ++ help ++ This makes the PCH PCI serial driver to support high speed PCH serial ports. ++ ++config SERIAL_8250_PCH_DMA ++ bool "Enable DMA mode of PCH PCI serial device" ++ depends on SERIAL_8250_PCH ++ select PCH_UART_DMA ++ default y ++ help ++ This makes the PCH PCI serial driver with DMA mode. ++ + config SERIAL_8250_PNP + tristate "8250/16550 PNP device support" if EMBEDDED + depends on SERIAL_8250 && PNP +diff -urN linux-2.6.33.1/drivers/serial/Makefile topcliff-2.6.33.1/drivers/serial/Makefile +--- linux-2.6.33.1/drivers/serial/Makefile 2010-03-16 01:09:39.000000000 +0900 ++++ topcliff-2.6.33.1/drivers/serial/Makefile 2010-03-23 10:34:44.000000000 +0900 +@@ -1,6 +1,17 @@ + # + # Makefile for the kernel serial device drivers. + # ++# ++#This is needed to enable ioh dma# ++#EXTRA_CFLAGS +=-DENABLE_IOH_DMA_FEATURE ++ifdef CONFIG_SERIAL_8250_PCH ++EXTRA_CFLAGS +=-DENABLE_SERIAL_8250_PCH ++endif ++ ++ifdef CONFIG_PCH_UART_DMA ++EXTRA_CFLAGS +=-DENABLE_PCH_DMA_FEATURE ++EXTRA_CFLAGS +=-Idrivers/dma/pch_dma/ ++endif + + obj-$(CONFIG_SERIAL_CORE) += serial_core.o + obj-$(CONFIG_SERIAL_21285) += 21285.o |