Modified: branches/2009R1/drivers/serial/bfin_sport_uart.c (6779 => 6780)
--- branches/2009R1/drivers/serial/bfin_sport_uart.c 2009-06-18 04:32:27 UTC (rev 6779)
+++ branches/2009R1/drivers/serial/bfin_sport_uart.c 2009-06-18 10:32:20 UTC (rev 6780)
@@ -1,27 +1,11 @@
/*
- * File: linux/drivers/serial/bfin_sport_uart.c
+ * Blackfin On-Chip Sport Emulated UART Driver
*
- * Based on: drivers/serial/bfin_5xx.c by Aubrey Li.
- * Author: Roy Huang <[email protected]>
+ * Copyright 2006-2008 Analog Devices Inc.
*
- * Created: Nov 22, 2006
- * Copyright: (c) 2006-2007 Analog Devices Inc.
- * Description: this driver enable SPORTs on Blackfin emulate UART.
+ * Enter bugs at http://blackfin.uclinux.org/
*
- * 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; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * Licensed under the GPL-2 or later.
*/
/*
@@ -29,37 +13,11 @@
* http://www.analog.com/UploadedFiles/Application_Notes/399447663EE191.pdf
* This application note describe how to implement a UART on a Sharc DSP,
* but this driver is implemented on Blackfin Processor.
+ * Transmit Frame Sync is not used by this driver to transfer data out.
*/
-/* After reset, there is a prelude of low level pulse when transmit data first
- * time. No addtional pulse in following transmit.
- * According to document:
- * The SPORTs are ready to start transmitting or receiving data no later than
- * three serial clock cycles after they are enabled in the SPORTx_TCR1 or
- * SPORTx_RCR1 register. No serial clock cycles are lost from this point on.
- * The first internal frame sync will occur one frame sync delay after the
- * SPORTs are ready. External frame syncs can occur as soon as the SPORT is
- * ready.
- */
+/* #define DEBUG */
-/* Thanks to Axel Alatalo <[email protected]> for fixing sport rx bug. Sometimes
- * sport receives data incorrectly. The following is Axel's words.
- * As EE-191, sport rx samples 3 times of the UART baudrate and takes the
- * middle smaple of every 3 samples as the data bit. For a 8-N-1 UART setting,
- * 30 samples will be required for a byte. If transmitter sends a 1/3 bit short
- * byte due to buadrate drift, then the 30th sample of a byte, this sample is
- * also the third sample of the stop bit, will happens on the immediately
- * following start bit which will be thrown away and missed. Thus since parts
- * of the startbit will be missed and the receiver will begin to drift, the
- * effect accumulates over time until synchronization is lost.
- * If only require 2 samples of the stopbit (by sampling in total 29 samples),
- * then a to short byte as in the case above will be tolerated. Then the 1/3
- * early startbit will trigger a framesync since the last read is complete
- * after only 2/3 stopbit and framesync is active during the last 1/3 looking
- * for a possible early startbit. */
-
-//#define DEBUG
-
#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/init.h>
@@ -84,6 +42,7 @@
P_SPORT1_DRPRI, P_SPORT1_RSCLK, P_SPORT1_DRSEC, P_SPORT1_DTSEC, 0};
#define DRV_NAME "bfin-sport-uart"
+#define DEVICE_NAME "ttySS"
struct sport_uart_port {
struct uart_port port;
@@ -91,6 +50,12 @@
int tx_irq;
int rx_irq;
int err_irq;
+ unsigned short csize;
+ unsigned short rxmask;
+ unsigned short txmask1;
+ unsigned short txmask2;
+ unsigned char stopb;
+/* unsigned char parib; */
};
static void sport_uart_tx_chars(struct sport_uart_port *up);
@@ -98,37 +63,42 @@
static inline void tx_one_byte(struct sport_uart_port *up, unsigned int value)
{
- pr_debug("%s value:%x\n", __func__, value);
- /* Place a Start and Stop bit */
+ pr_debug("%s value:%x, mask1=0x%x, mask2=0x%x\n", __func__, value,
+ up->txmask1, up->txmask2);
+
+ /* Place Start and Stop bits */
__asm__ __volatile__ (
- "R2 = b#01111111100;"
- "R3 = b#10000000001;"
- "%0 <<= 2;"
- "%0 = %0 & R2;"
- "%0 = %0 | R3;"
- : "=d"(value)
- : "d"(value)
- : "ASTAT", "R2", "R3"
+ "%[val] <<= 1;"
+ "%[val] = %[val] & %[mask1];"
+ "%[val] = %[val] | %[mask2];"
+ : [val]"+d"(value)
+ : [mask1]"d"(up->txmask1), [mask2]"d"(up->txmask2)
+ : "ASTAT"
);
pr_debug("%s value:%x\n", __func__, value);
SPORT_PUT_TX(up, value);
}
-static inline unsigned char rx_one_byte(struct sport_uart_port *up)
+static unsigned char rx_one_byte(struct sport_uart_port *up)
{
unsigned int value;
unsigned char extract;
u32 tmp_mask1, tmp_mask2, tmp_shift, tmp;
- value = SPORT_GET_RX32(up);
- pr_debug("%s value:%x\n", __func__, value);
+ if ((up->csize + up->stopb) > 7)
+ value = SPORT_GET_RX32(up);
+ else
+ value = SPORT_GET_RX(up);
- /* Extract 8 bits data */
+ pr_debug("%s value:%x, cs=%d, mask=0x%x\n", __func__, value,
+ up->csize, up->rxmask);
+
+ /* Extract data */
__asm__ __volatile__ (
"%[extr] = 0;"
- "%[mask1] = 0x1801(Z);"
- "%[mask2] = 0x0300(Z);"
+ "%[mask1] = %[rxmask];"
+ "%[mask2] = 0x0200(Z);"
"%[shift] = 0;"
"LSETUP(.Lloop_s, .Lloop_e) LC0 = %[lc];"
".Lloop_s:"
@@ -138,9 +108,9 @@
"%[mask1] = %[mask1] - %[mask2];"
".Lloop_e:"
"%[shift] += 1;"
- : [val]"=d"(value), [extr]"=d"(extract), [shift]"=d"(tmp_shift), [tmp]"=d"(tmp),
- [mask1]"=d"(tmp_mask1), [mask2]"=d"(tmp_mask2)
- : "d"(value), [lc]"a"(8)
+ : [extr]"=&d"(extract), [shift]"=&d"(tmp_shift), [tmp]"=&d"(tmp),
+ [mask1]"=&d"(tmp_mask1), [mask2]"=&d"(tmp_mask2)
+ : [val]"d"(value), [rxmask]"d"(up->rxmask), [lc]"a"(up->csize)
: "ASTAT", "LB0", "LC0", "LT0"
);
@@ -148,29 +118,28 @@
return extract;
}
-static int sport_uart_setup(struct sport_uart_port *up, int sclk, int baud_rate)
+static int sport_uart_setup(struct sport_uart_port *up, int size, int baud_rate)
{
- int tclkdiv, tfsdiv, rclkdiv;
+ int tclkdiv, rclkdiv;
+ unsigned int sclk = get_sclk();
- /* Set TCR1 and TCR2 */
- SPORT_PUT_TCR1(up, (LATFS | ITFS | TFSR | TLSBIT | ITCLK));
- SPORT_PUT_TCR2(up, 10);
+ /* Set TCR1 and TCR2, TFSR is not enabled for uart */
+ SPORT_PUT_TCR1(up, (ITFS | TLSBIT | ITCLK));
+ SPORT_PUT_TCR2(up, size + 1);
pr_debug("%s TCR1:%x, TCR2:%x\n", __func__, SPORT_GET_TCR1(up), SPORT_GET_TCR2(up));
/* Set RCR1 and RCR2 */
SPORT_PUT_RCR1(up, (RCKFE | LARFS | LRFS | RFSR | IRCLK));
- SPORT_PUT_RCR2(up, 28);
+ SPORT_PUT_RCR2(up, (size + 1) * 2 - 1);
pr_debug("%s RCR1:%x, RCR2:%x\n", __func__, SPORT_GET_RCR1(up), SPORT_GET_RCR2(up));
tclkdiv = sclk/(2 * baud_rate) - 1;
- tfsdiv = 12;
- rclkdiv = sclk/(2 * baud_rate * 3) - 1;
+ rclkdiv = sclk/(2 * baud_rate * 2) - 1;
SPORT_PUT_TCLKDIV(up, tclkdiv);
- SPORT_PUT_TFSDIV(up, tfsdiv);
SPORT_PUT_RCLKDIV(up, rclkdiv);
SSYNC();
- pr_debug("%s sclk:%d, baud_rate:%d, tclkdiv:%d, tfsdiv:%d, rclkdiv:%d\n",
- __func__, sclk, baud_rate, tclkdiv, tfsdiv, rclkdiv);
+ pr_debug("%s sclk:%d, baud_rate:%d, tclkdiv:%d, rclkdiv:%d\n",
+ __func__, sclk, baud_rate, tclkdiv, rclkdiv);
return 0;
}
@@ -181,7 +150,9 @@
struct tty_struct *tty = up->port.info->port.tty;
unsigned char ch;
- do {
+ spin_lock(&up->port.lock);
+
+ while (SPORT_GET_STAT(up) & RXNE) {
ch = rx_one_byte(up);
up->port.icount.rx++;
@@ -189,16 +160,22 @@
;
else
tty_insert_flip_char(tty, ch, TTY_NORMAL);
- } while (SPORT_GET_STAT(up) & RXNE);
+ };
tty_flip_buffer_push(tty);
+ spin_unlock(&up->port.lock);
+
return IRQ_HANDLED;
}
static irqreturn_t sport_uart_tx_irq(int irq, void *dev_id)
{
- sport_uart_tx_chars(dev_id);
+ struct sport_uart_port *up = dev_id;
+ spin_lock(&up->port.lock);
+ sport_uart_tx_chars(up);
+ spin_unlock(&up->port.lock);
+
return IRQ_HANDLED;
}
@@ -208,6 +185,8 @@
struct tty_struct *tty = up->port.info->port.tty;
unsigned int stat = SPORT_GET_STAT(up);
+ spin_lock(&up->port.lock);
+
/* Overflow in RX FIFO */
if (stat & ROVF) {
up->port.icount.overrun++;
@@ -225,6 +204,7 @@
}
SSYNC();
+ spin_unlock(&up->port.lock);
return IRQ_HANDLED;
}
@@ -258,28 +238,7 @@
goto fail2;
}
- if (port->line) {
- if (peripheral_request_list(bfin_uart_pin_req_sport1, DRV_NAME))
- goto fail3;
- } else {
- if (peripheral_request_list(bfin_uart_pin_req_sport0, DRV_NAME))
- goto fail3;
- }
-
- sport_uart_setup(up, get_sclk(), port->uartclk);
-
- /* Enable receive interrupt */
- SPORT_PUT_RCR1(up, (SPORT_GET_RCR1(up) | RSPEN));
- SSYNC();
-
return 0;
-
-
-fail3:
- printk(KERN_ERR DRV_NAME
- ": Requesting Peripherals failed\n");
-
- free_irq(up->err_irq, up);
fail2:
free_irq(up->tx_irq, up);
fail1:
@@ -345,20 +304,17 @@
static void sport_stop_tx(struct uart_port *port)
{
struct sport_uart_port *up = (struct sport_uart_port *)port;
- unsigned int stat;
pr_debug("%s enter\n", __func__);
- stat = SPORT_GET_STAT(up);
- while(!(stat & TXHRE)) {
- udelay(1);
- stat = SPORT_GET_STAT(up);
- }
/* Although the hold register is empty, last byte is still in shift
- * register and not sent out yet. If baud rate is lower than default,
- * delay should be longer. For example, if the baud rate is 9600,
- * the delay must be at least 2ms by experience */
- udelay(500);
+ * register and not sent out yet. So, put a dummy data into TX FIFO.
+ * Then, sport tx stops when last byte is shift out and the dummy
+ * data is moved into the shift register.
+ */
+ SPORT_PUT_TX(up, 0xffff);
+ while (!(SPORT_GET_STAT(up) & TXHRE))
+ cpu_relax();
SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) & ~TSPEN));
SSYNC();
@@ -371,6 +327,7 @@
struct sport_uart_port *up = (struct sport_uart_port *)port;
pr_debug("%s enter\n", __func__);
+
/* Write data into SPORT FIFO before enable SPROT to transmit */
sport_uart_tx_chars(up);
@@ -411,24 +368,11 @@
SPORT_PUT_RCR1(up, (SPORT_GET_RCR1(up) & ~RSPEN));
SSYNC();
- if (port->line) {
- peripheral_free_list(bfin_uart_pin_req_sport1);
- } else {
- peripheral_free_list(bfin_uart_pin_req_sport0);
- }
-
free_irq(up->rx_irq, up);
free_irq(up->tx_irq, up);
free_irq(up->err_irq, up);
}
-static void sport_set_termios(struct uart_port *port,
- struct ktermios *termios, struct ktermios *old)
-{
- pr_debug("%s enter, c_cflag:%08x\n", __func__, termios->c_cflag);
- uart_update_timeout(port, CS8 ,port->uartclk);
-}
-
static const char *sport_type(struct uart_port *port)
{
struct sport_uart_port *up = (struct sport_uart_port *)port;
@@ -462,6 +406,116 @@
return 0;
}
+static void sport_set_termios(struct uart_port *port,
+ struct ktermios *termios, struct ktermios *old)
+{
+ struct sport_uart_port *up = (struct sport_uart_port *)port;
+ unsigned long flags;
+ int i;
+
+ pr_debug("%s enter, c_cflag:%08x\n", __func__, termios->c_cflag);
+
+ switch (termios->c_cflag & CSIZE) {
+ case CS8:
+ printk(KERN_WARNING "Warning: If you don't want to get rx underflow when"
+ "receive rx\ndata on sport, don't use 8 bit uart mode.\n");
+ up->csize = 8;
+ break;
+ case CS7:
+ up->csize = 7;
+ break;
+ case CS6:
+ up->csize = 6;
+ break;
+ case CS5:
+ up->csize = 5;
+ break;
+ default:
+ printk(KERN_ERR "%s: word lengh not supported\n",
+ __func__);
+ }
+
+ if (termios->c_cflag & CSTOPB) {
+ up->stopb = 1;
+ if (up->csize == 8)
+ printk(KERN_WARNING "If you don't want to get rx underflow when"
+ "receive rx data on sport, don't use 2 stop bits mode.\n");
+ }
+ if (termios->c_cflag & PARENB) {
+ printk(KERN_WARNING "PAREN bits is not supported yet.\n");
+/* up->parib = 1; */
+ }
+
+ port->read_status_mask = OE;
+ if (termios->c_iflag & INPCK)
+ port->read_status_mask |= (FE | PE);
+ if (termios->c_iflag & (BRKINT | PARMRK))
+ port->read_status_mask |= BI;
+
+ /*
+ * Characters to ignore
+ */
+ port->ignore_status_mask = 0;
+ if (termios->c_iflag & IGNPAR)
+ port->ignore_status_mask |= FE | PE;
+ if (termios->c_iflag & IGNBRK) {
+ port->ignore_status_mask |= BI;
+ /*
+ * If we're ignoring parity and break indicators,
+ * ignore overruns too (for real raw support).
+ */
+ if (termios->c_iflag & IGNPAR)
+ port->ignore_status_mask |= OE;
+ }
+
+ /* RX extract mask */
+ up->rxmask = 0x01 | (((up->csize + up->stopb) * 2 - 1) << 0x8);
+ /* TX masks, 8 bit data and 1 bit stop for example:
+ mask1 = b#0111111110
+ mask2 = b#1000000000
+ */
+ for (i = 0, up->txmask1 = 0; i < up->csize; i++)
+ up->txmask1 |= (1<<i);
+ up->txmask2 = (1<<i);
+ if (up->stopb) {
+ ++i;
+ up->txmask2 |= (1<<i);
+ }
+ up->txmask1 <<= 1;
+ up->txmask2 <<= 1;
+ /* uart baud rate */
+ port->uartclk = uart_get_baud_rate(port, termios, old, 0, get_sclk()/16);
+
+ spin_lock_irqsave(&up->port.lock, flags);
+
+ /* Disable UART */
+ SPORT_PUT_TCR1(up, SPORT_GET_TCR1(up) & ~TSPEN);
+ SPORT_PUT_RCR1(up, SPORT_GET_RCR1(up) & ~RSPEN);
+
+ sport_uart_setup(up, up->csize + up->stopb, port->uartclk);
+
+ /* driver TX line high after config, one dummy data is
+ * necessary to stop sport after shift one byte
+ */
+ SPORT_PUT_TX(up, 0xffff);
+ SPORT_PUT_TX(up, 0xffff);
+ SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) | TSPEN));
+ SSYNC();
+ while (!(SPORT_GET_STAT(up) & TXHRE))
+ cpu_relax();
+ SPORT_PUT_TCR1(up, SPORT_GET_TCR1(up) & ~TSPEN);
+ SSYNC();
+
+ /* Port speed changed, update the per-port timeout. */
+ uart_update_timeout(port, termios->c_cflag, port->uartclk);
+
+ /* Enable sport rx */
+ SPORT_PUT_RCR1(up, SPORT_GET_RCR1(up) | RSPEN);
+ SSYNC();
+
+ spin_unlock_irqrestore(&up->port.lock, flags);
+}
+
struct uart_ops sport_uart_ops = {
.tx_empty = sport_tx_empty,
.set_mctrl = sport_set_mctrl,
@@ -488,15 +542,9 @@
.rx_irq = IRQ_SPORT0_RX,
.err_irq= IRQ_SPORT0_ERROR,
.port = {
- .type = PORT_BFIN_SPORT,
- .iotype = UPIO_MEM,
.membase = (void __iomem *)SPORT0_TCR1,
.mapbase = SPORT0_TCR1,
.irq = IRQ_SPORT0_RX,
- .uartclk = CONFIG_SPORT_BAUD_RATE,
- .fifosize = 8,
- .ops = &sport_uart_ops,
- .line = 0,
},
}, { /* SPORT 1 */
.name = "SPORT1",
@@ -504,27 +552,165 @@
.rx_irq = IRQ_SPORT1_RX,
.err_irq= IRQ_SPORT1_ERROR,
.port = {
- .type = PORT_BFIN_SPORT,
- .iotype = UPIO_MEM,
.membase = (void __iomem *)SPORT1_TCR1,
.mapbase = SPORT1_TCR1,
.irq = IRQ_SPORT1_RX,
- .uartclk = CONFIG_SPORT_BAUD_RATE,
- .fifosize = 8,
- .ops = &sport_uart_ops,
- .line = 1,
},
}
};
+static int nr_active_ports = ARRAY_SIZE(sport_uart_ports);
+
+static int __init sport_uart_init_ports(void)
+{
+ static int first = 1;
+ int i;
+
+ if (!first)
+ return 0;
+ first = 0;
+
+ if (peripheral_request_list(bfin_uart_pin_req_sport0, DRV_NAME)) {
+ printk(KERN_ERR DRV_NAME
+ ": Requesting Peripherals on sport0 failed\n");
+ return -EBUSY;
+ }
+ if (peripheral_request_list(bfin_uart_pin_req_sport1, DRV_NAME)) {
+ peripheral_free_list(bfin_uart_pin_req_sport0);
+ printk(KERN_ERR DRV_NAME
+ ": Requesting Peripherals on sport 1 failed\n");
+ return -EBUSY;
+ }
+
+ for (i = 0; i < nr_active_ports; i++) {
+ spin_lock_init(&sport_uart_ports[i].port.lock);
+ sport_uart_ports[i].port.fifosize = SPORT_TX_FIFO_SIZE,
+ sport_uart_ports[i].port.ops = &sport_uart_ops;
+ sport_uart_ports[i].port.line = i;
+ sport_uart_ports[i].port.iotype = UPIO_MEM;
+ sport_uart_ports[i].port.flags = UPF_BOOT_AUTOCONF;
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_SERIAL_BFIN_SPORT_CONSOLE
+static int __init
+sport_uart_console_setup(struct console *co, char *options)
+{
+ struct sport_uart_port *up;
+ int baud = 57600;
+ int bits = 8;
+ int parity = 'n';
+ int flow = 'n';
+
+ /*
+ * Check whether an invalid uart number has been specified, and
+ * if so, search for the first available port that does have
+ * console support.
+ */
+ if (co->index == -1 || co->index >= nr_active_ports)
+ co->index = 0;
+ up = &sport_uart_ports[co->index];
+
+ if (options)
+ uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+ return uart_set_options(&up->port, co, baud, parity, bits, flow);
+}
+
+static void sport_uart_console_putchar(struct uart_port *port, int ch)
+{
+ struct sport_uart_port *up = (struct sport_uart_port *)port;
+
+ while (SPORT_GET_STAT(up) & TXF)
+ barrier();
+
+ tx_one_byte(up, ch);
+}
+
+/*
+ * Interrupts are disabled on entering
+ */
+static void
+sport_uart_console_write(struct console *co, const char *s, unsigned int count)
+{
+ struct sport_uart_port *up = &sport_uart_ports[co->index];
+ unsigned long flags;
+
+ spin_lock_irqsave(&up->port.lock, flags);
+
+ if (SPORT_GET_TCR1(up) & TSPEN)
+ uart_console_write(&up->port, s, count, sport_uart_console_putchar);
+ else {
+ /* dummy data to start sport */
+ while (SPORT_GET_STAT(up) & TXF)
+ barrier();
+ SPORT_PUT_TX(up, 0xffff);
+ /* Enable transmit, then an interrupt will generated */
+ SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) | TSPEN));
+ SSYNC();
+
+ uart_console_write(&up->port, s, count, sport_uart_console_putchar);
+
+ /* Although the hold register is empty, last byte is still in shift
+ * register and not sent out yet. So, put a dummy data into TX FIFO.
+ * Then, sport tx stops when last byte is shift out and the dummy
+ * data is moved into the shift register.
+ */
+ while (SPORT_GET_STAT(up) & TXF)
+ barrier();
+ SPORT_PUT_TX(up, 0xffff);
+ while (!(SPORT_GET_STAT(up) & TXHRE))
+ barrier();
+
+ /* Stop sport tx transfer */
+ SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) & ~TSPEN));
+ SSYNC();
+ }
+
+ spin_unlock_irqrestore(&up->port.lock, flags);
+
+}
+
+static struct uart_driver sport_uart_reg;
+
+static struct console sport_uart_console = {
+ .name = DEVICE_NAME,
+ .write = sport_uart_console_write,
+ .device = uart_console_device,
+ .setup = sport_uart_console_setup,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+ .data = ""
+};
+
+static int __init sport_uart_rs_console_init(void)
+{
+ if (sport_uart_init_ports())
+ return -EBUSY;
+
+ register_console(&sport_uart_console);
+
+ return 0;
+}
+console_initcall(sport_uart_rs_console_init);
+
+#define SPORT_UART_CONSOLE (&sport_uart_console)
+#else
+#define SPORT_UART_CONSOLE NULL
+#endif /* CONFIG_SERIAL_BFIN_CONSOLE */
+
+
+
static struct uart_driver sport_uart_reg = {
.owner = THIS_MODULE,
- .driver_name = "SPORT-UART",
- .dev_name = "ttySS",
+ .driver_name = DRV_NAME,
+ .dev_name = DEVICE_NAME,
.major = 204,
.minor = 84,
.nr = ARRAY_SIZE(sport_uart_ports),
- .cons = NULL,
+ .cons = SPORT_UART_CONSOLE,
};
static int sport_uart_suspend(struct platform_device *dev, pm_message_t state)
@@ -587,6 +773,10 @@
int ret;
pr_debug("%s enter\n", __func__);
+
+ if (sport_uart_init_ports())
+ return -EBUSY;
+
ret = uart_register_driver(&sport_uart_reg);
if (ret != 0) {
printk(KERN_ERR "Failed to register %s:%d\n",
@@ -610,6 +800,9 @@
pr_debug("%s enter\n", __func__);
platform_driver_unregister(&sport_uart_driver);
uart_unregister_driver(&sport_uart_reg);
+
+ peripheral_free_list(bfin_uart_pin_req_sport1);
+ peripheral_free_list(bfin_uart_pin_req_sport0);
}
module_init(sport_uart_init);