diff options
Diffstat (limited to 'drivers/usb/serial/iuu_phoenix.c')
-rw-r--r-- | drivers/usb/serial/iuu_phoenix.c | 115 |
1 files changed, 105 insertions, 10 deletions
diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index 6138c1cda35f..e6e02b178d2b 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c | |||
@@ -40,7 +40,7 @@ static int debug; | |||
40 | /* | 40 | /* |
41 | * Version Information | 41 | * Version Information |
42 | */ | 42 | */ |
43 | #define DRIVER_VERSION "v0.10" | 43 | #define DRIVER_VERSION "v0.11" |
44 | #define DRIVER_DESC "Infinity USB Unlimited Phoenix driver" | 44 | #define DRIVER_DESC "Infinity USB Unlimited Phoenix driver" |
45 | 45 | ||
46 | static struct usb_device_id id_table[] = { | 46 | static struct usb_device_id id_table[] = { |
@@ -64,6 +64,7 @@ static int cdmode = 1; | |||
64 | static int iuu_cardin; | 64 | static int iuu_cardin; |
65 | static int iuu_cardout; | 65 | static int iuu_cardout; |
66 | static int xmas; | 66 | static int xmas; |
67 | static int vcc_default = 5; | ||
67 | 68 | ||
68 | static void read_rxcmd_callback(struct urb *urb); | 69 | static void read_rxcmd_callback(struct urb *urb); |
69 | 70 | ||
@@ -79,6 +80,7 @@ struct iuu_private { | |||
79 | u8 *buf; /* used for initialize speed */ | 80 | u8 *buf; /* used for initialize speed */ |
80 | u8 *dbgbuf; /* debug buffer */ | 81 | u8 *dbgbuf; /* debug buffer */ |
81 | u8 len; | 82 | u8 len; |
83 | int vcc; /* vcc (either 3 or 5 V) */ | ||
82 | }; | 84 | }; |
83 | 85 | ||
84 | 86 | ||
@@ -114,6 +116,7 @@ static int iuu_startup(struct usb_serial *serial) | |||
114 | kfree(priv); | 116 | kfree(priv); |
115 | return -ENOMEM; | 117 | return -ENOMEM; |
116 | } | 118 | } |
119 | priv->vcc = vcc_default; | ||
117 | spin_lock_init(&priv->lock); | 120 | spin_lock_init(&priv->lock); |
118 | init_waitqueue_head(&priv->delta_msr_wait); | 121 | init_waitqueue_head(&priv->delta_msr_wait); |
119 | usb_set_serial_port_data(serial->port[0], priv); | 122 | usb_set_serial_port_data(serial->port[0], priv); |
@@ -1009,11 +1012,7 @@ static void iuu_close(struct usb_serial_port *port) | |||
1009 | usb_kill_urb(port->write_urb); | 1012 | usb_kill_urb(port->write_urb); |
1010 | usb_kill_urb(port->read_urb); | 1013 | usb_kill_urb(port->read_urb); |
1011 | usb_kill_urb(port->interrupt_in_urb); | 1014 | usb_kill_urb(port->interrupt_in_urb); |
1012 | msleep(1000); | ||
1013 | /* wait one second to free all buffers */ | ||
1014 | iuu_led(port, 0, 0, 0xF000, 0xFF); | 1015 | iuu_led(port, 0, 0, 0xF000, 0xFF); |
1015 | msleep(1000); | ||
1016 | usb_reset_device(port->serial->dev); | ||
1017 | } | 1016 | } |
1018 | } | 1017 | } |
1019 | 1018 | ||
@@ -1182,6 +1181,95 @@ static int iuu_open(struct tty_struct *tty, struct usb_serial_port *port) | |||
1182 | return result; | 1181 | return result; |
1183 | } | 1182 | } |
1184 | 1183 | ||
1184 | /* how to change VCC */ | ||
1185 | static int iuu_vcc_set(struct usb_serial_port *port, unsigned int vcc) | ||
1186 | { | ||
1187 | int status; | ||
1188 | u8 *buf; | ||
1189 | |||
1190 | buf = kmalloc(5, GFP_KERNEL); | ||
1191 | if (!buf) | ||
1192 | return -ENOMEM; | ||
1193 | |||
1194 | dbg("%s - enter", __func__); | ||
1195 | |||
1196 | buf[0] = IUU_SET_VCC; | ||
1197 | buf[1] = vcc & 0xFF; | ||
1198 | buf[2] = (vcc >> 8) & 0xFF; | ||
1199 | buf[3] = (vcc >> 16) & 0xFF; | ||
1200 | buf[4] = (vcc >> 24) & 0xFF; | ||
1201 | |||
1202 | status = bulk_immediate(port, buf, 5); | ||
1203 | kfree(buf); | ||
1204 | |||
1205 | if (status != IUU_OPERATION_OK) | ||
1206 | dbg("%s - vcc error status = %2x", __func__, status); | ||
1207 | else | ||
1208 | dbg("%s - vcc OK !", __func__); | ||
1209 | |||
1210 | return status; | ||
1211 | } | ||
1212 | |||
1213 | /* | ||
1214 | * Sysfs Attributes | ||
1215 | */ | ||
1216 | |||
1217 | static ssize_t show_vcc_mode(struct device *dev, | ||
1218 | struct device_attribute *attr, char *buf) | ||
1219 | { | ||
1220 | struct usb_serial_port *port = to_usb_serial_port(dev); | ||
1221 | struct iuu_private *priv = usb_get_serial_port_data(port); | ||
1222 | |||
1223 | return sprintf(buf, "%d\n", priv->vcc); | ||
1224 | } | ||
1225 | |||
1226 | static ssize_t store_vcc_mode(struct device *dev, | ||
1227 | struct device_attribute *attr, const char *buf, size_t count) | ||
1228 | { | ||
1229 | struct usb_serial_port *port = to_usb_serial_port(dev); | ||
1230 | struct iuu_private *priv = usb_get_serial_port_data(port); | ||
1231 | unsigned long v; | ||
1232 | |||
1233 | if (strict_strtoul(buf, 10, &v)) { | ||
1234 | dev_err(dev, "%s - vcc_mode: %s is not a unsigned long\n", | ||
1235 | __func__, buf); | ||
1236 | goto fail_store_vcc_mode; | ||
1237 | } | ||
1238 | |||
1239 | dbg("%s: setting vcc_mode = %ld", __func__, v); | ||
1240 | |||
1241 | if ((v != 3) && (v != 5)) { | ||
1242 | dev_err(dev, "%s - vcc_mode %ld is invalid\n", __func__, v); | ||
1243 | } else { | ||
1244 | iuu_vcc_set(port, v); | ||
1245 | priv->vcc = v; | ||
1246 | } | ||
1247 | fail_store_vcc_mode: | ||
1248 | return count; | ||
1249 | } | ||
1250 | |||
1251 | static DEVICE_ATTR(vcc_mode, S_IRUSR | S_IWUSR, show_vcc_mode, | ||
1252 | store_vcc_mode); | ||
1253 | |||
1254 | static int iuu_create_sysfs_attrs(struct usb_serial_port *port) | ||
1255 | { | ||
1256 | dbg("%s", __func__); | ||
1257 | |||
1258 | return device_create_file(&port->dev, &dev_attr_vcc_mode); | ||
1259 | } | ||
1260 | |||
1261 | static int iuu_remove_sysfs_attrs(struct usb_serial_port *port) | ||
1262 | { | ||
1263 | dbg("%s", __func__); | ||
1264 | |||
1265 | device_remove_file(&port->dev, &dev_attr_vcc_mode); | ||
1266 | return 0; | ||
1267 | } | ||
1268 | |||
1269 | /* | ||
1270 | * End Sysfs Attributes | ||
1271 | */ | ||
1272 | |||
1185 | static struct usb_serial_driver iuu_device = { | 1273 | static struct usb_serial_driver iuu_device = { |
1186 | .driver = { | 1274 | .driver = { |
1187 | .owner = THIS_MODULE, | 1275 | .owner = THIS_MODULE, |
@@ -1189,6 +1277,8 @@ static struct usb_serial_driver iuu_device = { | |||
1189 | }, | 1277 | }, |
1190 | .id_table = id_table, | 1278 | .id_table = id_table, |
1191 | .num_ports = 1, | 1279 | .num_ports = 1, |
1280 | .port_probe = iuu_create_sysfs_attrs, | ||
1281 | .port_remove = iuu_remove_sysfs_attrs, | ||
1192 | .open = iuu_open, | 1282 | .open = iuu_open, |
1193 | .close = iuu_close, | 1283 | .close = iuu_close, |
1194 | .write = iuu_uart_write, | 1284 | .write = iuu_uart_write, |
@@ -1238,14 +1328,19 @@ module_param(debug, bool, S_IRUGO | S_IWUSR); | |||
1238 | MODULE_PARM_DESC(debug, "Debug enabled or not"); | 1328 | MODULE_PARM_DESC(debug, "Debug enabled or not"); |
1239 | 1329 | ||
1240 | module_param(xmas, bool, S_IRUGO | S_IWUSR); | 1330 | module_param(xmas, bool, S_IRUGO | S_IWUSR); |
1241 | MODULE_PARM_DESC(xmas, "xmas color enabled or not"); | 1331 | MODULE_PARM_DESC(xmas, "Xmas colors enabled or not"); |
1242 | 1332 | ||
1243 | module_param(boost, int, S_IRUGO | S_IWUSR); | 1333 | module_param(boost, int, S_IRUGO | S_IWUSR); |
1244 | MODULE_PARM_DESC(boost, "overclock boost percent 100 to 500"); | 1334 | MODULE_PARM_DESC(boost, "Card overclock boost (in percent 100-500)"); |
1245 | 1335 | ||
1246 | module_param(clockmode, int, S_IRUGO | S_IWUSR); | 1336 | module_param(clockmode, int, S_IRUGO | S_IWUSR); |
1247 | MODULE_PARM_DESC(clockmode, "1=3Mhz579,2=3Mhz680,3=6Mhz"); | 1337 | MODULE_PARM_DESC(clockmode, "Card clock mode (1=3.579 MHz, 2=3.680 MHz, " |
1338 | "3=6 Mhz)"); | ||
1248 | 1339 | ||
1249 | module_param(cdmode, int, S_IRUGO | S_IWUSR); | 1340 | module_param(cdmode, int, S_IRUGO | S_IWUSR); |
1250 | MODULE_PARM_DESC(cdmode, "Card detect mode 0=none, 1=CD, 2=!CD, 3=DSR, " | 1341 | MODULE_PARM_DESC(cdmode, "Card detect mode (0=none, 1=CD, 2=!CD, 3=DSR, " |
1251 | "4=!DSR, 5=CTS, 6=!CTS, 7=RING, 8=!RING"); | 1342 | "4=!DSR, 5=CTS, 6=!CTS, 7=RING, 8=!RING)"); |
1343 | |||
1344 | module_param(vcc_default, int, S_IRUGO | S_IWUSR); | ||
1345 | MODULE_PARM_DESC(vcc_default, "Set default VCC (either 3 for 3.3V or 5 " | ||
1346 | "for 5V). Default to 5."); | ||