Commit 20eda943 authored by Olivier Bornet's avatar Olivier Bornet Committed by Greg Kroah-Hartman

USB: iuu_phoenix: add support for changing VCC

You can now set the IUU reader to 3.3V VCC instead of 5V VCC, using the sysfs
parameter vcc_mode. Valid values are 3 and 5.
Signed-off-by: default avatarOlivier Bornet <Olivier.Bornet@puck.ch>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 8844a32d
...@@ -79,6 +79,7 @@ struct iuu_private { ...@@ -79,6 +79,7 @@ struct iuu_private {
u8 *buf; /* used for initialize speed */ u8 *buf; /* used for initialize speed */
u8 *dbgbuf; /* debug buffer */ u8 *dbgbuf; /* debug buffer */
u8 len; u8 len;
int vcc; /* vcc (either 3 or 5 V) */
}; };
...@@ -114,6 +115,7 @@ static int iuu_startup(struct usb_serial *serial) ...@@ -114,6 +115,7 @@ static int iuu_startup(struct usb_serial *serial)
kfree(priv); kfree(priv);
return -ENOMEM; return -ENOMEM;
} }
priv->vcc = 5; /* 5 V for vcc by default */
spin_lock_init(&priv->lock); spin_lock_init(&priv->lock);
init_waitqueue_head(&priv->delta_msr_wait); init_waitqueue_head(&priv->delta_msr_wait);
usb_set_serial_port_data(serial->port[0], priv); usb_set_serial_port_data(serial->port[0], priv);
...@@ -1178,6 +1180,95 @@ static int iuu_open(struct tty_struct *tty, struct usb_serial_port *port) ...@@ -1178,6 +1180,95 @@ static int iuu_open(struct tty_struct *tty, struct usb_serial_port *port)
return result; return result;
} }
/* how to change VCC */
static int iuu_vcc_set(struct usb_serial_port *port, unsigned int vcc)
{
int status;
u8 *buf;
buf = kmalloc(5, GFP_KERNEL);
if (!buf)
return -ENOMEM;
dbg("%s - enter", __func__);
buf[0] = IUU_SET_VCC;
buf[1] = vcc & 0xFF;
buf[2] = (vcc >> 8) & 0xFF;
buf[3] = (vcc >> 16) & 0xFF;
buf[4] = (vcc >> 24) & 0xFF;
status = bulk_immediate(port, buf, 5);
kfree(buf);
if (status != IUU_OPERATION_OK)
dbg("%s - vcc error status = %2x", __func__, status);
else
dbg("%s - vcc OK !", __func__);
return status;
}
/*
* Sysfs Attributes
*/
static ssize_t show_vcc_mode(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct usb_serial_port *port = to_usb_serial_port(dev);
struct iuu_private *priv = usb_get_serial_port_data(port);
return sprintf(buf, "%d\n", priv->vcc);
}
static ssize_t store_vcc_mode(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct usb_serial_port *port = to_usb_serial_port(dev);
struct iuu_private *priv = usb_get_serial_port_data(port);
unsigned long v;
if (strict_strtoul(buf, 10, &v)) {
dev_err(dev, "%s - vcc_mode: %s is not a unsigned long\n",
__func__, buf);
goto fail_store_vcc_mode;
}
dbg("%s: setting vcc_mode = %ld", __func__, v);
if ((v != 3) && (v != 5)) {
dev_err(dev, "%s - vcc_mode %ld is invalid\n", __func__, v);
} else {
iuu_vcc_set(port, v);
priv->vcc = v;
}
fail_store_vcc_mode:
return count;
}
static DEVICE_ATTR(vcc_mode, S_IRUSR | S_IWUSR, show_vcc_mode,
store_vcc_mode);
static int iuu_create_sysfs_attrs(struct usb_serial_port *port)
{
dbg("%s", __func__);
return device_create_file(&port->dev, &dev_attr_vcc_mode);
}
static int iuu_remove_sysfs_attrs(struct usb_serial_port *port)
{
dbg("%s", __func__);
device_remove_file(&port->dev, &dev_attr_vcc_mode);
return 0;
}
/*
* End Sysfs Attributes
*/
static struct usb_serial_driver iuu_device = { static struct usb_serial_driver iuu_device = {
.driver = { .driver = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
...@@ -1185,6 +1276,8 @@ static struct usb_serial_driver iuu_device = { ...@@ -1185,6 +1276,8 @@ static struct usb_serial_driver iuu_device = {
}, },
.id_table = id_table, .id_table = id_table,
.num_ports = 1, .num_ports = 1,
.port_probe = iuu_create_sysfs_attrs,
.port_remove = iuu_remove_sysfs_attrs,
.open = iuu_open, .open = iuu_open,
.close = iuu_close, .close = iuu_close,
.write = iuu_uart_write, .write = iuu_uart_write,
......
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