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 int error; 54 struct fsl_mc_device_irq *irq; 55 cpumask_t mask; 56 57 irq = dpio_dev->irqs[0]; 58 error = devm_request_irq(&dpio_dev->dev, 59 irq->msi_desc->irq, 60 dpio_irq_handler, 61 0, 62 dev_name(&dpio_dev->dev), 63 &dpio_dev->dev); 64 if (error < 0) { 65 dev_err(&dpio_dev->dev, 66 "devm_request_irq() failed: %d\n", 67 error); 68 return error; 69 } 70 71 /* set the affinity hint */ 72 cpumask_clear(&mask); 73 cpumask_set_cpu(cpu, &mask); 74 if (irq_set_affinity_hint(irq->msi_desc->irq, &mask)) 75 dev_err(&dpio_dev->dev, 76 "irq_set_affinity failed irq %d cpu %d\n", 77 irq->msi_desc->irq, cpu); 78 79 return 0; 80 } 81 82 static int dpaa2_dpio_probe(struct fsl_mc_device *dpio_dev) 83 { 84 struct dpio_attr dpio_attrs; 85 struct dpaa2_io_desc desc; 86 struct dpio_priv *priv; 87 int err = -ENOMEM; 88 struct device *dev = &dpio_dev->dev; 89 static int next_cpu = -1; 90 91 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 92 if (!priv) 93 goto err_priv_alloc; 94 95 dev_set_drvdata(dev, priv); 96 97 err = fsl_mc_portal_allocate(dpio_dev, 0, &dpio_dev->mc_io); 98 if (err) { 99 dev_dbg(dev, "MC portal allocation failed\n"); 100 err = -EPROBE_DEFER; 101 goto err_priv_alloc; 102 } 103 104 err = dpio_open(dpio_dev->mc_io, 0, dpio_dev->obj_desc.id, 105 &dpio_dev->mc_handle); 106 if (err) { 107 dev_err(dev, "dpio_open() failed\n"); 108 goto err_open; 109 } 110 111 err = dpio_get_attributes(dpio_dev->mc_io, 0, dpio_dev->mc_handle, 112 &dpio_attrs); 113 if (err) { 114 dev_err(dev, "dpio_get_attributes() failed %d\n", err); 115 goto err_get_attr; 116 } 117 desc.qman_version = dpio_attrs.qbman_version; 118 119 err = dpio_enable(dpio_dev->mc_io, 0, dpio_dev->mc_handle); 120 if (err) { 121 dev_err(dev, "dpio_enable() failed %d\n", err); 122 goto err_get_attr; 123 } 124 125 /* initialize DPIO descriptor */ 126 desc.receives_notifications = dpio_attrs.num_priorities ? 1 : 0; 127 desc.has_8prio = dpio_attrs.num_priorities == 8 ? 1 : 0; 128 desc.dpio_id = dpio_dev->obj_desc.id; 129 130 /* get the cpu to use for the affinity hint */ 131 if (next_cpu == -1) 132 next_cpu = cpumask_first(cpu_online_mask); 133 else 134 next_cpu = cpumask_next(next_cpu, cpu_online_mask); 135 136 if (!cpu_possible(next_cpu)) { 137 dev_err(dev, "probe failed. Number of DPIOs exceeds NR_CPUS.\n"); 138 err = -ERANGE; 139 goto err_allocate_irqs; 140 } 141 desc.cpu = next_cpu; 142 143 /* 144 * Set the CENA regs to be the cache inhibited area of the portal to 145 * avoid coherency issues if a user migrates to another core. 146 */ 147 desc.regs_cena = devm_memremap(dev, dpio_dev->regions[1].start, 148 resource_size(&dpio_dev->regions[1]), 149 MEMREMAP_WC); 150 if (IS_ERR(desc.regs_cena)) { 151 dev_err(dev, "devm_memremap failed\n"); 152 err = PTR_ERR(desc.regs_cena); 153 goto err_allocate_irqs; 154 } 155 156 desc.regs_cinh = devm_ioremap(dev, dpio_dev->regions[1].start, 157 resource_size(&dpio_dev->regions[1])); 158 if (!desc.regs_cinh) { 159 err = -ENOMEM; 160 dev_err(dev, "devm_ioremap failed\n"); 161 goto err_allocate_irqs; 162 } 163 164 err = fsl_mc_allocate_irqs(dpio_dev); 165 if (err) { 166 dev_err(dev, "fsl_mc_allocate_irqs failed. err=%d\n", err); 167 goto err_allocate_irqs; 168 } 169 170 err = register_dpio_irq_handlers(dpio_dev, desc.cpu); 171 if (err) 172 goto err_register_dpio_irq; 173 174 priv->io = dpaa2_io_create(&desc); 175 if (!priv->io) { 176 dev_err(dev, "dpaa2_io_create failed\n"); 177 err = -ENOMEM; 178 goto err_dpaa2_io_create; 179 } 180 181 dev_info(dev, "probed\n"); 182 dev_dbg(dev, " receives_notifications = %d\n", 183 desc.receives_notifications); 184 dpio_close(dpio_dev->mc_io, 0, dpio_dev->mc_handle); 185 fsl_mc_portal_free(dpio_dev->mc_io); 186 187 return 0; 188 189 err_dpaa2_io_create: 190 unregister_dpio_irq_handlers(dpio_dev); 191 err_register_dpio_irq: 192 fsl_mc_free_irqs(dpio_dev); 193 err_allocate_irqs: 194 dpio_disable(dpio_dev->mc_io, 0, dpio_dev->mc_handle); 195 err_get_attr: 196 dpio_close(dpio_dev->mc_io, 0, dpio_dev->mc_handle); 197 err_open: 198 fsl_mc_portal_free(dpio_dev->mc_io); 199 err_priv_alloc: 200 return err; 201 } 202 203 /* Tear down interrupts for a given DPIO object */ 204 static void dpio_teardown_irqs(struct fsl_mc_device *dpio_dev) 205 { 206 unregister_dpio_irq_handlers(dpio_dev); 207 fsl_mc_free_irqs(dpio_dev); 208 } 209 210 static int dpaa2_dpio_remove(struct fsl_mc_device *dpio_dev) 211 { 212 struct device *dev; 213 struct dpio_priv *priv; 214 int err; 215 216 dev = &dpio_dev->dev; 217 priv = dev_get_drvdata(dev); 218 219 dpaa2_io_down(priv->io); 220 221 dpio_teardown_irqs(dpio_dev); 222 223 err = fsl_mc_portal_allocate(dpio_dev, 0, &dpio_dev->mc_io); 224 if (err) { 225 dev_err(dev, "MC portal allocation failed\n"); 226 goto err_mcportal; 227 } 228 229 err = dpio_open(dpio_dev->mc_io, 0, dpio_dev->obj_desc.id, 230 &dpio_dev->mc_handle); 231 if (err) { 232 dev_err(dev, "dpio_open() failed\n"); 233 goto err_open; 234 } 235 236 dpio_disable(dpio_dev->mc_io, 0, dpio_dev->mc_handle); 237 238 dpio_close(dpio_dev->mc_io, 0, dpio_dev->mc_handle); 239 240 fsl_mc_portal_free(dpio_dev->mc_io); 241 242 return 0; 243 244 err_open: 245 fsl_mc_portal_free(dpio_dev->mc_io); 246 err_mcportal: 247 return err; 248 } 249 250 static const struct fsl_mc_device_id dpaa2_dpio_match_id_table[] = { 251 { 252 .vendor = FSL_MC_VENDOR_FREESCALE, 253 .obj_type = "dpio", 254 }, 255 { .vendor = 0x0 } 256 }; 257 258 static struct fsl_mc_driver dpaa2_dpio_driver = { 259 .driver = { 260 .name = KBUILD_MODNAME, 261 .owner = THIS_MODULE, 262 }, 263 .probe = dpaa2_dpio_probe, 264 .remove = dpaa2_dpio_remove, 265 .match_id_table = dpaa2_dpio_match_id_table 266 }; 267 268 static int dpio_driver_init(void) 269 { 270 return fsl_mc_driver_register(&dpaa2_dpio_driver); 271 } 272 273 static void dpio_driver_exit(void) 274 { 275 fsl_mc_driver_unregister(&dpaa2_dpio_driver); 276 } 277 module_init(dpio_driver_init); 278 module_exit(dpio_driver_exit); 279