18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * PCI Endpoint *Controller* (EPC) library
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2017 Texas Instruments
68c2ecf20Sopenharmony_ci * Author: Kishon Vijay Abraham I <kishon@ti.com>
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include <linux/device.h>
108c2ecf20Sopenharmony_ci#include <linux/slab.h>
118c2ecf20Sopenharmony_ci#include <linux/module.h>
128c2ecf20Sopenharmony_ci#include <linux/of_device.h>
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#include <linux/pci-epc.h>
158c2ecf20Sopenharmony_ci#include <linux/pci-epf.h>
168c2ecf20Sopenharmony_ci#include <linux/pci-ep-cfs.h>
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_cistatic struct class *pci_epc_class;
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_cistatic void devm_pci_epc_release(struct device *dev, void *res)
218c2ecf20Sopenharmony_ci{
228c2ecf20Sopenharmony_ci	struct pci_epc *epc = *(struct pci_epc **)res;
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci	pci_epc_destroy(epc);
258c2ecf20Sopenharmony_ci}
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_cistatic int devm_pci_epc_match(struct device *dev, void *res, void *match_data)
288c2ecf20Sopenharmony_ci{
298c2ecf20Sopenharmony_ci	struct pci_epc **epc = res;
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci	return *epc == match_data;
328c2ecf20Sopenharmony_ci}
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci/**
358c2ecf20Sopenharmony_ci * pci_epc_put() - release the PCI endpoint controller
368c2ecf20Sopenharmony_ci * @epc: epc returned by pci_epc_get()
378c2ecf20Sopenharmony_ci *
388c2ecf20Sopenharmony_ci * release the refcount the caller obtained by invoking pci_epc_get()
398c2ecf20Sopenharmony_ci */
408c2ecf20Sopenharmony_civoid pci_epc_put(struct pci_epc *epc)
418c2ecf20Sopenharmony_ci{
428c2ecf20Sopenharmony_ci	if (!epc || IS_ERR(epc))
438c2ecf20Sopenharmony_ci		return;
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci	module_put(epc->ops->owner);
468c2ecf20Sopenharmony_ci	put_device(&epc->dev);
478c2ecf20Sopenharmony_ci}
488c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_epc_put);
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci/**
518c2ecf20Sopenharmony_ci * pci_epc_get() - get the PCI endpoint controller
528c2ecf20Sopenharmony_ci * @epc_name: device name of the endpoint controller
538c2ecf20Sopenharmony_ci *
548c2ecf20Sopenharmony_ci * Invoke to get struct pci_epc * corresponding to the device name of the
558c2ecf20Sopenharmony_ci * endpoint controller
568c2ecf20Sopenharmony_ci */
578c2ecf20Sopenharmony_cistruct pci_epc *pci_epc_get(const char *epc_name)
588c2ecf20Sopenharmony_ci{
598c2ecf20Sopenharmony_ci	int ret = -EINVAL;
608c2ecf20Sopenharmony_ci	struct pci_epc *epc;
618c2ecf20Sopenharmony_ci	struct device *dev;
628c2ecf20Sopenharmony_ci	struct class_dev_iter iter;
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci	class_dev_iter_init(&iter, pci_epc_class, NULL, NULL);
658c2ecf20Sopenharmony_ci	while ((dev = class_dev_iter_next(&iter))) {
668c2ecf20Sopenharmony_ci		if (strcmp(epc_name, dev_name(dev)))
678c2ecf20Sopenharmony_ci			continue;
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci		epc = to_pci_epc(dev);
708c2ecf20Sopenharmony_ci		if (!try_module_get(epc->ops->owner)) {
718c2ecf20Sopenharmony_ci			ret = -EINVAL;
728c2ecf20Sopenharmony_ci			goto err;
738c2ecf20Sopenharmony_ci		}
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci		class_dev_iter_exit(&iter);
768c2ecf20Sopenharmony_ci		get_device(&epc->dev);
778c2ecf20Sopenharmony_ci		return epc;
788c2ecf20Sopenharmony_ci	}
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_cierr:
818c2ecf20Sopenharmony_ci	class_dev_iter_exit(&iter);
828c2ecf20Sopenharmony_ci	return ERR_PTR(ret);
838c2ecf20Sopenharmony_ci}
848c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_epc_get);
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci/**
878c2ecf20Sopenharmony_ci * pci_epc_get_first_free_bar() - helper to get first unreserved BAR
888c2ecf20Sopenharmony_ci * @epc_features: pci_epc_features structure that holds the reserved bar bitmap
898c2ecf20Sopenharmony_ci *
908c2ecf20Sopenharmony_ci * Invoke to get the first unreserved BAR that can be used by the endpoint
918c2ecf20Sopenharmony_ci * function. For any incorrect value in reserved_bar return '0'.
928c2ecf20Sopenharmony_ci */
938c2ecf20Sopenharmony_cienum pci_barno
948c2ecf20Sopenharmony_cipci_epc_get_first_free_bar(const struct pci_epc_features *epc_features)
958c2ecf20Sopenharmony_ci{
968c2ecf20Sopenharmony_ci	return pci_epc_get_next_free_bar(epc_features, BAR_0);
978c2ecf20Sopenharmony_ci}
988c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_epc_get_first_free_bar);
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci/**
1018c2ecf20Sopenharmony_ci * pci_epc_get_next_free_bar() - helper to get unreserved BAR starting from @bar
1028c2ecf20Sopenharmony_ci * @epc_features: pci_epc_features structure that holds the reserved bar bitmap
1038c2ecf20Sopenharmony_ci * @bar: the starting BAR number from where unreserved BAR should be searched
1048c2ecf20Sopenharmony_ci *
1058c2ecf20Sopenharmony_ci * Invoke to get the next unreserved BAR starting from @bar that can be used
1068c2ecf20Sopenharmony_ci * for endpoint function. For any incorrect value in reserved_bar return '0'.
1078c2ecf20Sopenharmony_ci */
1088c2ecf20Sopenharmony_cienum pci_barno pci_epc_get_next_free_bar(const struct pci_epc_features
1098c2ecf20Sopenharmony_ci					 *epc_features, enum pci_barno bar)
1108c2ecf20Sopenharmony_ci{
1118c2ecf20Sopenharmony_ci	unsigned long free_bar;
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ci	if (!epc_features)
1148c2ecf20Sopenharmony_ci		return BAR_0;
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci	/* If 'bar - 1' is a 64-bit BAR, move to the next BAR */
1178c2ecf20Sopenharmony_ci	if ((epc_features->bar_fixed_64bit << 1) & 1 << bar)
1188c2ecf20Sopenharmony_ci		bar++;
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci	/* Find if the reserved BAR is also a 64-bit BAR */
1218c2ecf20Sopenharmony_ci	free_bar = epc_features->reserved_bar & epc_features->bar_fixed_64bit;
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci	/* Set the adjacent bit if the reserved BAR is also a 64-bit BAR */
1248c2ecf20Sopenharmony_ci	free_bar <<= 1;
1258c2ecf20Sopenharmony_ci	free_bar |= epc_features->reserved_bar;
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci	free_bar = find_next_zero_bit(&free_bar, 6, bar);
1288c2ecf20Sopenharmony_ci	if (free_bar > 5)
1298c2ecf20Sopenharmony_ci		return NO_BAR;
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci	return free_bar;
1328c2ecf20Sopenharmony_ci}
1338c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_epc_get_next_free_bar);
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_ci/**
1368c2ecf20Sopenharmony_ci * pci_epc_get_features() - get the features supported by EPC
1378c2ecf20Sopenharmony_ci * @epc: the features supported by *this* EPC device will be returned
1388c2ecf20Sopenharmony_ci * @func_no: the features supported by the EPC device specific to the
1398c2ecf20Sopenharmony_ci *	     endpoint function with func_no will be returned
1408c2ecf20Sopenharmony_ci *
1418c2ecf20Sopenharmony_ci * Invoke to get the features provided by the EPC which may be
1428c2ecf20Sopenharmony_ci * specific to an endpoint function. Returns pci_epc_features on success
1438c2ecf20Sopenharmony_ci * and NULL for any failures.
1448c2ecf20Sopenharmony_ci */
1458c2ecf20Sopenharmony_ciconst struct pci_epc_features *pci_epc_get_features(struct pci_epc *epc,
1468c2ecf20Sopenharmony_ci						    u8 func_no)
1478c2ecf20Sopenharmony_ci{
1488c2ecf20Sopenharmony_ci	const struct pci_epc_features *epc_features;
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci	if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions)
1518c2ecf20Sopenharmony_ci		return NULL;
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_ci	if (!epc->ops->get_features)
1548c2ecf20Sopenharmony_ci		return NULL;
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_ci	mutex_lock(&epc->lock);
1578c2ecf20Sopenharmony_ci	epc_features = epc->ops->get_features(epc, func_no);
1588c2ecf20Sopenharmony_ci	mutex_unlock(&epc->lock);
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ci	return epc_features;
1618c2ecf20Sopenharmony_ci}
1628c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_epc_get_features);
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_ci/**
1658c2ecf20Sopenharmony_ci * pci_epc_stop() - stop the PCI link
1668c2ecf20Sopenharmony_ci * @epc: the link of the EPC device that has to be stopped
1678c2ecf20Sopenharmony_ci *
1688c2ecf20Sopenharmony_ci * Invoke to stop the PCI link
1698c2ecf20Sopenharmony_ci */
1708c2ecf20Sopenharmony_civoid pci_epc_stop(struct pci_epc *epc)
1718c2ecf20Sopenharmony_ci{
1728c2ecf20Sopenharmony_ci	if (IS_ERR(epc) || !epc->ops->stop)
1738c2ecf20Sopenharmony_ci		return;
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ci	mutex_lock(&epc->lock);
1768c2ecf20Sopenharmony_ci	epc->ops->stop(epc);
1778c2ecf20Sopenharmony_ci	mutex_unlock(&epc->lock);
1788c2ecf20Sopenharmony_ci}
1798c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_epc_stop);
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_ci/**
1828c2ecf20Sopenharmony_ci * pci_epc_start() - start the PCI link
1838c2ecf20Sopenharmony_ci * @epc: the link of *this* EPC device has to be started
1848c2ecf20Sopenharmony_ci *
1858c2ecf20Sopenharmony_ci * Invoke to start the PCI link
1868c2ecf20Sopenharmony_ci */
1878c2ecf20Sopenharmony_ciint pci_epc_start(struct pci_epc *epc)
1888c2ecf20Sopenharmony_ci{
1898c2ecf20Sopenharmony_ci	int ret;
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci	if (IS_ERR(epc))
1928c2ecf20Sopenharmony_ci		return -EINVAL;
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ci	if (!epc->ops->start)
1958c2ecf20Sopenharmony_ci		return 0;
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_ci	mutex_lock(&epc->lock);
1988c2ecf20Sopenharmony_ci	ret = epc->ops->start(epc);
1998c2ecf20Sopenharmony_ci	mutex_unlock(&epc->lock);
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_ci	return ret;
2028c2ecf20Sopenharmony_ci}
2038c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_epc_start);
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_ci/**
2068c2ecf20Sopenharmony_ci * pci_epc_raise_irq() - interrupt the host system
2078c2ecf20Sopenharmony_ci * @epc: the EPC device which has to interrupt the host
2088c2ecf20Sopenharmony_ci * @func_no: the endpoint function number in the EPC device
2098c2ecf20Sopenharmony_ci * @type: specify the type of interrupt; legacy, MSI or MSI-X
2108c2ecf20Sopenharmony_ci * @interrupt_num: the MSI or MSI-X interrupt number
2118c2ecf20Sopenharmony_ci *
2128c2ecf20Sopenharmony_ci * Invoke to raise an legacy, MSI or MSI-X interrupt
2138c2ecf20Sopenharmony_ci */
2148c2ecf20Sopenharmony_ciint pci_epc_raise_irq(struct pci_epc *epc, u8 func_no,
2158c2ecf20Sopenharmony_ci		      enum pci_epc_irq_type type, u16 interrupt_num)
2168c2ecf20Sopenharmony_ci{
2178c2ecf20Sopenharmony_ci	int ret;
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_ci	if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions)
2208c2ecf20Sopenharmony_ci		return -EINVAL;
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci	if (!epc->ops->raise_irq)
2238c2ecf20Sopenharmony_ci		return 0;
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ci	mutex_lock(&epc->lock);
2268c2ecf20Sopenharmony_ci	ret = epc->ops->raise_irq(epc, func_no, type, interrupt_num);
2278c2ecf20Sopenharmony_ci	mutex_unlock(&epc->lock);
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ci	return ret;
2308c2ecf20Sopenharmony_ci}
2318c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_epc_raise_irq);
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci/**
2348c2ecf20Sopenharmony_ci * pci_epc_get_msi() - get the number of MSI interrupt numbers allocated
2358c2ecf20Sopenharmony_ci * @epc: the EPC device to which MSI interrupts was requested
2368c2ecf20Sopenharmony_ci * @func_no: the endpoint function number in the EPC device
2378c2ecf20Sopenharmony_ci *
2388c2ecf20Sopenharmony_ci * Invoke to get the number of MSI interrupts allocated by the RC
2398c2ecf20Sopenharmony_ci */
2408c2ecf20Sopenharmony_ciint pci_epc_get_msi(struct pci_epc *epc, u8 func_no)
2418c2ecf20Sopenharmony_ci{
2428c2ecf20Sopenharmony_ci	int interrupt;
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci	if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions)
2458c2ecf20Sopenharmony_ci		return 0;
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci	if (!epc->ops->get_msi)
2488c2ecf20Sopenharmony_ci		return 0;
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	mutex_lock(&epc->lock);
2518c2ecf20Sopenharmony_ci	interrupt = epc->ops->get_msi(epc, func_no);
2528c2ecf20Sopenharmony_ci	mutex_unlock(&epc->lock);
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci	if (interrupt < 0)
2558c2ecf20Sopenharmony_ci		return 0;
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci	interrupt = 1 << interrupt;
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_ci	return interrupt;
2608c2ecf20Sopenharmony_ci}
2618c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_epc_get_msi);
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_ci/**
2648c2ecf20Sopenharmony_ci * pci_epc_set_msi() - set the number of MSI interrupt numbers required
2658c2ecf20Sopenharmony_ci * @epc: the EPC device on which MSI has to be configured
2668c2ecf20Sopenharmony_ci * @func_no: the endpoint function number in the EPC device
2678c2ecf20Sopenharmony_ci * @interrupts: number of MSI interrupts required by the EPF
2688c2ecf20Sopenharmony_ci *
2698c2ecf20Sopenharmony_ci * Invoke to set the required number of MSI interrupts.
2708c2ecf20Sopenharmony_ci */
2718c2ecf20Sopenharmony_ciint pci_epc_set_msi(struct pci_epc *epc, u8 func_no, u8 interrupts)
2728c2ecf20Sopenharmony_ci{
2738c2ecf20Sopenharmony_ci	int ret;
2748c2ecf20Sopenharmony_ci	u8 encode_int;
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci	if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions ||
2778c2ecf20Sopenharmony_ci	    interrupts > 32)
2788c2ecf20Sopenharmony_ci		return -EINVAL;
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_ci	if (!epc->ops->set_msi)
2818c2ecf20Sopenharmony_ci		return 0;
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_ci	encode_int = order_base_2(interrupts);
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_ci	mutex_lock(&epc->lock);
2868c2ecf20Sopenharmony_ci	ret = epc->ops->set_msi(epc, func_no, encode_int);
2878c2ecf20Sopenharmony_ci	mutex_unlock(&epc->lock);
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_ci	return ret;
2908c2ecf20Sopenharmony_ci}
2918c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_epc_set_msi);
2928c2ecf20Sopenharmony_ci
2938c2ecf20Sopenharmony_ci/**
2948c2ecf20Sopenharmony_ci * pci_epc_get_msix() - get the number of MSI-X interrupt numbers allocated
2958c2ecf20Sopenharmony_ci * @epc: the EPC device to which MSI-X interrupts was requested
2968c2ecf20Sopenharmony_ci * @func_no: the endpoint function number in the EPC device
2978c2ecf20Sopenharmony_ci *
2988c2ecf20Sopenharmony_ci * Invoke to get the number of MSI-X interrupts allocated by the RC
2998c2ecf20Sopenharmony_ci */
3008c2ecf20Sopenharmony_ciint pci_epc_get_msix(struct pci_epc *epc, u8 func_no)
3018c2ecf20Sopenharmony_ci{
3028c2ecf20Sopenharmony_ci	int interrupt;
3038c2ecf20Sopenharmony_ci
3048c2ecf20Sopenharmony_ci	if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions)
3058c2ecf20Sopenharmony_ci		return 0;
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ci	if (!epc->ops->get_msix)
3088c2ecf20Sopenharmony_ci		return 0;
3098c2ecf20Sopenharmony_ci
3108c2ecf20Sopenharmony_ci	mutex_lock(&epc->lock);
3118c2ecf20Sopenharmony_ci	interrupt = epc->ops->get_msix(epc, func_no);
3128c2ecf20Sopenharmony_ci	mutex_unlock(&epc->lock);
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_ci	if (interrupt < 0)
3158c2ecf20Sopenharmony_ci		return 0;
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci	return interrupt + 1;
3188c2ecf20Sopenharmony_ci}
3198c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_epc_get_msix);
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_ci/**
3228c2ecf20Sopenharmony_ci * pci_epc_set_msix() - set the number of MSI-X interrupt numbers required
3238c2ecf20Sopenharmony_ci * @epc: the EPC device on which MSI-X has to be configured
3248c2ecf20Sopenharmony_ci * @func_no: the endpoint function number in the EPC device
3258c2ecf20Sopenharmony_ci * @interrupts: number of MSI-X interrupts required by the EPF
3268c2ecf20Sopenharmony_ci * @bir: BAR where the MSI-X table resides
3278c2ecf20Sopenharmony_ci * @offset: Offset pointing to the start of MSI-X table
3288c2ecf20Sopenharmony_ci *
3298c2ecf20Sopenharmony_ci * Invoke to set the required number of MSI-X interrupts.
3308c2ecf20Sopenharmony_ci */
3318c2ecf20Sopenharmony_ciint pci_epc_set_msix(struct pci_epc *epc, u8 func_no, u16 interrupts,
3328c2ecf20Sopenharmony_ci		     enum pci_barno bir, u32 offset)
3338c2ecf20Sopenharmony_ci{
3348c2ecf20Sopenharmony_ci	int ret;
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_ci	if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions ||
3378c2ecf20Sopenharmony_ci	    interrupts < 1 || interrupts > 2048)
3388c2ecf20Sopenharmony_ci		return -EINVAL;
3398c2ecf20Sopenharmony_ci
3408c2ecf20Sopenharmony_ci	if (!epc->ops->set_msix)
3418c2ecf20Sopenharmony_ci		return 0;
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_ci	mutex_lock(&epc->lock);
3448c2ecf20Sopenharmony_ci	ret = epc->ops->set_msix(epc, func_no, interrupts - 1, bir, offset);
3458c2ecf20Sopenharmony_ci	mutex_unlock(&epc->lock);
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_ci	return ret;
3488c2ecf20Sopenharmony_ci}
3498c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_epc_set_msix);
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_ci/**
3528c2ecf20Sopenharmony_ci * pci_epc_unmap_addr() - unmap CPU address from PCI address
3538c2ecf20Sopenharmony_ci * @epc: the EPC device on which address is allocated
3548c2ecf20Sopenharmony_ci * @func_no: the endpoint function number in the EPC device
3558c2ecf20Sopenharmony_ci * @phys_addr: physical address of the local system
3568c2ecf20Sopenharmony_ci *
3578c2ecf20Sopenharmony_ci * Invoke to unmap the CPU address from PCI address.
3588c2ecf20Sopenharmony_ci */
3598c2ecf20Sopenharmony_civoid pci_epc_unmap_addr(struct pci_epc *epc, u8 func_no,
3608c2ecf20Sopenharmony_ci			phys_addr_t phys_addr)
3618c2ecf20Sopenharmony_ci{
3628c2ecf20Sopenharmony_ci	if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions)
3638c2ecf20Sopenharmony_ci		return;
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_ci	if (!epc->ops->unmap_addr)
3668c2ecf20Sopenharmony_ci		return;
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_ci	mutex_lock(&epc->lock);
3698c2ecf20Sopenharmony_ci	epc->ops->unmap_addr(epc, func_no, phys_addr);
3708c2ecf20Sopenharmony_ci	mutex_unlock(&epc->lock);
3718c2ecf20Sopenharmony_ci}
3728c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_epc_unmap_addr);
3738c2ecf20Sopenharmony_ci
3748c2ecf20Sopenharmony_ci/**
3758c2ecf20Sopenharmony_ci * pci_epc_map_addr() - map CPU address to PCI address
3768c2ecf20Sopenharmony_ci * @epc: the EPC device on which address is allocated
3778c2ecf20Sopenharmony_ci * @func_no: the endpoint function number in the EPC device
3788c2ecf20Sopenharmony_ci * @phys_addr: physical address of the local system
3798c2ecf20Sopenharmony_ci * @pci_addr: PCI address to which the physical address should be mapped
3808c2ecf20Sopenharmony_ci * @size: the size of the allocation
3818c2ecf20Sopenharmony_ci *
3828c2ecf20Sopenharmony_ci * Invoke to map CPU address with PCI address.
3838c2ecf20Sopenharmony_ci */
3848c2ecf20Sopenharmony_ciint pci_epc_map_addr(struct pci_epc *epc, u8 func_no,
3858c2ecf20Sopenharmony_ci		     phys_addr_t phys_addr, u64 pci_addr, size_t size)
3868c2ecf20Sopenharmony_ci{
3878c2ecf20Sopenharmony_ci	int ret;
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_ci	if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions)
3908c2ecf20Sopenharmony_ci		return -EINVAL;
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_ci	if (!epc->ops->map_addr)
3938c2ecf20Sopenharmony_ci		return 0;
3948c2ecf20Sopenharmony_ci
3958c2ecf20Sopenharmony_ci	mutex_lock(&epc->lock);
3968c2ecf20Sopenharmony_ci	ret = epc->ops->map_addr(epc, func_no, phys_addr, pci_addr, size);
3978c2ecf20Sopenharmony_ci	mutex_unlock(&epc->lock);
3988c2ecf20Sopenharmony_ci
3998c2ecf20Sopenharmony_ci	return ret;
4008c2ecf20Sopenharmony_ci}
4018c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_epc_map_addr);
4028c2ecf20Sopenharmony_ci
4038c2ecf20Sopenharmony_ci/**
4048c2ecf20Sopenharmony_ci * pci_epc_clear_bar() - reset the BAR
4058c2ecf20Sopenharmony_ci * @epc: the EPC device for which the BAR has to be cleared
4068c2ecf20Sopenharmony_ci * @func_no: the endpoint function number in the EPC device
4078c2ecf20Sopenharmony_ci * @epf_bar: the struct epf_bar that contains the BAR information
4088c2ecf20Sopenharmony_ci *
4098c2ecf20Sopenharmony_ci * Invoke to reset the BAR of the endpoint device.
4108c2ecf20Sopenharmony_ci */
4118c2ecf20Sopenharmony_civoid pci_epc_clear_bar(struct pci_epc *epc, u8 func_no,
4128c2ecf20Sopenharmony_ci		       struct pci_epf_bar *epf_bar)
4138c2ecf20Sopenharmony_ci{
4148c2ecf20Sopenharmony_ci	if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions ||
4158c2ecf20Sopenharmony_ci	    (epf_bar->barno == BAR_5 &&
4168c2ecf20Sopenharmony_ci	     epf_bar->flags & PCI_BASE_ADDRESS_MEM_TYPE_64))
4178c2ecf20Sopenharmony_ci		return;
4188c2ecf20Sopenharmony_ci
4198c2ecf20Sopenharmony_ci	if (!epc->ops->clear_bar)
4208c2ecf20Sopenharmony_ci		return;
4218c2ecf20Sopenharmony_ci
4228c2ecf20Sopenharmony_ci	mutex_lock(&epc->lock);
4238c2ecf20Sopenharmony_ci	epc->ops->clear_bar(epc, func_no, epf_bar);
4248c2ecf20Sopenharmony_ci	mutex_unlock(&epc->lock);
4258c2ecf20Sopenharmony_ci}
4268c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_epc_clear_bar);
4278c2ecf20Sopenharmony_ci
4288c2ecf20Sopenharmony_ci/**
4298c2ecf20Sopenharmony_ci * pci_epc_set_bar() - configure BAR in order for host to assign PCI addr space
4308c2ecf20Sopenharmony_ci * @epc: the EPC device on which BAR has to be configured
4318c2ecf20Sopenharmony_ci * @func_no: the endpoint function number in the EPC device
4328c2ecf20Sopenharmony_ci * @epf_bar: the struct epf_bar that contains the BAR information
4338c2ecf20Sopenharmony_ci *
4348c2ecf20Sopenharmony_ci * Invoke to configure the BAR of the endpoint device.
4358c2ecf20Sopenharmony_ci */
4368c2ecf20Sopenharmony_ciint pci_epc_set_bar(struct pci_epc *epc, u8 func_no,
4378c2ecf20Sopenharmony_ci		    struct pci_epf_bar *epf_bar)
4388c2ecf20Sopenharmony_ci{
4398c2ecf20Sopenharmony_ci	int ret;
4408c2ecf20Sopenharmony_ci	int flags = epf_bar->flags;
4418c2ecf20Sopenharmony_ci
4428c2ecf20Sopenharmony_ci	if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions ||
4438c2ecf20Sopenharmony_ci	    (epf_bar->barno == BAR_5 &&
4448c2ecf20Sopenharmony_ci	     flags & PCI_BASE_ADDRESS_MEM_TYPE_64) ||
4458c2ecf20Sopenharmony_ci	    (flags & PCI_BASE_ADDRESS_SPACE_IO &&
4468c2ecf20Sopenharmony_ci	     flags & PCI_BASE_ADDRESS_IO_MASK) ||
4478c2ecf20Sopenharmony_ci	    (upper_32_bits(epf_bar->size) &&
4488c2ecf20Sopenharmony_ci	     !(flags & PCI_BASE_ADDRESS_MEM_TYPE_64)))
4498c2ecf20Sopenharmony_ci		return -EINVAL;
4508c2ecf20Sopenharmony_ci
4518c2ecf20Sopenharmony_ci	if (!epc->ops->set_bar)
4528c2ecf20Sopenharmony_ci		return 0;
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_ci	mutex_lock(&epc->lock);
4558c2ecf20Sopenharmony_ci	ret = epc->ops->set_bar(epc, func_no, epf_bar);
4568c2ecf20Sopenharmony_ci	mutex_unlock(&epc->lock);
4578c2ecf20Sopenharmony_ci
4588c2ecf20Sopenharmony_ci	return ret;
4598c2ecf20Sopenharmony_ci}
4608c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_epc_set_bar);
4618c2ecf20Sopenharmony_ci
4628c2ecf20Sopenharmony_ci/**
4638c2ecf20Sopenharmony_ci * pci_epc_write_header() - write standard configuration header
4648c2ecf20Sopenharmony_ci * @epc: the EPC device to which the configuration header should be written
4658c2ecf20Sopenharmony_ci * @func_no: the endpoint function number in the EPC device
4668c2ecf20Sopenharmony_ci * @header: standard configuration header fields
4678c2ecf20Sopenharmony_ci *
4688c2ecf20Sopenharmony_ci * Invoke to write the configuration header to the endpoint controller. Every
4698c2ecf20Sopenharmony_ci * endpoint controller will have a dedicated location to which the standard
4708c2ecf20Sopenharmony_ci * configuration header would be written. The callback function should write
4718c2ecf20Sopenharmony_ci * the header fields to this dedicated location.
4728c2ecf20Sopenharmony_ci */
4738c2ecf20Sopenharmony_ciint pci_epc_write_header(struct pci_epc *epc, u8 func_no,
4748c2ecf20Sopenharmony_ci			 struct pci_epf_header *header)
4758c2ecf20Sopenharmony_ci{
4768c2ecf20Sopenharmony_ci	int ret;
4778c2ecf20Sopenharmony_ci
4788c2ecf20Sopenharmony_ci	if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions)
4798c2ecf20Sopenharmony_ci		return -EINVAL;
4808c2ecf20Sopenharmony_ci
4818c2ecf20Sopenharmony_ci	if (!epc->ops->write_header)
4828c2ecf20Sopenharmony_ci		return 0;
4838c2ecf20Sopenharmony_ci
4848c2ecf20Sopenharmony_ci	mutex_lock(&epc->lock);
4858c2ecf20Sopenharmony_ci	ret = epc->ops->write_header(epc, func_no, header);
4868c2ecf20Sopenharmony_ci	mutex_unlock(&epc->lock);
4878c2ecf20Sopenharmony_ci
4888c2ecf20Sopenharmony_ci	return ret;
4898c2ecf20Sopenharmony_ci}
4908c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_epc_write_header);
4918c2ecf20Sopenharmony_ci
4928c2ecf20Sopenharmony_ci/**
4938c2ecf20Sopenharmony_ci * pci_epc_add_epf() - bind PCI endpoint function to an endpoint controller
4948c2ecf20Sopenharmony_ci * @epc: the EPC device to which the endpoint function should be added
4958c2ecf20Sopenharmony_ci * @epf: the endpoint function to be added
4968c2ecf20Sopenharmony_ci *
4978c2ecf20Sopenharmony_ci * A PCI endpoint device can have one or more functions. In the case of PCIe,
4988c2ecf20Sopenharmony_ci * the specification allows up to 8 PCIe endpoint functions. Invoke
4998c2ecf20Sopenharmony_ci * pci_epc_add_epf() to add a PCI endpoint function to an endpoint controller.
5008c2ecf20Sopenharmony_ci */
5018c2ecf20Sopenharmony_ciint pci_epc_add_epf(struct pci_epc *epc, struct pci_epf *epf)
5028c2ecf20Sopenharmony_ci{
5038c2ecf20Sopenharmony_ci	u32 func_no;
5048c2ecf20Sopenharmony_ci	int ret = 0;
5058c2ecf20Sopenharmony_ci
5068c2ecf20Sopenharmony_ci	if (epf->epc)
5078c2ecf20Sopenharmony_ci		return -EBUSY;
5088c2ecf20Sopenharmony_ci
5098c2ecf20Sopenharmony_ci	if (IS_ERR(epc))
5108c2ecf20Sopenharmony_ci		return -EINVAL;
5118c2ecf20Sopenharmony_ci
5128c2ecf20Sopenharmony_ci	mutex_lock(&epc->lock);
5138c2ecf20Sopenharmony_ci	func_no = find_first_zero_bit(&epc->function_num_map,
5148c2ecf20Sopenharmony_ci				      BITS_PER_LONG);
5158c2ecf20Sopenharmony_ci	if (func_no >= BITS_PER_LONG) {
5168c2ecf20Sopenharmony_ci		ret = -EINVAL;
5178c2ecf20Sopenharmony_ci		goto ret;
5188c2ecf20Sopenharmony_ci	}
5198c2ecf20Sopenharmony_ci
5208c2ecf20Sopenharmony_ci	if (func_no > epc->max_functions - 1) {
5218c2ecf20Sopenharmony_ci		dev_err(&epc->dev, "Exceeding max supported Function Number\n");
5228c2ecf20Sopenharmony_ci		ret = -EINVAL;
5238c2ecf20Sopenharmony_ci		goto ret;
5248c2ecf20Sopenharmony_ci	}
5258c2ecf20Sopenharmony_ci
5268c2ecf20Sopenharmony_ci	set_bit(func_no, &epc->function_num_map);
5278c2ecf20Sopenharmony_ci	epf->func_no = func_no;
5288c2ecf20Sopenharmony_ci	epf->epc = epc;
5298c2ecf20Sopenharmony_ci
5308c2ecf20Sopenharmony_ci	list_add_tail(&epf->list, &epc->pci_epf);
5318c2ecf20Sopenharmony_ci
5328c2ecf20Sopenharmony_ciret:
5338c2ecf20Sopenharmony_ci	mutex_unlock(&epc->lock);
5348c2ecf20Sopenharmony_ci
5358c2ecf20Sopenharmony_ci	return ret;
5368c2ecf20Sopenharmony_ci}
5378c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_epc_add_epf);
5388c2ecf20Sopenharmony_ci
5398c2ecf20Sopenharmony_ci/**
5408c2ecf20Sopenharmony_ci * pci_epc_remove_epf() - remove PCI endpoint function from endpoint controller
5418c2ecf20Sopenharmony_ci * @epc: the EPC device from which the endpoint function should be removed
5428c2ecf20Sopenharmony_ci * @epf: the endpoint function to be removed
5438c2ecf20Sopenharmony_ci *
5448c2ecf20Sopenharmony_ci * Invoke to remove PCI endpoint function from the endpoint controller.
5458c2ecf20Sopenharmony_ci */
5468c2ecf20Sopenharmony_civoid pci_epc_remove_epf(struct pci_epc *epc, struct pci_epf *epf)
5478c2ecf20Sopenharmony_ci{
5488c2ecf20Sopenharmony_ci	if (!epc || IS_ERR(epc) || !epf)
5498c2ecf20Sopenharmony_ci		return;
5508c2ecf20Sopenharmony_ci
5518c2ecf20Sopenharmony_ci	mutex_lock(&epc->lock);
5528c2ecf20Sopenharmony_ci	clear_bit(epf->func_no, &epc->function_num_map);
5538c2ecf20Sopenharmony_ci	list_del(&epf->list);
5548c2ecf20Sopenharmony_ci	epf->epc = NULL;
5558c2ecf20Sopenharmony_ci	mutex_unlock(&epc->lock);
5568c2ecf20Sopenharmony_ci}
5578c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_epc_remove_epf);
5588c2ecf20Sopenharmony_ci
5598c2ecf20Sopenharmony_ci/**
5608c2ecf20Sopenharmony_ci * pci_epc_linkup() - Notify the EPF device that EPC device has established a
5618c2ecf20Sopenharmony_ci *		      connection with the Root Complex.
5628c2ecf20Sopenharmony_ci * @epc: the EPC device which has established link with the host
5638c2ecf20Sopenharmony_ci *
5648c2ecf20Sopenharmony_ci * Invoke to Notify the EPF device that the EPC device has established a
5658c2ecf20Sopenharmony_ci * connection with the Root Complex.
5668c2ecf20Sopenharmony_ci */
5678c2ecf20Sopenharmony_civoid pci_epc_linkup(struct pci_epc *epc)
5688c2ecf20Sopenharmony_ci{
5698c2ecf20Sopenharmony_ci	if (!epc || IS_ERR(epc))
5708c2ecf20Sopenharmony_ci		return;
5718c2ecf20Sopenharmony_ci
5728c2ecf20Sopenharmony_ci	atomic_notifier_call_chain(&epc->notifier, LINK_UP, NULL);
5738c2ecf20Sopenharmony_ci}
5748c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_epc_linkup);
5758c2ecf20Sopenharmony_ci
5768c2ecf20Sopenharmony_ci/**
5778c2ecf20Sopenharmony_ci * pci_epc_init_notify() - Notify the EPF device that EPC device's core
5788c2ecf20Sopenharmony_ci *			   initialization is completed.
5798c2ecf20Sopenharmony_ci * @epc: the EPC device whose core initialization is completeds
5808c2ecf20Sopenharmony_ci *
5818c2ecf20Sopenharmony_ci * Invoke to Notify the EPF device that the EPC device's initialization
5828c2ecf20Sopenharmony_ci * is completed.
5838c2ecf20Sopenharmony_ci */
5848c2ecf20Sopenharmony_civoid pci_epc_init_notify(struct pci_epc *epc)
5858c2ecf20Sopenharmony_ci{
5868c2ecf20Sopenharmony_ci	if (!epc || IS_ERR(epc))
5878c2ecf20Sopenharmony_ci		return;
5888c2ecf20Sopenharmony_ci
5898c2ecf20Sopenharmony_ci	atomic_notifier_call_chain(&epc->notifier, CORE_INIT, NULL);
5908c2ecf20Sopenharmony_ci}
5918c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_epc_init_notify);
5928c2ecf20Sopenharmony_ci
5938c2ecf20Sopenharmony_ci/**
5948c2ecf20Sopenharmony_ci * pci_epc_destroy() - destroy the EPC device
5958c2ecf20Sopenharmony_ci * @epc: the EPC device that has to be destroyed
5968c2ecf20Sopenharmony_ci *
5978c2ecf20Sopenharmony_ci * Invoke to destroy the PCI EPC device
5988c2ecf20Sopenharmony_ci */
5998c2ecf20Sopenharmony_civoid pci_epc_destroy(struct pci_epc *epc)
6008c2ecf20Sopenharmony_ci{
6018c2ecf20Sopenharmony_ci	pci_ep_cfs_remove_epc_group(epc->group);
6028c2ecf20Sopenharmony_ci	device_unregister(&epc->dev);
6038c2ecf20Sopenharmony_ci	kfree(epc);
6048c2ecf20Sopenharmony_ci}
6058c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_epc_destroy);
6068c2ecf20Sopenharmony_ci
6078c2ecf20Sopenharmony_ci/**
6088c2ecf20Sopenharmony_ci * devm_pci_epc_destroy() - destroy the EPC device
6098c2ecf20Sopenharmony_ci * @dev: device that wants to destroy the EPC
6108c2ecf20Sopenharmony_ci * @epc: the EPC device that has to be destroyed
6118c2ecf20Sopenharmony_ci *
6128c2ecf20Sopenharmony_ci * Invoke to destroy the devres associated with this
6138c2ecf20Sopenharmony_ci * pci_epc and destroy the EPC device.
6148c2ecf20Sopenharmony_ci */
6158c2ecf20Sopenharmony_civoid devm_pci_epc_destroy(struct device *dev, struct pci_epc *epc)
6168c2ecf20Sopenharmony_ci{
6178c2ecf20Sopenharmony_ci	int r;
6188c2ecf20Sopenharmony_ci
6198c2ecf20Sopenharmony_ci	r = devres_destroy(dev, devm_pci_epc_release, devm_pci_epc_match,
6208c2ecf20Sopenharmony_ci			   epc);
6218c2ecf20Sopenharmony_ci	dev_WARN_ONCE(dev, r, "couldn't find PCI EPC resource\n");
6228c2ecf20Sopenharmony_ci}
6238c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(devm_pci_epc_destroy);
6248c2ecf20Sopenharmony_ci
6258c2ecf20Sopenharmony_ci/**
6268c2ecf20Sopenharmony_ci * __pci_epc_create() - create a new endpoint controller (EPC) device
6278c2ecf20Sopenharmony_ci * @dev: device that is creating the new EPC
6288c2ecf20Sopenharmony_ci * @ops: function pointers for performing EPC operations
6298c2ecf20Sopenharmony_ci * @owner: the owner of the module that creates the EPC device
6308c2ecf20Sopenharmony_ci *
6318c2ecf20Sopenharmony_ci * Invoke to create a new EPC device and add it to pci_epc class.
6328c2ecf20Sopenharmony_ci */
6338c2ecf20Sopenharmony_cistruct pci_epc *
6348c2ecf20Sopenharmony_ci__pci_epc_create(struct device *dev, const struct pci_epc_ops *ops,
6358c2ecf20Sopenharmony_ci		 struct module *owner)
6368c2ecf20Sopenharmony_ci{
6378c2ecf20Sopenharmony_ci	int ret;
6388c2ecf20Sopenharmony_ci	struct pci_epc *epc;
6398c2ecf20Sopenharmony_ci
6408c2ecf20Sopenharmony_ci	if (WARN_ON(!dev)) {
6418c2ecf20Sopenharmony_ci		ret = -EINVAL;
6428c2ecf20Sopenharmony_ci		goto err_ret;
6438c2ecf20Sopenharmony_ci	}
6448c2ecf20Sopenharmony_ci
6458c2ecf20Sopenharmony_ci	epc = kzalloc(sizeof(*epc), GFP_KERNEL);
6468c2ecf20Sopenharmony_ci	if (!epc) {
6478c2ecf20Sopenharmony_ci		ret = -ENOMEM;
6488c2ecf20Sopenharmony_ci		goto err_ret;
6498c2ecf20Sopenharmony_ci	}
6508c2ecf20Sopenharmony_ci
6518c2ecf20Sopenharmony_ci	mutex_init(&epc->lock);
6528c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&epc->pci_epf);
6538c2ecf20Sopenharmony_ci	ATOMIC_INIT_NOTIFIER_HEAD(&epc->notifier);
6548c2ecf20Sopenharmony_ci
6558c2ecf20Sopenharmony_ci	device_initialize(&epc->dev);
6568c2ecf20Sopenharmony_ci	epc->dev.class = pci_epc_class;
6578c2ecf20Sopenharmony_ci	epc->dev.parent = dev;
6588c2ecf20Sopenharmony_ci	epc->ops = ops;
6598c2ecf20Sopenharmony_ci
6608c2ecf20Sopenharmony_ci	ret = dev_set_name(&epc->dev, "%s", dev_name(dev));
6618c2ecf20Sopenharmony_ci	if (ret)
6628c2ecf20Sopenharmony_ci		goto put_dev;
6638c2ecf20Sopenharmony_ci
6648c2ecf20Sopenharmony_ci	ret = device_add(&epc->dev);
6658c2ecf20Sopenharmony_ci	if (ret)
6668c2ecf20Sopenharmony_ci		goto put_dev;
6678c2ecf20Sopenharmony_ci
6688c2ecf20Sopenharmony_ci	epc->group = pci_ep_cfs_add_epc_group(dev_name(dev));
6698c2ecf20Sopenharmony_ci
6708c2ecf20Sopenharmony_ci	return epc;
6718c2ecf20Sopenharmony_ci
6728c2ecf20Sopenharmony_ciput_dev:
6738c2ecf20Sopenharmony_ci	put_device(&epc->dev);
6748c2ecf20Sopenharmony_ci	kfree(epc);
6758c2ecf20Sopenharmony_ci
6768c2ecf20Sopenharmony_cierr_ret:
6778c2ecf20Sopenharmony_ci	return ERR_PTR(ret);
6788c2ecf20Sopenharmony_ci}
6798c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(__pci_epc_create);
6808c2ecf20Sopenharmony_ci
6818c2ecf20Sopenharmony_ci/**
6828c2ecf20Sopenharmony_ci * __devm_pci_epc_create() - create a new endpoint controller (EPC) device
6838c2ecf20Sopenharmony_ci * @dev: device that is creating the new EPC
6848c2ecf20Sopenharmony_ci * @ops: function pointers for performing EPC operations
6858c2ecf20Sopenharmony_ci * @owner: the owner of the module that creates the EPC device
6868c2ecf20Sopenharmony_ci *
6878c2ecf20Sopenharmony_ci * Invoke to create a new EPC device and add it to pci_epc class.
6888c2ecf20Sopenharmony_ci * While at that, it also associates the device with the pci_epc using devres.
6898c2ecf20Sopenharmony_ci * On driver detach, release function is invoked on the devres data,
6908c2ecf20Sopenharmony_ci * then, devres data is freed.
6918c2ecf20Sopenharmony_ci */
6928c2ecf20Sopenharmony_cistruct pci_epc *
6938c2ecf20Sopenharmony_ci__devm_pci_epc_create(struct device *dev, const struct pci_epc_ops *ops,
6948c2ecf20Sopenharmony_ci		      struct module *owner)
6958c2ecf20Sopenharmony_ci{
6968c2ecf20Sopenharmony_ci	struct pci_epc **ptr, *epc;
6978c2ecf20Sopenharmony_ci
6988c2ecf20Sopenharmony_ci	ptr = devres_alloc(devm_pci_epc_release, sizeof(*ptr), GFP_KERNEL);
6998c2ecf20Sopenharmony_ci	if (!ptr)
7008c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
7018c2ecf20Sopenharmony_ci
7028c2ecf20Sopenharmony_ci	epc = __pci_epc_create(dev, ops, owner);
7038c2ecf20Sopenharmony_ci	if (!IS_ERR(epc)) {
7048c2ecf20Sopenharmony_ci		*ptr = epc;
7058c2ecf20Sopenharmony_ci		devres_add(dev, ptr);
7068c2ecf20Sopenharmony_ci	} else {
7078c2ecf20Sopenharmony_ci		devres_free(ptr);
7088c2ecf20Sopenharmony_ci	}
7098c2ecf20Sopenharmony_ci
7108c2ecf20Sopenharmony_ci	return epc;
7118c2ecf20Sopenharmony_ci}
7128c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(__devm_pci_epc_create);
7138c2ecf20Sopenharmony_ci
7148c2ecf20Sopenharmony_cistatic int __init pci_epc_init(void)
7158c2ecf20Sopenharmony_ci{
7168c2ecf20Sopenharmony_ci	pci_epc_class = class_create(THIS_MODULE, "pci_epc");
7178c2ecf20Sopenharmony_ci	if (IS_ERR(pci_epc_class)) {
7188c2ecf20Sopenharmony_ci		pr_err("failed to create pci epc class --> %ld\n",
7198c2ecf20Sopenharmony_ci		       PTR_ERR(pci_epc_class));
7208c2ecf20Sopenharmony_ci		return PTR_ERR(pci_epc_class);
7218c2ecf20Sopenharmony_ci	}
7228c2ecf20Sopenharmony_ci
7238c2ecf20Sopenharmony_ci	return 0;
7248c2ecf20Sopenharmony_ci}
7258c2ecf20Sopenharmony_cimodule_init(pci_epc_init);
7268c2ecf20Sopenharmony_ci
7278c2ecf20Sopenharmony_cistatic void __exit pci_epc_exit(void)
7288c2ecf20Sopenharmony_ci{
7298c2ecf20Sopenharmony_ci	class_destroy(pci_epc_class);
7308c2ecf20Sopenharmony_ci}
7318c2ecf20Sopenharmony_cimodule_exit(pci_epc_exit);
7328c2ecf20Sopenharmony_ci
7338c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("PCI EPC Library");
7348c2ecf20Sopenharmony_ciMODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");
7358c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2");
736