^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * mos7720.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Controls the Moschip 7720 usb to dual port serial converter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright 2006 Moschip Semiconductor Tech. Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Developed by:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Vijaya Kumar <vijaykumar.gn@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Ajay Kumar <naanuajay@yahoo.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Gurudeva <ngurudeva@yahoo.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Cleaned up from the original by:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * Greg Kroah-Hartman <gregkh@suse.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * Originally based on drivers/usb/serial/io_edgeport.c which is:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * Copyright (C) 2000 Inside Out Networks, All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * Copyright (C) 2001-2002 Greg Kroah-Hartman <greg@kroah.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/tty.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/tty_driver.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/tty_flip.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/serial.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/serial_reg.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/usb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/usb/serial.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/parport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define DRIVER_AUTHOR "Aspire Communications pvt Ltd."
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define DRIVER_DESC "Moschip USB Serial Driver"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) /* default urb timeout */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define MOS_WDR_TIMEOUT 5000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define MOS_MAX_PORT 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define MOS_WRITE 0x0E
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define MOS_READ 0x0D
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) /* Interrupt Routines Defines */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define SERIAL_IIR_RLS 0x06
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define SERIAL_IIR_RDA 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define SERIAL_IIR_CTI 0x0c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define SERIAL_IIR_THR 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define SERIAL_IIR_MS 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define NUM_URBS 16 /* URB Count */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define URB_TRANSFER_BUFFER_SIZE 32 /* URB Size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) /* This structure holds all of the local serial port information */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) struct moschip_port {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) __u8 shadowLCR; /* last LCR value received */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) __u8 shadowMCR; /* last MCR value received */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) __u8 shadowMSR; /* last MSR value received */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) char open;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) struct usb_serial_port *port; /* loop back to the owner */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) struct urb *write_urb_pool[NUM_URBS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define USB_VENDOR_ID_MOSCHIP 0x9710
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define MOSCHIP_DEVICE_ID_7720 0x7720
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define MOSCHIP_DEVICE_ID_7715 0x7715
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) static const struct usb_device_id id_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) { USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7720) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) { USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7715) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) { } /* terminating entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) MODULE_DEVICE_TABLE(usb, id_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #ifdef CONFIG_USB_SERIAL_MOS7715_PARPORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) /* initial values for parport regs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define DCR_INIT_VAL 0x0c /* SLCTIN, nINIT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define ECR_INIT_VAL 0x00 /* SPP mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) struct urbtracker {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) struct mos7715_parport *mos_parport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) struct list_head urblist_entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) struct kref ref_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) struct urb *urb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) struct usb_ctrlrequest *setup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) enum mos7715_pp_modes {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) SPP = 0<<5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) PS2 = 1<<5, /* moschip calls this 'NIBBLE' mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) PPF = 2<<5, /* moschip calls this 'CB-FIFO mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) struct mos7715_parport {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) struct parport *pp; /* back to containing struct */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) struct kref ref_count; /* to instance of this struct */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) struct list_head deferred_urbs; /* list deferred async urbs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) struct list_head active_urbs; /* list async urbs in flight */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) spinlock_t listlock; /* protects list access */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) bool msg_pending; /* usb sync call pending */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) struct completion syncmsg_compl; /* usb sync call completed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) struct tasklet_struct urb_tasklet; /* for sending deferred urbs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) struct usb_serial *serial; /* back to containing struct */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) __u8 shadowECR; /* parallel port regs... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) __u8 shadowDCR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) atomic_t shadowDSR; /* updated in int-in callback */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) /* lock guards against dereferencing NULL ptr in parport ops callbacks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) static DEFINE_SPINLOCK(release_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) #endif /* CONFIG_USB_SERIAL_MOS7715_PARPORT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) static const unsigned int dummy; /* for clarity in register access fns */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) enum mos_regs {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) MOS7720_THR, /* serial port regs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) MOS7720_RHR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) MOS7720_IER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) MOS7720_FCR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) MOS7720_ISR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) MOS7720_LCR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) MOS7720_MCR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) MOS7720_LSR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) MOS7720_MSR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) MOS7720_SPR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) MOS7720_DLL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) MOS7720_DLM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) MOS7720_DPR, /* parallel port regs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) MOS7720_DSR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) MOS7720_DCR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) MOS7720_ECR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) MOS7720_SP1_REG, /* device control regs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) MOS7720_SP2_REG, /* serial port 2 (7720 only) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) MOS7720_PP_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) MOS7720_SP_CONTROL_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * Return the correct value for the Windex field of the setup packet
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * for a control endpoint message. See the 7715 datasheet.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) static inline __u16 get_reg_index(enum mos_regs reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) static const __u16 mos7715_index_lookup_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 0x00, /* MOS7720_THR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 0x00, /* MOS7720_RHR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 0x01, /* MOS7720_IER */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 0x02, /* MOS7720_FCR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 0x02, /* MOS7720_ISR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 0x03, /* MOS7720_LCR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 0x04, /* MOS7720_MCR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 0x05, /* MOS7720_LSR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 0x06, /* MOS7720_MSR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 0x07, /* MOS7720_SPR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 0x00, /* MOS7720_DLL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 0x01, /* MOS7720_DLM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 0x00, /* MOS7720_DPR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 0x01, /* MOS7720_DSR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 0x02, /* MOS7720_DCR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 0x0a, /* MOS7720_ECR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 0x01, /* MOS7720_SP1_REG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 0x02, /* MOS7720_SP2_REG (7720 only) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 0x04, /* MOS7720_PP_REG (7715 only) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 0x08, /* MOS7720_SP_CONTROL_REG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) return mos7715_index_lookup_table[reg];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) * Return the correct value for the upper byte of the Wvalue field of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * the setup packet for a control endpoint message.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) static inline __u16 get_reg_value(enum mos_regs reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) unsigned int serial_portnum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) if (reg >= MOS7720_SP1_REG) /* control reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) return 0x0000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) else if (reg >= MOS7720_DPR) /* parallel port reg (7715 only) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) return 0x0100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) else /* serial port reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) return (serial_portnum + 2) << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) * Write data byte to the specified device register. The data is embedded in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) * the value field of the setup packet. serial_portnum is ignored for registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) * not specific to a particular serial port.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) static int write_mos_reg(struct usb_serial *serial, unsigned int serial_portnum,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) enum mos_regs reg, __u8 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) struct usb_device *usbdev = serial->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) unsigned int pipe = usb_sndctrlpipe(usbdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) __u8 request = (__u8)0x0e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) __u8 requesttype = (__u8)0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) __u16 index = get_reg_index(reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) __u16 value = get_reg_value(reg, serial_portnum) + data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) int status = usb_control_msg(usbdev, pipe, request, requesttype, value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) index, NULL, 0, MOS_WDR_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) dev_err(&usbdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) "mos7720: usb_control_msg() failed: %d\n", status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) * Read data byte from the specified device register. The data returned by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) * device is embedded in the value field of the setup packet. serial_portnum is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) * ignored for registers that are not specific to a particular serial port.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) static int read_mos_reg(struct usb_serial *serial, unsigned int serial_portnum,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) enum mos_regs reg, __u8 *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) struct usb_device *usbdev = serial->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) unsigned int pipe = usb_rcvctrlpipe(usbdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) __u8 request = (__u8)0x0d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) __u8 requesttype = (__u8)0xc0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) __u16 index = get_reg_index(reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) __u16 value = get_reg_value(reg, serial_portnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) u8 *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) buf = kmalloc(1, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) if (!buf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) *data = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) status = usb_control_msg(usbdev, pipe, request, requesttype, value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) index, buf, 1, MOS_WDR_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) if (status == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) *data = *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) dev_err(&usbdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) "mos7720: usb_control_msg() failed: %d\n", status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) if (status >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) status = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) *data = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) #ifdef CONFIG_USB_SERIAL_MOS7715_PARPORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) static inline int mos7715_change_mode(struct mos7715_parport *mos_parport,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) enum mos7715_pp_modes mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) mos_parport->shadowECR = mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) write_mos_reg(mos_parport->serial, dummy, MOS7720_ECR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) mos_parport->shadowECR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) static void destroy_mos_parport(struct kref *kref)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) struct mos7715_parport *mos_parport =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) container_of(kref, struct mos7715_parport, ref_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) kfree(mos_parport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) static void destroy_urbtracker(struct kref *kref)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) struct urbtracker *urbtrack =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) container_of(kref, struct urbtracker, ref_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) struct mos7715_parport *mos_parport = urbtrack->mos_parport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) usb_free_urb(urbtrack->urb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) kfree(urbtrack->setup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) kfree(urbtrack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) kref_put(&mos_parport->ref_count, destroy_mos_parport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) * This runs as a tasklet when sending an urb in a non-blocking parallel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) * port callback had to be deferred because the disconnect mutex could not be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) * obtained at the time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) static void send_deferred_urbs(struct tasklet_struct *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) int ret_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) struct mos7715_parport *mos_parport = from_tasklet(mos_parport, t,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) urb_tasklet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) struct urbtracker *urbtrack, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) struct list_head *cursor, *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) /* if release function ran, game over */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) if (unlikely(mos_parport->serial == NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) dev = &mos_parport->serial->dev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) /* try again to get the mutex */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) if (!mutex_trylock(&mos_parport->serial->disc_mutex)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) dev_dbg(dev, "%s: rescheduling tasklet\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) tasklet_schedule(&mos_parport->urb_tasklet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) /* if device disconnected, game over */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) if (unlikely(mos_parport->serial->disconnected)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) mutex_unlock(&mos_parport->serial->disc_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) spin_lock_irqsave(&mos_parport->listlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) if (list_empty(&mos_parport->deferred_urbs)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) spin_unlock_irqrestore(&mos_parport->listlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) mutex_unlock(&mos_parport->serial->disc_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) dev_dbg(dev, "%s: deferred_urbs list empty\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) /* move contents of deferred_urbs list to active_urbs list and submit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) list_for_each_safe(cursor, next, &mos_parport->deferred_urbs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) list_move_tail(cursor, &mos_parport->active_urbs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) list_for_each_entry_safe(urbtrack, tmp, &mos_parport->active_urbs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) urblist_entry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) ret_val = usb_submit_urb(urbtrack->urb, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) dev_dbg(dev, "%s: urb submitted\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) if (ret_val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) dev_err(dev, "usb_submit_urb() failed: %d\n", ret_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) list_del(&urbtrack->urblist_entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) kref_put(&urbtrack->ref_count, destroy_urbtracker);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) spin_unlock_irqrestore(&mos_parport->listlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) mutex_unlock(&mos_parport->serial->disc_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) /* callback for parallel port control urbs submitted asynchronously */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) static void async_complete(struct urb *urb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) struct urbtracker *urbtrack = urb->context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) int status = urb->status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) if (unlikely(status))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) dev_dbg(&urb->dev->dev, "%s - nonzero urb status received: %d\n", __func__, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) /* remove the urbtracker from the active_urbs list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) spin_lock_irqsave(&urbtrack->mos_parport->listlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) list_del(&urbtrack->urblist_entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) spin_unlock_irqrestore(&urbtrack->mos_parport->listlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) kref_put(&urbtrack->ref_count, destroy_urbtracker);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) static int write_parport_reg_nonblock(struct mos7715_parport *mos_parport,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) enum mos_regs reg, __u8 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) struct urbtracker *urbtrack;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) int ret_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) struct usb_serial *serial = mos_parport->serial;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) struct usb_device *usbdev = serial->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) /* create and initialize the control urb and containing urbtracker */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) urbtrack = kmalloc(sizeof(struct urbtracker), GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) if (!urbtrack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) urbtrack->urb = usb_alloc_urb(0, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) if (!urbtrack->urb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) kfree(urbtrack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) urbtrack->setup = kmalloc(sizeof(*urbtrack->setup), GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) if (!urbtrack->setup) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) usb_free_urb(urbtrack->urb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) kfree(urbtrack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) urbtrack->setup->bRequestType = (__u8)0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) urbtrack->setup->bRequest = (__u8)0x0e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) urbtrack->setup->wValue = cpu_to_le16(get_reg_value(reg, dummy));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) urbtrack->setup->wIndex = cpu_to_le16(get_reg_index(reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) urbtrack->setup->wLength = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) usb_fill_control_urb(urbtrack->urb, usbdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) usb_sndctrlpipe(usbdev, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) (unsigned char *)urbtrack->setup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) NULL, 0, async_complete, urbtrack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) kref_get(&mos_parport->ref_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) urbtrack->mos_parport = mos_parport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) kref_init(&urbtrack->ref_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) INIT_LIST_HEAD(&urbtrack->urblist_entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) * get the disconnect mutex, or add tracker to the deferred_urbs list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) * and schedule a tasklet to try again later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) if (!mutex_trylock(&serial->disc_mutex)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) spin_lock_irqsave(&mos_parport->listlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) list_add_tail(&urbtrack->urblist_entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) &mos_parport->deferred_urbs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) spin_unlock_irqrestore(&mos_parport->listlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) tasklet_schedule(&mos_parport->urb_tasklet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) dev_dbg(&usbdev->dev, "tasklet scheduled\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) /* bail if device disconnected */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) if (serial->disconnected) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) kref_put(&urbtrack->ref_count, destroy_urbtracker);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) mutex_unlock(&serial->disc_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) /* add the tracker to the active_urbs list and submit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) spin_lock_irqsave(&mos_parport->listlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) list_add_tail(&urbtrack->urblist_entry, &mos_parport->active_urbs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) spin_unlock_irqrestore(&mos_parport->listlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) ret_val = usb_submit_urb(urbtrack->urb, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) mutex_unlock(&serial->disc_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) if (ret_val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) dev_err(&usbdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) "%s: submit_urb() failed: %d\n", __func__, ret_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) spin_lock_irqsave(&mos_parport->listlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) list_del(&urbtrack->urblist_entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) spin_unlock_irqrestore(&mos_parport->listlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) kref_put(&urbtrack->ref_count, destroy_urbtracker);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) return ret_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) * This is the the common top part of all parallel port callback operations that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) * send synchronous messages to the device. This implements convoluted locking
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) * that avoids two scenarios: (1) a port operation is called after usbserial
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) * has called our release function, at which point struct mos7715_parport has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) * been destroyed, and (2) the device has been disconnected, but usbserial has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) * not called the release function yet because someone has a serial port open.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) * The shared release_lock prevents the first, and the mutex and disconnected
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) * flag maintained by usbserial covers the second. We also use the msg_pending
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) * flag to ensure that all synchronous usb message calls have completed before
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) * our release function can return.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) static int parport_prologue(struct parport *pp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) struct mos7715_parport *mos_parport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) spin_lock(&release_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) mos_parport = pp->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) if (unlikely(mos_parport == NULL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) /* release fn called, port struct destroyed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) spin_unlock(&release_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) mos_parport->msg_pending = true; /* synch usb call pending */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) reinit_completion(&mos_parport->syncmsg_compl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) spin_unlock(&release_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) mutex_lock(&mos_parport->serial->disc_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) if (mos_parport->serial->disconnected) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) /* device disconnected */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) mutex_unlock(&mos_parport->serial->disc_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) mos_parport->msg_pending = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) complete(&mos_parport->syncmsg_compl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) * This is the common bottom part of all parallel port functions that send
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) * synchronous messages to the device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) static inline void parport_epilogue(struct parport *pp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) struct mos7715_parport *mos_parport = pp->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) mutex_unlock(&mos_parport->serial->disc_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) mos_parport->msg_pending = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) complete(&mos_parport->syncmsg_compl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) static void parport_mos7715_write_data(struct parport *pp, unsigned char d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) struct mos7715_parport *mos_parport = pp->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) if (parport_prologue(pp) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) mos7715_change_mode(mos_parport, SPP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) write_mos_reg(mos_parport->serial, dummy, MOS7720_DPR, (__u8)d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) parport_epilogue(pp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) static unsigned char parport_mos7715_read_data(struct parport *pp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) struct mos7715_parport *mos_parport = pp->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) unsigned char d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) if (parport_prologue(pp) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) read_mos_reg(mos_parport->serial, dummy, MOS7720_DPR, &d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) parport_epilogue(pp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) return d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) static void parport_mos7715_write_control(struct parport *pp, unsigned char d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) struct mos7715_parport *mos_parport = pp->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) __u8 data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) if (parport_prologue(pp) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) data = ((__u8)d & 0x0f) | (mos_parport->shadowDCR & 0xf0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) write_mos_reg(mos_parport->serial, dummy, MOS7720_DCR, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) mos_parport->shadowDCR = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) parport_epilogue(pp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) static unsigned char parport_mos7715_read_control(struct parport *pp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) struct mos7715_parport *mos_parport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) __u8 dcr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) spin_lock(&release_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) mos_parport = pp->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) if (unlikely(mos_parport == NULL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) spin_unlock(&release_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) dcr = mos_parport->shadowDCR & 0x0f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) spin_unlock(&release_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) return dcr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) static unsigned char parport_mos7715_frob_control(struct parport *pp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) unsigned char mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) unsigned char val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) struct mos7715_parport *mos_parport = pp->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) __u8 dcr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) mask &= 0x0f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) val &= 0x0f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) if (parport_prologue(pp) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) mos_parport->shadowDCR = (mos_parport->shadowDCR & (~mask)) ^ val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) write_mos_reg(mos_parport->serial, dummy, MOS7720_DCR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) mos_parport->shadowDCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) dcr = mos_parport->shadowDCR & 0x0f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) parport_epilogue(pp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) return dcr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) static unsigned char parport_mos7715_read_status(struct parport *pp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) unsigned char status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) struct mos7715_parport *mos_parport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) spin_lock(&release_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) mos_parport = pp->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) if (unlikely(mos_parport == NULL)) { /* release called */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) spin_unlock(&release_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) status = atomic_read(&mos_parport->shadowDSR) & 0xf8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) spin_unlock(&release_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) static void parport_mos7715_enable_irq(struct parport *pp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) static void parport_mos7715_disable_irq(struct parport *pp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) static void parport_mos7715_data_forward(struct parport *pp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) struct mos7715_parport *mos_parport = pp->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) if (parport_prologue(pp) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) mos7715_change_mode(mos_parport, PS2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) mos_parport->shadowDCR &= ~0x20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) write_mos_reg(mos_parport->serial, dummy, MOS7720_DCR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) mos_parport->shadowDCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) parport_epilogue(pp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) static void parport_mos7715_data_reverse(struct parport *pp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) struct mos7715_parport *mos_parport = pp->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) if (parport_prologue(pp) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) mos7715_change_mode(mos_parport, PS2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) mos_parport->shadowDCR |= 0x20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) write_mos_reg(mos_parport->serial, dummy, MOS7720_DCR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) mos_parport->shadowDCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) parport_epilogue(pp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) static void parport_mos7715_init_state(struct pardevice *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) struct parport_state *s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) s->u.pc.ctr = DCR_INIT_VAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) s->u.pc.ecr = ECR_INIT_VAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) /* N.B. Parport core code requires that this function not block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) static void parport_mos7715_save_state(struct parport *pp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) struct parport_state *s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) struct mos7715_parport *mos_parport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) spin_lock(&release_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) mos_parport = pp->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) if (unlikely(mos_parport == NULL)) { /* release called */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) spin_unlock(&release_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) s->u.pc.ctr = mos_parport->shadowDCR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) s->u.pc.ecr = mos_parport->shadowECR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) spin_unlock(&release_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) /* N.B. Parport core code requires that this function not block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) static void parport_mos7715_restore_state(struct parport *pp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) struct parport_state *s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) struct mos7715_parport *mos_parport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) spin_lock(&release_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) mos_parport = pp->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) if (unlikely(mos_parport == NULL)) { /* release called */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) spin_unlock(&release_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) mos_parport->shadowDCR = s->u.pc.ctr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) mos_parport->shadowECR = s->u.pc.ecr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) write_parport_reg_nonblock(mos_parport, MOS7720_DCR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) mos_parport->shadowDCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) write_parport_reg_nonblock(mos_parport, MOS7720_ECR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) mos_parport->shadowECR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) spin_unlock(&release_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) static size_t parport_mos7715_write_compat(struct parport *pp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) const void *buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) size_t len, int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) struct mos7715_parport *mos_parport = pp->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) int actual_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) if (parport_prologue(pp) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) mos7715_change_mode(mos_parport, PPF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) retval = usb_bulk_msg(mos_parport->serial->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) usb_sndbulkpipe(mos_parport->serial->dev, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) (void *)buffer, len, &actual_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) MOS_WDR_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) parport_epilogue(pp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) if (retval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) dev_err(&mos_parport->serial->dev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) "mos7720: usb_bulk_msg() failed: %d\n", retval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) return actual_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) static struct parport_operations parport_mos7715_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) .write_data = parport_mos7715_write_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) .read_data = parport_mos7715_read_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) .write_control = parport_mos7715_write_control,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) .read_control = parport_mos7715_read_control,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) .frob_control = parport_mos7715_frob_control,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) .read_status = parport_mos7715_read_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) .enable_irq = parport_mos7715_enable_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) .disable_irq = parport_mos7715_disable_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) .data_forward = parport_mos7715_data_forward,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) .data_reverse = parport_mos7715_data_reverse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) .init_state = parport_mos7715_init_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) .save_state = parport_mos7715_save_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) .restore_state = parport_mos7715_restore_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) .compat_write_data = parport_mos7715_write_compat,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) .nibble_read_data = parport_ieee1284_read_nibble,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) .byte_read_data = parport_ieee1284_read_byte,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) * Allocate and initialize parallel port control struct, initialize
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) * the parallel port hardware device, and register with the parport subsystem.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) static int mos7715_parport_init(struct usb_serial *serial)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) struct mos7715_parport *mos_parport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) /* allocate and initialize parallel port control struct */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) mos_parport = kzalloc(sizeof(struct mos7715_parport), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) if (!mos_parport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) mos_parport->msg_pending = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) kref_init(&mos_parport->ref_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) spin_lock_init(&mos_parport->listlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) INIT_LIST_HEAD(&mos_parport->active_urbs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) INIT_LIST_HEAD(&mos_parport->deferred_urbs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) usb_set_serial_data(serial, mos_parport); /* hijack private pointer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) mos_parport->serial = serial;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) tasklet_setup(&mos_parport->urb_tasklet, send_deferred_urbs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) init_completion(&mos_parport->syncmsg_compl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) /* cycle parallel port reset bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) write_mos_reg(mos_parport->serial, dummy, MOS7720_PP_REG, (__u8)0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) write_mos_reg(mos_parport->serial, dummy, MOS7720_PP_REG, (__u8)0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) /* initialize device registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) mos_parport->shadowDCR = DCR_INIT_VAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) write_mos_reg(mos_parport->serial, dummy, MOS7720_DCR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) mos_parport->shadowDCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) mos_parport->shadowECR = ECR_INIT_VAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) write_mos_reg(mos_parport->serial, dummy, MOS7720_ECR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) mos_parport->shadowECR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) /* register with parport core */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) mos_parport->pp = parport_register_port(0, PARPORT_IRQ_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) PARPORT_DMA_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) &parport_mos7715_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) if (mos_parport->pp == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) dev_err(&serial->interface->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) "Could not register parport\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) kref_put(&mos_parport->ref_count, destroy_mos_parport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) mos_parport->pp->private_data = mos_parport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) mos_parport->pp->modes = PARPORT_MODE_COMPAT | PARPORT_MODE_PCSPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) mos_parport->pp->dev = &serial->interface->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) parport_announce_port(mos_parport->pp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) #endif /* CONFIG_USB_SERIAL_MOS7715_PARPORT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) * mos7720_interrupt_callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) * this is the callback function for when we have received data on the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) * interrupt endpoint.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) static void mos7720_interrupt_callback(struct urb *urb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) int length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) int status = urb->status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) struct device *dev = &urb->dev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) __u8 *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) __u8 sp1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) __u8 sp2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) switch (status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) /* success */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) case -ECONNRESET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) case -ENOENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) case -ESHUTDOWN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) /* this urb is terminated, clean up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) dev_dbg(dev, "%s - urb shutting down with status: %d\n", __func__, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) dev_dbg(dev, "%s - nonzero urb status received: %d\n", __func__, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) length = urb->actual_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) data = urb->transfer_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) /* Moschip get 4 bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) * Byte 1 IIR Port 1 (port.number is 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) * Byte 2 IIR Port 2 (port.number is 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) * Byte 3 --------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) * Byte 4 FIFO status for both */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) /* the above description is inverted
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) * oneukum 2007-03-14 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) if (unlikely(length != 4)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) dev_dbg(dev, "Wrong data !!!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) sp1 = data[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) sp2 = data[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) if ((sp1 | sp2) & 0x01) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) /* No Interrupt Pending in both the ports */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) dev_dbg(dev, "No Interrupt !!!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) switch (sp1 & 0x0f) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) case SERIAL_IIR_RLS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) dev_dbg(dev, "Serial Port 1: Receiver status error or address bit detected in 9-bit mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) case SERIAL_IIR_CTI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) dev_dbg(dev, "Serial Port 1: Receiver time out\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) case SERIAL_IIR_MS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) /* dev_dbg(dev, "Serial Port 1: Modem status change\n"); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) switch (sp2 & 0x0f) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) case SERIAL_IIR_RLS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) dev_dbg(dev, "Serial Port 2: Receiver status error or address bit detected in 9-bit mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) case SERIAL_IIR_CTI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) dev_dbg(dev, "Serial Port 2: Receiver time out\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) case SERIAL_IIR_MS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) /* dev_dbg(dev, "Serial Port 2: Modem status change\n"); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) result = usb_submit_urb(urb, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) if (result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) dev_err(dev, "%s - Error %d submitting control urb\n", __func__, result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) * mos7715_interrupt_callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) * this is the 7715's callback function for when we have received data on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) * the interrupt endpoint.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) static void mos7715_interrupt_callback(struct urb *urb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) int length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) int status = urb->status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) struct device *dev = &urb->dev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) __u8 *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) __u8 iir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) switch (status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) /* success */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) case -ECONNRESET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) case -ENOENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) case -ESHUTDOWN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) case -ENODEV:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) /* this urb is terminated, clean up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) dev_dbg(dev, "%s - urb shutting down with status: %d\n", __func__, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) dev_dbg(dev, "%s - nonzero urb status received: %d\n", __func__, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) length = urb->actual_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) data = urb->transfer_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) /* Structure of data from 7715 device:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) * Byte 1: IIR serial Port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) * Byte 2: unused
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) * Byte 2: DSR parallel port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) * Byte 4: FIFO status for both */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) if (unlikely(length != 4)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) dev_dbg(dev, "Wrong data !!!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) iir = data[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) if (!(iir & 0x01)) { /* serial port interrupt pending */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) switch (iir & 0x0f) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) case SERIAL_IIR_RLS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) dev_dbg(dev, "Serial Port: Receiver status error or address bit detected in 9-bit mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) case SERIAL_IIR_CTI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) dev_dbg(dev, "Serial Port: Receiver time out\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) case SERIAL_IIR_MS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) /* dev_dbg(dev, "Serial Port: Modem status change\n"); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) #ifdef CONFIG_USB_SERIAL_MOS7715_PARPORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) { /* update local copy of DSR reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) struct usb_serial_port *port = urb->context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) struct mos7715_parport *mos_parport = port->serial->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) if (unlikely(mos_parport == NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) atomic_set(&mos_parport->shadowDSR, data[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) result = usb_submit_urb(urb, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) if (result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) dev_err(dev, "%s - Error %d submitting control urb\n", __func__, result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) * mos7720_bulk_in_callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) * this is the callback function for when we have received data on the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) * bulk in endpoint.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) static void mos7720_bulk_in_callback(struct urb *urb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) unsigned char *data ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) struct usb_serial_port *port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) int status = urb->status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) if (status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) dev_dbg(&urb->dev->dev, "nonzero read bulk status received: %d\n", status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) port = urb->context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) dev_dbg(&port->dev, "Entering...%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) data = urb->transfer_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) if (urb->actual_length) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) tty_insert_flip_string(&port->port, data, urb->actual_length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) tty_flip_buffer_push(&port->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) if (port->read_urb->status != -EINPROGRESS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) retval = usb_submit_urb(port->read_urb, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) if (retval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) dev_dbg(&port->dev, "usb_submit_urb(read bulk) failed, retval = %d\n", retval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) * mos7720_bulk_out_data_callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) * this is the callback function for when we have finished sending serial
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) * data on the bulk out endpoint.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) static void mos7720_bulk_out_data_callback(struct urb *urb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) struct moschip_port *mos7720_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) int status = urb->status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) if (status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) dev_dbg(&urb->dev->dev, "nonzero write bulk status received:%d\n", status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) mos7720_port = urb->context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) if (!mos7720_port) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) dev_dbg(&urb->dev->dev, "NULL mos7720_port pointer\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) return ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) if (mos7720_port->open)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) tty_port_tty_wakeup(&mos7720_port->port->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) static int mos77xx_calc_num_ports(struct usb_serial *serial,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) struct usb_serial_endpoints *epds)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) u16 product = le16_to_cpu(serial->dev->descriptor.idProduct);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) if (product == MOSCHIP_DEVICE_ID_7715) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) * The 7715 uses the first bulk in/out endpoint pair for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) * parallel port, and the second for the serial port. We swap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) * the endpoint descriptors here so that the the first and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) * only registered port structure uses the serial-port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) * endpoints.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) swap(epds->bulk_in[0], epds->bulk_in[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) swap(epds->bulk_out[0], epds->bulk_out[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) return 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) static int mos7720_open(struct tty_struct *tty, struct usb_serial_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) struct usb_serial *serial;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) struct urb *urb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) struct moschip_port *mos7720_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) int response;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) int port_number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) __u8 data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) int allocated_urbs = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) int j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) serial = port->serial;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) mos7720_port = usb_get_serial_port_data(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) if (mos7720_port == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) usb_clear_halt(serial->dev, port->write_urb->pipe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) usb_clear_halt(serial->dev, port->read_urb->pipe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) /* Initialising the write urb pool */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) for (j = 0; j < NUM_URBS; ++j) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) urb = usb_alloc_urb(0, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) mos7720_port->write_urb_pool[j] = urb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) if (!urb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) if (!urb->transfer_buffer) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) usb_free_urb(mos7720_port->write_urb_pool[j]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) mos7720_port->write_urb_pool[j] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) allocated_urbs++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) if (!allocated_urbs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) /* Initialize MCS7720 -- Write Init values to corresponding Registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) * Register Index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) * 0 : MOS7720_THR/MOS7720_RHR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) * 1 : MOS7720_IER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) * 2 : MOS7720_FCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) * 3 : MOS7720_LCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) * 4 : MOS7720_MCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) * 5 : MOS7720_LSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) * 6 : MOS7720_MSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) * 7 : MOS7720_SPR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) * 0x08 : SP1/2 Control Reg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) port_number = port->port_number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) read_mos_reg(serial, port_number, MOS7720_LSR, &data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) dev_dbg(&port->dev, "SS::%p LSR:%x\n", mos7720_port, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) write_mos_reg(serial, dummy, MOS7720_SP1_REG, 0x02);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) write_mos_reg(serial, dummy, MOS7720_SP2_REG, 0x02);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) write_mos_reg(serial, port_number, MOS7720_IER, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) write_mos_reg(serial, port_number, MOS7720_FCR, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) write_mos_reg(serial, port_number, MOS7720_FCR, 0xcf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) mos7720_port->shadowLCR = 0x03;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) write_mos_reg(serial, port_number, MOS7720_LCR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) mos7720_port->shadowLCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) mos7720_port->shadowMCR = 0x0b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) write_mos_reg(serial, port_number, MOS7720_MCR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) mos7720_port->shadowMCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) write_mos_reg(serial, port_number, MOS7720_SP_CONTROL_REG, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) read_mos_reg(serial, dummy, MOS7720_SP_CONTROL_REG, &data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) data = data | (port->port_number + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) write_mos_reg(serial, dummy, MOS7720_SP_CONTROL_REG, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) mos7720_port->shadowLCR = 0x83;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) write_mos_reg(serial, port_number, MOS7720_LCR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) mos7720_port->shadowLCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) write_mos_reg(serial, port_number, MOS7720_THR, 0x0c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) write_mos_reg(serial, port_number, MOS7720_IER, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) mos7720_port->shadowLCR = 0x03;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) write_mos_reg(serial, port_number, MOS7720_LCR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) mos7720_port->shadowLCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) write_mos_reg(serial, port_number, MOS7720_IER, 0x0c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) response = usb_submit_urb(port->read_urb, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) if (response)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) dev_err(&port->dev, "%s - Error %d submitting read urb\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) __func__, response);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) /* initialize our port settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) mos7720_port->shadowMCR = UART_MCR_OUT2; /* Must set to enable ints! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) /* send a open port command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) mos7720_port->open = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) * mos7720_chars_in_buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) * this function is called by the tty driver when it wants to know how many
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) * bytes of data we currently have outstanding in the port (data that has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) * been written, but hasn't made it out the port yet)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) * If successful, we return the number of bytes left to be written in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) * system,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) * Otherwise we return a negative error number.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) static int mos7720_chars_in_buffer(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) struct usb_serial_port *port = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) int chars = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) struct moschip_port *mos7720_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) mos7720_port = usb_get_serial_port_data(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) if (mos7720_port == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) for (i = 0; i < NUM_URBS; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) if (mos7720_port->write_urb_pool[i] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) mos7720_port->write_urb_pool[i]->status == -EINPROGRESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) chars += URB_TRANSFER_BUFFER_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) dev_dbg(&port->dev, "%s - returns %d\n", __func__, chars);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) return chars;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) static void mos7720_close(struct usb_serial_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) struct usb_serial *serial;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) struct moschip_port *mos7720_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) int j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) serial = port->serial;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) mos7720_port = usb_get_serial_port_data(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) if (mos7720_port == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) for (j = 0; j < NUM_URBS; ++j)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) usb_kill_urb(mos7720_port->write_urb_pool[j]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) /* Freeing Write URBs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) for (j = 0; j < NUM_URBS; ++j) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) if (mos7720_port->write_urb_pool[j]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) kfree(mos7720_port->write_urb_pool[j]->transfer_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) usb_free_urb(mos7720_port->write_urb_pool[j]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) /* While closing port, shutdown all bulk read, write *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) * and interrupt read if they exists, otherwise nop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) usb_kill_urb(port->write_urb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) usb_kill_urb(port->read_urb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) write_mos_reg(serial, port->port_number, MOS7720_MCR, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) write_mos_reg(serial, port->port_number, MOS7720_IER, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) mos7720_port->open = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) static void mos7720_break(struct tty_struct *tty, int break_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) struct usb_serial_port *port = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) unsigned char data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) struct usb_serial *serial;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) struct moschip_port *mos7720_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) serial = port->serial;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) mos7720_port = usb_get_serial_port_data(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) if (mos7720_port == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) if (break_state == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) data = mos7720_port->shadowLCR | UART_LCR_SBC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) data = mos7720_port->shadowLCR & ~UART_LCR_SBC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) mos7720_port->shadowLCR = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) write_mos_reg(serial, port->port_number, MOS7720_LCR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) mos7720_port->shadowLCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) * mos7720_write_room
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) * this function is called by the tty driver when it wants to know how many
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) * bytes of data we can accept for a specific port.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) * If successful, we return the amount of room that we have for this port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) * Otherwise we return a negative error number.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) static int mos7720_write_room(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) struct usb_serial_port *port = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) struct moschip_port *mos7720_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) int room = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) mos7720_port = usb_get_serial_port_data(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) if (mos7720_port == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) /* FIXME: Locking */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) for (i = 0; i < NUM_URBS; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) if (mos7720_port->write_urb_pool[i] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) mos7720_port->write_urb_pool[i]->status != -EINPROGRESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) room += URB_TRANSFER_BUFFER_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) dev_dbg(&port->dev, "%s - returns %d\n", __func__, room);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) return room;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) static int mos7720_write(struct tty_struct *tty, struct usb_serial_port *port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) const unsigned char *data, int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) int bytes_sent = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) int transfer_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) struct moschip_port *mos7720_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) struct usb_serial *serial;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) struct urb *urb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) const unsigned char *current_position = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) serial = port->serial;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) mos7720_port = usb_get_serial_port_data(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) if (mos7720_port == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) /* try to find a free urb in the list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) urb = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) for (i = 0; i < NUM_URBS; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) if (mos7720_port->write_urb_pool[i] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) mos7720_port->write_urb_pool[i]->status != -EINPROGRESS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) urb = mos7720_port->write_urb_pool[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) dev_dbg(&port->dev, "URB:%d\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) if (urb == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) dev_dbg(&port->dev, "%s - no more free urbs\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) if (urb->transfer_buffer == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) if (!urb->transfer_buffer) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) bytes_sent = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) transfer_size = min(count, URB_TRANSFER_BUFFER_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) memcpy(urb->transfer_buffer, current_position, transfer_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) usb_serial_debug_data(&port->dev, __func__, transfer_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) urb->transfer_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) /* fill urb with data and submit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) usb_fill_bulk_urb(urb, serial->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) usb_sndbulkpipe(serial->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) port->bulk_out_endpointAddress),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) urb->transfer_buffer, transfer_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) mos7720_bulk_out_data_callback, mos7720_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) /* send it down the pipe */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) status = usb_submit_urb(urb, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) if (status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) dev_err_console(port, "%s - usb_submit_urb(write bulk) failed "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) "with status = %d\n", __func__, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) bytes_sent = status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) bytes_sent = transfer_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) return bytes_sent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) static void mos7720_throttle(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) struct usb_serial_port *port = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) struct moschip_port *mos7720_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) mos7720_port = usb_get_serial_port_data(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) if (mos7720_port == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) if (!mos7720_port->open) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) dev_dbg(&port->dev, "%s - port not opened\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) /* if we are implementing XON/XOFF, send the stop character */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) if (I_IXOFF(tty)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) unsigned char stop_char = STOP_CHAR(tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) status = mos7720_write(tty, port, &stop_char, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) if (status <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) /* if we are implementing RTS/CTS, toggle that line */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) if (C_CRTSCTS(tty)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) mos7720_port->shadowMCR &= ~UART_MCR_RTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) write_mos_reg(port->serial, port->port_number, MOS7720_MCR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) mos7720_port->shadowMCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) static void mos7720_unthrottle(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) struct usb_serial_port *port = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) struct moschip_port *mos7720_port = usb_get_serial_port_data(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) if (mos7720_port == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) if (!mos7720_port->open) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) dev_dbg(&port->dev, "%s - port not opened\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) /* if we are implementing XON/XOFF, send the start character */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) if (I_IXOFF(tty)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) unsigned char start_char = START_CHAR(tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) status = mos7720_write(tty, port, &start_char, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) if (status <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) /* if we are implementing RTS/CTS, toggle that line */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) if (C_CRTSCTS(tty)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) mos7720_port->shadowMCR |= UART_MCR_RTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) write_mos_reg(port->serial, port->port_number, MOS7720_MCR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) mos7720_port->shadowMCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) /* FIXME: this function does not work */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) static int set_higher_rates(struct moschip_port *mos7720_port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) unsigned int baud)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) struct usb_serial_port *port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) struct usb_serial *serial;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) int port_number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) enum mos_regs sp_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) if (mos7720_port == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) port = mos7720_port->port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) serial = port->serial;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) /***********************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) * Init Sequence for higher rates
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) ***********************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) dev_dbg(&port->dev, "Sending Setting Commands ..........\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) port_number = port->port_number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) write_mos_reg(serial, port_number, MOS7720_IER, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) write_mos_reg(serial, port_number, MOS7720_FCR, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) write_mos_reg(serial, port_number, MOS7720_FCR, 0xcf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) mos7720_port->shadowMCR = 0x0b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) write_mos_reg(serial, port_number, MOS7720_MCR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) mos7720_port->shadowMCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) write_mos_reg(serial, dummy, MOS7720_SP_CONTROL_REG, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) /***********************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) * Set for higher rates *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) ***********************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) /* writing baud rate verbatum into uart clock field clearly not right */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) if (port_number == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) sp_reg = MOS7720_SP1_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) sp_reg = MOS7720_SP2_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) write_mos_reg(serial, dummy, sp_reg, baud * 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) write_mos_reg(serial, dummy, MOS7720_SP_CONTROL_REG, 0x03);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) mos7720_port->shadowMCR = 0x2b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) write_mos_reg(serial, port_number, MOS7720_MCR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) mos7720_port->shadowMCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) /***********************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) * Set DLL/DLM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) ***********************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) mos7720_port->shadowLCR = mos7720_port->shadowLCR | UART_LCR_DLAB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) write_mos_reg(serial, port_number, MOS7720_LCR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) mos7720_port->shadowLCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) write_mos_reg(serial, port_number, MOS7720_DLL, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) write_mos_reg(serial, port_number, MOS7720_DLM, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) mos7720_port->shadowLCR = mos7720_port->shadowLCR & ~UART_LCR_DLAB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) write_mos_reg(serial, port_number, MOS7720_LCR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) mos7720_port->shadowLCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) /* baud rate information */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) struct divisor_table_entry {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) __u32 baudrate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) __u16 divisor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) /* Define table of divisors for moschip 7720 hardware *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) * These assume a 3.6864MHz crystal, the standard /16, and *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) * MCR.7 = 0. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) static const struct divisor_table_entry divisor_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) { 50, 2304},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) { 110, 1047}, /* 2094.545455 => 230450 => .0217 % over */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) { 134, 857}, /* 1713.011152 => 230398.5 => .00065% under */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) { 150, 768},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) { 300, 384},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) { 600, 192},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) { 1200, 96},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) { 1800, 64},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) { 2400, 48},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) { 4800, 24},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) { 7200, 16},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) { 9600, 12},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) { 19200, 6},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) { 38400, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) { 57600, 2},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) { 115200, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) /*****************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) * calc_baud_rate_divisor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) * this function calculates the proper baud rate divisor for the specified
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) * baud rate.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) *****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) static int calc_baud_rate_divisor(struct usb_serial_port *port, int baudrate, int *divisor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) __u16 custom;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) __u16 round1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) __u16 round;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) dev_dbg(&port->dev, "%s - %d\n", __func__, baudrate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) for (i = 0; i < ARRAY_SIZE(divisor_table); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) if (divisor_table[i].baudrate == baudrate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) *divisor = divisor_table[i].divisor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) /* After trying for all the standard baud rates *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) * Try calculating the divisor for this baud rate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) if (baudrate > 75 && baudrate < 230400) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) /* get the divisor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) custom = (__u16)(230400L / baudrate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) /* Check for round off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) round1 = (__u16)(2304000L / baudrate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) round = (__u16)(round1 - (custom * 10));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) if (round > 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) custom++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) *divisor = custom;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) dev_dbg(&port->dev, "Baud %d = %d\n", baudrate, custom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) dev_dbg(&port->dev, "Baud calculation Failed...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) * send_cmd_write_baud_rate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) * this function sends the proper command to change the baud rate of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) * specified port.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) static int send_cmd_write_baud_rate(struct moschip_port *mos7720_port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) int baudrate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) struct usb_serial_port *port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) struct usb_serial *serial;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) int divisor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) unsigned char number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) if (mos7720_port == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) port = mos7720_port->port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) serial = port->serial;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) number = port->port_number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) dev_dbg(&port->dev, "%s - baud = %d\n", __func__, baudrate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) /* Calculate the Divisor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) status = calc_baud_rate_divisor(port, baudrate, &divisor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) if (status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) dev_err(&port->dev, "%s - bad baud rate\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) /* Enable access to divisor latch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) mos7720_port->shadowLCR = mos7720_port->shadowLCR | UART_LCR_DLAB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) write_mos_reg(serial, number, MOS7720_LCR, mos7720_port->shadowLCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) /* Write the divisor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) write_mos_reg(serial, number, MOS7720_DLL, (__u8)(divisor & 0xff));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) write_mos_reg(serial, number, MOS7720_DLM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) (__u8)((divisor & 0xff00) >> 8));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) /* Disable access to divisor latch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) mos7720_port->shadowLCR = mos7720_port->shadowLCR & ~UART_LCR_DLAB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) write_mos_reg(serial, number, MOS7720_LCR, mos7720_port->shadowLCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) * change_port_settings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) * This routine is called to set the UART on the device to match
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) * the specified new settings.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) static void change_port_settings(struct tty_struct *tty,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) struct moschip_port *mos7720_port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) struct ktermios *old_termios)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) struct usb_serial_port *port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) struct usb_serial *serial;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) int baud;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) unsigned cflag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) __u8 lData;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) __u8 lParity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) __u8 lStop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) int port_number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) if (mos7720_port == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) return ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) port = mos7720_port->port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) serial = port->serial;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) port_number = port->port_number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) if (!mos7720_port->open) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) dev_dbg(&port->dev, "%s - port not opened\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) lData = UART_LCR_WLEN8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) lStop = 0x00; /* 1 stop bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) lParity = 0x00; /* No parity */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) cflag = tty->termios.c_cflag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) /* Change the number of bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) switch (cflag & CSIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) case CS5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) lData = UART_LCR_WLEN5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) case CS6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) lData = UART_LCR_WLEN6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) case CS7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) lData = UART_LCR_WLEN7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) case CS8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) lData = UART_LCR_WLEN8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) /* Change the Parity bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) if (cflag & PARENB) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) if (cflag & PARODD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) lParity = UART_LCR_PARITY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) dev_dbg(&port->dev, "%s - parity = odd\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) lParity = (UART_LCR_EPAR | UART_LCR_PARITY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) dev_dbg(&port->dev, "%s - parity = even\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) dev_dbg(&port->dev, "%s - parity = none\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) if (cflag & CMSPAR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) lParity = lParity | 0x20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) /* Change the Stop bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) if (cflag & CSTOPB) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) lStop = UART_LCR_STOP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) dev_dbg(&port->dev, "%s - stop bits = 2\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) lStop = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) dev_dbg(&port->dev, "%s - stop bits = 1\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) #define LCR_BITS_MASK 0x03 /* Mask for bits/char field */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) #define LCR_STOP_MASK 0x04 /* Mask for stop bits field */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) #define LCR_PAR_MASK 0x38 /* Mask for parity field */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) /* Update the LCR with the correct value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) mos7720_port->shadowLCR &=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) ~(LCR_BITS_MASK | LCR_STOP_MASK | LCR_PAR_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) mos7720_port->shadowLCR |= (lData | lParity | lStop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) /* Disable Interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) write_mos_reg(serial, port_number, MOS7720_IER, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) write_mos_reg(serial, port_number, MOS7720_FCR, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) write_mos_reg(serial, port_number, MOS7720_FCR, 0xcf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) /* Send the updated LCR value to the mos7720 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) write_mos_reg(serial, port_number, MOS7720_LCR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) mos7720_port->shadowLCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) mos7720_port->shadowMCR = 0x0b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) write_mos_reg(serial, port_number, MOS7720_MCR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) mos7720_port->shadowMCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) /* set up the MCR register and send it to the mos7720 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) mos7720_port->shadowMCR = UART_MCR_OUT2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) if (cflag & CBAUD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) mos7720_port->shadowMCR |= (UART_MCR_DTR | UART_MCR_RTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) if (cflag & CRTSCTS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) mos7720_port->shadowMCR |= (UART_MCR_XONANY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) /* To set hardware flow control to the specified *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) * serial port, in SP1/2_CONTROL_REG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) if (port_number)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) write_mos_reg(serial, dummy, MOS7720_SP_CONTROL_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) write_mos_reg(serial, dummy, MOS7720_SP_CONTROL_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) 0x02);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) mos7720_port->shadowMCR &= ~(UART_MCR_XONANY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) write_mos_reg(serial, port_number, MOS7720_MCR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) mos7720_port->shadowMCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) /* Determine divisor based on baud rate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) baud = tty_get_baud_rate(tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) if (!baud) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) /* pick a default, any default... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) dev_dbg(&port->dev, "Picked default baud...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) baud = 9600;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) if (baud >= 230400) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) set_higher_rates(mos7720_port, baud);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) /* Enable Interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) write_mos_reg(serial, port_number, MOS7720_IER, 0x0c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) dev_dbg(&port->dev, "%s - baud rate = %d\n", __func__, baud);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) status = send_cmd_write_baud_rate(mos7720_port, baud);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) /* FIXME: needs to write actual resulting baud back not just
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) blindly do so */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) if (cflag & CBAUD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) tty_encode_baud_rate(tty, baud, baud);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) /* Enable Interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) write_mos_reg(serial, port_number, MOS7720_IER, 0x0c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) if (port->read_urb->status != -EINPROGRESS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) status = usb_submit_urb(port->read_urb, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) dev_dbg(&port->dev, "usb_submit_urb(read bulk) failed, status = %d\n", status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) * mos7720_set_termios
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) * this function is called by the tty driver when it wants to change the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) * termios structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) static void mos7720_set_termios(struct tty_struct *tty,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) struct usb_serial_port *port, struct ktermios *old_termios)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) struct moschip_port *mos7720_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) mos7720_port = usb_get_serial_port_data(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) if (mos7720_port == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) if (!mos7720_port->open) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) dev_dbg(&port->dev, "%s - port not opened\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) /* change the port settings to the new ones specified */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) change_port_settings(tty, mos7720_port, old_termios);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) if (port->read_urb->status != -EINPROGRESS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) status = usb_submit_urb(port->read_urb, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) dev_dbg(&port->dev, "usb_submit_urb(read bulk) failed, status = %d\n", status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) * get_lsr_info - get line status register info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) * Purpose: Let user call ioctl() to get info when the UART physically
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) * is emptied. On bus types like RS485, the transmitter must
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) * release the bus after transmitting. This must be done when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) * the transmit shift register is empty, not be done when the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) * transmit holding register is empty. This functionality
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) * allows an RS485 driver to be written in user space.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) static int get_lsr_info(struct tty_struct *tty,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) struct moschip_port *mos7720_port, unsigned int __user *value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) struct usb_serial_port *port = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) unsigned int result = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) unsigned char data = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) int port_number = port->port_number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) count = mos7720_chars_in_buffer(tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) if (count == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) read_mos_reg(port->serial, port_number, MOS7720_LSR, &data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) if ((data & (UART_LSR_TEMT | UART_LSR_THRE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) == (UART_LSR_TEMT | UART_LSR_THRE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) dev_dbg(&port->dev, "%s -- Empty\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) result = TIOCSER_TEMT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) if (copy_to_user(value, &result, sizeof(int)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) static int mos7720_tiocmget(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) struct usb_serial_port *port = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) struct moschip_port *mos7720_port = usb_get_serial_port_data(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) unsigned int result = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) unsigned int mcr ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) unsigned int msr ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) mcr = mos7720_port->shadowMCR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) msr = mos7720_port->shadowMSR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) result = ((mcr & UART_MCR_DTR) ? TIOCM_DTR : 0) /* 0x002 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) | ((mcr & UART_MCR_RTS) ? TIOCM_RTS : 0) /* 0x004 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) | ((msr & UART_MSR_CTS) ? TIOCM_CTS : 0) /* 0x020 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) | ((msr & UART_MSR_DCD) ? TIOCM_CAR : 0) /* 0x040 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) | ((msr & UART_MSR_RI) ? TIOCM_RI : 0) /* 0x080 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) | ((msr & UART_MSR_DSR) ? TIOCM_DSR : 0); /* 0x100 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) static int mos7720_tiocmset(struct tty_struct *tty,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) unsigned int set, unsigned int clear)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) struct usb_serial_port *port = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) struct moschip_port *mos7720_port = usb_get_serial_port_data(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) unsigned int mcr ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) mcr = mos7720_port->shadowMCR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) if (set & TIOCM_RTS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) mcr |= UART_MCR_RTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) if (set & TIOCM_DTR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) mcr |= UART_MCR_DTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) if (set & TIOCM_LOOP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) mcr |= UART_MCR_LOOP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) if (clear & TIOCM_RTS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) mcr &= ~UART_MCR_RTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) if (clear & TIOCM_DTR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) mcr &= ~UART_MCR_DTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) if (clear & TIOCM_LOOP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) mcr &= ~UART_MCR_LOOP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) mos7720_port->shadowMCR = mcr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) write_mos_reg(port->serial, port->port_number, MOS7720_MCR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) mos7720_port->shadowMCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) static int get_serial_info(struct tty_struct *tty,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) struct serial_struct *ss)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) struct usb_serial_port *port = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) struct moschip_port *mos7720_port = usb_get_serial_port_data(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) ss->type = PORT_16550A;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) ss->line = mos7720_port->port->minor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) ss->port = mos7720_port->port->port_number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) ss->irq = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) ss->xmit_fifo_size = NUM_URBS * URB_TRANSFER_BUFFER_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) ss->baud_base = 9600;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) ss->close_delay = 5*HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) ss->closing_wait = 30*HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) static int mos7720_ioctl(struct tty_struct *tty,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) unsigned int cmd, unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) struct usb_serial_port *port = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) struct moschip_port *mos7720_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) mos7720_port = usb_get_serial_port_data(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) if (mos7720_port == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) case TIOCSERGETLSR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) dev_dbg(&port->dev, "%s TIOCSERGETLSR\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) return get_lsr_info(tty, mos7720_port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) (unsigned int __user *)arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) return -ENOIOCTLCMD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) static int mos7720_startup(struct usb_serial *serial)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) struct usb_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) char data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) u16 product;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) int ret_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) product = le16_to_cpu(serial->dev->descriptor.idProduct);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) dev = serial->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) if (product == MOSCHIP_DEVICE_ID_7715) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) struct urb *urb = serial->port[0]->interrupt_in_urb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) urb->complete = mos7715_interrupt_callback;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) #ifdef CONFIG_USB_SERIAL_MOS7715_PARPORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) ret_val = mos7715_parport_init(serial);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) if (ret_val < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) return ret_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) /* start the interrupt urb */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) ret_val = usb_submit_urb(serial->port[0]->interrupt_in_urb, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) if (ret_val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) dev_err(&dev->dev, "failed to submit interrupt urb: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) ret_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) /* LSR For Port 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) read_mos_reg(serial, 0, MOS7720_LSR, &data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) dev_dbg(&dev->dev, "LSR:%x\n", data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) static void mos7720_release(struct usb_serial *serial)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) usb_kill_urb(serial->port[0]->interrupt_in_urb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) #ifdef CONFIG_USB_SERIAL_MOS7715_PARPORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) /* close the parallel port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) if (le16_to_cpu(serial->dev->descriptor.idProduct)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) == MOSCHIP_DEVICE_ID_7715) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) struct urbtracker *urbtrack;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) struct mos7715_parport *mos_parport =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) usb_get_serial_data(serial);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) /* prevent NULL ptr dereference in port callbacks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) spin_lock(&release_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) mos_parport->pp->private_data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) spin_unlock(&release_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) /* wait for synchronous usb calls to return */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) if (mos_parport->msg_pending)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) wait_for_completion_timeout(&mos_parport->syncmsg_compl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) msecs_to_jiffies(MOS_WDR_TIMEOUT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) parport_remove_port(mos_parport->pp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) usb_set_serial_data(serial, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) mos_parport->serial = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) /* if tasklet currently scheduled, wait for it to complete */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) tasklet_kill(&mos_parport->urb_tasklet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) /* unlink any urbs sent by the tasklet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) spin_lock_irqsave(&mos_parport->listlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) list_for_each_entry(urbtrack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) &mos_parport->active_urbs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) urblist_entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) usb_unlink_urb(urbtrack->urb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) spin_unlock_irqrestore(&mos_parport->listlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) parport_del_port(mos_parport->pp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) kref_put(&mos_parport->ref_count, destroy_mos_parport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) static int mos7720_port_probe(struct usb_serial_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) struct moschip_port *mos7720_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) mos7720_port = kzalloc(sizeof(*mos7720_port), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) if (!mos7720_port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) mos7720_port->port = port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) usb_set_serial_port_data(port, mos7720_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) static int mos7720_port_remove(struct usb_serial_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) struct moschip_port *mos7720_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) mos7720_port = usb_get_serial_port_data(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) kfree(mos7720_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) static struct usb_serial_driver moschip7720_2port_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) .name = "moschip7720",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) .description = "Moschip 2 port adapter",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) .id_table = id_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) .num_bulk_in = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) .num_bulk_out = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) .num_interrupt_in = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) .calc_num_ports = mos77xx_calc_num_ports,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) .open = mos7720_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) .close = mos7720_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) .throttle = mos7720_throttle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) .unthrottle = mos7720_unthrottle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) .attach = mos7720_startup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) .release = mos7720_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) .port_probe = mos7720_port_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) .port_remove = mos7720_port_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) .ioctl = mos7720_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) .tiocmget = mos7720_tiocmget,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) .tiocmset = mos7720_tiocmset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) .get_serial = get_serial_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) .set_termios = mos7720_set_termios,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) .write = mos7720_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) .write_room = mos7720_write_room,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) .chars_in_buffer = mos7720_chars_in_buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) .break_ctl = mos7720_break,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) .read_bulk_callback = mos7720_bulk_in_callback,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) .read_int_callback = mos7720_interrupt_callback,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) static struct usb_serial_driver * const serial_drivers[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) &moschip7720_2port_driver, NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) module_usb_serial_driver(serial_drivers, id_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) MODULE_AUTHOR(DRIVER_AUTHOR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) MODULE_DESCRIPTION(DRIVER_DESC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) MODULE_LICENSE("GPL v2");