Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

soc: ti: k3-ringacc: add AM64 DMA rings support.

The DMAs in AM64 have built in rings compared to AM654/J721e/J7200 where a
separate and generic ringacc is used.

The ring SW interface is similar to ringacc with some major architectural
differences, like

They are part of the DMA (BCDMA or PKTDMA).

They are dual mode rings are modeled as pair of Rings objects which has
common configuration and memory buffer, but separate real-time control
register sets for each direction mem2dev (forward) and dev2mem (reverse).

The ringacc driver must be initialized for DMA rings use with
k3_ringacc_dmarings_init() as it is not an independent device as ringacc
is.

AM64 rings must be requested only using k3_ringacc_request_rings_pair(),
and forward ring must always be initialized/configured. After this any
other Ringacc APIs can be used without any callers changes.

Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
Link: https://lore.kernel.org/r/20201208090440.31792-17-peter.ujfalusi@ti.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>

authored by

Grygorii Strashko and committed by
Vinod Koul
d782298c fc373e47

+335 -7
+318 -7
drivers/soc/ti/k3-ringacc.c
··· 11 11 #include <linux/of.h> 12 12 #include <linux/platform_device.h> 13 13 #include <linux/sys_soc.h> 14 + #include <linux/dma/ti-cppi5.h> 14 15 #include <linux/soc/ti/k3-ringacc.h> 15 16 #include <linux/soc/ti/ti_sci_protocol.h> 16 17 #include <linux/soc/ti/ti_sci_inta_msi.h> ··· 22 21 static DEFINE_MUTEX(k3_ringacc_list_lock); 23 22 24 23 #define K3_RINGACC_CFG_RING_SIZE_ELCNT_MASK GENMASK(19, 0) 24 + #define K3_DMARING_CFG_RING_SIZE_ELCNT_MASK GENMASK(15, 0) 25 25 26 26 /** 27 27 * struct k3_ring_rt_regs - The RA realtime Control/Status Registers region ··· 45 43 u32 hwindx; 46 44 }; 47 45 48 - #define K3_RINGACC_RT_REGS_STEP 0x1000 46 + #define K3_RINGACC_RT_REGS_STEP 0x1000 47 + #define K3_DMARING_RT_REGS_STEP 0x2000 48 + #define K3_DMARING_RT_REGS_REVERSE_OFS 0x1000 49 + #define K3_RINGACC_RT_OCC_MASK GENMASK(20, 0) 50 + #define K3_DMARING_RT_OCC_TDOWN_COMPLETE BIT(31) 51 + #define K3_DMARING_RT_DB_ENTRY_MASK GENMASK(7, 0) 52 + #define K3_DMARING_RT_DB_TDOWN_ACK BIT(31) 49 53 50 54 /** 51 55 * struct k3_ring_fifo_regs - The Ring Accelerator Queues Registers region ··· 130 122 u32 occ; 131 123 u32 windex; 132 124 u32 rindex; 125 + u32 tdown_complete:1; 133 126 }; 134 127 135 128 /** ··· 152 143 * @use_count: Use count for shared rings 153 144 * @proxy_id: RA Ring Proxy Id (only if @K3_RINGACC_RING_USE_PROXY) 154 145 * @dma_dev: device to be used for DMA API (allocation, mapping) 146 + * @asel: Address Space Select value for physical addresses 155 147 */ 156 148 struct k3_ring { 157 149 struct k3_ring_rt_regs __iomem *rt; ··· 167 157 u32 flags; 168 158 #define K3_RING_FLAG_BUSY BIT(1) 169 159 #define K3_RING_FLAG_SHARED BIT(2) 160 + #define K3_RING_FLAG_REVERSE BIT(3) 170 161 struct k3_ring_state state; 171 162 u32 ring_id; 172 163 struct k3_ringacc *parent; 173 164 u32 use_count; 174 165 int proxy_id; 175 166 struct device *dma_dev; 167 + u32 asel; 168 + #define K3_ADDRESS_ASEL_SHIFT 48 176 169 }; 177 170 178 171 struct k3_ringacc_ops { ··· 201 188 * @tisci_ring_ops: ti-sci rings ops 202 189 * @tisci_dev_id: ti-sci device id 203 190 * @ops: SoC specific ringacc operation 191 + * @dma_rings: indicate DMA ring (dual ring within BCDMA/PKTDMA) 204 192 */ 205 193 struct k3_ringacc { 206 194 struct device *dev; ··· 224 210 u32 tisci_dev_id; 225 211 226 212 const struct k3_ringacc_ops *ops; 213 + bool dma_rings; 227 214 }; 228 215 229 216 /** ··· 235 220 struct k3_ringacc_soc_data { 236 221 unsigned dma_ring_reset_quirk:1; 237 222 }; 223 + 224 + static int k3_ringacc_ring_read_occ(struct k3_ring *ring) 225 + { 226 + return readl(&ring->rt->occ) & K3_RINGACC_RT_OCC_MASK; 227 + } 228 + 229 + static void k3_ringacc_ring_update_occ(struct k3_ring *ring) 230 + { 231 + u32 val; 232 + 233 + val = readl(&ring->rt->occ); 234 + 235 + ring->state.occ = val & K3_RINGACC_RT_OCC_MASK; 236 + ring->state.tdown_complete = !!(val & K3_DMARING_RT_OCC_TDOWN_COMPLETE); 237 + } 238 238 239 239 static long k3_ringacc_ring_get_fifo_pos(struct k3_ring *ring) 240 240 { ··· 264 234 265 235 static int k3_ringacc_ring_push_mem(struct k3_ring *ring, void *elem); 266 236 static int k3_ringacc_ring_pop_mem(struct k3_ring *ring, void *elem); 237 + static int k3_dmaring_fwd_pop(struct k3_ring *ring, void *elem); 238 + static int k3_dmaring_reverse_pop(struct k3_ring *ring, void *elem); 267 239 268 240 static struct k3_ring_ops k3_ring_mode_ring_ops = { 269 241 .push_tail = k3_ringacc_ring_push_mem, 270 242 .pop_head = k3_ringacc_ring_pop_mem, 243 + }; 244 + 245 + static struct k3_ring_ops k3_dmaring_fwd_ops = { 246 + .push_tail = k3_ringacc_ring_push_mem, 247 + .pop_head = k3_dmaring_fwd_pop, 248 + }; 249 + 250 + static struct k3_ring_ops k3_dmaring_reverse_ops = { 251 + /* Reverse side of the DMA ring can only be popped by SW */ 252 + .pop_head = k3_dmaring_reverse_pop, 271 253 }; 272 254 273 255 static int k3_ringacc_ring_push_io(struct k3_ring *ring, void *elem); ··· 384 342 } 385 343 EXPORT_SYMBOL_GPL(k3_ringacc_request_ring); 386 344 345 + static int k3_dmaring_request_dual_ring(struct k3_ringacc *ringacc, int fwd_id, 346 + struct k3_ring **fwd_ring, 347 + struct k3_ring **compl_ring) 348 + { 349 + int ret = 0; 350 + 351 + /* 352 + * DMA rings must be requested by ID, completion ring is the reverse 353 + * side of the forward ring 354 + */ 355 + if (fwd_id < 0) 356 + return -EINVAL; 357 + 358 + mutex_lock(&ringacc->req_lock); 359 + 360 + if (test_bit(fwd_id, ringacc->rings_inuse)) { 361 + ret = -EBUSY; 362 + goto error; 363 + } 364 + 365 + *fwd_ring = &ringacc->rings[fwd_id]; 366 + *compl_ring = &ringacc->rings[fwd_id + ringacc->num_rings]; 367 + set_bit(fwd_id, ringacc->rings_inuse); 368 + ringacc->rings[fwd_id].use_count++; 369 + dev_dbg(ringacc->dev, "Giving ring#%d\n", fwd_id); 370 + 371 + mutex_unlock(&ringacc->req_lock); 372 + return 0; 373 + 374 + error: 375 + mutex_unlock(&ringacc->req_lock); 376 + return ret; 377 + } 378 + 387 379 int k3_ringacc_request_rings_pair(struct k3_ringacc *ringacc, 388 380 int fwd_id, int compl_id, 389 381 struct k3_ring **fwd_ring, ··· 427 351 428 352 if (!fwd_ring || !compl_ring) 429 353 return -EINVAL; 354 + 355 + if (ringacc->dma_rings) 356 + return k3_dmaring_request_dual_ring(ringacc, fwd_id, 357 + fwd_ring, compl_ring); 430 358 431 359 *fwd_ring = k3_ringacc_request_ring(ringacc, fwd_id, 0); 432 360 if (!(*fwd_ring)) ··· 501 421 goto reset; 502 422 503 423 if (!occ) 504 - occ = readl(&ring->rt->occ); 424 + occ = k3_ringacc_ring_read_occ(ring); 505 425 506 426 if (occ) { 507 427 u32 db_ring_cnt, db_ring_cnt_cur; ··· 576 496 577 497 ringacc = ring->parent; 578 498 499 + /* 500 + * DMA rings: rings shared memory and configuration, only forward ring 501 + * is configured and reverse ring considered as slave. 502 + */ 503 + if (ringacc->dma_rings && (ring->flags & K3_RING_FLAG_REVERSE)) 504 + return 0; 505 + 579 506 dev_dbg(ring->parent->dev, "flags: 0x%08x\n", ring->flags); 580 507 581 508 if (!test_bit(ring->ring_id, ringacc->rings_inuse)) ··· 604 517 ring->flags = 0; 605 518 ring->ops = NULL; 606 519 ring->dma_dev = NULL; 520 + ring->asel = 0; 521 + 607 522 if (ring->proxy_id != K3_RINGACC_PROXY_NOT_USED) { 608 523 clear_bit(ring->proxy_id, ringacc->proxy_inuse); 609 524 ring->proxy = NULL; ··· 670 581 ring_cfg.count = ring->size; 671 582 ring_cfg.mode = ring->mode; 672 583 ring_cfg.size = ring->elm_size; 584 + ring_cfg.asel = ring->asel; 673 585 674 586 ret = ringacc->tisci_ring_ops->set_cfg(ringacc->tisci, &ring_cfg); 675 587 if (ret) 676 588 dev_err(ringacc->dev, "TISCI config ring fail (%d) ring_idx %d\n", 677 589 ret, ring->ring_id); 678 590 591 + return ret; 592 + } 593 + 594 + static int k3_dmaring_cfg(struct k3_ring *ring, struct k3_ring_cfg *cfg) 595 + { 596 + struct k3_ringacc *ringacc; 597 + struct k3_ring *reverse_ring; 598 + int ret = 0; 599 + 600 + if (cfg->elm_size != K3_RINGACC_RING_ELSIZE_8 || 601 + cfg->mode != K3_RINGACC_RING_MODE_RING || 602 + cfg->size & ~K3_DMARING_CFG_RING_SIZE_ELCNT_MASK) 603 + return -EINVAL; 604 + 605 + ringacc = ring->parent; 606 + 607 + /* 608 + * DMA rings: rings shared memory and configuration, only forward ring 609 + * is configured and reverse ring considered as slave. 610 + */ 611 + if (ringacc->dma_rings && (ring->flags & K3_RING_FLAG_REVERSE)) 612 + return 0; 613 + 614 + if (!test_bit(ring->ring_id, ringacc->rings_inuse)) 615 + return -EINVAL; 616 + 617 + ring->size = cfg->size; 618 + ring->elm_size = cfg->elm_size; 619 + ring->mode = cfg->mode; 620 + ring->asel = cfg->asel; 621 + ring->dma_dev = cfg->dma_dev; 622 + if (!ring->dma_dev) { 623 + dev_warn(ringacc->dev, "dma_dev is not provided for ring%d\n", 624 + ring->ring_id); 625 + ring->dma_dev = ringacc->dev; 626 + } 627 + 628 + memset(&ring->state, 0, sizeof(ring->state)); 629 + 630 + ring->ops = &k3_dmaring_fwd_ops; 631 + 632 + ring->ring_mem_virt = dma_alloc_coherent(ring->dma_dev, 633 + ring->size * (4 << ring->elm_size), 634 + &ring->ring_mem_dma, GFP_KERNEL); 635 + if (!ring->ring_mem_virt) { 636 + dev_err(ringacc->dev, "Failed to alloc ring mem\n"); 637 + ret = -ENOMEM; 638 + goto err_free_ops; 639 + } 640 + 641 + ret = k3_ringacc_ring_cfg_sci(ring); 642 + if (ret) 643 + goto err_free_mem; 644 + 645 + ring->flags |= K3_RING_FLAG_BUSY; 646 + 647 + k3_ringacc_ring_dump(ring); 648 + 649 + /* DMA rings: configure reverse ring */ 650 + reverse_ring = &ringacc->rings[ring->ring_id + ringacc->num_rings]; 651 + reverse_ring->size = cfg->size; 652 + reverse_ring->elm_size = cfg->elm_size; 653 + reverse_ring->mode = cfg->mode; 654 + reverse_ring->asel = cfg->asel; 655 + memset(&reverse_ring->state, 0, sizeof(reverse_ring->state)); 656 + reverse_ring->ops = &k3_dmaring_reverse_ops; 657 + 658 + reverse_ring->ring_mem_virt = ring->ring_mem_virt; 659 + reverse_ring->ring_mem_dma = ring->ring_mem_dma; 660 + reverse_ring->flags |= K3_RING_FLAG_BUSY; 661 + k3_ringacc_ring_dump(reverse_ring); 662 + 663 + return 0; 664 + 665 + err_free_mem: 666 + dma_free_coherent(ring->dma_dev, 667 + ring->size * (4 << ring->elm_size), 668 + ring->ring_mem_virt, 669 + ring->ring_mem_dma); 670 + err_free_ops: 671 + ring->ops = NULL; 672 + ring->proxy = NULL; 673 + ring->dma_dev = NULL; 674 + ring->asel = 0; 679 675 return ret; 680 676 } 681 677 ··· 771 597 772 598 if (!ring || !cfg) 773 599 return -EINVAL; 600 + 774 601 ringacc = ring->parent; 602 + 603 + if (ringacc->dma_rings) 604 + return k3_dmaring_cfg(ring, cfg); 775 605 776 606 if (cfg->elm_size > K3_RINGACC_RING_ELSIZE_256 || 777 607 cfg->mode >= K3_RINGACC_RING_MODE_INVALID || ··· 883 705 return -EINVAL; 884 706 885 707 if (!ring->state.free) 886 - ring->state.free = ring->size - readl(&ring->rt->occ); 708 + ring->state.free = ring->size - k3_ringacc_ring_read_occ(ring); 887 709 888 710 return ring->state.free; 889 711 } ··· 894 716 if (!ring || !(ring->flags & K3_RING_FLAG_BUSY)) 895 717 return -EINVAL; 896 718 897 - return readl(&ring->rt->occ); 719 + return k3_ringacc_ring_read_occ(ring); 898 720 } 899 721 EXPORT_SYMBOL_GPL(k3_ringacc_ring_get_occ); 900 722 ··· 1070 892 K3_RINGACC_ACCESS_MODE_POP_HEAD); 1071 893 } 1072 894 895 + /* 896 + * The element is 48 bits of address + ASEL bits in the ring. 897 + * ASEL is used by the DMAs and should be removed for the kernel as it is not 898 + * part of the physical memory address. 899 + */ 900 + static void k3_dmaring_remove_asel_from_elem(u64 *elem) 901 + { 902 + *elem &= GENMASK_ULL(K3_ADDRESS_ASEL_SHIFT - 1, 0); 903 + } 904 + 905 + static int k3_dmaring_fwd_pop(struct k3_ring *ring, void *elem) 906 + { 907 + void *elem_ptr; 908 + u32 elem_idx; 909 + 910 + /* 911 + * DMA rings: forward ring is always tied DMA channel and HW does not 912 + * maintain any state data required for POP operation and its unknown 913 + * how much elements were consumed by HW. So, to actually 914 + * do POP, the read pointer has to be recalculated every time. 915 + */ 916 + ring->state.occ = k3_ringacc_ring_read_occ(ring); 917 + if (ring->state.windex >= ring->state.occ) 918 + elem_idx = ring->state.windex - ring->state.occ; 919 + else 920 + elem_idx = ring->size - (ring->state.occ - ring->state.windex); 921 + 922 + elem_ptr = k3_ringacc_get_elm_addr(ring, elem_idx); 923 + memcpy(elem, elem_ptr, (4 << ring->elm_size)); 924 + k3_dmaring_remove_asel_from_elem(elem); 925 + 926 + ring->state.occ--; 927 + writel(-1, &ring->rt->db); 928 + 929 + dev_dbg(ring->parent->dev, "%s: occ%d Windex%d Rindex%d pos_ptr%px\n", 930 + __func__, ring->state.occ, ring->state.windex, elem_idx, 931 + elem_ptr); 932 + return 0; 933 + } 934 + 935 + static int k3_dmaring_reverse_pop(struct k3_ring *ring, void *elem) 936 + { 937 + void *elem_ptr; 938 + 939 + elem_ptr = k3_ringacc_get_elm_addr(ring, ring->state.rindex); 940 + 941 + if (ring->state.occ) { 942 + memcpy(elem, elem_ptr, (4 << ring->elm_size)); 943 + k3_dmaring_remove_asel_from_elem(elem); 944 + 945 + ring->state.rindex = (ring->state.rindex + 1) % ring->size; 946 + ring->state.occ--; 947 + writel(-1 & K3_DMARING_RT_DB_ENTRY_MASK, &ring->rt->db); 948 + } else if (ring->state.tdown_complete) { 949 + dma_addr_t *value = elem; 950 + 951 + *value = CPPI5_TDCM_MARKER; 952 + writel(K3_DMARING_RT_DB_TDOWN_ACK, &ring->rt->db); 953 + ring->state.tdown_complete = false; 954 + } 955 + 956 + dev_dbg(ring->parent->dev, "%s: occ%d index%d pos_ptr%px\n", 957 + __func__, ring->state.occ, ring->state.rindex, elem_ptr); 958 + return 0; 959 + } 960 + 1073 961 static int k3_ringacc_ring_push_mem(struct k3_ring *ring, void *elem) 1074 962 { 1075 963 void *elem_ptr; ··· 1143 899 elem_ptr = k3_ringacc_get_elm_addr(ring, ring->state.windex); 1144 900 1145 901 memcpy(elem_ptr, elem, (4 << ring->elm_size)); 902 + if (ring->parent->dma_rings) { 903 + u64 *addr = elem_ptr; 904 + 905 + *addr |= ((u64)ring->asel << K3_ADDRESS_ASEL_SHIFT); 906 + } 1146 907 1147 908 ring->state.windex = (ring->state.windex + 1) % ring->size; 1148 909 ring->state.free--; ··· 1224 975 return -EINVAL; 1225 976 1226 977 if (!ring->state.occ) 1227 - ring->state.occ = k3_ringacc_ring_get_occ(ring); 978 + k3_ringacc_ring_update_occ(ring); 1228 979 1229 980 dev_dbg(ring->parent->dev, "ring_pop: occ%d index%d\n", ring->state.occ, 1230 981 ring->state.rindex); 1231 982 1232 - if (!ring->state.occ) 983 + if (!ring->state.occ && !ring->state.tdown_complete) 1233 984 return -ENODATA; 1234 985 1235 986 if (ring->ops && ring->ops->pop_head) ··· 1247 998 return -EINVAL; 1248 999 1249 1000 if (!ring->state.occ) 1250 - ring->state.occ = k3_ringacc_ring_get_occ(ring); 1001 + k3_ringacc_ring_update_occ(ring); 1251 1002 1252 1003 dev_dbg(ring->parent->dev, "ring_pop_tail: occ%d index%d\n", 1253 1004 ring->state.occ, ring->state.rindex); ··· 1451 1202 { .compatible = "ti,am654-navss-ringacc", .data = &k3_ringacc_data, }, 1452 1203 {}, 1453 1204 }; 1205 + 1206 + struct k3_ringacc *k3_ringacc_dmarings_init(struct platform_device *pdev, 1207 + struct k3_ringacc_init_data *data) 1208 + { 1209 + struct device *dev = &pdev->dev; 1210 + struct k3_ringacc *ringacc; 1211 + void __iomem *base_rt; 1212 + struct resource *res; 1213 + int i; 1214 + 1215 + ringacc = devm_kzalloc(dev, sizeof(*ringacc), GFP_KERNEL); 1216 + if (!ringacc) 1217 + return ERR_PTR(-ENOMEM); 1218 + 1219 + ringacc->dev = dev; 1220 + ringacc->dma_rings = true; 1221 + ringacc->num_rings = data->num_rings; 1222 + ringacc->tisci = data->tisci; 1223 + ringacc->tisci_dev_id = data->tisci_dev_id; 1224 + 1225 + mutex_init(&ringacc->req_lock); 1226 + 1227 + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ringrt"); 1228 + base_rt = devm_ioremap_resource(dev, res); 1229 + if (IS_ERR(base_rt)) 1230 + return base_rt; 1231 + 1232 + ringacc->rings = devm_kzalloc(dev, 1233 + sizeof(*ringacc->rings) * 1234 + ringacc->num_rings * 2, 1235 + GFP_KERNEL); 1236 + ringacc->rings_inuse = devm_kcalloc(dev, 1237 + BITS_TO_LONGS(ringacc->num_rings), 1238 + sizeof(unsigned long), GFP_KERNEL); 1239 + 1240 + if (!ringacc->rings || !ringacc->rings_inuse) 1241 + return ERR_PTR(-ENOMEM); 1242 + 1243 + for (i = 0; i < ringacc->num_rings; i++) { 1244 + struct k3_ring *ring = &ringacc->rings[i]; 1245 + 1246 + ring->rt = base_rt + K3_DMARING_RT_REGS_STEP * i; 1247 + ring->parent = ringacc; 1248 + ring->ring_id = i; 1249 + ring->proxy_id = K3_RINGACC_PROXY_NOT_USED; 1250 + 1251 + ring = &ringacc->rings[ringacc->num_rings + i]; 1252 + ring->rt = base_rt + K3_DMARING_RT_REGS_STEP * i + 1253 + K3_DMARING_RT_REGS_REVERSE_OFS; 1254 + ring->parent = ringacc; 1255 + ring->ring_id = i; 1256 + ring->proxy_id = K3_RINGACC_PROXY_NOT_USED; 1257 + ring->flags = K3_RING_FLAG_REVERSE; 1258 + } 1259 + 1260 + ringacc->tisci_ring_ops = &ringacc->tisci->ops.rm_ring_ops; 1261 + 1262 + dev_info(dev, "Number of rings: %u\n", ringacc->num_rings); 1263 + 1264 + return ringacc; 1265 + } 1266 + EXPORT_SYMBOL_GPL(k3_ringacc_dmarings_init); 1454 1267 1455 1268 static int k3_ringacc_probe(struct platform_device *pdev) 1456 1269 {
+17
include/linux/soc/ti/k3-ringacc.h
··· 70 70 * @dma_dev: Master device which is using and accessing to the ring 71 71 * memory when the mode is K3_RINGACC_RING_MODE_RING. Memory allocations 72 72 * should be done using this device. 73 + * @asel: Address Space Select value for physical addresses 73 74 */ 74 75 struct k3_ring_cfg { 75 76 u32 size; ··· 80 79 u32 flags; 81 80 82 81 struct device *dma_dev; 82 + u32 asel; 83 83 }; 84 84 85 85 #define K3_RINGACC_RING_ID_ANY (-1) ··· 251 249 int k3_ringacc_ring_pop_tail(struct k3_ring *ring, void *elem); 252 250 253 251 u32 k3_ringacc_get_tisci_dev_id(struct k3_ring *ring); 252 + 253 + /* DMA ring support */ 254 + struct ti_sci_handle; 255 + 256 + /** 257 + * struct struct k3_ringacc_init_data - Initialization data for DMA rings 258 + */ 259 + struct k3_ringacc_init_data { 260 + const struct ti_sci_handle *tisci; 261 + u32 tisci_dev_id; 262 + u32 num_rings; 263 + }; 264 + 265 + struct k3_ringacc *k3_ringacc_dmarings_init(struct platform_device *pdev, 266 + struct k3_ringacc_init_data *data); 254 267 255 268 #endif /* __SOC_TI_K3_RINGACC_API_H_ */