1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2025 Inochi Amaoto <inochiama@gmail.com> 4 */ 5 6 #include <linux/bitops.h> 7 #include <linux/cleanup.h> 8 #include <linux/module.h> 9 #include <linux/of_dma.h> 10 #include <linux/of_address.h> 11 #include <linux/of_platform.h> 12 #include <linux/platform_device.h> 13 #include <linux/llist.h> 14 #include <linux/regmap.h> 15 #include <linux/spinlock.h> 16 #include <linux/mfd/syscon.h> 17 18 #define REG_DMA_CHANNEL_REMAP0 0x154 19 #define REG_DMA_CHANNEL_REMAP1 0x158 20 #define REG_DMA_INT_MUX 0x298 21 22 #define DMAMUX_NCELLS 2 23 #define MAX_DMA_MAPPING_ID 42 24 #define MAX_DMA_CPU_ID 2 25 #define MAX_DMA_CH_ID 7 26 27 #define DMAMUX_INTMUX_REGISTER_LEN 4 28 #define DMAMUX_NR_CH_PER_REGISTER 4 29 #define DMAMUX_BIT_PER_CH 8 30 #define DMAMUX_CH_MASk GENMASK(5, 0) 31 #define DMAMUX_INT_BIT_PER_CPU 10 32 #define DMAMUX_CH_UPDATE_BIT BIT(31) 33 34 #define DMAMUX_CH_REGPOS(chid) \ 35 ((chid) / DMAMUX_NR_CH_PER_REGISTER) 36 #define DMAMUX_CH_REGOFF(chid) \ 37 ((chid) % DMAMUX_NR_CH_PER_REGISTER) 38 #define DMAMUX_CH_REG(chid) \ 39 ((DMAMUX_CH_REGPOS(chid) * sizeof(u32)) + \ 40 REG_DMA_CHANNEL_REMAP0) 41 #define DMAMUX_CH_SET(chid, val) \ 42 (((val) << (DMAMUX_CH_REGOFF(chid) * DMAMUX_BIT_PER_CH)) | \ 43 DMAMUX_CH_UPDATE_BIT) 44 #define DMAMUX_CH_MASK(chid) \ 45 DMAMUX_CH_SET(chid, DMAMUX_CH_MASk) 46 47 #define DMAMUX_INT_BIT(chid, cpuid) \ 48 BIT((cpuid) * DMAMUX_INT_BIT_PER_CPU + (chid)) 49 #define DMAMUX_INTEN_BIT(cpuid) \ 50 DMAMUX_INT_BIT(8, cpuid) 51 #define DMAMUX_INT_CH_BIT(chid, cpuid) \ 52 (DMAMUX_INT_BIT(chid, cpuid) | DMAMUX_INTEN_BIT(cpuid)) 53 #define DMAMUX_INT_MASK(chid) \ 54 (DMAMUX_INT_BIT(chid, 0) | \ 55 DMAMUX_INT_BIT(chid, 1) | \ 56 DMAMUX_INT_BIT(chid, 2)) 57 #define DMAMUX_INT_CH_MASK(chid, cpuid) \ 58 (DMAMUX_INT_MASK(chid) | DMAMUX_INTEN_BIT(cpuid)) 59 60 struct cv1800_dmamux_data { 61 struct dma_router dmarouter; 62 struct regmap *regmap; 63 spinlock_t lock; 64 struct llist_head free_maps; 65 struct llist_head reserve_maps; 66 DECLARE_BITMAP(mapped_peripherals, MAX_DMA_MAPPING_ID); 67 }; 68 69 struct cv1800_dmamux_map { 70 struct llist_node node; 71 unsigned int channel; 72 unsigned int peripheral; 73 unsigned int cpu; 74 }; 75 76 static void cv1800_dmamux_free(struct device *dev, void *route_data) 77 { 78 struct cv1800_dmamux_data *dmamux = dev_get_drvdata(dev); 79 struct cv1800_dmamux_map *map = route_data; 80 81 guard(spinlock_irqsave)(&dmamux->lock); 82 83 regmap_update_bits(dmamux->regmap, 84 DMAMUX_CH_REG(map->channel), 85 DMAMUX_CH_MASK(map->channel), 86 DMAMUX_CH_UPDATE_BIT); 87 88 regmap_update_bits(dmamux->regmap, REG_DMA_INT_MUX, 89 DMAMUX_INT_CH_MASK(map->channel, map->cpu), 90 DMAMUX_INTEN_BIT(map->cpu)); 91 92 dev_dbg(dev, "free channel %u for req %u (cpu %u)\n", 93 map->channel, map->peripheral, map->cpu); 94 } 95 96 static void *cv1800_dmamux_route_allocate(struct of_phandle_args *dma_spec, 97 struct of_dma *ofdma) 98 { 99 struct platform_device *pdev = of_find_device_by_node(ofdma->of_node); 100 struct cv1800_dmamux_data *dmamux = platform_get_drvdata(pdev); 101 struct cv1800_dmamux_map *map; 102 struct llist_node *node; 103 unsigned long flags; 104 unsigned int chid, devid, cpuid; 105 int ret = -EINVAL; 106 107 if (dma_spec->args_count != DMAMUX_NCELLS) { 108 dev_err(&pdev->dev, "invalid number of dma mux args\n"); 109 goto err_put_pdev; 110 } 111 112 devid = dma_spec->args[0]; 113 cpuid = dma_spec->args[1]; 114 dma_spec->args_count = 1; 115 116 if (devid > MAX_DMA_MAPPING_ID) { 117 dev_err(&pdev->dev, "invalid device id: %u\n", devid); 118 goto err_put_pdev; 119 } 120 121 if (cpuid > MAX_DMA_CPU_ID) { 122 dev_err(&pdev->dev, "invalid cpu id: %u\n", cpuid); 123 goto err_put_pdev; 124 } 125 126 dma_spec->np = of_parse_phandle(ofdma->of_node, "dma-masters", 0); 127 if (!dma_spec->np) { 128 dev_err(&pdev->dev, "can't get dma master\n"); 129 goto err_put_pdev; 130 } 131 132 spin_lock_irqsave(&dmamux->lock, flags); 133 134 if (test_bit(devid, dmamux->mapped_peripherals)) { 135 llist_for_each_entry(map, dmamux->reserve_maps.first, node) { 136 if (map->peripheral == devid && map->cpu == cpuid) 137 goto found; 138 } 139 goto failed; 140 } else { 141 node = llist_del_first(&dmamux->free_maps); 142 if (!node) { 143 ret = -ENODEV; 144 goto failed; 145 } 146 147 map = llist_entry(node, struct cv1800_dmamux_map, node); 148 llist_add(&map->node, &dmamux->reserve_maps); 149 set_bit(devid, dmamux->mapped_peripherals); 150 } 151 152 found: 153 chid = map->channel; 154 map->peripheral = devid; 155 map->cpu = cpuid; 156 157 regmap_set_bits(dmamux->regmap, 158 DMAMUX_CH_REG(chid), 159 DMAMUX_CH_SET(chid, devid)); 160 161 regmap_update_bits(dmamux->regmap, REG_DMA_INT_MUX, 162 DMAMUX_INT_CH_MASK(chid, cpuid), 163 DMAMUX_INT_CH_BIT(chid, cpuid)); 164 165 spin_unlock_irqrestore(&dmamux->lock, flags); 166 167 dma_spec->args[0] = chid; 168 169 dev_dbg(&pdev->dev, "register channel %u for req %u (cpu %u)\n", 170 chid, devid, cpuid); 171 172 put_device(&pdev->dev); 173 174 return map; 175 176 failed: 177 spin_unlock_irqrestore(&dmamux->lock, flags); 178 of_node_put(dma_spec->np); 179 dev_err(&pdev->dev, "errno %d\n", ret); 180 err_put_pdev: 181 put_device(&pdev->dev); 182 183 return ERR_PTR(ret); 184 } 185 186 static int cv1800_dmamux_probe(struct platform_device *pdev) 187 { 188 struct device *dev = &pdev->dev; 189 struct device_node *mux_node = dev->of_node; 190 struct cv1800_dmamux_data *data; 191 struct cv1800_dmamux_map *tmp; 192 struct device *parent = dev->parent; 193 struct regmap *regmap = NULL; 194 unsigned int i; 195 196 if (!parent) 197 return -ENODEV; 198 199 regmap = device_node_to_regmap(parent->of_node); 200 if (IS_ERR(regmap)) 201 return PTR_ERR(regmap); 202 203 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 204 if (!data) 205 return -ENOMEM; 206 207 spin_lock_init(&data->lock); 208 init_llist_head(&data->free_maps); 209 init_llist_head(&data->reserve_maps); 210 211 for (i = 0; i <= MAX_DMA_CH_ID; i++) { 212 tmp = devm_kmalloc(dev, sizeof(*tmp), GFP_KERNEL); 213 if (!tmp) { 214 /* It is OK for not allocating all channel */ 215 dev_warn(dev, "can not allocate channel %u\n", i); 216 continue; 217 } 218 219 init_llist_node(&tmp->node); 220 tmp->channel = i; 221 llist_add(&tmp->node, &data->free_maps); 222 } 223 224 /* if no channel is allocated, the probe must fail */ 225 if (llist_empty(&data->free_maps)) 226 return -ENOMEM; 227 228 data->regmap = regmap; 229 data->dmarouter.dev = dev; 230 data->dmarouter.route_free = cv1800_dmamux_free; 231 232 platform_set_drvdata(pdev, data); 233 234 return of_dma_router_register(mux_node, 235 cv1800_dmamux_route_allocate, 236 &data->dmarouter); 237 } 238 239 static void cv1800_dmamux_remove(struct platform_device *pdev) 240 { 241 of_dma_controller_free(pdev->dev.of_node); 242 } 243 244 static const struct of_device_id cv1800_dmamux_ids[] = { 245 { .compatible = "sophgo,cv1800b-dmamux", }, 246 { } 247 }; 248 MODULE_DEVICE_TABLE(of, cv1800_dmamux_ids); 249 250 static struct platform_driver cv1800_dmamux_driver = { 251 .probe = cv1800_dmamux_probe, 252 .remove = cv1800_dmamux_remove, 253 .driver = { 254 .name = "cv1800-dmamux", 255 .of_match_table = cv1800_dmamux_ids, 256 }, 257 }; 258 module_platform_driver(cv1800_dmamux_driver); 259 260 MODULE_AUTHOR("Inochi Amaoto <inochiama@gmail.com>"); 261 MODULE_DESCRIPTION("Sophgo CV1800/SG2000 Series SoC DMAMUX driver"); 262 MODULE_LICENSE("GPL"); 263