Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * XHCI extended capability handling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Copyright (c) 2017 Hans de Goede <hdegoede@redhat.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/property.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include "xhci.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #define USB_SW_DRV_NAME		"intel_xhci_usb_sw"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #define USB_SW_RESOURCE_SIZE	0x400
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #define PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI	0x22b5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) static const struct property_entry role_switch_props[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) 	PROPERTY_ENTRY_BOOL("sw_switch_disable"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 	{},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) static void xhci_intel_unregister_pdev(void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 	platform_device_unregister(arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) static int xhci_create_intel_xhci_sw_pdev(struct xhci_hcd *xhci, u32 cap_offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 	struct usb_hcd *hcd = xhci_to_hcd(xhci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 	struct device *dev = hcd->self.controller;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 	struct platform_device *pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	struct pci_dev *pci = to_pci_dev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	struct resource	res = { 0, };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	pdev = platform_device_alloc(USB_SW_DRV_NAME, PLATFORM_DEVID_NONE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	if (!pdev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 		xhci_err(xhci, "couldn't allocate %s platform device\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 			 USB_SW_DRV_NAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	res.start = hcd->rsrc_start + cap_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	res.end	  = res.start + USB_SW_RESOURCE_SIZE - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	res.name  = USB_SW_DRV_NAME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	res.flags = IORESOURCE_MEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	ret = platform_device_add_resources(pdev, &res, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 		dev_err(dev, "couldn't add resources to intel_xhci_usb_sw pdev\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 		platform_device_put(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	if (pci->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 		ret = platform_device_add_properties(pdev, role_switch_props);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 		if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 			dev_err(dev, "failed to register device properties\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 			platform_device_put(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	pdev->dev.parent = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	ret = platform_device_add(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 		dev_err(dev, "couldn't register intel_xhci_usb_sw pdev\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 		platform_device_put(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	ret = devm_add_action_or_reset(dev, xhci_intel_unregister_pdev, pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 		dev_err(dev, "couldn't add unregister action for intel_xhci_usb_sw pdev\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) int xhci_ext_cap_init(struct xhci_hcd *xhci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	void __iomem *base = &xhci->cap_regs->hc_capbase;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	u32 offset, val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	offset = xhci_find_next_ext_cap(base, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	while (offset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 		val = readl(base + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 		switch (XHCI_EXT_CAPS_ID(val)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 		case XHCI_EXT_CAPS_VENDOR_INTEL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 			if (xhci->quirks & XHCI_INTEL_USB_ROLE_SW) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 				ret = xhci_create_intel_xhci_sw_pdev(xhci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 								     offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 				if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 					return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 		offset = xhci_find_next_ext_cap(base, offset, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) EXPORT_SYMBOL_GPL(xhci_ext_cap_init);