mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-20 00:11:22 +00:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6: (25 commits) serial: Tidy REMOTE_DEBUG serial: isicomm: handle running out of slots serial: bfin_sport_uart: Use resource size to fix off-by-one error tty: fix obsolete comment on tty_insert_flip_string_fixed_flag serial: Add driver for the Altera UART serial: Add driver for the Altera JTAG UART serial: timbuart: make sure last byte is sent when port is closed serial: two branches the same in timbuart_set_mctrl() serial: uartlite: move from byte accesses to word accesses tty: n_gsm: depends on NET tty: n_gsm line discipline serial: TTY: new ldiscs for staging serial: bfin_sport_uart: drop redundant cpu depends serial: bfin_sport_uart: drop the experimental markings serial: bfin_sport_uart: pull in bfin_sport.h for SPORT defines serial: bfin_sport_uart: only enable SPORT TX if data is to be sent serial: bfin_sport_uart: drop useless status masks serial: bfin_sport_uart: zero sport_uart_port if allocated dynamically serial: bfin_sport_uart: protect changes to uart_port serial: bfin_sport_uart: add support for CTS/RTS via GPIOs ...
This commit is contained in:
commit
7f02ab3ce3
@ -276,11 +276,19 @@ config N_HDLC
|
|||||||
Allows synchronous HDLC communications with tty device drivers that
|
Allows synchronous HDLC communications with tty device drivers that
|
||||||
support synchronous HDLC such as the Microgate SyncLink adapter.
|
support synchronous HDLC such as the Microgate SyncLink adapter.
|
||||||
|
|
||||||
This driver can only be built as a module ( = code which can be
|
This driver can be built as a module ( = code which can be
|
||||||
inserted in and removed from the running kernel whenever you want).
|
inserted in and removed from the running kernel whenever you want).
|
||||||
The module will be called n_hdlc. If you want to do that, say M
|
The module will be called n_hdlc. If you want to do that, say M
|
||||||
here.
|
here.
|
||||||
|
|
||||||
|
config N_GSM
|
||||||
|
tristate "GSM MUX line discipline support (EXPERIMENTAL)"
|
||||||
|
depends on EXPERIMENTAL
|
||||||
|
depends on NET
|
||||||
|
help
|
||||||
|
This line discipline provides support for the GSM MUX protocol and
|
||||||
|
presents the mux as a set of 61 individual tty devices.
|
||||||
|
|
||||||
config RISCOM8
|
config RISCOM8
|
||||||
tristate "SDL RISCom/8 card support"
|
tristate "SDL RISCom/8 card support"
|
||||||
depends on SERIAL_NONSTANDARD
|
depends on SERIAL_NONSTANDARD
|
||||||
|
@ -40,6 +40,7 @@ obj-$(CONFIG_SYNCLINK) += synclink.o
|
|||||||
obj-$(CONFIG_SYNCLINKMP) += synclinkmp.o
|
obj-$(CONFIG_SYNCLINKMP) += synclinkmp.o
|
||||||
obj-$(CONFIG_SYNCLINK_GT) += synclink_gt.o
|
obj-$(CONFIG_SYNCLINK_GT) += synclink_gt.o
|
||||||
obj-$(CONFIG_N_HDLC) += n_hdlc.o
|
obj-$(CONFIG_N_HDLC) += n_hdlc.o
|
||||||
|
obj-$(CONFIG_N_GSM) += n_gsm.o
|
||||||
obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o
|
obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o
|
||||||
obj-$(CONFIG_SX) += sx.o generic_serial.o
|
obj-$(CONFIG_SX) += sx.o generic_serial.o
|
||||||
obj-$(CONFIG_RIO) += rio/ generic_serial.o
|
obj-$(CONFIG_RIO) += rio/ generic_serial.o
|
||||||
|
@ -1573,11 +1573,16 @@ static int __devinit isicom_probe(struct pci_dev *pdev,
|
|||||||
dev_info(&pdev->dev, "ISI PCI Card(Device ID 0x%x)\n", ent->device);
|
dev_info(&pdev->dev, "ISI PCI Card(Device ID 0x%x)\n", ent->device);
|
||||||
|
|
||||||
/* allot the first empty slot in the array */
|
/* allot the first empty slot in the array */
|
||||||
for (index = 0; index < BOARD_COUNT; index++)
|
for (index = 0; index < BOARD_COUNT; index++) {
|
||||||
if (isi_card[index].base == 0) {
|
if (isi_card[index].base == 0) {
|
||||||
board = &isi_card[index];
|
board = &isi_card[index];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (index == BOARD_COUNT) {
|
||||||
|
retval = -ENODEV;
|
||||||
|
goto err_disable;
|
||||||
|
}
|
||||||
|
|
||||||
board->index = index;
|
board->index = index;
|
||||||
board->base = pci_resource_start(pdev, 3);
|
board->base = pci_resource_start(pdev, 3);
|
||||||
@ -1624,6 +1629,7 @@ errunrr:
|
|||||||
errdec:
|
errdec:
|
||||||
board->base = 0;
|
board->base = 0;
|
||||||
card_count--;
|
card_count--;
|
||||||
|
err_disable:
|
||||||
pci_disable_device(pdev);
|
pci_disable_device(pdev);
|
||||||
err:
|
err:
|
||||||
return retval;
|
return retval;
|
||||||
|
2763
drivers/char/n_gsm.c
Normal file
2763
drivers/char/n_gsm.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -176,23 +176,6 @@ static void config_setup(struct cyclades_port *);
|
|||||||
static void show_status(int);
|
static void show_status(int);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_REMOTE_DEBUG
|
|
||||||
static void debug_setup(void);
|
|
||||||
void queueDebugChar(int c);
|
|
||||||
int getDebugChar(void);
|
|
||||||
|
|
||||||
#define DEBUG_PORT 1
|
|
||||||
#define DEBUG_LEN 256
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int in;
|
|
||||||
int out;
|
|
||||||
unsigned char buf[DEBUG_LEN];
|
|
||||||
} debugq;
|
|
||||||
|
|
||||||
debugq debugiq;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* I have my own version of udelay(), as it is needed when initialising
|
* I have my own version of udelay(), as it is needed when initialising
|
||||||
* the chip, before the delay loop has been calibrated. Should probably
|
* the chip, before the delay loop has been calibrated. Should probably
|
||||||
@ -515,11 +498,6 @@ static irqreturn_t cd2401_tx_interrupt(int irq, void *dev_id)
|
|||||||
/* determine the channel and change to that context */
|
/* determine the channel and change to that context */
|
||||||
channel = (u_short) (base_addr[CyLICR] >> 2);
|
channel = (u_short) (base_addr[CyLICR] >> 2);
|
||||||
|
|
||||||
#ifdef CONFIG_REMOTE_DEBUG
|
|
||||||
if (channel == DEBUG_PORT) {
|
|
||||||
panic("TxInt on debug port!!!");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
/* validate the port number (as configured and open) */
|
/* validate the port number (as configured and open) */
|
||||||
if ((channel < 0) || (NR_PORTS <= channel)) {
|
if ((channel < 0) || (NR_PORTS <= channel)) {
|
||||||
base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
|
base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
|
||||||
@ -634,14 +612,6 @@ static irqreturn_t cd2401_rx_interrupt(int irq, void *dev_id)
|
|||||||
info->last_active = jiffies;
|
info->last_active = jiffies;
|
||||||
save_cnt = char_count = base_addr[CyRFOC];
|
save_cnt = char_count = base_addr[CyRFOC];
|
||||||
|
|
||||||
#ifdef CONFIG_REMOTE_DEBUG
|
|
||||||
if (channel == DEBUG_PORT) {
|
|
||||||
while (char_count--) {
|
|
||||||
data = base_addr[CyRDR];
|
|
||||||
queueDebugChar(data);
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
/* if there is nowhere to put the data, discard it */
|
/* if there is nowhere to put the data, discard it */
|
||||||
if (info->tty == 0) {
|
if (info->tty == 0) {
|
||||||
while (char_count--) {
|
while (char_count--) {
|
||||||
@ -2195,9 +2165,7 @@ static int __init serial167_init(void)
|
|||||||
port_num++;
|
port_num++;
|
||||||
info++;
|
info++;
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_REMOTE_DEBUG
|
|
||||||
debug_setup();
|
|
||||||
#endif
|
|
||||||
ret = request_irq(MVME167_IRQ_SER_ERR, cd2401_rxerr_interrupt, 0,
|
ret = request_irq(MVME167_IRQ_SER_ERR, cd2401_rxerr_interrupt, 0,
|
||||||
"cd2401_errors", cd2401_rxerr_interrupt);
|
"cd2401_errors", cd2401_rxerr_interrupt);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
@ -2518,193 +2486,4 @@ static int __init serial167_console_init(void)
|
|||||||
|
|
||||||
console_initcall(serial167_console_init);
|
console_initcall(serial167_console_init);
|
||||||
|
|
||||||
#ifdef CONFIG_REMOTE_DEBUG
|
|
||||||
void putDebugChar(int c)
|
|
||||||
{
|
|
||||||
volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
|
|
||||||
unsigned long flags;
|
|
||||||
volatile u_char sink;
|
|
||||||
u_char ier;
|
|
||||||
int port;
|
|
||||||
|
|
||||||
local_irq_save(flags);
|
|
||||||
|
|
||||||
/* Ensure transmitter is enabled! */
|
|
||||||
|
|
||||||
port = DEBUG_PORT;
|
|
||||||
base_addr[CyCAR] = (u_char) port;
|
|
||||||
while (base_addr[CyCCR])
|
|
||||||
;
|
|
||||||
base_addr[CyCCR] = CyENB_XMTR;
|
|
||||||
|
|
||||||
ier = base_addr[CyIER];
|
|
||||||
base_addr[CyIER] = CyTxMpty;
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
if (pcc2chip[PccSCCTICR] & 0x20) {
|
|
||||||
/* We have a Tx int. Acknowledge it */
|
|
||||||
sink = pcc2chip[PccTPIACKR];
|
|
||||||
if ((base_addr[CyLICR] >> 2) == port) {
|
|
||||||
base_addr[CyTDR] = c;
|
|
||||||
base_addr[CyTEOIR] = 0;
|
|
||||||
break;
|
|
||||||
} else
|
|
||||||
base_addr[CyTEOIR] = CyNOTRANS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
base_addr[CyIER] = ier;
|
|
||||||
|
|
||||||
local_irq_restore(flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
int getDebugChar()
|
|
||||||
{
|
|
||||||
volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
|
|
||||||
unsigned long flags;
|
|
||||||
volatile u_char sink;
|
|
||||||
u_char ier;
|
|
||||||
int port;
|
|
||||||
int i, c;
|
|
||||||
|
|
||||||
i = debugiq.out;
|
|
||||||
if (i != debugiq.in) {
|
|
||||||
c = debugiq.buf[i];
|
|
||||||
if (++i == DEBUG_LEN)
|
|
||||||
i = 0;
|
|
||||||
debugiq.out = i;
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
/* OK, nothing in queue, wait in poll loop */
|
|
||||||
|
|
||||||
local_irq_save(flags);
|
|
||||||
|
|
||||||
/* Ensure receiver is enabled! */
|
|
||||||
|
|
||||||
port = DEBUG_PORT;
|
|
||||||
base_addr[CyCAR] = (u_char) port;
|
|
||||||
#if 0
|
|
||||||
while (base_addr[CyCCR])
|
|
||||||
;
|
|
||||||
base_addr[CyCCR] = CyENB_RCVR;
|
|
||||||
#endif
|
|
||||||
ier = base_addr[CyIER];
|
|
||||||
base_addr[CyIER] = CyRxData;
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
if (pcc2chip[PccSCCRICR] & 0x20) {
|
|
||||||
/* We have a Rx int. Acknowledge it */
|
|
||||||
sink = pcc2chip[PccRPIACKR];
|
|
||||||
if ((base_addr[CyLICR] >> 2) == port) {
|
|
||||||
int cnt = base_addr[CyRFOC];
|
|
||||||
while (cnt-- > 0) {
|
|
||||||
c = base_addr[CyRDR];
|
|
||||||
if (c == 0)
|
|
||||||
printk
|
|
||||||
("!! debug char is null (cnt=%d) !!",
|
|
||||||
cnt);
|
|
||||||
else
|
|
||||||
queueDebugChar(c);
|
|
||||||
}
|
|
||||||
base_addr[CyREOIR] = 0;
|
|
||||||
i = debugiq.out;
|
|
||||||
if (i == debugiq.in)
|
|
||||||
panic("Debug input queue empty!");
|
|
||||||
c = debugiq.buf[i];
|
|
||||||
if (++i == DEBUG_LEN)
|
|
||||||
i = 0;
|
|
||||||
debugiq.out = i;
|
|
||||||
break;
|
|
||||||
} else
|
|
||||||
base_addr[CyREOIR] = CyNOTRANS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
base_addr[CyIER] = ier;
|
|
||||||
|
|
||||||
local_irq_restore(flags);
|
|
||||||
|
|
||||||
return (c);
|
|
||||||
}
|
|
||||||
|
|
||||||
void queueDebugChar(int c)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
i = debugiq.in;
|
|
||||||
debugiq.buf[i] = c;
|
|
||||||
if (++i == DEBUG_LEN)
|
|
||||||
i = 0;
|
|
||||||
if (i != debugiq.out)
|
|
||||||
debugiq.in = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void debug_setup()
|
|
||||||
{
|
|
||||||
unsigned long flags;
|
|
||||||
volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
|
|
||||||
int i, cflag;
|
|
||||||
|
|
||||||
cflag = B19200;
|
|
||||||
|
|
||||||
local_irq_save(flags);
|
|
||||||
|
|
||||||
for (i = 0; i < 4; i++) {
|
|
||||||
base_addr[CyCAR] = i;
|
|
||||||
base_addr[CyLICR] = i << 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
debugiq.in = debugiq.out = 0;
|
|
||||||
|
|
||||||
base_addr[CyCAR] = DEBUG_PORT;
|
|
||||||
|
|
||||||
/* baud rate */
|
|
||||||
i = cflag & CBAUD;
|
|
||||||
|
|
||||||
base_addr[CyIER] = 0;
|
|
||||||
|
|
||||||
base_addr[CyCMR] = CyASYNC;
|
|
||||||
base_addr[CyLICR] = DEBUG_PORT << 2;
|
|
||||||
base_addr[CyLIVR] = 0x5c;
|
|
||||||
|
|
||||||
/* tx and rx baud rate */
|
|
||||||
|
|
||||||
base_addr[CyTCOR] = baud_co[i];
|
|
||||||
base_addr[CyTBPR] = baud_bpr[i];
|
|
||||||
base_addr[CyRCOR] = baud_co[i] >> 5;
|
|
||||||
base_addr[CyRBPR] = baud_bpr[i];
|
|
||||||
|
|
||||||
/* set line characteristics according configuration */
|
|
||||||
|
|
||||||
base_addr[CySCHR1] = 0;
|
|
||||||
base_addr[CySCHR2] = 0;
|
|
||||||
base_addr[CySCRL] = 0;
|
|
||||||
base_addr[CySCRH] = 0;
|
|
||||||
base_addr[CyCOR1] = Cy_8_BITS | CyPARITY_NONE;
|
|
||||||
base_addr[CyCOR2] = 0;
|
|
||||||
base_addr[CyCOR3] = Cy_1_STOP;
|
|
||||||
base_addr[CyCOR4] = baud_cor4[i];
|
|
||||||
base_addr[CyCOR5] = 0;
|
|
||||||
base_addr[CyCOR6] = 0;
|
|
||||||
base_addr[CyCOR7] = 0;
|
|
||||||
|
|
||||||
write_cy_cmd(base_addr, CyINIT_CHAN);
|
|
||||||
write_cy_cmd(base_addr, CyENB_RCVR);
|
|
||||||
|
|
||||||
base_addr[CyCAR] = DEBUG_PORT; /* !!! Is this needed? */
|
|
||||||
|
|
||||||
base_addr[CyRTPRL] = 2;
|
|
||||||
base_addr[CyRTPRH] = 0;
|
|
||||||
|
|
||||||
base_addr[CyMSVR1] = CyRTS;
|
|
||||||
base_addr[CyMSVR2] = CyDTR;
|
|
||||||
|
|
||||||
base_addr[CyIER] = CyRxData;
|
|
||||||
|
|
||||||
local_irq_restore(flags);
|
|
||||||
|
|
||||||
} /* debug_setup */
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
@ -238,7 +238,7 @@ EXPORT_SYMBOL_GPL(tty_buffer_request_room);
|
|||||||
* @size: size
|
* @size: size
|
||||||
*
|
*
|
||||||
* Queue a series of bytes to the tty buffering. All the characters
|
* Queue a series of bytes to the tty buffering. All the characters
|
||||||
* passed are marked as without error. Returns the number added.
|
* passed are marked with the supplied flag. Returns the number added.
|
||||||
*
|
*
|
||||||
* Locking: Called functions may take tty->buf.lock
|
* Locking: Called functions may take tty->buf.lock
|
||||||
*/
|
*/
|
||||||
|
@ -1423,8 +1423,8 @@ config SERIAL_SC26XX_CONSOLE
|
|||||||
Support for Console on SC2681/SC2692 serial ports.
|
Support for Console on SC2681/SC2692 serial ports.
|
||||||
|
|
||||||
config SERIAL_BFIN_SPORT
|
config SERIAL_BFIN_SPORT
|
||||||
tristate "Blackfin SPORT emulate UART (EXPERIMENTAL)"
|
tristate "Blackfin SPORT emulate UART"
|
||||||
depends on BLACKFIN && EXPERIMENTAL
|
depends on BLACKFIN
|
||||||
select SERIAL_CORE
|
select SERIAL_CORE
|
||||||
help
|
help
|
||||||
Enable SPORT emulate UART on Blackfin series.
|
Enable SPORT emulate UART on Blackfin series.
|
||||||
@ -1439,28 +1439,52 @@ config SERIAL_BFIN_SPORT_CONSOLE
|
|||||||
|
|
||||||
config SERIAL_BFIN_SPORT0_UART
|
config SERIAL_BFIN_SPORT0_UART
|
||||||
bool "Enable UART over SPORT0"
|
bool "Enable UART over SPORT0"
|
||||||
depends on SERIAL_BFIN_SPORT && !(BF542 || BF542M || BF544 || BF544M)
|
depends on SERIAL_BFIN_SPORT && !(BF542 || BF544)
|
||||||
help
|
help
|
||||||
Enable UART over SPORT0
|
Enable UART over SPORT0
|
||||||
|
|
||||||
|
config SERIAL_BFIN_SPORT0_UART_CTSRTS
|
||||||
|
bool "Enable UART over SPORT0 hardware flow control"
|
||||||
|
depends on SERIAL_BFIN_SPORT0_UART
|
||||||
|
help
|
||||||
|
Enable hardware flow control in the driver.
|
||||||
|
|
||||||
config SERIAL_BFIN_SPORT1_UART
|
config SERIAL_BFIN_SPORT1_UART
|
||||||
bool "Enable UART over SPORT1"
|
bool "Enable UART over SPORT1"
|
||||||
depends on SERIAL_BFIN_SPORT
|
depends on SERIAL_BFIN_SPORT
|
||||||
help
|
help
|
||||||
Enable UART over SPORT1
|
Enable UART over SPORT1
|
||||||
|
|
||||||
|
config SERIAL_BFIN_SPORT1_UART_CTSRTS
|
||||||
|
bool "Enable UART over SPORT1 hardware flow control"
|
||||||
|
depends on SERIAL_BFIN_SPORT1_UART
|
||||||
|
help
|
||||||
|
Enable hardware flow control in the driver.
|
||||||
|
|
||||||
config SERIAL_BFIN_SPORT2_UART
|
config SERIAL_BFIN_SPORT2_UART
|
||||||
bool "Enable UART over SPORT2"
|
bool "Enable UART over SPORT2"
|
||||||
depends on SERIAL_BFIN_SPORT && (BF54x || BF538 || BF539)
|
depends on SERIAL_BFIN_SPORT && (BF54x || BF538 || BF539)
|
||||||
help
|
help
|
||||||
Enable UART over SPORT2
|
Enable UART over SPORT2
|
||||||
|
|
||||||
|
config SERIAL_BFIN_SPORT2_UART_CTSRTS
|
||||||
|
bool "Enable UART over SPORT2 hardware flow control"
|
||||||
|
depends on SERIAL_BFIN_SPORT2_UART
|
||||||
|
help
|
||||||
|
Enable hardware flow control in the driver.
|
||||||
|
|
||||||
config SERIAL_BFIN_SPORT3_UART
|
config SERIAL_BFIN_SPORT3_UART
|
||||||
bool "Enable UART over SPORT3"
|
bool "Enable UART over SPORT3"
|
||||||
depends on SERIAL_BFIN_SPORT && (BF54x || BF538 || BF539)
|
depends on SERIAL_BFIN_SPORT && (BF54x || BF538 || BF539)
|
||||||
help
|
help
|
||||||
Enable UART over SPORT3
|
Enable UART over SPORT3
|
||||||
|
|
||||||
|
config SERIAL_BFIN_SPORT3_UART_CTSRTS
|
||||||
|
bool "Enable UART over SPORT3 hardware flow control"
|
||||||
|
depends on SERIAL_BFIN_SPORT3_UART
|
||||||
|
help
|
||||||
|
Enable hardware flow control in the driver.
|
||||||
|
|
||||||
config SERIAL_TIMBERDALE
|
config SERIAL_TIMBERDALE
|
||||||
tristate "Support for timberdale UART"
|
tristate "Support for timberdale UART"
|
||||||
select SERIAL_CORE
|
select SERIAL_CORE
|
||||||
@ -1499,4 +1523,56 @@ config SERIAL_GRLIB_GAISLER_APBUART_CONSOLE
|
|||||||
help
|
help
|
||||||
Support for running a console on the GRLIB APBUART
|
Support for running a console on the GRLIB APBUART
|
||||||
|
|
||||||
|
config SERIAL_ALTERA_JTAGUART
|
||||||
|
tristate "Altera JTAG UART support"
|
||||||
|
select SERIAL_CORE
|
||||||
|
help
|
||||||
|
This driver supports the Altera JTAG UART port.
|
||||||
|
|
||||||
|
config SERIAL_ALTERA_JTAGUART_CONSOLE
|
||||||
|
bool "Altera JTAG UART console support"
|
||||||
|
depends on SERIAL_ALTERA_JTAGUART=y
|
||||||
|
select SERIAL_CORE_CONSOLE
|
||||||
|
help
|
||||||
|
Enable a Altera JTAG UART port to be the system console.
|
||||||
|
|
||||||
|
config SERIAL_ALTERA_JTAGUART_CONSOLE_BYPASS
|
||||||
|
bool "Bypass output when no connection"
|
||||||
|
depends on SERIAL_ALTERA_JTAGUART_CONSOLE
|
||||||
|
select SERIAL_CORE_CONSOLE
|
||||||
|
help
|
||||||
|
Bypass console output and keep going even if there is no
|
||||||
|
JTAG terminal connection with the host.
|
||||||
|
|
||||||
|
config SERIAL_ALTERA_UART
|
||||||
|
tristate "Altera UART support"
|
||||||
|
select SERIAL_CORE
|
||||||
|
help
|
||||||
|
This driver supports the Altera softcore UART port.
|
||||||
|
|
||||||
|
config SERIAL_ALTERA_UART_MAXPORTS
|
||||||
|
int "Maximum number of Altera UART ports"
|
||||||
|
depends on SERIAL_ALTERA_UART
|
||||||
|
default 4
|
||||||
|
help
|
||||||
|
This setting lets you define the maximum number of the Altera
|
||||||
|
UART ports. The usual default varies from board to board, and
|
||||||
|
this setting is a way of catering for that.
|
||||||
|
|
||||||
|
config SERIAL_ALTERA_UART_BAUDRATE
|
||||||
|
int "Default baudrate for Altera UART ports"
|
||||||
|
depends on SERIAL_ALTERA_UART
|
||||||
|
default 115200
|
||||||
|
help
|
||||||
|
This setting lets you define what the default baudrate is for the
|
||||||
|
Altera UART ports. The usual default varies from board to board,
|
||||||
|
and this setting is a way of catering for that.
|
||||||
|
|
||||||
|
config SERIAL_ALTERA_UART_CONSOLE
|
||||||
|
bool "Altera UART console support"
|
||||||
|
depends on SERIAL_ALTERA_UART=y
|
||||||
|
select SERIAL_CORE_CONSOLE
|
||||||
|
help
|
||||||
|
Enable a Altera UART port to be the system console.
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
@ -82,3 +82,5 @@ obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o
|
|||||||
obj-$(CONFIG_SERIAL_QE) += ucc_uart.o
|
obj-$(CONFIG_SERIAL_QE) += ucc_uart.o
|
||||||
obj-$(CONFIG_SERIAL_TIMBERDALE) += timbuart.o
|
obj-$(CONFIG_SERIAL_TIMBERDALE) += timbuart.o
|
||||||
obj-$(CONFIG_SERIAL_GRLIB_GAISLER_APBUART) += apbuart.o
|
obj-$(CONFIG_SERIAL_GRLIB_GAISLER_APBUART) += apbuart.o
|
||||||
|
obj-$(CONFIG_SERIAL_ALTERA_JTAGUART) += altera_jtaguart.o
|
||||||
|
obj-$(CONFIG_SERIAL_ALTERA_UART) += altera_uart.o
|
||||||
|
504
drivers/serial/altera_jtaguart.c
Normal file
504
drivers/serial/altera_jtaguart.c
Normal file
@ -0,0 +1,504 @@
|
|||||||
|
/*
|
||||||
|
* altera_jtaguart.c -- Altera JTAG UART driver
|
||||||
|
*
|
||||||
|
* Based on mcf.c -- Freescale ColdFire UART driver
|
||||||
|
*
|
||||||
|
* (C) Copyright 2003-2007, Greg Ungerer <gerg@snapgear.com>
|
||||||
|
* (C) Copyright 2008, Thomas Chou <thomas@wytron.com.tw>
|
||||||
|
* (C) Copyright 2010, Tobias Klauser <tklauser@distanz.ch>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/console.h>
|
||||||
|
#include <linux/tty.h>
|
||||||
|
#include <linux/tty_flip.h>
|
||||||
|
#include <linux/serial.h>
|
||||||
|
#include <linux/serial_core.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/altera_jtaguart.h>
|
||||||
|
|
||||||
|
#define DRV_NAME "altera_jtaguart"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Altera JTAG UART register definitions according to the Altera JTAG UART
|
||||||
|
* datasheet: http://www.altera.com/literature/hb/nios2/n2cpu_nii51009.pdf
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define ALTERA_JTAGUART_SIZE 8
|
||||||
|
|
||||||
|
#define ALTERA_JTAGUART_DATA_REG 0
|
||||||
|
|
||||||
|
#define ALTERA_JTAGUART_DATA_DATA_MSK 0x000000FF
|
||||||
|
#define ALTERA_JTAGUART_DATA_RVALID_MSK 0x00008000
|
||||||
|
#define ALTERA_JTAGUART_DATA_RAVAIL_MSK 0xFFFF0000
|
||||||
|
#define ALTERA_JTAGUART_DATA_RAVAIL_OFF 16
|
||||||
|
|
||||||
|
#define ALTERA_JTAGUART_CONTROL_REG 4
|
||||||
|
|
||||||
|
#define ALTERA_JTAGUART_CONTROL_RE_MSK 0x00000001
|
||||||
|
#define ALTERA_JTAGUART_CONTROL_WE_MSK 0x00000002
|
||||||
|
#define ALTERA_JTAGUART_CONTROL_RI_MSK 0x00000100
|
||||||
|
#define ALTERA_JTAGUART_CONTROL_RI_OFF 8
|
||||||
|
#define ALTERA_JTAGUART_CONTROL_WI_MSK 0x00000200
|
||||||
|
#define ALTERA_JTAGUART_CONTROL_AC_MSK 0x00000400
|
||||||
|
#define ALTERA_JTAGUART_CONTROL_WSPACE_MSK 0xFFFF0000
|
||||||
|
#define ALTERA_JTAGUART_CONTROL_WSPACE_OFF 16
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local per-uart structure.
|
||||||
|
*/
|
||||||
|
struct altera_jtaguart {
|
||||||
|
struct uart_port port;
|
||||||
|
unsigned int sigs; /* Local copy of line sigs */
|
||||||
|
unsigned long imr; /* Local IMR mirror */
|
||||||
|
};
|
||||||
|
|
||||||
|
static unsigned int altera_jtaguart_tx_empty(struct uart_port *port)
|
||||||
|
{
|
||||||
|
return (readl(port->membase + ALTERA_JTAGUART_CONTROL_REG) &
|
||||||
|
ALTERA_JTAGUART_CONTROL_WSPACE_MSK) ? TIOCSER_TEMT : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int altera_jtaguart_get_mctrl(struct uart_port *port)
|
||||||
|
{
|
||||||
|
return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void altera_jtaguart_set_mctrl(struct uart_port *port, unsigned int sigs)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void altera_jtaguart_start_tx(struct uart_port *port)
|
||||||
|
{
|
||||||
|
struct altera_jtaguart *pp =
|
||||||
|
container_of(port, struct altera_jtaguart, port);
|
||||||
|
|
||||||
|
pp->imr |= ALTERA_JTAGUART_CONTROL_WE_MSK;
|
||||||
|
writel(pp->imr, port->membase + ALTERA_JTAGUART_CONTROL_REG);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void altera_jtaguart_stop_tx(struct uart_port *port)
|
||||||
|
{
|
||||||
|
struct altera_jtaguart *pp =
|
||||||
|
container_of(port, struct altera_jtaguart, port);
|
||||||
|
|
||||||
|
pp->imr &= ~ALTERA_JTAGUART_CONTROL_WE_MSK;
|
||||||
|
writel(pp->imr, port->membase + ALTERA_JTAGUART_CONTROL_REG);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void altera_jtaguart_stop_rx(struct uart_port *port)
|
||||||
|
{
|
||||||
|
struct altera_jtaguart *pp =
|
||||||
|
container_of(port, struct altera_jtaguart, port);
|
||||||
|
|
||||||
|
pp->imr &= ~ALTERA_JTAGUART_CONTROL_RE_MSK;
|
||||||
|
writel(pp->imr, port->membase + ALTERA_JTAGUART_CONTROL_REG);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void altera_jtaguart_break_ctl(struct uart_port *port, int break_state)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void altera_jtaguart_enable_ms(struct uart_port *port)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void altera_jtaguart_set_termios(struct uart_port *port,
|
||||||
|
struct ktermios *termios,
|
||||||
|
struct ktermios *old)
|
||||||
|
{
|
||||||
|
/* Just copy the old termios settings back */
|
||||||
|
if (old)
|
||||||
|
tty_termios_copy_hw(termios, old);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void altera_jtaguart_rx_chars(struct altera_jtaguart *pp)
|
||||||
|
{
|
||||||
|
struct uart_port *port = &pp->port;
|
||||||
|
unsigned char ch, flag;
|
||||||
|
unsigned long status;
|
||||||
|
|
||||||
|
while ((status = readl(port->membase + ALTERA_JTAGUART_DATA_REG)) &
|
||||||
|
ALTERA_JTAGUART_DATA_RVALID_MSK) {
|
||||||
|
ch = status & ALTERA_JTAGUART_DATA_DATA_MSK;
|
||||||
|
flag = TTY_NORMAL;
|
||||||
|
port->icount.rx++;
|
||||||
|
|
||||||
|
if (uart_handle_sysrq_char(port, ch))
|
||||||
|
continue;
|
||||||
|
uart_insert_char(port, 0, 0, ch, flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
tty_flip_buffer_push(port->state->port.tty);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void altera_jtaguart_tx_chars(struct altera_jtaguart *pp)
|
||||||
|
{
|
||||||
|
struct uart_port *port = &pp->port;
|
||||||
|
struct circ_buf *xmit = &port->state->xmit;
|
||||||
|
unsigned int pending, count;
|
||||||
|
|
||||||
|
if (port->x_char) {
|
||||||
|
/* Send special char - probably flow control */
|
||||||
|
writel(port->x_char, port->membase + ALTERA_JTAGUART_DATA_REG);
|
||||||
|
port->x_char = 0;
|
||||||
|
port->icount.tx++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pending = uart_circ_chars_pending(xmit);
|
||||||
|
if (pending > 0) {
|
||||||
|
count = (readl(port->membase + ALTERA_JTAGUART_CONTROL_REG) &
|
||||||
|
ALTERA_JTAGUART_CONTROL_WSPACE_MSK) >>
|
||||||
|
ALTERA_JTAGUART_CONTROL_WSPACE_OFF;
|
||||||
|
if (count > pending)
|
||||||
|
count = pending;
|
||||||
|
if (count > 0) {
|
||||||
|
pending -= count;
|
||||||
|
while (count--) {
|
||||||
|
writel(xmit->buf[xmit->tail],
|
||||||
|
port->membase + ALTERA_JTAGUART_DATA_REG);
|
||||||
|
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||||
|
port->icount.tx++;
|
||||||
|
}
|
||||||
|
if (pending < WAKEUP_CHARS)
|
||||||
|
uart_write_wakeup(port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pending == 0) {
|
||||||
|
pp->imr &= ~ALTERA_JTAGUART_CONTROL_WE_MSK;
|
||||||
|
writel(pp->imr, port->membase + ALTERA_JTAGUART_CONTROL_REG);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static irqreturn_t altera_jtaguart_interrupt(int irq, void *data)
|
||||||
|
{
|
||||||
|
struct uart_port *port = data;
|
||||||
|
struct altera_jtaguart *pp =
|
||||||
|
container_of(port, struct altera_jtaguart, port);
|
||||||
|
unsigned int isr;
|
||||||
|
|
||||||
|
isr = (readl(port->membase + ALTERA_JTAGUART_CONTROL_REG) >>
|
||||||
|
ALTERA_JTAGUART_CONTROL_RI_OFF) & pp->imr;
|
||||||
|
|
||||||
|
spin_lock(&port->lock);
|
||||||
|
|
||||||
|
if (isr & ALTERA_JTAGUART_CONTROL_RE_MSK)
|
||||||
|
altera_jtaguart_rx_chars(pp);
|
||||||
|
if (isr & ALTERA_JTAGUART_CONTROL_WE_MSK)
|
||||||
|
altera_jtaguart_tx_chars(pp);
|
||||||
|
|
||||||
|
spin_unlock(&port->lock);
|
||||||
|
|
||||||
|
return IRQ_RETVAL(isr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void altera_jtaguart_config_port(struct uart_port *port, int flags)
|
||||||
|
{
|
||||||
|
port->type = PORT_ALTERA_JTAGUART;
|
||||||
|
|
||||||
|
/* Clear mask, so no surprise interrupts. */
|
||||||
|
writel(0, port->membase + ALTERA_JTAGUART_CONTROL_REG);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int altera_jtaguart_startup(struct uart_port *port)
|
||||||
|
{
|
||||||
|
struct altera_jtaguart *pp =
|
||||||
|
container_of(port, struct altera_jtaguart, port);
|
||||||
|
unsigned long flags;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = request_irq(port->irq, altera_jtaguart_interrupt, IRQF_DISABLED,
|
||||||
|
DRV_NAME, port);
|
||||||
|
if (ret) {
|
||||||
|
pr_err(DRV_NAME ": unable to attach Altera JTAG UART %d "
|
||||||
|
"interrupt vector=%d\n", port->line, port->irq);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
spin_lock_irqsave(&port->lock, flags);
|
||||||
|
|
||||||
|
/* Enable RX interrupts now */
|
||||||
|
pp->imr = ALTERA_JTAGUART_CONTROL_RE_MSK;
|
||||||
|
writel(pp->imr, port->membase + ALTERA_JTAGUART_CONTROL_REG);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void altera_jtaguart_shutdown(struct uart_port *port)
|
||||||
|
{
|
||||||
|
struct altera_jtaguart *pp =
|
||||||
|
container_of(port, struct altera_jtaguart, port);
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&port->lock, flags);
|
||||||
|
|
||||||
|
/* Disable all interrupts now */
|
||||||
|
pp->imr = 0;
|
||||||
|
writel(pp->imr, port->membase + ALTERA_JTAGUART_CONTROL_REG);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
|
|
||||||
|
free_irq(port->irq, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *altera_jtaguart_type(struct uart_port *port)
|
||||||
|
{
|
||||||
|
return (port->type == PORT_ALTERA_JTAGUART) ? "Altera JTAG UART" : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int altera_jtaguart_request_port(struct uart_port *port)
|
||||||
|
{
|
||||||
|
/* UARTs always present */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void altera_jtaguart_release_port(struct uart_port *port)
|
||||||
|
{
|
||||||
|
/* Nothing to release... */
|
||||||
|
}
|
||||||
|
|
||||||
|
static int altera_jtaguart_verify_port(struct uart_port *port,
|
||||||
|
struct serial_struct *ser)
|
||||||
|
{
|
||||||
|
if (ser->type != PORT_UNKNOWN && ser->type != PORT_ALTERA_JTAGUART)
|
||||||
|
return -EINVAL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Define the basic serial functions we support.
|
||||||
|
*/
|
||||||
|
static struct uart_ops altera_jtaguart_ops = {
|
||||||
|
.tx_empty = altera_jtaguart_tx_empty,
|
||||||
|
.get_mctrl = altera_jtaguart_get_mctrl,
|
||||||
|
.set_mctrl = altera_jtaguart_set_mctrl,
|
||||||
|
.start_tx = altera_jtaguart_start_tx,
|
||||||
|
.stop_tx = altera_jtaguart_stop_tx,
|
||||||
|
.stop_rx = altera_jtaguart_stop_rx,
|
||||||
|
.enable_ms = altera_jtaguart_enable_ms,
|
||||||
|
.break_ctl = altera_jtaguart_break_ctl,
|
||||||
|
.startup = altera_jtaguart_startup,
|
||||||
|
.shutdown = altera_jtaguart_shutdown,
|
||||||
|
.set_termios = altera_jtaguart_set_termios,
|
||||||
|
.type = altera_jtaguart_type,
|
||||||
|
.request_port = altera_jtaguart_request_port,
|
||||||
|
.release_port = altera_jtaguart_release_port,
|
||||||
|
.config_port = altera_jtaguart_config_port,
|
||||||
|
.verify_port = altera_jtaguart_verify_port,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define ALTERA_JTAGUART_MAXPORTS 1
|
||||||
|
static struct altera_jtaguart altera_jtaguart_ports[ALTERA_JTAGUART_MAXPORTS];
|
||||||
|
|
||||||
|
#if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE)
|
||||||
|
|
||||||
|
int __init early_altera_jtaguart_setup(struct altera_jtaguart_platform_uart
|
||||||
|
*platp)
|
||||||
|
{
|
||||||
|
struct uart_port *port;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < ALTERA_JTAGUART_MAXPORTS && platp[i].mapbase; i++) {
|
||||||
|
port = &altera_jtaguart_ports[i].port;
|
||||||
|
|
||||||
|
port->line = i;
|
||||||
|
port->type = PORT_ALTERA_JTAGUART;
|
||||||
|
port->mapbase = platp[i].mapbase;
|
||||||
|
port->membase = ioremap(port->mapbase, ALTERA_JTAGUART_SIZE);
|
||||||
|
port->iotype = SERIAL_IO_MEM;
|
||||||
|
port->irq = platp[i].irq;
|
||||||
|
port->flags = ASYNC_BOOT_AUTOCONF;
|
||||||
|
port->ops = &altera_jtaguart_ops;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE_BYPASS)
|
||||||
|
static void altera_jtaguart_console_putc(struct console *co, const char c)
|
||||||
|
{
|
||||||
|
struct uart_port *port = &(altera_jtaguart_ports + co->index)->port;
|
||||||
|
unsigned long status;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&port->lock, flags);
|
||||||
|
while (((status = readl(port->membase + ALTERA_JTAGUART_CONTROL_REG)) &
|
||||||
|
ALTERA_JTAGUART_CONTROL_WSPACE_MSK) == 0) {
|
||||||
|
if ((status & ALTERA_JTAGUART_CONTROL_AC_MSK) == 0) {
|
||||||
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
|
return; /* no connection activity */
|
||||||
|
}
|
||||||
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
|
cpu_relax();
|
||||||
|
spin_lock_irqsave(&port->lock, flags);
|
||||||
|
}
|
||||||
|
writel(c, port->membase + ALTERA_JTAGUART_DATA_REG);
|
||||||
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static void altera_jtaguart_console_putc(struct console *co, const char c)
|
||||||
|
{
|
||||||
|
struct uart_port *port = &(altera_jtaguart_ports + co->index)->port;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&port->lock, flags);
|
||||||
|
while ((readl(port->membase + ALTERA_JTAGUART_CONTROL_REG) &
|
||||||
|
ALTERA_JTAGUART_CONTROL_WSPACE_MSK) == 0) {
|
||||||
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
|
cpu_relax();
|
||||||
|
spin_lock_irqsave(&port->lock, flags);
|
||||||
|
}
|
||||||
|
writel(c, port->membase + ALTERA_JTAGUART_DATA_REG);
|
||||||
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void altera_jtaguart_console_write(struct console *co, const char *s,
|
||||||
|
unsigned int count)
|
||||||
|
{
|
||||||
|
for (; count; count--, s++) {
|
||||||
|
altera_jtaguart_console_putc(co, *s);
|
||||||
|
if (*s == '\n')
|
||||||
|
altera_jtaguart_console_putc(co, '\r');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __init altera_jtaguart_console_setup(struct console *co,
|
||||||
|
char *options)
|
||||||
|
{
|
||||||
|
struct uart_port *port;
|
||||||
|
|
||||||
|
if (co->index < 0 || co->index >= ALTERA_JTAGUART_MAXPORTS)
|
||||||
|
return -EINVAL;
|
||||||
|
port = &altera_jtaguart_ports[co->index].port;
|
||||||
|
if (port->membase == 0)
|
||||||
|
return -ENODEV;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct uart_driver altera_jtaguart_driver;
|
||||||
|
|
||||||
|
static struct console altera_jtaguart_console = {
|
||||||
|
.name = "ttyJ",
|
||||||
|
.write = altera_jtaguart_console_write,
|
||||||
|
.device = uart_console_device,
|
||||||
|
.setup = altera_jtaguart_console_setup,
|
||||||
|
.flags = CON_PRINTBUFFER,
|
||||||
|
.index = -1,
|
||||||
|
.data = &altera_jtaguart_driver,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init altera_jtaguart_console_init(void)
|
||||||
|
{
|
||||||
|
register_console(&altera_jtaguart_console);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
console_initcall(altera_jtaguart_console_init);
|
||||||
|
|
||||||
|
#define ALTERA_JTAGUART_CONSOLE (&altera_jtaguart_console)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define ALTERA_JTAGUART_CONSOLE NULL
|
||||||
|
|
||||||
|
#endif /* CONFIG_ALTERA_JTAGUART_CONSOLE */
|
||||||
|
|
||||||
|
static struct uart_driver altera_jtaguart_driver = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.driver_name = "altera_jtaguart",
|
||||||
|
.dev_name = "ttyJ",
|
||||||
|
.major = ALTERA_JTAGUART_MAJOR,
|
||||||
|
.minor = ALTERA_JTAGUART_MINOR,
|
||||||
|
.nr = ALTERA_JTAGUART_MAXPORTS,
|
||||||
|
.cons = ALTERA_JTAGUART_CONSOLE,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __devinit altera_jtaguart_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct altera_jtaguart_platform_uart *platp = pdev->dev.platform_data;
|
||||||
|
struct uart_port *port;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < ALTERA_JTAGUART_MAXPORTS && platp[i].mapbase; i++) {
|
||||||
|
port = &altera_jtaguart_ports[i].port;
|
||||||
|
|
||||||
|
port->line = i;
|
||||||
|
port->type = PORT_ALTERA_JTAGUART;
|
||||||
|
port->mapbase = platp[i].mapbase;
|
||||||
|
port->membase = ioremap(port->mapbase, ALTERA_JTAGUART_SIZE);
|
||||||
|
port->iotype = SERIAL_IO_MEM;
|
||||||
|
port->irq = platp[i].irq;
|
||||||
|
port->ops = &altera_jtaguart_ops;
|
||||||
|
port->flags = ASYNC_BOOT_AUTOCONF;
|
||||||
|
|
||||||
|
uart_add_one_port(&altera_jtaguart_driver, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __devexit altera_jtaguart_remove(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct uart_port *port;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < ALTERA_JTAGUART_MAXPORTS; i++) {
|
||||||
|
port = &altera_jtaguart_ports[i].port;
|
||||||
|
if (port)
|
||||||
|
uart_remove_one_port(&altera_jtaguart_driver, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct platform_driver altera_jtaguart_platform_driver = {
|
||||||
|
.probe = altera_jtaguart_probe,
|
||||||
|
.remove = __devexit_p(altera_jtaguart_remove),
|
||||||
|
.driver = {
|
||||||
|
.name = DRV_NAME,
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init altera_jtaguart_init(void)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = uart_register_driver(&altera_jtaguart_driver);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
rc = platform_driver_register(&altera_jtaguart_platform_driver);
|
||||||
|
if (rc) {
|
||||||
|
uart_unregister_driver(&altera_jtaguart_driver);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit altera_jtaguart_exit(void)
|
||||||
|
{
|
||||||
|
platform_driver_unregister(&altera_jtaguart_platform_driver);
|
||||||
|
uart_unregister_driver(&altera_jtaguart_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(altera_jtaguart_init);
|
||||||
|
module_exit(altera_jtaguart_exit);
|
||||||
|
|
||||||
|
MODULE_DESCRIPTION("Altera JTAG UART driver");
|
||||||
|
MODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
MODULE_ALIAS("platform:" DRV_NAME);
|
570
drivers/serial/altera_uart.c
Normal file
570
drivers/serial/altera_uart.c
Normal file
@ -0,0 +1,570 @@
|
|||||||
|
/*
|
||||||
|
* altera_uart.c -- Altera UART driver
|
||||||
|
*
|
||||||
|
* Based on mcf.c -- Freescale ColdFire UART driver
|
||||||
|
*
|
||||||
|
* (C) Copyright 2003-2007, Greg Ungerer <gerg@snapgear.com>
|
||||||
|
* (C) Copyright 2008, Thomas Chou <thomas@wytron.com.tw>
|
||||||
|
* (C) Copyright 2010, Tobias Klauser <tklauser@distanz.ch>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/console.h>
|
||||||
|
#include <linux/tty.h>
|
||||||
|
#include <linux/tty_flip.h>
|
||||||
|
#include <linux/serial.h>
|
||||||
|
#include <linux/serial_core.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/altera_uart.h>
|
||||||
|
|
||||||
|
#define DRV_NAME "altera_uart"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Altera UART register definitions according to the Nios UART datasheet:
|
||||||
|
* http://www.altera.com/literature/ds/ds_nios_uart.pdf
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define ALTERA_UART_SIZE 32
|
||||||
|
|
||||||
|
#define ALTERA_UART_RXDATA_REG 0
|
||||||
|
#define ALTERA_UART_TXDATA_REG 4
|
||||||
|
#define ALTERA_UART_STATUS_REG 8
|
||||||
|
#define ALTERA_UART_CONTROL_REG 12
|
||||||
|
#define ALTERA_UART_DIVISOR_REG 16
|
||||||
|
#define ALTERA_UART_EOP_REG 20
|
||||||
|
|
||||||
|
#define ALTERA_UART_STATUS_PE_MSK 0x0001 /* parity error */
|
||||||
|
#define ALTERA_UART_STATUS_FE_MSK 0x0002 /* framing error */
|
||||||
|
#define ALTERA_UART_STATUS_BRK_MSK 0x0004 /* break */
|
||||||
|
#define ALTERA_UART_STATUS_ROE_MSK 0x0008 /* RX overrun error */
|
||||||
|
#define ALTERA_UART_STATUS_TOE_MSK 0x0010 /* TX overrun error */
|
||||||
|
#define ALTERA_UART_STATUS_TMT_MSK 0x0020 /* TX shift register state */
|
||||||
|
#define ALTERA_UART_STATUS_TRDY_MSK 0x0040 /* TX ready */
|
||||||
|
#define ALTERA_UART_STATUS_RRDY_MSK 0x0080 /* RX ready */
|
||||||
|
#define ALTERA_UART_STATUS_E_MSK 0x0100 /* exception condition */
|
||||||
|
#define ALTERA_UART_STATUS_DCTS_MSK 0x0400 /* CTS logic-level change */
|
||||||
|
#define ALTERA_UART_STATUS_CTS_MSK 0x0800 /* CTS logic state */
|
||||||
|
#define ALTERA_UART_STATUS_EOP_MSK 0x1000 /* EOP written/read */
|
||||||
|
|
||||||
|
/* Enable interrupt on... */
|
||||||
|
#define ALTERA_UART_CONTROL_PE_MSK 0x0001 /* ...parity error */
|
||||||
|
#define ALTERA_UART_CONTROL_FE_MSK 0x0002 /* ...framing error */
|
||||||
|
#define ALTERA_UART_CONTROL_BRK_MSK 0x0004 /* ...break */
|
||||||
|
#define ALTERA_UART_CONTROL_ROE_MSK 0x0008 /* ...RX overrun */
|
||||||
|
#define ALTERA_UART_CONTROL_TOE_MSK 0x0010 /* ...TX overrun */
|
||||||
|
#define ALTERA_UART_CONTROL_TMT_MSK 0x0020 /* ...TX shift register empty */
|
||||||
|
#define ALTERA_UART_CONTROL_TRDY_MSK 0x0040 /* ...TX ready */
|
||||||
|
#define ALTERA_UART_CONTROL_RRDY_MSK 0x0080 /* ...RX ready */
|
||||||
|
#define ALTERA_UART_CONTROL_E_MSK 0x0100 /* ...exception*/
|
||||||
|
|
||||||
|
#define ALTERA_UART_CONTROL_TRBK_MSK 0x0200 /* TX break */
|
||||||
|
#define ALTERA_UART_CONTROL_DCTS_MSK 0x0400 /* Interrupt on CTS change */
|
||||||
|
#define ALTERA_UART_CONTROL_RTS_MSK 0x0800 /* RTS signal */
|
||||||
|
#define ALTERA_UART_CONTROL_EOP_MSK 0x1000 /* Interrupt on EOP */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local per-uart structure.
|
||||||
|
*/
|
||||||
|
struct altera_uart {
|
||||||
|
struct uart_port port;
|
||||||
|
unsigned int sigs; /* Local copy of line sigs */
|
||||||
|
unsigned short imr; /* Local IMR mirror */
|
||||||
|
};
|
||||||
|
|
||||||
|
static unsigned int altera_uart_tx_empty(struct uart_port *port)
|
||||||
|
{
|
||||||
|
return (readl(port->membase + ALTERA_UART_STATUS_REG) &
|
||||||
|
ALTERA_UART_STATUS_TMT_MSK) ? TIOCSER_TEMT : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int altera_uart_get_mctrl(struct uart_port *port)
|
||||||
|
{
|
||||||
|
struct altera_uart *pp = container_of(port, struct altera_uart, port);
|
||||||
|
unsigned long flags;
|
||||||
|
unsigned int sigs;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&port->lock, flags);
|
||||||
|
sigs =
|
||||||
|
(readl(port->membase + ALTERA_UART_STATUS_REG) &
|
||||||
|
ALTERA_UART_STATUS_CTS_MSK) ? TIOCM_CTS : 0;
|
||||||
|
sigs |= (pp->sigs & TIOCM_RTS);
|
||||||
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
|
|
||||||
|
return sigs;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void altera_uart_set_mctrl(struct uart_port *port, unsigned int sigs)
|
||||||
|
{
|
||||||
|
struct altera_uart *pp = container_of(port, struct altera_uart, port);
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&port->lock, flags);
|
||||||
|
pp->sigs = sigs;
|
||||||
|
if (sigs & TIOCM_RTS)
|
||||||
|
pp->imr |= ALTERA_UART_CONTROL_RTS_MSK;
|
||||||
|
else
|
||||||
|
pp->imr &= ~ALTERA_UART_CONTROL_RTS_MSK;
|
||||||
|
writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
|
||||||
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void altera_uart_start_tx(struct uart_port *port)
|
||||||
|
{
|
||||||
|
struct altera_uart *pp = container_of(port, struct altera_uart, port);
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&port->lock, flags);
|
||||||
|
pp->imr |= ALTERA_UART_CONTROL_TRDY_MSK;
|
||||||
|
writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
|
||||||
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void altera_uart_stop_tx(struct uart_port *port)
|
||||||
|
{
|
||||||
|
struct altera_uart *pp = container_of(port, struct altera_uart, port);
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&port->lock, flags);
|
||||||
|
pp->imr &= ~ALTERA_UART_CONTROL_TRDY_MSK;
|
||||||
|
writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
|
||||||
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void altera_uart_stop_rx(struct uart_port *port)
|
||||||
|
{
|
||||||
|
struct altera_uart *pp = container_of(port, struct altera_uart, port);
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&port->lock, flags);
|
||||||
|
pp->imr &= ~ALTERA_UART_CONTROL_RRDY_MSK;
|
||||||
|
writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
|
||||||
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void altera_uart_break_ctl(struct uart_port *port, int break_state)
|
||||||
|
{
|
||||||
|
struct altera_uart *pp = container_of(port, struct altera_uart, port);
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&port->lock, flags);
|
||||||
|
if (break_state == -1)
|
||||||
|
pp->imr |= ALTERA_UART_CONTROL_TRBK_MSK;
|
||||||
|
else
|
||||||
|
pp->imr &= ~ALTERA_UART_CONTROL_TRBK_MSK;
|
||||||
|
writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
|
||||||
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void altera_uart_enable_ms(struct uart_port *port)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void altera_uart_set_termios(struct uart_port *port,
|
||||||
|
struct ktermios *termios,
|
||||||
|
struct ktermios *old)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
unsigned int baud, baudclk;
|
||||||
|
|
||||||
|
baud = uart_get_baud_rate(port, termios, old, 0, 4000000);
|
||||||
|
baudclk = port->uartclk / baud;
|
||||||
|
|
||||||
|
if (old)
|
||||||
|
tty_termios_copy_hw(termios, old);
|
||||||
|
tty_termios_encode_baud_rate(termios, baud, baud);
|
||||||
|
|
||||||
|
spin_lock_irqsave(&port->lock, flags);
|
||||||
|
writel(baudclk, port->membase + ALTERA_UART_DIVISOR_REG);
|
||||||
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void altera_uart_rx_chars(struct altera_uart *pp)
|
||||||
|
{
|
||||||
|
struct uart_port *port = &pp->port;
|
||||||
|
unsigned char ch, flag;
|
||||||
|
unsigned short status;
|
||||||
|
|
||||||
|
while ((status = readl(port->membase + ALTERA_UART_STATUS_REG)) &
|
||||||
|
ALTERA_UART_STATUS_RRDY_MSK) {
|
||||||
|
ch = readl(port->membase + ALTERA_UART_RXDATA_REG);
|
||||||
|
flag = TTY_NORMAL;
|
||||||
|
port->icount.rx++;
|
||||||
|
|
||||||
|
if (status & ALTERA_UART_STATUS_E_MSK) {
|
||||||
|
writel(status, port->membase + ALTERA_UART_STATUS_REG);
|
||||||
|
|
||||||
|
if (status & ALTERA_UART_STATUS_BRK_MSK) {
|
||||||
|
port->icount.brk++;
|
||||||
|
if (uart_handle_break(port))
|
||||||
|
continue;
|
||||||
|
} else if (status & ALTERA_UART_STATUS_PE_MSK) {
|
||||||
|
port->icount.parity++;
|
||||||
|
} else if (status & ALTERA_UART_STATUS_ROE_MSK) {
|
||||||
|
port->icount.overrun++;
|
||||||
|
} else if (status & ALTERA_UART_STATUS_FE_MSK) {
|
||||||
|
port->icount.frame++;
|
||||||
|
}
|
||||||
|
|
||||||
|
status &= port->read_status_mask;
|
||||||
|
|
||||||
|
if (status & ALTERA_UART_STATUS_BRK_MSK)
|
||||||
|
flag = TTY_BREAK;
|
||||||
|
else if (status & ALTERA_UART_STATUS_PE_MSK)
|
||||||
|
flag = TTY_PARITY;
|
||||||
|
else if (status & ALTERA_UART_STATUS_FE_MSK)
|
||||||
|
flag = TTY_FRAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uart_handle_sysrq_char(port, ch))
|
||||||
|
continue;
|
||||||
|
uart_insert_char(port, status, ALTERA_UART_STATUS_ROE_MSK, ch,
|
||||||
|
flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
tty_flip_buffer_push(port->state->port.tty);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void altera_uart_tx_chars(struct altera_uart *pp)
|
||||||
|
{
|
||||||
|
struct uart_port *port = &pp->port;
|
||||||
|
struct circ_buf *xmit = &port->state->xmit;
|
||||||
|
|
||||||
|
if (port->x_char) {
|
||||||
|
/* Send special char - probably flow control */
|
||||||
|
writel(port->x_char, port->membase + ALTERA_UART_TXDATA_REG);
|
||||||
|
port->x_char = 0;
|
||||||
|
port->icount.tx++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (readl(port->membase + ALTERA_UART_STATUS_REG) &
|
||||||
|
ALTERA_UART_STATUS_TRDY_MSK) {
|
||||||
|
if (xmit->head == xmit->tail)
|
||||||
|
break;
|
||||||
|
writel(xmit->buf[xmit->tail],
|
||||||
|
port->membase + ALTERA_UART_TXDATA_REG);
|
||||||
|
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||||
|
port->icount.tx++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||||
|
uart_write_wakeup(port);
|
||||||
|
|
||||||
|
if (xmit->head == xmit->tail) {
|
||||||
|
pp->imr &= ~ALTERA_UART_CONTROL_TRDY_MSK;
|
||||||
|
writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static irqreturn_t altera_uart_interrupt(int irq, void *data)
|
||||||
|
{
|
||||||
|
struct uart_port *port = data;
|
||||||
|
struct altera_uart *pp = container_of(port, struct altera_uart, port);
|
||||||
|
unsigned int isr;
|
||||||
|
|
||||||
|
isr = readl(port->membase + ALTERA_UART_STATUS_REG) & pp->imr;
|
||||||
|
if (isr & ALTERA_UART_STATUS_RRDY_MSK)
|
||||||
|
altera_uart_rx_chars(pp);
|
||||||
|
if (isr & ALTERA_UART_STATUS_TRDY_MSK)
|
||||||
|
altera_uart_tx_chars(pp);
|
||||||
|
return IRQ_RETVAL(isr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void altera_uart_config_port(struct uart_port *port, int flags)
|
||||||
|
{
|
||||||
|
port->type = PORT_ALTERA_UART;
|
||||||
|
|
||||||
|
/* Clear mask, so no surprise interrupts. */
|
||||||
|
writel(0, port->membase + ALTERA_UART_CONTROL_REG);
|
||||||
|
/* Clear status register */
|
||||||
|
writel(0, port->membase + ALTERA_UART_STATUS_REG);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int altera_uart_startup(struct uart_port *port)
|
||||||
|
{
|
||||||
|
struct altera_uart *pp = container_of(port, struct altera_uart, port);
|
||||||
|
unsigned long flags;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = request_irq(port->irq, altera_uart_interrupt, IRQF_DISABLED,
|
||||||
|
DRV_NAME, port);
|
||||||
|
if (ret) {
|
||||||
|
pr_err(DRV_NAME ": unable to attach Altera UART %d "
|
||||||
|
"interrupt vector=%d\n", port->line, port->irq);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
spin_lock_irqsave(&port->lock, flags);
|
||||||
|
|
||||||
|
/* Enable RX interrupts now */
|
||||||
|
pp->imr = ALTERA_UART_CONTROL_RRDY_MSK;
|
||||||
|
writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void altera_uart_shutdown(struct uart_port *port)
|
||||||
|
{
|
||||||
|
struct altera_uart *pp = container_of(port, struct altera_uart, port);
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&port->lock, flags);
|
||||||
|
|
||||||
|
/* Disable all interrupts now */
|
||||||
|
pp->imr = 0;
|
||||||
|
writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
|
|
||||||
|
free_irq(port->irq, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *altera_uart_type(struct uart_port *port)
|
||||||
|
{
|
||||||
|
return (port->type == PORT_ALTERA_UART) ? "Altera UART" : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int altera_uart_request_port(struct uart_port *port)
|
||||||
|
{
|
||||||
|
/* UARTs always present */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void altera_uart_release_port(struct uart_port *port)
|
||||||
|
{
|
||||||
|
/* Nothing to release... */
|
||||||
|
}
|
||||||
|
|
||||||
|
static int altera_uart_verify_port(struct uart_port *port,
|
||||||
|
struct serial_struct *ser)
|
||||||
|
{
|
||||||
|
if ((ser->type != PORT_UNKNOWN) && (ser->type != PORT_ALTERA_UART))
|
||||||
|
return -EINVAL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Define the basic serial functions we support.
|
||||||
|
*/
|
||||||
|
static struct uart_ops altera_uart_ops = {
|
||||||
|
.tx_empty = altera_uart_tx_empty,
|
||||||
|
.get_mctrl = altera_uart_get_mctrl,
|
||||||
|
.set_mctrl = altera_uart_set_mctrl,
|
||||||
|
.start_tx = altera_uart_start_tx,
|
||||||
|
.stop_tx = altera_uart_stop_tx,
|
||||||
|
.stop_rx = altera_uart_stop_rx,
|
||||||
|
.enable_ms = altera_uart_enable_ms,
|
||||||
|
.break_ctl = altera_uart_break_ctl,
|
||||||
|
.startup = altera_uart_startup,
|
||||||
|
.shutdown = altera_uart_shutdown,
|
||||||
|
.set_termios = altera_uart_set_termios,
|
||||||
|
.type = altera_uart_type,
|
||||||
|
.request_port = altera_uart_request_port,
|
||||||
|
.release_port = altera_uart_release_port,
|
||||||
|
.config_port = altera_uart_config_port,
|
||||||
|
.verify_port = altera_uart_verify_port,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct altera_uart altera_uart_ports[CONFIG_SERIAL_ALTERA_UART_MAXPORTS];
|
||||||
|
|
||||||
|
#if defined(CONFIG_SERIAL_ALTERA_UART_CONSOLE)
|
||||||
|
|
||||||
|
int __init early_altera_uart_setup(struct altera_uart_platform_uart *platp)
|
||||||
|
{
|
||||||
|
struct uart_port *port;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < CONFIG_SERIAL_ALTERA_UART_MAXPORTS && platp[i].mapbase; i++) {
|
||||||
|
port = &altera_uart_ports[i].port;
|
||||||
|
|
||||||
|
port->line = i;
|
||||||
|
port->type = PORT_ALTERA_UART;
|
||||||
|
port->mapbase = platp[i].mapbase;
|
||||||
|
port->membase = ioremap(port->mapbase, ALTERA_UART_SIZE);
|
||||||
|
port->iotype = SERIAL_IO_MEM;
|
||||||
|
port->irq = platp[i].irq;
|
||||||
|
port->uartclk = platp[i].uartclk;
|
||||||
|
port->flags = ASYNC_BOOT_AUTOCONF;
|
||||||
|
port->ops = &altera_uart_ops;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void altera_uart_console_putc(struct console *co, const char c)
|
||||||
|
{
|
||||||
|
struct uart_port *port = &(altera_uart_ports + co->index)->port;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 0x10000; i++) {
|
||||||
|
if (readl(port->membase + ALTERA_UART_STATUS_REG) &
|
||||||
|
ALTERA_UART_STATUS_TRDY_MSK)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
writel(c, port->membase + ALTERA_UART_TXDATA_REG);
|
||||||
|
for (i = 0; i < 0x10000; i++) {
|
||||||
|
if (readl(port->membase + ALTERA_UART_STATUS_REG) &
|
||||||
|
ALTERA_UART_STATUS_TRDY_MSK)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void altera_uart_console_write(struct console *co, const char *s,
|
||||||
|
unsigned int count)
|
||||||
|
{
|
||||||
|
for (; count; count--, s++) {
|
||||||
|
altera_uart_console_putc(co, *s);
|
||||||
|
if (*s == '\n')
|
||||||
|
altera_uart_console_putc(co, '\r');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __init altera_uart_console_setup(struct console *co, char *options)
|
||||||
|
{
|
||||||
|
struct uart_port *port;
|
||||||
|
int baud = CONFIG_SERIAL_ALTERA_UART_BAUDRATE;
|
||||||
|
int bits = 8;
|
||||||
|
int parity = 'n';
|
||||||
|
int flow = 'n';
|
||||||
|
|
||||||
|
if (co->index < 0 || co->index >= CONFIG_SERIAL_ALTERA_UART_MAXPORTS)
|
||||||
|
return -EINVAL;
|
||||||
|
port = &altera_uart_ports[co->index].port;
|
||||||
|
if (port->membase == 0)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
if (options)
|
||||||
|
uart_parse_options(options, &baud, &parity, &bits, &flow);
|
||||||
|
|
||||||
|
return uart_set_options(port, co, baud, parity, bits, flow);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct uart_driver altera_uart_driver;
|
||||||
|
|
||||||
|
static struct console altera_uart_console = {
|
||||||
|
.name = "ttyS",
|
||||||
|
.write = altera_uart_console_write,
|
||||||
|
.device = uart_console_device,
|
||||||
|
.setup = altera_uart_console_setup,
|
||||||
|
.flags = CON_PRINTBUFFER,
|
||||||
|
.index = -1,
|
||||||
|
.data = &altera_uart_driver,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init altera_uart_console_init(void)
|
||||||
|
{
|
||||||
|
register_console(&altera_uart_console);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
console_initcall(altera_uart_console_init);
|
||||||
|
|
||||||
|
#define ALTERA_UART_CONSOLE (&altera_uart_console)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define ALTERA_UART_CONSOLE NULL
|
||||||
|
|
||||||
|
#endif /* CONFIG_ALTERA_UART_CONSOLE */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Define the altera_uart UART driver structure.
|
||||||
|
*/
|
||||||
|
static struct uart_driver altera_uart_driver = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.driver_name = DRV_NAME,
|
||||||
|
.dev_name = "ttyS",
|
||||||
|
.major = TTY_MAJOR,
|
||||||
|
.minor = 64,
|
||||||
|
.nr = CONFIG_SERIAL_ALTERA_UART_MAXPORTS,
|
||||||
|
.cons = ALTERA_UART_CONSOLE,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __devinit altera_uart_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct altera_uart_platform_uart *platp = pdev->dev.platform_data;
|
||||||
|
struct uart_port *port;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < CONFIG_SERIAL_ALTERA_UART_MAXPORTS && platp[i].mapbase; i++) {
|
||||||
|
port = &altera_uart_ports[i].port;
|
||||||
|
|
||||||
|
port->line = i;
|
||||||
|
port->type = PORT_ALTERA_UART;
|
||||||
|
port->mapbase = platp[i].mapbase;
|
||||||
|
port->membase = ioremap(port->mapbase, ALTERA_UART_SIZE);
|
||||||
|
port->iotype = SERIAL_IO_MEM;
|
||||||
|
port->irq = platp[i].irq;
|
||||||
|
port->uartclk = platp[i].uartclk;
|
||||||
|
port->ops = &altera_uart_ops;
|
||||||
|
port->flags = ASYNC_BOOT_AUTOCONF;
|
||||||
|
|
||||||
|
uart_add_one_port(&altera_uart_driver, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int altera_uart_remove(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct uart_port *port;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < CONFIG_SERIAL_ALTERA_UART_MAXPORTS; i++) {
|
||||||
|
port = &altera_uart_ports[i].port;
|
||||||
|
if (port)
|
||||||
|
uart_remove_one_port(&altera_uart_driver, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct platform_driver altera_uart_platform_driver = {
|
||||||
|
.probe = altera_uart_probe,
|
||||||
|
.remove = __devexit_p(altera_uart_remove),
|
||||||
|
.driver = {
|
||||||
|
.name = DRV_NAME,
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.pm = NULL,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init altera_uart_init(void)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = uart_register_driver(&altera_uart_driver);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
rc = platform_driver_register(&altera_uart_platform_driver);
|
||||||
|
if (rc) {
|
||||||
|
uart_unregister_driver(&altera_uart_driver);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit altera_uart_exit(void)
|
||||||
|
{
|
||||||
|
platform_driver_unregister(&altera_uart_platform_driver);
|
||||||
|
uart_unregister_driver(&altera_uart_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(altera_uart_init);
|
||||||
|
module_exit(altera_uart_exit);
|
||||||
|
|
||||||
|
MODULE_DESCRIPTION("Altera UART driver");
|
||||||
|
MODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
MODULE_ALIAS("platform:" DRV_NAME);
|
@ -34,32 +34,12 @@
|
|||||||
#include <linux/tty_flip.h>
|
#include <linux/tty_flip.h>
|
||||||
#include <linux/serial_core.h>
|
#include <linux/serial_core.h>
|
||||||
|
|
||||||
|
#include <asm/bfin_sport.h>
|
||||||
#include <asm/delay.h>
|
#include <asm/delay.h>
|
||||||
#include <asm/portmux.h>
|
#include <asm/portmux.h>
|
||||||
|
|
||||||
#include "bfin_sport_uart.h"
|
#include "bfin_sport_uart.h"
|
||||||
|
|
||||||
#ifdef CONFIG_SERIAL_BFIN_SPORT0_UART
|
|
||||||
unsigned short bfin_uart_pin_req_sport0[] =
|
|
||||||
{P_SPORT0_TFS, P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS, \
|
|
||||||
P_SPORT0_DRPRI, P_SPORT0_RSCLK, P_SPORT0_DRSEC, P_SPORT0_DTSEC, 0};
|
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_SERIAL_BFIN_SPORT1_UART
|
|
||||||
unsigned short bfin_uart_pin_req_sport1[] =
|
|
||||||
{P_SPORT1_TFS, P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS, \
|
|
||||||
P_SPORT1_DRPRI, P_SPORT1_RSCLK, P_SPORT1_DRSEC, P_SPORT1_DTSEC, 0};
|
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_SERIAL_BFIN_SPORT2_UART
|
|
||||||
unsigned short bfin_uart_pin_req_sport2[] =
|
|
||||||
{P_SPORT2_TFS, P_SPORT2_DTPRI, P_SPORT2_TSCLK, P_SPORT2_RFS, \
|
|
||||||
P_SPORT2_DRPRI, P_SPORT2_RSCLK, P_SPORT2_DRSEC, P_SPORT2_DTSEC, 0};
|
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_SERIAL_BFIN_SPORT3_UART
|
|
||||||
unsigned short bfin_uart_pin_req_sport3[] =
|
|
||||||
{P_SPORT3_TFS, P_SPORT3_DTPRI, P_SPORT3_TSCLK, P_SPORT3_RFS, \
|
|
||||||
P_SPORT3_DRPRI, P_SPORT3_RSCLK, P_SPORT3_DRSEC, P_SPORT3_DTSEC, 0};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct sport_uart_port {
|
struct sport_uart_port {
|
||||||
struct uart_port port;
|
struct uart_port port;
|
||||||
int err_irq;
|
int err_irq;
|
||||||
@ -69,9 +49,13 @@ struct sport_uart_port {
|
|||||||
unsigned short txmask2;
|
unsigned short txmask2;
|
||||||
unsigned char stopb;
|
unsigned char stopb;
|
||||||
/* unsigned char parib; */
|
/* unsigned char parib; */
|
||||||
|
#ifdef CONFIG_SERIAL_BFIN_SPORT_CTSRTS
|
||||||
|
int cts_pin;
|
||||||
|
int rts_pin;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static void sport_uart_tx_chars(struct sport_uart_port *up);
|
static int sport_uart_tx_chars(struct sport_uart_port *up);
|
||||||
static void sport_stop_tx(struct uart_port *port);
|
static void sport_stop_tx(struct uart_port *port);
|
||||||
|
|
||||||
static inline void tx_one_byte(struct sport_uart_port *up, unsigned int value)
|
static inline void tx_one_byte(struct sport_uart_port *up, unsigned int value)
|
||||||
@ -219,6 +203,59 @@ static irqreturn_t sport_uart_err_irq(int irq, void *dev_id)
|
|||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_SERIAL_BFIN_SPORT_CTSRTS
|
||||||
|
static unsigned int sport_get_mctrl(struct uart_port *port)
|
||||||
|
{
|
||||||
|
struct sport_uart_port *up = (struct sport_uart_port *)port;
|
||||||
|
if (up->cts_pin < 0)
|
||||||
|
return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
|
||||||
|
|
||||||
|
/* CTS PIN is negative assertive. */
|
||||||
|
if (SPORT_UART_GET_CTS(up))
|
||||||
|
return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
|
||||||
|
else
|
||||||
|
return TIOCM_DSR | TIOCM_CAR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sport_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||||
|
{
|
||||||
|
struct sport_uart_port *up = (struct sport_uart_port *)port;
|
||||||
|
if (up->rts_pin < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* RTS PIN is negative assertive. */
|
||||||
|
if (mctrl & TIOCM_RTS)
|
||||||
|
SPORT_UART_ENABLE_RTS(up);
|
||||||
|
else
|
||||||
|
SPORT_UART_DISABLE_RTS(up);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handle any change of modem status signal.
|
||||||
|
*/
|
||||||
|
static irqreturn_t sport_mctrl_cts_int(int irq, void *dev_id)
|
||||||
|
{
|
||||||
|
struct sport_uart_port *up = (struct sport_uart_port *)dev_id;
|
||||||
|
unsigned int status;
|
||||||
|
|
||||||
|
status = sport_get_mctrl(&up->port);
|
||||||
|
uart_handle_cts_change(&up->port, status & TIOCM_CTS);
|
||||||
|
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static unsigned int sport_get_mctrl(struct uart_port *port)
|
||||||
|
{
|
||||||
|
pr_debug("%s enter\n", __func__);
|
||||||
|
return TIOCM_CTS | TIOCM_CD | TIOCM_DSR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sport_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||||
|
{
|
||||||
|
pr_debug("%s enter\n", __func__);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Reqeust IRQ, Setup clock */
|
/* Reqeust IRQ, Setup clock */
|
||||||
static int sport_startup(struct uart_port *port)
|
static int sport_startup(struct uart_port *port)
|
||||||
{
|
{
|
||||||
@ -247,6 +284,21 @@ static int sport_startup(struct uart_port *port)
|
|||||||
goto fail2;
|
goto fail2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_SERIAL_BFIN_SPORT_CTSRTS
|
||||||
|
if (up->cts_pin >= 0) {
|
||||||
|
if (request_irq(gpio_to_irq(up->cts_pin),
|
||||||
|
sport_mctrl_cts_int,
|
||||||
|
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
|
||||||
|
IRQF_DISABLED, "BFIN_SPORT_UART_CTS", up)) {
|
||||||
|
up->cts_pin = -1;
|
||||||
|
dev_info(port->dev, "Unable to attach BlackFin UART \
|
||||||
|
over SPORT CTS interrupt. So, disable it.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (up->rts_pin >= 0)
|
||||||
|
gpio_direction_output(up->rts_pin, 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
fail2:
|
fail2:
|
||||||
free_irq(up->port.irq+1, up);
|
free_irq(up->port.irq+1, up);
|
||||||
@ -256,23 +308,35 @@ static int sport_startup(struct uart_port *port)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sport_uart_tx_chars(struct sport_uart_port *up)
|
/*
|
||||||
|
* sport_uart_tx_chars
|
||||||
|
*
|
||||||
|
* ret 1 means need to enable sport.
|
||||||
|
* ret 0 means do nothing.
|
||||||
|
*/
|
||||||
|
static int sport_uart_tx_chars(struct sport_uart_port *up)
|
||||||
{
|
{
|
||||||
struct circ_buf *xmit = &up->port.state->xmit;
|
struct circ_buf *xmit = &up->port.state->xmit;
|
||||||
|
|
||||||
if (SPORT_GET_STAT(up) & TXF)
|
if (SPORT_GET_STAT(up) & TXF)
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
if (up->port.x_char) {
|
if (up->port.x_char) {
|
||||||
tx_one_byte(up, up->port.x_char);
|
tx_one_byte(up, up->port.x_char);
|
||||||
up->port.icount.tx++;
|
up->port.icount.tx++;
|
||||||
up->port.x_char = 0;
|
up->port.x_char = 0;
|
||||||
return;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
|
if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
|
||||||
sport_stop_tx(&up->port);
|
/* The waiting loop to stop SPORT TX from TX interrupt is
|
||||||
return;
|
* too long. This may block SPORT RX interrupts and cause
|
||||||
|
* RX FIFO overflow. So, do stop sport TX only after the last
|
||||||
|
* char in TX FIFO is moved into the shift register.
|
||||||
|
*/
|
||||||
|
if (SPORT_GET_STAT(up) & TXHRE)
|
||||||
|
sport_stop_tx(&up->port);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
while(!(SPORT_GET_STAT(up) & TXF) && !uart_circ_empty(xmit)) {
|
while(!(SPORT_GET_STAT(up) & TXF) && !uart_circ_empty(xmit)) {
|
||||||
@ -283,6 +347,8 @@ static void sport_uart_tx_chars(struct sport_uart_port *up)
|
|||||||
|
|
||||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||||
uart_write_wakeup(&up->port);
|
uart_write_wakeup(&up->port);
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int sport_tx_empty(struct uart_port *port)
|
static unsigned int sport_tx_empty(struct uart_port *port)
|
||||||
@ -298,23 +364,15 @@ static unsigned int sport_tx_empty(struct uart_port *port)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int sport_get_mctrl(struct uart_port *port)
|
|
||||||
{
|
|
||||||
pr_debug("%s enter\n", __func__);
|
|
||||||
return (TIOCM_CTS | TIOCM_CD | TIOCM_DSR);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void sport_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
|
||||||
{
|
|
||||||
pr_debug("%s enter\n", __func__);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void sport_stop_tx(struct uart_port *port)
|
static void sport_stop_tx(struct uart_port *port)
|
||||||
{
|
{
|
||||||
struct sport_uart_port *up = (struct sport_uart_port *)port;
|
struct sport_uart_port *up = (struct sport_uart_port *)port;
|
||||||
|
|
||||||
pr_debug("%s enter\n", __func__);
|
pr_debug("%s enter\n", __func__);
|
||||||
|
|
||||||
|
if (!(SPORT_GET_TCR1(up) & TSPEN))
|
||||||
|
return;
|
||||||
|
|
||||||
/* Although the hold register is empty, last byte is still in shift
|
/* 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.
|
* 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
|
* Then, sport tx stops when last byte is shift out and the dummy
|
||||||
@ -337,11 +395,12 @@ static void sport_start_tx(struct uart_port *port)
|
|||||||
pr_debug("%s enter\n", __func__);
|
pr_debug("%s enter\n", __func__);
|
||||||
|
|
||||||
/* Write data into SPORT FIFO before enable SPROT to transmit */
|
/* Write data into SPORT FIFO before enable SPROT to transmit */
|
||||||
sport_uart_tx_chars(up);
|
if (sport_uart_tx_chars(up)) {
|
||||||
|
/* Enable transmit, then an interrupt will generated */
|
||||||
|
SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) | TSPEN));
|
||||||
|
SSYNC();
|
||||||
|
}
|
||||||
|
|
||||||
/* Enable transmit, then an interrupt will generated */
|
|
||||||
SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) | TSPEN));
|
|
||||||
SSYNC();
|
|
||||||
pr_debug("%s exit\n", __func__);
|
pr_debug("%s exit\n", __func__);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -379,6 +438,10 @@ static void sport_shutdown(struct uart_port *port)
|
|||||||
free_irq(up->port.irq, up);
|
free_irq(up->port.irq, up);
|
||||||
free_irq(up->port.irq+1, up);
|
free_irq(up->port.irq+1, up);
|
||||||
free_irq(up->err_irq, up);
|
free_irq(up->err_irq, up);
|
||||||
|
#ifdef CONFIG_SERIAL_BFIN_SPORT_CTSRTS
|
||||||
|
if (up->cts_pin >= 0)
|
||||||
|
free_irq(gpio_to_irq(up->cts_pin), up);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *sport_type(struct uart_port *port)
|
static const char *sport_type(struct uart_port *port)
|
||||||
@ -448,27 +511,14 @@ static void sport_set_termios(struct uart_port *port,
|
|||||||
/* up->parib = 1; */
|
/* up->parib = 1; */
|
||||||
}
|
}
|
||||||
|
|
||||||
port->read_status_mask = OE;
|
spin_lock_irqsave(&up->port.lock, flags);
|
||||||
if (termios->c_iflag & INPCK)
|
|
||||||
port->read_status_mask |= (FE | PE);
|
port->read_status_mask = 0;
|
||||||
if (termios->c_iflag & (BRKINT | PARMRK))
|
|
||||||
port->read_status_mask |= BI;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Characters to ignore
|
* Characters to ignore
|
||||||
*/
|
*/
|
||||||
port->ignore_status_mask = 0;
|
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 */
|
/* RX extract mask */
|
||||||
up->rxmask = 0x01 | (((up->csize + up->stopb) * 2 - 1) << 0x8);
|
up->rxmask = 0x01 | (((up->csize + up->stopb) * 2 - 1) << 0x8);
|
||||||
@ -488,8 +538,6 @@ static void sport_set_termios(struct uart_port *port,
|
|||||||
/* uart baud rate */
|
/* uart baud rate */
|
||||||
port->uartclk = uart_get_baud_rate(port, termios, old, 0, get_sclk()/16);
|
port->uartclk = uart_get_baud_rate(port, termios, old, 0, get_sclk()/16);
|
||||||
|
|
||||||
spin_lock_irqsave(&up->port.lock, flags);
|
|
||||||
|
|
||||||
/* Disable UART */
|
/* Disable UART */
|
||||||
SPORT_PUT_TCR1(up, SPORT_GET_TCR1(up) & ~TSPEN);
|
SPORT_PUT_TCR1(up, SPORT_GET_TCR1(up) & ~TSPEN);
|
||||||
SPORT_PUT_RCR1(up, SPORT_GET_RCR1(up) & ~RSPEN);
|
SPORT_PUT_RCR1(up, SPORT_GET_RCR1(up) & ~RSPEN);
|
||||||
@ -542,6 +590,8 @@ struct uart_ops sport_uart_ops = {
|
|||||||
static struct sport_uart_port *bfin_sport_uart_ports[BFIN_SPORT_UART_MAX_PORTS];
|
static struct sport_uart_port *bfin_sport_uart_ports[BFIN_SPORT_UART_MAX_PORTS];
|
||||||
|
|
||||||
#ifdef CONFIG_SERIAL_BFIN_SPORT_CONSOLE
|
#ifdef CONFIG_SERIAL_BFIN_SPORT_CONSOLE
|
||||||
|
#define CLASS_BFIN_SPORT_CONSOLE "bfin-sport-console"
|
||||||
|
|
||||||
static int __init
|
static int __init
|
||||||
sport_uart_console_setup(struct console *co, char *options)
|
sport_uart_console_setup(struct console *co, char *options)
|
||||||
{
|
{
|
||||||
@ -549,7 +599,11 @@ sport_uart_console_setup(struct console *co, char *options)
|
|||||||
int baud = 57600;
|
int baud = 57600;
|
||||||
int bits = 8;
|
int bits = 8;
|
||||||
int parity = 'n';
|
int parity = 'n';
|
||||||
|
# ifdef CONFIG_SERIAL_BFIN_SPORT_CTSRTS
|
||||||
|
int flow = 'r';
|
||||||
|
# else
|
||||||
int flow = 'n';
|
int flow = 'n';
|
||||||
|
# endif
|
||||||
|
|
||||||
/* Check whether an invalid uart number has been specified */
|
/* Check whether an invalid uart number has been specified */
|
||||||
if (co->index < 0 || co->index >= BFIN_SPORT_UART_MAX_PORTS)
|
if (co->index < 0 || co->index >= BFIN_SPORT_UART_MAX_PORTS)
|
||||||
@ -690,11 +744,11 @@ static int __devinit sport_uart_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
if (bfin_sport_uart_ports[pdev->id] == NULL) {
|
if (bfin_sport_uart_ports[pdev->id] == NULL) {
|
||||||
bfin_sport_uart_ports[pdev->id] =
|
bfin_sport_uart_ports[pdev->id] =
|
||||||
kmalloc(sizeof(struct sport_uart_port), GFP_KERNEL);
|
kzalloc(sizeof(struct sport_uart_port), GFP_KERNEL);
|
||||||
sport = bfin_sport_uart_ports[pdev->id];
|
sport = bfin_sport_uart_ports[pdev->id];
|
||||||
if (!sport) {
|
if (!sport) {
|
||||||
dev_err(&pdev->dev,
|
dev_err(&pdev->dev,
|
||||||
"Fail to kmalloc sport_uart_port\n");
|
"Fail to malloc sport_uart_port\n");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -720,13 +774,13 @@ static int __devinit sport_uart_probe(struct platform_device *pdev)
|
|||||||
goto out_error_free_peripherals;
|
goto out_error_free_peripherals;
|
||||||
}
|
}
|
||||||
|
|
||||||
sport->port.membase = ioremap(res->start,
|
sport->port.membase = ioremap(res->start, resource_size(res));
|
||||||
res->end - res->start);
|
|
||||||
if (!sport->port.membase) {
|
if (!sport->port.membase) {
|
||||||
dev_err(&pdev->dev, "Cannot map sport IO\n");
|
dev_err(&pdev->dev, "Cannot map sport IO\n");
|
||||||
ret = -ENXIO;
|
ret = -ENXIO;
|
||||||
goto out_error_free_peripherals;
|
goto out_error_free_peripherals;
|
||||||
}
|
}
|
||||||
|
sport->port.mapbase = res->start;
|
||||||
|
|
||||||
sport->port.irq = platform_get_irq(pdev, 0);
|
sport->port.irq = platform_get_irq(pdev, 0);
|
||||||
if (sport->port.irq < 0) {
|
if (sport->port.irq < 0) {
|
||||||
@ -741,6 +795,22 @@ static int __devinit sport_uart_probe(struct platform_device *pdev)
|
|||||||
ret = -ENOENT;
|
ret = -ENOENT;
|
||||||
goto out_error_unmap;
|
goto out_error_unmap;
|
||||||
}
|
}
|
||||||
|
#ifdef CONFIG_SERIAL_BFIN_SPORT_CTSRTS
|
||||||
|
res = platform_get_resource(pdev, IORESOURCE_IO, 0);
|
||||||
|
if (res == NULL)
|
||||||
|
sport->cts_pin = -1;
|
||||||
|
else
|
||||||
|
sport->cts_pin = res->start;
|
||||||
|
|
||||||
|
res = platform_get_resource(pdev, IORESOURCE_IO, 1);
|
||||||
|
if (res == NULL)
|
||||||
|
sport->rts_pin = -1;
|
||||||
|
else
|
||||||
|
sport->rts_pin = res->start;
|
||||||
|
|
||||||
|
if (sport->rts_pin >= 0)
|
||||||
|
gpio_request(sport->rts_pin, DRV_NAME);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_SERIAL_BFIN_SPORT_CONSOLE
|
#ifdef CONFIG_SERIAL_BFIN_SPORT_CONSOLE
|
||||||
@ -779,6 +849,10 @@ static int __devexit sport_uart_remove(struct platform_device *pdev)
|
|||||||
|
|
||||||
if (sport) {
|
if (sport) {
|
||||||
uart_remove_one_port(&sport_uart_reg, &sport->port);
|
uart_remove_one_port(&sport_uart_reg, &sport->port);
|
||||||
|
#ifdef CONFIG_SERIAL_BFIN_CTSRTS
|
||||||
|
if (sport->rts_pin >= 0)
|
||||||
|
gpio_free(sport->rts_pin);
|
||||||
|
#endif
|
||||||
iounmap(sport->port.membase);
|
iounmap(sport->port.membase);
|
||||||
peripheral_free_list(
|
peripheral_free_list(
|
||||||
(unsigned short *)pdev->dev.platform_data);
|
(unsigned short *)pdev->dev.platform_data);
|
||||||
@ -802,7 +876,7 @@ static struct platform_driver sport_uart_driver = {
|
|||||||
|
|
||||||
#ifdef CONFIG_SERIAL_BFIN_SPORT_CONSOLE
|
#ifdef CONFIG_SERIAL_BFIN_SPORT_CONSOLE
|
||||||
static __initdata struct early_platform_driver early_sport_uart_driver = {
|
static __initdata struct early_platform_driver early_sport_uart_driver = {
|
||||||
.class_str = DRV_NAME,
|
.class_str = CLASS_BFIN_SPORT_CONSOLE,
|
||||||
.pdrv = &sport_uart_driver,
|
.pdrv = &sport_uart_driver,
|
||||||
.requested_id = EARLY_PLATFORM_ID_UNSET,
|
.requested_id = EARLY_PLATFORM_ID_UNSET,
|
||||||
};
|
};
|
||||||
@ -811,7 +885,8 @@ static int __init sport_uart_rs_console_init(void)
|
|||||||
{
|
{
|
||||||
early_platform_driver_register(&early_sport_uart_driver, DRV_NAME);
|
early_platform_driver_register(&early_sport_uart_driver, DRV_NAME);
|
||||||
|
|
||||||
early_platform_driver_probe(DRV_NAME, BFIN_SPORT_UART_MAX_PORTS, 0);
|
early_platform_driver_probe(CLASS_BFIN_SPORT_CONSOLE,
|
||||||
|
BFIN_SPORT_UART_MAX_PORTS, 0);
|
||||||
|
|
||||||
register_console(&sport_uart_console);
|
register_console(&sport_uart_console);
|
||||||
|
|
||||||
@ -824,7 +899,7 @@ static int __init sport_uart_init(void)
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
pr_info("Serial: Blackfin uart over sport driver\n");
|
pr_info("Blackfin uart over sport driver\n");
|
||||||
|
|
||||||
ret = uart_register_driver(&sport_uart_reg);
|
ret = uart_register_driver(&sport_uart_reg);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
@ -37,7 +37,21 @@
|
|||||||
#define SPORT_GET_TFSDIV(sport) bfin_read16(((sport)->port.membase + OFFSET_TFSDIV))
|
#define SPORT_GET_TFSDIV(sport) bfin_read16(((sport)->port.membase + OFFSET_TFSDIV))
|
||||||
#define SPORT_GET_TX(sport) bfin_read16(((sport)->port.membase + OFFSET_TX))
|
#define SPORT_GET_TX(sport) bfin_read16(((sport)->port.membase + OFFSET_TX))
|
||||||
#define SPORT_GET_RX(sport) bfin_read16(((sport)->port.membase + OFFSET_RX))
|
#define SPORT_GET_RX(sport) bfin_read16(((sport)->port.membase + OFFSET_RX))
|
||||||
#define SPORT_GET_RX32(sport) bfin_read32(((sport)->port.membase + OFFSET_RX))
|
/*
|
||||||
|
* If another interrupt fires while doing a 32-bit read from RX FIFO,
|
||||||
|
* a fake RX underflow error will be generated. So disable interrupts
|
||||||
|
* to prevent interruption while reading the FIFO.
|
||||||
|
*/
|
||||||
|
#define SPORT_GET_RX32(sport) \
|
||||||
|
({ \
|
||||||
|
unsigned int __ret; \
|
||||||
|
if (ANOMALY_05000473) \
|
||||||
|
local_irq_disable(); \
|
||||||
|
__ret = bfin_read32((sport)->port.membase + OFFSET_RX); \
|
||||||
|
if (ANOMALY_05000473) \
|
||||||
|
local_irq_enable(); \
|
||||||
|
__ret; \
|
||||||
|
})
|
||||||
#define SPORT_GET_RCR1(sport) bfin_read16(((sport)->port.membase + OFFSET_RCR1))
|
#define SPORT_GET_RCR1(sport) bfin_read16(((sport)->port.membase + OFFSET_RCR1))
|
||||||
#define SPORT_GET_RCR2(sport) bfin_read16(((sport)->port.membase + OFFSET_RCR2))
|
#define SPORT_GET_RCR2(sport) bfin_read16(((sport)->port.membase + OFFSET_RCR2))
|
||||||
#define SPORT_GET_RCLKDIV(sport) bfin_read16(((sport)->port.membase + OFFSET_RCLKDIV))
|
#define SPORT_GET_RCLKDIV(sport) bfin_read16(((sport)->port.membase + OFFSET_RCLKDIV))
|
||||||
@ -58,4 +72,15 @@
|
|||||||
|
|
||||||
#define SPORT_TX_FIFO_SIZE 8
|
#define SPORT_TX_FIFO_SIZE 8
|
||||||
|
|
||||||
|
#define SPORT_UART_GET_CTS(x) gpio_get_value(x->cts_pin)
|
||||||
|
#define SPORT_UART_DISABLE_RTS(x) gpio_set_value(x->rts_pin, 1)
|
||||||
|
#define SPORT_UART_ENABLE_RTS(x) gpio_set_value(x->rts_pin, 0)
|
||||||
|
|
||||||
|
#if defined(CONFIG_SERIAL_BFIN_SPORT0_UART_CTSRTS) \
|
||||||
|
|| defined(CONFIG_SERIAL_BFIN_SPORT1_UART_CTSRTS) \
|
||||||
|
|| defined(CONFIG_SERIAL_BFIN_SPORT2_UART_CTSRTS) \
|
||||||
|
|| defined(CONFIG_SERIAL_BFIN_SPORT3_UART_CTSRTS)
|
||||||
|
# define CONFIG_SERIAL_BFIN_SPORT_CTSRTS
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* _BFIN_SPORT_UART_H */
|
#endif /* _BFIN_SPORT_UART_H */
|
||||||
|
@ -68,12 +68,22 @@ static void timbuart_start_tx(struct uart_port *port)
|
|||||||
tasklet_schedule(&uart->tasklet);
|
tasklet_schedule(&uart->tasklet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned int timbuart_tx_empty(struct uart_port *port)
|
||||||
|
{
|
||||||
|
u32 isr = ioread32(port->membase + TIMBUART_ISR);
|
||||||
|
|
||||||
|
return (isr & TXBE) ? TIOCSER_TEMT : 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void timbuart_flush_buffer(struct uart_port *port)
|
static void timbuart_flush_buffer(struct uart_port *port)
|
||||||
{
|
{
|
||||||
u8 ctl = ioread8(port->membase + TIMBUART_CTRL) | TIMBUART_CTRL_FLSHTX;
|
if (!timbuart_tx_empty(port)) {
|
||||||
|
u8 ctl = ioread8(port->membase + TIMBUART_CTRL) |
|
||||||
|
TIMBUART_CTRL_FLSHTX;
|
||||||
|
|
||||||
iowrite8(ctl, port->membase + TIMBUART_CTRL);
|
iowrite8(ctl, port->membase + TIMBUART_CTRL);
|
||||||
iowrite32(TXBF, port->membase + TIMBUART_ISR);
|
iowrite32(TXBF, port->membase + TIMBUART_ISR);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void timbuart_rx_chars(struct uart_port *port)
|
static void timbuart_rx_chars(struct uart_port *port)
|
||||||
@ -195,13 +205,6 @@ void timbuart_tasklet(unsigned long arg)
|
|||||||
dev_dbg(uart->port.dev, "%s leaving\n", __func__);
|
dev_dbg(uart->port.dev, "%s leaving\n", __func__);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int timbuart_tx_empty(struct uart_port *port)
|
|
||||||
{
|
|
||||||
u32 isr = ioread32(port->membase + TIMBUART_ISR);
|
|
||||||
|
|
||||||
return (isr & TXBE) ? TIOCSER_TEMT : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned int timbuart_get_mctrl(struct uart_port *port)
|
static unsigned int timbuart_get_mctrl(struct uart_port *port)
|
||||||
{
|
{
|
||||||
u8 cts = ioread8(port->membase + TIMBUART_CTRL);
|
u8 cts = ioread8(port->membase + TIMBUART_CTRL);
|
||||||
@ -220,7 +223,7 @@ static void timbuart_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
|||||||
if (mctrl & TIOCM_RTS)
|
if (mctrl & TIOCM_RTS)
|
||||||
iowrite8(TIMBUART_CTRL_RTS, port->membase + TIMBUART_CTRL);
|
iowrite8(TIMBUART_CTRL_RTS, port->membase + TIMBUART_CTRL);
|
||||||
else
|
else
|
||||||
iowrite8(TIMBUART_CTRL_RTS, port->membase + TIMBUART_CTRL);
|
iowrite8(0, port->membase + TIMBUART_CTRL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void timbuart_mctrl_check(struct uart_port *port, u32 isr, u32 *ier)
|
static void timbuart_mctrl_check(struct uart_port *port, u32 isr, u32 *ier)
|
||||||
|
@ -86,7 +86,7 @@ static int ulite_receive(struct uart_port *port, int stat)
|
|||||||
/* stats */
|
/* stats */
|
||||||
if (stat & ULITE_STATUS_RXVALID) {
|
if (stat & ULITE_STATUS_RXVALID) {
|
||||||
port->icount.rx++;
|
port->icount.rx++;
|
||||||
ch = readb(port->membase + ULITE_RX);
|
ch = ioread32be(port->membase + ULITE_RX);
|
||||||
|
|
||||||
if (stat & ULITE_STATUS_PARITY)
|
if (stat & ULITE_STATUS_PARITY)
|
||||||
port->icount.parity++;
|
port->icount.parity++;
|
||||||
@ -131,7 +131,7 @@ static int ulite_transmit(struct uart_port *port, int stat)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (port->x_char) {
|
if (port->x_char) {
|
||||||
writeb(port->x_char, port->membase + ULITE_TX);
|
iowrite32be(port->x_char, port->membase + ULITE_TX);
|
||||||
port->x_char = 0;
|
port->x_char = 0;
|
||||||
port->icount.tx++;
|
port->icount.tx++;
|
||||||
return 1;
|
return 1;
|
||||||
@ -140,7 +140,7 @@ static int ulite_transmit(struct uart_port *port, int stat)
|
|||||||
if (uart_circ_empty(xmit) || uart_tx_stopped(port))
|
if (uart_circ_empty(xmit) || uart_tx_stopped(port))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
writeb(xmit->buf[xmit->tail], port->membase + ULITE_TX);
|
iowrite32be(xmit->buf[xmit->tail], port->membase + ULITE_TX);
|
||||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE-1);
|
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE-1);
|
||||||
port->icount.tx++;
|
port->icount.tx++;
|
||||||
|
|
||||||
@ -157,7 +157,7 @@ static irqreturn_t ulite_isr(int irq, void *dev_id)
|
|||||||
int busy, n = 0;
|
int busy, n = 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
int stat = readb(port->membase + ULITE_STATUS);
|
int stat = ioread32be(port->membase + ULITE_STATUS);
|
||||||
busy = ulite_receive(port, stat);
|
busy = ulite_receive(port, stat);
|
||||||
busy |= ulite_transmit(port, stat);
|
busy |= ulite_transmit(port, stat);
|
||||||
n++;
|
n++;
|
||||||
@ -178,7 +178,7 @@ static unsigned int ulite_tx_empty(struct uart_port *port)
|
|||||||
unsigned int ret;
|
unsigned int ret;
|
||||||
|
|
||||||
spin_lock_irqsave(&port->lock, flags);
|
spin_lock_irqsave(&port->lock, flags);
|
||||||
ret = readb(port->membase + ULITE_STATUS);
|
ret = ioread32be(port->membase + ULITE_STATUS);
|
||||||
spin_unlock_irqrestore(&port->lock, flags);
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
|
|
||||||
return ret & ULITE_STATUS_TXEMPTY ? TIOCSER_TEMT : 0;
|
return ret & ULITE_STATUS_TXEMPTY ? TIOCSER_TEMT : 0;
|
||||||
@ -201,7 +201,7 @@ static void ulite_stop_tx(struct uart_port *port)
|
|||||||
|
|
||||||
static void ulite_start_tx(struct uart_port *port)
|
static void ulite_start_tx(struct uart_port *port)
|
||||||
{
|
{
|
||||||
ulite_transmit(port, readb(port->membase + ULITE_STATUS));
|
ulite_transmit(port, ioread32be(port->membase + ULITE_STATUS));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ulite_stop_rx(struct uart_port *port)
|
static void ulite_stop_rx(struct uart_port *port)
|
||||||
@ -230,17 +230,17 @@ static int ulite_startup(struct uart_port *port)
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
writeb(ULITE_CONTROL_RST_RX | ULITE_CONTROL_RST_TX,
|
iowrite32be(ULITE_CONTROL_RST_RX | ULITE_CONTROL_RST_TX,
|
||||||
port->membase + ULITE_CONTROL);
|
port->membase + ULITE_CONTROL);
|
||||||
writeb(ULITE_CONTROL_IE, port->membase + ULITE_CONTROL);
|
iowrite32be(ULITE_CONTROL_IE, port->membase + ULITE_CONTROL);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ulite_shutdown(struct uart_port *port)
|
static void ulite_shutdown(struct uart_port *port)
|
||||||
{
|
{
|
||||||
writeb(0, port->membase + ULITE_CONTROL);
|
iowrite32be(0, port->membase + ULITE_CONTROL);
|
||||||
readb(port->membase + ULITE_CONTROL); /* dummy */
|
ioread32be(port->membase + ULITE_CONTROL); /* dummy */
|
||||||
free_irq(port->irq, port);
|
free_irq(port->irq, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -352,7 +352,7 @@ static void ulite_console_wait_tx(struct uart_port *port)
|
|||||||
|
|
||||||
/* Spin waiting for TX fifo to have space available */
|
/* Spin waiting for TX fifo to have space available */
|
||||||
for (i = 0; i < 100000; i++) {
|
for (i = 0; i < 100000; i++) {
|
||||||
val = readb(port->membase + ULITE_STATUS);
|
val = ioread32be(port->membase + ULITE_STATUS);
|
||||||
if ((val & ULITE_STATUS_TXFULL) == 0)
|
if ((val & ULITE_STATUS_TXFULL) == 0)
|
||||||
break;
|
break;
|
||||||
cpu_relax();
|
cpu_relax();
|
||||||
@ -362,7 +362,7 @@ static void ulite_console_wait_tx(struct uart_port *port)
|
|||||||
static void ulite_console_putchar(struct uart_port *port, int ch)
|
static void ulite_console_putchar(struct uart_port *port, int ch)
|
||||||
{
|
{
|
||||||
ulite_console_wait_tx(port);
|
ulite_console_wait_tx(port);
|
||||||
writeb(ch, port->membase + ULITE_TX);
|
iowrite32be(ch, port->membase + ULITE_TX);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ulite_console_write(struct console *co, const char *s,
|
static void ulite_console_write(struct console *co, const char *s,
|
||||||
@ -379,8 +379,8 @@ static void ulite_console_write(struct console *co, const char *s,
|
|||||||
spin_lock_irqsave(&port->lock, flags);
|
spin_lock_irqsave(&port->lock, flags);
|
||||||
|
|
||||||
/* save and disable interrupt */
|
/* save and disable interrupt */
|
||||||
ier = readb(port->membase + ULITE_STATUS) & ULITE_STATUS_IE;
|
ier = ioread32be(port->membase + ULITE_STATUS) & ULITE_STATUS_IE;
|
||||||
writeb(0, port->membase + ULITE_CONTROL);
|
iowrite32be(0, port->membase + ULITE_CONTROL);
|
||||||
|
|
||||||
uart_console_write(port, s, count, ulite_console_putchar);
|
uart_console_write(port, s, count, ulite_console_putchar);
|
||||||
|
|
||||||
@ -388,7 +388,7 @@ static void ulite_console_write(struct console *co, const char *s,
|
|||||||
|
|
||||||
/* restore interrupt state */
|
/* restore interrupt state */
|
||||||
if (ier)
|
if (ier)
|
||||||
writeb(ULITE_CONTROL_IE, port->membase + ULITE_CONTROL);
|
iowrite32be(ULITE_CONTROL_IE, port->membase + ULITE_CONTROL);
|
||||||
|
|
||||||
if (locked)
|
if (locked)
|
||||||
spin_unlock_irqrestore(&port->lock, flags);
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
@ -601,7 +601,7 @@ ulite_of_probe(struct of_device *op, const struct of_device_id *match)
|
|||||||
|
|
||||||
id = of_get_property(op->node, "port-number", NULL);
|
id = of_get_property(op->node, "port-number", NULL);
|
||||||
|
|
||||||
return ulite_assign(&op->dev, id ? *id : -1, res.start+3, irq);
|
return ulite_assign(&op->dev, id ? *id : -1, res.start, irq);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __devexit ulite_of_remove(struct of_device *op)
|
static int __devexit ulite_of_remove(struct of_device *op)
|
||||||
|
16
include/linux/altera_jtaguart.h
Normal file
16
include/linux/altera_jtaguart.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
/*
|
||||||
|
* altera_jtaguart.h -- Altera JTAG UART driver defines.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ALTJUART_H
|
||||||
|
#define __ALTJUART_H
|
||||||
|
|
||||||
|
#define ALTERA_JTAGUART_MAJOR 204
|
||||||
|
#define ALTERA_JTAGUART_MINOR 186
|
||||||
|
|
||||||
|
struct altera_jtaguart_platform_uart {
|
||||||
|
unsigned long mapbase; /* Physical address base */
|
||||||
|
unsigned int irq; /* Interrupt vector */
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* __ALTJUART_H */
|
14
include/linux/altera_uart.h
Normal file
14
include/linux/altera_uart.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
/*
|
||||||
|
* altera_uart.h -- Altera UART driver defines.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ALTUART_H
|
||||||
|
#define __ALTUART_H
|
||||||
|
|
||||||
|
struct altera_uart_platform_uart {
|
||||||
|
unsigned long mapbase; /* Physical address base */
|
||||||
|
unsigned int irq; /* Interrupt vector */
|
||||||
|
unsigned int uartclk; /* UART clock rate */
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* __ALTUART_H */
|
25
include/linux/gsmmux.h
Normal file
25
include/linux/gsmmux.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#ifndef _LINUX_GSMMUX_H
|
||||||
|
#define _LINUX_GSMMUX_H
|
||||||
|
|
||||||
|
struct gsm_config
|
||||||
|
{
|
||||||
|
unsigned int adaption;
|
||||||
|
unsigned int encapsulation;
|
||||||
|
unsigned int initiator;
|
||||||
|
unsigned int t1;
|
||||||
|
unsigned int t2;
|
||||||
|
unsigned int t3;
|
||||||
|
unsigned int n2;
|
||||||
|
unsigned int mru;
|
||||||
|
unsigned int mtu;
|
||||||
|
unsigned int k;
|
||||||
|
unsigned int i;
|
||||||
|
unsigned int unused[8]; /* Padding for expansion without
|
||||||
|
breaking stuff */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define GSMIOC_GETCONF _IOR('G', 0, struct gsm_config)
|
||||||
|
#define GSMIOC_SETCONF _IOW('G', 1, struct gsm_config)
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
@ -182,6 +182,10 @@
|
|||||||
/* Aeroflex Gaisler GRLIB APBUART */
|
/* Aeroflex Gaisler GRLIB APBUART */
|
||||||
#define PORT_APBUART 90
|
#define PORT_APBUART 90
|
||||||
|
|
||||||
|
/* Altera UARTs */
|
||||||
|
#define PORT_ALTERA_JTAGUART 91
|
||||||
|
#define PORT_ALTERA_UART 92
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
#ifdef __KERNEL__
|
||||||
|
|
||||||
#include <linux/compiler.h>
|
#include <linux/compiler.h>
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
*/
|
*/
|
||||||
#define NR_UNIX98_PTY_DEFAULT 4096 /* Default maximum for Unix98 ptys */
|
#define NR_UNIX98_PTY_DEFAULT 4096 /* Default maximum for Unix98 ptys */
|
||||||
#define NR_UNIX98_PTY_MAX (1 << MINORBITS) /* Absolute limit */
|
#define NR_UNIX98_PTY_MAX (1 << MINORBITS) /* Absolute limit */
|
||||||
#define NR_LDISCS 21
|
#define NR_LDISCS 30
|
||||||
|
|
||||||
/* line disciplines */
|
/* line disciplines */
|
||||||
#define N_TTY 0
|
#define N_TTY 0
|
||||||
@ -48,6 +48,7 @@
|
|||||||
#define N_PPS 18 /* Pulse per Second */
|
#define N_PPS 18 /* Pulse per Second */
|
||||||
#define N_V253 19 /* Codec control over voice modem */
|
#define N_V253 19 /* Codec control over voice modem */
|
||||||
#define N_CAIF 20 /* CAIF protocol for talking to modems */
|
#define N_CAIF 20 /* CAIF protocol for talking to modems */
|
||||||
|
#define N_GSM0710 21 /* GSM 0710 Mux */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This character is the same as _POSIX_VDISABLE: it cannot be used as
|
* This character is the same as _POSIX_VDISABLE: it cannot be used as
|
||||||
|
Loading…
Reference in New Issue
Block a user