Commit aa8698ec authored by Shrirang Bagul's avatar Shrirang Bagul Committed by Kleber Sacilotto de Souza

UBUNTU: SAUCE: xr-usb-serial: Update driver for Exar USB serial ports

BugLink: http://bugs.launchpad.net/bugs/1685133

This patch adds the vendor release version on the Exar USB serial
device. Features include:
1. Fix for RX fail after wake-up from sleep (S3/S4)
2. Removes unnecessary debug messages

Changelog:

Version 1B, 11/6/2015
Fixed Bug: The conditional logic to support kernel 3.9 was
incorrect(line 396 in xr_usb_serial_common.c).

Version 1A, 1/9/2015
This driver will work with any USB UART function in these Exar devices:
	XR21V1410/1412/1414
	XR21B1411
	XR21B1420/1422/1424
	XR22801/802/804

Exar serial devices are typically enuremated as /dev/ttyXRUSB[0-3].
Signed-off-by: default avatarShrirang Bagul <shrirang.bagul@canonical.com>
Acked-by: default avatarColin Ian King <colin.king@canonical.com>
Acked-by: default avatarStefan Bader <stefan.bader@canonical.com>
Signed-off-by: default avatarKleber Sacilotto de Souza <kleber.souza@canonical.com>
parent 07e6b086
Exar USB Serial Driver Exar USB Serial Driver
====================== ======================
Version 1B, 11/6/2015
Fixed Bug: The conditional logic to support kernel 3.9 was incorrect(line 396 in xr_usb_serial_common.c).
Version 1A, 1/9/2015 Version 1A, 1/9/2015
This driver will work with any USB UART function in these Exar devices: This driver will work with any USB UART function in these Exar devices:
......
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
static void *smbios_base = 0;
/** SM-BIOS entry point structure */
struct smbios_entry_point_struct *smbios_entry_point = 0;
/** DMI-BIOS entry point structure */
struct dmibios_entry_point_struct *dmibios_entry_point = 0;
/** SM-BIOS, resp. DMI-BIOS structures base address; starting point */
void *smbios_structures_base = 0;
/** enumeration of SM-BIOS, resp. DMI-BIOS types that do have subtypes */
__u8 smbios_types_with_subtypes[] = { TYPES_WITH_SUBTYPES };
/** contains the SMBIOS Version, e.g. V2.31 */
char smbios_version_string[32];
/** \fn unsigned char smbios_check_entry_point (void * addr)
* \brief checks the entry point structure for correct checksum
* \param addr pointer to the entry point structure
* \return the checksum of the entry point structure, should be '0'
*
* This function checks the entry point structure for correct checksum.
* The checksum is calculated with adding every byte of the structure
* to the checksum byte. The entry point structure is considered correct
* if the checksum byte is 0.
*
* \author Markus Lyra
* \author Thomas Bretthauer
* \date October 2000
*/
unsigned char smbios_check_entry_point (void *addr)
{
unsigned char *i;
unsigned char checksum = 0;
unsigned char length =((struct smbios_entry_point_struct *) addr)->entry_point_length;
/* calculate checksum for entry point structure (should be 0) */
for (i = (unsigned char *) addr; i < (unsigned char *) addr + length; i++)
checksum += *i;
return checksum;
}
struct smbios_entry_point_struct * smbios_find_entry_point (void *base)
{
struct smbios_entry_point_struct *entry_point = 0; /** SM-BIOS entry point */
unsigned int *temp; /** temp. pointer */
/* search for the magic dword - '_SM_ as DWORD formatted - on paragraph boundaries */
for (temp = base;
!entry_point && temp < (unsigned int *) base + BIOS_MAP_LENGTH;
temp += 4)
{
/* found the identifier ? */
if (*temp == SMBIOS_MAGIC_DWORD)
{
/* check if entry point valid (build checksum) */
if (!(smbios_check_entry_point (temp)))
{
entry_point = (struct smbios_entry_point_struct *) temp;
/* fix display of Bios version string */
/* SMBios version is known as 2.1, 2.2, 2.3 and 2.3.1, never as 2.01 (JB) */
SM_BIOS_DEBUG("SM-BIOS V%d.%d entry point found at 0x%x\n",
entry_point->major_version, entry_point->minor_version, (unsigned int) temp);
SM_BIOS_DEBUG("V%d.%d\n", entry_point->major_version, entry_point->minor_version);
}
}
}
return entry_point;
}
struct dmibios_entry_point_struct *dmibios_find_entry_point (void *base)
{
struct dmibios_entry_point_struct *entry_point = 0; /** DMI-BIOS entry point */
unsigned char *temp = 0; /** temp. pointer */
unsigned char biossignature[] = /** '_DMI20_NT_' */
{ 0x5f, 0x44, 0x4d, 0x49, 0x32, 0x30, 0x5f, 0x4e, 0x54, 0x5f };
/* search for the DMI-BIOS signature on character boundary (hm?) */
for (temp = base;
!entry_point &&
temp < (__u8 *) base + BIOS_MAP_LENGTH - sizeof (biossignature) - 32;
temp++)
{
unsigned long *tempdword = (unsigned long *) temp;
/* found the identifier '_DMI' ? (beginning of signature) */
if (*tempdword == DMIBIOS_MAGIC_DWORD)
{
entry_point = (struct dmibios_entry_point_struct *) temp;
SM_BIOS_DEBUG ("DMI-BIOS revision %d entry point at 0x%x\n",
entry_point->revision, (unsigned int) temp);
sprintf(smbios_version_string, "V%d\n", entry_point->revision);
if (memcmp (temp, biossignature, sizeof (biossignature)) == 0)
SM_BIOS_DEBUG ("DMI BIOS successfully identified\n");
}
}
return entry_point;
}
void dump_smbios_hex(unsigned char *p,int len)
{
int i;
SM_BIOS_DEBUG("dump_smbios_hex length:%d\n",len);
for(i=0;i<len;i++)
{
if((p[i] == 0xc0)&&(p[i+1]==0x06))
SM_BIOS_DEBUG("Found 0xc0 at offset:%d 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x \n\t",i,p[i],p[i+1],p[i+2],p[i+3],p[i+4],p[i+5]);
}
}
int smbios_type_has_subtype (unsigned char type)
{
int i;
for (i = 0; i < sizeof (smbios_types_with_subtypes); i++)
if (type == smbios_types_with_subtypes[i])
return 1;
return 0;
}
int smbios_get_struct_length (struct smbios_struct * struct_ptr)
{
/* jump to string list */
unsigned char *ptr = (unsigned char *) struct_ptr + struct_ptr->length;
/* search for the end of string list */
while (ptr[0] != 0x00 || ptr[1] != 0x00)
ptr++;
ptr += 2; /* terminating 0x0000 should be included */
return (int) ptr - (int) struct_ptr;
}
unsigned int smbios_get_readable_name(char *name, struct smbios_struct *struct_ptr)
{
switch(struct_ptr->type)
{
case 0: return sprintf (name, "%s", RD_BIOS);
case 1: return sprintf (name, "%s", RD_SYSTEM);
case 2: return sprintf (name, "%s", RD_BASEBOARD);
case 3: return sprintf (name, "%s", RD_ENCLOSURE);
case 4: return sprintf (name, "%s", RD_PROCESSOR);
case 5: return sprintf (name, "%s", RD_MEMCTRL);
case 6: return sprintf (name, "%s", RD_MEMMOD);
case 7: return sprintf (name, "%s", RD_CACHE);
case 8: return sprintf (name, "%s", RD_PORT);
case 9: return sprintf (name, "%s", RD_SLOT);
case 10: return sprintf (name, "%s", RD_ONBOARD);
case 11: return sprintf (name, "%s", RD_OEMSTRINGS);
case 12: return sprintf (name, "%s", RD_SYSTEMCONFIG);
case 13: return sprintf (name, "%s", RD_BIOSLANG);
case 14: return sprintf (name, "%s", RD_GROUPASSOC);
case 15: return sprintf (name, "%s", RD_EVENTLOG);
case 16: return sprintf (name, "%s", RD_MEMARRAY);
case 17: return sprintf (name, "%s", RD_MEMDEV);
case 18: return sprintf (name, "%s", RD_32MEMERR);
case 19: return sprintf (name, "%s", RD_MEMMAPPEDADR);
case 20: return sprintf (name, "%s", RD_MEMMAPPEDDEV);
case 21: return sprintf (name, "%s", RD_POINTINGDEV);
case 22: return sprintf (name, "%s", RD_BATTERY);
case 23: return sprintf (name, "%s", RD_RESET);
case 24: return sprintf (name, "%s", RD_SECURITY);
case 25: return sprintf (name, "%s", RD_PWRCTRL);
case 26: return sprintf (name, "%s", RD_VOLTAGE);
case 27: return sprintf (name, "%s", RD_COOLINGDEV);
case 28: return sprintf (name, "%s", RD_TEMP);
case 29: return sprintf (name, "%s", RD_CURRENT);
case 30: return sprintf (name, "%s", RD_RMTACCESS);
case 31: return sprintf (name, "%s", RD_BIS);
case 32: return sprintf (name, "%s", RD_BOOT_INFO);
case 33: return sprintf (name, "%s", RD_64MEMERR);
case 34: return sprintf (name, "%s", RD_MANAGDEV);
case 35: return sprintf (name, "%s", RD_MANAGDEVCOMP);
case 36: return sprintf (name, "%s", RD_MANAGDEVTHRESH);
case 37: return sprintf (name, "%s", RD_MEMCHANNEL);
case 38: return sprintf (name, "%s", RD_IPMI);
case 39: return sprintf (name, "%s", RD_PWRSUP);
case 126: return sprintf (name, "%s", RD_INACTIVE);
case 127: return sprintf (name, "%s", RD_EOT);
default: return sprintf (name, "%d", struct_ptr->type);
}
}
unsigned int smbios_get_readable_name_ext(char *name, struct smbios_struct *struct_ptr)
{
return sprintf (name, "%d-%d", struct_ptr->type, struct_ptr->subtype);
}
int smbios_make_dir_entries (void)
{
int i;
unsigned int raw_name_length = 0;
char raw_name[12]; /* e.g. 0.0 for structure type 0 , first instance */
unsigned int readable_name_length = 0;
char readable_name[64]; /* e.g. Bios.0 for structure type 0 , first instance */
struct smbios_struct *struct_ptr = smbios_structures_base;
/*
* for every SMBIOS structure do ...
*/
for (i = 0; i < smbios_entry_point->no_of_structures; i++)
{
memset(raw_name,0,12);
memset(readable_name,0,64);
/*
* generate an unique name for the file: "type[-subtype].count"
*/
if (smbios_type_has_subtype (((struct smbios_struct *) struct_ptr)->type))
{
/* name will contain the raw file name, it equals the structure type (e.g. 1 for Type 1).
* readable_name contains the interpreted file name (e.g. System for Type 1)
*/
raw_name_length = sprintf (raw_name, "%d-%d", struct_ptr->type, struct_ptr->subtype);
readable_name_length = smbios_get_readable_name_ext(readable_name, struct_ptr);
//printk(KERN_INFO "[%s] smbios_type_has_subtype[%d] length:%d\n",raw_name,struct_ptr->type,struct_ptr->length);
}
else
{
raw_name_length = sprintf (raw_name, "%d", struct_ptr->type);
readable_name_length = smbios_get_readable_name(readable_name, struct_ptr);
//printk(KERN_INFO "[%s] smbios_type_has type:%d length:%d\n",readable_name,struct_ptr->type,struct_ptr->length);
}
/*
* go to the next structure
*/
struct_ptr =(struct smbios_struct *) ((unsigned char *) struct_ptr + smbios_get_struct_length(struct_ptr));
}
return 0;
}
int smbios_check_if_have_exar_config(unsigned char *config0,unsigned char *config1)
{
int i;
int result = -1;
unsigned char *p;
smbios_base = ioremap (BIOS_START_ADDRESS, BIOS_MAP_LENGTH);
if(!smbios_base)
{
SM_BIOS_DEBUG ("ioremap() for entry point failed\n");
result = -ENXIO;
return result;
}
//printk(KERN_INFO "ioremap bios base at 0x%p\n", smbios_base);
if (!(smbios_entry_point = smbios_find_entry_point (smbios_base)))
{
SM_BIOS_DEBUG ("SM-BIOS entry point not found\n");
iounmap (smbios_base);
result = -ENXIO;
return result;
}
/*
* for SM-BIOS:
* check if Pointer to DMI structures exist.
* intermediate_string (_DMI_) is not '\0' terminated,
* so strncmp() with sizeof(DMI_STRING) - 1 is needed.
*/
if (smbios_entry_point)
{
if (strncmp((char *) &(smbios_entry_point->intermediate_string),
DMI_STRING, sizeof (DMI_STRING) - 1))
{
SM_BIOS_DEBUG ("Pointer to DMI structures not found!\n");
}
}
/*
* map the SM-BIOS structures physical address range.
* the 'real' smbios_structures_base contains the starting
* address, where the instances of dmi structures are located.
*/
if (smbios_entry_point)
{
if (!(smbios_structures_base =
ioremap (smbios_entry_point->struct_table_address,
(unsigned long) smbios_entry_point->struct_table_length)))
{
SM_BIOS_DEBUG("ioremap() for structures table failed\n");
iounmap (smbios_base);
result = -ENXIO;
return result;
}
}
SM_BIOS_DEBUG(KERN_INFO "smbios_structures_base to 0x%p length %d no_of_structures:%d\n",
smbios_structures_base,
smbios_entry_point->struct_table_length,
smbios_entry_point->no_of_structures);
//dump_smbios_hex((unsigned char *)smbios_structures_base,smbios_entry_point->struct_table_length);
p = (unsigned char *)smbios_structures_base;
for(i=0;i<smbios_entry_point->struct_table_length;i++)
{
if((p[i] == 0xc0)&&(p[i+1]==0x06))
{
SM_BIOS_DEBUG("Found 0xc0 at offset:%d 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x \n\t",i,p[i],p[i+1],p[i+2],p[i+3],p[i+4],p[i+5]);
*config0 = p[i+4];
*config1 = p[i+5];
result = 0;
break;
}
}
//smbios_make_dir_entries();
iounmap (smbios_structures_base);
iounmap (smbios_base);
return result;
}
/*
void dmi_dump_backup(void)
{
const char *board_vendor, *board_name,*board_serial;
const struct dmi_device *dmi;
struct dmi_dev_onboard *donboard;
board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR);
board_name = dmi_get_system_info(DMI_BOARD_NAME);
board_serial = dmi_get_system_info(DMI_BOARD_SERIAL);
printk(KERN_INFO "DMI_BOARD_VENDOR:%s\n",board_vendor);
printk(KERN_INFO "DMI_BOARD_NAME:%s\n",board_name);
printk(KERN_INFO "DMI_BOARD_SERIAL:%s\n",board_serial);
for(i=0;i<256;i++)
{
dmi = NULL;
//printk(KERN_INFO "dmi_find_device<%d>\n",i);
while ((dmi = dmi_find_device(i,NULL, dmi)) != NULL)
{
//donboard = dmi->device_data;
printk(KERN_INFO "<%d>Found name:%s type:%d \n",i,dmi->name,dmi->type);
}
}
}
*/
/* Copyright (C) 2001-2001 Fujitsu Siemens Computers
Joachim Braeuer
This file is part of smbios
smbios is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
smbios is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with smbios; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
/* $Id: bios.h,v 1.2 2002/09/03 10:33:12 bretthauert Exp $
*
* $Log: bios.h,v $
* Revision 1.2 2002/09/03 10:33:12 bretthauert
* fixed a bug with 2.4 kernels (changed kmalloc parameter from
* GFP_BUFFER to GFP_KERNEL
*
* Revision 1.1 2001/09/15 14:52:43 bretthauert
* initial release
*
*/
/** \file bios.h
* declarations and prototypes of DMI-BIOS and SM-BIOS stuff
*
* \author Markus Lyra
* \author Thomas Bretthauer
* \author Joachim Braeuer
* \version 0.11
* \date January 2001
*/
#ifndef __SM_BIOS_H__
#define __SM_BIOS_H__
#include <linux/types.h>
//#define _EN_DEBUG_ 1
#ifdef _EN_DEBUG_
# define SM_BIOS_DEBUG(fmt, args...) printk( KERN_DEBUG "smbios: " fmt, ## args)
#else
# define SM_BIOS_DEBUG(fmt, args...) /* not debugging: nothing */
#endif
/*
* Magic numbers
*/
/** start address of BIOS segment to scanned for SM-BIOS and DMI-BIOS */
#define BIOS_START_ADDRESS 0xF0000
/** length of the scanned BIOS area for SM-BIOS and DMI-BIOS */
#define BIOS_MAP_LENGTH 0x10000
/** magic 4 bytes to identify SM-BIOS entry point, paragraph boundary */
#define SMBIOS_MAGIC_DWORD 0x5F4D535F /* anchor string "_SM_" */
/** magic 4 bytes to identify DMI-BIOS entry point, byte boundary */
#define DMIBIOS_MAGIC_DWORD 0x494d445f /* anchor string "_DMI" */
/** identifier for SM-BIOS structures within SM-BIOS entry point */
#define DMI_STRING "_DMI_"
/** list of types which are known to have subtyes; expandable! */
#define TYPES_WITH_SUBTYPES 185, 187, 208, 209, 210, 211, 212, 254
/** maximum block size for proc read function */
#define PROC_BLOCK_SIZE (3*1024)
/** mode raw/cooked */
#define FILE_MODE_RAW 0
#define FILE_MODE_COOKED 1
/*
* Structures
*/
/** SM-BIOS entry point structure
* the SMBIOS Entry Point structure described below can be located by
* application software by searching for the anchor string on paragraph
* (16 byte) boundaries within the physical memory address range 000F0000h to
* 000FFFFFh. This entry point encapsulates an intermediate anchor string
* that is used by some existing DMI browsers.
*
* @note While the SMBIOS Major and Minor Versions (offsets 06h and 07h)
* currently duplicate the information present in the SMBIOS BCD Revision
* (offset 1Dh), they provide a path for future growth in this specification.
* The BCD Revision, for example, provides only a single digit for each of
* the major and minor version numbers.
*/
struct smbios_entry_point_struct
{
/** "_SM_", specified as four ASCII characters (5F 53 4D 5F) */
__u32 anchor_string;
/** checksum of the Entry Point Structure (EPS). This value, when added to
* all other bytes in the EPS, will result in the value 00h (using 8 bit
* addition calculations). Values in the EPS are summed starting at offset
* 00h, for Entry Point Length bytes.*/
__u8 entry_point_checksum;
/** Length of the Entry Point Structure, starting with the Anchor String
* field, in bytes, currently 1Fh. */
__u8 entry_point_length;
/** identifies the major version of this specification implemented in
* the table structures, e.g. the value will be 0Ah for revision 10.22
* and 02h for revision 2.1 */
__u8 major_version;
/** identifies the minor version of this specification implemented in
* the table structures, e.g. the value will be 16h for revision 10.22
* and 01h for revision 2.1 */
__u8 minor_version;
/** size of the largest SMBIOS structure, in bytes, and encompasses the
* structure's formatted area and text strings. This is the value returned
* as StructureSize from the Plug-n-Play 'Get SMBIOS Information' function */
__u16 max_struct_size;
/** identifies the EPS revision implemented in this structure and identifies
* the formatting of offsets 0Bh to 0Fh, one of:
* 00h Entry Point based on SMBIOS 2.1 definition; formatted area is
* reserved and set to all 00h.
* 01h-FFh reserved for assignment via this specification */
__u8 revision;
/** the value present in the Entry Point Revision field defines the
* interpretation to be placed upon these5 bytes. */
__u8 formated_area[5];
/** "_DMI_", specified as five ASCII characters (5F 44 4D 49 5F) */
__u8 intermediate_string[5];
/** checksum of the Intermediate Entry Point Structure (IEPS). This value,
* when added to all other bytes in the IEPS, will result in the value 00h
* (using 8 bit addition calculations). Values in the IEPS are summed
* starting at offset 10h, for 0Fh bytes */
__u8 intermediate_checksum;
/** the 32 bit physical starting address of the read-only SMBIOS Structure
* Table, that can start at any 32 bit address. This area contains all of the
* SMBIOS structures fully packed together. These structures can then be
* parsed to produce exactly the same format as that returned from a 'Get
* SMBIOS Structure' function call. */
__u16 struct_table_length;
__u32 struct_table_address;
__u16 no_of_structures;
__u8 bcd_revision;
}__attribute__ ((packed));
/** SM-BIOS and DMI-BIOS structure header */
struct smbios_struct
{
__u8 type ;
__u8 length ;
__u16 handle ;
__u8 subtype;
/* ... other fields are structure dependend ... */
} __attribute__ ((packed));
/** DMI-BIOS structure header */
struct dmibios_table_entry_struct
{
__u16 size;
__u16 handle;
__u32 procedure;
}__attribute__ ((packed));
/** DMI-BIOS entry point structure */
struct dmibios_entry_point_struct
{
__u8 signature[10];
__u8 revision;
struct dmibios_table_entry_struct entry[1];
}__attribute__ ((packed));
/** readable names for smbios structures, they serve as filenames in the /proc file system */
#define RD_BIOS "bios"
#define RD_SYSTEM "system"
#define RD_BASEBOARD "baseboard"
#define RD_ENCLOSURE "enclosure"
#define RD_PROCESSOR "processor"
#define RD_MEMCTRL "memory_controller"
#define RD_MEMMOD "memory_module"
#define RD_CACHE "cache"
#define RD_PORT "port_connector"
#define RD_SLOT "system_slot"
#define RD_ONBOARD "onboard_device"
#define RD_OEMSTRINGS "oem_strings"
#define RD_SYSTEMCONFIG "system_configuration"
#define RD_BIOSLANG "bios_language"
#define RD_GROUPASSOC "group_association"
#define RD_EVENTLOG "system_event_log"
#define RD_MEMARRAY "physical_memory_array"
#define RD_MEMDEV "physical_memory_device"
#define RD_32MEMERR "32bit_memory_error_information"
#define RD_MEMMAPPEDADR "memory_array_mapped_address"
#define RD_MEMMAPPEDDEV "memory_device_mapped_address"
#define RD_POINTINGDEV "pointing_device"
#define RD_BATTERY "portable_battery"
#define RD_RESET "system_reset"
#define RD_SECURITY "hardware_security"
#define RD_PWRCTRL "system_power_controls"
#define RD_VOLTAGE "voltage_probe"
#define RD_COOLINGDEV "cooling_device"
#define RD_TEMP "temperature_probe"
#define RD_CURRENT "current_probe"
#define RD_RMTACCESS "out_of_band_remote_access"
#define RD_BIS "boot_integrity_services"
#define RD_BOOT_INFO "system_boot_information"
#define RD_64MEMERR "64bit_memory_error_information"
#define RD_MANAGDEV "management_device"
#define RD_MANAGDEVCOMP "management_device_component"
#define RD_MANAGDEVTHRESH "management_device_thresholds"
#define RD_MEMCHANNEL "memory_channel"
#define RD_IPMI "ipmi_information"
#define RD_PWRSUP "system_power_supply"
#define RD_INACTIVE "inactive"
#define RD_EOT "end_of_table"
//extern smbios_entry_point_struct * smbios_entry_point; /* start of SMBIOS within the F-Segment */
//extern dmibios_entry_point_struct * dmibios_entry_point; /* start of DMIBIOS within the F-Segment */
extern void * smbios_structures_base; /* base of SMBIOS raw structures */
extern unsigned char smbios_types_with_subtypes[];
extern char smbios_version_string[32]; /* e.g. V2.31 */
/*
* Functions
*/
/* for the description see the implementation file */
struct smbios_entry_point_struct * smbios_find_entry_point(void * base);
struct dmibios_entry_point_struct * dmibios_find_entry_point(void * base);
unsigned char smbios_check_entry_point(void * addr);
int smbios_type_has_subtype(unsigned char type);
int smbios_get_struct_length(struct smbios_struct * struct_ptr);
int dmibios_get_struct_length(struct smbios_struct * struct_ptr);
unsigned int smbios_get_readable_name_ext(char *readable_name, struct smbios_struct *struct_ptr);
unsigned int smbios_get_readable_name(char *readable_name, struct smbios_struct *struct_ptr);
int smbios_check_if_have_exar_config(unsigned char *config0,unsigned char *config1);
#endif /* __BIOS_H__ */
...@@ -28,12 +28,12 @@ ...@@ -28,12 +28,12 @@
* from www.exar.com that will work with kernel versions 2.6.18 to 3.4.x. * from www.exar.com that will work with kernel versions 2.6.18 to 3.4.x.
* *
* ChangeLog: * ChangeLog:
* Version 1A - Initial released version. * Version 1B - Initial released version.
*/ */
//#undef DEBUG #undef DEBUG
#undef VERBOSE_DEBUG #undef VERBOSE_DEBUG
#include <linux/gpio.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/init.h> #include <linux/init.h>
...@@ -47,15 +47,20 @@ ...@@ -47,15 +47,20 @@
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/usb.h> #include <linux/usb.h>
#include <linux/usb/cdc.h> #include <linux/usb/cdc.h>
#include <linux/dmi.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/delay.h>
#include <asm/io.h> /* ioremap() */
#include "linux/version.h" #include "linux/version.h"
#include "xr_get_smbios.h"
#include "xr_usb_serial_common.h" #include "xr_usb_serial_common.h"
#include "xr_usb_serial_ioctl.h" #include "xr_usb_serial_ioctl.h"
#define DRIVER_AUTHOR "<uarttechsupport@exar.com>" #define DRIVER_AUTHOR "<uarttechsupport@exar.com>"
#define DRIVER_DESC "Exar USB UART (serial port) driver" #define DRIVER_DESC "Exar USB UART (serial port) driver"
...@@ -65,6 +70,10 @@ static struct xr_usb_serial *xr_usb_serial_table[XR_USB_SERIAL_TTY_MINORS]; ...@@ -65,6 +70,10 @@ static struct xr_usb_serial *xr_usb_serial_table[XR_USB_SERIAL_TTY_MINORS];
static DEFINE_MUTEX(xr_usb_serial_table_lock); static DEFINE_MUTEX(xr_usb_serial_table_lock);
/* /*
* xr_usb_serial_table accessors * xr_usb_serial_table accessors
*/ */
...@@ -137,6 +146,7 @@ static int xr_usb_serial_ctrl_msg(struct xr_usb_serial *xr_usb_serial, int reque ...@@ -137,6 +146,7 @@ static int xr_usb_serial_ctrl_msg(struct xr_usb_serial *xr_usb_serial, int reque
return retval < 0 ? retval : 0; return retval < 0 ? retval : 0;
} }
#include "xr_get_smbios.c"
#include "xr_usb_serial_hal.c" #include "xr_usb_serial_hal.c"
...@@ -249,46 +259,6 @@ static ssize_t show_country_rel_date ...@@ -249,46 +259,6 @@ static ssize_t show_country_rel_date
} }
static DEVICE_ATTR(iCountryCodeRelDate, S_IRUGO, show_country_rel_date, NULL); static DEVICE_ATTR(iCountryCodeRelDate, S_IRUGO, show_country_rel_date, NULL);
static ssize_t set_rs485_422_en(struct device *dev,
struct device_attribute *attr, const char *buf,
size_t count)
{
struct usb_interface *intf = to_usb_interface(dev);
struct xr_usb_serial *xr_usb_serial = usb_get_intfdata(intf);
int error, value = 0;
error = kstrtoint(buf, 0, &value);
if (error)
return error;
if (value == 0) {
xr_usb_serial->rs485_422_en = false;
} else if (value == 1) {
// RS485,RS422 HD/FD mode
xr_usb_serial->rs485_422_en = true;
}
return count;
}
static ssize_t show_rs485_422_en(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct usb_interface *intf = to_usb_interface(dev);
struct xr_usb_serial *xr_usb_serial = usb_get_intfdata(intf);
if (xr_usb_serial->rs485_422_en == false) {
return sprintf(buf, "0");
} else if (xr_usb_serial->rs485_422_en == true) {
// RS485,RS422 HD/FD mode
return sprintf(buf, "1");
}
return 0;
}
static DEVICE_ATTR(bRS485_422_en, 0644, show_rs485_422_en, set_rs485_422_en);
/* /*
* Interrupt handlers for various XR_USB_SERIAL device responses * Interrupt handlers for various XR_USB_SERIAL device responses
*/ */
...@@ -298,7 +268,10 @@ static void xr_usb_serial_ctrl_irq(struct urb *urb) ...@@ -298,7 +268,10 @@ static void xr_usb_serial_ctrl_irq(struct urb *urb)
{ {
struct xr_usb_serial *xr_usb_serial = urb->context; struct xr_usb_serial *xr_usb_serial = urb->context;
struct usb_cdc_notification *dr = urb->transfer_buffer; struct usb_cdc_notification *dr = urb->transfer_buffer;
#if LINUX_VERSION_CODE > KERNEL_VERSION(3, 9, 0)
#else
struct tty_struct *tty; struct tty_struct *tty;
#endif
unsigned char *data; unsigned char *data;
int newctrl; int newctrl;
int retval; int retval;
...@@ -309,10 +282,11 @@ static void xr_usb_serial_ctrl_irq(struct urb *urb) ...@@ -309,10 +282,11 @@ static void xr_usb_serial_ctrl_irq(struct urb *urb)
switch (status) { switch (status) {
case 0: case 0:
p = (unsigned char *)(urb->transfer_buffer); p = (unsigned char *)(urb->transfer_buffer);
/*
for(i=0;i<urb->actual_length;i++) for(i=0;i<urb->actual_length;i++)
{ {
dev_dbg(&xr_usb_serial->control->dev,"0x%02x\n",p[i]); dev_dbg(&xr_usb_serial->control->dev,"0x%02x\n",p[i]);
} }*/
/* success */ /* success */
break; break;
case -ECONNRESET: case -ECONNRESET:
...@@ -362,7 +336,7 @@ static void xr_usb_serial_ctrl_irq(struct urb *urb) ...@@ -362,7 +336,7 @@ static void xr_usb_serial_ctrl_irq(struct urb *urb)
} }
#endif #endif
xr_usb_serial->ctrlin = newctrl; xr_usb_serial->ctrlin = newctrl;
#if 0
dev_dbg(&xr_usb_serial->control->dev, dev_dbg(&xr_usb_serial->control->dev,
"%s - input control lines: dcd%c dsr%c break%c " "%s - input control lines: dcd%c dsr%c break%c "
"ring%c framing%c parity%c overrun%c\n", "ring%c framing%c parity%c overrun%c\n",
...@@ -374,6 +348,7 @@ static void xr_usb_serial_ctrl_irq(struct urb *urb) ...@@ -374,6 +348,7 @@ static void xr_usb_serial_ctrl_irq(struct urb *urb)
xr_usb_serial->ctrlin & XR_USB_SERIAL_CTRL_FRAMING ? '+' : '-', xr_usb_serial->ctrlin & XR_USB_SERIAL_CTRL_FRAMING ? '+' : '-',
xr_usb_serial->ctrlin & XR_USB_SERIAL_CTRL_PARITY ? '+' : '-', xr_usb_serial->ctrlin & XR_USB_SERIAL_CTRL_PARITY ? '+' : '-',
xr_usb_serial->ctrlin & XR_USB_SERIAL_CTRL_OVERRUN ? '+' : '-'); xr_usb_serial->ctrlin & XR_USB_SERIAL_CTRL_OVERRUN ? '+' : '-');
#endif
break; break;
default: default:
...@@ -399,7 +374,7 @@ static int xr_usb_serial_submit_read_urb(struct xr_usb_serial *xr_usb_serial, in ...@@ -399,7 +374,7 @@ static int xr_usb_serial_submit_read_urb(struct xr_usb_serial *xr_usb_serial, in
if (!test_and_clear_bit(index, &xr_usb_serial->read_urbs_free)) if (!test_and_clear_bit(index, &xr_usb_serial->read_urbs_free))
return 0; return 0;
dev_vdbg(&xr_usb_serial->data->dev, "%s - urb %d\n", __func__, index); //dev_vdbg(&xr_usb_serial->data->dev, "%s - urb %d\n", __func__, index);
res = usb_submit_urb(xr_usb_serial->read_urbs[index], mem_flags); res = usb_submit_urb(xr_usb_serial->read_urbs[index], mem_flags);
if (res) { if (res) {
...@@ -430,10 +405,75 @@ static int xr_usb_serial_submit_read_urbs(struct xr_usb_serial *xr_usb_serial, g ...@@ -430,10 +405,75 @@ static int xr_usb_serial_submit_read_urbs(struct xr_usb_serial *xr_usb_serial, g
} }
static void xr_usb_serial_process_read_urb(struct xr_usb_serial *xr_usb_serial, struct urb *urb) static void xr_usb_serial_process_read_urb(struct xr_usb_serial *xr_usb_serial, struct urb *urb)
{ {
#if LINUX_VERSION_CODE > KERNEL_VERSION(3, 9, 0)
#else
struct tty_struct *tty; struct tty_struct *tty;
#endif
int preciseflags = xr_usb_serial->preciseflags;
int have_extra_byte;
int length;
if (!urb->actual_length) if (!urb->actual_length)
return; return;
#if LINUX_VERSION_CODE > KERNEL_VERSION(3, 9, 0)
if (preciseflags)
{
char *dp = urb->transfer_buffer;
int i, ch, ch_flags;
length = urb->actual_length;
length = length + (xr_usb_serial->have_extra_byte ? 1 : 0);
have_extra_byte = (preciseflags && (length & 1));
length = (preciseflags) ? (length / 2) : length;
for (i = 0; i < length; ++i)
{
char tty_flag;
if (i == 0)
{
if (xr_usb_serial->have_extra_byte)
{
ch = xr_usb_serial->extra_byte;
}
else
{
ch = *dp++;
}
}
else
{
ch = *dp++;
}
ch_flags = *dp++;
if (ch_flags & RAMCTL_BUFFER_PARITY)
tty_flag = TTY_PARITY;
else if (ch_flags & RAMCTL_BUFFER_BREAK)
tty_flag = TTY_BREAK;
else if (ch_flags & RAMCTL_BUFFER_FRAME)
tty_flag = TTY_FRAME;
else if (ch_flags & RAMCTL_BUFFER_OVERRUN)
tty_flag = TTY_OVERRUN;
else
tty_flag = TTY_NORMAL;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
tty_insert_flip_char(&xr_usb_serial->port, ch, tty_flag);
tty_flip_buffer_push(&xr_usb_serial->port);
#else
tty = tty_port_tty_get(&xr_usb_serial->port);
if (!tty)
return;
tty_insert_flip_char(&xr_usb_serial->port, ch, tty_flag);
tty_flip_buffer_push(tty);
tty_kref_put(tty);
#endif
}
}
else
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
tty_insert_flip_string(&xr_usb_serial->port, urb->transfer_buffer, tty_insert_flip_string(&xr_usb_serial->port, urb->transfer_buffer,
urb->actual_length); urb->actual_length);
tty_flip_buffer_push(&xr_usb_serial->port); tty_flip_buffer_push(&xr_usb_serial->port);
...@@ -446,6 +486,7 @@ static void xr_usb_serial_process_read_urb(struct xr_usb_serial *xr_usb_serial, ...@@ -446,6 +486,7 @@ static void xr_usb_serial_process_read_urb(struct xr_usb_serial *xr_usb_serial,
tty_kref_put(tty); tty_kref_put(tty);
#endif #endif
}
} }
static void xr_usb_serial_read_bulk_callback(struct urb *urb) static void xr_usb_serial_read_bulk_callback(struct urb *urb)
...@@ -453,9 +494,10 @@ static void xr_usb_serial_read_bulk_callback(struct urb *urb) ...@@ -453,9 +494,10 @@ static void xr_usb_serial_read_bulk_callback(struct urb *urb)
struct xr_usb_serial_rb *rb = urb->context; struct xr_usb_serial_rb *rb = urb->context;
struct xr_usb_serial *xr_usb_serial = rb->instance; struct xr_usb_serial *xr_usb_serial = rb->instance;
unsigned long flags; unsigned long flags;
/*
dev_vdbg(&xr_usb_serial->data->dev, "%s - urb %d, len %d\n", __func__, dev_vdbg(&xr_usb_serial->data->dev, "%s - urb %d, len %d\n", __func__,
rb->index, urb->actual_length); rb->index, urb->actual_length);*/
set_bit(rb->index, &xr_usb_serial->read_urbs_free); set_bit(rb->index, &xr_usb_serial->read_urbs_free);
if (!xr_usb_serial->dev) { if (!xr_usb_serial->dev) {
...@@ -467,7 +509,7 @@ static void xr_usb_serial_read_bulk_callback(struct urb *urb) ...@@ -467,7 +509,7 @@ static void xr_usb_serial_read_bulk_callback(struct urb *urb)
if (urb->status) { if (urb->status) {
dev_dbg(&xr_usb_serial->data->dev, "%s - non-zero urb status: %d\n", dev_dbg(&xr_usb_serial->data->dev, "%s - non-zero urb status: %d\n",
__func__, urb->status); __func__, urb->status);
return; //return;
} }
xr_usb_serial_process_read_urb(xr_usb_serial, urb); xr_usb_serial_process_read_urb(xr_usb_serial, urb);
...@@ -505,9 +547,13 @@ static void xr_usb_serial_write_bulk(struct urb *urb) ...@@ -505,9 +547,13 @@ static void xr_usb_serial_write_bulk(struct urb *urb)
static void xr_usb_serial_softint(struct work_struct *work) static void xr_usb_serial_softint(struct work_struct *work)
{ {
struct xr_usb_serial *xr_usb_serial = container_of(work, struct xr_usb_serial, work); struct xr_usb_serial *xr_usb_serial = container_of(work, struct xr_usb_serial, work);
#if LINUX_VERSION_CODE > KERNEL_VERSION(3, 9, 0)
#else
struct tty_struct *tty; struct tty_struct *tty;
#endif
dev_vdbg(&xr_usb_serial->data->dev, "%s\n", __func__); //dev_vdbg(&xr_usb_serial->data->dev, "%s\n", __func__);
#if LINUX_VERSION_CODE > KERNEL_VERSION(3, 9, 0) #if LINUX_VERSION_CODE > KERNEL_VERSION(3, 9, 0)
tty_port_tty_wakeup(&xr_usb_serial->port); tty_port_tty_wakeup(&xr_usb_serial->port);
#else #else
...@@ -528,7 +574,7 @@ static int xr_usb_serial_tty_install(struct tty_driver *driver, struct tty_struc ...@@ -528,7 +574,7 @@ static int xr_usb_serial_tty_install(struct tty_driver *driver, struct tty_struc
struct xr_usb_serial *xr_usb_serial; struct xr_usb_serial *xr_usb_serial;
int retval; int retval;
dev_dbg(tty->dev, "%s\n", __func__); //dev_dbg(tty->dev, "%s\n", __func__);
xr_usb_serial = xr_usb_serial_get_by_index(tty->index); xr_usb_serial = xr_usb_serial_get_by_index(tty->index);
if (!xr_usb_serial) if (!xr_usb_serial)
...@@ -550,8 +596,9 @@ static int xr_usb_serial_tty_install(struct tty_driver *driver, struct tty_struc ...@@ -550,8 +596,9 @@ static int xr_usb_serial_tty_install(struct tty_driver *driver, struct tty_struc
static int xr_usb_serial_tty_open(struct tty_struct *tty, struct file *filp) static int xr_usb_serial_tty_open(struct tty_struct *tty, struct file *filp)
{ {
struct xr_usb_serial *xr_usb_serial = tty->driver_data; struct xr_usb_serial *xr_usb_serial = tty->driver_data;
int result;
dev_dbg(tty->dev, "%s\n", __func__); result = xr_usb_serial_fifo_reset(xr_usb_serial);
//dev_dbg(tty->dev, "%s\n", __func__);
return tty_port_open(&xr_usb_serial->port, tty, filp); return tty_port_open(&xr_usb_serial->port, tty, filp);
} }
...@@ -561,7 +608,7 @@ static int xr_usb_serial_port_activate(struct tty_port *port, struct tty_struct ...@@ -561,7 +608,7 @@ static int xr_usb_serial_port_activate(struct tty_port *port, struct tty_struct
struct xr_usb_serial *xr_usb_serial = container_of(port, struct xr_usb_serial, port); struct xr_usb_serial *xr_usb_serial = container_of(port, struct xr_usb_serial, port);
int retval = -ENODEV; int retval = -ENODEV;
dev_dbg(&xr_usb_serial->control->dev, "%s\n", __func__); //dev_dbg(&xr_usb_serial->control->dev, "%s\n", __func__);
mutex_lock(&xr_usb_serial->mutex); mutex_lock(&xr_usb_serial->mutex);
if (xr_usb_serial->disconnected) if (xr_usb_serial->disconnected)
...@@ -624,14 +671,18 @@ static void xr_usb_serial_port_destruct(struct tty_port *port) ...@@ -624,14 +671,18 @@ static void xr_usb_serial_port_destruct(struct tty_port *port)
{ {
struct xr_usb_serial *xr_usb_serial = container_of(port, struct xr_usb_serial, port); struct xr_usb_serial *xr_usb_serial = container_of(port, struct xr_usb_serial, port);
dev_dbg(&xr_usb_serial->control->dev, "%s\n", __func__); //dev_dbg(&xr_usb_serial->control->dev, "%s\n", __func__);
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0) #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0)
tty_unregister_device(xr_usb_serial_tty_driver, xr_usb_serial->minor); tty_unregister_device(xr_usb_serial_tty_driver, xr_usb_serial->minor);
#endif #endif
#ifdef CONFIG_GPIOLIB
gpiochip_remove(&xr_usb_serial->xr_usb_gpio);
#endif
xr_usb_serial_release_minor(xr_usb_serial); xr_usb_serial_release_minor(xr_usb_serial);
usb_put_intf(xr_usb_serial->control); usb_put_intf(xr_usb_serial->control);
kfree(xr_usb_serial->country_codes); kfree(xr_usb_serial->country_codes);
kfree(xr_usb_serial); kfree(xr_usb_serial);
} }
static void xr_usb_serial_port_shutdown(struct tty_port *port) static void xr_usb_serial_port_shutdown(struct tty_port *port)
...@@ -639,7 +690,7 @@ static void xr_usb_serial_port_shutdown(struct tty_port *port) ...@@ -639,7 +690,7 @@ static void xr_usb_serial_port_shutdown(struct tty_port *port)
struct xr_usb_serial *xr_usb_serial = container_of(port, struct xr_usb_serial, port); struct xr_usb_serial *xr_usb_serial = container_of(port, struct xr_usb_serial, port);
int i; int i;
dev_dbg(&xr_usb_serial->control->dev, "%s\n", __func__); //dev_dbg(&xr_usb_serial->control->dev, "%s\n", __func__);
mutex_lock(&xr_usb_serial->mutex); mutex_lock(&xr_usb_serial->mutex);
if (!xr_usb_serial->disconnected) { if (!xr_usb_serial->disconnected) {
...@@ -659,21 +710,21 @@ static void xr_usb_serial_port_shutdown(struct tty_port *port) ...@@ -659,21 +710,21 @@ static void xr_usb_serial_port_shutdown(struct tty_port *port)
static void xr_usb_serial_tty_cleanup(struct tty_struct *tty) static void xr_usb_serial_tty_cleanup(struct tty_struct *tty)
{ {
struct xr_usb_serial *xr_usb_serial = tty->driver_data; struct xr_usb_serial *xr_usb_serial = tty->driver_data;
dev_dbg(&xr_usb_serial->control->dev, "%s\n", __func__); //dev_dbg(&xr_usb_serial->control->dev, "%s\n", __func__);
tty_port_put(&xr_usb_serial->port); tty_port_put(&xr_usb_serial->port);
} }
static void xr_usb_serial_tty_hangup(struct tty_struct *tty) static void xr_usb_serial_tty_hangup(struct tty_struct *tty)
{ {
struct xr_usb_serial *xr_usb_serial = tty->driver_data; struct xr_usb_serial *xr_usb_serial = tty->driver_data;
dev_dbg(&xr_usb_serial->control->dev, "%s\n", __func__); //dev_dbg(&xr_usb_serial->control->dev, "%s\n", __func__);
tty_port_hangup(&xr_usb_serial->port); tty_port_hangup(&xr_usb_serial->port);
} }
static void xr_usb_serial_tty_close(struct tty_struct *tty, struct file *filp) static void xr_usb_serial_tty_close(struct tty_struct *tty, struct file *filp)
{ {
struct xr_usb_serial *xr_usb_serial = tty->driver_data; struct xr_usb_serial *xr_usb_serial = tty->driver_data;
dev_dbg(&xr_usb_serial->control->dev, "%s\n", __func__); //dev_dbg(&xr_usb_serial->control->dev, "%s\n", __func__);
tty_port_close(&xr_usb_serial->port, tty, filp); tty_port_close(&xr_usb_serial->port, tty, filp);
} }
...@@ -689,7 +740,7 @@ static int xr_usb_serial_tty_write(struct tty_struct *tty, ...@@ -689,7 +740,7 @@ static int xr_usb_serial_tty_write(struct tty_struct *tty,
if (!count) if (!count)
return 0; return 0;
dev_vdbg(&xr_usb_serial->data->dev, "%s - count %d\n", __func__, count); //dev_vdbg(&xr_usb_serial->data->dev, "%s - count %d\n", __func__, count);
spin_lock_irqsave(&xr_usb_serial->write_lock, flags); spin_lock_irqsave(&xr_usb_serial->write_lock, flags);
wbn = xr_usb_serial_wb_alloc(xr_usb_serial); wbn = xr_usb_serial_wb_alloc(xr_usb_serial);
...@@ -706,7 +757,7 @@ static int xr_usb_serial_tty_write(struct tty_struct *tty, ...@@ -706,7 +757,7 @@ static int xr_usb_serial_tty_write(struct tty_struct *tty,
} }
count = (count > xr_usb_serial->writesize) ? xr_usb_serial->writesize : count; count = (count > xr_usb_serial->writesize) ? xr_usb_serial->writesize : count;
dev_vdbg(&xr_usb_serial->data->dev, "%s - write %d\n", __func__, count); //dev_vdbg(&xr_usb_serial->data->dev, "%s - write %d\n", __func__, count);
memcpy(wb->buf, buf, count); memcpy(wb->buf, buf, count);
wb->len = count; wb->len = count;
...@@ -785,7 +836,7 @@ static int xr_usb_serial_tty_break_ctl(struct tty_struct *tty, int state) ...@@ -785,7 +836,7 @@ static int xr_usb_serial_tty_break_ctl(struct tty_struct *tty, int state)
retval = xr_usb_serial_send_break(xr_usb_serial, state ? 0xffff : 0); retval = xr_usb_serial_send_break(xr_usb_serial, state ? 0xffff : 0);
if (retval < 0) if (retval < 0)
dev_dbg(&xr_usb_serial->control->dev, "%s - send break failed\n", dev_err(&xr_usb_serial->control->dev, "%s - send break failed\n",
__func__); __func__);
return retval; return retval;
} }
...@@ -793,7 +844,7 @@ static int xr_usb_serial_tty_break_ctl(struct tty_struct *tty, int state) ...@@ -793,7 +844,7 @@ static int xr_usb_serial_tty_break_ctl(struct tty_struct *tty, int state)
static int xr_usb_serial_tty_tiocmget(struct tty_struct *tty) static int xr_usb_serial_tty_tiocmget(struct tty_struct *tty)
{ {
struct xr_usb_serial *xr_usb_serial = tty->driver_data; struct xr_usb_serial *xr_usb_serial = tty->driver_data;
dev_dbg(&xr_usb_serial->control->dev, "xr_usb_serial_tty_tiocmget\n"); //dev_dbg(&xr_usb_serial->control->dev, "xr_usb_serial_tty_tiocmget\n");
return xr_usb_serial_tiocmget(xr_usb_serial); return xr_usb_serial_tiocmget(xr_usb_serial);
} }
...@@ -802,7 +853,7 @@ static int xr_usb_serial_tty_tiocmset(struct tty_struct *tty, ...@@ -802,7 +853,7 @@ static int xr_usb_serial_tty_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear) unsigned int set, unsigned int clear)
{ {
struct xr_usb_serial *xr_usb_serial = tty->driver_data; struct xr_usb_serial *xr_usb_serial = tty->driver_data;
dev_dbg(&xr_usb_serial->control->dev, "xr_usb_serial_tty_tiocmset set=0x%x clear=0x%x\n",set,clear); //dev_dbg(&xr_usb_serial->control->dev, "xr_usb_serial_tty_tiocmset set=0x%x clear=0x%x\n",set,clear);
return xr_usb_serial_tiocmset(xr_usb_serial,set,clear); return xr_usb_serial_tiocmset(xr_usb_serial,set,clear);
} }
...@@ -865,8 +916,9 @@ static int xr_usb_serial_tty_ioctl(struct tty_struct *tty, ...@@ -865,8 +916,9 @@ static int xr_usb_serial_tty_ioctl(struct tty_struct *tty,
{ {
struct xr_usb_serial *xr_usb_serial = tty->driver_data; struct xr_usb_serial *xr_usb_serial = tty->driver_data;
int rv = -ENOIOCTLCMD; int rv = -ENOIOCTLCMD;
unsigned int channel, reg, val; unsigned int channel, reg, val,preciseflags;
int baud_rate = 0;
struct usb_cdc_line_coding newline;
short *data; short *data;
switch (cmd) { switch (cmd) {
case TIOCGSERIAL: /* gets serial port data */ case TIOCGSERIAL: /* gets serial port data */
...@@ -895,7 +947,8 @@ static int xr_usb_serial_tty_ioctl(struct tty_struct *tty, ...@@ -895,7 +947,8 @@ static int xr_usb_serial_tty_ioctl(struct tty_struct *tty,
{ {
rv = xr_usb_serial_get_reg_ext(xr_usb_serial,channel,reg, data); rv = xr_usb_serial_get_reg_ext(xr_usb_serial,channel,reg, data);
} }
if (rv != 1) { if (rv < 0)
{
dev_err(&xr_usb_serial->control->dev, "Cannot get register (%d)\n", rv); dev_err(&xr_usb_serial->control->dev, "Cannot get register (%d)\n", rv);
kfree(data); kfree(data);
return -EFAULT; return -EFAULT;
...@@ -941,6 +994,93 @@ static int xr_usb_serial_tty_ioctl(struct tty_struct *tty, ...@@ -941,6 +994,93 @@ static int xr_usb_serial_tty_ioctl(struct tty_struct *tty,
return -EFAULT; return -EFAULT;
rv = 0; rv = 0;
break; break;
case XR_USB_SERIAL_SET_GPIO_MODE_REG:
xr_usb_serial_disable(xr_usb_serial);
if (get_user(channel, (int __user *)arg))
return -EFAULT;
if (get_user(val, (int __user *)(arg + sizeof(int))))
return -EFAULT;
if (channel == -1)
{
//block = portdata->block;
rv = xr_usb_serial_set_reg(xr_usb_serial,xr_usb_serial->reg_map.uart_gpio_mode_addr, val);
}
else
{
rv = xr_usb_serial_set_reg_ext(xr_usb_serial,channel,xr_usb_serial->reg_map.uart_gpio_mode_addr, val);
}
dev_dbg(&xr_usb_serial->control->dev, "XR_USB_SERIAL_SET_GPIO_MODE_REG 0x%x val:0x%x \n", xr_usb_serial->reg_map.uart_gpio_mode_addr,val);
xr_usb_serial_enable(xr_usb_serial);
if (rv < 0)
return -EFAULT;
break;
case XR_USB_SERIAL_GET_GPIO_MODE_REG:
xr_usb_serial_disable(xr_usb_serial);
if (get_user(channel, (int __user *)arg))
return -EFAULT;
data = kmalloc(2, GFP_KERNEL);
if (data == NULL) {
dev_err(&xr_usb_serial->control->dev, "%s - Cannot allocate USB buffer.\n", __func__);
return -ENOMEM;
}
if (channel == -1)
{
rv = xr_usb_serial_get_reg(xr_usb_serial,xr_usb_serial->reg_map.uart_gpio_mode_addr, data);
}
else
{
rv = xr_usb_serial_get_reg_ext(xr_usb_serial,channel,xr_usb_serial->reg_map.uart_gpio_mode_addr,data);
}
xr_usb_serial_enable(xr_usb_serial);
dev_dbg(&xr_usb_serial->control->dev, "XR_USB_SERIAL_GET_GPIO_MODE_REG 0x%x val:0x%x \n", xr_usb_serial->reg_map.uart_gpio_mode_addr,*data);
if (rv < 0 ) {
dev_err(&xr_usb_serial->control->dev, "Cannot get register (%d) channel=%d \n", rv,channel);
kfree(data);
return -EFAULT;
}
if (put_user(data[0], (int __user *)(arg + sizeof(int)))) {
dev_err(&xr_usb_serial->control->dev, "Cannot put user result\n");
kfree(data);
return -EFAULT;
}
kfree(data);
break;
case XRIOC_SET_ANY_BAUD_RATE:
if (get_user(baud_rate, (int __user *)arg)) {
dev_dbg(&xr_usb_serial->control->dev, "get_user errot \n");
return -EFAULT;
}
xr_usb_serial->line.dwDTERate = baud_rate;
memcpy(&newline,&(xr_usb_serial->line),sizeof(struct usb_cdc_line_coding));
xr_usb_serial_disable(xr_usb_serial);
rv = xr_usb_serial_set_line(xr_usb_serial,&newline);
xr_usb_serial_enable(xr_usb_serial);
dev_dbg(&xr_usb_serial->control->dev, "XRIOC_SET_ANY_BAUD_RATE set baud_rate:%d ret=%d\n", baud_rate,rv);
break;
case XRIOC_SET_PRECISE_FLAGS:
preciseflags = arg;
dev_dbg(&xr_usb_serial->control->dev, "%s VIOC_SET_PRECISE_FLAGS %d\n", __func__, preciseflags);
xr_usb_serial_disable(xr_usb_serial);
if (preciseflags)
{
xr_usb_serial->preciseflags = 1;
}
else
{
xr_usb_serial->preciseflags = 0;
}
xr_usb_serial_set_wide_mode(xr_usb_serial,xr_usb_serial->preciseflags);
xr_usb_serial_enable(xr_usb_serial);
break;
} }
...@@ -965,9 +1105,11 @@ static void xr_usb_serial_tty_set_termios(struct tty_struct *tty, ...@@ -965,9 +1105,11 @@ static void xr_usb_serial_tty_set_termios(struct tty_struct *tty,
newline.bParityType = termios->c_cflag & PARENB ? newline.bParityType = termios->c_cflag & PARENB ?
(termios->c_cflag & PARODD ? 1 : 2) + (termios->c_cflag & PARODD ? 1 : 2) +
(termios->c_cflag & CMSPAR ? 2 : 0) : 0; (termios->c_cflag & CMSPAR ? 2 : 0) : 0;
xr_usb_serial->trans9 = 0;
switch (termios->c_cflag & CSIZE) { switch (termios->c_cflag & CSIZE) {
case CS5:/*using CS5 replace of the 9 bit data mode*/ case CS5:/*using CS5 replace of the 9 bit data mode*/
newline.bDataBits = 9; newline.bDataBits = 9;
xr_usb_serial->trans9 =1;
break; break;
case CS6: case CS6:
newline.bDataBits = 6; newline.bDataBits = 6;
...@@ -993,15 +1135,27 @@ static void xr_usb_serial_tty_set_termios(struct tty_struct *tty, ...@@ -993,15 +1135,27 @@ static void xr_usb_serial_tty_set_termios(struct tty_struct *tty,
xr_usb_serial_set_control(xr_usb_serial, xr_usb_serial->ctrlout = newctrl); xr_usb_serial_set_control(xr_usb_serial, xr_usb_serial->ctrlout = newctrl);
xr_usb_serial_set_flow_mode(xr_usb_serial,tty,cflag);/*set the serial flow mode*/ xr_usb_serial_set_flow_mode(xr_usb_serial,tty,cflag);/*set the serial flow mode*/
if (xr_usb_serial->trans9)
{
/* Turn on wide mode if we're 9-bit transparent. */
xr_usb_serial_set_wide_mode(xr_usb_serial,1);
}
else if (!xr_usb_serial->preciseflags)
{
xr_usb_serial_set_wide_mode(xr_usb_serial,0);
}
if (memcmp(&xr_usb_serial->line, &newline, sizeof newline)) if (memcmp(&xr_usb_serial->line, &newline, sizeof newline))
{ {
memcpy(&xr_usb_serial->line, &newline, sizeof newline); memcpy(&xr_usb_serial->line, &newline, sizeof newline);
/*
dev_dbg(&xr_usb_serial->control->dev, "%s - set line: %d %d %d %d\n", dev_dbg(&xr_usb_serial->control->dev, "%s - set line: %d %d %d %d\n",
__func__, __func__,
le32_to_cpu(newline.dwDTERate), le32_to_cpu(newline.dwDTERate),
newline.bCharFormat, newline.bParityType, newline.bCharFormat, newline.bParityType,
newline.bDataBits); newline.bDataBits);*/
xr_usb_serial_set_line(xr_usb_serial, &xr_usb_serial->line); xr_usb_serial_set_line(xr_usb_serial, &xr_usb_serial->line);
} }
xr_usb_serial_enable(xr_usb_serial); xr_usb_serial_enable(xr_usb_serial);
...@@ -1060,6 +1214,36 @@ static int xr_usb_serial_write_buffers_alloc(struct xr_usb_serial *xr_usb_serial ...@@ -1060,6 +1214,36 @@ static int xr_usb_serial_write_buffers_alloc(struct xr_usb_serial *xr_usb_serial
return 0; return 0;
} }
#ifdef CONFIG_GPIOLIB
static int xr_usb_gpio_get(struct gpio_chip *chip, unsigned offset)
{
struct xr_usb_serial *xr_usb_serial = container_of(chip, struct xr_usb_serial, xr_usb_gpio);
dev_dbg(chip->dev, "xr_usb_gpio_get offset = %d channel = %d\n",offset,xr_usb_serial->channel);
return 0;
}
static void xr_usb_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
{
struct xr_usb_serial *xr_usb_serial = container_of(chip, struct xr_usb_serial, xr_usb_gpio);
dev_dbg(chip->dev, "xr_usb_gpio_set offset =%d val=%d channel = %d\n",offset,val,xr_usb_serial->channel);
}
static int xr_usb_gpio_direction_input(struct gpio_chip *chip,unsigned offset)
{
struct xr_usb_serial *xr_usb_serial = container_of(chip, struct xr_usb_serial, xr_usb_gpio);
dev_dbg(chip->dev, "xr_usb_gpio_direction_input offset =%d channel = %d\n",offset,xr_usb_serial->channel);
return 0;
}
static int xr_usb_gpio_direction_output(struct gpio_chip *chip,
unsigned offset, int val)
{
struct xr_usb_serial *xr_usb_serial = container_of(chip, struct xr_usb_serial, xr_usb_gpio);
dev_dbg(chip->dev, "xr_usb_gpio_direction_output offset =%d val=%d channel:%d\n",offset,val,xr_usb_serial->channel);
return 0;
}
#endif
static int xr_usb_serial_probe(struct usb_interface *intf, static int xr_usb_serial_probe(struct usb_interface *intf,
const struct usb_device_id *id) const struct usb_device_id *id)
{ {
...@@ -1096,7 +1280,7 @@ static int xr_usb_serial_probe(struct usb_interface *intf, ...@@ -1096,7 +1280,7 @@ static int xr_usb_serial_probe(struct usb_interface *intf,
num_rx_buf = (quirks == SINGLE_RX_URB) ? 1 : XR_USB_SERIAL_NR; num_rx_buf = (quirks == SINGLE_RX_URB) ? 1 : XR_USB_SERIAL_NR;
dev_dbg(&intf->dev, "USB_device_id idVendor:%04x, idProduct %04x\n",id->idVendor,id->idProduct); //dev_dbg(&intf->dev, "USB_device_id idVendor:%04x, idProduct %04x\n",id->idVendor,id->idProduct);
/* handle quirks deadly to normal probing*/ /* handle quirks deadly to normal probing*/
if (quirks == NO_UNION_NORMAL) { if (quirks == NO_UNION_NORMAL) {
...@@ -1337,7 +1521,7 @@ static int xr_usb_serial_probe(struct usb_interface *intf, ...@@ -1337,7 +1521,7 @@ static int xr_usb_serial_probe(struct usb_interface *intf,
} }
#else #else
xr_usb_serial->channel = epwrite->bEndpointAddress; xr_usb_serial->channel = epwrite->bEndpointAddress;
dev_dbg(&intf->dev, "epwrite->bEndpointAddress =%d\n",epwrite->bEndpointAddress); //dev_dbg(&intf->dev, "epwrite->bEndpointAddress =%d\n",epwrite->bEndpointAddress);
#endif #endif
buf = usb_alloc_coherent(usb_dev, ctrlsize, GFP_KERNEL, &xr_usb_serial->ctrl_dma); buf = usb_alloc_coherent(usb_dev, ctrlsize, GFP_KERNEL, &xr_usb_serial->ctrl_dma);
if (!buf) { if (!buf) {
...@@ -1424,14 +1608,9 @@ static int xr_usb_serial_probe(struct usb_interface *intf, ...@@ -1424,14 +1608,9 @@ static int xr_usb_serial_probe(struct usb_interface *intf,
usb_set_intfdata(intf, xr_usb_serial); usb_set_intfdata(intf, xr_usb_serial);
xr_usb_serial->rs485_422_en = false; //default enable rs232
i = device_create_file(&intf->dev, &dev_attr_bRS485_422_en);
if (i < 0)
goto alloc_fail7;
i = device_create_file(&intf->dev, &dev_attr_bmCapabilities); i = device_create_file(&intf->dev, &dev_attr_bmCapabilities);
if (i < 0) if (i < 0)
goto alloc_fail8; goto alloc_fail7;
if (cfd) { /* export the country data */ if (cfd) { /* export the country data */
xr_usb_serial->country_codes = kmalloc(cfd->bLength - 4, GFP_KERNEL); xr_usb_serial->country_codes = kmalloc(cfd->bLength - 4, GFP_KERNEL);
...@@ -1470,7 +1649,7 @@ static int xr_usb_serial_probe(struct usb_interface *intf, ...@@ -1470,7 +1649,7 @@ static int xr_usb_serial_probe(struct usb_interface *intf,
xr_usb_serial->ctrlurb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; xr_usb_serial->ctrlurb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
xr_usb_serial->ctrlurb->transfer_dma = xr_usb_serial->ctrl_dma; xr_usb_serial->ctrlurb->transfer_dma = xr_usb_serial->ctrl_dma;
dev_info(&intf->dev, "ttyXR_USB_SERIAL%d: USB XR_USB_SERIAL device\n", minor); //dev_info(&intf->dev, "ttyXR_USB_SERIAL%d: USB XR_USB_SERIAL device channel:%d\n", minor,xr_usb_serial->channel);
xr_usb_serial_pre_setup(xr_usb_serial); xr_usb_serial_pre_setup(xr_usb_serial);
...@@ -1491,12 +1670,26 @@ static int xr_usb_serial_probe(struct usb_interface *intf, ...@@ -1491,12 +1670,26 @@ static int xr_usb_serial_probe(struct usb_interface *intf,
&control_interface->dev); &control_interface->dev);
if (IS_ERR(tty_dev)) { if (IS_ERR(tty_dev)) {
rv = PTR_ERR(tty_dev); rv = PTR_ERR(tty_dev);
goto alloc_fail9; goto alloc_fail8;
} }
#endif #endif
#ifdef CONFIG_GPIOLIB
/* Setup GPIO cotroller */
xr_usb_serial->xr_usb_gpio.owner = THIS_MODULE;
xr_usb_serial->xr_usb_gpio.dev = &control_interface->dev;
xr_usb_serial->xr_usb_gpio.label = dev_name(&control_interface->dev);
xr_usb_serial->xr_usb_gpio.direction_input = xr_usb_gpio_direction_input;
xr_usb_serial->xr_usb_gpio.get = xr_usb_gpio_get;
xr_usb_serial->xr_usb_gpio.direction_output = xr_usb_gpio_direction_output;
xr_usb_serial->xr_usb_gpio.set = xr_usb_gpio_set;
xr_usb_serial->xr_usb_gpio.base = 100 + xr_usb_serial->channel*10;
xr_usb_serial->xr_usb_gpio.ngpio = 4;
xr_usb_serial->xr_usb_gpio.can_sleep = 1;
rv = gpiochip_add(&xr_usb_serial->xr_usb_gpio);
dev_dbg(&xr_usb_serial->control->dev, "gpiochip_add %d\n",rv);
#endif
return 0; return 0;
alloc_fail9: alloc_fail8:
if (xr_usb_serial->country_codes) { if (xr_usb_serial->country_codes) {
device_remove_file(&xr_usb_serial->control->dev, device_remove_file(&xr_usb_serial->control->dev,
&dev_attr_wCountryCodes); &dev_attr_wCountryCodes);
...@@ -1504,8 +1697,6 @@ static int xr_usb_serial_probe(struct usb_interface *intf, ...@@ -1504,8 +1697,6 @@ static int xr_usb_serial_probe(struct usb_interface *intf,
&dev_attr_iCountryCodeRelDate); &dev_attr_iCountryCodeRelDate);
} }
device_remove_file(&xr_usb_serial->control->dev, &dev_attr_bmCapabilities); device_remove_file(&xr_usb_serial->control->dev, &dev_attr_bmCapabilities);
alloc_fail8:
device_remove_file(&xr_usb_serial->control->dev, &dev_attr_bRS485_422_en);
alloc_fail7: alloc_fail7:
usb_set_intfdata(intf, NULL); usb_set_intfdata(intf, NULL);
for (i = 0; i < XR_USB_SERIAL_NW; i++) for (i = 0; i < XR_USB_SERIAL_NW; i++)
...@@ -1530,7 +1721,7 @@ static void stop_data_traffic(struct xr_usb_serial *xr_usb_serial) ...@@ -1530,7 +1721,7 @@ static void stop_data_traffic(struct xr_usb_serial *xr_usb_serial)
{ {
int i; int i;
dev_dbg(&xr_usb_serial->control->dev, "%s\n", __func__); //dev_dbg(&xr_usb_serial->control->dev, "%s\n", __func__);
usb_kill_urb(xr_usb_serial->ctrlurb); usb_kill_urb(xr_usb_serial->ctrlurb);
for (i = 0; i < XR_USB_SERIAL_NW; i++) for (i = 0; i < XR_USB_SERIAL_NW; i++)
...@@ -1548,7 +1739,7 @@ static void xr_usb_serial_disconnect(struct usb_interface *intf) ...@@ -1548,7 +1739,7 @@ static void xr_usb_serial_disconnect(struct usb_interface *intf)
struct tty_struct *tty; struct tty_struct *tty;
int i; int i;
dev_dbg(&intf->dev, "%s\n", __func__); //dev_dbg(&intf->dev, "%s\n", __func__);
/* sibling interface is already cleaning up */ /* sibling interface is already cleaning up */
if (!xr_usb_serial) if (!xr_usb_serial)
...@@ -1563,7 +1754,6 @@ static void xr_usb_serial_disconnect(struct usb_interface *intf) ...@@ -1563,7 +1754,6 @@ static void xr_usb_serial_disconnect(struct usb_interface *intf)
&dev_attr_iCountryCodeRelDate); &dev_attr_iCountryCodeRelDate);
} }
device_remove_file(&xr_usb_serial->control->dev, &dev_attr_bmCapabilities); device_remove_file(&xr_usb_serial->control->dev, &dev_attr_bmCapabilities);
device_remove_file(&xr_usb_serial->control->dev, &dev_attr_bRS485_422_en);
usb_set_intfdata(xr_usb_serial->control, NULL); usb_set_intfdata(xr_usb_serial->control, NULL);
usb_set_intfdata(xr_usb_serial->data, NULL); usb_set_intfdata(xr_usb_serial->data, NULL);
mutex_unlock(&xr_usb_serial->mutex); mutex_unlock(&xr_usb_serial->mutex);
...@@ -1632,6 +1822,8 @@ static int xr_usb_serial_resume(struct usb_interface *intf) ...@@ -1632,6 +1822,8 @@ static int xr_usb_serial_resume(struct usb_interface *intf)
int rv = 0; int rv = 0;
int cnt; int cnt;
xr_usb_serial_pre_setup(xr_usb_serial);
spin_lock_irq(&xr_usb_serial->read_lock); spin_lock_irq(&xr_usb_serial->read_lock);
xr_usb_serial->susp_count -= 1; xr_usb_serial->susp_count -= 1;
cnt = xr_usb_serial->susp_count; cnt = xr_usb_serial->susp_count;
...@@ -1670,7 +1862,10 @@ static int xr_usb_serial_resume(struct usb_interface *intf) ...@@ -1670,7 +1862,10 @@ static int xr_usb_serial_resume(struct usb_interface *intf)
static int xr_usb_serial_reset_resume(struct usb_interface *intf) static int xr_usb_serial_reset_resume(struct usb_interface *intf)
{ {
struct xr_usb_serial *xr_usb_serial = usb_get_intfdata(intf); struct xr_usb_serial *xr_usb_serial = usb_get_intfdata(intf);
#if LINUX_VERSION_CODE > KERNEL_VERSION(3, 9, 0)
#else
struct tty_struct *tty; struct tty_struct *tty;
#endif
if (test_bit(ASYNCB_INITIALIZED, &xr_usb_serial->port.flags)){ if (test_bit(ASYNCB_INITIALIZED, &xr_usb_serial->port.flags)){
#if LINUX_VERSION_CODE > KERNEL_VERSION(3, 9, 0) #if LINUX_VERSION_CODE > KERNEL_VERSION(3, 9, 0)
tty_port_tty_hangup(&xr_usb_serial->port, false); tty_port_tty_hangup(&xr_usb_serial->port, false);
...@@ -1745,14 +1940,11 @@ static const struct tty_operations xr_usb_serial_ops = { ...@@ -1745,14 +1940,11 @@ static const struct tty_operations xr_usb_serial_ops = {
.tiocmget = xr_usb_serial_tty_tiocmget, .tiocmget = xr_usb_serial_tty_tiocmget,
.tiocmset = xr_usb_serial_tty_tiocmset, .tiocmset = xr_usb_serial_tty_tiocmset,
}; };
/*
* Init / exit.
*/
static int __init xr_usb_serial_init(void) static int __init xr_usb_serial_init(void)
{ {
int retval; int retval;
int i;
xr_usb_serial_tty_driver = alloc_tty_driver(XR_USB_SERIAL_TTY_MINORS); xr_usb_serial_tty_driver = alloc_tty_driver(XR_USB_SERIAL_TTY_MINORS);
if (!xr_usb_serial_tty_driver) if (!xr_usb_serial_tty_driver)
return -ENOMEM; return -ENOMEM;
...@@ -1785,12 +1977,12 @@ static int __init xr_usb_serial_init(void) ...@@ -1785,12 +1977,12 @@ static int __init xr_usb_serial_init(void)
return 0; return 0;
} }
static void __exit xr_usb_serial_exit(void) static void __exit xr_usb_serial_exit(void)
{ {
usb_deregister(&xr_usb_serial_driver); usb_deregister(&xr_usb_serial_driver);
tty_unregister_driver(xr_usb_serial_tty_driver); tty_unregister_driver(xr_usb_serial_tty_driver);
put_tty_driver(xr_usb_serial_tty_driver); put_tty_driver(xr_usb_serial_tty_driver);
} }
module_init(xr_usb_serial_init); module_init(xr_usb_serial_init);
......
...@@ -70,6 +70,11 @@ ...@@ -70,6 +70,11 @@
#define XR_USB_SERIAL_NW 16 #define XR_USB_SERIAL_NW 16
#define XR_USB_SERIAL_NR 16 #define XR_USB_SERIAL_NR 16
#define RAMCTL_BUFFER_PARITY 0x1
#define RAMCTL_BUFFER_BREAK 0x2
#define RAMCTL_BUFFER_FRAME 0x4
#define RAMCTL_BUFFER_OVERRUN 0x8
struct xr_usb_serial_wb { struct xr_usb_serial_wb {
unsigned char *buf; unsigned char *buf;
dma_addr_t dmah; dma_addr_t dmah;
...@@ -144,10 +149,19 @@ struct xr_usb_serial { ...@@ -144,10 +149,19 @@ struct xr_usb_serial {
u8 bInterval; u8 bInterval;
struct xr_usb_serial_wb *delayed_wb; /* write queued for a device about to be woken */ struct xr_usb_serial_wb *delayed_wb; /* write queued for a device about to be woken */
unsigned int channel; unsigned int channel;
int preciseflags; /* USB: wide mode, TTY: flags per character */
int trans9; /* USB: wide mode, serial 9N1 */
int have_extra_byte;
int extra_byte;
unsigned short DeviceVendor; unsigned short DeviceVendor;
unsigned short DeviceProduct; unsigned short DeviceProduct;
#ifdef CONFIG_GPIOLIB
struct gpio_chip xr_usb_gpio;
#endif
struct reg_addr_map reg_map; struct reg_addr_map reg_map;
bool rs485_422_en; int found_smbios_exar_config;
unsigned char channel_config;
}; };
#define CDC_DATA_INTERFACE_TYPE 0x0a #define CDC_DATA_INTERFACE_TYPE 0x0a
......
...@@ -31,7 +31,7 @@ int xr_usb_serial_set_reg(struct xr_usb_serial *xr_usb_serial,int regnum, int va ...@@ -31,7 +31,7 @@ int xr_usb_serial_set_reg(struct xr_usb_serial *xr_usb_serial,int regnum, int va
{ {
int result; int result;
int channel = 0; int channel = 0;
dev_dbg(&xr_usb_serial->control->dev, "%s Channel:%d 0x%02x = 0x%02x\n", __func__,channel,regnum, value); //dev_info(&xr_usb_serial->control->dev, "%s Channel:%d 0x%02x = 0x%02x\n", __func__,channel,regnum, value);
if((xr_usb_serial->DeviceProduct&0xfff0) == 0x1400) if((xr_usb_serial->DeviceProduct&0xfff0) == 0x1400)
{ {
int XR2280xaddr = XR2280x_FUNC_MGR_OFFSET + regnum; int XR2280xaddr = XR2280x_FUNC_MGR_OFFSET + regnum;
...@@ -97,7 +97,7 @@ int xr_usb_serial_set_reg(struct xr_usb_serial *xr_usb_serial,int regnum, int va ...@@ -97,7 +97,7 @@ int xr_usb_serial_set_reg(struct xr_usb_serial *xr_usb_serial,int regnum, int va
result = -1; result = -1;
} }
if(result < 0) if(result < 0)
dev_dbg(&xr_usb_serial->control->dev, "%s Error:%d\n", __func__,result); dev_err(&xr_usb_serial->control->dev, "%s Error:%d\n", __func__,result);
return result; return result;
...@@ -106,7 +106,7 @@ int xr_usb_serial_set_reg_ext(struct xr_usb_serial *xr_usb_serial,int channel,in ...@@ -106,7 +106,7 @@ int xr_usb_serial_set_reg_ext(struct xr_usb_serial *xr_usb_serial,int channel,in
{ {
int result; int result;
int XR2280xaddr = XR2280x_FUNC_MGR_OFFSET + regnum; int XR2280xaddr = XR2280x_FUNC_MGR_OFFSET + regnum;
dev_dbg(&xr_usb_serial->control->dev, "%s channel:%d 0x%02x = 0x%02x\n", __func__,channel,regnum, value); //dev_info(&xr_usb_serial->control->dev, "%s channel:%d 0x%02x = 0x%02x\n", __func__,channel,regnum, value);
if((xr_usb_serial->DeviceProduct&0xfff0) == 0x1400) if((xr_usb_serial->DeviceProduct&0xfff0) == 0x1400)
{ {
result = usb_control_msg(xr_usb_serial->dev, /* usb device */ result = usb_control_msg(xr_usb_serial->dev, /* usb device */
...@@ -165,7 +165,7 @@ int xr_usb_serial_set_reg_ext(struct xr_usb_serial *xr_usb_serial,int channel,in ...@@ -165,7 +165,7 @@ int xr_usb_serial_set_reg_ext(struct xr_usb_serial *xr_usb_serial,int channel,in
result = -1; result = -1;
} }
if(result < 0) if(result < 0)
dev_dbg(&xr_usb_serial->control->dev, "%s Error:%d\n", __func__,result); dev_err(&xr_usb_serial->control->dev, "%s Error:%d\n", __func__,result);
return result; return result;
...@@ -242,9 +242,9 @@ int xr_usb_serial_get_reg(struct xr_usb_serial *xr_usb_serial,int regnum, short ...@@ -242,9 +242,9 @@ int xr_usb_serial_get_reg(struct xr_usb_serial *xr_usb_serial,int regnum, short
} }
if(result < 0) if(result < 0)
dev_dbg(&xr_usb_serial->control->dev, "%s channel:%d Reg 0x%x Error:%d\n", __func__,channel,regnum,result); dev_err(&xr_usb_serial->control->dev, "%s channel:%d Reg 0x%x Error:%d\n", __func__,channel,regnum,result);
else //else
dev_dbg(&xr_usb_serial->control->dev, "%s channel:%d 0x%x = 0x%04x\n", __func__,channel,regnum, *value); //dev_info(&xr_usb_serial->control->dev, "%s channel:%d 0x%x = 0x%04x\n", __func__,channel,regnum, *value);
return result; return result;
...@@ -285,7 +285,7 @@ int xr_usb_serial_get_reg_ext(struct xr_usb_serial *xr_usb_serial,int channel,in ...@@ -285,7 +285,7 @@ int xr_usb_serial_get_reg_ext(struct xr_usb_serial *xr_usb_serial,int channel,in
&reg_value, /* data */ &reg_value, /* data */
1, /* size */ 1, /* size */
5000); /* timeout */ 5000); /* timeout */
dev_dbg(&xr_usb_serial->control->dev, "xr_usb_serial_get_reg_ext reg:%x\n",reg_value); //dev_dbg(&xr_usb_serial->control->dev, "xr_usb_serial_get_reg_ext reg:%x\n",reg_value);
*value = reg_value; *value = reg_value;
} }
else if(xr_usb_serial->DeviceProduct == 0x1411) else if(xr_usb_serial->DeviceProduct == 0x1411)
...@@ -320,9 +320,9 @@ int xr_usb_serial_get_reg_ext(struct xr_usb_serial *xr_usb_serial,int channel,in ...@@ -320,9 +320,9 @@ int xr_usb_serial_get_reg_ext(struct xr_usb_serial *xr_usb_serial,int channel,in
} }
if(result < 0) if(result < 0)
dev_dbg(&xr_usb_serial->control->dev, "%s Error:%d\n", __func__,result); dev_err(&xr_usb_serial->control->dev, "%s Error:%d\n", __func__,result);
else //else
dev_dbg(&xr_usb_serial->control->dev, "%s channel:%d 0x%x = 0x%04x\n", __func__,channel,regnum, *value); //dev_info(&xr_usb_serial->control->dev, "%s channel:%d 0x%x = 0x%04x\n", __func__,channel,regnum, *value);
return result; return result;
...@@ -384,7 +384,7 @@ static int xr21v141x_set_baud_rate(struct xr_usb_serial *xr_usb_serial, unsigned ...@@ -384,7 +384,7 @@ static int xr21v141x_set_baud_rate(struct xr_usb_serial *xr_usb_serial, unsigned
unsigned int tx_mask = xr21v141x_baud_rates[i].tx; unsigned int tx_mask = xr21v141x_baud_rates[i].tx;
unsigned int rx_mask = (divisor & 1) ? xr21v141x_baud_rates[i].rx1 : xr21v141x_baud_rates[i].rx0; unsigned int rx_mask = (divisor & 1) ? xr21v141x_baud_rates[i].rx1 : xr21v141x_baud_rates[i].rx0;
dev_dbg(&xr_usb_serial->control->dev, "Setting baud rate to %d: i=%u div=%u tx=%03x rx=%03x\n", rate, i, divisor, tx_mask, rx_mask); //dev_info(&xr_usb_serial->control->dev, "Setting baud rate to %d: i=%u div=%u tx=%03x rx=%03x\n", rate, i, divisor, tx_mask, rx_mask);
xr_usb_serial_set_reg(xr_usb_serial,UART_CLOCK_DIVISOR_0, (divisor >> 0) & 0xff); xr_usb_serial_set_reg(xr_usb_serial,UART_CLOCK_DIVISOR_0, (divisor >> 0) & 0xff);
xr_usb_serial_set_reg(xr_usb_serial,UART_CLOCK_DIVISOR_1, (divisor >> 8) & 0xff); xr_usb_serial_set_reg(xr_usb_serial,UART_CLOCK_DIVISOR_1, (divisor >> 8) & 0xff);
...@@ -458,7 +458,7 @@ int xr_usb_serial_set_line(struct xr_usb_serial *xr_usb_serial, struct usb_cdc_l ...@@ -458,7 +458,7 @@ int xr_usb_serial_set_line(struct xr_usb_serial *xr_usb_serial, struct usb_cdc_l
if (cflag & CRTSCTS) if (cflag & CRTSCTS)
{ {
dev_dbg(&xr_usb_serial->control->dev, "xr_usb_serial_set_flow_mode:hardware\n"); //dev_dbg(&xr_usb_serial->control->dev, "xr_usb_serial_set_flow_mode:hardware\n");
flow = UART_FLOW_MODE_HW; flow = UART_FLOW_MODE_HW;
gpio_mode = UART_GPIO_MODE_SEL_RTS_CTS; gpio_mode = UART_GPIO_MODE_SEL_RTS_CTS;
} }
...@@ -466,7 +466,7 @@ int xr_usb_serial_set_line(struct xr_usb_serial *xr_usb_serial, struct usb_cdc_l ...@@ -466,7 +466,7 @@ int xr_usb_serial_set_line(struct xr_usb_serial *xr_usb_serial, struct usb_cdc_l
{ {
unsigned char start_char = START_CHAR(tty); unsigned char start_char = START_CHAR(tty);
unsigned char stop_char = STOP_CHAR(tty); unsigned char stop_char = STOP_CHAR(tty);
dev_dbg(&xr_usb_serial->control->dev, "xr_usb_serial_set_flow_mode:software\n"); //dev_dbg(&xr_usb_serial->control->dev, "xr_usb_serial_set_flow_mode:software\n");
flow = UART_FLOW_MODE_SW; flow = UART_FLOW_MODE_SW;
gpio_mode = UART_GPIO_MODE_SEL_GPIO; gpio_mode = UART_GPIO_MODE_SEL_GPIO;
...@@ -475,24 +475,48 @@ int xr_usb_serial_set_line(struct xr_usb_serial *xr_usb_serial, struct usb_cdc_l ...@@ -475,24 +475,48 @@ int xr_usb_serial_set_line(struct xr_usb_serial *xr_usb_serial, struct usb_cdc_l
} }
else else
{ {
dev_dbg(&xr_usb_serial->control->dev, "xr_usb_serial_set_flow_mode:none\n"); //dev_dbg(&xr_usb_serial->control->dev, "xr_usb_serial_set_flow_mode:none\n");
flow = UART_FLOW_MODE_NONE; flow = UART_FLOW_MODE_NONE;
gpio_mode = UART_GPIO_MODE_SEL_GPIO; gpio_mode = UART_GPIO_MODE_SEL_GPIO;
} }
// rs485,rs422 FD/HD mode
if (xr_usb_serial->rs485_422_en) { if((xr_usb_serial->DeviceProduct == 0x1420)||
xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_flow_addr, 0x00); (xr_usb_serial->DeviceProduct == 0x1422)||
xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_gpio_mode_addr, 0x0B); (xr_usb_serial->DeviceProduct == 0x1424))
} else { {//Add support for the TXT and RXT function for 0x1420, 0x1422, 0x1424, by setting GPIO_MODE [9:8] = '11'
//rs232, default mode gpio_mode |= 0x300;
}
if((xr_usb_serial->DeviceProduct == 0x1412)||
(xr_usb_serial->DeviceProduct == 0x1414))
{
if(xr_usb_serial->found_smbios_exar_config)
{
if((xr_usb_serial->channel_config == 2)
||(xr_usb_serial->channel_config == 3))
//if find the exar channel config in the smbios, the value can not be changed by the application
//dev_info(&xr_usb_serial->control->dev, "Sorry, Application can not change the channel gpio&flow mode,because there are config at SMBIOS\n");
return 0;
}
}
xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_flow_addr, flow); xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_flow_addr, flow);
xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_gpio_mode_addr, gpio_mode);
if((xr_usb_serial->found_smbios_exar_config == 1)&&(xr_usb_serial->channel_config == 1))
{
//dev_info(&xr_usb_serial->control->dev, "Sorry, Application can not change the channel gpio mode,because there are config at SMBIOS\n");
} }
else
xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_gpio_mode_addr, gpio_mode);
return 0; return 0;
} }
int xr_usb_serial_send_break(struct xr_usb_serial *xr_usb_serial, int state) int xr_usb_serial_send_break(struct xr_usb_serial *xr_usb_serial, int state)
{ {
int ret = 0; int ret = 0;
...@@ -516,11 +540,17 @@ int xr_usb_serial_send_break(struct xr_usb_serial *xr_usb_serial, int state) ...@@ -516,11 +540,17 @@ int xr_usb_serial_send_break(struct xr_usb_serial *xr_usb_serial, int state)
#define URM_ENABLE_BASE 0x010 #define URM_ENABLE_BASE 0x010
#define URM_ENABLE_0_TX 0x001 #define URM_ENABLE_0_TX 0x001
#define URM_ENABLE_0_RX 0x002 #define URM_ENABLE_0_RX 0x002
#define URM_RESET_RX_FIFO_BASE 0x018
#define URM_RESET_TX_FIFO_BASE 0x01C
int xr_usb_serial_enable(struct xr_usb_serial *xr_usb_serial) int xr_usb_serial_enable(struct xr_usb_serial *xr_usb_serial)
{ {
int ret = 0; int ret = 0;
int channel = xr_usb_serial->channel; int channel = xr_usb_serial->channel;
//dev_info(&xr_usb_serial->control->dev, "xr_usb_serial_enable channel=%d\n",channel);
if(channel) channel--;
if((xr_usb_serial->DeviceProduct == 0x1410)|| if((xr_usb_serial->DeviceProduct == 0x1410)||
(xr_usb_serial->DeviceProduct == 0x1412)|| (xr_usb_serial->DeviceProduct == 0x1412)||
(xr_usb_serial->DeviceProduct == 0x1414)) (xr_usb_serial->DeviceProduct == 0x1414))
...@@ -536,10 +566,31 @@ int xr_usb_serial_enable(struct xr_usb_serial *xr_usb_serial) ...@@ -536,10 +566,31 @@ int xr_usb_serial_enable(struct xr_usb_serial *xr_usb_serial)
return ret; return ret;
} }
int xr_usb_serial_fifo_reset(struct xr_usb_serial *xr_usb_serial)
{
int ret = 0;
int channel = xr_usb_serial->channel;
if(channel) channel--;
if((xr_usb_serial->DeviceProduct == 0x1410)||
(xr_usb_serial->DeviceProduct == 0x1412)||
(xr_usb_serial->DeviceProduct == 0x1414))
{
ret = xr_usb_serial_set_reg_ext(xr_usb_serial,URM_REG_BLOCK,URM_RESET_RX_FIFO_BASE + channel,0xff);
ret |= xr_usb_serial_set_reg_ext(xr_usb_serial,URM_REG_BLOCK,URM_RESET_TX_FIFO_BASE + channel,0xff);
}
return ret;
}
int xr_usb_serial_disable(struct xr_usb_serial *xr_usb_serial) int xr_usb_serial_disable(struct xr_usb_serial *xr_usb_serial)
{ {
int ret = 0; int ret = 0;
int channel = xr_usb_serial->channel; int channel = xr_usb_serial->channel;
//dev_info(&xr_usb_serial->control->dev, "xr_usb_serial_disable channel=%d\n",channel);
if(channel) channel--;
ret = xr_usb_serial_set_reg(xr_usb_serial,xr_usb_serial->reg_map.uart_enable_addr,0); ret = xr_usb_serial_set_reg(xr_usb_serial,xr_usb_serial->reg_map.uart_enable_addr,0);
if((xr_usb_serial->DeviceProduct == 0x1410)|| if((xr_usb_serial->DeviceProduct == 0x1410)||
(xr_usb_serial->DeviceProduct == 0x1412)|| (xr_usb_serial->DeviceProduct == 0x1412)||
...@@ -554,8 +605,77 @@ int xr_usb_serial_set_loopback(struct xr_usb_serial *xr_usb_serial, int channel) ...@@ -554,8 +605,77 @@ int xr_usb_serial_set_loopback(struct xr_usb_serial *xr_usb_serial, int channel)
{ {
int ret = 0; int ret = 0;
xr_usb_serial_disable(xr_usb_serial); xr_usb_serial_disable(xr_usb_serial);
if((xr_usb_serial->DeviceProduct == 0x1410) ||
(xr_usb_serial->DeviceProduct == 0x1412) ||
(xr_usb_serial->DeviceProduct == 0x1414))
{
switch (channel)
{
case 0:
ret = xr_usb_serial_set_reg_ext(xr_usb_serial,channel,
xr_usb_serial->reg_map.uart_loopback_addr,0x40);
break;
case 1:
ret = xr_usb_serial_set_reg_ext(xr_usb_serial,channel,
xr_usb_serial->reg_map.uart_loopback_addr,0x41);
break;
case 2:
ret = xr_usb_serial_set_reg_ext(xr_usb_serial,channel,
xr_usb_serial->reg_map.uart_loopback_addr,0x42);
break;
case 3:
ret = xr_usb_serial_set_reg_ext(xr_usb_serial,channel,
xr_usb_serial->reg_map.uart_loopback_addr,0x43);
break;
default:
break;
}
}
else if((xr_usb_serial->DeviceProduct == 0x1420)||
(xr_usb_serial->DeviceProduct == 0x1422)||
(xr_usb_serial->DeviceProduct == 0x1424))
{
ret = xr_usb_serial_set_reg_ext(xr_usb_serial,channel, ret = xr_usb_serial_set_reg_ext(xr_usb_serial,channel,
xr_usb_serial->reg_map.uart_loopback_addr,0x07); xr_usb_serial->reg_map.uart_loopback_addr,0x07);
}
xr_usb_serial_enable(xr_usb_serial);
return ret;
}
#define XR21V1414_WIDE_MODE_OFFSET 3
#define XR21B142X_WIDE_MODE_TX_OFFSET 0x42
#define XR21B142X_WIDE_MODE_RX_OFFSET 0x45
int xr_usb_serial_set_wide_mode(struct xr_usb_serial *xr_usb_serial, int preciseflags)
{
int ret = 0;
int channel = xr_usb_serial->channel;
xr_usb_serial_disable(xr_usb_serial);
if((xr_usb_serial->DeviceProduct&0xfff0) == 0x1400)
{
}
else if((xr_usb_serial->DeviceProduct == 0x1410)||
(xr_usb_serial->DeviceProduct == 0x1412)||
(xr_usb_serial->DeviceProduct == 0x1414))
{
if(channel) channel--;
xr_usb_serial_set_reg_ext(xr_usb_serial, 0x66, channel*8 + XR21V1414_WIDE_MODE_OFFSET, preciseflags);
}
else if(xr_usb_serial->DeviceProduct == 0x1411)
{
xr_usb_serial_set_reg(xr_usb_serial,0xd02, preciseflags);
}
else if((xr_usb_serial->DeviceProduct == 0x1420)||
(xr_usb_serial->DeviceProduct == 0x1422)||
(xr_usb_serial->DeviceProduct == 0x1424))
{
xr_usb_serial_set_reg(xr_usb_serial, XR21B142X_WIDE_MODE_TX_OFFSET, preciseflags);
xr_usb_serial_set_reg(xr_usb_serial, XR21B142X_WIDE_MODE_RX_OFFSET, preciseflags);
}
xr_usb_serial_enable(xr_usb_serial); xr_usb_serial_enable(xr_usb_serial);
return ret; return ret;
} }
...@@ -567,7 +687,7 @@ static int xr_usb_serial_tiocmget(struct xr_usb_serial *xr_usb_serial) ...@@ -567,7 +687,7 @@ static int xr_usb_serial_tiocmget(struct xr_usb_serial *xr_usb_serial)
short data; short data;
int result; int result;
result = xr_usb_serial_get_reg(xr_usb_serial,xr_usb_serial->reg_map.uart_gpio_status_addr, &data); result = xr_usb_serial_get_reg(xr_usb_serial,xr_usb_serial->reg_map.uart_gpio_status_addr, &data);
dev_dbg(&xr_usb_serial->control->dev, "xr_usb_serial_tiocmget uart_gpio_status_addr:0x%04x\n",data); //dev_info(&xr_usb_serial->control->dev, "xr_usb_serial_tiocmget uart_gpio_status_addr:0x%04x\n",data);
if (result) if (result)
return ((data & 0x8) ? 0: TIOCM_DTR) | ((data & 0x20) ? 0:TIOCM_RTS ) | ((data & 0x4) ? 0:TIOCM_DSR) | ((data & 0x1) ? 0 : TIOCM_RI) | ((data & 0x2) ? 0:TIOCM_CD) | ((data & 0x10) ? 0 : TIOCM_CTS); return ((data & 0x8) ? 0: TIOCM_DTR) | ((data & 0x20) ? 0:TIOCM_RTS ) | ((data & 0x4) ? 0:TIOCM_DSR) | ((data & 0x1) ? 0 : TIOCM_RI) | ((data & 0x2) ? 0:TIOCM_CD) | ((data & 0x10) ? 0 : TIOCM_CTS);
else else
...@@ -675,11 +795,12 @@ static void init_xr21b142x_reg_map(void) ...@@ -675,11 +795,12 @@ static void init_xr21b142x_reg_map(void)
xr21b140x_reg_map.uart_custom_driver = 0x60; xr21b140x_reg_map.uart_custom_driver = 0x60;
xr21b140x_reg_map.uart_low_latency = 0x46; xr21b140x_reg_map.uart_low_latency = 0x46;
} }
int smbios_check_if_have_exar_config(unsigned char *config0,unsigned char *config1);
int xr_usb_serial_pre_setup(struct xr_usb_serial *xr_usb_serial) int xr_usb_serial_pre_setup(struct xr_usb_serial *xr_usb_serial)
{ {
int ret = 0; int ret = 0;
unsigned char channel1_config = 255;
unsigned char channel2_config = 255;
init_xr21b140x_reg_map(); init_xr21b140x_reg_map();
init_xr21b1411_reg_map(); init_xr21b1411_reg_map();
init_xr21v141x_reg_map(); init_xr21v141x_reg_map();
...@@ -716,9 +837,74 @@ int xr_usb_serial_pre_setup(struct xr_usb_serial *xr_usb_serial) ...@@ -716,9 +837,74 @@ int xr_usb_serial_pre_setup(struct xr_usb_serial *xr_usb_serial)
xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_gpio_dir_addr, 0x28); xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_gpio_dir_addr, 0x28);
xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_gpio_set_addr, UART_GPIO_SET_DTR | UART_GPIO_SET_RTS); xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_gpio_set_addr, UART_GPIO_SET_DTR | UART_GPIO_SET_RTS);
return ret; if((xr_usb_serial->DeviceProduct == 0x1412)||
(xr_usb_serial->DeviceProduct == 0x1414))
{
xr_usb_serial->found_smbios_exar_config = 0;
if(smbios_check_if_have_exar_config(&channel1_config,&channel2_config) == 0)
{
} if(xr_usb_serial->channel == 1)
{
xr_usb_serial->found_smbios_exar_config = 1;
xr_usb_serial->channel_config = channel1_config;
switch (channel1_config)
{
case 1://for RS232 Mode
//dev_info(&xr_usb_serial->control->dev, "SMBIOS Set Channel Mode to RS232\n");
xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_gpio_mode_addr, 0);
break;
case 2://RS-485 HALF DUPLEX
//dev_info(&xr_usb_serial->control->dev, "SMBIOS Set Channel Mode to RS-485 HALF DUPLEX\n");
xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_gpio_mode_addr, 0x0b);
xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_flow_addr, 0x00);
break;
case 3://RS-485/422 FULL DUPLEX
//dev_info(&xr_usb_serial->control->dev, "SMBIOS Set Channel Mode to RS-485/422 FULL DUPLEX\n");
xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_gpio_mode_addr, 0x0b);
xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_flow_addr, 0x00);
break;
default:
xr_usb_serial->found_smbios_exar_config = 0;
break;
}
}
else if(xr_usb_serial->channel == 2)
{
xr_usb_serial->found_smbios_exar_config = 1;
xr_usb_serial->channel_config = channel2_config;
switch (channel2_config)
{
case 1://for RS232 Mode
//dev_info(&xr_usb_serial->control->dev, "SMBIOS Set Channel Mode to RS232\n");
xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_gpio_mode_addr, 0);
break;
case 2://RS-485 HALF DUPLEX
//dev_info(&xr_usb_serial->control->dev, "SMBIOS Set Channel Mode to RS-485 HALF DUPLEX\n");
xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_gpio_mode_addr, 0x0b);
xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_flow_addr, 0x00);
break;
case 3://RS-485/422 FULL DUPLEX
//dev_info(&xr_usb_serial->control->dev, "SMBIOS Set Channel Mode to RS-485/422 FULL DUPLEX\n");
xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_gpio_mode_addr, 0x0b);
xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_flow_addr, 0x00);
break;
default:
xr_usb_serial->found_smbios_exar_config = 0;
break;
}
}
else
{
//Nothing to do
}
}
}
return ret;
}
...@@ -24,6 +24,13 @@ ...@@ -24,6 +24,13 @@
#define XR_USB_SERIAL_SET_PRECISE_FLAGS _IO(XR_USB_SERIAL_IOC_MAGIC, 4) #define XR_USB_SERIAL_SET_PRECISE_FLAGS _IO(XR_USB_SERIAL_IOC_MAGIC, 4)
#define XR_USB_SERIAL_TEST_MODE _IO(XR_USB_SERIAL_IOC_MAGIC, 5) #define XR_USB_SERIAL_TEST_MODE _IO(XR_USB_SERIAL_IOC_MAGIC, 5)
#define XR_USB_SERIAL_LOOPBACK _IO(XR_USB_SERIAL_IOC_MAGIC, 6) #define XR_USB_SERIAL_LOOPBACK _IO(XR_USB_SERIAL_IOC_MAGIC, 6)
#define XR_USB_SERIAL_SET_GPIO_MODE_REG _IO(XR_USB_SERIAL_IOC_MAGIC, 9)
#define XR_USB_SERIAL_GET_GPIO_MODE_REG _IO(XR_USB_SERIAL_IOC_MAGIC, 10)
#define XRIOC_SET_ANY_BAUD_RATE _IO(XR_USB_SERIAL_IOC_MAGIC, 11)
#define XRIOC_SET_PRECISE_FLAGS _IO(XR_USB_SERIAL_IOC_MAGIC, 12)
#define VZ_ADDRESS_UNICAST_S 0 #define VZ_ADDRESS_UNICAST_S 0
#define VZ_ADDRESS_BROADCAST_S 8 #define VZ_ADDRESS_BROADCAST_S 8
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment