18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright 2014-2016 Freescale Semiconductor Inc. 48c2ecf20Sopenharmony_ci * Copyright NXP 2016 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/types.h> 98c2ecf20Sopenharmony_ci#include <linux/init.h> 108c2ecf20Sopenharmony_ci#include <linux/module.h> 118c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 128c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 138c2ecf20Sopenharmony_ci#include <linux/msi.h> 148c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h> 158c2ecf20Sopenharmony_ci#include <linux/delay.h> 168c2ecf20Sopenharmony_ci#include <linux/io.h> 178c2ecf20Sopenharmony_ci#include <linux/sys_soc.h> 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#include <linux/fsl/mc.h> 208c2ecf20Sopenharmony_ci#include <soc/fsl/dpaa2-io.h> 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci#include "qbman-portal.h" 238c2ecf20Sopenharmony_ci#include "dpio.h" 248c2ecf20Sopenharmony_ci#include "dpio-cmd.h" 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ciMODULE_LICENSE("Dual BSD/GPL"); 278c2ecf20Sopenharmony_ciMODULE_AUTHOR("Freescale Semiconductor, Inc"); 288c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("DPIO Driver"); 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_cistruct dpio_priv { 318c2ecf20Sopenharmony_ci struct dpaa2_io *io; 328c2ecf20Sopenharmony_ci}; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_cistatic cpumask_var_t cpus_unused_mask; 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_cistatic const struct soc_device_attribute ls1088a_soc[] = { 378c2ecf20Sopenharmony_ci {.family = "QorIQ LS1088A"}, 388c2ecf20Sopenharmony_ci { /* sentinel */ } 398c2ecf20Sopenharmony_ci}; 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_cistatic const struct soc_device_attribute ls2080a_soc[] = { 428c2ecf20Sopenharmony_ci {.family = "QorIQ LS2080A"}, 438c2ecf20Sopenharmony_ci { /* sentinel */ } 448c2ecf20Sopenharmony_ci}; 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_cistatic const struct soc_device_attribute ls2088a_soc[] = { 478c2ecf20Sopenharmony_ci {.family = "QorIQ LS2088A"}, 488c2ecf20Sopenharmony_ci { /* sentinel */ } 498c2ecf20Sopenharmony_ci}; 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_cistatic const struct soc_device_attribute lx2160a_soc[] = { 528c2ecf20Sopenharmony_ci {.family = "QorIQ LX2160A"}, 538c2ecf20Sopenharmony_ci { /* sentinel */ } 548c2ecf20Sopenharmony_ci}; 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_cistatic int dpaa2_dpio_get_cluster_sdest(struct fsl_mc_device *dpio_dev, int cpu) 578c2ecf20Sopenharmony_ci{ 588c2ecf20Sopenharmony_ci int cluster_base, cluster_size; 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci if (soc_device_match(ls1088a_soc)) { 618c2ecf20Sopenharmony_ci cluster_base = 2; 628c2ecf20Sopenharmony_ci cluster_size = 4; 638c2ecf20Sopenharmony_ci } else if (soc_device_match(ls2080a_soc) || 648c2ecf20Sopenharmony_ci soc_device_match(ls2088a_soc) || 658c2ecf20Sopenharmony_ci soc_device_match(lx2160a_soc)) { 668c2ecf20Sopenharmony_ci cluster_base = 0; 678c2ecf20Sopenharmony_ci cluster_size = 2; 688c2ecf20Sopenharmony_ci } else { 698c2ecf20Sopenharmony_ci dev_err(&dpio_dev->dev, "unknown SoC version\n"); 708c2ecf20Sopenharmony_ci return -1; 718c2ecf20Sopenharmony_ci } 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci return cluster_base + cpu / cluster_size; 748c2ecf20Sopenharmony_ci} 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_cistatic irqreturn_t dpio_irq_handler(int irq_num, void *arg) 778c2ecf20Sopenharmony_ci{ 788c2ecf20Sopenharmony_ci struct device *dev = (struct device *)arg; 798c2ecf20Sopenharmony_ci struct dpio_priv *priv = dev_get_drvdata(dev); 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci return dpaa2_io_irq(priv->io); 828c2ecf20Sopenharmony_ci} 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_cistatic void unregister_dpio_irq_handlers(struct fsl_mc_device *dpio_dev) 858c2ecf20Sopenharmony_ci{ 868c2ecf20Sopenharmony_ci struct fsl_mc_device_irq *irq; 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci irq = dpio_dev->irqs[0]; 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci /* clear the affinity hint */ 918c2ecf20Sopenharmony_ci irq_set_affinity_hint(irq->msi_desc->irq, NULL); 928c2ecf20Sopenharmony_ci} 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_cistatic int register_dpio_irq_handlers(struct fsl_mc_device *dpio_dev, int cpu) 958c2ecf20Sopenharmony_ci{ 968c2ecf20Sopenharmony_ci int error; 978c2ecf20Sopenharmony_ci struct fsl_mc_device_irq *irq; 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci irq = dpio_dev->irqs[0]; 1008c2ecf20Sopenharmony_ci error = devm_request_irq(&dpio_dev->dev, 1018c2ecf20Sopenharmony_ci irq->msi_desc->irq, 1028c2ecf20Sopenharmony_ci dpio_irq_handler, 1038c2ecf20Sopenharmony_ci 0, 1048c2ecf20Sopenharmony_ci dev_name(&dpio_dev->dev), 1058c2ecf20Sopenharmony_ci &dpio_dev->dev); 1068c2ecf20Sopenharmony_ci if (error < 0) { 1078c2ecf20Sopenharmony_ci dev_err(&dpio_dev->dev, 1088c2ecf20Sopenharmony_ci "devm_request_irq() failed: %d\n", 1098c2ecf20Sopenharmony_ci error); 1108c2ecf20Sopenharmony_ci return error; 1118c2ecf20Sopenharmony_ci } 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci /* set the affinity hint */ 1148c2ecf20Sopenharmony_ci if (irq_set_affinity_hint(irq->msi_desc->irq, cpumask_of(cpu))) 1158c2ecf20Sopenharmony_ci dev_err(&dpio_dev->dev, 1168c2ecf20Sopenharmony_ci "irq_set_affinity failed irq %d cpu %d\n", 1178c2ecf20Sopenharmony_ci irq->msi_desc->irq, cpu); 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci return 0; 1208c2ecf20Sopenharmony_ci} 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_cistatic int dpaa2_dpio_probe(struct fsl_mc_device *dpio_dev) 1238c2ecf20Sopenharmony_ci{ 1248c2ecf20Sopenharmony_ci struct dpio_attr dpio_attrs; 1258c2ecf20Sopenharmony_ci struct dpaa2_io_desc desc; 1268c2ecf20Sopenharmony_ci struct dpio_priv *priv; 1278c2ecf20Sopenharmony_ci int err = -ENOMEM; 1288c2ecf20Sopenharmony_ci struct device *dev = &dpio_dev->dev; 1298c2ecf20Sopenharmony_ci int possible_next_cpu; 1308c2ecf20Sopenharmony_ci int sdest; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 1338c2ecf20Sopenharmony_ci if (!priv) 1348c2ecf20Sopenharmony_ci goto err_priv_alloc; 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci dev_set_drvdata(dev, priv); 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci err = fsl_mc_portal_allocate(dpio_dev, 0, &dpio_dev->mc_io); 1398c2ecf20Sopenharmony_ci if (err) { 1408c2ecf20Sopenharmony_ci dev_dbg(dev, "MC portal allocation failed\n"); 1418c2ecf20Sopenharmony_ci err = -EPROBE_DEFER; 1428c2ecf20Sopenharmony_ci goto err_priv_alloc; 1438c2ecf20Sopenharmony_ci } 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci err = dpio_open(dpio_dev->mc_io, 0, dpio_dev->obj_desc.id, 1468c2ecf20Sopenharmony_ci &dpio_dev->mc_handle); 1478c2ecf20Sopenharmony_ci if (err) { 1488c2ecf20Sopenharmony_ci dev_err(dev, "dpio_open() failed\n"); 1498c2ecf20Sopenharmony_ci goto err_open; 1508c2ecf20Sopenharmony_ci } 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci err = dpio_reset(dpio_dev->mc_io, 0, dpio_dev->mc_handle); 1538c2ecf20Sopenharmony_ci if (err) { 1548c2ecf20Sopenharmony_ci dev_err(dev, "dpio_reset() failed\n"); 1558c2ecf20Sopenharmony_ci goto err_reset; 1568c2ecf20Sopenharmony_ci } 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci err = dpio_get_attributes(dpio_dev->mc_io, 0, dpio_dev->mc_handle, 1598c2ecf20Sopenharmony_ci &dpio_attrs); 1608c2ecf20Sopenharmony_ci if (err) { 1618c2ecf20Sopenharmony_ci dev_err(dev, "dpio_get_attributes() failed %d\n", err); 1628c2ecf20Sopenharmony_ci goto err_get_attr; 1638c2ecf20Sopenharmony_ci } 1648c2ecf20Sopenharmony_ci desc.qman_version = dpio_attrs.qbman_version; 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci err = dpio_enable(dpio_dev->mc_io, 0, dpio_dev->mc_handle); 1678c2ecf20Sopenharmony_ci if (err) { 1688c2ecf20Sopenharmony_ci dev_err(dev, "dpio_enable() failed %d\n", err); 1698c2ecf20Sopenharmony_ci goto err_get_attr; 1708c2ecf20Sopenharmony_ci } 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci /* initialize DPIO descriptor */ 1738c2ecf20Sopenharmony_ci desc.receives_notifications = dpio_attrs.num_priorities ? 1 : 0; 1748c2ecf20Sopenharmony_ci desc.has_8prio = dpio_attrs.num_priorities == 8 ? 1 : 0; 1758c2ecf20Sopenharmony_ci desc.dpio_id = dpio_dev->obj_desc.id; 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci /* get the cpu to use for the affinity hint */ 1788c2ecf20Sopenharmony_ci possible_next_cpu = cpumask_first(cpus_unused_mask); 1798c2ecf20Sopenharmony_ci if (possible_next_cpu >= nr_cpu_ids) { 1808c2ecf20Sopenharmony_ci dev_err(dev, "probe failed. Number of DPIOs exceeds NR_CPUS.\n"); 1818c2ecf20Sopenharmony_ci err = -ERANGE; 1828c2ecf20Sopenharmony_ci goto err_allocate_irqs; 1838c2ecf20Sopenharmony_ci } 1848c2ecf20Sopenharmony_ci desc.cpu = possible_next_cpu; 1858c2ecf20Sopenharmony_ci cpumask_clear_cpu(possible_next_cpu, cpus_unused_mask); 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci sdest = dpaa2_dpio_get_cluster_sdest(dpio_dev, desc.cpu); 1888c2ecf20Sopenharmony_ci if (sdest >= 0) { 1898c2ecf20Sopenharmony_ci err = dpio_set_stashing_destination(dpio_dev->mc_io, 0, 1908c2ecf20Sopenharmony_ci dpio_dev->mc_handle, 1918c2ecf20Sopenharmony_ci sdest); 1928c2ecf20Sopenharmony_ci if (err) 1938c2ecf20Sopenharmony_ci dev_err(dev, "dpio_set_stashing_destination failed for cpu%d\n", 1948c2ecf20Sopenharmony_ci desc.cpu); 1958c2ecf20Sopenharmony_ci } 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci if (dpio_dev->obj_desc.region_count < 3) { 1988c2ecf20Sopenharmony_ci /* No support for DDR backed portals, use classic mapping */ 1998c2ecf20Sopenharmony_ci /* 2008c2ecf20Sopenharmony_ci * Set the CENA regs to be the cache inhibited area of the 2018c2ecf20Sopenharmony_ci * portal to avoid coherency issues if a user migrates to 2028c2ecf20Sopenharmony_ci * another core. 2038c2ecf20Sopenharmony_ci */ 2048c2ecf20Sopenharmony_ci desc.regs_cena = devm_memremap(dev, dpio_dev->regions[1].start, 2058c2ecf20Sopenharmony_ci resource_size(&dpio_dev->regions[1]), 2068c2ecf20Sopenharmony_ci MEMREMAP_WC); 2078c2ecf20Sopenharmony_ci } else { 2088c2ecf20Sopenharmony_ci desc.regs_cena = devm_memremap(dev, dpio_dev->regions[2].start, 2098c2ecf20Sopenharmony_ci resource_size(&dpio_dev->regions[2]), 2108c2ecf20Sopenharmony_ci MEMREMAP_WB); 2118c2ecf20Sopenharmony_ci } 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci if (IS_ERR(desc.regs_cena)) { 2148c2ecf20Sopenharmony_ci dev_err(dev, "devm_memremap failed\n"); 2158c2ecf20Sopenharmony_ci err = PTR_ERR(desc.regs_cena); 2168c2ecf20Sopenharmony_ci goto err_allocate_irqs; 2178c2ecf20Sopenharmony_ci } 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci desc.regs_cinh = devm_ioremap(dev, dpio_dev->regions[1].start, 2208c2ecf20Sopenharmony_ci resource_size(&dpio_dev->regions[1])); 2218c2ecf20Sopenharmony_ci if (!desc.regs_cinh) { 2228c2ecf20Sopenharmony_ci err = -ENOMEM; 2238c2ecf20Sopenharmony_ci dev_err(dev, "devm_ioremap failed\n"); 2248c2ecf20Sopenharmony_ci goto err_allocate_irqs; 2258c2ecf20Sopenharmony_ci } 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci err = fsl_mc_allocate_irqs(dpio_dev); 2288c2ecf20Sopenharmony_ci if (err) { 2298c2ecf20Sopenharmony_ci dev_err(dev, "fsl_mc_allocate_irqs failed. err=%d\n", err); 2308c2ecf20Sopenharmony_ci goto err_allocate_irqs; 2318c2ecf20Sopenharmony_ci } 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci priv->io = dpaa2_io_create(&desc, dev); 2348c2ecf20Sopenharmony_ci if (!priv->io) { 2358c2ecf20Sopenharmony_ci dev_err(dev, "dpaa2_io_create failed\n"); 2368c2ecf20Sopenharmony_ci err = -ENOMEM; 2378c2ecf20Sopenharmony_ci goto err_dpaa2_io_create; 2388c2ecf20Sopenharmony_ci } 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci err = register_dpio_irq_handlers(dpio_dev, desc.cpu); 2418c2ecf20Sopenharmony_ci if (err) 2428c2ecf20Sopenharmony_ci goto err_register_dpio_irq; 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci dev_info(dev, "probed\n"); 2458c2ecf20Sopenharmony_ci dev_dbg(dev, " receives_notifications = %d\n", 2468c2ecf20Sopenharmony_ci desc.receives_notifications); 2478c2ecf20Sopenharmony_ci dpio_close(dpio_dev->mc_io, 0, dpio_dev->mc_handle); 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci return 0; 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_cierr_dpaa2_io_create: 2528c2ecf20Sopenharmony_ci unregister_dpio_irq_handlers(dpio_dev); 2538c2ecf20Sopenharmony_cierr_register_dpio_irq: 2548c2ecf20Sopenharmony_ci fsl_mc_free_irqs(dpio_dev); 2558c2ecf20Sopenharmony_cierr_allocate_irqs: 2568c2ecf20Sopenharmony_ci dpio_disable(dpio_dev->mc_io, 0, dpio_dev->mc_handle); 2578c2ecf20Sopenharmony_cierr_get_attr: 2588c2ecf20Sopenharmony_cierr_reset: 2598c2ecf20Sopenharmony_ci dpio_close(dpio_dev->mc_io, 0, dpio_dev->mc_handle); 2608c2ecf20Sopenharmony_cierr_open: 2618c2ecf20Sopenharmony_ci fsl_mc_portal_free(dpio_dev->mc_io); 2628c2ecf20Sopenharmony_cierr_priv_alloc: 2638c2ecf20Sopenharmony_ci return err; 2648c2ecf20Sopenharmony_ci} 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci/* Tear down interrupts for a given DPIO object */ 2678c2ecf20Sopenharmony_cistatic void dpio_teardown_irqs(struct fsl_mc_device *dpio_dev) 2688c2ecf20Sopenharmony_ci{ 2698c2ecf20Sopenharmony_ci unregister_dpio_irq_handlers(dpio_dev); 2708c2ecf20Sopenharmony_ci fsl_mc_free_irqs(dpio_dev); 2718c2ecf20Sopenharmony_ci} 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_cistatic int dpaa2_dpio_remove(struct fsl_mc_device *dpio_dev) 2748c2ecf20Sopenharmony_ci{ 2758c2ecf20Sopenharmony_ci struct device *dev; 2768c2ecf20Sopenharmony_ci struct dpio_priv *priv; 2778c2ecf20Sopenharmony_ci int err = 0, cpu; 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci dev = &dpio_dev->dev; 2808c2ecf20Sopenharmony_ci priv = dev_get_drvdata(dev); 2818c2ecf20Sopenharmony_ci cpu = dpaa2_io_get_cpu(priv->io); 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci dpaa2_io_down(priv->io); 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci dpio_teardown_irqs(dpio_dev); 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci cpumask_set_cpu(cpu, cpus_unused_mask); 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci err = dpio_open(dpio_dev->mc_io, 0, dpio_dev->obj_desc.id, 2908c2ecf20Sopenharmony_ci &dpio_dev->mc_handle); 2918c2ecf20Sopenharmony_ci if (err) { 2928c2ecf20Sopenharmony_ci dev_err(dev, "dpio_open() failed\n"); 2938c2ecf20Sopenharmony_ci goto err_open; 2948c2ecf20Sopenharmony_ci } 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci dpio_disable(dpio_dev->mc_io, 0, dpio_dev->mc_handle); 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci dpio_close(dpio_dev->mc_io, 0, dpio_dev->mc_handle); 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci fsl_mc_portal_free(dpio_dev->mc_io); 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci return 0; 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_cierr_open: 3058c2ecf20Sopenharmony_ci fsl_mc_portal_free(dpio_dev->mc_io); 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci return err; 3088c2ecf20Sopenharmony_ci} 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_cistatic const struct fsl_mc_device_id dpaa2_dpio_match_id_table[] = { 3118c2ecf20Sopenharmony_ci { 3128c2ecf20Sopenharmony_ci .vendor = FSL_MC_VENDOR_FREESCALE, 3138c2ecf20Sopenharmony_ci .obj_type = "dpio", 3148c2ecf20Sopenharmony_ci }, 3158c2ecf20Sopenharmony_ci { .vendor = 0x0 } 3168c2ecf20Sopenharmony_ci}; 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_cistatic struct fsl_mc_driver dpaa2_dpio_driver = { 3198c2ecf20Sopenharmony_ci .driver = { 3208c2ecf20Sopenharmony_ci .name = KBUILD_MODNAME, 3218c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 3228c2ecf20Sopenharmony_ci }, 3238c2ecf20Sopenharmony_ci .probe = dpaa2_dpio_probe, 3248c2ecf20Sopenharmony_ci .remove = dpaa2_dpio_remove, 3258c2ecf20Sopenharmony_ci .match_id_table = dpaa2_dpio_match_id_table 3268c2ecf20Sopenharmony_ci}; 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_cistatic int dpio_driver_init(void) 3298c2ecf20Sopenharmony_ci{ 3308c2ecf20Sopenharmony_ci if (!zalloc_cpumask_var(&cpus_unused_mask, GFP_KERNEL)) 3318c2ecf20Sopenharmony_ci return -ENOMEM; 3328c2ecf20Sopenharmony_ci cpumask_copy(cpus_unused_mask, cpu_online_mask); 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci return fsl_mc_driver_register(&dpaa2_dpio_driver); 3358c2ecf20Sopenharmony_ci} 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_cistatic void dpio_driver_exit(void) 3388c2ecf20Sopenharmony_ci{ 3398c2ecf20Sopenharmony_ci free_cpumask_var(cpus_unused_mask); 3408c2ecf20Sopenharmony_ci fsl_mc_driver_unregister(&dpaa2_dpio_driver); 3418c2ecf20Sopenharmony_ci} 3428c2ecf20Sopenharmony_cimodule_init(dpio_driver_init); 3438c2ecf20Sopenharmony_cimodule_exit(dpio_driver_exit); 344