aboutsummaryrefslogtreecommitdiff
path: root/drivers/usb/misc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/misc')
-rw-r--r--drivers/usb/misc/appledisplay.c13
-rw-r--r--drivers/usb/misc/usb3503.c59
-rw-r--r--drivers/usb/misc/usbtest.c29
-rw-r--r--drivers/usb/misc/yurex.c3
4 files changed, 96 insertions, 8 deletions
diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c
index f37c78d1bdf..b3d245ef46e 100644
--- a/drivers/usb/misc/appledisplay.c
+++ b/drivers/usb/misc/appledisplay.c
@@ -81,6 +81,7 @@ struct appledisplay {
struct delayed_work work;
int button_pressed;
spinlock_t lock;
+ struct mutex sysfslock; /* concurrent read and write */
};
static atomic_t count_displays = ATOMIC_INIT(0);
@@ -144,6 +145,7 @@ static int appledisplay_bl_update_status(struct backlight_device *bd)
struct appledisplay *pdata = bl_get_data(bd);
int retval;
+ mutex_lock(&pdata->sysfslock);
pdata->msgdata[0] = 0x10;
pdata->msgdata[1] = bd->props.brightness;
@@ -156,15 +158,17 @@ static int appledisplay_bl_update_status(struct backlight_device *bd)
0,
pdata->msgdata, 2,
ACD_USB_TIMEOUT);
-
+ mutex_unlock(&pdata->sysfslock);
+
return retval;
}
static int appledisplay_bl_get_brightness(struct backlight_device *bd)
{
struct appledisplay *pdata = bl_get_data(bd);
- int retval;
+ int retval, brightness;
+ mutex_lock(&pdata->sysfslock);
retval = usb_control_msg(
pdata->udev,
usb_rcvctrlpipe(pdata->udev, 0),
@@ -174,11 +178,13 @@ static int appledisplay_bl_get_brightness(struct backlight_device *bd)
0,
pdata->msgdata, 2,
ACD_USB_TIMEOUT);
+ brightness = pdata->msgdata[1];
+ mutex_unlock(&pdata->sysfslock);
if (retval < 0)
return retval;
else
- return pdata->msgdata[1];
+ return brightness;
}
static const struct backlight_ops appledisplay_bl_data = {
@@ -241,6 +247,7 @@ static int appledisplay_probe(struct usb_interface *iface,
spin_lock_init(&pdata->lock);
INIT_DELAYED_WORK(&pdata->work, appledisplay_work);
+ mutex_init(&pdata->sysfslock);
/* Allocate buffer for control messages */
pdata->msgdata = kmalloc(ACD_MSG_BUFFER_LEN, GFP_KERNEL);
diff --git a/drivers/usb/misc/usb3503.c b/drivers/usb/misc/usb3503.c
index a31641e18d1..f43c61989ce 100644
--- a/drivers/usb/misc/usb3503.c
+++ b/drivers/usb/misc/usb3503.c
@@ -18,6 +18,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <linux/clk.h>
#include <linux/i2c.h>
#include <linux/gpio.h>
#include <linux/delay.h>
@@ -57,10 +58,12 @@ struct usb3503 {
enum usb3503_mode mode;
struct regmap *regmap;
struct device *dev;
+ struct clk *clk;
u8 port_off_mask;
int gpio_intn;
int gpio_reset;
int gpio_connect;
+ bool secondary_ref_clk;
};
static int usb3503_reset(struct usb3503 *hub, int state)
@@ -184,8 +187,58 @@ static int usb3503_probe(struct usb3503 *hub)
hub->gpio_reset = pdata->gpio_reset;
hub->mode = pdata->initial_mode;
} else if (np) {
+ struct clk *clk;
hub->port_off_mask = 0;
+ clk = devm_clk_get(dev, "refclk");
+ if (IS_ERR(clk) && PTR_ERR(clk) != -ENOENT) {
+ dev_err(dev, "unable to request refclk (%d)\n", err);
+ return PTR_ERR(clk);
+ }
+
+ if (!IS_ERR(clk)) {
+ u32 rate = 0;
+ hub->clk = clk;
+
+ if (!of_property_read_u32(np, "refclk-frequency",
+ &rate)) {
+
+ switch (rate) {
+ case 38400000:
+ case 26000000:
+ case 19200000:
+ case 12000000:
+ hub->secondary_ref_clk = 0;
+ break;
+ case 24000000:
+ case 27000000:
+ case 25000000:
+ case 50000000:
+ hub->secondary_ref_clk = 1;
+ break;
+ default:
+ dev_err(dev,
+ "unsupported reference clock rate (%d)\n",
+ (int) rate);
+ return -EINVAL;
+ }
+ err = clk_set_rate(hub->clk, rate);
+ if (err) {
+ dev_err(dev,
+ "unable to set reference clock rate to %d\n",
+ (int) rate);
+ return err;
+ }
+ }
+
+ err = clk_prepare_enable(hub->clk);
+ if (err) {
+ dev_err(dev,
+ "unable to enable reference clock\n");
+ return err;
+ }
+ }
+
property = of_get_property(np, "disabled-ports", &len);
if (property && (len / sizeof(u32)) > 0) {
int i;
@@ -213,8 +266,10 @@ static int usb3503_probe(struct usb3503 *hub)
dev_err(dev, "Ports disabled with no control interface\n");
if (gpio_is_valid(hub->gpio_intn)) {
- err = devm_gpio_request_one(dev, hub->gpio_intn,
- GPIOF_OUT_INIT_HIGH, "usb3503 intn");
+ int val = hub->secondary_ref_clk ? GPIOF_OUT_INIT_LOW :
+ GPIOF_OUT_INIT_HIGH;
+ err = devm_gpio_request_one(dev, hub->gpio_intn, val,
+ "usb3503 intn");
if (err) {
dev_err(dev,
"unable to request GPIO %d as connect pin (%d)\n",
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index f6568b5e9b0..829f446064e 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -7,7 +7,7 @@
#include <linux/moduleparam.h>
#include <linux/scatterlist.h>
#include <linux/mutex.h>
-
+#include <linux/timer.h>
#include <linux/usb.h>
#define SIMPLE_IO_TIMEOUT 10000 /* in milliseconds */
@@ -484,6 +484,14 @@ alloc_sglist(int nents, int max, int vary)
return sg;
}
+static void sg_timeout(unsigned long _req)
+{
+ struct usb_sg_request *req = (struct usb_sg_request *) _req;
+
+ req->status = -ETIMEDOUT;
+ usb_sg_cancel(req);
+}
+
static int perform_sglist(
struct usbtest_dev *tdev,
unsigned iterations,
@@ -495,6 +503,9 @@ static int perform_sglist(
{
struct usb_device *udev = testdev_to_usbdev(tdev);
int retval = 0;
+ struct timer_list sg_timer;
+
+ setup_timer_on_stack(&sg_timer, sg_timeout, (unsigned long) req);
while (retval == 0 && iterations-- > 0) {
retval = usb_sg_init(req, udev, pipe,
@@ -505,7 +516,10 @@ static int perform_sglist(
if (retval)
break;
+ mod_timer(&sg_timer, jiffies +
+ msecs_to_jiffies(SIMPLE_IO_TIMEOUT));
usb_sg_wait(req);
+ del_timer_sync(&sg_timer);
retval = req->status;
/* FIXME check resulting data pattern */
@@ -1320,6 +1334,11 @@ static int unlink1(struct usbtest_dev *dev, int pipe, int size, int async)
urb->context = &completion;
urb->complete = unlink1_callback;
+ if (usb_pipeout(urb->pipe)) {
+ simple_fill_buf(urb);
+ urb->transfer_flags |= URB_ZERO_PACKET;
+ }
+
/* keep the endpoint busy. there are lots of hc/hcd-internal
* states, and testing should get to all of them over time.
*
@@ -1340,6 +1359,9 @@ static int unlink1(struct usbtest_dev *dev, int pipe, int size, int async)
while (!completion_done(&completion)) {
retval = usb_unlink_urb(urb);
+ if (retval == 0 && usb_pipein(urb->pipe))
+ retval = simple_check_buf(dev, urb);
+
switch (retval) {
case -EBUSY:
case -EIDRM:
@@ -1450,6 +1472,11 @@ static int unlink_queued(struct usbtest_dev *dev, int pipe, unsigned num,
unlink_queued_callback, &ctx);
ctx.urbs[i]->transfer_dma = buf_dma;
ctx.urbs[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
+
+ if (usb_pipeout(ctx.urbs[i]->pipe)) {
+ simple_fill_buf(ctx.urbs[i]);
+ ctx.urbs[i]->transfer_flags |= URB_ZERO_PACKET;
+ }
}
/* Submit all the URBs and then unlink URBs num - 4 and num - 2. */
diff --git a/drivers/usb/misc/yurex.c b/drivers/usb/misc/yurex.c
index 24278208bf7..1472805083d 100644
--- a/drivers/usb/misc/yurex.c
+++ b/drivers/usb/misc/yurex.c
@@ -296,6 +296,7 @@ static int yurex_probe(struct usb_interface *interface, const struct usb_device_
/* save our data pointer in this interface device */
usb_set_intfdata(interface, dev);
+ dev->bbu = -1;
/* we can register the device now, as it is ready */
retval = usb_register_dev(interface, &yurex_class);
@@ -306,8 +307,6 @@ static int yurex_probe(struct usb_interface *interface, const struct usb_device_
goto error;
}
- dev->bbu = -1;
-
dev_info(&interface->dev,
"USB YUREX device now attached to Yurex #%d\n",
interface->minor);