1 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) 2 /* 3 * Copyright 2014-2016 Freescale Semiconductor Inc. 4 * Copyright NXP 2016 5 * 6 */ 7 8 #include <linux/types.h> 9 #include <linux/init.h> 10 #include <linux/module.h> 11 #include <linux/platform_device.h> 12 #include <linux/interrupt.h> 13 #include <linux/msi.h> 14 #include <linux/dma-mapping.h> 15 #include <linux/delay.h> 16 #include <linux/io.h> 17 18 #include <linux/fsl/mc.h> 19 #include <soc/fsl/dpaa2-io.h> 20 21 #include "qbman-portal.h" 22 #include "dpio.h" 23 #include "dpio-cmd.h" 24 25 MODULE_LICENSE("Dual BSD/GPL"); 26 MODULE_AUTHOR("Freescale Semiconductor, Inc"); 27 MODULE_DESCRIPTION("DPIO Driver"); 28 29 struct dpio_priv { 30 struct dpaa2_io *io; 31 }; 32 33 static irqreturn_t dpio_irq_handler(int irq_num, void *arg) 34 { 35 struct device *dev = (struct device *)arg; 36 struct dpio_priv *priv = dev_get_drvdata(dev); 37 38 return dpaa2_io_irq(priv->io); 39 } 40 41 static void unregister_dpio_irq_handlers(struct fsl_mc_device *dpio_dev) 42 { 43 struct fsl_mc_device_irq *irq; 44 45 irq = dpio_dev->irqs[0]; 46 47 /* clear the affinity hint */ 48 irq_set_affinity_hint(irq->msi_desc->irq, NULL); 49 } 50 51 static int register_dpio_irq_handlers(struct fsl_mc_device *dpio_dev, int cpu) 52 { 53 struct dpio_priv *priv; 54 int error; 55 struct fsl_mc_device_irq *irq; 56 cpumask_t mask; 57 58 priv = dev_get_drvdata(&dpio_dev->dev); 59 60 irq = dpio_dev->irqs[0]; 61 error = devm_request_irq(&dpio_dev->dev, 62 irq->msi_desc->irq, 63 dpio_irq_handler, 64 0, 65 dev_name(&dpio_dev->dev), 66 &dpio_dev->dev); 67 if (error < 0) { 68 dev_err(&dpio_dev->dev, 69 "devm_request_irq() failed: %d\n", 70 error); 71 return error; 72 } 73 74 /* set the affinity hint */ 75 cpumask_clear(&mask); 76 cpumask_set_cpu(cpu, &mask); 77 if (irq_set_affinity_hint(irq->msi_desc->irq, &mask)) 78 dev_err(&dpio_dev->dev, 79 "irq_set_affinity failed irq %d cpu %d\n", 80 irq->msi_desc->irq, cpu); 81 82 return 0; 83 } 84 85 static int dpaa2_dpio_probe(struct fsl_mc_device *dpio_dev) 86 { 87 struct dpio_attr dpio_attrs; 88 struct dpaa2_io_desc desc; 89 struct dpio_priv *priv; 90 int err = -ENOMEM; 91 struct device *dev = &dpio_dev->dev; 92 static int next_cpu = -1; 93 94 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 95 if (!priv) 96 goto err_priv_alloc; 97 98 dev_set_drvdata(dev, priv); 99 100 err = fsl_mc_portal_allocate(dpio_dev, 0, &dpio_dev->mc_io); 101 if (err) { 102 dev_dbg(dev, "MC portal allocation failed\n"); 103 err = -EPROBE_DEFER; 104 goto err_priv_alloc; 105 } 106 107 err = dpio_open(dpio_dev->mc_io, 0, dpio_dev->obj_desc.id, 108 &dpio_dev->mc_handle); 109 if (err) { 110 dev_err(dev, "dpio_open() failed\n"); 111 goto err_open; 112 } 113 114 err = dpio_get_attributes(dpio_dev->mc_io, 0, dpio_dev->mc_handle, 115 &dpio_attrs); 116 if (err) { 117 dev_err(dev, "dpio_get_attributes() failed %d\n", err); 118 goto err_get_attr; 119 } 120 desc.qman_version = dpio_attrs.qbman_version; 121 122 err = dpio_enable(dpio_dev->mc_io, 0, dpio_dev->mc_handle); 123 if (err) { 124 dev_err(dev, "dpio_enable() failed %d\n", err); 125 goto err_get_attr; 126 } 127 128 /* initialize DPIO descriptor */ 129 desc.receives_notifications = dpio_attrs.num_priorities ? 1 : 0; 130 desc.has_8prio = dpio_attrs.num_priorities == 8 ? 1 : 0; 131 desc.dpio_id = dpio_dev->obj_desc.id; 132 133 /* get the cpu to use for the affinity hint */ 134 if (next_cpu == -1) 135 next_cpu = cpumask_first(cpu_online_mask); 136 else 137 next_cpu = cpumask_next(next_cpu, cpu_online_mask); 138 139 if (!cpu_possible(next_cpu)) { 140 dev_err(dev, "probe failed. Number of DPIOs exceeds NR_CPUS.\n"); 141 err = -ERANGE; 142 goto err_allocate_irqs; 143 } 144 desc.cpu = next_cpu; 145 146 /* 147 * Set the CENA regs to be the cache inhibited area of the portal to 148 * avoid coherency issues if a user migrates to another core. 149 */ 150 desc.regs_cena = devm_memremap(dev, dpio_dev->regions[1].start, 151 resource_size(&dpio_dev->regions[1]), 152 MEMREMAP_WC); 153 if (IS_ERR(desc.regs_cena)) { 154 dev_err(dev, "devm_memremap failed\n"); 155 err = PTR_ERR(desc.regs_cena); 156 goto err_allocate_irqs; 157 } 158 159 desc.regs_cinh = devm_ioremap(dev, dpio_dev->regions[1].start, 160 resource_size(&dpio_dev->regions[1])); 161 if (!desc.regs_cinh) { 162 err = -ENOMEM; 163 dev_err(dev, "devm_ioremap failed\n"); 164 goto err_allocate_irqs; 165 } 166 167 err = fsl_mc_allocate_irqs(dpio_dev); 168 if (err) { 169 dev_err(dev, "fsl_mc_allocate_irqs failed. err=%d\n", err); 170 goto err_allocate_irqs; 171 } 172 173 err = register_dpio_irq_handlers(dpio_dev, desc.cpu); 174 if (err) 175 goto err_register_dpio_irq; 176 177 priv->io = dpaa2_io_create(&desc); 178 if (!priv->io) { 179 dev_err(dev, "dpaa2_io_create failed\n"); 180 err = -ENOMEM; 181 goto err_dpaa2_io_create; 182 } 183 184 dev_info(dev, "probed\n"); 185 dev_dbg(dev, " receives_notifications = %d\n", 186 desc.receives_notifications); 187 dpio_close(dpio_dev->mc_io, 0, dpio_dev->mc_handle); 188 fsl_mc_portal_free(dpio_dev->mc_io); 189 190 return 0; 191 192 err_dpaa2_io_create: 193 unregister_dpio_irq_handlers(dpio_dev); 194 err_register_dpio_irq: 195 fsl_mc_free_irqs(dpio_dev); 196 err_allocate_irqs: 197 dpio_disable(dpio_dev->mc_io, 0, dpio_dev->mc_handle); 198 err_get_attr: 199 dpio_close(dpio_dev->mc_io, 0, dpio_dev->mc_handle); 200 err_open: 201 fsl_mc_portal_free(dpio_dev->mc_io); 202 err_priv_alloc: 203 return err; 204 } 205 206 /* Tear down interrupts for a given DPIO object */ 207 static void dpio_teardown_irqs(struct fsl_mc_device *dpio_dev) 208 { 209 unregister_dpio_irq_handlers(dpio_dev); 210 fsl_mc_free_irqs(dpio_dev); 211 } 212 213 static int dpaa2_dpio_remove(struct fsl_mc_device *dpio_dev) 214 { 215 struct device *dev; 216 struct dpio_priv *priv; 217 int err; 218 219 dev = &dpio_dev->dev; 220 priv = dev_get_drvdata(dev); 221 222 dpaa2_io_down(priv->io); 223 224 dpio_teardown_irqs(dpio_dev); 225 226 err = fsl_mc_portal_allocate(dpio_dev, 0, &dpio_dev->mc_io); 227 if (err) { 228 dev_err(dev, "MC portal allocation failed\n"); 229 goto err_mcportal; 230 } 231 232 err = dpio_open(dpio_dev->mc_io, 0, dpio_dev->obj_desc.id, 233 &dpio_dev->mc_handle); 234 if (err) { 235 dev_err(dev, "dpio_open() failed\n"); 236 goto err_open; 237 } 238 239 dpio_disable(dpio_dev->mc_io, 0, dpio_dev->mc_handle); 240 241 dpio_close(dpio_dev->mc_io, 0, dpio_dev->mc_handle); 242 243 fsl_mc_portal_free(dpio_dev->mc_io); 244 245 return 0; 246 247 err_open: 248 fsl_mc_portal_free(dpio_dev->mc_io); 249 err_mcportal: 250 return err; 251 } 252 253 static const struct fsl_mc_device_id dpaa2_dpio_match_id_table[] = { 254 { 255 .vendor = FSL_MC_VENDOR_FREESCALE, 256 .obj_type = "dpio", 257 }, 258 { .vendor = 0x0 } 259 }; 260 261 static struct fsl_mc_driver dpaa2_dpio_driver = { 262 .driver = { 263 .name = KBUILD_MODNAME, 264 .owner = THIS_MODULE, 265 }, 266 .probe = dpaa2_dpio_probe, 267 .remove = dpaa2_dpio_remove, 268 .match_id_table = dpaa2_dpio_match_id_table 269 }; 270 271 static int dpio_driver_init(void) 272 { 273 return fsl_mc_driver_register(&dpaa2_dpio_driver); 274 } 275 276 static void dpio_driver_exit(void) 277 { 278 fsl_mc_driver_unregister(&dpaa2_dpio_driver); 279 } 280 module_init(dpio_driver_init); 281 module_exit(dpio_driver_exit); 282