From a79220b7633b3926a9bd3527bdac3f04dbe6845c Mon Sep 17 00:00:00 2001 From: Matej Kenda Date: Mon, 5 Mar 2007 13:06:40 +0100 Subject: [ARM] 4246/1: i2c-pxa: add adapter class to platform specific data Reposted patch for kernel 2.6.21-rc2. The driver i2c-pxa doesn't set the class member in i2c_adapter, which is used to register the I2C adapter. The hwmon (sensors) drivers (e.g. adm1021) that are connected to a i2c-pxa adapter don't attach because they expect that the adapter supports class I2C_CLASS_HWMON. This patch adds functionality to allow platforms to set the class and pass it as platform_data to the i2c-pxa driver. Sample usage in platform code: static struct i2c_pxa_platform_data my_i2c_platform_data = { .class = I2C_CLASS_HWMON }; static void __init my_platform_init(void) { (void) platform_add_devices(devices, ARRAY_SIZE(devices)); pxa_set_i2c_info(&my_i2c_platform_data); } Signed-off-by: Matej Kenda Signed-off-by: Russell King --- drivers/i2c/busses/i2c-pxa.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index 14e83d0aac8c..11c7477a0ffa 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c @@ -839,9 +839,7 @@ static int i2c_pxa_probe(struct platform_device *dev) { struct pxa_i2c *i2c = &i2c_pxa; struct resource *res; -#ifdef CONFIG_I2C_PXA_SLAVE struct i2c_pxa_platform_data *plat = dev->dev.platform_data; -#endif int ret; int irq; @@ -911,6 +909,10 @@ static int i2c_pxa_probe(struct platform_device *dev) i2c->adap.algo_data = i2c; i2c->adap.dev.parent = &dev->dev; + if (plat) { + i2c->adap.class = plat->class; + } + ret = i2c_add_adapter(&i2c->adap); if (ret < 0) { printk(KERN_INFO "I2C: Failed to add bus\n"); -- cgit v1.2.2 From 7053acbd78336abf5d4bc3d8a875a03624cfb83f Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Thu, 5 Apr 2007 04:07:20 +0100 Subject: [ARM] 4304/1: removes the unnecessary bit number from CKENnn_XXXX This patch removes the unnecessary bit number from CKENnn_XXXX definitions for PXA, so that CKEN0_PWM0 --> CKEN_PWM0 CKEN1_PWM1 --> CKEN_PWM1 ... CKEN24_CAMERA --> CKEN_CAMERA The reasons for the change of these defitions are: 1. they do not scale - they are currently valid for pxa2xx, but definitely not valid for pxa3xx, e.g., pxa3xx has bit 3 for camera instead of bit 24 2. they are unnecessary - the peripheral name within the definition has already announced its usage, we don't need those bit numbers to know which peripheral we are going to enable/disable clock for 3. they are inconvenient - think about this: a driver programmer for pxa has to remember which bit in the CKEN register to turn on/off Another change in the patch is to make the definitions equal to its clock bit index, so that #define CKEN_CAMERA (24) instead of #define CKEN_CAMERA (1 << 24) this change, however, will add a run-time bit shift operation in pxa_set_cken(), but the benefit of this change is that it scales when bit index exceeds 32, e.g., pxa3xx has two registers CKENA and CKENB, totally 64 bit for this, suppose CAMERA clock enabling bit is CKENB:10, one can simply define CKEN_CAMERA to be (32 + 10) and so that pxa_set_cken() need minimum change to adapt to that. Signed-off-by: eric miao Signed-off-by: Russell King --- drivers/i2c/busses/i2c-pxa.c | 12 ++++++------ drivers/mmc/pxamci.c | 4 ++-- drivers/net/irda/pxaficp_ir.c | 12 ++++++------ drivers/serial/pxa.c | 8 ++++---- drivers/usb/gadget/pxa2xx_udc.c | 4 ++-- drivers/usb/host/ohci-pxa27x.c | 4 ++-- drivers/video/pxafb.c | 4 ++-- 7 files changed, 24 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index 11c7477a0ffa..4443d3bb3fbf 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c @@ -887,14 +887,14 @@ static int i2c_pxa_probe(struct platform_device *dev) pxa_gpio_mode(GPIO117_I2CSCL_MD); pxa_gpio_mode(GPIO118_I2CSDA_MD); #endif - pxa_set_cken(CKEN14_I2C, 1); + pxa_set_cken(CKEN_I2C, 1); break; #ifdef CONFIG_PXA27x case 1: local_irq_disable(); PCFR |= PCFR_PI2CEN; local_irq_enable(); - pxa_set_cken(CKEN15_PWRI2C, 1); + pxa_set_cken(CKEN_PWRI2C, 1); #endif } @@ -935,11 +935,11 @@ eadapt: ereqirq: switch (dev->id) { case 0: - pxa_set_cken(CKEN14_I2C, 0); + pxa_set_cken(CKEN_I2C, 0); break; #ifdef CONFIG_PXA27x case 1: - pxa_set_cken(CKEN15_PWRI2C, 0); + pxa_set_cken(CKEN_PWRI2C, 0); local_irq_disable(); PCFR &= ~PCFR_PI2CEN; local_irq_enable(); @@ -962,11 +962,11 @@ static int i2c_pxa_remove(struct platform_device *dev) free_irq(i2c->irq, i2c); switch (dev->id) { case 0: - pxa_set_cken(CKEN14_I2C, 0); + pxa_set_cken(CKEN_I2C, 0); break; #ifdef CONFIG_PXA27x case 1: - pxa_set_cken(CKEN15_PWRI2C, 0); + pxa_set_cken(CKEN_PWRI2C, 0); local_irq_disable(); PCFR &= ~PCFR_PI2CEN; local_irq_enable(); diff --git a/drivers/mmc/pxamci.c b/drivers/mmc/pxamci.c index 9774fc68b61a..fca894e55f4a 100644 --- a/drivers/mmc/pxamci.c +++ b/drivers/mmc/pxamci.c @@ -369,14 +369,14 @@ static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) if (CLOCKRATE / clk > ios->clock) clk <<= 1; host->clkrt = fls(clk) - 1; - pxa_set_cken(CKEN12_MMC, 1); + pxa_set_cken(CKEN_MMC, 1); /* * we write clkrt on the next command */ } else { pxamci_stop_clock(host); - pxa_set_cken(CKEN12_MMC, 0); + pxa_set_cken(CKEN_MMC, 0); } if (host->power_mode != ios->power_mode) { diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c index 2272156af31e..d6d5361f0936 100644 --- a/drivers/net/irda/pxaficp_ir.c +++ b/drivers/net/irda/pxaficp_ir.c @@ -134,7 +134,7 @@ static int pxa_irda_set_speed(struct pxa_irda *si, int speed) DCSR(si->rxdma) &= ~DCSR_RUN; /* disable FICP */ ICCR0 = 0; - pxa_set_cken(CKEN13_FICP, 0); + pxa_set_cken(CKEN_FICP, 0); /* set board transceiver to SIR mode */ si->pdata->transceiver_mode(si->dev, IR_SIRMODE); @@ -144,7 +144,7 @@ static int pxa_irda_set_speed(struct pxa_irda *si, int speed) pxa_gpio_mode(GPIO47_STTXD_MD); /* enable the STUART clock */ - pxa_set_cken(CKEN5_STUART, 1); + pxa_set_cken(CKEN_STUART, 1); } /* disable STUART first */ @@ -169,7 +169,7 @@ static int pxa_irda_set_speed(struct pxa_irda *si, int speed) /* disable STUART */ STIER = 0; STISR = 0; - pxa_set_cken(CKEN5_STUART, 0); + pxa_set_cken(CKEN_STUART, 0); /* disable FICP first */ ICCR0 = 0; @@ -182,7 +182,7 @@ static int pxa_irda_set_speed(struct pxa_irda *si, int speed) pxa_gpio_mode(GPIO47_ICPTXD_MD); /* enable the FICP clock */ - pxa_set_cken(CKEN13_FICP, 1); + pxa_set_cken(CKEN_FICP, 1); si->speed = speed; pxa_irda_fir_dma_rx_start(si); @@ -593,7 +593,7 @@ static void pxa_irda_shutdown(struct pxa_irda *si) /* disable STUART SIR mode */ STISR = 0; /* disable the STUART clock */ - pxa_set_cken(CKEN5_STUART, 0); + pxa_set_cken(CKEN_STUART, 0); /* disable DMA */ DCSR(si->txdma) &= ~DCSR_RUN; @@ -601,7 +601,7 @@ static void pxa_irda_shutdown(struct pxa_irda *si) /* disable FICP */ ICCR0 = 0; /* disable the FICP clock */ - pxa_set_cken(CKEN13_FICP, 0); + pxa_set_cken(CKEN_FICP, 0); DRCMR17 = 0; DRCMR18 = 0; diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c index d403aaa55092..e9c6cb391a23 100644 --- a/drivers/serial/pxa.c +++ b/drivers/serial/pxa.c @@ -717,7 +717,7 @@ struct uart_ops serial_pxa_pops = { static struct uart_pxa_port serial_pxa_ports[] = { { /* FFUART */ .name = "FFUART", - .cken = CKEN6_FFUART, + .cken = CKEN_FFUART, .port = { .type = PORT_PXA, .iotype = UPIO_MEM, @@ -731,7 +731,7 @@ static struct uart_pxa_port serial_pxa_ports[] = { }, }, { /* BTUART */ .name = "BTUART", - .cken = CKEN7_BTUART, + .cken = CKEN_BTUART, .port = { .type = PORT_PXA, .iotype = UPIO_MEM, @@ -745,7 +745,7 @@ static struct uart_pxa_port serial_pxa_ports[] = { }, }, { /* STUART */ .name = "STUART", - .cken = CKEN5_STUART, + .cken = CKEN_STUART, .port = { .type = PORT_PXA, .iotype = UPIO_MEM, @@ -759,7 +759,7 @@ static struct uart_pxa_port serial_pxa_ports[] = { }, }, { /* HWUART */ .name = "HWUART", - .cken = CKEN4_HWUART, + .cken = CKEN_HWUART, .port = { .type = PORT_PXA, .iotype = UPIO_MEM, diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c index f01890dc8751..018b0d65765a 100644 --- a/drivers/usb/gadget/pxa2xx_udc.c +++ b/drivers/usb/gadget/pxa2xx_udc.c @@ -1497,7 +1497,7 @@ static void udc_disable(struct pxa2xx_udc *dev) #ifdef CONFIG_ARCH_PXA /* Disable clock for USB device */ - pxa_set_cken(CKEN11_USB, 0); + pxa_set_cken(CKEN_USB, 0); #endif ep0_idle (dev); @@ -1543,7 +1543,7 @@ static void udc_enable (struct pxa2xx_udc *dev) #ifdef CONFIG_ARCH_PXA /* Enable clock for USB device */ - pxa_set_cken(CKEN11_USB, 1); + pxa_set_cken(CKEN_USB, 1); udelay(5); #endif diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c index f1563dc319d3..23d2fe5a62f4 100644 --- a/drivers/usb/host/ohci-pxa27x.c +++ b/drivers/usb/host/ohci-pxa27x.c @@ -80,7 +80,7 @@ static int pxa27x_start_hc(struct device *dev) inf = dev->platform_data; - pxa_set_cken(CKEN10_USBHOST, 1); + pxa_set_cken(CKEN_USBHOST, 1); UHCHR |= UHCHR_FHR; udelay(11); @@ -123,7 +123,7 @@ static void pxa27x_stop_hc(struct device *dev) UHCCOMS |= 1; udelay(10); - pxa_set_cken(CKEN10_USBHOST, 0); + pxa_set_cken(CKEN_USBHOST, 0); } diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c index b4947c810706..0b195f33f84f 100644 --- a/drivers/video/pxafb.c +++ b/drivers/video/pxafb.c @@ -803,7 +803,7 @@ static void pxafb_enable_controller(struct pxafb_info *fbi) pr_debug("reg_lccr3 0x%08x\n", (unsigned int) fbi->reg_lccr3); /* enable LCD controller clock */ - pxa_set_cken(CKEN16_LCD, 1); + pxa_set_cken(CKEN_LCD, 1); /* Sequence from 11.7.10 */ LCCR3 = fbi->reg_lccr3; @@ -840,7 +840,7 @@ static void pxafb_disable_controller(struct pxafb_info *fbi) remove_wait_queue(&fbi->ctrlr_wait, &wait); /* disable LCD controller clock */ - pxa_set_cken(CKEN16_LCD, 0); + pxa_set_cken(CKEN_LCD, 0); } /* -- cgit v1.2.2 From 1b0646a033c370d6c7f5390f2cb452cc1884bb5b Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 22 Apr 2007 11:55:59 +0100 Subject: [ARM] Convert AMBA PL010 driver to use 'uart_amba_port' Use a pointer to struct uart_amba_port throughout the driver rather than a mixture of that and struct uart_port. Signed-off-by: Russell King --- drivers/serial/amba-pl010.c | 258 +++++++++++++++++++++++--------------------- 1 file changed, 134 insertions(+), 124 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c index f69bd097166e..ea49aafd66bf 100644 --- a/drivers/serial/amba-pl010.c +++ b/drivers/serial/amba-pl010.c @@ -77,73 +77,77 @@ struct uart_amba_port { static void pl010_stop_tx(struct uart_port *port) { + struct uart_amba_port *uap = (struct uart_amba_port *)port; unsigned int cr; - cr = readb(port->membase + UART010_CR); + cr = readb(uap->port.membase + UART010_CR); cr &= ~UART010_CR_TIE; - writel(cr, port->membase + UART010_CR); + writel(cr, uap->port.membase + UART010_CR); } static void pl010_start_tx(struct uart_port *port) { + struct uart_amba_port *uap = (struct uart_amba_port *)port; unsigned int cr; - cr = readb(port->membase + UART010_CR); + cr = readb(uap->port.membase + UART010_CR); cr |= UART010_CR_TIE; - writel(cr, port->membase + UART010_CR); + writel(cr, uap->port.membase + UART010_CR); } static void pl010_stop_rx(struct uart_port *port) { + struct uart_amba_port *uap = (struct uart_amba_port *)port; unsigned int cr; - cr = readb(port->membase + UART010_CR); + cr = readb(uap->port.membase + UART010_CR); cr &= ~(UART010_CR_RIE | UART010_CR_RTIE); - writel(cr, port->membase + UART010_CR); + writel(cr, uap->port.membase + UART010_CR); } static void pl010_enable_ms(struct uart_port *port) { + struct uart_amba_port *uap = (struct uart_amba_port *)port; unsigned int cr; - cr = readb(port->membase + UART010_CR); + cr = readb(uap->port.membase + UART010_CR); cr |= UART010_CR_MSIE; - writel(cr, port->membase + UART010_CR); + writel(cr, uap->port.membase + UART010_CR); } -static void pl010_rx_chars(struct uart_port *port) +static void pl010_rx_chars(struct uart_amba_port *uap) { - struct tty_struct *tty = port->info->tty; + struct tty_struct *tty = uap->port.info->tty; unsigned int status, ch, flag, rsr, max_count = 256; - status = readb(port->membase + UART01x_FR); + status = readb(uap->port.membase + UART01x_FR); while (UART_RX_DATA(status) && max_count--) { - ch = readb(port->membase + UART01x_DR); + ch = readb(uap->port.membase + UART01x_DR); flag = TTY_NORMAL; - port->icount.rx++; + uap->port.icount.rx++; /* * Note that the error handling code is * out of the main execution path */ - rsr = readb(port->membase + UART01x_RSR) | UART_DUMMY_RSR_RX; + rsr = readb(uap->port.membase + UART01x_RSR) | UART_DUMMY_RSR_RX; if (unlikely(rsr & UART01x_RSR_ANY)) { - writel(0, port->membase + UART01x_ECR); + writel(0, uap->port.membase + UART01x_ECR); if (rsr & UART01x_RSR_BE) { rsr &= ~(UART01x_RSR_FE | UART01x_RSR_PE); - port->icount.brk++; - if (uart_handle_break(port)) + uap->port.icount.brk++; + if (uart_handle_break(&uap->port)) goto ignore_char; } else if (rsr & UART01x_RSR_PE) - port->icount.parity++; + uap->port.icount.parity++; else if (rsr & UART01x_RSR_FE) - port->icount.frame++; + uap->port.icount.frame++; if (rsr & UART01x_RSR_OE) - port->icount.overrun++; + uap->port.icount.overrun++; - rsr &= port->read_status_mask; + rsr &= uap->port.read_status_mask; if (rsr & UART01x_RSR_BE) flag = TTY_BREAK; @@ -153,53 +157,52 @@ static void pl010_rx_chars(struct uart_port *port) flag = TTY_FRAME; } - if (uart_handle_sysrq_char(port, ch)) + if (uart_handle_sysrq_char(&uap->port, ch)) goto ignore_char; - uart_insert_char(port, rsr, UART01x_RSR_OE, ch, flag); + uart_insert_char(&uap->port, rsr, UART01x_RSR_OE, ch, flag); ignore_char: - status = readb(port->membase + UART01x_FR); + status = readb(uap->port.membase + UART01x_FR); } tty_flip_buffer_push(tty); return; } -static void pl010_tx_chars(struct uart_port *port) +static void pl010_tx_chars(struct uart_amba_port *uap) { - struct circ_buf *xmit = &port->info->xmit; + struct circ_buf *xmit = &uap->port.info->xmit; int count; - if (port->x_char) { - writel(port->x_char, port->membase + UART01x_DR); - port->icount.tx++; - port->x_char = 0; + if (uap->port.x_char) { + writel(uap->port.x_char, uap->port.membase + UART01x_DR); + uap->port.icount.tx++; + uap->port.x_char = 0; return; } - if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { - pl010_stop_tx(port); + if (uart_circ_empty(xmit) || uart_tx_stopped(&uap->port)) { + pl010_stop_tx(&uap->port); return; } - count = port->fifosize >> 1; + count = uap->port.fifosize >> 1; do { - writel(xmit->buf[xmit->tail], port->membase + UART01x_DR); + writel(xmit->buf[xmit->tail], uap->port.membase + UART01x_DR); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); - port->icount.tx++; + uap->port.icount.tx++; if (uart_circ_empty(xmit)) break; } while (--count > 0); if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) - uart_write_wakeup(port); + uart_write_wakeup(&uap->port); if (uart_circ_empty(xmit)) - pl010_stop_tx(port); + pl010_stop_tx(&uap->port); } -static void pl010_modem_status(struct uart_port *port) +static void pl010_modem_status(struct uart_amba_port *uap) { - struct uart_amba_port *uap = (struct uart_amba_port *)port; unsigned int status, delta; writel(0, uap->port.membase + UART010_ICR); @@ -226,47 +229,50 @@ static void pl010_modem_status(struct uart_port *port) static irqreturn_t pl010_int(int irq, void *dev_id) { - struct uart_port *port = dev_id; + struct uart_amba_port *uap = dev_id; unsigned int status, pass_counter = AMBA_ISR_PASS_LIMIT; int handled = 0; - spin_lock(&port->lock); + spin_lock(&uap->port.lock); - status = readb(port->membase + UART010_IIR); + status = readb(uap->port.membase + UART010_IIR); if (status) { do { if (status & (UART010_IIR_RTIS | UART010_IIR_RIS)) - pl010_rx_chars(port); + pl010_rx_chars(uap); if (status & UART010_IIR_MIS) - pl010_modem_status(port); + pl010_modem_status(uap); if (status & UART010_IIR_TIS) - pl010_tx_chars(port); + pl010_tx_chars(uap); if (pass_counter-- == 0) break; - status = readb(port->membase + UART010_IIR); + status = readb(uap->port.membase + UART010_IIR); } while (status & (UART010_IIR_RTIS | UART010_IIR_RIS | UART010_IIR_TIS)); handled = 1; } - spin_unlock(&port->lock); + spin_unlock(&uap->port.lock); return IRQ_RETVAL(handled); } static unsigned int pl010_tx_empty(struct uart_port *port) { - return readb(port->membase + UART01x_FR) & UART01x_FR_BUSY ? 0 : TIOCSER_TEMT; + struct uart_amba_port *uap = (struct uart_amba_port *)port; + unsigned int status = readb(uap->port.membase + UART01x_FR); + return status & UART01x_FR_BUSY ? 0 : TIOCSER_TEMT; } static unsigned int pl010_get_mctrl(struct uart_port *port) { + struct uart_amba_port *uap = (struct uart_amba_port *)port; unsigned int result = 0; unsigned int status; - status = readb(port->membase + UART01x_FR); + status = readb(uap->port.membase + UART01x_FR); if (status & UART01x_FR_DCD) result |= TIOCM_CAR; if (status & UART01x_FR_DSR) @@ -287,17 +293,18 @@ static void pl010_set_mctrl(struct uart_port *port, unsigned int mctrl) static void pl010_break_ctl(struct uart_port *port, int break_state) { + struct uart_amba_port *uap = (struct uart_amba_port *)port; unsigned long flags; unsigned int lcr_h; - spin_lock_irqsave(&port->lock, flags); - lcr_h = readb(port->membase + UART010_LCRH); + spin_lock_irqsave(&uap->port.lock, flags); + lcr_h = readb(uap->port.membase + UART010_LCRH); if (break_state == -1) lcr_h |= UART01x_LCRH_BRK; else lcr_h &= ~UART01x_LCRH_BRK; - writel(lcr_h, port->membase + UART010_LCRH); - spin_unlock_irqrestore(&port->lock, flags); + writel(lcr_h, uap->port.membase + UART010_LCRH); + spin_unlock_irqrestore(&uap->port.lock, flags); } static int pl010_startup(struct uart_port *port) @@ -308,46 +315,49 @@ static int pl010_startup(struct uart_port *port) /* * Allocate the IRQ */ - retval = request_irq(port->irq, pl010_int, 0, "uart-pl010", port); + retval = request_irq(uap->port.irq, pl010_int, 0, "uart-pl010", uap); if (retval) return retval; /* * initialise the old status of the modem signals */ - uap->old_status = readb(port->membase + UART01x_FR) & UART01x_FR_MODEM_ANY; + uap->old_status = readb(uap->port.membase + UART01x_FR) & UART01x_FR_MODEM_ANY; /* * Finally, enable interrupts */ writel(UART01x_CR_UARTEN | UART010_CR_RIE | UART010_CR_RTIE, - port->membase + UART010_CR); + uap->port.membase + UART010_CR); return 0; } static void pl010_shutdown(struct uart_port *port) { + struct uart_amba_port *uap = (struct uart_amba_port *)port; + /* * Free the interrupt */ - free_irq(port->irq, port); + free_irq(uap->port.irq, uap); /* * disable all interrupts, disable the port */ - writel(0, port->membase + UART010_CR); + writel(0, uap->port.membase + UART010_CR); /* disable break condition and fifos */ - writel(readb(port->membase + UART010_LCRH) & + writel(readb(uap->port.membase + UART010_LCRH) & ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN), - port->membase + UART010_LCRH); + uap->port.membase + UART010_LCRH); } static void pl010_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { + struct uart_amba_port *uap = (struct uart_amba_port *)port; unsigned int lcr_h, old_cr; unsigned long flags; unsigned int baud, quot; @@ -355,7 +365,7 @@ pl010_set_termios(struct uart_port *port, struct ktermios *termios, /* * Ask the core to calculate the divisor for us. */ - baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); + baud = uart_get_baud_rate(port, termios, old, 0, uap->port.uartclk/16); quot = uart_get_divisor(port, baud); switch (termios->c_cflag & CSIZE) { @@ -379,66 +389,66 @@ pl010_set_termios(struct uart_port *port, struct ktermios *termios, if (!(termios->c_cflag & PARODD)) lcr_h |= UART01x_LCRH_EPS; } - if (port->fifosize > 1) + if (uap->port.fifosize > 1) lcr_h |= UART01x_LCRH_FEN; - spin_lock_irqsave(&port->lock, flags); + spin_lock_irqsave(&uap->port.lock, flags); /* * Update the per-port timeout. */ uart_update_timeout(port, termios->c_cflag, baud); - port->read_status_mask = UART01x_RSR_OE; + uap->port.read_status_mask = UART01x_RSR_OE; if (termios->c_iflag & INPCK) - port->read_status_mask |= UART01x_RSR_FE | UART01x_RSR_PE; + uap->port.read_status_mask |= UART01x_RSR_FE | UART01x_RSR_PE; if (termios->c_iflag & (BRKINT | PARMRK)) - port->read_status_mask |= UART01x_RSR_BE; + uap->port.read_status_mask |= UART01x_RSR_BE; /* * Characters to ignore */ - port->ignore_status_mask = 0; + uap->port.ignore_status_mask = 0; if (termios->c_iflag & IGNPAR) - port->ignore_status_mask |= UART01x_RSR_FE | UART01x_RSR_PE; + uap->port.ignore_status_mask |= UART01x_RSR_FE | UART01x_RSR_PE; if (termios->c_iflag & IGNBRK) { - port->ignore_status_mask |= UART01x_RSR_BE; + uap->port.ignore_status_mask |= UART01x_RSR_BE; /* * If we're ignoring parity and break indicators, * ignore overruns too (for real raw support). */ if (termios->c_iflag & IGNPAR) - port->ignore_status_mask |= UART01x_RSR_OE; + uap->port.ignore_status_mask |= UART01x_RSR_OE; } /* * Ignore all characters if CREAD is not set. */ if ((termios->c_cflag & CREAD) == 0) - port->ignore_status_mask |= UART_DUMMY_RSR_RX; + uap->port.ignore_status_mask |= UART_DUMMY_RSR_RX; /* first, disable everything */ - old_cr = readb(port->membase + UART010_CR) & ~UART010_CR_MSIE; + old_cr = readb(uap->port.membase + UART010_CR) & ~UART010_CR_MSIE; if (UART_ENABLE_MS(port, termios->c_cflag)) old_cr |= UART010_CR_MSIE; - writel(0, port->membase + UART010_CR); + writel(0, uap->port.membase + UART010_CR); /* Set baud rate */ quot -= 1; - writel((quot & 0xf00) >> 8, port->membase + UART010_LCRM); - writel(quot & 0xff, port->membase + UART010_LCRL); + writel((quot & 0xf00) >> 8, uap->port.membase + UART010_LCRM); + writel(quot & 0xff, uap->port.membase + UART010_LCRL); /* * ----------v----------v----------v----------v----- * NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L * ----------^----------^----------^----------^----- */ - writel(lcr_h, port->membase + UART010_LCRH); - writel(old_cr, port->membase + UART010_CR); + writel(lcr_h, uap->port.membase + UART010_LCRH); + writel(old_cr, uap->port.membase + UART010_CR); - spin_unlock_irqrestore(&port->lock, flags); + spin_unlock_irqrestore(&uap->port.lock, flags); } static const char *pl010_type(struct uart_port *port) @@ -514,47 +524,48 @@ static struct uart_amba_port *amba_ports[UART_NR]; static void pl010_console_putchar(struct uart_port *port, int ch) { + struct uart_amba_port *uap = (struct uart_amba_port *)port; unsigned int status; do { - status = readb(port->membase + UART01x_FR); + status = readb(uap->port.membase + UART01x_FR); barrier(); } while (!UART_TX_READY(status)); - writel(ch, port->membase + UART01x_DR); + writel(ch, uap->port.membase + UART01x_DR); } static void pl010_console_write(struct console *co, const char *s, unsigned int count) { - struct uart_port *port = &amba_ports[co->index]->port; + struct uart_amba_port *uap = amba_ports[co->index]; unsigned int status, old_cr; /* * First save the CR then disable the interrupts */ - old_cr = readb(port->membase + UART010_CR); - writel(UART01x_CR_UARTEN, port->membase + UART010_CR); + old_cr = readb(uap->port.membase + UART010_CR); + writel(UART01x_CR_UARTEN, uap->port.membase + UART010_CR); - uart_console_write(port, s, count, pl010_console_putchar); + uart_console_write(&uap->port, s, count, pl010_console_putchar); /* * Finally, wait for transmitter to become empty * and restore the TCR */ do { - status = readb(port->membase + UART01x_FR); + status = readb(uap->port.membase + UART01x_FR); barrier(); } while (status & UART01x_FR_BUSY); - writel(old_cr, port->membase + UART010_CR); + writel(old_cr, uap->port.membase + UART010_CR); } static void __init -pl010_console_get_options(struct uart_port *port, int *baud, +pl010_console_get_options(struct uart_amba_port *uap, int *baud, int *parity, int *bits) { - if (readb(port->membase + UART010_CR) & UART01x_CR_UARTEN) { + if (readb(uap->port.membase + UART010_CR) & UART01x_CR_UARTEN) { unsigned int lcr_h, quot; - lcr_h = readb(port->membase + UART010_LCRH); + lcr_h = readb(uap->port.membase + UART010_LCRH); *parity = 'n'; if (lcr_h & UART01x_LCRH_PEN) { @@ -569,14 +580,15 @@ pl010_console_get_options(struct uart_port *port, int *baud, else *bits = 8; - quot = readb(port->membase + UART010_LCRL) | readb(port->membase + UART010_LCRM) << 8; - *baud = port->uartclk / (16 * (quot + 1)); + quot = readb(uap->port.membase + UART010_LCRL) | + readb(uap->port.membase + UART010_LCRM) << 8; + *baud = uap->port.uartclk / (16 * (quot + 1)); } } static int __init pl010_console_setup(struct console *co, char *options) { - struct uart_port *port; + struct uart_amba_port *uap; int baud = 38400; int bits = 8; int parity = 'n'; @@ -589,16 +601,16 @@ static int __init pl010_console_setup(struct console *co, char *options) */ if (co->index >= UART_NR) co->index = 0; - if (!amba_ports[co->index]) + uap = amba_ports[co->index]; + if (!uap) return -ENODEV; - port = &amba_ports[co->index]->port; if (options) uart_parse_options(options, &baud, &parity, &bits, &flow); else - pl010_console_get_options(port, &baud, &parity, &bits); + pl010_console_get_options(uap, &baud, &parity, &bits); - return uart_set_options(port, co, baud, parity, bits, flow); + return uart_set_options(&uap->port, co, baud, parity, bits, flow); } static struct uart_driver amba_reg; @@ -629,7 +641,7 @@ static struct uart_driver amba_reg = { static int pl010_probe(struct amba_device *dev, void *id) { - struct uart_amba_port *port; + struct uart_amba_port *uap; void __iomem *base; int i, ret; @@ -642,8 +654,8 @@ static int pl010_probe(struct amba_device *dev, void *id) goto out; } - port = kzalloc(sizeof(struct uart_amba_port), GFP_KERNEL); - if (!port) { + uap = kzalloc(sizeof(struct uart_amba_port), GFP_KERNEL); + if (!uap) { ret = -ENOMEM; goto out; } @@ -654,51 +666,49 @@ static int pl010_probe(struct amba_device *dev, void *id) goto free; } - port->port.dev = &dev->dev; - port->port.mapbase = dev->res.start; - port->port.membase = base; - port->port.iotype = UPIO_MEM; - port->port.irq = dev->irq[0]; - port->port.uartclk = 14745600; - port->port.fifosize = 16; - port->port.ops = &amba_pl010_pops; - port->port.flags = UPF_BOOT_AUTOCONF; - port->port.line = i; - port->dev = dev; - port->data = dev->dev.platform_data; - - amba_ports[i] = port; - - amba_set_drvdata(dev, port); - ret = uart_add_one_port(&amba_reg, &port->port); + uap->port.dev = &dev->dev; + uap->port.mapbase = dev->res.start; + uap->port.membase = base; + uap->port.iotype = UPIO_MEM; + uap->port.irq = dev->irq[0]; + uap->port.uartclk = 14745600; + uap->port.fifosize = 16; + uap->port.ops = &amba_pl010_pops; + uap->port.flags = UPF_BOOT_AUTOCONF; + uap->port.line = i; + uap->dev = dev; + uap->data = dev->dev.platform_data; + + amba_ports[i] = uap; + + amba_set_drvdata(dev, uap); + ret = uart_add_one_port(&amba_reg, &uap->port); if (ret) { amba_set_drvdata(dev, NULL); amba_ports[i] = NULL; iounmap(base); free: - kfree(port); + kfree(uap); } - out: return ret; } static int pl010_remove(struct amba_device *dev) { - struct uart_amba_port *port = amba_get_drvdata(dev); + struct uart_amba_port *uap = amba_get_drvdata(dev); int i; amba_set_drvdata(dev, NULL); - uart_remove_one_port(&amba_reg, &port->port); + uart_remove_one_port(&amba_reg, &uap->port); for (i = 0; i < ARRAY_SIZE(amba_ports); i++) - if (amba_ports[i] == port) + if (amba_ports[i] == uap) amba_ports[i] = NULL; - iounmap(port->port.membase); - kfree(port); - + iounmap(uap->port.membase); + kfree(uap); return 0; } -- cgit v1.2.2 From ed519dede3d705e1c0012acd5b8de4074aa30fa4 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 22 Apr 2007 12:30:41 +0100 Subject: [ARM] Convert AMBA PL010 driver to use the clk infrastructure Convert the AMBA PL010 serial driver to use the clock infrastructure to allow EP93xx platforms to properly gate the clock to the UARTs. Signed-off-by: Russell King --- drivers/serial/amba-pl010.c | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c index ea49aafd66bf..1a9a24b82636 100644 --- a/drivers/serial/amba-pl010.c +++ b/drivers/serial/amba-pl010.c @@ -48,6 +48,7 @@ #include #include #include +#include #include @@ -70,6 +71,7 @@ */ struct uart_amba_port { struct uart_port port; + struct clk *clk; struct amba_device *dev; struct amba_pl010_data *data; unsigned int old_status; @@ -312,12 +314,21 @@ static int pl010_startup(struct uart_port *port) struct uart_amba_port *uap = (struct uart_amba_port *)port; int retval; + /* + * Try to enable the clock producer. + */ + retval = clk_enable(uap->clk); + if (retval) + goto out; + + uap->port.uartclk = clk_get_rate(uap->clk); + /* * Allocate the IRQ */ retval = request_irq(uap->port.irq, pl010_int, 0, "uart-pl010", uap); if (retval) - return retval; + goto clk_dis; /* * initialise the old status of the modem signals @@ -331,6 +342,11 @@ static int pl010_startup(struct uart_port *port) uap->port.membase + UART010_CR); return 0; + + clk_dis: + clk_disable(uap->clk); + out: + return retval; } static void pl010_shutdown(struct uart_port *port) @@ -351,6 +367,11 @@ static void pl010_shutdown(struct uart_port *port) writel(readb(uap->port.membase + UART010_LCRH) & ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN), uap->port.membase + UART010_LCRH); + + /* + * Shut down the clock producer + */ + clk_disable(uap->clk); } static void @@ -540,6 +561,8 @@ pl010_console_write(struct console *co, const char *s, unsigned int count) struct uart_amba_port *uap = amba_ports[co->index]; unsigned int status, old_cr; + clk_enable(uap->clk); + /* * First save the CR then disable the interrupts */ @@ -557,6 +580,8 @@ pl010_console_write(struct console *co, const char *s, unsigned int count) barrier(); } while (status & UART01x_FR_BUSY); writel(old_cr, uap->port.membase + UART010_CR); + + clk_disable(uap->clk); } static void __init @@ -605,6 +630,8 @@ static int __init pl010_console_setup(struct console *co, char *options) if (!uap) return -ENODEV; + uap->port.uartclk = clk_get_rate(uap->clk); + if (options) uart_parse_options(options, &baud, &parity, &bits, &flow); else @@ -666,12 +693,17 @@ static int pl010_probe(struct amba_device *dev, void *id) goto free; } + uap->clk = clk_get(&dev->dev, "UARTCLK"); + if (IS_ERR(uap->clk)) { + ret = PTR_ERR(uap->clk); + goto unmap; + } + uap->port.dev = &dev->dev; uap->port.mapbase = dev->res.start; uap->port.membase = base; uap->port.iotype = UPIO_MEM; uap->port.irq = dev->irq[0]; - uap->port.uartclk = 14745600; uap->port.fifosize = 16; uap->port.ops = &amba_pl010_pops; uap->port.flags = UPF_BOOT_AUTOCONF; @@ -686,6 +718,8 @@ static int pl010_probe(struct amba_device *dev, void *id) if (ret) { amba_set_drvdata(dev, NULL); amba_ports[i] = NULL; + clk_put(uap->clk); + unmap: iounmap(base); free: kfree(uap); @@ -708,6 +742,7 @@ static int pl010_remove(struct amba_device *dev) amba_ports[i] = NULL; iounmap(uap->port.membase); + clk_put(uap->clk); kfree(uap); return 0; } -- cgit v1.2.2 From 03abeac0a222060ae8f02e8359c285df0971437e Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Thu, 3 May 2007 12:26:24 +0100 Subject: [ARM] 4357/1: AT91: Support slower serial baud-rates Allow slower serial baud-rates by switching the UART clock from MCK to MCK/8. Based on patches by Mike Wolfram and Russell King. Signed-off-by: Andrew Victor Signed-off-by: Russell King --- drivers/serial/atmel_serial.c | 9 +++++++-- drivers/serial/atmel_serial.h | 3 +++ 2 files changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c index 935f48fa501d..3320bcd92c0a 100644 --- a/drivers/serial/atmel_serial.c +++ b/drivers/serial/atmel_serial.c @@ -484,11 +484,16 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios * termios, unsigned long flags; unsigned int mode, imr, quot, baud; + /* Get current mode register */ + mode = UART_GET_MR(port) & ~(ATMEL_US_USCLKS | ATMEL_US_CHRL | ATMEL_US_NBSTOP | ATMEL_US_PAR); + baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); quot = uart_get_divisor(port, baud); - /* Get current mode register */ - mode = UART_GET_MR(port) & ~(ATMEL_US_CHRL | ATMEL_US_NBSTOP | ATMEL_US_PAR); + if (quot > 65535) { /* BRGR is 16-bit, so switch to slower clock */ + quot /= 8; + mode |= ATMEL_US_USCLKS_MCK_DIV8; + } /* byte size */ switch (termios->c_cflag & CSIZE) { diff --git a/drivers/serial/atmel_serial.h b/drivers/serial/atmel_serial.h index 11b44360e108..e0141776517c 100644 --- a/drivers/serial/atmel_serial.h +++ b/drivers/serial/atmel_serial.h @@ -46,6 +46,9 @@ #define ATMEL_US_USMODE_ISO7816_T1 6 #define ATMEL_US_USMODE_IRDA 8 #define ATMEL_US_USCLKS (3 << 4) /* Clock Selection */ +#define ATMEL_US_USCLKS_MCK (0 << 4) +#define ATMEL_US_USCLKS_MCK_DIV8 (1 << 4) +#define ATMEL_US_USCLKS_SCK (3 << 4) #define ATMEL_US_CHRL (3 << 6) /* Character Length */ #define ATMEL_US_CHRL_5 (0 << 6) #define ATMEL_US_CHRL_6 (1 << 6) -- cgit v1.2.2 From a17dba8df9848c548912fbe9bf4b28c5a67c5413 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 21 Apr 2007 15:55:06 +0100 Subject: [ARM] Add platform support for PATA on RiscPC Add pata_platform device for RiscPC, thereby converting the primary IDE channel on the machine to PATA. Acked-by: Jeff Garzik Signed-off-by: Russell King --- drivers/ata/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 7bdbe5a914d0..e0820e8dd1c7 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -545,7 +545,7 @@ config PATA_WINBOND_VLB config PATA_PLATFORM tristate "Generic platform device PATA support" - depends on EMBEDDED + depends on EMBEDDED || ARCH_RPC help This option enables support for generic directly connected ATA devices commonly found on embedded systems. -- cgit v1.2.2 From 73b6a2be8b29b2067aa3c0f1d6433b6148d88705 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 3 May 2007 09:55:52 +0100 Subject: [ARM] Add support for ICSIDE interface on RiscPC Signed-off-by: Russell King --- drivers/ata/Kconfig | 8 + drivers/ata/Makefile | 1 + drivers/ata/pata_icside.c | 686 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 695 insertions(+) create mode 100644 drivers/ata/pata_icside.c (limited to 'drivers') diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index e0820e8dd1c7..77846dd0a4fa 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -552,6 +552,14 @@ config PATA_PLATFORM If unsure, say N. +config PATA_ICSIDE + tristate "Acorn ICS PATA support" + depends on ARM && ARCH_ACORN + help + On Acorn systems, say Y here if you wish to use the ICS PATA + interface card. This is not required for ICS partition support. + If you are unsure, say N to this. + config PATA_IXP4XX_CF tristate "IXP4XX Compact Flash support" depends on ARCH_IXP4XX diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile index 13d7397e0008..cc8798b1a54f 100644 --- a/drivers/ata/Makefile +++ b/drivers/ata/Makefile @@ -61,6 +61,7 @@ obj-$(CONFIG_PATA_TRIFLEX) += pata_triflex.o obj-$(CONFIG_PATA_IXP4XX_CF) += pata_ixp4xx_cf.o obj-$(CONFIG_PATA_SCC) += pata_scc.o obj-$(CONFIG_PATA_PLATFORM) += pata_platform.o +obj-$(CONFIG_PATA_ICSIDE) += pata_icside.o # Should be last but one libata driver obj-$(CONFIG_ATA_GENERIC) += ata_generic.o # Should be last libata driver diff --git a/drivers/ata/pata_icside.c b/drivers/ata/pata_icside.c new file mode 100644 index 000000000000..dbc8ee2adcf0 --- /dev/null +++ b/drivers/ata/pata_icside.c @@ -0,0 +1,686 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define DRV_NAME "pata_icside" + +#define ICS_IDENT_OFFSET 0x2280 + +#define ICS_ARCIN_V5_INTRSTAT 0x0000 +#define ICS_ARCIN_V5_INTROFFSET 0x0004 + +#define ICS_ARCIN_V6_INTROFFSET_1 0x2200 +#define ICS_ARCIN_V6_INTRSTAT_1 0x2290 +#define ICS_ARCIN_V6_INTROFFSET_2 0x3200 +#define ICS_ARCIN_V6_INTRSTAT_2 0x3290 + +struct portinfo { + unsigned int dataoffset; + unsigned int ctrloffset; + unsigned int stepping; +}; + +static const struct portinfo pata_icside_portinfo_v5 = { + .dataoffset = 0x2800, + .ctrloffset = 0x2b80, + .stepping = 6, +}; + +static const struct portinfo pata_icside_portinfo_v6_1 = { + .dataoffset = 0x2000, + .ctrloffset = 0x2380, + .stepping = 6, +}; + +static const struct portinfo pata_icside_portinfo_v6_2 = { + .dataoffset = 0x3000, + .ctrloffset = 0x3380, + .stepping = 6, +}; + +#define PATA_ICSIDE_MAX_SG 128 + +struct pata_icside_state { + void __iomem *irq_port; + void __iomem *ioc_base; + unsigned int type; + unsigned int dma; + struct { + u8 port_sel; + u8 disabled; + unsigned int speed[ATA_MAX_DEVICES]; + } port[2]; + struct scatterlist sg[PATA_ICSIDE_MAX_SG]; +}; + +#define ICS_TYPE_A3IN 0 +#define ICS_TYPE_A3USER 1 +#define ICS_TYPE_V6 3 +#define ICS_TYPE_V5 15 +#define ICS_TYPE_NOTYPE ((unsigned int)-1) + +/* ---------------- Version 5 PCB Support Functions --------------------- */ +/* Prototype: pata_icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr) + * Purpose : enable interrupts from card + */ +static void pata_icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr) +{ + struct pata_icside_state *state = ec->irq_data; + + writeb(0, state->irq_port + ICS_ARCIN_V5_INTROFFSET); +} + +/* Prototype: pata_icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr) + * Purpose : disable interrupts from card + */ +static void pata_icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr) +{ + struct pata_icside_state *state = ec->irq_data; + + readb(state->irq_port + ICS_ARCIN_V5_INTROFFSET); +} + +static const expansioncard_ops_t pata_icside_ops_arcin_v5 = { + .irqenable = pata_icside_irqenable_arcin_v5, + .irqdisable = pata_icside_irqdisable_arcin_v5, +}; + + +/* ---------------- Version 6 PCB Support Functions --------------------- */ +/* Prototype: pata_icside_irqenable_arcin_v6 (struct expansion_card *ec, int irqnr) + * Purpose : enable interrupts from card + */ +static void pata_icside_irqenable_arcin_v6 (struct expansion_card *ec, int irqnr) +{ + struct pata_icside_state *state = ec->irq_data; + void __iomem *base = state->irq_port; + + if (!state->port[0].disabled) + writeb(0, base + ICS_ARCIN_V6_INTROFFSET_1); + if (!state->port[1].disabled) + writeb(0, base + ICS_ARCIN_V6_INTROFFSET_2); +} + +/* Prototype: pata_icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr) + * Purpose : disable interrupts from card + */ +static void pata_icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr) +{ + struct pata_icside_state *state = ec->irq_data; + + readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1); + readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2); +} + +/* Prototype: pata_icside_irqprobe(struct expansion_card *ec) + * Purpose : detect an active interrupt from card + */ +static int pata_icside_irqpending_arcin_v6(struct expansion_card *ec) +{ + struct pata_icside_state *state = ec->irq_data; + + return readb(state->irq_port + ICS_ARCIN_V6_INTRSTAT_1) & 1 || + readb(state->irq_port + ICS_ARCIN_V6_INTRSTAT_2) & 1; +} + +static const expansioncard_ops_t pata_icside_ops_arcin_v6 = { + .irqenable = pata_icside_irqenable_arcin_v6, + .irqdisable = pata_icside_irqdisable_arcin_v6, + .irqpending = pata_icside_irqpending_arcin_v6, +}; + + +/* + * SG-DMA support. + * + * Similar to the BM-DMA, but we use the RiscPCs IOMD DMA controllers. + * There is only one DMA controller per card, which means that only + * one drive can be accessed at one time. NOTE! We do not enforce that + * here, but we rely on the main IDE driver spotting that both + * interfaces use the same IRQ, which should guarantee this. + */ + +/* + * Configure the IOMD to give the appropriate timings for the transfer + * mode being requested. We take the advice of the ATA standards, and + * calculate the cycle time based on the transfer mode, and the EIDE + * MW DMA specs that the drive provides in the IDENTIFY command. + * + * We have the following IOMD DMA modes to choose from: + * + * Type Active Recovery Cycle + * A 250 (250) 312 (550) 562 (800) + * B 187 (200) 250 (550) 437 (750) + * C 125 (125) 125 (375) 250 (500) + * D 62 (50) 125 (375) 187 (425) + * + * (figures in brackets are actual measured timings on DIOR/DIOW) + * + * However, we also need to take care of the read/write active and + * recovery timings: + * + * Read Write + * Mode Active -- Recovery -- Cycle IOMD type + * MW0 215 50 215 480 A + * MW1 80 50 50 150 C + * MW2 70 25 25 120 C + */ +static void pata_icside_set_dmamode(struct ata_port *ap, struct ata_device *adev) +{ + struct pata_icside_state *state = ap->host->private_data; + struct ata_timing t; + unsigned int cycle; + char iomd_type; + + /* + * DMA is based on a 16MHz clock + */ + if (ata_timing_compute(adev, adev->dma_mode, &t, 1000, 1)) + return; + + /* + * Choose the IOMD cycle timing which ensure that the interface + * satisfies the measured active, recovery and cycle times. + */ + if (t.active <= 50 && t.recover <= 375 && t.cycle <= 425) + iomd_type = 'D', cycle = 187; + else if (t.active <= 125 && t.recover <= 375 && t.cycle <= 500) + iomd_type = 'C', cycle = 250; + else if (t.active <= 200 && t.recover <= 550 && t.cycle <= 750) + iomd_type = 'B', cycle = 437; + else + iomd_type = 'A', cycle = 562; + + ata_dev_printk(adev, KERN_INFO, "timings: act %dns rec %dns cyc %dns (%c)\n", + t.active, t.recover, t.cycle, iomd_type); + + state->port[ap->port_no].speed[adev->devno] = cycle; +} + +static void pata_icside_bmdma_setup(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + struct pata_icside_state *state = ap->host->private_data; + struct scatterlist *sg, *rsg = state->sg; + unsigned int write = qc->tf.flags & ATA_TFLAG_WRITE; + + /* + * We are simplex; BUG if we try to fiddle with DMA + * while it's active. + */ + BUG_ON(dma_channel_active(state->dma)); + + /* + * Copy ATAs scattered sg list into a contiguous array of sg + */ + ata_for_each_sg(sg, qc) { + memcpy(rsg, sg, sizeof(*sg)); + rsg++; + } + + /* + * Route the DMA signals to the correct interface + */ + writeb(state->port[ap->port_no].port_sel, state->ioc_base); + + set_dma_speed(state->dma, state->port[ap->port_no].speed[qc->dev->devno]); + set_dma_sg(state->dma, state->sg, rsg - state->sg); + set_dma_mode(state->dma, write ? DMA_MODE_WRITE : DMA_MODE_READ); + + /* issue r/w command */ + ap->ops->exec_command(ap, &qc->tf); +} + +static void pata_icside_bmdma_start(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + struct pata_icside_state *state = ap->host->private_data; + + BUG_ON(dma_channel_active(state->dma)); + enable_dma(state->dma); +} + +static void pata_icside_bmdma_stop(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + struct pata_icside_state *state = ap->host->private_data; + + disable_dma(state->dma); + + /* see ata_bmdma_stop */ + ata_altstatus(ap); +} + +static u8 pata_icside_bmdma_status(struct ata_port *ap) +{ + struct pata_icside_state *state = ap->host->private_data; + void __iomem *irq_port; + + irq_port = state->irq_port + (ap->port_no ? ICS_ARCIN_V6_INTRSTAT_2 : + ICS_ARCIN_V6_INTRSTAT_1); + + return readb(irq_port) & 1 ? ATA_DMA_INTR : 0; +} + +static int icside_dma_init(struct ata_probe_ent *ae, struct expansion_card *ec) +{ + struct pata_icside_state *state = ae->private_data; + int i; + + for (i = 0; i < ATA_MAX_DEVICES; i++) { + state->port[0].speed[i] = 480; + state->port[1].speed[i] = 480; + } + + if (ec->dma != NO_DMA && !request_dma(ec->dma, DRV_NAME)) { + state->dma = ec->dma; + ae->mwdma_mask = 0x07; /* MW0..2 */ + } + + return 0; +} + + +static int pata_icside_port_start(struct ata_port *ap) +{ + /* No PRD to alloc */ + return ata_pad_alloc(ap, ap->dev); +} + +static struct scsi_host_template pata_icside_sht = { + .module = THIS_MODULE, + .name = DRV_NAME, + .ioctl = ata_scsi_ioctl, + .queuecommand = ata_scsi_queuecmd, + .can_queue = ATA_DEF_QUEUE, + .this_id = ATA_SHT_THIS_ID, + .sg_tablesize = PATA_ICSIDE_MAX_SG, + .cmd_per_lun = ATA_SHT_CMD_PER_LUN, + .emulated = ATA_SHT_EMULATED, + .use_clustering = ATA_SHT_USE_CLUSTERING, + .proc_name = DRV_NAME, + .dma_boundary = ~0, /* no dma boundaries */ + .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, + .bios_param = ata_std_bios_param, +}; + +/* wish this was exported from libata-core */ +static void ata_dummy_noret(struct ata_port *port) +{ +} + +/* + * We need to shut down unused ports to prevent spurious interrupts. + * FIXME: the libata core doesn't call this function for PATA interfaces. + */ +static void pata_icside_port_disable(struct ata_port *ap) +{ + struct pata_icside_state *state = ap->host->private_data; + + ata_port_printk(ap, KERN_ERR, "disabling icside port\n"); + + ata_port_disable(ap); + + state->port[ap->port_no].disabled = 1; + + if (state->type == ICS_TYPE_V6) { + /* + * Disable interrupts from this port, otherwise we + * receive spurious interrupts from the floating + * interrupt line. + */ + void __iomem *irq_port = state->irq_port + + (ap->port_no ? ICS_ARCIN_V6_INTROFFSET_2 : ICS_ARCIN_V6_INTROFFSET_1); + readb(irq_port); + } +} + +static u8 pata_icside_irq_ack(struct ata_port *ap, unsigned int chk_drq) +{ + unsigned int bits = chk_drq ? ATA_BUSY | ATA_DRQ : ATA_BUSY; + u8 status; + + status = ata_busy_wait(ap, bits, 1000); + if (status & bits) + if (ata_msg_err(ap)) + printk(KERN_ERR "abnormal status 0x%X\n", status); + + if (ata_msg_intr(ap)) + printk(KERN_INFO "%s: irq ack: drv_stat 0x%X\n", + __FUNCTION__, status); + + return status; +} + +static struct ata_port_operations pata_icside_port_ops = { + .port_disable = pata_icside_port_disable, + + .set_dmamode = pata_icside_set_dmamode, + + .tf_load = ata_tf_load, + .tf_read = ata_tf_read, + .exec_command = ata_exec_command, + .check_status = ata_check_status, + .dev_select = ata_std_dev_select, + + .bmdma_setup = pata_icside_bmdma_setup, + .bmdma_start = pata_icside_bmdma_start, + + .data_xfer = ata_data_xfer_noirq, + + /* no need to build any PRD tables for DMA */ + .qc_prep = ata_noop_qc_prep, + .qc_issue = ata_qc_issue_prot, + + .freeze = ata_bmdma_freeze, + .thaw = ata_bmdma_thaw, + .error_handler = ata_bmdma_error_handler, + .post_internal_cmd = pata_icside_bmdma_stop, + + .irq_handler = ata_interrupt, + .irq_clear = ata_dummy_noret, + .irq_on = ata_irq_on, + .irq_ack = pata_icside_irq_ack, + + .port_start = pata_icside_port_start, + + .bmdma_stop = pata_icside_bmdma_stop, + .bmdma_status = pata_icside_bmdma_status, +}; + +static void +pata_icside_add_port(struct ata_probe_ent *ae, void __iomem *base, + const struct portinfo *info) +{ + struct ata_ioports *ioaddr = &ae->port[ae->n_ports++]; + void __iomem *cmd = base + info->dataoffset; + + ioaddr->cmd_addr = cmd; + ioaddr->data_addr = cmd + (ATA_REG_DATA << info->stepping); + ioaddr->error_addr = cmd + (ATA_REG_ERR << info->stepping); + ioaddr->feature_addr = cmd + (ATA_REG_FEATURE << info->stepping); + ioaddr->nsect_addr = cmd + (ATA_REG_NSECT << info->stepping); + ioaddr->lbal_addr = cmd + (ATA_REG_LBAL << info->stepping); + ioaddr->lbam_addr = cmd + (ATA_REG_LBAM << info->stepping); + ioaddr->lbah_addr = cmd + (ATA_REG_LBAH << info->stepping); + ioaddr->device_addr = cmd + (ATA_REG_DEVICE << info->stepping); + ioaddr->status_addr = cmd + (ATA_REG_STATUS << info->stepping); + ioaddr->command_addr = cmd + (ATA_REG_CMD << info->stepping); + + ioaddr->ctl_addr = base + info->ctrloffset; + ioaddr->altstatus_addr = ioaddr->ctl_addr; +} + +static int __init +pata_icside_register_v5(struct ata_probe_ent *ae, struct expansion_card *ec) +{ + struct pata_icside_state *state = ae->private_data; + void __iomem *base; + + base = ioremap(ecard_resource_start(ec, ECARD_RES_MEMC), + ecard_resource_len(ec, ECARD_RES_MEMC)); + if (!base) + return -ENOMEM; + + state->irq_port = base; + + ec->irqaddr = base + ICS_ARCIN_V5_INTRSTAT; + ec->irqmask = 1; + ec->irq_data = state; + ec->ops = &pata_icside_ops_arcin_v5; + + /* + * Be on the safe side - disable interrupts + */ + ec->ops->irqdisable(ec, ec->irq); + + pata_icside_add_port(ae, base, &pata_icside_portinfo_v5); + + return 0; +} + +static int __init +pata_icside_register_v6(struct ata_probe_ent *ae, struct expansion_card *ec) +{ + struct pata_icside_state *state = ae->private_data; + void __iomem *ioc_base, *easi_base; + unsigned int sel = 0; + int ret; + + ioc_base = ioremap(ecard_resource_start(ec, ECARD_RES_IOCFAST), + ecard_resource_len(ec, ECARD_RES_IOCFAST)); + if (!ioc_base) { + ret = -ENOMEM; + goto out; + } + + easi_base = ioc_base; + + if (ecard_resource_flags(ec, ECARD_RES_EASI)) { + easi_base = ioremap(ecard_resource_start(ec, ECARD_RES_EASI), + ecard_resource_len(ec, ECARD_RES_EASI)); + if (!easi_base) { + ret = -ENOMEM; + goto unmap_slot; + } + + /* + * Enable access to the EASI region. + */ + sel = 1 << 5; + } + + writeb(sel, ioc_base); + + ec->irq_data = state; + ec->ops = &pata_icside_ops_arcin_v6; + + state->irq_port = easi_base; + state->ioc_base = ioc_base; + state->port[0].port_sel = sel; + state->port[1].port_sel = sel | 1; + + /* + * Be on the safe side - disable interrupts + */ + ec->ops->irqdisable(ec, ec->irq); + + /* + * Find and register the interfaces. + */ + pata_icside_add_port(ae, easi_base, &pata_icside_portinfo_v6_1); + pata_icside_add_port(ae, easi_base, &pata_icside_portinfo_v6_2); + + /* + * FIXME: work around libata's aversion to calling port_disable. + * This permanently disables interrupts on port 0 - bad luck if + * you have a drive on that port. + */ + state->port[0].disabled = 1; + + return icside_dma_init(ae, ec); + + unmap_slot: + iounmap(ioc_base); + out: + return ret; +} + +static int __devinit +pata_icside_probe(struct expansion_card *ec, const struct ecard_id *id) +{ + struct pata_icside_state *state; + struct ata_probe_ent ae; + void __iomem *idmem; + int ret; + + ret = ecard_request_resources(ec); + if (ret) + goto out; + + state = kzalloc(sizeof(struct pata_icside_state), GFP_KERNEL); + if (!state) { + ret = -ENOMEM; + goto release; + } + + state->type = ICS_TYPE_NOTYPE; + state->dma = NO_DMA; + + idmem = ioremap(ecard_resource_start(ec, ECARD_RES_IOCFAST), + ecard_resource_len(ec, ECARD_RES_IOCFAST)); + if (idmem) { + unsigned int type; + + type = readb(idmem + ICS_IDENT_OFFSET) & 1; + type |= (readb(idmem + ICS_IDENT_OFFSET + 4) & 1) << 1; + type |= (readb(idmem + ICS_IDENT_OFFSET + 8) & 1) << 2; + type |= (readb(idmem + ICS_IDENT_OFFSET + 12) & 1) << 3; + iounmap(idmem); + + state->type = type; + } + + memset(&ae, 0, sizeof(ae)); + INIT_LIST_HEAD(&ae.node); + ae.dev = &ec->dev; + ae.port_ops = &pata_icside_port_ops; + ae.sht = &pata_icside_sht; + ae.pio_mask = 0x1f; + ae.irq = ec->irq; + ae.port_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST; + ae._host_flags = ATA_HOST_SIMPLEX; + ae.private_data = state; + + switch (state->type) { + case ICS_TYPE_A3IN: + dev_warn(&ec->dev, "A3IN unsupported\n"); + ret = -ENODEV; + break; + + case ICS_TYPE_A3USER: + dev_warn(&ec->dev, "A3USER unsupported\n"); + ret = -ENODEV; + break; + + case ICS_TYPE_V5: + ret = pata_icside_register_v5(&ae, ec); + break; + + case ICS_TYPE_V6: + ret = pata_icside_register_v6(&ae, ec); + break; + + default: + dev_warn(&ec->dev, "unknown interface type\n"); + ret = -ENODEV; + break; + } + + if (ret == 0) + ret = ata_device_add(&ae) == 0 ? -ENODEV : 0; + + if (ret == 0) + goto out; + + kfree(state); + release: + ecard_release_resources(ec); + out: + return ret; +} + +static void pata_icside_shutdown(struct expansion_card *ec) +{ + struct ata_host *host = ecard_get_drvdata(ec); + unsigned long flags; + + /* + * Disable interrupts from this card. We need to do + * this before disabling EASI since we may be accessing + * this register via that region. + */ + local_irq_save(flags); + if (ec->ops) + ec->ops->irqdisable(ec, ec->irq); + local_irq_restore(flags); + + /* + * Reset the ROM pointer so that we can read the ROM + * after a soft reboot. This also disables access to + * the IDE taskfile via the EASI region. + */ + if (host) { + struct pata_icside_state *state = host->private_data; + if (state->ioc_base) + writeb(0, state->ioc_base); + } +} + +static void __devexit pata_icside_remove(struct expansion_card *ec) +{ + struct ata_host *host = ecard_get_drvdata(ec); + struct pata_icside_state *state = host->private_data; + + ata_host_detach(host); + + pata_icside_shutdown(ec); + + /* + * don't NULL out the drvdata - devres/libata wants it + * to free the ata_host structure. + */ + ec->ops = NULL; + ec->irq_data = NULL; + + if (state->dma != NO_DMA) + free_dma(state->dma); + if (state->ioc_base) + iounmap(state->ioc_base); + if (state->ioc_base != state->irq_port) + iounmap(state->irq_port); + + kfree(state); + ecard_release_resources(ec); +} + +static const struct ecard_id pata_icside_ids[] = { + { MANU_ICS, PROD_ICS_IDE }, + { MANU_ICS2, PROD_ICS2_IDE }, + { 0xffff, 0xffff } +}; + +static struct ecard_driver pata_icside_driver = { + .probe = pata_icside_probe, + .remove = __devexit_p(pata_icside_remove), + .shutdown = pata_icside_shutdown, + .id_table = pata_icside_ids, + .drv = { + .name = DRV_NAME, + }, +}; + +static int __init pata_icside_init(void) +{ + return ecard_register_driver(&pata_icside_driver); +} + +static void __exit pata_icside_exit(void) +{ + ecard_remove_driver(&pata_icside_driver); +} + +MODULE_AUTHOR("Russell King "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("ICS PATA driver"); + +module_init(pata_icside_init); +module_exit(pata_icside_exit); -- cgit v1.2.2 From ff4bfb2163e8914332267be3758eb28239460316 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 26 Apr 2007 08:26:13 +0100 Subject: [ARM] 4328/1: Move i.MX UART regs to driver This patch moves the i.MX UART register descriptions from include/asm-arm/arch-imx/imx-regs.h to the serial driver itself. This helps using the driver on other architectures like mx31 Signed-off-by: Sascha Hauer Signed-off-by: Russell King --- drivers/serial/imx.c | 268 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 205 insertions(+), 63 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index 04cc88cc528c..e42faa4e4282 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c @@ -46,6 +46,122 @@ #include #include +/* Register definitions */ +#define URXD0 0x0 /* Receiver Register */ +#define URTX0 0x40 /* Transmitter Register */ +#define UCR1 0x80 /* Control Register 1 */ +#define UCR2 0x84 /* Control Register 2 */ +#define UCR3 0x88 /* Control Register 3 */ +#define UCR4 0x8c /* Control Register 4 */ +#define UFCR 0x90 /* FIFO Control Register */ +#define USR1 0x94 /* Status Register 1 */ +#define USR2 0x98 /* Status Register 2 */ +#define UESC 0x9c /* Escape Character Register */ +#define UTIM 0xa0 /* Escape Timer Register */ +#define UBIR 0xa4 /* BRM Incremental Register */ +#define UBMR 0xa8 /* BRM Modulator Register */ +#define UBRC 0xac /* Baud Rate Count Register */ +#define BIPR1 0xb0 /* Incremental Preset Register 1 */ +#define BIPR2 0xb4 /* Incremental Preset Register 2 */ +#define BIPR3 0xb8 /* Incremental Preset Register 3 */ +#define BIPR4 0xbc /* Incremental Preset Register 4 */ +#define BMPR1 0xc0 /* BRM Modulator Register 1 */ +#define BMPR2 0xc4 /* BRM Modulator Register 2 */ +#define BMPR3 0xc8 /* BRM Modulator Register 3 */ +#define BMPR4 0xcc /* BRM Modulator Register 4 */ +#define UTS 0xd0 /* UART Test Register */ + +/* UART Control Register Bit Fields.*/ +#define URXD_CHARRDY (1<<15) +#define URXD_ERR (1<<14) +#define URXD_OVRRUN (1<<13) +#define URXD_FRMERR (1<<12) +#define URXD_BRK (1<<11) +#define URXD_PRERR (1<<10) +#define UCR1_ADEN (1<<15) /* Auto dectect interrupt */ +#define UCR1_ADBR (1<<14) /* Auto detect baud rate */ +#define UCR1_TRDYEN (1<<13) /* Transmitter ready interrupt enable */ +#define UCR1_IDEN (1<<12) /* Idle condition interrupt */ +#define UCR1_RRDYEN (1<<9) /* Recv ready interrupt enable */ +#define UCR1_RDMAEN (1<<8) /* Recv ready DMA enable */ +#define UCR1_IREN (1<<7) /* Infrared interface enable */ +#define UCR1_TXMPTYEN (1<<6) /* Transimitter empty interrupt enable */ +#define UCR1_RTSDEN (1<<5) /* RTS delta interrupt enable */ +#define UCR1_SNDBRK (1<<4) /* Send break */ +#define UCR1_TDMAEN (1<<3) /* Transmitter ready DMA enable */ +#define UCR1_UARTCLKEN (1<<2) /* UART clock enabled */ +#define UCR1_DOZE (1<<1) /* Doze */ +#define UCR1_UARTEN (1<<0) /* UART enabled */ +#define UCR2_ESCI (1<<15) /* Escape seq interrupt enable */ +#define UCR2_IRTS (1<<14) /* Ignore RTS pin */ +#define UCR2_CTSC (1<<13) /* CTS pin control */ +#define UCR2_CTS (1<<12) /* Clear to send */ +#define UCR2_ESCEN (1<<11) /* Escape enable */ +#define UCR2_PREN (1<<8) /* Parity enable */ +#define UCR2_PROE (1<<7) /* Parity odd/even */ +#define UCR2_STPB (1<<6) /* Stop */ +#define UCR2_WS (1<<5) /* Word size */ +#define UCR2_RTSEN (1<<4) /* Request to send interrupt enable */ +#define UCR2_TXEN (1<<2) /* Transmitter enabled */ +#define UCR2_RXEN (1<<1) /* Receiver enabled */ +#define UCR2_SRST (1<<0) /* SW reset */ +#define UCR3_DTREN (1<<13) /* DTR interrupt enable */ +#define UCR3_PARERREN (1<<12) /* Parity enable */ +#define UCR3_FRAERREN (1<<11) /* Frame error interrupt enable */ +#define UCR3_DSR (1<<10) /* Data set ready */ +#define UCR3_DCD (1<<9) /* Data carrier detect */ +#define UCR3_RI (1<<8) /* Ring indicator */ +#define UCR3_TIMEOUTEN (1<<7) /* Timeout interrupt enable */ +#define UCR3_RXDSEN (1<<6) /* Receive status interrupt enable */ +#define UCR3_AIRINTEN (1<<5) /* Async IR wake interrupt enable */ +#define UCR3_AWAKEN (1<<4) /* Async wake interrupt enable */ +#define UCR3_REF25 (1<<3) /* Ref freq 25 MHz */ +#define UCR3_REF30 (1<<2) /* Ref Freq 30 MHz */ +#define UCR3_INVT (1<<1) /* Inverted Infrared transmission */ +#define UCR3_BPEN (1<<0) /* Preset registers enable */ +#define UCR4_CTSTL_32 (32<<10) /* CTS trigger level (32 chars) */ +#define UCR4_INVR (1<<9) /* Inverted infrared reception */ +#define UCR4_ENIRI (1<<8) /* Serial infrared interrupt enable */ +#define UCR4_WKEN (1<<7) /* Wake interrupt enable */ +#define UCR4_REF16 (1<<6) /* Ref freq 16 MHz */ +#define UCR4_IRSC (1<<5) /* IR special case */ +#define UCR4_TCEN (1<<3) /* Transmit complete interrupt enable */ +#define UCR4_BKEN (1<<2) /* Break condition interrupt enable */ +#define UCR4_OREN (1<<1) /* Receiver overrun interrupt enable */ +#define UCR4_DREN (1<<0) /* Recv data ready interrupt enable */ +#define UFCR_RXTL_SHF 0 /* Receiver trigger level shift */ +#define UFCR_RFDIV (7<<7) /* Reference freq divider mask */ +#define UFCR_TXTL_SHF 10 /* Transmitter trigger level shift */ +#define USR1_PARITYERR (1<<15) /* Parity error interrupt flag */ +#define USR1_RTSS (1<<14) /* RTS pin status */ +#define USR1_TRDY (1<<13) /* Transmitter ready interrupt/dma flag */ +#define USR1_RTSD (1<<12) /* RTS delta */ +#define USR1_ESCF (1<<11) /* Escape seq interrupt flag */ +#define USR1_FRAMERR (1<<10) /* Frame error interrupt flag */ +#define USR1_RRDY (1<<9) /* Receiver ready interrupt/dma flag */ +#define USR1_TIMEOUT (1<<7) /* Receive timeout interrupt status */ +#define USR1_RXDS (1<<6) /* Receiver idle interrupt flag */ +#define USR1_AIRINT (1<<5) /* Async IR wake interrupt flag */ +#define USR1_AWAKE (1<<4) /* Aysnc wake interrupt flag */ +#define USR2_ADET (1<<15) /* Auto baud rate detect complete */ +#define USR2_TXFE (1<<14) /* Transmit buffer FIFO empty */ +#define USR2_DTRF (1<<13) /* DTR edge interrupt flag */ +#define USR2_IDLE (1<<12) /* Idle condition */ +#define USR2_IRINT (1<<8) /* Serial infrared interrupt flag */ +#define USR2_WAKE (1<<7) /* Wake */ +#define USR2_RTSF (1<<4) /* RTS edge interrupt flag */ +#define USR2_TXDC (1<<3) /* Transmitter complete */ +#define USR2_BRCD (1<<2) /* Break condition */ +#define USR2_ORE (1<<1) /* Overrun error */ +#define USR2_RDR (1<<0) /* Recv data ready */ +#define UTS_FRCPERR (1<<13) /* Force parity error */ +#define UTS_LOOP (1<<12) /* Loop tx and rx */ +#define UTS_TXEMPTY (1<<6) /* TxFIFO empty */ +#define UTS_RXEMPTY (1<<5) /* RxFIFO empty */ +#define UTS_TXFULL (1<<4) /* TxFIFO full */ +#define UTS_RXFULL (1<<3) /* RxFIFO full */ +#define UTS_SOFTRST (1<<0) /* Software reset */ + /* We've been assigned a range on the "Low-density serial ports" major */ #define SERIAL_IMX_MAJOR 204 #define MINOR_START 41 @@ -128,7 +244,10 @@ static void imx_timeout(unsigned long data) static void imx_stop_tx(struct uart_port *port) { struct imx_port *sport = (struct imx_port *)port; - UCR1((u32)sport->port.membase) &= ~UCR1_TXMPTYEN; + unsigned long temp; + + temp = readl(sport->port.membase + UCR1); + writel(temp & ~UCR1_TXMPTYEN, sport->port.membase + UCR1); } /* @@ -137,7 +256,10 @@ static void imx_stop_tx(struct uart_port *port) static void imx_stop_rx(struct uart_port *port) { struct imx_port *sport = (struct imx_port *)port; - UCR2((u32)sport->port.membase) &= ~UCR2_RXEN; + unsigned long temp; + + temp = readl(sport->port.membase + UCR2); + writel(temp &~ UCR2_RXEN, sport->port.membase + UCR2); } /* @@ -154,10 +276,10 @@ static inline void imx_transmit_buffer(struct imx_port *sport) { struct circ_buf *xmit = &sport->port.info->xmit; - while (!(UTS((u32)sport->port.membase) & UTS_TXFULL)) { + while (!(readl(sport->port.membase + UTS) & UTS_TXFULL)) { /* send xmit->buf[xmit->tail] * out the port here */ - URTX0((u32)sport->port.membase) = xmit->buf[xmit->tail]; + writel(xmit->buf[xmit->tail], sport->port.membase + URTX0); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); sport->port.icount.tx++; @@ -175,21 +297,24 @@ static inline void imx_transmit_buffer(struct imx_port *sport) static void imx_start_tx(struct uart_port *port) { struct imx_port *sport = (struct imx_port *)port; + unsigned long temp; - UCR1((u32)sport->port.membase) |= UCR1_TXMPTYEN; + temp = readl(sport->port.membase + UCR1); + writel(temp | UCR1_TXMPTYEN, sport->port.membase + UCR1); - imx_transmit_buffer(sport); + if (readl(sport->port.membase + UTS) & UTS_TXEMPTY) + imx_transmit_buffer(sport); } static irqreturn_t imx_rtsint(int irq, void *dev_id) { struct imx_port *sport = (struct imx_port *)dev_id; - unsigned int val = USR1((u32)sport->port.membase)&USR1_RTSS; + unsigned int val = readl(sport->port.membase + USR1) & USR1_RTSS; unsigned long flags; spin_lock_irqsave(&sport->port.lock, flags); - USR1((u32)sport->port.membase) = USR1_RTSD; + writel(USR1_RTSD, sport->port.membase + USR1); uart_handle_cts_change(&sport->port, !!val); wake_up_interruptible(&sport->port.info->delta_msr_wait); @@ -207,7 +332,7 @@ static irqreturn_t imx_txint(int irq, void *dev_id) if (sport->port.x_char) { /* Send next char */ - URTX0((u32)sport->port.membase) = sport->port.x_char; + writel(sport->port.x_char, sport->port.membase + URTX0); goto out; } @@ -231,17 +356,18 @@ static irqreturn_t imx_rxint(int irq, void *dev_id) struct imx_port *sport = dev_id; unsigned int rx,flg,ignored = 0; struct tty_struct *tty = sport->port.info->tty; - unsigned long flags; + unsigned long flags, temp; - rx = URXD0((u32)sport->port.membase); + rx = readl(sport->port.membase + URXD0); spin_lock_irqsave(&sport->port.lock,flags); do { flg = TTY_NORMAL; sport->port.icount.rx++; - if( USR2((u32)sport->port.membase) & USR2_BRCD ) { - USR2((u32)sport->port.membase) |= USR2_BRCD; + temp = readl(sport->port.membase + USR2); + if( temp & USR2_BRCD ) { + writel(temp | USR2_BRCD, sport->port.membase + USR2); if(uart_handle_break(&sport->port)) goto ignore_char; } @@ -257,7 +383,7 @@ static irqreturn_t imx_rxint(int irq, void *dev_id) tty_insert_flip_char(tty, rx, flg); ignore_char: - rx = URXD0((u32)sport->port.membase); + rx = readl(sport->port.membase + URXD0); } while(rx & URXD_CHARRDY); out: @@ -301,7 +427,7 @@ static unsigned int imx_tx_empty(struct uart_port *port) { struct imx_port *sport = (struct imx_port *)port; - return USR2((u32)sport->port.membase) & USR2_TXDC ? TIOCSER_TEMT : 0; + return (readl(sport->port.membase + USR2) & USR2_TXDC) ? TIOCSER_TEMT : 0; } /* @@ -312,10 +438,10 @@ static unsigned int imx_get_mctrl(struct uart_port *port) struct imx_port *sport = (struct imx_port *)port; unsigned int tmp = TIOCM_DSR | TIOCM_CAR; - if (USR1((u32)sport->port.membase) & USR1_RTSS) + if (readl(sport->port.membase + USR1) & USR1_RTSS) tmp |= TIOCM_CTS; - if (UCR2((u32)sport->port.membase) & UCR2_CTS) + if (readl(sport->port.membase + UCR2) & UCR2_CTS) tmp |= TIOCM_RTS; return tmp; @@ -324,11 +450,14 @@ static unsigned int imx_get_mctrl(struct uart_port *port) static void imx_set_mctrl(struct uart_port *port, unsigned int mctrl) { struct imx_port *sport = (struct imx_port *)port; + unsigned long temp; + + temp = readl(sport->port.membase + UCR2) & ~UCR2_CTS; if (mctrl & TIOCM_RTS) - UCR2((u32)sport->port.membase) |= UCR2_CTS; - else - UCR2((u32)sport->port.membase) &= ~UCR2_CTS; + temp |= UCR2_CTS; + + writel(temp, sport->port.membase + UCR2); } /* @@ -337,14 +466,16 @@ static void imx_set_mctrl(struct uart_port *port, unsigned int mctrl) static void imx_break_ctl(struct uart_port *port, int break_state) { struct imx_port *sport = (struct imx_port *)port; - unsigned long flags; + unsigned long flags, temp; spin_lock_irqsave(&sport->port.lock, flags); + temp = readl(sport->port.membase + UCR1) & ~UCR1_SNDBRK; + if ( break_state != 0 ) - UCR1((u32)sport->port.membase) |= UCR1_SNDBRK; - else - UCR1((u32)sport->port.membase) &= ~UCR1_SNDBRK; + temp |= UCR1_SNDBRK; + + writel(temp, sport->port.membase + UCR1); spin_unlock_irqrestore(&sport->port.lock, flags); } @@ -360,7 +491,7 @@ static int imx_setup_ufcr(struct imx_port *sport, unsigned int mode) /* set receiver / transmitter trigger level. * RFDIV is set such way to satisfy requested uartclk value */ - val = TXTL<<10 | RXTL; + val = TXTL << 10 | RXTL; ufcr_rfdiv = (imx_get_perclk1() + sport->port.uartclk / 2) / sport->port.uartclk; if(!ufcr_rfdiv) @@ -373,7 +504,7 @@ static int imx_setup_ufcr(struct imx_port *sport, unsigned int mode) val |= UFCR_RFDIV & (ufcr_rfdiv << 7); - UFCR((u32)sport->port.membase) = val; + writel(val, sport->port.membase + UFCR); return 0; } @@ -382,14 +513,15 @@ static int imx_startup(struct uart_port *port) { struct imx_port *sport = (struct imx_port *)port; int retval; - unsigned long flags; + unsigned long flags, temp; imx_setup_ufcr(sport, 0); /* disable the DREN bit (Data Ready interrupt enable) before * requesting IRQs */ - UCR4((u32)sport->port.membase) &= ~UCR4_DREN; + temp = readl(sport->port.membase + UCR4); + writel(temp & ~UCR4_DREN, sport->port.membase + UCR4); /* * Allocate the IRQ @@ -411,12 +543,16 @@ static int imx_startup(struct uart_port *port) /* * Finally, clear and enable interrupts */ + writel(USR1_RTSD, sport->port.membase + USR1); + + temp = readl(sport->port.membase + UCR1); + temp |= (UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN); + writel(temp, sport->port.membase + UCR1); - USR1((u32)sport->port.membase) = USR1_RTSD; - UCR1((u32)sport->port.membase) |= - (UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN); + temp = readl(sport->port.membase + UCR2); + temp |= (UCR2_RXEN | UCR2_TXEN); + writel(temp, sport->port.membase + UCR2); - UCR2((u32)sport->port.membase) |= (UCR2_RXEN | UCR2_TXEN); /* * Enable modem status interrupts */ @@ -437,6 +573,7 @@ error_out1: static void imx_shutdown(struct uart_port *port) { struct imx_port *sport = (struct imx_port *)port; + unsigned long temp; /* * Stop our timer. @@ -454,8 +591,9 @@ static void imx_shutdown(struct uart_port *port) * Disable all interrupts, port and break condition. */ - UCR1((u32)sport->port.membase) &= - ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN); + temp = readl(sport->port.membase + UCR1); + temp &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN); + writel(temp, sport->port.membase + UCR1); } static void @@ -548,18 +686,18 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios, /* * disable interrupts and drain transmitter */ - old_ucr1 = UCR1((u32)sport->port.membase); - UCR1((u32)sport->port.membase) &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN); + old_ucr1 = readl(sport->port.membase + UCR1); + writel(old_ucr1 & ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN), + sport->port.membase + UCR1); - while ( !(USR2((u32)sport->port.membase) & USR2_TXDC)) + while ( !(readl(sport->port.membase + USR2) & USR2_TXDC)) barrier(); /* then, disable everything */ - old_txrxen = UCR2((u32)sport->port.membase) & ( UCR2_TXEN | UCR2_RXEN ); - UCR2((u32)sport->port.membase) &= ~( UCR2_TXEN | UCR2_RXEN); - - /* set the parity, stop bits and data size */ - UCR2((u32)sport->port.membase) = ucr2; + old_txrxen = readl(sport->port.membase + UCR2); + writel(old_txrxen & ~( UCR2_TXEN | UCR2_RXEN), + sport->port.membase + UCR2); + old_txrxen &= (UCR2_TXEN | UCR2_RXEN); /* set the baud rate. We assume uartclk = 16 MHz * @@ -567,11 +705,13 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios, * --------- = -------- * uartclk UBMR - 1 */ - UBIR((u32)sport->port.membase) = (baud / 100) - 1; - UBMR((u32)sport->port.membase) = 10000 - 1; + writel((baud / 100) - 1, sport->port.membase + UBIR); + writel(10000 - 1, sport->port.membase + UBMR); + + writel(old_ucr1, sport->port.membase + UCR1); - UCR1((u32)sport->port.membase) = old_ucr1; - UCR2((u32)sport->port.membase) |= old_txrxen; + /* set the parity, stop bits and data size */ + writel(ucr2 | old_txrxen, sport->port.membase + UCR2); if (UART_ENABLE_MS(&sport->port, termios->c_cflag)) imx_enable_ms(&sport->port); @@ -730,9 +870,11 @@ static void __init imx_init_ports(void) static void imx_console_putchar(struct uart_port *port, int ch) { struct imx_port *sport = (struct imx_port *)port; - while ((UTS((u32)sport->port.membase) & UTS_TXFULL)) + + while (readl(sport->port.membase + UTS) & UTS_TXFULL) barrier(); - URTX0((u32)sport->port.membase) = ch; + + writel(ch, sport->port.membase + URTX0); } /* @@ -747,13 +889,14 @@ imx_console_write(struct console *co, const char *s, unsigned int count) /* * First, save UCR1/2 and then disable interrupts */ - old_ucr1 = UCR1((u32)sport->port.membase); - old_ucr2 = UCR2((u32)sport->port.membase); + old_ucr1 = readl(sport->port.membase + UCR1); + old_ucr2 = readl(sport->port.membase + UCR2); - UCR1((u32)sport->port.membase) = - (old_ucr1 | UCR1_UARTCLKEN | UCR1_UARTEN) - & ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN); - UCR2((u32)sport->port.membase) = old_ucr2 | UCR2_TXEN; + writel((old_ucr1 | UCR1_UARTCLKEN | UCR1_UARTEN) & + ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN), + sport->port.membase + UCR1); + + writel(old_ucr2 | UCR2_TXEN, sport->port.membase + UCR2); uart_console_write(&sport->port, s, count, imx_console_putchar); @@ -761,10 +904,10 @@ imx_console_write(struct console *co, const char *s, unsigned int count) * Finally, wait for transmitter to become empty * and restore UCR1/2 */ - while (!(USR2((u32)sport->port.membase) & USR2_TXDC)); + while (!(readl(sport->port.membase + USR2) & USR2_TXDC)); - UCR1((u32)sport->port.membase) = old_ucr1; - UCR2((u32)sport->port.membase) = old_ucr2; + writel(old_ucr1, sport->port.membase + UCR1); + writel(old_ucr2, sport->port.membase + UCR2); } /* @@ -776,13 +919,13 @@ imx_console_get_options(struct imx_port *sport, int *baud, int *parity, int *bits) { - if ( UCR1((u32)sport->port.membase) | UCR1_UARTEN ) { + if ( readl(sport->port.membase + UCR1) | UCR1_UARTEN ) { /* ok, the port was enabled */ unsigned int ucr2, ubir,ubmr, uartclk; unsigned int baud_raw; unsigned int ucfr_rfdiv; - ucr2 = UCR2((u32)sport->port.membase); + ucr2 = readl(sport->port.membase + UCR2); *parity = 'n'; if (ucr2 & UCR2_PREN) { @@ -797,11 +940,10 @@ imx_console_get_options(struct imx_port *sport, int *baud, else *bits = 7; - ubir = UBIR((u32)sport->port.membase) & 0xffff; - ubmr = UBMR((u32)sport->port.membase) & 0xffff; - + ubir = readl(sport->port.membase + UBIR) & 0xffff; + ubmr = readl(sport->port.membase + UBMR) & 0xffff; - ucfr_rfdiv = (UFCR((u32)sport->port.membase) & UFCR_RFDIV) >> 7; + ucfr_rfdiv = (readl(sport->port.membase + UFCR) & UFCR_RFDIV) >> 7; if (ucfr_rfdiv == 6) ucfr_rfdiv = 7; else -- cgit v1.2.2