cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

common.c (12150B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Provides code common for host and device side USB.
      4 *
      5 * If either host side (ie. CONFIG_USB=y) or device side USB stack
      6 * (ie. CONFIG_USB_GADGET=y) is compiled in the kernel, this module is
      7 * compiled-in as well.  Otherwise, if either of the two stacks is
      8 * compiled as module, this file is compiled as module as well.
      9 */
     10
     11#include <linux/kernel.h>
     12#include <linux/module.h>
     13#include <linux/of.h>
     14#include <linux/usb/ch9.h>
     15#include <linux/usb/of.h>
     16#include <linux/usb/otg.h>
     17#include <linux/of_platform.h>
     18#include <linux/debugfs.h>
     19#include "common.h"
     20
     21static const char *const ep_type_names[] = {
     22	[USB_ENDPOINT_XFER_CONTROL] = "ctrl",
     23	[USB_ENDPOINT_XFER_ISOC] = "isoc",
     24	[USB_ENDPOINT_XFER_BULK] = "bulk",
     25	[USB_ENDPOINT_XFER_INT] = "intr",
     26};
     27
     28/**
     29 * usb_ep_type_string() - Returns human readable-name of the endpoint type.
     30 * @ep_type: The endpoint type to return human-readable name for.  If it's not
     31 *   any of the types: USB_ENDPOINT_XFER_{CONTROL, ISOC, BULK, INT},
     32 *   usually got by usb_endpoint_type(), the string 'unknown' will be returned.
     33 */
     34const char *usb_ep_type_string(int ep_type)
     35{
     36	if (ep_type < 0 || ep_type >= ARRAY_SIZE(ep_type_names))
     37		return "unknown";
     38
     39	return ep_type_names[ep_type];
     40}
     41EXPORT_SYMBOL_GPL(usb_ep_type_string);
     42
     43const char *usb_otg_state_string(enum usb_otg_state state)
     44{
     45	static const char *const names[] = {
     46		[OTG_STATE_A_IDLE] = "a_idle",
     47		[OTG_STATE_A_WAIT_VRISE] = "a_wait_vrise",
     48		[OTG_STATE_A_WAIT_BCON] = "a_wait_bcon",
     49		[OTG_STATE_A_HOST] = "a_host",
     50		[OTG_STATE_A_SUSPEND] = "a_suspend",
     51		[OTG_STATE_A_PERIPHERAL] = "a_peripheral",
     52		[OTG_STATE_A_WAIT_VFALL] = "a_wait_vfall",
     53		[OTG_STATE_A_VBUS_ERR] = "a_vbus_err",
     54		[OTG_STATE_B_IDLE] = "b_idle",
     55		[OTG_STATE_B_SRP_INIT] = "b_srp_init",
     56		[OTG_STATE_B_PERIPHERAL] = "b_peripheral",
     57		[OTG_STATE_B_WAIT_ACON] = "b_wait_acon",
     58		[OTG_STATE_B_HOST] = "b_host",
     59	};
     60
     61	if (state < 0 || state >= ARRAY_SIZE(names))
     62		return "UNDEFINED";
     63
     64	return names[state];
     65}
     66EXPORT_SYMBOL_GPL(usb_otg_state_string);
     67
     68static const char *const speed_names[] = {
     69	[USB_SPEED_UNKNOWN] = "UNKNOWN",
     70	[USB_SPEED_LOW] = "low-speed",
     71	[USB_SPEED_FULL] = "full-speed",
     72	[USB_SPEED_HIGH] = "high-speed",
     73	[USB_SPEED_WIRELESS] = "wireless",
     74	[USB_SPEED_SUPER] = "super-speed",
     75	[USB_SPEED_SUPER_PLUS] = "super-speed-plus",
     76};
     77
     78static const char *const ssp_rate[] = {
     79	[USB_SSP_GEN_UNKNOWN] = "UNKNOWN",
     80	[USB_SSP_GEN_2x1] = "super-speed-plus-gen2x1",
     81	[USB_SSP_GEN_1x2] = "super-speed-plus-gen1x2",
     82	[USB_SSP_GEN_2x2] = "super-speed-plus-gen2x2",
     83};
     84
     85/**
     86 * usb_speed_string() - Returns human readable-name of the speed.
     87 * @speed: The speed to return human-readable name for.  If it's not
     88 *   any of the speeds defined in usb_device_speed enum, string for
     89 *   USB_SPEED_UNKNOWN will be returned.
     90 */
     91const char *usb_speed_string(enum usb_device_speed speed)
     92{
     93	if (speed < 0 || speed >= ARRAY_SIZE(speed_names))
     94		speed = USB_SPEED_UNKNOWN;
     95	return speed_names[speed];
     96}
     97EXPORT_SYMBOL_GPL(usb_speed_string);
     98
     99/**
    100 * usb_get_maximum_speed - Get maximum requested speed for a given USB
    101 * controller.
    102 * @dev: Pointer to the given USB controller device
    103 *
    104 * The function gets the maximum speed string from property "maximum-speed",
    105 * and returns the corresponding enum usb_device_speed.
    106 */
    107enum usb_device_speed usb_get_maximum_speed(struct device *dev)
    108{
    109	const char *maximum_speed;
    110	int ret;
    111
    112	ret = device_property_read_string(dev, "maximum-speed", &maximum_speed);
    113	if (ret < 0)
    114		return USB_SPEED_UNKNOWN;
    115
    116	ret = match_string(ssp_rate, ARRAY_SIZE(ssp_rate), maximum_speed);
    117	if (ret > 0)
    118		return USB_SPEED_SUPER_PLUS;
    119
    120	ret = match_string(speed_names, ARRAY_SIZE(speed_names), maximum_speed);
    121	return (ret < 0) ? USB_SPEED_UNKNOWN : ret;
    122}
    123EXPORT_SYMBOL_GPL(usb_get_maximum_speed);
    124
    125/**
    126 * usb_get_maximum_ssp_rate - Get the signaling rate generation and lane count
    127 *	of a SuperSpeed Plus capable device.
    128 * @dev: Pointer to the given USB controller device
    129 *
    130 * If the string from "maximum-speed" property is super-speed-plus-genXxY where
    131 * 'X' is the generation number and 'Y' is the number of lanes, then this
    132 * function returns the corresponding enum usb_ssp_rate.
    133 */
    134enum usb_ssp_rate usb_get_maximum_ssp_rate(struct device *dev)
    135{
    136	const char *maximum_speed;
    137	int ret;
    138
    139	ret = device_property_read_string(dev, "maximum-speed", &maximum_speed);
    140	if (ret < 0)
    141		return USB_SSP_GEN_UNKNOWN;
    142
    143	ret = match_string(ssp_rate, ARRAY_SIZE(ssp_rate), maximum_speed);
    144	return (ret < 0) ? USB_SSP_GEN_UNKNOWN : ret;
    145}
    146EXPORT_SYMBOL_GPL(usb_get_maximum_ssp_rate);
    147
    148/**
    149 * usb_state_string - Returns human readable name for the state.
    150 * @state: The state to return a human-readable name for. If it's not
    151 *	any of the states devices in usb_device_state_string enum,
    152 *	the string UNKNOWN will be returned.
    153 */
    154const char *usb_state_string(enum usb_device_state state)
    155{
    156	static const char *const names[] = {
    157		[USB_STATE_NOTATTACHED] = "not attached",
    158		[USB_STATE_ATTACHED] = "attached",
    159		[USB_STATE_POWERED] = "powered",
    160		[USB_STATE_RECONNECTING] = "reconnecting",
    161		[USB_STATE_UNAUTHENTICATED] = "unauthenticated",
    162		[USB_STATE_DEFAULT] = "default",
    163		[USB_STATE_ADDRESS] = "addressed",
    164		[USB_STATE_CONFIGURED] = "configured",
    165		[USB_STATE_SUSPENDED] = "suspended",
    166	};
    167
    168	if (state < 0 || state >= ARRAY_SIZE(names))
    169		return "UNKNOWN";
    170
    171	return names[state];
    172}
    173EXPORT_SYMBOL_GPL(usb_state_string);
    174
    175static const char *const usb_dr_modes[] = {
    176	[USB_DR_MODE_UNKNOWN]		= "",
    177	[USB_DR_MODE_HOST]		= "host",
    178	[USB_DR_MODE_PERIPHERAL]	= "peripheral",
    179	[USB_DR_MODE_OTG]		= "otg",
    180};
    181
    182static enum usb_dr_mode usb_get_dr_mode_from_string(const char *str)
    183{
    184	int ret;
    185
    186	ret = match_string(usb_dr_modes, ARRAY_SIZE(usb_dr_modes), str);
    187	return (ret < 0) ? USB_DR_MODE_UNKNOWN : ret;
    188}
    189
    190enum usb_dr_mode usb_get_dr_mode(struct device *dev)
    191{
    192	const char *dr_mode;
    193	int err;
    194
    195	err = device_property_read_string(dev, "dr_mode", &dr_mode);
    196	if (err < 0)
    197		return USB_DR_MODE_UNKNOWN;
    198
    199	return usb_get_dr_mode_from_string(dr_mode);
    200}
    201EXPORT_SYMBOL_GPL(usb_get_dr_mode);
    202
    203/**
    204 * usb_get_role_switch_default_mode - Get default mode for given device
    205 * @dev: Pointer to the given device
    206 *
    207 * The function gets string from property 'role-switch-default-mode',
    208 * and returns the corresponding enum usb_dr_mode.
    209 */
    210enum usb_dr_mode usb_get_role_switch_default_mode(struct device *dev)
    211{
    212	const char *str;
    213	int ret;
    214
    215	ret = device_property_read_string(dev, "role-switch-default-mode", &str);
    216	if (ret < 0)
    217		return USB_DR_MODE_UNKNOWN;
    218
    219	return usb_get_dr_mode_from_string(str);
    220}
    221EXPORT_SYMBOL_GPL(usb_get_role_switch_default_mode);
    222
    223/**
    224 * usb_decode_interval - Decode bInterval into the time expressed in 1us unit
    225 * @epd: The descriptor of the endpoint
    226 * @speed: The speed that the endpoint works as
    227 *
    228 * Function returns the interval expressed in 1us unit for servicing
    229 * endpoint for data transfers.
    230 */
    231unsigned int usb_decode_interval(const struct usb_endpoint_descriptor *epd,
    232				 enum usb_device_speed speed)
    233{
    234	unsigned int interval = 0;
    235
    236	switch (usb_endpoint_type(epd)) {
    237	case USB_ENDPOINT_XFER_CONTROL:
    238		/* uframes per NAK */
    239		if (speed == USB_SPEED_HIGH)
    240			interval = epd->bInterval;
    241		break;
    242	case USB_ENDPOINT_XFER_ISOC:
    243		interval = 1 << (epd->bInterval - 1);
    244		break;
    245	case USB_ENDPOINT_XFER_BULK:
    246		/* uframes per NAK */
    247		if (speed == USB_SPEED_HIGH && usb_endpoint_dir_out(epd))
    248			interval = epd->bInterval;
    249		break;
    250	case USB_ENDPOINT_XFER_INT:
    251		if (speed >= USB_SPEED_HIGH)
    252			interval = 1 << (epd->bInterval - 1);
    253		else
    254			interval = epd->bInterval;
    255		break;
    256	}
    257
    258	interval *= (speed >= USB_SPEED_HIGH) ? 125 : 1000;
    259
    260	return interval;
    261}
    262EXPORT_SYMBOL_GPL(usb_decode_interval);
    263
    264#ifdef CONFIG_OF
    265/**
    266 * of_usb_get_dr_mode_by_phy - Get dual role mode for the controller device
    267 * which is associated with the given phy device_node
    268 * @np:	Pointer to the given phy device_node
    269 * @arg0: phandle args[0] for phy's with #phy-cells >= 1, or -1 for
    270 *        phys which do not have phy-cells
    271 *
    272 * In dts a usb controller associates with phy devices.  The function gets
    273 * the string from property 'dr_mode' of the controller associated with the
    274 * given phy device node, and returns the correspondig enum usb_dr_mode.
    275 */
    276enum usb_dr_mode of_usb_get_dr_mode_by_phy(struct device_node *np, int arg0)
    277{
    278	struct device_node *controller = NULL;
    279	struct of_phandle_args args;
    280	const char *dr_mode;
    281	int index;
    282	int err;
    283
    284	do {
    285		controller = of_find_node_with_property(controller, "phys");
    286		if (!of_device_is_available(controller))
    287			continue;
    288		index = 0;
    289		do {
    290			if (arg0 == -1) {
    291				args.np = of_parse_phandle(controller, "phys",
    292							index);
    293				args.args_count = 0;
    294			} else {
    295				err = of_parse_phandle_with_args(controller,
    296							"phys", "#phy-cells",
    297							index, &args);
    298				if (err)
    299					break;
    300			}
    301
    302			of_node_put(args.np);
    303			if (args.np == np && (args.args_count == 0 ||
    304					      args.args[0] == arg0))
    305				goto finish;
    306			index++;
    307		} while (args.np);
    308	} while (controller);
    309
    310finish:
    311	err = of_property_read_string(controller, "dr_mode", &dr_mode);
    312	of_node_put(controller);
    313
    314	if (err < 0)
    315		return USB_DR_MODE_UNKNOWN;
    316
    317	return usb_get_dr_mode_from_string(dr_mode);
    318}
    319EXPORT_SYMBOL_GPL(of_usb_get_dr_mode_by_phy);
    320
    321/**
    322 * of_usb_host_tpl_support - to get if Targeted Peripheral List is supported
    323 * for given targeted hosts (non-PC hosts)
    324 * @np: Pointer to the given device_node
    325 *
    326 * The function gets if the targeted hosts support TPL or not
    327 */
    328bool of_usb_host_tpl_support(struct device_node *np)
    329{
    330	return of_property_read_bool(np, "tpl-support");
    331}
    332EXPORT_SYMBOL_GPL(of_usb_host_tpl_support);
    333
    334/**
    335 * of_usb_update_otg_caps - to update usb otg capabilities according to
    336 * the passed properties in DT.
    337 * @np: Pointer to the given device_node
    338 * @otg_caps: Pointer to the target usb_otg_caps to be set
    339 *
    340 * The function updates the otg capabilities
    341 */
    342int of_usb_update_otg_caps(struct device_node *np,
    343			struct usb_otg_caps *otg_caps)
    344{
    345	u32 otg_rev;
    346
    347	if (!otg_caps)
    348		return -EINVAL;
    349
    350	if (!of_property_read_u32(np, "otg-rev", &otg_rev)) {
    351		switch (otg_rev) {
    352		case 0x0100:
    353		case 0x0120:
    354		case 0x0130:
    355		case 0x0200:
    356			/* Choose the lesser one if it's already been set */
    357			if (otg_caps->otg_rev)
    358				otg_caps->otg_rev = min_t(u16, otg_rev,
    359							otg_caps->otg_rev);
    360			else
    361				otg_caps->otg_rev = otg_rev;
    362			break;
    363		default:
    364			pr_err("%pOF: unsupported otg-rev: 0x%x\n",
    365						np, otg_rev);
    366			return -EINVAL;
    367		}
    368	} else {
    369		/*
    370		 * otg-rev is mandatory for otg properties, if not passed
    371		 * we set it to be 0 and assume it's a legacy otg device.
    372		 * Non-dt platform can set it afterwards.
    373		 */
    374		otg_caps->otg_rev = 0;
    375	}
    376
    377	if (of_property_read_bool(np, "hnp-disable"))
    378		otg_caps->hnp_support = false;
    379	if (of_property_read_bool(np, "srp-disable"))
    380		otg_caps->srp_support = false;
    381	if (of_property_read_bool(np, "adp-disable") ||
    382				(otg_caps->otg_rev < 0x0200))
    383		otg_caps->adp_support = false;
    384
    385	return 0;
    386}
    387EXPORT_SYMBOL_GPL(of_usb_update_otg_caps);
    388
    389/**
    390 * usb_of_get_companion_dev - Find the companion device
    391 * @dev: the device pointer to find a companion
    392 *
    393 * Find the companion device from platform bus.
    394 *
    395 * Takes a reference to the returned struct device which needs to be dropped
    396 * after use.
    397 *
    398 * Return: On success, a pointer to the companion device, %NULL on failure.
    399 */
    400struct device *usb_of_get_companion_dev(struct device *dev)
    401{
    402	struct device_node *node;
    403	struct platform_device *pdev = NULL;
    404
    405	node = of_parse_phandle(dev->of_node, "companion", 0);
    406	if (node)
    407		pdev = of_find_device_by_node(node);
    408
    409	of_node_put(node);
    410
    411	return pdev ? &pdev->dev : NULL;
    412}
    413EXPORT_SYMBOL_GPL(usb_of_get_companion_dev);
    414#endif
    415
    416struct dentry *usb_debug_root;
    417EXPORT_SYMBOL_GPL(usb_debug_root);
    418
    419static int __init usb_common_init(void)
    420{
    421	usb_debug_root = debugfs_create_dir("usb", NULL);
    422	ledtrig_usb_init();
    423	return 0;
    424}
    425
    426static void __exit usb_common_exit(void)
    427{
    428	ledtrig_usb_exit();
    429	debugfs_remove_recursive(usb_debug_root);
    430}
    431
    432subsys_initcall(usb_common_init);
    433module_exit(usb_common_exit);
    434
    435MODULE_LICENSE("GPL");