1 /* 2 * Qualcomm Technologies HIDMA DMA engine Management interface 3 * 4 * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 and 8 * only version 2 as published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 */ 15 16 #include <linux/dmaengine.h> 17 #include <linux/acpi.h> 18 #include <linux/of.h> 19 #include <linux/property.h> 20 #include <linux/of_irq.h> 21 #include <linux/of_platform.h> 22 #include <linux/module.h> 23 #include <linux/uaccess.h> 24 #include <linux/slab.h> 25 #include <linux/pm_runtime.h> 26 #include <linux/bitops.h> 27 #include <linux/dma-mapping.h> 28 29 #include "hidma_mgmt.h" 30 31 #define HIDMA_QOS_N_OFFSET 0x300 32 #define HIDMA_CFG_OFFSET 0x400 33 #define HIDMA_MAX_BUS_REQ_LEN_OFFSET 0x41C 34 #define HIDMA_MAX_XACTIONS_OFFSET 0x420 35 #define HIDMA_HW_VERSION_OFFSET 0x424 36 #define HIDMA_CHRESET_TIMEOUT_OFFSET 0x418 37 38 #define HIDMA_MAX_WR_XACTIONS_MASK GENMASK(4, 0) 39 #define HIDMA_MAX_RD_XACTIONS_MASK GENMASK(4, 0) 40 #define HIDMA_WEIGHT_MASK GENMASK(6, 0) 41 #define HIDMA_MAX_BUS_REQ_LEN_MASK GENMASK(15, 0) 42 #define HIDMA_CHRESET_TIMEOUT_MASK GENMASK(19, 0) 43 44 #define HIDMA_MAX_WR_XACTIONS_BIT_POS 16 45 #define HIDMA_MAX_BUS_WR_REQ_BIT_POS 16 46 #define HIDMA_WRR_BIT_POS 8 47 #define HIDMA_PRIORITY_BIT_POS 15 48 49 #define HIDMA_AUTOSUSPEND_TIMEOUT 2000 50 #define HIDMA_MAX_CHANNEL_WEIGHT 15 51 52 int hidma_mgmt_setup(struct hidma_mgmt_dev *mgmtdev) 53 { 54 unsigned int i; 55 u32 val; 56 57 if (!is_power_of_2(mgmtdev->max_write_request) || 58 (mgmtdev->max_write_request < 128) || 59 (mgmtdev->max_write_request > 1024)) { 60 dev_err(&mgmtdev->pdev->dev, "invalid write request %d\n", 61 mgmtdev->max_write_request); 62 return -EINVAL; 63 } 64 65 if (!is_power_of_2(mgmtdev->max_read_request) || 66 (mgmtdev->max_read_request < 128) || 67 (mgmtdev->max_read_request > 1024)) { 68 dev_err(&mgmtdev->pdev->dev, "invalid read request %d\n", 69 mgmtdev->max_read_request); 70 return -EINVAL; 71 } 72 73 if (mgmtdev->max_wr_xactions > HIDMA_MAX_WR_XACTIONS_MASK) { 74 dev_err(&mgmtdev->pdev->dev, 75 "max_wr_xactions cannot be bigger than %ld\n", 76 HIDMA_MAX_WR_XACTIONS_MASK); 77 return -EINVAL; 78 } 79 80 if (mgmtdev->max_rd_xactions > HIDMA_MAX_RD_XACTIONS_MASK) { 81 dev_err(&mgmtdev->pdev->dev, 82 "max_rd_xactions cannot be bigger than %ld\n", 83 HIDMA_MAX_RD_XACTIONS_MASK); 84 return -EINVAL; 85 } 86 87 for (i = 0; i < mgmtdev->dma_channels; i++) { 88 if (mgmtdev->priority[i] > 1) { 89 dev_err(&mgmtdev->pdev->dev, 90 "priority can be 0 or 1\n"); 91 return -EINVAL; 92 } 93 94 if (mgmtdev->weight[i] > HIDMA_MAX_CHANNEL_WEIGHT) { 95 dev_err(&mgmtdev->pdev->dev, 96 "max value of weight can be %d.\n", 97 HIDMA_MAX_CHANNEL_WEIGHT); 98 return -EINVAL; 99 } 100 101 /* weight needs to be at least one */ 102 if (mgmtdev->weight[i] == 0) 103 mgmtdev->weight[i] = 1; 104 } 105 106 pm_runtime_get_sync(&mgmtdev->pdev->dev); 107 val = readl(mgmtdev->virtaddr + HIDMA_MAX_BUS_REQ_LEN_OFFSET); 108 val &= ~(HIDMA_MAX_BUS_REQ_LEN_MASK << HIDMA_MAX_BUS_WR_REQ_BIT_POS); 109 val |= mgmtdev->max_write_request << HIDMA_MAX_BUS_WR_REQ_BIT_POS; 110 val &= ~HIDMA_MAX_BUS_REQ_LEN_MASK; 111 val |= mgmtdev->max_read_request; 112 writel(val, mgmtdev->virtaddr + HIDMA_MAX_BUS_REQ_LEN_OFFSET); 113 114 val = readl(mgmtdev->virtaddr + HIDMA_MAX_XACTIONS_OFFSET); 115 val &= ~(HIDMA_MAX_WR_XACTIONS_MASK << HIDMA_MAX_WR_XACTIONS_BIT_POS); 116 val |= mgmtdev->max_wr_xactions << HIDMA_MAX_WR_XACTIONS_BIT_POS; 117 val &= ~HIDMA_MAX_RD_XACTIONS_MASK; 118 val |= mgmtdev->max_rd_xactions; 119 writel(val, mgmtdev->virtaddr + HIDMA_MAX_XACTIONS_OFFSET); 120 121 mgmtdev->hw_version = 122 readl(mgmtdev->virtaddr + HIDMA_HW_VERSION_OFFSET); 123 mgmtdev->hw_version_major = (mgmtdev->hw_version >> 28) & 0xF; 124 mgmtdev->hw_version_minor = (mgmtdev->hw_version >> 16) & 0xF; 125 126 for (i = 0; i < mgmtdev->dma_channels; i++) { 127 u32 weight = mgmtdev->weight[i]; 128 u32 priority = mgmtdev->priority[i]; 129 130 val = readl(mgmtdev->virtaddr + HIDMA_QOS_N_OFFSET + (4 * i)); 131 val &= ~(1 << HIDMA_PRIORITY_BIT_POS); 132 val |= (priority & 0x1) << HIDMA_PRIORITY_BIT_POS; 133 val &= ~(HIDMA_WEIGHT_MASK << HIDMA_WRR_BIT_POS); 134 val |= (weight & HIDMA_WEIGHT_MASK) << HIDMA_WRR_BIT_POS; 135 writel(val, mgmtdev->virtaddr + HIDMA_QOS_N_OFFSET + (4 * i)); 136 } 137 138 val = readl(mgmtdev->virtaddr + HIDMA_CHRESET_TIMEOUT_OFFSET); 139 val &= ~HIDMA_CHRESET_TIMEOUT_MASK; 140 val |= mgmtdev->chreset_timeout_cycles & HIDMA_CHRESET_TIMEOUT_MASK; 141 writel(val, mgmtdev->virtaddr + HIDMA_CHRESET_TIMEOUT_OFFSET); 142 143 pm_runtime_mark_last_busy(&mgmtdev->pdev->dev); 144 pm_runtime_put_autosuspend(&mgmtdev->pdev->dev); 145 return 0; 146 } 147 EXPORT_SYMBOL_GPL(hidma_mgmt_setup); 148 149 static int hidma_mgmt_probe(struct platform_device *pdev) 150 { 151 struct hidma_mgmt_dev *mgmtdev; 152 struct resource *res; 153 void __iomem *virtaddr; 154 int irq; 155 int rc; 156 u32 val; 157 158 pm_runtime_set_autosuspend_delay(&pdev->dev, HIDMA_AUTOSUSPEND_TIMEOUT); 159 pm_runtime_use_autosuspend(&pdev->dev); 160 pm_runtime_set_active(&pdev->dev); 161 pm_runtime_enable(&pdev->dev); 162 pm_runtime_get_sync(&pdev->dev); 163 164 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 165 virtaddr = devm_ioremap_resource(&pdev->dev, res); 166 if (IS_ERR(virtaddr)) { 167 rc = -ENOMEM; 168 goto out; 169 } 170 171 irq = platform_get_irq(pdev, 0); 172 if (irq < 0) { 173 dev_err(&pdev->dev, "irq resources not found\n"); 174 rc = irq; 175 goto out; 176 } 177 178 mgmtdev = devm_kzalloc(&pdev->dev, sizeof(*mgmtdev), GFP_KERNEL); 179 if (!mgmtdev) { 180 rc = -ENOMEM; 181 goto out; 182 } 183 184 mgmtdev->pdev = pdev; 185 mgmtdev->addrsize = resource_size(res); 186 mgmtdev->virtaddr = virtaddr; 187 188 rc = device_property_read_u32(&pdev->dev, "dma-channels", 189 &mgmtdev->dma_channels); 190 if (rc) { 191 dev_err(&pdev->dev, "number of channels missing\n"); 192 goto out; 193 } 194 195 rc = device_property_read_u32(&pdev->dev, 196 "channel-reset-timeout-cycles", 197 &mgmtdev->chreset_timeout_cycles); 198 if (rc) { 199 dev_err(&pdev->dev, "channel reset timeout missing\n"); 200 goto out; 201 } 202 203 rc = device_property_read_u32(&pdev->dev, "max-write-burst-bytes", 204 &mgmtdev->max_write_request); 205 if (rc) { 206 dev_err(&pdev->dev, "max-write-burst-bytes missing\n"); 207 goto out; 208 } 209 210 rc = device_property_read_u32(&pdev->dev, "max-read-burst-bytes", 211 &mgmtdev->max_read_request); 212 if (rc) { 213 dev_err(&pdev->dev, "max-read-burst-bytes missing\n"); 214 goto out; 215 } 216 217 rc = device_property_read_u32(&pdev->dev, "max-write-transactions", 218 &mgmtdev->max_wr_xactions); 219 if (rc) { 220 dev_err(&pdev->dev, "max-write-transactions missing\n"); 221 goto out; 222 } 223 224 rc = device_property_read_u32(&pdev->dev, "max-read-transactions", 225 &mgmtdev->max_rd_xactions); 226 if (rc) { 227 dev_err(&pdev->dev, "max-read-transactions missing\n"); 228 goto out; 229 } 230 231 mgmtdev->priority = devm_kcalloc(&pdev->dev, 232 mgmtdev->dma_channels, 233 sizeof(*mgmtdev->priority), 234 GFP_KERNEL); 235 if (!mgmtdev->priority) { 236 rc = -ENOMEM; 237 goto out; 238 } 239 240 mgmtdev->weight = devm_kcalloc(&pdev->dev, 241 mgmtdev->dma_channels, 242 sizeof(*mgmtdev->weight), GFP_KERNEL); 243 if (!mgmtdev->weight) { 244 rc = -ENOMEM; 245 goto out; 246 } 247 248 rc = hidma_mgmt_setup(mgmtdev); 249 if (rc) { 250 dev_err(&pdev->dev, "setup failed\n"); 251 goto out; 252 } 253 254 /* start the HW */ 255 val = readl(mgmtdev->virtaddr + HIDMA_CFG_OFFSET); 256 val |= 1; 257 writel(val, mgmtdev->virtaddr + HIDMA_CFG_OFFSET); 258 259 rc = hidma_mgmt_init_sys(mgmtdev); 260 if (rc) { 261 dev_err(&pdev->dev, "sysfs setup failed\n"); 262 goto out; 263 } 264 265 dev_info(&pdev->dev, 266 "HW rev: %d.%d @ %pa with %d physical channels\n", 267 mgmtdev->hw_version_major, mgmtdev->hw_version_minor, 268 &res->start, mgmtdev->dma_channels); 269 270 platform_set_drvdata(pdev, mgmtdev); 271 pm_runtime_mark_last_busy(&pdev->dev); 272 pm_runtime_put_autosuspend(&pdev->dev); 273 return 0; 274 out: 275 pm_runtime_put_sync_suspend(&pdev->dev); 276 pm_runtime_disable(&pdev->dev); 277 return rc; 278 } 279 280 #if IS_ENABLED(CONFIG_ACPI) 281 static const struct acpi_device_id hidma_mgmt_acpi_ids[] = { 282 {"QCOM8060"}, 283 {}, 284 }; 285 MODULE_DEVICE_TABLE(acpi, hidma_mgmt_acpi_ids); 286 #endif 287 288 static const struct of_device_id hidma_mgmt_match[] = { 289 {.compatible = "qcom,hidma-mgmt-1.0",}, 290 {}, 291 }; 292 MODULE_DEVICE_TABLE(of, hidma_mgmt_match); 293 294 static struct platform_driver hidma_mgmt_driver = { 295 .probe = hidma_mgmt_probe, 296 .driver = { 297 .name = "hidma-mgmt", 298 .of_match_table = hidma_mgmt_match, 299 .acpi_match_table = ACPI_PTR(hidma_mgmt_acpi_ids), 300 }, 301 }; 302 303 #if defined(CONFIG_OF) && defined(CONFIG_OF_IRQ) 304 static int object_counter; 305 306 static int __init hidma_mgmt_of_populate_channels(struct device_node *np) 307 { 308 struct platform_device *pdev_parent = of_find_device_by_node(np); 309 struct platform_device_info pdevinfo; 310 struct of_phandle_args out_irq; 311 struct device_node *child; 312 struct resource *res; 313 const __be32 *cell; 314 int ret = 0, size, i, num; 315 u64 addr, addr_size; 316 317 for_each_available_child_of_node(np, child) { 318 struct resource *res_iter; 319 struct platform_device *new_pdev; 320 321 cell = of_get_property(child, "reg", &size); 322 if (!cell) { 323 ret = -EINVAL; 324 goto out; 325 } 326 327 size /= sizeof(*cell); 328 num = size / 329 (of_n_addr_cells(child) + of_n_size_cells(child)) + 1; 330 331 /* allocate a resource array */ 332 res = kcalloc(num, sizeof(*res), GFP_KERNEL); 333 if (!res) { 334 ret = -ENOMEM; 335 goto out; 336 } 337 338 /* read each reg value */ 339 i = 0; 340 res_iter = res; 341 while (i < size) { 342 addr = of_read_number(&cell[i], 343 of_n_addr_cells(child)); 344 i += of_n_addr_cells(child); 345 346 addr_size = of_read_number(&cell[i], 347 of_n_size_cells(child)); 348 i += of_n_size_cells(child); 349 350 res_iter->start = addr; 351 res_iter->end = res_iter->start + addr_size - 1; 352 res_iter->flags = IORESOURCE_MEM; 353 res_iter++; 354 } 355 356 ret = of_irq_parse_one(child, 0, &out_irq); 357 if (ret) 358 goto out; 359 360 res_iter->start = irq_create_of_mapping(&out_irq); 361 res_iter->name = "hidma event irq"; 362 res_iter->flags = IORESOURCE_IRQ; 363 364 memset(&pdevinfo, 0, sizeof(pdevinfo)); 365 pdevinfo.fwnode = &child->fwnode; 366 pdevinfo.parent = pdev_parent ? &pdev_parent->dev : NULL; 367 pdevinfo.name = child->name; 368 pdevinfo.id = object_counter++; 369 pdevinfo.res = res; 370 pdevinfo.num_res = num; 371 pdevinfo.data = NULL; 372 pdevinfo.size_data = 0; 373 pdevinfo.dma_mask = DMA_BIT_MASK(64); 374 new_pdev = platform_device_register_full(&pdevinfo); 375 if (IS_ERR(new_pdev)) { 376 ret = PTR_ERR(new_pdev); 377 goto out; 378 } 379 of_node_get(child); 380 new_pdev->dev.of_node = child; 381 of_dma_configure(&new_pdev->dev, child); 382 /* 383 * It is assumed that calling of_msi_configure is safe on 384 * platforms with or without MSI support. 385 */ 386 of_msi_configure(&new_pdev->dev, child); 387 of_node_put(child); 388 kfree(res); 389 res = NULL; 390 } 391 out: 392 kfree(res); 393 394 return ret; 395 } 396 #endif 397 398 static int __init hidma_mgmt_init(void) 399 { 400 #if defined(CONFIG_OF) && defined(CONFIG_OF_IRQ) 401 struct device_node *child; 402 403 for_each_matching_node(child, hidma_mgmt_match) { 404 /* device tree based firmware here */ 405 hidma_mgmt_of_populate_channels(child); 406 } 407 #endif 408 platform_driver_register(&hidma_mgmt_driver); 409 410 return 0; 411 } 412 module_init(hidma_mgmt_init); 413 MODULE_LICENSE("GPL v2"); 414