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; 106 107 if (dma_spec->args_count != DMAMUX_NCELLS) { 108 dev_err(&pdev->dev, "invalid number of dma mux args\n"); 109 return ERR_PTR(-EINVAL); 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 return ERR_PTR(-EINVAL); 119 } 120 121 if (cpuid > MAX_DMA_CPU_ID) { 122 dev_err(&pdev->dev, "invalid cpu id: %u\n", cpuid); 123 return ERR_PTR(-EINVAL); 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 return ERR_PTR(-EINVAL); 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 140 ret = -EINVAL; 141 goto failed; 142 } else { 143 node = llist_del_first(&dmamux->free_maps); 144 if (!node) { 145 ret = -ENODEV; 146 goto failed; 147 } 148 149 map = llist_entry(node, struct cv1800_dmamux_map, node); 150 llist_add(&map->node, &dmamux->reserve_maps); 151 set_bit(devid, dmamux->mapped_peripherals); 152 } 153 154 found: 155 chid = map->channel; 156 map->peripheral = devid; 157 map->cpu = cpuid; 158 159 regmap_set_bits(dmamux->regmap, 160 DMAMUX_CH_REG(chid), 161 DMAMUX_CH_SET(chid, devid)); 162 163 regmap_update_bits(dmamux->regmap, REG_DMA_INT_MUX, 164 DMAMUX_INT_CH_MASK(chid, cpuid), 165 DMAMUX_INT_CH_BIT(chid, cpuid)); 166 167 spin_unlock_irqrestore(&dmamux->lock, flags); 168 169 dma_spec->args[0] = chid; 170 171 dev_dbg(&pdev->dev, "register channel %u for req %u (cpu %u)\n", 172 chid, devid, cpuid); 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 return ERR_PTR(ret); 181 } 182 183 static int cv1800_dmamux_probe(struct platform_device *pdev) 184 { 185 struct device *dev = &pdev->dev; 186 struct device_node *mux_node = dev->of_node; 187 struct cv1800_dmamux_data *data; 188 struct cv1800_dmamux_map *tmp; 189 struct device *parent = dev->parent; 190 struct regmap *regmap = NULL; 191 unsigned int i; 192 193 if (!parent) 194 return -ENODEV; 195 196 regmap = device_node_to_regmap(parent->of_node); 197 if (IS_ERR(regmap)) 198 return PTR_ERR(regmap); 199 200 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 201 if (!data) 202 return -ENOMEM; 203 204 spin_lock_init(&data->lock); 205 init_llist_head(&data->free_maps); 206 init_llist_head(&data->reserve_maps); 207 208 for (i = 0; i <= MAX_DMA_CH_ID; i++) { 209 tmp = devm_kmalloc(dev, sizeof(*tmp), GFP_KERNEL); 210 if (!tmp) { 211 /* It is OK for not allocating all channel */ 212 dev_warn(dev, "can not allocate channel %u\n", i); 213 continue; 214 } 215 216 init_llist_node(&tmp->node); 217 tmp->channel = i; 218 llist_add(&tmp->node, &data->free_maps); 219 } 220 221 /* if no channel is allocated, the probe must fail */ 222 if (llist_empty(&data->free_maps)) 223 return -ENOMEM; 224 225 data->regmap = regmap; 226 data->dmarouter.dev = dev; 227 data->dmarouter.route_free = cv1800_dmamux_free; 228 229 platform_set_drvdata(pdev, data); 230 231 return of_dma_router_register(mux_node, 232 cv1800_dmamux_route_allocate, 233 &data->dmarouter); 234 } 235 236 static void cv1800_dmamux_remove(struct platform_device *pdev) 237 { 238 of_dma_controller_free(pdev->dev.of_node); 239 } 240 241 static const struct of_device_id cv1800_dmamux_ids[] = { 242 { .compatible = "sophgo,cv1800b-dmamux", }, 243 { } 244 }; 245 MODULE_DEVICE_TABLE(of, cv1800_dmamux_ids); 246 247 static struct platform_driver cv1800_dmamux_driver = { 248 .probe = cv1800_dmamux_probe, 249 .remove = cv1800_dmamux_remove, 250 .driver = { 251 .name = "cv1800-dmamux", 252 .of_match_table = cv1800_dmamux_ids, 253 }, 254 }; 255 module_platform_driver(cv1800_dmamux_driver); 256 257 MODULE_AUTHOR("Inochi Amaoto <inochiama@gmail.com>"); 258 MODULE_DESCRIPTION("Sophgo CV1800/SG2000 Series SoC DMAMUX driver"); 259 MODULE_LICENSE("GPL"); 260