Merge tag 'tty-3.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
Pull TTY/Serial merge from Greg Kroah-Hartman: "Here's the big tty/serial tree set of changes for 3.8-rc1. Contained in here is a bunch more reworks of the tty port layer from Jiri and bugfixes from Alan, along with a number of other tty and serial driver updates by the various driver authors. Also, Jiri has been coerced^Wconvinced to be the co-maintainer of the TTY layer, which is much appreciated by me. All of these have been in the linux-next tree for a while. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>" Fixed up some trivial conflicts in the staging tree, due to the fwserial driver having come in both ways (but fixed up a bit in the serial tree), and the ioctl handling in the dgrp driver having been done slightly differently (staging tree got that one right, and removed both TIOCGSOFTCAR and TIOCSSOFTCAR). * tag 'tty-3.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (146 commits) staging: sb105x: fix potential NULL pointer dereference in mp_chars_in_buffer() staging/fwserial: Remove superfluous free staging/fwserial: Use WARN_ONCE when port table is corrupted staging/fwserial: Destruct embedded tty_port on teardown staging/fwserial: Fix build breakage when !CONFIG_BUG staging: fwserial: Add TTY-over-Firewire serial driver drivers/tty/serial/serial_core.c: clean up HIGH_BITS_OFFSET usage staging: dgrp: dgrp_tty.c: Audit the return values of get/put_user() staging: dgrp: dgrp_tty.c: Remove the TIOCSSOFTCAR ioctl handler from dgrp driver serial: ifx6x60: Add modem power off function in the platform reboot process serial: mxs-auart: unmap the scatter list before we copy the data serial: mxs-auart: disable the Receive Timeout Interrupt when DMA is enabled serial: max310x: Setup missing "can_sleep" field for GPIO tty/serial: fix ifx6x60.c declaration warning serial: samsung: add devicetree properties for non-Exynos SoCs serial: samsung: fix potential soft lockup during uart write tty: vt: Remove redundant null check before kfree. tty/8250 Add check for pci_ioremap_bar failure tty/8250 Add support for Commtech's Fastcom Async-335 and Fastcom Async-PCIe cards tty/8250 Add XR17D15x devices to the exar_handle_irq override ...
This commit is contained in:
@@ -1771,6 +1771,7 @@ fail_free_irq:
|
||||
fail_unregister:
|
||||
tty_unregister_driver(serial_driver);
|
||||
fail_put_tty_driver:
|
||||
tty_port_destroy(&state->tport);
|
||||
put_tty_driver(serial_driver);
|
||||
return error;
|
||||
}
|
||||
@@ -1785,6 +1786,7 @@ static int __exit amiga_serial_remove(struct platform_device *pdev)
|
||||
printk("SERIAL: failed to unregister serial driver (%d)\n",
|
||||
error);
|
||||
put_tty_driver(serial_driver);
|
||||
tty_port_destroy(&state->tport);
|
||||
|
||||
free_irq(IRQ_AMIGA_TBE, state);
|
||||
free_irq(IRQ_AMIGA_RBF, state);
|
||||
|
@@ -240,8 +240,6 @@ static int __init bfin_jc_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
tty_port_init(&port);
|
||||
|
||||
bfin_jc_kthread = kthread_create(bfin_jc_emudat_manager, NULL, DRV_NAME);
|
||||
if (IS_ERR(bfin_jc_kthread))
|
||||
return PTR_ERR(bfin_jc_kthread);
|
||||
@@ -257,6 +255,8 @@ static int __init bfin_jc_init(void)
|
||||
if (!bfin_jc_driver)
|
||||
goto err_driver;
|
||||
|
||||
tty_port_init(&port);
|
||||
|
||||
bfin_jc_driver->driver_name = DRV_NAME;
|
||||
bfin_jc_driver->name = DEV_NAME;
|
||||
bfin_jc_driver->type = TTY_DRIVER_TYPE_SERIAL;
|
||||
@@ -274,6 +274,7 @@ static int __init bfin_jc_init(void)
|
||||
return 0;
|
||||
|
||||
err:
|
||||
tty_port_destroy(&port);
|
||||
put_tty_driver(bfin_jc_driver);
|
||||
err_driver:
|
||||
kfree(bfin_jc_write_buf.buf);
|
||||
@@ -289,6 +290,7 @@ static void __exit bfin_jc_exit(void)
|
||||
kfree(bfin_jc_write_buf.buf);
|
||||
tty_unregister_driver(bfin_jc_driver);
|
||||
put_tty_driver(bfin_jc_driver);
|
||||
tty_port_destroy(&port);
|
||||
}
|
||||
module_exit(bfin_jc_exit);
|
||||
|
||||
|
@@ -3099,7 +3099,7 @@ static const struct tty_port_operations cyz_port_ops = {
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int __devinit cy_init_card(struct cyclades_card *cinfo)
|
||||
static int cy_init_card(struct cyclades_card *cinfo)
|
||||
{
|
||||
struct cyclades_port *info;
|
||||
unsigned int channel, port;
|
||||
@@ -3196,7 +3196,7 @@ static int __devinit cy_init_card(struct cyclades_card *cinfo)
|
||||
|
||||
/* initialize chips on Cyclom-Y card -- return number of valid
|
||||
chips (which is number of ports/4) */
|
||||
static unsigned short __devinit cyy_init_card(void __iomem *true_base_addr,
|
||||
static unsigned short cyy_init_card(void __iomem *true_base_addr,
|
||||
int index)
|
||||
{
|
||||
unsigned int chip_number;
|
||||
@@ -3405,7 +3405,7 @@ static int __init cy_detect_isa(void)
|
||||
} /* cy_detect_isa */
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
static inline int __devinit cyc_isfwstr(const char *str, unsigned int size)
|
||||
static inline int cyc_isfwstr(const char *str, unsigned int size)
|
||||
{
|
||||
unsigned int a;
|
||||
|
||||
@@ -3420,7 +3420,7 @@ static inline int __devinit cyc_isfwstr(const char *str, unsigned int size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void __devinit cyz_fpga_copy(void __iomem *fpga, const u8 *data,
|
||||
static inline void cyz_fpga_copy(void __iomem *fpga, const u8 *data,
|
||||
unsigned int size)
|
||||
{
|
||||
for (; size > 0; size--) {
|
||||
@@ -3429,7 +3429,7 @@ static inline void __devinit cyz_fpga_copy(void __iomem *fpga, const u8 *data,
|
||||
}
|
||||
}
|
||||
|
||||
static void __devinit plx_init(struct pci_dev *pdev, int irq,
|
||||
static void plx_init(struct pci_dev *pdev, int irq,
|
||||
struct RUNTIME_9060 __iomem *addr)
|
||||
{
|
||||
/* Reset PLX */
|
||||
@@ -3449,7 +3449,7 @@ static void __devinit plx_init(struct pci_dev *pdev, int irq,
|
||||
pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, irq);
|
||||
}
|
||||
|
||||
static int __devinit __cyz_load_fw(const struct firmware *fw,
|
||||
static int __cyz_load_fw(const struct firmware *fw,
|
||||
const char *name, const u32 mailbox, void __iomem *base,
|
||||
void __iomem *fpga)
|
||||
{
|
||||
@@ -3526,7 +3526,7 @@ static int __devinit __cyz_load_fw(const struct firmware *fw,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr,
|
||||
static int cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr,
|
||||
struct RUNTIME_9060 __iomem *ctl_addr, int irq)
|
||||
{
|
||||
const struct firmware *fw;
|
||||
@@ -3692,7 +3692,7 @@ err:
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int __devinit cy_pci_probe(struct pci_dev *pdev,
|
||||
static int cy_pci_probe(struct pci_dev *pdev,
|
||||
const struct pci_device_id *ent)
|
||||
{
|
||||
struct cyclades_card *card;
|
||||
@@ -3931,10 +3931,10 @@ err:
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void __devexit cy_pci_remove(struct pci_dev *pdev)
|
||||
static void cy_pci_remove(struct pci_dev *pdev)
|
||||
{
|
||||
struct cyclades_card *cinfo = pci_get_drvdata(pdev);
|
||||
unsigned int i;
|
||||
unsigned int i, channel;
|
||||
|
||||
/* non-Z with old PLX */
|
||||
if (!cy_is_Z(cinfo) && (readb(cinfo->base_addr + CyPLX_VER) & 0x0f) ==
|
||||
@@ -3960,9 +3960,11 @@ static void __devexit cy_pci_remove(struct pci_dev *pdev)
|
||||
pci_release_regions(pdev);
|
||||
|
||||
cinfo->base_addr = NULL;
|
||||
for (i = cinfo->first_line; i < cinfo->first_line +
|
||||
cinfo->nports; i++)
|
||||
for (channel = 0, i = cinfo->first_line; i < cinfo->first_line +
|
||||
cinfo->nports; i++, channel++) {
|
||||
tty_unregister_device(cy_serial_driver, i);
|
||||
tty_port_destroy(&cinfo->ports[channel].port);
|
||||
}
|
||||
cinfo->nports = 0;
|
||||
kfree(cinfo->ports);
|
||||
}
|
||||
@@ -3971,7 +3973,7 @@ static struct pci_driver cy_pci_driver = {
|
||||
.name = "cyclades",
|
||||
.id_table = cy_pci_dev_id,
|
||||
.probe = cy_pci_probe,
|
||||
.remove = __devexit_p(cy_pci_remove)
|
||||
.remove = cy_pci_remove
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@@ -699,7 +699,7 @@ static const struct tty_port_operations ehv_bc_tty_port_ops = {
|
||||
.shutdown = ehv_bc_tty_port_shutdown,
|
||||
};
|
||||
|
||||
static int __devinit ehv_bc_tty_probe(struct platform_device *pdev)
|
||||
static int ehv_bc_tty_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct ehv_bc_data *bc;
|
||||
@@ -757,6 +757,7 @@ static int __devinit ehv_bc_tty_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
|
||||
error:
|
||||
tty_port_destroy(&bc->port);
|
||||
irq_dispose_mapping(bc->tx_irq);
|
||||
irq_dispose_mapping(bc->rx_irq);
|
||||
|
||||
@@ -770,6 +771,7 @@ static int ehv_bc_tty_remove(struct platform_device *pdev)
|
||||
|
||||
tty_unregister_device(ehv_bc_driver, bc - bcs);
|
||||
|
||||
tty_port_destroy(&bc->port);
|
||||
irq_dispose_mapping(bc->tx_irq);
|
||||
irq_dispose_mapping(bc->rx_irq);
|
||||
|
||||
|
@@ -41,7 +41,7 @@
|
||||
|
||||
static const char hvc_opal_name[] = "hvc_opal";
|
||||
|
||||
static struct of_device_id hvc_opal_match[] __devinitdata = {
|
||||
static struct of_device_id hvc_opal_match[] = {
|
||||
{ .name = "serial", .compatible = "ibm,opal-console-raw" },
|
||||
{ .name = "serial", .compatible = "ibm,opal-console-hvsi" },
|
||||
{ },
|
||||
@@ -161,7 +161,7 @@ static const struct hv_ops hvc_opal_hvsi_ops = {
|
||||
.tiocmset = hvc_opal_hvsi_tiocmset,
|
||||
};
|
||||
|
||||
static int __devinit hvc_opal_probe(struct platform_device *dev)
|
||||
static int hvc_opal_probe(struct platform_device *dev)
|
||||
{
|
||||
const struct hv_ops *ops;
|
||||
struct hvc_struct *hp;
|
||||
@@ -222,7 +222,7 @@ static int __devinit hvc_opal_probe(struct platform_device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit hvc_opal_remove(struct platform_device *dev)
|
||||
static int hvc_opal_remove(struct platform_device *dev)
|
||||
{
|
||||
struct hvc_struct *hp = dev_get_drvdata(&dev->dev);
|
||||
int rc, termno;
|
||||
@@ -239,7 +239,7 @@ static int __devexit hvc_opal_remove(struct platform_device *dev)
|
||||
|
||||
static struct platform_driver hvc_opal_driver = {
|
||||
.probe = hvc_opal_probe,
|
||||
.remove = __devexit_p(hvc_opal_remove),
|
||||
.remove = hvc_opal_remove,
|
||||
.driver = {
|
||||
.name = hvc_opal_name,
|
||||
.owner = THIS_MODULE,
|
||||
|
@@ -53,7 +53,7 @@
|
||||
|
||||
static const char hvc_driver_name[] = "hvc_console";
|
||||
|
||||
static struct vio_device_id hvc_driver_table[] __devinitdata = {
|
||||
static struct vio_device_id hvc_driver_table[] = {
|
||||
{"serial", "hvterm1"},
|
||||
#ifndef HVC_OLD_HVSI
|
||||
{"serial", "hvterm-protocol"},
|
||||
@@ -293,7 +293,7 @@ static int udbg_hvc_getc(void)
|
||||
}
|
||||
}
|
||||
|
||||
static int __devinit hvc_vio_probe(struct vio_dev *vdev,
|
||||
static int hvc_vio_probe(struct vio_dev *vdev,
|
||||
const struct vio_device_id *id)
|
||||
{
|
||||
const struct hv_ops *ops;
|
||||
@@ -362,7 +362,7 @@ static int __devinit hvc_vio_probe(struct vio_dev *vdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit hvc_vio_remove(struct vio_dev *vdev)
|
||||
static int hvc_vio_remove(struct vio_dev *vdev)
|
||||
{
|
||||
struct hvc_struct *hp = dev_get_drvdata(&vdev->dev);
|
||||
int rc, termno;
|
||||
|
@@ -422,7 +422,7 @@ static int xencons_connect_backend(struct xenbus_device *dev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devinit xencons_probe(struct xenbus_device *dev,
|
||||
static int xencons_probe(struct xenbus_device *dev,
|
||||
const struct xenbus_device_id *id)
|
||||
{
|
||||
int ret, devid;
|
||||
|
@@ -330,12 +330,12 @@ static int hvcs_open(struct tty_struct *tty, struct file *filp);
|
||||
static void hvcs_close(struct tty_struct *tty, struct file *filp);
|
||||
static void hvcs_hangup(struct tty_struct * tty);
|
||||
|
||||
static int __devinit hvcs_probe(struct vio_dev *dev,
|
||||
static int hvcs_probe(struct vio_dev *dev,
|
||||
const struct vio_device_id *id);
|
||||
static int __devexit hvcs_remove(struct vio_dev *dev);
|
||||
static int hvcs_remove(struct vio_dev *dev);
|
||||
static int __init hvcs_module_init(void);
|
||||
static void __exit hvcs_module_exit(void);
|
||||
static int __devinit hvcs_initialize(void);
|
||||
static int hvcs_initialize(void);
|
||||
|
||||
#define HVCS_SCHED_READ 0x00000001
|
||||
#define HVCS_QUICK_READ 0x00000002
|
||||
@@ -676,7 +676,7 @@ static int khvcsd(void *unused)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct vio_device_id hvcs_driver_table[] __devinitdata= {
|
||||
static struct vio_device_id hvcs_driver_table[] = {
|
||||
{"serial-server", "hvterm2"},
|
||||
{ "", "" }
|
||||
};
|
||||
@@ -756,7 +756,7 @@ static int hvcs_get_index(void)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int __devinit hvcs_probe(
|
||||
static int hvcs_probe(
|
||||
struct vio_dev *dev,
|
||||
const struct vio_device_id *id)
|
||||
{
|
||||
@@ -835,7 +835,7 @@ static int __devinit hvcs_probe(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit hvcs_remove(struct vio_dev *dev)
|
||||
static int hvcs_remove(struct vio_dev *dev)
|
||||
{
|
||||
struct hvcs_struct *hvcsd = dev_get_drvdata(&dev->dev);
|
||||
unsigned long flags;
|
||||
@@ -874,7 +874,7 @@ static int __devexit hvcs_remove(struct vio_dev *dev)
|
||||
static struct vio_driver hvcs_vio_driver = {
|
||||
.id_table = hvcs_driver_table,
|
||||
.probe = hvcs_probe,
|
||||
.remove = __devexit_p(hvcs_remove),
|
||||
.remove = hvcs_remove,
|
||||
.name = hvcs_driver_name,
|
||||
};
|
||||
|
||||
@@ -1478,7 +1478,7 @@ static void hvcs_free_index_list(void)
|
||||
hvcs_index_count = 0;
|
||||
}
|
||||
|
||||
static int __devinit hvcs_initialize(void)
|
||||
static int hvcs_initialize(void)
|
||||
{
|
||||
int rc, num_ttys_to_alloc;
|
||||
|
||||
@@ -1496,8 +1496,10 @@ static int __devinit hvcs_initialize(void)
|
||||
num_ttys_to_alloc = hvcs_parm_num_devs;
|
||||
|
||||
hvcs_tty_driver = alloc_tty_driver(num_ttys_to_alloc);
|
||||
if (!hvcs_tty_driver)
|
||||
if (!hvcs_tty_driver) {
|
||||
mutex_unlock(&hvcs_init_mutex);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (hvcs_alloc_index_list(num_ttys_to_alloc)) {
|
||||
rc = -ENOMEM;
|
||||
|
@@ -1218,6 +1218,7 @@ static int __init hvsi_console_init(void)
|
||||
if (hp->virq == 0) {
|
||||
printk(KERN_ERR "%s: couldn't create irq mapping for 0x%x\n",
|
||||
__func__, irq[0]);
|
||||
tty_port_destroy(&hp->port);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@@ -352,6 +352,8 @@ static struct sk_buff *ipw_packet_received_skb(unsigned char *data,
|
||||
}
|
||||
|
||||
skb = dev_alloc_skb(length + 4);
|
||||
if (skb == NULL)
|
||||
return NULL;
|
||||
skb_reserve(skb, 2);
|
||||
memcpy(skb_put(skb, length), data, length);
|
||||
|
||||
@@ -397,7 +399,8 @@ void ipwireless_network_packet_received(struct ipw_network *network,
|
||||
|
||||
/* Send the data to the ppp_generic module. */
|
||||
skb = ipw_packet_received_skb(data, length);
|
||||
ppp_input(network->ppp_channel, skb);
|
||||
if (skb)
|
||||
ppp_input(network->ppp_channel, skb);
|
||||
} else
|
||||
spin_unlock_irqrestore(&network->lock,
|
||||
flags);
|
||||
|
@@ -566,6 +566,7 @@ void ipwireless_tty_free(struct ipw_tty *tty)
|
||||
ipwireless_disassociate_network_ttys(network,
|
||||
ttyj->channel_idx);
|
||||
tty_unregister_device(ipw_tty_driver, j);
|
||||
tty_port_destroy(&ttyj->port);
|
||||
ttys[j] = NULL;
|
||||
mutex_unlock(&ttyj->ipw_tty_mutex);
|
||||
kfree(ttyj);
|
||||
|
@@ -148,7 +148,7 @@
|
||||
#endif
|
||||
|
||||
static int isicom_probe(struct pci_dev *, const struct pci_device_id *);
|
||||
static void __devexit isicom_remove(struct pci_dev *);
|
||||
static void isicom_remove(struct pci_dev *);
|
||||
|
||||
static struct pci_device_id isicom_pci_tbl[] = {
|
||||
{ PCI_DEVICE(VENDOR_ID, 0x2028) },
|
||||
@@ -168,7 +168,7 @@ static struct pci_driver isicom_driver = {
|
||||
.name = "isicom",
|
||||
.id_table = isicom_pci_tbl,
|
||||
.probe = isicom_probe,
|
||||
.remove = __devexit_p(isicom_remove)
|
||||
.remove = isicom_remove
|
||||
};
|
||||
|
||||
static int prev_card = 3; /* start servicing isi_card[0] */
|
||||
@@ -603,7 +603,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id)
|
||||
if (tty_port_cts_enabled(&port->port)) {
|
||||
if (tty->hw_stopped) {
|
||||
if (header & ISI_CTS) {
|
||||
port->port.tty->hw_stopped = 0;
|
||||
tty->hw_stopped = 0;
|
||||
/* start tx ing */
|
||||
port->status |= (ISI_TXOK
|
||||
| ISI_CTS);
|
||||
@@ -1307,7 +1307,7 @@ static const struct tty_port_operations isicom_port_ops = {
|
||||
.shutdown = isicom_shutdown,
|
||||
};
|
||||
|
||||
static int __devinit reset_card(struct pci_dev *pdev,
|
||||
static int reset_card(struct pci_dev *pdev,
|
||||
const unsigned int card, unsigned int *signature)
|
||||
{
|
||||
struct isi_board *board = pci_get_drvdata(pdev);
|
||||
@@ -1368,7 +1368,7 @@ end:
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int __devinit load_firmware(struct pci_dev *pdev,
|
||||
static int load_firmware(struct pci_dev *pdev,
|
||||
const unsigned int index, const unsigned int signature)
|
||||
{
|
||||
struct isi_board *board = pci_get_drvdata(pdev);
|
||||
@@ -1548,7 +1548,7 @@ end:
|
||||
*/
|
||||
static unsigned int card_count;
|
||||
|
||||
static int __devinit isicom_probe(struct pci_dev *pdev,
|
||||
static int isicom_probe(struct pci_dev *pdev,
|
||||
const struct pci_device_id *ent)
|
||||
{
|
||||
unsigned int uninitialized_var(signature), index;
|
||||
@@ -1610,10 +1610,15 @@ static int __devinit isicom_probe(struct pci_dev *pdev,
|
||||
if (retval < 0)
|
||||
goto errunri;
|
||||
|
||||
for (index = 0; index < board->port_count; index++)
|
||||
tty_port_register_device(&board->ports[index].port,
|
||||
isicom_normal, board->index * 16 + index,
|
||||
&pdev->dev);
|
||||
for (index = 0; index < board->port_count; index++) {
|
||||
struct tty_port *tport = &board->ports[index].port;
|
||||
tty_port_init(tport);
|
||||
tport->ops = &isicom_port_ops;
|
||||
tport->close_delay = 50 * HZ/100;
|
||||
tport->closing_wait = 3000 * HZ/100;
|
||||
tty_port_register_device(tport, isicom_normal,
|
||||
board->index * 16 + index, &pdev->dev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -1630,13 +1635,15 @@ err:
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void __devexit isicom_remove(struct pci_dev *pdev)
|
||||
static void isicom_remove(struct pci_dev *pdev)
|
||||
{
|
||||
struct isi_board *board = pci_get_drvdata(pdev);
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < board->port_count; i++)
|
||||
for (i = 0; i < board->port_count; i++) {
|
||||
tty_unregister_device(isicom_normal, board->index * 16 + i);
|
||||
tty_port_destroy(&board->ports[i].port);
|
||||
}
|
||||
|
||||
free_irq(board->irq, board);
|
||||
pci_release_region(pdev, 3);
|
||||
@@ -1655,13 +1662,9 @@ static int __init isicom_init(void)
|
||||
isi_card[idx].ports = port;
|
||||
spin_lock_init(&isi_card[idx].card_lock);
|
||||
for (channel = 0; channel < 16; channel++, port++) {
|
||||
tty_port_init(&port->port);
|
||||
port->port.ops = &isicom_port_ops;
|
||||
port->magic = ISICOM_MAGIC;
|
||||
port->card = &isi_card[idx];
|
||||
port->channel = channel;
|
||||
port->port.close_delay = 50 * HZ/100;
|
||||
port->port.closing_wait = 3000 * HZ/100;
|
||||
port->status = 0;
|
||||
/* . . . */
|
||||
}
|
||||
|
@@ -895,6 +895,8 @@ static int moxa_init_board(struct moxa_board_conf *brd, struct device *dev)
|
||||
|
||||
return 0;
|
||||
err_free:
|
||||
for (i = 0; i < MAX_PORTS_PER_BOARD; i++)
|
||||
tty_port_destroy(&brd->ports[i].port);
|
||||
kfree(brd->ports);
|
||||
err:
|
||||
return ret;
|
||||
@@ -919,6 +921,8 @@ static void moxa_board_deinit(struct moxa_board_conf *brd)
|
||||
tty_kref_put(tty);
|
||||
}
|
||||
}
|
||||
for (a = 0; a < MAX_PORTS_PER_BOARD; a++)
|
||||
tty_port_destroy(&brd->ports[a].port);
|
||||
while (1) {
|
||||
opened = 0;
|
||||
for (a = 0; a < brd->numPorts; a++)
|
||||
@@ -941,7 +945,7 @@ static void moxa_board_deinit(struct moxa_board_conf *brd)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
static int __devinit moxa_pci_probe(struct pci_dev *pdev,
|
||||
static int moxa_pci_probe(struct pci_dev *pdev,
|
||||
const struct pci_device_id *ent)
|
||||
{
|
||||
struct moxa_board_conf *board;
|
||||
@@ -1016,7 +1020,7 @@ err:
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void __devexit moxa_pci_remove(struct pci_dev *pdev)
|
||||
static void moxa_pci_remove(struct pci_dev *pdev)
|
||||
{
|
||||
struct moxa_board_conf *brd = pci_get_drvdata(pdev);
|
||||
|
||||
@@ -1029,7 +1033,7 @@ static struct pci_driver moxa_pci_driver = {
|
||||
.name = "moxa",
|
||||
.id_table = moxa_pcibrds,
|
||||
.probe = moxa_pci_probe,
|
||||
.remove = __devexit_p(moxa_pci_remove)
|
||||
.remove = moxa_pci_remove
|
||||
};
|
||||
#endif /* CONFIG_PCI */
|
||||
|
||||
@@ -1370,7 +1374,7 @@ static void moxa_new_dcdstate(struct moxa_port *p, u8 dcd)
|
||||
p->DCDState = dcd;
|
||||
spin_unlock_irqrestore(&p->port.lock, flags);
|
||||
tty = tty_port_tty_get(&p->port);
|
||||
if (tty && C_CLOCAL(tty) && !dcd)
|
||||
if (tty && !C_CLOCAL(tty) && !dcd)
|
||||
tty_hangup(tty);
|
||||
tty_kref_put(tty);
|
||||
}
|
||||
|
@@ -487,7 +487,7 @@ static void mxser_disable_must_rx_software_flow_control(unsigned long baseio)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
static int __devinit CheckIsMoxaMust(unsigned long io)
|
||||
static int CheckIsMoxaMust(unsigned long io)
|
||||
{
|
||||
u8 oldmcr, hwid;
|
||||
int i;
|
||||
@@ -2369,7 +2369,7 @@ static void mxser_release_ISA_res(struct mxser_board *brd)
|
||||
mxser_release_vector(brd);
|
||||
}
|
||||
|
||||
static int __devinit mxser_initbrd(struct mxser_board *brd,
|
||||
static int mxser_initbrd(struct mxser_board *brd,
|
||||
struct pci_dev *pdev)
|
||||
{
|
||||
struct mxser_port *info;
|
||||
@@ -2411,14 +2411,27 @@ static int __devinit mxser_initbrd(struct mxser_board *brd,
|
||||
|
||||
retval = request_irq(brd->irq, mxser_interrupt, IRQF_SHARED, "mxser",
|
||||
brd);
|
||||
if (retval)
|
||||
if (retval) {
|
||||
for (i = 0; i < brd->info->nports; i++)
|
||||
tty_port_destroy(&brd->ports[i].port);
|
||||
printk(KERN_ERR "Board %s: Request irq failed, IRQ (%d) may "
|
||||
"conflict with another device.\n",
|
||||
brd->info->name, brd->irq);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void mxser_board_remove(struct mxser_board *brd)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < brd->info->nports; i++) {
|
||||
tty_unregister_device(mxvar_sdriver, brd->idx + i);
|
||||
tty_port_destroy(&brd->ports[i].port);
|
||||
}
|
||||
}
|
||||
|
||||
static int __init mxser_get_ISA_conf(int cap, struct mxser_board *brd)
|
||||
{
|
||||
int id, i, bits, ret;
|
||||
@@ -2534,7 +2547,7 @@ err_irqconflict:
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static int __devinit mxser_probe(struct pci_dev *pdev,
|
||||
static int mxser_probe(struct pci_dev *pdev,
|
||||
const struct pci_device_id *ent)
|
||||
{
|
||||
#ifdef CONFIG_PCI
|
||||
@@ -2645,14 +2658,12 @@ err:
|
||||
#endif
|
||||
}
|
||||
|
||||
static void __devexit mxser_remove(struct pci_dev *pdev)
|
||||
static void mxser_remove(struct pci_dev *pdev)
|
||||
{
|
||||
#ifdef CONFIG_PCI
|
||||
struct mxser_board *brd = pci_get_drvdata(pdev);
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < brd->info->nports; i++)
|
||||
tty_unregister_device(mxvar_sdriver, brd->idx + i);
|
||||
mxser_board_remove(brd);
|
||||
|
||||
free_irq(pdev->irq, brd);
|
||||
pci_release_region(pdev, 2);
|
||||
@@ -2666,7 +2677,7 @@ static struct pci_driver mxser_driver = {
|
||||
.name = "mxser",
|
||||
.id_table = mxser_pcibrds,
|
||||
.probe = mxser_probe,
|
||||
.remove = __devexit_p(mxser_remove)
|
||||
.remove = mxser_remove
|
||||
};
|
||||
|
||||
static int __init mxser_module_init(void)
|
||||
@@ -2748,15 +2759,13 @@ err_put:
|
||||
|
||||
static void __exit mxser_module_exit(void)
|
||||
{
|
||||
unsigned int i, j;
|
||||
unsigned int i;
|
||||
|
||||
pci_unregister_driver(&mxser_driver);
|
||||
|
||||
for (i = 0; i < MXSER_BOARDS; i++) /* ISA remains */
|
||||
if (mxser_boards[i].info != NULL)
|
||||
for (j = 0; j < mxser_boards[i].info->nports; j++)
|
||||
tty_unregister_device(mxvar_sdriver,
|
||||
mxser_boards[i].idx + j);
|
||||
mxser_board_remove(&mxser_boards[i]);
|
||||
tty_unregister_driver(mxvar_sdriver);
|
||||
put_tty_driver(mxvar_sdriver);
|
||||
|
||||
|
@@ -134,7 +134,6 @@ struct gsm_dlci {
|
||||
#define DLCI_OPENING 1 /* Sending SABM not seen UA */
|
||||
#define DLCI_OPEN 2 /* SABM/UA complete */
|
||||
#define DLCI_CLOSING 3 /* Sending DISC not seen UA/DM */
|
||||
struct kref ref; /* freed from port or mux close */
|
||||
struct mutex mutex;
|
||||
|
||||
/* Link layer */
|
||||
@@ -1635,7 +1634,6 @@ static struct gsm_dlci *gsm_dlci_alloc(struct gsm_mux *gsm, int addr)
|
||||
if (dlci == NULL)
|
||||
return NULL;
|
||||
spin_lock_init(&dlci->lock);
|
||||
kref_init(&dlci->ref);
|
||||
mutex_init(&dlci->mutex);
|
||||
dlci->fifo = &dlci->_fifo;
|
||||
if (kfifo_alloc(&dlci->_fifo, 4096, GFP_KERNEL) < 0) {
|
||||
@@ -1669,9 +1667,9 @@ static struct gsm_dlci *gsm_dlci_alloc(struct gsm_mux *gsm, int addr)
|
||||
*
|
||||
* Can sleep.
|
||||
*/
|
||||
static void gsm_dlci_free(struct kref *ref)
|
||||
static void gsm_dlci_free(struct tty_port *port)
|
||||
{
|
||||
struct gsm_dlci *dlci = container_of(ref, struct gsm_dlci, ref);
|
||||
struct gsm_dlci *dlci = container_of(port, struct gsm_dlci, port);
|
||||
|
||||
del_timer_sync(&dlci->t1);
|
||||
dlci->gsm->dlci[dlci->addr] = NULL;
|
||||
@@ -1683,12 +1681,12 @@ static void gsm_dlci_free(struct kref *ref)
|
||||
|
||||
static inline void dlci_get(struct gsm_dlci *dlci)
|
||||
{
|
||||
kref_get(&dlci->ref);
|
||||
tty_port_get(&dlci->port);
|
||||
}
|
||||
|
||||
static inline void dlci_put(struct gsm_dlci *dlci)
|
||||
{
|
||||
kref_put(&dlci->ref, gsm_dlci_free);
|
||||
tty_port_put(&dlci->port);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2874,6 +2872,7 @@ static void gsm_dtr_rts(struct tty_port *port, int onoff)
|
||||
static const struct tty_port_operations gsm_port_ops = {
|
||||
.carrier_raised = gsm_carrier_raised,
|
||||
.dtr_rts = gsm_dtr_rts,
|
||||
.destruct = gsm_dlci_free,
|
||||
};
|
||||
|
||||
static int gsmtty_install(struct tty_driver *driver, struct tty_struct *tty)
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -400,7 +400,7 @@ struct buffer {
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Global variables */
|
||||
static const struct pci_device_id nozomi_pci_tbl[] __devinitconst = {
|
||||
static const struct pci_device_id nozomi_pci_tbl[] = {
|
||||
{PCI_DEVICE(0x1931, 0x000c)}, /* Nozomi HSDPA */
|
||||
{},
|
||||
};
|
||||
@@ -1360,7 +1360,7 @@ static void remove_sysfs_files(struct nozomi *dc)
|
||||
}
|
||||
|
||||
/* Allocate memory for one device */
|
||||
static int __devinit nozomi_card_init(struct pci_dev *pdev,
|
||||
static int nozomi_card_init(struct pci_dev *pdev,
|
||||
const struct pci_device_id *ent)
|
||||
{
|
||||
resource_size_t start;
|
||||
@@ -1479,6 +1479,7 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev,
|
||||
if (IS_ERR(tty_dev)) {
|
||||
ret = PTR_ERR(tty_dev);
|
||||
dev_err(&pdev->dev, "Could not allocate tty?\n");
|
||||
tty_port_destroy(&port->port);
|
||||
goto err_free_tty;
|
||||
}
|
||||
}
|
||||
@@ -1486,8 +1487,10 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev,
|
||||
return 0;
|
||||
|
||||
err_free_tty:
|
||||
for (i = dc->index_start; i < dc->index_start + MAX_PORT; ++i)
|
||||
tty_unregister_device(ntty_driver, i);
|
||||
for (i = 0; i < MAX_PORT; ++i) {
|
||||
tty_unregister_device(ntty_driver, dc->index_start + i);
|
||||
tty_port_destroy(&dc->port[i].port);
|
||||
}
|
||||
err_free_kfifo:
|
||||
for (i = 0; i < MAX_PORT; i++)
|
||||
kfifo_free(&dc->port[i].fifo_ul);
|
||||
@@ -1504,7 +1507,7 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __devexit tty_exit(struct nozomi *dc)
|
||||
static void tty_exit(struct nozomi *dc)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
@@ -1520,12 +1523,14 @@ static void __devexit tty_exit(struct nozomi *dc)
|
||||
complete off a hangup method ? */
|
||||
while (dc->open_ttys)
|
||||
msleep(1);
|
||||
for (i = dc->index_start; i < dc->index_start + MAX_PORT; ++i)
|
||||
tty_unregister_device(ntty_driver, i);
|
||||
for (i = 0; i < MAX_PORT; ++i) {
|
||||
tty_unregister_device(ntty_driver, dc->index_start + i);
|
||||
tty_port_destroy(&dc->port[i].port);
|
||||
}
|
||||
}
|
||||
|
||||
/* Deallocate memory for one device */
|
||||
static void __devexit nozomi_card_exit(struct pci_dev *pdev)
|
||||
static void nozomi_card_exit(struct pci_dev *pdev)
|
||||
{
|
||||
int i;
|
||||
struct ctrl_ul ctrl;
|
||||
@@ -1903,7 +1908,7 @@ static struct pci_driver nozomi_driver = {
|
||||
.name = NOZOMI_NAME,
|
||||
.id_table = nozomi_pci_tbl,
|
||||
.probe = nozomi_card_init,
|
||||
.remove = __devexit_p(nozomi_card_exit),
|
||||
.remove = nozomi_card_exit,
|
||||
};
|
||||
|
||||
static __init int nozomi_init(void)
|
||||
|
@@ -4,9 +4,6 @@
|
||||
* Added support for a Unix98-style ptmx device.
|
||||
* -- C. Scott Ananian <cananian@alumni.princeton.edu>, 14-Jan-1998
|
||||
*
|
||||
* When reading this code see also fs/devpts. In particular note that the
|
||||
* driver_data field is used by the devpts side as a binding to the devpts
|
||||
* inode.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
@@ -59,7 +56,7 @@ static void pty_close(struct tty_struct *tty, struct file *filp)
|
||||
#ifdef CONFIG_UNIX98_PTYS
|
||||
if (tty->driver == ptm_driver) {
|
||||
mutex_lock(&devpts_mutex);
|
||||
devpts_pty_kill(tty->link);
|
||||
devpts_pty_kill(tty->link->driver_data);
|
||||
mutex_unlock(&devpts_mutex);
|
||||
}
|
||||
#endif
|
||||
@@ -96,7 +93,7 @@ static void pty_unthrottle(struct tty_struct *tty)
|
||||
|
||||
static int pty_space(struct tty_struct *to)
|
||||
{
|
||||
int n = 8192 - to->buf.memory_used;
|
||||
int n = 8192 - to->port->buf.memory_used;
|
||||
if (n < 0)
|
||||
return 0;
|
||||
return n;
|
||||
@@ -174,6 +171,41 @@ static int pty_set_lock(struct tty_struct *tty, int __user *arg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pty_get_lock(struct tty_struct *tty, int __user *arg)
|
||||
{
|
||||
int locked = test_bit(TTY_PTY_LOCK, &tty->flags);
|
||||
return put_user(locked, arg);
|
||||
}
|
||||
|
||||
/* Set the packet mode on a pty */
|
||||
static int pty_set_pktmode(struct tty_struct *tty, int __user *arg)
|
||||
{
|
||||
unsigned long flags;
|
||||
int pktmode;
|
||||
|
||||
if (get_user(pktmode, arg))
|
||||
return -EFAULT;
|
||||
|
||||
spin_lock_irqsave(&tty->ctrl_lock, flags);
|
||||
if (pktmode) {
|
||||
if (!tty->packet) {
|
||||
tty->packet = 1;
|
||||
tty->link->ctrl_status = 0;
|
||||
}
|
||||
} else
|
||||
tty->packet = 0;
|
||||
spin_unlock_irqrestore(&tty->ctrl_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get the packet mode of a pty */
|
||||
static int pty_get_pktmode(struct tty_struct *tty, int __user *arg)
|
||||
{
|
||||
int pktmode = tty->packet;
|
||||
return put_user(pktmode, arg);
|
||||
}
|
||||
|
||||
/* Send a signal to the slave */
|
||||
static int pty_signal(struct tty_struct *tty, int sig)
|
||||
{
|
||||
@@ -245,7 +277,7 @@ static void pty_set_termios(struct tty_struct *tty,
|
||||
* peform a terminal resize correctly
|
||||
*/
|
||||
|
||||
int pty_resize(struct tty_struct *tty, struct winsize *ws)
|
||||
static int pty_resize(struct tty_struct *tty, struct winsize *ws)
|
||||
{
|
||||
struct pid *pgrp, *rpgrp;
|
||||
unsigned long flags;
|
||||
@@ -348,6 +380,7 @@ static int pty_common_install(struct tty_driver *driver, struct tty_struct *tty,
|
||||
tty_port_init(ports[1]);
|
||||
o_tty->port = ports[0];
|
||||
tty->port = ports[1];
|
||||
o_tty->port->itty = o_tty;
|
||||
|
||||
tty_driver_kref_get(driver);
|
||||
tty->count++;
|
||||
@@ -366,9 +399,16 @@ err:
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* this is called once with whichever end is closed last */
|
||||
static void pty_unix98_shutdown(struct tty_struct *tty)
|
||||
{
|
||||
devpts_kill_index(tty->driver_data, tty->index);
|
||||
}
|
||||
|
||||
static void pty_cleanup(struct tty_struct *tty)
|
||||
{
|
||||
kfree(tty->port);
|
||||
tty->port->itty = NULL;
|
||||
tty_port_put(tty->port);
|
||||
}
|
||||
|
||||
/* Traditional BSD devices */
|
||||
@@ -393,6 +433,12 @@ static int pty_bsd_ioctl(struct tty_struct *tty,
|
||||
switch (cmd) {
|
||||
case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */
|
||||
return pty_set_lock(tty, (int __user *) arg);
|
||||
case TIOCGPTLCK: /* Get PT Lock status */
|
||||
return pty_get_lock(tty, (int __user *)arg);
|
||||
case TIOCPKT: /* Set PT packet mode */
|
||||
return pty_set_pktmode(tty, (int __user *)arg);
|
||||
case TIOCGPKT: /* Get PT packet mode */
|
||||
return pty_get_pktmode(tty, (int __user *)arg);
|
||||
case TIOCSIG: /* Send signal to other side of pty */
|
||||
return pty_signal(tty, (int) arg);
|
||||
}
|
||||
@@ -507,6 +553,12 @@ static int pty_unix98_ioctl(struct tty_struct *tty,
|
||||
switch (cmd) {
|
||||
case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */
|
||||
return pty_set_lock(tty, (int __user *)arg);
|
||||
case TIOCGPTLCK: /* Get PT Lock status */
|
||||
return pty_get_lock(tty, (int __user *)arg);
|
||||
case TIOCPKT: /* Set PT packet mode */
|
||||
return pty_set_pktmode(tty, (int __user *)arg);
|
||||
case TIOCGPKT: /* Get PT packet mode */
|
||||
return pty_get_pktmode(tty, (int __user *)arg);
|
||||
case TIOCGPTN: /* Get PT Number */
|
||||
return put_user(tty->index, (unsigned int __user *)arg);
|
||||
case TIOCSIG: /* Send signal to other side of pty */
|
||||
@@ -547,7 +599,7 @@ static struct tty_struct *pts_unix98_lookup(struct tty_driver *driver,
|
||||
struct tty_struct *tty;
|
||||
|
||||
mutex_lock(&devpts_mutex);
|
||||
tty = devpts_get_tty(pts_inode, idx);
|
||||
tty = devpts_get_priv(pts_inode);
|
||||
mutex_unlock(&devpts_mutex);
|
||||
/* Master must be open before slave */
|
||||
if (!tty)
|
||||
@@ -581,6 +633,7 @@ static const struct tty_operations ptm_unix98_ops = {
|
||||
.set_termios = pty_set_termios,
|
||||
.ioctl = pty_unix98_ioctl,
|
||||
.resize = pty_resize,
|
||||
.shutdown = pty_unix98_shutdown,
|
||||
.cleanup = pty_cleanup
|
||||
};
|
||||
|
||||
@@ -596,6 +649,7 @@ static const struct tty_operations pty_unix98_ops = {
|
||||
.chars_in_buffer = pty_chars_in_buffer,
|
||||
.unthrottle = pty_unthrottle,
|
||||
.set_termios = pty_set_termios,
|
||||
.shutdown = pty_unix98_shutdown,
|
||||
.cleanup = pty_cleanup,
|
||||
};
|
||||
|
||||
@@ -614,6 +668,7 @@ static const struct tty_operations pty_unix98_ops = {
|
||||
static int ptmx_open(struct inode *inode, struct file *filp)
|
||||
{
|
||||
struct tty_struct *tty;
|
||||
struct inode *slave_inode;
|
||||
int retval;
|
||||
int index;
|
||||
|
||||
@@ -650,15 +705,21 @@ static int ptmx_open(struct inode *inode, struct file *filp)
|
||||
|
||||
tty_add_file(tty, filp);
|
||||
|
||||
retval = devpts_pty_new(inode, tty->link);
|
||||
if (retval)
|
||||
slave_inode = devpts_pty_new(inode,
|
||||
MKDEV(UNIX98_PTY_SLAVE_MAJOR, index), index,
|
||||
tty->link);
|
||||
if (IS_ERR(slave_inode)) {
|
||||
retval = PTR_ERR(slave_inode);
|
||||
goto err_release;
|
||||
}
|
||||
|
||||
retval = ptm_driver->ops->open(tty, filp);
|
||||
if (retval)
|
||||
goto err_release;
|
||||
|
||||
tty_unlock(tty);
|
||||
tty->driver_data = inode;
|
||||
tty->link->driver_data = slave_inode;
|
||||
return 0;
|
||||
err_release:
|
||||
tty_unlock(tty);
|
||||
|
@@ -673,6 +673,7 @@ static void init_r_port(int board, int aiop, int chan, struct pci_dev *pci_dev)
|
||||
if (sInitChan(ctlp, &info->channel, aiop, chan) == 0) {
|
||||
printk(KERN_ERR "RocketPort sInitChan(%d, %d, %d) failed!\n",
|
||||
board, aiop, chan);
|
||||
tty_port_destroy(&info->port);
|
||||
kfree(info);
|
||||
return;
|
||||
}
|
||||
@@ -1757,7 +1758,7 @@ static void rp_flush_buffer(struct tty_struct *tty)
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
|
||||
static struct pci_device_id __devinitdata __used rocket_pci_ids[] = {
|
||||
static struct pci_device_id __used rocket_pci_ids[] = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_ANY_ID) },
|
||||
{ }
|
||||
};
|
||||
@@ -2357,6 +2358,7 @@ static void rp_cleanup_module(void)
|
||||
for (i = 0; i < MAX_RP_PORTS; i++)
|
||||
if (rp_table[i]) {
|
||||
tty_unregister_device(rocket_driver, i);
|
||||
tty_port_destroy(&rp_table[i]->port);
|
||||
kfree(rp_table[i]);
|
||||
}
|
||||
|
||||
|
@@ -1225,6 +1225,8 @@ rs68328_init(void)
|
||||
|
||||
if (tty_register_driver(serial_driver)) {
|
||||
put_tty_driver(serial_driver);
|
||||
for (i = 0; i < NR_PORTS; i++)
|
||||
tty_port_destroy(&m68k_soft[i].tport);
|
||||
printk(KERN_ERR "Couldn't register serial driver\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
@@ -280,7 +280,17 @@ static const struct serial8250_config uart_config[] = {
|
||||
.fifo_size = 64,
|
||||
.tx_loadsz = 64,
|
||||
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
|
||||
.flags = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR,
|
||||
.flags = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR |
|
||||
UART_CAP_SLEEP,
|
||||
},
|
||||
[PORT_XR17V35X] = {
|
||||
.name = "XR17V35X",
|
||||
.fifo_size = 256,
|
||||
.tx_loadsz = 256,
|
||||
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_11 |
|
||||
UART_FCR_T_TRIG_11,
|
||||
.flags = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR |
|
||||
UART_CAP_SLEEP,
|
||||
},
|
||||
[PORT_LPC3220] = {
|
||||
.name = "LPC3220",
|
||||
@@ -455,6 +465,7 @@ static void io_serial_out(struct uart_port *p, int offset, int value)
|
||||
}
|
||||
|
||||
static int serial8250_default_handle_irq(struct uart_port *port);
|
||||
static int exar_handle_irq(struct uart_port *port);
|
||||
|
||||
static void set_io_from_upio(struct uart_port *p)
|
||||
{
|
||||
@@ -574,6 +585,19 @@ EXPORT_SYMBOL_GPL(serial8250_clear_and_reinit_fifos);
|
||||
*/
|
||||
static void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
|
||||
{
|
||||
/*
|
||||
* Exar UARTs have a SLEEP register that enables or disables
|
||||
* each UART to enter sleep mode separately. On the XR17V35x the
|
||||
* register is accessible to each UART at the UART_EXAR_SLEEP
|
||||
* offset but the UART channel may only write to the corresponding
|
||||
* bit.
|
||||
*/
|
||||
if ((p->port.type == PORT_XR17V35X) ||
|
||||
(p->port.type == PORT_XR17D15X)) {
|
||||
serial_out(p, UART_EXAR_SLEEP, 0xff);
|
||||
return;
|
||||
}
|
||||
|
||||
if (p->capabilities & UART_CAP_SLEEP) {
|
||||
if (p->capabilities & UART_CAP_EFR) {
|
||||
serial_out(p, UART_LCR, UART_LCR_CONF_MODE_B);
|
||||
@@ -881,6 +905,27 @@ static void autoconfig_16550a(struct uart_8250_port *up)
|
||||
up->port.type = PORT_16550A;
|
||||
up->capabilities |= UART_CAP_FIFO;
|
||||
|
||||
/*
|
||||
* XR17V35x UARTs have an extra divisor register, DLD
|
||||
* that gets enabled with when DLAB is set which will
|
||||
* cause the device to incorrectly match and assign
|
||||
* port type to PORT_16650. The EFR for this UART is
|
||||
* found at offset 0x09. Instead check the Deice ID (DVID)
|
||||
* register for a 2, 4 or 8 port UART.
|
||||
*/
|
||||
if (up->port.flags & UPF_EXAR_EFR) {
|
||||
status1 = serial_in(up, UART_EXAR_DVID);
|
||||
if (status1 == 0x82 || status1 == 0x84 || status1 == 0x88) {
|
||||
DEBUG_AUTOCONF("Exar XR17V35x ");
|
||||
up->port.type = PORT_XR17V35X;
|
||||
up->capabilities |= UART_CAP_AFE | UART_CAP_EFR |
|
||||
UART_CAP_SLEEP;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for presence of the EFR when DLAB is set.
|
||||
* Only ST16C650V1 UARTs pass this test.
|
||||
@@ -1013,8 +1058,12 @@ static void autoconfig_16550a(struct uart_8250_port *up)
|
||||
* Exar uarts have EFR in a weird location
|
||||
*/
|
||||
if (up->port.flags & UPF_EXAR_EFR) {
|
||||
DEBUG_AUTOCONF("Exar XR17D15x ");
|
||||
up->port.type = PORT_XR17D15X;
|
||||
up->capabilities |= UART_CAP_AFE | UART_CAP_EFR;
|
||||
up->capabilities |= UART_CAP_AFE | UART_CAP_EFR |
|
||||
UART_CAP_SLEEP;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1515,6 +1564,31 @@ static int serial8250_default_handle_irq(struct uart_port *port)
|
||||
return serial8250_handle_irq(port, iir);
|
||||
}
|
||||
|
||||
/*
|
||||
* These Exar UARTs have an extra interrupt indicator that could
|
||||
* fire for a few unimplemented interrupts. One of which is a
|
||||
* wakeup event when coming out of sleep. Put this here just
|
||||
* to be on the safe side that these interrupts don't go unhandled.
|
||||
*/
|
||||
static int exar_handle_irq(struct uart_port *port)
|
||||
{
|
||||
unsigned char int0, int1, int2, int3;
|
||||
unsigned int iir = serial_port_in(port, UART_IIR);
|
||||
int ret;
|
||||
|
||||
ret = serial8250_handle_irq(port, iir);
|
||||
|
||||
if ((port->type == PORT_XR17V35X) ||
|
||||
(port->type == PORT_XR17D15X)) {
|
||||
int0 = serial_port_in(port, 0x80);
|
||||
int1 = serial_port_in(port, 0x81);
|
||||
int2 = serial_port_in(port, 0x82);
|
||||
int3 = serial_port_in(port, 0x83);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the serial driver's interrupt routine.
|
||||
*
|
||||
@@ -2349,16 +2423,14 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||
serial_port_out(port, UART_EFR, efr);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARCH_OMAP1
|
||||
/* Workaround to enable 115200 baud on OMAP1510 internal ports */
|
||||
if (cpu_is_omap1510() && is_omap_port(up)) {
|
||||
if (is_omap1510_8250(up)) {
|
||||
if (baud == 115200) {
|
||||
quot = 1;
|
||||
serial_port_out(port, UART_OMAP_OSC_12M_SEL, 1);
|
||||
} else
|
||||
serial_port_out(port, UART_OMAP_OSC_12M_SEL, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* For NatSemi, switch to bank 2 not bank 1, to avoid resetting EXCR2,
|
||||
@@ -2439,10 +2511,9 @@ static unsigned int serial8250_port_size(struct uart_8250_port *pt)
|
||||
{
|
||||
if (pt->port.iotype == UPIO_AU)
|
||||
return 0x1000;
|
||||
#ifdef CONFIG_ARCH_OMAP1
|
||||
if (is_omap_port(pt))
|
||||
if (is_omap1_8250(pt))
|
||||
return 0x16 << pt->port.regshift;
|
||||
#endif
|
||||
|
||||
return 8 << pt->port.regshift;
|
||||
}
|
||||
|
||||
@@ -2617,6 +2688,11 @@ static void serial8250_config_port(struct uart_port *port, int flags)
|
||||
serial8250_release_rsa_resource(up);
|
||||
if (port->type == PORT_UNKNOWN)
|
||||
serial8250_release_std_resource(up);
|
||||
|
||||
/* Fixme: probably not the best place for this */
|
||||
if ((port->type == PORT_XR17V35X) ||
|
||||
(port->type == PORT_XR17D15X))
|
||||
port->handle_irq = exar_handle_irq;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -2992,7 +3068,7 @@ void serial8250_resume_port(int line)
|
||||
* list is terminated with a zero flags entry, which means we expect
|
||||
* all entries to have at least UPF_BOOT_AUTOCONF set.
|
||||
*/
|
||||
static int __devinit serial8250_probe(struct platform_device *dev)
|
||||
static int serial8250_probe(struct platform_device *dev)
|
||||
{
|
||||
struct plat_serial8250_port *p = dev->dev.platform_data;
|
||||
struct uart_8250_port uart;
|
||||
@@ -3038,7 +3114,7 @@ static int __devinit serial8250_probe(struct platform_device *dev)
|
||||
/*
|
||||
* Remove serial ports registered against a platform device.
|
||||
*/
|
||||
static int __devexit serial8250_remove(struct platform_device *dev)
|
||||
static int serial8250_remove(struct platform_device *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -3081,7 +3157,7 @@ static int serial8250_resume(struct platform_device *dev)
|
||||
|
||||
static struct platform_driver serial8250_isa_driver = {
|
||||
.probe = serial8250_probe,
|
||||
.remove = __devexit_p(serial8250_remove),
|
||||
.remove = serial8250_remove,
|
||||
.suspend = serial8250_suspend,
|
||||
.resume = serial8250_resume,
|
||||
.driver = {
|
||||
|
@@ -106,3 +106,39 @@ static inline int serial8250_pnp_init(void) { return 0; }
|
||||
static inline void serial8250_pnp_exit(void) { }
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARCH_OMAP1
|
||||
static inline int is_omap1_8250(struct uart_8250_port *pt)
|
||||
{
|
||||
int res;
|
||||
|
||||
switch (pt->port.mapbase) {
|
||||
case OMAP1_UART1_BASE:
|
||||
case OMAP1_UART2_BASE:
|
||||
case OMAP1_UART3_BASE:
|
||||
res = 1;
|
||||
break;
|
||||
default:
|
||||
res = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline int is_omap1510_8250(struct uart_8250_port *pt)
|
||||
{
|
||||
if (!cpu_is_omap1510())
|
||||
return 0;
|
||||
|
||||
return is_omap1_8250(pt);
|
||||
}
|
||||
#else
|
||||
static inline int is_omap1_8250(struct uart_8250_port *pt)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline int is_omap1510_8250(struct uart_8250_port *pt)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
@@ -38,7 +38,7 @@ struct serial_card_info {
|
||||
void __iomem *vaddr;
|
||||
};
|
||||
|
||||
static int __devinit
|
||||
static int
|
||||
serial_card_probe(struct expansion_card *ec, const struct ecard_id *id)
|
||||
{
|
||||
struct serial_card_info *info;
|
||||
@@ -80,7 +80,7 @@ serial_card_probe(struct expansion_card *ec, const struct ecard_id *id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __devexit serial_card_remove(struct expansion_card *ec)
|
||||
static void serial_card_remove(struct expansion_card *ec)
|
||||
{
|
||||
struct serial_card_info *info = ecard_get_drvdata(ec);
|
||||
int i;
|
||||
@@ -116,7 +116,7 @@ static const struct ecard_id serial_cids[] = {
|
||||
|
||||
static struct ecard_driver serial_card_driver = {
|
||||
.probe = serial_card_probe,
|
||||
.remove = __devexit_p(serial_card_remove),
|
||||
.remove = serial_card_remove,
|
||||
.id_table = serial_cids,
|
||||
.drv = {
|
||||
.name = "8250_acorn",
|
||||
|
@@ -87,7 +87,7 @@ static int dw8250_handle_irq(struct uart_port *p)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit dw8250_probe(struct platform_device *pdev)
|
||||
static int dw8250_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct uart_8250_port uart = {};
|
||||
struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
@@ -152,7 +152,7 @@ static int __devinit dw8250_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit dw8250_remove(struct platform_device *pdev)
|
||||
static int dw8250_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct dw8250_data *data = platform_get_drvdata(pdev);
|
||||
|
||||
@@ -161,6 +161,29 @@ static int __devexit dw8250_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int dw8250_suspend(struct platform_device *pdev, pm_message_t state)
|
||||
{
|
||||
struct dw8250_data *data = platform_get_drvdata(pdev);
|
||||
|
||||
serial8250_suspend_port(data->line);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dw8250_resume(struct platform_device *pdev)
|
||||
{
|
||||
struct dw8250_data *data = platform_get_drvdata(pdev);
|
||||
|
||||
serial8250_resume_port(data->line);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define dw8250_suspend NULL
|
||||
#define dw8250_resume NULL
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
static const struct of_device_id dw8250_match[] = {
|
||||
{ .compatible = "snps,dw-apb-uart" },
|
||||
{ /* Sentinel */ }
|
||||
@@ -174,7 +197,9 @@ static struct platform_driver dw8250_platform_driver = {
|
||||
.of_match_table = dw8250_match,
|
||||
},
|
||||
.probe = dw8250_probe,
|
||||
.remove = __devexit_p(dw8250_remove),
|
||||
.remove = dw8250_remove,
|
||||
.suspend = dw8250_suspend,
|
||||
.resume = dw8250_resume,
|
||||
};
|
||||
|
||||
module_platform_driver(dw8250_platform_driver);
|
||||
|
@@ -48,7 +48,7 @@ struct early_serial8250_device {
|
||||
|
||||
static struct early_serial8250_device early_device;
|
||||
|
||||
static unsigned int __init serial_in(struct uart_port *port, int offset)
|
||||
unsigned int __weak __init serial8250_early_in(struct uart_port *port, int offset)
|
||||
{
|
||||
switch (port->iotype) {
|
||||
case UPIO_MEM:
|
||||
@@ -62,7 +62,7 @@ static unsigned int __init serial_in(struct uart_port *port, int offset)
|
||||
}
|
||||
}
|
||||
|
||||
static void __init serial_out(struct uart_port *port, int offset, int value)
|
||||
void __weak __init serial8250_early_out(struct uart_port *port, int offset, int value)
|
||||
{
|
||||
switch (port->iotype) {
|
||||
case UPIO_MEM:
|
||||
@@ -84,7 +84,7 @@ static void __init wait_for_xmitr(struct uart_port *port)
|
||||
unsigned int status;
|
||||
|
||||
for (;;) {
|
||||
status = serial_in(port, UART_LSR);
|
||||
status = serial8250_early_in(port, UART_LSR);
|
||||
if ((status & BOTH_EMPTY) == BOTH_EMPTY)
|
||||
return;
|
||||
cpu_relax();
|
||||
@@ -94,7 +94,7 @@ static void __init wait_for_xmitr(struct uart_port *port)
|
||||
static void __init serial_putc(struct uart_port *port, int c)
|
||||
{
|
||||
wait_for_xmitr(port);
|
||||
serial_out(port, UART_TX, c);
|
||||
serial8250_early_out(port, UART_TX, c);
|
||||
}
|
||||
|
||||
static void __init early_serial8250_write(struct console *console,
|
||||
@@ -104,14 +104,14 @@ static void __init early_serial8250_write(struct console *console,
|
||||
unsigned int ier;
|
||||
|
||||
/* Save the IER and disable interrupts */
|
||||
ier = serial_in(port, UART_IER);
|
||||
serial_out(port, UART_IER, 0);
|
||||
ier = serial8250_early_in(port, UART_IER);
|
||||
serial8250_early_out(port, UART_IER, 0);
|
||||
|
||||
uart_console_write(port, s, count, serial_putc);
|
||||
|
||||
/* Wait for transmitter to become empty and restore the IER */
|
||||
wait_for_xmitr(port);
|
||||
serial_out(port, UART_IER, ier);
|
||||
serial8250_early_out(port, UART_IER, ier);
|
||||
}
|
||||
|
||||
static unsigned int __init probe_baud(struct uart_port *port)
|
||||
@@ -119,11 +119,11 @@ static unsigned int __init probe_baud(struct uart_port *port)
|
||||
unsigned char lcr, dll, dlm;
|
||||
unsigned int quot;
|
||||
|
||||
lcr = serial_in(port, UART_LCR);
|
||||
serial_out(port, UART_LCR, lcr | UART_LCR_DLAB);
|
||||
dll = serial_in(port, UART_DLL);
|
||||
dlm = serial_in(port, UART_DLM);
|
||||
serial_out(port, UART_LCR, lcr);
|
||||
lcr = serial8250_early_in(port, UART_LCR);
|
||||
serial8250_early_out(port, UART_LCR, lcr | UART_LCR_DLAB);
|
||||
dll = serial8250_early_in(port, UART_DLL);
|
||||
dlm = serial8250_early_in(port, UART_DLM);
|
||||
serial8250_early_out(port, UART_LCR, lcr);
|
||||
|
||||
quot = (dlm << 8) | dll;
|
||||
return (port->uartclk / 16) / quot;
|
||||
@@ -135,17 +135,17 @@ static void __init init_port(struct early_serial8250_device *device)
|
||||
unsigned int divisor;
|
||||
unsigned char c;
|
||||
|
||||
serial_out(port, UART_LCR, 0x3); /* 8n1 */
|
||||
serial_out(port, UART_IER, 0); /* no interrupt */
|
||||
serial_out(port, UART_FCR, 0); /* no fifo */
|
||||
serial_out(port, UART_MCR, 0x3); /* DTR + RTS */
|
||||
serial8250_early_out(port, UART_LCR, 0x3); /* 8n1 */
|
||||
serial8250_early_out(port, UART_IER, 0); /* no interrupt */
|
||||
serial8250_early_out(port, UART_FCR, 0); /* no fifo */
|
||||
serial8250_early_out(port, UART_MCR, 0x3); /* DTR + RTS */
|
||||
|
||||
divisor = port->uartclk / (16 * device->baud);
|
||||
c = serial_in(port, UART_LCR);
|
||||
serial_out(port, UART_LCR, c | UART_LCR_DLAB);
|
||||
serial_out(port, UART_DLL, divisor & 0xff);
|
||||
serial_out(port, UART_DLM, (divisor >> 8) & 0xff);
|
||||
serial_out(port, UART_LCR, c & ~UART_LCR_DLAB);
|
||||
divisor = DIV_ROUND_CLOSEST(port->uartclk, 16 * device->baud);
|
||||
c = serial8250_early_in(port, UART_LCR);
|
||||
serial8250_early_out(port, UART_LCR, c | UART_LCR_DLAB);
|
||||
serial8250_early_out(port, UART_DLL, divisor & 0xff);
|
||||
serial8250_early_out(port, UART_DLM, (divisor >> 8) & 0xff);
|
||||
serial8250_early_out(port, UART_LCR, c & ~UART_LCR_DLAB);
|
||||
}
|
||||
|
||||
static int __init parse_options(struct early_serial8250_device *device,
|
||||
|
@@ -89,7 +89,7 @@ static void serial8250_em_serial_dl_write(struct uart_8250_port *up, int value)
|
||||
serial_out(up, UART_DLM_EM, value >> 8 & 0xff);
|
||||
}
|
||||
|
||||
static int __devinit serial8250_em_probe(struct platform_device *pdev)
|
||||
static int serial8250_em_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
||||
@@ -152,7 +152,7 @@ static int __devinit serial8250_em_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit serial8250_em_remove(struct platform_device *pdev)
|
||||
static int serial8250_em_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct serial8250_em_priv *priv = platform_get_drvdata(pdev);
|
||||
|
||||
@@ -163,7 +163,7 @@ static int __devexit serial8250_em_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id serial8250_em_dt_ids[] __devinitconst = {
|
||||
static const struct of_device_id serial8250_em_dt_ids[] = {
|
||||
{ .compatible = "renesas,em-uart", },
|
||||
{},
|
||||
};
|
||||
@@ -176,7 +176,7 @@ static struct platform_driver serial8250_em_platform_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = serial8250_em_probe,
|
||||
.remove = __devexit_p(serial8250_em_remove),
|
||||
.remove = serial8250_em_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(serial8250_em_platform_driver);
|
||||
|
@@ -36,9 +36,9 @@ static struct hp300_port *hp300_ports;
|
||||
|
||||
#ifdef CONFIG_HPDCA
|
||||
|
||||
static int __devinit hpdca_init_one(struct dio_dev *d,
|
||||
static int hpdca_init_one(struct dio_dev *d,
|
||||
const struct dio_device_id *ent);
|
||||
static void __devexit hpdca_remove_one(struct dio_dev *d);
|
||||
static void hpdca_remove_one(struct dio_dev *d);
|
||||
|
||||
static struct dio_device_id hpdca_dio_tbl[] = {
|
||||
{ DIO_ID_DCA0 },
|
||||
@@ -52,7 +52,7 @@ static struct dio_driver hpdca_driver = {
|
||||
.name = "hpdca",
|
||||
.id_table = hpdca_dio_tbl,
|
||||
.probe = hpdca_init_one,
|
||||
.remove = __devexit_p(hpdca_remove_one),
|
||||
.remove = hpdca_remove_one,
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -159,7 +159,7 @@ int __init hp300_setup_serial_console(void)
|
||||
#endif /* CONFIG_SERIAL_8250_CONSOLE */
|
||||
|
||||
#ifdef CONFIG_HPDCA
|
||||
static int __devinit hpdca_init_one(struct dio_dev *d,
|
||||
static int hpdca_init_one(struct dio_dev *d,
|
||||
const struct dio_device_id *ent)
|
||||
{
|
||||
struct uart_8250_port uart;
|
||||
@@ -288,7 +288,7 @@ static int __init hp300_8250_init(void)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HPDCA
|
||||
static void __devexit hpdca_remove_one(struct dio_dev *d)
|
||||
static void hpdca_remove_one(struct dio_dev *d)
|
||||
{
|
||||
int line;
|
||||
|
||||
|
@@ -288,7 +288,7 @@ static int pci_plx9050_init(struct pci_dev *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __devexit pci_plx9050_exit(struct pci_dev *dev)
|
||||
static void pci_plx9050_exit(struct pci_dev *dev)
|
||||
{
|
||||
u8 __iomem *p;
|
||||
|
||||
@@ -313,7 +313,7 @@ static void __devexit pci_plx9050_exit(struct pci_dev *dev)
|
||||
#define NI8420_INT_ENABLE_REG 0x38
|
||||
#define NI8420_INT_ENABLE_BIT 0x2000
|
||||
|
||||
static void __devexit pci_ni8420_exit(struct pci_dev *dev)
|
||||
static void pci_ni8420_exit(struct pci_dev *dev)
|
||||
{
|
||||
void __iomem *p;
|
||||
unsigned long base, len;
|
||||
@@ -345,7 +345,7 @@ static void __devexit pci_ni8420_exit(struct pci_dev *dev)
|
||||
|
||||
#define MITE_LCIMR2_CLR_CPU_IE (1 << 30)
|
||||
|
||||
static void __devexit pci_ni8430_exit(struct pci_dev *dev)
|
||||
static void pci_ni8430_exit(struct pci_dev *dev)
|
||||
{
|
||||
void __iomem *p;
|
||||
unsigned long base, len;
|
||||
@@ -422,7 +422,7 @@ static int sbs_init(struct pci_dev *dev)
|
||||
* Disables the global interrupt of PMC-OctalPro
|
||||
*/
|
||||
|
||||
static void __devexit sbs_exit(struct pci_dev *dev)
|
||||
static void sbs_exit(struct pci_dev *dev)
|
||||
{
|
||||
u8 __iomem *p;
|
||||
|
||||
@@ -991,7 +991,7 @@ static int pci_ite887x_init(struct pci_dev *dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __devexit pci_ite887x_exit(struct pci_dev *dev)
|
||||
static void pci_ite887x_exit(struct pci_dev *dev)
|
||||
{
|
||||
u32 ioport;
|
||||
/* the ioport is bit 0-15 in POSIO0R */
|
||||
@@ -1068,7 +1068,7 @@ ce4100_serial_setup(struct serial_private *priv,
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = setup_port(priv, port, 0, 0, board->reg_shift);
|
||||
ret = setup_port(priv, port, idx, 0, board->reg_shift);
|
||||
port->port.iotype = UPIO_MEM32;
|
||||
port->port.type = PORT_XSCALE;
|
||||
port->port.flags = (port->port.flags | UPF_FIXED_PORT | UPF_FIXED_TYPE);
|
||||
@@ -1164,6 +1164,94 @@ pci_xr17c154_setup(struct serial_private *priv,
|
||||
return pci_default_setup(priv, board, port, idx);
|
||||
}
|
||||
|
||||
static int
|
||||
pci_xr17v35x_setup(struct serial_private *priv,
|
||||
const struct pciserial_board *board,
|
||||
struct uart_8250_port *port, int idx)
|
||||
{
|
||||
u8 __iomem *p;
|
||||
|
||||
p = pci_ioremap_bar(priv->dev, 0);
|
||||
if (p == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
port->port.flags |= UPF_EXAR_EFR;
|
||||
|
||||
/*
|
||||
* Setup Multipurpose Input/Output pins.
|
||||
*/
|
||||
if (idx == 0) {
|
||||
writeb(0x00, p + 0x8f); /*MPIOINT[7:0]*/
|
||||
writeb(0x00, p + 0x90); /*MPIOLVL[7:0]*/
|
||||
writeb(0x00, p + 0x91); /*MPIO3T[7:0]*/
|
||||
writeb(0x00, p + 0x92); /*MPIOINV[7:0]*/
|
||||
writeb(0x00, p + 0x93); /*MPIOSEL[7:0]*/
|
||||
writeb(0x00, p + 0x94); /*MPIOOD[7:0]*/
|
||||
writeb(0x00, p + 0x95); /*MPIOINT[15:8]*/
|
||||
writeb(0x00, p + 0x96); /*MPIOLVL[15:8]*/
|
||||
writeb(0x00, p + 0x97); /*MPIO3T[15:8]*/
|
||||
writeb(0x00, p + 0x98); /*MPIOINV[15:8]*/
|
||||
writeb(0x00, p + 0x99); /*MPIOSEL[15:8]*/
|
||||
writeb(0x00, p + 0x9a); /*MPIOOD[15:8]*/
|
||||
}
|
||||
writeb(0x00, p + UART_EXAR_8XMODE);
|
||||
writeb(UART_FCTR_EXAR_TRGD, p + UART_EXAR_FCTR);
|
||||
writeb(128, p + UART_EXAR_TXTRG);
|
||||
writeb(128, p + UART_EXAR_RXTRG);
|
||||
iounmap(p);
|
||||
|
||||
return pci_default_setup(priv, board, port, idx);
|
||||
}
|
||||
|
||||
#define PCI_DEVICE_ID_COMMTECH_4222PCI335 0x0004
|
||||
#define PCI_DEVICE_ID_COMMTECH_4224PCI335 0x0002
|
||||
#define PCI_DEVICE_ID_COMMTECH_2324PCI335 0x000a
|
||||
#define PCI_DEVICE_ID_COMMTECH_2328PCI335 0x000b
|
||||
|
||||
static int
|
||||
pci_fastcom335_setup(struct serial_private *priv,
|
||||
const struct pciserial_board *board,
|
||||
struct uart_8250_port *port, int idx)
|
||||
{
|
||||
u8 __iomem *p;
|
||||
|
||||
p = pci_ioremap_bar(priv->dev, 0);
|
||||
if (p == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
port->port.flags |= UPF_EXAR_EFR;
|
||||
|
||||
/*
|
||||
* Setup Multipurpose Input/Output pins.
|
||||
*/
|
||||
if (idx == 0) {
|
||||
switch (priv->dev->device) {
|
||||
case PCI_DEVICE_ID_COMMTECH_4222PCI335:
|
||||
case PCI_DEVICE_ID_COMMTECH_4224PCI335:
|
||||
writeb(0x78, p + 0x90); /* MPIOLVL[7:0] */
|
||||
writeb(0x00, p + 0x92); /* MPIOINV[7:0] */
|
||||
writeb(0x00, p + 0x93); /* MPIOSEL[7:0] */
|
||||
break;
|
||||
case PCI_DEVICE_ID_COMMTECH_2324PCI335:
|
||||
case PCI_DEVICE_ID_COMMTECH_2328PCI335:
|
||||
writeb(0x00, p + 0x90); /* MPIOLVL[7:0] */
|
||||
writeb(0xc0, p + 0x92); /* MPIOINV[7:0] */
|
||||
writeb(0xc0, p + 0x93); /* MPIOSEL[7:0] */
|
||||
break;
|
||||
}
|
||||
writeb(0x00, p + 0x8f); /* MPIOINT[7:0] */
|
||||
writeb(0x00, p + 0x91); /* MPIO3T[7:0] */
|
||||
writeb(0x00, p + 0x94); /* MPIOOD[7:0] */
|
||||
}
|
||||
writeb(0x00, p + UART_EXAR_8XMODE);
|
||||
writeb(UART_FCTR_EXAR_TRGD, p + UART_EXAR_FCTR);
|
||||
writeb(32, p + UART_EXAR_TXTRG);
|
||||
writeb(32, p + UART_EXAR_RXTRG);
|
||||
iounmap(p);
|
||||
|
||||
return pci_default_setup(priv, board, port, idx);
|
||||
}
|
||||
|
||||
static int
|
||||
pci_wch_ch353_setup(struct serial_private *priv,
|
||||
const struct pciserial_board *board,
|
||||
@@ -1213,6 +1301,10 @@ pci_wch_ch353_setup(struct serial_private *priv,
|
||||
#define PCI_VENDOR_ID_AGESTAR 0x5372
|
||||
#define PCI_DEVICE_ID_AGESTAR_9375 0x6872
|
||||
#define PCI_VENDOR_ID_ASIX 0x9710
|
||||
#define PCI_DEVICE_ID_COMMTECH_4222PCIE 0x0019
|
||||
#define PCI_DEVICE_ID_COMMTECH_4224PCIE 0x0020
|
||||
#define PCI_DEVICE_ID_COMMTECH_4228PCIE 0x0021
|
||||
|
||||
|
||||
/* Unknown vendors/cards - this should not be in linux/pci_ids.h */
|
||||
#define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584
|
||||
@@ -1314,7 +1406,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.init = pci_ite887x_init,
|
||||
.setup = pci_default_setup,
|
||||
.exit = __devexit_p(pci_ite887x_exit),
|
||||
.exit = pci_ite887x_exit,
|
||||
},
|
||||
/*
|
||||
* National Instruments
|
||||
@@ -1326,7 +1418,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.init = pci_ni8420_init,
|
||||
.setup = pci_default_setup,
|
||||
.exit = __devexit_p(pci_ni8420_exit),
|
||||
.exit = pci_ni8420_exit,
|
||||
},
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_NI,
|
||||
@@ -1335,7 +1427,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.init = pci_ni8420_init,
|
||||
.setup = pci_default_setup,
|
||||
.exit = __devexit_p(pci_ni8420_exit),
|
||||
.exit = pci_ni8420_exit,
|
||||
},
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_NI,
|
||||
@@ -1344,7 +1436,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.init = pci_ni8420_init,
|
||||
.setup = pci_default_setup,
|
||||
.exit = __devexit_p(pci_ni8420_exit),
|
||||
.exit = pci_ni8420_exit,
|
||||
},
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_NI,
|
||||
@@ -1353,7 +1445,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.init = pci_ni8420_init,
|
||||
.setup = pci_default_setup,
|
||||
.exit = __devexit_p(pci_ni8420_exit),
|
||||
.exit = pci_ni8420_exit,
|
||||
},
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_NI,
|
||||
@@ -1362,7 +1454,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.init = pci_ni8420_init,
|
||||
.setup = pci_default_setup,
|
||||
.exit = __devexit_p(pci_ni8420_exit),
|
||||
.exit = pci_ni8420_exit,
|
||||
},
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_NI,
|
||||
@@ -1371,7 +1463,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.init = pci_ni8420_init,
|
||||
.setup = pci_default_setup,
|
||||
.exit = __devexit_p(pci_ni8420_exit),
|
||||
.exit = pci_ni8420_exit,
|
||||
},
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_NI,
|
||||
@@ -1380,7 +1472,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.init = pci_ni8420_init,
|
||||
.setup = pci_default_setup,
|
||||
.exit = __devexit_p(pci_ni8420_exit),
|
||||
.exit = pci_ni8420_exit,
|
||||
},
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_NI,
|
||||
@@ -1389,7 +1481,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.init = pci_ni8420_init,
|
||||
.setup = pci_default_setup,
|
||||
.exit = __devexit_p(pci_ni8420_exit),
|
||||
.exit = pci_ni8420_exit,
|
||||
},
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_NI,
|
||||
@@ -1398,7 +1490,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.init = pci_ni8420_init,
|
||||
.setup = pci_default_setup,
|
||||
.exit = __devexit_p(pci_ni8420_exit),
|
||||
.exit = pci_ni8420_exit,
|
||||
},
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_NI,
|
||||
@@ -1407,7 +1499,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.init = pci_ni8420_init,
|
||||
.setup = pci_default_setup,
|
||||
.exit = __devexit_p(pci_ni8420_exit),
|
||||
.exit = pci_ni8420_exit,
|
||||
},
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_NI,
|
||||
@@ -1416,7 +1508,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.init = pci_ni8420_init,
|
||||
.setup = pci_default_setup,
|
||||
.exit = __devexit_p(pci_ni8420_exit),
|
||||
.exit = pci_ni8420_exit,
|
||||
},
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_NI,
|
||||
@@ -1425,7 +1517,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.init = pci_ni8420_init,
|
||||
.setup = pci_default_setup,
|
||||
.exit = __devexit_p(pci_ni8420_exit),
|
||||
.exit = pci_ni8420_exit,
|
||||
},
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_NI,
|
||||
@@ -1434,7 +1526,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.init = pci_ni8430_init,
|
||||
.setup = pci_ni8430_setup,
|
||||
.exit = __devexit_p(pci_ni8430_exit),
|
||||
.exit = pci_ni8430_exit,
|
||||
},
|
||||
/*
|
||||
* Panacom
|
||||
@@ -1446,7 +1538,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.init = pci_plx9050_init,
|
||||
.setup = pci_default_setup,
|
||||
.exit = __devexit_p(pci_plx9050_exit),
|
||||
.exit = pci_plx9050_exit,
|
||||
},
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_PANACOM,
|
||||
@@ -1455,7 +1547,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.init = pci_plx9050_init,
|
||||
.setup = pci_default_setup,
|
||||
.exit = __devexit_p(pci_plx9050_exit),
|
||||
.exit = pci_plx9050_exit,
|
||||
},
|
||||
/*
|
||||
* PLX
|
||||
@@ -1474,7 +1566,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
|
||||
.subdevice = PCI_SUBDEVICE_ID_EXSYS_4055,
|
||||
.init = pci_plx9050_init,
|
||||
.setup = pci_default_setup,
|
||||
.exit = __devexit_p(pci_plx9050_exit),
|
||||
.exit = pci_plx9050_exit,
|
||||
},
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_PLX,
|
||||
@@ -1483,7 +1575,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
|
||||
.subdevice = PCI_SUBDEVICE_ID_KEYSPAN_SX2,
|
||||
.init = pci_plx9050_init,
|
||||
.setup = pci_default_setup,
|
||||
.exit = __devexit_p(pci_plx9050_exit),
|
||||
.exit = pci_plx9050_exit,
|
||||
},
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_PLX,
|
||||
@@ -1492,7 +1584,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
|
||||
.subdevice = PCI_SUBDEVICE_ID_UNKNOWN_0x1584,
|
||||
.init = pci_plx9050_init,
|
||||
.setup = pci_default_setup,
|
||||
.exit = __devexit_p(pci_plx9050_exit),
|
||||
.exit = pci_plx9050_exit,
|
||||
},
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_PLX,
|
||||
@@ -1501,7 +1593,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
|
||||
.subdevice = PCI_DEVICE_ID_PLX_ROMULUS,
|
||||
.init = pci_plx9050_init,
|
||||
.setup = pci_default_setup,
|
||||
.exit = __devexit_p(pci_plx9050_exit),
|
||||
.exit = pci_plx9050_exit,
|
||||
},
|
||||
/*
|
||||
* SBS Technologies, Inc., PMC-OCTALPRO 232
|
||||
@@ -1513,7 +1605,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
|
||||
.subdevice = PCI_SUBDEVICE_ID_OCTPRO232,
|
||||
.init = sbs_init,
|
||||
.setup = sbs_setup,
|
||||
.exit = __devexit_p(sbs_exit),
|
||||
.exit = sbs_exit,
|
||||
},
|
||||
/*
|
||||
* SBS Technologies, Inc., PMC-OCTALPRO 422
|
||||
@@ -1525,7 +1617,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
|
||||
.subdevice = PCI_SUBDEVICE_ID_OCTPRO422,
|
||||
.init = sbs_init,
|
||||
.setup = sbs_setup,
|
||||
.exit = __devexit_p(sbs_exit),
|
||||
.exit = sbs_exit,
|
||||
},
|
||||
/*
|
||||
* SBS Technologies, Inc., P-Octal 232
|
||||
@@ -1537,7 +1629,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
|
||||
.subdevice = PCI_SUBDEVICE_ID_POCTAL232,
|
||||
.init = sbs_init,
|
||||
.setup = sbs_setup,
|
||||
.exit = __devexit_p(sbs_exit),
|
||||
.exit = sbs_exit,
|
||||
},
|
||||
/*
|
||||
* SBS Technologies, Inc., P-Octal 422
|
||||
@@ -1549,7 +1641,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
|
||||
.subdevice = PCI_SUBDEVICE_ID_POCTAL422,
|
||||
.init = sbs_init,
|
||||
.setup = sbs_setup,
|
||||
.exit = __devexit_p(sbs_exit),
|
||||
.exit = sbs_exit,
|
||||
},
|
||||
/*
|
||||
* SIIG cards - these may be called via parport_serial
|
||||
@@ -1622,6 +1714,27 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.setup = pci_xr17c154_setup,
|
||||
},
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_EXAR,
|
||||
.device = PCI_DEVICE_ID_EXAR_XR17V352,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.setup = pci_xr17v35x_setup,
|
||||
},
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_EXAR,
|
||||
.device = PCI_DEVICE_ID_EXAR_XR17V354,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.setup = pci_xr17v35x_setup,
|
||||
},
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_EXAR,
|
||||
.device = PCI_DEVICE_ID_EXAR_XR17V358,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.setup = pci_xr17v35x_setup,
|
||||
},
|
||||
/*
|
||||
* Xircom cards
|
||||
*/
|
||||
@@ -1787,6 +1900,59 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.setup = pci_asix_setup,
|
||||
},
|
||||
/*
|
||||
* Commtech, Inc. Fastcom adapters
|
||||
*
|
||||
*/
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_COMMTECH,
|
||||
.device = PCI_DEVICE_ID_COMMTECH_4222PCI335,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.setup = pci_fastcom335_setup,
|
||||
},
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_COMMTECH,
|
||||
.device = PCI_DEVICE_ID_COMMTECH_4224PCI335,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.setup = pci_fastcom335_setup,
|
||||
},
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_COMMTECH,
|
||||
.device = PCI_DEVICE_ID_COMMTECH_2324PCI335,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.setup = pci_fastcom335_setup,
|
||||
},
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_COMMTECH,
|
||||
.device = PCI_DEVICE_ID_COMMTECH_2328PCI335,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.setup = pci_fastcom335_setup,
|
||||
},
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_COMMTECH,
|
||||
.device = PCI_DEVICE_ID_COMMTECH_4222PCIE,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.setup = pci_xr17v35x_setup,
|
||||
},
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_COMMTECH,
|
||||
.device = PCI_DEVICE_ID_COMMTECH_4224PCIE,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.setup = pci_xr17v35x_setup,
|
||||
},
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_COMMTECH,
|
||||
.device = PCI_DEVICE_ID_COMMTECH_4228PCIE,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.setup = pci_xr17v35x_setup,
|
||||
},
|
||||
/*
|
||||
* Default "match everything" terminator entry
|
||||
*/
|
||||
@@ -1863,6 +2029,10 @@ enum pci_board_num_t {
|
||||
|
||||
pbn_b0_4_1152000,
|
||||
|
||||
pbn_b0_2_1152000_200,
|
||||
pbn_b0_4_1152000_200,
|
||||
pbn_b0_8_1152000_200,
|
||||
|
||||
pbn_b0_2_1843200,
|
||||
pbn_b0_4_1843200,
|
||||
|
||||
@@ -1962,6 +2132,9 @@ enum pci_board_num_t {
|
||||
pbn_exar_XR17C152,
|
||||
pbn_exar_XR17C154,
|
||||
pbn_exar_XR17C158,
|
||||
pbn_exar_XR17V352,
|
||||
pbn_exar_XR17V354,
|
||||
pbn_exar_XR17V358,
|
||||
pbn_exar_ibm_saturn,
|
||||
pbn_pasemi_1682M,
|
||||
pbn_ni8430_2,
|
||||
@@ -1987,7 +2160,7 @@ enum pci_board_num_t {
|
||||
* see first lines of serial_in() and serial_out() in 8250.c
|
||||
*/
|
||||
|
||||
static struct pciserial_board pci_boards[] __devinitdata = {
|
||||
static struct pciserial_board pci_boards[] = {
|
||||
[pbn_default] = {
|
||||
.flags = FL_BASE0,
|
||||
.num_ports = 1,
|
||||
@@ -2057,6 +2230,27 @@ static struct pciserial_board pci_boards[] __devinitdata = {
|
||||
.uart_offset = 8,
|
||||
},
|
||||
|
||||
[pbn_b0_2_1152000_200] = {
|
||||
.flags = FL_BASE0,
|
||||
.num_ports = 2,
|
||||
.base_baud = 1152000,
|
||||
.uart_offset = 0x200,
|
||||
},
|
||||
|
||||
[pbn_b0_4_1152000_200] = {
|
||||
.flags = FL_BASE0,
|
||||
.num_ports = 4,
|
||||
.base_baud = 1152000,
|
||||
.uart_offset = 0x200,
|
||||
},
|
||||
|
||||
[pbn_b0_8_1152000_200] = {
|
||||
.flags = FL_BASE0,
|
||||
.num_ports = 2,
|
||||
.base_baud = 1152000,
|
||||
.uart_offset = 0x200,
|
||||
},
|
||||
|
||||
[pbn_b0_2_1843200] = {
|
||||
.flags = FL_BASE0,
|
||||
.num_ports = 2,
|
||||
@@ -2580,6 +2774,30 @@ static struct pciserial_board pci_boards[] __devinitdata = {
|
||||
.base_baud = 921600,
|
||||
.uart_offset = 0x200,
|
||||
},
|
||||
[pbn_exar_XR17V352] = {
|
||||
.flags = FL_BASE0,
|
||||
.num_ports = 2,
|
||||
.base_baud = 7812500,
|
||||
.uart_offset = 0x400,
|
||||
.reg_shift = 0,
|
||||
.first_offset = 0,
|
||||
},
|
||||
[pbn_exar_XR17V354] = {
|
||||
.flags = FL_BASE0,
|
||||
.num_ports = 4,
|
||||
.base_baud = 7812500,
|
||||
.uart_offset = 0x400,
|
||||
.reg_shift = 0,
|
||||
.first_offset = 0,
|
||||
},
|
||||
[pbn_exar_XR17V358] = {
|
||||
.flags = FL_BASE0,
|
||||
.num_ports = 8,
|
||||
.base_baud = 7812500,
|
||||
.uart_offset = 0x400,
|
||||
.reg_shift = 0,
|
||||
.first_offset = 0,
|
||||
},
|
||||
[pbn_exar_ibm_saturn] = {
|
||||
.flags = FL_BASE0,
|
||||
.num_ports = 1,
|
||||
@@ -2658,8 +2876,8 @@ static struct pciserial_board pci_boards[] __devinitdata = {
|
||||
.first_offset = 0x1000,
|
||||
},
|
||||
[pbn_ce4100_1_115200] = {
|
||||
.flags = FL_BASE0,
|
||||
.num_ports = 1,
|
||||
.flags = FL_BASE_BARS,
|
||||
.num_ports = 2,
|
||||
.base_baud = 921600,
|
||||
.reg_shift = 2,
|
||||
},
|
||||
@@ -2691,7 +2909,7 @@ static const struct pci_device_id blacklist[] = {
|
||||
* guess what the configuration might be, based on the pitiful PCI
|
||||
* serial specs. Returns 0 on success, 1 on failure.
|
||||
*/
|
||||
static int __devinit
|
||||
static int
|
||||
serial_pci_guess_board(struct pci_dev *dev, struct pciserial_board *board)
|
||||
{
|
||||
const struct pci_device_id *bldev;
|
||||
@@ -2917,7 +3135,7 @@ EXPORT_SYMBOL_GPL(pciserial_resume_ports);
|
||||
* Probe one serial board. Unfortunately, there is no rhyme nor reason
|
||||
* to the arrangement of serial ports on a PCI card.
|
||||
*/
|
||||
static int __devinit
|
||||
static int
|
||||
pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
|
||||
{
|
||||
struct pci_serial_quirk *quirk;
|
||||
@@ -2988,7 +3206,7 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void __devexit pciserial_remove_one(struct pci_dev *dev)
|
||||
static void pciserial_remove_one(struct pci_dev *dev)
|
||||
{
|
||||
struct serial_private *priv = pci_get_drvdata(dev);
|
||||
|
||||
@@ -3826,6 +4044,21 @@ static struct pci_device_id serial_pci_tbl[] = {
|
||||
PCI_ANY_ID, PCI_ANY_ID,
|
||||
0,
|
||||
0, pbn_exar_XR17C158 },
|
||||
/*
|
||||
* Exar Corp. XR17V35[248] Dual/Quad/Octal PCIe UARTs
|
||||
*/
|
||||
{ PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17V352,
|
||||
PCI_ANY_ID, PCI_ANY_ID,
|
||||
0,
|
||||
0, pbn_exar_XR17V352 },
|
||||
{ PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17V354,
|
||||
PCI_ANY_ID, PCI_ANY_ID,
|
||||
0,
|
||||
0, pbn_exar_XR17V354 },
|
||||
{ PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17V358,
|
||||
PCI_ANY_ID, PCI_ANY_ID,
|
||||
0,
|
||||
0, pbn_exar_XR17V358 },
|
||||
|
||||
/*
|
||||
* Topic TP560 Data/Fax/Voice 56k modem (reported by Evan Clarke)
|
||||
@@ -4256,6 +4489,38 @@ static struct pci_device_id serial_pci_tbl[] = {
|
||||
PCI_ANY_ID, PCI_ANY_ID,
|
||||
0, 0, pbn_b0_bt_2_115200 },
|
||||
|
||||
/*
|
||||
* Commtech, Inc. Fastcom adapters
|
||||
*/
|
||||
{ PCI_VENDOR_ID_COMMTECH, PCI_DEVICE_ID_COMMTECH_4222PCI335,
|
||||
PCI_ANY_ID, PCI_ANY_ID,
|
||||
0,
|
||||
0, pbn_b0_2_1152000_200 },
|
||||
{ PCI_VENDOR_ID_COMMTECH, PCI_DEVICE_ID_COMMTECH_4224PCI335,
|
||||
PCI_ANY_ID, PCI_ANY_ID,
|
||||
0,
|
||||
0, pbn_b0_4_1152000_200 },
|
||||
{ PCI_VENDOR_ID_COMMTECH, PCI_DEVICE_ID_COMMTECH_2324PCI335,
|
||||
PCI_ANY_ID, PCI_ANY_ID,
|
||||
0,
|
||||
0, pbn_b0_4_1152000_200 },
|
||||
{ PCI_VENDOR_ID_COMMTECH, PCI_DEVICE_ID_COMMTECH_2328PCI335,
|
||||
PCI_ANY_ID, PCI_ANY_ID,
|
||||
0,
|
||||
0, pbn_b0_8_1152000_200 },
|
||||
{ PCI_VENDOR_ID_COMMTECH, PCI_DEVICE_ID_COMMTECH_4222PCIE,
|
||||
PCI_ANY_ID, PCI_ANY_ID,
|
||||
0,
|
||||
0, pbn_exar_XR17V352 },
|
||||
{ PCI_VENDOR_ID_COMMTECH, PCI_DEVICE_ID_COMMTECH_4224PCIE,
|
||||
PCI_ANY_ID, PCI_ANY_ID,
|
||||
0,
|
||||
0, pbn_exar_XR17V354 },
|
||||
{ PCI_VENDOR_ID_COMMTECH, PCI_DEVICE_ID_COMMTECH_4228PCIE,
|
||||
PCI_ANY_ID, PCI_ANY_ID,
|
||||
0,
|
||||
0, pbn_exar_XR17V358 },
|
||||
|
||||
/*
|
||||
* These entries match devices with class COMMUNICATION_SERIAL,
|
||||
* COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL
|
||||
@@ -4323,7 +4588,7 @@ static const struct pci_error_handlers serial8250_err_handler = {
|
||||
static struct pci_driver serial_pci_driver = {
|
||||
.name = "serial",
|
||||
.probe = pciserial_init_one,
|
||||
.remove = __devexit_p(pciserial_remove_one),
|
||||
.remove = pciserial_remove_one,
|
||||
#ifdef CONFIG_PM
|
||||
.suspend = pciserial_suspend_one,
|
||||
.resume = pciserial_resume_one,
|
||||
@@ -4332,18 +4597,7 @@ static struct pci_driver serial_pci_driver = {
|
||||
.err_handler = &serial8250_err_handler,
|
||||
};
|
||||
|
||||
static int __init serial8250_pci_init(void)
|
||||
{
|
||||
return pci_register_driver(&serial_pci_driver);
|
||||
}
|
||||
|
||||
static void __exit serial8250_pci_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&serial_pci_driver);
|
||||
}
|
||||
|
||||
module_init(serial8250_pci_init);
|
||||
module_exit(serial8250_pci_exit);
|
||||
module_pci_driver(serial_pci_driver);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Generic 8250/16x50 PCI serial probe module");
|
||||
|
@@ -370,14 +370,14 @@ static const struct pnp_device_id pnp_dev_table[] = {
|
||||
|
||||
MODULE_DEVICE_TABLE(pnp, pnp_dev_table);
|
||||
|
||||
static char *modem_names[] __devinitdata = {
|
||||
static char *modem_names[] = {
|
||||
"MODEM", "Modem", "modem", "FAX", "Fax", "fax",
|
||||
"56K", "56k", "K56", "33.6", "28.8", "14.4",
|
||||
"33,600", "28,800", "14,400", "33.600", "28.800", "14.400",
|
||||
"33600", "28800", "14400", "V.90", "V.34", "V.32", NULL
|
||||
};
|
||||
|
||||
static int __devinit check_name(char *name)
|
||||
static int check_name(char *name)
|
||||
{
|
||||
char **tmp;
|
||||
|
||||
@@ -388,7 +388,7 @@ static int __devinit check_name(char *name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit check_resources(struct pnp_dev *dev)
|
||||
static int check_resources(struct pnp_dev *dev)
|
||||
{
|
||||
resource_size_t base[] = {0x2f8, 0x3f8, 0x2e8, 0x3e8};
|
||||
int i;
|
||||
@@ -412,7 +412,7 @@ static int __devinit check_resources(struct pnp_dev *dev)
|
||||
* PnP modems, alternatively we must hardcode all modems in pnp_devices[]
|
||||
* table.
|
||||
*/
|
||||
static int __devinit serial_pnp_guess_board(struct pnp_dev *dev)
|
||||
static int serial_pnp_guess_board(struct pnp_dev *dev)
|
||||
{
|
||||
if (!(check_name(pnp_dev_name(dev)) ||
|
||||
(dev->card && check_name(dev->card->name))))
|
||||
@@ -424,7 +424,7 @@ static int __devinit serial_pnp_guess_board(struct pnp_dev *dev)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static int __devinit
|
||||
static int
|
||||
serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
|
||||
{
|
||||
struct uart_8250_port uart;
|
||||
@@ -476,7 +476,7 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __devexit serial_pnp_remove(struct pnp_dev *dev)
|
||||
static void serial_pnp_remove(struct pnp_dev *dev)
|
||||
{
|
||||
long line = (long)pnp_get_drvdata(dev);
|
||||
if (line)
|
||||
@@ -511,7 +511,7 @@ static int serial_pnp_resume(struct pnp_dev *dev)
|
||||
static struct pnp_driver serial_pnp_driver = {
|
||||
.name = "serial",
|
||||
.probe = serial_pnp_probe,
|
||||
.remove = __devexit_p(serial_pnp_remove),
|
||||
.remove = serial_pnp_remove,
|
||||
.suspend = serial_pnp_suspend,
|
||||
.resume = serial_pnp_resume,
|
||||
.id_table = pnp_dev_table,
|
||||
|
@@ -93,7 +93,7 @@ config SERIAL_SB1250_DUART_CONSOLE
|
||||
|
||||
config SERIAL_ATMEL
|
||||
bool "AT91 / AT32 on-chip serial port support"
|
||||
depends on (ARM && ARCH_AT91) || AVR32
|
||||
depends on ARCH_AT91 || AVR32
|
||||
select SERIAL_CORE
|
||||
help
|
||||
This enables the driver for the on-chip UARTs of the Atmel
|
||||
@@ -198,7 +198,7 @@ config SERIAL_CLPS711X_CONSOLE
|
||||
|
||||
config SERIAL_SAMSUNG
|
||||
tristate "Samsung SoC serial support"
|
||||
depends on ARM && PLAT_SAMSUNG
|
||||
depends on PLAT_SAMSUNG
|
||||
select SERIAL_CORE
|
||||
help
|
||||
Support for the on-chip UARTs on the Samsung S3C24XX series CPUs,
|
||||
@@ -208,14 +208,14 @@ config SERIAL_SAMSUNG
|
||||
|
||||
config SERIAL_SAMSUNG_UARTS_4
|
||||
bool
|
||||
depends on ARM && PLAT_SAMSUNG
|
||||
depends on PLAT_SAMSUNG
|
||||
default y if !(CPU_S3C2410 || SERIAL_S3C2412 || CPU_S3C2440 || CPU_S3C2442)
|
||||
help
|
||||
Internal node for the common case of 4 Samsung compatible UARTs
|
||||
|
||||
config SERIAL_SAMSUNG_UARTS
|
||||
int
|
||||
depends on ARM && PLAT_SAMSUNG
|
||||
depends on PLAT_SAMSUNG
|
||||
default 6 if ARCH_S5P6450
|
||||
default 4 if SERIAL_SAMSUNG_UARTS_4 || CPU_S3C2416
|
||||
default 3
|
||||
@@ -249,7 +249,7 @@ config SERIAL_SAMSUNG_CONSOLE
|
||||
|
||||
config SERIAL_SIRFSOC
|
||||
tristate "SiRF SoC Platform Serial port support"
|
||||
depends on ARM && ARCH_PRIMA2
|
||||
depends on ARCH_PRIMA2
|
||||
select SERIAL_CORE
|
||||
help
|
||||
Support for the on-chip UART on the CSR SiRFprimaII series,
|
||||
@@ -347,7 +347,7 @@ config SERIAL_ZS_CONSOLE
|
||||
|
||||
config SERIAL_21285
|
||||
tristate "DC21285 serial port support"
|
||||
depends on ARM && FOOTBRIDGE
|
||||
depends on FOOTBRIDGE
|
||||
select SERIAL_CORE
|
||||
help
|
||||
If you have a machine based on a 21285 (Footbridge) StrongARM(R)/
|
||||
@@ -371,7 +371,7 @@ config SERIAL_21285_CONSOLE
|
||||
|
||||
config SERIAL_MPSC
|
||||
bool "Marvell MPSC serial port support"
|
||||
depends on PPC32 && MV64X60
|
||||
depends on MV64X60
|
||||
select SERIAL_CORE
|
||||
help
|
||||
Say Y here if you want to use the Marvell MPSC serial controller.
|
||||
@@ -408,7 +408,7 @@ config SERIAL_PXA_CONSOLE
|
||||
|
||||
config SERIAL_SA1100
|
||||
bool "SA1100 serial port support"
|
||||
depends on ARM && ARCH_SA1100
|
||||
depends on ARCH_SA1100
|
||||
select SERIAL_CORE
|
||||
help
|
||||
If you have a machine based on a SA1100/SA1110 StrongARM(R) CPU you
|
||||
@@ -716,7 +716,7 @@ config SERIAL_SH_SCI_DMA
|
||||
|
||||
config SERIAL_PNX8XXX
|
||||
bool "Enable PNX8XXX SoCs' UART Support"
|
||||
depends on MIPS && (SOC_PNX8550 || SOC_PNX833X)
|
||||
depends on SOC_PNX8550 || SOC_PNX833X
|
||||
select SERIAL_CORE
|
||||
help
|
||||
If you have a MIPS-based Philips SoC such as PNX8550 or PNX8330
|
||||
@@ -1013,7 +1013,7 @@ config SERIAL_SGI_IOC3
|
||||
|
||||
config SERIAL_MSM
|
||||
bool "MSM on-chip serial port support"
|
||||
depends on ARM && ARCH_MSM
|
||||
depends on ARCH_MSM
|
||||
select SERIAL_CORE
|
||||
|
||||
config SERIAL_MSM_CONSOLE
|
||||
@@ -1035,7 +1035,7 @@ config SERIAL_MSM_HS
|
||||
|
||||
config SERIAL_VT8500
|
||||
bool "VIA VT8500 on-chip serial port support"
|
||||
depends on ARM && ARCH_VT8500
|
||||
depends on ARCH_VT8500
|
||||
select SERIAL_CORE
|
||||
|
||||
config SERIAL_VT8500_CONSOLE
|
||||
@@ -1045,7 +1045,7 @@ config SERIAL_VT8500_CONSOLE
|
||||
|
||||
config SERIAL_NETX
|
||||
tristate "NetX serial port support"
|
||||
depends on ARM && ARCH_NETX
|
||||
depends on ARCH_NETX
|
||||
select SERIAL_CORE
|
||||
help
|
||||
If you have a machine based on a Hilscher NetX SoC you
|
||||
@@ -1376,6 +1376,7 @@ config SERIAL_MXS_AUART_CONSOLE
|
||||
|
||||
config SERIAL_XILINX_PS_UART
|
||||
tristate "Xilinx PS UART support"
|
||||
depends on OF
|
||||
select SERIAL_CORE
|
||||
help
|
||||
This driver supports the Xilinx PS UART port.
|
||||
@@ -1423,4 +1424,27 @@ config SERIAL_EFM32_UART_CONSOLE
|
||||
depends on SERIAL_EFM32_UART=y
|
||||
select SERIAL_CORE_CONSOLE
|
||||
|
||||
config SERIAL_ARC
|
||||
tristate "ARC UART driver support"
|
||||
select SERIAL_CORE
|
||||
help
|
||||
Driver for on-chip UART for ARC(Synopsys) for the legacy
|
||||
FPGA Boards (ML50x/ARCAngel4)
|
||||
|
||||
config SERIAL_ARC_CONSOLE
|
||||
bool "Console on ARC UART"
|
||||
depends on SERIAL_ARC=y
|
||||
select SERIAL_CORE_CONSOLE
|
||||
help
|
||||
Enable system Console on ARC UART
|
||||
|
||||
config SERIAL_ARC_NR_PORTS
|
||||
int "Number of ARC UART ports"
|
||||
depends on SERIAL_ARC
|
||||
range 1 3
|
||||
default "1"
|
||||
help
|
||||
Set this to the number of serial ports you want the driver
|
||||
to support.
|
||||
|
||||
endmenu
|
||||
|
@@ -82,3 +82,4 @@ obj-$(CONFIG_SERIAL_XILINX_PS_UART) += xilinx_uartps.o
|
||||
obj-$(CONFIG_SERIAL_SIRFSOC) += sirfsoc_uart.o
|
||||
obj-$(CONFIG_SERIAL_AR933X) += ar933x_uart.o
|
||||
obj-$(CONFIG_SERIAL_EFM32_UART) += efm32-uart.o
|
||||
obj-$(CONFIG_SERIAL_ARC) += arc_uart.o
|
||||
|
@@ -406,7 +406,7 @@ static struct uart_driver altera_jtaguart_driver = {
|
||||
.cons = ALTERA_JTAGUART_CONSOLE,
|
||||
};
|
||||
|
||||
static int __devinit altera_jtaguart_probe(struct platform_device *pdev)
|
||||
static int altera_jtaguart_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct altera_jtaguart_platform_uart *platp = pdev->dev.platform_data;
|
||||
struct uart_port *port;
|
||||
@@ -453,7 +453,7 @@ static int __devinit altera_jtaguart_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit altera_jtaguart_remove(struct platform_device *pdev)
|
||||
static int altera_jtaguart_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct uart_port *port;
|
||||
int i = pdev->id;
|
||||
@@ -477,7 +477,7 @@ MODULE_DEVICE_TABLE(of, altera_jtaguart_match);
|
||||
|
||||
static struct platform_driver altera_jtaguart_platform_driver = {
|
||||
.probe = altera_jtaguart_probe,
|
||||
.remove = __devexit_p(altera_jtaguart_remove),
|
||||
.remove = altera_jtaguart_remove,
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
|
@@ -532,7 +532,7 @@ static int altera_uart_get_of_uartclk(struct platform_device *pdev,
|
||||
}
|
||||
#endif /* CONFIG_OF */
|
||||
|
||||
static int __devinit altera_uart_probe(struct platform_device *pdev)
|
||||
static int altera_uart_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct altera_uart_platform_uart *platp = pdev->dev.platform_data;
|
||||
struct uart_port *port;
|
||||
@@ -598,7 +598,7 @@ static int __devinit altera_uart_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit altera_uart_remove(struct platform_device *pdev)
|
||||
static int altera_uart_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct uart_port *port = platform_get_drvdata(pdev);
|
||||
|
||||
@@ -621,7 +621,7 @@ MODULE_DEVICE_TABLE(of, altera_uart_match);
|
||||
|
||||
static struct platform_driver altera_uart_platform_driver = {
|
||||
.probe = altera_uart_probe,
|
||||
.remove = __devexit_p(altera_uart_remove),
|
||||
.remove = altera_uart_remove,
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
|
@@ -56,8 +56,7 @@
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/sizes.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#define UART_NR 14
|
||||
|
||||
@@ -1973,7 +1972,8 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
|
||||
goto out;
|
||||
}
|
||||
|
||||
uap = kzalloc(sizeof(struct uart_amba_port), GFP_KERNEL);
|
||||
uap = devm_kzalloc(&dev->dev, sizeof(struct uart_amba_port),
|
||||
GFP_KERNEL);
|
||||
if (uap == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
@@ -1981,16 +1981,17 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
|
||||
|
||||
i = pl011_probe_dt_alias(i, &dev->dev);
|
||||
|
||||
base = ioremap(dev->res.start, resource_size(&dev->res));
|
||||
base = devm_ioremap(&dev->dev, dev->res.start,
|
||||
resource_size(&dev->res));
|
||||
if (!base) {
|
||||
ret = -ENOMEM;
|
||||
goto free;
|
||||
goto out;
|
||||
}
|
||||
|
||||
uap->pinctrl = devm_pinctrl_get(&dev->dev);
|
||||
if (IS_ERR(uap->pinctrl)) {
|
||||
ret = PTR_ERR(uap->pinctrl);
|
||||
goto unmap;
|
||||
goto out;
|
||||
}
|
||||
uap->pins_default = pinctrl_lookup_state(uap->pinctrl,
|
||||
PINCTRL_STATE_DEFAULT);
|
||||
@@ -2002,10 +2003,10 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
|
||||
if (IS_ERR(uap->pins_sleep))
|
||||
dev_dbg(&dev->dev, "could not get sleep pinstate\n");
|
||||
|
||||
uap->clk = clk_get(&dev->dev, NULL);
|
||||
uap->clk = devm_clk_get(&dev->dev, NULL);
|
||||
if (IS_ERR(uap->clk)) {
|
||||
ret = PTR_ERR(uap->clk);
|
||||
goto unmap;
|
||||
goto out;
|
||||
}
|
||||
|
||||
uap->vendor = vendor;
|
||||
@@ -2038,11 +2039,6 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
|
||||
amba_set_drvdata(dev, NULL);
|
||||
amba_ports[i] = NULL;
|
||||
pl011_dma_remove(uap);
|
||||
clk_put(uap->clk);
|
||||
unmap:
|
||||
iounmap(base);
|
||||
free:
|
||||
kfree(uap);
|
||||
}
|
||||
out:
|
||||
return ret;
|
||||
@@ -2062,9 +2058,6 @@ static int pl011_remove(struct amba_device *dev)
|
||||
amba_ports[i] = NULL;
|
||||
|
||||
pl011_dma_remove(uap);
|
||||
iounmap(uap->port.membase);
|
||||
clk_put(uap->clk);
|
||||
kfree(uap);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@@ -554,7 +554,7 @@ static struct uart_driver grlib_apbuart_driver = {
|
||||
/* OF Platform Driver */
|
||||
/* ======================================================================== */
|
||||
|
||||
static int __devinit apbuart_probe(struct platform_device *op)
|
||||
static int apbuart_probe(struct platform_device *op)
|
||||
{
|
||||
int i;
|
||||
struct uart_port *port = NULL;
|
||||
|
@@ -25,11 +25,19 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/irq.h>
|
||||
|
||||
#include <asm/div64.h>
|
||||
|
||||
#include <asm/mach-ath79/ar933x_uart.h>
|
||||
#include <asm/mach-ath79/ar933x_uart_platform.h>
|
||||
|
||||
#define DRIVER_NAME "ar933x-uart"
|
||||
|
||||
#define AR933X_UART_MAX_SCALE 0xff
|
||||
#define AR933X_UART_MAX_STEP 0xffff
|
||||
|
||||
#define AR933X_UART_MIN_BAUD 300
|
||||
#define AR933X_UART_MAX_BAUD 3000000
|
||||
|
||||
#define AR933X_DUMMY_STATUS_RD 0x01
|
||||
|
||||
static struct uart_driver ar933x_uart_driver;
|
||||
@@ -37,6 +45,8 @@ static struct uart_driver ar933x_uart_driver;
|
||||
struct ar933x_uart_port {
|
||||
struct uart_port port;
|
||||
unsigned int ier; /* shadow Interrupt Enable Register */
|
||||
unsigned int min_baud;
|
||||
unsigned int max_baud;
|
||||
};
|
||||
|
||||
static inline unsigned int ar933x_uart_read(struct ar933x_uart_port *up,
|
||||
@@ -162,6 +172,57 @@ static void ar933x_uart_enable_ms(struct uart_port *port)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* baudrate = (clk / (scale + 1)) * (step * (1 / 2^17))
|
||||
*/
|
||||
static unsigned long ar933x_uart_get_baud(unsigned int clk,
|
||||
unsigned int scale,
|
||||
unsigned int step)
|
||||
{
|
||||
u64 t;
|
||||
u32 div;
|
||||
|
||||
div = (2 << 16) * (scale + 1);
|
||||
t = clk;
|
||||
t *= step;
|
||||
t += (div / 2);
|
||||
do_div(t, div);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
static void ar933x_uart_get_scale_step(unsigned int clk,
|
||||
unsigned int baud,
|
||||
unsigned int *scale,
|
||||
unsigned int *step)
|
||||
{
|
||||
unsigned int tscale;
|
||||
long min_diff;
|
||||
|
||||
*scale = 0;
|
||||
*step = 0;
|
||||
|
||||
min_diff = baud;
|
||||
for (tscale = 0; tscale < AR933X_UART_MAX_SCALE; tscale++) {
|
||||
u64 tstep;
|
||||
int diff;
|
||||
|
||||
tstep = baud * (tscale + 1);
|
||||
tstep *= (2 << 16);
|
||||
do_div(tstep, clk);
|
||||
|
||||
if (tstep > AR933X_UART_MAX_STEP)
|
||||
break;
|
||||
|
||||
diff = abs(ar933x_uart_get_baud(clk, tscale, tstep) - baud);
|
||||
if (diff < min_diff) {
|
||||
min_diff = diff;
|
||||
*scale = tscale;
|
||||
*step = tstep;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ar933x_uart_set_termios(struct uart_port *port,
|
||||
struct ktermios *new,
|
||||
struct ktermios *old)
|
||||
@@ -169,7 +230,7 @@ static void ar933x_uart_set_termios(struct uart_port *port,
|
||||
struct ar933x_uart_port *up = (struct ar933x_uart_port *) port;
|
||||
unsigned int cs;
|
||||
unsigned long flags;
|
||||
unsigned int baud, scale;
|
||||
unsigned int baud, scale, step;
|
||||
|
||||
/* Only CS8 is supported */
|
||||
new->c_cflag &= ~CSIZE;
|
||||
@@ -191,8 +252,8 @@ static void ar933x_uart_set_termios(struct uart_port *port,
|
||||
/* Mark/space parity is not supported */
|
||||
new->c_cflag &= ~CMSPAR;
|
||||
|
||||
baud = uart_get_baud_rate(port, new, old, 0, port->uartclk / 16);
|
||||
scale = (port->uartclk / (16 * baud)) - 1;
|
||||
baud = uart_get_baud_rate(port, new, old, up->min_baud, up->max_baud);
|
||||
ar933x_uart_get_scale_step(port->uartclk, baud, &scale, &step);
|
||||
|
||||
/*
|
||||
* Ok, we're now changing the port state. Do it with
|
||||
@@ -200,6 +261,10 @@ static void ar933x_uart_set_termios(struct uart_port *port,
|
||||
*/
|
||||
spin_lock_irqsave(&up->port.lock, flags);
|
||||
|
||||
/* disable the UART */
|
||||
ar933x_uart_rmw_clear(up, AR933X_UART_CS_REG,
|
||||
AR933X_UART_CS_IF_MODE_M << AR933X_UART_CS_IF_MODE_S);
|
||||
|
||||
/* Update the per-port timeout. */
|
||||
uart_update_timeout(port, new->c_cflag, baud);
|
||||
|
||||
@@ -210,7 +275,7 @@ static void ar933x_uart_set_termios(struct uart_port *port,
|
||||
up->port.ignore_status_mask |= AR933X_DUMMY_STATUS_RD;
|
||||
|
||||
ar933x_uart_write(up, AR933X_UART_CLOCK_REG,
|
||||
scale << AR933X_UART_CLOCK_SCALE_S | 8192);
|
||||
scale << AR933X_UART_CLOCK_SCALE_S | step);
|
||||
|
||||
/* setup configuration register */
|
||||
ar933x_uart_rmw(up, AR933X_UART_CS_REG, AR933X_UART_CS_PARITY_M, cs);
|
||||
@@ -219,6 +284,11 @@ static void ar933x_uart_set_termios(struct uart_port *port,
|
||||
ar933x_uart_rmw_set(up, AR933X_UART_CS_REG,
|
||||
AR933X_UART_CS_HOST_INT_EN);
|
||||
|
||||
/* reenable the UART */
|
||||
ar933x_uart_rmw(up, AR933X_UART_CS_REG,
|
||||
AR933X_UART_CS_IF_MODE_M << AR933X_UART_CS_IF_MODE_S,
|
||||
AR933X_UART_CS_IF_MODE_DCE << AR933X_UART_CS_IF_MODE_S);
|
||||
|
||||
spin_unlock_irqrestore(&up->port.lock, flags);
|
||||
|
||||
if (tty_termios_baud_rate(new))
|
||||
@@ -401,6 +471,8 @@ static void ar933x_uart_config_port(struct uart_port *port, int flags)
|
||||
static int ar933x_uart_verify_port(struct uart_port *port,
|
||||
struct serial_struct *ser)
|
||||
{
|
||||
struct ar933x_uart_port *up = (struct ar933x_uart_port *) port;
|
||||
|
||||
if (ser->type != PORT_UNKNOWN &&
|
||||
ser->type != PORT_AR933X)
|
||||
return -EINVAL;
|
||||
@@ -408,7 +480,8 @@ static int ar933x_uart_verify_port(struct uart_port *port,
|
||||
if (ser->irq < 0 || ser->irq >= NR_IRQS)
|
||||
return -EINVAL;
|
||||
|
||||
if (ser->baud_base < 28800)
|
||||
if (ser->baud_base < up->min_baud ||
|
||||
ser->baud_base > up->max_baud)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
@@ -554,13 +627,14 @@ static struct uart_driver ar933x_uart_driver = {
|
||||
.cons = AR933X_SERIAL_CONSOLE,
|
||||
};
|
||||
|
||||
static int __devinit ar933x_uart_probe(struct platform_device *pdev)
|
||||
static int ar933x_uart_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct ar933x_uart_platform_data *pdata;
|
||||
struct ar933x_uart_port *up;
|
||||
struct uart_port *port;
|
||||
struct resource *mem_res;
|
||||
struct resource *irq_res;
|
||||
unsigned int baud;
|
||||
int id;
|
||||
int ret;
|
||||
|
||||
@@ -611,6 +685,12 @@ static int __devinit ar933x_uart_probe(struct platform_device *pdev)
|
||||
port->fifosize = AR933X_UART_FIFO_SIZE;
|
||||
port->ops = &ar933x_uart_ops;
|
||||
|
||||
baud = ar933x_uart_get_baud(port->uartclk, AR933X_UART_MAX_SCALE, 1);
|
||||
up->min_baud = max_t(unsigned int, baud, AR933X_UART_MIN_BAUD);
|
||||
|
||||
baud = ar933x_uart_get_baud(port->uartclk, 0, AR933X_UART_MAX_STEP);
|
||||
up->max_baud = min_t(unsigned int, baud, AR933X_UART_MAX_BAUD);
|
||||
|
||||
ar933x_uart_add_console_port(up);
|
||||
|
||||
ret = uart_add_one_port(&ar933x_uart_driver, &up->port);
|
||||
@@ -627,7 +707,7 @@ err_free_up:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit ar933x_uart_remove(struct platform_device *pdev)
|
||||
static int ar933x_uart_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct ar933x_uart_port *up;
|
||||
|
||||
@@ -645,7 +725,7 @@ static int __devexit ar933x_uart_remove(struct platform_device *pdev)
|
||||
|
||||
static struct platform_driver ar933x_uart_platform_driver = {
|
||||
.probe = ar933x_uart_probe,
|
||||
.remove = __devexit_p(ar933x_uart_remove),
|
||||
.remove = ar933x_uart_remove,
|
||||
.driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
|
746
drivers/tty/serial/arc_uart.c
Normal file
746
drivers/tty/serial/arc_uart.c
Normal file
@@ -0,0 +1,746 @@
|
||||
/*
|
||||
* ARC On-Chip(fpga) UART Driver
|
||||
*
|
||||
* Copyright (C) 2010-2012 Synopsys, Inc. (www.synopsys.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* vineetg: July 10th 2012
|
||||
* -Decoupled the driver from arch/arc
|
||||
* +Using platform_get_resource() for irq/membase (thx to bfin_uart.c)
|
||||
* +Using early_platform_xxx() for early console (thx to mach-shmobile/xxx)
|
||||
*
|
||||
* Vineetg: Aug 21st 2010
|
||||
* -Is uart_tx_stopped() not done in tty write path as it has already been
|
||||
* taken care of, in serial core
|
||||
*
|
||||
* Vineetg: Aug 18th 2010
|
||||
* -New Serial Core based ARC UART driver
|
||||
* -Derived largely from blackfin driver albiet with some major tweaks
|
||||
*
|
||||
* TODO:
|
||||
* -check if sysreq works
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_SERIAL_ARC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
|
||||
#define SUPPORT_SYSRQ
|
||||
#endif
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/sysrq.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/tty_flip.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
/*************************************
|
||||
* ARC UART Hardware Specs
|
||||
************************************/
|
||||
#define ARC_UART_TX_FIFO_SIZE 1
|
||||
|
||||
/*
|
||||
* UART Register set (this is not a Standards Compliant IP)
|
||||
* Also each reg is Word aligned, but only 8 bits wide
|
||||
*/
|
||||
#define R_ID0 0
|
||||
#define R_ID1 4
|
||||
#define R_ID2 8
|
||||
#define R_ID3 12
|
||||
#define R_DATA 16
|
||||
#define R_STS 20
|
||||
#define R_BAUDL 24
|
||||
#define R_BAUDH 28
|
||||
|
||||
/* Bits for UART Status Reg (R/W) */
|
||||
#define RXIENB 0x04 /* Receive Interrupt Enable */
|
||||
#define TXIENB 0x40 /* Transmit Interrupt Enable */
|
||||
|
||||
#define RXEMPTY 0x20 /* Receive FIFO Empty: No char receivede */
|
||||
#define TXEMPTY 0x80 /* Transmit FIFO Empty, thus char can be written into */
|
||||
|
||||
#define RXFULL 0x08 /* Receive FIFO full */
|
||||
#define RXFULL1 0x10 /* Receive FIFO has space for 1 char (tot space=4) */
|
||||
|
||||
#define RXFERR 0x01 /* Frame Error: Stop Bit not detected */
|
||||
#define RXOERR 0x02 /* OverFlow Err: Char recv but RXFULL still set */
|
||||
|
||||
/* Uart bit fiddling helpers: lowest level */
|
||||
#define RBASE(uart, reg) (uart->port.membase + reg)
|
||||
#define UART_REG_SET(u, r, v) writeb((v), RBASE(u, r))
|
||||
#define UART_REG_GET(u, r) readb(RBASE(u, r))
|
||||
|
||||
#define UART_REG_OR(u, r, v) UART_REG_SET(u, r, UART_REG_GET(u, r) | (v))
|
||||
#define UART_REG_CLR(u, r, v) UART_REG_SET(u, r, UART_REG_GET(u, r) & ~(v))
|
||||
|
||||
/* Uart bit fiddling helpers: API level */
|
||||
#define UART_SET_DATA(uart, val) UART_REG_SET(uart, R_DATA, val)
|
||||
#define UART_GET_DATA(uart) UART_REG_GET(uart, R_DATA)
|
||||
|
||||
#define UART_SET_BAUDH(uart, val) UART_REG_SET(uart, R_BAUDH, val)
|
||||
#define UART_SET_BAUDL(uart, val) UART_REG_SET(uart, R_BAUDL, val)
|
||||
|
||||
#define UART_CLR_STATUS(uart, val) UART_REG_CLR(uart, R_STS, val)
|
||||
#define UART_GET_STATUS(uart) UART_REG_GET(uart, R_STS)
|
||||
|
||||
#define UART_ALL_IRQ_DISABLE(uart) UART_REG_CLR(uart, R_STS, RXIENB|TXIENB)
|
||||
#define UART_RX_IRQ_DISABLE(uart) UART_REG_CLR(uart, R_STS, RXIENB)
|
||||
#define UART_TX_IRQ_DISABLE(uart) UART_REG_CLR(uart, R_STS, TXIENB)
|
||||
|
||||
#define UART_ALL_IRQ_ENABLE(uart) UART_REG_OR(uart, R_STS, RXIENB|TXIENB)
|
||||
#define UART_RX_IRQ_ENABLE(uart) UART_REG_OR(uart, R_STS, RXIENB)
|
||||
#define UART_TX_IRQ_ENABLE(uart) UART_REG_OR(uart, R_STS, TXIENB)
|
||||
|
||||
#define ARC_SERIAL_DEV_NAME "ttyARC"
|
||||
|
||||
struct arc_uart_port {
|
||||
struct uart_port port;
|
||||
unsigned long baud;
|
||||
int is_emulated; /* H/w vs. Instruction Set Simulator */
|
||||
};
|
||||
|
||||
#define to_arc_port(uport) container_of(uport, struct arc_uart_port, port)
|
||||
|
||||
static struct arc_uart_port arc_uart_ports[CONFIG_SERIAL_ARC_NR_PORTS];
|
||||
|
||||
#ifdef CONFIG_SERIAL_ARC_CONSOLE
|
||||
static struct console arc_console;
|
||||
#endif
|
||||
|
||||
#define DRIVER_NAME "arc-uart"
|
||||
|
||||
static struct uart_driver arc_uart_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.driver_name = DRIVER_NAME,
|
||||
.dev_name = ARC_SERIAL_DEV_NAME,
|
||||
.major = 0,
|
||||
.minor = 0,
|
||||
.nr = CONFIG_SERIAL_ARC_NR_PORTS,
|
||||
#ifdef CONFIG_SERIAL_ARC_CONSOLE
|
||||
.cons = &arc_console,
|
||||
#endif
|
||||
};
|
||||
|
||||
static void arc_serial_stop_rx(struct uart_port *port)
|
||||
{
|
||||
struct arc_uart_port *uart = to_arc_port(port);
|
||||
|
||||
UART_RX_IRQ_DISABLE(uart);
|
||||
}
|
||||
|
||||
static void arc_serial_stop_tx(struct uart_port *port)
|
||||
{
|
||||
struct arc_uart_port *uart = to_arc_port(port);
|
||||
|
||||
while (!(UART_GET_STATUS(uart) & TXEMPTY))
|
||||
cpu_relax();
|
||||
|
||||
UART_TX_IRQ_DISABLE(uart);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return TIOCSER_TEMT when transmitter is not busy.
|
||||
*/
|
||||
static unsigned int arc_serial_tx_empty(struct uart_port *port)
|
||||
{
|
||||
struct arc_uart_port *uart = to_arc_port(port);
|
||||
unsigned int stat;
|
||||
|
||||
stat = UART_GET_STATUS(uart);
|
||||
if (stat & TXEMPTY)
|
||||
return TIOCSER_TEMT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Driver internal routine, used by both tty(serial core) as well as tx-isr
|
||||
* -Called under spinlock in either cases
|
||||
* -also tty->stopped / tty->hw_stopped has already been checked
|
||||
* = by uart_start( ) before calling us
|
||||
* = tx_ist checks that too before calling
|
||||
*/
|
||||
static void arc_serial_tx_chars(struct arc_uart_port *uart)
|
||||
{
|
||||
struct circ_buf *xmit = &uart->port.state->xmit;
|
||||
int sent = 0;
|
||||
unsigned char ch;
|
||||
|
||||
if (unlikely(uart->port.x_char)) {
|
||||
UART_SET_DATA(uart, uart->port.x_char);
|
||||
uart->port.icount.tx++;
|
||||
uart->port.x_char = 0;
|
||||
sent = 1;
|
||||
} else if (xmit->tail != xmit->head) { /* TODO: uart_circ_empty */
|
||||
ch = xmit->buf[xmit->tail];
|
||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||
uart->port.icount.tx++;
|
||||
while (!(UART_GET_STATUS(uart) & TXEMPTY))
|
||||
cpu_relax();
|
||||
UART_SET_DATA(uart, ch);
|
||||
sent = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* If num chars in xmit buffer are too few, ask tty layer for more.
|
||||
* By Hard ISR to schedule processing in software interrupt part
|
||||
*/
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(&uart->port);
|
||||
|
||||
if (sent)
|
||||
UART_TX_IRQ_ENABLE(uart);
|
||||
}
|
||||
|
||||
/*
|
||||
* port is locked and interrupts are disabled
|
||||
* uart_start( ) calls us under the port spinlock irqsave
|
||||
*/
|
||||
static void arc_serial_start_tx(struct uart_port *port)
|
||||
{
|
||||
struct arc_uart_port *uart = to_arc_port(port);
|
||||
|
||||
arc_serial_tx_chars(uart);
|
||||
}
|
||||
|
||||
static void arc_serial_rx_chars(struct arc_uart_port *uart)
|
||||
{
|
||||
struct tty_struct *tty = tty_port_tty_get(&uart->port.state->port);
|
||||
unsigned int status, ch, flg = 0;
|
||||
|
||||
if (!tty)
|
||||
return;
|
||||
|
||||
/*
|
||||
* UART has 4 deep RX-FIFO. Driver's recongnition of this fact
|
||||
* is very subtle. Here's how ...
|
||||
* Upon getting a RX-Intr, such that RX-EMPTY=0, meaning data available,
|
||||
* driver reads the DATA Reg and keeps doing that in a loop, until
|
||||
* RX-EMPTY=1. Multiple chars being avail, with a single Interrupt,
|
||||
* before RX-EMPTY=0, implies some sort of buffering going on in the
|
||||
* controller, which is indeed the Rx-FIFO.
|
||||
*/
|
||||
while (!((status = UART_GET_STATUS(uart)) & RXEMPTY)) {
|
||||
|
||||
ch = UART_GET_DATA(uart);
|
||||
uart->port.icount.rx++;
|
||||
|
||||
if (unlikely(status & (RXOERR | RXFERR))) {
|
||||
if (status & RXOERR) {
|
||||
uart->port.icount.overrun++;
|
||||
flg = TTY_OVERRUN;
|
||||
UART_CLR_STATUS(uart, RXOERR);
|
||||
}
|
||||
|
||||
if (status & RXFERR) {
|
||||
uart->port.icount.frame++;
|
||||
flg = TTY_FRAME;
|
||||
UART_CLR_STATUS(uart, RXFERR);
|
||||
}
|
||||
} else
|
||||
flg = TTY_NORMAL;
|
||||
|
||||
if (unlikely(uart_handle_sysrq_char(&uart->port, ch)))
|
||||
goto done;
|
||||
|
||||
uart_insert_char(&uart->port, status, RXOERR, ch, flg);
|
||||
|
||||
done:
|
||||
tty_flip_buffer_push(tty);
|
||||
}
|
||||
|
||||
tty_kref_put(tty);
|
||||
}
|
||||
|
||||
/*
|
||||
* A note on the Interrupt handling state machine of this driver
|
||||
*
|
||||
* kernel printk writes funnel thru the console driver framework and in order
|
||||
* to keep things simple as well as efficient, it writes to UART in polled
|
||||
* mode, in one shot, and exits.
|
||||
*
|
||||
* OTOH, Userland output (via tty layer), uses interrupt based writes as there
|
||||
* can be undeterministic delay between char writes.
|
||||
*
|
||||
* Thus Rx-interrupts are always enabled, while tx-interrupts are by default
|
||||
* disabled.
|
||||
*
|
||||
* When tty has some data to send out, serial core calls driver's start_tx
|
||||
* which
|
||||
* -checks-if-tty-buffer-has-char-to-send
|
||||
* -writes-data-to-uart
|
||||
* -enable-tx-intr
|
||||
*
|
||||
* Once data bits are pushed out, controller raises the Tx-room-avail-Interrupt.
|
||||
* The first thing Tx ISR does is disable further Tx interrupts (as this could
|
||||
* be the last char to send, before settling down into the quiet polled mode).
|
||||
* It then calls the exact routine used by tty layer write to send out any
|
||||
* more char in tty buffer. In case of sending, it re-enables Tx-intr. In case
|
||||
* of no data, it remains disabled.
|
||||
* This is how the transmit state machine is dynamically switched on/off
|
||||
*/
|
||||
|
||||
static irqreturn_t arc_serial_isr(int irq, void *dev_id)
|
||||
{
|
||||
struct arc_uart_port *uart = dev_id;
|
||||
unsigned int status;
|
||||
|
||||
status = UART_GET_STATUS(uart);
|
||||
|
||||
/*
|
||||
* Single IRQ for both Rx (data available) Tx (room available) Interrupt
|
||||
* notifications from the UART Controller.
|
||||
* To demultiplex between the two, we check the relevant bits
|
||||
*/
|
||||
if ((status & RXIENB) && !(status & RXEMPTY)) {
|
||||
|
||||
/* already in ISR, no need of xx_irqsave */
|
||||
spin_lock(&uart->port.lock);
|
||||
arc_serial_rx_chars(uart);
|
||||
spin_unlock(&uart->port.lock);
|
||||
}
|
||||
|
||||
if ((status & TXIENB) && (status & TXEMPTY)) {
|
||||
|
||||
/* Unconditionally disable further Tx-Interrupts.
|
||||
* will be enabled by tx_chars() if needed.
|
||||
*/
|
||||
UART_TX_IRQ_DISABLE(uart);
|
||||
|
||||
spin_lock(&uart->port.lock);
|
||||
|
||||
if (!uart_tx_stopped(&uart->port))
|
||||
arc_serial_tx_chars(uart);
|
||||
|
||||
spin_unlock(&uart->port.lock);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static unsigned int arc_serial_get_mctrl(struct uart_port *port)
|
||||
{
|
||||
/*
|
||||
* Pretend we have a Modem status reg and following bits are
|
||||
* always set, to satify the serial core state machine
|
||||
* (DSR) Data Set Ready
|
||||
* (CTS) Clear To Send
|
||||
* (CAR) Carrier Detect
|
||||
*/
|
||||
return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
|
||||
}
|
||||
|
||||
static void arc_serial_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||
{
|
||||
/* MCR not present */
|
||||
}
|
||||
|
||||
/* Enable Modem Status Interrupts */
|
||||
|
||||
static void arc_serial_enable_ms(struct uart_port *port)
|
||||
{
|
||||
/* MSR not present */
|
||||
}
|
||||
|
||||
static void arc_serial_break_ctl(struct uart_port *port, int break_state)
|
||||
{
|
||||
/* ARC UART doesn't support sending Break signal */
|
||||
}
|
||||
|
||||
static int arc_serial_startup(struct uart_port *port)
|
||||
{
|
||||
struct arc_uart_port *uart = to_arc_port(port);
|
||||
|
||||
/* Before we hook up the ISR, Disable all UART Interrupts */
|
||||
UART_ALL_IRQ_DISABLE(uart);
|
||||
|
||||
if (request_irq(uart->port.irq, arc_serial_isr, 0, "arc uart rx-tx",
|
||||
uart)) {
|
||||
dev_warn(uart->port.dev, "Unable to attach ARC UART intr\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
UART_RX_IRQ_ENABLE(uart); /* Only Rx IRQ enabled to begin with */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This is not really needed */
|
||||
static void arc_serial_shutdown(struct uart_port *port)
|
||||
{
|
||||
struct arc_uart_port *uart = to_arc_port(port);
|
||||
free_irq(uart->port.irq, uart);
|
||||
}
|
||||
|
||||
static void
|
||||
arc_serial_set_termios(struct uart_port *port, struct ktermios *new,
|
||||
struct ktermios *old)
|
||||
{
|
||||
struct arc_uart_port *uart = to_arc_port(port);
|
||||
unsigned int baud, uartl, uarth, hw_val;
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
* Use the generic handler so that any specially encoded baud rates
|
||||
* such as SPD_xx flags or "%B0" can be handled
|
||||
* Max Baud I suppose will not be more than current 115K * 4
|
||||
* Formula for ARC UART is: hw-val = ((CLK/(BAUD*4)) -1)
|
||||
* spread over two 8-bit registers
|
||||
*/
|
||||
baud = uart_get_baud_rate(port, new, old, 0, 460800);
|
||||
|
||||
hw_val = port->uartclk / (uart->baud * 4) - 1;
|
||||
uartl = hw_val & 0xFF;
|
||||
uarth = (hw_val >> 8) & 0xFF;
|
||||
|
||||
/*
|
||||
* UART ISS(Instruction Set simulator) emulation has a subtle bug:
|
||||
* A existing value of Baudh = 0 is used as a indication to startup
|
||||
* it's internal state machine.
|
||||
* Thus if baudh is set to 0, 2 times, it chokes.
|
||||
* This happens with BAUD=115200 and the formaula above
|
||||
* Until that is fixed, when running on ISS, we will set baudh to !0
|
||||
*/
|
||||
if (uart->is_emulated)
|
||||
uarth = 1;
|
||||
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
|
||||
UART_ALL_IRQ_DISABLE(uart);
|
||||
|
||||
UART_SET_BAUDL(uart, uartl);
|
||||
UART_SET_BAUDH(uart, uarth);
|
||||
|
||||
UART_RX_IRQ_ENABLE(uart);
|
||||
|
||||
/*
|
||||
* UART doesn't support Parity/Hardware Flow Control;
|
||||
* Only supports 8N1 character size
|
||||
*/
|
||||
new->c_cflag &= ~(CMSPAR|CRTSCTS|CSIZE);
|
||||
new->c_cflag |= CS8;
|
||||
|
||||
if (old)
|
||||
tty_termios_copy_hw(new, old);
|
||||
|
||||
/* Don't rewrite B0 */
|
||||
if (tty_termios_baud_rate(new))
|
||||
tty_termios_encode_baud_rate(new, baud, baud);
|
||||
|
||||
uart_update_timeout(port, new->c_cflag, baud);
|
||||
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
}
|
||||
|
||||
static const char *arc_serial_type(struct uart_port *port)
|
||||
{
|
||||
struct arc_uart_port *uart = to_arc_port(port);
|
||||
|
||||
return uart->port.type == PORT_ARC ? DRIVER_NAME : NULL;
|
||||
}
|
||||
|
||||
static void arc_serial_release_port(struct uart_port *port)
|
||||
{
|
||||
}
|
||||
|
||||
static int arc_serial_request_port(struct uart_port *port)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify the new serial_struct (for TIOCSSERIAL).
|
||||
*/
|
||||
static int
|
||||
arc_serial_verify_port(struct uart_port *port, struct serial_struct *ser)
|
||||
{
|
||||
if (port->type != PORT_UNKNOWN && ser->type != PORT_ARC)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Configure/autoconfigure the port.
|
||||
*/
|
||||
static void arc_serial_config_port(struct uart_port *port, int flags)
|
||||
{
|
||||
struct arc_uart_port *uart = to_arc_port(port);
|
||||
|
||||
if (flags & UART_CONFIG_TYPE)
|
||||
uart->port.type = PORT_ARC;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_ARC_CONSOLE)
|
||||
|
||||
static void arc_serial_poll_putchar(struct uart_port *port, unsigned char chr)
|
||||
{
|
||||
struct arc_uart_port *uart = to_arc_port(port);
|
||||
|
||||
while (!(UART_GET_STATUS(uart) & TXEMPTY))
|
||||
cpu_relax();
|
||||
|
||||
UART_SET_DATA(uart, chr);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CONSOLE_POLL
|
||||
static int arc_serial_poll_getchar(struct uart_port *port)
|
||||
{
|
||||
struct arc_uart_port *uart = to_arc_port(port);
|
||||
unsigned char chr;
|
||||
|
||||
while (!(UART_GET_STATUS(uart) & RXEMPTY))
|
||||
cpu_relax();
|
||||
|
||||
chr = UART_GET_DATA(uart);
|
||||
return chr;
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct uart_ops arc_serial_pops = {
|
||||
.tx_empty = arc_serial_tx_empty,
|
||||
.set_mctrl = arc_serial_set_mctrl,
|
||||
.get_mctrl = arc_serial_get_mctrl,
|
||||
.stop_tx = arc_serial_stop_tx,
|
||||
.start_tx = arc_serial_start_tx,
|
||||
.stop_rx = arc_serial_stop_rx,
|
||||
.enable_ms = arc_serial_enable_ms,
|
||||
.break_ctl = arc_serial_break_ctl,
|
||||
.startup = arc_serial_startup,
|
||||
.shutdown = arc_serial_shutdown,
|
||||
.set_termios = arc_serial_set_termios,
|
||||
.type = arc_serial_type,
|
||||
.release_port = arc_serial_release_port,
|
||||
.request_port = arc_serial_request_port,
|
||||
.config_port = arc_serial_config_port,
|
||||
.verify_port = arc_serial_verify_port,
|
||||
#ifdef CONFIG_CONSOLE_POLL
|
||||
.poll_put_char = arc_serial_poll_putchar,
|
||||
.poll_get_char = arc_serial_poll_getchar,
|
||||
#endif
|
||||
};
|
||||
|
||||
static int
|
||||
arc_uart_init_one(struct platform_device *pdev, struct arc_uart_port *uart)
|
||||
{
|
||||
struct resource *res, *res2;
|
||||
unsigned long *plat_data;
|
||||
|
||||
if (pdev->id < 0 || pdev->id >= CONFIG_SERIAL_ARC_NR_PORTS) {
|
||||
dev_err(&pdev->dev, "Wrong uart platform device id.\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
plat_data = ((unsigned long *)(pdev->dev.platform_data));
|
||||
uart->baud = plat_data[0];
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res)
|
||||
return -ENODEV;
|
||||
|
||||
res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
||||
if (!res2)
|
||||
return -ENODEV;
|
||||
|
||||
uart->port.mapbase = res->start;
|
||||
uart->port.membase = ioremap_nocache(res->start, resource_size(res));
|
||||
if (!uart->port.membase)
|
||||
/* No point of dev_err since UART itself is hosed here */
|
||||
return -ENXIO;
|
||||
|
||||
uart->port.irq = res2->start;
|
||||
uart->port.dev = &pdev->dev;
|
||||
uart->port.iotype = UPIO_MEM;
|
||||
uart->port.flags = UPF_BOOT_AUTOCONF;
|
||||
uart->port.line = pdev->id;
|
||||
uart->port.ops = &arc_serial_pops;
|
||||
|
||||
uart->port.uartclk = plat_data[1];
|
||||
uart->port.fifosize = ARC_UART_TX_FIFO_SIZE;
|
||||
|
||||
/*
|
||||
* uart_insert_char( ) uses it in decideding whether to ignore a
|
||||
* char or not. Explicitly setting it here, removes the subtelty
|
||||
*/
|
||||
uart->port.ignore_status_mask = 0;
|
||||
|
||||
/* Real Hardware vs. emulated to work around a bug */
|
||||
uart->is_emulated = !!plat_data[2];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SERIAL_ARC_CONSOLE
|
||||
|
||||
static int arc_serial_console_setup(struct console *co, char *options)
|
||||
{
|
||||
struct uart_port *port;
|
||||
int baud = 115200;
|
||||
int bits = 8;
|
||||
int parity = 'n';
|
||||
int flow = 'n';
|
||||
|
||||
if (co->index < 0 || co->index >= CONFIG_SERIAL_ARC_NR_PORTS)
|
||||
return -ENODEV;
|
||||
|
||||
/*
|
||||
* The uart port backing the console (e.g. ttyARC1) might not have been
|
||||
* init yet. If so, defer the console setup to after the port.
|
||||
*/
|
||||
port = &arc_uart_ports[co->index].port;
|
||||
if (!port->membase)
|
||||
return -ENODEV;
|
||||
|
||||
if (options)
|
||||
uart_parse_options(options, &baud, &parity, &bits, &flow);
|
||||
|
||||
/*
|
||||
* Serial core will call port->ops->set_termios( )
|
||||
* which will set the baud reg
|
||||
*/
|
||||
return uart_set_options(port, co, baud, parity, bits, flow);
|
||||
}
|
||||
|
||||
static void arc_serial_console_putchar(struct uart_port *port, int ch)
|
||||
{
|
||||
arc_serial_poll_putchar(port, (unsigned char)ch);
|
||||
}
|
||||
|
||||
/*
|
||||
* Interrupts are disabled on entering
|
||||
*/
|
||||
static void arc_serial_console_write(struct console *co, const char *s,
|
||||
unsigned int count)
|
||||
{
|
||||
struct uart_port *port = &arc_uart_ports[co->index].port;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
uart_console_write(port, s, count, arc_serial_console_putchar);
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
}
|
||||
|
||||
static struct console arc_console = {
|
||||
.name = ARC_SERIAL_DEV_NAME,
|
||||
.write = arc_serial_console_write,
|
||||
.device = uart_console_device,
|
||||
.setup = arc_serial_console_setup,
|
||||
.flags = CON_PRINTBUFFER,
|
||||
.index = -1,
|
||||
.data = &arc_uart_driver
|
||||
};
|
||||
|
||||
static __init void early_serial_write(struct console *con, const char *s,
|
||||
unsigned int n)
|
||||
{
|
||||
struct uart_port *port = &arc_uart_ports[con->index].port;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < n; i++, s++) {
|
||||
if (*s == '\n')
|
||||
arc_serial_poll_putchar(port, '\r');
|
||||
arc_serial_poll_putchar(port, *s);
|
||||
}
|
||||
}
|
||||
|
||||
static struct __initdata console arc_early_serial_console = {
|
||||
.name = "early_ARCuart",
|
||||
.write = early_serial_write,
|
||||
.flags = CON_PRINTBUFFER | CON_BOOT,
|
||||
.index = -1
|
||||
};
|
||||
|
||||
static int arc_serial_probe_earlyprintk(struct platform_device *pdev)
|
||||
{
|
||||
arc_early_serial_console.index = pdev->id;
|
||||
|
||||
arc_uart_init_one(pdev, &arc_uart_ports[pdev->id]);
|
||||
|
||||
arc_serial_console_setup(&arc_early_serial_console, NULL);
|
||||
|
||||
register_console(&arc_early_serial_console);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static int arc_serial_probe_earlyprintk(struct platform_device *pdev)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
#endif /* CONFIG_SERIAL_ARC_CONSOLE */
|
||||
|
||||
static int arc_serial_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct arc_uart_port *uart;
|
||||
int rc;
|
||||
|
||||
if (is_early_platform_device(pdev))
|
||||
return arc_serial_probe_earlyprintk(pdev);
|
||||
|
||||
uart = &arc_uart_ports[pdev->id];
|
||||
rc = arc_uart_init_one(pdev, uart);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
return uart_add_one_port(&arc_uart_driver, &uart->port);
|
||||
}
|
||||
|
||||
static int arc_serial_remove(struct platform_device *pdev)
|
||||
{
|
||||
/* This will never be called */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver arc_platform_driver = {
|
||||
.probe = arc_serial_probe,
|
||||
.remove = arc_serial_remove,
|
||||
.driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
#ifdef CONFIG_SERIAL_ARC_CONSOLE
|
||||
/*
|
||||
* Register an early platform driver of "earlyprintk" class.
|
||||
* ARCH platform code installs the driver and probes the early devices
|
||||
* The installation could rely on user specifying earlyprintk=xyx in cmd line
|
||||
* or it could be done independently, for all "earlyprintk" class drivers.
|
||||
* [see arch/arc/plat-arcfpga/platform.c]
|
||||
*/
|
||||
early_platform_init("earlyprintk", &arc_platform_driver);
|
||||
|
||||
#endif /* CONFIG_SERIAL_ARC_CONSOLE */
|
||||
|
||||
static int __init arc_serial_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = uart_register_driver(&arc_uart_driver);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = platform_driver_register(&arc_platform_driver);
|
||||
if (ret)
|
||||
uart_unregister_driver(&arc_uart_driver);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit arc_serial_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&arc_platform_driver);
|
||||
uart_unregister_driver(&arc_uart_driver);
|
||||
}
|
||||
|
||||
module_init(arc_serial_init);
|
||||
module_exit(arc_serial_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("plat-arcfpga/uart");
|
||||
MODULE_AUTHOR("Vineet Gupta");
|
||||
MODULE_DESCRIPTION("ARC(Synopsys) On-Chip(fpga) serial driver");
|
@@ -1424,7 +1424,7 @@ static struct uart_ops atmel_pops = {
|
||||
#endif
|
||||
};
|
||||
|
||||
static void __devinit atmel_of_init_port(struct atmel_uart_port *atmel_port,
|
||||
static void atmel_of_init_port(struct atmel_uart_port *atmel_port,
|
||||
struct device_node *np)
|
||||
{
|
||||
u32 rs485_delay[2];
|
||||
@@ -1459,7 +1459,7 @@ static void __devinit atmel_of_init_port(struct atmel_uart_port *atmel_port,
|
||||
/*
|
||||
* Configure the port from the platform device resource info.
|
||||
*/
|
||||
static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port,
|
||||
static void atmel_init_port(struct atmel_uart_port *atmel_port,
|
||||
struct platform_device *pdev)
|
||||
{
|
||||
struct uart_port *port = &atmel_port->uart;
|
||||
@@ -1767,7 +1767,7 @@ static int atmel_serial_resume(struct platform_device *pdev)
|
||||
#define atmel_serial_resume NULL
|
||||
#endif
|
||||
|
||||
static int __devinit atmel_serial_probe(struct platform_device *pdev)
|
||||
static int atmel_serial_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct atmel_uart_port *port;
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
@@ -1859,7 +1859,7 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit atmel_serial_remove(struct platform_device *pdev)
|
||||
static int atmel_serial_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct uart_port *port = platform_get_drvdata(pdev);
|
||||
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
|
||||
@@ -1884,7 +1884,7 @@ static int __devexit atmel_serial_remove(struct platform_device *pdev)
|
||||
|
||||
static struct platform_driver atmel_serial_driver = {
|
||||
.probe = atmel_serial_probe,
|
||||
.remove = __devexit_p(atmel_serial_remove),
|
||||
.remove = atmel_serial_remove,
|
||||
.suspend = atmel_serial_suspend,
|
||||
.resume = atmel_serial_resume,
|
||||
.driver = {
|
||||
|
@@ -801,7 +801,7 @@ static struct uart_driver bcm_uart_driver = {
|
||||
/*
|
||||
* platform driver probe/remove callback
|
||||
*/
|
||||
static int __devinit bcm_uart_probe(struct platform_device *pdev)
|
||||
static int bcm_uart_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *res_mem, *res_irq;
|
||||
struct uart_port *port;
|
||||
@@ -848,7 +848,7 @@ static int __devinit bcm_uart_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit bcm_uart_remove(struct platform_device *pdev)
|
||||
static int bcm_uart_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct uart_port *port;
|
||||
|
||||
@@ -865,7 +865,7 @@ static int __devexit bcm_uart_remove(struct platform_device *pdev)
|
||||
*/
|
||||
static struct platform_driver bcm_uart_platform_driver = {
|
||||
.probe = bcm_uart_probe,
|
||||
.remove = __devexit_p(bcm_uart_remove),
|
||||
.remove = bcm_uart_remove,
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "bcm63xx_uart",
|
||||
|
@@ -740,7 +740,7 @@ static struct dev_pm_ops bfin_sport_uart_dev_pm_ops = {
|
||||
};
|
||||
#endif
|
||||
|
||||
static int __devinit sport_uart_probe(struct platform_device *pdev)
|
||||
static int sport_uart_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *res;
|
||||
struct sport_uart_port *sport;
|
||||
@@ -850,7 +850,7 @@ out_error_free_mem:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit sport_uart_remove(struct platform_device *pdev)
|
||||
static int sport_uart_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct sport_uart_port *sport = platform_get_drvdata(pdev);
|
||||
|
||||
@@ -871,7 +871,7 @@ static int __devexit sport_uart_remove(struct platform_device *pdev)
|
||||
|
||||
static struct platform_driver sport_uart_driver = {
|
||||
.probe = sport_uart_probe,
|
||||
.remove = __devexit_p(sport_uart_remove),
|
||||
.remove = sport_uart_remove,
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
#ifdef CONFIG_PM
|
||||
|
@@ -477,9 +477,9 @@ static void bfin_serial_dma_rx_chars(struct bfin_serial_port *uart)
|
||||
void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart)
|
||||
{
|
||||
int x_pos, pos;
|
||||
unsigned long flags;
|
||||
|
||||
dma_disable_irq_nosync(uart->rx_dma_channel);
|
||||
spin_lock_bh(&uart->rx_lock);
|
||||
spin_lock_irqsave(&uart->rx_lock, flags);
|
||||
|
||||
/* 2D DMA RX buffer ring is used. Because curr_y_count and
|
||||
* curr_x_count can't be read as an atomic operation,
|
||||
@@ -510,8 +510,7 @@ void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart)
|
||||
uart->rx_dma_buf.tail = uart->rx_dma_buf.head;
|
||||
}
|
||||
|
||||
spin_unlock_bh(&uart->rx_lock);
|
||||
dma_enable_irq(uart->rx_dma_channel);
|
||||
spin_unlock_irqrestore(&uart->rx_lock, flags);
|
||||
|
||||
mod_timer(&(uart->rx_dma_timer), jiffies + DMA_RX_FLUSH_JIFFIES);
|
||||
}
|
||||
@@ -800,6 +799,7 @@ bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||
unsigned long flags;
|
||||
unsigned int baud, quot;
|
||||
unsigned int ier, lcr = 0;
|
||||
unsigned long timeout;
|
||||
|
||||
switch (termios->c_cflag & CSIZE) {
|
||||
case CS8:
|
||||
@@ -869,6 +869,14 @@ bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||
|
||||
UART_SET_ANOMALY_THRESHOLD(uart, USEC_PER_SEC / baud * 15);
|
||||
|
||||
/* Wait till the transfer buffer is empty */
|
||||
timeout = jiffies + msecs_to_jiffies(10);
|
||||
while (UART_GET_GCTL(uart) & UCEN && !(UART_GET_LSR(uart) & TEMT))
|
||||
if (time_after(jiffies, timeout)) {
|
||||
dev_warn(port->dev, "timeout waiting for TX buffer empty\n");
|
||||
break;
|
||||
}
|
||||
|
||||
/* Disable UART */
|
||||
ier = UART_GET_IER(uart);
|
||||
UART_PUT_GCTL(uart, UART_GET_GCTL(uart) & ~UCEN);
|
||||
@@ -1390,7 +1398,7 @@ out_error_free_mem:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit bfin_serial_remove(struct platform_device *pdev)
|
||||
static int bfin_serial_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct bfin_serial_port *uart = platform_get_drvdata(pdev);
|
||||
|
||||
@@ -1410,7 +1418,7 @@ static int __devexit bfin_serial_remove(struct platform_device *pdev)
|
||||
|
||||
static struct platform_driver bfin_serial_driver = {
|
||||
.probe = bfin_serial_probe,
|
||||
.remove = __devexit_p(bfin_serial_remove),
|
||||
.remove = bfin_serial_remove,
|
||||
.suspend = bfin_serial_suspend,
|
||||
.resume = bfin_serial_resume,
|
||||
.driver = {
|
||||
|
@@ -10,15 +10,6 @@
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_SERIAL_CLPS711X_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
|
||||
@@ -26,172 +17,169 @@
|
||||
#endif
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/sysrq.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/tty_flip.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/tty_flip.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <asm/irq.h>
|
||||
|
||||
#define UART_NR 2
|
||||
#define UART_CLPS711X_NAME "uart-clps711x"
|
||||
#define UART_CLPS711X_NR 2
|
||||
#define UART_CLPS711X_MAJOR 204
|
||||
#define UART_CLPS711X_MINOR 40
|
||||
|
||||
#define SERIAL_CLPS711X_MAJOR 204
|
||||
#define SERIAL_CLPS711X_MINOR 40
|
||||
#define SERIAL_CLPS711X_NR UART_NR
|
||||
#define UBRLCR(port) ((port)->line ? UBRLCR2 : UBRLCR1)
|
||||
#define UARTDR(port) ((port)->line ? UARTDR2 : UARTDR1)
|
||||
#define SYSFLG(port) ((port)->line ? SYSFLG2 : SYSFLG1)
|
||||
#define SYSCON(port) ((port)->line ? SYSCON2 : SYSCON1)
|
||||
#define TX_IRQ(port) ((port)->line ? IRQ_UTXINT2 : IRQ_UTXINT1)
|
||||
#define RX_IRQ(port) ((port)->line ? IRQ_URXINT2 : IRQ_URXINT1)
|
||||
|
||||
/*
|
||||
* We use the relevant SYSCON register as a base address for these ports.
|
||||
*/
|
||||
#define UBRLCR(port) ((port)->iobase + UBRLCR1 - SYSCON1)
|
||||
#define UARTDR(port) ((port)->iobase + UARTDR1 - SYSCON1)
|
||||
#define SYSFLG(port) ((port)->iobase + SYSFLG1 - SYSCON1)
|
||||
#define SYSCON(port) ((port)->iobase + SYSCON1 - SYSCON1)
|
||||
struct clps711x_port {
|
||||
struct uart_driver uart;
|
||||
struct clk *uart_clk;
|
||||
struct uart_port port[UART_CLPS711X_NR];
|
||||
int tx_enabled[UART_CLPS711X_NR];
|
||||
#ifdef CONFIG_SERIAL_CLPS711X_CONSOLE
|
||||
struct console console;
|
||||
#endif
|
||||
};
|
||||
|
||||
#define TX_IRQ(port) ((port)->irq)
|
||||
#define RX_IRQ(port) ((port)->irq + 1)
|
||||
|
||||
#define UART_ANY_ERR (UARTDR_FRMERR | UARTDR_PARERR | UARTDR_OVERR)
|
||||
|
||||
#define tx_enabled(port) ((port)->unused[0])
|
||||
|
||||
static void clps711xuart_stop_tx(struct uart_port *port)
|
||||
static void uart_clps711x_stop_tx(struct uart_port *port)
|
||||
{
|
||||
if (tx_enabled(port)) {
|
||||
struct clps711x_port *s = dev_get_drvdata(port->dev);
|
||||
|
||||
if (s->tx_enabled[port->line]) {
|
||||
disable_irq(TX_IRQ(port));
|
||||
tx_enabled(port) = 0;
|
||||
s->tx_enabled[port->line] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void clps711xuart_start_tx(struct uart_port *port)
|
||||
static void uart_clps711x_start_tx(struct uart_port *port)
|
||||
{
|
||||
if (!tx_enabled(port)) {
|
||||
struct clps711x_port *s = dev_get_drvdata(port->dev);
|
||||
|
||||
if (!s->tx_enabled[port->line]) {
|
||||
enable_irq(TX_IRQ(port));
|
||||
tx_enabled(port) = 1;
|
||||
s->tx_enabled[port->line] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void clps711xuart_stop_rx(struct uart_port *port)
|
||||
static void uart_clps711x_stop_rx(struct uart_port *port)
|
||||
{
|
||||
disable_irq(RX_IRQ(port));
|
||||
}
|
||||
|
||||
static void clps711xuart_enable_ms(struct uart_port *port)
|
||||
static void uart_clps711x_enable_ms(struct uart_port *port)
|
||||
{
|
||||
/* Do nothing */
|
||||
}
|
||||
|
||||
static irqreturn_t clps711xuart_int_rx(int irq, void *dev_id)
|
||||
static irqreturn_t uart_clps711x_int_rx(int irq, void *dev_id)
|
||||
{
|
||||
struct uart_port *port = dev_id;
|
||||
struct tty_struct *tty = port->state->port.tty;
|
||||
struct tty_struct *tty = tty_port_tty_get(&port->state->port);
|
||||
unsigned int status, ch, flg;
|
||||
|
||||
status = clps_readl(SYSFLG(port));
|
||||
while (!(status & SYSFLG_URXFE)) {
|
||||
ch = clps_readl(UARTDR(port));
|
||||
if (!tty)
|
||||
return IRQ_HANDLED;
|
||||
|
||||
for (;;) {
|
||||
status = clps_readl(SYSFLG(port));
|
||||
if (status & SYSFLG_URXFE)
|
||||
break;
|
||||
|
||||
ch = clps_readw(UARTDR(port));
|
||||
status = ch & (UARTDR_FRMERR | UARTDR_PARERR | UARTDR_OVERR);
|
||||
ch &= 0xff;
|
||||
|
||||
port->icount.rx++;
|
||||
|
||||
flg = TTY_NORMAL;
|
||||
|
||||
/*
|
||||
* Note that the error handling code is
|
||||
* out of the main execution path
|
||||
*/
|
||||
if (unlikely(ch & UART_ANY_ERR)) {
|
||||
if (ch & UARTDR_PARERR)
|
||||
if (unlikely(status)) {
|
||||
if (status & UARTDR_PARERR)
|
||||
port->icount.parity++;
|
||||
else if (ch & UARTDR_FRMERR)
|
||||
else if (status & UARTDR_FRMERR)
|
||||
port->icount.frame++;
|
||||
if (ch & UARTDR_OVERR)
|
||||
else if (status & UARTDR_OVERR)
|
||||
port->icount.overrun++;
|
||||
|
||||
ch &= port->read_status_mask;
|
||||
status &= port->read_status_mask;
|
||||
|
||||
if (ch & UARTDR_PARERR)
|
||||
if (status & UARTDR_PARERR)
|
||||
flg = TTY_PARITY;
|
||||
else if (ch & UARTDR_FRMERR)
|
||||
else if (status & UARTDR_FRMERR)
|
||||
flg = TTY_FRAME;
|
||||
|
||||
#ifdef SUPPORT_SYSRQ
|
||||
port->sysrq = 0;
|
||||
#endif
|
||||
else if (status & UARTDR_OVERR)
|
||||
flg = TTY_OVERRUN;
|
||||
}
|
||||
|
||||
if (uart_handle_sysrq_char(port, ch))
|
||||
goto ignore_char;
|
||||
continue;
|
||||
|
||||
/*
|
||||
* CHECK: does overrun affect the current character?
|
||||
* ASSUMPTION: it does not.
|
||||
*/
|
||||
uart_insert_char(port, ch, UARTDR_OVERR, ch, flg);
|
||||
if (status & port->ignore_status_mask)
|
||||
continue;
|
||||
|
||||
ignore_char:
|
||||
status = clps_readl(SYSFLG(port));
|
||||
uart_insert_char(port, status, UARTDR_OVERR, ch, flg);
|
||||
}
|
||||
|
||||
tty_flip_buffer_push(tty);
|
||||
|
||||
tty_kref_put(tty);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t clps711xuart_int_tx(int irq, void *dev_id)
|
||||
static irqreturn_t uart_clps711x_int_tx(int irq, void *dev_id)
|
||||
{
|
||||
struct uart_port *port = dev_id;
|
||||
struct clps711x_port *s = dev_get_drvdata(port->dev);
|
||||
struct circ_buf *xmit = &port->state->xmit;
|
||||
int count;
|
||||
|
||||
if (port->x_char) {
|
||||
clps_writel(port->x_char, UARTDR(port));
|
||||
clps_writew(port->x_char, UARTDR(port));
|
||||
port->icount.tx++;
|
||||
port->x_char = 0;
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
if (uart_circ_empty(xmit) || uart_tx_stopped(port))
|
||||
goto disable_tx_irq;
|
||||
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
|
||||
disable_irq_nosync(TX_IRQ(port));
|
||||
s->tx_enabled[port->line] = 0;
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
count = port->fifosize >> 1;
|
||||
do {
|
||||
clps_writel(xmit->buf[xmit->tail], UARTDR(port));
|
||||
while (!uart_circ_empty(xmit)) {
|
||||
clps_writew(xmit->buf[xmit->tail], UARTDR(port));
|
||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||
port->icount.tx++;
|
||||
if (uart_circ_empty(xmit))
|
||||
if (clps_readl(SYSFLG(port) & SYSFLG_UTXFF))
|
||||
break;
|
||||
} while (--count > 0);
|
||||
}
|
||||
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(port);
|
||||
|
||||
if (uart_circ_empty(xmit)) {
|
||||
disable_tx_irq:
|
||||
disable_irq_nosync(TX_IRQ(port));
|
||||
tx_enabled(port) = 0;
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static unsigned int clps711xuart_tx_empty(struct uart_port *port)
|
||||
static unsigned int uart_clps711x_tx_empty(struct uart_port *port)
|
||||
{
|
||||
unsigned int status = clps_readl(SYSFLG(port));
|
||||
return status & SYSFLG_UBUSY ? 0 : TIOCSER_TEMT;
|
||||
return (clps_readl(SYSFLG(port) & SYSFLG_UBUSY)) ? 0 : TIOCSER_TEMT;
|
||||
}
|
||||
|
||||
static unsigned int clps711xuart_get_mctrl(struct uart_port *port)
|
||||
static unsigned int uart_clps711x_get_mctrl(struct uart_port *port)
|
||||
{
|
||||
unsigned int port_addr;
|
||||
unsigned int result = 0;
|
||||
unsigned int status;
|
||||
unsigned int status, result = 0;
|
||||
|
||||
port_addr = SYSFLG(port);
|
||||
if (port_addr == SYSFLG1) {
|
||||
if (port->line == 0) {
|
||||
status = clps_readl(SYSFLG1);
|
||||
if (status & SYSFLG1_DCD)
|
||||
result |= TIOCM_CAR;
|
||||
@@ -199,104 +187,86 @@ static unsigned int clps711xuart_get_mctrl(struct uart_port *port)
|
||||
result |= TIOCM_DSR;
|
||||
if (status & SYSFLG1_CTS)
|
||||
result |= TIOCM_CTS;
|
||||
}
|
||||
} else
|
||||
result = TIOCM_DSR | TIOCM_CTS | TIOCM_CAR;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
clps711xuart_set_mctrl_null(struct uart_port *port, unsigned int mctrl)
|
||||
static void uart_clps711x_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||
{
|
||||
/* Do nothing */
|
||||
}
|
||||
|
||||
static void clps711xuart_break_ctl(struct uart_port *port, int break_state)
|
||||
static void uart_clps711x_break_ctl(struct uart_port *port, int break_state)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned int ubrlcr;
|
||||
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
|
||||
ubrlcr = clps_readl(UBRLCR(port));
|
||||
if (break_state == -1)
|
||||
if (break_state)
|
||||
ubrlcr |= UBRLCR_BREAK;
|
||||
else
|
||||
ubrlcr &= ~UBRLCR_BREAK;
|
||||
clps_writel(ubrlcr, UBRLCR(port));
|
||||
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
}
|
||||
|
||||
static int clps711xuart_startup(struct uart_port *port)
|
||||
static int uart_clps711x_startup(struct uart_port *port)
|
||||
{
|
||||
unsigned int syscon;
|
||||
int retval;
|
||||
struct clps711x_port *s = dev_get_drvdata(port->dev);
|
||||
int ret;
|
||||
|
||||
tx_enabled(port) = 1;
|
||||
s->tx_enabled[port->line] = 1;
|
||||
/* Allocate the IRQs */
|
||||
ret = devm_request_irq(port->dev, TX_IRQ(port), uart_clps711x_int_tx,
|
||||
0, UART_CLPS711X_NAME " TX", port);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Allocate the IRQs
|
||||
*/
|
||||
retval = request_irq(TX_IRQ(port), clps711xuart_int_tx, 0,
|
||||
"clps711xuart_tx", port);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
retval = request_irq(RX_IRQ(port), clps711xuart_int_rx, 0,
|
||||
"clps711xuart_rx", port);
|
||||
if (retval) {
|
||||
free_irq(TX_IRQ(port), port);
|
||||
return retval;
|
||||
ret = devm_request_irq(port->dev, RX_IRQ(port), uart_clps711x_int_rx,
|
||||
0, UART_CLPS711X_NAME " RX", port);
|
||||
if (ret) {
|
||||
devm_free_irq(port->dev, TX_IRQ(port), port);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* enable the port
|
||||
*/
|
||||
syscon = clps_readl(SYSCON(port));
|
||||
syscon |= SYSCON_UARTEN;
|
||||
clps_writel(syscon, SYSCON(port));
|
||||
/* Disable break */
|
||||
clps_writel(clps_readl(UBRLCR(port)) & ~UBRLCR_BREAK, UBRLCR(port));
|
||||
|
||||
/* Enable the port */
|
||||
clps_writel(clps_readl(SYSCON(port)) | SYSCON_UARTEN, SYSCON(port));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void clps711xuart_shutdown(struct uart_port *port)
|
||||
static void uart_clps711x_shutdown(struct uart_port *port)
|
||||
{
|
||||
unsigned int ubrlcr, syscon;
|
||||
/* Free the interrupts */
|
||||
devm_free_irq(port->dev, TX_IRQ(port), port);
|
||||
devm_free_irq(port->dev, RX_IRQ(port), port);
|
||||
|
||||
/*
|
||||
* Free the interrupt
|
||||
*/
|
||||
free_irq(TX_IRQ(port), port); /* TX interrupt */
|
||||
free_irq(RX_IRQ(port), port); /* RX interrupt */
|
||||
|
||||
/*
|
||||
* disable the port
|
||||
*/
|
||||
syscon = clps_readl(SYSCON(port));
|
||||
syscon &= ~SYSCON_UARTEN;
|
||||
clps_writel(syscon, SYSCON(port));
|
||||
|
||||
/*
|
||||
* disable break condition and fifos
|
||||
*/
|
||||
ubrlcr = clps_readl(UBRLCR(port));
|
||||
ubrlcr &= ~(UBRLCR_FIFOEN | UBRLCR_BREAK);
|
||||
clps_writel(ubrlcr, UBRLCR(port));
|
||||
/* Disable the port */
|
||||
clps_writel(clps_readl(SYSCON(port)) & ~SYSCON_UARTEN, SYSCON(port));
|
||||
}
|
||||
|
||||
static void
|
||||
clps711xuart_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||
struct ktermios *old)
|
||||
static void uart_clps711x_set_termios(struct uart_port *port,
|
||||
struct ktermios *termios,
|
||||
struct ktermios *old)
|
||||
{
|
||||
unsigned int ubrlcr, baud, quot;
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
* We don't implement CREAD.
|
||||
*/
|
||||
termios->c_cflag |= CREAD;
|
||||
/* Mask termios capabilities we don't support */
|
||||
termios->c_cflag &= ~CMSPAR;
|
||||
termios->c_iflag &= ~(BRKINT | IGNBRK);
|
||||
|
||||
/*
|
||||
* Ask the core to calculate the divisor for us.
|
||||
*/
|
||||
baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
|
||||
/* Ask the core to calculate the divisor for us */
|
||||
baud = uart_get_baud_rate(port, termios, old, port->uartclk / 4096,
|
||||
port->uartclk / 16);
|
||||
quot = uart_get_divisor(port, baud);
|
||||
|
||||
switch (termios->c_cflag & CSIZE) {
|
||||
@@ -309,160 +279,117 @@ clps711xuart_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||
case CS7:
|
||||
ubrlcr = UBRLCR_WRDLEN7;
|
||||
break;
|
||||
default: // CS8
|
||||
case CS8:
|
||||
default:
|
||||
ubrlcr = UBRLCR_WRDLEN8;
|
||||
break;
|
||||
}
|
||||
|
||||
if (termios->c_cflag & CSTOPB)
|
||||
ubrlcr |= UBRLCR_XSTOP;
|
||||
|
||||
if (termios->c_cflag & PARENB) {
|
||||
ubrlcr |= UBRLCR_PRTEN;
|
||||
if (!(termios->c_cflag & PARODD))
|
||||
ubrlcr |= UBRLCR_EVENPRT;
|
||||
}
|
||||
if (port->fifosize > 1)
|
||||
ubrlcr |= UBRLCR_FIFOEN;
|
||||
|
||||
/* Enable FIFO */
|
||||
ubrlcr |= UBRLCR_FIFOEN;
|
||||
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
|
||||
/*
|
||||
* Update the per-port timeout.
|
||||
*/
|
||||
uart_update_timeout(port, termios->c_cflag, baud);
|
||||
|
||||
/* Set read status mask */
|
||||
port->read_status_mask = UARTDR_OVERR;
|
||||
if (termios->c_iflag & INPCK)
|
||||
port->read_status_mask |= UARTDR_PARERR | UARTDR_FRMERR;
|
||||
|
||||
/*
|
||||
* Characters to ignore
|
||||
*/
|
||||
/* Set status ignore mask */
|
||||
port->ignore_status_mask = 0;
|
||||
if (termios->c_iflag & IGNPAR)
|
||||
port->ignore_status_mask |= UARTDR_FRMERR | UARTDR_PARERR;
|
||||
if (termios->c_iflag & IGNBRK) {
|
||||
/*
|
||||
* If we're ignoring parity and break indicators,
|
||||
* ignore overruns to (for real raw support).
|
||||
*/
|
||||
if (termios->c_iflag & IGNPAR)
|
||||
port->ignore_status_mask |= UARTDR_OVERR;
|
||||
}
|
||||
if (!(termios->c_cflag & CREAD))
|
||||
port->ignore_status_mask |= UARTDR_OVERR | UARTDR_PARERR |
|
||||
UARTDR_FRMERR;
|
||||
|
||||
quot -= 1;
|
||||
uart_update_timeout(port, termios->c_cflag, baud);
|
||||
|
||||
clps_writel(ubrlcr | quot, UBRLCR(port));
|
||||
clps_writel(ubrlcr | (quot - 1), UBRLCR(port));
|
||||
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
}
|
||||
|
||||
static const char *clps711xuart_type(struct uart_port *port)
|
||||
static const char *uart_clps711x_type(struct uart_port *port)
|
||||
{
|
||||
return port->type == PORT_CLPS711X ? "CLPS711x" : NULL;
|
||||
return (port->type == PORT_CLPS711X) ? "CLPS711X" : NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Configure/autoconfigure the port.
|
||||
*/
|
||||
static void clps711xuart_config_port(struct uart_port *port, int flags)
|
||||
static void uart_clps711x_config_port(struct uart_port *port, int flags)
|
||||
{
|
||||
if (flags & UART_CONFIG_TYPE)
|
||||
port->type = PORT_CLPS711X;
|
||||
}
|
||||
|
||||
static void clps711xuart_release_port(struct uart_port *port)
|
||||
static void uart_clps711x_release_port(struct uart_port *port)
|
||||
{
|
||||
/* Do nothing */
|
||||
}
|
||||
|
||||
static int clps711xuart_request_port(struct uart_port *port)
|
||||
static int uart_clps711x_request_port(struct uart_port *port)
|
||||
{
|
||||
/* Do nothing */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct uart_ops clps711x_pops = {
|
||||
.tx_empty = clps711xuart_tx_empty,
|
||||
.set_mctrl = clps711xuart_set_mctrl_null,
|
||||
.get_mctrl = clps711xuart_get_mctrl,
|
||||
.stop_tx = clps711xuart_stop_tx,
|
||||
.start_tx = clps711xuart_start_tx,
|
||||
.stop_rx = clps711xuart_stop_rx,
|
||||
.enable_ms = clps711xuart_enable_ms,
|
||||
.break_ctl = clps711xuart_break_ctl,
|
||||
.startup = clps711xuart_startup,
|
||||
.shutdown = clps711xuart_shutdown,
|
||||
.set_termios = clps711xuart_set_termios,
|
||||
.type = clps711xuart_type,
|
||||
.config_port = clps711xuart_config_port,
|
||||
.release_port = clps711xuart_release_port,
|
||||
.request_port = clps711xuart_request_port,
|
||||
};
|
||||
|
||||
static struct uart_port clps711x_ports[UART_NR] = {
|
||||
{
|
||||
.iobase = SYSCON1,
|
||||
.irq = IRQ_UTXINT1, /* IRQ_URXINT1, IRQ_UMSINT */
|
||||
.uartclk = 3686400,
|
||||
.fifosize = 16,
|
||||
.ops = &clps711x_pops,
|
||||
.line = 0,
|
||||
.flags = UPF_BOOT_AUTOCONF,
|
||||
},
|
||||
{
|
||||
.iobase = SYSCON2,
|
||||
.irq = IRQ_UTXINT2, /* IRQ_URXINT2 */
|
||||
.uartclk = 3686400,
|
||||
.fifosize = 16,
|
||||
.ops = &clps711x_pops,
|
||||
.line = 1,
|
||||
.flags = UPF_BOOT_AUTOCONF,
|
||||
}
|
||||
static const struct uart_ops uart_clps711x_ops = {
|
||||
.tx_empty = uart_clps711x_tx_empty,
|
||||
.set_mctrl = uart_clps711x_set_mctrl,
|
||||
.get_mctrl = uart_clps711x_get_mctrl,
|
||||
.stop_tx = uart_clps711x_stop_tx,
|
||||
.start_tx = uart_clps711x_start_tx,
|
||||
.stop_rx = uart_clps711x_stop_rx,
|
||||
.enable_ms = uart_clps711x_enable_ms,
|
||||
.break_ctl = uart_clps711x_break_ctl,
|
||||
.startup = uart_clps711x_startup,
|
||||
.shutdown = uart_clps711x_shutdown,
|
||||
.set_termios = uart_clps711x_set_termios,
|
||||
.type = uart_clps711x_type,
|
||||
.config_port = uart_clps711x_config_port,
|
||||
.release_port = uart_clps711x_release_port,
|
||||
.request_port = uart_clps711x_request_port,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_SERIAL_CLPS711X_CONSOLE
|
||||
static void clps711xuart_console_putchar(struct uart_port *port, int ch)
|
||||
static void uart_clps711x_console_putchar(struct uart_port *port, int ch)
|
||||
{
|
||||
while (clps_readl(SYSFLG(port)) & SYSFLG_UTXFF)
|
||||
barrier();
|
||||
clps_writel(ch, UARTDR(port));
|
||||
|
||||
clps_writew(ch, UARTDR(port));
|
||||
}
|
||||
|
||||
/*
|
||||
* Print a string to the serial port trying not to disturb
|
||||
* any possible real use of the port...
|
||||
*
|
||||
* The console_lock must be held when we get here.
|
||||
*
|
||||
* Note that this is called with interrupts already disabled
|
||||
*/
|
||||
static void
|
||||
clps711xuart_console_write(struct console *co, const char *s,
|
||||
unsigned int count)
|
||||
static void uart_clps711x_console_write(struct console *co, const char *c,
|
||||
unsigned n)
|
||||
{
|
||||
struct uart_port *port = clps711x_ports + co->index;
|
||||
unsigned int status, syscon;
|
||||
struct clps711x_port *s = (struct clps711x_port *)co->data;
|
||||
struct uart_port *port = &s->port[co->index];
|
||||
u32 syscon;
|
||||
|
||||
/*
|
||||
* Ensure that the port is enabled.
|
||||
*/
|
||||
/* Ensure that the port is enabled */
|
||||
syscon = clps_readl(SYSCON(port));
|
||||
clps_writel(syscon | SYSCON_UARTEN, SYSCON(port));
|
||||
|
||||
uart_console_write(port, s, count, clps711xuart_console_putchar);
|
||||
uart_console_write(port, c, n, uart_clps711x_console_putchar);
|
||||
|
||||
/*
|
||||
* Finally, wait for transmitter to become empty
|
||||
* and restore the uart state.
|
||||
*/
|
||||
do {
|
||||
status = clps_readl(SYSFLG(port));
|
||||
} while (status & SYSFLG_UBUSY);
|
||||
/* Wait for transmitter to become empty */
|
||||
while (clps_readl(SYSFLG(port)) & SYSFLG_UBUSY)
|
||||
barrier();
|
||||
|
||||
/* Restore the uart state */
|
||||
clps_writel(syscon, SYSCON(port));
|
||||
}
|
||||
|
||||
static void __init
|
||||
clps711xuart_console_get_options(struct uart_port *port, int *baud,
|
||||
int *parity, int *bits)
|
||||
static void uart_clps711x_console_get_options(struct uart_port *port,
|
||||
int *baud, int *parity,
|
||||
int *bits)
|
||||
{
|
||||
if (clps_readl(SYSCON(port)) & SYSCON_UARTEN) {
|
||||
unsigned int ubrlcr, quot;
|
||||
@@ -487,92 +414,124 @@ clps711xuart_console_get_options(struct uart_port *port, int *baud,
|
||||
}
|
||||
}
|
||||
|
||||
static int __init clps711xuart_console_setup(struct console *co, char *options)
|
||||
static int uart_clps711x_console_setup(struct console *co, char *options)
|
||||
{
|
||||
struct uart_port *port;
|
||||
int baud = 38400;
|
||||
int bits = 8;
|
||||
int parity = 'n';
|
||||
int flow = 'n';
|
||||
|
||||
/*
|
||||
* Check whether an invalid uart number has been specified, and
|
||||
* if so, search for the first available port that does have
|
||||
* console support.
|
||||
*/
|
||||
port = uart_get_console(clps711x_ports, UART_NR, co);
|
||||
int baud = 38400, bits = 8, parity = 'n', flow = 'n';
|
||||
struct clps711x_port *s = (struct clps711x_port *)co->data;
|
||||
struct uart_port *port = &s->port[(co->index > 0) ? co->index : 0];
|
||||
|
||||
if (options)
|
||||
uart_parse_options(options, &baud, &parity, &bits, &flow);
|
||||
else
|
||||
clps711xuart_console_get_options(port, &baud, &parity, &bits);
|
||||
uart_clps711x_console_get_options(port, &baud, &parity, &bits);
|
||||
|
||||
return uart_set_options(port, co, baud, parity, bits, flow);
|
||||
}
|
||||
|
||||
static struct uart_driver clps711x_reg;
|
||||
static struct console clps711x_console = {
|
||||
.name = "ttyCL",
|
||||
.write = clps711xuart_console_write,
|
||||
.device = uart_console_device,
|
||||
.setup = clps711xuart_console_setup,
|
||||
.flags = CON_PRINTBUFFER,
|
||||
.index = -1,
|
||||
.data = &clps711x_reg,
|
||||
};
|
||||
|
||||
static int __init clps711xuart_console_init(void)
|
||||
{
|
||||
register_console(&clps711x_console);
|
||||
return 0;
|
||||
}
|
||||
console_initcall(clps711xuart_console_init);
|
||||
|
||||
#define CLPS711X_CONSOLE &clps711x_console
|
||||
#else
|
||||
#define CLPS711X_CONSOLE NULL
|
||||
#endif
|
||||
|
||||
static struct uart_driver clps711x_reg = {
|
||||
.driver_name = "ttyCL",
|
||||
.dev_name = "ttyCL",
|
||||
.major = SERIAL_CLPS711X_MAJOR,
|
||||
.minor = SERIAL_CLPS711X_MINOR,
|
||||
.nr = UART_NR,
|
||||
|
||||
.cons = CLPS711X_CONSOLE,
|
||||
};
|
||||
|
||||
static int __init clps711xuart_init(void)
|
||||
static int uart_clps711x_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct clps711x_port *s;
|
||||
int ret, i;
|
||||
|
||||
printk(KERN_INFO "Serial: CLPS711x driver\n");
|
||||
s = devm_kzalloc(&pdev->dev, sizeof(struct clps711x_port), GFP_KERNEL);
|
||||
if (!s) {
|
||||
dev_err(&pdev->dev, "Error allocating port structure\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
platform_set_drvdata(pdev, s);
|
||||
|
||||
ret = uart_register_driver(&clps711x_reg);
|
||||
if (ret)
|
||||
return ret;
|
||||
s->uart_clk = devm_clk_get(&pdev->dev, "uart");
|
||||
if (IS_ERR(s->uart_clk)) {
|
||||
dev_err(&pdev->dev, "Can't get UART clocks\n");
|
||||
ret = PTR_ERR(s->uart_clk);
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
for (i = 0; i < UART_NR; i++)
|
||||
uart_add_one_port(&clps711x_reg, &clps711x_ports[i]);
|
||||
s->uart.owner = THIS_MODULE;
|
||||
s->uart.dev_name = "ttyCL";
|
||||
s->uart.major = UART_CLPS711X_MAJOR;
|
||||
s->uart.minor = UART_CLPS711X_MINOR;
|
||||
s->uart.nr = UART_CLPS711X_NR;
|
||||
#ifdef CONFIG_SERIAL_CLPS711X_CONSOLE
|
||||
s->uart.cons = &s->console;
|
||||
s->uart.cons->device = uart_console_device;
|
||||
s->uart.cons->write = uart_clps711x_console_write;
|
||||
s->uart.cons->setup = uart_clps711x_console_setup;
|
||||
s->uart.cons->flags = CON_PRINTBUFFER;
|
||||
s->uart.cons->index = -1;
|
||||
s->uart.cons->data = s;
|
||||
strcpy(s->uart.cons->name, "ttyCL");
|
||||
#endif
|
||||
ret = uart_register_driver(&s->uart);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Registering UART driver failed\n");
|
||||
devm_clk_put(&pdev->dev, s->uart_clk);
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
for (i = 0; i < UART_CLPS711X_NR; i++) {
|
||||
s->port[i].line = i;
|
||||
s->port[i].dev = &pdev->dev;
|
||||
s->port[i].irq = TX_IRQ(&s->port[i]);
|
||||
s->port[i].iobase = SYSCON(&s->port[i]);
|
||||
s->port[i].type = PORT_CLPS711X;
|
||||
s->port[i].fifosize = 16;
|
||||
s->port[i].flags = UPF_SKIP_TEST | UPF_FIXED_TYPE;
|
||||
s->port[i].uartclk = clk_get_rate(s->uart_clk);
|
||||
s->port[i].ops = &uart_clps711x_ops;
|
||||
WARN_ON(uart_add_one_port(&s->uart, &s->port[i]));
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_out:
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int uart_clps711x_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct clps711x_port *s = platform_get_drvdata(pdev);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < UART_CLPS711X_NR; i++)
|
||||
uart_remove_one_port(&s->uart, &s->port[i]);
|
||||
|
||||
devm_clk_put(&pdev->dev, s->uart_clk);
|
||||
uart_unregister_driver(&s->uart);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit clps711xuart_exit(void)
|
||||
static struct platform_driver clps711x_uart_driver = {
|
||||
.driver = {
|
||||
.name = UART_CLPS711X_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = uart_clps711x_probe,
|
||||
.remove = uart_clps711x_remove,
|
||||
};
|
||||
module_platform_driver(clps711x_uart_driver);
|
||||
|
||||
static struct platform_device clps711x_uart_device = {
|
||||
.name = UART_CLPS711X_NAME,
|
||||
};
|
||||
|
||||
static int __init uart_clps711x_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < UART_NR; i++)
|
||||
uart_remove_one_port(&clps711x_reg, &clps711x_ports[i]);
|
||||
|
||||
uart_unregister_driver(&clps711x_reg);
|
||||
return platform_device_register(&clps711x_uart_device);
|
||||
}
|
||||
module_init(uart_clps711x_init);
|
||||
|
||||
module_init(clps711xuart_init);
|
||||
module_exit(clps711xuart_exit);
|
||||
static void __exit uart_clps711x_exit(void)
|
||||
{
|
||||
platform_device_unregister(&clps711x_uart_device);
|
||||
}
|
||||
module_exit(uart_clps711x_exit);
|
||||
|
||||
MODULE_AUTHOR("Deep Blue Solutions Ltd");
|
||||
MODULE_DESCRIPTION("CLPS-711x generic serial driver");
|
||||
MODULE_DESCRIPTION("CLPS711X serial driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS_CHARDEV(SERIAL_CLPS711X_MAJOR, SERIAL_CLPS711X_MINOR);
|
||||
|
@@ -1373,7 +1373,7 @@ static struct uart_driver cpm_reg = {
|
||||
|
||||
static int probe_index;
|
||||
|
||||
static int __devinit cpm_uart_probe(struct platform_device *ofdev)
|
||||
static int cpm_uart_probe(struct platform_device *ofdev)
|
||||
{
|
||||
int index = probe_index++;
|
||||
struct uart_cpm_port *pinfo = &cpm_uart_ports[index];
|
||||
@@ -1396,7 +1396,7 @@ static int __devinit cpm_uart_probe(struct platform_device *ofdev)
|
||||
return uart_add_one_port(&cpm_reg, &pinfo->port);
|
||||
}
|
||||
|
||||
static int __devexit cpm_uart_remove(struct platform_device *ofdev)
|
||||
static int cpm_uart_remove(struct platform_device *ofdev)
|
||||
{
|
||||
struct uart_cpm_port *pinfo = dev_get_drvdata(&ofdev->dev);
|
||||
return uart_remove_one_port(&cpm_reg, &pinfo->port);
|
||||
|
@@ -690,7 +690,7 @@ static int efm32_uart_probe_dt(struct platform_device *pdev,
|
||||
|
||||
}
|
||||
|
||||
static int __devinit efm32_uart_probe(struct platform_device *pdev)
|
||||
static int efm32_uart_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct efm32_uart_port *efm_port;
|
||||
struct resource *res;
|
||||
@@ -764,7 +764,7 @@ err_get_base:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit efm32_uart_remove(struct platform_device *pdev)
|
||||
static int efm32_uart_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct efm32_uart_port *efm_port = platform_get_drvdata(pdev);
|
||||
|
||||
@@ -791,7 +791,7 @@ MODULE_DEVICE_TABLE(of, efm32_uart_dt_ids);
|
||||
|
||||
static struct platform_driver efm32_uart_driver = {
|
||||
.probe = efm32_uart_probe,
|
||||
.remove = __devexit_p(efm32_uart_remove),
|
||||
.remove = efm32_uart_remove,
|
||||
|
||||
.driver = {
|
||||
.name = DRIVER_NAME,
|
||||
|
@@ -175,7 +175,7 @@ static void free_port_memory(struct icom_port *icom_port)
|
||||
}
|
||||
}
|
||||
|
||||
static int __devinit get_port_memory(struct icom_port *icom_port)
|
||||
static int get_port_memory(struct icom_port *icom_port)
|
||||
{
|
||||
int index;
|
||||
unsigned long stgAddr;
|
||||
@@ -1314,7 +1314,7 @@ static struct uart_driver icom_uart_driver = {
|
||||
.cons = ICOM_CONSOLE,
|
||||
};
|
||||
|
||||
static int __devinit icom_init_ports(struct icom_adapter *icom_adapter)
|
||||
static int icom_init_ports(struct icom_adapter *icom_adapter)
|
||||
{
|
||||
u32 subsystem_id = icom_adapter->subsystem_id;
|
||||
int i;
|
||||
@@ -1381,7 +1381,7 @@ static void icom_port_active(struct icom_port *icom_port, struct icom_adapter *i
|
||||
0x8024 + 2 - 2 * (icom_port->port - 2);
|
||||
}
|
||||
}
|
||||
static int __devinit icom_load_ports(struct icom_adapter *icom_adapter)
|
||||
static int icom_load_ports(struct icom_adapter *icom_adapter)
|
||||
{
|
||||
struct icom_port *icom_port;
|
||||
int port_num;
|
||||
@@ -1407,7 +1407,7 @@ static int __devinit icom_load_ports(struct icom_adapter *icom_adapter)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit icom_alloc_adapter(struct icom_adapter
|
||||
static int icom_alloc_adapter(struct icom_adapter
|
||||
**icom_adapter_ref)
|
||||
{
|
||||
int adapter_count = 0;
|
||||
@@ -1487,7 +1487,7 @@ static void icom_kref_release(struct kref *kref)
|
||||
icom_remove_adapter(icom_adapter);
|
||||
}
|
||||
|
||||
static int __devinit icom_probe(struct pci_dev *dev,
|
||||
static int icom_probe(struct pci_dev *dev,
|
||||
const struct pci_device_id *ent)
|
||||
{
|
||||
int index;
|
||||
@@ -1596,7 +1596,7 @@ probe_exit0:
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void __devexit icom_remove(struct pci_dev *dev)
|
||||
static void icom_remove(struct pci_dev *dev)
|
||||
{
|
||||
struct icom_adapter *icom_adapter;
|
||||
struct list_head *tmp;
|
||||
@@ -1617,7 +1617,7 @@ static struct pci_driver icom_pci_driver = {
|
||||
.name = ICOM_DRIVER_NAME,
|
||||
.id_table = icom_pci_table,
|
||||
.probe = icom_probe,
|
||||
.remove = __devexit_p(icom_remove),
|
||||
.remove = icom_remove,
|
||||
};
|
||||
|
||||
static int __init icom_init(void)
|
||||
|
@@ -60,20 +60,27 @@
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/spi/ifx_modem.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/reboot.h>
|
||||
|
||||
#include "ifx6x60.h"
|
||||
|
||||
#define IFX_SPI_MORE_MASK 0x10
|
||||
#define IFX_SPI_MORE_BIT 12 /* bit position in u16 */
|
||||
#define IFX_SPI_CTS_BIT 13 /* bit position in u16 */
|
||||
#define IFX_SPI_MORE_BIT 4 /* bit position in u8 */
|
||||
#define IFX_SPI_CTS_BIT 6 /* bit position in u8 */
|
||||
#define IFX_SPI_MODE SPI_MODE_1
|
||||
#define IFX_SPI_TTY_ID 0
|
||||
#define IFX_SPI_TIMEOUT_SEC 2
|
||||
#define IFX_SPI_HEADER_0 (-1)
|
||||
#define IFX_SPI_HEADER_F (-2)
|
||||
|
||||
#define PO_POST_DELAY 200
|
||||
#define IFX_MDM_RST_PMU 4
|
||||
|
||||
/* forward reference */
|
||||
static void ifx_spi_handle_srdy(struct ifx_spi_device *ifx_dev);
|
||||
static int ifx_modem_reboot_callback(struct notifier_block *nfb,
|
||||
unsigned long event, void *data);
|
||||
static int ifx_modem_power_off(struct ifx_spi_device *ifx_dev);
|
||||
|
||||
/* local variables */
|
||||
static int spi_bpw = 16; /* 8, 16 or 32 bit word length */
|
||||
@@ -81,6 +88,29 @@ static struct tty_driver *tty_drv;
|
||||
static struct ifx_spi_device *saved_ifx_dev;
|
||||
static struct lock_class_key ifx_spi_key;
|
||||
|
||||
static struct notifier_block ifx_modem_reboot_notifier_block = {
|
||||
.notifier_call = ifx_modem_reboot_callback,
|
||||
};
|
||||
|
||||
static int ifx_modem_power_off(struct ifx_spi_device *ifx_dev)
|
||||
{
|
||||
gpio_set_value(IFX_MDM_RST_PMU, 1);
|
||||
msleep(PO_POST_DELAY);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ifx_modem_reboot_callback(struct notifier_block *nfb,
|
||||
unsigned long event, void *data)
|
||||
{
|
||||
if (saved_ifx_dev)
|
||||
ifx_modem_power_off(saved_ifx_dev);
|
||||
else
|
||||
pr_warn("no ifx modem active;\n");
|
||||
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
/* GPIO/GPE settings */
|
||||
|
||||
/**
|
||||
@@ -152,26 +182,67 @@ ifx_spi_power_state_clear(struct ifx_spi_device *ifx_dev, unsigned char val)
|
||||
}
|
||||
|
||||
/**
|
||||
* swap_buf
|
||||
* swap_buf_8
|
||||
* @buf: our buffer
|
||||
* @len : number of bytes (not words) in the buffer
|
||||
* @end: end of buffer
|
||||
*
|
||||
* Swap the contents of a buffer into big endian format
|
||||
*/
|
||||
static inline void swap_buf(u16 *buf, int len, void *end)
|
||||
static inline void swap_buf_8(unsigned char *buf, int len, void *end)
|
||||
{
|
||||
/* don't swap buffer if SPI word width is 8 bits */
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* swap_buf_16
|
||||
* @buf: our buffer
|
||||
* @len : number of bytes (not words) in the buffer
|
||||
* @end: end of buffer
|
||||
*
|
||||
* Swap the contents of a buffer into big endian format
|
||||
*/
|
||||
static inline void swap_buf_16(unsigned char *buf, int len, void *end)
|
||||
{
|
||||
int n;
|
||||
|
||||
u16 *buf_16 = (u16 *)buf;
|
||||
len = ((len + 1) >> 1);
|
||||
if ((void *)&buf[len] > end) {
|
||||
pr_err("swap_buf: swap exceeds boundary (%p > %p)!",
|
||||
&buf[len], end);
|
||||
if ((void *)&buf_16[len] > end) {
|
||||
pr_err("swap_buf_16: swap exceeds boundary (%p > %p)!",
|
||||
&buf_16[len], end);
|
||||
return;
|
||||
}
|
||||
for (n = 0; n < len; n++) {
|
||||
*buf = cpu_to_be16(*buf);
|
||||
buf++;
|
||||
*buf_16 = cpu_to_be16(*buf_16);
|
||||
buf_16++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* swap_buf_32
|
||||
* @buf: our buffer
|
||||
* @len : number of bytes (not words) in the buffer
|
||||
* @end: end of buffer
|
||||
*
|
||||
* Swap the contents of a buffer into big endian format
|
||||
*/
|
||||
static inline void swap_buf_32(unsigned char *buf, int len, void *end)
|
||||
{
|
||||
int n;
|
||||
|
||||
u32 *buf_32 = (u32 *)buf;
|
||||
len = (len + 3) >> 2;
|
||||
|
||||
if ((void *)&buf_32[len] > end) {
|
||||
pr_err("swap_buf_32: swap exceeds boundary (%p > %p)!\n",
|
||||
&buf_32[len], end);
|
||||
return;
|
||||
}
|
||||
for (n = 0; n < len; n++) {
|
||||
*buf_32 = cpu_to_be32(*buf_32);
|
||||
buf_32++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,9 +261,7 @@ static void mrdy_assert(struct ifx_spi_device *ifx_dev)
|
||||
if (!val) {
|
||||
if (!test_and_set_bit(IFX_SPI_STATE_TIMER_PENDING,
|
||||
&ifx_dev->flags)) {
|
||||
ifx_dev->spi_timer.expires =
|
||||
jiffies + IFX_SPI_TIMEOUT_SEC*HZ;
|
||||
add_timer(&ifx_dev->spi_timer);
|
||||
mod_timer(&ifx_dev->spi_timer,jiffies + IFX_SPI_TIMEOUT_SEC*HZ);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -449,7 +518,7 @@ static int ifx_spi_prepare_tx_buffer(struct ifx_spi_device *ifx_dev)
|
||||
tx_count-IFX_SPI_HEADER_OVERHEAD,
|
||||
ifx_dev->spi_more);
|
||||
/* swap actual data in the buffer */
|
||||
swap_buf((u16 *)(ifx_dev->tx_buffer), tx_count,
|
||||
ifx_dev->swap_buf((ifx_dev->tx_buffer), tx_count,
|
||||
&ifx_dev->tx_buffer[IFX_SPI_TRANSFER_SIZE]);
|
||||
return tx_count;
|
||||
}
|
||||
@@ -469,9 +538,17 @@ static int ifx_spi_write(struct tty_struct *tty, const unsigned char *buf,
|
||||
{
|
||||
struct ifx_spi_device *ifx_dev = tty->driver_data;
|
||||
unsigned char *tmp_buf = (unsigned char *)buf;
|
||||
int tx_count = kfifo_in_locked(&ifx_dev->tx_fifo, tmp_buf, count,
|
||||
&ifx_dev->fifo_lock);
|
||||
mrdy_assert(ifx_dev);
|
||||
unsigned long flags;
|
||||
bool is_fifo_empty;
|
||||
int tx_count;
|
||||
|
||||
spin_lock_irqsave(&ifx_dev->fifo_lock, flags);
|
||||
is_fifo_empty = kfifo_is_empty(&ifx_dev->tx_fifo);
|
||||
tx_count = kfifo_in(&ifx_dev->tx_fifo, tmp_buf, count);
|
||||
spin_unlock_irqrestore(&ifx_dev->fifo_lock, flags);
|
||||
if (is_fifo_empty)
|
||||
mrdy_assert(ifx_dev);
|
||||
|
||||
return tx_count;
|
||||
}
|
||||
|
||||
@@ -530,12 +607,19 @@ static int ifx_port_activate(struct tty_port *port, struct tty_struct *tty)
|
||||
/* clear any old data; can't do this in 'close' */
|
||||
kfifo_reset(&ifx_dev->tx_fifo);
|
||||
|
||||
/* clear any flag which may be set in port shutdown procedure */
|
||||
clear_bit(IFX_SPI_STATE_IO_IN_PROGRESS, &ifx_dev->flags);
|
||||
clear_bit(IFX_SPI_STATE_IO_READY, &ifx_dev->flags);
|
||||
|
||||
/* put port data into this tty */
|
||||
tty->driver_data = ifx_dev;
|
||||
|
||||
/* allows flip string push from int context */
|
||||
tty->low_latency = 1;
|
||||
|
||||
/* set flag to allows data transfer */
|
||||
set_bit(IFX_SPI_STATE_IO_AVAILABLE, &ifx_dev->flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -551,6 +635,7 @@ static void ifx_port_shutdown(struct tty_port *port)
|
||||
struct ifx_spi_device *ifx_dev =
|
||||
container_of(port, struct ifx_spi_device, tty_port);
|
||||
|
||||
clear_bit(IFX_SPI_STATE_IO_AVAILABLE, &ifx_dev->flags);
|
||||
mrdy_set_low(ifx_dev);
|
||||
clear_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags);
|
||||
tasklet_kill(&ifx_dev->io_work_tasklet);
|
||||
@@ -617,7 +702,7 @@ static void ifx_spi_complete(void *ctx)
|
||||
|
||||
if (!ifx_dev->spi_msg.status) {
|
||||
/* check header validity, get comm flags */
|
||||
swap_buf((u16 *)ifx_dev->rx_buffer, IFX_SPI_HEADER_OVERHEAD,
|
||||
ifx_dev->swap_buf(ifx_dev->rx_buffer, IFX_SPI_HEADER_OVERHEAD,
|
||||
&ifx_dev->rx_buffer[IFX_SPI_HEADER_OVERHEAD]);
|
||||
decode_result = ifx_spi_decode_spi_header(ifx_dev->rx_buffer,
|
||||
&length, &more, &cts);
|
||||
@@ -636,7 +721,8 @@ static void ifx_spi_complete(void *ctx)
|
||||
|
||||
actual_length = min((unsigned int)length,
|
||||
ifx_dev->spi_msg.actual_length);
|
||||
swap_buf((u16 *)(ifx_dev->rx_buffer + IFX_SPI_HEADER_OVERHEAD),
|
||||
ifx_dev->swap_buf(
|
||||
(ifx_dev->rx_buffer + IFX_SPI_HEADER_OVERHEAD),
|
||||
actual_length,
|
||||
&ifx_dev->rx_buffer[IFX_SPI_TRANSFER_SIZE]);
|
||||
ifx_spi_insert_flip_string(
|
||||
@@ -705,7 +791,8 @@ static void ifx_spi_io(unsigned long data)
|
||||
int retval;
|
||||
struct ifx_spi_device *ifx_dev = (struct ifx_spi_device *) data;
|
||||
|
||||
if (!test_and_set_bit(IFX_SPI_STATE_IO_IN_PROGRESS, &ifx_dev->flags)) {
|
||||
if (!test_and_set_bit(IFX_SPI_STATE_IO_IN_PROGRESS, &ifx_dev->flags) &&
|
||||
test_bit(IFX_SPI_STATE_IO_AVAILABLE, &ifx_dev->flags)) {
|
||||
if (ifx_dev->gpio.unack_srdy_int_nb > 0)
|
||||
ifx_dev->gpio.unack_srdy_int_nb--;
|
||||
|
||||
@@ -773,6 +860,7 @@ static void ifx_spi_free_port(struct ifx_spi_device *ifx_dev)
|
||||
{
|
||||
if (ifx_dev->tty_dev)
|
||||
tty_unregister_device(tty_drv, ifx_dev->minor);
|
||||
tty_port_destroy(&ifx_dev->tty_port);
|
||||
kfifo_free(&ifx_dev->tx_fifo);
|
||||
}
|
||||
|
||||
@@ -806,10 +894,12 @@ static int ifx_spi_create_port(struct ifx_spi_device *ifx_dev)
|
||||
dev_dbg(&ifx_dev->spi_dev->dev,
|
||||
"%s: registering tty device failed", __func__);
|
||||
ret = PTR_ERR(ifx_dev->tty_dev);
|
||||
goto error_ret;
|
||||
goto error_port;
|
||||
}
|
||||
return 0;
|
||||
|
||||
error_port:
|
||||
tty_port_destroy(pport);
|
||||
error_ret:
|
||||
ifx_spi_free_port(ifx_dev);
|
||||
return ret;
|
||||
@@ -826,7 +916,7 @@ error_ret:
|
||||
static void ifx_spi_handle_srdy(struct ifx_spi_device *ifx_dev)
|
||||
{
|
||||
if (test_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags)) {
|
||||
del_timer_sync(&ifx_dev->spi_timer);
|
||||
del_timer(&ifx_dev->spi_timer);
|
||||
clear_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags);
|
||||
}
|
||||
|
||||
@@ -1001,6 +1091,14 @@ static int ifx_spi_spi_probe(struct spi_device *spi)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* init swap_buf function according to word width configuration */
|
||||
if (spi->bits_per_word == 32)
|
||||
ifx_dev->swap_buf = swap_buf_32;
|
||||
else if (spi->bits_per_word == 16)
|
||||
ifx_dev->swap_buf = swap_buf_16;
|
||||
else
|
||||
ifx_dev->swap_buf = swap_buf_8;
|
||||
|
||||
/* ensure SPI protocol flags are initialized to enable transfer */
|
||||
ifx_dev->spi_more = 0;
|
||||
ifx_dev->spi_slave_cts = 0;
|
||||
@@ -1219,6 +1317,9 @@ static int ifx_spi_spi_remove(struct spi_device *spi)
|
||||
|
||||
static void ifx_spi_spi_shutdown(struct spi_device *spi)
|
||||
{
|
||||
struct ifx_spi_device *ifx_dev = spi_get_drvdata(spi);
|
||||
|
||||
ifx_modem_power_off(ifx_dev);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1338,7 +1439,7 @@ static struct spi_driver ifx_spi_driver = {
|
||||
.owner = THIS_MODULE},
|
||||
.probe = ifx_spi_spi_probe,
|
||||
.shutdown = ifx_spi_spi_shutdown,
|
||||
.remove = __devexit_p(ifx_spi_spi_remove),
|
||||
.remove = ifx_spi_spi_remove,
|
||||
.suspend = ifx_spi_spi_suspend,
|
||||
.resume = ifx_spi_spi_resume,
|
||||
.id_table = ifx_id_table
|
||||
@@ -1354,7 +1455,9 @@ static void __exit ifx_spi_exit(void)
|
||||
{
|
||||
/* unregister */
|
||||
tty_unregister_driver(tty_drv);
|
||||
put_tty_driver(tty_drv);
|
||||
spi_unregister_driver((void *)&ifx_spi_driver);
|
||||
unregister_reboot_notifier(&ifx_modem_reboot_notifier_block);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1389,16 +1492,31 @@ static int __init ifx_spi_init(void)
|
||||
if (result) {
|
||||
pr_err("%s: tty_register_driver failed(%d)",
|
||||
DRVNAME, result);
|
||||
put_tty_driver(tty_drv);
|
||||
return result;
|
||||
goto err_free_tty;
|
||||
}
|
||||
|
||||
result = spi_register_driver((void *)&ifx_spi_driver);
|
||||
if (result) {
|
||||
pr_err("%s: spi_register_driver failed(%d)",
|
||||
DRVNAME, result);
|
||||
tty_unregister_driver(tty_drv);
|
||||
goto err_unreg_tty;
|
||||
}
|
||||
|
||||
result = register_reboot_notifier(&ifx_modem_reboot_notifier_block);
|
||||
if (result) {
|
||||
pr_err("%s: register ifx modem reboot notifier failed(%d)",
|
||||
DRVNAME, result);
|
||||
goto err_unreg_spi;
|
||||
}
|
||||
|
||||
return 0;
|
||||
err_unreg_spi:
|
||||
spi_unregister_driver((void *)&ifx_spi_driver);
|
||||
err_unreg_tty:
|
||||
tty_unregister_driver(tty_drv);
|
||||
err_free_tty:
|
||||
put_tty_driver(tty_drv);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@@ -41,6 +41,7 @@
|
||||
#define IFX_SPI_STATE_IO_IN_PROGRESS 1
|
||||
#define IFX_SPI_STATE_IO_READY 2
|
||||
#define IFX_SPI_STATE_TIMER_PENDING 3
|
||||
#define IFX_SPI_STATE_IO_AVAILABLE 4
|
||||
|
||||
/* flow control bitfields */
|
||||
#define IFX_SPI_DCD 0
|
||||
@@ -124,6 +125,7 @@ struct ifx_spi_device {
|
||||
#define MR_INPROGRESS 1
|
||||
#define MR_COMPLETE 2
|
||||
wait_queue_head_t mdm_reset_wait;
|
||||
void (*swap_buf)(unsigned char *buf, int len, void *end);
|
||||
};
|
||||
|
||||
#endif /* _IFX6X60_H */
|
||||
|
@@ -2010,7 +2010,7 @@ static int ioc3uart_remove(struct ioc3_submodule *is,
|
||||
* @idd: ioc3 driver data for this card
|
||||
*/
|
||||
|
||||
static int __devinit
|
||||
static int
|
||||
ioc3uart_probe(struct ioc3_submodule *is, struct ioc3_driver_data *idd)
|
||||
{
|
||||
struct pci_dev *pdev = idd->pdev;
|
||||
|
@@ -57,9 +57,11 @@ enum {
|
||||
DBG_CARR = 0x10000,
|
||||
};
|
||||
|
||||
#define jsm_printk(nlevel, klevel, pdev, fmt, args...) \
|
||||
if ((DBG_##nlevel & jsm_debug)) \
|
||||
dev_printk(KERN_##klevel, pdev->dev, fmt, ## args)
|
||||
#define jsm_dbg(nlevel, pdev, fmt, ...) \
|
||||
do { \
|
||||
if (DBG_##nlevel & jsm_debug) \
|
||||
dev_dbg(pdev->dev, fmt, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define MAXLINES 256
|
||||
#define MAXPORTS 8
|
||||
|
@@ -64,7 +64,7 @@ int jsm_debug;
|
||||
module_param(jsm_debug, int, 0);
|
||||
MODULE_PARM_DESC(jsm_debug, "Driver debugging level");
|
||||
|
||||
static int __devinit jsm_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
static int jsm_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
{
|
||||
int rc = 0;
|
||||
struct jsm_board *brd;
|
||||
@@ -107,8 +107,7 @@ static int __devinit jsm_probe_one(struct pci_dev *pdev, const struct pci_device
|
||||
|
||||
brd->irq = pdev->irq;
|
||||
|
||||
jsm_printk(INIT, INFO, &brd->pci_dev,
|
||||
"jsm_found_board - NEO adapter\n");
|
||||
jsm_dbg(INIT, &brd->pci_dev, "jsm_found_board - NEO adapter\n");
|
||||
|
||||
/* get the PCI Base Address Registers */
|
||||
brd->membase = pci_resource_start(pdev, 0);
|
||||
@@ -179,7 +178,7 @@ static int __devinit jsm_probe_one(struct pci_dev *pdev, const struct pci_device
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void __devexit jsm_remove_one(struct pci_dev *pdev)
|
||||
static void jsm_remove_one(struct pci_dev *pdev)
|
||||
{
|
||||
struct jsm_board *brd = pci_get_drvdata(pdev);
|
||||
int i = 0;
|
||||
@@ -218,7 +217,7 @@ static struct pci_driver jsm_driver = {
|
||||
.name = "jsm",
|
||||
.id_table = jsm_pci_tbl,
|
||||
.probe = jsm_probe_one,
|
||||
.remove = __devexit_p(jsm_remove_one),
|
||||
.remove = jsm_remove_one,
|
||||
.err_handler = &jsm_err_handler,
|
||||
};
|
||||
|
||||
|
@@ -52,7 +52,7 @@ static void neo_set_cts_flow_control(struct jsm_channel *ch)
|
||||
ier = readb(&ch->ch_neo_uart->ier);
|
||||
efr = readb(&ch->ch_neo_uart->efr);
|
||||
|
||||
jsm_printk(PARAM, INFO, &ch->ch_bd->pci_dev, "Setting CTSFLOW\n");
|
||||
jsm_dbg(PARAM, &ch->ch_bd->pci_dev, "Setting CTSFLOW\n");
|
||||
|
||||
/* Turn on auto CTS flow control */
|
||||
ier |= (UART_17158_IER_CTSDSR);
|
||||
@@ -83,7 +83,7 @@ static void neo_set_rts_flow_control(struct jsm_channel *ch)
|
||||
ier = readb(&ch->ch_neo_uart->ier);
|
||||
efr = readb(&ch->ch_neo_uart->efr);
|
||||
|
||||
jsm_printk(PARAM, INFO, &ch->ch_bd->pci_dev, "Setting RTSFLOW\n");
|
||||
jsm_dbg(PARAM, &ch->ch_bd->pci_dev, "Setting RTSFLOW\n");
|
||||
|
||||
/* Turn on auto RTS flow control */
|
||||
ier |= (UART_17158_IER_RTSDTR);
|
||||
@@ -123,7 +123,7 @@ static void neo_set_ixon_flow_control(struct jsm_channel *ch)
|
||||
ier = readb(&ch->ch_neo_uart->ier);
|
||||
efr = readb(&ch->ch_neo_uart->efr);
|
||||
|
||||
jsm_printk(PARAM, INFO, &ch->ch_bd->pci_dev, "Setting IXON FLOW\n");
|
||||
jsm_dbg(PARAM, &ch->ch_bd->pci_dev, "Setting IXON FLOW\n");
|
||||
|
||||
/* Turn off auto CTS flow control */
|
||||
ier &= ~(UART_17158_IER_CTSDSR);
|
||||
@@ -160,7 +160,7 @@ static void neo_set_ixoff_flow_control(struct jsm_channel *ch)
|
||||
ier = readb(&ch->ch_neo_uart->ier);
|
||||
efr = readb(&ch->ch_neo_uart->efr);
|
||||
|
||||
jsm_printk(PARAM, INFO, &ch->ch_bd->pci_dev, "Setting IXOFF FLOW\n");
|
||||
jsm_dbg(PARAM, &ch->ch_bd->pci_dev, "Setting IXOFF FLOW\n");
|
||||
|
||||
/* Turn off auto RTS flow control */
|
||||
ier &= ~(UART_17158_IER_RTSDTR);
|
||||
@@ -198,7 +198,7 @@ static void neo_set_no_input_flow_control(struct jsm_channel *ch)
|
||||
ier = readb(&ch->ch_neo_uart->ier);
|
||||
efr = readb(&ch->ch_neo_uart->efr);
|
||||
|
||||
jsm_printk(PARAM, INFO, &ch->ch_bd->pci_dev, "Unsetting Input FLOW\n");
|
||||
jsm_dbg(PARAM, &ch->ch_bd->pci_dev, "Unsetting Input FLOW\n");
|
||||
|
||||
/* Turn off auto RTS flow control */
|
||||
ier &= ~(UART_17158_IER_RTSDTR);
|
||||
@@ -237,7 +237,7 @@ static void neo_set_no_output_flow_control(struct jsm_channel *ch)
|
||||
ier = readb(&ch->ch_neo_uart->ier);
|
||||
efr = readb(&ch->ch_neo_uart->efr);
|
||||
|
||||
jsm_printk(PARAM, INFO, &ch->ch_bd->pci_dev, "Unsetting Output FLOW\n");
|
||||
jsm_dbg(PARAM, &ch->ch_bd->pci_dev, "Unsetting Output FLOW\n");
|
||||
|
||||
/* Turn off auto CTS flow control */
|
||||
ier &= ~(UART_17158_IER_CTSDSR);
|
||||
@@ -276,7 +276,7 @@ static inline void neo_set_new_start_stop_chars(struct jsm_channel *ch)
|
||||
if (ch->ch_c_cflag & CRTSCTS)
|
||||
return;
|
||||
|
||||
jsm_printk(PARAM, INFO, &ch->ch_bd->pci_dev, "start\n");
|
||||
jsm_dbg(PARAM, &ch->ch_bd->pci_dev, "start\n");
|
||||
|
||||
/* Tell UART what start/stop chars it should be looking for */
|
||||
writeb(ch->ch_startc, &ch->ch_neo_uart->xonchar1);
|
||||
@@ -455,7 +455,7 @@ static void neo_copy_data_from_uart_to_queue(struct jsm_channel *ch)
|
||||
* I hope thats okay with everyone? Yes? Good.
|
||||
*/
|
||||
while (qleft < 1) {
|
||||
jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
|
||||
jsm_dbg(READ, &ch->ch_bd->pci_dev,
|
||||
"Queue full, dropping DATA:%x LSR:%x\n",
|
||||
ch->ch_rqueue[tail], ch->ch_equeue[tail]);
|
||||
|
||||
@@ -467,8 +467,8 @@ static void neo_copy_data_from_uart_to_queue(struct jsm_channel *ch)
|
||||
memcpy_fromio(ch->ch_rqueue + head, &ch->ch_neo_uart->txrxburst, 1);
|
||||
ch->ch_equeue[head] = (u8) linestatus;
|
||||
|
||||
jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
|
||||
"DATA/LSR pair: %x %x\n", ch->ch_rqueue[head], ch->ch_equeue[head]);
|
||||
jsm_dbg(READ, &ch->ch_bd->pci_dev, "DATA/LSR pair: %x %x\n",
|
||||
ch->ch_rqueue[head], ch->ch_equeue[head]);
|
||||
|
||||
/* Ditch any remaining linestatus value. */
|
||||
linestatus = 0;
|
||||
@@ -521,8 +521,8 @@ static void neo_copy_data_from_queue_to_uart(struct jsm_channel *ch)
|
||||
ch->ch_cached_lsr &= ~(UART_LSR_THRE);
|
||||
|
||||
writeb(circ->buf[circ->tail], &ch->ch_neo_uart->txrx);
|
||||
jsm_printk(WRITE, INFO, &ch->ch_bd->pci_dev,
|
||||
"Tx data: %x\n", circ->buf[circ->tail]);
|
||||
jsm_dbg(WRITE, &ch->ch_bd->pci_dev,
|
||||
"Tx data: %x\n", circ->buf[circ->tail]);
|
||||
circ->tail = (circ->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||
ch->ch_txcount++;
|
||||
}
|
||||
@@ -575,8 +575,9 @@ static void neo_parse_modem(struct jsm_channel *ch, u8 signals)
|
||||
{
|
||||
u8 msignals = signals;
|
||||
|
||||
jsm_printk(MSIGS, INFO, &ch->ch_bd->pci_dev,
|
||||
"neo_parse_modem: port: %d msignals: %x\n", ch->ch_portnum, msignals);
|
||||
jsm_dbg(MSIGS, &ch->ch_bd->pci_dev,
|
||||
"neo_parse_modem: port: %d msignals: %x\n",
|
||||
ch->ch_portnum, msignals);
|
||||
|
||||
/* Scrub off lower bits. They signify delta's, which I don't care about */
|
||||
/* Keep DDCD and DDSR though */
|
||||
@@ -606,8 +607,8 @@ static void neo_parse_modem(struct jsm_channel *ch, u8 signals)
|
||||
else
|
||||
ch->ch_mistat &= ~UART_MSR_CTS;
|
||||
|
||||
jsm_printk(MSIGS, INFO, &ch->ch_bd->pci_dev,
|
||||
"Port: %d DTR: %d RTS: %d CTS: %d DSR: %d " "RI: %d CD: %d\n",
|
||||
jsm_dbg(MSIGS, &ch->ch_bd->pci_dev,
|
||||
"Port: %d DTR: %d RTS: %d CTS: %d DSR: %d " "RI: %d CD: %d\n",
|
||||
ch->ch_portnum,
|
||||
!!((ch->ch_mistat | ch->ch_mostat) & UART_MCR_DTR),
|
||||
!!((ch->ch_mistat | ch->ch_mostat) & UART_MCR_RTS),
|
||||
@@ -649,8 +650,8 @@ static void neo_flush_uart_write(struct jsm_channel *ch)
|
||||
/* Check to see if the UART feels it completely flushed the FIFO. */
|
||||
tmp = readb(&ch->ch_neo_uart->isr_fcr);
|
||||
if (tmp & 4) {
|
||||
jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev,
|
||||
"Still flushing TX UART... i: %d\n", i);
|
||||
jsm_dbg(IOCTL, &ch->ch_bd->pci_dev,
|
||||
"Still flushing TX UART... i: %d\n", i);
|
||||
udelay(10);
|
||||
}
|
||||
else
|
||||
@@ -681,8 +682,8 @@ static void neo_flush_uart_read(struct jsm_channel *ch)
|
||||
/* Check to see if the UART feels it completely flushed the FIFO. */
|
||||
tmp = readb(&ch->ch_neo_uart->isr_fcr);
|
||||
if (tmp & 2) {
|
||||
jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev,
|
||||
"Still flushing RX UART... i: %d\n", i);
|
||||
jsm_dbg(IOCTL, &ch->ch_bd->pci_dev,
|
||||
"Still flushing RX UART... i: %d\n", i);
|
||||
udelay(10);
|
||||
}
|
||||
else
|
||||
@@ -705,8 +706,9 @@ static void neo_clear_break(struct jsm_channel *ch, int force)
|
||||
writeb((temp & ~UART_LCR_SBC), &ch->ch_neo_uart->lcr);
|
||||
|
||||
ch->ch_flags &= ~(CH_BREAK_SENDING);
|
||||
jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev,
|
||||
"clear break Finishing UART_LCR_SBC! finished: %lx\n", jiffies);
|
||||
jsm_dbg(IOCTL, &ch->ch_bd->pci_dev,
|
||||
"clear break Finishing UART_LCR_SBC! finished: %lx\n",
|
||||
jiffies);
|
||||
|
||||
/* flush write operation */
|
||||
neo_pci_posting_flush(ch->ch_bd);
|
||||
@@ -748,8 +750,8 @@ static inline void neo_parse_isr(struct jsm_board *brd, u32 port)
|
||||
*/
|
||||
isr &= ~(UART_17158_IIR_FIFO_ENABLED);
|
||||
|
||||
jsm_printk(INTR, INFO, &ch->ch_bd->pci_dev,
|
||||
"%s:%d isr: %x\n", __FILE__, __LINE__, isr);
|
||||
jsm_dbg(INTR, &ch->ch_bd->pci_dev, "%s:%d isr: %x\n",
|
||||
__FILE__, __LINE__, isr);
|
||||
|
||||
if (isr & (UART_17158_IIR_RDI_TIMEOUT | UART_IIR_RDI)) {
|
||||
/* Read data from uart -> queue */
|
||||
@@ -772,8 +774,9 @@ static inline void neo_parse_isr(struct jsm_board *brd, u32 port)
|
||||
if (isr & UART_17158_IIR_XONXOFF) {
|
||||
cause = readb(&ch->ch_neo_uart->xoffchar1);
|
||||
|
||||
jsm_printk(INTR, INFO, &ch->ch_bd->pci_dev,
|
||||
"Port %d. Got ISR_XONXOFF: cause:%x\n", port, cause);
|
||||
jsm_dbg(INTR, &ch->ch_bd->pci_dev,
|
||||
"Port %d. Got ISR_XONXOFF: cause:%x\n",
|
||||
port, cause);
|
||||
|
||||
/*
|
||||
* Since the UART detected either an XON or
|
||||
@@ -786,17 +789,19 @@ static inline void neo_parse_isr(struct jsm_board *brd, u32 port)
|
||||
if (brd->channels[port]->ch_flags & CH_STOP) {
|
||||
ch->ch_flags &= ~(CH_STOP);
|
||||
}
|
||||
jsm_printk(INTR, INFO, &ch->ch_bd->pci_dev,
|
||||
"Port %d. XON detected in incoming data\n", port);
|
||||
jsm_dbg(INTR, &ch->ch_bd->pci_dev,
|
||||
"Port %d. XON detected in incoming data\n",
|
||||
port);
|
||||
}
|
||||
else if (cause == UART_17158_XOFF_DETECT) {
|
||||
if (!(brd->channels[port]->ch_flags & CH_STOP)) {
|
||||
ch->ch_flags |= CH_STOP;
|
||||
jsm_printk(INTR, INFO, &ch->ch_bd->pci_dev,
|
||||
"Setting CH_STOP\n");
|
||||
jsm_dbg(INTR, &ch->ch_bd->pci_dev,
|
||||
"Setting CH_STOP\n");
|
||||
}
|
||||
jsm_printk(INTR, INFO, &ch->ch_bd->pci_dev,
|
||||
"Port: %d. XOFF detected in incoming data\n", port);
|
||||
jsm_dbg(INTR, &ch->ch_bd->pci_dev,
|
||||
"Port: %d. XOFF detected in incoming data\n",
|
||||
port);
|
||||
}
|
||||
spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
|
||||
}
|
||||
@@ -825,8 +830,8 @@ static inline void neo_parse_isr(struct jsm_board *brd, u32 port)
|
||||
}
|
||||
|
||||
/* Parse any modem signal changes */
|
||||
jsm_printk(INTR, INFO, &ch->ch_bd->pci_dev,
|
||||
"MOD_STAT: sending to parse_modem_sigs\n");
|
||||
jsm_dbg(INTR, &ch->ch_bd->pci_dev,
|
||||
"MOD_STAT: sending to parse_modem_sigs\n");
|
||||
neo_parse_modem(ch, readb(&ch->ch_neo_uart->msr));
|
||||
}
|
||||
}
|
||||
@@ -849,8 +854,8 @@ static inline void neo_parse_lsr(struct jsm_board *brd, u32 port)
|
||||
|
||||
linestatus = readb(&ch->ch_neo_uart->lsr);
|
||||
|
||||
jsm_printk(INTR, INFO, &ch->ch_bd->pci_dev,
|
||||
"%s:%d port: %d linestatus: %x\n", __FILE__, __LINE__, port, linestatus);
|
||||
jsm_dbg(INTR, &ch->ch_bd->pci_dev, "%s:%d port: %d linestatus: %x\n",
|
||||
__FILE__, __LINE__, port, linestatus);
|
||||
|
||||
ch->ch_cached_lsr |= linestatus;
|
||||
|
||||
@@ -869,7 +874,7 @@ static inline void neo_parse_lsr(struct jsm_board *brd, u32 port)
|
||||
*to do the special RX+LSR read for this FIFO load.
|
||||
*/
|
||||
if (linestatus & UART_17158_RX_FIFO_DATA_ERROR)
|
||||
jsm_printk(INTR, DEBUG, &ch->ch_bd->pci_dev,
|
||||
jsm_dbg(INTR, &ch->ch_bd->pci_dev,
|
||||
"%s:%d Port: %d Got an RX error, need to parse LSR\n",
|
||||
__FILE__, __LINE__, port);
|
||||
|
||||
@@ -880,20 +885,21 @@ static inline void neo_parse_lsr(struct jsm_board *brd, u32 port)
|
||||
|
||||
if (linestatus & UART_LSR_PE) {
|
||||
ch->ch_err_parity++;
|
||||
jsm_printk(INTR, DEBUG, &ch->ch_bd->pci_dev,
|
||||
"%s:%d Port: %d. PAR ERR!\n", __FILE__, __LINE__, port);
|
||||
jsm_dbg(INTR, &ch->ch_bd->pci_dev, "%s:%d Port: %d. PAR ERR!\n",
|
||||
__FILE__, __LINE__, port);
|
||||
}
|
||||
|
||||
if (linestatus & UART_LSR_FE) {
|
||||
ch->ch_err_frame++;
|
||||
jsm_printk(INTR, DEBUG, &ch->ch_bd->pci_dev,
|
||||
"%s:%d Port: %d. FRM ERR!\n", __FILE__, __LINE__, port);
|
||||
jsm_dbg(INTR, &ch->ch_bd->pci_dev, "%s:%d Port: %d. FRM ERR!\n",
|
||||
__FILE__, __LINE__, port);
|
||||
}
|
||||
|
||||
if (linestatus & UART_LSR_BI) {
|
||||
ch->ch_err_break++;
|
||||
jsm_printk(INTR, DEBUG, &ch->ch_bd->pci_dev,
|
||||
"%s:%d Port: %d. BRK INTR!\n", __FILE__, __LINE__, port);
|
||||
jsm_dbg(INTR, &ch->ch_bd->pci_dev,
|
||||
"%s:%d Port: %d. BRK INTR!\n",
|
||||
__FILE__, __LINE__, port);
|
||||
}
|
||||
|
||||
if (linestatus & UART_LSR_OE) {
|
||||
@@ -904,8 +910,9 @@ static inline void neo_parse_lsr(struct jsm_board *brd, u32 port)
|
||||
* Probably we should eventually have an orun stat in our driver...
|
||||
*/
|
||||
ch->ch_err_overrun++;
|
||||
jsm_printk(INTR, DEBUG, &ch->ch_bd->pci_dev,
|
||||
"%s:%d Port: %d. Rx Overrun!\n", __FILE__, __LINE__, port);
|
||||
jsm_dbg(INTR, &ch->ch_bd->pci_dev,
|
||||
"%s:%d Port: %d. Rx Overrun!\n",
|
||||
__FILE__, __LINE__, port);
|
||||
}
|
||||
|
||||
if (linestatus & UART_LSR_THRE) {
|
||||
@@ -1128,11 +1135,11 @@ static irqreturn_t neo_intr(int irq, void *voidbrd)
|
||||
*/
|
||||
uart_poll = readl(brd->re_map_membase + UART_17158_POLL_ADDR_OFFSET);
|
||||
|
||||
jsm_printk(INTR, INFO, &brd->pci_dev,
|
||||
"%s:%d uart_poll: %x\n", __FILE__, __LINE__, uart_poll);
|
||||
jsm_dbg(INTR, &brd->pci_dev, "%s:%d uart_poll: %x\n",
|
||||
__FILE__, __LINE__, uart_poll);
|
||||
|
||||
if (!uart_poll) {
|
||||
jsm_printk(INTR, INFO, &brd->pci_dev,
|
||||
jsm_dbg(INTR, &brd->pci_dev,
|
||||
"Kernel interrupted to me, but no pending interrupts...\n");
|
||||
spin_unlock_irqrestore(&brd->bd_intr_lock, lock_flags);
|
||||
return IRQ_NONE;
|
||||
@@ -1158,15 +1165,15 @@ static irqreturn_t neo_intr(int irq, void *voidbrd)
|
||||
continue;
|
||||
}
|
||||
|
||||
jsm_printk(INTR, INFO, &brd->pci_dev,
|
||||
"%s:%d port: %x type: %x\n", __FILE__, __LINE__, port, type);
|
||||
jsm_dbg(INTR, &brd->pci_dev, "%s:%d port: %x type: %x\n",
|
||||
__FILE__, __LINE__, port, type);
|
||||
|
||||
/* Remove this port + type from uart_poll */
|
||||
uart_poll &= ~(jsm_offset_table[port]);
|
||||
|
||||
if (!type) {
|
||||
/* If no type, just ignore it, and move onto next port */
|
||||
jsm_printk(INTR, ERR, &brd->pci_dev,
|
||||
jsm_dbg(INTR, &brd->pci_dev,
|
||||
"Interrupt with no type! port: %d\n", port);
|
||||
continue;
|
||||
}
|
||||
@@ -1231,15 +1238,16 @@ static irqreturn_t neo_intr(int irq, void *voidbrd)
|
||||
* these once and awhile.
|
||||
* Its harmless, just ignore it and move on.
|
||||
*/
|
||||
jsm_printk(INTR, ERR, &brd->pci_dev,
|
||||
"%s:%d Unknown Interrupt type: %x\n", __FILE__, __LINE__, type);
|
||||
jsm_dbg(INTR, &brd->pci_dev,
|
||||
"%s:%d Unknown Interrupt type: %x\n",
|
||||
__FILE__, __LINE__, type);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&brd->bd_intr_lock, lock_flags);
|
||||
|
||||
jsm_printk(INTR, INFO, &brd->pci_dev, "finish.\n");
|
||||
jsm_dbg(INTR, &brd->pci_dev, "finish\n");
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
@@ -43,7 +43,7 @@ static inline int jsm_get_mstat(struct jsm_channel *ch)
|
||||
unsigned char mstat;
|
||||
unsigned result;
|
||||
|
||||
jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev, "start\n");
|
||||
jsm_dbg(IOCTL, &ch->ch_bd->pci_dev, "start\n");
|
||||
|
||||
mstat = (ch->ch_mostat | ch->ch_mistat);
|
||||
|
||||
@@ -62,7 +62,7 @@ static inline int jsm_get_mstat(struct jsm_channel *ch)
|
||||
if (mstat & UART_MSR_DCD)
|
||||
result |= TIOCM_CD;
|
||||
|
||||
jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev, "finish\n");
|
||||
jsm_dbg(IOCTL, &ch->ch_bd->pci_dev, "finish\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -79,14 +79,14 @@ static unsigned int jsm_tty_get_mctrl(struct uart_port *port)
|
||||
int result;
|
||||
struct jsm_channel *channel = (struct jsm_channel *)port;
|
||||
|
||||
jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "start\n");
|
||||
jsm_dbg(IOCTL, &channel->ch_bd->pci_dev, "start\n");
|
||||
|
||||
result = jsm_get_mstat(channel);
|
||||
|
||||
if (result < 0)
|
||||
return -ENXIO;
|
||||
|
||||
jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "finish\n");
|
||||
jsm_dbg(IOCTL, &channel->ch_bd->pci_dev, "finish\n");
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -100,7 +100,7 @@ static void jsm_tty_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||
{
|
||||
struct jsm_channel *channel = (struct jsm_channel *)port;
|
||||
|
||||
jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "start\n");
|
||||
jsm_dbg(IOCTL, &channel->ch_bd->pci_dev, "start\n");
|
||||
|
||||
if (mctrl & TIOCM_RTS)
|
||||
channel->ch_mostat |= UART_MCR_RTS;
|
||||
@@ -114,7 +114,7 @@ static void jsm_tty_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||
|
||||
channel->ch_bd->bd_ops->assert_modem_signals(channel);
|
||||
|
||||
jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "finish\n");
|
||||
jsm_dbg(IOCTL, &channel->ch_bd->pci_dev, "finish\n");
|
||||
udelay(10);
|
||||
}
|
||||
|
||||
@@ -135,23 +135,23 @@ static void jsm_tty_start_tx(struct uart_port *port)
|
||||
{
|
||||
struct jsm_channel *channel = (struct jsm_channel *)port;
|
||||
|
||||
jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "start\n");
|
||||
jsm_dbg(IOCTL, &channel->ch_bd->pci_dev, "start\n");
|
||||
|
||||
channel->ch_flags &= ~(CH_STOP);
|
||||
jsm_tty_write(port);
|
||||
|
||||
jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "finish\n");
|
||||
jsm_dbg(IOCTL, &channel->ch_bd->pci_dev, "finish\n");
|
||||
}
|
||||
|
||||
static void jsm_tty_stop_tx(struct uart_port *port)
|
||||
{
|
||||
struct jsm_channel *channel = (struct jsm_channel *)port;
|
||||
|
||||
jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "start\n");
|
||||
jsm_dbg(IOCTL, &channel->ch_bd->pci_dev, "start\n");
|
||||
|
||||
channel->ch_flags |= (CH_STOP);
|
||||
|
||||
jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "finish\n");
|
||||
jsm_dbg(IOCTL, &channel->ch_bd->pci_dev, "finish\n");
|
||||
}
|
||||
|
||||
static void jsm_tty_send_xchar(struct uart_port *port, char ch)
|
||||
@@ -216,16 +216,16 @@ static int jsm_tty_open(struct uart_port *port)
|
||||
if (!channel->ch_rqueue) {
|
||||
channel->ch_rqueue = kzalloc(RQUEUESIZE, GFP_KERNEL);
|
||||
if (!channel->ch_rqueue) {
|
||||
jsm_printk(INIT, ERR, &channel->ch_bd->pci_dev,
|
||||
"unable to allocate read queue buf");
|
||||
jsm_dbg(INIT, &channel->ch_bd->pci_dev,
|
||||
"unable to allocate read queue buf\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
if (!channel->ch_equeue) {
|
||||
channel->ch_equeue = kzalloc(EQUEUESIZE, GFP_KERNEL);
|
||||
if (!channel->ch_equeue) {
|
||||
jsm_printk(INIT, ERR, &channel->ch_bd->pci_dev,
|
||||
"unable to allocate error queue buf");
|
||||
jsm_dbg(INIT, &channel->ch_bd->pci_dev,
|
||||
"unable to allocate error queue buf\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
@@ -234,7 +234,7 @@ static int jsm_tty_open(struct uart_port *port)
|
||||
/*
|
||||
* Initialize if neither terminal is open.
|
||||
*/
|
||||
jsm_printk(OPEN, INFO, &channel->ch_bd->pci_dev,
|
||||
jsm_dbg(OPEN, &channel->ch_bd->pci_dev,
|
||||
"jsm_open: initializing channel in open...\n");
|
||||
|
||||
/*
|
||||
@@ -270,7 +270,7 @@ static int jsm_tty_open(struct uart_port *port)
|
||||
|
||||
channel->ch_open_count++;
|
||||
|
||||
jsm_printk(OPEN, INFO, &channel->ch_bd->pci_dev, "finish\n");
|
||||
jsm_dbg(OPEN, &channel->ch_bd->pci_dev, "finish\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -280,7 +280,7 @@ static void jsm_tty_close(struct uart_port *port)
|
||||
struct ktermios *ts;
|
||||
struct jsm_channel *channel = (struct jsm_channel *)port;
|
||||
|
||||
jsm_printk(CLOSE, INFO, &channel->ch_bd->pci_dev, "start\n");
|
||||
jsm_dbg(CLOSE, &channel->ch_bd->pci_dev, "start\n");
|
||||
|
||||
bd = channel->ch_bd;
|
||||
ts = &port->state->port.tty->termios;
|
||||
@@ -293,7 +293,7 @@ static void jsm_tty_close(struct uart_port *port)
|
||||
* If we have HUPCL set, lower DTR and RTS
|
||||
*/
|
||||
if (channel->ch_c_cflag & HUPCL) {
|
||||
jsm_printk(CLOSE, INFO, &channel->ch_bd->pci_dev,
|
||||
jsm_dbg(CLOSE, &channel->ch_bd->pci_dev,
|
||||
"Close. HUPCL set, dropping DTR/RTS\n");
|
||||
|
||||
/* Drop RTS/DTR */
|
||||
@@ -304,7 +304,7 @@ static void jsm_tty_close(struct uart_port *port)
|
||||
/* Turn off UART interrupts for this port */
|
||||
channel->ch_bd->bd_ops->uart_off(channel);
|
||||
|
||||
jsm_printk(CLOSE, INFO, &channel->ch_bd->pci_dev, "finish\n");
|
||||
jsm_dbg(CLOSE, &channel->ch_bd->pci_dev, "finish\n");
|
||||
}
|
||||
|
||||
static void jsm_tty_set_termios(struct uart_port *port,
|
||||
@@ -371,7 +371,7 @@ static struct uart_ops jsm_ops = {
|
||||
* Init the tty subsystem. Called once per board after board has been
|
||||
* downloaded and init'ed.
|
||||
*/
|
||||
int __devinit jsm_tty_init(struct jsm_board *brd)
|
||||
int jsm_tty_init(struct jsm_board *brd)
|
||||
{
|
||||
int i;
|
||||
void __iomem *vaddr;
|
||||
@@ -380,7 +380,7 @@ int __devinit jsm_tty_init(struct jsm_board *brd)
|
||||
if (!brd)
|
||||
return -ENXIO;
|
||||
|
||||
jsm_printk(INIT, INFO, &brd->pci_dev, "start\n");
|
||||
jsm_dbg(INIT, &brd->pci_dev, "start\n");
|
||||
|
||||
/*
|
||||
* Initialize board structure elements.
|
||||
@@ -401,9 +401,9 @@ int __devinit jsm_tty_init(struct jsm_board *brd)
|
||||
*/
|
||||
brd->channels[i] = kzalloc(sizeof(struct jsm_channel), GFP_KERNEL);
|
||||
if (!brd->channels[i]) {
|
||||
jsm_printk(CORE, ERR, &brd->pci_dev,
|
||||
jsm_dbg(CORE, &brd->pci_dev,
|
||||
"%s:%d Unable to allocate memory for channel struct\n",
|
||||
__FILE__, __LINE__);
|
||||
__FILE__, __LINE__);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -431,7 +431,7 @@ int __devinit jsm_tty_init(struct jsm_board *brd)
|
||||
init_waitqueue_head(&ch->ch_flags_wait);
|
||||
}
|
||||
|
||||
jsm_printk(INIT, INFO, &brd->pci_dev, "finish\n");
|
||||
jsm_dbg(INIT, &brd->pci_dev, "finish\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -444,7 +444,7 @@ int jsm_uart_port_init(struct jsm_board *brd)
|
||||
if (!brd)
|
||||
return -ENXIO;
|
||||
|
||||
jsm_printk(INIT, INFO, &brd->pci_dev, "start\n");
|
||||
jsm_dbg(INIT, &brd->pci_dev, "start\n");
|
||||
|
||||
/*
|
||||
* Initialize board structure elements.
|
||||
@@ -481,7 +481,7 @@ int jsm_uart_port_init(struct jsm_board *brd)
|
||||
printk(KERN_INFO "jsm: Port %d added\n", i);
|
||||
}
|
||||
|
||||
jsm_printk(INIT, INFO, &brd->pci_dev, "finish\n");
|
||||
jsm_dbg(INIT, &brd->pci_dev, "finish\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -493,7 +493,7 @@ int jsm_remove_uart_port(struct jsm_board *brd)
|
||||
if (!brd)
|
||||
return -ENXIO;
|
||||
|
||||
jsm_printk(INIT, INFO, &brd->pci_dev, "start\n");
|
||||
jsm_dbg(INIT, &brd->pci_dev, "start\n");
|
||||
|
||||
/*
|
||||
* Initialize board structure elements.
|
||||
@@ -513,7 +513,7 @@ int jsm_remove_uart_port(struct jsm_board *brd)
|
||||
uart_remove_one_port(&jsm_uart_driver, &brd->channels[i]->uart_port);
|
||||
}
|
||||
|
||||
jsm_printk(INIT, INFO, &brd->pci_dev, "finish\n");
|
||||
jsm_dbg(INIT, &brd->pci_dev, "finish\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -531,7 +531,7 @@ void jsm_input(struct jsm_channel *ch)
|
||||
int s = 0;
|
||||
int i = 0;
|
||||
|
||||
jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "start\n");
|
||||
jsm_dbg(READ, &ch->ch_bd->pci_dev, "start\n");
|
||||
|
||||
if (!ch)
|
||||
return;
|
||||
@@ -560,7 +560,7 @@ void jsm_input(struct jsm_channel *ch)
|
||||
return;
|
||||
}
|
||||
|
||||
jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "start\n");
|
||||
jsm_dbg(READ, &ch->ch_bd->pci_dev, "start\n");
|
||||
|
||||
/*
|
||||
*If the device is not open, or CREAD is off, flush
|
||||
@@ -569,8 +569,9 @@ void jsm_input(struct jsm_channel *ch)
|
||||
if (!tp ||
|
||||
!(tp->termios.c_cflag & CREAD) ) {
|
||||
|
||||
jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
|
||||
"input. dropping %d bytes on port %d...\n", data_len, ch->ch_portnum);
|
||||
jsm_dbg(READ, &ch->ch_bd->pci_dev,
|
||||
"input. dropping %d bytes on port %d...\n",
|
||||
data_len, ch->ch_portnum);
|
||||
ch->ch_r_head = tail;
|
||||
|
||||
/* Force queue flow control to be released, if needed */
|
||||
@@ -585,17 +586,17 @@ void jsm_input(struct jsm_channel *ch)
|
||||
*/
|
||||
if (ch->ch_flags & CH_STOPI) {
|
||||
spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
|
||||
jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
|
||||
jsm_dbg(READ, &ch->ch_bd->pci_dev,
|
||||
"Port %d throttled, not reading any data. head: %x tail: %x\n",
|
||||
ch->ch_portnum, head, tail);
|
||||
return;
|
||||
}
|
||||
|
||||
jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "start 2\n");
|
||||
jsm_dbg(READ, &ch->ch_bd->pci_dev, "start 2\n");
|
||||
|
||||
if (data_len <= 0) {
|
||||
spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
|
||||
jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "jsm_input 1\n");
|
||||
jsm_dbg(READ, &ch->ch_bd->pci_dev, "jsm_input 1\n");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -653,7 +654,7 @@ void jsm_input(struct jsm_channel *ch)
|
||||
/* Tell the tty layer its okay to "eat" the data now */
|
||||
tty_flip_buffer_push(tp);
|
||||
|
||||
jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev, "finish\n");
|
||||
jsm_dbg(IOCTL, &ch->ch_bd->pci_dev, "finish\n");
|
||||
}
|
||||
|
||||
static void jsm_carrier(struct jsm_channel *ch)
|
||||
@@ -663,7 +664,7 @@ static void jsm_carrier(struct jsm_channel *ch)
|
||||
int virt_carrier = 0;
|
||||
int phys_carrier = 0;
|
||||
|
||||
jsm_printk(CARR, INFO, &ch->ch_bd->pci_dev, "start\n");
|
||||
jsm_dbg(CARR, &ch->ch_bd->pci_dev, "start\n");
|
||||
if (!ch)
|
||||
return;
|
||||
|
||||
@@ -673,16 +674,16 @@ static void jsm_carrier(struct jsm_channel *ch)
|
||||
return;
|
||||
|
||||
if (ch->ch_mistat & UART_MSR_DCD) {
|
||||
jsm_printk(CARR, INFO, &ch->ch_bd->pci_dev,
|
||||
"mistat: %x D_CD: %x\n", ch->ch_mistat, ch->ch_mistat & UART_MSR_DCD);
|
||||
jsm_dbg(CARR, &ch->ch_bd->pci_dev, "mistat: %x D_CD: %x\n",
|
||||
ch->ch_mistat, ch->ch_mistat & UART_MSR_DCD);
|
||||
phys_carrier = 1;
|
||||
}
|
||||
|
||||
if (ch->ch_c_cflag & CLOCAL)
|
||||
virt_carrier = 1;
|
||||
|
||||
jsm_printk(CARR, INFO, &ch->ch_bd->pci_dev,
|
||||
"DCD: physical: %d virt: %d\n", phys_carrier, virt_carrier);
|
||||
jsm_dbg(CARR, &ch->ch_bd->pci_dev, "DCD: physical: %d virt: %d\n",
|
||||
phys_carrier, virt_carrier);
|
||||
|
||||
/*
|
||||
* Test for a VIRTUAL carrier transition to HIGH.
|
||||
@@ -694,8 +695,7 @@ static void jsm_carrier(struct jsm_channel *ch)
|
||||
* for carrier in the open routine.
|
||||
*/
|
||||
|
||||
jsm_printk(CARR, INFO, &ch->ch_bd->pci_dev,
|
||||
"carrier: virt DCD rose\n");
|
||||
jsm_dbg(CARR, &ch->ch_bd->pci_dev, "carrier: virt DCD rose\n");
|
||||
|
||||
if (waitqueue_active(&(ch->ch_flags_wait)))
|
||||
wake_up_interruptible(&ch->ch_flags_wait);
|
||||
@@ -711,7 +711,7 @@ static void jsm_carrier(struct jsm_channel *ch)
|
||||
* for carrier in the open routine.
|
||||
*/
|
||||
|
||||
jsm_printk(CARR, INFO, &ch->ch_bd->pci_dev,
|
||||
jsm_dbg(CARR, &ch->ch_bd->pci_dev,
|
||||
"carrier: physical DCD rose\n");
|
||||
|
||||
if (waitqueue_active(&(ch->ch_flags_wait)))
|
||||
@@ -790,8 +790,8 @@ void jsm_check_queue_flow_control(struct jsm_channel *ch)
|
||||
if(!(ch->ch_flags & CH_RECEIVER_OFF)) {
|
||||
bd_ops->disable_receiver(ch);
|
||||
ch->ch_flags |= (CH_RECEIVER_OFF);
|
||||
jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
|
||||
"Internal queue hit hilevel mark (%d)! Turning off interrupts.\n",
|
||||
jsm_dbg(READ, &ch->ch_bd->pci_dev,
|
||||
"Internal queue hit hilevel mark (%d)! Turning off interrupts\n",
|
||||
qleft);
|
||||
}
|
||||
}
|
||||
@@ -800,8 +800,9 @@ void jsm_check_queue_flow_control(struct jsm_channel *ch)
|
||||
if (ch->ch_stops_sent <= MAX_STOPS_SENT) {
|
||||
bd_ops->send_stop_character(ch);
|
||||
ch->ch_stops_sent++;
|
||||
jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
|
||||
"Sending stop char! Times sent: %x\n", ch->ch_stops_sent);
|
||||
jsm_dbg(READ, &ch->ch_bd->pci_dev,
|
||||
"Sending stop char! Times sent: %x\n",
|
||||
ch->ch_stops_sent);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -827,8 +828,8 @@ void jsm_check_queue_flow_control(struct jsm_channel *ch)
|
||||
if (ch->ch_flags & CH_RECEIVER_OFF) {
|
||||
bd_ops->enable_receiver(ch);
|
||||
ch->ch_flags &= ~(CH_RECEIVER_OFF);
|
||||
jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
|
||||
"Internal queue hit lowlevel mark (%d)! Turning on interrupts.\n",
|
||||
jsm_dbg(READ, &ch->ch_bd->pci_dev,
|
||||
"Internal queue hit lowlevel mark (%d)! Turning on interrupts\n",
|
||||
qleft);
|
||||
}
|
||||
}
|
||||
@@ -836,7 +837,8 @@ void jsm_check_queue_flow_control(struct jsm_channel *ch)
|
||||
else if (ch->ch_c_iflag & IXOFF && ch->ch_stops_sent) {
|
||||
ch->ch_stops_sent = 0;
|
||||
bd_ops->send_start_character(ch);
|
||||
jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "Sending start char!\n");
|
||||
jsm_dbg(READ, &ch->ch_bd->pci_dev,
|
||||
"Sending start char!\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -266,6 +266,7 @@ static int kgdb_nmi_tty_install(struct tty_driver *drv, struct tty_struct *tty)
|
||||
}
|
||||
return 0;
|
||||
err:
|
||||
tty_port_destroy(&priv->port);
|
||||
kfree(priv);
|
||||
return ret;
|
||||
}
|
||||
@@ -275,6 +276,7 @@ static void kgdb_nmi_tty_cleanup(struct tty_struct *tty)
|
||||
struct kgdb_nmi_tty_priv *priv = tty->driver_data;
|
||||
|
||||
tty->driver_data = NULL;
|
||||
tty_port_destroy(&priv->port);
|
||||
kfree(priv);
|
||||
}
|
||||
|
||||
|
@@ -686,7 +686,7 @@ static struct uart_ops serial_lpc32xx_pops = {
|
||||
/*
|
||||
* Register a set of serial devices attached to a platform device
|
||||
*/
|
||||
static int __devinit serial_hs_lpc32xx_probe(struct platform_device *pdev)
|
||||
static int serial_hs_lpc32xx_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct lpc32xx_hsuart_port *p = &lpc32xx_hs_ports[uarts_registered];
|
||||
int ret = 0;
|
||||
@@ -740,7 +740,7 @@ static int __devinit serial_hs_lpc32xx_probe(struct platform_device *pdev)
|
||||
/*
|
||||
* Remove serial ports registered against a platform device.
|
||||
*/
|
||||
static int __devexit serial_hs_lpc32xx_remove(struct platform_device *pdev)
|
||||
static int serial_hs_lpc32xx_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct lpc32xx_hsuart_port *p = platform_get_drvdata(pdev);
|
||||
|
||||
@@ -783,7 +783,7 @@ MODULE_DEVICE_TABLE(of, serial_hs_lpc32xx_dt_ids);
|
||||
|
||||
static struct platform_driver serial_hs_lpc32xx_driver = {
|
||||
.probe = serial_hs_lpc32xx_probe,
|
||||
.remove = __devexit_p(serial_hs_lpc32xx_remove),
|
||||
.remove = serial_hs_lpc32xx_remove,
|
||||
.suspend = serial_hs_lpc32xx_suspend,
|
||||
.resume = serial_hs_lpc32xx_resume,
|
||||
.driver = {
|
||||
|
@@ -742,7 +742,7 @@ static struct uart_driver max3100_uart_driver = {
|
||||
};
|
||||
static int uart_driver_registered;
|
||||
|
||||
static int __devinit max3100_probe(struct spi_device *spi)
|
||||
static int max3100_probe(struct spi_device *spi)
|
||||
{
|
||||
int i, retval;
|
||||
struct plat_max3100 *pdata;
|
||||
@@ -818,7 +818,7 @@ static int __devinit max3100_probe(struct spi_device *spi)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit max3100_remove(struct spi_device *spi)
|
||||
static int max3100_remove(struct spi_device *spi)
|
||||
{
|
||||
struct max3100_port *s = dev_get_drvdata(&spi->dev);
|
||||
int i;
|
||||
@@ -907,7 +907,7 @@ static struct spi_driver max3100_driver = {
|
||||
},
|
||||
|
||||
.probe = max3100_probe,
|
||||
.remove = __devexit_p(max3100_remove),
|
||||
.remove = max3100_remove,
|
||||
.suspend = max3100_suspend,
|
||||
.resume = max3100_resume,
|
||||
};
|
||||
|
@@ -378,7 +378,7 @@ static void max310x_wait_pll(struct max310x_port *s)
|
||||
}
|
||||
}
|
||||
|
||||
static int __devinit max310x_update_best_err(unsigned long f, long *besterr)
|
||||
static int max310x_update_best_err(unsigned long f, long *besterr)
|
||||
{
|
||||
/* Use baudrate 115200 for calculate error */
|
||||
long err = f % (115200 * 16);
|
||||
@@ -391,7 +391,7 @@ static int __devinit max310x_update_best_err(unsigned long f, long *besterr)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int __devinit max310x_set_ref_clk(struct max310x_port *s)
|
||||
static int max310x_set_ref_clk(struct max310x_port *s)
|
||||
{
|
||||
unsigned int div, clksrc, pllcfg = 0;
|
||||
long besterr = -1;
|
||||
@@ -995,7 +995,7 @@ static struct max310x_pdata generic_plat_data = {
|
||||
.frequency = 26000000,
|
||||
};
|
||||
|
||||
static int __devinit max310x_probe(struct spi_device *spi)
|
||||
static int max310x_probe(struct spi_device *spi)
|
||||
{
|
||||
struct max310x_port *s;
|
||||
struct device *dev = &spi->dev;
|
||||
@@ -1178,6 +1178,7 @@ static int __devinit max310x_probe(struct spi_device *spi)
|
||||
s->gpio.set = max310x_gpio_set;
|
||||
s->gpio.base = pdata->gpio_base;
|
||||
s->gpio.ngpio = s->nr_gpio;
|
||||
s->gpio.can_sleep = 1;
|
||||
if (gpiochip_add(&s->gpio)) {
|
||||
/* Indicate that we should not call gpiochip_remove */
|
||||
s->gpio.base = 0;
|
||||
@@ -1202,7 +1203,7 @@ err_out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit max310x_remove(struct spi_device *spi)
|
||||
static int max310x_remove(struct spi_device *spi)
|
||||
{
|
||||
struct device *dev = &spi->dev;
|
||||
struct max310x_port *s = dev_get_drvdata(dev);
|
||||
@@ -1249,7 +1250,7 @@ static struct spi_driver max310x_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = max310x_probe,
|
||||
.remove = __devexit_p(max310x_remove),
|
||||
.remove = max310x_remove,
|
||||
.suspend = max310x_suspend,
|
||||
.resume = max310x_resume,
|
||||
.id_table = max310x_id_table,
|
||||
|
@@ -571,7 +571,7 @@ static struct uart_driver mcf_driver = {
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
static int __devinit mcf_probe(struct platform_device *pdev)
|
||||
static int mcf_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct mcf_platform_uart *platp = pdev->dev.platform_data;
|
||||
struct uart_port *port;
|
||||
@@ -599,7 +599,7 @@ static int __devinit mcf_probe(struct platform_device *pdev)
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
static int __devexit mcf_remove(struct platform_device *pdev)
|
||||
static int mcf_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct uart_port *port;
|
||||
int i;
|
||||
@@ -617,7 +617,7 @@ static int __devexit mcf_remove(struct platform_device *pdev)
|
||||
|
||||
static struct platform_driver mcf_platform_driver = {
|
||||
.probe = mcf_probe,
|
||||
.remove = __devexit_p(mcf_remove),
|
||||
.remove = mcf_remove,
|
||||
.driver = {
|
||||
.name = "mcfuart",
|
||||
.owner = THIS_MODULE,
|
||||
|
@@ -36,6 +36,7 @@
|
||||
#include <linux/serial_mfd.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/nmi.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
@@ -1113,6 +1114,8 @@ serial_hsu_console_write(struct console *co, const char *s, unsigned int count)
|
||||
unsigned int ier;
|
||||
int locked = 1;
|
||||
|
||||
touch_nmi_watchdog();
|
||||
|
||||
local_irq_save(flags);
|
||||
if (up->port.sysrq)
|
||||
locked = 0;
|
||||
@@ -1456,7 +1459,7 @@ static void serial_hsu_remove(struct pci_dev *pdev)
|
||||
}
|
||||
|
||||
/* First 3 are UART ports, and the 4th is the DMA */
|
||||
static const struct pci_device_id pci_ids[] __devinitconst = {
|
||||
static const struct pci_device_id pci_ids[] = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081B) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081C) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081D) },
|
||||
@@ -1468,7 +1471,7 @@ static struct pci_driver hsu_pci_driver = {
|
||||
.name = "HSU serial",
|
||||
.id_table = pci_ids,
|
||||
.probe = serial_hsu_probe,
|
||||
.remove = __devexit_p(serial_hsu_remove),
|
||||
.remove = serial_hsu_remove,
|
||||
.suspend = serial_hsu_suspend,
|
||||
.resume = serial_hsu_resume,
|
||||
.driver = {
|
||||
|
@@ -1308,7 +1308,7 @@ static struct of_device_id mpc52xx_uart_of_match[] = {
|
||||
{},
|
||||
};
|
||||
|
||||
static int __devinit mpc52xx_uart_of_probe(struct platform_device *op)
|
||||
static int mpc52xx_uart_of_probe(struct platform_device *op)
|
||||
{
|
||||
int idx = -1;
|
||||
unsigned int uartclk;
|
||||
|
@@ -773,7 +773,7 @@ static int serial_m3110_resume(struct spi_device *spi)
|
||||
#define serial_m3110_resume NULL
|
||||
#endif
|
||||
|
||||
static int __devinit serial_m3110_probe(struct spi_device *spi)
|
||||
static int serial_m3110_probe(struct spi_device *spi)
|
||||
{
|
||||
struct uart_max3110 *max;
|
||||
void *buffer;
|
||||
@@ -855,7 +855,7 @@ err_get_page:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit serial_m3110_remove(struct spi_device *dev)
|
||||
static int serial_m3110_remove(struct spi_device *dev)
|
||||
{
|
||||
struct uart_max3110 *max = spi_get_drvdata(dev);
|
||||
|
||||
@@ -879,7 +879,7 @@ static struct spi_driver uart_max3110_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = serial_m3110_probe,
|
||||
.remove = __devexit_p(serial_m3110_remove),
|
||||
.remove = serial_m3110_remove,
|
||||
.suspend = serial_m3110_suspend,
|
||||
.resume = serial_m3110_resume,
|
||||
};
|
||||
|
@@ -917,7 +917,7 @@ static int __init msm_serial_probe(struct platform_device *pdev)
|
||||
return uart_add_one_port(&msm_uart_driver, port);
|
||||
}
|
||||
|
||||
static int __devexit msm_serial_remove(struct platform_device *pdev)
|
||||
static int msm_serial_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct msm_port *msm_port = platform_get_drvdata(pdev);
|
||||
|
||||
|
@@ -401,7 +401,7 @@ static int msm_hs_request_port(struct uart_port *port)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit msm_hs_remove(struct platform_device *pdev)
|
||||
static int msm_hs_remove(struct platform_device *pdev)
|
||||
{
|
||||
|
||||
struct msm_hs_port *msm_uport;
|
||||
@@ -1521,7 +1521,7 @@ err_msm_hs_init_clk:
|
||||
}
|
||||
|
||||
/* Initialize tx and rx data structures */
|
||||
static int __devinit uartdm_init_port(struct uart_port *uport)
|
||||
static int uartdm_init_port(struct uart_port *uport)
|
||||
{
|
||||
int ret = 0;
|
||||
struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
|
||||
@@ -1614,7 +1614,7 @@ err_tx_command_ptr_ptr:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devinit msm_hs_probe(struct platform_device *pdev)
|
||||
static int msm_hs_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
struct uart_port *uport;
|
||||
@@ -1838,7 +1838,7 @@ static const struct dev_pm_ops msm_hs_dev_pm_ops = {
|
||||
|
||||
static struct platform_driver msm_serial_hs_platform_driver = {
|
||||
.probe = msm_hs_probe,
|
||||
.remove = __devexit_p(msm_hs_remove),
|
||||
.remove = msm_hs_remove,
|
||||
.driver = {
|
||||
.name = "msm_serial_hs",
|
||||
.owner = THIS_MODULE,
|
||||
|
@@ -520,7 +520,7 @@ static int __init mux_probe(struct parisc_device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit mux_remove(struct parisc_device *dev)
|
||||
static int mux_remove(struct parisc_device *dev)
|
||||
{
|
||||
int i, j;
|
||||
int port_count = (long)dev_get_drvdata(&dev->dev);
|
||||
@@ -571,14 +571,14 @@ static struct parisc_driver builtin_serial_mux_driver = {
|
||||
.name = "builtin_serial_mux",
|
||||
.id_table = builtin_mux_tbl,
|
||||
.probe = mux_probe,
|
||||
.remove = __devexit_p(mux_remove),
|
||||
.remove = mux_remove,
|
||||
};
|
||||
|
||||
static struct parisc_driver serial_mux_driver = {
|
||||
.name = "serial_mux",
|
||||
.id_table = mux_tbl,
|
||||
.probe = mux_probe,
|
||||
.remove = __devexit_p(mux_remove),
|
||||
.remove = mux_remove,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@@ -34,6 +34,8 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/fsl/mxs-dma.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
|
||||
@@ -71,6 +73,15 @@
|
||||
|
||||
#define AUART_CTRL0_SFTRST (1 << 31)
|
||||
#define AUART_CTRL0_CLKGATE (1 << 30)
|
||||
#define AUART_CTRL0_RXTO_ENABLE (1 << 27)
|
||||
#define AUART_CTRL0_RXTIMEOUT(v) (((v) & 0x7ff) << 16)
|
||||
#define AUART_CTRL0_XFER_COUNT(v) ((v) & 0xffff)
|
||||
|
||||
#define AUART_CTRL1_XFER_COUNT(v) ((v) & 0xffff)
|
||||
|
||||
#define AUART_CTRL2_DMAONERR (1 << 26)
|
||||
#define AUART_CTRL2_TXDMAE (1 << 25)
|
||||
#define AUART_CTRL2_RXDMAE (1 << 24)
|
||||
|
||||
#define AUART_CTRL2_CTSEN (1 << 15)
|
||||
#define AUART_CTRL2_RTSEN (1 << 14)
|
||||
@@ -111,29 +122,170 @@
|
||||
#define AUART_STAT_BERR (1 << 18)
|
||||
#define AUART_STAT_PERR (1 << 17)
|
||||
#define AUART_STAT_FERR (1 << 16)
|
||||
#define AUART_STAT_RXCOUNT_MASK 0xffff
|
||||
|
||||
static struct uart_driver auart_driver;
|
||||
|
||||
enum mxs_auart_type {
|
||||
IMX23_AUART,
|
||||
IMX28_AUART,
|
||||
};
|
||||
|
||||
struct mxs_auart_port {
|
||||
struct uart_port port;
|
||||
|
||||
unsigned int flags;
|
||||
#define MXS_AUART_DMA_CONFIG 0x1
|
||||
#define MXS_AUART_DMA_ENABLED 0x2
|
||||
#define MXS_AUART_DMA_TX_SYNC 2 /* bit 2 */
|
||||
#define MXS_AUART_DMA_RX_READY 3 /* bit 3 */
|
||||
unsigned long flags;
|
||||
unsigned int ctrl;
|
||||
enum mxs_auart_type devtype;
|
||||
|
||||
unsigned int irq;
|
||||
|
||||
struct clk *clk;
|
||||
struct device *dev;
|
||||
|
||||
/* for DMA */
|
||||
struct mxs_dma_data dma_data;
|
||||
int dma_channel_rx, dma_channel_tx;
|
||||
int dma_irq_rx, dma_irq_tx;
|
||||
int dma_channel;
|
||||
|
||||
struct scatterlist tx_sgl;
|
||||
struct dma_chan *tx_dma_chan;
|
||||
void *tx_dma_buf;
|
||||
|
||||
struct scatterlist rx_sgl;
|
||||
struct dma_chan *rx_dma_chan;
|
||||
void *rx_dma_buf;
|
||||
};
|
||||
|
||||
static struct platform_device_id mxs_auart_devtype[] = {
|
||||
{ .name = "mxs-auart-imx23", .driver_data = IMX23_AUART },
|
||||
{ .name = "mxs-auart-imx28", .driver_data = IMX28_AUART },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, mxs_auart_devtype);
|
||||
|
||||
static struct of_device_id mxs_auart_dt_ids[] = {
|
||||
{
|
||||
.compatible = "fsl,imx28-auart",
|
||||
.data = &mxs_auart_devtype[IMX28_AUART]
|
||||
}, {
|
||||
.compatible = "fsl,imx23-auart",
|
||||
.data = &mxs_auart_devtype[IMX23_AUART]
|
||||
}, { /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, mxs_auart_dt_ids);
|
||||
|
||||
static inline int is_imx28_auart(struct mxs_auart_port *s)
|
||||
{
|
||||
return s->devtype == IMX28_AUART;
|
||||
}
|
||||
|
||||
static inline bool auart_dma_enabled(struct mxs_auart_port *s)
|
||||
{
|
||||
return s->flags & MXS_AUART_DMA_ENABLED;
|
||||
}
|
||||
|
||||
static void mxs_auart_stop_tx(struct uart_port *u);
|
||||
|
||||
#define to_auart_port(u) container_of(u, struct mxs_auart_port, port)
|
||||
|
||||
static inline void mxs_auart_tx_chars(struct mxs_auart_port *s)
|
||||
static void mxs_auart_tx_chars(struct mxs_auart_port *s);
|
||||
|
||||
static void dma_tx_callback(void *param)
|
||||
{
|
||||
struct mxs_auart_port *s = param;
|
||||
struct circ_buf *xmit = &s->port.state->xmit;
|
||||
|
||||
dma_unmap_sg(s->dev, &s->tx_sgl, 1, DMA_TO_DEVICE);
|
||||
|
||||
/* clear the bit used to serialize the DMA tx. */
|
||||
clear_bit(MXS_AUART_DMA_TX_SYNC, &s->flags);
|
||||
smp_mb__after_clear_bit();
|
||||
|
||||
/* wake up the possible processes. */
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(&s->port);
|
||||
|
||||
mxs_auart_tx_chars(s);
|
||||
}
|
||||
|
||||
static int mxs_auart_dma_tx(struct mxs_auart_port *s, int size)
|
||||
{
|
||||
struct dma_async_tx_descriptor *desc;
|
||||
struct scatterlist *sgl = &s->tx_sgl;
|
||||
struct dma_chan *channel = s->tx_dma_chan;
|
||||
u32 pio;
|
||||
|
||||
/* [1] : send PIO. Note, the first pio word is CTRL1. */
|
||||
pio = AUART_CTRL1_XFER_COUNT(size);
|
||||
desc = dmaengine_prep_slave_sg(channel, (struct scatterlist *)&pio,
|
||||
1, DMA_TRANS_NONE, 0);
|
||||
if (!desc) {
|
||||
dev_err(s->dev, "step 1 error\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* [2] : set DMA buffer. */
|
||||
sg_init_one(sgl, s->tx_dma_buf, size);
|
||||
dma_map_sg(s->dev, sgl, 1, DMA_TO_DEVICE);
|
||||
desc = dmaengine_prep_slave_sg(channel, sgl,
|
||||
1, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
|
||||
if (!desc) {
|
||||
dev_err(s->dev, "step 2 error\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* [3] : submit the DMA */
|
||||
desc->callback = dma_tx_callback;
|
||||
desc->callback_param = s;
|
||||
dmaengine_submit(desc);
|
||||
dma_async_issue_pending(channel);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mxs_auart_tx_chars(struct mxs_auart_port *s)
|
||||
{
|
||||
struct circ_buf *xmit = &s->port.state->xmit;
|
||||
|
||||
if (auart_dma_enabled(s)) {
|
||||
int i = 0;
|
||||
int size;
|
||||
void *buffer = s->tx_dma_buf;
|
||||
|
||||
if (test_and_set_bit(MXS_AUART_DMA_TX_SYNC, &s->flags))
|
||||
return;
|
||||
|
||||
while (!uart_circ_empty(xmit) && !uart_tx_stopped(&s->port)) {
|
||||
size = min_t(u32, UART_XMIT_SIZE - i,
|
||||
CIRC_CNT_TO_END(xmit->head,
|
||||
xmit->tail,
|
||||
UART_XMIT_SIZE));
|
||||
memcpy(buffer + i, xmit->buf + xmit->tail, size);
|
||||
xmit->tail = (xmit->tail + size) & (UART_XMIT_SIZE - 1);
|
||||
|
||||
i += size;
|
||||
if (i >= UART_XMIT_SIZE)
|
||||
break;
|
||||
}
|
||||
|
||||
if (uart_tx_stopped(&s->port))
|
||||
mxs_auart_stop_tx(&s->port);
|
||||
|
||||
if (i) {
|
||||
mxs_auart_dma_tx(s, i);
|
||||
} else {
|
||||
clear_bit(MXS_AUART_DMA_TX_SYNC, &s->flags);
|
||||
smp_mb__after_clear_bit();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
while (!(readl(s->port.membase + AUART_STAT) &
|
||||
AUART_STAT_TXFF)) {
|
||||
if (s->port.x_char) {
|
||||
@@ -287,10 +439,159 @@ static u32 mxs_auart_get_mctrl(struct uart_port *u)
|
||||
return mctrl;
|
||||
}
|
||||
|
||||
static bool mxs_auart_dma_filter(struct dma_chan *chan, void *param)
|
||||
{
|
||||
struct mxs_auart_port *s = param;
|
||||
|
||||
if (!mxs_dma_is_apbx(chan))
|
||||
return false;
|
||||
|
||||
if (s->dma_channel == chan->chan_id) {
|
||||
chan->private = &s->dma_data;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static int mxs_auart_dma_prep_rx(struct mxs_auart_port *s);
|
||||
static void dma_rx_callback(void *arg)
|
||||
{
|
||||
struct mxs_auart_port *s = (struct mxs_auart_port *) arg;
|
||||
struct tty_struct *tty = s->port.state->port.tty;
|
||||
int count;
|
||||
u32 stat;
|
||||
|
||||
dma_unmap_sg(s->dev, &s->rx_sgl, 1, DMA_FROM_DEVICE);
|
||||
|
||||
stat = readl(s->port.membase + AUART_STAT);
|
||||
stat &= ~(AUART_STAT_OERR | AUART_STAT_BERR |
|
||||
AUART_STAT_PERR | AUART_STAT_FERR);
|
||||
|
||||
count = stat & AUART_STAT_RXCOUNT_MASK;
|
||||
tty_insert_flip_string(tty, s->rx_dma_buf, count);
|
||||
|
||||
writel(stat, s->port.membase + AUART_STAT);
|
||||
tty_flip_buffer_push(tty);
|
||||
|
||||
/* start the next DMA for RX. */
|
||||
mxs_auart_dma_prep_rx(s);
|
||||
}
|
||||
|
||||
static int mxs_auart_dma_prep_rx(struct mxs_auart_port *s)
|
||||
{
|
||||
struct dma_async_tx_descriptor *desc;
|
||||
struct scatterlist *sgl = &s->rx_sgl;
|
||||
struct dma_chan *channel = s->rx_dma_chan;
|
||||
u32 pio[1];
|
||||
|
||||
/* [1] : send PIO */
|
||||
pio[0] = AUART_CTRL0_RXTO_ENABLE
|
||||
| AUART_CTRL0_RXTIMEOUT(0x80)
|
||||
| AUART_CTRL0_XFER_COUNT(UART_XMIT_SIZE);
|
||||
desc = dmaengine_prep_slave_sg(channel, (struct scatterlist *)pio,
|
||||
1, DMA_TRANS_NONE, 0);
|
||||
if (!desc) {
|
||||
dev_err(s->dev, "step 1 error\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* [2] : send DMA request */
|
||||
sg_init_one(sgl, s->rx_dma_buf, UART_XMIT_SIZE);
|
||||
dma_map_sg(s->dev, sgl, 1, DMA_FROM_DEVICE);
|
||||
desc = dmaengine_prep_slave_sg(channel, sgl, 1, DMA_DEV_TO_MEM,
|
||||
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
|
||||
if (!desc) {
|
||||
dev_err(s->dev, "step 2 error\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* [3] : submit the DMA, but do not issue it. */
|
||||
desc->callback = dma_rx_callback;
|
||||
desc->callback_param = s;
|
||||
dmaengine_submit(desc);
|
||||
dma_async_issue_pending(channel);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mxs_auart_dma_exit_channel(struct mxs_auart_port *s)
|
||||
{
|
||||
if (s->tx_dma_chan) {
|
||||
dma_release_channel(s->tx_dma_chan);
|
||||
s->tx_dma_chan = NULL;
|
||||
}
|
||||
if (s->rx_dma_chan) {
|
||||
dma_release_channel(s->rx_dma_chan);
|
||||
s->rx_dma_chan = NULL;
|
||||
}
|
||||
|
||||
kfree(s->tx_dma_buf);
|
||||
kfree(s->rx_dma_buf);
|
||||
s->tx_dma_buf = NULL;
|
||||
s->rx_dma_buf = NULL;
|
||||
}
|
||||
|
||||
static void mxs_auart_dma_exit(struct mxs_auart_port *s)
|
||||
{
|
||||
|
||||
writel(AUART_CTRL2_TXDMAE | AUART_CTRL2_RXDMAE | AUART_CTRL2_DMAONERR,
|
||||
s->port.membase + AUART_CTRL2_CLR);
|
||||
|
||||
mxs_auart_dma_exit_channel(s);
|
||||
s->flags &= ~MXS_AUART_DMA_ENABLED;
|
||||
clear_bit(MXS_AUART_DMA_TX_SYNC, &s->flags);
|
||||
clear_bit(MXS_AUART_DMA_RX_READY, &s->flags);
|
||||
}
|
||||
|
||||
static int mxs_auart_dma_init(struct mxs_auart_port *s)
|
||||
{
|
||||
dma_cap_mask_t mask;
|
||||
|
||||
if (auart_dma_enabled(s))
|
||||
return 0;
|
||||
|
||||
/* We do not get the right DMA channels. */
|
||||
if (s->dma_channel_rx == -1 || s->dma_channel_rx == -1)
|
||||
return -EINVAL;
|
||||
|
||||
/* init for RX */
|
||||
dma_cap_zero(mask);
|
||||
dma_cap_set(DMA_SLAVE, mask);
|
||||
s->dma_channel = s->dma_channel_rx;
|
||||
s->dma_data.chan_irq = s->dma_irq_rx;
|
||||
s->rx_dma_chan = dma_request_channel(mask, mxs_auart_dma_filter, s);
|
||||
if (!s->rx_dma_chan)
|
||||
goto err_out;
|
||||
s->rx_dma_buf = kzalloc(UART_XMIT_SIZE, GFP_KERNEL | GFP_DMA);
|
||||
if (!s->rx_dma_buf)
|
||||
goto err_out;
|
||||
|
||||
/* init for TX */
|
||||
s->dma_channel = s->dma_channel_tx;
|
||||
s->dma_data.chan_irq = s->dma_irq_tx;
|
||||
s->tx_dma_chan = dma_request_channel(mask, mxs_auart_dma_filter, s);
|
||||
if (!s->tx_dma_chan)
|
||||
goto err_out;
|
||||
s->tx_dma_buf = kzalloc(UART_XMIT_SIZE, GFP_KERNEL | GFP_DMA);
|
||||
if (!s->tx_dma_buf)
|
||||
goto err_out;
|
||||
|
||||
/* set the flags */
|
||||
s->flags |= MXS_AUART_DMA_ENABLED;
|
||||
dev_dbg(s->dev, "enabled the DMA support.");
|
||||
|
||||
return 0;
|
||||
|
||||
err_out:
|
||||
mxs_auart_dma_exit_channel(s);
|
||||
return -EINVAL;
|
||||
|
||||
}
|
||||
|
||||
static void mxs_auart_settermios(struct uart_port *u,
|
||||
struct ktermios *termios,
|
||||
struct ktermios *old)
|
||||
{
|
||||
struct mxs_auart_port *s = to_auart_port(u);
|
||||
u32 bm, ctrl, ctrl2, div;
|
||||
unsigned int cflag, baud;
|
||||
|
||||
@@ -362,10 +663,23 @@ static void mxs_auart_settermios(struct uart_port *u,
|
||||
ctrl |= AUART_LINECTRL_STP2;
|
||||
|
||||
/* figure out the hardware flow control settings */
|
||||
if (cflag & CRTSCTS)
|
||||
if (cflag & CRTSCTS) {
|
||||
/*
|
||||
* The DMA has a bug(see errata:2836) in mx23.
|
||||
* So we can not implement the DMA for auart in mx23,
|
||||
* we can only implement the DMA support for auart
|
||||
* in mx28.
|
||||
*/
|
||||
if (is_imx28_auart(s) && (s->flags & MXS_AUART_DMA_CONFIG)) {
|
||||
if (!mxs_auart_dma_init(s))
|
||||
/* enable DMA tranfer */
|
||||
ctrl2 |= AUART_CTRL2_TXDMAE | AUART_CTRL2_RXDMAE
|
||||
| AUART_CTRL2_DMAONERR;
|
||||
}
|
||||
ctrl2 |= AUART_CTRL2_CTSEN | AUART_CTRL2_RTSEN;
|
||||
else
|
||||
} else {
|
||||
ctrl2 &= ~(AUART_CTRL2_CTSEN | AUART_CTRL2_RTSEN);
|
||||
}
|
||||
|
||||
/* set baud rate */
|
||||
baud = uart_get_baud_rate(u, termios, old, 0, u->uartclk);
|
||||
@@ -377,6 +691,19 @@ static void mxs_auart_settermios(struct uart_port *u,
|
||||
writel(ctrl2, u->membase + AUART_CTRL2);
|
||||
|
||||
uart_update_timeout(u, termios->c_cflag, baud);
|
||||
|
||||
/* prepare for the DMA RX. */
|
||||
if (auart_dma_enabled(s) &&
|
||||
!test_and_set_bit(MXS_AUART_DMA_RX_READY, &s->flags)) {
|
||||
if (!mxs_auart_dma_prep_rx(s)) {
|
||||
/* Disable the normal RX interrupt. */
|
||||
writel(AUART_INTR_RXIEN | AUART_INTR_RTIEN,
|
||||
u->membase + AUART_INTR_CLR);
|
||||
} else {
|
||||
mxs_auart_dma_exit(s);
|
||||
dev_err(s->dev, "We can not start up the DMA.\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static irqreturn_t mxs_auart_irq_handle(int irq, void *context)
|
||||
@@ -395,7 +722,8 @@ static irqreturn_t mxs_auart_irq_handle(int irq, void *context)
|
||||
}
|
||||
|
||||
if (istat & (AUART_INTR_RTIS | AUART_INTR_RXIS)) {
|
||||
mxs_auart_rx_chars(s);
|
||||
if (!auart_dma_enabled(s))
|
||||
mxs_auart_rx_chars(s);
|
||||
istat &= ~(AUART_INTR_RTIS | AUART_INTR_RXIS);
|
||||
}
|
||||
|
||||
@@ -455,6 +783,9 @@ static void mxs_auart_shutdown(struct uart_port *u)
|
||||
{
|
||||
struct mxs_auart_port *s = to_auart_port(u);
|
||||
|
||||
if (auart_dma_enabled(s))
|
||||
mxs_auart_dma_exit(s);
|
||||
|
||||
writel(AUART_CTRL2_UARTEN, u->membase + AUART_CTRL2_CLR);
|
||||
|
||||
writel(AUART_INTR_RXIEN | AUART_INTR_RTIEN | AUART_INTR_CTSMIEN,
|
||||
@@ -688,6 +1019,7 @@ static int serial_mxs_probe_dt(struct mxs_auart_port *s,
|
||||
struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
u32 dma_channel[2];
|
||||
int ret;
|
||||
|
||||
if (!np)
|
||||
@@ -701,11 +1033,27 @@ static int serial_mxs_probe_dt(struct mxs_auart_port *s,
|
||||
}
|
||||
s->port.line = ret;
|
||||
|
||||
s->dma_irq_rx = platform_get_irq(pdev, 1);
|
||||
s->dma_irq_tx = platform_get_irq(pdev, 2);
|
||||
|
||||
ret = of_property_read_u32_array(np, "fsl,auart-dma-channel",
|
||||
dma_channel, 2);
|
||||
if (ret == 0) {
|
||||
s->dma_channel_rx = dma_channel[0];
|
||||
s->dma_channel_tx = dma_channel[1];
|
||||
|
||||
s->flags |= MXS_AUART_DMA_CONFIG;
|
||||
} else {
|
||||
s->dma_channel_rx = -1;
|
||||
s->dma_channel_tx = -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit mxs_auart_probe(struct platform_device *pdev)
|
||||
static int mxs_auart_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct of_device_id *of_id =
|
||||
of_match_device(mxs_auart_dt_ids, &pdev->dev);
|
||||
struct mxs_auart_port *s;
|
||||
u32 version;
|
||||
int ret = 0;
|
||||
@@ -730,6 +1078,11 @@ static int __devinit mxs_auart_probe(struct platform_device *pdev)
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
if (of_id) {
|
||||
pdev->id_entry = of_id->data;
|
||||
s->devtype = pdev->id_entry->driver_data;
|
||||
}
|
||||
|
||||
s->clk = clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(s->clk)) {
|
||||
ret = PTR_ERR(s->clk);
|
||||
@@ -751,7 +1104,6 @@ static int __devinit mxs_auart_probe(struct platform_device *pdev)
|
||||
s->port.type = PORT_IMX;
|
||||
s->port.dev = s->dev = get_device(&pdev->dev);
|
||||
|
||||
s->flags = 0;
|
||||
s->ctrl = 0;
|
||||
|
||||
s->irq = platform_get_irq(pdev, 0);
|
||||
@@ -789,7 +1141,7 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit mxs_auart_remove(struct platform_device *pdev)
|
||||
static int mxs_auart_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct mxs_auart_port *s = platform_get_drvdata(pdev);
|
||||
|
||||
@@ -805,15 +1157,9 @@ static int __devexit mxs_auart_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct of_device_id mxs_auart_dt_ids[] = {
|
||||
{ .compatible = "fsl,imx23-auart", },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, mxs_auart_dt_ids);
|
||||
|
||||
static struct platform_driver mxs_auart_driver = {
|
||||
.probe = mxs_auart_probe,
|
||||
.remove = __devexit_p(mxs_auart_remove),
|
||||
.remove = mxs_auart_remove,
|
||||
.driver = {
|
||||
.name = "mxs-auart",
|
||||
.owner = THIS_MODULE,
|
||||
|
@@ -21,8 +21,10 @@
|
||||
#include <linux/of_serial.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/nwpserial.h>
|
||||
#include <linux/clk.h>
|
||||
|
||||
struct of_serial_info {
|
||||
struct clk *clk;
|
||||
int type;
|
||||
int line;
|
||||
};
|
||||
@@ -50,8 +52,9 @@ EXPORT_SYMBOL_GPL(tegra_serial_handle_break);
|
||||
/*
|
||||
* Fill a struct uart_port for a given device node
|
||||
*/
|
||||
static int __devinit of_platform_serial_setup(struct platform_device *ofdev,
|
||||
int type, struct uart_port *port)
|
||||
static int of_platform_serial_setup(struct platform_device *ofdev,
|
||||
int type, struct uart_port *port,
|
||||
struct of_serial_info *info)
|
||||
{
|
||||
struct resource resource;
|
||||
struct device_node *np = ofdev->dev.of_node;
|
||||
@@ -60,8 +63,17 @@ static int __devinit of_platform_serial_setup(struct platform_device *ofdev,
|
||||
|
||||
memset(port, 0, sizeof *port);
|
||||
if (of_property_read_u32(np, "clock-frequency", &clk)) {
|
||||
dev_warn(&ofdev->dev, "no clock-frequency property set\n");
|
||||
return -ENODEV;
|
||||
|
||||
/* Get clk rate through clk driver if present */
|
||||
info->clk = clk_get(&ofdev->dev, NULL);
|
||||
if (IS_ERR(info->clk)) {
|
||||
dev_warn(&ofdev->dev,
|
||||
"clk or clock-frequency not defined\n");
|
||||
return PTR_ERR(info->clk);
|
||||
}
|
||||
|
||||
clk_prepare_enable(info->clk);
|
||||
clk = clk_get_rate(info->clk);
|
||||
}
|
||||
/* If current-speed was set, then try not to change it. */
|
||||
if (of_property_read_u32(np, "current-speed", &spd) == 0)
|
||||
@@ -70,7 +82,7 @@ static int __devinit of_platform_serial_setup(struct platform_device *ofdev,
|
||||
ret = of_address_to_resource(np, 0, &resource);
|
||||
if (ret) {
|
||||
dev_warn(&ofdev->dev, "invalid address\n");
|
||||
return ret;
|
||||
goto out;
|
||||
}
|
||||
|
||||
spin_lock_init(&port->lock);
|
||||
@@ -97,7 +109,8 @@ static int __devinit of_platform_serial_setup(struct platform_device *ofdev,
|
||||
default:
|
||||
dev_warn(&ofdev->dev, "unsupported reg-io-width (%d)\n",
|
||||
prop);
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,13 +128,17 @@ static int __devinit of_platform_serial_setup(struct platform_device *ofdev,
|
||||
port->handle_break = tegra_serial_handle_break;
|
||||
|
||||
return 0;
|
||||
out:
|
||||
if (info->clk)
|
||||
clk_disable_unprepare(info->clk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to register a serial port
|
||||
*/
|
||||
static struct of_device_id of_platform_serial_table[];
|
||||
static int __devinit of_platform_serial_probe(struct platform_device *ofdev)
|
||||
static int of_platform_serial_probe(struct platform_device *ofdev)
|
||||
{
|
||||
const struct of_device_id *match;
|
||||
struct of_serial_info *info;
|
||||
@@ -141,7 +158,7 @@ static int __devinit of_platform_serial_probe(struct platform_device *ofdev)
|
||||
return -ENOMEM;
|
||||
|
||||
port_type = (unsigned long)match->data;
|
||||
ret = of_platform_serial_setup(ofdev, port_type, &port);
|
||||
ret = of_platform_serial_setup(ofdev, port_type, &port, info);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
@@ -204,6 +221,9 @@ static int of_platform_serial_remove(struct platform_device *ofdev)
|
||||
/* need to add code for these */
|
||||
break;
|
||||
}
|
||||
|
||||
if (info->clk)
|
||||
clk_disable_unprepare(info->clk);
|
||||
kfree(info);
|
||||
return 0;
|
||||
}
|
||||
@@ -211,7 +231,7 @@ static int of_platform_serial_remove(struct platform_device *ofdev)
|
||||
/*
|
||||
* A few common types, add more as needed.
|
||||
*/
|
||||
static struct of_device_id __devinitdata of_platform_serial_table[] = {
|
||||
static struct of_device_id of_platform_serial_table[] = {
|
||||
{ .compatible = "ns8250", .data = (void *)PORT_8250, },
|
||||
{ .compatible = "ns16450", .data = (void *)PORT_16450, },
|
||||
{ .compatible = "ns16550a", .data = (void *)PORT_16550A, },
|
||||
|
@@ -96,7 +96,7 @@ struct uart_omap_port {
|
||||
unsigned char msr_saved_flags;
|
||||
char name[20];
|
||||
unsigned long port_activity;
|
||||
u32 context_loss_cnt;
|
||||
int context_loss_cnt;
|
||||
u32 errata;
|
||||
u8 wakeups_enabled;
|
||||
unsigned int irq_pending:1;
|
||||
@@ -702,11 +702,7 @@ serial_omap_configure_xonxoff
|
||||
serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
|
||||
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
|
||||
serial_out(up, UART_TI752_TCR, OMAP_UART_TCR_TRIG);
|
||||
/* Enable special char function UARTi.EFR_REG[5] and
|
||||
* load the new software flow control mode IXON or IXOFF
|
||||
* and restore the UARTi.EFR_REG[4] ENHANCED_EN value.
|
||||
*/
|
||||
serial_out(up, UART_EFR, up->efr | UART_EFR_SCD);
|
||||
|
||||
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
|
||||
|
||||
serial_out(up, UART_MCR, up->mcr & ~UART_MCR_TCRTLR);
|
||||
@@ -1081,7 +1077,7 @@ out:
|
||||
|
||||
#ifdef CONFIG_SERIAL_OMAP_CONSOLE
|
||||
|
||||
static struct uart_omap_port *serial_omap_console_ports[4];
|
||||
static struct uart_omap_port *serial_omap_console_ports[OMAP_MAX_HSUART_PORTS];
|
||||
|
||||
static struct uart_driver serial_omap_reg;
|
||||
|
||||
@@ -1242,7 +1238,7 @@ static int serial_omap_resume(struct device *dev)
|
||||
}
|
||||
#endif
|
||||
|
||||
static void __devinit omap_serial_fill_features_erratas(struct uart_omap_port *up)
|
||||
static void omap_serial_fill_features_erratas(struct uart_omap_port *up)
|
||||
{
|
||||
u32 mvr, scheme;
|
||||
u16 revision, major, minor;
|
||||
@@ -1295,7 +1291,7 @@ static void __devinit omap_serial_fill_features_erratas(struct uart_omap_port *u
|
||||
}
|
||||
}
|
||||
|
||||
static __devinit struct omap_uart_port_info *of_get_uart_port_info(struct device *dev)
|
||||
static struct omap_uart_port_info *of_get_uart_port_info(struct device *dev)
|
||||
{
|
||||
struct omap_uart_port_info *omap_up_info;
|
||||
|
||||
@@ -1308,7 +1304,7 @@ static __devinit struct omap_uart_port_info *of_get_uart_port_info(struct device
|
||||
return omap_up_info;
|
||||
}
|
||||
|
||||
static int __devinit serial_omap_probe(struct platform_device *pdev)
|
||||
static int serial_omap_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct uart_omap_port *up;
|
||||
struct resource *mem, *irq;
|
||||
@@ -1445,7 +1441,7 @@ err_port_line:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit serial_omap_remove(struct platform_device *dev)
|
||||
static int serial_omap_remove(struct platform_device *dev)
|
||||
{
|
||||
struct uart_omap_port *up = platform_get_drvdata(dev);
|
||||
|
||||
@@ -1556,11 +1552,15 @@ static int serial_omap_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct uart_omap_port *up = dev_get_drvdata(dev);
|
||||
|
||||
u32 loss_cnt = serial_omap_get_context_loss_count(up);
|
||||
int loss_cnt = serial_omap_get_context_loss_count(up);
|
||||
|
||||
if (up->context_loss_cnt != loss_cnt)
|
||||
if (loss_cnt < 0) {
|
||||
dev_err(dev, "serial_omap_get_context_loss_count failed : %d\n",
|
||||
loss_cnt);
|
||||
serial_omap_restore_context(up);
|
||||
|
||||
} else if (up->context_loss_cnt != loss_cnt) {
|
||||
serial_omap_restore_context(up);
|
||||
}
|
||||
up->latency = up->calc_latency;
|
||||
schedule_work(&up->qos_work);
|
||||
|
||||
@@ -1586,7 +1586,7 @@ MODULE_DEVICE_TABLE(of, omap_serial_of_match);
|
||||
|
||||
static struct platform_driver serial_omap_driver = {
|
||||
.probe = serial_omap_probe,
|
||||
.remove = __devexit_p(serial_omap_remove),
|
||||
.remove = serial_omap_remove,
|
||||
.driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.pm = &serial_omap_dev_pm_ops,
|
||||
|
@@ -1839,7 +1839,7 @@ static DEFINE_PCI_DEVICE_TABLE(pch_uart_pci_id) = {
|
||||
{0,},
|
||||
};
|
||||
|
||||
static int __devinit pch_uart_pci_probe(struct pci_dev *pdev,
|
||||
static int pch_uart_pci_probe(struct pci_dev *pdev,
|
||||
const struct pci_device_id *id)
|
||||
{
|
||||
int ret;
|
||||
@@ -1869,7 +1869,7 @@ static struct pci_driver pch_uart_pci_driver = {
|
||||
.name = "pch_uart",
|
||||
.id_table = pch_uart_pci_id,
|
||||
.probe = pch_uart_pci_probe,
|
||||
.remove = __devexit_p(pch_uart_pci_remove),
|
||||
.remove = pch_uart_pci_remove,
|
||||
.suspend = pch_uart_pci_suspend,
|
||||
.resume = pch_uart_pci_resume,
|
||||
};
|
||||
|
@@ -705,6 +705,57 @@ serial_pxa_console_write(struct console *co, const char *s, unsigned int count)
|
||||
clk_disable_unprepare(up->clk);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CONSOLE_POLL
|
||||
/*
|
||||
* Console polling routines for writing and reading from the uart while
|
||||
* in an interrupt or debug context.
|
||||
*/
|
||||
|
||||
static int serial_pxa_get_poll_char(struct uart_port *port)
|
||||
{
|
||||
struct uart_pxa_port *up = (struct uart_pxa_port *)port;
|
||||
unsigned char lsr = serial_in(up, UART_LSR);
|
||||
|
||||
while (!(lsr & UART_LSR_DR))
|
||||
lsr = serial_in(up, UART_LSR);
|
||||
|
||||
return serial_in(up, UART_RX);
|
||||
}
|
||||
|
||||
|
||||
static void serial_pxa_put_poll_char(struct uart_port *port,
|
||||
unsigned char c)
|
||||
{
|
||||
unsigned int ier;
|
||||
struct uart_pxa_port *up = (struct uart_pxa_port *)port;
|
||||
|
||||
/*
|
||||
* First save the IER then disable the interrupts
|
||||
*/
|
||||
ier = serial_in(up, UART_IER);
|
||||
serial_out(up, UART_IER, UART_IER_UUE);
|
||||
|
||||
wait_for_xmitr(up);
|
||||
/*
|
||||
* Send the character out.
|
||||
* If a LF, also do CR...
|
||||
*/
|
||||
serial_out(up, UART_TX, c);
|
||||
if (c == 10) {
|
||||
wait_for_xmitr(up);
|
||||
serial_out(up, UART_TX, 13);
|
||||
}
|
||||
|
||||
/*
|
||||
* Finally, wait for transmitter to become empty
|
||||
* and restore the IER
|
||||
*/
|
||||
wait_for_xmitr(up);
|
||||
serial_out(up, UART_IER, ier);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_CONSOLE_POLL */
|
||||
|
||||
static int __init
|
||||
serial_pxa_console_setup(struct console *co, char *options)
|
||||
{
|
||||
@@ -759,6 +810,10 @@ struct uart_ops serial_pxa_pops = {
|
||||
.request_port = serial_pxa_request_port,
|
||||
.config_port = serial_pxa_config_port,
|
||||
.verify_port = serial_pxa_verify_port,
|
||||
#ifdef CONFIG_CONSOLE_POLL
|
||||
.poll_get_char = serial_pxa_get_poll_char,
|
||||
.poll_put_char = serial_pxa_put_poll_char,
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct uart_driver serial_pxa_reg = {
|
||||
|
@@ -637,7 +637,7 @@ static void __init sa1100_init_ports(void)
|
||||
PPSR |= PPC_TXD1 | PPC_TXD3;
|
||||
}
|
||||
|
||||
void __devinit sa1100_register_uart_fns(struct sa1100_port_fns *fns)
|
||||
void sa1100_register_uart_fns(struct sa1100_port_fns *fns)
|
||||
{
|
||||
if (fns->get_mctrl)
|
||||
sa1100_pops.get_mctrl = fns->get_mctrl;
|
||||
|
@@ -223,8 +223,11 @@ s3c24xx_serial_rx_chars(int irq, void *dev_id)
|
||||
struct uart_port *port = &ourport->port;
|
||||
struct tty_struct *tty = port->state->port.tty;
|
||||
unsigned int ufcon, ch, flag, ufstat, uerstat;
|
||||
unsigned long flags;
|
||||
int max_count = 64;
|
||||
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
|
||||
while (max_count-- > 0) {
|
||||
ufcon = rd_regl(port, S3C2410_UFCON);
|
||||
ufstat = rd_regl(port, S3C2410_UFSTAT);
|
||||
@@ -299,6 +302,7 @@ s3c24xx_serial_rx_chars(int irq, void *dev_id)
|
||||
tty_flip_buffer_push(tty);
|
||||
|
||||
out:
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
@@ -307,8 +311,11 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
|
||||
struct s3c24xx_uart_port *ourport = id;
|
||||
struct uart_port *port = &ourport->port;
|
||||
struct circ_buf *xmit = &port->state->xmit;
|
||||
unsigned long flags;
|
||||
int count = 256;
|
||||
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
|
||||
if (port->x_char) {
|
||||
wr_regb(port, S3C2410_UTXH, port->x_char);
|
||||
port->icount.tx++;
|
||||
@@ -336,13 +343,17 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
|
||||
port->icount.tx++;
|
||||
}
|
||||
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) {
|
||||
spin_unlock(&port->lock);
|
||||
uart_write_wakeup(port);
|
||||
spin_lock(&port->lock);
|
||||
}
|
||||
|
||||
if (uart_circ_empty(xmit))
|
||||
s3c24xx_serial_stop_tx(port);
|
||||
|
||||
out:
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
@@ -352,10 +363,8 @@ static irqreturn_t s3c64xx_serial_handle_irq(int irq, void *id)
|
||||
struct s3c24xx_uart_port *ourport = id;
|
||||
struct uart_port *port = &ourport->port;
|
||||
unsigned int pend = rd_regl(port, S3C64XX_UINTP);
|
||||
unsigned long flags;
|
||||
irqreturn_t ret = IRQ_HANDLED;
|
||||
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
if (pend & S3C64XX_UINTM_RXD_MSK) {
|
||||
ret = s3c24xx_serial_rx_chars(irq, id);
|
||||
wr_regl(port, S3C64XX_UINTP, S3C64XX_UINTM_RXD_MSK);
|
||||
@@ -364,7 +373,6 @@ static irqreturn_t s3c64xx_serial_handle_irq(int irq, void *id)
|
||||
ret = s3c24xx_serial_tx_chars(irq, id);
|
||||
wr_regl(port, S3C64XX_UINTP, S3C64XX_UINTM_TXD_MSK);
|
||||
}
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -530,16 +538,16 @@ static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,
|
||||
switch (level) {
|
||||
case 3:
|
||||
if (!IS_ERR(ourport->baudclk))
|
||||
clk_disable(ourport->baudclk);
|
||||
clk_disable_unprepare(ourport->baudclk);
|
||||
|
||||
clk_disable(ourport->clk);
|
||||
clk_disable_unprepare(ourport->clk);
|
||||
break;
|
||||
|
||||
case 0:
|
||||
clk_enable(ourport->clk);
|
||||
clk_prepare_enable(ourport->clk);
|
||||
|
||||
if (!IS_ERR(ourport->baudclk))
|
||||
clk_enable(ourport->baudclk);
|
||||
clk_prepare_enable(ourport->baudclk);
|
||||
|
||||
break;
|
||||
default:
|
||||
@@ -713,11 +721,11 @@ static void s3c24xx_serial_set_termios(struct uart_port *port,
|
||||
s3c24xx_serial_setsource(port, clk_sel);
|
||||
|
||||
if (!IS_ERR(ourport->baudclk)) {
|
||||
clk_disable(ourport->baudclk);
|
||||
clk_disable_unprepare(ourport->baudclk);
|
||||
ourport->baudclk = ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
clk_enable(clk);
|
||||
clk_prepare_enable(clk);
|
||||
|
||||
ourport->baudclk = clk;
|
||||
ourport->baudclk_rate = clk ? clk_get_rate(clk) : 0;
|
||||
@@ -1256,7 +1264,7 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit s3c24xx_serial_remove(struct platform_device *dev)
|
||||
static int s3c24xx_serial_remove(struct platform_device *dev)
|
||||
{
|
||||
struct uart_port *port = s3c24xx_dev_to_port(&dev->dev);
|
||||
|
||||
@@ -1287,9 +1295,9 @@ static int s3c24xx_serial_resume(struct device *dev)
|
||||
struct s3c24xx_uart_port *ourport = to_ourport(port);
|
||||
|
||||
if (port) {
|
||||
clk_enable(ourport->clk);
|
||||
clk_prepare_enable(ourport->clk);
|
||||
s3c24xx_serial_resetport(port, s3c24xx_port_to_cfg(port));
|
||||
clk_disable(ourport->clk);
|
||||
clk_disable_unprepare(ourport->clk);
|
||||
|
||||
uart_resume_port(&s3c24xx_uart_drv, port);
|
||||
}
|
||||
@@ -1701,6 +1709,16 @@ MODULE_DEVICE_TABLE(platform, s3c24xx_serial_driver_ids);
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id s3c24xx_uart_dt_match[] = {
|
||||
{ .compatible = "samsung,s3c2410-uart",
|
||||
.data = (void *)S3C2410_SERIAL_DRV_DATA },
|
||||
{ .compatible = "samsung,s3c2412-uart",
|
||||
.data = (void *)S3C2412_SERIAL_DRV_DATA },
|
||||
{ .compatible = "samsung,s3c2440-uart",
|
||||
.data = (void *)S3C2440_SERIAL_DRV_DATA },
|
||||
{ .compatible = "samsung,s3c6400-uart",
|
||||
.data = (void *)S3C6400_SERIAL_DRV_DATA },
|
||||
{ .compatible = "samsung,s5pv210-uart",
|
||||
.data = (void *)S5PV210_SERIAL_DRV_DATA },
|
||||
{ .compatible = "samsung,exynos4210-uart",
|
||||
.data = (void *)EXYNOS4210_SERIAL_DRV_DATA },
|
||||
{},
|
||||
@@ -1712,7 +1730,7 @@ MODULE_DEVICE_TABLE(of, s3c24xx_uart_dt_match);
|
||||
|
||||
static struct platform_driver samsung_serial_driver = {
|
||||
.probe = s3c24xx_serial_probe,
|
||||
.remove = __devexit_p(s3c24xx_serial_remove),
|
||||
.remove = s3c24xx_serial_remove,
|
||||
.id_table = s3c24xx_serial_driver_ids,
|
||||
.driver = {
|
||||
.name = "samsung-uart",
|
||||
|
@@ -621,7 +621,7 @@ static u8 sc26xx_flags2mask(unsigned int flags, unsigned int bitpos)
|
||||
return bit ? (1 << (bit - 1)) : 0;
|
||||
}
|
||||
|
||||
static void __devinit sc26xx_init_masks(struct uart_sc26xx_port *up,
|
||||
static void sc26xx_init_masks(struct uart_sc26xx_port *up,
|
||||
int line, unsigned int data)
|
||||
{
|
||||
up->dtr_mask[line] = sc26xx_flags2mask(data, 0);
|
||||
@@ -632,7 +632,7 @@ static void __devinit sc26xx_init_masks(struct uart_sc26xx_port *up,
|
||||
up->ri_mask[line] = sc26xx_flags2mask(data, 20);
|
||||
}
|
||||
|
||||
static int __devinit sc26xx_probe(struct platform_device *dev)
|
||||
static int sc26xx_probe(struct platform_device *dev)
|
||||
{
|
||||
struct resource *res;
|
||||
struct uart_sc26xx_port *up;
|
||||
@@ -733,7 +733,7 @@ static int __exit sc26xx_driver_remove(struct platform_device *dev)
|
||||
|
||||
static struct platform_driver sc26xx_driver = {
|
||||
.probe = sc26xx_probe,
|
||||
.remove = __devexit_p(sc26xx_driver_remove),
|
||||
.remove = sc26xx_driver_remove,
|
||||
.driver = {
|
||||
.name = "SC26xx",
|
||||
.owner = THIS_MODULE,
|
||||
|
@@ -740,7 +740,7 @@ static int sccnxp_console_setup(struct console *co, char *options)
|
||||
}
|
||||
#endif
|
||||
|
||||
static int __devinit sccnxp_probe(struct platform_device *pdev)
|
||||
static int sccnxp_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
int chiptype = pdev->id_entry->driver_data;
|
||||
@@ -943,7 +943,7 @@ err_out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit sccnxp_remove(struct platform_device *pdev)
|
||||
static int sccnxp_remove(struct platform_device *pdev)
|
||||
{
|
||||
int i;
|
||||
struct sccnxp_port *s = platform_get_drvdata(pdev);
|
||||
@@ -981,7 +981,7 @@ static struct platform_driver sccnxp_uart_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = sccnxp_probe,
|
||||
.remove = __devexit_p(sccnxp_remove),
|
||||
.remove = sccnxp_remove,
|
||||
.id_table = sccnxp_id_table,
|
||||
};
|
||||
module_platform_driver(sccnxp_uart_driver);
|
||||
|
@@ -634,10 +634,10 @@ static void uart_unthrottle(struct tty_struct *tty)
|
||||
uart_set_mctrl(port, TIOCM_RTS);
|
||||
}
|
||||
|
||||
static void uart_get_info(struct tty_port *port,
|
||||
struct uart_state *state,
|
||||
static void do_uart_get_info(struct tty_port *port,
|
||||
struct serial_struct *retinfo)
|
||||
{
|
||||
struct uart_state *state = container_of(port, struct uart_state, port);
|
||||
struct uart_port *uport = state->uart_port;
|
||||
|
||||
memset(retinfo, 0, sizeof(*retinfo));
|
||||
@@ -662,17 +662,21 @@ static void uart_get_info(struct tty_port *port,
|
||||
retinfo->iomem_base = (void *)(unsigned long)uport->mapbase;
|
||||
}
|
||||
|
||||
static int uart_get_info_user(struct uart_state *state,
|
||||
struct serial_struct __user *retinfo)
|
||||
static void uart_get_info(struct tty_port *port,
|
||||
struct serial_struct *retinfo)
|
||||
{
|
||||
struct tty_port *port = &state->port;
|
||||
struct serial_struct tmp;
|
||||
|
||||
/* Ensure the state we copy is consistent and no hardware changes
|
||||
occur as we go */
|
||||
mutex_lock(&port->mutex);
|
||||
uart_get_info(port, state, &tmp);
|
||||
do_uart_get_info(port, retinfo);
|
||||
mutex_unlock(&port->mutex);
|
||||
}
|
||||
|
||||
static int uart_get_info_user(struct tty_port *port,
|
||||
struct serial_struct __user *retinfo)
|
||||
{
|
||||
struct serial_struct tmp;
|
||||
uart_get_info(port, &tmp);
|
||||
|
||||
if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
|
||||
return -EFAULT;
|
||||
@@ -1131,7 +1135,7 @@ uart_ioctl(struct tty_struct *tty, unsigned int cmd,
|
||||
*/
|
||||
switch (cmd) {
|
||||
case TIOCGSERIAL:
|
||||
ret = uart_get_info_user(state, uarg);
|
||||
ret = uart_get_info_user(port, uarg);
|
||||
break;
|
||||
|
||||
case TIOCSSERIAL:
|
||||
@@ -2293,6 +2297,8 @@ int uart_register_driver(struct uart_driver *drv)
|
||||
if (retval >= 0)
|
||||
return retval;
|
||||
|
||||
for (i = 0; i < drv->nr; i++)
|
||||
tty_port_destroy(&drv->state[i].port);
|
||||
put_tty_driver(normal);
|
||||
out_kfree:
|
||||
kfree(drv->state);
|
||||
@@ -2312,8 +2318,12 @@ out:
|
||||
void uart_unregister_driver(struct uart_driver *drv)
|
||||
{
|
||||
struct tty_driver *p = drv->tty_driver;
|
||||
unsigned int i;
|
||||
|
||||
tty_unregister_driver(p);
|
||||
put_tty_driver(p);
|
||||
for (i = 0; i < drv->nr; i++)
|
||||
tty_port_destroy(&drv->state[i].port);
|
||||
kfree(drv->state);
|
||||
drv->state = NULL;
|
||||
drv->tty_driver = NULL;
|
||||
@@ -2329,21 +2339,166 @@ struct tty_driver *uart_console_device(struct console *co, int *index)
|
||||
static ssize_t uart_get_attr_uartclk(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int ret;
|
||||
struct serial_struct tmp;
|
||||
struct tty_port *port = dev_get_drvdata(dev);
|
||||
struct uart_state *state = container_of(port, struct uart_state, port);
|
||||
|
||||
mutex_lock(&state->port.mutex);
|
||||
ret = snprintf(buf, PAGE_SIZE, "%d\n", state->uart_port->uartclk);
|
||||
mutex_unlock(&state->port.mutex);
|
||||
|
||||
return ret;
|
||||
uart_get_info(port, &tmp);
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", tmp.baud_base * 16);
|
||||
}
|
||||
|
||||
static ssize_t uart_get_attr_type(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct serial_struct tmp;
|
||||
struct tty_port *port = dev_get_drvdata(dev);
|
||||
|
||||
uart_get_info(port, &tmp);
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", tmp.type);
|
||||
}
|
||||
static ssize_t uart_get_attr_line(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct serial_struct tmp;
|
||||
struct tty_port *port = dev_get_drvdata(dev);
|
||||
|
||||
uart_get_info(port, &tmp);
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", tmp.line);
|
||||
}
|
||||
|
||||
static ssize_t uart_get_attr_port(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct serial_struct tmp;
|
||||
struct tty_port *port = dev_get_drvdata(dev);
|
||||
unsigned long ioaddr;
|
||||
|
||||
uart_get_info(port, &tmp);
|
||||
ioaddr = tmp.port;
|
||||
if (HIGH_BITS_OFFSET)
|
||||
ioaddr |= (unsigned long)tmp.port_high << HIGH_BITS_OFFSET;
|
||||
return snprintf(buf, PAGE_SIZE, "0x%lX\n", ioaddr);
|
||||
}
|
||||
|
||||
static ssize_t uart_get_attr_irq(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct serial_struct tmp;
|
||||
struct tty_port *port = dev_get_drvdata(dev);
|
||||
|
||||
uart_get_info(port, &tmp);
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", tmp.irq);
|
||||
}
|
||||
|
||||
static ssize_t uart_get_attr_flags(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct serial_struct tmp;
|
||||
struct tty_port *port = dev_get_drvdata(dev);
|
||||
|
||||
uart_get_info(port, &tmp);
|
||||
return snprintf(buf, PAGE_SIZE, "0x%X\n", tmp.flags);
|
||||
}
|
||||
|
||||
static ssize_t uart_get_attr_xmit_fifo_size(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct serial_struct tmp;
|
||||
struct tty_port *port = dev_get_drvdata(dev);
|
||||
|
||||
uart_get_info(port, &tmp);
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", tmp.xmit_fifo_size);
|
||||
}
|
||||
|
||||
|
||||
static ssize_t uart_get_attr_close_delay(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct serial_struct tmp;
|
||||
struct tty_port *port = dev_get_drvdata(dev);
|
||||
|
||||
uart_get_info(port, &tmp);
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", tmp.close_delay);
|
||||
}
|
||||
|
||||
|
||||
static ssize_t uart_get_attr_closing_wait(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct serial_struct tmp;
|
||||
struct tty_port *port = dev_get_drvdata(dev);
|
||||
|
||||
uart_get_info(port, &tmp);
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", tmp.closing_wait);
|
||||
}
|
||||
|
||||
static ssize_t uart_get_attr_custom_divisor(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct serial_struct tmp;
|
||||
struct tty_port *port = dev_get_drvdata(dev);
|
||||
|
||||
uart_get_info(port, &tmp);
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", tmp.custom_divisor);
|
||||
}
|
||||
|
||||
static ssize_t uart_get_attr_io_type(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct serial_struct tmp;
|
||||
struct tty_port *port = dev_get_drvdata(dev);
|
||||
|
||||
uart_get_info(port, &tmp);
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", tmp.io_type);
|
||||
}
|
||||
|
||||
static ssize_t uart_get_attr_iomem_base(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct serial_struct tmp;
|
||||
struct tty_port *port = dev_get_drvdata(dev);
|
||||
|
||||
uart_get_info(port, &tmp);
|
||||
return snprintf(buf, PAGE_SIZE, "0x%lX\n", (unsigned long)tmp.iomem_base);
|
||||
}
|
||||
|
||||
static ssize_t uart_get_attr_iomem_reg_shift(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct serial_struct tmp;
|
||||
struct tty_port *port = dev_get_drvdata(dev);
|
||||
|
||||
uart_get_info(port, &tmp);
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", tmp.iomem_reg_shift);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(type, S_IRUSR | S_IRGRP, uart_get_attr_type, NULL);
|
||||
static DEVICE_ATTR(line, S_IRUSR | S_IRGRP, uart_get_attr_line, NULL);
|
||||
static DEVICE_ATTR(port, S_IRUSR | S_IRGRP, uart_get_attr_port, NULL);
|
||||
static DEVICE_ATTR(irq, S_IRUSR | S_IRGRP, uart_get_attr_irq, NULL);
|
||||
static DEVICE_ATTR(flags, S_IRUSR | S_IRGRP, uart_get_attr_flags, NULL);
|
||||
static DEVICE_ATTR(xmit_fifo_size, S_IRUSR | S_IRGRP, uart_get_attr_xmit_fifo_size, NULL);
|
||||
static DEVICE_ATTR(uartclk, S_IRUSR | S_IRGRP, uart_get_attr_uartclk, NULL);
|
||||
static DEVICE_ATTR(close_delay, S_IRUSR | S_IRGRP, uart_get_attr_close_delay, NULL);
|
||||
static DEVICE_ATTR(closing_wait, S_IRUSR | S_IRGRP, uart_get_attr_closing_wait, NULL);
|
||||
static DEVICE_ATTR(custom_divisor, S_IRUSR | S_IRGRP, uart_get_attr_custom_divisor, NULL);
|
||||
static DEVICE_ATTR(io_type, S_IRUSR | S_IRGRP, uart_get_attr_io_type, NULL);
|
||||
static DEVICE_ATTR(iomem_base, S_IRUSR | S_IRGRP, uart_get_attr_iomem_base, NULL);
|
||||
static DEVICE_ATTR(iomem_reg_shift, S_IRUSR | S_IRGRP, uart_get_attr_iomem_reg_shift, NULL);
|
||||
|
||||
static struct attribute *tty_dev_attrs[] = {
|
||||
&dev_attr_type.attr,
|
||||
&dev_attr_line.attr,
|
||||
&dev_attr_port.attr,
|
||||
&dev_attr_irq.attr,
|
||||
&dev_attr_flags.attr,
|
||||
&dev_attr_xmit_fifo_size.attr,
|
||||
&dev_attr_uartclk.attr,
|
||||
&dev_attr_close_delay.attr,
|
||||
&dev_attr_closing_wait.attr,
|
||||
&dev_attr_custom_divisor.attr,
|
||||
&dev_attr_io_type.attr,
|
||||
&dev_attr_iomem_base.attr,
|
||||
&dev_attr_iomem_reg_shift.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
@@ -2356,6 +2511,7 @@ static const struct attribute_group *tty_dev_attr_groups[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* uart_add_one_port - attach a driver-defined port structure
|
||||
* @drv: pointer to the uart low level driver structure for this port
|
||||
|
@@ -1030,7 +1030,7 @@ static DEFINE_MUTEX(serial_txx9_mutex);
|
||||
*
|
||||
* On success the port is ready to use and the line number is returned.
|
||||
*/
|
||||
static int __devinit serial_txx9_register_port(struct uart_port *port)
|
||||
static int serial_txx9_register_port(struct uart_port *port)
|
||||
{
|
||||
int i;
|
||||
struct uart_txx9_port *uart;
|
||||
@@ -1078,7 +1078,7 @@ static int __devinit serial_txx9_register_port(struct uart_port *port)
|
||||
* Remove one serial port. This may not be called from interrupt
|
||||
* context. We hand the port back to the our control.
|
||||
*/
|
||||
static void __devexit serial_txx9_unregister_port(int line)
|
||||
static void serial_txx9_unregister_port(int line)
|
||||
{
|
||||
struct uart_txx9_port *uart = &serial_txx9_ports[line];
|
||||
|
||||
@@ -1096,7 +1096,7 @@ static void __devexit serial_txx9_unregister_port(int line)
|
||||
/*
|
||||
* Register a set of serial devices attached to a platform device.
|
||||
*/
|
||||
static int __devinit serial_txx9_probe(struct platform_device *dev)
|
||||
static int serial_txx9_probe(struct platform_device *dev)
|
||||
{
|
||||
struct uart_port *p = dev->dev.platform_data;
|
||||
struct uart_port port;
|
||||
@@ -1126,7 +1126,7 @@ static int __devinit serial_txx9_probe(struct platform_device *dev)
|
||||
/*
|
||||
* Remove serial ports registered against a platform device.
|
||||
*/
|
||||
static int __devexit serial_txx9_remove(struct platform_device *dev)
|
||||
static int serial_txx9_remove(struct platform_device *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -1171,7 +1171,7 @@ static int serial_txx9_resume(struct platform_device *dev)
|
||||
|
||||
static struct platform_driver serial_txx9_plat_driver = {
|
||||
.probe = serial_txx9_probe,
|
||||
.remove = __devexit_p(serial_txx9_remove),
|
||||
.remove = serial_txx9_remove,
|
||||
#ifdef CONFIG_PM
|
||||
.suspend = serial_txx9_suspend,
|
||||
.resume = serial_txx9_resume,
|
||||
@@ -1187,7 +1187,7 @@ static struct platform_driver serial_txx9_plat_driver = {
|
||||
* Probe one serial board. Unfortunately, there is no rhyme nor reason
|
||||
* to the arrangement of serial ports on a PCI card.
|
||||
*/
|
||||
static int __devinit
|
||||
static int
|
||||
pciserial_txx9_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
|
||||
{
|
||||
struct uart_port port;
|
||||
@@ -1217,7 +1217,7 @@ pciserial_txx9_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __devexit pciserial_txx9_remove_one(struct pci_dev *dev)
|
||||
static void pciserial_txx9_remove_one(struct pci_dev *dev)
|
||||
{
|
||||
struct uart_txx9_port *up = pci_get_drvdata(dev);
|
||||
|
||||
@@ -1261,7 +1261,7 @@ static const struct pci_device_id serial_txx9_pci_tbl[] = {
|
||||
static struct pci_driver serial_txx9_pci_driver = {
|
||||
.name = "serial_txx9",
|
||||
.probe = pciserial_txx9_init_one,
|
||||
.remove = __devexit_p(pciserial_txx9_remove_one),
|
||||
.remove = pciserial_txx9_remove_one,
|
||||
#ifdef CONFIG_PM
|
||||
.suspend = pciserial_txx9_suspend_one,
|
||||
.resume = pciserial_txx9_resume_one,
|
||||
|
@@ -99,12 +99,6 @@ struct sci_port {
|
||||
#endif
|
||||
|
||||
struct notifier_block freq_transition;
|
||||
|
||||
#ifdef CONFIG_SERIAL_SH_SCI_CONSOLE
|
||||
unsigned short saved_smr;
|
||||
unsigned short saved_fcr;
|
||||
unsigned char saved_brr;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Function prototypes */
|
||||
@@ -202,9 +196,9 @@ static struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
|
||||
[SCxSR] = { 0x14, 16 },
|
||||
[SCxRDR] = { 0x60, 8 },
|
||||
[SCFCR] = { 0x18, 16 },
|
||||
[SCFDR] = { 0x1c, 16 },
|
||||
[SCTFDR] = sci_reg_invalid,
|
||||
[SCRFDR] = sci_reg_invalid,
|
||||
[SCFDR] = sci_reg_invalid,
|
||||
[SCTFDR] = { 0x38, 16 },
|
||||
[SCRFDR] = { 0x3c, 16 },
|
||||
[SCSPTR] = sci_reg_invalid,
|
||||
[SCLSR] = sci_reg_invalid,
|
||||
},
|
||||
@@ -491,7 +485,7 @@ static int sci_txfill(struct uart_port *port)
|
||||
|
||||
reg = sci_getreg(port, SCTFDR);
|
||||
if (reg->size)
|
||||
return serial_port_in(port, SCTFDR) & 0xff;
|
||||
return serial_port_in(port, SCTFDR) & ((port->fifosize << 1) - 1);
|
||||
|
||||
reg = sci_getreg(port, SCFDR);
|
||||
if (reg->size)
|
||||
@@ -511,7 +505,7 @@ static int sci_rxfill(struct uart_port *port)
|
||||
|
||||
reg = sci_getreg(port, SCRFDR);
|
||||
if (reg->size)
|
||||
return serial_port_in(port, SCRFDR) & 0xff;
|
||||
return serial_port_in(port, SCRFDR) & ((port->fifosize << 1) - 1);
|
||||
|
||||
reg = sci_getreg(port, SCFDR);
|
||||
if (reg->size)
|
||||
@@ -1132,7 +1126,7 @@ static const char *sci_gpio_str(unsigned int index)
|
||||
return sci_gpio_names[index];
|
||||
}
|
||||
|
||||
static void __devinit sci_init_gpios(struct sci_port *port)
|
||||
static void sci_init_gpios(struct sci_port *port)
|
||||
{
|
||||
struct uart_port *up = &port->port;
|
||||
int i;
|
||||
@@ -1749,22 +1743,21 @@ static inline void sci_free_dma(struct uart_port *port)
|
||||
static int sci_startup(struct uart_port *port)
|
||||
{
|
||||
struct sci_port *s = to_sci_port(port);
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
|
||||
|
||||
pm_runtime_put_noidle(port->dev);
|
||||
|
||||
sci_port_enable(s);
|
||||
|
||||
ret = sci_request_irq(s);
|
||||
if (unlikely(ret < 0))
|
||||
return ret;
|
||||
|
||||
sci_request_dma(port);
|
||||
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
sci_start_tx(port);
|
||||
sci_start_rx(port);
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1772,18 +1765,17 @@ static int sci_startup(struct uart_port *port)
|
||||
static void sci_shutdown(struct uart_port *port)
|
||||
{
|
||||
struct sci_port *s = to_sci_port(port);
|
||||
unsigned long flags;
|
||||
|
||||
dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
|
||||
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
sci_stop_rx(port);
|
||||
sci_stop_tx(port);
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
|
||||
sci_free_dma(port);
|
||||
sci_free_irq(s);
|
||||
|
||||
sci_port_disable(s);
|
||||
|
||||
pm_runtime_get_noresume(port->dev);
|
||||
}
|
||||
|
||||
static unsigned int sci_scbrr_calc(unsigned int algo_id, unsigned int bps,
|
||||
@@ -1829,7 +1821,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||
{
|
||||
struct sci_port *s = to_sci_port(port);
|
||||
struct plat_sci_reg *reg;
|
||||
unsigned int baud, smr_val, max_baud;
|
||||
unsigned int baud, smr_val, max_baud, cks;
|
||||
int t = -1;
|
||||
|
||||
/*
|
||||
@@ -1863,21 +1855,18 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||
|
||||
uart_update_timeout(port, termios->c_cflag, baud);
|
||||
|
||||
serial_port_out(port, SCSMR, smr_val);
|
||||
for (cks = 0; t >= 256 && cks <= 3; cks++)
|
||||
t >>= 2;
|
||||
|
||||
dev_dbg(port->dev, "%s: SMR %x, t %x, SCSCR %x\n", __func__, smr_val, t,
|
||||
s->cfg->scscr);
|
||||
|
||||
if (t > 0) {
|
||||
if (t >= 256) {
|
||||
serial_port_out(port, SCSMR, (serial_port_in(port, SCSMR) & ~3) | 1);
|
||||
t >>= 2;
|
||||
} else
|
||||
serial_port_out(port, SCSMR, serial_port_in(port, SCSMR) & ~3);
|
||||
dev_dbg(port->dev, "%s: SMR %x, cks %x, t %x, SCSCR %x\n",
|
||||
__func__, smr_val, cks, t, s->cfg->scscr);
|
||||
|
||||
if (t >= 0) {
|
||||
serial_port_out(port, SCSMR, (smr_val & ~3) | cks);
|
||||
serial_port_out(port, SCBRR, t);
|
||||
udelay((1000000+(baud-1)) / baud); /* Wait one bit interval */
|
||||
}
|
||||
} else
|
||||
serial_port_out(port, SCSMR, smr_val);
|
||||
|
||||
sci_init_pins(port, termios->c_cflag);
|
||||
|
||||
@@ -1932,6 +1921,21 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||
sci_port_disable(s);
|
||||
}
|
||||
|
||||
static void sci_pm(struct uart_port *port, unsigned int state,
|
||||
unsigned int oldstate)
|
||||
{
|
||||
struct sci_port *sci_port = to_sci_port(port);
|
||||
|
||||
switch (state) {
|
||||
case 3:
|
||||
sci_port_disable(sci_port);
|
||||
break;
|
||||
default:
|
||||
sci_port_enable(sci_port);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const char *sci_type(struct uart_port *port)
|
||||
{
|
||||
switch (port->type) {
|
||||
@@ -2053,6 +2057,7 @@ static struct uart_ops sci_uart_ops = {
|
||||
.startup = sci_startup,
|
||||
.shutdown = sci_shutdown,
|
||||
.set_termios = sci_set_termios,
|
||||
.pm = sci_pm,
|
||||
.type = sci_type,
|
||||
.release_port = sci_release_port,
|
||||
.request_port = sci_request_port,
|
||||
@@ -2064,7 +2069,7 @@ static struct uart_ops sci_uart_ops = {
|
||||
#endif
|
||||
};
|
||||
|
||||
static int __devinit sci_init_single(struct platform_device *dev,
|
||||
static int sci_init_single(struct platform_device *dev,
|
||||
struct sci_port *sci_port,
|
||||
unsigned int index,
|
||||
struct plat_sci_port *p)
|
||||
@@ -2121,8 +2126,6 @@ static int __devinit sci_init_single(struct platform_device *dev,
|
||||
|
||||
sci_init_gpios(sci_port);
|
||||
|
||||
pm_runtime_irq_safe(&dev->dev);
|
||||
pm_runtime_get_noresume(&dev->dev);
|
||||
pm_runtime_enable(&dev->dev);
|
||||
}
|
||||
|
||||
@@ -2206,9 +2209,21 @@ static void serial_console_write(struct console *co, const char *s,
|
||||
{
|
||||
struct sci_port *sci_port = &sci_ports[co->index];
|
||||
struct uart_port *port = &sci_port->port;
|
||||
unsigned short bits;
|
||||
unsigned short bits, ctrl;
|
||||
unsigned long flags;
|
||||
int locked = 1;
|
||||
|
||||
sci_port_enable(sci_port);
|
||||
local_irq_save(flags);
|
||||
if (port->sysrq)
|
||||
locked = 0;
|
||||
else if (oops_in_progress)
|
||||
locked = spin_trylock(&port->lock);
|
||||
else
|
||||
spin_lock(&port->lock);
|
||||
|
||||
/* first save the SCSCR then disable the interrupts */
|
||||
ctrl = serial_port_in(port, SCSCR);
|
||||
serial_port_out(port, SCSCR, sci_port->cfg->scscr);
|
||||
|
||||
uart_console_write(port, s, count, serial_console_putchar);
|
||||
|
||||
@@ -2217,10 +2232,15 @@ static void serial_console_write(struct console *co, const char *s,
|
||||
while ((serial_port_in(port, SCxSR) & bits) != bits)
|
||||
cpu_relax();
|
||||
|
||||
sci_port_disable(sci_port);
|
||||
/* restore the SCSCR */
|
||||
serial_port_out(port, SCSCR, ctrl);
|
||||
|
||||
if (locked)
|
||||
spin_unlock(&port->lock);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static int __devinit serial_console_setup(struct console *co, char *options)
|
||||
static int serial_console_setup(struct console *co, char *options)
|
||||
{
|
||||
struct sci_port *sci_port;
|
||||
struct uart_port *port;
|
||||
@@ -2249,13 +2269,9 @@ static int __devinit serial_console_setup(struct console *co, char *options)
|
||||
if (unlikely(ret != 0))
|
||||
return ret;
|
||||
|
||||
sci_port_enable(sci_port);
|
||||
|
||||
if (options)
|
||||
uart_parse_options(options, &baud, &parity, &bits, &flow);
|
||||
|
||||
sci_port_disable(sci_port);
|
||||
|
||||
return uart_set_options(port, co, baud, parity, bits, flow);
|
||||
}
|
||||
|
||||
@@ -2278,7 +2294,7 @@ static struct console early_serial_console = {
|
||||
|
||||
static char early_serial_buf[32];
|
||||
|
||||
static int __devinit sci_probe_earlyprintk(struct platform_device *pdev)
|
||||
static int sci_probe_earlyprintk(struct platform_device *pdev)
|
||||
{
|
||||
struct plat_sci_port *cfg = pdev->dev.platform_data;
|
||||
|
||||
@@ -2298,57 +2314,15 @@ static int __devinit sci_probe_earlyprintk(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define uart_console(port) ((port)->cons->index == (port)->line)
|
||||
|
||||
static int sci_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct sci_port *sci_port = dev_get_drvdata(dev);
|
||||
struct uart_port *port = &sci_port->port;
|
||||
|
||||
if (uart_console(port)) {
|
||||
struct plat_sci_reg *reg;
|
||||
|
||||
sci_port->saved_smr = serial_port_in(port, SCSMR);
|
||||
sci_port->saved_brr = serial_port_in(port, SCBRR);
|
||||
|
||||
reg = sci_getreg(port, SCFCR);
|
||||
if (reg->size)
|
||||
sci_port->saved_fcr = serial_port_in(port, SCFCR);
|
||||
else
|
||||
sci_port->saved_fcr = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sci_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct sci_port *sci_port = dev_get_drvdata(dev);
|
||||
struct uart_port *port = &sci_port->port;
|
||||
|
||||
if (uart_console(port)) {
|
||||
sci_reset(port);
|
||||
serial_port_out(port, SCSMR, sci_port->saved_smr);
|
||||
serial_port_out(port, SCBRR, sci_port->saved_brr);
|
||||
|
||||
if (sci_port->saved_fcr)
|
||||
serial_port_out(port, SCFCR, sci_port->saved_fcr);
|
||||
|
||||
serial_port_out(port, SCSCR, sci_port->cfg->scscr);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define SCI_CONSOLE (&serial_console)
|
||||
|
||||
#else
|
||||
static inline int __devinit sci_probe_earlyprintk(struct platform_device *pdev)
|
||||
static inline int sci_probe_earlyprintk(struct platform_device *pdev)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#define SCI_CONSOLE NULL
|
||||
#define sci_runtime_suspend NULL
|
||||
#define sci_runtime_resume NULL
|
||||
|
||||
#endif /* CONFIG_SERIAL_SH_SCI_CONSOLE */
|
||||
|
||||
@@ -2379,7 +2353,7 @@ static int sci_remove(struct platform_device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit sci_probe_single(struct platform_device *dev,
|
||||
static int sci_probe_single(struct platform_device *dev,
|
||||
unsigned int index,
|
||||
struct plat_sci_port *p,
|
||||
struct sci_port *sciport)
|
||||
@@ -2409,7 +2383,7 @@ static int __devinit sci_probe_single(struct platform_device *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit sci_probe(struct platform_device *dev)
|
||||
static int sci_probe(struct platform_device *dev)
|
||||
{
|
||||
struct plat_sci_port *p = dev->dev.platform_data;
|
||||
struct sci_port *sp = &sci_ports[dev->id];
|
||||
@@ -2466,8 +2440,6 @@ static int sci_resume(struct device *dev)
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops sci_dev_pm_ops = {
|
||||
.runtime_suspend = sci_runtime_suspend,
|
||||
.runtime_resume = sci_runtime_resume,
|
||||
.suspend = sci_suspend,
|
||||
.resume = sci_resume,
|
||||
};
|
||||
|
@@ -727,7 +727,7 @@ static int sirfsoc_uart_resume(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct of_device_id sirfsoc_uart_ids[] __devinitdata = {
|
||||
static struct of_device_id sirfsoc_uart_ids[] = {
|
||||
{ .compatible = "sirf,prima2-uart", },
|
||||
{}
|
||||
};
|
||||
@@ -735,7 +735,7 @@ MODULE_DEVICE_TABLE(of, sirfsoc_serial_of_match);
|
||||
|
||||
static struct platform_driver sirfsoc_uart_driver = {
|
||||
.probe = sirfsoc_uart_probe,
|
||||
.remove = __devexit_p(sirfsoc_uart_remove),
|
||||
.remove = sirfsoc_uart_remove,
|
||||
.suspend = sirfsoc_uart_suspend,
|
||||
.resume = sirfsoc_uart_resume,
|
||||
.driver = {
|
||||
|
@@ -519,7 +519,7 @@ static struct console sunhv_console = {
|
||||
.data = &sunhv_reg,
|
||||
};
|
||||
|
||||
static int __devinit hv_probe(struct platform_device *op)
|
||||
static int hv_probe(struct platform_device *op)
|
||||
{
|
||||
struct uart_port *port;
|
||||
unsigned long minor;
|
||||
@@ -598,7 +598,7 @@ out_free_port:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __devexit hv_remove(struct platform_device *dev)
|
||||
static int hv_remove(struct platform_device *dev)
|
||||
{
|
||||
struct uart_port *port = dev_get_drvdata(&dev->dev);
|
||||
|
||||
@@ -636,7 +636,7 @@ static struct platform_driver hv_driver = {
|
||||
.of_match_table = hv_match,
|
||||
},
|
||||
.probe = hv_probe,
|
||||
.remove = __devexit_p(hv_remove),
|
||||
.remove = hv_remove,
|
||||
};
|
||||
|
||||
static int __init sunhv_init(void)
|
||||
|
@@ -954,7 +954,7 @@ static inline struct console *SUNSAB_CONSOLE(void)
|
||||
#define sunsab_console_init() do { } while (0)
|
||||
#endif
|
||||
|
||||
static int __devinit sunsab_init_one(struct uart_sunsab_port *up,
|
||||
static int sunsab_init_one(struct uart_sunsab_port *up,
|
||||
struct platform_device *op,
|
||||
unsigned long offset,
|
||||
int line)
|
||||
@@ -1007,7 +1007,7 @@ static int __devinit sunsab_init_one(struct uart_sunsab_port *up,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit sab_probe(struct platform_device *op)
|
||||
static int sab_probe(struct platform_device *op)
|
||||
{
|
||||
static int inst;
|
||||
struct uart_sunsab_port *up;
|
||||
@@ -1063,7 +1063,7 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __devexit sab_remove(struct platform_device *op)
|
||||
static int sab_remove(struct platform_device *op)
|
||||
{
|
||||
struct uart_sunsab_port *up = dev_get_drvdata(&op->dev);
|
||||
|
||||
@@ -1100,7 +1100,7 @@ static struct platform_driver sab_driver = {
|
||||
.of_match_table = sab_match,
|
||||
},
|
||||
.probe = sab_probe,
|
||||
.remove = __devexit_p(sab_remove),
|
||||
.remove = sab_remove,
|
||||
};
|
||||
|
||||
static int __init sunsab_init(void)
|
||||
|
@@ -1185,7 +1185,7 @@ static struct uart_driver sunsu_reg = {
|
||||
.major = TTY_MAJOR,
|
||||
};
|
||||
|
||||
static int __devinit sunsu_kbd_ms_init(struct uart_sunsu_port *up)
|
||||
static int sunsu_kbd_ms_init(struct uart_sunsu_port *up)
|
||||
{
|
||||
int quot, baud;
|
||||
#ifdef CONFIG_SERIO
|
||||
@@ -1391,7 +1391,7 @@ static inline struct console *SUNSU_CONSOLE(void)
|
||||
#define sunsu_serial_console_init() do { } while (0)
|
||||
#endif
|
||||
|
||||
static enum su_type __devinit su_get_type(struct device_node *dp)
|
||||
static enum su_type su_get_type(struct device_node *dp)
|
||||
{
|
||||
struct device_node *ap = of_find_node_by_path("/aliases");
|
||||
|
||||
@@ -1412,7 +1412,7 @@ static enum su_type __devinit su_get_type(struct device_node *dp)
|
||||
return SU_PORT_PORT;
|
||||
}
|
||||
|
||||
static int __devinit su_probe(struct platform_device *op)
|
||||
static int su_probe(struct platform_device *op)
|
||||
{
|
||||
static int inst;
|
||||
struct device_node *dp = op->dev.of_node;
|
||||
@@ -1503,7 +1503,7 @@ out_unmap:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __devexit su_remove(struct platform_device *op)
|
||||
static int su_remove(struct platform_device *op)
|
||||
{
|
||||
struct uart_sunsu_port *up = dev_get_drvdata(&op->dev);
|
||||
bool kbdms = false;
|
||||
@@ -1556,7 +1556,7 @@ static struct platform_driver su_driver = {
|
||||
.of_match_table = su_match,
|
||||
},
|
||||
.probe = su_probe,
|
||||
.remove = __devexit_p(su_remove),
|
||||
.remove = su_remove,
|
||||
};
|
||||
|
||||
static int __init sunsu_init(void)
|
||||
|
@@ -1282,7 +1282,7 @@ static inline struct console *SUNZILOG_CONSOLE(void)
|
||||
#define SUNZILOG_CONSOLE() (NULL)
|
||||
#endif
|
||||
|
||||
static void __devinit sunzilog_init_kbdms(struct uart_sunzilog_port *up)
|
||||
static void sunzilog_init_kbdms(struct uart_sunzilog_port *up)
|
||||
{
|
||||
int baud, brg;
|
||||
|
||||
@@ -1302,7 +1302,7 @@ static void __devinit sunzilog_init_kbdms(struct uart_sunzilog_port *up)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SERIO
|
||||
static void __devinit sunzilog_register_serio(struct uart_sunzilog_port *up)
|
||||
static void sunzilog_register_serio(struct uart_sunzilog_port *up)
|
||||
{
|
||||
struct serio *serio = &up->serio;
|
||||
|
||||
@@ -1331,7 +1331,7 @@ static void __devinit sunzilog_register_serio(struct uart_sunzilog_port *up)
|
||||
}
|
||||
#endif
|
||||
|
||||
static void __devinit sunzilog_init_hw(struct uart_sunzilog_port *up)
|
||||
static void sunzilog_init_hw(struct uart_sunzilog_port *up)
|
||||
{
|
||||
struct zilog_channel __iomem *channel;
|
||||
unsigned long flags;
|
||||
@@ -1400,7 +1400,7 @@ static void __devinit sunzilog_init_hw(struct uart_sunzilog_port *up)
|
||||
|
||||
static int zilog_irq;
|
||||
|
||||
static int __devinit zs_probe(struct platform_device *op)
|
||||
static int zs_probe(struct platform_device *op)
|
||||
{
|
||||
static int kbm_inst, uart_inst;
|
||||
int inst;
|
||||
@@ -1507,7 +1507,7 @@ static int __devinit zs_probe(struct platform_device *op)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __devexit zs_remove_one(struct uart_sunzilog_port *up)
|
||||
static void zs_remove_one(struct uart_sunzilog_port *up)
|
||||
{
|
||||
if (ZS_IS_KEYB(up) || ZS_IS_MOUSE(up)) {
|
||||
#ifdef CONFIG_SERIO
|
||||
@@ -1517,7 +1517,7 @@ static void __devexit zs_remove_one(struct uart_sunzilog_port *up)
|
||||
uart_remove_one_port(&sunzilog_reg, &up->port);
|
||||
}
|
||||
|
||||
static int __devexit zs_remove(struct platform_device *op)
|
||||
static int zs_remove(struct platform_device *op)
|
||||
{
|
||||
struct uart_sunzilog_port *up = dev_get_drvdata(&op->dev);
|
||||
struct zilog_layout __iomem *regs;
|
||||
@@ -1548,7 +1548,7 @@ static struct platform_driver zs_driver = {
|
||||
.of_match_table = zs_match,
|
||||
},
|
||||
.probe = zs_probe,
|
||||
.remove = __devexit_p(zs_remove),
|
||||
.remove = zs_remove,
|
||||
};
|
||||
|
||||
static int __init sunzilog_init(void)
|
||||
|
@@ -426,7 +426,7 @@ static struct uart_driver timbuart_driver = {
|
||||
.nr = 1
|
||||
};
|
||||
|
||||
static int __devinit timbuart_probe(struct platform_device *dev)
|
||||
static int timbuart_probe(struct platform_device *dev)
|
||||
{
|
||||
int err, irq;
|
||||
struct timbuart_port *uart;
|
||||
@@ -492,7 +492,7 @@ err_mem:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __devexit timbuart_remove(struct platform_device *dev)
|
||||
static int timbuart_remove(struct platform_device *dev)
|
||||
{
|
||||
struct timbuart_port *uart = platform_get_drvdata(dev);
|
||||
|
||||
@@ -510,7 +510,7 @@ static struct platform_driver timbuart_platform_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = timbuart_probe,
|
||||
.remove = __devexit_p(timbuart_remove),
|
||||
.remove = timbuart_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(timbuart_platform_driver);
|
||||
|
@@ -408,7 +408,7 @@ static void ulite_console_write(struct console *co, const char *s,
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
}
|
||||
|
||||
static int __devinit ulite_console_setup(struct console *co, char *options)
|
||||
static int ulite_console_setup(struct console *co, char *options)
|
||||
{
|
||||
struct uart_port *port;
|
||||
int baud = 9600;
|
||||
@@ -486,7 +486,7 @@ static struct uart_driver ulite_uart_driver = {
|
||||
*
|
||||
* Returns: 0 on success, <0 otherwise
|
||||
*/
|
||||
static int __devinit ulite_assign(struct device *dev, int id, u32 base, int irq)
|
||||
static int ulite_assign(struct device *dev, int id, u32 base, int irq)
|
||||
{
|
||||
struct uart_port *port;
|
||||
int rc;
|
||||
@@ -542,7 +542,7 @@ static int __devinit ulite_assign(struct device *dev, int id, u32 base, int irq)
|
||||
*
|
||||
* @dev: pointer to device structure
|
||||
*/
|
||||
static int __devexit ulite_release(struct device *dev)
|
||||
static int ulite_release(struct device *dev)
|
||||
{
|
||||
struct uart_port *port = dev_get_drvdata(dev);
|
||||
int rc = 0;
|
||||
@@ -562,7 +562,7 @@ static int __devexit ulite_release(struct device *dev)
|
||||
|
||||
#if defined(CONFIG_OF)
|
||||
/* Match table for of_platform binding */
|
||||
static struct of_device_id ulite_of_match[] __devinitdata = {
|
||||
static struct of_device_id ulite_of_match[] = {
|
||||
{ .compatible = "xlnx,opb-uartlite-1.00.b", },
|
||||
{ .compatible = "xlnx,xps-uartlite-1.00.a", },
|
||||
{}
|
||||
@@ -570,7 +570,7 @@ static struct of_device_id ulite_of_match[] __devinitdata = {
|
||||
MODULE_DEVICE_TABLE(of, ulite_of_match);
|
||||
#endif /* CONFIG_OF */
|
||||
|
||||
static int __devinit ulite_probe(struct platform_device *pdev)
|
||||
static int ulite_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *res, *res2;
|
||||
int id = pdev->id;
|
||||
@@ -593,7 +593,7 @@ static int __devinit ulite_probe(struct platform_device *pdev)
|
||||
return ulite_assign(&pdev->dev, id, res->start, res2->start);
|
||||
}
|
||||
|
||||
static int __devexit ulite_remove(struct platform_device *pdev)
|
||||
static int ulite_remove(struct platform_device *pdev)
|
||||
{
|
||||
return ulite_release(&pdev->dev);
|
||||
}
|
||||
@@ -603,7 +603,7 @@ MODULE_ALIAS("platform:uartlite");
|
||||
|
||||
static struct platform_driver ulite_platform_driver = {
|
||||
.probe = ulite_probe,
|
||||
.remove = __devexit_p(ulite_remove),
|
||||
.remove = ulite_remove,
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "uartlite",
|
||||
|
@@ -823,7 +823,7 @@ static struct console siu_console = {
|
||||
.data = &siu_uart_driver,
|
||||
};
|
||||
|
||||
static int __devinit siu_console_init(void)
|
||||
static int siu_console_init(void)
|
||||
{
|
||||
struct uart_port *port;
|
||||
int i;
|
||||
@@ -867,7 +867,7 @@ static struct uart_driver siu_uart_driver = {
|
||||
.cons = SERIAL_VR41XX_CONSOLE,
|
||||
};
|
||||
|
||||
static int __devinit siu_probe(struct platform_device *dev)
|
||||
static int siu_probe(struct platform_device *dev)
|
||||
{
|
||||
struct uart_port *port;
|
||||
int num, i, retval;
|
||||
@@ -901,7 +901,7 @@ static int __devinit siu_probe(struct platform_device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit siu_remove(struct platform_device *dev)
|
||||
static int siu_remove(struct platform_device *dev)
|
||||
{
|
||||
struct uart_port *port;
|
||||
int i;
|
||||
@@ -952,7 +952,7 @@ static int siu_resume(struct platform_device *dev)
|
||||
|
||||
static struct platform_driver siu_device_driver = {
|
||||
.probe = siu_probe,
|
||||
.remove = __devexit_p(siu_remove),
|
||||
.remove = siu_remove,
|
||||
.suspend = siu_suspend,
|
||||
.resume = siu_resume,
|
||||
.driver = {
|
||||
|
@@ -554,7 +554,7 @@ static struct uart_driver vt8500_uart_driver = {
|
||||
.cons = VT8500_CONSOLE,
|
||||
};
|
||||
|
||||
static int __devinit vt8500_serial_probe(struct platform_device *pdev)
|
||||
static int vt8500_serial_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct vt8500_port *vt8500_port;
|
||||
struct resource *mmres, *irqres;
|
||||
@@ -567,10 +567,6 @@ static int __devinit vt8500_serial_probe(struct platform_device *pdev)
|
||||
if (!mmres || !irqres)
|
||||
return -ENODEV;
|
||||
|
||||
vt8500_port = kzalloc(sizeof(struct vt8500_port), GFP_KERNEL);
|
||||
if (!vt8500_port)
|
||||
return -ENOMEM;
|
||||
|
||||
if (np)
|
||||
port = of_alias_get_id(np, "serial");
|
||||
if (port > VT8500_MAX_PORTS)
|
||||
@@ -593,6 +589,10 @@ static int __devinit vt8500_serial_probe(struct platform_device *pdev)
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
vt8500_port = kzalloc(sizeof(struct vt8500_port), GFP_KERNEL);
|
||||
if (!vt8500_port)
|
||||
return -ENOMEM;
|
||||
|
||||
vt8500_port->uart.type = PORT_VT8500;
|
||||
vt8500_port->uart.iotype = UPIO_MEM;
|
||||
vt8500_port->uart.mapbase = mmres->start;
|
||||
@@ -634,7 +634,7 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit vt8500_serial_remove(struct platform_device *pdev)
|
||||
static int vt8500_serial_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct vt8500_port *vt8500_port = platform_get_drvdata(pdev);
|
||||
|
||||
@@ -652,7 +652,7 @@ static const struct of_device_id wmt_dt_ids[] = {
|
||||
|
||||
static struct platform_driver vt8500_platform_driver = {
|
||||
.probe = vt8500_serial_probe,
|
||||
.remove = __devexit_p(vt8500_serial_remove),
|
||||
.remove = vt8500_serial_remove,
|
||||
.driver = {
|
||||
.name = "vt8500_serial",
|
||||
.owner = THIS_MODULE,
|
||||
|
@@ -939,22 +939,18 @@ static struct uart_driver xuartps_uart_driver = {
|
||||
*
|
||||
* Returns 0 on success, negative error otherwise
|
||||
**/
|
||||
static int __devinit xuartps_probe(struct platform_device *pdev)
|
||||
static int xuartps_probe(struct platform_device *pdev)
|
||||
{
|
||||
int rc;
|
||||
struct uart_port *port;
|
||||
struct resource *res, *res2;
|
||||
int clk = 0;
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
const unsigned int *prop;
|
||||
|
||||
prop = of_get_property(pdev->dev.of_node, "clock", NULL);
|
||||
if (prop)
|
||||
clk = be32_to_cpup(prop);
|
||||
#else
|
||||
clk = *((unsigned int *)(pdev->dev.platform_data));
|
||||
#endif
|
||||
if (!clk) {
|
||||
dev_err(&pdev->dev, "no clock specified\n");
|
||||
return -ENODEV;
|
||||
@@ -1001,7 +997,7 @@ static int __devinit xuartps_probe(struct platform_device *pdev)
|
||||
*
|
||||
* Returns 0 on success, negative error otherwise
|
||||
**/
|
||||
static int __devexit xuartps_remove(struct platform_device *pdev)
|
||||
static int xuartps_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct uart_port *port = dev_get_drvdata(&pdev->dev);
|
||||
int rc = 0;
|
||||
@@ -1044,16 +1040,11 @@ static int xuartps_resume(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
/* Match table for of_platform binding */
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static struct of_device_id xuartps_of_match[] __devinitdata = {
|
||||
static struct of_device_id xuartps_of_match[] = {
|
||||
{ .compatible = "xlnx,xuartps", },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, xuartps_of_match);
|
||||
#else
|
||||
#define xuartps_of_match NULL
|
||||
#endif
|
||||
|
||||
static struct platform_driver xuartps_platform_driver = {
|
||||
.probe = xuartps_probe, /* Probe method */
|
||||
|
@@ -898,7 +898,7 @@ static struct pci_driver synclink_pci_driver = {
|
||||
.name = "synclink",
|
||||
.id_table = synclink_pci_tbl,
|
||||
.probe = synclink_init_one,
|
||||
.remove = __devexit_p(synclink_remove_one),
|
||||
.remove = synclink_remove_one,
|
||||
};
|
||||
|
||||
static struct tty_driver *serial_driver;
|
||||
@@ -4425,6 +4425,7 @@ static void synclink_cleanup(void)
|
||||
mgsl_release_resources(info);
|
||||
tmp = info;
|
||||
info = info->next_device;
|
||||
tty_port_destroy(&tmp->port);
|
||||
kfree(tmp);
|
||||
}
|
||||
|
||||
@@ -8064,7 +8065,7 @@ static void hdlcdev_exit(struct mgsl_struct *info)
|
||||
#endif /* CONFIG_HDLC */
|
||||
|
||||
|
||||
static int __devinit synclink_init_one (struct pci_dev *dev,
|
||||
static int synclink_init_one (struct pci_dev *dev,
|
||||
const struct pci_device_id *ent)
|
||||
{
|
||||
struct mgsl_struct *info;
|
||||
@@ -8116,7 +8117,7 @@ static int __devinit synclink_init_one (struct pci_dev *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __devexit synclink_remove_one (struct pci_dev *dev)
|
||||
static void synclink_remove_one (struct pci_dev *dev)
|
||||
{
|
||||
}
|
||||
|
||||
|
@@ -110,7 +110,7 @@ static struct pci_driver pci_driver = {
|
||||
.name = "synclink_gt",
|
||||
.id_table = pci_table,
|
||||
.probe = init_one,
|
||||
.remove = __devexit_p(remove_one),
|
||||
.remove = remove_one,
|
||||
};
|
||||
|
||||
static bool pci_registered;
|
||||
@@ -3645,8 +3645,10 @@ static void device_init(int adapter_num, struct pci_dev *pdev)
|
||||
for (i=0; i < port_count; ++i) {
|
||||
port_array[i] = alloc_dev(adapter_num, i, pdev);
|
||||
if (port_array[i] == NULL) {
|
||||
for (--i; i >= 0; --i)
|
||||
for (--i; i >= 0; --i) {
|
||||
tty_port_destroy(&port_array[i]->port);
|
||||
kfree(port_array[i]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -3696,7 +3698,7 @@ static void device_init(int adapter_num, struct pci_dev *pdev)
|
||||
}
|
||||
}
|
||||
|
||||
static int __devinit init_one(struct pci_dev *dev,
|
||||
static int init_one(struct pci_dev *dev,
|
||||
const struct pci_device_id *ent)
|
||||
{
|
||||
if (pci_enable_device(dev)) {
|
||||
@@ -3708,7 +3710,7 @@ static int __devinit init_one(struct pci_dev *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __devexit remove_one(struct pci_dev *dev)
|
||||
static void remove_one(struct pci_dev *dev)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -3773,6 +3775,7 @@ static void slgt_cleanup(void)
|
||||
release_resources(info);
|
||||
tmp = info;
|
||||
info = info->next_device;
|
||||
tty_port_destroy(&tmp->port);
|
||||
kfree(tmp);
|
||||
}
|
||||
|
||||
|
@@ -492,7 +492,7 @@ static struct pci_driver synclinkmp_pci_driver = {
|
||||
.name = "synclinkmp",
|
||||
.id_table = synclinkmp_pci_tbl,
|
||||
.probe = synclinkmp_init_one,
|
||||
.remove = __devexit_p(synclinkmp_remove_one),
|
||||
.remove = synclinkmp_remove_one,
|
||||
};
|
||||
|
||||
|
||||
@@ -3843,8 +3843,10 @@ static void device_init(int adapter_num, struct pci_dev *pdev)
|
||||
for ( port = 0; port < SCA_MAX_PORTS; ++port ) {
|
||||
port_array[port] = alloc_dev(adapter_num,port,pdev);
|
||||
if( port_array[port] == NULL ) {
|
||||
for ( --port; port >= 0; --port )
|
||||
for (--port; port >= 0; --port) {
|
||||
tty_port_destroy(&port_array[port]->port);
|
||||
kfree(port_array[port]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -3953,6 +3955,7 @@ static void synclinkmp_cleanup(void)
|
||||
}
|
||||
tmp = info;
|
||||
info = info->next_device;
|
||||
tty_port_destroy(&tmp->port);
|
||||
kfree(tmp);
|
||||
}
|
||||
|
||||
@@ -5592,7 +5595,7 @@ static void write_control_reg(SLMP_INFO * info)
|
||||
}
|
||||
|
||||
|
||||
static int __devinit synclinkmp_init_one (struct pci_dev *dev,
|
||||
static int synclinkmp_init_one (struct pci_dev *dev,
|
||||
const struct pci_device_id *ent)
|
||||
{
|
||||
if (pci_enable_device(dev)) {
|
||||
@@ -5603,6 +5606,6 @@ static int __devinit synclinkmp_init_one (struct pci_dev *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __devexit synclinkmp_remove_one (struct pci_dev *dev)
|
||||
static void synclinkmp_remove_one (struct pci_dev *dev)
|
||||
{
|
||||
}
|
||||
|
@@ -346,7 +346,8 @@ static struct sysrq_key_op sysrq_term_op = {
|
||||
|
||||
static void moom_callback(struct work_struct *ignored)
|
||||
{
|
||||
out_of_memory(node_zonelist(0, GFP_KERNEL), GFP_KERNEL, 0, NULL, true);
|
||||
out_of_memory(node_zonelist(first_online_node, GFP_KERNEL), GFP_KERNEL,
|
||||
0, NULL, true);
|
||||
}
|
||||
|
||||
static DECLARE_WORK(moom_work, moom_callback);
|
||||
|
@@ -23,7 +23,7 @@ struct tty_audit_buf {
|
||||
};
|
||||
|
||||
static struct tty_audit_buf *tty_audit_buf_alloc(int major, int minor,
|
||||
int icanon)
|
||||
unsigned icanon)
|
||||
{
|
||||
struct tty_audit_buf *buf;
|
||||
|
||||
@@ -239,7 +239,8 @@ int tty_audit_push_task(struct task_struct *tsk, kuid_t loginuid, u32 sessionid)
|
||||
* if TTY auditing is disabled or out of memory. Otherwise, return a new
|
||||
* reference to the buffer.
|
||||
*/
|
||||
static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty)
|
||||
static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty,
|
||||
unsigned icanon)
|
||||
{
|
||||
struct tty_audit_buf *buf, *buf2;
|
||||
|
||||
@@ -257,7 +258,7 @@ static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty)
|
||||
|
||||
buf2 = tty_audit_buf_alloc(tty->driver->major,
|
||||
tty->driver->minor_start + tty->index,
|
||||
tty->icanon);
|
||||
icanon);
|
||||
if (buf2 == NULL) {
|
||||
audit_log_lost("out of memory in TTY auditing");
|
||||
return NULL;
|
||||
@@ -287,7 +288,7 @@ static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty)
|
||||
* Audit @data of @size from @tty, if necessary.
|
||||
*/
|
||||
void tty_audit_add_data(struct tty_struct *tty, unsigned char *data,
|
||||
size_t size)
|
||||
size_t size, unsigned icanon)
|
||||
{
|
||||
struct tty_audit_buf *buf;
|
||||
int major, minor;
|
||||
@@ -299,7 +300,7 @@ void tty_audit_add_data(struct tty_struct *tty, unsigned char *data,
|
||||
&& tty->driver->subtype == PTY_TYPE_MASTER)
|
||||
return;
|
||||
|
||||
buf = tty_audit_buf_get(tty);
|
||||
buf = tty_audit_buf_get(tty, icanon);
|
||||
if (!buf)
|
||||
return;
|
||||
|
||||
@@ -307,11 +308,11 @@ void tty_audit_add_data(struct tty_struct *tty, unsigned char *data,
|
||||
major = tty->driver->major;
|
||||
minor = tty->driver->minor_start + tty->index;
|
||||
if (buf->major != major || buf->minor != minor
|
||||
|| buf->icanon != tty->icanon) {
|
||||
|| buf->icanon != icanon) {
|
||||
tty_audit_buf_push_current(buf);
|
||||
buf->major = major;
|
||||
buf->minor = minor;
|
||||
buf->icanon = tty->icanon;
|
||||
buf->icanon = icanon;
|
||||
}
|
||||
do {
|
||||
size_t run;
|
||||
|
@@ -27,19 +27,21 @@
|
||||
* Locking: none
|
||||
*/
|
||||
|
||||
void tty_buffer_free_all(struct tty_struct *tty)
|
||||
void tty_buffer_free_all(struct tty_port *port)
|
||||
{
|
||||
struct tty_bufhead *buf = &port->buf;
|
||||
struct tty_buffer *thead;
|
||||
while ((thead = tty->buf.head) != NULL) {
|
||||
tty->buf.head = thead->next;
|
||||
|
||||
while ((thead = buf->head) != NULL) {
|
||||
buf->head = thead->next;
|
||||
kfree(thead);
|
||||
}
|
||||
while ((thead = tty->buf.free) != NULL) {
|
||||
tty->buf.free = thead->next;
|
||||
while ((thead = buf->free) != NULL) {
|
||||
buf->free = thead->next;
|
||||
kfree(thead);
|
||||
}
|
||||
tty->buf.tail = NULL;
|
||||
tty->buf.memory_used = 0;
|
||||
buf->tail = NULL;
|
||||
buf->memory_used = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -54,11 +56,11 @@ void tty_buffer_free_all(struct tty_struct *tty)
|
||||
* Locking: Caller must hold tty->buf.lock
|
||||
*/
|
||||
|
||||
static struct tty_buffer *tty_buffer_alloc(struct tty_struct *tty, size_t size)
|
||||
static struct tty_buffer *tty_buffer_alloc(struct tty_port *port, size_t size)
|
||||
{
|
||||
struct tty_buffer *p;
|
||||
|
||||
if (tty->buf.memory_used + size > 65536)
|
||||
if (port->buf.memory_used + size > 65536)
|
||||
return NULL;
|
||||
p = kmalloc(sizeof(struct tty_buffer) + 2 * size, GFP_ATOMIC);
|
||||
if (p == NULL)
|
||||
@@ -70,7 +72,7 @@ static struct tty_buffer *tty_buffer_alloc(struct tty_struct *tty, size_t size)
|
||||
p->read = 0;
|
||||
p->char_buf_ptr = (char *)(p->data);
|
||||
p->flag_buf_ptr = (unsigned char *)p->char_buf_ptr + size;
|
||||
tty->buf.memory_used += size;
|
||||
port->buf.memory_used += size;
|
||||
return p;
|
||||
}
|
||||
|
||||
@@ -85,17 +87,19 @@ static struct tty_buffer *tty_buffer_alloc(struct tty_struct *tty, size_t size)
|
||||
* Locking: Caller must hold tty->buf.lock
|
||||
*/
|
||||
|
||||
static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b)
|
||||
static void tty_buffer_free(struct tty_port *port, struct tty_buffer *b)
|
||||
{
|
||||
struct tty_bufhead *buf = &port->buf;
|
||||
|
||||
/* Dumb strategy for now - should keep some stats */
|
||||
tty->buf.memory_used -= b->size;
|
||||
WARN_ON(tty->buf.memory_used < 0);
|
||||
buf->memory_used -= b->size;
|
||||
WARN_ON(buf->memory_used < 0);
|
||||
|
||||
if (b->size >= 512)
|
||||
kfree(b);
|
||||
else {
|
||||
b->next = tty->buf.free;
|
||||
tty->buf.free = b;
|
||||
b->next = buf->free;
|
||||
buf->free = b;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,15 +114,16 @@ static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b)
|
||||
* Locking: Caller must hold tty->buf.lock
|
||||
*/
|
||||
|
||||
static void __tty_buffer_flush(struct tty_struct *tty)
|
||||
static void __tty_buffer_flush(struct tty_port *port)
|
||||
{
|
||||
struct tty_bufhead *buf = &port->buf;
|
||||
struct tty_buffer *thead;
|
||||
|
||||
while ((thead = tty->buf.head) != NULL) {
|
||||
tty->buf.head = thead->next;
|
||||
tty_buffer_free(tty, thead);
|
||||
while ((thead = buf->head) != NULL) {
|
||||
buf->head = thead->next;
|
||||
tty_buffer_free(port, thead);
|
||||
}
|
||||
tty->buf.tail = NULL;
|
||||
buf->tail = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -134,21 +139,24 @@ static void __tty_buffer_flush(struct tty_struct *tty)
|
||||
|
||||
void tty_buffer_flush(struct tty_struct *tty)
|
||||
{
|
||||
struct tty_port *port = tty->port;
|
||||
struct tty_bufhead *buf = &port->buf;
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&tty->buf.lock, flags);
|
||||
|
||||
spin_lock_irqsave(&buf->lock, flags);
|
||||
|
||||
/* If the data is being pushed to the tty layer then we can't
|
||||
process it here. Instead set a flag and the flush_to_ldisc
|
||||
path will process the flush request before it exits */
|
||||
if (test_bit(TTY_FLUSHING, &tty->flags)) {
|
||||
set_bit(TTY_FLUSHPENDING, &tty->flags);
|
||||
spin_unlock_irqrestore(&tty->buf.lock, flags);
|
||||
if (test_bit(TTYP_FLUSHING, &port->iflags)) {
|
||||
set_bit(TTYP_FLUSHPENDING, &port->iflags);
|
||||
spin_unlock_irqrestore(&buf->lock, flags);
|
||||
wait_event(tty->read_wait,
|
||||
test_bit(TTY_FLUSHPENDING, &tty->flags) == 0);
|
||||
test_bit(TTYP_FLUSHPENDING, &port->iflags) == 0);
|
||||
return;
|
||||
} else
|
||||
__tty_buffer_flush(tty);
|
||||
spin_unlock_irqrestore(&tty->buf.lock, flags);
|
||||
__tty_buffer_flush(port);
|
||||
spin_unlock_irqrestore(&buf->lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -163,9 +171,9 @@ void tty_buffer_flush(struct tty_struct *tty)
|
||||
* Locking: Caller must hold tty->buf.lock
|
||||
*/
|
||||
|
||||
static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size)
|
||||
static struct tty_buffer *tty_buffer_find(struct tty_port *port, size_t size)
|
||||
{
|
||||
struct tty_buffer **tbh = &tty->buf.free;
|
||||
struct tty_buffer **tbh = &port->buf.free;
|
||||
while ((*tbh) != NULL) {
|
||||
struct tty_buffer *t = *tbh;
|
||||
if (t->size >= size) {
|
||||
@@ -174,14 +182,14 @@ static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size)
|
||||
t->used = 0;
|
||||
t->commit = 0;
|
||||
t->read = 0;
|
||||
tty->buf.memory_used += t->size;
|
||||
port->buf.memory_used += t->size;
|
||||
return t;
|
||||
}
|
||||
tbh = &((*tbh)->next);
|
||||
}
|
||||
/* Round the buffer size out */
|
||||
size = (size + 0xFF) & ~0xFF;
|
||||
return tty_buffer_alloc(tty, size);
|
||||
return tty_buffer_alloc(port, size);
|
||||
/* Should possibly check if this fails for the largest buffer we
|
||||
have queued and recycle that ? */
|
||||
}
|
||||
@@ -192,29 +200,31 @@ static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size)
|
||||
*
|
||||
* Make at least size bytes of linear space available for the tty
|
||||
* buffer. If we fail return the size we managed to find.
|
||||
* Locking: Caller must hold tty->buf.lock
|
||||
* Locking: Caller must hold port->buf.lock
|
||||
*/
|
||||
static int __tty_buffer_request_room(struct tty_struct *tty, size_t size)
|
||||
static int __tty_buffer_request_room(struct tty_port *port, size_t size)
|
||||
{
|
||||
struct tty_bufhead *buf = &port->buf;
|
||||
struct tty_buffer *b, *n;
|
||||
int left;
|
||||
/* OPTIMISATION: We could keep a per tty "zero" sized buffer to
|
||||
remove this conditional if its worth it. This would be invisible
|
||||
to the callers */
|
||||
if ((b = tty->buf.tail) != NULL)
|
||||
b = buf->tail;
|
||||
if (b != NULL)
|
||||
left = b->size - b->used;
|
||||
else
|
||||
left = 0;
|
||||
|
||||
if (left < size) {
|
||||
/* This is the slow path - looking for new buffers to use */
|
||||
if ((n = tty_buffer_find(tty, size)) != NULL) {
|
||||
if ((n = tty_buffer_find(port, size)) != NULL) {
|
||||
if (b != NULL) {
|
||||
b->next = n;
|
||||
b->commit = b->used;
|
||||
} else
|
||||
tty->buf.head = n;
|
||||
tty->buf.tail = n;
|
||||
buf->head = n;
|
||||
buf->tail = n;
|
||||
} else
|
||||
size = left;
|
||||
}
|
||||
@@ -231,16 +241,17 @@ static int __tty_buffer_request_room(struct tty_struct *tty, size_t size)
|
||||
* Make at least size bytes of linear space available for the tty
|
||||
* buffer. If we fail return the size we managed to find.
|
||||
*
|
||||
* Locking: Takes tty->buf.lock
|
||||
* Locking: Takes port->buf.lock
|
||||
*/
|
||||
int tty_buffer_request_room(struct tty_struct *tty, size_t size)
|
||||
{
|
||||
struct tty_port *port = tty->port;
|
||||
unsigned long flags;
|
||||
int length;
|
||||
|
||||
spin_lock_irqsave(&tty->buf.lock, flags);
|
||||
length = __tty_buffer_request_room(tty, size);
|
||||
spin_unlock_irqrestore(&tty->buf.lock, flags);
|
||||
spin_lock_irqsave(&port->buf.lock, flags);
|
||||
length = __tty_buffer_request_room(port, size);
|
||||
spin_unlock_irqrestore(&port->buf.lock, flags);
|
||||
return length;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tty_buffer_request_room);
|
||||
@@ -255,12 +266,13 @@ EXPORT_SYMBOL_GPL(tty_buffer_request_room);
|
||||
* Queue a series of bytes to the tty buffering. All the characters
|
||||
* passed are marked with the supplied flag. Returns the number added.
|
||||
*
|
||||
* Locking: Called functions may take tty->buf.lock
|
||||
* Locking: Called functions may take port->buf.lock
|
||||
*/
|
||||
|
||||
int tty_insert_flip_string_fixed_flag(struct tty_struct *tty,
|
||||
const unsigned char *chars, char flag, size_t size)
|
||||
{
|
||||
struct tty_bufhead *buf = &tty->port->buf;
|
||||
int copied = 0;
|
||||
do {
|
||||
int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE);
|
||||
@@ -268,18 +280,18 @@ int tty_insert_flip_string_fixed_flag(struct tty_struct *tty,
|
||||
unsigned long flags;
|
||||
struct tty_buffer *tb;
|
||||
|
||||
spin_lock_irqsave(&tty->buf.lock, flags);
|
||||
space = __tty_buffer_request_room(tty, goal);
|
||||
tb = tty->buf.tail;
|
||||
spin_lock_irqsave(&buf->lock, flags);
|
||||
space = __tty_buffer_request_room(tty->port, goal);
|
||||
tb = buf->tail;
|
||||
/* If there is no space then tb may be NULL */
|
||||
if (unlikely(space == 0)) {
|
||||
spin_unlock_irqrestore(&tty->buf.lock, flags);
|
||||
spin_unlock_irqrestore(&buf->lock, flags);
|
||||
break;
|
||||
}
|
||||
memcpy(tb->char_buf_ptr + tb->used, chars, space);
|
||||
memset(tb->flag_buf_ptr + tb->used, flag, space);
|
||||
tb->used += space;
|
||||
spin_unlock_irqrestore(&tty->buf.lock, flags);
|
||||
spin_unlock_irqrestore(&buf->lock, flags);
|
||||
copied += space;
|
||||
chars += space;
|
||||
/* There is a small chance that we need to split the data over
|
||||
@@ -300,12 +312,13 @@ EXPORT_SYMBOL(tty_insert_flip_string_fixed_flag);
|
||||
* the flags array indicates the status of the character. Returns the
|
||||
* number added.
|
||||
*
|
||||
* Locking: Called functions may take tty->buf.lock
|
||||
* Locking: Called functions may take port->buf.lock
|
||||
*/
|
||||
|
||||
int tty_insert_flip_string_flags(struct tty_struct *tty,
|
||||
const unsigned char *chars, const char *flags, size_t size)
|
||||
{
|
||||
struct tty_bufhead *buf = &tty->port->buf;
|
||||
int copied = 0;
|
||||
do {
|
||||
int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE);
|
||||
@@ -313,18 +326,18 @@ int tty_insert_flip_string_flags(struct tty_struct *tty,
|
||||
unsigned long __flags;
|
||||
struct tty_buffer *tb;
|
||||
|
||||
spin_lock_irqsave(&tty->buf.lock, __flags);
|
||||
space = __tty_buffer_request_room(tty, goal);
|
||||
tb = tty->buf.tail;
|
||||
spin_lock_irqsave(&buf->lock, __flags);
|
||||
space = __tty_buffer_request_room(tty->port, goal);
|
||||
tb = buf->tail;
|
||||
/* If there is no space then tb may be NULL */
|
||||
if (unlikely(space == 0)) {
|
||||
spin_unlock_irqrestore(&tty->buf.lock, __flags);
|
||||
spin_unlock_irqrestore(&buf->lock, __flags);
|
||||
break;
|
||||
}
|
||||
memcpy(tb->char_buf_ptr + tb->used, chars, space);
|
||||
memcpy(tb->flag_buf_ptr + tb->used, flags, space);
|
||||
tb->used += space;
|
||||
spin_unlock_irqrestore(&tty->buf.lock, __flags);
|
||||
spin_unlock_irqrestore(&buf->lock, __flags);
|
||||
copied += space;
|
||||
chars += space;
|
||||
flags += space;
|
||||
@@ -342,18 +355,23 @@ EXPORT_SYMBOL(tty_insert_flip_string_flags);
|
||||
* Takes any pending buffers and transfers their ownership to the
|
||||
* ldisc side of the queue. It then schedules those characters for
|
||||
* processing by the line discipline.
|
||||
* Note that this function can only be used when the low_latency flag
|
||||
* is unset. Otherwise the workqueue won't be flushed.
|
||||
*
|
||||
* Locking: Takes tty->buf.lock
|
||||
* Locking: Takes port->buf.lock
|
||||
*/
|
||||
|
||||
void tty_schedule_flip(struct tty_struct *tty)
|
||||
{
|
||||
struct tty_bufhead *buf = &tty->port->buf;
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&tty->buf.lock, flags);
|
||||
if (tty->buf.tail != NULL)
|
||||
tty->buf.tail->commit = tty->buf.tail->used;
|
||||
spin_unlock_irqrestore(&tty->buf.lock, flags);
|
||||
schedule_work(&tty->buf.work);
|
||||
WARN_ON(tty->low_latency);
|
||||
|
||||
spin_lock_irqsave(&buf->lock, flags);
|
||||
if (buf->tail != NULL)
|
||||
buf->tail->commit = buf->tail->used;
|
||||
spin_unlock_irqrestore(&buf->lock, flags);
|
||||
schedule_work(&buf->work);
|
||||
}
|
||||
EXPORT_SYMBOL(tty_schedule_flip);
|
||||
|
||||
@@ -369,26 +387,27 @@ EXPORT_SYMBOL(tty_schedule_flip);
|
||||
* that need their own block copy routines into the buffer. There is no
|
||||
* guarantee the buffer is a DMA target!
|
||||
*
|
||||
* Locking: May call functions taking tty->buf.lock
|
||||
* Locking: May call functions taking port->buf.lock
|
||||
*/
|
||||
|
||||
int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars,
|
||||
size_t size)
|
||||
size_t size)
|
||||
{
|
||||
struct tty_bufhead *buf = &tty->port->buf;
|
||||
int space;
|
||||
unsigned long flags;
|
||||
struct tty_buffer *tb;
|
||||
|
||||
spin_lock_irqsave(&tty->buf.lock, flags);
|
||||
space = __tty_buffer_request_room(tty, size);
|
||||
spin_lock_irqsave(&buf->lock, flags);
|
||||
space = __tty_buffer_request_room(tty->port, size);
|
||||
|
||||
tb = tty->buf.tail;
|
||||
tb = buf->tail;
|
||||
if (likely(space)) {
|
||||
*chars = tb->char_buf_ptr + tb->used;
|
||||
memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space);
|
||||
tb->used += space;
|
||||
}
|
||||
spin_unlock_irqrestore(&tty->buf.lock, flags);
|
||||
spin_unlock_irqrestore(&buf->lock, flags);
|
||||
return space;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tty_prepare_flip_string);
|
||||
@@ -406,26 +425,27 @@ EXPORT_SYMBOL_GPL(tty_prepare_flip_string);
|
||||
* that need their own block copy routines into the buffer. There is no
|
||||
* guarantee the buffer is a DMA target!
|
||||
*
|
||||
* Locking: May call functions taking tty->buf.lock
|
||||
* Locking: May call functions taking port->buf.lock
|
||||
*/
|
||||
|
||||
int tty_prepare_flip_string_flags(struct tty_struct *tty,
|
||||
unsigned char **chars, char **flags, size_t size)
|
||||
{
|
||||
struct tty_bufhead *buf = &tty->port->buf;
|
||||
int space;
|
||||
unsigned long __flags;
|
||||
struct tty_buffer *tb;
|
||||
|
||||
spin_lock_irqsave(&tty->buf.lock, __flags);
|
||||
space = __tty_buffer_request_room(tty, size);
|
||||
spin_lock_irqsave(&buf->lock, __flags);
|
||||
space = __tty_buffer_request_room(tty->port, size);
|
||||
|
||||
tb = tty->buf.tail;
|
||||
tb = buf->tail;
|
||||
if (likely(space)) {
|
||||
*chars = tb->char_buf_ptr + tb->used;
|
||||
*flags = tb->flag_buf_ptr + tb->used;
|
||||
tb->used += space;
|
||||
}
|
||||
spin_unlock_irqrestore(&tty->buf.lock, __flags);
|
||||
spin_unlock_irqrestore(&buf->lock, __flags);
|
||||
return space;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags);
|
||||
@@ -446,20 +466,25 @@ EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags);
|
||||
|
||||
static void flush_to_ldisc(struct work_struct *work)
|
||||
{
|
||||
struct tty_struct *tty =
|
||||
container_of(work, struct tty_struct, buf.work);
|
||||
struct tty_port *port = container_of(work, struct tty_port, buf.work);
|
||||
struct tty_bufhead *buf = &port->buf;
|
||||
struct tty_struct *tty;
|
||||
unsigned long flags;
|
||||
struct tty_ldisc *disc;
|
||||
|
||||
tty = port->itty;
|
||||
if (WARN_RATELIMIT(tty == NULL, "tty is NULL\n"))
|
||||
return;
|
||||
|
||||
disc = tty_ldisc_ref(tty);
|
||||
if (disc == NULL) /* !TTY_LDISC */
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&tty->buf.lock, flags);
|
||||
spin_lock_irqsave(&buf->lock, flags);
|
||||
|
||||
if (!test_and_set_bit(TTY_FLUSHING, &tty->flags)) {
|
||||
if (!test_and_set_bit(TTYP_FLUSHING, &port->iflags)) {
|
||||
struct tty_buffer *head;
|
||||
while ((head = tty->buf.head) != NULL) {
|
||||
while ((head = buf->head) != NULL) {
|
||||
int count;
|
||||
char *char_buf;
|
||||
unsigned char *flag_buf;
|
||||
@@ -468,14 +493,14 @@ static void flush_to_ldisc(struct work_struct *work)
|
||||
if (!count) {
|
||||
if (head->next == NULL)
|
||||
break;
|
||||
tty->buf.head = head->next;
|
||||
tty_buffer_free(tty, head);
|
||||
buf->head = head->next;
|
||||
tty_buffer_free(port, head);
|
||||
continue;
|
||||
}
|
||||
/* Ldisc or user is trying to flush the buffers
|
||||
we are feeding to the ldisc, stop feeding the
|
||||
line discipline as we want to empty the queue */
|
||||
if (test_bit(TTY_FLUSHPENDING, &tty->flags))
|
||||
if (test_bit(TTYP_FLUSHPENDING, &port->iflags))
|
||||
break;
|
||||
if (!tty->receive_room)
|
||||
break;
|
||||
@@ -484,22 +509,22 @@ static void flush_to_ldisc(struct work_struct *work)
|
||||
char_buf = head->char_buf_ptr + head->read;
|
||||
flag_buf = head->flag_buf_ptr + head->read;
|
||||
head->read += count;
|
||||
spin_unlock_irqrestore(&tty->buf.lock, flags);
|
||||
spin_unlock_irqrestore(&buf->lock, flags);
|
||||
disc->ops->receive_buf(tty, char_buf,
|
||||
flag_buf, count);
|
||||
spin_lock_irqsave(&tty->buf.lock, flags);
|
||||
spin_lock_irqsave(&buf->lock, flags);
|
||||
}
|
||||
clear_bit(TTY_FLUSHING, &tty->flags);
|
||||
clear_bit(TTYP_FLUSHING, &port->iflags);
|
||||
}
|
||||
|
||||
/* We may have a deferred request to flush the input buffer,
|
||||
if so pull the chain under the lock and empty the queue */
|
||||
if (test_bit(TTY_FLUSHPENDING, &tty->flags)) {
|
||||
__tty_buffer_flush(tty);
|
||||
clear_bit(TTY_FLUSHPENDING, &tty->flags);
|
||||
if (test_bit(TTYP_FLUSHPENDING, &port->iflags)) {
|
||||
__tty_buffer_flush(port);
|
||||
clear_bit(TTYP_FLUSHPENDING, &port->iflags);
|
||||
wake_up(&tty->read_wait);
|
||||
}
|
||||
spin_unlock_irqrestore(&tty->buf.lock, flags);
|
||||
spin_unlock_irqrestore(&buf->lock, flags);
|
||||
|
||||
tty_ldisc_deref(disc);
|
||||
}
|
||||
@@ -514,7 +539,8 @@ static void flush_to_ldisc(struct work_struct *work)
|
||||
*/
|
||||
void tty_flush_to_ldisc(struct tty_struct *tty)
|
||||
{
|
||||
flush_work(&tty->buf.work);
|
||||
if (!tty->low_latency)
|
||||
flush_work(&tty->port->buf.work);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -532,16 +558,18 @@ void tty_flush_to_ldisc(struct tty_struct *tty)
|
||||
|
||||
void tty_flip_buffer_push(struct tty_struct *tty)
|
||||
{
|
||||
struct tty_bufhead *buf = &tty->port->buf;
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&tty->buf.lock, flags);
|
||||
if (tty->buf.tail != NULL)
|
||||
tty->buf.tail->commit = tty->buf.tail->used;
|
||||
spin_unlock_irqrestore(&tty->buf.lock, flags);
|
||||
|
||||
spin_lock_irqsave(&buf->lock, flags);
|
||||
if (buf->tail != NULL)
|
||||
buf->tail->commit = buf->tail->used;
|
||||
spin_unlock_irqrestore(&buf->lock, flags);
|
||||
|
||||
if (tty->low_latency)
|
||||
flush_to_ldisc(&tty->buf.work);
|
||||
flush_to_ldisc(&buf->work);
|
||||
else
|
||||
schedule_work(&tty->buf.work);
|
||||
schedule_work(&buf->work);
|
||||
}
|
||||
EXPORT_SYMBOL(tty_flip_buffer_push);
|
||||
|
||||
@@ -555,13 +583,15 @@ EXPORT_SYMBOL(tty_flip_buffer_push);
|
||||
* Locking: none
|
||||
*/
|
||||
|
||||
void tty_buffer_init(struct tty_struct *tty)
|
||||
void tty_buffer_init(struct tty_port *port)
|
||||
{
|
||||
spin_lock_init(&tty->buf.lock);
|
||||
tty->buf.head = NULL;
|
||||
tty->buf.tail = NULL;
|
||||
tty->buf.free = NULL;
|
||||
tty->buf.memory_used = 0;
|
||||
INIT_WORK(&tty->buf.work, flush_to_ldisc);
|
||||
struct tty_bufhead *buf = &port->buf;
|
||||
|
||||
spin_lock_init(&buf->lock);
|
||||
buf->head = NULL;
|
||||
buf->tail = NULL;
|
||||
buf->free = NULL;
|
||||
buf->memory_used = 0;
|
||||
INIT_WORK(&buf->work, flush_to_ldisc);
|
||||
}
|
||||
|
||||
|
@@ -186,7 +186,6 @@ void free_tty_struct(struct tty_struct *tty)
|
||||
if (tty->dev)
|
||||
put_device(tty->dev);
|
||||
kfree(tty->write_buf);
|
||||
tty_buffer_free_all(tty);
|
||||
tty->magic = 0xDEADDEAD;
|
||||
kfree(tty);
|
||||
}
|
||||
@@ -237,7 +236,7 @@ void tty_free_file(struct file *file)
|
||||
}
|
||||
|
||||
/* Delete file from its tty */
|
||||
void tty_del_file(struct file *file)
|
||||
static void tty_del_file(struct file *file)
|
||||
{
|
||||
struct tty_file_private *priv = file->private_data;
|
||||
|
||||
@@ -555,7 +554,7 @@ EXPORT_SYMBOL_GPL(tty_wakeup);
|
||||
* tasklist_lock to walk task list for hangup event
|
||||
* ->siglock to protect ->signal/->sighand
|
||||
*/
|
||||
void __tty_hangup(struct tty_struct *tty)
|
||||
static void __tty_hangup(struct tty_struct *tty)
|
||||
{
|
||||
struct file *cons_filp = NULL;
|
||||
struct file *filp, *f = NULL;
|
||||
@@ -1417,6 +1416,8 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx)
|
||||
"%s: %s driver does not set tty->port. This will crash the kernel later. Fix the driver!\n",
|
||||
__func__, tty->driver->name);
|
||||
|
||||
tty->port->itty = tty;
|
||||
|
||||
/*
|
||||
* Structures all installed ... call the ldisc open routines.
|
||||
* If we fail here just call release_tty to clean up. No need
|
||||
@@ -1552,6 +1553,7 @@ static void release_tty(struct tty_struct *tty, int idx)
|
||||
tty->ops->shutdown(tty);
|
||||
tty_free_termios(tty);
|
||||
tty_driver_remove_tty(tty->driver, tty);
|
||||
tty->port->itty = NULL;
|
||||
|
||||
if (tty->link)
|
||||
tty_kref_put(tty->link);
|
||||
@@ -1625,7 +1627,6 @@ int tty_release(struct inode *inode, struct file *filp)
|
||||
struct tty_struct *tty = file_tty(filp);
|
||||
struct tty_struct *o_tty;
|
||||
int pty_master, tty_closing, o_tty_closing, do_sleep;
|
||||
int devpts;
|
||||
int idx;
|
||||
char buf[64];
|
||||
|
||||
@@ -1640,7 +1641,6 @@ int tty_release(struct inode *inode, struct file *filp)
|
||||
idx = tty->index;
|
||||
pty_master = (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
|
||||
tty->driver->subtype == PTY_TYPE_MASTER);
|
||||
devpts = (tty->driver->flags & TTY_DRIVER_DEVPTS_MEM) != 0;
|
||||
/* Review: parallel close */
|
||||
o_tty = tty->link;
|
||||
|
||||
@@ -1799,9 +1799,6 @@ int tty_release(struct inode *inode, struct file *filp)
|
||||
release_tty(tty, idx);
|
||||
mutex_unlock(&tty_mutex);
|
||||
|
||||
/* Make this pty number available for reallocation */
|
||||
if (devpts)
|
||||
devpts_kill_index(inode, idx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2690,6 +2687,11 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
case TIOCNXCL:
|
||||
clear_bit(TTY_EXCLUSIVE, &tty->flags);
|
||||
return 0;
|
||||
case TIOCGEXCL:
|
||||
{
|
||||
int excl = test_bit(TTY_EXCLUSIVE, &tty->flags);
|
||||
return put_user(excl, (int __user *)p);
|
||||
}
|
||||
case TIOCNOTTY:
|
||||
if (current->signal->tty != tty)
|
||||
return -ENOTTY;
|
||||
@@ -2937,19 +2939,13 @@ void initialize_tty_struct(struct tty_struct *tty,
|
||||
tty_ldisc_init(tty);
|
||||
tty->session = NULL;
|
||||
tty->pgrp = NULL;
|
||||
tty->overrun_time = jiffies;
|
||||
tty_buffer_init(tty);
|
||||
mutex_init(&tty->legacy_mutex);
|
||||
mutex_init(&tty->termios_mutex);
|
||||
mutex_init(&tty->ldisc_mutex);
|
||||
init_waitqueue_head(&tty->write_wait);
|
||||
init_waitqueue_head(&tty->read_wait);
|
||||
INIT_WORK(&tty->hangup_work, do_tty_hangup);
|
||||
mutex_init(&tty->atomic_read_lock);
|
||||
mutex_init(&tty->atomic_write_lock);
|
||||
mutex_init(&tty->output_lock);
|
||||
mutex_init(&tty->echo_lock);
|
||||
spin_lock_init(&tty->read_lock);
|
||||
spin_lock_init(&tty->ctrl_lock);
|
||||
INIT_LIST_HEAD(&tty->tty_files);
|
||||
INIT_WORK(&tty->SAK_work, do_SAK_work);
|
||||
|
@@ -1118,7 +1118,6 @@ EXPORT_SYMBOL_GPL(tty_perform_flush);
|
||||
int n_tty_ioctl_helper(struct tty_struct *tty, struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
unsigned long flags;
|
||||
int retval;
|
||||
|
||||
switch (cmd) {
|
||||
@@ -1153,26 +1152,6 @@ int n_tty_ioctl_helper(struct tty_struct *tty, struct file *file,
|
||||
return 0;
|
||||
case TCFLSH:
|
||||
return tty_perform_flush(tty, arg);
|
||||
case TIOCPKT:
|
||||
{
|
||||
int pktmode;
|
||||
|
||||
if (tty->driver->type != TTY_DRIVER_TYPE_PTY ||
|
||||
tty->driver->subtype != PTY_TYPE_MASTER)
|
||||
return -ENOTTY;
|
||||
if (get_user(pktmode, (int __user *) arg))
|
||||
return -EFAULT;
|
||||
spin_lock_irqsave(&tty->ctrl_lock, flags);
|
||||
if (pktmode) {
|
||||
if (!tty->packet) {
|
||||
tty->packet = 1;
|
||||
tty->link->ctrl_status = 0;
|
||||
}
|
||||
} else
|
||||
tty->packet = 0;
|
||||
spin_unlock_irqrestore(&tty->ctrl_lock, flags);
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
/* Try the mode commands */
|
||||
return tty_mode_ioctl(tty, file, cmd, arg);
|
||||
|
@@ -26,7 +26,7 @@
|
||||
* callers who will do ldisc lookups and cannot sleep.
|
||||
*/
|
||||
|
||||
static DEFINE_SPINLOCK(tty_ldisc_lock);
|
||||
static DEFINE_RAW_SPINLOCK(tty_ldisc_lock);
|
||||
static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait);
|
||||
/* Line disc dispatch table */
|
||||
static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS];
|
||||
@@ -49,21 +49,21 @@ static void put_ldisc(struct tty_ldisc *ld)
|
||||
* If this is the last user, free the ldisc, and
|
||||
* release the ldisc ops.
|
||||
*
|
||||
* We really want an "atomic_dec_and_lock_irqsave()",
|
||||
* We really want an "atomic_dec_and_raw_lock_irqsave()",
|
||||
* but we don't have it, so this does it by hand.
|
||||
*/
|
||||
local_irq_save(flags);
|
||||
if (atomic_dec_and_lock(&ld->users, &tty_ldisc_lock)) {
|
||||
raw_spin_lock_irqsave(&tty_ldisc_lock, flags);
|
||||
if (atomic_dec_and_test(&ld->users)) {
|
||||
struct tty_ldisc_ops *ldo = ld->ops;
|
||||
|
||||
ldo->refcount--;
|
||||
module_put(ldo->owner);
|
||||
spin_unlock_irqrestore(&tty_ldisc_lock, flags);
|
||||
raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
|
||||
|
||||
kfree(ld);
|
||||
return;
|
||||
}
|
||||
local_irq_restore(flags);
|
||||
raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
|
||||
wake_up(&ld->wq_idle);
|
||||
}
|
||||
|
||||
@@ -88,11 +88,11 @@ int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc)
|
||||
if (disc < N_TTY || disc >= NR_LDISCS)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&tty_ldisc_lock, flags);
|
||||
raw_spin_lock_irqsave(&tty_ldisc_lock, flags);
|
||||
tty_ldiscs[disc] = new_ldisc;
|
||||
new_ldisc->num = disc;
|
||||
new_ldisc->refcount = 0;
|
||||
spin_unlock_irqrestore(&tty_ldisc_lock, flags);
|
||||
raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -118,12 +118,12 @@ int tty_unregister_ldisc(int disc)
|
||||
if (disc < N_TTY || disc >= NR_LDISCS)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&tty_ldisc_lock, flags);
|
||||
raw_spin_lock_irqsave(&tty_ldisc_lock, flags);
|
||||
if (tty_ldiscs[disc]->refcount)
|
||||
ret = -EBUSY;
|
||||
else
|
||||
tty_ldiscs[disc] = NULL;
|
||||
spin_unlock_irqrestore(&tty_ldisc_lock, flags);
|
||||
raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -134,7 +134,7 @@ static struct tty_ldisc_ops *get_ldops(int disc)
|
||||
unsigned long flags;
|
||||
struct tty_ldisc_ops *ldops, *ret;
|
||||
|
||||
spin_lock_irqsave(&tty_ldisc_lock, flags);
|
||||
raw_spin_lock_irqsave(&tty_ldisc_lock, flags);
|
||||
ret = ERR_PTR(-EINVAL);
|
||||
ldops = tty_ldiscs[disc];
|
||||
if (ldops) {
|
||||
@@ -144,7 +144,7 @@ static struct tty_ldisc_ops *get_ldops(int disc)
|
||||
ret = ldops;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&tty_ldisc_lock, flags);
|
||||
raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -152,10 +152,10 @@ static void put_ldops(struct tty_ldisc_ops *ldops)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&tty_ldisc_lock, flags);
|
||||
raw_spin_lock_irqsave(&tty_ldisc_lock, flags);
|
||||
ldops->refcount--;
|
||||
module_put(ldops->owner);
|
||||
spin_unlock_irqrestore(&tty_ldisc_lock, flags);
|
||||
raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -287,11 +287,11 @@ static struct tty_ldisc *tty_ldisc_try(struct tty_struct *tty)
|
||||
unsigned long flags;
|
||||
struct tty_ldisc *ld;
|
||||
|
||||
spin_lock_irqsave(&tty_ldisc_lock, flags);
|
||||
raw_spin_lock_irqsave(&tty_ldisc_lock, flags);
|
||||
ld = NULL;
|
||||
if (test_bit(TTY_LDISC, &tty->flags))
|
||||
ld = get_ldisc(tty->ldisc);
|
||||
spin_unlock_irqrestore(&tty_ldisc_lock, flags);
|
||||
raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
|
||||
return ld;
|
||||
}
|
||||
|
||||
@@ -512,7 +512,7 @@ static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
|
||||
static int tty_ldisc_halt(struct tty_struct *tty)
|
||||
{
|
||||
clear_bit(TTY_LDISC, &tty->flags);
|
||||
return cancel_work_sync(&tty->buf.work);
|
||||
return cancel_work_sync(&tty->port->buf.work);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -525,7 +525,7 @@ static void tty_ldisc_flush_works(struct tty_struct *tty)
|
||||
{
|
||||
flush_work(&tty->hangup_work);
|
||||
flush_work(&tty->SAK_work);
|
||||
flush_work(&tty->buf.work);
|
||||
flush_work(&tty->port->buf.work);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -704,9 +704,9 @@ enable:
|
||||
/* Restart the work queue in case no characters kick it off. Safe if
|
||||
already running */
|
||||
if (work)
|
||||
schedule_work(&tty->buf.work);
|
||||
schedule_work(&tty->port->buf.work);
|
||||
if (o_work)
|
||||
schedule_work(&o_tty->buf.work);
|
||||
schedule_work(&o_tty->port->buf.work);
|
||||
mutex_unlock(&tty->ldisc_mutex);
|
||||
tty_unlock(tty);
|
||||
return retval;
|
||||
@@ -817,7 +817,7 @@ void tty_ldisc_hangup(struct tty_struct *tty)
|
||||
*/
|
||||
clear_bit(TTY_LDISC, &tty->flags);
|
||||
tty_unlock(tty);
|
||||
cancel_work_sync(&tty->buf.work);
|
||||
cancel_work_sync(&tty->port->buf.work);
|
||||
mutex_unlock(&tty->ldisc_mutex);
|
||||
retry:
|
||||
tty_lock(tty);
|
||||
@@ -897,6 +897,11 @@ int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty)
|
||||
|
||||
static void tty_ldisc_kill(struct tty_struct *tty)
|
||||
{
|
||||
/* There cannot be users from userspace now. But there still might be
|
||||
* drivers holding a reference via tty_ldisc_ref. Do not steal them the
|
||||
* ldisc until they are done. */
|
||||
tty_ldisc_wait_idle(tty, MAX_SCHEDULE_TIMEOUT);
|
||||
|
||||
mutex_lock(&tty->ldisc_mutex);
|
||||
/*
|
||||
* Now kill off the ldisc
|
||||
|
@@ -19,7 +19,7 @@ static void __lockfunc tty_lock_nested(struct tty_struct *tty,
|
||||
unsigned int subclass)
|
||||
{
|
||||
if (tty->magic != TTY_MAGIC) {
|
||||
printk(KERN_ERR "L Bad %p\n", tty);
|
||||
pr_err("L Bad %p\n", tty);
|
||||
WARN_ON(1);
|
||||
return;
|
||||
}
|
||||
@@ -36,7 +36,7 @@ EXPORT_SYMBOL(tty_lock);
|
||||
void __lockfunc tty_unlock(struct tty_struct *tty)
|
||||
{
|
||||
if (tty->magic != TTY_MAGIC) {
|
||||
printk(KERN_ERR "U Bad %p\n", tty);
|
||||
pr_err("U Bad %p\n", tty);
|
||||
WARN_ON(1);
|
||||
return;
|
||||
}
|
||||
|
@@ -21,6 +21,7 @@
|
||||
void tty_port_init(struct tty_port *port)
|
||||
{
|
||||
memset(port, 0, sizeof(*port));
|
||||
tty_buffer_init(port);
|
||||
init_waitqueue_head(&port->open_wait);
|
||||
init_waitqueue_head(&port->close_wait);
|
||||
init_waitqueue_head(&port->delta_msr_wait);
|
||||
@@ -121,12 +122,27 @@ void tty_port_free_xmit_buf(struct tty_port *port)
|
||||
}
|
||||
EXPORT_SYMBOL(tty_port_free_xmit_buf);
|
||||
|
||||
/**
|
||||
* tty_port_destroy -- destroy inited port
|
||||
* @port: tty port to be doestroyed
|
||||
*
|
||||
* When a port was initialized using tty_port_init, one has to destroy the
|
||||
* port by this function. Either indirectly by using tty_port refcounting
|
||||
* (tty_port_put) or directly if refcounting is not used.
|
||||
*/
|
||||
void tty_port_destroy(struct tty_port *port)
|
||||
{
|
||||
tty_buffer_free_all(port);
|
||||
}
|
||||
EXPORT_SYMBOL(tty_port_destroy);
|
||||
|
||||
static void tty_port_destructor(struct kref *kref)
|
||||
{
|
||||
struct tty_port *port = container_of(kref, struct tty_port, kref);
|
||||
if (port->xmit_buf)
|
||||
free_page((unsigned long)port->xmit_buf);
|
||||
if (port->ops->destruct)
|
||||
tty_port_destroy(port);
|
||||
if (port->ops && port->ops->destruct)
|
||||
port->ops->destruct(port);
|
||||
else
|
||||
kfree(port);
|
||||
|
@@ -410,10 +410,8 @@ static void con_release_unimap(struct uni_pagedir *p)
|
||||
kfree(p->inverse_translations[i]);
|
||||
p->inverse_translations[i] = NULL;
|
||||
}
|
||||
if (p->inverse_trans_unicode) {
|
||||
kfree(p->inverse_trans_unicode);
|
||||
p->inverse_trans_unicode = NULL;
|
||||
}
|
||||
kfree(p->inverse_trans_unicode);
|
||||
p->inverse_trans_unicode = NULL;
|
||||
}
|
||||
|
||||
/* Caller must hold the console lock */
|
||||
|
@@ -341,15 +341,11 @@ int paste_selection(struct tty_struct *tty)
|
||||
struct tty_ldisc *ld;
|
||||
DECLARE_WAITQUEUE(wait, current);
|
||||
|
||||
|
||||
console_lock();
|
||||
poke_blanked_console();
|
||||
console_unlock();
|
||||
|
||||
/* FIXME: wtf is this supposed to achieve ? */
|
||||
ld = tty_ldisc_ref(tty);
|
||||
if (!ld)
|
||||
ld = tty_ldisc_ref_wait(tty);
|
||||
ld = tty_ldisc_ref_wait(tty);
|
||||
|
||||
/* FIXME: this is completely unsafe */
|
||||
add_wait_queue(&vc->paste_wait, &wait);
|
||||
@@ -361,8 +357,7 @@ int paste_selection(struct tty_struct *tty)
|
||||
}
|
||||
count = sel_buffer_lth - pasted;
|
||||
count = min(count, tty->receive_room);
|
||||
tty->ldisc->ops->receive_buf(tty, sel_buffer + pasted,
|
||||
NULL, count);
|
||||
ld->ops->receive_buf(tty, sel_buffer + pasted, NULL, count);
|
||||
pasted += count;
|
||||
}
|
||||
remove_wait_queue(&vc->paste_wait, &wait);
|
||||
|
@@ -779,6 +779,7 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */
|
||||
con_set_default_unimap(vc);
|
||||
vc->vc_screenbuf = kmalloc(vc->vc_screenbuf_size, GFP_KERNEL);
|
||||
if (!vc->vc_screenbuf) {
|
||||
tty_port_destroy(&vc->port);
|
||||
kfree(vc);
|
||||
vc_cons[currcons].d = NULL;
|
||||
return -ENOMEM;
|
||||
@@ -999,8 +1000,10 @@ void vc_deallocate(unsigned int currcons)
|
||||
put_pid(vc->vt_pid);
|
||||
module_put(vc->vc_sw->owner);
|
||||
kfree(vc->vc_screenbuf);
|
||||
if (currcons >= MIN_NR_CONSOLES)
|
||||
if (currcons >= MIN_NR_CONSOLES) {
|
||||
tty_port_destroy(&vc->port);
|
||||
kfree(vc);
|
||||
}
|
||||
vc_cons[currcons].d = NULL;
|
||||
}
|
||||
}
|
||||
|
@@ -25,6 +25,7 @@
|
||||
#include <linux/console.h>
|
||||
#include <linux/consolemap.h>
|
||||
#include <linux/signal.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <linux/timex.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
|
Reference in New Issue
Block a user