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 #endif 286 287 static const struct of_device_id hidma_mgmt_match[] = { 288 {.compatible = "qcom,hidma-mgmt-1.0",}, 289 {}, 290 }; 291 MODULE_DEVICE_TABLE(of, hidma_mgmt_match); 292 293 static struct platform_driver hidma_mgmt_driver = { 294 .probe = hidma_mgmt_probe, 295 .driver = { 296 .name = "hidma-mgmt", 297 .of_match_table = hidma_mgmt_match, 298 .acpi_match_table = ACPI_PTR(hidma_mgmt_acpi_ids), 299 }, 300 }; 301 302 #if defined(CONFIG_OF) && defined(CONFIG_OF_IRQ) 303 static int object_counter; 304 305 static int __init hidma_mgmt_of_populate_channels(struct device_node *np) 306 { 307 struct platform_device *pdev_parent = of_find_device_by_node(np); 308 struct platform_device_info pdevinfo; 309 struct of_phandle_args out_irq; 310 struct device_node *child; 311 struct resource *res; 312 const __be32 *cell; 313 int ret = 0, size, i, num; 314 u64 addr, addr_size; 315 316 for_each_available_child_of_node(np, child) { 317 struct resource *res_iter; 318 struct platform_device *new_pdev; 319 320 cell = of_get_property(child, "reg", &size); 321 if (!cell) { 322 ret = -EINVAL; 323 goto out; 324 } 325 326 size /= sizeof(*cell); 327 num = size / 328 (of_n_addr_cells(child) + of_n_size_cells(child)) + 1; 329 330 /* allocate a resource array */ 331 res = kcalloc(num, sizeof(*res), GFP_KERNEL); 332 if (!res) { 333 ret = -ENOMEM; 334 goto out; 335 } 336 337 /* read each reg value */ 338 i = 0; 339 res_iter = res; 340 while (i < size) { 341 addr = of_read_number(&cell[i], 342 of_n_addr_cells(child)); 343 i += of_n_addr_cells(child); 344 345 addr_size = of_read_number(&cell[i], 346 of_n_size_cells(child)); 347 i += of_n_size_cells(child); 348 349 res_iter->start = addr; 350 res_iter->end = res_iter->start + addr_size - 1; 351 res_iter->flags = IORESOURCE_MEM; 352 res_iter++; 353 } 354 355 ret = of_irq_parse_one(child, 0, &out_irq); 356 if (ret) 357 goto out; 358 359 res_iter->start = irq_create_of_mapping(&out_irq); 360 res_iter->name = "hidma event irq"; 361 res_iter->flags = IORESOURCE_IRQ; 362 363 memset(&pdevinfo, 0, sizeof(pdevinfo)); 364 pdevinfo.fwnode = &child->fwnode; 365 pdevinfo.parent = pdev_parent ? &pdev_parent->dev : NULL; 366 pdevinfo.name = child->name; 367 pdevinfo.id = object_counter++; 368 pdevinfo.res = res; 369 pdevinfo.num_res = num; 370 pdevinfo.data = NULL; 371 pdevinfo.size_data = 0; 372 pdevinfo.dma_mask = DMA_BIT_MASK(64); 373 new_pdev = platform_device_register_full(&pdevinfo); 374 if (IS_ERR(new_pdev)) { 375 ret = PTR_ERR(new_pdev); 376 goto out; 377 } 378 of_dma_configure(&new_pdev->dev, child); 379 380 kfree(res); 381 res = NULL; 382 } 383 out: 384 kfree(res); 385 386 return ret; 387 } 388 #endif 389 390 static int __init hidma_mgmt_init(void) 391 { 392 #if defined(CONFIG_OF) && defined(CONFIG_OF_IRQ) 393 struct device_node *child; 394 395 for_each_matching_node(child, hidma_mgmt_match) { 396 /* device tree based firmware here */ 397 hidma_mgmt_of_populate_channels(child); 398 of_node_put(child); 399 } 400 #endif 401 platform_driver_register(&hidma_mgmt_driver); 402 403 return 0; 404 } 405 module_init(hidma_mgmt_init); 406 MODULE_LICENSE("GPL v2"); 407