1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Device tree helpers for DMA request / controller 4 * 5 * Based on of_gpio.c 6 * 7 * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ 8 */ 9 10 #include <linux/device.h> 11 #include <linux/err.h> 12 #include <linux/module.h> 13 #include <linux/mutex.h> 14 #include <linux/slab.h> 15 #include <linux/of.h> 16 #include <linux/of_dma.h> 17 18 #include "dmaengine.h" 19 20 static LIST_HEAD(of_dma_list); 21 static DEFINE_MUTEX(of_dma_lock); 22 23 /** 24 * of_dma_find_controller - Get a DMA controller in DT DMA helpers list 25 * @dma_spec: pointer to DMA specifier as found in the device tree 26 * 27 * Finds a DMA controller with matching device node and number for dma cells 28 * in a list of registered DMA controllers. If a match is found a valid pointer 29 * to the DMA data stored is retuned. A NULL pointer is returned if no match is 30 * found. 31 */ 32 static struct of_dma *of_dma_find_controller(struct of_phandle_args *dma_spec) 33 { 34 struct of_dma *ofdma; 35 36 list_for_each_entry(ofdma, &of_dma_list, of_dma_controllers) 37 if (ofdma->of_node == dma_spec->np) 38 return ofdma; 39 40 pr_debug("%s: can't find DMA controller %pOF\n", __func__, 41 dma_spec->np); 42 43 return NULL; 44 } 45 46 /** 47 * of_dma_router_xlate - translation function for router devices 48 * @dma_spec: pointer to DMA specifier as found in the device tree 49 * @of_dma: pointer to DMA controller data (router information) 50 * 51 * The function creates new dma_spec to be passed to the router driver's 52 * of_dma_route_allocate() function to prepare a dma_spec which will be used 53 * to request channel from the real DMA controller. 54 */ 55 static struct dma_chan *of_dma_router_xlate(struct of_phandle_args *dma_spec, 56 struct of_dma *ofdma) 57 { 58 struct dma_chan *chan; 59 struct of_dma *ofdma_target; 60 struct of_phandle_args dma_spec_target; 61 void *route_data; 62 63 /* translate the request for the real DMA controller */ 64 memcpy(&dma_spec_target, dma_spec, sizeof(dma_spec_target)); 65 route_data = ofdma->of_dma_route_allocate(&dma_spec_target, ofdma); 66 if (IS_ERR(route_data)) 67 return NULL; 68 69 ofdma_target = of_dma_find_controller(&dma_spec_target); 70 if (!ofdma_target) 71 return NULL; 72 73 chan = ofdma_target->of_dma_xlate(&dma_spec_target, ofdma_target); 74 if (chan) { 75 chan->router = ofdma->dma_router; 76 chan->route_data = route_data; 77 } else { 78 ofdma->dma_router->route_free(ofdma->dma_router->dev, 79 route_data); 80 } 81 82 /* 83 * Need to put the node back since the ofdma->of_dma_route_allocate 84 * has taken it for generating the new, translated dma_spec 85 */ 86 of_node_put(dma_spec_target.np); 87 return chan; 88 } 89 90 /** 91 * of_dma_controller_register - Register a DMA controller to DT DMA helpers 92 * @np: device node of DMA controller 93 * @of_dma_xlate: translation function which converts a phandle 94 * arguments list into a dma_chan structure 95 * @data pointer to controller specific data to be used by 96 * translation function 97 * 98 * Returns 0 on success or appropriate errno value on error. 99 * 100 * Allocated memory should be freed with appropriate of_dma_controller_free() 101 * call. 102 */ 103 int of_dma_controller_register(struct device_node *np, 104 struct dma_chan *(*of_dma_xlate) 105 (struct of_phandle_args *, struct of_dma *), 106 void *data) 107 { 108 struct of_dma *ofdma; 109 110 if (!np || !of_dma_xlate) { 111 pr_err("%s: not enough information provided\n", __func__); 112 return -EINVAL; 113 } 114 115 ofdma = kzalloc(sizeof(*ofdma), GFP_KERNEL); 116 if (!ofdma) 117 return -ENOMEM; 118 119 ofdma->of_node = np; 120 ofdma->of_dma_xlate = of_dma_xlate; 121 ofdma->of_dma_data = data; 122 123 /* Now queue of_dma controller structure in list */ 124 mutex_lock(&of_dma_lock); 125 list_add_tail(&ofdma->of_dma_controllers, &of_dma_list); 126 mutex_unlock(&of_dma_lock); 127 128 return 0; 129 } 130 EXPORT_SYMBOL_GPL(of_dma_controller_register); 131 132 /** 133 * of_dma_controller_free - Remove a DMA controller from DT DMA helpers list 134 * @np: device node of DMA controller 135 * 136 * Memory allocated by of_dma_controller_register() is freed here. 137 */ 138 void of_dma_controller_free(struct device_node *np) 139 { 140 struct of_dma *ofdma; 141 142 mutex_lock(&of_dma_lock); 143 144 list_for_each_entry(ofdma, &of_dma_list, of_dma_controllers) 145 if (ofdma->of_node == np) { 146 list_del(&ofdma->of_dma_controllers); 147 kfree(ofdma); 148 break; 149 } 150 151 mutex_unlock(&of_dma_lock); 152 } 153 EXPORT_SYMBOL_GPL(of_dma_controller_free); 154 155 /** 156 * of_dma_router_register - Register a DMA router to DT DMA helpers as a 157 * controller 158 * @np: device node of DMA router 159 * @of_dma_route_allocate: setup function for the router which need to 160 * modify the dma_spec for the DMA controller to 161 * use and to set up the requested route. 162 * @dma_router: pointer to dma_router structure to be used when 163 * the route need to be free up. 164 * 165 * Returns 0 on success or appropriate errno value on error. 166 * 167 * Allocated memory should be freed with appropriate of_dma_controller_free() 168 * call. 169 */ 170 int of_dma_router_register(struct device_node *np, 171 void *(*of_dma_route_allocate) 172 (struct of_phandle_args *, struct of_dma *), 173 struct dma_router *dma_router) 174 { 175 struct of_dma *ofdma; 176 177 if (!np || !of_dma_route_allocate || !dma_router) { 178 pr_err("%s: not enough information provided\n", __func__); 179 return -EINVAL; 180 } 181 182 ofdma = kzalloc(sizeof(*ofdma), GFP_KERNEL); 183 if (!ofdma) 184 return -ENOMEM; 185 186 ofdma->of_node = np; 187 ofdma->of_dma_xlate = of_dma_router_xlate; 188 ofdma->of_dma_route_allocate = of_dma_route_allocate; 189 ofdma->dma_router = dma_router; 190 191 /* Now queue of_dma controller structure in list */ 192 mutex_lock(&of_dma_lock); 193 list_add_tail(&ofdma->of_dma_controllers, &of_dma_list); 194 mutex_unlock(&of_dma_lock); 195 196 return 0; 197 } 198 EXPORT_SYMBOL_GPL(of_dma_router_register); 199 200 /** 201 * of_dma_match_channel - Check if a DMA specifier matches name 202 * @np: device node to look for DMA channels 203 * @name: channel name to be matched 204 * @index: index of DMA specifier in list of DMA specifiers 205 * @dma_spec: pointer to DMA specifier as found in the device tree 206 * 207 * Check if the DMA specifier pointed to by the index in a list of DMA 208 * specifiers, matches the name provided. Returns 0 if the name matches and 209 * a valid pointer to the DMA specifier is found. Otherwise returns -ENODEV. 210 */ 211 static int of_dma_match_channel(struct device_node *np, const char *name, 212 int index, struct of_phandle_args *dma_spec) 213 { 214 const char *s; 215 216 if (of_property_read_string_index(np, "dma-names", index, &s)) 217 return -ENODEV; 218 219 if (strcmp(name, s)) 220 return -ENODEV; 221 222 if (of_parse_phandle_with_args(np, "dmas", "#dma-cells", index, 223 dma_spec)) 224 return -ENODEV; 225 226 return 0; 227 } 228 229 /** 230 * of_dma_request_slave_channel - Get the DMA slave channel 231 * @np: device node to get DMA request from 232 * @name: name of desired channel 233 * 234 * Returns pointer to appropriate DMA channel on success or an error pointer. 235 */ 236 struct dma_chan *of_dma_request_slave_channel(struct device_node *np, 237 const char *name) 238 { 239 struct of_phandle_args dma_spec; 240 struct of_dma *ofdma; 241 struct dma_chan *chan; 242 int count, i, start; 243 int ret_no_channel = -ENODEV; 244 static atomic_t last_index; 245 246 if (!np || !name) { 247 pr_err("%s: not enough information provided\n", __func__); 248 return ERR_PTR(-ENODEV); 249 } 250 251 /* Silently fail if there is not even the "dmas" property */ 252 if (!of_find_property(np, "dmas", NULL)) 253 return ERR_PTR(-ENODEV); 254 255 count = of_property_count_strings(np, "dma-names"); 256 if (count < 0) { 257 pr_err("%s: dma-names property of node '%pOF' missing or empty\n", 258 __func__, np); 259 return ERR_PTR(-ENODEV); 260 } 261 262 /* 263 * approximate an average distribution across multiple 264 * entries with the same name 265 */ 266 start = atomic_inc_return(&last_index); 267 for (i = 0; i < count; i++) { 268 if (of_dma_match_channel(np, name, 269 (i + start) % count, 270 &dma_spec)) 271 continue; 272 273 mutex_lock(&of_dma_lock); 274 ofdma = of_dma_find_controller(&dma_spec); 275 276 if (ofdma) { 277 chan = ofdma->of_dma_xlate(&dma_spec, ofdma); 278 } else { 279 ret_no_channel = -EPROBE_DEFER; 280 chan = NULL; 281 } 282 283 mutex_unlock(&of_dma_lock); 284 285 of_node_put(dma_spec.np); 286 287 if (chan) 288 return chan; 289 } 290 291 return ERR_PTR(ret_no_channel); 292 } 293 EXPORT_SYMBOL_GPL(of_dma_request_slave_channel); 294 295 /** 296 * of_dma_simple_xlate - Simple DMA engine translation function 297 * @dma_spec: pointer to DMA specifier as found in the device tree 298 * @of_dma: pointer to DMA controller data 299 * 300 * A simple translation function for devices that use a 32-bit value for the 301 * filter_param when calling the DMA engine dma_request_channel() function. 302 * Note that this translation function requires that #dma-cells is equal to 1 303 * and the argument of the dma specifier is the 32-bit filter_param. Returns 304 * pointer to appropriate dma channel on success or NULL on error. 305 */ 306 struct dma_chan *of_dma_simple_xlate(struct of_phandle_args *dma_spec, 307 struct of_dma *ofdma) 308 { 309 int count = dma_spec->args_count; 310 struct of_dma_filter_info *info = ofdma->of_dma_data; 311 312 if (!info || !info->filter_fn) 313 return NULL; 314 315 if (count != 1) 316 return NULL; 317 318 return __dma_request_channel(&info->dma_cap, info->filter_fn, 319 &dma_spec->args[0], dma_spec->np); 320 } 321 EXPORT_SYMBOL_GPL(of_dma_simple_xlate); 322 323 /** 324 * of_dma_xlate_by_chan_id - Translate dt property to DMA channel by channel id 325 * @dma_spec: pointer to DMA specifier as found in the device tree 326 * @of_dma: pointer to DMA controller data 327 * 328 * This function can be used as the of xlate callback for DMA driver which wants 329 * to match the channel based on the channel id. When using this xlate function 330 * the #dma-cells propety of the DMA controller dt node needs to be set to 1. 331 * The data parameter of of_dma_controller_register must be a pointer to the 332 * dma_device struct the function should match upon. 333 * 334 * Returns pointer to appropriate dma channel on success or NULL on error. 335 */ 336 struct dma_chan *of_dma_xlate_by_chan_id(struct of_phandle_args *dma_spec, 337 struct of_dma *ofdma) 338 { 339 struct dma_device *dev = ofdma->of_dma_data; 340 struct dma_chan *chan, *candidate = NULL; 341 342 if (!dev || dma_spec->args_count != 1) 343 return NULL; 344 345 list_for_each_entry(chan, &dev->channels, device_node) 346 if (chan->chan_id == dma_spec->args[0]) { 347 candidate = chan; 348 break; 349 } 350 351 if (!candidate) 352 return NULL; 353 354 return dma_get_slave_channel(candidate); 355 } 356 EXPORT_SYMBOL_GPL(of_dma_xlate_by_chan_id); 357