diff options
| author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-22 10:38:37 -0500 |
|---|---|---|
| committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-22 10:38:37 -0500 |
| commit | fcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (patch) | |
| tree | a57612d1888735a2ec7972891b68c1ac5ec8faea /drivers/usb | |
| parent | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff) | |
Diffstat (limited to 'drivers/usb')
39 files changed, 25590 insertions, 0 deletions
diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c new file mode 100644 index 00000000000..2278dad886e --- /dev/null +++ b/drivers/usb/core/inode.c | |||
| @@ -0,0 +1,776 @@ | |||
| 1 | /*****************************************************************************/ | ||
| 2 | |||
| 3 | /* | ||
| 4 | * inode.c -- Inode/Dentry functions for the USB device file system. | ||
| 5 | * | ||
| 6 | * Copyright (C) 2000 Thomas Sailer (sailer@ife.ee.ethz.ch) | ||
| 7 | * Copyright (C) 2001,2002,2004 Greg Kroah-Hartman (greg@kroah.com) | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify | ||
| 10 | * it under the terms of the GNU General Public License as published by | ||
| 11 | * the Free Software Foundation; either version 2 of the License, or | ||
| 12 | * (at your option) any later version. | ||
| 13 | * | ||
| 14 | * This program is distributed in the hope that it will be useful, | ||
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | * GNU General Public License for more details. | ||
| 18 | * | ||
| 19 | * You should have received a copy of the GNU General Public License | ||
| 20 | * along with this program; if not, write to the Free Software | ||
| 21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 22 | * | ||
| 23 | * History: | ||
| 24 | * 0.1 04.01.2000 Created | ||
| 25 | * 0.2 10.12.2001 converted to use the vfs layer better | ||
| 26 | */ | ||
| 27 | |||
| 28 | /*****************************************************************************/ | ||
| 29 | |||
| 30 | #include <linux/module.h> | ||
| 31 | #include <linux/fs.h> | ||
| 32 | #include <linux/mount.h> | ||
| 33 | #include <linux/pagemap.h> | ||
| 34 | #include <linux/init.h> | ||
| 35 | #include <linux/proc_fs.h> | ||
| 36 | #include <linux/usb.h> | ||
| 37 | #include <linux/namei.h> | ||
| 38 | #include <linux/usbdevice_fs.h> | ||
| 39 | #include <linux/parser.h> | ||
| 40 | #include <linux/notifier.h> | ||
| 41 | #include <linux/seq_file.h> | ||
| 42 | #include <linux/usb/hcd.h> | ||
| 43 | #include <asm/byteorder.h> | ||
| 44 | #include "usb.h" | ||
| 45 | |||
| 46 | #define USBFS_DEFAULT_DEVMODE (S_IWUSR | S_IRUGO) | ||
| 47 | #define USBFS_DEFAULT_BUSMODE (S_IXUGO | S_IRUGO) | ||
| 48 | #define USBFS_DEFAULT_LISTMODE S_IRUGO | ||
| 49 | |||
| 50 | static const struct file_operations default_file_operations; | ||
| 51 | static struct vfsmount *usbfs_mount; | ||
| 52 | static int usbfs_mount_count; /* = 0 */ | ||
| 53 | static int ignore_mount = 0; | ||
| 54 | |||
| 55 | static struct dentry *devices_usbfs_dentry; | ||
| 56 | static int num_buses; /* = 0 */ | ||
| 57 | |||
| 58 | static uid_t devuid; /* = 0 */ | ||
| 59 | static uid_t busuid; /* = 0 */ | ||
| 60 | static uid_t listuid; /* = 0 */ | ||
| 61 | static gid_t devgid; /* = 0 */ | ||
| 62 | static gid_t busgid; /* = 0 */ | ||
| 63 | static gid_t listgid; /* = 0 */ | ||
| 64 | static umode_t devmode = USBFS_DEFAULT_DEVMODE; | ||
| 65 | static umode_t busmode = USBFS_DEFAULT_BUSMODE; | ||
| 66 | static umode_t listmode = USBFS_DEFAULT_LISTMODE; | ||
| 67 | |||
| 68 | static int usbfs_show_options(struct seq_file *seq, struct vfsmount *mnt) | ||
| 69 | { | ||
| 70 | if (devuid != 0) | ||
| 71 | seq_printf(seq, ",devuid=%u", devuid); | ||
| 72 | if (devgid != 0) | ||
| 73 | seq_printf(seq, ",devgid=%u", devgid); | ||
| 74 | if (devmode != USBFS_DEFAULT_DEVMODE) | ||
| 75 | seq_printf(seq, ",devmode=%o", devmode); | ||
| 76 | if (busuid != 0) | ||
| 77 | seq_printf(seq, ",busuid=%u", busuid); | ||
| 78 | if (busgid != 0) | ||
| 79 | seq_printf(seq, ",busgid=%u", busgid); | ||
| 80 | if (busmode != USBFS_DEFAULT_BUSMODE) | ||
| 81 | seq_printf(seq, ",busmode=%o", busmode); | ||
| 82 | if (listuid != 0) | ||
| 83 | seq_printf(seq, ",listuid=%u", listuid); | ||
| 84 | if (listgid != 0) | ||
| 85 | seq_printf(seq, ",listgid=%u", listgid); | ||
| 86 | if (listmode != USBFS_DEFAULT_LISTMODE) | ||
| 87 | seq_printf(seq, ",listmode=%o", listmode); | ||
| 88 | |||
| 89 | return 0; | ||
| 90 | } | ||
| 91 | |||
| 92 | enum { | ||
| 93 | Opt_devuid, Opt_devgid, Opt_devmode, | ||
| 94 | Opt_busuid, Opt_busgid, Opt_busmode, | ||
| 95 | Opt_listuid, Opt_listgid, Opt_listmode, | ||
| 96 | Opt_err, | ||
| 97 | }; | ||
| 98 | |||
| 99 | static const match_table_t tokens = { | ||
| 100 | {Opt_devuid, "devuid=%u"}, | ||
| 101 | {Opt_devgid, "devgid=%u"}, | ||
| 102 | {Opt_devmode, "devmode=%o"}, | ||
| 103 | {Opt_busuid, "busuid=%u"}, | ||
| 104 | {Opt_busgid, "busgid=%u"}, | ||
| 105 | {Opt_busmode, "busmode=%o"}, | ||
| 106 | {Opt_listuid, "listuid=%u"}, | ||
| 107 | {Opt_listgid, "listgid=%u"}, | ||
| 108 | {Opt_listmode, "listmode=%o"}, | ||
| 109 | {Opt_err, NULL} | ||
| 110 | }; | ||
| 111 | |||
| 112 | static int parse_options(struct super_block *s, char *data) | ||
| 113 | { | ||
| 114 | char *p; | ||
| 115 | int option; | ||
| 116 | |||
| 117 | /* (re)set to defaults. */ | ||
| 118 | devuid = 0; | ||
| 119 | busuid = 0; | ||
| 120 | listuid = 0; | ||
| 121 | devgid = 0; | ||
| 122 | busgid = 0; | ||
| 123 | listgid = 0; | ||
| 124 | devmode = USBFS_DEFAULT_DEVMODE; | ||
| 125 | busmode = USBFS_DEFAULT_BUSMODE; | ||
| 126 | listmode = USBFS_DEFAULT_LISTMODE; | ||
| 127 | |||
| 128 | while ((p = strsep(&data, ",")) != NULL) { | ||
| 129 | substring_t args[MAX_OPT_ARGS]; | ||
| 130 | int token; | ||
| 131 | if (!*p) | ||
| 132 | continue; | ||
| 133 | |||
| 134 | token = match_token(p, tokens, args); | ||
| 135 | switch (token) { | ||
| 136 | case Opt_devuid: | ||
| 137 | if (match_int(&args[0], &option)) | ||
| 138 | return -EINVAL; | ||
| 139 | devuid = option; | ||
| 140 | break; | ||
| 141 | case Opt_devgid: | ||
| 142 | if (match_int(&args[0], &option)) | ||
| 143 | return -EINVAL; | ||
| 144 | devgid = option; | ||
| 145 | break; | ||
| 146 | case Opt_devmode: | ||
| 147 | if (match_octal(&args[0], &option)) | ||
| 148 | return -EINVAL; | ||
| 149 | devmode = option & S_IRWXUGO; | ||
| 150 | break; | ||
| 151 | case Opt_busuid: | ||
| 152 | if (match_int(&args[0], &option)) | ||
| 153 | return -EINVAL; | ||
| 154 | busuid = option; | ||
| 155 | break; | ||
| 156 | case Opt_busgid: | ||
| 157 | if (match_int(&args[0], &option)) | ||
| 158 | return -EINVAL; | ||
| 159 | busgid = option; | ||
| 160 | break; | ||
| 161 | case Opt_busmode: | ||
| 162 | if (match_octal(&args[0], &option)) | ||
| 163 | return -EINVAL; | ||
| 164 | busmode = option & S_IRWXUGO; | ||
| 165 | break; | ||
| 166 | case Opt_listuid: | ||
| 167 | if (match_int(&args[0], &option)) | ||
| 168 | return -EINVAL; | ||
| 169 | listuid = option; | ||
| 170 | break; | ||
| 171 | case Opt_listgid: | ||
| 172 | if (match_int(&args[0], &option)) | ||
| 173 | return -EINVAL; | ||
| 174 | listgid = option; | ||
| 175 | break; | ||
| 176 | case Opt_listmode: | ||
| 177 | if (match_octal(&args[0], &option)) | ||
| 178 | return -EINVAL; | ||
| 179 | listmode = option & S_IRWXUGO; | ||
| 180 | break; | ||
| 181 | default: | ||
| 182 | printk(KERN_ERR "usbfs: unrecognised mount option " | ||
| 183 | "\"%s\" or missing value\n", p); | ||
| 184 | return -EINVAL; | ||
| 185 | } | ||
| 186 | } | ||
| 187 | |||
| 188 | return 0; | ||
| 189 | } | ||
| 190 | |||
| 191 | static void update_special(struct dentry *special) | ||
| 192 | { | ||
| 193 | special->d_inode->i_uid = listuid; | ||
| 194 | special->d_inode->i_gid = listgid; | ||
| 195 | special->d_inode->i_mode = S_IFREG | listmode; | ||
| 196 | } | ||
| 197 | |||
| 198 | static void update_dev(struct dentry *dev) | ||
| 199 | { | ||
| 200 | dev->d_inode->i_uid = devuid; | ||
| 201 | dev->d_inode->i_gid = devgid; | ||
| 202 | dev->d_inode->i_mode = S_IFREG | devmode; | ||
| 203 | } | ||
| 204 | |||
| 205 | static void update_bus(struct dentry *bus) | ||
| 206 | { | ||
| 207 | struct dentry *dev = NULL; | ||
| 208 | |||
| 209 | bus->d_inode->i_uid = busuid; | ||
| 210 | bus->d_inode->i_gid = busgid; | ||
| 211 | bus->d_inode->i_mode = S_IFDIR | busmode; | ||
| 212 | |||
| 213 | mutex_lock(&bus->d_inode->i_mutex); | ||
| 214 | |||
| 215 | list_for_each_entry(dev, &bus->d_subdirs, d_u.d_child) | ||
| 216 | if (dev->d_inode) | ||
| 217 | update_dev(dev); | ||
| 218 | |||
| 219 | mutex_unlock(&bus->d_inode->i_mutex); | ||
| 220 | } | ||
| 221 | |||
| 222 | static void update_sb(struct super_block *sb) | ||
| 223 | { | ||
| 224 | struct dentry *root = sb->s_root; | ||
| 225 | struct dentry *bus = NULL; | ||
| 226 | |||
| 227 | if (!root) | ||
| 228 | return; | ||
| 229 | |||
| 230 | mutex_lock_nested(&root->d_inode->i_mutex, I_MUTEX_PARENT); | ||
| 231 | |||
| 232 | list_for_each_entry(bus, &root->d_subdirs, d_u.d_child) { | ||
| 233 | if (bus->d_inode) { | ||
| 234 | switch (S_IFMT & bus->d_inode->i_mode) { | ||
| 235 | case S_IFDIR: | ||
| 236 | update_bus(bus); | ||
| 237 | break; | ||
| 238 | case S_IFREG: | ||
| 239 | update_special(bus); | ||
| 240 | break; | ||
| 241 | default: | ||
| 242 | printk(KERN_WARNING "usbfs: Unknown node %s " | ||
| 243 | "mode %x found on remount!\n", | ||
| 244 | bus->d_name.name, bus->d_inode->i_mode); | ||
| 245 | break; | ||
| 246 | } | ||
| 247 | } | ||
| 248 | } | ||
| 249 | |||
| 250 | mutex_unlock(&root->d_inode->i_mutex); | ||
| 251 | } | ||
| 252 | |||
| 253 | static int remount(struct super_block *sb, int *flags, char *data) | ||
| 254 | { | ||
| 255 | /* If this is not a real mount, | ||
| 256 | * i.e. it's a simple_pin_fs from create_special_files, | ||
| 257 | * then ignore it. | ||
| 258 | */ | ||
| 259 | if (ignore_mount) | ||
| 260 | return 0; | ||
| 261 | |||
| 262 | if (parse_options(sb, data)) { | ||
| 263 | printk(KERN_WARNING "usbfs: mount parameter error.\n"); | ||
| 264 | return -EINVAL; | ||
| 265 | } | ||
| 266 | |||
| 267 | if (usbfs_mount && usbfs_mount->mnt_sb) | ||
| 268 | update_sb(usbfs_mount->mnt_sb); | ||
| 269 | |||
| 270 | return 0; | ||
| 271 | } | ||
| 272 | |||
| 273 | static struct inode *usbfs_get_inode (struct super_block *sb, int mode, dev_t dev) | ||
| 274 | { | ||
| 275 | struct inode *inode = new_inode(sb); | ||
| 276 | |||
| 277 | if (inode) { | ||
| 278 | inode->i_ino = get_next_ino(); | ||
| 279 | inode->i_mode = mode; | ||
| 280 | inode->i_uid = current_fsuid(); | ||
| 281 | inode->i_gid = current_fsgid(); | ||
| 282 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; | ||
| 283 | switch (mode & S_IFMT) { | ||
| 284 | default: | ||
| 285 | init_special_inode(inode, mode, dev); | ||
| 286 | break; | ||
| 287 | case S_IFREG: | ||
| 288 | inode->i_fop = &default_file_operations; | ||
| 289 | break; | ||
| 290 | case S_IFDIR: | ||
| 291 | inode->i_op = &simple_dir_inode_operations; | ||
| 292 | inode->i_fop = &simple_dir_operations; | ||
| 293 | |||
| 294 | /* directory inodes start off with i_nlink == 2 (for "." entry) */ | ||
| 295 | inc_nlink(inode); | ||
| 296 | break; | ||
| 297 | } | ||
| 298 | } | ||
| 299 | return inode; | ||
| 300 | } | ||
| 301 | |||
| 302 | /* SMP-safe */ | ||
| 303 | static int usbfs_mknod (struct inode *dir, struct dentry *dentry, int mode, | ||
| 304 | dev_t dev) | ||
| 305 | { | ||
| 306 | struct inode *inode = usbfs_get_inode(dir->i_sb, mode, dev); | ||
| 307 | int error = -EPERM; | ||
| 308 | |||
| 309 | if (dentry->d_inode) | ||
| 310 | return -EEXIST; | ||
| 311 | |||
| 312 | if (inode) { | ||
| 313 | d_instantiate(dentry, inode); | ||
| 314 | dget(dentry); | ||
| 315 | error = 0; | ||
| 316 | } | ||
| 317 | return error; | ||
| 318 | } | ||
| 319 | |||
| 320 | static int usbfs_mkdir (struct inode *dir, struct dentry *dentry, int mode) | ||
| 321 | { | ||
| 322 | int res; | ||
| 323 | |||
| 324 | mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR; | ||
| 325 | res = usbfs_mknod (dir, dentry, mode, 0); | ||
| 326 | if (!res) | ||
| 327 | inc_nlink(dir); | ||
| 328 | return res; | ||
| 329 | } | ||
| 330 | |||
| 331 | static int usbfs_create (struct inode *dir, struct dentry *dentry, int mode) | ||
| 332 | { | ||
| 333 | mode = (mode & S_IALLUGO) | S_IFREG; | ||
| 334 | return usbfs_mknod (dir, dentry, mode, 0); | ||
| 335 | } | ||
| 336 | |||
| 337 | static inline int usbfs_positive (struct dentry *dentry) | ||
| 338 | { | ||
| 339 | return dentry->d_inode && !d_unhashed(dentry); | ||
| 340 | } | ||
| 341 | |||
| 342 | static int usbfs_empty (struct dentry *dentry) | ||
| 343 | { | ||
| 344 | struct list_head *list; | ||
| 345 | |||
| 346 | spin_lock(&dentry->d_lock); | ||
| 347 | list_for_each(list, &dentry->d_subdirs) { | ||
| 348 | struct dentry *de = list_entry(list, struct dentry, d_u.d_child); | ||
| 349 | |||
| 350 | spin_lock_nested(&de->d_lock, DENTRY_D_LOCK_NESTED); | ||
| 351 | if (usbfs_positive(de)) { | ||
| 352 | spin_unlock(&de->d_lock); | ||
| 353 | spin_unlock(&dentry->d_lock); | ||
| 354 | return 0; | ||
| 355 | } | ||
| 356 | spin_unlock(&de->d_lock); | ||
| 357 | } | ||
| 358 | spin_unlock(&dentry->d_lock); | ||
| 359 | return 1; | ||
| 360 | } | ||
| 361 | |||
| 362 | static int usbfs_unlink (struct inode *dir, struct dentry *dentry) | ||
| 363 | { | ||
| 364 | struct inode *inode = dentry->d_inode; | ||
| 365 | mutex_lock(&inode->i_mutex); | ||
| 366 | drop_nlink(dentry->d_inode); | ||
| 367 | dput(dentry); | ||
| 368 | mutex_unlock(&inode->i_mutex); | ||
| 369 | d_delete(dentry); | ||
| 370 | return 0; | ||
| 371 | } | ||
| 372 | |||
| 373 | static int usbfs_rmdir(struct inode *dir, struct dentry *dentry) | ||
| 374 | { | ||
| 375 | int error = -ENOTEMPTY; | ||
| 376 | struct inode * inode = dentry->d_inode; | ||
| 377 | |||
| 378 | mutex_lock(&inode->i_mutex); | ||
| 379 | dentry_unhash(dentry); | ||
| 380 | if (usbfs_empty(dentry)) { | ||
| 381 | dont_mount(dentry); | ||
| 382 | drop_nlink(dentry->d_inode); | ||
| 383 | drop_nlink(dentry->d_inode); | ||
| 384 | dput(dentry); | ||
| 385 | inode->i_flags |= S_DEAD; | ||
| 386 | drop_nlink(dir); | ||
| 387 | error = 0; | ||
| 388 | } | ||
| 389 | mutex_unlock(&inode->i_mutex); | ||
| 390 | if (!error) | ||
| 391 | d_delete(dentry); | ||
| 392 | return error; | ||
| 393 | } | ||
| 394 | |||
| 395 | |||
| 396 | /* default file operations */ | ||
| 397 | static ssize_t default_read_file (struct file *file, char __user *buf, | ||
| 398 | size_t count, loff_t *ppos) | ||
| 399 | { | ||
| 400 | return 0; | ||
| 401 | } | ||
| 402 | |||
| 403 | static ssize_t default_write_file (struct file *file, const char __user *buf, | ||
| 404 | size_t count, loff_t *ppos) | ||
| 405 | { | ||
| 406 | return count; | ||
| 407 | } | ||
| 408 | |||
| 409 | static loff_t default_file_lseek (struct file *file, loff_t offset, int orig) | ||
| 410 | { | ||
| 411 | loff_t retval = -EINVAL; | ||
| 412 | |||
| 413 | mutex_lock(&file->f_path.dentry->d_inode->i_mutex); | ||
| 414 | switch(orig) { | ||
| 415 | case 0: | ||
| 416 | if (offset > 0) { | ||
| 417 | file->f_pos = offset; | ||
| 418 | retval = file->f_pos; | ||
| 419 | } | ||
| 420 | break; | ||
| 421 | case 1: | ||
| 422 | if ((offset + file->f_pos) > 0) { | ||
| 423 | file->f_pos += offset; | ||
| 424 | retval = file->f_pos; | ||
| 425 | } | ||
| 426 | break; | ||
| 427 | default: | ||
| 428 | break; | ||
| 429 | } | ||
| 430 | mutex_unlock(&file->f_path.dentry->d_inode->i_mutex); | ||
| 431 | return retval; | ||
| 432 | } | ||
| 433 | |||
| 434 | static int default_open (struct inode *inode, struct file *file) | ||
| 435 | { | ||
| 436 | if (inode->i_private) | ||
| 437 | file->private_data = inode->i_private; | ||
| 438 | |||
| 439 | return 0; | ||
| 440 | } | ||
| 441 | |||
| 442 | static const struct file_operations default_file_operations = { | ||
| 443 | .read = default_read_file, | ||
| 444 | .write = default_write_file, | ||
| 445 | .open = default_open, | ||
| 446 | .llseek = default_file_lseek, | ||
| 447 | }; | ||
| 448 | |||
| 449 | static const struct super_operations usbfs_ops = { | ||
| 450 | .statfs = simple_statfs, | ||
| 451 | .drop_inode = generic_delete_inode, | ||
| 452 | .remount_fs = remount, | ||
| 453 | .show_options = usbfs_show_options, | ||
| 454 | }; | ||
| 455 | |||
| 456 | static int usbfs_fill_super(struct super_block *sb, void *data, int silent) | ||
| 457 | { | ||
| 458 | struct inode *inode; | ||
| 459 | struct dentry *root; | ||
| 460 | |||
| 461 | sb->s_blocksize = PAGE_CACHE_SIZE; | ||
| 462 | sb->s_blocksize_bits = PAGE_CACHE_SHIFT; | ||
| 463 | sb->s_magic = USBDEVICE_SUPER_MAGIC; | ||
| 464 | sb->s_op = &usbfs_ops; | ||
| 465 | sb->s_time_gran = 1; | ||
| 466 | inode = usbfs_get_inode(sb, S_IFDIR | 0755, 0); | ||
| 467 | |||
| 468 | if (!inode) { | ||
| 469 | dbg("%s: could not get inode!",__func__); | ||
| 470 | return -ENOMEM; | ||
| 471 | } | ||
| 472 | |||
| 473 | root = d_alloc_root(inode); | ||
| 474 | if (!root) { | ||
| 475 | dbg("%s: could not get root dentry!",__func__); | ||
| 476 | iput(inode); | ||
| 477 | return -ENOMEM; | ||
| 478 | } | ||
| 479 | sb->s_root = root; | ||
| 480 | return 0; | ||
| 481 | } | ||
| 482 | |||
| 483 | /* | ||
| 484 | * fs_create_by_name - create a file, given a name | ||
| 485 | * @name: name of file | ||
| 486 | * @mode: type of file | ||
| 487 | * @parent: dentry of directory to create it in | ||
| 488 | * @dentry: resulting dentry of file | ||
| 489 | * | ||
| 490 | * This function handles both regular files and directories. | ||
| 491 | */ | ||
| 492 | static int fs_create_by_name (const char *name, mode_t mode, | ||
| 493 | struct dentry *parent, struct dentry **dentry) | ||
| 494 | { | ||
| 495 | int error = 0; | ||
| 496 | |||
| 497 | /* If the parent is not specified, we create it in the root. | ||
| 498 | * We need the root dentry to do this, which is in the super | ||
| 499 | * block. A pointer to that is in the struct vfsmount that we | ||
| 500 | * have around. | ||
| 501 | */ | ||
| 502 | if (!parent ) { | ||
| 503 | if (usbfs_mount && usbfs_mount->mnt_sb) { | ||
| 504 | parent = usbfs_mount->mnt_sb->s_root; | ||
| 505 | } | ||
| 506 | } | ||
| 507 | |||
| 508 | if (!parent) { | ||
| 509 | dbg("Ah! can not find a parent!"); | ||
| 510 | return -EFAULT; | ||
| 511 | } | ||
| 512 | |||
| 513 | *dentry = NULL; | ||
| 514 | mutex_lock(&parent->d_inode->i_mutex); | ||
| 515 | *dentry = lookup_one_len(name, parent, strlen(name)); | ||
| 516 | if (!IS_ERR(*dentry)) { | ||
| 517 | if ((mode & S_IFMT) == S_IFDIR) | ||
| 518 | error = usbfs_mkdir (parent->d_inode, *dentry, mode); | ||
| 519 | else | ||
| 520 | error = usbfs_create (parent->d_inode, *dentry, mode); | ||
| 521 | } else | ||
| 522 | error = PTR_ERR(*dentry); | ||
| 523 | mutex_unlock(&parent->d_inode->i_mutex); | ||
| 524 | |||
| 525 | return error; | ||
| 526 | } | ||
| 527 | |||
| 528 | static struct dentry *fs_create_file (const char *name, mode_t mode, | ||
| 529 | struct dentry *parent, void *data, | ||
| 530 | const struct file_operations *fops, | ||
| 531 | uid_t uid, gid_t gid) | ||
| 532 | { | ||
| 533 | struct dentry *dentry; | ||
| 534 | int error; | ||
| 535 | |||
| 536 | dbg("creating file '%s'",name); | ||
| 537 | |||
| 538 | error = fs_create_by_name (name, mode, parent, &dentry); | ||
| 539 | if (error) { | ||
| 540 | dentry = NULL; | ||
| 541 | } else { | ||
| 542 | if (dentry->d_inode) { | ||
| 543 | if (data) | ||
| 544 | dentry->d_inode->i_private = data; | ||
| 545 | if (fops) | ||
| 546 | dentry->d_inode->i_fop = fops; | ||
| 547 | dentry->d_inode->i_uid = uid; | ||
| 548 | dentry->d_inode->i_gid = gid; | ||
| 549 | } | ||
| 550 | } | ||
| 551 | |||
| 552 | return dentry; | ||
| 553 | } | ||
| 554 | |||
| 555 | static void fs_remove_file (struct dentry *dentry) | ||
| 556 | { | ||
| 557 | struct dentry *parent = dentry->d_parent; | ||
| 558 | |||
| 559 | if (!parent || !parent->d_inode) | ||
| 560 | return; | ||
| 561 | |||
| 562 | mutex_lock_nested(&parent->d_inode->i_mutex, I_MUTEX_PARENT); | ||
| 563 | if (usbfs_positive(dentry)) { | ||
| 564 | if (dentry->d_inode) { | ||
| 565 | if (S_ISDIR(dentry->d_inode->i_mode)) | ||
| 566 | usbfs_rmdir(parent->d_inode, dentry); | ||
| 567 | else | ||
| 568 | usbfs_unlink(parent->d_inode, dentry); | ||
| 569 | dput(dentry); | ||
| 570 | } | ||
| 571 | } | ||
| 572 | mutex_unlock(&parent->d_inode->i_mutex); | ||
| 573 | } | ||
| 574 | |||
| 575 | /* --------------------------------------------------------------------- */ | ||
| 576 | |||
| 577 | static struct dentry *usb_mount(struct file_system_type *fs_type, | ||
| 578 | int flags, const char *dev_name, void *data) | ||
| 579 | { | ||
| 580 | return mount_single(fs_type, flags, data, usbfs_fill_super); | ||
| 581 | } | ||
| 582 | |||
| 583 | static struct file_system_type usb_fs_type = { | ||
| 584 | .owner = THIS_MODULE, | ||
| 585 | .name = "usbfs", | ||
| 586 | .mount = usb_mount, | ||
| 587 | .kill_sb = kill_litter_super, | ||
| 588 | }; | ||
| 589 | |||
| 590 | /* --------------------------------------------------------------------- */ | ||
| 591 | |||
| 592 | static int create_special_files (void) | ||
| 593 | { | ||
| 594 | struct dentry *parent; | ||
| 595 | int retval; | ||
| 596 | |||
| 597 | /* the simple_pin_fs calls will call remount with no options | ||
| 598 | * without this flag that would overwrite the real mount options (if any) | ||
| 599 | */ | ||
| 600 | ignore_mount = 1; | ||
| 601 | |||
| 602 | /* create the devices special file */ | ||
| 603 | retval = simple_pin_fs(&usb_fs_type, &usbfs_mount, &usbfs_mount_count); | ||
| 604 | if (retval) { | ||
| 605 | printk(KERN_ERR "Unable to get usbfs mount\n"); | ||
| 606 | goto exit; | ||
| 607 | } | ||
| 608 | |||
| 609 | ignore_mount = 0; | ||
| 610 | |||
| 611 | parent = usbfs_mount->mnt_sb->s_root; | ||
| 612 | devices_usbfs_dentry = fs_create_file ("devices", | ||
| 613 | listmode | S_IFREG, parent, | ||
| 614 | NULL, &usbfs_devices_fops, | ||
| 615 | listuid, listgid); | ||
| 616 | if (devices_usbfs_dentry == NULL) { | ||
| 617 | printk(KERN_ERR "Unable to create devices usbfs file\n"); | ||
| 618 | retval = -ENODEV; | ||
| 619 | goto error_clean_mounts; | ||
| 620 | } | ||
| 621 | |||
| 622 | goto exit; | ||
| 623 | |||
| 624 | error_clean_mounts: | ||
| 625 | simple_release_fs(&usbfs_mount, &usbfs_mount_count); | ||
| 626 | exit: | ||
| 627 | return retval; | ||
| 628 | } | ||
| 629 | |||
| 630 | static void remove_special_files (void) | ||
| 631 | { | ||
| 632 | if (devices_usbfs_dentry) | ||
| 633 | fs_remove_file (devices_usbfs_dentry); | ||
| 634 | devices_usbfs_dentry = NULL; | ||
| 635 | simple_release_fs(&usbfs_mount, &usbfs_mount_count); | ||
| 636 | } | ||
| 637 | |||
| 638 | void usbfs_update_special (void) | ||
| 639 | { | ||
| 640 | struct inode *inode; | ||
| 641 | |||
| 642 | if (devices_usbfs_dentry) { | ||
| 643 | inode = devices_usbfs_dentry->d_inode; | ||
| 644 | if (inode) | ||
| 645 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; | ||
| 646 | } | ||
| 647 | } | ||
| 648 | |||
| 649 | static void usbfs_add_bus(struct usb_bus *bus) | ||
| 650 | { | ||
| 651 | struct dentry *parent; | ||
| 652 | char name[8]; | ||
| 653 | int retval; | ||
| 654 | |||
| 655 | /* create the special files if this is the first bus added */ | ||
| 656 | if (num_buses == 0) { | ||
| 657 | retval = create_special_files(); | ||
| 658 | if (retval) | ||
| 659 | return; | ||
| 660 | } | ||
| 661 | ++num_buses; | ||
| 662 | |||
| 663 | sprintf (name, "%03d", bus->busnum); | ||
| 664 | |||
| 665 | parent = usbfs_mount->mnt_sb->s_root; | ||
| 666 | bus->usbfs_dentry = fs_create_file (name, busmode | S_IFDIR, parent, | ||
| 667 | bus, NULL, busuid, busgid); | ||
| 668 | if (bus->usbfs_dentry == NULL) { | ||
| 669 | printk(KERN_ERR "Error creating usbfs bus entry\n"); | ||
| 670 | return; | ||
| 671 | } | ||
| 672 | } | ||
| 673 | |||
| 674 | static void usbfs_remove_bus(struct usb_bus *bus) | ||
| 675 | { | ||
| 676 | if (bus->usbfs_dentry) { | ||
| 677 | fs_remove_file (bus->usbfs_dentry); | ||
| 678 | bus->usbfs_dentry = NULL; | ||
| 679 | } | ||
| 680 | |||
| 681 | --num_buses; | ||
| 682 | if (num_buses <= 0) { | ||
| 683 | remove_special_files(); | ||
| 684 | num_buses = 0; | ||
| 685 | } | ||
| 686 | } | ||
| 687 | |||
| 688 | static void usbfs_add_device(struct usb_device *dev) | ||
| 689 | { | ||
| 690 | char name[8]; | ||
| 691 | int i; | ||
| 692 | int i_size; | ||
| 693 | |||
| 694 | sprintf (name, "%03d", dev->devnum); | ||
| 695 | dev->usbfs_dentry = fs_create_file (name, devmode | S_IFREG, | ||
| 696 | dev->bus->usbfs_dentry, dev, | ||
| 697 | &usbdev_file_operations, | ||
| 698 | devuid, devgid); | ||
| 699 | if (dev->usbfs_dentry == NULL) { | ||
| 700 | printk(KERN_ERR "Error creating usbfs device entry\n"); | ||
| 701 | return; | ||
| 702 | } | ||
| 703 | |||
| 704 | /* Set the size of the device's file to be | ||
| 705 | * equal to the size of the device descriptors. */ | ||
| 706 | i_size = sizeof (struct usb_device_descriptor); | ||
| 707 | for (i = 0; i < dev->descriptor.bNumConfigurations; ++i) { | ||
| 708 | struct usb_config_descriptor *config = | ||
| 709 | (struct usb_config_descriptor *)dev->rawdescriptors[i]; | ||
| 710 | i_size += le16_to_cpu(config->wTotalLength); | ||
| 711 | } | ||
| 712 | if (dev->usbfs_dentry->d_inode) | ||
| 713 | dev->usbfs_dentry->d_inode->i_size = i_size; | ||
| 714 | } | ||
| 715 | |||
| 716 | static void usbfs_remove_device(struct usb_device *dev) | ||
| 717 | { | ||
| 718 | if (dev->usbfs_dentry) { | ||
| 719 | fs_remove_file (dev->usbfs_dentry); | ||
| 720 | dev->usbfs_dentry = NULL; | ||
| 721 | } | ||
| 722 | } | ||
| 723 | |||
| 724 | static int usbfs_notify(struct notifier_block *self, unsigned long action, void *dev) | ||
| 725 | { | ||
| 726 | switch (action) { | ||
| 727 | case USB_DEVICE_ADD: | ||
| 728 | usbfs_add_device(dev); | ||
| 729 | break; | ||
| 730 | case USB_DEVICE_REMOVE: | ||
| 731 | usbfs_remove_device(dev); | ||
| 732 | break; | ||
| 733 | case USB_BUS_ADD: | ||
| 734 | usbfs_add_bus(dev); | ||
| 735 | break; | ||
| 736 | case USB_BUS_REMOVE: | ||
| 737 | usbfs_remove_bus(dev); | ||
| 738 | } | ||
| 739 | |||
| 740 | usbfs_update_special(); | ||
| 741 | usbfs_conn_disc_event(); | ||
| 742 | return NOTIFY_OK; | ||
| 743 | } | ||
| 744 | |||
| 745 | static struct notifier_block usbfs_nb = { | ||
| 746 | .notifier_call = usbfs_notify, | ||
| 747 | }; | ||
| 748 | |||
| 749 | /* --------------------------------------------------------------------- */ | ||
| 750 | |||
| 751 | static struct proc_dir_entry *usbdir = NULL; | ||
| 752 | |||
| 753 | int __init usbfs_init(void) | ||
| 754 | { | ||
| 755 | int retval; | ||
| 756 | |||
| 757 | retval = register_filesystem(&usb_fs_type); | ||
| 758 | if (retval) | ||
| 759 | return retval; | ||
| 760 | |||
| 761 | usb_register_notify(&usbfs_nb); | ||
| 762 | |||
| 763 | /* create mount point for usbfs */ | ||
| 764 | usbdir = proc_mkdir("bus/usb", NULL); | ||
| 765 | |||
| 766 | return 0; | ||
| 767 | } | ||
| 768 | |||
| 769 | void usbfs_cleanup(void) | ||
| 770 | { | ||
| 771 | usb_unregister_notify(&usbfs_nb); | ||
| 772 | unregister_filesystem(&usb_fs_type); | ||
| 773 | if (usbdir) | ||
| 774 | remove_proc_entry("bus/usb", NULL); | ||
| 775 | } | ||
| 776 | |||
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c new file mode 100644 index 00000000000..fbafe8a3bca --- /dev/null +++ b/drivers/usb/gadget/android.c | |||
| @@ -0,0 +1,1181 @@ | |||
| 1 | /* | ||
| 2 | * Gadget Driver for Android | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008 Google, Inc. | ||
| 5 | * Author: Mike Lockwood <lockwood@android.com> | ||
| 6 | * | ||
| 7 | * This software is licensed under the terms of the GNU General Public | ||
| 8 | * License version 2, as published by the Free Software Foundation, and | ||
| 9 | * may be copied, distributed, and modified under those terms. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | */ | ||
| 17 | |||
| 18 | /* #define DEBUG */ | ||
| 19 | /* #define VERBOSE_DEBUG */ | ||
| 20 | |||
| 21 | #include <linux/init.h> | ||
| 22 | #include <linux/module.h> | ||
| 23 | #include <linux/fs.h> | ||
| 24 | |||
| 25 | #include <linux/delay.h> | ||
| 26 | #include <linux/kernel.h> | ||
| 27 | #include <linux/utsname.h> | ||
| 28 | #include <linux/platform_device.h> | ||
| 29 | |||
| 30 | #include <linux/usb/ch9.h> | ||
| 31 | #include <linux/usb/composite.h> | ||
| 32 | #include <linux/usb/gadget.h> | ||
| 33 | |||
| 34 | #include "gadget_chips.h" | ||
| 35 | |||
| 36 | /* | ||
| 37 | * Kbuild is not very cooperative with respect to linking separately | ||
| 38 | * compiled library objects into one module. So for now we won't use | ||
| 39 | * separate compilation ... ensuring init/exit sections work to shrink | ||
| 40 | * the runtime footprint, and giving us at least some parts of what | ||
| 41 | * a "gcc --combine ... part1.c part2.c part3.c ... " build would. | ||
| 42 | */ | ||
| 43 | #include "usbstring.c" | ||
| 44 | #include "config.c" | ||
| 45 | #include "epautoconf.c" | ||
| 46 | #include "composite.c" | ||
| 47 | |||
| 48 | #include "f_mass_storage.c" | ||
| 49 | #include "u_serial.c" | ||
| 50 | #include "f_acm.c" | ||
| 51 | #include "f_adb.c" | ||
| 52 | #include "f_mtp.c" | ||
| 53 | #include "f_accessory.c" | ||
| 54 | #define USB_ETH_RNDIS y | ||
| 55 | #include "f_rndis.c" | ||
| 56 | #include "rndis.c" | ||
| 57 | #include "u_ether.c" | ||
| 58 | |||
| 59 | MODULE_AUTHOR("Mike Lockwood"); | ||
| 60 | MODULE_DESCRIPTION("Android Composite USB Driver"); | ||
| 61 | MODULE_LICENSE("GPL"); | ||
| 62 | MODULE_VERSION("1.0"); | ||
| 63 | |||
| 64 | static const char longname[] = "Gadget Android"; | ||
| 65 | |||
| 66 | /* Default vendor and product IDs, overridden by userspace */ | ||
| 67 | #define VENDOR_ID 0x18D1 | ||
| 68 | #define PRODUCT_ID 0x0001 | ||
| 69 | |||
| 70 | struct android_usb_function { | ||
| 71 | char *name; | ||
| 72 | void *config; | ||
| 73 | |||
| 74 | struct device *dev; | ||
| 75 | char *dev_name; | ||
| 76 | struct device_attribute **attributes; | ||
| 77 | |||
| 78 | /* for android_dev.enabled_functions */ | ||
| 79 | struct list_head enabled_list; | ||
| 80 | |||
| 81 | /* Optional: initialization during gadget bind */ | ||
| 82 | int (*init)(struct android_usb_function *, struct usb_composite_dev *); | ||
| 83 | /* Optional: cleanup during gadget unbind */ | ||
| 84 | void (*cleanup)(struct android_usb_function *); | ||
| 85 | |||
| 86 | int (*bind_config)(struct android_usb_function *, struct usb_configuration *); | ||
| 87 | |||
| 88 | /* Optional: called when the configuration is removed */ | ||
| 89 | void (*unbind_config)(struct android_usb_function *, struct usb_configuration *); | ||
| 90 | /* Optional: handle ctrl requests before the device is configured */ | ||
| 91 | int (*ctrlrequest)(struct android_usb_function *, | ||
| 92 | struct usb_composite_dev *, | ||
| 93 | const struct usb_ctrlrequest *); | ||
| 94 | }; | ||
| 95 | |||
| 96 | struct android_dev { | ||
| 97 | struct android_usb_function **functions; | ||
| 98 | struct list_head enabled_functions; | ||
| 99 | struct usb_composite_dev *cdev; | ||
| 100 | struct device *dev; | ||
| 101 | |||
| 102 | bool enabled; | ||
| 103 | struct mutex mutex; | ||
| 104 | bool connected; | ||
| 105 | bool sw_connected; | ||
| 106 | struct work_struct work; | ||
| 107 | }; | ||
| 108 | |||
| 109 | static struct class *android_class; | ||
| 110 | static struct android_dev *_android_dev; | ||
| 111 | static int android_bind_config(struct usb_configuration *c); | ||
| 112 | static void android_unbind_config(struct usb_configuration *c); | ||
| 113 | |||
| 114 | /* string IDs are assigned dynamically */ | ||
| 115 | #define STRING_MANUFACTURER_IDX 0 | ||
| 116 | #define STRING_PRODUCT_IDX 1 | ||
| 117 | #define STRING_SERIAL_IDX 2 | ||
| 118 | |||
| 119 | static char manufacturer_string[256]; | ||
| 120 | static char product_string[256]; | ||
| 121 | static char serial_string[256]; | ||
| 122 | |||
| 123 | /* String Table */ | ||
| 124 | static struct usb_string strings_dev[] = { | ||
| 125 | [STRING_MANUFACTURER_IDX].s = manufacturer_string, | ||
| 126 | [STRING_PRODUCT_IDX].s = product_string, | ||
| 127 | [STRING_SERIAL_IDX].s = serial_string, | ||
| 128 | { } /* end of list */ | ||
| 129 | }; | ||
| 130 | |||
| 131 | static struct usb_gadget_strings stringtab_dev = { | ||
| 132 | .language = 0x0409, /* en-us */ | ||
| 133 | .strings = strings_dev, | ||
| 134 | }; | ||
| 135 | |||
| 136 | static struct usb_gadget_strings *dev_strings[] = { | ||
| 137 | &stringtab_dev, | ||
| 138 | NULL, | ||
| 139 | }; | ||
| 140 | |||
| 141 | static struct usb_device_descriptor device_desc = { | ||
| 142 | .bLength = sizeof(device_desc), | ||
| 143 | .bDescriptorType = USB_DT_DEVICE, | ||
| 144 | .bcdUSB = __constant_cpu_to_le16(0x0200), | ||
| 145 | .bDeviceClass = USB_CLASS_PER_INTERFACE, | ||
| 146 | .idVendor = __constant_cpu_to_le16(VENDOR_ID), | ||
| 147 | .idProduct = __constant_cpu_to_le16(PRODUCT_ID), | ||
| 148 | .bcdDevice = __constant_cpu_to_le16(0xffff), | ||
| 149 | .bNumConfigurations = 1, | ||
| 150 | }; | ||
| 151 | |||
| 152 | static struct usb_configuration android_config_driver = { | ||
| 153 | .label = "android", | ||
| 154 | .unbind = android_unbind_config, | ||
| 155 | .bConfigurationValue = 1, | ||
| 156 | }; | ||
| 157 | |||
| 158 | static void android_work(struct work_struct *data) | ||
| 159 | { | ||
| 160 | struct android_dev *dev = container_of(data, struct android_dev, work); | ||
| 161 | struct usb_composite_dev *cdev = dev->cdev; | ||
| 162 | char *disconnected[2] = { "USB_STATE=DISCONNECTED", NULL }; | ||
| 163 | char *connected[2] = { "USB_STATE=CONNECTED", NULL }; | ||
| 164 | char *configured[2] = { "USB_STATE=CONFIGURED", NULL }; | ||
| 165 | char **uevent_envp = NULL; | ||
| 166 | unsigned long flags; | ||
| 167 | |||
| 168 | spin_lock_irqsave(&cdev->lock, flags); | ||
| 169 | if (cdev->config) | ||
| 170 | uevent_envp = configured; | ||
| 171 | else if (dev->connected != dev->sw_connected) | ||
| 172 | uevent_envp = dev->connected ? connected : disconnected; | ||
| 173 | dev->sw_connected = dev->connected; | ||
| 174 | spin_unlock_irqrestore(&cdev->lock, flags); | ||
| 175 | |||
| 176 | if (uevent_envp) { | ||
| 177 | kobject_uevent_env(&dev->dev->kobj, KOBJ_CHANGE, uevent_envp); | ||
| 178 | pr_info("%s: sent uevent %s\n", __func__, uevent_envp[0]); | ||
| 179 | } else { | ||
| 180 | pr_info("%s: did not send uevent (%d %d %p)\n", __func__, | ||
| 181 | dev->connected, dev->sw_connected, cdev->config); | ||
| 182 | } | ||
| 183 | } | ||
| 184 | |||
| 185 | |||
| 186 | /*-------------------------------------------------------------------------*/ | ||
| 187 | /* Supported functions initialization */ | ||
| 188 | |||
| 189 | static int adb_function_init(struct android_usb_function *f, struct usb_composite_dev *cdev) | ||
| 190 | { | ||
| 191 | return adb_setup(); | ||
| 192 | } | ||
| 193 | |||
| 194 | static void adb_function_cleanup(struct android_usb_function *f) | ||
| 195 | { | ||
| 196 | adb_cleanup(); | ||
| 197 | } | ||
| 198 | |||
| 199 | static int adb_function_bind_config(struct android_usb_function *f, struct usb_configuration *c) | ||
| 200 | { | ||
| 201 | return adb_bind_config(c); | ||
| 202 | } | ||
| 203 | |||
| 204 | static struct android_usb_function adb_function = { | ||
| 205 | .name = "adb", | ||
| 206 | .init = adb_function_init, | ||
| 207 | .cleanup = adb_function_cleanup, | ||
| 208 | .bind_config = adb_function_bind_config, | ||
| 209 | }; | ||
| 210 | |||
| 211 | |||
| 212 | #define MAX_ACM_INSTANCES 4 | ||
| 213 | struct acm_function_config { | ||
| 214 | int instances; | ||
| 215 | }; | ||
| 216 | |||
| 217 | static int acm_function_init(struct android_usb_function *f, struct usb_composite_dev *cdev) | ||
| 218 | { | ||
| 219 | f->config = kzalloc(sizeof(struct acm_function_config), GFP_KERNEL); | ||
| 220 | if (!f->config) | ||
| 221 | return -ENOMEM; | ||
| 222 | |||
| 223 | return gserial_setup(cdev->gadget, MAX_ACM_INSTANCES); | ||
| 224 | } | ||
| 225 | |||
| 226 | static void acm_function_cleanup(struct android_usb_function *f) | ||
| 227 | { | ||
| 228 | gserial_cleanup(); | ||
| 229 | kfree(f->config); | ||
| 230 | f->config = NULL; | ||
| 231 | } | ||
| 232 | |||
| 233 | static int acm_function_bind_config(struct android_usb_function *f, struct usb_configuration *c) | ||
| 234 | { | ||
| 235 | int i; | ||
| 236 | int ret = 0; | ||
| 237 | struct acm_function_config *config = f->config; | ||
| 238 | |||
| 239 | for (i = 0; i < config->instances; i++) { | ||
| 240 | ret = acm_bind_config(c, i); | ||
| 241 | if (ret) { | ||
| 242 | pr_err("Could not bind acm%u config\n", i); | ||
| 243 | break; | ||
| 244 | } | ||
| 245 | } | ||
| 246 | |||
| 247 | return ret; | ||
| 248 | } | ||
| 249 | |||
| 250 | static ssize_t acm_instances_show(struct device *dev, | ||
| 251 | struct device_attribute *attr, char *buf) | ||
| 252 | { | ||
| 253 | struct android_usb_function *f = dev_get_drvdata(dev); | ||
| 254 | struct acm_function_config *config = f->config; | ||
| 255 | return sprintf(buf, "%d\n", config->instances); | ||
| 256 | } | ||
| 257 | |||
| 258 | static ssize_t acm_instances_store(struct device *dev, | ||
| 259 | struct device_attribute *attr, const char *buf, size_t size) | ||
| 260 | { | ||
| 261 | struct android_usb_function *f = dev_get_drvdata(dev); | ||
| 262 | struct acm_function_config *config = f->config; | ||
| 263 | int value; | ||
| 264 | |||
| 265 | sscanf(buf, "%d", &value); | ||
| 266 | if (value > MAX_ACM_INSTANCES) | ||
| 267 | value = MAX_ACM_INSTANCES; | ||
| 268 | config->instances = value; | ||
| 269 | return size; | ||
| 270 | } | ||
| 271 | |||
| 272 | static DEVICE_ATTR(instances, S_IRUGO | S_IWUSR, acm_instances_show, acm_instances_store); | ||
| 273 | static struct device_attribute *acm_function_attributes[] = { &dev_attr_instances, NULL }; | ||
| 274 | |||
| 275 | static struct android_usb_function acm_function = { | ||
| 276 | .name = "acm", | ||
| 277 | .init = acm_function_init, | ||
| 278 | .cleanup = acm_function_cleanup, | ||
| 279 | .bind_config = acm_function_bind_config, | ||
| 280 | .attributes = acm_function_attributes, | ||
| 281 | }; | ||
| 282 | |||
| 283 | |||
| 284 | static int mtp_function_init(struct android_usb_function *f, struct usb_composite_dev *cdev) | ||
| 285 | { | ||
| 286 | return mtp_setup(); | ||
| 287 | } | ||
| 288 | |||
| 289 | static void mtp_function_cleanup(struct android_usb_function *f) | ||
| 290 | { | ||
| 291 | mtp_cleanup(); | ||
| 292 | } | ||
| 293 | |||
| 294 | static int mtp_function_bind_config(struct android_usb_function *f, struct usb_configuration *c) | ||
| 295 | { | ||
| 296 | return mtp_bind_config(c, false); | ||
| 297 | } | ||
| 298 | |||
| 299 | static int ptp_function_init(struct android_usb_function *f, struct usb_composite_dev *cdev) | ||
| 300 | { | ||
| 301 | /* nothing to do - initialization is handled by mtp_function_init */ | ||
| 302 | return 0; | ||
| 303 | } | ||
| 304 | |||
| 305 | static void ptp_function_cleanup(struct android_usb_function *f) | ||
| 306 | { | ||
| 307 | /* nothing to do - cleanup is handled by mtp_function_cleanup */ | ||
| 308 | } | ||
| 309 | |||
| 310 | static int ptp_function_bind_config(struct android_usb_function *f, struct usb_configuration *c) | ||
| 311 | { | ||
| 312 | return mtp_bind_config(c, true); | ||
| 313 | } | ||
| 314 | |||
| 315 | static int mtp_function_ctrlrequest(struct android_usb_function *f, | ||
| 316 | struct usb_composite_dev *cdev, | ||
| 317 | const struct usb_ctrlrequest *c) | ||
| 318 | { | ||
| 319 | return mtp_ctrlrequest(cdev, c); | ||
| 320 | } | ||
| 321 | |||
| 322 | static struct android_usb_function mtp_function = { | ||
| 323 | .name = "mtp", | ||
| 324 | .init = mtp_function_init, | ||
| 325 | .cleanup = mtp_function_cleanup, | ||
| 326 | .bind_config = mtp_function_bind_config, | ||
| 327 | .ctrlrequest = mtp_function_ctrlrequest, | ||
| 328 | }; | ||
| 329 | |||
| 330 | /* PTP function is same as MTP with slightly different interface descriptor */ | ||
| 331 | static struct android_usb_function ptp_function = { | ||
| 332 | .name = "ptp", | ||
| 333 | .init = ptp_function_init, | ||
| 334 | .cleanup = ptp_function_cleanup, | ||
| 335 | .bind_config = ptp_function_bind_config, | ||
| 336 | }; | ||
| 337 | |||
| 338 | |||
| 339 | struct rndis_function_config { | ||
| 340 | u8 ethaddr[ETH_ALEN]; | ||
| 341 | u32 vendorID; | ||
| 342 | char manufacturer[256]; | ||
| 343 | bool wceis; | ||
| 344 | }; | ||
| 345 | |||
| 346 | static int rndis_function_init(struct android_usb_function *f, struct usb_composite_dev *cdev) | ||
| 347 | { | ||
| 348 | f->config = kzalloc(sizeof(struct rndis_function_config), GFP_KERNEL); | ||
| 349 | if (!f->config) | ||
| 350 | return -ENOMEM; | ||
| 351 | return 0; | ||
| 352 | } | ||
| 353 | |||
| 354 | static void rndis_function_cleanup(struct android_usb_function *f) | ||
| 355 | { | ||
| 356 | kfree(f->config); | ||
| 357 | f->config = NULL; | ||
| 358 | } | ||
| 359 | |||
| 360 | static int rndis_function_bind_config(struct android_usb_function *f, | ||
| 361 | struct usb_configuration *c) | ||
| 362 | { | ||
| 363 | int ret; | ||
| 364 | struct rndis_function_config *rndis = f->config; | ||
| 365 | |||
| 366 | if (!rndis) { | ||
| 367 | pr_err("%s: rndis_pdata\n", __func__); | ||
| 368 | return -1; | ||
| 369 | } | ||
| 370 | |||
| 371 | pr_info("%s MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", __func__, | ||
| 372 | rndis->ethaddr[0], rndis->ethaddr[1], rndis->ethaddr[2], | ||
| 373 | rndis->ethaddr[3], rndis->ethaddr[4], rndis->ethaddr[5]); | ||
| 374 | |||
| 375 | ret = gether_setup_name(c->cdev->gadget, rndis->ethaddr, "rndis"); | ||
| 376 | if (ret) { | ||
| 377 | pr_err("%s: gether_setup failed\n", __func__); | ||
| 378 | return ret; | ||
| 379 | } | ||
| 380 | |||
| 381 | if (rndis->wceis) { | ||
| 382 | /* "Wireless" RNDIS; auto-detected by Windows */ | ||
| 383 | rndis_iad_descriptor.bFunctionClass = | ||
| 384 | USB_CLASS_WIRELESS_CONTROLLER; | ||
| 385 | rndis_iad_descriptor.bFunctionSubClass = 0x01; | ||
| 386 | rndis_iad_descriptor.bFunctionProtocol = 0x03; | ||
| 387 | rndis_control_intf.bInterfaceClass = | ||
| 388 | USB_CLASS_WIRELESS_CONTROLLER; | ||
| 389 | rndis_control_intf.bInterfaceSubClass = 0x01; | ||
| 390 | rndis_control_intf.bInterfaceProtocol = 0x03; | ||
| 391 | } | ||
| 392 | |||
| 393 | return rndis_bind_config(c, rndis->ethaddr, rndis->vendorID, | ||
| 394 | rndis->manufacturer); | ||
| 395 | } | ||
| 396 | |||
| 397 | static void rndis_function_unbind_config(struct android_usb_function *f, | ||
| 398 | struct usb_configuration *c) | ||
| 399 | { | ||
| 400 | gether_cleanup(); | ||
| 401 | } | ||
| 402 | |||
| 403 | static ssize_t rndis_manufacturer_show(struct device *dev, | ||
| 404 | struct device_attribute *attr, char *buf) | ||
| 405 | { | ||
| 406 | struct android_usb_function *f = dev_get_drvdata(dev); | ||
| 407 | struct rndis_function_config *config = f->config; | ||
| 408 | return sprintf(buf, "%s\n", config->manufacturer); | ||
| 409 | } | ||
| 410 | |||
| 411 | static ssize_t rndis_manufacturer_store(struct device *dev, | ||
| 412 | struct device_attribute *attr, const char *buf, size_t size) | ||
| 413 | { | ||
| 414 | struct android_usb_function *f = dev_get_drvdata(dev); | ||
| 415 | struct rndis_function_config *config = f->config; | ||
| 416 | |||
| 417 | if (size >= sizeof(config->manufacturer)) | ||
| 418 | return -EINVAL; | ||
| 419 | if (sscanf(buf, "%s", config->manufacturer) == 1) | ||
| 420 | return size; | ||
| 421 | return -1; | ||
| 422 | } | ||
| 423 | |||
| 424 | static DEVICE_ATTR(manufacturer, S_IRUGO | S_IWUSR, rndis_manufacturer_show, | ||
| 425 | rndis_manufacturer_store); | ||
| 426 | |||
| 427 | static ssize_t rndis_wceis_show(struct device *dev, | ||
| 428 | struct device_attribute *attr, char *buf) | ||
| 429 | { | ||
| 430 | struct android_usb_function *f = dev_get_drvdata(dev); | ||
| 431 | struct rndis_function_config *config = f->config; | ||
| 432 | return sprintf(buf, "%d\n", config->wceis); | ||
| 433 | } | ||
| 434 | |||
| 435 | static ssize_t rndis_wceis_store(struct device *dev, | ||
| 436 | struct device_attribute *attr, const char *buf, size_t size) | ||
| 437 | { | ||
| 438 | struct android_usb_function *f = dev_get_drvdata(dev); | ||
| 439 | struct rndis_function_config *config = f->config; | ||
| 440 | int value; | ||
| 441 | |||
| 442 | if (sscanf(buf, "%d", &value) == 1) { | ||
| 443 | config->wceis = value; | ||
| 444 | return size; | ||
| 445 | } | ||
| 446 | return -EINVAL; | ||
| 447 | } | ||
| 448 | |||
| 449 | static DEVICE_ATTR(wceis, S_IRUGO | S_IWUSR, rndis_wceis_show, | ||
| 450 | rndis_wceis_store); | ||
| 451 | |||
| 452 | static ssize_t rndis_ethaddr_show(struct device *dev, | ||
| 453 | struct device_attribute *attr, char *buf) | ||
| 454 | { | ||
| 455 | struct android_usb_function *f = dev_get_drvdata(dev); | ||
| 456 | struct rndis_function_config *rndis = f->config; | ||
| 457 | return sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x\n", | ||
| 458 | rndis->ethaddr[0], rndis->ethaddr[1], rndis->ethaddr[2], | ||
| 459 | rndis->ethaddr[3], rndis->ethaddr[4], rndis->ethaddr[5]); | ||
| 460 | } | ||
| 461 | |||
| 462 | static ssize_t rndis_ethaddr_store(struct device *dev, | ||
| 463 | struct device_attribute *attr, const char *buf, size_t size) | ||
| 464 | { | ||
| 465 | struct android_usb_function *f = dev_get_drvdata(dev); | ||
| 466 | struct rndis_function_config *rndis = f->config; | ||
| 467 | |||
| 468 | if (sscanf(buf, "%02x:%02x:%02x:%02x:%02x:%02x\n", | ||
| 469 | (int *)&rndis->ethaddr[0], (int *)&rndis->ethaddr[1], | ||
| 470 | (int *)&rndis->ethaddr[2], (int *)&rndis->ethaddr[3], | ||
| 471 | (int *)&rndis->ethaddr[4], (int *)&rndis->ethaddr[5]) == 6) | ||
| 472 | return size; | ||
| 473 | return -EINVAL; | ||
| 474 | } | ||
| 475 | |||
| 476 | static DEVICE_ATTR(ethaddr, S_IRUGO | S_IWUSR, rndis_ethaddr_show, | ||
| 477 | rndis_ethaddr_store); | ||
| 478 | |||
| 479 | static ssize_t rndis_vendorID_show(struct device *dev, | ||
| 480 | struct device_attribute *attr, char *buf) | ||
| 481 | { | ||
| 482 | struct android_usb_function *f = dev_get_drvdata(dev); | ||
| 483 | struct rndis_function_config *config = f->config; | ||
| 484 | return sprintf(buf, "%04x\n", config->vendorID); | ||
| 485 | } | ||
| 486 | |||
| 487 | static ssize_t rndis_vendorID_store(struct device *dev, | ||
| 488 | struct device_attribute *attr, const char *buf, size_t size) | ||
| 489 | { | ||
| 490 | struct android_usb_function *f = dev_get_drvdata(dev); | ||
| 491 | struct rndis_function_config *config = f->config; | ||
| 492 | int value; | ||
| 493 | |||
| 494 | if (sscanf(buf, "%04x", &value) == 1) { | ||
| 495 | config->vendorID = value; | ||
| 496 | return size; | ||
| 497 | } | ||
| 498 | return -EINVAL; | ||
| 499 | } | ||
| 500 | |||
| 501 | static DEVICE_ATTR(vendorID, S_IRUGO | S_IWUSR, rndis_vendorID_show, | ||
| 502 | rndis_vendorID_store); | ||
| 503 | |||
| 504 | static struct device_attribute *rndis_function_attributes[] = { | ||
| 505 | &dev_attr_manufacturer, | ||
| 506 | &dev_attr_wceis, | ||
| 507 | &dev_attr_ethaddr, | ||
| 508 | &dev_attr_vendorID, | ||
| 509 | NULL | ||
| 510 | }; | ||
| 511 | |||
| 512 | static struct android_usb_function rndis_function = { | ||
| 513 | .name = "rndis", | ||
| 514 | .init = rndis_function_init, | ||
| 515 | .cleanup = rndis_function_cleanup, | ||
| 516 | .bind_config = rndis_function_bind_config, | ||
| 517 | .unbind_config = rndis_function_unbind_config, | ||
| 518 | .attributes = rndis_function_attributes, | ||
| 519 | }; | ||
| 520 | |||
| 521 | |||
| 522 | struct mass_storage_function_config { | ||
| 523 | struct fsg_config fsg; | ||
| 524 | struct fsg_common *common; | ||
| 525 | }; | ||
| 526 | |||
| 527 | static int mass_storage_function_init(struct android_usb_function *f, | ||
| 528 | struct usb_composite_dev *cdev) | ||
| 529 | { | ||
| 530 | struct mass_storage_function_config *config; | ||
| 531 | struct fsg_common *common; | ||
| 532 | int err; | ||
| 533 | |||
| 534 | config = kzalloc(sizeof(struct mass_storage_function_config), | ||
| 535 | GFP_KERNEL); | ||
| 536 | if (!config) | ||
| 537 | return -ENOMEM; | ||
| 538 | |||
| 539 | config->fsg.nluns = 1; | ||
| 540 | config->fsg.luns[0].removable = 1; | ||
| 541 | |||
| 542 | common = fsg_common_init(NULL, cdev, &config->fsg); | ||
| 543 | if (IS_ERR(common)) { | ||
| 544 | kfree(config); | ||
| 545 | return PTR_ERR(common); | ||
| 546 | } | ||
| 547 | |||
| 548 | err = sysfs_create_link(&f->dev->kobj, | ||
| 549 | &common->luns[0].dev.kobj, | ||
| 550 | "lun"); | ||
| 551 | if (err) { | ||
| 552 | kfree(config); | ||
| 553 | return err; | ||
| 554 | } | ||
| 555 | |||
| 556 | config->common = common; | ||
| 557 | f->config = config; | ||
| 558 | return 0; | ||
| 559 | } | ||
| 560 | |||
| 561 | static void mass_storage_function_cleanup(struct android_usb_function *f) | ||
| 562 | { | ||
| 563 | kfree(f->config); | ||
| 564 | f->config = NULL; | ||
| 565 | } | ||
| 566 | |||
| 567 | static int mass_storage_function_bind_config(struct android_usb_function *f, | ||
| 568 | struct usb_configuration *c) | ||
| 569 | { | ||
| 570 | struct mass_storage_function_config *config = f->config; | ||
| 571 | return fsg_bind_config(c->cdev, c, config->common); | ||
| 572 | } | ||
| 573 | |||
| 574 | static ssize_t mass_storage_inquiry_show(struct device *dev, | ||
| 575 | struct device_attribute *attr, char *buf) | ||
| 576 | { | ||
| 577 | struct android_usb_function *f = dev_get_drvdata(dev); | ||
| 578 | struct mass_storage_function_config *config = f->config; | ||
| 579 | return sprintf(buf, "%s\n", config->common->inquiry_string); | ||
| 580 | } | ||
| 581 | |||
| 582 | static ssize_t mass_storage_inquiry_store(struct device *dev, | ||
| 583 | struct device_attribute *attr, const char *buf, size_t size) | ||
| 584 | { | ||
| 585 | struct android_usb_function *f = dev_get_drvdata(dev); | ||
| 586 | struct mass_storage_function_config *config = f->config; | ||
| 587 | if (size >= sizeof(config->common->inquiry_string)) | ||
| 588 | return -EINVAL; | ||
| 589 | if (sscanf(buf, "%s", config->common->inquiry_string) != 1) | ||
| 590 | return -EINVAL; | ||
| 591 | return size; | ||
| 592 | } | ||
| 593 | |||
| 594 | static DEVICE_ATTR(inquiry_string, S_IRUGO | S_IWUSR, | ||
| 595 | mass_storage_inquiry_show, | ||
| 596 | mass_storage_inquiry_store); | ||
| 597 | |||
| 598 | static struct device_attribute *mass_storage_function_attributes[] = { | ||
| 599 | &dev_attr_inquiry_string, | ||
| 600 | NULL | ||
| 601 | }; | ||
| 602 | |||
| 603 | static struct android_usb_function mass_storage_function = { | ||
| 604 | .name = "mass_storage", | ||
| 605 | .init = mass_storage_function_init, | ||
| 606 | .cleanup = mass_storage_function_cleanup, | ||
| 607 | .bind_config = mass_storage_function_bind_config, | ||
| 608 | .attributes = mass_storage_function_attributes, | ||
| 609 | }; | ||
| 610 | |||
| 611 | |||
| 612 | static int accessory_function_init(struct android_usb_function *f, | ||
| 613 | struct usb_composite_dev *cdev) | ||
| 614 | { | ||
| 615 | return acc_setup(); | ||
| 616 | } | ||
| 617 | |||
| 618 | static void accessory_function_cleanup(struct android_usb_function *f) | ||
| 619 | { | ||
| 620 | acc_cleanup(); | ||
| 621 | } | ||
| 622 | |||
| 623 | static int accessory_function_bind_config(struct android_usb_function *f, | ||
| 624 | struct usb_configuration *c) | ||
| 625 | { | ||
| 626 | return acc_bind_config(c); | ||
| 627 | } | ||
| 628 | |||
| 629 | static int accessory_function_ctrlrequest(struct android_usb_function *f, | ||
| 630 | struct usb_composite_dev *cdev, | ||
| 631 | const struct usb_ctrlrequest *c) | ||
| 632 | { | ||
| 633 | return acc_ctrlrequest(cdev, c); | ||
| 634 | } | ||
| 635 | |||
| 636 | static struct android_usb_function accessory_function = { | ||
| 637 | .name = "accessory", | ||
| 638 | .init = accessory_function_init, | ||
| 639 | .cleanup = accessory_function_cleanup, | ||
| 640 | .bind_config = accessory_function_bind_config, | ||
| 641 | .ctrlrequest = accessory_function_ctrlrequest, | ||
| 642 | }; | ||
| 643 | |||
| 644 | |||
| 645 | static struct android_usb_function *supported_functions[] = { | ||
| 646 | &adb_function, | ||
| 647 | &acm_function, | ||
| 648 | &mtp_function, | ||
| 649 | &ptp_function, | ||
| 650 | &rndis_function, | ||
| 651 | &mass_storage_function, | ||
| 652 | &accessory_function, | ||
| 653 | NULL | ||
| 654 | }; | ||
| 655 | |||
| 656 | |||
| 657 | static int android_init_functions(struct android_usb_function **functions, | ||
| 658 | struct usb_composite_dev *cdev) | ||
| 659 | { | ||
| 660 | struct android_dev *dev = _android_dev; | ||
| 661 | struct android_usb_function *f; | ||
| 662 | struct device_attribute **attrs; | ||
| 663 | struct device_attribute *attr; | ||
| 664 | int err; | ||
| 665 | int index = 0; | ||
| 666 | |||
| 667 | for (; (f = *functions++); index++) { | ||
| 668 | f->dev_name = kasprintf(GFP_KERNEL, "f_%s", f->name); | ||
| 669 | f->dev = device_create(android_class, dev->dev, | ||
| 670 | MKDEV(0, index), f, f->dev_name); | ||
| 671 | if (IS_ERR(f->dev)) { | ||
| 672 | pr_err("%s: Failed to create dev %s", __func__, | ||
| 673 | f->dev_name); | ||
| 674 | err = PTR_ERR(f->dev); | ||
| 675 | goto err_create; | ||
| 676 | } | ||
| 677 | |||
| 678 | if (f->init) { | ||
| 679 | err = f->init(f, cdev); | ||
| 680 | if (err) { | ||
| 681 | pr_err("%s: Failed to init %s", __func__, | ||
| 682 | f->name); | ||
| 683 | goto err_out; | ||
| 684 | } | ||
| 685 | } | ||
| 686 | |||
| 687 | attrs = f->attributes; | ||
| 688 | if (attrs) { | ||
| 689 | while ((attr = *attrs++) && !err) | ||
| 690 | err = device_create_file(f->dev, attr); | ||
| 691 | } | ||
| 692 | if (err) { | ||
| 693 | pr_err("%s: Failed to create function %s attributes", | ||
| 694 | __func__, f->name); | ||
| 695 | goto err_out; | ||
| 696 | } | ||
| 697 | } | ||
| 698 | return 0; | ||
| 699 | |||
| 700 | err_out: | ||
| 701 | device_destroy(android_class, f->dev->devt); | ||
| 702 | err_create: | ||
| 703 | kfree(f->dev_name); | ||
| 704 | return err; | ||
| 705 | } | ||
| 706 | |||
| 707 | static void android_cleanup_functions(struct android_usb_function **functions) | ||
| 708 | { | ||
| 709 | struct android_usb_function *f; | ||
| 710 | |||
| 711 | while (*functions) { | ||
| 712 | f = *functions++; | ||
| 713 | |||
| 714 | if (f->dev) { | ||
| 715 | device_destroy(android_class, f->dev->devt); | ||
| 716 | kfree(f->dev_name); | ||
| 717 | } | ||
| 718 | |||
| 719 | if (f->cleanup) | ||
| 720 | f->cleanup(f); | ||
| 721 | } | ||
| 722 | } | ||
| 723 | |||
| 724 | static int | ||
| 725 | android_bind_enabled_functions(struct android_dev *dev, | ||
| 726 | struct usb_configuration *c) | ||
| 727 | { | ||
| 728 | struct android_usb_function *f; | ||
| 729 | int ret; | ||
| 730 | |||
| 731 | list_for_each_entry(f, &dev->enabled_functions, enabled_list) { | ||
| 732 | ret = f->bind_config(f, c); | ||
| 733 | if (ret) { | ||
| 734 | pr_err("%s: %s failed", __func__, f->name); | ||
| 735 | return ret; | ||
| 736 | } | ||
| 737 | } | ||
| 738 | return 0; | ||
| 739 | } | ||
| 740 | |||
| 741 | static void | ||
| 742 | android_unbind_enabled_functions(struct android_dev *dev, | ||
| 743 | struct usb_configuration *c) | ||
| 744 | { | ||
| 745 | struct android_usb_function *f; | ||
| 746 | |||
| 747 | list_for_each_entry(f, &dev->enabled_functions, enabled_list) { | ||
| 748 | if (f->unbind_config) | ||
| 749 | f->unbind_config(f, c); | ||
| 750 | } | ||
| 751 | } | ||
| 752 | |||
| 753 | static int android_enable_function(struct android_dev *dev, char *name) | ||
| 754 | { | ||
| 755 | struct android_usb_function **functions = dev->functions; | ||
| 756 | struct android_usb_function *f; | ||
| 757 | while ((f = *functions++)) { | ||
| 758 | if (!strcmp(name, f->name)) { | ||
| 759 | list_add_tail(&f->enabled_list, &dev->enabled_functions); | ||
| 760 | return 0; | ||
| 761 | } | ||
| 762 | } | ||
| 763 | return -EINVAL; | ||
| 764 | } | ||
| 765 | |||
| 766 | /*-------------------------------------------------------------------------*/ | ||
| 767 | /* /sys/class/android_usb/android%d/ interface */ | ||
| 768 | |||
| 769 | static ssize_t | ||
| 770 | functions_show(struct device *pdev, struct device_attribute *attr, char *buf) | ||
| 771 | { | ||
| 772 | struct android_dev *dev = dev_get_drvdata(pdev); | ||
| 773 | struct android_usb_function *f; | ||
| 774 | char *buff = buf; | ||
| 775 | |||
| 776 | mutex_lock(&dev->mutex); | ||
| 777 | |||
| 778 | list_for_each_entry(f, &dev->enabled_functions, enabled_list) | ||
| 779 | buff += sprintf(buff, "%s,", f->name); | ||
| 780 | |||
| 781 | mutex_unlock(&dev->mutex); | ||
| 782 | |||
| 783 | if (buff != buf) | ||
| 784 | *(buff-1) = '\n'; | ||
| 785 | return buff - buf; | ||
| 786 | } | ||
| 787 | |||
| 788 | static ssize_t | ||
| 789 | functions_store(struct device *pdev, struct device_attribute *attr, | ||
| 790 | const char *buff, size_t size) | ||
| 791 | { | ||
| 792 | struct android_dev *dev = dev_get_drvdata(pdev); | ||
| 793 | char *name; | ||
| 794 | char buf[256], *b; | ||
| 795 | int err; | ||
| 796 | |||
| 797 | mutex_lock(&dev->mutex); | ||
| 798 | |||
| 799 | if (dev->enabled) { | ||
| 800 | mutex_unlock(&dev->mutex); | ||
| 801 | return -EBUSY; | ||
| 802 | } | ||
| 803 | |||
| 804 | INIT_LIST_HEAD(&dev->enabled_functions); | ||
| 805 | |||
| 806 | strncpy(buf, buff, sizeof(buf)); | ||
| 807 | b = strim(buf); | ||
| 808 | |||
| 809 | while (b) { | ||
| 810 | name = strsep(&b, ","); | ||
| 811 | if (name) { | ||
| 812 | err = android_enable_function(dev, name); | ||
| 813 | if (err) | ||
| 814 | pr_err("android_usb: Cannot enable '%s'", name); | ||
| 815 | } | ||
| 816 | } | ||
| 817 | |||
| 818 | mutex_unlock(&dev->mutex); | ||
| 819 | |||
| 820 | return size; | ||
| 821 | } | ||
| 822 | |||
| 823 | static ssize_t enable_show(struct device *pdev, struct device_attribute *attr, | ||
| 824 | char *buf) | ||
| 825 | { | ||
| 826 | struct android_dev *dev = dev_get_drvdata(pdev); | ||
| 827 | return sprintf(buf, "%d\n", dev->enabled); | ||
| 828 | } | ||
| 829 | |||
| 830 | static ssize_t enable_store(struct device *pdev, struct device_attribute *attr, | ||
| 831 | const char *buff, size_t size) | ||
| 832 | { | ||
| 833 | struct android_dev *dev = dev_get_drvdata(pdev); | ||
| 834 | struct usb_composite_dev *cdev = dev->cdev; | ||
| 835 | int enabled = 0; | ||
| 836 | |||
| 837 | mutex_lock(&dev->mutex); | ||
| 838 | |||
| 839 | sscanf(buff, "%d", &enabled); | ||
| 840 | if (enabled && !dev->enabled) { | ||
| 841 | /* update values in composite driver's copy of device descriptor */ | ||
| 842 | cdev->desc.idVendor = device_desc.idVendor; | ||
| 843 | cdev->desc.idProduct = device_desc.idProduct; | ||
| 844 | cdev->desc.bcdDevice = device_desc.bcdDevice; | ||
| 845 | cdev->desc.bDeviceClass = device_desc.bDeviceClass; | ||
| 846 | cdev->desc.bDeviceSubClass = device_desc.bDeviceSubClass; | ||
| 847 | cdev->desc.bDeviceProtocol = device_desc.bDeviceProtocol; | ||
| 848 | usb_add_config(cdev, &android_config_driver, | ||
| 849 | android_bind_config); | ||
| 850 | usb_gadget_connect(cdev->gadget); | ||
| 851 | dev->enabled = true; | ||
| 852 | } else if (!enabled && dev->enabled) { | ||
| 853 | usb_gadget_disconnect(cdev->gadget); | ||
| 854 | /* Cancel pending control requests */ | ||
| 855 | usb_ep_dequeue(cdev->gadget->ep0, cdev->req); | ||
| 856 | usb_remove_config(cdev, &android_config_driver); | ||
| 857 | dev->enabled = false; | ||
| 858 | } else { | ||
| 859 | pr_err("android_usb: already %s\n", | ||
| 860 | dev->enabled ? "enabled" : "disabled"); | ||
| 861 | } | ||
| 862 | |||
| 863 | mutex_unlock(&dev->mutex); | ||
| 864 | return size; | ||
| 865 | } | ||
| 866 | |||
| 867 | static ssize_t state_show(struct device *pdev, struct device_attribute *attr, | ||
| 868 | char *buf) | ||
| 869 | { | ||
| 870 | struct android_dev *dev = dev_get_drvdata(pdev); | ||
| 871 | struct usb_composite_dev *cdev = dev->cdev; | ||
| 872 | char *state = "DISCONNECTED"; | ||
| 873 | unsigned long flags; | ||
| 874 | |||
| 875 | if (!cdev) | ||
| 876 | goto out; | ||
| 877 | |||
| 878 | spin_lock_irqsave(&cdev->lock, flags); | ||
| 879 | if (cdev->config) | ||
| 880 | state = "CONFIGURED"; | ||
| 881 | else if (dev->connected) | ||
| 882 | state = "CONNECTED"; | ||
| 883 | spin_unlock_irqrestore(&cdev->lock, flags); | ||
| 884 | out: | ||
| 885 | return sprintf(buf, "%s\n", state); | ||
| 886 | } | ||
| 887 | |||
| 888 | #define DESCRIPTOR_ATTR(field, format_string) \ | ||
| 889 | static ssize_t \ | ||
| 890 | field ## _show(struct device *dev, struct device_attribute *attr, \ | ||
| 891 | char *buf) \ | ||
| 892 | { \ | ||
| 893 | return sprintf(buf, format_string, device_desc.field); \ | ||
| 894 | } \ | ||
| 895 | static ssize_t \ | ||
| 896 | field ## _store(struct device *dev, struct device_attribute *attr, \ | ||
| 897 | const char *buf, size_t size) \ | ||
| 898 | { \ | ||
| 899 | int value; \ | ||
| 900 | if (sscanf(buf, format_string, &value) == 1) { \ | ||
| 901 | device_desc.field = value; \ | ||
| 902 | return size; \ | ||
| 903 | } \ | ||
| 904 | return -1; \ | ||
| 905 | } \ | ||
| 906 | static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, field ## _show, field ## _store); | ||
| 907 | |||
| 908 | #define DESCRIPTOR_STRING_ATTR(field, buffer) \ | ||
| 909 | static ssize_t \ | ||
| 910 | field ## _show(struct device *dev, struct device_attribute *attr, \ | ||
| 911 | char *buf) \ | ||
| 912 | { \ | ||
| 913 | return sprintf(buf, "%s", buffer); \ | ||
| 914 | } \ | ||
| 915 | static ssize_t \ | ||
| 916 | field ## _store(struct device *dev, struct device_attribute *attr, \ | ||
| 917 | const char *buf, size_t size) \ | ||
| 918 | { \ | ||
| 919 | if (size >= sizeof(buffer)) return -EINVAL; \ | ||
| 920 | if (sscanf(buf, "%s", buffer) == 1) { \ | ||
| 921 | return size; \ | ||
| 922 | } \ | ||
| 923 | return -1; \ | ||
| 924 | } \ | ||
| 925 | static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, field ## _show, field ## _store); | ||
| 926 | |||
| 927 | |||
| 928 | DESCRIPTOR_ATTR(idVendor, "%04x\n") | ||
| 929 | DESCRIPTOR_ATTR(idProduct, "%04x\n") | ||
| 930 | DESCRIPTOR_ATTR(bcdDevice, "%04x\n") | ||
| 931 | DESCRIPTOR_ATTR(bDeviceClass, "%d\n") | ||
| 932 | DESCRIPTOR_ATTR(bDeviceSubClass, "%d\n") | ||
| 933 | DESCRIPTOR_ATTR(bDeviceProtocol, "%d\n") | ||
| 934 | DESCRIPTOR_STRING_ATTR(iManufacturer, manufacturer_string) | ||
| 935 | DESCRIPTOR_STRING_ATTR(iProduct, product_string) | ||
| 936 | DESCRIPTOR_STRING_ATTR(iSerial, serial_string) | ||
| 937 | |||
| 938 | static DEVICE_ATTR(functions, S_IRUGO | S_IWUSR, functions_show, functions_store); | ||
| 939 | static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, enable_show, enable_store); | ||
| 940 | static DEVICE_ATTR(state, S_IRUGO, state_show, NULL); | ||
| 941 | |||
| 942 | static struct device_attribute *android_usb_attributes[] = { | ||
| 943 | &dev_attr_idVendor, | ||
| 944 | &dev_attr_idProduct, | ||
| 945 | &dev_attr_bcdDevice, | ||
| 946 | &dev_attr_bDeviceClass, | ||
| 947 | &dev_attr_bDeviceSubClass, | ||
| 948 | &dev_attr_bDeviceProtocol, | ||
| 949 | &dev_attr_iManufacturer, | ||
| 950 | &dev_attr_iProduct, | ||
| 951 | &dev_attr_iSerial, | ||
| 952 | &dev_attr_functions, | ||
| 953 | &dev_attr_enable, | ||
| 954 | &dev_attr_state, | ||
| 955 | NULL | ||
| 956 | }; | ||
| 957 | |||
| 958 | /*-------------------------------------------------------------------------*/ | ||
| 959 | /* Composite driver */ | ||
| 960 | |||
| 961 | static int android_bind_config(struct usb_configuration *c) | ||
| 962 | { | ||
| 963 | struct android_dev *dev = _android_dev; | ||
| 964 | int ret = 0; | ||
| 965 | |||
| 966 | ret = android_bind_enabled_functions(dev, c); | ||
| 967 | if (ret) | ||
| 968 | return ret; | ||
| 969 | |||
| 970 | return 0; | ||
| 971 | } | ||
| 972 | |||
| 973 | static void android_unbind_config(struct usb_configuration *c) | ||
| 974 | { | ||
| 975 | struct android_dev *dev = _android_dev; | ||
| 976 | |||
| 977 | android_unbind_enabled_functions(dev, c); | ||
| 978 | } | ||
| 979 | |||
| 980 | static int android_bind(struct usb_composite_dev *cdev) | ||
| 981 | { | ||
| 982 | struct android_dev *dev = _android_dev; | ||
| 983 | struct usb_gadget *gadget = cdev->gadget; | ||
| 984 | int gcnum, id, ret; | ||
| 985 | |||
| 986 | usb_gadget_disconnect(gadget); | ||
| 987 | |||
| 988 | ret = android_init_functions(dev->functions, cdev); | ||
| 989 | if (ret) | ||
| 990 | return ret; | ||
| 991 | |||
| 992 | /* Allocate string descriptor numbers ... note that string | ||
| 993 | * contents can be overridden by the composite_dev glue. | ||
| 994 | */ | ||
| 995 | id = usb_string_id(cdev); | ||
| 996 | if (id < 0) | ||
| 997 | return id; | ||
| 998 | strings_dev[STRING_MANUFACTURER_IDX].id = id; | ||
| 999 | device_desc.iManufacturer = id; | ||
| 1000 | |||
| 1001 | id = usb_string_id(cdev); | ||
| 1002 | if (id < 0) | ||
| 1003 | return id; | ||
| 1004 | strings_dev[STRING_PRODUCT_IDX].id = id; | ||
| 1005 | device_desc.iProduct = id; | ||
| 1006 | |||
| 1007 | /* Default strings - should be updated by userspace */ | ||
| 1008 | strncpy(manufacturer_string, "Android", sizeof(manufacturer_string) - 1); | ||
| 1009 | strncpy(product_string, "Android", sizeof(product_string) - 1); | ||
| 1010 | strncpy(serial_string, "0123456789ABCDEF", sizeof(serial_string) - 1); | ||
| 1011 | |||
| 1012 | id = usb_string_id(cdev); | ||
| 1013 | if (id < 0) | ||
| 1014 | return id; | ||
| 1015 | strings_dev[STRING_SERIAL_IDX].id = id; | ||
| 1016 | device_desc.iSerialNumber = id; | ||
| 1017 | |||
| 1018 | gcnum = usb_gadget_controller_number(gadget); | ||
| 1019 | if (gcnum >= 0) | ||
| 1020 | device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum); | ||
| 1021 | else { | ||
| 1022 | /* gadget zero is so simple (for now, no altsettings) that | ||
| 1023 | * it SHOULD NOT have problems with bulk-capable hardware. | ||
| 1024 | * so just warn about unrcognized controllers -- don't panic. | ||
| 1025 | * | ||
| 1026 | * things like configuration and altsetting numbering | ||
| 1027 | * can need hardware-specific attention though. | ||
| 1028 | */ | ||
| 1029 | pr_warning("%s: controller '%s' not recognized\n", | ||
| 1030 | longname, gadget->name); | ||
| 1031 | device_desc.bcdDevice = __constant_cpu_to_le16(0x9999); | ||
| 1032 | } | ||
| 1033 | |||
| 1034 | dev->cdev = cdev; | ||
| 1035 | |||
| 1036 | return 0; | ||
| 1037 | } | ||
| 1038 | |||
| 1039 | static int android_usb_unbind(struct usb_composite_dev *cdev) | ||
| 1040 | { | ||
| 1041 | struct android_dev *dev = _android_dev; | ||
| 1042 | |||
| 1043 | cancel_work_sync(&dev->work); | ||
| 1044 | android_cleanup_functions(dev->functions); | ||
| 1045 | return 0; | ||
| 1046 | } | ||
| 1047 | |||
| 1048 | static struct usb_composite_driver android_usb_driver = { | ||
| 1049 | .name = "android_usb", | ||
| 1050 | .dev = &device_desc, | ||
| 1051 | .strings = dev_strings, | ||
| 1052 | .unbind = android_usb_unbind, | ||
| 1053 | .max_speed = USB_SPEED_HIGH, | ||
| 1054 | }; | ||
| 1055 | |||
| 1056 | static int | ||
| 1057 | android_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *c) | ||
| 1058 | { | ||
| 1059 | struct android_dev *dev = _android_dev; | ||
| 1060 | struct usb_composite_dev *cdev = get_gadget_data(gadget); | ||
| 1061 | struct usb_request *req = cdev->req; | ||
| 1062 | struct android_usb_function *f; | ||
| 1063 | int value = -EOPNOTSUPP; | ||
| 1064 | unsigned long flags; | ||
| 1065 | |||
| 1066 | req->zero = 0; | ||
| 1067 | req->complete = composite_setup_complete; | ||
| 1068 | req->length = 0; | ||
| 1069 | gadget->ep0->driver_data = cdev; | ||
| 1070 | |||
| 1071 | list_for_each_entry(f, &dev->enabled_functions, enabled_list) { | ||
| 1072 | if (f->ctrlrequest) { | ||
| 1073 | value = f->ctrlrequest(f, cdev, c); | ||
| 1074 | if (value >= 0) | ||
| 1075 | break; | ||
| 1076 | } | ||
| 1077 | } | ||
| 1078 | |||
| 1079 | /* Special case the accessory function. | ||
| 1080 | * It needs to handle control requests before it is enabled. | ||
| 1081 | */ | ||
| 1082 | if (value < 0) | ||
| 1083 | value = acc_ctrlrequest(cdev, c); | ||
| 1084 | |||
| 1085 | if (value < 0) | ||
| 1086 | value = composite_setup(gadget, c); | ||
| 1087 | |||
| 1088 | spin_lock_irqsave(&cdev->lock, flags); | ||
| 1089 | if (!dev->connected) { | ||
| 1090 | dev->connected = 1; | ||
| 1091 | schedule_work(&dev->work); | ||
| 1092 | } | ||
| 1093 | else if (c->bRequest == USB_REQ_SET_CONFIGURATION && cdev->config) { | ||
| 1094 | schedule_work(&dev->work); | ||
| 1095 | } | ||
| 1096 | spin_unlock_irqrestore(&cdev->lock, flags); | ||
| 1097 | |||
| 1098 | return value; | ||
| 1099 | } | ||
| 1100 | |||
| 1101 | static void android_disconnect(struct usb_gadget *gadget) | ||
| 1102 | { | ||
| 1103 | struct android_dev *dev = _android_dev; | ||
| 1104 | struct usb_composite_dev *cdev = get_gadget_data(gadget); | ||
| 1105 | unsigned long flags; | ||
| 1106 | |||
| 1107 | composite_disconnect(gadget); | ||
| 1108 | |||
| 1109 | spin_lock_irqsave(&cdev->lock, flags); | ||
| 1110 | dev->connected = 0; | ||
| 1111 | schedule_work(&dev->work); | ||
| 1112 | spin_unlock_irqrestore(&cdev->lock, flags); | ||
| 1113 | } | ||
| 1114 | |||
| 1115 | static int android_create_device(struct android_dev *dev) | ||
| 1116 | { | ||
| 1117 | struct device_attribute **attrs = android_usb_attributes; | ||
| 1118 | struct device_attribute *attr; | ||
| 1119 | int err; | ||
| 1120 | |||
| 1121 | dev->dev = device_create(android_class, NULL, | ||
| 1122 | MKDEV(0, 0), NULL, "android0"); | ||
| 1123 | if (IS_ERR(dev->dev)) | ||
| 1124 | return PTR_ERR(dev->dev); | ||
| 1125 | |||
| 1126 | dev_set_drvdata(dev->dev, dev); | ||
| 1127 | |||
| 1128 | while ((attr = *attrs++)) { | ||
| 1129 | err = device_create_file(dev->dev, attr); | ||
| 1130 | if (err) { | ||
| 1131 | device_destroy(android_class, dev->dev->devt); | ||
| 1132 | return err; | ||
| 1133 | } | ||
| 1134 | } | ||
| 1135 | return 0; | ||
| 1136 | } | ||
| 1137 | |||
| 1138 | |||
| 1139 | static int __init init(void) | ||
| 1140 | { | ||
| 1141 | struct android_dev *dev; | ||
| 1142 | int err; | ||
| 1143 | |||
| 1144 | android_class = class_create(THIS_MODULE, "android_usb"); | ||
| 1145 | if (IS_ERR(android_class)) | ||
| 1146 | return PTR_ERR(android_class); | ||
| 1147 | |||
| 1148 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||
| 1149 | if (!dev) | ||
| 1150 | return -ENOMEM; | ||
| 1151 | |||
| 1152 | dev->functions = supported_functions; | ||
| 1153 | INIT_LIST_HEAD(&dev->enabled_functions); | ||
| 1154 | INIT_WORK(&dev->work, android_work); | ||
| 1155 | mutex_init(&dev->mutex); | ||
| 1156 | |||
| 1157 | err = android_create_device(dev); | ||
| 1158 | if (err) { | ||
| 1159 | class_destroy(android_class); | ||
| 1160 | kfree(dev); | ||
| 1161 | return err; | ||
| 1162 | } | ||
| 1163 | |||
| 1164 | _android_dev = dev; | ||
| 1165 | |||
| 1166 | /* Override composite driver functions */ | ||
| 1167 | composite_driver.setup = android_setup; | ||
| 1168 | composite_driver.disconnect = android_disconnect; | ||
| 1169 | |||
| 1170 | return usb_composite_probe(&android_usb_driver, android_bind); | ||
| 1171 | } | ||
| 1172 | module_init(init); | ||
| 1173 | |||
| 1174 | static void __exit cleanup(void) | ||
| 1175 | { | ||
| 1176 | usb_composite_unregister(&android_usb_driver); | ||
| 1177 | class_destroy(android_class); | ||
| 1178 | kfree(_android_dev); | ||
| 1179 | _android_dev = NULL; | ||
| 1180 | } | ||
| 1181 | module_exit(cleanup); | ||
diff --git a/drivers/usb/gadget/ci13xxx_msm.c b/drivers/usb/gadget/ci13xxx_msm.c new file mode 100644 index 00000000000..470981ad6f7 --- /dev/null +++ b/drivers/usb/gadget/ci13xxx_msm.c | |||
| @@ -0,0 +1,135 @@ | |||
| 1 | /* Copyright (c) 2010, Code Aurora Forum. All rights reserved. | ||
| 2 | * | ||
| 3 | * This program is free software; you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License version 2 and | ||
| 5 | * only version 2 as published by the Free Software Foundation. | ||
| 6 | * | ||
| 7 | * This program is distributed in the hope that it will be useful, | ||
| 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 10 | * GNU General Public License for more details. | ||
| 11 | * | ||
| 12 | * You should have received a copy of the GNU General Public License | ||
| 13 | * along with this program; if not, write to the Free Software | ||
| 14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
| 15 | * 02110-1301, USA. | ||
| 16 | * | ||
| 17 | */ | ||
| 18 | |||
| 19 | #include <linux/module.h> | ||
| 20 | #include <linux/platform_device.h> | ||
| 21 | #include <linux/pm_runtime.h> | ||
| 22 | #include <linux/usb/msm_hsusb_hw.h> | ||
| 23 | #include <linux/usb/ulpi.h> | ||
| 24 | |||
| 25 | #include "ci13xxx_udc.c" | ||
| 26 | |||
| 27 | #define MSM_USB_BASE (udc->regs) | ||
| 28 | |||
| 29 | static irqreturn_t msm_udc_irq(int irq, void *data) | ||
| 30 | { | ||
| 31 | return udc_irq(); | ||
| 32 | } | ||
| 33 | |||
| 34 | static void ci13xxx_msm_notify_event(struct ci13xxx *udc, unsigned event) | ||
| 35 | { | ||
| 36 | struct device *dev = udc->gadget.dev.parent; | ||
| 37 | int val; | ||
| 38 | |||
| 39 | switch (event) { | ||
| 40 | case CI13XXX_CONTROLLER_RESET_EVENT: | ||
| 41 | dev_dbg(dev, "CI13XXX_CONTROLLER_RESET_EVENT received\n"); | ||
| 42 | writel(0, USB_AHBBURST); | ||
| 43 | writel(0, USB_AHBMODE); | ||
| 44 | break; | ||
| 45 | case CI13XXX_CONTROLLER_STOPPED_EVENT: | ||
| 46 | dev_dbg(dev, "CI13XXX_CONTROLLER_STOPPED_EVENT received\n"); | ||
| 47 | /* | ||
| 48 | * Put the transceiver in non-driving mode. Otherwise host | ||
| 49 | * may not detect soft-disconnection. | ||
| 50 | */ | ||
| 51 | val = otg_io_read(udc->transceiver, ULPI_FUNC_CTRL); | ||
| 52 | val &= ~ULPI_FUNC_CTRL_OPMODE_MASK; | ||
| 53 | val |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING; | ||
| 54 | otg_io_write(udc->transceiver, val, ULPI_FUNC_CTRL); | ||
| 55 | break; | ||
| 56 | default: | ||
| 57 | dev_dbg(dev, "unknown ci13xxx_udc event\n"); | ||
| 58 | break; | ||
| 59 | } | ||
| 60 | } | ||
| 61 | |||
| 62 | static struct ci13xxx_udc_driver ci13xxx_msm_udc_driver = { | ||
| 63 | .name = "ci13xxx_msm", | ||
| 64 | .flags = CI13XXX_REGS_SHARED | | ||
| 65 | CI13XXX_REQUIRE_TRANSCEIVER | | ||
| 66 | CI13XXX_PULLUP_ON_VBUS | | ||
| 67 | CI13XXX_DISABLE_STREAMING, | ||
| 68 | |||
| 69 | .notify_event = ci13xxx_msm_notify_event, | ||
| 70 | }; | ||
| 71 | |||
| 72 | static int ci13xxx_msm_probe(struct platform_device *pdev) | ||
| 73 | { | ||
| 74 | struct resource *res; | ||
| 75 | void __iomem *regs; | ||
| 76 | int irq; | ||
| 77 | int ret; | ||
| 78 | |||
| 79 | dev_dbg(&pdev->dev, "ci13xxx_msm_probe\n"); | ||
| 80 | |||
| 81 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 82 | if (!res) { | ||
| 83 | dev_err(&pdev->dev, "failed to get platform resource mem\n"); | ||
| 84 | return -ENXIO; | ||
| 85 | } | ||
| 86 | |||
| 87 | regs = ioremap(res->start, resource_size(res)); | ||
| 88 | if (!regs) { | ||
| 89 | dev_err(&pdev->dev, "ioremap failed\n"); | ||
| 90 | return -ENOMEM; | ||
| 91 | } | ||
| 92 | |||
| 93 | ret = udc_probe(&ci13xxx_msm_udc_driver, &pdev->dev, regs); | ||
| 94 | if (ret < 0) { | ||
| 95 | dev_err(&pdev->dev, "udc_probe failed\n"); | ||
| 96 | goto iounmap; | ||
| 97 | } | ||
| 98 | |||
| 99 | irq = platform_get_irq(pdev, 0); | ||
| 100 | if (irq < 0) { | ||
| 101 | dev_err(&pdev->dev, "IRQ not found\n"); | ||
| 102 | ret = -ENXIO; | ||
| 103 | goto udc_remove; | ||
| 104 | } | ||
| 105 | |||
| 106 | ret = request_irq(irq, msm_udc_irq, IRQF_SHARED, pdev->name, pdev); | ||
| 107 | if (ret < 0) { | ||
| 108 | dev_err(&pdev->dev, "request_irq failed\n"); | ||
| 109 | goto udc_remove; | ||
| 110 | } | ||
| 111 | |||
| 112 | pm_runtime_no_callbacks(&pdev->dev); | ||
| 113 | pm_runtime_enable(&pdev->dev); | ||
| 114 | |||
| 115 | return 0; | ||
| 116 | |||
| 117 | udc_remove: | ||
| 118 | udc_remove(); | ||
| 119 | iounmap: | ||
| 120 | iounmap(regs); | ||
| 121 | |||
| 122 | return ret; | ||
| 123 | } | ||
| 124 | |||
| 125 | static struct platform_driver ci13xxx_msm_driver = { | ||
| 126 | .probe = ci13xxx_msm_probe, | ||
| 127 | .driver = { .name = "msm_hsusb", }, | ||
| 128 | }; | ||
| 129 | MODULE_ALIAS("platform:msm_hsusb"); | ||
| 130 | |||
| 131 | static int __init ci13xxx_msm_init(void) | ||
| 132 | { | ||
| 133 | return platform_driver_register(&ci13xxx_msm_driver); | ||
| 134 | } | ||
| 135 | module_init(ci13xxx_msm_init); | ||
diff --git a/drivers/usb/gadget/ci13xxx_pci.c b/drivers/usb/gadget/ci13xxx_pci.c new file mode 100644 index 00000000000..883ab5e832d --- /dev/null +++ b/drivers/usb/gadget/ci13xxx_pci.c | |||
| @@ -0,0 +1,176 @@ | |||
| 1 | /* | ||
| 2 | * ci13xxx_pci.c - MIPS USB IP core family device controller | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved. | ||
| 5 | * | ||
| 6 | * Author: David Lopo | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include <linux/module.h> | ||
| 14 | #include <linux/pci.h> | ||
| 15 | |||
| 16 | #include "ci13xxx_udc.c" | ||
| 17 | |||
| 18 | /* driver name */ | ||
| 19 | #define UDC_DRIVER_NAME "ci13xxx_pci" | ||
| 20 | |||
| 21 | /****************************************************************************** | ||
| 22 | * PCI block | ||
| 23 | *****************************************************************************/ | ||
| 24 | /** | ||
| 25 | * ci13xxx_pci_irq: interrut handler | ||
| 26 | * @irq: irq number | ||
| 27 | * @pdev: USB Device Controller interrupt source | ||
| 28 | * | ||
| 29 | * This function returns IRQ_HANDLED if the IRQ has been handled | ||
| 30 | * This is an ISR don't trace, use attribute interface instead | ||
| 31 | */ | ||
| 32 | static irqreturn_t ci13xxx_pci_irq(int irq, void *pdev) | ||
| 33 | { | ||
| 34 | if (irq == 0) { | ||
| 35 | dev_err(&((struct pci_dev *)pdev)->dev, "Invalid IRQ0 usage!"); | ||
| 36 | return IRQ_HANDLED; | ||
| 37 | } | ||
| 38 | return udc_irq(); | ||
| 39 | } | ||
| 40 | |||
| 41 | static struct ci13xxx_udc_driver ci13xxx_pci_udc_driver = { | ||
| 42 | .name = UDC_DRIVER_NAME, | ||
| 43 | }; | ||
| 44 | |||
| 45 | /** | ||
| 46 | * ci13xxx_pci_probe: PCI probe | ||
| 47 | * @pdev: USB device controller being probed | ||
| 48 | * @id: PCI hotplug ID connecting controller to UDC framework | ||
| 49 | * | ||
| 50 | * This function returns an error code | ||
| 51 | * Allocates basic PCI resources for this USB device controller, and then | ||
| 52 | * invokes the udc_probe() method to start the UDC associated with it | ||
| 53 | */ | ||
| 54 | static int __devinit ci13xxx_pci_probe(struct pci_dev *pdev, | ||
| 55 | const struct pci_device_id *id) | ||
| 56 | { | ||
| 57 | void __iomem *regs = NULL; | ||
| 58 | int retval = 0; | ||
| 59 | |||
| 60 | if (id == NULL) | ||
| 61 | return -EINVAL; | ||
| 62 | |||
| 63 | retval = pci_enable_device(pdev); | ||
| 64 | if (retval) | ||
| 65 | goto done; | ||
| 66 | |||
| 67 | if (!pdev->irq) { | ||
| 68 | dev_err(&pdev->dev, "No IRQ, check BIOS/PCI setup!"); | ||
| 69 | retval = -ENODEV; | ||
| 70 | goto disable_device; | ||
| 71 | } | ||
| 72 | |||
| 73 | retval = pci_request_regions(pdev, UDC_DRIVER_NAME); | ||
| 74 | if (retval) | ||
| 75 | goto disable_device; | ||
| 76 | |||
| 77 | /* BAR 0 holds all the registers */ | ||
| 78 | regs = pci_iomap(pdev, 0, 0); | ||
| 79 | if (!regs) { | ||
| 80 | dev_err(&pdev->dev, "Error mapping memory!"); | ||
| 81 | retval = -EFAULT; | ||
| 82 | goto release_regions; | ||
| 83 | } | ||
| 84 | pci_set_drvdata(pdev, (__force void *)regs); | ||
| 85 | |||
| 86 | pci_set_master(pdev); | ||
| 87 | pci_try_set_mwi(pdev); | ||
| 88 | |||
| 89 | retval = udc_probe(&ci13xxx_pci_udc_driver, &pdev->dev, regs); | ||
| 90 | if (retval) | ||
| 91 | goto iounmap; | ||
| 92 | |||
| 93 | /* our device does not have MSI capability */ | ||
| 94 | |||
| 95 | retval = request_irq(pdev->irq, ci13xxx_pci_irq, IRQF_SHARED, | ||
| 96 | UDC_DRIVER_NAME, pdev); | ||
| 97 | if (retval) | ||
| 98 | goto gadget_remove; | ||
| 99 | |||
| 100 | return 0; | ||
| 101 | |||
| 102 | gadget_remove: | ||
| 103 | udc_remove(); | ||
| 104 | iounmap: | ||
| 105 | pci_iounmap(pdev, regs); | ||
| 106 | release_regions: | ||
| 107 | pci_release_regions(pdev); | ||
| 108 | disable_device: | ||
| 109 | pci_disable_device(pdev); | ||
| 110 | done: | ||
| 111 | return retval; | ||
| 112 | } | ||
| 113 | |||
| 114 | /** | ||
| 115 | * ci13xxx_pci_remove: PCI remove | ||
| 116 | * @pdev: USB Device Controller being removed | ||
| 117 | * | ||
| 118 | * Reverses the effect of ci13xxx_pci_probe(), | ||
| 119 | * first invoking the udc_remove() and then releases | ||
| 120 | * all PCI resources allocated for this USB device controller | ||
| 121 | */ | ||
| 122 | static void __devexit ci13xxx_pci_remove(struct pci_dev *pdev) | ||
| 123 | { | ||
| 124 | free_irq(pdev->irq, pdev); | ||
| 125 | udc_remove(); | ||
| 126 | pci_iounmap(pdev, (__force void __iomem *)pci_get_drvdata(pdev)); | ||
| 127 | pci_release_regions(pdev); | ||
| 128 | pci_disable_device(pdev); | ||
| 129 | } | ||
| 130 | |||
| 131 | /** | ||
| 132 | * PCI device table | ||
| 133 | * PCI device structure | ||
| 134 | * | ||
| 135 | * Check "pci.h" for details | ||
| 136 | */ | ||
| 137 | static DEFINE_PCI_DEVICE_TABLE(ci13xxx_pci_id_table) = { | ||
| 138 | { PCI_DEVICE(0x153F, 0x1004) }, | ||
| 139 | { PCI_DEVICE(0x153F, 0x1006) }, | ||
| 140 | { 0, 0, 0, 0, 0, 0, 0 /* end: all zeroes */ } | ||
| 141 | }; | ||
| 142 | MODULE_DEVICE_TABLE(pci, ci13xxx_pci_id_table); | ||
| 143 | |||
| 144 | static struct pci_driver ci13xxx_pci_driver = { | ||
| 145 | .name = UDC_DRIVER_NAME, | ||
| 146 | .id_table = ci13xxx_pci_id_table, | ||
| 147 | .probe = ci13xxx_pci_probe, | ||
| 148 | .remove = __devexit_p(ci13xxx_pci_remove), | ||
| 149 | }; | ||
| 150 | |||
| 151 | /** | ||
| 152 | * ci13xxx_pci_init: module init | ||
| 153 | * | ||
| 154 | * Driver load | ||
| 155 | */ | ||
| 156 | static int __init ci13xxx_pci_init(void) | ||
| 157 | { | ||
| 158 | return pci_register_driver(&ci13xxx_pci_driver); | ||
| 159 | } | ||
| 160 | module_init(ci13xxx_pci_init); | ||
| 161 | |||
| 162 | /** | ||
| 163 | * ci13xxx_pci_exit: module exit | ||
| 164 | * | ||
| 165 | * Driver unload | ||
| 166 | */ | ||
| 167 | static void __exit ci13xxx_pci_exit(void) | ||
| 168 | { | ||
| 169 | pci_unregister_driver(&ci13xxx_pci_driver); | ||
| 170 | } | ||
| 171 | module_exit(ci13xxx_pci_exit); | ||
| 172 | |||
| 173 | MODULE_AUTHOR("MIPS - David Lopo <dlopo@chipidea.mips.com>"); | ||
| 174 | MODULE_DESCRIPTION("MIPS CI13XXX USB Peripheral Controller"); | ||
| 175 | MODULE_LICENSE("GPL"); | ||
| 176 | MODULE_VERSION("June 2008"); | ||
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c new file mode 100644 index 00000000000..1265a8502ea --- /dev/null +++ b/drivers/usb/gadget/ci13xxx_udc.c | |||
| @@ -0,0 +1,2977 @@ | |||
| 1 | /* | ||
| 2 | * ci13xxx_udc.c - MIPS USB IP core family device controller | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved. | ||
| 5 | * | ||
| 6 | * Author: David Lopo | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | |||
| 13 | /* | ||
| 14 | * Description: MIPS USB IP core family device controller | ||
| 15 | * Currently it only supports IP part number CI13412 | ||
| 16 | * | ||
| 17 | * This driver is composed of several blocks: | ||
| 18 | * - HW: hardware interface | ||
| 19 | * - DBG: debug facilities (optional) | ||
| 20 | * - UTIL: utilities | ||
| 21 | * - ISR: interrupts handling | ||
| 22 | * - ENDPT: endpoint operations (Gadget API) | ||
| 23 | * - GADGET: gadget operations (Gadget API) | ||
| 24 | * - BUS: bus glue code, bus abstraction layer | ||
| 25 | * | ||
| 26 | * Compile Options | ||
| 27 | * - CONFIG_USB_GADGET_DEBUG_FILES: enable debug facilities | ||
| 28 | * - STALL_IN: non-empty bulk-in pipes cannot be halted | ||
| 29 | * if defined mass storage compliance succeeds but with warnings | ||
| 30 | * => case 4: Hi > Dn | ||
| 31 | * => case 5: Hi > Di | ||
| 32 | * => case 8: Hi <> Do | ||
| 33 | * if undefined usbtest 13 fails | ||
| 34 | * - TRACE: enable function tracing (depends on DEBUG) | ||
| 35 | * | ||
| 36 | * Main Features | ||
| 37 | * - Chapter 9 & Mass Storage Compliance with Gadget File Storage | ||
| 38 | * - Chapter 9 Compliance with Gadget Zero (STALL_IN undefined) | ||
| 39 | * - Normal & LPM support | ||
| 40 | * | ||
| 41 | * USBTEST Report | ||
| 42 | * - OK: 0-12, 13 (STALL_IN defined) & 14 | ||
| 43 | * - Not Supported: 15 & 16 (ISO) | ||
| 44 | * | ||
| 45 | * TODO List | ||
| 46 | * - OTG | ||
| 47 | * - Isochronous & Interrupt Traffic | ||
| 48 | * - Handle requests which spawns into several TDs | ||
| 49 | * - GET_STATUS(device) - always reports 0 | ||
| 50 | * - Gadget API (majority of optional features) | ||
| 51 | * - Suspend & Remote Wakeup | ||
| 52 | */ | ||
| 53 | #include <linux/delay.h> | ||
| 54 | #include <linux/device.h> | ||
| 55 | #include <linux/dmapool.h> | ||
| 56 | #include <linux/dma-mapping.h> | ||
| 57 | #include <linux/init.h> | ||
| 58 | #include <linux/interrupt.h> | ||
| 59 | #include <linux/io.h> | ||
| 60 | #include <linux/irq.h> | ||
| 61 | #include <linux/kernel.h> | ||
| 62 | #include <linux/slab.h> | ||
| 63 | #include <linux/pm_runtime.h> | ||
| 64 | #include <linux/usb/ch9.h> | ||
| 65 | #include <linux/usb/gadget.h> | ||
| 66 | #include <linux/usb/otg.h> | ||
| 67 | |||
| 68 | #include "ci13xxx_udc.h" | ||
| 69 | |||
| 70 | |||
| 71 | /****************************************************************************** | ||
| 72 | * DEFINE | ||
| 73 | *****************************************************************************/ | ||
| 74 | /* ctrl register bank access */ | ||
| 75 | static DEFINE_SPINLOCK(udc_lock); | ||
| 76 | |||
| 77 | /* control endpoint description */ | ||
| 78 | static const struct usb_endpoint_descriptor | ||
| 79 | ctrl_endpt_out_desc = { | ||
| 80 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
| 81 | .bDescriptorType = USB_DT_ENDPOINT, | ||
| 82 | |||
| 83 | .bEndpointAddress = USB_DIR_OUT, | ||
| 84 | .bmAttributes = USB_ENDPOINT_XFER_CONTROL, | ||
| 85 | .wMaxPacketSize = cpu_to_le16(CTRL_PAYLOAD_MAX), | ||
| 86 | }; | ||
| 87 | |||
| 88 | static const struct usb_endpoint_descriptor | ||
| 89 | ctrl_endpt_in_desc = { | ||
| 90 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
| 91 | .bDescriptorType = USB_DT_ENDPOINT, | ||
| 92 | |||
| 93 | .bEndpointAddress = USB_DIR_IN, | ||
| 94 | .bmAttributes = USB_ENDPOINT_XFER_CONTROL, | ||
| 95 | .wMaxPacketSize = cpu_to_le16(CTRL_PAYLOAD_MAX), | ||
| 96 | }; | ||
| 97 | |||
| 98 | /* UDC descriptor */ | ||
| 99 | static struct ci13xxx *_udc; | ||
| 100 | |||
| 101 | /* Interrupt statistics */ | ||
| 102 | #define ISR_MASK 0x1F | ||
| 103 | static struct { | ||
| 104 | u32 test; | ||
| 105 | u32 ui; | ||
| 106 | u32 uei; | ||
| 107 | u32 pci; | ||
| 108 | u32 uri; | ||
| 109 | u32 sli; | ||
| 110 | u32 none; | ||
| 111 | struct { | ||
| 112 | u32 cnt; | ||
| 113 | u32 buf[ISR_MASK+1]; | ||
| 114 | u32 idx; | ||
| 115 | } hndl; | ||
| 116 | } isr_statistics; | ||
| 117 | |||
| 118 | /** | ||
| 119 | * ffs_nr: find first (least significant) bit set | ||
| 120 | * @x: the word to search | ||
| 121 | * | ||
| 122 | * This function returns bit number (instead of position) | ||
| 123 | */ | ||
| 124 | static int ffs_nr(u32 x) | ||
| 125 | { | ||
| 126 | int n = ffs(x); | ||
| 127 | |||
| 128 | return n ? n-1 : 32; | ||
| 129 | } | ||
| 130 | |||
| 131 | /****************************************************************************** | ||
| 132 | * HW block | ||
| 133 | *****************************************************************************/ | ||
| 134 | /* register bank descriptor */ | ||
| 135 | static struct { | ||
| 136 | unsigned lpm; /* is LPM? */ | ||
| 137 | void __iomem *abs; /* bus map offset */ | ||
| 138 | void __iomem *cap; /* bus map offset + CAP offset + CAP data */ | ||
| 139 | size_t size; /* bank size */ | ||
| 140 | } hw_bank; | ||
| 141 | |||
| 142 | /* MSM specific */ | ||
| 143 | #define ABS_AHBBURST (0x0090UL) | ||
| 144 | #define ABS_AHBMODE (0x0098UL) | ||
| 145 | /* UDC register map */ | ||
| 146 | #define ABS_CAPLENGTH (0x100UL) | ||
| 147 | #define ABS_HCCPARAMS (0x108UL) | ||
| 148 | #define ABS_DCCPARAMS (0x124UL) | ||
| 149 | #define ABS_TESTMODE (hw_bank.lpm ? 0x0FCUL : 0x138UL) | ||
| 150 | /* offset to CAPLENTGH (addr + data) */ | ||
| 151 | #define CAP_USBCMD (0x000UL) | ||
| 152 | #define CAP_USBSTS (0x004UL) | ||
| 153 | #define CAP_USBINTR (0x008UL) | ||
| 154 | #define CAP_DEVICEADDR (0x014UL) | ||
| 155 | #define CAP_ENDPTLISTADDR (0x018UL) | ||
| 156 | #define CAP_PORTSC (0x044UL) | ||
| 157 | #define CAP_DEVLC (0x084UL) | ||
| 158 | #define CAP_USBMODE (hw_bank.lpm ? 0x0C8UL : 0x068UL) | ||
| 159 | #define CAP_ENDPTSETUPSTAT (hw_bank.lpm ? 0x0D8UL : 0x06CUL) | ||
| 160 | #define CAP_ENDPTPRIME (hw_bank.lpm ? 0x0DCUL : 0x070UL) | ||
| 161 | #define CAP_ENDPTFLUSH (hw_bank.lpm ? 0x0E0UL : 0x074UL) | ||
| 162 | #define CAP_ENDPTSTAT (hw_bank.lpm ? 0x0E4UL : 0x078UL) | ||
| 163 | #define CAP_ENDPTCOMPLETE (hw_bank.lpm ? 0x0E8UL : 0x07CUL) | ||
| 164 | #define CAP_ENDPTCTRL (hw_bank.lpm ? 0x0ECUL : 0x080UL) | ||
| 165 | #define CAP_LAST (hw_bank.lpm ? 0x12CUL : 0x0C0UL) | ||
| 166 | |||
| 167 | /* maximum number of enpoints: valid only after hw_device_reset() */ | ||
| 168 | static unsigned hw_ep_max; | ||
| 169 | |||
| 170 | /** | ||
| 171 | * hw_ep_bit: calculates the bit number | ||
| 172 | * @num: endpoint number | ||
| 173 | * @dir: endpoint direction | ||
| 174 | * | ||
| 175 | * This function returns bit number | ||
| 176 | */ | ||
| 177 | static inline int hw_ep_bit(int num, int dir) | ||
| 178 | { | ||
| 179 | return num + (dir ? 16 : 0); | ||
| 180 | } | ||
| 181 | |||
| 182 | /** | ||
| 183 | * hw_aread: reads from register bitfield | ||
| 184 | * @addr: address relative to bus map | ||
| 185 | * @mask: bitfield mask | ||
| 186 | * | ||
| 187 | * This function returns register bitfield data | ||
| 188 | */ | ||
| 189 | static u32 hw_aread(u32 addr, u32 mask) | ||
| 190 | { | ||
| 191 | return ioread32(addr + hw_bank.abs) & mask; | ||
| 192 | } | ||
| 193 | |||
| 194 | /** | ||
| 195 | * hw_awrite: writes to register bitfield | ||
| 196 | * @addr: address relative to bus map | ||
| 197 | * @mask: bitfield mask | ||
| 198 | * @data: new data | ||
| 199 | */ | ||
| 200 | static void hw_awrite(u32 addr, u32 mask, u32 data) | ||
| 201 | { | ||
| 202 | iowrite32(hw_aread(addr, ~mask) | (data & mask), | ||
| 203 | addr + hw_bank.abs); | ||
| 204 | } | ||
| 205 | |||
| 206 | /** | ||
| 207 | * hw_cread: reads from register bitfield | ||
| 208 | * @addr: address relative to CAP offset plus content | ||
| 209 | * @mask: bitfield mask | ||
| 210 | * | ||
| 211 | * This function returns register bitfield data | ||
| 212 | */ | ||
| 213 | static u32 hw_cread(u32 addr, u32 mask) | ||
| 214 | { | ||
| 215 | return ioread32(addr + hw_bank.cap) & mask; | ||
| 216 | } | ||
| 217 | |||
| 218 | /** | ||
| 219 | * hw_cwrite: writes to register bitfield | ||
| 220 | * @addr: address relative to CAP offset plus content | ||
| 221 | * @mask: bitfield mask | ||
| 222 | * @data: new data | ||
| 223 | */ | ||
| 224 | static void hw_cwrite(u32 addr, u32 mask, u32 data) | ||
| 225 | { | ||
| 226 | iowrite32(hw_cread(addr, ~mask) | (data & mask), | ||
| 227 | addr + hw_bank.cap); | ||
| 228 | } | ||
| 229 | |||
| 230 | /** | ||
| 231 | * hw_ctest_and_clear: tests & clears register bitfield | ||
| 232 | * @addr: address relative to CAP offset plus content | ||
| 233 | * @mask: bitfield mask | ||
| 234 | * | ||
| 235 | * This function returns register bitfield data | ||
| 236 | */ | ||
| 237 | static u32 hw_ctest_and_clear(u32 addr, u32 mask) | ||
| 238 | { | ||
| 239 | u32 reg = hw_cread(addr, mask); | ||
| 240 | |||
| 241 | iowrite32(reg, addr + hw_bank.cap); | ||
| 242 | return reg; | ||
| 243 | } | ||
| 244 | |||
| 245 | /** | ||
| 246 | * hw_ctest_and_write: tests & writes register bitfield | ||
| 247 | * @addr: address relative to CAP offset plus content | ||
| 248 | * @mask: bitfield mask | ||
| 249 | * @data: new data | ||
| 250 | * | ||
| 251 | * This function returns register bitfield data | ||
| 252 | */ | ||
| 253 | static u32 hw_ctest_and_write(u32 addr, u32 mask, u32 data) | ||
| 254 | { | ||
| 255 | u32 reg = hw_cread(addr, ~0); | ||
| 256 | |||
| 257 | iowrite32((reg & ~mask) | (data & mask), addr + hw_bank.cap); | ||
| 258 | return (reg & mask) >> ffs_nr(mask); | ||
| 259 | } | ||
| 260 | |||
| 261 | static int hw_device_init(void __iomem *base) | ||
| 262 | { | ||
| 263 | u32 reg; | ||
| 264 | |||
| 265 | /* bank is a module variable */ | ||
| 266 | hw_bank.abs = base; | ||
| 267 | |||
| 268 | hw_bank.cap = hw_bank.abs; | ||
| 269 | hw_bank.cap += ABS_CAPLENGTH; | ||
| 270 | hw_bank.cap += ioread8(hw_bank.cap); | ||
| 271 | |||
| 272 | reg = hw_aread(ABS_HCCPARAMS, HCCPARAMS_LEN) >> ffs_nr(HCCPARAMS_LEN); | ||
| 273 | hw_bank.lpm = reg; | ||
| 274 | hw_bank.size = hw_bank.cap - hw_bank.abs; | ||
| 275 | hw_bank.size += CAP_LAST; | ||
| 276 | hw_bank.size /= sizeof(u32); | ||
| 277 | |||
| 278 | reg = hw_aread(ABS_DCCPARAMS, DCCPARAMS_DEN) >> ffs_nr(DCCPARAMS_DEN); | ||
| 279 | hw_ep_max = reg * 2; /* cache hw ENDPT_MAX */ | ||
| 280 | |||
| 281 | if (hw_ep_max == 0 || hw_ep_max > ENDPT_MAX) | ||
| 282 | return -ENODEV; | ||
| 283 | |||
| 284 | /* setup lock mode ? */ | ||
| 285 | |||
| 286 | /* ENDPTSETUPSTAT is '0' by default */ | ||
| 287 | |||
| 288 | /* HCSPARAMS.bf.ppc SHOULD BE zero for device */ | ||
| 289 | |||
| 290 | return 0; | ||
| 291 | } | ||
| 292 | /** | ||
| 293 | * hw_device_reset: resets chip (execute without interruption) | ||
| 294 | * @base: register base address | ||
| 295 | * | ||
| 296 | * This function returns an error code | ||
| 297 | */ | ||
| 298 | static int hw_device_reset(struct ci13xxx *udc) | ||
| 299 | { | ||
| 300 | /* should flush & stop before reset */ | ||
| 301 | hw_cwrite(CAP_ENDPTFLUSH, ~0, ~0); | ||
| 302 | hw_cwrite(CAP_USBCMD, USBCMD_RS, 0); | ||
| 303 | |||
| 304 | hw_cwrite(CAP_USBCMD, USBCMD_RST, USBCMD_RST); | ||
| 305 | while (hw_cread(CAP_USBCMD, USBCMD_RST)) | ||
| 306 | udelay(10); /* not RTOS friendly */ | ||
| 307 | |||
| 308 | |||
| 309 | if (udc->udc_driver->notify_event) | ||
| 310 | udc->udc_driver->notify_event(udc, | ||
| 311 | CI13XXX_CONTROLLER_RESET_EVENT); | ||
| 312 | |||
| 313 | if (udc->udc_driver->flags & CI13XXX_DISABLE_STREAMING) | ||
| 314 | hw_cwrite(CAP_USBMODE, USBMODE_SDIS, USBMODE_SDIS); | ||
| 315 | |||
| 316 | /* USBMODE should be configured step by step */ | ||
| 317 | hw_cwrite(CAP_USBMODE, USBMODE_CM, USBMODE_CM_IDLE); | ||
| 318 | hw_cwrite(CAP_USBMODE, USBMODE_CM, USBMODE_CM_DEVICE); | ||
| 319 | hw_cwrite(CAP_USBMODE, USBMODE_SLOM, USBMODE_SLOM); /* HW >= 2.3 */ | ||
| 320 | |||
| 321 | if (hw_cread(CAP_USBMODE, USBMODE_CM) != USBMODE_CM_DEVICE) { | ||
| 322 | pr_err("cannot enter in device mode"); | ||
| 323 | pr_err("lpm = %i", hw_bank.lpm); | ||
| 324 | return -ENODEV; | ||
| 325 | } | ||
| 326 | |||
| 327 | return 0; | ||
| 328 | } | ||
| 329 | |||
| 330 | /** | ||
| 331 | * hw_device_state: enables/disables interrupts & starts/stops device (execute | ||
| 332 | * without interruption) | ||
| 333 | * @dma: 0 => disable, !0 => enable and set dma engine | ||
| 334 | * | ||
| 335 | * This function returns an error code | ||
| 336 | */ | ||
| 337 | static int hw_device_state(u32 dma) | ||
| 338 | { | ||
| 339 | if (dma) { | ||
| 340 | hw_cwrite(CAP_ENDPTLISTADDR, ~0, dma); | ||
| 341 | /* interrupt, error, port change, reset, sleep/suspend */ | ||
| 342 | hw_cwrite(CAP_USBINTR, ~0, | ||
| 343 | USBi_UI|USBi_UEI|USBi_PCI|USBi_URI|USBi_SLI); | ||
| 344 | hw_cwrite(CAP_USBCMD, USBCMD_RS, USBCMD_RS); | ||
| 345 | } else { | ||
| 346 | hw_cwrite(CAP_USBCMD, USBCMD_RS, 0); | ||
| 347 | hw_cwrite(CAP_USBINTR, ~0, 0); | ||
| 348 | } | ||
| 349 | return 0; | ||
| 350 | } | ||
| 351 | |||
| 352 | /** | ||
| 353 | * hw_ep_flush: flush endpoint fifo (execute without interruption) | ||
| 354 | * @num: endpoint number | ||
| 355 | * @dir: endpoint direction | ||
| 356 | * | ||
| 357 | * This function returns an error code | ||
| 358 | */ | ||
| 359 | static int hw_ep_flush(int num, int dir) | ||
| 360 | { | ||
| 361 | int n = hw_ep_bit(num, dir); | ||
| 362 | |||
| 363 | do { | ||
| 364 | /* flush any pending transfer */ | ||
| 365 | hw_cwrite(CAP_ENDPTFLUSH, BIT(n), BIT(n)); | ||
| 366 | while (hw_cread(CAP_ENDPTFLUSH, BIT(n))) | ||
| 367 | cpu_relax(); | ||
| 368 | } while (hw_cread(CAP_ENDPTSTAT, BIT(n))); | ||
| 369 | |||
| 370 | return 0; | ||
| 371 | } | ||
| 372 | |||
| 373 | /** | ||
| 374 | * hw_ep_disable: disables endpoint (execute without interruption) | ||
| 375 | * @num: endpoint number | ||
| 376 | * @dir: endpoint direction | ||
| 377 | * | ||
| 378 | * This function returns an error code | ||
| 379 | */ | ||
| 380 | static int hw_ep_disable(int num, int dir) | ||
| 381 | { | ||
| 382 | hw_ep_flush(num, dir); | ||
| 383 | hw_cwrite(CAP_ENDPTCTRL + num * sizeof(u32), | ||
| 384 | dir ? ENDPTCTRL_TXE : ENDPTCTRL_RXE, 0); | ||
| 385 | return 0; | ||
| 386 | } | ||
| 387 | |||
| 388 | /** | ||
| 389 | * hw_ep_enable: enables endpoint (execute without interruption) | ||
| 390 | * @num: endpoint number | ||
| 391 | * @dir: endpoint direction | ||
| 392 | * @type: endpoint type | ||
| 393 | * | ||
| 394 | * This function returns an error code | ||
| 395 | */ | ||
| 396 | static int hw_ep_enable(int num, int dir, int type) | ||
| 397 | { | ||
| 398 | u32 mask, data; | ||
| 399 | |||
| 400 | if (dir) { | ||
| 401 | mask = ENDPTCTRL_TXT; /* type */ | ||
| 402 | data = type << ffs_nr(mask); | ||
| 403 | |||
| 404 | mask |= ENDPTCTRL_TXS; /* unstall */ | ||
| 405 | mask |= ENDPTCTRL_TXR; /* reset data toggle */ | ||
| 406 | data |= ENDPTCTRL_TXR; | ||
| 407 | mask |= ENDPTCTRL_TXE; /* enable */ | ||
| 408 | data |= ENDPTCTRL_TXE; | ||
| 409 | } else { | ||
| 410 | mask = ENDPTCTRL_RXT; /* type */ | ||
| 411 | data = type << ffs_nr(mask); | ||
| 412 | |||
| 413 | mask |= ENDPTCTRL_RXS; /* unstall */ | ||
| 414 | mask |= ENDPTCTRL_RXR; /* reset data toggle */ | ||
| 415 | data |= ENDPTCTRL_RXR; | ||
| 416 | mask |= ENDPTCTRL_RXE; /* enable */ | ||
| 417 | data |= ENDPTCTRL_RXE; | ||
| 418 | } | ||
| 419 | hw_cwrite(CAP_ENDPTCTRL + num * sizeof(u32), mask, data); | ||
| 420 | return 0; | ||
| 421 | } | ||
| 422 | |||
| 423 | /** | ||
| 424 | * hw_ep_get_halt: return endpoint halt status | ||
| 425 | * @num: endpoint number | ||
| 426 | * @dir: endpoint direction | ||
| 427 | * | ||
| 428 | * This function returns 1 if endpoint halted | ||
| 429 | */ | ||
| 430 | static int hw_ep_get_halt(int num, int dir) | ||
| 431 | { | ||
| 432 | u32 mask = dir ? ENDPTCTRL_TXS : ENDPTCTRL_RXS; | ||
| 433 | |||
| 434 | return hw_cread(CAP_ENDPTCTRL + num * sizeof(u32), mask) ? 1 : 0; | ||
| 435 | } | ||
| 436 | |||
| 437 | /** | ||
| 438 | * hw_test_and_clear_setup_status: test & clear setup status (execute without | ||
| 439 | * interruption) | ||
| 440 | * @n: bit number (endpoint) | ||
| 441 | * | ||
| 442 | * This function returns setup status | ||
| 443 | */ | ||
| 444 | static int hw_test_and_clear_setup_status(int n) | ||
| 445 | { | ||
| 446 | return hw_ctest_and_clear(CAP_ENDPTSETUPSTAT, BIT(n)); | ||
| 447 | } | ||
| 448 | |||
| 449 | /** | ||
| 450 | * hw_ep_prime: primes endpoint (execute without interruption) | ||
| 451 | * @num: endpoint number | ||
| 452 | * @dir: endpoint direction | ||
| 453 | * @is_ctrl: true if control endpoint | ||
| 454 | * | ||
| 455 | * This function returns an error code | ||
| 456 | */ | ||
| 457 | static int hw_ep_prime(int num, int dir, int is_ctrl) | ||
| 458 | { | ||
| 459 | int n = hw_ep_bit(num, dir); | ||
| 460 | |||
| 461 | if (is_ctrl && dir == RX && hw_cread(CAP_ENDPTSETUPSTAT, BIT(num))) | ||
| 462 | return -EAGAIN; | ||
| 463 | |||
| 464 | hw_cwrite(CAP_ENDPTPRIME, BIT(n), BIT(n)); | ||
| 465 | |||
| 466 | while (hw_cread(CAP_ENDPTPRIME, BIT(n))) | ||
| 467 | cpu_relax(); | ||
| 468 | if (is_ctrl && dir == RX && hw_cread(CAP_ENDPTSETUPSTAT, BIT(num))) | ||
| 469 | return -EAGAIN; | ||
| 470 | |||
| 471 | /* status shoult be tested according with manual but it doesn't work */ | ||
| 472 | return 0; | ||
| 473 | } | ||
| 474 | |||
| 475 | /** | ||
| 476 | * hw_ep_set_halt: configures ep halt & resets data toggle after clear (execute | ||
| 477 | * without interruption) | ||
| 478 | * @num: endpoint number | ||
| 479 | * @dir: endpoint direction | ||
| 480 | * @value: true => stall, false => unstall | ||
| 481 | * | ||
| 482 | * This function returns an error code | ||
| 483 | */ | ||
| 484 | static int hw_ep_set_halt(int num, int dir, int value) | ||
| 485 | { | ||
| 486 | if (value != 0 && value != 1) | ||
| 487 | return -EINVAL; | ||
| 488 | |||
| 489 | do { | ||
| 490 | u32 addr = CAP_ENDPTCTRL + num * sizeof(u32); | ||
| 491 | u32 mask_xs = dir ? ENDPTCTRL_TXS : ENDPTCTRL_RXS; | ||
| 492 | u32 mask_xr = dir ? ENDPTCTRL_TXR : ENDPTCTRL_RXR; | ||
| 493 | |||
| 494 | /* data toggle - reserved for EP0 but it's in ESS */ | ||
| 495 | hw_cwrite(addr, mask_xs|mask_xr, value ? mask_xs : mask_xr); | ||
| 496 | |||
| 497 | } while (value != hw_ep_get_halt(num, dir)); | ||
| 498 | |||
| 499 | return 0; | ||
| 500 | } | ||
| 501 | |||
| 502 | /** | ||
| 503 | * hw_intr_clear: disables interrupt & clears interrupt status (execute without | ||
| 504 | * interruption) | ||
| 505 | * @n: interrupt bit | ||
| 506 | * | ||
| 507 | * This function returns an error code | ||
| 508 | */ | ||
| 509 | static int hw_intr_clear(int n) | ||
| 510 | { | ||
| 511 | if (n >= REG_BITS) | ||
| 512 | return -EINVAL; | ||
| 513 | |||
| 514 | hw_cwrite(CAP_USBINTR, BIT(n), 0); | ||
| 515 | hw_cwrite(CAP_USBSTS, BIT(n), BIT(n)); | ||
| 516 | return 0; | ||
| 517 | } | ||
| 518 | |||
| 519 | /** | ||
| 520 | * hw_intr_force: enables interrupt & forces interrupt status (execute without | ||
| 521 | * interruption) | ||
| 522 | * @n: interrupt bit | ||
| 523 | * | ||
| 524 | * This function returns an error code | ||
| 525 | */ | ||
| 526 | static int hw_intr_force(int n) | ||
| 527 | { | ||
| 528 | if (n >= REG_BITS) | ||
| 529 | return -EINVAL; | ||
| 530 | |||
| 531 | hw_awrite(ABS_TESTMODE, TESTMODE_FORCE, TESTMODE_FORCE); | ||
| 532 | hw_cwrite(CAP_USBINTR, BIT(n), BIT(n)); | ||
| 533 | hw_cwrite(CAP_USBSTS, BIT(n), BIT(n)); | ||
| 534 | hw_awrite(ABS_TESTMODE, TESTMODE_FORCE, 0); | ||
| 535 | return 0; | ||
| 536 | } | ||
| 537 | |||
| 538 | /** | ||
| 539 | * hw_is_port_high_speed: test if port is high speed | ||
| 540 | * | ||
| 541 | * This function returns true if high speed port | ||
| 542 | */ | ||
| 543 | static int hw_port_is_high_speed(void) | ||
| 544 | { | ||
| 545 | return hw_bank.lpm ? hw_cread(CAP_DEVLC, DEVLC_PSPD) : | ||
| 546 | hw_cread(CAP_PORTSC, PORTSC_HSP); | ||
| 547 | } | ||
| 548 | |||
| 549 | /** | ||
| 550 | * hw_port_test_get: reads port test mode value | ||
| 551 | * | ||
| 552 | * This function returns port test mode value | ||
| 553 | */ | ||
| 554 | static u8 hw_port_test_get(void) | ||
| 555 | { | ||
| 556 | return hw_cread(CAP_PORTSC, PORTSC_PTC) >> ffs_nr(PORTSC_PTC); | ||
| 557 | } | ||
| 558 | |||
| 559 | /** | ||
| 560 | * hw_port_test_set: writes port test mode (execute without interruption) | ||
| 561 | * @mode: new value | ||
| 562 | * | ||
| 563 | * This function returns an error code | ||
| 564 | */ | ||
| 565 | static int hw_port_test_set(u8 mode) | ||
| 566 | { | ||
| 567 | const u8 TEST_MODE_MAX = 7; | ||
| 568 | |||
| 569 | if (mode > TEST_MODE_MAX) | ||
| 570 | return -EINVAL; | ||
| 571 | |||
| 572 | hw_cwrite(CAP_PORTSC, PORTSC_PTC, mode << ffs_nr(PORTSC_PTC)); | ||
| 573 | return 0; | ||
| 574 | } | ||
| 575 | |||
| 576 | /** | ||
| 577 | * hw_read_intr_enable: returns interrupt enable register | ||
| 578 | * | ||
| 579 | * This function returns register data | ||
| 580 | */ | ||
| 581 | static u32 hw_read_intr_enable(void) | ||
| 582 | { | ||
| 583 | return hw_cread(CAP_USBINTR, ~0); | ||
| 584 | } | ||
| 585 | |||
| 586 | /** | ||
| 587 | * hw_read_intr_status: returns interrupt status register | ||
| 588 | * | ||
| 589 | * This function returns register data | ||
| 590 | */ | ||
| 591 | static u32 hw_read_intr_status(void) | ||
| 592 | { | ||
| 593 | return hw_cread(CAP_USBSTS, ~0); | ||
| 594 | } | ||
| 595 | |||
| 596 | /** | ||
| 597 | * hw_register_read: reads all device registers (execute without interruption) | ||
| 598 | * @buf: destination buffer | ||
| 599 | * @size: buffer size | ||
| 600 | * | ||
| 601 | * This function returns number of registers read | ||
| 602 | */ | ||
| 603 | static size_t hw_register_read(u32 *buf, size_t size) | ||
| 604 | { | ||
| 605 | unsigned i; | ||
| 606 | |||
| 607 | if (size > hw_bank.size) | ||
| 608 | size = hw_bank.size; | ||
| 609 | |||
| 610 | for (i = 0; i < size; i++) | ||
| 611 | buf[i] = hw_aread(i * sizeof(u32), ~0); | ||
| 612 | |||
| 613 | return size; | ||
| 614 | } | ||
| 615 | |||
| 616 | /** | ||
| 617 | * hw_register_write: writes to register | ||
| 618 | * @addr: register address | ||
| 619 | * @data: register value | ||
| 620 | * | ||
| 621 | * This function returns an error code | ||
| 622 | */ | ||
| 623 | static int hw_register_write(u16 addr, u32 data) | ||
| 624 | { | ||
| 625 | /* align */ | ||
| 626 | addr /= sizeof(u32); | ||
| 627 | |||
| 628 | if (addr >= hw_bank.size) | ||
| 629 | return -EINVAL; | ||
| 630 | |||
| 631 | /* align */ | ||
| 632 | addr *= sizeof(u32); | ||
| 633 | |||
| 634 | hw_awrite(addr, ~0, data); | ||
| 635 | return 0; | ||
| 636 | } | ||
| 637 | |||
| 638 | /** | ||
| 639 | * hw_test_and_clear_complete: test & clear complete status (execute without | ||
| 640 | * interruption) | ||
| 641 | * @n: bit number (endpoint) | ||
| 642 | * | ||
| 643 | * This function returns complete status | ||
| 644 | */ | ||
| 645 | static int hw_test_and_clear_complete(int n) | ||
| 646 | { | ||
| 647 | return hw_ctest_and_clear(CAP_ENDPTCOMPLETE, BIT(n)); | ||
| 648 | } | ||
| 649 | |||
| 650 | /** | ||
| 651 | * hw_test_and_clear_intr_active: test & clear active interrupts (execute | ||
| 652 | * without interruption) | ||
| 653 | * | ||
| 654 | * This function returns active interrutps | ||
| 655 | */ | ||
| 656 | static u32 hw_test_and_clear_intr_active(void) | ||
| 657 | { | ||
| 658 | u32 reg = hw_read_intr_status() & hw_read_intr_enable(); | ||
| 659 | |||
| 660 | hw_cwrite(CAP_USBSTS, ~0, reg); | ||
| 661 | return reg; | ||
| 662 | } | ||
| 663 | |||
| 664 | /** | ||
| 665 | * hw_test_and_clear_setup_guard: test & clear setup guard (execute without | ||
| 666 | * interruption) | ||
| 667 | * | ||
| 668 | * This function returns guard value | ||
| 669 | */ | ||
| 670 | static int hw_test_and_clear_setup_guard(void) | ||
| 671 | { | ||
| 672 | return hw_ctest_and_write(CAP_USBCMD, USBCMD_SUTW, 0); | ||
| 673 | } | ||
| 674 | |||
| 675 | /** | ||
| 676 | * hw_test_and_set_setup_guard: test & set setup guard (execute without | ||
| 677 | * interruption) | ||
| 678 | * | ||
| 679 | * This function returns guard value | ||
| 680 | */ | ||
| 681 | static int hw_test_and_set_setup_guard(void) | ||
| 682 | { | ||
| 683 | return hw_ctest_and_write(CAP_USBCMD, USBCMD_SUTW, USBCMD_SUTW); | ||
| 684 | } | ||
| 685 | |||
| 686 | /** | ||
| 687 | * hw_usb_set_address: configures USB address (execute without interruption) | ||
| 688 | * @value: new USB address | ||
| 689 | * | ||
| 690 | * This function returns an error code | ||
| 691 | */ | ||
| 692 | static int hw_usb_set_address(u8 value) | ||
| 693 | { | ||
| 694 | /* advance */ | ||
| 695 | hw_cwrite(CAP_DEVICEADDR, DEVICEADDR_USBADR | DEVICEADDR_USBADRA, | ||
| 696 | value << ffs_nr(DEVICEADDR_USBADR) | DEVICEADDR_USBADRA); | ||
| 697 | return 0; | ||
| 698 | } | ||
| 699 | |||
| 700 | /** | ||
| 701 | * hw_usb_reset: restart device after a bus reset (execute without | ||
| 702 | * interruption) | ||
| 703 | * | ||
| 704 | * This function returns an error code | ||
| 705 | */ | ||
| 706 | static int hw_usb_reset(void) | ||
| 707 | { | ||
| 708 | hw_usb_set_address(0); | ||
| 709 | |||
| 710 | /* ESS flushes only at end?!? */ | ||
| 711 | hw_cwrite(CAP_ENDPTFLUSH, ~0, ~0); /* flush all EPs */ | ||
| 712 | |||
| 713 | /* clear setup token semaphores */ | ||
| 714 | hw_cwrite(CAP_ENDPTSETUPSTAT, 0, 0); /* writes its content */ | ||
| 715 | |||
| 716 | /* clear complete status */ | ||
| 717 | hw_cwrite(CAP_ENDPTCOMPLETE, 0, 0); /* writes its content */ | ||
| 718 | |||
| 719 | /* wait until all bits cleared */ | ||
| 720 | while (hw_cread(CAP_ENDPTPRIME, ~0)) | ||
| 721 | udelay(10); /* not RTOS friendly */ | ||
| 722 | |||
| 723 | /* reset all endpoints ? */ | ||
| 724 | |||
| 725 | /* reset internal status and wait for further instructions | ||
| 726 | no need to verify the port reset status (ESS does it) */ | ||
| 727 | |||
| 728 | return 0; | ||
| 729 | } | ||
| 730 | |||
| 731 | /****************************************************************************** | ||
| 732 | * DBG block | ||
| 733 | *****************************************************************************/ | ||
| 734 | /** | ||
| 735 | * show_device: prints information about device capabilities and status | ||
| 736 | * | ||
| 737 | * Check "device.h" for details | ||
| 738 | */ | ||
| 739 | static ssize_t show_device(struct device *dev, struct device_attribute *attr, | ||
| 740 | char *buf) | ||
| 741 | { | ||
| 742 | struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev); | ||
| 743 | struct usb_gadget *gadget = &udc->gadget; | ||
| 744 | int n = 0; | ||
| 745 | |||
| 746 | dbg_trace("[%s] %p\n", __func__, buf); | ||
| 747 | if (attr == NULL || buf == NULL) { | ||
| 748 | dev_err(dev, "[%s] EINVAL\n", __func__); | ||
| 749 | return 0; | ||
| 750 | } | ||
| 751 | |||
| 752 | n += scnprintf(buf + n, PAGE_SIZE - n, "speed = %d\n", | ||
| 753 | gadget->speed); | ||
| 754 | n += scnprintf(buf + n, PAGE_SIZE - n, "is_dualspeed = %d\n", | ||
| 755 | gadget->is_dualspeed); | ||
| 756 | n += scnprintf(buf + n, PAGE_SIZE - n, "is_otg = %d\n", | ||
| 757 | gadget->is_otg); | ||
| 758 | n += scnprintf(buf + n, PAGE_SIZE - n, "is_a_peripheral = %d\n", | ||
| 759 | gadget->is_a_peripheral); | ||
| 760 | n += scnprintf(buf + n, PAGE_SIZE - n, "b_hnp_enable = %d\n", | ||
| 761 | gadget->b_hnp_enable); | ||
| 762 | n += scnprintf(buf + n, PAGE_SIZE - n, "a_hnp_support = %d\n", | ||
| 763 | gadget->a_hnp_support); | ||
| 764 | n += scnprintf(buf + n, PAGE_SIZE - n, "a_alt_hnp_support = %d\n", | ||
| 765 | gadget->a_alt_hnp_support); | ||
| 766 | n += scnprintf(buf + n, PAGE_SIZE - n, "name = %s\n", | ||
| 767 | (gadget->name ? gadget->name : "")); | ||
| 768 | |||
| 769 | return n; | ||
| 770 | } | ||
| 771 | static DEVICE_ATTR(device, S_IRUSR, show_device, NULL); | ||
| 772 | |||
| 773 | /** | ||
| 774 | * show_driver: prints information about attached gadget (if any) | ||
| 775 | * | ||
| 776 | * Check "device.h" for details | ||
| 777 | */ | ||
| 778 | static ssize_t show_driver(struct device *dev, struct device_attribute *attr, | ||
| 779 | char *buf) | ||
| 780 | { | ||
| 781 | struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev); | ||
| 782 | struct usb_gadget_driver *driver = udc->driver; | ||
| 783 | int n = 0; | ||
| 784 | |||
| 785 | dbg_trace("[%s] %p\n", __func__, buf); | ||
| 786 | if (attr == NULL || buf == NULL) { | ||
| 787 | dev_err(dev, "[%s] EINVAL\n", __func__); | ||
| 788 | return 0; | ||
| 789 | } | ||
| 790 | |||
| 791 | if (driver == NULL) | ||
| 792 | return scnprintf(buf, PAGE_SIZE, | ||
| 793 | "There is no gadget attached!\n"); | ||
| 794 | |||
| 795 | n += scnprintf(buf + n, PAGE_SIZE - n, "function = %s\n", | ||
| 796 | (driver->function ? driver->function : "")); | ||
| 797 | n += scnprintf(buf + n, PAGE_SIZE - n, "max speed = %d\n", | ||
| 798 | driver->speed); | ||
| 799 | |||
| 800 | return n; | ||
| 801 | } | ||
| 802 | static DEVICE_ATTR(driver, S_IRUSR, show_driver, NULL); | ||
| 803 | |||
| 804 | /* Maximum event message length */ | ||
| 805 | #define DBG_DATA_MSG 64UL | ||
| 806 | |||
| 807 | /* Maximum event messages */ | ||
| 808 | #define DBG_DATA_MAX 128UL | ||
| 809 | |||
| 810 | /* Event buffer descriptor */ | ||
| 811 | static struct { | ||
| 812 | char (buf[DBG_DATA_MAX])[DBG_DATA_MSG]; /* buffer */ | ||
| 813 | unsigned idx; /* index */ | ||
| 814 | unsigned tty; /* print to console? */ | ||
| 815 | rwlock_t lck; /* lock */ | ||
| 816 | } dbg_data = { | ||
| 817 | .idx = 0, | ||
| 818 | .tty = 0, | ||
| 819 | .lck = __RW_LOCK_UNLOCKED(lck) | ||
| 820 | }; | ||
| 821 | |||
| 822 | /** | ||
| 823 | * dbg_dec: decrements debug event index | ||
| 824 | * @idx: buffer index | ||
| 825 | */ | ||
| 826 | static void dbg_dec(unsigned *idx) | ||
| 827 | { | ||
| 828 | *idx = (*idx - 1) & (DBG_DATA_MAX-1); | ||
| 829 | } | ||
| 830 | |||
| 831 | /** | ||
| 832 | * dbg_inc: increments debug event index | ||
| 833 | * @idx: buffer index | ||
| 834 | */ | ||
| 835 | static void dbg_inc(unsigned *idx) | ||
| 836 | { | ||
| 837 | *idx = (*idx + 1) & (DBG_DATA_MAX-1); | ||
| 838 | } | ||
| 839 | |||
| 840 | /** | ||
| 841 | * dbg_print: prints the common part of the event | ||
| 842 | * @addr: endpoint address | ||
| 843 | * @name: event name | ||
| 844 | * @status: status | ||
| 845 | * @extra: extra information | ||
| 846 | */ | ||
| 847 | static void dbg_print(u8 addr, const char *name, int status, const char *extra) | ||
| 848 | { | ||
| 849 | struct timeval tval; | ||
| 850 | unsigned int stamp; | ||
| 851 | unsigned long flags; | ||
| 852 | |||
| 853 | write_lock_irqsave(&dbg_data.lck, flags); | ||
| 854 | |||
| 855 | do_gettimeofday(&tval); | ||
| 856 | stamp = tval.tv_sec & 0xFFFF; /* 2^32 = 4294967296. Limit to 4096s */ | ||
| 857 | stamp = stamp * 1000000 + tval.tv_usec; | ||
| 858 | |||
| 859 | scnprintf(dbg_data.buf[dbg_data.idx], DBG_DATA_MSG, | ||
| 860 | "%04X\t? %02X %-7.7s %4i ?\t%s\n", | ||
| 861 | stamp, addr, name, status, extra); | ||
| 862 | |||
| 863 | dbg_inc(&dbg_data.idx); | ||
| 864 | |||
| 865 | write_unlock_irqrestore(&dbg_data.lck, flags); | ||
| 866 | |||
| 867 | if (dbg_data.tty != 0) | ||
| 868 | pr_notice("%04X\t? %02X %-7.7s %4i ?\t%s\n", | ||
| 869 | stamp, addr, name, status, extra); | ||
| 870 | } | ||
| 871 | |||
| 872 | /** | ||
| 873 | * dbg_done: prints a DONE event | ||
| 874 | * @addr: endpoint address | ||
| 875 | * @td: transfer descriptor | ||
| 876 | * @status: status | ||
| 877 | */ | ||
| 878 | static void dbg_done(u8 addr, const u32 token, int status) | ||
| 879 | { | ||
| 880 | char msg[DBG_DATA_MSG]; | ||
| 881 | |||
| 882 | scnprintf(msg, sizeof(msg), "%d %02X", | ||
| 883 | (int)(token & TD_TOTAL_BYTES) >> ffs_nr(TD_TOTAL_BYTES), | ||
| 884 | (int)(token & TD_STATUS) >> ffs_nr(TD_STATUS)); | ||
| 885 | dbg_print(addr, "DONE", status, msg); | ||
| 886 | } | ||
| 887 | |||
| 888 | /** | ||
| 889 | * dbg_event: prints a generic event | ||
| 890 | * @addr: endpoint address | ||
| 891 | * @name: event name | ||
| 892 | * @status: status | ||
| 893 | */ | ||
| 894 | static void dbg_event(u8 addr, const char *name, int status) | ||
| 895 | { | ||
| 896 | if (name != NULL) | ||
| 897 | dbg_print(addr, name, status, ""); | ||
| 898 | } | ||
| 899 | |||
| 900 | /* | ||
| 901 | * dbg_queue: prints a QUEUE event | ||
| 902 | * @addr: endpoint address | ||
| 903 | * @req: USB request | ||
| 904 | * @status: status | ||
| 905 | */ | ||
| 906 | static void dbg_queue(u8 addr, const struct usb_request *req, int status) | ||
| 907 | { | ||
| 908 | char msg[DBG_DATA_MSG]; | ||
| 909 | |||
| 910 | if (req != NULL) { | ||
| 911 | scnprintf(msg, sizeof(msg), | ||
| 912 | "%d %d", !req->no_interrupt, req->length); | ||
| 913 | dbg_print(addr, "QUEUE", status, msg); | ||
| 914 | } | ||
| 915 | } | ||
| 916 | |||
| 917 | /** | ||
| 918 | * dbg_setup: prints a SETUP event | ||
| 919 | * @addr: endpoint address | ||
| 920 | * @req: setup request | ||
| 921 | */ | ||
| 922 | static void dbg_setup(u8 addr, const struct usb_ctrlrequest *req) | ||
| 923 | { | ||
| 924 | char msg[DBG_DATA_MSG]; | ||
| 925 | |||
| 926 | if (req != NULL) { | ||
| 927 | scnprintf(msg, sizeof(msg), | ||
| 928 | "%02X %02X %04X %04X %d", req->bRequestType, | ||
| 929 | req->bRequest, le16_to_cpu(req->wValue), | ||
| 930 | le16_to_cpu(req->wIndex), le16_to_cpu(req->wLength)); | ||
| 931 | dbg_print(addr, "SETUP", 0, msg); | ||
| 932 | } | ||
| 933 | } | ||
| 934 | |||
| 935 | /** | ||
| 936 | * show_events: displays the event buffer | ||
| 937 | * | ||
| 938 | * Check "device.h" for details | ||
| 939 | */ | ||
| 940 | static ssize_t show_events(struct device *dev, struct device_attribute *attr, | ||
| 941 | char *buf) | ||
| 942 | { | ||
| 943 | unsigned long flags; | ||
| 944 | unsigned i, j, n = 0; | ||
| 945 | |||
| 946 | dbg_trace("[%s] %p\n", __func__, buf); | ||
| 947 | if (attr == NULL || buf == NULL) { | ||
| 948 | dev_err(dev, "[%s] EINVAL\n", __func__); | ||
| 949 | return 0; | ||
| 950 | } | ||
| 951 | |||
| 952 | read_lock_irqsave(&dbg_data.lck, flags); | ||
| 953 | |||
| 954 | i = dbg_data.idx; | ||
| 955 | for (dbg_dec(&i); i != dbg_data.idx; dbg_dec(&i)) { | ||
| 956 | n += strlen(dbg_data.buf[i]); | ||
| 957 | if (n >= PAGE_SIZE) { | ||
| 958 | n -= strlen(dbg_data.buf[i]); | ||
| 959 | break; | ||
| 960 | } | ||
| 961 | } | ||
| 962 | for (j = 0, dbg_inc(&i); j < n; dbg_inc(&i)) | ||
| 963 | j += scnprintf(buf + j, PAGE_SIZE - j, | ||
| 964 | "%s", dbg_data.buf[i]); | ||
| 965 | |||
| 966 | read_unlock_irqrestore(&dbg_data.lck, flags); | ||
| 967 | |||
| 968 | return n; | ||
| 969 | } | ||
| 970 | |||
| 971 | /** | ||
| 972 | * store_events: configure if events are going to be also printed to console | ||
| 973 | * | ||
| 974 | * Check "device.h" for details | ||
| 975 | */ | ||
| 976 | static ssize_t store_events(struct device *dev, struct device_attribute *attr, | ||
| 977 | const char *buf, size_t count) | ||
| 978 | { | ||
| 979 | unsigned tty; | ||
| 980 | |||
| 981 | dbg_trace("[%s] %p, %d\n", __func__, buf, count); | ||
| 982 | if (attr == NULL || buf == NULL) { | ||
| 983 | dev_err(dev, "[%s] EINVAL\n", __func__); | ||
| 984 | goto done; | ||
| 985 | } | ||
| 986 | |||
| 987 | if (sscanf(buf, "%u", &tty) != 1 || tty > 1) { | ||
| 988 | dev_err(dev, "<1|0>: enable|disable console log\n"); | ||
| 989 | goto done; | ||
| 990 | } | ||
| 991 | |||
| 992 | dbg_data.tty = tty; | ||
| 993 | dev_info(dev, "tty = %u", dbg_data.tty); | ||
| 994 | |||
| 995 | done: | ||
| 996 | return count; | ||
| 997 | } | ||
| 998 | static DEVICE_ATTR(events, S_IRUSR | S_IWUSR, show_events, store_events); | ||
| 999 | |||
| 1000 | /** | ||
| 1001 | * show_inters: interrupt status, enable status and historic | ||
| 1002 | * | ||
| 1003 | * Check "device.h" for details | ||
| 1004 | */ | ||
| 1005 | static ssize_t show_inters(struct device *dev, struct device_attribute *attr, | ||
| 1006 | char *buf) | ||
| 1007 | { | ||
| 1008 | struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev); | ||
| 1009 | unsigned long flags; | ||
| 1010 | u32 intr; | ||
| 1011 | unsigned i, j, n = 0; | ||
| 1012 | |||
| 1013 | dbg_trace("[%s] %p\n", __func__, buf); | ||
| 1014 | if (attr == NULL || buf == NULL) { | ||
| 1015 | dev_err(dev, "[%s] EINVAL\n", __func__); | ||
| 1016 | return 0; | ||
| 1017 | } | ||
| 1018 | |||
| 1019 | spin_lock_irqsave(udc->lock, flags); | ||
| 1020 | |||
| 1021 | n += scnprintf(buf + n, PAGE_SIZE - n, | ||
| 1022 | "status = %08x\n", hw_read_intr_status()); | ||
| 1023 | n += scnprintf(buf + n, PAGE_SIZE - n, | ||
| 1024 | "enable = %08x\n", hw_read_intr_enable()); | ||
| 1025 | |||
| 1026 | n += scnprintf(buf + n, PAGE_SIZE - n, "*test = %d\n", | ||
| 1027 | isr_statistics.test); | ||
| 1028 | n += scnprintf(buf + n, PAGE_SIZE - n, "? ui = %d\n", | ||
| 1029 | isr_statistics.ui); | ||
| 1030 | n += scnprintf(buf + n, PAGE_SIZE - n, "? uei = %d\n", | ||
| 1031 | isr_statistics.uei); | ||
| 1032 | n += scnprintf(buf + n, PAGE_SIZE - n, "? pci = %d\n", | ||
| 1033 | isr_statistics.pci); | ||
| 1034 | n += scnprintf(buf + n, PAGE_SIZE - n, "? uri = %d\n", | ||
| 1035 | isr_statistics.uri); | ||
| 1036 | n += scnprintf(buf + n, PAGE_SIZE - n, "? sli = %d\n", | ||
| 1037 | isr_statistics.sli); | ||
| 1038 | n += scnprintf(buf + n, PAGE_SIZE - n, "*none = %d\n", | ||
| 1039 | isr_statistics.none); | ||
| 1040 | n += scnprintf(buf + n, PAGE_SIZE - n, "*hndl = %d\n", | ||
| 1041 | isr_statistics.hndl.cnt); | ||
| 1042 | |||
| 1043 | for (i = isr_statistics.hndl.idx, j = 0; j <= ISR_MASK; j++, i++) { | ||
| 1044 | i &= ISR_MASK; | ||
| 1045 | intr = isr_statistics.hndl.buf[i]; | ||
| 1046 | |||
| 1047 | if (USBi_UI & intr) | ||
| 1048 | n += scnprintf(buf + n, PAGE_SIZE - n, "ui "); | ||
| 1049 | intr &= ~USBi_UI; | ||
| 1050 | if (USBi_UEI & intr) | ||
| 1051 | n += scnprintf(buf + n, PAGE_SIZE - n, "uei "); | ||
| 1052 | intr &= ~USBi_UEI; | ||
| 1053 | if (USBi_PCI & intr) | ||
| 1054 | n += scnprintf(buf + n, PAGE_SIZE - n, "pci "); | ||
| 1055 | intr &= ~USBi_PCI; | ||
| 1056 | if (USBi_URI & intr) | ||
| 1057 | n += scnprintf(buf + n, PAGE_SIZE - n, "uri "); | ||
| 1058 | intr &= ~USBi_URI; | ||
| 1059 | if (USBi_SLI & intr) | ||
| 1060 | n += scnprintf(buf + n, PAGE_SIZE - n, "sli "); | ||
| 1061 | intr &= ~USBi_SLI; | ||
| 1062 | if (intr) | ||
| 1063 | n += scnprintf(buf + n, PAGE_SIZE - n, "??? "); | ||
| 1064 | if (isr_statistics.hndl.buf[i]) | ||
| 1065 | n += scnprintf(buf + n, PAGE_SIZE - n, "\n"); | ||
| 1066 | } | ||
| 1067 | |||
| 1068 | spin_unlock_irqrestore(udc->lock, flags); | ||
| 1069 | |||
| 1070 | return n; | ||
| 1071 | } | ||
| 1072 | |||
| 1073 | /** | ||
| 1074 | * store_inters: enable & force or disable an individual interrutps | ||
| 1075 | * (to be used for test purposes only) | ||
| 1076 | * | ||
| 1077 | * Check "device.h" for details | ||
| 1078 | */ | ||
| 1079 | static ssize_t store_inters(struct device *dev, struct device_attribute *attr, | ||
| 1080 | const char *buf, size_t count) | ||
| 1081 | { | ||
| 1082 | struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev); | ||
| 1083 | unsigned long flags; | ||
| 1084 | unsigned en, bit; | ||
| 1085 | |||
| 1086 | dbg_trace("[%s] %p, %d\n", __func__, buf, count); | ||
| 1087 | if (attr == NULL || buf == NULL) { | ||
| 1088 | dev_err(dev, "[%s] EINVAL\n", __func__); | ||
| 1089 | goto done; | ||
| 1090 | } | ||
| 1091 | |||
| 1092 | if (sscanf(buf, "%u %u", &en, &bit) != 2 || en > 1) { | ||
| 1093 | dev_err(dev, "<1|0> <bit>: enable|disable interrupt"); | ||
| 1094 | goto done; | ||
| 1095 | } | ||
| 1096 | |||
| 1097 | spin_lock_irqsave(udc->lock, flags); | ||
| 1098 | if (en) { | ||
| 1099 | if (hw_intr_force(bit)) | ||
| 1100 | dev_err(dev, "invalid bit number\n"); | ||
| 1101 | else | ||
| 1102 | isr_statistics.test++; | ||
| 1103 | } else { | ||
| 1104 | if (hw_intr_clear(bit)) | ||
| 1105 | dev_err(dev, "invalid bit number\n"); | ||
| 1106 | } | ||
| 1107 | spin_unlock_irqrestore(udc->lock, flags); | ||
| 1108 | |||
| 1109 | done: | ||
| 1110 | return count; | ||
| 1111 | } | ||
| 1112 | static DEVICE_ATTR(inters, S_IRUSR | S_IWUSR, show_inters, store_inters); | ||
| 1113 | |||
| 1114 | /** | ||
| 1115 | * show_port_test: reads port test mode | ||
| 1116 | * | ||
| 1117 | * Check "device.h" for details | ||
| 1118 | */ | ||
| 1119 | static ssize_t show_port_test(struct device *dev, | ||
| 1120 | struct device_attribute *attr, char *buf) | ||
| 1121 | { | ||
| 1122 | struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev); | ||
| 1123 | unsigned long flags; | ||
| 1124 | unsigned mode; | ||
| 1125 | |||
| 1126 | dbg_trace("[%s] %p\n", __func__, buf); | ||
| 1127 | if (attr == NULL || buf == NULL) { | ||
| 1128 | dev_err(dev, "[%s] EINVAL\n", __func__); | ||
| 1129 | return 0; | ||
| 1130 | } | ||
| 1131 | |||
| 1132 | spin_lock_irqsave(udc->lock, flags); | ||
| 1133 | mode = hw_port_test_get(); | ||
| 1134 | spin_unlock_irqrestore(udc->lock, flags); | ||
| 1135 | |||
| 1136 | return scnprintf(buf, PAGE_SIZE, "mode = %u\n", mode); | ||
| 1137 | } | ||
| 1138 | |||
| 1139 | /** | ||
| 1140 | * store_port_test: writes port test mode | ||
| 1141 | * | ||
| 1142 | * Check "device.h" for details | ||
| 1143 | */ | ||
| 1144 | static ssize_t store_port_test(struct device *dev, | ||
| 1145 | struct device_attribute *attr, | ||
| 1146 | const char *buf, size_t count) | ||
| 1147 | { | ||
| 1148 | struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev); | ||
| 1149 | unsigned long flags; | ||
| 1150 | unsigned mode; | ||
| 1151 | |||
| 1152 | dbg_trace("[%s] %p, %d\n", __func__, buf, count); | ||
| 1153 | if (attr == NULL || buf == NULL) { | ||
| 1154 | dev_err(dev, "[%s] EINVAL\n", __func__); | ||
| 1155 | goto done; | ||
| 1156 | } | ||
| 1157 | |||
| 1158 | if (sscanf(buf, "%u", &mode) != 1) { | ||
| 1159 | dev_err(dev, "<mode>: set port test mode"); | ||
| 1160 | goto done; | ||
| 1161 | } | ||
| 1162 | |||
| 1163 | spin_lock_irqsave(udc->lock, flags); | ||
| 1164 | if (hw_port_test_set(mode)) | ||
| 1165 | dev_err(dev, "invalid mode\n"); | ||
| 1166 | spin_unlock_irqrestore(udc->lock, flags); | ||
| 1167 | |||
| 1168 | done: | ||
| 1169 | return count; | ||
| 1170 | } | ||
| 1171 | static DEVICE_ATTR(port_test, S_IRUSR | S_IWUSR, | ||
| 1172 | show_port_test, store_port_test); | ||
| 1173 | |||
| 1174 | /** | ||
| 1175 | * show_qheads: DMA contents of all queue heads | ||
| 1176 | * | ||
| 1177 | * Check "device.h" for details | ||
| 1178 | */ | ||
| 1179 | static ssize_t show_qheads(struct device *dev, struct device_attribute *attr, | ||
| 1180 | char *buf) | ||
| 1181 | { | ||
| 1182 | struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev); | ||
| 1183 | unsigned long flags; | ||
| 1184 | unsigned i, j, n = 0; | ||
| 1185 | |||
| 1186 | dbg_trace("[%s] %p\n", __func__, buf); | ||
| 1187 | if (attr == NULL || buf == NULL) { | ||
| 1188 | dev_err(dev, "[%s] EINVAL\n", __func__); | ||
| 1189 | return 0; | ||
| 1190 | } | ||
| 1191 | |||
| 1192 | spin_lock_irqsave(udc->lock, flags); | ||
| 1193 | for (i = 0; i < hw_ep_max/2; i++) { | ||
| 1194 | struct ci13xxx_ep *mEpRx = &udc->ci13xxx_ep[i]; | ||
| 1195 | struct ci13xxx_ep *mEpTx = &udc->ci13xxx_ep[i + hw_ep_max/2]; | ||
| 1196 | n += scnprintf(buf + n, PAGE_SIZE - n, | ||
| 1197 | "EP=%02i: RX=%08X TX=%08X\n", | ||
| 1198 | i, (u32)mEpRx->qh.dma, (u32)mEpTx->qh.dma); | ||
| 1199 | for (j = 0; j < (sizeof(struct ci13xxx_qh)/sizeof(u32)); j++) { | ||
| 1200 | n += scnprintf(buf + n, PAGE_SIZE - n, | ||
| 1201 | " %04X: %08X %08X\n", j, | ||
| 1202 | *((u32 *)mEpRx->qh.ptr + j), | ||
| 1203 | *((u32 *)mEpTx->qh.ptr + j)); | ||
| 1204 | } | ||
| 1205 | } | ||
| 1206 | spin_unlock_irqrestore(udc->lock, flags); | ||
| 1207 | |||
| 1208 | return n; | ||
| 1209 | } | ||
| 1210 | static DEVICE_ATTR(qheads, S_IRUSR, show_qheads, NULL); | ||
| 1211 | |||
| 1212 | /** | ||
| 1213 | * show_registers: dumps all registers | ||
| 1214 | * | ||
| 1215 | * Check "device.h" for details | ||
| 1216 | */ | ||
| 1217 | #define DUMP_ENTRIES 512 | ||
| 1218 | static ssize_t show_registers(struct device *dev, | ||
| 1219 | struct device_attribute *attr, char *buf) | ||
| 1220 | { | ||
| 1221 | struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev); | ||
| 1222 | unsigned long flags; | ||
| 1223 | u32 *dump; | ||
| 1224 | unsigned i, k, n = 0; | ||
| 1225 | |||
| 1226 | dbg_trace("[%s] %p\n", __func__, buf); | ||
| 1227 | if (attr == NULL || buf == NULL) { | ||
| 1228 | dev_err(dev, "[%s] EINVAL\n", __func__); | ||
| 1229 | return 0; | ||
| 1230 | } | ||
| 1231 | |||
| 1232 | dump = kmalloc(sizeof(u32) * DUMP_ENTRIES, GFP_KERNEL); | ||
| 1233 | if (!dump) { | ||
| 1234 | dev_err(dev, "%s: out of memory\n", __func__); | ||
| 1235 | return 0; | ||
| 1236 | } | ||
| 1237 | |||
| 1238 | spin_lock_irqsave(udc->lock, flags); | ||
| 1239 | k = hw_register_read(dump, DUMP_ENTRIES); | ||
| 1240 | spin_unlock_irqrestore(udc->lock, flags); | ||
| 1241 | |||
| 1242 | for (i = 0; i < k; i++) { | ||
| 1243 | n += scnprintf(buf + n, PAGE_SIZE - n, | ||
| 1244 | "reg[0x%04X] = 0x%08X\n", | ||
| 1245 | i * (unsigned)sizeof(u32), dump[i]); | ||
| 1246 | } | ||
| 1247 | kfree(dump); | ||
| 1248 | |||
| 1249 | return n; | ||
| 1250 | } | ||
| 1251 | |||
| 1252 | /** | ||
| 1253 | * store_registers: writes value to register address | ||
| 1254 | * | ||
| 1255 | * Check "device.h" for details | ||
| 1256 | */ | ||
| 1257 | static ssize_t store_registers(struct device *dev, | ||
| 1258 | struct device_attribute *attr, | ||
| 1259 | const char *buf, size_t count) | ||
| 1260 | { | ||
| 1261 | struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev); | ||
| 1262 | unsigned long addr, data, flags; | ||
| 1263 | |||
| 1264 | dbg_trace("[%s] %p, %d\n", __func__, buf, count); | ||
| 1265 | if (attr == NULL || buf == NULL) { | ||
| 1266 | dev_err(dev, "[%s] EINVAL\n", __func__); | ||
| 1267 | goto done; | ||
| 1268 | } | ||
| 1269 | |||
| 1270 | if (sscanf(buf, "%li %li", &addr, &data) != 2) { | ||
| 1271 | dev_err(dev, "<addr> <data>: write data to register address"); | ||
| 1272 | goto done; | ||
| 1273 | } | ||
| 1274 | |||
| 1275 | spin_lock_irqsave(udc->lock, flags); | ||
| 1276 | if (hw_register_write(addr, data)) | ||
| 1277 | dev_err(dev, "invalid address range\n"); | ||
| 1278 | spin_unlock_irqrestore(udc->lock, flags); | ||
| 1279 | |||
| 1280 | done: | ||
| 1281 | return count; | ||
| 1282 | } | ||
| 1283 | static DEVICE_ATTR(registers, S_IRUSR | S_IWUSR, | ||
| 1284 | show_registers, store_registers); | ||
| 1285 | |||
| 1286 | /** | ||
| 1287 | * show_requests: DMA contents of all requests currently queued (all endpts) | ||
| 1288 | * | ||
| 1289 | * Check "device.h" for details | ||
| 1290 | */ | ||
| 1291 | static ssize_t show_requests(struct device *dev, struct device_attribute *attr, | ||
| 1292 | char *buf) | ||
| 1293 | { | ||
| 1294 | struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev); | ||
| 1295 | unsigned long flags; | ||
| 1296 | struct list_head *ptr = NULL; | ||
| 1297 | struct ci13xxx_req *req = NULL; | ||
| 1298 | unsigned i, j, n = 0, qSize = sizeof(struct ci13xxx_td)/sizeof(u32); | ||
| 1299 | |||
| 1300 | dbg_trace("[%s] %p\n", __func__, buf); | ||
| 1301 | if (attr == NULL || buf == NULL) { | ||
| 1302 | dev_err(dev, "[%s] EINVAL\n", __func__); | ||
| 1303 | return 0; | ||
| 1304 | } | ||
| 1305 | |||
| 1306 | spin_lock_irqsave(udc->lock, flags); | ||
| 1307 | for (i = 0; i < hw_ep_max; i++) | ||
| 1308 | list_for_each(ptr, &udc->ci13xxx_ep[i].qh.queue) | ||
| 1309 | { | ||
| 1310 | req = list_entry(ptr, struct ci13xxx_req, queue); | ||
| 1311 | |||
| 1312 | n += scnprintf(buf + n, PAGE_SIZE - n, | ||
| 1313 | "EP=%02i: TD=%08X %s\n", | ||
| 1314 | i % hw_ep_max/2, (u32)req->dma, | ||
| 1315 | ((i < hw_ep_max/2) ? "RX" : "TX")); | ||
| 1316 | |||
| 1317 | for (j = 0; j < qSize; j++) | ||
| 1318 | n += scnprintf(buf + n, PAGE_SIZE - n, | ||
| 1319 | " %04X: %08X\n", j, | ||
| 1320 | *((u32 *)req->ptr + j)); | ||
| 1321 | } | ||
| 1322 | spin_unlock_irqrestore(udc->lock, flags); | ||
| 1323 | |||
| 1324 | return n; | ||
| 1325 | } | ||
| 1326 | static DEVICE_ATTR(requests, S_IRUSR, show_requests, NULL); | ||
| 1327 | |||
| 1328 | /** | ||
| 1329 | * dbg_create_files: initializes the attribute interface | ||
| 1330 | * @dev: device | ||
| 1331 | * | ||
| 1332 | * This function returns an error code | ||
| 1333 | */ | ||
| 1334 | __maybe_unused static int dbg_create_files(struct device *dev) | ||
| 1335 | { | ||
| 1336 | int retval = 0; | ||
| 1337 | |||
| 1338 | if (dev == NULL) | ||
| 1339 | return -EINVAL; | ||
| 1340 | retval = device_create_file(dev, &dev_attr_device); | ||
| 1341 | if (retval) | ||
| 1342 | goto done; | ||
| 1343 | retval = device_create_file(dev, &dev_attr_driver); | ||
| 1344 | if (retval) | ||
| 1345 | goto rm_device; | ||
| 1346 | retval = device_create_file(dev, &dev_attr_events); | ||
| 1347 | if (retval) | ||
| 1348 | goto rm_driver; | ||
| 1349 | retval = device_create_file(dev, &dev_attr_inters); | ||
| 1350 | if (retval) | ||
| 1351 | goto rm_events; | ||
| 1352 | retval = device_create_file(dev, &dev_attr_port_test); | ||
| 1353 | if (retval) | ||
| 1354 | goto rm_inters; | ||
| 1355 | retval = device_create_file(dev, &dev_attr_qheads); | ||
| 1356 | if (retval) | ||
| 1357 | goto rm_port_test; | ||
| 1358 | retval = device_create_file(dev, &dev_attr_registers); | ||
| 1359 | if (retval) | ||
| 1360 | goto rm_qheads; | ||
| 1361 | retval = device_create_file(dev, &dev_attr_requests); | ||
| 1362 | if (retval) | ||
| 1363 | goto rm_registers; | ||
| 1364 | return 0; | ||
| 1365 | |||
| 1366 | rm_registers: | ||
| 1367 | device_remove_file(dev, &dev_attr_registers); | ||
| 1368 | rm_qheads: | ||
| 1369 | device_remove_file(dev, &dev_attr_qheads); | ||
| 1370 | rm_port_test: | ||
| 1371 | device_remove_file(dev, &dev_attr_port_test); | ||
| 1372 | rm_inters: | ||
| 1373 | device_remove_file(dev, &dev_attr_inters); | ||
| 1374 | rm_events: | ||
| 1375 | device_remove_file(dev, &dev_attr_events); | ||
| 1376 | rm_driver: | ||
| 1377 | device_remove_file(dev, &dev_attr_driver); | ||
| 1378 | rm_device: | ||
| 1379 | device_remove_file(dev, &dev_attr_device); | ||
| 1380 | done: | ||
| 1381 | return retval; | ||
| 1382 | } | ||
| 1383 | |||
| 1384 | /** | ||
| 1385 | * dbg_remove_files: destroys the attribute interface | ||
| 1386 | * @dev: device | ||
| 1387 | * | ||
| 1388 | * This function returns an error code | ||
| 1389 | */ | ||
| 1390 | __maybe_unused static int dbg_remove_files(struct device *dev) | ||
| 1391 | { | ||
| 1392 | if (dev == NULL) | ||
| 1393 | return -EINVAL; | ||
| 1394 | device_remove_file(dev, &dev_attr_requests); | ||
| 1395 | device_remove_file(dev, &dev_attr_registers); | ||
| 1396 | device_remove_file(dev, &dev_attr_qheads); | ||
| 1397 | device_remove_file(dev, &dev_attr_port_test); | ||
| 1398 | device_remove_file(dev, &dev_attr_inters); | ||
| 1399 | device_remove_file(dev, &dev_attr_events); | ||
| 1400 | device_remove_file(dev, &dev_attr_driver); | ||
| 1401 | device_remove_file(dev, &dev_attr_device); | ||
| 1402 | return 0; | ||
| 1403 | } | ||
| 1404 | |||
| 1405 | /****************************************************************************** | ||
| 1406 | * UTIL block | ||
| 1407 | *****************************************************************************/ | ||
| 1408 | /** | ||
| 1409 | * _usb_addr: calculates endpoint address from direction & number | ||
| 1410 | * @ep: endpoint | ||
| 1411 | */ | ||
| 1412 | static inline u8 _usb_addr(struct ci13xxx_ep *ep) | ||
| 1413 | { | ||
| 1414 | return ((ep->dir == TX) ? USB_ENDPOINT_DIR_MASK : 0) | ep->num; | ||
| 1415 | } | ||
| 1416 | |||
| 1417 | /** | ||
| 1418 | * _hardware_queue: configures a request at hardware level | ||
| 1419 | * @gadget: gadget | ||
| 1420 | * @mEp: endpoint | ||
| 1421 | * | ||
| 1422 | * This function returns an error code | ||
| 1423 | */ | ||
| 1424 | static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq) | ||
| 1425 | { | ||
| 1426 | unsigned i; | ||
| 1427 | int ret = 0; | ||
| 1428 | unsigned length = mReq->req.length; | ||
| 1429 | |||
| 1430 | trace("%p, %p", mEp, mReq); | ||
| 1431 | |||
| 1432 | /* don't queue twice */ | ||
| 1433 | if (mReq->req.status == -EALREADY) | ||
| 1434 | return -EALREADY; | ||
| 1435 | |||
| 1436 | mReq->req.status = -EALREADY; | ||
| 1437 | if (length && !mReq->req.dma) { | ||
| 1438 | mReq->req.dma = \ | ||
| 1439 | dma_map_single(mEp->device, mReq->req.buf, | ||
| 1440 | length, mEp->dir ? DMA_TO_DEVICE : | ||
| 1441 | DMA_FROM_DEVICE); | ||
| 1442 | if (mReq->req.dma == 0) | ||
| 1443 | return -ENOMEM; | ||
| 1444 | |||
| 1445 | mReq->map = 1; | ||
| 1446 | } | ||
| 1447 | |||
| 1448 | if (mReq->req.zero && length && (length % mEp->ep.maxpacket == 0)) { | ||
| 1449 | mReq->zptr = dma_pool_alloc(mEp->td_pool, GFP_ATOMIC, | ||
| 1450 | &mReq->zdma); | ||
| 1451 | if (mReq->zptr == NULL) { | ||
| 1452 | if (mReq->map) { | ||
| 1453 | dma_unmap_single(mEp->device, mReq->req.dma, | ||
| 1454 | length, mEp->dir ? DMA_TO_DEVICE : | ||
| 1455 | DMA_FROM_DEVICE); | ||
| 1456 | mReq->req.dma = 0; | ||
| 1457 | mReq->map = 0; | ||
| 1458 | } | ||
| 1459 | return -ENOMEM; | ||
| 1460 | } | ||
| 1461 | memset(mReq->zptr, 0, sizeof(*mReq->zptr)); | ||
| 1462 | mReq->zptr->next = TD_TERMINATE; | ||
| 1463 | mReq->zptr->token = TD_STATUS_ACTIVE; | ||
| 1464 | if (!mReq->req.no_interrupt) | ||
| 1465 | mReq->zptr->token |= TD_IOC; | ||
| 1466 | } | ||
| 1467 | /* | ||
| 1468 | * TD configuration | ||
| 1469 | * TODO - handle requests which spawns into several TDs | ||
| 1470 | */ | ||
| 1471 | memset(mReq->ptr, 0, sizeof(*mReq->ptr)); | ||
| 1472 | mReq->ptr->token = length << ffs_nr(TD_TOTAL_BYTES); | ||
| 1473 | mReq->ptr->token &= TD_TOTAL_BYTES; | ||
| 1474 | mReq->ptr->token |= TD_STATUS_ACTIVE; | ||
| 1475 | if (mReq->zptr) { | ||
| 1476 | mReq->ptr->next = mReq->zdma; | ||
| 1477 | } else { | ||
| 1478 | mReq->ptr->next = TD_TERMINATE; | ||
| 1479 | if (!mReq->req.no_interrupt) | ||
| 1480 | mReq->ptr->token |= TD_IOC; | ||
| 1481 | } | ||
| 1482 | mReq->ptr->page[0] = mReq->req.dma; | ||
| 1483 | for (i = 1; i < 5; i++) | ||
| 1484 | mReq->ptr->page[i] = | ||
| 1485 | (mReq->req.dma + i * CI13XXX_PAGE_SIZE) & ~TD_RESERVED_MASK; | ||
| 1486 | |||
| 1487 | if (!list_empty(&mEp->qh.queue)) { | ||
| 1488 | struct ci13xxx_req *mReqPrev; | ||
| 1489 | int n = hw_ep_bit(mEp->num, mEp->dir); | ||
| 1490 | int tmp_stat; | ||
| 1491 | |||
| 1492 | mReqPrev = list_entry(mEp->qh.queue.prev, | ||
| 1493 | struct ci13xxx_req, queue); | ||
| 1494 | if (mReqPrev->zptr) | ||
| 1495 | mReqPrev->zptr->next = mReq->dma & TD_ADDR_MASK; | ||
| 1496 | else | ||
| 1497 | mReqPrev->ptr->next = mReq->dma & TD_ADDR_MASK; | ||
| 1498 | wmb(); | ||
| 1499 | if (hw_cread(CAP_ENDPTPRIME, BIT(n))) | ||
| 1500 | goto done; | ||
| 1501 | do { | ||
| 1502 | hw_cwrite(CAP_USBCMD, USBCMD_ATDTW, USBCMD_ATDTW); | ||
| 1503 | tmp_stat = hw_cread(CAP_ENDPTSTAT, BIT(n)); | ||
| 1504 | } while (!hw_cread(CAP_USBCMD, USBCMD_ATDTW)); | ||
| 1505 | hw_cwrite(CAP_USBCMD, USBCMD_ATDTW, 0); | ||
| 1506 | if (tmp_stat) | ||
| 1507 | goto done; | ||
| 1508 | } | ||
| 1509 | |||
| 1510 | /* QH configuration */ | ||
| 1511 | mEp->qh.ptr->td.next = mReq->dma; /* TERMINATE = 0 */ | ||
| 1512 | mEp->qh.ptr->td.token &= ~TD_STATUS; /* clear status */ | ||
| 1513 | mEp->qh.ptr->cap |= QH_ZLT; | ||
| 1514 | |||
| 1515 | wmb(); /* synchronize before ep prime */ | ||
| 1516 | |||
| 1517 | ret = hw_ep_prime(mEp->num, mEp->dir, | ||
| 1518 | mEp->type == USB_ENDPOINT_XFER_CONTROL); | ||
| 1519 | done: | ||
| 1520 | return ret; | ||
| 1521 | } | ||
| 1522 | |||
| 1523 | /** | ||
| 1524 | * _hardware_dequeue: handles a request at hardware level | ||
| 1525 | * @gadget: gadget | ||
| 1526 | * @mEp: endpoint | ||
| 1527 | * | ||
| 1528 | * This function returns an error code | ||
| 1529 | */ | ||
| 1530 | static int _hardware_dequeue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq) | ||
| 1531 | { | ||
| 1532 | trace("%p, %p", mEp, mReq); | ||
| 1533 | |||
| 1534 | if (mReq->req.status != -EALREADY) | ||
| 1535 | return -EINVAL; | ||
| 1536 | |||
| 1537 | if ((TD_STATUS_ACTIVE & mReq->ptr->token) != 0) | ||
| 1538 | return -EBUSY; | ||
| 1539 | |||
| 1540 | if (mReq->zptr) { | ||
| 1541 | if ((TD_STATUS_ACTIVE & mReq->zptr->token) != 0) | ||
| 1542 | return -EBUSY; | ||
| 1543 | dma_pool_free(mEp->td_pool, mReq->zptr, mReq->zdma); | ||
| 1544 | mReq->zptr = NULL; | ||
| 1545 | } | ||
| 1546 | |||
| 1547 | mReq->req.status = 0; | ||
| 1548 | |||
| 1549 | if (mReq->map) { | ||
| 1550 | dma_unmap_single(mEp->device, mReq->req.dma, mReq->req.length, | ||
| 1551 | mEp->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE); | ||
| 1552 | mReq->req.dma = 0; | ||
| 1553 | mReq->map = 0; | ||
| 1554 | } | ||
| 1555 | |||
| 1556 | mReq->req.status = mReq->ptr->token & TD_STATUS; | ||
| 1557 | if ((TD_STATUS_HALTED & mReq->req.status) != 0) | ||
| 1558 | mReq->req.status = -1; | ||
| 1559 | else if ((TD_STATUS_DT_ERR & mReq->req.status) != 0) | ||
| 1560 | mReq->req.status = -1; | ||
| 1561 | else if ((TD_STATUS_TR_ERR & mReq->req.status) != 0) | ||
| 1562 | mReq->req.status = -1; | ||
| 1563 | |||
| 1564 | mReq->req.actual = mReq->ptr->token & TD_TOTAL_BYTES; | ||
| 1565 | mReq->req.actual >>= ffs_nr(TD_TOTAL_BYTES); | ||
| 1566 | mReq->req.actual = mReq->req.length - mReq->req.actual; | ||
| 1567 | mReq->req.actual = mReq->req.status ? 0 : mReq->req.actual; | ||
| 1568 | |||
| 1569 | return mReq->req.actual; | ||
| 1570 | } | ||
| 1571 | |||
| 1572 | /** | ||
| 1573 | * _ep_nuke: dequeues all endpoint requests | ||
| 1574 | * @mEp: endpoint | ||
| 1575 | * | ||
| 1576 | * This function returns an error code | ||
| 1577 | * Caller must hold lock | ||
| 1578 | */ | ||
| 1579 | static int _ep_nuke(struct ci13xxx_ep *mEp) | ||
| 1580 | __releases(mEp->lock) | ||
| 1581 | __acquires(mEp->lock) | ||
| 1582 | { | ||
| 1583 | trace("%p", mEp); | ||
| 1584 | |||
| 1585 | if (mEp == NULL) | ||
| 1586 | return -EINVAL; | ||
| 1587 | |||
| 1588 | hw_ep_flush(mEp->num, mEp->dir); | ||
| 1589 | |||
| 1590 | while (!list_empty(&mEp->qh.queue)) { | ||
| 1591 | |||
| 1592 | /* pop oldest request */ | ||
| 1593 | struct ci13xxx_req *mReq = \ | ||
| 1594 | list_entry(mEp->qh.queue.next, | ||
| 1595 | struct ci13xxx_req, queue); | ||
| 1596 | list_del_init(&mReq->queue); | ||
| 1597 | mReq->req.status = -ESHUTDOWN; | ||
| 1598 | |||
| 1599 | if (mReq->req.complete != NULL) { | ||
| 1600 | spin_unlock(mEp->lock); | ||
| 1601 | mReq->req.complete(&mEp->ep, &mReq->req); | ||
| 1602 | spin_lock(mEp->lock); | ||
| 1603 | } | ||
| 1604 | } | ||
| 1605 | return 0; | ||
| 1606 | } | ||
| 1607 | |||
| 1608 | /** | ||
| 1609 | * _gadget_stop_activity: stops all USB activity, flushes & disables all endpts | ||
| 1610 | * @gadget: gadget | ||
| 1611 | * | ||
| 1612 | * This function returns an error code | ||
| 1613 | * Caller must hold lock | ||
| 1614 | */ | ||
| 1615 | static int _gadget_stop_activity(struct usb_gadget *gadget) | ||
| 1616 | { | ||
| 1617 | struct usb_ep *ep; | ||
| 1618 | struct ci13xxx *udc = container_of(gadget, struct ci13xxx, gadget); | ||
| 1619 | unsigned long flags; | ||
| 1620 | |||
| 1621 | trace("%p", gadget); | ||
| 1622 | |||
| 1623 | if (gadget == NULL) | ||
| 1624 | return -EINVAL; | ||
| 1625 | |||
| 1626 | spin_lock_irqsave(udc->lock, flags); | ||
| 1627 | udc->gadget.speed = USB_SPEED_UNKNOWN; | ||
| 1628 | udc->remote_wakeup = 0; | ||
| 1629 | udc->suspended = 0; | ||
| 1630 | spin_unlock_irqrestore(udc->lock, flags); | ||
| 1631 | |||
| 1632 | /* flush all endpoints */ | ||
| 1633 | gadget_for_each_ep(ep, gadget) { | ||
| 1634 | usb_ep_fifo_flush(ep); | ||
| 1635 | } | ||
| 1636 | usb_ep_fifo_flush(&udc->ep0out.ep); | ||
| 1637 | usb_ep_fifo_flush(&udc->ep0in.ep); | ||
| 1638 | |||
| 1639 | udc->driver->disconnect(gadget); | ||
| 1640 | |||
| 1641 | /* make sure to disable all endpoints */ | ||
| 1642 | gadget_for_each_ep(ep, gadget) { | ||
| 1643 | usb_ep_disable(ep); | ||
| 1644 | } | ||
| 1645 | |||
| 1646 | if (udc->status != NULL) { | ||
| 1647 | usb_ep_free_request(&udc->ep0in.ep, udc->status); | ||
| 1648 | udc->status = NULL; | ||
| 1649 | } | ||
| 1650 | |||
| 1651 | return 0; | ||
| 1652 | } | ||
| 1653 | |||
| 1654 | /****************************************************************************** | ||
| 1655 | * ISR block | ||
| 1656 | *****************************************************************************/ | ||
| 1657 | /** | ||
| 1658 | * isr_reset_handler: USB reset interrupt handler | ||
| 1659 | * @udc: UDC device | ||
| 1660 | * | ||
| 1661 | * This function resets USB engine after a bus reset occurred | ||
| 1662 | */ | ||
| 1663 | static void isr_reset_handler(struct ci13xxx *udc) | ||
| 1664 | __releases(udc->lock) | ||
| 1665 | __acquires(udc->lock) | ||
| 1666 | { | ||
| 1667 | int retval; | ||
| 1668 | |||
| 1669 | trace("%p", udc); | ||
| 1670 | |||
| 1671 | if (udc == NULL) { | ||
| 1672 | err("EINVAL"); | ||
| 1673 | return; | ||
| 1674 | } | ||
| 1675 | |||
| 1676 | dbg_event(0xFF, "BUS RST", 0); | ||
| 1677 | |||
| 1678 | spin_unlock(udc->lock); | ||
| 1679 | retval = _gadget_stop_activity(&udc->gadget); | ||
| 1680 | if (retval) | ||
| 1681 | goto done; | ||
| 1682 | |||
| 1683 | retval = hw_usb_reset(); | ||
| 1684 | if (retval) | ||
| 1685 | goto done; | ||
| 1686 | |||
| 1687 | udc->status = usb_ep_alloc_request(&udc->ep0in.ep, GFP_ATOMIC); | ||
| 1688 | if (udc->status == NULL) | ||
| 1689 | retval = -ENOMEM; | ||
| 1690 | |||
| 1691 | spin_lock(udc->lock); | ||
| 1692 | |||
| 1693 | done: | ||
| 1694 | if (retval) | ||
| 1695 | err("error: %i", retval); | ||
| 1696 | } | ||
| 1697 | |||
| 1698 | /** | ||
| 1699 | * isr_get_status_complete: get_status request complete function | ||
| 1700 | * @ep: endpoint | ||
| 1701 | * @req: request handled | ||
| 1702 | * | ||
| 1703 | * Caller must release lock | ||
| 1704 | */ | ||
| 1705 | static void isr_get_status_complete(struct usb_ep *ep, struct usb_request *req) | ||
| 1706 | { | ||
| 1707 | trace("%p, %p", ep, req); | ||
| 1708 | |||
| 1709 | if (ep == NULL || req == NULL) { | ||
| 1710 | err("EINVAL"); | ||
| 1711 | return; | ||
| 1712 | } | ||
| 1713 | |||
| 1714 | kfree(req->buf); | ||
| 1715 | usb_ep_free_request(ep, req); | ||
| 1716 | } | ||
| 1717 | |||
| 1718 | /** | ||
| 1719 | * isr_get_status_response: get_status request response | ||
| 1720 | * @udc: udc struct | ||
| 1721 | * @setup: setup request packet | ||
| 1722 | * | ||
| 1723 | * This function returns an error code | ||
| 1724 | */ | ||
| 1725 | static int isr_get_status_response(struct ci13xxx *udc, | ||
| 1726 | struct usb_ctrlrequest *setup) | ||
| 1727 | __releases(mEp->lock) | ||
| 1728 | __acquires(mEp->lock) | ||
| 1729 | { | ||
| 1730 | struct ci13xxx_ep *mEp = &udc->ep0in; | ||
| 1731 | struct usb_request *req = NULL; | ||
| 1732 | gfp_t gfp_flags = GFP_ATOMIC; | ||
| 1733 | int dir, num, retval; | ||
| 1734 | |||
| 1735 | trace("%p, %p", mEp, setup); | ||
| 1736 | |||
| 1737 | if (mEp == NULL || setup == NULL) | ||
| 1738 | return -EINVAL; | ||
| 1739 | |||
| 1740 | spin_unlock(mEp->lock); | ||
| 1741 | req = usb_ep_alloc_request(&mEp->ep, gfp_flags); | ||
| 1742 | spin_lock(mEp->lock); | ||
| 1743 | if (req == NULL) | ||
| 1744 | return -ENOMEM; | ||
| 1745 | |||
| 1746 | req->complete = isr_get_status_complete; | ||
| 1747 | req->length = 2; | ||
| 1748 | req->buf = kzalloc(req->length, gfp_flags); | ||
| 1749 | if (req->buf == NULL) { | ||
| 1750 | retval = -ENOMEM; | ||
| 1751 | goto err_free_req; | ||
| 1752 | } | ||
| 1753 | |||
| 1754 | if ((setup->bRequestType & USB_RECIP_MASK) == USB_RECIP_DEVICE) { | ||
| 1755 | /* Assume that device is bus powered for now. */ | ||
| 1756 | *((u16 *)req->buf) = _udc->remote_wakeup << 1; | ||
| 1757 | retval = 0; | ||
| 1758 | } else if ((setup->bRequestType & USB_RECIP_MASK) \ | ||
| 1759 | == USB_RECIP_ENDPOINT) { | ||
| 1760 | dir = (le16_to_cpu(setup->wIndex) & USB_ENDPOINT_DIR_MASK) ? | ||
| 1761 | TX : RX; | ||
| 1762 | num = le16_to_cpu(setup->wIndex) & USB_ENDPOINT_NUMBER_MASK; | ||
| 1763 | *((u16 *)req->buf) = hw_ep_get_halt(num, dir); | ||
| 1764 | } | ||
| 1765 | /* else do nothing; reserved for future use */ | ||
| 1766 | |||
| 1767 | spin_unlock(mEp->lock); | ||
| 1768 | retval = usb_ep_queue(&mEp->ep, req, gfp_flags); | ||
| 1769 | spin_lock(mEp->lock); | ||
| 1770 | if (retval) | ||
| 1771 | goto err_free_buf; | ||
| 1772 | |||
| 1773 | return 0; | ||
| 1774 | |||
| 1775 | err_free_buf: | ||
| 1776 | kfree(req->buf); | ||
| 1777 | err_free_req: | ||
| 1778 | spin_unlock(mEp->lock); | ||
| 1779 | usb_ep_free_request(&mEp->ep, req); | ||
| 1780 | spin_lock(mEp->lock); | ||
| 1781 | return retval; | ||
| 1782 | } | ||
| 1783 | |||
| 1784 | /** | ||
| 1785 | * isr_setup_status_complete: setup_status request complete function | ||
| 1786 | * @ep: endpoint | ||
| 1787 | * @req: request handled | ||
| 1788 | * | ||
| 1789 | * Caller must release lock. Put the port in test mode if test mode | ||
| 1790 | * feature is selected. | ||
| 1791 | */ | ||
| 1792 | static void | ||
| 1793 | isr_setup_status_complete(struct usb_ep *ep, struct usb_request *req) | ||
| 1794 | { | ||
| 1795 | struct ci13xxx *udc = req->context; | ||
| 1796 | unsigned long flags; | ||
| 1797 | |||
| 1798 | trace("%p, %p", ep, req); | ||
| 1799 | |||
| 1800 | spin_lock_irqsave(udc->lock, flags); | ||
| 1801 | if (udc->test_mode) | ||
| 1802 | hw_port_test_set(udc->test_mode); | ||
| 1803 | spin_unlock_irqrestore(udc->lock, flags); | ||
| 1804 | } | ||
| 1805 | |||
| 1806 | /** | ||
| 1807 | * isr_setup_status_phase: queues the status phase of a setup transation | ||
| 1808 | * @udc: udc struct | ||
| 1809 | * | ||
| 1810 | * This function returns an error code | ||
| 1811 | */ | ||
| 1812 | static int isr_setup_status_phase(struct ci13xxx *udc) | ||
| 1813 | __releases(mEp->lock) | ||
| 1814 | __acquires(mEp->lock) | ||
| 1815 | { | ||
| 1816 | int retval; | ||
| 1817 | struct ci13xxx_ep *mEp; | ||
| 1818 | |||
| 1819 | trace("%p", udc); | ||
| 1820 | |||
| 1821 | mEp = (udc->ep0_dir == TX) ? &udc->ep0out : &udc->ep0in; | ||
| 1822 | udc->status->context = udc; | ||
| 1823 | udc->status->complete = isr_setup_status_complete; | ||
| 1824 | |||
| 1825 | spin_unlock(mEp->lock); | ||
| 1826 | retval = usb_ep_queue(&mEp->ep, udc->status, GFP_ATOMIC); | ||
| 1827 | spin_lock(mEp->lock); | ||
| 1828 | |||
| 1829 | return retval; | ||
| 1830 | } | ||
| 1831 | |||
| 1832 | /** | ||
| 1833 | * isr_tr_complete_low: transaction complete low level handler | ||
| 1834 | * @mEp: endpoint | ||
| 1835 | * | ||
| 1836 | * This function returns an error code | ||
| 1837 | * Caller must hold lock | ||
| 1838 | */ | ||
| 1839 | static int isr_tr_complete_low(struct ci13xxx_ep *mEp) | ||
| 1840 | __releases(mEp->lock) | ||
| 1841 | __acquires(mEp->lock) | ||
| 1842 | { | ||
| 1843 | struct ci13xxx_req *mReq, *mReqTemp; | ||
| 1844 | struct ci13xxx_ep *mEpTemp = mEp; | ||
| 1845 | int uninitialized_var(retval); | ||
| 1846 | |||
| 1847 | trace("%p", mEp); | ||
| 1848 | |||
| 1849 | if (list_empty(&mEp->qh.queue)) | ||
| 1850 | return -EINVAL; | ||
| 1851 | |||
| 1852 | list_for_each_entry_safe(mReq, mReqTemp, &mEp->qh.queue, | ||
| 1853 | queue) { | ||
| 1854 | retval = _hardware_dequeue(mEp, mReq); | ||
| 1855 | if (retval < 0) | ||
| 1856 | break; | ||
| 1857 | list_del_init(&mReq->queue); | ||
| 1858 | dbg_done(_usb_addr(mEp), mReq->ptr->token, retval); | ||
| 1859 | if (mReq->req.complete != NULL) { | ||
| 1860 | spin_unlock(mEp->lock); | ||
| 1861 | if ((mEp->type == USB_ENDPOINT_XFER_CONTROL) && | ||
| 1862 | mReq->req.length) | ||
| 1863 | mEpTemp = &_udc->ep0in; | ||
| 1864 | mReq->req.complete(&mEpTemp->ep, &mReq->req); | ||
| 1865 | spin_lock(mEp->lock); | ||
| 1866 | } | ||
| 1867 | } | ||
| 1868 | |||
| 1869 | if (retval == -EBUSY) | ||
| 1870 | retval = 0; | ||
| 1871 | if (retval < 0) | ||
| 1872 | dbg_event(_usb_addr(mEp), "DONE", retval); | ||
| 1873 | |||
| 1874 | return retval; | ||
| 1875 | } | ||
| 1876 | |||
| 1877 | /** | ||
| 1878 | * isr_tr_complete_handler: transaction complete interrupt handler | ||
| 1879 | * @udc: UDC descriptor | ||
| 1880 | * | ||
| 1881 | * This function handles traffic events | ||
| 1882 | */ | ||
| 1883 | static void isr_tr_complete_handler(struct ci13xxx *udc) | ||
| 1884 | __releases(udc->lock) | ||
| 1885 | __acquires(udc->lock) | ||
| 1886 | { | ||
| 1887 | unsigned i; | ||
| 1888 | u8 tmode = 0; | ||
| 1889 | |||
| 1890 | trace("%p", udc); | ||
| 1891 | |||
| 1892 | if (udc == NULL) { | ||
| 1893 | err("EINVAL"); | ||
| 1894 | return; | ||
| 1895 | } | ||
| 1896 | |||
| 1897 | for (i = 0; i < hw_ep_max; i++) { | ||
| 1898 | struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i]; | ||
| 1899 | int type, num, dir, err = -EINVAL; | ||
| 1900 | struct usb_ctrlrequest req; | ||
| 1901 | |||
| 1902 | if (mEp->desc == NULL) | ||
| 1903 | continue; /* not configured */ | ||
| 1904 | |||
| 1905 | if (hw_test_and_clear_complete(i)) { | ||
| 1906 | err = isr_tr_complete_low(mEp); | ||
| 1907 | if (mEp->type == USB_ENDPOINT_XFER_CONTROL) { | ||
| 1908 | if (err > 0) /* needs status phase */ | ||
| 1909 | err = isr_setup_status_phase(udc); | ||
| 1910 | if (err < 0) { | ||
| 1911 | dbg_event(_usb_addr(mEp), | ||
| 1912 | "ERROR", err); | ||
| 1913 | spin_unlock(udc->lock); | ||
| 1914 | if (usb_ep_set_halt(&mEp->ep)) | ||
| 1915 | err("error: ep_set_halt"); | ||
| 1916 | spin_lock(udc->lock); | ||
| 1917 | } | ||
| 1918 | } | ||
| 1919 | } | ||
| 1920 | |||
| 1921 | if (mEp->type != USB_ENDPOINT_XFER_CONTROL || | ||
| 1922 | !hw_test_and_clear_setup_status(i)) | ||
| 1923 | continue; | ||
| 1924 | |||
| 1925 | if (i != 0) { | ||
| 1926 | warn("ctrl traffic received at endpoint"); | ||
| 1927 | continue; | ||
| 1928 | } | ||
| 1929 | |||
| 1930 | /* | ||
| 1931 | * Flush data and handshake transactions of previous | ||
| 1932 | * setup packet. | ||
| 1933 | */ | ||
| 1934 | _ep_nuke(&udc->ep0out); | ||
| 1935 | _ep_nuke(&udc->ep0in); | ||
| 1936 | |||
| 1937 | /* read_setup_packet */ | ||
| 1938 | do { | ||
| 1939 | hw_test_and_set_setup_guard(); | ||
| 1940 | memcpy(&req, &mEp->qh.ptr->setup, sizeof(req)); | ||
| 1941 | } while (!hw_test_and_clear_setup_guard()); | ||
| 1942 | |||
| 1943 | type = req.bRequestType; | ||
| 1944 | |||
| 1945 | udc->ep0_dir = (type & USB_DIR_IN) ? TX : RX; | ||
| 1946 | |||
| 1947 | dbg_setup(_usb_addr(mEp), &req); | ||
| 1948 | |||
| 1949 | switch (req.bRequest) { | ||
| 1950 | case USB_REQ_CLEAR_FEATURE: | ||
| 1951 | if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) && | ||
| 1952 | le16_to_cpu(req.wValue) == | ||
| 1953 | USB_ENDPOINT_HALT) { | ||
| 1954 | if (req.wLength != 0) | ||
| 1955 | break; | ||
| 1956 | num = le16_to_cpu(req.wIndex); | ||
| 1957 | dir = num & USB_ENDPOINT_DIR_MASK; | ||
| 1958 | num &= USB_ENDPOINT_NUMBER_MASK; | ||
| 1959 | if (dir) /* TX */ | ||
| 1960 | num += hw_ep_max/2; | ||
| 1961 | if (!udc->ci13xxx_ep[num].wedge) { | ||
| 1962 | spin_unlock(udc->lock); | ||
| 1963 | err = usb_ep_clear_halt( | ||
| 1964 | &udc->ci13xxx_ep[num].ep); | ||
| 1965 | spin_lock(udc->lock); | ||
| 1966 | if (err) | ||
| 1967 | break; | ||
| 1968 | } | ||
| 1969 | err = isr_setup_status_phase(udc); | ||
| 1970 | } else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE) && | ||
| 1971 | le16_to_cpu(req.wValue) == | ||
| 1972 | USB_DEVICE_REMOTE_WAKEUP) { | ||
| 1973 | if (req.wLength != 0) | ||
| 1974 | break; | ||
| 1975 | udc->remote_wakeup = 0; | ||
| 1976 | err = isr_setup_status_phase(udc); | ||
| 1977 | } else { | ||
| 1978 | goto delegate; | ||
| 1979 | } | ||
| 1980 | break; | ||
| 1981 | case USB_REQ_GET_STATUS: | ||
| 1982 | if (type != (USB_DIR_IN|USB_RECIP_DEVICE) && | ||
| 1983 | type != (USB_DIR_IN|USB_RECIP_ENDPOINT) && | ||
| 1984 | type != (USB_DIR_IN|USB_RECIP_INTERFACE)) | ||
| 1985 | goto delegate; | ||
| 1986 | if (le16_to_cpu(req.wLength) != 2 || | ||
| 1987 | le16_to_cpu(req.wValue) != 0) | ||
| 1988 | break; | ||
| 1989 | err = isr_get_status_response(udc, &req); | ||
| 1990 | break; | ||
| 1991 | case USB_REQ_SET_ADDRESS: | ||
| 1992 | if (type != (USB_DIR_OUT|USB_RECIP_DEVICE)) | ||
| 1993 | goto delegate; | ||
| 1994 | if (le16_to_cpu(req.wLength) != 0 || | ||
| 1995 | le16_to_cpu(req.wIndex) != 0) | ||
| 1996 | break; | ||
| 1997 | err = hw_usb_set_address((u8)le16_to_cpu(req.wValue)); | ||
| 1998 | if (err) | ||
| 1999 | break; | ||
| 2000 | err = isr_setup_status_phase(udc); | ||
| 2001 | break; | ||
| 2002 | case USB_REQ_SET_FEATURE: | ||
| 2003 | if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) && | ||
| 2004 | le16_to_cpu(req.wValue) == | ||
| 2005 | USB_ENDPOINT_HALT) { | ||
| 2006 | if (req.wLength != 0) | ||
| 2007 | break; | ||
| 2008 | num = le16_to_cpu(req.wIndex); | ||
| 2009 | dir = num & USB_ENDPOINT_DIR_MASK; | ||
| 2010 | num &= USB_ENDPOINT_NUMBER_MASK; | ||
| 2011 | if (dir) /* TX */ | ||
| 2012 | num += hw_ep_max/2; | ||
| 2013 | |||
| 2014 | spin_unlock(udc->lock); | ||
| 2015 | err = usb_ep_set_halt(&udc->ci13xxx_ep[num].ep); | ||
| 2016 | spin_lock(udc->lock); | ||
| 2017 | if (!err) | ||
| 2018 | isr_setup_status_phase(udc); | ||
| 2019 | } else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE)) { | ||
| 2020 | if (req.wLength != 0) | ||
| 2021 | break; | ||
| 2022 | switch (le16_to_cpu(req.wValue)) { | ||
| 2023 | case USB_DEVICE_REMOTE_WAKEUP: | ||
| 2024 | udc->remote_wakeup = 1; | ||
| 2025 | err = isr_setup_status_phase(udc); | ||
| 2026 | break; | ||
| 2027 | case USB_DEVICE_TEST_MODE: | ||
| 2028 | tmode = le16_to_cpu(req.wIndex) >> 8; | ||
| 2029 | switch (tmode) { | ||
| 2030 | case TEST_J: | ||
| 2031 | case TEST_K: | ||
| 2032 | case TEST_SE0_NAK: | ||
| 2033 | case TEST_PACKET: | ||
| 2034 | case TEST_FORCE_EN: | ||
| 2035 | udc->test_mode = tmode; | ||
| 2036 | err = isr_setup_status_phase( | ||
| 2037 | udc); | ||
| 2038 | break; | ||
| 2039 | default: | ||
| 2040 | break; | ||
| 2041 | } | ||
| 2042 | default: | ||
| 2043 | goto delegate; | ||
| 2044 | } | ||
| 2045 | } else { | ||
| 2046 | goto delegate; | ||
| 2047 | } | ||
| 2048 | break; | ||
| 2049 | default: | ||
| 2050 | delegate: | ||
| 2051 | if (req.wLength == 0) /* no data phase */ | ||
| 2052 | udc->ep0_dir = TX; | ||
| 2053 | |||
| 2054 | spin_unlock(udc->lock); | ||
| 2055 | err = udc->driver->setup(&udc->gadget, &req); | ||
| 2056 | spin_lock(udc->lock); | ||
| 2057 | break; | ||
| 2058 | } | ||
| 2059 | |||
| 2060 | if (err < 0) { | ||
| 2061 | dbg_event(_usb_addr(mEp), "ERROR", err); | ||
| 2062 | |||
| 2063 | spin_unlock(udc->lock); | ||
| 2064 | if (usb_ep_set_halt(&mEp->ep)) | ||
| 2065 | err("error: ep_set_halt"); | ||
| 2066 | spin_lock(udc->lock); | ||
| 2067 | } | ||
| 2068 | } | ||
| 2069 | } | ||
| 2070 | |||
| 2071 | /****************************************************************************** | ||
| 2072 | * ENDPT block | ||
| 2073 | *****************************************************************************/ | ||
| 2074 | /** | ||
| 2075 | * ep_enable: configure endpoint, making it usable | ||
| 2076 | * | ||
| 2077 | * Check usb_ep_enable() at "usb_gadget.h" for details | ||
| 2078 | */ | ||
| 2079 | static int ep_enable(struct usb_ep *ep, | ||
| 2080 | const struct usb_endpoint_descriptor *desc) | ||
| 2081 | { | ||
| 2082 | struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep); | ||
| 2083 | int retval = 0; | ||
| 2084 | unsigned long flags; | ||
| 2085 | |||
| 2086 | trace("%p, %p", ep, desc); | ||
| 2087 | |||
| 2088 | if (ep == NULL || desc == NULL) | ||
| 2089 | return -EINVAL; | ||
| 2090 | |||
| 2091 | spin_lock_irqsave(mEp->lock, flags); | ||
| 2092 | |||
| 2093 | /* only internal SW should enable ctrl endpts */ | ||
| 2094 | |||
| 2095 | mEp->desc = desc; | ||
| 2096 | |||
| 2097 | if (!list_empty(&mEp->qh.queue)) | ||
| 2098 | warn("enabling a non-empty endpoint!"); | ||
| 2099 | |||
| 2100 | mEp->dir = usb_endpoint_dir_in(desc) ? TX : RX; | ||
| 2101 | mEp->num = usb_endpoint_num(desc); | ||
| 2102 | mEp->type = usb_endpoint_type(desc); | ||
| 2103 | |||
| 2104 | mEp->ep.maxpacket = __constant_le16_to_cpu(desc->wMaxPacketSize); | ||
| 2105 | |||
| 2106 | dbg_event(_usb_addr(mEp), "ENABLE", 0); | ||
| 2107 | |||
| 2108 | mEp->qh.ptr->cap = 0; | ||
| 2109 | |||
| 2110 | if (mEp->type == USB_ENDPOINT_XFER_CONTROL) | ||
| 2111 | mEp->qh.ptr->cap |= QH_IOS; | ||
| 2112 | else if (mEp->type == USB_ENDPOINT_XFER_ISOC) | ||
| 2113 | mEp->qh.ptr->cap &= ~QH_MULT; | ||
| 2114 | else | ||
| 2115 | mEp->qh.ptr->cap &= ~QH_ZLT; | ||
| 2116 | |||
| 2117 | mEp->qh.ptr->cap |= | ||
| 2118 | (mEp->ep.maxpacket << ffs_nr(QH_MAX_PKT)) & QH_MAX_PKT; | ||
| 2119 | mEp->qh.ptr->td.next |= TD_TERMINATE; /* needed? */ | ||
| 2120 | |||
| 2121 | /* | ||
| 2122 | * Enable endpoints in the HW other than ep0 as ep0 | ||
| 2123 | * is always enabled | ||
| 2124 | */ | ||
| 2125 | if (mEp->num) | ||
| 2126 | retval |= hw_ep_enable(mEp->num, mEp->dir, mEp->type); | ||
| 2127 | |||
| 2128 | spin_unlock_irqrestore(mEp->lock, flags); | ||
| 2129 | return retval; | ||
| 2130 | } | ||
| 2131 | |||
| 2132 | /** | ||
| 2133 | * ep_disable: endpoint is no longer usable | ||
| 2134 | * | ||
| 2135 | * Check usb_ep_disable() at "usb_gadget.h" for details | ||
| 2136 | */ | ||
| 2137 | static int ep_disable(struct usb_ep *ep) | ||
| 2138 | { | ||
| 2139 | struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep); | ||
| 2140 | int direction, retval = 0; | ||
| 2141 | unsigned long flags; | ||
| 2142 | |||
| 2143 | trace("%p", ep); | ||
| 2144 | |||
| 2145 | if (ep == NULL) | ||
| 2146 | return -EINVAL; | ||
| 2147 | else if (mEp->desc == NULL) | ||
| 2148 | return -EBUSY; | ||
| 2149 | |||
| 2150 | spin_lock_irqsave(mEp->lock, flags); | ||
| 2151 | |||
| 2152 | /* only internal SW should disable ctrl endpts */ | ||
| 2153 | |||
| 2154 | direction = mEp->dir; | ||
| 2155 | do { | ||
| 2156 | dbg_event(_usb_addr(mEp), "DISABLE", 0); | ||
| 2157 | |||
| 2158 | retval |= _ep_nuke(mEp); | ||
| 2159 | retval |= hw_ep_disable(mEp->num, mEp->dir); | ||
| 2160 | |||
| 2161 | if (mEp->type == USB_ENDPOINT_XFER_CONTROL) | ||
| 2162 | mEp->dir = (mEp->dir == TX) ? RX : TX; | ||
| 2163 | |||
| 2164 | } while (mEp->dir != direction); | ||
| 2165 | |||
| 2166 | mEp->desc = NULL; | ||
| 2167 | |||
| 2168 | spin_unlock_irqrestore(mEp->lock, flags); | ||
| 2169 | return retval; | ||
| 2170 | } | ||
| 2171 | |||
| 2172 | /** | ||
| 2173 | * ep_alloc_request: allocate a request object to use with this endpoint | ||
| 2174 | * | ||
| 2175 | * Check usb_ep_alloc_request() at "usb_gadget.h" for details | ||
| 2176 | */ | ||
| 2177 | static struct usb_request *ep_alloc_request(struct usb_ep *ep, gfp_t gfp_flags) | ||
| 2178 | { | ||
| 2179 | struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep); | ||
| 2180 | struct ci13xxx_req *mReq = NULL; | ||
| 2181 | |||
| 2182 | trace("%p, %i", ep, gfp_flags); | ||
| 2183 | |||
| 2184 | if (ep == NULL) { | ||
| 2185 | err("EINVAL"); | ||
| 2186 | return NULL; | ||
| 2187 | } | ||
| 2188 | |||
| 2189 | mReq = kzalloc(sizeof(struct ci13xxx_req), gfp_flags); | ||
| 2190 | if (mReq != NULL) { | ||
| 2191 | INIT_LIST_HEAD(&mReq->queue); | ||
| 2192 | |||
| 2193 | mReq->ptr = dma_pool_alloc(mEp->td_pool, gfp_flags, | ||
| 2194 | &mReq->dma); | ||
| 2195 | if (mReq->ptr == NULL) { | ||
| 2196 | kfree(mReq); | ||
| 2197 | mReq = NULL; | ||
| 2198 | } | ||
| 2199 | } | ||
| 2200 | |||
| 2201 | dbg_event(_usb_addr(mEp), "ALLOC", mReq == NULL); | ||
| 2202 | |||
| 2203 | return (mReq == NULL) ? NULL : &mReq->req; | ||
| 2204 | } | ||
| 2205 | |||
| 2206 | /** | ||
| 2207 | * ep_free_request: frees a request object | ||
| 2208 | * | ||
| 2209 | * Check usb_ep_free_request() at "usb_gadget.h" for details | ||
| 2210 | */ | ||
| 2211 | static void ep_free_request(struct usb_ep *ep, struct usb_request *req) | ||
| 2212 | { | ||
| 2213 | struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep); | ||
| 2214 | struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req); | ||
| 2215 | unsigned long flags; | ||
| 2216 | |||
| 2217 | trace("%p, %p", ep, req); | ||
| 2218 | |||
| 2219 | if (ep == NULL || req == NULL) { | ||
| 2220 | err("EINVAL"); | ||
| 2221 | return; | ||
| 2222 | } else if (!list_empty(&mReq->queue)) { | ||
| 2223 | err("EBUSY"); | ||
| 2224 | return; | ||
| 2225 | } | ||
| 2226 | |||
| 2227 | spin_lock_irqsave(mEp->lock, flags); | ||
| 2228 | |||
| 2229 | if (mReq->ptr) | ||
| 2230 | dma_pool_free(mEp->td_pool, mReq->ptr, mReq->dma); | ||
| 2231 | kfree(mReq); | ||
| 2232 | |||
| 2233 | dbg_event(_usb_addr(mEp), "FREE", 0); | ||
| 2234 | |||
| 2235 | spin_unlock_irqrestore(mEp->lock, flags); | ||
| 2236 | } | ||
| 2237 | |||
| 2238 | /** | ||
| 2239 | * ep_queue: queues (submits) an I/O request to an endpoint | ||
| 2240 | * | ||
| 2241 | * Check usb_ep_queue()* at usb_gadget.h" for details | ||
| 2242 | */ | ||
| 2243 | static int ep_queue(struct usb_ep *ep, struct usb_request *req, | ||
| 2244 | gfp_t __maybe_unused gfp_flags) | ||
| 2245 | { | ||
| 2246 | struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep); | ||
| 2247 | struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req); | ||
| 2248 | int retval = 0; | ||
| 2249 | unsigned long flags; | ||
| 2250 | |||
| 2251 | trace("%p, %p, %X", ep, req, gfp_flags); | ||
| 2252 | |||
| 2253 | if (ep == NULL || req == NULL || mEp->desc == NULL) | ||
| 2254 | return -EINVAL; | ||
| 2255 | |||
| 2256 | spin_lock_irqsave(mEp->lock, flags); | ||
| 2257 | |||
| 2258 | if (mEp->type == USB_ENDPOINT_XFER_CONTROL) { | ||
| 2259 | if (req->length) | ||
| 2260 | mEp = (_udc->ep0_dir == RX) ? | ||
| 2261 | &_udc->ep0out : &_udc->ep0in; | ||
| 2262 | if (!list_empty(&mEp->qh.queue)) { | ||
| 2263 | _ep_nuke(mEp); | ||
| 2264 | retval = -EOVERFLOW; | ||
| 2265 | warn("endpoint ctrl %X nuked", _usb_addr(mEp)); | ||
| 2266 | } | ||
| 2267 | } | ||
| 2268 | |||
| 2269 | /* first nuke then test link, e.g. previous status has not sent */ | ||
| 2270 | if (!list_empty(&mReq->queue)) { | ||
| 2271 | retval = -EBUSY; | ||
| 2272 | err("request already in queue"); | ||
| 2273 | goto done; | ||
| 2274 | } | ||
| 2275 | |||
| 2276 | if (req->length > (4 * CI13XXX_PAGE_SIZE)) { | ||
| 2277 | req->length = (4 * CI13XXX_PAGE_SIZE); | ||
| 2278 | retval = -EMSGSIZE; | ||
| 2279 | warn("request length truncated"); | ||
| 2280 | } | ||
| 2281 | |||
| 2282 | dbg_queue(_usb_addr(mEp), req, retval); | ||
| 2283 | |||
| 2284 | /* push request */ | ||
| 2285 | mReq->req.status = -EINPROGRESS; | ||
| 2286 | mReq->req.actual = 0; | ||
| 2287 | |||
| 2288 | retval = _hardware_enqueue(mEp, mReq); | ||
| 2289 | |||
| 2290 | if (retval == -EALREADY) { | ||
| 2291 | dbg_event(_usb_addr(mEp), "QUEUE", retval); | ||
| 2292 | retval = 0; | ||
| 2293 | } | ||
| 2294 | if (!retval) | ||
| 2295 | list_add_tail(&mReq->queue, &mEp->qh.queue); | ||
| 2296 | |||
| 2297 | done: | ||
| 2298 | spin_unlock_irqrestore(mEp->lock, flags); | ||
| 2299 | return retval; | ||
| 2300 | } | ||
| 2301 | |||
| 2302 | /** | ||
| 2303 | * ep_dequeue: dequeues (cancels, unlinks) an I/O request from an endpoint | ||
| 2304 | * | ||
| 2305 | * Check usb_ep_dequeue() at "usb_gadget.h" for details | ||
| 2306 | */ | ||
| 2307 | static int ep_dequeue(struct usb_ep *ep, struct usb_request *req) | ||
| 2308 | { | ||
| 2309 | struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep); | ||
| 2310 | struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req); | ||
| 2311 | unsigned long flags; | ||
| 2312 | |||
| 2313 | trace("%p, %p", ep, req); | ||
| 2314 | |||
| 2315 | if (ep == NULL || req == NULL || mReq->req.status != -EALREADY || | ||
| 2316 | mEp->desc == NULL || list_empty(&mReq->queue) || | ||
| 2317 | list_empty(&mEp->qh.queue)) | ||
| 2318 | return -EINVAL; | ||
| 2319 | |||
| 2320 | spin_lock_irqsave(mEp->lock, flags); | ||
| 2321 | |||
| 2322 | dbg_event(_usb_addr(mEp), "DEQUEUE", 0); | ||
| 2323 | |||
| 2324 | hw_ep_flush(mEp->num, mEp->dir); | ||
| 2325 | |||
| 2326 | /* pop request */ | ||
| 2327 | list_del_init(&mReq->queue); | ||
| 2328 | if (mReq->map) { | ||
| 2329 | dma_unmap_single(mEp->device, mReq->req.dma, mReq->req.length, | ||
| 2330 | mEp->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE); | ||
| 2331 | mReq->req.dma = 0; | ||
| 2332 | mReq->map = 0; | ||
| 2333 | } | ||
| 2334 | req->status = -ECONNRESET; | ||
| 2335 | |||
| 2336 | if (mReq->req.complete != NULL) { | ||
| 2337 | spin_unlock(mEp->lock); | ||
| 2338 | mReq->req.complete(&mEp->ep, &mReq->req); | ||
| 2339 | spin_lock(mEp->lock); | ||
| 2340 | } | ||
| 2341 | |||
| 2342 | spin_unlock_irqrestore(mEp->lock, flags); | ||
| 2343 | return 0; | ||
| 2344 | } | ||
| 2345 | |||
| 2346 | /** | ||
| 2347 | * ep_set_halt: sets the endpoint halt feature | ||
| 2348 | * | ||
| 2349 | * Check usb_ep_set_halt() at "usb_gadget.h" for details | ||
| 2350 | */ | ||
| 2351 | static int ep_set_halt(struct usb_ep *ep, int value) | ||
| 2352 | { | ||
| 2353 | struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep); | ||
| 2354 | int direction, retval = 0; | ||
| 2355 | unsigned long flags; | ||
| 2356 | |||
| 2357 | trace("%p, %i", ep, value); | ||
| 2358 | |||
| 2359 | if (ep == NULL || mEp->desc == NULL) | ||
| 2360 | return -EINVAL; | ||
| 2361 | |||
| 2362 | spin_lock_irqsave(mEp->lock, flags); | ||
| 2363 | |||
| 2364 | #ifndef STALL_IN | ||
| 2365 | /* g_file_storage MS compliant but g_zero fails chapter 9 compliance */ | ||
| 2366 | if (value && mEp->type == USB_ENDPOINT_XFER_BULK && mEp->dir == TX && | ||
| 2367 | !list_empty(&mEp->qh.queue)) { | ||
| 2368 | spin_unlock_irqrestore(mEp->lock, flags); | ||
| 2369 | return -EAGAIN; | ||
| 2370 | } | ||
| 2371 | #endif | ||
| 2372 | |||
| 2373 | direction = mEp->dir; | ||
| 2374 | do { | ||
| 2375 | dbg_event(_usb_addr(mEp), "HALT", value); | ||
| 2376 | retval |= hw_ep_set_halt(mEp->num, mEp->dir, value); | ||
| 2377 | |||
| 2378 | if (!value) | ||
| 2379 | mEp->wedge = 0; | ||
| 2380 | |||
| 2381 | if (mEp->type == USB_ENDPOINT_XFER_CONTROL) | ||
| 2382 | mEp->dir = (mEp->dir == TX) ? RX : TX; | ||
| 2383 | |||
| 2384 | } while (mEp->dir != direction); | ||
| 2385 | |||
| 2386 | spin_unlock_irqrestore(mEp->lock, flags); | ||
| 2387 | return retval; | ||
| 2388 | } | ||
| 2389 | |||
| 2390 | /** | ||
| 2391 | * ep_set_wedge: sets the halt feature and ignores clear requests | ||
| 2392 | * | ||
| 2393 | * Check usb_ep_set_wedge() at "usb_gadget.h" for details | ||
| 2394 | */ | ||
| 2395 | static int ep_set_wedge(struct usb_ep *ep) | ||
| 2396 | { | ||
| 2397 | struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep); | ||
| 2398 | unsigned long flags; | ||
| 2399 | |||
| 2400 | trace("%p", ep); | ||
| 2401 | |||
| 2402 | if (ep == NULL || mEp->desc == NULL) | ||
| 2403 | return -EINVAL; | ||
| 2404 | |||
| 2405 | spin_lock_irqsave(mEp->lock, flags); | ||
| 2406 | |||
| 2407 | dbg_event(_usb_addr(mEp), "WEDGE", 0); | ||
| 2408 | mEp->wedge = 1; | ||
| 2409 | |||
| 2410 | spin_unlock_irqrestore(mEp->lock, flags); | ||
| 2411 | |||
| 2412 | return usb_ep_set_halt(ep); | ||
| 2413 | } | ||
| 2414 | |||
| 2415 | /** | ||
| 2416 | * ep_fifo_flush: flushes contents of a fifo | ||
| 2417 | * | ||
| 2418 | * Check usb_ep_fifo_flush() at "usb_gadget.h" for details | ||
| 2419 | */ | ||
| 2420 | static void ep_fifo_flush(struct usb_ep *ep) | ||
| 2421 | { | ||
| 2422 | struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep); | ||
| 2423 | unsigned long flags; | ||
| 2424 | |||
| 2425 | trace("%p", ep); | ||
| 2426 | |||
| 2427 | if (ep == NULL) { | ||
| 2428 | err("%02X: -EINVAL", _usb_addr(mEp)); | ||
| 2429 | return; | ||
| 2430 | } | ||
| 2431 | |||
| 2432 | spin_lock_irqsave(mEp->lock, flags); | ||
| 2433 | |||
| 2434 | dbg_event(_usb_addr(mEp), "FFLUSH", 0); | ||
| 2435 | hw_ep_flush(mEp->num, mEp->dir); | ||
| 2436 | |||
| 2437 | spin_unlock_irqrestore(mEp->lock, flags); | ||
| 2438 | } | ||
| 2439 | |||
| 2440 | /** | ||
| 2441 | * Endpoint-specific part of the API to the USB controller hardware | ||
| 2442 | * Check "usb_gadget.h" for details | ||
| 2443 | */ | ||
| 2444 | static const struct usb_ep_ops usb_ep_ops = { | ||
| 2445 | .enable = ep_enable, | ||
| 2446 | .disable = ep_disable, | ||
| 2447 | .alloc_request = ep_alloc_request, | ||
| 2448 | .free_request = ep_free_request, | ||
| 2449 | .queue = ep_queue, | ||
| 2450 | .dequeue = ep_dequeue, | ||
| 2451 | .set_halt = ep_set_halt, | ||
| 2452 | .set_wedge = ep_set_wedge, | ||
| 2453 | .fifo_flush = ep_fifo_flush, | ||
| 2454 | }; | ||
| 2455 | |||
| 2456 | /****************************************************************************** | ||
| 2457 | * GADGET block | ||
| 2458 | *****************************************************************************/ | ||
| 2459 | static int ci13xxx_vbus_session(struct usb_gadget *_gadget, int is_active) | ||
| 2460 | { | ||
| 2461 | struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget); | ||
| 2462 | unsigned long flags; | ||
| 2463 | int gadget_ready = 0; | ||
| 2464 | |||
| 2465 | if (!(udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS)) | ||
| 2466 | return -EOPNOTSUPP; | ||
| 2467 | |||
| 2468 | spin_lock_irqsave(udc->lock, flags); | ||
| 2469 | udc->vbus_active = is_active; | ||
| 2470 | if (udc->driver) | ||
| 2471 | gadget_ready = 1; | ||
| 2472 | spin_unlock_irqrestore(udc->lock, flags); | ||
| 2473 | |||
| 2474 | if (gadget_ready) { | ||
| 2475 | if (is_active) { | ||
| 2476 | pm_runtime_get_sync(&_gadget->dev); | ||
| 2477 | hw_device_reset(udc); | ||
| 2478 | hw_device_state(udc->ep0out.qh.dma); | ||
| 2479 | } else { | ||
| 2480 | hw_device_state(0); | ||
| 2481 | if (udc->udc_driver->notify_event) | ||
| 2482 | udc->udc_driver->notify_event(udc, | ||
| 2483 | CI13XXX_CONTROLLER_STOPPED_EVENT); | ||
| 2484 | _gadget_stop_activity(&udc->gadget); | ||
| 2485 | pm_runtime_put_sync(&_gadget->dev); | ||
| 2486 | } | ||
| 2487 | } | ||
| 2488 | |||
| 2489 | return 0; | ||
| 2490 | } | ||
| 2491 | |||
| 2492 | static int ci13xxx_wakeup(struct usb_gadget *_gadget) | ||
| 2493 | { | ||
| 2494 | struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget); | ||
| 2495 | unsigned long flags; | ||
| 2496 | int ret = 0; | ||
| 2497 | |||
| 2498 | trace(); | ||
| 2499 | |||
| 2500 | spin_lock_irqsave(udc->lock, flags); | ||
| 2501 | if (!udc->remote_wakeup) { | ||
| 2502 | ret = -EOPNOTSUPP; | ||
| 2503 | dbg_trace("remote wakeup feature is not enabled\n"); | ||
| 2504 | goto out; | ||
| 2505 | } | ||
| 2506 | if (!hw_cread(CAP_PORTSC, PORTSC_SUSP)) { | ||
| 2507 | ret = -EINVAL; | ||
| 2508 | dbg_trace("port is not suspended\n"); | ||
| 2509 | goto out; | ||
| 2510 | } | ||
| 2511 | hw_cwrite(CAP_PORTSC, PORTSC_FPR, PORTSC_FPR); | ||
| 2512 | out: | ||
| 2513 | spin_unlock_irqrestore(udc->lock, flags); | ||
| 2514 | return ret; | ||
| 2515 | } | ||
| 2516 | |||
| 2517 | static int ci13xxx_vbus_draw(struct usb_gadget *_gadget, unsigned mA) | ||
| 2518 | { | ||
| 2519 | struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget); | ||
| 2520 | |||
| 2521 | if (udc->transceiver) | ||
| 2522 | return otg_set_power(udc->transceiver, mA); | ||
| 2523 | return -ENOTSUPP; | ||
| 2524 | } | ||
| 2525 | |||
| 2526 | static int ci13xxx_start(struct usb_gadget_driver *driver, | ||
| 2527 | int (*bind)(struct usb_gadget *)); | ||
| 2528 | static int ci13xxx_stop(struct usb_gadget_driver *driver); | ||
| 2529 | /** | ||
| 2530 | * Device operations part of the API to the USB controller hardware, | ||
| 2531 | * which don't involve endpoints (or i/o) | ||
| 2532 | * Check "usb_gadget.h" for details | ||
| 2533 | */ | ||
| 2534 | static const struct usb_gadget_ops usb_gadget_ops = { | ||
| 2535 | .vbus_session = ci13xxx_vbus_session, | ||
| 2536 | .wakeup = ci13xxx_wakeup, | ||
| 2537 | .vbus_draw = ci13xxx_vbus_draw, | ||
| 2538 | .start = ci13xxx_start, | ||
| 2539 | .stop = ci13xxx_stop, | ||
| 2540 | }; | ||
| 2541 | |||
| 2542 | /** | ||
| 2543 | * ci13xxx_start: register a gadget driver | ||
| 2544 | * @driver: the driver being registered | ||
| 2545 | * @bind: the driver's bind callback | ||
| 2546 | * | ||
| 2547 | * Check ci13xxx_start() at <linux/usb/gadget.h> for details. | ||
| 2548 | * Interrupts are enabled here. | ||
| 2549 | */ | ||
| 2550 | static int ci13xxx_start(struct usb_gadget_driver *driver, | ||
| 2551 | int (*bind)(struct usb_gadget *)) | ||
| 2552 | { | ||
| 2553 | struct ci13xxx *udc = _udc; | ||
| 2554 | unsigned long flags; | ||
| 2555 | int i, j; | ||
| 2556 | int retval = -ENOMEM; | ||
| 2557 | |||
| 2558 | trace("%p", driver); | ||
| 2559 | |||
| 2560 | if (driver == NULL || | ||
| 2561 | bind == NULL || | ||
| 2562 | driver->setup == NULL || | ||
| 2563 | driver->disconnect == NULL || | ||
| 2564 | driver->suspend == NULL || | ||
| 2565 | driver->resume == NULL) | ||
| 2566 | return -EINVAL; | ||
| 2567 | else if (udc == NULL) | ||
| 2568 | return -ENODEV; | ||
| 2569 | else if (udc->driver != NULL) | ||
| 2570 | return -EBUSY; | ||
| 2571 | |||
| 2572 | /* alloc resources */ | ||
| 2573 | udc->qh_pool = dma_pool_create("ci13xxx_qh", &udc->gadget.dev, | ||
| 2574 | sizeof(struct ci13xxx_qh), | ||
| 2575 | 64, CI13XXX_PAGE_SIZE); | ||
| 2576 | if (udc->qh_pool == NULL) | ||
| 2577 | return -ENOMEM; | ||
| 2578 | |||
| 2579 | udc->td_pool = dma_pool_create("ci13xxx_td", &udc->gadget.dev, | ||
| 2580 | sizeof(struct ci13xxx_td), | ||
| 2581 | 64, CI13XXX_PAGE_SIZE); | ||
| 2582 | if (udc->td_pool == NULL) { | ||
| 2583 | dma_pool_destroy(udc->qh_pool); | ||
| 2584 | udc->qh_pool = NULL; | ||
| 2585 | return -ENOMEM; | ||
| 2586 | } | ||
| 2587 | |||
| 2588 | spin_lock_irqsave(udc->lock, flags); | ||
| 2589 | |||
| 2590 | info("hw_ep_max = %d", hw_ep_max); | ||
| 2591 | |||
| 2592 | udc->gadget.dev.driver = NULL; | ||
| 2593 | |||
| 2594 | retval = 0; | ||
| 2595 | for (i = 0; i < hw_ep_max/2; i++) { | ||
| 2596 | for (j = RX; j <= TX; j++) { | ||
| 2597 | int k = i + j * hw_ep_max/2; | ||
| 2598 | struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[k]; | ||
| 2599 | |||
| 2600 | scnprintf(mEp->name, sizeof(mEp->name), "ep%i%s", i, | ||
| 2601 | (j == TX) ? "in" : "out"); | ||
| 2602 | |||
| 2603 | mEp->lock = udc->lock; | ||
| 2604 | mEp->device = &udc->gadget.dev; | ||
| 2605 | mEp->td_pool = udc->td_pool; | ||
| 2606 | |||
| 2607 | mEp->ep.name = mEp->name; | ||
| 2608 | mEp->ep.ops = &usb_ep_ops; | ||
| 2609 | mEp->ep.maxpacket = CTRL_PAYLOAD_MAX; | ||
| 2610 | |||
| 2611 | INIT_LIST_HEAD(&mEp->qh.queue); | ||
| 2612 | spin_unlock_irqrestore(udc->lock, flags); | ||
| 2613 | mEp->qh.ptr = dma_pool_alloc(udc->qh_pool, GFP_KERNEL, | ||
| 2614 | &mEp->qh.dma); | ||
| 2615 | spin_lock_irqsave(udc->lock, flags); | ||
| 2616 | if (mEp->qh.ptr == NULL) | ||
| 2617 | retval = -ENOMEM; | ||
| 2618 | else | ||
| 2619 | memset(mEp->qh.ptr, 0, sizeof(*mEp->qh.ptr)); | ||
| 2620 | |||
| 2621 | /* skip ep0 out and in endpoints */ | ||
| 2622 | if (i == 0) | ||
| 2623 | continue; | ||
| 2624 | |||
| 2625 | list_add_tail(&mEp->ep.ep_list, &udc->gadget.ep_list); | ||
| 2626 | } | ||
| 2627 | } | ||
| 2628 | if (retval) | ||
| 2629 | goto done; | ||
| 2630 | spin_unlock_irqrestore(udc->lock, flags); | ||
| 2631 | udc->ep0out.ep.desc = &ctrl_endpt_out_desc; | ||
| 2632 | retval = usb_ep_enable(&udc->ep0out.ep); | ||
| 2633 | if (retval) | ||
| 2634 | return retval; | ||
| 2635 | |||
| 2636 | udc->ep0in.ep.desc = &ctrl_endpt_in_desc; | ||
| 2637 | retval = usb_ep_enable(&udc->ep0in.ep); | ||
| 2638 | if (retval) | ||
| 2639 | return retval; | ||
| 2640 | spin_lock_irqsave(udc->lock, flags); | ||
| 2641 | |||
| 2642 | udc->gadget.ep0 = &udc->ep0in.ep; | ||
| 2643 | /* bind gadget */ | ||
| 2644 | driver->driver.bus = NULL; | ||
| 2645 | udc->gadget.dev.driver = &driver->driver; | ||
| 2646 | |||
| 2647 | spin_unlock_irqrestore(udc->lock, flags); | ||
| 2648 | retval = bind(&udc->gadget); /* MAY SLEEP */ | ||
| 2649 | spin_lock_irqsave(udc->lock, flags); | ||
| 2650 | |||
| 2651 | if (retval) { | ||
| 2652 | udc->gadget.dev.driver = NULL; | ||
| 2653 | goto done; | ||
| 2654 | } | ||
| 2655 | |||
| 2656 | udc->driver = driver; | ||
| 2657 | pm_runtime_get_sync(&udc->gadget.dev); | ||
| 2658 | if (udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) { | ||
| 2659 | if (udc->vbus_active) { | ||
| 2660 | if (udc->udc_driver->flags & CI13XXX_REGS_SHARED) | ||
| 2661 | hw_device_reset(udc); | ||
| 2662 | } else { | ||
| 2663 | pm_runtime_put_sync(&udc->gadget.dev); | ||
| 2664 | goto done; | ||
| 2665 | } | ||
| 2666 | } | ||
| 2667 | |||
| 2668 | retval = hw_device_state(udc->ep0out.qh.dma); | ||
| 2669 | if (retval) | ||
| 2670 | pm_runtime_put_sync(&udc->gadget.dev); | ||
| 2671 | |||
| 2672 | done: | ||
| 2673 | spin_unlock_irqrestore(udc->lock, flags); | ||
| 2674 | return retval; | ||
| 2675 | } | ||
| 2676 | |||
| 2677 | /** | ||
| 2678 | * ci13xxx_stop: unregister a gadget driver | ||
| 2679 | * | ||
| 2680 | * Check usb_gadget_unregister_driver() at "usb_gadget.h" for details | ||
| 2681 | */ | ||
| 2682 | static int ci13xxx_stop(struct usb_gadget_driver *driver) | ||
| 2683 | { | ||
| 2684 | struct ci13xxx *udc = _udc; | ||
| 2685 | unsigned long i, flags; | ||
| 2686 | |||
| 2687 | trace("%p", driver); | ||
| 2688 | |||
| 2689 | if (driver == NULL || | ||
| 2690 | driver->unbind == NULL || | ||
| 2691 | driver->setup == NULL || | ||
| 2692 | driver->disconnect == NULL || | ||
| 2693 | driver->suspend == NULL || | ||
| 2694 | driver->resume == NULL || | ||
| 2695 | driver != udc->driver) | ||
| 2696 | return -EINVAL; | ||
| 2697 | |||
| 2698 | spin_lock_irqsave(udc->lock, flags); | ||
| 2699 | |||
| 2700 | if (!(udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) || | ||
| 2701 | udc->vbus_active) { | ||
| 2702 | hw_device_state(0); | ||
| 2703 | if (udc->udc_driver->notify_event) | ||
| 2704 | udc->udc_driver->notify_event(udc, | ||
| 2705 | CI13XXX_CONTROLLER_STOPPED_EVENT); | ||
| 2706 | _gadget_stop_activity(&udc->gadget); | ||
| 2707 | pm_runtime_put(&udc->gadget.dev); | ||
| 2708 | } | ||
| 2709 | |||
| 2710 | /* unbind gadget */ | ||
| 2711 | spin_unlock_irqrestore(udc->lock, flags); | ||
| 2712 | driver->unbind(&udc->gadget); /* MAY SLEEP */ | ||
| 2713 | spin_lock_irqsave(udc->lock, flags); | ||
| 2714 | |||
| 2715 | udc->gadget.dev.driver = NULL; | ||
| 2716 | |||
| 2717 | /* free resources */ | ||
| 2718 | for (i = 0; i < hw_ep_max; i++) { | ||
| 2719 | struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i]; | ||
| 2720 | |||
| 2721 | if (!list_empty(&mEp->ep.ep_list)) | ||
| 2722 | list_del_init(&mEp->ep.ep_list); | ||
| 2723 | |||
| 2724 | if (mEp->qh.ptr != NULL) | ||
| 2725 | dma_pool_free(udc->qh_pool, mEp->qh.ptr, mEp->qh.dma); | ||
| 2726 | } | ||
| 2727 | |||
| 2728 | udc->gadget.ep0 = NULL; | ||
| 2729 | udc->driver = NULL; | ||
| 2730 | |||
| 2731 | spin_unlock_irqrestore(udc->lock, flags); | ||
| 2732 | |||
| 2733 | if (udc->td_pool != NULL) { | ||
| 2734 | dma_pool_destroy(udc->td_pool); | ||
| 2735 | udc->td_pool = NULL; | ||
| 2736 | } | ||
| 2737 | if (udc->qh_pool != NULL) { | ||
| 2738 | dma_pool_destroy(udc->qh_pool); | ||
| 2739 | udc->qh_pool = NULL; | ||
| 2740 | } | ||
| 2741 | |||
| 2742 | return 0; | ||
| 2743 | } | ||
| 2744 | |||
| 2745 | /****************************************************************************** | ||
| 2746 | * BUS block | ||
| 2747 | *****************************************************************************/ | ||
| 2748 | /** | ||
| 2749 | * udc_irq: global interrupt handler | ||
| 2750 | * | ||
| 2751 | * This function returns IRQ_HANDLED if the IRQ has been handled | ||
| 2752 | * It locks access to registers | ||
| 2753 | */ | ||
| 2754 | static irqreturn_t udc_irq(void) | ||
| 2755 | { | ||
| 2756 | struct ci13xxx *udc = _udc; | ||
| 2757 | irqreturn_t retval; | ||
| 2758 | u32 intr; | ||
| 2759 | |||
| 2760 | trace(); | ||
| 2761 | |||
| 2762 | if (udc == NULL) { | ||
| 2763 | err("ENODEV"); | ||
| 2764 | return IRQ_HANDLED; | ||
| 2765 | } | ||
| 2766 | |||
| 2767 | spin_lock(udc->lock); | ||
| 2768 | |||
| 2769 | if (udc->udc_driver->flags & CI13XXX_REGS_SHARED) { | ||
| 2770 | if (hw_cread(CAP_USBMODE, USBMODE_CM) != | ||
| 2771 | USBMODE_CM_DEVICE) { | ||
| 2772 | spin_unlock(udc->lock); | ||
| 2773 | return IRQ_NONE; | ||
| 2774 | } | ||
| 2775 | } | ||
| 2776 | intr = hw_test_and_clear_intr_active(); | ||
| 2777 | if (intr) { | ||
| 2778 | isr_statistics.hndl.buf[isr_statistics.hndl.idx++] = intr; | ||
| 2779 | isr_statistics.hndl.idx &= ISR_MASK; | ||
| 2780 | isr_statistics.hndl.cnt++; | ||
| 2781 | |||
| 2782 | /* order defines priority - do NOT change it */ | ||
| 2783 | if (USBi_URI & intr) { | ||
| 2784 | isr_statistics.uri++; | ||
| 2785 | isr_reset_handler(udc); | ||
| 2786 | } | ||
| 2787 | if (USBi_PCI & intr) { | ||
| 2788 | isr_statistics.pci++; | ||
| 2789 | udc->gadget.speed = hw_port_is_high_speed() ? | ||
| 2790 | USB_SPEED_HIGH : USB_SPEED_FULL; | ||
| 2791 | if (udc->suspended) { | ||
| 2792 | spin_unlock(udc->lock); | ||
| 2793 | udc->driver->resume(&udc->gadget); | ||
| 2794 | spin_lock(udc->lock); | ||
| 2795 | udc->suspended = 0; | ||
| 2796 | } | ||
| 2797 | } | ||
| 2798 | if (USBi_UEI & intr) | ||
| 2799 | isr_statistics.uei++; | ||
| 2800 | if (USBi_UI & intr) { | ||
| 2801 | isr_statistics.ui++; | ||
| 2802 | isr_tr_complete_handler(udc); | ||
| 2803 | } | ||
| 2804 | if (USBi_SLI & intr) { | ||
| 2805 | if (udc->gadget.speed != USB_SPEED_UNKNOWN) { | ||
| 2806 | udc->suspended = 1; | ||
| 2807 | spin_unlock(udc->lock); | ||
| 2808 | udc->driver->suspend(&udc->gadget); | ||
| 2809 | spin_lock(udc->lock); | ||
| 2810 | } | ||
| 2811 | isr_statistics.sli++; | ||
| 2812 | } | ||
| 2813 | retval = IRQ_HANDLED; | ||
| 2814 | } else { | ||
| 2815 | isr_statistics.none++; | ||
| 2816 | retval = IRQ_NONE; | ||
| 2817 | } | ||
| 2818 | spin_unlock(udc->lock); | ||
| 2819 | |||
| 2820 | return retval; | ||
| 2821 | } | ||
| 2822 | |||
| 2823 | /** | ||
| 2824 | * udc_release: driver release function | ||
| 2825 | * @dev: device | ||
| 2826 | * | ||
| 2827 | * Currently does nothing | ||
| 2828 | */ | ||
| 2829 | static void udc_release(struct device *dev) | ||
| 2830 | { | ||
| 2831 | trace("%p", dev); | ||
| 2832 | |||
| 2833 | if (dev == NULL) | ||
| 2834 | err("EINVAL"); | ||
| 2835 | } | ||
| 2836 | |||
| 2837 | /** | ||
| 2838 | * udc_probe: parent probe must call this to initialize UDC | ||
| 2839 | * @dev: parent device | ||
| 2840 | * @regs: registers base address | ||
| 2841 | * @name: driver name | ||
| 2842 | * | ||
| 2843 | * This function returns an error code | ||
| 2844 | * No interrupts active, the IRQ has not been requested yet | ||
| 2845 | * Kernel assumes 32-bit DMA operations by default, no need to dma_set_mask | ||
| 2846 | */ | ||
| 2847 | static int udc_probe(struct ci13xxx_udc_driver *driver, struct device *dev, | ||
| 2848 | void __iomem *regs) | ||
| 2849 | { | ||
| 2850 | struct ci13xxx *udc; | ||
| 2851 | int retval = 0; | ||
| 2852 | |||
| 2853 | trace("%p, %p, %p", dev, regs, name); | ||
| 2854 | |||
| 2855 | if (dev == NULL || regs == NULL || driver == NULL || | ||
| 2856 | driver->name == NULL) | ||
| 2857 | return -EINVAL; | ||
| 2858 | |||
| 2859 | udc = kzalloc(sizeof(struct ci13xxx), GFP_KERNEL); | ||
| 2860 | if (udc == NULL) | ||
| 2861 | return -ENOMEM; | ||
| 2862 | |||
| 2863 | udc->lock = &udc_lock; | ||
| 2864 | udc->regs = regs; | ||
| 2865 | udc->udc_driver = driver; | ||
| 2866 | |||
| 2867 | udc->gadget.ops = &usb_gadget_ops; | ||
| 2868 | udc->gadget.speed = USB_SPEED_UNKNOWN; | ||
| 2869 | udc->gadget.is_dualspeed = 1; | ||
| 2870 | udc->gadget.is_otg = 0; | ||
| 2871 | udc->gadget.name = driver->name; | ||
| 2872 | |||
| 2873 | INIT_LIST_HEAD(&udc->gadget.ep_list); | ||
| 2874 | udc->gadget.ep0 = NULL; | ||
| 2875 | |||
| 2876 | dev_set_name(&udc->gadget.dev, "gadget"); | ||
| 2877 | udc->gadget.dev.dma_mask = dev->dma_mask; | ||
| 2878 | udc->gadget.dev.coherent_dma_mask = dev->coherent_dma_mask; | ||
| 2879 | udc->gadget.dev.parent = dev; | ||
| 2880 | udc->gadget.dev.release = udc_release; | ||
| 2881 | |||
| 2882 | retval = hw_device_init(regs); | ||
| 2883 | if (retval < 0) | ||
| 2884 | goto free_udc; | ||
| 2885 | |||
| 2886 | udc->transceiver = otg_get_transceiver(); | ||
| 2887 | |||
| 2888 | if (udc->udc_driver->flags & CI13XXX_REQUIRE_TRANSCEIVER) { | ||
| 2889 | if (udc->transceiver == NULL) { | ||
| 2890 | retval = -ENODEV; | ||
| 2891 | goto free_udc; | ||
| 2892 | } | ||
| 2893 | } | ||
| 2894 | |||
| 2895 | if (!(udc->udc_driver->flags & CI13XXX_REGS_SHARED)) { | ||
| 2896 | retval = hw_device_reset(udc); | ||
| 2897 | if (retval) | ||
| 2898 | goto put_transceiver; | ||
| 2899 | } | ||
| 2900 | |||
| 2901 | retval = device_register(&udc->gadget.dev); | ||
| 2902 | if (retval) { | ||
| 2903 | put_device(&udc->gadget.dev); | ||
| 2904 | goto put_transceiver; | ||
| 2905 | } | ||
| 2906 | |||
| 2907 | #ifdef CONFIG_USB_GADGET_DEBUG_FILES | ||
| 2908 | retval = dbg_create_files(&udc->gadget.dev); | ||
| 2909 | #endif | ||
| 2910 | if (retval) | ||
| 2911 | goto unreg_device; | ||
| 2912 | |||
| 2913 | if (udc->transceiver) { | ||
| 2914 | retval = otg_set_peripheral(udc->transceiver, &udc->gadget); | ||
| 2915 | if (retval) | ||
| 2916 | goto remove_dbg; | ||
| 2917 | } | ||
| 2918 | |||
| 2919 | retval = usb_add_gadget_udc(dev, &udc->gadget); | ||
| 2920 | if (retval) | ||
| 2921 | goto remove_trans; | ||
| 2922 | |||
| 2923 | pm_runtime_no_callbacks(&udc->gadget.dev); | ||
| 2924 | pm_runtime_enable(&udc->gadget.dev); | ||
| 2925 | |||
| 2926 | _udc = udc; | ||
| 2927 | return retval; | ||
| 2928 | |||
| 2929 | remove_trans: | ||
| 2930 | if (udc->transceiver) { | ||
| 2931 | otg_set_peripheral(udc->transceiver, &udc->gadget); | ||
| 2932 | otg_put_transceiver(udc->transceiver); | ||
| 2933 | } | ||
| 2934 | |||
| 2935 | err("error = %i", retval); | ||
| 2936 | remove_dbg: | ||
| 2937 | #ifdef CONFIG_USB_GADGET_DEBUG_FILES | ||
| 2938 | dbg_remove_files(&udc->gadget.dev); | ||
| 2939 | #endif | ||
| 2940 | unreg_device: | ||
| 2941 | device_unregister(&udc->gadget.dev); | ||
| 2942 | put_transceiver: | ||
| 2943 | if (udc->transceiver) | ||
| 2944 | otg_put_transceiver(udc->transceiver); | ||
| 2945 | free_udc: | ||
| 2946 | kfree(udc); | ||
| 2947 | _udc = NULL; | ||
| 2948 | return retval; | ||
| 2949 | } | ||
| 2950 | |||
| 2951 | /** | ||
| 2952 | * udc_remove: parent remove must call this to remove UDC | ||
| 2953 | * | ||
| 2954 | * No interrupts active, the IRQ has been released | ||
| 2955 | */ | ||
| 2956 | static void udc_remove(void) | ||
| 2957 | { | ||
| 2958 | struct ci13xxx *udc = _udc; | ||
| 2959 | |||
| 2960 | if (udc == NULL) { | ||
| 2961 | err("EINVAL"); | ||
| 2962 | return; | ||
| 2963 | } | ||
| 2964 | usb_del_gadget_udc(&udc->gadget); | ||
| 2965 | |||
| 2966 | if (udc->transceiver) { | ||
| 2967 | otg_set_peripheral(udc->transceiver, &udc->gadget); | ||
| 2968 | otg_put_transceiver(udc->transceiver); | ||
| 2969 | } | ||
| 2970 | #ifdef CONFIG_USB_GADGET_DEBUG_FILES | ||
| 2971 | dbg_remove_files(&udc->gadget.dev); | ||
| 2972 | #endif | ||
| 2973 | device_unregister(&udc->gadget.dev); | ||
| 2974 | |||
| 2975 | kfree(udc); | ||
| 2976 | _udc = NULL; | ||
| 2977 | } | ||
diff --git a/drivers/usb/gadget/ci13xxx_udc.h b/drivers/usb/gadget/ci13xxx_udc.h new file mode 100644 index 00000000000..23707775cb4 --- /dev/null +++ b/drivers/usb/gadget/ci13xxx_udc.h | |||
| @@ -0,0 +1,227 @@ | |||
| 1 | /* | ||
| 2 | * ci13xxx_udc.h - structures, registers, and macros MIPS USB IP core | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved. | ||
| 5 | * | ||
| 6 | * Author: David Lopo | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | * | ||
| 12 | * Description: MIPS USB IP core family device controller | ||
| 13 | * Structures, registers and logging macros | ||
| 14 | */ | ||
| 15 | |||
| 16 | #ifndef _CI13XXX_h_ | ||
| 17 | #define _CI13XXX_h_ | ||
| 18 | |||
| 19 | /****************************************************************************** | ||
| 20 | * DEFINE | ||
| 21 | *****************************************************************************/ | ||
| 22 | #define CI13XXX_PAGE_SIZE 4096ul /* page size for TD's */ | ||
| 23 | #define ENDPT_MAX (32) | ||
| 24 | #define CTRL_PAYLOAD_MAX (64) | ||
| 25 | #define RX (0) /* similar to USB_DIR_OUT but can be used as an index */ | ||
| 26 | #define TX (1) /* similar to USB_DIR_IN but can be used as an index */ | ||
| 27 | |||
| 28 | /****************************************************************************** | ||
| 29 | * STRUCTURES | ||
| 30 | *****************************************************************************/ | ||
| 31 | /* DMA layout of transfer descriptors */ | ||
| 32 | struct ci13xxx_td { | ||
| 33 | /* 0 */ | ||
| 34 | u32 next; | ||
| 35 | #define TD_TERMINATE BIT(0) | ||
| 36 | #define TD_ADDR_MASK (0xFFFFFFEUL << 5) | ||
| 37 | /* 1 */ | ||
| 38 | u32 token; | ||
| 39 | #define TD_STATUS (0x00FFUL << 0) | ||
| 40 | #define TD_STATUS_TR_ERR BIT(3) | ||
| 41 | #define TD_STATUS_DT_ERR BIT(5) | ||
| 42 | #define TD_STATUS_HALTED BIT(6) | ||
| 43 | #define TD_STATUS_ACTIVE BIT(7) | ||
| 44 | #define TD_MULTO (0x0003UL << 10) | ||
| 45 | #define TD_IOC BIT(15) | ||
| 46 | #define TD_TOTAL_BYTES (0x7FFFUL << 16) | ||
| 47 | /* 2 */ | ||
| 48 | u32 page[5]; | ||
| 49 | #define TD_CURR_OFFSET (0x0FFFUL << 0) | ||
| 50 | #define TD_FRAME_NUM (0x07FFUL << 0) | ||
| 51 | #define TD_RESERVED_MASK (0x0FFFUL << 0) | ||
| 52 | } __attribute__ ((packed)); | ||
| 53 | |||
| 54 | /* DMA layout of queue heads */ | ||
| 55 | struct ci13xxx_qh { | ||
| 56 | /* 0 */ | ||
| 57 | u32 cap; | ||
| 58 | #define QH_IOS BIT(15) | ||
| 59 | #define QH_MAX_PKT (0x07FFUL << 16) | ||
| 60 | #define QH_ZLT BIT(29) | ||
| 61 | #define QH_MULT (0x0003UL << 30) | ||
| 62 | /* 1 */ | ||
| 63 | u32 curr; | ||
| 64 | /* 2 - 8 */ | ||
| 65 | struct ci13xxx_td td; | ||
| 66 | /* 9 */ | ||
| 67 | u32 RESERVED; | ||
| 68 | struct usb_ctrlrequest setup; | ||
| 69 | } __attribute__ ((packed)); | ||
| 70 | |||
| 71 | /* Extension of usb_request */ | ||
| 72 | struct ci13xxx_req { | ||
| 73 | struct usb_request req; | ||
| 74 | unsigned map; | ||
| 75 | struct list_head queue; | ||
| 76 | struct ci13xxx_td *ptr; | ||
| 77 | dma_addr_t dma; | ||
| 78 | struct ci13xxx_td *zptr; | ||
| 79 | dma_addr_t zdma; | ||
| 80 | }; | ||
| 81 | |||
| 82 | /* Extension of usb_ep */ | ||
| 83 | struct ci13xxx_ep { | ||
| 84 | struct usb_ep ep; | ||
| 85 | const struct usb_endpoint_descriptor *desc; | ||
| 86 | u8 dir; | ||
| 87 | u8 num; | ||
| 88 | u8 type; | ||
| 89 | char name[16]; | ||
| 90 | struct { | ||
| 91 | struct list_head queue; | ||
| 92 | struct ci13xxx_qh *ptr; | ||
| 93 | dma_addr_t dma; | ||
| 94 | } qh; | ||
| 95 | int wedge; | ||
| 96 | |||
| 97 | /* global resources */ | ||
| 98 | spinlock_t *lock; | ||
| 99 | struct device *device; | ||
| 100 | struct dma_pool *td_pool; | ||
| 101 | }; | ||
| 102 | |||
| 103 | struct ci13xxx; | ||
| 104 | struct ci13xxx_udc_driver { | ||
| 105 | const char *name; | ||
| 106 | unsigned long flags; | ||
| 107 | #define CI13XXX_REGS_SHARED BIT(0) | ||
| 108 | #define CI13XXX_REQUIRE_TRANSCEIVER BIT(1) | ||
| 109 | #define CI13XXX_PULLUP_ON_VBUS BIT(2) | ||
| 110 | #define CI13XXX_DISABLE_STREAMING BIT(3) | ||
| 111 | |||
| 112 | #define CI13XXX_CONTROLLER_RESET_EVENT 0 | ||
| 113 | #define CI13XXX_CONTROLLER_STOPPED_EVENT 1 | ||
| 114 | void (*notify_event) (struct ci13xxx *udc, unsigned event); | ||
| 115 | }; | ||
| 116 | |||
| 117 | /* CI13XXX UDC descriptor & global resources */ | ||
| 118 | struct ci13xxx { | ||
| 119 | spinlock_t *lock; /* ctrl register bank access */ | ||
| 120 | void __iomem *regs; /* registers address space */ | ||
| 121 | |||
| 122 | struct dma_pool *qh_pool; /* DMA pool for queue heads */ | ||
| 123 | struct dma_pool *td_pool; /* DMA pool for transfer descs */ | ||
| 124 | struct usb_request *status; /* ep0 status request */ | ||
| 125 | |||
| 126 | struct usb_gadget gadget; /* USB slave device */ | ||
| 127 | struct ci13xxx_ep ci13xxx_ep[ENDPT_MAX]; /* extended endpts */ | ||
| 128 | u32 ep0_dir; /* ep0 direction */ | ||
| 129 | #define ep0out ci13xxx_ep[0] | ||
| 130 | #define ep0in ci13xxx_ep[16] | ||
| 131 | u8 remote_wakeup; /* Is remote wakeup feature | ||
| 132 | enabled by the host? */ | ||
| 133 | u8 suspended; /* suspended by the host */ | ||
| 134 | u8 test_mode; /* the selected test mode */ | ||
| 135 | |||
| 136 | struct usb_gadget_driver *driver; /* 3rd party gadget driver */ | ||
| 137 | struct ci13xxx_udc_driver *udc_driver; /* device controller driver */ | ||
| 138 | int vbus_active; /* is VBUS active */ | ||
| 139 | struct otg_transceiver *transceiver; /* Transceiver struct */ | ||
| 140 | }; | ||
| 141 | |||
| 142 | /****************************************************************************** | ||
| 143 | * REGISTERS | ||
| 144 | *****************************************************************************/ | ||
| 145 | /* register size */ | ||
| 146 | #define REG_BITS (32) | ||
| 147 | |||
| 148 | /* HCCPARAMS */ | ||
| 149 | #define HCCPARAMS_LEN BIT(17) | ||
| 150 | |||
| 151 | /* DCCPARAMS */ | ||
| 152 | #define DCCPARAMS_DEN (0x1F << 0) | ||
| 153 | #define DCCPARAMS_DC BIT(7) | ||
| 154 | |||
| 155 | /* TESTMODE */ | ||
| 156 | #define TESTMODE_FORCE BIT(0) | ||
| 157 | |||
| 158 | /* USBCMD */ | ||
| 159 | #define USBCMD_RS BIT(0) | ||
| 160 | #define USBCMD_RST BIT(1) | ||
| 161 | #define USBCMD_SUTW BIT(13) | ||
| 162 | #define USBCMD_ATDTW BIT(14) | ||
| 163 | |||
| 164 | /* USBSTS & USBINTR */ | ||
| 165 | #define USBi_UI BIT(0) | ||
| 166 | #define USBi_UEI BIT(1) | ||
| 167 | #define USBi_PCI BIT(2) | ||
| 168 | #define USBi_URI BIT(6) | ||
| 169 | #define USBi_SLI BIT(8) | ||
| 170 | |||
| 171 | /* DEVICEADDR */ | ||
| 172 | #define DEVICEADDR_USBADRA BIT(24) | ||
| 173 | #define DEVICEADDR_USBADR (0x7FUL << 25) | ||
| 174 | |||
| 175 | /* PORTSC */ | ||
| 176 | #define PORTSC_FPR BIT(6) | ||
| 177 | #define PORTSC_SUSP BIT(7) | ||
| 178 | #define PORTSC_HSP BIT(9) | ||
| 179 | #define PORTSC_PTC (0x0FUL << 16) | ||
| 180 | |||
| 181 | /* DEVLC */ | ||
| 182 | #define DEVLC_PSPD (0x03UL << 25) | ||
| 183 | #define DEVLC_PSPD_HS (0x02UL << 25) | ||
| 184 | |||
| 185 | /* USBMODE */ | ||
| 186 | #define USBMODE_CM (0x03UL << 0) | ||
| 187 | #define USBMODE_CM_IDLE (0x00UL << 0) | ||
| 188 | #define USBMODE_CM_DEVICE (0x02UL << 0) | ||
| 189 | #define USBMODE_CM_HOST (0x03UL << 0) | ||
| 190 | #define USBMODE_SLOM BIT(3) | ||
| 191 | #define USBMODE_SDIS BIT(4) | ||
| 192 | |||
| 193 | /* ENDPTCTRL */ | ||
| 194 | #define ENDPTCTRL_RXS BIT(0) | ||
| 195 | #define ENDPTCTRL_RXT (0x03UL << 2) | ||
| 196 | #define ENDPTCTRL_RXR BIT(6) /* reserved for port 0 */ | ||
| 197 | #define ENDPTCTRL_RXE BIT(7) | ||
| 198 | #define ENDPTCTRL_TXS BIT(16) | ||
| 199 | #define ENDPTCTRL_TXT (0x03UL << 18) | ||
| 200 | #define ENDPTCTRL_TXR BIT(22) /* reserved for port 0 */ | ||
| 201 | #define ENDPTCTRL_TXE BIT(23) | ||
| 202 | |||
| 203 | /****************************************************************************** | ||
| 204 | * LOGGING | ||
| 205 | *****************************************************************************/ | ||
| 206 | #define ci13xxx_printk(level, format, args...) \ | ||
| 207 | do { \ | ||
| 208 | if (_udc == NULL) \ | ||
| 209 | printk(level "[%s] " format "\n", __func__, ## args); \ | ||
| 210 | else \ | ||
| 211 | dev_printk(level, _udc->gadget.dev.parent, \ | ||
| 212 | "[%s] " format "\n", __func__, ## args); \ | ||
| 213 | } while (0) | ||
| 214 | |||
| 215 | #define err(format, args...) ci13xxx_printk(KERN_ERR, format, ## args) | ||
| 216 | #define warn(format, args...) ci13xxx_printk(KERN_WARNING, format, ## args) | ||
| 217 | #define info(format, args...) ci13xxx_printk(KERN_INFO, format, ## args) | ||
| 218 | |||
| 219 | #ifdef TRACE | ||
| 220 | #define trace(format, args...) ci13xxx_printk(KERN_DEBUG, format, ## args) | ||
| 221 | #define dbg_trace(format, args...) dev_dbg(dev, format, ##args) | ||
| 222 | #else | ||
| 223 | #define trace(format, args...) do {} while (0) | ||
| 224 | #define dbg_trace(format, args...) do {} while (0) | ||
| 225 | #endif | ||
| 226 | |||
| 227 | #endif /* _CI13XXX_h_ */ | ||
diff --git a/drivers/usb/gadget/f_accessory.c b/drivers/usb/gadget/f_accessory.c new file mode 100644 index 00000000000..ae65faaf3d7 --- /dev/null +++ b/drivers/usb/gadget/f_accessory.c | |||
| @@ -0,0 +1,788 @@ | |||
| 1 | /* | ||
| 2 | * Gadget Function Driver for Android USB accessories | ||
| 3 | * | ||
| 4 | * Copyright (C) 2011 Google, Inc. | ||
| 5 | * Author: Mike Lockwood <lockwood@android.com> | ||
| 6 | * | ||
| 7 | * This software is licensed under the terms of the GNU General Public | ||
| 8 | * License version 2, as published by the Free Software Foundation, and | ||
| 9 | * may be copied, distributed, and modified under those terms. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | */ | ||
| 17 | |||
| 18 | /* #define DEBUG */ | ||
| 19 | /* #define VERBOSE_DEBUG */ | ||
| 20 | |||
| 21 | #include <linux/module.h> | ||
| 22 | #include <linux/init.h> | ||
| 23 | #include <linux/poll.h> | ||
| 24 | #include <linux/delay.h> | ||
| 25 | #include <linux/wait.h> | ||
| 26 | #include <linux/err.h> | ||
| 27 | #include <linux/interrupt.h> | ||
| 28 | #include <linux/kthread.h> | ||
| 29 | #include <linux/freezer.h> | ||
| 30 | |||
| 31 | #include <linux/types.h> | ||
| 32 | #include <linux/file.h> | ||
| 33 | #include <linux/device.h> | ||
| 34 | #include <linux/miscdevice.h> | ||
| 35 | |||
| 36 | #include <linux/usb.h> | ||
| 37 | #include <linux/usb/ch9.h> | ||
| 38 | #include <linux/usb/f_accessory.h> | ||
| 39 | |||
| 40 | #define BULK_BUFFER_SIZE 16384 | ||
| 41 | #define ACC_STRING_SIZE 256 | ||
| 42 | |||
| 43 | #define PROTOCOL_VERSION 1 | ||
| 44 | |||
| 45 | /* String IDs */ | ||
| 46 | #define INTERFACE_STRING_INDEX 0 | ||
| 47 | |||
| 48 | /* number of tx and rx requests to allocate */ | ||
| 49 | #define TX_REQ_MAX 4 | ||
| 50 | #define RX_REQ_MAX 2 | ||
| 51 | |||
| 52 | struct acc_dev { | ||
| 53 | struct usb_function function; | ||
| 54 | struct usb_composite_dev *cdev; | ||
| 55 | spinlock_t lock; | ||
| 56 | |||
| 57 | struct usb_ep *ep_in; | ||
| 58 | struct usb_ep *ep_out; | ||
| 59 | |||
| 60 | /* set to 1 when we connect */ | ||
| 61 | int online:1; | ||
| 62 | /* Set to 1 when we disconnect. | ||
| 63 | * Not cleared until our file is closed. | ||
| 64 | */ | ||
| 65 | int disconnected:1; | ||
| 66 | |||
| 67 | /* strings sent by the host */ | ||
| 68 | char manufacturer[ACC_STRING_SIZE]; | ||
| 69 | char model[ACC_STRING_SIZE]; | ||
| 70 | char description[ACC_STRING_SIZE]; | ||
| 71 | char version[ACC_STRING_SIZE]; | ||
| 72 | char uri[ACC_STRING_SIZE]; | ||
| 73 | char serial[ACC_STRING_SIZE]; | ||
| 74 | |||
| 75 | /* for acc_complete_set_string */ | ||
| 76 | int string_index; | ||
| 77 | |||
| 78 | /* set to 1 if we have a pending start request */ | ||
| 79 | int start_requested; | ||
| 80 | |||
| 81 | /* synchronize access to our device file */ | ||
| 82 | atomic_t open_excl; | ||
| 83 | |||
| 84 | struct list_head tx_idle; | ||
| 85 | |||
| 86 | wait_queue_head_t read_wq; | ||
| 87 | wait_queue_head_t write_wq; | ||
| 88 | struct usb_request *rx_req[RX_REQ_MAX]; | ||
| 89 | int rx_done; | ||
| 90 | struct delayed_work work; | ||
| 91 | }; | ||
| 92 | |||
| 93 | static struct usb_interface_descriptor acc_interface_desc = { | ||
| 94 | .bLength = USB_DT_INTERFACE_SIZE, | ||
| 95 | .bDescriptorType = USB_DT_INTERFACE, | ||
| 96 | .bInterfaceNumber = 0, | ||
| 97 | .bNumEndpoints = 2, | ||
| 98 | .bInterfaceClass = USB_CLASS_VENDOR_SPEC, | ||
| 99 | .bInterfaceSubClass = USB_SUBCLASS_VENDOR_SPEC, | ||
| 100 | .bInterfaceProtocol = 0, | ||
| 101 | }; | ||
| 102 | |||
| 103 | static struct usb_endpoint_descriptor acc_highspeed_in_desc = { | ||
| 104 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
| 105 | .bDescriptorType = USB_DT_ENDPOINT, | ||
| 106 | .bEndpointAddress = USB_DIR_IN, | ||
| 107 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
| 108 | .wMaxPacketSize = __constant_cpu_to_le16(512), | ||
| 109 | }; | ||
| 110 | |||
| 111 | static struct usb_endpoint_descriptor acc_highspeed_out_desc = { | ||
| 112 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
| 113 | .bDescriptorType = USB_DT_ENDPOINT, | ||
| 114 | .bEndpointAddress = USB_DIR_OUT, | ||
| 115 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
| 116 | .wMaxPacketSize = __constant_cpu_to_le16(512), | ||
| 117 | }; | ||
| 118 | |||
| 119 | static struct usb_endpoint_descriptor acc_fullspeed_in_desc = { | ||
| 120 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
| 121 | .bDescriptorType = USB_DT_ENDPOINT, | ||
| 122 | .bEndpointAddress = USB_DIR_IN, | ||
| 123 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
| 124 | }; | ||
| 125 | |||
| 126 | static struct usb_endpoint_descriptor acc_fullspeed_out_desc = { | ||
| 127 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
| 128 | .bDescriptorType = USB_DT_ENDPOINT, | ||
| 129 | .bEndpointAddress = USB_DIR_OUT, | ||
| 130 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
| 131 | }; | ||
| 132 | |||
| 133 | static struct usb_descriptor_header *fs_acc_descs[] = { | ||
| 134 | (struct usb_descriptor_header *) &acc_interface_desc, | ||
| 135 | (struct usb_descriptor_header *) &acc_fullspeed_in_desc, | ||
| 136 | (struct usb_descriptor_header *) &acc_fullspeed_out_desc, | ||
| 137 | NULL, | ||
| 138 | }; | ||
| 139 | |||
| 140 | static struct usb_descriptor_header *hs_acc_descs[] = { | ||
| 141 | (struct usb_descriptor_header *) &acc_interface_desc, | ||
| 142 | (struct usb_descriptor_header *) &acc_highspeed_in_desc, | ||
| 143 | (struct usb_descriptor_header *) &acc_highspeed_out_desc, | ||
| 144 | NULL, | ||
| 145 | }; | ||
| 146 | |||
| 147 | static struct usb_string acc_string_defs[] = { | ||
| 148 | [INTERFACE_STRING_INDEX].s = "Android Accessory Interface", | ||
| 149 | { }, /* end of list */ | ||
| 150 | }; | ||
| 151 | |||
| 152 | static struct usb_gadget_strings acc_string_table = { | ||
| 153 | .language = 0x0409, /* en-US */ | ||
| 154 | .strings = acc_string_defs, | ||
| 155 | }; | ||
| 156 | |||
| 157 | static struct usb_gadget_strings *acc_strings[] = { | ||
| 158 | &acc_string_table, | ||
| 159 | NULL, | ||
| 160 | }; | ||
| 161 | |||
| 162 | /* temporary variable used between acc_open() and acc_gadget_bind() */ | ||
| 163 | static struct acc_dev *_acc_dev; | ||
| 164 | |||
| 165 | static inline struct acc_dev *func_to_dev(struct usb_function *f) | ||
| 166 | { | ||
| 167 | return container_of(f, struct acc_dev, function); | ||
| 168 | } | ||
| 169 | |||
| 170 | static struct usb_request *acc_request_new(struct usb_ep *ep, int buffer_size) | ||
| 171 | { | ||
| 172 | struct usb_request *req = usb_ep_alloc_request(ep, GFP_KERNEL); | ||
| 173 | if (!req) | ||
| 174 | return NULL; | ||
| 175 | |||
| 176 | /* now allocate buffers for the requests */ | ||
| 177 | req->buf = kmalloc(buffer_size, GFP_KERNEL); | ||
| 178 | if (!req->buf) { | ||
| 179 | usb_ep_free_request(ep, req); | ||
| 180 | return NULL; | ||
| 181 | } | ||
| 182 | |||
| 183 | return req; | ||
| 184 | } | ||
| 185 | |||
| 186 | static void acc_request_free(struct usb_request *req, struct usb_ep *ep) | ||
| 187 | { | ||
| 188 | if (req) { | ||
| 189 | kfree(req->buf); | ||
| 190 | usb_ep_free_request(ep, req); | ||
| 191 | } | ||
| 192 | } | ||
| 193 | |||
| 194 | /* add a request to the tail of a list */ | ||
| 195 | static void req_put(struct acc_dev *dev, struct list_head *head, | ||
| 196 | struct usb_request *req) | ||
| 197 | { | ||
| 198 | unsigned long flags; | ||
| 199 | |||
| 200 | spin_lock_irqsave(&dev->lock, flags); | ||
| 201 | list_add_tail(&req->list, head); | ||
| 202 | spin_unlock_irqrestore(&dev->lock, flags); | ||
| 203 | } | ||
| 204 | |||
| 205 | /* remove a request from the head of a list */ | ||
| 206 | static struct usb_request *req_get(struct acc_dev *dev, struct list_head *head) | ||
| 207 | { | ||
| 208 | unsigned long flags; | ||
| 209 | struct usb_request *req; | ||
| 210 | |||
| 211 | spin_lock_irqsave(&dev->lock, flags); | ||
| 212 | if (list_empty(head)) { | ||
| 213 | req = 0; | ||
| 214 | } else { | ||
| 215 | req = list_first_entry(head, struct usb_request, list); | ||
| 216 | list_del(&req->list); | ||
| 217 | } | ||
| 218 | spin_unlock_irqrestore(&dev->lock, flags); | ||
| 219 | return req; | ||
| 220 | } | ||
| 221 | |||
| 222 | static void acc_set_disconnected(struct acc_dev *dev) | ||
| 223 | { | ||
| 224 | dev->online = 0; | ||
| 225 | dev->disconnected = 1; | ||
| 226 | } | ||
| 227 | |||
| 228 | static void acc_complete_in(struct usb_ep *ep, struct usb_request *req) | ||
| 229 | { | ||
| 230 | struct acc_dev *dev = _acc_dev; | ||
| 231 | |||
| 232 | if (req->status != 0) | ||
| 233 | acc_set_disconnected(dev); | ||
| 234 | |||
| 235 | req_put(dev, &dev->tx_idle, req); | ||
| 236 | |||
| 237 | wake_up(&dev->write_wq); | ||
| 238 | } | ||
| 239 | |||
| 240 | static void acc_complete_out(struct usb_ep *ep, struct usb_request *req) | ||
| 241 | { | ||
| 242 | struct acc_dev *dev = _acc_dev; | ||
| 243 | |||
| 244 | dev->rx_done = 1; | ||
| 245 | if (req->status != 0) | ||
| 246 | acc_set_disconnected(dev); | ||
| 247 | |||
| 248 | wake_up(&dev->read_wq); | ||
| 249 | } | ||
| 250 | |||
| 251 | static void acc_complete_set_string(struct usb_ep *ep, struct usb_request *req) | ||
| 252 | { | ||
| 253 | struct acc_dev *dev = ep->driver_data; | ||
| 254 | char *string_dest = NULL; | ||
| 255 | int length = req->actual; | ||
| 256 | |||
| 257 | if (req->status != 0) { | ||
| 258 | pr_err("acc_complete_set_string, err %d\n", req->status); | ||
| 259 | return; | ||
| 260 | } | ||
| 261 | |||
| 262 | switch (dev->string_index) { | ||
| 263 | case ACCESSORY_STRING_MANUFACTURER: | ||
| 264 | string_dest = dev->manufacturer; | ||
| 265 | break; | ||
| 266 | case ACCESSORY_STRING_MODEL: | ||
| 267 | string_dest = dev->model; | ||
| 268 | break; | ||
| 269 | case ACCESSORY_STRING_DESCRIPTION: | ||
| 270 | string_dest = dev->description; | ||
| 271 | break; | ||
| 272 | case ACCESSORY_STRING_VERSION: | ||
| 273 | string_dest = dev->version; | ||
| 274 | break; | ||
| 275 | case ACCESSORY_STRING_URI: | ||
| 276 | string_dest = dev->uri; | ||
| 277 | break; | ||
| 278 | case ACCESSORY_STRING_SERIAL: | ||
| 279 | string_dest = dev->serial; | ||
| 280 | break; | ||
| 281 | } | ||
| 282 | if (string_dest) { | ||
| 283 | unsigned long flags; | ||
| 284 | |||
| 285 | if (length >= ACC_STRING_SIZE) | ||
| 286 | length = ACC_STRING_SIZE - 1; | ||
| 287 | |||
| 288 | spin_lock_irqsave(&dev->lock, flags); | ||
| 289 | memcpy(string_dest, req->buf, length); | ||
| 290 | /* ensure zero termination */ | ||
| 291 | string_dest[length] = 0; | ||
| 292 | spin_unlock_irqrestore(&dev->lock, flags); | ||
| 293 | } else { | ||
| 294 | pr_err("unknown accessory string index %d\n", | ||
| 295 | dev->string_index); | ||
| 296 | } | ||
| 297 | } | ||
| 298 | |||
| 299 | static int __init create_bulk_endpoints(struct acc_dev *dev, | ||
| 300 | struct usb_endpoint_descriptor *in_desc, | ||
| 301 | struct usb_endpoint_descriptor *out_desc) | ||
| 302 | { | ||
| 303 | struct usb_composite_dev *cdev = dev->cdev; | ||
| 304 | struct usb_request *req; | ||
| 305 | struct usb_ep *ep; | ||
| 306 | int i; | ||
| 307 | |||
| 308 | DBG(cdev, "create_bulk_endpoints dev: %p\n", dev); | ||
| 309 | |||
| 310 | ep = usb_ep_autoconfig(cdev->gadget, in_desc); | ||
| 311 | if (!ep) { | ||
| 312 | DBG(cdev, "usb_ep_autoconfig for ep_in failed\n"); | ||
| 313 | return -ENODEV; | ||
| 314 | } | ||
| 315 | DBG(cdev, "usb_ep_autoconfig for ep_in got %s\n", ep->name); | ||
| 316 | ep->driver_data = dev; /* claim the endpoint */ | ||
| 317 | dev->ep_in = ep; | ||
| 318 | |||
| 319 | ep = usb_ep_autoconfig(cdev->gadget, out_desc); | ||
| 320 | if (!ep) { | ||
| 321 | DBG(cdev, "usb_ep_autoconfig for ep_out failed\n"); | ||
| 322 | return -ENODEV; | ||
| 323 | } | ||
| 324 | DBG(cdev, "usb_ep_autoconfig for ep_out got %s\n", ep->name); | ||
| 325 | ep->driver_data = dev; /* claim the endpoint */ | ||
| 326 | dev->ep_out = ep; | ||
| 327 | |||
| 328 | ep = usb_ep_autoconfig(cdev->gadget, out_desc); | ||
| 329 | if (!ep) { | ||
| 330 | DBG(cdev, "usb_ep_autoconfig for ep_out failed\n"); | ||
| 331 | return -ENODEV; | ||
| 332 | } | ||
| 333 | DBG(cdev, "usb_ep_autoconfig for ep_out got %s\n", ep->name); | ||
| 334 | ep->driver_data = dev; /* claim the endpoint */ | ||
| 335 | dev->ep_out = ep; | ||
| 336 | |||
| 337 | /* now allocate requests for our endpoints */ | ||
| 338 | for (i = 0; i < TX_REQ_MAX; i++) { | ||
| 339 | req = acc_request_new(dev->ep_in, BULK_BUFFER_SIZE); | ||
| 340 | if (!req) | ||
| 341 | goto fail; | ||
| 342 | req->complete = acc_complete_in; | ||
| 343 | req_put(dev, &dev->tx_idle, req); | ||
| 344 | } | ||
| 345 | for (i = 0; i < RX_REQ_MAX; i++) { | ||
| 346 | req = acc_request_new(dev->ep_out, BULK_BUFFER_SIZE); | ||
| 347 | if (!req) | ||
| 348 | goto fail; | ||
| 349 | req->complete = acc_complete_out; | ||
| 350 | dev->rx_req[i] = req; | ||
| 351 | } | ||
| 352 | |||
| 353 | return 0; | ||
| 354 | |||
| 355 | fail: | ||
| 356 | printk(KERN_ERR "acc_bind() could not allocate requests\n"); | ||
| 357 | while ((req = req_get(dev, &dev->tx_idle))) | ||
| 358 | acc_request_free(req, dev->ep_in); | ||
| 359 | for (i = 0; i < RX_REQ_MAX; i++) | ||
| 360 | acc_request_free(dev->rx_req[i], dev->ep_out); | ||
| 361 | return -1; | ||
| 362 | } | ||
| 363 | |||
| 364 | static ssize_t acc_read(struct file *fp, char __user *buf, | ||
| 365 | size_t count, loff_t *pos) | ||
| 366 | { | ||
| 367 | struct acc_dev *dev = fp->private_data; | ||
| 368 | struct usb_request *req; | ||
| 369 | int r = count, xfer; | ||
| 370 | int ret = 0; | ||
| 371 | |||
| 372 | pr_debug("acc_read(%d)\n", count); | ||
| 373 | |||
| 374 | if (dev->disconnected) | ||
| 375 | return -ENODEV; | ||
| 376 | |||
| 377 | if (count > BULK_BUFFER_SIZE) | ||
| 378 | count = BULK_BUFFER_SIZE; | ||
| 379 | |||
| 380 | /* we will block until we're online */ | ||
| 381 | pr_debug("acc_read: waiting for online\n"); | ||
| 382 | ret = wait_event_interruptible(dev->read_wq, dev->online); | ||
| 383 | if (ret < 0) { | ||
| 384 | r = ret; | ||
| 385 | goto done; | ||
| 386 | } | ||
| 387 | |||
| 388 | requeue_req: | ||
| 389 | /* queue a request */ | ||
| 390 | req = dev->rx_req[0]; | ||
| 391 | req->length = count; | ||
| 392 | dev->rx_done = 0; | ||
| 393 | ret = usb_ep_queue(dev->ep_out, req, GFP_KERNEL); | ||
| 394 | if (ret < 0) { | ||
| 395 | r = -EIO; | ||
| 396 | goto done; | ||
| 397 | } else { | ||
| 398 | pr_debug("rx %p queue\n", req); | ||
| 399 | } | ||
| 400 | |||
| 401 | /* wait for a request to complete */ | ||
| 402 | ret = wait_event_interruptible(dev->read_wq, dev->rx_done); | ||
| 403 | if (ret < 0) { | ||
| 404 | r = ret; | ||
| 405 | usb_ep_dequeue(dev->ep_out, req); | ||
| 406 | goto done; | ||
| 407 | } | ||
| 408 | if (dev->online) { | ||
| 409 | /* If we got a 0-len packet, throw it back and try again. */ | ||
| 410 | if (req->actual == 0) | ||
| 411 | goto requeue_req; | ||
| 412 | |||
| 413 | pr_debug("rx %p %d\n", req, req->actual); | ||
| 414 | xfer = (req->actual < count) ? req->actual : count; | ||
| 415 | r = xfer; | ||
| 416 | if (copy_to_user(buf, req->buf, xfer)) | ||
| 417 | r = -EFAULT; | ||
| 418 | } else | ||
| 419 | r = -EIO; | ||
| 420 | |||
| 421 | done: | ||
| 422 | pr_debug("acc_read returning %d\n", r); | ||
| 423 | return r; | ||
| 424 | } | ||
| 425 | |||
| 426 | static ssize_t acc_write(struct file *fp, const char __user *buf, | ||
| 427 | size_t count, loff_t *pos) | ||
| 428 | { | ||
| 429 | struct acc_dev *dev = fp->private_data; | ||
| 430 | struct usb_request *req = 0; | ||
| 431 | int r = count, xfer; | ||
| 432 | int ret; | ||
| 433 | |||
| 434 | pr_debug("acc_write(%d)\n", count); | ||
| 435 | |||
| 436 | if (!dev->online || dev->disconnected) | ||
| 437 | return -ENODEV; | ||
| 438 | |||
| 439 | while (count > 0) { | ||
| 440 | if (!dev->online) { | ||
| 441 | pr_debug("acc_write dev->error\n"); | ||
| 442 | r = -EIO; | ||
| 443 | break; | ||
| 444 | } | ||
| 445 | |||
| 446 | /* get an idle tx request to use */ | ||
| 447 | req = 0; | ||
| 448 | ret = wait_event_interruptible(dev->write_wq, | ||
| 449 | ((req = req_get(dev, &dev->tx_idle)) || !dev->online)); | ||
| 450 | if (!req) { | ||
| 451 | r = ret; | ||
| 452 | break; | ||
| 453 | } | ||
| 454 | |||
| 455 | if (count > BULK_BUFFER_SIZE) | ||
| 456 | xfer = BULK_BUFFER_SIZE; | ||
| 457 | else | ||
| 458 | xfer = count; | ||
| 459 | if (copy_from_user(req->buf, buf, xfer)) { | ||
| 460 | r = -EFAULT; | ||
| 461 | break; | ||
| 462 | } | ||
| 463 | |||
| 464 | req->length = xfer; | ||
| 465 | ret = usb_ep_queue(dev->ep_in, req, GFP_KERNEL); | ||
| 466 | if (ret < 0) { | ||
| 467 | pr_debug("acc_write: xfer error %d\n", ret); | ||
| 468 | r = -EIO; | ||
| 469 | break; | ||
| 470 | } | ||
| 471 | |||
| 472 | buf += xfer; | ||
| 473 | count -= xfer; | ||
| 474 | |||
| 475 | /* zero this so we don't try to free it on error exit */ | ||
| 476 | req = 0; | ||
| 477 | } | ||
| 478 | |||
| 479 | if (req) | ||
| 480 | req_put(dev, &dev->tx_idle, req); | ||
| 481 | |||
| 482 | pr_debug("acc_write returning %d\n", r); | ||
| 483 | return r; | ||
| 484 | } | ||
| 485 | |||
| 486 | static long acc_ioctl(struct file *fp, unsigned code, unsigned long value) | ||
| 487 | { | ||
| 488 | struct acc_dev *dev = fp->private_data; | ||
| 489 | char *src = NULL; | ||
| 490 | int ret; | ||
| 491 | |||
| 492 | switch (code) { | ||
| 493 | case ACCESSORY_GET_STRING_MANUFACTURER: | ||
| 494 | src = dev->manufacturer; | ||
| 495 | break; | ||
| 496 | case ACCESSORY_GET_STRING_MODEL: | ||
| 497 | src = dev->model; | ||
| 498 | break; | ||
| 499 | case ACCESSORY_GET_STRING_DESCRIPTION: | ||
| 500 | src = dev->description; | ||
| 501 | break; | ||
| 502 | case ACCESSORY_GET_STRING_VERSION: | ||
| 503 | src = dev->version; | ||
| 504 | break; | ||
| 505 | case ACCESSORY_GET_STRING_URI: | ||
| 506 | src = dev->uri; | ||
| 507 | break; | ||
| 508 | case ACCESSORY_GET_STRING_SERIAL: | ||
| 509 | src = dev->serial; | ||
| 510 | break; | ||
| 511 | case ACCESSORY_IS_START_REQUESTED: | ||
| 512 | return dev->start_requested; | ||
| 513 | } | ||
| 514 | if (!src) | ||
| 515 | return -EINVAL; | ||
| 516 | |||
| 517 | ret = strlen(src) + 1; | ||
| 518 | if (copy_to_user((void __user *)value, src, ret)) | ||
| 519 | ret = -EFAULT; | ||
| 520 | return ret; | ||
| 521 | } | ||
| 522 | |||
| 523 | static int acc_open(struct inode *ip, struct file *fp) | ||
| 524 | { | ||
| 525 | printk(KERN_INFO "acc_open\n"); | ||
| 526 | if (atomic_xchg(&_acc_dev->open_excl, 1)) | ||
| 527 | return -EBUSY; | ||
| 528 | |||
| 529 | _acc_dev->disconnected = 0; | ||
| 530 | fp->private_data = _acc_dev; | ||
| 531 | return 0; | ||
| 532 | } | ||
| 533 | |||
| 534 | static int acc_release(struct inode *ip, struct file *fp) | ||
| 535 | { | ||
| 536 | printk(KERN_INFO "acc_release\n"); | ||
| 537 | |||
| 538 | WARN_ON(!atomic_xchg(&_acc_dev->open_excl, 0)); | ||
| 539 | _acc_dev->disconnected = 0; | ||
| 540 | return 0; | ||
| 541 | } | ||
| 542 | |||
| 543 | /* file operations for /dev/acc_usb */ | ||
| 544 | static const struct file_operations acc_fops = { | ||
| 545 | .owner = THIS_MODULE, | ||
| 546 | .read = acc_read, | ||
| 547 | .write = acc_write, | ||
| 548 | .unlocked_ioctl = acc_ioctl, | ||
| 549 | .open = acc_open, | ||
| 550 | .release = acc_release, | ||
| 551 | }; | ||
| 552 | |||
| 553 | static struct miscdevice acc_device = { | ||
| 554 | .minor = MISC_DYNAMIC_MINOR, | ||
| 555 | .name = "usb_accessory", | ||
| 556 | .fops = &acc_fops, | ||
| 557 | }; | ||
| 558 | |||
| 559 | |||
| 560 | static int acc_ctrlrequest(struct usb_composite_dev *cdev, | ||
| 561 | const struct usb_ctrlrequest *ctrl) | ||
| 562 | { | ||
| 563 | struct acc_dev *dev = _acc_dev; | ||
| 564 | int value = -EOPNOTSUPP; | ||
| 565 | u8 b_requestType = ctrl->bRequestType; | ||
| 566 | u8 b_request = ctrl->bRequest; | ||
| 567 | u16 w_index = le16_to_cpu(ctrl->wIndex); | ||
| 568 | u16 w_value = le16_to_cpu(ctrl->wValue); | ||
| 569 | u16 w_length = le16_to_cpu(ctrl->wLength); | ||
| 570 | |||
| 571 | /* | ||
| 572 | printk(KERN_INFO "acc_ctrlrequest " | ||
| 573 | "%02x.%02x v%04x i%04x l%u\n", | ||
| 574 | b_requestType, b_request, | ||
| 575 | w_value, w_index, w_length); | ||
| 576 | */ | ||
| 577 | |||
| 578 | if (b_requestType == (USB_DIR_OUT | USB_TYPE_VENDOR)) { | ||
| 579 | if (b_request == ACCESSORY_START) { | ||
| 580 | dev->start_requested = 1; | ||
| 581 | schedule_delayed_work( | ||
| 582 | &dev->work, msecs_to_jiffies(10)); | ||
| 583 | value = 0; | ||
| 584 | } else if (b_request == ACCESSORY_SEND_STRING) { | ||
| 585 | dev->string_index = w_index; | ||
| 586 | cdev->gadget->ep0->driver_data = dev; | ||
| 587 | cdev->req->complete = acc_complete_set_string; | ||
| 588 | value = w_length; | ||
| 589 | } | ||
| 590 | } else if (b_requestType == (USB_DIR_IN | USB_TYPE_VENDOR)) { | ||
| 591 | if (b_request == ACCESSORY_GET_PROTOCOL) { | ||
| 592 | *((u16 *)cdev->req->buf) = PROTOCOL_VERSION; | ||
| 593 | value = sizeof(u16); | ||
| 594 | |||
| 595 | /* clear any strings left over from a previous session */ | ||
| 596 | memset(dev->manufacturer, 0, sizeof(dev->manufacturer)); | ||
| 597 | memset(dev->model, 0, sizeof(dev->model)); | ||
| 598 | memset(dev->description, 0, sizeof(dev->description)); | ||
| 599 | memset(dev->version, 0, sizeof(dev->version)); | ||
| 600 | memset(dev->uri, 0, sizeof(dev->uri)); | ||
| 601 | memset(dev->serial, 0, sizeof(dev->serial)); | ||
| 602 | dev->start_requested = 0; | ||
| 603 | } | ||
| 604 | } | ||
| 605 | |||
| 606 | if (value >= 0) { | ||
| 607 | cdev->req->zero = 0; | ||
| 608 | cdev->req->length = value; | ||
| 609 | value = usb_ep_queue(cdev->gadget->ep0, cdev->req, GFP_ATOMIC); | ||
| 610 | if (value < 0) | ||
| 611 | ERROR(cdev, "%s setup response queue error\n", | ||
| 612 | __func__); | ||
| 613 | } | ||
| 614 | |||
| 615 | if (value == -EOPNOTSUPP) | ||
| 616 | VDBG(cdev, | ||
| 617 | "unknown class-specific control req " | ||
| 618 | "%02x.%02x v%04x i%04x l%u\n", | ||
| 619 | ctrl->bRequestType, ctrl->bRequest, | ||
| 620 | w_value, w_index, w_length); | ||
| 621 | return value; | ||
| 622 | } | ||
| 623 | |||
| 624 | static int | ||
| 625 | acc_function_bind(struct usb_configuration *c, struct usb_function *f) | ||
| 626 | { | ||
| 627 | struct usb_composite_dev *cdev = c->cdev; | ||
| 628 | struct acc_dev *dev = func_to_dev(f); | ||
| 629 | int id; | ||
| 630 | int ret; | ||
| 631 | |||
| 632 | DBG(cdev, "acc_function_bind dev: %p\n", dev); | ||
| 633 | |||
| 634 | dev->start_requested = 0; | ||
| 635 | |||
| 636 | /* allocate interface ID(s) */ | ||
| 637 | id = usb_interface_id(c, f); | ||
| 638 | if (id < 0) | ||
| 639 | return id; | ||
| 640 | acc_interface_desc.bInterfaceNumber = id; | ||
| 641 | |||
| 642 | /* allocate endpoints */ | ||
| 643 | ret = create_bulk_endpoints(dev, &acc_fullspeed_in_desc, | ||
| 644 | &acc_fullspeed_out_desc); | ||
| 645 | if (ret) | ||
| 646 | return ret; | ||
| 647 | |||
| 648 | /* support high speed hardware */ | ||
| 649 | if (gadget_is_dualspeed(c->cdev->gadget)) { | ||
| 650 | acc_highspeed_in_desc.bEndpointAddress = | ||
| 651 | acc_fullspeed_in_desc.bEndpointAddress; | ||
| 652 | acc_highspeed_out_desc.bEndpointAddress = | ||
| 653 | acc_fullspeed_out_desc.bEndpointAddress; | ||
| 654 | } | ||
| 655 | |||
| 656 | DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n", | ||
| 657 | gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", | ||
| 658 | f->name, dev->ep_in->name, dev->ep_out->name); | ||
| 659 | return 0; | ||
| 660 | } | ||
| 661 | |||
| 662 | static void | ||
| 663 | acc_function_unbind(struct usb_configuration *c, struct usb_function *f) | ||
| 664 | { | ||
| 665 | struct acc_dev *dev = func_to_dev(f); | ||
| 666 | struct usb_request *req; | ||
| 667 | int i; | ||
| 668 | |||
| 669 | while ((req = req_get(dev, &dev->tx_idle))) | ||
| 670 | acc_request_free(req, dev->ep_in); | ||
| 671 | for (i = 0; i < RX_REQ_MAX; i++) | ||
| 672 | acc_request_free(dev->rx_req[i], dev->ep_out); | ||
| 673 | } | ||
| 674 | |||
| 675 | static void acc_work(struct work_struct *data) | ||
| 676 | { | ||
| 677 | char *envp[2] = { "ACCESSORY=START", NULL }; | ||
| 678 | kobject_uevent_env(&acc_device.this_device->kobj, KOBJ_CHANGE, envp); | ||
| 679 | } | ||
| 680 | |||
| 681 | static int acc_function_set_alt(struct usb_function *f, | ||
| 682 | unsigned intf, unsigned alt) | ||
| 683 | { | ||
| 684 | struct acc_dev *dev = func_to_dev(f); | ||
| 685 | struct usb_composite_dev *cdev = f->config->cdev; | ||
| 686 | int ret; | ||
| 687 | |||
| 688 | DBG(cdev, "acc_function_set_alt intf: %d alt: %d\n", intf, alt); | ||
| 689 | config_ep_by_speed(cdev->gadget, f, dev->ep_in); | ||
| 690 | ret = usb_ep_enable(dev->ep_in); | ||
| 691 | if (ret) | ||
| 692 | return ret; | ||
| 693 | config_ep_by_speed(cdev->gadget, f, dev->ep_out); | ||
| 694 | ret = usb_ep_enable(dev->ep_out); | ||
| 695 | if (ret) { | ||
| 696 | usb_ep_disable(dev->ep_in); | ||
| 697 | return ret; | ||
| 698 | } | ||
| 699 | |||
| 700 | dev->online = 1; | ||
| 701 | |||
| 702 | /* readers may be blocked waiting for us to go online */ | ||
| 703 | wake_up(&dev->read_wq); | ||
| 704 | return 0; | ||
| 705 | } | ||
| 706 | |||
| 707 | static void acc_function_disable(struct usb_function *f) | ||
| 708 | { | ||
| 709 | struct acc_dev *dev = func_to_dev(f); | ||
| 710 | struct usb_composite_dev *cdev = dev->cdev; | ||
| 711 | |||
| 712 | DBG(cdev, "acc_function_disable\n"); | ||
| 713 | acc_set_disconnected(dev); | ||
| 714 | usb_ep_disable(dev->ep_in); | ||
| 715 | usb_ep_disable(dev->ep_out); | ||
| 716 | |||
| 717 | /* readers may be blocked waiting for us to go online */ | ||
| 718 | wake_up(&dev->read_wq); | ||
| 719 | |||
| 720 | VDBG(cdev, "%s disabled\n", dev->function.name); | ||
| 721 | } | ||
| 722 | |||
| 723 | static int acc_bind_config(struct usb_configuration *c) | ||
| 724 | { | ||
| 725 | struct acc_dev *dev = _acc_dev; | ||
| 726 | int ret; | ||
| 727 | |||
| 728 | printk(KERN_INFO "acc_bind_config\n"); | ||
| 729 | |||
| 730 | /* allocate a string ID for our interface */ | ||
| 731 | if (acc_string_defs[INTERFACE_STRING_INDEX].id == 0) { | ||
| 732 | ret = usb_string_id(c->cdev); | ||
| 733 | if (ret < 0) | ||
| 734 | return ret; | ||
| 735 | acc_string_defs[INTERFACE_STRING_INDEX].id = ret; | ||
| 736 | acc_interface_desc.iInterface = ret; | ||
| 737 | } | ||
| 738 | |||
| 739 | dev->cdev = c->cdev; | ||
| 740 | dev->function.name = "accessory"; | ||
| 741 | dev->function.strings = acc_strings, | ||
| 742 | dev->function.descriptors = fs_acc_descs; | ||
| 743 | dev->function.hs_descriptors = hs_acc_descs; | ||
| 744 | dev->function.bind = acc_function_bind; | ||
| 745 | dev->function.unbind = acc_function_unbind; | ||
| 746 | dev->function.set_alt = acc_function_set_alt; | ||
| 747 | dev->function.disable = acc_function_disable; | ||
| 748 | |||
| 749 | return usb_add_function(c, &dev->function); | ||
| 750 | } | ||
| 751 | |||
| 752 | static int acc_setup(void) | ||
| 753 | { | ||
| 754 | struct acc_dev *dev; | ||
| 755 | int ret; | ||
| 756 | |||
| 757 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||
| 758 | if (!dev) | ||
| 759 | return -ENOMEM; | ||
| 760 | |||
| 761 | spin_lock_init(&dev->lock); | ||
| 762 | init_waitqueue_head(&dev->read_wq); | ||
| 763 | init_waitqueue_head(&dev->write_wq); | ||
| 764 | atomic_set(&dev->open_excl, 0); | ||
| 765 | INIT_LIST_HEAD(&dev->tx_idle); | ||
| 766 | INIT_DELAYED_WORK(&dev->work, acc_work); | ||
| 767 | |||
| 768 | /* _acc_dev must be set before calling usb_gadget_register_driver */ | ||
| 769 | _acc_dev = dev; | ||
| 770 | |||
| 771 | ret = misc_register(&acc_device); | ||
| 772 | if (ret) | ||
| 773 | goto err; | ||
| 774 | |||
| 775 | return 0; | ||
| 776 | |||
| 777 | err: | ||
| 778 | kfree(dev); | ||
| 779 | printk(KERN_ERR "USB accessory gadget driver failed to initialize\n"); | ||
| 780 | return ret; | ||
| 781 | } | ||
| 782 | |||
| 783 | static void acc_cleanup(void) | ||
| 784 | { | ||
| 785 | misc_deregister(&acc_device); | ||
| 786 | kfree(_acc_dev); | ||
| 787 | _acc_dev = NULL; | ||
| 788 | } | ||
diff --git a/drivers/usb/gadget/f_adb.c b/drivers/usb/gadget/f_adb.c new file mode 100644 index 00000000000..94a793f4390 --- /dev/null +++ b/drivers/usb/gadget/f_adb.c | |||
| @@ -0,0 +1,635 @@ | |||
| 1 | /* | ||
| 2 | * Gadget Driver for Android ADB | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008 Google, Inc. | ||
| 5 | * Author: Mike Lockwood <lockwood@android.com> | ||
| 6 | * | ||
| 7 | * This software is licensed under the terms of the GNU General Public | ||
| 8 | * License version 2, as published by the Free Software Foundation, and | ||
| 9 | * may be copied, distributed, and modified under those terms. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include <linux/module.h> | ||
| 19 | #include <linux/init.h> | ||
| 20 | #include <linux/poll.h> | ||
| 21 | #include <linux/delay.h> | ||
| 22 | #include <linux/wait.h> | ||
| 23 | #include <linux/err.h> | ||
| 24 | #include <linux/interrupt.h> | ||
| 25 | #include <linux/sched.h> | ||
| 26 | #include <linux/types.h> | ||
| 27 | #include <linux/device.h> | ||
| 28 | #include <linux/miscdevice.h> | ||
| 29 | |||
| 30 | #define ADB_BULK_BUFFER_SIZE 4096 | ||
| 31 | |||
| 32 | /* number of tx requests to allocate */ | ||
| 33 | #define TX_REQ_MAX 4 | ||
| 34 | |||
| 35 | static const char adb_shortname[] = "android_adb"; | ||
| 36 | |||
| 37 | struct adb_dev { | ||
| 38 | struct usb_function function; | ||
| 39 | struct usb_composite_dev *cdev; | ||
| 40 | spinlock_t lock; | ||
| 41 | |||
| 42 | struct usb_ep *ep_in; | ||
| 43 | struct usb_ep *ep_out; | ||
| 44 | |||
| 45 | int online; | ||
| 46 | int error; | ||
| 47 | |||
| 48 | atomic_t read_excl; | ||
| 49 | atomic_t write_excl; | ||
| 50 | atomic_t open_excl; | ||
| 51 | |||
| 52 | struct list_head tx_idle; | ||
| 53 | |||
| 54 | wait_queue_head_t read_wq; | ||
| 55 | wait_queue_head_t write_wq; | ||
| 56 | struct usb_request *rx_req; | ||
| 57 | int rx_done; | ||
| 58 | }; | ||
| 59 | |||
| 60 | static struct usb_interface_descriptor adb_interface_desc = { | ||
| 61 | .bLength = USB_DT_INTERFACE_SIZE, | ||
| 62 | .bDescriptorType = USB_DT_INTERFACE, | ||
| 63 | .bInterfaceNumber = 0, | ||
| 64 | .bNumEndpoints = 2, | ||
| 65 | .bInterfaceClass = 0xFF, | ||
| 66 | .bInterfaceSubClass = 0x42, | ||
| 67 | .bInterfaceProtocol = 1, | ||
| 68 | }; | ||
| 69 | |||
| 70 | static struct usb_endpoint_descriptor adb_highspeed_in_desc = { | ||
| 71 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
| 72 | .bDescriptorType = USB_DT_ENDPOINT, | ||
| 73 | .bEndpointAddress = USB_DIR_IN, | ||
| 74 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
| 75 | .wMaxPacketSize = __constant_cpu_to_le16(512), | ||
| 76 | }; | ||
| 77 | |||
| 78 | static struct usb_endpoint_descriptor adb_highspeed_out_desc = { | ||
| 79 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
| 80 | .bDescriptorType = USB_DT_ENDPOINT, | ||
| 81 | .bEndpointAddress = USB_DIR_OUT, | ||
| 82 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
| 83 | .wMaxPacketSize = __constant_cpu_to_le16(512), | ||
| 84 | }; | ||
| 85 | |||
| 86 | static struct usb_endpoint_descriptor adb_fullspeed_in_desc = { | ||
| 87 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
| 88 | .bDescriptorType = USB_DT_ENDPOINT, | ||
| 89 | .bEndpointAddress = USB_DIR_IN, | ||
| 90 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
| 91 | }; | ||
| 92 | |||
| 93 | static struct usb_endpoint_descriptor adb_fullspeed_out_desc = { | ||
| 94 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
| 95 | .bDescriptorType = USB_DT_ENDPOINT, | ||
| 96 | .bEndpointAddress = USB_DIR_OUT, | ||
| 97 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
| 98 | }; | ||
| 99 | |||
| 100 | static struct usb_descriptor_header *fs_adb_descs[] = { | ||
| 101 | (struct usb_descriptor_header *) &adb_interface_desc, | ||
| 102 | (struct usb_descriptor_header *) &adb_fullspeed_in_desc, | ||
| 103 | (struct usb_descriptor_header *) &adb_fullspeed_out_desc, | ||
| 104 | NULL, | ||
| 105 | }; | ||
| 106 | |||
| 107 | static struct usb_descriptor_header *hs_adb_descs[] = { | ||
| 108 | (struct usb_descriptor_header *) &adb_interface_desc, | ||
| 109 | (struct usb_descriptor_header *) &adb_highspeed_in_desc, | ||
| 110 | (struct usb_descriptor_header *) &adb_highspeed_out_desc, | ||
| 111 | NULL, | ||
| 112 | }; | ||
| 113 | |||
| 114 | |||
| 115 | /* temporary variable used between adb_open() and adb_gadget_bind() */ | ||
| 116 | static struct adb_dev *_adb_dev; | ||
| 117 | |||
| 118 | static inline struct adb_dev *func_to_adb(struct usb_function *f) | ||
| 119 | { | ||
| 120 | return container_of(f, struct adb_dev, function); | ||
| 121 | } | ||
| 122 | |||
| 123 | |||
| 124 | static struct usb_request *adb_request_new(struct usb_ep *ep, int buffer_size) | ||
| 125 | { | ||
| 126 | struct usb_request *req = usb_ep_alloc_request(ep, GFP_KERNEL); | ||
| 127 | if (!req) | ||
| 128 | return NULL; | ||
| 129 | |||
| 130 | /* now allocate buffers for the requests */ | ||
| 131 | req->buf = kmalloc(buffer_size, GFP_KERNEL); | ||
| 132 | if (!req->buf) { | ||
| 133 | usb_ep_free_request(ep, req); | ||
| 134 | return NULL; | ||
| 135 | } | ||
| 136 | |||
| 137 | return req; | ||
| 138 | } | ||
| 139 | |||
| 140 | static void adb_request_free(struct usb_request *req, struct usb_ep *ep) | ||
| 141 | { | ||
| 142 | if (req) { | ||
| 143 | kfree(req->buf); | ||
| 144 | usb_ep_free_request(ep, req); | ||
| 145 | } | ||
| 146 | } | ||
| 147 | |||
| 148 | static inline int adb_lock(atomic_t *excl) | ||
| 149 | { | ||
| 150 | int ret = -1; | ||
| 151 | |||
| 152 | preempt_disable(); | ||
| 153 | if (atomic_inc_return(excl) == 1) { | ||
| 154 | ret = 0; | ||
| 155 | } else | ||
| 156 | atomic_dec(excl); | ||
| 157 | |||
| 158 | preempt_enable(); | ||
| 159 | return ret; | ||
| 160 | } | ||
| 161 | |||
| 162 | static inline void adb_unlock(atomic_t *excl) | ||
| 163 | { | ||
| 164 | atomic_dec(excl); | ||
| 165 | } | ||
| 166 | |||
| 167 | /* add a request to the tail of a list */ | ||
| 168 | void adb_req_put(struct adb_dev *dev, struct list_head *head, | ||
| 169 | struct usb_request *req) | ||
| 170 | { | ||
| 171 | unsigned long flags; | ||
| 172 | |||
| 173 | spin_lock_irqsave(&dev->lock, flags); | ||
| 174 | list_add_tail(&req->list, head); | ||
| 175 | spin_unlock_irqrestore(&dev->lock, flags); | ||
| 176 | } | ||
| 177 | |||
| 178 | /* remove a request from the head of a list */ | ||
| 179 | struct usb_request *adb_req_get(struct adb_dev *dev, struct list_head *head) | ||
| 180 | { | ||
| 181 | unsigned long flags; | ||
| 182 | struct usb_request *req; | ||
| 183 | |||
| 184 | spin_lock_irqsave(&dev->lock, flags); | ||
| 185 | if (list_empty(head)) { | ||
| 186 | req = 0; | ||
| 187 | } else { | ||
| 188 | req = list_first_entry(head, struct usb_request, list); | ||
| 189 | list_del(&req->list); | ||
| 190 | } | ||
| 191 | spin_unlock_irqrestore(&dev->lock, flags); | ||
| 192 | return req; | ||
| 193 | } | ||
| 194 | |||
| 195 | static void adb_complete_in(struct usb_ep *ep, struct usb_request *req) | ||
| 196 | { | ||
| 197 | struct adb_dev *dev = _adb_dev; | ||
| 198 | |||
| 199 | if (req->status != 0) | ||
| 200 | dev->error = 1; | ||
| 201 | |||
| 202 | adb_req_put(dev, &dev->tx_idle, req); | ||
| 203 | |||
| 204 | wake_up(&dev->write_wq); | ||
| 205 | } | ||
| 206 | |||
| 207 | static void adb_complete_out(struct usb_ep *ep, struct usb_request *req) | ||
| 208 | { | ||
| 209 | struct adb_dev *dev = _adb_dev; | ||
| 210 | |||
| 211 | dev->rx_done = 1; | ||
| 212 | if (req->status != 0) | ||
| 213 | dev->error = 1; | ||
| 214 | |||
| 215 | wake_up(&dev->read_wq); | ||
| 216 | } | ||
| 217 | |||
| 218 | static int adb_create_bulk_endpoints(struct adb_dev *dev, | ||
| 219 | struct usb_endpoint_descriptor *in_desc, | ||
| 220 | struct usb_endpoint_descriptor *out_desc) | ||
| 221 | { | ||
| 222 | struct usb_composite_dev *cdev = dev->cdev; | ||
| 223 | struct usb_request *req; | ||
| 224 | struct usb_ep *ep; | ||
| 225 | int i; | ||
| 226 | |||
| 227 | DBG(cdev, "create_bulk_endpoints dev: %p\n", dev); | ||
| 228 | |||
| 229 | ep = usb_ep_autoconfig(cdev->gadget, in_desc); | ||
| 230 | if (!ep) { | ||
| 231 | DBG(cdev, "usb_ep_autoconfig for ep_in failed\n"); | ||
| 232 | return -ENODEV; | ||
| 233 | } | ||
| 234 | DBG(cdev, "usb_ep_autoconfig for ep_in got %s\n", ep->name); | ||
| 235 | ep->driver_data = dev; /* claim the endpoint */ | ||
| 236 | dev->ep_in = ep; | ||
| 237 | |||
| 238 | ep = usb_ep_autoconfig(cdev->gadget, out_desc); | ||
| 239 | if (!ep) { | ||
| 240 | DBG(cdev, "usb_ep_autoconfig for ep_out failed\n"); | ||
| 241 | return -ENODEV; | ||
| 242 | } | ||
| 243 | DBG(cdev, "usb_ep_autoconfig for adb ep_out got %s\n", ep->name); | ||
| 244 | ep->driver_data = dev; /* claim the endpoint */ | ||
| 245 | dev->ep_out = ep; | ||
| 246 | |||
| 247 | /* now allocate requests for our endpoints */ | ||
| 248 | req = adb_request_new(dev->ep_out, ADB_BULK_BUFFER_SIZE); | ||
| 249 | if (!req) | ||
| 250 | goto fail; | ||
| 251 | req->complete = adb_complete_out; | ||
| 252 | dev->rx_req = req; | ||
| 253 | |||
| 254 | for (i = 0; i < TX_REQ_MAX; i++) { | ||
| 255 | req = adb_request_new(dev->ep_in, ADB_BULK_BUFFER_SIZE); | ||
| 256 | if (!req) | ||
| 257 | goto fail; | ||
| 258 | req->complete = adb_complete_in; | ||
| 259 | adb_req_put(dev, &dev->tx_idle, req); | ||
| 260 | } | ||
| 261 | |||
| 262 | return 0; | ||
| 263 | |||
| 264 | fail: | ||
| 265 | printk(KERN_ERR "adb_bind() could not allocate requests\n"); | ||
| 266 | return -1; | ||
| 267 | } | ||
| 268 | |||
| 269 | static ssize_t adb_read(struct file *fp, char __user *buf, | ||
| 270 | size_t count, loff_t *pos) | ||
| 271 | { | ||
| 272 | struct adb_dev *dev = fp->private_data; | ||
| 273 | struct usb_request *req; | ||
| 274 | int r = count, xfer; | ||
| 275 | int ret; | ||
| 276 | |||
| 277 | pr_debug("adb_read(%d)\n", count); | ||
| 278 | if (!_adb_dev) | ||
| 279 | return -ENODEV; | ||
| 280 | |||
| 281 | if (count > ADB_BULK_BUFFER_SIZE) | ||
| 282 | return -EINVAL; | ||
| 283 | |||
| 284 | if (adb_lock(&dev->read_excl)) | ||
| 285 | return -EBUSY; | ||
| 286 | |||
| 287 | /* we will block until we're online */ | ||
| 288 | while (!(dev->online || dev->error)) { | ||
| 289 | pr_debug("adb_read: waiting for online state\n"); | ||
| 290 | ret = wait_event_interruptible(dev->read_wq, | ||
| 291 | (dev->online || dev->error)); | ||
| 292 | if (ret < 0) { | ||
| 293 | adb_unlock(&dev->read_excl); | ||
| 294 | return ret; | ||
| 295 | } | ||
| 296 | } | ||
| 297 | if (dev->error) { | ||
| 298 | r = -EIO; | ||
| 299 | goto done; | ||
| 300 | } | ||
| 301 | |||
| 302 | requeue_req: | ||
| 303 | /* queue a request */ | ||
| 304 | req = dev->rx_req; | ||
| 305 | req->length = count; | ||
| 306 | dev->rx_done = 0; | ||
| 307 | ret = usb_ep_queue(dev->ep_out, req, GFP_ATOMIC); | ||
| 308 | if (ret < 0) { | ||
| 309 | pr_debug("adb_read: failed to queue req %p (%d)\n", req, ret); | ||
| 310 | r = -EIO; | ||
| 311 | dev->error = 1; | ||
| 312 | goto done; | ||
| 313 | } else { | ||
| 314 | pr_debug("rx %p queue\n", req); | ||
| 315 | } | ||
| 316 | |||
| 317 | /* wait for a request to complete */ | ||
| 318 | ret = wait_event_interruptible(dev->read_wq, dev->rx_done); | ||
| 319 | if (ret < 0) { | ||
| 320 | dev->error = 1; | ||
| 321 | r = ret; | ||
| 322 | usb_ep_dequeue(dev->ep_out, req); | ||
| 323 | goto done; | ||
| 324 | } | ||
| 325 | if (!dev->error) { | ||
| 326 | /* If we got a 0-len packet, throw it back and try again. */ | ||
| 327 | if (req->actual == 0) | ||
| 328 | goto requeue_req; | ||
| 329 | |||
| 330 | pr_debug("rx %p %d\n", req, req->actual); | ||
| 331 | xfer = (req->actual < count) ? req->actual : count; | ||
| 332 | if (copy_to_user(buf, req->buf, xfer)) | ||
| 333 | r = -EFAULT; | ||
| 334 | |||
| 335 | } else | ||
| 336 | r = -EIO; | ||
| 337 | |||
| 338 | done: | ||
| 339 | adb_unlock(&dev->read_excl); | ||
| 340 | pr_debug("adb_read returning %d\n", r); | ||
| 341 | return r; | ||
| 342 | } | ||
| 343 | |||
| 344 | static ssize_t adb_write(struct file *fp, const char __user *buf, | ||
| 345 | size_t count, loff_t *pos) | ||
| 346 | { | ||
| 347 | struct adb_dev *dev = fp->private_data; | ||
| 348 | struct usb_request *req = 0; | ||
| 349 | int r = count, xfer; | ||
| 350 | int ret; | ||
| 351 | |||
| 352 | if (!_adb_dev) | ||
| 353 | return -ENODEV; | ||
| 354 | pr_debug("adb_write(%d)\n", count); | ||
| 355 | |||
| 356 | if (adb_lock(&dev->write_excl)) | ||
| 357 | return -EBUSY; | ||
| 358 | |||
| 359 | while (count > 0) { | ||
| 360 | if (dev->error) { | ||
| 361 | pr_debug("adb_write dev->error\n"); | ||
| 362 | r = -EIO; | ||
| 363 | break; | ||
| 364 | } | ||
| 365 | |||
| 366 | /* get an idle tx request to use */ | ||
| 367 | req = 0; | ||
| 368 | ret = wait_event_interruptible(dev->write_wq, | ||
| 369 | (req = adb_req_get(dev, &dev->tx_idle)) || dev->error); | ||
| 370 | |||
| 371 | if (ret < 0) { | ||
| 372 | r = ret; | ||
| 373 | break; | ||
| 374 | } | ||
| 375 | |||
| 376 | if (req != 0) { | ||
| 377 | if (count > ADB_BULK_BUFFER_SIZE) | ||
| 378 | xfer = ADB_BULK_BUFFER_SIZE; | ||
| 379 | else | ||
| 380 | xfer = count; | ||
| 381 | if (copy_from_user(req->buf, buf, xfer)) { | ||
| 382 | r = -EFAULT; | ||
| 383 | break; | ||
| 384 | } | ||
| 385 | |||
| 386 | req->length = xfer; | ||
| 387 | ret = usb_ep_queue(dev->ep_in, req, GFP_ATOMIC); | ||
| 388 | if (ret < 0) { | ||
| 389 | pr_debug("adb_write: xfer error %d\n", ret); | ||
| 390 | dev->error = 1; | ||
| 391 | r = -EIO; | ||
| 392 | break; | ||
| 393 | } | ||
| 394 | |||
| 395 | buf += xfer; | ||
| 396 | count -= xfer; | ||
| 397 | |||
| 398 | /* zero this so we don't try to free it on error exit */ | ||
| 399 | req = 0; | ||
| 400 | } | ||
| 401 | } | ||
| 402 | |||
| 403 | if (req) | ||
| 404 | adb_req_put(dev, &dev->tx_idle, req); | ||
| 405 | |||
| 406 | adb_unlock(&dev->write_excl); | ||
| 407 | pr_debug("adb_write returning %d\n", r); | ||
| 408 | return r; | ||
| 409 | } | ||
| 410 | |||
| 411 | static int adb_open(struct inode *ip, struct file *fp) | ||
| 412 | { | ||
| 413 | static unsigned long last_print; | ||
| 414 | static unsigned long count = 0; | ||
| 415 | |||
| 416 | if (!_adb_dev) | ||
| 417 | return -ENODEV; | ||
| 418 | |||
| 419 | if (++count == 1) | ||
| 420 | last_print = jiffies; | ||
| 421 | else { | ||
| 422 | if (!time_before(jiffies, last_print + HZ/2)) | ||
| 423 | count = 0; | ||
| 424 | last_print = jiffies; | ||
| 425 | } | ||
| 426 | |||
| 427 | if (adb_lock(&_adb_dev->open_excl)) { | ||
| 428 | cpu_relax(); | ||
| 429 | return -EBUSY; | ||
| 430 | } | ||
| 431 | |||
| 432 | if (count < 5) | ||
| 433 | printk(KERN_INFO "adb_open(%s)\n", current->comm); | ||
| 434 | |||
| 435 | |||
| 436 | fp->private_data = _adb_dev; | ||
| 437 | |||
| 438 | /* clear the error latch */ | ||
| 439 | _adb_dev->error = 0; | ||
| 440 | |||
| 441 | return 0; | ||
| 442 | } | ||
| 443 | |||
| 444 | static int adb_release(struct inode *ip, struct file *fp) | ||
| 445 | { | ||
| 446 | static unsigned long last_print; | ||
| 447 | static unsigned long count = 0; | ||
| 448 | |||
| 449 | if (++count == 1) | ||
| 450 | last_print = jiffies; | ||
| 451 | else { | ||
| 452 | if (!time_before(jiffies, last_print + HZ/2)) | ||
| 453 | count = 0; | ||
| 454 | last_print = jiffies; | ||
| 455 | } | ||
| 456 | |||
| 457 | if (count < 5) | ||
| 458 | printk(KERN_INFO "adb_release\n"); | ||
| 459 | adb_unlock(&_adb_dev->open_excl); | ||
| 460 | return 0; | ||
| 461 | } | ||
| 462 | |||
| 463 | /* file operations for ADB device /dev/android_adb */ | ||
| 464 | static struct file_operations adb_fops = { | ||
| 465 | .owner = THIS_MODULE, | ||
| 466 | .read = adb_read, | ||
| 467 | .write = adb_write, | ||
| 468 | .open = adb_open, | ||
| 469 | .release = adb_release, | ||
| 470 | }; | ||
| 471 | |||
| 472 | static struct miscdevice adb_device = { | ||
| 473 | .minor = MISC_DYNAMIC_MINOR, | ||
| 474 | .name = adb_shortname, | ||
| 475 | .fops = &adb_fops, | ||
| 476 | }; | ||
| 477 | |||
| 478 | |||
| 479 | |||
| 480 | |||
| 481 | static int | ||
| 482 | adb_function_bind(struct usb_configuration *c, struct usb_function *f) | ||
| 483 | { | ||
| 484 | struct usb_composite_dev *cdev = c->cdev; | ||
| 485 | struct adb_dev *dev = func_to_adb(f); | ||
| 486 | int id; | ||
| 487 | int ret; | ||
| 488 | |||
| 489 | dev->cdev = cdev; | ||
| 490 | DBG(cdev, "adb_function_bind dev: %p\n", dev); | ||
| 491 | |||
| 492 | /* allocate interface ID(s) */ | ||
| 493 | id = usb_interface_id(c, f); | ||
| 494 | if (id < 0) | ||
| 495 | return id; | ||
| 496 | adb_interface_desc.bInterfaceNumber = id; | ||
| 497 | |||
| 498 | /* allocate endpoints */ | ||
| 499 | ret = adb_create_bulk_endpoints(dev, &adb_fullspeed_in_desc, | ||
| 500 | &adb_fullspeed_out_desc); | ||
| 501 | if (ret) | ||
| 502 | return ret; | ||
| 503 | |||
| 504 | /* support high speed hardware */ | ||
| 505 | if (gadget_is_dualspeed(c->cdev->gadget)) { | ||
| 506 | adb_highspeed_in_desc.bEndpointAddress = | ||
| 507 | adb_fullspeed_in_desc.bEndpointAddress; | ||
| 508 | adb_highspeed_out_desc.bEndpointAddress = | ||
| 509 | adb_fullspeed_out_desc.bEndpointAddress; | ||
| 510 | } | ||
| 511 | |||
| 512 | DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n", | ||
| 513 | gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", | ||
| 514 | f->name, dev->ep_in->name, dev->ep_out->name); | ||
| 515 | return 0; | ||
| 516 | } | ||
| 517 | |||
| 518 | static void | ||
| 519 | adb_function_unbind(struct usb_configuration *c, struct usb_function *f) | ||
| 520 | { | ||
| 521 | struct adb_dev *dev = func_to_adb(f); | ||
| 522 | struct usb_request *req; | ||
| 523 | |||
| 524 | |||
| 525 | dev->online = 0; | ||
| 526 | dev->error = 1; | ||
| 527 | |||
| 528 | wake_up(&dev->read_wq); | ||
| 529 | |||
| 530 | adb_request_free(dev->rx_req, dev->ep_out); | ||
| 531 | while ((req = adb_req_get(dev, &dev->tx_idle))) | ||
| 532 | adb_request_free(req, dev->ep_in); | ||
| 533 | } | ||
| 534 | |||
| 535 | static int adb_function_set_alt(struct usb_function *f, | ||
| 536 | unsigned intf, unsigned alt) | ||
| 537 | { | ||
| 538 | struct adb_dev *dev = func_to_adb(f); | ||
| 539 | struct usb_composite_dev *cdev = f->config->cdev; | ||
| 540 | int ret; | ||
| 541 | |||
| 542 | DBG(cdev, "adb_function_set_alt intf: %d alt: %d\n", intf, alt); | ||
| 543 | config_ep_by_speed(cdev->gadget, f, dev->ep_in); | ||
| 544 | ret = usb_ep_enable(dev->ep_in); | ||
| 545 | if (ret) | ||
| 546 | return ret; | ||
| 547 | config_ep_by_speed(cdev->gadget, f, dev->ep_out); | ||
| 548 | ret = usb_ep_enable(dev->ep_out); | ||
| 549 | if (ret) { | ||
| 550 | usb_ep_disable(dev->ep_in); | ||
| 551 | return ret; | ||
| 552 | } | ||
| 553 | dev->online = 1; | ||
| 554 | |||
| 555 | /* readers may be blocked waiting for us to go online */ | ||
| 556 | wake_up(&dev->read_wq); | ||
| 557 | return 0; | ||
| 558 | } | ||
| 559 | |||
| 560 | static void adb_function_disable(struct usb_function *f) | ||
| 561 | { | ||
| 562 | struct adb_dev *dev = func_to_adb(f); | ||
| 563 | struct usb_composite_dev *cdev = dev->cdev; | ||
| 564 | |||
| 565 | DBG(cdev, "adb_function_disable cdev %p\n", cdev); | ||
| 566 | dev->online = 0; | ||
| 567 | dev->error = 1; | ||
| 568 | usb_ep_disable(dev->ep_in); | ||
| 569 | usb_ep_disable(dev->ep_out); | ||
| 570 | |||
| 571 | /* readers may be blocked waiting for us to go online */ | ||
| 572 | wake_up(&dev->read_wq); | ||
| 573 | |||
| 574 | VDBG(cdev, "%s disabled\n", dev->function.name); | ||
| 575 | } | ||
| 576 | |||
| 577 | static int adb_bind_config(struct usb_configuration *c) | ||
| 578 | { | ||
| 579 | struct adb_dev *dev = _adb_dev; | ||
| 580 | |||
| 581 | printk(KERN_INFO "adb_bind_config\n"); | ||
| 582 | |||
| 583 | dev->cdev = c->cdev; | ||
| 584 | dev->function.name = "adb"; | ||
| 585 | dev->function.descriptors = fs_adb_descs; | ||
| 586 | dev->function.hs_descriptors = hs_adb_descs; | ||
| 587 | dev->function.bind = adb_function_bind; | ||
| 588 | dev->function.unbind = adb_function_unbind; | ||
| 589 | dev->function.set_alt = adb_function_set_alt; | ||
| 590 | dev->function.disable = adb_function_disable; | ||
| 591 | |||
| 592 | return usb_add_function(c, &dev->function); | ||
| 593 | } | ||
| 594 | |||
| 595 | static int adb_setup(void) | ||
| 596 | { | ||
| 597 | struct adb_dev *dev; | ||
| 598 | int ret; | ||
| 599 | |||
| 600 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||
| 601 | if (!dev) | ||
| 602 | return -ENOMEM; | ||
| 603 | |||
| 604 | spin_lock_init(&dev->lock); | ||
| 605 | |||
| 606 | init_waitqueue_head(&dev->read_wq); | ||
| 607 | init_waitqueue_head(&dev->write_wq); | ||
| 608 | |||
| 609 | atomic_set(&dev->open_excl, 0); | ||
| 610 | atomic_set(&dev->read_excl, 0); | ||
| 611 | atomic_set(&dev->write_excl, 0); | ||
| 612 | |||
| 613 | INIT_LIST_HEAD(&dev->tx_idle); | ||
| 614 | |||
| 615 | _adb_dev = dev; | ||
| 616 | |||
| 617 | ret = misc_register(&adb_device); | ||
| 618 | if (ret) | ||
| 619 | goto err; | ||
| 620 | |||
| 621 | return 0; | ||
| 622 | |||
| 623 | err: | ||
| 624 | kfree(dev); | ||
| 625 | printk(KERN_ERR "adb gadget driver failed to initialize\n"); | ||
| 626 | return ret; | ||
| 627 | } | ||
| 628 | |||
| 629 | static void adb_cleanup(void) | ||
| 630 | { | ||
| 631 | misc_deregister(&adb_device); | ||
| 632 | |||
| 633 | kfree(_adb_dev); | ||
| 634 | _adb_dev = NULL; | ||
| 635 | } | ||
diff --git a/drivers/usb/gadget/f_audio.c b/drivers/usb/gadget/f_audio.c new file mode 100644 index 00000000000..a9a4eade7e8 --- /dev/null +++ b/drivers/usb/gadget/f_audio.c | |||
| @@ -0,0 +1,798 @@ | |||
| 1 | /* | ||
| 2 | * f_audio.c -- USB Audio class function driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008 Bryan Wu <cooloney@kernel.org> | ||
| 5 | * Copyright (C) 2008 Analog Devices, Inc | ||
| 6 | * | ||
| 7 | * Enter bugs at http://blackfin.uclinux.org/ | ||
| 8 | * | ||
| 9 | * Licensed under the GPL-2 or later. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/slab.h> | ||
| 13 | #include <linux/kernel.h> | ||
| 14 | #include <linux/device.h> | ||
| 15 | #include <linux/atomic.h> | ||
| 16 | |||
| 17 | #include "u_audio.h" | ||
| 18 | |||
| 19 | #define OUT_EP_MAX_PACKET_SIZE 200 | ||
| 20 | static int req_buf_size = OUT_EP_MAX_PACKET_SIZE; | ||
| 21 | module_param(req_buf_size, int, S_IRUGO); | ||
| 22 | MODULE_PARM_DESC(req_buf_size, "ISO OUT endpoint request buffer size"); | ||
| 23 | |||
| 24 | static int req_count = 256; | ||
| 25 | module_param(req_count, int, S_IRUGO); | ||
| 26 | MODULE_PARM_DESC(req_count, "ISO OUT endpoint request count"); | ||
| 27 | |||
| 28 | static int audio_buf_size = 48000; | ||
| 29 | module_param(audio_buf_size, int, S_IRUGO); | ||
| 30 | MODULE_PARM_DESC(audio_buf_size, "Audio buffer size"); | ||
| 31 | |||
| 32 | static int generic_set_cmd(struct usb_audio_control *con, u8 cmd, int value); | ||
| 33 | static int generic_get_cmd(struct usb_audio_control *con, u8 cmd); | ||
| 34 | |||
| 35 | /* | ||
| 36 | * DESCRIPTORS ... most are static, but strings and full | ||
| 37 | * configuration descriptors are built on demand. | ||
| 38 | */ | ||
| 39 | |||
| 40 | /* | ||
| 41 | * We have two interfaces- AudioControl and AudioStreaming | ||
| 42 | * TODO: only supcard playback currently | ||
| 43 | */ | ||
| 44 | #define F_AUDIO_AC_INTERFACE 0 | ||
| 45 | #define F_AUDIO_AS_INTERFACE 1 | ||
| 46 | #define F_AUDIO_NUM_INTERFACES 2 | ||
| 47 | |||
| 48 | /* B.3.1 Standard AC Interface Descriptor */ | ||
| 49 | static struct usb_interface_descriptor ac_interface_desc __initdata = { | ||
| 50 | .bLength = USB_DT_INTERFACE_SIZE, | ||
| 51 | .bDescriptorType = USB_DT_INTERFACE, | ||
| 52 | .bNumEndpoints = 0, | ||
| 53 | .bInterfaceClass = USB_CLASS_AUDIO, | ||
| 54 | .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, | ||
| 55 | }; | ||
| 56 | |||
| 57 | DECLARE_UAC_AC_HEADER_DESCRIPTOR(2); | ||
| 58 | |||
| 59 | #define UAC_DT_AC_HEADER_LENGTH UAC_DT_AC_HEADER_SIZE(F_AUDIO_NUM_INTERFACES) | ||
| 60 | /* 1 input terminal, 1 output terminal and 1 feature unit */ | ||
| 61 | #define UAC_DT_TOTAL_LENGTH (UAC_DT_AC_HEADER_LENGTH + UAC_DT_INPUT_TERMINAL_SIZE \ | ||
| 62 | + UAC_DT_OUTPUT_TERMINAL_SIZE + UAC_DT_FEATURE_UNIT_SIZE(0)) | ||
| 63 | /* B.3.2 Class-Specific AC Interface Descriptor */ | ||
| 64 | static struct uac1_ac_header_descriptor_2 ac_header_desc = { | ||
| 65 | .bLength = UAC_DT_AC_HEADER_LENGTH, | ||
| 66 | .bDescriptorType = USB_DT_CS_INTERFACE, | ||
| 67 | .bDescriptorSubtype = UAC_HEADER, | ||
| 68 | .bcdADC = __constant_cpu_to_le16(0x0100), | ||
| 69 | .wTotalLength = __constant_cpu_to_le16(UAC_DT_TOTAL_LENGTH), | ||
| 70 | .bInCollection = F_AUDIO_NUM_INTERFACES, | ||
| 71 | .baInterfaceNr = { | ||
| 72 | [0] = F_AUDIO_AC_INTERFACE, | ||
| 73 | [1] = F_AUDIO_AS_INTERFACE, | ||
| 74 | } | ||
| 75 | }; | ||
| 76 | |||
| 77 | #define INPUT_TERMINAL_ID 1 | ||
| 78 | static struct uac_input_terminal_descriptor input_terminal_desc = { | ||
| 79 | .bLength = UAC_DT_INPUT_TERMINAL_SIZE, | ||
| 80 | .bDescriptorType = USB_DT_CS_INTERFACE, | ||
| 81 | .bDescriptorSubtype = UAC_INPUT_TERMINAL, | ||
| 82 | .bTerminalID = INPUT_TERMINAL_ID, | ||
| 83 | .wTerminalType = UAC_TERMINAL_STREAMING, | ||
| 84 | .bAssocTerminal = 0, | ||
| 85 | .wChannelConfig = 0x3, | ||
| 86 | }; | ||
| 87 | |||
| 88 | DECLARE_UAC_FEATURE_UNIT_DESCRIPTOR(0); | ||
| 89 | |||
| 90 | #define FEATURE_UNIT_ID 2 | ||
| 91 | static struct uac_feature_unit_descriptor_0 feature_unit_desc = { | ||
| 92 | .bLength = UAC_DT_FEATURE_UNIT_SIZE(0), | ||
| 93 | .bDescriptorType = USB_DT_CS_INTERFACE, | ||
| 94 | .bDescriptorSubtype = UAC_FEATURE_UNIT, | ||
| 95 | .bUnitID = FEATURE_UNIT_ID, | ||
| 96 | .bSourceID = INPUT_TERMINAL_ID, | ||
| 97 | .bControlSize = 2, | ||
| 98 | .bmaControls[0] = (UAC_FU_MUTE | UAC_FU_VOLUME), | ||
| 99 | }; | ||
| 100 | |||
| 101 | static struct usb_audio_control mute_control = { | ||
| 102 | .list = LIST_HEAD_INIT(mute_control.list), | ||
| 103 | .name = "Mute Control", | ||
| 104 | .type = UAC_FU_MUTE, | ||
| 105 | /* Todo: add real Mute control code */ | ||
| 106 | .set = generic_set_cmd, | ||
| 107 | .get = generic_get_cmd, | ||
| 108 | }; | ||
| 109 | |||
| 110 | static struct usb_audio_control volume_control = { | ||
| 111 | .list = LIST_HEAD_INIT(volume_control.list), | ||
| 112 | .name = "Volume Control", | ||
| 113 | .type = UAC_FU_VOLUME, | ||
| 114 | /* Todo: add real Volume control code */ | ||
| 115 | .set = generic_set_cmd, | ||
| 116 | .get = generic_get_cmd, | ||
| 117 | }; | ||
| 118 | |||
| 119 | static struct usb_audio_control_selector feature_unit = { | ||
| 120 | .list = LIST_HEAD_INIT(feature_unit.list), | ||
| 121 | .id = FEATURE_UNIT_ID, | ||
| 122 | .name = "Mute & Volume Control", | ||
| 123 | .type = UAC_FEATURE_UNIT, | ||
| 124 | .desc = (struct usb_descriptor_header *)&feature_unit_desc, | ||
| 125 | }; | ||
| 126 | |||
| 127 | #define OUTPUT_TERMINAL_ID 3 | ||
| 128 | static struct uac1_output_terminal_descriptor output_terminal_desc = { | ||
| 129 | .bLength = UAC_DT_OUTPUT_TERMINAL_SIZE, | ||
| 130 | .bDescriptorType = USB_DT_CS_INTERFACE, | ||
| 131 | .bDescriptorSubtype = UAC_OUTPUT_TERMINAL, | ||
| 132 | .bTerminalID = OUTPUT_TERMINAL_ID, | ||
| 133 | .wTerminalType = UAC_OUTPUT_TERMINAL_SPEAKER, | ||
| 134 | .bAssocTerminal = FEATURE_UNIT_ID, | ||
| 135 | .bSourceID = FEATURE_UNIT_ID, | ||
| 136 | }; | ||
| 137 | |||
| 138 | /* B.4.1 Standard AS Interface Descriptor */ | ||
| 139 | static struct usb_interface_descriptor as_interface_alt_0_desc = { | ||
| 140 | .bLength = USB_DT_INTERFACE_SIZE, | ||
| 141 | .bDescriptorType = USB_DT_INTERFACE, | ||
| 142 | .bAlternateSetting = 0, | ||
| 143 | .bNumEndpoints = 0, | ||
| 144 | .bInterfaceClass = USB_CLASS_AUDIO, | ||
| 145 | .bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING, | ||
| 146 | }; | ||
| 147 | |||
| 148 | static struct usb_interface_descriptor as_interface_alt_1_desc = { | ||
| 149 | .bLength = USB_DT_INTERFACE_SIZE, | ||
| 150 | .bDescriptorType = USB_DT_INTERFACE, | ||
| 151 | .bAlternateSetting = 1, | ||
| 152 | .bNumEndpoints = 1, | ||
| 153 | .bInterfaceClass = USB_CLASS_AUDIO, | ||
| 154 | .bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING, | ||
| 155 | }; | ||
| 156 | |||
| 157 | /* B.4.2 Class-Specific AS Interface Descriptor */ | ||
| 158 | static struct uac1_as_header_descriptor as_header_desc = { | ||
| 159 | .bLength = UAC_DT_AS_HEADER_SIZE, | ||
| 160 | .bDescriptorType = USB_DT_CS_INTERFACE, | ||
| 161 | .bDescriptorSubtype = UAC_AS_GENERAL, | ||
| 162 | .bTerminalLink = INPUT_TERMINAL_ID, | ||
| 163 | .bDelay = 1, | ||
| 164 | .wFormatTag = UAC_FORMAT_TYPE_I_PCM, | ||
| 165 | }; | ||
| 166 | |||
| 167 | DECLARE_UAC_FORMAT_TYPE_I_DISCRETE_DESC(1); | ||
| 168 | |||
| 169 | static struct uac_format_type_i_discrete_descriptor_1 as_type_i_desc = { | ||
| 170 | .bLength = UAC_FORMAT_TYPE_I_DISCRETE_DESC_SIZE(1), | ||
| 171 | .bDescriptorType = USB_DT_CS_INTERFACE, | ||
| 172 | .bDescriptorSubtype = UAC_FORMAT_TYPE, | ||
| 173 | .bFormatType = UAC_FORMAT_TYPE_I, | ||
| 174 | .bSubframeSize = 2, | ||
| 175 | .bBitResolution = 16, | ||
| 176 | .bSamFreqType = 1, | ||
| 177 | }; | ||
| 178 | |||
| 179 | /* Standard ISO OUT Endpoint Descriptor */ | ||
| 180 | static struct usb_endpoint_descriptor as_out_ep_desc = { | ||
| 181 | .bLength = USB_DT_ENDPOINT_AUDIO_SIZE, | ||
| 182 | .bDescriptorType = USB_DT_ENDPOINT, | ||
| 183 | .bEndpointAddress = USB_DIR_OUT, | ||
| 184 | .bmAttributes = USB_ENDPOINT_SYNC_ADAPTIVE | ||
| 185 | | USB_ENDPOINT_XFER_ISOC, | ||
| 186 | .wMaxPacketSize = __constant_cpu_to_le16(OUT_EP_MAX_PACKET_SIZE), | ||
| 187 | .bInterval = 4, | ||
| 188 | }; | ||
| 189 | |||
| 190 | /* Class-specific AS ISO OUT Endpoint Descriptor */ | ||
| 191 | static struct uac_iso_endpoint_descriptor as_iso_out_desc __initdata = { | ||
| 192 | .bLength = UAC_ISO_ENDPOINT_DESC_SIZE, | ||
| 193 | .bDescriptorType = USB_DT_CS_ENDPOINT, | ||
| 194 | .bDescriptorSubtype = UAC_EP_GENERAL, | ||
| 195 | .bmAttributes = 1, | ||
| 196 | .bLockDelayUnits = 1, | ||
| 197 | .wLockDelay = __constant_cpu_to_le16(1), | ||
| 198 | }; | ||
| 199 | |||
| 200 | static struct usb_descriptor_header *f_audio_desc[] __initdata = { | ||
| 201 | (struct usb_descriptor_header *)&ac_interface_desc, | ||
| 202 | (struct usb_descriptor_header *)&ac_header_desc, | ||
| 203 | |||
| 204 | (struct usb_descriptor_header *)&input_terminal_desc, | ||
| 205 | (struct usb_descriptor_header *)&output_terminal_desc, | ||
| 206 | (struct usb_descriptor_header *)&feature_unit_desc, | ||
| 207 | |||
| 208 | (struct usb_descriptor_header *)&as_interface_alt_0_desc, | ||
| 209 | (struct usb_descriptor_header *)&as_interface_alt_1_desc, | ||
| 210 | (struct usb_descriptor_header *)&as_header_desc, | ||
| 211 | |||
| 212 | (struct usb_descriptor_header *)&as_type_i_desc, | ||
| 213 | |||
| 214 | (struct usb_descriptor_header *)&as_out_ep_desc, | ||
| 215 | (struct usb_descriptor_header *)&as_iso_out_desc, | ||
| 216 | NULL, | ||
| 217 | }; | ||
| 218 | |||
| 219 | /* string IDs are assigned dynamically */ | ||
| 220 | |||
| 221 | #define STRING_MANUFACTURER_IDX 0 | ||
| 222 | #define STRING_PRODUCT_IDX 1 | ||
| 223 | |||
| 224 | static char manufacturer[50]; | ||
| 225 | |||
| 226 | static struct usb_string strings_dev[] = { | ||
| 227 | [STRING_MANUFACTURER_IDX].s = manufacturer, | ||
| 228 | [STRING_PRODUCT_IDX].s = DRIVER_DESC, | ||
| 229 | { } /* end of list */ | ||
| 230 | }; | ||
| 231 | |||
| 232 | static struct usb_gadget_strings stringtab_dev = { | ||
| 233 | .language = 0x0409, /* en-us */ | ||
| 234 | .strings = strings_dev, | ||
| 235 | }; | ||
| 236 | |||
| 237 | static struct usb_gadget_strings *audio_strings[] = { | ||
| 238 | &stringtab_dev, | ||
| 239 | NULL, | ||
| 240 | }; | ||
| 241 | |||
| 242 | /* | ||
| 243 | * This function is an ALSA sound card following USB Audio Class Spec 1.0. | ||
| 244 | */ | ||
| 245 | |||
| 246 | /*-------------------------------------------------------------------------*/ | ||
| 247 | struct f_audio_buf { | ||
| 248 | u8 *buf; | ||
| 249 | int actual; | ||
| 250 | struct list_head list; | ||
| 251 | }; | ||
| 252 | |||
| 253 | static struct f_audio_buf *f_audio_buffer_alloc(int buf_size) | ||
| 254 | { | ||
| 255 | struct f_audio_buf *copy_buf; | ||
| 256 | |||
| 257 | copy_buf = kzalloc(sizeof *copy_buf, GFP_ATOMIC); | ||
| 258 | if (!copy_buf) | ||
| 259 | return ERR_PTR(-ENOMEM); | ||
| 260 | |||
| 261 | copy_buf->buf = kzalloc(buf_size, GFP_ATOMIC); | ||
| 262 | if (!copy_buf->buf) { | ||
| 263 | kfree(copy_buf); | ||
| 264 | return ERR_PTR(-ENOMEM); | ||
| 265 | } | ||
| 266 | |||
| 267 | return copy_buf; | ||
| 268 | } | ||
| 269 | |||
| 270 | static void f_audio_buffer_free(struct f_audio_buf *audio_buf) | ||
| 271 | { | ||
| 272 | kfree(audio_buf->buf); | ||
| 273 | kfree(audio_buf); | ||
| 274 | } | ||
| 275 | /*-------------------------------------------------------------------------*/ | ||
| 276 | |||
| 277 | struct f_audio { | ||
| 278 | struct gaudio card; | ||
| 279 | |||
| 280 | /* endpoints handle full and/or high speeds */ | ||
| 281 | struct usb_ep *out_ep; | ||
| 282 | |||
| 283 | spinlock_t lock; | ||
| 284 | struct f_audio_buf *copy_buf; | ||
| 285 | struct work_struct playback_work; | ||
| 286 | struct list_head play_queue; | ||
| 287 | |||
| 288 | /* Control Set command */ | ||
| 289 | struct list_head cs; | ||
| 290 | u8 set_cmd; | ||
| 291 | struct usb_audio_control *set_con; | ||
| 292 | }; | ||
| 293 | |||
| 294 | static inline struct f_audio *func_to_audio(struct usb_function *f) | ||
| 295 | { | ||
| 296 | return container_of(f, struct f_audio, card.func); | ||
| 297 | } | ||
| 298 | |||
| 299 | /*-------------------------------------------------------------------------*/ | ||
| 300 | |||
| 301 | static void f_audio_playback_work(struct work_struct *data) | ||
| 302 | { | ||
| 303 | struct f_audio *audio = container_of(data, struct f_audio, | ||
| 304 | playback_work); | ||
| 305 | struct f_audio_buf *play_buf; | ||
| 306 | |||
| 307 | spin_lock_irq(&audio->lock); | ||
| 308 | if (list_empty(&audio->play_queue)) { | ||
| 309 | spin_unlock_irq(&audio->lock); | ||
| 310 | return; | ||
| 311 | } | ||
| 312 | play_buf = list_first_entry(&audio->play_queue, | ||
| 313 | struct f_audio_buf, list); | ||
| 314 | list_del(&play_buf->list); | ||
| 315 | spin_unlock_irq(&audio->lock); | ||
| 316 | |||
| 317 | u_audio_playback(&audio->card, play_buf->buf, play_buf->actual); | ||
| 318 | f_audio_buffer_free(play_buf); | ||
| 319 | } | ||
| 320 | |||
| 321 | static int f_audio_out_ep_complete(struct usb_ep *ep, struct usb_request *req) | ||
| 322 | { | ||
| 323 | struct f_audio *audio = req->context; | ||
| 324 | struct usb_composite_dev *cdev = audio->card.func.config->cdev; | ||
| 325 | struct f_audio_buf *copy_buf = audio->copy_buf; | ||
| 326 | int err; | ||
| 327 | |||
| 328 | if (!copy_buf) | ||
| 329 | return -EINVAL; | ||
| 330 | |||
| 331 | /* Copy buffer is full, add it to the play_queue */ | ||
| 332 | if (audio_buf_size - copy_buf->actual < req->actual) { | ||
| 333 | list_add_tail(©_buf->list, &audio->play_queue); | ||
| 334 | schedule_work(&audio->playback_work); | ||
| 335 | copy_buf = f_audio_buffer_alloc(audio_buf_size); | ||
| 336 | if (IS_ERR(copy_buf)) | ||
| 337 | return -ENOMEM; | ||
| 338 | } | ||
| 339 | |||
| 340 | memcpy(copy_buf->buf + copy_buf->actual, req->buf, req->actual); | ||
| 341 | copy_buf->actual += req->actual; | ||
| 342 | audio->copy_buf = copy_buf; | ||
| 343 | |||
| 344 | err = usb_ep_queue(ep, req, GFP_ATOMIC); | ||
| 345 | if (err) | ||
| 346 | ERROR(cdev, "%s queue req: %d\n", ep->name, err); | ||
| 347 | |||
| 348 | return 0; | ||
| 349 | |||
| 350 | } | ||
| 351 | |||
| 352 | static void f_audio_complete(struct usb_ep *ep, struct usb_request *req) | ||
| 353 | { | ||
| 354 | struct f_audio *audio = req->context; | ||
| 355 | int status = req->status; | ||
| 356 | u32 data = 0; | ||
| 357 | struct usb_ep *out_ep = audio->out_ep; | ||
| 358 | |||
| 359 | switch (status) { | ||
| 360 | |||
| 361 | case 0: /* normal completion? */ | ||
| 362 | if (ep == out_ep) | ||
| 363 | f_audio_out_ep_complete(ep, req); | ||
| 364 | else if (audio->set_con) { | ||
| 365 | memcpy(&data, req->buf, req->length); | ||
| 366 | audio->set_con->set(audio->set_con, audio->set_cmd, | ||
| 367 | le16_to_cpu(data)); | ||
| 368 | audio->set_con = NULL; | ||
| 369 | } | ||
| 370 | break; | ||
| 371 | default: | ||
| 372 | break; | ||
| 373 | } | ||
| 374 | } | ||
| 375 | |||
| 376 | static int audio_set_intf_req(struct usb_function *f, | ||
| 377 | const struct usb_ctrlrequest *ctrl) | ||
| 378 | { | ||
| 379 | struct f_audio *audio = func_to_audio(f); | ||
| 380 | struct usb_composite_dev *cdev = f->config->cdev; | ||
| 381 | struct usb_request *req = cdev->req; | ||
| 382 | u8 id = ((le16_to_cpu(ctrl->wIndex) >> 8) & 0xFF); | ||
| 383 | u16 len = le16_to_cpu(ctrl->wLength); | ||
| 384 | u16 w_value = le16_to_cpu(ctrl->wValue); | ||
| 385 | u8 con_sel = (w_value >> 8) & 0xFF; | ||
| 386 | u8 cmd = (ctrl->bRequest & 0x0F); | ||
| 387 | struct usb_audio_control_selector *cs; | ||
| 388 | struct usb_audio_control *con; | ||
| 389 | |||
| 390 | DBG(cdev, "bRequest 0x%x, w_value 0x%04x, len %d, entity %d\n", | ||
| 391 | ctrl->bRequest, w_value, len, id); | ||
| 392 | |||
| 393 | list_for_each_entry(cs, &audio->cs, list) { | ||
| 394 | if (cs->id == id) { | ||
| 395 | list_for_each_entry(con, &cs->control, list) { | ||
| 396 | if (con->type == con_sel) { | ||
| 397 | audio->set_con = con; | ||
| 398 | break; | ||
| 399 | } | ||
| 400 | } | ||
| 401 | break; | ||
| 402 | } | ||
| 403 | } | ||
| 404 | |||
| 405 | audio->set_cmd = cmd; | ||
| 406 | req->context = audio; | ||
| 407 | req->complete = f_audio_complete; | ||
| 408 | |||
| 409 | return len; | ||
| 410 | } | ||
| 411 | |||
| 412 | static int audio_get_intf_req(struct usb_function *f, | ||
| 413 | const struct usb_ctrlrequest *ctrl) | ||
| 414 | { | ||
| 415 | struct f_audio *audio = func_to_audio(f); | ||
| 416 | struct usb_composite_dev *cdev = f->config->cdev; | ||
| 417 | struct usb_request *req = cdev->req; | ||
| 418 | int value = -EOPNOTSUPP; | ||
| 419 | u8 id = ((le16_to_cpu(ctrl->wIndex) >> 8) & 0xFF); | ||
| 420 | u16 len = le16_to_cpu(ctrl->wLength); | ||
| 421 | u16 w_value = le16_to_cpu(ctrl->wValue); | ||
| 422 | u8 con_sel = (w_value >> 8) & 0xFF; | ||
| 423 | u8 cmd = (ctrl->bRequest & 0x0F); | ||
| 424 | struct usb_audio_control_selector *cs; | ||
| 425 | struct usb_audio_control *con; | ||
| 426 | |||
| 427 | DBG(cdev, "bRequest 0x%x, w_value 0x%04x, len %d, entity %d\n", | ||
| 428 | ctrl->bRequest, w_value, len, id); | ||
| 429 | |||
| 430 | list_for_each_entry(cs, &audio->cs, list) { | ||
| 431 | if (cs->id == id) { | ||
| 432 | list_for_each_entry(con, &cs->control, list) { | ||
| 433 | if (con->type == con_sel && con->get) { | ||
| 434 | value = con->get(con, cmd); | ||
| 435 | break; | ||
| 436 | } | ||
| 437 | } | ||
| 438 | break; | ||
| 439 | } | ||
| 440 | } | ||
| 441 | |||
| 442 | req->context = audio; | ||
| 443 | req->complete = f_audio_complete; | ||
| 444 | memcpy(req->buf, &value, len); | ||
| 445 | |||
| 446 | return len; | ||
| 447 | } | ||
| 448 | |||
| 449 | static int audio_set_endpoint_req(struct usb_function *f, | ||
| 450 | const struct usb_ctrlrequest *ctrl) | ||
| 451 | { | ||
| 452 | struct usb_composite_dev *cdev = f->config->cdev; | ||
| 453 | int value = -EOPNOTSUPP; | ||
| 454 | u16 ep = le16_to_cpu(ctrl->wIndex); | ||
| 455 | u16 len = le16_to_cpu(ctrl->wLength); | ||
| 456 | u16 w_value = le16_to_cpu(ctrl->wValue); | ||
| 457 | |||
| 458 | DBG(cdev, "bRequest 0x%x, w_value 0x%04x, len %d, endpoint %d\n", | ||
| 459 | ctrl->bRequest, w_value, len, ep); | ||
| 460 | |||
| 461 | switch (ctrl->bRequest) { | ||
| 462 | case UAC_SET_CUR: | ||
| 463 | value = 0; | ||
| 464 | break; | ||
| 465 | |||
| 466 | case UAC_SET_MIN: | ||
| 467 | break; | ||
| 468 | |||
| 469 | case UAC_SET_MAX: | ||
| 470 | break; | ||
| 471 | |||
| 472 | case UAC_SET_RES: | ||
| 473 | break; | ||
| 474 | |||
| 475 | case UAC_SET_MEM: | ||
| 476 | break; | ||
| 477 | |||
| 478 | default: | ||
| 479 | break; | ||
| 480 | } | ||
| 481 | |||
| 482 | return value; | ||
| 483 | } | ||
| 484 | |||
| 485 | static int audio_get_endpoint_req(struct usb_function *f, | ||
| 486 | const struct usb_ctrlrequest *ctrl) | ||
| 487 | { | ||
| 488 | struct usb_composite_dev *cdev = f->config->cdev; | ||
| 489 | int value = -EOPNOTSUPP; | ||
| 490 | u8 ep = ((le16_to_cpu(ctrl->wIndex) >> 8) & 0xFF); | ||
| 491 | u16 len = le16_to_cpu(ctrl->wLength); | ||
| 492 | u16 w_value = le16_to_cpu(ctrl->wValue); | ||
| 493 | |||
| 494 | DBG(cdev, "bRequest 0x%x, w_value 0x%04x, len %d, endpoint %d\n", | ||
| 495 | ctrl->bRequest, w_value, len, ep); | ||
| 496 | |||
| 497 | switch (ctrl->bRequest) { | ||
| 498 | case UAC_GET_CUR: | ||
| 499 | case UAC_GET_MIN: | ||
| 500 | case UAC_GET_MAX: | ||
| 501 | case UAC_GET_RES: | ||
| 502 | value = 3; | ||
| 503 | break; | ||
| 504 | case UAC_GET_MEM: | ||
| 505 | break; | ||
| 506 | default: | ||
| 507 | break; | ||
| 508 | } | ||
| 509 | |||
| 510 | return value; | ||
| 511 | } | ||
| 512 | |||
| 513 | static int | ||
| 514 | f_audio_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) | ||
| 515 | { | ||
| 516 | struct usb_composite_dev *cdev = f->config->cdev; | ||
| 517 | struct usb_request *req = cdev->req; | ||
| 518 | int value = -EOPNOTSUPP; | ||
| 519 | u16 w_index = le16_to_cpu(ctrl->wIndex); | ||
| 520 | u16 w_value = le16_to_cpu(ctrl->wValue); | ||
| 521 | u16 w_length = le16_to_cpu(ctrl->wLength); | ||
| 522 | |||
| 523 | /* composite driver infrastructure handles everything; interface | ||
| 524 | * activation uses set_alt(). | ||
| 525 | */ | ||
| 526 | switch (ctrl->bRequestType) { | ||
| 527 | case USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE: | ||
| 528 | value = audio_set_intf_req(f, ctrl); | ||
| 529 | break; | ||
| 530 | |||
| 531 | case USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE: | ||
| 532 | value = audio_get_intf_req(f, ctrl); | ||
| 533 | break; | ||
| 534 | |||
| 535 | case USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_ENDPOINT: | ||
| 536 | value = audio_set_endpoint_req(f, ctrl); | ||
| 537 | break; | ||
| 538 | |||
| 539 | case USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT: | ||
| 540 | value = audio_get_endpoint_req(f, ctrl); | ||
| 541 | break; | ||
| 542 | |||
| 543 | default: | ||
| 544 | ERROR(cdev, "invalid control req%02x.%02x v%04x i%04x l%d\n", | ||
| 545 | ctrl->bRequestType, ctrl->bRequest, | ||
| 546 | w_value, w_index, w_length); | ||
| 547 | } | ||
| 548 | |||
| 549 | /* respond with data transfer or status phase? */ | ||
| 550 | if (value >= 0) { | ||
| 551 | DBG(cdev, "audio req%02x.%02x v%04x i%04x l%d\n", | ||
| 552 | ctrl->bRequestType, ctrl->bRequest, | ||
| 553 | w_value, w_index, w_length); | ||
| 554 | req->zero = 0; | ||
| 555 | req->length = value; | ||
| 556 | value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC); | ||
| 557 | if (value < 0) | ||
| 558 | ERROR(cdev, "audio response on err %d\n", value); | ||
| 559 | } | ||
| 560 | |||
| 561 | /* device either stalls (value < 0) or reports success */ | ||
| 562 | return value; | ||
| 563 | } | ||
| 564 | |||
| 565 | static int f_audio_set_alt(struct usb_function *f, unsigned intf, unsigned alt) | ||
| 566 | { | ||
| 567 | struct f_audio *audio = func_to_audio(f); | ||
| 568 | struct usb_composite_dev *cdev = f->config->cdev; | ||
| 569 | struct usb_ep *out_ep = audio->out_ep; | ||
| 570 | struct usb_request *req; | ||
| 571 | int i = 0, err = 0; | ||
| 572 | |||
| 573 | DBG(cdev, "intf %d, alt %d\n", intf, alt); | ||
| 574 | |||
| 575 | if (intf == 1) { | ||
| 576 | if (alt == 1) { | ||
| 577 | usb_ep_enable(out_ep); | ||
| 578 | out_ep->driver_data = audio; | ||
| 579 | audio->copy_buf = f_audio_buffer_alloc(audio_buf_size); | ||
| 580 | if (IS_ERR(audio->copy_buf)) | ||
| 581 | return -ENOMEM; | ||
| 582 | |||
| 583 | /* | ||
| 584 | * allocate a bunch of read buffers | ||
| 585 | * and queue them all at once. | ||
| 586 | */ | ||
| 587 | for (i = 0; i < req_count && err == 0; i++) { | ||
| 588 | req = usb_ep_alloc_request(out_ep, GFP_ATOMIC); | ||
| 589 | if (req) { | ||
| 590 | req->buf = kzalloc(req_buf_size, | ||
| 591 | GFP_ATOMIC); | ||
| 592 | if (req->buf) { | ||
| 593 | req->length = req_buf_size; | ||
| 594 | req->context = audio; | ||
| 595 | req->complete = | ||
| 596 | f_audio_complete; | ||
| 597 | err = usb_ep_queue(out_ep, | ||
| 598 | req, GFP_ATOMIC); | ||
| 599 | if (err) | ||
| 600 | ERROR(cdev, | ||
| 601 | "%s queue req: %d\n", | ||
| 602 | out_ep->name, err); | ||
| 603 | } else | ||
| 604 | err = -ENOMEM; | ||
| 605 | } else | ||
| 606 | err = -ENOMEM; | ||
| 607 | } | ||
| 608 | |||
| 609 | } else { | ||
| 610 | struct f_audio_buf *copy_buf = audio->copy_buf; | ||
| 611 | if (copy_buf) { | ||
| 612 | list_add_tail(©_buf->list, | ||
| 613 | &audio->play_queue); | ||
| 614 | schedule_work(&audio->playback_work); | ||
| 615 | } | ||
| 616 | } | ||
| 617 | } | ||
| 618 | |||
| 619 | return err; | ||
| 620 | } | ||
| 621 | |||
| 622 | static void f_audio_disable(struct usb_function *f) | ||
| 623 | { | ||
| 624 | return; | ||
| 625 | } | ||
| 626 | |||
| 627 | /*-------------------------------------------------------------------------*/ | ||
| 628 | |||
| 629 | static void f_audio_build_desc(struct f_audio *audio) | ||
| 630 | { | ||
| 631 | struct gaudio *card = &audio->card; | ||
| 632 | u8 *sam_freq; | ||
| 633 | int rate; | ||
| 634 | |||
| 635 | /* Set channel numbers */ | ||
| 636 | input_terminal_desc.bNrChannels = u_audio_get_playback_channels(card); | ||
| 637 | as_type_i_desc.bNrChannels = u_audio_get_playback_channels(card); | ||
| 638 | |||
| 639 | /* Set sample rates */ | ||
| 640 | rate = u_audio_get_playback_rate(card); | ||
| 641 | sam_freq = as_type_i_desc.tSamFreq[0]; | ||
| 642 | memcpy(sam_freq, &rate, 3); | ||
| 643 | |||
| 644 | /* Todo: Set Sample bits and other parameters */ | ||
| 645 | |||
| 646 | return; | ||
| 647 | } | ||
| 648 | |||
| 649 | /* audio function driver setup/binding */ | ||
| 650 | static int __init | ||
| 651 | f_audio_bind(struct usb_configuration *c, struct usb_function *f) | ||
| 652 | { | ||
| 653 | struct usb_composite_dev *cdev = c->cdev; | ||
| 654 | struct f_audio *audio = func_to_audio(f); | ||
| 655 | int status; | ||
| 656 | struct usb_ep *ep; | ||
| 657 | |||
| 658 | f_audio_build_desc(audio); | ||
| 659 | |||
| 660 | /* allocate instance-specific interface IDs, and patch descriptors */ | ||
| 661 | status = usb_interface_id(c, f); | ||
| 662 | if (status < 0) | ||
| 663 | goto fail; | ||
| 664 | ac_interface_desc.bInterfaceNumber = status; | ||
| 665 | |||
| 666 | status = usb_interface_id(c, f); | ||
| 667 | if (status < 0) | ||
| 668 | goto fail; | ||
| 669 | as_interface_alt_0_desc.bInterfaceNumber = status; | ||
| 670 | as_interface_alt_1_desc.bInterfaceNumber = status; | ||
| 671 | |||
| 672 | status = -ENODEV; | ||
| 673 | |||
| 674 | /* allocate instance-specific endpoints */ | ||
| 675 | ep = usb_ep_autoconfig(cdev->gadget, &as_out_ep_desc); | ||
| 676 | if (!ep) | ||
| 677 | goto fail; | ||
| 678 | audio->out_ep = ep; | ||
| 679 | audio->out_ep->desc = &as_out_ep_desc; | ||
| 680 | ep->driver_data = cdev; /* claim */ | ||
| 681 | |||
| 682 | status = -ENOMEM; | ||
| 683 | |||
| 684 | /* supcard all relevant hardware speeds... we expect that when | ||
| 685 | * hardware is dual speed, all bulk-capable endpoints work at | ||
| 686 | * both speeds | ||
| 687 | */ | ||
| 688 | |||
| 689 | /* copy descriptors, and track endpoint copies */ | ||
| 690 | if (gadget_is_dualspeed(c->cdev->gadget)) { | ||
| 691 | c->highspeed = true; | ||
| 692 | f->hs_descriptors = usb_copy_descriptors(f_audio_desc); | ||
| 693 | } else | ||
| 694 | f->descriptors = usb_copy_descriptors(f_audio_desc); | ||
| 695 | |||
| 696 | return 0; | ||
| 697 | |||
| 698 | fail: | ||
| 699 | |||
| 700 | return status; | ||
| 701 | } | ||
| 702 | |||
| 703 | static void | ||
| 704 | f_audio_unbind(struct usb_configuration *c, struct usb_function *f) | ||
| 705 | { | ||
| 706 | struct f_audio *audio = func_to_audio(f); | ||
| 707 | |||
| 708 | usb_free_descriptors(f->descriptors); | ||
| 709 | usb_free_descriptors(f->hs_descriptors); | ||
| 710 | kfree(audio); | ||
| 711 | } | ||
| 712 | |||
| 713 | /*-------------------------------------------------------------------------*/ | ||
| 714 | |||
| 715 | static int generic_set_cmd(struct usb_audio_control *con, u8 cmd, int value) | ||
| 716 | { | ||
| 717 | con->data[cmd] = value; | ||
| 718 | |||
| 719 | return 0; | ||
| 720 | } | ||
| 721 | |||
| 722 | static int generic_get_cmd(struct usb_audio_control *con, u8 cmd) | ||
| 723 | { | ||
| 724 | return con->data[cmd]; | ||
| 725 | } | ||
| 726 | |||
| 727 | /* Todo: add more control selecotor dynamically */ | ||
| 728 | int __init control_selector_init(struct f_audio *audio) | ||
| 729 | { | ||
| 730 | INIT_LIST_HEAD(&audio->cs); | ||
| 731 | list_add(&feature_unit.list, &audio->cs); | ||
| 732 | |||
| 733 | INIT_LIST_HEAD(&feature_unit.control); | ||
| 734 | list_add(&mute_control.list, &feature_unit.control); | ||
| 735 | list_add(&volume_control.list, &feature_unit.control); | ||
| 736 | |||
| 737 | volume_control.data[UAC__CUR] = 0xffc0; | ||
| 738 | volume_control.data[UAC__MIN] = 0xe3a0; | ||
| 739 | volume_control.data[UAC__MAX] = 0xfff0; | ||
| 740 | volume_control.data[UAC__RES] = 0x0030; | ||
| 741 | |||
| 742 | return 0; | ||
| 743 | } | ||
| 744 | |||
| 745 | /** | ||
| 746 | * audio_bind_config - add USB audio function to a configuration | ||
| 747 | * @c: the configuration to supcard the USB audio function | ||
| 748 | * Context: single threaded during gadget setup | ||
| 749 | * | ||
| 750 | * Returns zero on success, else negative errno. | ||
| 751 | */ | ||
| 752 | int __init audio_bind_config(struct usb_configuration *c) | ||
| 753 | { | ||
| 754 | struct f_audio *audio; | ||
| 755 | int status; | ||
| 756 | |||
| 757 | /* allocate and initialize one new instance */ | ||
| 758 | audio = kzalloc(sizeof *audio, GFP_KERNEL); | ||
| 759 | if (!audio) | ||
| 760 | return -ENOMEM; | ||
| 761 | |||
| 762 | audio->card.func.name = "g_audio"; | ||
| 763 | audio->card.gadget = c->cdev->gadget; | ||
| 764 | |||
| 765 | INIT_LIST_HEAD(&audio->play_queue); | ||
| 766 | spin_lock_init(&audio->lock); | ||
| 767 | |||
| 768 | /* set up ASLA audio devices */ | ||
| 769 | status = gaudio_setup(&audio->card); | ||
| 770 | if (status < 0) | ||
| 771 | goto setup_fail; | ||
| 772 | |||
| 773 | audio->card.func.strings = audio_strings; | ||
| 774 | audio->card.func.bind = f_audio_bind; | ||
| 775 | audio->card.func.unbind = f_audio_unbind; | ||
| 776 | audio->card.func.set_alt = f_audio_set_alt; | ||
| 777 | audio->card.func.setup = f_audio_setup; | ||
| 778 | audio->card.func.disable = f_audio_disable; | ||
| 779 | |||
| 780 | control_selector_init(audio); | ||
| 781 | |||
| 782 | INIT_WORK(&audio->playback_work, f_audio_playback_work); | ||
| 783 | |||
| 784 | status = usb_add_function(c, &audio->card.func); | ||
| 785 | if (status) | ||
| 786 | goto add_fail; | ||
| 787 | |||
| 788 | INFO(c->cdev, "audio_buf_size %d, req_buf_size %d, req_count %d\n", | ||
| 789 | audio_buf_size, req_buf_size, req_count); | ||
| 790 | |||
| 791 | return status; | ||
| 792 | |||
| 793 | add_fail: | ||
| 794 | gaudio_cleanup(); | ||
| 795 | setup_fail: | ||
| 796 | kfree(audio); | ||
| 797 | return status; | ||
| 798 | } | ||
diff --git a/drivers/usb/gadget/f_mtp.c b/drivers/usb/gadget/f_mtp.c new file mode 100644 index 00000000000..5aa5214297d --- /dev/null +++ b/drivers/usb/gadget/f_mtp.c | |||
| @@ -0,0 +1,1264 @@ | |||
| 1 | /* | ||
| 2 | * Gadget Function Driver for MTP | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Google, Inc. | ||
| 5 | * Author: Mike Lockwood <lockwood@android.com> | ||
| 6 | * | ||
| 7 | * This software is licensed under the terms of the GNU General Public | ||
| 8 | * License version 2, as published by the Free Software Foundation, and | ||
| 9 | * may be copied, distributed, and modified under those terms. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | */ | ||
| 17 | |||
| 18 | /* #define DEBUG */ | ||
| 19 | /* #define VERBOSE_DEBUG */ | ||
| 20 | |||
| 21 | #include <linux/module.h> | ||
| 22 | #include <linux/init.h> | ||
| 23 | #include <linux/poll.h> | ||
| 24 | #include <linux/delay.h> | ||
| 25 | #include <linux/wait.h> | ||
| 26 | #include <linux/err.h> | ||
| 27 | #include <linux/interrupt.h> | ||
| 28 | |||
| 29 | #include <linux/types.h> | ||
| 30 | #include <linux/file.h> | ||
| 31 | #include <linux/device.h> | ||
| 32 | #include <linux/miscdevice.h> | ||
| 33 | |||
| 34 | #include <linux/usb.h> | ||
| 35 | #include <linux/usb_usual.h> | ||
| 36 | #include <linux/usb/ch9.h> | ||
| 37 | #include <linux/usb/f_mtp.h> | ||
| 38 | |||
| 39 | #define MTP_BULK_BUFFER_SIZE 16384 | ||
| 40 | #define INTR_BUFFER_SIZE 28 | ||
| 41 | |||
| 42 | /* String IDs */ | ||
| 43 | #define INTERFACE_STRING_INDEX 0 | ||
| 44 | |||
| 45 | /* values for mtp_dev.state */ | ||
| 46 | #define STATE_OFFLINE 0 /* initial state, disconnected */ | ||
| 47 | #define STATE_READY 1 /* ready for userspace calls */ | ||
| 48 | #define STATE_BUSY 2 /* processing userspace calls */ | ||
| 49 | #define STATE_CANCELED 3 /* transaction canceled by host */ | ||
| 50 | #define STATE_ERROR 4 /* error from completion routine */ | ||
| 51 | |||
| 52 | /* number of tx and rx requests to allocate */ | ||
| 53 | #define TX_REQ_MAX 4 | ||
| 54 | #define RX_REQ_MAX 2 | ||
| 55 | #define INTR_REQ_MAX 5 | ||
| 56 | |||
| 57 | /* ID for Microsoft MTP OS String */ | ||
| 58 | #define MTP_OS_STRING_ID 0xEE | ||
| 59 | |||
| 60 | /* MTP class reqeusts */ | ||
| 61 | #define MTP_REQ_CANCEL 0x64 | ||
| 62 | #define MTP_REQ_GET_EXT_EVENT_DATA 0x65 | ||
| 63 | #define MTP_REQ_RESET 0x66 | ||
| 64 | #define MTP_REQ_GET_DEVICE_STATUS 0x67 | ||
| 65 | |||
| 66 | /* constants for device status */ | ||
| 67 | #define MTP_RESPONSE_OK 0x2001 | ||
| 68 | #define MTP_RESPONSE_DEVICE_BUSY 0x2019 | ||
| 69 | |||
| 70 | static const char mtp_shortname[] = "mtp_usb"; | ||
| 71 | |||
| 72 | struct mtp_dev { | ||
| 73 | struct usb_function function; | ||
| 74 | struct usb_composite_dev *cdev; | ||
| 75 | spinlock_t lock; | ||
| 76 | |||
| 77 | struct usb_ep *ep_in; | ||
| 78 | struct usb_ep *ep_out; | ||
| 79 | struct usb_ep *ep_intr; | ||
| 80 | |||
| 81 | int state; | ||
| 82 | |||
| 83 | /* synchronize access to our device file */ | ||
| 84 | atomic_t open_excl; | ||
| 85 | /* to enforce only one ioctl at a time */ | ||
| 86 | atomic_t ioctl_excl; | ||
| 87 | |||
| 88 | struct list_head tx_idle; | ||
| 89 | struct list_head intr_idle; | ||
| 90 | |||
| 91 | wait_queue_head_t read_wq; | ||
| 92 | wait_queue_head_t write_wq; | ||
| 93 | wait_queue_head_t intr_wq; | ||
| 94 | struct usb_request *rx_req[RX_REQ_MAX]; | ||
| 95 | int rx_done; | ||
| 96 | |||
| 97 | /* for processing MTP_SEND_FILE, MTP_RECEIVE_FILE and | ||
| 98 | * MTP_SEND_FILE_WITH_HEADER ioctls on a work queue | ||
| 99 | */ | ||
| 100 | struct workqueue_struct *wq; | ||
| 101 | struct work_struct send_file_work; | ||
| 102 | struct work_struct receive_file_work; | ||
| 103 | struct file *xfer_file; | ||
| 104 | loff_t xfer_file_offset; | ||
| 105 | int64_t xfer_file_length; | ||
| 106 | unsigned xfer_send_header; | ||
| 107 | uint16_t xfer_command; | ||
| 108 | uint32_t xfer_transaction_id; | ||
| 109 | int xfer_result; | ||
| 110 | }; | ||
| 111 | |||
| 112 | static struct usb_interface_descriptor mtp_interface_desc = { | ||
| 113 | .bLength = USB_DT_INTERFACE_SIZE, | ||
| 114 | .bDescriptorType = USB_DT_INTERFACE, | ||
| 115 | .bInterfaceNumber = 0, | ||
| 116 | .bNumEndpoints = 3, | ||
| 117 | .bInterfaceClass = USB_CLASS_VENDOR_SPEC, | ||
| 118 | .bInterfaceSubClass = USB_SUBCLASS_VENDOR_SPEC, | ||
| 119 | .bInterfaceProtocol = 0, | ||
| 120 | }; | ||
| 121 | |||
| 122 | static struct usb_interface_descriptor ptp_interface_desc = { | ||
| 123 | .bLength = USB_DT_INTERFACE_SIZE, | ||
| 124 | .bDescriptorType = USB_DT_INTERFACE, | ||
| 125 | .bInterfaceNumber = 0, | ||
| 126 | .bNumEndpoints = 3, | ||
| 127 | .bInterfaceClass = USB_CLASS_STILL_IMAGE, | ||
| 128 | .bInterfaceSubClass = 1, | ||
| 129 | .bInterfaceProtocol = 1, | ||
| 130 | }; | ||
| 131 | |||
| 132 | static struct usb_endpoint_descriptor mtp_highspeed_in_desc = { | ||
| 133 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
| 134 | .bDescriptorType = USB_DT_ENDPOINT, | ||
| 135 | .bEndpointAddress = USB_DIR_IN, | ||
| 136 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
| 137 | .wMaxPacketSize = __constant_cpu_to_le16(512), | ||
| 138 | }; | ||
| 139 | |||
| 140 | static struct usb_endpoint_descriptor mtp_highspeed_out_desc = { | ||
| 141 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
| 142 | .bDescriptorType = USB_DT_ENDPOINT, | ||
| 143 | .bEndpointAddress = USB_DIR_OUT, | ||
| 144 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
| 145 | .wMaxPacketSize = __constant_cpu_to_le16(512), | ||
| 146 | }; | ||
| 147 | |||
| 148 | static struct usb_endpoint_descriptor mtp_fullspeed_in_desc = { | ||
| 149 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
| 150 | .bDescriptorType = USB_DT_ENDPOINT, | ||
| 151 | .bEndpointAddress = USB_DIR_IN, | ||
| 152 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
| 153 | }; | ||
| 154 | |||
| 155 | static struct usb_endpoint_descriptor mtp_fullspeed_out_desc = { | ||
| 156 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
| 157 | .bDescriptorType = USB_DT_ENDPOINT, | ||
| 158 | .bEndpointAddress = USB_DIR_OUT, | ||
| 159 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
| 160 | }; | ||
| 161 | |||
| 162 | static struct usb_endpoint_descriptor mtp_intr_desc = { | ||
| 163 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
| 164 | .bDescriptorType = USB_DT_ENDPOINT, | ||
| 165 | .bEndpointAddress = USB_DIR_IN, | ||
| 166 | .bmAttributes = USB_ENDPOINT_XFER_INT, | ||
| 167 | .wMaxPacketSize = __constant_cpu_to_le16(INTR_BUFFER_SIZE), | ||
| 168 | .bInterval = 6, | ||
| 169 | }; | ||
| 170 | |||
| 171 | static struct usb_descriptor_header *fs_mtp_descs[] = { | ||
| 172 | (struct usb_descriptor_header *) &mtp_interface_desc, | ||
| 173 | (struct usb_descriptor_header *) &mtp_fullspeed_in_desc, | ||
| 174 | (struct usb_descriptor_header *) &mtp_fullspeed_out_desc, | ||
| 175 | (struct usb_descriptor_header *) &mtp_intr_desc, | ||
| 176 | NULL, | ||
| 177 | }; | ||
| 178 | |||
| 179 | static struct usb_descriptor_header *hs_mtp_descs[] = { | ||
| 180 | (struct usb_descriptor_header *) &mtp_interface_desc, | ||
| 181 | (struct usb_descriptor_header *) &mtp_highspeed_in_desc, | ||
| 182 | (struct usb_descriptor_header *) &mtp_highspeed_out_desc, | ||
| 183 | (struct usb_descriptor_header *) &mtp_intr_desc, | ||
| 184 | NULL, | ||
| 185 | }; | ||
| 186 | |||
| 187 | static struct usb_descriptor_header *fs_ptp_descs[] = { | ||
| 188 | (struct usb_descriptor_header *) &ptp_interface_desc, | ||
| 189 | (struct usb_descriptor_header *) &mtp_fullspeed_in_desc, | ||
| 190 | (struct usb_descriptor_header *) &mtp_fullspeed_out_desc, | ||
| 191 | (struct usb_descriptor_header *) &mtp_intr_desc, | ||
| 192 | NULL, | ||
| 193 | }; | ||
| 194 | |||
| 195 | static struct usb_descriptor_header *hs_ptp_descs[] = { | ||
| 196 | (struct usb_descriptor_header *) &ptp_interface_desc, | ||
| 197 | (struct usb_descriptor_header *) &mtp_highspeed_in_desc, | ||
| 198 | (struct usb_descriptor_header *) &mtp_highspeed_out_desc, | ||
| 199 | (struct usb_descriptor_header *) &mtp_intr_desc, | ||
| 200 | NULL, | ||
| 201 | }; | ||
| 202 | |||
| 203 | static struct usb_string mtp_string_defs[] = { | ||
| 204 | /* Naming interface "MTP" so libmtp will recognize us */ | ||
| 205 | [INTERFACE_STRING_INDEX].s = "MTP", | ||
| 206 | { }, /* end of list */ | ||
| 207 | }; | ||
| 208 | |||
| 209 | static struct usb_gadget_strings mtp_string_table = { | ||
| 210 | .language = 0x0409, /* en-US */ | ||
| 211 | .strings = mtp_string_defs, | ||
| 212 | }; | ||
| 213 | |||
| 214 | static struct usb_gadget_strings *mtp_strings[] = { | ||
| 215 | &mtp_string_table, | ||
| 216 | NULL, | ||
| 217 | }; | ||
| 218 | |||
| 219 | /* Microsoft MTP OS String */ | ||
| 220 | static u8 mtp_os_string[] = { | ||
| 221 | 18, /* sizeof(mtp_os_string) */ | ||
| 222 | USB_DT_STRING, | ||
| 223 | /* Signature field: "MSFT100" */ | ||
| 224 | 'M', 0, 'S', 0, 'F', 0, 'T', 0, '1', 0, '0', 0, '0', 0, | ||
| 225 | /* vendor code */ | ||
| 226 | 1, | ||
| 227 | /* padding */ | ||
| 228 | 0 | ||
| 229 | }; | ||
| 230 | |||
| 231 | /* Microsoft Extended Configuration Descriptor Header Section */ | ||
| 232 | struct mtp_ext_config_desc_header { | ||
| 233 | __le32 dwLength; | ||
| 234 | __u16 bcdVersion; | ||
| 235 | __le16 wIndex; | ||
| 236 | __u8 bCount; | ||
| 237 | __u8 reserved[7]; | ||
| 238 | }; | ||
| 239 | |||
| 240 | /* Microsoft Extended Configuration Descriptor Function Section */ | ||
| 241 | struct mtp_ext_config_desc_function { | ||
| 242 | __u8 bFirstInterfaceNumber; | ||
| 243 | __u8 bInterfaceCount; | ||
| 244 | __u8 compatibleID[8]; | ||
| 245 | __u8 subCompatibleID[8]; | ||
| 246 | __u8 reserved[6]; | ||
| 247 | }; | ||
| 248 | |||
| 249 | /* MTP Extended Configuration Descriptor */ | ||
| 250 | struct { | ||
| 251 | struct mtp_ext_config_desc_header header; | ||
| 252 | struct mtp_ext_config_desc_function function; | ||
| 253 | } mtp_ext_config_desc = { | ||
| 254 | .header = { | ||
| 255 | .dwLength = __constant_cpu_to_le32(sizeof(mtp_ext_config_desc)), | ||
| 256 | .bcdVersion = __constant_cpu_to_le16(0x0100), | ||
| 257 | .wIndex = __constant_cpu_to_le16(4), | ||
| 258 | .bCount = __constant_cpu_to_le16(1), | ||
| 259 | }, | ||
| 260 | .function = { | ||
| 261 | .bFirstInterfaceNumber = 0, | ||
| 262 | .bInterfaceCount = 1, | ||
| 263 | .compatibleID = { 'M', 'T', 'P' }, | ||
| 264 | }, | ||
| 265 | }; | ||
| 266 | |||
| 267 | struct mtp_device_status { | ||
| 268 | __le16 wLength; | ||
| 269 | __le16 wCode; | ||
| 270 | }; | ||
| 271 | |||
| 272 | /* temporary variable used between mtp_open() and mtp_gadget_bind() */ | ||
| 273 | static struct mtp_dev *_mtp_dev; | ||
| 274 | |||
| 275 | static inline struct mtp_dev *func_to_mtp(struct usb_function *f) | ||
| 276 | { | ||
| 277 | return container_of(f, struct mtp_dev, function); | ||
| 278 | } | ||
| 279 | |||
| 280 | static struct usb_request *mtp_request_new(struct usb_ep *ep, int buffer_size) | ||
| 281 | { | ||
| 282 | struct usb_request *req = usb_ep_alloc_request(ep, GFP_KERNEL); | ||
| 283 | if (!req) | ||
| 284 | return NULL; | ||
| 285 | |||
| 286 | /* now allocate buffers for the requests */ | ||
| 287 | req->buf = kmalloc(buffer_size, GFP_KERNEL); | ||
| 288 | if (!req->buf) { | ||
| 289 | usb_ep_free_request(ep, req); | ||
| 290 | return NULL; | ||
| 291 | } | ||
| 292 | |||
| 293 | return req; | ||
| 294 | } | ||
| 295 | |||
| 296 | static void mtp_request_free(struct usb_request *req, struct usb_ep *ep) | ||
| 297 | { | ||
| 298 | if (req) { | ||
| 299 | kfree(req->buf); | ||
| 300 | usb_ep_free_request(ep, req); | ||
| 301 | } | ||
| 302 | } | ||
| 303 | |||
| 304 | static inline int mtp_lock(atomic_t *excl) | ||
| 305 | { | ||
| 306 | if (atomic_inc_return(excl) == 1) { | ||
| 307 | return 0; | ||
| 308 | } else { | ||
| 309 | atomic_dec(excl); | ||
| 310 | return -1; | ||
| 311 | } | ||
| 312 | } | ||
| 313 | |||
| 314 | static inline void mtp_unlock(atomic_t *excl) | ||
| 315 | { | ||
| 316 | atomic_dec(excl); | ||
| 317 | } | ||
| 318 | |||
| 319 | /* add a request to the tail of a list */ | ||
| 320 | static void mtp_req_put(struct mtp_dev *dev, struct list_head *head, | ||
| 321 | struct usb_request *req) | ||
| 322 | { | ||
| 323 | unsigned long flags; | ||
| 324 | |||
| 325 | spin_lock_irqsave(&dev->lock, flags); | ||
| 326 | list_add_tail(&req->list, head); | ||
| 327 | spin_unlock_irqrestore(&dev->lock, flags); | ||
| 328 | } | ||
| 329 | |||
| 330 | /* remove a request from the head of a list */ | ||
| 331 | static struct usb_request | ||
| 332 | *mtp_req_get(struct mtp_dev *dev, struct list_head *head) | ||
| 333 | { | ||
| 334 | unsigned long flags; | ||
| 335 | struct usb_request *req; | ||
| 336 | |||
| 337 | spin_lock_irqsave(&dev->lock, flags); | ||
| 338 | if (list_empty(head)) { | ||
| 339 | req = 0; | ||
| 340 | } else { | ||
| 341 | req = list_first_entry(head, struct usb_request, list); | ||
| 342 | list_del(&req->list); | ||
| 343 | } | ||
| 344 | spin_unlock_irqrestore(&dev->lock, flags); | ||
| 345 | return req; | ||
| 346 | } | ||
| 347 | |||
| 348 | static void mtp_complete_in(struct usb_ep *ep, struct usb_request *req) | ||
| 349 | { | ||
| 350 | struct mtp_dev *dev = _mtp_dev; | ||
| 351 | |||
| 352 | if (req->status != 0) | ||
| 353 | dev->state = STATE_ERROR; | ||
| 354 | |||
| 355 | mtp_req_put(dev, &dev->tx_idle, req); | ||
| 356 | |||
| 357 | wake_up(&dev->write_wq); | ||
| 358 | } | ||
| 359 | |||
| 360 | static void mtp_complete_out(struct usb_ep *ep, struct usb_request *req) | ||
| 361 | { | ||
| 362 | struct mtp_dev *dev = _mtp_dev; | ||
| 363 | |||
| 364 | dev->rx_done = 1; | ||
| 365 | if (req->status != 0) | ||
| 366 | dev->state = STATE_ERROR; | ||
| 367 | |||
| 368 | wake_up(&dev->read_wq); | ||
| 369 | } | ||
| 370 | |||
| 371 | static void mtp_complete_intr(struct usb_ep *ep, struct usb_request *req) | ||
| 372 | { | ||
| 373 | struct mtp_dev *dev = _mtp_dev; | ||
| 374 | |||
| 375 | if (req->status != 0) | ||
| 376 | dev->state = STATE_ERROR; | ||
| 377 | |||
| 378 | mtp_req_put(dev, &dev->intr_idle, req); | ||
| 379 | |||
| 380 | wake_up(&dev->intr_wq); | ||
| 381 | } | ||
| 382 | |||
| 383 | static int mtp_create_bulk_endpoints(struct mtp_dev *dev, | ||
| 384 | struct usb_endpoint_descriptor *in_desc, | ||
| 385 | struct usb_endpoint_descriptor *out_desc, | ||
| 386 | struct usb_endpoint_descriptor *intr_desc) | ||
| 387 | { | ||
| 388 | struct usb_composite_dev *cdev = dev->cdev; | ||
| 389 | struct usb_request *req; | ||
| 390 | struct usb_ep *ep; | ||
| 391 | int i; | ||
| 392 | |||
| 393 | DBG(cdev, "create_bulk_endpoints dev: %p\n", dev); | ||
| 394 | |||
| 395 | ep = usb_ep_autoconfig(cdev->gadget, in_desc); | ||
| 396 | if (!ep) { | ||
| 397 | DBG(cdev, "usb_ep_autoconfig for ep_in failed\n"); | ||
| 398 | return -ENODEV; | ||
| 399 | } | ||
| 400 | DBG(cdev, "usb_ep_autoconfig for ep_in got %s\n", ep->name); | ||
| 401 | ep->driver_data = dev; /* claim the endpoint */ | ||
| 402 | dev->ep_in = ep; | ||
| 403 | |||
| 404 | ep = usb_ep_autoconfig(cdev->gadget, out_desc); | ||
| 405 | if (!ep) { | ||
| 406 | DBG(cdev, "usb_ep_autoconfig for ep_out failed\n"); | ||
| 407 | return -ENODEV; | ||
| 408 | } | ||
| 409 | DBG(cdev, "usb_ep_autoconfig for mtp ep_out got %s\n", ep->name); | ||
| 410 | ep->driver_data = dev; /* claim the endpoint */ | ||
| 411 | dev->ep_out = ep; | ||
| 412 | |||
| 413 | ep = usb_ep_autoconfig(cdev->gadget, out_desc); | ||
| 414 | if (!ep) { | ||
| 415 | DBG(cdev, "usb_ep_autoconfig for ep_out failed\n"); | ||
| 416 | return -ENODEV; | ||
| 417 | } | ||
| 418 | DBG(cdev, "usb_ep_autoconfig for mtp ep_out got %s\n", ep->name); | ||
| 419 | ep->driver_data = dev; /* claim the endpoint */ | ||
| 420 | dev->ep_out = ep; | ||
| 421 | |||
| 422 | ep = usb_ep_autoconfig(cdev->gadget, intr_desc); | ||
| 423 | if (!ep) { | ||
| 424 | DBG(cdev, "usb_ep_autoconfig for ep_intr failed\n"); | ||
| 425 | return -ENODEV; | ||
| 426 | } | ||
| 427 | DBG(cdev, "usb_ep_autoconfig for mtp ep_intr got %s\n", ep->name); | ||
| 428 | ep->driver_data = dev; /* claim the endpoint */ | ||
| 429 | dev->ep_intr = ep; | ||
| 430 | |||
| 431 | /* now allocate requests for our endpoints */ | ||
| 432 | for (i = 0; i < TX_REQ_MAX; i++) { | ||
| 433 | req = mtp_request_new(dev->ep_in, MTP_BULK_BUFFER_SIZE); | ||
| 434 | if (!req) | ||
| 435 | goto fail; | ||
| 436 | req->complete = mtp_complete_in; | ||
| 437 | mtp_req_put(dev, &dev->tx_idle, req); | ||
| 438 | } | ||
| 439 | for (i = 0; i < RX_REQ_MAX; i++) { | ||
| 440 | req = mtp_request_new(dev->ep_out, MTP_BULK_BUFFER_SIZE); | ||
| 441 | if (!req) | ||
| 442 | goto fail; | ||
| 443 | req->complete = mtp_complete_out; | ||
| 444 | dev->rx_req[i] = req; | ||
| 445 | } | ||
| 446 | for (i = 0; i < INTR_REQ_MAX; i++) { | ||
| 447 | req = mtp_request_new(dev->ep_intr, INTR_BUFFER_SIZE); | ||
| 448 | if (!req) | ||
| 449 | goto fail; | ||
| 450 | req->complete = mtp_complete_intr; | ||
| 451 | mtp_req_put(dev, &dev->intr_idle, req); | ||
| 452 | } | ||
| 453 | |||
| 454 | return 0; | ||
| 455 | |||
| 456 | fail: | ||
| 457 | printk(KERN_ERR "mtp_bind() could not allocate requests\n"); | ||
| 458 | return -1; | ||
| 459 | } | ||
| 460 | |||
| 461 | static ssize_t mtp_read(struct file *fp, char __user *buf, | ||
| 462 | size_t count, loff_t *pos) | ||
| 463 | { | ||
| 464 | struct mtp_dev *dev = fp->private_data; | ||
| 465 | struct usb_composite_dev *cdev = dev->cdev; | ||
| 466 | struct usb_request *req; | ||
| 467 | int r = count, xfer; | ||
| 468 | int ret = 0; | ||
| 469 | |||
| 470 | DBG(cdev, "mtp_read(%d)\n", count); | ||
| 471 | |||
| 472 | if (count > MTP_BULK_BUFFER_SIZE) | ||
| 473 | return -EINVAL; | ||
| 474 | |||
| 475 | /* we will block until we're online */ | ||
| 476 | DBG(cdev, "mtp_read: waiting for online state\n"); | ||
| 477 | ret = wait_event_interruptible(dev->read_wq, | ||
| 478 | dev->state != STATE_OFFLINE); | ||
| 479 | if (ret < 0) { | ||
| 480 | r = ret; | ||
| 481 | goto done; | ||
| 482 | } | ||
| 483 | spin_lock_irq(&dev->lock); | ||
| 484 | if (dev->state == STATE_CANCELED) { | ||
| 485 | /* report cancelation to userspace */ | ||
| 486 | dev->state = STATE_READY; | ||
| 487 | spin_unlock_irq(&dev->lock); | ||
| 488 | return -ECANCELED; | ||
| 489 | } | ||
| 490 | dev->state = STATE_BUSY; | ||
| 491 | spin_unlock_irq(&dev->lock); | ||
| 492 | |||
| 493 | requeue_req: | ||
| 494 | /* queue a request */ | ||
| 495 | req = dev->rx_req[0]; | ||
| 496 | req->length = count; | ||
| 497 | dev->rx_done = 0; | ||
| 498 | ret = usb_ep_queue(dev->ep_out, req, GFP_KERNEL); | ||
| 499 | if (ret < 0) { | ||
| 500 | r = -EIO; | ||
| 501 | goto done; | ||
| 502 | } else { | ||
| 503 | DBG(cdev, "rx %p queue\n", req); | ||
| 504 | } | ||
| 505 | |||
| 506 | /* wait for a request to complete */ | ||
| 507 | ret = wait_event_interruptible(dev->read_wq, dev->rx_done); | ||
| 508 | if (ret < 0) { | ||
| 509 | r = ret; | ||
| 510 | usb_ep_dequeue(dev->ep_out, req); | ||
| 511 | goto done; | ||
| 512 | } | ||
| 513 | if (dev->state == STATE_BUSY) { | ||
| 514 | /* If we got a 0-len packet, throw it back and try again. */ | ||
| 515 | if (req->actual == 0) | ||
| 516 | goto requeue_req; | ||
| 517 | |||
| 518 | DBG(cdev, "rx %p %d\n", req, req->actual); | ||
| 519 | xfer = (req->actual < count) ? req->actual : count; | ||
| 520 | r = xfer; | ||
| 521 | if (copy_to_user(buf, req->buf, xfer)) | ||
| 522 | r = -EFAULT; | ||
| 523 | } else | ||
| 524 | r = -EIO; | ||
| 525 | |||
| 526 | done: | ||
| 527 | spin_lock_irq(&dev->lock); | ||
| 528 | if (dev->state == STATE_CANCELED) | ||
| 529 | r = -ECANCELED; | ||
| 530 | else if (dev->state != STATE_OFFLINE) | ||
| 531 | dev->state = STATE_READY; | ||
| 532 | spin_unlock_irq(&dev->lock); | ||
| 533 | |||
| 534 | DBG(cdev, "mtp_read returning %d\n", r); | ||
| 535 | return r; | ||
| 536 | } | ||
| 537 | |||
| 538 | static ssize_t mtp_write(struct file *fp, const char __user *buf, | ||
| 539 | size_t count, loff_t *pos) | ||
| 540 | { | ||
| 541 | struct mtp_dev *dev = fp->private_data; | ||
| 542 | struct usb_composite_dev *cdev = dev->cdev; | ||
| 543 | struct usb_request *req = 0; | ||
| 544 | int r = count, xfer; | ||
| 545 | int sendZLP = 0; | ||
| 546 | int ret; | ||
| 547 | |||
| 548 | DBG(cdev, "mtp_write(%d)\n", count); | ||
| 549 | |||
| 550 | spin_lock_irq(&dev->lock); | ||
| 551 | if (dev->state == STATE_CANCELED) { | ||
| 552 | /* report cancelation to userspace */ | ||
| 553 | dev->state = STATE_READY; | ||
| 554 | spin_unlock_irq(&dev->lock); | ||
| 555 | return -ECANCELED; | ||
| 556 | } | ||
| 557 | if (dev->state == STATE_OFFLINE) { | ||
| 558 | spin_unlock_irq(&dev->lock); | ||
| 559 | return -ENODEV; | ||
| 560 | } | ||
| 561 | dev->state = STATE_BUSY; | ||
| 562 | spin_unlock_irq(&dev->lock); | ||
| 563 | |||
| 564 | /* we need to send a zero length packet to signal the end of transfer | ||
| 565 | * if the transfer size is aligned to a packet boundary. | ||
| 566 | */ | ||
| 567 | if ((count & (dev->ep_in->maxpacket - 1)) == 0) { | ||
| 568 | sendZLP = 1; | ||
| 569 | } | ||
| 570 | |||
| 571 | while (count > 0 || sendZLP) { | ||
| 572 | /* so we exit after sending ZLP */ | ||
| 573 | if (count == 0) | ||
| 574 | sendZLP = 0; | ||
| 575 | |||
| 576 | if (dev->state != STATE_BUSY) { | ||
| 577 | DBG(cdev, "mtp_write dev->error\n"); | ||
| 578 | r = -EIO; | ||
| 579 | break; | ||
| 580 | } | ||
| 581 | |||
| 582 | /* get an idle tx request to use */ | ||
| 583 | req = 0; | ||
| 584 | ret = wait_event_interruptible(dev->write_wq, | ||
| 585 | ((req = mtp_req_get(dev, &dev->tx_idle)) | ||
| 586 | || dev->state != STATE_BUSY)); | ||
| 587 | if (!req) { | ||
| 588 | r = ret; | ||
| 589 | break; | ||
| 590 | } | ||
| 591 | |||
| 592 | if (count > MTP_BULK_BUFFER_SIZE) | ||
| 593 | xfer = MTP_BULK_BUFFER_SIZE; | ||
| 594 | else | ||
| 595 | xfer = count; | ||
| 596 | if (xfer && copy_from_user(req->buf, buf, xfer)) { | ||
| 597 | r = -EFAULT; | ||
| 598 | break; | ||
| 599 | } | ||
| 600 | |||
| 601 | req->length = xfer; | ||
| 602 | ret = usb_ep_queue(dev->ep_in, req, GFP_KERNEL); | ||
| 603 | if (ret < 0) { | ||
| 604 | DBG(cdev, "mtp_write: xfer error %d\n", ret); | ||
| 605 | r = -EIO; | ||
| 606 | break; | ||
| 607 | } | ||
| 608 | |||
| 609 | buf += xfer; | ||
| 610 | count -= xfer; | ||
| 611 | |||
| 612 | /* zero this so we don't try to free it on error exit */ | ||
| 613 | req = 0; | ||
| 614 | } | ||
| 615 | |||
| 616 | if (req) | ||
| 617 | mtp_req_put(dev, &dev->tx_idle, req); | ||
| 618 | |||
| 619 | spin_lock_irq(&dev->lock); | ||
| 620 | if (dev->state == STATE_CANCELED) | ||
| 621 | r = -ECANCELED; | ||
| 622 | else if (dev->state != STATE_OFFLINE) | ||
| 623 | dev->state = STATE_READY; | ||
| 624 | spin_unlock_irq(&dev->lock); | ||
| 625 | |||
| 626 | DBG(cdev, "mtp_write returning %d\n", r); | ||
| 627 | return r; | ||
| 628 | } | ||
| 629 | |||
| 630 | /* read from a local file and write to USB */ | ||
| 631 | static void send_file_work(struct work_struct *data) { | ||
| 632 | struct mtp_dev *dev = container_of(data, struct mtp_dev, send_file_work); | ||
| 633 | struct usb_composite_dev *cdev = dev->cdev; | ||
| 634 | struct usb_request *req = 0; | ||
| 635 | struct mtp_data_header *header; | ||
| 636 | struct file *filp; | ||
| 637 | loff_t offset; | ||
| 638 | int64_t count; | ||
| 639 | int xfer, ret, hdr_size; | ||
| 640 | int r = 0; | ||
| 641 | int sendZLP = 0; | ||
| 642 | |||
| 643 | /* read our parameters */ | ||
| 644 | smp_rmb(); | ||
| 645 | filp = dev->xfer_file; | ||
| 646 | offset = dev->xfer_file_offset; | ||
| 647 | count = dev->xfer_file_length; | ||
| 648 | |||
| 649 | DBG(cdev, "send_file_work(%lld %lld)\n", offset, count); | ||
| 650 | |||
| 651 | if (dev->xfer_send_header) { | ||
| 652 | hdr_size = sizeof(struct mtp_data_header); | ||
| 653 | count += hdr_size; | ||
| 654 | } else { | ||
| 655 | hdr_size = 0; | ||
| 656 | } | ||
| 657 | |||
| 658 | /* we need to send a zero length packet to signal the end of transfer | ||
| 659 | * if the transfer size is aligned to a packet boundary. | ||
| 660 | */ | ||
| 661 | if ((count & (dev->ep_in->maxpacket - 1)) == 0) { | ||
| 662 | sendZLP = 1; | ||
| 663 | } | ||
| 664 | |||
| 665 | while (count > 0 || sendZLP) { | ||
| 666 | /* so we exit after sending ZLP */ | ||
| 667 | if (count == 0) | ||
| 668 | sendZLP = 0; | ||
| 669 | |||
| 670 | /* get an idle tx request to use */ | ||
| 671 | req = 0; | ||
| 672 | ret = wait_event_interruptible(dev->write_wq, | ||
| 673 | (req = mtp_req_get(dev, &dev->tx_idle)) | ||
| 674 | || dev->state != STATE_BUSY); | ||
| 675 | if (dev->state == STATE_CANCELED) { | ||
| 676 | r = -ECANCELED; | ||
| 677 | break; | ||
| 678 | } | ||
| 679 | if (!req) { | ||
| 680 | r = ret; | ||
| 681 | break; | ||
| 682 | } | ||
| 683 | |||
| 684 | if (count > MTP_BULK_BUFFER_SIZE) | ||
| 685 | xfer = MTP_BULK_BUFFER_SIZE; | ||
| 686 | else | ||
| 687 | xfer = count; | ||
| 688 | |||
| 689 | if (hdr_size) { | ||
| 690 | /* prepend MTP data header */ | ||
| 691 | header = (struct mtp_data_header *)req->buf; | ||
| 692 | header->length = __cpu_to_le32(count); | ||
| 693 | header->type = __cpu_to_le16(2); /* data packet */ | ||
| 694 | header->command = __cpu_to_le16(dev->xfer_command); | ||
| 695 | header->transaction_id = __cpu_to_le32(dev->xfer_transaction_id); | ||
| 696 | } | ||
| 697 | |||
| 698 | ret = vfs_read(filp, req->buf + hdr_size, xfer - hdr_size, &offset); | ||
| 699 | if (ret < 0) { | ||
| 700 | r = ret; | ||
| 701 | break; | ||
| 702 | } | ||
| 703 | xfer = ret + hdr_size; | ||
| 704 | hdr_size = 0; | ||
| 705 | |||
| 706 | req->length = xfer; | ||
| 707 | ret = usb_ep_queue(dev->ep_in, req, GFP_KERNEL); | ||
| 708 | if (ret < 0) { | ||
| 709 | DBG(cdev, "send_file_work: xfer error %d\n", ret); | ||
| 710 | dev->state = STATE_ERROR; | ||
| 711 | r = -EIO; | ||
| 712 | break; | ||
| 713 | } | ||
| 714 | |||
| 715 | count -= xfer; | ||
| 716 | |||
| 717 | /* zero this so we don't try to free it on error exit */ | ||
| 718 | req = 0; | ||
| 719 | } | ||
| 720 | |||
| 721 | if (req) | ||
| 722 | mtp_req_put(dev, &dev->tx_idle, req); | ||
| 723 | |||
| 724 | DBG(cdev, "send_file_work returning %d\n", r); | ||
| 725 | /* write the result */ | ||
| 726 | dev->xfer_result = r; | ||
| 727 | smp_wmb(); | ||
| 728 | } | ||
| 729 | |||
| 730 | /* read from USB and write to a local file */ | ||
| 731 | static void receive_file_work(struct work_struct *data) | ||
| 732 | { | ||
| 733 | struct mtp_dev *dev = container_of(data, struct mtp_dev, receive_file_work); | ||
| 734 | struct usb_composite_dev *cdev = dev->cdev; | ||
| 735 | struct usb_request *read_req = NULL, *write_req = NULL; | ||
| 736 | struct file *filp; | ||
| 737 | loff_t offset; | ||
| 738 | int64_t count; | ||
| 739 | int ret, cur_buf = 0; | ||
| 740 | int r = 0; | ||
| 741 | |||
| 742 | /* read our parameters */ | ||
| 743 | smp_rmb(); | ||
| 744 | filp = dev->xfer_file; | ||
| 745 | offset = dev->xfer_file_offset; | ||
| 746 | count = dev->xfer_file_length; | ||
| 747 | |||
| 748 | DBG(cdev, "receive_file_work(%lld)\n", count); | ||
| 749 | |||
| 750 | while (count > 0 || write_req) { | ||
| 751 | if (count > 0) { | ||
| 752 | /* queue a request */ | ||
| 753 | read_req = dev->rx_req[cur_buf]; | ||
| 754 | cur_buf = (cur_buf + 1) % RX_REQ_MAX; | ||
| 755 | |||
| 756 | read_req->length = (count > MTP_BULK_BUFFER_SIZE | ||
| 757 | ? MTP_BULK_BUFFER_SIZE : count); | ||
| 758 | dev->rx_done = 0; | ||
| 759 | ret = usb_ep_queue(dev->ep_out, read_req, GFP_KERNEL); | ||
| 760 | if (ret < 0) { | ||
| 761 | r = -EIO; | ||
| 762 | dev->state = STATE_ERROR; | ||
| 763 | break; | ||
| 764 | } | ||
| 765 | } | ||
| 766 | |||
| 767 | if (write_req) { | ||
| 768 | DBG(cdev, "rx %p %d\n", write_req, write_req->actual); | ||
| 769 | ret = vfs_write(filp, write_req->buf, write_req->actual, | ||
| 770 | &offset); | ||
| 771 | DBG(cdev, "vfs_write %d\n", ret); | ||
| 772 | if (ret != write_req->actual) { | ||
| 773 | r = -EIO; | ||
| 774 | dev->state = STATE_ERROR; | ||
| 775 | break; | ||
| 776 | } | ||
| 777 | write_req = NULL; | ||
| 778 | } | ||
| 779 | |||
| 780 | if (read_req) { | ||
| 781 | /* wait for our last read to complete */ | ||
| 782 | ret = wait_event_interruptible(dev->read_wq, | ||
| 783 | dev->rx_done || dev->state != STATE_BUSY); | ||
| 784 | if (dev->state == STATE_CANCELED) { | ||
| 785 | r = -ECANCELED; | ||
| 786 | if (!dev->rx_done) | ||
| 787 | usb_ep_dequeue(dev->ep_out, read_req); | ||
| 788 | break; | ||
| 789 | } | ||
| 790 | /* if xfer_file_length is 0xFFFFFFFF, then we read until | ||
| 791 | * we get a zero length packet | ||
| 792 | */ | ||
| 793 | if (count != 0xFFFFFFFF) | ||
| 794 | count -= read_req->actual; | ||
| 795 | if (read_req->actual < read_req->length) { | ||
| 796 | /* short packet is used to signal EOF for sizes > 4 gig */ | ||
| 797 | DBG(cdev, "got short packet\n"); | ||
| 798 | count = 0; | ||
| 799 | } | ||
| 800 | |||
| 801 | write_req = read_req; | ||
| 802 | read_req = NULL; | ||
| 803 | } | ||
| 804 | } | ||
| 805 | |||
| 806 | DBG(cdev, "receive_file_work returning %d\n", r); | ||
| 807 | /* write the result */ | ||
| 808 | dev->xfer_result = r; | ||
| 809 | smp_wmb(); | ||
| 810 | } | ||
| 811 | |||
| 812 | static int mtp_send_event(struct mtp_dev *dev, struct mtp_event *event) | ||
| 813 | { | ||
| 814 | struct usb_request *req= NULL; | ||
| 815 | int ret; | ||
| 816 | int length = event->length; | ||
| 817 | |||
| 818 | DBG(dev->cdev, "mtp_send_event(%d)\n", event->length); | ||
| 819 | |||
| 820 | if (length < 0 || length > INTR_BUFFER_SIZE) | ||
| 821 | return -EINVAL; | ||
| 822 | if (dev->state == STATE_OFFLINE) | ||
| 823 | return -ENODEV; | ||
| 824 | |||
| 825 | ret = wait_event_interruptible_timeout(dev->intr_wq, | ||
| 826 | (req = mtp_req_get(dev, &dev->intr_idle)), msecs_to_jiffies(1000)); | ||
| 827 | if (!req) | ||
| 828 | return -ETIME; | ||
| 829 | |||
| 830 | if (copy_from_user(req->buf, (void __user *)event->data, length)) { | ||
| 831 | mtp_req_put(dev, &dev->intr_idle, req); | ||
| 832 | return -EFAULT; | ||
| 833 | } | ||
| 834 | req->length = length; | ||
| 835 | ret = usb_ep_queue(dev->ep_intr, req, GFP_KERNEL); | ||
| 836 | if (ret) | ||
| 837 | mtp_req_put(dev, &dev->intr_idle, req); | ||
| 838 | |||
| 839 | return ret; | ||
| 840 | } | ||
| 841 | |||
| 842 | static long mtp_ioctl(struct file *fp, unsigned code, unsigned long value) | ||
| 843 | { | ||
| 844 | struct mtp_dev *dev = fp->private_data; | ||
| 845 | struct file *filp = NULL; | ||
| 846 | int ret = -EINVAL; | ||
| 847 | |||
| 848 | if (mtp_lock(&dev->ioctl_excl)) | ||
| 849 | return -EBUSY; | ||
| 850 | |||
| 851 | switch (code) { | ||
| 852 | case MTP_SEND_FILE: | ||
| 853 | case MTP_RECEIVE_FILE: | ||
| 854 | case MTP_SEND_FILE_WITH_HEADER: | ||
| 855 | { | ||
| 856 | struct mtp_file_range mfr; | ||
| 857 | struct work_struct *work; | ||
| 858 | |||
| 859 | spin_lock_irq(&dev->lock); | ||
| 860 | if (dev->state == STATE_CANCELED) { | ||
| 861 | /* report cancelation to userspace */ | ||
| 862 | dev->state = STATE_READY; | ||
| 863 | spin_unlock_irq(&dev->lock); | ||
| 864 | ret = -ECANCELED; | ||
| 865 | goto out; | ||
| 866 | } | ||
| 867 | if (dev->state == STATE_OFFLINE) { | ||
| 868 | spin_unlock_irq(&dev->lock); | ||
| 869 | ret = -ENODEV; | ||
| 870 | goto out; | ||
| 871 | } | ||
| 872 | dev->state = STATE_BUSY; | ||
| 873 | spin_unlock_irq(&dev->lock); | ||
| 874 | |||
| 875 | if (copy_from_user(&mfr, (void __user *)value, sizeof(mfr))) { | ||
| 876 | ret = -EFAULT; | ||
| 877 | goto fail; | ||
| 878 | } | ||
| 879 | /* hold a reference to the file while we are working with it */ | ||
| 880 | filp = fget(mfr.fd); | ||
| 881 | if (!filp) { | ||
| 882 | ret = -EBADF; | ||
| 883 | goto fail; | ||
| 884 | } | ||
| 885 | |||
| 886 | /* write the parameters */ | ||
| 887 | dev->xfer_file = filp; | ||
| 888 | dev->xfer_file_offset = mfr.offset; | ||
| 889 | dev->xfer_file_length = mfr.length; | ||
| 890 | smp_wmb(); | ||
| 891 | |||
| 892 | if (code == MTP_SEND_FILE_WITH_HEADER) { | ||
| 893 | work = &dev->send_file_work; | ||
| 894 | dev->xfer_send_header = 1; | ||
| 895 | dev->xfer_command = mfr.command; | ||
| 896 | dev->xfer_transaction_id = mfr.transaction_id; | ||
| 897 | } else if (code == MTP_SEND_FILE) { | ||
| 898 | work = &dev->send_file_work; | ||
| 899 | dev->xfer_send_header = 0; | ||
| 900 | } else { | ||
| 901 | work = &dev->receive_file_work; | ||
| 902 | } | ||
| 903 | |||
| 904 | /* We do the file transfer on a work queue so it will run | ||
| 905 | * in kernel context, which is necessary for vfs_read and | ||
| 906 | * vfs_write to use our buffers in the kernel address space. | ||
| 907 | */ | ||
| 908 | queue_work(dev->wq, work); | ||
| 909 | /* wait for operation to complete */ | ||
| 910 | flush_workqueue(dev->wq); | ||
| 911 | fput(filp); | ||
| 912 | |||
| 913 | /* read the result */ | ||
| 914 | smp_rmb(); | ||
| 915 | ret = dev->xfer_result; | ||
| 916 | break; | ||
| 917 | } | ||
| 918 | case MTP_SEND_EVENT: | ||
| 919 | { | ||
| 920 | struct mtp_event event; | ||
| 921 | /* return here so we don't change dev->state below, | ||
| 922 | * which would interfere with bulk transfer state. | ||
| 923 | */ | ||
| 924 | if (copy_from_user(&event, (void __user *)value, sizeof(event))) | ||
| 925 | ret = -EFAULT; | ||
| 926 | else | ||
| 927 | ret = mtp_send_event(dev, &event); | ||
| 928 | goto out; | ||
| 929 | } | ||
| 930 | } | ||
| 931 | |||
| 932 | fail: | ||
| 933 | spin_lock_irq(&dev->lock); | ||
| 934 | if (dev->state == STATE_CANCELED) | ||
| 935 | ret = -ECANCELED; | ||
| 936 | else if (dev->state != STATE_OFFLINE) | ||
| 937 | dev->state = STATE_READY; | ||
| 938 | spin_unlock_irq(&dev->lock); | ||
| 939 | out: | ||
| 940 | mtp_unlock(&dev->ioctl_excl); | ||
| 941 | DBG(dev->cdev, "ioctl returning %d\n", ret); | ||
| 942 | return ret; | ||
| 943 | } | ||
| 944 | |||
| 945 | static int mtp_open(struct inode *ip, struct file *fp) | ||
| 946 | { | ||
| 947 | printk(KERN_INFO "mtp_open\n"); | ||
| 948 | if (mtp_lock(&_mtp_dev->open_excl)) | ||
| 949 | return -EBUSY; | ||
| 950 | |||
| 951 | /* clear any error condition */ | ||
| 952 | if (_mtp_dev->state != STATE_OFFLINE) | ||
| 953 | _mtp_dev->state = STATE_READY; | ||
| 954 | |||
| 955 | fp->private_data = _mtp_dev; | ||
| 956 | return 0; | ||
| 957 | } | ||
| 958 | |||
| 959 | static int mtp_release(struct inode *ip, struct file *fp) | ||
| 960 | { | ||
| 961 | printk(KERN_INFO "mtp_release\n"); | ||
| 962 | |||
| 963 | mtp_unlock(&_mtp_dev->open_excl); | ||
| 964 | return 0; | ||
| 965 | } | ||
| 966 | |||
| 967 | /* file operations for /dev/mtp_usb */ | ||
| 968 | static const struct file_operations mtp_fops = { | ||
| 969 | .owner = THIS_MODULE, | ||
| 970 | .read = mtp_read, | ||
| 971 | .write = mtp_write, | ||
| 972 | .unlocked_ioctl = mtp_ioctl, | ||
| 973 | .open = mtp_open, | ||
| 974 | .release = mtp_release, | ||
| 975 | }; | ||
| 976 | |||
| 977 | static struct miscdevice mtp_device = { | ||
| 978 | .minor = MISC_DYNAMIC_MINOR, | ||
| 979 | .name = mtp_shortname, | ||
| 980 | .fops = &mtp_fops, | ||
| 981 | }; | ||
| 982 | |||
| 983 | static int mtp_ctrlrequest(struct usb_composite_dev *cdev, | ||
| 984 | const struct usb_ctrlrequest *ctrl) | ||
| 985 | { | ||
| 986 | struct mtp_dev *dev = _mtp_dev; | ||
| 987 | int value = -EOPNOTSUPP; | ||
| 988 | u16 w_index = le16_to_cpu(ctrl->wIndex); | ||
| 989 | u16 w_value = le16_to_cpu(ctrl->wValue); | ||
| 990 | u16 w_length = le16_to_cpu(ctrl->wLength); | ||
| 991 | unsigned long flags; | ||
| 992 | |||
| 993 | VDBG(cdev, "mtp_ctrlrequest " | ||
| 994 | "%02x.%02x v%04x i%04x l%u\n", | ||
| 995 | ctrl->bRequestType, ctrl->bRequest, | ||
| 996 | w_value, w_index, w_length); | ||
| 997 | |||
| 998 | /* Handle MTP OS string */ | ||
| 999 | if (ctrl->bRequestType == | ||
| 1000 | (USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE) | ||
| 1001 | && ctrl->bRequest == USB_REQ_GET_DESCRIPTOR | ||
| 1002 | && (w_value >> 8) == USB_DT_STRING | ||
| 1003 | && (w_value & 0xFF) == MTP_OS_STRING_ID) { | ||
| 1004 | value = (w_length < sizeof(mtp_os_string) | ||
| 1005 | ? w_length : sizeof(mtp_os_string)); | ||
| 1006 | memcpy(cdev->req->buf, mtp_os_string, value); | ||
| 1007 | } else if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_VENDOR) { | ||
| 1008 | /* Handle MTP OS descriptor */ | ||
| 1009 | DBG(cdev, "vendor request: %d index: %d value: %d length: %d\n", | ||
| 1010 | ctrl->bRequest, w_index, w_value, w_length); | ||
| 1011 | |||
| 1012 | if (ctrl->bRequest == 1 | ||
| 1013 | && (ctrl->bRequestType & USB_DIR_IN) | ||
| 1014 | && (w_index == 4 || w_index == 5)) { | ||
| 1015 | value = (w_length < sizeof(mtp_ext_config_desc) ? | ||
| 1016 | w_length : sizeof(mtp_ext_config_desc)); | ||
| 1017 | memcpy(cdev->req->buf, &mtp_ext_config_desc, value); | ||
| 1018 | } | ||
| 1019 | } else if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_CLASS) { | ||
| 1020 | DBG(cdev, "class request: %d index: %d value: %d length: %d\n", | ||
| 1021 | ctrl->bRequest, w_index, w_value, w_length); | ||
| 1022 | |||
| 1023 | if (ctrl->bRequest == MTP_REQ_CANCEL && w_index == 0 | ||
| 1024 | && w_value == 0) { | ||
| 1025 | DBG(cdev, "MTP_REQ_CANCEL\n"); | ||
| 1026 | |||
| 1027 | spin_lock_irqsave(&dev->lock, flags); | ||
| 1028 | if (dev->state == STATE_BUSY) { | ||
| 1029 | dev->state = STATE_CANCELED; | ||
| 1030 | wake_up(&dev->read_wq); | ||
| 1031 | wake_up(&dev->write_wq); | ||
| 1032 | } | ||
| 1033 | spin_unlock_irqrestore(&dev->lock, flags); | ||
| 1034 | |||
| 1035 | /* We need to queue a request to read the remaining | ||
| 1036 | * bytes, but we don't actually need to look at | ||
| 1037 | * the contents. | ||
| 1038 | */ | ||
| 1039 | value = w_length; | ||
| 1040 | } else if (ctrl->bRequest == MTP_REQ_GET_DEVICE_STATUS | ||
| 1041 | && w_index == 0 && w_value == 0) { | ||
| 1042 | struct mtp_device_status *status = cdev->req->buf; | ||
| 1043 | status->wLength = | ||
| 1044 | __constant_cpu_to_le16(sizeof(*status)); | ||
| 1045 | |||
| 1046 | DBG(cdev, "MTP_REQ_GET_DEVICE_STATUS\n"); | ||
| 1047 | spin_lock_irqsave(&dev->lock, flags); | ||
| 1048 | /* device status is "busy" until we report | ||
| 1049 | * the cancelation to userspace | ||
| 1050 | */ | ||
| 1051 | if (dev->state == STATE_CANCELED) | ||
| 1052 | status->wCode = | ||
| 1053 | __cpu_to_le16(MTP_RESPONSE_DEVICE_BUSY); | ||
| 1054 | else | ||
| 1055 | status->wCode = | ||
| 1056 | __cpu_to_le16(MTP_RESPONSE_OK); | ||
| 1057 | spin_unlock_irqrestore(&dev->lock, flags); | ||
| 1058 | value = sizeof(*status); | ||
| 1059 | } | ||
| 1060 | } | ||
| 1061 | |||
| 1062 | /* respond with data transfer or status phase? */ | ||
| 1063 | if (value >= 0) { | ||
| 1064 | int rc; | ||
| 1065 | cdev->req->zero = value < w_length; | ||
| 1066 | cdev->req->length = value; | ||
| 1067 | rc = usb_ep_queue(cdev->gadget->ep0, cdev->req, GFP_ATOMIC); | ||
| 1068 | if (rc < 0) | ||
| 1069 | ERROR(cdev, "%s setup response queue error\n", __func__); | ||
| 1070 | } | ||
| 1071 | return value; | ||
| 1072 | } | ||
| 1073 | |||
| 1074 | static int | ||
| 1075 | mtp_function_bind(struct usb_configuration *c, struct usb_function *f) | ||
| 1076 | { | ||
| 1077 | struct usb_composite_dev *cdev = c->cdev; | ||
| 1078 | struct mtp_dev *dev = func_to_mtp(f); | ||
| 1079 | int id; | ||
| 1080 | int ret; | ||
| 1081 | |||
| 1082 | dev->cdev = cdev; | ||
| 1083 | DBG(cdev, "mtp_function_bind dev: %p\n", dev); | ||
| 1084 | |||
| 1085 | /* allocate interface ID(s) */ | ||
| 1086 | id = usb_interface_id(c, f); | ||
| 1087 | if (id < 0) | ||
| 1088 | return id; | ||
| 1089 | mtp_interface_desc.bInterfaceNumber = id; | ||
| 1090 | |||
| 1091 | /* allocate endpoints */ | ||
| 1092 | ret = mtp_create_bulk_endpoints(dev, &mtp_fullspeed_in_desc, | ||
| 1093 | &mtp_fullspeed_out_desc, &mtp_intr_desc); | ||
| 1094 | if (ret) | ||
| 1095 | return ret; | ||
| 1096 | |||
| 1097 | /* support high speed hardware */ | ||
| 1098 | if (gadget_is_dualspeed(c->cdev->gadget)) { | ||
| 1099 | mtp_highspeed_in_desc.bEndpointAddress = | ||
| 1100 | mtp_fullspeed_in_desc.bEndpointAddress; | ||
| 1101 | mtp_highspeed_out_desc.bEndpointAddress = | ||
| 1102 | mtp_fullspeed_out_desc.bEndpointAddress; | ||
| 1103 | } | ||
| 1104 | |||
| 1105 | DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n", | ||
| 1106 | gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", | ||
| 1107 | f->name, dev->ep_in->name, dev->ep_out->name); | ||
| 1108 | return 0; | ||
| 1109 | } | ||
| 1110 | |||
| 1111 | static void | ||
| 1112 | mtp_function_unbind(struct usb_configuration *c, struct usb_function *f) | ||
| 1113 | { | ||
| 1114 | struct mtp_dev *dev = func_to_mtp(f); | ||
| 1115 | struct usb_request *req; | ||
| 1116 | int i; | ||
| 1117 | |||
| 1118 | while ((req = mtp_req_get(dev, &dev->tx_idle))) | ||
| 1119 | mtp_request_free(req, dev->ep_in); | ||
| 1120 | for (i = 0; i < RX_REQ_MAX; i++) | ||
| 1121 | mtp_request_free(dev->rx_req[i], dev->ep_out); | ||
| 1122 | while ((req = mtp_req_get(dev, &dev->intr_idle))) | ||
| 1123 | mtp_request_free(req, dev->ep_intr); | ||
| 1124 | dev->state = STATE_OFFLINE; | ||
| 1125 | } | ||
| 1126 | |||
| 1127 | static int mtp_function_set_alt(struct usb_function *f, | ||
| 1128 | unsigned intf, unsigned alt) | ||
| 1129 | { | ||
| 1130 | struct mtp_dev *dev = func_to_mtp(f); | ||
| 1131 | struct usb_composite_dev *cdev = f->config->cdev; | ||
| 1132 | int ret; | ||
| 1133 | |||
| 1134 | DBG(cdev, "mtp_function_set_alt intf: %d alt: %d\n", intf, alt); | ||
| 1135 | config_ep_by_speed(cdev->gadget, f, dev->ep_in); | ||
| 1136 | ret = usb_ep_enable(dev->ep_in); | ||
| 1137 | if (ret) | ||
| 1138 | return ret; | ||
| 1139 | config_ep_by_speed(cdev->gadget, f, dev->ep_out); | ||
| 1140 | ret = usb_ep_enable(dev->ep_out); | ||
| 1141 | if (ret) { | ||
| 1142 | usb_ep_disable(dev->ep_in); | ||
| 1143 | return ret; | ||
| 1144 | } | ||
| 1145 | dev->ep_intr->desc = &mtp_intr_desc; | ||
| 1146 | ret = usb_ep_enable(dev->ep_intr); | ||
| 1147 | if (ret) { | ||
| 1148 | usb_ep_disable(dev->ep_out); | ||
| 1149 | usb_ep_disable(dev->ep_in); | ||
| 1150 | return ret; | ||
| 1151 | } | ||
| 1152 | dev->state = STATE_READY; | ||
| 1153 | |||
| 1154 | /* readers may be blocked waiting for us to go online */ | ||
| 1155 | wake_up(&dev->read_wq); | ||
| 1156 | return 0; | ||
| 1157 | } | ||
| 1158 | |||
| 1159 | static void mtp_function_disable(struct usb_function *f) | ||
| 1160 | { | ||
| 1161 | struct mtp_dev *dev = func_to_mtp(f); | ||
| 1162 | struct usb_composite_dev *cdev = dev->cdev; | ||
| 1163 | |||
| 1164 | DBG(cdev, "mtp_function_disable\n"); | ||
| 1165 | dev->state = STATE_OFFLINE; | ||
| 1166 | usb_ep_disable(dev->ep_in); | ||
| 1167 | usb_ep_disable(dev->ep_out); | ||
| 1168 | usb_ep_disable(dev->ep_intr); | ||
| 1169 | |||
| 1170 | /* readers may be blocked waiting for us to go online */ | ||
| 1171 | wake_up(&dev->read_wq); | ||
| 1172 | |||
| 1173 | VDBG(cdev, "%s disabled\n", dev->function.name); | ||
| 1174 | } | ||
| 1175 | |||
| 1176 | static int mtp_bind_config(struct usb_configuration *c, bool ptp_config) | ||
| 1177 | { | ||
| 1178 | struct mtp_dev *dev = _mtp_dev; | ||
| 1179 | int ret = 0; | ||
| 1180 | |||
| 1181 | printk(KERN_INFO "mtp_bind_config\n"); | ||
| 1182 | |||
| 1183 | /* allocate a string ID for our interface */ | ||
| 1184 | if (mtp_string_defs[INTERFACE_STRING_INDEX].id == 0) { | ||
| 1185 | ret = usb_string_id(c->cdev); | ||
| 1186 | if (ret < 0) | ||
| 1187 | return ret; | ||
| 1188 | mtp_string_defs[INTERFACE_STRING_INDEX].id = ret; | ||
| 1189 | mtp_interface_desc.iInterface = ret; | ||
| 1190 | } | ||
| 1191 | |||
| 1192 | dev->cdev = c->cdev; | ||
| 1193 | dev->function.name = "mtp"; | ||
| 1194 | dev->function.strings = mtp_strings; | ||
| 1195 | if (ptp_config) { | ||
| 1196 | dev->function.descriptors = fs_ptp_descs; | ||
| 1197 | dev->function.hs_descriptors = hs_ptp_descs; | ||
| 1198 | } else { | ||
| 1199 | dev->function.descriptors = fs_mtp_descs; | ||
| 1200 | dev->function.hs_descriptors = hs_mtp_descs; | ||
| 1201 | } | ||
| 1202 | dev->function.bind = mtp_function_bind; | ||
| 1203 | dev->function.unbind = mtp_function_unbind; | ||
| 1204 | dev->function.set_alt = mtp_function_set_alt; | ||
| 1205 | dev->function.disable = mtp_function_disable; | ||
| 1206 | |||
| 1207 | return usb_add_function(c, &dev->function); | ||
| 1208 | } | ||
| 1209 | |||
| 1210 | static int mtp_setup(void) | ||
| 1211 | { | ||
| 1212 | struct mtp_dev *dev; | ||
| 1213 | int ret; | ||
| 1214 | |||
| 1215 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||
| 1216 | if (!dev) | ||
| 1217 | return -ENOMEM; | ||
| 1218 | |||
| 1219 | spin_lock_init(&dev->lock); | ||
| 1220 | init_waitqueue_head(&dev->read_wq); | ||
| 1221 | init_waitqueue_head(&dev->write_wq); | ||
| 1222 | init_waitqueue_head(&dev->intr_wq); | ||
| 1223 | atomic_set(&dev->open_excl, 0); | ||
| 1224 | atomic_set(&dev->ioctl_excl, 0); | ||
| 1225 | INIT_LIST_HEAD(&dev->tx_idle); | ||
| 1226 | INIT_LIST_HEAD(&dev->intr_idle); | ||
| 1227 | |||
| 1228 | dev->wq = create_singlethread_workqueue("f_mtp"); | ||
| 1229 | if (!dev->wq) { | ||
| 1230 | ret = -ENOMEM; | ||
| 1231 | goto err1; | ||
| 1232 | } | ||
| 1233 | INIT_WORK(&dev->send_file_work, send_file_work); | ||
| 1234 | INIT_WORK(&dev->receive_file_work, receive_file_work); | ||
| 1235 | |||
| 1236 | _mtp_dev = dev; | ||
| 1237 | |||
| 1238 | ret = misc_register(&mtp_device); | ||
| 1239 | if (ret) | ||
| 1240 | goto err2; | ||
| 1241 | |||
| 1242 | return 0; | ||
| 1243 | |||
| 1244 | err2: | ||
| 1245 | destroy_workqueue(dev->wq); | ||
| 1246 | err1: | ||
| 1247 | _mtp_dev = NULL; | ||
| 1248 | kfree(dev); | ||
| 1249 | printk(KERN_ERR "mtp gadget driver failed to initialize\n"); | ||
| 1250 | return ret; | ||
| 1251 | } | ||
| 1252 | |||
| 1253 | static void mtp_cleanup(void) | ||
| 1254 | { | ||
| 1255 | struct mtp_dev *dev = _mtp_dev; | ||
| 1256 | |||
| 1257 | if (!dev) | ||
| 1258 | return; | ||
| 1259 | |||
| 1260 | misc_deregister(&mtp_device); | ||
| 1261 | destroy_workqueue(dev->wq); | ||
| 1262 | _mtp_dev = NULL; | ||
| 1263 | kfree(dev); | ||
| 1264 | } | ||
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c new file mode 100644 index 00000000000..639e14a2fd1 --- /dev/null +++ b/drivers/usb/gadget/file_storage.c | |||
| @@ -0,0 +1,3631 @@ | |||
| 1 | /* | ||
| 2 | * file_storage.c -- File-backed USB Storage Gadget, for USB development | ||
| 3 | * | ||
| 4 | * Copyright (C) 2003-2008 Alan Stern | ||
| 5 | * All rights reserved. | ||
| 6 | * | ||
| 7 | * Redistribution and use in source and binary forms, with or without | ||
| 8 | * modification, are permitted provided that the following conditions | ||
| 9 | * are met: | ||
| 10 | * 1. Redistributions of source code must retain the above copyright | ||
| 11 | * notice, this list of conditions, and the following disclaimer, | ||
| 12 | * without modification. | ||
| 13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
| 14 | * notice, this list of conditions and the following disclaimer in the | ||
| 15 | * documentation and/or other materials provided with the distribution. | ||
| 16 | * 3. The names of the above-listed copyright holders may not be used | ||
| 17 | * to endorse or promote products derived from this software without | ||
| 18 | * specific prior written permission. | ||
| 19 | * | ||
| 20 | * ALTERNATIVELY, this software may be distributed under the terms of the | ||
| 21 | * GNU General Public License ("GPL") as published by the Free Software | ||
| 22 | * Foundation, either version 2 of that License or (at your option) any | ||
| 23 | * later version. | ||
| 24 | * | ||
| 25 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | ||
| 26 | * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | ||
| 27 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | ||
| 28 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||
| 29 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||
| 30 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||
| 31 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||
| 32 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
| 33 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||
| 34 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
| 35 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 36 | */ | ||
| 37 | |||
| 38 | |||
| 39 | /* | ||
| 40 | * The File-backed Storage Gadget acts as a USB Mass Storage device, | ||
| 41 | * appearing to the host as a disk drive or as a CD-ROM drive. In addition | ||
| 42 | * to providing an example of a genuinely useful gadget driver for a USB | ||
| 43 | * device, it also illustrates a technique of double-buffering for increased | ||
| 44 | * throughput. Last but not least, it gives an easy way to probe the | ||
| 45 | * behavior of the Mass Storage drivers in a USB host. | ||
| 46 | * | ||
| 47 | * Backing storage is provided by a regular file or a block device, specified | ||
| 48 | * by the "file" module parameter. Access can be limited to read-only by | ||
| 49 | * setting the optional "ro" module parameter. (For CD-ROM emulation, | ||
| 50 | * access is always read-only.) The gadget will indicate that it has | ||
| 51 | * removable media if the optional "removable" module parameter is set. | ||
| 52 | * | ||
| 53 | * The gadget supports the Control-Bulk (CB), Control-Bulk-Interrupt (CBI), | ||
| 54 | * and Bulk-Only (also known as Bulk-Bulk-Bulk or BBB) transports, selected | ||
| 55 | * by the optional "transport" module parameter. It also supports the | ||
| 56 | * following protocols: RBC (0x01), ATAPI or SFF-8020i (0x02), QIC-157 (0c03), | ||
| 57 | * UFI (0x04), SFF-8070i (0x05), and transparent SCSI (0x06), selected by | ||
| 58 | * the optional "protocol" module parameter. In addition, the default | ||
| 59 | * Vendor ID, Product ID, release number and serial number can be overridden. | ||
| 60 | * | ||
| 61 | * There is support for multiple logical units (LUNs), each of which has | ||
| 62 | * its own backing file. The number of LUNs can be set using the optional | ||
| 63 | * "luns" module parameter (anywhere from 1 to 8), and the corresponding | ||
| 64 | * files are specified using comma-separated lists for "file" and "ro". | ||
| 65 | * The default number of LUNs is taken from the number of "file" elements; | ||
| 66 | * it is 1 if "file" is not given. If "removable" is not set then a backing | ||
| 67 | * file must be specified for each LUN. If it is set, then an unspecified | ||
| 68 | * or empty backing filename means the LUN's medium is not loaded. Ideally | ||
| 69 | * each LUN would be settable independently as a disk drive or a CD-ROM | ||
| 70 | * drive, but currently all LUNs have to be the same type. The CD-ROM | ||
| 71 | * emulation includes a single data track and no audio tracks; hence there | ||
| 72 | * need be only one backing file per LUN. Note also that the CD-ROM block | ||
| 73 | * length is set to 512 rather than the more common value 2048. | ||
| 74 | * | ||
| 75 | * Requirements are modest; only a bulk-in and a bulk-out endpoint are | ||
| 76 | * needed (an interrupt-out endpoint is also needed for CBI). The memory | ||
| 77 | * requirement amounts to two 16K buffers, size configurable by a parameter. | ||
| 78 | * Support is included for both full-speed and high-speed operation. | ||
| 79 | * | ||
| 80 | * Note that the driver is slightly non-portable in that it assumes a | ||
| 81 | * single memory/DMA buffer will be useable for bulk-in, bulk-out, and | ||
| 82 | * interrupt-in endpoints. With most device controllers this isn't an | ||
| 83 | * issue, but there may be some with hardware restrictions that prevent | ||
| 84 | * a buffer from being used by more than one endpoint. | ||
| 85 | * | ||
| 86 | * Module options: | ||
| 87 | * | ||
| 88 | * file=filename[,filename...] | ||
| 89 | * Required if "removable" is not set, names of | ||
| 90 | * the files or block devices used for | ||
| 91 | * backing storage | ||
| 92 | * serial=HHHH... Required serial number (string of hex chars) | ||
| 93 | * ro=b[,b...] Default false, booleans for read-only access | ||
| 94 | * removable Default false, boolean for removable media | ||
| 95 | * luns=N Default N = number of filenames, number of | ||
| 96 | * LUNs to support | ||
| 97 | * nofua=b[,b...] Default false, booleans for ignore FUA flag | ||
| 98 | * in SCSI WRITE(10,12) commands | ||
| 99 | * stall Default determined according to the type of | ||
| 100 | * USB device controller (usually true), | ||
| 101 | * boolean to permit the driver to halt | ||
| 102 | * bulk endpoints | ||
| 103 | * cdrom Default false, boolean for whether to emulate | ||
| 104 | * a CD-ROM drive | ||
| 105 | * transport=XXX Default BBB, transport name (CB, CBI, or BBB) | ||
| 106 | * protocol=YYY Default SCSI, protocol name (RBC, 8020 or | ||
| 107 | * ATAPI, QIC, UFI, 8070, or SCSI; | ||
| 108 | * also 1 - 6) | ||
| 109 | * vendor=0xVVVV Default 0x0525 (NetChip), USB Vendor ID | ||
| 110 | * product=0xPPPP Default 0xa4a5 (FSG), USB Product ID | ||
| 111 | * release=0xRRRR Override the USB release number (bcdDevice) | ||
| 112 | * buflen=N Default N=16384, buffer size used (will be | ||
| 113 | * rounded down to a multiple of | ||
| 114 | * PAGE_CACHE_SIZE) | ||
| 115 | * | ||
| 116 | * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file", "serial", "ro", | ||
| 117 | * "removable", "luns", "nofua", "stall", and "cdrom" options are available; | ||
| 118 | * default values are used for everything else. | ||
| 119 | * | ||
| 120 | * The pathnames of the backing files and the ro settings are available in | ||
| 121 | * the attribute files "file", "nofua", and "ro" in the lun<n> subdirectory of | ||
| 122 | * the gadget's sysfs directory. If the "removable" option is set, writing to | ||
| 123 | * these files will simulate ejecting/loading the medium (writing an empty | ||
| 124 | * line means eject) and adjusting a write-enable tab. Changes to the ro | ||
| 125 | * setting are not allowed when the medium is loaded or if CD-ROM emulation | ||
| 126 | * is being used. | ||
| 127 | * | ||
| 128 | * This gadget driver is heavily based on "Gadget Zero" by David Brownell. | ||
| 129 | * The driver's SCSI command interface was based on the "Information | ||
| 130 | * technology - Small Computer System Interface - 2" document from | ||
| 131 | * X3T9.2 Project 375D, Revision 10L, 7-SEP-93, available at | ||
| 132 | * <http://www.t10.org/ftp/t10/drafts/s2/s2-r10l.pdf>. The single exception | ||
| 133 | * is opcode 0x23 (READ FORMAT CAPACITIES), which was based on the | ||
| 134 | * "Universal Serial Bus Mass Storage Class UFI Command Specification" | ||
| 135 | * document, Revision 1.0, December 14, 1998, available at | ||
| 136 | * <http://www.usb.org/developers/devclass_docs/usbmass-ufi10.pdf>. | ||
| 137 | */ | ||
| 138 | |||
| 139 | |||
| 140 | /* | ||
| 141 | * Driver Design | ||
| 142 | * | ||
| 143 | * The FSG driver is fairly straightforward. There is a main kernel | ||
| 144 | * thread that handles most of the work. Interrupt routines field | ||
| 145 | * callbacks from the controller driver: bulk- and interrupt-request | ||
| 146 | * completion notifications, endpoint-0 events, and disconnect events. | ||
| 147 | * Completion events are passed to the main thread by wakeup calls. Many | ||
| 148 | * ep0 requests are handled at interrupt time, but SetInterface, | ||
| 149 | * SetConfiguration, and device reset requests are forwarded to the | ||
| 150 | * thread in the form of "exceptions" using SIGUSR1 signals (since they | ||
| 151 | * should interrupt any ongoing file I/O operations). | ||
| 152 | * | ||
| 153 | * The thread's main routine implements the standard command/data/status | ||
| 154 | * parts of a SCSI interaction. It and its subroutines are full of tests | ||
| 155 | * for pending signals/exceptions -- all this polling is necessary since | ||
| 156 | * the kernel has no setjmp/longjmp equivalents. (Maybe this is an | ||
| 157 | * indication that the driver really wants to be running in userspace.) | ||
| 158 | * An important point is that so long as the thread is alive it keeps an | ||
| 159 | * open reference to the backing file. This will prevent unmounting | ||
| 160 | * the backing file's underlying filesystem and could cause problems | ||
| 161 | * during system shutdown, for example. To prevent such problems, the | ||
| 162 | * thread catches INT, TERM, and KILL signals and converts them into | ||
| 163 | * an EXIT exception. | ||
| 164 | * | ||
| 165 | * In normal operation the main thread is started during the gadget's | ||
| 166 | * fsg_bind() callback and stopped during fsg_unbind(). But it can also | ||
| 167 | * exit when it receives a signal, and there's no point leaving the | ||
| 168 | * gadget running when the thread is dead. So just before the thread | ||
| 169 | * exits, it deregisters the gadget driver. This makes things a little | ||
| 170 | * tricky: The driver is deregistered at two places, and the exiting | ||
| 171 | * thread can indirectly call fsg_unbind() which in turn can tell the | ||
| 172 | * thread to exit. The first problem is resolved through the use of the | ||
| 173 | * REGISTERED atomic bitflag; the driver will only be deregistered once. | ||
| 174 | * The second problem is resolved by having fsg_unbind() check | ||
| 175 | * fsg->state; it won't try to stop the thread if the state is already | ||
| 176 | * FSG_STATE_TERMINATED. | ||
| 177 | * | ||
| 178 | * To provide maximum throughput, the driver uses a circular pipeline of | ||
| 179 | * buffer heads (struct fsg_buffhd). In principle the pipeline can be | ||
| 180 | * arbitrarily long; in practice the benefits don't justify having more | ||
| 181 | * than 2 stages (i.e., double buffering). But it helps to think of the | ||
| 182 | * pipeline as being a long one. Each buffer head contains a bulk-in and | ||
| 183 | * a bulk-out request pointer (since the buffer can be used for both | ||
| 184 | * output and input -- directions always are given from the host's | ||
| 185 | * point of view) as well as a pointer to the buffer and various state | ||
| 186 | * variables. | ||
| 187 | * | ||
| 188 | * Use of the pipeline follows a simple protocol. There is a variable | ||
| 189 | * (fsg->next_buffhd_to_fill) that points to the next buffer head to use. | ||
| 190 | * At any time that buffer head may still be in use from an earlier | ||
| 191 | * request, so each buffer head has a state variable indicating whether | ||
| 192 | * it is EMPTY, FULL, or BUSY. Typical use involves waiting for the | ||
| 193 | * buffer head to be EMPTY, filling the buffer either by file I/O or by | ||
| 194 | * USB I/O (during which the buffer head is BUSY), and marking the buffer | ||
| 195 | * head FULL when the I/O is complete. Then the buffer will be emptied | ||
| 196 | * (again possibly by USB I/O, during which it is marked BUSY) and | ||
| 197 | * finally marked EMPTY again (possibly by a completion routine). | ||
| 198 | * | ||
| 199 | * A module parameter tells the driver to avoid stalling the bulk | ||
| 200 | * endpoints wherever the transport specification allows. This is | ||
| 201 | * necessary for some UDCs like the SuperH, which cannot reliably clear a | ||
| 202 | * halt on a bulk endpoint. However, under certain circumstances the | ||
| 203 | * Bulk-only specification requires a stall. In such cases the driver | ||
| 204 | * will halt the endpoint and set a flag indicating that it should clear | ||
| 205 | * the halt in software during the next device reset. Hopefully this | ||
| 206 | * will permit everything to work correctly. Furthermore, although the | ||
| 207 | * specification allows the bulk-out endpoint to halt when the host sends | ||
| 208 | * too much data, implementing this would cause an unavoidable race. | ||
| 209 | * The driver will always use the "no-stall" approach for OUT transfers. | ||
| 210 | * | ||
| 211 | * One subtle point concerns sending status-stage responses for ep0 | ||
| 212 | * requests. Some of these requests, such as device reset, can involve | ||
| 213 | * interrupting an ongoing file I/O operation, which might take an | ||
| 214 | * arbitrarily long time. During that delay the host might give up on | ||
| 215 | * the original ep0 request and issue a new one. When that happens the | ||
| 216 | * driver should not notify the host about completion of the original | ||
| 217 | * request, as the host will no longer be waiting for it. So the driver | ||
| 218 | * assigns to each ep0 request a unique tag, and it keeps track of the | ||
| 219 | * tag value of the request associated with a long-running exception | ||
| 220 | * (device-reset, interface-change, or configuration-change). When the | ||
| 221 | * exception handler is finished, the status-stage response is submitted | ||
| 222 | * only if the current ep0 request tag is equal to the exception request | ||
| 223 | * tag. Thus only the most recently received ep0 request will get a | ||
| 224 | * status-stage response. | ||
| 225 | * | ||
| 226 | * Warning: This driver source file is too long. It ought to be split up | ||
| 227 | * into a header file plus about 3 separate .c files, to handle the details | ||
| 228 | * of the Gadget, USB Mass Storage, and SCSI protocols. | ||
| 229 | */ | ||
| 230 | |||
| 231 | |||
| 232 | /* #define VERBOSE_DEBUG */ | ||
| 233 | /* #define DUMP_MSGS */ | ||
| 234 | |||
| 235 | |||
| 236 | #include <linux/blkdev.h> | ||
| 237 | #include <linux/completion.h> | ||
| 238 | #include <linux/dcache.h> | ||
| 239 | #include <linux/delay.h> | ||
| 240 | #include <linux/device.h> | ||
| 241 | #include <linux/fcntl.h> | ||
| 242 | #include <linux/file.h> | ||
| 243 | #include <linux/fs.h> | ||
| 244 | #include <linux/kref.h> | ||
| 245 | #include <linux/kthread.h> | ||
| 246 | #include <linux/limits.h> | ||
| 247 | #include <linux/rwsem.h> | ||
| 248 | #include <linux/slab.h> | ||
| 249 | #include <linux/spinlock.h> | ||
| 250 | #include <linux/string.h> | ||
| 251 | #include <linux/freezer.h> | ||
| 252 | #include <linux/utsname.h> | ||
| 253 | |||
| 254 | #include <linux/usb/ch9.h> | ||
| 255 | #include <linux/usb/gadget.h> | ||
| 256 | |||
| 257 | #include "gadget_chips.h" | ||
| 258 | |||
| 259 | |||
| 260 | |||
| 261 | /* | ||
| 262 | * Kbuild is not very cooperative with respect to linking separately | ||
| 263 | * compiled library objects into one module. So for now we won't use | ||
| 264 | * separate compilation ... ensuring init/exit sections work to shrink | ||
| 265 | * the runtime footprint, and giving us at least some parts of what | ||
| 266 | * a "gcc --combine ... part1.c part2.c part3.c ... " build would. | ||
| 267 | */ | ||
| 268 | #include "usbstring.c" | ||
| 269 | #include "config.c" | ||
| 270 | #include "epautoconf.c" | ||
| 271 | |||
| 272 | /*-------------------------------------------------------------------------*/ | ||
| 273 | |||
| 274 | #define DRIVER_DESC "File-backed Storage Gadget" | ||
| 275 | #define DRIVER_NAME "g_file_storage" | ||
| 276 | #define DRIVER_VERSION "1 September 2010" | ||
| 277 | |||
| 278 | static char fsg_string_manufacturer[64]; | ||
| 279 | static const char fsg_string_product[] = DRIVER_DESC; | ||
| 280 | static const char fsg_string_config[] = "Self-powered"; | ||
| 281 | static const char fsg_string_interface[] = "Mass Storage"; | ||
| 282 | |||
| 283 | |||
| 284 | #include "storage_common.c" | ||
| 285 | |||
| 286 | |||
| 287 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
| 288 | MODULE_AUTHOR("Alan Stern"); | ||
| 289 | MODULE_LICENSE("Dual BSD/GPL"); | ||
| 290 | |||
| 291 | /* | ||
| 292 | * This driver assumes self-powered hardware and has no way for users to | ||
| 293 | * trigger remote wakeup. It uses autoconfiguration to select endpoints | ||
| 294 | * and endpoint addresses. | ||
| 295 | */ | ||
| 296 | |||
| 297 | |||
| 298 | /*-------------------------------------------------------------------------*/ | ||
| 299 | |||
| 300 | |||
| 301 | /* Encapsulate the module parameter settings */ | ||
| 302 | |||
| 303 | static struct { | ||
| 304 | char *file[FSG_MAX_LUNS]; | ||
| 305 | char *serial; | ||
| 306 | int ro[FSG_MAX_LUNS]; | ||
| 307 | int nofua[FSG_MAX_LUNS]; | ||
| 308 | unsigned int num_filenames; | ||
| 309 | unsigned int num_ros; | ||
| 310 | unsigned int num_nofuas; | ||
| 311 | unsigned int nluns; | ||
| 312 | |||
| 313 | int removable; | ||
| 314 | int can_stall; | ||
| 315 | int cdrom; | ||
| 316 | |||
| 317 | char *transport_parm; | ||
| 318 | char *protocol_parm; | ||
| 319 | unsigned short vendor; | ||
| 320 | unsigned short product; | ||
| 321 | unsigned short release; | ||
| 322 | unsigned int buflen; | ||
| 323 | |||
| 324 | int transport_type; | ||
| 325 | char *transport_name; | ||
| 326 | int protocol_type; | ||
| 327 | char *protocol_name; | ||
| 328 | |||
| 329 | } mod_data = { // Default values | ||
| 330 | .transport_parm = "BBB", | ||
| 331 | .protocol_parm = "SCSI", | ||
| 332 | .removable = 0, | ||
| 333 | .can_stall = 1, | ||
| 334 | .cdrom = 0, | ||
| 335 | .vendor = FSG_VENDOR_ID, | ||
| 336 | .product = FSG_PRODUCT_ID, | ||
| 337 | .release = 0xffff, // Use controller chip type | ||
| 338 | .buflen = 16384, | ||
| 339 | }; | ||
| 340 | |||
| 341 | |||
| 342 | module_param_array_named(file, mod_data.file, charp, &mod_data.num_filenames, | ||
| 343 | S_IRUGO); | ||
| 344 | MODULE_PARM_DESC(file, "names of backing files or devices"); | ||
| 345 | |||
| 346 | module_param_named(serial, mod_data.serial, charp, S_IRUGO); | ||
| 347 | MODULE_PARM_DESC(serial, "USB serial number"); | ||
| 348 | |||
| 349 | module_param_array_named(ro, mod_data.ro, bool, &mod_data.num_ros, S_IRUGO); | ||
| 350 | MODULE_PARM_DESC(ro, "true to force read-only"); | ||
| 351 | |||
| 352 | module_param_array_named(nofua, mod_data.nofua, bool, &mod_data.num_nofuas, | ||
| 353 | S_IRUGO); | ||
| 354 | MODULE_PARM_DESC(nofua, "true to ignore SCSI WRITE(10,12) FUA bit"); | ||
| 355 | |||
| 356 | module_param_named(luns, mod_data.nluns, uint, S_IRUGO); | ||
| 357 | MODULE_PARM_DESC(luns, "number of LUNs"); | ||
| 358 | |||
| 359 | module_param_named(removable, mod_data.removable, bool, S_IRUGO); | ||
| 360 | MODULE_PARM_DESC(removable, "true to simulate removable media"); | ||
| 361 | |||
| 362 | module_param_named(stall, mod_data.can_stall, bool, S_IRUGO); | ||
| 363 | MODULE_PARM_DESC(stall, "false to prevent bulk stalls"); | ||
| 364 | |||
| 365 | module_param_named(cdrom, mod_data.cdrom, bool, S_IRUGO); | ||
| 366 | MODULE_PARM_DESC(cdrom, "true to emulate cdrom instead of disk"); | ||
| 367 | |||
| 368 | /* In the non-TEST version, only the module parameters listed above | ||
| 369 | * are available. */ | ||
| 370 | #ifdef CONFIG_USB_FILE_STORAGE_TEST | ||
| 371 | |||
| 372 | module_param_named(transport, mod_data.transport_parm, charp, S_IRUGO); | ||
| 373 | MODULE_PARM_DESC(transport, "type of transport (BBB, CBI, or CB)"); | ||
| 374 | |||
| 375 | module_param_named(protocol, mod_data.protocol_parm, charp, S_IRUGO); | ||
| 376 | MODULE_PARM_DESC(protocol, "type of protocol (RBC, 8020, QIC, UFI, " | ||
| 377 | "8070, or SCSI)"); | ||
| 378 | |||
| 379 | module_param_named(vendor, mod_data.vendor, ushort, S_IRUGO); | ||
| 380 | MODULE_PARM_DESC(vendor, "USB Vendor ID"); | ||
| 381 | |||
| 382 | module_param_named(product, mod_data.product, ushort, S_IRUGO); | ||
| 383 | MODULE_PARM_DESC(product, "USB Product ID"); | ||
| 384 | |||
| 385 | module_param_named(release, mod_data.release, ushort, S_IRUGO); | ||
| 386 | MODULE_PARM_DESC(release, "USB release number"); | ||
| 387 | |||
| 388 | module_param_named(buflen, mod_data.buflen, uint, S_IRUGO); | ||
| 389 | MODULE_PARM_DESC(buflen, "I/O buffer size"); | ||
| 390 | |||
| 391 | #endif /* CONFIG_USB_FILE_STORAGE_TEST */ | ||
| 392 | |||
| 393 | |||
| 394 | /* | ||
| 395 | * These definitions will permit the compiler to avoid generating code for | ||
| 396 | * parts of the driver that aren't used in the non-TEST version. Even gcc | ||
| 397 | * can recognize when a test of a constant expression yields a dead code | ||
| 398 | * path. | ||
| 399 | */ | ||
| 400 | |||
| 401 | #ifdef CONFIG_USB_FILE_STORAGE_TEST | ||
| 402 | |||
| 403 | #define transport_is_bbb() (mod_data.transport_type == USB_PR_BULK) | ||
| 404 | #define transport_is_cbi() (mod_data.transport_type == USB_PR_CBI) | ||
| 405 | #define protocol_is_scsi() (mod_data.protocol_type == USB_SC_SCSI) | ||
| 406 | |||
| 407 | #else | ||
| 408 | |||
| 409 | #define transport_is_bbb() 1 | ||
| 410 | #define transport_is_cbi() 0 | ||
| 411 | #define protocol_is_scsi() 1 | ||
| 412 | |||
| 413 | #endif /* CONFIG_USB_FILE_STORAGE_TEST */ | ||
| 414 | |||
| 415 | |||
| 416 | /*-------------------------------------------------------------------------*/ | ||
| 417 | |||
| 418 | |||
| 419 | struct fsg_dev { | ||
| 420 | /* lock protects: state, all the req_busy's, and cbbuf_cmnd */ | ||
| 421 | spinlock_t lock; | ||
| 422 | struct usb_gadget *gadget; | ||
| 423 | |||
| 424 | /* filesem protects: backing files in use */ | ||
| 425 | struct rw_semaphore filesem; | ||
| 426 | |||
| 427 | /* reference counting: wait until all LUNs are released */ | ||
| 428 | struct kref ref; | ||
| 429 | |||
| 430 | struct usb_ep *ep0; // Handy copy of gadget->ep0 | ||
| 431 | struct usb_request *ep0req; // For control responses | ||
| 432 | unsigned int ep0_req_tag; | ||
| 433 | const char *ep0req_name; | ||
| 434 | |||
| 435 | struct usb_request *intreq; // For interrupt responses | ||
| 436 | int intreq_busy; | ||
| 437 | struct fsg_buffhd *intr_buffhd; | ||
| 438 | |||
| 439 | unsigned int bulk_out_maxpacket; | ||
| 440 | enum fsg_state state; // For exception handling | ||
| 441 | unsigned int exception_req_tag; | ||
| 442 | |||
| 443 | u8 config, new_config; | ||
| 444 | |||
| 445 | unsigned int running : 1; | ||
| 446 | unsigned int bulk_in_enabled : 1; | ||
| 447 | unsigned int bulk_out_enabled : 1; | ||
| 448 | unsigned int intr_in_enabled : 1; | ||
| 449 | unsigned int phase_error : 1; | ||
| 450 | unsigned int short_packet_received : 1; | ||
| 451 | unsigned int bad_lun_okay : 1; | ||
| 452 | |||
| 453 | unsigned long atomic_bitflags; | ||
| 454 | #define REGISTERED 0 | ||
| 455 | #define IGNORE_BULK_OUT 1 | ||
| 456 | #define SUSPENDED 2 | ||
| 457 | |||
| 458 | struct usb_ep *bulk_in; | ||
| 459 | struct usb_ep *bulk_out; | ||
| 460 | struct usb_ep *intr_in; | ||
| 461 | |||
| 462 | struct fsg_buffhd *next_buffhd_to_fill; | ||
| 463 | struct fsg_buffhd *next_buffhd_to_drain; | ||
| 464 | struct fsg_buffhd buffhds[FSG_NUM_BUFFERS]; | ||
| 465 | |||
| 466 | int thread_wakeup_needed; | ||
| 467 | struct completion thread_notifier; | ||
| 468 | struct task_struct *thread_task; | ||
| 469 | |||
| 470 | int cmnd_size; | ||
| 471 | u8 cmnd[MAX_COMMAND_SIZE]; | ||
| 472 | enum data_direction data_dir; | ||
| 473 | u32 data_size; | ||
| 474 | u32 data_size_from_cmnd; | ||
| 475 | u32 tag; | ||
| 476 | unsigned int lun; | ||
| 477 | u32 residue; | ||
| 478 | u32 usb_amount_left; | ||
| 479 | |||
| 480 | /* The CB protocol offers no way for a host to know when a command | ||
| 481 | * has completed. As a result the next command may arrive early, | ||
| 482 | * and we will still have to handle it. For that reason we need | ||
| 483 | * a buffer to store new commands when using CB (or CBI, which | ||
| 484 | * does not oblige a host to wait for command completion either). */ | ||
| 485 | int cbbuf_cmnd_size; | ||
| 486 | u8 cbbuf_cmnd[MAX_COMMAND_SIZE]; | ||
| 487 | |||
| 488 | unsigned int nluns; | ||
| 489 | struct fsg_lun *luns; | ||
| 490 | struct fsg_lun *curlun; | ||
| 491 | }; | ||
| 492 | |||
| 493 | typedef void (*fsg_routine_t)(struct fsg_dev *); | ||
| 494 | |||
| 495 | static int exception_in_progress(struct fsg_dev *fsg) | ||
| 496 | { | ||
| 497 | return (fsg->state > FSG_STATE_IDLE); | ||
| 498 | } | ||
| 499 | |||
| 500 | /* Make bulk-out requests be divisible by the maxpacket size */ | ||
| 501 | static void set_bulk_out_req_length(struct fsg_dev *fsg, | ||
| 502 | struct fsg_buffhd *bh, unsigned int length) | ||
| 503 | { | ||
| 504 | unsigned int rem; | ||
| 505 | |||
| 506 | bh->bulk_out_intended_length = length; | ||
| 507 | rem = length % fsg->bulk_out_maxpacket; | ||
| 508 | if (rem > 0) | ||
| 509 | length += fsg->bulk_out_maxpacket - rem; | ||
| 510 | bh->outreq->length = length; | ||
| 511 | } | ||
| 512 | |||
| 513 | static struct fsg_dev *the_fsg; | ||
| 514 | static struct usb_gadget_driver fsg_driver; | ||
| 515 | |||
| 516 | |||
| 517 | /*-------------------------------------------------------------------------*/ | ||
| 518 | |||
| 519 | static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep) | ||
| 520 | { | ||
| 521 | const char *name; | ||
| 522 | |||
| 523 | if (ep == fsg->bulk_in) | ||
| 524 | name = "bulk-in"; | ||
| 525 | else if (ep == fsg->bulk_out) | ||
| 526 | name = "bulk-out"; | ||
| 527 | else | ||
| 528 | name = ep->name; | ||
| 529 | DBG(fsg, "%s set halt\n", name); | ||
| 530 | return usb_ep_set_halt(ep); | ||
| 531 | } | ||
| 532 | |||
| 533 | |||
| 534 | /*-------------------------------------------------------------------------*/ | ||
| 535 | |||
| 536 | /* | ||
| 537 | * DESCRIPTORS ... most are static, but strings and (full) configuration | ||
| 538 | * descriptors are built on demand. Also the (static) config and interface | ||
| 539 | * descriptors are adjusted during fsg_bind(). | ||
| 540 | */ | ||
| 541 | |||
| 542 | /* There is only one configuration. */ | ||
| 543 | #define CONFIG_VALUE 1 | ||
| 544 | |||
| 545 | static struct usb_device_descriptor | ||
| 546 | device_desc = { | ||
| 547 | .bLength = sizeof device_desc, | ||
| 548 | .bDescriptorType = USB_DT_DEVICE, | ||
| 549 | |||
| 550 | .bcdUSB = cpu_to_le16(0x0200), | ||
| 551 | .bDeviceClass = USB_CLASS_PER_INTERFACE, | ||
| 552 | |||
| 553 | /* The next three values can be overridden by module parameters */ | ||
| 554 | .idVendor = cpu_to_le16(FSG_VENDOR_ID), | ||
| 555 | .idProduct = cpu_to_le16(FSG_PRODUCT_ID), | ||
| 556 | .bcdDevice = cpu_to_le16(0xffff), | ||
| 557 | |||
| 558 | .iManufacturer = FSG_STRING_MANUFACTURER, | ||
| 559 | .iProduct = FSG_STRING_PRODUCT, | ||
| 560 | .iSerialNumber = FSG_STRING_SERIAL, | ||
| 561 | .bNumConfigurations = 1, | ||
| 562 | }; | ||
| 563 | |||
| 564 | static struct usb_config_descriptor | ||
| 565 | config_desc = { | ||
| 566 | .bLength = sizeof config_desc, | ||
| 567 | .bDescriptorType = USB_DT_CONFIG, | ||
| 568 | |||
| 569 | /* wTotalLength computed by usb_gadget_config_buf() */ | ||
| 570 | .bNumInterfaces = 1, | ||
| 571 | .bConfigurationValue = CONFIG_VALUE, | ||
| 572 | .iConfiguration = FSG_STRING_CONFIG, | ||
| 573 | .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, | ||
| 574 | .bMaxPower = CONFIG_USB_GADGET_VBUS_DRAW / 2, | ||
| 575 | }; | ||
| 576 | |||
| 577 | |||
| 578 | static struct usb_qualifier_descriptor | ||
| 579 | dev_qualifier = { | ||
| 580 | .bLength = sizeof dev_qualifier, | ||
| 581 | .bDescriptorType = USB_DT_DEVICE_QUALIFIER, | ||
| 582 | |||
| 583 | .bcdUSB = cpu_to_le16(0x0200), | ||
| 584 | .bDeviceClass = USB_CLASS_PER_INTERFACE, | ||
| 585 | |||
| 586 | .bNumConfigurations = 1, | ||
| 587 | }; | ||
| 588 | |||
| 589 | |||
| 590 | |||
| 591 | /* | ||
| 592 | * Config descriptors must agree with the code that sets configurations | ||
| 593 | * and with code managing interfaces and their altsettings. They must | ||
| 594 | * also handle different speeds and other-speed requests. | ||
| 595 | */ | ||
| 596 | static int populate_config_buf(struct usb_gadget *gadget, | ||
| 597 | u8 *buf, u8 type, unsigned index) | ||
| 598 | { | ||
| 599 | enum usb_device_speed speed = gadget->speed; | ||
| 600 | int len; | ||
| 601 | const struct usb_descriptor_header **function; | ||
| 602 | |||
| 603 | if (index > 0) | ||
| 604 | return -EINVAL; | ||
| 605 | |||
| 606 | if (gadget_is_dualspeed(gadget) && type == USB_DT_OTHER_SPEED_CONFIG) | ||
| 607 | speed = (USB_SPEED_FULL + USB_SPEED_HIGH) - speed; | ||
| 608 | function = gadget_is_dualspeed(gadget) && speed == USB_SPEED_HIGH | ||
| 609 | ? (const struct usb_descriptor_header **)fsg_hs_function | ||
| 610 | : (const struct usb_descriptor_header **)fsg_fs_function; | ||
| 611 | |||
| 612 | /* for now, don't advertise srp-only devices */ | ||
| 613 | if (!gadget_is_otg(gadget)) | ||
| 614 | function++; | ||
| 615 | |||
| 616 | len = usb_gadget_config_buf(&config_desc, buf, EP0_BUFSIZE, function); | ||
| 617 | ((struct usb_config_descriptor *) buf)->bDescriptorType = type; | ||
| 618 | return len; | ||
| 619 | } | ||
| 620 | |||
| 621 | |||
| 622 | /*-------------------------------------------------------------------------*/ | ||
| 623 | |||
| 624 | /* These routines may be called in process context or in_irq */ | ||
| 625 | |||
| 626 | /* Caller must hold fsg->lock */ | ||
| 627 | static void wakeup_thread(struct fsg_dev *fsg) | ||
| 628 | { | ||
| 629 | /* Tell the main thread that something has happened */ | ||
| 630 | fsg->thread_wakeup_needed = 1; | ||
| 631 | if (fsg->thread_task) | ||
| 632 | wake_up_process(fsg->thread_task); | ||
| 633 | } | ||
| 634 | |||
| 635 | |||
| 636 | static void raise_exception(struct fsg_dev *fsg, enum fsg_state new_state) | ||
| 637 | { | ||
| 638 | unsigned long flags; | ||
| 639 | |||
| 640 | /* Do nothing if a higher-priority exception is already in progress. | ||
| 641 | * If a lower-or-equal priority exception is in progress, preempt it | ||
| 642 | * and notify the main thread by sending it a signal. */ | ||
| 643 | spin_lock_irqsave(&fsg->lock, flags); | ||
| 644 | if (fsg->state <= new_state) { | ||
| 645 | fsg->exception_req_tag = fsg->ep0_req_tag; | ||
| 646 | fsg->state = new_state; | ||
| 647 | if (fsg->thread_task) | ||
| 648 | send_sig_info(SIGUSR1, SEND_SIG_FORCED, | ||
| 649 | fsg->thread_task); | ||
| 650 | } | ||
| 651 | spin_unlock_irqrestore(&fsg->lock, flags); | ||
| 652 | } | ||
| 653 | |||
| 654 | |||
| 655 | /*-------------------------------------------------------------------------*/ | ||
| 656 | |||
| 657 | /* The disconnect callback and ep0 routines. These always run in_irq, | ||
| 658 | * except that ep0_queue() is called in the main thread to acknowledge | ||
| 659 | * completion of various requests: set config, set interface, and | ||
| 660 | * Bulk-only device reset. */ | ||
| 661 | |||
| 662 | static void fsg_disconnect(struct usb_gadget *gadget) | ||
| 663 | { | ||
| 664 | struct fsg_dev *fsg = get_gadget_data(gadget); | ||
| 665 | |||
| 666 | DBG(fsg, "disconnect or port reset\n"); | ||
| 667 | raise_exception(fsg, FSG_STATE_DISCONNECT); | ||
| 668 | } | ||
| 669 | |||
| 670 | |||
| 671 | static int ep0_queue(struct fsg_dev *fsg) | ||
| 672 | { | ||
| 673 | int rc; | ||
| 674 | |||
| 675 | rc = usb_ep_queue(fsg->ep0, fsg->ep0req, GFP_ATOMIC); | ||
| 676 | if (rc != 0 && rc != -ESHUTDOWN) { | ||
| 677 | |||
| 678 | /* We can't do much more than wait for a reset */ | ||
| 679 | WARNING(fsg, "error in submission: %s --> %d\n", | ||
| 680 | fsg->ep0->name, rc); | ||
| 681 | } | ||
| 682 | return rc; | ||
| 683 | } | ||
| 684 | |||
| 685 | static void ep0_complete(struct usb_ep *ep, struct usb_request *req) | ||
| 686 | { | ||
| 687 | struct fsg_dev *fsg = ep->driver_data; | ||
| 688 | |||
| 689 | if (req->actual > 0) | ||
| 690 | dump_msg(fsg, fsg->ep0req_name, req->buf, req->actual); | ||
| 691 | if (req->status || req->actual != req->length) | ||
| 692 | DBG(fsg, "%s --> %d, %u/%u\n", __func__, | ||
| 693 | req->status, req->actual, req->length); | ||
| 694 | if (req->status == -ECONNRESET) // Request was cancelled | ||
| 695 | usb_ep_fifo_flush(ep); | ||
| 696 | |||
| 697 | if (req->status == 0 && req->context) | ||
| 698 | ((fsg_routine_t) (req->context))(fsg); | ||
| 699 | } | ||
| 700 | |||
| 701 | |||
| 702 | /*-------------------------------------------------------------------------*/ | ||
| 703 | |||
| 704 | /* Bulk and interrupt endpoint completion handlers. | ||
| 705 | * These always run in_irq. */ | ||
| 706 | |||
| 707 | static void bulk_in_complete(struct usb_ep *ep, struct usb_request *req) | ||
| 708 | { | ||
| 709 | struct fsg_dev *fsg = ep->driver_data; | ||
| 710 | struct fsg_buffhd *bh = req->context; | ||
| 711 | |||
| 712 | if (req->status || req->actual != req->length) | ||
| 713 | DBG(fsg, "%s --> %d, %u/%u\n", __func__, | ||
| 714 | req->status, req->actual, req->length); | ||
| 715 | if (req->status == -ECONNRESET) // Request was cancelled | ||
| 716 | usb_ep_fifo_flush(ep); | ||
| 717 | |||
| 718 | /* Hold the lock while we update the request and buffer states */ | ||
| 719 | smp_wmb(); | ||
| 720 | spin_lock(&fsg->lock); | ||
| 721 | bh->inreq_busy = 0; | ||
| 722 | bh->state = BUF_STATE_EMPTY; | ||
| 723 | wakeup_thread(fsg); | ||
| 724 | spin_unlock(&fsg->lock); | ||
| 725 | } | ||
| 726 | |||
| 727 | static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req) | ||
| 728 | { | ||
| 729 | struct fsg_dev *fsg = ep->driver_data; | ||
| 730 | struct fsg_buffhd *bh = req->context; | ||
| 731 | |||
| 732 | dump_msg(fsg, "bulk-out", req->buf, req->actual); | ||
| 733 | if (req->status || req->actual != bh->bulk_out_intended_length) | ||
| 734 | DBG(fsg, "%s --> %d, %u/%u\n", __func__, | ||
| 735 | req->status, req->actual, | ||
| 736 | bh->bulk_out_intended_length); | ||
| 737 | if (req->status == -ECONNRESET) // Request was cancelled | ||
| 738 | usb_ep_fifo_flush(ep); | ||
| 739 | |||
| 740 | /* Hold the lock while we update the request and buffer states */ | ||
| 741 | smp_wmb(); | ||
| 742 | spin_lock(&fsg->lock); | ||
| 743 | bh->outreq_busy = 0; | ||
| 744 | bh->state = BUF_STATE_FULL; | ||
| 745 | wakeup_thread(fsg); | ||
| 746 | spin_unlock(&fsg->lock); | ||
| 747 | } | ||
| 748 | |||
| 749 | |||
| 750 | #ifdef CONFIG_USB_FILE_STORAGE_TEST | ||
| 751 | static void intr_in_complete(struct usb_ep *ep, struct usb_request *req) | ||
| 752 | { | ||
| 753 | struct fsg_dev *fsg = ep->driver_data; | ||
| 754 | struct fsg_buffhd *bh = req->context; | ||
| 755 | |||
| 756 | if (req->status || req->actual != req->length) | ||
| 757 | DBG(fsg, "%s --> %d, %u/%u\n", __func__, | ||
| 758 | req->status, req->actual, req->length); | ||
| 759 | if (req->status == -ECONNRESET) // Request was cancelled | ||
| 760 | usb_ep_fifo_flush(ep); | ||
| 761 | |||
| 762 | /* Hold the lock while we update the request and buffer states */ | ||
| 763 | smp_wmb(); | ||
| 764 | spin_lock(&fsg->lock); | ||
| 765 | fsg->intreq_busy = 0; | ||
| 766 | bh->state = BUF_STATE_EMPTY; | ||
| 767 | wakeup_thread(fsg); | ||
| 768 | spin_unlock(&fsg->lock); | ||
| 769 | } | ||
| 770 | |||
| 771 | #else | ||
| 772 | static void intr_in_complete(struct usb_ep *ep, struct usb_request *req) | ||
| 773 | {} | ||
| 774 | #endif /* CONFIG_USB_FILE_STORAGE_TEST */ | ||
| 775 | |||
| 776 | |||
| 777 | /*-------------------------------------------------------------------------*/ | ||
| 778 | |||
| 779 | /* Ep0 class-specific handlers. These always run in_irq. */ | ||
| 780 | |||
| 781 | #ifdef CONFIG_USB_FILE_STORAGE_TEST | ||
| 782 | static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh) | ||
| 783 | { | ||
| 784 | struct usb_request *req = fsg->ep0req; | ||
| 785 | static u8 cbi_reset_cmnd[6] = { | ||
| 786 | SEND_DIAGNOSTIC, 4, 0xff, 0xff, 0xff, 0xff}; | ||
| 787 | |||
| 788 | /* Error in command transfer? */ | ||
| 789 | if (req->status || req->length != req->actual || | ||
| 790 | req->actual < 6 || req->actual > MAX_COMMAND_SIZE) { | ||
| 791 | |||
| 792 | /* Not all controllers allow a protocol stall after | ||
| 793 | * receiving control-out data, but we'll try anyway. */ | ||
| 794 | fsg_set_halt(fsg, fsg->ep0); | ||
| 795 | return; // Wait for reset | ||
| 796 | } | ||
| 797 | |||
| 798 | /* Is it the special reset command? */ | ||
| 799 | if (req->actual >= sizeof cbi_reset_cmnd && | ||
| 800 | memcmp(req->buf, cbi_reset_cmnd, | ||
| 801 | sizeof cbi_reset_cmnd) == 0) { | ||
| 802 | |||
| 803 | /* Raise an exception to stop the current operation | ||
| 804 | * and reinitialize our state. */ | ||
| 805 | DBG(fsg, "cbi reset request\n"); | ||
| 806 | raise_exception(fsg, FSG_STATE_RESET); | ||
| 807 | return; | ||
| 808 | } | ||
| 809 | |||
| 810 | VDBG(fsg, "CB[I] accept device-specific command\n"); | ||
| 811 | spin_lock(&fsg->lock); | ||
| 812 | |||
| 813 | /* Save the command for later */ | ||
| 814 | if (fsg->cbbuf_cmnd_size) | ||
| 815 | WARNING(fsg, "CB[I] overwriting previous command\n"); | ||
| 816 | fsg->cbbuf_cmnd_size = req->actual; | ||
| 817 | memcpy(fsg->cbbuf_cmnd, req->buf, fsg->cbbuf_cmnd_size); | ||
| 818 | |||
| 819 | wakeup_thread(fsg); | ||
| 820 | spin_unlock(&fsg->lock); | ||
| 821 | } | ||
| 822 | |||
| 823 | #else | ||
| 824 | static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh) | ||
| 825 | {} | ||
| 826 | #endif /* CONFIG_USB_FILE_STORAGE_TEST */ | ||
| 827 | |||
| 828 | |||
| 829 | static int class_setup_req(struct fsg_dev *fsg, | ||
| 830 | const struct usb_ctrlrequest *ctrl) | ||
| 831 | { | ||
| 832 | struct usb_request *req = fsg->ep0req; | ||
| 833 | int value = -EOPNOTSUPP; | ||
| 834 | u16 w_index = le16_to_cpu(ctrl->wIndex); | ||
| 835 | u16 w_value = le16_to_cpu(ctrl->wValue); | ||
| 836 | u16 w_length = le16_to_cpu(ctrl->wLength); | ||
| 837 | |||
| 838 | if (!fsg->config) | ||
| 839 | return value; | ||
| 840 | |||
| 841 | /* Handle Bulk-only class-specific requests */ | ||
| 842 | if (transport_is_bbb()) { | ||
| 843 | switch (ctrl->bRequest) { | ||
| 844 | |||
| 845 | case USB_BULK_RESET_REQUEST: | ||
| 846 | if (ctrl->bRequestType != (USB_DIR_OUT | | ||
| 847 | USB_TYPE_CLASS | USB_RECIP_INTERFACE)) | ||
| 848 | break; | ||
| 849 | if (w_index != 0 || w_value != 0) { | ||
| 850 | value = -EDOM; | ||
| 851 | break; | ||
| 852 | } | ||
| 853 | |||
| 854 | /* Raise an exception to stop the current operation | ||
| 855 | * and reinitialize our state. */ | ||
| 856 | DBG(fsg, "bulk reset request\n"); | ||
| 857 | raise_exception(fsg, FSG_STATE_RESET); | ||
| 858 | value = DELAYED_STATUS; | ||
| 859 | break; | ||
| 860 | |||
| 861 | case USB_BULK_GET_MAX_LUN_REQUEST: | ||
| 862 | if (ctrl->bRequestType != (USB_DIR_IN | | ||
| 863 | USB_TYPE_CLASS | USB_RECIP_INTERFACE)) | ||
| 864 | break; | ||
| 865 | if (w_index != 0 || w_value != 0) { | ||
| 866 | value = -EDOM; | ||
| 867 | break; | ||
| 868 | } | ||
| 869 | VDBG(fsg, "get max LUN\n"); | ||
| 870 | *(u8 *) req->buf = fsg->nluns - 1; | ||
| 871 | value = 1; | ||
| 872 | break; | ||
| 873 | } | ||
| 874 | } | ||
| 875 | |||
| 876 | /* Handle CBI class-specific requests */ | ||
| 877 | else { | ||
| 878 | switch (ctrl->bRequest) { | ||
| 879 | |||
| 880 | case USB_CBI_ADSC_REQUEST: | ||
| 881 | if (ctrl->bRequestType != (USB_DIR_OUT | | ||
| 882 | USB_TYPE_CLASS | USB_RECIP_INTERFACE)) | ||
| 883 | break; | ||
| 884 | if (w_index != 0 || w_value != 0) { | ||
| 885 | value = -EDOM; | ||
| 886 | break; | ||
| 887 | } | ||
| 888 | if (w_length > MAX_COMMAND_SIZE) { | ||
| 889 | value = -EOVERFLOW; | ||
| 890 | break; | ||
| 891 | } | ||
| 892 | value = w_length; | ||
| 893 | fsg->ep0req->context = received_cbi_adsc; | ||
| 894 | break; | ||
| 895 | } | ||
| 896 | } | ||
| 897 | |||
| 898 | if (value == -EOPNOTSUPP) | ||
| 899 | VDBG(fsg, | ||
| 900 | "unknown class-specific control req " | ||
| 901 | "%02x.%02x v%04x i%04x l%u\n", | ||
| 902 | ctrl->bRequestType, ctrl->bRequest, | ||
| 903 | le16_to_cpu(ctrl->wValue), w_index, w_length); | ||
| 904 | return value; | ||
| 905 | } | ||
| 906 | |||
| 907 | |||
| 908 | /*-------------------------------------------------------------------------*/ | ||
| 909 | |||
| 910 | /* Ep0 standard request handlers. These always run in_irq. */ | ||
| 911 | |||
| 912 | static int standard_setup_req(struct fsg_dev *fsg, | ||
| 913 | const struct usb_ctrlrequest *ctrl) | ||
| 914 | { | ||
| 915 | struct usb_request *req = fsg->ep0req; | ||
| 916 | int value = -EOPNOTSUPP; | ||
| 917 | u16 w_index = le16_to_cpu(ctrl->wIndex); | ||
| 918 | u16 w_value = le16_to_cpu(ctrl->wValue); | ||
| 919 | |||
| 920 | /* Usually this just stores reply data in the pre-allocated ep0 buffer, | ||
| 921 | * but config change events will also reconfigure hardware. */ | ||
| 922 | switch (ctrl->bRequest) { | ||
| 923 | |||
| 924 | case USB_REQ_GET_DESCRIPTOR: | ||
| 925 | if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD | | ||
| 926 | USB_RECIP_DEVICE)) | ||
| 927 | break; | ||
| 928 | switch (w_value >> 8) { | ||
| 929 | |||
| 930 | case USB_DT_DEVICE: | ||
| 931 | VDBG(fsg, "get device descriptor\n"); | ||
| 932 | device_desc.bMaxPacketSize0 = fsg->ep0->maxpacket; | ||
| 933 | value = sizeof device_desc; | ||
| 934 | memcpy(req->buf, &device_desc, value); | ||
| 935 | break; | ||
| 936 | case USB_DT_DEVICE_QUALIFIER: | ||
| 937 | VDBG(fsg, "get device qualifier\n"); | ||
| 938 | if (!gadget_is_dualspeed(fsg->gadget)) | ||
| 939 | break; | ||
| 940 | /* | ||
| 941 | * Assume ep0 uses the same maxpacket value for both | ||
| 942 | * speeds | ||
| 943 | */ | ||
| 944 | dev_qualifier.bMaxPacketSize0 = fsg->ep0->maxpacket; | ||
| 945 | value = sizeof dev_qualifier; | ||
| 946 | memcpy(req->buf, &dev_qualifier, value); | ||
| 947 | break; | ||
| 948 | |||
| 949 | case USB_DT_OTHER_SPEED_CONFIG: | ||
| 950 | VDBG(fsg, "get other-speed config descriptor\n"); | ||
| 951 | if (!gadget_is_dualspeed(fsg->gadget)) | ||
| 952 | break; | ||
| 953 | goto get_config; | ||
| 954 | case USB_DT_CONFIG: | ||
| 955 | VDBG(fsg, "get configuration descriptor\n"); | ||
| 956 | get_config: | ||
| 957 | value = populate_config_buf(fsg->gadget, | ||
| 958 | req->buf, | ||
| 959 | w_value >> 8, | ||
| 960 | w_value & 0xff); | ||
| 961 | break; | ||
| 962 | |||
| 963 | case USB_DT_STRING: | ||
| 964 | VDBG(fsg, "get string descriptor\n"); | ||
| 965 | |||
| 966 | /* wIndex == language code */ | ||
| 967 | value = usb_gadget_get_string(&fsg_stringtab, | ||
| 968 | w_value & 0xff, req->buf); | ||
| 969 | break; | ||
| 970 | } | ||
| 971 | break; | ||
| 972 | |||
| 973 | /* One config, two speeds */ | ||
| 974 | case USB_REQ_SET_CONFIGURATION: | ||
| 975 | if (ctrl->bRequestType != (USB_DIR_OUT | USB_TYPE_STANDARD | | ||
| 976 | USB_RECIP_DEVICE)) | ||
| 977 | break; | ||
| 978 | VDBG(fsg, "set configuration\n"); | ||
| 979 | if (w_value == CONFIG_VALUE || w_value == 0) { | ||
| 980 | fsg->new_config = w_value; | ||
| 981 | |||
| 982 | /* Raise an exception to wipe out previous transaction | ||
| 983 | * state (queued bufs, etc) and set the new config. */ | ||
| 984 | raise_exception(fsg, FSG_STATE_CONFIG_CHANGE); | ||
| 985 | value = DELAYED_STATUS; | ||
| 986 | } | ||
| 987 | break; | ||
| 988 | case USB_REQ_GET_CONFIGURATION: | ||
| 989 | if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD | | ||
| 990 | USB_RECIP_DEVICE)) | ||
| 991 | break; | ||
| 992 | VDBG(fsg, "get configuration\n"); | ||
| 993 | *(u8 *) req->buf = fsg->config; | ||
| 994 | value = 1; | ||
| 995 | break; | ||
| 996 | |||
| 997 | case USB_REQ_SET_INTERFACE: | ||
| 998 | if (ctrl->bRequestType != (USB_DIR_OUT| USB_TYPE_STANDARD | | ||
| 999 | USB_RECIP_INTERFACE)) | ||
| 1000 | break; | ||
| 1001 | if (fsg->config && w_index == 0) { | ||
| 1002 | |||
| 1003 | /* Raise an exception to wipe out previous transaction | ||
| 1004 | * state (queued bufs, etc) and install the new | ||
| 1005 | * interface altsetting. */ | ||
| 1006 | raise_exception(fsg, FSG_STATE_INTERFACE_CHANGE); | ||
| 1007 | value = DELAYED_STATUS; | ||
| 1008 | } | ||
| 1009 | break; | ||
| 1010 | case USB_REQ_GET_INTERFACE: | ||
| 1011 | if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD | | ||
| 1012 | USB_RECIP_INTERFACE)) | ||
| 1013 | break; | ||
| 1014 | if (!fsg->config) | ||
| 1015 | break; | ||
| 1016 | if (w_index != 0) { | ||
| 1017 | value = -EDOM; | ||
| 1018 | break; | ||
| 1019 | } | ||
| 1020 | VDBG(fsg, "get interface\n"); | ||
| 1021 | *(u8 *) req->buf = 0; | ||
| 1022 | value = 1; | ||
| 1023 | break; | ||
| 1024 | |||
| 1025 | default: | ||
| 1026 | VDBG(fsg, | ||
| 1027 | "unknown control req %02x.%02x v%04x i%04x l%u\n", | ||
| 1028 | ctrl->bRequestType, ctrl->bRequest, | ||
| 1029 | w_value, w_index, le16_to_cpu(ctrl->wLength)); | ||
| 1030 | } | ||
| 1031 | |||
| 1032 | return value; | ||
| 1033 | } | ||
| 1034 | |||
| 1035 | |||
| 1036 | static int fsg_setup(struct usb_gadget *gadget, | ||
| 1037 | const struct usb_ctrlrequest *ctrl) | ||
| 1038 | { | ||
| 1039 | struct fsg_dev *fsg = get_gadget_data(gadget); | ||
| 1040 | int rc; | ||
| 1041 | int w_length = le16_to_cpu(ctrl->wLength); | ||
| 1042 | |||
| 1043 | ++fsg->ep0_req_tag; // Record arrival of a new request | ||
| 1044 | fsg->ep0req->context = NULL; | ||
| 1045 | fsg->ep0req->length = 0; | ||
| 1046 | dump_msg(fsg, "ep0-setup", (u8 *) ctrl, sizeof(*ctrl)); | ||
| 1047 | |||
| 1048 | if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_CLASS) | ||
| 1049 | rc = class_setup_req(fsg, ctrl); | ||
| 1050 | else | ||
| 1051 | rc = standard_setup_req(fsg, ctrl); | ||
| 1052 | |||
| 1053 | /* Respond with data/status or defer until later? */ | ||
| 1054 | if (rc >= 0 && rc != DELAYED_STATUS) { | ||
| 1055 | rc = min(rc, w_length); | ||
| 1056 | fsg->ep0req->length = rc; | ||
| 1057 | fsg->ep0req->zero = rc < w_length; | ||
| 1058 | fsg->ep0req_name = (ctrl->bRequestType & USB_DIR_IN ? | ||
| 1059 | "ep0-in" : "ep0-out"); | ||
| 1060 | rc = ep0_queue(fsg); | ||
| 1061 | } | ||
| 1062 | |||
| 1063 | /* Device either stalls (rc < 0) or reports success */ | ||
| 1064 | return rc; | ||
| 1065 | } | ||
| 1066 | |||
| 1067 | |||
| 1068 | /*-------------------------------------------------------------------------*/ | ||
| 1069 | |||
| 1070 | /* All the following routines run in process context */ | ||
| 1071 | |||
| 1072 | |||
| 1073 | /* Use this for bulk or interrupt transfers, not ep0 */ | ||
| 1074 | static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep, | ||
| 1075 | struct usb_request *req, int *pbusy, | ||
| 1076 | enum fsg_buffer_state *state) | ||
| 1077 | { | ||
| 1078 | int rc; | ||
| 1079 | |||
| 1080 | if (ep == fsg->bulk_in) | ||
| 1081 | dump_msg(fsg, "bulk-in", req->buf, req->length); | ||
| 1082 | else if (ep == fsg->intr_in) | ||
| 1083 | dump_msg(fsg, "intr-in", req->buf, req->length); | ||
| 1084 | |||
| 1085 | spin_lock_irq(&fsg->lock); | ||
| 1086 | *pbusy = 1; | ||
| 1087 | *state = BUF_STATE_BUSY; | ||
| 1088 | spin_unlock_irq(&fsg->lock); | ||
| 1089 | rc = usb_ep_queue(ep, req, GFP_KERNEL); | ||
| 1090 | if (rc != 0) { | ||
| 1091 | *pbusy = 0; | ||
| 1092 | *state = BUF_STATE_EMPTY; | ||
| 1093 | |||
| 1094 | /* We can't do much more than wait for a reset */ | ||
| 1095 | |||
| 1096 | /* Note: currently the net2280 driver fails zero-length | ||
| 1097 | * submissions if DMA is enabled. */ | ||
| 1098 | if (rc != -ESHUTDOWN && !(rc == -EOPNOTSUPP && | ||
| 1099 | req->length == 0)) | ||
| 1100 | WARNING(fsg, "error in submission: %s --> %d\n", | ||
| 1101 | ep->name, rc); | ||
| 1102 | } | ||
| 1103 | } | ||
| 1104 | |||
| 1105 | |||
| 1106 | static int sleep_thread(struct fsg_dev *fsg) | ||
| 1107 | { | ||
| 1108 | int rc = 0; | ||
| 1109 | |||
| 1110 | /* Wait until a signal arrives or we are woken up */ | ||
| 1111 | for (;;) { | ||
| 1112 | try_to_freeze(); | ||
| 1113 | set_current_state(TASK_INTERRUPTIBLE); | ||
| 1114 | if (signal_pending(current)) { | ||
| 1115 | rc = -EINTR; | ||
| 1116 | break; | ||
| 1117 | } | ||
| 1118 | if (fsg->thread_wakeup_needed) | ||
| 1119 | break; | ||
| 1120 | schedule(); | ||
| 1121 | } | ||
| 1122 | __set_current_state(TASK_RUNNING); | ||
| 1123 | fsg->thread_wakeup_needed = 0; | ||
| 1124 | return rc; | ||
| 1125 | } | ||
| 1126 | |||
| 1127 | |||
| 1128 | /*-------------------------------------------------------------------------*/ | ||
| 1129 | |||
| 1130 | static int do_read(struct fsg_dev *fsg) | ||
| 1131 | { | ||
| 1132 | struct fsg_lun *curlun = fsg->curlun; | ||
| 1133 | u32 lba; | ||
| 1134 | struct fsg_buffhd *bh; | ||
| 1135 | int rc; | ||
| 1136 | u32 amount_left; | ||
| 1137 | loff_t file_offset, file_offset_tmp; | ||
| 1138 | unsigned int amount; | ||
| 1139 | unsigned int partial_page; | ||
| 1140 | ssize_t nread; | ||
| 1141 | |||
| 1142 | /* Get the starting Logical Block Address and check that it's | ||
| 1143 | * not too big */ | ||
| 1144 | if (fsg->cmnd[0] == READ_6) | ||
| 1145 | lba = get_unaligned_be24(&fsg->cmnd[1]); | ||
| 1146 | else { | ||
| 1147 | lba = get_unaligned_be32(&fsg->cmnd[2]); | ||
| 1148 | |||
| 1149 | /* We allow DPO (Disable Page Out = don't save data in the | ||
| 1150 | * cache) and FUA (Force Unit Access = don't read from the | ||
| 1151 | * cache), but we don't implement them. */ | ||
| 1152 | if ((fsg->cmnd[1] & ~0x18) != 0) { | ||
| 1153 | curlun->sense_data = SS_INVALID_FIELD_IN_CDB; | ||
| 1154 | return -EINVAL; | ||
| 1155 | } | ||
| 1156 | } | ||
| 1157 | if (lba >= curlun->num_sectors) { | ||
| 1158 | curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; | ||
| 1159 | return -EINVAL; | ||
| 1160 | } | ||
| 1161 | file_offset = ((loff_t) lba) << 9; | ||
| 1162 | |||
| 1163 | /* Carry out the file reads */ | ||
| 1164 | amount_left = fsg->data_size_from_cmnd; | ||
| 1165 | if (unlikely(amount_left == 0)) | ||
| 1166 | return -EIO; // No default reply | ||
| 1167 | |||
| 1168 | for (;;) { | ||
| 1169 | |||
| 1170 | /* Figure out how much we need to read: | ||
| 1171 | * Try to read the remaining amount. | ||
| 1172 | * But don't read more than the buffer size. | ||
| 1173 | * And don't try to read past the end of the file. | ||
| 1174 | * Finally, if we're not at a page boundary, don't read past | ||
| 1175 | * the next page. | ||
| 1176 | * If this means reading 0 then we were asked to read past | ||
| 1177 | * the end of file. */ | ||
| 1178 | amount = min((unsigned int) amount_left, mod_data.buflen); | ||
| 1179 | amount = min((loff_t) amount, | ||
| 1180 | curlun->file_length - file_offset); | ||
| 1181 | partial_page = file_offset & (PAGE_CACHE_SIZE - 1); | ||
| 1182 | if (partial_page > 0) | ||
| 1183 | amount = min(amount, (unsigned int) PAGE_CACHE_SIZE - | ||
| 1184 | partial_page); | ||
| 1185 | |||
| 1186 | /* Wait for the next buffer to become available */ | ||
| 1187 | bh = fsg->next_buffhd_to_fill; | ||
| 1188 | while (bh->state != BUF_STATE_EMPTY) { | ||
| 1189 | rc = sleep_thread(fsg); | ||
| 1190 | if (rc) | ||
| 1191 | return rc; | ||
| 1192 | } | ||
| 1193 | |||
| 1194 | /* If we were asked to read past the end of file, | ||
| 1195 | * end with an empty buffer. */ | ||
| 1196 | if (amount == 0) { | ||
| 1197 | curlun->sense_data = | ||
| 1198 | SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; | ||
| 1199 | curlun->sense_data_info = file_offset >> 9; | ||
| 1200 | curlun->info_valid = 1; | ||
| 1201 | bh->inreq->length = 0; | ||
| 1202 | bh->state = BUF_STATE_FULL; | ||
| 1203 | break; | ||
| 1204 | } | ||
| 1205 | |||
| 1206 | /* Perform the read */ | ||
| 1207 | file_offset_tmp = file_offset; | ||
| 1208 | nread = vfs_read(curlun->filp, | ||
| 1209 | (char __user *) bh->buf, | ||
| 1210 | amount, &file_offset_tmp); | ||
| 1211 | VLDBG(curlun, "file read %u @ %llu -> %d\n", amount, | ||
| 1212 | (unsigned long long) file_offset, | ||
| 1213 | (int) nread); | ||
| 1214 | if (signal_pending(current)) | ||
| 1215 | return -EINTR; | ||
| 1216 | |||
| 1217 | if (nread < 0) { | ||
| 1218 | LDBG(curlun, "error in file read: %d\n", | ||
| 1219 | (int) nread); | ||
| 1220 | nread = 0; | ||
| 1221 | } else if (nread < amount) { | ||
| 1222 | LDBG(curlun, "partial file read: %d/%u\n", | ||
| 1223 | (int) nread, amount); | ||
| 1224 | nread -= (nread & 511); // Round down to a block | ||
| 1225 | } | ||
| 1226 | file_offset += nread; | ||
| 1227 | amount_left -= nread; | ||
| 1228 | fsg->residue -= nread; | ||
| 1229 | bh->inreq->length = nread; | ||
| 1230 | bh->state = BUF_STATE_FULL; | ||
| 1231 | |||
| 1232 | /* If an error occurred, report it and its position */ | ||
| 1233 | if (nread < amount) { | ||
| 1234 | curlun->sense_data = SS_UNRECOVERED_READ_ERROR; | ||
| 1235 | curlun->sense_data_info = file_offset >> 9; | ||
| 1236 | curlun->info_valid = 1; | ||
| 1237 | break; | ||
| 1238 | } | ||
| 1239 | |||
| 1240 | if (amount_left == 0) | ||
| 1241 | break; // No more left to read | ||
| 1242 | |||
| 1243 | /* Send this buffer and go read some more */ | ||
| 1244 | bh->inreq->zero = 0; | ||
| 1245 | start_transfer(fsg, fsg->bulk_in, bh->inreq, | ||
| 1246 | &bh->inreq_busy, &bh->state); | ||
| 1247 | fsg->next_buffhd_to_fill = bh->next; | ||
| 1248 | } | ||
| 1249 | |||
| 1250 | return -EIO; // No default reply | ||
| 1251 | } | ||
| 1252 | |||
| 1253 | |||
| 1254 | /*-------------------------------------------------------------------------*/ | ||
| 1255 | |||
| 1256 | static int do_write(struct fsg_dev *fsg) | ||
| 1257 | { | ||
| 1258 | struct fsg_lun *curlun = fsg->curlun; | ||
| 1259 | u32 lba; | ||
| 1260 | struct fsg_buffhd *bh; | ||
| 1261 | int get_some_more; | ||
| 1262 | u32 amount_left_to_req, amount_left_to_write; | ||
| 1263 | loff_t usb_offset, file_offset, file_offset_tmp; | ||
| 1264 | unsigned int amount; | ||
| 1265 | unsigned int partial_page; | ||
| 1266 | ssize_t nwritten; | ||
| 1267 | int rc; | ||
| 1268 | |||
| 1269 | if (curlun->ro) { | ||
| 1270 | curlun->sense_data = SS_WRITE_PROTECTED; | ||
| 1271 | return -EINVAL; | ||
| 1272 | } | ||
| 1273 | spin_lock(&curlun->filp->f_lock); | ||
| 1274 | curlun->filp->f_flags &= ~O_SYNC; // Default is not to wait | ||
| 1275 | spin_unlock(&curlun->filp->f_lock); | ||
| 1276 | |||
| 1277 | /* Get the starting Logical Block Address and check that it's | ||
| 1278 | * not too big */ | ||
| 1279 | if (fsg->cmnd[0] == WRITE_6) | ||
| 1280 | lba = get_unaligned_be24(&fsg->cmnd[1]); | ||
| 1281 | else { | ||
| 1282 | lba = get_unaligned_be32(&fsg->cmnd[2]); | ||
| 1283 | |||
| 1284 | /* We allow DPO (Disable Page Out = don't save data in the | ||
| 1285 | * cache) and FUA (Force Unit Access = write directly to the | ||
| 1286 | * medium). We don't implement DPO; we implement FUA by | ||
| 1287 | * performing synchronous output. */ | ||
| 1288 | if ((fsg->cmnd[1] & ~0x18) != 0) { | ||
| 1289 | curlun->sense_data = SS_INVALID_FIELD_IN_CDB; | ||
| 1290 | return -EINVAL; | ||
| 1291 | } | ||
| 1292 | /* FUA */ | ||
| 1293 | if (!curlun->nofua && (fsg->cmnd[1] & 0x08)) { | ||
| 1294 | spin_lock(&curlun->filp->f_lock); | ||
| 1295 | curlun->filp->f_flags |= O_DSYNC; | ||
| 1296 | spin_unlock(&curlun->filp->f_lock); | ||
| 1297 | } | ||
| 1298 | } | ||
| 1299 | if (lba >= curlun->num_sectors) { | ||
| 1300 | curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; | ||
| 1301 | return -EINVAL; | ||
| 1302 | } | ||
| 1303 | |||
| 1304 | /* Carry out the file writes */ | ||
| 1305 | get_some_more = 1; | ||
| 1306 | file_offset = usb_offset = ((loff_t) lba) << 9; | ||
| 1307 | amount_left_to_req = amount_left_to_write = fsg->data_size_from_cmnd; | ||
| 1308 | |||
| 1309 | while (amount_left_to_write > 0) { | ||
| 1310 | |||
| 1311 | /* Queue a request for more data from the host */ | ||
| 1312 | bh = fsg->next_buffhd_to_fill; | ||
| 1313 | if (bh->state == BUF_STATE_EMPTY && get_some_more) { | ||
| 1314 | |||
| 1315 | /* Figure out how much we want to get: | ||
| 1316 | * Try to get the remaining amount. | ||
| 1317 | * But don't get more than the buffer size. | ||
| 1318 | * And don't try to go past the end of the file. | ||
| 1319 | * If we're not at a page boundary, | ||
| 1320 | * don't go past the next page. | ||
| 1321 | * If this means getting 0, then we were asked | ||
| 1322 | * to write past the end of file. | ||
| 1323 | * Finally, round down to a block boundary. */ | ||
| 1324 | amount = min(amount_left_to_req, mod_data.buflen); | ||
| 1325 | amount = min((loff_t) amount, curlun->file_length - | ||
| 1326 | usb_offset); | ||
| 1327 | partial_page = usb_offset & (PAGE_CACHE_SIZE - 1); | ||
| 1328 | if (partial_page > 0) | ||
| 1329 | amount = min(amount, | ||
| 1330 | (unsigned int) PAGE_CACHE_SIZE - partial_page); | ||
| 1331 | |||
| 1332 | if (amount == 0) { | ||
| 1333 | get_some_more = 0; | ||
| 1334 | curlun->sense_data = | ||
| 1335 | SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; | ||
| 1336 | curlun->sense_data_info = usb_offset >> 9; | ||
| 1337 | curlun->info_valid = 1; | ||
| 1338 | continue; | ||
| 1339 | } | ||
| 1340 | amount -= (amount & 511); | ||
| 1341 | if (amount == 0) { | ||
| 1342 | |||
| 1343 | /* Why were we were asked to transfer a | ||
| 1344 | * partial block? */ | ||
| 1345 | get_some_more = 0; | ||
| 1346 | continue; | ||
| 1347 | } | ||
| 1348 | |||
| 1349 | /* Get the next buffer */ | ||
| 1350 | usb_offset += amount; | ||
| 1351 | fsg->usb_amount_left -= amount; | ||
| 1352 | amount_left_to_req -= amount; | ||
| 1353 | if (amount_left_to_req == 0) | ||
| 1354 | get_some_more = 0; | ||
| 1355 | |||
| 1356 | /* amount is always divisible by 512, hence by | ||
| 1357 | * the bulk-out maxpacket size */ | ||
| 1358 | bh->outreq->length = bh->bulk_out_intended_length = | ||
| 1359 | amount; | ||
| 1360 | bh->outreq->short_not_ok = 1; | ||
| 1361 | start_transfer(fsg, fsg->bulk_out, bh->outreq, | ||
| 1362 | &bh->outreq_busy, &bh->state); | ||
| 1363 | fsg->next_buffhd_to_fill = bh->next; | ||
| 1364 | continue; | ||
| 1365 | } | ||
| 1366 | |||
| 1367 | /* Write the received data to the backing file */ | ||
| 1368 | bh = fsg->next_buffhd_to_drain; | ||
| 1369 | if (bh->state == BUF_STATE_EMPTY && !get_some_more) | ||
| 1370 | break; // We stopped early | ||
| 1371 | if (bh->state == BUF_STATE_FULL) { | ||
| 1372 | smp_rmb(); | ||
| 1373 | fsg->next_buffhd_to_drain = bh->next; | ||
| 1374 | bh->state = BUF_STATE_EMPTY; | ||
| 1375 | |||
| 1376 | /* Did something go wrong with the transfer? */ | ||
| 1377 | if (bh->outreq->status != 0) { | ||
| 1378 | curlun->sense_data = SS_COMMUNICATION_FAILURE; | ||
| 1379 | curlun->sense_data_info = file_offset >> 9; | ||
| 1380 | curlun->info_valid = 1; | ||
| 1381 | break; | ||
| 1382 | } | ||
| 1383 | |||
| 1384 | amount = bh->outreq->actual; | ||
| 1385 | if (curlun->file_length - file_offset < amount) { | ||
| 1386 | LERROR(curlun, | ||
| 1387 | "write %u @ %llu beyond end %llu\n", | ||
| 1388 | amount, (unsigned long long) file_offset, | ||
| 1389 | (unsigned long long) curlun->file_length); | ||
| 1390 | amount = curlun->file_length - file_offset; | ||
| 1391 | } | ||
| 1392 | |||
| 1393 | /* Perform the write */ | ||
| 1394 | file_offset_tmp = file_offset; | ||
| 1395 | nwritten = vfs_write(curlun->filp, | ||
| 1396 | (char __user *) bh->buf, | ||
| 1397 | amount, &file_offset_tmp); | ||
| 1398 | VLDBG(curlun, "file write %u @ %llu -> %d\n", amount, | ||
| 1399 | (unsigned long long) file_offset, | ||
| 1400 | (int) nwritten); | ||
| 1401 | if (signal_pending(current)) | ||
| 1402 | return -EINTR; // Interrupted! | ||
| 1403 | |||
| 1404 | if (nwritten < 0) { | ||
| 1405 | LDBG(curlun, "error in file write: %d\n", | ||
| 1406 | (int) nwritten); | ||
| 1407 | nwritten = 0; | ||
| 1408 | } else if (nwritten < amount) { | ||
| 1409 | LDBG(curlun, "partial file write: %d/%u\n", | ||
| 1410 | (int) nwritten, amount); | ||
| 1411 | nwritten -= (nwritten & 511); | ||
| 1412 | // Round down to a block | ||
| 1413 | } | ||
| 1414 | file_offset += nwritten; | ||
| 1415 | amount_left_to_write -= nwritten; | ||
| 1416 | fsg->residue -= nwritten; | ||
| 1417 | |||
| 1418 | /* If an error occurred, report it and its position */ | ||
| 1419 | if (nwritten < amount) { | ||
| 1420 | curlun->sense_data = SS_WRITE_ERROR; | ||
| 1421 | curlun->sense_data_info = file_offset >> 9; | ||
| 1422 | curlun->info_valid = 1; | ||
| 1423 | break; | ||
| 1424 | } | ||
| 1425 | |||
| 1426 | /* Did the host decide to stop early? */ | ||
| 1427 | if (bh->outreq->actual != bh->outreq->length) { | ||
| 1428 | fsg->short_packet_received = 1; | ||
| 1429 | break; | ||
| 1430 | } | ||
| 1431 | continue; | ||
| 1432 | } | ||
| 1433 | |||
| 1434 | /* Wait for something to happen */ | ||
| 1435 | rc = sleep_thread(fsg); | ||
| 1436 | if (rc) | ||
| 1437 | return rc; | ||
| 1438 | } | ||
| 1439 | |||
| 1440 | return -EIO; // No default reply | ||
| 1441 | } | ||
| 1442 | |||
| 1443 | |||
| 1444 | /*-------------------------------------------------------------------------*/ | ||
| 1445 | |||
| 1446 | static int do_synchronize_cache(struct fsg_dev *fsg) | ||
| 1447 | { | ||
| 1448 | struct fsg_lun *curlun = fsg->curlun; | ||
| 1449 | int rc; | ||
| 1450 | |||
| 1451 | /* We ignore the requested LBA and write out all file's | ||
| 1452 | * dirty data buffers. */ | ||
| 1453 | rc = fsg_lun_fsync_sub(curlun); | ||
| 1454 | if (rc) | ||
| 1455 | curlun->sense_data = SS_WRITE_ERROR; | ||
| 1456 | return 0; | ||
| 1457 | } | ||
| 1458 | |||
| 1459 | |||
| 1460 | /*-------------------------------------------------------------------------*/ | ||
| 1461 | |||
| 1462 | static void invalidate_sub(struct fsg_lun *curlun) | ||
| 1463 | { | ||
| 1464 | struct file *filp = curlun->filp; | ||
| 1465 | struct inode *inode = filp->f_path.dentry->d_inode; | ||
| 1466 | unsigned long rc; | ||
| 1467 | |||
| 1468 | rc = invalidate_mapping_pages(inode->i_mapping, 0, -1); | ||
| 1469 | VLDBG(curlun, "invalidate_mapping_pages -> %ld\n", rc); | ||
| 1470 | } | ||
| 1471 | |||
| 1472 | static int do_verify(struct fsg_dev *fsg) | ||
| 1473 | { | ||
| 1474 | struct fsg_lun *curlun = fsg->curlun; | ||
| 1475 | u32 lba; | ||
| 1476 | u32 verification_length; | ||
| 1477 | struct fsg_buffhd *bh = fsg->next_buffhd_to_fill; | ||
| 1478 | loff_t file_offset, file_offset_tmp; | ||
| 1479 | u32 amount_left; | ||
| 1480 | unsigned int amount; | ||
| 1481 | ssize_t nread; | ||
| 1482 | |||
| 1483 | /* Get the starting Logical Block Address and check that it's | ||
| 1484 | * not too big */ | ||
| 1485 | lba = get_unaligned_be32(&fsg->cmnd[2]); | ||
| 1486 | if (lba >= curlun->num_sectors) { | ||
| 1487 | curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; | ||
| 1488 | return -EINVAL; | ||
| 1489 | } | ||
| 1490 | |||
| 1491 | /* We allow DPO (Disable Page Out = don't save data in the | ||
| 1492 | * cache) but we don't implement it. */ | ||
| 1493 | if ((fsg->cmnd[1] & ~0x10) != 0) { | ||
| 1494 | curlun->sense_data = SS_INVALID_FIELD_IN_CDB; | ||
| 1495 | return -EINVAL; | ||
| 1496 | } | ||
| 1497 | |||
| 1498 | verification_length = get_unaligned_be16(&fsg->cmnd[7]); | ||
| 1499 | if (unlikely(verification_length == 0)) | ||
| 1500 | return -EIO; // No default reply | ||
| 1501 | |||
| 1502 | /* Prepare to carry out the file verify */ | ||
| 1503 | amount_left = verification_length << 9; | ||
| 1504 | file_offset = ((loff_t) lba) << 9; | ||
| 1505 | |||
| 1506 | /* Write out all the dirty buffers before invalidating them */ | ||
| 1507 | fsg_lun_fsync_sub(curlun); | ||
| 1508 | if (signal_pending(current)) | ||
| 1509 | return -EINTR; | ||
| 1510 | |||
| 1511 | invalidate_sub(curlun); | ||
| 1512 | if (signal_pending(current)) | ||
| 1513 | return -EINTR; | ||
| 1514 | |||
| 1515 | /* Just try to read the requested blocks */ | ||
| 1516 | while (amount_left > 0) { | ||
| 1517 | |||
| 1518 | /* Figure out how much we need to read: | ||
| 1519 | * Try to read the remaining amount, but not more than | ||
| 1520 | * the buffer size. | ||
| 1521 | * And don't try to read past the end of the file. | ||
| 1522 | * If this means reading 0 then we were asked to read | ||
| 1523 | * past the end of file. */ | ||
| 1524 | amount = min((unsigned int) amount_left, mod_data.buflen); | ||
| 1525 | amount = min((loff_t) amount, | ||
| 1526 | curlun->file_length - file_offset); | ||
| 1527 | if (amount == 0) { | ||
| 1528 | curlun->sense_data = | ||
| 1529 | SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; | ||
| 1530 | curlun->sense_data_info = file_offset >> 9; | ||
| 1531 | curlun->info_valid = 1; | ||
| 1532 | break; | ||
| 1533 | } | ||
| 1534 | |||
| 1535 | /* Perform the read */ | ||
| 1536 | file_offset_tmp = file_offset; | ||
| 1537 | nread = vfs_read(curlun->filp, | ||
| 1538 | (char __user *) bh->buf, | ||
| 1539 | amount, &file_offset_tmp); | ||
| 1540 | VLDBG(curlun, "file read %u @ %llu -> %d\n", amount, | ||
| 1541 | (unsigned long long) file_offset, | ||
| 1542 | (int) nread); | ||
| 1543 | if (signal_pending(current)) | ||
| 1544 | return -EINTR; | ||
| 1545 | |||
| 1546 | if (nread < 0) { | ||
| 1547 | LDBG(curlun, "error in file verify: %d\n", | ||
| 1548 | (int) nread); | ||
| 1549 | nread = 0; | ||
| 1550 | } else if (nread < amount) { | ||
| 1551 | LDBG(curlun, "partial file verify: %d/%u\n", | ||
| 1552 | (int) nread, amount); | ||
| 1553 | nread -= (nread & 511); // Round down to a sector | ||
| 1554 | } | ||
| 1555 | if (nread == 0) { | ||
| 1556 | curlun->sense_data = SS_UNRECOVERED_READ_ERROR; | ||
| 1557 | curlun->sense_data_info = file_offset >> 9; | ||
| 1558 | curlun->info_valid = 1; | ||
| 1559 | break; | ||
| 1560 | } | ||
| 1561 | file_offset += nread; | ||
| 1562 | amount_left -= nread; | ||
| 1563 | } | ||
| 1564 | return 0; | ||
| 1565 | } | ||
| 1566 | |||
| 1567 | |||
| 1568 | /*-------------------------------------------------------------------------*/ | ||
| 1569 | |||
| 1570 | static int do_inquiry(struct fsg_dev *fsg, struct fsg_buffhd *bh) | ||
| 1571 | { | ||
| 1572 | u8 *buf = (u8 *) bh->buf; | ||
| 1573 | |||
| 1574 | static char vendor_id[] = "Linux "; | ||
| 1575 | static char product_disk_id[] = "File-Stor Gadget"; | ||
| 1576 | static char product_cdrom_id[] = "File-CD Gadget "; | ||
| 1577 | |||
| 1578 | if (!fsg->curlun) { // Unsupported LUNs are okay | ||
| 1579 | fsg->bad_lun_okay = 1; | ||
| 1580 | memset(buf, 0, 36); | ||
| 1581 | buf[0] = 0x7f; // Unsupported, no device-type | ||
| 1582 | buf[4] = 31; // Additional length | ||
| 1583 | return 36; | ||
| 1584 | } | ||
| 1585 | |||
| 1586 | memset(buf, 0, 8); | ||
| 1587 | buf[0] = (mod_data.cdrom ? TYPE_ROM : TYPE_DISK); | ||
| 1588 | if (mod_data.removable) | ||
| 1589 | buf[1] = 0x80; | ||
| 1590 | buf[2] = 2; // ANSI SCSI level 2 | ||
| 1591 | buf[3] = 2; // SCSI-2 INQUIRY data format | ||
| 1592 | buf[4] = 31; // Additional length | ||
| 1593 | // No special options | ||
| 1594 | sprintf(buf + 8, "%-8s%-16s%04x", vendor_id, | ||
| 1595 | (mod_data.cdrom ? product_cdrom_id : | ||
| 1596 | product_disk_id), | ||
| 1597 | mod_data.release); | ||
| 1598 | return 36; | ||
| 1599 | } | ||
| 1600 | |||
| 1601 | |||
| 1602 | static int do_request_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh) | ||
| 1603 | { | ||
| 1604 | struct fsg_lun *curlun = fsg->curlun; | ||
| 1605 | u8 *buf = (u8 *) bh->buf; | ||
| 1606 | u32 sd, sdinfo; | ||
| 1607 | int valid; | ||
| 1608 | |||
| 1609 | /* | ||
| 1610 | * From the SCSI-2 spec., section 7.9 (Unit attention condition): | ||
| 1611 | * | ||
| 1612 | * If a REQUEST SENSE command is received from an initiator | ||
| 1613 | * with a pending unit attention condition (before the target | ||
| 1614 | * generates the contingent allegiance condition), then the | ||
| 1615 | * target shall either: | ||
| 1616 | * a) report any pending sense data and preserve the unit | ||
| 1617 | * attention condition on the logical unit, or, | ||
| 1618 | * b) report the unit attention condition, may discard any | ||
| 1619 | * pending sense data, and clear the unit attention | ||
| 1620 | * condition on the logical unit for that initiator. | ||
| 1621 | * | ||
| 1622 | * FSG normally uses option a); enable this code to use option b). | ||
| 1623 | */ | ||
| 1624 | #if 0 | ||
| 1625 | if (curlun && curlun->unit_attention_data != SS_NO_SENSE) { | ||
| 1626 | curlun->sense_data = curlun->unit_attention_data; | ||
| 1627 | curlun->unit_attention_data = SS_NO_SENSE; | ||
| 1628 | } | ||
| 1629 | #endif | ||
| 1630 | |||
| 1631 | if (!curlun) { // Unsupported LUNs are okay | ||
| 1632 | fsg->bad_lun_okay = 1; | ||
| 1633 | sd = SS_LOGICAL_UNIT_NOT_SUPPORTED; | ||
| 1634 | sdinfo = 0; | ||
| 1635 | valid = 0; | ||
| 1636 | } else { | ||
| 1637 | sd = curlun->sense_data; | ||
| 1638 | sdinfo = curlun->sense_data_info; | ||
| 1639 | valid = curlun->info_valid << 7; | ||
| 1640 | curlun->sense_data = SS_NO_SENSE; | ||
| 1641 | curlun->sense_data_info = 0; | ||
| 1642 | curlun->info_valid = 0; | ||
| 1643 | } | ||
| 1644 | |||
| 1645 | memset(buf, 0, 18); | ||
| 1646 | buf[0] = valid | 0x70; // Valid, current error | ||
| 1647 | buf[2] = SK(sd); | ||
| 1648 | put_unaligned_be32(sdinfo, &buf[3]); /* Sense information */ | ||
| 1649 | buf[7] = 18 - 8; // Additional sense length | ||
| 1650 | buf[12] = ASC(sd); | ||
| 1651 | buf[13] = ASCQ(sd); | ||
| 1652 | return 18; | ||
| 1653 | } | ||
| 1654 | |||
| 1655 | |||
| 1656 | static int do_read_capacity(struct fsg_dev *fsg, struct fsg_buffhd *bh) | ||
| 1657 | { | ||
| 1658 | struct fsg_lun *curlun = fsg->curlun; | ||
| 1659 | u32 lba = get_unaligned_be32(&fsg->cmnd[2]); | ||
| 1660 | int pmi = fsg->cmnd[8]; | ||
| 1661 | u8 *buf = (u8 *) bh->buf; | ||
| 1662 | |||
| 1663 | /* Check the PMI and LBA fields */ | ||
| 1664 | if (pmi > 1 || (pmi == 0 && lba != 0)) { | ||
| 1665 | curlun->sense_data = SS_INVALID_FIELD_IN_CDB; | ||
| 1666 | return -EINVAL; | ||
| 1667 | } | ||
| 1668 | |||
| 1669 | put_unaligned_be32(curlun->num_sectors - 1, &buf[0]); | ||
| 1670 | /* Max logical block */ | ||
| 1671 | put_unaligned_be32(512, &buf[4]); /* Block length */ | ||
| 1672 | return 8; | ||
| 1673 | } | ||
| 1674 | |||
| 1675 | |||
| 1676 | static int do_read_header(struct fsg_dev *fsg, struct fsg_buffhd *bh) | ||
| 1677 | { | ||
| 1678 | struct fsg_lun *curlun = fsg->curlun; | ||
| 1679 | int msf = fsg->cmnd[1] & 0x02; | ||
| 1680 | u32 lba = get_unaligned_be32(&fsg->cmnd[2]); | ||
| 1681 | u8 *buf = (u8 *) bh->buf; | ||
| 1682 | |||
| 1683 | if ((fsg->cmnd[1] & ~0x02) != 0) { /* Mask away MSF */ | ||
| 1684 | curlun->sense_data = SS_INVALID_FIELD_IN_CDB; | ||
| 1685 | return -EINVAL; | ||
| 1686 | } | ||
| 1687 | if (lba >= curlun->num_sectors) { | ||
| 1688 | curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; | ||
| 1689 | return -EINVAL; | ||
| 1690 | } | ||
| 1691 | |||
| 1692 | memset(buf, 0, 8); | ||
| 1693 | buf[0] = 0x01; /* 2048 bytes of user data, rest is EC */ | ||
| 1694 | store_cdrom_address(&buf[4], msf, lba); | ||
| 1695 | return 8; | ||
| 1696 | } | ||
| 1697 | |||
| 1698 | |||
| 1699 | static int do_read_toc(struct fsg_dev *fsg, struct fsg_buffhd *bh) | ||
| 1700 | { | ||
| 1701 | struct fsg_lun *curlun = fsg->curlun; | ||
| 1702 | int msf = fsg->cmnd[1] & 0x02; | ||
| 1703 | int start_track = fsg->cmnd[6]; | ||
| 1704 | u8 *buf = (u8 *) bh->buf; | ||
| 1705 | |||
| 1706 | if ((fsg->cmnd[1] & ~0x02) != 0 || /* Mask away MSF */ | ||
| 1707 | start_track > 1) { | ||
| 1708 | curlun->sense_data = SS_INVALID_FIELD_IN_CDB; | ||
| 1709 | return -EINVAL; | ||
| 1710 | } | ||
| 1711 | |||
| 1712 | memset(buf, 0, 20); | ||
| 1713 | buf[1] = (20-2); /* TOC data length */ | ||
| 1714 | buf[2] = 1; /* First track number */ | ||
| 1715 | buf[3] = 1; /* Last track number */ | ||
| 1716 | buf[5] = 0x16; /* Data track, copying allowed */ | ||
| 1717 | buf[6] = 0x01; /* Only track is number 1 */ | ||
| 1718 | store_cdrom_address(&buf[8], msf, 0); | ||
| 1719 | |||
| 1720 | buf[13] = 0x16; /* Lead-out track is data */ | ||
| 1721 | buf[14] = 0xAA; /* Lead-out track number */ | ||
| 1722 | store_cdrom_address(&buf[16], msf, curlun->num_sectors); | ||
| 1723 | return 20; | ||
| 1724 | } | ||
| 1725 | |||
| 1726 | |||
| 1727 | static int do_mode_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh) | ||
| 1728 | { | ||
| 1729 | struct fsg_lun *curlun = fsg->curlun; | ||
| 1730 | int mscmnd = fsg->cmnd[0]; | ||
| 1731 | u8 *buf = (u8 *) bh->buf; | ||
| 1732 | u8 *buf0 = buf; | ||
| 1733 | int pc, page_code; | ||
| 1734 | int changeable_values, all_pages; | ||
| 1735 | int valid_page = 0; | ||
| 1736 | int len, limit; | ||
| 1737 | |||
| 1738 | if ((fsg->cmnd[1] & ~0x08) != 0) { // Mask away DBD | ||
| 1739 | curlun->sense_data = SS_INVALID_FIELD_IN_CDB; | ||
| 1740 | return -EINVAL; | ||
| 1741 | } | ||
| 1742 | pc = fsg->cmnd[2] >> 6; | ||
| 1743 | page_code = fsg->cmnd[2] & 0x3f; | ||
| 1744 | if (pc == 3) { | ||
| 1745 | curlun->sense_data = SS_SAVING_PARAMETERS_NOT_SUPPORTED; | ||
| 1746 | return -EINVAL; | ||
| 1747 | } | ||
| 1748 | changeable_values = (pc == 1); | ||
| 1749 | all_pages = (page_code == 0x3f); | ||
| 1750 | |||
| 1751 | /* Write the mode parameter header. Fixed values are: default | ||
| 1752 | * medium type, no cache control (DPOFUA), and no block descriptors. | ||
| 1753 | * The only variable value is the WriteProtect bit. We will fill in | ||
| 1754 | * the mode data length later. */ | ||
| 1755 | memset(buf, 0, 8); | ||
| 1756 | if (mscmnd == MODE_SENSE) { | ||
| 1757 | buf[2] = (curlun->ro ? 0x80 : 0x00); // WP, DPOFUA | ||
| 1758 | buf += 4; | ||
| 1759 | limit = 255; | ||
| 1760 | } else { // MODE_SENSE_10 | ||
| 1761 | buf[3] = (curlun->ro ? 0x80 : 0x00); // WP, DPOFUA | ||
| 1762 | buf += 8; | ||
| 1763 | limit = 65535; // Should really be mod_data.buflen | ||
| 1764 | } | ||
| 1765 | |||
| 1766 | /* No block descriptors */ | ||
| 1767 | |||
| 1768 | /* The mode pages, in numerical order. The only page we support | ||
| 1769 | * is the Caching page. */ | ||
| 1770 | if (page_code == 0x08 || all_pages) { | ||
| 1771 | valid_page = 1; | ||
| 1772 | buf[0] = 0x08; // Page code | ||
| 1773 | buf[1] = 10; // Page length | ||
| 1774 | memset(buf+2, 0, 10); // None of the fields are changeable | ||
| 1775 | |||
| 1776 | if (!changeable_values) { | ||
| 1777 | buf[2] = 0x04; // Write cache enable, | ||
| 1778 | // Read cache not disabled | ||
| 1779 | // No cache retention priorities | ||
| 1780 | put_unaligned_be16(0xffff, &buf[4]); | ||
| 1781 | /* Don't disable prefetch */ | ||
| 1782 | /* Minimum prefetch = 0 */ | ||
| 1783 | put_unaligned_be16(0xffff, &buf[8]); | ||
| 1784 | /* Maximum prefetch */ | ||
| 1785 | put_unaligned_be16(0xffff, &buf[10]); | ||
| 1786 | /* Maximum prefetch ceiling */ | ||
| 1787 | } | ||
| 1788 | buf += 12; | ||
| 1789 | } | ||
| 1790 | |||
| 1791 | /* Check that a valid page was requested and the mode data length | ||
| 1792 | * isn't too long. */ | ||
| 1793 | len = buf - buf0; | ||
| 1794 | if (!valid_page || len > limit) { | ||
| 1795 | curlun->sense_data = SS_INVALID_FIELD_IN_CDB; | ||
| 1796 | return -EINVAL; | ||
| 1797 | } | ||
| 1798 | |||
| 1799 | /* Store the mode data length */ | ||
| 1800 | if (mscmnd == MODE_SENSE) | ||
| 1801 | buf0[0] = len - 1; | ||
| 1802 | else | ||
| 1803 | put_unaligned_be16(len - 2, buf0); | ||
| 1804 | return len; | ||
| 1805 | } | ||
| 1806 | |||
| 1807 | |||
| 1808 | static int do_start_stop(struct fsg_dev *fsg) | ||
| 1809 | { | ||
| 1810 | struct fsg_lun *curlun = fsg->curlun; | ||
| 1811 | int loej, start; | ||
| 1812 | |||
| 1813 | if (!mod_data.removable) { | ||
| 1814 | curlun->sense_data = SS_INVALID_COMMAND; | ||
| 1815 | return -EINVAL; | ||
| 1816 | } | ||
| 1817 | |||
| 1818 | // int immed = fsg->cmnd[1] & 0x01; | ||
| 1819 | loej = fsg->cmnd[4] & 0x02; | ||
| 1820 | start = fsg->cmnd[4] & 0x01; | ||
| 1821 | |||
| 1822 | #ifdef CONFIG_USB_FILE_STORAGE_TEST | ||
| 1823 | if ((fsg->cmnd[1] & ~0x01) != 0 || // Mask away Immed | ||
| 1824 | (fsg->cmnd[4] & ~0x03) != 0) { // Mask LoEj, Start | ||
| 1825 | curlun->sense_data = SS_INVALID_FIELD_IN_CDB; | ||
| 1826 | return -EINVAL; | ||
| 1827 | } | ||
| 1828 | |||
| 1829 | if (!start) { | ||
| 1830 | |||
| 1831 | /* Are we allowed to unload the media? */ | ||
| 1832 | if (curlun->prevent_medium_removal) { | ||
| 1833 | LDBG(curlun, "unload attempt prevented\n"); | ||
| 1834 | curlun->sense_data = SS_MEDIUM_REMOVAL_PREVENTED; | ||
| 1835 | return -EINVAL; | ||
| 1836 | } | ||
| 1837 | if (loej) { // Simulate an unload/eject | ||
| 1838 | up_read(&fsg->filesem); | ||
| 1839 | down_write(&fsg->filesem); | ||
| 1840 | fsg_lun_close(curlun); | ||
| 1841 | up_write(&fsg->filesem); | ||
| 1842 | down_read(&fsg->filesem); | ||
| 1843 | } | ||
| 1844 | } else { | ||
| 1845 | |||
| 1846 | /* Our emulation doesn't support mounting; the medium is | ||
| 1847 | * available for use as soon as it is loaded. */ | ||
| 1848 | if (!fsg_lun_is_open(curlun)) { | ||
| 1849 | curlun->sense_data = SS_MEDIUM_NOT_PRESENT; | ||
| 1850 | return -EINVAL; | ||
| 1851 | } | ||
| 1852 | } | ||
| 1853 | #endif | ||
| 1854 | return 0; | ||
| 1855 | } | ||
| 1856 | |||
| 1857 | |||
| 1858 | static int do_prevent_allow(struct fsg_dev *fsg) | ||
| 1859 | { | ||
| 1860 | struct fsg_lun *curlun = fsg->curlun; | ||
| 1861 | int prevent; | ||
| 1862 | |||
| 1863 | if (!mod_data.removable) { | ||
| 1864 | curlun->sense_data = SS_INVALID_COMMAND; | ||
| 1865 | return -EINVAL; | ||
| 1866 | } | ||
| 1867 | |||
| 1868 | prevent = fsg->cmnd[4] & 0x01; | ||
| 1869 | if ((fsg->cmnd[4] & ~0x01) != 0) { // Mask away Prevent | ||
| 1870 | curlun->sense_data = SS_INVALID_FIELD_IN_CDB; | ||
| 1871 | return -EINVAL; | ||
| 1872 | } | ||
| 1873 | |||
| 1874 | if (curlun->prevent_medium_removal && !prevent) | ||
| 1875 | fsg_lun_fsync_sub(curlun); | ||
| 1876 | curlun->prevent_medium_removal = prevent; | ||
| 1877 | return 0; | ||
| 1878 | } | ||
| 1879 | |||
| 1880 | |||
| 1881 | static int do_read_format_capacities(struct fsg_dev *fsg, | ||
| 1882 | struct fsg_buffhd *bh) | ||
| 1883 | { | ||
| 1884 | struct fsg_lun *curlun = fsg->curlun; | ||
| 1885 | u8 *buf = (u8 *) bh->buf; | ||
| 1886 | |||
| 1887 | buf[0] = buf[1] = buf[2] = 0; | ||
| 1888 | buf[3] = 8; // Only the Current/Maximum Capacity Descriptor | ||
| 1889 | buf += 4; | ||
| 1890 | |||
| 1891 | put_unaligned_be32(curlun->num_sectors, &buf[0]); | ||
| 1892 | /* Number of blocks */ | ||
| 1893 | put_unaligned_be32(512, &buf[4]); /* Block length */ | ||
| 1894 | buf[4] = 0x02; /* Current capacity */ | ||
| 1895 | return 12; | ||
| 1896 | } | ||
| 1897 | |||
| 1898 | |||
| 1899 | static int do_mode_select(struct fsg_dev *fsg, struct fsg_buffhd *bh) | ||
| 1900 | { | ||
| 1901 | struct fsg_lun *curlun = fsg->curlun; | ||
| 1902 | |||
| 1903 | /* We don't support MODE SELECT */ | ||
| 1904 | curlun->sense_data = SS_INVALID_COMMAND; | ||
| 1905 | return -EINVAL; | ||
| 1906 | } | ||
| 1907 | |||
| 1908 | |||
| 1909 | /*-------------------------------------------------------------------------*/ | ||
| 1910 | |||
| 1911 | static int halt_bulk_in_endpoint(struct fsg_dev *fsg) | ||
| 1912 | { | ||
| 1913 | int rc; | ||
| 1914 | |||
| 1915 | rc = fsg_set_halt(fsg, fsg->bulk_in); | ||
| 1916 | if (rc == -EAGAIN) | ||
| 1917 | VDBG(fsg, "delayed bulk-in endpoint halt\n"); | ||
| 1918 | while (rc != 0) { | ||
| 1919 | if (rc != -EAGAIN) { | ||
| 1920 | WARNING(fsg, "usb_ep_set_halt -> %d\n", rc); | ||
| 1921 | rc = 0; | ||
| 1922 | break; | ||
| 1923 | } | ||
| 1924 | |||
| 1925 | /* Wait for a short time and then try again */ | ||
| 1926 | if (msleep_interruptible(100) != 0) | ||
| 1927 | return -EINTR; | ||
| 1928 | rc = usb_ep_set_halt(fsg->bulk_in); | ||
| 1929 | } | ||
| 1930 | return rc; | ||
| 1931 | } | ||
| 1932 | |||
| 1933 | static int wedge_bulk_in_endpoint(struct fsg_dev *fsg) | ||
| 1934 | { | ||
| 1935 | int rc; | ||
| 1936 | |||
| 1937 | DBG(fsg, "bulk-in set wedge\n"); | ||
| 1938 | rc = usb_ep_set_wedge(fsg->bulk_in); | ||
| 1939 | if (rc == -EAGAIN) | ||
| 1940 | VDBG(fsg, "delayed bulk-in endpoint wedge\n"); | ||
| 1941 | while (rc != 0) { | ||
| 1942 | if (rc != -EAGAIN) { | ||
| 1943 | WARNING(fsg, "usb_ep_set_wedge -> %d\n", rc); | ||
| 1944 | rc = 0; | ||
| 1945 | break; | ||
| 1946 | } | ||
| 1947 | |||
| 1948 | /* Wait for a short time and then try again */ | ||
| 1949 | if (msleep_interruptible(100) != 0) | ||
| 1950 | return -EINTR; | ||
| 1951 | rc = usb_ep_set_wedge(fsg->bulk_in); | ||
| 1952 | } | ||
| 1953 | return rc; | ||
| 1954 | } | ||
| 1955 | |||
| 1956 | static int throw_away_data(struct fsg_dev *fsg) | ||
| 1957 | { | ||
| 1958 | struct fsg_buffhd *bh; | ||
| 1959 | u32 amount; | ||
| 1960 | int rc; | ||
| 1961 | |||
| 1962 | while ((bh = fsg->next_buffhd_to_drain)->state != BUF_STATE_EMPTY || | ||
| 1963 | fsg->usb_amount_left > 0) { | ||
| 1964 | |||
| 1965 | /* Throw away the data in a filled buffer */ | ||
| 1966 | if (bh->state == BUF_STATE_FULL) { | ||
| 1967 | smp_rmb(); | ||
| 1968 | bh->state = BUF_STATE_EMPTY; | ||
| 1969 | fsg->next_buffhd_to_drain = bh->next; | ||
| 1970 | |||
| 1971 | /* A short packet or an error ends everything */ | ||
| 1972 | if (bh->outreq->actual != bh->outreq->length || | ||
| 1973 | bh->outreq->status != 0) { | ||
| 1974 | raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT); | ||
| 1975 | return -EINTR; | ||
| 1976 | } | ||
| 1977 | continue; | ||
| 1978 | } | ||
| 1979 | |||
| 1980 | /* Try to submit another request if we need one */ | ||
| 1981 | bh = fsg->next_buffhd_to_fill; | ||
| 1982 | if (bh->state == BUF_STATE_EMPTY && fsg->usb_amount_left > 0) { | ||
| 1983 | amount = min(fsg->usb_amount_left, | ||
| 1984 | (u32) mod_data.buflen); | ||
| 1985 | |||
| 1986 | /* amount is always divisible by 512, hence by | ||
| 1987 | * the bulk-out maxpacket size */ | ||
| 1988 | bh->outreq->length = bh->bulk_out_intended_length = | ||
| 1989 | amount; | ||
| 1990 | bh->outreq->short_not_ok = 1; | ||
| 1991 | start_transfer(fsg, fsg->bulk_out, bh->outreq, | ||
| 1992 | &bh->outreq_busy, &bh->state); | ||
| 1993 | fsg->next_buffhd_to_fill = bh->next; | ||
| 1994 | fsg->usb_amount_left -= amount; | ||
| 1995 | continue; | ||
| 1996 | } | ||
| 1997 | |||
| 1998 | /* Otherwise wait for something to happen */ | ||
| 1999 | rc = sleep_thread(fsg); | ||
| 2000 | if (rc) | ||
| 2001 | return rc; | ||
| 2002 | } | ||
| 2003 | return 0; | ||
| 2004 | } | ||
| 2005 | |||
| 2006 | |||
| 2007 | static int finish_reply(struct fsg_dev *fsg) | ||
| 2008 | { | ||
| 2009 | struct fsg_buffhd *bh = fsg->next_buffhd_to_fill; | ||
| 2010 | int rc = 0; | ||
| 2011 | |||
| 2012 | switch (fsg->data_dir) { | ||
| 2013 | case DATA_DIR_NONE: | ||
| 2014 | break; // Nothing to send | ||
| 2015 | |||
| 2016 | /* If we don't know whether the host wants to read or write, | ||
| 2017 | * this must be CB or CBI with an unknown command. We mustn't | ||
| 2018 | * try to send or receive any data. So stall both bulk pipes | ||
| 2019 | * if we can and wait for a reset. */ | ||
| 2020 | case DATA_DIR_UNKNOWN: | ||
| 2021 | if (mod_data.can_stall) { | ||
| 2022 | fsg_set_halt(fsg, fsg->bulk_out); | ||
| 2023 | rc = halt_bulk_in_endpoint(fsg); | ||
| 2024 | } | ||
| 2025 | break; | ||
| 2026 | |||
| 2027 | /* All but the last buffer of data must have already been sent */ | ||
| 2028 | case DATA_DIR_TO_HOST: | ||
| 2029 | if (fsg->data_size == 0) | ||
| 2030 | ; // Nothing to send | ||
| 2031 | |||
| 2032 | /* If there's no residue, simply send the last buffer */ | ||
| 2033 | else if (fsg->residue == 0) { | ||
| 2034 | bh->inreq->zero = 0; | ||
| 2035 | start_transfer(fsg, fsg->bulk_in, bh->inreq, | ||
| 2036 | &bh->inreq_busy, &bh->state); | ||
| 2037 | fsg->next_buffhd_to_fill = bh->next; | ||
| 2038 | } | ||
| 2039 | |||
| 2040 | /* There is a residue. For CB and CBI, simply mark the end | ||
| 2041 | * of the data with a short packet. However, if we are | ||
| 2042 | * allowed to stall, there was no data at all (residue == | ||
| 2043 | * data_size), and the command failed (invalid LUN or | ||
| 2044 | * sense data is set), then halt the bulk-in endpoint | ||
| 2045 | * instead. */ | ||
| 2046 | else if (!transport_is_bbb()) { | ||
| 2047 | if (mod_data.can_stall && | ||
| 2048 | fsg->residue == fsg->data_size && | ||
| 2049 | (!fsg->curlun || fsg->curlun->sense_data != SS_NO_SENSE)) { | ||
| 2050 | bh->state = BUF_STATE_EMPTY; | ||
| 2051 | rc = halt_bulk_in_endpoint(fsg); | ||
| 2052 | } else { | ||
| 2053 | bh->inreq->zero = 1; | ||
| 2054 | start_transfer(fsg, fsg->bulk_in, bh->inreq, | ||
| 2055 | &bh->inreq_busy, &bh->state); | ||
| 2056 | fsg->next_buffhd_to_fill = bh->next; | ||
| 2057 | } | ||
| 2058 | } | ||
| 2059 | |||
| 2060 | /* | ||
| 2061 | * For Bulk-only, mark the end of the data with a short | ||
| 2062 | * packet. If we are allowed to stall, halt the bulk-in | ||
| 2063 | * endpoint. (Note: This violates the Bulk-Only Transport | ||
| 2064 | * specification, which requires us to pad the data if we | ||
| 2065 | * don't halt the endpoint. Presumably nobody will mind.) | ||
| 2066 | */ | ||
| 2067 | else { | ||
| 2068 | bh->inreq->zero = 1; | ||
| 2069 | start_transfer(fsg, fsg->bulk_in, bh->inreq, | ||
| 2070 | &bh->inreq_busy, &bh->state); | ||
| 2071 | fsg->next_buffhd_to_fill = bh->next; | ||
| 2072 | if (mod_data.can_stall) | ||
| 2073 | rc = halt_bulk_in_endpoint(fsg); | ||
| 2074 | } | ||
| 2075 | break; | ||
| 2076 | |||
| 2077 | /* We have processed all we want from the data the host has sent. | ||
| 2078 | * There may still be outstanding bulk-out requests. */ | ||
| 2079 | case DATA_DIR_FROM_HOST: | ||
| 2080 | if (fsg->residue == 0) | ||
| 2081 | ; // Nothing to receive | ||
| 2082 | |||
| 2083 | /* Did the host stop sending unexpectedly early? */ | ||
| 2084 | else if (fsg->short_packet_received) { | ||
| 2085 | raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT); | ||
| 2086 | rc = -EINTR; | ||
| 2087 | } | ||
| 2088 | |||
| 2089 | /* We haven't processed all the incoming data. Even though | ||
| 2090 | * we may be allowed to stall, doing so would cause a race. | ||
| 2091 | * The controller may already have ACK'ed all the remaining | ||
| 2092 | * bulk-out packets, in which case the host wouldn't see a | ||
| 2093 | * STALL. Not realizing the endpoint was halted, it wouldn't | ||
| 2094 | * clear the halt -- leading to problems later on. */ | ||
| 2095 | #if 0 | ||
| 2096 | else if (mod_data.can_stall) { | ||
| 2097 | fsg_set_halt(fsg, fsg->bulk_out); | ||
| 2098 | raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT); | ||
| 2099 | rc = -EINTR; | ||
| 2100 | } | ||
| 2101 | #endif | ||
| 2102 | |||
| 2103 | /* We can't stall. Read in the excess data and throw it | ||
| 2104 | * all away. */ | ||
| 2105 | else | ||
| 2106 | rc = throw_away_data(fsg); | ||
| 2107 | break; | ||
| 2108 | } | ||
| 2109 | return rc; | ||
| 2110 | } | ||
| 2111 | |||
| 2112 | |||
| 2113 | static int send_status(struct fsg_dev *fsg) | ||
| 2114 | { | ||
| 2115 | struct fsg_lun *curlun = fsg->curlun; | ||
| 2116 | struct fsg_buffhd *bh; | ||
| 2117 | int rc; | ||
| 2118 | u8 status = USB_STATUS_PASS; | ||
| 2119 | u32 sd, sdinfo = 0; | ||
| 2120 | |||
| 2121 | /* Wait for the next buffer to become available */ | ||
| 2122 | bh = fsg->next_buffhd_to_fill; | ||
| 2123 | while (bh->state != BUF_STATE_EMPTY) { | ||
| 2124 | rc = sleep_thread(fsg); | ||
| 2125 | if (rc) | ||
| 2126 | return rc; | ||
| 2127 | } | ||
| 2128 | |||
| 2129 | if (curlun) { | ||
| 2130 | sd = curlun->sense_data; | ||
| 2131 | sdinfo = curlun->sense_data_info; | ||
| 2132 | } else if (fsg->bad_lun_okay) | ||
| 2133 | sd = SS_NO_SENSE; | ||
| 2134 | else | ||
| 2135 | sd = SS_LOGICAL_UNIT_NOT_SUPPORTED; | ||
| 2136 | |||
| 2137 | if (fsg->phase_error) { | ||
| 2138 | DBG(fsg, "sending phase-error status\n"); | ||
| 2139 | status = USB_STATUS_PHASE_ERROR; | ||
| 2140 | sd = SS_INVALID_COMMAND; | ||
| 2141 | } else if (sd != SS_NO_SENSE) { | ||
| 2142 | DBG(fsg, "sending command-failure status\n"); | ||
| 2143 | status = USB_STATUS_FAIL; | ||
| 2144 | VDBG(fsg, " sense data: SK x%02x, ASC x%02x, ASCQ x%02x;" | ||
| 2145 | " info x%x\n", | ||
| 2146 | SK(sd), ASC(sd), ASCQ(sd), sdinfo); | ||
| 2147 | } | ||
| 2148 | |||
| 2149 | if (transport_is_bbb()) { | ||
| 2150 | struct bulk_cs_wrap *csw = bh->buf; | ||
| 2151 | |||
| 2152 | /* Store and send the Bulk-only CSW */ | ||
| 2153 | csw->Signature = cpu_to_le32(USB_BULK_CS_SIG); | ||
| 2154 | csw->Tag = fsg->tag; | ||
| 2155 | csw->Residue = cpu_to_le32(fsg->residue); | ||
| 2156 | csw->Status = status; | ||
| 2157 | |||
| 2158 | bh->inreq->length = USB_BULK_CS_WRAP_LEN; | ||
| 2159 | bh->inreq->zero = 0; | ||
| 2160 | start_transfer(fsg, fsg->bulk_in, bh->inreq, | ||
| 2161 | &bh->inreq_busy, &bh->state); | ||
| 2162 | |||
| 2163 | } else if (mod_data.transport_type == USB_PR_CB) { | ||
| 2164 | |||
| 2165 | /* Control-Bulk transport has no status phase! */ | ||
| 2166 | return 0; | ||
| 2167 | |||
| 2168 | } else { // USB_PR_CBI | ||
| 2169 | struct interrupt_data *buf = bh->buf; | ||
| 2170 | |||
| 2171 | /* Store and send the Interrupt data. UFI sends the ASC | ||
| 2172 | * and ASCQ bytes. Everything else sends a Type (which | ||
| 2173 | * is always 0) and the status Value. */ | ||
| 2174 | if (mod_data.protocol_type == USB_SC_UFI) { | ||
| 2175 | buf->bType = ASC(sd); | ||
| 2176 | buf->bValue = ASCQ(sd); | ||
| 2177 | } else { | ||
| 2178 | buf->bType = 0; | ||
| 2179 | buf->bValue = status; | ||
| 2180 | } | ||
| 2181 | fsg->intreq->length = CBI_INTERRUPT_DATA_LEN; | ||
| 2182 | |||
| 2183 | fsg->intr_buffhd = bh; // Point to the right buffhd | ||
| 2184 | fsg->intreq->buf = bh->inreq->buf; | ||
| 2185 | fsg->intreq->context = bh; | ||
| 2186 | start_transfer(fsg, fsg->intr_in, fsg->intreq, | ||
| 2187 | &fsg->intreq_busy, &bh->state); | ||
| 2188 | } | ||
| 2189 | |||
| 2190 | fsg->next_buffhd_to_fill = bh->next; | ||
| 2191 | return 0; | ||
| 2192 | } | ||
| 2193 | |||
| 2194 | |||
| 2195 | /*-------------------------------------------------------------------------*/ | ||
| 2196 | |||
| 2197 | /* Check whether the command is properly formed and whether its data size | ||
| 2198 | * and direction agree with the values we already have. */ | ||
| 2199 | static int check_command(struct fsg_dev *fsg, int cmnd_size, | ||
| 2200 | enum data_direction data_dir, unsigned int mask, | ||
| 2201 | int needs_medium, const char *name) | ||
| 2202 | { | ||
| 2203 | int i; | ||
| 2204 | int lun = fsg->cmnd[1] >> 5; | ||
| 2205 | static const char dirletter[4] = {'u', 'o', 'i', 'n'}; | ||
| 2206 | char hdlen[20]; | ||
| 2207 | struct fsg_lun *curlun; | ||
| 2208 | |||
| 2209 | /* Adjust the expected cmnd_size for protocol encapsulation padding. | ||
| 2210 | * Transparent SCSI doesn't pad. */ | ||
| 2211 | if (protocol_is_scsi()) | ||
| 2212 | ; | ||
| 2213 | |||
| 2214 | /* There's some disagreement as to whether RBC pads commands or not. | ||
| 2215 | * We'll play it safe and accept either form. */ | ||
| 2216 | else if (mod_data.protocol_type == USB_SC_RBC) { | ||
| 2217 | if (fsg->cmnd_size == 12) | ||
| 2218 | cmnd_size = 12; | ||
| 2219 | |||
| 2220 | /* All the other protocols pad to 12 bytes */ | ||
| 2221 | } else | ||
| 2222 | cmnd_size = 12; | ||
| 2223 | |||
| 2224 | hdlen[0] = 0; | ||
| 2225 | if (fsg->data_dir != DATA_DIR_UNKNOWN) | ||
| 2226 | sprintf(hdlen, ", H%c=%u", dirletter[(int) fsg->data_dir], | ||
| 2227 | fsg->data_size); | ||
| 2228 | VDBG(fsg, "SCSI command: %s; Dc=%d, D%c=%u; Hc=%d%s\n", | ||
| 2229 | name, cmnd_size, dirletter[(int) data_dir], | ||
| 2230 | fsg->data_size_from_cmnd, fsg->cmnd_size, hdlen); | ||
| 2231 | |||
| 2232 | /* We can't reply at all until we know the correct data direction | ||
| 2233 | * and size. */ | ||
| 2234 | if (fsg->data_size_from_cmnd == 0) | ||
| 2235 | data_dir = DATA_DIR_NONE; | ||
| 2236 | if (fsg->data_dir == DATA_DIR_UNKNOWN) { // CB or CBI | ||
| 2237 | fsg->data_dir = data_dir; | ||
| 2238 | fsg->data_size = fsg->data_size_from_cmnd; | ||
| 2239 | |||
| 2240 | } else { // Bulk-only | ||
| 2241 | if (fsg->data_size < fsg->data_size_from_cmnd) { | ||
| 2242 | |||
| 2243 | /* Host data size < Device data size is a phase error. | ||
| 2244 | * Carry out the command, but only transfer as much | ||
| 2245 | * as we are allowed. */ | ||
| 2246 | fsg->data_size_from_cmnd = fsg->data_size; | ||
| 2247 | fsg->phase_error = 1; | ||
| 2248 | } | ||
| 2249 | } | ||
| 2250 | fsg->residue = fsg->usb_amount_left = fsg->data_size; | ||
| 2251 | |||
| 2252 | /* Conflicting data directions is a phase error */ | ||
| 2253 | if (fsg->data_dir != data_dir && fsg->data_size_from_cmnd > 0) { | ||
| 2254 | fsg->phase_error = 1; | ||
| 2255 | return -EINVAL; | ||
| 2256 | } | ||
| 2257 | |||
| 2258 | /* Verify the length of the command itself */ | ||
| 2259 | if (cmnd_size != fsg->cmnd_size) { | ||
| 2260 | |||
| 2261 | /* Special case workaround: There are plenty of buggy SCSI | ||
| 2262 | * implementations. Many have issues with cbw->Length | ||
| 2263 | * field passing a wrong command size. For those cases we | ||
| 2264 | * always try to work around the problem by using the length | ||
| 2265 | * sent by the host side provided it is at least as large | ||
| 2266 | * as the correct command length. | ||
| 2267 | * Examples of such cases would be MS-Windows, which issues | ||
| 2268 | * REQUEST SENSE with cbw->Length == 12 where it should | ||
| 2269 | * be 6, and xbox360 issuing INQUIRY, TEST UNIT READY and | ||
| 2270 | * REQUEST SENSE with cbw->Length == 10 where it should | ||
| 2271 | * be 6 as well. | ||
| 2272 | */ | ||
| 2273 | if (cmnd_size <= fsg->cmnd_size) { | ||
| 2274 | DBG(fsg, "%s is buggy! Expected length %d " | ||
| 2275 | "but we got %d\n", name, | ||
| 2276 | cmnd_size, fsg->cmnd_size); | ||
| 2277 | cmnd_size = fsg->cmnd_size; | ||
| 2278 | } else { | ||
| 2279 | fsg->phase_error = 1; | ||
| 2280 | return -EINVAL; | ||
| 2281 | } | ||
| 2282 | } | ||
| 2283 | |||
| 2284 | /* Check that the LUN values are consistent */ | ||
| 2285 | if (transport_is_bbb()) { | ||
| 2286 | if (fsg->lun != lun) | ||
| 2287 | DBG(fsg, "using LUN %d from CBW, " | ||
| 2288 | "not LUN %d from CDB\n", | ||
| 2289 | fsg->lun, lun); | ||
| 2290 | } else | ||
| 2291 | fsg->lun = lun; // Use LUN from the command | ||
| 2292 | |||
| 2293 | /* Check the LUN */ | ||
| 2294 | if (fsg->lun < fsg->nluns) { | ||
| 2295 | fsg->curlun = curlun = &fsg->luns[fsg->lun]; | ||
| 2296 | if (fsg->cmnd[0] != REQUEST_SENSE) { | ||
| 2297 | curlun->sense_data = SS_NO_SENSE; | ||
| 2298 | curlun->sense_data_info = 0; | ||
| 2299 | curlun->info_valid = 0; | ||
| 2300 | } | ||
| 2301 | } else { | ||
| 2302 | fsg->curlun = curlun = NULL; | ||
| 2303 | fsg->bad_lun_okay = 0; | ||
| 2304 | |||
| 2305 | /* INQUIRY and REQUEST SENSE commands are explicitly allowed | ||
| 2306 | * to use unsupported LUNs; all others may not. */ | ||
| 2307 | if (fsg->cmnd[0] != INQUIRY && | ||
| 2308 | fsg->cmnd[0] != REQUEST_SENSE) { | ||
| 2309 | DBG(fsg, "unsupported LUN %d\n", fsg->lun); | ||
| 2310 | return -EINVAL; | ||
| 2311 | } | ||
| 2312 | } | ||
| 2313 | |||
| 2314 | /* If a unit attention condition exists, only INQUIRY and | ||
| 2315 | * REQUEST SENSE commands are allowed; anything else must fail. */ | ||
| 2316 | if (curlun && curlun->unit_attention_data != SS_NO_SENSE && | ||
| 2317 | fsg->cmnd[0] != INQUIRY && | ||
| 2318 | fsg->cmnd[0] != REQUEST_SENSE) { | ||
| 2319 | curlun->sense_data = curlun->unit_attention_data; | ||
| 2320 | curlun->unit_attention_data = SS_NO_SENSE; | ||
| 2321 | return -EINVAL; | ||
| 2322 | } | ||
| 2323 | |||
| 2324 | /* Check that only command bytes listed in the mask are non-zero */ | ||
| 2325 | fsg->cmnd[1] &= 0x1f; // Mask away the LUN | ||
| 2326 | for (i = 1; i < cmnd_size; ++i) { | ||
| 2327 | if (fsg->cmnd[i] && !(mask & (1 << i))) { | ||
| 2328 | if (curlun) | ||
| 2329 | curlun->sense_data = SS_INVALID_FIELD_IN_CDB; | ||
| 2330 | return -EINVAL; | ||
| 2331 | } | ||
| 2332 | } | ||
| 2333 | |||
| 2334 | /* If the medium isn't mounted and the command needs to access | ||
| 2335 | * it, return an error. */ | ||
| 2336 | if (curlun && !fsg_lun_is_open(curlun) && needs_medium) { | ||
| 2337 | curlun->sense_data = SS_MEDIUM_NOT_PRESENT; | ||
| 2338 | return -EINVAL; | ||
| 2339 | } | ||
| 2340 | |||
| 2341 | return 0; | ||
| 2342 | } | ||
| 2343 | |||
| 2344 | |||
| 2345 | static int do_scsi_command(struct fsg_dev *fsg) | ||
| 2346 | { | ||
| 2347 | struct fsg_buffhd *bh; | ||
| 2348 | int rc; | ||
| 2349 | int reply = -EINVAL; | ||
| 2350 | int i; | ||
| 2351 | static char unknown[16]; | ||
| 2352 | |||
| 2353 | dump_cdb(fsg); | ||
| 2354 | |||
| 2355 | /* Wait for the next buffer to become available for data or status */ | ||
| 2356 | bh = fsg->next_buffhd_to_drain = fsg->next_buffhd_to_fill; | ||
| 2357 | while (bh->state != BUF_STATE_EMPTY) { | ||
| 2358 | rc = sleep_thread(fsg); | ||
| 2359 | if (rc) | ||
| 2360 | return rc; | ||
| 2361 | } | ||
| 2362 | fsg->phase_error = 0; | ||
| 2363 | fsg->short_packet_received = 0; | ||
| 2364 | |||
| 2365 | down_read(&fsg->filesem); // We're using the backing file | ||
| 2366 | switch (fsg->cmnd[0]) { | ||
| 2367 | |||
| 2368 | case INQUIRY: | ||
| 2369 | fsg->data_size_from_cmnd = fsg->cmnd[4]; | ||
| 2370 | if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST, | ||
| 2371 | (1<<4), 0, | ||
| 2372 | "INQUIRY")) == 0) | ||
| 2373 | reply = do_inquiry(fsg, bh); | ||
| 2374 | break; | ||
| 2375 | |||
| 2376 | case MODE_SELECT: | ||
| 2377 | fsg->data_size_from_cmnd = fsg->cmnd[4]; | ||
| 2378 | if ((reply = check_command(fsg, 6, DATA_DIR_FROM_HOST, | ||
| 2379 | (1<<1) | (1<<4), 0, | ||
| 2380 | "MODE SELECT(6)")) == 0) | ||
| 2381 | reply = do_mode_select(fsg, bh); | ||
| 2382 | break; | ||
| 2383 | |||
| 2384 | case MODE_SELECT_10: | ||
| 2385 | fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]); | ||
| 2386 | if ((reply = check_command(fsg, 10, DATA_DIR_FROM_HOST, | ||
| 2387 | (1<<1) | (3<<7), 0, | ||
| 2388 | "MODE SELECT(10)")) == 0) | ||
| 2389 | reply = do_mode_select(fsg, bh); | ||
| 2390 | break; | ||
| 2391 | |||
| 2392 | case MODE_SENSE: | ||
| 2393 | fsg->data_size_from_cmnd = fsg->cmnd[4]; | ||
| 2394 | if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST, | ||
| 2395 | (1<<1) | (1<<2) | (1<<4), 0, | ||
| 2396 | "MODE SENSE(6)")) == 0) | ||
| 2397 | reply = do_mode_sense(fsg, bh); | ||
| 2398 | break; | ||
| 2399 | |||
| 2400 | case MODE_SENSE_10: | ||
| 2401 | fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]); | ||
| 2402 | if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST, | ||
| 2403 | (1<<1) | (1<<2) | (3<<7), 0, | ||
| 2404 | "MODE SENSE(10)")) == 0) | ||
| 2405 | reply = do_mode_sense(fsg, bh); | ||
| 2406 | break; | ||
| 2407 | |||
| 2408 | case ALLOW_MEDIUM_REMOVAL: | ||
| 2409 | fsg->data_size_from_cmnd = 0; | ||
| 2410 | if ((reply = check_command(fsg, 6, DATA_DIR_NONE, | ||
| 2411 | (1<<4), 0, | ||
| 2412 | "PREVENT-ALLOW MEDIUM REMOVAL")) == 0) | ||
| 2413 | reply = do_prevent_allow(fsg); | ||
| 2414 | break; | ||
| 2415 | |||
| 2416 | case READ_6: | ||
| 2417 | i = fsg->cmnd[4]; | ||
| 2418 | fsg->data_size_from_cmnd = (i == 0 ? 256 : i) << 9; | ||
| 2419 | if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST, | ||
| 2420 | (7<<1) | (1<<4), 1, | ||
| 2421 | "READ(6)")) == 0) | ||
| 2422 | reply = do_read(fsg); | ||
| 2423 | break; | ||
| 2424 | |||
| 2425 | case READ_10: | ||
| 2426 | fsg->data_size_from_cmnd = | ||
| 2427 | get_unaligned_be16(&fsg->cmnd[7]) << 9; | ||
| 2428 | if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST, | ||
| 2429 | (1<<1) | (0xf<<2) | (3<<7), 1, | ||
| 2430 | "READ(10)")) == 0) | ||
| 2431 | reply = do_read(fsg); | ||
| 2432 | break; | ||
| 2433 | |||
| 2434 | case READ_12: | ||
| 2435 | fsg->data_size_from_cmnd = | ||
| 2436 | get_unaligned_be32(&fsg->cmnd[6]) << 9; | ||
| 2437 | if ((reply = check_command(fsg, 12, DATA_DIR_TO_HOST, | ||
| 2438 | (1<<1) | (0xf<<2) | (0xf<<6), 1, | ||
| 2439 | "READ(12)")) == 0) | ||
| 2440 | reply = do_read(fsg); | ||
| 2441 | break; | ||
| 2442 | |||
| 2443 | case READ_CAPACITY: | ||
| 2444 | fsg->data_size_from_cmnd = 8; | ||
| 2445 | if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST, | ||
| 2446 | (0xf<<2) | (1<<8), 1, | ||
| 2447 | "READ CAPACITY")) == 0) | ||
| 2448 | reply = do_read_capacity(fsg, bh); | ||
| 2449 | break; | ||
| 2450 | |||
| 2451 | case READ_HEADER: | ||
| 2452 | if (!mod_data.cdrom) | ||
| 2453 | goto unknown_cmnd; | ||
| 2454 | fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]); | ||
| 2455 | if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST, | ||
| 2456 | (3<<7) | (0x1f<<1), 1, | ||
| 2457 | "READ HEADER")) == 0) | ||
| 2458 | reply = do_read_header(fsg, bh); | ||
| 2459 | break; | ||
| 2460 | |||
| 2461 | case READ_TOC: | ||
| 2462 | if (!mod_data.cdrom) | ||
| 2463 | goto unknown_cmnd; | ||
| 2464 | fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]); | ||
| 2465 | if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST, | ||
| 2466 | (7<<6) | (1<<1), 1, | ||
| 2467 | "READ TOC")) == 0) | ||
| 2468 | reply = do_read_toc(fsg, bh); | ||
| 2469 | break; | ||
| 2470 | |||
| 2471 | case READ_FORMAT_CAPACITIES: | ||
| 2472 | fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]); | ||
| 2473 | if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST, | ||
| 2474 | (3<<7), 1, | ||
| 2475 | "READ FORMAT CAPACITIES")) == 0) | ||
| 2476 | reply = do_read_format_capacities(fsg, bh); | ||
| 2477 | break; | ||
| 2478 | |||
| 2479 | case REQUEST_SENSE: | ||
| 2480 | fsg->data_size_from_cmnd = fsg->cmnd[4]; | ||
| 2481 | if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST, | ||
| 2482 | (1<<4), 0, | ||
| 2483 | "REQUEST SENSE")) == 0) | ||
| 2484 | reply = do_request_sense(fsg, bh); | ||
| 2485 | break; | ||
| 2486 | |||
| 2487 | case START_STOP: | ||
| 2488 | fsg->data_size_from_cmnd = 0; | ||
| 2489 | if ((reply = check_command(fsg, 6, DATA_DIR_NONE, | ||
| 2490 | (1<<1) | (1<<4), 0, | ||
| 2491 | "START-STOP UNIT")) == 0) | ||
| 2492 | reply = do_start_stop(fsg); | ||
| 2493 | break; | ||
| 2494 | |||
| 2495 | case SYNCHRONIZE_CACHE: | ||
| 2496 | fsg->data_size_from_cmnd = 0; | ||
| 2497 | if ((reply = check_command(fsg, 10, DATA_DIR_NONE, | ||
| 2498 | (0xf<<2) | (3<<7), 1, | ||
| 2499 | "SYNCHRONIZE CACHE")) == 0) | ||
| 2500 | reply = do_synchronize_cache(fsg); | ||
| 2501 | break; | ||
| 2502 | |||
| 2503 | case TEST_UNIT_READY: | ||
| 2504 | fsg->data_size_from_cmnd = 0; | ||
| 2505 | reply = check_command(fsg, 6, DATA_DIR_NONE, | ||
| 2506 | 0, 1, | ||
| 2507 | "TEST UNIT READY"); | ||
| 2508 | break; | ||
| 2509 | |||
| 2510 | /* Although optional, this command is used by MS-Windows. We | ||
| 2511 | * support a minimal version: BytChk must be 0. */ | ||
| 2512 | case VERIFY: | ||
| 2513 | fsg->data_size_from_cmnd = 0; | ||
| 2514 | if ((reply = check_command(fsg, 10, DATA_DIR_NONE, | ||
| 2515 | (1<<1) | (0xf<<2) | (3<<7), 1, | ||
| 2516 | "VERIFY")) == 0) | ||
| 2517 | reply = do_verify(fsg); | ||
| 2518 | break; | ||
| 2519 | |||
| 2520 | case WRITE_6: | ||
| 2521 | i = fsg->cmnd[4]; | ||
| 2522 | fsg->data_size_from_cmnd = (i == 0 ? 256 : i) << 9; | ||
| 2523 | if ((reply = check_command(fsg, 6, DATA_DIR_FROM_HOST, | ||
| 2524 | (7<<1) | (1<<4), 1, | ||
| 2525 | "WRITE(6)")) == 0) | ||
| 2526 | reply = do_write(fsg); | ||
| 2527 | break; | ||
| 2528 | |||
| 2529 | case WRITE_10: | ||
| 2530 | fsg->data_size_from_cmnd = | ||
| 2531 | get_unaligned_be16(&fsg->cmnd[7]) << 9; | ||
| 2532 | if ((reply = check_command(fsg, 10, DATA_DIR_FROM_HOST, | ||
| 2533 | (1<<1) | (0xf<<2) | (3<<7), 1, | ||
| 2534 | "WRITE(10)")) == 0) | ||
| 2535 | reply = do_write(fsg); | ||
| 2536 | break; | ||
| 2537 | |||
| 2538 | case WRITE_12: | ||
| 2539 | fsg->data_size_from_cmnd = | ||
| 2540 | get_unaligned_be32(&fsg->cmnd[6]) << 9; | ||
| 2541 | if ((reply = check_command(fsg, 12, DATA_DIR_FROM_HOST, | ||
| 2542 | (1<<1) | (0xf<<2) | (0xf<<6), 1, | ||
| 2543 | "WRITE(12)")) == 0) | ||
| 2544 | reply = do_write(fsg); | ||
| 2545 | break; | ||
| 2546 | |||
| 2547 | /* Some mandatory commands that we recognize but don't implement. | ||
| 2548 | * They don't mean much in this setting. It's left as an exercise | ||
| 2549 | * for anyone interested to implement RESERVE and RELEASE in terms | ||
| 2550 | * of Posix locks. */ | ||
| 2551 | case FORMAT_UNIT: | ||
| 2552 | case RELEASE: | ||
| 2553 | case RESERVE: | ||
| 2554 | case SEND_DIAGNOSTIC: | ||
| 2555 | // Fall through | ||
| 2556 | |||
| 2557 | default: | ||
| 2558 | unknown_cmnd: | ||
| 2559 | fsg->data_size_from_cmnd = 0; | ||
| 2560 | sprintf(unknown, "Unknown x%02x", fsg->cmnd[0]); | ||
| 2561 | if ((reply = check_command(fsg, fsg->cmnd_size, | ||
| 2562 | DATA_DIR_UNKNOWN, 0xff, 0, unknown)) == 0) { | ||
| 2563 | fsg->curlun->sense_data = SS_INVALID_COMMAND; | ||
| 2564 | reply = -EINVAL; | ||
| 2565 | } | ||
| 2566 | break; | ||
| 2567 | } | ||
| 2568 | up_read(&fsg->filesem); | ||
| 2569 | |||
| 2570 | if (reply == -EINTR || signal_pending(current)) | ||
| 2571 | return -EINTR; | ||
| 2572 | |||
| 2573 | /* Set up the single reply buffer for finish_reply() */ | ||
| 2574 | if (reply == -EINVAL) | ||
| 2575 | reply = 0; // Error reply length | ||
| 2576 | if (reply >= 0 && fsg->data_dir == DATA_DIR_TO_HOST) { | ||
| 2577 | reply = min((u32) reply, fsg->data_size_from_cmnd); | ||
| 2578 | bh->inreq->length = reply; | ||
| 2579 | bh->state = BUF_STATE_FULL; | ||
| 2580 | fsg->residue -= reply; | ||
| 2581 | } // Otherwise it's already set | ||
| 2582 | |||
| 2583 | return 0; | ||
| 2584 | } | ||
| 2585 | |||
| 2586 | |||
| 2587 | /*-------------------------------------------------------------------------*/ | ||
| 2588 | |||
| 2589 | static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh) | ||
| 2590 | { | ||
| 2591 | struct usb_request *req = bh->outreq; | ||
| 2592 | struct fsg_bulk_cb_wrap *cbw = req->buf; | ||
| 2593 | |||
| 2594 | /* Was this a real packet? Should it be ignored? */ | ||
| 2595 | if (req->status || test_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags)) | ||
| 2596 | return -EINVAL; | ||
| 2597 | |||
| 2598 | /* Is the CBW valid? */ | ||
| 2599 | if (req->actual != USB_BULK_CB_WRAP_LEN || | ||
| 2600 | cbw->Signature != cpu_to_le32( | ||
| 2601 | USB_BULK_CB_SIG)) { | ||
| 2602 | DBG(fsg, "invalid CBW: len %u sig 0x%x\n", | ||
| 2603 | req->actual, | ||
| 2604 | le32_to_cpu(cbw->Signature)); | ||
| 2605 | |||
| 2606 | /* The Bulk-only spec says we MUST stall the IN endpoint | ||
| 2607 | * (6.6.1), so it's unavoidable. It also says we must | ||
| 2608 | * retain this state until the next reset, but there's | ||
| 2609 | * no way to tell the controller driver it should ignore | ||
| 2610 | * Clear-Feature(HALT) requests. | ||
| 2611 | * | ||
| 2612 | * We aren't required to halt the OUT endpoint; instead | ||
| 2613 | * we can simply accept and discard any data received | ||
| 2614 | * until the next reset. */ | ||
| 2615 | wedge_bulk_in_endpoint(fsg); | ||
| 2616 | set_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags); | ||
| 2617 | return -EINVAL; | ||
| 2618 | } | ||
| 2619 | |||
| 2620 | /* Is the CBW meaningful? */ | ||
| 2621 | if (cbw->Lun >= FSG_MAX_LUNS || cbw->Flags & ~USB_BULK_IN_FLAG || | ||
| 2622 | cbw->Length <= 0 || cbw->Length > MAX_COMMAND_SIZE) { | ||
| 2623 | DBG(fsg, "non-meaningful CBW: lun = %u, flags = 0x%x, " | ||
| 2624 | "cmdlen %u\n", | ||
| 2625 | cbw->Lun, cbw->Flags, cbw->Length); | ||
| 2626 | |||
| 2627 | /* We can do anything we want here, so let's stall the | ||
| 2628 | * bulk pipes if we are allowed to. */ | ||
| 2629 | if (mod_data.can_stall) { | ||
| 2630 | fsg_set_halt(fsg, fsg->bulk_out); | ||
| 2631 | halt_bulk_in_endpoint(fsg); | ||
| 2632 | } | ||
| 2633 | return -EINVAL; | ||
| 2634 | } | ||
| 2635 | |||
| 2636 | /* Save the command for later */ | ||
| 2637 | fsg->cmnd_size = cbw->Length; | ||
| 2638 | memcpy(fsg->cmnd, cbw->CDB, fsg->cmnd_size); | ||
| 2639 | if (cbw->Flags & USB_BULK_IN_FLAG) | ||
| 2640 | fsg->data_dir = DATA_DIR_TO_HOST; | ||
| 2641 | else | ||
| 2642 | fsg->data_dir = DATA_DIR_FROM_HOST; | ||
| 2643 | fsg->data_size = le32_to_cpu(cbw->DataTransferLength); | ||
| 2644 | if (fsg->data_size == 0) | ||
| 2645 | fsg->data_dir = DATA_DIR_NONE; | ||
| 2646 | fsg->lun = cbw->Lun; | ||
| 2647 | fsg->tag = cbw->Tag; | ||
| 2648 | return 0; | ||
| 2649 | } | ||
| 2650 | |||
| 2651 | |||
| 2652 | static int get_next_command(struct fsg_dev *fsg) | ||
| 2653 | { | ||
| 2654 | struct fsg_buffhd *bh; | ||
| 2655 | int rc = 0; | ||
| 2656 | |||
| 2657 | if (transport_is_bbb()) { | ||
| 2658 | |||
| 2659 | /* Wait for the next buffer to become available */ | ||
| 2660 | bh = fsg->next_buffhd_to_fill; | ||
| 2661 | while (bh->state != BUF_STATE_EMPTY) { | ||
| 2662 | rc = sleep_thread(fsg); | ||
| 2663 | if (rc) | ||
| 2664 | return rc; | ||
| 2665 | } | ||
| 2666 | |||
| 2667 | /* Queue a request to read a Bulk-only CBW */ | ||
| 2668 | set_bulk_out_req_length(fsg, bh, USB_BULK_CB_WRAP_LEN); | ||
| 2669 | bh->outreq->short_not_ok = 1; | ||
| 2670 | start_transfer(fsg, fsg->bulk_out, bh->outreq, | ||
| 2671 | &bh->outreq_busy, &bh->state); | ||
| 2672 | |||
| 2673 | /* We will drain the buffer in software, which means we | ||
| 2674 | * can reuse it for the next filling. No need to advance | ||
| 2675 | * next_buffhd_to_fill. */ | ||
| 2676 | |||
| 2677 | /* Wait for the CBW to arrive */ | ||
| 2678 | while (bh->state != BUF_STATE_FULL) { | ||
| 2679 | rc = sleep_thread(fsg); | ||
| 2680 | if (rc) | ||
| 2681 | return rc; | ||
| 2682 | } | ||
| 2683 | smp_rmb(); | ||
| 2684 | rc = received_cbw(fsg, bh); | ||
| 2685 | bh->state = BUF_STATE_EMPTY; | ||
| 2686 | |||
| 2687 | } else { // USB_PR_CB or USB_PR_CBI | ||
| 2688 | |||
| 2689 | /* Wait for the next command to arrive */ | ||
| 2690 | while (fsg->cbbuf_cmnd_size == 0) { | ||
| 2691 | rc = sleep_thread(fsg); | ||
| 2692 | if (rc) | ||
| 2693 | return rc; | ||
| 2694 | } | ||
| 2695 | |||
| 2696 | /* Is the previous status interrupt request still busy? | ||
| 2697 | * The host is allowed to skip reading the status, | ||
| 2698 | * so we must cancel it. */ | ||
| 2699 | if (fsg->intreq_busy) | ||
| 2700 | usb_ep_dequeue(fsg->intr_in, fsg->intreq); | ||
| 2701 | |||
| 2702 | /* Copy the command and mark the buffer empty */ | ||
| 2703 | fsg->data_dir = DATA_DIR_UNKNOWN; | ||
| 2704 | spin_lock_irq(&fsg->lock); | ||
| 2705 | fsg->cmnd_size = fsg->cbbuf_cmnd_size; | ||
| 2706 | memcpy(fsg->cmnd, fsg->cbbuf_cmnd, fsg->cmnd_size); | ||
| 2707 | fsg->cbbuf_cmnd_size = 0; | ||
| 2708 | spin_unlock_irq(&fsg->lock); | ||
| 2709 | } | ||
| 2710 | return rc; | ||
| 2711 | } | ||
| 2712 | |||
| 2713 | |||
| 2714 | /*-------------------------------------------------------------------------*/ | ||
| 2715 | |||
| 2716 | static int enable_endpoint(struct fsg_dev *fsg, struct usb_ep *ep, | ||
| 2717 | const struct usb_endpoint_descriptor *d) | ||
| 2718 | { | ||
| 2719 | int rc; | ||
| 2720 | |||
| 2721 | ep->driver_data = fsg; | ||
| 2722 | ep->desc = d; | ||
| 2723 | rc = usb_ep_enable(ep); | ||
| 2724 | if (rc) | ||
| 2725 | ERROR(fsg, "can't enable %s, result %d\n", ep->name, rc); | ||
| 2726 | return rc; | ||
| 2727 | } | ||
| 2728 | |||
| 2729 | static int alloc_request(struct fsg_dev *fsg, struct usb_ep *ep, | ||
| 2730 | struct usb_request **preq) | ||
| 2731 | { | ||
| 2732 | *preq = usb_ep_alloc_request(ep, GFP_ATOMIC); | ||
| 2733 | if (*preq) | ||
| 2734 | return 0; | ||
| 2735 | ERROR(fsg, "can't allocate request for %s\n", ep->name); | ||
| 2736 | return -ENOMEM; | ||
| 2737 | } | ||
| 2738 | |||
| 2739 | /* | ||
| 2740 | * Reset interface setting and re-init endpoint state (toggle etc). | ||
| 2741 | * Call with altsetting < 0 to disable the interface. The only other | ||
| 2742 | * available altsetting is 0, which enables the interface. | ||
| 2743 | */ | ||
| 2744 | static int do_set_interface(struct fsg_dev *fsg, int altsetting) | ||
| 2745 | { | ||
| 2746 | int rc = 0; | ||
| 2747 | int i; | ||
| 2748 | const struct usb_endpoint_descriptor *d; | ||
| 2749 | |||
| 2750 | if (fsg->running) | ||
| 2751 | DBG(fsg, "reset interface\n"); | ||
| 2752 | |||
| 2753 | reset: | ||
| 2754 | /* Deallocate the requests */ | ||
| 2755 | for (i = 0; i < FSG_NUM_BUFFERS; ++i) { | ||
| 2756 | struct fsg_buffhd *bh = &fsg->buffhds[i]; | ||
| 2757 | |||
| 2758 | if (bh->inreq) { | ||
| 2759 | usb_ep_free_request(fsg->bulk_in, bh->inreq); | ||
| 2760 | bh->inreq = NULL; | ||
| 2761 | } | ||
| 2762 | if (bh->outreq) { | ||
| 2763 | usb_ep_free_request(fsg->bulk_out, bh->outreq); | ||
| 2764 | bh->outreq = NULL; | ||
| 2765 | } | ||
| 2766 | } | ||
| 2767 | if (fsg->intreq) { | ||
| 2768 | usb_ep_free_request(fsg->intr_in, fsg->intreq); | ||
| 2769 | fsg->intreq = NULL; | ||
| 2770 | } | ||
| 2771 | |||
| 2772 | /* Disable the endpoints */ | ||
| 2773 | if (fsg->bulk_in_enabled) { | ||
| 2774 | usb_ep_disable(fsg->bulk_in); | ||
| 2775 | fsg->bulk_in_enabled = 0; | ||
| 2776 | } | ||
| 2777 | if (fsg->bulk_out_enabled) { | ||
| 2778 | usb_ep_disable(fsg->bulk_out); | ||
| 2779 | fsg->bulk_out_enabled = 0; | ||
| 2780 | } | ||
| 2781 | if (fsg->intr_in_enabled) { | ||
| 2782 | usb_ep_disable(fsg->intr_in); | ||
| 2783 | fsg->intr_in_enabled = 0; | ||
| 2784 | } | ||
| 2785 | |||
| 2786 | fsg->running = 0; | ||
| 2787 | if (altsetting < 0 || rc != 0) | ||
| 2788 | return rc; | ||
| 2789 | |||
| 2790 | DBG(fsg, "set interface %d\n", altsetting); | ||
| 2791 | |||
| 2792 | /* Enable the endpoints */ | ||
| 2793 | d = fsg_ep_desc(fsg->gadget, | ||
| 2794 | &fsg_fs_bulk_in_desc, &fsg_hs_bulk_in_desc); | ||
| 2795 | if ((rc = enable_endpoint(fsg, fsg->bulk_in, d)) != 0) | ||
| 2796 | goto reset; | ||
| 2797 | fsg->bulk_in_enabled = 1; | ||
| 2798 | |||
| 2799 | d = fsg_ep_desc(fsg->gadget, | ||
| 2800 | &fsg_fs_bulk_out_desc, &fsg_hs_bulk_out_desc); | ||
| 2801 | if ((rc = enable_endpoint(fsg, fsg->bulk_out, d)) != 0) | ||
| 2802 | goto reset; | ||
| 2803 | fsg->bulk_out_enabled = 1; | ||
| 2804 | fsg->bulk_out_maxpacket = le16_to_cpu(d->wMaxPacketSize); | ||
| 2805 | clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags); | ||
| 2806 | |||
| 2807 | if (transport_is_cbi()) { | ||
| 2808 | d = fsg_ep_desc(fsg->gadget, | ||
| 2809 | &fsg_fs_intr_in_desc, &fsg_hs_intr_in_desc); | ||
| 2810 | if ((rc = enable_endpoint(fsg, fsg->intr_in, d)) != 0) | ||
| 2811 | goto reset; | ||
| 2812 | fsg->intr_in_enabled = 1; | ||
| 2813 | } | ||
| 2814 | |||
| 2815 | /* Allocate the requests */ | ||
| 2816 | for (i = 0; i < FSG_NUM_BUFFERS; ++i) { | ||
| 2817 | struct fsg_buffhd *bh = &fsg->buffhds[i]; | ||
| 2818 | |||
| 2819 | if ((rc = alloc_request(fsg, fsg->bulk_in, &bh->inreq)) != 0) | ||
| 2820 | goto reset; | ||
| 2821 | if ((rc = alloc_request(fsg, fsg->bulk_out, &bh->outreq)) != 0) | ||
| 2822 | goto reset; | ||
| 2823 | bh->inreq->buf = bh->outreq->buf = bh->buf; | ||
| 2824 | bh->inreq->context = bh->outreq->context = bh; | ||
| 2825 | bh->inreq->complete = bulk_in_complete; | ||
| 2826 | bh->outreq->complete = bulk_out_complete; | ||
| 2827 | } | ||
| 2828 | if (transport_is_cbi()) { | ||
| 2829 | if ((rc = alloc_request(fsg, fsg->intr_in, &fsg->intreq)) != 0) | ||
| 2830 | goto reset; | ||
| 2831 | fsg->intreq->complete = intr_in_complete; | ||
| 2832 | } | ||
| 2833 | |||
| 2834 | fsg->running = 1; | ||
| 2835 | for (i = 0; i < fsg->nluns; ++i) | ||
| 2836 | fsg->luns[i].unit_attention_data = SS_RESET_OCCURRED; | ||
| 2837 | return rc; | ||
| 2838 | } | ||
| 2839 | |||
| 2840 | |||
| 2841 | /* | ||
| 2842 | * Change our operational configuration. This code must agree with the code | ||
| 2843 | * that returns config descriptors, and with interface altsetting code. | ||
| 2844 | * | ||
| 2845 | * It's also responsible for power management interactions. Some | ||
| 2846 | * configurations might not work with our current power sources. | ||
| 2847 | * For now we just assume the gadget is always self-powered. | ||
| 2848 | */ | ||
| 2849 | static int do_set_config(struct fsg_dev *fsg, u8 new_config) | ||
| 2850 | { | ||
| 2851 | int rc = 0; | ||
| 2852 | |||
| 2853 | /* Disable the single interface */ | ||
| 2854 | if (fsg->config != 0) { | ||
| 2855 | DBG(fsg, "reset config\n"); | ||
| 2856 | fsg->config = 0; | ||
| 2857 | rc = do_set_interface(fsg, -1); | ||
| 2858 | } | ||
| 2859 | |||
| 2860 | /* Enable the interface */ | ||
| 2861 | if (new_config != 0) { | ||
| 2862 | fsg->config = new_config; | ||
| 2863 | if ((rc = do_set_interface(fsg, 0)) != 0) | ||
| 2864 | fsg->config = 0; // Reset on errors | ||
| 2865 | else { | ||
| 2866 | char *speed; | ||
| 2867 | |||
| 2868 | switch (fsg->gadget->speed) { | ||
| 2869 | case USB_SPEED_LOW: speed = "low"; break; | ||
| 2870 | case USB_SPEED_FULL: speed = "full"; break; | ||
| 2871 | case USB_SPEED_HIGH: speed = "high"; break; | ||
| 2872 | default: speed = "?"; break; | ||
| 2873 | } | ||
| 2874 | INFO(fsg, "%s speed config #%d\n", speed, fsg->config); | ||
| 2875 | } | ||
| 2876 | } | ||
| 2877 | return rc; | ||
| 2878 | } | ||
| 2879 | |||
| 2880 | |||
| 2881 | /*-------------------------------------------------------------------------*/ | ||
| 2882 | |||
| 2883 | static void handle_exception(struct fsg_dev *fsg) | ||
| 2884 | { | ||
| 2885 | siginfo_t info; | ||
| 2886 | int sig; | ||
| 2887 | int i; | ||
| 2888 | int num_active; | ||
| 2889 | struct fsg_buffhd *bh; | ||
| 2890 | enum fsg_state old_state; | ||
| 2891 | u8 new_config; | ||
| 2892 | struct fsg_lun *curlun; | ||
| 2893 | unsigned int exception_req_tag; | ||
| 2894 | int rc; | ||
| 2895 | |||
| 2896 | /* Clear the existing signals. Anything but SIGUSR1 is converted | ||
| 2897 | * into a high-priority EXIT exception. */ | ||
| 2898 | for (;;) { | ||
| 2899 | sig = dequeue_signal_lock(current, ¤t->blocked, &info); | ||
| 2900 | if (!sig) | ||
| 2901 | break; | ||
| 2902 | if (sig != SIGUSR1) { | ||
| 2903 | if (fsg->state < FSG_STATE_EXIT) | ||
| 2904 | DBG(fsg, "Main thread exiting on signal\n"); | ||
| 2905 | raise_exception(fsg, FSG_STATE_EXIT); | ||
| 2906 | } | ||
| 2907 | } | ||
| 2908 | |||
| 2909 | /* Cancel all the pending transfers */ | ||
| 2910 | if (fsg->intreq_busy) | ||
| 2911 | usb_ep_dequeue(fsg->intr_in, fsg->intreq); | ||
| 2912 | for (i = 0; i < FSG_NUM_BUFFERS; ++i) { | ||
| 2913 | bh = &fsg->buffhds[i]; | ||
| 2914 | if (bh->inreq_busy) | ||
| 2915 | usb_ep_dequeue(fsg->bulk_in, bh->inreq); | ||
| 2916 | if (bh->outreq_busy) | ||
| 2917 | usb_ep_dequeue(fsg->bulk_out, bh->outreq); | ||
| 2918 | } | ||
| 2919 | |||
| 2920 | /* Wait until everything is idle */ | ||
| 2921 | for (;;) { | ||
| 2922 | num_active = fsg->intreq_busy; | ||
| 2923 | for (i = 0; i < FSG_NUM_BUFFERS; ++i) { | ||
| 2924 | bh = &fsg->buffhds[i]; | ||
| 2925 | num_active += bh->inreq_busy + bh->outreq_busy; | ||
| 2926 | } | ||
| 2927 | if (num_active == 0) | ||
| 2928 | break; | ||
| 2929 | if (sleep_thread(fsg)) | ||
| 2930 | return; | ||
| 2931 | } | ||
| 2932 | |||
| 2933 | /* Clear out the controller's fifos */ | ||
| 2934 | if (fsg->bulk_in_enabled) | ||
| 2935 | usb_ep_fifo_flush(fsg->bulk_in); | ||
| 2936 | if (fsg->bulk_out_enabled) | ||
| 2937 | usb_ep_fifo_flush(fsg->bulk_out); | ||
| 2938 | if (fsg->intr_in_enabled) | ||
| 2939 | usb_ep_fifo_flush(fsg->intr_in); | ||
| 2940 | |||
| 2941 | /* Reset the I/O buffer states and pointers, the SCSI | ||
| 2942 | * state, and the exception. Then invoke the handler. */ | ||
| 2943 | spin_lock_irq(&fsg->lock); | ||
| 2944 | |||
| 2945 | for (i = 0; i < FSG_NUM_BUFFERS; ++i) { | ||
| 2946 | bh = &fsg->buffhds[i]; | ||
| 2947 | bh->state = BUF_STATE_EMPTY; | ||
| 2948 | } | ||
| 2949 | fsg->next_buffhd_to_fill = fsg->next_buffhd_to_drain = | ||
| 2950 | &fsg->buffhds[0]; | ||
| 2951 | |||
| 2952 | exception_req_tag = fsg->exception_req_tag; | ||
| 2953 | new_config = fsg->new_config; | ||
| 2954 | old_state = fsg->state; | ||
| 2955 | |||
| 2956 | if (old_state == FSG_STATE_ABORT_BULK_OUT) | ||
| 2957 | fsg->state = FSG_STATE_STATUS_PHASE; | ||
| 2958 | else { | ||
| 2959 | for (i = 0; i < fsg->nluns; ++i) { | ||
| 2960 | curlun = &fsg->luns[i]; | ||
| 2961 | curlun->prevent_medium_removal = 0; | ||
| 2962 | curlun->sense_data = curlun->unit_attention_data = | ||
| 2963 | SS_NO_SENSE; | ||
| 2964 | curlun->sense_data_info = 0; | ||
| 2965 | curlun->info_valid = 0; | ||
| 2966 | } | ||
| 2967 | fsg->state = FSG_STATE_IDLE; | ||
| 2968 | } | ||
| 2969 | spin_unlock_irq(&fsg->lock); | ||
| 2970 | |||
| 2971 | /* Carry out any extra actions required for the exception */ | ||
| 2972 | switch (old_state) { | ||
| 2973 | default: | ||
| 2974 | break; | ||
| 2975 | |||
| 2976 | case FSG_STATE_ABORT_BULK_OUT: | ||
| 2977 | send_status(fsg); | ||
| 2978 | spin_lock_irq(&fsg->lock); | ||
| 2979 | if (fsg->state == FSG_STATE_STATUS_PHASE) | ||
| 2980 | fsg->state = FSG_STATE_IDLE; | ||
| 2981 | spin_unlock_irq(&fsg->lock); | ||
| 2982 | break; | ||
| 2983 | |||
| 2984 | case FSG_STATE_RESET: | ||
| 2985 | /* In case we were forced against our will to halt a | ||
| 2986 | * bulk endpoint, clear the halt now. (The SuperH UDC | ||
| 2987 | * requires this.) */ | ||
| 2988 | if (test_and_clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags)) | ||
| 2989 | usb_ep_clear_halt(fsg->bulk_in); | ||
| 2990 | |||
| 2991 | if (transport_is_bbb()) { | ||
| 2992 | if (fsg->ep0_req_tag == exception_req_tag) | ||
| 2993 | ep0_queue(fsg); // Complete the status stage | ||
| 2994 | |||
| 2995 | } else if (transport_is_cbi()) | ||
| 2996 | send_status(fsg); // Status by interrupt pipe | ||
| 2997 | |||
| 2998 | /* Technically this should go here, but it would only be | ||
| 2999 | * a waste of time. Ditto for the INTERFACE_CHANGE and | ||
| 3000 | * CONFIG_CHANGE cases. */ | ||
| 3001 | // for (i = 0; i < fsg->nluns; ++i) | ||
| 3002 | // fsg->luns[i].unit_attention_data = SS_RESET_OCCURRED; | ||
| 3003 | break; | ||
| 3004 | |||
| 3005 | case FSG_STATE_INTERFACE_CHANGE: | ||
| 3006 | rc = do_set_interface(fsg, 0); | ||
| 3007 | if (fsg->ep0_req_tag != exception_req_tag) | ||
| 3008 | break; | ||
| 3009 | if (rc != 0) // STALL on errors | ||
| 3010 | fsg_set_halt(fsg, fsg->ep0); | ||
| 3011 | else // Complete the status stage | ||
| 3012 | ep0_queue(fsg); | ||
| 3013 | break; | ||
| 3014 | |||
| 3015 | case FSG_STATE_CONFIG_CHANGE: | ||
| 3016 | rc = do_set_config(fsg, new_config); | ||
| 3017 | if (fsg->ep0_req_tag != exception_req_tag) | ||
| 3018 | break; | ||
| 3019 | if (rc != 0) // STALL on errors | ||
| 3020 | fsg_set_halt(fsg, fsg->ep0); | ||
| 3021 | else // Complete the status stage | ||
| 3022 | ep0_queue(fsg); | ||
| 3023 | break; | ||
| 3024 | |||
| 3025 | case FSG_STATE_DISCONNECT: | ||
| 3026 | for (i = 0; i < fsg->nluns; ++i) | ||
| 3027 | fsg_lun_fsync_sub(fsg->luns + i); | ||
| 3028 | do_set_config(fsg, 0); // Unconfigured state | ||
| 3029 | break; | ||
| 3030 | |||
| 3031 | case FSG_STATE_EXIT: | ||
| 3032 | case FSG_STATE_TERMINATED: | ||
| 3033 | do_set_config(fsg, 0); // Free resources | ||
| 3034 | spin_lock_irq(&fsg->lock); | ||
| 3035 | fsg->state = FSG_STATE_TERMINATED; // Stop the thread | ||
| 3036 | spin_unlock_irq(&fsg->lock); | ||
| 3037 | break; | ||
| 3038 | } | ||
| 3039 | } | ||
| 3040 | |||
| 3041 | |||
| 3042 | /*-------------------------------------------------------------------------*/ | ||
| 3043 | |||
| 3044 | static int fsg_main_thread(void *fsg_) | ||
| 3045 | { | ||
| 3046 | struct fsg_dev *fsg = fsg_; | ||
| 3047 | |||
| 3048 | /* Allow the thread to be killed by a signal, but set the signal mask | ||
| 3049 | * to block everything but INT, TERM, KILL, and USR1. */ | ||
| 3050 | allow_signal(SIGINT); | ||
| 3051 | allow_signal(SIGTERM); | ||
| 3052 | allow_signal(SIGKILL); | ||
| 3053 | allow_signal(SIGUSR1); | ||
| 3054 | |||
| 3055 | /* Allow the thread to be frozen */ | ||
| 3056 | set_freezable(); | ||
| 3057 | |||
| 3058 | /* Arrange for userspace references to be interpreted as kernel | ||
| 3059 | * pointers. That way we can pass a kernel pointer to a routine | ||
| 3060 | * that expects a __user pointer and it will work okay. */ | ||
| 3061 | set_fs(get_ds()); | ||
| 3062 | |||
| 3063 | /* The main loop */ | ||
| 3064 | while (fsg->state != FSG_STATE_TERMINATED) { | ||
| 3065 | if (exception_in_progress(fsg) || signal_pending(current)) { | ||
| 3066 | handle_exception(fsg); | ||
| 3067 | continue; | ||
| 3068 | } | ||
| 3069 | |||
| 3070 | if (!fsg->running) { | ||
| 3071 | sleep_thread(fsg); | ||
| 3072 | continue; | ||
| 3073 | } | ||
| 3074 | |||
| 3075 | if (get_next_command(fsg)) | ||
| 3076 | continue; | ||
| 3077 | |||
| 3078 | spin_lock_irq(&fsg->lock); | ||
| 3079 | if (!exception_in_progress(fsg)) | ||
| 3080 | fsg->state = FSG_STATE_DATA_PHASE; | ||
| 3081 | spin_unlock_irq(&fsg->lock); | ||
| 3082 | |||
| 3083 | if (do_scsi_command(fsg) || finish_reply(fsg)) | ||
| 3084 | continue; | ||
| 3085 | |||
| 3086 | spin_lock_irq(&fsg->lock); | ||
| 3087 | if (!exception_in_progress(fsg)) | ||
| 3088 | fsg->state = FSG_STATE_STATUS_PHASE; | ||
| 3089 | spin_unlock_irq(&fsg->lock); | ||
| 3090 | |||
| 3091 | if (send_status(fsg)) | ||
| 3092 | continue; | ||
| 3093 | |||
| 3094 | spin_lock_irq(&fsg->lock); | ||
| 3095 | if (!exception_in_progress(fsg)) | ||
| 3096 | fsg->state = FSG_STATE_IDLE; | ||
| 3097 | spin_unlock_irq(&fsg->lock); | ||
| 3098 | } | ||
| 3099 | |||
| 3100 | spin_lock_irq(&fsg->lock); | ||
| 3101 | fsg->thread_task = NULL; | ||
| 3102 | spin_unlock_irq(&fsg->lock); | ||
| 3103 | |||
| 3104 | /* If we are exiting because of a signal, unregister the | ||
| 3105 | * gadget driver. */ | ||
| 3106 | if (test_and_clear_bit(REGISTERED, &fsg->atomic_bitflags)) | ||
| 3107 | usb_gadget_unregister_driver(&fsg_driver); | ||
| 3108 | |||
| 3109 | /* Let the unbind and cleanup routines know the thread has exited */ | ||
| 3110 | complete_and_exit(&fsg->thread_notifier, 0); | ||
| 3111 | } | ||
| 3112 | |||
| 3113 | |||
| 3114 | /*-------------------------------------------------------------------------*/ | ||
| 3115 | |||
| 3116 | |||
| 3117 | /* The write permissions and store_xxx pointers are set in fsg_bind() */ | ||
| 3118 | static DEVICE_ATTR(ro, 0444, fsg_show_ro, NULL); | ||
| 3119 | static DEVICE_ATTR(nofua, 0644, fsg_show_nofua, NULL); | ||
| 3120 | static DEVICE_ATTR(file, 0444, fsg_show_file, NULL); | ||
| 3121 | |||
| 3122 | |||
| 3123 | /*-------------------------------------------------------------------------*/ | ||
| 3124 | |||
| 3125 | static void fsg_release(struct kref *ref) | ||
| 3126 | { | ||
| 3127 | struct fsg_dev *fsg = container_of(ref, struct fsg_dev, ref); | ||
| 3128 | |||
| 3129 | kfree(fsg->luns); | ||
| 3130 | kfree(fsg); | ||
| 3131 | } | ||
| 3132 | |||
| 3133 | static void lun_release(struct device *dev) | ||
| 3134 | { | ||
| 3135 | struct rw_semaphore *filesem = dev_get_drvdata(dev); | ||
| 3136 | struct fsg_dev *fsg = | ||
| 3137 | container_of(filesem, struct fsg_dev, filesem); | ||
| 3138 | |||
| 3139 | kref_put(&fsg->ref, fsg_release); | ||
| 3140 | } | ||
| 3141 | |||
| 3142 | static void /* __init_or_exit */ fsg_unbind(struct usb_gadget *gadget) | ||
| 3143 | { | ||
| 3144 | struct fsg_dev *fsg = get_gadget_data(gadget); | ||
| 3145 | int i; | ||
| 3146 | struct fsg_lun *curlun; | ||
| 3147 | struct usb_request *req = fsg->ep0req; | ||
| 3148 | |||
| 3149 | DBG(fsg, "unbind\n"); | ||
| 3150 | clear_bit(REGISTERED, &fsg->atomic_bitflags); | ||
| 3151 | |||
| 3152 | /* Unregister the sysfs attribute files and the LUNs */ | ||
| 3153 | for (i = 0; i < fsg->nluns; ++i) { | ||
| 3154 | curlun = &fsg->luns[i]; | ||
| 3155 | if (curlun->registered) { | ||
| 3156 | device_remove_file(&curlun->dev, &dev_attr_nofua); | ||
| 3157 | device_remove_file(&curlun->dev, &dev_attr_ro); | ||
| 3158 | device_remove_file(&curlun->dev, &dev_attr_file); | ||
| 3159 | fsg_lun_close(curlun); | ||
| 3160 | device_unregister(&curlun->dev); | ||
| 3161 | curlun->registered = 0; | ||
| 3162 | } | ||
| 3163 | } | ||
| 3164 | |||
| 3165 | /* If the thread isn't already dead, tell it to exit now */ | ||
| 3166 | if (fsg->state != FSG_STATE_TERMINATED) { | ||
| 3167 | raise_exception(fsg, FSG_STATE_EXIT); | ||
| 3168 | wait_for_completion(&fsg->thread_notifier); | ||
| 3169 | |||
| 3170 | /* The cleanup routine waits for this completion also */ | ||
| 3171 | complete(&fsg->thread_notifier); | ||
| 3172 | } | ||
| 3173 | |||
| 3174 | /* Free the data buffers */ | ||
| 3175 | for (i = 0; i < FSG_NUM_BUFFERS; ++i) | ||
| 3176 | kfree(fsg->buffhds[i].buf); | ||
| 3177 | |||
| 3178 | /* Free the request and buffer for endpoint 0 */ | ||
| 3179 | if (req) { | ||
| 3180 | kfree(req->buf); | ||
| 3181 | usb_ep_free_request(fsg->ep0, req); | ||
| 3182 | } | ||
| 3183 | |||
| 3184 | set_gadget_data(gadget, NULL); | ||
| 3185 | } | ||
| 3186 | |||
| 3187 | |||
| 3188 | static int __init check_parameters(struct fsg_dev *fsg) | ||
| 3189 | { | ||
| 3190 | int prot; | ||
| 3191 | int gcnum; | ||
| 3192 | |||
| 3193 | /* Store the default values */ | ||
| 3194 | mod_data.transport_type = USB_PR_BULK; | ||
| 3195 | mod_data.transport_name = "Bulk-only"; | ||
| 3196 | mod_data.protocol_type = USB_SC_SCSI; | ||
| 3197 | mod_data.protocol_name = "Transparent SCSI"; | ||
| 3198 | |||
| 3199 | /* Some peripheral controllers are known not to be able to | ||
| 3200 | * halt bulk endpoints correctly. If one of them is present, | ||
| 3201 | * disable stalls. | ||
| 3202 | */ | ||
| 3203 | if (gadget_is_at91(fsg->gadget)) | ||
| 3204 | mod_data.can_stall = 0; | ||
| 3205 | |||
| 3206 | if (mod_data.release == 0xffff) { // Parameter wasn't set | ||
| 3207 | gcnum = usb_gadget_controller_number(fsg->gadget); | ||
| 3208 | if (gcnum >= 0) | ||
| 3209 | mod_data.release = 0x0300 + gcnum; | ||
| 3210 | else { | ||
| 3211 | WARNING(fsg, "controller '%s' not recognized\n", | ||
| 3212 | fsg->gadget->name); | ||
| 3213 | mod_data.release = 0x0399; | ||
| 3214 | } | ||
| 3215 | } | ||
| 3216 | |||
| 3217 | prot = simple_strtol(mod_data.protocol_parm, NULL, 0); | ||
| 3218 | |||
| 3219 | #ifdef CONFIG_USB_FILE_STORAGE_TEST | ||
| 3220 | if (strnicmp(mod_data.transport_parm, "BBB", 10) == 0) { | ||
| 3221 | ; // Use default setting | ||
| 3222 | } else if (strnicmp(mod_data.transport_parm, "CB", 10) == 0) { | ||
| 3223 | mod_data.transport_type = USB_PR_CB; | ||
| 3224 | mod_data.transport_name = "Control-Bulk"; | ||
| 3225 | } else if (strnicmp(mod_data.transport_parm, "CBI", 10) == 0) { | ||
| 3226 | mod_data.transport_type = USB_PR_CBI; | ||
| 3227 | mod_data.transport_name = "Control-Bulk-Interrupt"; | ||
| 3228 | } else { | ||
| 3229 | ERROR(fsg, "invalid transport: %s\n", mod_data.transport_parm); | ||
| 3230 | return -EINVAL; | ||
| 3231 | } | ||
| 3232 | |||
| 3233 | if (strnicmp(mod_data.protocol_parm, "SCSI", 10) == 0 || | ||
| 3234 | prot == USB_SC_SCSI) { | ||
| 3235 | ; // Use default setting | ||
| 3236 | } else if (strnicmp(mod_data.protocol_parm, "RBC", 10) == 0 || | ||
| 3237 | prot == USB_SC_RBC) { | ||
| 3238 | mod_data.protocol_type = USB_SC_RBC; | ||
| 3239 | mod_data.protocol_name = "RBC"; | ||
| 3240 | } else if (strnicmp(mod_data.protocol_parm, "8020", 4) == 0 || | ||
| 3241 | strnicmp(mod_data.protocol_parm, "ATAPI", 10) == 0 || | ||
| 3242 | prot == USB_SC_8020) { | ||
| 3243 | mod_data.protocol_type = USB_SC_8020; | ||
| 3244 | mod_data.protocol_name = "8020i (ATAPI)"; | ||
| 3245 | } else if (strnicmp(mod_data.protocol_parm, "QIC", 3) == 0 || | ||
| 3246 | prot == USB_SC_QIC) { | ||
| 3247 | mod_data.protocol_type = USB_SC_QIC; | ||
| 3248 | mod_data.protocol_name = "QIC-157"; | ||
| 3249 | } else if (strnicmp(mod_data.protocol_parm, "UFI", 10) == 0 || | ||
| 3250 | prot == USB_SC_UFI) { | ||
| 3251 | mod_data.protocol_type = USB_SC_UFI; | ||
| 3252 | mod_data.protocol_name = "UFI"; | ||
| 3253 | } else if (strnicmp(mod_data.protocol_parm, "8070", 4) == 0 || | ||
| 3254 | prot == USB_SC_8070) { | ||
| 3255 | mod_data.protocol_type = USB_SC_8070; | ||
| 3256 | mod_data.protocol_name = "8070i"; | ||
| 3257 | } else { | ||
| 3258 | ERROR(fsg, "invalid protocol: %s\n", mod_data.protocol_parm); | ||
| 3259 | return -EINVAL; | ||
| 3260 | } | ||
| 3261 | |||
| 3262 | mod_data.buflen &= PAGE_CACHE_MASK; | ||
| 3263 | if (mod_data.buflen <= 0) { | ||
| 3264 | ERROR(fsg, "invalid buflen\n"); | ||
| 3265 | return -ETOOSMALL; | ||
| 3266 | } | ||
| 3267 | |||
| 3268 | #endif /* CONFIG_USB_FILE_STORAGE_TEST */ | ||
| 3269 | |||
| 3270 | /* Serial string handling. | ||
| 3271 | * On a real device, the serial string would be loaded | ||
| 3272 | * from permanent storage. */ | ||
| 3273 | if (mod_data.serial) { | ||
| 3274 | const char *ch; | ||
| 3275 | unsigned len = 0; | ||
| 3276 | |||
| 3277 | /* Sanity check : | ||
| 3278 | * The CB[I] specification limits the serial string to | ||
| 3279 | * 12 uppercase hexadecimal characters. | ||
| 3280 | * BBB need at least 12 uppercase hexadecimal characters, | ||
| 3281 | * with a maximum of 126. */ | ||
| 3282 | for (ch = mod_data.serial; *ch; ++ch) { | ||
| 3283 | ++len; | ||
| 3284 | if ((*ch < '0' || *ch > '9') && | ||
| 3285 | (*ch < 'A' || *ch > 'F')) { /* not uppercase hex */ | ||
| 3286 | WARNING(fsg, | ||
| 3287 | "Invalid serial string character: %c\n", | ||
| 3288 | *ch); | ||
| 3289 | goto no_serial; | ||
| 3290 | } | ||
| 3291 | } | ||
| 3292 | if (len > 126 || | ||
| 3293 | (mod_data.transport_type == USB_PR_BULK && len < 12) || | ||
| 3294 | (mod_data.transport_type != USB_PR_BULK && len > 12)) { | ||
| 3295 | WARNING(fsg, "Invalid serial string length!\n"); | ||
| 3296 | goto no_serial; | ||
| 3297 | } | ||
| 3298 | fsg_strings[FSG_STRING_SERIAL - 1].s = mod_data.serial; | ||
| 3299 | } else { | ||
| 3300 | WARNING(fsg, "No serial-number string provided!\n"); | ||
| 3301 | no_serial: | ||
| 3302 | device_desc.iSerialNumber = 0; | ||
| 3303 | } | ||
| 3304 | |||
| 3305 | return 0; | ||
| 3306 | } | ||
| 3307 | |||
| 3308 | |||
| 3309 | static int __init fsg_bind(struct usb_gadget *gadget) | ||
| 3310 | { | ||
| 3311 | struct fsg_dev *fsg = the_fsg; | ||
| 3312 | int rc; | ||
| 3313 | int i; | ||
| 3314 | struct fsg_lun *curlun; | ||
| 3315 | struct usb_ep *ep; | ||
| 3316 | struct usb_request *req; | ||
| 3317 | char *pathbuf, *p; | ||
| 3318 | |||
| 3319 | fsg->gadget = gadget; | ||
| 3320 | set_gadget_data(gadget, fsg); | ||
| 3321 | fsg->ep0 = gadget->ep0; | ||
| 3322 | fsg->ep0->driver_data = fsg; | ||
| 3323 | |||
| 3324 | if ((rc = check_parameters(fsg)) != 0) | ||
| 3325 | goto out; | ||
| 3326 | |||
| 3327 | if (mod_data.removable) { // Enable the store_xxx attributes | ||
| 3328 | dev_attr_file.attr.mode = 0644; | ||
| 3329 | dev_attr_file.store = fsg_store_file; | ||
| 3330 | if (!mod_data.cdrom) { | ||
| 3331 | dev_attr_ro.attr.mode = 0644; | ||
| 3332 | dev_attr_ro.store = fsg_store_ro; | ||
| 3333 | } | ||
| 3334 | } | ||
| 3335 | |||
| 3336 | /* Only for removable media? */ | ||
| 3337 | dev_attr_nofua.attr.mode = 0644; | ||
| 3338 | dev_attr_nofua.store = fsg_store_nofua; | ||
| 3339 | |||
| 3340 | /* Find out how many LUNs there should be */ | ||
| 3341 | i = mod_data.nluns; | ||
| 3342 | if (i == 0) | ||
| 3343 | i = max(mod_data.num_filenames, 1u); | ||
| 3344 | if (i > FSG_MAX_LUNS) { | ||
| 3345 | ERROR(fsg, "invalid number of LUNs: %d\n", i); | ||
| 3346 | rc = -EINVAL; | ||
| 3347 | goto out; | ||
| 3348 | } | ||
| 3349 | |||
| 3350 | /* Create the LUNs, open their backing files, and register the | ||
| 3351 | * LUN devices in sysfs. */ | ||
| 3352 | fsg->luns = kzalloc(i * sizeof(struct fsg_lun), GFP_KERNEL); | ||
| 3353 | if (!fsg->luns) { | ||
| 3354 | rc = -ENOMEM; | ||
| 3355 | goto out; | ||
| 3356 | } | ||
| 3357 | fsg->nluns = i; | ||
| 3358 | |||
| 3359 | for (i = 0; i < fsg->nluns; ++i) { | ||
| 3360 | curlun = &fsg->luns[i]; | ||
| 3361 | curlun->cdrom = !!mod_data.cdrom; | ||
| 3362 | curlun->ro = mod_data.cdrom || mod_data.ro[i]; | ||
| 3363 | curlun->initially_ro = curlun->ro; | ||
| 3364 | curlun->removable = mod_data.removable; | ||
| 3365 | curlun->nofua = mod_data.nofua[i]; | ||
| 3366 | curlun->dev.release = lun_release; | ||
| 3367 | curlun->dev.parent = &gadget->dev; | ||
| 3368 | curlun->dev.driver = &fsg_driver.driver; | ||
| 3369 | dev_set_drvdata(&curlun->dev, &fsg->filesem); | ||
| 3370 | dev_set_name(&curlun->dev,"%s-lun%d", | ||
| 3371 | dev_name(&gadget->dev), i); | ||
| 3372 | |||
| 3373 | kref_get(&fsg->ref); | ||
| 3374 | rc = device_register(&curlun->dev); | ||
| 3375 | if (rc) { | ||
| 3376 | INFO(fsg, "failed to register LUN%d: %d\n", i, rc); | ||
| 3377 | put_device(&curlun->dev); | ||
| 3378 | goto out; | ||
| 3379 | } | ||
| 3380 | curlun->registered = 1; | ||
| 3381 | |||
| 3382 | rc = device_create_file(&curlun->dev, &dev_attr_ro); | ||
| 3383 | if (rc) | ||
| 3384 | goto out; | ||
| 3385 | rc = device_create_file(&curlun->dev, &dev_attr_nofua); | ||
| 3386 | if (rc) | ||
| 3387 | goto out; | ||
| 3388 | rc = device_create_file(&curlun->dev, &dev_attr_file); | ||
| 3389 | if (rc) | ||
| 3390 | goto out; | ||
| 3391 | |||
| 3392 | if (mod_data.file[i] && *mod_data.file[i]) { | ||
| 3393 | rc = fsg_lun_open(curlun, mod_data.file[i]); | ||
| 3394 | if (rc) | ||
| 3395 | goto out; | ||
| 3396 | } else if (!mod_data.removable) { | ||
| 3397 | ERROR(fsg, "no file given for LUN%d\n", i); | ||
| 3398 | rc = -EINVAL; | ||
| 3399 | goto out; | ||
| 3400 | } | ||
| 3401 | } | ||
| 3402 | |||
| 3403 | /* Find all the endpoints we will use */ | ||
| 3404 | usb_ep_autoconfig_reset(gadget); | ||
| 3405 | ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_in_desc); | ||
| 3406 | if (!ep) | ||
| 3407 | goto autoconf_fail; | ||
| 3408 | ep->driver_data = fsg; // claim the endpoint | ||
| 3409 | fsg->bulk_in = ep; | ||
| 3410 | |||
| 3411 | ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_out_desc); | ||
| 3412 | if (!ep) | ||
| 3413 | goto autoconf_fail; | ||
| 3414 | ep->driver_data = fsg; // claim the endpoint | ||
| 3415 | fsg->bulk_out = ep; | ||
| 3416 | |||
| 3417 | if (transport_is_cbi()) { | ||
| 3418 | ep = usb_ep_autoconfig(gadget, &fsg_fs_intr_in_desc); | ||
| 3419 | if (!ep) | ||
| 3420 | goto autoconf_fail; | ||
| 3421 | ep->driver_data = fsg; // claim the endpoint | ||
| 3422 | fsg->intr_in = ep; | ||
| 3423 | } | ||
| 3424 | |||
| 3425 | /* Fix up the descriptors */ | ||
| 3426 | device_desc.idVendor = cpu_to_le16(mod_data.vendor); | ||
| 3427 | device_desc.idProduct = cpu_to_le16(mod_data.product); | ||
| 3428 | device_desc.bcdDevice = cpu_to_le16(mod_data.release); | ||
| 3429 | |||
| 3430 | i = (transport_is_cbi() ? 3 : 2); // Number of endpoints | ||
| 3431 | fsg_intf_desc.bNumEndpoints = i; | ||
| 3432 | fsg_intf_desc.bInterfaceSubClass = mod_data.protocol_type; | ||
| 3433 | fsg_intf_desc.bInterfaceProtocol = mod_data.transport_type; | ||
| 3434 | fsg_fs_function[i + FSG_FS_FUNCTION_PRE_EP_ENTRIES] = NULL; | ||
| 3435 | |||
| 3436 | if (gadget_is_dualspeed(gadget)) { | ||
| 3437 | fsg_hs_function[i + FSG_HS_FUNCTION_PRE_EP_ENTRIES] = NULL; | ||
| 3438 | |||
| 3439 | /* Assume endpoint addresses are the same for both speeds */ | ||
| 3440 | fsg_hs_bulk_in_desc.bEndpointAddress = | ||
| 3441 | fsg_fs_bulk_in_desc.bEndpointAddress; | ||
| 3442 | fsg_hs_bulk_out_desc.bEndpointAddress = | ||
| 3443 | fsg_fs_bulk_out_desc.bEndpointAddress; | ||
| 3444 | fsg_hs_intr_in_desc.bEndpointAddress = | ||
| 3445 | fsg_fs_intr_in_desc.bEndpointAddress; | ||
| 3446 | } | ||
| 3447 | |||
| 3448 | if (gadget_is_otg(gadget)) | ||
| 3449 | fsg_otg_desc.bmAttributes |= USB_OTG_HNP; | ||
| 3450 | |||
| 3451 | rc = -ENOMEM; | ||
| 3452 | |||
| 3453 | /* Allocate the request and buffer for endpoint 0 */ | ||
| 3454 | fsg->ep0req = req = usb_ep_alloc_request(fsg->ep0, GFP_KERNEL); | ||
| 3455 | if (!req) | ||
| 3456 | goto out; | ||
| 3457 | req->buf = kmalloc(EP0_BUFSIZE, GFP_KERNEL); | ||
| 3458 | if (!req->buf) | ||
| 3459 | goto out; | ||
| 3460 | req->complete = ep0_complete; | ||
| 3461 | |||
| 3462 | /* Allocate the data buffers */ | ||
| 3463 | for (i = 0; i < FSG_NUM_BUFFERS; ++i) { | ||
| 3464 | struct fsg_buffhd *bh = &fsg->buffhds[i]; | ||
| 3465 | |||
| 3466 | /* Allocate for the bulk-in endpoint. We assume that | ||
| 3467 | * the buffer will also work with the bulk-out (and | ||
| 3468 | * interrupt-in) endpoint. */ | ||
| 3469 | bh->buf = kmalloc(mod_data.buflen, GFP_KERNEL); | ||
| 3470 | if (!bh->buf) | ||
| 3471 | goto out; | ||
| 3472 | bh->next = bh + 1; | ||
| 3473 | } | ||
| 3474 | fsg->buffhds[FSG_NUM_BUFFERS - 1].next = &fsg->buffhds[0]; | ||
| 3475 | |||
| 3476 | /* This should reflect the actual gadget power source */ | ||
| 3477 | usb_gadget_set_selfpowered(gadget); | ||
| 3478 | |||
| 3479 | snprintf(fsg_string_manufacturer, sizeof fsg_string_manufacturer, | ||
| 3480 | "%s %s with %s", | ||
| 3481 | init_utsname()->sysname, init_utsname()->release, | ||
| 3482 | gadget->name); | ||
| 3483 | |||
| 3484 | fsg->thread_task = kthread_create(fsg_main_thread, fsg, | ||
| 3485 | "file-storage-gadget"); | ||
| 3486 | if (IS_ERR(fsg->thread_task)) { | ||
| 3487 | rc = PTR_ERR(fsg->thread_task); | ||
| 3488 | goto out; | ||
| 3489 | } | ||
| 3490 | |||
| 3491 | INFO(fsg, DRIVER_DESC ", version: " DRIVER_VERSION "\n"); | ||
| 3492 | INFO(fsg, "NOTE: This driver is deprecated. " | ||
| 3493 | "Consider using g_mass_storage instead.\n"); | ||
| 3494 | INFO(fsg, "Number of LUNs=%d\n", fsg->nluns); | ||
| 3495 | |||
| 3496 | pathbuf = kmalloc(PATH_MAX, GFP_KERNEL); | ||
| 3497 | for (i = 0; i < fsg->nluns; ++i) { | ||
| 3498 | curlun = &fsg->luns[i]; | ||
| 3499 | if (fsg_lun_is_open(curlun)) { | ||
| 3500 | p = NULL; | ||
| 3501 | if (pathbuf) { | ||
| 3502 | p = d_path(&curlun->filp->f_path, | ||
| 3503 | pathbuf, PATH_MAX); | ||
| 3504 | if (IS_ERR(p)) | ||
| 3505 | p = NULL; | ||
| 3506 | } | ||
| 3507 | LINFO(curlun, "ro=%d, nofua=%d, file: %s\n", | ||
| 3508 | curlun->ro, curlun->nofua, (p ? p : "(error)")); | ||
| 3509 | } | ||
| 3510 | } | ||
| 3511 | kfree(pathbuf); | ||
| 3512 | |||
| 3513 | DBG(fsg, "transport=%s (x%02x)\n", | ||
| 3514 | mod_data.transport_name, mod_data.transport_type); | ||
| 3515 | DBG(fsg, "protocol=%s (x%02x)\n", | ||
| 3516 | mod_data.protocol_name, mod_data.protocol_type); | ||
| 3517 | DBG(fsg, "VendorID=x%04x, ProductID=x%04x, Release=x%04x\n", | ||
| 3518 | mod_data.vendor, mod_data.product, mod_data.release); | ||
| 3519 | DBG(fsg, "removable=%d, stall=%d, cdrom=%d, buflen=%u\n", | ||
| 3520 | mod_data.removable, mod_data.can_stall, | ||
| 3521 | mod_data.cdrom, mod_data.buflen); | ||
| 3522 | DBG(fsg, "I/O thread pid: %d\n", task_pid_nr(fsg->thread_task)); | ||
| 3523 | |||
| 3524 | set_bit(REGISTERED, &fsg->atomic_bitflags); | ||
| 3525 | |||
| 3526 | /* Tell the thread to start working */ | ||
| 3527 | wake_up_process(fsg->thread_task); | ||
| 3528 | return 0; | ||
| 3529 | |||
| 3530 | autoconf_fail: | ||
| 3531 | ERROR(fsg, "unable to autoconfigure all endpoints\n"); | ||
| 3532 | rc = -ENOTSUPP; | ||
| 3533 | |||
| 3534 | out: | ||
| 3535 | fsg->state = FSG_STATE_TERMINATED; // The thread is dead | ||
| 3536 | fsg_unbind(gadget); | ||
| 3537 | complete(&fsg->thread_notifier); | ||
| 3538 | return rc; | ||
| 3539 | } | ||
| 3540 | |||
| 3541 | |||
| 3542 | /*-------------------------------------------------------------------------*/ | ||
| 3543 | |||
| 3544 | static void fsg_suspend(struct usb_gadget *gadget) | ||
| 3545 | { | ||
| 3546 | struct fsg_dev *fsg = get_gadget_data(gadget); | ||
| 3547 | |||
| 3548 | DBG(fsg, "suspend\n"); | ||
| 3549 | set_bit(SUSPENDED, &fsg->atomic_bitflags); | ||
| 3550 | } | ||
| 3551 | |||
| 3552 | static void fsg_resume(struct usb_gadget *gadget) | ||
| 3553 | { | ||
| 3554 | struct fsg_dev *fsg = get_gadget_data(gadget); | ||
| 3555 | |||
| 3556 | DBG(fsg, "resume\n"); | ||
| 3557 | clear_bit(SUSPENDED, &fsg->atomic_bitflags); | ||
| 3558 | } | ||
| 3559 | |||
| 3560 | |||
| 3561 | /*-------------------------------------------------------------------------*/ | ||
| 3562 | |||
| 3563 | static struct usb_gadget_driver fsg_driver = { | ||
| 3564 | #ifdef CONFIG_USB_GADGET_DUALSPEED | ||
| 3565 | .speed = USB_SPEED_HIGH, | ||
| 3566 | #else | ||
| 3567 | .speed = USB_SPEED_FULL, | ||
| 3568 | #endif | ||
| 3569 | .function = (char *) fsg_string_product, | ||
| 3570 | .unbind = fsg_unbind, | ||
| 3571 | .disconnect = fsg_disconnect, | ||
| 3572 | .setup = fsg_setup, | ||
| 3573 | .suspend = fsg_suspend, | ||
| 3574 | .resume = fsg_resume, | ||
| 3575 | |||
| 3576 | .driver = { | ||
| 3577 | .name = DRIVER_NAME, | ||
| 3578 | .owner = THIS_MODULE, | ||
| 3579 | // .release = ... | ||
| 3580 | // .suspend = ... | ||
| 3581 | // .resume = ... | ||
| 3582 | }, | ||
| 3583 | }; | ||
| 3584 | |||
| 3585 | |||
| 3586 | static int __init fsg_alloc(void) | ||
| 3587 | { | ||
| 3588 | struct fsg_dev *fsg; | ||
| 3589 | |||
| 3590 | fsg = kzalloc(sizeof *fsg, GFP_KERNEL); | ||
| 3591 | if (!fsg) | ||
| 3592 | return -ENOMEM; | ||
| 3593 | spin_lock_init(&fsg->lock); | ||
| 3594 | init_rwsem(&fsg->filesem); | ||
| 3595 | kref_init(&fsg->ref); | ||
| 3596 | init_completion(&fsg->thread_notifier); | ||
| 3597 | |||
| 3598 | the_fsg = fsg; | ||
| 3599 | return 0; | ||
| 3600 | } | ||
| 3601 | |||
| 3602 | |||
| 3603 | static int __init fsg_init(void) | ||
| 3604 | { | ||
| 3605 | int rc; | ||
| 3606 | struct fsg_dev *fsg; | ||
| 3607 | |||
| 3608 | if ((rc = fsg_alloc()) != 0) | ||
| 3609 | return rc; | ||
| 3610 | fsg = the_fsg; | ||
| 3611 | if ((rc = usb_gadget_probe_driver(&fsg_driver, fsg_bind)) != 0) | ||
| 3612 | kref_put(&fsg->ref, fsg_release); | ||
| 3613 | return rc; | ||
| 3614 | } | ||
| 3615 | module_init(fsg_init); | ||
| 3616 | |||
| 3617 | |||
| 3618 | static void __exit fsg_cleanup(void) | ||
| 3619 | { | ||
| 3620 | struct fsg_dev *fsg = the_fsg; | ||
| 3621 | |||
| 3622 | /* Unregister the driver iff the thread hasn't already done so */ | ||
| 3623 | if (test_and_clear_bit(REGISTERED, &fsg->atomic_bitflags)) | ||
| 3624 | usb_gadget_unregister_driver(&fsg_driver); | ||
| 3625 | |||
| 3626 | /* Wait for the thread to finish up */ | ||
| 3627 | wait_for_completion(&fsg->thread_notifier); | ||
| 3628 | |||
| 3629 | kref_put(&fsg->ref, fsg_release); | ||
| 3630 | } | ||
| 3631 | module_exit(fsg_cleanup); | ||
diff --git a/drivers/usb/gadget/fsl_tegra_udc.c b/drivers/usb/gadget/fsl_tegra_udc.c new file mode 100644 index 00000000000..b254258726f --- /dev/null +++ b/drivers/usb/gadget/fsl_tegra_udc.c | |||
| @@ -0,0 +1,155 @@ | |||
| 1 | /* | ||
| 2 | * Description: | ||
| 3 | * Helper functions to support the tegra USB controller | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify it | ||
| 6 | * under the terms of the GNU General Public License as published by the | ||
| 7 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 8 | * option) any later version. | ||
| 9 | */ | ||
| 10 | #include <linux/fsl_devices.h> | ||
| 11 | #include <linux/platform_device.h> | ||
| 12 | #include <linux/err.h> | ||
| 13 | #include <linux/io.h> | ||
| 14 | #include <mach/usb_phy.h> | ||
| 15 | |||
| 16 | static struct tegra_usb_phy *phy; | ||
| 17 | static struct clk *udc_clk; | ||
| 18 | static struct clk *emc_clk; | ||
| 19 | static struct clk *sclk_clk; | ||
| 20 | static void *udc_base; | ||
| 21 | |||
| 22 | int fsl_udc_clk_init(struct platform_device *pdev) | ||
| 23 | { | ||
| 24 | struct resource *res; | ||
| 25 | int err; | ||
| 26 | int instance; | ||
| 27 | struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; | ||
| 28 | |||
| 29 | |||
| 30 | udc_clk = clk_get(&pdev->dev, NULL); | ||
| 31 | if (IS_ERR(udc_clk)) { | ||
| 32 | dev_err(&pdev->dev, "Can't get udc clock\n"); | ||
| 33 | return PTR_ERR(udc_clk); | ||
| 34 | } | ||
| 35 | |||
| 36 | clk_enable(udc_clk); | ||
| 37 | |||
| 38 | sclk_clk = clk_get(&pdev->dev, "sclk"); | ||
| 39 | if (IS_ERR(sclk_clk)) { | ||
| 40 | dev_err(&pdev->dev, "Can't get sclk clock\n"); | ||
| 41 | err = PTR_ERR(sclk_clk); | ||
| 42 | goto err_sclk; | ||
| 43 | } | ||
| 44 | |||
| 45 | clk_set_rate(sclk_clk, 80000000); | ||
| 46 | clk_enable(sclk_clk); | ||
| 47 | |||
| 48 | emc_clk = clk_get(&pdev->dev, "emc"); | ||
| 49 | if (IS_ERR(emc_clk)) { | ||
| 50 | dev_err(&pdev->dev, "Can't get emc clock\n"); | ||
| 51 | err = PTR_ERR(emc_clk); | ||
| 52 | goto err_emc; | ||
| 53 | } | ||
| 54 | |||
| 55 | clk_enable(emc_clk); | ||
| 56 | #ifdef CONFIG_ARCH_TEGRA_2x_SOC | ||
| 57 | /* Set DDR busy hints to 150MHz. For Tegra 2x SOC, DDR rate is half of EMC rate */ | ||
| 58 | clk_set_rate(emc_clk, 300000000); | ||
| 59 | #else | ||
| 60 | /* Set DDR busy hints to 100MHz. For Tegra 3x SOC DDR rate equals to EMC rate */ | ||
| 61 | clk_set_rate(emc_clk, 100000000); | ||
| 62 | #endif | ||
| 63 | |||
| 64 | /* we have to remap the registers ourselves as fsl_udc does not | ||
| 65 | * export them for us. | ||
| 66 | */ | ||
| 67 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 68 | if (!res) { | ||
| 69 | err = -ENXIO; | ||
| 70 | goto err0; | ||
| 71 | } | ||
| 72 | udc_base = ioremap(res->start, resource_size(res)); | ||
| 73 | if (!udc_base) { | ||
| 74 | err = -ENOMEM; | ||
| 75 | goto err0; | ||
| 76 | } | ||
| 77 | |||
| 78 | instance = pdev->id; | ||
| 79 | if (instance == -1) | ||
| 80 | instance = 0; | ||
| 81 | |||
| 82 | phy = tegra_usb_phy_open(instance, udc_base, pdata->phy_config, | ||
| 83 | TEGRA_USB_PHY_MODE_DEVICE, pdata->usb_phy_type); | ||
| 84 | if (IS_ERR(phy)) { | ||
| 85 | dev_err(&pdev->dev, "Can't open phy\n"); | ||
| 86 | err = PTR_ERR(phy); | ||
| 87 | goto err1; | ||
| 88 | } | ||
| 89 | tegra_usb_phy_power_on(phy, true); | ||
| 90 | |||
| 91 | return 0; | ||
| 92 | err1: | ||
| 93 | iounmap(udc_base); | ||
| 94 | err0: | ||
| 95 | clk_disable(emc_clk); | ||
| 96 | clk_put(emc_clk); | ||
| 97 | err_emc: | ||
| 98 | clk_disable(sclk_clk); | ||
| 99 | clk_put(sclk_clk); | ||
| 100 | err_sclk: | ||
| 101 | clk_disable(udc_clk); | ||
| 102 | clk_put(udc_clk); | ||
| 103 | return err; | ||
| 104 | } | ||
| 105 | |||
| 106 | void fsl_udc_clk_finalize(struct platform_device *pdev) | ||
| 107 | { | ||
| 108 | } | ||
| 109 | |||
| 110 | void fsl_udc_clk_release(void) | ||
| 111 | { | ||
| 112 | tegra_usb_phy_close(phy); | ||
| 113 | |||
| 114 | iounmap(udc_base); | ||
| 115 | |||
| 116 | clk_disable(udc_clk); | ||
| 117 | clk_put(udc_clk); | ||
| 118 | |||
| 119 | clk_disable(sclk_clk); | ||
| 120 | clk_put(sclk_clk); | ||
| 121 | |||
| 122 | clk_disable(emc_clk); | ||
| 123 | clk_put(emc_clk); | ||
| 124 | } | ||
| 125 | |||
| 126 | void fsl_udc_clk_suspend(bool is_dpd) | ||
| 127 | { | ||
| 128 | tegra_usb_phy_power_off(phy, is_dpd); | ||
| 129 | clk_disable(udc_clk); | ||
| 130 | clk_disable(sclk_clk); | ||
| 131 | clk_disable(emc_clk); | ||
| 132 | } | ||
| 133 | |||
| 134 | void fsl_udc_clk_resume(bool is_dpd) | ||
| 135 | { | ||
| 136 | clk_enable(emc_clk); | ||
| 137 | clk_enable(sclk_clk); | ||
| 138 | clk_enable(udc_clk); | ||
| 139 | tegra_usb_phy_power_on(phy, is_dpd); | ||
| 140 | } | ||
| 141 | |||
| 142 | void fsl_udc_clk_enable(void) | ||
| 143 | { | ||
| 144 | clk_enable(udc_clk); | ||
| 145 | } | ||
| 146 | |||
| 147 | void fsl_udc_clk_disable(void) | ||
| 148 | { | ||
| 149 | clk_disable(udc_clk); | ||
| 150 | } | ||
| 151 | |||
| 152 | bool fsl_udc_charger_detect(void) | ||
| 153 | { | ||
| 154 | return tegra_usb_phy_charger_detect(phy); | ||
| 155 | } | ||
diff --git a/drivers/usb/gadget/langwell_udc.c b/drivers/usb/gadget/langwell_udc.c new file mode 100644 index 00000000000..a06e2c27b43 --- /dev/null +++ b/drivers/usb/gadget/langwell_udc.c | |||
| @@ -0,0 +1,3607 @@ | |||
| 1 | /* | ||
| 2 | * Intel Langwell USB Device Controller driver | ||
| 3 | * Copyright (C) 2008-2009, Intel Corporation. | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify it | ||
| 6 | * under the terms and conditions of the GNU General Public License, | ||
| 7 | * version 2, as published by the Free Software Foundation. | ||
| 8 | * | ||
| 9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
| 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 12 | * more details. | ||
| 13 | * | ||
| 14 | * You should have received a copy of the GNU General Public License along with | ||
| 15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
| 16 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 17 | * | ||
| 18 | */ | ||
| 19 | |||
| 20 | |||
| 21 | /* #undef DEBUG */ | ||
| 22 | /* #undef VERBOSE_DEBUG */ | ||
| 23 | |||
| 24 | #if defined(CONFIG_USB_LANGWELL_OTG) | ||
| 25 | #define OTG_TRANSCEIVER | ||
| 26 | #endif | ||
| 27 | |||
| 28 | |||
| 29 | #include <linux/module.h> | ||
| 30 | #include <linux/pci.h> | ||
| 31 | #include <linux/dma-mapping.h> | ||
| 32 | #include <linux/kernel.h> | ||
| 33 | #include <linux/delay.h> | ||
| 34 | #include <linux/ioport.h> | ||
| 35 | #include <linux/sched.h> | ||
| 36 | #include <linux/slab.h> | ||
| 37 | #include <linux/errno.h> | ||
| 38 | #include <linux/init.h> | ||
| 39 | #include <linux/timer.h> | ||
| 40 | #include <linux/list.h> | ||
| 41 | #include <linux/interrupt.h> | ||
| 42 | #include <linux/moduleparam.h> | ||
| 43 | #include <linux/device.h> | ||
| 44 | #include <linux/usb/ch9.h> | ||
| 45 | #include <linux/usb/gadget.h> | ||
| 46 | #include <linux/usb/otg.h> | ||
| 47 | #include <linux/pm.h> | ||
| 48 | #include <linux/io.h> | ||
| 49 | #include <linux/irq.h> | ||
| 50 | #include <asm/system.h> | ||
| 51 | #include <asm/unaligned.h> | ||
| 52 | |||
| 53 | #include "langwell_udc.h" | ||
| 54 | |||
| 55 | |||
| 56 | #define DRIVER_DESC "Intel Langwell USB Device Controller driver" | ||
| 57 | #define DRIVER_VERSION "16 May 2009" | ||
| 58 | |||
| 59 | static const char driver_name[] = "langwell_udc"; | ||
| 60 | static const char driver_desc[] = DRIVER_DESC; | ||
| 61 | |||
| 62 | |||
| 63 | /* controller device global variable */ | ||
| 64 | static struct langwell_udc *the_controller; | ||
| 65 | |||
| 66 | /* for endpoint 0 operations */ | ||
| 67 | static const struct usb_endpoint_descriptor | ||
| 68 | langwell_ep0_desc = { | ||
| 69 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
| 70 | .bDescriptorType = USB_DT_ENDPOINT, | ||
| 71 | .bEndpointAddress = 0, | ||
| 72 | .bmAttributes = USB_ENDPOINT_XFER_CONTROL, | ||
| 73 | .wMaxPacketSize = EP0_MAX_PKT_SIZE, | ||
| 74 | }; | ||
| 75 | |||
| 76 | |||
| 77 | /*-------------------------------------------------------------------------*/ | ||
| 78 | /* debugging */ | ||
| 79 | |||
| 80 | #ifdef VERBOSE_DEBUG | ||
| 81 | static inline void print_all_registers(struct langwell_udc *dev) | ||
| 82 | { | ||
| 83 | int i; | ||
| 84 | |||
| 85 | /* Capability Registers */ | ||
| 86 | dev_dbg(&dev->pdev->dev, | ||
| 87 | "Capability Registers (offset: 0x%04x, length: 0x%08x)\n", | ||
| 88 | CAP_REG_OFFSET, (u32)sizeof(struct langwell_cap_regs)); | ||
| 89 | dev_dbg(&dev->pdev->dev, "caplength=0x%02x\n", | ||
| 90 | readb(&dev->cap_regs->caplength)); | ||
| 91 | dev_dbg(&dev->pdev->dev, "hciversion=0x%04x\n", | ||
| 92 | readw(&dev->cap_regs->hciversion)); | ||
| 93 | dev_dbg(&dev->pdev->dev, "hcsparams=0x%08x\n", | ||
| 94 | readl(&dev->cap_regs->hcsparams)); | ||
| 95 | dev_dbg(&dev->pdev->dev, "hccparams=0x%08x\n", | ||
| 96 | readl(&dev->cap_regs->hccparams)); | ||
| 97 | dev_dbg(&dev->pdev->dev, "dciversion=0x%04x\n", | ||
| 98 | readw(&dev->cap_regs->dciversion)); | ||
| 99 | dev_dbg(&dev->pdev->dev, "dccparams=0x%08x\n", | ||
| 100 | readl(&dev->cap_regs->dccparams)); | ||
| 101 | |||
| 102 | /* Operational Registers */ | ||
| 103 | dev_dbg(&dev->pdev->dev, | ||
| 104 | "Operational Registers (offset: 0x%04x, length: 0x%08x)\n", | ||
| 105 | OP_REG_OFFSET, (u32)sizeof(struct langwell_op_regs)); | ||
| 106 | dev_dbg(&dev->pdev->dev, "extsts=0x%08x\n", | ||
| 107 | readl(&dev->op_regs->extsts)); | ||
| 108 | dev_dbg(&dev->pdev->dev, "extintr=0x%08x\n", | ||
| 109 | readl(&dev->op_regs->extintr)); | ||
| 110 | dev_dbg(&dev->pdev->dev, "usbcmd=0x%08x\n", | ||
| 111 | readl(&dev->op_regs->usbcmd)); | ||
| 112 | dev_dbg(&dev->pdev->dev, "usbsts=0x%08x\n", | ||
| 113 | readl(&dev->op_regs->usbsts)); | ||
| 114 | dev_dbg(&dev->pdev->dev, "usbintr=0x%08x\n", | ||
| 115 | readl(&dev->op_regs->usbintr)); | ||
| 116 | dev_dbg(&dev->pdev->dev, "frindex=0x%08x\n", | ||
| 117 | readl(&dev->op_regs->frindex)); | ||
| 118 | dev_dbg(&dev->pdev->dev, "ctrldssegment=0x%08x\n", | ||
| 119 | readl(&dev->op_regs->ctrldssegment)); | ||
| 120 | dev_dbg(&dev->pdev->dev, "deviceaddr=0x%08x\n", | ||
| 121 | readl(&dev->op_regs->deviceaddr)); | ||
| 122 | dev_dbg(&dev->pdev->dev, "endpointlistaddr=0x%08x\n", | ||
| 123 | readl(&dev->op_regs->endpointlistaddr)); | ||
| 124 | dev_dbg(&dev->pdev->dev, "ttctrl=0x%08x\n", | ||
| 125 | readl(&dev->op_regs->ttctrl)); | ||
| 126 | dev_dbg(&dev->pdev->dev, "burstsize=0x%08x\n", | ||
| 127 | readl(&dev->op_regs->burstsize)); | ||
| 128 | dev_dbg(&dev->pdev->dev, "txfilltuning=0x%08x\n", | ||
| 129 | readl(&dev->op_regs->txfilltuning)); | ||
| 130 | dev_dbg(&dev->pdev->dev, "txttfilltuning=0x%08x\n", | ||
| 131 | readl(&dev->op_regs->txttfilltuning)); | ||
| 132 | dev_dbg(&dev->pdev->dev, "ic_usb=0x%08x\n", | ||
| 133 | readl(&dev->op_regs->ic_usb)); | ||
| 134 | dev_dbg(&dev->pdev->dev, "ulpi_viewport=0x%08x\n", | ||
| 135 | readl(&dev->op_regs->ulpi_viewport)); | ||
| 136 | dev_dbg(&dev->pdev->dev, "configflag=0x%08x\n", | ||
| 137 | readl(&dev->op_regs->configflag)); | ||
| 138 | dev_dbg(&dev->pdev->dev, "portsc1=0x%08x\n", | ||
| 139 | readl(&dev->op_regs->portsc1)); | ||
| 140 | dev_dbg(&dev->pdev->dev, "devlc=0x%08x\n", | ||
| 141 | readl(&dev->op_regs->devlc)); | ||
| 142 | dev_dbg(&dev->pdev->dev, "otgsc=0x%08x\n", | ||
| 143 | readl(&dev->op_regs->otgsc)); | ||
| 144 | dev_dbg(&dev->pdev->dev, "usbmode=0x%08x\n", | ||
| 145 | readl(&dev->op_regs->usbmode)); | ||
| 146 | dev_dbg(&dev->pdev->dev, "endptnak=0x%08x\n", | ||
| 147 | readl(&dev->op_regs->endptnak)); | ||
| 148 | dev_dbg(&dev->pdev->dev, "endptnaken=0x%08x\n", | ||
| 149 | readl(&dev->op_regs->endptnaken)); | ||
| 150 | dev_dbg(&dev->pdev->dev, "endptsetupstat=0x%08x\n", | ||
| 151 | readl(&dev->op_regs->endptsetupstat)); | ||
| 152 | dev_dbg(&dev->pdev->dev, "endptprime=0x%08x\n", | ||
| 153 | readl(&dev->op_regs->endptprime)); | ||
| 154 | dev_dbg(&dev->pdev->dev, "endptflush=0x%08x\n", | ||
| 155 | readl(&dev->op_regs->endptflush)); | ||
| 156 | dev_dbg(&dev->pdev->dev, "endptstat=0x%08x\n", | ||
| 157 | readl(&dev->op_regs->endptstat)); | ||
| 158 | dev_dbg(&dev->pdev->dev, "endptcomplete=0x%08x\n", | ||
| 159 | readl(&dev->op_regs->endptcomplete)); | ||
| 160 | |||
| 161 | for (i = 0; i < dev->ep_max / 2; i++) { | ||
| 162 | dev_dbg(&dev->pdev->dev, "endptctrl[%d]=0x%08x\n", | ||
| 163 | i, readl(&dev->op_regs->endptctrl[i])); | ||
| 164 | } | ||
| 165 | } | ||
| 166 | #else | ||
| 167 | |||
| 168 | #define print_all_registers(dev) do { } while (0) | ||
| 169 | |||
| 170 | #endif /* VERBOSE_DEBUG */ | ||
| 171 | |||
| 172 | |||
| 173 | /*-------------------------------------------------------------------------*/ | ||
| 174 | |||
| 175 | #define is_in(ep) (((ep)->ep_num == 0) ? ((ep)->dev->ep0_dir == \ | ||
| 176 | USB_DIR_IN) : (usb_endpoint_dir_in((ep)->desc))) | ||
| 177 | |||
| 178 | #define DIR_STRING(ep) (is_in(ep) ? "in" : "out") | ||
| 179 | |||
| 180 | |||
| 181 | static char *type_string(const struct usb_endpoint_descriptor *desc) | ||
| 182 | { | ||
| 183 | switch (usb_endpoint_type(desc)) { | ||
| 184 | case USB_ENDPOINT_XFER_BULK: | ||
| 185 | return "bulk"; | ||
| 186 | case USB_ENDPOINT_XFER_ISOC: | ||
| 187 | return "iso"; | ||
| 188 | case USB_ENDPOINT_XFER_INT: | ||
| 189 | return "int"; | ||
| 190 | }; | ||
| 191 | |||
| 192 | return "control"; | ||
| 193 | } | ||
| 194 | |||
| 195 | |||
| 196 | /* configure endpoint control registers */ | ||
| 197 | static void ep_reset(struct langwell_ep *ep, unsigned char ep_num, | ||
| 198 | unsigned char is_in, unsigned char ep_type) | ||
| 199 | { | ||
| 200 | struct langwell_udc *dev; | ||
| 201 | u32 endptctrl; | ||
| 202 | |||
| 203 | dev = ep->dev; | ||
| 204 | dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 205 | |||
| 206 | endptctrl = readl(&dev->op_regs->endptctrl[ep_num]); | ||
| 207 | if (is_in) { /* TX */ | ||
| 208 | if (ep_num) | ||
| 209 | endptctrl |= EPCTRL_TXR; | ||
| 210 | endptctrl |= EPCTRL_TXE; | ||
| 211 | endptctrl |= ep_type << EPCTRL_TXT_SHIFT; | ||
| 212 | } else { /* RX */ | ||
| 213 | if (ep_num) | ||
| 214 | endptctrl |= EPCTRL_RXR; | ||
| 215 | endptctrl |= EPCTRL_RXE; | ||
| 216 | endptctrl |= ep_type << EPCTRL_RXT_SHIFT; | ||
| 217 | } | ||
| 218 | |||
| 219 | writel(endptctrl, &dev->op_regs->endptctrl[ep_num]); | ||
| 220 | |||
| 221 | dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 222 | } | ||
| 223 | |||
| 224 | |||
| 225 | /* reset ep0 dQH and endptctrl */ | ||
| 226 | static void ep0_reset(struct langwell_udc *dev) | ||
| 227 | { | ||
| 228 | struct langwell_ep *ep; | ||
| 229 | int i; | ||
| 230 | |||
| 231 | dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 232 | |||
| 233 | /* ep0 in and out */ | ||
| 234 | for (i = 0; i < 2; i++) { | ||
| 235 | ep = &dev->ep[i]; | ||
| 236 | ep->dev = dev; | ||
| 237 | |||
| 238 | /* ep0 dQH */ | ||
| 239 | ep->dqh = &dev->ep_dqh[i]; | ||
| 240 | |||
| 241 | /* configure ep0 endpoint capabilities in dQH */ | ||
| 242 | ep->dqh->dqh_ios = 1; | ||
| 243 | ep->dqh->dqh_mpl = EP0_MAX_PKT_SIZE; | ||
| 244 | |||
| 245 | /* enable ep0-in HW zero length termination select */ | ||
| 246 | if (is_in(ep)) | ||
| 247 | ep->dqh->dqh_zlt = 0; | ||
| 248 | ep->dqh->dqh_mult = 0; | ||
| 249 | |||
| 250 | ep->dqh->dtd_next = DTD_TERM; | ||
| 251 | |||
| 252 | /* configure ep0 control registers */ | ||
| 253 | ep_reset(&dev->ep[0], 0, i, USB_ENDPOINT_XFER_CONTROL); | ||
| 254 | } | ||
| 255 | |||
| 256 | dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 257 | } | ||
| 258 | |||
| 259 | |||
| 260 | /*-------------------------------------------------------------------------*/ | ||
| 261 | |||
| 262 | /* endpoints operations */ | ||
| 263 | |||
| 264 | /* configure endpoint, making it usable */ | ||
| 265 | static int langwell_ep_enable(struct usb_ep *_ep, | ||
| 266 | const struct usb_endpoint_descriptor *desc) | ||
| 267 | { | ||
| 268 | struct langwell_udc *dev; | ||
| 269 | struct langwell_ep *ep; | ||
| 270 | u16 max = 0; | ||
| 271 | unsigned long flags; | ||
| 272 | int i, retval = 0; | ||
| 273 | unsigned char zlt, ios = 0, mult = 0; | ||
| 274 | |||
| 275 | ep = container_of(_ep, struct langwell_ep, ep); | ||
| 276 | dev = ep->dev; | ||
| 277 | dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 278 | |||
| 279 | if (!_ep || !desc || ep->desc | ||
| 280 | || desc->bDescriptorType != USB_DT_ENDPOINT) | ||
| 281 | return -EINVAL; | ||
| 282 | |||
| 283 | if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) | ||
| 284 | return -ESHUTDOWN; | ||
| 285 | |||
| 286 | max = le16_to_cpu(desc->wMaxPacketSize); | ||
| 287 | |||
| 288 | /* | ||
| 289 | * disable HW zero length termination select | ||
| 290 | * driver handles zero length packet through req->req.zero | ||
| 291 | */ | ||
| 292 | zlt = 1; | ||
| 293 | |||
| 294 | /* | ||
| 295 | * sanity check type, direction, address, and then | ||
| 296 | * initialize the endpoint capabilities fields in dQH | ||
| 297 | */ | ||
| 298 | switch (usb_endpoint_type(desc)) { | ||
| 299 | case USB_ENDPOINT_XFER_CONTROL: | ||
| 300 | ios = 1; | ||
| 301 | break; | ||
| 302 | case USB_ENDPOINT_XFER_BULK: | ||
| 303 | if ((dev->gadget.speed == USB_SPEED_HIGH | ||
| 304 | && max != 512) | ||
| 305 | || (dev->gadget.speed == USB_SPEED_FULL | ||
| 306 | && max > 64)) { | ||
| 307 | goto done; | ||
| 308 | } | ||
| 309 | break; | ||
| 310 | case USB_ENDPOINT_XFER_INT: | ||
| 311 | if (strstr(ep->ep.name, "-iso")) /* bulk is ok */ | ||
| 312 | goto done; | ||
| 313 | |||
| 314 | switch (dev->gadget.speed) { | ||
| 315 | case USB_SPEED_HIGH: | ||
| 316 | if (max <= 1024) | ||
| 317 | break; | ||
| 318 | case USB_SPEED_FULL: | ||
| 319 | if (max <= 64) | ||
| 320 | break; | ||
| 321 | default: | ||
| 322 | if (max <= 8) | ||
| 323 | break; | ||
| 324 | goto done; | ||
| 325 | } | ||
| 326 | break; | ||
| 327 | case USB_ENDPOINT_XFER_ISOC: | ||
| 328 | if (strstr(ep->ep.name, "-bulk") | ||
| 329 | || strstr(ep->ep.name, "-int")) | ||
| 330 | goto done; | ||
| 331 | |||
| 332 | switch (dev->gadget.speed) { | ||
| 333 | case USB_SPEED_HIGH: | ||
| 334 | if (max <= 1024) | ||
| 335 | break; | ||
| 336 | case USB_SPEED_FULL: | ||
| 337 | if (max <= 1023) | ||
| 338 | break; | ||
| 339 | default: | ||
| 340 | goto done; | ||
| 341 | } | ||
| 342 | /* | ||
| 343 | * FIXME: | ||
| 344 | * calculate transactions needed for high bandwidth iso | ||
| 345 | */ | ||
| 346 | mult = (unsigned char)(1 + ((max >> 11) & 0x03)); | ||
| 347 | max = max & 0x8ff; /* bit 0~10 */ | ||
| 348 | /* 3 transactions at most */ | ||
| 349 | if (mult > 3) | ||
| 350 | goto done; | ||
| 351 | break; | ||
| 352 | default: | ||
| 353 | goto done; | ||
| 354 | } | ||
| 355 | |||
| 356 | spin_lock_irqsave(&dev->lock, flags); | ||
| 357 | |||
| 358 | ep->ep.maxpacket = max; | ||
| 359 | ep->desc = desc; | ||
| 360 | ep->stopped = 0; | ||
| 361 | ep->ep_num = usb_endpoint_num(desc); | ||
| 362 | |||
| 363 | /* ep_type */ | ||
| 364 | ep->ep_type = usb_endpoint_type(desc); | ||
| 365 | |||
| 366 | /* configure endpoint control registers */ | ||
| 367 | ep_reset(ep, ep->ep_num, is_in(ep), ep->ep_type); | ||
| 368 | |||
| 369 | /* configure endpoint capabilities in dQH */ | ||
| 370 | i = ep->ep_num * 2 + is_in(ep); | ||
| 371 | ep->dqh = &dev->ep_dqh[i]; | ||
| 372 | ep->dqh->dqh_ios = ios; | ||
| 373 | ep->dqh->dqh_mpl = cpu_to_le16(max); | ||
| 374 | ep->dqh->dqh_zlt = zlt; | ||
| 375 | ep->dqh->dqh_mult = mult; | ||
| 376 | ep->dqh->dtd_next = DTD_TERM; | ||
| 377 | |||
| 378 | dev_dbg(&dev->pdev->dev, "enabled %s (ep%d%s-%s), max %04x\n", | ||
| 379 | _ep->name, | ||
| 380 | ep->ep_num, | ||
| 381 | DIR_STRING(ep), | ||
| 382 | type_string(desc), | ||
| 383 | max); | ||
| 384 | |||
| 385 | spin_unlock_irqrestore(&dev->lock, flags); | ||
| 386 | done: | ||
| 387 | dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 388 | return retval; | ||
| 389 | } | ||
| 390 | |||
| 391 | |||
| 392 | /*-------------------------------------------------------------------------*/ | ||
| 393 | |||
| 394 | /* retire a request */ | ||
| 395 | static void done(struct langwell_ep *ep, struct langwell_request *req, | ||
| 396 | int status) | ||
| 397 | { | ||
| 398 | struct langwell_udc *dev = ep->dev; | ||
| 399 | unsigned stopped = ep->stopped; | ||
| 400 | struct langwell_dtd *curr_dtd, *next_dtd; | ||
| 401 | int i; | ||
| 402 | |||
| 403 | dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 404 | |||
| 405 | /* remove the req from ep->queue */ | ||
| 406 | list_del_init(&req->queue); | ||
| 407 | |||
| 408 | if (req->req.status == -EINPROGRESS) | ||
| 409 | req->req.status = status; | ||
| 410 | else | ||
| 411 | status = req->req.status; | ||
| 412 | |||
| 413 | /* free dTD for the request */ | ||
| 414 | next_dtd = req->head; | ||
| 415 | for (i = 0; i < req->dtd_count; i++) { | ||
| 416 | curr_dtd = next_dtd; | ||
| 417 | if (i != req->dtd_count - 1) | ||
| 418 | next_dtd = curr_dtd->next_dtd_virt; | ||
| 419 | dma_pool_free(dev->dtd_pool, curr_dtd, curr_dtd->dtd_dma); | ||
| 420 | } | ||
| 421 | |||
| 422 | if (req->mapped) { | ||
| 423 | dma_unmap_single(&dev->pdev->dev, | ||
| 424 | req->req.dma, req->req.length, | ||
| 425 | is_in(ep) ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); | ||
| 426 | req->req.dma = DMA_ADDR_INVALID; | ||
| 427 | req->mapped = 0; | ||
| 428 | } else | ||
| 429 | dma_sync_single_for_cpu(&dev->pdev->dev, req->req.dma, | ||
| 430 | req->req.length, | ||
| 431 | is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE); | ||
| 432 | |||
| 433 | if (status != -ESHUTDOWN) | ||
| 434 | dev_dbg(&dev->pdev->dev, | ||
| 435 | "complete %s, req %p, stat %d, len %u/%u\n", | ||
| 436 | ep->ep.name, &req->req, status, | ||
| 437 | req->req.actual, req->req.length); | ||
| 438 | |||
| 439 | /* don't modify queue heads during completion callback */ | ||
| 440 | ep->stopped = 1; | ||
| 441 | |||
| 442 | spin_unlock(&dev->lock); | ||
| 443 | /* complete routine from gadget driver */ | ||
| 444 | if (req->req.complete) | ||
| 445 | req->req.complete(&ep->ep, &req->req); | ||
| 446 | |||
| 447 | spin_lock(&dev->lock); | ||
| 448 | ep->stopped = stopped; | ||
| 449 | |||
| 450 | dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 451 | } | ||
| 452 | |||
| 453 | |||
| 454 | static void langwell_ep_fifo_flush(struct usb_ep *_ep); | ||
| 455 | |||
| 456 | /* delete all endpoint requests, called with spinlock held */ | ||
| 457 | static void nuke(struct langwell_ep *ep, int status) | ||
| 458 | { | ||
| 459 | /* called with spinlock held */ | ||
| 460 | ep->stopped = 1; | ||
| 461 | |||
| 462 | /* endpoint fifo flush */ | ||
| 463 | if (&ep->ep && ep->desc) | ||
| 464 | langwell_ep_fifo_flush(&ep->ep); | ||
| 465 | |||
| 466 | while (!list_empty(&ep->queue)) { | ||
| 467 | struct langwell_request *req = NULL; | ||
| 468 | req = list_entry(ep->queue.next, struct langwell_request, | ||
| 469 | queue); | ||
| 470 | done(ep, req, status); | ||
| 471 | } | ||
| 472 | } | ||
| 473 | |||
| 474 | |||
| 475 | /*-------------------------------------------------------------------------*/ | ||
| 476 | |||
| 477 | /* endpoint is no longer usable */ | ||
| 478 | static int langwell_ep_disable(struct usb_ep *_ep) | ||
| 479 | { | ||
| 480 | struct langwell_ep *ep; | ||
| 481 | unsigned long flags; | ||
| 482 | struct langwell_udc *dev; | ||
| 483 | int ep_num; | ||
| 484 | u32 endptctrl; | ||
| 485 | |||
| 486 | ep = container_of(_ep, struct langwell_ep, ep); | ||
| 487 | dev = ep->dev; | ||
| 488 | dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 489 | |||
| 490 | if (!_ep || !ep->desc) | ||
| 491 | return -EINVAL; | ||
| 492 | |||
| 493 | spin_lock_irqsave(&dev->lock, flags); | ||
| 494 | |||
| 495 | /* disable endpoint control register */ | ||
| 496 | ep_num = ep->ep_num; | ||
| 497 | endptctrl = readl(&dev->op_regs->endptctrl[ep_num]); | ||
| 498 | if (is_in(ep)) | ||
| 499 | endptctrl &= ~EPCTRL_TXE; | ||
| 500 | else | ||
| 501 | endptctrl &= ~EPCTRL_RXE; | ||
| 502 | writel(endptctrl, &dev->op_regs->endptctrl[ep_num]); | ||
| 503 | |||
| 504 | /* nuke all pending requests (does flush) */ | ||
| 505 | nuke(ep, -ESHUTDOWN); | ||
| 506 | |||
| 507 | ep->desc = NULL; | ||
| 508 | ep->stopped = 1; | ||
| 509 | |||
| 510 | spin_unlock_irqrestore(&dev->lock, flags); | ||
| 511 | |||
| 512 | dev_dbg(&dev->pdev->dev, "disabled %s\n", _ep->name); | ||
| 513 | dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 514 | |||
| 515 | return 0; | ||
| 516 | } | ||
| 517 | |||
| 518 | |||
| 519 | /* allocate a request object to use with this endpoint */ | ||
| 520 | static struct usb_request *langwell_alloc_request(struct usb_ep *_ep, | ||
| 521 | gfp_t gfp_flags) | ||
| 522 | { | ||
| 523 | struct langwell_ep *ep; | ||
| 524 | struct langwell_udc *dev; | ||
| 525 | struct langwell_request *req = NULL; | ||
| 526 | |||
| 527 | if (!_ep) | ||
| 528 | return NULL; | ||
| 529 | |||
| 530 | ep = container_of(_ep, struct langwell_ep, ep); | ||
| 531 | dev = ep->dev; | ||
| 532 | dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 533 | |||
| 534 | req = kzalloc(sizeof(*req), gfp_flags); | ||
| 535 | if (!req) | ||
| 536 | return NULL; | ||
| 537 | |||
| 538 | req->req.dma = DMA_ADDR_INVALID; | ||
| 539 | INIT_LIST_HEAD(&req->queue); | ||
| 540 | |||
| 541 | dev_vdbg(&dev->pdev->dev, "alloc request for %s\n", _ep->name); | ||
| 542 | dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 543 | return &req->req; | ||
| 544 | } | ||
| 545 | |||
| 546 | |||
| 547 | /* free a request object */ | ||
| 548 | static void langwell_free_request(struct usb_ep *_ep, | ||
| 549 | struct usb_request *_req) | ||
| 550 | { | ||
| 551 | struct langwell_ep *ep; | ||
| 552 | struct langwell_udc *dev; | ||
| 553 | struct langwell_request *req = NULL; | ||
| 554 | |||
| 555 | ep = container_of(_ep, struct langwell_ep, ep); | ||
| 556 | dev = ep->dev; | ||
| 557 | dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 558 | |||
| 559 | if (!_ep || !_req) | ||
| 560 | return; | ||
| 561 | |||
| 562 | req = container_of(_req, struct langwell_request, req); | ||
| 563 | WARN_ON(!list_empty(&req->queue)); | ||
| 564 | |||
| 565 | if (_req) | ||
| 566 | kfree(req); | ||
| 567 | |||
| 568 | dev_vdbg(&dev->pdev->dev, "free request for %s\n", _ep->name); | ||
| 569 | dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 570 | } | ||
| 571 | |||
| 572 | |||
| 573 | /*-------------------------------------------------------------------------*/ | ||
| 574 | |||
| 575 | /* queue dTD and PRIME endpoint */ | ||
| 576 | static int queue_dtd(struct langwell_ep *ep, struct langwell_request *req) | ||
| 577 | { | ||
| 578 | u32 bit_mask, usbcmd, endptstat, dtd_dma; | ||
| 579 | u8 dtd_status; | ||
| 580 | int i; | ||
| 581 | struct langwell_dqh *dqh; | ||
| 582 | struct langwell_udc *dev; | ||
| 583 | |||
| 584 | dev = ep->dev; | ||
| 585 | dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 586 | |||
| 587 | i = ep->ep_num * 2 + is_in(ep); | ||
| 588 | dqh = &dev->ep_dqh[i]; | ||
| 589 | |||
| 590 | if (ep->ep_num) | ||
| 591 | dev_vdbg(&dev->pdev->dev, "%s\n", ep->name); | ||
| 592 | else | ||
| 593 | /* ep0 */ | ||
| 594 | dev_vdbg(&dev->pdev->dev, "%s-%s\n", ep->name, DIR_STRING(ep)); | ||
| 595 | |||
| 596 | dev_vdbg(&dev->pdev->dev, "ep_dqh[%d] addr: 0x%p\n", | ||
| 597 | i, &(dev->ep_dqh[i])); | ||
| 598 | |||
| 599 | bit_mask = is_in(ep) ? | ||
| 600 | (1 << (ep->ep_num + 16)) : (1 << (ep->ep_num)); | ||
| 601 | |||
| 602 | dev_vdbg(&dev->pdev->dev, "bit_mask = 0x%08x\n", bit_mask); | ||
| 603 | |||
| 604 | /* check if the pipe is empty */ | ||
| 605 | if (!(list_empty(&ep->queue))) { | ||
| 606 | /* add dTD to the end of linked list */ | ||
| 607 | struct langwell_request *lastreq; | ||
| 608 | lastreq = list_entry(ep->queue.prev, | ||
| 609 | struct langwell_request, queue); | ||
| 610 | |||
| 611 | lastreq->tail->dtd_next = | ||
| 612 | cpu_to_le32(req->head->dtd_dma & DTD_NEXT_MASK); | ||
| 613 | |||
| 614 | /* read prime bit, if 1 goto out */ | ||
| 615 | if (readl(&dev->op_regs->endptprime) & bit_mask) | ||
| 616 | goto out; | ||
| 617 | |||
| 618 | do { | ||
| 619 | /* set ATDTW bit in USBCMD */ | ||
| 620 | usbcmd = readl(&dev->op_regs->usbcmd); | ||
| 621 | writel(usbcmd | CMD_ATDTW, &dev->op_regs->usbcmd); | ||
| 622 | |||
| 623 | /* read correct status bit */ | ||
| 624 | endptstat = readl(&dev->op_regs->endptstat) & bit_mask; | ||
| 625 | |||
| 626 | } while (!(readl(&dev->op_regs->usbcmd) & CMD_ATDTW)); | ||
| 627 | |||
| 628 | /* write ATDTW bit to 0 */ | ||
| 629 | usbcmd = readl(&dev->op_regs->usbcmd); | ||
| 630 | writel(usbcmd & ~CMD_ATDTW, &dev->op_regs->usbcmd); | ||
| 631 | |||
| 632 | if (endptstat) | ||
| 633 | goto out; | ||
| 634 | } | ||
| 635 | |||
| 636 | /* write dQH next pointer and terminate bit to 0 */ | ||
| 637 | dtd_dma = req->head->dtd_dma & DTD_NEXT_MASK; | ||
| 638 | dqh->dtd_next = cpu_to_le32(dtd_dma); | ||
| 639 | |||
| 640 | /* clear active and halt bit */ | ||
| 641 | dtd_status = (u8) ~(DTD_STS_ACTIVE | DTD_STS_HALTED); | ||
| 642 | dqh->dtd_status &= dtd_status; | ||
| 643 | dev_vdbg(&dev->pdev->dev, "dqh->dtd_status = 0x%x\n", dqh->dtd_status); | ||
| 644 | |||
| 645 | /* ensure that updates to the dQH will occur before priming */ | ||
| 646 | wmb(); | ||
| 647 | |||
| 648 | /* write 1 to endptprime register to PRIME endpoint */ | ||
| 649 | bit_mask = is_in(ep) ? (1 << (ep->ep_num + 16)) : (1 << ep->ep_num); | ||
| 650 | dev_vdbg(&dev->pdev->dev, "endprime bit_mask = 0x%08x\n", bit_mask); | ||
| 651 | writel(bit_mask, &dev->op_regs->endptprime); | ||
| 652 | out: | ||
| 653 | dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 654 | return 0; | ||
| 655 | } | ||
| 656 | |||
| 657 | |||
| 658 | /* fill in the dTD structure to build a transfer descriptor */ | ||
| 659 | static struct langwell_dtd *build_dtd(struct langwell_request *req, | ||
| 660 | unsigned *length, dma_addr_t *dma, int *is_last) | ||
| 661 | { | ||
| 662 | u32 buf_ptr; | ||
| 663 | struct langwell_dtd *dtd; | ||
| 664 | struct langwell_udc *dev; | ||
| 665 | int i; | ||
| 666 | |||
| 667 | dev = req->ep->dev; | ||
| 668 | dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 669 | |||
| 670 | /* the maximum transfer length, up to 16k bytes */ | ||
| 671 | *length = min(req->req.length - req->req.actual, | ||
| 672 | (unsigned)DTD_MAX_TRANSFER_LENGTH); | ||
| 673 | |||
| 674 | /* create dTD dma_pool resource */ | ||
| 675 | dtd = dma_pool_alloc(dev->dtd_pool, GFP_KERNEL, dma); | ||
| 676 | if (dtd == NULL) | ||
| 677 | return dtd; | ||
| 678 | dtd->dtd_dma = *dma; | ||
| 679 | |||
| 680 | /* initialize buffer page pointers */ | ||
| 681 | buf_ptr = (u32)(req->req.dma + req->req.actual); | ||
| 682 | for (i = 0; i < 5; i++) | ||
| 683 | dtd->dtd_buf[i] = cpu_to_le32(buf_ptr + i * PAGE_SIZE); | ||
| 684 | |||
| 685 | req->req.actual += *length; | ||
| 686 | |||
| 687 | /* fill in total bytes with transfer size */ | ||
| 688 | dtd->dtd_total = cpu_to_le16(*length); | ||
| 689 | dev_vdbg(&dev->pdev->dev, "dtd->dtd_total = %d\n", dtd->dtd_total); | ||
| 690 | |||
| 691 | /* set is_last flag if req->req.zero is set or not */ | ||
| 692 | if (req->req.zero) { | ||
| 693 | if (*length == 0 || (*length % req->ep->ep.maxpacket) != 0) | ||
| 694 | *is_last = 1; | ||
| 695 | else | ||
| 696 | *is_last = 0; | ||
| 697 | } else if (req->req.length == req->req.actual) { | ||
| 698 | *is_last = 1; | ||
| 699 | } else | ||
| 700 | *is_last = 0; | ||
| 701 | |||
| 702 | if (*is_last == 0) | ||
| 703 | dev_vdbg(&dev->pdev->dev, "multi-dtd request!\n"); | ||
| 704 | |||
| 705 | /* set interrupt on complete bit for the last dTD */ | ||
| 706 | if (*is_last && !req->req.no_interrupt) | ||
| 707 | dtd->dtd_ioc = 1; | ||
| 708 | |||
| 709 | /* set multiplier override 0 for non-ISO and non-TX endpoint */ | ||
| 710 | dtd->dtd_multo = 0; | ||
| 711 | |||
| 712 | /* set the active bit of status field to 1 */ | ||
| 713 | dtd->dtd_status = DTD_STS_ACTIVE; | ||
| 714 | dev_vdbg(&dev->pdev->dev, "dtd->dtd_status = 0x%02x\n", | ||
| 715 | dtd->dtd_status); | ||
| 716 | |||
| 717 | dev_vdbg(&dev->pdev->dev, "length = %d, dma addr= 0x%08x\n", | ||
| 718 | *length, (int)*dma); | ||
| 719 | dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 720 | return dtd; | ||
| 721 | } | ||
| 722 | |||
| 723 | |||
| 724 | /* generate dTD linked list for a request */ | ||
| 725 | static int req_to_dtd(struct langwell_request *req) | ||
| 726 | { | ||
| 727 | unsigned count; | ||
| 728 | int is_last, is_first = 1; | ||
| 729 | struct langwell_dtd *dtd, *last_dtd = NULL; | ||
| 730 | struct langwell_udc *dev; | ||
| 731 | dma_addr_t dma; | ||
| 732 | |||
| 733 | dev = req->ep->dev; | ||
| 734 | dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 735 | do { | ||
| 736 | dtd = build_dtd(req, &count, &dma, &is_last); | ||
| 737 | if (dtd == NULL) | ||
| 738 | return -ENOMEM; | ||
| 739 | |||
| 740 | if (is_first) { | ||
| 741 | is_first = 0; | ||
| 742 | req->head = dtd; | ||
| 743 | } else { | ||
| 744 | last_dtd->dtd_next = cpu_to_le32(dma); | ||
| 745 | last_dtd->next_dtd_virt = dtd; | ||
| 746 | } | ||
| 747 | last_dtd = dtd; | ||
| 748 | req->dtd_count++; | ||
| 749 | } while (!is_last); | ||
| 750 | |||
| 751 | /* set terminate bit to 1 for the last dTD */ | ||
| 752 | dtd->dtd_next = DTD_TERM; | ||
| 753 | |||
| 754 | req->tail = dtd; | ||
| 755 | |||
| 756 | dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 757 | return 0; | ||
| 758 | } | ||
| 759 | |||
| 760 | /*-------------------------------------------------------------------------*/ | ||
| 761 | |||
| 762 | /* queue (submits) an I/O requests to an endpoint */ | ||
| 763 | static int langwell_ep_queue(struct usb_ep *_ep, struct usb_request *_req, | ||
| 764 | gfp_t gfp_flags) | ||
| 765 | { | ||
| 766 | struct langwell_request *req; | ||
| 767 | struct langwell_ep *ep; | ||
| 768 | struct langwell_udc *dev; | ||
| 769 | unsigned long flags; | ||
| 770 | int is_iso = 0, zlflag = 0; | ||
| 771 | |||
| 772 | /* always require a cpu-view buffer */ | ||
| 773 | req = container_of(_req, struct langwell_request, req); | ||
| 774 | ep = container_of(_ep, struct langwell_ep, ep); | ||
| 775 | |||
| 776 | if (!_req || !_req->complete || !_req->buf | ||
| 777 | || !list_empty(&req->queue)) { | ||
| 778 | return -EINVAL; | ||
| 779 | } | ||
| 780 | |||
| 781 | if (unlikely(!_ep || !ep->desc)) | ||
| 782 | return -EINVAL; | ||
| 783 | |||
| 784 | dev = ep->dev; | ||
| 785 | req->ep = ep; | ||
| 786 | dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 787 | |||
| 788 | if (usb_endpoint_xfer_isoc(ep->desc)) { | ||
| 789 | if (req->req.length > ep->ep.maxpacket) | ||
| 790 | return -EMSGSIZE; | ||
| 791 | is_iso = 1; | ||
| 792 | } | ||
| 793 | |||
| 794 | if (unlikely(!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)) | ||
| 795 | return -ESHUTDOWN; | ||
| 796 | |||
| 797 | /* set up dma mapping in case the caller didn't */ | ||
| 798 | if (_req->dma == DMA_ADDR_INVALID) { | ||
| 799 | /* WORKAROUND: WARN_ON(size == 0) */ | ||
| 800 | if (_req->length == 0) { | ||
| 801 | dev_vdbg(&dev->pdev->dev, "req->length: 0->1\n"); | ||
| 802 | zlflag = 1; | ||
| 803 | _req->length++; | ||
| 804 | } | ||
| 805 | |||
| 806 | _req->dma = dma_map_single(&dev->pdev->dev, | ||
| 807 | _req->buf, _req->length, | ||
| 808 | is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE); | ||
| 809 | if (zlflag && (_req->length == 1)) { | ||
| 810 | dev_vdbg(&dev->pdev->dev, "req->length: 1->0\n"); | ||
| 811 | zlflag = 0; | ||
| 812 | _req->length = 0; | ||
| 813 | } | ||
| 814 | |||
| 815 | req->mapped = 1; | ||
| 816 | dev_vdbg(&dev->pdev->dev, "req->mapped = 1\n"); | ||
| 817 | } else { | ||
| 818 | dma_sync_single_for_device(&dev->pdev->dev, | ||
| 819 | _req->dma, _req->length, | ||
| 820 | is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE); | ||
| 821 | req->mapped = 0; | ||
| 822 | dev_vdbg(&dev->pdev->dev, "req->mapped = 0\n"); | ||
| 823 | } | ||
| 824 | |||
| 825 | dev_dbg(&dev->pdev->dev, | ||
| 826 | "%s queue req %p, len %u, buf %p, dma 0x%08x\n", | ||
| 827 | _ep->name, | ||
| 828 | _req, _req->length, _req->buf, (int)_req->dma); | ||
| 829 | |||
| 830 | _req->status = -EINPROGRESS; | ||
| 831 | _req->actual = 0; | ||
| 832 | req->dtd_count = 0; | ||
| 833 | |||
| 834 | spin_lock_irqsave(&dev->lock, flags); | ||
| 835 | |||
| 836 | /* build and put dTDs to endpoint queue */ | ||
| 837 | if (!req_to_dtd(req)) { | ||
| 838 | queue_dtd(ep, req); | ||
| 839 | } else { | ||
| 840 | spin_unlock_irqrestore(&dev->lock, flags); | ||
| 841 | return -ENOMEM; | ||
| 842 | } | ||
| 843 | |||
| 844 | /* update ep0 state */ | ||
| 845 | if (ep->ep_num == 0) | ||
| 846 | dev->ep0_state = DATA_STATE_XMIT; | ||
| 847 | |||
| 848 | if (likely(req != NULL)) { | ||
| 849 | list_add_tail(&req->queue, &ep->queue); | ||
| 850 | dev_vdbg(&dev->pdev->dev, "list_add_tail()\n"); | ||
| 851 | } | ||
| 852 | |||
| 853 | spin_unlock_irqrestore(&dev->lock, flags); | ||
| 854 | |||
| 855 | dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 856 | return 0; | ||
| 857 | } | ||
| 858 | |||
| 859 | |||
| 860 | /* dequeue (cancels, unlinks) an I/O request from an endpoint */ | ||
| 861 | static int langwell_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req) | ||
| 862 | { | ||
| 863 | struct langwell_ep *ep; | ||
| 864 | struct langwell_udc *dev; | ||
| 865 | struct langwell_request *req; | ||
| 866 | unsigned long flags; | ||
| 867 | int stopped, ep_num, retval = 0; | ||
| 868 | u32 endptctrl; | ||
| 869 | |||
| 870 | ep = container_of(_ep, struct langwell_ep, ep); | ||
| 871 | dev = ep->dev; | ||
| 872 | dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 873 | |||
| 874 | if (!_ep || !ep->desc || !_req) | ||
| 875 | return -EINVAL; | ||
| 876 | |||
| 877 | if (!dev->driver) | ||
| 878 | return -ESHUTDOWN; | ||
| 879 | |||
| 880 | spin_lock_irqsave(&dev->lock, flags); | ||
| 881 | stopped = ep->stopped; | ||
| 882 | |||
| 883 | /* quiesce dma while we patch the queue */ | ||
| 884 | ep->stopped = 1; | ||
| 885 | ep_num = ep->ep_num; | ||
| 886 | |||
| 887 | /* disable endpoint control register */ | ||
| 888 | endptctrl = readl(&dev->op_regs->endptctrl[ep_num]); | ||
| 889 | if (is_in(ep)) | ||
| 890 | endptctrl &= ~EPCTRL_TXE; | ||
| 891 | else | ||
| 892 | endptctrl &= ~EPCTRL_RXE; | ||
| 893 | writel(endptctrl, &dev->op_regs->endptctrl[ep_num]); | ||
| 894 | |||
| 895 | /* make sure it's still queued on this endpoint */ | ||
| 896 | list_for_each_entry(req, &ep->queue, queue) { | ||
| 897 | if (&req->req == _req) | ||
| 898 | break; | ||
| 899 | } | ||
| 900 | |||
| 901 | if (&req->req != _req) { | ||
| 902 | retval = -EINVAL; | ||
| 903 | goto done; | ||
| 904 | } | ||
| 905 | |||
| 906 | /* queue head may be partially complete. */ | ||
| 907 | if (ep->queue.next == &req->queue) { | ||
| 908 | dev_dbg(&dev->pdev->dev, "unlink (%s) dma\n", _ep->name); | ||
| 909 | _req->status = -ECONNRESET; | ||
| 910 | langwell_ep_fifo_flush(&ep->ep); | ||
| 911 | |||
| 912 | /* not the last request in endpoint queue */ | ||
| 913 | if (likely(ep->queue.next == &req->queue)) { | ||
| 914 | struct langwell_dqh *dqh; | ||
| 915 | struct langwell_request *next_req; | ||
| 916 | |||
| 917 | dqh = ep->dqh; | ||
| 918 | next_req = list_entry(req->queue.next, | ||
| 919 | struct langwell_request, queue); | ||
| 920 | |||
| 921 | /* point the dQH to the first dTD of next request */ | ||
| 922 | writel((u32) next_req->head, &dqh->dqh_current); | ||
| 923 | } | ||
| 924 | } else { | ||
| 925 | struct langwell_request *prev_req; | ||
| 926 | |||
| 927 | prev_req = list_entry(req->queue.prev, | ||
| 928 | struct langwell_request, queue); | ||
| 929 | writel(readl(&req->tail->dtd_next), | ||
| 930 | &prev_req->tail->dtd_next); | ||
| 931 | } | ||
| 932 | |||
| 933 | done(ep, req, -ECONNRESET); | ||
| 934 | |||
| 935 | done: | ||
| 936 | /* enable endpoint again */ | ||
| 937 | endptctrl = readl(&dev->op_regs->endptctrl[ep_num]); | ||
| 938 | if (is_in(ep)) | ||
| 939 | endptctrl |= EPCTRL_TXE; | ||
| 940 | else | ||
| 941 | endptctrl |= EPCTRL_RXE; | ||
| 942 | writel(endptctrl, &dev->op_regs->endptctrl[ep_num]); | ||
| 943 | |||
| 944 | ep->stopped = stopped; | ||
| 945 | spin_unlock_irqrestore(&dev->lock, flags); | ||
| 946 | |||
| 947 | dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 948 | return retval; | ||
| 949 | } | ||
| 950 | |||
| 951 | |||
| 952 | /*-------------------------------------------------------------------------*/ | ||
| 953 | |||
| 954 | /* endpoint set/clear halt */ | ||
| 955 | static void ep_set_halt(struct langwell_ep *ep, int value) | ||
| 956 | { | ||
| 957 | u32 endptctrl = 0; | ||
| 958 | int ep_num; | ||
| 959 | struct langwell_udc *dev = ep->dev; | ||
| 960 | dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 961 | |||
| 962 | ep_num = ep->ep_num; | ||
| 963 | endptctrl = readl(&dev->op_regs->endptctrl[ep_num]); | ||
| 964 | |||
| 965 | /* value: 1 - set halt, 0 - clear halt */ | ||
| 966 | if (value) { | ||
| 967 | /* set the stall bit */ | ||
| 968 | if (is_in(ep)) | ||
| 969 | endptctrl |= EPCTRL_TXS; | ||
| 970 | else | ||
| 971 | endptctrl |= EPCTRL_RXS; | ||
| 972 | } else { | ||
| 973 | /* clear the stall bit and reset data toggle */ | ||
| 974 | if (is_in(ep)) { | ||
| 975 | endptctrl &= ~EPCTRL_TXS; | ||
| 976 | endptctrl |= EPCTRL_TXR; | ||
| 977 | } else { | ||
| 978 | endptctrl &= ~EPCTRL_RXS; | ||
| 979 | endptctrl |= EPCTRL_RXR; | ||
| 980 | } | ||
| 981 | } | ||
| 982 | |||
| 983 | writel(endptctrl, &dev->op_regs->endptctrl[ep_num]); | ||
| 984 | |||
| 985 | dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 986 | } | ||
| 987 | |||
| 988 | |||
| 989 | /* set the endpoint halt feature */ | ||
| 990 | static int langwell_ep_set_halt(struct usb_ep *_ep, int value) | ||
| 991 | { | ||
| 992 | struct langwell_ep *ep; | ||
| 993 | struct langwell_udc *dev; | ||
| 994 | unsigned long flags; | ||
| 995 | int retval = 0; | ||
| 996 | |||
| 997 | ep = container_of(_ep, struct langwell_ep, ep); | ||
| 998 | dev = ep->dev; | ||
| 999 | |||
| 1000 | dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 1001 | |||
| 1002 | if (!_ep || !ep->desc) | ||
| 1003 | return -EINVAL; | ||
| 1004 | |||
| 1005 | if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) | ||
| 1006 | return -ESHUTDOWN; | ||
| 1007 | |||
| 1008 | if (usb_endpoint_xfer_isoc(ep->desc)) | ||
| 1009 | return -EOPNOTSUPP; | ||
| 1010 | |||
| 1011 | spin_lock_irqsave(&dev->lock, flags); | ||
| 1012 | |||
| 1013 | /* | ||
| 1014 | * attempt to halt IN ep will fail if any transfer requests | ||
| 1015 | * are still queue | ||
| 1016 | */ | ||
| 1017 | if (!list_empty(&ep->queue) && is_in(ep) && value) { | ||
| 1018 | /* IN endpoint FIFO holds bytes */ | ||
| 1019 | dev_dbg(&dev->pdev->dev, "%s FIFO holds bytes\n", _ep->name); | ||
| 1020 | retval = -EAGAIN; | ||
| 1021 | goto done; | ||
| 1022 | } | ||
| 1023 | |||
| 1024 | /* endpoint set/clear halt */ | ||
| 1025 | if (ep->ep_num) { | ||
| 1026 | ep_set_halt(ep, value); | ||
| 1027 | } else { /* endpoint 0 */ | ||
| 1028 | dev->ep0_state = WAIT_FOR_SETUP; | ||
| 1029 | dev->ep0_dir = USB_DIR_OUT; | ||
| 1030 | } | ||
| 1031 | done: | ||
| 1032 | spin_unlock_irqrestore(&dev->lock, flags); | ||
| 1033 | dev_dbg(&dev->pdev->dev, "%s %s halt\n", | ||
| 1034 | _ep->name, value ? "set" : "clear"); | ||
| 1035 | dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 1036 | return retval; | ||
| 1037 | } | ||
| 1038 | |||
| 1039 | |||
| 1040 | /* set the halt feature and ignores clear requests */ | ||
| 1041 | static int langwell_ep_set_wedge(struct usb_ep *_ep) | ||
| 1042 | { | ||
| 1043 | struct langwell_ep *ep; | ||
| 1044 | struct langwell_udc *dev; | ||
| 1045 | |||
| 1046 | ep = container_of(_ep, struct langwell_ep, ep); | ||
| 1047 | dev = ep->dev; | ||
| 1048 | |||
| 1049 | dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 1050 | |||
| 1051 | if (!_ep || !ep->desc) | ||
| 1052 | return -EINVAL; | ||
| 1053 | |||
| 1054 | dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 1055 | return usb_ep_set_halt(_ep); | ||
| 1056 | } | ||
| 1057 | |||
| 1058 | |||
| 1059 | /* flush contents of a fifo */ | ||
| 1060 | static void langwell_ep_fifo_flush(struct usb_ep *_ep) | ||
| 1061 | { | ||
| 1062 | struct langwell_ep *ep; | ||
| 1063 | struct langwell_udc *dev; | ||
| 1064 | u32 flush_bit; | ||
| 1065 | unsigned long timeout; | ||
| 1066 | |||
| 1067 | ep = container_of(_ep, struct langwell_ep, ep); | ||
| 1068 | dev = ep->dev; | ||
| 1069 | |||
| 1070 | dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 1071 | |||
| 1072 | if (!_ep || !ep->desc) { | ||
| 1073 | dev_vdbg(&dev->pdev->dev, "ep or ep->desc is NULL\n"); | ||
| 1074 | dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 1075 | return; | ||
| 1076 | } | ||
| 1077 | |||
| 1078 | dev_vdbg(&dev->pdev->dev, "%s-%s fifo flush\n", | ||
| 1079 | _ep->name, DIR_STRING(ep)); | ||
| 1080 | |||
| 1081 | /* flush endpoint buffer */ | ||
| 1082 | if (ep->ep_num == 0) | ||
| 1083 | flush_bit = (1 << 16) | 1; | ||
| 1084 | else if (is_in(ep)) | ||
| 1085 | flush_bit = 1 << (ep->ep_num + 16); /* TX */ | ||
| 1086 | else | ||
| 1087 | flush_bit = 1 << ep->ep_num; /* RX */ | ||
| 1088 | |||
| 1089 | /* wait until flush complete */ | ||
| 1090 | timeout = jiffies + FLUSH_TIMEOUT; | ||
| 1091 | do { | ||
| 1092 | writel(flush_bit, &dev->op_regs->endptflush); | ||
| 1093 | while (readl(&dev->op_regs->endptflush)) { | ||
| 1094 | if (time_after(jiffies, timeout)) { | ||
| 1095 | dev_err(&dev->pdev->dev, "ep flush timeout\n"); | ||
| 1096 | goto done; | ||
| 1097 | } | ||
| 1098 | cpu_relax(); | ||
| 1099 | } | ||
| 1100 | } while (readl(&dev->op_regs->endptstat) & flush_bit); | ||
| 1101 | done: | ||
| 1102 | dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 1103 | } | ||
| 1104 | |||
| 1105 | |||
| 1106 | /* endpoints operations structure */ | ||
| 1107 | static const struct usb_ep_ops langwell_ep_ops = { | ||
| 1108 | |||
| 1109 | /* configure endpoint, making it usable */ | ||
| 1110 | .enable = langwell_ep_enable, | ||
| 1111 | |||
| 1112 | /* endpoint is no longer usable */ | ||
| 1113 | .disable = langwell_ep_disable, | ||
| 1114 | |||
| 1115 | /* allocate a request object to use with this endpoint */ | ||
| 1116 | .alloc_request = langwell_alloc_request, | ||
| 1117 | |||
| 1118 | /* free a request object */ | ||
| 1119 | .free_request = langwell_free_request, | ||
| 1120 | |||
| 1121 | /* queue (submits) an I/O requests to an endpoint */ | ||
| 1122 | .queue = langwell_ep_queue, | ||
| 1123 | |||
| 1124 | /* dequeue (cancels, unlinks) an I/O request from an endpoint */ | ||
| 1125 | .dequeue = langwell_ep_dequeue, | ||
| 1126 | |||
| 1127 | /* set the endpoint halt feature */ | ||
| 1128 | .set_halt = langwell_ep_set_halt, | ||
| 1129 | |||
| 1130 | /* set the halt feature and ignores clear requests */ | ||
| 1131 | .set_wedge = langwell_ep_set_wedge, | ||
| 1132 | |||
| 1133 | /* flush contents of a fifo */ | ||
| 1134 | .fifo_flush = langwell_ep_fifo_flush, | ||
| 1135 | }; | ||
| 1136 | |||
| 1137 | |||
| 1138 | /*-------------------------------------------------------------------------*/ | ||
| 1139 | |||
| 1140 | /* device controller usb_gadget_ops structure */ | ||
| 1141 | |||
| 1142 | /* returns the current frame number */ | ||
| 1143 | static int langwell_get_frame(struct usb_gadget *_gadget) | ||
| 1144 | { | ||
| 1145 | struct langwell_udc *dev; | ||
| 1146 | u16 retval; | ||
| 1147 | |||
| 1148 | if (!_gadget) | ||
| 1149 | return -ENODEV; | ||
| 1150 | |||
| 1151 | dev = container_of(_gadget, struct langwell_udc, gadget); | ||
| 1152 | dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 1153 | |||
| 1154 | retval = readl(&dev->op_regs->frindex) & FRINDEX_MASK; | ||
| 1155 | |||
| 1156 | dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 1157 | return retval; | ||
| 1158 | } | ||
| 1159 | |||
| 1160 | |||
| 1161 | /* enter or exit PHY low power state */ | ||
| 1162 | static void langwell_phy_low_power(struct langwell_udc *dev, bool flag) | ||
| 1163 | { | ||
| 1164 | u32 devlc; | ||
| 1165 | u8 devlc_byte2; | ||
| 1166 | dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 1167 | |||
| 1168 | devlc = readl(&dev->op_regs->devlc); | ||
| 1169 | dev_vdbg(&dev->pdev->dev, "devlc = 0x%08x\n", devlc); | ||
| 1170 | |||
| 1171 | if (flag) | ||
| 1172 | devlc |= LPM_PHCD; | ||
| 1173 | else | ||
| 1174 | devlc &= ~LPM_PHCD; | ||
| 1175 | |||
| 1176 | /* FIXME: workaround for Langwell A1/A2/A3 sighting */ | ||
| 1177 | devlc_byte2 = (devlc >> 16) & 0xff; | ||
| 1178 | writeb(devlc_byte2, (u8 *)&dev->op_regs->devlc + 2); | ||
| 1179 | |||
| 1180 | devlc = readl(&dev->op_regs->devlc); | ||
| 1181 | dev_vdbg(&dev->pdev->dev, | ||
| 1182 | "%s PHY low power suspend, devlc = 0x%08x\n", | ||
| 1183 | flag ? "enter" : "exit", devlc); | ||
| 1184 | } | ||
| 1185 | |||
| 1186 | |||
| 1187 | /* tries to wake up the host connected to this gadget */ | ||
| 1188 | static int langwell_wakeup(struct usb_gadget *_gadget) | ||
| 1189 | { | ||
| 1190 | struct langwell_udc *dev; | ||
| 1191 | u32 portsc1; | ||
| 1192 | unsigned long flags; | ||
| 1193 | |||
| 1194 | if (!_gadget) | ||
| 1195 | return 0; | ||
| 1196 | |||
| 1197 | dev = container_of(_gadget, struct langwell_udc, gadget); | ||
| 1198 | dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 1199 | |||
| 1200 | /* remote wakeup feature not enabled by host */ | ||
| 1201 | if (!dev->remote_wakeup) { | ||
| 1202 | dev_info(&dev->pdev->dev, "remote wakeup is disabled\n"); | ||
| 1203 | return -ENOTSUPP; | ||
| 1204 | } | ||
| 1205 | |||
| 1206 | spin_lock_irqsave(&dev->lock, flags); | ||
| 1207 | |||
| 1208 | portsc1 = readl(&dev->op_regs->portsc1); | ||
| 1209 | if (!(portsc1 & PORTS_SUSP)) { | ||
| 1210 | spin_unlock_irqrestore(&dev->lock, flags); | ||
| 1211 | return 0; | ||
| 1212 | } | ||
| 1213 | |||
| 1214 | /* LPM L1 to L0 or legacy remote wakeup */ | ||
| 1215 | if (dev->lpm && dev->lpm_state == LPM_L1) | ||
| 1216 | dev_info(&dev->pdev->dev, "LPM L1 to L0 remote wakeup\n"); | ||
| 1217 | else | ||
| 1218 | dev_info(&dev->pdev->dev, "device remote wakeup\n"); | ||
| 1219 | |||
| 1220 | /* exit PHY low power suspend */ | ||
| 1221 | if (dev->pdev->device != 0x0829) | ||
| 1222 | langwell_phy_low_power(dev, 0); | ||
| 1223 | |||
| 1224 | /* force port resume */ | ||
| 1225 | portsc1 |= PORTS_FPR; | ||
| 1226 | writel(portsc1, &dev->op_regs->portsc1); | ||
| 1227 | |||
| 1228 | spin_unlock_irqrestore(&dev->lock, flags); | ||
| 1229 | |||
| 1230 | dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 1231 | return 0; | ||
| 1232 | } | ||
| 1233 | |||
| 1234 | |||
| 1235 | /* notify controller that VBUS is powered or not */ | ||
| 1236 | static int langwell_vbus_session(struct usb_gadget *_gadget, int is_active) | ||
| 1237 | { | ||
| 1238 | struct langwell_udc *dev; | ||
| 1239 | unsigned long flags; | ||
| 1240 | u32 usbcmd; | ||
| 1241 | |||
| 1242 | if (!_gadget) | ||
| 1243 | return -ENODEV; | ||
| 1244 | |||
| 1245 | dev = container_of(_gadget, struct langwell_udc, gadget); | ||
| 1246 | dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 1247 | |||
| 1248 | spin_lock_irqsave(&dev->lock, flags); | ||
| 1249 | dev_vdbg(&dev->pdev->dev, "VBUS status: %s\n", | ||
| 1250 | is_active ? "on" : "off"); | ||
| 1251 | |||
| 1252 | dev->vbus_active = (is_active != 0); | ||
| 1253 | if (dev->driver && dev->softconnected && dev->vbus_active) { | ||
| 1254 | usbcmd = readl(&dev->op_regs->usbcmd); | ||
| 1255 | usbcmd |= CMD_RUNSTOP; | ||
| 1256 | writel(usbcmd, &dev->op_regs->usbcmd); | ||
| 1257 | } else { | ||
| 1258 | usbcmd = readl(&dev->op_regs->usbcmd); | ||
| 1259 | usbcmd &= ~CMD_RUNSTOP; | ||
| 1260 | writel(usbcmd, &dev->op_regs->usbcmd); | ||
| 1261 | } | ||
| 1262 | |||
| 1263 | spin_unlock_irqrestore(&dev->lock, flags); | ||
| 1264 | |||
| 1265 | dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 1266 | return 0; | ||
| 1267 | } | ||
| 1268 | |||
| 1269 | |||
| 1270 | /* constrain controller's VBUS power usage */ | ||
| 1271 | static int langwell_vbus_draw(struct usb_gadget *_gadget, unsigned mA) | ||
| 1272 | { | ||
| 1273 | struct langwell_udc *dev; | ||
| 1274 | |||
| 1275 | if (!_gadget) | ||
| 1276 | return -ENODEV; | ||
| 1277 | |||
| 1278 | dev = container_of(_gadget, struct langwell_udc, gadget); | ||
| 1279 | dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 1280 | |||
| 1281 | if (dev->transceiver) { | ||
| 1282 | dev_vdbg(&dev->pdev->dev, "otg_set_power\n"); | ||
| 1283 | dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 1284 | return otg_set_power(dev->transceiver, mA); | ||
| 1285 | } | ||
| 1286 | |||
| 1287 | dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 1288 | return -ENOTSUPP; | ||
| 1289 | } | ||
| 1290 | |||
| 1291 | |||
| 1292 | /* D+ pullup, software-controlled connect/disconnect to USB host */ | ||
| 1293 | static int langwell_pullup(struct usb_gadget *_gadget, int is_on) | ||
| 1294 | { | ||
| 1295 | struct langwell_udc *dev; | ||
| 1296 | u32 usbcmd; | ||
| 1297 | unsigned long flags; | ||
| 1298 | |||
| 1299 | if (!_gadget) | ||
| 1300 | return -ENODEV; | ||
| 1301 | |||
| 1302 | dev = container_of(_gadget, struct langwell_udc, gadget); | ||
| 1303 | |||
| 1304 | dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 1305 | |||
| 1306 | spin_lock_irqsave(&dev->lock, flags); | ||
| 1307 | dev->softconnected = (is_on != 0); | ||
| 1308 | |||
| 1309 | if (dev->driver && dev->softconnected && dev->vbus_active) { | ||
| 1310 | usbcmd = readl(&dev->op_regs->usbcmd); | ||
| 1311 | usbcmd |= CMD_RUNSTOP; | ||
| 1312 | writel(usbcmd, &dev->op_regs->usbcmd); | ||
| 1313 | } else { | ||
| 1314 | usbcmd = readl(&dev->op_regs->usbcmd); | ||
| 1315 | usbcmd &= ~CMD_RUNSTOP; | ||
| 1316 | writel(usbcmd, &dev->op_regs->usbcmd); | ||
| 1317 | } | ||
| 1318 | spin_unlock_irqrestore(&dev->lock, flags); | ||
| 1319 | |||
| 1320 | dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 1321 | return 0; | ||
| 1322 | } | ||
| 1323 | |||
| 1324 | static int langwell_start(struct usb_gadget_driver *driver, | ||
| 1325 | int (*bind)(struct usb_gadget *)); | ||
| 1326 | static int langwell_stop(struct usb_gadget_driver *driver); | ||
| 1327 | /* device controller usb_gadget_ops structure */ | ||
| 1328 | static const struct usb_gadget_ops langwell_ops = { | ||
| 1329 | |||
| 1330 | /* returns the current frame number */ | ||
| 1331 | .get_frame = langwell_get_frame, | ||
| 1332 | |||
| 1333 | /* tries to wake up the host connected to this gadget */ | ||
| 1334 | .wakeup = langwell_wakeup, | ||
| 1335 | |||
| 1336 | /* set the device selfpowered feature, always selfpowered */ | ||
| 1337 | /* .set_selfpowered = langwell_set_selfpowered, */ | ||
| 1338 | |||
| 1339 | /* notify controller that VBUS is powered or not */ | ||
| 1340 | .vbus_session = langwell_vbus_session, | ||
| 1341 | |||
| 1342 | /* constrain controller's VBUS power usage */ | ||
| 1343 | .vbus_draw = langwell_vbus_draw, | ||
| 1344 | |||
| 1345 | /* D+ pullup, software-controlled connect/disconnect to USB host */ | ||
| 1346 | .pullup = langwell_pullup, | ||
| 1347 | |||
| 1348 | .start = langwell_start, | ||
| 1349 | .stop = langwell_stop, | ||
| 1350 | }; | ||
| 1351 | |||
| 1352 | |||
| 1353 | /*-------------------------------------------------------------------------*/ | ||
| 1354 | |||
| 1355 | /* device controller operations */ | ||
| 1356 | |||
| 1357 | /* reset device controller */ | ||
| 1358 | static int langwell_udc_reset(struct langwell_udc *dev) | ||
| 1359 | { | ||
| 1360 | u32 usbcmd, usbmode, devlc, endpointlistaddr; | ||
| 1361 | u8 devlc_byte0, devlc_byte2; | ||
| 1362 | unsigned long timeout; | ||
| 1363 | |||
| 1364 | if (!dev) | ||
| 1365 | return -EINVAL; | ||
| 1366 | |||
| 1367 | dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 1368 | |||
| 1369 | /* set controller to stop state */ | ||
| 1370 | usbcmd = readl(&dev->op_regs->usbcmd); | ||
| 1371 | usbcmd &= ~CMD_RUNSTOP; | ||
| 1372 | writel(usbcmd, &dev->op_regs->usbcmd); | ||
| 1373 | |||
| 1374 | /* reset device controller */ | ||
| 1375 | usbcmd = readl(&dev->op_regs->usbcmd); | ||
| 1376 | usbcmd |= CMD_RST; | ||
| 1377 | writel(usbcmd, &dev->op_regs->usbcmd); | ||
| 1378 | |||
| 1379 | /* wait for reset to complete */ | ||
| 1380 | timeout = jiffies + RESET_TIMEOUT; | ||
| 1381 | while (readl(&dev->op_regs->usbcmd) & CMD_RST) { | ||
| 1382 | if (time_after(jiffies, timeout)) { | ||
| 1383 | dev_err(&dev->pdev->dev, "device reset timeout\n"); | ||
| 1384 | return -ETIMEDOUT; | ||
| 1385 | } | ||
| 1386 | cpu_relax(); | ||
| 1387 | } | ||
| 1388 | |||
| 1389 | /* set controller to device mode */ | ||
| 1390 | usbmode = readl(&dev->op_regs->usbmode); | ||
| 1391 | usbmode |= MODE_DEVICE; | ||
| 1392 | |||
| 1393 | /* turn setup lockout off, require setup tripwire in usbcmd */ | ||
| 1394 | usbmode |= MODE_SLOM; | ||
| 1395 | |||
| 1396 | writel(usbmode, &dev->op_regs->usbmode); | ||
| 1397 | usbmode = readl(&dev->op_regs->usbmode); | ||
| 1398 | dev_vdbg(&dev->pdev->dev, "usbmode=0x%08x\n", usbmode); | ||
| 1399 | |||
| 1400 | /* Write-Clear setup status */ | ||
| 1401 | writel(0, &dev->op_regs->usbsts); | ||
| 1402 | |||
| 1403 | /* if support USB LPM, ACK all LPM token */ | ||
| 1404 | if (dev->lpm) { | ||
| 1405 | devlc = readl(&dev->op_regs->devlc); | ||
| 1406 | dev_vdbg(&dev->pdev->dev, "devlc = 0x%08x\n", devlc); | ||
| 1407 | /* FIXME: workaround for Langwell A1/A2/A3 sighting */ | ||
| 1408 | devlc &= ~LPM_STL; /* don't STALL LPM token */ | ||
| 1409 | devlc &= ~LPM_NYT_ACK; /* ACK LPM token */ | ||
| 1410 | devlc_byte0 = devlc & 0xff; | ||
| 1411 | devlc_byte2 = (devlc >> 16) & 0xff; | ||
| 1412 | writeb(devlc_byte0, (u8 *)&dev->op_regs->devlc); | ||
| 1413 | writeb(devlc_byte2, (u8 *)&dev->op_regs->devlc + 2); | ||
| 1414 | devlc = readl(&dev->op_regs->devlc); | ||
| 1415 | dev_vdbg(&dev->pdev->dev, | ||
| 1416 | "ACK LPM token, devlc = 0x%08x\n", devlc); | ||
| 1417 | } | ||
| 1418 | |||
| 1419 | /* fill endpointlistaddr register */ | ||
| 1420 | endpointlistaddr = dev->ep_dqh_dma; | ||
| 1421 | endpointlistaddr &= ENDPOINTLISTADDR_MASK; | ||
| 1422 | writel(endpointlistaddr, &dev->op_regs->endpointlistaddr); | ||
| 1423 | |||
| 1424 | dev_vdbg(&dev->pdev->dev, | ||
| 1425 | "dQH base (vir: %p, phy: 0x%08x), endpointlistaddr=0x%08x\n", | ||
| 1426 | dev->ep_dqh, endpointlistaddr, | ||
| 1427 | readl(&dev->op_regs->endpointlistaddr)); | ||
| 1428 | dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 1429 | return 0; | ||
| 1430 | } | ||
| 1431 | |||
| 1432 | |||
| 1433 | /* reinitialize device controller endpoints */ | ||
| 1434 | static int eps_reinit(struct langwell_udc *dev) | ||
| 1435 | { | ||
| 1436 | struct langwell_ep *ep; | ||
| 1437 | char name[14]; | ||
| 1438 | int i; | ||
| 1439 | |||
| 1440 | dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 1441 | |||
| 1442 | /* initialize ep0 */ | ||
| 1443 | ep = &dev->ep[0]; | ||
| 1444 | ep->dev = dev; | ||
| 1445 | strncpy(ep->name, "ep0", sizeof(ep->name)); | ||
| 1446 | ep->ep.name = ep->name; | ||
| 1447 | ep->ep.ops = &langwell_ep_ops; | ||
| 1448 | ep->stopped = 0; | ||
| 1449 | ep->ep.maxpacket = EP0_MAX_PKT_SIZE; | ||
| 1450 | ep->ep_num = 0; | ||
| 1451 | ep->desc = &langwell_ep0_desc; | ||
| 1452 | INIT_LIST_HEAD(&ep->queue); | ||
| 1453 | |||
| 1454 | ep->ep_type = USB_ENDPOINT_XFER_CONTROL; | ||
| 1455 | |||
| 1456 | /* initialize other endpoints */ | ||
| 1457 | for (i = 2; i < dev->ep_max; i++) { | ||
| 1458 | ep = &dev->ep[i]; | ||
| 1459 | if (i % 2) | ||
| 1460 | snprintf(name, sizeof(name), "ep%din", i / 2); | ||
| 1461 | else | ||
| 1462 | snprintf(name, sizeof(name), "ep%dout", i / 2); | ||
| 1463 | ep->dev = dev; | ||
| 1464 | strncpy(ep->name, name, sizeof(ep->name)); | ||
| 1465 | ep->ep.name = ep->name; | ||
| 1466 | |||
| 1467 | ep->ep.ops = &langwell_ep_ops; | ||
| 1468 | ep->stopped = 0; | ||
| 1469 | ep->ep.maxpacket = (unsigned short) ~0; | ||
| 1470 | ep->ep_num = i / 2; | ||
| 1471 | |||
| 1472 | INIT_LIST_HEAD(&ep->queue); | ||
| 1473 | list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list); | ||
| 1474 | } | ||
| 1475 | |||
| 1476 | dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 1477 | return 0; | ||
| 1478 | } | ||
| 1479 | |||
| 1480 | |||
| 1481 | /* enable interrupt and set controller to run state */ | ||
| 1482 | static void langwell_udc_start(struct langwell_udc *dev) | ||
| 1483 | { | ||
| 1484 | u32 usbintr, usbcmd; | ||
| 1485 | dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 1486 | |||
| 1487 | /* enable interrupts */ | ||
| 1488 | usbintr = INTR_ULPIE /* ULPI */ | ||
| 1489 | | INTR_SLE /* suspend */ | ||
| 1490 | /* | INTR_SRE SOF received */ | ||
| 1491 | | INTR_URE /* USB reset */ | ||
| 1492 | | INTR_AAE /* async advance */ | ||
| 1493 | | INTR_SEE /* system error */ | ||
| 1494 | | INTR_FRE /* frame list rollover */ | ||
| 1495 | | INTR_PCE /* port change detect */ | ||
| 1496 | | INTR_UEE /* USB error interrupt */ | ||
| 1497 | | INTR_UE; /* USB interrupt */ | ||
| 1498 | writel(usbintr, &dev->op_regs->usbintr); | ||
| 1499 | |||
| 1500 | /* clear stopped bit */ | ||
| 1501 | dev->stopped = 0; | ||
| 1502 | |||
| 1503 | /* set controller to run */ | ||
| 1504 | usbcmd = readl(&dev->op_regs->usbcmd); | ||
| 1505 | usbcmd |= CMD_RUNSTOP; | ||
| 1506 | writel(usbcmd, &dev->op_regs->usbcmd); | ||
| 1507 | |||
| 1508 | dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 1509 | } | ||
| 1510 | |||
| 1511 | |||
| 1512 | /* disable interrupt and set controller to stop state */ | ||
| 1513 | static void langwell_udc_stop(struct langwell_udc *dev) | ||
| 1514 | { | ||
| 1515 | u32 usbcmd; | ||
| 1516 | |||
| 1517 | dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 1518 | |||
| 1519 | /* disable all interrupts */ | ||
| 1520 | writel(0, &dev->op_regs->usbintr); | ||
| 1521 | |||
| 1522 | /* set stopped bit */ | ||
| 1523 | dev->stopped = 1; | ||
| 1524 | |||
| 1525 | /* set controller to stop state */ | ||
| 1526 | usbcmd = readl(&dev->op_regs->usbcmd); | ||
| 1527 | usbcmd &= ~CMD_RUNSTOP; | ||
| 1528 | writel(usbcmd, &dev->op_regs->usbcmd); | ||
| 1529 | |||
| 1530 | dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 1531 | } | ||
| 1532 | |||
| 1533 | |||
| 1534 | /* stop all USB activities */ | ||
| 1535 | static void stop_activity(struct langwell_udc *dev, | ||
| 1536 | struct usb_gadget_driver *driver) | ||
| 1537 | { | ||
| 1538 | struct langwell_ep *ep; | ||
| 1539 | dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 1540 | |||
| 1541 | nuke(&dev->ep[0], -ESHUTDOWN); | ||
| 1542 | |||
| 1543 | list_for_each_entry(ep, &dev->gadget.ep_list, ep.ep_list) { | ||
| 1544 | nuke(ep, -ESHUTDOWN); | ||
| 1545 | } | ||
| 1546 | |||
| 1547 | /* report disconnect; the driver is already quiesced */ | ||
| 1548 | if (driver) { | ||
| 1549 | spin_unlock(&dev->lock); | ||
| 1550 | driver->disconnect(&dev->gadget); | ||
| 1551 | spin_lock(&dev->lock); | ||
| 1552 | } | ||
| 1553 | |||
| 1554 | dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 1555 | } | ||
| 1556 | |||
| 1557 | |||
| 1558 | /*-------------------------------------------------------------------------*/ | ||
| 1559 | |||
| 1560 | /* device "function" sysfs attribute file */ | ||
| 1561 | static ssize_t show_function(struct device *_dev, | ||
| 1562 | struct device_attribute *attr, char *buf) | ||
| 1563 | { | ||
| 1564 | struct langwell_udc *dev = the_controller; | ||
| 1565 | |||
| 1566 | if (!dev->driver || !dev->driver->function | ||
| 1567 | || strlen(dev->driver->function) > PAGE_SIZE) | ||
| 1568 | return 0; | ||
| 1569 | |||
| 1570 | return scnprintf(buf, PAGE_SIZE, "%s\n", dev->driver->function); | ||
| 1571 | } | ||
| 1572 | static DEVICE_ATTR(function, S_IRUGO, show_function, NULL); | ||
| 1573 | |||
| 1574 | |||
| 1575 | /* device "langwell_udc" sysfs attribute file */ | ||
| 1576 | static ssize_t show_langwell_udc(struct device *_dev, | ||
| 1577 | struct device_attribute *attr, char *buf) | ||
| 1578 | { | ||
| 1579 | struct langwell_udc *dev = the_controller; | ||
| 1580 | struct langwell_request *req; | ||
| 1581 | struct langwell_ep *ep = NULL; | ||
| 1582 | char *next; | ||
| 1583 | unsigned size; | ||
| 1584 | unsigned t; | ||
| 1585 | unsigned i; | ||
| 1586 | unsigned long flags; | ||
| 1587 | u32 tmp_reg; | ||
| 1588 | |||
| 1589 | next = buf; | ||
| 1590 | size = PAGE_SIZE; | ||
| 1591 | spin_lock_irqsave(&dev->lock, flags); | ||
| 1592 | |||
| 1593 | /* driver basic information */ | ||
| 1594 | t = scnprintf(next, size, | ||
| 1595 | DRIVER_DESC "\n" | ||
| 1596 | "%s version: %s\n" | ||
| 1597 | "Gadget driver: %s\n\n", | ||
| 1598 | driver_name, DRIVER_VERSION, | ||
| 1599 | dev->driver ? dev->driver->driver.name : "(none)"); | ||
| 1600 | size -= t; | ||
| 1601 | next += t; | ||
| 1602 | |||
| 1603 | /* device registers */ | ||
| 1604 | tmp_reg = readl(&dev->op_regs->usbcmd); | ||
| 1605 | t = scnprintf(next, size, | ||
| 1606 | "USBCMD reg:\n" | ||
| 1607 | "SetupTW: %d\n" | ||
| 1608 | "Run/Stop: %s\n\n", | ||
| 1609 | (tmp_reg & CMD_SUTW) ? 1 : 0, | ||
| 1610 | (tmp_reg & CMD_RUNSTOP) ? "Run" : "Stop"); | ||
| 1611 | size -= t; | ||
| 1612 | next += t; | ||
| 1613 | |||
| 1614 | tmp_reg = readl(&dev->op_regs->usbsts); | ||
| 1615 | t = scnprintf(next, size, | ||
| 1616 | "USB Status Reg:\n" | ||
| 1617 | "Device Suspend: %d\n" | ||
| 1618 | "Reset Received: %d\n" | ||
| 1619 | "System Error: %s\n" | ||
| 1620 | "USB Error Interrupt: %s\n\n", | ||
| 1621 | (tmp_reg & STS_SLI) ? 1 : 0, | ||
| 1622 | (tmp_reg & STS_URI) ? 1 : 0, | ||
| 1623 | (tmp_reg & STS_SEI) ? "Error" : "No error", | ||
| 1624 | (tmp_reg & STS_UEI) ? "Error detected" : "No error"); | ||
| 1625 | size -= t; | ||
| 1626 | next += t; | ||
| 1627 | |||
| 1628 | tmp_reg = readl(&dev->op_regs->usbintr); | ||
| 1629 | t = scnprintf(next, size, | ||
| 1630 | "USB Intrrupt Enable Reg:\n" | ||
| 1631 | "Sleep Enable: %d\n" | ||
| 1632 | "SOF Received Enable: %d\n" | ||
| 1633 | "Reset Enable: %d\n" | ||
| 1634 | "System Error Enable: %d\n" | ||
| 1635 | "Port Change Dectected Enable: %d\n" | ||
| 1636 | "USB Error Intr Enable: %d\n" | ||
| 1637 | "USB Intr Enable: %d\n\n", | ||
| 1638 | (tmp_reg & INTR_SLE) ? 1 : 0, | ||
| 1639 | (tmp_reg & INTR_SRE) ? 1 : 0, | ||
| 1640 | (tmp_reg & INTR_URE) ? 1 : 0, | ||
| 1641 | (tmp_reg & INTR_SEE) ? 1 : 0, | ||
| 1642 | (tmp_reg & INTR_PCE) ? 1 : 0, | ||
| 1643 | (tmp_reg & INTR_UEE) ? 1 : 0, | ||
| 1644 | (tmp_reg & INTR_UE) ? 1 : 0); | ||
| 1645 | size -= t; | ||
| 1646 | next += t; | ||
| 1647 | |||
| 1648 | tmp_reg = readl(&dev->op_regs->frindex); | ||
| 1649 | t = scnprintf(next, size, | ||
| 1650 | "USB Frame Index Reg:\n" | ||
| 1651 | "Frame Number is 0x%08x\n\n", | ||
| 1652 | (tmp_reg & FRINDEX_MASK)); | ||
| 1653 | size -= t; | ||
| 1654 | next += t; | ||
| 1655 | |||
| 1656 | tmp_reg = readl(&dev->op_regs->deviceaddr); | ||
| 1657 | t = scnprintf(next, size, | ||
| 1658 | "USB Device Address Reg:\n" | ||
| 1659 | "Device Addr is 0x%x\n\n", | ||
| 1660 | USBADR(tmp_reg)); | ||
| 1661 | size -= t; | ||
| 1662 | next += t; | ||
| 1663 | |||
| 1664 | tmp_reg = readl(&dev->op_regs->endpointlistaddr); | ||
| 1665 | t = scnprintf(next, size, | ||
| 1666 | "USB Endpoint List Address Reg:\n" | ||
| 1667 | "Endpoint List Pointer is 0x%x\n\n", | ||
| 1668 | EPBASE(tmp_reg)); | ||
| 1669 | size -= t; | ||
| 1670 | next += t; | ||
| 1671 | |||
| 1672 | tmp_reg = readl(&dev->op_regs->portsc1); | ||
| 1673 | t = scnprintf(next, size, | ||
| 1674 | "USB Port Status & Control Reg:\n" | ||
| 1675 | "Port Reset: %s\n" | ||
| 1676 | "Port Suspend Mode: %s\n" | ||
| 1677 | "Over-current Change: %s\n" | ||
| 1678 | "Port Enable/Disable Change: %s\n" | ||
| 1679 | "Port Enabled/Disabled: %s\n" | ||
| 1680 | "Current Connect Status: %s\n" | ||
| 1681 | "LPM Suspend Status: %s\n\n", | ||
| 1682 | (tmp_reg & PORTS_PR) ? "Reset" : "Not Reset", | ||
| 1683 | (tmp_reg & PORTS_SUSP) ? "Suspend " : "Not Suspend", | ||
| 1684 | (tmp_reg & PORTS_OCC) ? "Detected" : "No", | ||
| 1685 | (tmp_reg & PORTS_PEC) ? "Changed" : "Not Changed", | ||
| 1686 | (tmp_reg & PORTS_PE) ? "Enable" : "Not Correct", | ||
| 1687 | (tmp_reg & PORTS_CCS) ? "Attached" : "Not Attached", | ||
| 1688 | (tmp_reg & PORTS_SLP) ? "LPM L1" : "LPM L0"); | ||
| 1689 | size -= t; | ||
| 1690 | next += t; | ||
| 1691 | |||
| 1692 | tmp_reg = readl(&dev->op_regs->devlc); | ||
| 1693 | t = scnprintf(next, size, | ||
| 1694 | "Device LPM Control Reg:\n" | ||
| 1695 | "Parallel Transceiver : %d\n" | ||
| 1696 | "Serial Transceiver : %d\n" | ||
| 1697 | "Port Speed: %s\n" | ||
| 1698 | "Port Force Full Speed Connenct: %s\n" | ||
| 1699 | "PHY Low Power Suspend Clock: %s\n" | ||
| 1700 | "BmAttributes: %d\n\n", | ||
| 1701 | LPM_PTS(tmp_reg), | ||
| 1702 | (tmp_reg & LPM_STS) ? 1 : 0, | ||
| 1703 | ({ | ||
| 1704 | char *s; | ||
| 1705 | switch (LPM_PSPD(tmp_reg)) { | ||
| 1706 | case LPM_SPEED_FULL: | ||
| 1707 | s = "Full Speed"; break; | ||
| 1708 | case LPM_SPEED_LOW: | ||
| 1709 | s = "Low Speed"; break; | ||
| 1710 | case LPM_SPEED_HIGH: | ||
| 1711 | s = "High Speed"; break; | ||
| 1712 | default: | ||
| 1713 | s = "Unknown Speed"; break; | ||
| 1714 | } | ||
| 1715 | s; | ||
| 1716 | }), | ||
| 1717 | (tmp_reg & LPM_PFSC) ? "Force Full Speed" : "Not Force", | ||
| 1718 | (tmp_reg & LPM_PHCD) ? "Disabled" : "Enabled", | ||
| 1719 | LPM_BA(tmp_reg)); | ||
| 1720 | size -= t; | ||
| 1721 | next += t; | ||
| 1722 | |||
| 1723 | tmp_reg = readl(&dev->op_regs->usbmode); | ||
| 1724 | t = scnprintf(next, size, | ||
| 1725 | "USB Mode Reg:\n" | ||
| 1726 | "Controller Mode is : %s\n\n", ({ | ||
| 1727 | char *s; | ||
| 1728 | switch (MODE_CM(tmp_reg)) { | ||
| 1729 | case MODE_IDLE: | ||
| 1730 | s = "Idle"; break; | ||
| 1731 | case MODE_DEVICE: | ||
| 1732 | s = "Device Controller"; break; | ||
| 1733 | case MODE_HOST: | ||
| 1734 | s = "Host Controller"; break; | ||
| 1735 | default: | ||
| 1736 | s = "None"; break; | ||
| 1737 | } | ||
| 1738 | s; | ||
| 1739 | })); | ||
| 1740 | size -= t; | ||
| 1741 | next += t; | ||
| 1742 | |||
| 1743 | tmp_reg = readl(&dev->op_regs->endptsetupstat); | ||
| 1744 | t = scnprintf(next, size, | ||
| 1745 | "Endpoint Setup Status Reg:\n" | ||
| 1746 | "SETUP on ep 0x%04x\n\n", | ||
| 1747 | tmp_reg & SETUPSTAT_MASK); | ||
| 1748 | size -= t; | ||
| 1749 | next += t; | ||
| 1750 | |||
| 1751 | for (i = 0; i < dev->ep_max / 2; i++) { | ||
| 1752 | tmp_reg = readl(&dev->op_regs->endptctrl[i]); | ||
| 1753 | t = scnprintf(next, size, "EP Ctrl Reg [%d]: 0x%08x\n", | ||
| 1754 | i, tmp_reg); | ||
| 1755 | size -= t; | ||
| 1756 | next += t; | ||
| 1757 | } | ||
| 1758 | tmp_reg = readl(&dev->op_regs->endptprime); | ||
| 1759 | t = scnprintf(next, size, "EP Prime Reg: 0x%08x\n\n", tmp_reg); | ||
| 1760 | size -= t; | ||
| 1761 | next += t; | ||
| 1762 | |||
| 1763 | /* langwell_udc, langwell_ep, langwell_request structure information */ | ||
| 1764 | ep = &dev->ep[0]; | ||
| 1765 | t = scnprintf(next, size, "%s MaxPacketSize: 0x%x, ep_num: %d\n", | ||
| 1766 | ep->ep.name, ep->ep.maxpacket, ep->ep_num); | ||
| 1767 | size -= t; | ||
| 1768 | next += t; | ||
| 1769 | |||
| 1770 | if (list_empty(&ep->queue)) { | ||
| 1771 | t = scnprintf(next, size, "its req queue is empty\n\n"); | ||
| 1772 | size -= t; | ||
| 1773 | next += t; | ||
| 1774 | } else { | ||
| 1775 | list_for_each_entry(req, &ep->queue, queue) { | ||
| 1776 | t = scnprintf(next, size, | ||
| 1777 | "req %p actual 0x%x length 0x%x buf %p\n", | ||
| 1778 | &req->req, req->req.actual, | ||
| 1779 | req->req.length, req->req.buf); | ||
| 1780 | size -= t; | ||
| 1781 | next += t; | ||
| 1782 | } | ||
| 1783 | } | ||
| 1784 | /* other gadget->eplist ep */ | ||
| 1785 | list_for_each_entry(ep, &dev->gadget.ep_list, ep.ep_list) { | ||
| 1786 | if (ep->desc) { | ||
| 1787 | t = scnprintf(next, size, | ||
| 1788 | "\n%s MaxPacketSize: 0x%x, " | ||
| 1789 | "ep_num: %d\n", | ||
| 1790 | ep->ep.name, ep->ep.maxpacket, | ||
| 1791 | ep->ep_num); | ||
| 1792 | size -= t; | ||
| 1793 | next += t; | ||
| 1794 | |||
| 1795 | if (list_empty(&ep->queue)) { | ||
| 1796 | t = scnprintf(next, size, | ||
| 1797 | "its req queue is empty\n\n"); | ||
| 1798 | size -= t; | ||
| 1799 | next += t; | ||
| 1800 | } else { | ||
| 1801 | list_for_each_entry(req, &ep->queue, queue) { | ||
| 1802 | t = scnprintf(next, size, | ||
| 1803 | "req %p actual 0x%x length " | ||
| 1804 | "0x%x buf %p\n", | ||
| 1805 | &req->req, req->req.actual, | ||
| 1806 | req->req.length, req->req.buf); | ||
| 1807 | size -= t; | ||
| 1808 | next += t; | ||
| 1809 | } | ||
| 1810 | } | ||
| 1811 | } | ||
| 1812 | } | ||
| 1813 | |||
| 1814 | spin_unlock_irqrestore(&dev->lock, flags); | ||
| 1815 | return PAGE_SIZE - size; | ||
| 1816 | } | ||
| 1817 | static DEVICE_ATTR(langwell_udc, S_IRUGO, show_langwell_udc, NULL); | ||
| 1818 | |||
| 1819 | |||
| 1820 | /* device "remote_wakeup" sysfs attribute file */ | ||
| 1821 | static ssize_t store_remote_wakeup(struct device *_dev, | ||
| 1822 | struct device_attribute *attr, const char *buf, size_t count) | ||
| 1823 | { | ||
| 1824 | struct langwell_udc *dev = the_controller; | ||
| 1825 | unsigned long flags; | ||
| 1826 | ssize_t rc = count; | ||
| 1827 | |||
| 1828 | if (count > 2) | ||
| 1829 | return -EINVAL; | ||
| 1830 | |||
| 1831 | if (count > 0 && buf[count-1] == '\n') | ||
| 1832 | ((char *) buf)[count-1] = 0; | ||
| 1833 | |||
| 1834 | if (buf[0] != '1') | ||
| 1835 | return -EINVAL; | ||
| 1836 | |||
| 1837 | /* force remote wakeup enabled in case gadget driver doesn't support */ | ||
| 1838 | spin_lock_irqsave(&dev->lock, flags); | ||
| 1839 | dev->remote_wakeup = 1; | ||
| 1840 | dev->dev_status |= (1 << USB_DEVICE_REMOTE_WAKEUP); | ||
| 1841 | spin_unlock_irqrestore(&dev->lock, flags); | ||
| 1842 | |||
| 1843 | langwell_wakeup(&dev->gadget); | ||
| 1844 | |||
| 1845 | return rc; | ||
| 1846 | } | ||
| 1847 | static DEVICE_ATTR(remote_wakeup, S_IWUSR, NULL, store_remote_wakeup); | ||
| 1848 | |||
| 1849 | |||
| 1850 | /*-------------------------------------------------------------------------*/ | ||
| 1851 | |||
| 1852 | /* | ||
| 1853 | * when a driver is successfully registered, it will receive | ||
| 1854 | * control requests including set_configuration(), which enables | ||
| 1855 | * non-control requests. then usb traffic follows until a | ||
| 1856 | * disconnect is reported. then a host may connect again, or | ||
| 1857 | * the driver might get unbound. | ||
| 1858 | */ | ||
| 1859 | |||
| 1860 | static int langwell_start(struct usb_gadget_driver *driver, | ||
| 1861 | int (*bind)(struct usb_gadget *)) | ||
| 1862 | { | ||
| 1863 | struct langwell_udc *dev = the_controller; | ||
| 1864 | unsigned long flags; | ||
| 1865 | int retval; | ||
| 1866 | |||
| 1867 | if (!dev) | ||
| 1868 | return -ENODEV; | ||
| 1869 | |||
| 1870 | dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 1871 | |||
| 1872 | if (dev->driver) | ||
| 1873 | return -EBUSY; | ||
| 1874 | |||
| 1875 | spin_lock_irqsave(&dev->lock, flags); | ||
| 1876 | |||
| 1877 | /* hook up the driver ... */ | ||
| 1878 | driver->driver.bus = NULL; | ||
| 1879 | dev->driver = driver; | ||
| 1880 | dev->gadget.dev.driver = &driver->driver; | ||
| 1881 | |||
| 1882 | spin_unlock_irqrestore(&dev->lock, flags); | ||
| 1883 | |||
| 1884 | retval = bind(&dev->gadget); | ||
| 1885 | if (retval) { | ||
| 1886 | dev_dbg(&dev->pdev->dev, "bind to driver %s --> %d\n", | ||
| 1887 | driver->driver.name, retval); | ||
| 1888 | dev->driver = NULL; | ||
| 1889 | dev->gadget.dev.driver = NULL; | ||
| 1890 | return retval; | ||
| 1891 | } | ||
| 1892 | |||
| 1893 | retval = device_create_file(&dev->pdev->dev, &dev_attr_function); | ||
| 1894 | if (retval) | ||
| 1895 | goto err_unbind; | ||
| 1896 | |||
| 1897 | dev->usb_state = USB_STATE_ATTACHED; | ||
| 1898 | dev->ep0_state = WAIT_FOR_SETUP; | ||
| 1899 | dev->ep0_dir = USB_DIR_OUT; | ||
| 1900 | |||
| 1901 | /* enable interrupt and set controller to run state */ | ||
| 1902 | if (dev->got_irq) | ||
| 1903 | langwell_udc_start(dev); | ||
| 1904 | |||
| 1905 | dev_vdbg(&dev->pdev->dev, | ||
| 1906 | "After langwell_udc_start(), print all registers:\n"); | ||
| 1907 | print_all_registers(dev); | ||
| 1908 | |||
| 1909 | dev_info(&dev->pdev->dev, "register driver: %s\n", | ||
| 1910 | driver->driver.name); | ||
| 1911 | dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 1912 | return 0; | ||
| 1913 | |||
| 1914 | err_unbind: | ||
| 1915 | driver->unbind(&dev->gadget); | ||
| 1916 | dev->gadget.dev.driver = NULL; | ||
| 1917 | dev->driver = NULL; | ||
| 1918 | |||
| 1919 | dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 1920 | return retval; | ||
| 1921 | } | ||
| 1922 | |||
| 1923 | /* unregister gadget driver */ | ||
| 1924 | static int langwell_stop(struct usb_gadget_driver *driver) | ||
| 1925 | { | ||
| 1926 | struct langwell_udc *dev = the_controller; | ||
| 1927 | unsigned long flags; | ||
| 1928 | |||
| 1929 | if (!dev) | ||
| 1930 | return -ENODEV; | ||
| 1931 | |||
| 1932 | dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 1933 | |||
| 1934 | if (unlikely(!driver || !driver->unbind)) | ||
| 1935 | return -EINVAL; | ||
| 1936 | |||
| 1937 | /* exit PHY low power suspend */ | ||
| 1938 | if (dev->pdev->device != 0x0829) | ||
| 1939 | langwell_phy_low_power(dev, 0); | ||
| 1940 | |||
| 1941 | /* unbind OTG transceiver */ | ||
| 1942 | if (dev->transceiver) | ||
| 1943 | (void)otg_set_peripheral(dev->transceiver, 0); | ||
| 1944 | |||
| 1945 | /* disable interrupt and set controller to stop state */ | ||
| 1946 | langwell_udc_stop(dev); | ||
| 1947 | |||
| 1948 | dev->usb_state = USB_STATE_ATTACHED; | ||
| 1949 | dev->ep0_state = WAIT_FOR_SETUP; | ||
| 1950 | dev->ep0_dir = USB_DIR_OUT; | ||
| 1951 | |||
| 1952 | spin_lock_irqsave(&dev->lock, flags); | ||
| 1953 | |||
| 1954 | /* stop all usb activities */ | ||
| 1955 | dev->gadget.speed = USB_SPEED_UNKNOWN; | ||
| 1956 | stop_activity(dev, driver); | ||
| 1957 | spin_unlock_irqrestore(&dev->lock, flags); | ||
| 1958 | |||
| 1959 | /* unbind gadget driver */ | ||
| 1960 | driver->unbind(&dev->gadget); | ||
| 1961 | dev->gadget.dev.driver = NULL; | ||
| 1962 | dev->driver = NULL; | ||
| 1963 | |||
| 1964 | device_remove_file(&dev->pdev->dev, &dev_attr_function); | ||
| 1965 | |||
| 1966 | dev_info(&dev->pdev->dev, "unregistered driver '%s'\n", | ||
| 1967 | driver->driver.name); | ||
| 1968 | dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 1969 | return 0; | ||
| 1970 | } | ||
| 1971 | |||
| 1972 | /*-------------------------------------------------------------------------*/ | ||
| 1973 | |||
| 1974 | /* | ||
| 1975 | * setup tripwire is used as a semaphore to ensure that the setup data | ||
| 1976 | * payload is extracted from a dQH without being corrupted | ||
| 1977 | */ | ||
| 1978 | static void setup_tripwire(struct langwell_udc *dev) | ||
| 1979 | { | ||
| 1980 | u32 usbcmd, | ||
| 1981 | endptsetupstat; | ||
| 1982 | unsigned long timeout; | ||
| 1983 | struct langwell_dqh *dqh; | ||
| 1984 | |||
| 1985 | dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 1986 | |||
| 1987 | /* ep0 OUT dQH */ | ||
| 1988 | dqh = &dev->ep_dqh[EP_DIR_OUT]; | ||
| 1989 | |||
| 1990 | /* Write-Clear endptsetupstat */ | ||
| 1991 | endptsetupstat = readl(&dev->op_regs->endptsetupstat); | ||
| 1992 | writel(endptsetupstat, &dev->op_regs->endptsetupstat); | ||
| 1993 | |||
| 1994 | /* wait until endptsetupstat is cleared */ | ||
| 1995 | timeout = jiffies + SETUPSTAT_TIMEOUT; | ||
| 1996 | while (readl(&dev->op_regs->endptsetupstat)) { | ||
| 1997 | if (time_after(jiffies, timeout)) { | ||
| 1998 | dev_err(&dev->pdev->dev, "setup_tripwire timeout\n"); | ||
| 1999 | break; | ||
| 2000 | } | ||
| 2001 | cpu_relax(); | ||
| 2002 | } | ||
| 2003 | |||
| 2004 | /* while a hazard exists when setup packet arrives */ | ||
| 2005 | do { | ||
| 2006 | /* set setup tripwire bit */ | ||
| 2007 | usbcmd = readl(&dev->op_regs->usbcmd); | ||
| 2008 | writel(usbcmd | CMD_SUTW, &dev->op_regs->usbcmd); | ||
| 2009 | |||
| 2010 | /* copy the setup packet to local buffer */ | ||
| 2011 | memcpy(&dev->local_setup_buff, &dqh->dqh_setup, 8); | ||
| 2012 | } while (!(readl(&dev->op_regs->usbcmd) & CMD_SUTW)); | ||
| 2013 | |||
| 2014 | /* Write-Clear setup tripwire bit */ | ||
| 2015 | usbcmd = readl(&dev->op_regs->usbcmd); | ||
| 2016 | writel(usbcmd & ~CMD_SUTW, &dev->op_regs->usbcmd); | ||
| 2017 | |||
| 2018 | dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 2019 | } | ||
| 2020 | |||
| 2021 | |||
| 2022 | /* protocol ep0 stall, will automatically be cleared on new transaction */ | ||
| 2023 | static void ep0_stall(struct langwell_udc *dev) | ||
| 2024 | { | ||
| 2025 | u32 endptctrl; | ||
| 2026 | |||
| 2027 | dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 2028 | |||
| 2029 | /* set TX and RX to stall */ | ||
| 2030 | endptctrl = readl(&dev->op_regs->endptctrl[0]); | ||
| 2031 | endptctrl |= EPCTRL_TXS | EPCTRL_RXS; | ||
| 2032 | writel(endptctrl, &dev->op_regs->endptctrl[0]); | ||
| 2033 | |||
| 2034 | /* update ep0 state */ | ||
| 2035 | dev->ep0_state = WAIT_FOR_SETUP; | ||
| 2036 | dev->ep0_dir = USB_DIR_OUT; | ||
| 2037 | |||
| 2038 | dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 2039 | } | ||
| 2040 | |||
| 2041 | |||
| 2042 | /* PRIME a status phase for ep0 */ | ||
| 2043 | static int prime_status_phase(struct langwell_udc *dev, int dir) | ||
| 2044 | { | ||
| 2045 | struct langwell_request *req; | ||
| 2046 | struct langwell_ep *ep; | ||
| 2047 | int status = 0; | ||
| 2048 | |||
| 2049 | dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 2050 | |||
| 2051 | if (dir == EP_DIR_IN) | ||
| 2052 | dev->ep0_dir = USB_DIR_IN; | ||
| 2053 | else | ||
| 2054 | dev->ep0_dir = USB_DIR_OUT; | ||
| 2055 | |||
| 2056 | ep = &dev->ep[0]; | ||
| 2057 | dev->ep0_state = WAIT_FOR_OUT_STATUS; | ||
| 2058 | |||
| 2059 | req = dev->status_req; | ||
| 2060 | |||
| 2061 | req->ep = ep; | ||
| 2062 | req->req.length = 0; | ||
| 2063 | req->req.status = -EINPROGRESS; | ||
| 2064 | req->req.actual = 0; | ||
| 2065 | req->req.complete = NULL; | ||
| 2066 | req->dtd_count = 0; | ||
| 2067 | |||
| 2068 | if (!req_to_dtd(req)) | ||
| 2069 | status = queue_dtd(ep, req); | ||
| 2070 | else | ||
| 2071 | return -ENOMEM; | ||
| 2072 | |||
| 2073 | if (status) | ||
| 2074 | dev_err(&dev->pdev->dev, "can't queue ep0 status request\n"); | ||
| 2075 | |||
| 2076 | list_add_tail(&req->queue, &ep->queue); | ||
| 2077 | |||
| 2078 | dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 2079 | return status; | ||
| 2080 | } | ||
| 2081 | |||
| 2082 | |||
| 2083 | /* SET_ADDRESS request routine */ | ||
| 2084 | static void set_address(struct langwell_udc *dev, u16 value, | ||
| 2085 | u16 index, u16 length) | ||
| 2086 | { | ||
| 2087 | dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 2088 | |||
| 2089 | /* save the new address to device struct */ | ||
| 2090 | dev->dev_addr = (u8) value; | ||
| 2091 | dev_vdbg(&dev->pdev->dev, "dev->dev_addr = %d\n", dev->dev_addr); | ||
| 2092 | |||
| 2093 | /* update usb state */ | ||
| 2094 | dev->usb_state = USB_STATE_ADDRESS; | ||
| 2095 | |||
| 2096 | /* STATUS phase */ | ||
| 2097 | if (prime_status_phase(dev, EP_DIR_IN)) | ||
| 2098 | ep0_stall(dev); | ||
| 2099 | |||
| 2100 | dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 2101 | } | ||
| 2102 | |||
| 2103 | |||
| 2104 | /* return endpoint by windex */ | ||
| 2105 | static struct langwell_ep *get_ep_by_windex(struct langwell_udc *dev, | ||
| 2106 | u16 wIndex) | ||
| 2107 | { | ||
| 2108 | struct langwell_ep *ep; | ||
| 2109 | dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 2110 | |||
| 2111 | if ((wIndex & USB_ENDPOINT_NUMBER_MASK) == 0) | ||
| 2112 | return &dev->ep[0]; | ||
| 2113 | |||
| 2114 | list_for_each_entry(ep, &dev->gadget.ep_list, ep.ep_list) { | ||
| 2115 | u8 bEndpointAddress; | ||
| 2116 | if (!ep->desc) | ||
| 2117 | continue; | ||
| 2118 | |||
| 2119 | bEndpointAddress = ep->desc->bEndpointAddress; | ||
| 2120 | if ((wIndex ^ bEndpointAddress) & USB_DIR_IN) | ||
| 2121 | continue; | ||
| 2122 | |||
| 2123 | if ((wIndex & USB_ENDPOINT_NUMBER_MASK) | ||
| 2124 | == (bEndpointAddress & USB_ENDPOINT_NUMBER_MASK)) | ||
| 2125 | return ep; | ||
| 2126 | } | ||
| 2127 | |||
| 2128 | dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 2129 | return NULL; | ||
| 2130 | } | ||
| 2131 | |||
| 2132 | |||
| 2133 | /* return whether endpoint is stalled, 0: not stalled; 1: stalled */ | ||
| 2134 | static int ep_is_stall(struct langwell_ep *ep) | ||
| 2135 | { | ||
| 2136 | struct langwell_udc *dev = ep->dev; | ||
| 2137 | u32 endptctrl; | ||
| 2138 | int retval; | ||
| 2139 | |||
| 2140 | dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 2141 | |||
| 2142 | endptctrl = readl(&dev->op_regs->endptctrl[ep->ep_num]); | ||
| 2143 | if (is_in(ep)) | ||
| 2144 | retval = endptctrl & EPCTRL_TXS ? 1 : 0; | ||
| 2145 | else | ||
| 2146 | retval = endptctrl & EPCTRL_RXS ? 1 : 0; | ||
| 2147 | |||
| 2148 | dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 2149 | return retval; | ||
| 2150 | } | ||
| 2151 | |||
| 2152 | |||
| 2153 | /* GET_STATUS request routine */ | ||
| 2154 | static void get_status(struct langwell_udc *dev, u8 request_type, u16 value, | ||
| 2155 | u16 index, u16 length) | ||
| 2156 | { | ||
| 2157 | struct langwell_request *req; | ||
| 2158 | struct langwell_ep *ep; | ||
| 2159 | u16 status_data = 0; /* 16 bits cpu view status data */ | ||
| 2160 | int status = 0; | ||
| 2161 | |||
| 2162 | dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 2163 | |||
| 2164 | ep = &dev->ep[0]; | ||
| 2165 | |||
| 2166 | if ((request_type & USB_RECIP_MASK) == USB_RECIP_DEVICE) { | ||
| 2167 | /* get device status */ | ||
| 2168 | status_data = dev->dev_status; | ||
| 2169 | } else if ((request_type & USB_RECIP_MASK) == USB_RECIP_INTERFACE) { | ||
| 2170 | /* get interface status */ | ||
| 2171 | status_data = 0; | ||
| 2172 | } else if ((request_type & USB_RECIP_MASK) == USB_RECIP_ENDPOINT) { | ||
| 2173 | /* get endpoint status */ | ||
| 2174 | struct langwell_ep *epn; | ||
| 2175 | epn = get_ep_by_windex(dev, index); | ||
| 2176 | /* stall if endpoint doesn't exist */ | ||
| 2177 | if (!epn) | ||
| 2178 | goto stall; | ||
| 2179 | |||
| 2180 | status_data = ep_is_stall(epn) << USB_ENDPOINT_HALT; | ||
| 2181 | } | ||
| 2182 | |||
| 2183 | dev_dbg(&dev->pdev->dev, "get status data: 0x%04x\n", status_data); | ||
| 2184 | |||
| 2185 | dev->ep0_dir = USB_DIR_IN; | ||
| 2186 | |||
| 2187 | /* borrow the per device status_req */ | ||
| 2188 | req = dev->status_req; | ||
| 2189 | |||
| 2190 | /* fill in the reqest structure */ | ||
| 2191 | *((u16 *) req->req.buf) = cpu_to_le16(status_data); | ||
| 2192 | req->ep = ep; | ||
| 2193 | req->req.length = 2; | ||
| 2194 | req->req.status = -EINPROGRESS; | ||
| 2195 | req->req.actual = 0; | ||
| 2196 | req->req.complete = NULL; | ||
| 2197 | req->dtd_count = 0; | ||
| 2198 | |||
| 2199 | /* prime the data phase */ | ||
| 2200 | if (!req_to_dtd(req)) | ||
| 2201 | status = queue_dtd(ep, req); | ||
| 2202 | else /* no mem */ | ||
| 2203 | goto stall; | ||
| 2204 | |||
| 2205 | if (status) { | ||
| 2206 | dev_err(&dev->pdev->dev, | ||
| 2207 | "response error on GET_STATUS request\n"); | ||
| 2208 | goto stall; | ||
| 2209 | } | ||
| 2210 | |||
| 2211 | list_add_tail(&req->queue, &ep->queue); | ||
| 2212 | dev->ep0_state = DATA_STATE_XMIT; | ||
| 2213 | |||
| 2214 | dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 2215 | return; | ||
| 2216 | stall: | ||
| 2217 | ep0_stall(dev); | ||
| 2218 | dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 2219 | } | ||
| 2220 | |||
| 2221 | |||
| 2222 | /* setup packet interrupt handler */ | ||
| 2223 | static void handle_setup_packet(struct langwell_udc *dev, | ||
| 2224 | struct usb_ctrlrequest *setup) | ||
| 2225 | { | ||
| 2226 | u16 wValue = le16_to_cpu(setup->wValue); | ||
| 2227 | u16 wIndex = le16_to_cpu(setup->wIndex); | ||
| 2228 | u16 wLength = le16_to_cpu(setup->wLength); | ||
| 2229 | u32 portsc1; | ||
| 2230 | |||
| 2231 | dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 2232 | |||
| 2233 | /* ep0 fifo flush */ | ||
| 2234 | nuke(&dev->ep[0], -ESHUTDOWN); | ||
| 2235 | |||
| 2236 | dev_dbg(&dev->pdev->dev, "SETUP %02x.%02x v%04x i%04x l%04x\n", | ||
| 2237 | setup->bRequestType, setup->bRequest, | ||
| 2238 | wValue, wIndex, wLength); | ||
| 2239 | |||
| 2240 | /* RNDIS gadget delegate */ | ||
| 2241 | if ((setup->bRequestType == 0x21) && (setup->bRequest == 0x00)) { | ||
| 2242 | /* USB_CDC_SEND_ENCAPSULATED_COMMAND */ | ||
| 2243 | goto delegate; | ||
| 2244 | } | ||
| 2245 | |||
| 2246 | /* USB_CDC_GET_ENCAPSULATED_RESPONSE */ | ||
| 2247 | if ((setup->bRequestType == 0xa1) && (setup->bRequest == 0x01)) { | ||
| 2248 | /* USB_CDC_GET_ENCAPSULATED_RESPONSE */ | ||
| 2249 | goto delegate; | ||
| 2250 | } | ||
| 2251 | |||
| 2252 | /* We process some stardard setup requests here */ | ||
| 2253 | switch (setup->bRequest) { | ||
| 2254 | case USB_REQ_GET_STATUS: | ||
| 2255 | dev_dbg(&dev->pdev->dev, "SETUP: USB_REQ_GET_STATUS\n"); | ||
| 2256 | /* get status, DATA and STATUS phase */ | ||
| 2257 | if ((setup->bRequestType & (USB_DIR_IN | USB_TYPE_MASK)) | ||
| 2258 | != (USB_DIR_IN | USB_TYPE_STANDARD)) | ||
| 2259 | break; | ||
| 2260 | get_status(dev, setup->bRequestType, wValue, wIndex, wLength); | ||
| 2261 | goto end; | ||
| 2262 | |||
| 2263 | case USB_REQ_SET_ADDRESS: | ||
| 2264 | dev_dbg(&dev->pdev->dev, "SETUP: USB_REQ_SET_ADDRESS\n"); | ||
| 2265 | /* STATUS phase */ | ||
| 2266 | if (setup->bRequestType != (USB_DIR_OUT | USB_TYPE_STANDARD | ||
| 2267 | | USB_RECIP_DEVICE)) | ||
| 2268 | break; | ||
| 2269 | set_address(dev, wValue, wIndex, wLength); | ||
| 2270 | goto end; | ||
| 2271 | |||
| 2272 | case USB_REQ_CLEAR_FEATURE: | ||
| 2273 | case USB_REQ_SET_FEATURE: | ||
| 2274 | /* STATUS phase */ | ||
| 2275 | { | ||
| 2276 | int rc = -EOPNOTSUPP; | ||
| 2277 | if (setup->bRequest == USB_REQ_SET_FEATURE) | ||
| 2278 | dev_dbg(&dev->pdev->dev, | ||
| 2279 | "SETUP: USB_REQ_SET_FEATURE\n"); | ||
| 2280 | else if (setup->bRequest == USB_REQ_CLEAR_FEATURE) | ||
| 2281 | dev_dbg(&dev->pdev->dev, | ||
| 2282 | "SETUP: USB_REQ_CLEAR_FEATURE\n"); | ||
| 2283 | |||
| 2284 | if ((setup->bRequestType & (USB_RECIP_MASK | USB_TYPE_MASK)) | ||
| 2285 | == (USB_RECIP_ENDPOINT | USB_TYPE_STANDARD)) { | ||
| 2286 | struct langwell_ep *epn; | ||
| 2287 | epn = get_ep_by_windex(dev, wIndex); | ||
| 2288 | /* stall if endpoint doesn't exist */ | ||
| 2289 | if (!epn) { | ||
| 2290 | ep0_stall(dev); | ||
| 2291 | goto end; | ||
| 2292 | } | ||
| 2293 | |||
| 2294 | if (wValue != 0 || wLength != 0 | ||
| 2295 | || epn->ep_num > dev->ep_max) | ||
| 2296 | break; | ||
| 2297 | |||
| 2298 | spin_unlock(&dev->lock); | ||
| 2299 | rc = langwell_ep_set_halt(&epn->ep, | ||
| 2300 | (setup->bRequest == USB_REQ_SET_FEATURE) | ||
| 2301 | ? 1 : 0); | ||
| 2302 | spin_lock(&dev->lock); | ||
| 2303 | |||
| 2304 | } else if ((setup->bRequestType & (USB_RECIP_MASK | ||
| 2305 | | USB_TYPE_MASK)) == (USB_RECIP_DEVICE | ||
| 2306 | | USB_TYPE_STANDARD)) { | ||
| 2307 | rc = 0; | ||
| 2308 | switch (wValue) { | ||
| 2309 | case USB_DEVICE_REMOTE_WAKEUP: | ||
| 2310 | if (setup->bRequest == USB_REQ_SET_FEATURE) { | ||
| 2311 | dev->remote_wakeup = 1; | ||
| 2312 | dev->dev_status |= (1 << wValue); | ||
| 2313 | } else { | ||
| 2314 | dev->remote_wakeup = 0; | ||
| 2315 | dev->dev_status &= ~(1 << wValue); | ||
| 2316 | } | ||
| 2317 | break; | ||
| 2318 | case USB_DEVICE_TEST_MODE: | ||
| 2319 | dev_dbg(&dev->pdev->dev, "SETUP: TEST MODE\n"); | ||
| 2320 | if ((wIndex & 0xff) || | ||
| 2321 | (dev->gadget.speed != USB_SPEED_HIGH)) | ||
| 2322 | ep0_stall(dev); | ||
| 2323 | |||
| 2324 | switch (wIndex >> 8) { | ||
| 2325 | case TEST_J: | ||
| 2326 | case TEST_K: | ||
| 2327 | case TEST_SE0_NAK: | ||
| 2328 | case TEST_PACKET: | ||
| 2329 | case TEST_FORCE_EN: | ||
| 2330 | if (prime_status_phase(dev, EP_DIR_IN)) | ||
| 2331 | ep0_stall(dev); | ||
| 2332 | portsc1 = readl(&dev->op_regs->portsc1); | ||
| 2333 | portsc1 |= (wIndex & 0xf00) << 8; | ||
| 2334 | writel(portsc1, &dev->op_regs->portsc1); | ||
| 2335 | goto end; | ||
| 2336 | default: | ||
| 2337 | rc = -EOPNOTSUPP; | ||
| 2338 | } | ||
| 2339 | break; | ||
| 2340 | default: | ||
| 2341 | rc = -EOPNOTSUPP; | ||
| 2342 | break; | ||
| 2343 | } | ||
| 2344 | |||
| 2345 | if (!gadget_is_otg(&dev->gadget)) | ||
| 2346 | break; | ||
| 2347 | else if (setup->bRequest == USB_DEVICE_B_HNP_ENABLE) { | ||
| 2348 | dev->gadget.b_hnp_enable = 1; | ||
| 2349 | #ifdef OTG_TRANSCEIVER | ||
| 2350 | if (!dev->lotg->otg.default_a) | ||
| 2351 | dev->lotg->hsm.b_hnp_enable = 1; | ||
| 2352 | #endif | ||
| 2353 | } else if (setup->bRequest == USB_DEVICE_A_HNP_SUPPORT) | ||
| 2354 | dev->gadget.a_hnp_support = 1; | ||
| 2355 | else if (setup->bRequest == | ||
| 2356 | USB_DEVICE_A_ALT_HNP_SUPPORT) | ||
| 2357 | dev->gadget.a_alt_hnp_support = 1; | ||
| 2358 | else | ||
| 2359 | break; | ||
| 2360 | } else | ||
| 2361 | break; | ||
| 2362 | |||
| 2363 | if (rc == 0) { | ||
| 2364 | if (prime_status_phase(dev, EP_DIR_IN)) | ||
| 2365 | ep0_stall(dev); | ||
| 2366 | } | ||
| 2367 | goto end; | ||
| 2368 | } | ||
| 2369 | |||
| 2370 | case USB_REQ_GET_DESCRIPTOR: | ||
| 2371 | dev_dbg(&dev->pdev->dev, | ||
| 2372 | "SETUP: USB_REQ_GET_DESCRIPTOR\n"); | ||
| 2373 | goto delegate; | ||
| 2374 | |||
| 2375 | case USB_REQ_SET_DESCRIPTOR: | ||
| 2376 | dev_dbg(&dev->pdev->dev, | ||
| 2377 | "SETUP: USB_REQ_SET_DESCRIPTOR unsupported\n"); | ||
| 2378 | goto delegate; | ||
| 2379 | |||
| 2380 | case USB_REQ_GET_CONFIGURATION: | ||
| 2381 | dev_dbg(&dev->pdev->dev, | ||
| 2382 | "SETUP: USB_REQ_GET_CONFIGURATION\n"); | ||
| 2383 | goto delegate; | ||
| 2384 | |||
| 2385 | case USB_REQ_SET_CONFIGURATION: | ||
| 2386 | dev_dbg(&dev->pdev->dev, | ||
| 2387 | "SETUP: USB_REQ_SET_CONFIGURATION\n"); | ||
| 2388 | goto delegate; | ||
| 2389 | |||
| 2390 | case USB_REQ_GET_INTERFACE: | ||
| 2391 | dev_dbg(&dev->pdev->dev, | ||
| 2392 | "SETUP: USB_REQ_GET_INTERFACE\n"); | ||
| 2393 | goto delegate; | ||
| 2394 | |||
| 2395 | case USB_REQ_SET_INTERFACE: | ||
| 2396 | dev_dbg(&dev->pdev->dev, | ||
| 2397 | "SETUP: USB_REQ_SET_INTERFACE\n"); | ||
| 2398 | goto delegate; | ||
| 2399 | |||
| 2400 | case USB_REQ_SYNCH_FRAME: | ||
| 2401 | dev_dbg(&dev->pdev->dev, | ||
| 2402 | "SETUP: USB_REQ_SYNCH_FRAME unsupported\n"); | ||
| 2403 | goto delegate; | ||
| 2404 | |||
| 2405 | default: | ||
| 2406 | /* delegate USB standard requests to the gadget driver */ | ||
| 2407 | goto delegate; | ||
| 2408 | delegate: | ||
| 2409 | /* USB requests handled by gadget */ | ||
| 2410 | if (wLength) { | ||
| 2411 | /* DATA phase from gadget, STATUS phase from udc */ | ||
| 2412 | dev->ep0_dir = (setup->bRequestType & USB_DIR_IN) | ||
| 2413 | ? USB_DIR_IN : USB_DIR_OUT; | ||
| 2414 | dev_vdbg(&dev->pdev->dev, | ||
| 2415 | "dev->ep0_dir = 0x%x, wLength = %d\n", | ||
| 2416 | dev->ep0_dir, wLength); | ||
| 2417 | spin_unlock(&dev->lock); | ||
| 2418 | if (dev->driver->setup(&dev->gadget, | ||
| 2419 | &dev->local_setup_buff) < 0) | ||
| 2420 | ep0_stall(dev); | ||
| 2421 | spin_lock(&dev->lock); | ||
| 2422 | dev->ep0_state = (setup->bRequestType & USB_DIR_IN) | ||
| 2423 | ? DATA_STATE_XMIT : DATA_STATE_RECV; | ||
| 2424 | } else { | ||
| 2425 | /* no DATA phase, IN STATUS phase from gadget */ | ||
| 2426 | dev->ep0_dir = USB_DIR_IN; | ||
| 2427 | dev_vdbg(&dev->pdev->dev, | ||
| 2428 | "dev->ep0_dir = 0x%x, wLength = %d\n", | ||
| 2429 | dev->ep0_dir, wLength); | ||
| 2430 | spin_unlock(&dev->lock); | ||
| 2431 | if (dev->driver->setup(&dev->gadget, | ||
| 2432 | &dev->local_setup_buff) < 0) | ||
| 2433 | ep0_stall(dev); | ||
| 2434 | spin_lock(&dev->lock); | ||
| 2435 | dev->ep0_state = WAIT_FOR_OUT_STATUS; | ||
| 2436 | } | ||
| 2437 | break; | ||
| 2438 | } | ||
| 2439 | end: | ||
| 2440 | dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 2441 | } | ||
| 2442 | |||
| 2443 | |||
| 2444 | /* transfer completion, process endpoint request and free the completed dTDs | ||
| 2445 | * for this request | ||
| 2446 | */ | ||
| 2447 | static int process_ep_req(struct langwell_udc *dev, int index, | ||
| 2448 | struct langwell_request *curr_req) | ||
| 2449 | { | ||
| 2450 | struct langwell_dtd *curr_dtd; | ||
| 2451 | struct langwell_dqh *curr_dqh; | ||
| 2452 | int td_complete, actual, remaining_length; | ||
| 2453 | int i, dir; | ||
| 2454 | u8 dtd_status = 0; | ||
| 2455 | int retval = 0; | ||
| 2456 | |||
| 2457 | curr_dqh = &dev->ep_dqh[index]; | ||
| 2458 | dir = index % 2; | ||
| 2459 | |||
| 2460 | curr_dtd = curr_req->head; | ||
| 2461 | td_complete = 0; | ||
| 2462 | actual = curr_req->req.length; | ||
| 2463 | |||
| 2464 | dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 2465 | |||
| 2466 | for (i = 0; i < curr_req->dtd_count; i++) { | ||
| 2467 | |||
| 2468 | /* command execution states by dTD */ | ||
| 2469 | dtd_status = curr_dtd->dtd_status; | ||
| 2470 | |||
| 2471 | barrier(); | ||
| 2472 | remaining_length = le16_to_cpu(curr_dtd->dtd_total); | ||
| 2473 | actual -= remaining_length; | ||
| 2474 | |||
| 2475 | if (!dtd_status) { | ||
| 2476 | /* transfers completed successfully */ | ||
| 2477 | if (!remaining_length) { | ||
| 2478 | td_complete++; | ||
| 2479 | dev_vdbg(&dev->pdev->dev, | ||
| 2480 | "dTD transmitted successfully\n"); | ||
| 2481 | } else { | ||
| 2482 | if (dir) { | ||
| 2483 | dev_vdbg(&dev->pdev->dev, | ||
| 2484 | "TX dTD remains data\n"); | ||
| 2485 | retval = -EPROTO; | ||
| 2486 | break; | ||
| 2487 | |||
| 2488 | } else { | ||
| 2489 | td_complete++; | ||
| 2490 | break; | ||
| 2491 | } | ||
| 2492 | } | ||
| 2493 | } else { | ||
| 2494 | /* transfers completed with errors */ | ||
| 2495 | if (dtd_status & DTD_STS_ACTIVE) { | ||
| 2496 | dev_dbg(&dev->pdev->dev, | ||
| 2497 | "dTD status ACTIVE dQH[%d]\n", index); | ||
| 2498 | retval = 1; | ||
| 2499 | return retval; | ||
| 2500 | } else if (dtd_status & DTD_STS_HALTED) { | ||
| 2501 | dev_err(&dev->pdev->dev, | ||
| 2502 | "dTD error %08x dQH[%d]\n", | ||
| 2503 | dtd_status, index); | ||
| 2504 | /* clear the errors and halt condition */ | ||
| 2505 | curr_dqh->dtd_status = 0; | ||
| 2506 | retval = -EPIPE; | ||
| 2507 | break; | ||
| 2508 | } else if (dtd_status & DTD_STS_DBE) { | ||
| 2509 | dev_dbg(&dev->pdev->dev, | ||
| 2510 | "data buffer (overflow) error\n"); | ||
| 2511 | retval = -EPROTO; | ||
| 2512 | break; | ||
| 2513 | } else if (dtd_status & DTD_STS_TRE) { | ||
| 2514 | dev_dbg(&dev->pdev->dev, | ||
| 2515 | "transaction(ISO) error\n"); | ||
| 2516 | retval = -EILSEQ; | ||
| 2517 | break; | ||
| 2518 | } else | ||
| 2519 | dev_err(&dev->pdev->dev, | ||
| 2520 | "unknown error (0x%x)!\n", | ||
| 2521 | dtd_status); | ||
| 2522 | } | ||
| 2523 | |||
| 2524 | if (i != curr_req->dtd_count - 1) | ||
| 2525 | curr_dtd = (struct langwell_dtd *) | ||
| 2526 | curr_dtd->next_dtd_virt; | ||
| 2527 | } | ||
| 2528 | |||
| 2529 | if (retval) | ||
| 2530 | return retval; | ||
| 2531 | |||
| 2532 | curr_req->req.actual = actual; | ||
| 2533 | |||
| 2534 | dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 2535 | return 0; | ||
| 2536 | } | ||
| 2537 | |||
| 2538 | |||
| 2539 | /* complete DATA or STATUS phase of ep0 prime status phase if needed */ | ||
| 2540 | static void ep0_req_complete(struct langwell_udc *dev, | ||
| 2541 | struct langwell_ep *ep0, struct langwell_request *req) | ||
| 2542 | { | ||
| 2543 | u32 new_addr; | ||
| 2544 | dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 2545 | |||
| 2546 | if (dev->usb_state == USB_STATE_ADDRESS) { | ||
| 2547 | /* set the new address */ | ||
| 2548 | new_addr = (u32)dev->dev_addr; | ||
| 2549 | writel(new_addr << USBADR_SHIFT, &dev->op_regs->deviceaddr); | ||
| 2550 | |||
| 2551 | new_addr = USBADR(readl(&dev->op_regs->deviceaddr)); | ||
| 2552 | dev_vdbg(&dev->pdev->dev, "new_addr = %d\n", new_addr); | ||
| 2553 | } | ||
| 2554 | |||
| 2555 | done(ep0, req, 0); | ||
| 2556 | |||
| 2557 | switch (dev->ep0_state) { | ||
| 2558 | case DATA_STATE_XMIT: | ||
| 2559 | /* receive status phase */ | ||
| 2560 | if (prime_status_phase(dev, EP_DIR_OUT)) | ||
| 2561 | ep0_stall(dev); | ||
| 2562 | break; | ||
| 2563 | case DATA_STATE_RECV: | ||
| 2564 | /* send status phase */ | ||
| 2565 | if (prime_status_phase(dev, EP_DIR_IN)) | ||
| 2566 | ep0_stall(dev); | ||
| 2567 | break; | ||
| 2568 | case WAIT_FOR_OUT_STATUS: | ||
| 2569 | dev->ep0_state = WAIT_FOR_SETUP; | ||
| 2570 | break; | ||
| 2571 | case WAIT_FOR_SETUP: | ||
| 2572 | dev_err(&dev->pdev->dev, "unexpect ep0 packets\n"); | ||
| 2573 | break; | ||
| 2574 | default: | ||
| 2575 | ep0_stall(dev); | ||
| 2576 | break; | ||
| 2577 | } | ||
| 2578 | |||
| 2579 | dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 2580 | } | ||
| 2581 | |||
| 2582 | |||
| 2583 | /* USB transfer completion interrupt */ | ||
| 2584 | static void handle_trans_complete(struct langwell_udc *dev) | ||
| 2585 | { | ||
| 2586 | u32 complete_bits; | ||
| 2587 | int i, ep_num, dir, bit_mask, status; | ||
| 2588 | struct langwell_ep *epn; | ||
| 2589 | struct langwell_request *curr_req, *temp_req; | ||
| 2590 | |||
| 2591 | dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 2592 | |||
| 2593 | complete_bits = readl(&dev->op_regs->endptcomplete); | ||
| 2594 | dev_vdbg(&dev->pdev->dev, "endptcomplete register: 0x%08x\n", | ||
| 2595 | complete_bits); | ||
| 2596 | |||
| 2597 | /* Write-Clear the bits in endptcomplete register */ | ||
| 2598 | writel(complete_bits, &dev->op_regs->endptcomplete); | ||
| 2599 | |||
| 2600 | if (!complete_bits) { | ||
| 2601 | dev_dbg(&dev->pdev->dev, "complete_bits = 0\n"); | ||
| 2602 | goto done; | ||
| 2603 | } | ||
| 2604 | |||
| 2605 | for (i = 0; i < dev->ep_max; i++) { | ||
| 2606 | ep_num = i / 2; | ||
| 2607 | dir = i % 2; | ||
| 2608 | |||
| 2609 | bit_mask = 1 << (ep_num + 16 * dir); | ||
| 2610 | |||
| 2611 | if (!(complete_bits & bit_mask)) | ||
| 2612 | continue; | ||
| 2613 | |||
| 2614 | /* ep0 */ | ||
| 2615 | if (i == 1) | ||
| 2616 | epn = &dev->ep[0]; | ||
| 2617 | else | ||
| 2618 | epn = &dev->ep[i]; | ||
| 2619 | |||
| 2620 | if (epn->name == NULL) { | ||
| 2621 | dev_warn(&dev->pdev->dev, "invalid endpoint\n"); | ||
| 2622 | continue; | ||
| 2623 | } | ||
| 2624 | |||
| 2625 | if (i < 2) | ||
| 2626 | /* ep0 in and out */ | ||
| 2627 | dev_dbg(&dev->pdev->dev, "%s-%s transfer completed\n", | ||
| 2628 | epn->name, | ||
| 2629 | is_in(epn) ? "in" : "out"); | ||
| 2630 | else | ||
| 2631 | dev_dbg(&dev->pdev->dev, "%s transfer completed\n", | ||
| 2632 | epn->name); | ||
| 2633 | |||
| 2634 | /* process the req queue until an uncomplete request */ | ||
| 2635 | list_for_each_entry_safe(curr_req, temp_req, | ||
| 2636 | &epn->queue, queue) { | ||
| 2637 | status = process_ep_req(dev, i, curr_req); | ||
| 2638 | dev_vdbg(&dev->pdev->dev, "%s req status: %d\n", | ||
| 2639 | epn->name, status); | ||
| 2640 | |||
| 2641 | if (status) | ||
| 2642 | break; | ||
| 2643 | |||
| 2644 | /* write back status to req */ | ||
| 2645 | curr_req->req.status = status; | ||
| 2646 | |||
| 2647 | /* ep0 request completion */ | ||
| 2648 | if (ep_num == 0) { | ||
| 2649 | ep0_req_complete(dev, epn, curr_req); | ||
| 2650 | break; | ||
| 2651 | } else { | ||
| 2652 | done(epn, curr_req, status); | ||
| 2653 | } | ||
| 2654 | } | ||
| 2655 | } | ||
| 2656 | done: | ||
| 2657 | dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 2658 | } | ||
| 2659 | |||
| 2660 | |||
| 2661 | /* port change detect interrupt handler */ | ||
| 2662 | static void handle_port_change(struct langwell_udc *dev) | ||
| 2663 | { | ||
| 2664 | u32 portsc1, devlc; | ||
| 2665 | u32 speed; | ||
| 2666 | |||
| 2667 | dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 2668 | |||
| 2669 | if (dev->bus_reset) | ||
| 2670 | dev->bus_reset = 0; | ||
| 2671 | |||
| 2672 | portsc1 = readl(&dev->op_regs->portsc1); | ||
| 2673 | devlc = readl(&dev->op_regs->devlc); | ||
| 2674 | dev_vdbg(&dev->pdev->dev, "portsc1 = 0x%08x, devlc = 0x%08x\n", | ||
| 2675 | portsc1, devlc); | ||
| 2676 | |||
| 2677 | /* bus reset is finished */ | ||
| 2678 | if (!(portsc1 & PORTS_PR)) { | ||
| 2679 | /* get the speed */ | ||
| 2680 | speed = LPM_PSPD(devlc); | ||
| 2681 | switch (speed) { | ||
| 2682 | case LPM_SPEED_HIGH: | ||
| 2683 | dev->gadget.speed = USB_SPEED_HIGH; | ||
| 2684 | break; | ||
| 2685 | case LPM_SPEED_FULL: | ||
| 2686 | dev->gadget.speed = USB_SPEED_FULL; | ||
| 2687 | break; | ||
| 2688 | case LPM_SPEED_LOW: | ||
| 2689 | dev->gadget.speed = USB_SPEED_LOW; | ||
| 2690 | break; | ||
| 2691 | default: | ||
| 2692 | dev->gadget.speed = USB_SPEED_UNKNOWN; | ||
| 2693 | break; | ||
| 2694 | } | ||
| 2695 | dev_vdbg(&dev->pdev->dev, | ||
| 2696 | "speed = %d, dev->gadget.speed = %d\n", | ||
| 2697 | speed, dev->gadget.speed); | ||
| 2698 | } | ||
| 2699 | |||
| 2700 | /* LPM L0 to L1 */ | ||
| 2701 | if (dev->lpm && dev->lpm_state == LPM_L0) | ||
| 2702 | if (portsc1 & PORTS_SUSP && portsc1 & PORTS_SLP) { | ||
| 2703 | dev_info(&dev->pdev->dev, "LPM L0 to L1\n"); | ||
| 2704 | dev->lpm_state = LPM_L1; | ||
| 2705 | } | ||
| 2706 | |||
| 2707 | /* LPM L1 to L0, force resume or remote wakeup finished */ | ||
| 2708 | if (dev->lpm && dev->lpm_state == LPM_L1) | ||
| 2709 | if (!(portsc1 & PORTS_SUSP)) { | ||
| 2710 | dev_info(&dev->pdev->dev, "LPM L1 to L0\n"); | ||
| 2711 | dev->lpm_state = LPM_L0; | ||
| 2712 | } | ||
| 2713 | |||
| 2714 | /* update USB state */ | ||
| 2715 | if (!dev->resume_state) | ||
| 2716 | dev->usb_state = USB_STATE_DEFAULT; | ||
| 2717 | |||
| 2718 | dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 2719 | } | ||
| 2720 | |||
| 2721 | |||
| 2722 | /* USB reset interrupt handler */ | ||
| 2723 | static void handle_usb_reset(struct langwell_udc *dev) | ||
| 2724 | { | ||
| 2725 | u32 deviceaddr, | ||
| 2726 | endptsetupstat, | ||
| 2727 | endptcomplete; | ||
| 2728 | unsigned long timeout; | ||
| 2729 | |||
| 2730 | dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 2731 | |||
| 2732 | /* Write-Clear the device address */ | ||
| 2733 | deviceaddr = readl(&dev->op_regs->deviceaddr); | ||
| 2734 | writel(deviceaddr & ~USBADR_MASK, &dev->op_regs->deviceaddr); | ||
| 2735 | |||
| 2736 | dev->dev_addr = 0; | ||
| 2737 | |||
| 2738 | /* clear usb state */ | ||
| 2739 | dev->resume_state = 0; | ||
| 2740 | |||
| 2741 | /* LPM L1 to L0, reset */ | ||
| 2742 | if (dev->lpm) | ||
| 2743 | dev->lpm_state = LPM_L0; | ||
| 2744 | |||
| 2745 | dev->ep0_dir = USB_DIR_OUT; | ||
| 2746 | dev->ep0_state = WAIT_FOR_SETUP; | ||
| 2747 | |||
| 2748 | /* remote wakeup reset to 0 when the device is reset */ | ||
| 2749 | dev->remote_wakeup = 0; | ||
| 2750 | dev->dev_status = 1 << USB_DEVICE_SELF_POWERED; | ||
| 2751 | dev->gadget.b_hnp_enable = 0; | ||
| 2752 | dev->gadget.a_hnp_support = 0; | ||
| 2753 | dev->gadget.a_alt_hnp_support = 0; | ||
| 2754 | |||
| 2755 | /* Write-Clear all the setup token semaphores */ | ||
| 2756 | endptsetupstat = readl(&dev->op_regs->endptsetupstat); | ||
| 2757 | writel(endptsetupstat, &dev->op_regs->endptsetupstat); | ||
| 2758 | |||
| 2759 | /* Write-Clear all the endpoint complete status bits */ | ||
| 2760 | endptcomplete = readl(&dev->op_regs->endptcomplete); | ||
| 2761 | writel(endptcomplete, &dev->op_regs->endptcomplete); | ||
| 2762 | |||
| 2763 | /* wait until all endptprime bits cleared */ | ||
| 2764 | timeout = jiffies + PRIME_TIMEOUT; | ||
| 2765 | while (readl(&dev->op_regs->endptprime)) { | ||
| 2766 | if (time_after(jiffies, timeout)) { | ||
| 2767 | dev_err(&dev->pdev->dev, "USB reset timeout\n"); | ||
| 2768 | break; | ||
| 2769 | } | ||
| 2770 | cpu_relax(); | ||
| 2771 | } | ||
| 2772 | |||
| 2773 | /* write 1s to endptflush register to clear any primed buffers */ | ||
| 2774 | writel((u32) ~0, &dev->op_regs->endptflush); | ||
| 2775 | |||
| 2776 | if (readl(&dev->op_regs->portsc1) & PORTS_PR) { | ||
| 2777 | dev_vdbg(&dev->pdev->dev, "USB bus reset\n"); | ||
| 2778 | /* bus is reseting */ | ||
| 2779 | dev->bus_reset = 1; | ||
| 2780 | |||
| 2781 | /* reset all the queues, stop all USB activities */ | ||
| 2782 | stop_activity(dev, dev->driver); | ||
| 2783 | dev->usb_state = USB_STATE_DEFAULT; | ||
| 2784 | } else { | ||
| 2785 | dev_vdbg(&dev->pdev->dev, "device controller reset\n"); | ||
| 2786 | /* controller reset */ | ||
| 2787 | langwell_udc_reset(dev); | ||
| 2788 | |||
| 2789 | /* reset all the queues, stop all USB activities */ | ||
| 2790 | stop_activity(dev, dev->driver); | ||
| 2791 | |||
| 2792 | /* reset ep0 dQH and endptctrl */ | ||
| 2793 | ep0_reset(dev); | ||
| 2794 | |||
| 2795 | /* enable interrupt and set controller to run state */ | ||
| 2796 | langwell_udc_start(dev); | ||
| 2797 | |||
| 2798 | dev->usb_state = USB_STATE_ATTACHED; | ||
| 2799 | } | ||
| 2800 | |||
| 2801 | #ifdef OTG_TRANSCEIVER | ||
| 2802 | /* refer to USB OTG 6.6.2.3 b_hnp_en is cleared */ | ||
| 2803 | if (!dev->lotg->otg.default_a) | ||
| 2804 | dev->lotg->hsm.b_hnp_enable = 0; | ||
| 2805 | #endif | ||
| 2806 | |||
| 2807 | dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 2808 | } | ||
| 2809 | |||
| 2810 | |||
| 2811 | /* USB bus suspend/resume interrupt */ | ||
| 2812 | static void handle_bus_suspend(struct langwell_udc *dev) | ||
| 2813 | { | ||
| 2814 | dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 2815 | |||
| 2816 | dev->resume_state = dev->usb_state; | ||
| 2817 | dev->usb_state = USB_STATE_SUSPENDED; | ||
| 2818 | |||
| 2819 | #ifdef OTG_TRANSCEIVER | ||
| 2820 | if (dev->lotg->otg.default_a) { | ||
| 2821 | if (dev->lotg->hsm.b_bus_suspend_vld == 1) { | ||
| 2822 | dev->lotg->hsm.b_bus_suspend = 1; | ||
| 2823 | /* notify transceiver the state changes */ | ||
| 2824 | if (spin_trylock(&dev->lotg->wq_lock)) { | ||
| 2825 | langwell_update_transceiver(); | ||
| 2826 | spin_unlock(&dev->lotg->wq_lock); | ||
| 2827 | } | ||
| 2828 | } | ||
| 2829 | dev->lotg->hsm.b_bus_suspend_vld++; | ||
| 2830 | } else { | ||
| 2831 | if (!dev->lotg->hsm.a_bus_suspend) { | ||
| 2832 | dev->lotg->hsm.a_bus_suspend = 1; | ||
| 2833 | /* notify transceiver the state changes */ | ||
| 2834 | if (spin_trylock(&dev->lotg->wq_lock)) { | ||
| 2835 | langwell_update_transceiver(); | ||
| 2836 | spin_unlock(&dev->lotg->wq_lock); | ||
| 2837 | } | ||
| 2838 | } | ||
| 2839 | } | ||
| 2840 | #endif | ||
| 2841 | |||
| 2842 | /* report suspend to the driver */ | ||
| 2843 | if (dev->driver) { | ||
| 2844 | if (dev->driver->suspend) { | ||
| 2845 | spin_unlock(&dev->lock); | ||
| 2846 | dev->driver->suspend(&dev->gadget); | ||
| 2847 | spin_lock(&dev->lock); | ||
| 2848 | dev_dbg(&dev->pdev->dev, "suspend %s\n", | ||
| 2849 | dev->driver->driver.name); | ||
| 2850 | } | ||
| 2851 | } | ||
| 2852 | |||
| 2853 | /* enter PHY low power suspend */ | ||
| 2854 | if (dev->pdev->device != 0x0829) | ||
| 2855 | langwell_phy_low_power(dev, 0); | ||
| 2856 | |||
| 2857 | dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 2858 | } | ||
| 2859 | |||
| 2860 | |||
| 2861 | static void handle_bus_resume(struct langwell_udc *dev) | ||
| 2862 | { | ||
| 2863 | dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 2864 | |||
| 2865 | dev->usb_state = dev->resume_state; | ||
| 2866 | dev->resume_state = 0; | ||
| 2867 | |||
| 2868 | /* exit PHY low power suspend */ | ||
| 2869 | if (dev->pdev->device != 0x0829) | ||
| 2870 | langwell_phy_low_power(dev, 0); | ||
| 2871 | |||
| 2872 | #ifdef OTG_TRANSCEIVER | ||
| 2873 | if (dev->lotg->otg.default_a == 0) | ||
| 2874 | dev->lotg->hsm.a_bus_suspend = 0; | ||
| 2875 | #endif | ||
| 2876 | |||
| 2877 | /* report resume to the driver */ | ||
| 2878 | if (dev->driver) { | ||
| 2879 | if (dev->driver->resume) { | ||
| 2880 | spin_unlock(&dev->lock); | ||
| 2881 | dev->driver->resume(&dev->gadget); | ||
| 2882 | spin_lock(&dev->lock); | ||
| 2883 | dev_dbg(&dev->pdev->dev, "resume %s\n", | ||
| 2884 | dev->driver->driver.name); | ||
| 2885 | } | ||
| 2886 | } | ||
| 2887 | |||
| 2888 | dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 2889 | } | ||
| 2890 | |||
| 2891 | |||
| 2892 | /* USB device controller interrupt handler */ | ||
| 2893 | static irqreturn_t langwell_irq(int irq, void *_dev) | ||
| 2894 | { | ||
| 2895 | struct langwell_udc *dev = _dev; | ||
| 2896 | u32 usbsts, | ||
| 2897 | usbintr, | ||
| 2898 | irq_sts, | ||
| 2899 | portsc1; | ||
| 2900 | |||
| 2901 | dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 2902 | |||
| 2903 | if (dev->stopped) { | ||
| 2904 | dev_vdbg(&dev->pdev->dev, "handle IRQ_NONE\n"); | ||
| 2905 | dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 2906 | return IRQ_NONE; | ||
| 2907 | } | ||
| 2908 | |||
| 2909 | spin_lock(&dev->lock); | ||
| 2910 | |||
| 2911 | /* USB status */ | ||
| 2912 | usbsts = readl(&dev->op_regs->usbsts); | ||
| 2913 | |||
| 2914 | /* USB interrupt enable */ | ||
| 2915 | usbintr = readl(&dev->op_regs->usbintr); | ||
| 2916 | |||
| 2917 | irq_sts = usbsts & usbintr; | ||
| 2918 | dev_vdbg(&dev->pdev->dev, | ||
| 2919 | "usbsts = 0x%08x, usbintr = 0x%08x, irq_sts = 0x%08x\n", | ||
| 2920 | usbsts, usbintr, irq_sts); | ||
| 2921 | |||
| 2922 | if (!irq_sts) { | ||
| 2923 | dev_vdbg(&dev->pdev->dev, "handle IRQ_NONE\n"); | ||
| 2924 | dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 2925 | spin_unlock(&dev->lock); | ||
| 2926 | return IRQ_NONE; | ||
| 2927 | } | ||
| 2928 | |||
| 2929 | /* Write-Clear interrupt status bits */ | ||
| 2930 | writel(irq_sts, &dev->op_regs->usbsts); | ||
| 2931 | |||
| 2932 | /* resume from suspend */ | ||
| 2933 | portsc1 = readl(&dev->op_regs->portsc1); | ||
| 2934 | if (dev->usb_state == USB_STATE_SUSPENDED) | ||
| 2935 | if (!(portsc1 & PORTS_SUSP)) | ||
| 2936 | handle_bus_resume(dev); | ||
| 2937 | |||
| 2938 | /* USB interrupt */ | ||
| 2939 | if (irq_sts & STS_UI) { | ||
| 2940 | dev_vdbg(&dev->pdev->dev, "USB interrupt\n"); | ||
| 2941 | |||
| 2942 | /* setup packet received from ep0 */ | ||
| 2943 | if (readl(&dev->op_regs->endptsetupstat) | ||
| 2944 | & EP0SETUPSTAT_MASK) { | ||
| 2945 | dev_vdbg(&dev->pdev->dev, | ||
| 2946 | "USB SETUP packet received interrupt\n"); | ||
| 2947 | /* setup tripwire semaphone */ | ||
| 2948 | setup_tripwire(dev); | ||
| 2949 | handle_setup_packet(dev, &dev->local_setup_buff); | ||
| 2950 | } | ||
| 2951 | |||
| 2952 | /* USB transfer completion */ | ||
| 2953 | if (readl(&dev->op_regs->endptcomplete)) { | ||
| 2954 | dev_vdbg(&dev->pdev->dev, | ||
| 2955 | "USB transfer completion interrupt\n"); | ||
| 2956 | handle_trans_complete(dev); | ||
| 2957 | } | ||
| 2958 | } | ||
| 2959 | |||
| 2960 | /* SOF received interrupt (for ISO transfer) */ | ||
| 2961 | if (irq_sts & STS_SRI) { | ||
| 2962 | /* FIXME */ | ||
| 2963 | /* dev_vdbg(&dev->pdev->dev, "SOF received interrupt\n"); */ | ||
| 2964 | } | ||
| 2965 | |||
| 2966 | /* port change detect interrupt */ | ||
| 2967 | if (irq_sts & STS_PCI) { | ||
| 2968 | dev_vdbg(&dev->pdev->dev, "port change detect interrupt\n"); | ||
| 2969 | handle_port_change(dev); | ||
| 2970 | } | ||
| 2971 | |||
| 2972 | /* suspend interrrupt */ | ||
| 2973 | if (irq_sts & STS_SLI) { | ||
| 2974 | dev_vdbg(&dev->pdev->dev, "suspend interrupt\n"); | ||
| 2975 | handle_bus_suspend(dev); | ||
| 2976 | } | ||
| 2977 | |||
| 2978 | /* USB reset interrupt */ | ||
| 2979 | if (irq_sts & STS_URI) { | ||
| 2980 | dev_vdbg(&dev->pdev->dev, "USB reset interrupt\n"); | ||
| 2981 | handle_usb_reset(dev); | ||
| 2982 | } | ||
| 2983 | |||
| 2984 | /* USB error or system error interrupt */ | ||
| 2985 | if (irq_sts & (STS_UEI | STS_SEI)) { | ||
| 2986 | /* FIXME */ | ||
| 2987 | dev_warn(&dev->pdev->dev, "error IRQ, irq_sts: %x\n", irq_sts); | ||
| 2988 | } | ||
| 2989 | |||
| 2990 | spin_unlock(&dev->lock); | ||
| 2991 | |||
| 2992 | dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 2993 | return IRQ_HANDLED; | ||
| 2994 | } | ||
| 2995 | |||
| 2996 | |||
| 2997 | /*-------------------------------------------------------------------------*/ | ||
| 2998 | |||
| 2999 | /* release device structure */ | ||
| 3000 | static void gadget_release(struct device *_dev) | ||
| 3001 | { | ||
| 3002 | struct langwell_udc *dev = the_controller; | ||
| 3003 | |||
| 3004 | dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 3005 | |||
| 3006 | complete(dev->done); | ||
| 3007 | |||
| 3008 | dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 3009 | kfree(dev); | ||
| 3010 | } | ||
| 3011 | |||
| 3012 | |||
| 3013 | /* enable SRAM caching if SRAM detected */ | ||
| 3014 | static void sram_init(struct langwell_udc *dev) | ||
| 3015 | { | ||
| 3016 | struct pci_dev *pdev = dev->pdev; | ||
| 3017 | |||
| 3018 | dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 3019 | |||
| 3020 | dev->sram_addr = pci_resource_start(pdev, 1); | ||
| 3021 | dev->sram_size = pci_resource_len(pdev, 1); | ||
| 3022 | dev_info(&dev->pdev->dev, "Found private SRAM at %x size:%x\n", | ||
| 3023 | dev->sram_addr, dev->sram_size); | ||
| 3024 | dev->got_sram = 1; | ||
| 3025 | |||
| 3026 | if (pci_request_region(pdev, 1, kobject_name(&pdev->dev.kobj))) { | ||
| 3027 | dev_warn(&dev->pdev->dev, "SRAM request failed\n"); | ||
| 3028 | dev->got_sram = 0; | ||
| 3029 | } else if (!dma_declare_coherent_memory(&pdev->dev, dev->sram_addr, | ||
| 3030 | dev->sram_addr, dev->sram_size, DMA_MEMORY_MAP)) { | ||
| 3031 | dev_warn(&dev->pdev->dev, "SRAM DMA declare failed\n"); | ||
| 3032 | pci_release_region(pdev, 1); | ||
| 3033 | dev->got_sram = 0; | ||
| 3034 | } | ||
| 3035 | |||
| 3036 | dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 3037 | } | ||
| 3038 | |||
| 3039 | |||
| 3040 | /* release SRAM caching */ | ||
| 3041 | static void sram_deinit(struct langwell_udc *dev) | ||
| 3042 | { | ||
| 3043 | struct pci_dev *pdev = dev->pdev; | ||
| 3044 | |||
| 3045 | dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 3046 | |||
| 3047 | dma_release_declared_memory(&pdev->dev); | ||
| 3048 | pci_release_region(pdev, 1); | ||
| 3049 | |||
| 3050 | dev->got_sram = 0; | ||
| 3051 | |||
| 3052 | dev_info(&dev->pdev->dev, "release SRAM caching\n"); | ||
| 3053 | dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 3054 | } | ||
| 3055 | |||
| 3056 | |||
| 3057 | /* tear down the binding between this driver and the pci device */ | ||
| 3058 | static void langwell_udc_remove(struct pci_dev *pdev) | ||
| 3059 | { | ||
| 3060 | struct langwell_udc *dev = the_controller; | ||
| 3061 | |||
| 3062 | DECLARE_COMPLETION(done); | ||
| 3063 | |||
| 3064 | BUG_ON(dev->driver); | ||
| 3065 | dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 3066 | |||
| 3067 | dev->done = &done; | ||
| 3068 | |||
| 3069 | #ifndef OTG_TRANSCEIVER | ||
| 3070 | /* free dTD dma_pool and dQH */ | ||
| 3071 | if (dev->dtd_pool) | ||
| 3072 | dma_pool_destroy(dev->dtd_pool); | ||
| 3073 | |||
| 3074 | if (dev->ep_dqh) | ||
| 3075 | dma_free_coherent(&pdev->dev, dev->ep_dqh_size, | ||
| 3076 | dev->ep_dqh, dev->ep_dqh_dma); | ||
| 3077 | |||
| 3078 | /* release SRAM caching */ | ||
| 3079 | if (dev->has_sram && dev->got_sram) | ||
| 3080 | sram_deinit(dev); | ||
| 3081 | #endif | ||
| 3082 | |||
| 3083 | if (dev->status_req) { | ||
| 3084 | kfree(dev->status_req->req.buf); | ||
| 3085 | kfree(dev->status_req); | ||
| 3086 | } | ||
| 3087 | |||
| 3088 | kfree(dev->ep); | ||
| 3089 | |||
| 3090 | /* disable IRQ handler */ | ||
| 3091 | if (dev->got_irq) | ||
| 3092 | free_irq(pdev->irq, dev); | ||
| 3093 | |||
| 3094 | #ifndef OTG_TRANSCEIVER | ||
| 3095 | if (dev->cap_regs) | ||
| 3096 | iounmap(dev->cap_regs); | ||
| 3097 | |||
| 3098 | if (dev->region) | ||
| 3099 | release_mem_region(pci_resource_start(pdev, 0), | ||
| 3100 | pci_resource_len(pdev, 0)); | ||
| 3101 | |||
| 3102 | if (dev->enabled) | ||
| 3103 | pci_disable_device(pdev); | ||
| 3104 | #else | ||
| 3105 | if (dev->transceiver) { | ||
| 3106 | otg_put_transceiver(dev->transceiver); | ||
| 3107 | dev->transceiver = NULL; | ||
| 3108 | dev->lotg = NULL; | ||
| 3109 | } | ||
| 3110 | #endif | ||
| 3111 | |||
| 3112 | dev->cap_regs = NULL; | ||
| 3113 | |||
| 3114 | dev_info(&dev->pdev->dev, "unbind\n"); | ||
| 3115 | dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 3116 | |||
| 3117 | device_unregister(&dev->gadget.dev); | ||
| 3118 | device_remove_file(&pdev->dev, &dev_attr_langwell_udc); | ||
| 3119 | device_remove_file(&pdev->dev, &dev_attr_remote_wakeup); | ||
| 3120 | |||
| 3121 | #ifndef OTG_TRANSCEIVER | ||
| 3122 | pci_set_drvdata(pdev, NULL); | ||
| 3123 | #endif | ||
| 3124 | |||
| 3125 | /* free dev, wait for the release() finished */ | ||
| 3126 | wait_for_completion(&done); | ||
| 3127 | |||
| 3128 | the_controller = NULL; | ||
| 3129 | } | ||
| 3130 | |||
| 3131 | |||
| 3132 | /* | ||
| 3133 | * wrap this driver around the specified device, but | ||
| 3134 | * don't respond over USB until a gadget driver binds to us. | ||
| 3135 | */ | ||
| 3136 | static int langwell_udc_probe(struct pci_dev *pdev, | ||
| 3137 | const struct pci_device_id *id) | ||
| 3138 | { | ||
| 3139 | struct langwell_udc *dev; | ||
| 3140 | #ifndef OTG_TRANSCEIVER | ||
| 3141 | unsigned long resource, len; | ||
| 3142 | #endif | ||
| 3143 | void __iomem *base = NULL; | ||
| 3144 | size_t size; | ||
| 3145 | int retval; | ||
| 3146 | |||
| 3147 | if (the_controller) { | ||
| 3148 | dev_warn(&pdev->dev, "ignoring\n"); | ||
| 3149 | return -EBUSY; | ||
| 3150 | } | ||
| 3151 | |||
| 3152 | /* alloc, and start init */ | ||
| 3153 | dev = kzalloc(sizeof *dev, GFP_KERNEL); | ||
| 3154 | if (dev == NULL) { | ||
| 3155 | retval = -ENOMEM; | ||
| 3156 | goto error; | ||
| 3157 | } | ||
| 3158 | |||
| 3159 | /* initialize device spinlock */ | ||
| 3160 | spin_lock_init(&dev->lock); | ||
| 3161 | |||
| 3162 | dev->pdev = pdev; | ||
| 3163 | dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 3164 | |||
| 3165 | #ifdef OTG_TRANSCEIVER | ||
| 3166 | /* PCI device is already enabled by otg_transceiver driver */ | ||
| 3167 | dev->enabled = 1; | ||
| 3168 | |||
| 3169 | /* mem region and register base */ | ||
| 3170 | dev->region = 1; | ||
| 3171 | dev->transceiver = otg_get_transceiver(); | ||
| 3172 | dev->lotg = otg_to_langwell(dev->transceiver); | ||
| 3173 | base = dev->lotg->regs; | ||
| 3174 | #else | ||
| 3175 | pci_set_drvdata(pdev, dev); | ||
| 3176 | |||
| 3177 | /* now all the pci goodies ... */ | ||
| 3178 | if (pci_enable_device(pdev) < 0) { | ||
| 3179 | retval = -ENODEV; | ||
| 3180 | goto error; | ||
| 3181 | } | ||
| 3182 | dev->enabled = 1; | ||
| 3183 | |||
| 3184 | /* control register: BAR 0 */ | ||
| 3185 | resource = pci_resource_start(pdev, 0); | ||
| 3186 | len = pci_resource_len(pdev, 0); | ||
| 3187 | if (!request_mem_region(resource, len, driver_name)) { | ||
| 3188 | dev_err(&dev->pdev->dev, "controller already in use\n"); | ||
| 3189 | retval = -EBUSY; | ||
| 3190 | goto error; | ||
| 3191 | } | ||
| 3192 | dev->region = 1; | ||
| 3193 | |||
| 3194 | base = ioremap_nocache(resource, len); | ||
| 3195 | #endif | ||
| 3196 | if (base == NULL) { | ||
| 3197 | dev_err(&dev->pdev->dev, "can't map memory\n"); | ||
| 3198 | retval = -EFAULT; | ||
| 3199 | goto error; | ||
| 3200 | } | ||
| 3201 | |||
| 3202 | dev->cap_regs = (struct langwell_cap_regs __iomem *) base; | ||
| 3203 | dev_vdbg(&dev->pdev->dev, "dev->cap_regs: %p\n", dev->cap_regs); | ||
| 3204 | dev->op_regs = (struct langwell_op_regs __iomem *) | ||
| 3205 | (base + OP_REG_OFFSET); | ||
| 3206 | dev_vdbg(&dev->pdev->dev, "dev->op_regs: %p\n", dev->op_regs); | ||
| 3207 | |||
| 3208 | /* irq setup after old hardware is cleaned up */ | ||
| 3209 | if (!pdev->irq) { | ||
| 3210 | dev_err(&dev->pdev->dev, "No IRQ. Check PCI setup!\n"); | ||
| 3211 | retval = -ENODEV; | ||
| 3212 | goto error; | ||
| 3213 | } | ||
| 3214 | |||
| 3215 | dev->has_sram = 1; | ||
| 3216 | dev->got_sram = 0; | ||
| 3217 | dev_vdbg(&dev->pdev->dev, "dev->has_sram: %d\n", dev->has_sram); | ||
| 3218 | |||
| 3219 | #ifndef OTG_TRANSCEIVER | ||
| 3220 | /* enable SRAM caching if detected */ | ||
| 3221 | if (dev->has_sram && !dev->got_sram) | ||
| 3222 | sram_init(dev); | ||
| 3223 | |||
| 3224 | dev_info(&dev->pdev->dev, | ||
| 3225 | "irq %d, io mem: 0x%08lx, len: 0x%08lx, pci mem 0x%p\n", | ||
| 3226 | pdev->irq, resource, len, base); | ||
| 3227 | /* enables bus-mastering for device dev */ | ||
| 3228 | pci_set_master(pdev); | ||
| 3229 | |||
| 3230 | if (request_irq(pdev->irq, langwell_irq, IRQF_SHARED, | ||
| 3231 | driver_name, dev) != 0) { | ||
| 3232 | dev_err(&dev->pdev->dev, | ||
| 3233 | "request interrupt %d failed\n", pdev->irq); | ||
| 3234 | retval = -EBUSY; | ||
| 3235 | goto error; | ||
| 3236 | } | ||
| 3237 | dev->got_irq = 1; | ||
| 3238 | #endif | ||
| 3239 | |||
| 3240 | /* set stopped bit */ | ||
| 3241 | dev->stopped = 1; | ||
| 3242 | |||
| 3243 | /* capabilities and endpoint number */ | ||
| 3244 | dev->lpm = (readl(&dev->cap_regs->hccparams) & HCC_LEN) ? 1 : 0; | ||
| 3245 | dev->dciversion = readw(&dev->cap_regs->dciversion); | ||
| 3246 | dev->devcap = (readl(&dev->cap_regs->dccparams) & DEVCAP) ? 1 : 0; | ||
| 3247 | dev_vdbg(&dev->pdev->dev, "dev->lpm: %d\n", dev->lpm); | ||
| 3248 | dev_vdbg(&dev->pdev->dev, "dev->dciversion: 0x%04x\n", | ||
| 3249 | dev->dciversion); | ||
| 3250 | dev_vdbg(&dev->pdev->dev, "dccparams: 0x%08x\n", | ||
| 3251 | readl(&dev->cap_regs->dccparams)); | ||
| 3252 | dev_vdbg(&dev->pdev->dev, "dev->devcap: %d\n", dev->devcap); | ||
| 3253 | if (!dev->devcap) { | ||
| 3254 | dev_err(&dev->pdev->dev, "can't support device mode\n"); | ||
| 3255 | retval = -ENODEV; | ||
| 3256 | goto error; | ||
| 3257 | } | ||
| 3258 | |||
| 3259 | /* a pair of endpoints (out/in) for each address */ | ||
| 3260 | dev->ep_max = DEN(readl(&dev->cap_regs->dccparams)) * 2; | ||
| 3261 | dev_vdbg(&dev->pdev->dev, "dev->ep_max: %d\n", dev->ep_max); | ||
| 3262 | |||
| 3263 | /* allocate endpoints memory */ | ||
| 3264 | dev->ep = kzalloc(sizeof(struct langwell_ep) * dev->ep_max, | ||
| 3265 | GFP_KERNEL); | ||
| 3266 | if (!dev->ep) { | ||
| 3267 | dev_err(&dev->pdev->dev, "allocate endpoints memory failed\n"); | ||
| 3268 | retval = -ENOMEM; | ||
| 3269 | goto error; | ||
| 3270 | } | ||
| 3271 | |||
| 3272 | /* allocate device dQH memory */ | ||
| 3273 | size = dev->ep_max * sizeof(struct langwell_dqh); | ||
| 3274 | dev_vdbg(&dev->pdev->dev, "orig size = %zd\n", size); | ||
| 3275 | if (size < DQH_ALIGNMENT) | ||
| 3276 | size = DQH_ALIGNMENT; | ||
| 3277 | else if ((size % DQH_ALIGNMENT) != 0) { | ||
| 3278 | size += DQH_ALIGNMENT + 1; | ||
| 3279 | size &= ~(DQH_ALIGNMENT - 1); | ||
| 3280 | } | ||
| 3281 | dev->ep_dqh = dma_alloc_coherent(&pdev->dev, size, | ||
| 3282 | &dev->ep_dqh_dma, GFP_KERNEL); | ||
| 3283 | if (!dev->ep_dqh) { | ||
| 3284 | dev_err(&dev->pdev->dev, "allocate dQH memory failed\n"); | ||
| 3285 | retval = -ENOMEM; | ||
| 3286 | goto error; | ||
| 3287 | } | ||
| 3288 | dev->ep_dqh_size = size; | ||
| 3289 | dev_vdbg(&dev->pdev->dev, "ep_dqh_size = %zd\n", dev->ep_dqh_size); | ||
| 3290 | |||
| 3291 | /* initialize ep0 status request structure */ | ||
| 3292 | dev->status_req = kzalloc(sizeof(struct langwell_request), GFP_KERNEL); | ||
| 3293 | if (!dev->status_req) { | ||
| 3294 | dev_err(&dev->pdev->dev, | ||
| 3295 | "allocate status_req memory failed\n"); | ||
| 3296 | retval = -ENOMEM; | ||
| 3297 | goto error; | ||
| 3298 | } | ||
| 3299 | INIT_LIST_HEAD(&dev->status_req->queue); | ||
| 3300 | |||
| 3301 | /* allocate a small amount of memory to get valid address */ | ||
| 3302 | dev->status_req->req.buf = kmalloc(8, GFP_KERNEL); | ||
| 3303 | dev->status_req->req.dma = virt_to_phys(dev->status_req->req.buf); | ||
| 3304 | |||
| 3305 | dev->resume_state = USB_STATE_NOTATTACHED; | ||
| 3306 | dev->usb_state = USB_STATE_POWERED; | ||
| 3307 | dev->ep0_dir = USB_DIR_OUT; | ||
| 3308 | |||
| 3309 | /* remote wakeup reset to 0 when the device is reset */ | ||
| 3310 | dev->remote_wakeup = 0; | ||
| 3311 | dev->dev_status = 1 << USB_DEVICE_SELF_POWERED; | ||
| 3312 | |||
| 3313 | #ifndef OTG_TRANSCEIVER | ||
| 3314 | /* reset device controller */ | ||
| 3315 | langwell_udc_reset(dev); | ||
| 3316 | #endif | ||
| 3317 | |||
| 3318 | /* initialize gadget structure */ | ||
| 3319 | dev->gadget.ops = &langwell_ops; /* usb_gadget_ops */ | ||
| 3320 | dev->gadget.ep0 = &dev->ep[0].ep; /* gadget ep0 */ | ||
| 3321 | INIT_LIST_HEAD(&dev->gadget.ep_list); /* ep_list */ | ||
| 3322 | dev->gadget.speed = USB_SPEED_UNKNOWN; /* speed */ | ||
| 3323 | dev->gadget.is_dualspeed = 1; /* support dual speed */ | ||
| 3324 | #ifdef OTG_TRANSCEIVER | ||
| 3325 | dev->gadget.is_otg = 1; /* support otg mode */ | ||
| 3326 | #endif | ||
| 3327 | |||
| 3328 | /* the "gadget" abstracts/virtualizes the controller */ | ||
| 3329 | dev_set_name(&dev->gadget.dev, "gadget"); | ||
| 3330 | dev->gadget.dev.parent = &pdev->dev; | ||
| 3331 | dev->gadget.dev.dma_mask = pdev->dev.dma_mask; | ||
| 3332 | dev->gadget.dev.release = gadget_release; | ||
| 3333 | dev->gadget.name = driver_name; /* gadget name */ | ||
| 3334 | |||
| 3335 | /* controller endpoints reinit */ | ||
| 3336 | eps_reinit(dev); | ||
| 3337 | |||
| 3338 | #ifndef OTG_TRANSCEIVER | ||
| 3339 | /* reset ep0 dQH and endptctrl */ | ||
| 3340 | ep0_reset(dev); | ||
| 3341 | #endif | ||
| 3342 | |||
| 3343 | /* create dTD dma_pool resource */ | ||
| 3344 | dev->dtd_pool = dma_pool_create("langwell_dtd", | ||
| 3345 | &dev->pdev->dev, | ||
| 3346 | sizeof(struct langwell_dtd), | ||
| 3347 | DTD_ALIGNMENT, | ||
| 3348 | DMA_BOUNDARY); | ||
| 3349 | |||
| 3350 | if (!dev->dtd_pool) { | ||
| 3351 | retval = -ENOMEM; | ||
| 3352 | goto error; | ||
| 3353 | } | ||
| 3354 | |||
| 3355 | /* done */ | ||
| 3356 | dev_info(&dev->pdev->dev, "%s\n", driver_desc); | ||
| 3357 | dev_info(&dev->pdev->dev, "irq %d, pci mem %p\n", pdev->irq, base); | ||
| 3358 | dev_info(&dev->pdev->dev, "Driver version: " DRIVER_VERSION "\n"); | ||
| 3359 | dev_info(&dev->pdev->dev, "Support (max) %d endpoints\n", dev->ep_max); | ||
| 3360 | dev_info(&dev->pdev->dev, "Device interface version: 0x%04x\n", | ||
| 3361 | dev->dciversion); | ||
| 3362 | dev_info(&dev->pdev->dev, "Controller mode: %s\n", | ||
| 3363 | dev->devcap ? "Device" : "Host"); | ||
| 3364 | dev_info(&dev->pdev->dev, "Support USB LPM: %s\n", | ||
| 3365 | dev->lpm ? "Yes" : "No"); | ||
| 3366 | |||
| 3367 | dev_vdbg(&dev->pdev->dev, | ||
| 3368 | "After langwell_udc_probe(), print all registers:\n"); | ||
| 3369 | print_all_registers(dev); | ||
| 3370 | |||
| 3371 | the_controller = dev; | ||
| 3372 | |||
| 3373 | retval = device_register(&dev->gadget.dev); | ||
| 3374 | if (retval) | ||
| 3375 | goto error; | ||
| 3376 | |||
| 3377 | retval = usb_add_gadget_udc(&pdev->dev, &dev->gadget); | ||
| 3378 | if (retval) | ||
| 3379 | goto error; | ||
| 3380 | |||
| 3381 | retval = device_create_file(&pdev->dev, &dev_attr_langwell_udc); | ||
| 3382 | if (retval) | ||
| 3383 | goto error; | ||
| 3384 | |||
| 3385 | retval = device_create_file(&pdev->dev, &dev_attr_remote_wakeup); | ||
| 3386 | if (retval) | ||
| 3387 | goto error_attr1; | ||
| 3388 | |||
| 3389 | dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 3390 | return 0; | ||
| 3391 | |||
| 3392 | error_attr1: | ||
| 3393 | device_remove_file(&pdev->dev, &dev_attr_langwell_udc); | ||
| 3394 | error: | ||
| 3395 | if (dev) { | ||
| 3396 | dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 3397 | langwell_udc_remove(pdev); | ||
| 3398 | } | ||
| 3399 | |||
| 3400 | return retval; | ||
| 3401 | } | ||
| 3402 | |||
| 3403 | |||
| 3404 | /* device controller suspend */ | ||
| 3405 | static int langwell_udc_suspend(struct pci_dev *pdev, pm_message_t state) | ||
| 3406 | { | ||
| 3407 | struct langwell_udc *dev = the_controller; | ||
| 3408 | |||
| 3409 | dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 3410 | |||
| 3411 | usb_del_gadget_udc(&dev->gadget); | ||
| 3412 | /* disable interrupt and set controller to stop state */ | ||
| 3413 | langwell_udc_stop(dev); | ||
| 3414 | |||
| 3415 | /* disable IRQ handler */ | ||
| 3416 | if (dev->got_irq) | ||
| 3417 | free_irq(pdev->irq, dev); | ||
| 3418 | dev->got_irq = 0; | ||
| 3419 | |||
| 3420 | /* save PCI state */ | ||
| 3421 | pci_save_state(pdev); | ||
| 3422 | |||
| 3423 | spin_lock_irq(&dev->lock); | ||
| 3424 | /* stop all usb activities */ | ||
| 3425 | stop_activity(dev, dev->driver); | ||
| 3426 | spin_unlock_irq(&dev->lock); | ||
| 3427 | |||
| 3428 | /* free dTD dma_pool and dQH */ | ||
| 3429 | if (dev->dtd_pool) | ||
| 3430 | dma_pool_destroy(dev->dtd_pool); | ||
| 3431 | |||
| 3432 | if (dev->ep_dqh) | ||
| 3433 | dma_free_coherent(&pdev->dev, dev->ep_dqh_size, | ||
| 3434 | dev->ep_dqh, dev->ep_dqh_dma); | ||
| 3435 | |||
| 3436 | /* release SRAM caching */ | ||
| 3437 | if (dev->has_sram && dev->got_sram) | ||
| 3438 | sram_deinit(dev); | ||
| 3439 | |||
| 3440 | /* set device power state */ | ||
| 3441 | pci_set_power_state(pdev, PCI_D3hot); | ||
| 3442 | |||
| 3443 | /* enter PHY low power suspend */ | ||
| 3444 | if (dev->pdev->device != 0x0829) | ||
| 3445 | langwell_phy_low_power(dev, 1); | ||
| 3446 | |||
| 3447 | dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 3448 | return 0; | ||
| 3449 | } | ||
| 3450 | |||
| 3451 | |||
| 3452 | /* device controller resume */ | ||
| 3453 | static int langwell_udc_resume(struct pci_dev *pdev) | ||
| 3454 | { | ||
| 3455 | struct langwell_udc *dev = the_controller; | ||
| 3456 | size_t size; | ||
| 3457 | |||
| 3458 | dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 3459 | |||
| 3460 | /* exit PHY low power suspend */ | ||
| 3461 | if (dev->pdev->device != 0x0829) | ||
| 3462 | langwell_phy_low_power(dev, 0); | ||
| 3463 | |||
| 3464 | /* set device D0 power state */ | ||
| 3465 | pci_set_power_state(pdev, PCI_D0); | ||
| 3466 | |||
| 3467 | /* enable SRAM caching if detected */ | ||
| 3468 | if (dev->has_sram && !dev->got_sram) | ||
| 3469 | sram_init(dev); | ||
| 3470 | |||
| 3471 | /* allocate device dQH memory */ | ||
| 3472 | size = dev->ep_max * sizeof(struct langwell_dqh); | ||
| 3473 | dev_vdbg(&dev->pdev->dev, "orig size = %zd\n", size); | ||
| 3474 | if (size < DQH_ALIGNMENT) | ||
| 3475 | size = DQH_ALIGNMENT; | ||
| 3476 | else if ((size % DQH_ALIGNMENT) != 0) { | ||
| 3477 | size += DQH_ALIGNMENT + 1; | ||
| 3478 | size &= ~(DQH_ALIGNMENT - 1); | ||
| 3479 | } | ||
| 3480 | dev->ep_dqh = dma_alloc_coherent(&pdev->dev, size, | ||
| 3481 | &dev->ep_dqh_dma, GFP_KERNEL); | ||
| 3482 | if (!dev->ep_dqh) { | ||
| 3483 | dev_err(&dev->pdev->dev, "allocate dQH memory failed\n"); | ||
| 3484 | return -ENOMEM; | ||
| 3485 | } | ||
| 3486 | dev->ep_dqh_size = size; | ||
| 3487 | dev_vdbg(&dev->pdev->dev, "ep_dqh_size = %zd\n", dev->ep_dqh_size); | ||
| 3488 | |||
| 3489 | /* create dTD dma_pool resource */ | ||
| 3490 | dev->dtd_pool = dma_pool_create("langwell_dtd", | ||
| 3491 | &dev->pdev->dev, | ||
| 3492 | sizeof(struct langwell_dtd), | ||
| 3493 | DTD_ALIGNMENT, | ||
| 3494 | DMA_BOUNDARY); | ||
| 3495 | |||
| 3496 | if (!dev->dtd_pool) | ||
| 3497 | return -ENOMEM; | ||
| 3498 | |||
| 3499 | /* restore PCI state */ | ||
| 3500 | pci_restore_state(pdev); | ||
| 3501 | |||
| 3502 | /* enable IRQ handler */ | ||
| 3503 | if (request_irq(pdev->irq, langwell_irq, IRQF_SHARED, | ||
| 3504 | driver_name, dev) != 0) { | ||
| 3505 | dev_err(&dev->pdev->dev, "request interrupt %d failed\n", | ||
| 3506 | pdev->irq); | ||
| 3507 | return -EBUSY; | ||
| 3508 | } | ||
| 3509 | dev->got_irq = 1; | ||
| 3510 | |||
| 3511 | /* reset and start controller to run state */ | ||
| 3512 | if (dev->stopped) { | ||
| 3513 | /* reset device controller */ | ||
| 3514 | langwell_udc_reset(dev); | ||
| 3515 | |||
| 3516 | /* reset ep0 dQH and endptctrl */ | ||
| 3517 | ep0_reset(dev); | ||
| 3518 | |||
| 3519 | /* start device if gadget is loaded */ | ||
| 3520 | if (dev->driver) | ||
| 3521 | langwell_udc_start(dev); | ||
| 3522 | } | ||
| 3523 | |||
| 3524 | /* reset USB status */ | ||
| 3525 | dev->usb_state = USB_STATE_ATTACHED; | ||
| 3526 | dev->ep0_state = WAIT_FOR_SETUP; | ||
| 3527 | dev->ep0_dir = USB_DIR_OUT; | ||
| 3528 | |||
| 3529 | dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 3530 | return 0; | ||
| 3531 | } | ||
| 3532 | |||
| 3533 | |||
| 3534 | /* pci driver shutdown */ | ||
| 3535 | static void langwell_udc_shutdown(struct pci_dev *pdev) | ||
| 3536 | { | ||
| 3537 | struct langwell_udc *dev = the_controller; | ||
| 3538 | u32 usbmode; | ||
| 3539 | |||
| 3540 | dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
| 3541 | |||
| 3542 | /* reset controller mode to IDLE */ | ||
| 3543 | usbmode = readl(&dev->op_regs->usbmode); | ||
| 3544 | dev_dbg(&dev->pdev->dev, "usbmode = 0x%08x\n", usbmode); | ||
| 3545 | usbmode &= (~3 | MODE_IDLE); | ||
| 3546 | writel(usbmode, &dev->op_regs->usbmode); | ||
| 3547 | |||
| 3548 | dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); | ||
| 3549 | } | ||
| 3550 | |||
| 3551 | /*-------------------------------------------------------------------------*/ | ||
| 3552 | |||
| 3553 | static const struct pci_device_id pci_ids[] = { { | ||
| 3554 | .class = ((PCI_CLASS_SERIAL_USB << 8) | 0xfe), | ||
| 3555 | .class_mask = ~0, | ||
| 3556 | .vendor = 0x8086, | ||
| 3557 | .device = 0x0811, | ||
| 3558 | .subvendor = PCI_ANY_ID, | ||
| 3559 | .subdevice = PCI_ANY_ID, | ||
| 3560 | }, { /* end: all zeroes */ } | ||
| 3561 | }; | ||
| 3562 | |||
| 3563 | MODULE_DEVICE_TABLE(pci, pci_ids); | ||
| 3564 | |||
| 3565 | |||
| 3566 | static struct pci_driver langwell_pci_driver = { | ||
| 3567 | .name = (char *) driver_name, | ||
| 3568 | .id_table = pci_ids, | ||
| 3569 | |||
| 3570 | .probe = langwell_udc_probe, | ||
| 3571 | .remove = langwell_udc_remove, | ||
| 3572 | |||
| 3573 | /* device controller suspend/resume */ | ||
| 3574 | .suspend = langwell_udc_suspend, | ||
| 3575 | .resume = langwell_udc_resume, | ||
| 3576 | |||
| 3577 | .shutdown = langwell_udc_shutdown, | ||
| 3578 | }; | ||
| 3579 | |||
| 3580 | |||
| 3581 | static int __init init(void) | ||
| 3582 | { | ||
| 3583 | #ifdef OTG_TRANSCEIVER | ||
| 3584 | return langwell_register_peripheral(&langwell_pci_driver); | ||
| 3585 | #else | ||
| 3586 | return pci_register_driver(&langwell_pci_driver); | ||
| 3587 | #endif | ||
| 3588 | } | ||
| 3589 | module_init(init); | ||
| 3590 | |||
| 3591 | |||
| 3592 | static void __exit cleanup(void) | ||
| 3593 | { | ||
| 3594 | #ifdef OTG_TRANSCEIVER | ||
| 3595 | return langwell_unregister_peripheral(&langwell_pci_driver); | ||
| 3596 | #else | ||
| 3597 | pci_unregister_driver(&langwell_pci_driver); | ||
| 3598 | #endif | ||
| 3599 | } | ||
| 3600 | module_exit(cleanup); | ||
| 3601 | |||
| 3602 | |||
| 3603 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
| 3604 | MODULE_AUTHOR("Xiaochen Shen <xiaochen.shen@intel.com>"); | ||
| 3605 | MODULE_VERSION(DRIVER_VERSION); | ||
| 3606 | MODULE_LICENSE("GPL"); | ||
| 3607 | |||
diff --git a/drivers/usb/gadget/langwell_udc.h b/drivers/usb/gadget/langwell_udc.h new file mode 100644 index 00000000000..f1d9c1bb04f --- /dev/null +++ b/drivers/usb/gadget/langwell_udc.h | |||
| @@ -0,0 +1,233 @@ | |||
| 1 | /* | ||
| 2 | * Intel Langwell USB Device Controller driver | ||
| 3 | * Copyright (C) 2008-2009, Intel Corporation. | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify it | ||
| 6 | * under the terms and conditions of the GNU General Public License, | ||
| 7 | * version 2, as published by the Free Software Foundation. | ||
| 8 | * | ||
| 9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
| 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 12 | * more details. | ||
| 13 | * | ||
| 14 | * You should have received a copy of the GNU General Public License along with | ||
| 15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
| 16 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 17 | * | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <linux/usb/langwell_udc.h> | ||
| 21 | #include <linux/usb/langwell_otg.h> | ||
| 22 | |||
| 23 | /*-------------------------------------------------------------------------*/ | ||
| 24 | |||
| 25 | /* driver data structures and utilities */ | ||
| 26 | |||
| 27 | /* | ||
| 28 | * dTD: Device Endpoint Transfer Descriptor | ||
| 29 | * describe to the device controller the location and quantity of | ||
| 30 | * data to be send/received for given transfer | ||
| 31 | */ | ||
| 32 | struct langwell_dtd { | ||
| 33 | u32 dtd_next; | ||
| 34 | /* bits 31:5, next transfer element pointer */ | ||
| 35 | #define DTD_NEXT(d) (((d)>>5)&0x7ffffff) | ||
| 36 | #define DTD_NEXT_MASK (0x7ffffff << 5) | ||
| 37 | /* terminate */ | ||
| 38 | #define DTD_TERM BIT(0) | ||
| 39 | /* bits 7:0, execution back states */ | ||
| 40 | u32 dtd_status:8; | ||
| 41 | #define DTD_STATUS(d) (((d)>>0)&0xff) | ||
| 42 | #define DTD_STS_ACTIVE BIT(7) /* active */ | ||
| 43 | #define DTD_STS_HALTED BIT(6) /* halted */ | ||
| 44 | #define DTD_STS_DBE BIT(5) /* data buffer error */ | ||
| 45 | #define DTD_STS_TRE BIT(3) /* transaction error */ | ||
| 46 | /* bits 9:8 */ | ||
| 47 | u32 dtd_res0:2; | ||
| 48 | /* bits 11:10, multipier override */ | ||
| 49 | u32 dtd_multo:2; | ||
| 50 | #define DTD_MULTO (BIT(11) | BIT(10)) | ||
| 51 | /* bits 14:12 */ | ||
| 52 | u32 dtd_res1:3; | ||
| 53 | /* bit 15, interrupt on complete */ | ||
| 54 | u32 dtd_ioc:1; | ||
| 55 | #define DTD_IOC BIT(15) | ||
| 56 | /* bits 30:16, total bytes */ | ||
| 57 | u32 dtd_total:15; | ||
| 58 | #define DTD_TOTAL(d) (((d)>>16)&0x7fff) | ||
| 59 | #define DTD_MAX_TRANSFER_LENGTH 0x4000 | ||
| 60 | /* bit 31 */ | ||
| 61 | u32 dtd_res2:1; | ||
| 62 | /* dTD buffer pointer page 0 to 4 */ | ||
| 63 | u32 dtd_buf[5]; | ||
| 64 | #define DTD_OFFSET_MASK 0xfff | ||
| 65 | /* bits 31:12, buffer pointer */ | ||
| 66 | #define DTD_BUFFER(d) (((d)>>12)&0x3ff) | ||
| 67 | /* bits 11:0, current offset */ | ||
| 68 | #define DTD_C_OFFSET(d) (((d)>>0)&0xfff) | ||
| 69 | /* bits 10:0, frame number */ | ||
| 70 | #define DTD_FRAME(d) (((d)>>0)&0x7ff) | ||
| 71 | |||
| 72 | /* driver-private parts */ | ||
| 73 | |||
| 74 | /* dtd dma address */ | ||
| 75 | dma_addr_t dtd_dma; | ||
| 76 | /* next dtd virtual address */ | ||
| 77 | struct langwell_dtd *next_dtd_virt; | ||
| 78 | }; | ||
| 79 | |||
| 80 | |||
| 81 | /* | ||
| 82 | * dQH: Device Endpoint Queue Head | ||
| 83 | * describe where all transfers are managed | ||
| 84 | * 48-byte data structure, aligned on 64-byte boundary | ||
| 85 | * | ||
| 86 | * These are associated with dTD structure | ||
| 87 | */ | ||
| 88 | struct langwell_dqh { | ||
| 89 | /* endpoint capabilities and characteristics */ | ||
| 90 | u32 dqh_res0:15; /* bits 14:0 */ | ||
| 91 | u32 dqh_ios:1; /* bit 15, interrupt on setup */ | ||
| 92 | #define DQH_IOS BIT(15) | ||
| 93 | u32 dqh_mpl:11; /* bits 26:16, maximum packet length */ | ||
| 94 | #define DQH_MPL (0x7ff << 16) | ||
| 95 | u32 dqh_res1:2; /* bits 28:27 */ | ||
| 96 | u32 dqh_zlt:1; /* bit 29, zero length termination */ | ||
| 97 | #define DQH_ZLT BIT(29) | ||
| 98 | u32 dqh_mult:2; /* bits 31:30 */ | ||
| 99 | #define DQH_MULT (BIT(30) | BIT(31)) | ||
| 100 | |||
| 101 | /* current dTD pointer */ | ||
| 102 | u32 dqh_current; /* locate the transfer in progress */ | ||
| 103 | #define DQH_C_DTD(e) \ | ||
| 104 | (((e)>>5)&0x7ffffff) /* bits 31:5, current dTD pointer */ | ||
| 105 | |||
| 106 | /* transfer overlay, hardware parts of a struct langwell_dtd */ | ||
| 107 | u32 dtd_next; | ||
| 108 | u32 dtd_status:8; /* bits 7:0, execution back states */ | ||
| 109 | u32 dtd_res0:2; /* bits 9:8 */ | ||
| 110 | u32 dtd_multo:2; /* bits 11:10, multipier override */ | ||
| 111 | u32 dtd_res1:3; /* bits 14:12 */ | ||
| 112 | u32 dtd_ioc:1; /* bit 15, interrupt on complete */ | ||
| 113 | u32 dtd_total:15; /* bits 30:16, total bytes */ | ||
| 114 | u32 dtd_res2:1; /* bit 31 */ | ||
| 115 | u32 dtd_buf[5]; /* dTD buffer pointer page 0 to 4 */ | ||
| 116 | |||
| 117 | u32 dqh_res2; | ||
| 118 | struct usb_ctrlrequest dqh_setup; /* setup packet buffer */ | ||
| 119 | } __attribute__ ((aligned(64))); | ||
| 120 | |||
| 121 | |||
| 122 | /* endpoint data structure */ | ||
| 123 | struct langwell_ep { | ||
| 124 | struct usb_ep ep; | ||
| 125 | dma_addr_t dma; | ||
| 126 | struct langwell_udc *dev; | ||
| 127 | unsigned long irqs; | ||
| 128 | struct list_head queue; | ||
| 129 | struct langwell_dqh *dqh; | ||
| 130 | const struct usb_endpoint_descriptor *desc; | ||
| 131 | char name[14]; | ||
| 132 | unsigned stopped:1, | ||
| 133 | ep_type:2, | ||
| 134 | ep_num:8; | ||
| 135 | }; | ||
| 136 | |||
| 137 | |||
| 138 | /* request data structure */ | ||
| 139 | struct langwell_request { | ||
| 140 | struct usb_request req; | ||
| 141 | struct langwell_dtd *dtd, *head, *tail; | ||
| 142 | struct langwell_ep *ep; | ||
| 143 | dma_addr_t dtd_dma; | ||
| 144 | struct list_head queue; | ||
| 145 | unsigned dtd_count; | ||
| 146 | unsigned mapped:1; | ||
| 147 | }; | ||
| 148 | |||
| 149 | |||
| 150 | /* ep0 transfer state */ | ||
| 151 | enum ep0_state { | ||
| 152 | WAIT_FOR_SETUP, | ||
| 153 | DATA_STATE_XMIT, | ||
| 154 | DATA_STATE_NEED_ZLP, | ||
| 155 | WAIT_FOR_OUT_STATUS, | ||
| 156 | DATA_STATE_RECV, | ||
| 157 | }; | ||
| 158 | |||
| 159 | |||
| 160 | /* device suspend state */ | ||
| 161 | enum lpm_state { | ||
| 162 | LPM_L0, /* on */ | ||
| 163 | LPM_L1, /* LPM L1 sleep */ | ||
| 164 | LPM_L2, /* suspend */ | ||
| 165 | LPM_L3, /* off */ | ||
| 166 | }; | ||
| 167 | |||
| 168 | |||
| 169 | /* device data structure */ | ||
| 170 | struct langwell_udc { | ||
| 171 | /* each pci device provides one gadget, several endpoints */ | ||
| 172 | struct usb_gadget gadget; | ||
| 173 | spinlock_t lock; /* device lock */ | ||
| 174 | struct langwell_ep *ep; | ||
| 175 | struct usb_gadget_driver *driver; | ||
| 176 | struct otg_transceiver *transceiver; | ||
| 177 | u8 dev_addr; | ||
| 178 | u32 usb_state; | ||
| 179 | u32 resume_state; | ||
| 180 | u32 bus_reset; | ||
| 181 | enum lpm_state lpm_state; | ||
| 182 | enum ep0_state ep0_state; | ||
| 183 | u32 ep0_dir; | ||
| 184 | u16 dciversion; | ||
| 185 | unsigned ep_max; | ||
| 186 | unsigned devcap:1, | ||
| 187 | enabled:1, | ||
| 188 | region:1, | ||
| 189 | got_irq:1, | ||
| 190 | powered:1, | ||
| 191 | remote_wakeup:1, | ||
| 192 | rate:1, | ||
| 193 | is_reset:1, | ||
| 194 | softconnected:1, | ||
| 195 | vbus_active:1, | ||
| 196 | suspended:1, | ||
| 197 | stopped:1, | ||
| 198 | lpm:1, /* LPM capability */ | ||
| 199 | has_sram:1, /* SRAM caching */ | ||
| 200 | got_sram:1; | ||
| 201 | |||
| 202 | /* pci state used to access those endpoints */ | ||
| 203 | struct pci_dev *pdev; | ||
| 204 | |||
| 205 | /* Langwell otg transceiver */ | ||
| 206 | struct langwell_otg *lotg; | ||
| 207 | |||
| 208 | /* control registers */ | ||
| 209 | struct langwell_cap_regs __iomem *cap_regs; | ||
| 210 | struct langwell_op_regs __iomem *op_regs; | ||
| 211 | |||
| 212 | struct usb_ctrlrequest local_setup_buff; | ||
| 213 | struct langwell_dqh *ep_dqh; | ||
| 214 | size_t ep_dqh_size; | ||
| 215 | dma_addr_t ep_dqh_dma; | ||
| 216 | |||
| 217 | /* ep0 status request */ | ||
| 218 | struct langwell_request *status_req; | ||
| 219 | |||
| 220 | /* dma pool */ | ||
| 221 | struct dma_pool *dtd_pool; | ||
| 222 | |||
| 223 | /* make sure release() is done */ | ||
| 224 | struct completion *done; | ||
| 225 | |||
| 226 | /* for private SRAM caching */ | ||
| 227 | unsigned int sram_addr; | ||
| 228 | unsigned int sram_size; | ||
| 229 | |||
| 230 | /* device status data for get_status request */ | ||
| 231 | u16 dev_status; | ||
| 232 | }; | ||
| 233 | |||
diff --git a/drivers/usb/gadget/mv_udc_phy.c b/drivers/usb/gadget/mv_udc_phy.c new file mode 100644 index 00000000000..d4dea97e38a --- /dev/null +++ b/drivers/usb/gadget/mv_udc_phy.c | |||
| @@ -0,0 +1,214 @@ | |||
| 1 | #include <linux/delay.h> | ||
| 2 | #include <linux/timer.h> | ||
| 3 | #include <linux/io.h> | ||
| 4 | #include <linux/errno.h> | ||
| 5 | |||
| 6 | #include <mach/cputype.h> | ||
| 7 | |||
| 8 | #ifdef CONFIG_ARCH_MMP | ||
| 9 | |||
| 10 | #define UTMI_REVISION 0x0 | ||
| 11 | #define UTMI_CTRL 0x4 | ||
| 12 | #define UTMI_PLL 0x8 | ||
| 13 | #define UTMI_TX 0xc | ||
| 14 | #define UTMI_RX 0x10 | ||
| 15 | #define UTMI_IVREF 0x14 | ||
| 16 | #define UTMI_T0 0x18 | ||
| 17 | #define UTMI_T1 0x1c | ||
| 18 | #define UTMI_T2 0x20 | ||
| 19 | #define UTMI_T3 0x24 | ||
| 20 | #define UTMI_T4 0x28 | ||
| 21 | #define UTMI_T5 0x2c | ||
| 22 | #define UTMI_RESERVE 0x30 | ||
| 23 | #define UTMI_USB_INT 0x34 | ||
| 24 | #define UTMI_DBG_CTL 0x38 | ||
| 25 | #define UTMI_OTG_ADDON 0x3c | ||
| 26 | |||
| 27 | /* For UTMICTRL Register */ | ||
| 28 | #define UTMI_CTRL_USB_CLK_EN (1 << 31) | ||
| 29 | /* pxa168 */ | ||
| 30 | #define UTMI_CTRL_SUSPEND_SET1 (1 << 30) | ||
| 31 | #define UTMI_CTRL_SUSPEND_SET2 (1 << 29) | ||
| 32 | #define UTMI_CTRL_RXBUF_PDWN (1 << 24) | ||
| 33 | #define UTMI_CTRL_TXBUF_PDWN (1 << 11) | ||
| 34 | |||
| 35 | #define UTMI_CTRL_INPKT_DELAY_SHIFT 30 | ||
| 36 | #define UTMI_CTRL_INPKT_DELAY_SOF_SHIFT 28 | ||
| 37 | #define UTMI_CTRL_PU_REF_SHIFT 20 | ||
| 38 | #define UTMI_CTRL_ARC_PULLDN_SHIFT 12 | ||
| 39 | #define UTMI_CTRL_PLL_PWR_UP_SHIFT 1 | ||
| 40 | #define UTMI_CTRL_PWR_UP_SHIFT 0 | ||
| 41 | /* For UTMI_PLL Register */ | ||
| 42 | #define UTMI_PLL_CLK_BLK_EN_SHIFT 24 | ||
| 43 | #define UTMI_PLL_FBDIV_SHIFT 4 | ||
| 44 | #define UTMI_PLL_REFDIV_SHIFT 0 | ||
| 45 | #define UTMI_PLL_FBDIV_MASK 0x00000FF0 | ||
| 46 | #define UTMI_PLL_REFDIV_MASK 0x0000000F | ||
| 47 | #define UTMI_PLL_ICP_MASK 0x00007000 | ||
| 48 | #define UTMI_PLL_KVCO_MASK 0x00031000 | ||
| 49 | #define UTMI_PLL_PLLCALI12_SHIFT 29 | ||
| 50 | #define UTMI_PLL_PLLCALI12_MASK (0x3 << 29) | ||
| 51 | #define UTMI_PLL_PLLVDD18_SHIFT 27 | ||
| 52 | #define UTMI_PLL_PLLVDD18_MASK (0x3 << 27) | ||
| 53 | #define UTMI_PLL_PLLVDD12_SHIFT 25 | ||
| 54 | #define UTMI_PLL_PLLVDD12_MASK (0x3 << 25) | ||
| 55 | #define UTMI_PLL_KVCO_SHIFT 15 | ||
| 56 | #define UTMI_PLL_ICP_SHIFT 12 | ||
| 57 | /* For UTMI_TX Register */ | ||
| 58 | #define UTMI_TX_REG_EXT_FS_RCAL_SHIFT 27 | ||
| 59 | #define UTMI_TX_REG_EXT_FS_RCAL_MASK (0xf << 27) | ||
| 60 | #define UTMI_TX_REG_EXT_FS_RCAL_EN_MASK 26 | ||
| 61 | #define UTMI_TX_REG_EXT_FS_RCAL_EN (0x1 << 26) | ||
| 62 | #define UTMI_TX_LOW_VDD_EN_SHIFT 11 | ||
| 63 | #define UTMI_TX_IMPCAL_VTH_SHIFT 14 | ||
| 64 | #define UTMI_TX_IMPCAL_VTH_MASK (0x7 << 14) | ||
| 65 | #define UTMI_TX_CK60_PHSEL_SHIFT 17 | ||
| 66 | #define UTMI_TX_CK60_PHSEL_MASK (0xf << 17) | ||
| 67 | #define UTMI_TX_TXVDD12_SHIFT 22 | ||
| 68 | #define UTMI_TX_TXVDD12_MASK (0x3 << 22) | ||
| 69 | #define UTMI_TX_AMP_SHIFT 0 | ||
| 70 | #define UTMI_TX_AMP_MASK (0x7 << 0) | ||
| 71 | /* For UTMI_RX Register */ | ||
| 72 | #define UTMI_RX_SQ_THRESH_SHIFT 4 | ||
| 73 | #define UTMI_RX_SQ_THRESH_MASK (0xf << 4) | ||
| 74 | #define UTMI_REG_SQ_LENGTH_SHIFT 15 | ||
| 75 | #define UTMI_REG_SQ_LENGTH_MASK (0x3 << 15) | ||
| 76 | |||
| 77 | #define REG_RCAL_START 0x00001000 | ||
| 78 | #define VCOCAL_START 0x00200000 | ||
| 79 | #define KVCO_EXT 0x00400000 | ||
| 80 | #define PLL_READY 0x00800000 | ||
| 81 | #define CLK_BLK_EN 0x01000000 | ||
| 82 | #endif | ||
| 83 | |||
| 84 | static unsigned int u2o_read(unsigned int base, unsigned int offset) | ||
| 85 | { | ||
| 86 | return readl(base + offset); | ||
| 87 | } | ||
| 88 | |||
| 89 | static void u2o_set(unsigned int base, unsigned int offset, unsigned int value) | ||
| 90 | { | ||
| 91 | unsigned int reg; | ||
| 92 | |||
| 93 | reg = readl(base + offset); | ||
| 94 | reg |= value; | ||
| 95 | writel(reg, base + offset); | ||
| 96 | readl(base + offset); | ||
| 97 | } | ||
| 98 | |||
| 99 | static void u2o_clear(unsigned int base, unsigned int offset, | ||
| 100 | unsigned int value) | ||
| 101 | { | ||
| 102 | unsigned int reg; | ||
| 103 | |||
| 104 | reg = readl(base + offset); | ||
| 105 | reg &= ~value; | ||
| 106 | writel(reg, base + offset); | ||
| 107 | readl(base + offset); | ||
| 108 | } | ||
| 109 | |||
| 110 | static void u2o_write(unsigned int base, unsigned int offset, | ||
| 111 | unsigned int value) | ||
| 112 | { | ||
| 113 | writel(value, base + offset); | ||
| 114 | readl(base + offset); | ||
| 115 | } | ||
| 116 | |||
| 117 | #ifdef CONFIG_ARCH_MMP | ||
| 118 | int mv_udc_phy_init(unsigned int base) | ||
| 119 | { | ||
| 120 | unsigned long timeout; | ||
| 121 | |||
| 122 | /* Initialize the USB PHY power */ | ||
| 123 | if (cpu_is_pxa910()) { | ||
| 124 | u2o_set(base, UTMI_CTRL, (1 << UTMI_CTRL_INPKT_DELAY_SOF_SHIFT) | ||
| 125 | | (1 << UTMI_CTRL_PU_REF_SHIFT)); | ||
| 126 | } | ||
| 127 | |||
| 128 | u2o_set(base, UTMI_CTRL, 1 << UTMI_CTRL_PLL_PWR_UP_SHIFT); | ||
| 129 | u2o_set(base, UTMI_CTRL, 1 << UTMI_CTRL_PWR_UP_SHIFT); | ||
| 130 | |||
| 131 | /* UTMI_PLL settings */ | ||
| 132 | u2o_clear(base, UTMI_PLL, UTMI_PLL_PLLVDD18_MASK | ||
| 133 | | UTMI_PLL_PLLVDD12_MASK | UTMI_PLL_PLLCALI12_MASK | ||
| 134 | | UTMI_PLL_FBDIV_MASK | UTMI_PLL_REFDIV_MASK | ||
| 135 | | UTMI_PLL_ICP_MASK | UTMI_PLL_KVCO_MASK); | ||
| 136 | |||
| 137 | u2o_set(base, UTMI_PLL, (0xee << UTMI_PLL_FBDIV_SHIFT) | ||
| 138 | | (0xb << UTMI_PLL_REFDIV_SHIFT) | ||
| 139 | | (3 << UTMI_PLL_PLLVDD18_SHIFT) | ||
| 140 | | (3 << UTMI_PLL_PLLVDD12_SHIFT) | ||
| 141 | | (3 << UTMI_PLL_PLLCALI12_SHIFT) | ||
| 142 | | (1 << UTMI_PLL_ICP_SHIFT) | (3 << UTMI_PLL_KVCO_SHIFT)); | ||
| 143 | |||
| 144 | /* UTMI_TX */ | ||
| 145 | u2o_clear(base, UTMI_TX, UTMI_TX_REG_EXT_FS_RCAL_EN_MASK | ||
| 146 | | UTMI_TX_TXVDD12_MASK | ||
| 147 | | UTMI_TX_CK60_PHSEL_MASK | UTMI_TX_IMPCAL_VTH_MASK | ||
| 148 | | UTMI_TX_REG_EXT_FS_RCAL_MASK | UTMI_TX_AMP_MASK); | ||
| 149 | u2o_set(base, UTMI_TX, (3 << UTMI_TX_TXVDD12_SHIFT) | ||
| 150 | | (4 << UTMI_TX_CK60_PHSEL_SHIFT) | ||
| 151 | | (4 << UTMI_TX_IMPCAL_VTH_SHIFT) | ||
| 152 | | (8 << UTMI_TX_REG_EXT_FS_RCAL_SHIFT) | ||
| 153 | | (3 << UTMI_TX_AMP_SHIFT)); | ||
| 154 | |||
| 155 | /* UTMI_RX */ | ||
| 156 | u2o_clear(base, UTMI_RX, UTMI_RX_SQ_THRESH_MASK | ||
| 157 | | UTMI_REG_SQ_LENGTH_MASK); | ||
| 158 | if (cpu_is_pxa168()) | ||
| 159 | u2o_set(base, UTMI_RX, (7 << UTMI_RX_SQ_THRESH_SHIFT) | ||
| 160 | | (2 << UTMI_REG_SQ_LENGTH_SHIFT)); | ||
| 161 | else | ||
| 162 | u2o_set(base, UTMI_RX, (0x7 << UTMI_RX_SQ_THRESH_SHIFT) | ||
| 163 | | (2 << UTMI_REG_SQ_LENGTH_SHIFT)); | ||
| 164 | |||
| 165 | /* UTMI_IVREF */ | ||
| 166 | if (cpu_is_pxa168()) | ||
| 167 | /* | ||
| 168 | * fixing Microsoft Altair board interface with NEC hub issue - | ||
| 169 | * Set UTMI_IVREF from 0x4a3 to 0x4bf | ||
| 170 | */ | ||
| 171 | u2o_write(base, UTMI_IVREF, 0x4bf); | ||
| 172 | |||
| 173 | /* calibrate */ | ||
| 174 | timeout = jiffies + 100; | ||
| 175 | while ((u2o_read(base, UTMI_PLL) & PLL_READY) == 0) { | ||
| 176 | if (time_after(jiffies, timeout)) | ||
| 177 | return -ETIME; | ||
| 178 | cpu_relax(); | ||
| 179 | } | ||
| 180 | |||
| 181 | /* toggle VCOCAL_START bit of UTMI_PLL */ | ||
| 182 | udelay(200); | ||
| 183 | u2o_set(base, UTMI_PLL, VCOCAL_START); | ||
| 184 | udelay(40); | ||
| 185 | u2o_clear(base, UTMI_PLL, VCOCAL_START); | ||
| 186 | |||
| 187 | /* toggle REG_RCAL_START bit of UTMI_TX */ | ||
| 188 | udelay(200); | ||
| 189 | u2o_set(base, UTMI_TX, REG_RCAL_START); | ||
| 190 | udelay(40); | ||
| 191 | u2o_clear(base, UTMI_TX, REG_RCAL_START); | ||
| 192 | udelay(200); | ||
| 193 | |||
| 194 | /* make sure phy is ready */ | ||
| 195 | timeout = jiffies + 100; | ||
| 196 | while ((u2o_read(base, UTMI_PLL) & PLL_READY) == 0) { | ||
| 197 | if (time_after(jiffies, timeout)) | ||
| 198 | return -ETIME; | ||
| 199 | cpu_relax(); | ||
| 200 | } | ||
| 201 | |||
| 202 | if (cpu_is_pxa168()) { | ||
| 203 | u2o_set(base, UTMI_RESERVE, 1 << 5); | ||
| 204 | /* Turn on UTMI PHY OTG extension */ | ||
| 205 | u2o_write(base, UTMI_OTG_ADDON, 1); | ||
| 206 | } | ||
| 207 | return 0; | ||
| 208 | } | ||
| 209 | #else | ||
| 210 | int mv_udc_phy_init(unsigned int base) | ||
| 211 | { | ||
| 212 | return 0; | ||
| 213 | } | ||
| 214 | #endif | ||
diff --git a/drivers/usb/gadget/u_audio.c b/drivers/usb/gadget/u_audio.c new file mode 100644 index 00000000000..59ffe1ecf1c --- /dev/null +++ b/drivers/usb/gadget/u_audio.c | |||
| @@ -0,0 +1,327 @@ | |||
| 1 | /* | ||
| 2 | * u_audio.c -- ALSA audio utilities for Gadget stack | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008 Bryan Wu <cooloney@kernel.org> | ||
| 5 | * Copyright (C) 2008 Analog Devices, Inc | ||
| 6 | * | ||
| 7 | * Enter bugs at http://blackfin.uclinux.org/ | ||
| 8 | * | ||
| 9 | * Licensed under the GPL-2 or later. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/kernel.h> | ||
| 13 | #include <linux/slab.h> | ||
| 14 | #include <linux/device.h> | ||
| 15 | #include <linux/delay.h> | ||
| 16 | #include <linux/ctype.h> | ||
| 17 | #include <linux/random.h> | ||
| 18 | #include <linux/syscalls.h> | ||
| 19 | |||
| 20 | #include "u_audio.h" | ||
| 21 | |||
| 22 | /* | ||
| 23 | * This component encapsulates the ALSA devices for USB audio gadget | ||
| 24 | */ | ||
| 25 | |||
| 26 | #define FILE_PCM_PLAYBACK "/dev/snd/pcmC0D0p" | ||
| 27 | #define FILE_PCM_CAPTURE "/dev/snd/pcmC0D0c" | ||
| 28 | #define FILE_CONTROL "/dev/snd/controlC0" | ||
| 29 | |||
| 30 | static char *fn_play = FILE_PCM_PLAYBACK; | ||
| 31 | module_param(fn_play, charp, S_IRUGO); | ||
| 32 | MODULE_PARM_DESC(fn_play, "Playback PCM device file name"); | ||
| 33 | |||
| 34 | static char *fn_cap = FILE_PCM_CAPTURE; | ||
| 35 | module_param(fn_cap, charp, S_IRUGO); | ||
| 36 | MODULE_PARM_DESC(fn_cap, "Capture PCM device file name"); | ||
| 37 | |||
| 38 | static char *fn_cntl = FILE_CONTROL; | ||
| 39 | module_param(fn_cntl, charp, S_IRUGO); | ||
| 40 | MODULE_PARM_DESC(fn_cntl, "Control device file name"); | ||
| 41 | |||
| 42 | /*-------------------------------------------------------------------------*/ | ||
| 43 | |||
| 44 | /** | ||
| 45 | * Some ALSA internal helper functions | ||
| 46 | */ | ||
| 47 | static int snd_interval_refine_set(struct snd_interval *i, unsigned int val) | ||
| 48 | { | ||
| 49 | struct snd_interval t; | ||
| 50 | t.empty = 0; | ||
| 51 | t.min = t.max = val; | ||
| 52 | t.openmin = t.openmax = 0; | ||
| 53 | t.integer = 1; | ||
| 54 | return snd_interval_refine(i, &t); | ||
| 55 | } | ||
| 56 | |||
| 57 | static int _snd_pcm_hw_param_set(struct snd_pcm_hw_params *params, | ||
| 58 | snd_pcm_hw_param_t var, unsigned int val, | ||
| 59 | int dir) | ||
| 60 | { | ||
| 61 | int changed; | ||
| 62 | if (hw_is_mask(var)) { | ||
| 63 | struct snd_mask *m = hw_param_mask(params, var); | ||
| 64 | if (val == 0 && dir < 0) { | ||
| 65 | changed = -EINVAL; | ||
| 66 | snd_mask_none(m); | ||
| 67 | } else { | ||
| 68 | if (dir > 0) | ||
| 69 | val++; | ||
| 70 | else if (dir < 0) | ||
| 71 | val--; | ||
| 72 | changed = snd_mask_refine_set( | ||
| 73 | hw_param_mask(params, var), val); | ||
| 74 | } | ||
| 75 | } else if (hw_is_interval(var)) { | ||
| 76 | struct snd_interval *i = hw_param_interval(params, var); | ||
| 77 | if (val == 0 && dir < 0) { | ||
| 78 | changed = -EINVAL; | ||
| 79 | snd_interval_none(i); | ||
| 80 | } else if (dir == 0) | ||
| 81 | changed = snd_interval_refine_set(i, val); | ||
| 82 | else { | ||
| 83 | struct snd_interval t; | ||
| 84 | t.openmin = 1; | ||
| 85 | t.openmax = 1; | ||
| 86 | t.empty = 0; | ||
| 87 | t.integer = 0; | ||
| 88 | if (dir < 0) { | ||
| 89 | t.min = val - 1; | ||
| 90 | t.max = val; | ||
| 91 | } else { | ||
| 92 | t.min = val; | ||
| 93 | t.max = val+1; | ||
| 94 | } | ||
| 95 | changed = snd_interval_refine(i, &t); | ||
| 96 | } | ||
| 97 | } else | ||
| 98 | return -EINVAL; | ||
| 99 | if (changed) { | ||
| 100 | params->cmask |= 1 << var; | ||
| 101 | params->rmask |= 1 << var; | ||
| 102 | } | ||
| 103 | return changed; | ||
| 104 | } | ||
| 105 | /*-------------------------------------------------------------------------*/ | ||
| 106 | |||
| 107 | /** | ||
| 108 | * Set default hardware params | ||
| 109 | */ | ||
| 110 | static int playback_default_hw_params(struct gaudio_snd_dev *snd) | ||
| 111 | { | ||
| 112 | struct snd_pcm_substream *substream = snd->substream; | ||
| 113 | struct snd_pcm_hw_params *params; | ||
| 114 | snd_pcm_sframes_t result; | ||
| 115 | |||
| 116 | /* | ||
| 117 | * SNDRV_PCM_ACCESS_RW_INTERLEAVED, | ||
| 118 | * SNDRV_PCM_FORMAT_S16_LE | ||
| 119 | * CHANNELS: 2 | ||
| 120 | * RATE: 48000 | ||
| 121 | */ | ||
| 122 | snd->access = SNDRV_PCM_ACCESS_RW_INTERLEAVED; | ||
| 123 | snd->format = SNDRV_PCM_FORMAT_S16_LE; | ||
| 124 | snd->channels = 2; | ||
| 125 | snd->rate = 48000; | ||
| 126 | |||
| 127 | params = kzalloc(sizeof(*params), GFP_KERNEL); | ||
| 128 | if (!params) | ||
| 129 | return -ENOMEM; | ||
| 130 | |||
| 131 | _snd_pcm_hw_params_any(params); | ||
| 132 | _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_ACCESS, | ||
| 133 | snd->access, 0); | ||
| 134 | _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_FORMAT, | ||
| 135 | snd->format, 0); | ||
| 136 | _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_CHANNELS, | ||
| 137 | snd->channels, 0); | ||
| 138 | _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_RATE, | ||
| 139 | snd->rate, 0); | ||
| 140 | |||
| 141 | snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); | ||
| 142 | snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_HW_PARAMS, params); | ||
| 143 | |||
| 144 | result = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_PREPARE, NULL); | ||
| 145 | if (result < 0) { | ||
| 146 | ERROR(snd->card, | ||
| 147 | "Preparing sound card failed: %d\n", (int)result); | ||
| 148 | kfree(params); | ||
| 149 | return result; | ||
| 150 | } | ||
| 151 | |||
| 152 | /* Store the hardware parameters */ | ||
| 153 | snd->access = params_access(params); | ||
| 154 | snd->format = params_format(params); | ||
| 155 | snd->channels = params_channels(params); | ||
| 156 | snd->rate = params_rate(params); | ||
| 157 | |||
| 158 | kfree(params); | ||
| 159 | |||
| 160 | INFO(snd->card, | ||
| 161 | "Hardware params: access %x, format %x, channels %d, rate %d\n", | ||
| 162 | snd->access, snd->format, snd->channels, snd->rate); | ||
| 163 | |||
| 164 | return 0; | ||
| 165 | } | ||
| 166 | |||
| 167 | /** | ||
| 168 | * Playback audio buffer data by ALSA PCM device | ||
| 169 | */ | ||
| 170 | static size_t u_audio_playback(struct gaudio *card, void *buf, size_t count) | ||
| 171 | { | ||
| 172 | struct gaudio_snd_dev *snd = &card->playback; | ||
| 173 | struct snd_pcm_substream *substream = snd->substream; | ||
| 174 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
| 175 | mm_segment_t old_fs; | ||
| 176 | ssize_t result; | ||
| 177 | snd_pcm_sframes_t frames; | ||
| 178 | |||
| 179 | try_again: | ||
| 180 | if (runtime->status->state == SNDRV_PCM_STATE_XRUN || | ||
| 181 | runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { | ||
| 182 | result = snd_pcm_kernel_ioctl(substream, | ||
| 183 | SNDRV_PCM_IOCTL_PREPARE, NULL); | ||
| 184 | if (result < 0) { | ||
| 185 | ERROR(card, "Preparing sound card failed: %d\n", | ||
| 186 | (int)result); | ||
| 187 | return result; | ||
| 188 | } | ||
| 189 | } | ||
| 190 | |||
| 191 | frames = bytes_to_frames(runtime, count); | ||
| 192 | old_fs = get_fs(); | ||
| 193 | set_fs(KERNEL_DS); | ||
| 194 | result = snd_pcm_lib_write(snd->substream, buf, frames); | ||
| 195 | if (result != frames) { | ||
| 196 | ERROR(card, "Playback error: %d\n", (int)result); | ||
| 197 | set_fs(old_fs); | ||
| 198 | goto try_again; | ||
| 199 | } | ||
| 200 | set_fs(old_fs); | ||
| 201 | |||
| 202 | return 0; | ||
| 203 | } | ||
| 204 | |||
| 205 | static int u_audio_get_playback_channels(struct gaudio *card) | ||
| 206 | { | ||
| 207 | return card->playback.channels; | ||
| 208 | } | ||
| 209 | |||
| 210 | static int u_audio_get_playback_rate(struct gaudio *card) | ||
| 211 | { | ||
| 212 | return card->playback.rate; | ||
| 213 | } | ||
| 214 | |||
| 215 | /** | ||
| 216 | * Open ALSA PCM and control device files | ||
| 217 | * Initial the PCM or control device | ||
| 218 | */ | ||
| 219 | static int gaudio_open_snd_dev(struct gaudio *card) | ||
| 220 | { | ||
| 221 | struct snd_pcm_file *pcm_file; | ||
| 222 | struct gaudio_snd_dev *snd; | ||
| 223 | |||
| 224 | if (!card) | ||
| 225 | return -ENODEV; | ||
| 226 | |||
| 227 | /* Open control device */ | ||
| 228 | snd = &card->control; | ||
| 229 | snd->filp = filp_open(fn_cntl, O_RDWR, 0); | ||
| 230 | if (IS_ERR(snd->filp)) { | ||
| 231 | int ret = PTR_ERR(snd->filp); | ||
| 232 | ERROR(card, "unable to open sound control device file: %s\n", | ||
| 233 | fn_cntl); | ||
| 234 | snd->filp = NULL; | ||
| 235 | return ret; | ||
| 236 | } | ||
| 237 | snd->card = card; | ||
| 238 | |||
| 239 | /* Open PCM playback device and setup substream */ | ||
| 240 | snd = &card->playback; | ||
| 241 | snd->filp = filp_open(fn_play, O_WRONLY, 0); | ||
| 242 | if (IS_ERR(snd->filp)) { | ||
| 243 | ERROR(card, "No such PCM playback device: %s\n", fn_play); | ||
| 244 | snd->filp = NULL; | ||
| 245 | } | ||
| 246 | pcm_file = snd->filp->private_data; | ||
| 247 | snd->substream = pcm_file->substream; | ||
| 248 | snd->card = card; | ||
| 249 | playback_default_hw_params(snd); | ||
| 250 | |||
| 251 | /* Open PCM capture device and setup substream */ | ||
| 252 | snd = &card->capture; | ||
| 253 | snd->filp = filp_open(fn_cap, O_RDONLY, 0); | ||
| 254 | if (IS_ERR(snd->filp)) { | ||
| 255 | ERROR(card, "No such PCM capture device: %s\n", fn_cap); | ||
| 256 | snd->substream = NULL; | ||
| 257 | snd->card = NULL; | ||
| 258 | snd->filp = NULL; | ||
| 259 | } else { | ||
| 260 | pcm_file = snd->filp->private_data; | ||
| 261 | snd->substream = pcm_file->substream; | ||
| 262 | snd->card = card; | ||
| 263 | } | ||
| 264 | |||
| 265 | return 0; | ||
| 266 | } | ||
| 267 | |||
| 268 | /** | ||
| 269 | * Close ALSA PCM and control device files | ||
| 270 | */ | ||
| 271 | static int gaudio_close_snd_dev(struct gaudio *gau) | ||
| 272 | { | ||
| 273 | struct gaudio_snd_dev *snd; | ||
| 274 | |||
| 275 | /* Close control device */ | ||
| 276 | snd = &gau->control; | ||
| 277 | if (snd->filp) | ||
| 278 | filp_close(snd->filp, current->files); | ||
| 279 | |||
| 280 | /* Close PCM playback device and setup substream */ | ||
| 281 | snd = &gau->playback; | ||
| 282 | if (snd->filp) | ||
| 283 | filp_close(snd->filp, current->files); | ||
| 284 | |||
| 285 | /* Close PCM capture device and setup substream */ | ||
| 286 | snd = &gau->capture; | ||
| 287 | if (snd->filp) | ||
| 288 | filp_close(snd->filp, current->files); | ||
| 289 | |||
| 290 | return 0; | ||
| 291 | } | ||
| 292 | |||
| 293 | static struct gaudio *the_card; | ||
| 294 | /** | ||
| 295 | * gaudio_setup - setup ALSA interface and preparing for USB transfer | ||
| 296 | * | ||
| 297 | * This sets up PCM, mixer or MIDI ALSA devices fore USB gadget using. | ||
| 298 | * | ||
| 299 | * Returns negative errno, or zero on success | ||
| 300 | */ | ||
| 301 | int __init gaudio_setup(struct gaudio *card) | ||
| 302 | { | ||
| 303 | int ret; | ||
| 304 | |||
| 305 | ret = gaudio_open_snd_dev(card); | ||
| 306 | if (ret) | ||
| 307 | ERROR(card, "we need at least one control device\n"); | ||
| 308 | else if (!the_card) | ||
| 309 | the_card = card; | ||
| 310 | |||
| 311 | return ret; | ||
| 312 | |||
| 313 | } | ||
| 314 | |||
| 315 | /** | ||
| 316 | * gaudio_cleanup - remove ALSA device interface | ||
| 317 | * | ||
| 318 | * This is called to free all resources allocated by @gaudio_setup(). | ||
| 319 | */ | ||
| 320 | void gaudio_cleanup(void) | ||
| 321 | { | ||
| 322 | if (the_card) { | ||
| 323 | gaudio_close_snd_dev(the_card); | ||
| 324 | the_card = NULL; | ||
| 325 | } | ||
| 326 | } | ||
| 327 | |||
diff --git a/drivers/usb/gadget/u_audio.h b/drivers/usb/gadget/u_audio.h new file mode 100644 index 00000000000..08ffce3298e --- /dev/null +++ b/drivers/usb/gadget/u_audio.h | |||
| @@ -0,0 +1,56 @@ | |||
| 1 | /* | ||
| 2 | * u_audio.h -- interface to USB gadget "ALSA AUDIO" utilities | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008 Bryan Wu <cooloney@kernel.org> | ||
| 5 | * Copyright (C) 2008 Analog Devices, Inc | ||
| 6 | * | ||
| 7 | * Enter bugs at http://blackfin.uclinux.org/ | ||
| 8 | * | ||
| 9 | * Licensed under the GPL-2 or later. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #ifndef __U_AUDIO_H | ||
| 13 | #define __U_AUDIO_H | ||
| 14 | |||
| 15 | #include <linux/device.h> | ||
| 16 | #include <linux/err.h> | ||
| 17 | #include <linux/usb/audio.h> | ||
| 18 | #include <linux/usb/composite.h> | ||
| 19 | |||
| 20 | #include <sound/core.h> | ||
| 21 | #include <sound/pcm.h> | ||
| 22 | #include <sound/pcm_params.h> | ||
| 23 | |||
| 24 | #include "gadget_chips.h" | ||
| 25 | |||
| 26 | /* | ||
| 27 | * This represents the USB side of an audio card device, managed by a USB | ||
| 28 | * function which provides control and stream interfaces. | ||
| 29 | */ | ||
| 30 | |||
| 31 | struct gaudio_snd_dev { | ||
| 32 | struct gaudio *card; | ||
| 33 | struct file *filp; | ||
| 34 | struct snd_pcm_substream *substream; | ||
| 35 | int access; | ||
| 36 | int format; | ||
| 37 | int channels; | ||
| 38 | int rate; | ||
| 39 | }; | ||
| 40 | |||
| 41 | struct gaudio { | ||
| 42 | struct usb_function func; | ||
| 43 | struct usb_gadget *gadget; | ||
| 44 | |||
| 45 | /* ALSA sound device interfaces */ | ||
| 46 | struct gaudio_snd_dev control; | ||
| 47 | struct gaudio_snd_dev playback; | ||
| 48 | struct gaudio_snd_dev capture; | ||
| 49 | |||
| 50 | /* TODO */ | ||
| 51 | }; | ||
| 52 | |||
| 53 | int gaudio_setup(struct gaudio *card); | ||
| 54 | void gaudio_cleanup(void); | ||
| 55 | |||
| 56 | #endif /* __U_AUDIO_H */ | ||
diff --git a/drivers/usb/host/ehci-ath79.c b/drivers/usb/host/ehci-ath79.c new file mode 100644 index 00000000000..4d2e88d04da --- /dev/null +++ b/drivers/usb/host/ehci-ath79.c | |||
| @@ -0,0 +1,204 @@ | |||
| 1 | /* | ||
| 2 | * Bus Glue for Atheros AR7XXX/AR9XXX built-in EHCI controller. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> | ||
| 5 | * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> | ||
| 6 | * | ||
| 7 | * Parts of this file are based on Atheros' 2.6.15 BSP | ||
| 8 | * Copyright (C) 2007 Atheros Communications, Inc. | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify it | ||
| 11 | * under the terms of the GNU General Public License version 2 as published | ||
| 12 | * by the Free Software Foundation. | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include <linux/platform_device.h> | ||
| 16 | |||
| 17 | enum { | ||
| 18 | EHCI_ATH79_IP_V1 = 0, | ||
| 19 | EHCI_ATH79_IP_V2, | ||
| 20 | }; | ||
| 21 | |||
| 22 | static const struct platform_device_id ehci_ath79_id_table[] = { | ||
| 23 | { | ||
| 24 | .name = "ar71xx-ehci", | ||
| 25 | .driver_data = EHCI_ATH79_IP_V1, | ||
| 26 | }, | ||
| 27 | { | ||
| 28 | .name = "ar724x-ehci", | ||
| 29 | .driver_data = EHCI_ATH79_IP_V2, | ||
| 30 | }, | ||
| 31 | { | ||
| 32 | .name = "ar913x-ehci", | ||
| 33 | .driver_data = EHCI_ATH79_IP_V2, | ||
| 34 | }, | ||
| 35 | { | ||
| 36 | /* terminating entry */ | ||
| 37 | }, | ||
| 38 | }; | ||
| 39 | |||
| 40 | MODULE_DEVICE_TABLE(platform, ehci_ath79_id_table); | ||
| 41 | |||
| 42 | static int ehci_ath79_init(struct usb_hcd *hcd) | ||
| 43 | { | ||
| 44 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | ||
| 45 | struct platform_device *pdev = to_platform_device(hcd->self.controller); | ||
| 46 | const struct platform_device_id *id; | ||
| 47 | int ret; | ||
| 48 | |||
| 49 | id = platform_get_device_id(pdev); | ||
| 50 | if (!id) { | ||
| 51 | dev_err(hcd->self.controller, "missing device id\n"); | ||
| 52 | return -EINVAL; | ||
| 53 | } | ||
| 54 | |||
| 55 | switch (id->driver_data) { | ||
| 56 | case EHCI_ATH79_IP_V1: | ||
| 57 | ehci->has_synopsys_hc_bug = 1; | ||
| 58 | |||
| 59 | ehci->caps = hcd->regs; | ||
| 60 | ehci->regs = hcd->regs + | ||
| 61 | HC_LENGTH(ehci, | ||
| 62 | ehci_readl(ehci, &ehci->caps->hc_capbase)); | ||
| 63 | break; | ||
| 64 | |||
| 65 | case EHCI_ATH79_IP_V2: | ||
| 66 | hcd->has_tt = 1; | ||
| 67 | |||
| 68 | ehci->caps = hcd->regs + 0x100; | ||
| 69 | ehci->regs = hcd->regs + 0x100 + | ||
| 70 | HC_LENGTH(ehci, | ||
| 71 | ehci_readl(ehci, &ehci->caps->hc_capbase)); | ||
| 72 | break; | ||
| 73 | |||
| 74 | default: | ||
| 75 | BUG(); | ||
| 76 | } | ||
| 77 | |||
| 78 | dbg_hcs_params(ehci, "reset"); | ||
| 79 | dbg_hcc_params(ehci, "reset"); | ||
| 80 | ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); | ||
| 81 | ehci->sbrn = 0x20; | ||
| 82 | |||
| 83 | ehci_reset(ehci); | ||
| 84 | |||
| 85 | ret = ehci_init(hcd); | ||
| 86 | if (ret) | ||
| 87 | return ret; | ||
| 88 | |||
| 89 | ehci_port_power(ehci, 0); | ||
| 90 | |||
| 91 | return 0; | ||
| 92 | } | ||
| 93 | |||
| 94 | static const struct hc_driver ehci_ath79_hc_driver = { | ||
| 95 | .description = hcd_name, | ||
| 96 | .product_desc = "Atheros built-in EHCI controller", | ||
| 97 | .hcd_priv_size = sizeof(struct ehci_hcd), | ||
| 98 | .irq = ehci_irq, | ||
| 99 | .flags = HCD_MEMORY | HCD_USB2, | ||
| 100 | |||
| 101 | .reset = ehci_ath79_init, | ||
| 102 | .start = ehci_run, | ||
| 103 | .stop = ehci_stop, | ||
| 104 | .shutdown = ehci_shutdown, | ||
| 105 | |||
| 106 | .urb_enqueue = ehci_urb_enqueue, | ||
| 107 | .urb_dequeue = ehci_urb_dequeue, | ||
| 108 | .endpoint_disable = ehci_endpoint_disable, | ||
| 109 | .endpoint_reset = ehci_endpoint_reset, | ||
| 110 | |||
| 111 | .get_frame_number = ehci_get_frame, | ||
| 112 | |||
| 113 | .hub_status_data = ehci_hub_status_data, | ||
| 114 | .hub_control = ehci_hub_control, | ||
| 115 | |||
| 116 | .relinquish_port = ehci_relinquish_port, | ||
| 117 | .port_handed_over = ehci_port_handed_over, | ||
| 118 | |||
| 119 | .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, | ||
| 120 | }; | ||
| 121 | |||
| 122 | static int ehci_ath79_probe(struct platform_device *pdev) | ||
| 123 | { | ||
| 124 | struct usb_hcd *hcd; | ||
| 125 | struct resource *res; | ||
| 126 | int irq; | ||
| 127 | int ret; | ||
| 128 | |||
| 129 | if (usb_disabled()) | ||
| 130 | return -ENODEV; | ||
| 131 | |||
| 132 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
| 133 | if (!res) { | ||
| 134 | dev_dbg(&pdev->dev, "no IRQ specified\n"); | ||
| 135 | return -ENODEV; | ||
| 136 | } | ||
| 137 | irq = res->start; | ||
| 138 | |||
| 139 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 140 | if (!res) { | ||
| 141 | dev_dbg(&pdev->dev, "no base address specified\n"); | ||
| 142 | return -ENODEV; | ||
| 143 | } | ||
| 144 | |||
| 145 | hcd = usb_create_hcd(&ehci_ath79_hc_driver, &pdev->dev, | ||
| 146 | dev_name(&pdev->dev)); | ||
| 147 | if (!hcd) | ||
| 148 | return -ENOMEM; | ||
| 149 | |||
| 150 | hcd->rsrc_start = res->start; | ||
| 151 | hcd->rsrc_len = resource_size(res); | ||
| 152 | |||
| 153 | if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { | ||
| 154 | dev_dbg(&pdev->dev, "controller already in use\n"); | ||
| 155 | ret = -EBUSY; | ||
| 156 | goto err_put_hcd; | ||
| 157 | } | ||
| 158 | |||
| 159 | hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); | ||
| 160 | if (!hcd->regs) { | ||
| 161 | dev_dbg(&pdev->dev, "error mapping memory\n"); | ||
| 162 | ret = -EFAULT; | ||
| 163 | goto err_release_region; | ||
| 164 | } | ||
| 165 | |||
| 166 | ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); | ||
| 167 | if (ret) | ||
| 168 | goto err_iounmap; | ||
| 169 | |||
| 170 | return 0; | ||
| 171 | |||
| 172 | err_iounmap: | ||
| 173 | iounmap(hcd->regs); | ||
| 174 | |||
| 175 | err_release_region: | ||
| 176 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
| 177 | err_put_hcd: | ||
| 178 | usb_put_hcd(hcd); | ||
| 179 | return ret; | ||
| 180 | } | ||
| 181 | |||
| 182 | static int ehci_ath79_remove(struct platform_device *pdev) | ||
| 183 | { | ||
| 184 | struct usb_hcd *hcd = platform_get_drvdata(pdev); | ||
| 185 | |||
| 186 | usb_remove_hcd(hcd); | ||
| 187 | iounmap(hcd->regs); | ||
| 188 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
| 189 | usb_put_hcd(hcd); | ||
| 190 | |||
| 191 | return 0; | ||
| 192 | } | ||
| 193 | |||
| 194 | static struct platform_driver ehci_ath79_driver = { | ||
| 195 | .probe = ehci_ath79_probe, | ||
| 196 | .remove = ehci_ath79_remove, | ||
| 197 | .id_table = ehci_ath79_id_table, | ||
| 198 | .driver = { | ||
| 199 | .owner = THIS_MODULE, | ||
| 200 | .name = "ath79-ehci", | ||
| 201 | } | ||
| 202 | }; | ||
| 203 | |||
| 204 | MODULE_ALIAS(PLATFORM_MODULE_PREFIX "ath79-ehci"); | ||
diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c new file mode 100644 index 00000000000..42ae5740990 --- /dev/null +++ b/drivers/usb/host/ehci-au1xxx.c | |||
| @@ -0,0 +1,323 @@ | |||
| 1 | /* | ||
| 2 | * EHCI HCD (Host Controller Driver) for USB. | ||
| 3 | * | ||
| 4 | * Bus Glue for AMD Alchemy Au1xxx | ||
| 5 | * | ||
| 6 | * Based on "ohci-au1xxx.c" by Matt Porter <mporter@kernel.crashing.org> | ||
| 7 | * | ||
| 8 | * Modified for AMD Alchemy Au1200 EHC | ||
| 9 | * by K.Boge <karsten.boge@amd.com> | ||
| 10 | * | ||
| 11 | * This file is licenced under the GPL. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/platform_device.h> | ||
| 15 | #include <asm/mach-au1x00/au1000.h> | ||
| 16 | |||
| 17 | #define USB_HOST_CONFIG (USB_MSR_BASE + USB_MSR_MCFG) | ||
| 18 | #define USB_MCFG_PFEN (1<<31) | ||
| 19 | #define USB_MCFG_RDCOMB (1<<30) | ||
| 20 | #define USB_MCFG_SSDEN (1<<23) | ||
| 21 | #define USB_MCFG_PHYPLLEN (1<<19) | ||
| 22 | #define USB_MCFG_UCECLKEN (1<<18) | ||
| 23 | #define USB_MCFG_EHCCLKEN (1<<17) | ||
| 24 | #ifdef CONFIG_DMA_COHERENT | ||
| 25 | #define USB_MCFG_UCAM (1<<7) | ||
| 26 | #else | ||
| 27 | #define USB_MCFG_UCAM (0) | ||
| 28 | #endif | ||
| 29 | #define USB_MCFG_EBMEN (1<<3) | ||
| 30 | #define USB_MCFG_EMEMEN (1<<2) | ||
| 31 | |||
| 32 | #define USBH_ENABLE_CE (USB_MCFG_PHYPLLEN | USB_MCFG_EHCCLKEN) | ||
| 33 | #define USBH_ENABLE_INIT (USB_MCFG_PFEN | USB_MCFG_RDCOMB | \ | ||
| 34 | USBH_ENABLE_CE | USB_MCFG_SSDEN | \ | ||
| 35 | USB_MCFG_UCAM | USB_MCFG_EBMEN | \ | ||
| 36 | USB_MCFG_EMEMEN) | ||
| 37 | |||
| 38 | #define USBH_DISABLE (USB_MCFG_EBMEN | USB_MCFG_EMEMEN) | ||
| 39 | |||
| 40 | extern int usb_disabled(void); | ||
| 41 | |||
| 42 | static void au1xxx_start_ehc(void) | ||
| 43 | { | ||
| 44 | /* enable clock to EHCI block and HS PHY PLL*/ | ||
| 45 | au_writel(au_readl(USB_HOST_CONFIG) | USBH_ENABLE_CE, USB_HOST_CONFIG); | ||
| 46 | au_sync(); | ||
| 47 | udelay(1000); | ||
| 48 | |||
| 49 | /* enable EHCI mmio */ | ||
| 50 | au_writel(au_readl(USB_HOST_CONFIG) | USBH_ENABLE_INIT, USB_HOST_CONFIG); | ||
| 51 | au_sync(); | ||
| 52 | udelay(1000); | ||
| 53 | } | ||
| 54 | |||
| 55 | static void au1xxx_stop_ehc(void) | ||
| 56 | { | ||
| 57 | unsigned long c; | ||
| 58 | |||
| 59 | /* Disable mem */ | ||
| 60 | au_writel(au_readl(USB_HOST_CONFIG) & ~USBH_DISABLE, USB_HOST_CONFIG); | ||
| 61 | au_sync(); | ||
| 62 | udelay(1000); | ||
| 63 | |||
| 64 | /* Disable EHC clock. If the HS PHY is unused disable it too. */ | ||
| 65 | c = au_readl(USB_HOST_CONFIG) & ~USB_MCFG_EHCCLKEN; | ||
| 66 | if (!(c & USB_MCFG_UCECLKEN)) /* UDC disabled? */ | ||
| 67 | c &= ~USB_MCFG_PHYPLLEN; /* yes: disable HS PHY PLL */ | ||
| 68 | au_writel(c, USB_HOST_CONFIG); | ||
| 69 | au_sync(); | ||
| 70 | } | ||
| 71 | |||
| 72 | static int au1xxx_ehci_setup(struct usb_hcd *hcd) | ||
| 73 | { | ||
| 74 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | ||
| 75 | int ret = ehci_init(hcd); | ||
| 76 | |||
| 77 | ehci->need_io_watchdog = 0; | ||
| 78 | return ret; | ||
| 79 | } | ||
| 80 | |||
| 81 | static const struct hc_driver ehci_au1xxx_hc_driver = { | ||
| 82 | .description = hcd_name, | ||
| 83 | .product_desc = "Au1xxx EHCI", | ||
| 84 | .hcd_priv_size = sizeof(struct ehci_hcd), | ||
| 85 | |||
| 86 | /* | ||
| 87 | * generic hardware linkage | ||
| 88 | */ | ||
| 89 | .irq = ehci_irq, | ||
| 90 | .flags = HCD_MEMORY | HCD_USB2, | ||
| 91 | |||
| 92 | /* | ||
| 93 | * basic lifecycle operations | ||
| 94 | * | ||
| 95 | * FIXME -- ehci_init() doesn't do enough here. | ||
| 96 | * See ehci-ppc-soc for a complete implementation. | ||
| 97 | */ | ||
| 98 | .reset = au1xxx_ehci_setup, | ||
| 99 | .start = ehci_run, | ||
| 100 | .stop = ehci_stop, | ||
| 101 | .shutdown = ehci_shutdown, | ||
| 102 | |||
| 103 | /* | ||
| 104 | * managing i/o requests and associated device resources | ||
| 105 | */ | ||
| 106 | .urb_enqueue = ehci_urb_enqueue, | ||
| 107 | .urb_dequeue = ehci_urb_dequeue, | ||
| 108 | .endpoint_disable = ehci_endpoint_disable, | ||
| 109 | .endpoint_reset = ehci_endpoint_reset, | ||
| 110 | |||
| 111 | /* | ||
| 112 | * scheduling support | ||
| 113 | */ | ||
| 114 | .get_frame_number = ehci_get_frame, | ||
| 115 | |||
| 116 | /* | ||
| 117 | * root hub support | ||
| 118 | */ | ||
| 119 | .hub_status_data = ehci_hub_status_data, | ||
| 120 | .hub_control = ehci_hub_control, | ||
| 121 | .bus_suspend = ehci_bus_suspend, | ||
| 122 | .bus_resume = ehci_bus_resume, | ||
| 123 | .relinquish_port = ehci_relinquish_port, | ||
| 124 | .port_handed_over = ehci_port_handed_over, | ||
| 125 | |||
| 126 | .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, | ||
| 127 | }; | ||
| 128 | |||
| 129 | static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev) | ||
| 130 | { | ||
| 131 | struct usb_hcd *hcd; | ||
| 132 | struct ehci_hcd *ehci; | ||
| 133 | struct resource *res; | ||
| 134 | int ret; | ||
| 135 | |||
| 136 | if (usb_disabled()) | ||
| 137 | return -ENODEV; | ||
| 138 | |||
| 139 | #if defined(CONFIG_SOC_AU1200) && defined(CONFIG_DMA_COHERENT) | ||
| 140 | /* Au1200 AB USB does not support coherent memory */ | ||
| 141 | if (!(read_c0_prid() & 0xff)) { | ||
| 142 | printk(KERN_INFO "%s: this is chip revision AB!\n", pdev->name); | ||
| 143 | printk(KERN_INFO "%s: update your board or re-configure" | ||
| 144 | " the kernel\n", pdev->name); | ||
| 145 | return -ENODEV; | ||
| 146 | } | ||
| 147 | #endif | ||
| 148 | |||
| 149 | if (pdev->resource[1].flags != IORESOURCE_IRQ) { | ||
| 150 | pr_debug("resource[1] is not IORESOURCE_IRQ"); | ||
| 151 | return -ENOMEM; | ||
| 152 | } | ||
| 153 | hcd = usb_create_hcd(&ehci_au1xxx_hc_driver, &pdev->dev, "Au1xxx"); | ||
| 154 | if (!hcd) | ||
| 155 | return -ENOMEM; | ||
| 156 | |||
| 157 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 158 | hcd->rsrc_start = res->start; | ||
| 159 | hcd->rsrc_len = resource_size(res); | ||
| 160 | |||
| 161 | if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { | ||
| 162 | pr_debug("request_mem_region failed"); | ||
| 163 | ret = -EBUSY; | ||
| 164 | goto err1; | ||
| 165 | } | ||
| 166 | |||
| 167 | hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); | ||
| 168 | if (!hcd->regs) { | ||
| 169 | pr_debug("ioremap failed"); | ||
| 170 | ret = -ENOMEM; | ||
| 171 | goto err2; | ||
| 172 | } | ||
| 173 | |||
| 174 | au1xxx_start_ehc(); | ||
| 175 | |||
| 176 | ehci = hcd_to_ehci(hcd); | ||
| 177 | ehci->caps = hcd->regs; | ||
| 178 | ehci->regs = hcd->regs + | ||
| 179 | HC_LENGTH(ehci, readl(&ehci->caps->hc_capbase)); | ||
| 180 | /* cache this readonly data; minimize chip reads */ | ||
| 181 | ehci->hcs_params = readl(&ehci->caps->hcs_params); | ||
| 182 | |||
| 183 | ret = usb_add_hcd(hcd, pdev->resource[1].start, | ||
| 184 | IRQF_DISABLED | IRQF_SHARED); | ||
| 185 | if (ret == 0) { | ||
| 186 | platform_set_drvdata(pdev, hcd); | ||
| 187 | return ret; | ||
| 188 | } | ||
| 189 | |||
| 190 | au1xxx_stop_ehc(); | ||
| 191 | iounmap(hcd->regs); | ||
| 192 | err2: | ||
| 193 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
| 194 | err1: | ||
| 195 | usb_put_hcd(hcd); | ||
| 196 | return ret; | ||
| 197 | } | ||
| 198 | |||
| 199 | static int ehci_hcd_au1xxx_drv_remove(struct platform_device *pdev) | ||
| 200 | { | ||
| 201 | struct usb_hcd *hcd = platform_get_drvdata(pdev); | ||
| 202 | |||
| 203 | usb_remove_hcd(hcd); | ||
| 204 | iounmap(hcd->regs); | ||
| 205 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
| 206 | usb_put_hcd(hcd); | ||
| 207 | au1xxx_stop_ehc(); | ||
| 208 | platform_set_drvdata(pdev, NULL); | ||
| 209 | |||
| 210 | return 0; | ||
| 211 | } | ||
| 212 | |||
| 213 | #ifdef CONFIG_PM | ||
| 214 | static int ehci_hcd_au1xxx_drv_suspend(struct device *dev) | ||
| 215 | { | ||
| 216 | struct usb_hcd *hcd = dev_get_drvdata(dev); | ||
| 217 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | ||
| 218 | unsigned long flags; | ||
| 219 | int rc = 0; | ||
| 220 | |||
| 221 | if (time_before(jiffies, ehci->next_statechange)) | ||
| 222 | msleep(10); | ||
| 223 | |||
| 224 | /* Root hub was already suspended. Disable irq emission and | ||
| 225 | * mark HW unaccessible. The PM and USB cores make sure that | ||
| 226 | * the root hub is either suspended or stopped. | ||
| 227 | */ | ||
| 228 | ehci_prepare_ports_for_controller_suspend(ehci, device_may_wakeup(dev)); | ||
| 229 | spin_lock_irqsave(&ehci->lock, flags); | ||
| 230 | ehci_writel(ehci, 0, &ehci->regs->intr_enable); | ||
| 231 | (void)ehci_readl(ehci, &ehci->regs->intr_enable); | ||
| 232 | |||
| 233 | clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); | ||
| 234 | spin_unlock_irqrestore(&ehci->lock, flags); | ||
| 235 | |||
| 236 | // could save FLADJ in case of Vaux power loss | ||
| 237 | // ... we'd only use it to handle clock skew | ||
| 238 | |||
| 239 | au1xxx_stop_ehc(); | ||
| 240 | |||
| 241 | return rc; | ||
| 242 | } | ||
| 243 | |||
| 244 | static int ehci_hcd_au1xxx_drv_resume(struct device *dev) | ||
| 245 | { | ||
| 246 | struct usb_hcd *hcd = dev_get_drvdata(dev); | ||
| 247 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | ||
| 248 | |||
| 249 | au1xxx_start_ehc(); | ||
| 250 | |||
| 251 | // maybe restore FLADJ | ||
| 252 | |||
| 253 | if (time_before(jiffies, ehci->next_statechange)) | ||
| 254 | msleep(100); | ||
| 255 | |||
| 256 | /* Mark hardware accessible again as we are out of D3 state by now */ | ||
| 257 | set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); | ||
| 258 | |||
| 259 | /* If CF is still set, we maintained PCI Vaux power. | ||
| 260 | * Just undo the effect of ehci_pci_suspend(). | ||
| 261 | */ | ||
| 262 | if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) { | ||
| 263 | int mask = INTR_MASK; | ||
| 264 | |||
| 265 | ehci_prepare_ports_for_controller_resume(ehci); | ||
| 266 | if (!hcd->self.root_hub->do_remote_wakeup) | ||
| 267 | mask &= ~STS_PCD; | ||
| 268 | ehci_writel(ehci, mask, &ehci->regs->intr_enable); | ||
| 269 | ehci_readl(ehci, &ehci->regs->intr_enable); | ||
| 270 | return 0; | ||
| 271 | } | ||
| 272 | |||
| 273 | ehci_dbg(ehci, "lost power, restarting\n"); | ||
| 274 | usb_root_hub_lost_power(hcd->self.root_hub); | ||
| 275 | |||
| 276 | /* Else reset, to cope with power loss or flush-to-storage | ||
| 277 | * style "resume" having let BIOS kick in during reboot. | ||
| 278 | */ | ||
| 279 | (void) ehci_halt(ehci); | ||
| 280 | (void) ehci_reset(ehci); | ||
| 281 | |||
| 282 | /* emptying the schedule aborts any urbs */ | ||
| 283 | spin_lock_irq(&ehci->lock); | ||
| 284 | if (ehci->reclaim) | ||
| 285 | end_unlink_async(ehci); | ||
| 286 | ehci_work(ehci); | ||
| 287 | spin_unlock_irq(&ehci->lock); | ||
| 288 | |||
| 289 | ehci_writel(ehci, ehci->command, &ehci->regs->command); | ||
| 290 | ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag); | ||
| 291 | ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */ | ||
| 292 | |||
| 293 | /* here we "know" root ports should always stay powered */ | ||
| 294 | ehci_port_power(ehci, 1); | ||
| 295 | |||
| 296 | hcd->state = HC_STATE_SUSPENDED; | ||
| 297 | |||
| 298 | return 0; | ||
| 299 | } | ||
| 300 | |||
| 301 | static const struct dev_pm_ops au1xxx_ehci_pmops = { | ||
| 302 | .suspend = ehci_hcd_au1xxx_drv_suspend, | ||
| 303 | .resume = ehci_hcd_au1xxx_drv_resume, | ||
| 304 | }; | ||
| 305 | |||
| 306 | #define AU1XXX_EHCI_PMOPS &au1xxx_ehci_pmops | ||
| 307 | |||
| 308 | #else | ||
| 309 | #define AU1XXX_EHCI_PMOPS NULL | ||
| 310 | #endif | ||
| 311 | |||
| 312 | static struct platform_driver ehci_hcd_au1xxx_driver = { | ||
| 313 | .probe = ehci_hcd_au1xxx_drv_probe, | ||
| 314 | .remove = ehci_hcd_au1xxx_drv_remove, | ||
| 315 | .shutdown = usb_hcd_platform_shutdown, | ||
| 316 | .driver = { | ||
| 317 | .name = "au1xxx-ehci", | ||
| 318 | .owner = THIS_MODULE, | ||
| 319 | .pm = AU1XXX_EHCI_PMOPS, | ||
| 320 | } | ||
| 321 | }; | ||
| 322 | |||
| 323 | MODULE_ALIAS("platform:au1xxx-ehci"); | ||
diff --git a/drivers/usb/host/ehci-cns3xxx.c b/drivers/usb/host/ehci-cns3xxx.c new file mode 100644 index 00000000000..6536abdea6e --- /dev/null +++ b/drivers/usb/host/ehci-cns3xxx.c | |||
| @@ -0,0 +1,171 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2008 Cavium Networks | ||
| 3 | * | ||
| 4 | * This file is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License, Version 2, as | ||
| 6 | * published by the Free Software Foundation. | ||
| 7 | */ | ||
| 8 | |||
| 9 | #include <linux/platform_device.h> | ||
| 10 | #include <linux/atomic.h> | ||
| 11 | #include <mach/cns3xxx.h> | ||
| 12 | #include <mach/pm.h> | ||
| 13 | |||
| 14 | static int cns3xxx_ehci_init(struct usb_hcd *hcd) | ||
| 15 | { | ||
| 16 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | ||
| 17 | int retval; | ||
| 18 | |||
| 19 | /* | ||
| 20 | * EHCI and OHCI share the same clock and power, | ||
| 21 | * resetting twice would cause the 1st controller been reset. | ||
| 22 | * Therefore only do power up at the first up device, and | ||
| 23 | * power down at the last down device. | ||
| 24 | * | ||
| 25 | * Set USB AHB INCR length to 16 | ||
| 26 | */ | ||
| 27 | if (atomic_inc_return(&usb_pwr_ref) == 1) { | ||
| 28 | cns3xxx_pwr_power_up(1 << PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_USB); | ||
| 29 | cns3xxx_pwr_clk_en(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST); | ||
| 30 | cns3xxx_pwr_soft_rst(1 << PM_SOFT_RST_REG_OFFST_USB_HOST); | ||
| 31 | __raw_writel((__raw_readl(MISC_CHIP_CONFIG_REG) | (0X2 << 24)), | ||
| 32 | MISC_CHIP_CONFIG_REG); | ||
| 33 | } | ||
| 34 | |||
| 35 | ehci->caps = hcd->regs; | ||
| 36 | ehci->regs = hcd->regs | ||
| 37 | + HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); | ||
| 38 | ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); | ||
| 39 | |||
| 40 | hcd->has_tt = 0; | ||
| 41 | ehci_reset(ehci); | ||
| 42 | |||
| 43 | retval = ehci_init(hcd); | ||
| 44 | if (retval) | ||
| 45 | return retval; | ||
| 46 | |||
| 47 | ehci_port_power(ehci, 0); | ||
| 48 | |||
| 49 | return retval; | ||
| 50 | } | ||
| 51 | |||
| 52 | static const struct hc_driver cns3xxx_ehci_hc_driver = { | ||
| 53 | .description = hcd_name, | ||
| 54 | .product_desc = "CNS3XXX EHCI Host Controller", | ||
| 55 | .hcd_priv_size = sizeof(struct ehci_hcd), | ||
| 56 | .irq = ehci_irq, | ||
| 57 | .flags = HCD_MEMORY | HCD_USB2, | ||
| 58 | .reset = cns3xxx_ehci_init, | ||
| 59 | .start = ehci_run, | ||
| 60 | .stop = ehci_stop, | ||
| 61 | .shutdown = ehci_shutdown, | ||
| 62 | .urb_enqueue = ehci_urb_enqueue, | ||
| 63 | .urb_dequeue = ehci_urb_dequeue, | ||
| 64 | .endpoint_disable = ehci_endpoint_disable, | ||
| 65 | .endpoint_reset = ehci_endpoint_reset, | ||
| 66 | .get_frame_number = ehci_get_frame, | ||
| 67 | .hub_status_data = ehci_hub_status_data, | ||
| 68 | .hub_control = ehci_hub_control, | ||
| 69 | #ifdef CONFIG_PM | ||
| 70 | .bus_suspend = ehci_bus_suspend, | ||
| 71 | .bus_resume = ehci_bus_resume, | ||
| 72 | #endif | ||
| 73 | .relinquish_port = ehci_relinquish_port, | ||
| 74 | .port_handed_over = ehci_port_handed_over, | ||
| 75 | |||
| 76 | .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, | ||
| 77 | }; | ||
| 78 | |||
| 79 | static int cns3xxx_ehci_probe(struct platform_device *pdev) | ||
| 80 | { | ||
| 81 | struct device *dev = &pdev->dev; | ||
| 82 | struct usb_hcd *hcd; | ||
| 83 | const struct hc_driver *driver = &cns3xxx_ehci_hc_driver; | ||
| 84 | struct resource *res; | ||
| 85 | int irq; | ||
| 86 | int retval; | ||
| 87 | |||
| 88 | if (usb_disabled()) | ||
| 89 | return -ENODEV; | ||
| 90 | |||
| 91 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
| 92 | if (!res) { | ||
| 93 | dev_err(dev, "Found HC with no IRQ.\n"); | ||
| 94 | return -ENODEV; | ||
| 95 | } | ||
| 96 | irq = res->start; | ||
| 97 | |||
| 98 | hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev)); | ||
| 99 | if (!hcd) | ||
| 100 | return -ENOMEM; | ||
| 101 | |||
| 102 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 103 | if (!res) { | ||
| 104 | dev_err(dev, "Found HC with no register addr.\n"); | ||
| 105 | retval = -ENODEV; | ||
| 106 | goto err1; | ||
| 107 | } | ||
| 108 | |||
| 109 | hcd->rsrc_start = res->start; | ||
| 110 | hcd->rsrc_len = resource_size(res); | ||
| 111 | |||
| 112 | if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, | ||
| 113 | driver->description)) { | ||
| 114 | dev_dbg(dev, "controller already in use\n"); | ||
| 115 | retval = -EBUSY; | ||
| 116 | goto err1; | ||
| 117 | } | ||
| 118 | |||
| 119 | hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); | ||
| 120 | if (hcd->regs == NULL) { | ||
| 121 | dev_dbg(dev, "error mapping memory\n"); | ||
| 122 | retval = -EFAULT; | ||
| 123 | goto err2; | ||
| 124 | } | ||
| 125 | |||
| 126 | retval = usb_add_hcd(hcd, irq, IRQF_SHARED); | ||
| 127 | if (retval == 0) | ||
| 128 | return retval; | ||
| 129 | |||
| 130 | iounmap(hcd->regs); | ||
| 131 | err2: | ||
| 132 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
| 133 | err1: | ||
| 134 | usb_put_hcd(hcd); | ||
| 135 | |||
| 136 | return retval; | ||
| 137 | } | ||
| 138 | |||
| 139 | static int cns3xxx_ehci_remove(struct platform_device *pdev) | ||
| 140 | { | ||
| 141 | struct usb_hcd *hcd = platform_get_drvdata(pdev); | ||
| 142 | |||
| 143 | usb_remove_hcd(hcd); | ||
| 144 | iounmap(hcd->regs); | ||
| 145 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
| 146 | |||
| 147 | /* | ||
| 148 | * EHCI and OHCI share the same clock and power, | ||
| 149 | * resetting twice would cause the 1st controller been reset. | ||
| 150 | * Therefore only do power up at the first up device, and | ||
| 151 | * power down at the last down device. | ||
| 152 | */ | ||
| 153 | if (atomic_dec_return(&usb_pwr_ref) == 0) | ||
| 154 | cns3xxx_pwr_clk_dis(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST); | ||
| 155 | |||
| 156 | usb_put_hcd(hcd); | ||
| 157 | |||
| 158 | platform_set_drvdata(pdev, NULL); | ||
| 159 | |||
| 160 | return 0; | ||
| 161 | } | ||
| 162 | |||
| 163 | MODULE_ALIAS("platform:cns3xxx-ehci"); | ||
| 164 | |||
| 165 | static struct platform_driver cns3xxx_ehci_driver = { | ||
| 166 | .probe = cns3xxx_ehci_probe, | ||
| 167 | .remove = cns3xxx_ehci_remove, | ||
| 168 | .driver = { | ||
| 169 | .name = "cns3xxx-ehci", | ||
| 170 | }, | ||
| 171 | }; | ||
diff --git a/drivers/usb/host/ehci-ixp4xx.c b/drivers/usb/host/ehci-ixp4xx.c new file mode 100644 index 00000000000..c4460f3d009 --- /dev/null +++ b/drivers/usb/host/ehci-ixp4xx.c | |||
| @@ -0,0 +1,156 @@ | |||
| 1 | /* | ||
| 2 | * IXP4XX EHCI Host Controller Driver | ||
| 3 | * | ||
| 4 | * Author: Vladimir Barinov <vbarinov@embeddedalley.com> | ||
| 5 | * | ||
| 6 | * Based on "ehci-fsl.c" by Randy Vinson <rvinson@mvista.com> | ||
| 7 | * | ||
| 8 | * 2007 (c) MontaVista Software, Inc. This file is licensed under | ||
| 9 | * the terms of the GNU General Public License version 2. This program | ||
| 10 | * is licensed "as is" without any warranty of any kind, whether express | ||
| 11 | * or implied. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/platform_device.h> | ||
| 15 | |||
| 16 | static int ixp4xx_ehci_init(struct usb_hcd *hcd) | ||
| 17 | { | ||
| 18 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | ||
| 19 | int retval = 0; | ||
| 20 | |||
| 21 | ehci->big_endian_desc = 1; | ||
| 22 | ehci->big_endian_mmio = 1; | ||
| 23 | |||
| 24 | ehci->caps = hcd->regs + 0x100; | ||
| 25 | ehci->regs = hcd->regs + 0x100 | ||
| 26 | + HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); | ||
| 27 | ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); | ||
| 28 | |||
| 29 | hcd->has_tt = 1; | ||
| 30 | ehci_reset(ehci); | ||
| 31 | |||
| 32 | retval = ehci_init(hcd); | ||
| 33 | if (retval) | ||
| 34 | return retval; | ||
| 35 | |||
| 36 | ehci_port_power(ehci, 0); | ||
| 37 | |||
| 38 | return retval; | ||
| 39 | } | ||
| 40 | |||
| 41 | static const struct hc_driver ixp4xx_ehci_hc_driver = { | ||
| 42 | .description = hcd_name, | ||
| 43 | .product_desc = "IXP4XX EHCI Host Controller", | ||
| 44 | .hcd_priv_size = sizeof(struct ehci_hcd), | ||
| 45 | .irq = ehci_irq, | ||
| 46 | .flags = HCD_MEMORY | HCD_USB2, | ||
| 47 | .reset = ixp4xx_ehci_init, | ||
| 48 | .start = ehci_run, | ||
| 49 | .stop = ehci_stop, | ||
| 50 | .shutdown = ehci_shutdown, | ||
| 51 | .urb_enqueue = ehci_urb_enqueue, | ||
| 52 | .urb_dequeue = ehci_urb_dequeue, | ||
| 53 | .endpoint_disable = ehci_endpoint_disable, | ||
| 54 | .endpoint_reset = ehci_endpoint_reset, | ||
| 55 | .get_frame_number = ehci_get_frame, | ||
| 56 | .hub_status_data = ehci_hub_status_data, | ||
| 57 | .hub_control = ehci_hub_control, | ||
| 58 | #if defined(CONFIG_PM) | ||
| 59 | .bus_suspend = ehci_bus_suspend, | ||
| 60 | .bus_resume = ehci_bus_resume, | ||
| 61 | #endif | ||
| 62 | .relinquish_port = ehci_relinquish_port, | ||
| 63 | .port_handed_over = ehci_port_handed_over, | ||
| 64 | |||
| 65 | .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, | ||
| 66 | }; | ||
| 67 | |||
| 68 | static int ixp4xx_ehci_probe(struct platform_device *pdev) | ||
| 69 | { | ||
| 70 | struct usb_hcd *hcd; | ||
| 71 | const struct hc_driver *driver = &ixp4xx_ehci_hc_driver; | ||
| 72 | struct resource *res; | ||
| 73 | int irq; | ||
| 74 | int retval; | ||
| 75 | |||
| 76 | if (usb_disabled()) | ||
| 77 | return -ENODEV; | ||
| 78 | |||
| 79 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
| 80 | if (!res) { | ||
| 81 | dev_err(&pdev->dev, | ||
| 82 | "Found HC with no IRQ. Check %s setup!\n", | ||
| 83 | dev_name(&pdev->dev)); | ||
| 84 | return -ENODEV; | ||
| 85 | } | ||
| 86 | irq = res->start; | ||
| 87 | |||
| 88 | hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev)); | ||
| 89 | if (!hcd) { | ||
| 90 | retval = -ENOMEM; | ||
| 91 | goto fail_create_hcd; | ||
| 92 | } | ||
| 93 | |||
| 94 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 95 | if (!res) { | ||
| 96 | dev_err(&pdev->dev, | ||
| 97 | "Found HC with no register addr. Check %s setup!\n", | ||
| 98 | dev_name(&pdev->dev)); | ||
| 99 | retval = -ENODEV; | ||
| 100 | goto fail_request_resource; | ||
| 101 | } | ||
| 102 | hcd->rsrc_start = res->start; | ||
| 103 | hcd->rsrc_len = resource_size(res); | ||
| 104 | |||
| 105 | if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, | ||
| 106 | driver->description)) { | ||
| 107 | dev_dbg(&pdev->dev, "controller already in use\n"); | ||
| 108 | retval = -EBUSY; | ||
| 109 | goto fail_request_resource; | ||
| 110 | } | ||
| 111 | |||
| 112 | hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); | ||
| 113 | if (hcd->regs == NULL) { | ||
| 114 | dev_dbg(&pdev->dev, "error mapping memory\n"); | ||
| 115 | retval = -EFAULT; | ||
| 116 | goto fail_ioremap; | ||
| 117 | } | ||
| 118 | |||
| 119 | retval = usb_add_hcd(hcd, irq, IRQF_SHARED); | ||
| 120 | if (retval) | ||
| 121 | goto fail_add_hcd; | ||
| 122 | |||
| 123 | return retval; | ||
| 124 | |||
| 125 | fail_add_hcd: | ||
| 126 | iounmap(hcd->regs); | ||
| 127 | fail_ioremap: | ||
| 128 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
| 129 | fail_request_resource: | ||
| 130 | usb_put_hcd(hcd); | ||
| 131 | fail_create_hcd: | ||
| 132 | dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev), retval); | ||
| 133 | return retval; | ||
| 134 | } | ||
| 135 | |||
| 136 | static int ixp4xx_ehci_remove(struct platform_device *pdev) | ||
| 137 | { | ||
| 138 | struct usb_hcd *hcd = platform_get_drvdata(pdev); | ||
| 139 | |||
| 140 | usb_remove_hcd(hcd); | ||
| 141 | iounmap(hcd->regs); | ||
| 142 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
| 143 | usb_put_hcd(hcd); | ||
| 144 | |||
| 145 | return 0; | ||
| 146 | } | ||
| 147 | |||
| 148 | MODULE_ALIAS("platform:ixp4xx-ehci"); | ||
| 149 | |||
| 150 | static struct platform_driver ixp4xx_ehci_driver = { | ||
| 151 | .probe = ixp4xx_ehci_probe, | ||
| 152 | .remove = ixp4xx_ehci_remove, | ||
| 153 | .driver = { | ||
| 154 | .name = "ixp4xx-ehci", | ||
| 155 | }, | ||
| 156 | }; | ||
diff --git a/drivers/usb/host/ehci-lpm.c b/drivers/usb/host/ehci-lpm.c new file mode 100644 index 00000000000..2111627a19d --- /dev/null +++ b/drivers/usb/host/ehci-lpm.c | |||
| @@ -0,0 +1,84 @@ | |||
| 1 | /* ehci-lpm.c EHCI HCD LPM support code | ||
| 2 | * Copyright (c) 2008 - 2010, Intel Corporation. | ||
| 3 | * Author: Jacob Pan <jacob.jun.pan@intel.com> | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify | ||
| 6 | * it under the terms of the GNU General Public License version 2 as | ||
| 7 | * published by the Free Software Foundation. | ||
| 8 | * | ||
| 9 | * This program is distributed in the hope that it will be useful, | ||
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | * GNU General Public License for more details. | ||
| 13 | * | ||
| 14 | * You should have received a copy of the GNU General Public License | ||
| 15 | * along with this program; if not, write to the Free Software | ||
| 16 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 17 | */ | ||
| 18 | |||
| 19 | /* this file is part of ehci-hcd.c */ | ||
| 20 | static int __maybe_unused ehci_lpm_set_da(struct ehci_hcd *ehci, | ||
| 21 | int dev_addr, int port_num) | ||
| 22 | { | ||
| 23 | u32 __iomem portsc; | ||
| 24 | |||
| 25 | ehci_dbg(ehci, "set dev address %d for port %d\n", dev_addr, port_num); | ||
| 26 | if (port_num > HCS_N_PORTS(ehci->hcs_params)) { | ||
| 27 | ehci_dbg(ehci, "invalid port number %d\n", port_num); | ||
| 28 | return -ENODEV; | ||
| 29 | } | ||
| 30 | portsc = ehci_readl(ehci, &ehci->regs->port_status[port_num-1]); | ||
| 31 | portsc &= ~PORT_DEV_ADDR; | ||
| 32 | portsc |= dev_addr<<25; | ||
| 33 | ehci_writel(ehci, portsc, &ehci->regs->port_status[port_num-1]); | ||
| 34 | return 0; | ||
| 35 | } | ||
| 36 | |||
| 37 | /* | ||
| 38 | * this function is used to check if the device support LPM | ||
| 39 | * if yes, mark the PORTSC register with PORT_LPM bit | ||
| 40 | */ | ||
| 41 | static int __maybe_unused ehci_lpm_check(struct ehci_hcd *ehci, int port) | ||
| 42 | { | ||
| 43 | u32 __iomem *portsc ; | ||
| 44 | u32 val32; | ||
| 45 | int retval; | ||
| 46 | |||
| 47 | portsc = &ehci->regs->port_status[port-1]; | ||
| 48 | val32 = ehci_readl(ehci, portsc); | ||
| 49 | if (!(val32 & PORT_DEV_ADDR)) { | ||
| 50 | ehci_dbg(ehci, "LPM: no device attached\n"); | ||
| 51 | return -ENODEV; | ||
| 52 | } | ||
| 53 | val32 |= PORT_LPM; | ||
| 54 | ehci_writel(ehci, val32, portsc); | ||
| 55 | msleep(5); | ||
| 56 | val32 |= PORT_SUSPEND; | ||
| 57 | ehci_dbg(ehci, "Sending LPM 0x%08x to port %d\n", val32, port); | ||
| 58 | ehci_writel(ehci, val32, portsc); | ||
| 59 | /* wait for ACK */ | ||
| 60 | msleep(10); | ||
| 61 | retval = handshake(ehci, &ehci->regs->port_status[port-1], PORT_SSTS, | ||
| 62 | PORTSC_SUSPEND_STS_ACK, 125); | ||
| 63 | dbg_port(ehci, "LPM", port, val32); | ||
| 64 | if (retval != -ETIMEDOUT) { | ||
| 65 | ehci_dbg(ehci, "LPM: device ACK for LPM\n"); | ||
| 66 | val32 |= PORT_LPM; | ||
| 67 | /* | ||
| 68 | * now device should be in L1 sleep, let's wake up the device | ||
| 69 | * so that we can complete enumeration. | ||
| 70 | */ | ||
| 71 | ehci_writel(ehci, val32, portsc); | ||
| 72 | msleep(10); | ||
| 73 | val32 |= PORT_RESUME; | ||
| 74 | ehci_writel(ehci, val32, portsc); | ||
| 75 | } else { | ||
| 76 | ehci_dbg(ehci, "LPM: device does not ACK, disable LPM %d\n", | ||
| 77 | retval); | ||
| 78 | val32 &= ~PORT_LPM; | ||
| 79 | retval = -ETIMEDOUT; | ||
| 80 | ehci_writel(ehci, val32, portsc); | ||
| 81 | } | ||
| 82 | |||
| 83 | return retval; | ||
| 84 | } | ||
diff --git a/drivers/usb/host/ohci-ath79.c b/drivers/usb/host/ohci-ath79.c new file mode 100644 index 00000000000..c620c50f677 --- /dev/null +++ b/drivers/usb/host/ohci-ath79.c | |||
| @@ -0,0 +1,151 @@ | |||
| 1 | /* | ||
| 2 | * OHCI HCD (Host Controller Driver) for USB. | ||
| 3 | * | ||
| 4 | * Bus Glue for Atheros AR71XX/AR724X built-in OHCI controller. | ||
| 5 | * | ||
| 6 | * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> | ||
| 7 | * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> | ||
| 8 | * | ||
| 9 | * Parts of this file are based on Atheros' 2.6.15 BSP | ||
| 10 | * Copyright (C) 2007 Atheros Communications, Inc. | ||
| 11 | * | ||
| 12 | * This program is free software; you can redistribute it and/or modify it | ||
| 13 | * under the terms of the GNU General Public License version 2 as published | ||
| 14 | * by the Free Software Foundation. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/platform_device.h> | ||
| 18 | |||
| 19 | static int __devinit ohci_ath79_start(struct usb_hcd *hcd) | ||
| 20 | { | ||
| 21 | struct ohci_hcd *ohci = hcd_to_ohci(hcd); | ||
| 22 | int ret; | ||
| 23 | |||
| 24 | ret = ohci_init(ohci); | ||
| 25 | if (ret < 0) | ||
| 26 | return ret; | ||
| 27 | |||
| 28 | ret = ohci_run(ohci); | ||
| 29 | if (ret < 0) | ||
| 30 | goto err; | ||
| 31 | |||
| 32 | return 0; | ||
| 33 | |||
| 34 | err: | ||
| 35 | ohci_stop(hcd); | ||
| 36 | return ret; | ||
| 37 | } | ||
| 38 | |||
| 39 | static const struct hc_driver ohci_ath79_hc_driver = { | ||
| 40 | .description = hcd_name, | ||
| 41 | .product_desc = "Atheros built-in OHCI controller", | ||
| 42 | .hcd_priv_size = sizeof(struct ohci_hcd), | ||
| 43 | |||
| 44 | .irq = ohci_irq, | ||
| 45 | .flags = HCD_USB11 | HCD_MEMORY, | ||
| 46 | |||
| 47 | .start = ohci_ath79_start, | ||
| 48 | .stop = ohci_stop, | ||
| 49 | .shutdown = ohci_shutdown, | ||
| 50 | |||
| 51 | .urb_enqueue = ohci_urb_enqueue, | ||
| 52 | .urb_dequeue = ohci_urb_dequeue, | ||
| 53 | .endpoint_disable = ohci_endpoint_disable, | ||
| 54 | |||
| 55 | /* | ||
| 56 | * scheduling support | ||
| 57 | */ | ||
| 58 | .get_frame_number = ohci_get_frame, | ||
| 59 | |||
| 60 | /* | ||
| 61 | * root hub support | ||
| 62 | */ | ||
| 63 | .hub_status_data = ohci_hub_status_data, | ||
| 64 | .hub_control = ohci_hub_control, | ||
| 65 | .start_port_reset = ohci_start_port_reset, | ||
| 66 | }; | ||
| 67 | |||
| 68 | static int ohci_ath79_probe(struct platform_device *pdev) | ||
| 69 | { | ||
| 70 | struct usb_hcd *hcd; | ||
| 71 | struct resource *res; | ||
| 72 | int irq; | ||
| 73 | int ret; | ||
| 74 | |||
| 75 | if (usb_disabled()) | ||
| 76 | return -ENODEV; | ||
| 77 | |||
| 78 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
| 79 | if (!res) { | ||
| 80 | dev_dbg(&pdev->dev, "no IRQ specified\n"); | ||
| 81 | return -ENODEV; | ||
| 82 | } | ||
| 83 | irq = res->start; | ||
| 84 | |||
| 85 | hcd = usb_create_hcd(&ohci_ath79_hc_driver, &pdev->dev, | ||
| 86 | dev_name(&pdev->dev)); | ||
| 87 | if (!hcd) | ||
| 88 | return -ENOMEM; | ||
| 89 | |||
| 90 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 91 | if (!res) { | ||
| 92 | dev_dbg(&pdev->dev, "no base address specified\n"); | ||
| 93 | ret = -ENODEV; | ||
| 94 | goto err_put_hcd; | ||
| 95 | } | ||
| 96 | hcd->rsrc_start = res->start; | ||
| 97 | hcd->rsrc_len = resource_size(res); | ||
| 98 | |||
| 99 | if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { | ||
| 100 | dev_dbg(&pdev->dev, "controller already in use\n"); | ||
| 101 | ret = -EBUSY; | ||
| 102 | goto err_put_hcd; | ||
| 103 | } | ||
| 104 | |||
| 105 | hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); | ||
| 106 | if (!hcd->regs) { | ||
| 107 | dev_dbg(&pdev->dev, "error mapping memory\n"); | ||
| 108 | ret = -EFAULT; | ||
| 109 | goto err_release_region; | ||
| 110 | } | ||
| 111 | |||
| 112 | ohci_hcd_init(hcd_to_ohci(hcd)); | ||
| 113 | |||
| 114 | ret = usb_add_hcd(hcd, irq, IRQF_DISABLED); | ||
| 115 | if (ret) | ||
| 116 | goto err_stop_hcd; | ||
| 117 | |||
| 118 | return 0; | ||
| 119 | |||
| 120 | err_stop_hcd: | ||
| 121 | iounmap(hcd->regs); | ||
| 122 | err_release_region: | ||
| 123 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
| 124 | err_put_hcd: | ||
| 125 | usb_put_hcd(hcd); | ||
| 126 | return ret; | ||
| 127 | } | ||
| 128 | |||
| 129 | static int ohci_ath79_remove(struct platform_device *pdev) | ||
| 130 | { | ||
| 131 | struct usb_hcd *hcd = platform_get_drvdata(pdev); | ||
| 132 | |||
| 133 | usb_remove_hcd(hcd); | ||
| 134 | iounmap(hcd->regs); | ||
| 135 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
| 136 | usb_put_hcd(hcd); | ||
| 137 | |||
| 138 | return 0; | ||
| 139 | } | ||
| 140 | |||
| 141 | static struct platform_driver ohci_hcd_ath79_driver = { | ||
| 142 | .probe = ohci_ath79_probe, | ||
| 143 | .remove = ohci_ath79_remove, | ||
| 144 | .shutdown = usb_hcd_platform_shutdown, | ||
| 145 | .driver = { | ||
| 146 | .name = "ath79-ohci", | ||
| 147 | .owner = THIS_MODULE, | ||
| 148 | }, | ||
| 149 | }; | ||
| 150 | |||
| 151 | MODULE_ALIAS(PLATFORM_MODULE_PREFIX "ath79-ohci"); | ||
diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c new file mode 100644 index 00000000000..958d985f295 --- /dev/null +++ b/drivers/usb/host/ohci-au1xxx.c | |||
| @@ -0,0 +1,319 @@ | |||
| 1 | /* | ||
| 2 | * OHCI HCD (Host Controller Driver) for USB. | ||
| 3 | * | ||
| 4 | * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> | ||
| 5 | * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net> | ||
| 6 | * (C) Copyright 2002 Hewlett-Packard Company | ||
| 7 | * | ||
| 8 | * Bus Glue for AMD Alchemy Au1xxx | ||
| 9 | * | ||
| 10 | * Written by Christopher Hoover <ch@hpl.hp.com> | ||
| 11 | * Based on fragments of previous driver by Russell King et al. | ||
| 12 | * | ||
| 13 | * Modified for LH7A404 from ohci-sa1111.c | ||
| 14 | * by Durgesh Pattamatta <pattamattad@sharpsec.com> | ||
| 15 | * Modified for AMD Alchemy Au1xxx | ||
| 16 | * by Matt Porter <mporter@kernel.crashing.org> | ||
| 17 | * | ||
| 18 | * This file is licenced under the GPL. | ||
| 19 | */ | ||
| 20 | |||
| 21 | #include <linux/platform_device.h> | ||
| 22 | #include <linux/signal.h> | ||
| 23 | |||
| 24 | #include <asm/mach-au1x00/au1000.h> | ||
| 25 | |||
| 26 | #ifndef CONFIG_SOC_AU1200 | ||
| 27 | |||
| 28 | #define USBH_ENABLE_BE (1<<0) | ||
| 29 | #define USBH_ENABLE_C (1<<1) | ||
| 30 | #define USBH_ENABLE_E (1<<2) | ||
| 31 | #define USBH_ENABLE_CE (1<<3) | ||
| 32 | #define USBH_ENABLE_RD (1<<4) | ||
| 33 | |||
| 34 | #ifdef __LITTLE_ENDIAN | ||
| 35 | #define USBH_ENABLE_INIT (USBH_ENABLE_CE | USBH_ENABLE_E | USBH_ENABLE_C) | ||
| 36 | #elif defined(__BIG_ENDIAN) | ||
| 37 | #define USBH_ENABLE_INIT (USBH_ENABLE_CE | USBH_ENABLE_E | USBH_ENABLE_C | \ | ||
| 38 | USBH_ENABLE_BE) | ||
| 39 | #else | ||
| 40 | #error not byte order defined | ||
| 41 | #endif | ||
| 42 | |||
| 43 | #else /* Au1200 */ | ||
| 44 | |||
| 45 | #define USB_HOST_CONFIG (USB_MSR_BASE + USB_MSR_MCFG) | ||
| 46 | #define USB_MCFG_PFEN (1<<31) | ||
| 47 | #define USB_MCFG_RDCOMB (1<<30) | ||
| 48 | #define USB_MCFG_SSDEN (1<<23) | ||
| 49 | #define USB_MCFG_OHCCLKEN (1<<16) | ||
| 50 | #ifdef CONFIG_DMA_COHERENT | ||
| 51 | #define USB_MCFG_UCAM (1<<7) | ||
| 52 | #else | ||
| 53 | #define USB_MCFG_UCAM (0) | ||
| 54 | #endif | ||
| 55 | #define USB_MCFG_OBMEN (1<<1) | ||
| 56 | #define USB_MCFG_OMEMEN (1<<0) | ||
| 57 | |||
| 58 | #define USBH_ENABLE_CE USB_MCFG_OHCCLKEN | ||
| 59 | |||
| 60 | #define USBH_ENABLE_INIT (USB_MCFG_PFEN | USB_MCFG_RDCOMB | \ | ||
| 61 | USBH_ENABLE_CE | USB_MCFG_SSDEN | \ | ||
| 62 | USB_MCFG_UCAM | \ | ||
| 63 | USB_MCFG_OBMEN | USB_MCFG_OMEMEN) | ||
| 64 | |||
| 65 | #define USBH_DISABLE (USB_MCFG_OBMEN | USB_MCFG_OMEMEN) | ||
| 66 | |||
| 67 | #endif /* Au1200 */ | ||
| 68 | |||
| 69 | extern int usb_disabled(void); | ||
| 70 | |||
| 71 | static void au1xxx_start_ohc(void) | ||
| 72 | { | ||
| 73 | /* enable host controller */ | ||
| 74 | #ifndef CONFIG_SOC_AU1200 | ||
| 75 | au_writel(USBH_ENABLE_CE, USB_HOST_CONFIG); | ||
| 76 | au_sync(); | ||
| 77 | udelay(1000); | ||
| 78 | |||
| 79 | au_writel(au_readl(USB_HOST_CONFIG) | USBH_ENABLE_INIT, USB_HOST_CONFIG); | ||
| 80 | au_sync(); | ||
| 81 | udelay(1000); | ||
| 82 | |||
| 83 | /* wait for reset complete (read register twice; see au1500 errata) */ | ||
| 84 | while (au_readl(USB_HOST_CONFIG), | ||
| 85 | !(au_readl(USB_HOST_CONFIG) & USBH_ENABLE_RD)) | ||
| 86 | udelay(1000); | ||
| 87 | |||
| 88 | #else /* Au1200 */ | ||
| 89 | au_writel(au_readl(USB_HOST_CONFIG) | USBH_ENABLE_CE, USB_HOST_CONFIG); | ||
| 90 | au_sync(); | ||
| 91 | udelay(1000); | ||
| 92 | |||
| 93 | au_writel(au_readl(USB_HOST_CONFIG) | USBH_ENABLE_INIT, USB_HOST_CONFIG); | ||
| 94 | au_sync(); | ||
| 95 | udelay(2000); | ||
| 96 | #endif /* Au1200 */ | ||
| 97 | } | ||
| 98 | |||
| 99 | static void au1xxx_stop_ohc(void) | ||
| 100 | { | ||
| 101 | #ifdef CONFIG_SOC_AU1200 | ||
| 102 | /* Disable mem */ | ||
| 103 | au_writel(au_readl(USB_HOST_CONFIG) & ~USBH_DISABLE, USB_HOST_CONFIG); | ||
| 104 | au_sync(); | ||
| 105 | udelay(1000); | ||
| 106 | #endif | ||
| 107 | /* Disable clock */ | ||
| 108 | au_writel(au_readl(USB_HOST_CONFIG) & ~USBH_ENABLE_CE, USB_HOST_CONFIG); | ||
| 109 | au_sync(); | ||
| 110 | } | ||
| 111 | |||
| 112 | static int __devinit ohci_au1xxx_start(struct usb_hcd *hcd) | ||
| 113 | { | ||
| 114 | struct ohci_hcd *ohci = hcd_to_ohci(hcd); | ||
| 115 | int ret; | ||
| 116 | |||
| 117 | ohci_dbg(ohci, "ohci_au1xxx_start, ohci:%p", ohci); | ||
| 118 | |||
| 119 | if ((ret = ohci_init(ohci)) < 0) | ||
| 120 | return ret; | ||
| 121 | |||
| 122 | if ((ret = ohci_run(ohci)) < 0) { | ||
| 123 | err ("can't start %s", hcd->self.bus_name); | ||
| 124 | ohci_stop(hcd); | ||
| 125 | return ret; | ||
| 126 | } | ||
| 127 | |||
| 128 | return 0; | ||
| 129 | } | ||
| 130 | |||
| 131 | static const struct hc_driver ohci_au1xxx_hc_driver = { | ||
| 132 | .description = hcd_name, | ||
| 133 | .product_desc = "Au1xxx OHCI", | ||
| 134 | .hcd_priv_size = sizeof(struct ohci_hcd), | ||
| 135 | |||
| 136 | /* | ||
| 137 | * generic hardware linkage | ||
| 138 | */ | ||
| 139 | .irq = ohci_irq, | ||
| 140 | .flags = HCD_USB11 | HCD_MEMORY, | ||
| 141 | |||
| 142 | /* | ||
| 143 | * basic lifecycle operations | ||
| 144 | */ | ||
| 145 | .start = ohci_au1xxx_start, | ||
| 146 | .stop = ohci_stop, | ||
| 147 | .shutdown = ohci_shutdown, | ||
| 148 | |||
| 149 | /* | ||
| 150 | * managing i/o requests and associated device resources | ||
| 151 | */ | ||
| 152 | .urb_enqueue = ohci_urb_enqueue, | ||
| 153 | .urb_dequeue = ohci_urb_dequeue, | ||
| 154 | .endpoint_disable = ohci_endpoint_disable, | ||
| 155 | |||
| 156 | /* | ||
| 157 | * scheduling support | ||
| 158 | */ | ||
| 159 | .get_frame_number = ohci_get_frame, | ||
| 160 | |||
| 161 | /* | ||
| 162 | * root hub support | ||
| 163 | */ | ||
| 164 | .hub_status_data = ohci_hub_status_data, | ||
| 165 | .hub_control = ohci_hub_control, | ||
| 166 | #ifdef CONFIG_PM | ||
| 167 | .bus_suspend = ohci_bus_suspend, | ||
| 168 | .bus_resume = ohci_bus_resume, | ||
| 169 | #endif | ||
| 170 | .start_port_reset = ohci_start_port_reset, | ||
| 171 | }; | ||
| 172 | |||
| 173 | static int ohci_hcd_au1xxx_drv_probe(struct platform_device *pdev) | ||
| 174 | { | ||
| 175 | int ret; | ||
| 176 | struct usb_hcd *hcd; | ||
| 177 | |||
| 178 | if (usb_disabled()) | ||
| 179 | return -ENODEV; | ||
| 180 | |||
| 181 | #if defined(CONFIG_SOC_AU1200) && defined(CONFIG_DMA_COHERENT) | ||
| 182 | /* Au1200 AB USB does not support coherent memory */ | ||
| 183 | if (!(read_c0_prid() & 0xff)) { | ||
| 184 | printk(KERN_INFO "%s: this is chip revision AB !!\n", | ||
| 185 | pdev->name); | ||
| 186 | printk(KERN_INFO "%s: update your board or re-configure " | ||
| 187 | "the kernel\n", pdev->name); | ||
| 188 | return -ENODEV; | ||
| 189 | } | ||
| 190 | #endif | ||
| 191 | |||
| 192 | if (pdev->resource[1].flags != IORESOURCE_IRQ) { | ||
| 193 | pr_debug("resource[1] is not IORESOURCE_IRQ\n"); | ||
| 194 | return -ENOMEM; | ||
| 195 | } | ||
| 196 | |||
| 197 | hcd = usb_create_hcd(&ohci_au1xxx_hc_driver, &pdev->dev, "au1xxx"); | ||
| 198 | if (!hcd) | ||
| 199 | return -ENOMEM; | ||
| 200 | |||
| 201 | hcd->rsrc_start = pdev->resource[0].start; | ||
| 202 | hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1; | ||
| 203 | |||
| 204 | if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { | ||
| 205 | pr_debug("request_mem_region failed\n"); | ||
| 206 | ret = -EBUSY; | ||
| 207 | goto err1; | ||
| 208 | } | ||
| 209 | |||
| 210 | hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); | ||
| 211 | if (!hcd->regs) { | ||
| 212 | pr_debug("ioremap failed\n"); | ||
| 213 | ret = -ENOMEM; | ||
| 214 | goto err2; | ||
| 215 | } | ||
| 216 | |||
| 217 | au1xxx_start_ohc(); | ||
| 218 | ohci_hcd_init(hcd_to_ohci(hcd)); | ||
| 219 | |||
| 220 | ret = usb_add_hcd(hcd, pdev->resource[1].start, | ||
| 221 | IRQF_DISABLED | IRQF_SHARED); | ||
| 222 | if (ret == 0) { | ||
| 223 | platform_set_drvdata(pdev, hcd); | ||
| 224 | return ret; | ||
| 225 | } | ||
| 226 | |||
| 227 | au1xxx_stop_ohc(); | ||
| 228 | iounmap(hcd->regs); | ||
| 229 | err2: | ||
| 230 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
| 231 | err1: | ||
| 232 | usb_put_hcd(hcd); | ||
| 233 | return ret; | ||
| 234 | } | ||
| 235 | |||
| 236 | static int ohci_hcd_au1xxx_drv_remove(struct platform_device *pdev) | ||
| 237 | { | ||
| 238 | struct usb_hcd *hcd = platform_get_drvdata(pdev); | ||
| 239 | |||
| 240 | usb_remove_hcd(hcd); | ||
| 241 | au1xxx_stop_ohc(); | ||
| 242 | iounmap(hcd->regs); | ||
| 243 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
| 244 | usb_put_hcd(hcd); | ||
| 245 | platform_set_drvdata(pdev, NULL); | ||
| 246 | |||
| 247 | return 0; | ||
| 248 | } | ||
| 249 | |||
| 250 | #ifdef CONFIG_PM | ||
| 251 | static int ohci_hcd_au1xxx_drv_suspend(struct device *dev) | ||
| 252 | { | ||
| 253 | struct usb_hcd *hcd = dev_get_drvdata(dev); | ||
| 254 | struct ohci_hcd *ohci = hcd_to_ohci(hcd); | ||
| 255 | unsigned long flags; | ||
| 256 | int rc; | ||
| 257 | |||
| 258 | rc = 0; | ||
| 259 | |||
| 260 | /* Root hub was already suspended. Disable irq emission and | ||
| 261 | * mark HW unaccessible, bail out if RH has been resumed. Use | ||
| 262 | * the spinlock to properly synchronize with possible pending | ||
| 263 | * RH suspend or resume activity. | ||
| 264 | * | ||
| 265 | * This is still racy as hcd->state is manipulated outside of | ||
| 266 | * any locks =P But that will be a different fix. | ||
| 267 | */ | ||
| 268 | spin_lock_irqsave(&ohci->lock, flags); | ||
| 269 | if (hcd->state != HC_STATE_SUSPENDED) { | ||
| 270 | rc = -EINVAL; | ||
| 271 | goto bail; | ||
| 272 | } | ||
| 273 | ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); | ||
| 274 | (void)ohci_readl(ohci, &ohci->regs->intrdisable); | ||
| 275 | |||
| 276 | clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); | ||
| 277 | |||
| 278 | au1xxx_stop_ohc(); | ||
| 279 | bail: | ||
| 280 | spin_unlock_irqrestore(&ohci->lock, flags); | ||
| 281 | |||
| 282 | return rc; | ||
| 283 | } | ||
| 284 | |||
| 285 | static int ohci_hcd_au1xxx_drv_resume(struct device *dev) | ||
| 286 | { | ||
| 287 | struct usb_hcd *hcd = dev_get_drvdata(dev); | ||
| 288 | |||
| 289 | au1xxx_start_ohc(); | ||
| 290 | |||
| 291 | set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); | ||
| 292 | ohci_finish_controller_resume(hcd); | ||
| 293 | |||
| 294 | return 0; | ||
| 295 | } | ||
| 296 | |||
| 297 | static const struct dev_pm_ops au1xxx_ohci_pmops = { | ||
| 298 | .suspend = ohci_hcd_au1xxx_drv_suspend, | ||
| 299 | .resume = ohci_hcd_au1xxx_drv_resume, | ||
| 300 | }; | ||
| 301 | |||
| 302 | #define AU1XXX_OHCI_PMOPS &au1xxx_ohci_pmops | ||
| 303 | |||
| 304 | #else | ||
| 305 | #define AU1XXX_OHCI_PMOPS NULL | ||
| 306 | #endif | ||
| 307 | |||
| 308 | static struct platform_driver ohci_hcd_au1xxx_driver = { | ||
| 309 | .probe = ohci_hcd_au1xxx_drv_probe, | ||
| 310 | .remove = ohci_hcd_au1xxx_drv_remove, | ||
| 311 | .shutdown = usb_hcd_platform_shutdown, | ||
| 312 | .driver = { | ||
| 313 | .name = "au1xxx-ohci", | ||
| 314 | .owner = THIS_MODULE, | ||
| 315 | .pm = AU1XXX_OHCI_PMOPS, | ||
| 316 | }, | ||
| 317 | }; | ||
| 318 | |||
| 319 | MODULE_ALIAS("platform:au1xxx-ohci"); | ||
diff --git a/drivers/usb/host/ohci-cns3xxx.c b/drivers/usb/host/ohci-cns3xxx.c new file mode 100644 index 00000000000..5a00a1e1c6c --- /dev/null +++ b/drivers/usb/host/ohci-cns3xxx.c | |||
| @@ -0,0 +1,165 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2008 Cavium Networks | ||
| 3 | * | ||
| 4 | * This file is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License, Version 2, as | ||
| 6 | * published by the Free Software Foundation. | ||
| 7 | */ | ||
| 8 | |||
| 9 | #include <linux/platform_device.h> | ||
| 10 | #include <linux/atomic.h> | ||
| 11 | #include <mach/cns3xxx.h> | ||
| 12 | #include <mach/pm.h> | ||
| 13 | |||
| 14 | static int __devinit | ||
| 15 | cns3xxx_ohci_start(struct usb_hcd *hcd) | ||
| 16 | { | ||
| 17 | struct ohci_hcd *ohci = hcd_to_ohci(hcd); | ||
| 18 | int ret; | ||
| 19 | |||
| 20 | /* | ||
| 21 | * EHCI and OHCI share the same clock and power, | ||
| 22 | * resetting twice would cause the 1st controller been reset. | ||
| 23 | * Therefore only do power up at the first up device, and | ||
| 24 | * power down at the last down device. | ||
| 25 | * | ||
| 26 | * Set USB AHB INCR length to 16 | ||
| 27 | */ | ||
| 28 | if (atomic_inc_return(&usb_pwr_ref) == 1) { | ||
| 29 | cns3xxx_pwr_power_up(1 << PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_USB); | ||
| 30 | cns3xxx_pwr_clk_en(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST); | ||
| 31 | cns3xxx_pwr_soft_rst(1 << PM_SOFT_RST_REG_OFFST_USB_HOST); | ||
| 32 | __raw_writel((__raw_readl(MISC_CHIP_CONFIG_REG) | (0X2 << 24)), | ||
| 33 | MISC_CHIP_CONFIG_REG); | ||
| 34 | } | ||
| 35 | |||
| 36 | ret = ohci_init(ohci); | ||
| 37 | if (ret < 0) | ||
| 38 | return ret; | ||
| 39 | |||
| 40 | ohci->num_ports = 1; | ||
| 41 | |||
| 42 | ret = ohci_run(ohci); | ||
| 43 | if (ret < 0) { | ||
| 44 | err("can't start %s", hcd->self.bus_name); | ||
| 45 | ohci_stop(hcd); | ||
| 46 | return ret; | ||
| 47 | } | ||
| 48 | return 0; | ||
| 49 | } | ||
| 50 | |||
| 51 | static const struct hc_driver cns3xxx_ohci_hc_driver = { | ||
| 52 | .description = hcd_name, | ||
| 53 | .product_desc = "CNS3XXX OHCI Host controller", | ||
| 54 | .hcd_priv_size = sizeof(struct ohci_hcd), | ||
| 55 | .irq = ohci_irq, | ||
| 56 | .flags = HCD_USB11 | HCD_MEMORY, | ||
| 57 | .start = cns3xxx_ohci_start, | ||
| 58 | .stop = ohci_stop, | ||
| 59 | .shutdown = ohci_shutdown, | ||
| 60 | .urb_enqueue = ohci_urb_enqueue, | ||
| 61 | .urb_dequeue = ohci_urb_dequeue, | ||
| 62 | .endpoint_disable = ohci_endpoint_disable, | ||
| 63 | .get_frame_number = ohci_get_frame, | ||
| 64 | .hub_status_data = ohci_hub_status_data, | ||
| 65 | .hub_control = ohci_hub_control, | ||
| 66 | #ifdef CONFIG_PM | ||
| 67 | .bus_suspend = ohci_bus_suspend, | ||
| 68 | .bus_resume = ohci_bus_resume, | ||
| 69 | #endif | ||
| 70 | .start_port_reset = ohci_start_port_reset, | ||
| 71 | }; | ||
| 72 | |||
| 73 | static int cns3xxx_ohci_probe(struct platform_device *pdev) | ||
| 74 | { | ||
| 75 | struct device *dev = &pdev->dev; | ||
| 76 | struct usb_hcd *hcd; | ||
| 77 | const struct hc_driver *driver = &cns3xxx_ohci_hc_driver; | ||
| 78 | struct resource *res; | ||
| 79 | int irq; | ||
| 80 | int retval; | ||
| 81 | |||
| 82 | if (usb_disabled()) | ||
| 83 | return -ENODEV; | ||
| 84 | |||
| 85 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
| 86 | if (!res) { | ||
| 87 | dev_err(dev, "Found HC with no IRQ.\n"); | ||
| 88 | return -ENODEV; | ||
| 89 | } | ||
| 90 | irq = res->start; | ||
| 91 | |||
| 92 | hcd = usb_create_hcd(driver, dev, dev_name(dev)); | ||
| 93 | if (!hcd) | ||
| 94 | return -ENOMEM; | ||
| 95 | |||
| 96 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 97 | if (!res) { | ||
| 98 | dev_err(dev, "Found HC with no register addr.\n"); | ||
| 99 | retval = -ENODEV; | ||
| 100 | goto err1; | ||
| 101 | } | ||
| 102 | hcd->rsrc_start = res->start; | ||
| 103 | hcd->rsrc_len = resource_size(res); | ||
| 104 | |||
| 105 | if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, | ||
| 106 | driver->description)) { | ||
| 107 | dev_dbg(dev, "controller already in use\n"); | ||
| 108 | retval = -EBUSY; | ||
| 109 | goto err1; | ||
| 110 | } | ||
| 111 | |||
| 112 | hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); | ||
| 113 | if (!hcd->regs) { | ||
| 114 | dev_dbg(dev, "error mapping memory\n"); | ||
| 115 | retval = -EFAULT; | ||
| 116 | goto err2; | ||
| 117 | } | ||
| 118 | |||
| 119 | ohci_hcd_init(hcd_to_ohci(hcd)); | ||
| 120 | |||
| 121 | retval = usb_add_hcd(hcd, irq, IRQF_SHARED); | ||
| 122 | if (retval == 0) | ||
| 123 | return retval; | ||
| 124 | |||
| 125 | iounmap(hcd->regs); | ||
| 126 | err2: | ||
| 127 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
| 128 | err1: | ||
| 129 | usb_put_hcd(hcd); | ||
| 130 | return retval; | ||
| 131 | } | ||
| 132 | |||
| 133 | static int cns3xxx_ohci_remove(struct platform_device *pdev) | ||
| 134 | { | ||
| 135 | struct usb_hcd *hcd = platform_get_drvdata(pdev); | ||
| 136 | |||
| 137 | usb_remove_hcd(hcd); | ||
| 138 | iounmap(hcd->regs); | ||
| 139 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
| 140 | |||
| 141 | /* | ||
| 142 | * EHCI and OHCI share the same clock and power, | ||
| 143 | * resetting twice would cause the 1st controller been reset. | ||
| 144 | * Therefore only do power up at the first up device, and | ||
| 145 | * power down at the last down device. | ||
| 146 | */ | ||
| 147 | if (atomic_dec_return(&usb_pwr_ref) == 0) | ||
| 148 | cns3xxx_pwr_clk_dis(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST); | ||
| 149 | |||
| 150 | usb_put_hcd(hcd); | ||
| 151 | |||
| 152 | platform_set_drvdata(pdev, NULL); | ||
| 153 | |||
| 154 | return 0; | ||
| 155 | } | ||
| 156 | |||
| 157 | MODULE_ALIAS("platform:cns3xxx-ohci"); | ||
| 158 | |||
| 159 | static struct platform_driver ohci_hcd_cns3xxx_driver = { | ||
| 160 | .probe = cns3xxx_ohci_probe, | ||
| 161 | .remove = cns3xxx_ohci_remove, | ||
| 162 | .driver = { | ||
| 163 | .name = "cns3xxx-ohci", | ||
| 164 | }, | ||
| 165 | }; | ||
diff --git a/drivers/usb/host/ohci-pnx4008.c b/drivers/usb/host/ohci-pnx4008.c new file mode 100644 index 00000000000..653d6a60edb --- /dev/null +++ b/drivers/usb/host/ohci-pnx4008.c | |||
| @@ -0,0 +1,453 @@ | |||
| 1 | /* | ||
| 2 | * drivers/usb/host/ohci-pnx4008.c | ||
| 3 | * | ||
| 4 | * driver for Philips PNX4008 USB Host | ||
| 5 | * | ||
| 6 | * Authors: Dmitry Chigirev <source@mvista.com> | ||
| 7 | * Vitaly Wool <vitalywool@gmail.com> | ||
| 8 | * | ||
| 9 | * register initialization is based on code examples provided by Philips | ||
| 10 | * Copyright (c) 2005 Koninklijke Philips Electronics N.V. | ||
| 11 | * | ||
| 12 | * NOTE: This driver does not have suspend/resume functionality | ||
| 13 | * This driver is intended for engineering development purposes only | ||
| 14 | * | ||
| 15 | * 2005-2006 (c) MontaVista Software, Inc. This file is licensed under | ||
| 16 | * the terms of the GNU General Public License version 2. This program | ||
| 17 | * is licensed "as is" without any warranty of any kind, whether express | ||
| 18 | * or implied. | ||
| 19 | */ | ||
| 20 | #include <linux/clk.h> | ||
| 21 | #include <linux/platform_device.h> | ||
| 22 | #include <linux/i2c.h> | ||
| 23 | |||
| 24 | #include <mach/hardware.h> | ||
| 25 | #include <asm/io.h> | ||
| 26 | |||
| 27 | #include <mach/platform.h> | ||
| 28 | #include <mach/irqs.h> | ||
| 29 | #include <mach/gpio.h> | ||
| 30 | |||
| 31 | #define USB_CTRL IO_ADDRESS(PNX4008_PWRMAN_BASE + 0x64) | ||
| 32 | |||
| 33 | /* USB_CTRL bit defines */ | ||
| 34 | #define USB_SLAVE_HCLK_EN (1 << 24) | ||
| 35 | #define USB_HOST_NEED_CLK_EN (1 << 21) | ||
| 36 | |||
| 37 | #define USB_OTG_CLK_CTRL IO_ADDRESS(PNX4008_USB_CONFIG_BASE + 0xFF4) | ||
| 38 | #define USB_OTG_CLK_STAT IO_ADDRESS(PNX4008_USB_CONFIG_BASE + 0xFF8) | ||
| 39 | |||
| 40 | /* USB_OTG_CLK_CTRL bit defines */ | ||
| 41 | #define AHB_M_CLOCK_ON (1 << 4) | ||
| 42 | #define OTG_CLOCK_ON (1 << 3) | ||
| 43 | #define I2C_CLOCK_ON (1 << 2) | ||
| 44 | #define DEV_CLOCK_ON (1 << 1) | ||
| 45 | #define HOST_CLOCK_ON (1 << 0) | ||
| 46 | |||
| 47 | #define USB_OTG_STAT_CONTROL IO_ADDRESS(PNX4008_USB_CONFIG_BASE + 0x110) | ||
| 48 | |||
| 49 | /* USB_OTG_STAT_CONTROL bit defines */ | ||
| 50 | #define TRANSPARENT_I2C_EN (1 << 7) | ||
| 51 | #define HOST_EN (1 << 0) | ||
| 52 | |||
| 53 | /* ISP1301 USB transceiver I2C registers */ | ||
| 54 | #define ISP1301_MODE_CONTROL_1 0x04 /* u8 read, set, +1 clear */ | ||
| 55 | |||
| 56 | #define MC1_SPEED_REG (1 << 0) | ||
| 57 | #define MC1_SUSPEND_REG (1 << 1) | ||
| 58 | #define MC1_DAT_SE0 (1 << 2) | ||
| 59 | #define MC1_TRANSPARENT (1 << 3) | ||
| 60 | #define MC1_BDIS_ACON_EN (1 << 4) | ||
| 61 | #define MC1_OE_INT_EN (1 << 5) | ||
| 62 | #define MC1_UART_EN (1 << 6) | ||
| 63 | #define MC1_MASK 0x7f | ||
| 64 | |||
| 65 | #define ISP1301_MODE_CONTROL_2 0x12 /* u8 read, set, +1 clear */ | ||
| 66 | |||
| 67 | #define MC2_GLOBAL_PWR_DN (1 << 0) | ||
| 68 | #define MC2_SPD_SUSP_CTRL (1 << 1) | ||
| 69 | #define MC2_BI_DI (1 << 2) | ||
| 70 | #define MC2_TRANSP_BDIR0 (1 << 3) | ||
| 71 | #define MC2_TRANSP_BDIR1 (1 << 4) | ||
| 72 | #define MC2_AUDIO_EN (1 << 5) | ||
| 73 | #define MC2_PSW_EN (1 << 6) | ||
| 74 | #define MC2_EN2V7 (1 << 7) | ||
| 75 | |||
| 76 | #define ISP1301_OTG_CONTROL_1 0x06 /* u8 read, set, +1 clear */ | ||
| 77 | # define OTG1_DP_PULLUP (1 << 0) | ||
| 78 | # define OTG1_DM_PULLUP (1 << 1) | ||
| 79 | # define OTG1_DP_PULLDOWN (1 << 2) | ||
| 80 | # define OTG1_DM_PULLDOWN (1 << 3) | ||
| 81 | # define OTG1_ID_PULLDOWN (1 << 4) | ||
| 82 | # define OTG1_VBUS_DRV (1 << 5) | ||
| 83 | # define OTG1_VBUS_DISCHRG (1 << 6) | ||
| 84 | # define OTG1_VBUS_CHRG (1 << 7) | ||
| 85 | #define ISP1301_OTG_STATUS 0x10 /* u8 readonly */ | ||
| 86 | # define OTG_B_SESS_END (1 << 6) | ||
| 87 | # define OTG_B_SESS_VLD (1 << 7) | ||
| 88 | |||
| 89 | #define ISP1301_I2C_ADDR 0x2C | ||
| 90 | |||
| 91 | #define ISP1301_I2C_MODE_CONTROL_1 0x4 | ||
| 92 | #define ISP1301_I2C_MODE_CONTROL_2 0x12 | ||
| 93 | #define ISP1301_I2C_OTG_CONTROL_1 0x6 | ||
| 94 | #define ISP1301_I2C_OTG_CONTROL_2 0x10 | ||
| 95 | #define ISP1301_I2C_INTERRUPT_SOURCE 0x8 | ||
| 96 | #define ISP1301_I2C_INTERRUPT_LATCH 0xA | ||
| 97 | #define ISP1301_I2C_INTERRUPT_FALLING 0xC | ||
| 98 | #define ISP1301_I2C_INTERRUPT_RISING 0xE | ||
| 99 | #define ISP1301_I2C_REG_CLEAR_ADDR 1 | ||
| 100 | |||
| 101 | static struct i2c_driver isp1301_driver; | ||
| 102 | static struct i2c_client *isp1301_i2c_client; | ||
| 103 | |||
| 104 | extern int usb_disabled(void); | ||
| 105 | extern int ocpi_enable(void); | ||
| 106 | |||
| 107 | static struct clk *usb_clk; | ||
| 108 | |||
| 109 | static const unsigned short normal_i2c[] = | ||
| 110 | { ISP1301_I2C_ADDR, ISP1301_I2C_ADDR + 1, I2C_CLIENT_END }; | ||
| 111 | |||
| 112 | static int isp1301_probe(struct i2c_client *client, | ||
| 113 | const struct i2c_device_id *id) | ||
| 114 | { | ||
| 115 | return 0; | ||
| 116 | } | ||
| 117 | |||
| 118 | static int isp1301_remove(struct i2c_client *client) | ||
| 119 | { | ||
| 120 | return 0; | ||
| 121 | } | ||
| 122 | |||
| 123 | static const struct i2c_device_id isp1301_id[] = { | ||
| 124 | { "isp1301_pnx", 0 }, | ||
| 125 | { } | ||
| 126 | }; | ||
| 127 | |||
| 128 | static struct i2c_driver isp1301_driver = { | ||
| 129 | .driver = { | ||
| 130 | .name = "isp1301_pnx", | ||
| 131 | }, | ||
| 132 | .probe = isp1301_probe, | ||
| 133 | .remove = isp1301_remove, | ||
| 134 | .id_table = isp1301_id, | ||
| 135 | }; | ||
| 136 | |||
| 137 | static void i2c_write(u8 buf, u8 subaddr) | ||
| 138 | { | ||
| 139 | char tmpbuf[2]; | ||
| 140 | |||
| 141 | tmpbuf[0] = subaddr; /*register number */ | ||
| 142 | tmpbuf[1] = buf; /*register data */ | ||
| 143 | i2c_master_send(isp1301_i2c_client, &tmpbuf[0], 2); | ||
| 144 | } | ||
| 145 | |||
| 146 | static void isp1301_configure(void) | ||
| 147 | { | ||
| 148 | /* PNX4008 only supports DAT_SE0 USB mode */ | ||
| 149 | /* PNX4008 R2A requires setting the MAX603 to output 3.6V */ | ||
| 150 | /* Power up externel charge-pump */ | ||
| 151 | |||
| 152 | i2c_write(MC1_DAT_SE0 | MC1_SPEED_REG, ISP1301_I2C_MODE_CONTROL_1); | ||
| 153 | i2c_write(~(MC1_DAT_SE0 | MC1_SPEED_REG), | ||
| 154 | ISP1301_I2C_MODE_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR); | ||
| 155 | i2c_write(MC2_BI_DI | MC2_PSW_EN | MC2_SPD_SUSP_CTRL, | ||
| 156 | ISP1301_I2C_MODE_CONTROL_2); | ||
| 157 | i2c_write(~(MC2_BI_DI | MC2_PSW_EN | MC2_SPD_SUSP_CTRL), | ||
| 158 | ISP1301_I2C_MODE_CONTROL_2 | ISP1301_I2C_REG_CLEAR_ADDR); | ||
| 159 | i2c_write(OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN, | ||
| 160 | ISP1301_I2C_OTG_CONTROL_1); | ||
| 161 | i2c_write(~(OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN), | ||
| 162 | ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR); | ||
| 163 | i2c_write(0xFF, | ||
| 164 | ISP1301_I2C_INTERRUPT_LATCH | ISP1301_I2C_REG_CLEAR_ADDR); | ||
| 165 | i2c_write(0xFF, | ||
| 166 | ISP1301_I2C_INTERRUPT_FALLING | ISP1301_I2C_REG_CLEAR_ADDR); | ||
| 167 | i2c_write(0xFF, | ||
| 168 | ISP1301_I2C_INTERRUPT_RISING | ISP1301_I2C_REG_CLEAR_ADDR); | ||
| 169 | |||
| 170 | } | ||
| 171 | |||
| 172 | static inline void isp1301_vbus_on(void) | ||
| 173 | { | ||
| 174 | i2c_write(OTG1_VBUS_DRV, ISP1301_I2C_OTG_CONTROL_1); | ||
| 175 | } | ||
| 176 | |||
| 177 | static inline void isp1301_vbus_off(void) | ||
| 178 | { | ||
| 179 | i2c_write(OTG1_VBUS_DRV, | ||
| 180 | ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR); | ||
| 181 | } | ||
| 182 | |||
| 183 | static void pnx4008_start_hc(void) | ||
| 184 | { | ||
| 185 | unsigned long tmp = __raw_readl(USB_OTG_STAT_CONTROL) | HOST_EN; | ||
| 186 | __raw_writel(tmp, USB_OTG_STAT_CONTROL); | ||
| 187 | isp1301_vbus_on(); | ||
| 188 | } | ||
| 189 | |||
| 190 | static void pnx4008_stop_hc(void) | ||
| 191 | { | ||
| 192 | unsigned long tmp; | ||
| 193 | isp1301_vbus_off(); | ||
| 194 | tmp = __raw_readl(USB_OTG_STAT_CONTROL) & ~HOST_EN; | ||
| 195 | __raw_writel(tmp, USB_OTG_STAT_CONTROL); | ||
| 196 | } | ||
| 197 | |||
| 198 | static int __devinit ohci_pnx4008_start(struct usb_hcd *hcd) | ||
| 199 | { | ||
| 200 | struct ohci_hcd *ohci = hcd_to_ohci(hcd); | ||
| 201 | int ret; | ||
| 202 | |||
| 203 | if ((ret = ohci_init(ohci)) < 0) | ||
| 204 | return ret; | ||
| 205 | |||
| 206 | if ((ret = ohci_run(ohci)) < 0) { | ||
| 207 | dev_err(hcd->self.controller, "can't start\n"); | ||
| 208 | ohci_stop(hcd); | ||
| 209 | return ret; | ||
| 210 | } | ||
| 211 | return 0; | ||
| 212 | } | ||
| 213 | |||
| 214 | static const struct hc_driver ohci_pnx4008_hc_driver = { | ||
| 215 | .description = hcd_name, | ||
| 216 | .product_desc = "pnx4008 OHCI", | ||
| 217 | |||
| 218 | /* | ||
| 219 | * generic hardware linkage | ||
| 220 | */ | ||
| 221 | .irq = ohci_irq, | ||
| 222 | .flags = HCD_USB11 | HCD_MEMORY, | ||
| 223 | |||
| 224 | .hcd_priv_size = sizeof(struct ohci_hcd), | ||
| 225 | /* | ||
| 226 | * basic lifecycle operations | ||
| 227 | */ | ||
| 228 | .start = ohci_pnx4008_start, | ||
| 229 | .stop = ohci_stop, | ||
| 230 | .shutdown = ohci_shutdown, | ||
| 231 | |||
| 232 | /* | ||
| 233 | * managing i/o requests and associated device resources | ||
| 234 | */ | ||
| 235 | .urb_enqueue = ohci_urb_enqueue, | ||
| 236 | .urb_dequeue = ohci_urb_dequeue, | ||
| 237 | .endpoint_disable = ohci_endpoint_disable, | ||
| 238 | |||
| 239 | /* | ||
| 240 | * scheduling support | ||
| 241 | */ | ||
| 242 | .get_frame_number = ohci_get_frame, | ||
| 243 | |||
| 244 | /* | ||
| 245 | * root hub support | ||
| 246 | */ | ||
| 247 | .hub_status_data = ohci_hub_status_data, | ||
| 248 | .hub_control = ohci_hub_control, | ||
| 249 | #ifdef CONFIG_PM | ||
| 250 | .bus_suspend = ohci_bus_suspend, | ||
| 251 | .bus_resume = ohci_bus_resume, | ||
| 252 | #endif | ||
| 253 | .start_port_reset = ohci_start_port_reset, | ||
| 254 | }; | ||
| 255 | |||
| 256 | #define USB_CLOCK_MASK (AHB_M_CLOCK_ON| OTG_CLOCK_ON | HOST_CLOCK_ON | I2C_CLOCK_ON) | ||
| 257 | |||
| 258 | static void pnx4008_set_usb_bits(void) | ||
| 259 | { | ||
| 260 | start_int_set_falling_edge(SE_USB_OTG_ATX_INT_N); | ||
| 261 | start_int_ack(SE_USB_OTG_ATX_INT_N); | ||
| 262 | start_int_umask(SE_USB_OTG_ATX_INT_N); | ||
| 263 | |||
| 264 | start_int_set_rising_edge(SE_USB_OTG_TIMER_INT); | ||
| 265 | start_int_ack(SE_USB_OTG_TIMER_INT); | ||
| 266 | start_int_umask(SE_USB_OTG_TIMER_INT); | ||
| 267 | |||
| 268 | start_int_set_rising_edge(SE_USB_I2C_INT); | ||
| 269 | start_int_ack(SE_USB_I2C_INT); | ||
| 270 | start_int_umask(SE_USB_I2C_INT); | ||
| 271 | |||
| 272 | start_int_set_rising_edge(SE_USB_INT); | ||
| 273 | start_int_ack(SE_USB_INT); | ||
| 274 | start_int_umask(SE_USB_INT); | ||
| 275 | |||
| 276 | start_int_set_rising_edge(SE_USB_NEED_CLK_INT); | ||
| 277 | start_int_ack(SE_USB_NEED_CLK_INT); | ||
| 278 | start_int_umask(SE_USB_NEED_CLK_INT); | ||
| 279 | |||
| 280 | start_int_set_rising_edge(SE_USB_AHB_NEED_CLK_INT); | ||
| 281 | start_int_ack(SE_USB_AHB_NEED_CLK_INT); | ||
| 282 | start_int_umask(SE_USB_AHB_NEED_CLK_INT); | ||
| 283 | } | ||
| 284 | |||
| 285 | static void pnx4008_unset_usb_bits(void) | ||
| 286 | { | ||
| 287 | start_int_mask(SE_USB_OTG_ATX_INT_N); | ||
| 288 | start_int_mask(SE_USB_OTG_TIMER_INT); | ||
| 289 | start_int_mask(SE_USB_I2C_INT); | ||
| 290 | start_int_mask(SE_USB_INT); | ||
| 291 | start_int_mask(SE_USB_NEED_CLK_INT); | ||
| 292 | start_int_mask(SE_USB_AHB_NEED_CLK_INT); | ||
| 293 | } | ||
| 294 | |||
| 295 | static int __devinit usb_hcd_pnx4008_probe(struct platform_device *pdev) | ||
| 296 | { | ||
| 297 | struct usb_hcd *hcd = 0; | ||
| 298 | struct ohci_hcd *ohci; | ||
| 299 | const struct hc_driver *driver = &ohci_pnx4008_hc_driver; | ||
| 300 | struct i2c_adapter *i2c_adap; | ||
| 301 | struct i2c_board_info i2c_info; | ||
| 302 | |||
| 303 | int ret = 0, irq; | ||
| 304 | |||
| 305 | dev_dbg(&pdev->dev, "%s: " DRIVER_DESC " (pnx4008)\n", hcd_name); | ||
| 306 | if (usb_disabled()) { | ||
| 307 | err("USB is disabled"); | ||
| 308 | ret = -ENODEV; | ||
| 309 | goto out; | ||
| 310 | } | ||
| 311 | |||
| 312 | if (pdev->num_resources != 2 | ||
| 313 | || pdev->resource[0].flags != IORESOURCE_MEM | ||
| 314 | || pdev->resource[1].flags != IORESOURCE_IRQ) { | ||
| 315 | err("Invalid resource configuration"); | ||
| 316 | ret = -ENODEV; | ||
| 317 | goto out; | ||
| 318 | } | ||
| 319 | |||
| 320 | /* Enable AHB slave USB clock, needed for further USB clock control */ | ||
| 321 | __raw_writel(USB_SLAVE_HCLK_EN | (1 << 19), USB_CTRL); | ||
| 322 | |||
| 323 | ret = i2c_add_driver(&isp1301_driver); | ||
| 324 | if (ret < 0) { | ||
| 325 | err("failed to add ISP1301 driver"); | ||
| 326 | goto out; | ||
| 327 | } | ||
| 328 | i2c_adap = i2c_get_adapter(2); | ||
| 329 | memset(&i2c_info, 0, sizeof(struct i2c_board_info)); | ||
| 330 | strlcpy(i2c_info.type, "isp1301_pnx", I2C_NAME_SIZE); | ||
| 331 | isp1301_i2c_client = i2c_new_probed_device(i2c_adap, &i2c_info, | ||
| 332 | normal_i2c, NULL); | ||
| 333 | i2c_put_adapter(i2c_adap); | ||
| 334 | if (!isp1301_i2c_client) { | ||
| 335 | err("failed to connect I2C to ISP1301 USB Transceiver"); | ||
| 336 | ret = -ENODEV; | ||
| 337 | goto out_i2c_driver; | ||
| 338 | } | ||
| 339 | |||
| 340 | isp1301_configure(); | ||
| 341 | |||
| 342 | /* Enable USB PLL */ | ||
| 343 | usb_clk = clk_get(&pdev->dev, "ck_pll5"); | ||
| 344 | if (IS_ERR(usb_clk)) { | ||
| 345 | err("failed to acquire USB PLL"); | ||
| 346 | ret = PTR_ERR(usb_clk); | ||
| 347 | goto out1; | ||
| 348 | } | ||
| 349 | |||
| 350 | ret = clk_enable(usb_clk); | ||
| 351 | if (ret < 0) { | ||
| 352 | err("failed to start USB PLL"); | ||
| 353 | goto out2; | ||
| 354 | } | ||
| 355 | |||
| 356 | ret = clk_set_rate(usb_clk, 48000); | ||
| 357 | if (ret < 0) { | ||
| 358 | err("failed to set USB clock rate"); | ||
| 359 | goto out3; | ||
| 360 | } | ||
| 361 | |||
| 362 | __raw_writel(__raw_readl(USB_CTRL) | USB_HOST_NEED_CLK_EN, USB_CTRL); | ||
| 363 | |||
| 364 | /* Set to enable all needed USB clocks */ | ||
| 365 | __raw_writel(USB_CLOCK_MASK, USB_OTG_CLK_CTRL); | ||
| 366 | |||
| 367 | while ((__raw_readl(USB_OTG_CLK_STAT) & USB_CLOCK_MASK) != | ||
| 368 | USB_CLOCK_MASK) ; | ||
| 369 | |||
| 370 | hcd = usb_create_hcd (driver, &pdev->dev, dev_name(&pdev->dev)); | ||
| 371 | if (!hcd) { | ||
| 372 | err("Failed to allocate HC buffer"); | ||
| 373 | ret = -ENOMEM; | ||
| 374 | goto out3; | ||
| 375 | } | ||
| 376 | |||
| 377 | /* Set all USB bits in the Start Enable register */ | ||
| 378 | pnx4008_set_usb_bits(); | ||
| 379 | |||
| 380 | hcd->rsrc_start = pdev->resource[0].start; | ||
| 381 | hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1; | ||
| 382 | if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { | ||
| 383 | dev_dbg(&pdev->dev, "request_mem_region failed\n"); | ||
| 384 | ret = -ENOMEM; | ||
| 385 | goto out4; | ||
| 386 | } | ||
| 387 | hcd->regs = (void __iomem *)pdev->resource[0].start; | ||
| 388 | |||
| 389 | irq = platform_get_irq(pdev, 0); | ||
| 390 | if (irq < 0) { | ||
| 391 | ret = -ENXIO; | ||
| 392 | goto out4; | ||
| 393 | } | ||
| 394 | |||
| 395 | pnx4008_start_hc(); | ||
| 396 | platform_set_drvdata(pdev, hcd); | ||
| 397 | ohci = hcd_to_ohci(hcd); | ||
| 398 | ohci_hcd_init(ohci); | ||
| 399 | |||
| 400 | dev_info(&pdev->dev, "at 0x%p, irq %d\n", hcd->regs, hcd->irq); | ||
| 401 | ret = usb_add_hcd(hcd, irq, IRQF_DISABLED); | ||
| 402 | if (ret == 0) | ||
| 403 | return ret; | ||
| 404 | |||
| 405 | pnx4008_stop_hc(); | ||
| 406 | out4: | ||
| 407 | pnx4008_unset_usb_bits(); | ||
| 408 | usb_put_hcd(hcd); | ||
| 409 | out3: | ||
| 410 | clk_disable(usb_clk); | ||
| 411 | out2: | ||
| 412 | clk_put(usb_clk); | ||
| 413 | out1: | ||
| 414 | i2c_unregister_device(isp1301_i2c_client); | ||
| 415 | isp1301_i2c_client = NULL; | ||
| 416 | out_i2c_driver: | ||
| 417 | i2c_del_driver(&isp1301_driver); | ||
| 418 | out: | ||
| 419 | return ret; | ||
| 420 | } | ||
| 421 | |||
| 422 | static int usb_hcd_pnx4008_remove(struct platform_device *pdev) | ||
| 423 | { | ||
| 424 | struct usb_hcd *hcd = platform_get_drvdata(pdev); | ||
| 425 | |||
| 426 | usb_remove_hcd(hcd); | ||
| 427 | pnx4008_stop_hc(); | ||
| 428 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
| 429 | usb_put_hcd(hcd); | ||
| 430 | pnx4008_unset_usb_bits(); | ||
| 431 | clk_disable(usb_clk); | ||
| 432 | clk_put(usb_clk); | ||
| 433 | i2c_unregister_device(isp1301_i2c_client); | ||
| 434 | isp1301_i2c_client = NULL; | ||
| 435 | i2c_del_driver(&isp1301_driver); | ||
| 436 | |||
| 437 | platform_set_drvdata(pdev, NULL); | ||
| 438 | |||
| 439 | return 0; | ||
| 440 | } | ||
| 441 | |||
| 442 | /* work with hotplug and coldplug */ | ||
| 443 | MODULE_ALIAS("platform:usb-ohci"); | ||
| 444 | |||
| 445 | static struct platform_driver usb_hcd_pnx4008_driver = { | ||
| 446 | .driver = { | ||
| 447 | .name = "usb-ohci", | ||
| 448 | .owner = THIS_MODULE, | ||
| 449 | }, | ||
| 450 | .probe = usb_hcd_pnx4008_probe, | ||
| 451 | .remove = usb_hcd_pnx4008_remove, | ||
| 452 | }; | ||
| 453 | |||
diff --git a/drivers/usb/host/ohci-pnx8550.c b/drivers/usb/host/ohci-pnx8550.c new file mode 100644 index 00000000000..28467e288a9 --- /dev/null +++ b/drivers/usb/host/ohci-pnx8550.c | |||
| @@ -0,0 +1,242 @@ | |||
| 1 | /* | ||
| 2 | * OHCI HCD (Host Controller Driver) for USB. | ||
| 3 | * | ||
| 4 | * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> | ||
| 5 | * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net> | ||
| 6 | * (C) Copyright 2002 Hewlett-Packard Company | ||
| 7 | * (C) Copyright 2005 Embedded Alley Solutions, Inc. | ||
| 8 | * | ||
| 9 | * Bus Glue for PNX8550 | ||
| 10 | * | ||
| 11 | * Written by Christopher Hoover <ch@hpl.hp.com> | ||
| 12 | * Based on fragments of previous driver by Russell King et al. | ||
| 13 | * | ||
| 14 | * Modified for LH7A404 from ohci-sa1111.c | ||
| 15 | * by Durgesh Pattamatta <pattamattad@sharpsec.com> | ||
| 16 | * | ||
| 17 | * Modified for PNX8550 from ohci-sa1111.c and sa-omap.c | ||
| 18 | * by Vitaly Wool <vitalywool@gmail.com> | ||
| 19 | * | ||
| 20 | * This file is licenced under the GPL. | ||
| 21 | */ | ||
| 22 | |||
| 23 | #include <linux/device.h> | ||
| 24 | #include <linux/platform_device.h> | ||
| 25 | #include <asm/mach-pnx8550/usb.h> | ||
| 26 | #include <asm/mach-pnx8550/int.h> | ||
| 27 | #include <asm/mach-pnx8550/pci.h> | ||
| 28 | |||
| 29 | #ifndef CONFIG_PNX8550 | ||
| 30 | #error "This file is PNX8550 bus glue. CONFIG_PNX8550 must be defined." | ||
| 31 | #endif | ||
| 32 | |||
| 33 | extern int usb_disabled(void); | ||
| 34 | |||
| 35 | /*-------------------------------------------------------------------------*/ | ||
| 36 | |||
| 37 | static void pnx8550_start_hc(struct platform_device *dev) | ||
| 38 | { | ||
| 39 | /* | ||
| 40 | * Set register CLK48CTL to enable and 48MHz | ||
| 41 | */ | ||
| 42 | outl(0x00000003, PCI_BASE | 0x0004770c); | ||
| 43 | |||
| 44 | /* | ||
| 45 | * Set register CLK12CTL to enable and 48MHz | ||
| 46 | */ | ||
| 47 | outl(0x00000003, PCI_BASE | 0x00047710); | ||
| 48 | |||
| 49 | udelay(100); | ||
| 50 | } | ||
| 51 | |||
| 52 | static void pnx8550_stop_hc(struct platform_device *dev) | ||
| 53 | { | ||
| 54 | udelay(10); | ||
| 55 | } | ||
| 56 | |||
| 57 | |||
| 58 | /*-------------------------------------------------------------------------*/ | ||
| 59 | |||
| 60 | /* configure so an HC device and id are always provided */ | ||
| 61 | /* always called with process context; sleeping is OK */ | ||
| 62 | |||
| 63 | |||
| 64 | /** | ||
| 65 | * usb_hcd_pnx8550_probe - initialize pnx8550-based HCDs | ||
| 66 | * Context: !in_interrupt() | ||
| 67 | * | ||
| 68 | * Allocates basic resources for this USB host controller, and | ||
| 69 | * then invokes the start() method for the HCD associated with it | ||
| 70 | * through the hotplug entry's driver_data. | ||
| 71 | * | ||
| 72 | */ | ||
| 73 | int usb_hcd_pnx8550_probe (const struct hc_driver *driver, | ||
| 74 | struct platform_device *dev) | ||
| 75 | { | ||
| 76 | int retval; | ||
| 77 | struct usb_hcd *hcd; | ||
| 78 | |||
| 79 | if (dev->resource[0].flags != IORESOURCE_MEM || | ||
| 80 | dev->resource[1].flags != IORESOURCE_IRQ) { | ||
| 81 | dev_err (&dev->dev,"invalid resource type\n"); | ||
| 82 | return -ENOMEM; | ||
| 83 | } | ||
| 84 | |||
| 85 | hcd = usb_create_hcd (driver, &dev->dev, "pnx8550"); | ||
| 86 | if (!hcd) | ||
| 87 | return -ENOMEM; | ||
| 88 | hcd->rsrc_start = dev->resource[0].start; | ||
| 89 | hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1; | ||
| 90 | |||
| 91 | if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { | ||
| 92 | dev_err(&dev->dev, "request_mem_region [0x%08llx, 0x%08llx] " | ||
| 93 | "failed\n", hcd->rsrc_start, hcd->rsrc_len); | ||
| 94 | retval = -EBUSY; | ||
| 95 | goto err1; | ||
| 96 | } | ||
| 97 | |||
| 98 | hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); | ||
| 99 | if (!hcd->regs) { | ||
| 100 | dev_err(&dev->dev, "ioremap [[0x%08llx, 0x%08llx] failed\n", | ||
| 101 | hcd->rsrc_start, hcd->rsrc_len); | ||
| 102 | retval = -ENOMEM; | ||
| 103 | goto err2; | ||
| 104 | } | ||
| 105 | |||
| 106 | pnx8550_start_hc(dev); | ||
| 107 | |||
| 108 | ohci_hcd_init(hcd_to_ohci(hcd)); | ||
| 109 | |||
| 110 | retval = usb_add_hcd(hcd, dev->resource[1].start, IRQF_DISABLED); | ||
| 111 | if (retval == 0) | ||
| 112 | return retval; | ||
| 113 | |||
| 114 | pnx8550_stop_hc(dev); | ||
| 115 | iounmap(hcd->regs); | ||
| 116 | err2: | ||
| 117 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
| 118 | err1: | ||
| 119 | usb_put_hcd(hcd); | ||
| 120 | return retval; | ||
| 121 | } | ||
| 122 | |||
| 123 | |||
| 124 | /* may be called without controller electrically present */ | ||
| 125 | /* may be called with controller, bus, and devices active */ | ||
| 126 | |||
| 127 | /** | ||
| 128 | * usb_hcd_pnx8550_remove - shutdown processing for pnx8550-based HCDs | ||
| 129 | * @dev: USB Host Controller being removed | ||
| 130 | * Context: !in_interrupt() | ||
| 131 | * | ||
| 132 | * Reverses the effect of usb_hcd_pnx8550_probe(), first invoking | ||
| 133 | * the HCD's stop() method. It is always called from a thread | ||
| 134 | * context, normally "rmmod", "apmd", or something similar. | ||
| 135 | * | ||
| 136 | */ | ||
| 137 | void usb_hcd_pnx8550_remove (struct usb_hcd *hcd, struct platform_device *dev) | ||
| 138 | { | ||
| 139 | usb_remove_hcd(hcd); | ||
| 140 | pnx8550_stop_hc(dev); | ||
| 141 | iounmap(hcd->regs); | ||
| 142 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
| 143 | usb_put_hcd(hcd); | ||
| 144 | } | ||
| 145 | |||
| 146 | /*-------------------------------------------------------------------------*/ | ||
| 147 | |||
| 148 | static int __devinit | ||
| 149 | ohci_pnx8550_start (struct usb_hcd *hcd) | ||
| 150 | { | ||
| 151 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | ||
| 152 | int ret; | ||
| 153 | |||
| 154 | ohci_dbg (ohci, "ohci_pnx8550_start, ohci:%p", ohci); | ||
| 155 | |||
| 156 | if ((ret = ohci_init(ohci)) < 0) | ||
| 157 | return ret; | ||
| 158 | |||
| 159 | if ((ret = ohci_run (ohci)) < 0) { | ||
| 160 | err ("can't start %s", hcd->self.bus_name); | ||
| 161 | ohci_stop (hcd); | ||
| 162 | return ret; | ||
| 163 | } | ||
| 164 | |||
| 165 | return 0; | ||
| 166 | } | ||
| 167 | |||
| 168 | /*-------------------------------------------------------------------------*/ | ||
| 169 | |||
| 170 | static const struct hc_driver ohci_pnx8550_hc_driver = { | ||
| 171 | .description = hcd_name, | ||
| 172 | .product_desc = "PNX8550 OHCI", | ||
| 173 | .hcd_priv_size = sizeof(struct ohci_hcd), | ||
| 174 | |||
| 175 | /* | ||
| 176 | * generic hardware linkage | ||
| 177 | */ | ||
| 178 | .irq = ohci_irq, | ||
| 179 | .flags = HCD_USB11 | HCD_MEMORY, | ||
| 180 | |||
| 181 | /* | ||
| 182 | * basic lifecycle operations | ||
| 183 | */ | ||
| 184 | .start = ohci_pnx8550_start, | ||
| 185 | .stop = ohci_stop, | ||
| 186 | |||
| 187 | /* | ||
| 188 | * managing i/o requests and associated device resources | ||
| 189 | */ | ||
| 190 | .urb_enqueue = ohci_urb_enqueue, | ||
| 191 | .urb_dequeue = ohci_urb_dequeue, | ||
| 192 | .endpoint_disable = ohci_endpoint_disable, | ||
| 193 | |||
| 194 | /* | ||
| 195 | * scheduling support | ||
| 196 | */ | ||
| 197 | .get_frame_number = ohci_get_frame, | ||
| 198 | |||
| 199 | /* | ||
| 200 | * root hub support | ||
| 201 | */ | ||
| 202 | .hub_status_data = ohci_hub_status_data, | ||
| 203 | .hub_control = ohci_hub_control, | ||
| 204 | #ifdef CONFIG_PM | ||
| 205 | .bus_suspend = ohci_bus_suspend, | ||
| 206 | .bus_resume = ohci_bus_resume, | ||
| 207 | #endif | ||
| 208 | .start_port_reset = ohci_start_port_reset, | ||
| 209 | }; | ||
| 210 | |||
| 211 | /*-------------------------------------------------------------------------*/ | ||
| 212 | |||
| 213 | static int ohci_hcd_pnx8550_drv_probe(struct platform_device *pdev) | ||
| 214 | { | ||
| 215 | int ret; | ||
| 216 | |||
| 217 | if (usb_disabled()) | ||
| 218 | return -ENODEV; | ||
| 219 | |||
| 220 | ret = usb_hcd_pnx8550_probe(&ohci_pnx8550_hc_driver, pdev); | ||
| 221 | return ret; | ||
| 222 | } | ||
| 223 | |||
| 224 | static int ohci_hcd_pnx8550_drv_remove(struct platform_device *pdev) | ||
| 225 | { | ||
| 226 | struct usb_hcd *hcd = platform_get_drvdata(pdev); | ||
| 227 | |||
| 228 | usb_hcd_pnx8550_remove(hcd, pdev); | ||
| 229 | return 0; | ||
| 230 | } | ||
| 231 | |||
| 232 | MODULE_ALIAS("platform:pnx8550-ohci"); | ||
| 233 | |||
| 234 | static struct platform_driver ohci_hcd_pnx8550_driver = { | ||
| 235 | .driver = { | ||
| 236 | .name = "pnx8550-ohci", | ||
| 237 | .owner = THIS_MODULE, | ||
| 238 | }, | ||
| 239 | .probe = ohci_hcd_pnx8550_drv_probe, | ||
| 240 | .remove = ohci_hcd_pnx8550_drv_remove, | ||
| 241 | }; | ||
| 242 | |||
diff --git a/drivers/usb/host/ohci-ppc-soc.c b/drivers/usb/host/ohci-ppc-soc.c new file mode 100644 index 00000000000..c0f595c4448 --- /dev/null +++ b/drivers/usb/host/ohci-ppc-soc.c | |||
| @@ -0,0 +1,215 @@ | |||
| 1 | /* | ||
| 2 | * OHCI HCD (Host Controller Driver) for USB. | ||
| 3 | * | ||
| 4 | * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> | ||
| 5 | * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net> | ||
| 6 | * (C) Copyright 2002 Hewlett-Packard Company | ||
| 7 | * (C) Copyright 2003-2005 MontaVista Software Inc. | ||
| 8 | * | ||
| 9 | * Bus Glue for PPC On-Chip OHCI driver | ||
| 10 | * Tested on Freescale MPC5200 and IBM STB04xxx | ||
| 11 | * | ||
| 12 | * Modified by Dale Farnsworth <dale@farnsworth.org> from ohci-sa1111.c | ||
| 13 | * | ||
| 14 | * This file is licenced under the GPL. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/platform_device.h> | ||
| 18 | #include <linux/signal.h> | ||
| 19 | |||
| 20 | /* configure so an HC device and id are always provided */ | ||
| 21 | /* always called with process context; sleeping is OK */ | ||
| 22 | |||
| 23 | /** | ||
| 24 | * usb_hcd_ppc_soc_probe - initialize On-Chip HCDs | ||
| 25 | * Context: !in_interrupt() | ||
| 26 | * | ||
| 27 | * Allocates basic resources for this USB host controller. | ||
| 28 | * | ||
| 29 | * Store this function in the HCD's struct pci_driver as probe(). | ||
| 30 | */ | ||
| 31 | static int usb_hcd_ppc_soc_probe(const struct hc_driver *driver, | ||
| 32 | struct platform_device *pdev) | ||
| 33 | { | ||
| 34 | int retval; | ||
| 35 | struct usb_hcd *hcd; | ||
| 36 | struct ohci_hcd *ohci; | ||
| 37 | struct resource *res; | ||
| 38 | int irq; | ||
| 39 | |||
| 40 | pr_debug("initializing PPC-SOC USB Controller\n"); | ||
| 41 | |||
| 42 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
| 43 | if (!res) { | ||
| 44 | pr_debug("%s: no irq\n", __FILE__); | ||
| 45 | return -ENODEV; | ||
| 46 | } | ||
| 47 | irq = res->start; | ||
| 48 | |||
| 49 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 50 | if (!res) { | ||
| 51 | pr_debug("%s: no reg addr\n", __FILE__); | ||
| 52 | return -ENODEV; | ||
| 53 | } | ||
| 54 | |||
| 55 | hcd = usb_create_hcd(driver, &pdev->dev, "PPC-SOC USB"); | ||
| 56 | if (!hcd) | ||
| 57 | return -ENOMEM; | ||
| 58 | hcd->rsrc_start = res->start; | ||
| 59 | hcd->rsrc_len = resource_size(res); | ||
| 60 | |||
| 61 | if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { | ||
| 62 | pr_debug("%s: request_mem_region failed\n", __FILE__); | ||
| 63 | retval = -EBUSY; | ||
| 64 | goto err1; | ||
| 65 | } | ||
| 66 | |||
| 67 | hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); | ||
| 68 | if (!hcd->regs) { | ||
| 69 | pr_debug("%s: ioremap failed\n", __FILE__); | ||
| 70 | retval = -ENOMEM; | ||
| 71 | goto err2; | ||
| 72 | } | ||
| 73 | |||
| 74 | ohci = hcd_to_ohci(hcd); | ||
| 75 | ohci->flags |= OHCI_QUIRK_BE_MMIO | OHCI_QUIRK_BE_DESC; | ||
| 76 | |||
| 77 | #ifdef CONFIG_PPC_MPC52xx | ||
| 78 | /* MPC52xx doesn't need frame_no shift */ | ||
| 79 | ohci->flags |= OHCI_QUIRK_FRAME_NO; | ||
| 80 | #endif | ||
| 81 | ohci_hcd_init(ohci); | ||
| 82 | |||
| 83 | retval = usb_add_hcd(hcd, irq, IRQF_DISABLED); | ||
| 84 | if (retval == 0) | ||
| 85 | return retval; | ||
| 86 | |||
| 87 | pr_debug("Removing PPC-SOC USB Controller\n"); | ||
| 88 | |||
| 89 | iounmap(hcd->regs); | ||
| 90 | err2: | ||
| 91 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
| 92 | err1: | ||
| 93 | usb_put_hcd(hcd); | ||
| 94 | return retval; | ||
| 95 | } | ||
| 96 | |||
| 97 | |||
| 98 | /* may be called without controller electrically present */ | ||
| 99 | /* may be called with controller, bus, and devices active */ | ||
| 100 | |||
| 101 | /** | ||
| 102 | * usb_hcd_ppc_soc_remove - shutdown processing for On-Chip HCDs | ||
| 103 | * @pdev: USB Host Controller being removed | ||
| 104 | * Context: !in_interrupt() | ||
| 105 | * | ||
| 106 | * Reverses the effect of usb_hcd_ppc_soc_probe(). | ||
| 107 | * It is always called from a thread | ||
| 108 | * context, normally "rmmod", "apmd", or something similar. | ||
| 109 | * | ||
| 110 | */ | ||
| 111 | static void usb_hcd_ppc_soc_remove(struct usb_hcd *hcd, | ||
| 112 | struct platform_device *pdev) | ||
| 113 | { | ||
| 114 | usb_remove_hcd(hcd); | ||
| 115 | |||
| 116 | pr_debug("stopping PPC-SOC USB Controller\n"); | ||
| 117 | |||
| 118 | iounmap(hcd->regs); | ||
| 119 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
| 120 | usb_put_hcd(hcd); | ||
| 121 | } | ||
| 122 | |||
| 123 | static int __devinit | ||
| 124 | ohci_ppc_soc_start(struct usb_hcd *hcd) | ||
| 125 | { | ||
| 126 | struct ohci_hcd *ohci = hcd_to_ohci(hcd); | ||
| 127 | int ret; | ||
| 128 | |||
| 129 | if ((ret = ohci_init(ohci)) < 0) | ||
| 130 | return ret; | ||
| 131 | |||
| 132 | if ((ret = ohci_run(ohci)) < 0) { | ||
| 133 | err("can't start %s", ohci_to_hcd(ohci)->self.bus_name); | ||
| 134 | ohci_stop(hcd); | ||
| 135 | return ret; | ||
| 136 | } | ||
| 137 | |||
| 138 | return 0; | ||
| 139 | } | ||
| 140 | |||
| 141 | static const struct hc_driver ohci_ppc_soc_hc_driver = { | ||
| 142 | .description = hcd_name, | ||
| 143 | .hcd_priv_size = sizeof(struct ohci_hcd), | ||
| 144 | |||
| 145 | /* | ||
| 146 | * generic hardware linkage | ||
| 147 | */ | ||
| 148 | .irq = ohci_irq, | ||
| 149 | .flags = HCD_USB11 | HCD_MEMORY, | ||
| 150 | |||
| 151 | /* | ||
| 152 | * basic lifecycle operations | ||
| 153 | */ | ||
| 154 | .start = ohci_ppc_soc_start, | ||
| 155 | .stop = ohci_stop, | ||
| 156 | .shutdown = ohci_shutdown, | ||
| 157 | |||
| 158 | /* | ||
| 159 | * managing i/o requests and associated device resources | ||
| 160 | */ | ||
| 161 | .urb_enqueue = ohci_urb_enqueue, | ||
| 162 | .urb_dequeue = ohci_urb_dequeue, | ||
| 163 | .endpoint_disable = ohci_endpoint_disable, | ||
| 164 | |||
| 165 | /* | ||
| 166 | * scheduling support | ||
| 167 | */ | ||
| 168 | .get_frame_number = ohci_get_frame, | ||
| 169 | |||
| 170 | /* | ||
| 171 | * root hub support | ||
| 172 | */ | ||
| 173 | .hub_status_data = ohci_hub_status_data, | ||
| 174 | .hub_control = ohci_hub_control, | ||
| 175 | #ifdef CONFIG_PM | ||
| 176 | .bus_suspend = ohci_bus_suspend, | ||
| 177 | .bus_resume = ohci_bus_resume, | ||
| 178 | #endif | ||
| 179 | .start_port_reset = ohci_start_port_reset, | ||
| 180 | }; | ||
| 181 | |||
| 182 | static int ohci_hcd_ppc_soc_drv_probe(struct platform_device *pdev) | ||
| 183 | { | ||
| 184 | int ret; | ||
| 185 | |||
| 186 | if (usb_disabled()) | ||
| 187 | return -ENODEV; | ||
| 188 | |||
| 189 | ret = usb_hcd_ppc_soc_probe(&ohci_ppc_soc_hc_driver, pdev); | ||
| 190 | return ret; | ||
| 191 | } | ||
| 192 | |||
| 193 | static int ohci_hcd_ppc_soc_drv_remove(struct platform_device *pdev) | ||
| 194 | { | ||
| 195 | struct usb_hcd *hcd = platform_get_drvdata(pdev); | ||
| 196 | |||
| 197 | usb_hcd_ppc_soc_remove(hcd, pdev); | ||
| 198 | return 0; | ||
| 199 | } | ||
| 200 | |||
| 201 | static struct platform_driver ohci_hcd_ppc_soc_driver = { | ||
| 202 | .probe = ohci_hcd_ppc_soc_drv_probe, | ||
| 203 | .remove = ohci_hcd_ppc_soc_drv_remove, | ||
| 204 | .shutdown = usb_hcd_platform_shutdown, | ||
| 205 | #ifdef CONFIG_PM | ||
| 206 | /*.suspend = ohci_hcd_ppc_soc_drv_suspend,*/ | ||
| 207 | /*.resume = ohci_hcd_ppc_soc_drv_resume,*/ | ||
| 208 | #endif | ||
| 209 | .driver = { | ||
| 210 | .name = "ppc-soc-ohci", | ||
| 211 | .owner = THIS_MODULE, | ||
| 212 | }, | ||
| 213 | }; | ||
| 214 | |||
| 215 | MODULE_ALIAS("platform:ppc-soc-ohci"); | ||
diff --git a/drivers/usb/host/ohci-sh.c b/drivers/usb/host/ohci-sh.c new file mode 100644 index 00000000000..14cecb52a9f --- /dev/null +++ b/drivers/usb/host/ohci-sh.c | |||
| @@ -0,0 +1,142 @@ | |||
| 1 | /* | ||
| 2 | * OHCI HCD (Host Controller Driver) for USB. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008 Renesas Solutions Corp. | ||
| 5 | * | ||
| 6 | * Author : Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; version 2 of the License. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 20 | * | ||
| 21 | */ | ||
| 22 | |||
| 23 | #include <linux/platform_device.h> | ||
| 24 | |||
| 25 | static int ohci_sh_start(struct usb_hcd *hcd) | ||
| 26 | { | ||
| 27 | struct ohci_hcd *ohci = hcd_to_ohci(hcd); | ||
| 28 | |||
| 29 | ohci_hcd_init(ohci); | ||
| 30 | ohci_init(ohci); | ||
| 31 | ohci_run(ohci); | ||
| 32 | hcd->state = HC_STATE_RUNNING; | ||
| 33 | return 0; | ||
| 34 | } | ||
| 35 | |||
| 36 | static const struct hc_driver ohci_sh_hc_driver = { | ||
| 37 | .description = hcd_name, | ||
| 38 | .product_desc = "SuperH OHCI", | ||
| 39 | .hcd_priv_size = sizeof(struct ohci_hcd), | ||
| 40 | |||
| 41 | /* | ||
| 42 | * generic hardware linkage | ||
| 43 | */ | ||
| 44 | .irq = ohci_irq, | ||
| 45 | .flags = HCD_USB11 | HCD_MEMORY, | ||
| 46 | |||
| 47 | /* | ||
| 48 | * basic lifecycle operations | ||
| 49 | */ | ||
| 50 | .start = ohci_sh_start, | ||
| 51 | .stop = ohci_stop, | ||
| 52 | .shutdown = ohci_shutdown, | ||
| 53 | |||
| 54 | /* | ||
| 55 | * managing i/o requests and associated device resources | ||
| 56 | */ | ||
| 57 | .urb_enqueue = ohci_urb_enqueue, | ||
| 58 | .urb_dequeue = ohci_urb_dequeue, | ||
| 59 | .endpoint_disable = ohci_endpoint_disable, | ||
| 60 | |||
| 61 | /* | ||
| 62 | * scheduling support | ||
| 63 | */ | ||
| 64 | .get_frame_number = ohci_get_frame, | ||
| 65 | |||
| 66 | /* | ||
| 67 | * root hub support | ||
| 68 | */ | ||
| 69 | .hub_status_data = ohci_hub_status_data, | ||
| 70 | .hub_control = ohci_hub_control, | ||
| 71 | #ifdef CONFIG_PM | ||
| 72 | .bus_suspend = ohci_bus_suspend, | ||
| 73 | .bus_resume = ohci_bus_resume, | ||
| 74 | #endif | ||
| 75 | .start_port_reset = ohci_start_port_reset, | ||
| 76 | }; | ||
| 77 | |||
| 78 | /*-------------------------------------------------------------------------*/ | ||
| 79 | |||
| 80 | static int ohci_hcd_sh_probe(struct platform_device *pdev) | ||
| 81 | { | ||
| 82 | struct resource *res = NULL; | ||
| 83 | struct usb_hcd *hcd = NULL; | ||
| 84 | int irq = -1; | ||
| 85 | int ret; | ||
| 86 | |||
| 87 | if (usb_disabled()) | ||
| 88 | return -ENODEV; | ||
| 89 | |||
| 90 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 91 | if (!res) { | ||
| 92 | err("platform_get_resource error."); | ||
| 93 | return -ENODEV; | ||
| 94 | } | ||
| 95 | |||
| 96 | irq = platform_get_irq(pdev, 0); | ||
| 97 | if (irq < 0) { | ||
| 98 | err("platform_get_irq error."); | ||
| 99 | return -ENODEV; | ||
| 100 | } | ||
| 101 | |||
| 102 | /* initialize hcd */ | ||
| 103 | hcd = usb_create_hcd(&ohci_sh_hc_driver, &pdev->dev, (char *)hcd_name); | ||
| 104 | if (!hcd) { | ||
| 105 | err("Failed to create hcd"); | ||
| 106 | return -ENOMEM; | ||
| 107 | } | ||
| 108 | |||
| 109 | hcd->regs = (void __iomem *)res->start; | ||
| 110 | hcd->rsrc_start = res->start; | ||
| 111 | hcd->rsrc_len = resource_size(res); | ||
| 112 | ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); | ||
| 113 | if (ret != 0) { | ||
| 114 | err("Failed to add hcd"); | ||
| 115 | usb_put_hcd(hcd); | ||
| 116 | return ret; | ||
| 117 | } | ||
| 118 | |||
| 119 | return ret; | ||
| 120 | } | ||
| 121 | |||
| 122 | static int ohci_hcd_sh_remove(struct platform_device *pdev) | ||
| 123 | { | ||
| 124 | struct usb_hcd *hcd = platform_get_drvdata(pdev); | ||
| 125 | |||
| 126 | usb_remove_hcd(hcd); | ||
| 127 | usb_put_hcd(hcd); | ||
| 128 | |||
| 129 | return 0; | ||
| 130 | } | ||
| 131 | |||
| 132 | static struct platform_driver ohci_hcd_sh_driver = { | ||
| 133 | .probe = ohci_hcd_sh_probe, | ||
| 134 | .remove = ohci_hcd_sh_remove, | ||
| 135 | .shutdown = usb_hcd_platform_shutdown, | ||
| 136 | .driver = { | ||
| 137 | .name = "sh_ohci", | ||
| 138 | .owner = THIS_MODULE, | ||
| 139 | }, | ||
| 140 | }; | ||
| 141 | |||
| 142 | MODULE_ALIAS("platform:sh_ohci"); | ||
diff --git a/drivers/usb/host/ohci-ssb.c b/drivers/usb/host/ohci-ssb.c new file mode 100644 index 00000000000..c4aea3b8315 --- /dev/null +++ b/drivers/usb/host/ohci-ssb.c | |||
| @@ -0,0 +1,260 @@ | |||
| 1 | /* | ||
| 2 | * Sonics Silicon Backplane | ||
| 3 | * Broadcom USB-core OHCI driver | ||
| 4 | * | ||
| 5 | * Copyright 2007 Michael Buesch <m@bues.ch> | ||
| 6 | * | ||
| 7 | * Derived from the OHCI-PCI driver | ||
| 8 | * Copyright 1999 Roman Weissgaerber | ||
| 9 | * Copyright 2000-2002 David Brownell | ||
| 10 | * Copyright 1999 Linus Torvalds | ||
| 11 | * Copyright 1999 Gregory P. Smith | ||
| 12 | * | ||
| 13 | * Derived from the USBcore related parts of Broadcom-SB | ||
| 14 | * Copyright 2005 Broadcom Corporation | ||
| 15 | * | ||
| 16 | * Licensed under the GNU/GPL. See COPYING for details. | ||
| 17 | */ | ||
| 18 | #include <linux/ssb/ssb.h> | ||
| 19 | |||
| 20 | |||
| 21 | #define SSB_OHCI_TMSLOW_HOSTMODE (1 << 29) | ||
| 22 | |||
| 23 | struct ssb_ohci_device { | ||
| 24 | struct ohci_hcd ohci; /* _must_ be at the beginning. */ | ||
| 25 | |||
| 26 | u32 enable_flags; | ||
| 27 | }; | ||
| 28 | |||
| 29 | static inline | ||
| 30 | struct ssb_ohci_device *hcd_to_ssb_ohci(struct usb_hcd *hcd) | ||
| 31 | { | ||
| 32 | return (struct ssb_ohci_device *)(hcd->hcd_priv); | ||
| 33 | } | ||
| 34 | |||
| 35 | |||
| 36 | static int ssb_ohci_reset(struct usb_hcd *hcd) | ||
| 37 | { | ||
| 38 | struct ssb_ohci_device *ohcidev = hcd_to_ssb_ohci(hcd); | ||
| 39 | struct ohci_hcd *ohci = &ohcidev->ohci; | ||
| 40 | int err; | ||
| 41 | |||
| 42 | ohci_hcd_init(ohci); | ||
| 43 | err = ohci_init(ohci); | ||
| 44 | |||
| 45 | return err; | ||
| 46 | } | ||
| 47 | |||
| 48 | static int ssb_ohci_start(struct usb_hcd *hcd) | ||
| 49 | { | ||
| 50 | struct ssb_ohci_device *ohcidev = hcd_to_ssb_ohci(hcd); | ||
| 51 | struct ohci_hcd *ohci = &ohcidev->ohci; | ||
| 52 | int err; | ||
| 53 | |||
| 54 | err = ohci_run(ohci); | ||
| 55 | if (err < 0) { | ||
| 56 | ohci_err(ohci, "can't start\n"); | ||
| 57 | ohci_stop(hcd); | ||
| 58 | } | ||
| 59 | |||
| 60 | return err; | ||
| 61 | } | ||
| 62 | |||
| 63 | static const struct hc_driver ssb_ohci_hc_driver = { | ||
| 64 | .description = "ssb-usb-ohci", | ||
| 65 | .product_desc = "SSB OHCI Controller", | ||
| 66 | .hcd_priv_size = sizeof(struct ssb_ohci_device), | ||
| 67 | |||
| 68 | .irq = ohci_irq, | ||
| 69 | .flags = HCD_MEMORY | HCD_USB11, | ||
| 70 | |||
| 71 | .reset = ssb_ohci_reset, | ||
| 72 | .start = ssb_ohci_start, | ||
| 73 | .stop = ohci_stop, | ||
| 74 | .shutdown = ohci_shutdown, | ||
| 75 | |||
| 76 | .urb_enqueue = ohci_urb_enqueue, | ||
| 77 | .urb_dequeue = ohci_urb_dequeue, | ||
| 78 | .endpoint_disable = ohci_endpoint_disable, | ||
| 79 | |||
| 80 | .get_frame_number = ohci_get_frame, | ||
| 81 | |||
| 82 | .hub_status_data = ohci_hub_status_data, | ||
| 83 | .hub_control = ohci_hub_control, | ||
| 84 | #ifdef CONFIG_PM | ||
| 85 | .bus_suspend = ohci_bus_suspend, | ||
| 86 | .bus_resume = ohci_bus_resume, | ||
| 87 | #endif | ||
| 88 | |||
| 89 | .start_port_reset = ohci_start_port_reset, | ||
| 90 | }; | ||
| 91 | |||
| 92 | static void ssb_ohci_detach(struct ssb_device *dev) | ||
| 93 | { | ||
| 94 | struct usb_hcd *hcd = ssb_get_drvdata(dev); | ||
| 95 | |||
| 96 | if (hcd->driver->shutdown) | ||
| 97 | hcd->driver->shutdown(hcd); | ||
| 98 | usb_remove_hcd(hcd); | ||
| 99 | iounmap(hcd->regs); | ||
| 100 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
| 101 | usb_put_hcd(hcd); | ||
| 102 | ssb_device_disable(dev, 0); | ||
| 103 | } | ||
| 104 | |||
| 105 | static int ssb_ohci_attach(struct ssb_device *dev) | ||
| 106 | { | ||
| 107 | struct ssb_ohci_device *ohcidev; | ||
| 108 | struct usb_hcd *hcd; | ||
| 109 | int err = -ENOMEM; | ||
| 110 | u32 tmp, flags = 0; | ||
| 111 | |||
| 112 | if (dma_set_mask(dev->dma_dev, DMA_BIT_MASK(32)) || | ||
| 113 | dma_set_coherent_mask(dev->dma_dev, DMA_BIT_MASK(32))) | ||
| 114 | return -EOPNOTSUPP; | ||
| 115 | |||
| 116 | if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV) { | ||
| 117 | /* Put the device into host-mode. */ | ||
| 118 | flags |= SSB_OHCI_TMSLOW_HOSTMODE; | ||
| 119 | ssb_device_enable(dev, flags); | ||
| 120 | } else if (dev->id.coreid == SSB_DEV_USB20_HOST) { | ||
| 121 | /* | ||
| 122 | * USB 2.0 special considerations: | ||
| 123 | * | ||
| 124 | * In addition to the standard SSB reset sequence, the Host | ||
| 125 | * Control Register must be programmed to bring the USB core | ||
| 126 | * and various phy components out of reset. | ||
| 127 | */ | ||
| 128 | ssb_device_enable(dev, 0); | ||
| 129 | ssb_write32(dev, 0x200, 0x7ff); | ||
| 130 | |||
| 131 | /* Change Flush control reg */ | ||
| 132 | tmp = ssb_read32(dev, 0x400); | ||
| 133 | tmp &= ~8; | ||
| 134 | ssb_write32(dev, 0x400, tmp); | ||
| 135 | tmp = ssb_read32(dev, 0x400); | ||
| 136 | |||
| 137 | /* Change Shim control reg */ | ||
| 138 | tmp = ssb_read32(dev, 0x304); | ||
| 139 | tmp &= ~0x100; | ||
| 140 | ssb_write32(dev, 0x304, tmp); | ||
| 141 | tmp = ssb_read32(dev, 0x304); | ||
| 142 | |||
| 143 | udelay(1); | ||
| 144 | |||
| 145 | /* Work around for 5354 failures */ | ||
| 146 | if (dev->id.revision == 2 && dev->bus->chip_id == 0x5354) { | ||
| 147 | /* Change syn01 reg */ | ||
| 148 | tmp = 0x00fe00fe; | ||
| 149 | ssb_write32(dev, 0x894, tmp); | ||
| 150 | |||
| 151 | /* Change syn03 reg */ | ||
| 152 | tmp = ssb_read32(dev, 0x89c); | ||
| 153 | tmp |= 0x1; | ||
| 154 | ssb_write32(dev, 0x89c, tmp); | ||
| 155 | } | ||
| 156 | } else | ||
| 157 | ssb_device_enable(dev, 0); | ||
| 158 | |||
| 159 | hcd = usb_create_hcd(&ssb_ohci_hc_driver, dev->dev, | ||
| 160 | dev_name(dev->dev)); | ||
| 161 | if (!hcd) | ||
| 162 | goto err_dev_disable; | ||
| 163 | ohcidev = hcd_to_ssb_ohci(hcd); | ||
| 164 | ohcidev->enable_flags = flags; | ||
| 165 | |||
| 166 | tmp = ssb_read32(dev, SSB_ADMATCH0); | ||
| 167 | hcd->rsrc_start = ssb_admatch_base(tmp); | ||
| 168 | hcd->rsrc_len = ssb_admatch_size(tmp); | ||
| 169 | hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); | ||
| 170 | if (!hcd->regs) | ||
| 171 | goto err_put_hcd; | ||
| 172 | err = usb_add_hcd(hcd, dev->irq, IRQF_DISABLED | IRQF_SHARED); | ||
| 173 | if (err) | ||
| 174 | goto err_iounmap; | ||
| 175 | |||
| 176 | ssb_set_drvdata(dev, hcd); | ||
| 177 | |||
| 178 | return err; | ||
| 179 | |||
| 180 | err_iounmap: | ||
| 181 | iounmap(hcd->regs); | ||
| 182 | err_put_hcd: | ||
| 183 | usb_put_hcd(hcd); | ||
| 184 | err_dev_disable: | ||
| 185 | ssb_device_disable(dev, flags); | ||
| 186 | return err; | ||
| 187 | } | ||
| 188 | |||
| 189 | static int ssb_ohci_probe(struct ssb_device *dev, | ||
| 190 | const struct ssb_device_id *id) | ||
| 191 | { | ||
| 192 | int err; | ||
| 193 | u16 chipid_top; | ||
| 194 | |||
| 195 | /* USBcores are only connected on embedded devices. */ | ||
| 196 | chipid_top = (dev->bus->chip_id & 0xFF00); | ||
| 197 | if (chipid_top != 0x4700 && chipid_top != 0x5300) | ||
| 198 | return -ENODEV; | ||
| 199 | |||
| 200 | /* TODO: Probably need checks here; is the core connected? */ | ||
| 201 | |||
| 202 | if (usb_disabled()) | ||
| 203 | return -ENODEV; | ||
| 204 | |||
| 205 | /* We currently always attach SSB_DEV_USB11_HOSTDEV | ||
| 206 | * as HOST OHCI. If we want to attach it as Client device, | ||
| 207 | * we must branch here and call into the (yet to | ||
| 208 | * be written) Client mode driver. Same for remove(). */ | ||
| 209 | |||
| 210 | err = ssb_ohci_attach(dev); | ||
| 211 | |||
| 212 | return err; | ||
| 213 | } | ||
| 214 | |||
| 215 | static void ssb_ohci_remove(struct ssb_device *dev) | ||
| 216 | { | ||
| 217 | ssb_ohci_detach(dev); | ||
| 218 | } | ||
| 219 | |||
| 220 | #ifdef CONFIG_PM | ||
| 221 | |||
| 222 | static int ssb_ohci_suspend(struct ssb_device *dev, pm_message_t state) | ||
| 223 | { | ||
| 224 | ssb_device_disable(dev, 0); | ||
| 225 | |||
| 226 | return 0; | ||
| 227 | } | ||
| 228 | |||
| 229 | static int ssb_ohci_resume(struct ssb_device *dev) | ||
| 230 | { | ||
| 231 | struct usb_hcd *hcd = ssb_get_drvdata(dev); | ||
| 232 | struct ssb_ohci_device *ohcidev = hcd_to_ssb_ohci(hcd); | ||
| 233 | |||
| 234 | ssb_device_enable(dev, ohcidev->enable_flags); | ||
| 235 | |||
| 236 | ohci_finish_controller_resume(hcd); | ||
| 237 | return 0; | ||
| 238 | } | ||
| 239 | |||
| 240 | #else /* !CONFIG_PM */ | ||
| 241 | #define ssb_ohci_suspend NULL | ||
| 242 | #define ssb_ohci_resume NULL | ||
| 243 | #endif /* CONFIG_PM */ | ||
| 244 | |||
| 245 | static const struct ssb_device_id ssb_ohci_table[] = { | ||
| 246 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOSTDEV, SSB_ANY_REV), | ||
| 247 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOST, SSB_ANY_REV), | ||
| 248 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV), | ||
| 249 | SSB_DEVTABLE_END | ||
| 250 | }; | ||
| 251 | MODULE_DEVICE_TABLE(ssb, ssb_ohci_table); | ||
| 252 | |||
| 253 | static struct ssb_driver ssb_ohci_driver = { | ||
| 254 | .name = KBUILD_MODNAME, | ||
| 255 | .id_table = ssb_ohci_table, | ||
| 256 | .probe = ssb_ohci_probe, | ||
| 257 | .remove = ssb_ohci_remove, | ||
| 258 | .suspend = ssb_ohci_suspend, | ||
| 259 | .resume = ssb_ohci_resume, | ||
| 260 | }; | ||
diff --git a/drivers/usb/otg/langwell_otg.c b/drivers/usb/otg/langwell_otg.c new file mode 100644 index 00000000000..f08f784086f --- /dev/null +++ b/drivers/usb/otg/langwell_otg.c | |||
| @@ -0,0 +1,2347 @@ | |||
| 1 | /* | ||
| 2 | * Intel Langwell USB OTG transceiver driver | ||
| 3 | * Copyright (C) 2008 - 2010, Intel Corporation. | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify it | ||
| 6 | * under the terms and conditions of the GNU General Public License, | ||
| 7 | * version 2, as published by the Free Software Foundation. | ||
| 8 | * | ||
| 9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
| 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 12 | * more details. | ||
| 13 | * | ||
| 14 | * You should have received a copy of the GNU General Public License along with | ||
| 15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
| 16 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 17 | * | ||
| 18 | */ | ||
| 19 | /* This driver helps to switch Langwell OTG controller function between host | ||
| 20 | * and peripheral. It works with EHCI driver and Langwell client controller | ||
| 21 | * driver together. | ||
| 22 | */ | ||
| 23 | #include <linux/module.h> | ||
| 24 | #include <linux/init.h> | ||
| 25 | #include <linux/pci.h> | ||
| 26 | #include <linux/errno.h> | ||
| 27 | #include <linux/interrupt.h> | ||
| 28 | #include <linux/kernel.h> | ||
| 29 | #include <linux/device.h> | ||
| 30 | #include <linux/moduleparam.h> | ||
| 31 | #include <linux/usb/ch9.h> | ||
| 32 | #include <linux/usb/gadget.h> | ||
| 33 | #include <linux/usb.h> | ||
| 34 | #include <linux/usb/otg.h> | ||
| 35 | #include <linux/usb/hcd.h> | ||
| 36 | #include <linux/notifier.h> | ||
| 37 | #include <linux/delay.h> | ||
| 38 | #include <asm/intel_scu_ipc.h> | ||
| 39 | |||
| 40 | #include <linux/usb/langwell_otg.h> | ||
| 41 | |||
| 42 | #define DRIVER_DESC "Intel Langwell USB OTG transceiver driver" | ||
| 43 | #define DRIVER_VERSION "July 10, 2010" | ||
| 44 | |||
| 45 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
| 46 | MODULE_AUTHOR("Henry Yuan <hang.yuan@intel.com>, Hao Wu <hao.wu@intel.com>"); | ||
| 47 | MODULE_VERSION(DRIVER_VERSION); | ||
| 48 | MODULE_LICENSE("GPL"); | ||
| 49 | |||
| 50 | static const char driver_name[] = "langwell_otg"; | ||
| 51 | |||
| 52 | static int langwell_otg_probe(struct pci_dev *pdev, | ||
| 53 | const struct pci_device_id *id); | ||
| 54 | static void langwell_otg_remove(struct pci_dev *pdev); | ||
| 55 | static int langwell_otg_suspend(struct pci_dev *pdev, pm_message_t message); | ||
| 56 | static int langwell_otg_resume(struct pci_dev *pdev); | ||
| 57 | |||
| 58 | static int langwell_otg_set_host(struct otg_transceiver *otg, | ||
| 59 | struct usb_bus *host); | ||
| 60 | static int langwell_otg_set_peripheral(struct otg_transceiver *otg, | ||
| 61 | struct usb_gadget *gadget); | ||
| 62 | static int langwell_otg_start_srp(struct otg_transceiver *otg); | ||
| 63 | |||
| 64 | static const struct pci_device_id pci_ids[] = {{ | ||
| 65 | .class = ((PCI_CLASS_SERIAL_USB << 8) | 0xfe), | ||
| 66 | .class_mask = ~0, | ||
| 67 | .vendor = 0x8086, | ||
| 68 | .device = 0x0811, | ||
| 69 | .subvendor = PCI_ANY_ID, | ||
| 70 | .subdevice = PCI_ANY_ID, | ||
| 71 | }, { /* end: all zeroes */ } | ||
| 72 | }; | ||
| 73 | |||
| 74 | static struct pci_driver otg_pci_driver = { | ||
| 75 | .name = (char *) driver_name, | ||
| 76 | .id_table = pci_ids, | ||
| 77 | |||
| 78 | .probe = langwell_otg_probe, | ||
| 79 | .remove = langwell_otg_remove, | ||
| 80 | |||
| 81 | .suspend = langwell_otg_suspend, | ||
| 82 | .resume = langwell_otg_resume, | ||
| 83 | }; | ||
| 84 | |||
| 85 | /* HSM timers */ | ||
| 86 | static inline struct langwell_otg_timer *otg_timer_initializer | ||
| 87 | (void (*function)(unsigned long), unsigned long expires, unsigned long data) | ||
| 88 | { | ||
| 89 | struct langwell_otg_timer *timer; | ||
| 90 | timer = kmalloc(sizeof(struct langwell_otg_timer), GFP_KERNEL); | ||
| 91 | if (timer == NULL) | ||
| 92 | return timer; | ||
| 93 | |||
| 94 | timer->function = function; | ||
| 95 | timer->expires = expires; | ||
| 96 | timer->data = data; | ||
| 97 | return timer; | ||
| 98 | } | ||
| 99 | |||
| 100 | static struct langwell_otg_timer *a_wait_vrise_tmr, *a_aidl_bdis_tmr, | ||
| 101 | *b_se0_srp_tmr, *b_srp_init_tmr; | ||
| 102 | |||
| 103 | static struct list_head active_timers; | ||
| 104 | |||
| 105 | static struct langwell_otg *the_transceiver; | ||
| 106 | |||
| 107 | /* host/client notify transceiver when event affects HNP state */ | ||
| 108 | void langwell_update_transceiver(void) | ||
| 109 | { | ||
| 110 | struct langwell_otg *lnw = the_transceiver; | ||
| 111 | |||
| 112 | dev_dbg(lnw->dev, "transceiver is updated\n"); | ||
| 113 | |||
| 114 | if (!lnw->qwork) | ||
| 115 | return ; | ||
| 116 | |||
| 117 | queue_work(lnw->qwork, &lnw->work); | ||
| 118 | } | ||
| 119 | EXPORT_SYMBOL(langwell_update_transceiver); | ||
| 120 | |||
| 121 | static int langwell_otg_set_host(struct otg_transceiver *otg, | ||
| 122 | struct usb_bus *host) | ||
| 123 | { | ||
| 124 | otg->host = host; | ||
| 125 | |||
| 126 | return 0; | ||
| 127 | } | ||
| 128 | |||
| 129 | static int langwell_otg_set_peripheral(struct otg_transceiver *otg, | ||
| 130 | struct usb_gadget *gadget) | ||
| 131 | { | ||
| 132 | otg->gadget = gadget; | ||
| 133 | |||
| 134 | return 0; | ||
| 135 | } | ||
| 136 | |||
| 137 | static int langwell_otg_set_power(struct otg_transceiver *otg, | ||
| 138 | unsigned mA) | ||
| 139 | { | ||
| 140 | return 0; | ||
| 141 | } | ||
| 142 | |||
| 143 | /* A-device drives vbus, controlled through IPC commands */ | ||
| 144 | static int langwell_otg_set_vbus(struct otg_transceiver *otg, bool enabled) | ||
| 145 | { | ||
| 146 | struct langwell_otg *lnw = the_transceiver; | ||
| 147 | u8 sub_id; | ||
| 148 | |||
| 149 | dev_dbg(lnw->dev, "%s <--- %s\n", __func__, enabled ? "on" : "off"); | ||
| 150 | |||
| 151 | if (enabled) | ||
| 152 | sub_id = 0x8; /* Turn on the VBus */ | ||
| 153 | else | ||
| 154 | sub_id = 0x9; /* Turn off the VBus */ | ||
| 155 | |||
| 156 | if (intel_scu_ipc_simple_command(0xef, sub_id)) { | ||
| 157 | dev_dbg(lnw->dev, "Failed to set Vbus via IPC commands\n"); | ||
| 158 | return -EBUSY; | ||
| 159 | } | ||
| 160 | |||
| 161 | dev_dbg(lnw->dev, "%s --->\n", __func__); | ||
| 162 | |||
| 163 | return 0; | ||
| 164 | } | ||
| 165 | |||
| 166 | /* charge vbus or discharge vbus through a resistor to ground */ | ||
| 167 | static void langwell_otg_chrg_vbus(int on) | ||
| 168 | { | ||
| 169 | struct langwell_otg *lnw = the_transceiver; | ||
| 170 | u32 val; | ||
| 171 | |||
| 172 | val = readl(lnw->iotg.base + CI_OTGSC); | ||
| 173 | |||
| 174 | if (on) | ||
| 175 | writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_VC, | ||
| 176 | lnw->iotg.base + CI_OTGSC); | ||
| 177 | else | ||
| 178 | writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_VD, | ||
| 179 | lnw->iotg.base + CI_OTGSC); | ||
| 180 | } | ||
| 181 | |||
| 182 | /* Start SRP */ | ||
| 183 | static int langwell_otg_start_srp(struct otg_transceiver *otg) | ||
| 184 | { | ||
| 185 | struct langwell_otg *lnw = the_transceiver; | ||
| 186 | struct intel_mid_otg_xceiv *iotg = &lnw->iotg; | ||
| 187 | u32 val; | ||
| 188 | |||
| 189 | dev_dbg(lnw->dev, "%s --->\n", __func__); | ||
| 190 | |||
| 191 | val = readl(iotg->base + CI_OTGSC); | ||
| 192 | |||
| 193 | writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HADP, | ||
| 194 | iotg->base + CI_OTGSC); | ||
| 195 | |||
| 196 | /* Check if the data plus is finished or not */ | ||
| 197 | msleep(8); | ||
| 198 | val = readl(iotg->base + CI_OTGSC); | ||
| 199 | if (val & (OTGSC_HADP | OTGSC_DP)) | ||
| 200 | dev_dbg(lnw->dev, "DataLine SRP Error\n"); | ||
| 201 | |||
| 202 | /* Disable interrupt - b_sess_vld */ | ||
| 203 | val = readl(iotg->base + CI_OTGSC); | ||
| 204 | val &= (~(OTGSC_BSVIE | OTGSC_BSEIE)); | ||
| 205 | writel(val, iotg->base + CI_OTGSC); | ||
| 206 | |||
| 207 | /* Start VBus SRP, drive vbus to generate VBus pulse */ | ||
| 208 | iotg->otg.set_vbus(&iotg->otg, true); | ||
| 209 | msleep(15); | ||
| 210 | iotg->otg.set_vbus(&iotg->otg, false); | ||
| 211 | |||
| 212 | /* Enable interrupt - b_sess_vld*/ | ||
| 213 | val = readl(iotg->base + CI_OTGSC); | ||
| 214 | dev_dbg(lnw->dev, "after VBUS pulse otgsc = %x\n", val); | ||
| 215 | |||
| 216 | val |= (OTGSC_BSVIE | OTGSC_BSEIE); | ||
| 217 | writel(val, iotg->base + CI_OTGSC); | ||
| 218 | |||
| 219 | /* If Vbus is valid, then update the hsm */ | ||
| 220 | if (val & OTGSC_BSV) { | ||
| 221 | dev_dbg(lnw->dev, "no b_sess_vld interrupt\n"); | ||
| 222 | |||
| 223 | lnw->iotg.hsm.b_sess_vld = 1; | ||
| 224 | langwell_update_transceiver(); | ||
| 225 | } | ||
| 226 | |||
| 227 | dev_dbg(lnw->dev, "%s <---\n", __func__); | ||
| 228 | return 0; | ||
| 229 | } | ||
| 230 | |||
| 231 | /* stop SOF via bus_suspend */ | ||
| 232 | static void langwell_otg_loc_sof(int on) | ||
| 233 | { | ||
| 234 | struct langwell_otg *lnw = the_transceiver; | ||
| 235 | struct usb_hcd *hcd; | ||
| 236 | int err; | ||
| 237 | |||
| 238 | dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "suspend" : "resume"); | ||
| 239 | |||
| 240 | hcd = bus_to_hcd(lnw->iotg.otg.host); | ||
| 241 | if (on) | ||
| 242 | err = hcd->driver->bus_resume(hcd); | ||
| 243 | else | ||
| 244 | err = hcd->driver->bus_suspend(hcd); | ||
| 245 | |||
| 246 | if (err) | ||
| 247 | dev_dbg(lnw->dev, "Fail to resume/suspend USB bus - %d\n", err); | ||
| 248 | |||
| 249 | dev_dbg(lnw->dev, "%s <---\n", __func__); | ||
| 250 | } | ||
| 251 | |||
| 252 | static int langwell_otg_check_otgsc(void) | ||
| 253 | { | ||
| 254 | struct langwell_otg *lnw = the_transceiver; | ||
| 255 | u32 otgsc, usbcfg; | ||
| 256 | |||
| 257 | dev_dbg(lnw->dev, "check sync OTGSC and USBCFG registers\n"); | ||
| 258 | |||
| 259 | otgsc = readl(lnw->iotg.base + CI_OTGSC); | ||
| 260 | usbcfg = readl(lnw->usbcfg); | ||
| 261 | |||
| 262 | dev_dbg(lnw->dev, "OTGSC = %08x, USBCFG = %08x\n", | ||
| 263 | otgsc, usbcfg); | ||
| 264 | dev_dbg(lnw->dev, "OTGSC_AVV = %d\n", !!(otgsc & OTGSC_AVV)); | ||
| 265 | dev_dbg(lnw->dev, "USBCFG.VBUSVAL = %d\n", | ||
| 266 | !!(usbcfg & USBCFG_VBUSVAL)); | ||
| 267 | dev_dbg(lnw->dev, "OTGSC_ASV = %d\n", !!(otgsc & OTGSC_ASV)); | ||
| 268 | dev_dbg(lnw->dev, "USBCFG.AVALID = %d\n", | ||
| 269 | !!(usbcfg & USBCFG_AVALID)); | ||
| 270 | dev_dbg(lnw->dev, "OTGSC_BSV = %d\n", !!(otgsc & OTGSC_BSV)); | ||
| 271 | dev_dbg(lnw->dev, "USBCFG.BVALID = %d\n", | ||
| 272 | !!(usbcfg & USBCFG_BVALID)); | ||
| 273 | dev_dbg(lnw->dev, "OTGSC_BSE = %d\n", !!(otgsc & OTGSC_BSE)); | ||
| 274 | dev_dbg(lnw->dev, "USBCFG.SESEND = %d\n", | ||
| 275 | !!(usbcfg & USBCFG_SESEND)); | ||
| 276 | |||
| 277 | /* Check USBCFG VBusValid/AValid/BValid/SessEnd */ | ||
| 278 | if (!!(otgsc & OTGSC_AVV) ^ !!(usbcfg & USBCFG_VBUSVAL)) { | ||
| 279 | dev_dbg(lnw->dev, "OTGSC.AVV != USBCFG.VBUSVAL\n"); | ||
| 280 | goto err; | ||
| 281 | } | ||
| 282 | if (!!(otgsc & OTGSC_ASV) ^ !!(usbcfg & USBCFG_AVALID)) { | ||
| 283 | dev_dbg(lnw->dev, "OTGSC.ASV != USBCFG.AVALID\n"); | ||
| 284 | goto err; | ||
| 285 | } | ||
| 286 | if (!!(otgsc & OTGSC_BSV) ^ !!(usbcfg & USBCFG_BVALID)) { | ||
| 287 | dev_dbg(lnw->dev, "OTGSC.BSV != USBCFG.BVALID\n"); | ||
| 288 | goto err; | ||
| 289 | } | ||
| 290 | if (!!(otgsc & OTGSC_BSE) ^ !!(usbcfg & USBCFG_SESEND)) { | ||
| 291 | dev_dbg(lnw->dev, "OTGSC.BSE != USBCFG.SESSEN\n"); | ||
| 292 | goto err; | ||
| 293 | } | ||
| 294 | |||
| 295 | dev_dbg(lnw->dev, "OTGSC and USBCFG are synced\n"); | ||
| 296 | |||
| 297 | return 0; | ||
| 298 | |||
| 299 | err: | ||
| 300 | dev_warn(lnw->dev, "OTGSC isn't equal to USBCFG\n"); | ||
| 301 | return -EPIPE; | ||
| 302 | } | ||
| 303 | |||
| 304 | |||
| 305 | static void langwell_otg_phy_low_power(int on) | ||
| 306 | { | ||
| 307 | struct langwell_otg *lnw = the_transceiver; | ||
| 308 | struct intel_mid_otg_xceiv *iotg = &lnw->iotg; | ||
| 309 | u8 val, phcd; | ||
| 310 | int retval; | ||
| 311 | |||
| 312 | dev_dbg(lnw->dev, "%s ---> %s mode\n", | ||
| 313 | __func__, on ? "Low power" : "Normal"); | ||
| 314 | |||
| 315 | phcd = 0x40; | ||
| 316 | |||
| 317 | val = readb(iotg->base + CI_HOSTPC1 + 2); | ||
| 318 | |||
| 319 | if (on) { | ||
| 320 | /* Due to hardware issue, after set PHCD, sync will failed | ||
| 321 | * between USBCFG and OTGSC, so before set PHCD, check if | ||
| 322 | * sync is in process now. If the answer is "yes", then do | ||
| 323 | * not touch PHCD bit */ | ||
| 324 | retval = langwell_otg_check_otgsc(); | ||
| 325 | if (retval) { | ||
| 326 | dev_dbg(lnw->dev, "Skip PHCD programming..\n"); | ||
| 327 | return ; | ||
| 328 | } | ||
| 329 | |||
| 330 | writeb(val | phcd, iotg->base + CI_HOSTPC1 + 2); | ||
| 331 | } else | ||
| 332 | writeb(val & ~phcd, iotg->base + CI_HOSTPC1 + 2); | ||
| 333 | |||
| 334 | dev_dbg(lnw->dev, "%s <--- done\n", __func__); | ||
| 335 | } | ||
| 336 | |||
| 337 | /* After drv vbus, add 5 ms delay to set PHCD */ | ||
| 338 | static void langwell_otg_phy_low_power_wait(int on) | ||
| 339 | { | ||
| 340 | struct langwell_otg *lnw = the_transceiver; | ||
| 341 | |||
| 342 | dev_dbg(lnw->dev, "add 5ms delay before programing PHCD\n"); | ||
| 343 | |||
| 344 | mdelay(5); | ||
| 345 | langwell_otg_phy_low_power(on); | ||
| 346 | } | ||
| 347 | |||
| 348 | /* Enable/Disable OTG interrupt */ | ||
| 349 | static void langwell_otg_intr(int on) | ||
| 350 | { | ||
| 351 | struct langwell_otg *lnw = the_transceiver; | ||
| 352 | struct intel_mid_otg_xceiv *iotg = &lnw->iotg; | ||
| 353 | u32 val; | ||
| 354 | |||
| 355 | dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "on" : "off"); | ||
| 356 | |||
| 357 | val = readl(iotg->base + CI_OTGSC); | ||
| 358 | |||
| 359 | /* OTGSC_INT_MASK doesn't contains 1msInt */ | ||
| 360 | if (on) { | ||
| 361 | val = val | (OTGSC_INT_MASK); | ||
| 362 | writel(val, iotg->base + CI_OTGSC); | ||
| 363 | } else { | ||
| 364 | val = val & ~(OTGSC_INT_MASK); | ||
| 365 | writel(val, iotg->base + CI_OTGSC); | ||
| 366 | } | ||
| 367 | |||
| 368 | dev_dbg(lnw->dev, "%s <---\n", __func__); | ||
| 369 | } | ||
| 370 | |||
| 371 | /* set HAAR: Hardware Assist Auto-Reset */ | ||
| 372 | static void langwell_otg_HAAR(int on) | ||
| 373 | { | ||
| 374 | struct langwell_otg *lnw = the_transceiver; | ||
| 375 | struct intel_mid_otg_xceiv *iotg = &lnw->iotg; | ||
| 376 | u32 val; | ||
| 377 | |||
| 378 | dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "on" : "off"); | ||
| 379 | |||
| 380 | val = readl(iotg->base + CI_OTGSC); | ||
| 381 | if (on) | ||
| 382 | writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HAAR, | ||
| 383 | iotg->base + CI_OTGSC); | ||
| 384 | else | ||
| 385 | writel((val & ~OTGSC_INTSTS_MASK) & ~OTGSC_HAAR, | ||
| 386 | iotg->base + CI_OTGSC); | ||
| 387 | |||
| 388 | dev_dbg(lnw->dev, "%s <---\n", __func__); | ||
| 389 | } | ||
| 390 | |||
| 391 | /* set HABA: Hardware Assist B-Disconnect to A-Connect */ | ||
| 392 | static void langwell_otg_HABA(int on) | ||
| 393 | { | ||
| 394 | struct langwell_otg *lnw = the_transceiver; | ||
| 395 | struct intel_mid_otg_xceiv *iotg = &lnw->iotg; | ||
| 396 | u32 val; | ||
| 397 | |||
| 398 | dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "on" : "off"); | ||
| 399 | |||
| 400 | val = readl(iotg->base + CI_OTGSC); | ||
| 401 | if (on) | ||
| 402 | writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HABA, | ||
| 403 | iotg->base + CI_OTGSC); | ||
| 404 | else | ||
| 405 | writel((val & ~OTGSC_INTSTS_MASK) & ~OTGSC_HABA, | ||
| 406 | iotg->base + CI_OTGSC); | ||
| 407 | |||
| 408 | dev_dbg(lnw->dev, "%s <---\n", __func__); | ||
| 409 | } | ||
| 410 | |||
| 411 | static int langwell_otg_check_se0_srp(int on) | ||
| 412 | { | ||
| 413 | struct langwell_otg *lnw = the_transceiver; | ||
| 414 | int delay_time = TB_SE0_SRP * 10; | ||
| 415 | u32 val; | ||
| 416 | |||
| 417 | dev_dbg(lnw->dev, "%s --->\n", __func__); | ||
| 418 | |||
| 419 | do { | ||
| 420 | udelay(100); | ||
| 421 | if (!delay_time--) | ||
| 422 | break; | ||
| 423 | val = readl(lnw->iotg.base + CI_PORTSC1); | ||
| 424 | val &= PORTSC_LS; | ||
| 425 | } while (!val); | ||
| 426 | |||
| 427 | dev_dbg(lnw->dev, "%s <---\n", __func__); | ||
| 428 | return val; | ||
| 429 | } | ||
| 430 | |||
| 431 | /* The timeout callback function to set time out bit */ | ||
| 432 | static void set_tmout(unsigned long indicator) | ||
| 433 | { | ||
| 434 | *(int *)indicator = 1; | ||
| 435 | } | ||
| 436 | |||
| 437 | void langwell_otg_nsf_msg(unsigned long indicator) | ||
| 438 | { | ||
| 439 | struct langwell_otg *lnw = the_transceiver; | ||
| 440 | |||
| 441 | switch (indicator) { | ||
| 442 | case 2: | ||
| 443 | case 4: | ||
| 444 | case 6: | ||
| 445 | case 7: | ||
| 446 | dev_warn(lnw->dev, | ||
| 447 | "OTG:NSF-%lu - deivce not responding\n", indicator); | ||
| 448 | break; | ||
| 449 | case 3: | ||
| 450 | dev_warn(lnw->dev, | ||
| 451 | "OTG:NSF-%lu - deivce not supported\n", indicator); | ||
| 452 | break; | ||
| 453 | default: | ||
| 454 | dev_warn(lnw->dev, "Do not have this kind of NSF\n"); | ||
| 455 | break; | ||
| 456 | } | ||
| 457 | } | ||
| 458 | |||
| 459 | /* Initialize timers */ | ||
| 460 | static int langwell_otg_init_timers(struct otg_hsm *hsm) | ||
| 461 | { | ||
| 462 | /* HSM used timers */ | ||
| 463 | a_wait_vrise_tmr = otg_timer_initializer(&set_tmout, TA_WAIT_VRISE, | ||
| 464 | (unsigned long)&hsm->a_wait_vrise_tmout); | ||
| 465 | if (a_wait_vrise_tmr == NULL) | ||
| 466 | return -ENOMEM; | ||
| 467 | a_aidl_bdis_tmr = otg_timer_initializer(&set_tmout, TA_AIDL_BDIS, | ||
| 468 | (unsigned long)&hsm->a_aidl_bdis_tmout); | ||
| 469 | if (a_aidl_bdis_tmr == NULL) | ||
| 470 | return -ENOMEM; | ||
| 471 | b_se0_srp_tmr = otg_timer_initializer(&set_tmout, TB_SE0_SRP, | ||
| 472 | (unsigned long)&hsm->b_se0_srp); | ||
| 473 | if (b_se0_srp_tmr == NULL) | ||
| 474 | return -ENOMEM; | ||
| 475 | b_srp_init_tmr = otg_timer_initializer(&set_tmout, TB_SRP_INIT, | ||
| 476 | (unsigned long)&hsm->b_srp_init_tmout); | ||
| 477 | if (b_srp_init_tmr == NULL) | ||
| 478 | return -ENOMEM; | ||
| 479 | |||
| 480 | return 0; | ||
| 481 | } | ||
| 482 | |||
| 483 | /* Free timers */ | ||
| 484 | static void langwell_otg_free_timers(void) | ||
| 485 | { | ||
| 486 | kfree(a_wait_vrise_tmr); | ||
| 487 | kfree(a_aidl_bdis_tmr); | ||
| 488 | kfree(b_se0_srp_tmr); | ||
| 489 | kfree(b_srp_init_tmr); | ||
| 490 | } | ||
| 491 | |||
| 492 | /* The timeout callback function to set time out bit */ | ||
| 493 | static void langwell_otg_timer_fn(unsigned long indicator) | ||
| 494 | { | ||
| 495 | struct langwell_otg *lnw = the_transceiver; | ||
| 496 | |||
| 497 | *(int *)indicator = 1; | ||
| 498 | |||
| 499 | dev_dbg(lnw->dev, "kernel timer - timeout\n"); | ||
| 500 | |||
| 501 | langwell_update_transceiver(); | ||
| 502 | } | ||
| 503 | |||
| 504 | /* kernel timer used instead of HW based interrupt */ | ||
| 505 | static void langwell_otg_add_ktimer(enum langwell_otg_timer_type timers) | ||
| 506 | { | ||
| 507 | struct langwell_otg *lnw = the_transceiver; | ||
| 508 | struct intel_mid_otg_xceiv *iotg = &lnw->iotg; | ||
| 509 | unsigned long j = jiffies; | ||
| 510 | unsigned long data, time; | ||
| 511 | |||
| 512 | switch (timers) { | ||
| 513 | case TA_WAIT_VRISE_TMR: | ||
| 514 | iotg->hsm.a_wait_vrise_tmout = 0; | ||
| 515 | data = (unsigned long)&iotg->hsm.a_wait_vrise_tmout; | ||
| 516 | time = TA_WAIT_VRISE; | ||
| 517 | break; | ||
| 518 | case TA_WAIT_BCON_TMR: | ||
| 519 | iotg->hsm.a_wait_bcon_tmout = 0; | ||
| 520 | data = (unsigned long)&iotg->hsm.a_wait_bcon_tmout; | ||
| 521 | time = TA_WAIT_BCON; | ||
| 522 | break; | ||
| 523 | case TA_AIDL_BDIS_TMR: | ||
| 524 | iotg->hsm.a_aidl_bdis_tmout = 0; | ||
| 525 | data = (unsigned long)&iotg->hsm.a_aidl_bdis_tmout; | ||
| 526 | time = TA_AIDL_BDIS; | ||
| 527 | break; | ||
| 528 | case TB_ASE0_BRST_TMR: | ||
| 529 | iotg->hsm.b_ase0_brst_tmout = 0; | ||
| 530 | data = (unsigned long)&iotg->hsm.b_ase0_brst_tmout; | ||
| 531 | time = TB_ASE0_BRST; | ||
| 532 | break; | ||
| 533 | case TB_SRP_INIT_TMR: | ||
| 534 | iotg->hsm.b_srp_init_tmout = 0; | ||
| 535 | data = (unsigned long)&iotg->hsm.b_srp_init_tmout; | ||
| 536 | time = TB_SRP_INIT; | ||
| 537 | break; | ||
| 538 | case TB_SRP_FAIL_TMR: | ||
| 539 | iotg->hsm.b_srp_fail_tmout = 0; | ||
| 540 | data = (unsigned long)&iotg->hsm.b_srp_fail_tmout; | ||
| 541 | time = TB_SRP_FAIL; | ||
| 542 | break; | ||
| 543 | case TB_BUS_SUSPEND_TMR: | ||
| 544 | iotg->hsm.b_bus_suspend_tmout = 0; | ||
| 545 | data = (unsigned long)&iotg->hsm.b_bus_suspend_tmout; | ||
| 546 | time = TB_BUS_SUSPEND; | ||
| 547 | break; | ||
| 548 | default: | ||
| 549 | dev_dbg(lnw->dev, "unknown timer, cannot enable it\n"); | ||
| 550 | return; | ||
| 551 | } | ||
| 552 | |||
| 553 | lnw->hsm_timer.data = data; | ||
| 554 | lnw->hsm_timer.function = langwell_otg_timer_fn; | ||
| 555 | lnw->hsm_timer.expires = j + time * HZ / 1000; /* milliseconds */ | ||
| 556 | |||
| 557 | add_timer(&lnw->hsm_timer); | ||
| 558 | |||
| 559 | dev_dbg(lnw->dev, "add timer successfully\n"); | ||
| 560 | } | ||
| 561 | |||
| 562 | /* Add timer to timer list */ | ||
| 563 | static void langwell_otg_add_timer(void *gtimer) | ||
| 564 | { | ||
| 565 | struct langwell_otg_timer *timer = (struct langwell_otg_timer *)gtimer; | ||
| 566 | struct langwell_otg_timer *tmp_timer; | ||
| 567 | struct intel_mid_otg_xceiv *iotg = &the_transceiver->iotg; | ||
| 568 | u32 val32; | ||
| 569 | |||
| 570 | /* Check if the timer is already in the active list, | ||
| 571 | * if so update timer count | ||
| 572 | */ | ||
| 573 | list_for_each_entry(tmp_timer, &active_timers, list) | ||
| 574 | if (tmp_timer == timer) { | ||
| 575 | timer->count = timer->expires; | ||
| 576 | return; | ||
| 577 | } | ||
| 578 | timer->count = timer->expires; | ||
| 579 | |||
| 580 | if (list_empty(&active_timers)) { | ||
| 581 | val32 = readl(iotg->base + CI_OTGSC); | ||
| 582 | writel(val32 | OTGSC_1MSE, iotg->base + CI_OTGSC); | ||
| 583 | } | ||
| 584 | |||
| 585 | list_add_tail(&timer->list, &active_timers); | ||
| 586 | } | ||
| 587 | |||
| 588 | /* Remove timer from the timer list; clear timeout status */ | ||
| 589 | static void langwell_otg_del_timer(void *gtimer) | ||
| 590 | { | ||
| 591 | struct langwell_otg *lnw = the_transceiver; | ||
| 592 | struct langwell_otg_timer *timer = (struct langwell_otg_timer *)gtimer; | ||
| 593 | struct langwell_otg_timer *tmp_timer, *del_tmp; | ||
| 594 | u32 val32; | ||
| 595 | |||
| 596 | list_for_each_entry_safe(tmp_timer, del_tmp, &active_timers, list) | ||
| 597 | if (tmp_timer == timer) | ||
| 598 | list_del(&timer->list); | ||
| 599 | |||
| 600 | if (list_empty(&active_timers)) { | ||
| 601 | val32 = readl(lnw->iotg.base + CI_OTGSC); | ||
| 602 | writel(val32 & ~OTGSC_1MSE, lnw->iotg.base + CI_OTGSC); | ||
| 603 | } | ||
| 604 | } | ||
| 605 | |||
| 606 | /* Reduce timer count by 1, and find timeout conditions.*/ | ||
| 607 | static int langwell_otg_tick_timer(u32 *int_sts) | ||
| 608 | { | ||
| 609 | struct langwell_otg *lnw = the_transceiver; | ||
| 610 | struct langwell_otg_timer *tmp_timer, *del_tmp; | ||
| 611 | int expired = 0; | ||
| 612 | |||
| 613 | list_for_each_entry_safe(tmp_timer, del_tmp, &active_timers, list) { | ||
| 614 | tmp_timer->count--; | ||
| 615 | /* check if timer expires */ | ||
| 616 | if (!tmp_timer->count) { | ||
| 617 | list_del(&tmp_timer->list); | ||
| 618 | tmp_timer->function(tmp_timer->data); | ||
| 619 | expired = 1; | ||
| 620 | } | ||
| 621 | } | ||
| 622 | |||
| 623 | if (list_empty(&active_timers)) { | ||
| 624 | dev_dbg(lnw->dev, "tick timer: disable 1ms int\n"); | ||
| 625 | *int_sts = *int_sts & ~OTGSC_1MSE; | ||
| 626 | } | ||
| 627 | return expired; | ||
| 628 | } | ||
| 629 | |||
| 630 | static void reset_otg(void) | ||
| 631 | { | ||
| 632 | struct langwell_otg *lnw = the_transceiver; | ||
| 633 | int delay_time = 1000; | ||
| 634 | u32 val; | ||
| 635 | |||
| 636 | dev_dbg(lnw->dev, "reseting OTG controller ...\n"); | ||
| 637 | val = readl(lnw->iotg.base + CI_USBCMD); | ||
| 638 | writel(val | USBCMD_RST, lnw->iotg.base + CI_USBCMD); | ||
| 639 | do { | ||
| 640 | udelay(100); | ||
| 641 | if (!delay_time--) | ||
| 642 | dev_dbg(lnw->dev, "reset timeout\n"); | ||
| 643 | val = readl(lnw->iotg.base + CI_USBCMD); | ||
| 644 | val &= USBCMD_RST; | ||
| 645 | } while (val != 0); | ||
| 646 | dev_dbg(lnw->dev, "reset done.\n"); | ||
| 647 | } | ||
| 648 | |||
| 649 | static void set_host_mode(void) | ||
| 650 | { | ||
| 651 | struct langwell_otg *lnw = the_transceiver; | ||
| 652 | u32 val; | ||
| 653 | |||
| 654 | reset_otg(); | ||
| 655 | val = readl(lnw->iotg.base + CI_USBMODE); | ||
| 656 | val = (val & (~USBMODE_CM)) | USBMODE_HOST; | ||
| 657 | writel(val, lnw->iotg.base + CI_USBMODE); | ||
| 658 | } | ||
| 659 | |||
| 660 | static void set_client_mode(void) | ||
| 661 | { | ||
| 662 | struct langwell_otg *lnw = the_transceiver; | ||
| 663 | u32 val; | ||
| 664 | |||
| 665 | reset_otg(); | ||
| 666 | val = readl(lnw->iotg.base + CI_USBMODE); | ||
| 667 | val = (val & (~USBMODE_CM)) | USBMODE_DEVICE; | ||
| 668 | writel(val, lnw->iotg.base + CI_USBMODE); | ||
| 669 | } | ||
| 670 | |||
| 671 | static void init_hsm(void) | ||
| 672 | { | ||
| 673 | struct langwell_otg *lnw = the_transceiver; | ||
| 674 | struct intel_mid_otg_xceiv *iotg = &lnw->iotg; | ||
| 675 | u32 val32; | ||
| 676 | |||
| 677 | /* read OTGSC after reset */ | ||
| 678 | val32 = readl(lnw->iotg.base + CI_OTGSC); | ||
| 679 | dev_dbg(lnw->dev, "%s: OTGSC init value = 0x%x\n", __func__, val32); | ||
| 680 | |||
| 681 | /* set init state */ | ||
| 682 | if (val32 & OTGSC_ID) { | ||
| 683 | iotg->hsm.id = 1; | ||
| 684 | iotg->otg.default_a = 0; | ||
| 685 | set_client_mode(); | ||
| 686 | iotg->otg.state = OTG_STATE_B_IDLE; | ||
| 687 | } else { | ||
| 688 | iotg->hsm.id = 0; | ||
| 689 | iotg->otg.default_a = 1; | ||
| 690 | set_host_mode(); | ||
| 691 | iotg->otg.state = OTG_STATE_A_IDLE; | ||
| 692 | } | ||
| 693 | |||
| 694 | /* set session indicator */ | ||
| 695 | if (val32 & OTGSC_BSE) | ||
| 696 | iotg->hsm.b_sess_end = 1; | ||
| 697 | if (val32 & OTGSC_BSV) | ||
| 698 | iotg->hsm.b_sess_vld = 1; | ||
| 699 | if (val32 & OTGSC_ASV) | ||
| 700 | iotg->hsm.a_sess_vld = 1; | ||
| 701 | if (val32 & OTGSC_AVV) | ||
| 702 | iotg->hsm.a_vbus_vld = 1; | ||
| 703 | |||
| 704 | /* defautly power the bus */ | ||
| 705 | iotg->hsm.a_bus_req = 1; | ||
| 706 | iotg->hsm.a_bus_drop = 0; | ||
| 707 | /* defautly don't request bus as B device */ | ||
| 708 | iotg->hsm.b_bus_req = 0; | ||
| 709 | /* no system error */ | ||
| 710 | iotg->hsm.a_clr_err = 0; | ||
| 711 | |||
| 712 | langwell_otg_phy_low_power_wait(1); | ||
| 713 | } | ||
| 714 | |||
| 715 | static void update_hsm(void) | ||
| 716 | { | ||
| 717 | struct langwell_otg *lnw = the_transceiver; | ||
| 718 | struct intel_mid_otg_xceiv *iotg = &lnw->iotg; | ||
| 719 | u32 val32; | ||
| 720 | |||
| 721 | /* read OTGSC */ | ||
| 722 | val32 = readl(lnw->iotg.base + CI_OTGSC); | ||
| 723 | dev_dbg(lnw->dev, "%s: OTGSC value = 0x%x\n", __func__, val32); | ||
| 724 | |||
| 725 | iotg->hsm.id = !!(val32 & OTGSC_ID); | ||
| 726 | iotg->hsm.b_sess_end = !!(val32 & OTGSC_BSE); | ||
| 727 | iotg->hsm.b_sess_vld = !!(val32 & OTGSC_BSV); | ||
| 728 | iotg->hsm.a_sess_vld = !!(val32 & OTGSC_ASV); | ||
| 729 | iotg->hsm.a_vbus_vld = !!(val32 & OTGSC_AVV); | ||
| 730 | } | ||
| 731 | |||
| 732 | static irqreturn_t otg_dummy_irq(int irq, void *_dev) | ||
| 733 | { | ||
| 734 | struct langwell_otg *lnw = the_transceiver; | ||
| 735 | void __iomem *reg_base = _dev; | ||
| 736 | u32 val; | ||
| 737 | u32 int_mask = 0; | ||
| 738 | |||
| 739 | val = readl(reg_base + CI_USBMODE); | ||
| 740 | if ((val & USBMODE_CM) != USBMODE_DEVICE) | ||
| 741 | return IRQ_NONE; | ||
| 742 | |||
| 743 | val = readl(reg_base + CI_USBSTS); | ||
| 744 | int_mask = val & INTR_DUMMY_MASK; | ||
| 745 | |||
| 746 | if (int_mask == 0) | ||
| 747 | return IRQ_NONE; | ||
| 748 | |||
| 749 | /* clear hsm.b_conn here since host driver can't detect it | ||
| 750 | * otg_dummy_irq called means B-disconnect happened. | ||
| 751 | */ | ||
| 752 | if (lnw->iotg.hsm.b_conn) { | ||
| 753 | lnw->iotg.hsm.b_conn = 0; | ||
| 754 | if (spin_trylock(&lnw->wq_lock)) { | ||
| 755 | langwell_update_transceiver(); | ||
| 756 | spin_unlock(&lnw->wq_lock); | ||
| 757 | } | ||
| 758 | } | ||
| 759 | |||
| 760 | /* Clear interrupts */ | ||
| 761 | writel(int_mask, reg_base + CI_USBSTS); | ||
| 762 | return IRQ_HANDLED; | ||
| 763 | } | ||
| 764 | |||
| 765 | static irqreturn_t otg_irq(int irq, void *_dev) | ||
| 766 | { | ||
| 767 | struct langwell_otg *lnw = _dev; | ||
| 768 | struct intel_mid_otg_xceiv *iotg = &lnw->iotg; | ||
| 769 | u32 int_sts, int_en; | ||
| 770 | u32 int_mask = 0; | ||
| 771 | int flag = 0; | ||
| 772 | |||
| 773 | int_sts = readl(lnw->iotg.base + CI_OTGSC); | ||
| 774 | int_en = (int_sts & OTGSC_INTEN_MASK) >> 8; | ||
| 775 | int_mask = int_sts & int_en; | ||
| 776 | if (int_mask == 0) | ||
| 777 | return IRQ_NONE; | ||
| 778 | |||
| 779 | if (int_mask & OTGSC_IDIS) { | ||
| 780 | dev_dbg(lnw->dev, "%s: id change int\n", __func__); | ||
| 781 | iotg->hsm.id = (int_sts & OTGSC_ID) ? 1 : 0; | ||
| 782 | dev_dbg(lnw->dev, "id = %d\n", iotg->hsm.id); | ||
| 783 | flag = 1; | ||
| 784 | } | ||
| 785 | if (int_mask & OTGSC_DPIS) { | ||
| 786 | dev_dbg(lnw->dev, "%s: data pulse int\n", __func__); | ||
| 787 | iotg->hsm.a_srp_det = (int_sts & OTGSC_DPS) ? 1 : 0; | ||
| 788 | dev_dbg(lnw->dev, "data pulse = %d\n", iotg->hsm.a_srp_det); | ||
| 789 | flag = 1; | ||
| 790 | } | ||
| 791 | if (int_mask & OTGSC_BSEIS) { | ||
| 792 | dev_dbg(lnw->dev, "%s: b session end int\n", __func__); | ||
| 793 | iotg->hsm.b_sess_end = (int_sts & OTGSC_BSE) ? 1 : 0; | ||
| 794 | dev_dbg(lnw->dev, "b_sess_end = %d\n", iotg->hsm.b_sess_end); | ||
| 795 | flag = 1; | ||
| 796 | } | ||
| 797 | if (int_mask & OTGSC_BSVIS) { | ||
| 798 | dev_dbg(lnw->dev, "%s: b session valid int\n", __func__); | ||
| 799 | iotg->hsm.b_sess_vld = (int_sts & OTGSC_BSV) ? 1 : 0; | ||
| 800 | dev_dbg(lnw->dev, "b_sess_vld = %d\n", iotg->hsm.b_sess_end); | ||
| 801 | flag = 1; | ||
| 802 | } | ||
| 803 | if (int_mask & OTGSC_ASVIS) { | ||
| 804 | dev_dbg(lnw->dev, "%s: a session valid int\n", __func__); | ||
| 805 | iotg->hsm.a_sess_vld = (int_sts & OTGSC_ASV) ? 1 : 0; | ||
| 806 | dev_dbg(lnw->dev, "a_sess_vld = %d\n", iotg->hsm.a_sess_vld); | ||
| 807 | flag = 1; | ||
| 808 | } | ||
| 809 | if (int_mask & OTGSC_AVVIS) { | ||
| 810 | dev_dbg(lnw->dev, "%s: a vbus valid int\n", __func__); | ||
| 811 | iotg->hsm.a_vbus_vld = (int_sts & OTGSC_AVV) ? 1 : 0; | ||
| 812 | dev_dbg(lnw->dev, "a_vbus_vld = %d\n", iotg->hsm.a_vbus_vld); | ||
| 813 | flag = 1; | ||
| 814 | } | ||
| 815 | |||
| 816 | if (int_mask & OTGSC_1MSS) { | ||
| 817 | /* need to schedule otg_work if any timer is expired */ | ||
| 818 | if (langwell_otg_tick_timer(&int_sts)) | ||
| 819 | flag = 1; | ||
| 820 | } | ||
| 821 | |||
| 822 | writel((int_sts & ~OTGSC_INTSTS_MASK) | int_mask, | ||
| 823 | lnw->iotg.base + CI_OTGSC); | ||
| 824 | if (flag) | ||
| 825 | langwell_update_transceiver(); | ||
| 826 | |||
| 827 | return IRQ_HANDLED; | ||
| 828 | } | ||
| 829 | |||
| 830 | static int langwell_otg_iotg_notify(struct notifier_block *nb, | ||
| 831 | unsigned long action, void *data) | ||
| 832 | { | ||
| 833 | struct langwell_otg *lnw = the_transceiver; | ||
| 834 | struct intel_mid_otg_xceiv *iotg = data; | ||
| 835 | int flag = 0; | ||
| 836 | |||
| 837 | if (iotg == NULL) | ||
| 838 | return NOTIFY_BAD; | ||
| 839 | |||
| 840 | if (lnw == NULL) | ||
| 841 | return NOTIFY_BAD; | ||
| 842 | |||
| 843 | switch (action) { | ||
| 844 | case MID_OTG_NOTIFY_CONNECT: | ||
| 845 | dev_dbg(lnw->dev, "Lnw OTG Notify Connect Event\n"); | ||
| 846 | if (iotg->otg.default_a == 1) | ||
| 847 | iotg->hsm.b_conn = 1; | ||
| 848 | else | ||
| 849 | iotg->hsm.a_conn = 1; | ||
| 850 | flag = 1; | ||
| 851 | break; | ||
| 852 | case MID_OTG_NOTIFY_DISCONN: | ||
| 853 | dev_dbg(lnw->dev, "Lnw OTG Notify Disconnect Event\n"); | ||
| 854 | if (iotg->otg.default_a == 1) | ||
| 855 | iotg->hsm.b_conn = 0; | ||
| 856 | else | ||
| 857 | iotg->hsm.a_conn = 0; | ||
| 858 | flag = 1; | ||
| 859 | break; | ||
| 860 | case MID_OTG_NOTIFY_HSUSPEND: | ||
| 861 | dev_dbg(lnw->dev, "Lnw OTG Notify Host Bus suspend Event\n"); | ||
| 862 | if (iotg->otg.default_a == 1) | ||
| 863 | iotg->hsm.a_suspend_req = 1; | ||
| 864 | else | ||
| 865 | iotg->hsm.b_bus_req = 0; | ||
| 866 | flag = 1; | ||
| 867 | break; | ||
| 868 | case MID_OTG_NOTIFY_HRESUME: | ||
| 869 | dev_dbg(lnw->dev, "Lnw OTG Notify Host Bus resume Event\n"); | ||
| 870 | if (iotg->otg.default_a == 1) | ||
| 871 | iotg->hsm.b_bus_resume = 1; | ||
| 872 | flag = 1; | ||
| 873 | break; | ||
| 874 | case MID_OTG_NOTIFY_CSUSPEND: | ||
| 875 | dev_dbg(lnw->dev, "Lnw OTG Notify Client Bus suspend Event\n"); | ||
| 876 | if (iotg->otg.default_a == 1) { | ||
| 877 | if (iotg->hsm.b_bus_suspend_vld == 2) { | ||
| 878 | iotg->hsm.b_bus_suspend = 1; | ||
| 879 | iotg->hsm.b_bus_suspend_vld = 0; | ||
| 880 | flag = 1; | ||
| 881 | } else { | ||
| 882 | iotg->hsm.b_bus_suspend_vld++; | ||
| 883 | flag = 0; | ||
| 884 | } | ||
| 885 | } else { | ||
| 886 | if (iotg->hsm.a_bus_suspend == 0) { | ||
| 887 | iotg->hsm.a_bus_suspend = 1; | ||
| 888 | flag = 1; | ||
| 889 | } | ||
| 890 | } | ||
| 891 | break; | ||
| 892 | case MID_OTG_NOTIFY_CRESUME: | ||
| 893 | dev_dbg(lnw->dev, "Lnw OTG Notify Client Bus resume Event\n"); | ||
| 894 | if (iotg->otg.default_a == 0) | ||
| 895 | iotg->hsm.a_bus_suspend = 0; | ||
| 896 | flag = 0; | ||
| 897 | break; | ||
| 898 | case MID_OTG_NOTIFY_HOSTADD: | ||
| 899 | dev_dbg(lnw->dev, "Lnw OTG Nofity Host Driver Add\n"); | ||
| 900 | flag = 1; | ||
| 901 | break; | ||
| 902 | case MID_OTG_NOTIFY_HOSTREMOVE: | ||
| 903 | dev_dbg(lnw->dev, "Lnw OTG Nofity Host Driver remove\n"); | ||
| 904 | flag = 1; | ||
| 905 | break; | ||
| 906 | case MID_OTG_NOTIFY_CLIENTADD: | ||
| 907 | dev_dbg(lnw->dev, "Lnw OTG Nofity Client Driver Add\n"); | ||
| 908 | flag = 1; | ||
| 909 | break; | ||
| 910 | case MID_OTG_NOTIFY_CLIENTREMOVE: | ||
| 911 | dev_dbg(lnw->dev, "Lnw OTG Nofity Client Driver remove\n"); | ||
| 912 | flag = 1; | ||
| 913 | break; | ||
| 914 | default: | ||
| 915 | dev_dbg(lnw->dev, "Lnw OTG Nofity unknown notify message\n"); | ||
| 916 | return NOTIFY_DONE; | ||
| 917 | } | ||
| 918 | |||
| 919 | if (flag) | ||
| 920 | langwell_update_transceiver(); | ||
| 921 | |||
| 922 | return NOTIFY_OK; | ||
| 923 | } | ||
| 924 | |||
| 925 | static void langwell_otg_work(struct work_struct *work) | ||
| 926 | { | ||
| 927 | struct langwell_otg *lnw; | ||
| 928 | struct intel_mid_otg_xceiv *iotg; | ||
| 929 | int retval; | ||
| 930 | struct pci_dev *pdev; | ||
| 931 | |||
| 932 | lnw = container_of(work, struct langwell_otg, work); | ||
| 933 | iotg = &lnw->iotg; | ||
| 934 | pdev = to_pci_dev(lnw->dev); | ||
| 935 | |||
| 936 | dev_dbg(lnw->dev, "%s: old state = %s\n", __func__, | ||
| 937 | otg_state_string(iotg->otg.state)); | ||
| 938 | |||
| 939 | switch (iotg->otg.state) { | ||
| 940 | case OTG_STATE_UNDEFINED: | ||
| 941 | case OTG_STATE_B_IDLE: | ||
| 942 | if (!iotg->hsm.id) { | ||
| 943 | langwell_otg_del_timer(b_srp_init_tmr); | ||
| 944 | del_timer_sync(&lnw->hsm_timer); | ||
| 945 | |||
| 946 | iotg->otg.default_a = 1; | ||
| 947 | iotg->hsm.a_srp_det = 0; | ||
| 948 | |||
| 949 | langwell_otg_chrg_vbus(0); | ||
| 950 | set_host_mode(); | ||
| 951 | langwell_otg_phy_low_power(1); | ||
| 952 | |||
| 953 | iotg->otg.state = OTG_STATE_A_IDLE; | ||
| 954 | langwell_update_transceiver(); | ||
| 955 | } else if (iotg->hsm.b_sess_vld) { | ||
| 956 | langwell_otg_del_timer(b_srp_init_tmr); | ||
| 957 | del_timer_sync(&lnw->hsm_timer); | ||
| 958 | iotg->hsm.b_sess_end = 0; | ||
| 959 | iotg->hsm.a_bus_suspend = 0; | ||
| 960 | langwell_otg_chrg_vbus(0); | ||
| 961 | |||
| 962 | if (lnw->iotg.start_peripheral) { | ||
| 963 | lnw->iotg.start_peripheral(&lnw->iotg); | ||
| 964 | iotg->otg.state = OTG_STATE_B_PERIPHERAL; | ||
| 965 | } else | ||
| 966 | dev_dbg(lnw->dev, "client driver not loaded\n"); | ||
| 967 | |||
| 968 | } else if (iotg->hsm.b_srp_init_tmout) { | ||
| 969 | iotg->hsm.b_srp_init_tmout = 0; | ||
| 970 | dev_warn(lnw->dev, "SRP init timeout\n"); | ||
| 971 | } else if (iotg->hsm.b_srp_fail_tmout) { | ||
| 972 | iotg->hsm.b_srp_fail_tmout = 0; | ||
| 973 | iotg->hsm.b_bus_req = 0; | ||
| 974 | |||
| 975 | /* No silence failure */ | ||
| 976 | langwell_otg_nsf_msg(6); | ||
| 977 | } else if (iotg->hsm.b_bus_req && iotg->hsm.b_sess_end) { | ||
| 978 | del_timer_sync(&lnw->hsm_timer); | ||
| 979 | /* workaround for b_se0_srp detection */ | ||
| 980 | retval = langwell_otg_check_se0_srp(0); | ||
| 981 | if (retval) { | ||
| 982 | iotg->hsm.b_bus_req = 0; | ||
| 983 | dev_dbg(lnw->dev, "LS isn't SE0, try later\n"); | ||
| 984 | } else { | ||
| 985 | /* clear the PHCD before start srp */ | ||
| 986 | langwell_otg_phy_low_power(0); | ||
| 987 | |||
| 988 | /* Start SRP */ | ||
| 989 | langwell_otg_add_timer(b_srp_init_tmr); | ||
| 990 | iotg->otg.start_srp(&iotg->otg); | ||
| 991 | langwell_otg_del_timer(b_srp_init_tmr); | ||
| 992 | langwell_otg_add_ktimer(TB_SRP_FAIL_TMR); | ||
| 993 | |||
| 994 | /* reset PHY low power mode here */ | ||
| 995 | langwell_otg_phy_low_power_wait(1); | ||
| 996 | } | ||
| 997 | } | ||
| 998 | break; | ||
| 999 | case OTG_STATE_B_SRP_INIT: | ||
| 1000 | if (!iotg->hsm.id) { | ||
| 1001 | iotg->otg.default_a = 1; | ||
| 1002 | iotg->hsm.a_srp_det = 0; | ||
| 1003 | |||
| 1004 | /* Turn off VBus */ | ||
| 1005 | iotg->otg.set_vbus(&iotg->otg, false); | ||
| 1006 | langwell_otg_chrg_vbus(0); | ||
| 1007 | set_host_mode(); | ||
| 1008 | langwell_otg_phy_low_power(1); | ||
| 1009 | iotg->otg.state = OTG_STATE_A_IDLE; | ||
| 1010 | langwell_update_transceiver(); | ||
| 1011 | } else if (iotg->hsm.b_sess_vld) { | ||
| 1012 | langwell_otg_chrg_vbus(0); | ||
| 1013 | if (lnw->iotg.start_peripheral) { | ||
| 1014 | lnw->iotg.start_peripheral(&lnw->iotg); | ||
| 1015 | iotg->otg.state = OTG_STATE_B_PERIPHERAL; | ||
| 1016 | } else | ||
| 1017 | dev_dbg(lnw->dev, "client driver not loaded\n"); | ||
| 1018 | } | ||
| 1019 | break; | ||
| 1020 | case OTG_STATE_B_PERIPHERAL: | ||
| 1021 | if (!iotg->hsm.id) { | ||
| 1022 | iotg->otg.default_a = 1; | ||
| 1023 | iotg->hsm.a_srp_det = 0; | ||
| 1024 | |||
| 1025 | langwell_otg_chrg_vbus(0); | ||
| 1026 | |||
| 1027 | if (lnw->iotg.stop_peripheral) | ||
| 1028 | lnw->iotg.stop_peripheral(&lnw->iotg); | ||
| 1029 | else | ||
| 1030 | dev_dbg(lnw->dev, | ||
| 1031 | "client driver has been removed.\n"); | ||
| 1032 | |||
| 1033 | set_host_mode(); | ||
| 1034 | langwell_otg_phy_low_power(1); | ||
| 1035 | iotg->otg.state = OTG_STATE_A_IDLE; | ||
| 1036 | langwell_update_transceiver(); | ||
| 1037 | } else if (!iotg->hsm.b_sess_vld) { | ||
| 1038 | iotg->hsm.b_hnp_enable = 0; | ||
| 1039 | |||
| 1040 | if (lnw->iotg.stop_peripheral) | ||
| 1041 | lnw->iotg.stop_peripheral(&lnw->iotg); | ||
| 1042 | else | ||
| 1043 | dev_dbg(lnw->dev, | ||
| 1044 | "client driver has been removed.\n"); | ||
| 1045 | |||
| 1046 | iotg->otg.state = OTG_STATE_B_IDLE; | ||
| 1047 | } else if (iotg->hsm.b_bus_req && iotg->otg.gadget && | ||
| 1048 | iotg->otg.gadget->b_hnp_enable && | ||
| 1049 | iotg->hsm.a_bus_suspend) { | ||
| 1050 | |||
| 1051 | if (lnw->iotg.stop_peripheral) | ||
| 1052 | lnw->iotg.stop_peripheral(&lnw->iotg); | ||
| 1053 | else | ||
| 1054 | dev_dbg(lnw->dev, | ||
| 1055 | "client driver has been removed.\n"); | ||
| 1056 | |||
| 1057 | langwell_otg_HAAR(1); | ||
| 1058 | iotg->hsm.a_conn = 0; | ||
| 1059 | |||
| 1060 | if (lnw->iotg.start_host) { | ||
| 1061 | lnw->iotg.start_host(&lnw->iotg); | ||
| 1062 | iotg->otg.state = OTG_STATE_B_WAIT_ACON; | ||
| 1063 | } else | ||
| 1064 | dev_dbg(lnw->dev, | ||
| 1065 | "host driver not loaded.\n"); | ||
| 1066 | |||
| 1067 | iotg->hsm.a_bus_resume = 0; | ||
| 1068 | langwell_otg_add_ktimer(TB_ASE0_BRST_TMR); | ||
| 1069 | } | ||
| 1070 | break; | ||
| 1071 | |||
| 1072 | case OTG_STATE_B_WAIT_ACON: | ||
| 1073 | if (!iotg->hsm.id) { | ||
| 1074 | /* delete hsm timer for b_ase0_brst_tmr */ | ||
| 1075 | del_timer_sync(&lnw->hsm_timer); | ||
| 1076 | |||
| 1077 | iotg->otg.default_a = 1; | ||
| 1078 | iotg->hsm.a_srp_det = 0; | ||
| 1079 | |||
| 1080 | langwell_otg_chrg_vbus(0); | ||
| 1081 | |||
| 1082 | langwell_otg_HAAR(0); | ||
| 1083 | if (lnw->iotg.stop_host) | ||
| 1084 | lnw->iotg.stop_host(&lnw->iotg); | ||
| 1085 | else | ||
| 1086 | dev_dbg(lnw->dev, | ||
| 1087 | "host driver has been removed.\n"); | ||
| 1088 | |||
| 1089 | set_host_mode(); | ||
| 1090 | langwell_otg_phy_low_power(1); | ||
| 1091 | iotg->otg.state = OTG_STATE_A_IDLE; | ||
| 1092 | langwell_update_transceiver(); | ||
| 1093 | } else if (!iotg->hsm.b_sess_vld) { | ||
| 1094 | /* delete hsm timer for b_ase0_brst_tmr */ | ||
| 1095 | del_timer_sync(&lnw->hsm_timer); | ||
| 1096 | |||
| 1097 | iotg->hsm.b_hnp_enable = 0; | ||
| 1098 | iotg->hsm.b_bus_req = 0; | ||
| 1099 | |||
| 1100 | langwell_otg_chrg_vbus(0); | ||
| 1101 | langwell_otg_HAAR(0); | ||
| 1102 | |||
| 1103 | if (lnw->iotg.stop_host) | ||
| 1104 | lnw->iotg.stop_host(&lnw->iotg); | ||
| 1105 | else | ||
| 1106 | dev_dbg(lnw->dev, | ||
| 1107 | "host driver has been removed.\n"); | ||
| 1108 | |||
| 1109 | set_client_mode(); | ||
| 1110 | langwell_otg_phy_low_power(1); | ||
| 1111 | iotg->otg.state = OTG_STATE_B_IDLE; | ||
| 1112 | } else if (iotg->hsm.a_conn) { | ||
| 1113 | /* delete hsm timer for b_ase0_brst_tmr */ | ||
| 1114 | del_timer_sync(&lnw->hsm_timer); | ||
| 1115 | |||
| 1116 | langwell_otg_HAAR(0); | ||
| 1117 | iotg->otg.state = OTG_STATE_B_HOST; | ||
| 1118 | langwell_update_transceiver(); | ||
| 1119 | } else if (iotg->hsm.a_bus_resume || | ||
| 1120 | iotg->hsm.b_ase0_brst_tmout) { | ||
| 1121 | /* delete hsm timer for b_ase0_brst_tmr */ | ||
| 1122 | del_timer_sync(&lnw->hsm_timer); | ||
| 1123 | |||
| 1124 | langwell_otg_HAAR(0); | ||
| 1125 | langwell_otg_nsf_msg(7); | ||
| 1126 | |||
| 1127 | if (lnw->iotg.stop_host) | ||
| 1128 | lnw->iotg.stop_host(&lnw->iotg); | ||
| 1129 | else | ||
| 1130 | dev_dbg(lnw->dev, | ||
| 1131 | "host driver has been removed.\n"); | ||
| 1132 | |||
| 1133 | iotg->hsm.a_bus_suspend = 0; | ||
| 1134 | iotg->hsm.b_bus_req = 0; | ||
| 1135 | |||
| 1136 | if (lnw->iotg.start_peripheral) | ||
| 1137 | lnw->iotg.start_peripheral(&lnw->iotg); | ||
| 1138 | else | ||
| 1139 | dev_dbg(lnw->dev, | ||
| 1140 | "client driver not loaded.\n"); | ||
| 1141 | |||
| 1142 | iotg->otg.state = OTG_STATE_B_PERIPHERAL; | ||
| 1143 | } | ||
| 1144 | break; | ||
| 1145 | |||
| 1146 | case OTG_STATE_B_HOST: | ||
| 1147 | if (!iotg->hsm.id) { | ||
| 1148 | iotg->otg.default_a = 1; | ||
| 1149 | iotg->hsm.a_srp_det = 0; | ||
| 1150 | |||
| 1151 | langwell_otg_chrg_vbus(0); | ||
| 1152 | |||
| 1153 | if (lnw->iotg.stop_host) | ||
| 1154 | lnw->iotg.stop_host(&lnw->iotg); | ||
| 1155 | else | ||
| 1156 | dev_dbg(lnw->dev, | ||
| 1157 | "host driver has been removed.\n"); | ||
| 1158 | |||
| 1159 | set_host_mode(); | ||
| 1160 | langwell_otg_phy_low_power(1); | ||
| 1161 | iotg->otg.state = OTG_STATE_A_IDLE; | ||
| 1162 | langwell_update_transceiver(); | ||
| 1163 | } else if (!iotg->hsm.b_sess_vld) { | ||
| 1164 | iotg->hsm.b_hnp_enable = 0; | ||
| 1165 | iotg->hsm.b_bus_req = 0; | ||
| 1166 | |||
| 1167 | langwell_otg_chrg_vbus(0); | ||
| 1168 | if (lnw->iotg.stop_host) | ||
| 1169 | lnw->iotg.stop_host(&lnw->iotg); | ||
| 1170 | else | ||
| 1171 | dev_dbg(lnw->dev, | ||
| 1172 | "host driver has been removed.\n"); | ||
| 1173 | |||
| 1174 | set_client_mode(); | ||
| 1175 | langwell_otg_phy_low_power(1); | ||
| 1176 | iotg->otg.state = OTG_STATE_B_IDLE; | ||
| 1177 | } else if ((!iotg->hsm.b_bus_req) || | ||
| 1178 | (!iotg->hsm.a_conn)) { | ||
| 1179 | iotg->hsm.b_bus_req = 0; | ||
| 1180 | langwell_otg_loc_sof(0); | ||
| 1181 | |||
| 1182 | if (lnw->iotg.stop_host) | ||
| 1183 | lnw->iotg.stop_host(&lnw->iotg); | ||
| 1184 | else | ||
| 1185 | dev_dbg(lnw->dev, | ||
| 1186 | "host driver has been removed.\n"); | ||
| 1187 | |||
| 1188 | iotg->hsm.a_bus_suspend = 0; | ||
| 1189 | |||
| 1190 | if (lnw->iotg.start_peripheral) | ||
| 1191 | lnw->iotg.start_peripheral(&lnw->iotg); | ||
| 1192 | else | ||
| 1193 | dev_dbg(lnw->dev, | ||
| 1194 | "client driver not loaded.\n"); | ||
| 1195 | |||
| 1196 | iotg->otg.state = OTG_STATE_B_PERIPHERAL; | ||
| 1197 | } | ||
| 1198 | break; | ||
| 1199 | |||
| 1200 | case OTG_STATE_A_IDLE: | ||
| 1201 | iotg->otg.default_a = 1; | ||
| 1202 | if (iotg->hsm.id) { | ||
| 1203 | iotg->otg.default_a = 0; | ||
| 1204 | iotg->hsm.b_bus_req = 0; | ||
| 1205 | iotg->hsm.vbus_srp_up = 0; | ||
| 1206 | |||
| 1207 | langwell_otg_chrg_vbus(0); | ||
| 1208 | set_client_mode(); | ||
| 1209 | langwell_otg_phy_low_power(1); | ||
| 1210 | iotg->otg.state = OTG_STATE_B_IDLE; | ||
| 1211 | langwell_update_transceiver(); | ||
| 1212 | } else if (!iotg->hsm.a_bus_drop && | ||
| 1213 | (iotg->hsm.a_srp_det || iotg->hsm.a_bus_req)) { | ||
| 1214 | langwell_otg_phy_low_power(0); | ||
| 1215 | |||
| 1216 | /* Turn on VBus */ | ||
| 1217 | iotg->otg.set_vbus(&iotg->otg, true); | ||
| 1218 | |||
| 1219 | iotg->hsm.vbus_srp_up = 0; | ||
| 1220 | iotg->hsm.a_wait_vrise_tmout = 0; | ||
| 1221 | langwell_otg_add_timer(a_wait_vrise_tmr); | ||
| 1222 | iotg->otg.state = OTG_STATE_A_WAIT_VRISE; | ||
| 1223 | langwell_update_transceiver(); | ||
| 1224 | } else if (!iotg->hsm.a_bus_drop && iotg->hsm.a_sess_vld) { | ||
| 1225 | iotg->hsm.vbus_srp_up = 1; | ||
| 1226 | } else if (!iotg->hsm.a_sess_vld && iotg->hsm.vbus_srp_up) { | ||
| 1227 | msleep(10); | ||
| 1228 | langwell_otg_phy_low_power(0); | ||
| 1229 | |||
| 1230 | /* Turn on VBus */ | ||
| 1231 | iotg->otg.set_vbus(&iotg->otg, true); | ||
| 1232 | iotg->hsm.a_srp_det = 1; | ||
| 1233 | iotg->hsm.vbus_srp_up = 0; | ||
| 1234 | iotg->hsm.a_wait_vrise_tmout = 0; | ||
| 1235 | langwell_otg_add_timer(a_wait_vrise_tmr); | ||
| 1236 | iotg->otg.state = OTG_STATE_A_WAIT_VRISE; | ||
| 1237 | langwell_update_transceiver(); | ||
| 1238 | } else if (!iotg->hsm.a_sess_vld && | ||
| 1239 | !iotg->hsm.vbus_srp_up) { | ||
| 1240 | langwell_otg_phy_low_power(1); | ||
| 1241 | } | ||
| 1242 | break; | ||
| 1243 | case OTG_STATE_A_WAIT_VRISE: | ||
| 1244 | if (iotg->hsm.id) { | ||
| 1245 | langwell_otg_del_timer(a_wait_vrise_tmr); | ||
| 1246 | iotg->hsm.b_bus_req = 0; | ||
| 1247 | iotg->otg.default_a = 0; | ||
| 1248 | |||
| 1249 | /* Turn off VBus */ | ||
| 1250 | iotg->otg.set_vbus(&iotg->otg, false); | ||
| 1251 | set_client_mode(); | ||
| 1252 | langwell_otg_phy_low_power_wait(1); | ||
| 1253 | iotg->otg.state = OTG_STATE_B_IDLE; | ||
| 1254 | } else if (iotg->hsm.a_vbus_vld) { | ||
| 1255 | langwell_otg_del_timer(a_wait_vrise_tmr); | ||
| 1256 | iotg->hsm.b_conn = 0; | ||
| 1257 | if (lnw->iotg.start_host) | ||
| 1258 | lnw->iotg.start_host(&lnw->iotg); | ||
| 1259 | else { | ||
| 1260 | dev_dbg(lnw->dev, "host driver not loaded.\n"); | ||
| 1261 | break; | ||
| 1262 | } | ||
| 1263 | |||
| 1264 | langwell_otg_add_ktimer(TA_WAIT_BCON_TMR); | ||
| 1265 | iotg->otg.state = OTG_STATE_A_WAIT_BCON; | ||
| 1266 | } else if (iotg->hsm.a_wait_vrise_tmout) { | ||
| 1267 | iotg->hsm.b_conn = 0; | ||
| 1268 | if (iotg->hsm.a_vbus_vld) { | ||
| 1269 | if (lnw->iotg.start_host) | ||
| 1270 | lnw->iotg.start_host(&lnw->iotg); | ||
| 1271 | else { | ||
| 1272 | dev_dbg(lnw->dev, | ||
| 1273 | "host driver not loaded.\n"); | ||
| 1274 | break; | ||
| 1275 | } | ||
| 1276 | langwell_otg_add_ktimer(TA_WAIT_BCON_TMR); | ||
| 1277 | iotg->otg.state = OTG_STATE_A_WAIT_BCON; | ||
| 1278 | } else { | ||
| 1279 | |||
| 1280 | /* Turn off VBus */ | ||
| 1281 | iotg->otg.set_vbus(&iotg->otg, false); | ||
| 1282 | langwell_otg_phy_low_power_wait(1); | ||
| 1283 | iotg->otg.state = OTG_STATE_A_VBUS_ERR; | ||
| 1284 | } | ||
| 1285 | } | ||
| 1286 | break; | ||
| 1287 | case OTG_STATE_A_WAIT_BCON: | ||
| 1288 | if (iotg->hsm.id) { | ||
| 1289 | /* delete hsm timer for a_wait_bcon_tmr */ | ||
| 1290 | del_timer_sync(&lnw->hsm_timer); | ||
| 1291 | |||
| 1292 | iotg->otg.default_a = 0; | ||
| 1293 | iotg->hsm.b_bus_req = 0; | ||
| 1294 | |||
| 1295 | if (lnw->iotg.stop_host) | ||
| 1296 | lnw->iotg.stop_host(&lnw->iotg); | ||
| 1297 | else | ||
| 1298 | dev_dbg(lnw->dev, | ||
| 1299 | "host driver has been removed.\n"); | ||
| 1300 | |||
| 1301 | /* Turn off VBus */ | ||
| 1302 | iotg->otg.set_vbus(&iotg->otg, false); | ||
| 1303 | set_client_mode(); | ||
| 1304 | langwell_otg_phy_low_power_wait(1); | ||
| 1305 | iotg->otg.state = OTG_STATE_B_IDLE; | ||
| 1306 | langwell_update_transceiver(); | ||
| 1307 | } else if (!iotg->hsm.a_vbus_vld) { | ||
| 1308 | /* delete hsm timer for a_wait_bcon_tmr */ | ||
| 1309 | del_timer_sync(&lnw->hsm_timer); | ||
| 1310 | |||
| 1311 | if (lnw->iotg.stop_host) | ||
| 1312 | lnw->iotg.stop_host(&lnw->iotg); | ||
| 1313 | else | ||
| 1314 | dev_dbg(lnw->dev, | ||
| 1315 | "host driver has been removed.\n"); | ||
| 1316 | |||
| 1317 | /* Turn off VBus */ | ||
| 1318 | iotg->otg.set_vbus(&iotg->otg, false); | ||
| 1319 | langwell_otg_phy_low_power_wait(1); | ||
| 1320 | iotg->otg.state = OTG_STATE_A_VBUS_ERR; | ||
| 1321 | } else if (iotg->hsm.a_bus_drop || | ||
| 1322 | (iotg->hsm.a_wait_bcon_tmout && | ||
| 1323 | !iotg->hsm.a_bus_req)) { | ||
| 1324 | /* delete hsm timer for a_wait_bcon_tmr */ | ||
| 1325 | del_timer_sync(&lnw->hsm_timer); | ||
| 1326 | |||
| 1327 | if (lnw->iotg.stop_host) | ||
| 1328 | lnw->iotg.stop_host(&lnw->iotg); | ||
| 1329 | else | ||
| 1330 | dev_dbg(lnw->dev, | ||
| 1331 | "host driver has been removed.\n"); | ||
| 1332 | |||
| 1333 | /* Turn off VBus */ | ||
| 1334 | iotg->otg.set_vbus(&iotg->otg, false); | ||
| 1335 | iotg->otg.state = OTG_STATE_A_WAIT_VFALL; | ||
| 1336 | } else if (iotg->hsm.b_conn) { | ||
| 1337 | /* delete hsm timer for a_wait_bcon_tmr */ | ||
| 1338 | del_timer_sync(&lnw->hsm_timer); | ||
| 1339 | |||
| 1340 | iotg->hsm.a_suspend_req = 0; | ||
| 1341 | iotg->otg.state = OTG_STATE_A_HOST; | ||
| 1342 | if (iotg->hsm.a_srp_det && iotg->otg.host && | ||
| 1343 | !iotg->otg.host->b_hnp_enable) { | ||
| 1344 | /* SRP capable peripheral-only device */ | ||
| 1345 | iotg->hsm.a_bus_req = 1; | ||
| 1346 | iotg->hsm.a_srp_det = 0; | ||
| 1347 | } else if (!iotg->hsm.a_bus_req && iotg->otg.host && | ||
| 1348 | iotg->otg.host->b_hnp_enable) { | ||
| 1349 | /* It is not safe enough to do a fast | ||
| 1350 | * transition from A_WAIT_BCON to | ||
| 1351 | * A_SUSPEND */ | ||
| 1352 | msleep(10000); | ||
| 1353 | if (iotg->hsm.a_bus_req) | ||
| 1354 | break; | ||
| 1355 | |||
| 1356 | if (request_irq(pdev->irq, | ||
| 1357 | otg_dummy_irq, IRQF_SHARED, | ||
| 1358 | driver_name, iotg->base) != 0) { | ||
| 1359 | dev_dbg(lnw->dev, | ||
| 1360 | "request interrupt %d fail\n", | ||
| 1361 | pdev->irq); | ||
| 1362 | } | ||
| 1363 | |||
| 1364 | langwell_otg_HABA(1); | ||
| 1365 | iotg->hsm.b_bus_resume = 0; | ||
| 1366 | iotg->hsm.a_aidl_bdis_tmout = 0; | ||
| 1367 | |||
| 1368 | langwell_otg_loc_sof(0); | ||
| 1369 | /* clear PHCD to enable HW timer */ | ||
| 1370 | langwell_otg_phy_low_power(0); | ||
| 1371 | langwell_otg_add_timer(a_aidl_bdis_tmr); | ||
| 1372 | iotg->otg.state = OTG_STATE_A_SUSPEND; | ||
| 1373 | } else if (!iotg->hsm.a_bus_req && iotg->otg.host && | ||
| 1374 | !iotg->otg.host->b_hnp_enable) { | ||
| 1375 | if (lnw->iotg.stop_host) | ||
| 1376 | lnw->iotg.stop_host(&lnw->iotg); | ||
| 1377 | else | ||
| 1378 | dev_dbg(lnw->dev, | ||
| 1379 | "host driver removed.\n"); | ||
| 1380 | |||
| 1381 | /* Turn off VBus */ | ||
| 1382 | iotg->otg.set_vbus(&iotg->otg, false); | ||
| 1383 | iotg->otg.state = OTG_STATE_A_WAIT_VFALL; | ||
| 1384 | } | ||
| 1385 | } | ||
| 1386 | break; | ||
| 1387 | case OTG_STATE_A_HOST: | ||
| 1388 | if (iotg->hsm.id) { | ||
| 1389 | iotg->otg.default_a = 0; | ||
| 1390 | iotg->hsm.b_bus_req = 0; | ||
| 1391 | |||
| 1392 | if (lnw->iotg.stop_host) | ||
| 1393 | lnw->iotg.stop_host(&lnw->iotg); | ||
| 1394 | else | ||
| 1395 | dev_dbg(lnw->dev, | ||
| 1396 | "host driver has been removed.\n"); | ||
| 1397 | |||
| 1398 | /* Turn off VBus */ | ||
| 1399 | iotg->otg.set_vbus(&iotg->otg, false); | ||
| 1400 | set_client_mode(); | ||
| 1401 | langwell_otg_phy_low_power_wait(1); | ||
| 1402 | iotg->otg.state = OTG_STATE_B_IDLE; | ||
| 1403 | langwell_update_transceiver(); | ||
| 1404 | } else if (iotg->hsm.a_bus_drop || | ||
| 1405 | (iotg->otg.host && | ||
| 1406 | !iotg->otg.host->b_hnp_enable && | ||
| 1407 | !iotg->hsm.a_bus_req)) { | ||
| 1408 | if (lnw->iotg.stop_host) | ||
| 1409 | lnw->iotg.stop_host(&lnw->iotg); | ||
| 1410 | else | ||
| 1411 | dev_dbg(lnw->dev, | ||
| 1412 | "host driver has been removed.\n"); | ||
| 1413 | |||
| 1414 | /* Turn off VBus */ | ||
| 1415 | iotg->otg.set_vbus(&iotg->otg, false); | ||
| 1416 | iotg->otg.state = OTG_STATE_A_WAIT_VFALL; | ||
| 1417 | } else if (!iotg->hsm.a_vbus_vld) { | ||
| 1418 | if (lnw->iotg.stop_host) | ||
| 1419 | lnw->iotg.stop_host(&lnw->iotg); | ||
| 1420 | else | ||
| 1421 | dev_dbg(lnw->dev, | ||
| 1422 | "host driver has been removed.\n"); | ||
| 1423 | |||
| 1424 | /* Turn off VBus */ | ||
| 1425 | iotg->otg.set_vbus(&iotg->otg, false); | ||
| 1426 | langwell_otg_phy_low_power_wait(1); | ||
| 1427 | iotg->otg.state = OTG_STATE_A_VBUS_ERR; | ||
| 1428 | } else if (iotg->otg.host && | ||
| 1429 | iotg->otg.host->b_hnp_enable && | ||
| 1430 | !iotg->hsm.a_bus_req) { | ||
| 1431 | /* Set HABA to enable hardware assistance to signal | ||
| 1432 | * A-connect after receiver B-disconnect. Hardware | ||
| 1433 | * will then set client mode and enable URE, SLE and | ||
| 1434 | * PCE after the assistance. otg_dummy_irq is used to | ||
| 1435 | * clean these ints when client driver is not resumed. | ||
| 1436 | */ | ||
| 1437 | if (request_irq(pdev->irq, otg_dummy_irq, IRQF_SHARED, | ||
| 1438 | driver_name, iotg->base) != 0) { | ||
| 1439 | dev_dbg(lnw->dev, | ||
| 1440 | "request interrupt %d failed\n", | ||
| 1441 | pdev->irq); | ||
| 1442 | } | ||
| 1443 | |||
| 1444 | /* set HABA */ | ||
| 1445 | langwell_otg_HABA(1); | ||
| 1446 | iotg->hsm.b_bus_resume = 0; | ||
| 1447 | iotg->hsm.a_aidl_bdis_tmout = 0; | ||
| 1448 | langwell_otg_loc_sof(0); | ||
| 1449 | /* clear PHCD to enable HW timer */ | ||
| 1450 | langwell_otg_phy_low_power(0); | ||
| 1451 | langwell_otg_add_timer(a_aidl_bdis_tmr); | ||
| 1452 | iotg->otg.state = OTG_STATE_A_SUSPEND; | ||
| 1453 | } else if (!iotg->hsm.b_conn || !iotg->hsm.a_bus_req) { | ||
| 1454 | langwell_otg_add_ktimer(TA_WAIT_BCON_TMR); | ||
| 1455 | iotg->otg.state = OTG_STATE_A_WAIT_BCON; | ||
| 1456 | } | ||
| 1457 | break; | ||
| 1458 | case OTG_STATE_A_SUSPEND: | ||
| 1459 | if (iotg->hsm.id) { | ||
| 1460 | langwell_otg_del_timer(a_aidl_bdis_tmr); | ||
| 1461 | langwell_otg_HABA(0); | ||
| 1462 | free_irq(pdev->irq, iotg->base); | ||
| 1463 | iotg->otg.default_a = 0; | ||
| 1464 | iotg->hsm.b_bus_req = 0; | ||
| 1465 | |||
| 1466 | if (lnw->iotg.stop_host) | ||
| 1467 | lnw->iotg.stop_host(&lnw->iotg); | ||
| 1468 | else | ||
| 1469 | dev_dbg(lnw->dev, | ||
| 1470 | "host driver has been removed.\n"); | ||
| 1471 | |||
| 1472 | /* Turn off VBus */ | ||
| 1473 | iotg->otg.set_vbus(&iotg->otg, false); | ||
| 1474 | set_client_mode(); | ||
| 1475 | langwell_otg_phy_low_power(1); | ||
| 1476 | iotg->otg.state = OTG_STATE_B_IDLE; | ||
| 1477 | langwell_update_transceiver(); | ||
| 1478 | } else if (iotg->hsm.a_bus_req || | ||
| 1479 | iotg->hsm.b_bus_resume) { | ||
| 1480 | langwell_otg_del_timer(a_aidl_bdis_tmr); | ||
| 1481 | langwell_otg_HABA(0); | ||
| 1482 | free_irq(pdev->irq, iotg->base); | ||
| 1483 | iotg->hsm.a_suspend_req = 0; | ||
| 1484 | langwell_otg_loc_sof(1); | ||
| 1485 | iotg->otg.state = OTG_STATE_A_HOST; | ||
| 1486 | } else if (iotg->hsm.a_aidl_bdis_tmout || | ||
| 1487 | iotg->hsm.a_bus_drop) { | ||
| 1488 | langwell_otg_del_timer(a_aidl_bdis_tmr); | ||
| 1489 | langwell_otg_HABA(0); | ||
| 1490 | free_irq(pdev->irq, iotg->base); | ||
| 1491 | if (lnw->iotg.stop_host) | ||
| 1492 | lnw->iotg.stop_host(&lnw->iotg); | ||
| 1493 | else | ||
| 1494 | dev_dbg(lnw->dev, | ||
| 1495 | "host driver has been removed.\n"); | ||
| 1496 | |||
| 1497 | /* Turn off VBus */ | ||
| 1498 | iotg->otg.set_vbus(&iotg->otg, false); | ||
| 1499 | iotg->otg.state = OTG_STATE_A_WAIT_VFALL; | ||
| 1500 | } else if (!iotg->hsm.b_conn && iotg->otg.host && | ||
| 1501 | iotg->otg.host->b_hnp_enable) { | ||
| 1502 | langwell_otg_del_timer(a_aidl_bdis_tmr); | ||
| 1503 | langwell_otg_HABA(0); | ||
| 1504 | free_irq(pdev->irq, iotg->base); | ||
| 1505 | |||
| 1506 | if (lnw->iotg.stop_host) | ||
| 1507 | lnw->iotg.stop_host(&lnw->iotg); | ||
| 1508 | else | ||
| 1509 | dev_dbg(lnw->dev, | ||
| 1510 | "host driver has been removed.\n"); | ||
| 1511 | |||
| 1512 | iotg->hsm.b_bus_suspend = 0; | ||
| 1513 | iotg->hsm.b_bus_suspend_vld = 0; | ||
| 1514 | |||
| 1515 | /* msleep(200); */ | ||
| 1516 | if (lnw->iotg.start_peripheral) | ||
| 1517 | lnw->iotg.start_peripheral(&lnw->iotg); | ||
| 1518 | else | ||
| 1519 | dev_dbg(lnw->dev, | ||
| 1520 | "client driver not loaded.\n"); | ||
| 1521 | |||
| 1522 | langwell_otg_add_ktimer(TB_BUS_SUSPEND_TMR); | ||
| 1523 | iotg->otg.state = OTG_STATE_A_PERIPHERAL; | ||
| 1524 | break; | ||
| 1525 | } else if (!iotg->hsm.a_vbus_vld) { | ||
| 1526 | langwell_otg_del_timer(a_aidl_bdis_tmr); | ||
| 1527 | langwell_otg_HABA(0); | ||
| 1528 | free_irq(pdev->irq, iotg->base); | ||
| 1529 | if (lnw->iotg.stop_host) | ||
| 1530 | lnw->iotg.stop_host(&lnw->iotg); | ||
| 1531 | else | ||
| 1532 | dev_dbg(lnw->dev, | ||
| 1533 | "host driver has been removed.\n"); | ||
| 1534 | |||
| 1535 | /* Turn off VBus */ | ||
| 1536 | iotg->otg.set_vbus(&iotg->otg, false); | ||
| 1537 | langwell_otg_phy_low_power_wait(1); | ||
| 1538 | iotg->otg.state = OTG_STATE_A_VBUS_ERR; | ||
| 1539 | } | ||
| 1540 | break; | ||
| 1541 | case OTG_STATE_A_PERIPHERAL: | ||
| 1542 | if (iotg->hsm.id) { | ||
| 1543 | /* delete hsm timer for b_bus_suspend_tmr */ | ||
| 1544 | del_timer_sync(&lnw->hsm_timer); | ||
| 1545 | iotg->otg.default_a = 0; | ||
| 1546 | iotg->hsm.b_bus_req = 0; | ||
| 1547 | if (lnw->iotg.stop_peripheral) | ||
| 1548 | lnw->iotg.stop_peripheral(&lnw->iotg); | ||
| 1549 | else | ||
| 1550 | dev_dbg(lnw->dev, | ||
| 1551 | "client driver has been removed.\n"); | ||
| 1552 | |||
| 1553 | /* Turn off VBus */ | ||
| 1554 | iotg->otg.set_vbus(&iotg->otg, false); | ||
| 1555 | set_client_mode(); | ||
| 1556 | langwell_otg_phy_low_power_wait(1); | ||
| 1557 | iotg->otg.state = OTG_STATE_B_IDLE; | ||
| 1558 | langwell_update_transceiver(); | ||
| 1559 | } else if (!iotg->hsm.a_vbus_vld) { | ||
| 1560 | /* delete hsm timer for b_bus_suspend_tmr */ | ||
| 1561 | del_timer_sync(&lnw->hsm_timer); | ||
| 1562 | |||
| 1563 | if (lnw->iotg.stop_peripheral) | ||
| 1564 | lnw->iotg.stop_peripheral(&lnw->iotg); | ||
| 1565 | else | ||
| 1566 | dev_dbg(lnw->dev, | ||
| 1567 | "client driver has been removed.\n"); | ||
| 1568 | |||
| 1569 | /* Turn off VBus */ | ||
| 1570 | iotg->otg.set_vbus(&iotg->otg, false); | ||
| 1571 | langwell_otg_phy_low_power_wait(1); | ||
| 1572 | iotg->otg.state = OTG_STATE_A_VBUS_ERR; | ||
| 1573 | } else if (iotg->hsm.a_bus_drop) { | ||
| 1574 | /* delete hsm timer for b_bus_suspend_tmr */ | ||
| 1575 | del_timer_sync(&lnw->hsm_timer); | ||
| 1576 | |||
| 1577 | if (lnw->iotg.stop_peripheral) | ||
| 1578 | lnw->iotg.stop_peripheral(&lnw->iotg); | ||
| 1579 | else | ||
| 1580 | dev_dbg(lnw->dev, | ||
| 1581 | "client driver has been removed.\n"); | ||
| 1582 | |||
| 1583 | /* Turn off VBus */ | ||
| 1584 | iotg->otg.set_vbus(&iotg->otg, false); | ||
| 1585 | iotg->otg.state = OTG_STATE_A_WAIT_VFALL; | ||
| 1586 | } else if (iotg->hsm.b_bus_suspend) { | ||
| 1587 | /* delete hsm timer for b_bus_suspend_tmr */ | ||
| 1588 | del_timer_sync(&lnw->hsm_timer); | ||
| 1589 | |||
| 1590 | if (lnw->iotg.stop_peripheral) | ||
| 1591 | lnw->iotg.stop_peripheral(&lnw->iotg); | ||
| 1592 | else | ||
| 1593 | dev_dbg(lnw->dev, | ||
| 1594 | "client driver has been removed.\n"); | ||
| 1595 | |||
| 1596 | if (lnw->iotg.start_host) | ||
| 1597 | lnw->iotg.start_host(&lnw->iotg); | ||
| 1598 | else | ||
| 1599 | dev_dbg(lnw->dev, | ||
| 1600 | "host driver not loaded.\n"); | ||
| 1601 | langwell_otg_add_ktimer(TA_WAIT_BCON_TMR); | ||
| 1602 | iotg->otg.state = OTG_STATE_A_WAIT_BCON; | ||
| 1603 | } else if (iotg->hsm.b_bus_suspend_tmout) { | ||
| 1604 | u32 val; | ||
| 1605 | val = readl(lnw->iotg.base + CI_PORTSC1); | ||
| 1606 | if (!(val & PORTSC_SUSP)) | ||
| 1607 | break; | ||
| 1608 | |||
| 1609 | if (lnw->iotg.stop_peripheral) | ||
| 1610 | lnw->iotg.stop_peripheral(&lnw->iotg); | ||
| 1611 | else | ||
| 1612 | dev_dbg(lnw->dev, | ||
| 1613 | "client driver has been removed.\n"); | ||
| 1614 | |||
| 1615 | if (lnw->iotg.start_host) | ||
| 1616 | lnw->iotg.start_host(&lnw->iotg); | ||
| 1617 | else | ||
| 1618 | dev_dbg(lnw->dev, | ||
| 1619 | "host driver not loaded.\n"); | ||
| 1620 | langwell_otg_add_ktimer(TA_WAIT_BCON_TMR); | ||
| 1621 | iotg->otg.state = OTG_STATE_A_WAIT_BCON; | ||
| 1622 | } | ||
| 1623 | break; | ||
| 1624 | case OTG_STATE_A_VBUS_ERR: | ||
| 1625 | if (iotg->hsm.id) { | ||
| 1626 | iotg->otg.default_a = 0; | ||
| 1627 | iotg->hsm.a_clr_err = 0; | ||
| 1628 | iotg->hsm.a_srp_det = 0; | ||
| 1629 | set_client_mode(); | ||
| 1630 | langwell_otg_phy_low_power(1); | ||
| 1631 | iotg->otg.state = OTG_STATE_B_IDLE; | ||
| 1632 | langwell_update_transceiver(); | ||
| 1633 | } else if (iotg->hsm.a_clr_err) { | ||
| 1634 | iotg->hsm.a_clr_err = 0; | ||
| 1635 | iotg->hsm.a_srp_det = 0; | ||
| 1636 | reset_otg(); | ||
| 1637 | init_hsm(); | ||
| 1638 | if (iotg->otg.state == OTG_STATE_A_IDLE) | ||
| 1639 | langwell_update_transceiver(); | ||
| 1640 | } else { | ||
| 1641 | /* FW will clear PHCD bit when any VBus | ||
| 1642 | * event detected. Reset PHCD to 1 again */ | ||
| 1643 | langwell_otg_phy_low_power(1); | ||
| 1644 | } | ||
| 1645 | break; | ||
| 1646 | case OTG_STATE_A_WAIT_VFALL: | ||
| 1647 | if (iotg->hsm.id) { | ||
| 1648 | iotg->otg.default_a = 0; | ||
| 1649 | set_client_mode(); | ||
| 1650 | langwell_otg_phy_low_power(1); | ||
| 1651 | iotg->otg.state = OTG_STATE_B_IDLE; | ||
| 1652 | langwell_update_transceiver(); | ||
| 1653 | } else if (iotg->hsm.a_bus_req) { | ||
| 1654 | |||
| 1655 | /* Turn on VBus */ | ||
| 1656 | iotg->otg.set_vbus(&iotg->otg, true); | ||
| 1657 | iotg->hsm.a_wait_vrise_tmout = 0; | ||
| 1658 | langwell_otg_add_timer(a_wait_vrise_tmr); | ||
| 1659 | iotg->otg.state = OTG_STATE_A_WAIT_VRISE; | ||
| 1660 | } else if (!iotg->hsm.a_sess_vld) { | ||
| 1661 | iotg->hsm.a_srp_det = 0; | ||
| 1662 | set_host_mode(); | ||
| 1663 | langwell_otg_phy_low_power(1); | ||
| 1664 | iotg->otg.state = OTG_STATE_A_IDLE; | ||
| 1665 | } | ||
| 1666 | break; | ||
| 1667 | default: | ||
| 1668 | ; | ||
| 1669 | } | ||
| 1670 | |||
| 1671 | dev_dbg(lnw->dev, "%s: new state = %s\n", __func__, | ||
| 1672 | otg_state_string(iotg->otg.state)); | ||
| 1673 | } | ||
| 1674 | |||
| 1675 | static ssize_t | ||
| 1676 | show_registers(struct device *_dev, struct device_attribute *attr, char *buf) | ||
| 1677 | { | ||
| 1678 | struct langwell_otg *lnw = the_transceiver; | ||
| 1679 | char *next; | ||
| 1680 | unsigned size, t; | ||
| 1681 | |||
| 1682 | next = buf; | ||
| 1683 | size = PAGE_SIZE; | ||
| 1684 | |||
| 1685 | t = scnprintf(next, size, | ||
| 1686 | "\n" | ||
| 1687 | "USBCMD = 0x%08x\n" | ||
| 1688 | "USBSTS = 0x%08x\n" | ||
| 1689 | "USBINTR = 0x%08x\n" | ||
| 1690 | "ASYNCLISTADDR = 0x%08x\n" | ||
| 1691 | "PORTSC1 = 0x%08x\n" | ||
| 1692 | "HOSTPC1 = 0x%08x\n" | ||
| 1693 | "OTGSC = 0x%08x\n" | ||
| 1694 | "USBMODE = 0x%08x\n", | ||
| 1695 | readl(lnw->iotg.base + 0x30), | ||
| 1696 | readl(lnw->iotg.base + 0x34), | ||
| 1697 | readl(lnw->iotg.base + 0x38), | ||
| 1698 | readl(lnw->iotg.base + 0x48), | ||
| 1699 | readl(lnw->iotg.base + 0x74), | ||
| 1700 | readl(lnw->iotg.base + 0xb4), | ||
| 1701 | readl(lnw->iotg.base + 0xf4), | ||
| 1702 | readl(lnw->iotg.base + 0xf8) | ||
| 1703 | ); | ||
| 1704 | size -= t; | ||
| 1705 | next += t; | ||
| 1706 | |||
| 1707 | return PAGE_SIZE - size; | ||
| 1708 | } | ||
| 1709 | static DEVICE_ATTR(registers, S_IRUGO, show_registers, NULL); | ||
| 1710 | |||
| 1711 | static ssize_t | ||
| 1712 | show_hsm(struct device *_dev, struct device_attribute *attr, char *buf) | ||
| 1713 | { | ||
| 1714 | struct langwell_otg *lnw = the_transceiver; | ||
| 1715 | struct intel_mid_otg_xceiv *iotg = &lnw->iotg; | ||
| 1716 | char *next; | ||
| 1717 | unsigned size, t; | ||
| 1718 | |||
| 1719 | next = buf; | ||
| 1720 | size = PAGE_SIZE; | ||
| 1721 | |||
| 1722 | if (iotg->otg.host) | ||
| 1723 | iotg->hsm.a_set_b_hnp_en = iotg->otg.host->b_hnp_enable; | ||
| 1724 | |||
| 1725 | if (iotg->otg.gadget) | ||
| 1726 | iotg->hsm.b_hnp_enable = iotg->otg.gadget->b_hnp_enable; | ||
| 1727 | |||
| 1728 | t = scnprintf(next, size, | ||
| 1729 | "\n" | ||
| 1730 | "current state = %s\n" | ||
| 1731 | "a_bus_resume = \t%d\n" | ||
| 1732 | "a_bus_suspend = \t%d\n" | ||
| 1733 | "a_conn = \t%d\n" | ||
| 1734 | "a_sess_vld = \t%d\n" | ||
| 1735 | "a_srp_det = \t%d\n" | ||
| 1736 | "a_vbus_vld = \t%d\n" | ||
| 1737 | "b_bus_resume = \t%d\n" | ||
| 1738 | "b_bus_suspend = \t%d\n" | ||
| 1739 | "b_conn = \t%d\n" | ||
| 1740 | "b_se0_srp = \t%d\n" | ||
| 1741 | "b_sess_end = \t%d\n" | ||
| 1742 | "b_sess_vld = \t%d\n" | ||
| 1743 | "id = \t%d\n" | ||
| 1744 | "a_set_b_hnp_en = \t%d\n" | ||
| 1745 | "b_srp_done = \t%d\n" | ||
| 1746 | "b_hnp_enable = \t%d\n" | ||
| 1747 | "a_wait_vrise_tmout = \t%d\n" | ||
| 1748 | "a_wait_bcon_tmout = \t%d\n" | ||
| 1749 | "a_aidl_bdis_tmout = \t%d\n" | ||
| 1750 | "b_ase0_brst_tmout = \t%d\n" | ||
| 1751 | "a_bus_drop = \t%d\n" | ||
| 1752 | "a_bus_req = \t%d\n" | ||
| 1753 | "a_clr_err = \t%d\n" | ||
| 1754 | "a_suspend_req = \t%d\n" | ||
| 1755 | "b_bus_req = \t%d\n" | ||
| 1756 | "b_bus_suspend_tmout = \t%d\n" | ||
| 1757 | "b_bus_suspend_vld = \t%d\n", | ||
| 1758 | otg_state_string(iotg->otg.state), | ||
| 1759 | iotg->hsm.a_bus_resume, | ||
| 1760 | iotg->hsm.a_bus_suspend, | ||
| 1761 | iotg->hsm.a_conn, | ||
| 1762 | iotg->hsm.a_sess_vld, | ||
| 1763 | iotg->hsm.a_srp_det, | ||
| 1764 | iotg->hsm.a_vbus_vld, | ||
| 1765 | iotg->hsm.b_bus_resume, | ||
| 1766 | iotg->hsm.b_bus_suspend, | ||
| 1767 | iotg->hsm.b_conn, | ||
| 1768 | iotg->hsm.b_se0_srp, | ||
| 1769 | iotg->hsm.b_sess_end, | ||
| 1770 | iotg->hsm.b_sess_vld, | ||
| 1771 | iotg->hsm.id, | ||
| 1772 | iotg->hsm.a_set_b_hnp_en, | ||
| 1773 | iotg->hsm.b_srp_done, | ||
| 1774 | iotg->hsm.b_hnp_enable, | ||
| 1775 | iotg->hsm.a_wait_vrise_tmout, | ||
| 1776 | iotg->hsm.a_wait_bcon_tmout, | ||
| 1777 | iotg->hsm.a_aidl_bdis_tmout, | ||
| 1778 | iotg->hsm.b_ase0_brst_tmout, | ||
| 1779 | iotg->hsm.a_bus_drop, | ||
| 1780 | iotg->hsm.a_bus_req, | ||
| 1781 | iotg->hsm.a_clr_err, | ||
| 1782 | iotg->hsm.a_suspend_req, | ||
| 1783 | iotg->hsm.b_bus_req, | ||
| 1784 | iotg->hsm.b_bus_suspend_tmout, | ||
| 1785 | iotg->hsm.b_bus_suspend_vld | ||
| 1786 | ); | ||
| 1787 | size -= t; | ||
| 1788 | next += t; | ||
| 1789 | |||
| 1790 | return PAGE_SIZE - size; | ||
| 1791 | } | ||
| 1792 | static DEVICE_ATTR(hsm, S_IRUGO, show_hsm, NULL); | ||
| 1793 | |||
| 1794 | static ssize_t | ||
| 1795 | get_a_bus_req(struct device *dev, struct device_attribute *attr, char *buf) | ||
| 1796 | { | ||
| 1797 | struct langwell_otg *lnw = the_transceiver; | ||
| 1798 | char *next; | ||
| 1799 | unsigned size, t; | ||
| 1800 | |||
| 1801 | next = buf; | ||
| 1802 | size = PAGE_SIZE; | ||
| 1803 | |||
| 1804 | t = scnprintf(next, size, "%d", lnw->iotg.hsm.a_bus_req); | ||
| 1805 | size -= t; | ||
| 1806 | next += t; | ||
| 1807 | |||
| 1808 | return PAGE_SIZE - size; | ||
| 1809 | } | ||
| 1810 | |||
| 1811 | static ssize_t | ||
| 1812 | set_a_bus_req(struct device *dev, struct device_attribute *attr, | ||
| 1813 | const char *buf, size_t count) | ||
| 1814 | { | ||
| 1815 | struct langwell_otg *lnw = the_transceiver; | ||
| 1816 | struct intel_mid_otg_xceiv *iotg = &lnw->iotg; | ||
| 1817 | |||
| 1818 | if (!iotg->otg.default_a) | ||
| 1819 | return -1; | ||
| 1820 | if (count > 2) | ||
| 1821 | return -1; | ||
| 1822 | |||
| 1823 | if (buf[0] == '0') { | ||
| 1824 | iotg->hsm.a_bus_req = 0; | ||
| 1825 | dev_dbg(lnw->dev, "User request: a_bus_req = 0\n"); | ||
| 1826 | } else if (buf[0] == '1') { | ||
| 1827 | /* If a_bus_drop is TRUE, a_bus_req can't be set */ | ||
| 1828 | if (iotg->hsm.a_bus_drop) | ||
| 1829 | return -1; | ||
| 1830 | iotg->hsm.a_bus_req = 1; | ||
| 1831 | dev_dbg(lnw->dev, "User request: a_bus_req = 1\n"); | ||
| 1832 | } | ||
| 1833 | if (spin_trylock(&lnw->wq_lock)) { | ||
| 1834 | langwell_update_transceiver(); | ||
| 1835 | spin_unlock(&lnw->wq_lock); | ||
| 1836 | } | ||
| 1837 | return count; | ||
| 1838 | } | ||
| 1839 | static DEVICE_ATTR(a_bus_req, S_IRUGO | S_IWUSR, get_a_bus_req, set_a_bus_req); | ||
| 1840 | |||
| 1841 | static ssize_t | ||
| 1842 | get_a_bus_drop(struct device *dev, struct device_attribute *attr, char *buf) | ||
| 1843 | { | ||
| 1844 | struct langwell_otg *lnw = the_transceiver; | ||
| 1845 | char *next; | ||
| 1846 | unsigned size, t; | ||
| 1847 | |||
| 1848 | next = buf; | ||
| 1849 | size = PAGE_SIZE; | ||
| 1850 | |||
| 1851 | t = scnprintf(next, size, "%d", lnw->iotg.hsm.a_bus_drop); | ||
| 1852 | size -= t; | ||
| 1853 | next += t; | ||
| 1854 | |||
| 1855 | return PAGE_SIZE - size; | ||
| 1856 | } | ||
| 1857 | |||
| 1858 | static ssize_t | ||
| 1859 | set_a_bus_drop(struct device *dev, struct device_attribute *attr, | ||
| 1860 | const char *buf, size_t count) | ||
| 1861 | { | ||
| 1862 | struct langwell_otg *lnw = the_transceiver; | ||
| 1863 | struct intel_mid_otg_xceiv *iotg = &lnw->iotg; | ||
| 1864 | |||
| 1865 | if (!iotg->otg.default_a) | ||
| 1866 | return -1; | ||
| 1867 | if (count > 2) | ||
| 1868 | return -1; | ||
| 1869 | |||
| 1870 | if (buf[0] == '0') { | ||
| 1871 | iotg->hsm.a_bus_drop = 0; | ||
| 1872 | dev_dbg(lnw->dev, "User request: a_bus_drop = 0\n"); | ||
| 1873 | } else if (buf[0] == '1') { | ||
| 1874 | iotg->hsm.a_bus_drop = 1; | ||
| 1875 | iotg->hsm.a_bus_req = 0; | ||
| 1876 | dev_dbg(lnw->dev, "User request: a_bus_drop = 1\n"); | ||
| 1877 | dev_dbg(lnw->dev, "User request: and a_bus_req = 0\n"); | ||
| 1878 | } | ||
| 1879 | if (spin_trylock(&lnw->wq_lock)) { | ||
| 1880 | langwell_update_transceiver(); | ||
| 1881 | spin_unlock(&lnw->wq_lock); | ||
| 1882 | } | ||
| 1883 | return count; | ||
| 1884 | } | ||
| 1885 | static DEVICE_ATTR(a_bus_drop, S_IRUGO | S_IWUSR, get_a_bus_drop, set_a_bus_drop); | ||
| 1886 | |||
| 1887 | static ssize_t | ||
| 1888 | get_b_bus_req(struct device *dev, struct device_attribute *attr, char *buf) | ||
| 1889 | { | ||
| 1890 | struct langwell_otg *lnw = the_transceiver; | ||
| 1891 | char *next; | ||
| 1892 | unsigned size, t; | ||
| 1893 | |||
| 1894 | next = buf; | ||
| 1895 | size = PAGE_SIZE; | ||
| 1896 | |||
| 1897 | t = scnprintf(next, size, "%d", lnw->iotg.hsm.b_bus_req); | ||
| 1898 | size -= t; | ||
| 1899 | next += t; | ||
| 1900 | |||
| 1901 | return PAGE_SIZE - size; | ||
| 1902 | } | ||
| 1903 | |||
| 1904 | static ssize_t | ||
| 1905 | set_b_bus_req(struct device *dev, struct device_attribute *attr, | ||
| 1906 | const char *buf, size_t count) | ||
| 1907 | { | ||
| 1908 | struct langwell_otg *lnw = the_transceiver; | ||
| 1909 | struct intel_mid_otg_xceiv *iotg = &lnw->iotg; | ||
| 1910 | |||
| 1911 | if (iotg->otg.default_a) | ||
| 1912 | return -1; | ||
| 1913 | |||
| 1914 | if (count > 2) | ||
| 1915 | return -1; | ||
| 1916 | |||
| 1917 | if (buf[0] == '0') { | ||
| 1918 | iotg->hsm.b_bus_req = 0; | ||
| 1919 | dev_dbg(lnw->dev, "User request: b_bus_req = 0\n"); | ||
| 1920 | } else if (buf[0] == '1') { | ||
| 1921 | iotg->hsm.b_bus_req = 1; | ||
| 1922 | dev_dbg(lnw->dev, "User request: b_bus_req = 1\n"); | ||
| 1923 | } | ||
| 1924 | if (spin_trylock(&lnw->wq_lock)) { | ||
| 1925 | langwell_update_transceiver(); | ||
| 1926 | spin_unlock(&lnw->wq_lock); | ||
| 1927 | } | ||
| 1928 | return count; | ||
| 1929 | } | ||
| 1930 | static DEVICE_ATTR(b_bus_req, S_IRUGO | S_IWUSR, get_b_bus_req, set_b_bus_req); | ||
| 1931 | |||
| 1932 | static ssize_t | ||
| 1933 | set_a_clr_err(struct device *dev, struct device_attribute *attr, | ||
| 1934 | const char *buf, size_t count) | ||
| 1935 | { | ||
| 1936 | struct langwell_otg *lnw = the_transceiver; | ||
| 1937 | struct intel_mid_otg_xceiv *iotg = &lnw->iotg; | ||
| 1938 | |||
| 1939 | if (!iotg->otg.default_a) | ||
| 1940 | return -1; | ||
| 1941 | if (count > 2) | ||
| 1942 | return -1; | ||
| 1943 | |||
| 1944 | if (buf[0] == '1') { | ||
| 1945 | iotg->hsm.a_clr_err = 1; | ||
| 1946 | dev_dbg(lnw->dev, "User request: a_clr_err = 1\n"); | ||
| 1947 | } | ||
| 1948 | if (spin_trylock(&lnw->wq_lock)) { | ||
| 1949 | langwell_update_transceiver(); | ||
| 1950 | spin_unlock(&lnw->wq_lock); | ||
| 1951 | } | ||
| 1952 | return count; | ||
| 1953 | } | ||
| 1954 | static DEVICE_ATTR(a_clr_err, S_IWUSR, NULL, set_a_clr_err); | ||
| 1955 | |||
| 1956 | static struct attribute *inputs_attrs[] = { | ||
| 1957 | &dev_attr_a_bus_req.attr, | ||
| 1958 | &dev_attr_a_bus_drop.attr, | ||
| 1959 | &dev_attr_b_bus_req.attr, | ||
| 1960 | &dev_attr_a_clr_err.attr, | ||
| 1961 | NULL, | ||
| 1962 | }; | ||
| 1963 | |||
| 1964 | static struct attribute_group debug_dev_attr_group = { | ||
| 1965 | .name = "inputs", | ||
| 1966 | .attrs = inputs_attrs, | ||
| 1967 | }; | ||
| 1968 | |||
| 1969 | static int langwell_otg_probe(struct pci_dev *pdev, | ||
| 1970 | const struct pci_device_id *id) | ||
| 1971 | { | ||
| 1972 | unsigned long resource, len; | ||
| 1973 | void __iomem *base = NULL; | ||
| 1974 | int retval; | ||
| 1975 | u32 val32; | ||
| 1976 | struct langwell_otg *lnw; | ||
| 1977 | char qname[] = "langwell_otg_queue"; | ||
| 1978 | |||
| 1979 | retval = 0; | ||
| 1980 | dev_dbg(&pdev->dev, "\notg controller is detected.\n"); | ||
| 1981 | if (pci_enable_device(pdev) < 0) { | ||
| 1982 | retval = -ENODEV; | ||
| 1983 | goto done; | ||
| 1984 | } | ||
| 1985 | |||
| 1986 | lnw = kzalloc(sizeof *lnw, GFP_KERNEL); | ||
| 1987 | if (lnw == NULL) { | ||
| 1988 | retval = -ENOMEM; | ||
| 1989 | goto done; | ||
| 1990 | } | ||
| 1991 | the_transceiver = lnw; | ||
| 1992 | |||
| 1993 | /* control register: BAR 0 */ | ||
| 1994 | resource = pci_resource_start(pdev, 0); | ||
| 1995 | len = pci_resource_len(pdev, 0); | ||
| 1996 | if (!request_mem_region(resource, len, driver_name)) { | ||
| 1997 | retval = -EBUSY; | ||
| 1998 | goto err; | ||
| 1999 | } | ||
| 2000 | lnw->region = 1; | ||
| 2001 | |||
| 2002 | base = ioremap_nocache(resource, len); | ||
| 2003 | if (base == NULL) { | ||
| 2004 | retval = -EFAULT; | ||
| 2005 | goto err; | ||
| 2006 | } | ||
| 2007 | lnw->iotg.base = base; | ||
| 2008 | |||
| 2009 | if (!request_mem_region(USBCFG_ADDR, USBCFG_LEN, driver_name)) { | ||
| 2010 | retval = -EBUSY; | ||
| 2011 | goto err; | ||
| 2012 | } | ||
| 2013 | lnw->cfg_region = 1; | ||
| 2014 | |||
| 2015 | /* For the SCCB.USBCFG register */ | ||
| 2016 | base = ioremap_nocache(USBCFG_ADDR, USBCFG_LEN); | ||
| 2017 | if (base == NULL) { | ||
| 2018 | retval = -EFAULT; | ||
| 2019 | goto err; | ||
| 2020 | } | ||
| 2021 | lnw->usbcfg = base; | ||
| 2022 | |||
| 2023 | if (!pdev->irq) { | ||
| 2024 | dev_dbg(&pdev->dev, "No IRQ.\n"); | ||
| 2025 | retval = -ENODEV; | ||
| 2026 | goto err; | ||
| 2027 | } | ||
| 2028 | |||
| 2029 | lnw->qwork = create_singlethread_workqueue(qname); | ||
| 2030 | if (!lnw->qwork) { | ||
| 2031 | dev_dbg(&pdev->dev, "cannot create workqueue %s\n", qname); | ||
| 2032 | retval = -ENOMEM; | ||
| 2033 | goto err; | ||
| 2034 | } | ||
| 2035 | INIT_WORK(&lnw->work, langwell_otg_work); | ||
| 2036 | |||
| 2037 | /* OTG common part */ | ||
| 2038 | lnw->dev = &pdev->dev; | ||
| 2039 | lnw->iotg.otg.dev = lnw->dev; | ||
| 2040 | lnw->iotg.otg.label = driver_name; | ||
| 2041 | lnw->iotg.otg.set_host = langwell_otg_set_host; | ||
| 2042 | lnw->iotg.otg.set_peripheral = langwell_otg_set_peripheral; | ||
| 2043 | lnw->iotg.otg.set_power = langwell_otg_set_power; | ||
| 2044 | lnw->iotg.otg.set_vbus = langwell_otg_set_vbus; | ||
| 2045 | lnw->iotg.otg.start_srp = langwell_otg_start_srp; | ||
| 2046 | lnw->iotg.otg.state = OTG_STATE_UNDEFINED; | ||
| 2047 | |||
| 2048 | if (otg_set_transceiver(&lnw->iotg.otg)) { | ||
| 2049 | dev_dbg(lnw->dev, "can't set transceiver\n"); | ||
| 2050 | retval = -EBUSY; | ||
| 2051 | goto err; | ||
| 2052 | } | ||
| 2053 | |||
| 2054 | reset_otg(); | ||
| 2055 | init_hsm(); | ||
| 2056 | |||
| 2057 | spin_lock_init(&lnw->lock); | ||
| 2058 | spin_lock_init(&lnw->wq_lock); | ||
| 2059 | INIT_LIST_HEAD(&active_timers); | ||
| 2060 | retval = langwell_otg_init_timers(&lnw->iotg.hsm); | ||
| 2061 | if (retval) { | ||
| 2062 | dev_dbg(&pdev->dev, "Failed to init timers\n"); | ||
| 2063 | goto err; | ||
| 2064 | } | ||
| 2065 | |||
| 2066 | init_timer(&lnw->hsm_timer); | ||
| 2067 | ATOMIC_INIT_NOTIFIER_HEAD(&lnw->iotg.iotg_notifier); | ||
| 2068 | |||
| 2069 | lnw->iotg_notifier.notifier_call = langwell_otg_iotg_notify; | ||
| 2070 | |||
| 2071 | retval = intel_mid_otg_register_notifier(&lnw->iotg, | ||
| 2072 | &lnw->iotg_notifier); | ||
| 2073 | if (retval) { | ||
| 2074 | dev_dbg(lnw->dev, "Failed to register notifier\n"); | ||
| 2075 | goto err; | ||
| 2076 | } | ||
| 2077 | |||
| 2078 | if (request_irq(pdev->irq, otg_irq, IRQF_SHARED, | ||
| 2079 | driver_name, lnw) != 0) { | ||
| 2080 | dev_dbg(lnw->dev, "request interrupt %d failed\n", pdev->irq); | ||
| 2081 | retval = -EBUSY; | ||
| 2082 | goto err; | ||
| 2083 | } | ||
| 2084 | |||
| 2085 | /* enable OTGSC int */ | ||
| 2086 | val32 = OTGSC_DPIE | OTGSC_BSEIE | OTGSC_BSVIE | | ||
| 2087 | OTGSC_ASVIE | OTGSC_AVVIE | OTGSC_IDIE | OTGSC_IDPU; | ||
| 2088 | writel(val32, lnw->iotg.base + CI_OTGSC); | ||
| 2089 | |||
| 2090 | retval = device_create_file(&pdev->dev, &dev_attr_registers); | ||
| 2091 | if (retval < 0) { | ||
| 2092 | dev_dbg(lnw->dev, | ||
| 2093 | "Can't register sysfs attribute: %d\n", retval); | ||
| 2094 | goto err; | ||
| 2095 | } | ||
| 2096 | |||
| 2097 | retval = device_create_file(&pdev->dev, &dev_attr_hsm); | ||
| 2098 | if (retval < 0) { | ||
| 2099 | dev_dbg(lnw->dev, "Can't hsm sysfs attribute: %d\n", retval); | ||
| 2100 | goto err; | ||
| 2101 | } | ||
| 2102 | |||
| 2103 | retval = sysfs_create_group(&pdev->dev.kobj, &debug_dev_attr_group); | ||
| 2104 | if (retval < 0) { | ||
| 2105 | dev_dbg(lnw->dev, | ||
| 2106 | "Can't register sysfs attr group: %d\n", retval); | ||
| 2107 | goto err; | ||
| 2108 | } | ||
| 2109 | |||
| 2110 | if (lnw->iotg.otg.state == OTG_STATE_A_IDLE) | ||
| 2111 | langwell_update_transceiver(); | ||
| 2112 | |||
| 2113 | return 0; | ||
| 2114 | |||
| 2115 | err: | ||
| 2116 | if (the_transceiver) | ||
| 2117 | langwell_otg_remove(pdev); | ||
| 2118 | done: | ||
| 2119 | return retval; | ||
| 2120 | } | ||
| 2121 | |||
| 2122 | static void langwell_otg_remove(struct pci_dev *pdev) | ||
| 2123 | { | ||
| 2124 | struct langwell_otg *lnw = the_transceiver; | ||
| 2125 | |||
| 2126 | if (lnw->qwork) { | ||
| 2127 | flush_workqueue(lnw->qwork); | ||
| 2128 | destroy_workqueue(lnw->qwork); | ||
| 2129 | } | ||
| 2130 | intel_mid_otg_unregister_notifier(&lnw->iotg, &lnw->iotg_notifier); | ||
| 2131 | langwell_otg_free_timers(); | ||
| 2132 | |||
| 2133 | /* disable OTGSC interrupt as OTGSC doesn't change in reset */ | ||
| 2134 | writel(0, lnw->iotg.base + CI_OTGSC); | ||
| 2135 | |||
| 2136 | if (pdev->irq) | ||
| 2137 | free_irq(pdev->irq, lnw); | ||
| 2138 | if (lnw->usbcfg) | ||
| 2139 | iounmap(lnw->usbcfg); | ||
| 2140 | if (lnw->cfg_region) | ||
| 2141 | release_mem_region(USBCFG_ADDR, USBCFG_LEN); | ||
| 2142 | if (lnw->iotg.base) | ||
| 2143 | iounmap(lnw->iotg.base); | ||
| 2144 | if (lnw->region) | ||
| 2145 | release_mem_region(pci_resource_start(pdev, 0), | ||
| 2146 | pci_resource_len(pdev, 0)); | ||
| 2147 | |||
| 2148 | otg_set_transceiver(NULL); | ||
| 2149 | pci_disable_device(pdev); | ||
| 2150 | sysfs_remove_group(&pdev->dev.kobj, &debug_dev_attr_group); | ||
| 2151 | device_remove_file(&pdev->dev, &dev_attr_hsm); | ||
| 2152 | device_remove_file(&pdev->dev, &dev_attr_registers); | ||
| 2153 | kfree(lnw); | ||
| 2154 | lnw = NULL; | ||
| 2155 | } | ||
| 2156 | |||
| 2157 | static void transceiver_suspend(struct pci_dev *pdev) | ||
| 2158 | { | ||
| 2159 | pci_save_state(pdev); | ||
| 2160 | pci_set_power_state(pdev, PCI_D3hot); | ||
| 2161 | langwell_otg_phy_low_power(1); | ||
| 2162 | } | ||
| 2163 | |||
| 2164 | static int langwell_otg_suspend(struct pci_dev *pdev, pm_message_t message) | ||
| 2165 | { | ||
| 2166 | struct langwell_otg *lnw = the_transceiver; | ||
| 2167 | struct intel_mid_otg_xceiv *iotg = &lnw->iotg; | ||
| 2168 | int ret = 0; | ||
| 2169 | |||
| 2170 | /* Disbale OTG interrupts */ | ||
| 2171 | langwell_otg_intr(0); | ||
| 2172 | |||
| 2173 | if (pdev->irq) | ||
| 2174 | free_irq(pdev->irq, lnw); | ||
| 2175 | |||
| 2176 | /* Prevent more otg_work */ | ||
| 2177 | flush_workqueue(lnw->qwork); | ||
| 2178 | destroy_workqueue(lnw->qwork); | ||
| 2179 | lnw->qwork = NULL; | ||
| 2180 | |||
| 2181 | /* start actions */ | ||
| 2182 | switch (iotg->otg.state) { | ||
| 2183 | case OTG_STATE_A_WAIT_VFALL: | ||
| 2184 | iotg->otg.state = OTG_STATE_A_IDLE; | ||
| 2185 | case OTG_STATE_A_IDLE: | ||
| 2186 | case OTG_STATE_B_IDLE: | ||
| 2187 | case OTG_STATE_A_VBUS_ERR: | ||
| 2188 | transceiver_suspend(pdev); | ||
| 2189 | break; | ||
| 2190 | case OTG_STATE_A_WAIT_VRISE: | ||
| 2191 | langwell_otg_del_timer(a_wait_vrise_tmr); | ||
| 2192 | iotg->hsm.a_srp_det = 0; | ||
| 2193 | |||
| 2194 | /* Turn off VBus */ | ||
| 2195 | iotg->otg.set_vbus(&iotg->otg, false); | ||
| 2196 | iotg->otg.state = OTG_STATE_A_IDLE; | ||
| 2197 | transceiver_suspend(pdev); | ||
| 2198 | break; | ||
| 2199 | case OTG_STATE_A_WAIT_BCON: | ||
| 2200 | del_timer_sync(&lnw->hsm_timer); | ||
| 2201 | if (lnw->iotg.stop_host) | ||
| 2202 | lnw->iotg.stop_host(&lnw->iotg); | ||
| 2203 | else | ||
| 2204 | dev_dbg(&pdev->dev, "host driver has been removed.\n"); | ||
| 2205 | |||
| 2206 | iotg->hsm.a_srp_det = 0; | ||
| 2207 | |||
| 2208 | /* Turn off VBus */ | ||
| 2209 | iotg->otg.set_vbus(&iotg->otg, false); | ||
| 2210 | iotg->otg.state = OTG_STATE_A_IDLE; | ||
| 2211 | transceiver_suspend(pdev); | ||
| 2212 | break; | ||
| 2213 | case OTG_STATE_A_HOST: | ||
| 2214 | if (lnw->iotg.stop_host) | ||
| 2215 | lnw->iotg.stop_host(&lnw->iotg); | ||
| 2216 | else | ||
| 2217 | dev_dbg(&pdev->dev, "host driver has been removed.\n"); | ||
| 2218 | |||
| 2219 | iotg->hsm.a_srp_det = 0; | ||
| 2220 | |||
| 2221 | /* Turn off VBus */ | ||
| 2222 | iotg->otg.set_vbus(&iotg->otg, false); | ||
| 2223 | |||
| 2224 | iotg->otg.state = OTG_STATE_A_IDLE; | ||
| 2225 | transceiver_suspend(pdev); | ||
| 2226 | break; | ||
| 2227 | case OTG_STATE_A_SUSPEND: | ||
| 2228 | langwell_otg_del_timer(a_aidl_bdis_tmr); | ||
| 2229 | langwell_otg_HABA(0); | ||
| 2230 | if (lnw->iotg.stop_host) | ||
| 2231 | lnw->iotg.stop_host(&lnw->iotg); | ||
| 2232 | else | ||
| 2233 | dev_dbg(lnw->dev, "host driver has been removed.\n"); | ||
| 2234 | iotg->hsm.a_srp_det = 0; | ||
| 2235 | |||
| 2236 | /* Turn off VBus */ | ||
| 2237 | iotg->otg.set_vbus(&iotg->otg, false); | ||
| 2238 | iotg->otg.state = OTG_STATE_A_IDLE; | ||
| 2239 | transceiver_suspend(pdev); | ||
| 2240 | break; | ||
| 2241 | case OTG_STATE_A_PERIPHERAL: | ||
| 2242 | del_timer_sync(&lnw->hsm_timer); | ||
| 2243 | |||
| 2244 | if (lnw->iotg.stop_peripheral) | ||
| 2245 | lnw->iotg.stop_peripheral(&lnw->iotg); | ||
| 2246 | else | ||
| 2247 | dev_dbg(&pdev->dev, | ||
| 2248 | "client driver has been removed.\n"); | ||
| 2249 | iotg->hsm.a_srp_det = 0; | ||
| 2250 | |||
| 2251 | /* Turn off VBus */ | ||
| 2252 | iotg->otg.set_vbus(&iotg->otg, false); | ||
| 2253 | iotg->otg.state = OTG_STATE_A_IDLE; | ||
| 2254 | transceiver_suspend(pdev); | ||
| 2255 | break; | ||
| 2256 | case OTG_STATE_B_HOST: | ||
| 2257 | if (lnw->iotg.stop_host) | ||
| 2258 | lnw->iotg.stop_host(&lnw->iotg); | ||
| 2259 | else | ||
| 2260 | dev_dbg(&pdev->dev, "host driver has been removed.\n"); | ||
| 2261 | iotg->hsm.b_bus_req = 0; | ||
| 2262 | iotg->otg.state = OTG_STATE_B_IDLE; | ||
| 2263 | transceiver_suspend(pdev); | ||
| 2264 | break; | ||
| 2265 | case OTG_STATE_B_PERIPHERAL: | ||
| 2266 | if (lnw->iotg.stop_peripheral) | ||
| 2267 | lnw->iotg.stop_peripheral(&lnw->iotg); | ||
| 2268 | else | ||
| 2269 | dev_dbg(&pdev->dev, | ||
| 2270 | "client driver has been removed.\n"); | ||
| 2271 | iotg->otg.state = OTG_STATE_B_IDLE; | ||
| 2272 | transceiver_suspend(pdev); | ||
| 2273 | break; | ||
| 2274 | case OTG_STATE_B_WAIT_ACON: | ||
| 2275 | /* delete hsm timer for b_ase0_brst_tmr */ | ||
| 2276 | del_timer_sync(&lnw->hsm_timer); | ||
| 2277 | |||
| 2278 | langwell_otg_HAAR(0); | ||
| 2279 | |||
| 2280 | if (lnw->iotg.stop_host) | ||
| 2281 | lnw->iotg.stop_host(&lnw->iotg); | ||
| 2282 | else | ||
| 2283 | dev_dbg(&pdev->dev, "host driver has been removed.\n"); | ||
| 2284 | iotg->hsm.b_bus_req = 0; | ||
| 2285 | iotg->otg.state = OTG_STATE_B_IDLE; | ||
| 2286 | transceiver_suspend(pdev); | ||
| 2287 | break; | ||
| 2288 | default: | ||
| 2289 | dev_dbg(lnw->dev, "error state before suspend\n"); | ||
| 2290 | break; | ||
| 2291 | } | ||
| 2292 | |||
| 2293 | return ret; | ||
| 2294 | } | ||
| 2295 | |||
| 2296 | static void transceiver_resume(struct pci_dev *pdev) | ||
| 2297 | { | ||
| 2298 | pci_restore_state(pdev); | ||
| 2299 | pci_set_power_state(pdev, PCI_D0); | ||
| 2300 | } | ||
| 2301 | |||
| 2302 | static int langwell_otg_resume(struct pci_dev *pdev) | ||
| 2303 | { | ||
| 2304 | struct langwell_otg *lnw = the_transceiver; | ||
| 2305 | int ret = 0; | ||
| 2306 | |||
| 2307 | transceiver_resume(pdev); | ||
| 2308 | |||
| 2309 | lnw->qwork = create_singlethread_workqueue("langwell_otg_queue"); | ||
| 2310 | if (!lnw->qwork) { | ||
| 2311 | dev_dbg(&pdev->dev, "cannot create langwell otg workqueuen"); | ||
| 2312 | ret = -ENOMEM; | ||
| 2313 | goto error; | ||
| 2314 | } | ||
| 2315 | |||
| 2316 | if (request_irq(pdev->irq, otg_irq, IRQF_SHARED, | ||
| 2317 | driver_name, lnw) != 0) { | ||
| 2318 | dev_dbg(&pdev->dev, "request interrupt %d failed\n", pdev->irq); | ||
| 2319 | ret = -EBUSY; | ||
| 2320 | goto error; | ||
| 2321 | } | ||
| 2322 | |||
| 2323 | /* enable OTG interrupts */ | ||
| 2324 | langwell_otg_intr(1); | ||
| 2325 | |||
| 2326 | update_hsm(); | ||
| 2327 | |||
| 2328 | langwell_update_transceiver(); | ||
| 2329 | |||
| 2330 | return ret; | ||
| 2331 | error: | ||
| 2332 | langwell_otg_intr(0); | ||
| 2333 | transceiver_suspend(pdev); | ||
| 2334 | return ret; | ||
| 2335 | } | ||
| 2336 | |||
| 2337 | static int __init langwell_otg_init(void) | ||
| 2338 | { | ||
| 2339 | return pci_register_driver(&otg_pci_driver); | ||
| 2340 | } | ||
| 2341 | module_init(langwell_otg_init); | ||
| 2342 | |||
| 2343 | static void __exit langwell_otg_cleanup(void) | ||
| 2344 | { | ||
| 2345 | pci_unregister_driver(&otg_pci_driver); | ||
| 2346 | } | ||
| 2347 | module_exit(langwell_otg_cleanup); | ||
diff --git a/drivers/usb/otg/otg-wakelock.c b/drivers/usb/otg/otg-wakelock.c new file mode 100644 index 00000000000..2f11472dd2b --- /dev/null +++ b/drivers/usb/otg/otg-wakelock.c | |||
| @@ -0,0 +1,169 @@ | |||
| 1 | /* | ||
| 2 | * otg-wakelock.c | ||
| 3 | * | ||
| 4 | * Copyright (C) 2011 Google, Inc. | ||
| 5 | * | ||
| 6 | * This software is licensed under the terms of the GNU General Public | ||
| 7 | * License version 2, as published by the Free Software Foundation, and | ||
| 8 | * may be copied, distributed, and modified under those terms. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | * | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/kernel.h> | ||
| 18 | #include <linux/device.h> | ||
| 19 | #include <linux/notifier.h> | ||
| 20 | #include <linux/wakelock.h> | ||
| 21 | #include <linux/spinlock.h> | ||
| 22 | #include <linux/usb/otg.h> | ||
| 23 | |||
| 24 | #define TEMPORARY_HOLD_TIME 2000 | ||
| 25 | |||
| 26 | static bool enabled = true; | ||
| 27 | static struct otg_transceiver *otgwl_xceiv; | ||
| 28 | static struct notifier_block otgwl_nb; | ||
| 29 | |||
| 30 | /* | ||
| 31 | * otgwl_spinlock is held while the VBUS lock is grabbed or dropped and the | ||
| 32 | * held field is updated to match. | ||
| 33 | */ | ||
| 34 | |||
| 35 | static DEFINE_SPINLOCK(otgwl_spinlock); | ||
| 36 | |||
| 37 | /* | ||
| 38 | * Only one lock, but since these 3 fields are associated with each other... | ||
| 39 | */ | ||
| 40 | |||
| 41 | struct otgwl_lock { | ||
| 42 | char name[40]; | ||
| 43 | struct wake_lock wakelock; | ||
| 44 | bool held; | ||
| 45 | }; | ||
| 46 | |||
| 47 | /* | ||
| 48 | * VBUS present lock. Also used as a timed lock on charger | ||
| 49 | * connect/disconnect and USB host disconnect, to allow the system | ||
| 50 | * to react to the change in power. | ||
| 51 | */ | ||
| 52 | |||
| 53 | static struct otgwl_lock vbus_lock; | ||
| 54 | |||
| 55 | static void otgwl_hold(struct otgwl_lock *lock) | ||
| 56 | { | ||
| 57 | if (!lock->held) { | ||
| 58 | wake_lock(&lock->wakelock); | ||
| 59 | lock->held = true; | ||
| 60 | } | ||
| 61 | } | ||
| 62 | |||
| 63 | static void otgwl_temporary_hold(struct otgwl_lock *lock) | ||
| 64 | { | ||
| 65 | wake_lock_timeout(&lock->wakelock, | ||
| 66 | msecs_to_jiffies(TEMPORARY_HOLD_TIME)); | ||
| 67 | lock->held = false; | ||
| 68 | } | ||
| 69 | |||
| 70 | static void otgwl_drop(struct otgwl_lock *lock) | ||
| 71 | { | ||
| 72 | if (lock->held) { | ||
| 73 | wake_unlock(&lock->wakelock); | ||
| 74 | lock->held = false; | ||
| 75 | } | ||
| 76 | } | ||
| 77 | |||
| 78 | static void otgwl_handle_event(unsigned long event) | ||
| 79 | { | ||
| 80 | unsigned long irqflags; | ||
| 81 | |||
| 82 | spin_lock_irqsave(&otgwl_spinlock, irqflags); | ||
| 83 | |||
| 84 | if (!enabled) { | ||
| 85 | otgwl_drop(&vbus_lock); | ||
| 86 | spin_unlock_irqrestore(&otgwl_spinlock, irqflags); | ||
| 87 | return; | ||
| 88 | } | ||
| 89 | |||
| 90 | switch (event) { | ||
| 91 | case USB_EVENT_VBUS: | ||
| 92 | case USB_EVENT_ENUMERATED: | ||
| 93 | otgwl_hold(&vbus_lock); | ||
| 94 | break; | ||
| 95 | |||
| 96 | case USB_EVENT_NONE: | ||
| 97 | case USB_EVENT_ID: | ||
| 98 | case USB_EVENT_CHARGER: | ||
| 99 | otgwl_temporary_hold(&vbus_lock); | ||
| 100 | break; | ||
| 101 | |||
| 102 | default: | ||
| 103 | break; | ||
| 104 | } | ||
| 105 | |||
| 106 | spin_unlock_irqrestore(&otgwl_spinlock, irqflags); | ||
| 107 | } | ||
| 108 | |||
| 109 | static int otgwl_otg_notifications(struct notifier_block *nb, | ||
| 110 | unsigned long event, void *unused) | ||
| 111 | { | ||
| 112 | otgwl_handle_event(event); | ||
| 113 | return NOTIFY_OK; | ||
| 114 | } | ||
| 115 | |||
| 116 | static int set_enabled(const char *val, const struct kernel_param *kp) | ||
| 117 | { | ||
| 118 | int rv = param_set_bool(val, kp); | ||
| 119 | |||
| 120 | if (rv) | ||
| 121 | return rv; | ||
| 122 | |||
| 123 | if (otgwl_xceiv) | ||
| 124 | otgwl_handle_event(otgwl_xceiv->last_event); | ||
| 125 | |||
| 126 | return 0; | ||
| 127 | } | ||
| 128 | |||
| 129 | static struct kernel_param_ops enabled_param_ops = { | ||
| 130 | .set = set_enabled, | ||
| 131 | .get = param_get_bool, | ||
| 132 | }; | ||
| 133 | |||
| 134 | module_param_cb(enabled, &enabled_param_ops, &enabled, 0644); | ||
| 135 | MODULE_PARM_DESC(enabled, "enable wakelock when VBUS present"); | ||
| 136 | |||
| 137 | static int __init otg_wakelock_init(void) | ||
| 138 | { | ||
| 139 | int ret; | ||
| 140 | |||
| 141 | otgwl_xceiv = otg_get_transceiver(); | ||
| 142 | |||
| 143 | if (!otgwl_xceiv) { | ||
| 144 | pr_err("%s: No OTG transceiver found\n", __func__); | ||
| 145 | return -ENODEV; | ||
| 146 | } | ||
| 147 | |||
| 148 | snprintf(vbus_lock.name, sizeof(vbus_lock.name), "vbus-%s", | ||
| 149 | dev_name(otgwl_xceiv->dev)); | ||
| 150 | wake_lock_init(&vbus_lock.wakelock, WAKE_LOCK_SUSPEND, | ||
| 151 | vbus_lock.name); | ||
| 152 | |||
| 153 | otgwl_nb.notifier_call = otgwl_otg_notifications; | ||
| 154 | ret = otg_register_notifier(otgwl_xceiv, &otgwl_nb); | ||
| 155 | |||
| 156 | if (ret) { | ||
| 157 | pr_err("%s: otg_register_notifier on transceiver %s" | ||
| 158 | " failed\n", __func__, | ||
| 159 | dev_name(otgwl_xceiv->dev)); | ||
| 160 | otgwl_xceiv = NULL; | ||
| 161 | wake_lock_destroy(&vbus_lock.wakelock); | ||
| 162 | return ret; | ||
| 163 | } | ||
| 164 | |||
| 165 | otgwl_handle_event(otgwl_xceiv->last_event); | ||
| 166 | return ret; | ||
| 167 | } | ||
| 168 | |||
| 169 | late_initcall(otg_wakelock_init); | ||
diff --git a/drivers/usb/otg/otg_id.c b/drivers/usb/otg/otg_id.c new file mode 100644 index 00000000000..8037edbf314 --- /dev/null +++ b/drivers/usb/otg/otg_id.c | |||
| @@ -0,0 +1,205 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2011 Google, Inc. | ||
| 3 | * | ||
| 4 | * Author: | ||
| 5 | * Colin Cross <ccross@android.com> | ||
| 6 | * | ||
| 7 | * This software is licensed under the terms of the GNU General Public | ||
| 8 | * License version 2, as published by the Free Software Foundation, and | ||
| 9 | * may be copied, distributed, and modified under those terms. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include <linux/kernel.h> | ||
| 19 | #include <linux/mutex.h> | ||
| 20 | #include <linux/notifier.h> | ||
| 21 | #include <linux/usb/otg_id.h> | ||
| 22 | |||
| 23 | static DEFINE_MUTEX(otg_id_lock); | ||
| 24 | static struct plist_head otg_id_plist = | ||
| 25 | PLIST_HEAD_INIT(otg_id_plist); | ||
| 26 | static struct otg_id_notifier_block *otg_id_active; | ||
| 27 | static bool otg_id_cancelling; | ||
| 28 | static bool otg_id_inited; | ||
| 29 | static int otg_id_suspended; | ||
| 30 | static bool otg_id_pending; | ||
| 31 | |||
| 32 | static void otg_id_cancel(void) | ||
| 33 | { | ||
| 34 | if (otg_id_active) { | ||
| 35 | otg_id_cancelling = true; | ||
| 36 | mutex_unlock(&otg_id_lock); | ||
| 37 | |||
| 38 | otg_id_active->cancel(otg_id_active); | ||
| 39 | |||
| 40 | mutex_lock(&otg_id_lock); | ||
| 41 | otg_id_cancelling = false; | ||
| 42 | } | ||
| 43 | } | ||
| 44 | |||
| 45 | static void __otg_id_notify(void) | ||
| 46 | { | ||
| 47 | int ret; | ||
| 48 | struct otg_id_notifier_block *otg_id_nb; | ||
| 49 | bool proxy_wait = false; | ||
| 50 | if (plist_head_empty(&otg_id_plist)) | ||
| 51 | return; | ||
| 52 | |||
| 53 | plist_for_each_entry(otg_id_nb, &otg_id_plist, p) { | ||
| 54 | if (proxy_wait) { | ||
| 55 | if (otg_id_nb->proxy_wait) | ||
| 56 | ret = otg_id_nb->proxy_wait(otg_id_nb); | ||
| 57 | } else { | ||
| 58 | ret = otg_id_nb->detect(otg_id_nb); | ||
| 59 | } | ||
| 60 | if (ret == OTG_ID_HANDLED) { | ||
| 61 | otg_id_active = otg_id_nb; | ||
| 62 | return; | ||
| 63 | } | ||
| 64 | if (ret == OTG_ID_PROXY_WAIT) | ||
| 65 | proxy_wait = true; | ||
| 66 | |||
| 67 | } | ||
| 68 | |||
| 69 | WARN(1, "otg id event not handled"); | ||
| 70 | otg_id_active = NULL; | ||
| 71 | } | ||
| 72 | |||
| 73 | int otg_id_init(void) | ||
| 74 | { | ||
| 75 | mutex_lock(&otg_id_lock); | ||
| 76 | |||
| 77 | otg_id_inited = true; | ||
| 78 | __otg_id_notify(); | ||
| 79 | |||
| 80 | mutex_unlock(&otg_id_lock); | ||
| 81 | return 0; | ||
| 82 | } | ||
| 83 | late_initcall(otg_id_init); | ||
| 84 | |||
| 85 | /** | ||
| 86 | * otg_id_register_notifier | ||
| 87 | * @otg_id_nb: notifier block containing priority and callback function | ||
| 88 | * | ||
| 89 | * Register a notifier that will be called on any USB cable state change. | ||
| 90 | * The priority determines the order the callback will be called in, a higher | ||
| 91 | * number will be called first. A callback function needs to determine the | ||
| 92 | * type of USB cable that is connected. If it can determine the type, it | ||
| 93 | * should notify the appropriate drivers (for example, call an otg notifier | ||
| 94 | * with USB_EVENT_VBUS), and return OTG_ID_HANDLED. Once a callback has | ||
| 95 | * returned OTG_ID_HANDLED, it is responsible for calling otg_id_notify() when | ||
| 96 | * the detected USB cable is disconnected. | ||
| 97 | */ | ||
| 98 | int otg_id_register_notifier(struct otg_id_notifier_block *otg_id_nb) | ||
| 99 | { | ||
| 100 | plist_node_init(&otg_id_nb->p, otg_id_nb->priority); | ||
| 101 | |||
| 102 | mutex_lock(&otg_id_lock); | ||
| 103 | plist_add(&otg_id_nb->p, &otg_id_plist); | ||
| 104 | |||
| 105 | if (otg_id_inited) { | ||
| 106 | otg_id_cancel(); | ||
| 107 | __otg_id_notify(); | ||
| 108 | } | ||
| 109 | |||
| 110 | mutex_unlock(&otg_id_lock); | ||
| 111 | |||
| 112 | return 0; | ||
| 113 | } | ||
| 114 | |||
| 115 | void otg_id_unregister_notifier(struct otg_id_notifier_block *otg_id_nb) | ||
| 116 | { | ||
| 117 | mutex_lock(&otg_id_lock); | ||
| 118 | |||
| 119 | plist_del(&otg_id_nb->p, &otg_id_plist); | ||
| 120 | |||
| 121 | if (otg_id_inited && (otg_id_active == otg_id_nb)) { | ||
| 122 | otg_id_cancel(); | ||
| 123 | __otg_id_notify(); | ||
| 124 | } | ||
| 125 | |||
| 126 | mutex_unlock(&otg_id_lock); | ||
| 127 | } | ||
| 128 | |||
| 129 | /** | ||
| 130 | * otg_id_notify | ||
| 131 | * | ||
| 132 | * Notify listeners on any USB cable state change. | ||
| 133 | * | ||
| 134 | * A driver may only call otg_id_notify if it returned OTG_ID_HANDLED the last | ||
| 135 | * time it's notifier was called, and it's cancel function has not been called. | ||
| 136 | */ | ||
| 137 | void otg_id_notify(void) | ||
| 138 | { | ||
| 139 | mutex_lock(&otg_id_lock); | ||
| 140 | |||
| 141 | if (otg_id_cancelling) | ||
| 142 | goto out; | ||
| 143 | |||
| 144 | if (otg_id_suspended != 0) { | ||
| 145 | otg_id_pending = true; | ||
| 146 | goto out; | ||
| 147 | } | ||
| 148 | |||
| 149 | __otg_id_notify(); | ||
| 150 | out: | ||
| 151 | mutex_unlock(&otg_id_lock); | ||
| 152 | } | ||
| 153 | |||
| 154 | /** | ||
| 155 | * otg_id_suspend | ||
| 156 | * | ||
| 157 | * Mark the otg_id subsystem as going into suspend. From here on out, | ||
| 158 | * any notifications will be deferred until the last otg_id client resumes. | ||
| 159 | * If there is a pending notification when calling this function, it will | ||
| 160 | * return a negative errno and expects that the caller will abort suspend. | ||
| 161 | * Returs 0 on success. | ||
| 162 | */ | ||
| 163 | int otg_id_suspend(void) | ||
| 164 | { | ||
| 165 | int ret = 0; | ||
| 166 | |||
| 167 | mutex_lock(&otg_id_lock); | ||
| 168 | |||
| 169 | /* | ||
| 170 | * if there's a pending notification, tell the caller to abort suspend | ||
| 171 | */ | ||
| 172 | if (otg_id_suspended != 0 && otg_id_pending) { | ||
| 173 | pr_info("otg_id: pending notification, should abort suspend\n"); | ||
| 174 | ret = -EBUSY; | ||
| 175 | goto out; | ||
| 176 | } | ||
| 177 | |||
| 178 | otg_id_suspended++; | ||
| 179 | out: | ||
| 180 | mutex_unlock(&otg_id_lock); | ||
| 181 | return ret; | ||
| 182 | } | ||
| 183 | |||
| 184 | /** | ||
| 185 | * otg_id_resume | ||
| 186 | * | ||
| 187 | * Inform the otg_id subsystem that a client is resuming. If this is the | ||
| 188 | * last client to be resumed and there's a pending notification, | ||
| 189 | * otg_id_notify() is called. | ||
| 190 | */ | ||
| 191 | void otg_id_resume(void) | ||
| 192 | { | ||
| 193 | mutex_lock(&otg_id_lock); | ||
| 194 | if (WARN(!otg_id_suspended, "unbalanced otg_id_resume\n")) | ||
| 195 | goto out; | ||
| 196 | if (--otg_id_suspended == 0) { | ||
| 197 | if (otg_id_pending) { | ||
| 198 | pr_info("otg_id: had pending notification\n"); | ||
| 199 | otg_id_pending = false; | ||
| 200 | __otg_id_notify(); | ||
| 201 | } | ||
| 202 | } | ||
| 203 | out: | ||
| 204 | mutex_unlock(&otg_id_lock); | ||
| 205 | } | ||
diff --git a/drivers/usb/otg/tegra-otg.c b/drivers/usb/otg/tegra-otg.c new file mode 100644 index 00000000000..4c04e6e183f --- /dev/null +++ b/drivers/usb/otg/tegra-otg.c | |||
| @@ -0,0 +1,540 @@ | |||
| 1 | /* | ||
| 2 | * drivers/usb/otg/tegra-otg.c | ||
| 3 | * | ||
| 4 | * OTG transceiver driver for Tegra UTMI phy | ||
| 5 | * | ||
| 6 | * Copyright (C) 2010 NVIDIA Corp. | ||
| 7 | * Copyright (C) 2010 Google, Inc. | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify it | ||
| 10 | * under the terms of the GNU General Public License as published by the | ||
| 11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 12 | * option) any later version. | ||
| 13 | * | ||
| 14 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
| 15 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 16 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 17 | * more details. | ||
| 18 | * | ||
| 19 | * You should have received a copy of the GNU General Public License along | ||
| 20 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 21 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
| 22 | */ | ||
| 23 | |||
| 24 | #include <linux/usb.h> | ||
| 25 | #include <linux/usb/otg.h> | ||
| 26 | #include <linux/usb/gadget.h> | ||
| 27 | #include <linux/usb/hcd.h> | ||
| 28 | #include <linux/platform_device.h> | ||
| 29 | #include <linux/platform_data/tegra_usb.h> | ||
| 30 | #include <linux/clk.h> | ||
| 31 | #include <linux/io.h> | ||
| 32 | #include <linux/delay.h> | ||
| 33 | #include <linux/err.h> | ||
| 34 | |||
| 35 | #define USB_PHY_WAKEUP 0x408 | ||
| 36 | #define USB_ID_INT_EN (1 << 0) | ||
| 37 | #define USB_ID_INT_STATUS (1 << 1) | ||
| 38 | #define USB_ID_STATUS (1 << 2) | ||
| 39 | #define USB_ID_PIN_WAKEUP_EN (1 << 6) | ||
| 40 | #define USB_VBUS_WAKEUP_EN (1 << 30) | ||
| 41 | #define USB_VBUS_INT_EN (1 << 8) | ||
| 42 | #define USB_VBUS_INT_STATUS (1 << 9) | ||
| 43 | #define USB_VBUS_STATUS (1 << 10) | ||
| 44 | #define USB_INTS (USB_VBUS_INT_STATUS | USB_ID_INT_STATUS) | ||
| 45 | |||
| 46 | typedef void (*callback_t)(enum usb_otg_state to, | ||
| 47 | enum usb_otg_state from, void *args); | ||
| 48 | |||
| 49 | struct tegra_otg_data { | ||
| 50 | struct otg_transceiver otg; | ||
| 51 | unsigned long int_status; | ||
| 52 | spinlock_t lock; | ||
| 53 | void __iomem *regs; | ||
| 54 | struct clk *clk; | ||
| 55 | int irq; | ||
| 56 | struct platform_device *pdev; | ||
| 57 | struct work_struct work; | ||
| 58 | unsigned int intr_reg_data; | ||
| 59 | bool detect_vbus; | ||
| 60 | bool clk_enabled; | ||
| 61 | callback_t charger_cb; | ||
| 62 | void *charger_cb_data; | ||
| 63 | |||
| 64 | }; | ||
| 65 | static struct tegra_otg_data *tegra_clone; | ||
| 66 | |||
| 67 | static inline unsigned long otg_readl(struct tegra_otg_data *tegra, | ||
| 68 | unsigned int offset) | ||
| 69 | { | ||
| 70 | return readl(tegra->regs + offset); | ||
| 71 | } | ||
| 72 | |||
| 73 | static inline void otg_writel(struct tegra_otg_data *tegra, unsigned long val, | ||
| 74 | unsigned int offset) | ||
| 75 | { | ||
| 76 | writel(val, tegra->regs + offset); | ||
| 77 | } | ||
| 78 | |||
| 79 | static void tegra_otg_enable_clk(void) | ||
| 80 | { | ||
| 81 | if (!tegra_clone->clk_enabled) | ||
| 82 | clk_enable(tegra_clone->clk); | ||
| 83 | tegra_clone->clk_enabled = true; | ||
| 84 | } | ||
| 85 | |||
| 86 | static void tegra_otg_disable_clk(void) | ||
| 87 | { | ||
| 88 | if (tegra_clone->clk_enabled) | ||
| 89 | clk_disable(tegra_clone->clk); | ||
| 90 | tegra_clone->clk_enabled = false; | ||
| 91 | } | ||
| 92 | |||
| 93 | static const char *tegra_state_name(enum usb_otg_state state) | ||
| 94 | { | ||
| 95 | switch (state) { | ||
| 96 | case OTG_STATE_A_HOST: | ||
| 97 | return "HOST"; | ||
| 98 | case OTG_STATE_B_PERIPHERAL: | ||
| 99 | return "PERIPHERAL"; | ||
| 100 | case OTG_STATE_A_SUSPEND: | ||
| 101 | return "SUSPEND"; | ||
| 102 | case OTG_STATE_UNDEFINED: | ||
| 103 | return "UNDEFINED"; | ||
| 104 | default: | ||
| 105 | return "INVALID"; | ||
| 106 | } | ||
| 107 | } | ||
| 108 | |||
| 109 | static struct platform_device * | ||
| 110 | tegra_usb_otg_host_register(struct platform_device *ehci_device, | ||
| 111 | struct tegra_ehci_platform_data *pdata) | ||
| 112 | { | ||
| 113 | struct platform_device *pdev; | ||
| 114 | void *platform_data; | ||
| 115 | int val; | ||
| 116 | |||
| 117 | pdev = platform_device_alloc(ehci_device->name, ehci_device->id); | ||
| 118 | if (!pdev) | ||
| 119 | return NULL; | ||
| 120 | |||
| 121 | val = platform_device_add_resources(pdev, ehci_device->resource, | ||
| 122 | ehci_device->num_resources); | ||
| 123 | if (val) | ||
| 124 | goto error; | ||
| 125 | |||
| 126 | pdev->dev.dma_mask = ehci_device->dev.dma_mask; | ||
| 127 | pdev->dev.coherent_dma_mask = ehci_device->dev.coherent_dma_mask; | ||
| 128 | |||
| 129 | platform_data = kmalloc(sizeof(struct tegra_ehci_platform_data), | ||
| 130 | GFP_KERNEL); | ||
| 131 | if (!platform_data) | ||
| 132 | goto error; | ||
| 133 | |||
| 134 | memcpy(platform_data, pdata, sizeof(struct tegra_ehci_platform_data)); | ||
| 135 | pdev->dev.platform_data = platform_data; | ||
| 136 | |||
| 137 | val = platform_device_add(pdev); | ||
| 138 | if (val) | ||
| 139 | goto error_add; | ||
| 140 | |||
| 141 | return pdev; | ||
| 142 | |||
| 143 | error_add: | ||
| 144 | kfree(platform_data); | ||
| 145 | error: | ||
| 146 | pr_err("%s: failed to add the host controller device\n", __func__); | ||
| 147 | platform_device_put(pdev); | ||
| 148 | return NULL; | ||
| 149 | } | ||
| 150 | |||
| 151 | static void tegra_usb_otg_host_unregister(struct platform_device *pdev) | ||
| 152 | { | ||
| 153 | kfree(pdev->dev.platform_data); | ||
| 154 | pdev->dev.platform_data = NULL; | ||
| 155 | platform_device_unregister(pdev); | ||
| 156 | } | ||
| 157 | |||
| 158 | void tegra_start_host(struct tegra_otg_data *tegra) | ||
| 159 | { | ||
| 160 | struct tegra_otg_platform_data *pdata = tegra->otg.dev->platform_data; | ||
| 161 | if (!tegra->pdev) { | ||
| 162 | tegra->pdev = tegra_usb_otg_host_register(pdata->ehci_device, | ||
| 163 | pdata->ehci_pdata); | ||
| 164 | } | ||
| 165 | } | ||
| 166 | |||
| 167 | void tegra_stop_host(struct tegra_otg_data *tegra) | ||
| 168 | { | ||
| 169 | if (tegra->pdev) { | ||
| 170 | tegra_usb_otg_host_unregister(tegra->pdev); | ||
| 171 | tegra->pdev = NULL; | ||
| 172 | } | ||
| 173 | } | ||
| 174 | |||
| 175 | int register_otg_callback(callback_t cb, void *args) | ||
| 176 | { | ||
| 177 | if (!tegra_clone) | ||
| 178 | return -ENODEV; | ||
| 179 | tegra_clone->charger_cb = cb; | ||
| 180 | tegra_clone->charger_cb_data = args; | ||
| 181 | return 0; | ||
| 182 | } | ||
| 183 | EXPORT_SYMBOL_GPL(register_otg_callback); | ||
| 184 | |||
| 185 | static void irq_work(struct work_struct *work) | ||
| 186 | { | ||
| 187 | struct tegra_otg_data *tegra = | ||
| 188 | container_of(work, struct tegra_otg_data, work); | ||
| 189 | struct otg_transceiver *otg = &tegra->otg; | ||
| 190 | enum usb_otg_state from = otg->state; | ||
| 191 | enum usb_otg_state to = OTG_STATE_UNDEFINED; | ||
| 192 | unsigned long flags; | ||
| 193 | unsigned long status; | ||
| 194 | |||
| 195 | if (tegra->detect_vbus) { | ||
| 196 | tegra->detect_vbus = false; | ||
| 197 | tegra_otg_enable_clk(); | ||
| 198 | return; | ||
| 199 | } | ||
| 200 | |||
| 201 | clk_enable(tegra->clk); | ||
| 202 | |||
| 203 | spin_lock_irqsave(&tegra->lock, flags); | ||
| 204 | |||
| 205 | status = tegra->int_status; | ||
| 206 | |||
| 207 | if (tegra->int_status & USB_ID_INT_STATUS) { | ||
| 208 | if (status & USB_ID_STATUS) { | ||
| 209 | if ((status & USB_VBUS_STATUS) && (from != OTG_STATE_A_HOST)) | ||
| 210 | to = OTG_STATE_B_PERIPHERAL; | ||
| 211 | else | ||
| 212 | to = OTG_STATE_A_SUSPEND; | ||
| 213 | } | ||
| 214 | else | ||
| 215 | to = OTG_STATE_A_HOST; | ||
| 216 | } | ||
| 217 | if (from != OTG_STATE_A_HOST) { | ||
| 218 | if (tegra->int_status & USB_VBUS_INT_STATUS) { | ||
| 219 | if (status & USB_VBUS_STATUS) | ||
| 220 | to = OTG_STATE_B_PERIPHERAL; | ||
| 221 | else | ||
| 222 | to = OTG_STATE_A_SUSPEND; | ||
| 223 | } | ||
| 224 | } | ||
| 225 | spin_unlock_irqrestore(&tegra->lock, flags); | ||
| 226 | |||
| 227 | if (to != OTG_STATE_UNDEFINED) { | ||
| 228 | otg->state = to; | ||
| 229 | |||
| 230 | dev_info(tegra->otg.dev, "%s --> %s\n", tegra_state_name(from), | ||
| 231 | tegra_state_name(to)); | ||
| 232 | |||
| 233 | if (tegra->charger_cb) | ||
| 234 | tegra->charger_cb(to, from, tegra->charger_cb_data); | ||
| 235 | |||
| 236 | if (to == OTG_STATE_A_SUSPEND) { | ||
| 237 | if (from == OTG_STATE_A_HOST) | ||
| 238 | tegra_stop_host(tegra); | ||
| 239 | else if (from == OTG_STATE_B_PERIPHERAL && otg->gadget) | ||
| 240 | usb_gadget_vbus_disconnect(otg->gadget); | ||
| 241 | } else if (to == OTG_STATE_B_PERIPHERAL && otg->gadget) { | ||
| 242 | if (from == OTG_STATE_A_SUSPEND) | ||
| 243 | usb_gadget_vbus_connect(otg->gadget); | ||
| 244 | } else if (to == OTG_STATE_A_HOST) { | ||
| 245 | if (from == OTG_STATE_A_SUSPEND) | ||
| 246 | tegra_start_host(tegra); | ||
| 247 | } | ||
| 248 | } | ||
| 249 | |||
| 250 | |||
| 251 | clk_disable(tegra->clk); | ||
| 252 | tegra_otg_disable_clk(); | ||
| 253 | } | ||
| 254 | |||
| 255 | static irqreturn_t tegra_otg_irq(int irq, void *data) | ||
| 256 | { | ||
| 257 | struct tegra_otg_data *tegra = data; | ||
| 258 | unsigned long flags; | ||
| 259 | unsigned long val; | ||
| 260 | |||
| 261 | spin_lock_irqsave(&tegra->lock, flags); | ||
| 262 | |||
| 263 | val = otg_readl(tegra, USB_PHY_WAKEUP); | ||
| 264 | if (val & (USB_VBUS_INT_EN | USB_ID_INT_EN)) { | ||
| 265 | otg_writel(tegra, val, USB_PHY_WAKEUP); | ||
| 266 | if ((val & USB_ID_INT_STATUS) || (val & USB_VBUS_INT_STATUS)) { | ||
| 267 | tegra->int_status = val; | ||
| 268 | tegra->detect_vbus = false; | ||
| 269 | schedule_work(&tegra->work); | ||
| 270 | } | ||
| 271 | } | ||
| 272 | |||
| 273 | spin_unlock_irqrestore(&tegra->lock, flags); | ||
| 274 | |||
| 275 | return IRQ_HANDLED; | ||
| 276 | } | ||
| 277 | |||
| 278 | void tegra_otg_check_vbus_detection(void) | ||
| 279 | { | ||
| 280 | tegra_clone->detect_vbus = true; | ||
| 281 | schedule_work(&tegra_clone->work); | ||
| 282 | } | ||
| 283 | EXPORT_SYMBOL(tegra_otg_check_vbus_detection); | ||
| 284 | |||
| 285 | static int tegra_otg_set_peripheral(struct otg_transceiver *otg, | ||
| 286 | struct usb_gadget *gadget) | ||
| 287 | { | ||
| 288 | struct tegra_otg_data *tegra; | ||
| 289 | unsigned long val; | ||
| 290 | |||
| 291 | tegra = container_of(otg, struct tegra_otg_data, otg); | ||
| 292 | otg->gadget = gadget; | ||
| 293 | |||
| 294 | clk_enable(tegra->clk); | ||
| 295 | val = otg_readl(tegra, USB_PHY_WAKEUP); | ||
| 296 | val |= (USB_VBUS_INT_EN | USB_VBUS_WAKEUP_EN); | ||
| 297 | val |= (USB_ID_INT_EN | USB_ID_PIN_WAKEUP_EN); | ||
| 298 | otg_writel(tegra, val, USB_PHY_WAKEUP); | ||
| 299 | /* Add delay to make sure register is updated */ | ||
| 300 | udelay(1); | ||
| 301 | clk_disable(tegra->clk); | ||
| 302 | |||
| 303 | if ((val & USB_ID_STATUS) && (val & USB_VBUS_STATUS)) { | ||
| 304 | val |= USB_VBUS_INT_STATUS; | ||
| 305 | } else if (!(val & USB_ID_STATUS)) { | ||
| 306 | val |= USB_ID_INT_STATUS; | ||
| 307 | } else { | ||
| 308 | val &= ~(USB_ID_INT_STATUS | USB_VBUS_INT_STATUS); | ||
| 309 | } | ||
| 310 | |||
| 311 | if ((val & USB_ID_INT_STATUS) || (val & USB_VBUS_INT_STATUS)) { | ||
| 312 | tegra->int_status = val; | ||
| 313 | tegra->detect_vbus = false; | ||
| 314 | schedule_work (&tegra->work); | ||
| 315 | } | ||
| 316 | |||
| 317 | return 0; | ||
| 318 | } | ||
| 319 | |||
| 320 | static int tegra_otg_set_host(struct otg_transceiver *otg, | ||
| 321 | struct usb_bus *host) | ||
| 322 | { | ||
| 323 | struct tegra_otg_data *tegra; | ||
| 324 | unsigned long val; | ||
| 325 | |||
| 326 | tegra = container_of(otg, struct tegra_otg_data, otg); | ||
| 327 | otg->host = host; | ||
| 328 | |||
| 329 | clk_enable(tegra->clk); | ||
| 330 | val = otg_readl(tegra, USB_PHY_WAKEUP); | ||
| 331 | val &= ~(USB_VBUS_INT_STATUS | USB_ID_INT_STATUS); | ||
| 332 | |||
| 333 | val |= (USB_ID_INT_EN | USB_ID_PIN_WAKEUP_EN); | ||
| 334 | otg_writel(tegra, val, USB_PHY_WAKEUP); | ||
| 335 | clk_disable(tegra->clk); | ||
| 336 | |||
| 337 | return 0; | ||
| 338 | } | ||
| 339 | |||
| 340 | static int tegra_otg_set_power(struct otg_transceiver *otg, unsigned mA) | ||
| 341 | { | ||
| 342 | return 0; | ||
| 343 | } | ||
| 344 | |||
| 345 | static int tegra_otg_set_suspend(struct otg_transceiver *otg, int suspend) | ||
| 346 | { | ||
| 347 | return 0; | ||
| 348 | } | ||
| 349 | |||
| 350 | static int tegra_otg_probe(struct platform_device *pdev) | ||
| 351 | { | ||
| 352 | struct tegra_otg_data *tegra; | ||
| 353 | struct tegra_otg_platform_data *otg_pdata; | ||
| 354 | struct tegra_ehci_platform_data *ehci_pdata; | ||
| 355 | struct resource *res; | ||
| 356 | int err; | ||
| 357 | |||
| 358 | tegra = kzalloc(sizeof(struct tegra_otg_data), GFP_KERNEL); | ||
| 359 | if (!tegra) | ||
| 360 | return -ENOMEM; | ||
| 361 | |||
| 362 | tegra->otg.dev = &pdev->dev; | ||
| 363 | otg_pdata = tegra->otg.dev->platform_data; | ||
| 364 | ehci_pdata = otg_pdata->ehci_pdata; | ||
| 365 | tegra->otg.label = "tegra-otg"; | ||
| 366 | tegra->otg.state = OTG_STATE_UNDEFINED; | ||
| 367 | tegra->otg.set_host = tegra_otg_set_host; | ||
| 368 | tegra->otg.set_peripheral = tegra_otg_set_peripheral; | ||
| 369 | tegra->otg.set_suspend = tegra_otg_set_suspend; | ||
| 370 | tegra->otg.set_power = tegra_otg_set_power; | ||
| 371 | spin_lock_init(&tegra->lock); | ||
| 372 | |||
| 373 | platform_set_drvdata(pdev, tegra); | ||
| 374 | tegra_clone = tegra; | ||
| 375 | tegra->clk_enabled = false; | ||
| 376 | |||
| 377 | tegra->clk = clk_get(&pdev->dev, NULL); | ||
| 378 | if (IS_ERR(tegra->clk)) { | ||
| 379 | dev_err(&pdev->dev, "Can't get otg clock\n"); | ||
| 380 | err = PTR_ERR(tegra->clk); | ||
| 381 | goto err_clk; | ||
| 382 | } | ||
| 383 | |||
| 384 | err = clk_enable(tegra->clk); | ||
| 385 | if (err) | ||
| 386 | goto err_clken; | ||
| 387 | |||
| 388 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 389 | if (!res) { | ||
| 390 | dev_err(&pdev->dev, "Failed to get I/O memory\n"); | ||
| 391 | err = -ENXIO; | ||
| 392 | goto err_io; | ||
| 393 | } | ||
| 394 | tegra->regs = ioremap(res->start, resource_size(res)); | ||
| 395 | if (!tegra->regs) { | ||
| 396 | err = -ENOMEM; | ||
| 397 | goto err_io; | ||
| 398 | } | ||
| 399 | |||
| 400 | tegra->otg.state = OTG_STATE_A_SUSPEND; | ||
| 401 | |||
| 402 | err = otg_set_transceiver(&tegra->otg); | ||
| 403 | if (err) { | ||
| 404 | dev_err(&pdev->dev, "can't register transceiver (%d)\n", err); | ||
| 405 | goto err_otg; | ||
| 406 | } | ||
| 407 | |||
| 408 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
| 409 | if (!res) { | ||
| 410 | dev_err(&pdev->dev, "Failed to get IRQ\n"); | ||
| 411 | err = -ENXIO; | ||
| 412 | goto err_irq; | ||
| 413 | } | ||
| 414 | tegra->irq = res->start; | ||
| 415 | err = request_threaded_irq(tegra->irq, tegra_otg_irq, | ||
| 416 | NULL, | ||
| 417 | IRQF_SHARED, "tegra-otg", tegra); | ||
| 418 | if (err) { | ||
| 419 | dev_err(&pdev->dev, "Failed to register IRQ\n"); | ||
| 420 | goto err_irq; | ||
| 421 | } | ||
| 422 | INIT_WORK (&tegra->work, irq_work); | ||
| 423 | |||
| 424 | if (!ehci_pdata->default_enable) | ||
| 425 | clk_disable(tegra->clk); | ||
| 426 | dev_info(&pdev->dev, "otg transceiver registered\n"); | ||
| 427 | return 0; | ||
| 428 | |||
| 429 | err_irq: | ||
| 430 | otg_set_transceiver(NULL); | ||
| 431 | err_otg: | ||
| 432 | iounmap(tegra->regs); | ||
| 433 | err_io: | ||
| 434 | clk_disable(tegra->clk); | ||
| 435 | err_clken: | ||
| 436 | clk_put(tegra->clk); | ||
| 437 | err_clk: | ||
| 438 | platform_set_drvdata(pdev, NULL); | ||
| 439 | kfree(tegra); | ||
| 440 | return err; | ||
| 441 | } | ||
| 442 | |||
| 443 | static int __exit tegra_otg_remove(struct platform_device *pdev) | ||
| 444 | { | ||
| 445 | struct tegra_otg_data *tegra = platform_get_drvdata(pdev); | ||
| 446 | |||
| 447 | free_irq(tegra->irq, tegra); | ||
| 448 | otg_set_transceiver(NULL); | ||
| 449 | iounmap(tegra->regs); | ||
| 450 | clk_disable(tegra->clk); | ||
| 451 | clk_put(tegra->clk); | ||
| 452 | platform_set_drvdata(pdev, NULL); | ||
| 453 | kfree(tegra); | ||
| 454 | |||
| 455 | return 0; | ||
| 456 | } | ||
| 457 | |||
| 458 | #ifdef CONFIG_PM | ||
| 459 | static int tegra_otg_suspend(struct device *dev) | ||
| 460 | { | ||
| 461 | struct platform_device *pdev = to_platform_device(dev); | ||
| 462 | struct tegra_otg_data *tegra_otg = platform_get_drvdata(pdev); | ||
| 463 | struct otg_transceiver *otg = &tegra_otg->otg; | ||
| 464 | enum usb_otg_state from = otg->state; | ||
| 465 | /* store the interupt enable for cable ID and VBUS */ | ||
| 466 | clk_enable(tegra_otg->clk); | ||
| 467 | tegra_otg->intr_reg_data = readl(tegra_otg->regs + USB_PHY_WAKEUP); | ||
| 468 | writel(0, (tegra_otg->regs + USB_PHY_WAKEUP)); | ||
| 469 | clk_disable(tegra_otg->clk); | ||
| 470 | |||
| 471 | if (from == OTG_STATE_B_PERIPHERAL && otg->gadget) { | ||
| 472 | usb_gadget_vbus_disconnect(otg->gadget); | ||
| 473 | otg->state = OTG_STATE_A_SUSPEND; | ||
| 474 | } | ||
| 475 | tegra_otg_disable_clk(); | ||
| 476 | return 0; | ||
| 477 | } | ||
| 478 | |||
| 479 | static void tegra_otg_resume(struct device *dev) | ||
| 480 | { | ||
| 481 | struct platform_device *pdev = to_platform_device(dev); | ||
| 482 | struct tegra_otg_data *tegra_otg = platform_get_drvdata(pdev); | ||
| 483 | int val; | ||
| 484 | unsigned long flags; | ||
| 485 | |||
| 486 | tegra_otg_enable_clk(); | ||
| 487 | |||
| 488 | /* Following delay is intentional. | ||
| 489 | * It is placed here after observing system hang. | ||
| 490 | * Root cause is not confirmed. | ||
| 491 | */ | ||
| 492 | msleep(1); | ||
| 493 | /* restore the interupt enable for cable ID and VBUS */ | ||
| 494 | clk_enable(tegra_otg->clk); | ||
| 495 | writel(tegra_otg->intr_reg_data, (tegra_otg->regs + USB_PHY_WAKEUP)); | ||
| 496 | val = readl(tegra_otg->regs + USB_PHY_WAKEUP); | ||
| 497 | clk_disable(tegra_otg->clk); | ||
| 498 | |||
| 499 | /* A device might be connected while CPU is in sleep mode. In this case no interrupt | ||
| 500 | * will be triggered | ||
| 501 | * force irq_work to recheck connected devices | ||
| 502 | */ | ||
| 503 | if (!(val & USB_ID_STATUS)) { | ||
| 504 | spin_lock_irqsave(&tegra_otg->lock, flags); | ||
| 505 | tegra_otg->int_status = (val | USB_ID_INT_STATUS ); | ||
| 506 | schedule_work(&tegra_otg->work); | ||
| 507 | spin_unlock_irqrestore(&tegra_otg->lock, flags); | ||
| 508 | } | ||
| 509 | |||
| 510 | return; | ||
| 511 | } | ||
| 512 | |||
| 513 | static const struct dev_pm_ops tegra_otg_pm_ops = { | ||
| 514 | .complete = tegra_otg_resume, | ||
| 515 | .suspend = tegra_otg_suspend, | ||
| 516 | }; | ||
| 517 | #endif | ||
| 518 | |||
| 519 | static struct platform_driver tegra_otg_driver = { | ||
| 520 | .driver = { | ||
| 521 | .name = "tegra-otg", | ||
| 522 | #ifdef CONFIG_PM | ||
| 523 | .pm = &tegra_otg_pm_ops, | ||
| 524 | #endif | ||
| 525 | }, | ||
| 526 | .remove = __exit_p(tegra_otg_remove), | ||
| 527 | .probe = tegra_otg_probe, | ||
| 528 | }; | ||
| 529 | |||
| 530 | static int __init tegra_otg_init(void) | ||
| 531 | { | ||
| 532 | return platform_driver_register(&tegra_otg_driver); | ||
| 533 | } | ||
| 534 | subsys_initcall(tegra_otg_init); | ||
| 535 | |||
| 536 | static void __exit tegra_otg_exit(void) | ||
| 537 | { | ||
| 538 | platform_driver_unregister(&tegra_otg_driver); | ||
| 539 | } | ||
| 540 | module_exit(tegra_otg_exit); | ||
diff --git a/drivers/usb/serial/ChangeLog.history b/drivers/usb/serial/ChangeLog.history new file mode 100644 index 00000000000..f13fd488ebe --- /dev/null +++ b/drivers/usb/serial/ChangeLog.history | |||
| @@ -0,0 +1,730 @@ | |||
| 1 | This is the contents of some of the drivers/usb/serial/ files that had old | ||
| 2 | changelog comments. They were quite old, and out of date, and we don't keep | ||
| 3 | them anymore, so I've put them here, away from the source files, in case | ||
| 4 | people still care to see them. | ||
| 5 | |||
| 6 | - Greg Kroah-Hartman <greg@kroah.com> October 20, 2005 | ||
| 7 | |||
| 8 | ----------------------------------------------------------------------- | ||
| 9 | usb-serial.h Change Log comments: | ||
| 10 | |||
| 11 | (03/26/2002) gkh | ||
| 12 | removed the port->tty check from port_paranoia_check() due to serial | ||
| 13 | consoles not having a tty device assigned to them. | ||
| 14 | |||
| 15 | (12/03/2001) gkh | ||
| 16 | removed active from the port structure. | ||
| 17 | added documentation to the usb_serial_device_type structure | ||
| 18 | |||
| 19 | (10/10/2001) gkh | ||
| 20 | added vendor and product to serial structure. Needed to determine device | ||
| 21 | owner when the device is disconnected. | ||
| 22 | |||
| 23 | (05/30/2001) gkh | ||
| 24 | added sem to port structure and removed port_lock | ||
| 25 | |||
| 26 | (10/05/2000) gkh | ||
| 27 | Added interrupt_in_endpointAddress and bulk_in_endpointAddress to help | ||
| 28 | fix bug with urb->dev not being set properly, now that the usb core | ||
| 29 | needs it. | ||
| 30 | |||
| 31 | (09/11/2000) gkh | ||
| 32 | Added usb_serial_debug_data function to help get rid of #DEBUG in the | ||
| 33 | drivers. | ||
| 34 | |||
| 35 | (08/28/2000) gkh | ||
| 36 | Added port_lock to port structure. | ||
| 37 | |||
| 38 | (08/08/2000) gkh | ||
| 39 | Added open_count to port structure. | ||
| 40 | |||
| 41 | (07/23/2000) gkh | ||
| 42 | Added bulk_out_endpointAddress to port structure. | ||
| 43 | |||
| 44 | (07/19/2000) gkh, pberger, and borchers | ||
| 45 | Modifications to allow usb-serial drivers to be modules. | ||
| 46 | |||
| 47 | ----------------------------------------------------------------------- | ||
| 48 | usb-serial.c Change Log comments: | ||
| 49 | |||
| 50 | (12/10/2002) gkh | ||
| 51 | Split the ports off into their own struct device, and added a | ||
| 52 | usb-serial bus driver. | ||
| 53 | |||
| 54 | (11/19/2002) gkh | ||
| 55 | removed a few #ifdefs for the generic code and cleaned up the failure | ||
| 56 | logic in initialization. | ||
| 57 | |||
| 58 | (10/02/2002) gkh | ||
| 59 | moved the console code to console.c and out of this file. | ||
| 60 | |||
| 61 | (06/05/2002) gkh | ||
| 62 | moved location of startup() call in serial_probe() until after all | ||
| 63 | of the port information and endpoints are initialized. This makes | ||
| 64 | things easier for some drivers. | ||
| 65 | |||
| 66 | (04/10/2002) gkh | ||
| 67 | added serial_read_proc function which creates a | ||
| 68 | /proc/tty/driver/usb-serial file. | ||
| 69 | |||
| 70 | (03/27/2002) gkh | ||
| 71 | Got USB serial console code working properly and merged into the main | ||
| 72 | version of the tree. Thanks to Randy Dunlap for the initial version | ||
| 73 | of this code, and for pushing me to finish it up. | ||
| 74 | The USB serial console works with any usb serial driver device. | ||
| 75 | |||
| 76 | (03/21/2002) gkh | ||
| 77 | Moved all manipulation of port->open_count into the core. Now the | ||
| 78 | individual driver's open and close functions are called only when the | ||
| 79 | first open() and last close() is called. Making the drivers a bit | ||
| 80 | smaller and simpler. | ||
| 81 | Fixed a bug if a driver didn't have the owner field set. | ||
| 82 | |||
| 83 | (02/26/2002) gkh | ||
| 84 | Moved all locking into the main serial_* functions, instead of having | ||
| 85 | the individual drivers have to grab the port semaphore. This should | ||
| 86 | reduce races. | ||
| 87 | Reworked the MOD_INC logic a bit to always increment and decrement, even | ||
| 88 | if the generic driver is being used. | ||
| 89 | |||
| 90 | (10/10/2001) gkh | ||
| 91 | usb_serial_disconnect() now sets the serial->dev pointer is to NULL to | ||
| 92 | help prevent child drivers from accessing the device since it is now | ||
| 93 | gone. | ||
| 94 | |||
| 95 | (09/13/2001) gkh | ||
| 96 | Moved generic driver initialize after we have registered with the USB | ||
| 97 | core. Thanks to Randy Dunlap for pointing this problem out. | ||
| 98 | |||
| 99 | (07/03/2001) gkh | ||
| 100 | Fixed module paramater size. Thanks to John Brockmeyer for the pointer. | ||
| 101 | Fixed vendor and product getting defined through the MODULE_PARM macro | ||
| 102 | if the Generic driver wasn't compiled in. | ||
| 103 | Fixed problem with generic_shutdown() not being called for drivers that | ||
| 104 | don't have a shutdown() function. | ||
| 105 | |||
| 106 | (06/06/2001) gkh | ||
| 107 | added evil hack that is needed for the prolific pl2303 device due to the | ||
| 108 | crazy way its endpoints are set up. | ||
| 109 | |||
| 110 | (05/30/2001) gkh | ||
| 111 | switched from using spinlock to a semaphore, which fixes lots of problems. | ||
| 112 | |||
| 113 | (04/08/2001) gb | ||
| 114 | Identify version on module load. | ||
| 115 | |||
| 116 | 2001_02_05 gkh | ||
| 117 | Fixed buffer overflows bug with the generic serial driver. Thanks to | ||
| 118 | Todd Squires <squirest@ct0.com> for fixing this. | ||
| 119 | |||
| 120 | (01/10/2001) gkh | ||
| 121 | Fixed bug where the generic serial adaptor grabbed _any_ device that was | ||
| 122 | offered to it. | ||
| 123 | |||
| 124 | (12/12/2000) gkh | ||
| 125 | Removed MOD_INC and MOD_DEC from poll and disconnect functions, and | ||
| 126 | moved them to the serial_open and serial_close functions. | ||
| 127 | Also fixed bug with there not being a MOD_DEC for the generic driver | ||
| 128 | (thanks to Gary Brubaker for finding this.) | ||
| 129 | |||
| 130 | (11/29/2000) gkh | ||
| 131 | Small NULL pointer initialization cleanup which saves a bit of disk image | ||
| 132 | |||
| 133 | (11/01/2000) Adam J. Richter | ||
| 134 | instead of using idVendor/idProduct pairs, usb serial drivers | ||
| 135 | now identify their hardware interest with usb_device_id tables, | ||
| 136 | which they usually have anyhow for use with MODULE_DEVICE_TABLE. | ||
| 137 | |||
| 138 | (10/05/2000) gkh | ||
| 139 | Fixed bug with urb->dev not being set properly, now that the usb | ||
| 140 | core needs it. | ||
| 141 | |||
| 142 | (09/11/2000) gkh | ||
| 143 | Removed DEBUG #ifdefs with call to usb_serial_debug_data | ||
| 144 | |||
| 145 | (08/28/2000) gkh | ||
| 146 | Added port_lock to port structure. | ||
| 147 | Added locks for SMP safeness to generic driver | ||
| 148 | Fixed the ability to open a generic device's port more than once. | ||
| 149 | |||
| 150 | (07/23/2000) gkh | ||
| 151 | Added bulk_out_endpointAddress to port structure. | ||
| 152 | |||
| 153 | (07/19/2000) gkh, pberger, and borchers | ||
| 154 | Modifications to allow usb-serial drivers to be modules. | ||
| 155 | |||
| 156 | (07/03/2000) gkh | ||
| 157 | Added more debugging to serial_ioctl call | ||
| 158 | |||
| 159 | (06/25/2000) gkh | ||
| 160 | Changed generic_write_bulk_callback to not call wake_up_interruptible | ||
| 161 | directly, but to have port_softint do it at a safer time. | ||
| 162 | |||
| 163 | (06/23/2000) gkh | ||
| 164 | Cleaned up debugging statements in a quest to find UHCI timeout bug. | ||
| 165 | |||
| 166 | (05/22/2000) gkh | ||
| 167 | Changed the makefile, enabling the big CONFIG_USB_SERIAL_SOMTHING to be | ||
| 168 | removed from the individual device source files. | ||
| 169 | |||
| 170 | (05/03/2000) gkh | ||
| 171 | Added the Digi Acceleport driver from Al Borchers and Peter Berger. | ||
| 172 | |||
| 173 | (05/02/2000) gkh | ||
| 174 | Changed devfs and tty register code to work properly now. This was based on | ||
| 175 | the ACM driver changes by Vojtech Pavlik. | ||
| 176 | |||
| 177 | (04/27/2000) Ryan VanderBijl | ||
| 178 | Put calls to *_paranoia_checks into one function. | ||
| 179 | |||
| 180 | (04/23/2000) gkh | ||
| 181 | Fixed bug that Randy Dunlap found for Generic devices with no bulk out ports. | ||
| 182 | Moved when the startup code printed out the devices that are supported. | ||
| 183 | |||
| 184 | (04/19/2000) gkh | ||
| 185 | Added driver for ZyXEL omni.net lcd plus ISDN TA | ||
| 186 | Made startup info message specify which drivers were compiled in. | ||
| 187 | |||
| 188 | (04/03/2000) gkh | ||
| 189 | Changed the probe process to remove the module unload races. | ||
| 190 | Changed where the tty layer gets initialized to have devfs work nicer. | ||
| 191 | Added initial devfs support. | ||
| 192 | |||
| 193 | (03/26/2000) gkh | ||
| 194 | Split driver up into device specific pieces. | ||
| 195 | |||
| 196 | (03/19/2000) gkh | ||
| 197 | Fixed oops that could happen when device was removed while a program | ||
| 198 | was talking to the device. | ||
| 199 | Removed the static urbs and now all urbs are created and destroyed | ||
| 200 | dynamically. | ||
| 201 | Reworked the internal interface. Now everything is based on the | ||
| 202 | usb_serial_port structure instead of the larger usb_serial structure. | ||
| 203 | This fixes the bug that a multiport device could not have more than | ||
| 204 | one port open at one time. | ||
| 205 | |||
| 206 | (03/17/2000) gkh | ||
| 207 | Added config option for debugging messages. | ||
| 208 | Added patch for keyspan pda from Brian Warner. | ||
| 209 | |||
| 210 | (03/06/2000) gkh | ||
| 211 | Added the keyspan pda code from Brian Warner <warner@lothar.com> | ||
| 212 | Moved a bunch of the port specific stuff into its own structure. This | ||
| 213 | is in anticipation of the true multiport devices (there's a bug if you | ||
| 214 | try to access more than one port of any multiport device right now) | ||
| 215 | |||
| 216 | (02/21/2000) gkh | ||
| 217 | Made it so that any serial devices only have to specify which functions | ||
| 218 | they want to overload from the generic function calls (great, | ||
| 219 | inheritance in C, in a driver, just what I wanted...) | ||
| 220 | Added support for set_termios and ioctl function calls. No drivers take | ||
| 221 | advantage of this yet. | ||
| 222 | Removed the #ifdef MODULE, now there is no module specific code. | ||
| 223 | Cleaned up a few comments in usb-serial.h that were wrong (thanks again | ||
| 224 | to Miles Lott). | ||
| 225 | Small fix to get_free_serial. | ||
| 226 | |||
| 227 | (02/14/2000) gkh | ||
| 228 | Removed the Belkin and Peracom functionality from the driver due to | ||
| 229 | the lack of support from the vendor, and me not wanting people to | ||
| 230 | accidenatly buy the device, expecting it to work with Linux. | ||
| 231 | Added read_bulk_callback and write_bulk_callback to the type structure | ||
| 232 | for the needs of the FTDI and WhiteHEAT driver. | ||
| 233 | Changed all reverences to FTDI to FTDI_SIO at the request of Bill | ||
| 234 | Ryder. | ||
| 235 | Changed the output urb size back to the max endpoint size to make | ||
| 236 | the ftdi_sio driver have it easier, and due to the fact that it didn't | ||
| 237 | really increase the speed any. | ||
| 238 | |||
| 239 | (02/11/2000) gkh | ||
| 240 | Added VISOR_FUNCTION_CONSOLE to the visor startup function. This was a | ||
| 241 | patch from Miles Lott (milos@insync.net). | ||
| 242 | Fixed bug with not restoring the minor range that a device grabs, if | ||
| 243 | the startup function fails (thanks Miles for finding this). | ||
| 244 | |||
| 245 | (02/05/2000) gkh | ||
| 246 | Added initial framework for the Keyspan PDA serial converter so that | ||
| 247 | Brian Warner has a place to put his code. | ||
| 248 | Made the ezusb specific functions generic enough that different | ||
| 249 | devices can use them (whiteheat and keyspan_pda both need them). | ||
| 250 | Split out a whole bunch of structure and other stuff to a separate | ||
| 251 | usb-serial.h file. | ||
| 252 | Made the Visor connection messages a little more understandable, now | ||
| 253 | that Miles Lott (milos@insync.net) has gotten the Generic channel to | ||
| 254 | work. Also made them always show up in the log file. | ||
| 255 | |||
| 256 | (01/25/2000) gkh | ||
| 257 | Added initial framework for FTDI serial converter so that Bill Ryder | ||
| 258 | has a place to put his code. | ||
| 259 | Added the vendor specific info from Handspring. Now we can print out | ||
| 260 | informational debug messages as well as understand what is happening. | ||
| 261 | |||
| 262 | (01/23/2000) gkh | ||
| 263 | Fixed problem of crash when trying to open a port that didn't have a | ||
| 264 | device assigned to it. Made the minor node finding a little smarter, | ||
| 265 | now it looks to find a continuous space for the new device. | ||
| 266 | |||
| 267 | (01/21/2000) gkh | ||
| 268 | Fixed bug in visor_startup with patch from Miles Lott (milos@insync.net) | ||
| 269 | Fixed get_serial_by_minor which was all messed up for multi port | ||
| 270 | devices. Fixed multi port problem for generic devices. Now the number | ||
| 271 | of ports is determined by the number of bulk out endpoints for the | ||
| 272 | generic device. | ||
| 273 | |||
| 274 | (01/19/2000) gkh | ||
| 275 | Removed lots of cruft that was around from the old (pre urb) driver | ||
| 276 | interface. | ||
| 277 | Made the serial_table dynamic. This should save lots of memory when | ||
| 278 | the number of minor nodes goes up to 256. | ||
| 279 | Added initial support for devices that have more than one port. | ||
| 280 | Added more debugging comments for the Visor, and added a needed | ||
| 281 | set_configuration call. | ||
| 282 | |||
| 283 | (01/17/2000) gkh | ||
| 284 | Fixed the WhiteHEAT firmware (my processing tool had a bug) | ||
| 285 | and added new debug loader firmware for it. | ||
| 286 | Removed the put_char function as it isn't really needed. | ||
| 287 | Added visor startup commands as found by the Win98 dump. | ||
| 288 | |||
| 289 | (01/13/2000) gkh | ||
| 290 | Fixed the vendor id for the generic driver to the one I meant it to be. | ||
| 291 | |||
| 292 | (01/12/2000) gkh | ||
| 293 | Forget the version numbering...that's pretty useless... | ||
| 294 | Made the driver able to be compiled so that the user can select which | ||
| 295 | converter they want to use. This allows people who only want the Visor | ||
| 296 | support to not pay the memory size price of the WhiteHEAT. | ||
| 297 | Fixed bug where the generic driver (idVendor=0000 and idProduct=0000) | ||
| 298 | grabbed the root hub. Not good. | ||
| 299 | |||
| 300 | version 0.4.0 (01/10/2000) gkh | ||
| 301 | Added whiteheat.h containing the firmware for the ConnectTech WhiteHEAT | ||
| 302 | device. Added startup function to allow firmware to be downloaded to | ||
| 303 | a device if it needs to be. | ||
| 304 | Added firmware download logic to the WhiteHEAT device. | ||
| 305 | Started to add #defines to split up the different drivers for potential | ||
| 306 | configuration option. | ||
| 307 | |||
| 308 | version 0.3.1 (12/30/99) gkh | ||
| 309 | Fixed problems with urb for bulk out. | ||
| 310 | Added initial support for multiple sets of endpoints. This enables | ||
| 311 | the Handspring Visor to be attached successfully. Only the first | ||
| 312 | bulk in / bulk out endpoint pair is being used right now. | ||
| 313 | |||
| 314 | version 0.3.0 (12/27/99) gkh | ||
| 315 | Added initial support for the Handspring Visor based on a patch from | ||
| 316 | Miles Lott (milos@sneety.insync.net) | ||
| 317 | Cleaned up the code a bunch and converted over to using urbs only. | ||
| 318 | |||
| 319 | version 0.2.3 (12/21/99) gkh | ||
| 320 | Added initial support for the Connect Tech WhiteHEAT converter. | ||
| 321 | Incremented the number of ports in expectation of getting the | ||
| 322 | WhiteHEAT to work properly (4 ports per connection). | ||
| 323 | Added notification on insertion and removal of what port the | ||
| 324 | device is/was connected to (and what kind of device it was). | ||
| 325 | |||
| 326 | version 0.2.2 (12/16/99) gkh | ||
| 327 | Changed major number to the new allocated number. We're legal now! | ||
| 328 | |||
| 329 | version 0.2.1 (12/14/99) gkh | ||
| 330 | Fixed bug that happens when device node is opened when there isn't a | ||
| 331 | device attached to it. Thanks to marek@webdesign.no for noticing this. | ||
| 332 | |||
| 333 | version 0.2.0 (11/10/99) gkh | ||
| 334 | Split up internals to make it easier to add different types of serial | ||
| 335 | converters to the code. | ||
| 336 | Added a "generic" driver that gets it's vendor and product id | ||
| 337 | from when the module is loaded. Thanks to David E. Nelson (dnelson@jump.net) | ||
| 338 | for the idea and sample code (from the usb scanner driver.) | ||
| 339 | Cleared up any licensing questions by releasing it under the GNU GPL. | ||
| 340 | |||
| 341 | version 0.1.2 (10/25/99) gkh | ||
| 342 | Fixed bug in detecting device. | ||
| 343 | |||
| 344 | version 0.1.1 (10/05/99) gkh | ||
| 345 | Changed the major number to not conflict with anything else. | ||
| 346 | |||
| 347 | version 0.1 (09/28/99) gkh | ||
| 348 | Can recognize the two different devices and start up a read from | ||
| 349 | device when asked to. Writes also work. No control signals yet, this | ||
| 350 | all is vendor specific data (i.e. no spec), also no control for | ||
| 351 | different baud rates or other bit settings. | ||
| 352 | Currently we are using the same devid as the acm driver. This needs | ||
| 353 | to change. | ||
| 354 | |||
| 355 | ----------------------------------------------------------------------- | ||
| 356 | visor.c Change Log comments: | ||
| 357 | |||
| 358 | (06/03/2003) Judd Montgomery <judd at jpilot.org> | ||
| 359 | Added support for module parameter options for untested/unknown | ||
| 360 | devices. | ||
| 361 | |||
| 362 | (03/09/2003) gkh | ||
| 363 | Added support for the Sony Clie NZ90V device. Thanks to Martin Brachtl | ||
| 364 | <brachtl@redgrep.cz> for the information. | ||
| 365 | |||
| 366 | (03/05/2003) gkh | ||
| 367 | Think Treo support is now working. | ||
| 368 | |||
| 369 | (04/03/2002) gkh | ||
| 370 | Added support for the Sony OS 4.1 devices. Thanks to Hiroyuki ARAKI | ||
| 371 | <hiro@zob.ne.jp> for the information. | ||
| 372 | |||
| 373 | (03/27/2002) gkh | ||
| 374 | Removed assumptions that port->tty was always valid (is not true | ||
| 375 | for usb serial console devices.) | ||
| 376 | |||
| 377 | (03/23/2002) gkh | ||
| 378 | Added support for the Palm i705 device, thanks to Thomas Riemer | ||
| 379 | <tom@netmech.com> for the information. | ||
| 380 | |||
| 381 | (03/21/2002) gkh | ||
| 382 | Added support for the Palm m130 device, thanks to Udo Eisenbarth | ||
| 383 | <udo.eisenbarth@web.de> for the information. | ||
| 384 | |||
| 385 | (02/27/2002) gkh | ||
| 386 | Reworked the urb handling logic. We have no more pool, but dynamically | ||
| 387 | allocate the urb and the transfer buffer on the fly. In testing this | ||
| 388 | does not incure any measurable overhead. This also relies on the fact | ||
| 389 | that we have proper reference counting logic for urbs. | ||
| 390 | |||
| 391 | (02/21/2002) SilaS | ||
| 392 | Added initial support for the Palm m515 devices. | ||
| 393 | |||
| 394 | (02/14/2002) gkh | ||
| 395 | Added support for the Clie S-360 device. | ||
| 396 | |||
| 397 | (12/18/2001) gkh | ||
| 398 | Added better Clie support for 3.5 devices. Thanks to Geoffrey Levand | ||
| 399 | for the patch. | ||
| 400 | |||
| 401 | (11/11/2001) gkh | ||
| 402 | Added support for the m125 devices, and added check to prevent oopses | ||
| 403 | for Clié devices that lie about the number of ports they have. | ||
| 404 | |||
| 405 | (08/30/2001) gkh | ||
| 406 | Added support for the Clie devices, both the 3.5 and 4.0 os versions. | ||
| 407 | Many thanks to Daniel Burke, and Bryan Payne for helping with this. | ||
| 408 | |||
| 409 | (08/23/2001) gkh | ||
| 410 | fixed a few potential bugs pointed out by Oliver Neukum. | ||
| 411 | |||
| 412 | (05/30/2001) gkh | ||
| 413 | switched from using spinlock to a semaphore, which fixes lots of problems. | ||
| 414 | |||
| 415 | (05/28/2000) gkh | ||
| 416 | Added initial support for the Palm m500 and Palm m505 devices. | ||
| 417 | |||
| 418 | (04/08/2001) gb | ||
| 419 | Identify version on module load. | ||
| 420 | |||
| 421 | (01/21/2000) gkh | ||
| 422 | Added write_room and chars_in_buffer, as they were previously using the | ||
| 423 | generic driver versions which is all wrong now that we are using an urb | ||
| 424 | pool. Thanks to Wolfgang Grandegger for pointing this out to me. | ||
| 425 | Removed count assignment in the write function, which was not needed anymore | ||
| 426 | either. Thanks to Al Borchers for pointing this out. | ||
| 427 | |||
| 428 | (12/12/2000) gkh | ||
| 429 | Moved MOD_DEC to end of visor_close to be nicer, as the final write | ||
| 430 | message can sleep. | ||
| 431 | |||
| 432 | (11/12/2000) gkh | ||
| 433 | Fixed bug with data being dropped on the floor by forcing tty->low_latency | ||
| 434 | to be on. Hopefully this fixes the OHCI issue! | ||
| 435 | |||
| 436 | (11/01/2000) Adam J. Richter | ||
| 437 | usb_device_id table support | ||
| 438 | |||
| 439 | (10/05/2000) gkh | ||
| 440 | Fixed bug with urb->dev not being set properly, now that the usb | ||
| 441 | core needs it. | ||
| 442 | |||
| 443 | (09/11/2000) gkh | ||
| 444 | Got rid of always calling kmalloc for every urb we wrote out to the | ||
| 445 | device. | ||
| 446 | Added visor_read_callback so we can keep track of bytes in and out for | ||
| 447 | those people who like to know the speed of their device. | ||
| 448 | Removed DEBUG #ifdefs with call to usb_serial_debug_data | ||
| 449 | |||
| 450 | (09/06/2000) gkh | ||
| 451 | Fixed oops in visor_exit. Need to uncomment usb_unlink_urb call _after_ | ||
| 452 | the host controller drivers set urb->dev = NULL when the urb is finished. | ||
| 453 | |||
| 454 | (08/28/2000) gkh | ||
| 455 | Added locks for SMP safeness. | ||
| 456 | |||
| 457 | (08/08/2000) gkh | ||
| 458 | Fixed endian problem in visor_startup. | ||
| 459 | Fixed MOD_INC and MOD_DEC logic and the ability to open a port more | ||
| 460 | than once. | ||
| 461 | |||
| 462 | (07/23/2000) gkh | ||
| 463 | Added pool of write urbs to speed up transfers to the visor. | ||
| 464 | |||
| 465 | (07/19/2000) gkh | ||
| 466 | Added module_init and module_exit functions to handle the fact that this | ||
| 467 | driver is a loadable module now. | ||
| 468 | |||
| 469 | (07/03/2000) gkh | ||
| 470 | Added visor_set_ioctl and visor_set_termios functions (they don't do much | ||
| 471 | of anything, but are good for debugging.) | ||
| 472 | |||
| 473 | (06/25/2000) gkh | ||
| 474 | Fixed bug in visor_unthrottle that should help with the disconnect in PPP | ||
| 475 | bug that people have been reporting. | ||
| 476 | |||
| 477 | (06/23/2000) gkh | ||
| 478 | Cleaned up debugging statements in a quest to find UHCI timeout bug. | ||
| 479 | |||
| 480 | (04/27/2000) Ryan VanderBijl | ||
| 481 | Fixed memory leak in visor_close | ||
| 482 | |||
| 483 | (03/26/2000) gkh | ||
| 484 | Split driver up into device specific pieces. | ||
| 485 | |||
| 486 | ----------------------------------------------------------------------- | ||
| 487 | pl2303.c Change Log comments: | ||
| 488 | |||
| 489 | 2002_Mar_26 gkh | ||
| 490 | allowed driver to work properly if there is no tty assigned to a port | ||
| 491 | (this happens for serial console devices.) | ||
| 492 | |||
| 493 | 2001_Oct_06 gkh | ||
| 494 | Added RTS and DTR line control. Thanks to joe@bndlg.de for parts of it. | ||
| 495 | |||
| 496 | 2001_Sep_19 gkh | ||
| 497 | Added break support. | ||
| 498 | |||
| 499 | 2001_Aug_30 gkh | ||
| 500 | fixed oops in write_bulk_callback. | ||
| 501 | |||
| 502 | 2001_Aug_28 gkh | ||
| 503 | reworked buffer logic to be like other usb-serial drivers. Hopefully | ||
| 504 | removing some reported problems. | ||
| 505 | |||
| 506 | 2001_Jun_06 gkh | ||
| 507 | finished porting to 2.4 format. | ||
| 508 | |||
| 509 | |||
| 510 | ----------------------------------------------------------------------- | ||
| 511 | io_edgeport.c Change Log comments: | ||
| 512 | |||
| 513 | 2003_04_03 al borchers | ||
| 514 | - fixed a bug (that shows up with dosemu) where the tty struct is | ||
| 515 | used in a callback after it has been freed | ||
| 516 | |||
| 517 | 2.3 2002_03_08 greg kroah-hartman | ||
| 518 | - fixed bug when multiple devices were attached at the same time. | ||
| 519 | |||
| 520 | 2.2 2001_11_14 greg kroah-hartman | ||
| 521 | - fixed bug in edge_close that kept the port from being used more | ||
| 522 | than once. | ||
| 523 | - fixed memory leak on device removal. | ||
| 524 | - fixed potential double free of memory when command urb submitting | ||
| 525 | failed. | ||
| 526 | - other small cleanups when the device is removed | ||
| 527 | |||
| 528 | 2.1 2001_07_09 greg kroah-hartman | ||
| 529 | - added support for TIOCMBIS and TIOCMBIC. | ||
| 530 | |||
| 531 | (04/08/2001) gb | ||
| 532 | - Identify version on module load. | ||
| 533 | |||
| 534 | 2.0 2001_03_05 greg kroah-hartman | ||
| 535 | - reworked entire driver to fit properly in with the other usb-serial | ||
| 536 | drivers. Occasional oopses still happen, but it's a good start. | ||
| 537 | |||
| 538 | 1.2.3 (02/23/2001) greg kroah-hartman | ||
| 539 | - changed device table to work properly for 2.4.x final format. | ||
| 540 | - fixed problem with dropping data at high data rates. | ||
| 541 | |||
| 542 | 1.2.2 (11/27/2000) greg kroah-hartman | ||
| 543 | - cleaned up more NTisms. | ||
| 544 | - Added device table for 2.4.0-test11 | ||
| 545 | |||
| 546 | 1.2.1 (11/08/2000) greg kroah-hartman | ||
| 547 | - Started to clean up NTisms. | ||
| 548 | - Fixed problem with dev field of urb for kernels >= 2.4.0-test9 | ||
| 549 | |||
| 550 | 1.2 (10/17/2000) David Iacovelli | ||
| 551 | Remove all EPIC code and GPL source | ||
| 552 | Fix RELEVANT_IFLAG macro to include flow control | ||
| 553 | changes port configuration changes. | ||
| 554 | Fix redefinition of SERIAL_MAGIC | ||
| 555 | Change all timeout values to 5 seconds | ||
| 556 | Tried to fix the UHCI multiple urb submission, but failed miserably. | ||
| 557 | it seems to work fine with OHCI. | ||
| 558 | ( Greg take a look at the #if 0 at end of WriteCmdUsb() we must | ||
| 559 | find a way to work arount this UHCI bug ) | ||
| 560 | |||
| 561 | 1.1 (10/11/2000) David Iacovelli | ||
| 562 | Fix XON/XOFF flow control to support both IXON and IXOFF | ||
| 563 | |||
| 564 | 0.9.27 (06/30/2000) David Iacovelli | ||
| 565 | Added transmit queue and now allocate urb for command writes. | ||
| 566 | |||
| 567 | 0.9.26 (06/29/2000) David Iacovelli | ||
| 568 | Add support for 80251 based edgeport | ||
| 569 | |||
| 570 | 0.9.25 (06/27/2000) David Iacovelli | ||
| 571 | Do not close the port if it has multiple opens. | ||
| 572 | |||
| 573 | 0.9.24 (05/26/2000) David Iacovelli | ||
| 574 | Add IOCTLs to support RXTX and JAVA POS | ||
| 575 | and first cut at running BlackBox Demo | ||
| 576 | |||
| 577 | 0.9.23 (05/24/2000) David Iacovelli | ||
| 578 | Add IOCTLs to support RXTX and JAVA POS | ||
| 579 | |||
| 580 | 0.9.22 (05/23/2000) David Iacovelli | ||
| 581 | fixed bug in enumeration. If epconfig turns on mapping by | ||
| 582 | path after a device is already plugged in, we now update | ||
| 583 | the mapping correctly | ||
| 584 | |||
| 585 | 0.9.21 (05/16/2000) David Iacovelli | ||
| 586 | Added BlockUntilChaseResp() to also wait for txcredits | ||
| 587 | Updated the way we allocate and handle write URBs | ||
| 588 | Add debug code to dump buffers | ||
| 589 | |||
| 590 | 0.9.20 (05/01/2000) David Iacovelli | ||
| 591 | change driver to use usb/tts/ | ||
| 592 | |||
| 593 | 0.9.19 (05/01/2000) David Iacovelli | ||
| 594 | Update code to compile if DEBUG is off | ||
| 595 | |||
| 596 | 0.9.18 (04/28/2000) David Iacovelli | ||
| 597 | cleanup and test tty_register with devfs | ||
| 598 | |||
| 599 | 0.9.17 (04/27/2000) greg kroah-hartman | ||
| 600 | changed tty_register around to be like the way it | ||
| 601 | was before, but now it works properly with devfs. | ||
| 602 | |||
| 603 | 0.9.16 (04/26/2000) david iacovelli | ||
| 604 | Fixed bug in GetProductInfo() | ||
| 605 | |||
| 606 | 0.9.15 (04/25/2000) david iacovelli | ||
| 607 | Updated enumeration | ||
| 608 | |||
| 609 | 0.9.14 (04/24/2000) david iacovelli | ||
| 610 | Removed all config/status IOCTLS and | ||
| 611 | converted to using /proc/edgeport | ||
| 612 | still playing with devfs | ||
| 613 | |||
| 614 | 0.9.13 (04/24/2000) david iacovelli | ||
| 615 | Removed configuration based on ttyUSB0 | ||
| 616 | Added support for configuration using /prod/edgeport | ||
| 617 | first attempt at using devfs (not working yet!) | ||
| 618 | Added IOCTL to GetProductInfo() | ||
| 619 | Added support for custom baud rates | ||
| 620 | Add support for random port numbers | ||
| 621 | |||
| 622 | 0.9.12 (04/18/2000) david iacovelli | ||
| 623 | added additional configuration IOCTLs | ||
| 624 | use ttyUSB0 for configuration | ||
| 625 | |||
| 626 | 0.9.11 (04/17/2000) greg kroah-hartman | ||
| 627 | fixed module initialization race conditions. | ||
| 628 | made all urbs dynamically allocated. | ||
| 629 | made driver devfs compatible. now it only registers the tty device | ||
| 630 | when the device is actually plugged in. | ||
| 631 | |||
| 632 | 0.9.10 (04/13/2000) greg kroah-hartman | ||
| 633 | added proc interface framework. | ||
| 634 | |||
| 635 | 0.9.9 (04/13/2000) david iacovelli | ||
| 636 | added enumeration code and ioctls to configure the device | ||
| 637 | |||
| 638 | 0.9.8 (04/12/2000) david iacovelli | ||
| 639 | Change interrupt read start when device is plugged in | ||
| 640 | and stop when device is removed | ||
| 641 | process interrupt reads when all ports are closed | ||
| 642 | (keep value of rxBytesAvail consistent with the edgeport) | ||
| 643 | set the USB_BULK_QUEUE flag so that we can shove a bunch | ||
| 644 | of urbs at once down the pipe | ||
| 645 | |||
| 646 | 0.9.7 (04/10/2000) david iacovelli | ||
| 647 | start to add enumeration code. | ||
| 648 | generate serial number for epic devices | ||
| 649 | add support for kdb | ||
| 650 | |||
| 651 | 0.9.6 (03/30/2000) david iacovelli | ||
| 652 | add IOCTL to get string, manufacture, and boot descriptors | ||
| 653 | |||
| 654 | 0.9.5 (03/14/2000) greg kroah-hartman | ||
| 655 | more error checking added to SerialOpen to try to fix UHCI open problem | ||
| 656 | |||
| 657 | 0.9.4 (03/09/2000) greg kroah-hartman | ||
| 658 | added more error checking to handle oops when data is hanging | ||
| 659 | around and tty is abruptly closed. | ||
| 660 | |||
| 661 | 0.9.3 (03/09/2000) david iacovelli | ||
| 662 | Add epic support for xon/xoff chars | ||
| 663 | play with performance | ||
| 664 | |||
| 665 | 0.9.2 (03/08/2000) greg kroah-hartman | ||
| 666 | changed most "info" calls to "dbg" | ||
| 667 | implemented flow control properly in the termios call | ||
| 668 | |||
| 669 | 0.9.1 (03/08/2000) david iacovelli | ||
| 670 | added EPIC support | ||
| 671 | enabled bootloader update | ||
| 672 | |||
| 673 | 0.9 (03/08/2000) greg kroah-hartman | ||
| 674 | Release to IO networks. | ||
| 675 | Integrated changes that David made | ||
| 676 | made getting urbs for writing SMP safe | ||
| 677 | |||
| 678 | 0.8 (03/07/2000) greg kroah-hartman | ||
| 679 | Release to IO networks. | ||
| 680 | Fixed problems that were seen in code by David. | ||
| 681 | Now both Edgeport/4 and Edgeport/2 works properly. | ||
| 682 | Changed most of the functions to use port instead of serial. | ||
| 683 | |||
| 684 | 0.7 (02/27/2000) greg kroah-hartman | ||
| 685 | Milestone 3 release. | ||
| 686 | Release to IO Networks | ||
| 687 | ioctl for waiting on line change implemented. | ||
| 688 | ioctl for getting statistics implemented. | ||
| 689 | multiport support working. | ||
| 690 | lsr and msr registers are now handled properly. | ||
| 691 | change break now hooked up and working. | ||
| 692 | support for all known Edgeport devices. | ||
| 693 | |||
| 694 | 0.6 (02/22/2000) greg kroah-hartman | ||
| 695 | Release to IO networks. | ||
| 696 | CHASE is implemented correctly when port is closed. | ||
| 697 | SerialOpen now blocks correctly until port is fully opened. | ||
| 698 | |||
| 699 | 0.5 (02/20/2000) greg kroah-hartman | ||
| 700 | Release to IO networks. | ||
| 701 | Known problems: | ||
| 702 | modem status register changes are not sent on to the user | ||
| 703 | CHASE is not implemented when the port is closed. | ||
| 704 | |||
| 705 | 0.4 (02/16/2000) greg kroah-hartman | ||
| 706 | Second cut at the CeBit demo. | ||
| 707 | Doesn't leak memory on every write to the port | ||
| 708 | Still small leaks on startup. | ||
| 709 | Added support for Edgeport/2 and Edgeport/8 | ||
| 710 | |||
| 711 | 0.3 (02/15/2000) greg kroah-hartman | ||
| 712 | CeBit demo release. | ||
| 713 | Force the line settings to 4800, 8, 1, e for the demo. | ||
| 714 | Warning! This version leaks memory like crazy! | ||
| 715 | |||
| 716 | 0.2 (01/30/2000) greg kroah-hartman | ||
| 717 | Milestone 1 release. | ||
| 718 | Device is found by USB subsystem, enumerated, firmware is downloaded | ||
| 719 | and the descriptors are printed to the debug log, config is set, and | ||
| 720 | green light starts to blink. Open port works, and data can be sent | ||
| 721 | and received at the default settings of the UART. Loopback connector | ||
| 722 | and debug log confirms this. | ||
| 723 | |||
| 724 | 0.1 (01/23/2000) greg kroah-hartman | ||
| 725 | Initial release to help IO Networks try to set up their test system. | ||
| 726 | Edgeport4 is recognized, firmware is downloaded, config is set so | ||
| 727 | device blinks green light every 3 sec. Port is bound, but opening, | ||
| 728 | closing, and sending data do not work properly. | ||
| 729 | |||
| 730 | |||
diff --git a/drivers/usb/serial/baseband_usb_chr.c b/drivers/usb/serial/baseband_usb_chr.c new file mode 100644 index 00000000000..6d691a40312 --- /dev/null +++ b/drivers/usb/serial/baseband_usb_chr.c | |||
| @@ -0,0 +1,1124 @@ | |||
| 1 | /* | ||
| 2 | * baseband_usb_chr.c | ||
| 3 | * | ||
| 4 | * USB character driver to communicate with baseband modems. | ||
| 5 | * | ||
| 6 | * Copyright (c) 2011, NVIDIA Corporation. | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
| 14 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 15 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 16 | * more details. | ||
| 17 | * | ||
| 18 | * You should have received a copy of the GNU General Public License along | ||
| 19 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 20 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
| 21 | */ | ||
| 22 | |||
| 23 | #include <linux/types.h> | ||
| 24 | #include <linux/init.h> | ||
| 25 | #include <linux/module.h> | ||
| 26 | #include <linux/moduleparam.h> | ||
| 27 | #include <linux/kernel.h> | ||
| 28 | #include <linux/cdev.h> | ||
| 29 | #include <linux/fs.h> | ||
| 30 | #include <linux/slab.h> | ||
| 31 | #include <linux/delay.h> | ||
| 32 | #include <linux/list.h> | ||
| 33 | #include <linux/errno.h> | ||
| 34 | #include <linux/usb.h> | ||
| 35 | #include <linux/workqueue.h> | ||
| 36 | #include <asm/ioctls.h> | ||
| 37 | #include <linux/uaccess.h> | ||
| 38 | #include "baseband_usb_chr.h" | ||
| 39 | |||
| 40 | MODULE_LICENSE("GPL"); | ||
| 41 | |||
| 42 | unsigned long baseband_usb_chr_vid = 0x058b; | ||
| 43 | unsigned long baseband_usb_chr_pid = 0x0041; | ||
| 44 | unsigned long baseband_usb_chr_intf = 0x01; | ||
| 45 | |||
| 46 | module_param(baseband_usb_chr_vid, ulong, 0644); | ||
| 47 | MODULE_PARM_DESC(baseband_usb_chr_vid, "baseband (usb chr) - USB VID"); | ||
| 48 | module_param(baseband_usb_chr_pid, ulong, 0644); | ||
| 49 | MODULE_PARM_DESC(baseband_usb_chr_pid, "baseband (usb chr) - USB PID"); | ||
| 50 | module_param(baseband_usb_chr_intf, ulong, 0644); | ||
| 51 | MODULE_PARM_DESC(baseband_usb_chr_intf, "baseband (usb chr) - USB interface"); | ||
| 52 | |||
| 53 | static struct baseband_usb *baseband_usb_chr; | ||
| 54 | static bool usb_device_connection; | ||
| 55 | |||
| 56 | static atomic_t g_rx_count = ATOMIC_INIT(0); | ||
| 57 | |||
| 58 | /* baseband ipc functions */ | ||
| 59 | |||
| 60 | static void baseband_ipc_dump(const char *prefix, unsigned long int offset, | ||
| 61 | const void *buf, size_t bufsiz) | ||
| 62 | { | ||
| 63 | size_t i; | ||
| 64 | |||
| 65 | for (i = 0; i < bufsiz; i += 16) { | ||
| 66 | pr_debug("%s" | ||
| 67 | "[%lx+%x] %p " | ||
| 68 | "%02x %02x %02x %02x " | ||
| 69 | "%02x %02x %02x %02x " | ||
| 70 | "%02x %02x %02x %02x " | ||
| 71 | "%02x %02x %02x %02x\n", | ||
| 72 | prefix, | ||
| 73 | offset, | ||
| 74 | i, | ||
| 75 | ((const unsigned char *) buf) + i, | ||
| 76 | (i + 0 < bufsiz) ? ((const unsigned char *) buf)[i+0] | ||
| 77 | : 0xff, | ||
| 78 | (i + 1 < bufsiz) ? ((const unsigned char *) buf)[i+1] | ||
| 79 | : 0xff, | ||
| 80 | (i + 2 < bufsiz) ? ((const unsigned char *) buf)[i+2] | ||
| 81 | : 0xff, | ||
| 82 | (i + 3 < bufsiz) ? ((const unsigned char *) buf)[i+3] | ||
| 83 | : 0xff, | ||
| 84 | (i + 4 < bufsiz) ? ((const unsigned char *) buf)[i+4] | ||
| 85 | : 0xff, | ||
| 86 | (i + 5 < bufsiz) ? ((const unsigned char *) buf)[i+5] | ||
| 87 | : 0xff, | ||
| 88 | (i + 6 < bufsiz) ? ((const unsigned char *) buf)[i+6] | ||
| 89 | : 0xff, | ||
| 90 | (i + 7 < bufsiz) ? ((const unsigned char *) buf)[i+7] | ||
| 91 | : 0xff, | ||
| 92 | (i + 8 < bufsiz) ? ((const unsigned char *) buf)[i+8] | ||
| 93 | : 0xff, | ||
| 94 | (i + 9 < bufsiz) ? ((const unsigned char *) buf)[i+9] | ||
| 95 | : 0xff, | ||
| 96 | (i + 10 < bufsiz) ? ((const unsigned char *) buf)[i+10] | ||
| 97 | : 0xff, | ||
| 98 | (i + 11 < bufsiz) ? ((const unsigned char *) buf)[i+11] | ||
| 99 | : 0xff, | ||
| 100 | (i + 12 < bufsiz) ? ((const unsigned char *) buf)[i+12] | ||
| 101 | : 0xff, | ||
| 102 | (i + 13 < bufsiz) ? ((const unsigned char *) buf)[i+13] | ||
| 103 | : 0xff, | ||
| 104 | (i + 14 < bufsiz) ? ((const unsigned char *) buf)[i+14] | ||
| 105 | : 0xff, | ||
| 106 | (i + 15 < bufsiz) ? ((const unsigned char *) buf)[i+15] | ||
| 107 | : 0xff); | ||
| 108 | } | ||
| 109 | |||
| 110 | } | ||
| 111 | |||
| 112 | static size_t peek_ipc_tx_bufsiz(struct baseband_ipc *ipc, | ||
| 113 | size_t bufsiz) | ||
| 114 | { | ||
| 115 | struct baseband_ipc_buf *ipc_buf, *ipc_buf_next; | ||
| 116 | size_t tx_bufsiz; | ||
| 117 | |||
| 118 | pr_debug("peek_ipc_tx_bufsiz\n"); | ||
| 119 | |||
| 120 | /* check input */ | ||
| 121 | if (!ipc) { | ||
| 122 | pr_err("!ipc\n"); | ||
| 123 | return 0; | ||
| 124 | } | ||
| 125 | |||
| 126 | /* acquire tx buffer semaphores */ | ||
| 127 | if (down_interruptible(&ipc->buf_sem)) { | ||
| 128 | pr_err("peek_ipc_tx_bufsiz - " | ||
| 129 | "cannot acquire buffer semaphore\n"); | ||
| 130 | return -ERESTARTSYS; | ||
| 131 | } | ||
| 132 | |||
| 133 | /* calculate maximum number of tx buffers which can be sent */ | ||
| 134 | tx_bufsiz = 0; | ||
| 135 | list_for_each_entry_safe(ipc_buf, ipc_buf_next, &ipc->tx.buf, list) | ||
| 136 | { | ||
| 137 | pr_debug("peek_ipc_tx_bufsiz - " | ||
| 138 | "ipc_buf %p ipc_buf->offset %x ipc_buf->count %x\n", | ||
| 139 | ipc_buf, ipc_buf->offset, ipc_buf->count); | ||
| 140 | if (ipc_buf->count > bufsiz - tx_bufsiz) | ||
| 141 | break; | ||
| 142 | else | ||
| 143 | tx_bufsiz += ipc_buf->count; | ||
| 144 | } | ||
| 145 | |||
| 146 | /* release tx buffer semaphores */ | ||
| 147 | up(&ipc->buf_sem); | ||
| 148 | |||
| 149 | return tx_bufsiz; | ||
| 150 | } | ||
| 151 | |||
| 152 | static size_t get_ipc_tx_buf(struct baseband_ipc *ipc, | ||
| 153 | void *buf, size_t bufsiz) | ||
| 154 | { | ||
| 155 | struct baseband_ipc_buf *ipc_buf, *ipc_buf_next; | ||
| 156 | size_t tx_bufsiz; | ||
| 157 | |||
| 158 | pr_debug("get_ipc_tx_buf\n"); | ||
| 159 | |||
| 160 | /* check input */ | ||
| 161 | if (!ipc || !buf) { | ||
| 162 | pr_err("!ipc || !buf\n"); | ||
| 163 | return 0; | ||
| 164 | } | ||
| 165 | if (!bufsiz) | ||
| 166 | return 0; | ||
| 167 | |||
| 168 | /* acquire tx buffer semaphores */ | ||
| 169 | if (down_interruptible(&ipc->buf_sem)) { | ||
| 170 | pr_err("get_ipc_tx_buf - " | ||
| 171 | "cannot acquire buffer semaphore\n"); | ||
| 172 | return -ERESTARTSYS; | ||
| 173 | } | ||
| 174 | |||
| 175 | /* get tx data from tx linked list */ | ||
| 176 | tx_bufsiz = 0; | ||
| 177 | list_for_each_entry_safe(ipc_buf, ipc_buf_next, &ipc->tx.buf, list) | ||
| 178 | { | ||
| 179 | pr_debug("get_ipc_tx_buf - " | ||
| 180 | "ipc_buf %p ipc_buf->offset %x ipc_buf->count %x\n", | ||
| 181 | ipc_buf, ipc_buf->offset, ipc_buf->count); | ||
| 182 | pr_debug("get_ipc_tx_buf - " | ||
| 183 | "ipc_buf->data [0] %x [1] %x [2] %x [3] %x\n", | ||
| 184 | ipc_buf->data[0], | ||
| 185 | ipc_buf->data[1], | ||
| 186 | ipc_buf->data[2], | ||
| 187 | ipc_buf->data[3]); | ||
| 188 | if (ipc_buf->count > bufsiz - tx_bufsiz) { | ||
| 189 | /* copy part of tx buffer */ | ||
| 190 | memcpy(buf + tx_bufsiz, | ||
| 191 | ipc_buf->data + ipc_buf->offset, | ||
| 192 | bufsiz - tx_bufsiz); | ||
| 193 | ipc_buf->offset += bufsiz - tx_bufsiz; | ||
| 194 | ipc_buf->count -= bufsiz - tx_bufsiz; | ||
| 195 | tx_bufsiz = bufsiz; | ||
| 196 | } else { | ||
| 197 | /* copy all data from tx buffer */ | ||
| 198 | memcpy(buf + tx_bufsiz, | ||
| 199 | ipc_buf->data + ipc_buf->offset, | ||
| 200 | ipc_buf->count); | ||
| 201 | tx_bufsiz += ipc_buf->count; | ||
| 202 | ipc_buf->offset = 0; | ||
| 203 | ipc_buf->count = 0; | ||
| 204 | /* add tx buffer to tx free list */ | ||
| 205 | list_move_tail(&ipc_buf->list, &ipc->tx_free.buf); | ||
| 206 | wake_up(&ipc->tx_free.wait); | ||
| 207 | } | ||
| 208 | /* check if done */ | ||
| 209 | if (tx_bufsiz == bufsiz) | ||
| 210 | break; | ||
| 211 | } | ||
| 212 | |||
| 213 | /* release tx buffer semaphores */ | ||
| 214 | up(&ipc->buf_sem); | ||
| 215 | |||
| 216 | return tx_bufsiz; | ||
| 217 | } | ||
| 218 | |||
| 219 | static size_t put_ipc_rx_buf(struct baseband_ipc *ipc, | ||
| 220 | const void *buf, size_t bufsiz) | ||
| 221 | { | ||
| 222 | struct baseband_ipc_buf *ipc_buf, *ipc_buf_next; | ||
| 223 | size_t rx_bufsiz; | ||
| 224 | |||
| 225 | pr_debug("put_ipc_rx_buf\n"); | ||
| 226 | |||
| 227 | /* check input */ | ||
| 228 | if (!ipc || !buf) { | ||
| 229 | pr_err("!ipc || !buf\n"); | ||
| 230 | return 0; | ||
| 231 | } | ||
| 232 | if (!bufsiz) | ||
| 233 | return 0; | ||
| 234 | |||
| 235 | /* acquire rx buffer semaphores */ | ||
| 236 | retry: | ||
| 237 | if (down_interruptible(&ipc->buf_sem)) { | ||
| 238 | pr_err("put_ipc_rx_buf - " | ||
| 239 | "cannot acquire buffer semaphore\n"); | ||
| 240 | return -ERESTARTSYS; | ||
| 241 | } | ||
| 242 | |||
| 243 | /* put rx data in rx linked list */ | ||
| 244 | rx_bufsiz = 0; | ||
| 245 | list_for_each_entry_safe(ipc_buf, ipc_buf_next, &ipc->rx_free.buf, list) | ||
| 246 | { | ||
| 247 | pr_debug("put_ipc_rx_buf - " | ||
| 248 | "ipc_buf %p ipc_buf->offset %x ipc_buf->count %x\n", | ||
| 249 | ipc_buf, ipc_buf->offset, ipc_buf->count); | ||
| 250 | if (sizeof(ipc_buf->data) > bufsiz - rx_bufsiz) { | ||
| 251 | /* partially fill rx free buffer */ | ||
| 252 | memcpy(ipc_buf->data, | ||
| 253 | buf + rx_bufsiz, | ||
| 254 | bufsiz - rx_bufsiz); | ||
| 255 | ipc_buf->offset = 0; | ||
| 256 | ipc_buf->count = bufsiz - rx_bufsiz; | ||
| 257 | rx_bufsiz = bufsiz; | ||
| 258 | } else { | ||
| 259 | /* fill entire rx free buffer */ | ||
| 260 | memcpy(ipc_buf->data, | ||
| 261 | buf + rx_bufsiz, | ||
| 262 | sizeof(ipc_buf->data)); | ||
| 263 | ipc_buf->offset = 0; | ||
| 264 | ipc_buf->count = sizeof(ipc_buf->data); | ||
| 265 | rx_bufsiz += sizeof(ipc_buf->data); | ||
| 266 | } | ||
| 267 | /* add filled rx free buffer to rx linked list */ | ||
| 268 | list_move_tail(&ipc_buf->list, &ipc->rx.buf); | ||
| 269 | wake_up(&ipc->rx.wait); | ||
| 270 | /* check if done */ | ||
| 271 | if (rx_bufsiz == bufsiz) | ||
| 272 | break; | ||
| 273 | } | ||
| 274 | |||
| 275 | /* release rx buffer semaphores */ | ||
| 276 | up(&ipc->buf_sem); | ||
| 277 | |||
| 278 | /* wait for rx free buffer available */ | ||
| 279 | if (!rx_bufsiz) { | ||
| 280 | if (wait_event_interruptible(ipc->rx_free.wait, | ||
| 281 | !list_empty(&ipc->rx_free.buf))) { | ||
| 282 | pr_err("put_ipc_rx_buf - " | ||
| 283 | "interrupted wait\n"); | ||
| 284 | return -ERESTARTSYS; | ||
| 285 | } | ||
| 286 | goto retry; | ||
| 287 | } | ||
| 288 | |||
| 289 | return rx_bufsiz; | ||
| 290 | |||
| 291 | } | ||
| 292 | |||
| 293 | static ssize_t baseband_ipc_file_read(struct baseband_ipc *ipc, | ||
| 294 | struct file *file, char *buf, size_t count, loff_t *pos) | ||
| 295 | { | ||
| 296 | struct baseband_ipc_buf *ipc_buf, *ipc_buf_next; | ||
| 297 | size_t read_count; | ||
| 298 | |||
| 299 | pr_debug("baseband_ipc_file_read\n"); | ||
| 300 | |||
| 301 | /* check input */ | ||
| 302 | if (!ipc) { | ||
| 303 | pr_err("!ipc\n"); | ||
| 304 | return -EIO; | ||
| 305 | } | ||
| 306 | |||
| 307 | /* acquire rx buffer semaphores */ | ||
| 308 | retry: | ||
| 309 | if (down_interruptible(&ipc->buf_sem)) { | ||
| 310 | pr_err("baseband_ipc_file_read - " | ||
| 311 | "cannot acquire buffer semaphore\n"); | ||
| 312 | return -ERESTARTSYS; | ||
| 313 | } | ||
| 314 | |||
| 315 | /* get read data from rx linked list */ | ||
| 316 | read_count = 0; | ||
| 317 | list_for_each_entry_safe(ipc_buf, ipc_buf_next, &ipc->rx.buf, list) | ||
| 318 | { | ||
| 319 | pr_debug("baseband_ipc_file_read - " | ||
| 320 | "ipc_buf %p ipc_buf->offset %x ipc_buf->count %x\n", | ||
| 321 | ipc_buf, ipc_buf->offset, ipc_buf->count); | ||
| 322 | pr_debug("baseband_ipc_file_read - " | ||
| 323 | "ipc_buf->data [0] %x [1] %x [2] %x [3] %x\n", | ||
| 324 | ipc_buf->data[0], | ||
| 325 | ipc_buf->data[1], | ||
| 326 | ipc_buf->data[2], | ||
| 327 | ipc_buf->data[3]); | ||
| 328 | if (ipc_buf->count > count - read_count) { | ||
| 329 | /* copy part of rx buffer */ | ||
| 330 | if (copy_to_user(buf + read_count, | ||
| 331 | ipc_buf->data + ipc_buf->offset, | ||
| 332 | count - read_count)) { | ||
| 333 | pr_err("copy_to_user failed\n"); | ||
| 334 | up(&ipc->buf_sem); | ||
| 335 | return -EFAULT; | ||
| 336 | } | ||
| 337 | ipc_buf->offset += count - read_count; | ||
| 338 | ipc_buf->count -= count - read_count; | ||
| 339 | read_count = count; | ||
| 340 | } else { | ||
| 341 | /* copy all data from rx buffer */ | ||
| 342 | if (copy_to_user(buf + read_count, | ||
| 343 | ipc_buf->data + ipc_buf->offset, | ||
| 344 | ipc_buf->count)) { | ||
| 345 | pr_err("copy_to_user failed\n"); | ||
| 346 | up(&ipc->buf_sem); | ||
| 347 | return -EFAULT; | ||
| 348 | } | ||
| 349 | read_count += ipc_buf->count; | ||
| 350 | ipc_buf->offset = 0; | ||
| 351 | ipc_buf->count = 0; | ||
| 352 | /* add rx buffer to rx free list */ | ||
| 353 | list_move_tail(&ipc_buf->list, &ipc->rx_free.buf); | ||
| 354 | wake_up(&ipc->rx_free.wait); | ||
| 355 | } | ||
| 356 | /* check if done */ | ||
| 357 | if (read_count == count) | ||
| 358 | break; | ||
| 359 | } | ||
| 360 | |||
| 361 | /* release rx buffer semaphores */ | ||
| 362 | up(&ipc->buf_sem); | ||
| 363 | |||
| 364 | /* wait for rx buffer available */ | ||
| 365 | if (!read_count) { | ||
| 366 | if (wait_event_interruptible(ipc->rx.wait, | ||
| 367 | !list_empty(&ipc->rx.buf))) { | ||
| 368 | pr_err("baseband_ipc_file_read - " | ||
| 369 | "interrupted wait\n"); | ||
| 370 | return -ERESTARTSYS; | ||
| 371 | } | ||
| 372 | goto retry; | ||
| 373 | } | ||
| 374 | |||
| 375 | return read_count; | ||
| 376 | } | ||
| 377 | |||
| 378 | static ssize_t baseband_ipc_file_write(struct baseband_ipc *ipc, | ||
| 379 | struct file *file, const char *buf, size_t count, loff_t *pos) | ||
| 380 | { | ||
| 381 | struct baseband_ipc_buf *ipc_buf, *ipc_buf_next; | ||
| 382 | size_t write_count; | ||
| 383 | |||
| 384 | pr_debug("baseband_ipc_file_write\n"); | ||
| 385 | |||
| 386 | /* check input */ | ||
| 387 | if (!ipc) { | ||
| 388 | pr_err("!ipc\n"); | ||
| 389 | return -EIO; | ||
| 390 | } | ||
| 391 | |||
| 392 | /* acquire tx buffer semaphores */ | ||
| 393 | retry: | ||
| 394 | if (down_interruptible(&ipc->buf_sem)) { | ||
| 395 | pr_err("baseband_ipc_file_write - " | ||
| 396 | "cannot acquire buffer semaphore\n"); | ||
| 397 | return -ERESTARTSYS; | ||
| 398 | } | ||
| 399 | |||
| 400 | /* put write data in tx linked list */ | ||
| 401 | write_count = 0; | ||
| 402 | list_for_each_entry_safe(ipc_buf, ipc_buf_next, &ipc->tx_free.buf, list) | ||
| 403 | { | ||
| 404 | pr_debug("baseband_ipc_file_write - " | ||
| 405 | "ipc_buf %p ipc_buf->offset %x ipc_buf->count %x\n", | ||
| 406 | ipc_buf, ipc_buf->offset, ipc_buf->count); | ||
| 407 | if (sizeof(ipc_buf->data) > count - write_count) { | ||
| 408 | /* partially fill tx free buffer */ | ||
| 409 | if (copy_from_user(ipc_buf->data, | ||
| 410 | buf + write_count, | ||
| 411 | count - write_count)) { | ||
| 412 | pr_err("copy_from_user failed\n"); | ||
| 413 | up(&ipc->buf_sem); | ||
| 414 | return -EFAULT; | ||
| 415 | } | ||
| 416 | ipc_buf->offset = 0; | ||
| 417 | ipc_buf->count = count - write_count; | ||
| 418 | write_count = count; | ||
| 419 | } else { | ||
| 420 | /* fill entire tx free buffer */ | ||
| 421 | if (copy_from_user(ipc_buf->data, | ||
| 422 | buf + write_count, | ||
| 423 | sizeof(ipc_buf->data))) { | ||
| 424 | pr_err("copy_from_user failed\n"); | ||
| 425 | up(&ipc->buf_sem); | ||
| 426 | return -EFAULT; | ||
| 427 | } | ||
| 428 | ipc_buf->offset = 0; | ||
| 429 | ipc_buf->count = sizeof(ipc_buf->data); | ||
| 430 | write_count += sizeof(ipc_buf->data); | ||
| 431 | } | ||
| 432 | /* add filled tx free buffer to tx linked list */ | ||
| 433 | pr_debug("baseband_ipc_file_write - " | ||
| 434 | "ipc_buf->data [0] %x [1] %x [2] %x [3] %x\n", | ||
| 435 | ipc_buf->data[0], | ||
| 436 | ipc_buf->data[1], | ||
| 437 | ipc_buf->data[2], | ||
| 438 | ipc_buf->data[3]); | ||
| 439 | list_move_tail(&ipc_buf->list, &ipc->tx.buf); | ||
| 440 | wake_up(&ipc->tx.wait); | ||
| 441 | /* check if done */ | ||
| 442 | if (write_count == count) | ||
| 443 | break; | ||
| 444 | } | ||
| 445 | |||
| 446 | /* release tx buffer semaphores */ | ||
| 447 | up(&ipc->buf_sem); | ||
| 448 | |||
| 449 | /* wait for tx buffer available */ | ||
| 450 | if (!write_count) { | ||
| 451 | if (wait_event_interruptible(ipc->tx_free.wait, | ||
| 452 | !list_empty(&ipc->tx_free.buf))) { | ||
| 453 | pr_err("baseband_ipc_file_write - " | ||
| 454 | "interrupted wait\n"); | ||
| 455 | return -ERESTARTSYS; | ||
| 456 | } | ||
| 457 | goto retry; | ||
| 458 | } | ||
| 459 | |||
| 460 | /* queue ipc transaction work */ | ||
| 461 | queue_work(ipc->workqueue, &ipc->work); | ||
| 462 | |||
| 463 | return write_count; | ||
| 464 | } | ||
| 465 | |||
| 466 | static void baseband_ipc_close(struct baseband_ipc *ipc) | ||
| 467 | { | ||
| 468 | struct baseband_ipc_buf *ipc_buf, *ipc_buf_next; | ||
| 469 | |||
| 470 | pr_debug("baseband_ipc_close {\n"); | ||
| 471 | |||
| 472 | /* check input */ | ||
| 473 | if (!ipc) | ||
| 474 | return; | ||
| 475 | |||
| 476 | /* destroy work queue */ | ||
| 477 | if (ipc->workqueue) { | ||
| 478 | pr_debug("destroy workqueue {\n"); | ||
| 479 | cancel_work_sync(&ipc->work); | ||
| 480 | destroy_workqueue(ipc->workqueue); | ||
| 481 | ipc->workqueue = (struct workqueue_struct *) 0; | ||
| 482 | pr_debug("destroy workqueue }\n"); | ||
| 483 | } | ||
| 484 | memset(&ipc->work, 0, sizeof(ipc->work)); | ||
| 485 | |||
| 486 | /* destroy wait queues */ | ||
| 487 | memset(&ipc->tx_free.wait, 0, sizeof(ipc->tx_free.wait)); | ||
| 488 | memset(&ipc->rx_free.wait, 0, sizeof(ipc->rx_free.wait)); | ||
| 489 | memset(&ipc->tx.wait, 0, sizeof(ipc->tx.wait)); | ||
| 490 | memset(&ipc->rx.wait, 0, sizeof(ipc->rx.wait)); | ||
| 491 | |||
| 492 | /* destroy data buffers */ | ||
| 493 | kfree(ipc->ipc_tx); | ||
| 494 | ipc->ipc_tx = (unsigned char *) 0; | ||
| 495 | kfree(ipc->ipc_rx); | ||
| 496 | ipc->ipc_rx = (unsigned char *) 0; | ||
| 497 | list_for_each_entry_safe(ipc_buf, ipc_buf_next, &ipc->tx_free.buf, list) | ||
| 498 | { | ||
| 499 | kfree(ipc_buf); | ||
| 500 | } | ||
| 501 | list_for_each_entry_safe(ipc_buf, ipc_buf_next, &ipc->rx_free.buf, list) | ||
| 502 | { | ||
| 503 | kfree(ipc_buf); | ||
| 504 | } | ||
| 505 | list_for_each_entry_safe(ipc_buf, ipc_buf_next, &ipc->tx.buf, list) | ||
| 506 | { | ||
| 507 | kfree(ipc_buf); | ||
| 508 | } | ||
| 509 | list_for_each_entry_safe(ipc_buf, ipc_buf_next, &ipc->rx.buf, list) | ||
| 510 | { | ||
| 511 | kfree(ipc_buf); | ||
| 512 | } | ||
| 513 | |||
| 514 | /* destroy semaphores */ | ||
| 515 | memset(&ipc->buf_sem, 0, sizeof(ipc->buf_sem)); | ||
| 516 | |||
| 517 | /* free baseband ipc structure */ | ||
| 518 | kfree(ipc); | ||
| 519 | |||
| 520 | pr_debug("baseband_ipc_close }\n"); | ||
| 521 | } | ||
| 522 | |||
| 523 | static struct baseband_ipc *baseband_ipc_open(work_func_t work_func, | ||
| 524 | work_func_t rx_work_func, | ||
| 525 | work_func_t tx_work_func) | ||
| 526 | { | ||
| 527 | struct baseband_ipc *ipc; | ||
| 528 | struct baseband_ipc_buf *ipc_buf; | ||
| 529 | int i; | ||
| 530 | |||
| 531 | pr_debug("baseband_ipc_open {\n"); | ||
| 532 | |||
| 533 | /* allocate baseband ipc structure */ | ||
| 534 | ipc = kzalloc(sizeof(struct baseband_ipc), GFP_KERNEL); | ||
| 535 | if (!ipc) | ||
| 536 | return (struct baseband_ipc *) 0; | ||
| 537 | |||
| 538 | /* create semaphores */ | ||
| 539 | sema_init(&ipc->buf_sem, 1); | ||
| 540 | |||
| 541 | /* create data buffers */ | ||
| 542 | INIT_LIST_HEAD(&ipc->rx.buf); | ||
| 543 | INIT_LIST_HEAD(&ipc->tx.buf); | ||
| 544 | INIT_LIST_HEAD(&ipc->rx_free.buf); | ||
| 545 | INIT_LIST_HEAD(&ipc->tx_free.buf); | ||
| 546 | for (i = 0; i < BASEBAND_IPC_NUM_RX_BUF; i++) { | ||
| 547 | ipc_buf = (struct baseband_ipc_buf *) | ||
| 548 | kzalloc(sizeof(struct baseband_ipc_buf), GFP_KERNEL); | ||
| 549 | if (!ipc_buf) { | ||
| 550 | pr_err("cannot allocate baseband ipc rx buffer #%d\n", | ||
| 551 | i); | ||
| 552 | goto error_exit; | ||
| 553 | } | ||
| 554 | pr_debug("baseband_ipc_open - " | ||
| 555 | "rx_free: ipc_buf %p\n", | ||
| 556 | ipc_buf); | ||
| 557 | list_add_tail(&ipc_buf->list, &ipc->rx_free.buf); | ||
| 558 | } | ||
| 559 | for (i = 0; i < BASEBAND_IPC_NUM_TX_BUF; i++) { | ||
| 560 | ipc_buf = (struct baseband_ipc_buf *) | ||
| 561 | kzalloc(sizeof(struct baseband_ipc_buf), GFP_KERNEL); | ||
| 562 | if (!ipc_buf) { | ||
| 563 | pr_err("cannot allocate baseband ipc tx buffer #%d\n", | ||
| 564 | i); | ||
| 565 | goto error_exit; | ||
| 566 | } | ||
| 567 | pr_debug("baseband_ipc_open - " | ||
| 568 | "tx_free: ipc_buf %p\n", | ||
| 569 | ipc_buf); | ||
| 570 | list_add_tail(&ipc_buf->list, &ipc->tx_free.buf); | ||
| 571 | } | ||
| 572 | ipc->ipc_rx = (unsigned char *) 0; | ||
| 573 | ipc->ipc_tx = (unsigned char *) 0; | ||
| 574 | |||
| 575 | /* create wait queues */ | ||
| 576 | init_waitqueue_head(&ipc->rx.wait); | ||
| 577 | init_waitqueue_head(&ipc->tx.wait); | ||
| 578 | init_waitqueue_head(&ipc->rx_free.wait); | ||
| 579 | init_waitqueue_head(&ipc->tx_free.wait); | ||
| 580 | |||
| 581 | /* create work queue */ | ||
| 582 | ipc->workqueue = create_singlethread_workqueue | ||
| 583 | ("baseband_usb_chr_ipc_workqueue"); | ||
| 584 | if (!ipc->workqueue) { | ||
| 585 | pr_err("cannot create workqueue\n"); | ||
| 586 | goto error_exit; | ||
| 587 | } | ||
| 588 | if (work_func) | ||
| 589 | INIT_WORK(&ipc->work, work_func); | ||
| 590 | if (rx_work_func) | ||
| 591 | INIT_WORK(&ipc->rx_work, rx_work_func); | ||
| 592 | if (tx_work_func) | ||
| 593 | INIT_WORK(&ipc->tx_work, tx_work_func); | ||
| 594 | |||
| 595 | pr_debug("baseband_ipc_open }\n"); | ||
| 596 | return ipc; | ||
| 597 | |||
| 598 | error_exit: | ||
| 599 | baseband_ipc_close(ipc); | ||
| 600 | return (struct baseband_ipc *) 0; | ||
| 601 | } | ||
| 602 | |||
| 603 | /* usb rx */ | ||
| 604 | |||
| 605 | static void baseband_usb_chr_rx_urb_comp(struct urb *urb) | ||
| 606 | { | ||
| 607 | struct baseband_usb *usb = (struct baseband_usb *) urb->context; | ||
| 608 | |||
| 609 | pr_debug("baseband_usb_chr_rx_urb_comp { urb %p\n", urb); | ||
| 610 | |||
| 611 | /* queue rx urb completion work */ | ||
| 612 | queue_work(usb->ipc->workqueue, &usb->ipc->rx_work); | ||
| 613 | |||
| 614 | pr_debug("baseband_usb_chr_rx_urb_comp }\n"); | ||
| 615 | } | ||
| 616 | |||
| 617 | static int baseband_usb_chr_rx_urb_submit(struct baseband_usb *usb) | ||
| 618 | { | ||
| 619 | struct urb *urb; | ||
| 620 | void *buf; | ||
| 621 | int err; | ||
| 622 | |||
| 623 | pr_debug("baseband_usb_chr_rx_urb_submit { usb %p\n", usb); | ||
| 624 | |||
| 625 | if (!usb_device_connection) { | ||
| 626 | pr_err("!!no usb device conenction!!!!!\n"); | ||
| 627 | return -1; | ||
| 628 | } | ||
| 629 | |||
| 630 | /* check input */ | ||
| 631 | if (usb->usb.rx_urb) { | ||
| 632 | pr_err("previous urb still active\n"); | ||
| 633 | return -1; | ||
| 634 | } | ||
| 635 | |||
| 636 | /* allocate rx urb */ | ||
| 637 | urb = usb_alloc_urb(0, GFP_ATOMIC); | ||
| 638 | if (!urb) { | ||
| 639 | pr_err("usb_alloc_urb() failed\n"); | ||
| 640 | return -ENOMEM; | ||
| 641 | } | ||
| 642 | buf = kzalloc(USB_CHR_RX_BUFSIZ, GFP_ATOMIC); | ||
| 643 | if (!buf) { | ||
| 644 | pr_err("usb buffer kzalloc() failed\n"); | ||
| 645 | usb_free_urb(urb); | ||
| 646 | return -ENOMEM; | ||
| 647 | } | ||
| 648 | usb_fill_bulk_urb(urb, usb->usb.device, usb->usb.pipe.bulk.in, | ||
| 649 | buf, USB_CHR_RX_BUFSIZ, | ||
| 650 | baseband_usb_chr_rx_urb_comp, | ||
| 651 | usb); | ||
| 652 | urb->transfer_flags = 0; | ||
| 653 | |||
| 654 | /* submit rx urb */ | ||
| 655 | usb->usb.rx_urb = urb; | ||
| 656 | err = usb_submit_urb(urb, GFP_ATOMIC); | ||
| 657 | if (err < 0) { | ||
| 658 | pr_err("usb_submit_urb() failed - err %d\n", err); | ||
| 659 | usb->usb.rx_urb = (struct urb *) 0; | ||
| 660 | kfree(urb->transfer_buffer); | ||
| 661 | usb_free_urb(urb); | ||
| 662 | return err; | ||
| 663 | } | ||
| 664 | |||
| 665 | pr_debug("baseband_usb_chr_rx_urb_submit }\n"); | ||
| 666 | return err; | ||
| 667 | } | ||
| 668 | |||
| 669 | static void baseband_usb_chr_rx_urb_comp_work(struct work_struct *work) | ||
| 670 | { | ||
| 671 | struct baseband_usb *usb = baseband_usb_chr; | ||
| 672 | struct urb *urb = usb->usb.rx_urb; | ||
| 673 | size_t len; | ||
| 674 | |||
| 675 | pr_debug("baseband_usb_chr_rx_urb_comp_work { work %p\n", work); | ||
| 676 | |||
| 677 | /* put rx urb data in rx buffer */ | ||
| 678 | if (urb->actual_length) { | ||
| 679 | pr_debug("baseband_usb_chr_rx_urb_comp_work - " | ||
| 680 | "urb->actual_length %d\n", urb->actual_length); | ||
| 681 | len = put_ipc_rx_buf(usb->ipc, | ||
| 682 | urb->transfer_buffer, urb->actual_length); | ||
| 683 | baseband_ipc_dump("baseband_usb_chr_rx_urb_comp_work" | ||
| 684 | " - rx buf ", 0, | ||
| 685 | urb->transfer_buffer, len > 16 ? 16 : len); | ||
| 686 | if (len != urb->actual_length) { | ||
| 687 | pr_err("baseband_usb_chr_rx_urb_comp_work - " | ||
| 688 | "put_ipx_rx_buf() only put %d/%d bytes\n", | ||
| 689 | len, urb->actual_length); | ||
| 690 | } | ||
| 691 | /* increment count of available rx bytes */ | ||
| 692 | atomic_add(len, &g_rx_count); | ||
| 693 | } | ||
| 694 | |||
| 695 | /* free rx urb */ | ||
| 696 | kfree(urb->transfer_buffer); | ||
| 697 | urb->transfer_buffer = (void *) 0; | ||
| 698 | usb_free_urb(urb); | ||
| 699 | usb->usb.rx_urb = (struct urb *) 0; | ||
| 700 | |||
| 701 | /* submit next rx urb */ | ||
| 702 | baseband_usb_chr_rx_urb_submit(usb); | ||
| 703 | |||
| 704 | pr_debug("baseband_usb_chr_rx_urb_comp_work }\n"); | ||
| 705 | } | ||
| 706 | |||
| 707 | /* usb functions */ | ||
| 708 | |||
| 709 | static void find_usb_pipe(struct baseband_usb *usb) | ||
| 710 | { | ||
| 711 | struct usb_device *usbdev = usb->usb.device; | ||
| 712 | struct usb_interface *intf = usb->usb.interface; | ||
| 713 | unsigned char numendpoint = intf->cur_altsetting->desc.bNumEndpoints; | ||
| 714 | struct usb_host_endpoint *endpoint = intf->cur_altsetting->endpoint; | ||
| 715 | unsigned char n; | ||
| 716 | |||
| 717 | for (n = 0; n < numendpoint; n++) { | ||
| 718 | if (usb_endpoint_is_isoc_in(&endpoint[n].desc)) { | ||
| 719 | pr_debug("endpoint[%d] isochronous in\n", n); | ||
| 720 | usb->usb.pipe.isoch.in = usb_rcvisocpipe(usbdev, | ||
| 721 | endpoint[n].desc.bEndpointAddress); | ||
| 722 | } else if (usb_endpoint_is_isoc_out(&endpoint[n].desc)) { | ||
| 723 | pr_debug("endpoint[%d] isochronous out\n", n); | ||
| 724 | usb->usb.pipe.isoch.out = usb_sndisocpipe(usbdev, | ||
| 725 | endpoint[n].desc.bEndpointAddress); | ||
| 726 | } else if (usb_endpoint_is_bulk_in(&endpoint[n].desc)) { | ||
| 727 | pr_debug("endpoint[%d] bulk in\n", n); | ||
| 728 | usb->usb.pipe.bulk.in = usb_rcvbulkpipe(usbdev, | ||
| 729 | endpoint[n].desc.bEndpointAddress); | ||
| 730 | } else if (usb_endpoint_is_bulk_out(&endpoint[n].desc)) { | ||
| 731 | pr_debug("endpoint[%d] bulk out\n", n); | ||
| 732 | usb->usb.pipe.bulk.out = usb_sndbulkpipe(usbdev, | ||
| 733 | endpoint[n].desc.bEndpointAddress); | ||
| 734 | } else if (usb_endpoint_is_int_in(&endpoint[n].desc)) { | ||
| 735 | pr_debug("endpoint[%d] interrupt in\n", n); | ||
| 736 | usb->usb.pipe.interrupt.in = usb_rcvintpipe(usbdev, | ||
| 737 | endpoint[n].desc.bEndpointAddress); | ||
| 738 | } else if (usb_endpoint_is_int_out(&endpoint[n].desc)) { | ||
| 739 | pr_debug("endpoint[%d] interrupt out\n", n); | ||
| 740 | usb->usb.pipe.interrupt.out = usb_sndintpipe(usbdev, | ||
| 741 | endpoint[n].desc.bEndpointAddress); | ||
| 742 | } else { | ||
| 743 | pr_debug("endpoint[%d] skipped\n", n); | ||
| 744 | } | ||
| 745 | } | ||
| 746 | } | ||
| 747 | |||
| 748 | static int baseband_usb_driver_probe(struct usb_interface *intf, | ||
| 749 | const struct usb_device_id *id) | ||
| 750 | { | ||
| 751 | int err; | ||
| 752 | |||
| 753 | pr_debug("%s(%d) { intf %p id %p\n", __func__, __LINE__, intf, id); | ||
| 754 | |||
| 755 | pr_debug("intf->cur_altsetting->desc.bInterfaceNumber %02x\n", | ||
| 756 | intf->cur_altsetting->desc.bInterfaceNumber); | ||
| 757 | pr_debug("intf->cur_altsetting->desc.bAlternateSetting %02x\n", | ||
| 758 | intf->cur_altsetting->desc.bAlternateSetting); | ||
| 759 | pr_debug("intf->cur_altsetting->desc.bNumEndpoints %02x\n", | ||
| 760 | intf->cur_altsetting->desc.bNumEndpoints); | ||
| 761 | pr_debug("intf->cur_altsetting->desc.bInterfaceClass %02x\n", | ||
| 762 | intf->cur_altsetting->desc.bInterfaceClass); | ||
| 763 | pr_debug("intf->cur_altsetting->desc.bInterfaceSubClass %02x\n", | ||
| 764 | intf->cur_altsetting->desc.bInterfaceSubClass); | ||
| 765 | pr_debug("intf->cur_altsetting->desc.bInterfaceProtocol %02x\n", | ||
| 766 | intf->cur_altsetting->desc.bInterfaceProtocol); | ||
| 767 | pr_debug("intf->cur_altsetting->desc.iInterface %02x\n", | ||
| 768 | intf->cur_altsetting->desc.iInterface); | ||
| 769 | |||
| 770 | /* usb interface mismatch */ | ||
| 771 | if (baseband_usb_chr_intf != | ||
| 772 | intf->cur_altsetting->desc.bInterfaceNumber) { | ||
| 773 | pr_debug("%s(%d) } -ENODEV\n", __func__, __LINE__); | ||
| 774 | return -ENODEV; | ||
| 775 | } | ||
| 776 | |||
| 777 | /* usb interface match */ | ||
| 778 | baseband_usb_chr->usb.device = interface_to_usbdev(intf); | ||
| 779 | baseband_usb_chr->usb.interface = intf; | ||
| 780 | find_usb_pipe(baseband_usb_chr); | ||
| 781 | baseband_usb_chr->usb.rx_urb = (struct urb *) 0; | ||
| 782 | baseband_usb_chr->usb.tx_urb = (struct urb *) 0; | ||
| 783 | pr_debug("baseband_usb_chr->usb.driver->name %s\n", | ||
| 784 | baseband_usb_chr->usb.driver->name); | ||
| 785 | pr_debug("baseband_usb_chr->usb.device %p\n", | ||
| 786 | baseband_usb_chr->usb.device); | ||
| 787 | pr_debug("baseband_usb_chr->usb.interface %p\n", | ||
| 788 | baseband_usb_chr->usb.interface); | ||
| 789 | pr_debug("baseband_usb_chr->usb.pipe.isoch.in %x\n", | ||
| 790 | baseband_usb_chr->usb.pipe.isoch.in); | ||
| 791 | pr_debug("baseband_usb_chr->usb.pipe.isoch.out %x\n", | ||
| 792 | baseband_usb_chr->usb.pipe.isoch.out); | ||
| 793 | pr_debug("baseband_usb_chr->usb.pipe.bulk.in %x\n", | ||
| 794 | baseband_usb_chr->usb.pipe.bulk.in); | ||
| 795 | pr_debug("baseband_usb_chr->usb.pipe.bulk.out %x\n", | ||
| 796 | baseband_usb_chr->usb.pipe.bulk.out); | ||
| 797 | pr_debug("baseband_usb_chr->usb.pipe.interrupt.in %x\n", | ||
| 798 | baseband_usb_chr->usb.pipe.interrupt.in); | ||
| 799 | pr_debug("baseband_usb_chr->usb.pipe.interrupt.out %x\n", | ||
| 800 | baseband_usb_chr->usb.pipe.interrupt.out); | ||
| 801 | usb_device_connection = true; | ||
| 802 | |||
| 803 | /* start usb rx */ | ||
| 804 | err = baseband_usb_chr_rx_urb_submit(baseband_usb_chr); | ||
| 805 | if (err < 0) { | ||
| 806 | pr_err("submit rx failed - err %d\n", err); | ||
| 807 | return -ENODEV; | ||
| 808 | } | ||
| 809 | |||
| 810 | pr_debug("%s(%d) }\n", __func__, __LINE__); | ||
| 811 | return 0; | ||
| 812 | } | ||
| 813 | |||
| 814 | static void baseband_usb_driver_disconnect(struct usb_interface *intf) | ||
| 815 | { | ||
| 816 | struct usb_device *usb_dev = interface_to_usbdev(intf); | ||
| 817 | pr_debug("%s(%d) { intf %p\n", __func__, __LINE__, intf); | ||
| 818 | pr_debug("%s(%d) }\n", __func__, __LINE__); | ||
| 819 | if (baseband_usb_chr->usb.interface != intf) { | ||
| 820 | pr_info("%s(%d) -ENODEV\n", __func__, __LINE__); | ||
| 821 | return; | ||
| 822 | } | ||
| 823 | if (baseband_usb_chr->usb.device == usb_dev) { | ||
| 824 | pr_info("%s: Matching usb device: Flush workqueue\n", __func__); | ||
| 825 | flush_workqueue(baseband_usb_chr->ipc->workqueue); | ||
| 826 | usb_device_connection = false; | ||
| 827 | } | ||
| 828 | |||
| 829 | } | ||
| 830 | |||
| 831 | static char baseband_usb_driver_name[32]; | ||
| 832 | |||
| 833 | static struct usb_device_id baseband_usb_driver_id_table[2]; | ||
| 834 | |||
| 835 | static struct usb_driver baseband_usb_driver = { | ||
| 836 | .name = baseband_usb_driver_name, | ||
| 837 | .probe = baseband_usb_driver_probe, | ||
| 838 | .disconnect = baseband_usb_driver_disconnect, | ||
| 839 | .id_table = baseband_usb_driver_id_table, | ||
| 840 | }; | ||
| 841 | |||
| 842 | static void baseband_usb_chr_work(struct work_struct *work) | ||
| 843 | { | ||
| 844 | struct baseband_usb *usb = baseband_usb_chr; | ||
| 845 | struct { | ||
| 846 | unsigned char *buf; | ||
| 847 | unsigned int bufsiz_byte; | ||
| 848 | } rx, tx; | ||
| 849 | int ipc_tx_byte; | ||
| 850 | int err; | ||
| 851 | |||
| 852 | pr_debug("baseband_usb_chr_work {\n"); | ||
| 853 | |||
| 854 | /* check input */ | ||
| 855 | if (!usb || !usb->ipc) { | ||
| 856 | pr_err("baseband_usb_chr_work - " | ||
| 857 | "usb not open\n"); | ||
| 858 | return; | ||
| 859 | } | ||
| 860 | if (!usb->usb.device) { | ||
| 861 | pr_err("baseband_usb_chr_work - " | ||
| 862 | "usb device not probed yet\n"); | ||
| 863 | mdelay(10); | ||
| 864 | queue_work(usb->ipc->workqueue, &usb->ipc->work); | ||
| 865 | return; | ||
| 866 | } | ||
| 867 | |||
| 868 | /* allocate buffers on first transaction (will be freed on close) */ | ||
| 869 | if (!usb->ipc->ipc_rx) { | ||
| 870 | usb->ipc->ipc_rx = kzalloc(USB_CHR_RX_BUFSIZ, GFP_KERNEL); | ||
| 871 | if (!usb->ipc->ipc_rx) { | ||
| 872 | pr_err("baseband_usb_chr_work - " | ||
| 873 | "cannot allocate usb->ipc->ipc_rx\n"); | ||
| 874 | return; | ||
| 875 | } | ||
| 876 | } | ||
| 877 | if (!usb->ipc->ipc_tx) { | ||
| 878 | usb->ipc->ipc_tx = kzalloc(USB_CHR_TX_BUFSIZ, GFP_KERNEL); | ||
| 879 | if (!usb->ipc->ipc_tx) { | ||
| 880 | pr_err("baseband_usb_chr_work - " | ||
| 881 | "cannot allocate usb->ipc->ipc_tx\n"); | ||
| 882 | return; | ||
| 883 | } | ||
| 884 | } | ||
| 885 | |||
| 886 | /* usb transaction loop */ | ||
| 887 | rx.buf = usb->ipc->ipc_rx; | ||
| 888 | tx.buf = usb->ipc->ipc_tx; | ||
| 889 | while ((tx.bufsiz_byte = peek_ipc_tx_bufsiz(usb->ipc, | ||
| 890 | USB_CHR_TX_BUFSIZ)) != 0) { | ||
| 891 | get_ipc_tx_buf(usb->ipc, tx.buf, tx.bufsiz_byte); | ||
| 892 | err = usb_bulk_msg(usb->usb.device, usb->usb.pipe.bulk.out, | ||
| 893 | tx.buf, tx.bufsiz_byte, &ipc_tx_byte, USB_CHR_TIMEOUT); | ||
| 894 | if (err < 0) { | ||
| 895 | pr_err("baseband_usb_chr_work - " | ||
| 896 | "usb_bulk_msg err %d\n", err); | ||
| 897 | continue; | ||
| 898 | } | ||
| 899 | if (tx.bufsiz_byte != ipc_tx_byte) { | ||
| 900 | pr_err("tx.bufsiz_byte %d != ipc_tx_byte %d\n", | ||
| 901 | tx.bufsiz_byte, ipc_tx_byte); | ||
| 902 | continue; | ||
| 903 | } | ||
| 904 | } | ||
| 905 | |||
| 906 | pr_debug("baseband_usb_chr_work }\n"); | ||
| 907 | } | ||
| 908 | |||
| 909 | /* usb character file operations */ | ||
| 910 | |||
| 911 | static int baseband_usb_chr_open(struct inode *inode, struct file *file) | ||
| 912 | { | ||
| 913 | pr_debug("baseband_usb_chr_open\n"); | ||
| 914 | return 0; | ||
| 915 | } | ||
| 916 | |||
| 917 | static int baseband_usb_chr_release(struct inode *inode, struct file *file) | ||
| 918 | { | ||
| 919 | pr_debug("baseband_usb_chr_release\n"); | ||
| 920 | return 0; | ||
| 921 | } | ||
| 922 | |||
| 923 | static ssize_t baseband_usb_chr_read(struct file *file, char *buf, | ||
| 924 | size_t count, loff_t *pos) | ||
| 925 | { | ||
| 926 | ssize_t ret; | ||
| 927 | |||
| 928 | pr_debug("baseband_usb_chr_read\n"); | ||
| 929 | |||
| 930 | ret = baseband_ipc_file_read(baseband_usb_chr->ipc, | ||
| 931 | file, buf, count, pos); | ||
| 932 | if (ret > 0) { | ||
| 933 | /* decrement count of available rx bytes */ | ||
| 934 | int val = atomic_read(&g_rx_count); | ||
| 935 | pr_debug("baseband_usb_chr_read - read %d unread %d\n", | ||
| 936 | ret, val - ret); | ||
| 937 | atomic_sub(ret, &g_rx_count); | ||
| 938 | } | ||
| 939 | return ret; | ||
| 940 | } | ||
| 941 | |||
| 942 | static ssize_t baseband_usb_chr_write(struct file *file, const char *buf, | ||
| 943 | size_t count, loff_t *pos) | ||
| 944 | { | ||
| 945 | pr_debug("baseband_usb_chr_write\n"); | ||
| 946 | return baseband_ipc_file_write(baseband_usb_chr->ipc, | ||
| 947 | file, buf, count, pos); | ||
| 948 | } | ||
| 949 | |||
| 950 | static long baseband_usb_chr_ioctl(struct file *file, unsigned int cmd, | ||
| 951 | unsigned long arg) | ||
| 952 | { | ||
| 953 | pr_debug("baseband_usb_chr_ioctl\n"); | ||
| 954 | switch (cmd) { | ||
| 955 | case TCFLSH: | ||
| 956 | pr_debug("TCFLSH\n"); | ||
| 957 | /* flush queued ipc transaction work */ | ||
| 958 | flush_workqueue(baseband_usb_chr->ipc->workqueue); | ||
| 959 | return 0; | ||
| 960 | case FIONREAD: | ||
| 961 | pr_debug("FIONREAD\n"); | ||
| 962 | /* return count of available rx bytes */ | ||
| 963 | { | ||
| 964 | int __user *p = (int __user *) arg; | ||
| 965 | int val = atomic_read(&g_rx_count); | ||
| 966 | if (put_user(val, p)) | ||
| 967 | break; | ||
| 968 | } | ||
| 969 | return 0; | ||
| 970 | default: | ||
| 971 | pr_err("unsupported ioctl cmd %x\n", cmd); | ||
| 972 | } | ||
| 973 | return -ENODEV; | ||
| 974 | } | ||
| 975 | |||
| 976 | static const struct file_operations baseband_usb_chr_fops = { | ||
| 977 | .open = baseband_usb_chr_open, | ||
| 978 | .release = baseband_usb_chr_release, | ||
| 979 | .read = baseband_usb_chr_read, | ||
| 980 | .write = baseband_usb_chr_write, | ||
| 981 | .unlocked_ioctl = baseband_usb_chr_ioctl, | ||
| 982 | }; | ||
| 983 | |||
| 984 | /* usb device driver functions */ | ||
| 985 | |||
| 986 | static void baseband_usb_close(struct baseband_usb *usb) | ||
| 987 | { | ||
| 988 | pr_debug("baseband_usb_close {\n"); | ||
| 989 | |||
| 990 | /* check input */ | ||
| 991 | if (!usb) | ||
| 992 | return; | ||
| 993 | |||
| 994 | /* close usb driver */ | ||
| 995 | if (usb->usb.driver) { | ||
| 996 | pr_debug("close usb driver {\n"); | ||
| 997 | usb_deregister(usb->usb.driver); | ||
| 998 | usb->usb.driver = (struct usb_driver *) 0; | ||
| 999 | pr_debug("close usb driver }\n"); | ||
| 1000 | } | ||
| 1001 | |||
| 1002 | /* close baseband ipc */ | ||
| 1003 | if (usb->ipc) { | ||
| 1004 | baseband_ipc_close(usb->ipc); | ||
| 1005 | usb->ipc = (struct baseband_ipc *) 0; | ||
| 1006 | } | ||
| 1007 | |||
| 1008 | /* free baseband usb structure */ | ||
| 1009 | kfree(usb); | ||
| 1010 | |||
| 1011 | pr_debug("baseband_usb_close }\n"); | ||
| 1012 | } | ||
| 1013 | |||
| 1014 | static struct baseband_usb *baseband_usb_open(unsigned int vid, | ||
| 1015 | unsigned int pid, | ||
| 1016 | unsigned int intf, | ||
| 1017 | work_func_t work_func, | ||
| 1018 | work_func_t rx_work_func, | ||
| 1019 | work_func_t tx_work_func) | ||
| 1020 | { | ||
| 1021 | struct baseband_usb *usb; | ||
| 1022 | int err; | ||
| 1023 | |||
| 1024 | pr_debug("baseband_usb_open {\n"); | ||
| 1025 | |||
| 1026 | /* allocate baseband usb structure */ | ||
| 1027 | usb = kzalloc(sizeof(struct baseband_usb), GFP_KERNEL); | ||
| 1028 | if (!usb) | ||
| 1029 | return (struct baseband_usb *) 0; | ||
| 1030 | baseband_usb_chr = usb; | ||
| 1031 | |||
| 1032 | /* open baseband ipc */ | ||
| 1033 | usb->ipc = baseband_ipc_open(work_func, | ||
| 1034 | rx_work_func, | ||
| 1035 | tx_work_func); | ||
| 1036 | if (!usb->ipc) { | ||
| 1037 | pr_err("open baseband ipc failed\n"); | ||
| 1038 | goto error_exit; | ||
| 1039 | } | ||
| 1040 | |||
| 1041 | /* open usb driver */ | ||
| 1042 | sprintf(baseband_usb_driver_name, | ||
| 1043 | "baseband_usb_%x_%x_%x", | ||
| 1044 | vid, pid, intf); | ||
| 1045 | baseband_usb_driver_id_table[0].match_flags | ||
| 1046 | = USB_DEVICE_ID_MATCH_DEVICE; | ||
| 1047 | baseband_usb_driver_id_table[0].idVendor = vid; | ||
| 1048 | baseband_usb_driver_id_table[0].idProduct = pid; | ||
| 1049 | usb->usb.driver = &baseband_usb_driver; | ||
| 1050 | err = usb_register(&baseband_usb_driver); | ||
| 1051 | if (err < 0) { | ||
| 1052 | pr_err("cannot open usb driver - err %d\n", err); | ||
| 1053 | goto error_exit; | ||
| 1054 | } | ||
| 1055 | |||
| 1056 | pr_debug("baseband_usb_open }\n"); | ||
| 1057 | return usb; | ||
| 1058 | |||
| 1059 | error_exit: | ||
| 1060 | baseband_usb_close(usb); | ||
| 1061 | baseband_usb_chr = (struct baseband_usb *) 0; | ||
| 1062 | return (struct baseband_usb *) 0; | ||
| 1063 | } | ||
| 1064 | |||
| 1065 | /* module init / exit functions */ | ||
| 1066 | |||
| 1067 | static int baseband_usb_chr_init(void) | ||
| 1068 | { | ||
| 1069 | int err; | ||
| 1070 | |||
| 1071 | pr_debug("baseband_usb_chr_init {\n"); | ||
| 1072 | |||
| 1073 | /* open baseband usb */ | ||
| 1074 | baseband_usb_chr = baseband_usb_open | ||
| 1075 | (baseband_usb_chr_vid, | ||
| 1076 | baseband_usb_chr_pid, | ||
| 1077 | baseband_usb_chr_intf, | ||
| 1078 | baseband_usb_chr_work, | ||
| 1079 | baseband_usb_chr_rx_urb_comp_work, | ||
| 1080 | (work_func_t) 0); | ||
| 1081 | if (!baseband_usb_chr) { | ||
| 1082 | pr_err("cannot open baseband usb chr\n"); | ||
| 1083 | err = -1; | ||
| 1084 | goto err1; | ||
| 1085 | } | ||
| 1086 | |||
| 1087 | /* register character device */ | ||
| 1088 | err = register_chrdev(BASEBAND_USB_CHR_DEV_MAJOR, | ||
| 1089 | BASEBAND_USB_CHR_DEV_NAME, | ||
| 1090 | &baseband_usb_chr_fops); | ||
| 1091 | if (err < 0) { | ||
| 1092 | pr_err("cannot register character device - %d\n", err); | ||
| 1093 | goto err2; | ||
| 1094 | } | ||
| 1095 | pr_debug("registered baseband usb character device - major %d\n", | ||
| 1096 | BASEBAND_USB_CHR_DEV_MAJOR); | ||
| 1097 | |||
| 1098 | pr_debug("baseband_usb_chr_init }\n"); | ||
| 1099 | return 0; | ||
| 1100 | err2: baseband_usb_close(baseband_usb_chr); | ||
| 1101 | baseband_usb_chr = (struct baseband_usb *) 0; | ||
| 1102 | err1: return err; | ||
| 1103 | } | ||
| 1104 | |||
| 1105 | static void baseband_usb_chr_exit(void) | ||
| 1106 | { | ||
| 1107 | pr_debug("baseband_usb_chr_exit {\n"); | ||
| 1108 | |||
| 1109 | /* unregister character device */ | ||
| 1110 | unregister_chrdev(BASEBAND_USB_CHR_DEV_MAJOR, | ||
| 1111 | BASEBAND_USB_CHR_DEV_NAME); | ||
| 1112 | |||
| 1113 | /* close baseband usb */ | ||
| 1114 | if (baseband_usb_chr) { | ||
| 1115 | baseband_usb_close(baseband_usb_chr); | ||
| 1116 | baseband_usb_chr = (struct baseband_usb *) 0; | ||
| 1117 | } | ||
| 1118 | |||
| 1119 | pr_debug("baseband_usb_chr_exit }\n"); | ||
| 1120 | } | ||
| 1121 | |||
| 1122 | module_init(baseband_usb_chr_init) | ||
| 1123 | module_exit(baseband_usb_chr_exit) | ||
| 1124 | |||
diff --git a/drivers/usb/serial/baseband_usb_chr.h b/drivers/usb/serial/baseband_usb_chr.h new file mode 100644 index 00000000000..7935e795a54 --- /dev/null +++ b/drivers/usb/serial/baseband_usb_chr.h | |||
| @@ -0,0 +1,106 @@ | |||
| 1 | /* | ||
| 2 | * baseband_usb_chr.h | ||
| 3 | * | ||
| 4 | * USB character driver to communicate with baseband modems. | ||
| 5 | * | ||
| 6 | * Copyright (c) 2011, NVIDIA Corporation. | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
| 14 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 15 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 16 | * more details. | ||
| 17 | * | ||
| 18 | * You should have received a copy of the GNU General Public License along | ||
| 19 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 20 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
| 21 | */ | ||
| 22 | |||
| 23 | #ifndef __BASEBAND_USB_CHR_H__ | ||
| 24 | #define __BASEBAND_USB_CHR_H__ | ||
| 25 | |||
| 26 | #define BASEBAND_USB_CHR_DEV_NAME "baseband_usb_chr" | ||
| 27 | #define BASEBAND_USB_CHR_DEV_MAJOR 66 | ||
| 28 | |||
| 29 | #ifndef USB_CHR_RX_BUFSIZ | ||
| 30 | #define USB_CHR_RX_BUFSIZ (128*1024) | ||
| 31 | #endif /* USB_CHR_RX_BUFSIZ */ | ||
| 32 | |||
| 33 | #ifndef USB_CHR_TX_BUFSIZ | ||
| 34 | #define USB_CHR_TX_BUFSIZ (128*1024) | ||
| 35 | #endif /* USB_CHR_TX_BUFSIZ */ | ||
| 36 | |||
| 37 | #ifndef USB_CHR_TIMEOUT | ||
| 38 | #define USB_CHR_TIMEOUT 5000 /* ms */ | ||
| 39 | #endif /* USB_CHR_TIMEOUT */ | ||
| 40 | |||
| 41 | #ifndef BASEBAND_IPC_NUM_RX_BUF | ||
| 42 | #define BASEBAND_IPC_NUM_RX_BUF 32 | ||
| 43 | #endif /* BASEBAND_IPC_NUM_RX_BUF */ | ||
| 44 | |||
| 45 | #ifndef BASEBAND_IPC_NUM_TX_BUF | ||
| 46 | #define BASEBAND_IPC_NUM_TX_BUF 16 | ||
| 47 | #endif /* BASEBAND_IPC_NUM_TX_BUF */ | ||
| 48 | |||
| 49 | #ifndef BASEBAND_IPC_BUFSIZ | ||
| 50 | #define BASEBAND_IPC_BUFSIZ 65536 | ||
| 51 | #endif /* BASEBAND_IPC_BUFSIZ */ | ||
| 52 | |||
| 53 | struct baseband_ipc { | ||
| 54 | /* rx / tx data */ | ||
| 55 | struct semaphore buf_sem; | ||
| 56 | struct { | ||
| 57 | /* linked list of data buffers */ | ||
| 58 | struct list_head buf; | ||
| 59 | /* wait queue of processes trying to access data buffers */ | ||
| 60 | wait_queue_head_t wait; | ||
| 61 | } rx, tx, rx_free, tx_free; | ||
| 62 | unsigned char *ipc_rx; | ||
| 63 | unsigned char *ipc_tx; | ||
| 64 | /* work queue | ||
| 65 | * - queued per ipc transaction | ||
| 66 | * - initiated by either: | ||
| 67 | * = interrupt on gpio line (rx data available) | ||
| 68 | * = tx data packet being added to tx linked list | ||
| 69 | */ | ||
| 70 | struct workqueue_struct *workqueue; | ||
| 71 | struct work_struct work; | ||
| 72 | struct work_struct rx_work; | ||
| 73 | struct work_struct tx_work; | ||
| 74 | }; | ||
| 75 | |||
| 76 | struct baseband_ipc_buf { | ||
| 77 | struct list_head list; | ||
| 78 | /* data buffer */ | ||
| 79 | unsigned char data[BASEBAND_IPC_BUFSIZ]; | ||
| 80 | /* offset of first data byte */ | ||
| 81 | size_t offset; | ||
| 82 | /* number of valid data bytes */ | ||
| 83 | size_t count; | ||
| 84 | }; | ||
| 85 | |||
| 86 | struct baseband_usb { | ||
| 87 | struct baseband_ipc *ipc; | ||
| 88 | struct { | ||
| 89 | struct usb_driver *driver; | ||
| 90 | struct usb_device *device; | ||
| 91 | struct usb_interface *interface; | ||
| 92 | struct { | ||
| 93 | struct { | ||
| 94 | unsigned int in; | ||
| 95 | unsigned int out; | ||
| 96 | } isoch, bulk, interrupt; | ||
| 97 | } pipe; | ||
| 98 | /* currently active rx urb */ | ||
| 99 | struct urb *rx_urb; | ||
| 100 | /* currently active tx urb */ | ||
| 101 | struct urb *tx_urb; | ||
| 102 | } usb; | ||
| 103 | }; | ||
| 104 | |||
| 105 | #endif /* __BASEBAND_USB_CHR_H__ */ | ||
| 106 | |||
diff --git a/drivers/usb/serial/ezusb.c b/drivers/usb/serial/ezusb.c new file mode 100644 index 00000000000..3cfc762f505 --- /dev/null +++ b/drivers/usb/serial/ezusb.c | |||
| @@ -0,0 +1,61 @@ | |||
| 1 | /* | ||
| 2 | * EZ-USB specific functions used by some of the USB to Serial drivers. | ||
| 3 | * | ||
| 4 | * Copyright (C) 1999 - 2002 Greg Kroah-Hartman (greg@kroah.com) | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License version | ||
| 8 | * 2 as published by the Free Software Foundation. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/kernel.h> | ||
| 12 | #include <linux/errno.h> | ||
| 13 | #include <linux/init.h> | ||
| 14 | #include <linux/slab.h> | ||
| 15 | #include <linux/tty.h> | ||
| 16 | #include <linux/module.h> | ||
| 17 | #include <linux/usb.h> | ||
| 18 | #include <linux/usb/serial.h> | ||
| 19 | |||
| 20 | /* EZ-USB Control and Status Register. Bit 0 controls 8051 reset */ | ||
| 21 | #define CPUCS_REG 0x7F92 | ||
| 22 | |||
| 23 | int ezusb_writememory(struct usb_serial *serial, int address, | ||
| 24 | unsigned char *data, int length, __u8 request) | ||
| 25 | { | ||
| 26 | int result; | ||
| 27 | unsigned char *transfer_buffer; | ||
| 28 | |||
| 29 | /* dbg("ezusb_writememory %x, %d", address, length); */ | ||
| 30 | if (!serial->dev) { | ||
| 31 | printk(KERN_ERR "ezusb: %s - no physical device present, " | ||
| 32 | "failing.\n", __func__); | ||
| 33 | return -ENODEV; | ||
| 34 | } | ||
| 35 | |||
| 36 | transfer_buffer = kmemdup(data, length, GFP_KERNEL); | ||
| 37 | if (!transfer_buffer) { | ||
| 38 | dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", | ||
| 39 | __func__, length); | ||
| 40 | return -ENOMEM; | ||
| 41 | } | ||
| 42 | result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), | ||
| 43 | request, 0x40, address, 0, transfer_buffer, length, 3000); | ||
| 44 | kfree(transfer_buffer); | ||
| 45 | return result; | ||
| 46 | } | ||
| 47 | EXPORT_SYMBOL_GPL(ezusb_writememory); | ||
| 48 | |||
| 49 | int ezusb_set_reset(struct usb_serial *serial, unsigned char reset_bit) | ||
| 50 | { | ||
| 51 | int response; | ||
| 52 | |||
| 53 | /* dbg("%s - %d", __func__, reset_bit); */ | ||
| 54 | response = ezusb_writememory(serial, CPUCS_REG, &reset_bit, 1, 0xa0); | ||
| 55 | if (response < 0) | ||
| 56 | dev_err(&serial->dev->dev, "%s- %d failed\n", | ||
| 57 | __func__, reset_bit); | ||
| 58 | return response; | ||
| 59 | } | ||
| 60 | EXPORT_SYMBOL_GPL(ezusb_set_reset); | ||
| 61 | |||
diff --git a/drivers/usb/storage/libusual.c b/drivers/usb/storage/libusual.c new file mode 100644 index 00000000000..fe3ffe1459b --- /dev/null +++ b/drivers/usb/storage/libusual.c | |||
| @@ -0,0 +1,243 @@ | |||
| 1 | /* | ||
| 2 | * libusual | ||
| 3 | * | ||
| 4 | * The libusual contains the table of devices common for ub and usb-storage. | ||
| 5 | */ | ||
| 6 | #include <linux/kernel.h> | ||
| 7 | #include <linux/module.h> | ||
| 8 | #include <linux/usb.h> | ||
| 9 | #include <linux/usb_usual.h> | ||
| 10 | #include <linux/vmalloc.h> | ||
| 11 | #include <linux/kthread.h> | ||
| 12 | #include <linux/mutex.h> | ||
| 13 | |||
| 14 | /* | ||
| 15 | */ | ||
| 16 | #define USU_MOD_FL_THREAD 1 /* Thread is running */ | ||
| 17 | #define USU_MOD_FL_PRESENT 2 /* The module is loaded */ | ||
| 18 | |||
| 19 | struct mod_status { | ||
| 20 | unsigned long fls; | ||
| 21 | }; | ||
| 22 | |||
| 23 | static struct mod_status stat[3]; | ||
| 24 | static DEFINE_SPINLOCK(usu_lock); | ||
| 25 | |||
| 26 | /* | ||
| 27 | */ | ||
| 28 | #define USB_US_DEFAULT_BIAS USB_US_TYPE_STOR | ||
| 29 | static atomic_t usu_bias = ATOMIC_INIT(USB_US_DEFAULT_BIAS); | ||
| 30 | |||
| 31 | #define BIAS_NAME_SIZE (sizeof("usb-storage")) | ||
| 32 | static const char *bias_names[3] = { "none", "usb-storage", "ub" }; | ||
| 33 | |||
| 34 | static DEFINE_MUTEX(usu_probe_mutex); | ||
| 35 | static DECLARE_COMPLETION(usu_end_notify); | ||
| 36 | static atomic_t total_threads = ATOMIC_INIT(0); | ||
| 37 | |||
| 38 | static int usu_probe_thread(void *arg); | ||
| 39 | |||
| 40 | /* | ||
| 41 | * @type: the module type as an integer | ||
| 42 | */ | ||
| 43 | void usb_usual_set_present(int type) | ||
| 44 | { | ||
| 45 | struct mod_status *st; | ||
| 46 | unsigned long flags; | ||
| 47 | |||
| 48 | if (type <= 0 || type >= 3) | ||
| 49 | return; | ||
| 50 | st = &stat[type]; | ||
| 51 | spin_lock_irqsave(&usu_lock, flags); | ||
| 52 | st->fls |= USU_MOD_FL_PRESENT; | ||
| 53 | spin_unlock_irqrestore(&usu_lock, flags); | ||
| 54 | } | ||
| 55 | EXPORT_SYMBOL_GPL(usb_usual_set_present); | ||
| 56 | |||
| 57 | void usb_usual_clear_present(int type) | ||
| 58 | { | ||
| 59 | struct mod_status *st; | ||
| 60 | unsigned long flags; | ||
| 61 | |||
| 62 | if (type <= 0 || type >= 3) | ||
| 63 | return; | ||
| 64 | st = &stat[type]; | ||
| 65 | spin_lock_irqsave(&usu_lock, flags); | ||
| 66 | st->fls &= ~USU_MOD_FL_PRESENT; | ||
| 67 | spin_unlock_irqrestore(&usu_lock, flags); | ||
| 68 | } | ||
| 69 | EXPORT_SYMBOL_GPL(usb_usual_clear_present); | ||
| 70 | |||
| 71 | /* | ||
| 72 | * Match the calling driver type against the table. | ||
| 73 | * Returns: 0 if the device matches. | ||
| 74 | */ | ||
| 75 | int usb_usual_check_type(const struct usb_device_id *id, int caller_type) | ||
| 76 | { | ||
| 77 | int id_type = USB_US_TYPE(id->driver_info); | ||
| 78 | |||
| 79 | if (caller_type <= 0 || caller_type >= 3) | ||
| 80 | return -EINVAL; | ||
| 81 | |||
| 82 | /* Drivers grab fixed assignment devices */ | ||
| 83 | if (id_type == caller_type) | ||
| 84 | return 0; | ||
| 85 | /* Drivers grab devices biased to them */ | ||
| 86 | if (id_type == USB_US_TYPE_NONE && caller_type == atomic_read(&usu_bias)) | ||
| 87 | return 0; | ||
| 88 | return -ENODEV; | ||
| 89 | } | ||
| 90 | EXPORT_SYMBOL_GPL(usb_usual_check_type); | ||
| 91 | |||
| 92 | /* | ||
| 93 | */ | ||
| 94 | static int usu_probe(struct usb_interface *intf, | ||
| 95 | const struct usb_device_id *id) | ||
| 96 | { | ||
| 97 | int rc; | ||
| 98 | unsigned long type; | ||
| 99 | struct task_struct* task; | ||
| 100 | unsigned long flags; | ||
| 101 | |||
| 102 | type = USB_US_TYPE(id->driver_info); | ||
| 103 | if (type == 0) | ||
| 104 | type = atomic_read(&usu_bias); | ||
| 105 | |||
| 106 | spin_lock_irqsave(&usu_lock, flags); | ||
| 107 | if ((stat[type].fls & (USU_MOD_FL_THREAD|USU_MOD_FL_PRESENT)) != 0) { | ||
| 108 | spin_unlock_irqrestore(&usu_lock, flags); | ||
| 109 | return -ENXIO; | ||
| 110 | } | ||
| 111 | stat[type].fls |= USU_MOD_FL_THREAD; | ||
| 112 | spin_unlock_irqrestore(&usu_lock, flags); | ||
| 113 | |||
| 114 | task = kthread_run(usu_probe_thread, (void*)type, "libusual_%ld", type); | ||
| 115 | if (IS_ERR(task)) { | ||
| 116 | rc = PTR_ERR(task); | ||
| 117 | printk(KERN_WARNING "libusual: " | ||
| 118 | "Unable to start the thread for %s: %d\n", | ||
| 119 | bias_names[type], rc); | ||
| 120 | spin_lock_irqsave(&usu_lock, flags); | ||
| 121 | stat[type].fls &= ~USU_MOD_FL_THREAD; | ||
| 122 | spin_unlock_irqrestore(&usu_lock, flags); | ||
| 123 | return rc; /* Not being -ENXIO causes a message printed */ | ||
| 124 | } | ||
| 125 | atomic_inc(&total_threads); | ||
| 126 | |||
| 127 | return -ENXIO; | ||
| 128 | } | ||
| 129 | |||
| 130 | static void usu_disconnect(struct usb_interface *intf) | ||
| 131 | { | ||
| 132 | ; /* We should not be here. */ | ||
| 133 | } | ||
| 134 | |||
| 135 | static struct usb_driver usu_driver = { | ||
| 136 | .name = "libusual", | ||
| 137 | .probe = usu_probe, | ||
| 138 | .disconnect = usu_disconnect, | ||
| 139 | .id_table = usb_storage_usb_ids, | ||
| 140 | }; | ||
| 141 | |||
| 142 | /* | ||
| 143 | * A whole new thread for a purpose of request_module seems quite stupid. | ||
| 144 | * The request_module forks once inside again. However, if we attempt | ||
| 145 | * to load a storage module from our own modprobe thread, that module | ||
| 146 | * references our symbols, which cannot be resolved until our module is | ||
| 147 | * initialized. I wish there was a way to wait for the end of initialization. | ||
| 148 | * The module notifier reports MODULE_STATE_COMING only. | ||
| 149 | * So, we wait until module->init ends as the next best thing. | ||
| 150 | */ | ||
| 151 | static int usu_probe_thread(void *arg) | ||
| 152 | { | ||
| 153 | int type = (unsigned long) arg; | ||
| 154 | struct mod_status *st = &stat[type]; | ||
| 155 | int rc; | ||
| 156 | unsigned long flags; | ||
| 157 | |||
| 158 | mutex_lock(&usu_probe_mutex); | ||
| 159 | rc = request_module(bias_names[type]); | ||
| 160 | spin_lock_irqsave(&usu_lock, flags); | ||
| 161 | if (rc == 0 && (st->fls & USU_MOD_FL_PRESENT) == 0) { | ||
| 162 | /* | ||
| 163 | * This should not happen, but let us keep tabs on it. | ||
| 164 | */ | ||
| 165 | printk(KERN_NOTICE "libusual: " | ||
| 166 | "modprobe for %s succeeded, but module is not present\n", | ||
| 167 | bias_names[type]); | ||
| 168 | } | ||
| 169 | st->fls &= ~USU_MOD_FL_THREAD; | ||
| 170 | spin_unlock_irqrestore(&usu_lock, flags); | ||
| 171 | mutex_unlock(&usu_probe_mutex); | ||
| 172 | |||
| 173 | complete_and_exit(&usu_end_notify, 0); | ||
| 174 | } | ||
| 175 | |||
| 176 | /* | ||
| 177 | */ | ||
| 178 | static int __init usb_usual_init(void) | ||
| 179 | { | ||
| 180 | int rc; | ||
| 181 | |||
| 182 | mutex_lock(&usu_probe_mutex); | ||
| 183 | rc = usb_register(&usu_driver); | ||
| 184 | mutex_unlock(&usu_probe_mutex); | ||
| 185 | return rc; | ||
| 186 | } | ||
| 187 | |||
| 188 | static void __exit usb_usual_exit(void) | ||
| 189 | { | ||
| 190 | /* | ||
| 191 | * We do not check for any drivers present, because | ||
| 192 | * they keep us pinned with symbol references. | ||
| 193 | */ | ||
| 194 | |||
| 195 | usb_deregister(&usu_driver); | ||
| 196 | |||
| 197 | while (atomic_read(&total_threads) > 0) { | ||
| 198 | wait_for_completion(&usu_end_notify); | ||
| 199 | atomic_dec(&total_threads); | ||
| 200 | } | ||
| 201 | } | ||
| 202 | |||
| 203 | /* | ||
| 204 | * Validate and accept the bias parameter. | ||
| 205 | */ | ||
| 206 | static int usu_set_bias(const char *bias_s, struct kernel_param *kp) | ||
| 207 | { | ||
| 208 | int i; | ||
| 209 | int len; | ||
| 210 | int bias_n = 0; | ||
| 211 | |||
| 212 | len = strlen(bias_s); | ||
| 213 | if (len == 0) | ||
| 214 | return -EDOM; | ||
| 215 | if (bias_s[len-1] == '\n') | ||
| 216 | --len; | ||
| 217 | |||
| 218 | for (i = 1; i < 3; i++) { | ||
| 219 | if (strncmp(bias_s, bias_names[i], len) == 0) { | ||
| 220 | bias_n = i; | ||
| 221 | break; | ||
| 222 | } | ||
| 223 | } | ||
| 224 | if (bias_n == 0) | ||
| 225 | return -EINVAL; | ||
| 226 | |||
| 227 | atomic_set(&usu_bias, bias_n); | ||
| 228 | return 0; | ||
| 229 | } | ||
| 230 | |||
| 231 | static int usu_get_bias(char *buffer, struct kernel_param *kp) | ||
| 232 | { | ||
| 233 | return strlen(strcpy(buffer, bias_names[atomic_read(&usu_bias)])); | ||
| 234 | } | ||
| 235 | |||
| 236 | module_init(usb_usual_init); | ||
| 237 | module_exit(usb_usual_exit); | ||
| 238 | |||
| 239 | module_param_call(bias, usu_set_bias, usu_get_bias, NULL, S_IRUGO|S_IWUSR); | ||
| 240 | __MODULE_PARM_TYPE(bias, "string"); | ||
| 241 | MODULE_PARM_DESC(bias, "Bias to usb-storage or ub"); | ||
| 242 | |||
| 243 | MODULE_LICENSE("GPL"); | ||
