Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.8-rc2 237 lines 5.5 kB view raw
1/* 2 * otg.c -- USB OTG utility code 3 * 4 * Copyright (C) 2004 Texas Instruments 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 */ 11 12#include <linux/kernel.h> 13#include <linux/export.h> 14#include <linux/err.h> 15#include <linux/device.h> 16#include <linux/slab.h> 17 18#include <linux/usb/otg.h> 19 20static LIST_HEAD(phy_list); 21static DEFINE_SPINLOCK(phy_lock); 22 23static struct usb_phy *__usb_find_phy(struct list_head *list, 24 enum usb_phy_type type) 25{ 26 struct usb_phy *phy = NULL; 27 28 list_for_each_entry(phy, list, head) { 29 if (phy->type != type) 30 continue; 31 32 return phy; 33 } 34 35 return ERR_PTR(-ENODEV); 36} 37 38static void devm_usb_phy_release(struct device *dev, void *res) 39{ 40 struct usb_phy *phy = *(struct usb_phy **)res; 41 42 usb_put_phy(phy); 43} 44 45static int devm_usb_phy_match(struct device *dev, void *res, void *match_data) 46{ 47 return res == match_data; 48} 49 50/** 51 * devm_usb_get_phy - find the USB PHY 52 * @dev - device that requests this phy 53 * @type - the type of the phy the controller requires 54 * 55 * Gets the phy using usb_get_phy(), and associates a device with it using 56 * devres. On driver detach, release function is invoked on the devres data, 57 * then, devres data is freed. 58 * 59 * For use by USB host and peripheral drivers. 60 */ 61struct usb_phy *devm_usb_get_phy(struct device *dev, enum usb_phy_type type) 62{ 63 struct usb_phy **ptr, *phy; 64 65 ptr = devres_alloc(devm_usb_phy_release, sizeof(*ptr), GFP_KERNEL); 66 if (!ptr) 67 return NULL; 68 69 phy = usb_get_phy(type); 70 if (!IS_ERR(phy)) { 71 *ptr = phy; 72 devres_add(dev, ptr); 73 } else 74 devres_free(ptr); 75 76 return phy; 77} 78EXPORT_SYMBOL(devm_usb_get_phy); 79 80/** 81 * usb_get_phy - find the USB PHY 82 * @type - the type of the phy the controller requires 83 * 84 * Returns the phy driver, after getting a refcount to it; or 85 * -ENODEV if there is no such phy. The caller is responsible for 86 * calling usb_put_phy() to release that count. 87 * 88 * For use by USB host and peripheral drivers. 89 */ 90struct usb_phy *usb_get_phy(enum usb_phy_type type) 91{ 92 struct usb_phy *phy = NULL; 93 unsigned long flags; 94 95 spin_lock_irqsave(&phy_lock, flags); 96 97 phy = __usb_find_phy(&phy_list, type); 98 if (IS_ERR(phy)) { 99 pr_err("unable to find transceiver of type %s\n", 100 usb_phy_type_string(type)); 101 goto err0; 102 } 103 104 get_device(phy->dev); 105 106err0: 107 spin_unlock_irqrestore(&phy_lock, flags); 108 109 return phy; 110} 111EXPORT_SYMBOL(usb_get_phy); 112 113/** 114 * devm_usb_put_phy - release the USB PHY 115 * @dev - device that wants to release this phy 116 * @phy - the phy returned by devm_usb_get_phy() 117 * 118 * destroys the devres associated with this phy and invokes usb_put_phy 119 * to release the phy. 120 * 121 * For use by USB host and peripheral drivers. 122 */ 123void devm_usb_put_phy(struct device *dev, struct usb_phy *phy) 124{ 125 int r; 126 127 r = devres_destroy(dev, devm_usb_phy_release, devm_usb_phy_match, phy); 128 dev_WARN_ONCE(dev, r, "couldn't find PHY resource\n"); 129} 130EXPORT_SYMBOL(devm_usb_put_phy); 131 132/** 133 * usb_put_phy - release the USB PHY 134 * @x: the phy returned by usb_get_phy() 135 * 136 * Releases a refcount the caller received from usb_get_phy(). 137 * 138 * For use by USB host and peripheral drivers. 139 */ 140void usb_put_phy(struct usb_phy *x) 141{ 142 if (x) 143 put_device(x->dev); 144} 145EXPORT_SYMBOL(usb_put_phy); 146 147/** 148 * usb_add_phy - declare the USB PHY 149 * @x: the USB phy to be used; or NULL 150 * @type - the type of this PHY 151 * 152 * This call is exclusively for use by phy drivers, which 153 * coordinate the activities of drivers for host and peripheral 154 * controllers, and in some cases for VBUS current regulation. 155 */ 156int usb_add_phy(struct usb_phy *x, enum usb_phy_type type) 157{ 158 int ret = 0; 159 unsigned long flags; 160 struct usb_phy *phy; 161 162 if (x->type != USB_PHY_TYPE_UNDEFINED) { 163 dev_err(x->dev, "not accepting initialized PHY %s\n", x->label); 164 return -EINVAL; 165 } 166 167 spin_lock_irqsave(&phy_lock, flags); 168 169 list_for_each_entry(phy, &phy_list, head) { 170 if (phy->type == type) { 171 ret = -EBUSY; 172 dev_err(x->dev, "transceiver type %s already exists\n", 173 usb_phy_type_string(type)); 174 goto out; 175 } 176 } 177 178 x->type = type; 179 list_add_tail(&x->head, &phy_list); 180 181out: 182 spin_unlock_irqrestore(&phy_lock, flags); 183 return ret; 184} 185EXPORT_SYMBOL(usb_add_phy); 186 187/** 188 * usb_remove_phy - remove the OTG PHY 189 * @x: the USB OTG PHY to be removed; 190 * 191 * This reverts the effects of usb_add_phy 192 */ 193void usb_remove_phy(struct usb_phy *x) 194{ 195 unsigned long flags; 196 197 spin_lock_irqsave(&phy_lock, flags); 198 if (x) 199 list_del(&x->head); 200 spin_unlock_irqrestore(&phy_lock, flags); 201} 202EXPORT_SYMBOL(usb_remove_phy); 203 204const char *otg_state_string(enum usb_otg_state state) 205{ 206 switch (state) { 207 case OTG_STATE_A_IDLE: 208 return "a_idle"; 209 case OTG_STATE_A_WAIT_VRISE: 210 return "a_wait_vrise"; 211 case OTG_STATE_A_WAIT_BCON: 212 return "a_wait_bcon"; 213 case OTG_STATE_A_HOST: 214 return "a_host"; 215 case OTG_STATE_A_SUSPEND: 216 return "a_suspend"; 217 case OTG_STATE_A_PERIPHERAL: 218 return "a_peripheral"; 219 case OTG_STATE_A_WAIT_VFALL: 220 return "a_wait_vfall"; 221 case OTG_STATE_A_VBUS_ERR: 222 return "a_vbus_err"; 223 case OTG_STATE_B_IDLE: 224 return "b_idle"; 225 case OTG_STATE_B_SRP_INIT: 226 return "b_srp_init"; 227 case OTG_STATE_B_PERIPHERAL: 228 return "b_peripheral"; 229 case OTG_STATE_B_WAIT_ACON: 230 return "b_wait_acon"; 231 case OTG_STATE_B_HOST: 232 return "b_host"; 233 default: 234 return "UNDEFINED"; 235 } 236} 237EXPORT_SYMBOL(otg_state_string);